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