Annotation of embedaddon/ipsec-tools/src/setkey/setkey.c, revision 1.1

1.1     ! misho       1: /*     $NetBSD: setkey.c,v 1.14 2009/08/06 04:44:43 tteras Exp $       */
        !             2: 
        !             3: /*     $KAME: setkey.c,v 1.36 2003/09/24 23:52:51 itojun Exp $ */
        !             4: 
        !             5: /*
        !             6:  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 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: #ifdef HAVE_CONFIG_H
        !            35: #include "config.h"
        !            36: #endif
        !            37: 
        !            38: #include <sys/types.h>
        !            39: #include <sys/param.h>
        !            40: #include <sys/socket.h>
        !            41: #include <sys/time.h>
        !            42: #include <sys/stat.h>
        !            43: #include <sys/sysctl.h>
        !            44: #include <err.h>
        !            45: #include <netinet/in.h>
        !            46: #include <net/pfkeyv2.h>
        !            47: #include PATH_IPSEC_H
        !            48: 
        !            49: #include <stdio.h>
        !            50: #include <stdlib.h>
        !            51: #include <limits.h>
        !            52: #include <string.h>
        !            53: #include <ctype.h>
        !            54: #include <unistd.h>
        !            55: #include <errno.h>
        !            56: #include <netdb.h>
        !            57: #include <fcntl.h>
        !            58: #include <dirent.h>
        !            59: #include <time.h>
        !            60: 
        !            61: #ifdef HAVE_READLINE
        !            62: #include <readline/readline.h>
        !            63: #include <readline/history.h>
        !            64: #endif
        !            65: 
        !            66: #include "config.h"
        !            67: #include "libpfkey.h"
        !            68: #include "package_version.h"
        !            69: #define extern /* so that variables in extern.h are not extern... */
        !            70: #include "extern.h"
        !            71: 
        !            72: #define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0')
        !            73: 
        !            74: void usage __P((int));
        !            75: int main __P((int, char **));
        !            76: int get_supported __P((void));
        !            77: void sendkeyshort __P((u_int));
        !            78: void promisc __P((void));
        !            79: int postproc __P((struct sadb_msg *, int));
        !            80: int verifypriority __P((struct sadb_msg *m));
        !            81: int fileproc __P((const char *));
        !            82: const char *numstr __P((int));
        !            83: void shortdump_hdr __P((void));
        !            84: void shortdump __P((struct sadb_msg *));
        !            85: static void printdate __P((void));
        !            86: static int32_t gmt2local __P((time_t));
        !            87: void stdin_loop __P((void));
        !            88: 
        !            89: #define MODE_SCRIPT    1
        !            90: #define MODE_CMDDUMP   2
        !            91: #define MODE_CMDFLUSH  3
        !            92: #define MODE_PROMISC   4
        !            93: #define MODE_STDIN     5
        !            94: 
        !            95: int so;
        !            96: 
        !            97: int f_forever = 0;
        !            98: int f_all = 0;
        !            99: int f_verbose = 0;
        !           100: int f_mode = 0;
        !           101: int f_cmddump = 0;
        !           102: int f_policy = 0;
        !           103: int f_hexdump = 0;
        !           104: int f_tflag = 0;
        !           105: int f_notreally = 0;
        !           106: int f_withports = 0;
        !           107: #ifdef HAVE_POLICY_FWD
        !           108: int f_rfcmode = 1;
        !           109: #define RK_OPTS "rk"
        !           110: #else
        !           111: int f_rkwarn = 0;
        !           112: #define RK_OPTS ""
        !           113: static void rkwarn(void);
        !           114: static void
        !           115: rkwarn(void)
        !           116: {
        !           117:        if (!f_rkwarn) {
        !           118:                f_rkwarn = 1;
        !           119:                printf("warning: -r and -k options are not supported in this environment\n");
        !           120:        }
        !           121: }
        !           122: 
        !           123: #endif
        !           124: static time_t thiszone;
        !           125: 
        !           126: void
        !           127: usage(int only_version)
        !           128: {
        !           129:        printf("setkey @(#) %s (%s)\n", TOP_PACKAGE_STRING, TOP_PACKAGE_URL); 
        !           130:        if (! only_version) {
        !           131:                printf("usage: setkey [-v" RK_OPTS "] file ...\n");
        !           132:                printf("       setkey [-nv" RK_OPTS "] -c\n");
        !           133:                printf("       setkey [-nv" RK_OPTS "] -f filename\n");
        !           134:                printf("       setkey [-Palpv" RK_OPTS "] -D\n");
        !           135:                printf("       setkey [-Pv] -F\n");
        !           136:                printf("       setkey [-H] -x\n");
        !           137:                printf("       setkey [-V] [-h]\n");
        !           138:        }
        !           139:        exit(1);
        !           140: }
        !           141: 
        !           142: int
        !           143: main(argc, argv)
        !           144:        int argc;
        !           145:        char **argv;
        !           146: {
        !           147:        FILE *fp = stdin;
        !           148:        int c;
        !           149: 
        !           150:        if (argc == 1) {
        !           151:                usage(0);
        !           152:                /* NOTREACHED */
        !           153:        }
        !           154: 
        !           155:        thiszone = gmt2local(0);
        !           156: 
        !           157:        while ((c = getopt(argc, argv, "acdf:HlnvxDFPphVrk?")) != -1) {
        !           158:                switch (c) {
        !           159:                case 'c':
        !           160:                        f_mode = MODE_STDIN;
        !           161: #ifdef HAVE_READLINE
        !           162:                        /* disable filename completion */
        !           163:                        rl_bind_key('\t', rl_insert);
        !           164: #endif
        !           165:                        break;
        !           166:                case 'f':
        !           167:                        f_mode = MODE_SCRIPT;
        !           168:                        if ((fp = fopen(optarg, "r")) == NULL) {
        !           169:                                err(1, "fopen");
        !           170:                                /*NOTREACHED*/
        !           171:                        }
        !           172:                        break;
        !           173:                case 'D':
        !           174:                        f_mode = MODE_CMDDUMP;
        !           175:                        break;
        !           176:                case 'F':
        !           177:                        f_mode = MODE_CMDFLUSH;
        !           178:                        break;
        !           179:                case 'a':
        !           180:                        f_all = 1;
        !           181:                        break;
        !           182:                case 'l':
        !           183:                        f_forever = 1;
        !           184:                        break;
        !           185:                case 'n':
        !           186:                        f_notreally = 1;
        !           187:                        break;
        !           188: #ifdef __NetBSD__
        !           189:                case 'h':
        !           190: #endif
        !           191:                case 'H':
        !           192:                        f_hexdump = 1;
        !           193:                        break;
        !           194:                case 'x':
        !           195:                        f_mode = MODE_PROMISC;
        !           196:                        f_tflag++;
        !           197:                        break;
        !           198:                case 'P':
        !           199:                        f_policy = 1;
        !           200:                        break;
        !           201:                case 'p':
        !           202:                        f_withports = 1;
        !           203:                        break;
        !           204:                case 'v':
        !           205:                        f_verbose = 1;
        !           206:                        break;
        !           207:                case 'r':
        !           208: #ifdef HAVE_POLICY_FWD
        !           209:                        f_rfcmode = 1;
        !           210: #else
        !           211:                        rkwarn();
        !           212: #endif
        !           213:                        break;
        !           214:                case 'k':
        !           215: #ifdef HAVE_POLICY_FWD
        !           216:                        f_rfcmode = 0;
        !           217: #else
        !           218:                        rkwarn();
        !           219: #endif
        !           220:                        break;
        !           221:                case 'V':
        !           222:                        usage(1);
        !           223:                        break;
        !           224:                        /*NOTREACHED*/
        !           225: #ifndef __NetBSD__
        !           226:                case 'h':
        !           227: #endif
        !           228:                case '?':
        !           229:                default:
        !           230:                        usage(0);
        !           231:                        /*NOTREACHED*/
        !           232:                }
        !           233:        }
        !           234: 
        !           235:        argc -= optind;
        !           236:        argv += optind;
        !           237: 
        !           238:        if (argc > 0) {
        !           239:                while (argc--)
        !           240:                        if (fileproc(*argv++) < 0) {
        !           241:                                err(1, "%s", argv[-1]);
        !           242:                                /*NOTREACHED*/
        !           243:                        }
        !           244:                exit(0);
        !           245:        }
        !           246: 
        !           247:        so = pfkey_open();
        !           248:        if (so < 0) {
        !           249:                perror("pfkey_open");
        !           250:                exit(1);
        !           251:        }
        !           252: 
        !           253:        switch (f_mode) {
        !           254:        case MODE_CMDDUMP:
        !           255:                sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP);
        !           256:                break;
        !           257:        case MODE_CMDFLUSH:
        !           258:                sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH);
        !           259:                break;
        !           260:        case MODE_SCRIPT:
        !           261:                if (get_supported() < 0) {
        !           262:                        errx(1, "%s", ipsec_strerror());
        !           263:                        /*NOTREACHED*/
        !           264:                }
        !           265:                if (parse(&fp))
        !           266:                        exit (1);
        !           267:                break;
        !           268:        case MODE_STDIN:
        !           269:                if (get_supported() < 0) {
        !           270:                        errx(1, "%s", ipsec_strerror());
        !           271:                        /*NOTREACHED*/
        !           272:                }
        !           273:                stdin_loop();
        !           274:                break;
        !           275:        case MODE_PROMISC:
        !           276:                promisc();
        !           277:                /*NOTREACHED*/
        !           278:        default:
        !           279:                usage(0);
        !           280:                /*NOTREACHED*/
        !           281:        }
        !           282: 
        !           283:        exit(0);
        !           284: }
        !           285: 
        !           286: int
        !           287: get_supported()
        !           288: {
        !           289: 
        !           290:        if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
        !           291:                return -1;
        !           292: 
        !           293:        if (pfkey_recv_register(so) < 0)
        !           294:                return -1;
        !           295: 
        !           296:        return (0);
        !           297: }
        !           298: 
        !           299: void
        !           300: stdin_loop()
        !           301: {
        !           302:        char line[1024], *semicolon, *comment;
        !           303:        size_t linelen = 0;
        !           304:        
        !           305:        memset (line, 0, sizeof(line));
        !           306: 
        !           307:        parse_init();
        !           308:        while (1) {
        !           309: #ifdef HAVE_READLINE
        !           310:                char *rbuf;
        !           311:                rbuf = readline ("");
        !           312:                if (! rbuf)
        !           313:                        break;
        !           314: #else
        !           315:                char rbuf[1024];
        !           316:                rbuf[0] = '\0';
        !           317:                if (fgets(rbuf, sizeof(rbuf), stdin) == NULL)
        !           318:                        break;
        !           319:                if (rbuf[strlen(rbuf)-1] == '\n')
        !           320:                        rbuf[strlen(rbuf)-1] = '\0';
        !           321: #endif
        !           322:                comment = strchr(rbuf, '#');
        !           323:                if (comment)
        !           324:                        *comment = '\0';
        !           325: 
        !           326:                if (!rbuf[0])
        !           327:                        continue;
        !           328: 
        !           329:                linelen += snprintf (&line[linelen], sizeof(line) - linelen,
        !           330:                                     "%s%s", linelen > 0 ? " " : "", rbuf);
        !           331: 
        !           332:                semicolon = strchr(line, ';');
        !           333:                while (semicolon) {
        !           334:                        char saved_char = *++semicolon;
        !           335:                        *semicolon = '\0';
        !           336: #ifdef HAVE_READLINE
        !           337:                        add_history (line);
        !           338: #endif
        !           339: 
        !           340: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !           341:                        last_msg_type = -1;  /* invalid message type */
        !           342: #endif
        !           343: 
        !           344:                        parse_string (line);
        !           345:                        if (exit_now)
        !           346:                                return;
        !           347:                        if (saved_char) {
        !           348:                                *semicolon = saved_char;
        !           349:                                linelen = strlen (semicolon);
        !           350:                                memmove (line, semicolon, linelen + 1);
        !           351:                                semicolon = strchr(line, ';');
        !           352:                        }
        !           353:                        else {
        !           354:                                semicolon = NULL;
        !           355:                                linelen = 0;
        !           356:                        }
        !           357:                }
        !           358:        }
        !           359: }
        !           360: 
        !           361: void
        !           362: sendkeyshort(type)
        !           363:         u_int type;
        !           364: {
        !           365:        struct sadb_msg msg;
        !           366: 
        !           367:        msg.sadb_msg_version = PF_KEY_V2;
        !           368:        msg.sadb_msg_type = type;
        !           369:        msg.sadb_msg_errno = 0;
        !           370:        msg.sadb_msg_satype = SADB_SATYPE_UNSPEC;
        !           371:        msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
        !           372:        msg.sadb_msg_reserved = 0;
        !           373:        msg.sadb_msg_seq = 0;
        !           374:        msg.sadb_msg_pid = getpid();
        !           375: 
        !           376:        sendkeymsg((char *)&msg, sizeof(msg));
        !           377: 
        !           378:        return;
        !           379: }
        !           380: 
        !           381: void
        !           382: promisc()
        !           383: {
        !           384:        struct sadb_msg msg;
        !           385:        u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
        !           386:        ssize_t l;
        !           387: 
        !           388:        msg.sadb_msg_version = PF_KEY_V2;
        !           389:        msg.sadb_msg_type = SADB_X_PROMISC;
        !           390:        msg.sadb_msg_errno = 0;
        !           391:        msg.sadb_msg_satype = 1;
        !           392:        msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
        !           393:        msg.sadb_msg_reserved = 0;
        !           394:        msg.sadb_msg_seq = 0;
        !           395:        msg.sadb_msg_pid = getpid();
        !           396: 
        !           397:        if ((l = send(so, &msg, sizeof(msg), 0)) < 0) {
        !           398:                err(1, "send");
        !           399:                /*NOTREACHED*/
        !           400:        }
        !           401: 
        !           402:        while (1) {
        !           403:                struct sadb_msg *base;
        !           404: 
        !           405:                if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) {
        !           406:                        err(1, "recv");
        !           407:                        /*NOTREACHED*/
        !           408:                }
        !           409: 
        !           410:                if (l != sizeof(*base))
        !           411:                        continue;
        !           412: 
        !           413:                base = (struct sadb_msg *)rbuf;
        !           414:                if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len),
        !           415:                                0)) < 0) {
        !           416:                        err(1, "recv");
        !           417:                        /*NOTREACHED*/
        !           418:                }
        !           419:                printdate();
        !           420:                if (f_hexdump) {
        !           421:                        int i;
        !           422:                        for (i = 0; i < l; i++) {
        !           423:                                if (i % 16 == 0)
        !           424:                                        printf("%08x: ", i);
        !           425:                                printf("%02x ", rbuf[i] & 0xff);
        !           426:                                if (i % 16 == 15)
        !           427:                                        printf("\n");
        !           428:                        }
        !           429:                        if (l % 16)
        !           430:                                printf("\n");
        !           431:                }
        !           432:                /* adjust base pointer for promisc mode */
        !           433:                if (base->sadb_msg_type == SADB_X_PROMISC) {
        !           434:                        if ((ssize_t)sizeof(*base) < l)
        !           435:                                base++;
        !           436:                        else
        !           437:                                base = NULL;
        !           438:                }
        !           439:                if (base) {
        !           440:                        kdebug_sadb(base);
        !           441:                        printf("\n");
        !           442:                        fflush(stdout);
        !           443:                }
        !           444:        }
        !           445: }
        !           446: 
        !           447: /* Generate 'spi' array with SPIs matching 'satype', 'srcs', and 'dsts'
        !           448:  * Return value is dynamically generated array of SPIs, also number of
        !           449:  * SPIs through num_spi pointer.
        !           450:  * On any error, set *num_spi to 0 and return NULL.
        !           451:  */
        !           452: u_int32_t *
        !           453: sendkeymsg_spigrep(satype, srcs, dsts, num_spi)
        !           454:        unsigned int satype;
        !           455:        struct addrinfo *srcs;
        !           456:        struct addrinfo *dsts;
        !           457:        int *num_spi;
        !           458: {
        !           459:        struct sadb_msg msg, *m;
        !           460:        char *buf;
        !           461:        size_t len;
        !           462:        ssize_t l;
        !           463:        u_char rbuf[1024 * 32];
        !           464:        caddr_t mhp[SADB_EXT_MAX + 1];
        !           465:        struct sadb_address *saddr;
        !           466:        struct sockaddr *s;
        !           467:        struct addrinfo *a;
        !           468:        struct sadb_sa *sa;
        !           469:        u_int32_t *spi = NULL;
        !           470:        int max_spi = 0, fail = 0;
        !           471: 
        !           472:        *num_spi = 0;
        !           473: 
        !           474:        if (f_notreally) {
        !           475:                return NULL;
        !           476:        }
        !           477: 
        !           478:     {
        !           479:        struct timeval tv;
        !           480:        tv.tv_sec = 1;
        !           481:        tv.tv_usec = 0;
        !           482:        if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
        !           483:                perror("setsockopt");
        !           484:                return NULL;
        !           485:        }
        !           486:     }
        !           487: 
        !           488:        msg.sadb_msg_version = PF_KEY_V2;
        !           489:        msg.sadb_msg_type = SADB_DUMP;
        !           490:        msg.sadb_msg_errno = 0;
        !           491:        msg.sadb_msg_satype = satype;
        !           492:        msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg));
        !           493:        msg.sadb_msg_reserved = 0;
        !           494:        msg.sadb_msg_seq = 0;
        !           495:        msg.sadb_msg_pid = getpid();
        !           496:        buf = (char *)&msg;
        !           497:        len = sizeof(msg);
        !           498: 
        !           499:        if (f_verbose) {
        !           500:                kdebug_sadb(&msg);
        !           501:                printf("\n");
        !           502:        }
        !           503:        if (f_hexdump) {
        !           504:                int i;
        !           505:                for (i = 0; i < len; i++) {
        !           506:                        if (i % 16 == 0)
        !           507:                                printf("%08x: ", i);
        !           508:                        printf("%02x ", buf[i] & 0xff);
        !           509:                        if (i % 16 == 15)
        !           510:                                printf("\n");
        !           511:                }
        !           512:                if (len % 16)
        !           513:                        printf("\n");
        !           514:        }
        !           515: 
        !           516:        if ((l = send(so, buf, len, 0)) < 0) {
        !           517:                perror("send");
        !           518:                return NULL;
        !           519:        }
        !           520: 
        !           521:        m = (struct sadb_msg *)rbuf;
        !           522:        do {
        !           523:                if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
        !           524:                        perror("recv");
        !           525:                        fail = 1;
        !           526:                        break;
        !           527:                }
        !           528: 
        !           529:                if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) {
        !           530:                        warnx("invalid keymsg length");
        !           531:                        fail = 1;
        !           532:                        break;
        !           533:                }
        !           534: 
        !           535:                if (f_verbose) {
        !           536:                        kdebug_sadb(m);
        !           537:                        printf("\n");
        !           538:                }
        !           539: 
        !           540:                if (m->sadb_msg_type != SADB_DUMP) {
        !           541:                        warnx("unexpected message type");
        !           542:                        fail = 1;
        !           543:                        break;
        !           544:                }
        !           545: 
        !           546:                if (m->sadb_msg_errno != 0) {
        !           547:                        warnx("error encountered");
        !           548:                        fail = 1;
        !           549:                        break;
        !           550:                }
        !           551: 
        !           552:                /* match satype */
        !           553:                if (m->sadb_msg_satype != satype)
        !           554:                        continue;
        !           555: 
        !           556:                pfkey_align(m, mhp);
        !           557:                pfkey_check(mhp);
        !           558: 
        !           559:                /* match src */
        !           560:                saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
        !           561:                if (saddr == NULL)
        !           562:                        continue;
        !           563:                s = (struct sockaddr *)(saddr + 1);
        !           564:                for (a = srcs; a; a = a->ai_next)
        !           565:                        if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
        !           566:                                break;
        !           567:                if (a == NULL)
        !           568:                        continue;
        !           569: 
        !           570:                /* match dst */
        !           571:                saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
        !           572:                if (saddr == NULL)
        !           573:                        continue;
        !           574:                s = (struct sockaddr *)(saddr + 1);
        !           575:                for (a = dsts; a; a = a->ai_next)
        !           576:                        if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0)
        !           577:                                break;
        !           578:                if (a == NULL)
        !           579:                        continue;
        !           580: 
        !           581:                if (*num_spi >= max_spi) {
        !           582:                        max_spi += 512;
        !           583:                        spi = realloc(spi, max_spi * sizeof(u_int32_t));
        !           584:                }
        !           585: 
        !           586:                sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
        !           587:                if (sa != NULL)
        !           588:                        spi[(*num_spi)++] = (u_int32_t)ntohl(sa->sadb_sa_spi);
        !           589: 
        !           590:                m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len));
        !           591: 
        !           592:                if (f_verbose) {
        !           593:                        kdebug_sadb(m);
        !           594:                        printf("\n");
        !           595:                }
        !           596: 
        !           597:        } while (m->sadb_msg_seq);
        !           598: 
        !           599:        if (fail) {
        !           600:                free(spi);
        !           601:                *num_spi = 0;
        !           602:                return NULL;
        !           603:        }
        !           604: 
        !           605:        return spi;
        !           606: }
        !           607: 
        !           608: int
        !           609: sendkeymsg(buf, len)
        !           610:        char *buf;
        !           611:        size_t len;
        !           612: {
        !           613:        u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
        !           614:        ssize_t l;
        !           615:        struct sadb_msg *msg;
        !           616: 
        !           617:        if (f_notreally) {
        !           618:                goto end;
        !           619:        }
        !           620: 
        !           621:     {
        !           622:        struct timeval tv;
        !           623:        tv.tv_sec = 1;
        !           624:        tv.tv_usec = 0;
        !           625:        if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
        !           626:                perror("setsockopt");
        !           627:                goto end;
        !           628:        }
        !           629:     }
        !           630: 
        !           631:        if (f_forever)
        !           632:                shortdump_hdr();
        !           633: again:
        !           634:        if (f_verbose) {
        !           635:                kdebug_sadb((struct sadb_msg *)buf);
        !           636:                printf("\n");
        !           637:        }
        !           638:        if (f_hexdump) {
        !           639:                int i;
        !           640:                for (i = 0; i < len; i++) {
        !           641:                        if (i % 16 == 0)
        !           642:                                printf("%08x: ", i);
        !           643:                        printf("%02x ", buf[i] & 0xff);
        !           644:                        if (i % 16 == 15)
        !           645:                                printf("\n");
        !           646:                }
        !           647:                if (len % 16)
        !           648:                        printf("\n");
        !           649:        }
        !           650: 
        !           651:        if ((l = send(so, buf, len, 0)) < 0) {
        !           652:                perror("send");
        !           653:                goto end;
        !           654:        }
        !           655: 
        !           656:        msg = (struct sadb_msg *)rbuf;
        !           657:        do {
        !           658:                if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
        !           659:                        perror("recv");
        !           660:                        goto end;
        !           661:                }
        !           662: 
        !           663:                if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) {
        !           664:                        warnx("invalid keymsg length");
        !           665:                        break;
        !           666:                }
        !           667: 
        !           668:                if (f_verbose) {
        !           669:                        kdebug_sadb(msg);
        !           670:                        printf("\n");
        !           671:                }
        !           672:                if (postproc(msg, l) < 0)
        !           673:                        break;
        !           674:        } while (msg->sadb_msg_errno || msg->sadb_msg_seq);
        !           675: 
        !           676:        if (f_forever) {
        !           677:                fflush(stdout);
        !           678:                sleep(1);
        !           679:                goto again;
        !           680:        }
        !           681: 
        !           682: end:
        !           683:        return (0);
        !           684: }
        !           685: 
        !           686: int
        !           687: postproc(msg, len)
        !           688:        struct sadb_msg *msg;
        !           689:        int len;
        !           690: {
        !           691: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !           692:        static int priority_support_check = 0;
        !           693: #endif
        !           694: 
        !           695:        if (msg->sadb_msg_errno != 0) {
        !           696:                char inf[80];
        !           697:                const char *errmsg = NULL;
        !           698: 
        !           699:                if (f_mode == MODE_SCRIPT)
        !           700:                        snprintf(inf, sizeof(inf), "The result of line %d: ", lineno);
        !           701:                else
        !           702:                        inf[0] = '\0';
        !           703: 
        !           704:                switch (msg->sadb_msg_errno) {
        !           705:                case ENOENT:
        !           706:                        switch (msg->sadb_msg_type) {
        !           707:                        case SADB_DELETE:
        !           708:                        case SADB_GET:
        !           709:                        case SADB_X_SPDDELETE:
        !           710:                                errmsg = "No entry";
        !           711:                                break;
        !           712:                        case SADB_DUMP:
        !           713:                                errmsg = "No SAD entries";
        !           714:                                break;
        !           715:                        case SADB_X_SPDDUMP:
        !           716:                                errmsg = "No SPD entries";
        !           717:                                break;
        !           718:                        }
        !           719:                        break;
        !           720:                default:
        !           721:                        errmsg = strerror(msg->sadb_msg_errno);
        !           722:                }
        !           723:                printf("%s%s.\n", inf, errmsg);
        !           724:                return (-1);
        !           725:        }
        !           726: 
        !           727:        switch (msg->sadb_msg_type) {
        !           728:        case SADB_GET:
        !           729:                if (f_withports)
        !           730:                        pfkey_sadump_withports(msg);
        !           731:                else
        !           732:                        pfkey_sadump(msg);
        !           733:                break;
        !           734: 
        !           735:        case SADB_DUMP:
        !           736:                /* filter out DEAD SAs */
        !           737:                if (!f_all) {
        !           738:                        caddr_t mhp[SADB_EXT_MAX + 1];
        !           739:                        struct sadb_sa *sa;
        !           740:                        pfkey_align(msg, mhp);
        !           741:                        pfkey_check(mhp);
        !           742:                        if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
        !           743:                                if (sa->sadb_sa_state == SADB_SASTATE_DEAD)
        !           744:                                        break;
        !           745:                        }
        !           746:                }
        !           747:                if (f_forever) {
        !           748:                        /* TODO: f_withports */
        !           749:                        shortdump(msg);
        !           750:                } else {
        !           751:                        if (f_withports)
        !           752:                                pfkey_sadump_withports(msg);
        !           753:                        else
        !           754:                                pfkey_sadump(msg);
        !           755:                }
        !           756:                msg = (struct sadb_msg *)((caddr_t)msg +
        !           757:                                     PFKEY_UNUNIT64(msg->sadb_msg_len));
        !           758:                if (f_verbose) {
        !           759:                        kdebug_sadb((struct sadb_msg *)msg);
        !           760:                        printf("\n");
        !           761:                }
        !           762:                break;
        !           763: 
        !           764:        case SADB_X_SPDGET:
        !           765:                if (f_withports) 
        !           766:                        pfkey_spdump_withports(msg);
        !           767:                else
        !           768:                        pfkey_spdump(msg);
        !           769:                break;
        !           770: 
        !           771:        case SADB_X_SPDDUMP:
        !           772:                if (f_withports) 
        !           773:                        pfkey_spdump_withports(msg);
        !           774:                else
        !           775:                        pfkey_spdump(msg);
        !           776:                if (msg->sadb_msg_seq == 0) break;
        !           777:                msg = (struct sadb_msg *)((caddr_t)msg +
        !           778:                                     PFKEY_UNUNIT64(msg->sadb_msg_len));
        !           779:                if (f_verbose) {
        !           780:                        kdebug_sadb((struct sadb_msg *)msg);
        !           781:                        printf("\n");
        !           782:                }
        !           783:                break;
        !           784: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !           785:        case SADB_X_SPDADD:
        !           786:                if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && 
        !           787:                    msg->sadb_msg_pid == getpid() && !priority_support_check) {
        !           788:                        priority_support_check = 1;     
        !           789:                        if (!verifypriority(msg))
        !           790:                                printf ("WARNING: Kernel does not support policy priorities\n");
        !           791:                }
        !           792:                break;
        !           793: #endif
        !           794:        }
        !           795: 
        !           796:        return (0);
        !           797: }
        !           798: 
        !           799: #ifdef HAVE_PFKEY_POLICY_PRIORITY
        !           800: int
        !           801: verifypriority(m)
        !           802:        struct sadb_msg *m;
        !           803: {
        !           804:        caddr_t mhp[SADB_EXT_MAX + 1];
        !           805:        struct sadb_x_policy *xpl;
        !           806: 
        !           807:        /* check pfkey message. */
        !           808:        if (pfkey_align(m, mhp)) {
        !           809:                printf("(%s\n", ipsec_strerror());
        !           810:                return 0;
        !           811:        }
        !           812:        if (pfkey_check(mhp)) {
        !           813:                printf("%s\n", ipsec_strerror());
        !           814:                return 0;
        !           815:        }
        !           816: 
        !           817:        xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY];
        !           818: 
        !           819:        if (xpl == NULL) {
        !           820:                printf("no X_POLICY extension.\n");
        !           821:                return 0;
        !           822:        }
        !           823: 
        !           824:        /* now make sure they match */
        !           825:        if (last_priority != xpl->sadb_x_policy_priority)
        !           826:                return 0;
        !           827: 
        !           828:        return 1; 
        !           829: }
        !           830: #endif
        !           831: 
        !           832: int
        !           833: fileproc(filename)
        !           834:        const char *filename;
        !           835: {
        !           836:        int fd;
        !           837:        ssize_t len, l;
        !           838:        u_char *p, *ep;
        !           839:        struct sadb_msg *msg;
        !           840:        u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
        !           841: 
        !           842:        fd = open(filename, O_RDONLY);
        !           843:        if (fd < 0)
        !           844:                return -1;
        !           845: 
        !           846:        l = 0;
        !           847:        while (1) {
        !           848:                len = read(fd, rbuf + l, sizeof(rbuf) - l);
        !           849:                if (len < 0) {
        !           850:                        close(fd);
        !           851:                        return -1;
        !           852:                } else if (len == 0)
        !           853:                        break;
        !           854:                l += len;
        !           855:        }
        !           856: 
        !           857:        if (l < sizeof(struct sadb_msg)) {
        !           858:                close(fd);
        !           859:                errno = EINVAL;
        !           860:                return -1;
        !           861:        }
        !           862:        close(fd);
        !           863: 
        !           864:        p = rbuf;
        !           865:        ep = rbuf + l;
        !           866: 
        !           867:        while (p < ep) {
        !           868:                msg = (struct sadb_msg *)p;
        !           869:                len = PFKEY_UNUNIT64(msg->sadb_msg_len);
        !           870:                postproc(msg, len);
        !           871:                p += len;
        !           872:        }
        !           873: 
        !           874:        return (0);
        !           875: }
        !           876: 
        !           877: 
        !           878: /*------------------------------------------------------------*/
        !           879: static const char *satype[] = {
        !           880:        NULL, NULL, "ah", "esp"
        !           881: };
        !           882: static const char *sastate[] = {
        !           883:        "L", "M", "D", "d"
        !           884: };
        !           885: static const char *ipproto[] = {
        !           886: /*0*/  "ip", "icmp", "igmp", "ggp", "ip4",
        !           887:        NULL, "tcp", NULL, "egp", NULL,
        !           888: /*10*/ NULL, NULL, NULL, NULL, NULL,
        !           889:        NULL, NULL, "udp", NULL, NULL,
        !           890: /*20*/ NULL, NULL, "idp", NULL, NULL,
        !           891:        NULL, NULL, NULL, NULL, "tp",
        !           892: /*30*/ NULL, NULL, NULL, NULL, NULL,
        !           893:        NULL, NULL, NULL, NULL, NULL,
        !           894: /*40*/ NULL, "ip6", NULL, "rt6", "frag6",
        !           895:        NULL, "rsvp", "gre", NULL, NULL,
        !           896: /*50*/ "esp", "ah", NULL, NULL, NULL,
        !           897:        NULL, NULL, NULL, "icmp6", "none",
        !           898: /*60*/ "dst6",
        !           899: };
        !           900: 
        !           901: #define STR_OR_ID(x, tab) \
        !           902:        (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
        !           903: 
        !           904: const char *
        !           905: numstr(x)
        !           906:        int x;
        !           907: {
        !           908:        static char buf[20];
        !           909:        snprintf(buf, sizeof(buf), "#%d", x);
        !           910:        return buf;
        !           911: }
        !           912: 
        !           913: void
        !           914: shortdump_hdr()
        !           915: {
        !           916:        printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
        !           917:                "time", "p", "s", "spi", "ltime", "src", "dst");
        !           918: }
        !           919: 
        !           920: void
        !           921: shortdump(msg)
        !           922:        struct sadb_msg *msg;
        !           923: {
        !           924:        caddr_t mhp[SADB_EXT_MAX + 1];
        !           925:        char buf[NI_MAXHOST], pbuf[NI_MAXSERV];
        !           926:        struct sadb_sa *sa;
        !           927:        struct sadb_address *saddr;
        !           928:        struct sadb_lifetime *lts, *lth, *ltc;
        !           929:        struct sockaddr *s;
        !           930:        u_int t;
        !           931:        time_t cur = time(0);
        !           932: 
        !           933:        pfkey_align(msg, mhp);
        !           934:        pfkey_check(mhp);
        !           935: 
        !           936:        printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60));
        !           937: 
        !           938:        printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype));
        !           939: 
        !           940:        if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
        !           941:                printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate));
        !           942:                printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi));
        !           943:        } else
        !           944:                printf("%-1s %-8s", "?", "?");
        !           945: 
        !           946:        lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
        !           947:        lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
        !           948:        ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
        !           949:        if (lts && lth && ltc) {
        !           950:                if (ltc->sadb_lifetime_addtime == 0)
        !           951:                        t = (u_long)0;
        !           952:                else
        !           953:                        t = (u_long)(cur - ltc->sadb_lifetime_addtime);
        !           954:                if (t >= 1000)
        !           955:                        strlcpy(buf, " big/", sizeof(buf));
        !           956:                else
        !           957:                        snprintf(buf, sizeof(buf), " %3lu/", (u_long)t);
        !           958:                printf("%s", buf);
        !           959: 
        !           960:                t = (u_long)lth->sadb_lifetime_addtime;
        !           961:                if (t >= 1000)
        !           962:                        strlcpy(buf, "big", sizeof(buf));
        !           963:                else
        !           964:                        snprintf(buf, sizeof(buf), "%-3lu", (u_long)t);
        !           965:                printf("%s", buf);
        !           966:        } else
        !           967:                printf(" ??\?/???");    /* backslash to avoid trigraph ??/ */
        !           968: 
        !           969:        printf(" ");
        !           970: 
        !           971:        if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) {
        !           972:                if (saddr->sadb_address_proto)
        !           973:                        printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
        !           974:                s = (struct sockaddr *)(saddr + 1);
        !           975:                getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
        !           976:                        pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
        !           977:                if (strcmp(pbuf, "0") != 0)
        !           978:                        printf("%s[%s]", buf, pbuf);
        !           979:                else
        !           980:                        printf("%s", buf);
        !           981:        } else
        !           982:                printf("?");
        !           983: 
        !           984:        printf(" -> ");
        !           985: 
        !           986:        if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) {
        !           987:                if (saddr->sadb_address_proto)
        !           988:                        printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
        !           989: 
        !           990:                s = (struct sockaddr *)(saddr + 1);
        !           991:                getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf),
        !           992:                        pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
        !           993:                if (strcmp(pbuf, "0") != 0)
        !           994:                        printf("%s[%s]", buf, pbuf);
        !           995:                else
        !           996:                        printf("%s", buf);
        !           997:        } else
        !           998:                printf("?");
        !           999: 
        !          1000:        printf("\n");
        !          1001: }
        !          1002: 
        !          1003: /* From: tcpdump(1):gmt2local.c and util.c */
        !          1004: /*
        !          1005:  * Print the timestamp
        !          1006:  */
        !          1007: static void
        !          1008: printdate()
        !          1009: {
        !          1010:        struct timeval tp;
        !          1011:        int s;
        !          1012: 
        !          1013:        if (gettimeofday(&tp, NULL) == -1) {
        !          1014:                perror("gettimeofday");
        !          1015:                return;
        !          1016:        }
        !          1017: 
        !          1018:        if (f_tflag == 1) {
        !          1019:                /* Default */
        !          1020:                s = (tp.tv_sec + thiszone ) % 86400;
        !          1021:                (void)printf("%02d:%02d:%02d.%06u ",
        !          1022:                    s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec);
        !          1023:        } else if (f_tflag > 1) {
        !          1024:                /* Unix timeval style */
        !          1025:                (void)printf("%u.%06u ",
        !          1026:                    (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec);
        !          1027:        }
        !          1028: 
        !          1029:        printf("\n");
        !          1030: }
        !          1031: 
        !          1032: /*
        !          1033:  * Returns the difference between gmt and local time in seconds.
        !          1034:  * Use gmtime() and localtime() to keep things simple.
        !          1035:  */
        !          1036: int32_t
        !          1037: gmt2local(time_t t)
        !          1038: {
        !          1039:        register int dt, dir;
        !          1040:        register struct tm *gmt, *loc;
        !          1041:        struct tm sgmt;
        !          1042: 
        !          1043:        if (t == 0)
        !          1044:                t = time(NULL);
        !          1045:        gmt = &sgmt;
        !          1046:        *gmt = *gmtime(&t);
        !          1047:        loc = localtime(&t);
        !          1048:        dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
        !          1049:            (loc->tm_min - gmt->tm_min) * 60;
        !          1050: 
        !          1051:        /*
        !          1052:         * If the year or julian day is different, we span 00:00 GMT
        !          1053:         * and must add or subtract a day. Check the year first to
        !          1054:         * avoid problems when the julian day wraps.
        !          1055:         */
        !          1056:        dir = loc->tm_year - gmt->tm_year;
        !          1057:        if (dir == 0)
        !          1058:                dir = loc->tm_yday - gmt->tm_yday;
        !          1059:        dt += dir * 24 * 60 * 60;
        !          1060: 
        !          1061:        return (dt);
        !          1062: }

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