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
usage()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
main(ac,av)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
evt_poll(void)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 *
get_combuf(ac,av)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 *
f_reload(ac,av)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 *
f_getevt(ac,av)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 *
f_getsched(ac,av)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 *
f_getsa(ac,av)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 *
f_flushsa(ac,av)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 *
f_deletesa(ac,av)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 *
f_deleteallsadst(ac,av)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 *
f_exchangesa(ac,av)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 *
f_vpnc(ac,av)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 *
f_vpnd(ac,av)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 *
f_logoutusr(ac,av)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
get_proto(str)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 *
get_index(ac,av)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
get_family(str)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 *
get_comindexes(family,ac,av)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
get_comindex(str,name,port,pref)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
get_ulproto(str)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
dump_isakmp_sa(buf,len)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
dump_internal(buf,tlen)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 *
pindex_isakmp(index)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
print_schedule(buf,len)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
print_evt(buf,len)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
print_err(buf,len)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
print_ph1down(buf,len)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
print_cfg(buf,len)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 *
fixed_addr(addr,port,len)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
handle_recv(combuf)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