⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 router.c

📁 一个学习SNMP项目:tmoerlan.
💻 C
字号:
/* snap-1.0. Copyright (C) 2000 by Jonathan T. Moore and Michael Hicks. * * router.c : reads the Linux routing table from /proc/net/route and *   implements a simple-minded routing lookup engine. Also, reads *   names of interfaces from /proc/net/dev. * * $Id: router.c,v 1.2 2003/09/17 11:26:10 tmoerlan Exp $ */#include <sys/types.h>#include <sys/sysctl.h>#include <assert.h>#include <sys/socket.h>#include <net/route.h>//#include <netinet/in_systm.h>#include <netinet/in.h>#include <net/if.h>#include <net/if_var.h>#include <net/if_mib.h>#include <string.h>#include "bytecode.h"#include "d_printf.h"#include "memalloc.h"#include "router.h"#include "proc.h"#define NIPQUAD(addr) \        ((unsigned char *)&(addr))[0], \        ((unsigned char *)&(addr))[1], \        ((unsigned char *)&(addr))[2], \        ((unsigned char *)&(addr))[3]static addr_t get_addr(char *addrstr) {  char buf[20];  addr_t addr = 0;    sprintf(buf,"0x%s",addrstr);  sscanf(buf,"%x",&addr);  return addr;}static void sprintf_addr(char *addrstr, addr_t addr) {  sprintf(addrstr,"%d.%d.%d.%d",NIPQUAD(addr));}#ifdef LINUX/* MWH---defined my own version of rtentry that uses addr_t's rather   than sockaddrs */struct rtentry {  addr_t rt_dst;		/* Target address. */  addr_t rt_gateway;		/* Gateway addr. */  addr_t rt_genmask;		/* Target network mask (IP). */  unsigned short int rt_flags;  short int rt_pad2;  unsigned long int rt_ifidx;	/* index of device used */  unsigned char rt_tos;  unsigned char rt_class;  short int rt_pad4;  short int rt_metric;                /* +1 for binary compatibility!  */  char *rt_dev;                       /* Forcing the device at add.  */  unsigned long int rt_mtu;           /* Per route MTU/Window.  */  unsigned long int rt_window;        /* Window clamping.  */  unsigned short int rt_irtt;         /* Initial RTT.  */};#endif/* route table */struct rtentry *routes = NULL;int num_rt_entries = 0;int num_routes = 0;/*  #define rt_ifidx rt_pad3 */struct sockaddr mask[5];/* interface table. right now we just track interface names */char **ifaces = NULL;int num_if_entries = 0;int num_ifaces = 0;/* get the interface number of the named interface */int get_iface_index(char *iface_name) {  int i;  assert(iface_name != NULL);  for(i = 0; i<num_ifaces; i++) {    if (strcmp(iface_name,ifaces[i]) == 0) {      return(i);    }  }  return(-1);}#ifndef LINUX/* iface_file is not used by this function */void read_ifaces(char *iface_file) {	struct ifmibdata ifmd;        int name[6];        size_t len;        len = sizeof(num_if_entries);        	name[0] = CTL_NET;	name[1] = PF_LINK;	name[2] = NETLINK_GENERIC;	name[3] = IFMIB_SYSTEM;	name[4] = IFMIB_IFCOUNT;        if (sysctl(name, 5, &num_if_entries, &len, (void *)0, 0) < 0)		d_printf(40, "sysctl error while getting ifcount\n");	num_ifaces = num_if_entries;	d_printf(40, "found %d interfaces\n", num_ifaces);		ifaces = (char **) malloc(sizeof(char *) * num_ifaces);        name[0] = CTL_NET;        name[1] = PF_LINK;        name[2] = NETLINK_GENERIC;        name[3] = IFMIB_IFDATA;        name[5] = IFDATA_GENERAL;        len = sizeof(ifmd);	int i;	for(i = 1; i <= num_ifaces; i++) {		name[4] = i;		if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) < 0)			d_printf(40, "sysctl error while getting ifname\n");		ifaces[i-1] = strdup(ifmd.ifmd_name);		d_printf(40, "%s\t", ifaces[i-1]);	}	d_printf(40, "\n");}	#else/* read interface names in out of /proc/net/dev */void read_ifaces(char *iface_file) {  char buf[2048];  FILE *f;  int num_ifs;  char **curr_if;  char iface[256];  f = fopen("/compat/linux/proc/net/dev"/*iface_file*/,"r");  if (f == NULL) {    fprintf(stderr,"%s:%d: unable to open %s\n",	    __FILE__,__LINE__,iface_file);    fflush(stderr);    exit(1);  }  num_ifs = 0;  /* count number of interfaces */  while(fgets(buf,sizeof(buf),f)) {    num_ifs++;  }  num_ifs -= 2;			/* strip off title lines */  d_printf(40,"%s:%d: reading %d interfaces\n",__FILE__,__LINE__,num_ifs);  /* make room in the interface table */  if (num_ifs > num_if_entries) {    if (ifaces != NULL) {      free(ifaces);    }    memalloc(ifaces,char **,sizeof(char *) * num_ifs);    num_if_entries = num_ifs;  }  /* now read in the interface names */  rewind(f);  fgets(buf,sizeof(buf)-1,f);	/* strip off 2 title lines */  fgets(buf,sizeof(buf)-1,f);  curr_if = &ifaces[0];  while(fgets(buf,sizeof(buf)-1,f)) {    int _sscanf_retval = 0;    char *cp = NULL;    assert(curr_if >= &ifaces[0]);    assert(curr_if < &ifaces[num_ifs]);    _sscanf_retval = sscanf(buf,"%s",iface);    if (_sscanf_retval < 1) {      fprintf(stderr,              "Warning: scanf (%d) failed on bogus iface entry |%s|\n",              _sscanf_retval, buf);      continue;    }    /* strip the : */    cp = &iface[0];    while(*cp != '\0' && *cp != ':')      cp++;    *cp = '\0';    d_printf(40,"%s:%d: found interface %d = %s\n",	     __FILE__,__LINE__,(curr_if - ifaces),iface);    *curr_if = strdup(iface);    curr_if++;  }  num_ifaces = curr_if - ifaces;    return;}#endif#ifndef LINUX#define ROUNDUP(a) \	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))voidroute_ParseHdr(struct rt_msghdr *rtm, struct sockaddr *sa[RTAX_MAX]){  char *wp;  int rtax;  wp = (char *)(rtm + 1);  for (rtax = 0; rtax < RTAX_MAX; rtax++)    if (rtm->rtm_addrs & (1 << rtax)) {      sa[rtax] = (struct sockaddr *)wp;      wp += ROUNDUP(sa[rtax]->sa_len);      if (sa[rtax]->sa_family == 0)        sa[rtax] = NULL;	/* ??? */    } else      sa[rtax] = NULL;}/* route_file is not used anymore */void read_routes(char *route_file) {	int mib[] = { CTL_NET, PF_ROUTE,0,0,NET_RT_DUMP, 0 };	size_t len;	static void *p;	void *q;	int nr = 0;	memset(mask, 0, 4 * sizeof(struct sockaddr));	mask[0].sa_len = 16;	memset(mask[0].sa_data, 0xff, 1);	mask[1].sa_len = 16;        memset(mask[1].sa_data, 0xff, 2);	mask[2].sa_len = 16;        memset(mask[2].sa_data, 0xff, 3);	mask[3].sa_len = 16;        memset(mask[3].sa_data, 0xff, 4);	mask[4].sa_len = 16;	memset(mask[4].sa_data, 0, 4);	if (p != NULL)		free(p);	sysctl(mib,sizeof(mib)/sizeof(int),NULL,&len,NULL,0);	p = malloc(len);	sysctl(mib,sizeof(mib)/sizeof(int),p,&len,NULL,0);	for(q=p; q<p+len;) {	 	        struct rt_msghdr *rtmsg = (struct rt_msghdr *) q;			nr++;			q += rtmsg->rtm_msglen;	};	d_printf(45, "found %d routetable entries\n", nr);	if (nr > num_rt_entries) {		d_printf(45, "alloc'ing mem\n");		if (routes != NULL)			free(routes);		routes = malloc(sizeof(struct rtentry) * nr);		if (routes == NULL)			d_printf(45, "ERROR: not enough mem for routing table\n");		num_rt_entries = nr;	}	nr = 0;	d_printf(45, "pointer p = %p\n", p);	for(q=p; q<p+len;) {                        struct rt_msghdr *rtmsg = (struct rt_msghdr *) q;			struct sockaddr *sa[RTAX_MAX];        		struct rtentry *current_rt = &routes[nr];//			d_printf(45, "routes addr = %p, current_rt = %p\n", routes, current_rt);//			d_printf(45, "rt_msghdr %d: %d extra bytes\n", nr, rtmsg->rtm_msglen - sizeof(struct rt_msghdr));			route_ParseHdr(rtmsg, sa);			if (sa[RTAX_GATEWAY]) {				/* take only the internet routes */				if (sa[RTAX_GATEWAY]->sa_family != AF_INET) {					q += rtmsg->rtm_msglen;					continue;				}                                d_printf(45, "gateway %d.%d.%d.%d\t ", NIPQUAD(sa[RTAX_GATEWAY]->sa_data[2]));				current_rt->rt_gateway = sa[RTAX_GATEWAY];			}			if (sa[RTAX_DST]) {                                d_printf(45, "dst %d.%d.%d.%d (%d)\t ", NIPQUAD(sa[RTAX_DST]->sa_data[2]), sa[RTAX_DST]->sa_len);                                rt_key(current_rt) = sa[RTAX_DST]; //, sa[RTAX_DST], sizeof(struct sockaddr));	                }/*			if (sa[RTAX_NETMASK]) {                                d_printf(45, "netmask %d.%d.%d.%d\n ", NIPQUAD(sa[RTAX_NETMASK]->sa_data));//				rt_mask(current_rt) = sa[RTAX_NETMASK];//				d_printf(45, "netmask sa ptr = %p\n", rt_mask(current_rt));//				d_printf(45, "maskptr = %p\n", rt_mask(current_rt)->sa_data);//				d_printf(45, "mask = %d.%d.%d.%d\n", NIPQUAD(*(rt_mask(current_rt)->sa_data)));//				rt_mask(current_rt) = (struct sockaddr *) 1;			}			else*/			{				unsigned int *m = (unsigned int *) &sa[RTAX_DST]->sa_data[2];				if ((*m & 0xffffffff) == 0) {//default entry, set mask to 0.0.0.0 to autoselect the of default								//we'll take the route entry with greatest netmask in nexthop anyway					rt_mask(current_rt) = &mask[4];				}				else if ((*m & 0xffffff00) == 0)					rt_mask(current_rt) = &mask[0];				else if ((*m & 0xffff0000) == 0)                                        rt_mask(current_rt) = &mask[1];				else if ((*m & 0xff000000) == 0)                                        rt_mask(current_rt) = &mask[2];				else {					rt_mask(current_rt) = &mask[3];				}				d_printf(45, "created netmask %d.%d.%d.%d\n", NIPQUAD(*(rt_mask(current_rt)->sa_data)));			}			if (sa[RTAX_GENMASK]) {                                d_printf(45, "genmask %d.%d.%d.%d\t ", NIPQUAD(sa[RTAX_GENMASK]->sa_data));				current_rt->rt_genmask = sa[RTAX_GENMASK];			}			current_rt->rt_ifp = malloc(sizeof(struct ifnet));			current_rt->rt_ifp->if_index = rtmsg->rtm_index;//			d_printf(45, "iface index=%d\n", rtmsg->rtm_index);			nr++;                                        q += rtmsg->rtm_msglen;        };	num_routes = nr;	d_printf(45, "%d INET routes among them\n", nr);}/* looks up the next hop to the given destination address. On success,   fill in the results in retval, and return 0. On failure, return -1. */extern int nexthop(addr_t dstaddr, struct rt_lookup *retval) {  int i;  unsigned int found_gw = 0;  unsigned int found_index = 0;  unsigned int found_netmask = 0x0;  assert(retval != NULL);  assert(routes != NULL);  d_printf(16, "nexthop!\n");//  print_anti_timer(16,"nexthop");  for(i=0; i<num_routes; i++) {    struct rtentry *rt = &routes[i];#if LINUX    unsigned int *gw = (unsigned int *)&(rt->rt_gateway.sa_data);    unsigned int *dest_net = (unsigned int *)&(rt->rt_dst.sa_data);    unsigned int *mask = (unsigned int *)&(rt->rt_genmask.sa_data);#else    unsigned int *gw = (unsigned int *)(&rt->rt_gateway->sa_data[2]);    unsigned int *dest_net = (unsigned int *)(&rt_key(rt)->sa_data[2]);    unsigned int *mask = (unsigned int *)(rt_mask(rt)->sa_data);    unsigned short if_index = rt->rt_ifp->if_index;#endif    d_printf(16, "%d.%d.%d.%d & %d.%d.%d.%d ?= %d.%d.%d.%d : %d\n", NIPQUAD(dstaddr), NIPQUAD(*mask), NIPQUAD(*dest_net),		(dstaddr & *mask) == *dest_net ? 1 : 0);    if ((dstaddr & *mask) == *dest_net) {      d_printf(16, "found a gw!\n");      if (*mask >= found_netmask) {		//we found a higher precision route entry (mask is bigger)		found_netmask = *mask;		found_gw = *gw;		found_index = if_index;      }    }  } //for...  if (found_gw > 0) {      retval->hopaddr = (addr_t) found_gw;      retval->ifidx = found_index;      d_printf(16, "nexthop returning for dest %d.%d.%d.%d --> gw %d.%d.%d.%d, iface %s (%d)\n",		NIPQUAD(dstaddr), NIPQUAD(retval->hopaddr), ifaces[retval->ifidx-1], retval->ifidx);      return(0);  }  else {	d_printf(16, "nexthop: no gateway found in routing table for dest %d.%d.%d.%d\n", NIPQUAD(dstaddr));  }//  print_timer(16,"nexthop");  return(-1);}#else/* read routing table out of /proc/net/route */void read_routes(char *route_file) {  char buf[1024];  FILE *f;  int nr;  struct rtentry *curr_rt;  char *fmt;  char addrstr1[22],addrstr2[22],addrstr3[22];  char iface[16];  addr_t mask, dest_addr, gw_addr;  unsigned int flags,refcnt,use,metric,mtu,window,irtt;    f = fopen(route_file,"r");  if (f == NULL) {    fprintf(stderr,"%s:%d: unable to open %s\n",	    __FILE__,__LINE__,route_file);    exit(1);  }  nr = 0;  /* count number of routes */  while(fgets(buf,sizeof(buf),f)) {    nr++;  }  nr--;				/* strip off title line */  d_printf(40,"%s:%d: reading %d routes\n",__FILE__,__LINE__,nr);	      /* do we have enough room in the routing table? */  if (nr > num_rt_entries) {    if (routes != NULL) {      free(routes);    }    memalloc(routes,struct rtentry *,sizeof(struct rtentry) * nr);    num_rt_entries = nr;  }  /* now read in the routes */  rewind(f);  fmt = proc_gen_fmt(route_file, f,		     "Iface", "%16s",		     "Destination", "%s",		     "Gateway", "%s",		     "Flags", "%X",		     "RefCnt", "%d",		     "Use", "%d",		     "Metric", "%d",		     "Mask", "%s",		     "MTU", "%d",		     "Window", "%d",		     "IRTT", "%d",		     NULL);  if (fmt == NULL) {    fprintf(stderr,"%s:%d: did not get format for reading %s\n",__FILE__,	    __LINE__,route_file);    exit(1);  }  curr_rt = routes;  while(fgets(buf,sizeof(buf)-1,f)) {    int ifidx;    assert(curr_rt >= &routes[0]);    assert(curr_rt < &routes[nr]);     if (sscanf(buf,fmt,	       iface,addrstr1,addrstr2,&flags,&refcnt,&use,	       &metric,addrstr3,&mtu,&window,&irtt) < 11) {      fprintf(stderr,"Warning: scanf failed on bogus tab entry |%s|\n",buf);      continue;    }    /* read the addresses */    dest_addr = get_addr(addrstr1);    gw_addr = get_addr(addrstr2);    mask = get_addr(addrstr3);    ifidx = if_nametoindex(iface);    if (ifidx == -1) {		/* unknown interface! */      fprintf(stderr,"Warning: unknown iface |%s| in tab entry |%s|\n",              iface,buf);      continue;    }    sprintf_addr(addrstr1,dest_addr);    sprintf_addr(addrstr2,gw_addr);    sprintf_addr(addrstr3,mask);    d_printf(45,"%s:%d: route : dst = %s, gw = %s, mask = %s, ifidx = %d (%s)\n",	     __FILE__,__LINE__,addrstr1,addrstr2,addrstr3,	     ifidx,iface);    curr_rt->rt_ifidx = ifidx;    curr_rt->rt_dst = dest_addr;    curr_rt->rt_gateway = gw_addr;    curr_rt->rt_genmask = mask;    curr_rt->rt_flags = (unsigned short int)flags;    curr_rt->rt_metric = (short int)metric;    curr_rt->rt_mtu = (unsigned long int)mtu;    curr_rt->rt_window = (unsigned long int)window;    curr_rt->rt_irtt = (unsigned short int)irtt;    curr_rt++;  }  num_routes = curr_rt - routes;}/* looks up the next hop to the given destination address. On success,   fill in the results in retval, and return 0. On failure, return -1. */extern int nexthop(addr_t dstaddr, struct rt_lookup *retval) {  int i;  assert(retval != NULL);  print_anti_timer(16,"nexthop");  for(i=0; i<num_routes; i++) {    struct rtentry *rt = &routes[i];    addr_t dest_net = rt->rt_dst;    addr_t gw = rt->rt_gateway;    addr_t mask = rt->rt_genmask;    if ((dstaddr & mask) == dest_net) {      print_timer(16,"nexthop");      if (gw == 0) {	retval->hopaddr = dstaddr;      } else {	retval->hopaddr = gw;      }      retval->ifidx = rt->rt_ifidx;      return(0);    }  }  print_timer(16,"nexthop");  return(-1);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -