Annotation of embedaddon/strongswan/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2006-2013 Tobias Brunner
                      3:  * Copyright (C) 2006 Daniel Roethlisberger
                      4:  * Copyright (C) 2005-2010 Martin Willi
                      5:  * Copyright (C) 2005 Jan Hutter
                      6:  * HSR Hochschule fuer Technik Rapperswil
                      7:  * Copyright (C) 2010 revosec AG
                      8:  *
                      9:  * This program is free software; you can redistribute it and/or modify it
                     10:  * under the terms of the GNU General Public License as published by the
                     11:  * Free Software Foundation; either version 2 of the License, or (at your
                     12:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     13:  *
                     14:  * This program is distributed in the hope that it will be useful, but
                     15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     16:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     17:  * for more details.
                     18:  */
                     19: 
                     20: /* for struct in6_pktinfo */
                     21: #define _GNU_SOURCE
                     22: 
                     23: #include "socket_dynamic_socket.h"
                     24: 
                     25: #include <sys/types.h>
                     26: #include <sys/socket.h>
                     27: #include <string.h>
                     28: #include <errno.h>
                     29: #include <unistd.h>
                     30: #include <stdlib.h>
                     31: #include <fcntl.h>
                     32: #include <sys/ioctl.h>
                     33: #include <netinet/in_systm.h>
                     34: #include <netinet/in.h>
                     35: #include <netinet/ip.h>
                     36: #include <netinet/udp.h>
                     37: #include <net/if.h>
                     38: 
                     39: #include <daemon.h>
                     40: #include <threading/thread.h>
                     41: #include <threading/rwlock.h>
                     42: #include <collections/hashtable.h>
                     43: 
                     44: /* these are not defined on some platforms */
                     45: #ifndef SOL_IP
                     46: #define SOL_IP IPPROTO_IP
                     47: #endif
                     48: #ifndef SOL_IPV6
                     49: #define SOL_IPV6 IPPROTO_IPV6
                     50: #endif
                     51: 
                     52: /* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
                     53:  * previously defined IPV6_PKTINFO */
                     54: #ifndef IPV6_RECVPKTINFO
                     55: #define IPV6_RECVPKTINFO IPV6_PKTINFO
                     56: #endif
                     57: 
                     58: typedef struct private_socket_dynamic_socket_t private_socket_dynamic_socket_t;
                     59: typedef struct dynsock_t dynsock_t;
                     60: 
                     61: /**
                     62:  * Private data of an socket_t object
                     63:  */
                     64: struct private_socket_dynamic_socket_t {
                     65: 
                     66:        /**
                     67:         * public functions
                     68:         */
                     69:        socket_dynamic_socket_t public;
                     70: 
                     71:        /**
                     72:         * Hashtable of bound sockets
                     73:         */
                     74:        hashtable_t *sockets;
                     75: 
                     76:        /**
                     77:         * Lock for sockets hashtable
                     78:         */
                     79:        rwlock_t *lock;
                     80: 
                     81:        /**
                     82:         * Notification pipe to signal receiver
                     83:         */
                     84:        int notify[2];
                     85: 
                     86:        /**
                     87:         * Maximum packet size to receive
                     88:         */
                     89:        int max_packet;
                     90: };
                     91: 
                     92: /**
                     93:  * Struct for a dynamically allocated socket
                     94:  */
                     95: struct dynsock_t {
                     96: 
                     97:        /**
                     98:         * File descriptor of socket
                     99:         */
                    100:        int fd;
                    101: 
                    102:        /**
                    103:         * Address family
                    104:         */
                    105:        int family;
                    106: 
                    107:        /**
                    108:         * Bound source port
                    109:         */
                    110:        uint16_t port;
                    111: };
                    112: 
                    113: /**
                    114:  * Hash function for hashtable
                    115:  */
                    116: static u_int hash(dynsock_t *key)
                    117: {
                    118:        return (key->family << 16) | key->port;
                    119: }
                    120: 
                    121: /**
                    122:  * Equals function for hashtable
                    123:  */
                    124: static bool equals(dynsock_t *a, dynsock_t *b)
                    125: {
                    126:        return a->family == b->family && a->port == b->port;
                    127: }
                    128: 
                    129: /**
                    130:  * Create a fd_set from all bound sockets
                    131:  */
                    132: static int build_fds(private_socket_dynamic_socket_t *this, fd_set *fds)
                    133: {
                    134:        enumerator_t *enumerator;
                    135:        dynsock_t *key, *value;
                    136:        int maxfd;
                    137: 
                    138:        FD_ZERO(fds);
                    139:        FD_SET(this->notify[0], fds);
                    140:        maxfd = this->notify[0];
                    141: 
                    142:        this->lock->read_lock(this->lock);
                    143:        enumerator = this->sockets->create_enumerator(this->sockets);
                    144:        while (enumerator->enumerate(enumerator, &key, &value))
                    145:        {
                    146:                FD_SET(value->fd, fds);
                    147:                maxfd = max(maxfd, value->fd);
                    148:        }
                    149:        enumerator->destroy(enumerator);
                    150:        this->lock->unlock(this->lock);
                    151: 
                    152:        return maxfd + 1;
                    153: }
                    154: 
                    155: /**
                    156:  * Find the socket select()ed
                    157:  */
                    158: static dynsock_t* scan_fds(private_socket_dynamic_socket_t *this, fd_set *fds)
                    159: {
                    160:        enumerator_t *enumerator;
                    161:        dynsock_t *key, *value, *selected = NULL;
                    162: 
                    163:        this->lock->read_lock(this->lock);
                    164:        enumerator = this->sockets->create_enumerator(this->sockets);
                    165:        while (enumerator->enumerate(enumerator, &key, &value))
                    166:        {
                    167:                if (FD_ISSET(value->fd, fds))
                    168:                {
                    169:                        selected = value;
                    170:                        break;
                    171:                }
                    172:        }
                    173:        enumerator->destroy(enumerator);
                    174:        this->lock->unlock(this->lock);
                    175: 
                    176:        return selected;
                    177: }
                    178: 
                    179: /**
                    180:  * Receive a packet from a given socket fd
                    181:  */
                    182: static packet_t *receive_packet(private_socket_dynamic_socket_t *this,
                    183:                                                                dynsock_t *skt)
                    184: {
                    185:        host_t *source = NULL, *dest = NULL;
                    186:        ssize_t len;
                    187:        char buffer[this->max_packet];
                    188:        chunk_t data;
                    189:        packet_t *packet;
                    190:        struct msghdr msg;
                    191:        struct cmsghdr *cmsgptr;
                    192:        struct iovec iov;
                    193:        char ancillary[64];
                    194:        union {
                    195:                struct sockaddr_in in4;
                    196:                struct sockaddr_in6 in6;
                    197:        } src;
                    198: 
                    199:        msg.msg_name = &src;
                    200:        msg.msg_namelen = sizeof(src);
                    201:        iov.iov_base = buffer;
                    202:        iov.iov_len = this->max_packet;
                    203:        msg.msg_iov = &iov;
                    204:        msg.msg_iovlen = 1;
                    205:        msg.msg_control = ancillary;
                    206:        msg.msg_controllen = sizeof(ancillary);
                    207:        msg.msg_flags = 0;
                    208:        len = recvmsg(skt->fd, &msg, 0);
                    209:        if (len < 0)
                    210:        {
                    211:                DBG1(DBG_NET, "error reading socket: %s", strerror(errno));
                    212:                return NULL;
                    213:        }
                    214:        if (msg.msg_flags & MSG_TRUNC)
                    215:        {
                    216:                DBG1(DBG_NET, "receive buffer too small, packet discarded");
                    217:                return NULL;
                    218:        }
                    219:        DBG3(DBG_NET, "received packet %b", buffer, (u_int)len);
                    220: 
                    221:        /* read ancillary data to get destination address */
                    222:        for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
                    223:                 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
                    224:        {
                    225:                if (cmsgptr->cmsg_len == 0)
                    226:                {
                    227:                        DBG1(DBG_NET, "error reading ancillary data");
                    228:                        return NULL;
                    229:                }
                    230: 
                    231:                if (cmsgptr->cmsg_level == SOL_IPV6 &&
                    232:                        cmsgptr->cmsg_type == IPV6_PKTINFO)
                    233:                {
                    234:                        struct in6_pktinfo *pktinfo;
                    235:                        struct sockaddr_in6 dst;
                    236: 
                    237:                        pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
                    238:                        memset(&dst, 0, sizeof(dst));
                    239:                        memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
                    240:                        dst.sin6_family = AF_INET6;
                    241:                        dst.sin6_port = htons(skt->port);
                    242:                        dest = host_create_from_sockaddr((sockaddr_t*)&dst);
                    243:                }
                    244:                if (cmsgptr->cmsg_level == SOL_IP &&
                    245:                        cmsgptr->cmsg_type == IP_PKTINFO)
                    246:                {
                    247:                        struct in_pktinfo *pktinfo;
                    248:                        struct sockaddr_in dst;
                    249: 
                    250:                        pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsgptr);
                    251:                        memset(&dst, 0, sizeof(dst));
                    252:                        memcpy(&dst.sin_addr, &pktinfo->ipi_addr, sizeof(dst.sin_addr));
                    253: 
                    254:                        dst.sin_family = AF_INET;
                    255:                        dst.sin_port = htons(skt->port);
                    256:                        dest = host_create_from_sockaddr((sockaddr_t*)&dst);
                    257:                }
                    258:                if (dest)
                    259:                {
                    260:                        break;
                    261:                }
                    262:        }
                    263:        if (dest == NULL)
                    264:        {
                    265:                DBG1(DBG_NET, "error reading IP header");
                    266:                return NULL;
                    267:        }
                    268:        source = host_create_from_sockaddr((sockaddr_t*)&src);
                    269:        DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
                    270:        data = chunk_create(buffer, len);
                    271: 
                    272:        packet = packet_create();
                    273:        packet->set_source(packet, source);
                    274:        packet->set_destination(packet, dest);
                    275:        packet->set_data(packet, chunk_clone(data));
                    276:        return packet;
                    277: }
                    278: 
                    279: METHOD(socket_t, receiver, status_t,
                    280:        private_socket_dynamic_socket_t *this, packet_t **packet)
                    281: {
                    282:        dynsock_t *selected;
                    283:        packet_t *pkt;
                    284:        bool oldstate;
                    285:        fd_set fds;
                    286:        int maxfd;
                    287: 
                    288:        while (TRUE)
                    289:        {
                    290:                maxfd = build_fds(this, &fds);
                    291: 
                    292:                DBG2(DBG_NET, "waiting for data on sockets");
                    293:                oldstate = thread_cancelability(TRUE);
                    294:                if (select(maxfd, &fds, NULL, NULL, NULL) <= 0)
                    295:                {
                    296:                        thread_cancelability(oldstate);
                    297:                        return FAILED;
                    298:                }
                    299:                thread_cancelability(oldstate);
                    300: 
                    301:                if (FD_ISSET(this->notify[0], &fds))
                    302:                {       /* got notified, read garbage, rebuild fdset */
                    303:                        char buf[1];
                    304: 
                    305:                        ignore_result(read(this->notify[0], buf, sizeof(buf)));
                    306:                        DBG2(DBG_NET, "rebuilding fdset due to newly bound ports");
                    307:                        continue;
                    308:                }
                    309:                selected = scan_fds(this, &fds);
                    310:                if (selected)
                    311:                {
                    312:                        break;
                    313:                }
                    314:        }
                    315:        pkt = receive_packet(this, selected);
                    316:        if (pkt)
                    317:        {
                    318:                *packet = pkt;
                    319:                return SUCCESS;
                    320:        }
                    321:        return FAILED;
                    322: }
                    323: 
                    324: /**
                    325:  * Get the port allocated dynamically using bind()
                    326:  */
                    327: static bool get_dynamic_port(int fd, int family, uint16_t *port)
                    328: {
                    329:        union {
                    330:                struct sockaddr_storage ss;
                    331:                struct sockaddr s;
                    332:                struct sockaddr_in sin;
                    333:                struct sockaddr_in6 sin6;
                    334:        } addr;
                    335:        socklen_t addrlen;
                    336: 
                    337:        addrlen = sizeof(addr);
                    338:        if (getsockname(fd, &addr.s, &addrlen) != 0)
                    339:        {
                    340:                DBG1(DBG_NET, "unable to getsockname: %s", strerror(errno));
                    341:                return FALSE;
                    342:        }
                    343:        switch (family)
                    344:        {
                    345:                case AF_INET:
                    346:                        if (addrlen != sizeof(addr.sin) || addr.sin.sin_family != family)
                    347:                        {
                    348:                                break;
                    349:                        }
                    350:                        *port = ntohs(addr.sin.sin_port);
                    351:                        return TRUE;
                    352:                case AF_INET6:
                    353:                        if (addrlen != sizeof(addr.sin6) || addr.sin6.sin6_family != family)
                    354:                        {
                    355:                                break;
                    356:                        }
                    357:                        *port = ntohs(addr.sin6.sin6_port);
                    358:                        return TRUE;
                    359:                default:
                    360:                        return FALSE;
                    361:        }
                    362:        DBG1(DBG_NET, "received invalid getsockname() result");
                    363:        return FALSE;
                    364: }
                    365: 
                    366: /**
                    367:  * open a socket to send and receive packets
                    368:  */
                    369: static int open_socket(private_socket_dynamic_socket_t *this,
                    370:                                           int family, uint16_t *port)
                    371: {
                    372:        union {
                    373:                struct sockaddr_storage ss;
                    374:                struct sockaddr s;
                    375:                struct sockaddr_in sin;
                    376:                struct sockaddr_in6 sin6;
                    377:        } addr;
                    378:        int on = TRUE;
                    379:        socklen_t addrlen;
                    380:        u_int sol, pktinfo = 0;
                    381:        int fd;
                    382: 
                    383:        memset(&addr, 0, sizeof(addr));
                    384:        /* precalculate constants depending on address family */
                    385:        switch (family)
                    386:        {
                    387:                case AF_INET:
                    388:                        addr.sin.sin_family = AF_INET;
                    389:                        addr.sin.sin_addr.s_addr = INADDR_ANY;
                    390:                        addr.sin.sin_port = htons(*port);
                    391:                        addrlen = sizeof(addr.sin);
                    392:                        sol = SOL_IP;
                    393:                        pktinfo = IP_PKTINFO;
                    394:                        break;
                    395:                case AF_INET6:
                    396:                        addr.sin6.sin6_family = AF_INET6;
                    397:                        memset(&addr.sin6.sin6_addr, 0, sizeof(addr.sin6.sin6_addr));
                    398:                        addr.sin6.sin6_port = htons(*port);
                    399:                        addrlen = sizeof(addr.sin6);
                    400:                        sol = SOL_IPV6;
                    401:                        pktinfo = IPV6_RECVPKTINFO;
                    402:                        break;
                    403:                default:
                    404:                        return 0;
                    405:        }
                    406: 
                    407:        fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
                    408:        if (fd < 0)
                    409:        {
                    410:                DBG1(DBG_NET, "could not open socket: %s", strerror(errno));
                    411:                return 0;
                    412:        }
                    413:        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
                    414:        {
                    415:                DBG1(DBG_NET, "unable to set SO_REUSEADDR on socket: %s", strerror(errno));
                    416:                close(fd);
                    417:                return 0;
                    418:        }
                    419: 
                    420:        if (bind(fd, &addr.s, addrlen) < 0)
                    421:        {
                    422:                DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno));
                    423:                close(fd);
                    424:                return 0;
                    425:        }
                    426:        if (*port == 0 && !get_dynamic_port(fd, family, port))
                    427:        {
                    428:                close(fd);
                    429:                return 0;
                    430:        }
                    431: 
                    432:        /* get additional packet info on receive */
                    433:        if (setsockopt(fd, sol, pktinfo, &on, sizeof(on)) < 0)
                    434:        {
                    435:                DBG1(DBG_NET, "unable to set IP_PKTINFO on socket: %s", strerror(errno));
                    436:                close(fd);
                    437:                return 0;
                    438:        }
                    439: 
                    440:        if (!charon->kernel->bypass_socket(charon->kernel, fd, family))
                    441:        {
                    442:                DBG1(DBG_NET, "installing IKE bypass policy failed");
                    443:        }
                    444: 
                    445:        /* enable UDP decapsulation on each socket */
                    446:        if (!charon->kernel->enable_udp_decap(charon->kernel, fd, family, *port))
                    447:        {
                    448:                DBG1(DBG_NET, "enabling UDP decapsulation for %s on port %d failed",
                    449:                         family == AF_INET ? "IPv4" : "IPv6", *port);
                    450:        }
                    451: 
                    452:        return fd;
                    453: }
                    454: 
                    455: /**
                    456:  * Get the first usable socket for an address family
                    457:  */
                    458: static dynsock_t *get_any_socket(private_socket_dynamic_socket_t *this,
                    459:                                                                 int family)
                    460: {
                    461:        dynsock_t *key, *value, *found = NULL;
                    462:        enumerator_t *enumerator;
                    463: 
                    464:        this->lock->read_lock(this->lock);
                    465:        enumerator = this->sockets->create_enumerator(this->sockets);
                    466:        while (enumerator->enumerate(enumerator, &key, &value))
                    467:        {
                    468:                if (value->family == family)
                    469:                {
                    470:                        found = value;
                    471:                        break;
                    472:                }
                    473:        }
                    474:        enumerator->destroy(enumerator);
                    475:        this->lock->unlock(this->lock);
                    476: 
                    477:        return found;
                    478: }
                    479: 
                    480: /**
                    481:  * Find/Create a socket to send from host
                    482:  */
                    483: static dynsock_t *find_socket(private_socket_dynamic_socket_t *this,
                    484:                                                          int family, uint16_t port)
                    485: {
                    486:        dynsock_t *skt, lookup = {
                    487:                .family = family,
                    488:                .port = port,
                    489:        };
                    490:        char buf[] = {0x01};
                    491:        int fd;
                    492: 
                    493:        this->lock->read_lock(this->lock);
                    494:        skt = this->sockets->get(this->sockets, &lookup);
                    495:        this->lock->unlock(this->lock);
                    496:        if (skt)
                    497:        {
                    498:                return skt;
                    499:        }
                    500:        if (!port)
                    501:        {
                    502:                skt = get_any_socket(this, family);
                    503:                if (skt)
                    504:                {
                    505:                        return skt;
                    506:                }
                    507:        }
                    508:        fd = open_socket(this, family, &port);
                    509:        if (!fd)
                    510:        {
                    511:                return NULL;
                    512:        }
                    513:        INIT(skt,
                    514:                .family = family,
                    515:                .port = port,
                    516:                .fd = fd,
                    517:        );
                    518:        this->lock->write_lock(this->lock);
                    519:        this->sockets->put(this->sockets, skt, skt);
                    520:        this->lock->unlock(this->lock);
                    521:        /* notify receiver thread to reread socket list */
                    522:        ignore_result(write(this->notify[1], buf, sizeof(buf)));
                    523: 
                    524:        return skt;
                    525: }
                    526: 
                    527: /**
                    528:  * Generic function to send a message.
                    529:  */
                    530: static ssize_t send_msg_generic(int skt, struct msghdr *msg)
                    531: {
                    532:        return sendmsg(skt, msg, 0);
                    533: }
                    534: 
                    535: /**
                    536:  * Send a message with the IPv4 source address set.
                    537:  */
                    538: static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
                    539: {
                    540:        char buf[CMSG_SPACE(sizeof(struct in_pktinfo))] = {};
                    541:        struct cmsghdr *cmsg;
                    542:        struct in_addr *addr;
                    543:        struct in_pktinfo *pktinfo;
                    544:        struct sockaddr_in *sin;
                    545: 
                    546:        msg->msg_control = buf;
                    547:        msg->msg_controllen = sizeof(buf);
                    548:        cmsg = CMSG_FIRSTHDR(msg);
                    549:        cmsg->cmsg_level = SOL_IP;
                    550:        cmsg->cmsg_type = IP_PKTINFO;
                    551:        cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
                    552: 
                    553:        pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
                    554:        addr = &pktinfo->ipi_spec_dst;
                    555: 
                    556:        sin = (struct sockaddr_in*)src->get_sockaddr(src);
                    557:        memcpy(addr, &sin->sin_addr, sizeof(struct in_addr));
                    558:        return send_msg_generic(skt, msg);
                    559: }
                    560: 
                    561: /**
                    562:  * Send a message with the IPv6 source address set.
                    563:  */
                    564: static ssize_t send_msg_v6(int skt, struct msghdr *msg, host_t *src)
                    565: {
                    566:        char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {};
                    567:        struct cmsghdr *cmsg;
                    568:        struct in6_pktinfo *pktinfo;
                    569:        struct sockaddr_in6 *sin;
                    570: 
                    571:        msg->msg_control = buf;
                    572:        msg->msg_controllen = sizeof(buf);
                    573:        cmsg = CMSG_FIRSTHDR(msg);
                    574:        cmsg->cmsg_level = SOL_IPV6;
                    575:        cmsg->cmsg_type = IPV6_PKTINFO;
                    576:        cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
                    577:        pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
                    578:        sin = (struct sockaddr_in6*)src->get_sockaddr(src);
                    579:        memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
                    580:        return send_msg_generic(skt, msg);
                    581: }
                    582: 
                    583: METHOD(socket_t, sender, status_t,
                    584:        private_socket_dynamic_socket_t *this, packet_t *packet)
                    585: {
                    586:        dynsock_t *skt;
                    587:        host_t *src, *dst;
                    588:        int family;
                    589:        ssize_t len;
                    590:        chunk_t data;
                    591:        struct msghdr msg;
                    592:        struct iovec iov;
                    593: 
                    594:        src = packet->get_source(packet);
                    595:        dst = packet->get_destination(packet);
                    596:        family = src->get_family(src);
                    597:        skt = find_socket(this, family, src->get_port(src));
                    598:        if (!skt)
                    599:        {
                    600:                return FAILED;
                    601:        }
                    602: 
                    603:        data = packet->get_data(packet);
                    604:        DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
                    605: 
                    606:        memset(&msg, 0, sizeof(struct msghdr));
                    607:        msg.msg_name = dst->get_sockaddr(dst);;
                    608:        msg.msg_namelen = *dst->get_sockaddr_len(dst);
                    609:        iov.iov_base = data.ptr;
                    610:        iov.iov_len = data.len;
                    611:        msg.msg_iov = &iov;
                    612:        msg.msg_iovlen = 1;
                    613:        msg.msg_flags = 0;
                    614: 
                    615:        if (!src->is_anyaddr(src))
                    616:        {
                    617:                if (family == AF_INET)
                    618:                {
                    619:                        len = send_msg_v4(skt->fd, &msg, src);
                    620:                }
                    621:                else
                    622:                {
                    623:                        len = send_msg_v6(skt->fd, &msg, src);
                    624:                }
                    625:        }
                    626:        else
                    627:        {
                    628:                len = send_msg_generic(skt->fd, &msg);
                    629:        }
                    630: 
                    631:        if (len != data.len)
                    632:        {
                    633:                DBG1(DBG_NET, "error writing to socket: %s", strerror(errno));
                    634:                return FAILED;
                    635:        }
                    636:        return SUCCESS;
                    637: }
                    638: 
                    639: METHOD(socket_t, get_port, uint16_t,
                    640:        private_socket_dynamic_socket_t *this, bool nat_t)
                    641: {
                    642:        /* we return 0 here for users that have no explicit port configured, the
                    643:         * sender will default to the default port in this case */
                    644:        return 0;
                    645: }
                    646: 
                    647: METHOD(socket_t, supported_families, socket_family_t,
                    648:        private_socket_dynamic_socket_t *this)
                    649: {
                    650:        /* we could return only the families of the opened sockets, but it could
                    651:         * be that both families are supported even if no socket is yet open */
                    652:        return SOCKET_FAMILY_BOTH;
                    653: }
                    654: 
                    655: METHOD(socket_t, destroy, void,
                    656:        private_socket_dynamic_socket_t *this)
                    657: {
                    658:        enumerator_t *enumerator;
                    659:        dynsock_t *key, *value;
                    660: 
                    661:        enumerator = this->sockets->create_enumerator(this->sockets);
                    662:        while (enumerator->enumerate(enumerator, &key, &value))
                    663:        {
                    664:                close(value->fd);
                    665:                free(value);
                    666:        }
                    667:        enumerator->destroy(enumerator);
                    668:        this->sockets->destroy(this->sockets);
                    669:        this->lock->destroy(this->lock);
                    670: 
                    671:        close(this->notify[0]);
                    672:        close(this->notify[1]);
                    673:        free(this);
                    674: }
                    675: 
                    676: /*
                    677:  * See header for description
                    678:  */
                    679: socket_dynamic_socket_t *socket_dynamic_socket_create()
                    680: {
                    681:        private_socket_dynamic_socket_t *this;
                    682: 
                    683:        INIT(this,
                    684:                .public = {
                    685:                        .socket = {
                    686:                                .send = _sender,
                    687:                                .receive = _receiver,
                    688:                                .get_port = _get_port,
                    689:                                .supported_families = _supported_families,
                    690:                                .destroy = _destroy,
                    691:                        },
                    692:                },
                    693:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                    694:                .max_packet = lib->settings->get_int(lib->settings,
                    695:                                                                "%s.max_packet", PACKET_MAX_DEFAULT, lib->ns),
                    696:        );
                    697: 
                    698:        if (pipe(this->notify) != 0)
                    699:        {
                    700:                DBG1(DBG_NET, "creating notify pipe for dynamic socket failed");
                    701:                free(this);
                    702:                return NULL;
                    703:        }
                    704: 
                    705:        this->sockets = hashtable_create((void*)hash, (void*)equals, 8);
                    706: 
                    707:        return &this->public;
                    708: }

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