Skip to content

Commit ce014a7

Browse files
authored
New class Layer7::Stormshield (#550)
* Initial Stormshield.pm * Stormshield serial() plus tiny Info.pm QoL comments * Stormshield model() * Stormshield os_ver() * add Stormshield tests * skip test for now, mibs not in image yet * fix Stormshield tests
1 parent 4b150c4 commit ce014a7

3 files changed

Lines changed: 477 additions & 2 deletions

File tree

lib/SNMP/Info.pm

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ list any missing functionality (such as neighbor discovery tables).
7575
# AuthPass => 'authp4ss',
7676
# PrivProto => 'DES', # DES|AES
7777
# PrivPass => 'pr1vp4ss',
78+
79+
# Rarer options - see https://metacpan.org/pod/SNMP for full list
80+
# Timeout => 15 * 1000000, # microseconds
81+
# RemotePort => 161,
82+
# NonIncreasing => 1
7883
});
7984
8085
my $err = $info->error();
@@ -1217,6 +1222,12 @@ Subclass for Citrix Netscaler appliances.
12171222
12181223
See documentation in L<SNMP::Info::Layer7::Netscaler> for details.
12191224
1225+
=item SNMP::Info::Layer7::Stormshield
1226+
1227+
Subclass for Stormshield Network Security appliances.
1228+
1229+
See documentation in L<SNMP::Info::Layer7::Stormshield> for details.
1230+
12201231
12211232
=back
12221233
@@ -1487,6 +1498,12 @@ sub new {
14871498

14881499
$new_obj->{nosuch} = $args{RetryNoSuch} || $NOSUCH;
14891500

1501+
# this will have the cleartext community, enable when needed
1502+
#if ($args{Debug}) {
1503+
# use Data::Dumper;
1504+
# print "SNMP::Info::new sess_args for SNMP::Session : ", Dumper(\%sess_args);
1505+
#}
1506+
14901507
# Initialize mibs if not done
14911508
my $init_ref = $new_obj->{init};
14921509
unless ( defined $$init_ref and $$init_ref ) {
@@ -1816,6 +1833,7 @@ sub device_type {
18161833
9303 => 'SNMP::Info::Layer3::PacketFront',
18171834
10002 => 'SNMP::Info::Layer2::Ubiquiti',
18181835
10418 => 'SNMP::Info::Layer1::Cyclades',
1836+
11256 => 'SNMP::Info::Layer7::Stormshield',
18191837
12325 => 'SNMP::Info::Layer3::Pf',
18201838
12356 => 'SNMP::Info::Layer3::Fortinet',
18211839
13191 => 'SNMP::Info::Layer3::OneAccess',
@@ -1895,6 +1913,7 @@ sub device_type {
18951913
476 => 'SNMP::Info::Layer7::Liebert',
18961914
5951 => 'SNMP::Info::Layer7::Netscaler',
18971915
9694 => 'SNMP::Info::Layer7::Arbor',
1916+
11256 => 'SNMP::Info::Layer7::Stormshield',
18981917
12532 => 'SNMP::Info::Layer7::Neoteris',
18991918
14525 => 'SNMP::Info::Layer2::Trapeze',
19001919
21796 => 'SNMP::Info::Layer7::HWGroup',
@@ -2278,14 +2297,14 @@ sub device_type {
22782297
$objtype = 'SNMP::Info::Layer7::CiscoIPS'
22792298
if ( $soid =~ /\.1\.3\.6\.1\.4\.1\.9\.1\.1545/i );
22802299

2281-
# Siemens Simatic Scalance
2300+
# Siemens Simatic Scalance
22822301
# Scalance overwrites layers later,
22832302
# so if we don't add it here (layer3) and at other
22842303
# it would flip/flop between those
22852304
$objtype = 'SNMP::Info::Layer3::Scalance'
22862305
if ( $soid =~ /\.1\.3\.6\.1\.4\.1\.4329\.6\.1\.2/i );
22872306

2288-
# Whiterabbit Timing
2307+
# Whiterabbit Timing
22892308
$objtype = 'SNMP::Info::Layer3::Whiterabbit'
22902309
if ( $soid =~ /\.1\.3\.6\.1\.4\.1\.96\.100\.1000/i );
22912310

Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
# SNMP::Info::Layer7::Stormshield
2+
#
3+
# Copyright (c) 2025 snmp-info Developers
4+
# All rights reserved.
5+
#
6+
# Redistribution and use in source and binary forms, with or without
7+
# modification, are permitted provided that the following conditions are met:
8+
#
9+
# * Redistributions of source code must retain the above copyright notice,
10+
# this list of conditions and the following disclaimer.
11+
# * Redistributions in binary form must reproduce the above copyright
12+
# notice, this list of conditions and the following disclaimer in the
13+
# documentation and/or other materials provided with the distribution.
14+
# * Neither the name of the University of California, Santa Cruz nor the
15+
# names of its contributors may be used to endorse or promote products
16+
# derived from this software without specific prior written permission.
17+
#
18+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22+
# LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
# POSSIBILITY OF SUCH DAMAGE.
29+
30+
package SNMP::Info::Layer7::Stormshield;
31+
32+
use strict;
33+
use warnings;
34+
use Exporter;
35+
use SNMP::Info::Layer7;
36+
use Data::Dumper;
37+
38+
@SNMP::Info::Layer7::Stormshield::ISA = qw/SNMP::Info::Layer7 Exporter/;
39+
@SNMP::Info::Layer7::Stormshield::EXPORT_OK = qw//;
40+
41+
our ($VERSION, %GLOBALS, %MIBS, %FUNCS, %MUNGE);
42+
43+
$VERSION = '3.972002';
44+
45+
%MIBS = (
46+
%SNMP::Info::Layer7::MIBS,
47+
'STORMSHIELD-HA-MIB' => 'snsFwSerial',
48+
'STORMSHIELD-PROPERTY-MIB' => 'snsSerialNumber',
49+
);
50+
51+
52+
# use qualified names to avoid leaf conflicts. There is PROPERTY, HA and some DEPRECATED mibs
53+
# with identical symbols
54+
55+
%GLOBALS = (
56+
%SNMP::Info::Layer7::GLOBALS,
57+
'propmib_serial' => 'STORMSHIELD_PROPERTY_MIB__snsSerialNumber',
58+
'propmib_model' => 'STORMSHIELD_PROPERTY_MIB__snsModel',
59+
'propmib_version' => 'STORMSHIELD_PROPERTY_MIB__snsVersion',
60+
);
61+
62+
%FUNCS = (
63+
%SNMP::Info::Layer7::FUNCS,
64+
# HA MIB
65+
'hamib_serial' => 'STORMSHIELD_HA_MIB__snsFwSerial',
66+
'hamib_model' => 'STORMSHIELD_HA_MIB__snsModel',
67+
'hamib_version' => 'STORMSHIELD_HA_MIB__snsVersion',
68+
);
69+
70+
%MUNGE = (
71+
%SNMP::Info::Layer7::MUNGE,
72+
);
73+
74+
sub vendor {
75+
return 'stormshield';
76+
}
77+
78+
sub os {
79+
return 'SNS';
80+
}
81+
82+
sub serial {
83+
84+
my $Stormshield = shift;
85+
my $hamib_serial = $Stormshield->hamib_serial();
86+
my $propmib_serial = $Stormshield->propmib_serial();
87+
88+
# Collect serials preserving HA MIB order
89+
my %unique_serials;
90+
my @serials;
91+
my %seen;
92+
93+
if (ref($hamib_serial) eq 'HASH') {
94+
foreach my $key (sort keys %$hamib_serial) {
95+
my $value = $hamib_serial->{$key};
96+
push @serials, $value unless $seen{$value}++;
97+
}
98+
} else {
99+
push @serials, $hamib_serial unless $seen{$hamib_serial}++;
100+
}
101+
102+
# Add Property MIB serials (avoiding duplicates)
103+
if (ref($propmib_serial) eq 'HASH') {
104+
foreach my $value (values %$propmib_serial) {
105+
push @serials, $value unless $seen{$value}++;
106+
}
107+
} else {
108+
push @serials, $propmib_serial unless $seen{$propmib_serial}++;
109+
}
110+
111+
my $serial = join(' ', grep { defined && length } @serials);
112+
return $serial;
113+
}
114+
115+
116+
117+
sub model {
118+
119+
my $Stormshield = shift;
120+
my $hamib_model = $Stormshield->hamib_model();
121+
my $propmib_model = $Stormshield->propmib_model();
122+
123+
my @models;
124+
my %seen;
125+
126+
# Collect unique models preserving HA MIB order
127+
if (ref($hamib_model) eq 'HASH') {
128+
foreach my $key (sort keys %$hamib_model) {
129+
my $value = $hamib_model->{$key};
130+
push @models, $value unless $seen{$value}++;
131+
}
132+
} else {
133+
push @models, $hamib_model unless $seen{$hamib_model}++;
134+
}
135+
136+
# Add Property MIB model
137+
if (ref($propmib_model) eq 'HASH') {
138+
foreach my $value (values %$propmib_model) {
139+
push @models, $value unless $seen{$value}++;
140+
}
141+
} else {
142+
push @models, $propmib_model unless $seen{$propmib_model}++;
143+
}
144+
145+
my $model = join(' ', grep { defined && length } @models);
146+
return $model;
147+
}
148+
149+
sub os_ver {
150+
151+
my $Stormshield = shift;
152+
my $hamib_version = $Stormshield->hamib_version();
153+
my $propmib_version = $Stormshield->propmib_version();
154+
155+
my @versions;
156+
my %seen;
157+
158+
# Collect unique versions preserving HA MIB order
159+
if (ref($hamib_version) eq 'HASH') {
160+
foreach my $key (sort keys %$hamib_version) {
161+
my $value = $hamib_version->{$key};
162+
push @versions, $value unless $seen{$value}++;
163+
}
164+
} else {
165+
push @versions, $hamib_version unless $seen{$hamib_version}++;
166+
}
167+
168+
# Add Property MIB version
169+
if (ref($propmib_version) eq 'HASH') {
170+
foreach my $value (values %$propmib_version) {
171+
push @versions, $value unless $seen{$value}++;
172+
}
173+
} else {
174+
push @versions, $propmib_version unless $seen{$propmib_version}++;
175+
}
176+
177+
my $os_ver = join(' ', grep { defined && length } @versions);
178+
return $os_ver;
179+
}
180+
181+
182+
183+
1;
184+
185+
__END__
186+
187+
=head1 NAME
188+
189+
SNMP::Info::Layer7::Stormshield - SNMP Interface to Stormshield Network Security appliances
190+
191+
=head1 AUTHORS
192+
193+
Rob Woodward
194+
195+
=head1 SYNOPSIS
196+
197+
# Let SNMP::Info determine the correct subclass for you.
198+
my $Stormshield = new SNMP::Info(
199+
AutoSpecify => 1,
200+
Debug => 1,
201+
DestHost => 'myfirewall',
202+
Community => 'public',
203+
Version => 2
204+
)
205+
or die "Can't connect to DestHost.\n";
206+
207+
my $class = $Stormshield->class();
208+
print "SNMP::Info determined this device to fall under subclass : $class\n";
209+
210+
=head1 DESCRIPTION
211+
212+
Subclass for Stormshield Network Security (SNS) appliances
213+
214+
The module supports both High Availability (HA) and non-HA Stormshield appliances. The information retrieved can be different based on whether the device is a HA or non-HA device.
215+
216+
=head2 High Availability (HA) Devices
217+
218+
For HA devices, the module uses the STORMSHIELD-HA-MIB:
219+
220+
=over
221+
222+
=item Serial Number: C<snsFwSerial> (.1.3.6.1.4.1.11256.1.11.7.1.2)
223+
224+
=item Model: C<snsModel> (.1.3.6.1.4.1.11256.1.11.7.1.4)
225+
226+
=item Version: C<snsVersion> (.1.3.6.1.4.1.11256.1.11.7.1.5)
227+
228+
=back
229+
230+
Example SNMP walk for model:
231+
snmpwalk -v2c -On .1.3.6.1.4.1.11256.1.11.7.1.4
232+
.1.3.6.1.4.1.11256.1.11.7.1.4.0 = STRING: "SN-S-Series-220"
233+
.1.3.6.1.4.1.11256.1.11.7.1.4.1 = STRING: "SN-S-Series-220"
234+
235+
=head2 Non-HA Devices
236+
237+
For non-HA devices, the module uses the STORMSHIELD-PROPERTY-MIB:
238+
239+
=over
240+
241+
=item Serial Number: C<snsSerialNumber> (.1.3.6.1.4.1.11256.1.18.3)
242+
243+
=item Model: C<snsModel> (.1.3.6.1.4.1.11256.1.18.1)
244+
245+
=item Version: C<snsVersion> (.1.3.6.1.4.1.11256.1.18.2)
246+
247+
=back
248+
249+
Example SNMP walk for model:
250+
snmpwalk -v2c -On .1.3.6.1.4.1.11256.1.18
251+
.1.3.6.1.4.1.11256.1.18.1.0 = STRING: "SN-S-Series-220"
252+
253+
=head2 Inherited Classes
254+
255+
=over
256+
257+
=item SNMP::Info::Layer7
258+
259+
=back
260+
261+
=head2 Required MIBs
262+
263+
=over
264+
265+
=item Inherited Classes' MIBs
266+
267+
See L<SNMP::Info::Layer7> for its own MIB requirements.
268+
269+
=item STORMSHIELD-HA-MIB
270+
271+
Required for High Availability (HA) Stormshield appliances.
272+
273+
=item STORMSHIELD-PROPERTY-MIB
274+
275+
Required for non-HA Stormshield appliances.
276+
277+
=back
278+
279+
=head1 GLOBALS
280+
281+
These are methods that return scalar value from SNMP
282+
283+
=over
284+
285+
=item $Stormshield->vendor()
286+
287+
Returns 'stormshield'.
288+
289+
=item $Stormshield->os()
290+
291+
Returns 'SNS'.
292+
293+
=item $Stormshield->os_ver()
294+
295+
Release extracted from Stormshield MIBs (HA or Property MIB).
296+
297+
=item $Stormshield->model()
298+
299+
Model extracted from Stormshield MIBs (HA or Property MIB).
300+
301+
=item $Stormshield->serial()
302+
303+
Returns serial number extracted from Stormshield MIBs (HA or Property MIB).
304+
305+
=back
306+
307+
=head2 Globals imported from SNMP::Info::Layer7
308+
309+
See documentation in L<SNMP::Info::Layer7> for details.
310+
311+
=head1 TABLE ENTRIES
312+
313+
These are methods that return tables of information in the form of a reference
314+
to a hash.
315+
316+
=head2 Table Methods imported from SNMP::Info::Layer7
317+
318+
See documentation in L<SNMP::Info::Layer7> for details.
319+
320+
=cut

0 commit comments

Comments
 (0)