Issues (2963)

includes/discovery/vrf.inc.php (1 issue)

1
<?php
2
3
use LibreNMS\Config;
4
5
if (Config::get('enable_vrfs')) {
6
    if (in_array($device['os_group'], ['vrp', 'cisco']) ||
7
        in_array($device['os'], ['junos', 'ironware'])) {
8
        unset($vrf_count);
9
10
        /*
11
            There are 2 MIBs for VPNs : MPLS-VPN-MIB (oldest) and MPLS-L3VPN-STD-MIB (newest)
12
            Unfortunately, there is no simple way to find out which one to use, unless we reference
13
            all the possible devices and check what they support.
14
            Therefore we start testing the MPLS-L3VPN-STD-MIB that is prefered if available.
15
         */
16
17
        // Grab all the info first, then use it in the code.
18
        // It removes load on the device and makes things much faster
19
        $rds = snmp_walk($device, 'mplsL3VpnVrfRD', '-Osqn', 'MPLS-L3VPN-STD-MIB', null);
20
21
        if (empty($rds)) {
22
            $rds = snmp_walk($device, 'mplsVpnVrfRouteDistinguisher', '-Osqn', 'MPLS-VPN-MIB', null);
23
24
            if (empty($rds) && $device['os_group'] == 'cisco') {
25
                // Use CISCO-VRF-MIB if others don't work
26
                $rds = snmp_walk($device, 'cvVrfName', '-Osqn', 'CISCO-VRF-MIB', null);
27
                $rds = str_replace('.1.3.6.1.4.1.9.9.711.1.1.1.1.2.', '', $rds);
28
29
                $vpnmib = 'CISCO-VRF-MIB';
30
                // No descr_oid given, does not exist for CISCO-VRF-MIB
31
                $descr_oid = null;
32
                $ports_oid = '.1.3.6.1.4.1.9.9.711.1.2.1.1.2';
33
            } else {
34
                $vpnmib = 'MPLS-VPN-MIB';
35
                $rds = str_replace('.1.3.6.1.3.118.1.2.2.1.3.', '', $rds);
36
37
                $descr_oid = '.1.3.6.1.3.118.1.2.2.1.2';
38
                $ports_oid = '.1.3.6.1.3.118.1.2.1.1.2';
39
            }
40
        } else {
41
            $vpnmib = 'MPLS-L3VPN-STD-MIB';
42
            $rds = str_replace('.1.3.6.1.2.1.10.166.11.1.2.2.1.4.', '', $rds);
43
44
            $descr_oid = '.1.3.6.1.2.1.10.166.11.1.2.2.1.3';
45
            $ports_oid = '.1.3.6.1.2.1.10.166.11.1.2.1.1.2';
46
        }
47
48
        d_echo("\n[DEBUG]\nUsing $vpnmib\n[/DEBUG]\n");
49
        d_echo("\n[DEBUG OIDS]\n$rds\n[/DEBUG]\n");
50
51
        $rds = trim($rds);
52
53
        if ($descr_oid) {
54
            $descrs = snmp_walk($device, $descr_oid, '-Osqn', $vpnmib, null);
55
            $descrs = trim(str_replace("$descr_oid.", '', $descrs));
56
            $descr_table = [];
57
            foreach (explode("\n", $descrs) as $descr) {
58
                $t = explode(' ', $descr, 2);
59
                $descr_table[$t[0]] = $t[1];
60
            }
61
        }
62
63
        $ports = snmp_walk($device, $ports_oid, '-Osqn', $vpnmib, null);
64
        $ports = trim(str_replace("$ports_oid.", '', $ports));
65
        $port_table = [];
66
        foreach (explode("\n", $ports) as $port) {
67
            $t = explode(' ', $port);
68
            $dotpos = strrpos($t[0], '.');
69
            $vrf_oid = substr($t[0], 0, $dotpos);
70
            $port_id = substr($t[0], ($dotpos + 1));
71
72
            if (empty($port_table[$vrf_oid])) {
73
                $port_table[$vrf_oid][0] = $port_id;
74
            } else {
75
                array_push($port_table[$vrf_oid], $port_id);
76
            }
77
        }
78
79
        foreach (explode("\n", $rds) as $oid) {
80
            if (empty($descr_oid) && strpos($oid, 'Platform_iVRF')) {
81
                // Skip since it is an internal service and not a VRF
82
                continue;
83
            }
84
            echo "\n";
85
            if ($oid) {
86
                // 8.49.53.48.56.58.49.48.48 "1508:100"
87
                // First digit gives number of chars in VRF Name, then it's ASCII
88
                [$vrf_oid, $vrf_rd] = explode(' ', $oid);
89
                $oid_values = explode('.', $vrf_oid);
90
                $vrf_name = '';
91
                for ($i = 1; $i <= $oid_values[0]; $i++) {
92
                    $vrf_name .= chr($oid_values[$i]);
0 ignored issues
show
$oid_values[$i] of type string is incompatible with the type integer expected by parameter $codepoint of chr(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

92
                    $vrf_name .= chr(/** @scrutinizer ignore-type */ $oid_values[$i]);
Loading history...
93
                }
94
95
                // Some VRP versions output VRF RD values as Null terminated Hex-STRING rather than string.
96
                // This has to be converted to decimal
97
                if ($device['os'] == 'vrp' && preg_match('/^([^ ]+) +(([^ ]+) +.*) 00/', $oid, $matches)) {
98
                    //.1.3.6.1.2.1.10.166.11.1.2.2.1.4.5.116.101.115.116.49 36 35 33 30 31 3A 31 00
99
                    // regexp result => 5.116.101.115.116.49 -- 36 35 33 30 31 3A 31 -- 00
100
                    d_echo("  [DEBUG] VRP: RD HexString handling: $matches[2]");
101
                    $hex_vrf_rd = str_replace(' ', '', $matches[2]);
102
                    $vrf_rd = hex2str($hex_vrf_rd);
103
                    d_echo("\n  [DEBUG] VRP: RD : $hex_vrf_rd -> $vrf_rd");
104
                }
105
106
                // Brocade Ironware outputs VRF RD values as Hex-STRING rather than string. This has to be converted to decimal
107
                if ($device['os'] == 'ironware') {
108
                    $vrf_rd = substr($oid, -24);  // Grab last 24 characters from $oid, which is the RD hex value
109
                    $vrf_rd = str_replace(' ', '', $vrf_rd); // Remove whitespace
110
                    $vrf_rd = str_split($vrf_rd, 8); // Split it into an array, with an object for each half of the RD
111
                    $vrf_rd[0] = hexdec($vrf_rd[0]); // Convert first object to decimal
112
                    $vrf_rd[1] = hexdec($vrf_rd[1]); // Convert second object to deciamal
113
                    $vrf_rd = implode(':', $vrf_rd); // Combine back into string, delimiter by colon
114
                } elseif (empty($descr_oid)) {
115
                    // Move rd to vrf_name and remove rd (no way to grab these values with CISCO-VRF-MIB)
116
                    $vrf_name = $vrf_rd;
117
                    unset($vrf_rd);
118
                }
119
120
                echo "\n  [VRF $vrf_name] OID   - $vrf_oid";
121
                echo "\n  [VRF $vrf_name] RD    - $vrf_rd";
122
                echo "\n  [VRF $vrf_name] DESC  - " . $descr_table[$vrf_oid];
123
124
                if (dbFetchCell('SELECT COUNT(*) FROM vrfs WHERE device_id = ? AND `vrf_oid`=?', [$device['device_id'], $vrf_oid])) {
125
                    dbUpdate(['vrf_name' => $vrf_name, 'mplsVpnVrfDescription' => $descr_table[$vrf_oid], 'mplsVpnVrfRouteDistinguisher' => $vrf_rd], 'vrfs', 'device_id=? AND vrf_oid=?', [$device['device_id'], $vrf_oid]);
126
                } else {
127
                    dbInsert(['vrf_oid' => $vrf_oid, 'vrf_name' => $vrf_name, 'mplsVpnVrfRouteDistinguisher' => $vrf_rd, 'mplsVpnVrfDescription' => $descr_table[$vrf_oid], 'device_id' => $device['device_id']], 'vrfs');
128
                }
129
130
                $vrf_id = dbFetchCell('SELECT vrf_id FROM vrfs WHERE device_id = ? AND `vrf_oid`=?', [$device['device_id'], $vrf_oid]);
131
                $valid_vrf[$vrf_id] = 1;
132
133
                echo "\n  [VRF $vrf_name] PORTS - ";
134
                foreach ($port_table[$vrf_oid] as $if_id) {
135
                    $interface = dbFetchRow('SELECT * FROM `ports` WHERE `device_id` = ? AND `ifIndex` = ?', [$device['device_id'], $if_id]);
136
                    echo makeshortif($interface['ifDescr']) . ' ';
137
                    dbUpdate(['ifVrf' => $vrf_id], 'ports', 'port_id=?', [$interface['port_id']]);
138
                    $if = $interface['port_id'];
139
                    $valid_vrf_if[$vrf_id][$if] = 1;
140
                }
141
            }//end if
142
        }//end foreach
143
    } elseif ($device['os_group'] == 'nokia') {
144
        unset($vrf_count);
145
146
        $vrtr = snmpwalk_cache_oid($device, 'vRtrConfTable', [], 'TIMETRA-VRTR-MIB');
147
        $port_table = snmpwalk_cache_twopart_oid($device, 'vRtrIfName', [], 'TIMETRA-VRTR-MIB');
148
149
        foreach ($vrtr as $vrf_oid => $vr) {
150
            $vrf_name = $vr['vRtrName'];
151
            $vrf_desc = $vr['vRtrName'];
152
            $vrf_as = $vr['vRtrAS4Byte'];
153
            $vrf_rd = $vr['vRtrRouteDistinguisher'];
154
            // Nokia, The VPRN route distinguisher is a 8-octet object.
155
            // It contains a 2-octet type field followed by a 6-octet value field. The type field specify how to interpret the value field.
156
            // Type 0 specifies two subfields as a 2-octet administrative field and a 4-octet assigned number subfield.
157
            // Type 1 specifies two subfields as a 4-octet administrative field which must contain an IP address and a 2-octet assigned number subfield.
158
            // Type 2 specifies two subfields as a 4-octet administrative field which contains a 4-octet AS number and a 2-octet assigned number subfield.
159
            // FIXME Hardcoded to Type 0
160
            $vrf_rd = str_replace(' ', '', $vrf_rd);
161
            if ($vrf_rd != '000000000000') {
162
                $vrf_rd_1 = substr($vrf_rd, 4, 4);
163
                $vrf_rd_2 = substr($vrf_rd, 8);
164
                $vrf_rd = hexdec($vrf_rd_1) . ':' . hexdec($vrf_rd_2);
165
            } else {
166
                $vrf_rd = null;
167
            }
168
169
            echo "\n  [VRF $vrf_name] OID   - $vrf_oid";
170
            echo "\n  [VRF $vrf_name] RD    - $vrf_rd";
171
            echo "\n  [VRF $vrf_name] DESC  - $vrf_desc";
172
173
            $vrfs = [
174
                'vrf_oid' => $vrf_oid,
175
                'vrf_name' => $vrf_name,
176
                'bgpLocalAs' => $vrf_as,
177
                'mplsVpnVrfRouteDistinguisher' => $vrf_rd,
178
                'mplsVpnVrfDescription' => $$vrf_desc,
179
                'device_id' => $device['device_id'],
180
            ];
181
182
            if (dbFetchCell('SELECT COUNT(*) FROM vrfs WHERE device_id = ? AND `vrf_oid`=?', [$device['device_id'], $vrf_oid])) {
183
                dbUpdate(['vrf_name' => $vrf_name, 'bgpLocalAs' => $vrf_as, 'mplsVpnVrfRouteDistinguisher' => $vrf_rd, 'mplsVpnVrfDescription' => $vrf_desc], 'vrfs', 'device_id=? AND vrf_oid=?', [$device['device_id'], $vrf_oid]);
184
            } else {
185
                dbInsert($vrfs, 'vrfs');
186
            }
187
188
            $vrf_id = dbFetchCell('SELECT vrf_id FROM vrfs WHERE device_id = ? AND `vrf_oid`=?', [$device['device_id'], $vrf_oid]);
189
            $valid_vrf[$vrf_id] = 1;
190
            echo "\n  [VRF $vrf_name] PORTS - ";
191
            foreach ($port_table[$vrf_oid] as $if_index => $if_name) {
192
                $interface = dbFetchRow('SELECT * FROM `ports` WHERE `device_id` = ? AND `ifIndex` = ?', [$device['device_id'], $if_index]);
193
                echo makeshortif($interface['ifDescr']) . ' ';
194
                dbUpdate(['ifVrf' => $vrf_id], 'ports', 'port_id=?', [$interface['port_id']]);
195
                $if = $interface['port_id'];
196
                $valid_vrf_if[$vrf_id][$if] = 1;
197
            }
198
        } //end foreach
199
    } elseif ($device['os_group'] == 'arista') {
200
        echo "Arista\n";
201
        unset($vrf_count);
202
203
        $aristaVrfTable = snmpwalk_cache_oid($device, 'aristaVrfTable', [], 'ARISTA-VRF-MIB');
204
        $aristaVrfIfTable = snmpwalk_cache_oid($device, 'aristaVrfIfTable', [], 'ARISTA-VRF-MIB');
205
        d_echo($aristaVrfTable);
206
        d_echo($aristaVrfIfTable);
207
208
        foreach ($aristaVrfTable as $vrf_name => $vrf_data) {
209
            //$vrf_desc = $vr['vRtrName'];
210
            //$vrf_as = $vr['vRtrAS4Byte'];
211
            $vrf_oid = $vrf_name;
212
            $vrf_rd = $vrf_data['aristaVrfRouteDistinguisher'];
213
214
            echo "\n  [VRF $vrf_name] OID   - $vrf_oid";
215
            echo "\n  [VRF $vrf_name] RD    - $vrf_rd";
216
            echo "\n  [VRF $vrf_name] DESC  - $vrf_desc";
217
218
            $vrfs = [
219
                'vrf_oid' => $vrf_oid,
220
                'vrf_name' => $vrf_name,
221
                //'bgpLocalAs' => $vrf_as,
222
                'mplsVpnVrfRouteDistinguisher' => $vrf_rd,
223
                //'mplsVpnVrfDescription' => $$vrf_desc,
224
                'device_id' => $device['device_id'],
225
            ];
226
227
            if (dbFetchCell('SELECT COUNT(*) FROM vrfs WHERE device_id = ? AND `vrf_oid`=?', [$device['device_id'], $vrf_oid])) {
228
                dbUpdate(['vrf_name' => $vrf_name, 'bgpLocalAs' => $vrf_as, 'mplsVpnVrfRouteDistinguisher' => $vrf_rd, 'mplsVpnVrfDescription' => $vrf_desc], 'vrfs', 'device_id=? AND vrf_oid=?', [$device['device_id'], $vrf_oid]);
229
            } else {
230
                dbInsert($vrfs, 'vrfs');
231
            }
232
        } //end foreach
233
234
        echo "\n  [VRF $vrf_name] PORTS - ";
235
        foreach ($aristaVrfIfTable as $if_index => $if_data) {
236
            try {
237
                $ifVrfName = $if_data['aristaVrfIfMembership'];
238
                $vrf_id = dbFetchCell('SELECT vrf_id FROM vrfs WHERE device_id = ? AND `vrf_oid`=?', [$device['device_id'], $ifVrfName]);
239
                $valid_vrf[$vrf_id] = 1;
240
                $interface = dbFetchRow('SELECT * FROM `ports` WHERE `device_id` = ? AND `ifIndex` = ?', [$device['device_id'], $if_index]);
241
                echo makeshortif($interface['ifDescr']) . ' ';
242
                dbUpdate(['ifVrf' => $vrf_id], 'ports', 'port_id=?', [$interface['port_id']]);
243
                $if = $interface['port_id'];
244
                $valid_vrf_if[$vrf_id][$if] = 1;
245
            } catch (Exception $e) {
246
                continue;
247
            }
248
        }
249
    } //end if
250
251
    unset(
252
        $descr_table,
253
        $port_table
254
    );
255
    echo "\n";
256
257
    $sql = "SELECT * FROM ports WHERE device_id = '" . $device['device_id'] . "'";
258
    foreach (dbFetchRows($sql) as $row) {
259
        $if = $row['port_id'];
260
        $vrf_id = $row['ifVrf'];
261
        if ($row['ifVrf']) {
262
            if (! $valid_vrf_if[$vrf_id][$if]) {
263
                echo '-';
264
                dbUpdate(['ifVrf' => 'NULL'], 'ports', 'port_id=?', [$if]);
265
            } else {
266
                echo '.';
267
            }
268
        }
269
    }
270
271
    $sql = "SELECT * FROM vrfs WHERE device_id = '" . $device['device_id'] . "'";
272
    foreach (dbFetchRows($sql) as $row) {
273
        $vrf_id = $row['vrf_id'];
274
        if (! $valid_vrf[$vrf_id]) {
275
            echo '-';
276
            dbDelete('vrfs', '`vrf_id` = ?', [$vrf_id]);
277
        } else {
278
            echo '.';
279
        }
280
    }
281
282
    unset(
283
        $valid_vrf_if,
284
        $valid_vrf,
285
        $row,
286
        $sql
287
    );
288
289
    echo "\n";
290
} //end if
291