1<?php
2
3/**
4 * Observium
5 *
6 *   This file is part of Observium.
7 *
8 * @package    observium
9 * @subpackage poller
10 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2019 Observium Limited
11 *
12 */
13
14// We should walk, so we can discover here too.
15
16$table_rows = array();
17$c_table_rows = array();
18
19// 'BGP4-MIB', 'CISCO-BGP4-MIB', 'BGP4-V2-MIB-JUNIPER', 'FORCE10-BGP4-V2-MIB', 'ARISTA-BGP4V2-MIB', 'FOUNDRY-BGP4V2-MIB'
20if ($config['enable_bgp'] && is_device_mib($device, 'BGP4-MIB')) // Note, BGP4-MIB is main MIB, without it, the rest will not be checked
21{
22  $p_list          = array(); // Init founded peers list
23  $force_discovery = FALSE;   // Flag for force or not rediscover bgp peers
24  $snmp_incomplete = FALSE;   // Flag for detect if snmpwalk fetch complete data (required for force_discovery)
25
26  // Get Local ASN
27  $bgpLocalAs = snmp_get_oid($device, 'bgpLocalAs.0', 'BGP4-MIB');
28
29  $bgp_oids  = array('bgpPeerState', 'bgpPeerAdminStatus', 'bgpPeerInUpdates', 'bgpPeerOutUpdates',
30                     'bgpPeerInTotalMessages', 'bgpPeerOutTotalMessages', 'bgpPeerFsmEstablishedTime',
31                     'bgpPeerInUpdateElapsedTime'); // , 'bgpPeerLocalAddr', 'bgpPeerIdentifier');
32  $cbgp_oids = array('cbgpPeerAcceptedPrefixes', 'cbgpPeerDeniedPrefixes', 'cbgpPeerPrefixAdminLimit',
33                     'cbgpPeerPrefixThreshold', 'cbgpPeerPrefixClearThreshold', 'cbgpPeerAdvertisedPrefixes',
34                     'cbgpPeerSuppressedPrefixes', 'cbgpPeerWithdrawnPrefixes');
35  $vendor_oids = array(
36    // Juniper BGP4-V2 MIB
37    'BGP4-V2-MIB-JUNIPER' => array('vendor_use_index'         => array('jnxBgpM2PeerRemoteAddr'     => 1,
38                                                                       'jnxBgpM2PeerRemoteAddrType' => 1,
39                                                                       'jnxBgpM2PeerLocalAddr'      => 1),
40                                   'vendor_PeerTable'               => 'jnxBgpM2PeerTable',
41                                   'vendor_PeerState'               => 'jnxBgpM2PeerState',
42                                   'vendor_PeerAdminStatus'         => 'jnxBgpM2PeerStatus',                //'jnxBgpM2CfgPeerAdminStatus' not exist in JunOS
43                                   'vendor_PeerInUpdates'           => 'jnxBgpM2PeerInUpdates',
44                                   'vendor_PeerOutUpdates'          => 'jnxBgpM2PeerOutUpdates',
45                                   'vendor_PeerInTotalMessages'     => 'jnxBgpM2PeerInTotalMessages',
46                                   'vendor_PeerOutTotalMessages'    => 'jnxBgpM2PeerOutTotalMessages',
47                                   'vendor_PeerFsmEstablishedTime'  => 'jnxBgpM2PeerFsmEstablishedTime',
48                                   'vendor_PeerInUpdateElapsedTime' => 'jnxBgpM2PeerInUpdatesElapsedTime',
49                                   'vendor_PeerLocalAs'             => 'jnxBgpM2PeerLocalAs',
50                                   'vendor_PeerLocalAddr'           => 'jnxBgpM2PeerLocalAddr',
51                                   'vendor_PeerIdentifier'          => 'jnxBgpM2PeerIdentifier',
52                                   'vendor_PeerRemoteAs'            => 'jnxBgpM2PeerRemoteAs',
53                                   'vendor_PeerRemoteAddr'          => 'jnxBgpM2PeerRemoteAddr',
54                                   'vendor_PeerRemoteAddrType'      => 'jnxBgpM2PeerRemoteAddrType',
55                                   'vendor_PeerIndex'               => 'jnxBgpM2PeerIndex',
56                                   'vendor_PeerAcceptedPrefixes'    => 'jnxBgpM2PrefixInPrefixesAccepted',
57                                   'vendor_PeerDeniedPrefixes'      => 'jnxBgpM2PrefixInPrefixesRejected',
58                                   'vendor_PeerAdvertisedPrefixes'  => 'jnxBgpM2PrefixOutPrefixes',
59                                   'vendor_PrefixCountersSafi'      => 'jnxBgpM2PrefixCountersSafi'),
60    // Force10 BGP4-V2 MIB
61    'FORCE10-BGP4-V2-MIB' => array('vendor_PeerTable'               => 'f10BgpM2PeerTable',
62                                   'vendor_PeerState'               => 'f10BgpM2PeerState',
63                                   'vendor_PeerAdminStatus'         => 'f10BgpM2PeerStatus',
64                                   'vendor_PeerInUpdates'           => 'f10BgpM2PeerInUpdates',
65                                   'vendor_PeerOutUpdates'          => 'f10BgpM2PeerOutUpdates',
66                                   'vendor_PeerInTotalMessages'     => 'f10BgpM2PeerInTotalMessages',
67                                   'vendor_PeerOutTotalMessages'    => 'f10BgpM2PeerOutTotalMessages',
68                                   'vendor_PeerFsmEstablishedTime'  => 'f10BgpM2PeerFsmEstablishedTime',
69                                   'vendor_PeerInUpdateElapsedTime' => 'f10BgpM2PeerInUpdatesElapsedTime',
70                                   'vendor_PeerLocalAs'             => 'f10BgpM2PeerLocalAs',
71                                   'vendor_PeerLocalAddr'           => 'f10BgpM2PeerLocalAddr',
72                                   'vendor_PeerIdentifier'          => 'f10BgpM2PeerIdentifier',
73                                   'vendor_PeerRemoteAs'            => 'f10BgpM2PeerRemoteAs',
74                                   'vendor_PeerRemoteAddr'          => 'f10BgpM2PeerRemoteAddr',
75                                   'vendor_PeerRemoteAddrType'      => 'f10BgpM2PeerRemoteAddrType',
76                                   'vendor_PeerIndex'               => 'f10BgpM2PeerIndex',
77                                   'vendor_PeerAcceptedPrefixes'    => 'f10BgpM2PrefixInPrefixesAccepted',
78                                   'vendor_PeerDeniedPrefixes'      => 'f10BgpM2PrefixInPrefixesRejected',
79                                   'vendor_PeerAdvertisedPrefixes'  => 'f10BgpM2PrefixOutPrefixes',
80                                   'vendor_PrefixCountersSafi'      => 'f10BgpM2PrefixCountersSafi'),
81    // Arista BGP4-V2 MIB
82    'ARISTA-BGP4V2-MIB'   => array('vendor_use_index'         => array('aristaBgp4V2PeerRemoteAddr'      => 1,
83                                                                       'aristaBgp4V2PeerRemoteAddrType'  => 1),
84                                   'vendor_PeerTable'               => 'aristaBgp4V2PeerTable',
85                                   'vendor_PeerState'               => 'aristaBgp4V2PeerState',
86                                   'vendor_PeerAdminStatus'         => 'aristaBgp4V2PeerAdminStatus',
87                                   'vendor_PeerInUpdates'           => 'aristaBgp4V2PeerInUpdates',
88                                   'vendor_PeerOutUpdates'          => 'aristaBgp4V2PeerOutUpdates',
89                                   'vendor_PeerInTotalMessages'     => 'aristaBgp4V2PeerInTotalMessages',
90                                   'vendor_PeerOutTotalMessages'    => 'aristaBgp4V2PeerOutTotalMessages',
91                                   'vendor_PeerFsmEstablishedTime'  => 'aristaBgp4V2PeerFsmEstablishedTime',
92                                   'vendor_PeerInUpdateElapsedTime' => 'aristaBgp4V2PeerInUpdatesElapsedTime',
93                                   'vendor_PeerLocalAs'             => 'aristaBgp4V2PeerLocalAs',
94                                   'vendor_PeerLocalAddr'           => 'aristaBgp4V2PeerLocalAddr',
95                                   'vendor_PeerIdentifier'          => 'aristaBgp4V2PeerRemoteIdentifier',
96                                   'vendor_PeerRemoteAs'            => 'aristaBgp4V2PeerRemoteAs',
97                                   'vendor_PeerRemoteAddr'          => 'aristaBgp4V2PeerRemoteAddr',
98                                   'vendor_PeerRemoteAddrType'      => 'aristaBgp4V2PeerRemoteAddrType',
99                                   'vendor_PeerIndex'               => '',
100                                   'vendor_PeerAcceptedPrefixes'    => 'aristaBgp4V2PrefixInPrefixesAccepted',
101                                   'vendor_PeerDeniedPrefixes'      => '',
102                                   'vendor_PeerAdvertisedPrefixes'  => 'aristaBgp4V2PrefixOutPrefixes',
103                                   'vendor_PrefixCountersSafi'      => 'aristaBgp4V2PrefixInPrefixes'),
104                                   # PrefixCountersSafi is not-accessible in draft-13, but we
105                                   # only use the INDEX from it, so use aristaBgp4V2PrefixInPrefixes.
106    // Brocade BGP4-V2 MIB
107    // Counters unsupported: http://www.brocade.com/content/html/en/mib-reference-guide/ipmib-feb2016-reference/GUID-C9294495-3C42-4267-A36A-561D7A536B6B.html
108    'FOUNDRY-BGP4V2-MIB'  => array('vendor_use_index'         => array('bgp4V2PeerRemoteAddr'      => 1,
109                                                                       'bgp4V2PeerRemoteAddrType'  => 1,
110                                                                       'bgp4V2PeerLocalAddr'       => 1),
111                                   'vendor_PeerTable'               => 'bgp4V2PeerTable',
112                                   'vendor_PeerState'               => 'bgp4V2PeerState',
113                                   'vendor_PeerAdminStatus'         => 'bgp4V2PeerAdminStatus',
114                                   'vendor_PeerInUpdates'           => '', //'bgp4V2PeerInUpdates',        // not exist
115                                   'vendor_PeerOutUpdates'          => '', //'bgp4V2PeerOutUpdates',       // not exist
116                                   'vendor_PeerInTotalMessages'     => '', //'bgp4V2PeerInTotalMessages',  // not exist
117                                   'vendor_PeerOutTotalMessages'    => '', //'bgp4V2PeerOutTotalMessages', // not exist
118                                   'vendor_PeerFsmEstablishedTime'  => 'bgp4V2PeerFsmEstablishedTime',
119                                   'vendor_PeerInUpdateElapsedTime' => 'bgp4V2PeerInUpdatesElapsedTime',
120                                   'vendor_PeerLocalAs'             => 'bgp4V2PeerLocalAs',
121                                   'vendor_PeerLocalAddr'           => 'bgp4V2PeerLocalAddr',
122                                   'vendor_PeerIdentifier'          => 'bgp4V2PeerRemoteIdentifier',
123                                   'vendor_PeerRemoteAs'            => 'bgp4V2PeerRemoteAs',
124                                   'vendor_PeerRemoteAddr'          => 'bgp4V2PeerRemoteAddr',
125                                   'vendor_PeerRemoteAddrType'      => 'bgp4V2PeerRemoteAddrType',
126                                   'vendor_PeerIndex'               => '',
127                                   'vendor_PeerAcceptedPrefixes'    => '', //'bgp4V2PrefixInPrefixesAccepted', // not exist
128                                   'vendor_PeerDeniedPrefixes'      => '',
129                                   'vendor_PeerAdvertisedPrefixes'  => '', //'bgp4V2PrefixOutPrefixes',        // not exist
130                                   'vendor_PrefixCountersSafi'      => 'bgp4V2PrefixInPrefixes'),
131                                   # PrefixCountersSafi is not-accessible in draft-13, but we
132                                   # only use the INDEX from it, so use bgp4V2PrefixInPrefixes.
133  );
134
135  $vendor_mib = FALSE;
136  foreach ($vendor_oids as $v_mib => $v_array)
137  {
138    if (is_device_mib($device, $v_mib))
139    {
140      $vendor_mib = $v_mib; // Set to current vendor mib
141      foreach ($v_array as $v => $val) { $$v = $val; }
142
143      if ($v_mib === 'BGP4-V2-MIB-JUNIPER' && $bgpLocalAs === '0')
144      {
145        // On JunOS BGP4-MIB::bgpLocalAs.0 is always '0'.
146        $v_bgpLocalAs = snmpwalk_values($device, 'jnxBgpM2PeerLocalAs', array(), 'BGP4-V2-MIB-JUNIPER');
147        $bgpLocalAs   = array_shift($v_bgpLocalAs);
148      }
149      break;
150    }
151  }
152
153  // Some Old IOS-XR (ie 4.3.2) also return BGP4-MIB::bgpLocalAs.0 as '0'.
154  //if ($vendor_mib === FALSE && $bgpLocalAs === '0' && is_device_mib($device, 'CISCO-BGP4-MIB'))
155
156  // Use cbgpLocalAs on Cisco devices since bgpLocalAs doesn't handle 32bit ASNs
157  if (is_device_mib($device, 'CISCO-BGP4-MIB'))
158  {
159    $v_bgpLocalAs = snmp_get_oid($device, 'cbgpLocalAs.0', 'CISCO-BGP4-MIB');
160    if (is_numeric($v_bgpLocalAs) && $v_bgpLocalAs > 0)
161    {
162      $bgpLocalAs = $v_bgpLocalAs;
163    }
164  }
165
166  if (is_numeric($bgpLocalAs) && $bgpLocalAs != '0')
167  {
168    $bgpLocalAs = snmp_dewrap32bit($bgpLocalAs); // Dewrap for 32bit ASN
169    print_cli_data("Local AS", "AS$bgpLocalAs ", 2);
170
171    $cisco_version   = FALSE;
172    if (is_device_mib($device, 'CISCO-BGP4-MIB'))
173    {
174      $cisco_version = 1;
175      // Check Cisco cbgpPeer2Table first
176      $cisco_peers   = snmpwalk_cache_oid($device, 'cbgpPeer2RemoteAs', array(), 'CISCO-BGP4-MIB');
177      if (count($cisco_peers) > 0)
178      {
179        $cisco_version = 2;
180
181        // #2 - Request not completed
182        // #1002 - Request timeout
183        if (snmp_error_code() === 2 || snmp_error_code() === 1002)
184        {
185          $snmp_incomplete = TRUE;
186        }
187      }
188    }
189
190    // Cache data
191    print_cli_data_field("Caching", 2);
192    if ($cisco_version === 2)
193    {
194      echo("CISCO-BGP4-MIB ");
195      foreach ($bgp_oids as $bgp_oid)
196      {
197        $c_oid = str_replace(array('bgpPeer', 'Identifier'), array('cbgpPeer2', 'RemoteIdentifier'), $bgp_oid);
198        $cisco_peers = snmpwalk_cache_oid($device, $c_oid, $cisco_peers, 'CISCO-BGP4-MIB');
199      }
200
201      // Collect founded peers
202      foreach ($cisco_peers as $peer_ip => $entry)
203      {
204        list(,$peer_ip) = explode('.', $peer_ip, 2);
205        $peer_ip  = hex2ip($peer_ip);
206
207        if ($peer_ip  == '0.0.0.0') { $peer_ip  = ''; }
208        $peer_as  = $entry['cbgpPeer2RemoteAs'];
209        $peer = array('ip'            => $peer_ip,
210                      'as'            => $peer_as,
211                      'admin_status'  => $entry['cbgpPeer2AdminStatus']);
212        if (is_bgp_peer_valid($peer, $device))
213        {
214          $p_list[$peer_ip][$peer_as] = 1;
215        } else {
216          unset($cisco_peers[$peer_ip]); // Remove invalid entry for suppress force rediscover
217        }
218      }
219      // And anyway get bgpPeerLocalAddr for fix Cisco issue with incorrect random data in cbgpPeer2LocalAddr
220      //$cisco_fix   = snmpwalk_cache_oid($device, 'bgpPeerLocalAddr', array(), 'BGP4-MIB');
221    } else {
222      echo("BGP4-MIB ");
223      $bgp_peers = snmpwalk_cache_multi_oid($device, 'bgpPeerRemoteAs', array(), 'BGP4-MIB');
224
225      // #2 - Request not completed
226      // #1002 - Request timeout
227      if (snmp_error_code() === 2 || snmp_error_code() === 1002)
228      {
229        $snmp_incomplete = TRUE;
230      }
231
232      foreach ($bgp_oids as $bgp_oid)
233      {
234        $bgp_peers = snmpwalk_cache_multi_oid($device, $bgp_oid, $bgp_peers, 'BGP4-MIB');
235      }
236
237      // Collect founded peers
238      foreach ($bgp_peers as $peer_ip => $entry)
239      {
240        $peer_as  = snmp_dewrap32bit($entry['bgpPeerRemoteAs']); // Dewrap for 32bit ASN
241        if ($peer_as > $entry['bgpPeerRemoteAs'])
242        {
243          $bgp_peers[$peer_ip]['bgpPeerRemoteAs'] = $peer_as;
244        }
245
246        if ($peer_ip  == '0.0.0.0') { $peer_ip  = ''; }
247        $peer = array('ip'            => $peer_ip,
248                      'as'            => $peer_as,
249                      'admin_status'  => $entry['bgpPeerAdminStatus']);
250        if (is_bgp_peer_valid($peer, $device))
251        {
252          $p_list[$peer_ip][$peer_as] = 1;
253        } else {
254          unset($bgp_peers[$peer_ip]); // Remove invalid entry for suppress force rediscover
255        }
256      }
257    }
258
259    if ($vendor_mib)
260    {
261      // Vendor specific IPv4/IPv6 BGP4 MIB
262      echo("$vendor_mib ");
263
264      // Fetch BGP counters for vendor specific MIBs
265      $vendor_bgp = snmpwalk_cache_oid($device, $vendor_PeerRemoteAs,           array(), $vendor_mib, NULL, OBS_SNMP_ALL_NUMERIC_INDEX);
266      if (count($vendor_bgp) > 0)
267      {
268        // #2 - Request not completed
269        // #1002 - Request timeout
270        if (snmp_error_code() === 2 || snmp_error_code() === 1002)
271        {
272          $snmp_incomplete = TRUE;
273        }
274
275        if (!isset($vendor_use_index[$vendor_PeerRemoteAddr]))
276        {
277          $vendor_bgp = snmpwalk_cache_oid($device, $vendor_PeerRemoteAddr, $vendor_bgp, $vendor_mib, NULL, OBS_SNMP_ALL_NUMERIC_INDEX);
278          //$vendor_bgp = snmpwalk_cache_oid($device, $vendor_PeerRemoteAddrType,      $vendor_bgp, $vendor_mib, NULL, OBS_SNMP_ALL_NUMERIC_INDEX);
279        }
280        $v_oids = array('PeerState', 'PeerAdminStatus', 'PeerInUpdates', 'PeerOutUpdates',
281                        'PeerInTotalMessages', 'PeerOutTotalMessages',
282                        'PeerFsmEstablishedTime', 'PeerInUpdateElapsedTime');
283        foreach ($v_oids as $oid)
284        {
285          $oid = 'vendor_'.$oid;
286          $vendor_oid = $$oid;
287          //print_vars($oid);
288          if ($vendor_oid)
289          {
290            //print_vars($vendor_oid);
291            $vendor_bgp = snmpwalk_cache_oid($device, $vendor_oid, $vendor_bgp, $vendor_mib, NULL, OBS_SNMP_ALL_NUMERIC_INDEX);
292          }
293        }
294        unset($vendor_oid);
295
296        // Collect founded peers and rewrite to pretty array.
297        foreach ($vendor_bgp as $idx => $entry)
298        {
299          if (count($vendor_use_index))
300          {
301            parse_bgp_peer_index($entry, $idx, $vendor_mib);
302          }
303          $peer_ip = hex2ip($entry[$vendor_PeerRemoteAddr]);
304
305          //$entry[$vendor_PeerLocalAddr] = hex2ip($entry[$vendor_PeerLocalAddr]);
306          $entry['idx'] = $idx;
307          if ($peer_ip  == '0.0.0.0') { $peer_ip  = ''; }
308          $peer_as = $entry[$vendor_PeerRemoteAs];
309          $peer = array('ip'            => $peer_ip,
310                        'as'            => $peer_as,
311                        'admin_status'  => $entry[$vendor_PeerAdminStatus]);
312          if (is_bgp_peer_valid($peer, $device))
313          {
314            // Fix possible 32bit ASN for peers from BGP4-MIB
315            // Brocade example:
316            //                                     BGP4-MIB::bgpPeerRemoteAs.27.122.122.4 = 23456
317            //  FOUNDRY-BGPV2-MIB::bgp4V2PeerRemoteAs.1.1.4.27.122.122.5.1.4.27.122.122.4 = 133189
318            if (isset($p_list[$peer_ip]) && !isset($p_list[$peer_ip][$peer_as]))
319            {
320              unset($p_list[$peer_ip]); // Clean old peer list
321              $bgp4_peer_as = $bgp_peers[$peer_ip]['bgpPeerRemoteAs'];
322              if ($peer_as > $bgp4_peer_as)
323              {
324                $bgp_peers[$peer_ip]['bgpPeerRemoteAs'] = $peer_as;
325              }
326            }
327
328            $p_list[$peer_ip][$peer_as] = 1;
329            $vendor_peers[$peer_ip][$peer_as] = $entry;
330
331          }
332        }
333
334        // Fetch vendor specific counters
335        $vendor_counters = array();
336        $v_oids = array('PeerAcceptedPrefixes', 'PeerDeniedPrefixes', 'PeerAdvertisedPrefixes');
337        foreach ($v_oids as $oid)
338        {
339          $oid = 'vendor_'.$oid;
340          $vendor_oid = $$oid;
341          //print_vars($oid);
342          if ($vendor_oid)
343          {
344            //print_vars($vendor_oid);
345            $vendor_counters = snmpwalk_cache_oid($device, $vendor_oid, $vendor_counters, $vendor_mib, NULL, OBS_SNMP_ALL_NUMERIC_INDEX);
346          }
347        }
348        unset($vendor_oid);
349        /*
350        $vendor_counters = snmpwalk_cache_oid($device, $vendor_PeerAcceptedPrefixes,            array(), $vendor_mib, NULL, OBS_SNMP_ALL_NUMERIC_INDEX);
351        if ($vendor_PeerDeniedPrefixes != '')
352        {
353          $vendor_counters = snmpwalk_cache_oid($device, $vendor_PeerDeniedPrefixes,   $vendor_counters, $vendor_mib, NULL, OBS_SNMP_ALL_NUMERIC_INDEX);
354        }
355        $vendor_counters = snmpwalk_cache_oid($device, $vendor_PeerAdvertisedPrefixes, $vendor_counters, $vendor_mib, NULL, OBS_SNMP_ALL_NUMERIC_INDEX);
356        */
357      } else {
358        $vendor_mib = FALSE;
359      }
360    }
361    echo(PHP_EOL);
362
363    if ($cisco_version)
364    {
365      $c_prefixes = array();
366      foreach ($cbgp_oids as $cbgp_oid)
367      {
368        $c_oid = ($cisco_version === 2) ? str_replace('cbgpPeer', 'cbgpPeer2', $cbgp_oid) : $cbgp_oid;
369        $c_prefixes = snmpwalk_cache_oid($device, $c_oid, $c_prefixes, 'CISCO-BGP4-MIB');
370      }
371    }
372
373  }
374
375  if (OBS_DEBUG > 1)
376  {
377    print_vars($bgp_peers);
378    print_vars($cisco_peers);
379    print_vars($vendor_peers);
380    print_vars($p_list);
381  }
382
383  $sql  = 'SELECT * FROM `bgpPeers`';
384  //$sql .= ' LEFT JOIN `bgpPeers-state` USING(`bgpPeer_id`)';
385  $sql .= ' WHERE `device_id` = ?';
386
387  foreach (dbFetchRows($sql, array($device['device_id'])) as $peer)
388  {
389    $peer_as = $peer['bgpPeerRemoteAs'];
390    $peer_ip = $peer['bgpPeerRemoteAddr'];
391    $remote_ip = (strstr($peer_ip, ':')) ? Net_IPv6::compress($peer_ip) : $peer_ip; // Compact IPv6. Used only for log.
392
393    // Check if peers exist in SNMP data
394    if (isset($p_list[$peer_ip][$peer_as]))
395    {
396      // OK
397      unset($p_list[$peer_ip][$peer_as]);
398    } else {
399      // This peer removed from table, force rediscover peers
400      $force_discovery = TRUE;
401    }
402
403    if (!strstr($peer_ip, ':') && isset($bgp_peers[$peer_ip]) && $cisco_version !== 2)
404    {
405      // Common IPv4 BGP4 MIB
406      foreach ($bgp_oids as $bgp_oid)
407      {
408        $$bgp_oid = $bgp_peers[$peer_ip][$bgp_oid];
409      }
410    }
411    else if ($cisco_version === 2)
412    {
413      // Cisco BGP4 V2 MIB
414      $c_index = (strstr($peer_ip, ':')) ? 'ipv6.' . ip2hex($peer_ip, ':') : 'ipv4.' . $peer_ip;
415      foreach ($bgp_oids as $bgp_oid)
416      {
417        $c_oid = str_replace(array('bgpPeer', 'Identifier'), array('cbgpPeer2', 'RemoteIdentifier'), $bgp_oid);
418        /*
419        if ($bgp_oid == 'bgpPeerLocalAddr')
420        {
421          if (isset($cisco_fix[$peer_ip]) && strlen($cisco_fix[$peer_ip][$bgp_oid]))
422          {
423            // Fix incorrect IPv4 local IPs
424            $cisco_peers[$c_index][$c_oid] = $cisco_fix[$peer_ip][$bgp_oid];
425          } else {
426            $cisco_peers[$c_index][$c_oid] = hex2ip($cisco_peers[$c_index][$c_oid]);
427          }
428        }
429        */
430        $$bgp_oid = $cisco_peers[$c_index][$c_oid];
431      }
432    }
433    else if ($vendor_mib)
434    {
435      foreach ($bgp_oids as $bgp_oid)
436      {
437        $vendor_oid = $vendor_oids[$vendor_mib][str_replace('bgp', 'vendor_', $bgp_oid)];
438        $$bgp_oid   = $vendor_peers[$peer_ip][$peer_as][$vendor_oid];
439      }
440    }
441    print_debug(PHP_EOL."Peer: $peer_ip (State = $bgpPeerState, AdminStatus = $bgpPeerAdminStatus)");
442
443    // FIXME I left the eventlog code for now, as soon as alerts send an entry to the eventlog this can go.
444    if ($bgpPeerFsmEstablishedTime)
445    {
446      if (!(is_array($config['alerts']['bgp']['whitelist']) && !in_array($peer['bgpPeerRemoteAs'], $config['alerts']['bgp']['whitelist'])) && ($bgpPeerFsmEstablishedTime < $peer['bgpPeerFsmEstablishedTime'] || $bgpPeerState != $peer['bgpPeerState']))
447      {
448        if ($peer['bgpPeerState'] == $bgpPeerState)
449        {
450          log_event('BGP Session flapped: ' . $remote_ip . ' (AS' . $peer['bgpPeerRemoteAs'] . '), time '. format_uptime($bgpPeerFsmEstablishedTime) . ' ago', $device, 'bgp_peer', $peer['bgpPeer_id']);
451        }
452        else if ($bgpPeerState == "established")
453        {
454          log_event('BGP Session Up: ' . $remote_ip . ' (AS' . $peer['bgpPeerRemoteAs'] . '), time '. format_uptime($bgpPeerFsmEstablishedTime) . ' ago', $device, 'bgp_peer', $peer['bgpPeer_id'], 'warning');
455        }
456        else if ($peer['bgpPeerState'] == "established")
457        {
458          log_event('BGP Session Down: ' . $remote_ip . ' (AS' . $peer['bgpPeerRemoteAs'] . '), time '. format_uptime($bgpPeerFsmEstablishedTime) . ' ago.', $device, 'bgp_peer', $peer['bgpPeer_id'], 'warning');
459        }
460      }
461    }
462
463    $polled = time();
464    $polled_period = $polled - $peer['bgpPeer_polled'];
465
466    print_debug("[ polled $polled -> period $polled_period ]");
467
468    rrdtool_update_ng($device, 'bgp', array(
469      'bgpPeerOutUpdates'  => $bgpPeerOutUpdates,
470      'bgpPeerInUpdates'   => $bgpPeerInUpdates,
471      'bgpPeerOutTotal'    => $bgpPeerOutTotalMessages,
472      'bgpPeerInTotal'     => $bgpPeerInTotalMessages,
473      'bgpPeerEstablished' => $bgpPeerFsmEstablishedTime,
474      ), $peer_ip);
475
476    //$graphs['bgp_updates'] = TRUE; // not a device graph
477
478    // Update states
479    $peer['update'] = array();
480    //foreach (array('bgpPeerState', 'bgpPeerAdminStatus', 'bgpPeerLocalAddr', 'bgpPeerIdentifier') as $oid)
481    foreach (array('bgpPeerState', 'bgpPeerAdminStatus') as $oid)
482    {
483      if ($$oid != $peer[$oid]) { $peer['update'][$oid] = $$oid; }
484    }
485
486    //if (count($peer['update']))
487    //{
488    //  dbUpdate($peer['update'], 'bgpPeers', '`bgpPeer_id` = ?', array($peer['bgpPeer_id']));
489    //}
490
491    $check_metrics = array('bgpPeerState'              => $bgpPeerState,
492                           'bgpPeerAdminStatus'        => $bgpPeerAdminStatus,
493                           'bgpPeerFsmEstablishedTime' => $bgpPeerFsmEstablishedTime);
494
495    // Update metrics
496    $metrics = array('bgpPeerInUpdates', 'bgpPeerOutUpdates','bgpPeerInTotalMessages','bgpPeerOutTotalMessages');
497    foreach ($metrics as $oid)
498    {
499      $peer['update'][$oid] = $$oid;
500      if (isset($peer[$oid]) && $peer[$oid] != "0")
501      {
502        $peer['update'][$oid.'_delta'] = $peer['update'][$oid] - $peer[$oid];
503        $peer['update'][$oid.'_rate']  = $peer['update'][$oid.'_delta'] / $polled_period;
504        if ($peer['update'][$oid.'_rate'] < 0)
505        {
506          $peer['update'][$oid.'_rate'] = '0';
507          echo($oid." went backwards.");
508        }
509
510        $check_metrics[$oid.'_delta'] = $peer['update'][$oid.'_delta'];
511        $check_metrics[$oid.'_rate'] = $peer['update'][$oid.'_rate'];
512
513        if ($config['statsd']['enable'] == TRUE)
514        {
515          // Update StatsD/Carbon
516          StatsD::gauge(str_replace(".", "_", $device['hostname']).'.'.'bgp'.'.'.str_replace(".", "_", $peer_ip).'.'.$oid, $$oid);
517        }
518      }
519    }
520
521    check_entity('bgp_peer', $peer, $check_metrics);
522
523    //if (!is_numeric($peer['bgpPeer_polled']))
524    //{
525    //  dbInsert(array('bgpPeer_id' => $peer['bgpPeer_id']), 'bgpPeers-state');
526    //}
527
528    $peer['update']['bgpPeerFsmEstablishedTime'] = $bgpPeerFsmEstablishedTime;
529    $peer['update']['bgpPeerInUpdateElapsedTime'] = $bgpPeerInUpdateElapsedTime;
530    $peer['update']['bgpPeer_polled'] = $polled;
531    dbUpdate($peer['update'], 'bgpPeers', '`bgpPeer_id` = ?', array($peer['bgpPeer_id']));
532
533    $table_row = array();
534    $table_row[] = $peer_ip;
535    $table_row[] = $peer['bgpPeerRemoteAs'];
536    $table_row[] = truncate($peer['astext'], 15);
537    $table_row[] = $bgpPeerAdminStatus;
538    $table_row[] = $bgpPeerState;
539    $table_row[] = $peer['bgpPeerLocalAddr'];
540    $table_row[] = format_uptime($bgpPeerFsmEstablishedTime);
541    $table_row[] = format_uptime($bgpPeerInUpdateElapsedTime);
542    $table_rows[] = $table_row;
543    unset($table_row);
544
545    if ($cisco_version || $vendor_mib)
546    {
547      // Poll each AFI/SAFI for this peer
548      $peer_afis = dbFetchRows('SELECT * FROM `bgpPeers_cbgp` WHERE `device_id` = ? AND `bgpPeer_id` = ?', array($device['device_id'], $peer['bgpPeer_id']));
549      foreach ($peer_afis as $peer_afi)
550      {
551        $afi = $peer_afi['afi'];
552        $safi = $peer_afi['safi'];
553        print_debug("$afi $safi");
554
555        if ($cisco_version)
556        {
557          $c_index = ($cisco_version === 2) ? "$c_index.$afi.$safi" : "$peer_ip.$afi.$safi";
558          foreach ($cbgp_oids as $cbgp_oid)
559          {
560            $c_oid = ($cisco_version === 2) ? str_replace('cbgpPeer', 'cbgpPeer2', $cbgp_oid) : $cbgp_oid;
561            #$c_prefixes = snmpwalk_cache_oid($device, $c_oid, $c_prefixes, 'CISCO-BGP4-MIB');
562            $$cbgp_oid = $c_prefixes[$c_index][$c_oid];
563          }
564        }
565
566        if ($vendor_mib)
567        {
568          // Missing: cbgpPeerAdminLimit cbgpPeerPrefixThreshold cbgpPeerPrefixClearThreshold cbgpPeerSuppressedPrefixes cbgpPeerWithdrawnPrefixes
569
570          // See posible AFI/SAFI here: https://www.juniper.net/techpubs/en_US/junos12.3/topics/topic-map/bgp-multiprotocol.html
571          $afis['1'] = 'ipv4';
572          $afis['2'] = 'ipv6';
573          $afis['ipv4'] = '1';
574          $afis['ipv6'] = '2';
575          $safis = array('unicast'    => 1,
576                         'multicast'  => 2,
577                         'mpls'       => 4,
578                         'mdt'        => 66,
579                         'vpn'        => 128,
580                         'vpn multicast' => 129);
581
582          //$peer_index = $vendor_peers[$peer_ip][$peer_as][$vendor_PeerIndex];
583          $peer_index = $peer_afi['bgpPeerIndex'];
584          if (isset($vendor_counters[$peer_index.'.'.$afi.'.'.$safis[$safi]]))
585          {
586            $index = $peer_index . '.' . $afi        . '.' . $safis[$safi];
587          } else {
588            $index = $peer_index . '.' . $afis[$afi] . '.' . $safis[$safi];
589          }
590
591          $cbgpPeerAcceptedPrefixes   = $vendor_counters[$index][$vendor_PeerAcceptedPrefixes];
592          $cbgpPeerDeniedPrefixes     = $vendor_counters[$index][$vendor_PeerDeniedPrefixes];
593          $cbgpPeerAdvertisedPrefixes = $vendor_counters[$index][$vendor_PeerAdvertisedPrefixes];
594          $cbgpPeerSuppressedPrefixes = "U";
595          $cbgpPeerWithdrawnPrefixes  = "U";
596        }
597
598        // Update cbgp states
599        $peer['c_update']['AcceptedPrefixes']     = $cbgpPeerAcceptedPrefixes;
600        $peer['c_update']['DeniedPrefixes']       = $cbgpPeerDeniedPrefixes;
601        $peer['c_update']['PrefixAdminLimit']     = $cbgpPeerPrefixAdminLimit;
602        $peer['c_update']['PrefixThreshold']      = $cbgpPeerPrefixThreshold;
603        $peer['c_update']['PrefixClearThreshold'] = $cbgpPeerPrefixClearThreshold;
604        $peer['c_update']['AdvertisedPrefixes']   = $cbgpPeerAdvertisedPrefixes;
605        $peer['c_update']['SuppressedPrefixes']   = $cbgpPeerSuppressedPrefixes;
606        $peer['c_update']['WithdrawnPrefixes']    = $cbgpPeerWithdrawnPrefixes;
607
608        //if (dbFetchCell('SELECT COUNT(`cbgp_id`) FROM `bgpPeers_cbgp-state` WHERE `cbgp_id` = ?', array($peer_afi['cbgp_id'])) == 0)
609        //{
610        //  dbInsert(array('cbgp_id' => $peer_afi['cbgp_id']), 'bgpPeers_cbgp-state');
611        //}
612
613        dbUpdate($peer['c_update'], 'bgpPeers_cbgp', '`cbgp_id` = ?', array($peer_afi['cbgp_id']));
614
615        // Update cbgp StatsD
616        if ($config['statsd']['enable'] == TRUE)
617        {
618          foreach (array('AcceptedPrefixes', 'DeniedPrefixes', 'AdvertisedPrefixes', 'SuppressedPrefixes', 'WithdrawnPrefixes') as $oid)
619          {
620            // Update StatsD/Carbon
621            $r_oid = 'cbgpPeer'.$oid;
622            StatsD::gauge(str_replace('.', '_', $device['hostname']).'.'.'bgp' . '.' . str_replace('.', '_', $peer_ip).".$afi.$safi" . '.' . $oid, $$r_oid);
623          }
624        }
625
626        // Update RRD
627        rrdtool_update_ng($device, 'cbgp', array(
628          'AcceptedPrefixes'   => $cbgpPeerAcceptedPrefixes,
629          'DeniedPrefixes'     => $cbgpPeerDeniedPrefixes,
630          'AdvertisedPrefixes' => $cbgpPeerAdvertisedPrefixes,
631          'SuppressedPrefixes' => $cbgpPeerSuppressedPrefixes,
632          'WithdrawnPrefixes'  => $cbgpPeerWithdrawnPrefixes,
633        ), $peer_ip.".$afi.$safi");
634
635        //$graphs['bgp_prefixes_'.$afi.$safi] = TRUE; // Not a device graph
636
637        $check_metrics = array('AcceptedPrefixes'   => $cbgpPeerAcceptedPrefixes,
638                               'DeniedPrefixes'     => $cbgpPeerDeniedPrefixes,
639                               'AdvertisedPrefixes' => $cbgpPeerAdvertisedPrefixes,
640                               'SuppressedPrefixes' => $cbgpPeerSuppressedPrefixes,
641                               'WithdrawnPrefixes'  => $cbgpPeerWithdrawnPrefixes);
642
643        check_entity('bgp_peer_af', $peer_afi, $check_metrics);
644
645        $c_table_row = array();
646        $c_table_row[] = $peer_ip;
647        $c_table_row[] = $peer['bgpPeerRemoteAs'];
648        $c_table_row[] = $afi."-".$safi;
649        $c_table_row[] = $cbgpPeerAcceptedPrefixes;
650        $c_table_row[] = $cbgpPeerDeniedPrefixes;
651        $c_table_row[] = $cbgpPeerAdvertisedPrefixes;
652        $c_table_rows[] = $c_table_row;
653        unset($c_table_row);
654
655      } # while
656    } # os_group=cisco | vendors
657
658  } // End While loop on peers
659
660  if (count($table_rows))
661  {
662    echo(PHP_EOL);
663    $headers = array('%WPeer IP%n', '%WASN%n', '%WAS%n', '%WAdmin%n', '%WState%n', '%WLocal IP%n', '%WEstablished Time%n', '%WLast Update%n');
664    print_cli_table($table_rows, $headers, "Sessions");
665
666    $headers = array('%WPeer IP%n', '%WASN%n', '%WAFI/SAFI%n', '%WAccepted Pfx%n', '%WDenied Pfx%n', '%WAdvertised Pfx%n');
667    print_cli_table($c_table_rows, $headers, "Address Families");
668
669  }
670
671  foreach ($p_list as $peer_ip => $entry)
672  {
673    // Check if new peers found
674    $force_discovery = $force_discovery || !empty($entry);
675  }
676
677  if ($snmp_incomplete)
678  {
679    print_debug("WARNING! BGP snmpwalk did not complete.");
680    log_event("WARNING! BGP snmpwalk did not complete. Try to increase SNMP timeout on the device properties page.", $device, 'device', $device['device_id'], 7);
681  }
682  else if ($force_discovery)
683  {
684      // Force rediscover bgp peers
685      print_debug("BGP peers list for this device changed, force rediscover BGP.");
686      print_debug_vars($p_list, 1);
687      force_discovery($device, 'bgp-peers');
688  }
689
690} // End check for BGP support
691
692// Clean
693unset($bgp_peers, $vendor_peers, $vendor_mib, $cisco_version, $cisco_peers, $c_prefixes);
694
695// EOF
696