[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/snap_kern_iface.cGo to the documentation of this file.00001 /* 00002 * snap_kern_iface.c : interface between snap interpreter and the rest 00003 * of the kernel networking code 00004 */ 00005 00006 #include <asm/types.h> 00007 #include <assert.h> 00008 #include <errno.h> 00009 #include <features.h> 00010 #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 00011 #include <netpacket/packet.h> 00012 #include <net/ethernet.h> /* the L2 protocols */ 00013 #else 00014 #include <asm/types.h> 00015 #include <linux/if_packet.h> 00016 #include <linux/if_ether.h> /* The L2 protocols */ 00017 #endif 00018 #include <net/if.h> 00019 #include <net/if_arp.h> 00020 #include <netdb.h> 00021 #include <netinet/in.h> 00022 #include <netinet/ip.h> 00023 #include <stdlib.h> 00024 #include <sys/types.h> 00025 #include <sys/ioctl.h> 00026 #include <sys/socket.h> 00027 #include <sys/un.h> 00028 #include <unistd.h> 00029 #include "d_printf.h" 00030 #include "packet.h" 00031 #include "memalloc.h" 00032 #include "interface.h" 00033 #include "sockets.h" 00034 #include "pathnames.h" 00035 #include "intl.h" 00036 #include "net-support.h" 00037 #include "router.h" 00038 #include "io.h" 00039 #include "warn.h" 00040 00041 #define NIPQUAD(addr) \ 00042 ((unsigned char *)&(addr))[0], \ 00043 ((unsigned char *)&(addr))[1], \ 00044 ((unsigned char *)&(addr))[2], \ 00045 ((unsigned char *)&(addr))[3] 00046 00047 #ifdef CONFIG_IP_SNAP 00048 00049 static inline unsigned short ip_fast_csum(unsigned char * iph, 00050 unsigned int ihl); 00051 00052 00053 #ifdef CONFIG_IP_SNAP_DEBUG 00054 int sysctl_snap_debug_level = 0; 00055 #endif /* CONFIG_IP_SNAP_DEBUG */ 00056 00057 /* hardware interface definitions */ 00058 struct if_info { 00059 struct if_nameindex ifni; 00060 __u32 addr; 00061 char hwaddr[32]; 00062 }; 00063 00064 /* hardware interface variables */ 00065 struct sockaddr_in *thishosthint = NULL; 00066 struct hostent *thishe = NULL; 00067 unsigned int numifs = 0; 00068 struct if_info *ifs = NULL; 00069 unsigned int maxifnum = 0; 00070 unsigned int ifs_size = 0; 00071 00072 /* the send sockets */ 00073 static int rawip_send_ra_socket; 00074 00075 void init_kern_iface(struct sockaddr_in *hint) { 00076 char hostname[128]; 00077 struct if_nameindex *allifs; 00078 struct if_nameindex *currif; 00079 struct interface ife; 00080 00081 unsigned char ra_space[4]; 00082 00083 /* get the primary hostname */ 00084 if ((hint != NULL) && (hint->sin_addr.s_addr != 0)) { 00085 thishosthint = hint; 00086 } 00087 00088 if (gethostname(hostname,sizeof(hostname)) < 0) { 00089 perror("gethostname"); 00090 exit(EXIT_FAILURE); 00091 } 00092 if ((thishe = gethostbyname(hostname)) == NULL) { 00093 herror("gethostbyname"); 00094 fprintf(stderr,"debug >> error while trying to resolve %s\n",hostname); 00095 exit(EXIT_FAILURE); 00096 } 00097 00098 if ((rawip_send_ra_socket = socket(AF_INET, SOCK_RAW, IPPROTO_SNAP)) < 0) { 00099 perror("snap_kern_iface: rawip_send_ra_socket: socket()"); 00100 exit(EXIT_FAILURE); 00101 } 00102 ra_space[IPOPT_OPTVAL] = IPOPT_RA; 00103 ra_space[IPOPT_OLEN] = 4; 00104 ra_space[2] = ra_space[3] = 0; 00105 if (setsockopt(rawip_send_ra_socket, IPPROTO_IP, IP_OPTIONS, ra_space, 00106 sizeof(ra_space)) < 0) { 00107 perror("rawip_send_ra_socket: router alert setsockopt()"); 00108 exit(EXIT_FAILURE); 00109 } 00110 00111 /* retrieve the active interfaces from the kernel */ 00112 if ((skfd = sockets_open()) < 0) { 00113 perror("skfd: sockets_open()"); 00114 exit(EXIT_FAILURE); 00115 } 00116 00117 /* collect IFACE info from glibc functions */ 00118 if ((allifs = if_nameindex()) == NULL) { 00119 perror("if_nameindex"); 00120 exit(EXIT_FAILURE); 00121 } 00122 for (currif = allifs; 00123 (currif->if_index != 0) && (currif->if_name != NULL); 00124 currif++) { 00125 if (currif->if_index > maxifnum) { 00126 maxifnum = currif->if_index; 00127 } 00128 numifs++; 00129 } 00130 d_printf(40,"found %d interfaces\n",numifs); 00131 00132 assert(maxifnum > 0); 00133 00134 /* get additional IFACE info from local functions */ 00135 memalloc(ifs,struct if_info *,sizeof(struct if_info) * (maxifnum + 1)); 00136 ifs_size = maxifnum + 1; 00137 for (currif = allifs;(currif->if_index != 0) && (currif->if_name != NULL); currif++) { 00138 (void)if_fetch(currif->if_name, &ife); 00139 ifs[currif->if_index].ifni.if_index = currif->if_index; 00140 ifs[currif->if_index].ifni.if_name = currif->if_name; 00141 ifs[currif->if_index].addr = 00142 (*(struct sockaddr_in *)(&ife.addr)).sin_addr.s_addr; 00143 memcpy(ifs[currif->if_index].hwaddr, ife.hwaddr, 32); 00144 d_printf(45,"if_index %d = %s inaddr = %d.%d.%d.%d\n", currif->if_index,currif->if_name, NIPQUAD((*(struct sockaddr_in *)(&ife.addr)).sin_addr.s_addr)); 00145 fflush(stderr); 00146 } 00147 00148 /* 00149 read additional IFACE and ROUTE info from /proc 00150 NB: IFACE info from /proc/net/dev is used for ifacename<->ifaceindex translation 00151 I don't know why Jon implemented this. 00152 */ 00153 read_ifaces(PROC_NET_DEV_PATH); 00154 read_routes(PROC_NET_ROUTE_PATH); 00155 } 00156 00157 /* returns one of the current host's IP addresses, preferably not 00158 127.0.0.1 */ 00159 #ifdef __KERNEL__ 00160 int snap_here(u32 *addr, struct sk_buff *skb) { 00161 #else 00162 int snap_here(__u32 *addr, packet_t *p) { 00163 #endif 00164 00165 int i; 00166 __u32 tmpaddr; 00167 00168 if (thishosthint != NULL) { 00169 d_printf(50,"%s:%d: HERE: found non-loopback addr\n", 00170 __FILE__,__LINE__); 00171 *addr = thishosthint->sin_addr.s_addr; 00172 return 0; 00173 } 00174 00175 assert(thishe != NULL); 00176 for(i=0; thishe->h_addr_list[i] != NULL; i++) { 00177 tmpaddr = *(__u32 *)thishe->h_addr_list[i]; 00178 if (tmpaddr != htonl(INADDR_LOOPBACK)) { 00179 d_printf(50,"%s:%d: HERE: found non-loopback addr\n", 00180 __FILE__,__LINE__); 00181 *addr = tmpaddr; 00182 return 0; 00183 } 00184 } 00185 if (i > 0) { 00186 d_printf(50,"%s:%d: HERE: ran through %d ifs, all loopback!\n", 00187 __FILE__,__LINE__,i); 00188 *addr = *(__u32 *)thishe->h_addr_list[0]; 00189 return 0; 00190 } 00191 return -1; 00192 00193 } 00194 00195 #ifdef __KERNEL__ 00196 int getdevindex(struct device *dev_in) { 00197 return -1; /* not found */ 00198 } 00199 #endif 00200 00201 int next_hop(__u32 *hop, 00202 __u32 daddr, /* where we are headed */ 00203 int tos ) { /* type of service */ 00204 00205 struct rt_lookup rt; 00206 00207 if (nexthop(daddr,&rt) < 0) { 00208 *hop = 0; 00209 return -1; 00210 } 00211 *hop = rt.hopaddr; 00212 return 0; 00213 } 00214 00215 #ifdef __KERNEL__ 00216 int ishere(__u32 addr, struct sk_buff *skb) { 00217 #else 00218 int ishere(__u32 addr, packet_t *p) { 00219 #endif 00220 int i; 00221 struct if_info *curr; 00222 00223 for(i=0; i<=maxifnum; i++) { 00224 curr = &ifs[i]; 00225 d_printf(100,"%s:%d: curr=%d, here=(%d.%d.%d.%d)\n", 00226 __FILE__,__LINE__,i,NIPQUAD(curr->addr)); 00227 if ((curr->ifni.if_index != 0) && (curr->ifni.if_name != NULL) && 00228 (curr->addr == addr)) { 00229 d_printf(100,"%s:%d: ishere(%d.%d.%d.%d) -> YES\n", 00230 __FILE__,__LINE__,NIPQUAD(addr)); 00231 return 1; 00232 } 00233 } 00234 d_printf(100,"%s:%d: ishere(%d.%d.%d.%d) -> NO\n", __FILE__,__LINE__,NIPQUAD(addr)); 00235 return 0; 00236 } 00237 00238 /* 00239 protocol specific demux send handlers 00240 00241 */ 00242 00243 #include "../src/snap_demux_handler.h" 00244 00245 #ifdef __KERNEL__ 00246 int snap_demux_send_unix(__u16 destport, struct sk_buff *skb, 00247 void *s, unsigned int slen) { 00248 #else 00249 int snap_demux_send_unix(__u16 destport, packet_t *p, 00250 void *s, unsigned int slen) { 00251 #endif 00252 00253 int usock; 00254 struct sockaddr_un laddr; 00255 00256 d_printf_timed(7,"snap_demux_send_unix : creating socket\n"); 00257 00258 if ((usock = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) { 00259 perror("snap_demux_send_unix: socket()"); 00260 return -1; 00261 } 00262 00263 d_printf_timed(7,"snap_demux_send_unix : creating sockaddr_un struct\n"); 00264 00265 laddr.sun_family = AF_UNIX; 00266 sprintf(laddr.sun_path, "/tmp/snap%d",destport); 00267 00268 d_printf_timed(7,"snap_demux_send_unix : sending \n"); 00269 00270 if (sendto(usock, s, slen, 0, (struct sockaddr *)&laddr, 00271 sizeof(laddr)) < slen) { 00272 perror("snap_demux_send_unix: sendto()"); 00273 return -1; 00274 } 00275 00276 d_printf_timed(7,"snap_demux_send_unix : finished \n"); 00277 00278 close(usock); 00279 return 0; 00280 } 00281 00282 #ifdef __KERNEL__ 00283 int snap_demux_send_rawip(__u16 destport, struct sk_buff *skb, 00284 void *s, unsigned int slen) { 00285 #else 00286 int snap_demux_send_rawip(__u16 destport, packet_t *p, 00287 void *s, unsigned int slen) { 00288 #endif 00289 00290 struct sockaddr_in bindaddr; 00291 int socket_rawip; 00292 00293 if ((socket_rawip = socket(AF_INET, SOCK_RAW, IPPROTO_SNAP)) < 0) { 00294 perror("snap_demux_send_rawip: socket()"); 00295 return 1; 00296 } 00297 00298 memset(&bindaddr, 0, sizeof(bindaddr)); 00299 bindaddr.sin_family = AF_INET; 00300 bindaddr.sin_addr.s_addr = htonl( (127 << 24) + 1 ); /* == 127.0.0.1 */ 00301 00302 if (sendto(socket_rawip, s, slen, 0, (struct sockaddr *)&bindaddr, 00303 sizeof(bindaddr)) < slen) { 00304 perror("snap_demux_send_udp: sendto()"); 00305 close (socket_rawip); 00306 return -1; 00307 } 00308 00309 close (socket_rawip); 00310 return 0; 00311 } 00312 00313 #ifdef __KERNEL__ 00314 int snap_demux_send_udp(__u16 destport, struct sk_buff *skb, 00315 void *s, unsigned int slen) { 00316 #else 00317 int snap_demux_send_udp(__u16 destport, packet_t *p, 00318 void *s, unsigned int slen) { 00319 #endif 00320 00321 struct sockaddr_in bindaddr; 00322 int socket_udp; 00323 00324 d_printf_timed(7,"snap_demux_send_udp : creating socket\n"); 00325 00326 if ((socket_udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00327 perror("snap_demux_send_udp: socket()"); 00328 return 1; 00329 } 00330 00331 d_printf_timed(7,"snap_demux_send_udp : creating sockaddr_in struct\n"); 00332 00333 memset(&bindaddr, 0, sizeof(bindaddr)); 00334 bindaddr.sin_family = AF_INET; 00335 bindaddr.sin_addr.s_addr = htonl( (127 << 24) + 1 ); /* == 127.0.0.1 */ 00336 bindaddr.sin_port = htons(destport); 00337 00338 00339 d_printf_timed(7,"snap_demux_send_udp : sending \n"); 00340 00341 if (sendto(socket_udp, s, slen, 0, (struct sockaddr *)&bindaddr, 00342 sizeof(bindaddr)) < slen) { 00343 perror("snap_demux_send_udp: sendto()"); 00344 close(socket_udp); 00345 return -1; 00346 } 00347 close(socket_udp); 00348 00349 d_printf_timed(7,"snap_demux_send_udp : finished \n"); 00350 00351 return 0; 00352 } 00353 00354 00355 /* 00356 handle demux instruction. Outgoing interfaces can be selected 00357 by setting an environment variable. For backward compatibility 00358 purposes handling defaults to a unix pipe 00359 */ 00360 #ifdef __KERNEL__ 00361 int snap_demux_send(__u16 destport, struct sk_buff *skb, 00362 void *s, unsigned int slen) { 00363 #else 00364 int snap_demux_send(__u16 destport, packet_t *p, 00365 void *s, unsigned int slen) { 00366 #endif 00367 int protocols; 00368 int returnvals = 0; 00369 char* env_val; 00370 00371 d_printf_timed(7,"snap_demux_send : preparing for send ..\n"); 00372 /* retrieve the protocols */ 00373 env_val = getenv("SNAP_DEMUX_HANDLER"); 00374 if (env_val != NULL) 00375 protocols = atoi(env_val); 00376 else 00377 protocols = SNAP_UDP; 00378 00379 if (protocols & SNAP_UNIX) 00380 returnvals += snap_demux_send_unix(destport, p, s, slen); 00381 00382 if (protocols & SNAP_RAWIP) 00383 returnvals += snap_demux_send_rawip(destport, p, s, slen); 00384 00385 if (protocols & SNAP_UDP) 00386 returnvals += snap_demux_send_udp(destport, p, s, slen); 00387 00388 d_printf_timed(7,"snap_demux_send : .. sent message\n"); 00389 00390 return returnvals; 00391 00392 } 00393 00394 int snap_send_packet(packet_t *p, int stack_amt, __u32 dest, unsigned char rb, int ep, short direct) { 00395 00396 struct snaphdr *sh; 00397 buffer_t newbuf; 00398 __u32 hopaddr; 00399 struct rt_lookup rt; 00400 struct iphdr *newiph; 00401 struct sockaddr_in hopipaddr; 00402 00403 d_printf(60,"snap_send_packet : marshalling packet and initializing structure\n"); 00404 00405 if (marshal_packet(p, stack_amt, &newbuf)) { 00406 warn("%s:%d: marshal_packet failed\n",__FILE__,__LINE__); 00407 return -1; 00408 } 00409 00410 /* modify the snapheader */ 00411 newiph = (struct iphdr *)newbuf.s; 00412 sh = (struct snaphdr *)(newbuf.s + newiph->ihl * 4); 00413 sh->entry_point = htons(ep); 00414 sh->daddr = dest; 00415 00416 /* create the ip header */ 00417 newiph->daddr = dest; 00418 newiph->ttl = rb; 00419 newiph->check = 0; 00420 newiph->check = 00421 ip_fast_csum((unsigned char *)newiph, 00422 newiph->ihl); 00423 00424 /* initialize the sockaddr structure */ 00425 memset(&hopipaddr, 0, sizeof(hopipaddr)); 00426 hopipaddr.sin_family = AF_INET; 00427 00428 /* calculate the next hop only if we do not want a direct connection */ 00429 if (!direct){ 00430 if (nexthop(dest,&rt) < 0) /* find next IP hop */ 00431 return -1; 00432 hopaddr = rt.hopaddr; 00433 00434 d_printf(100,"%s:%d: indirect send to next hop: %d.%d.%d.%d, ifindex %d\n",__FILE__,__LINE__,NIPQUAD(hopaddr),rt.ifidx); 00435 hopipaddr.sin_addr.s_addr = hopaddr; 00436 } 00437 else 00438 { 00439 d_printf(100,"%s:%d: direct send to next host: %d.%d.%d.%d, ifindex unknown\n",__FILE__,__LINE__,NIPQUAD(dest)); 00440 hopipaddr.sin_addr.s_addr = dest; 00441 } 00442 00443 if (setsockopt(rawip_send_ra_socket, IPPROTO_IP, IP_TTL, (char *)&rb, 00444 sizeof(rb)) < 0) { 00445 perror("rawip_send_ra_socket: ttl setsockopt()"); 00446 return -1; 00447 } 00448 00449 d_printf(60,"snap_send_packet : sending packet\n"); 00450 00451 00452 if (sendto(rawip_send_ra_socket, sh, newbuf.lenb - (newiph->ihl * 4), 0, 00453 (struct sockaddr *)&hopipaddr, sizeof(hopipaddr)) != 00454 newbuf.lenb - (newiph->ihl * 4)) { 00455 perror("rawip_send_ra_socket: sendto()"); 00456 return -1; 00457 } 00458 00459 d_printf(60,"snap_send_packet : finished\n"); 00460 00461 return 0; 00462 } 00463 00464 packet_t *pkt_dup(packet_t *p) { 00465 00466 return NULL; 00467 } 00468 00469 00470 int next_hop_and_dev(__u32 *hop, int *dev, __u32 daddr) { 00471 struct rt_lookup rt; 00472 00473 if (nexthop(daddr, &rt) < 0) { 00474 *hop = 0; 00475 *dev = 0; 00476 return -1; 00477 } 00478 *hop = rt.hopaddr; 00479 *dev = rt.ifidx; 00480 return 0; 00481 } 00482 00483 static inline unsigned short ip_fast_csum(unsigned char * iph, 00484 unsigned int ihl) { 00485 unsigned int sum; 00486 00487 __asm__ __volatile__("\n\ 00488 movl (%1), %0 \n\ 00489 subl $4, %2 \n\ 00490 jbe 2f \n\ 00491 addl 4(%1), %0 \n\ 00492 adcl 8(%1), %0 \n\ 00493 adcl 12(%1), %0 \n\ 00494 1: adcl 16(%1), %0 \n\ 00495 lea 4(%1), %1 \n\ 00496 decl %2 \n\ 00497 jne 1b \n\ 00498 adcl $0, %0 \n\ 00499 movl %0, %2 \n\ 00500 shrl $16, %0 \n\ 00501 addw %w2, %w0 \n\ 00502 adcl $0, %0 \n\ 00503 notl %0 \n\ 00504 2: \n\ 00505 " 00506 /* Since the input registers which are loaded with iph and ipl 00507 are modified, we must also specify them as outputs, or gcc 00508 will assume they contain their original values. */ 00509 : "=r" (sum), "=r" (iph), "=r" (ihl) 00510 : "1" (iph), "2" (ihl)); 00511 return(sum); 00512 } 00513 00514 00515 #endif /* CONFIG_IP_SNAP */ |