N-sim
Emulation and simulation of
Wireless Sensor Networks



   Home


   Project Page


   Download


   CVS



   Installation


   Configuration


   Plug-ins




 Hosted by
SourceForge.net Logo

/home/brennan/n-sim/Vaike/linux/system-addons/networking/mesh_on_demand.c

Go to the documentation of this file.
00001 
00014 /*
00015  * Copyright 2007. Los Alamos National Security, LLC. This material
00016  * was produced under U.S. Government contract DE-AC52-06NA25396 for
00017  * Los Alamos National Laboratory (LANL), which is operated by Los
00018  * Alamos National Security, LLC, for the Department of Energy. The
00019  * U.S. Government has rights to use, reproduce, and distribute this
00020  * software. NEITHER THE GOVERNMENT NOR LOS ALAMOS NATIONAL SECURITY,
00021  * LLC, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL
00022  * LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to
00023  * produce derivative works, such modified software should be clearly
00024  * marked, so as not to confuse it with the version available from LANL.
00025  *
00026  * Additionally, this program is free software; you can redistribute
00027  * it and/or modify it under the terms of the GNU General Public
00028  * License as published by the Free Software Foundation; version 2 of
00029  * the License. Accordingly, this program is distributed in the hope
00030  * it will be useful, but WITHOUT ANY WARRANTY; without even the
00031  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00032  * PURPOSE. See the GNU General Public License for more details.
00033  */
00034 
00035 #define _BSD_SOURCE
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <syslog.h>
00040 #include <sys/types.h>
00041 #include <sys/socket.h>
00042 #include <sys/stat.h>
00043 #include <sys/time.h>
00044 #include <sys/ioctl.h>
00045 #include <fcntl.h>
00046 #include <unistd.h>
00047 #include <net/if.h>
00048 #include <netinet/in.h>
00049 #include <netinet/ip.h>
00050 #include <netinet/udp.h>
00051 #include <net/ethernet.h>
00052 #include <net/if_arp.h>
00053 #include <arpa/inet.h>
00054 
00057 #include <linux/if_tun.h>
00058 #include <linux/netfilter.h>
00059 #include "libipq.h"
00060 #define MISC_MAJOR  10
00061 #define TUN_MINOR   200
00062 /******************************************/
00063 
00064 #include "sensor_self.h"
00065 #include "mesh_link.h"
00066 #include "mesh_route.h"
00067 #include "mesh_on_demand.h"
00068 
00069 
00070 #define DIVERT_DEV_IP "127.0.0.2"
00071 #define DIVERT_DEV_NAME "tun"
00072 
00073 
00074 /* callback */
00075 int route_discovery_done(u_int32_t daddr, protocol_t *proto,
00076                          discovery_result_t reachable)
00077 {
00078   link_entry_t *entry;
00079   msg_queue_t *pkt;
00080 
00081   if (proto == NULL) {
00082     errno = EINVAL;
00083     return -1;
00084   }
00085 
00086   if ((entry = retrieve_entry(proto, daddr)) == NULL) {
00087     errno = ENOLINK;
00088     return -1;
00089   }
00090   pkt = entry->routing_backlog;
00091   entry->routing_pending = 0;
00092 
00093   if (reachable == ROUTE_FOUND) {
00094     while (pkt != NULL) {
00095       msg_queue_t *cur = pkt;
00096       struct sockaddr_in to;
00097       to.sin_family = AF_INET;
00098       to.sin_port = pkt->port;
00099       to.sin_addr = entry->link.node;
00100       mesh_sendmsg(proto->sensor->interface, proto->sensor->mac_addr,
00101                    proto->queue_sd, pkt->data, pkt->len, &to);
00102       free(pkt->data);
00103       pkt = pkt->next;
00104       free(cur);
00105     }
00106   } else if (reachable == NO_ROUTE) {
00107     // TODO: search other protocols for a route??
00108     while (pkt != NULL) {
00109       msg_queue_t *cur = pkt;
00110       pkt = pkt->next;
00111       free(pkt->data);
00112       free(cur);
00113     }
00114   }
00115   return 0;
00116 }
00117 
00118 
00119 /* 1 if discovery is pending, 0 otherwise, -1 on error */
00120 static int route_discovery_pending(u_int32_t daddr, protocol_t *proto)
00121 {
00122   link_entry_t *entry;
00123   
00124   if (proto == NULL)
00125     return -1;
00126 
00127   if ((entry = retrieve_entry(proto, daddr)) == NULL)
00128     return entry->routing_pending;
00129   return 0;
00130 }
00131 
00132 
00134 static int divert_init(void)
00135 {
00136   struct ifreq ifr;
00137   int fd, error;
00138   char cmd[256];
00139   unsigned char dev[IFNAMSIZ];
00140   char *dev_name = "/dev/net/tun";
00141 
00142   umask(0);
00143   mkdir("/dev/net", 0755);
00144   mknod(dev_name, S_IFCHR|S_IREAD|S_IWRITE, makedev(MISC_MAJOR, TUN_MINOR));
00145   system("modprobe tun");
00146 
00147   if ((fd = open(dev_name, O_RDWR)) < 0) {
00148     syslog(LOG_ERR, "open %s: %m", dev_name);
00149     return -1;
00150   }
00151 
00152   memset(&ifr, 0, sizeof(ifr));
00153   ifr.ifr_flags = IFF_TUN | IFF_NO_PI;  /* i.e. no ethernet hdr, no pkt info */
00154   strcpy(ifr.ifr_name, DIVERT_DEV_NAME);
00155 
00156   if ((error = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) {
00157     syslog(LOG_ERR, "ioctl (TUNSETIFF): %m");
00158     close(fd);
00159     return error;
00160   }
00161   strcpy(dev, ifr.ifr_name);
00162   sprintf(cmd, "/sbin/ifconfig %s %s netmask 255.255.255.255 up",
00163           dev, DIVERT_DEV_IP);
00164   system(cmd);
00165          
00166   /* no checksum */
00167   if ((error = ioctl(fd, TUNSETNOCSUM, 1)) < 0) {
00168     syslog(LOG_ERR, "ioctl (TUNSETNOCSUM): %m");
00169     close(fd);
00170     return error;
00171   }
00172   
00173   return fd;
00174 }
00175 /*************************************/
00176 
00177 
00178 static int read_route_request(self_t *self, int fd, u_int32_t *dest_addr,
00179                               protocol_t *proto)
00180 {
00181   unsigned int buflen = MAX_MTU;
00182   unsigned char buf[buflen], *iphdr;
00183   ssize_t rlen;
00184   link_entry_t *entry;
00185   msg_queue_t *pkt;
00186   u_int32_t src_addr;
00187   struct ether_header eh;
00188   struct ip ip;
00189   struct udphdr udp;
00190   struct mesh_hdr mh;
00191   unsigned int header_size = ETHER_HDR_LEN + sizeof(ip) + sizeof(udp);
00192 
00193   if ((rlen = read(fd, buf, buflen)) <= 0) {
00194     if (rlen < 0)
00195       syslog(LOG_ERR, "read: %m");
00196     return rlen;
00197   }
00198 
00199   if (header_size > rlen) {
00200     syslog(LOG_ERR, "read_route_request: invalid packet");
00201     return -1;
00202   }
00203   iphdr = buf + ETHER_HDR_LEN;
00204 
00205   pkt = malloc(sizeof(msg_queue_t));
00206   pkt->data = malloc(rlen * sizeof(unsigned char));
00207   pkt->len = rlen;
00208   memcpy(pkt->data, buf + header_size, rlen);
00209 
00210   memcpy(&eh, buf, ETHER_HDR_LEN);
00211   memcpy(&ip, iphdr, sizeof(ip));
00212   memcpy(&udp, iphdr + sizeof(ip), sizeof(udp));
00213   memcpy(&mh, iphdr + sizeof(ip) + sizeof(udp), sizeof(mh));
00214   *dest_addr = ip.ip_dst.s_addr;
00215   src_addr = ip.ip_src.s_addr;
00216   pkt->port = udp.uh_sport;
00217   proto = protocol_by_id(self, mh.protocol_id);
00218 
00219   if ((entry = retrieve_entry(proto, *dest_addr)) == NULL) {
00220     int error = 0;
00221 
00222     entry = new_link_entry(proto);
00223     entry->node_id = *dest_addr;
00224     entry->link.node.s_addr = *dest_addr;
00225     entry->requester = src_addr;
00226 
00227     if ((error = add_entry(proto, *dest_addr, entry)) < 0)
00228       return error;
00229     entry->routing_backlog = entry->last_packet = pkt;
00230   } else {
00231     if (entry->last_packet == NULL) {
00232       entry->routing_backlog = entry->last_packet = pkt;
00233     } else {
00234       entry->last_packet->next = pkt;
00235       entry->last_packet = pkt;
00236     }
00237   }
00238 
00239   if (retrieve_entry(proto, src_addr) == NULL) {
00240     int sd, error = 0;
00241     struct arpreq ar;
00242     link_entry_t *sentry = new_link_entry(proto);
00243     sentry->node_id = src_addr;
00244     sentry->link.node.s_addr = src_addr;
00245     sentry->requester = 0;
00246 
00247     ar.arp_ha.sa_family = AF_INET;
00248     strncpy(ar.arp_ha.sa_data, eh.ether_shost, sizeof(ar.arp_ha.sa_data));
00249     strncpy(ar.arp_dev, proto->sensor->interface, sizeof(ar.arp_dev));
00250     if ((sd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
00251       syslog(LOG_ERR, "read_route_request: source backtrack socket %m");
00252       return -1;
00253     }
00254     if ((error = ioctl(sd, SIOCGRARP, &ar)) < 0) {
00255       syslog(LOG_ERR, "read_route_request: ioctl SIOCGRARP %m");
00256       return error;
00257     }
00258     sentry->link.next_hop = ((struct sockaddr_in*)(&ar.arp_pa))->sin_addr;
00259 
00260     if ((error = add_entry(proto, src_addr, sentry)) < 0)
00261       return error;
00262   }
00263   return 0;
00264 }
00265 
00266 
00267 int route_idle_time(u_int32_t dest, protocol_t *proto)
00268 {
00269   link_entry_t *entry = retrieve_entry(proto, dest);
00270   if (entry == NULL) {
00271     errno = ENOLINK;
00272     return -1;
00273   }
00274 
00275   return (int)(get_current_time() - entry->time_last_used);
00276 }
00277 
00278 
00279 static int init_on_demand(void)
00280 {
00281   int fd, error = 0;
00282   link_entry_t deflt;
00283 
00285   system("sysctl -w net/ipv4/ip_forward=1");
00286   system("sysctl -w net/ipv4/conf/all/accept_redirects=0");
00287   system("sysctl -w net/ipv4/conf/all/send_redirects=0");
00288   system("sysctl -w net/ipv4/route/min_delay=0");
00289 
00290   if ((fd = divert_init()) < 0) {
00291     syslog(LOG_ERR, "tun_init");
00292     return fd;
00293   }
00294 
00295   /* default route to divert device */
00296   inet_aton("0.0.0.0", &deflt.link.node);
00297   inet_aton("0.0.0.0", &deflt.link.next_hop);
00298   deflt.iface = DIVERT_DEV_NAME;
00299   if ((error = add_kernel_route(&deflt)) < 0)
00300     return error;
00301   return fd;
00302 }
00303 
00304 
00305 /* thread */
00306 int on_demand(self_t *self)
00307 {
00308   int fd;
00309 
00310   if (self == NULL) {
00311     errno = EINVAL;
00312     return -1;
00313   }
00314   if ((fd = init_on_demand()) < 0)
00315     return fd;
00316 
00317   while (1) {
00318     int error;
00319     u_int32_t dest_addr;
00320     protocol_t *proto = NULL;
00321 
00322     if ((error = read_route_request(self, fd, &dest_addr, proto)) <= 0) {
00323       if (error < 0)
00324         syslog(LOG_ERR, "read_route_request: %m");
00325       continue;
00326     }
00327     if ((error = route_discovery_pending(dest_addr, proto)) <= 0) {
00328       if (error < 0)
00329         syslog(LOG_ERR, "route_discovery_pending: %m");
00330       continue;
00331     }
00332     proto->mesh_init_discovery(proto, dest_addr);
00333   }
00334 }
00335 
00336 
00337 /* thread for tracking  */
00338 int packet_usage(self_t *self)
00339 {
00340   int error;
00341   struct ipq_handle *qh;
00342 
00343   if ((qh = ipq_create_handle(0, PF_INET)) < 0) {
00344     syslog(LOG_ERR, "ipq_create_handle %m");
00345     return -1;
00346   }
00347   if ((error = ipq_set_mode(qh, IPQ_COPY_META, 0)) < 0) {
00348     syslog(LOG_ERR, "ipq_set_mode (IPQ_COPY_META): %m");
00349     return -1;
00350   }
00351 
00352   while (1) {
00353     unsigned int bufsize = sizeof(struct ip) + sizeof(struct udphdr);
00354     unsigned char buf[bufsize];
00355 
00356     if ((error = ipq_read(qh, buf, bufsize, 0)) < 0) {
00357       syslog(LOG_ERR, "ipq_read %m");
00358       continue;
00359     }
00360 
00361     switch (ipq_message_type(buf)) {
00362     case NLMSG_ERROR:
00363       syslog(LOG_ERR, "NLMSG_ERROR: %s", strerror(ipq_get_msgerr(buf)));
00364       break;
00365     case IPQM_PACKET:
00366       {
00367         ipq_packet_msg_t *pkt;
00368         struct iphdr *iph;
00369         link_entry_t *entry;
00370         protocol_t *proto = self->protocols;
00371 
00372         if ((pkt = ipq_get_packet(buf)) == NULL) {
00373           syslog(LOG_ERR, "ipq_get_packet %m");
00374           break;
00375         }
00376         iph = (struct iphdr*)pkt->payload;
00377         while (proto != NULL) {
00378           if ((entry = retrieve_entry(proto, iph->daddr)) ==  NULL) {
00379             syslog(LOG_ERR, "no entry for %s: %m", ip_to_dot(iph->daddr));
00380             continue;
00381           }
00382           entry->time_last_used = get_current_time();
00383 
00384           if ((entry = retrieve_entry(proto, iph->saddr)) ==  NULL) {
00385             syslog(LOG_ERR, "no entry for %s: %m", ip_to_dot(iph->saddr));
00386             continue;
00387           }
00388           entry->time_last_used = get_current_time();
00389 
00390           proto = proto->next;
00391         }
00392 
00393         if ((error = ipq_set_verdict(qh, pkt->packet_id,
00394                                      NF_ACCEPT, 0, NULL)) < 0)
00395           syslog(LOG_ERR, "ipq_set_verdict %m");
00396         break;
00397       }
00398     }
00399   }
00400   ipq_destroy_handle(qh);
00401   return 0;
00402 }


© 2007, Los Alamos National Security, LLC.