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