[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 |
Splash - DocumentationSNMP Plus a Lightweight API for SNAP Handlingsnap-1.1-wjdb/lib/router.cGo 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 } |