Annotation of embedaddon/strongswan/src/libstrongswan/networking/tun_device.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2012 Tobias Brunner
                      3:  * Copyright (C) 2012 Giuliano Grassi
                      4:  * Copyright (C) 2012 Ralf Sager
                      5:  * HSR Hochschule fuer Technik Rapperswil
                      6:  * Copyright (C) 2012 Martin Willi
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include "tun_device.h"
                     20: 
                     21: #include <utils/debug.h>
                     22: #include <threading/thread.h>
                     23: 
                     24: #if defined(__APPLE__)
                     25: #include "TargetConditionals.h"
                     26: #if !TARGET_OS_OSX
                     27: #define TUN_DEVICE_NOT_SUPPORTED
                     28: #endif
                     29: #elif !defined(__linux__) && !defined(HAVE_NET_IF_TUN_H)
                     30: #define TUN_DEVICE_NOT_SUPPORTED
                     31: #endif
                     32: 
                     33: #ifdef TUN_DEVICE_NOT_SUPPORTED
                     34: 
                     35: tun_device_t *tun_device_create(const char *name_tmpl)
                     36: {
                     37:        DBG1(DBG_LIB, "TUN devices are not supported");
                     38:        return NULL;
                     39: }
                     40: 
                     41: #else /* TUN devices supported */
                     42: 
                     43: #include <errno.h>
                     44: #include <fcntl.h>
                     45: #include <netinet/in.h>
                     46: #include <string.h>
                     47: #include <sys/ioctl.h>
                     48: #include <sys/types.h>
                     49: #include <sys/socket.h>
                     50: #include <sys/stat.h>
                     51: #include <unistd.h>
                     52: #include <net/if.h>
                     53: 
                     54: #ifdef __APPLE__
                     55: #include <net/if_utun.h>
                     56: #include <netinet/in_var.h>
                     57: #include <sys/kern_control.h>
                     58: #elif defined(__linux__)
                     59: #include <linux/types.h>
                     60: #include <linux/if_tun.h>
                     61: #elif __FreeBSD__ >= 10
                     62: #include <net/if_tun.h>
                     63: #include <net/if_var.h>
                     64: #include <netinet/in_var.h>
                     65: #else
                     66: #include <net/if_tun.h>
                     67: #endif
                     68: 
                     69: #define TUN_DEFAULT_MTU 1500
                     70: 
                     71: typedef struct private_tun_device_t private_tun_device_t;
                     72: 
                     73: struct private_tun_device_t {
                     74: 
                     75:        /**
                     76:         * Public interface
                     77:         */
                     78:        tun_device_t public;
                     79: 
                     80:        /**
                     81:         * The TUN device's file descriptor
                     82:         */
                     83:        int tunfd;
                     84: 
                     85:        /**
                     86:         * Name of the TUN device
                     87:         */
                     88:        char if_name[IFNAMSIZ];
                     89: 
                     90:        /**
                     91:         * Socket used for ioctl() to set interface addr, ...
                     92:         */
                     93:        int sock;
                     94: 
                     95:        /**
                     96:         * The current MTU
                     97:         */
                     98:        int mtu;
                     99: 
                    100:        /**
                    101:         * Associated address
                    102:         */
                    103:        host_t *address;
                    104: 
                    105:        /**
                    106:         * Netmask for address
                    107:         */
                    108:        uint8_t netmask;
                    109: };
                    110: 
                    111: /**
                    112:  * FreeBSD 10 deprecated the SIOCSIFADDR etc. commands.
                    113:  */
                    114: #if __FreeBSD__ >= 10
                    115: 
                    116: static bool set_address_and_mask(struct in_aliasreq *ifra, host_t *addr,
                    117:                                                                 uint8_t netmask)
                    118: {
                    119:        host_t *mask;
                    120: 
                    121:        memcpy(&ifra->ifra_addr, addr->get_sockaddr(addr),
                    122:                   *addr->get_sockaddr_len(addr));
                    123:        /* set the same address as destination address */
                    124:        memcpy(&ifra->ifra_dstaddr, addr->get_sockaddr(addr),
                    125:                   *addr->get_sockaddr_len(addr));
                    126: 
                    127:        mask = host_create_netmask(addr->get_family(addr), netmask);
                    128:        if (!mask)
                    129:        {
                    130:                DBG1(DBG_LIB, "invalid netmask: %d", netmask);
                    131:                return FALSE;
                    132:        }
                    133:        memcpy(&ifra->ifra_mask, mask->get_sockaddr(mask),
                    134:                   *mask->get_sockaddr_len(mask));
                    135:        mask->destroy(mask);
                    136:        return TRUE;
                    137: }
                    138: 
                    139: /**
                    140:  * Set the address using the more flexible SIOCAIFADDR/SIOCDIFADDR commands
                    141:  * on FreeBSD 10 an newer.
                    142:  */
                    143: static bool set_address_impl(private_tun_device_t *this, host_t *addr,
                    144:                                                         uint8_t netmask)
                    145: {
                    146:        struct in_aliasreq ifra;
                    147: 
                    148:        memset(&ifra, 0, sizeof(ifra));
                    149:        strncpy(ifra.ifra_name, this->if_name, IFNAMSIZ);
                    150: 
                    151:        if (this->address)
                    152:        {       /* remove the existing address first */
                    153:                if (!set_address_and_mask(&ifra, this->address, this->netmask))
                    154:                {
                    155:                        return FALSE;
                    156:                }
                    157:                if (ioctl(this->sock, SIOCDIFADDR, &ifra) < 0)
                    158:                {
                    159:                        DBG1(DBG_LIB, "failed to remove existing address on %s: %s",
                    160:                                 this->if_name, strerror(errno));
                    161:                        return FALSE;
                    162:                }
                    163:        }
                    164:        if (!set_address_and_mask(&ifra, addr, netmask))
                    165:        {
                    166:                return FALSE;
                    167:        }
                    168:        if (ioctl(this->sock, SIOCAIFADDR, &ifra) < 0)
                    169:        {
                    170:                DBG1(DBG_LIB, "failed to add address on %s: %s",
                    171:                         this->if_name, strerror(errno));
                    172:                return FALSE;
                    173:        }
                    174:        return TRUE;
                    175: }
                    176: 
                    177: #else /* __FreeBSD__ */
                    178: 
                    179: /**
                    180:  * Set the address using the classic SIOCSIFADDR etc. commands on other systems.
                    181:  */
                    182: static bool set_address_impl(private_tun_device_t *this, host_t *addr,
                    183:                                                         uint8_t netmask)
                    184: {
                    185:        struct ifreq ifr;
                    186:        host_t *mask;
                    187: 
                    188:        memset(&ifr, 0, sizeof(ifr));
                    189:        strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
                    190:        memcpy(&ifr.ifr_addr, addr->get_sockaddr(addr),
                    191:                   *addr->get_sockaddr_len(addr));
                    192: 
                    193:        if (ioctl(this->sock, SIOCSIFADDR, &ifr) < 0)
                    194:        {
                    195:                DBG1(DBG_LIB, "failed to set address on %s: %s",
                    196:                         this->if_name, strerror(errno));
                    197:                return FALSE;
                    198:        }
                    199: #ifdef __APPLE__
                    200:        if (ioctl(this->sock, SIOCSIFDSTADDR, &ifr) < 0)
                    201:        {
                    202:                DBG1(DBG_LIB, "failed to set dest address on %s: %s",
                    203:                         this->if_name, strerror(errno));
                    204:                return FALSE;
                    205:        }
                    206: #endif /* __APPLE__ */
                    207: 
                    208:        mask = host_create_netmask(addr->get_family(addr), netmask);
                    209:        if (!mask)
                    210:        {
                    211:                DBG1(DBG_LIB, "invalid netmask: %d", netmask);
                    212:                return FALSE;
                    213:        }
                    214:        memcpy(&ifr.ifr_addr, mask->get_sockaddr(mask),
                    215:                   *mask->get_sockaddr_len(mask));
                    216:        mask->destroy(mask);
                    217: 
                    218:        if (ioctl(this->sock, SIOCSIFNETMASK, &ifr) < 0)
                    219:        {
                    220:                DBG1(DBG_LIB, "failed to set netmask on %s: %s",
                    221:                         this->if_name, strerror(errno));
                    222:                return FALSE;
                    223:        }
                    224:        return TRUE;
                    225: }
                    226: 
                    227: #endif /* __FreeBSD__ */
                    228: 
                    229: METHOD(tun_device_t, set_address, bool,
                    230:        private_tun_device_t *this, host_t *addr, uint8_t netmask)
                    231: {
                    232:        if (!set_address_impl(this, addr, netmask))
                    233:        {
                    234:                return FALSE;
                    235:        }
                    236:        DESTROY_IF(this->address);
                    237:        this->address = addr->clone(addr);
                    238:        this->netmask = netmask;
                    239:        return TRUE;
                    240: }
                    241: 
                    242: METHOD(tun_device_t, get_address, host_t*,
                    243:        private_tun_device_t *this, uint8_t *netmask)
                    244: {
                    245:        if (netmask && this->address)
                    246:        {
                    247:                *netmask = this->netmask;
                    248:        }
                    249:        return this->address;
                    250: }
                    251: 
                    252: METHOD(tun_device_t, up, bool,
                    253:        private_tun_device_t *this)
                    254: {
                    255:        struct ifreq ifr;
                    256: 
                    257:        memset(&ifr, 0, sizeof(ifr));
                    258:        strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
                    259: 
                    260:        if (ioctl(this->sock, SIOCGIFFLAGS, &ifr) < 0)
                    261:        {
                    262:                DBG1(DBG_LIB, "failed to get interface flags for %s: %s", this->if_name,
                    263:                         strerror(errno));
                    264:                return FALSE;
                    265:        }
                    266: 
                    267:        ifr.ifr_flags |= IFF_RUNNING | IFF_UP;
                    268: 
                    269:        if (ioctl(this->sock, SIOCSIFFLAGS, &ifr) < 0)
                    270:        {
                    271:                DBG1(DBG_LIB, "failed to set interface flags on %s: %s", this->if_name,
                    272:                         strerror(errno));
                    273:                return FALSE;
                    274:        }
                    275:        return TRUE;
                    276: }
                    277: 
                    278: METHOD(tun_device_t, set_mtu, bool,
                    279:        private_tun_device_t *this, int mtu)
                    280: {
                    281:        struct ifreq ifr;
                    282: 
                    283:        memset(&ifr, 0, sizeof(ifr));
                    284:        strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
                    285:        ifr.ifr_mtu = mtu;
                    286: 
                    287:        if (ioctl(this->sock, SIOCSIFMTU, &ifr) < 0)
                    288:        {
                    289:                DBG1(DBG_LIB, "failed to set MTU on %s: %s", this->if_name,
                    290:                         strerror(errno));
                    291:                return FALSE;
                    292:        }
                    293:        this->mtu = mtu;
                    294:        return TRUE;
                    295: }
                    296: 
                    297: METHOD(tun_device_t, get_mtu, int,
                    298:        private_tun_device_t *this)
                    299: {
                    300:        struct ifreq ifr;
                    301: 
                    302:        if (this->mtu > 0)
                    303:        {
                    304:                return this->mtu;
                    305:        }
                    306: 
                    307:        memset(&ifr, 0, sizeof(ifr));
                    308:        strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
                    309:        this->mtu = TUN_DEFAULT_MTU;
                    310: 
                    311:        if (ioctl(this->sock, SIOCGIFMTU, &ifr) == 0)
                    312:        {
                    313:                this->mtu = ifr.ifr_mtu;
                    314:        }
                    315:        return this->mtu;
                    316: }
                    317: 
                    318: METHOD(tun_device_t, get_name, char*,
                    319:        private_tun_device_t *this)
                    320: {
                    321:        return this->if_name;
                    322: }
                    323: 
                    324: METHOD(tun_device_t, get_fd, int,
                    325:        private_tun_device_t *this)
                    326: {
                    327:        return this->tunfd;
                    328: }
                    329: 
                    330: METHOD(tun_device_t, write_packet, bool,
                    331:        private_tun_device_t *this, chunk_t packet)
                    332: {
                    333:        ssize_t s;
                    334: 
                    335: #ifdef __APPLE__
                    336:        /* UTUN's expect the packets to be prepended by a 32-bit protocol number
                    337:         * instead of parsing the packet again, we assume IPv4 for now */
                    338:        uint32_t proto = htonl(AF_INET);
                    339:        packet = chunk_cata("cc", chunk_from_thing(proto), packet);
                    340: #endif
                    341:        s = write(this->tunfd, packet.ptr, packet.len);
                    342:        if (s < 0)
                    343:        {
                    344:                DBG1(DBG_LIB, "failed to write packet to TUN device %s: %s",
                    345:                         this->if_name, strerror(errno));
                    346:                return FALSE;
                    347:        }
                    348:        else if (s != packet.len)
                    349:        {
                    350:                return FALSE;
                    351:        }
                    352:        return TRUE;
                    353: }
                    354: 
                    355: METHOD(tun_device_t, read_packet, bool,
                    356:        private_tun_device_t *this, chunk_t *packet)
                    357: {
                    358:        chunk_t data;
                    359:        ssize_t len;
                    360:        bool old;
                    361: 
                    362:        data = chunk_alloca(get_mtu(this));
                    363: 
                    364:        old = thread_cancelability(TRUE);
                    365:        len = read(this->tunfd, data.ptr, data.len);
                    366:        thread_cancelability(old);
                    367:        if (len < 0)
                    368:        {
                    369:                DBG1(DBG_LIB, "reading from TUN device %s failed: %s", this->if_name,
                    370:                         strerror(errno));
                    371:                return FALSE;
                    372:        }
                    373:        data.len = len;
                    374: #ifdef __APPLE__
                    375:        /* UTUN's prepend packets with a 32-bit protocol number */
                    376:        data = chunk_skip(data, sizeof(uint32_t));
                    377: #endif
                    378:        *packet = chunk_clone(data);
                    379:        return TRUE;
                    380: }
                    381: 
                    382: METHOD(tun_device_t, destroy, void,
                    383:        private_tun_device_t *this)
                    384: {
                    385:        if (this->tunfd > 0)
                    386:        {
                    387:                close(this->tunfd);
                    388: #ifdef __FreeBSD__
                    389:                /* tun(4) says the following: "These network interfaces persist until
                    390:                 * the if_tun.ko module is unloaded, or until removed with the
                    391:                 * ifconfig(8) command."  So simply closing the FD is not enough. */
                    392:                struct ifreq ifr;
                    393: 
                    394:                memset(&ifr, 0, sizeof(ifr));
                    395:                strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
                    396:                if (ioctl(this->sock, SIOCIFDESTROY, &ifr) < 0)
                    397:                {
                    398:                        DBG1(DBG_LIB, "failed to destroy %s: %s", this->if_name,
                    399:                                 strerror(errno));
                    400:                }
                    401: #endif /* __FreeBSD__ */
                    402:        }
                    403:        if (this->sock > 0)
                    404:        {
                    405:                close(this->sock);
                    406:        }
                    407:        DESTROY_IF(this->address);
                    408:        free(this);
                    409: }
                    410: 
                    411: /**
                    412:  * Initialize the tun device
                    413:  */
                    414: static bool init_tun(private_tun_device_t *this, const char *name_tmpl)
                    415: {
                    416: #ifdef __APPLE__
                    417: 
                    418:        struct ctl_info info;
                    419:        struct sockaddr_ctl addr;
                    420:        socklen_t size = IFNAMSIZ;
                    421: 
                    422:        memset(&info, 0, sizeof(info));
                    423:        memset(&addr, 0, sizeof(addr));
                    424: 
                    425:        this->tunfd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
                    426:        if (this->tunfd < 0)
                    427:        {
                    428:                DBG1(DBG_LIB, "failed to open tundevice PF_SYSTEM socket: %s",
                    429:                         strerror(errno));
                    430:                return FALSE;
                    431:        }
                    432: 
                    433:        /* get a control identifier for the utun kernel extension */
                    434:        strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
                    435:        if (ioctl(this->tunfd, CTLIOCGINFO, &info) < 0)
                    436:        {
                    437:                DBG1(DBG_LIB, "failed to ioctl tundevice: %s", strerror(errno));
                    438:                close(this->tunfd);
                    439:                return FALSE;
                    440:        }
                    441: 
                    442:        addr.sc_id = info.ctl_id;
                    443:        addr.sc_len = sizeof(addr);
                    444:        addr.sc_family = AF_SYSTEM;
                    445:        addr.ss_sysaddr = AF_SYS_CONTROL;
                    446:        /* allocate identifier dynamically */
                    447:        addr.sc_unit = 0;
                    448: 
                    449:        if (connect(this->tunfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
                    450:        {
                    451:                DBG1(DBG_LIB, "failed to connect tundevice: %s", strerror(errno));
                    452:                close(this->tunfd);
                    453:                return FALSE;
                    454:        }
                    455:        if (getsockopt(this->tunfd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME,
                    456:                                   this->if_name, &size) < 0)
                    457:        {
                    458:                DBG1(DBG_LIB, "getting tundevice name failed: %s", strerror(errno));
                    459:                close(this->tunfd);
                    460:                return FALSE;
                    461:        }
                    462:        return TRUE;
                    463: 
                    464: #elif defined(IFF_TUN)
                    465: 
                    466:        struct ifreq ifr;
                    467: 
                    468:        strncpy(this->if_name, name_tmpl ?: "tun%d", IFNAMSIZ);
                    469:        this->if_name[IFNAMSIZ-1] = '\0';
                    470: 
                    471:        this->tunfd = open("/dev/net/tun", O_RDWR);
                    472:        if (this->tunfd < 0)
                    473:        {
                    474:                DBG1(DBG_LIB, "failed to open /dev/net/tun: %s", strerror(errno));
                    475:                return FALSE;
                    476:        }
                    477: 
                    478:        memset(&ifr, 0, sizeof(ifr));
                    479: 
                    480:        /* TUN device, no packet info */
                    481:        ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
                    482: 
                    483:        strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
                    484:        if (ioctl(this->tunfd, TUNSETIFF, (void*)&ifr) < 0)
                    485:        {
                    486:                DBG1(DBG_LIB, "failed to configure TUN device: %s", strerror(errno));
                    487:                close(this->tunfd);
                    488:                return FALSE;
                    489:        }
                    490:        strncpy(this->if_name, ifr.ifr_name, IFNAMSIZ);
                    491:        return TRUE;
                    492: 
                    493: #elif defined(__FreeBSD__)
                    494: 
                    495:        if (name_tmpl)
                    496:        {
                    497:                DBG1(DBG_LIB, "arbitrary naming of TUN devices is not supported");
                    498:        }
                    499: 
                    500:        this->tunfd = open("/dev/tun", O_RDWR);
                    501:        if (this->tunfd < 0)
                    502:        {
                    503:                DBG1(DBG_LIB, "failed to open /dev/tun: %s", strerror(errno));
                    504:                return FALSE;
                    505:        }
                    506:        fdevname_r(this->tunfd, this->if_name, IFNAMSIZ);
                    507:        return TRUE;
                    508: 
                    509: #else /* !__FreeBSD__ */
                    510: 
                    511:        /* this might work on Linux with older TUN driver versions (no IFF_TUN) */
                    512:        char devname[IFNAMSIZ];
                    513:        /* the same process is allowed to open a device again, but that's not what
                    514:         * we want (unless we previously closed a device, which we don't know at
                    515:         * this point).  therefore, this counter is static so we don't accidentally
                    516:         * open a device twice */
                    517:        static int i = -1;
                    518: 
                    519:        if (name_tmpl)
                    520:        {
                    521:                DBG1(DBG_LIB, "arbitrary naming of TUN devices is not supported");
                    522:        }
                    523: 
                    524:        for (; ++i < 256; )
                    525:        {
                    526:                snprintf(devname, IFNAMSIZ, "/dev/tun%d", i);
                    527:                this->tunfd = open(devname, O_RDWR);
                    528:                if (this->tunfd > 0)
                    529:                {       /* for ioctl(2) calls only the interface name is used */
                    530:                        snprintf(this->if_name, IFNAMSIZ, "tun%d", i);
                    531:                        break;
                    532:                }
                    533:                DBG1(DBG_LIB, "failed to open %s: %s", this->if_name, strerror(errno));
                    534:        }
                    535:        return this->tunfd > 0;
                    536: 
                    537: #endif /* !__APPLE__ */
                    538: }
                    539: 
                    540: /*
                    541:  * Described in header
                    542:  */
                    543: tun_device_t *tun_device_create(const char *name_tmpl)
                    544: {
                    545:        private_tun_device_t *this;
                    546: 
                    547:        INIT(this,
                    548:                .public = {
                    549:                        .read_packet = _read_packet,
                    550:                        .write_packet = _write_packet,
                    551:                        .get_mtu = _get_mtu,
                    552:                        .set_mtu = _set_mtu,
                    553:                        .get_name = _get_name,
                    554:                        .get_fd = _get_fd,
                    555:                        .set_address = _set_address,
                    556:                        .get_address = _get_address,
                    557:                        .up = _up,
                    558:                        .destroy = _destroy,
                    559:                },
                    560:                .tunfd = -1,
                    561:                .sock = -1,
                    562:        );
                    563: 
                    564:        if (!init_tun(this, name_tmpl))
                    565:        {
                    566:                free(this);
                    567:                return NULL;
                    568:        }
                    569:        DBG1(DBG_LIB, "created TUN device: %s", this->if_name);
                    570: 
                    571:        this->sock = socket(AF_INET, SOCK_DGRAM, 0);
                    572:        if (this->sock < 0)
                    573:        {
                    574:                DBG1(DBG_LIB, "failed to open socket to configure TUN device");
                    575:                destroy(this);
                    576:                return NULL;
                    577:        }
                    578:        return &this->public;
                    579: }
                    580: 
                    581: #endif /* TUN devices supported */

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