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