~ubuntu-branches/ubuntu/warty/quagga/warty

« back to all changes in this revision

Viewing changes to bgpd/bgp_snmp.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2004-06-29 09:50:59 UTC
  • Revision ID: james.westby@ubuntu.com-20040629095059-px1m2m108z4qw1mr
Tags: upstream-0.96.5
ImportĀ upstreamĀ versionĀ 0.96.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* BGP4 SNMP support
 
2
   Copyright (C) 1999, 2000 Kunihiro Ishiguro
 
3
 
 
4
This file is part of GNU Zebra.
 
5
 
 
6
GNU Zebra is free software; you can redistribute it and/or modify it
 
7
under the terms of the GNU General Public License as published by the
 
8
Free Software Foundation; either version 2, or (at your option) any
 
9
later version.
 
10
 
 
11
GNU Zebra is distributed in the hope that it will be useful, but
 
12
WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU General Public License
 
17
along with GNU Zebra; see the file COPYING.  If not, write to the Free
 
18
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
02111-1307, USA.  */
 
20
 
 
21
#include <zebra.h>
 
22
 
 
23
#ifdef HAVE_SNMP
 
24
#ifdef HAVE_NETSNMP
 
25
#include <net-snmp/net-snmp-config.h>
 
26
#endif
 
27
#include <asn1.h>
 
28
#include <snmp.h>
 
29
#include <snmp_impl.h>
 
30
 
 
31
#include "if.h"
 
32
#include "log.h"
 
33
#include "prefix.h"
 
34
#include "command.h"
 
35
#include "thread.h"
 
36
#include "smux.h"
 
37
 
 
38
#include "bgpd/bgpd.h"
 
39
#include "bgpd/bgp_table.h"
 
40
#include "bgpd/bgp_aspath.h"
 
41
#include "bgpd/bgp_attr.h"
 
42
#include "bgpd/bgp_route.h"
 
43
#include "bgpd/bgp_fsm.h"
 
44
 
 
45
/* BGP4-MIB described in RFC1657. */
 
46
#define BGP4MIB 1,3,6,1,2,1,15
 
47
 
 
48
/* BGP TRAP. */
 
49
#define BGPESTABLISHED                  1
 
50
#define BGPBACKWARDTRANSITION           2       
 
51
 
 
52
/* Zebra enterprise BGP MIB.  This variable is used for register
 
53
   OSPF MIB to SNMP agent under SMUX protocol.  */
 
54
#define BGPDMIB 1,3,6,1,4,1,3317,1,2,2
 
55
 
 
56
/* BGP MIB bgpVersion. */
 
57
#define BGPVERSION                            0
 
58
 
 
59
/* BGP MIB bgpLocalAs. */
 
60
#define BGPLOCALAS                            0
 
61
 
 
62
/* BGP MIB bgpPeerTable. */
 
63
#define BGPPEERIDENTIFIER                     1
 
64
#define BGPPEERSTATE                          2
 
65
#define BGPPEERADMINSTATUS                    3
 
66
#define BGPPEERNEGOTIATEDVERSION              4
 
67
#define BGPPEERLOCALADDR                      5
 
68
#define BGPPEERLOCALPORT                      6
 
69
#define BGPPEERREMOTEADDR                     7
 
70
#define BGPPEERREMOTEPORT                     8
 
71
#define BGPPEERREMOTEAS                       9
 
72
#define BGPPEERINUPDATES                     10
 
73
#define BGPPEEROUTUPDATES                    11
 
74
#define BGPPEERINTOTALMESSAGES               12
 
75
#define BGPPEEROUTTOTALMESSAGES              13
 
76
#define BGPPEERLASTERROR                     14
 
77
#define BGPPEERFSMESTABLISHEDTRANSITIONS     15
 
78
#define BGPPEERFSMESTABLISHEDTIME            16
 
79
#define BGPPEERCONNECTRETRYINTERVAL          17
 
80
#define BGPPEERHOLDTIME                      18
 
81
#define BGPPEERKEEPALIVE                     19
 
82
#define BGPPEERHOLDTIMECONFIGURED            20
 
83
#define BGPPEERKEEPALIVECONFIGURED           21
 
84
#define BGPPEERMINASORIGINATIONINTERVAL      22
 
85
#define BGPPEERMINROUTEADVERTISEMENTINTERVAL 23
 
86
#define BGPPEERINUPDATEELAPSEDTIME           24
 
87
 
 
88
/* BGP MIB bgpIdentifier. */
 
89
#define BGPIDENTIFIER                         0
 
90
 
 
91
/* BGP MIB bgpRcvdPathAttrTable */
 
92
#define BGPPATHATTRPEER                       1
 
93
#define BGPPATHATTRDESTNETWORK                2
 
94
#define BGPPATHATTRORIGIN                     3
 
95
#define BGPPATHATTRASPATH                     4
 
96
#define BGPPATHATTRNEXTHOP                    5
 
97
#define BGPPATHATTRINTERASMETRIC              6
 
98
 
 
99
/* BGP MIB bgp4PathAttrTable. */
 
100
#define BGP4PATHATTRPEER                      1
 
101
#define BGP4PATHATTRIPADDRPREFIXLEN           2
 
102
#define BGP4PATHATTRIPADDRPREFIX              3
 
103
#define BGP4PATHATTRORIGIN                    4
 
104
#define BGP4PATHATTRASPATHSEGMENT             5
 
105
#define BGP4PATHATTRNEXTHOP                   6
 
106
#define BGP4PATHATTRMULTIEXITDISC             7
 
107
#define BGP4PATHATTRLOCALPREF                 8
 
108
#define BGP4PATHATTRATOMICAGGREGATE           9
 
109
#define BGP4PATHATTRAGGREGATORAS             10
 
110
#define BGP4PATHATTRAGGREGATORADDR           11
 
111
#define BGP4PATHATTRCALCLOCALPREF            12
 
112
#define BGP4PATHATTRBEST                     13
 
113
#define BGP4PATHATTRUNKNOWN                  14
 
114
 
 
115
/* SNMP value hack. */
 
116
#define INTEGER ASN_INTEGER
 
117
#define INTEGER32 ASN_INTEGER
 
118
#define COUNTER32 ASN_COUNTER
 
119
#define OCTET_STRING ASN_OCTET_STR
 
120
#define IPADDRESS ASN_IPADDRESS
 
121
#define GAUGE32 ASN_UNSIGNED
 
122
 
 
123
/* Declare static local variables for convenience. */
 
124
SNMP_LOCAL_VARIABLES
 
125
 
 
126
/* BGP-MIB instances. */
 
127
oid bgp_oid [] = { BGP4MIB };
 
128
oid bgpd_oid [] = { BGPDMIB };
 
129
 
 
130
/* IP address 0.0.0.0. */
 
131
static struct in_addr bgp_empty_addr = {0};
 
132
 
 
133
/* Hook functions. */
 
134
static u_char *bgpVersion ();
 
135
static u_char *bgpLocalAs ();
 
136
static u_char *bgpPeerTable ();
 
137
static u_char *bgpRcvdPathAttrTable ();
 
138
static u_char *bgpIdentifier ();
 
139
static u_char *bgp4PathAttrTable ();
 
140
/* static u_char *bgpTraps (); */
 
141
 
 
142
struct variable bgp_variables[] = 
 
143
{
 
144
  /* BGP version. */
 
145
  {BGPVERSION,                OCTET_STRING, RONLY, bgpVersion,
 
146
   1, {1}},
 
147
  /* BGP local AS. */
 
148
  {BGPLOCALAS,                INTEGER, RONLY, bgpLocalAs,
 
149
   1, {2}},
 
150
  /* BGP peer table. */
 
151
  {BGPPEERIDENTIFIER,         IPADDRESS, RONLY, bgpPeerTable,
 
152
   3, {3, 1, 1}},
 
153
  {BGPPEERSTATE,              INTEGER, RONLY, bgpPeerTable,
 
154
   3, {3, 1, 2}},
 
155
  {BGPPEERADMINSTATUS,        INTEGER, RWRITE, bgpPeerTable,
 
156
   3, {3, 1, 3}},
 
157
  {BGPPEERNEGOTIATEDVERSION,  INTEGER32, RONLY, bgpPeerTable,
 
158
   3, {3, 1, 4}},
 
159
  {BGPPEERLOCALADDR,          IPADDRESS, RONLY, bgpPeerTable,
 
160
   3, {3, 1, 5}},
 
161
  {BGPPEERLOCALPORT,          INTEGER, RONLY, bgpPeerTable,
 
162
   3, {3, 1, 6}},
 
163
  {BGPPEERREMOTEADDR,         IPADDRESS, RONLY, bgpPeerTable,
 
164
   3, {3, 1, 7}},
 
165
  {BGPPEERREMOTEPORT,         INTEGER, RONLY, bgpPeerTable,
 
166
   3, {3, 1, 8}},
 
167
  {BGPPEERREMOTEAS,           INTEGER, RONLY, bgpPeerTable,
 
168
   3, {3, 1, 9}},
 
169
  {BGPPEERINUPDATES,          COUNTER32, RONLY, bgpPeerTable,
 
170
   3, {3, 1, 10}},
 
171
  {BGPPEEROUTUPDATES,         COUNTER32, RONLY, bgpPeerTable,
 
172
   3, {3, 1, 11}},
 
173
  {BGPPEERINTOTALMESSAGES,    COUNTER32, RONLY, bgpPeerTable,
 
174
   3, {3, 1, 12}},
 
175
  {BGPPEEROUTTOTALMESSAGES,   COUNTER32, RONLY, bgpPeerTable,
 
176
   3, {3, 1, 13}},
 
177
  {BGPPEERLASTERROR,          OCTET_STRING, RONLY, bgpPeerTable,
 
178
   3, {3, 1, 14}},
 
179
  {BGPPEERFSMESTABLISHEDTRANSITIONS, COUNTER32, RONLY, bgpPeerTable,
 
180
   3, {3, 1, 15}},
 
181
  {BGPPEERFSMESTABLISHEDTIME, GAUGE32, RONLY, bgpPeerTable,
 
182
   3, {3, 1, 16}},
 
183
  {BGPPEERCONNECTRETRYINTERVAL, INTEGER, RWRITE, bgpPeerTable,
 
184
   3, {3, 1, 17}},
 
185
  {BGPPEERHOLDTIME,           INTEGER, RONLY, bgpPeerTable,
 
186
   3, {3, 1, 18}},
 
187
  {BGPPEERKEEPALIVE,          INTEGER, RONLY, bgpPeerTable,
 
188
   3, {3, 1, 19}},
 
189
  {BGPPEERHOLDTIMECONFIGURED, INTEGER, RWRITE, bgpPeerTable,
 
190
   3, {3, 1, 20}},
 
191
  {BGPPEERKEEPALIVECONFIGURED, INTEGER, RWRITE, bgpPeerTable,
 
192
   3, {3, 1, 21}},
 
193
  {BGPPEERMINASORIGINATIONINTERVAL, INTEGER, RWRITE, bgpPeerTable,
 
194
   3, {3, 1, 22}},
 
195
  {BGPPEERMINROUTEADVERTISEMENTINTERVAL, INTEGER, RWRITE, bgpPeerTable,
 
196
   3, {3, 1, 23}},
 
197
  {BGPPEERINUPDATEELAPSEDTIME, GAUGE32, RONLY, bgpPeerTable,
 
198
   3, {3, 1, 24}},
 
199
  /* BGP identifier. */
 
200
  {BGPIDENTIFIER,             IPADDRESS, RONLY, bgpIdentifier,
 
201
   1, {4}},
 
202
  /* BGP received path attribute table. */
 
203
  {BGPPATHATTRPEER,           IPADDRESS, RONLY, bgpRcvdPathAttrTable,
 
204
   3, {5, 1, 1}},
 
205
  {BGPPATHATTRDESTNETWORK,    IPADDRESS, RONLY, bgpRcvdPathAttrTable,
 
206
   3, {5, 1, 2}},
 
207
  {BGPPATHATTRORIGIN,         INTEGER, RONLY, bgpRcvdPathAttrTable,
 
208
   3, {5, 1, 3}},
 
209
  {BGPPATHATTRASPATH,         OCTET_STRING, RONLY, bgpRcvdPathAttrTable,
 
210
   3, {5, 1, 4}},
 
211
  {BGPPATHATTRNEXTHOP,        IPADDRESS, RONLY, bgpRcvdPathAttrTable,
 
212
   3, {5, 1, 5}},
 
213
  {BGPPATHATTRINTERASMETRIC,  INTEGER32, RONLY, bgpRcvdPathAttrTable,
 
214
   3, {5, 1, 6}},
 
215
  /* BGP-4 received path attribute table. */
 
216
  {BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable,
 
217
   3, {6, 1, 1}},
 
218
  {BGP4PATHATTRIPADDRPREFIXLEN, INTEGER, RONLY, bgp4PathAttrTable,
 
219
   3, {6, 1, 2}},
 
220
  {BGP4PATHATTRIPADDRPREFIX,  IPADDRESS, RONLY, bgp4PathAttrTable,
 
221
   3, {6, 1, 3}},
 
222
  {BGP4PATHATTRORIGIN,        INTEGER, RONLY, bgp4PathAttrTable,
 
223
   3, {6, 1, 4}},
 
224
  {BGP4PATHATTRASPATHSEGMENT, OCTET_STRING, RONLY, bgp4PathAttrTable,
 
225
   3, {6, 1, 5}},
 
226
  {BGP4PATHATTRNEXTHOP,       IPADDRESS, RONLY, bgp4PathAttrTable,
 
227
   3, {6, 1, 6}},
 
228
  {BGP4PATHATTRMULTIEXITDISC, INTEGER, RONLY, bgp4PathAttrTable,
 
229
   3, {6, 1, 7}},
 
230
  {BGP4PATHATTRLOCALPREF,     INTEGER, RONLY, bgp4PathAttrTable,
 
231
   3, {6, 1, 8}},
 
232
  {BGP4PATHATTRATOMICAGGREGATE, INTEGER, RONLY, bgp4PathAttrTable,
 
233
   3, {6, 1, 9}},
 
234
  {BGP4PATHATTRAGGREGATORAS,  INTEGER, RONLY, bgp4PathAttrTable,
 
235
   3, {6, 1, 10}},
 
236
  {BGP4PATHATTRAGGREGATORADDR, IPADDRESS, RONLY, bgp4PathAttrTable,
 
237
   3, {6, 1, 11}},
 
238
  {BGP4PATHATTRCALCLOCALPREF, INTEGER, RONLY, bgp4PathAttrTable,
 
239
   3, {6, 1, 12}},
 
240
  {BGP4PATHATTRBEST,          INTEGER, RONLY, bgp4PathAttrTable,
 
241
   3, {6, 1, 13}},
 
242
  {BGP4PATHATTRUNKNOWN,       OCTET_STRING, RONLY, bgp4PathAttrTable,
 
243
   3, {6, 1, 14}},
 
244
};
 
245
 
 
246
 
 
247
static u_char *
 
248
bgpVersion (struct variable *v, oid name[], size_t *length, int exact,
 
249
            size_t *var_len, WriteMethod **write_method)
 
250
{
 
251
  static u_char version;
 
252
 
 
253
  if (smux_header_generic(v, name, length, exact, var_len, write_method)
 
254
      == MATCH_FAILED)
 
255
    return NULL;
 
256
 
 
257
  /* Retrun BGP version.  Zebra bgpd only support version 4. */
 
258
  version = (0x80 >> (BGP_VERSION_4 - 1));
 
259
 
 
260
  /* Return octet string length 1. */
 
261
  *var_len = 1;
 
262
  return (u_char *)&version;
 
263
}
 
264
 
 
265
static u_char *
 
266
bgpLocalAs (struct variable *v, oid name[], size_t *length,
 
267
            int exact, size_t *var_len, WriteMethod **write_method)
 
268
{
 
269
  struct bgp *bgp;
 
270
 
 
271
  if (smux_header_generic(v, name, length, exact, var_len, write_method)
 
272
      == MATCH_FAILED)
 
273
    return NULL;
 
274
 
 
275
  /* Get BGP structure. */
 
276
  bgp = bgp_get_default ();
 
277
  if (! bgp)
 
278
    return NULL;
 
279
 
 
280
  return SNMP_INTEGER (bgp->as);
 
281
}
 
282
 
 
283
struct peer *
 
284
peer_lookup_addr_ipv4 (struct in_addr *src)
 
285
{
 
286
  struct bgp *bgp;
 
287
  struct peer *peer;
 
288
  struct listnode *nn;
 
289
  struct in_addr addr;
 
290
  int ret;
 
291
 
 
292
  bgp = bgp_get_default ();
 
293
  if (! bgp)
 
294
    return NULL;
 
295
 
 
296
  LIST_LOOP (bgp->peer, peer, nn)
 
297
    {
 
298
      ret = inet_pton (AF_INET, peer->host, &addr);
 
299
      if (ret > 0)
 
300
        {
 
301
          if (IPV4_ADDR_SAME (&addr, src))
 
302
            return peer;
 
303
        }
 
304
    }
 
305
  return NULL;
 
306
}
 
307
 
 
308
struct peer *
 
309
bgp_peer_lookup_next (struct in_addr *src)
 
310
{
 
311
  struct bgp *bgp;
 
312
  struct peer *peer;
 
313
  struct listnode *nn;
 
314
  struct in_addr *p;
 
315
  union sockunion su;
 
316
  int ret;
 
317
 
 
318
  memset (&su, 0, sizeof (union sockunion));
 
319
 
 
320
  bgp = bgp_get_default ();
 
321
  if (! bgp)
 
322
    return NULL;
 
323
 
 
324
  LIST_LOOP (bgp->peer, peer, nn)
 
325
    {
 
326
      ret = inet_pton (AF_INET, peer->host, &su.sin.sin_addr);
 
327
      if (ret > 0)
 
328
        {
 
329
          p = &su.sin.sin_addr;
 
330
 
 
331
          if (ntohl (p->s_addr) > ntohl (src->s_addr))
 
332
            {
 
333
              src->s_addr = p->s_addr;
 
334
              return peer;
 
335
            }
 
336
        }
 
337
    }
 
338
  return NULL;
 
339
}
 
340
 
 
341
struct peer *
 
342
bgpPeerTable_lookup (struct variable *v, oid name[], size_t *length, 
 
343
                     struct in_addr *addr, int exact)
 
344
{
 
345
  struct peer *peer = NULL;
 
346
  int len;
 
347
 
 
348
  if (exact)
 
349
    {
 
350
      /* Check the length. */
 
351
      if (*length - v->namelen != sizeof (struct in_addr))
 
352
        return NULL;
 
353
 
 
354
      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, addr);
 
355
 
 
356
      peer = peer_lookup_addr_ipv4 (addr);
 
357
      return peer;
 
358
    }
 
359
  else
 
360
    {
 
361
      len = *length - v->namelen;
 
362
      if (len > 4) len = 4;
 
363
      
 
364
      oid2in_addr (name + v->namelen, len, addr);
 
365
      
 
366
      peer = bgp_peer_lookup_next (addr);
 
367
 
 
368
      if (peer == NULL)
 
369
        return NULL;
 
370
 
 
371
      oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
 
372
      *length = sizeof (struct in_addr) + v->namelen;
 
373
 
 
374
      return peer;
 
375
    }
 
376
  return NULL;
 
377
}
 
378
 
 
379
/* BGP write methods. */
 
380
int
 
381
write_bgpPeerTable (int action, u_char *var_val,
 
382
                    u_char var_val_type, size_t var_val_len,
 
383
                    u_char *statP, oid *name, size_t length,
 
384
                    struct variable *v)
 
385
{
 
386
  struct in_addr addr;
 
387
  struct peer *peer;
 
388
  long intval;
 
389
  int bigsize = SNMP_MAX_LEN;
 
390
  
 
391
  if (var_val_type != ASN_INTEGER) 
 
392
    {
 
393
      return SNMP_ERR_WRONGTYPE;
 
394
    }
 
395
  if (var_val_len != sizeof (long)) 
 
396
    {
 
397
      return SNMP_ERR_WRONGLENGTH;
 
398
    }
 
399
 
 
400
  if (! asn_parse_int(var_val, &bigsize, &var_val_type,
 
401
                      &intval, sizeof(long)))
 
402
    {
 
403
      return SNMP_ERR_WRONGENCODING;
 
404
    }
 
405
 
 
406
  memset (&addr, 0, sizeof (struct in_addr));
 
407
 
 
408
  peer = bgpPeerTable_lookup (v, name, &length, &addr, 1);
 
409
  if (! peer)
 
410
    return SNMP_ERR_NOSUCHNAME;
 
411
 
 
412
  printf ("val: %ld\n", intval);
 
413
 
 
414
  switch (v->magic)
 
415
    {
 
416
    case BGPPEERADMINSTATUS:
 
417
#define BGP_PeerAdmin_stop  1
 
418
#define BGP_PeerAdmin_start 2
 
419
      /* When the peer is established,   */
 
420
      if (intval == BGP_PeerAdmin_stop)
 
421
        BGP_EVENT_ADD (peer, BGP_Stop);
 
422
      else if (intval == BGP_PeerAdmin_start)
 
423
        ;                       /* Do nothing. */
 
424
      else
 
425
        return SNMP_ERR_NOSUCHNAME;
 
426
      break;
 
427
    case BGPPEERCONNECTRETRYINTERVAL:
 
428
      SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
 
429
      peer->connect = intval;
 
430
      peer->v_connect = intval;
 
431
      break;
 
432
    case BGPPEERHOLDTIMECONFIGURED:
 
433
      SET_FLAG (peer->config, PEER_CONFIG_TIMER);
 
434
      peer->holdtime = intval;
 
435
      peer->v_holdtime = intval;
 
436
      break;
 
437
    case BGPPEERKEEPALIVECONFIGURED:
 
438
      SET_FLAG (peer->config, PEER_CONFIG_TIMER);
 
439
      peer->keepalive = intval;
 
440
      peer->v_keepalive = intval;
 
441
      break;
 
442
    case BGPPEERMINASORIGINATIONINTERVAL:
 
443
      peer->v_asorig = intval;
 
444
      break;
 
445
    case BGPPEERMINROUTEADVERTISEMENTINTERVAL:
 
446
      peer->v_routeadv = intval;
 
447
      break;
 
448
    }
 
449
  return SNMP_ERR_NOERROR;
 
450
}
 
451
 
 
452
u_char *
 
453
bgpPeerTable (struct variable *v, oid name[], size_t *length,
 
454
              int exact, size_t *var_len, WriteMethod **write_method)
 
455
{
 
456
  static struct in_addr addr;
 
457
  struct peer *peer;
 
458
 
 
459
  *write_method = NULL;
 
460
  memset (&addr, 0, sizeof (struct in_addr));
 
461
 
 
462
  peer = bgpPeerTable_lookup (v, name, length, &addr, exact);
 
463
  if (! peer)
 
464
    return NULL;
 
465
 
 
466
  switch (v->magic)
 
467
    {
 
468
    case BGPPEERIDENTIFIER:
 
469
      return SNMP_IPADDRESS (peer->remote_id);
 
470
      break;
 
471
    case BGPPEERSTATE:
 
472
      return SNMP_INTEGER (peer->status);
 
473
      break;
 
474
    case BGPPEERADMINSTATUS:
 
475
      *write_method = write_bgpPeerTable;
 
476
#define BGP_PeerAdmin_stop  1
 
477
#define BGP_PeerAdmin_start 2
 
478
      if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
 
479
        return SNMP_INTEGER (BGP_PeerAdmin_stop);
 
480
      else
 
481
        return SNMP_INTEGER (BGP_PeerAdmin_start);
 
482
      break;
 
483
    case BGPPEERNEGOTIATEDVERSION:
 
484
      return SNMP_INTEGER (peer->version);
 
485
      break;
 
486
    case BGPPEERLOCALADDR:
 
487
      if (peer->su_local)
 
488
        return SNMP_IPADDRESS (peer->su_local->sin.sin_addr);
 
489
      else
 
490
        return SNMP_IPADDRESS (bgp_empty_addr);
 
491
      break;
 
492
    case BGPPEERLOCALPORT:
 
493
      if (peer->su_local)
 
494
        return SNMP_INTEGER (ntohs (peer->su_local->sin.sin_port));
 
495
      else
 
496
        return SNMP_INTEGER (0);
 
497
      break;
 
498
    case BGPPEERREMOTEADDR:
 
499
      if (peer->su_remote)
 
500
        return SNMP_IPADDRESS (peer->su_remote->sin.sin_addr);
 
501
      else
 
502
        return SNMP_IPADDRESS (bgp_empty_addr);
 
503
      break;
 
504
    case BGPPEERREMOTEPORT:
 
505
      if (peer->su_remote)
 
506
        return SNMP_INTEGER (ntohs (peer->su_remote->sin.sin_port));
 
507
      else
 
508
        return SNMP_INTEGER (0);
 
509
      break;
 
510
    case BGPPEERREMOTEAS:
 
511
      return SNMP_INTEGER (peer->as);
 
512
      break;
 
513
    case BGPPEERINUPDATES:
 
514
      return SNMP_INTEGER (peer->update_in);
 
515
      break;
 
516
    case BGPPEEROUTUPDATES:
 
517
      return SNMP_INTEGER (peer->update_out);
 
518
      break;
 
519
    case BGPPEERINTOTALMESSAGES:
 
520
      return SNMP_INTEGER (peer->open_in + peer->update_in
 
521
                           + peer->keepalive_in + peer->notify_in
 
522
                           + peer->refresh_in + peer->dynamic_cap_in);
 
523
      break;
 
524
    case BGPPEEROUTTOTALMESSAGES:
 
525
      return SNMP_INTEGER (peer->open_out + peer->update_out
 
526
                           + peer->keepalive_out + peer->notify_out
 
527
                           + peer->refresh_out + peer->dynamic_cap_out);
 
528
      break;
 
529
    case BGPPEERLASTERROR:
 
530
      {
 
531
        static u_char lasterror[2];
 
532
        lasterror[0] = peer->notify.code;
 
533
        lasterror[1] = peer->notify.subcode;
 
534
        *var_len = 2;
 
535
        return (u_char *)&lasterror;
 
536
      }
 
537
      break;
 
538
    case BGPPEERFSMESTABLISHEDTRANSITIONS:
 
539
      return SNMP_INTEGER (peer->established);
 
540
      break;
 
541
    case BGPPEERFSMESTABLISHEDTIME:
 
542
      if (peer->uptime == 0)
 
543
        return SNMP_INTEGER (0);
 
544
      else
 
545
        return SNMP_INTEGER (time (NULL) - peer->uptime);
 
546
      break;
 
547
    case BGPPEERCONNECTRETRYINTERVAL:
 
548
      *write_method = write_bgpPeerTable;
 
549
      return SNMP_INTEGER (peer->v_connect);
 
550
      break;
 
551
    case BGPPEERHOLDTIME:
 
552
      return SNMP_INTEGER (peer->v_holdtime);
 
553
      break;
 
554
    case BGPPEERKEEPALIVE:
 
555
      return SNMP_INTEGER (peer->v_keepalive);
 
556
      break;
 
557
    case BGPPEERHOLDTIMECONFIGURED:
 
558
      *write_method = write_bgpPeerTable;
 
559
      if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
 
560
        return SNMP_INTEGER (peer->holdtime);
 
561
      else
 
562
        return SNMP_INTEGER (peer->v_holdtime);
 
563
      break;
 
564
    case BGPPEERKEEPALIVECONFIGURED:
 
565
      *write_method = write_bgpPeerTable;
 
566
      if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
 
567
        return SNMP_INTEGER (peer->keepalive);
 
568
      else
 
569
        return SNMP_INTEGER (peer->v_keepalive);
 
570
      break;
 
571
    case BGPPEERMINASORIGINATIONINTERVAL:
 
572
      *write_method = write_bgpPeerTable;
 
573
      return SNMP_INTEGER (peer->v_asorig);
 
574
      break;
 
575
    case BGPPEERMINROUTEADVERTISEMENTINTERVAL:
 
576
      *write_method = write_bgpPeerTable;
 
577
      return SNMP_INTEGER (peer->v_routeadv);
 
578
      break;
 
579
    case BGPPEERINUPDATEELAPSEDTIME:
 
580
      if (peer->update_time == 0)
 
581
        return SNMP_INTEGER (0);
 
582
      else
 
583
        return SNMP_INTEGER (time (NULL) - peer->update_time);
 
584
      break;
 
585
    default:
 
586
      return NULL;
 
587
      break;
 
588
    }  
 
589
  return NULL;
 
590
}
 
591
 
 
592
u_char *
 
593
bgpIdentifier (struct variable *v, oid name[], size_t *length,
 
594
               int exact, size_t *var_len, WriteMethod **write_method)
 
595
{
 
596
  struct bgp *bgp;
 
597
 
 
598
  if (smux_header_generic(v, name, length, exact, var_len, write_method)
 
599
      == MATCH_FAILED)
 
600
    return NULL;
 
601
 
 
602
  bgp = bgp_get_default ();
 
603
  if (!bgp)
 
604
    return NULL;
 
605
 
 
606
  return SNMP_IPADDRESS (bgp->router_id);
 
607
}
 
608
 
 
609
u_char *
 
610
bgpRcvdPathAttrTable (struct variable *v, oid name[], size_t *length,
 
611
                      int exact, size_t *var_len, WriteMethod **write_method)
 
612
{
 
613
  /* Received Path Attribute Table.  This table contains, one entry
 
614
     per path to a network, path attributes received from all peers
 
615
     running BGP version 3 or less.  This table is obsolete, having
 
616
     been replaced in functionality with the bgp4PathAttrTable.  */
 
617
  return NULL;
 
618
}
 
619
 
 
620
struct bgp_info *
 
621
bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length,
 
622
                    struct bgp *bgp, struct prefix_ipv4 *addr, int exact)
 
623
{
 
624
  oid *offset;
 
625
  int offsetlen;
 
626
  struct bgp_info *binfo;
 
627
  struct bgp_info *min;
 
628
  struct bgp_node *rn;
 
629
  union sockunion su;
 
630
  int len;
 
631
  struct in_addr paddr;
 
632
 
 
633
#define BGP_PATHATTR_ENTRY_OFFSET \
 
634
          (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE)
 
635
 
 
636
  if (exact)
 
637
    {
 
638
      if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET)
 
639
        return NULL;
 
640
 
 
641
      /* Set OID offset for prefix. */
 
642
      offset = name + v->namelen;
 
643
      oid2in_addr (offset, IN_ADDR_SIZE, &addr->prefix);
 
644
      offset += IN_ADDR_SIZE;
 
645
 
 
646
      /* Prefix length. */
 
647
      addr->prefixlen = *offset;
 
648
      offset++;
 
649
 
 
650
      /* Peer address. */
 
651
      su.sin.sin_family = AF_INET;
 
652
      oid2in_addr (offset, IN_ADDR_SIZE, &su.sin.sin_addr);
 
653
 
 
654
      /* Lookup node. */
 
655
      rn = bgp_node_lookup (bgp->rib[AFI_IP][SAFI_UNICAST], 
 
656
                              (struct prefix *) addr);
 
657
      if (rn)
 
658
        {
 
659
          bgp_unlock_node (rn);
 
660
 
 
661
          for (binfo = rn->info; binfo; binfo = binfo->next)
 
662
            if (sockunion_same (&binfo->peer->su, &su))
 
663
              return binfo;
 
664
        }
 
665
    }
 
666
  else
 
667
    {
 
668
      offset = name + v->namelen;
 
669
      offsetlen = *length - v->namelen;
 
670
      len = offsetlen;
 
671
 
 
672
      if (offsetlen == 0)
 
673
        rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]);
 
674
      else
 
675
        {
 
676
          if (len > IN_ADDR_SIZE)
 
677
            len = IN_ADDR_SIZE;
 
678
      
 
679
          oid2in_addr (offset, len, &addr->prefix);
 
680
 
 
681
          offset += IN_ADDR_SIZE;
 
682
          offsetlen -= IN_ADDR_SIZE;
 
683
 
 
684
          if (offsetlen > 0)
 
685
            addr->prefixlen = *offset;
 
686
          else
 
687
            addr->prefixlen = len * 8;
 
688
 
 
689
          rn = bgp_node_get (bgp->rib[AFI_IP][SAFI_UNICAST],
 
690
                               (struct prefix *) addr);
 
691
 
 
692
          offset++;
 
693
          offsetlen--;
 
694
        }
 
695
 
 
696
      if (offsetlen > 0)
 
697
        {
 
698
          len = offsetlen;
 
699
          if (len > IN_ADDR_SIZE)
 
700
            len = IN_ADDR_SIZE;
 
701
 
 
702
          oid2in_addr (offset, len, &paddr);
 
703
        }
 
704
      else
 
705
        paddr.s_addr = 0;
 
706
 
 
707
      if (! rn)
 
708
        return NULL;
 
709
 
 
710
      do
 
711
        {
 
712
          min = NULL;
 
713
 
 
714
          for (binfo = rn->info; binfo; binfo = binfo->next)
 
715
            {
 
716
              if (binfo->peer->su.sin.sin_family == AF_INET
 
717
                  && ntohl (paddr.s_addr) 
 
718
                  < ntohl (binfo->peer->su.sin.sin_addr.s_addr))
 
719
                {
 
720
                  if (min)
 
721
                    {
 
722
                      if (ntohl (binfo->peer->su.sin.sin_addr.s_addr) 
 
723
                          < ntohl (min->peer->su.sin.sin_addr.s_addr))
 
724
                        min = binfo;
 
725
                    }
 
726
                  else
 
727
                    min = binfo;
 
728
                }
 
729
            }
 
730
 
 
731
          if (min)
 
732
            {
 
733
              *length = v->namelen + BGP_PATHATTR_ENTRY_OFFSET;
 
734
 
 
735
              offset = name + v->namelen;
 
736
              oid_copy_addr (offset, &rn->p.u.prefix4, IN_ADDR_SIZE);
 
737
              offset += IN_ADDR_SIZE;
 
738
              *offset = rn->p.prefixlen;
 
739
              offset++;
 
740
              oid_copy_addr (offset, &min->peer->su.sin.sin_addr, 
 
741
                             IN_ADDR_SIZE);
 
742
              addr->prefix = rn->p.u.prefix4;
 
743
              addr->prefixlen = rn->p.prefixlen;
 
744
 
 
745
              bgp_unlock_node (rn);
 
746
 
 
747
              return min;
 
748
            }
 
749
 
 
750
          paddr.s_addr = 0;
 
751
        }
 
752
      while ((rn = bgp_route_next (rn)) != NULL);
 
753
    }
 
754
  return NULL;
 
755
}
 
756
 
 
757
u_char *
 
758
bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
 
759
                   int exact, size_t *var_len, WriteMethod **write_method)
 
760
{
 
761
  struct bgp *bgp;
 
762
  struct bgp_info *binfo;
 
763
  struct prefix_ipv4 addr;
 
764
  
 
765
  bgp = bgp_get_default ();
 
766
  if (! bgp)
 
767
    return NULL;
 
768
 
 
769
  memset (&addr, 0, sizeof (struct prefix_ipv4));
 
770
 
 
771
  binfo = bgp4PathAttrLookup (v, name, length, bgp, &addr, exact);
 
772
  if (! binfo)
 
773
    return NULL;
 
774
 
 
775
  switch (v->magic)
 
776
    {
 
777
    case BGP4PATHATTRPEER:      /* 1 */
 
778
      return SNMP_IPADDRESS (binfo->peer->su.sin.sin_addr);
 
779
      break;
 
780
    case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */
 
781
      return SNMP_INTEGER (addr.prefixlen);
 
782
      break;
 
783
    case BGP4PATHATTRIPADDRPREFIX: /* 3 */
 
784
      return SNMP_IPADDRESS (addr.prefix);
 
785
      break;
 
786
    case BGP4PATHATTRORIGIN:    /* 4 */
 
787
      return SNMP_INTEGER (binfo->attr->origin);
 
788
      break;
 
789
    case BGP4PATHATTRASPATHSEGMENT: /* 5 */
 
790
      *var_len = binfo->attr->aspath->length;
 
791
      return (u_char *) binfo->attr->aspath->data;
 
792
      break;
 
793
    case BGP4PATHATTRNEXTHOP:   /* 6 */
 
794
      return SNMP_IPADDRESS (binfo->attr->nexthop);
 
795
      break;
 
796
    case BGP4PATHATTRMULTIEXITDISC: /* 7 */
 
797
      return SNMP_INTEGER (binfo->attr->med);
 
798
      break;
 
799
    case BGP4PATHATTRLOCALPREF: /* 8 */
 
800
      return SNMP_INTEGER (binfo->attr->local_pref);
 
801
      break;
 
802
    case BGP4PATHATTRATOMICAGGREGATE: /* 9 */
 
803
      return SNMP_INTEGER (1);
 
804
      break;
 
805
    case BGP4PATHATTRAGGREGATORAS: /* 10 */
 
806
      return SNMP_INTEGER (binfo->attr->aggregator_as);
 
807
      break;
 
808
    case BGP4PATHATTRAGGREGATORADDR: /* 11 */
 
809
      return SNMP_IPADDRESS (binfo->attr->aggregator_addr);
 
810
      break;
 
811
    case BGP4PATHATTRCALCLOCALPREF: /* 12 */
 
812
      return SNMP_INTEGER (-1);
 
813
      break;
 
814
    case BGP4PATHATTRBEST:      /* 13 */
 
815
#define BGP4_PathAttrBest_false 1
 
816
#define BGP4_PathAttrBest_true  2
 
817
      if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
 
818
        return SNMP_INTEGER (BGP4_PathAttrBest_true);
 
819
      else
 
820
        return SNMP_INTEGER (BGP4_PathAttrBest_false);
 
821
      break;
 
822
    case BGP4PATHATTRUNKNOWN:   /* 14 */
 
823
      *var_len = 0;
 
824
      return NULL;
 
825
      break;
 
826
    }
 
827
  return NULL;
 
828
}
 
829
 
 
830
/* BGP Traps. */
 
831
struct trap_object bgpTrapList[] =
 
832
{
 
833
  {bgpPeerTable, 3, {3, 1, BGPPEERLASTERROR}},
 
834
  {bgpPeerTable, 3, {3, 1, BGPPEERSTATE}}
 
835
};
 
836
 
 
837
void
 
838
bgpTrapEstablished (struct peer *peer)
 
839
{
 
840
  int ret;
 
841
  struct in_addr addr;
 
842
  oid index[sizeof (oid) * IN_ADDR_SIZE];
 
843
 
 
844
  ret = inet_aton (peer->host, &addr);
 
845
  if (ret == 0)
 
846
    return;
 
847
 
 
848
  oid_copy_addr (index, &addr, IN_ADDR_SIZE);
 
849
 
 
850
  smux_trap (bgp_oid, sizeof bgp_oid / sizeof (oid),
 
851
             index, IN_ADDR_SIZE,
 
852
             bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
 
853
             bm->start_time - time (NULL), BGPESTABLISHED);
 
854
}
 
855
 
 
856
void
 
857
bgpTrapBackwardTransition (struct peer *peer)
 
858
{
 
859
  int ret;
 
860
  struct in_addr addr;
 
861
  oid index[sizeof (oid) * IN_ADDR_SIZE];
 
862
 
 
863
  ret = inet_aton (peer->host, &addr);
 
864
  if (ret == 0)
 
865
    return;
 
866
 
 
867
  oid_copy_addr (index, &addr, IN_ADDR_SIZE);
 
868
 
 
869
  smux_trap (bgp_oid, sizeof bgp_oid / sizeof (oid),
 
870
             index, IN_ADDR_SIZE,
 
871
             bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
 
872
             bm->start_time - time (NULL), BGPBACKWARDTRANSITION);
 
873
}
 
874
 
 
875
void
 
876
bgp_snmp_init ()
 
877
{
 
878
  struct bgp_master *bm;
 
879
  
 
880
  if ( !(bm = bgp_get_master ()) )
 
881
    return;
 
882
    
 
883
  smux_init (bm->master, bgpd_oid, sizeof bgpd_oid / sizeof (oid));
 
884
  REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
 
885
  smux_start ();
 
886
}
 
887
#endif /* HAVE_SNMP */