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

1.1     ! misho       1: /*     $NetBSD: racoonctl.c,v 1.18 2010/11/12 09:08:26 tteras Exp $    */
        !             2: 
        !             3: /*     Id: racoonctl.c,v 1.11 2006/04/06 17:06:25 manubsd Exp */
        !             4: 
        !             5: /*
        !             6:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
        !             7:  * Copyright (C) 2008 Timo Teras.
        !             8:  * All rights reserved.
        !             9:  * 
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. Neither the name of the project nor the names of its contributors
        !            19:  *    may be used to endorse or promote products derived from this software
        !            20:  *    without specific prior written permission.
        !            21:  * 
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
        !            23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
        !            26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            32:  * SUCH DAMAGE.
        !            33:  */
        !            34: 
        !            35: #include "config.h"
        !            36: 
        !            37: #include <sys/types.h>
        !            38: #include <sys/param.h>
        !            39: #include <sys/socket.h>
        !            40: #include <sys/un.h>
        !            41: 
        !            42: #include <netinet/in.h>
        !            43: #include <arpa/inet.h>
        !            44: #include <net/pfkeyv2.h>
        !            45: 
        !            46: #include <stdlib.h>
        !            47: #include <stdio.h>
        !            48: #include <string.h>
        !            49: #include <errno.h>
        !            50: #if TIME_WITH_SYS_TIME
        !            51: # include <sys/time.h>
        !            52: # include <time.h>
        !            53: #else
        !            54: # if HAVE_SYS_TIME_H
        !            55: #  include <sys/time.h>
        !            56: # else
        !            57: #  include <time.h>
        !            58: # endif
        !            59: #endif
        !            60: #include <netdb.h>
        !            61: #ifdef HAVE_UNISTD_H
        !            62: #include <unistd.h>
        !            63: #endif
        !            64: #include <err.h>
        !            65: #include <sys/ioctl.h> 
        !            66: #include <resolv.h>
        !            67: 
        !            68: #include "var.h"
        !            69: #include "vmbuf.h"
        !            70: #include "misc.h"
        !            71: #include "gcmalloc.h"
        !            72: 
        !            73: #include "racoonctl.h"
        !            74: #include "admin.h"
        !            75: #include "schedule.h"
        !            76: #include "handler.h"
        !            77: #include "sockmisc.h"
        !            78: #include "vmbuf.h"
        !            79: #include "plog.h"
        !            80: #include "isakmp_var.h"
        !            81: #include "isakmp.h"
        !            82: #include "isakmp_xauth.h"
        !            83: #include "isakmp_cfg.h"
        !            84: #include "isakmp_unity.h"
        !            85: #include "ipsec_doi.h"
        !            86: #include "evt.h"
        !            87: 
        !            88: char *adminsock_path = ADMINSOCK_PATH;
        !            89: 
        !            90: static void usage __P((void));
        !            91: static vchar_t *get_combuf __P((int, char **));
        !            92: static int handle_recv __P((vchar_t *));
        !            93: static vchar_t *f_reload __P((int, char **));
        !            94: static vchar_t *f_getsched __P((int, char **));
        !            95: static vchar_t *f_getsa __P((int, char **));
        !            96: static vchar_t *f_getsacert __P((int, char **));
        !            97: static vchar_t *f_flushsa __P((int, char **));
        !            98: static vchar_t *f_deletesa __P((int, char **));
        !            99: static vchar_t *f_exchangesa __P((int, char **));
        !           100: static vchar_t *f_vpnc __P((int, char **));
        !           101: static vchar_t *f_vpnd __P((int, char **));
        !           102: static vchar_t *f_getevt __P((int, char **));
        !           103: #ifdef ENABLE_HYBRID
        !           104: static vchar_t *f_logoutusr __P((int, char **));
        !           105: #endif
        !           106: 
        !           107: struct cmd_tag {
        !           108:        vchar_t *(*func) __P((int, char **));
        !           109:        char *str;
        !           110: } cmdtab[] = {
        !           111:        { f_reload,     "reload-config" },
        !           112:        { f_reload,     "rc" },
        !           113:        { f_getsched,   "show-schedule" },
        !           114:        { f_getsched,   "sc" },
        !           115:        { f_getsa,      "show-sa" },
        !           116:        { f_getsa,      "ss" },
        !           117:        { f_getsacert,  "get-cert" },
        !           118:        { f_getsacert,  "gc" },
        !           119:        { f_flushsa,    "flush-sa" },
        !           120:        { f_flushsa,    "fs" },
        !           121:        { f_deletesa,   "delete-sa" },
        !           122:        { f_deletesa,   "ds" },
        !           123:        { f_exchangesa, "establish-sa" },
        !           124:        { f_exchangesa, "es" },
        !           125:        { f_vpnc,       "vpn-connect" },
        !           126:        { f_vpnc,       "vc" },
        !           127:        { f_vpnd,       "vpn-disconnect" },
        !           128:        { f_vpnd,       "vd" },
        !           129:        { f_getevt,     "show-event" },
        !           130:        { f_getevt,     "se" },
        !           131: #ifdef ENABLE_HYBRID
        !           132:        { f_logoutusr,  "logout-user" },
        !           133:        { f_logoutusr,  "lu" },
        !           134: #endif
        !           135:        { NULL, NULL },
        !           136: };
        !           137: 
        !           138: struct evtmsg {
        !           139:        int type;
        !           140:        char *msg;
        !           141: } evtmsg[] = {
        !           142:        { EVT_RACOON_QUIT,              "Racoon terminated" },
        !           143: 
        !           144:        { EVT_PHASE1_UP,                "Phase 1 established" },
        !           145:        { EVT_PHASE1_DOWN,              "Phase 1 deleted" },
        !           146:        { EVT_PHASE1_NO_RESPONSE,       "Phase 1 error: peer not responding" },
        !           147:        { EVT_PHASE1_NO_PROPOSAL,       "Phase 1 error: no proposal chosen" },
        !           148:        { EVT_PHASE1_AUTH_FAILED,
        !           149:          "Phase 1 error: authentication failed (bad certificate?)" },
        !           150:        { EVT_PHASE1_DPD_TIMEOUT,       "Phase 1 error: dead peer detected" },
        !           151:        { EVT_PHASE1_MODE_CFG,          "Phase 1 mode configuration done" },
        !           152:        { EVT_PHASE1_XAUTH_SUCCESS,     "Phase 1 Xauth succeeded" },
        !           153:        { EVT_PHASE1_XAUTH_FAILED,      "Phase 1 Xauth failed" },
        !           154: 
        !           155:        { EVT_PHASE2_NO_PHASE1,         "Phase 2 error: no suitable phase 1" },
        !           156:        { EVT_PHASE2_UP,                "Phase 2 established" },
        !           157:        { EVT_PHASE2_DOWN,              "Phase 2 deleted" },
        !           158:        { EVT_PHASE2_NO_RESPONSE,       "Phase 2 error: no response" },
        !           159: };
        !           160: 
        !           161: static vchar_t *get_proto_and_index __P((int, char **, u_int16_t *));
        !           162: static int get_proto __P((char *));
        !           163: static vchar_t *get_index __P((int, char **));
        !           164: static int get_family __P((char *));
        !           165: static vchar_t *get_comindexes __P((int, int, char **));
        !           166: static int get_comindex __P((char *, char **, char **, char **));
        !           167: static int get_ulproto __P((char *));
        !           168: 
        !           169: struct proto_tag {
        !           170:        int proto;
        !           171:        char *str;
        !           172: } prototab[] = {
        !           173:        { ADMIN_PROTO_ISAKMP,   "isakmp" },
        !           174:        { ADMIN_PROTO_IPSEC,    "ipsec" },
        !           175:        { ADMIN_PROTO_AH,       "ah" },
        !           176:        { ADMIN_PROTO_ESP,      "esp" },
        !           177:        { ADMIN_PROTO_INTERNAL, "internal" },
        !           178:        { 0, NULL },
        !           179: };
        !           180: 
        !           181: struct ulproto_tag {
        !           182:        int ul_proto;
        !           183:        char *str;
        !           184: } ulprototab[] = {
        !           185:        { 0,            "any" },
        !           186:        { IPPROTO_ICMP, "icmp" },
        !           187:        { IPPROTO_TCP,  "tcp" },
        !           188:        { IPPROTO_UDP,  "udp" },
        !           189:        { IPPROTO_GRE,  "gre" },
        !           190:        { 0, NULL },
        !           191: };
        !           192: 
        !           193: int so;
        !           194: 
        !           195: static char _addr1_[NI_MAXHOST], _addr2_[NI_MAXHOST];
        !           196: 
        !           197: char *pname;
        !           198: int long_format = 0;
        !           199: int evt_quit_event = 0;
        !           200: 
        !           201: void dump_isakmp_sa __P((char *, int));
        !           202: void dump_internal __P((char *, int));
        !           203: char *pindex_isakmp __P((isakmp_index *));
        !           204: void print_schedule __P((caddr_t, int));
        !           205: void print_evt __P((struct evt_async *));
        !           206: char * fixed_addr __P((char *, char *, int));
        !           207: 
        !           208: static void
        !           209: usage()
        !           210: {
        !           211:        printf(
        !           212: "Usage:\n"
        !           213: "  %s [opts] reload-config\n"
        !           214: "  %s [opts] show-schedule\n"
        !           215: "  %s [opts] show-sa [protocol]\n"
        !           216: "  %s [opts] flush-sa [protocol]\n"
        !           217: "  %s [opts] delete-sa <saopts>\n"
        !           218: "  %s [opts] establish-sa [-u identity] [-n remoteconf] [-w] <saopts>\n"
        !           219: "  %s [opts] vpn-connect [-u identity] vpn_gateway\n"
        !           220: "  %s [opts] vpn-disconnect vpn_gateway\n"
        !           221: "  %s [opts] show-event\n"
        !           222: "  %s [opts] logout-user login\n"
        !           223: "\n"
        !           224: "General options:\n"
        !           225: "  -d          Debug: hexdump admin messages before sending\n"
        !           226: "  -l          Increase output verbosity (mainly for show-sa)\n"
        !           227: "  -s <socket> Specify adminport socket to use (default: %s)\n"
        !           228: "\n"
        !           229: "Parameter specifications:\n"
        !           230: "    <protocol>: \"isakmp\", \"esp\" or \"ah\".\n"
        !           231: "        In the case of \"show-sa\" or \"flush-sa\", you can use \"ipsec\".\n"
        !           232: "\n"
        !           233: "    <saopts>: \"isakmp\" <family> <src> <dst>\n"
        !           234: "            : {\"esp\",\"ah\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n"
        !           235: "                              <ul_proto>\n"
        !           236: "    <family>: \"inet\" or \"inet6\"\n"
        !           237: "    <ul_proto>: \"icmp\", \"tcp\", \"udp\", \"gre\" or \"any\"\n"
        !           238: "\n",
        !           239:                pname, pname, pname, pname, pname, pname, pname, pname, pname, pname,
        !           240:                ADMINSOCK_PATH);
        !           241: }
        !           242: 
        !           243: /*
        !           244:  * Check for proper racoonctl interface
        !           245:  */
        !           246: #if ((RACOONCTL_INTERFACE_MAJOR != 1) || (RACOONCTL_INTERFACE < 20041230))
        !           247: #error "Incompatible racoonctl interface"
        !           248: #endif
        !           249: 
        !           250: int
        !           251: main(ac, av)
        !           252:        int ac;
        !           253:        char **av;
        !           254: {
        !           255:        vchar_t *combuf;
        !           256:        int c;
        !           257: 
        !           258:        pname = *av;
        !           259: 
        !           260:        /*
        !           261:         * Check for proper racoonctl interface
        !           262:         */
        !           263:        if ((racoonctl_interface_major != RACOONCTL_INTERFACE_MAJOR) ||
        !           264:            (racoonctl_interface < RACOONCTL_INTERFACE))
        !           265:                errx(1, "Incompatible racoonctl interface");
        !           266: 
        !           267: #ifdef __linux__
        !           268:        /*
        !           269:         * Disable GNU extensions that will prevent racoonct vc -u login
        !           270:         * from working (GNU getopt(3) does not like options after vc)
        !           271:         */
        !           272:        setenv("POSIXLY_CORRECT", "1", 0);
        !           273: #endif
        !           274:        while ((c = getopt(ac, av, "lds:")) != -1) {
        !           275:                switch(c) {
        !           276:                case 'l':
        !           277:                        long_format++;
        !           278:                        break;
        !           279: 
        !           280:                case 'd':
        !           281:                        loglevel++;
        !           282:                        break;
        !           283: 
        !           284:                case 's':
        !           285:                        adminsock_path = optarg;
        !           286:                        break;
        !           287: 
        !           288:                default:
        !           289:                        usage();
        !           290:                        exit(0);
        !           291:                }
        !           292:        }
        !           293: 
        !           294:        ac -= optind;
        !           295:        av += optind;
        !           296: 
        !           297:        combuf = get_combuf(ac, av);
        !           298:        if (!combuf)
        !           299:                err(1, "kmpstat");
        !           300: 
        !           301:        if (loglevel)
        !           302:                racoon_hexdump(combuf, ((struct admin_com *)combuf)->ac_len);
        !           303: 
        !           304:        com_init();
        !           305: 
        !           306:        if (com_send(combuf) != 0)
        !           307:                goto bad;
        !           308: 
        !           309:        vfree(combuf);
        !           310: 
        !           311:        do {
        !           312:                if (com_recv(&combuf) != 0)
        !           313:                        goto bad;
        !           314:                if (handle_recv(combuf) != 0)
        !           315:                        goto bad;
        !           316:                vfree(combuf);
        !           317:        } while (evt_quit_event != 0);
        !           318: 
        !           319:        close(so);
        !           320:        exit(0);
        !           321: 
        !           322: bad:
        !           323:        close(so);
        !           324:        if (errno == EEXIST)
        !           325:                exit(0);
        !           326:        exit(1);
        !           327: }
        !           328: 
        !           329: /* %%% */
        !           330: /*
        !           331:  * return command buffer.
        !           332:  */
        !           333: static vchar_t *
        !           334: get_combuf(ac, av)
        !           335:        int ac;
        !           336:        char **av;
        !           337: {
        !           338:        struct cmd_tag *cp;
        !           339: 
        !           340:        if (ac == 0) {
        !           341:                usage();
        !           342:                exit(0);
        !           343:        }
        !           344: 
        !           345:        /* checking the string of command. */
        !           346:        for (cp = &cmdtab[0]; cp->str; cp++) {
        !           347:                if (strcmp(*av, cp->str) == 0) {
        !           348:                        break;
        !           349:                }
        !           350:        }
        !           351:        if (!cp->str) {
        !           352:                printf("Invalid command [%s]\n", *av);
        !           353:                errno = EINVAL;
        !           354:                return NULL;
        !           355:        }
        !           356: 
        !           357:        ac--;
        !           358:        av++;
        !           359:        return (cp->func)(ac, av);
        !           360: }
        !           361: 
        !           362: static vchar_t *
        !           363: make_request(u_int16_t cmd, u_int16_t proto, size_t len)
        !           364: {
        !           365:        vchar_t *buf;
        !           366:        struct admin_com *head;
        !           367: 
        !           368:        buf = vmalloc(sizeof(struct admin_com) + len);
        !           369:        if (buf == NULL)
        !           370:                errx(1, "not enough core");
        !           371: 
        !           372:        head = (struct admin_com *) buf->v;
        !           373:        head->ac_len = buf->l;
        !           374:        head->ac_cmd = ADMIN_FLAG_VERSION | cmd;
        !           375:        head->ac_version = 1;
        !           376:        head->ac_proto = proto;
        !           377: 
        !           378:        return buf;
        !           379: }
        !           380: 
        !           381: static vchar_t *
        !           382: f_reload(ac, av)
        !           383:        int ac;
        !           384:        char **av;
        !           385: {
        !           386:        return make_request(ADMIN_RELOAD_CONF, 0, 0);
        !           387: }
        !           388: 
        !           389: static vchar_t *
        !           390: f_getevt(ac, av)
        !           391:        int ac;
        !           392:        char **av;
        !           393: {
        !           394:        evt_quit_event = -1;
        !           395:        if (ac >= 1)
        !           396:                errx(1, "too many arguments");
        !           397: 
        !           398:        return make_request(ADMIN_SHOW_EVT, 0, 0);
        !           399: }
        !           400: 
        !           401: static vchar_t *
        !           402: f_getsched(ac, av)
        !           403:        int ac;
        !           404:        char **av;
        !           405: {
        !           406:        return make_request(ADMIN_SHOW_SCHED, 0, 0);
        !           407: }
        !           408: 
        !           409: static vchar_t *
        !           410: f_getsa(ac, av)
        !           411:        int ac;
        !           412:        char **av;
        !           413: {
        !           414:        int proto;
        !           415: 
        !           416:        /* need protocol */
        !           417:        if (ac != 1)
        !           418:                errx(1, "insufficient arguments");
        !           419:        proto = get_proto(*av);
        !           420:        if (proto == -1)
        !           421:                errx(1, "unknown protocol %s", *av);
        !           422: 
        !           423:        return make_request(ADMIN_SHOW_SA, proto, 0);
        !           424: }
        !           425: 
        !           426: static vchar_t *
        !           427: f_getsacert(ac, av)
        !           428:        int ac;
        !           429:        char **av;
        !           430: {
        !           431:        vchar_t *buf, *index;
        !           432:        struct admin_com_indexes *com;
        !           433: 
        !           434:        index = get_index(ac, av);
        !           435:        if (index == NULL)
        !           436:                return NULL;
        !           437: 
        !           438:        com = (struct admin_com_indexes *) index->v;
        !           439:        buf = make_request(ADMIN_GET_SA_CERT, ADMIN_PROTO_ISAKMP, index->l);
        !           440:        if (buf == NULL)
        !           441:                errx(1, "Cannot allocate buffer");
        !           442: 
        !           443:        memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
        !           444: 
        !           445:        vfree(index);
        !           446: 
        !           447:        return buf;
        !           448: }
        !           449: 
        !           450: static vchar_t *
        !           451: f_flushsa(ac, av)
        !           452:        int ac;
        !           453:        char **av;
        !           454: {
        !           455:        vchar_t *buf;
        !           456:        struct admin_com *head;
        !           457:        int proto;
        !           458: 
        !           459:        /* need protocol */
        !           460:        if (ac != 1)
        !           461:                errx(1, "insufficient arguments");
        !           462:        proto = get_proto(*av);
        !           463:        if (proto == -1)
        !           464:                errx(1, "unknown protocol %s", *av);
        !           465: 
        !           466:        return make_request(ADMIN_FLUSH_SA, proto, 0);
        !           467: }
        !           468: 
        !           469: static vchar_t *
        !           470: f_deletesa(ac, av)
        !           471:        int ac;
        !           472:        char **av;
        !           473: {
        !           474:        vchar_t *buf, *index;
        !           475:        int proto;
        !           476: 
        !           477:        /* need protocol */
        !           478:        if (ac < 1)
        !           479:                errx(1, "insufficient arguments");
        !           480:        proto = get_proto(*av);
        !           481:        if (proto == -1)
        !           482:                errx(1, "unknown protocol %s", *av);
        !           483: 
        !           484:        /* get index(es) */
        !           485:        av++;
        !           486:        ac--;
        !           487:        switch (proto) {
        !           488:        case ADMIN_PROTO_ISAKMP:
        !           489:                index = get_index(ac, av);
        !           490:                if (index == NULL)
        !           491:                        return NULL;
        !           492:                break;
        !           493:        case ADMIN_PROTO_AH:
        !           494:        case ADMIN_PROTO_ESP:
        !           495:                index = get_index(ac, av);
        !           496:                if (index == NULL)
        !           497:                        return NULL;
        !           498:                break;
        !           499:        default:
        !           500:                errno = EPROTONOSUPPORT;
        !           501:                return NULL;
        !           502:        }
        !           503: 
        !           504:        buf = make_request(ADMIN_DELETE_SA, proto, index->l);
        !           505:        if (buf == NULL)
        !           506:                goto out;
        !           507: 
        !           508:        memcpy(buf->v + sizeof(struct admin_com), index->v, index->l);
        !           509: 
        !           510: out:
        !           511:        if (index != NULL)
        !           512:                vfree(index);
        !           513: 
        !           514:        return buf;
        !           515: }
        !           516: 
        !           517: static vchar_t *
        !           518: f_deleteallsadst(ac, av)
        !           519:        int ac;
        !           520:        char **av;
        !           521: {
        !           522:        vchar_t *buf, *index;
        !           523:        u_int16_t proto;
        !           524: 
        !           525:        index = get_proto_and_index(ac, av, &proto);
        !           526:        if (index == NULL)
        !           527:                return NULL;
        !           528: 
        !           529:        buf = make_request(ADMIN_DELETE_ALL_SA_DST, proto, index->l);
        !           530:        if (buf == NULL)
        !           531:                goto out;
        !           532: 
        !           533:        memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
        !           534: 
        !           535: out:
        !           536:        if (index != NULL)
        !           537:                vfree(index);
        !           538: 
        !           539:        return buf;
        !           540: }
        !           541: 
        !           542: static vchar_t *
        !           543: f_exchangesa(ac, av)
        !           544:        int ac;
        !           545:        char **av;
        !           546: {
        !           547:        vchar_t *buf, *index;
        !           548:        u_int16_t proto;
        !           549:        int cmd = ADMIN_ESTABLISH_SA;
        !           550:        size_t com_len = 0;
        !           551:        char *id = NULL;
        !           552:        char *key = NULL;
        !           553:        char *remoteconf = NULL;
        !           554:        struct admin_com_psk *acp;
        !           555:        int wait = 0;
        !           556: 
        !           557:        if (ac < 1)
        !           558:                errx(1, "insufficient arguments");
        !           559: 
        !           560:        /* Optional -u identity */
        !           561:        if (strcmp(av[0], "-u") == 0) {
        !           562:                if (ac < 2)
        !           563:                        errx(1, "-u require an argument");
        !           564: 
        !           565:                id = av[1];
        !           566:                if ((key = getpass("Password: ")) == NULL)
        !           567:                        errx(1, "getpass() failed: %s", strerror(errno));
        !           568:                
        !           569:                com_len += sizeof(*acp) + strlen(id) + 1 + strlen(key) + 1;
        !           570:                cmd = ADMIN_ESTABLISH_SA_PSK;
        !           571: 
        !           572:                av += 2;
        !           573:                ac -= 2;
        !           574:        }
        !           575: 
        !           576:        if (ac >= 2 && strcmp(av[0], "-n") == 0) {
        !           577:                /* Remoteconf name */
        !           578:                remoteconf = av[1];
        !           579:                av += 2;
        !           580:                ac -= 2;
        !           581:        }
        !           582: 
        !           583:        if (ac >= 1 && strcmp(av[0], "-w") == 0) {
        !           584:                wait = 1;
        !           585:                av++;
        !           586:                ac--;
        !           587:        }
        !           588: 
        !           589:        index = get_proto_and_index(ac, av, &proto);
        !           590:        if (index == NULL)
        !           591:                return NULL;
        !           592: 
        !           593:        if (proto == ADMIN_PROTO_ISAKMP && cmd == ADMIN_ESTABLISH_SA &&
        !           594:            remoteconf != NULL)
        !           595:                com_len += strlen(remoteconf) + 1;
        !           596: 
        !           597:        if (wait) {
        !           598:                switch (proto) {
        !           599:                case ADMIN_PROTO_ISAKMP:
        !           600:                        evt_quit_event = EVT_PHASE1_MODE_CFG;
        !           601:                        break;
        !           602:                case ADMIN_PROTO_AH:
        !           603:                case ADMIN_PROTO_ESP:
        !           604:                        evt_quit_event = EVT_PHASE2_UP;
        !           605:                        break;
        !           606:                default:
        !           607:                        errno = EPROTONOSUPPORT;
        !           608:                        return NULL;
        !           609:                }
        !           610:        }
        !           611: 
        !           612:        com_len += index->l;
        !           613:        buf = make_request(cmd, proto, com_len);
        !           614:        if (buf == NULL)
        !           615:                errx(1, "Cannot allocate buffer");
        !           616: 
        !           617:        memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
        !           618: 
        !           619:        if (proto == ADMIN_PROTO_ISAKMP && cmd == ADMIN_ESTABLISH_SA &&
        !           620:            remoteconf != NULL) {
        !           621:                strcpy(buf->v + sizeof(struct admin_com) + index->l,
        !           622:                       remoteconf);
        !           623:        } else if (id && key) {
        !           624:                char *data;
        !           625:                acp = (struct admin_com_psk *)
        !           626:                    (buf->v + sizeof(struct admin_com) + index->l);
        !           627: 
        !           628:                acp->id_type = IDTYPE_USERFQDN;
        !           629:                acp->id_len = strlen(id) + 1;
        !           630:                acp->key_len = strlen(key) + 1;
        !           631: 
        !           632:                data = (char *)(acp + 1);
        !           633:                strcpy(data, id);
        !           634: 
        !           635:                data = (char *)(data + acp->id_len);
        !           636:                strcpy(data, key);
        !           637:        }
        !           638: 
        !           639:        vfree(index);
        !           640: 
        !           641:        return buf;
        !           642: }
        !           643: 
        !           644: static vchar_t *
        !           645: f_vpnc(ac, av)
        !           646:        int ac;
        !           647:        char **av;
        !           648: {
        !           649:        char *nav[] = {NULL, NULL, NULL, NULL, NULL, NULL};
        !           650:        int nac = 0;
        !           651:        char *isakmp = "isakmp";
        !           652:        char *inet = "inet";
        !           653:        char *srcaddr;
        !           654:        struct addrinfo hints, *res;
        !           655:        struct sockaddr *src;
        !           656:        char *idx;
        !           657: 
        !           658:        if (ac < 1)
        !           659:                errx(1, "insufficient arguments");
        !           660: 
        !           661:        evt_quit_event = EVT_PHASE1_MODE_CFG;
        !           662:        
        !           663:        /* Optional -u identity */
        !           664:        if (strcmp(av[0], "-u") == 0) {
        !           665:                if (ac < 2)
        !           666:                        errx(1, "-u require an argument");
        !           667: 
        !           668:                nav[nac++] = av[0];
        !           669:                nav[nac++] = av[1];
        !           670: 
        !           671:                ac -= 2;
        !           672:                av += 2;
        !           673:        }
        !           674: 
        !           675:        if (ac < 1)
        !           676:                errx(1, "VPN gateway required");
        !           677:        if (ac > 1)
        !           678:                warnx("Extra arguments");
        !           679: 
        !           680:        /*
        !           681:         * Find the source address
        !           682:         */
        !           683:        memset(&hints, 0, sizeof(hints));
        !           684:        hints.ai_family = PF_UNSPEC;
        !           685:        hints.ai_socktype = SOCK_DGRAM;
        !           686:        if (getaddrinfo(av[0], "4500", &hints, &res) != 0)
        !           687:                errx(1, "Cannot resolve destination address");
        !           688: 
        !           689:        if ((src = getlocaladdr(res->ai_addr)) == NULL)
        !           690:                errx(1, "cannot find source address");
        !           691: 
        !           692:        if ((srcaddr = saddr2str(src)) == NULL)
        !           693:                errx(1, "cannot read source address");
        !           694: 
        !           695:        /* We get "ip[port]" strip the port */
        !           696:        if ((idx = index(srcaddr, '[')) == NULL) 
        !           697:                errx(1, "unexpected source address format");
        !           698:        *idx = '\0';
        !           699: 
        !           700:        nav[nac++] = isakmp;
        !           701:        nav[nac++] = inet;
        !           702:        nav[nac++] = srcaddr;
        !           703:        nav[nac++] = av[0];
        !           704: 
        !           705:        return f_exchangesa(nac, nav);
        !           706: }
        !           707: 
        !           708: static vchar_t *
        !           709: f_vpnd(ac, av)
        !           710:        int ac;
        !           711:        char **av;
        !           712: {
        !           713:        char *nav[] = {NULL, NULL, NULL, NULL};
        !           714:        int nac = 0;
        !           715:        char *isakmp = "isakmp";
        !           716:        char *inet = "inet";
        !           717:        char *anyaddr = "0.0.0.0";
        !           718:        char *idx;
        !           719: 
        !           720:        if (ac < 1)
        !           721:                errx(1, "VPN gateway required");
        !           722:        if (ac > 1)
        !           723:                warnx("Extra arguments");
        !           724: 
        !           725:        evt_quit_event = EVT_PHASE1_DOWN;
        !           726: 
        !           727:        nav[nac++] = isakmp;
        !           728:        nav[nac++] = inet;
        !           729:        nav[nac++] = anyaddr;
        !           730:        nav[nac++] = av[0];
        !           731: 
        !           732:        return f_deleteallsadst(nac, nav);
        !           733: }
        !           734: 
        !           735: #ifdef ENABLE_HYBRID
        !           736: static vchar_t *
        !           737: f_logoutusr(ac, av)
        !           738:        int ac;
        !           739:        char **av;
        !           740: {
        !           741:        vchar_t *buf;
        !           742:        char *user;
        !           743:        size_t userlen;
        !           744: 
        !           745:        /* need username */
        !           746:        if (ac < 1)
        !           747:                errx(1, "insufficient arguments");
        !           748:        user = av[0];
        !           749:        userlen = strlen(user);
        !           750:        if ((user == NULL) || (userlen > LOGINLEN))
        !           751:                errx(1, "bad login (too long?)");
        !           752: 
        !           753:        buf = make_request(ADMIN_LOGOUT_USER, 0, userlen);
        !           754:        if (buf == NULL)
        !           755:                return NULL;
        !           756: 
        !           757:        strncpy(buf->v + sizeof(struct admin_com), user, userlen);
        !           758: 
        !           759:        return buf;
        !           760: }
        !           761: #endif /* ENABLE_HYBRID */
        !           762: 
        !           763: static vchar_t *
        !           764: get_proto_and_index(ac, av, proto)
        !           765:        int ac;
        !           766:        char **av;
        !           767:        u_int16_t *proto;
        !           768: {
        !           769:        vchar_t *index = NULL;
        !           770: 
        !           771:        /* need protocol */
        !           772:        if (ac < 1)
        !           773:                errx(1, "insufficient arguments");
        !           774:        *proto = get_proto(*av);
        !           775:        if (*proto == (u_int16_t) -1)
        !           776:                errx(1, "unknown protocol %s", *av);
        !           777: 
        !           778:        /* get index(es) */
        !           779:        av++;
        !           780:        ac--;
        !           781:        switch (*proto) {
        !           782:        case ADMIN_PROTO_ISAKMP:
        !           783:        case ADMIN_PROTO_AH:
        !           784:        case ADMIN_PROTO_ESP:
        !           785:                index = get_index(ac, av);
        !           786:                break;
        !           787:        default:
        !           788:                errno = EPROTONOSUPPORT;
        !           789:                break;
        !           790:        }
        !           791:        return index;
        !           792: }
        !           793: 
        !           794: static int
        !           795: get_proto(str)
        !           796:        char *str;
        !           797: {
        !           798:        struct proto_tag *cp;
        !           799: 
        !           800:        if (str == NULL) {
        !           801:                errno = EINVAL;
        !           802:                return -1;
        !           803:        }
        !           804: 
        !           805:        /* checking the string of command. */
        !           806:        for (cp = &prototab[0]; cp->str; cp++) {
        !           807:                if (strcmp(str, cp->str) == 0)
        !           808:                        return cp->proto;
        !           809:        }
        !           810: 
        !           811:        errno = EINVAL;
        !           812:        return -1;
        !           813: }
        !           814: 
        !           815: static vchar_t *
        !           816: get_index(ac, av)
        !           817:        int ac;
        !           818:        char **av;
        !           819: {
        !           820:        int family;
        !           821: 
        !           822:        if (ac != 3 && ac != 4) {
        !           823:                errno = EINVAL;
        !           824:                return NULL;
        !           825:        }
        !           826: 
        !           827:        /* checking the string of family */
        !           828:        family = get_family(*av);
        !           829:        if (family == -1)
        !           830:                return NULL;
        !           831:        av++;
        !           832:        ac--;
        !           833: 
        !           834:        return get_comindexes(family, ac, av);
        !           835: }
        !           836: 
        !           837: static int
        !           838: get_family(str)
        !           839:        char *str;
        !           840: {
        !           841:        if (strcmp("inet", str) == 0)
        !           842:                return AF_INET;
        !           843: #ifdef INET6
        !           844:        else if (strcmp("inet6", str) == 0)
        !           845:                return AF_INET6;
        !           846: #endif
        !           847:        errno = EAFNOSUPPORT;
        !           848:        return -1;
        !           849: }
        !           850: 
        !           851: static vchar_t *
        !           852: get_comindexes(family, ac, av)
        !           853:        int family;
        !           854:        int ac;
        !           855:        char **av;
        !           856: {
        !           857:        vchar_t *buf;
        !           858:        struct admin_com_indexes *ci;
        !           859:        char *p_name = NULL, *p_port = NULL;
        !           860:        char *p_prefs = NULL, *p_prefd = NULL;
        !           861:        struct sockaddr *src = NULL, *dst = NULL;
        !           862:        int ulproto;
        !           863: 
        !           864:        if (ac != 2 && ac != 3) {
        !           865:                errno = EINVAL;
        !           866:                return NULL;
        !           867:        }
        !           868: 
        !           869:        if (get_comindex(*av, &p_name, &p_port, &p_prefs) == -1)
        !           870:                goto bad;
        !           871:        src = get_sockaddr(family, p_name, p_port);
        !           872:        if (p_name) {
        !           873:                racoon_free(p_name);
        !           874:                p_name = NULL;
        !           875:        }
        !           876:        if (p_port) {
        !           877:                racoon_free(p_port);
        !           878:                p_port = NULL;
        !           879:        }
        !           880:        if (src == NULL)
        !           881:                goto bad;
        !           882:        av++;
        !           883:        ac--;
        !           884:        if (get_comindex(*av, &p_name, &p_port, &p_prefd) == -1)
        !           885:                goto bad;
        !           886:        dst = get_sockaddr(family, p_name, p_port);
        !           887:        if (p_name) {
        !           888:                racoon_free(p_name);
        !           889:                p_name = NULL;
        !           890:        }
        !           891:        if (p_port) {
        !           892:                racoon_free(p_port);
        !           893:                p_port = NULL;
        !           894:        }
        !           895:        if (dst == NULL)
        !           896:                goto bad;
        !           897: 
        !           898:        buf = vmalloc(sizeof(*ci));
        !           899:        if (buf == NULL)
        !           900:                goto bad;
        !           901: 
        !           902:        av++;
        !           903:        ac--;
        !           904:        if(ac){
        !           905:                ulproto = get_ulproto(*av);
        !           906:                if (ulproto == -1)
        !           907:                        goto bad;
        !           908:        }else
        !           909:                ulproto=0;
        !           910: 
        !           911:        ci = (struct admin_com_indexes *)buf->v;
        !           912:        if(p_prefs)
        !           913:                ci->prefs = (u_int8_t)atoi(p_prefs); /* XXX should be handled error. */
        !           914:        else
        !           915:                ci->prefs = 32;
        !           916:        if(p_prefd)
        !           917:                ci->prefd = (u_int8_t)atoi(p_prefd); /* XXX should be handled error. */
        !           918:        else
        !           919:                ci->prefd = 32;
        !           920:        ci->ul_proto = ulproto;
        !           921:        memcpy(&ci->src, src, sysdep_sa_len(src));
        !           922:        memcpy(&ci->dst, dst, sysdep_sa_len(dst));
        !           923: 
        !           924:        if (p_name)
        !           925:                racoon_free(p_name);
        !           926: 
        !           927:        return buf;
        !           928: 
        !           929:    bad:
        !           930:        if (p_name)
        !           931:                racoon_free(p_name);
        !           932:        if (p_port)
        !           933:                racoon_free(p_port);
        !           934:        if (p_prefs)
        !           935:                racoon_free(p_prefs);
        !           936:        if (p_prefd)
        !           937:                racoon_free(p_prefd);
        !           938:        return NULL;
        !           939: }
        !           940: 
        !           941: static int
        !           942: get_comindex(str, name, port, pref)
        !           943:        char *str, **name, **port, **pref;
        !           944: {
        !           945:        char *p;
        !           946: 
        !           947:        *name = *port = *pref = NULL;
        !           948: 
        !           949:        *name = racoon_strdup(str);
        !           950:        STRDUP_FATAL(*name);
        !           951:        p = strpbrk(*name, "/[");
        !           952:        if (p != NULL) {
        !           953:                if (*(p + 1) == '\0')
        !           954:                        goto bad;
        !           955:                if (*p == '/') {
        !           956:                        *p = '\0';
        !           957:                        *pref = racoon_strdup(p + 1);
        !           958:                        STRDUP_FATAL(*pref);
        !           959:                        p = strchr(*pref, '[');
        !           960:                        if (p != NULL) {
        !           961:                                if (*(p + 1) == '\0')
        !           962:                                        goto bad;
        !           963:                                *p = '\0';
        !           964:                                *port = racoon_strdup(p + 1);
        !           965:                                STRDUP_FATAL(*port);
        !           966:                                p = strchr(*pref, ']');
        !           967:                                if (p == NULL)
        !           968:                                        goto bad;
        !           969:                                *p = '\0';
        !           970:                        }
        !           971:                } else if (*p == '[') {
        !           972:                        if (*pref == NULL)
        !           973:                                goto bad;
        !           974:                        *p = '\0';
        !           975:                        *port = racoon_strdup(p + 1);
        !           976:                        STRDUP_FATAL(*port);
        !           977:                        p = strchr(*pref, ']');
        !           978:                        if (p == NULL)
        !           979:                                goto bad;
        !           980:                        *p = '\0';
        !           981:                } else {
        !           982:                        /* XXX */
        !           983:                }
        !           984:        }
        !           985: 
        !           986:        return 0;
        !           987: 
        !           988:     bad:
        !           989: 
        !           990:        if (*name)
        !           991:                racoon_free(*name);
        !           992:        if (*port)
        !           993:                racoon_free(*port);
        !           994:        if (*pref)
        !           995:                racoon_free(*pref);
        !           996:        *name = *port = *pref = NULL;
        !           997:        return -1;
        !           998: }
        !           999: 
        !          1000: static int
        !          1001: get_ulproto(str)
        !          1002:        char *str;
        !          1003: {
        !          1004:        struct ulproto_tag *cp;
        !          1005: 
        !          1006:        if(str == NULL){
        !          1007:                errno = EINVAL;
        !          1008:                return -1;
        !          1009:        }
        !          1010: 
        !          1011:        /* checking the string of upper layer protocol. */
        !          1012:        for (cp = &ulprototab[0]; cp->str; cp++) {
        !          1013:                if (strcmp(str, cp->str) == 0)
        !          1014:                        return cp->ul_proto;
        !          1015:        }
        !          1016: 
        !          1017:        errno = EINVAL;
        !          1018:        return -1;
        !          1019: }
        !          1020: 
        !          1021: /* %%% */
        !          1022: void
        !          1023: dump_isakmp_sa(buf, len)
        !          1024:        char *buf;
        !          1025:        int len;
        !          1026: {
        !          1027:        struct ph1dump *pd;
        !          1028:        struct tm *tm;
        !          1029:        char tbuf[56];
        !          1030:        caddr_t p = NULL;
        !          1031: 
        !          1032: /* isakmp status header */
        !          1033: /* short header;
        !          1034:  1234567890123456789012 0000000000000000:0000000000000000 000000000000
        !          1035: */
        !          1036: char *header1 = 
        !          1037: "Destination            Cookies                           Created";
        !          1038: 
        !          1039: /* semi long header;
        !          1040:  1234567890123456789012 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000
        !          1041: */
        !          1042: char *header2 = 
        !          1043: "Destination            Cookies                           ST S  V E Created             Phase2";
        !          1044: 
        !          1045: /* long header;
        !          1046:  0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000
        !          1047: */
        !          1048: char *header3 =
        !          1049: "Source                                        Destination                                   Cookies                           ST S  V E Created             Phase2";
        !          1050: 
        !          1051: /* phase status header */
        !          1052: /* short format;
        !          1053:    side stats source address         destination address   
        !          1054:    xxx  xxxxx 1234567890123456789012 1234567890123456789012
        !          1055: */
        !          1056: 
        !          1057:        static char *estr[] = { "", "B", "M", "U", "A", "I", };
        !          1058: 
        !          1059:        switch (long_format) {
        !          1060:        case 0:
        !          1061:                printf("%s\n", header1);
        !          1062:                break;
        !          1063:        case 1:
        !          1064:                printf("%s\n", header2);
        !          1065:                break;
        !          1066:        case 2:
        !          1067:        default:
        !          1068:                printf("%s\n", header3);
        !          1069:                break;
        !          1070:        }
        !          1071: 
        !          1072:        if (len % sizeof(*pd))
        !          1073:                printf("invalid length %d\n", len);
        !          1074:        len /= sizeof(*pd);
        !          1075: 
        !          1076:        pd = (struct ph1dump *)buf;
        !          1077: 
        !          1078:        while (len-- > 0) {
        !          1079:                /* source address */
        !          1080:                if (long_format >= 2) {
        !          1081:                        GETNAMEINFO((struct sockaddr *)&pd->local, _addr1_, _addr2_);
        !          1082:                        switch (long_format) {
        !          1083:                        case 0:
        !          1084:                                break;
        !          1085:                        case 1:
        !          1086:                                p = fixed_addr(_addr1_, _addr2_, 22);
        !          1087:                                break;
        !          1088:                        case 2:
        !          1089:                        default:
        !          1090:                                p = fixed_addr(_addr1_, _addr2_, 45);
        !          1091:                                break;
        !          1092:                        }
        !          1093:                        printf("%s ", p);
        !          1094:                }
        !          1095: 
        !          1096:                /* destination address */
        !          1097:                GETNAMEINFO((struct sockaddr *)&pd->remote, _addr1_, _addr2_);
        !          1098:                switch (long_format) {
        !          1099:                case 0:
        !          1100:                case 1:
        !          1101:                        p = fixed_addr(_addr1_, _addr2_, 22);
        !          1102:                        break;
        !          1103:                case 2:
        !          1104:                default:
        !          1105:                        p = fixed_addr(_addr1_, _addr2_, 45);
        !          1106:                        break;
        !          1107:                }
        !          1108:                printf("%s ", p);
        !          1109: 
        !          1110:                printf("%s ", pindex_isakmp(&pd->index));
        !          1111: 
        !          1112:                /* statuc, side and version */
        !          1113:                if (long_format >= 1) {
        !          1114:                        printf("%2d %c %2x ",
        !          1115:                                pd->status,
        !          1116:                                pd->side == INITIATOR ? 'I' : 'R',
        !          1117:                                pd->version);
        !          1118:                        if (ARRAYLEN(estr) > pd->etype)
        !          1119:                                printf("%s ", estr[pd->etype]);
        !          1120:                }
        !          1121: 
        !          1122:                /* created date */
        !          1123:                if (pd->created) {
        !          1124:                        tm = localtime(&pd->created);
        !          1125:                        strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm);
        !          1126:                } else
        !          1127:                        snprintf(tbuf, sizeof(tbuf), "                   ");
        !          1128:                printf("%s ", tbuf);
        !          1129: 
        !          1130:                /* counter of phase 2 */
        !          1131:                if (long_format >= 1)
        !          1132:                        printf("%6d ", pd->ph2cnt);
        !          1133: 
        !          1134:                printf("\n");
        !          1135: 
        !          1136:                pd++;
        !          1137:        }
        !          1138: 
        !          1139:        return;
        !          1140: }
        !          1141: 
        !          1142: /* %%% */
        !          1143: void
        !          1144: dump_internal(buf, tlen)
        !          1145:        char *buf;
        !          1146:        int tlen;
        !          1147: {
        !          1148:        struct ph2handle *iph2;
        !          1149:        struct sockaddr *addr;
        !          1150: 
        !          1151: /*
        !          1152: short header;
        !          1153:  source address         destination address    
        !          1154:  1234567890123456789012 1234567890123456789012 
        !          1155: */
        !          1156: char *short_h1 = 
        !          1157: "Source                 Destination            ";
        !          1158: 
        !          1159: /*
        !          1160: long header;
        !          1161:  source address                                destination address                           
        !          1162:  123456789012345678901234567890123456789012345 123456789012345678901234567890123456789012345 
        !          1163:  0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000 0000:0000:0000:0000:0000:0000:0000:0000.00000
        !          1164: */
        !          1165: char *long_h1 = 
        !          1166: "Source                                        Destination                                  ";
        !          1167: 
        !          1168:        printf("%s\n", long_format ? long_h1 : short_h1);
        !          1169: 
        !          1170:        while (tlen > 0) {
        !          1171:                iph2 = (struct ph2handle *)buf;
        !          1172:                addr = (struct sockaddr *)(++iph2);
        !          1173: 
        !          1174:                GETNAMEINFO(addr, _addr1_, _addr2_);
        !          1175:                printf("%s ", long_format ?
        !          1176:                          fixed_addr(_addr1_, _addr2_, 45)
        !          1177:                        : fixed_addr(_addr1_, _addr2_, 22));
        !          1178:                addr++;
        !          1179:                tlen -= sysdep_sa_len(addr);
        !          1180: 
        !          1181:                GETNAMEINFO(addr, _addr1_, _addr2_);
        !          1182:                printf("%s ", long_format ?
        !          1183:                          fixed_addr(_addr1_, _addr2_, 45)
        !          1184:                        : fixed_addr(_addr1_, _addr2_, 22));
        !          1185:                addr++;
        !          1186:                tlen -= sysdep_sa_len(addr);
        !          1187: 
        !          1188:                printf("\n");
        !          1189:        }
        !          1190: 
        !          1191:        return;
        !          1192: }
        !          1193: 
        !          1194: /* %%% */
        !          1195: char *
        !          1196: pindex_isakmp(index)
        !          1197:        isakmp_index *index;
        !          1198: {
        !          1199:        static char buf[64];
        !          1200:        u_char *p;
        !          1201:        int i, j;
        !          1202: 
        !          1203:        memset(buf, 0, sizeof(buf));
        !          1204: 
        !          1205:        /* copy index */
        !          1206:        p = (u_char *)index;
        !          1207:        for (j = 0, i = 0; i < sizeof(isakmp_index); i++) {
        !          1208:                snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]);
        !          1209:                j += 2;
        !          1210:                switch (i) {
        !          1211:                case 7:
        !          1212: #if 0
        !          1213:                case 15:
        !          1214: #endif
        !          1215:                        buf[j++] = ':';
        !          1216:                }
        !          1217:        }
        !          1218: 
        !          1219:        return buf;
        !          1220: }
        !          1221: 
        !          1222: /* print schedule */
        !          1223: char *str_sched_stat[] = {
        !          1224: "off",
        !          1225: "on",
        !          1226: "dead",
        !          1227: };
        !          1228: 
        !          1229: char *str_sched_id[] = {
        !          1230: "PH1resend",
        !          1231: "PH1lifetime",
        !          1232: "PH2resend",
        !          1233: "PSTacquire",
        !          1234: "PSTlifetime",
        !          1235: };
        !          1236: 
        !          1237: void
        !          1238: print_schedule(buf, len)
        !          1239:        caddr_t buf;
        !          1240:        int len;
        !          1241: {
        !          1242:        struct scheddump *sc = (struct scheddump *)buf;
        !          1243:        struct tm *tm;
        !          1244:        char tbuf[56];
        !          1245: 
        !          1246:        if (len % sizeof(*sc))
        !          1247:                printf("invalid length %d\n", len);
        !          1248:        len /= sizeof(*sc);
        !          1249: 
        !          1250:        /*      00000000 00000000 00000000 xxx........*/
        !          1251:        printf("index    tick     xtime    created\n");
        !          1252: 
        !          1253:        while (len-- > 0) {
        !          1254:                tm = localtime(&sc->created);
        !          1255:                strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm);
        !          1256: 
        !          1257:                printf("%-8ld %-8ld %-8ld %s\n",
        !          1258:                        sc->id,
        !          1259:                        (long)sc->tick,
        !          1260:                        (long)sc->xtime,
        !          1261:                        tbuf);
        !          1262:                sc++;
        !          1263:        }
        !          1264: 
        !          1265:        return;
        !          1266: }
        !          1267: 
        !          1268: 
        !          1269: void
        !          1270: print_evt(evtdump)
        !          1271:        struct evt_async *evtdump;
        !          1272: {
        !          1273:        int i;
        !          1274:        char *srcstr;
        !          1275:        char *dststr;
        !          1276:        
        !          1277:        for (i = 0; i < sizeof(evtmsg) / sizeof(evtmsg[0]); i++)
        !          1278:                if (evtmsg[i].type == evtdump->ec_type)
        !          1279:                        break;
        !          1280: 
        !          1281:        if (evtmsg[i].msg == NULL)
        !          1282:                printf("Event %d: ", evtdump->ec_type);
        !          1283:        else
        !          1284:                printf("%s : ", evtmsg[i].msg);
        !          1285: 
        !          1286:        if ((srcstr = saddr2str((struct sockaddr *)&evtdump->ec_ph1src)) == NULL)
        !          1287:                printf("unknown");
        !          1288:        else
        !          1289:                printf("%s", srcstr);
        !          1290:        printf(" -> ");
        !          1291:        if ((dststr = saddr2str((struct sockaddr *)&evtdump->ec_ph1dst)) == NULL)
        !          1292:                printf("unknown");
        !          1293:        else
        !          1294:                printf("%s", dststr);
        !          1295:        printf("\n");
        !          1296: }
        !          1297: 
        !          1298: /*
        !          1299:  * Print ISAKMP mode config info (IP and banner)
        !          1300:  */
        !          1301: void
        !          1302: print_cfg(buf, len)
        !          1303:        caddr_t buf;
        !          1304:        int len;
        !          1305: {
        !          1306:        struct evt_async *evtdump = (struct evt_async *)buf;
        !          1307:        struct isakmp_data *attr;
        !          1308:        char *banner = NULL;
        !          1309:        struct in_addr addr4;
        !          1310:        
        !          1311:        memset(&addr4, 0, sizeof(addr4));
        !          1312: 
        !          1313:        if (evtdump->ec_type != EVT_PHASE1_MODE_CFG)
        !          1314:                return;
        !          1315: 
        !          1316:        len -= sizeof(*evtdump);
        !          1317:        attr = (struct isakmp_data *)(evtdump + 1);
        !          1318: 
        !          1319:        while (len > 0) {
        !          1320:                if (len < sizeof(*attr)) {
        !          1321:                        printf("short attribute too short\n");
        !          1322:                        break;
        !          1323:                }
        !          1324: 
        !          1325:                if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
        !          1326:                        /* Short attribute, skip */
        !          1327:                        len -= sizeof(*attr);
        !          1328:                        attr++;
        !          1329:                } else { /* Long attribute */
        !          1330:                        char *n;
        !          1331: 
        !          1332:                        if (len < (sizeof(*attr) + ntohs(attr->lorv))) {
        !          1333:                                printf("long attribute too long\n");
        !          1334:                                break;
        !          1335:                        }
        !          1336: 
        !          1337:                        switch (ntohs(attr->type) & ~ISAKMP_GEN_MASK) {
        !          1338:                        case INTERNAL_IP4_ADDRESS:
        !          1339:                                if (ntohs(attr->lorv) < sizeof(addr4)) {
        !          1340:                                        printf("addr4 attribute too short\n");
        !          1341:                                        break;
        !          1342:                                }
        !          1343:                                memcpy(&addr4, attr + 1, sizeof(addr4));
        !          1344:                                break;
        !          1345: 
        !          1346:                        case UNITY_BANNER:
        !          1347:                                banner = racoon_malloc(ntohs(attr->lorv) + 1);
        !          1348:                                if (banner == NULL) {
        !          1349:                                        printf("malloc failed\n");
        !          1350:                                        break;
        !          1351:                                }
        !          1352:                                memcpy(banner, attr + 1, ntohs(attr->lorv));
        !          1353:                                banner[ntohs(attr->lorv)] = '\0';
        !          1354:                                break;
        !          1355: 
        !          1356:                        default:
        !          1357:                                break;
        !          1358:                        }
        !          1359: 
        !          1360:                        len -= (sizeof(*attr) + ntohs(attr->lorv));
        !          1361:                        n = (char *)attr;
        !          1362:                        attr = (struct isakmp_data *)
        !          1363:                            (n + sizeof(*attr) + ntohs(attr->lorv));
        !          1364:                }
        !          1365:        }
        !          1366: 
        !          1367:        if (len > 0)
        !          1368:                printf("Bound to address %s\n", inet_ntoa(addr4));
        !          1369:        else
        !          1370:                printf("VPN connexion established\n");
        !          1371: 
        !          1372:        if (banner) {
        !          1373:                struct winsize win;
        !          1374:                int col = 0;
        !          1375:                int i;
        !          1376: 
        !          1377:                if (ioctl(1, TIOCGWINSZ, &win) != 1) 
        !          1378:                        col = win.ws_col;
        !          1379:                        
        !          1380:                for (i = 0; i < col; i++)
        !          1381:                        printf("%c", '=');
        !          1382:                printf("\n%s\n", banner);
        !          1383:                for (i = 0; i < col; i++)
        !          1384:                        printf("%c", '=');
        !          1385:                printf("\n");
        !          1386:                racoon_free(banner);
        !          1387:        }
        !          1388: }
        !          1389: 
        !          1390: 
        !          1391: char *
        !          1392: fixed_addr(addr, port, len)
        !          1393:        char *addr, *port;
        !          1394:        int len;
        !          1395: {
        !          1396:        static char _addr_buf_[BUFSIZ];
        !          1397:        char *p;
        !          1398:        int plen, i;
        !          1399: 
        !          1400:        /* initialize */
        !          1401:        memset(_addr_buf_, ' ', sizeof(_addr_buf_));
        !          1402: 
        !          1403:        plen = strlen(port);
        !          1404:        if (len < plen + 1)
        !          1405:                return NULL;
        !          1406: 
        !          1407:        p = _addr_buf_;
        !          1408:        for (i = 0; i < len - plen - 1 && addr[i] != '\0'; /*noting*/)
        !          1409:                *p++ = addr[i++];
        !          1410:        *p++ = '.';
        !          1411: 
        !          1412:        for (i = 0; i < plen && port[i] != '\0'; /*noting*/)
        !          1413:                *p++ = port[i++];
        !          1414: 
        !          1415:        _addr_buf_[len] = '\0';
        !          1416: 
        !          1417:        return _addr_buf_;
        !          1418: }
        !          1419: 
        !          1420: static int
        !          1421: handle_recv(combuf)
        !          1422:        vchar_t *combuf;
        !          1423: {
        !          1424:         struct admin_com *com;
        !          1425:         caddr_t buf;
        !          1426:         int len;
        !          1427: 
        !          1428:        com = (struct admin_com *)combuf->v;
        !          1429:        if (com->ac_cmd & ADMIN_FLAG_LONG_REPLY)
        !          1430:                len = ((u_int32_t)com->ac_len) + (((u_int32_t)com->ac_len_high) << 16);
        !          1431:        else
        !          1432:                len = com->ac_len;
        !          1433:        len -= sizeof(*com);
        !          1434:        buf = combuf->v + sizeof(*com);
        !          1435: 
        !          1436:        switch (com->ac_cmd & ~ADMIN_FLAG_LONG_REPLY) {
        !          1437:        case ADMIN_SHOW_SCHED:
        !          1438:                print_schedule(buf, len);
        !          1439:                break;
        !          1440: 
        !          1441:        case ADMIN_SHOW_EVT: {
        !          1442:                struct evt_async *ec;
        !          1443: 
        !          1444:                /* We got no event? */
        !          1445:                if (len == 0)
        !          1446:                        break;
        !          1447: 
        !          1448:                if (len < sizeof(struct evt_async))
        !          1449:                        errx(1, "Short buffer\n");
        !          1450: 
        !          1451:                ec = (struct evt_async *) buf;
        !          1452:                if (evt_quit_event <= 0)
        !          1453:                        print_evt(ec);
        !          1454:                else if (evt_quit_event == ec->ec_type) {
        !          1455:                        switch (ec->ec_type) {
        !          1456:                        case EVT_PHASE1_MODE_CFG:
        !          1457:                                print_cfg(ec, len);
        !          1458:                                break;
        !          1459:                        default:
        !          1460:                                print_evt(ec);
        !          1461:                                break;
        !          1462:                        }
        !          1463:                        evt_quit_event = 0;
        !          1464:                }
        !          1465:                break;
        !          1466:        }
        !          1467: 
        !          1468:        case ADMIN_GET_SA_CERT:
        !          1469:                fwrite(buf, len, 1, stdout);
        !          1470:                break;
        !          1471: 
        !          1472:        case ADMIN_SHOW_SA:
        !          1473:           {
        !          1474:                switch (com->ac_proto) {
        !          1475:                case ADMIN_PROTO_ISAKMP:
        !          1476:                        dump_isakmp_sa(buf, len);
        !          1477:                        break;
        !          1478:                case ADMIN_PROTO_IPSEC:
        !          1479:                case ADMIN_PROTO_AH:
        !          1480:                case ADMIN_PROTO_ESP:
        !          1481:                    {
        !          1482:                        struct sadb_msg *msg = (struct sadb_msg *)buf;
        !          1483: 
        !          1484:                        switch (msg->sadb_msg_errno) {
        !          1485:                        case ENOENT:
        !          1486:                                switch (msg->sadb_msg_type) {
        !          1487:                                case SADB_DELETE:
        !          1488:                                case SADB_GET:
        !          1489:                                        printf("No entry.\n");
        !          1490:                                        break;
        !          1491:                                case SADB_DUMP:
        !          1492:                                        printf("No SAD entries.\n");
        !          1493:                                        break;
        !          1494:                                }
        !          1495:                                break;
        !          1496:                        case 0:
        !          1497:                                while (1) {
        !          1498:                                        pfkey_sadump(msg);
        !          1499:                                        if (msg->sadb_msg_seq == 0)
        !          1500:                                                break;
        !          1501:                                        msg = (struct sadb_msg *)((caddr_t)msg +
        !          1502:                                                     PFKEY_UNUNIT64(msg->sadb_msg_len));
        !          1503:                                }
        !          1504:                                break;
        !          1505:                        default:
        !          1506:                                printf("%s.\n", strerror(msg->sadb_msg_errno));
        !          1507:                        }
        !          1508:                    }
        !          1509:                        break;
        !          1510:                case ADMIN_PROTO_INTERNAL:
        !          1511:                        dump_internal(buf, len);
        !          1512:                        break;
        !          1513:                default:
        !          1514:                        printf("Invalid proto [%d]\n", com->ac_proto);
        !          1515:                }
        !          1516: 
        !          1517:            }
        !          1518:                break;
        !          1519: 
        !          1520:        default:
        !          1521:                /* IGNORE */
        !          1522:                break;
        !          1523:        }
        !          1524: 
        !          1525:        return 0;
        !          1526: 
        !          1527: bad:
        !          1528:        return -1;
        !          1529: }

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