route.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:13k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /* $OpenBSD: route.c,v 1.66 2004/11/17 01:47:20 itojun Exp $ */
  2. /* $NetBSD: route.c,v 1.15 1996/05/07 02:55:06 thorpej Exp $ */
  3. /*
  4.  * Copyright (c) 1983, 1988, 1993
  5.  * The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 3. Neither the name of the University nor the names of its contributors
  16.  *    may be used to endorse or promote products derived from this software
  17.  *    without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  20.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  23.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29.  * SUCH DAMAGE.
  30.  */
  31. #ifdef  INHERITED_CODE
  32. #ifndef lint
  33. #if 0
  34. static char sccsid[] = "from: @(#)route.c 8.3 (Berkeley) 3/9/94";
  35. #else
  36. static char *rcsid = "$OpenBSD: route.c,v 1.66 2004/11/17 01:47:20 itojun Exp $";
  37. #endif
  38. #endif /* not lint */
  39. #endif
  40. #include <net-snmp/net-snmp-config.h>
  41. #include <net-snmp/net-snmp-includes.h>
  42. #if HAVE_UNISTD_H
  43. #include <unistd.h>
  44. #endif
  45. #if HAVE_NETDB_H
  46. #include <netdb.h>
  47. #endif
  48. #ifndef INET
  49. #define INET
  50. #endif
  51. #include "main.h"
  52. #include "netstat.h"
  53. #define SET_MASK 0x01
  54. #define SET_GWAY 0x02
  55. #define SET_IFNO 0x04
  56. #define SET_TYPE 0x08
  57. #define SET_PRTO 0x10
  58. #define SET_ALL  0x1f
  59. struct route_entry {
  60.     oid             instance[4];
  61.     in_addr_t       destination;
  62.     in_addr_t       mask;
  63.     in_addr_t       gateway;
  64.     int             ifNumber;
  65.     int             type;
  66.     int             proto;
  67.     int             set_bits;
  68.     char            ifname[64];
  69. };
  70. void p_rtnode( struct route_entry *rp );
  71. extern int _ffs(int mask);
  72. /*
  73.  * Print routing tables.
  74.  */
  75. void
  76. routepr(void)
  77. {
  78.     struct route_entry  route, *rp = &route;
  79.     oid    rtcol_oid[]  = { 1,3,6,1,2,1,4,21,1,0 };
  80.     size_t rtcol_len    = OID_LENGTH( rtcol_oid );
  81.     union {
  82.         in_addr_t addr;
  83.         char      data[4];
  84.     } tmpAddr;
  85.     netsnmp_variable_list *var=NULL, *vp;
  86.     char  *cp;
  87.     
  88.     printf("Routing tablesn");
  89.     pr_rthdr(AF_INET);
  90. #define ADD_RTVAR( x ) rtcol_oid[ rtcol_len-1 ] = x; 
  91.     snmp_varlist_add_variable( &var, rtcol_oid, rtcol_len, ASN_NULL, NULL,  0)
  92.     ADD_RTVAR( 2 );                 /* ipRouteIfIndex */
  93.     ADD_RTVAR( 7 );                 /* ipRouteNextHop */
  94.     ADD_RTVAR( 8 );                 /* ipRouteType    */
  95.     ADD_RTVAR( 9 );                 /* ipRouteProto   */
  96.     ADD_RTVAR( 11 );                /* ipRouteMask    */
  97. #undef ADD_RTVAR
  98.         /*
  99.  * Now walk the ipRouteTable, reporting the various route entries
  100.  */
  101.     while ( 1 ) {
  102.         if (netsnmp_query_getnext( var, ss ) != SNMP_ERR_NOERROR)
  103.             break;
  104.         rtcol_oid[ rtcol_len-1 ] = 2; /* ifRouteIfIndex */
  105.         if ( snmp_oid_compare( rtcol_oid, rtcol_len,
  106.                                var->name, rtcol_len) != 0 )
  107.             break;    /* End of Table */
  108.         memset( &route, 0, sizeof( struct route_entry ));
  109.         /* Extract ipRouteDest index value */
  110.         cp = tmpAddr.data;
  111.         cp[0] = var->name[ 10 ] & 0xff;
  112.         cp[1] = var->name[ 11 ] & 0xff;
  113.         cp[2] = var->name[ 12 ] & 0xff;
  114.         cp[3] = var->name[ 13 ] & 0xff;
  115.         rp->destination = tmpAddr.addr;
  116.         for ( vp=var; vp; vp=vp->next_variable ) {
  117.             switch ( vp->name[ 9 ] ) {
  118.             case 2:     /* ifRouteIfIndex */
  119.                 rp->ifNumber  = *vp->val.integer;
  120.                 rp->set_bits |= SET_IFNO;
  121.                 break;
  122.             case 7:                 /* ipRouteNextHop */
  123.                 memmove(&rp->gateway, vp->val.string, 4);
  124.                 rp->set_bits |= SET_GWAY;
  125.                 break;
  126.             case 8:                 /* ipRouteType    */
  127.                 rp->type      = *vp->val.integer;
  128.                 rp->set_bits |= SET_TYPE;
  129.                 break;
  130.             case 9:                 /* ipRouteProto   */
  131.                 rp->proto     = *vp->val.integer;
  132.                 rp->set_bits |= SET_PRTO;
  133.                 break;
  134.             case 11:                /* ipRouteMask    */
  135.                 memmove(&rp->mask, vp->val.string, 4);
  136.                 rp->set_bits |= SET_MASK;
  137.                 break;
  138.             }
  139.         }
  140.         if (rp->set_bits != SET_ALL) {
  141.             continue;   /* Incomplete query */
  142.         }
  143.         p_rtnode( rp );
  144.     }
  145. }
  146. struct iflist {
  147.     int             index;
  148.     char            name[64];
  149.     struct iflist  *next;
  150. }              *Iflist = NULL;
  151. void
  152. get_ifname(char *name, int ifIndex)
  153. {
  154.     oid    ifdescr_oid[]  = { 1,3,6,1,2,1,2,2,1,2,0 };
  155.     size_t ifdescr_len    = OID_LENGTH( ifdescr_oid );
  156.     netsnmp_variable_list *var = NULL;
  157.     struct iflist         *ip;
  158.     for (ip = Iflist; ip; ip = ip->next) {
  159.         if (ip->index == ifIndex)
  160.             break;
  161.     }
  162.     if (ip) {
  163.         strcpy(name, ip->name);
  164.         return;
  165.     }
  166.     ip = (struct iflist *) malloc(sizeof(struct iflist));
  167.     if (ip == NULL)
  168.         return;
  169.     ip->next = Iflist;
  170.     Iflist = ip;
  171.     ip->index = ifIndex;
  172.     ifdescr_oid[ ifdescr_len-1 ] = ifIndex;
  173.     snmp_varlist_add_variable( &var, ifdescr_oid, ifdescr_len,
  174.                                ASN_NULL, NULL,  0);
  175.     if (netsnmp_query_get( var, ss ) == SNMP_ERR_NOERROR) {
  176.         if (var->val_len >= sizeof(ip->name))
  177.             var->val_len  = sizeof(ip->name) - 1;
  178.         memmove(ip->name, var->val.string, var->val_len);
  179.         ip->name[var->val_len] = '';
  180.     } else {
  181.         sprintf(ip->name, "if%d", ifIndex);
  182.     }
  183.     strcpy(name, ip->name);
  184. }
  185. /*
  186.  * Print address family header before a section of the routing table.
  187.  */
  188. void
  189. pr_family(int af)
  190. {
  191. const char *afname;
  192. switch (af) {
  193. case AF_INET:
  194. afname = "Internet";
  195. break;
  196. #ifdef INET6
  197. case AF_INET6:
  198. afname = "Internet6";
  199. break;
  200. #endif
  201.     /*
  202. case AF_NS:
  203. afname = "XNS";
  204. break;
  205. case AF_IPX:
  206. afname = "IPX";
  207. break;
  208. case AF_CCITT:
  209. afname = "X.25";
  210. break;
  211. case PF_KEY:
  212. afname = "Encap";
  213. break;
  214. case AF_APPLETALK:
  215. afname = "AppleTalk";
  216. break;
  217.      */
  218. default:
  219. afname = NULL;
  220. break;
  221. }
  222. if (afname)
  223. printf("n%s:n", afname);
  224. else
  225. printf("nProtocol Family %d:n", af);
  226. }
  227. /* column widths; each followed by one space */
  228. #ifndef INET6
  229. #define WID_DST(af) 26 /* width of destination column */
  230. #define WID_GW(af) 18 /* width of gateway column */
  231. #else
  232. /* width of destination/gateway column */
  233. #if 1
  234. /* strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4 */
  235. #define WID_DST(af) ((af) == AF_INET6 ? (nflag ? 34 : 26) : 26)
  236. #define WID_GW(af) ((af) == AF_INET6 ? (nflag ? 30 : 18) : 18)
  237. #else
  238. /* strlen("fe80::aaaa:bbbb:cccc:dddd") == 25, strlen("/128") == 4 */
  239. #define WID_DST(af) ((af) == AF_INET6 ? (nflag ? 29 : 18) : 18)
  240. #define WID_GW(af) ((af) == AF_INET6 ? (nflag ? 25 : 18) : 18)
  241. #endif
  242. #endif /* INET6 */
  243. /*
  244.  * Print header for routing table columns.
  245.  */
  246. void
  247. pr_rthdr(int af)
  248. {
  249.    /*
  250. if (Aflag)
  251. printf("%-*.*s ", PLEN, PLEN, "Address");
  252. if (Sflag)
  253. printf("%-*.*s ",
  254.     WID_DST(af), WID_DST(af), "Source");
  255.     */
  256. printf("%-*.*s ",
  257.     WID_DST(af), WID_DST(af), "Destination");
  258. printf("%-*.*s %-6.6s  %sn",
  259.     WID_GW(af), WID_GW(af), "Gateway",
  260.     "Flags", "Interface");
  261. }
  262. /*
  263.  * Print header for PF_KEY entries.
  264. void
  265. pr_encaphdr(void)
  266. {
  267. if (Aflag)
  268. printf("%-*s ", PLEN, "Address");
  269. printf("%-18s %-5s %-18s %-5s %-5s %-22sn",
  270.     "Source", "Port", "Destination",
  271.     "Port", "Proto", "SA(Address/Proto/Type/Direction)");
  272. }
  273.  */
  274. char *
  275. routename(in_addr_t in)
  276. {
  277. char *cp;
  278. static char line[MAXHOSTNAMELEN];
  279. struct hostent *hp;
  280. static char domain[MAXHOSTNAMELEN];
  281. static int first = 1;
  282. if (first) {
  283. first = 0;
  284. if (gethostname(domain, sizeof domain) == 0 &&
  285.     (cp = strchr(domain, '.')))
  286. (void) strlcpy(domain, cp + 1, sizeof domain);
  287. else
  288. domain[0] = '';
  289. }
  290. cp = NULL;
  291. if (!nflag) {
  292. hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
  293.     AF_INET);
  294. if (hp) {
  295. if ((cp = strchr(hp->h_name, '.')) &&
  296.     !strcmp(cp + 1, domain))
  297. *cp = '';
  298. cp = hp->h_name;
  299. }
  300. }
  301. if (cp) {
  302. strlcpy(line, cp, sizeof(line));
  303. } else {
  304. #define C(x) ((x) & 0xff)
  305. in = ntohl(in);
  306. snprintf(line, sizeof line, "%u.%u.%u.%u",
  307.     C(in >> 24), C(in >> 16), C(in >> 8), C(in));
  308. }
  309. return (line);
  310. }
  311. /*
  312.  * Return the name of the network whose address is given.
  313.  * The address is assumed to be that of a net or subnet, not a host.
  314.  */
  315. char *
  316. netname(in_addr_t in, in_addr_t mask)
  317. {
  318. char *cp = NULL;
  319. static char line[MAXHOSTNAMELEN];
  320. struct netent *np = NULL;
  321. int mbits;
  322. in = ntohl(in);
  323. mask = ntohl(mask);
  324. if (!nflag && in != INADDR_ANY) {
  325. if ((np = getnetbyaddr(in, AF_INET)) != NULL)
  326. cp = np->n_name;
  327. }
  328. mbits = mask ? 33 - _ffs(mask) : 0;
  329. if (cp) {
  330. strlcpy(line, cp, sizeof(line));
  331. } else if (mbits < 9)
  332. snprintf(line, sizeof line, "%u", C(in >> 24));
  333. else if (mbits < 17)
  334. snprintf(line, sizeof line, "%u.%u",
  335.     C(in >> 24) , C(in >> 16));
  336. else if (mbits < 25)
  337. snprintf(line, sizeof line, "%u.%u.%u",
  338.     C(in >> 24), C(in >> 16), C(in >> 8));
  339. else
  340. snprintf(line, sizeof line, "%u.%u.%u.%u", C(in >> 24),
  341.     C(in >> 16), C(in >> 8), C(in));
  342. return (line);
  343. }
  344. #undef INET6
  345. #ifdef INET6
  346. char *
  347. netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask)
  348. {
  349. static char line[MAXHOSTNAMELEN + 1];
  350. struct sockaddr_in6 sin6;
  351. u_char *p;
  352. u_char *lim;
  353. int masklen, final = 0, illegal = 0;
  354. int i;
  355. char hbuf[NI_MAXHOST];
  356. int flag = 0;
  357. int error;
  358. sin6 = *sa6;
  359. masklen = 0;
  360. lim = (u_char *)(mask + 1);
  361. i = 0;
  362. if (mask) {
  363. for (p = (u_char *)mask; p < lim; p++) {
  364. if (final && *p) {
  365. illegal++;
  366. sin6.sin6_addr.s6_addr[i++] = 0x00;
  367. continue;
  368. }
  369. switch (*p & 0xff) {
  370. case 0xff:
  371. masklen += 8;
  372. break;
  373. case 0xfe:
  374. masklen += 7;
  375. final++;
  376. break;
  377. case 0xfc:
  378. masklen += 6;
  379. final++;
  380. break;
  381. case 0xf8:
  382. masklen += 5;
  383. final++;
  384. break;
  385. case 0xf0:
  386. masklen += 4;
  387. final++;
  388. break;
  389. case 0xe0:
  390. masklen += 3;
  391. final++;
  392. break;
  393. case 0xc0:
  394. masklen += 2;
  395. final++;
  396. break;
  397. case 0x80:
  398. masklen += 1;
  399. final++;
  400. break;
  401. case 0x00:
  402. final++;
  403. break;
  404. default:
  405. final++;
  406. illegal++;
  407. break;
  408. }
  409. if (!illegal)
  410. sin6.sin6_addr.s6_addr[i++] &= *p;
  411. else
  412. sin6.sin6_addr.s6_addr[i++] = 0x00;
  413. }
  414. } else
  415. masklen = 128;
  416. if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr))
  417. return("default");
  418. if (illegal)
  419. fprintf(stderr, "illegal prefixlenn");
  420. if (nflag)
  421. flag |= NI_NUMERICHOST;
  422. error = getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
  423.     hbuf, sizeof(hbuf), NULL, 0, flag);
  424. if (error)
  425. snprintf(hbuf, sizeof(hbuf), "invalid");
  426. snprintf(line, sizeof(line), "%s/%d", hbuf, masklen);
  427. return line;
  428. }
  429. char *
  430. routename6(struct sockaddr_in6 *sa6)
  431. {
  432. static char line[NI_MAXHOST];
  433. const int niflag = NI_NUMERICHOST;
  434. if (getnameinfo((struct sockaddr *)sa6, sa6->sin6_len,
  435.     line, sizeof(line), NULL, 0, niflag) != 0)
  436. strlcpy(line, "", sizeof line);
  437. return line;
  438. }
  439. #endif /*INET6*/
  440. char *
  441. s_rtflags( struct route_entry *rp )
  442. {
  443.     static char flag_buf[10];
  444.     char  *cp = flag_buf;
  445.     memset( flag_buf, 0, sizeof(flag_buf));
  446.     *cp++ = 'U';   /* route is in use */
  447.     if (rp->mask  == 0xffffffff)
  448.         *cp++ = 'H';   /* host */
  449.     if (rp->proto == 4)
  450.         *cp++ = 'D';   /* ICMP redirect */
  451.     if (rp->type  == 4)
  452.         *cp++ = 'G';   /* remote destination/net */
  453.     return flag_buf;
  454. }
  455. void
  456. p_rtnode( struct route_entry *rp )
  457. {
  458.     get_ifname(rp->ifname, rp->ifNumber);
  459.     printf("%-*.*s ",
  460.     WID_DST(AF_INET), WID_DST(AF_INET),
  461.             (rp->destination == INADDR_ANY) ? "default" :
  462.                 (rp->set_bits & SET_MASK) ?
  463.                     (rp->mask == 0xffffffff ?
  464.                         routename(rp->destination) :
  465.                         netname(rp->destination, rp->mask)) :
  466.                     netname(rp->destination, 0L));
  467.     printf("%-*.*s %-6.6s  %sn",
  468.     WID_GW(af), WID_GW(af),
  469.                 routename(rp->gateway),
  470.             s_rtflags(rp), rp->ifname);
  471. }