Annotation of embedaddon/coova-chilli/src/tun.c, revision 1.1.1.1

1.1       misho       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>