File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / coova-chilli / src / tun.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:48:25 2012 UTC (13 years, 1 month ago) by misho
Branches: coova-chilli, MAIN
CVS tags: v1_0_12, HEAD
coova-chilli

    1: /* 
    2:  * Tunnel Interface Functions.
    3:  * Copyright (C) 2002, 2003, 2004 Mondru AB.
    4:  * Copyright (c) 2006-2007 David Bird <david@coova.com>
    5:  * 
    6:  * The contents of this file may be used under the terms of the GNU
    7:  * General Public License Version 2, provided that the above copyright
    8:  * notice and this permission notice is included in all copies or
    9:  * substantial portions of the software.
   10:  * 
   11:  */
   12: 
   13: /*
   14:  *  A tunnel is the back-haul link which chilli sends traffic. Typically,
   15:  *  this is a single tun/tap interface allowing chilli to simply pass on
   16:  *  packets to the kernel for processing (iptables) and routing. Without the
   17:  *  tun/tap interface, chilli must decide for itself how to route traffic,
   18:  *  maintaining a socket into each back-haul interface. One or more tunnels
   19:  *  are required.
   20:  *
   21:  */
   22: 
   23: #include "system.h"
   24: #include "tun.h"
   25: #include "ippool.h"
   26: #include "radius.h"
   27: #include "radius_wispr.h"
   28: #include "radius_chillispot.h"
   29: #include "redir.h"
   30: #include "syserr.h"
   31: #include "dhcp.h"
   32: #include "cmdline.h"
   33: #include "chilli.h"
   34: #include "options.h"
   35: #include "net.h"
   36: 
   37: #define inaddr(x)    (((struct sockaddr_in *)&ifr->x)->sin_addr)
   38: #define inaddr2(p,x) (((struct sockaddr_in *)&(p)->x)->sin_addr)
   39: 
   40: int tun_discover(struct tun_t *this) {
   41:   net_interface netif;
   42:   struct ifconf ic;
   43:   int fd, len, i;
   44: 
   45:   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
   46:     log_err(errno, "socket() failed");
   47:     return -1;
   48:   }
   49: 
   50:   ic.ifc_buf=0;
   51:   ic.ifc_len=0;
   52: 
   53:   if (ioctl(fd, SIOCGIFCONF, &ic) < 0) {
   54:     log_err(errno, "ioctl(SIOCGIFCONF)");
   55:     close(fd);
   56:     return -1;
   57:   }
   58: 
   59:   ic.ifc_buf = calloc((size_t)ic.ifc_len, 1);
   60:   if (ioctl(fd, SIOCGIFCONF, &ic) < 0) {
   61:     log_err(errno, "ioctl(SIOCGIFCONF)");
   62:     close(fd);
   63:     return -1;
   64:   }
   65:     
   66:   len = (ic.ifc_len/sizeof(struct ifreq));
   67: 
   68:   for (i=0; i<len; ++i) {
   69:     struct ifreq *ifr = (struct ifreq *)&ic.ifc_req[i];
   70:     memset(&netif, 0, sizeof(netif));
   71: 
   72: 
   73:     /* device name and address */
   74:     strncpy(netif.devname, ifr->ifr_name, sizeof(netif.devname));
   75:     netif.address = inaddr(ifr_addr);
   76: 
   77:     log_dbg("Interface: %s", ifr->ifr_name);
   78:     log_dbg("\tIP Address:\t%s", inet_ntoa(inaddr(ifr_addr)));
   79: 
   80: 
   81:     /* netmask */
   82:     if (-1 < ioctl(fd, SIOCGIFNETMASK, (caddr_t)ifr)) {
   83: 
   84:       netif.netmask = inaddr(ifr_addr);
   85:       log_dbg("\tNetmask:\t%s", inet_ntoa(inaddr(ifr_addr)));
   86: 
   87:     } else log_err(errno, "ioctl(SIOCGIFNETMASK)");
   88: 
   89: 
   90:     /* hardware address */
   91: #ifdef SIOCGIFHWADDR
   92:     if (-1 < ioctl(fd, SIOCGIFHWADDR, (caddr_t)ifr)) {
   93:       switch (ifr->ifr_hwaddr.sa_family) {
   94:       case  ARPHRD_NETROM:  
   95:       case  ARPHRD_ETHER:  
   96:       case  ARPHRD_PPP:
   97:       case  ARPHRD_EETHER:  
   98:       case  ARPHRD_IEEE802: 
   99: 	{
  100: 	  unsigned char *u = (unsigned char *)&ifr->ifr_addr.sa_data;
  101: 
  102: 	  memcpy(netif.hwaddr, u, 6);
  103: 
  104: 	  log_dbg("\tHW Address:\t%2.2X-%2.2X-%2.2X-%2.2X-%2.2X-%2.2x",
  105: 		  u[0], u[1], u[2], u[3], u[4], u[5]);
  106: 	}
  107: 	break;
  108:       }
  109:     } else log_err(errno, "ioctl(SIOCGIFHWADDR)");
  110: #else
  111: #ifdef SIOCGENADDR
  112:     if (-1 < ioctl(fd, SIOCGENADDR, (caddr_t)ifr)) {
  113:       unsigned char *u = (unsigned char *)&ifr->ifr_enaddr;
  114: 
  115:       memcpy(netif.hwaddr, u, 6);
  116: 
  117:       log_dbg("\tHW Address:\t%2.2X-%2.2X-%2.2X-%2.2X-%2.2X-%2.2x",
  118: 		  u[0], u[1], u[2], u[3], u[4], u[5]);
  119:     } else log_err(errno, "ioctl(SIOCGENADDR)");
  120: #else
  121: #warning Do not know how to find interface hardware address
  122: #endif /* SIOCGENADDR */
  123: #endif /* SIOCGIFHWADDR */
  124: 
  125: 
  126:     /* flags */
  127:     if (-1 < ioctl(fd, SIOCGIFFLAGS, (caddr_t)ifr)) {
  128: 
  129:       netif.devflags = ifr->ifr_flags;
  130: 
  131:     } else log_err(errno, "ioctl(SIOCGIFFLAGS)");
  132: 
  133: 
  134:     /* point-to-point gateway */
  135:     if (netif.devflags & IFF_POINTOPOINT) {
  136:       if (-1 < ioctl(fd, SIOCGIFDSTADDR, (caddr_t)ifr)) {
  137: 
  138: 	netif.gateway = inaddr(ifr_addr);
  139: 	log_dbg("\tPoint-to-Point:\t%s", inet_ntoa(inaddr(ifr_dstaddr)));
  140: 
  141:       } else log_err(errno, "ioctl(SIOCGIFDSTADDR)");
  142:     }
  143: 
  144: 
  145:     /* broadcast address */
  146:     if (netif.devflags & IFF_BROADCAST) {
  147:       if (-1 < ioctl(fd, SIOCGIFBRDADDR, (caddr_t)ifr)) {
  148: 	
  149: 	netif.broadcast = inaddr(ifr_addr);
  150: 	log_dbg("\tBroadcast:\t%s", inet_ntoa(inaddr(ifr_addr)));
  151: 	
  152:       } else log_err(errno, "ioctl(SIOCGIFBRDADDR)");
  153:     }
  154: 
  155: 
  156:     /* mtu */
  157:     if (-1 < ioctl(fd, SIOCGIFMTU, (caddr_t)ifr)) {
  158:       
  159:       netif.mtu = ifr->ifr_mtu;
  160:       log_dbg("\tMTU:      \t%u",  ifr->ifr_mtu);
  161:       
  162:     } else log_err(errno, "ioctl(SIOCGIFMTU)");
  163:     
  164: 
  165:     /* if (0 == ioctl(fd, SIOCGIFMETRIC, ifr)) */
  166: 
  167:     if (netif.address.s_addr == htonl(INADDR_LOOPBACK) ||
  168:         netif.address.s_addr == INADDR_ANY ||
  169:         netif.address.s_addr == INADDR_NONE)
  170:       continue;
  171: 
  172:     else {
  173:       net_interface *newif = tun_nextif(tun);
  174:       if (newif) {
  175: 	memcpy(newif, &netif, sizeof(netif));
  176: 	net_open(newif);
  177: 
  178: 	if (!strcmp(options.routeif, netif.devname))
  179: 	  tun->routeidx = newif->idx;
  180:       } else {
  181: 	log_dbg("no room for interface %s", netif.devname);
  182:       }
  183:     }
  184:   }
  185: 
  186:   close(fd);
  187:   return 0;
  188: }
  189: 
  190: net_interface * tun_nextif(struct tun_t *tun) {
  191:   net_interface *netif;
  192: 
  193:   if (tun->_interface_count == TUN_MAX_INTERFACES)
  194:     return 0;
  195: 
  196:   netif = &tun->_interfaces[tun->_interface_count];
  197:   netif->idx = tun->_interface_count;
  198: 
  199:   tun->_interface_count++;
  200: 
  201:   return netif;
  202: }
  203: 
  204: int tun_name2idx(struct tun_t *tun, char *name) {
  205:   int i;
  206: 
  207:   for (i=0; i<tun->_interface_count; i++) 
  208:     if (!strcmp(name, tun->_interfaces[i].devname))
  209:       return i;
  210: 
  211:   return 0; /* tun/tap index */
  212: }
  213: 
  214: #if defined(__linux__)
  215: 
  216: int tun_nlattr(struct nlmsghdr *n, int nsize, int type, void *d, size_t dlen) {
  217:   size_t len = RTA_LENGTH(dlen);
  218:   size_t alen = NLMSG_ALIGN(n->nlmsg_len);
  219:   struct rtattr *rta = (struct rtattr*) (((void*)n) + alen);
  220:   if (alen + len > nsize)
  221:     return -1;
  222:   rta->rta_len = len;
  223:   rta->rta_type = type;
  224:   memcpy(RTA_DATA(rta), d, dlen);
  225:   n->nlmsg_len = alen + len;
  226:   return 0;
  227: }
  228: 
  229: int tun_gifindex(struct tun_t *this, int *index) {
  230:   struct ifreq ifr;
  231:   int fd;
  232: 
  233:   memset (&ifr, '\0', sizeof (ifr));
  234:   ifr.ifr_addr.sa_family = AF_INET;
  235:   ifr.ifr_dstaddr.sa_family = AF_INET;
  236:   ifr.ifr_netmask.sa_family = AF_INET;
  237:   strncpy(ifr.ifr_name, tuntap(this).devname, IFNAMSIZ);
  238:   ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
  239:   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  240:     log_err(errno, "socket() failed");
  241:   }
  242:   if (ioctl(fd, SIOCGIFINDEX, &ifr)) {
  243:     log_err(errno,"ioctl() failed");
  244:     close(fd);
  245:     return -1;
  246:   }
  247:   close(fd);
  248:   *index = ifr.ifr_ifindex;
  249:   return 0;
  250: }
  251: #endif
  252: 
  253: int tun_addaddr(struct tun_t *this, struct in_addr *addr,
  254: 		struct in_addr *dstaddr, struct in_addr *netmask) {
  255: 
  256: #if defined(__linux__)
  257:   struct {
  258:     struct nlmsghdr 	n;
  259:     struct ifaddrmsg 	i;
  260:     char buf[TUN_NLBUFSIZE];
  261:   } req;
  262:   
  263:   struct sockaddr_nl local;
  264:   size_t addr_len;
  265:   int fd;
  266:   int status;
  267:   
  268:   struct sockaddr_nl nladdr;
  269:   struct iovec iov;
  270:   struct msghdr msg;
  271: 
  272:   if (!this->addrs) /* Use ioctl for first addr to make ping work */
  273:     return tun_setaddr(this, addr, dstaddr, netmask);
  274: 
  275:   memset(&req, 0, sizeof(req));
  276:   req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
  277:   req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
  278:   req.n.nlmsg_type = RTM_NEWADDR;
  279:   req.i.ifa_family = AF_INET;
  280:   req.i.ifa_prefixlen = 32; /* 32 FOR IPv4 */
  281:   req.i.ifa_flags = 0;
  282:   req.i.ifa_scope = RT_SCOPE_HOST; /* TODO or 0 */
  283: 
  284:   if (tun_gifindex(this, &req.i.ifa_index)) {
  285:     log_err(errno,"tun_gifindex() failed");
  286:     return -1;
  287:   }
  288: 
  289:   tun_nlattr(&req.n, sizeof(req), IFA_ADDRESS, addr, sizeof(addr));
  290:   tun_nlattr(&req.n, sizeof(req), IFA_LOCAL, dstaddr, sizeof(dstaddr));
  291: 
  292:   if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
  293:     log_err(errno,"socket() failed");
  294:     return -1;
  295:   }
  296: 
  297:   memset(&local, 0, sizeof(local));
  298:   local.nl_family = AF_NETLINK;
  299:   local.nl_groups = 0;
  300:   
  301:   if (bind(fd, (struct sockaddr*)&local, sizeof(local)) < 0) {
  302:     log_err(errno, "bind() failed");
  303:     close(fd);
  304:     return -1;
  305:   }
  306: 
  307:   addr_len = sizeof(local);
  308:   if (getsockname(fd, (struct sockaddr*)&local, (socklen_t *) &addr_len) < 0) {
  309:     log_err(errno, "getsockname() failed");
  310:     close(fd);
  311:     return -1;
  312:   }
  313: 
  314:   if (addr_len != sizeof(local)) {
  315:     log_err(0, "Wrong address length %d", addr_len);
  316:     close(fd);
  317:     return -1;
  318:   }
  319: 
  320:   if (local.nl_family != AF_NETLINK) {
  321:     log_err(0, "Wrong address family %d", local.nl_family);
  322:     close(fd);
  323:     return -1;
  324:   }
  325:   
  326:   iov.iov_base = (void*)&req.n;
  327:   iov.iov_len = req.n.nlmsg_len;
  328: 
  329:   msg.msg_name = (void*)&nladdr;
  330:   msg.msg_namelen = sizeof(nladdr),
  331:   msg.msg_iov = &iov;
  332:   msg.msg_iovlen = 1;
  333:   msg.msg_control = NULL;
  334:   msg.msg_controllen = 0;
  335:   msg.msg_flags = 0;
  336: 
  337:   memset(&nladdr, 0, sizeof(nladdr));
  338:   nladdr.nl_family = AF_NETLINK;
  339:   nladdr.nl_pid = 0;
  340:   nladdr.nl_groups = 0;
  341: 
  342:   req.n.nlmsg_seq = 0;
  343:   req.n.nlmsg_flags |= NLM_F_ACK;
  344: 
  345:   status = sendmsg(fd, &msg, 0); 
  346: 
  347:   dev_set_flags(tuntap(this).devname, IFF_UP | IFF_RUNNING); 
  348: 
  349:   close(fd);
  350:   this->addrs++;
  351: 
  352:   return 0;
  353: 
  354: #elif defined (__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
  355: 
  356:   int fd;
  357:   struct ifaliasreq      areq;
  358: 
  359:   /* TODO: Is this needed on FreeBSD? */
  360:   if (!this->addrs) /* Use ioctl for first addr to make ping work */
  361:     return tun_setaddr(this, addr, dstaddr, netmask); /* TODO dstaddr */
  362: 
  363:   memset(&areq, 0, sizeof(areq));
  364: 
  365:   /* Set up interface name */
  366:   strncpy(areq.ifra_name, tuntap(this).devname, IFNAMSIZ);
  367:   areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
  368: 
  369:   ((struct sockaddr_in*) &areq.ifra_addr)->sin_family = AF_INET;
  370:   ((struct sockaddr_in*) &areq.ifra_addr)->sin_len = sizeof(areq.ifra_addr);
  371:   ((struct sockaddr_in*) &areq.ifra_addr)->sin_addr.s_addr = addr->s_addr;
  372: 
  373:   ((struct sockaddr_in*) &areq.ifra_mask)->sin_family = AF_INET;
  374:   ((struct sockaddr_in*) &areq.ifra_mask)->sin_len    = sizeof(areq.ifra_mask);
  375:   ((struct sockaddr_in*) &areq.ifra_mask)->sin_addr.s_addr = netmask->s_addr;
  376: 
  377:   /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
  378:   ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_family = AF_INET;
  379:   ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_len = sizeof(areq.ifra_broadaddr);
  380:   ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_addr.s_addr = dstaddr->s_addr;
  381: 
  382:   /* Create a channel to the NET kernel. */
  383:   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  384:     log_err(errno,
  385: 	    "socket() failed");
  386:     return -1;
  387:   }
  388:   
  389:   if (ioctl(fd, SIOCAIFADDR, (void *) &areq) < 0) {
  390:     log_err(errno,
  391: 	    "ioctl(SIOCAIFADDR) failed");
  392:     close(fd);
  393:     return -1;
  394:   }
  395: 
  396:   close(fd);
  397:   this->addrs++;
  398:   return 0;
  399: 
  400: #elif defined (__sun__)
  401:   
  402:   if (!this->addrs) /* Use ioctl for first addr to make ping work */
  403:     return tun_setaddr(this, addr, dstaddr, netmask);
  404:   
  405:   log_err(errno, "Setting multiple addresses not possible on Solaris");
  406:   return -1;
  407: 
  408: #else
  409: #error  "Unknown platform!"
  410: #endif
  411:   
  412: }
  413: 
  414: 
  415: int tun_setaddr(struct tun_t *this, struct in_addr *addr, struct in_addr *dstaddr, struct in_addr *netmask) {
  416:   net_set_address(&tuntap(this), addr, dstaddr, netmask);
  417:   
  418: #if defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
  419:   net_add_route(dstaddr, addr, netmask);
  420:   this->routes = 1;
  421: #endif
  422: 
  423:   return 0;
  424: }
  425: 
  426: static int tuntap_interface(struct _net_interface *netif) {
  427: #if defined(__linux__)
  428:   struct ifreq ifr;
  429: 
  430: #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
  431:   char devname[IFNAMSIZ+5]; /* "/dev/" + ifname */
  432:   int devnum;
  433:   struct ifaliasreq areq;
  434:   int fd;
  435: 
  436: #elif defined(__sun__)
  437:   int if_fd, ppa = -1;
  438:   static int ip_fd = 0;
  439:   int muxid;
  440:   struct ifreq ifr;
  441: 
  442: #else
  443: #error  "Unknown platform!"
  444: #endif
  445: 
  446: 
  447: #if defined(__linux__)
  448:   /* Open the actual tun device */
  449:   if ((netif->fd  = open("/dev/net/tun", O_RDWR)) < 0) {
  450:     log_err(errno, "open() failed");
  451:     return -1;
  452:   }
  453:   
  454:   /* Set device flags. For some weird reason this is also the method
  455:      used to obtain the network interface name */
  456:   memset(&ifr, 0, sizeof(ifr));
  457:   ifr.ifr_flags = (options.usetap ? IFF_TAP : IFF_TUN) | IFF_NO_PI; /* Tun device, no packet info */
  458: #if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
  459:   ifr.ifr_flags |= IFF_ONE_QUEUE;
  460: #endif
  461: 
  462:   if (options.tundev && *options.tundev && 
  463:       strcmp(options.tundev, "tap") && strcmp(options.tundev, "tun"))
  464:     strncpy(ifr.ifr_name, options.tundev, IFNAMSIZ);
  465: 
  466:   if (ioctl(netif->fd, TUNSETIFF, (void *) &ifr) < 0) {
  467:     log_err(errno, "ioctl() failed");
  468:     close(netif->fd);
  469:     return -1;
  470:   } 
  471:   
  472: #if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
  473:   {
  474:     struct ifreq nifr;
  475:     int nfd;
  476:     memset(&nifr, 0, sizeof(nifr));
  477:     if ((nfd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0) {
  478:       strncpy(nifr.ifr_name, ifr.ifr_name, IFNAMSIZ);
  479:       nifr.ifr_qlen = options.txqlen;
  480: 
  481:       if (ioctl(nfd, SIOCSIFTXQLEN, (void *) &nifr) >= 0) 
  482: 	log_info("TX queue length set to %d", options.txqlen);
  483:       else 
  484: 	log_err(errno, "Cannot set tx queue length on %s", ifr.ifr_name);
  485: 
  486:       close (nfd);
  487:     } else {
  488:       log_err(errno, "Cannot open socket on %s", ifr.ifr_name);
  489:     }
  490:   }
  491: #endif
  492:   
  493:   strncpy(netif->devname, ifr.ifr_name, IFNAMSIZ);
  494:   netif->devname[IFNAMSIZ-1] = 0;
  495:   
  496:   ioctl(netif->fd, TUNSETNOCSUM, 1); /* Disable checksums */
  497: 
  498:   /* Get the MAC address of our tap interface */
  499:   if (options.usetap) {
  500:     int fd;
  501:     netif->flags |= NET_ETHHDR;
  502:     if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0) {
  503:       memset(&ifr, 0, sizeof(ifr));
  504:       strncpy(ifr.ifr_name, netif->devname, IFNAMSIZ);
  505:       if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
  506: 	log_err(errno, "ioctl(d=%d, request=%d) failed", fd, SIOCGIFHWADDR);
  507:       }
  508:       memcpy(netif->hwaddr, ifr.ifr_hwaddr.sa_data, PKT_ETH_ALEN);
  509:       log_dbg("tap-mac: %s %.2X-%.2X-%.2X-%.2X-%.2X-%.2X", ifr.ifr_name,
  510: 	      netif->hwaddr[0],netif->hwaddr[1],netif->hwaddr[2],
  511: 	      netif->hwaddr[3],netif->hwaddr[4],netif->hwaddr[5]);
  512:       close(fd);
  513:     }
  514:   }
  515: 
  516:   return 0;
  517:   
  518: #elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
  519: 
  520:   /* Find suitable device */
  521:   for (devnum = 0; devnum < 255; devnum++) { /* TODO 255 */ 
  522:     snprintf(devname, sizeof(devname), "/dev/tun%d", devnum);
  523:     devname[sizeof(devname)] = 0;
  524:     if ((netif->fd = open(devname, O_RDWR)) >= 0) break;
  525:     if (errno != EBUSY) break;
  526:   } 
  527:   if (netif->fd < 0) {
  528:     log_err(errno, "Can't find tunnel device");
  529:     return -1;
  530:   }
  531: 
  532:   snprintf(netif->devname, sizeof(netif->devname), "tun%d", devnum);
  533:   netif->devname[sizeof(netif->devname)-1] = 0;
  534: 
  535:   /* The tun device we found might have "old" IP addresses allocated */
  536:   /* We need to delete those. This problem is not present on Linux */
  537: 
  538:   memset(&areq, 0, sizeof(areq));
  539: 
  540:   /* Set up interface name */
  541:   strncpy(areq.ifra_name, netif->devname, IFNAMSIZ);
  542:   areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
  543: 
  544:   /* Create a channel to the NET kernel. */
  545:   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  546:     log_err(errno,
  547: 	    "socket() failed");
  548:     return -1;
  549:   }
  550:   
  551:   /* Delete any IP addresses until SIOCDIFADDR fails */
  552:   while (ioctl(fd, SIOCDIFADDR, (void *) &areq) != -1);
  553: 
  554:   close(fd);
  555:   return 0;
  556: 
  557: #elif defined(__sun__)
  558: 
  559:   if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){
  560:     log_err(errno, "Can't open /dev/udp");
  561:     return -1;
  562:   }
  563:   
  564:   if( (netif->fd = open("/dev/tun", O_RDWR, 0)) < 0){
  565:     log_err(errno, "Can't open /dev/tun");
  566:     return -1;
  567:   }
  568:   
  569:   /* Assign a new PPA and get its unit number. */
  570:   if( (ppa = ioctl(netif->fd, TUNNEWPPA, -1)) < 0){
  571:     log_err(errno, "Can't assign new interface");
  572:     return -1;
  573:   }
  574:   
  575:   if( (if_fd = open("/dev/tun", O_RDWR, 0)) < 0){
  576:     log_err(errno, "Can't open /dev/tun (2)");
  577:     return -1;
  578:   }
  579:   if(ioctl(if_fd, I_PUSH, "ip") < 0){
  580:     log_err(errno, "Can't push IP module");
  581:     return -1;
  582:   }
  583:   
  584:   /* Assign ppa according to the unit number returned by tun device */
  585:   if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){
  586:     log_err(errno, "Can't set PPA %d", ppa);
  587:     return -1;
  588:   }
  589: 
  590:   /* Link the two streams */
  591:   if ((muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0) {
  592:     log_err(errno, "Can't link TUN device to IP");
  593:     return -1;
  594:   }
  595: 
  596:   close (if_fd);
  597:   
  598:   snprintf(netif->devname, sizeof(netif->devname), "tun%d", ppa);
  599:   netif->devname[sizeof(netif->devname)-1] = 0;
  600: 
  601:   memset(&ifr, 0, sizeof(ifr));
  602:   strcpy(ifr.ifr_name, netif->devname);
  603:   ifr.ifr_ip_muxid = muxid;
  604:   
  605:   if (ioctl(ip_fd, SIOCSIFMUXID, &ifr) < 0) {
  606:     ioctl(ip_fd, I_PUNLINK, muxid);
  607:     log_err(errno, "Can't set multiplexor id");
  608:     return -1;
  609:   }
  610:   
  611:   /*  if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0)
  612:       msg (M_ERR, "Set file descriptor to non-blocking failed"); */
  613: 
  614:   return 0;
  615: 
  616: #else
  617: #error  "Unknown platform!"
  618: #endif
  619: 
  620: }
  621: 
  622: int tun_new(struct tun_t **ptun) {
  623:   struct tun_t *tun;
  624: 
  625:   if (!(tun = *ptun = calloc(1, sizeof(struct tun_t)))) {
  626:     log_err(errno, "calloc() failed");
  627:     return EOF;
  628:   }
  629: 
  630:   tuntap_interface(tun_nextif(tun));
  631: 
  632:   if (options.routeif) {
  633:     tun_discover(tun);
  634:   }
  635: 
  636:   return 0;
  637: }
  638: 
  639: int tun_free(struct tun_t *tun) {
  640: 
  641:   if (tun->routes) {
  642: #warning fix this
  643:     /*XXX: todo! net_delete_route(&tuntap(tun)); */
  644:   }
  645: 
  646:   tun_close(tun);
  647: 
  648:   /* TODO: For solaris we need to unlink streams */
  649: 
  650:   free(tun);
  651:   return 0;
  652: }
  653: 
  654: int tun_set_cb_ind(struct tun_t *this, 
  655: 		   int (*cb_ind) (struct tun_t *tun, void *pack, size_t len, int idx)) {
  656:   this->cb_ind = cb_ind;
  657:   return 0;
  658: }
  659: 
  660: int tun_decaps(struct tun_t *this, int idx) {
  661: 
  662: #if defined(__linux__) || defined (__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
  663:   unsigned char buffer[PACKET_MAX];
  664:   ssize_t status;
  665: 
  666:   if ((status = net_read(&tun(this, idx), buffer, sizeof(buffer))) <= 0) {
  667:     log_err(errno, "read() failed");
  668:     return -1;
  669:   }
  670: 
  671:   if (this->debug)  
  672:     log_dbg("tun_decaps(%d) %s",status,tun(tun,idx).devname);
  673: 
  674:   if (0) { /* if we wanted to do nat'ing, it would could be done here */
  675:     struct in_addr a;
  676:     struct pkt_iphdr_t *iph = (struct pkt_iphdr_t *)buffer;
  677:     inet_aton("10.1.0.1", &a);
  678:     iph->daddr = a.s_addr;
  679:     chksum(iph);
  680:   }
  681:   
  682:    if (this->cb_ind)
  683: #if defined (__OpenBSD__)
  684:     /* tun interface adds 4 bytes to front of packet under OpenBSD */
  685:      return this->cb_ind(this, buffer+4, status, idx);
  686: #else
  687:      return this->cb_ind(this, buffer, status, idx);
  688: #endif
  689: 
  690:   return 0;
  691: 
  692: #elif defined (__sun__)
  693:   unsigned char buffer[PACKET_MAX];
  694:   struct strbuf sbuf;
  695:   int f = 0;
  696:   
  697:   sbuf.maxlen = PACKET_MAX;      
  698:   sbuf.buf = buffer;
  699:   if (getmsg(tun(this, idx).fd, NULL, &sbuf, &f) < 0) {
  700:     log_err(errno, "getmsg() failed");
  701:     return -1;
  702:   }
  703: 
  704:   if (this->cb_ind)
  705:     return this->cb_ind(this, &packet, sbuf.len);
  706: 
  707:   return 0;
  708:   
  709: #endif
  710: }
  711: 
  712: static uint32_t dnatip[1024];
  713: static uint16_t dnatport[1024];
  714: 
  715: int tun_encaps(struct tun_t *tun, void *pack, size_t len, int idx) {
  716: 
  717:   if (tun(tun, idx).flags & NET_ETHHDR) {
  718: 
  719:     struct pkt_ethhdr_t *ethh = (struct pkt_ethhdr_t *)pack;
  720:     /*memcpy(ethh->src, tun->tap_hwaddr, PKT_ETH_ALEN); */
  721: 
  722:     /** XXX **/
  723:     if (1) {
  724:       ethh->src[0]=0x00;
  725:       ethh->src[1]=0x17;
  726:       ethh->src[2]=0x3f;
  727:       ethh->src[3]=0x99;
  728:       ethh->src[4]=0xf4;
  729:       ethh->src[5]=0x46;
  730: 
  731:       ethh->dst[0]=0x00;
  732:       ethh->dst[1]=0x14;
  733:       ethh->dst[2]=0xBF;
  734:       ethh->dst[3]=0xE2;
  735:       ethh->dst[4]=0xC1;
  736:       ethh->dst[5]=0x75;
  737:     }
  738: 
  739:     log_dbg("writing to tun/tap src=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x dst=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
  740: 	    ethh->src[0],ethh->src[1],ethh->src[2],ethh->src[3],ethh->src[4],ethh->src[5],
  741: 	    ethh->dst[0],ethh->dst[1],ethh->dst[2],ethh->dst[3],ethh->dst[4],ethh->dst[5]);
  742:   } else {
  743:     pack += PKT_ETH_HLEN;
  744:     len  -= PKT_ETH_HLEN;
  745:   }
  746: 
  747:   if (tun->debug) 
  748:     log_dbg("tun_encaps(%d) %s",len,tun(tun,idx).devname);
  749: 
  750: #if defined (__OpenBSD__)
  751: 
  752:   unsigned char buffer[PACKET_MAX+4];
  753: 
  754:   /* Can we user writev here to be more efficient??? */
  755:   *((uint32_t *)(&buffer))=htonl(AF_INET);
  756:   memcpy(&buffer[4], pack, PACKET_MAX);
  757: 
  758:   return net_write(&tun(tun, idx), buffer, len+4);
  759: 
  760: #elif defined(__linux__) || defined (__FreeBSD__) || defined (__APPLE__) || defined (__NetBSD__)
  761: 
  762:   if (0) { /* if we wanted to do nat'ing we could do it here */
  763:     struct in_addr a;
  764:     struct pkt_iphdr_t *iph = (struct pkt_iphdr_t *)pack;
  765:     inet_aton("172.30.97.2", &a);
  766:     iph->saddr = a.s_addr;
  767:     chksum(iph);
  768:   }
  769: 
  770:   return net_write(&tun(tun, idx), pack, len);
  771: 
  772: #elif defined (__sun__)
  773: 
  774:   struct strbuf sbuf;
  775:   sbuf.len = len;      
  776:   sbuf.buf = pack;
  777:   return putmsg(tun(tun, idx).fd, NULL, &sbuf, 0);
  778: 
  779: #endif
  780: }
  781: 
  782: int tun_runscript(struct tun_t *tun, char* script) {
  783:   char saddr[TUN_ADDRSIZE];
  784:   char smask[TUN_ADDRSIZE];
  785:   char b[TUN_ADDRSIZE];
  786:   struct in_addr net;
  787:   int status;
  788: 
  789:   net.s_addr = tuntap(tun).address.s_addr & tuntap(tun).netmask.s_addr;
  790: 
  791:   if ((status = fork()) < 0) {
  792:     log_err(errno, "fork() returned -1!");
  793:     return 0;
  794:   }
  795:   
  796:   if (status > 0) { /* Parent */
  797:     return 0;
  798:   }
  799:   
  800: /*
  801: #ifdef HAVE_CLEARENV
  802:   if (clearenv() != 0) {
  803:     log_err(errno,
  804: 	    "clearenv() did not return 0!");
  805:     exit(0);
  806:   }
  807: #endif
  808: */
  809:   
  810:   if (setenv("DEV", tuntap(tun).devname, 1) != 0) {
  811:     log_err(errno, "setenv() did not return 0!");
  812:     exit(0);
  813:   }
  814: 
  815:   strncpy(saddr, inet_ntoa(tuntap(tun).address), sizeof(saddr));
  816:   saddr[sizeof(saddr)-1] = 0;
  817:   if (setenv("ADDR", saddr, 1 ) != 0) {
  818:     log_err(errno, "setenv() did not return 0!");
  819:     exit(0);
  820:   }
  821: 
  822:   strncpy(smask, inet_ntoa(tuntap(tun).netmask), sizeof(smask));
  823:   smask[sizeof(smask)-1] = 0;
  824:   if (setenv("MASK", smask, 1) != 0) {
  825:     log_err(errno, "setenv() did not return 0!");
  826:     exit(0);
  827:   }
  828: 
  829:   strncpy(b, inet_ntoa(net), sizeof(b));
  830:   b[sizeof(b)-1] = 0;
  831:   if (setenv("NET", b, 1 ) != 0) {
  832:     log_err(errno, "setenv() did not return 0!");
  833:     exit(0);
  834:   }
  835: 
  836:   snprintf(b, sizeof(b), "%d", options.uamport);
  837:   if (setenv("UAMPORT", b, 1 ) != 0) {
  838:     log_err(errno, "setenv() did not return 0!");
  839:     exit(0);
  840:   }
  841: 
  842:   snprintf(b, sizeof(b), "%d", options.uamuiport);
  843:   if (setenv("UAMUIPORT", b, 1 ) != 0) {
  844:     log_err(errno, "setenv() did not return 0!");
  845:     exit(0);
  846:   }
  847: 
  848:   if (setenv("DHCPIF", options.dhcpif ? options.dhcpif : "", 1 ) != 0) {
  849:     log_err(errno, "setenv() did not return 0!");
  850:     exit(0);
  851:   }
  852: 
  853:   if (execl(script, script, tuntap(tun).devname, saddr, smask, (char *) 0) != 0) {
  854:     log_err(errno, "execl() did not return 0!");
  855:     exit(0);
  856:   }
  857:   
  858:   exit(0);
  859: }
  860: 
  861: 
  862: /* Currently unused 
  863: int tun_addroute2(struct tun_t *this,
  864: 		  struct in_addr *dst,
  865: 		  struct in_addr *gateway,
  866: 		  struct in_addr *mask) {
  867:   
  868:   struct {
  869:     struct nlmsghdr 	n;
  870:     struct rtmsg 	r;
  871:     char buf[TUN_NLBUFSIZE];
  872:   } req;
  873:   
  874:   struct sockaddr_nl local;
  875:   int addr_len;
  876:   int fd;
  877:   int status;
  878:   struct sockaddr_nl nladdr;
  879:   struct iovec iov;
  880:   struct msghdr msg;
  881: 
  882:   memset(&req, 0, sizeof(req));
  883:   req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
  884:   req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
  885:   req.n.nlmsg_type = RTM_NEWROUTE;
  886:   req.r.rtm_family = AF_INET;
  887:   req.r.rtm_table  = RT_TABLE_MAIN;
  888:   req.r.rtm_protocol = RTPROT_BOOT;
  889:   req.r.rtm_scope  = RT_SCOPE_UNIVERSE;
  890:   req.r.rtm_type  = RTN_UNICAST;
  891:   tun_nlattr(&req.n, sizeof(req), RTA_DST, dst, 4);
  892:   tun_nlattr(&req.n, sizeof(req), RTA_GATEWAY, gateway, 4);
  893:   
  894:   if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
  895:     sys_err(LOG_ERR, __FILE__, __LINE__, errno,
  896: 	    "socket() failed");
  897:     return -1;
  898:   }
  899: 
  900:   memset(&local, 0, sizeof(local));
  901:   local.nl_family = AF_NETLINK;
  902:   local.nl_groups = 0;
  903:   
  904:   if (bind(fd, (struct sockaddr*)&local, sizeof(local)) < 0) {
  905:     sys_err(LOG_ERR, __FILE__, __LINE__, errno,
  906: 	    "bind() failed");
  907:     close(fd);
  908:     return -1;
  909:   }
  910: 
  911:   addr_len = sizeof(local);
  912:   if (getsockname(fd, (struct sockaddr*)&local, &addr_len) < 0) {
  913:     sys_err(LOG_ERR, __FILE__, __LINE__, errno,
  914: 	    "getsockname() failed");
  915:     close(fd);
  916:     return -1;
  917:   }
  918: 
  919:   if (addr_len != sizeof(local)) {
  920:     sys_err(LOG_ERR, __FILE__, __LINE__, 0,
  921: 	    "Wrong address length %d", addr_len);
  922:     close(fd);
  923:     return -1;
  924:   }
  925: 
  926:   if (local.nl_family != AF_NETLINK) {
  927:     sys_err(LOG_ERR, __FILE__, __LINE__, 0,
  928: 	    "Wrong address family %d", local.nl_family);
  929:     close(fd);
  930:     return -1;
  931:   }
  932:   
  933:   iov.iov_base = (void*)&req.n;
  934:   iov.iov_len = req.n.nlmsg_len;
  935: 
  936:   msg.msg_name = (void*)&nladdr;
  937:   msg.msg_namelen = sizeof(nladdr),
  938:   msg.msg_iov = &iov;
  939:   msg.msg_iovlen = 1;
  940:   msg.msg_control = NULL;
  941:   msg.msg_controllen = 0;
  942:   msg.msg_flags = 0;
  943: 
  944:   memset(&nladdr, 0, sizeof(nladdr));
  945:   nladdr.nl_family = AF_NETLINK;
  946:   nladdr.nl_pid = 0;
  947:   nladdr.nl_groups = 0;
  948: 
  949:   req.n.nlmsg_seq = 0;
  950:   req.n.nlmsg_flags |= NLM_F_ACK;
  951: 
  952:   status = sendmsg(fd, &msg, 0);  * TODO: Error check *
  953:   close(fd);
  954:   return 0;
  955: }
  956: */
  957: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>