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
usage()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
main(ac,av)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 *
get_combuf(ac,av)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 *
make_request(u_int16_t cmd,u_int16_t proto,size_t len)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 *
f_reload(ac,av)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 *
f_getevt(ac,av)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 *
f_getsched(ac,av)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 *
f_getsa(ac,av)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 *
f_getsacert(ac,av)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 *
f_flushsa(ac,av)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 *
f_deletesa(ac,av)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 *
f_deleteallsadst(ac,av)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 *
f_exchangesa(ac,av)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 *
f_vpnc(ac,av)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 *
f_vpnd(ac,av)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 *
f_logoutusr(ac,av)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 *
get_proto_and_index(ac,av,proto)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
get_proto(str)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 *
get_index(ac,av)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
get_family(str)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 *
get_comindexes(family,ac,av)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
get_comindex(str,name,port,pref)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
get_ulproto(str)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
dump_isakmp_sa(buf,len)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
dump_internal(buf,tlen)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 *
pindex_isakmp(index)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
print_schedule(buf,len)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
print_evt(evtdump)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
print_cfg(buf,len)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 *
fixed_addr(addr,port,len)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
handle_recv(combuf)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 }
1530