Annotation of embedaddon/ipsec-tools/src/setkey/setkey.c, revision 1.1.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>