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