📄 var_route.c
字号:
*/ memcpy( (char *)rthead[rtsize],(char *)rt, sizeof(RTENTRY)); rtsize++; } } free(routehash); } /* * Sort it! */ qsort((char *)rthead,rtsize,sizeof(rthead[0]),#ifdef __STDC__ (int (*)(const void *, const void *)) qsort_compare#else qsort_compare#endif );}#else#ifdef linuxstatic void Route_Scan_Reload (void){ FILE *in; char line [256]; struct rtentry *rt; char name[16], temp[16]; static int Time_Of_Last_Reload=0; struct timeval now; /* allow 20 seconds in cache: */ gettimeofday(&now, (struct timezone *)0); if (Time_Of_Last_Reload + 20 > now.tv_sec) return; Time_Of_Last_Reload = now.tv_sec; /* * Makes sure we have SOME space allocated for new routing entries */ if (! rthead) { rthead = (struct rtentry **) calloc(100, sizeof(struct rtentry *)); if (! rthead) { snmp_log(LOG_ERR,"route table malloc fail\n"); return; } rtallocate = 100; } /* * fetch routes from the proc file-system: */ rtsize = 0; if (! (in = fopen ("/proc/net/route", "r"))) { snmp_log(LOG_ERR, "cannot open /proc/net/route - burps\n"); return; } while (fgets (line, sizeof(line), in)) { struct rtentry rtent; char rtent_name [32]; int refcnt, flags, metric; unsigned use; rt = &rtent; memset ((char *) rt,(0), sizeof(*rt)); rt->rt_dev = rtent_name; /* * as with 1.99.14: * Iface Dest GW Flags RefCnt Use Metric Mask MTU Win IRTT * eth0 0A0A0A0A 00000000 05 0 0 0 FFFFFFFF 1500 0 0 */ if (8 != sscanf (line, "%s %x %x %x %u %d %d %x %*d %*d %*d\n", rt->rt_dev, &(((struct sockaddr_in *) &(rtent.rt_dst))->sin_addr.s_addr), &(((struct sockaddr_in *) &(rtent.rt_gateway))->sin_addr.s_addr),/* XXX: fix type of the args */ &flags, &refcnt, &use, &metric, &(((struct sockaddr_in *) &(rtent.rt_genmask))->sin_addr.s_addr))) continue; strcpy (name, rt->rt_dev); /* linux says ``lo'', but the interface is stored as ``lo0'': */ if (! strcmp (name, "lo")) strcat (name, "0"); name[15] = '\0'; rt->rt_flags = flags, rt->rt_refcnt = refcnt; rt->rt_use = use, rt->rt_metric = metric; Interface_Scan_Init(); while (Interface_Scan_Next((short *)&rt->rt_unit, temp, NULL, NULL) != 0) if (strcmp(name, temp) == 0) break; /* * Allocate a block to hold it and add it to the database */ if (rtsize >= rtallocate) { rthead = (struct rtentry **) realloc((char *)rthead, 2 * rtallocate * sizeof(struct rtentry *)); memset(&rthead[rtallocate], 0, rtallocate * sizeof(struct rtentry *)); rtallocate *= 2; } if (! rthead[rtsize]) rthead[rtsize] = (struct rtentry *) malloc(sizeof(struct rtentry)); /* * Add this to the database */ memcpy( (char *)rthead[rtsize],(char *)rt, sizeof(struct rtentry)); rtsize++; } fclose (in); /* * Sort it! */ qsort((char *)rthead,rtsize,sizeof(rthead[0]),#ifdef __STDC__ (int (*)(const void *, const void *)) qsort_compare#else qsort_compare#endif );}#endif#endif#endif#ifndef solaris2/* * Create a host table */static int qsort_compare(RTENTRY **r1, RTENTRY **r2){#if NEED_KLGETSA register u_long dst1 = ntohl(klgetsa((struct sockaddr_in *)(*r1)->rt_dst)->sin_addr.s_addr); register u_long dst2 = ntohl(klgetsa((struct sockaddr_in *)(*r2)->rt_dst)->sin_addr.s_addr);#else register u_long dst1 = ntohl(((struct sockaddr_in *) &((*r1)->rt_dst))->sin_addr.s_addr); register u_long dst2 = ntohl(((struct sockaddr_in *) &((*r2)->rt_dst))->sin_addr.s_addr);#endif /* NEED_KLGETSA */ /* * Do the comparison */ if (dst1 == dst2) return(0); if (dst1 > dst2) return(1); return(-1);}#endif /* not USE_SYSCTL_ROUTE_DUMP */#endif /* solaris2 */#else /* CAN_USE_SYSCTL */#include <stddef.h>#include <stdlib.h>#include <syslog.h>#include <time.h>#include <sys/types.h>#include <sys/param.h>#include <sys/queue.h>#include <sys/socket.h>#include <sys/sysctl.h>#if HAVE_SYS_TIME_H#include <sys/time.h>#endif#include <net/if_dl.h>#if HAVE_SYS_STREAM_H#include <sys/stream.h>#endif#include <net/route.h>#include <netinet/in.h>#define CACHE_TIME (120) /* Seconds */#include "asn1.h"#include "snmp_api.h"#include "snmp_impl.h"#include "mib.h"#include "snmp.h"#include "../snmp_vars.h"#include "ip.h"#include "../kernel.h"#include "interfaces.h"#include "struct.h"#include "util_funcs.h"#include "snmp_logging.h"#include "snmp_debug.h"static TAILQ_HEAD(, snmprt) rthead;static char *rtbuf;static size_t rtbuflen;static time_t lasttime;struct snmprt { TAILQ_ENTRY(snmprt) link; struct rt_msghdr *hdr; struct in_addr dest; struct in_addr gateway; struct in_addr netmask; int index; struct in_addr ifa;};static voidrtmsg(struct rt_msghdr *rtm){ struct snmprt *rt; struct sockaddr *sa; int bit, gotdest, gotmask; rt = malloc(sizeof *rt); if (rt == 0) return; rt->hdr = rtm; rt->ifa.s_addr = 0; rt->dest = rt->gateway = rt->netmask = rt->ifa; rt->index = rtm->rtm_index; gotdest = gotmask = 0; sa = (struct sockaddr *)(rtm + 1); for (bit = 1; ((char *)sa < (char *)rtm + rtm->rtm_msglen) && bit; bit <<= 1) { if ((rtm->rtm_addrs & bit) == 0) continue; switch (bit) { case RTA_DST:#define satosin(sa) ((struct sockaddr_in *)(sa)) rt->dest = satosin(sa)->sin_addr; gotdest = 1; break; case RTA_GATEWAY: if (sa->sa_family == AF_INET) rt->gateway = satosin(sa)->sin_addr; break; case RTA_NETMASK: if (sa->sa_len >= offsetof(struct sockaddr_in, sin_addr)) rt->netmask = satosin(sa)->sin_addr; gotmask = 1; break; case RTA_IFA: if (sa->sa_family == AF_INET) rt->ifa = satosin(sa)->sin_addr; break; }/* from rtsock.c */#define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len)); } if (!gotdest) { /* XXX can't happen if code above is correct */ snmp_log(LOG_ERR, "route no dest?\n"); free(rt); } else { /* If no mask provided, it was a host route. */ if (!gotmask) rt->netmask.s_addr = ~0; TAILQ_INSERT_TAIL(&rthead, rt, link); }}static intsuck_krt(int force){ time_t now; struct snmprt *rt, *next; size_t len; static int name[6] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0 }; char *cp; struct rt_msghdr *rtm; time(&now); if (now < (lasttime + CACHE_TIME) && !force) return 0; lasttime = now; for (rt = rthead.tqh_first; rt; rt = next) { next = rt->link.tqe_next; free(rt); } TAILQ_INIT(&rthead); if (sysctl(name, 6, 0, &len, 0, 0) < 0) { syslog(LOG_WARNING, "sysctl net-route-dump: %m"); return -1; } if (len > rtbuflen) { char *newbuf; newbuf = realloc(rtbuf, len); if (newbuf == 0) return -1; rtbuf = newbuf; rtbuflen = len; } if (sysctl(name, 6, rtbuf, &len, 0, 0) < 0) { syslog(LOG_WARNING, "sysctl net-route-dump: %m"); return -1; } cp = rtbuf; while (cp < rtbuf + len) { rtm = (struct rt_msghdr *)cp; /* * NB: * You might want to exclude routes with RTF_WASCLONED * set. This keeps the cloned host routes (and thus also * ARP entries) out of the routing table. Thus, it also * presents management stations with an incomplete view. * I believe that it should be possible for a management * station to examine (and perhaps delete) such routes. */ if (rtm->rtm_version == RTM_VERSION && rtm->rtm_type == RTM_GET) rtmsg(rtm); cp += rtm->rtm_msglen; } return 0;}u_char *var_ipRouteEntry(struct variable *vp, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method){ /* * object identifier is of form: * 1.3.6.1.2.1.4.21.1.1.A.B.C.D, where A.B.C.D is IP address. * IPADDR starts at offset 10. */ int Save_Valid, result; u_char *cp; oid *op; struct snmprt *rt; static struct snmprt *savert; static int saveNameLen, saveExact; static oid saveName[14], Current[14];#if 0 /* * OPTIMIZATION: * * If the name was the same as the last name, with the possible * exception of the [9]th token, then don't read the routing table * */ if ((saveNameLen == *length) && (saveExact == exact)) { int temp = name[9]; name[9] = 0; Save_Valid = !snmp_oid_compare(name, *length, saveName, saveNameLen); name[9] = temp; } else { Save_Valid = 0; }#else Save_Valid = 0;#endif if (Save_Valid) { int temp = name[9]; memcpy(name, Current, 14 * sizeof(oid)); name[9] = temp; *length = 14; rt = savert; } else { /* fill in object part of name for current (less sizeof instance part) */ memcpy(Current, vp->name, (int)(vp->namelen) * sizeof(oid)); suck_krt(0); for (rt = rthead.tqh_first; rt; rt = rt->link.tqe_next) { op = Current + 10; cp = (u_char *)&rt->dest; *op++ = *cp++; *op++ = *cp++; *op++ = *cp++; *op++ = *cp++; result = snmp_oid_compare(name, *length, Current, 14); if ((exact && (result == 0)) || (!exact && (result < 0))) break; } if (rt == NULL) return NULL; /* * Save in the 'cache' */ memcpy(saveName, name, *length * sizeof(oid)); saveName[9] = 0; saveNameLen = *length; saveExact = exact; savert = rt; /* * Return the name */ memcpy(name, Current, 14 * sizeof(oid)); *length = 14; } *write_method = write_rte; *var_len = sizeof long_return; switch (vp->magic) { case IPROUTEDEST: long_return = rt->dest.s_addr; return (u_char *)&long_return; case IPROUTEIFINDEX: long_return = rt->index; return (u_char *)&long_return; case IPROUTEMETRIC1: long_return = (rt->hdr->rtm_flags & RTF_GATEWAY) ? 1 : 0; return (u_char *)&long_return; case IPROUTEMETRIC2: long_return = rt->hdr->rtm_rmx.rmx_rtt; return (u_char *)&long_return; case IPROUTEMETRIC3: long_return = rt->hdr->rtm_rmx.rmx_rttvar; return (u_char *)&long_return; case IPROUTEMETRIC4: long_return = rt->hdr->rtm_rmx.rmx_ssthresh; return (u_char *)&long_return; case IPROUTEMETRIC5: long_return = rt->hdr->rtm_rmx.rmx_mtu; return (u_char *)&long_return; case IPROUTENEXTHOP: if (rt->gateway.s_addr == 0 && rt->ifa.s_addr == 0) long_return = 0; else if (rt->gateway.s_addr == 0) long_return = rt->ifa.s_addr; else long_return = rt->gateway.s_addr; return (u_char *)&long_return; case IPROUTETYPE: long_return = (rt->hdr->rtm_flags & RTF_GATEWAY) ? 4 : 3; return (u_char *)&long_return; case IPROUTEPROTO: long_return = (rt->hdr->rtm_flags & RTF_DYNAMIC) ? 4 : 2; return (u_char *)&long_return; case IPROUTEAGE:#if NO_DUMMY_VALUES return NULL;#endif long_return = 0; return (u_char *)&long_return; case IPROUTEMASK: long_return = rt->netmask.s_addr; return (u_char *)&long_return; case IPROUTEINFO: *var_len = nullOidLen; return (u_char *)nullOid; default: DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_ipRouteEntry\n", vp->magic)); } return NULL;}voidinit_var_route(void){ ;}#endif /* CAN_USE_SYSCTL */#if defined(HAVE_SYS_SYSCTL_H) && !defined(linux)/* get_address() Traverse the address structures after a routing socket message and extract a specific one. Some of this is peculiar to IRIX 6.2, which doesn't have sa_len in the sockaddr structure yet. With sa_len, skipping an address entry would be much easier. */#include <sys/un.h>const struct sockaddr *get_address (const void * _ap, int addresses, int wanted){ const struct sockaddr *ap = (const struct sockaddr *) _ap; int iindex; int bitmask; for (iindex = 0, bitmask = 1; iindex < RTAX_MAX; ++iindex, bitmask <<= 1) { if (bitmask == wanted) { if (bitmask & addresses) { return ap; } else { return 0; } } else if (bitmask & addresses) { unsigned length = (unsigned)snmp_socket_length(ap->sa_family); while (length % sizeof (long) != 0) ++length; ap = (const struct sockaddr *) ((const char *) ap + length); } } return 0;}/* get_in_address() Convenience function for the special case of get_address where an AF_INET address is desired, and we're only interested in the in_addr part. */const struct in_addr *get_in_address (const void * ap, int addresses, int wanted){ const struct sockaddr_in * a; a = (const struct sockaddr_in *)get_address (ap, addresses, wanted); if (a == NULL) return NULL; if (a->sin_family != AF_INET) { DEBUGMSGTL(("snmpd", "unknown socket family %d [AF_INET expected] in var_ipRouteEntry.\n", a->sin_family)); } return &a->sin_addr;}#endif /* HAVE_SYS_SYSCTL_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -