Annotation of embedaddon/strongswan/src/libcharon/plugins/socket_win/socket_win_socket.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2013 Martin Willi
        !             3:  * Copyright (C) 2013 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: /* for WSAID_WSASENDMSG, Windows 7 */
        !            17: #define _WIN32_WINNT 0x0601
        !            18: 
        !            19: #include "socket_win_socket.h"
        !            20: 
        !            21: #include <library.h>
        !            22: #include <threading/thread.h>
        !            23: #include <daemon.h>
        !            24: 
        !            25: #include <mswsock.h>
        !            26: 
        !            27: /* number of sockets in use */
        !            28: #define SOCKET_COUNT 2
        !            29: 
        !            30: /* missing on MinGW */
        !            31: #ifndef IPV6_V6ONLY
        !            32: # define IPV6_V6ONLY 27
        !            33: #endif
        !            34: 
        !            35: /* GUIDS to lookup WSASend/RecvMsg */
        !            36: static GUID WSARecvMsgGUID = WSAID_WSARECVMSG;
        !            37: static GUID WSASendMsgGUID = WSAID_WSASENDMSG;
        !            38: 
        !            39: typedef struct private_socket_win_socket_t private_socket_win_socket_t;
        !            40: 
        !            41: /**
        !            42:  * Private data of an socket_t object
        !            43:  */
        !            44: struct private_socket_win_socket_t {
        !            45: 
        !            46:        /**
        !            47:         * public functions
        !            48:         */
        !            49:        socket_win_socket_t public;
        !            50: 
        !            51:        /**
        !            52:         * Port for each socket
        !            53:         */
        !            54:        uint16_t ports[SOCKET_COUNT];
        !            55: 
        !            56:        /**
        !            57:         * IPv4/IPv6 dual-use sockets
        !            58:         */
        !            59:        SOCKET socks[SOCKET_COUNT];
        !            60: 
        !            61:        /**
        !            62:         * Events to wait for socket data
        !            63:         */
        !            64:        HANDLE events[SOCKET_COUNT];
        !            65: 
        !            66:        /**
        !            67:         * Maximum packet size to receive
        !            68:         */
        !            69:        int max_packet;
        !            70: 
        !            71:        /**
        !            72:         * WSASendMsg function
        !            73:         */
        !            74:        int WINAPI (*WSASendMsg)(SOCKET, LPWSAMSG, DWORD, LPDWORD,
        !            75:                                        LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
        !            76: 
        !            77:        /**
        !            78:         * WSARecvMsg function
        !            79:         */
        !            80:        int WINAPI (*WSARecvMsg)(SOCKET, LPWSAMSG, LPDWORD,
        !            81:                                        LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
        !            82: };
        !            83: 
        !            84: METHOD(socket_t, receiver, status_t,
        !            85:        private_socket_win_socket_t *this, packet_t **out)
        !            86: {
        !            87:        char buf[this->max_packet], cbuf[128];
        !            88:        bool old;
        !            89:        DWORD i, len, err;
        !            90:        WSAMSG msg;
        !            91:        WSABUF data;
        !            92:        WSACMSGHDR *cmsg;
        !            93:        SOCKADDR_IN6 addr;
        !            94:        host_t *src = NULL, *dst = NULL;
        !            95:        packet_t *pkt;
        !            96: 
        !            97:        data.buf = buf;
        !            98:        data.len = sizeof(buf);
        !            99: 
        !           100:        memset(&msg, 0, sizeof(msg));
        !           101:        msg.name = (struct sockaddr*)&addr;
        !           102:        msg.namelen = sizeof(addr);
        !           103:        msg.lpBuffers = &data;
        !           104:        msg.dwBufferCount = 1;
        !           105:        msg.Control.buf = cbuf;
        !           106:        msg.Control.len = sizeof(cbuf);
        !           107: 
        !           108:        /* wait for socket events */
        !           109:        old = thread_cancelability(TRUE);
        !           110:        i = WSAWaitForMultipleEvents(SOCKET_COUNT, this->events,
        !           111:                                                                 FALSE, INFINITE, TRUE);
        !           112:        thread_cancelability(old);
        !           113:        if (i < WSA_WAIT_EVENT_0 || i >= WSA_WAIT_EVENT_0 + SOCKET_COUNT)
        !           114:        {
        !           115:                DBG1(DBG_NET, "waiting on sockets failed: %d", WSAGetLastError());
        !           116:                return FAILED;
        !           117:        }
        !           118:        i -= WSA_WAIT_EVENT_0;
        !           119: 
        !           120:        /* WSAEvents must be reset manually */
        !           121:        WSAResetEvent(this->events[i]);
        !           122: 
        !           123:        if (this->WSARecvMsg(this->socks[i], &msg, &len,
        !           124:                                                 NULL, NULL) == SOCKET_ERROR)
        !           125:        {
        !           126:                err = WSAGetLastError();
        !           127:                /* ignore WSAECONNRESET; this is returned for any ICMP port unreachable,
        !           128:                 * for a packet we sent, but is most likely not related to the packet
        !           129:                 * we try to receive. */
        !           130:                if (err != WSAECONNRESET)
        !           131:                {
        !           132:                        DBG1(DBG_NET, "reading from socket failed: %d", WSAGetLastError());
        !           133:                }
        !           134:                return FAILED;
        !           135:        }
        !           136: 
        !           137:        DBG3(DBG_NET, "received packet %b", buf, (int)len);
        !           138: 
        !           139:        for (cmsg = WSA_CMSG_FIRSTHDR(&msg); dst == NULL && cmsg != NULL;
        !           140:                 cmsg = WSA_CMSG_NXTHDR(&msg, cmsg))
        !           141:        {
        !           142:                if (cmsg->cmsg_level == IPPROTO_IP &&
        !           143:                        cmsg->cmsg_type == IP_PKTINFO)
        !           144:                {
        !           145:                        struct in_pktinfo *pktinfo;
        !           146:                        struct sockaddr_in sin = {
        !           147:                                .sin_family = AF_INET,
        !           148:                        };
        !           149: 
        !           150:                        pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(cmsg);
        !           151:                        sin.sin_addr = pktinfo->ipi_addr;
        !           152:                        sin.sin_port = htons(this->ports[i]);
        !           153:                        dst = host_create_from_sockaddr((struct sockaddr*)&sin);
        !           154:                }
        !           155:                if (cmsg->cmsg_level == IPPROTO_IPV6 &&
        !           156:                        cmsg->cmsg_type == IPV6_PKTINFO)
        !           157:                {
        !           158:                        struct in6_pktinfo *pktinfo;
        !           159:                        struct sockaddr_in6 sin = {
        !           160:                                .sin6_family = AF_INET6,
        !           161:                        };
        !           162: 
        !           163:                        pktinfo = (struct in6_pktinfo*)WSA_CMSG_DATA(cmsg);
        !           164:                        sin.sin6_addr = pktinfo->ipi6_addr;
        !           165:                        sin.sin6_port = htons(this->ports[i]);
        !           166:                        dst = host_create_from_sockaddr((struct sockaddr*)&sin);
        !           167:                }
        !           168:        }
        !           169: 
        !           170:        if (!dst)
        !           171:        {
        !           172:                DBG1(DBG_NET, "receiving IP destination address failed");
        !           173:                return FAILED;
        !           174:        }
        !           175: 
        !           176:        switch (dst->get_family(dst))
        !           177:        {
        !           178:                case AF_INET6:
        !           179:                        src = host_create_from_sockaddr((struct sockaddr*)&addr);
        !           180:                        break;
        !           181:                case AF_INET:
        !           182:                        /* extract v4 address from mapped v6 */
        !           183:                        src = host_create_from_chunk(AF_INET,
        !           184:                                                                chunk_create(addr.sin6_addr.u.Byte + 12, 4),
        !           185:                                                                ntohs(addr.sin6_port));
        !           186:                        break;
        !           187:        }
        !           188:        if (!src)
        !           189:        {
        !           190:                DBG1(DBG_NET, "receiving IP source address failed");
        !           191:                dst->destroy(dst);
        !           192:                return FAILED;
        !           193:        }
        !           194: 
        !           195:        pkt = packet_create();
        !           196:        pkt->set_source(pkt, src);
        !           197:        pkt->set_destination(pkt, dst);
        !           198:        DBG2(DBG_NET, "received packet: from %#H to %#H", src, dst);
        !           199:        pkt->set_data(pkt, chunk_clone(chunk_create(buf, len)));
        !           200: 
        !           201:        *out = pkt;
        !           202:        return SUCCESS;
        !           203: }
        !           204: 
        !           205: METHOD(socket_t, sender, status_t,
        !           206:        private_socket_win_socket_t *this, packet_t *packet)
        !           207: {
        !           208:        uint16_t port;
        !           209:        int i = -1, j;
        !           210:        host_t *src, *dst;
        !           211:        WSAMSG msg;
        !           212:        DWORD len;
        !           213:        WSABUF data;
        !           214:        WSACMSGHDR *cmsg;
        !           215:        SOCKADDR_IN6 addr = {
        !           216:                .sin6_family = AF_INET6,
        !           217:                .sin6_addr = {
        !           218:                        .u = {
        !           219:                                .Byte = {
        !           220:                                        /* v6-mapped-v4 by default */
        !           221:                                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        !           222:                                        0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,
        !           223:                                },
        !           224:                        },
        !           225:                },
        !           226:        };
        !           227:        char buf[WSA_CMSG_SPACE(max(sizeof(struct in6_pktinfo),
        !           228:                                                                sizeof(struct in_pktinfo)))];
        !           229: 
        !           230:        src = packet->get_source(packet);
        !           231:        dst = packet->get_destination(packet);
        !           232:        data.len = packet->get_data(packet).len;
        !           233:        data.buf = packet->get_data(packet).ptr;
        !           234: 
        !           235:        DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
        !           236: 
        !           237:        DBG3(DBG_NET, "sending packet %b", data.buf, (int)data.len);
        !           238: 
        !           239:        port = src->get_port(src);
        !           240:        for (j = 0; j < SOCKET_COUNT; j++)
        !           241:        {
        !           242:                if (!port || this->ports[j] == port)
        !           243:                {
        !           244:                        i = j;
        !           245:                        break;
        !           246:                }
        !           247:        }
        !           248:        if (i == -1)
        !           249:        {
        !           250:                DBG1(DBG_NET, "no socket found to send packet from port %u", port);
        !           251:                return FAILED;
        !           252:        }
        !           253: 
        !           254:        /* copy destination IPv6, or last 32 bits of mapped IPv4 address */
        !           255:        len = dst->get_address(dst).len;
        !           256:        if (len > sizeof(addr.sin6_addr))
        !           257:        {
        !           258:                return FAILED;
        !           259:        }
        !           260:        memcpy(addr.sin6_addr.u.Byte + sizeof(addr.sin6_addr) - len,
        !           261:                   dst->get_address(dst).ptr, len);
        !           262:        addr.sin6_port = htons(dst->get_port(dst));
        !           263: 
        !           264:        memset(&msg, 0, sizeof(msg));
        !           265:        msg.name = (struct sockaddr*)&addr;
        !           266:        msg.namelen = sizeof(addr);
        !           267:        msg.lpBuffers = &data;
        !           268:        msg.dwBufferCount = 1;
        !           269: 
        !           270:        if (!src->is_anyaddr(src))
        !           271:        {
        !           272:                memset(buf, 0, sizeof(buf));
        !           273:                msg.Control.buf = buf;
        !           274: 
        !           275:                switch (src->get_family(src))
        !           276:                {
        !           277:                        case AF_INET:
        !           278:                        {
        !           279:                                struct in_pktinfo *pktinfo;
        !           280:                                SOCKADDR_IN *sin;
        !           281: 
        !           282:                                msg.Control.len = WSA_CMSG_SPACE(sizeof(*pktinfo));
        !           283:                                cmsg = WSA_CMSG_FIRSTHDR(&msg);
        !           284:                                cmsg->cmsg_level = IPPROTO_IP;
        !           285:                                cmsg->cmsg_type = IP_PKTINFO;
        !           286:                                cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(*pktinfo));
        !           287:                                pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(cmsg);
        !           288:                                sin = (SOCKADDR_IN*)src->get_sockaddr(src);
        !           289:                                pktinfo->ipi_addr = sin->sin_addr;
        !           290:                                break;
        !           291:                        }
        !           292:                        case AF_INET6:
        !           293:                        {
        !           294:                                struct in6_pktinfo *pktinfo;
        !           295:                                SOCKADDR_IN6 *sin;
        !           296: 
        !           297:                                msg.Control.len = WSA_CMSG_SPACE(sizeof(*pktinfo));
        !           298:                                cmsg = WSA_CMSG_FIRSTHDR(&msg);
        !           299:                                cmsg->cmsg_level = IPPROTO_IPV6;
        !           300:                                cmsg->cmsg_type = IPV6_PKTINFO;
        !           301:                                cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(*pktinfo));
        !           302:                                pktinfo = (struct in6_pktinfo*)WSA_CMSG_DATA(cmsg);
        !           303:                                sin = (SOCKADDR_IN6*)src->get_sockaddr(src);
        !           304:                                pktinfo->ipi6_addr = sin->sin6_addr;
        !           305:                                break;
        !           306:                        }
        !           307:                }
        !           308:        }
        !           309: 
        !           310:        if (this->WSASendMsg(this->socks[i], &msg, 0, &len,
        !           311:                                                 NULL, NULL) == SOCKET_ERROR)
        !           312:        {
        !           313:                DBG1(DBG_NET, "sending packet failed: %d", WSAGetLastError());
        !           314:                return FAILED;
        !           315:        }
        !           316:        return SUCCESS;
        !           317: }
        !           318: 
        !           319: METHOD(socket_t, get_port, uint16_t,
        !           320:        private_socket_win_socket_t *this, bool nat)
        !           321: {
        !           322:        return this->ports[nat != 0];
        !           323: }
        !           324: 
        !           325: METHOD(socket_t, supported_families, socket_family_t,
        !           326:        private_socket_win_socket_t *this)
        !           327: {
        !           328:        return SOCKET_FAMILY_IPV4 | SOCKET_FAMILY_IPV6;
        !           329: }
        !           330: 
        !           331: /**
        !           332:  * Open an IPv4/IPv6 dual-use socket to send and receive packets
        !           333:  */
        !           334: static SOCKET open_socket(private_socket_win_socket_t *this, int i)
        !           335: {
        !           336:        SOCKADDR_IN6 addr = {
        !           337:                .sin6_family = AF_INET6,
        !           338:                .sin6_port = htons(this->ports[i]),
        !           339:        };
        !           340:        int addrlen = sizeof(addr);
        !           341:        BOOL on = TRUE, off = FALSE;
        !           342:        DWORD dwon = TRUE;
        !           343:        SOCKET s;
        !           344: 
        !           345:        s = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
        !           346:        if (s == INVALID_SOCKET)
        !           347:        {
        !           348:                DBG1(DBG_NET, "creating socket failed: %d", WSAGetLastError());
        !           349:                return INVALID_SOCKET;
        !           350:        }
        !           351:        /* enable IPv4 on IPv6 socket */
        !           352:        if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
        !           353:                                   (const char*)&off, sizeof(off)) == SOCKET_ERROR)
        !           354:        {
        !           355:                DBG1(DBG_NET, "using dual-mode socket failed: %d", WSAGetLastError());
        !           356:                closesocket(s);
        !           357:                return INVALID_SOCKET;
        !           358:        }
        !           359:        if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
        !           360:                                   (const char*)&on, sizeof(on)) == SOCKET_ERROR)
        !           361:        {
        !           362:                DBG1(DBG_NET, "enabling SO_REUSEADDR failed: %d", WSAGetLastError());
        !           363:                closesocket(s);
        !           364:                return INVALID_SOCKET;
        !           365:        }
        !           366:        if (bind(s, (const struct sockaddr*)&addr, addrlen) == SOCKET_ERROR)
        !           367:        {
        !           368:                DBG1(DBG_NET, "unable to bind socket: %d", WSAGetLastError());
        !           369:                closesocket(s);
        !           370:                return INVALID_SOCKET;
        !           371:        }
        !           372:        /* retrieve randomly allocated port if needed */
        !           373:        if (this->ports[i] == 0)
        !           374:        {
        !           375:                if (getsockname(s, (struct sockaddr*)&addr,
        !           376:                                                &addrlen) == SOCKET_ERROR)
        !           377:                {
        !           378:                        DBG1(DBG_NET, "unable to determine port: %d", WSAGetLastError());
        !           379:                        closesocket(s);
        !           380:                        return INVALID_SOCKET;
        !           381:                }
        !           382:                this->ports[i] = ntohs(addr.sin6_port);
        !           383:        }
        !           384:        /* PKTINFO is required for both protocol families */
        !           385:        if (setsockopt(s, IPPROTO_IP, IP_PKTINFO,
        !           386:                                   (char*)&dwon, sizeof(dwon)) == SOCKET_ERROR)
        !           387:        {
        !           388:                DBG1(DBG_NET, "unable to set IP_PKTINFO: %d", WSAGetLastError());
        !           389:                closesocket(s);
        !           390:                return INVALID_SOCKET;
        !           391:        }
        !           392:        if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO,
        !           393:                                   (char*)&dwon, sizeof(dwon)) == SOCKET_ERROR)
        !           394:        {
        !           395:                DBG1(DBG_NET, "unable to set IP6_PKTINFO: %d", WSAGetLastError());
        !           396:                closesocket(s);
        !           397:                return INVALID_SOCKET;
        !           398:        }
        !           399:        if (!charon->kernel->bypass_socket(charon->kernel, s, AF_INET))
        !           400:        {
        !           401:                DBG1(DBG_NET, "installing IPv4 IKE bypass policy failed");
        !           402:        }
        !           403:        if (!charon->kernel->bypass_socket(charon->kernel, s, AF_INET6))
        !           404:        {
        !           405:                DBG1(DBG_NET, "installing IPv6 IKE bypass policy failed");
        !           406:        }
        !           407:        return s;
        !           408: }
        !           409: 
        !           410: METHOD(socket_t, destroy, void,
        !           411:        private_socket_win_socket_t *this)
        !           412: {
        !           413:        int i;
        !           414: 
        !           415:        for (i = 0; i < SOCKET_COUNT; i++)
        !           416:        {
        !           417:                if (this->socks[i] != INVALID_SOCKET)
        !           418:                {
        !           419:                        closesocket(this->socks[i]);
        !           420:                }
        !           421:                if (this->events[i] != WSA_INVALID_EVENT)
        !           422:                {
        !           423:                        WSACloseEvent(this->events[i]);
        !           424:                }
        !           425:        }
        !           426:        free(this);
        !           427: }
        !           428: 
        !           429: /*
        !           430:  * See header for description
        !           431:  */
        !           432: socket_win_socket_t *socket_win_socket_create()
        !           433: {
        !           434:        private_socket_win_socket_t *this;
        !           435:        DWORD len;
        !           436:        int i;
        !           437: 
        !           438:        INIT(this,
        !           439:                .public = {
        !           440:                        .socket = {
        !           441:                                .send = _sender,
        !           442:                                .receive = _receiver,
        !           443:                                .get_port = _get_port,
        !           444:                                .supported_families = _supported_families,
        !           445:                                .destroy = _destroy,
        !           446:                        },
        !           447:                },
        !           448:                .ports = {
        !           449:                        lib->settings->get_int(lib->settings,
        !           450:                                                        "%s.port", CHARON_UDP_PORT, lib->ns),
        !           451:                        lib->settings->get_int(lib->settings,
        !           452:                                                        "%s.port_nat_t", CHARON_NATT_PORT, lib->ns),
        !           453:                },
        !           454:                .max_packet = lib->settings->get_int(lib->settings,
        !           455:                                                        "%s.max_packet", PACKET_MAX_DEFAULT, lib->ns),
        !           456:        );
        !           457: 
        !           458:        for (i = 0; i < SOCKET_COUNT; i++)
        !           459:        {
        !           460:                this->socks[i] = open_socket(this, i);
        !           461:                this->events[i] = WSACreateEvent();
        !           462:        }
        !           463: 
        !           464:        for (i = 0; i < SOCKET_COUNT; i++)
        !           465:        {
        !           466:                if (this->events[i] == WSA_INVALID_EVENT ||
        !           467:                        this->socks[i] == INVALID_SOCKET)
        !           468:                {
        !           469:                        DBG1(DBG_NET, "creating socket failed: %d", WSAGetLastError());
        !           470:                        destroy(this);
        !           471:                        return NULL;
        !           472:                }
        !           473:                if (WSAEventSelect(this->socks[i], this->events[i],
        !           474:                                                   FD_READ) == SOCKET_ERROR)
        !           475:                {
        !           476:                        DBG1(DBG_NET, "WSAEventSelect() failed: %d", WSAGetLastError());
        !           477:                        destroy(this);
        !           478:                        return NULL;
        !           479:                }
        !           480:        }
        !           481: 
        !           482:        if (WSAIoctl(this->socks[0], SIO_GET_EXTENSION_FUNCTION_POINTER,
        !           483:                        &WSASendMsgGUID, sizeof(WSASendMsgGUID), &this->WSASendMsg,
        !           484:                        sizeof(this->WSASendMsg), &len, NULL, NULL) != 0 ||
        !           485:                WSAIoctl(this->socks[0], SIO_GET_EXTENSION_FUNCTION_POINTER,
        !           486:                        &WSARecvMsgGUID, sizeof(WSARecvMsgGUID), &this->WSARecvMsg,
        !           487:                        sizeof(this->WSARecvMsg), &len, NULL, NULL) != 0)
        !           488:        {
        !           489:                DBG1(DBG_NET, "send/recvmsg() lookup failed: %d", WSAGetLastError());
        !           490:                destroy(this);
        !           491:                return NULL;
        !           492:        }
        !           493: 
        !           494:        return &this->public;
        !           495: }

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