[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/snap_kern_iface.c

Go 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 */