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