1*731159f7Stteras /*	$NetBSD: racoonctl.c,v 1.18 2010/11/12 09:08:26 tteras Exp $	*/
28006965bSmanu 
3c8214a0aSmanu /*	Id: racoonctl.c,v 1.11 2006/04/06 17:06:25 manubsd Exp */
4a8f0ad3cSmanu 
5a8f0ad3cSmanu /*
6a8f0ad3cSmanu  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
73fd729adSmgrooms  * Copyright (C) 2008 Timo Teras.
8a8f0ad3cSmanu  * All rights reserved.
9a8f0ad3cSmanu  *
10a8f0ad3cSmanu  * Redistribution and use in source and binary forms, with or without
11a8f0ad3cSmanu  * modification, are permitted provided that the following conditions
12a8f0ad3cSmanu  * are met:
13a8f0ad3cSmanu  * 1. Redistributions of source code must retain the above copyright
14a8f0ad3cSmanu  *    notice, this list of conditions and the following disclaimer.
15a8f0ad3cSmanu  * 2. Redistributions in binary form must reproduce the above copyright
16a8f0ad3cSmanu  *    notice, this list of conditions and the following disclaimer in the
17a8f0ad3cSmanu  *    documentation and/or other materials provided with the distribution.
18a8f0ad3cSmanu  * 3. Neither the name of the project nor the names of its contributors
19a8f0ad3cSmanu  *    may be used to endorse or promote products derived from this software
20a8f0ad3cSmanu  *    without specific prior written permission.
21a8f0ad3cSmanu  *
22a8f0ad3cSmanu  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23a8f0ad3cSmanu  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24a8f0ad3cSmanu  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25a8f0ad3cSmanu  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26a8f0ad3cSmanu  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27a8f0ad3cSmanu  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28a8f0ad3cSmanu  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29a8f0ad3cSmanu  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30a8f0ad3cSmanu  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31a8f0ad3cSmanu  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32a8f0ad3cSmanu  * SUCH DAMAGE.
33a8f0ad3cSmanu  */
34a8f0ad3cSmanu 
35a8f0ad3cSmanu #include "config.h"
36a8f0ad3cSmanu 
37a8f0ad3cSmanu #include <sys/types.h>
38a8f0ad3cSmanu #include <sys/param.h>
39a8f0ad3cSmanu #include <sys/socket.h>
40a8f0ad3cSmanu #include <sys/un.h>
41a8f0ad3cSmanu 
42a8f0ad3cSmanu #include <netinet/in.h>
43a8f0ad3cSmanu #include <arpa/inet.h>
44a8f0ad3cSmanu #include <net/pfkeyv2.h>
45a8f0ad3cSmanu 
46a8f0ad3cSmanu #include <stdlib.h>
47a8f0ad3cSmanu #include <stdio.h>
48a8f0ad3cSmanu #include <string.h>
49a8f0ad3cSmanu #include <errno.h>
50a8f0ad3cSmanu #if TIME_WITH_SYS_TIME
51a8f0ad3cSmanu # include <sys/time.h>
52a8f0ad3cSmanu # include <time.h>
53a8f0ad3cSmanu #else
54a8f0ad3cSmanu # if HAVE_SYS_TIME_H
55a8f0ad3cSmanu #  include <sys/time.h>
56a8f0ad3cSmanu # else
57a8f0ad3cSmanu #  include <time.h>
58a8f0ad3cSmanu # endif
59a8f0ad3cSmanu #endif
60a8f0ad3cSmanu #include <netdb.h>
61a8f0ad3cSmanu #ifdef HAVE_UNISTD_H
62a8f0ad3cSmanu #include <unistd.h>
63a8f0ad3cSmanu #endif
64a8f0ad3cSmanu #include <err.h>
65a8f0ad3cSmanu #include <sys/ioctl.h>
66c8214a0aSmanu #include <resolv.h>
67a8f0ad3cSmanu 
68a8f0ad3cSmanu #include "var.h"
69a8f0ad3cSmanu #include "vmbuf.h"
70a8f0ad3cSmanu #include "misc.h"
71a8f0ad3cSmanu #include "gcmalloc.h"
72a8f0ad3cSmanu 
73a8f0ad3cSmanu #include "racoonctl.h"
74a8f0ad3cSmanu #include "admin.h"
75a8f0ad3cSmanu #include "schedule.h"
76a8f0ad3cSmanu #include "handler.h"
77a8f0ad3cSmanu #include "sockmisc.h"
78a8f0ad3cSmanu #include "vmbuf.h"
79c8214a0aSmanu #include "plog.h"
80a8f0ad3cSmanu #include "isakmp_var.h"
81a8f0ad3cSmanu #include "isakmp.h"
82a8f0ad3cSmanu #include "isakmp_xauth.h"
83a8f0ad3cSmanu #include "isakmp_cfg.h"
84a8f0ad3cSmanu #include "isakmp_unity.h"
85a8f0ad3cSmanu #include "ipsec_doi.h"
86a8f0ad3cSmanu #include "evt.h"
87a8f0ad3cSmanu 
88df08b9e7Smanu char *adminsock_path = ADMINSOCK_PATH;
89a8f0ad3cSmanu 
90a8f0ad3cSmanu static void usage __P((void));
91a8f0ad3cSmanu static vchar_t *get_combuf __P((int, char **));
92a8f0ad3cSmanu static int handle_recv __P((vchar_t *));
93a8f0ad3cSmanu static vchar_t *f_reload __P((int, char **));
94a8f0ad3cSmanu static vchar_t *f_getsched __P((int, char **));
95a8f0ad3cSmanu static vchar_t *f_getsa __P((int, char **));
9693c1205fSmgrooms static vchar_t *f_getsacert __P((int, char **));
97a8f0ad3cSmanu static vchar_t *f_flushsa __P((int, char **));
98a8f0ad3cSmanu static vchar_t *f_deletesa __P((int, char **));
99a8f0ad3cSmanu static vchar_t *f_exchangesa __P((int, char **));
100a8f0ad3cSmanu static vchar_t *f_vpnc __P((int, char **));
101a8f0ad3cSmanu static vchar_t *f_vpnd __P((int, char **));
102a8f0ad3cSmanu static vchar_t *f_getevt __P((int, char **));
103c8214a0aSmanu #ifdef ENABLE_HYBRID
104c8214a0aSmanu static vchar_t *f_logoutusr __P((int, char **));
105c8214a0aSmanu #endif
106a8f0ad3cSmanu 
107a8f0ad3cSmanu struct cmd_tag {
108a8f0ad3cSmanu 	vchar_t *(*func) __P((int, char **));
109a8f0ad3cSmanu 	char *str;
110a8f0ad3cSmanu } cmdtab[] = {
1117dac6429Smgrooms 	{ f_reload,	"reload-config" },
1127dac6429Smgrooms 	{ f_reload,	"rc" },
1137dac6429Smgrooms 	{ f_getsched,	"show-schedule" },
1147dac6429Smgrooms 	{ f_getsched,	"sc" },
1157dac6429Smgrooms 	{ f_getsa,	"show-sa" },
1167dac6429Smgrooms 	{ f_getsa,	"ss" },
11793c1205fSmgrooms 	{ f_getsacert,	"get-cert" },
11893c1205fSmgrooms 	{ f_getsacert,	"gc" },
1197dac6429Smgrooms 	{ f_flushsa,	"flush-sa" },
1207dac6429Smgrooms 	{ f_flushsa,	"fs" },
1217dac6429Smgrooms 	{ f_deletesa,	"delete-sa" },
1227dac6429Smgrooms 	{ f_deletesa,	"ds" },
1237dac6429Smgrooms 	{ f_exchangesa,	"establish-sa" },
1247dac6429Smgrooms 	{ f_exchangesa,	"es" },
1257dac6429Smgrooms 	{ f_vpnc,	"vpn-connect" },
1267dac6429Smgrooms 	{ f_vpnc,	"vc" },
1277dac6429Smgrooms 	{ f_vpnd,	"vpn-disconnect" },
1287dac6429Smgrooms 	{ f_vpnd,	"vd" },
1297dac6429Smgrooms 	{ f_getevt,	"show-event" },
1307dac6429Smgrooms 	{ f_getevt,	"se" },
131c8214a0aSmanu #ifdef ENABLE_HYBRID
1327dac6429Smgrooms 	{ f_logoutusr,	"logout-user" },
1337dac6429Smgrooms 	{ f_logoutusr,	"lu" },
134c8214a0aSmanu #endif
1357dac6429Smgrooms 	{ NULL, NULL },
136a8f0ad3cSmanu };
137a8f0ad3cSmanu 
138a8f0ad3cSmanu struct evtmsg {
139a8f0ad3cSmanu 	int type;
140a8f0ad3cSmanu 	char *msg;
141a8f0ad3cSmanu } evtmsg[] = {
1423fd729adSmgrooms 	{ EVT_RACOON_QUIT,		"Racoon terminated" },
1433fd729adSmgrooms 
1443fd729adSmgrooms 	{ EVT_PHASE1_UP,		"Phase 1 established" },
1453fd729adSmgrooms 	{ EVT_PHASE1_DOWN,		"Phase 1 deleted" },
1463fd729adSmgrooms 	{ EVT_PHASE1_NO_RESPONSE,	"Phase 1 error: peer not responding" },
1473fd729adSmgrooms 	{ EVT_PHASE1_NO_PROPOSAL,	"Phase 1 error: no proposal chosen" },
1483fd729adSmgrooms 	{ EVT_PHASE1_AUTH_FAILED,
1493fd729adSmgrooms 	  "Phase 1 error: authentication failed (bad certificate?)" },
1503fd729adSmgrooms 	{ EVT_PHASE1_DPD_TIMEOUT,	"Phase 1 error: dead peer detected" },
1513fd729adSmgrooms 	{ EVT_PHASE1_MODE_CFG,		"Phase 1 mode configuration done" },
1523fd729adSmgrooms 	{ EVT_PHASE1_XAUTH_SUCCESS,	"Phase 1 Xauth succeeded" },
1533fd729adSmgrooms 	{ EVT_PHASE1_XAUTH_FAILED,	"Phase 1 Xauth failed" },
1543fd729adSmgrooms 
1553fd729adSmgrooms 	{ EVT_PHASE2_NO_PHASE1,		"Phase 2 error: no suitable phase 1" },
1563fd729adSmgrooms 	{ EVT_PHASE2_UP,		"Phase 2 established" },
1573fd729adSmgrooms 	{ EVT_PHASE2_DOWN,		"Phase 2 deleted" },
1583fd729adSmgrooms 	{ EVT_PHASE2_NO_RESPONSE,	"Phase 2 error: no response" },
159a8f0ad3cSmanu };
160a8f0ad3cSmanu 
1617dac6429Smgrooms static vchar_t *get_proto_and_index __P((int, char **, u_int16_t *));
162a8f0ad3cSmanu static int get_proto __P((char *));
163a8f0ad3cSmanu static vchar_t *get_index __P((int, char **));
164a8f0ad3cSmanu static int get_family __P((char *));
165a8f0ad3cSmanu static vchar_t *get_comindexes __P((int, int, char **));
166a8f0ad3cSmanu static int get_comindex __P((char *, char **, char **, char **));
167a8f0ad3cSmanu static int get_ulproto __P((char *));
168a8f0ad3cSmanu 
169a8f0ad3cSmanu struct proto_tag {
170a8f0ad3cSmanu 	int proto;
171a8f0ad3cSmanu 	char *str;
172a8f0ad3cSmanu } prototab[] = {
173a8f0ad3cSmanu 	{ ADMIN_PROTO_ISAKMP,	"isakmp" },
174a8f0ad3cSmanu 	{ ADMIN_PROTO_IPSEC,	"ipsec" },
175a8f0ad3cSmanu 	{ ADMIN_PROTO_AH,	"ah" },
176a8f0ad3cSmanu 	{ ADMIN_PROTO_ESP,	"esp" },
177a8f0ad3cSmanu 	{ ADMIN_PROTO_INTERNAL,	"internal" },
178a8f0ad3cSmanu 	{ 0, NULL },
179a8f0ad3cSmanu };
180a8f0ad3cSmanu 
181a8f0ad3cSmanu struct ulproto_tag {
182a8f0ad3cSmanu 	int ul_proto;
183a8f0ad3cSmanu 	char *str;
184a8f0ad3cSmanu } ulprototab[] = {
185a8f0ad3cSmanu 	{ 0,		"any" },
186a8f0ad3cSmanu 	{ IPPROTO_ICMP,	"icmp" },
187a8f0ad3cSmanu 	{ IPPROTO_TCP,	"tcp" },
188a8f0ad3cSmanu 	{ IPPROTO_UDP,	"udp" },
189c825a8eeSmgrooms 	{ IPPROTO_GRE,	"gre" },
190a8f0ad3cSmanu 	{ 0, NULL },
191a8f0ad3cSmanu };
192a8f0ad3cSmanu 
193a8f0ad3cSmanu int so;
194a8f0ad3cSmanu 
195a8f0ad3cSmanu static char _addr1_[NI_MAXHOST], _addr2_[NI_MAXHOST];
196a8f0ad3cSmanu 
197a8f0ad3cSmanu char *pname;
198a8f0ad3cSmanu int long_format = 0;
1993fd729adSmgrooms int evt_quit_event = 0;
200a8f0ad3cSmanu 
201a8f0ad3cSmanu void dump_isakmp_sa __P((char *, int));
202a8f0ad3cSmanu void dump_internal __P((char *, int));
203a8f0ad3cSmanu char *pindex_isakmp __P((isakmp_index *));
204a8f0ad3cSmanu void print_schedule __P((caddr_t, int));
2053fd729adSmgrooms void print_evt __P((struct evt_async *));
206a8f0ad3cSmanu char * fixed_addr __P((char *, char *, int));
207a8f0ad3cSmanu 
208a8f0ad3cSmanu static void
usage()209a8f0ad3cSmanu usage()
210a8f0ad3cSmanu {
211a8f0ad3cSmanu 	printf(
212a8f0ad3cSmanu "Usage:\n"
213e9d216a4Stteras "  %s [opts] reload-config\n"
214e9d216a4Stteras "  %s [opts] show-schedule\n"
215e9d216a4Stteras "  %s [opts] show-sa [protocol]\n"
216e9d216a4Stteras "  %s [opts] flush-sa [protocol]\n"
217e9d216a4Stteras "  %s [opts] delete-sa <saopts>\n"
218983cc8feStteras "  %s [opts] establish-sa [-u identity] [-n remoteconf] [-w] <saopts>\n"
219e9d216a4Stteras "  %s [opts] vpn-connect [-u identity] vpn_gateway\n"
220e9d216a4Stteras "  %s [opts] vpn-disconnect vpn_gateway\n"
221e9d216a4Stteras "  %s [opts] show-event\n"
222e9d216a4Stteras "  %s [opts] logout-user login\n"
223a8f0ad3cSmanu "\n"
224e9d216a4Stteras "General options:\n"
225e9d216a4Stteras "  -d		Debug: hexdump admin messages before sending\n"
22658b21619Swiz "  -l		Increase output verbosity (mainly for show-sa)\n"
227e9d216a4Stteras "  -s <socket>	Specify adminport socket to use (default: %s)\n"
228e9d216a4Stteras "\n"
229e9d216a4Stteras "Parameter specifications:\n"
230a8f0ad3cSmanu "    <protocol>: \"isakmp\", \"esp\" or \"ah\".\n"
231a8f0ad3cSmanu "        In the case of \"show-sa\" or \"flush-sa\", you can use \"ipsec\".\n"
232a8f0ad3cSmanu "\n"
233a8f0ad3cSmanu "    <saopts>: \"isakmp\" <family> <src> <dst>\n"
234a8f0ad3cSmanu "            : {\"esp\",\"ah\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n"
235a8f0ad3cSmanu "                              <ul_proto>\n"
236a8f0ad3cSmanu "    <family>: \"inet\" or \"inet6\"\n"
237e9d216a4Stteras "    <ul_proto>: \"icmp\", \"tcp\", \"udp\", \"gre\" or \"any\"\n"
238e9d216a4Stteras "\n",
239e9d216a4Stteras 		pname, pname, pname, pname, pname, pname, pname, pname, pname, pname,
240e9d216a4Stteras 		ADMINSOCK_PATH);
241a8f0ad3cSmanu }
242a8f0ad3cSmanu 
243a8f0ad3cSmanu /*
244a8f0ad3cSmanu  * Check for proper racoonctl interface
245a8f0ad3cSmanu  */
246a8f0ad3cSmanu #if ((RACOONCTL_INTERFACE_MAJOR != 1) || (RACOONCTL_INTERFACE < 20041230))
247a8f0ad3cSmanu #error	"Incompatible racoonctl interface"
248a8f0ad3cSmanu #endif
249a8f0ad3cSmanu 
250a8f0ad3cSmanu int
main(ac,av)251a8f0ad3cSmanu main(ac, av)
252a8f0ad3cSmanu 	int ac;
253a8f0ad3cSmanu 	char **av;
254a8f0ad3cSmanu {
255a8f0ad3cSmanu 	vchar_t *combuf;
256a8f0ad3cSmanu 	int c;
257a8f0ad3cSmanu 
258a8f0ad3cSmanu 	pname = *av;
259a8f0ad3cSmanu 
260a8f0ad3cSmanu 	/*
261a8f0ad3cSmanu 	 * Check for proper racoonctl interface
262a8f0ad3cSmanu 	 */
263a8f0ad3cSmanu 	if ((racoonctl_interface_major != RACOONCTL_INTERFACE_MAJOR) ||
264a8f0ad3cSmanu 	    (racoonctl_interface < RACOONCTL_INTERFACE))
265a8f0ad3cSmanu 		errx(1, "Incompatible racoonctl interface");
266a8f0ad3cSmanu 
267a8f0ad3cSmanu #ifdef __linux__
268a8f0ad3cSmanu 	/*
269a8f0ad3cSmanu 	 * Disable GNU extensions that will prevent racoonct vc -u login
270a8f0ad3cSmanu 	 * from working (GNU getopt(3) does not like options after vc)
271a8f0ad3cSmanu 	 */
272a8f0ad3cSmanu 	setenv("POSIXLY_CORRECT", "1", 0);
273a8f0ad3cSmanu #endif
274a8f0ad3cSmanu 	while ((c = getopt(ac, av, "lds:")) != -1) {
275a8f0ad3cSmanu 		switch(c) {
276a8f0ad3cSmanu 		case 'l':
277a8f0ad3cSmanu 			long_format++;
278a8f0ad3cSmanu 			break;
279a8f0ad3cSmanu 
280a8f0ad3cSmanu 		case 'd':
281a8f0ad3cSmanu 			loglevel++;
282a8f0ad3cSmanu 			break;
283a8f0ad3cSmanu 
284a8f0ad3cSmanu 		case 's':
285a8f0ad3cSmanu 			adminsock_path = optarg;
286a8f0ad3cSmanu 			break;
287a8f0ad3cSmanu 
288a8f0ad3cSmanu 		default:
289a8f0ad3cSmanu 			usage();
290a8f0ad3cSmanu 			exit(0);
291a8f0ad3cSmanu 		}
292a8f0ad3cSmanu 	}
293a8f0ad3cSmanu 
294a8f0ad3cSmanu 	ac -= optind;
295a8f0ad3cSmanu 	av += optind;
296a8f0ad3cSmanu 
297a8f0ad3cSmanu 	combuf = get_combuf(ac, av);
298a8f0ad3cSmanu 	if (!combuf)
299a8f0ad3cSmanu 		err(1, "kmpstat");
300a8f0ad3cSmanu 
301a8f0ad3cSmanu 	if (loglevel)
3028f0b3482Smgrooms 		racoon_hexdump(combuf, ((struct admin_com *)combuf)->ac_len);
303a8f0ad3cSmanu 
304a8f0ad3cSmanu 	com_init();
305a8f0ad3cSmanu 
306a8f0ad3cSmanu 	if (com_send(combuf) != 0)
307a8f0ad3cSmanu 		goto bad;
308a8f0ad3cSmanu 
309a8f0ad3cSmanu 	vfree(combuf);
310a8f0ad3cSmanu 
3113fd729adSmgrooms 	do {
312a8f0ad3cSmanu 		if (com_recv(&combuf) != 0)
313a8f0ad3cSmanu 			goto bad;
314a8f0ad3cSmanu 		if (handle_recv(combuf) != 0)
315a8f0ad3cSmanu 			goto bad;
316a8f0ad3cSmanu 		vfree(combuf);
3173fd729adSmgrooms 	} while (evt_quit_event != 0);
318a8f0ad3cSmanu 
3193fd729adSmgrooms 	close(so);
320a8f0ad3cSmanu 	exit(0);
321a8f0ad3cSmanu 
322a8f0ad3cSmanu bad:
3233fd729adSmgrooms 	close(so);
3243fd729adSmgrooms 	if (errno == EEXIST)
3253fd729adSmgrooms 		exit(0);
326a8f0ad3cSmanu 	exit(1);
327a8f0ad3cSmanu }
328a8f0ad3cSmanu 
329a8f0ad3cSmanu /* %%% */
330a8f0ad3cSmanu /*
331a8f0ad3cSmanu  * return command buffer.
332a8f0ad3cSmanu  */
333a8f0ad3cSmanu static vchar_t *
get_combuf(ac,av)334a8f0ad3cSmanu get_combuf(ac, av)
335a8f0ad3cSmanu 	int ac;
336a8f0ad3cSmanu 	char **av;
337a8f0ad3cSmanu {
338a8f0ad3cSmanu 	struct cmd_tag *cp;
339a8f0ad3cSmanu 
340a8f0ad3cSmanu 	if (ac == 0) {
341a8f0ad3cSmanu 		usage();
342a8f0ad3cSmanu 		exit(0);
343a8f0ad3cSmanu 	}
344a8f0ad3cSmanu 
345a8f0ad3cSmanu 	/* checking the string of command. */
346a8f0ad3cSmanu 	for (cp = &cmdtab[0]; cp->str; cp++) {
347a8f0ad3cSmanu 		if (strcmp(*av, cp->str) == 0) {
348a8f0ad3cSmanu 			break;
349a8f0ad3cSmanu 		}
350a8f0ad3cSmanu 	}
351a8f0ad3cSmanu 	if (!cp->str) {
352a8f0ad3cSmanu 		printf("Invalid command [%s]\n", *av);
353a8f0ad3cSmanu 		errno = EINVAL;
354a8f0ad3cSmanu 		return NULL;
355a8f0ad3cSmanu 	}
356a8f0ad3cSmanu 
357a8f0ad3cSmanu 	ac--;
358a8f0ad3cSmanu 	av++;
359a8f0ad3cSmanu 	return (cp->func)(ac, av);
360a8f0ad3cSmanu }
361a8f0ad3cSmanu 
362a8f0ad3cSmanu static vchar_t *
make_request(u_int16_t cmd,u_int16_t proto,size_t len)3633fd729adSmgrooms make_request(u_int16_t cmd, u_int16_t proto, size_t len)
364a8f0ad3cSmanu {
365a8f0ad3cSmanu 	vchar_t *buf;
366a8f0ad3cSmanu 	struct admin_com *head;
367a8f0ad3cSmanu 
3683fd729adSmgrooms 	buf = vmalloc(sizeof(struct admin_com) + len);
369a8f0ad3cSmanu 	if (buf == NULL)
370a8f0ad3cSmanu 		errx(1, "not enough core");
371a8f0ad3cSmanu 
372a8f0ad3cSmanu 	head = (struct admin_com *) buf->v;
373a8f0ad3cSmanu 	head->ac_len = buf->l;
3743fd729adSmgrooms 	head->ac_cmd = ADMIN_FLAG_VERSION | cmd;
3753fd729adSmgrooms 	head->ac_version = 1;
3763fd729adSmgrooms 	head->ac_proto = proto;
377a8f0ad3cSmanu 
378a8f0ad3cSmanu 	return buf;
379a8f0ad3cSmanu }
380a8f0ad3cSmanu 
381a8f0ad3cSmanu static vchar_t *
f_reload(ac,av)3823fd729adSmgrooms f_reload(ac, av)
3833fd729adSmgrooms 	int ac;
3843fd729adSmgrooms 	char **av;
3853fd729adSmgrooms {
3863fd729adSmgrooms 	return make_request(ADMIN_RELOAD_CONF, 0, 0);
3873fd729adSmgrooms }
3883fd729adSmgrooms 
3893fd729adSmgrooms static vchar_t *
f_getevt(ac,av)390a8f0ad3cSmanu f_getevt(ac, av)
391a8f0ad3cSmanu 	int ac;
392a8f0ad3cSmanu 	char **av;
393a8f0ad3cSmanu {
3943fd729adSmgrooms 	evt_quit_event = -1;
3953fd729adSmgrooms 	if (ac >= 1)
396a8f0ad3cSmanu 		errx(1, "too many arguments");
397a8f0ad3cSmanu 
3983fd729adSmgrooms 	return make_request(ADMIN_SHOW_EVT, 0, 0);
399a8f0ad3cSmanu }
400a8f0ad3cSmanu 
401a8f0ad3cSmanu static vchar_t *
f_getsched(ac,av)402a8f0ad3cSmanu f_getsched(ac, av)
403a8f0ad3cSmanu 	int ac;
404a8f0ad3cSmanu 	char **av;
405a8f0ad3cSmanu {
4063fd729adSmgrooms 	return make_request(ADMIN_SHOW_SCHED, 0, 0);
407a8f0ad3cSmanu }
408a8f0ad3cSmanu 
409a8f0ad3cSmanu static vchar_t *
f_getsa(ac,av)410a8f0ad3cSmanu f_getsa(ac, av)
411a8f0ad3cSmanu 	int ac;
412a8f0ad3cSmanu 	char **av;
413a8f0ad3cSmanu {
414a8f0ad3cSmanu 	int proto;
415a8f0ad3cSmanu 
416a8f0ad3cSmanu 	/* need protocol */
417a8f0ad3cSmanu 	if (ac != 1)
418a8f0ad3cSmanu 		errx(1, "insufficient arguments");
419a8f0ad3cSmanu 	proto = get_proto(*av);
420a8f0ad3cSmanu 	if (proto == -1)
421a8f0ad3cSmanu 		errx(1, "unknown protocol %s", *av);
422a8f0ad3cSmanu 
4233fd729adSmgrooms 	return make_request(ADMIN_SHOW_SA, proto, 0);
424a8f0ad3cSmanu }
425a8f0ad3cSmanu 
426a8f0ad3cSmanu static vchar_t *
f_getsacert(ac,av)42793c1205fSmgrooms f_getsacert(ac, av)
42893c1205fSmgrooms 	int ac;
42993c1205fSmgrooms 	char **av;
43093c1205fSmgrooms {
43193c1205fSmgrooms 	vchar_t *buf, *index;
43293c1205fSmgrooms 	struct admin_com_indexes *com;
43393c1205fSmgrooms 
43493c1205fSmgrooms 	index = get_index(ac, av);
43593c1205fSmgrooms 	if (index == NULL)
43693c1205fSmgrooms 		return NULL;
43793c1205fSmgrooms 
43893c1205fSmgrooms 	com = (struct admin_com_indexes *) index->v;
43993c1205fSmgrooms 	buf = make_request(ADMIN_GET_SA_CERT, ADMIN_PROTO_ISAKMP, index->l);
44093c1205fSmgrooms 	if (buf == NULL)
44193c1205fSmgrooms 		errx(1, "Cannot allocate buffer");
44293c1205fSmgrooms 
44393c1205fSmgrooms 	memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
44493c1205fSmgrooms 
44593c1205fSmgrooms 	vfree(index);
44693c1205fSmgrooms 
44793c1205fSmgrooms 	return buf;
44893c1205fSmgrooms }
44993c1205fSmgrooms 
45093c1205fSmgrooms static vchar_t *
f_flushsa(ac,av)451a8f0ad3cSmanu f_flushsa(ac, av)
452a8f0ad3cSmanu 	int ac;
453a8f0ad3cSmanu 	char **av;
454a8f0ad3cSmanu {
455a8f0ad3cSmanu 	vchar_t *buf;
456a8f0ad3cSmanu 	struct admin_com *head;
457a8f0ad3cSmanu 	int proto;
458a8f0ad3cSmanu 
459a8f0ad3cSmanu 	/* need protocol */
460a8f0ad3cSmanu 	if (ac != 1)
461a8f0ad3cSmanu 		errx(1, "insufficient arguments");
462a8f0ad3cSmanu 	proto = get_proto(*av);
463a8f0ad3cSmanu 	if (proto == -1)
464a8f0ad3cSmanu 		errx(1, "unknown protocol %s", *av);
465a8f0ad3cSmanu 
4663fd729adSmgrooms 	return make_request(ADMIN_FLUSH_SA, proto, 0);
467a8f0ad3cSmanu }
468a8f0ad3cSmanu 
469a8f0ad3cSmanu static vchar_t *
f_deletesa(ac,av)470a8f0ad3cSmanu f_deletesa(ac, av)
471a8f0ad3cSmanu 	int ac;
472a8f0ad3cSmanu 	char **av;
473a8f0ad3cSmanu {
474a8f0ad3cSmanu 	vchar_t *buf, *index;
475a8f0ad3cSmanu 	int proto;
476a8f0ad3cSmanu 
477a8f0ad3cSmanu 	/* need protocol */
478a8f0ad3cSmanu 	if (ac < 1)
479a8f0ad3cSmanu 		errx(1, "insufficient arguments");
480a8f0ad3cSmanu 	proto = get_proto(*av);
481a8f0ad3cSmanu 	if (proto == -1)
482a8f0ad3cSmanu 		errx(1, "unknown protocol %s", *av);
483a8f0ad3cSmanu 
484a8f0ad3cSmanu 	/* get index(es) */
485a8f0ad3cSmanu 	av++;
486a8f0ad3cSmanu 	ac--;
487a8f0ad3cSmanu 	switch (proto) {
488a8f0ad3cSmanu 	case ADMIN_PROTO_ISAKMP:
489a8f0ad3cSmanu 		index = get_index(ac, av);
490a8f0ad3cSmanu 		if (index == NULL)
491a8f0ad3cSmanu 			return NULL;
492a8f0ad3cSmanu 		break;
493a8f0ad3cSmanu 	case ADMIN_PROTO_AH:
494a8f0ad3cSmanu 	case ADMIN_PROTO_ESP:
495a8f0ad3cSmanu 		index = get_index(ac, av);
496a8f0ad3cSmanu 		if (index == NULL)
497a8f0ad3cSmanu 			return NULL;
498a8f0ad3cSmanu 		break;
499a8f0ad3cSmanu 	default:
500a8f0ad3cSmanu 		errno = EPROTONOSUPPORT;
501a8f0ad3cSmanu 		return NULL;
502a8f0ad3cSmanu 	}
503a8f0ad3cSmanu 
5043fd729adSmgrooms 	buf = make_request(ADMIN_DELETE_SA, proto, index->l);
505a8f0ad3cSmanu 	if (buf == NULL)
506c8214a0aSmanu 		goto out;
507a8f0ad3cSmanu 
5083fd729adSmgrooms 	memcpy(buf->v + sizeof(struct admin_com), index->v, index->l);
509a8f0ad3cSmanu 
510c8214a0aSmanu out:
511c8214a0aSmanu 	if (index != NULL)
512c8214a0aSmanu 		vfree(index);
513c8214a0aSmanu 
514a8f0ad3cSmanu 	return buf;
515a8f0ad3cSmanu }
516a8f0ad3cSmanu 
517a8f0ad3cSmanu static vchar_t *
f_deleteallsadst(ac,av)518a8f0ad3cSmanu f_deleteallsadst(ac, av)
519a8f0ad3cSmanu 	int ac;
520a8f0ad3cSmanu 	char **av;
521a8f0ad3cSmanu {
522a8f0ad3cSmanu 	vchar_t *buf, *index;
5237dac6429Smgrooms 	u_int16_t proto;
524a8f0ad3cSmanu 
5257dac6429Smgrooms 	index = get_proto_and_index(ac, av, &proto);
526a8f0ad3cSmanu 	if (index == NULL)
527a8f0ad3cSmanu 		return NULL;
528a8f0ad3cSmanu 
5293fd729adSmgrooms 	buf = make_request(ADMIN_DELETE_ALL_SA_DST, proto, index->l);
530a8f0ad3cSmanu 	if (buf == NULL)
531c8214a0aSmanu 		goto out;
532a8f0ad3cSmanu 
5333fd729adSmgrooms 	memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
534a8f0ad3cSmanu 
535c8214a0aSmanu out:
536c8214a0aSmanu 	if (index != NULL)
537c8214a0aSmanu 		vfree(index);
538c8214a0aSmanu 
539a8f0ad3cSmanu 	return buf;
540a8f0ad3cSmanu }
541a8f0ad3cSmanu 
542a8f0ad3cSmanu static vchar_t *
f_exchangesa(ac,av)543a8f0ad3cSmanu f_exchangesa(ac, av)
544a8f0ad3cSmanu 	int ac;
545a8f0ad3cSmanu 	char **av;
546a8f0ad3cSmanu {
547a8f0ad3cSmanu 	vchar_t *buf, *index;
5487dac6429Smgrooms 	u_int16_t proto;
549a8f0ad3cSmanu 	int cmd = ADMIN_ESTABLISH_SA;
550a8f0ad3cSmanu 	size_t com_len = 0;
551a8f0ad3cSmanu 	char *id = NULL;
552a8f0ad3cSmanu 	char *key = NULL;
553983cc8feStteras 	char *remoteconf = NULL;
554a8f0ad3cSmanu 	struct admin_com_psk *acp;
5551e1f81ebSmgrooms 	int wait = 0;
556a8f0ad3cSmanu 
557a8f0ad3cSmanu 	if (ac < 1)
558a8f0ad3cSmanu 		errx(1, "insufficient arguments");
559a8f0ad3cSmanu 
560a8f0ad3cSmanu 	/* Optional -u identity */
561a8f0ad3cSmanu 	if (strcmp(av[0], "-u") == 0) {
562a8f0ad3cSmanu 		if (ac < 2)
563a8f0ad3cSmanu 			errx(1, "-u require an argument");
564a8f0ad3cSmanu 
565a8f0ad3cSmanu 		id = av[1];
566a8f0ad3cSmanu 		if ((key = getpass("Password: ")) == NULL)
567a8f0ad3cSmanu 			errx(1, "getpass() failed: %s", strerror(errno));
568a8f0ad3cSmanu 
569a8f0ad3cSmanu 		com_len += sizeof(*acp) + strlen(id) + 1 + strlen(key) + 1;
570a8f0ad3cSmanu 		cmd = ADMIN_ESTABLISH_SA_PSK;
571a8f0ad3cSmanu 
572a8f0ad3cSmanu 		av += 2;
573a8f0ad3cSmanu 		ac -= 2;
574a8f0ad3cSmanu 	}
575a8f0ad3cSmanu 
576983cc8feStteras 	if (ac >= 2 && strcmp(av[0], "-n") == 0) {
577983cc8feStteras 		/* Remoteconf name */
578983cc8feStteras 		remoteconf = av[1];
579983cc8feStteras 		av += 2;
580983cc8feStteras 		ac -= 2;
581983cc8feStteras 	}
582983cc8feStteras 
5831e1f81ebSmgrooms 	if (ac >= 1 && strcmp(av[0], "-w") == 0) {
5841e1f81ebSmgrooms 		wait = 1;
5851e1f81ebSmgrooms 		av++;
5861e1f81ebSmgrooms 		ac--;
5871e1f81ebSmgrooms 	}
5881e1f81ebSmgrooms 
5897dac6429Smgrooms 	index = get_proto_and_index(ac, av, &proto);
590a8f0ad3cSmanu 	if (index == NULL)
591a8f0ad3cSmanu 		return NULL;
5927dac6429Smgrooms 
593983cc8feStteras 	if (proto == ADMIN_PROTO_ISAKMP && cmd == ADMIN_ESTABLISH_SA &&
594983cc8feStteras 	    remoteconf != NULL)
595983cc8feStteras 		com_len += strlen(remoteconf) + 1;
596983cc8feStteras 
5977dac6429Smgrooms 	if (wait) {
5987dac6429Smgrooms 		switch (proto) {
5997dac6429Smgrooms 		case ADMIN_PROTO_ISAKMP:
6001e1f81ebSmgrooms 			evt_quit_event = EVT_PHASE1_MODE_CFG;
601a8f0ad3cSmanu 			break;
602a8f0ad3cSmanu 		case ADMIN_PROTO_AH:
603a8f0ad3cSmanu 		case ADMIN_PROTO_ESP:
6041e1f81ebSmgrooms 			evt_quit_event = EVT_PHASE2_UP;
605a8f0ad3cSmanu 			break;
606a8f0ad3cSmanu 		default:
607a8f0ad3cSmanu 			errno = EPROTONOSUPPORT;
608a8f0ad3cSmanu 			return NULL;
609a8f0ad3cSmanu 		}
6107dac6429Smgrooms 	}
611a8f0ad3cSmanu 
6123fd729adSmgrooms 	com_len += index->l;
6133fd729adSmgrooms 	buf = make_request(cmd, proto, com_len);
6143fd729adSmgrooms 	if (buf == NULL)
615a8f0ad3cSmanu 		errx(1, "Cannot allocate buffer");
616a8f0ad3cSmanu 
6173fd729adSmgrooms 	memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
618a8f0ad3cSmanu 
619983cc8feStteras 	if (proto == ADMIN_PROTO_ISAKMP && cmd == ADMIN_ESTABLISH_SA &&
620983cc8feStteras 	    remoteconf != NULL) {
621983cc8feStteras 		strcpy(buf->v + sizeof(struct admin_com) + index->l,
622983cc8feStteras 		       remoteconf);
623983cc8feStteras 	} else if (id && key) {
624a8f0ad3cSmanu 		char *data;
625a8f0ad3cSmanu 		acp = (struct admin_com_psk *)
6263fd729adSmgrooms 		    (buf->v + sizeof(struct admin_com) + index->l);
627a8f0ad3cSmanu 
628c8214a0aSmanu 		acp->id_type = IDTYPE_USERFQDN;
629a8f0ad3cSmanu 		acp->id_len = strlen(id) + 1;
630a8f0ad3cSmanu 		acp->key_len = strlen(key) + 1;
631a8f0ad3cSmanu 
632a8f0ad3cSmanu 		data = (char *)(acp + 1);
633a8f0ad3cSmanu 		strcpy(data, id);
634a8f0ad3cSmanu 
635a8f0ad3cSmanu 		data = (char *)(data + acp->id_len);
636a8f0ad3cSmanu 		strcpy(data, key);
637a8f0ad3cSmanu 	}
638a8f0ad3cSmanu 
639c8214a0aSmanu 	vfree(index);
640c8214a0aSmanu 
641a8f0ad3cSmanu 	return buf;
642a8f0ad3cSmanu }
643a8f0ad3cSmanu 
644a8f0ad3cSmanu static vchar_t *
f_vpnc(ac,av)645a8f0ad3cSmanu f_vpnc(ac, av)
646a8f0ad3cSmanu 	int ac;
647a8f0ad3cSmanu 	char **av;
648a8f0ad3cSmanu {
649a8f0ad3cSmanu 	char *nav[] = {NULL, NULL, NULL, NULL, NULL, NULL};
650a8f0ad3cSmanu 	int nac = 0;
651a8f0ad3cSmanu 	char *isakmp = "isakmp";
652a8f0ad3cSmanu 	char *inet = "inet";
653a8f0ad3cSmanu 	char *srcaddr;
654a8f0ad3cSmanu 	struct addrinfo hints, *res;
655a8f0ad3cSmanu 	struct sockaddr *src;
656a8f0ad3cSmanu 	char *idx;
657a8f0ad3cSmanu 
658a8f0ad3cSmanu 	if (ac < 1)
659a8f0ad3cSmanu 		errx(1, "insufficient arguments");
660a8f0ad3cSmanu 
6613fd729adSmgrooms 	evt_quit_event = EVT_PHASE1_MODE_CFG;
662a8f0ad3cSmanu 
663a8f0ad3cSmanu 	/* Optional -u identity */
664a8f0ad3cSmanu 	if (strcmp(av[0], "-u") == 0) {
665a8f0ad3cSmanu 		if (ac < 2)
666a8f0ad3cSmanu 			errx(1, "-u require an argument");
667a8f0ad3cSmanu 
668a8f0ad3cSmanu 		nav[nac++] = av[0];
669a8f0ad3cSmanu 		nav[nac++] = av[1];
670a8f0ad3cSmanu 
671a8f0ad3cSmanu 		ac -= 2;
672a8f0ad3cSmanu 		av += 2;
673a8f0ad3cSmanu 	}
674a8f0ad3cSmanu 
675a8f0ad3cSmanu 	if (ac < 1)
676a8f0ad3cSmanu 		errx(1, "VPN gateway required");
677a8f0ad3cSmanu 	if (ac > 1)
678a8f0ad3cSmanu 		warnx("Extra arguments");
679a8f0ad3cSmanu 
680a8f0ad3cSmanu 	/*
681a8f0ad3cSmanu 	 * Find the source address
682a8f0ad3cSmanu 	 */
683a8f0ad3cSmanu 	memset(&hints, 0, sizeof(hints));
684a8f0ad3cSmanu 	hints.ai_family = PF_UNSPEC;
685a8f0ad3cSmanu 	hints.ai_socktype = SOCK_DGRAM;
686a8f0ad3cSmanu 	if (getaddrinfo(av[0], "4500", &hints, &res) != 0)
687a8f0ad3cSmanu 		errx(1, "Cannot resolve destination address");
688a8f0ad3cSmanu 
689a8f0ad3cSmanu 	if ((src = getlocaladdr(res->ai_addr)) == NULL)
690a8f0ad3cSmanu 		errx(1, "cannot find source address");
691a8f0ad3cSmanu 
692a8f0ad3cSmanu 	if ((srcaddr = saddr2str(src)) == NULL)
693a8f0ad3cSmanu 		errx(1, "cannot read source address");
694a8f0ad3cSmanu 
695a8f0ad3cSmanu 	/* We get "ip[port]" strip the port */
696a8f0ad3cSmanu 	if ((idx = index(srcaddr, '[')) == NULL)
697a8f0ad3cSmanu 		errx(1, "unexpected source address format");
698a8f0ad3cSmanu 	*idx = '\0';
699a8f0ad3cSmanu 
700a8f0ad3cSmanu 	nav[nac++] = isakmp;
701a8f0ad3cSmanu 	nav[nac++] = inet;
702a8f0ad3cSmanu 	nav[nac++] = srcaddr;
703a8f0ad3cSmanu 	nav[nac++] = av[0];
704a8f0ad3cSmanu 
705a8f0ad3cSmanu 	return f_exchangesa(nac, nav);
706a8f0ad3cSmanu }
707a8f0ad3cSmanu 
708a8f0ad3cSmanu static vchar_t *
f_vpnd(ac,av)709a8f0ad3cSmanu f_vpnd(ac, av)
710a8f0ad3cSmanu 	int ac;
711a8f0ad3cSmanu 	char **av;
712a8f0ad3cSmanu {
713a8f0ad3cSmanu 	char *nav[] = {NULL, NULL, NULL, NULL};
714a8f0ad3cSmanu 	int nac = 0;
715a8f0ad3cSmanu 	char *isakmp = "isakmp";
716a8f0ad3cSmanu 	char *inet = "inet";
717a8f0ad3cSmanu 	char *anyaddr = "0.0.0.0";
718a8f0ad3cSmanu 	char *idx;
719a8f0ad3cSmanu 
720a8f0ad3cSmanu 	if (ac < 1)
721a8f0ad3cSmanu 		errx(1, "VPN gateway required");
722a8f0ad3cSmanu 	if (ac > 1)
723a8f0ad3cSmanu 		warnx("Extra arguments");
724a8f0ad3cSmanu 
7253fd729adSmgrooms 	evt_quit_event = EVT_PHASE1_DOWN;
726a8f0ad3cSmanu 
727a8f0ad3cSmanu 	nav[nac++] = isakmp;
728a8f0ad3cSmanu 	nav[nac++] = inet;
729a8f0ad3cSmanu 	nav[nac++] = anyaddr;
730a8f0ad3cSmanu 	nav[nac++] = av[0];
731a8f0ad3cSmanu 
732a8f0ad3cSmanu 	return f_deleteallsadst(nac, nav);
733a8f0ad3cSmanu }
734a8f0ad3cSmanu 
735c8214a0aSmanu #ifdef ENABLE_HYBRID
736c8214a0aSmanu static vchar_t *
f_logoutusr(ac,av)737c8214a0aSmanu f_logoutusr(ac, av)
738c8214a0aSmanu 	int ac;
739c8214a0aSmanu 	char **av;
740c8214a0aSmanu {
741c8214a0aSmanu 	vchar_t *buf;
742c8214a0aSmanu 	char *user;
743b1fd61f6Stteras 	size_t userlen;
744c8214a0aSmanu 
745c8214a0aSmanu 	/* need username */
746c8214a0aSmanu 	if (ac < 1)
747c8214a0aSmanu 		errx(1, "insufficient arguments");
748c8214a0aSmanu 	user = av[0];
749b1fd61f6Stteras 	userlen = strlen(user);
750b1fd61f6Stteras 	if ((user == NULL) || (userlen > LOGINLEN))
751c8214a0aSmanu 		errx(1, "bad login (too long?)");
752c8214a0aSmanu 
753b1fd61f6Stteras 	buf = make_request(ADMIN_LOGOUT_USER, 0, userlen);
754c8214a0aSmanu 	if (buf == NULL)
755c8214a0aSmanu 		return NULL;
756c8214a0aSmanu 
757b1fd61f6Stteras 	strncpy(buf->v + sizeof(struct admin_com), user, userlen);
758c8214a0aSmanu 
759c8214a0aSmanu 	return buf;
760c8214a0aSmanu }
761c8214a0aSmanu #endif /* ENABLE_HYBRID */
762c8214a0aSmanu 
7637dac6429Smgrooms static vchar_t *
get_proto_and_index(ac,av,proto)7647dac6429Smgrooms get_proto_and_index(ac, av, proto)
7657dac6429Smgrooms 	int ac;
7667dac6429Smgrooms 	char **av;
7677dac6429Smgrooms 	u_int16_t *proto;
7687dac6429Smgrooms {
7697dac6429Smgrooms 	vchar_t *index = NULL;
7707dac6429Smgrooms 
7717dac6429Smgrooms 	/* need protocol */
7727dac6429Smgrooms 	if (ac < 1)
7737dac6429Smgrooms 		errx(1, "insufficient arguments");
7747dac6429Smgrooms 	*proto = get_proto(*av);
7757dac6429Smgrooms 	if (*proto == (u_int16_t) -1)
7767dac6429Smgrooms 		errx(1, "unknown protocol %s", *av);
7777dac6429Smgrooms 
7787dac6429Smgrooms 	/* get index(es) */
7797dac6429Smgrooms 	av++;
7807dac6429Smgrooms 	ac--;
7817dac6429Smgrooms 	switch (*proto) {
7827dac6429Smgrooms 	case ADMIN_PROTO_ISAKMP:
7837dac6429Smgrooms 	case ADMIN_PROTO_AH:
7847dac6429Smgrooms 	case ADMIN_PROTO_ESP:
7857dac6429Smgrooms 		index = get_index(ac, av);
7867dac6429Smgrooms 		break;
7877dac6429Smgrooms 	default:
7887dac6429Smgrooms 		errno = EPROTONOSUPPORT;
7897dac6429Smgrooms 		break;
7907dac6429Smgrooms 	}
7917dac6429Smgrooms 	return index;
7927dac6429Smgrooms }
793a8f0ad3cSmanu 
794a8f0ad3cSmanu static int
get_proto(str)795a8f0ad3cSmanu get_proto(str)
796a8f0ad3cSmanu 	char *str;
797a8f0ad3cSmanu {
798a8f0ad3cSmanu 	struct proto_tag *cp;
799a8f0ad3cSmanu 
800a8f0ad3cSmanu 	if (str == NULL) {
801a8f0ad3cSmanu 		errno = EINVAL;
802a8f0ad3cSmanu 		return -1;
803a8f0ad3cSmanu 	}
804a8f0ad3cSmanu 
805a8f0ad3cSmanu 	/* checking the string of command. */
806a8f0ad3cSmanu 	for (cp = &prototab[0]; cp->str; cp++) {
807a8f0ad3cSmanu 		if (strcmp(str, cp->str) == 0)
808a8f0ad3cSmanu 			return cp->proto;
809a8f0ad3cSmanu 	}
810a8f0ad3cSmanu 
811a8f0ad3cSmanu 	errno = EINVAL;
812a8f0ad3cSmanu 	return -1;
813a8f0ad3cSmanu }
814a8f0ad3cSmanu 
815a8f0ad3cSmanu static vchar_t *
get_index(ac,av)816a8f0ad3cSmanu get_index(ac, av)
817a8f0ad3cSmanu 	int ac;
818a8f0ad3cSmanu 	char **av;
819a8f0ad3cSmanu {
820a8f0ad3cSmanu 	int family;
821a8f0ad3cSmanu 
822a8f0ad3cSmanu 	if (ac != 3 && ac != 4) {
823a8f0ad3cSmanu 		errno = EINVAL;
824a8f0ad3cSmanu 		return NULL;
825a8f0ad3cSmanu 	}
826a8f0ad3cSmanu 
827a8f0ad3cSmanu 	/* checking the string of family */
828a8f0ad3cSmanu 	family = get_family(*av);
829a8f0ad3cSmanu 	if (family == -1)
830a8f0ad3cSmanu 		return NULL;
831a8f0ad3cSmanu 	av++;
832a8f0ad3cSmanu 	ac--;
833a8f0ad3cSmanu 
834a8f0ad3cSmanu 	return get_comindexes(family, ac, av);
835a8f0ad3cSmanu }
836a8f0ad3cSmanu 
837a8f0ad3cSmanu static int
get_family(str)838a8f0ad3cSmanu get_family(str)
839a8f0ad3cSmanu 	char *str;
840a8f0ad3cSmanu {
841a8f0ad3cSmanu 	if (strcmp("inet", str) == 0)
842a8f0ad3cSmanu 		return AF_INET;
843a8f0ad3cSmanu #ifdef INET6
844a8f0ad3cSmanu 	else if (strcmp("inet6", str) == 0)
845a8f0ad3cSmanu 		return AF_INET6;
846a8f0ad3cSmanu #endif
847a8f0ad3cSmanu 	errno = EAFNOSUPPORT;
848a8f0ad3cSmanu 	return -1;
849a8f0ad3cSmanu }
850a8f0ad3cSmanu 
851a8f0ad3cSmanu static vchar_t *
get_comindexes(family,ac,av)852a8f0ad3cSmanu get_comindexes(family, ac, av)
853a8f0ad3cSmanu 	int family;
854a8f0ad3cSmanu 	int ac;
855a8f0ad3cSmanu 	char **av;
856a8f0ad3cSmanu {
857a8f0ad3cSmanu 	vchar_t *buf;
858a8f0ad3cSmanu 	struct admin_com_indexes *ci;
859a8f0ad3cSmanu 	char *p_name = NULL, *p_port = NULL;
860a8f0ad3cSmanu 	char *p_prefs = NULL, *p_prefd = NULL;
861a8f0ad3cSmanu 	struct sockaddr *src = NULL, *dst = NULL;
862a8f0ad3cSmanu 	int ulproto;
863a8f0ad3cSmanu 
864a8f0ad3cSmanu 	if (ac != 2 && ac != 3) {
865a8f0ad3cSmanu 		errno = EINVAL;
866a8f0ad3cSmanu 		return NULL;
867a8f0ad3cSmanu 	}
868a8f0ad3cSmanu 
869a8f0ad3cSmanu 	if (get_comindex(*av, &p_name, &p_port, &p_prefs) == -1)
870a8f0ad3cSmanu 		goto bad;
871a8f0ad3cSmanu 	src = get_sockaddr(family, p_name, p_port);
872a8f0ad3cSmanu 	if (p_name) {
873a8f0ad3cSmanu 		racoon_free(p_name);
874a8f0ad3cSmanu 		p_name = NULL;
875a8f0ad3cSmanu 	}
876a8f0ad3cSmanu 	if (p_port) {
877a8f0ad3cSmanu 		racoon_free(p_port);
878a8f0ad3cSmanu 		p_port = NULL;
879a8f0ad3cSmanu 	}
880a8f0ad3cSmanu 	if (src == NULL)
881a8f0ad3cSmanu 		goto bad;
882a8f0ad3cSmanu 	av++;
883a8f0ad3cSmanu 	ac--;
884a8f0ad3cSmanu 	if (get_comindex(*av, &p_name, &p_port, &p_prefd) == -1)
885a8f0ad3cSmanu 		goto bad;
886a8f0ad3cSmanu 	dst = get_sockaddr(family, p_name, p_port);
887a8f0ad3cSmanu 	if (p_name) {
888a8f0ad3cSmanu 		racoon_free(p_name);
889a8f0ad3cSmanu 		p_name = NULL;
890a8f0ad3cSmanu 	}
891a8f0ad3cSmanu 	if (p_port) {
892a8f0ad3cSmanu 		racoon_free(p_port);
893a8f0ad3cSmanu 		p_port = NULL;
894a8f0ad3cSmanu 	}
895a8f0ad3cSmanu 	if (dst == NULL)
896a8f0ad3cSmanu 		goto bad;
897a8f0ad3cSmanu 
898a8f0ad3cSmanu 	buf = vmalloc(sizeof(*ci));
899a8f0ad3cSmanu 	if (buf == NULL)
900a8f0ad3cSmanu 		goto bad;
901a8f0ad3cSmanu 
902a8f0ad3cSmanu 	av++;
903a8f0ad3cSmanu 	ac--;
904a8f0ad3cSmanu 	if(ac){
905a8f0ad3cSmanu 		ulproto = get_ulproto(*av);
906a8f0ad3cSmanu 		if (ulproto == -1)
907a8f0ad3cSmanu 			goto bad;
908a8f0ad3cSmanu 	}else
909a8f0ad3cSmanu 		ulproto=0;
910a8f0ad3cSmanu 
911a8f0ad3cSmanu 	ci = (struct admin_com_indexes *)buf->v;
912a8f0ad3cSmanu 	if(p_prefs)
913a8f0ad3cSmanu 		ci->prefs = (u_int8_t)atoi(p_prefs); /* XXX should be handled error. */
914a8f0ad3cSmanu 	else
915a8f0ad3cSmanu 		ci->prefs = 32;
916a8f0ad3cSmanu 	if(p_prefd)
917a8f0ad3cSmanu 		ci->prefd = (u_int8_t)atoi(p_prefd); /* XXX should be handled error. */
918a8f0ad3cSmanu 	else
919a8f0ad3cSmanu 		ci->prefd = 32;
920a8f0ad3cSmanu 	ci->ul_proto = ulproto;
921a8f0ad3cSmanu 	memcpy(&ci->src, src, sysdep_sa_len(src));
922a8f0ad3cSmanu 	memcpy(&ci->dst, dst, sysdep_sa_len(dst));
923a8f0ad3cSmanu 
924a8f0ad3cSmanu 	if (p_name)
925a8f0ad3cSmanu 		racoon_free(p_name);
926a8f0ad3cSmanu 
927a8f0ad3cSmanu 	return buf;
928a8f0ad3cSmanu 
929a8f0ad3cSmanu    bad:
930a8f0ad3cSmanu 	if (p_name)
931a8f0ad3cSmanu 		racoon_free(p_name);
932a8f0ad3cSmanu 	if (p_port)
933a8f0ad3cSmanu 		racoon_free(p_port);
934a8f0ad3cSmanu 	if (p_prefs)
935a8f0ad3cSmanu 		racoon_free(p_prefs);
936a8f0ad3cSmanu 	if (p_prefd)
937a8f0ad3cSmanu 		racoon_free(p_prefd);
938a8f0ad3cSmanu 	return NULL;
939a8f0ad3cSmanu }
940a8f0ad3cSmanu 
941a8f0ad3cSmanu static int
get_comindex(str,name,port,pref)942a8f0ad3cSmanu get_comindex(str, name, port, pref)
943a8f0ad3cSmanu 	char *str, **name, **port, **pref;
944a8f0ad3cSmanu {
945a8f0ad3cSmanu 	char *p;
946a8f0ad3cSmanu 
947a8f0ad3cSmanu 	*name = *port = *pref = NULL;
948a8f0ad3cSmanu 
949c8214a0aSmanu 	*name = racoon_strdup(str);
950c8214a0aSmanu 	STRDUP_FATAL(*name);
951a8f0ad3cSmanu 	p = strpbrk(*name, "/[");
952a8f0ad3cSmanu 	if (p != NULL) {
953a8f0ad3cSmanu 		if (*(p + 1) == '\0')
954a8f0ad3cSmanu 			goto bad;
955a8f0ad3cSmanu 		if (*p == '/') {
956a8f0ad3cSmanu 			*p = '\0';
957c8214a0aSmanu 			*pref = racoon_strdup(p + 1);
958c8214a0aSmanu 			STRDUP_FATAL(*pref);
959a8f0ad3cSmanu 			p = strchr(*pref, '[');
960a8f0ad3cSmanu 			if (p != NULL) {
961a8f0ad3cSmanu 				if (*(p + 1) == '\0')
962a8f0ad3cSmanu 					goto bad;
963a8f0ad3cSmanu 				*p = '\0';
964c8214a0aSmanu 				*port = racoon_strdup(p + 1);
965c8214a0aSmanu 				STRDUP_FATAL(*port);
966a8f0ad3cSmanu 				p = strchr(*pref, ']');
967a8f0ad3cSmanu 				if (p == NULL)
968a8f0ad3cSmanu 					goto bad;
969a8f0ad3cSmanu 				*p = '\0';
970a8f0ad3cSmanu 			}
971a8f0ad3cSmanu 		} else if (*p == '[') {
9729a55720fSmanu 			if (*pref == NULL)
9739a55720fSmanu 				goto bad;
974a8f0ad3cSmanu 			*p = '\0';
975c8214a0aSmanu 			*port = racoon_strdup(p + 1);
976c8214a0aSmanu 			STRDUP_FATAL(*port);
977a8f0ad3cSmanu 			p = strchr(*pref, ']');
978a8f0ad3cSmanu 			if (p == NULL)
979a8f0ad3cSmanu 				goto bad;
980a8f0ad3cSmanu 			*p = '\0';
981a8f0ad3cSmanu 		} else {
982a8f0ad3cSmanu 			/* XXX */
983a8f0ad3cSmanu 		}
984a8f0ad3cSmanu 	}
985a8f0ad3cSmanu 
986a8f0ad3cSmanu 	return 0;
987a8f0ad3cSmanu 
988a8f0ad3cSmanu     bad:
989a8f0ad3cSmanu 
990a8f0ad3cSmanu 	if (*name)
991a8f0ad3cSmanu 		racoon_free(*name);
992a8f0ad3cSmanu 	if (*port)
993a8f0ad3cSmanu 		racoon_free(*port);
994a8f0ad3cSmanu 	if (*pref)
995a8f0ad3cSmanu 		racoon_free(*pref);
996a8f0ad3cSmanu 	*name = *port = *pref = NULL;
997a8f0ad3cSmanu 	return -1;
998a8f0ad3cSmanu }
999a8f0ad3cSmanu 
1000a8f0ad3cSmanu static int
get_ulproto(str)1001a8f0ad3cSmanu get_ulproto(str)
1002a8f0ad3cSmanu 	char *str;
1003a8f0ad3cSmanu {
1004a8f0ad3cSmanu 	struct ulproto_tag *cp;
1005a8f0ad3cSmanu 
1006a8f0ad3cSmanu 	if(str == NULL){
1007a8f0ad3cSmanu 		errno = EINVAL;
1008a8f0ad3cSmanu 		return -1;
1009a8f0ad3cSmanu 	}
1010a8f0ad3cSmanu 
1011a8f0ad3cSmanu 	/* checking the string of upper layer protocol. */
1012a8f0ad3cSmanu 	for (cp = &ulprototab[0]; cp->str; cp++) {
1013a8f0ad3cSmanu 		if (strcmp(str, cp->str) == 0)
1014a8f0ad3cSmanu 			return cp->ul_proto;
1015a8f0ad3cSmanu 	}
1016a8f0ad3cSmanu 
1017a8f0ad3cSmanu 	errno = EINVAL;
1018a8f0ad3cSmanu 	return -1;
1019a8f0ad3cSmanu }
1020a8f0ad3cSmanu 
1021a8f0ad3cSmanu /* %%% */
1022a8f0ad3cSmanu void
dump_isakmp_sa(buf,len)1023a8f0ad3cSmanu dump_isakmp_sa(buf, len)
1024a8f0ad3cSmanu 	char *buf;
1025a8f0ad3cSmanu 	int len;
1026a8f0ad3cSmanu {
1027a8f0ad3cSmanu 	struct ph1dump *pd;
1028a8f0ad3cSmanu 	struct tm *tm;
1029a8f0ad3cSmanu 	char tbuf[56];
1030a8f0ad3cSmanu 	caddr_t p = NULL;
1031a8f0ad3cSmanu 
1032a8f0ad3cSmanu /* isakmp status header */
1033a8f0ad3cSmanu /* short header;
1034a8f0ad3cSmanu  1234567890123456789012 0000000000000000:0000000000000000 000000000000
1035a8f0ad3cSmanu */
1036a8f0ad3cSmanu char *header1 =
1037a8f0ad3cSmanu "Destination            Cookies                           Created";
1038a8f0ad3cSmanu 
1039a8f0ad3cSmanu /* semi long header;
1040a8f0ad3cSmanu  1234567890123456789012 0000000000000000:0000000000000000 00 X 00 X 0000-00-00 00:00:00 000000
1041a8f0ad3cSmanu */
1042a8f0ad3cSmanu char *header2 =
1043a8f0ad3cSmanu "Destination            Cookies                           ST S  V E Created             Phase2";
1044a8f0ad3cSmanu 
1045a8f0ad3cSmanu /* long header;
1046a8f0ad3cSmanu  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
1047a8f0ad3cSmanu */
1048a8f0ad3cSmanu char *header3 =
1049a8f0ad3cSmanu "Source                                        Destination                                   Cookies                           ST S  V E Created             Phase2";
1050a8f0ad3cSmanu 
1051a8f0ad3cSmanu /* phase status header */
1052a8f0ad3cSmanu /* short format;
1053a8f0ad3cSmanu    side stats source address         destination address
1054a8f0ad3cSmanu    xxx  xxxxx 1234567890123456789012 1234567890123456789012
1055a8f0ad3cSmanu */
1056a8f0ad3cSmanu 
1057a8f0ad3cSmanu 	static char *estr[] = { "", "B", "M", "U", "A", "I", };
1058a8f0ad3cSmanu 
1059a8f0ad3cSmanu 	switch (long_format) {
1060a8f0ad3cSmanu 	case 0:
1061a8f0ad3cSmanu 		printf("%s\n", header1);
1062a8f0ad3cSmanu 		break;
1063a8f0ad3cSmanu 	case 1:
1064a8f0ad3cSmanu 		printf("%s\n", header2);
1065a8f0ad3cSmanu 		break;
1066a8f0ad3cSmanu 	case 2:
1067a8f0ad3cSmanu 	default:
1068a8f0ad3cSmanu 		printf("%s\n", header3);
1069a8f0ad3cSmanu 		break;
1070a8f0ad3cSmanu 	}
1071a8f0ad3cSmanu 
1072a8f0ad3cSmanu 	if (len % sizeof(*pd))
1073a8f0ad3cSmanu 		printf("invalid length %d\n", len);
1074a8f0ad3cSmanu 	len /= sizeof(*pd);
1075a8f0ad3cSmanu 
1076a8f0ad3cSmanu 	pd = (struct ph1dump *)buf;
1077a8f0ad3cSmanu 
1078a8f0ad3cSmanu 	while (len-- > 0) {
1079a8f0ad3cSmanu 		/* source address */
1080a8f0ad3cSmanu 		if (long_format >= 2) {
1081a8f0ad3cSmanu 			GETNAMEINFO((struct sockaddr *)&pd->local, _addr1_, _addr2_);
1082a8f0ad3cSmanu 			switch (long_format) {
1083a8f0ad3cSmanu 			case 0:
1084a8f0ad3cSmanu 				break;
1085a8f0ad3cSmanu 			case 1:
1086a8f0ad3cSmanu 				p = fixed_addr(_addr1_, _addr2_, 22);
1087a8f0ad3cSmanu 				break;
1088a8f0ad3cSmanu 			case 2:
1089a8f0ad3cSmanu 			default:
1090a8f0ad3cSmanu 				p = fixed_addr(_addr1_, _addr2_, 45);
1091a8f0ad3cSmanu 				break;
1092a8f0ad3cSmanu 			}
1093a8f0ad3cSmanu 			printf("%s ", p);
1094a8f0ad3cSmanu 		}
1095a8f0ad3cSmanu 
1096a8f0ad3cSmanu 		/* destination address */
1097a8f0ad3cSmanu 		GETNAMEINFO((struct sockaddr *)&pd->remote, _addr1_, _addr2_);
1098a8f0ad3cSmanu 		switch (long_format) {
1099a8f0ad3cSmanu 		case 0:
1100a8f0ad3cSmanu 		case 1:
1101a8f0ad3cSmanu 			p = fixed_addr(_addr1_, _addr2_, 22);
1102a8f0ad3cSmanu 			break;
1103a8f0ad3cSmanu 		case 2:
1104a8f0ad3cSmanu 		default:
1105a8f0ad3cSmanu 			p = fixed_addr(_addr1_, _addr2_, 45);
1106a8f0ad3cSmanu 			break;
1107a8f0ad3cSmanu 		}
1108a8f0ad3cSmanu 		printf("%s ", p);
1109a8f0ad3cSmanu 
1110a8f0ad3cSmanu 		printf("%s ", pindex_isakmp(&pd->index));
1111a8f0ad3cSmanu 
1112a8f0ad3cSmanu 		/* statuc, side and version */
1113a8f0ad3cSmanu 		if (long_format >= 1) {
1114a8f0ad3cSmanu 			printf("%2d %c %2x ",
1115a8f0ad3cSmanu 				pd->status,
1116a8f0ad3cSmanu 				pd->side == INITIATOR ? 'I' : 'R',
1117a8f0ad3cSmanu 				pd->version);
1118a8f0ad3cSmanu 			if (ARRAYLEN(estr) > pd->etype)
1119a8f0ad3cSmanu 				printf("%s ", estr[pd->etype]);
1120a8f0ad3cSmanu 		}
1121a8f0ad3cSmanu 
1122a8f0ad3cSmanu 		/* created date */
1123a8f0ad3cSmanu 		if (pd->created) {
1124a8f0ad3cSmanu 			tm = localtime(&pd->created);
1125a8f0ad3cSmanu 			strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm);
1126a8f0ad3cSmanu 		} else
1127a8f0ad3cSmanu 			snprintf(tbuf, sizeof(tbuf), "                   ");
1128a8f0ad3cSmanu 		printf("%s ", tbuf);
1129a8f0ad3cSmanu 
1130a8f0ad3cSmanu 		/* counter of phase 2 */
1131a8f0ad3cSmanu 		if (long_format >= 1)
1132a8f0ad3cSmanu 			printf("%6d ", pd->ph2cnt);
1133a8f0ad3cSmanu 
1134a8f0ad3cSmanu 		printf("\n");
1135a8f0ad3cSmanu 
1136a8f0ad3cSmanu 		pd++;
1137a8f0ad3cSmanu 	}
1138a8f0ad3cSmanu 
1139a8f0ad3cSmanu 	return;
1140a8f0ad3cSmanu }
1141a8f0ad3cSmanu 
1142a8f0ad3cSmanu /* %%% */
1143a8f0ad3cSmanu void
dump_internal(buf,tlen)1144a8f0ad3cSmanu dump_internal(buf, tlen)
1145a8f0ad3cSmanu 	char *buf;
1146a8f0ad3cSmanu 	int tlen;
1147a8f0ad3cSmanu {
1148a8f0ad3cSmanu 	struct ph2handle *iph2;
1149a8f0ad3cSmanu 	struct sockaddr *addr;
1150a8f0ad3cSmanu 
1151a8f0ad3cSmanu /*
1152a8f0ad3cSmanu short header;
1153a8f0ad3cSmanu  source address         destination address
1154a8f0ad3cSmanu  1234567890123456789012 1234567890123456789012
1155a8f0ad3cSmanu */
1156a8f0ad3cSmanu char *short_h1 =
1157a8f0ad3cSmanu "Source                 Destination            ";
1158a8f0ad3cSmanu 
1159a8f0ad3cSmanu /*
1160a8f0ad3cSmanu long header;
1161a8f0ad3cSmanu  source address                                destination address
1162a8f0ad3cSmanu  123456789012345678901234567890123456789012345 123456789012345678901234567890123456789012345
1163a8f0ad3cSmanu  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
1164a8f0ad3cSmanu */
1165a8f0ad3cSmanu char *long_h1 =
1166a8f0ad3cSmanu "Source                                        Destination                                  ";
1167a8f0ad3cSmanu 
1168a8f0ad3cSmanu 	printf("%s\n", long_format ? long_h1 : short_h1);
1169a8f0ad3cSmanu 
1170a8f0ad3cSmanu 	while (tlen > 0) {
1171a8f0ad3cSmanu 		iph2 = (struct ph2handle *)buf;
1172a8f0ad3cSmanu 		addr = (struct sockaddr *)(++iph2);
1173a8f0ad3cSmanu 
1174a8f0ad3cSmanu 		GETNAMEINFO(addr, _addr1_, _addr2_);
1175a8f0ad3cSmanu 		printf("%s ", long_format ?
1176a8f0ad3cSmanu 			  fixed_addr(_addr1_, _addr2_, 45)
1177a8f0ad3cSmanu 			: fixed_addr(_addr1_, _addr2_, 22));
1178a8f0ad3cSmanu 		addr++;
1179a8f0ad3cSmanu 		tlen -= sysdep_sa_len(addr);
1180a8f0ad3cSmanu 
1181a8f0ad3cSmanu 		GETNAMEINFO(addr, _addr1_, _addr2_);
1182a8f0ad3cSmanu 		printf("%s ", long_format ?
1183a8f0ad3cSmanu 			  fixed_addr(_addr1_, _addr2_, 45)
1184a8f0ad3cSmanu 			: fixed_addr(_addr1_, _addr2_, 22));
1185a8f0ad3cSmanu 		addr++;
1186a8f0ad3cSmanu 		tlen -= sysdep_sa_len(addr);
1187a8f0ad3cSmanu 
1188a8f0ad3cSmanu 		printf("\n");
1189a8f0ad3cSmanu 	}
1190a8f0ad3cSmanu 
1191a8f0ad3cSmanu 	return;
1192a8f0ad3cSmanu }
1193a8f0ad3cSmanu 
1194a8f0ad3cSmanu /* %%% */
1195a8f0ad3cSmanu char *
pindex_isakmp(index)1196a8f0ad3cSmanu pindex_isakmp(index)
1197a8f0ad3cSmanu 	isakmp_index *index;
1198a8f0ad3cSmanu {
1199a8f0ad3cSmanu 	static char buf[64];
1200a8f0ad3cSmanu 	u_char *p;
1201a8f0ad3cSmanu 	int i, j;
1202a8f0ad3cSmanu 
1203a8f0ad3cSmanu 	memset(buf, 0, sizeof(buf));
1204a8f0ad3cSmanu 
1205a8f0ad3cSmanu 	/* copy index */
1206a8f0ad3cSmanu 	p = (u_char *)index;
1207a8f0ad3cSmanu 	for (j = 0, i = 0; i < sizeof(isakmp_index); i++) {
1208a8f0ad3cSmanu 		snprintf((char *)&buf[j], sizeof(buf) - j, "%02x", p[i]);
1209a8f0ad3cSmanu 		j += 2;
1210a8f0ad3cSmanu 		switch (i) {
1211a8f0ad3cSmanu 		case 7:
1212a8f0ad3cSmanu #if 0
1213a8f0ad3cSmanu 		case 15:
1214a8f0ad3cSmanu #endif
1215a8f0ad3cSmanu 			buf[j++] = ':';
1216a8f0ad3cSmanu 		}
1217a8f0ad3cSmanu 	}
1218a8f0ad3cSmanu 
1219a8f0ad3cSmanu 	return buf;
1220a8f0ad3cSmanu }
1221a8f0ad3cSmanu 
1222a8f0ad3cSmanu /* print schedule */
1223a8f0ad3cSmanu char *str_sched_stat[] = {
1224a8f0ad3cSmanu "off",
1225a8f0ad3cSmanu "on",
1226a8f0ad3cSmanu "dead",
1227a8f0ad3cSmanu };
1228a8f0ad3cSmanu 
1229a8f0ad3cSmanu char *str_sched_id[] = {
1230a8f0ad3cSmanu "PH1resend",
1231a8f0ad3cSmanu "PH1lifetime",
1232a8f0ad3cSmanu "PH2resend",
1233a8f0ad3cSmanu "PSTacquire",
1234a8f0ad3cSmanu "PSTlifetime",
1235a8f0ad3cSmanu };
1236a8f0ad3cSmanu 
1237a8f0ad3cSmanu void
print_schedule(buf,len)1238a8f0ad3cSmanu print_schedule(buf, len)
1239a8f0ad3cSmanu 	caddr_t buf;
1240a8f0ad3cSmanu 	int len;
1241a8f0ad3cSmanu {
1242a8f0ad3cSmanu 	struct scheddump *sc = (struct scheddump *)buf;
1243a8f0ad3cSmanu 	struct tm *tm;
1244a8f0ad3cSmanu 	char tbuf[56];
1245a8f0ad3cSmanu 
1246a8f0ad3cSmanu 	if (len % sizeof(*sc))
1247a8f0ad3cSmanu 		printf("invalid length %d\n", len);
1248a8f0ad3cSmanu 	len /= sizeof(*sc);
1249a8f0ad3cSmanu 
1250a8f0ad3cSmanu 	/*      00000000 00000000 00000000 xxx........*/
1251a8f0ad3cSmanu 	printf("index    tick     xtime    created\n");
1252a8f0ad3cSmanu 
1253a8f0ad3cSmanu 	while (len-- > 0) {
1254a8f0ad3cSmanu 		tm = localtime(&sc->created);
1255a8f0ad3cSmanu 		strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %T", tm);
1256a8f0ad3cSmanu 
1257a8f0ad3cSmanu 		printf("%-8ld %-8ld %-8ld %s\n",
1258a8f0ad3cSmanu 			sc->id,
1259a8f0ad3cSmanu 			(long)sc->tick,
1260a8f0ad3cSmanu 			(long)sc->xtime,
1261a8f0ad3cSmanu 			tbuf);
1262a8f0ad3cSmanu 		sc++;
1263a8f0ad3cSmanu 	}
1264a8f0ad3cSmanu 
1265a8f0ad3cSmanu 	return;
1266a8f0ad3cSmanu }
1267a8f0ad3cSmanu 
1268a8f0ad3cSmanu 
1269a8f0ad3cSmanu void
print_evt(evtdump)12703fd729adSmgrooms print_evt(evtdump)
12713fd729adSmgrooms 	struct evt_async *evtdump;
1272a8f0ad3cSmanu {
1273a8f0ad3cSmanu 	int i;
1274a8f0ad3cSmanu 	char *srcstr;
1275a8f0ad3cSmanu 	char *dststr;
1276a8f0ad3cSmanu 
12773fd729adSmgrooms 	for (i = 0; i < sizeof(evtmsg) / sizeof(evtmsg[0]); i++)
12783fd729adSmgrooms 		if (evtmsg[i].type == evtdump->ec_type)
1279a8f0ad3cSmanu 			break;
1280a8f0ad3cSmanu 
1281a8f0ad3cSmanu 	if (evtmsg[i].msg == NULL)
12823fd729adSmgrooms 		printf("Event %d: ", evtdump->ec_type);
1283a8f0ad3cSmanu 	else
1284a8f0ad3cSmanu 		printf("%s : ", evtmsg[i].msg);
1285a8f0ad3cSmanu 
12863fd729adSmgrooms 	if ((srcstr = saddr2str((struct sockaddr *)&evtdump->ec_ph1src)) == NULL)
1287a8f0ad3cSmanu 		printf("unknown");
1288a8f0ad3cSmanu 	else
1289a8f0ad3cSmanu 		printf("%s", srcstr);
1290a8f0ad3cSmanu 	printf(" -> ");
12913fd729adSmgrooms 	if ((dststr = saddr2str((struct sockaddr *)&evtdump->ec_ph1dst)) == NULL)
1292a8f0ad3cSmanu 		printf("unknown");
1293a8f0ad3cSmanu 	else
1294a8f0ad3cSmanu 		printf("%s", dststr);
1295a8f0ad3cSmanu 	printf("\n");
1296a8f0ad3cSmanu }
1297a8f0ad3cSmanu 
1298a8f0ad3cSmanu /*
1299a8f0ad3cSmanu  * Print ISAKMP mode config info (IP and banner)
1300a8f0ad3cSmanu  */
1301a8f0ad3cSmanu void
print_cfg(buf,len)1302a8f0ad3cSmanu print_cfg(buf, len)
1303a8f0ad3cSmanu 	caddr_t buf;
1304a8f0ad3cSmanu 	int len;
1305a8f0ad3cSmanu {
13063fd729adSmgrooms 	struct evt_async *evtdump = (struct evt_async *)buf;
1307a8f0ad3cSmanu 	struct isakmp_data *attr;
1308a8f0ad3cSmanu 	char *banner = NULL;
1309a8f0ad3cSmanu 	struct in_addr addr4;
1310a8f0ad3cSmanu 
1311a8f0ad3cSmanu 	memset(&addr4, 0, sizeof(addr4));
1312a8f0ad3cSmanu 
13133fd729adSmgrooms 	if (evtdump->ec_type != EVT_PHASE1_MODE_CFG)
1314a8f0ad3cSmanu 		return;
1315a8f0ad3cSmanu 
1316a8f0ad3cSmanu 	len -= sizeof(*evtdump);
1317a8f0ad3cSmanu 	attr = (struct isakmp_data *)(evtdump + 1);
1318a8f0ad3cSmanu 
1319a8f0ad3cSmanu 	while (len > 0) {
1320a8f0ad3cSmanu 		if (len < sizeof(*attr)) {
1321a8f0ad3cSmanu 			printf("short attribute too short\n");
1322a8f0ad3cSmanu 			break;
1323a8f0ad3cSmanu 		}
1324a8f0ad3cSmanu 
1325a8f0ad3cSmanu 		if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
1326a8f0ad3cSmanu 			/* Short attribute, skip */
1327a8f0ad3cSmanu 			len -= sizeof(*attr);
1328a8f0ad3cSmanu 			attr++;
1329a8f0ad3cSmanu 		} else { /* Long attribute */
1330a8f0ad3cSmanu 			char *n;
1331a8f0ad3cSmanu 
1332a8f0ad3cSmanu 			if (len < (sizeof(*attr) + ntohs(attr->lorv))) {
1333a8f0ad3cSmanu 				printf("long attribute too long\n");
1334a8f0ad3cSmanu 				break;
1335a8f0ad3cSmanu 			}
1336a8f0ad3cSmanu 
1337a8f0ad3cSmanu 			switch (ntohs(attr->type) & ~ISAKMP_GEN_MASK) {
1338a8f0ad3cSmanu 			case INTERNAL_IP4_ADDRESS:
1339a8f0ad3cSmanu 				if (ntohs(attr->lorv) < sizeof(addr4)) {
1340a8f0ad3cSmanu 					printf("addr4 attribute too short\n");
1341a8f0ad3cSmanu 					break;
1342a8f0ad3cSmanu 				}
1343a8f0ad3cSmanu 				memcpy(&addr4, attr + 1, sizeof(addr4));
1344a8f0ad3cSmanu 				break;
1345a8f0ad3cSmanu 
1346a8f0ad3cSmanu 			case UNITY_BANNER:
1347a8f0ad3cSmanu 				banner = racoon_malloc(ntohs(attr->lorv) + 1);
1348a8f0ad3cSmanu 				if (banner == NULL) {
1349a8f0ad3cSmanu 					printf("malloc failed\n");
1350a8f0ad3cSmanu 					break;
1351a8f0ad3cSmanu 				}
1352a8f0ad3cSmanu 				memcpy(banner, attr + 1, ntohs(attr->lorv));
1353a8f0ad3cSmanu 				banner[ntohs(attr->lorv)] = '\0';
1354a8f0ad3cSmanu 				break;
1355a8f0ad3cSmanu 
1356a8f0ad3cSmanu 			default:
1357a8f0ad3cSmanu 				break;
1358a8f0ad3cSmanu 			}
1359a8f0ad3cSmanu 
1360a8f0ad3cSmanu 			len -= (sizeof(*attr) + ntohs(attr->lorv));
1361a8f0ad3cSmanu 			n = (char *)attr;
1362a8f0ad3cSmanu 			attr = (struct isakmp_data *)
1363a8f0ad3cSmanu 			    (n + sizeof(*attr) + ntohs(attr->lorv));
1364a8f0ad3cSmanu 		}
1365a8f0ad3cSmanu 	}
1366a8f0ad3cSmanu 
13673fd729adSmgrooms 	if (len > 0)
1368a8f0ad3cSmanu 		printf("Bound to address %s\n", inet_ntoa(addr4));
1369c8214a0aSmanu 	else
1370c8214a0aSmanu 		printf("VPN connexion established\n");
1371c8214a0aSmanu 
1372a8f0ad3cSmanu 	if (banner) {
1373a8f0ad3cSmanu 		struct winsize win;
1374a8f0ad3cSmanu 		int col = 0;
1375a8f0ad3cSmanu 		int i;
1376a8f0ad3cSmanu 
1377a8f0ad3cSmanu 		if (ioctl(1, TIOCGWINSZ, &win) != 1)
1378a8f0ad3cSmanu 			col = win.ws_col;
1379a8f0ad3cSmanu 
1380a8f0ad3cSmanu 		for (i = 0; i < col; i++)
1381a8f0ad3cSmanu 			printf("%c", '=');
1382a8f0ad3cSmanu 		printf("\n%s\n", banner);
1383a8f0ad3cSmanu 		for (i = 0; i < col; i++)
1384a8f0ad3cSmanu 			printf("%c", '=');
1385a8f0ad3cSmanu 		printf("\n");
1386c8214a0aSmanu 		racoon_free(banner);
1387a8f0ad3cSmanu 	}
1388a8f0ad3cSmanu }
1389a8f0ad3cSmanu 
1390a8f0ad3cSmanu 
1391a8f0ad3cSmanu char *
fixed_addr(addr,port,len)1392a8f0ad3cSmanu fixed_addr(addr, port, len)
1393a8f0ad3cSmanu 	char *addr, *port;
1394a8f0ad3cSmanu 	int len;
1395a8f0ad3cSmanu {
1396a8f0ad3cSmanu 	static char _addr_buf_[BUFSIZ];
1397a8f0ad3cSmanu 	char *p;
1398a8f0ad3cSmanu 	int plen, i;
1399a8f0ad3cSmanu 
1400a8f0ad3cSmanu 	/* initialize */
1401a8f0ad3cSmanu 	memset(_addr_buf_, ' ', sizeof(_addr_buf_));
1402a8f0ad3cSmanu 
1403a8f0ad3cSmanu 	plen = strlen(port);
1404a8f0ad3cSmanu 	if (len < plen + 1)
1405a8f0ad3cSmanu 		return NULL;
1406a8f0ad3cSmanu 
1407a8f0ad3cSmanu 	p = _addr_buf_;
1408a8f0ad3cSmanu 	for (i = 0; i < len - plen - 1 && addr[i] != '\0'; /*noting*/)
1409a8f0ad3cSmanu 		*p++ = addr[i++];
1410a8f0ad3cSmanu 	*p++ = '.';
1411a8f0ad3cSmanu 
1412a8f0ad3cSmanu 	for (i = 0; i < plen && port[i] != '\0'; /*noting*/)
1413a8f0ad3cSmanu 		*p++ = port[i++];
1414a8f0ad3cSmanu 
1415a8f0ad3cSmanu 	_addr_buf_[len] = '\0';
1416a8f0ad3cSmanu 
1417a8f0ad3cSmanu 	return _addr_buf_;
1418a8f0ad3cSmanu }
1419a8f0ad3cSmanu 
1420a8f0ad3cSmanu static int
handle_recv(combuf)1421a8f0ad3cSmanu handle_recv(combuf)
1422a8f0ad3cSmanu 	vchar_t *combuf;
1423a8f0ad3cSmanu {
14243fd729adSmgrooms         struct admin_com *com;
1425a8f0ad3cSmanu         caddr_t buf;
1426a8f0ad3cSmanu         int len;
1427a8f0ad3cSmanu 
1428a8f0ad3cSmanu 	com = (struct admin_com *)combuf->v;
1429*731159f7Stteras 	if (com->ac_cmd & ADMIN_FLAG_LONG_REPLY)
1430*731159f7Stteras 		len = ((u_int32_t)com->ac_len) + (((u_int32_t)com->ac_len_high) << 16);
1431*731159f7Stteras 	else
1432*731159f7Stteras 		len = com->ac_len;
1433*731159f7Stteras 	len -= sizeof(*com);
1434a8f0ad3cSmanu 	buf = combuf->v + sizeof(*com);
1435a8f0ad3cSmanu 
1436*731159f7Stteras 	switch (com->ac_cmd & ~ADMIN_FLAG_LONG_REPLY) {
1437a8f0ad3cSmanu 	case ADMIN_SHOW_SCHED:
1438a8f0ad3cSmanu 		print_schedule(buf, len);
1439a8f0ad3cSmanu 		break;
1440a8f0ad3cSmanu 
1441a8f0ad3cSmanu 	case ADMIN_SHOW_EVT: {
14423fd729adSmgrooms 		struct evt_async *ec;
1443a8f0ad3cSmanu 
14443fd729adSmgrooms 		/* We got no event? */
14453fd729adSmgrooms 		if (len == 0)
1446a8f0ad3cSmanu 			break;
1447a8f0ad3cSmanu 
14483fd729adSmgrooms 		if (len < sizeof(struct evt_async))
1449a8f0ad3cSmanu 			errx(1, "Short buffer\n");
1450a8f0ad3cSmanu 
14513fd729adSmgrooms 		ec = (struct evt_async *) buf;
14523fd729adSmgrooms 		if (evt_quit_event <= 0)
14533fd729adSmgrooms 			print_evt(ec);
14543fd729adSmgrooms 		else if (evt_quit_event == ec->ec_type) {
14553fd729adSmgrooms 			switch (ec->ec_type) {
14563fd729adSmgrooms 			case EVT_PHASE1_MODE_CFG:
14573fd729adSmgrooms 				print_cfg(ec, len);
1458a8f0ad3cSmanu 				break;
14593fd729adSmgrooms 			default:
14603fd729adSmgrooms 				print_evt(ec);
14613fd729adSmgrooms 				break;
14623fd729adSmgrooms 			}
14633fd729adSmgrooms 			evt_quit_event = 0;
14643fd729adSmgrooms 		}
1465a8f0ad3cSmanu 		break;
1466a8f0ad3cSmanu 	}
1467a8f0ad3cSmanu 
146893c1205fSmgrooms 	case ADMIN_GET_SA_CERT:
146993c1205fSmgrooms 		fwrite(buf, len, 1, stdout);
147093c1205fSmgrooms 		break;
147193c1205fSmgrooms 
1472a8f0ad3cSmanu 	case ADMIN_SHOW_SA:
1473a8f0ad3cSmanu 	   {
1474a8f0ad3cSmanu 		switch (com->ac_proto) {
1475a8f0ad3cSmanu 		case ADMIN_PROTO_ISAKMP:
1476a8f0ad3cSmanu 			dump_isakmp_sa(buf, len);
1477a8f0ad3cSmanu 			break;
1478a8f0ad3cSmanu 		case ADMIN_PROTO_IPSEC:
1479a8f0ad3cSmanu 		case ADMIN_PROTO_AH:
1480a8f0ad3cSmanu 		case ADMIN_PROTO_ESP:
1481a8f0ad3cSmanu 		    {
1482a8f0ad3cSmanu 			struct sadb_msg *msg = (struct sadb_msg *)buf;
1483a8f0ad3cSmanu 
1484a8f0ad3cSmanu 			switch (msg->sadb_msg_errno) {
1485a8f0ad3cSmanu 			case ENOENT:
1486a8f0ad3cSmanu 				switch (msg->sadb_msg_type) {
1487a8f0ad3cSmanu 				case SADB_DELETE:
1488a8f0ad3cSmanu 				case SADB_GET:
1489a8f0ad3cSmanu 					printf("No entry.\n");
1490a8f0ad3cSmanu 					break;
1491a8f0ad3cSmanu 				case SADB_DUMP:
1492a8f0ad3cSmanu 					printf("No SAD entries.\n");
1493a8f0ad3cSmanu 					break;
1494a8f0ad3cSmanu 				}
1495a8f0ad3cSmanu 				break;
1496a8f0ad3cSmanu 			case 0:
1497a8f0ad3cSmanu 				while (1) {
1498a8f0ad3cSmanu 					pfkey_sadump(msg);
1499a8f0ad3cSmanu 					if (msg->sadb_msg_seq == 0)
1500a8f0ad3cSmanu 						break;
1501a8f0ad3cSmanu 					msg = (struct sadb_msg *)((caddr_t)msg +
1502a8f0ad3cSmanu 						     PFKEY_UNUNIT64(msg->sadb_msg_len));
1503a8f0ad3cSmanu 				}
1504a8f0ad3cSmanu 				break;
1505a8f0ad3cSmanu 			default:
1506a8f0ad3cSmanu 				printf("%s.\n", strerror(msg->sadb_msg_errno));
1507a8f0ad3cSmanu 			}
1508a8f0ad3cSmanu 		    }
1509a8f0ad3cSmanu 			break;
1510a8f0ad3cSmanu 		case ADMIN_PROTO_INTERNAL:
1511a8f0ad3cSmanu 			dump_internal(buf, len);
1512a8f0ad3cSmanu 			break;
1513a8f0ad3cSmanu 		default:
1514a8f0ad3cSmanu 			printf("Invalid proto [%d]\n", com->ac_proto);
1515a8f0ad3cSmanu 		}
1516a8f0ad3cSmanu 
1517a8f0ad3cSmanu 	    }
1518a8f0ad3cSmanu 		break;
1519a8f0ad3cSmanu 
1520a8f0ad3cSmanu 	default:
1521a8f0ad3cSmanu 		/* IGNORE */
1522a8f0ad3cSmanu 		break;
1523a8f0ad3cSmanu 	}
1524a8f0ad3cSmanu 
1525a8f0ad3cSmanu 	return 0;
1526a8f0ad3cSmanu 
1527a8f0ad3cSmanu bad:
1528a8f0ad3cSmanu 	return -1;
1529a8f0ad3cSmanu }
1530