[insert project logo here (125x200px max)]

Navigator

Mailinglists

Please report any errors or ommissions you find to our `Help' mailinglist, or post a message in the Forums.

Copyright and Licensing Information

Snap is (c) Jonathan T. Moore, 1999-2002 and licensed under the GNU General Public License (GPL).

All other parts of Splash are (c) Willem de Bruijn, 2002-2003 and licensed under the BSD Open Source License.

All sourcecode is made publicly available.

Acknowledgement

Splash and the Splash website are hosted by SourceForge.net

SourceForge.net Logo

osi-open source certified logo

Splash - Documentation

SNMP Plus a Lightweight API for SNAP Handling

Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

snap-1.1-wjdb/lib/router.c

Go to the documentation of this file.
00001 /* snap-1.0. Copyright (C) 2000 by Jonathan T. Moore and Michael Hicks.
00002  *
00003  * router.c : reads the Linux routing table from /proc/net/route and
00004  *   implements a simple-minded routing lookup engine. Also, reads
00005  *   names of interfaces from /proc/net/dev.
00006  *
00007  * $Id: router.c,v 1.2 2002/12/10 18:51:49 wdebruij Exp $
00008  */
00009 
00010 #include <assert.h>
00011 /*  #include <net/route.h> */
00012 #include <netinet/in.h>
00013 #include <net/if.h>
00014 #include <string.h>
00015 #include "bytecode.h"
00016 #include "d_printf.h"
00017 #include "memalloc.h"
00018 #include "router.h"
00019 #include "proc.h"
00020 
00021 #define NIPQUAD(addr) \
00022         ((unsigned char *)&(addr))[0], \
00023         ((unsigned char *)&(addr))[1], \
00024         ((unsigned char *)&(addr))[2], \
00025         ((unsigned char *)&(addr))[3]
00026 
00027 static addr_t get_addr(char *addrstr) {
00028   char buf[20];
00029   addr_t addr = 0;
00030   
00031   sprintf(buf,"0x%s",addrstr);
00032   sscanf(buf,"%x",&addr);
00033   return addr;
00034 }
00035 
00036 static void sprintf_addr(char *addrstr, addr_t addr) {
00037   sprintf(addrstr,"%d.%d.%d.%d",NIPQUAD(addr));
00038 }
00039 
00040 /* MWH---defined my own version of rtentry that uses addr_t's rather
00041    than sockaddrs */
00042 struct rtentry {
00043   addr_t rt_dst;        /* Target address. */
00044   addr_t rt_gateway;        /* Gateway addr. */
00045   addr_t rt_genmask;        /* Target network mask (IP). */
00046   unsigned short int rt_flags;
00047   short int rt_pad2;
00048   unsigned long int rt_ifidx;   /* index of device used */
00049   unsigned char rt_tos;
00050   unsigned char rt_class;
00051   short int rt_pad4;
00052   short int rt_metric;                /* +1 for binary compatibility!  */
00053   char *rt_dev;                       /* Forcing the device at add.  */
00054   unsigned long int rt_mtu;           /* Per route MTU/Window.  */
00055   unsigned long int rt_window;        /* Window clamping.  */
00056   unsigned short int rt_irtt;         /* Initial RTT.  */
00057 };
00058 
00059 /* route table */
00060 struct rtentry *routes = NULL;
00061 int num_rt_entries = 0;
00062 int num_routes = 0;
00063 /*  #define rt_ifidx rt_pad3 */
00064 
00065 /* interface table. right now we just track interface names */
00066 char **ifaces = NULL;
00067 int num_if_entries = 0;
00068 int num_ifaces = 0;
00069 
00070 /* get the interface number of the named interface */
00071 int get_iface_index(char *iface_name) {
00072   int i;
00073 
00074   assert(iface_name != NULL);
00075   for(i = 0; i<num_ifaces; i++) {
00076     if (strcmp(iface_name,ifaces[i]) == 0) {
00077       return(i);
00078     }
00079   }
00080   return(-1);
00081 }
00082 
00083 /* read interface names in out of /proc/net/dev */
00084 void read_ifaces(char *iface_file) {
00085   char buf[2048];
00086   FILE *f;
00087   int num_ifs;
00088   char **curr_if;
00089 
00090   char iface[256];
00091 
00092   f = fopen(iface_file,"r");
00093   if (f == NULL) {
00094     fprintf(stderr,"%s:%d: unable to open %s\n",
00095         __FILE__,__LINE__,iface_file);
00096     fflush(stderr);
00097     exit(1);
00098   }
00099 
00100   num_ifs = 0;
00101   /* count number of interfaces */
00102   while(fgets(buf,sizeof(buf),f)) {
00103     num_ifs++;
00104   }
00105   num_ifs -= 2;         /* strip off title lines */
00106   d_printf(40,"%s:%d: reading %d interfaces\n",__FILE__,__LINE__,num_ifs);
00107 
00108   /* make room in the interface table */
00109   if (num_ifs > num_if_entries) {
00110     if (ifaces != NULL) {
00111       free(ifaces);
00112     }
00113     memalloc(ifaces,char **,sizeof(char *) * num_ifs);
00114     num_if_entries = num_ifs;
00115   }
00116 
00117   /* now read in the interface names */
00118   rewind(f);
00119   fgets(buf,sizeof(buf)-1,f);   /* strip off 2 title lines */
00120   fgets(buf,sizeof(buf)-1,f);
00121 
00122   curr_if = &ifaces[0];
00123   while(fgets(buf,sizeof(buf)-1,f)) {
00124     int _sscanf_retval = 0;
00125     char *cp = NULL;
00126     assert(curr_if >= &ifaces[0]);
00127     assert(curr_if < &ifaces[num_ifs]);
00128     _sscanf_retval = sscanf(buf,"%s",iface);
00129     if (_sscanf_retval < 1) {
00130       fprintf(stderr,
00131               "Warning: scanf (%d) failed on bogus iface entry |%s|\n",
00132               _sscanf_retval, buf);
00133       continue;
00134     }
00135 
00136     /* strip the : */
00137     cp = &iface[0];
00138     while(*cp != '\0' && *cp != ':')
00139       cp++;
00140     *cp = '\0';
00141 
00142     d_printf(40,"%s:%d: found interface %d = %s\n",
00143          __FILE__,__LINE__,(curr_if - ifaces),iface);
00144 
00145     *curr_if = strdup(iface);
00146     curr_if++;
00147   }
00148   num_ifaces = curr_if - ifaces;
00149   
00150   return;
00151 }
00152 
00153 /* read routing table out of /proc/net/route */
00154 void read_routes(char *route_file) {
00155   char buf[1024];
00156   FILE *f;
00157   int nr;
00158   struct rtentry *curr_rt;
00159   char *fmt;
00160   char addrstr1[22],addrstr2[22],addrstr3[22];
00161 
00162   char iface[16];
00163   addr_t mask, dest_addr, gw_addr;
00164   unsigned int flags,refcnt,use,metric,mtu,window,irtt;
00165   
00166   f = fopen(route_file,"r");
00167   if (f == NULL) {
00168     fprintf(stderr,"%s:%d: unable to open %s\n",
00169         __FILE__,__LINE__,route_file);
00170     exit(1);
00171   }
00172 
00173   nr = 0;
00174   /* count number of routes */
00175   while(fgets(buf,sizeof(buf),f)) {
00176     nr++;
00177   }
00178   nr--;             /* strip off title line */
00179   d_printf(40,"%s:%d: reading %d routes\n",__FILE__,__LINE__,nr);
00180         
00181   /* do we have enough room in the routing table? */
00182   if (nr > num_rt_entries) {
00183     if (routes != NULL) {
00184       free(routes);
00185     }
00186     memalloc(routes,struct rtentry *,sizeof(struct rtentry) * nr);
00187     num_rt_entries = nr;
00188   }
00189 
00190   /* now read in the routes */
00191   rewind(f);
00192   fmt = proc_gen_fmt(route_file, f,
00193              "Iface", "%16s",
00194              "Destination", "%s",
00195              "Gateway", "%s",
00196              "Flags", "%X",
00197              "RefCnt", "%d",
00198              "Use", "%d",
00199              "Metric", "%d",
00200              "Mask", "%s",
00201              "MTU", "%d",
00202              "Window", "%d",
00203              "IRTT", "%d",
00204              NULL);
00205 
00206   if (fmt == NULL) {
00207     fprintf(stderr,"%s:%d: did not get format for reading %s\n",__FILE__,
00208         __LINE__,route_file);
00209     exit(1);
00210   }
00211 
00212   curr_rt = routes;
00213   while(fgets(buf,sizeof(buf)-1,f)) {
00214     int ifidx;
00215     assert(curr_rt >= &routes[0]);
00216     assert(curr_rt < &routes[nr]); 
00217     if (sscanf(buf,fmt,
00218            iface,addrstr1,addrstr2,&flags,&refcnt,&use,
00219            &metric,addrstr3,&mtu,&window,&irtt) < 11) {
00220       fprintf(stderr,"Warning: scanf failed on bogus tab entry |%s|\n",buf);
00221       continue;
00222     }
00223 
00224     /* read the addresses */
00225     dest_addr = get_addr(addrstr1);
00226     gw_addr = get_addr(addrstr2);
00227     mask = get_addr(addrstr3);
00228 
00229     ifidx = if_nametoindex(iface);
00230     if (ifidx == -1) {      /* unknown interface! */
00231       fprintf(stderr,"Warning: unknown iface |%s| in tab entry |%s|\n",
00232               iface,buf);
00233       continue;
00234     }
00235 
00236     sprintf_addr(addrstr1,dest_addr);
00237     sprintf_addr(addrstr2,gw_addr);
00238     sprintf_addr(addrstr3,mask);
00239     d_printf(45,"%s:%d: route : dst = %s, gw = %s, mask = %s, ifidx = %d (%s)\n",
00240          __FILE__,__LINE__,addrstr1,addrstr2,addrstr3,
00241          ifidx,iface);
00242 
00243     curr_rt->rt_ifidx = ifidx;
00244     curr_rt->rt_dst = dest_addr;
00245     curr_rt->rt_gateway = gw_addr;
00246     curr_rt->rt_genmask = mask;
00247     curr_rt->rt_flags = (unsigned short int)flags;
00248     curr_rt->rt_metric = (short int)metric;
00249     curr_rt->rt_mtu = (unsigned long int)mtu;
00250     curr_rt->rt_window = (unsigned long int)window;
00251     curr_rt->rt_irtt = (unsigned short int)irtt;
00252 
00253     curr_rt++;
00254   }
00255   num_routes = curr_rt - routes;
00256 }
00257 
00258 /* looks up the next hop to the given destination address. On success,
00259    fill in the results in retval, and return 0. On failure, return -1. */
00260 extern int nexthop(addr_t dstaddr, struct rt_lookup *retval) {
00261   int i;
00262 
00263   assert(retval != NULL);
00264   print_anti_timer(16,"nexthop");
00265   for(i=0; i<num_routes; i++) {
00266     struct rtentry *rt = &routes[i];
00267     addr_t dest_net = rt->rt_dst;
00268     addr_t gw = rt->rt_gateway;
00269     addr_t mask = rt->rt_genmask;
00270     if ((dstaddr & mask) == dest_net) {
00271       print_timer(16,"nexthop");
00272       if (gw == 0) {
00273     retval->hopaddr = dstaddr;
00274       } else {
00275     retval->hopaddr = gw;
00276       }
00277       retval->ifidx = rt->rt_ifidx;
00278       return(0);
00279     }
00280   }
00281   print_timer(16,"nexthop");
00282   return(-1);
00283 }