2 * snmp_var_route.c - return a pointer to the named variable.
6 /***********************************************************
7 Copyright 1988, 1989 by Carnegie Mellon University
8 Copyright 1989 TGV, Incorporated
12 Permission to use, copy, modify, and distribute this software and its
13 documentation for any purpose and without fee is hereby granted,
14 provided that the above copyright notice appear in all copies and that
15 both that copyright notice and this permission notice appear in
16 supporting documentation, and that the name of CMU and TGV not be used
17 in advertising or publicity pertaining to distribution of the software
18 without specific, written prior permission.
20 CMU AND TGV DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
22 EVENT SHALL CMU OR TGV BE LIABLE FOR ANY SPECIAL, INDIRECT OR
23 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26 PERFORMANCE OF THIS SOFTWARE.
27 ******************************************************************/
29 * additions, fixes and enhancements for Linux by Erik Schoenfelder
30 * (schoenfr@ibr.cs.tu-bs.de) 1994/1995.
31 * Linux additions taken from CMU to UCD stack by Jennifer Bray of Origin
32 * (jbray@origin-at.co.uk) 1997
33 * Support for system({CTL_NET,PF_ROUTE,...) by Simon Leinen
34 * (simon@switch.ch) 1997
37 #include <net-snmp/net-snmp-config.h>
39 #if !defined(CAN_USE_SYSCTL)
41 #define GATEWAY /* MultiNet is always configured this way! */
43 #include <sys/types.h>
45 #include <sys/param.h>
48 #include <sys/socket.h>
50 #if TIME_WITH_SYS_TIME
52 # include <sys/timeb.h>
54 # include <sys/time.h>
59 # include <sys/time.h>
65 #include <sys/select.h>
68 #include <netinet/in.h>
71 #include <arpa/inet.h>
76 #if HAVE_MACHINE_PARAM_H
77 #include <machine/param.h>
85 #ifdef HAVE_NET_IF_VAR_H
86 #include <net/if_var.h>
88 #if HAVE_SYS_HASHING_H
89 #include <sys/hashing.h>
91 #if HAVE_NETINET_IN_VAR_H
92 #include <netinet/in_var.h>
94 #define KERNEL /* to get routehash and RTHASHSIZ */
96 #include <sys/stream.h>
99 #include <net/route.h>
103 #ifndef STRUCT_RTENTRY_HAS_RT_UNIT
104 #define rt_unit rt_refcnt /* Reuse this field for device # */
106 #ifndef STRUCT_RTENTRY_HAS_RT_DST
107 #define rt_dst rt_nodes->rn_key
109 #else /* RTENTRY_4_3 */
110 #ifndef STRUCT_RTENTRY_HAS_RT_DST
111 #define rt_dst rt_nodes->rn_key
113 #ifndef STRUCT_RTENTRY_HAS_RT_HASH
114 #define rt_hash rt_pad1
116 #ifndef STRUCT_RTENTRY_HAS_RT_REFCNT
118 #define rt_refcnt rt_pad2
121 #ifndef STRUCT_RTENTRY_HAS_RT_USE
122 #define rt_use rt_pad3
124 #ifndef STRUCT_RTENTRY_HAS_RT_UNIT
125 #define rt_unit rt_refcnt /* Reuse this field for device # */
131 #if HAVE_KVM_OPENFILES
147 #include <inet/mib2.h>
149 #if HAVE_SYS_SYSCTL_H
150 #include <sys/sysctl.h>
154 #include <net/if_dl.h>
156 #include <sys/net/if_dl.h>
169 #include "kernel_sunos5.h"
172 #ifdef HAVE_SYS_SYSCTL_H
176 # define USE_SYSCTL_ROUTE_DUMP
191 #define CACHE_TIME (120) /* Seconds */
193 #include <net-snmp/net-snmp-includes.h>
194 #include <net-snmp/agent/net-snmp-agent-includes.h>
195 #include <net-snmp/agent/auto_nlist.h>
199 #include "interfaces.h"
201 #include "util_funcs.h"
204 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
209 #include <netinet/mib_kern.h>
212 extern WriteMethod write_rte;
216 #ifdef USE_SYSCTL_ROUTE_DUMP
218 static void Route_Scan_Reload(void);
220 static unsigned char *all_routes = 0;
221 static unsigned char *all_routes_end;
222 static size_t all_routes_size;
224 extern const struct sockaddr *get_address(const void *, int, int);
225 extern const struct in_addr *get_in_address(const void *, int, int);
228 * var_ipRouteEntry(...
230 * vp IN - pointer to variable entry that points here
231 * name IN/OUT - IN/name requested, OUT/name found
232 * length IN/OUT - length of IN/OUT oid's
233 * exact IN - TRUE if an exact match was requested
234 * var_len OUT - length of variable or 0 if function returned
235 * write_method out - pointer to function to set variable, otherwise 0
238 var_ipRouteEntry(struct variable *vp,
241 int exact, size_t * var_len, WriteMethod ** write_method)
244 * object identifier is of form:
245 * 1.3.6.1.2.1.4.21.1.1.A.B.C.D, where A.B.C.D is IP address.
246 * IPADDR starts at offset 10.
248 struct rt_msghdr *rtp, *saveRtp = 0;
249 register int Save_Valid, result;
250 static int saveNameLen = 0, saveExact = 0;
251 static oid saveName[MAX_OID_LEN], Current[MAX_OID_LEN];
257 ** this optimisation fails, if there is only a single route avail.
258 ** it is a very special case, but better leave it out ...
268 * If the name was the same as the last name, with the possible
269 * exception of the [9]th token, then don't read the routing table
273 if ((saveNameLen == *length) && (saveExact == exact)) {
274 register int temp = name[9];
277 (snmp_oid_compare(name, *length, saveName, saveNameLen) == 0);
282 if (Save_Valid && saveRtp) {
283 register int temp = name[9]; /* Fix up 'lowest' found entry */
284 memcpy((char *) name, (char *) Current, 14 * sizeof(oid));
291 * fill in object part of name for current (less sizeof instance part)
294 memcpy((char *) Current, (char *) vp->name,
295 (int) (vp->namelen) * sizeof(oid));
299 * Only reload if this is the start of a wildcard
307 for (ap = all_routes; ap < all_routes_end; ap += rtp->rtm_msglen) {
308 rtp = (struct rt_msghdr *) ap;
309 if (rtp->rtm_type == 0)
311 if (rtp->rtm_version != RTM_VERSION) {
313 "routing socket message version mismatch (%d instead of %d)\n",
314 rtp->rtm_version, RTM_VERSION);
317 if (rtp->rtm_type != RTM_GET) {
319 "routing socket returned message other than GET (%d)\n",
323 if (!(rtp->rtm_addrs & RTA_DST))
325 cp = (u_char *) get_in_address((struct sockaddr *) (rtp + 1),
326 rtp->rtm_addrs, RTA_DST);
336 result = snmp_oid_compare(name, *length, Current, 14);
337 if ((exact && (result == 0)) || (!exact && (result < 0)))
340 if (ap >= all_routes_end || rtp->rtm_type == 0)
343 * Save in the 'cache'
345 memcpy((char *) saveName, (char *) name,
346 SNMP_MIN(*length, MAX_OID_LEN) * sizeof(oid));
348 saveNameLen = *length;
354 memcpy((char *) name, (char *) Current, 14 * sizeof(oid));
360 *write_method = write_rte;
361 *var_len = sizeof(long_return);
365 return (u_char *) get_in_address((struct sockaddr *) (rtp + 1),
366 rtp->rtm_addrs, RTA_DST);
368 long_return = (u_long) rtp->rtm_index;
369 return (u_char *) & long_return;
371 long_return = (rtp->rtm_flags & RTF_UP) ? 1 : 0;
372 return (u_char *) & long_return;
378 return (u_char *) & long_return;
384 return (u_char *) & long_return;
390 return (u_char *) & long_return;
396 return (u_char *) & long_return;
398 return (u_char *) get_in_address((struct sockaddr *) (rtp + 1),
399 rtp->rtm_addrs, RTA_GATEWAY);
401 if (rtp->rtm_flags & RTF_UP) {
402 if (rtp->rtm_flags & RTF_GATEWAY) {
403 long_return = 4; /* indirect(4) */
405 long_return = 3; /* direct(3) */
408 long_return = 2; /* invalid(2) */
410 return (u_char *) & long_return;
412 long_return = (rtp->rtm_flags & RTF_DYNAMIC)
413 ? 10 : (rtp->rtm_flags & RTF_STATIC)
414 ? 2 : (rtp->rtm_flags & RTF_DYNAMIC) ? 4 : 1;
415 return (u_char *) & long_return;
421 return (u_char *) & long_return;
423 if (rtp->rtm_flags & RTF_HOST) {
424 long_return = 0x00000001;
425 return (u_char *) & long_return;
427 return (u_char *) get_in_address((struct sockaddr *) (rtp + 1),
428 rtp->rtm_addrs, RTA_NETMASK);
431 *var_len = nullOidLen;
432 return (u_char *) nullOid;
434 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipRouteEntry\n",
440 #else /* not USE_SYSCTL_ROUTE_DUMP */
442 static void Route_Scan_Reload(void);
445 static int rtsize = 0;
446 static mib_ipRouteEnt *rt = (mib_ipRouteEnt *) 0;
448 static RTENTRY **rthead = 0;
449 static int rtsize = 0, rtallocate = 0;
452 #if !(defined(linux) || defined(solaris2) || defined(hpux11))
453 #define NUM_ROUTE_SYMBOLS 2
454 static char *route_symbols[] = {
461 #ifdef USE_SYSCTL_ROUTE_DUMP
467 init_kernel_sunos5();
472 Route_Scan_Reload(void)
475 int name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_DUMP, 0 };
477 if (sysctl(name, sizeof(name) / sizeof(int), 0, &size, 0, 0) == -1) {
478 snmp_log(LOG_ERR, "sysctl(CTL_NET,PF_ROUTE,0,0,NET_RT_DUMP,0)\n");
480 if (all_routes == 0 || all_routes_size < size) {
481 if (all_routes != 0) {
485 if ((all_routes = malloc(size)) == 0) {
487 "out of memory allocating route table\n");
489 all_routes_size = size;
491 size = all_routes_size;
493 if (sysctl(name, sizeof(name) / sizeof(int),
494 all_routes, &size, 0, 0) == -1) {
496 "sysctl(CTL_NET,PF_ROUTE,0,0,NET_RT_DUMP,0)\n");
498 all_routes_end = all_routes + size;
502 #else /* not USE_SYSCTL_ROUTE_DUMP */
507 #ifdef RTTABLES_SYMBOL
508 auto_nlist(RTTABLES_SYMBOL, 0, 0);
510 #ifdef RTHASHSIZE_SYMBOL
511 auto_nlist(RTHASHSIZE_SYMBOL, 0, 0);
514 auto_nlist(RTHOST_SYMBOL, 0, 0);
517 auto_nlist(RTNET_SYMBOL, 0, 0);
525 struct sockaddr_in sin;
530 klgetsa(struct sockaddr_in *dst)
532 klookup((u_long) dst, (char *) &klgetsatmp.sin, sizeof klgetsatmp.sin);
533 if (klgetsatmp.sin.sin_len > sizeof(klgetsatmp.sin))
534 klookup((u_long) dst, (char *) &klgetsatmp.sin,
535 klgetsatmp.sin.sin_len);
536 return (&klgetsatmp.sin);
541 var_ipRouteEntry(struct variable * vp,
544 int exact, size_t * var_len, WriteMethod ** write_method)
547 * object identifier is of form:
548 * 1.3.6.1.2.1.4.21.1.1.A.B.C.D, where A.B.C.D is IP address.
549 * IPADDR starts at offset 10.
551 register int Save_Valid, result, RtIndex;
552 static int saveNameLen = 0, saveExact = 0, saveRtIndex = 0;
553 static oid saveName[MAX_OID_LEN], Current[MAX_OID_LEN];
557 struct sockaddr_in *sa;
559 #if !defined(linux) && !defined(hpux11)
560 struct ifnet rt_ifnet;
561 struct in_ifaddr rt_ifnetaddr;
564 ** this optimisation fails, if there is only a single route avail.
565 ** it is a very special case, but better leave it out ...
577 * If the name was the same as the last name, with the possible
578 * exception of the [9]th token, then don't read the routing table
582 if ((saveNameLen == *length) && (saveExact == exact)) {
583 register int temp = name[9];
586 (snmp_oid_compare(name, *length, saveName, saveNameLen) == 0);
592 register int temp = name[9]; /* Fix up 'lowest' found entry */
593 memcpy((char *) name, (char *) Current, 14 * sizeof(oid));
596 RtIndex = saveRtIndex;
599 * fill in object part of name for current (less sizeof instance part)
602 memcpy((char *) Current, (char *) vp->name,
603 (int) (vp->namelen) * sizeof(oid));
607 * Only reload if this is the start of a wildcard
615 for (RtIndex = 0; RtIndex < rtsize; RtIndex++) {
617 sa = klgetsa((struct sockaddr_in *) rthead[RtIndex]->rt_dst);
618 cp = (u_char *) & (sa->sin_addr.s_addr);
619 #elif defined(hpux11)
620 cp = (u_char *) & rt[RtIndex].Dest;
623 (((struct sockaddr_in *) &(rthead[RtIndex]->rt_dst))->
632 result = snmp_oid_compare(name, *length, Current, 14);
633 if ((exact && (result == 0)) || (!exact && (result < 0)))
636 if (RtIndex >= rtsize)
639 * Save in the 'cache'
641 memcpy((char *) saveName, (char *) name,
642 SNMP_MIN(*length, MAX_OID_LEN) * sizeof(oid));
644 saveNameLen = *length;
646 saveRtIndex = RtIndex;
650 memcpy((char *) name, (char *) Current, 14 * sizeof(oid));
654 #ifdef BRCM_SNMP_WRITE_SUPPORT
655 *write_method = write_rte;
657 *write_method = NULL;
659 *var_len = sizeof(long_return);
664 sa = klgetsa((struct sockaddr_in *) rthead[RtIndex]->rt_dst);
665 return (u_char *) & (sa->sin_addr.s_addr);
666 #elif defined(hpux11)
667 long_return = rt[RtIndex].Dest;
668 return (u_char *) & long_return;
670 return (u_char *) & ((struct sockaddr_in *) &rthead[RtIndex]->
671 rt_dst)->sin_addr.s_addr;
675 long_return = rt[RtIndex].IfIndex;
677 long_return = (u_long) rthead[RtIndex]->rt_unit;
679 return (u_char *) & long_return;
682 long_return = rt[RtIndex].Metric1;
684 long_return = (rthead[RtIndex]->rt_flags & RTF_GATEWAY) ? 1 : 0;
686 return (u_char *) & long_return;
689 long_return = rt[RtIndex].Metric2;
690 return (u_char *) & long_return;
691 #elif defined(NO_DUMMY_VALUES)
695 return (u_char *) & long_return;
698 long_return = rt[RtIndex].Metric3;
699 return (u_char *) & long_return;
700 #elif defined(NO_DUMMY_VALUES)
704 return (u_char *) & long_return;
707 long_return = rt[RtIndex].Metric4;
708 return (u_char *) & long_return;
709 #elif defined(NO_DUMMY_VALUES)
713 return (u_char *) & long_return;
719 return (u_char *) & long_return;
722 sa = klgetsa((struct sockaddr_in *) rthead[RtIndex]->rt_gateway);
723 return (u_char *) & (sa->sin_addr.s_addr);
724 #elif defined(hpux11)
725 long_return = rt[RtIndex].NextHop;
726 return (u_char *) & long_return;
728 return (u_char *) & ((struct sockaddr_in *) &rthead[RtIndex]->
729 rt_gateway)->sin_addr.s_addr;
733 long_return = rt[RtIndex].Type;
735 if (rthead[RtIndex]->rt_flags & RTF_UP) {
736 if (rthead[RtIndex]->rt_flags & RTF_GATEWAY) {
737 long_return = 4; /* indirect(4) */
739 long_return = 3; /* direct(3) */
742 long_return = 2; /* invalid(2) */
745 return (u_char *) & long_return;
748 long_return = rt[RtIndex].Proto;
750 long_return = (rthead[RtIndex]->rt_flags & RTF_DYNAMIC) ? 4 : 2;
752 return (u_char *) & long_return;
755 long_return = rt[RtIndex].Age;
756 return (u_char *) & long_return;
757 #elif defined(NO_DUMMY_VALUES)
761 return (u_char *) & long_return;
765 * XXX - Almost certainly not right
766 * but I don't have a suitable system to test this on
772 #elif defined(hpux11)
773 long_return = rt[RtIndex].Mask;
774 return (u_char *) & long_return;
775 #else /* !NEED_KLGETSA && !hpux11 */
776 if (((struct sockaddr_in *) &rthead[RtIndex]->rt_dst)->sin_addr.
778 long_return = 0; /* Default route */
781 klookup((unsigned long) rthead[RtIndex]->rt_ifp,
782 (char *) &rt_ifnet, sizeof(rt_ifnet));
783 klookup((unsigned long) rt_ifnet.if_addrlist,
784 (char *) &rt_ifnetaddr, sizeof(rt_ifnetaddr));
786 long_return = rt_ifnetaddr.ia_subnetmask;
789 (((struct sockaddr_in *) &(rthead[RtIndex]->rt_dst))->
792 (((struct sockaddr_in *) &(rthead[RtIndex]->rt_genmask))->
796 #endif /* NEED_KLGETSA */
797 return (u_char *) & long_return;
799 *var_len = nullOidLen;
800 return (u_char *) nullOid;
802 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipRouteEntry\n",
811 IP_Cmp_Route(void *addr, void *ep)
813 mib2_ipRouteEntry_t *Ep = ep, *Addr = addr;
815 if ((Ep->ipRouteDest == Addr->ipRouteDest) &&
816 (Ep->ipRouteNextHop == Addr->ipRouteNextHop) &&
817 (Ep->ipRouteType == Addr->ipRouteType) &&
818 (Ep->ipRouteProto == Addr->ipRouteProto) &&
819 (Ep->ipRouteMask == Addr->ipRouteMask) &&
820 (Ep->ipRouteInfo.re_max_frag == Addr->ipRouteInfo.re_max_frag) &&
821 (Ep->ipRouteInfo.re_rtt == Addr->ipRouteInfo.re_rtt) &&
822 (Ep->ipRouteInfo.re_ref == Addr->ipRouteInfo.re_ref) &&
823 (Ep->ipRouteInfo.re_frag_flag == Addr->ipRouteInfo.re_frag_flag) &&
824 (Ep->ipRouteInfo.re_src_addr == Addr->ipRouteInfo.re_src_addr) &&
825 (Ep->ipRouteInfo.re_ire_type == Addr->ipRouteInfo.re_ire_type) &&
826 (Ep->ipRouteInfo.re_obpkt == Addr->ipRouteInfo.re_obpkt) &&
827 (Ep->ipRouteInfo.re_ibpkt == Addr->ipRouteInfo.re_ibpkt)
831 return (1); /* Not found */
835 var_ipRouteEntry(struct variable * vp,
838 int exact, size_t * var_len, WriteMethod ** write_method)
841 * object identifier is of form:
842 * 1.3.6.1.2.1.4.21.1.1.A.B.C.D, where A.B.C.D is IP address.
843 * IPADDR starts at offset 10.
845 #define IP_ROUTENAME_LENGTH 14
846 #define IP_ROUTEADDR_OFF 10
847 oid current[IP_ROUTENAME_LENGTH],
848 lowest[IP_ROUTENAME_LENGTH];
851 mib2_ipRouteEntry_t Lowentry, Nextentry, entry;
856 * fill in object part of name for current (less sizeof instance part)
859 memcpy((char *) current, (char *) vp->name, vp->namelen * sizeof(oid));
860 if (*length == IP_ROUTENAME_LENGTH) /* Assume that the input name is the lowest */
861 memcpy((char *) lowest, (char *) name,
862 IP_ROUTENAME_LENGTH * sizeof(oid));
864 name[IP_ROUTEADDR_OFF] = (oid) - 1; /* Grhhh: to prevent accidental comparison :-( */
865 for (Nextentry.ipRouteDest = (u_long) - 2, req_type = GET_FIRST;;
866 Nextentry = entry, req_type = GET_NEXT) {
867 if (getMibstat(MIB_IP_ROUTE, &entry, sizeof(mib2_ipRouteEntry_t),
868 req_type, &IP_Cmp_Route, &Nextentry) != 0)
870 COPY_IPADDR(cp, (u_char *) & entry.ipRouteDest, op,
871 current + IP_ROUTEADDR_OFF);
874 (current, IP_ROUTENAME_LENGTH, name, *length) == 0) {
875 memcpy((char *) lowest, (char *) current,
876 IP_ROUTENAME_LENGTH * sizeof(oid));
879 break; /* no need to search further */
882 if ((snmp_oid_compare
883 (current, IP_ROUTENAME_LENGTH, name, *length) > 0)
884 && ((Nextentry.ipRouteDest == (u_long) - 2)
887 (current, IP_ROUTENAME_LENGTH, lowest,
888 IP_ROUTENAME_LENGTH) < 0)
891 (name, IP_ROUTENAME_LENGTH, lowest,
892 IP_ROUTENAME_LENGTH) == 0))) {
895 * if new one is greater than input and closer to input than
896 * * previous lowest, and is not equal to it, save this one as the "next" one.
898 memcpy((char *) lowest, (char *) current,
899 IP_ROUTENAME_LENGTH * sizeof(oid));
907 memcpy((char *) name, (char *) lowest,
908 IP_ROUTENAME_LENGTH * sizeof(oid));
909 *length = IP_ROUTENAME_LENGTH;
910 *write_method = write_rte;
911 *var_len = sizeof(long_return);
915 long_return = Lowentry.ipRouteDest;
916 return (u_char *) & long_return;
919 Interface_Index_By_Name(Lowentry.ipRouteIfIndex.o_bytes,
920 Lowentry.ipRouteIfIndex.o_length);
921 return (u_char *) & long_return;
923 long_return = Lowentry.ipRouteMetric1;
924 return (u_char *) & long_return;
926 long_return = Lowentry.ipRouteMetric2;
927 return (u_char *) & long_return;
929 long_return = Lowentry.ipRouteMetric3;
930 return (u_char *) & long_return;
932 long_return = Lowentry.ipRouteMetric4;
933 return (u_char *) & long_return;
935 long_return = Lowentry.ipRouteNextHop;
936 return (u_char *) & long_return;
938 long_return = Lowentry.ipRouteType;
939 return (u_char *) & long_return;
941 long_return = Lowentry.ipRouteProto;
942 if (long_return == -1)
944 return (u_char *) & long_return;
946 long_return = Lowentry.ipRouteAge;
947 return (u_char *) & long_return;
949 long_return = Lowentry.ipRouteMask;
950 return (u_char *) & long_return;
952 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipRouteEntry\n",
958 #endif /* solaris2 - var_IProute */
961 static int qsort_compare(const void *, const void *);
964 #if defined(RTENTRY_4_4) || defined(RTENTRY_RT_NEXT)
966 #if defined(RTENTRY_4_4) && !defined(hpux11)
968 load_rtentries(struct radix_node *pt)
970 struct radix_node node;
973 char name[16], temp[16];
974 #if !STRUCT_IFNET_HAS_IF_XNAME
979 ((unsigned long) pt, (char *) &node, sizeof(struct radix_node))) {
980 DEBUGMSGTL(("mibII/var_route", "Fail\n"));
983 if (node.rn_b >= 0) {
984 load_rtentries(node.rn_r);
985 load_rtentries(node.rn_l);
987 if (node.rn_flags & RNF_ROOT) {
991 if (node.rn_dupedkey)
992 load_rtentries(node.rn_dupedkey);
998 klookup((unsigned long) pt, (char *) &rt, sizeof(RTENTRY));
1000 if (rt.rt_ifp != 0) {
1001 klookup((unsigned long) rt.rt_ifp, (char *) &ifnet,
1003 #if STRUCT_IFNET_HAS_IF_XNAME
1004 #if defined(netbsd1) || defined(openbsd2)
1005 strncpy(name, ifnet.if_xname, sizeof name);
1007 klookup((unsigned long) ifnet.if_xname, name, sizeof name);
1009 name[sizeof(name) - 1] = '\0';
1011 klookup((unsigned long) ifnet.if_name, name, sizeof name);
1012 name[sizeof(name) - 1] = '\0';
1013 cp = (char *) strchr(name, '\0');
1014 string_append_int(cp, ifnet.if_unit);
1016 Interface_Scan_Init();
1018 while (Interface_Scan_Next
1019 ((short *) &(rt.rt_unit), temp, NULL, NULL) != 0) {
1020 if (strcmp(name, temp) == 0)
1025 if (((rt.rt_flags & RTF_CLONING) != RTF_CLONING)
1026 && ((rt.rt_flags & RTF_LLINFO) != RTF_LLINFO)) {
1029 * check for space and malloc
1031 if (rtsize >= rtallocate) {
1033 (RTENTRY **) realloc((char *) rthead,
1036 memset((char *) &rthead[rtallocate], (0),
1037 rtallocate * sizeof(RTENTRY *));
1041 if (!rthead[rtsize])
1042 rthead[rtsize] = (RTENTRY *) malloc(sizeof(RTENTRY));
1044 * Add this to the database
1046 memcpy((char *) rthead[rtsize], (char *) &rt, sizeof(RTENTRY));
1052 if (node.rn_dupedkey)
1053 load_rtentries(node.rn_dupedkey);
1056 #endif /* RTENTRY_4_4 && !hpux11 */
1059 Route_Scan_Reload(void)
1071 rt = (mib_ipRouteEnt *) 0;
1074 if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) >= 0) {
1075 p.objid = ID_ipRouteNumEnt;
1076 p.buffer = (void *) &val;
1079 if ((ret = get_mib_info(fd, &p)) == 0)
1083 ulen = (unsigned) rtsize *sizeof(mib_ipRouteEnt);
1084 rt = (mib_ipRouteEnt *) malloc(ulen);
1085 p.objid = ID_ipRouteTable;
1086 p.buffer = (void *) rt;
1088 if ((ret = get_mib_info(fd, &p)) < 0)
1098 qsort((char *) rt, rtsize, sizeof(rt[0]),
1100 (int (*)(const void *, const void *)) qsort_compare
1107 #if defined(RTENTRY_4_4)
1108 struct radix_node_head head, *rt_table[AF_MAX + 1];
1111 RTENTRY **routehash, mb;
1112 register RTENTRY *m;
1117 char name[16], temp[16];
1120 static int Time_Of_Last_Reload = 0;
1123 gettimeofday(&now, (struct timezone *) 0);
1124 if (Time_Of_Last_Reload + CACHE_TIME > now.tv_sec)
1126 Time_Of_Last_Reload = now.tv_sec;
1129 * * Makes sure we have SOME space allocated for new routing entries
1132 rthead = (RTENTRY **) malloc(100 * sizeof(RTENTRY *));
1134 snmp_log(LOG_ERR, "route table malloc fail\n");
1137 memset((char *) rthead, (0), 100 * sizeof(RTENTRY *));
1142 * reset the routing table size to zero -- was a CMU memory leak
1148 * rtentry is a BSD 4.4 compat
1151 #if !defined(AF_UNSPEC)
1152 #define AF_UNSPEC AF_INET
1155 auto_nlist(RTTABLES_SYMBOL, (char *) rt_table, sizeof(rt_table));
1156 for (i = 0; i <= AF_MAX; i++) {
1157 if (rt_table[i] == 0)
1160 ((unsigned long) rt_table[i], (char *) &head, sizeof(head))) {
1161 load_rtentries(head.rnh_treetop);
1165 #else /* rtentry is a BSD 4.3 compat */
1166 for (table = 0; table < NUM_ROUTE_SYMBOLS; table++) {
1167 auto_nlist(RTHASHSIZE_SYMBOL, (char *) &hashsize,
1169 routehash = (RTENTRY **) malloc(hashsize * sizeof(struct mbuf *));
1170 auto_nlist(route_symbols[table], (char *) routehash,
1171 hashsize * sizeof(struct mbuf *));
1172 for (i = 0; i < hashsize; i++) {
1173 if (routehash[i] == 0)
1178 * Dig the route out of the kernel...
1180 klookup(m, (char *) &mb, sizeof(mb));
1184 if (rt->rt_ifp != 0) {
1185 klookup(rt->rt_ifp, (char *) &ifnet, sizeof(ifnet));
1186 klookup(ifnet.if_name, name, 16);
1188 cp = (char *) strchr(name, '\0');
1189 string_append_int(cp, ifnet.if_unit);
1191 Interface_Scan_Init();
1192 while (Interface_Scan_Next
1193 ((short *) &rt->rt_unit, temp, NULL,
1195 if (strcmp(name, temp) == 0)
1200 * Allocate a block to hold it and add it to the database
1202 if (rtsize >= rtallocate) {
1204 (RTENTRY **) realloc((char *) rthead,
1207 memset((char *) &rthead[rtallocate], (0),
1208 rtallocate * sizeof(RTENTRY *));
1212 if (!rthead[rtsize])
1213 rthead[rtsize] = (RTENTRY *) malloc(sizeof(RTENTRY));
1215 * Add this to the database
1217 memcpy((char *) rthead[rtsize], (char *) rt,
1228 qsort((char *) rthead, rtsize, sizeof(rthead[0]),
1230 (int (*)(const void *, const void *)) qsort_compare
1242 Route_Scan_Reload(void)
1244 struct mbuf **routehash, mb;
1245 register struct mbuf *m;
1250 char name[16], temp[16];
1251 static int Time_Of_Last_Reload = 0;
1255 gettimeofday(&now, (struct timezone *) 0);
1256 if (Time_Of_Last_Reload + CACHE_TIME > now.tv_sec)
1258 Time_Of_Last_Reload = now.tv_sec;
1261 * Makes sure we have SOME space allocated for new routing entries
1264 rthead = (RTENTRY **) malloc(100 * sizeof(RTENTRY *));
1266 snmp_log(LOG_ERR, "route table malloc fail\n");
1269 memset((char *) rthead, (0), 100 * sizeof(RTENTRY *));
1274 * reset the routing table size to zero -- was a CMU memory leak
1278 for (table = 0; table < NUM_ROUTE_SYMBOLS; table++) {
1280 hashsize = RTHASHSIZ;
1282 auto_nlist(RTHASHSIZE_SYMBOL, (char *) &hashsize,
1286 (struct mbuf **) malloc(hashsize * sizeof(struct mbuf *));
1287 auto_nlist(route_symbols[table], (char *) routehash,
1288 hashsize * sizeof(struct mbuf *));
1289 for (i = 0; i < hashsize; i++) {
1290 if (routehash[i] == 0)
1295 * Dig the route out of the kernel...
1297 klookup((unsigned long) m, (char *) &mb, sizeof(mb));
1299 rt = mtod(&mb, RTENTRY *);
1301 if (rt->rt_ifp != 0) {
1303 klookup((unsigned long) rt->rt_ifp, (char *) &ifnet,
1305 klookup((unsigned long) ifnet.if_name, name, 16);
1307 cp = (char *) strchr(name, '\0');
1308 string_append_int(cp, ifnet.if_unit);
1309 if (strcmp(name, "lo0") == 0)
1312 Interface_Scan_Init();
1313 while (Interface_Scan_Next
1314 ((short *) &rt->rt_unit, temp, NULL,
1316 if (strcmp(name, temp) == 0)
1321 * Allocate a block to hold it and add it to the database
1323 if (rtsize >= rtallocate) {
1325 (RTENTRY **) realloc((char *) rthead,
1328 memset((char *) &rthead[rtallocate], (0),
1329 rtallocate * sizeof(RTENTRY *));
1333 if (!rthead[rtsize])
1334 rthead[rtsize] = (RTENTRY *) malloc(sizeof(RTENTRY));
1336 * * Add this to the database
1338 memcpy((char *) rthead[rtsize], (char *) rt,
1348 qsort((char *) rthead, rtsize, sizeof(rthead[0]), qsort_compare);
1353 Route_Scan_Reload(void)
1358 char name[16], temp[16];
1359 static int Time_Of_Last_Reload = 0;
1363 * allow 20 seconds in cache:
1365 gettimeofday(&now, (struct timezone *) 0);
1366 if (Time_Of_Last_Reload + 20 > now.tv_sec)
1368 Time_Of_Last_Reload = now.tv_sec;
1371 * Makes sure we have SOME space allocated for new routing entries
1374 rthead = (struct rtentry **) calloc(100, sizeof(struct rtentry *));
1376 snmp_log(LOG_ERR, "route table malloc fail\n");
1383 * fetch routes from the proc file-system:
1388 if (!(in = fopen("/proc/net/route", "r"))) {
1389 snmp_log(LOG_ERR, "cannot open /proc/net/route - burps\n");
1393 while (fgets(line, sizeof(line), in)) {
1394 struct rtentry rtent;
1395 char rtent_name[32];
1396 int refcnt, flags, metric;
1400 memset((char *) rt, (0), sizeof(*rt));
1401 rt->rt_dev = rtent_name;
1405 * Iface Dest GW Flags RefCnt Use Metric Mask MTU Win IRTT
1406 * eth0 0A0A0A0A 00000000 05 0 0 0 FFFFFFFF 1500 0 0
1408 if (8 != sscanf(line, "%s %x %x %x %u %d %d %x %*d %*d %*d\n",
1410 &(((struct sockaddr_in *) &(rtent.rt_dst))->
1412 &(((struct sockaddr_in *) &(rtent.rt_gateway))->
1415 * XXX: fix type of the args
1417 &flags, &refcnt, &use, &metric,
1418 &(((struct sockaddr_in *) &(rtent.rt_genmask))->
1422 strncpy(name, rt->rt_dev, sizeof(name));
1423 name[ sizeof(name)-1 ] = 0;
1425 * linux says ``lo'', but the interface is stored as ``lo0'':
1427 if (!strcmp(name, "lo"))
1430 rt->rt_flags = flags, rt->rt_refcnt = refcnt;
1431 rt->rt_use = use, rt->rt_metric = metric;
1433 Interface_Scan_Init();
1434 while (Interface_Scan_Next
1435 ((short *) &rt->rt_unit, temp, NULL, NULL) != 0)
1436 if (strcmp(name, temp) == 0)
1440 * Allocate a block to hold it and add it to the database
1442 if (rtsize >= rtallocate) {
1443 rthead = (struct rtentry **) realloc((char *) rthead,
1445 sizeof(struct rtentry *));
1446 memset(&rthead[rtallocate], 0,
1447 rtallocate * sizeof(struct rtentry *));
1450 if (!rthead[rtsize])
1452 (struct rtentry *) malloc(sizeof(struct rtentry));
1454 * Add this to the database
1456 memcpy((char *) rthead[rtsize], (char *) rt,
1457 sizeof(struct rtentry));
1466 qsort((char *) rthead, rtsize, sizeof(rthead[0]), qsort_compare);
1475 * Create a host table
1479 qsort_compare(const void *v1, const void *v2)
1481 mib_ipRouteEnt * const *r1 = (mib_ipRouteEnt * const *) v1;
1482 mib_ipRouteEnt * const *r2 = (mib_ipRouteEnt * const *) v2;
1486 if ((*r1)->Dest == (*r2)->Dest)
1488 if ((*r1)->Dest > (*r2)->Dest)
1494 qsort_compare(const void *v1, const void *v2)
1496 RTENTRY * const *r1 = (RTENTRY * const *) v1;
1497 RTENTRY * const *r2 = (RTENTRY * const *) v2;
1499 register u_long dst1 =
1500 ntohl(klgetsa((const struct sockaddr_in *) (*r1)->rt_dst)->
1502 register u_long dst2 =
1503 ntohl(klgetsa((const struct sockaddr_in *) (*r2)->rt_dst)->
1506 register u_long dst1 =
1507 ntohl(((const struct sockaddr_in *) &((*r1)->rt_dst))->sin_addr.
1509 register u_long dst2 =
1510 ntohl(((const struct sockaddr_in *) &((*r2)->rt_dst))->sin_addr.
1512 #endif /* NEED_KLGETSA */
1524 #endif /* not USE_SYSCTL_ROUTE_DUMP */
1526 #endif /* solaris2 */
1529 #include <iphlpapi.h>
1530 #ifndef MIB_IPPROTO_NETMGMT
1531 #define MIB_IPPROTO_NETMGMT 3
1534 PMIB_IPFORWARDROW route_row;
1537 init_var_route(void)
1542 var_ipRouteEntry(struct variable *vp,
1545 int exact, size_t * var_len, WriteMethod ** write_method)
1548 * object identifier is of form:
1549 * 1.3.6.1.2.1.4.21.1.?.A.B.C.D, where A.B.C.D is IP address.
1550 * IPADDR starts at offset 10.
1552 register int Save_Valid, result, RtIndex;
1553 static int saveNameLen = 0, saveExact = 0, saveRtIndex =
1555 static oid saveName[MAX_OID_LEN], Current[MAX_OID_LEN];
1558 DWORD status = NO_ERROR;
1559 DWORD dwActualSize = 0;
1560 static PMIB_IPFORWARDTABLE pIpRtrTable = NULL;
1562 static long Time_Of_Last_Reload = 0;
1563 u_char dest_addr[4];
1564 MIB_IPFORWARDROW temp_row;
1568 ** this optimisation fails, if there is only a single route avail.
1569 ** it is a very special case, but better leave it out ...
1574 if (route_row == NULL) {
1576 * Free allocated memory in case of SET request's FREE phase
1578 route_row = (PMIB_IPFORWARDROW) malloc(sizeof(MIB_IPFORWARDROW));
1580 gettimeofday(&now, (struct timezone *) 0);
1581 if ((rtsize <= 1) || (Time_Of_Last_Reload + 5 <= now.tv_sec))
1587 * If the name was the same as the last name, with the possible
1588 * exception of the [9]th token, then don't read the routing table
1592 if ((saveNameLen == (int) *length) && (saveExact == exact)) {
1593 register int temp = name[9];
1596 (snmp_oid_compare(name, *length, saveName, saveNameLen) == 0);
1602 register int temp = name[9]; /* Fix up 'lowest' found entry */
1603 memcpy((char *) name, (char *) Current, 14 * sizeof(oid));
1606 RtIndex = saveRtIndex;
1609 * fill in object part of name for current(less sizeof instance part)
1612 memcpy((char *) Current, (char *) vp->name,
1613 (int) (vp->namelen) * sizeof(oid));
1616 if ((Time_Of_Last_Reload + 5 <= now.tv_sec)
1617 || (pIpRtrTable == NULL)) {
1618 if (pIpRtrTable != NULL)
1620 Time_Of_Last_Reload = now.tv_sec;
1622 * query for buffer size needed
1624 status = GetIpForwardTable(pIpRtrTable, &dwActualSize, TRUE);
1625 if (status == ERROR_INSUFFICIENT_BUFFER) {
1626 pIpRtrTable = (PMIB_IPFORWARDTABLE) malloc(dwActualSize);
1627 if (pIpRtrTable != NULL) {
1629 * Get the sorted IP Route Table
1632 GetIpForwardTable(pIpRtrTable, &dwActualSize,
1637 if (status == NO_ERROR) {
1638 rtsize = pIpRtrTable->dwNumEntries;
1639 for (RtIndex = 0; RtIndex < rtsize; RtIndex++) {
1640 cp = (u_char *) & pIpRtrTable->table[RtIndex].
1648 result = snmp_oid_compare(name, *length, Current, 14);
1649 if ((exact && (result == 0)) || (!exact && (result < 0)))
1653 if (RtIndex >= rtsize) {
1655 * for creation of new row, only ipNetToMediaTable case is considered
1657 if (*length == 14) {
1659 *write_method = write_rte;
1660 dest_addr[0] = (u_char) name[10];
1661 dest_addr[1] = (u_char) name[11];
1662 dest_addr[2] = (u_char) name[12];
1663 dest_addr[3] = (u_char) name[13];
1664 temp_row.dwForwardDest = *((DWORD *) dest_addr);
1665 temp_row.dwForwardPolicy = 0;
1666 temp_row.dwForwardProto = MIB_IPPROTO_NETMGMT;
1667 *route_row = temp_row;
1676 * Save in the 'cache'
1678 memcpy((char *) saveName, (char *) name,
1679 SNMP_MIN(*length, MAX_OID_LEN) * sizeof(oid));
1681 saveNameLen = *length;
1683 saveRtIndex = RtIndex;
1688 memcpy((char *) name, (char *) Current, 14 * sizeof(oid));
1691 *var_len = sizeof(long_return);
1692 *route_row = pIpRtrTable->table[RtIndex];
1694 switch (vp->magic) {
1696 *write_method = write_rte;
1697 long_return = pIpRtrTable->table[RtIndex].dwForwardDest;
1698 return (u_char *) & long_return;
1699 case IPROUTEIFINDEX:
1700 *write_method = write_rte;
1701 long_return = pIpRtrTable->table[RtIndex].dwForwardIfIndex;
1702 return (u_char *) & long_return;
1703 case IPROUTEMETRIC1:
1704 *write_method = write_rte;
1705 long_return = pIpRtrTable->table[RtIndex].dwForwardMetric1;
1706 return (u_char *) & long_return;
1707 case IPROUTEMETRIC2:
1708 *write_method = write_rte;
1709 long_return = pIpRtrTable->table[RtIndex].dwForwardMetric2;
1710 return (u_char *) & long_return;
1711 case IPROUTEMETRIC3:
1712 *write_method = write_rte;
1713 long_return = pIpRtrTable->table[RtIndex].dwForwardMetric3;
1714 return (u_char *) & long_return;
1715 case IPROUTEMETRIC4:
1716 *write_method = write_rte;
1717 long_return = pIpRtrTable->table[RtIndex].dwForwardMetric4;
1718 return (u_char *) & long_return;
1719 case IPROUTEMETRIC5:
1720 *write_method = write_rte;
1721 long_return = pIpRtrTable->table[RtIndex].dwForwardMetric5;
1722 return (u_char *) & long_return;
1723 case IPROUTENEXTHOP:
1724 *write_method = write_rte;
1725 long_return = pIpRtrTable->table[RtIndex].dwForwardNextHop;
1726 return (u_char *) & long_return;
1728 *write_method = write_rte;
1729 long_return = pIpRtrTable->table[RtIndex].dwForwardType;
1730 return (u_char *) & long_return;
1732 long_return = pIpRtrTable->table[RtIndex].dwForwardProto;
1733 return (u_char *) & long_return;
1735 *write_method = write_rte;
1736 long_return = pIpRtrTable->table[RtIndex].dwForwardAge;
1737 return (u_char *) & long_return;
1739 *write_method = write_rte;
1740 long_return = pIpRtrTable->table[RtIndex].dwForwardMask;
1741 return (u_char *) & long_return;
1743 *var_len = nullOidLen;
1744 return (u_char *) nullOid;
1746 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipRouteEntry\n",
1754 #else /* CAN_USE_SYSCTL */
1761 #include <sys/types.h>
1762 #include <sys/param.h>
1763 #include <sys/queue.h>
1764 #include <sys/socket.h>
1765 #include <sys/sysctl.h>
1767 #include <sys/time.h>
1770 #include <net/if_dl.h>
1771 #if HAVE_SYS_STREAM_H
1772 #include <sys/stream.h>
1774 #include <net/route.h>
1775 #include <netinet/in.h>
1777 #define CACHE_TIME (120) /* Seconds */
1779 #include <net-snmp/net-snmp-includes.h>
1780 #include <net-snmp/agent/net-snmp-agent-includes.h>
1784 #include "interfaces.h"
1786 #include "util_funcs.h"
1789 TAILQ_HEAD(, snmprt)
1792 static size_t rtbuflen;
1793 static time_t lasttime;
1796 TAILQ_ENTRY(snmprt) link;
1797 struct rt_msghdr *hdr;
1798 struct in_addr dest;
1799 struct in_addr gateway;
1800 struct in_addr netmask;
1806 rtmsg(struct rt_msghdr *rtm)
1809 struct sockaddr *sa;
1810 int bit, gotdest, gotmask;
1812 rt = malloc(sizeof *rt);
1817 rt->dest = rt->gateway = rt->netmask = rt->ifa;
1818 rt->index = rtm->rtm_index;
1820 gotdest = gotmask = 0;
1821 sa = (struct sockaddr *) (rtm + 1);
1822 for (bit = 1; ((char *) sa < (char *) rtm + rtm->rtm_msglen) && bit;
1824 if ((rtm->rtm_addrs & bit) == 0)
1828 #define satosin(sa) ((struct sockaddr_in *)(sa))
1829 rt->dest = satosin(sa)->sin_addr;
1833 if (sa->sa_family == AF_INET)
1834 rt->gateway = satosin(sa)->sin_addr;
1837 if (sa->sa_len >= offsetof(struct sockaddr_in, sin_addr))
1838 rt->netmask = satosin(sa)->sin_addr;
1842 if (sa->sa_family == AF_INET)
1843 rt->ifa = satosin(sa)->sin_addr;
1849 #define ROUNDUP(a) \
1850 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1851 sa = (struct sockaddr *) ((char *) sa + ROUNDUP(sa->sa_len));
1855 * XXX can't happen if code above is correct
1857 snmp_log(LOG_ERR, "route no dest?\n");
1861 * If no mask provided, it was a host route.
1864 rt->netmask.s_addr = ~0;
1865 TAILQ_INSERT_TAIL(&rthead, rt, link);
1873 struct snmprt *rt, *next;
1875 static int name[6] =
1876 { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0 };
1878 struct rt_msghdr *rtm;
1881 if (now < (lasttime + CACHE_TIME) && !force)
1885 for (rt = rthead.tqh_first; rt; rt = next) {
1886 next = rt->link.tqe_next;
1889 TAILQ_INIT(&rthead);
1891 if (sysctl(name, 6, 0, &len, 0, 0) < 0) {
1892 syslog(LOG_WARNING, "sysctl net-route-dump: %m");
1896 if (len > rtbuflen) {
1898 newbuf = realloc(rtbuf, len);
1905 if (sysctl(name, 6, rtbuf, &len, 0, 0) < 0) {
1906 syslog(LOG_WARNING, "sysctl net-route-dump: %m");
1911 while (cp < rtbuf + len) {
1912 rtm = (struct rt_msghdr *) cp;
1915 * You might want to exclude routes with RTF_WASCLONED
1916 * set. This keeps the cloned host routes (and thus also
1917 * ARP entries) out of the routing table. Thus, it also
1918 * presents management stations with an incomplete view.
1919 * I believe that it should be possible for a management
1920 * station to examine (and perhaps delete) such routes.
1922 if (rtm->rtm_version == RTM_VERSION && rtm->rtm_type == RTM_GET)
1924 cp += rtm->rtm_msglen;
1930 var_ipRouteEntry(struct variable * vp,
1933 int exact, size_t * var_len, WriteMethod ** write_method)
1936 * object identifier is of form:
1937 * 1.3.6.1.2.1.4.21.1.1.A.B.C.D, where A.B.C.D is IP address.
1938 * IPADDR starts at offset 10.
1940 int Save_Valid, result;
1944 static struct snmprt *savert;
1945 static int saveNameLen, saveExact;
1946 static oid saveName[14], Current[14];
1952 * If the name was the same as the last name, with the possible
1953 * exception of the [9]th token, then don't read the routing table
1957 if ((saveNameLen == *length) && (saveExact == exact)) {
1961 !snmp_oid_compare(name, *length, saveName, saveNameLen);
1972 memcpy(name, Current, 14 * sizeof(oid));
1978 * fill in object part of name for current
1979 * (less sizeof instance part)
1982 memcpy(Current, vp->name, SNMP_MIN(sizeof(Current), (int)(vp->namelen) * sizeof(oid)));
1986 for (rt = rthead.tqh_first; rt; rt = rt->link.tqe_next) {
1988 cp = (u_char *) & rt->dest;
1993 result = snmp_oid_compare(name, *length, Current, 14);
1994 if ((exact && (result == 0))
1995 || (!exact && (result < 0)))
2002 * Save in the 'cache'
2004 memcpy(saveName, name, SNMP_MIN(sizeof(saveName), *length * sizeof(oid)));
2006 saveNameLen = *length;
2013 memcpy(name, Current, 14 * sizeof(oid));
2017 *write_method = write_rte;
2018 *var_len = sizeof long_return;
2020 switch (vp->magic) {
2022 long_return = rt->dest.s_addr;
2023 return (u_char *) & long_return;
2025 case IPROUTEIFINDEX:
2026 long_return = rt->index;
2027 return (u_char *) & long_return;
2029 case IPROUTEMETRIC1:
2030 long_return = (rt->hdr->rtm_flags & RTF_GATEWAY) ? 1 : 0;
2031 return (u_char *) & long_return;
2032 case IPROUTEMETRIC2:
2033 long_return = rt->hdr->rtm_rmx.rmx_rtt;
2034 return (u_char *) & long_return;
2035 case IPROUTEMETRIC3:
2036 long_return = rt->hdr->rtm_rmx.rmx_rttvar;
2037 return (u_char *) & long_return;
2038 case IPROUTEMETRIC4:
2039 long_return = rt->hdr->rtm_rmx.rmx_ssthresh;
2040 return (u_char *) & long_return;
2041 case IPROUTEMETRIC5:
2042 long_return = rt->hdr->rtm_rmx.rmx_mtu;
2043 return (u_char *) & long_return;
2045 case IPROUTENEXTHOP:
2046 if (rt->gateway.s_addr == 0 && rt->ifa.s_addr == 0)
2048 else if (rt->gateway.s_addr == 0)
2049 long_return = rt->ifa.s_addr;
2051 long_return = rt->gateway.s_addr;
2052 return (u_char *) & long_return;
2055 if (rt->hdr->rtm_flags & RTF_UP) {
2056 if (rt->hdr->rtm_flags & RTF_GATEWAY) {
2057 long_return = 4; /* indirect(4) */
2059 long_return = 3; /* direct(3) */
2062 long_return = 2; /* invalid(2) */
2064 return (u_char *) & long_return;
2067 long_return = (rt->hdr->rtm_flags & RTF_DYNAMIC) ? 4 : 2;
2068 return (u_char *) & long_return;
2075 return (u_char *) & long_return;
2078 long_return = rt->netmask.s_addr;
2079 return (u_char *) & long_return;
2082 *var_len = nullOidLen;
2083 return (u_char *) nullOid;
2085 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipRouteEntry\n",
2092 init_var_route(void)
2097 #endif /* CAN_USE_SYSCTL */
2099 #if defined(HAVE_SYS_SYSCTL_H) && !defined(linux)
2103 * Traverse the address structures after a routing socket message and
2104 * extract a specific one.
2106 * Some of this is peculiar to IRIX 6.2, which doesn't have sa_len in
2107 * the sockaddr structure yet. With sa_len, skipping an address entry
2108 * would be much easier.
2113 * returns the length of a socket structure
2117 snmp_socket_length(int family)
2126 length = sizeof(struct sockaddr_un);
2128 #endif /* AF_UNIX */
2136 length = _MAX_SA_LEN;
2137 #elif SOCK_MAXADDRLEN
2138 length = SOCK_MAXADDRLEN;
2140 length = sizeof(struct sockaddr_dl);
2143 #endif /* AF_LINK */
2147 length = sizeof(struct sockaddr_in);
2150 length = sizeof(struct sockaddr);
2157 const struct sockaddr *
2158 get_address(const void *_ap, int addresses, int wanted)
2160 const struct sockaddr *ap = (const struct sockaddr *) _ap;
2164 for (iindex = 0, bitmask = 1;
2165 iindex < RTAX_MAX; ++iindex, bitmask <<= 1) {
2166 if (bitmask == wanted) {
2167 if (bitmask & addresses) {
2172 } else if (bitmask & addresses) {
2174 (unsigned) snmp_socket_length(ap->sa_family);
2175 while (length % sizeof(long) != 0)
2177 ap = (const struct sockaddr *) ((const char *) ap + length);
2186 * Convenience function for the special case of get_address where an
2187 * AF_INET address is desired, and we're only interested in the in_addr
2190 const struct in_addr *
2191 get_in_address(const void *ap, int addresses, int wanted)
2193 const struct sockaddr_in *a;
2195 a = (const struct sockaddr_in *) get_address(ap, addresses, wanted);
2199 if (a->sin_family != AF_INET) {
2200 DEBUGMSGTL(("snmpd",
2201 "unknown socket family %d [AF_INET expected] in var_ipRouteEntry.\n",
2204 return &a->sin_addr;
2206 #endif /* HAVE_SYS_SYSCTL_H */