2 * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
4 * This file is part of GNU Zebra.
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
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.
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
26 #include <net-snmp/net-snmp-config.h>
30 #include <snmp_impl.h>
39 #include "ripd/ripd.h"
42 #define RIPV2MIB 1,3,6,1,2,1,23
44 /* RIPv2-MIB rip2Globals values. */
45 #define RIP2GLOBALROUTECHANGES 1
46 #define RIP2GLOBALQUERIES 2
48 /* RIPv2-MIB rip2IfStatEntry. */
49 #define RIP2IFSTATENTRY 1
51 /* RIPv2-MIB rip2IfStatTable. */
52 #define RIP2IFSTATADDRESS 1
53 #define RIP2IFSTATRCVBADPACKETS 2
54 #define RIP2IFSTATRCVBADROUTES 3
55 #define RIP2IFSTATSENTUPDATES 4
56 #define RIP2IFSTATSTATUS 5
58 /* RIPv2-MIB rip2IfConfTable. */
59 #define RIP2IFCONFADDRESS 1
60 #define RIP2IFCONFDOMAIN 2
61 #define RIP2IFCONFAUTHTYPE 3
62 #define RIP2IFCONFAUTHKEY 4
63 #define RIP2IFCONFSEND 5
64 #define RIP2IFCONFRECEIVE 6
65 #define RIP2IFCONFDEFAULTMETRIC 7
66 #define RIP2IFCONFSTATUS 8
67 #define RIP2IFCONFSRCADDRESS 9
69 /* RIPv2-MIB rip2PeerTable. */
70 #define RIP2PEERADDRESS 1
71 #define RIP2PEERDOMAIN 2
72 #define RIP2PEERLASTUPDATE 3
73 #define RIP2PEERVERSION 4
74 #define RIP2PEERRCVBADPACKETS 5
75 #define RIP2PEERRCVBADROUTES 6
77 /* SNMP value hack. */
78 #define COUNTER ASN_COUNTER
79 #define INTEGER ASN_INTEGER
80 #define TIMETICKS ASN_TIMETICKS
81 #define IPADDRESS ASN_IPADDRESS
82 #define STRING ASN_OCTET_STR
84 /* Define SNMP local variables. */
87 /* RIP-MIB instances. */
88 oid rip_oid
[] = { RIPV2MIB
};
90 /* Interface cache table sorted by interface's address. */
91 struct route_table
*rip_ifaddr_table
;
94 static u_char
*rip2Globals ();
95 static u_char
*rip2IfStatEntry ();
96 static u_char
*rip2IfConfAddress ();
97 static u_char
*rip2PeerTable ();
99 struct variable rip_variables
[] =
101 /* RIP Global Counters. */
102 {RIP2GLOBALROUTECHANGES
, COUNTER
, RONLY
, rip2Globals
,
104 {RIP2GLOBALQUERIES
, COUNTER
, RONLY
, rip2Globals
,
106 /* RIP Interface Tables. */
107 {RIP2IFSTATADDRESS
, IPADDRESS
, RONLY
, rip2IfStatEntry
,
109 {RIP2IFSTATRCVBADPACKETS
, COUNTER
, RONLY
, rip2IfStatEntry
,
111 {RIP2IFSTATRCVBADROUTES
, COUNTER
, RONLY
, rip2IfStatEntry
,
113 {RIP2IFSTATSENTUPDATES
, COUNTER
, RONLY
, rip2IfStatEntry
,
115 {RIP2IFSTATSTATUS
, COUNTER
, RWRITE
, rip2IfStatEntry
,
117 {RIP2IFCONFADDRESS
, IPADDRESS
, RONLY
, rip2IfConfAddress
,
118 /* RIP Interface Configuration Table. */
120 {RIP2IFCONFDOMAIN
, STRING
, RONLY
, rip2IfConfAddress
,
122 {RIP2IFCONFAUTHTYPE
, COUNTER
, RONLY
, rip2IfConfAddress
,
124 {RIP2IFCONFAUTHKEY
, STRING
, RONLY
, rip2IfConfAddress
,
126 {RIP2IFCONFSEND
, COUNTER
, RONLY
, rip2IfConfAddress
,
128 {RIP2IFCONFRECEIVE
, COUNTER
, RONLY
, rip2IfConfAddress
,
130 {RIP2IFCONFDEFAULTMETRIC
, COUNTER
, RONLY
, rip2IfConfAddress
,
132 {RIP2IFCONFSTATUS
, COUNTER
, RONLY
, rip2IfConfAddress
,
134 {RIP2IFCONFSRCADDRESS
, IPADDRESS
, RONLY
, rip2IfConfAddress
,
136 {RIP2PEERADDRESS
, IPADDRESS
, RONLY
, rip2PeerTable
,
137 /* RIP Peer Table. */
139 {RIP2PEERDOMAIN
, STRING
, RONLY
, rip2PeerTable
,
141 {RIP2PEERLASTUPDATE
, TIMETICKS
, RONLY
, rip2PeerTable
,
143 {RIP2PEERVERSION
, INTEGER
, RONLY
, rip2PeerTable
,
145 {RIP2PEERRCVBADPACKETS
, COUNTER
, RONLY
, rip2PeerTable
,
147 {RIP2PEERRCVBADROUTES
, COUNTER
, RONLY
, rip2PeerTable
,
151 extern struct thread_master
*master
;
154 rip2Globals (struct variable
*v
, oid name
[], size_t *length
,
155 int exact
, size_t *var_len
, WriteMethod
**write_method
)
157 if (smux_header_generic(v
, name
, length
, exact
, var_len
, write_method
)
161 /* Retrun global counter. */
164 case RIP2GLOBALROUTECHANGES
:
165 return SNMP_INTEGER (rip_global_route_changes
);
167 case RIP2GLOBALQUERIES
:
168 return SNMP_INTEGER (rip_global_queries
);
178 rip_ifaddr_add (struct interface
*ifp
, struct connected
*ifc
)
181 struct route_node
*rn
;
185 if (p
->family
!= AF_INET
)
188 rn
= route_node_get (rip_ifaddr_table
, p
);
193 rip_ifaddr_delete (struct interface
*ifp
, struct connected
*ifc
)
196 struct route_node
*rn
;
201 if (p
->family
!= AF_INET
)
204 rn
= route_node_lookup (rip_ifaddr_table
, p
);
208 if (rn
&& !strncmp(i
->name
,ifp
->name
,INTERFACE_NAMSIZ
))
211 route_unlock_node (rn
);
212 route_unlock_node (rn
);
217 rip_ifaddr_lookup_next (struct in_addr
*addr
)
219 struct prefix_ipv4 p
;
220 struct route_node
*rn
;
221 struct interface
*ifp
;
224 p
.prefixlen
= IPV4_MAX_BITLEN
;
227 rn
= route_node_get (rip_ifaddr_table
, (struct prefix
*) &p
);
229 for (rn
= route_next (rn
); rn
; rn
= route_next (rn
))
236 *addr
= rn
->p
.u
.prefix4
;
237 route_unlock_node (rn
);
243 static struct interface
*
244 rip2IfLookup (struct variable
*v
, oid name
[], size_t *length
,
245 struct in_addr
*addr
, int exact
)
248 struct interface
*ifp
;
252 /* Check the length. */
253 if (*length
- v
->namelen
!= sizeof (struct in_addr
))
256 oid2in_addr (name
+ v
->namelen
, sizeof (struct in_addr
), addr
);
258 return if_lookup_exact_address (*addr
);
262 len
= *length
- v
->namelen
;
263 if (len
> 4) len
= 4;
265 oid2in_addr (name
+ v
->namelen
, len
, addr
);
267 ifp
= rip_ifaddr_lookup_next (addr
);
272 oid_copy_addr (name
+ v
->namelen
, addr
, sizeof (struct in_addr
));
274 *length
= v
->namelen
+ sizeof (struct in_addr
);
281 static struct rip_peer
*
282 rip2PeerLookup (struct variable
*v
, oid name
[], size_t *length
,
283 struct in_addr
*addr
, int exact
)
286 struct rip_peer
*peer
;
290 /* Check the length. */
291 if (*length
- v
->namelen
!= sizeof (struct in_addr
) + 1)
294 oid2in_addr (name
+ v
->namelen
, sizeof (struct in_addr
), addr
);
296 peer
= rip_peer_lookup (addr
);
298 if (peer
->domain
== name
[v
->namelen
+ sizeof (struct in_addr
)])
305 len
= *length
- v
->namelen
;
306 if (len
> 4) len
= 4;
308 oid2in_addr (name
+ v
->namelen
, len
, addr
);
310 len
= *length
- v
->namelen
;
311 peer
= rip_peer_lookup (addr
);
314 if ((len
< sizeof (struct in_addr
) + 1) ||
315 (peer
->domain
> name
[v
->namelen
+ sizeof (struct in_addr
)]))
317 oid_copy_addr (name
+ v
->namelen
, &peer
->addr
,
318 sizeof (struct in_addr
));
319 name
[v
->namelen
+ sizeof (struct in_addr
)] = peer
->domain
;
320 *length
= sizeof (struct in_addr
) + v
->namelen
+ 1;
324 peer
= rip_peer_lookup_next (addr
);
329 oid_copy_addr (name
+ v
->namelen
, &peer
->addr
,
330 sizeof (struct in_addr
));
331 name
[v
->namelen
+ sizeof (struct in_addr
)] = peer
->domain
;
332 *length
= sizeof (struct in_addr
) + v
->namelen
+ 1;
340 rip2IfStatEntry (struct variable
*v
, oid name
[], size_t *length
,
341 int exact
, size_t *var_len
, WriteMethod
**write_method
)
343 struct interface
*ifp
;
344 struct rip_interface
*ri
;
345 static struct in_addr addr
;
346 static long valid
= SNMP_VALID
;
348 memset (&addr
, 0, sizeof (struct in_addr
));
350 /* Lookup interface. */
351 ifp
= rip2IfLookup (v
, name
, length
, &addr
, exact
);
355 /* Fetch rip_interface information. */
360 case RIP2IFSTATADDRESS
:
361 return SNMP_IPADDRESS (addr
);
363 case RIP2IFSTATRCVBADPACKETS
:
364 *var_len
= sizeof (long);
365 return (u_char
*) &ri
->recv_badpackets
;
367 case RIP2IFSTATRCVBADROUTES
:
368 *var_len
= sizeof (long);
369 return (u_char
*) &ri
->recv_badroutes
;
371 case RIP2IFSTATSENTUPDATES
:
372 *var_len
= sizeof (long);
373 return (u_char
*) &ri
->sent_updates
;
375 case RIP2IFSTATSTATUS
:
376 *var_len
= sizeof (long);
377 v
->type
= ASN_INTEGER
;
378 return (u_char
*) &valid
;
388 rip2IfConfSend (struct rip_interface
*ri
)
391 #define ripVersion1 2
392 #define rip1Compatible 3
393 #define ripVersion2 4
394 #define ripV1Demand 5
395 #define ripV2Demand 6
400 if (ri
->ri_send
& RIPv2
)
402 else if (ri
->ri_send
& RIPv1
)
406 if (rip
->version_send
== RIPv2
)
408 else if (rip
->version_send
== RIPv1
)
415 rip2IfConfReceive (struct rip_interface
*ri
)
420 #define doNotReceive 4
427 recvv
= (ri
->ri_receive
== RI_RIP_UNSPEC
) ? rip
->version_recv
:
429 if (recvv
== RI_RIP_VERSION_1_AND_2
)
431 else if (recvv
& RIPv2
)
433 else if (recvv
& RIPv1
)
440 rip2IfConfAddress (struct variable
*v
, oid name
[], size_t *length
,
441 int exact
, size_t *val_len
, WriteMethod
**write_method
)
443 static struct in_addr addr
;
444 static long valid
= SNMP_INVALID
;
445 static long domain
= 0;
446 static long config
= 0;
447 static u_int auth
= 0;
448 struct interface
*ifp
;
449 struct rip_interface
*ri
;
451 memset (&addr
, 0, sizeof (struct in_addr
));
453 /* Lookup interface. */
454 ifp
= rip2IfLookup (v
, name
, length
, &addr
, exact
);
458 /* Fetch rip_interface information. */
463 case RIP2IFCONFADDRESS
:
464 *val_len
= sizeof (struct in_addr
);
465 return (u_char
*) &addr
;
467 case RIP2IFCONFDOMAIN
:
469 return (u_char
*) &domain
;
471 case RIP2IFCONFAUTHTYPE
:
472 auth
= ri
->auth_type
;
473 *val_len
= sizeof (long);
474 v
->type
= ASN_INTEGER
;
475 return (u_char
*)&auth
;
477 case RIP2IFCONFAUTHKEY
:
479 return (u_char
*) &domain
;
481 config
= rip2IfConfSend (ri
);
482 *val_len
= sizeof (long);
483 v
->type
= ASN_INTEGER
;
484 return (u_char
*) &config
;
485 case RIP2IFCONFRECEIVE
:
486 config
= rip2IfConfReceive (ri
);
487 *val_len
= sizeof (long);
488 v
->type
= ASN_INTEGER
;
489 return (u_char
*) &config
;
491 case RIP2IFCONFDEFAULTMETRIC
:
492 *val_len
= sizeof (long);
493 v
->type
= ASN_INTEGER
;
494 return (u_char
*) &ifp
->metric
;
495 case RIP2IFCONFSTATUS
:
496 *val_len
= sizeof (long);
497 v
->type
= ASN_INTEGER
;
498 return (u_char
*) &valid
;
499 case RIP2IFCONFSRCADDRESS
:
500 *val_len
= sizeof (struct in_addr
);
501 return (u_char
*) &addr
;
511 rip2PeerTable (struct variable
*v
, oid name
[], size_t *length
,
512 int exact
, size_t *val_len
, WriteMethod
**write_method
)
514 static struct in_addr addr
;
515 static int domain
= 0;
517 /* static time_t uptime; */
519 struct rip_peer
*peer
;
521 memset (&addr
, 0, sizeof (struct in_addr
));
523 /* Lookup interface. */
524 peer
= rip2PeerLookup (v
, name
, length
, &addr
, exact
);
530 case RIP2PEERADDRESS
:
531 *val_len
= sizeof (struct in_addr
);
532 return (u_char
*) &peer
->addr
;
536 return (u_char
*) &domain
;
538 case RIP2PEERLASTUPDATE
:
540 /* We don't know the SNMP agent startup time. We have two choices here:
541 * - assume ripd startup time equals SNMP agent startup time
542 * - don't support this variable, at all
543 * Currently, we do the latter...
545 *val_len
= sizeof (time_t);
546 uptime
= peer
->uptime
; /* now - snmp_agent_startup - peer->uptime */
547 return (u_char
*) &uptime
;
549 return (u_char
*) NULL
;
552 case RIP2PEERVERSION
:
553 *val_len
= sizeof (int);
554 version
= peer
->version
;
555 return (u_char
*) &version
;
557 case RIP2PEERRCVBADPACKETS
:
558 *val_len
= sizeof (int);
559 return (u_char
*) &peer
->recv_badpackets
;
561 case RIP2PEERRCVBADROUTES
:
562 *val_len
= sizeof (int);
563 return (u_char
*) &peer
->recv_badroutes
;
572 /* Register RIPv2-MIB. */
576 rip_ifaddr_table
= route_table_init ();
579 REGISTER_MIB("mibII/rip", rip_variables
, variable
, rip_oid
);
581 #endif /* HAVE_SNMP */