Annotation of embedaddon/ipsec-tools/src/racoon/sockmisc.c, revision 1.1.1.1

1.1       misho       1: /*     $NetBSD: sockmisc.c,v 1.19 2011/03/14 17:18:13 tteras Exp $     */
                      2: 
                      3: /* Id: sockmisc.c,v 1.24 2006/05/07 21:32:59 manubsd Exp */
                      4: 
                      5: /*
                      6:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      7:  * All rights reserved.
                      8:  * 
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. Neither the name of the project nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  * 
                     21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  */
                     33: 
                     34: #include "config.h"
                     35: 
                     36: #include <sys/types.h>
                     37: #include <sys/param.h>
                     38: #include <sys/socket.h>
                     39: #include <sys/uio.h>
                     40: 
                     41: #include <netinet/in.h>
                     42: #include PATH_IPSEC_H
                     43: 
                     44: #if defined(INET6) && !defined(INET6_ADVAPI) && \
                     45:        defined(IP_RECVDSTADDR) && !defined(IPV6_RECVDSTADDR)
                     46: #define IPV6_RECVDSTADDR IP_RECVDSTADDR
                     47: #endif
                     48: 
                     49: #include <stdlib.h>
                     50: #include <stdio.h>
                     51: #include <string.h>
                     52: #include <errno.h>
                     53: #ifdef HAVE_UNISTD_H
                     54: #include <unistd.h>
                     55: #endif
                     56: 
                     57: #include "var.h"
                     58: #include "misc.h"
                     59: #include "vmbuf.h"
                     60: #include "plog.h"
                     61: #include "sockmisc.h"
                     62: #include "debug.h"
                     63: #include "gcmalloc.h"
                     64: #include "debugrm.h"
                     65: #include "libpfkey.h"
                     66: #include "isakmp_var.h"
                     67: 
                     68: #ifdef NOUSE_PRIVSEP
                     69: #define BIND bind
                     70: #define SOCKET socket
                     71: #define SETSOCKOPT setsockopt
                     72: #else
                     73: #include "admin.h"
                     74: #include "privsep.h"
                     75: #define BIND privsep_bind
                     76: #define SOCKET privsep_socket
                     77: #define SETSOCKOPT privsep_setsockopt
                     78: #endif
                     79: 
                     80: const int niflags = 0;
                     81: 
                     82: /*
                     83:  * compare two sockaddr with port, taking care wildcard.
                     84:  * addr1 is a subject address, addr2 is in a database entry.
                     85:  * OUT:        0: equal.
                     86:  *     1: not equal.
                     87:  */
                     88: int
                     89: cmpsaddr(addr1, addr2)
                     90:        const struct sockaddr *addr1;
                     91:        const struct sockaddr *addr2;
                     92: {
                     93:        caddr_t sa1, sa2;
                     94:        u_short port1 = IPSEC_PORT_ANY;
                     95:        u_short port2 = IPSEC_PORT_ANY;
                     96: 
                     97:        if (addr1 == NULL && addr2 == NULL)
                     98:                return CMPSADDR_MATCH;
                     99: 
                    100:        if (addr1 == NULL || addr2 == NULL)
                    101:                return CMPSADDR_MISMATCH;
                    102: 
                    103:        if (addr1->sa_family != addr2->sa_family ||
                    104:            sysdep_sa_len(addr1) != sysdep_sa_len(addr2))
                    105:                return CMPSADDR_MISMATCH;
                    106: 
                    107:        switch (addr1->sa_family) {
                    108:        case AF_UNSPEC:
                    109:                break;
                    110:        case AF_INET:
                    111:                sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
                    112:                sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
                    113:                port1 = ((struct sockaddr_in *)addr1)->sin_port;
                    114:                port2 = ((struct sockaddr_in *)addr2)->sin_port;
                    115:                if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
                    116:                        return CMPSADDR_MISMATCH;
                    117:                break;
                    118: #ifdef INET6
                    119:        case AF_INET6:
                    120:                sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
                    121:                sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
                    122:                port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
                    123:                port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
                    124:                if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
                    125:                        return CMPSADDR_MISMATCH;
                    126:                if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
                    127:                    ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
                    128:                        return CMPSADDR_MISMATCH;
                    129:                break;
                    130: #endif
                    131:        default:
                    132:                return CMPSADDR_MISMATCH;
                    133:        }
                    134: 
                    135:        if (port1 == port2)
                    136:                return CMPSADDR_MATCH;
                    137: 
                    138:        if (port1 == IPSEC_PORT_ANY ||
                    139:            port2 == IPSEC_PORT_ANY)
                    140:                return CMPSADDR_WILDPORT_MATCH;
                    141: 
                    142:        return CMPSADDR_WOP_MATCH;
                    143: }
                    144: 
                    145: /* get local address against the destination. */
                    146: struct sockaddr *
                    147: getlocaladdr(remote)
                    148:        struct sockaddr *remote;
                    149: {
                    150:        struct sockaddr *local;
                    151:        u_int local_len = sizeof(struct sockaddr_storage);
                    152:        int s;  /* for dummy connection */
                    153: 
                    154:        /* allocate buffer */
                    155:        if ((local = racoon_calloc(1, local_len)) == NULL) {
                    156:                plog(LLV_ERROR, LOCATION, NULL,
                    157:                        "failed to get address buffer.\n");
                    158:                goto err;
                    159:        }
                    160:        
                    161:        /* get real interface received packet */
                    162:        if ((s = SOCKET(remote->sa_family, SOCK_DGRAM, 0)) < 0) {
                    163:                plog(LLV_ERROR, LOCATION, NULL,
                    164:                        "socket (%s)\n", strerror(errno));
                    165:                goto err;
                    166:        }
                    167: 
                    168:        setsockopt_bypass(s, remote->sa_family);
                    169:        
                    170:        if (connect(s, remote, sysdep_sa_len(remote)) < 0) {
                    171:                plog(LLV_ERROR, LOCATION, NULL,
                    172:                        "connect (%s)\n", strerror(errno));
                    173:                close(s);
                    174:                goto err;
                    175:        }
                    176: 
                    177:        if (getsockname(s, local, &local_len) < 0) {
                    178:                plog(LLV_ERROR, LOCATION, NULL,
                    179:                        "getsockname (%s)\n", strerror(errno));
                    180:                close(s);
                    181:                return NULL;
                    182:        }
                    183: 
                    184:        close(s);
                    185:        return local;
                    186: 
                    187:     err:
                    188:        if (local != NULL)
                    189:                racoon_free(local);
                    190:        return NULL;
                    191: }
                    192: 
                    193: /*
                    194:  * Receive packet, with src/dst information.  It is assumed that necessary
                    195:  * setsockopt() have already performed on socket.
                    196:  */
                    197: int
                    198: recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
                    199:        int s;
                    200:        void *buf;
                    201:        size_t buflen;
                    202:        int flags;
                    203:        struct sockaddr *from;
                    204:        socklen_t *fromlen;
                    205:        struct sockaddr *to;
                    206:        u_int *tolen;
                    207: {
                    208:        int otolen;
                    209:        socklen_t slen;
                    210:        int len;
                    211:        union sockaddr_any sa;
                    212:        struct msghdr m;
                    213:        struct cmsghdr *cm;
                    214:        struct iovec iov[2];
                    215:        u_char cmsgbuf[256];
                    216: #if defined(INET6) && defined(INET6_ADVAPI)
                    217:        struct in6_pktinfo *pi;
                    218: #endif /*INET6_ADVAPI*/
                    219:        struct sockaddr_in *sin;
                    220: #ifdef INET6
                    221:        struct sockaddr_in6 *sin6;
                    222: #endif
                    223: 
                    224:        slen = sizeof(sa);
                    225:        if (getsockname(s, &sa.sa, &slen) < 0) {
                    226:                plog(LLV_ERROR, LOCATION, NULL,
                    227:                        "getsockname (%s)\n", strerror(errno));
                    228:                return -1;
                    229:        }
                    230: 
                    231:        m.msg_name = (caddr_t)from;
                    232:        m.msg_namelen = *fromlen;
                    233:        iov[0].iov_base = (caddr_t)buf;
                    234:        iov[0].iov_len = buflen;
                    235:        m.msg_iov = iov;
                    236:        m.msg_iovlen = 1;
                    237:        memset(cmsgbuf, 0, sizeof(cmsgbuf));
                    238:        cm = (struct cmsghdr *)cmsgbuf;
                    239:        m.msg_control = (caddr_t)cm;
                    240:        m.msg_controllen = sizeof(cmsgbuf);
                    241:        if ((len = recvmsg(s, &m, flags)) < 0) {
                    242:                plog(LLV_ERROR, LOCATION, NULL,
                    243:                        "recvmsg (%s)\n", strerror(errno));
                    244:                return -1;
                    245:        }
                    246:        *fromlen = m.msg_namelen;
                    247: 
                    248:        otolen = *tolen;
                    249:        *tolen = 0;
                    250:        for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m);
                    251:             m.msg_controllen != 0 && cm;
                    252:             cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) {
                    253: #if 0
                    254:                plog(LLV_ERROR, LOCATION, NULL,
                    255:                        "cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type);)
                    256: #endif
                    257: #if defined(INET6) && defined(INET6_ADVAPI)
                    258:                if (sa.sa.sa_family == AF_INET6
                    259:                 && cm->cmsg_level == IPPROTO_IPV6
                    260:                 && cm->cmsg_type == IPV6_PKTINFO
                    261:                 && otolen >= sizeof(*sin6)) {
                    262:                        pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
                    263:                        *tolen = sizeof(*sin6);
                    264:                        sin6 = (struct sockaddr_in6 *)to;
                    265:                        memset(sin6, 0, sizeof(*sin6));
                    266:                        sin6->sin6_family = AF_INET6;
                    267: #ifndef __linux__
                    268:                        sin6->sin6_len = sizeof(*sin6);
                    269: #endif
                    270:                        memcpy(&sin6->sin6_addr, &pi->ipi6_addr,
                    271:                                sizeof(sin6->sin6_addr));
                    272:                        /* XXX other cases, such as site-local? */
                    273:                        if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
                    274:                                sin6->sin6_scope_id = pi->ipi6_ifindex;
                    275:                        else
                    276:                                sin6->sin6_scope_id = 0;
                    277:                        sin6->sin6_port = sa.sin6.sin6_port;
                    278:                        otolen = -1;    /* "to" already set */
                    279:                        continue;
                    280:                }
                    281: #endif
                    282: #ifdef __linux__
                    283:                if (sa.sa.sa_family == AF_INET
                    284:                 && cm->cmsg_level == IPPROTO_IP
                    285:                 && cm->cmsg_type == IP_PKTINFO
                    286:                 && otolen >= sizeof(sin)) {
                    287:                        struct in_pktinfo *pi = (struct in_pktinfo *)(CMSG_DATA(cm));
                    288:                        *tolen = sizeof(*sin);
                    289:                        sin = (struct sockaddr_in *)to;
                    290:                        memset(sin, 0, sizeof(*sin));
                    291:                        sin->sin_family = AF_INET;
                    292:                        memcpy(&sin->sin_addr, &pi->ipi_addr,
                    293:                                sizeof(sin->sin_addr));
                    294:                        sin->sin_port = sa.sin.sin_port;
                    295:                        otolen = -1;    /* "to" already set */
                    296:                        continue;
                    297:                }
                    298: #endif
                    299: #if defined(INET6) && defined(IPV6_RECVDSTADDR)
                    300:                if (sa.sa.sa_family == AF_INET6
                    301:                      && cm->cmsg_level == IPPROTO_IPV6
                    302:                      && cm->cmsg_type == IPV6_RECVDSTADDR
                    303:                      && otolen >= sizeof(*sin6)) {
                    304:                        *tolen = sizeof(*sin6);
                    305:                        sin6 = (struct sockaddr_in6 *)to;
                    306:                        memset(sin6, 0, sizeof(*sin6));
                    307:                        sin6->sin6_family = AF_INET6;
                    308:                        sin6->sin6_len = sizeof(*sin6);
                    309:                        memcpy(&sin6->sin6_addr, CMSG_DATA(cm),
                    310:                                sizeof(sin6->sin6_addr));
                    311:                        sin6->sin6_port = sa.sin6.sin6_port;
                    312:                        otolen = -1;    /* "to" already set */
                    313:                        continue;
                    314:                }
                    315: #endif
                    316: #ifndef __linux__
                    317:                if (sa.sa.sa_family == AF_INET
                    318:                 && cm->cmsg_level == IPPROTO_IP
                    319:                 && cm->cmsg_type == IP_RECVDSTADDR
                    320:                 && otolen >= sizeof(*sin)) {
                    321:                        *tolen = sizeof(*sin);
                    322:                        sin = (struct sockaddr_in *)to;
                    323:                        memset(sin, 0, sizeof(*sin));
                    324:                        sin->sin_family = AF_INET;
                    325:                        sin->sin_len = sizeof(*sin);
                    326:                        memcpy(&sin->sin_addr, CMSG_DATA(cm),
                    327:                                sizeof(sin->sin_addr));
                    328:                        sin->sin_port = sa.sin.sin_port;
                    329:                        otolen = -1;    /* "to" already set */
                    330:                        continue;
                    331:                }
                    332: #endif
                    333:        }
                    334: 
                    335:        return len;
                    336: }
                    337: 
                    338: /* send packet, with fixing src/dst address pair. */
                    339: int
                    340: sendfromto(s, buf, buflen, src, dst, cnt)
                    341:        int s, cnt;
                    342:        const void *buf;
                    343:        size_t buflen;
                    344:        struct sockaddr *src;
                    345:        struct sockaddr *dst;
                    346: {
                    347:        struct sockaddr_storage ss;
                    348:        socklen_t slen;
                    349:        int len = 0;
                    350:        int i;
                    351: 
                    352:        if (src->sa_family != dst->sa_family) {
                    353:                plog(LLV_ERROR, LOCATION, NULL,
                    354:                        "address family mismatch\n");
                    355:                return -1;
                    356:        }
                    357: 
                    358:        slen = sizeof(ss);
                    359:        if (getsockname(s, (struct sockaddr *)&ss, &slen) < 0) {
                    360:                plog(LLV_ERROR, LOCATION, NULL,
                    361:                        "getsockname (%s)\n", strerror(errno));
                    362:                return -1;
                    363:        }
                    364: 
                    365:        plog(LLV_DEBUG, LOCATION, NULL,
                    366:                "sockname %s\n", saddr2str((struct sockaddr *)&ss));
                    367:        plog(LLV_DEBUG, LOCATION, NULL,
                    368:                "send packet from %s\n", saddr2str(src));
                    369:        plog(LLV_DEBUG, LOCATION, NULL,
                    370:                "send packet to %s\n", saddr2str(dst));
                    371: 
                    372:        if (src->sa_family != ss.ss_family) {
                    373:                plog(LLV_ERROR, LOCATION, NULL,
                    374:                        "address family mismatch\n");
                    375:                return -1;
                    376:        }
                    377: 
                    378:        switch (src->sa_family) {
                    379: #if defined(INET6) && defined(INET6_ADVAPI)
                    380: // XXX: This block wasn't compiled on Linux - does it work?
                    381:        case AF_INET6:
                    382:            {
                    383:                struct msghdr m;
                    384:                struct cmsghdr *cm;
                    385:                struct iovec iov[2];
                    386:                u_char cmsgbuf[256];
                    387:                struct in6_pktinfo *pi;
                    388:                int ifindex;
                    389:                struct sockaddr_in6 src6, dst6;
                    390: 
                    391:                memcpy(&src6, src, sizeof(src6));
                    392:                memcpy(&dst6, dst, sizeof(dst6));
                    393: 
                    394:                /* XXX take care of other cases, such as site-local */
                    395:                ifindex = 0;
                    396:                if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr)
                    397:                 || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) {
                    398:                        ifindex = src6.sin6_scope_id;   /*???*/
                    399:                }
                    400: 
                    401:                /* XXX some sanity check on dst6.sin6_scope_id */
                    402: 
                    403:                /* flowinfo for IKE?  mmm, maybe useful but for now make it 0 */
                    404:                src6.sin6_flowinfo = dst6.sin6_flowinfo = 0;
                    405: 
                    406:                memset(&m, 0, sizeof(m));
                    407:                m.msg_name = (caddr_t)&dst6;
                    408:                m.msg_namelen = sizeof(dst6);
                    409:                iov[0].iov_base = (char *)buf;
                    410:                iov[0].iov_len = buflen;
                    411:                m.msg_iov = iov;
                    412:                m.msg_iovlen = 1;
                    413: 
                    414:                memset(cmsgbuf, 0, sizeof(cmsgbuf));
                    415:                cm = (struct cmsghdr *)cmsgbuf;
                    416:                m.msg_control = (caddr_t)cm;
                    417:                m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
                    418: 
                    419:                cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
                    420:                cm->cmsg_level = IPPROTO_IPV6;
                    421:                cm->cmsg_type = IPV6_PKTINFO;
                    422:                pi = (struct in6_pktinfo *)CMSG_DATA(cm);
                    423:                memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr));
                    424:                pi->ipi6_ifindex = ifindex;
                    425: 
                    426:                plog(LLV_DEBUG, LOCATION, NULL,
                    427:                        "src6 %s %d\n",
                    428:                        saddr2str((struct sockaddr *)&src6),
                    429:                        src6.sin6_scope_id);
                    430:                plog(LLV_DEBUG, LOCATION, NULL,
                    431:                        "dst6 %s %d\n",
                    432:                        saddr2str((struct sockaddr *)&dst6),
                    433:                        dst6.sin6_scope_id);
                    434: 
                    435:                for (i = 0; i < cnt; i++) {
                    436:                        len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
                    437:                        if (len < 0) {
                    438:                                plog(LLV_ERROR, LOCATION, NULL,
                    439:                                        "sendmsg (%s)\n", strerror(errno));
                    440:                                return -1;
                    441:                        }
                    442:                        plog(LLV_DEBUG, LOCATION, NULL,
                    443:                                "%d times of %d bytes message will be sent "
                    444:                                "to %s\n",
                    445:                                i + 1, len, saddr2str(dst));
                    446:                }
                    447:                plogdump(LLV_DEBUG, (char *)buf, buflen);
                    448: 
                    449:                return len;
                    450:            }
                    451: #endif
                    452: #ifdef __linux__
                    453:        case AF_INET:
                    454:            {
                    455:                struct msghdr m;
                    456:                struct cmsghdr *cm;
                    457:                struct iovec iov[2];
                    458:                u_char cmsgbuf[256];
                    459:                struct in_pktinfo *pi;
                    460:                int ifindex = 0;
                    461:                struct sockaddr_in src6, dst6;
                    462: 
                    463:                memcpy(&src6, src, sizeof(src6));
                    464:                memcpy(&dst6, dst, sizeof(dst6));
                    465: 
                    466:                memset(&m, 0, sizeof(m));
                    467:                m.msg_name = (caddr_t)&dst6;
                    468:                m.msg_namelen = sizeof(dst6);
                    469:                iov[0].iov_base = (char *)buf;
                    470:                iov[0].iov_len = buflen;
                    471:                m.msg_iov = iov;
                    472:                m.msg_iovlen = 1;
                    473: 
                    474:                memset(cmsgbuf, 0, sizeof(cmsgbuf));
                    475:                cm = (struct cmsghdr *)cmsgbuf;
                    476:                m.msg_control = (caddr_t)cm;
                    477:                m.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
                    478: 
                    479:                cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
                    480:                cm->cmsg_level = IPPROTO_IP;
                    481:                cm->cmsg_type = IP_PKTINFO;
                    482:                pi = (struct in_pktinfo *)CMSG_DATA(cm);
                    483:                memcpy(&pi->ipi_spec_dst, &src6.sin_addr, sizeof(src6.sin_addr));
                    484:                pi->ipi_ifindex = ifindex;
                    485: 
                    486:                plog(LLV_DEBUG, LOCATION, NULL,
                    487:                        "src4 %s\n",
                    488:                        saddr2str((struct sockaddr *)&src6));
                    489:                plog(LLV_DEBUG, LOCATION, NULL,
                    490:                        "dst4 %s\n",
                    491:                        saddr2str((struct sockaddr *)&dst6));
                    492: 
                    493:                for (i = 0; i < cnt; i++) {
                    494:                        len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/);
                    495:                        if (len < 0) {
                    496:                                plog(LLV_ERROR, LOCATION, NULL,
                    497:                                        "sendmsg (%s)\n", strerror(errno));
                    498:                                return -1;
                    499:                        }
                    500:                        plog(LLV_DEBUG, LOCATION, NULL,
                    501:                                "%d times of %d bytes message will be sent "
                    502:                                "to %s\n",
                    503:                                i + 1, len, saddr2str(dst));
                    504:                }
                    505:                plogdump(LLV_DEBUG, (char *)buf, buflen);
                    506: 
                    507:                return len;
                    508:            }
                    509: #endif /* __linux__ */
                    510:        default:
                    511:            {
                    512:                int needclose = 0;
                    513:                int sendsock;
                    514: 
                    515:                if (ss.ss_family == src->sa_family && memcmp(&ss, src, sysdep_sa_len(src)) == 0) {
                    516:                        sendsock = s;
                    517:                        needclose = 0;
                    518:                } else {
                    519:                        int yes = 1;
                    520:                        /*
                    521:                         * Use newly opened socket for sending packets.
                    522:                         * NOTE: this is unsafe, because if the peer is quick enough
                    523:                         * the packet from the peer may be queued into sendsock.
                    524:                         * Better approach is to prepare bind'ed udp sockets for
                    525:                         * each of the interface addresses.
                    526:                         */
                    527:                        sendsock = SOCKET(src->sa_family, SOCK_DGRAM, 0);
                    528:                        if (sendsock < 0) {
                    529:                                plog(LLV_ERROR, LOCATION, NULL,
                    530:                                        "socket (%s)\n", strerror(errno));
                    531:                                return -1;
                    532:                        }
                    533:                        if (setsockopt(sendsock, SOL_SOCKET,
                    534: #ifdef __linux__
                    535:                                       SO_REUSEADDR,
                    536: #else
                    537:                                       SO_REUSEPORT,
                    538: #endif
                    539:                                       (void *)&yes, sizeof(yes)) < 0) {
                    540:                                plog(LLV_ERROR, LOCATION, NULL,
                    541:                                        "setsockopt SO_REUSEPORT (%s)\n", 
                    542:                                        strerror(errno));
                    543:                                close(sendsock);
                    544:                                return -1;
                    545:                        }
                    546: #ifdef IPV6_USE_MIN_MTU
                    547:                        if (src->sa_family == AF_INET6 &&
                    548:                            setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
                    549:                            (void *)&yes, sizeof(yes)) < 0) {
                    550:                                plog(LLV_ERROR, LOCATION, NULL,
                    551:                                        "setsockopt IPV6_USE_MIN_MTU (%s)\n", 
                    552:                                        strerror(errno));
                    553:                                close(sendsock);
                    554:                                return -1;
                    555:                        }
                    556: #endif
                    557:                        if (setsockopt_bypass(sendsock, src->sa_family) < 0) {
                    558:                                close(sendsock);
                    559:                                return -1;
                    560:                        }
                    561: 
                    562:                        if (BIND(sendsock, (struct sockaddr *)src,
                    563:                                 sysdep_sa_len(src)) < 0) {
                    564:                                plog(LLV_ERROR, LOCATION, NULL,
                    565:                                        "bind 1 (%s)\n", strerror(errno));
                    566:                                close(sendsock);
                    567:                                return -1;
                    568:                        }
                    569:                        needclose = 1;
                    570:                }
                    571: 
                    572:                for (i = 0; i < cnt; i++) {
                    573:                        len = sendto(sendsock, buf, buflen, 0, dst, sysdep_sa_len(dst));
                    574:                        if (len < 0) {
                    575:                                plog(LLV_ERROR, LOCATION, NULL,
                    576:                                        "sendto (%s)\n", strerror(errno));
                    577:                                if (needclose)
                    578:                                        close(sendsock);
                    579:                                return len;
                    580:                        }
                    581:                        plog(LLV_DEBUG, LOCATION, NULL,
                    582:                                "%d times of %d bytes message will be sent "
                    583:                                "to %s\n",
                    584:                                i + 1, len, saddr2str(dst));
                    585:                }
                    586:                plogdump(LLV_DEBUG, (char *)buf, buflen);
                    587: 
                    588:                if (needclose)
                    589:                        close(sendsock);
                    590: 
                    591:                return len;
                    592:            }
                    593:        }
                    594: }
                    595: 
                    596: int
                    597: setsockopt_bypass(so, family)
                    598:        int so, family;
                    599: {
                    600:        int level;
                    601:        char *buf;
                    602:        char *policy;
                    603: 
                    604:        switch (family) {
                    605:        case AF_INET:
                    606:                level = IPPROTO_IP;
                    607:                break;
                    608: #ifdef INET6
                    609:        case AF_INET6:
                    610:                level = IPPROTO_IPV6;
                    611:                break;
                    612: #endif
                    613:        default:
                    614:                plog(LLV_ERROR, LOCATION, NULL,
                    615:                        "unsupported address family %d\n", family);
                    616:                return -1;
                    617:        }
                    618: 
                    619:        policy = "in bypass";
                    620:        buf = ipsec_set_policy(policy, strlen(policy));
                    621:        if (buf == NULL) {
                    622:                plog(LLV_ERROR, LOCATION, NULL,
                    623:                        "ipsec_set_policy (%s)\n",
                    624:                        ipsec_strerror());
                    625:                return -1;
                    626:        }
                    627:        if (SETSOCKOPT(so, level,
                    628:                       (level == IPPROTO_IP ?
                    629:                                 IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
                    630:                       buf, ipsec_get_policylen(buf)) < 0) {
                    631:                plog(LLV_ERROR, LOCATION, NULL,
                    632:                        "setsockopt IP_IPSEC_POLICY (%s)\n",
                    633:                        strerror(errno));
                    634:                return -1;
                    635:        }
                    636:        racoon_free(buf);
                    637: 
                    638:        policy = "out bypass";
                    639:        buf = ipsec_set_policy(policy, strlen(policy));
                    640:        if (buf == NULL) {
                    641:                plog(LLV_ERROR, LOCATION, NULL,
                    642:                        "ipsec_set_policy (%s)\n",
                    643:                        ipsec_strerror());
                    644:                return -1;
                    645:        }
                    646:        if (SETSOCKOPT(so, level,
                    647:                       (level == IPPROTO_IP ?
                    648:                                 IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
                    649:                       buf, ipsec_get_policylen(buf)) < 0) {
                    650:                plog(LLV_ERROR, LOCATION, NULL,
                    651:                        "setsockopt IP_IPSEC_POLICY (%s)\n",
                    652:                        strerror(errno));
                    653:                return -1;
                    654:        }
                    655:        racoon_free(buf);
                    656: 
                    657:        return 0;
                    658: }
                    659: 
                    660: struct sockaddr *
                    661: newsaddr(len)
                    662:        int len;
                    663: {
                    664:        struct sockaddr *new;
                    665: 
                    666:        if ((new = racoon_calloc(1, len)) == NULL) {
                    667:                plog(LLV_ERROR, LOCATION, NULL,
                    668:                        "%s\n", strerror(errno)); 
                    669:                goto out;
                    670:        }
                    671: 
                    672: #ifdef __linux__
                    673:        if (len == sizeof (struct sockaddr_in6))
                    674:                new->sa_family = AF_INET6;
                    675:        else
                    676:                new->sa_family = AF_INET;
                    677: #else
                    678:        /* initial */
                    679:        new->sa_len = len;
                    680: #endif
                    681: out:
                    682:        return new;
                    683: }
                    684: 
                    685: struct sockaddr *
                    686: dupsaddr(src)
                    687:        struct sockaddr *src;
                    688: {
                    689:        struct sockaddr *dst;
                    690: 
                    691:        dst = racoon_calloc(1, sysdep_sa_len(src));
                    692:        if (dst == NULL) {
                    693:                plog(LLV_ERROR, LOCATION, NULL,
                    694:                        "%s\n", strerror(errno)); 
                    695:                return NULL;
                    696:        }
                    697: 
                    698:        memcpy(dst, src, sysdep_sa_len(src));
                    699: 
                    700:        return dst;
                    701: }
                    702: 
                    703: char *
                    704: saddr2str(saddr)
                    705:        const struct sockaddr *saddr;
                    706: {
                    707:        static char buf[NI_MAXHOST + NI_MAXSERV + 10];
                    708:        char addr[NI_MAXHOST], port[NI_MAXSERV];
                    709: 
                    710:        if (saddr == NULL)
                    711:                return NULL;
                    712: 
                    713:        if (saddr->sa_family == AF_UNSPEC)
                    714:                snprintf (buf, sizeof(buf), "%s", "anonymous");
                    715:        else {
                    716:                GETNAMEINFO(saddr, addr, port);
                    717:                snprintf(buf, sizeof(buf), "%s[%s]", addr, port);
                    718:        }
                    719: 
                    720:        return buf;
                    721: }
                    722: 
                    723: char *
                    724: saddrwop2str(saddr)
                    725:        const struct sockaddr *saddr;
                    726: {
                    727:        static char buf[NI_MAXHOST + NI_MAXSERV + 10];
                    728:        char addr[NI_MAXHOST];
                    729: 
                    730:        if (saddr == NULL)
                    731:                return NULL;
                    732: 
                    733:        GETNAMEINFO_NULL(saddr, addr);
                    734:        snprintf(buf, sizeof(buf), "%s", addr);
                    735: 
                    736:        return buf;
                    737: }
                    738: 
                    739: char *
                    740: naddrwop2str(const struct netaddr *naddr)
                    741: {
                    742:        static char buf[NI_MAXHOST + 10];
                    743:        static const struct sockaddr sa_any;    /* this is initialized to all zeros */
                    744:        
                    745:        if (naddr == NULL)
                    746:                return NULL;
                    747: 
                    748:        if (memcmp(&naddr->sa, &sa_any, sizeof(sa_any)) == 0)
                    749:                snprintf(buf, sizeof(buf), "%s", "any");
                    750:        else {
                    751:                snprintf(buf, sizeof(buf), "%s", saddrwop2str(&naddr->sa.sa));
                    752:                snprintf(&buf[strlen(buf)], sizeof(buf) - strlen(buf), "/%ld", naddr->prefix);
                    753:        }
                    754:        return buf;
                    755: }
                    756: 
                    757: char *
                    758: naddrwop2str_fromto(const char *format, const struct netaddr *saddr,
                    759:                    const struct netaddr *daddr)
                    760: {
                    761:        static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
                    762:        char *src, *dst;
                    763: 
                    764:        src = racoon_strdup(naddrwop2str(saddr));
                    765:        dst = racoon_strdup(naddrwop2str(daddr));
                    766:        STRDUP_FATAL(src);
                    767:        STRDUP_FATAL(dst);
                    768:        /* WARNING: Be careful about the format string! Don't 
                    769:           ever pass in something that a user can modify!!! */
                    770:        snprintf (buf, sizeof(buf), format, src, dst);
                    771:        racoon_free (src);
                    772:        racoon_free (dst);
                    773: 
                    774:        return buf;
                    775: }
                    776: 
                    777: char *
                    778: saddr2str_fromto(format, saddr, daddr)
                    779:        const char *format;
                    780:        const struct sockaddr *saddr;
                    781:        const struct sockaddr *daddr;
                    782: {
                    783:        static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100];
                    784:        char *src, *dst;
                    785: 
                    786:        src = racoon_strdup(saddr2str(saddr));
                    787:        dst = racoon_strdup(saddr2str(daddr));
                    788:        STRDUP_FATAL(src);
                    789:        STRDUP_FATAL(dst);
                    790:        /* WARNING: Be careful about the format string! Don't 
                    791:           ever pass in something that a user can modify!!! */
                    792:        snprintf (buf, sizeof(buf), format, src, dst);
                    793:        racoon_free (src);
                    794:        racoon_free (dst);
                    795: 
                    796:        return buf;
                    797: }
                    798: 
                    799: struct sockaddr *
                    800: str2saddr(host, port)
                    801:        char *host;
                    802:        char *port;
                    803: {
                    804:        struct addrinfo hints, *res;
                    805:        struct sockaddr *saddr;
                    806:        int error;
                    807: 
                    808:        memset(&hints, 0, sizeof(hints));
                    809:        hints.ai_family = PF_UNSPEC;
                    810:        hints.ai_socktype = SOCK_DGRAM;
                    811:        hints.ai_flags = AI_NUMERICHOST;
                    812:        error = getaddrinfo(host, port, &hints, &res);
                    813:        if (error != 0) {
                    814:                plog(LLV_ERROR, LOCATION, NULL,
                    815:                        "getaddrinfo(%s%s%s): %s\n",
                    816:                        host, port ? "," : "", port ? port : "",
                    817:                        gai_strerror(error));
                    818:                return NULL;
                    819:        }
                    820:        if (res->ai_next != NULL) {
                    821:                plog(LLV_WARNING, LOCATION, NULL,
                    822:                        "getaddrinfo(%s%s%s): "
                    823:                        "resolved to multiple address, "
                    824:                        "taking the first one\n",
                    825:                        host, port ? "," : "", port ? port : "");
                    826:        }
                    827:        saddr = racoon_malloc(res->ai_addrlen);
                    828:        if (saddr == NULL) {
                    829:                plog(LLV_ERROR, LOCATION, NULL,
                    830:                        "failed to allocate buffer.\n");
                    831:                freeaddrinfo(res);
                    832:                return NULL;
                    833:        }
                    834:        memcpy(saddr, res->ai_addr, res->ai_addrlen);
                    835:        freeaddrinfo(res);
                    836: 
                    837:        return saddr;
                    838: }
                    839: 
                    840: void
                    841: mask_sockaddr(a, b, l)
                    842:        struct sockaddr *a;
                    843:        const struct sockaddr *b;
                    844:        size_t l;
                    845: {
                    846:        size_t i;
                    847:        u_int8_t *p, alen;
                    848: 
                    849:        switch (b->sa_family) {
                    850:        case AF_INET:
                    851:                alen = sizeof(struct in_addr);
                    852:                p = (u_int8_t *)&((struct sockaddr_in *)a)->sin_addr;
                    853:                break;
                    854: #ifdef INET6
                    855:        case AF_INET6:
                    856:                alen = sizeof(struct in6_addr);
                    857:                p = (u_int8_t *)&((struct sockaddr_in6 *)a)->sin6_addr;
                    858:                break;
                    859: #endif
                    860:        default:
                    861:                plog(LLV_ERROR, LOCATION, NULL,
                    862:                        "invalid family: %d\n", b->sa_family);
                    863:                exit(1);
                    864:        }
                    865: 
                    866:        if ((alen << 3) < l) {
                    867:                plog(LLV_ERROR, LOCATION, NULL,
                    868:                        "unexpected inconsistency: %d %zu\n", b->sa_family, l);
                    869:                exit(1);
                    870:        }
                    871: 
                    872:        memcpy(a, b, sysdep_sa_len(b));
                    873:        p[l / 8] &= (0xff00 >> (l % 8)) & 0xff;
                    874:        for (i = l / 8 + 1; i < alen; i++)
                    875:                p[i] = 0x00;
                    876: }
                    877: 
                    878: /* Compute a score describing how "accurate" a netaddr is for a given sockaddr.
                    879:  * Examples:
                    880:  *     Return values for address 10.20.30.40 [port 500] and given netaddresses...
                    881:  *             10.10.0.0/16    => -1   ... doesn't match
                    882:  *             0.0.0.0/0       => 0    ... matches, but only 0 bits.
                    883:  *             10.20.0.0/16    => 16   ... 16 bits match
                    884:  *             10.20.30.0/24   => 24   ... guess what ;-)
                    885:  *             10.20.30.40/32  => 32   ... whole address match
                    886:  *             10.20.30.40:500 => 33   ... both address and port match
                    887:  *             10.20.30.40:501 => -1   ... port doesn't match and isn't 0 (=any)
                    888:  */
                    889: int
                    890: naddr_score(const struct netaddr *naddr, const struct sockaddr *saddr)
                    891: {
                    892:        static const struct netaddr naddr_any;  /* initialized to all-zeros */
                    893:        struct sockaddr sa;
                    894:        u_int16_t naddr_port, saddr_port;
                    895:        int port_score;
                    896: 
                    897:        if (!naddr || !saddr) {
                    898:                plog(LLV_ERROR, LOCATION, NULL,
                    899:                     "Call with null args: naddr=%p, saddr=%p\n",
                    900:                     naddr, saddr);
                    901:                return -1;
                    902:        }
                    903: 
                    904:        /* Wildcard address matches, but only 0 bits. */
                    905:        if (memcmp(naddr, &naddr_any, sizeof(naddr_any)) == 0)
                    906:                return 0;
                    907: 
                    908:        /* If families don't match we really can't do much... */
                    909:        if (naddr->sa.sa.sa_family != saddr->sa_family)
                    910:                return -1;
                    911:        
                    912:        /* If port check fail don't bother to check addresses. */
                    913:        naddr_port = extract_port(&naddr->sa.sa);
                    914:        saddr_port = extract_port(saddr);
                    915:        if (naddr_port == 0 || saddr_port == 0) /* wildcard match */
                    916:                port_score = 0;
                    917:        else if (naddr_port == saddr_port)      /* exact match */
                    918:                port_score = 1;
                    919:        else                                    /* mismatch :-) */
                    920:                return -1;
                    921: 
                    922:        /* Here it comes - compare network addresses. */
                    923:        mask_sockaddr(&sa, saddr, naddr->prefix);
                    924:        if (loglevel >= LLV_DEBUG) {    /* debug only */
                    925:                char *a1, *a2, *a3;
                    926:                a1 = racoon_strdup(naddrwop2str(naddr));
                    927:                a2 = racoon_strdup(saddrwop2str(saddr));
                    928:                a3 = racoon_strdup(saddrwop2str(&sa));
                    929:                STRDUP_FATAL(a1);
                    930:                STRDUP_FATAL(a2);
                    931:                STRDUP_FATAL(a3);
                    932:                plog(LLV_DEBUG, LOCATION, NULL,
                    933:                     "naddr=%s, saddr=%s (masked=%s)\n",
                    934:                     a1, a2, a3);
                    935:                free(a1);
                    936:                free(a2);
                    937:                free(a3);
                    938:        }
                    939:        if (cmpsaddr(&sa, &naddr->sa.sa) <= CMPSADDR_WOP_MATCH)
                    940:                return naddr->prefix + port_score;
                    941: 
                    942:        return -1;
                    943: }
                    944: 
                    945: /* Some useful functions for sockaddr port manipulations. */
                    946: u_int16_t
                    947: extract_port (const struct sockaddr *addr)
                    948: {
                    949:   u_int16_t port = 0;
                    950:   
                    951:   if (!addr)
                    952:     return port;
                    953: 
                    954:   switch (addr->sa_family) {
                    955:     case AF_UNSPEC:
                    956:       break;
                    957:     case AF_INET:
                    958:       port = ((struct sockaddr_in *)addr)->sin_port;
                    959:       break;
                    960:     case AF_INET6:
                    961:       port = ((struct sockaddr_in6 *)addr)->sin6_port;
                    962:       break;
                    963:     default:
                    964:       plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
                    965:       break;
                    966:   }
                    967: 
                    968:   return ntohs(port);
                    969: }
                    970: 
                    971: u_int16_t *
                    972: get_port_ptr (struct sockaddr *addr)
                    973: {
                    974:   u_int16_t *port_ptr;
                    975: 
                    976:   if (!addr)
                    977:     return NULL;
                    978: 
                    979:   switch (addr->sa_family) {
                    980:     case AF_INET:
                    981:       port_ptr = &(((struct sockaddr_in *)addr)->sin_port);
                    982:       break;
                    983:     case AF_INET6:
                    984:       port_ptr = &(((struct sockaddr_in6 *)addr)->sin6_port);
                    985:       break;
                    986:     default:
                    987:       plog(LLV_ERROR, LOCATION, NULL, "unknown AF: %u\n", addr->sa_family);
                    988:       return NULL;
                    989:       break;
                    990:   }
                    991: 
                    992:   return port_ptr;
                    993: }
                    994: 
                    995: u_int16_t *
                    996: set_port (struct sockaddr *addr, u_int16_t new_port)
                    997: {
                    998:   u_int16_t *port_ptr;
                    999: 
                   1000:   port_ptr = get_port_ptr (addr);
                   1001: 
                   1002:   if (port_ptr)
                   1003:     *port_ptr = htons(new_port);
                   1004: 
                   1005:   return port_ptr;
                   1006: }

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