admin.c revision 1.25
1/*	$NetBSD: admin.c,v 1.25 2008/08/29 00:30:15 gmcgarry Exp $	*/
2
3/* Id: admin.c,v 1.25 2006/04/06 14:31:04 manubsd Exp */
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/socket.h>
39#include <sys/signal.h>
40#include <sys/stat.h>
41#include <sys/un.h>
42
43#include <net/pfkeyv2.h>
44
45#include <netinet/in.h>
46#include PATH_IPSEC_H
47
48
49#include <stdlib.h>
50#include <stdio.h>
51#include <string.h>
52#include <errno.h>
53#include <netdb.h>
54#ifdef HAVE_UNISTD_H
55#include <unistd.h>
56#endif
57#ifdef ENABLE_HYBRID
58#include <resolv.h>
59#endif
60
61#include "var.h"
62#include "misc.h"
63#include "vmbuf.h"
64#include "plog.h"
65#include "sockmisc.h"
66#include "debug.h"
67
68#include "schedule.h"
69#include "localconf.h"
70#include "remoteconf.h"
71#include "grabmyaddr.h"
72#include "isakmp_var.h"
73#include "isakmp.h"
74#include "oakley.h"
75#include "handler.h"
76#include "evt.h"
77#include "pfkey.h"
78#include "ipsec_doi.h"
79#include "policy.h"
80#include "admin.h"
81#include "admin_var.h"
82#include "isakmp_inf.h"
83#ifdef ENABLE_HYBRID
84#include "isakmp_cfg.h"
85#endif
86#include "session.h"
87#include "gcmalloc.h"
88
89#ifdef ENABLE_ADMINPORT
90char *adminsock_path = ADMINSOCK_PATH;
91uid_t adminsock_owner = 0;
92gid_t adminsock_group = 0;
93mode_t adminsock_mode = 0600;
94
95static struct sockaddr_un sunaddr;
96static int admin_process __P((int, char *));
97static int admin_reply __P((int, struct admin_com *, int, vchar_t *));
98
99int
100admin_handler()
101{
102	int so2;
103	struct sockaddr_storage from;
104	socklen_t fromlen = sizeof(from);
105	struct admin_com com;
106	char *combuf = NULL;
107	int len, error = -1;
108
109	so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
110	if (so2 < 0) {
111		plog(LLV_ERROR, LOCATION, NULL,
112			"failed to accept admin command: %s\n",
113			strerror(errno));
114		return -1;
115	}
116	close_on_exec(so2);
117
118	/* get buffer length */
119	while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
120		if (errno == EINTR)
121			continue;
122		plog(LLV_ERROR, LOCATION, NULL,
123			"failed to recv admin command: %s\n",
124			strerror(errno));
125		goto end;
126	}
127
128	/* sanity check */
129	if (len < sizeof(com)) {
130		plog(LLV_ERROR, LOCATION, NULL,
131			"invalid header length of admin command\n");
132		goto end;
133	}
134
135	/* get buffer to receive */
136	if ((combuf = racoon_malloc(com.ac_len)) == 0) {
137		plog(LLV_ERROR, LOCATION, NULL,
138			"failed to alloc buffer for admin command\n");
139		goto end;
140	}
141
142	/* get real data */
143	while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
144		if (errno == EINTR)
145			continue;
146		plog(LLV_ERROR, LOCATION, NULL,
147			"failed to recv admin command: %s\n",
148			strerror(errno));
149		goto end;
150	}
151
152	error = admin_process(so2, combuf);
153
154end:
155	if (error == -2) {
156		plog(LLV_DEBUG, LOCATION, NULL,
157			"[%d] admin connection established\n", so2);
158	} else {
159		(void)close(so2);
160	}
161
162	if (combuf)
163		racoon_free(combuf);
164
165	return error;
166}
167
168/*
169 * main child's process.
170 */
171static int
172admin_process(so2, combuf)
173	int so2;
174	char *combuf;
175{
176	struct admin_com *com = (struct admin_com *)combuf;
177	vchar_t *buf = NULL;
178	vchar_t *id = NULL;
179	vchar_t *key = NULL;
180	int idtype = 0;
181	int error = 0, l_ac_errno = 0;
182	struct evt_listener_list *event_list = NULL;
183
184	if (com->ac_cmd & ADMIN_FLAG_VERSION)
185		com->ac_cmd &= ~ADMIN_FLAG_VERSION;
186	else
187		com->ac_version = 0;
188
189	switch (com->ac_cmd) {
190	case ADMIN_RELOAD_CONF:
191		signal_handler(SIGHUP);
192		break;
193
194	case ADMIN_SHOW_SCHED: {
195		caddr_t p = NULL;
196		int len;
197
198		if (sched_dump(&p, &len) != -1) {
199			buf = vmalloc(len);
200			if (buf != NULL)
201				memcpy(buf->v, p, len);
202			else
203				l_ac_errno = ENOMEM;
204			racoon_free(p);
205		} else
206			l_ac_errno = ENOMEM;
207		break;
208	}
209
210	case ADMIN_SHOW_EVT:
211		if (com->ac_version == 0) {
212			buf = evt_dump();
213			l_ac_errno = 0;
214		}
215		break;
216
217	case ADMIN_SHOW_SA:
218		switch (com->ac_proto) {
219		case ADMIN_PROTO_ISAKMP:
220			buf = dumpph1();
221			if (buf == NULL)
222				l_ac_errno = ENOMEM;
223			break;
224		case ADMIN_PROTO_IPSEC:
225		case ADMIN_PROTO_AH:
226		case ADMIN_PROTO_ESP: {
227			u_int p;
228			p = admin2pfkey_proto(com->ac_proto);
229			if (p != -1) {
230				buf = pfkey_dump_sadb(p);
231				if (buf == NULL)
232					l_ac_errno = ENOMEM;
233			} else
234				l_ac_errno = EINVAL;
235			break;
236		}
237		case ADMIN_PROTO_INTERNAL:
238		default:
239			l_ac_errno = ENOTSUP;
240			break;
241		}
242		break;
243
244	case ADMIN_GET_SA_CERT: {
245		struct admin_com_indexes *ndx;
246		struct sockaddr *src, *dst;
247		struct ph1handle *iph1;
248
249		ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
250		src = (struct sockaddr *) &ndx->src;
251		dst = (struct sockaddr *) &ndx->dst;
252
253		if (com->ac_proto != ADMIN_PROTO_ISAKMP) {
254			l_ac_errno = ENOTSUP;
255			break;
256		}
257
258		iph1 = getph1byaddrwop(src, dst);
259		if (iph1 == NULL) {
260			l_ac_errno = ENOENT;
261			break;
262		}
263
264		if (iph1->cert_p != NULL)
265			buf = vdup(&iph1->cert_p->cert);
266		break;
267	}
268
269	case ADMIN_FLUSH_SA:
270		switch (com->ac_proto) {
271		case ADMIN_PROTO_ISAKMP:
272			flushph1();
273			break;
274		case ADMIN_PROTO_IPSEC:
275		case ADMIN_PROTO_AH:
276		case ADMIN_PROTO_ESP:
277			pfkey_flush_sadb(com->ac_proto);
278			break;
279		case ADMIN_PROTO_INTERNAL:
280			/*XXX flushph2();*/
281		default:
282			l_ac_errno = ENOTSUP;
283			break;
284		}
285		break;
286
287	case ADMIN_DELETE_SA: {
288		struct ph1handle *iph1;
289		struct sockaddr *dst;
290		struct sockaddr *src;
291		char *loc, *rem;
292
293		src = (struct sockaddr *)
294			&((struct admin_com_indexes *)
295			    ((caddr_t)com + sizeof(*com)))->src;
296		dst = (struct sockaddr *)
297			&((struct admin_com_indexes *)
298			    ((caddr_t)com + sizeof(*com)))->dst;
299
300		loc = racoon_strdup(saddrwop2str(src));
301		rem = racoon_strdup(saddrwop2str(dst));
302		STRDUP_FATAL(loc);
303		STRDUP_FATAL(rem);
304
305		if ((iph1 = getph1byaddrwop(src, dst)) == NULL) {
306			plog(LLV_ERROR, LOCATION, NULL,
307			    "phase 1 for %s -> %s not found\n", loc, rem);
308		} else {
309			if (iph1->status == PHASE1ST_ESTABLISHED)
310				isakmp_info_send_d1(iph1);
311			purge_remote(iph1);
312		}
313
314		racoon_free(loc);
315		racoon_free(rem);
316		break;
317	}
318
319#ifdef ENABLE_HYBRID
320	case ADMIN_LOGOUT_USER: {
321		struct ph1handle *iph1;
322		char *user;
323		int found = 0;
324
325		if (com->ac_len > sizeof(com) + LOGINLEN + 1) {
326			plog(LLV_ERROR, LOCATION, NULL,
327			    "malformed message (login too long)\n");
328			break;
329		}
330
331		user = (char *)(com + 1);
332		found = purgeph1bylogin(user);
333		plog(LLV_INFO, LOCATION, NULL,
334		    "deleted %d SA for user \"%s\"\n", found, user);
335
336		break;
337	}
338#endif
339
340	case ADMIN_DELETE_ALL_SA_DST: {
341		struct ph1handle *iph1;
342		struct sockaddr *dst;
343		char *loc, *rem;
344
345		dst = (struct sockaddr *)
346			&((struct admin_com_indexes *)
347			    ((caddr_t)com + sizeof(*com)))->dst;
348
349		rem = racoon_strdup(saddrwop2str(dst));
350		STRDUP_FATAL(rem);
351
352		plog(LLV_INFO, LOCATION, NULL,
353		    "Flushing all SAs for peer %s\n", rem);
354
355		while ((iph1 = getph1bydstaddrwop(dst)) != NULL) {
356			loc = racoon_strdup(saddrwop2str(iph1->local));
357			STRDUP_FATAL(loc);
358
359			if (iph1->status == PHASE1ST_ESTABLISHED)
360				isakmp_info_send_d1(iph1);
361			purge_remote(iph1);
362
363			racoon_free(loc);
364		}
365
366		racoon_free(rem);
367		break;
368	}
369
370	case ADMIN_ESTABLISH_SA_PSK: {
371		struct admin_com_psk *acp;
372		char *data;
373
374		acp = (struct admin_com_psk *)
375		    ((char *)com + sizeof(*com) +
376		    sizeof(struct admin_com_indexes));
377
378		idtype = acp->id_type;
379
380		if ((id = vmalloc(acp->id_len)) == NULL) {
381			plog(LLV_ERROR, LOCATION, NULL,
382			    "cannot allocate memory: %s\n",
383			    strerror(errno));
384			break;
385		}
386		data = (char *)(acp + 1);
387		memcpy(id->v, data, id->l);
388
389		if ((key = vmalloc(acp->key_len)) == NULL) {
390			plog(LLV_ERROR, LOCATION, NULL,
391			    "cannot allocate memory: %s\n",
392			    strerror(errno));
393			vfree(id);
394			id = NULL;
395			break;
396		}
397		data = (char *)(data + acp->id_len);
398		memcpy(key->v, data, key->l);
399	}
400	/* FALLTHROUGH */
401	case ADMIN_ESTABLISH_SA: {
402		struct admin_com_indexes *ndx;
403		struct sockaddr *dst;
404		struct sockaddr *src;
405
406		ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
407		src = (struct sockaddr *) &ndx->src;
408		dst = (struct sockaddr *) &ndx->dst;
409
410		switch (com->ac_proto) {
411		case ADMIN_PROTO_ISAKMP: {
412			struct ph1handle *ph1;
413			struct remoteconf *rmconf;
414			struct sockaddr *remote = NULL;
415			struct sockaddr *local = NULL;
416			u_int16_t port;
417
418			l_ac_errno = -1;
419
420			/* connected already? */
421			ph1 = getph1byaddrwop(src, dst);
422			if (ph1 != NULL) {
423				event_list = &ph1->evt_listeners;
424				if (ph1->status == PHASE1ST_ESTABLISHED)
425					l_ac_errno = EEXIST;
426				else
427					l_ac_errno = 0;
428				break;
429			}
430
431			/* search appropreate configuration */
432			rmconf = getrmconf(dst);
433			if (rmconf == NULL) {
434				plog(LLV_ERROR, LOCATION, NULL,
435					"no configuration found "
436					"for %s\n", saddrwop2str(dst));
437				goto out1;
438			}
439
440			/* get remote IP address and port number. */
441			if ((remote = dupsaddr(dst)) == NULL)
442				goto out1;
443
444			port = extract_port(rmconf->remote);
445			if (set_port(remote, port) == NULL)
446				goto out1;
447
448			/* get local address */
449			if ((local = dupsaddr(src)) == NULL)
450				goto out1;
451
452			port = getmyaddrsport(local);
453			if (set_port(local, port) == NULL)
454				goto out1;
455
456#ifdef ENABLE_HYBRID
457			/* Set the id and key */
458			if (id && key) {
459				if (xauth_rmconf_used(&rmconf->xauth) == -1)
460					goto out1;
461
462				if (rmconf->xauth->login != NULL) {
463					vfree(rmconf->xauth->login);
464					rmconf->xauth->login = NULL;
465				}
466				if (rmconf->xauth->pass != NULL) {
467					vfree(rmconf->xauth->pass);
468					rmconf->xauth->pass = NULL;
469				}
470
471				rmconf->xauth->login = id;
472				rmconf->xauth->pass = key;
473			}
474#endif
475
476			plog(LLV_INFO, LOCATION, NULL,
477				"accept a request to establish IKE-SA: "
478				"%s\n", saddrwop2str(remote));
479
480			/* begin ident mode */
481			ph1 = isakmp_ph1begin_i(rmconf, remote, local);
482			if (ph1 == NULL)
483				goto out1;
484
485			event_list = &ph1->evt_listeners;
486			l_ac_errno = 0;
487out1:
488			if (local != NULL)
489				racoon_free(local);
490			if (remote != NULL)
491				racoon_free(remote);
492			break;
493		}
494		case ADMIN_PROTO_AH:
495		case ADMIN_PROTO_ESP: {
496			struct ph2handle *iph2;
497			struct secpolicy *sp_out = NULL, *sp_in = NULL;
498			struct policyindex spidx;
499
500			l_ac_errno = -1;
501
502			/* got outbound policy */
503			memset(&spidx, 0, sizeof(spidx));
504			spidx.dir = IPSEC_DIR_OUTBOUND;
505			memcpy(&spidx.src, src, sizeof(spidx.src));
506			memcpy(&spidx.dst, dst, sizeof(spidx.dst));
507			spidx.prefs = ndx->prefs;
508			spidx.prefd = ndx->prefd;
509			spidx.ul_proto = ndx->ul_proto;
510
511			sp_out = getsp_r(&spidx);
512			if (sp_out) {
513				plog(LLV_DEBUG, LOCATION, NULL,
514					"suitable outbound SP found: %s.\n",
515					spidx2str(&sp_out->spidx));
516			} else {
517				l_ac_errno = ENOENT;
518				plog(LLV_NOTIFY, LOCATION, NULL,
519					"no outbound policy found: %s\n",
520					spidx2str(&spidx));
521				break;
522			}
523
524			iph2 = getph2byid(src, dst, sp_out->id);
525			if (iph2 != NULL) {
526				event_list = &iph2->evt_listeners;
527				if (iph2->status == PHASE2ST_ESTABLISHED)
528					l_ac_errno = EEXIST;
529				else
530					l_ac_errno = 0;
531				break;
532			}
533
534			/* get inbound policy */
535			memset(&spidx, 0, sizeof(spidx));
536			spidx.dir = IPSEC_DIR_INBOUND;
537			memcpy(&spidx.src, dst, sizeof(spidx.src));
538			memcpy(&spidx.dst, src, sizeof(spidx.dst));
539			spidx.prefs = ndx->prefd;
540			spidx.prefd = ndx->prefs;
541			spidx.ul_proto = ndx->ul_proto;
542
543			sp_in = getsp_r(&spidx);
544			if (sp_in) {
545				plog(LLV_DEBUG, LOCATION, NULL,
546					"suitable inbound SP found: %s.\n",
547					spidx2str(&sp_in->spidx));
548			} else {
549				l_ac_errno = ENOENT;
550				plog(LLV_NOTIFY, LOCATION, NULL,
551					"no inbound policy found: %s\n",
552				spidx2str(&spidx));
553				break;
554			}
555
556			/* allocate a phase 2 */
557			iph2 = newph2();
558			if (iph2 == NULL) {
559				plog(LLV_ERROR, LOCATION, NULL,
560					"failed to allocate phase2 entry.\n");
561				break;
562			}
563			iph2->side = INITIATOR;
564			iph2->satype = admin2pfkey_proto(com->ac_proto);
565			iph2->spid = sp_out->id;
566			iph2->seq = pk_getseq();
567			iph2->status = PHASE2ST_STATUS2;
568
569			/* set end addresses of SA */
570			iph2->dst = dupsaddr(dst);
571			iph2->src = dupsaddr(src);
572			if (iph2->dst == NULL || iph2->src == NULL) {
573				delph2(iph2);
574				break;
575			}
576
577			if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
578				delph2(iph2);
579				break;
580			}
581
582			insph2(iph2);
583			if (isakmp_post_acquire(iph2) < 0) {
584				unbindph12(iph2);
585				remph2(iph2);
586				delph2(iph2);
587				break;
588			}
589
590			event_list = &iph2->evt_listeners;
591			l_ac_errno = 0;
592			break;
593		}
594		default:
595			/* ignore */
596			l_ac_errno = ENOTSUP;
597		}
598		break;
599	}
600
601	default:
602		plog(LLV_ERROR, LOCATION, NULL,
603			"invalid command: %d\n", com->ac_cmd);
604		l_ac_errno = ENOTSUP;
605	}
606
607	if ((error = admin_reply(so2, com, l_ac_errno, buf)) != 0)
608		goto out;
609
610	/* start pushing events if so requested */
611	if ((l_ac_errno == 0) &&
612	    (com->ac_version >= 1) &&
613	    (com->ac_cmd == ADMIN_SHOW_EVT || event_list != NULL))
614		error = evt_subscribe(event_list, so2);
615out:
616	if (buf != NULL)
617		vfree(buf);
618
619	return error;
620}
621
622static int
623admin_reply(so, req, l_ac_errno, buf)
624	int so, l_ac_errno;
625	struct admin_com *req;
626	vchar_t *buf;
627{
628	int tlen;
629	struct admin_com *combuf;
630	char *retbuf = NULL;
631
632	if (buf != NULL)
633		tlen = sizeof(*combuf) + buf->l;
634	else
635		tlen = sizeof(*combuf);
636
637	retbuf = racoon_calloc(1, tlen);
638	if (retbuf == NULL) {
639		plog(LLV_ERROR, LOCATION, NULL,
640			"failed to allocate admin buffer\n");
641		return -1;
642	}
643
644	combuf = (struct admin_com *) retbuf;
645	combuf->ac_len = tlen;
646	combuf->ac_cmd = req->ac_cmd & ~ADMIN_FLAG_VERSION;
647	combuf->ac_errno = l_ac_errno;
648	combuf->ac_proto = req->ac_proto;
649
650	if (buf != NULL)
651		memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
652
653	tlen = send(so, retbuf, tlen, 0);
654	racoon_free(retbuf);
655	if (tlen < 0) {
656		plog(LLV_ERROR, LOCATION, NULL,
657			"failed to send admin command: %s\n",
658			strerror(errno));
659		return -1;
660	}
661
662	return 0;
663}
664
665/* ADMIN_PROTO -> SADB_SATYPE */
666int
667admin2pfkey_proto(proto)
668	u_int proto;
669{
670	switch (proto) {
671	case ADMIN_PROTO_IPSEC:
672		return SADB_SATYPE_UNSPEC;
673	case ADMIN_PROTO_AH:
674		return SADB_SATYPE_AH;
675	case ADMIN_PROTO_ESP:
676		return SADB_SATYPE_ESP;
677	default:
678		plog(LLV_ERROR, LOCATION, NULL,
679			"unsupported proto for admin: %d\n", proto);
680		return -1;
681	}
682	/*NOTREACHED*/
683}
684
685int
686admin_init()
687{
688	if (adminsock_path == NULL) {
689		lcconf->sock_admin = -1;
690		return 0;
691	}
692
693	memset(&sunaddr, 0, sizeof(sunaddr));
694	sunaddr.sun_family = AF_UNIX;
695	snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
696		"%s", adminsock_path);
697
698	lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
699	if (lcconf->sock_admin == -1) {
700		plog(LLV_ERROR, LOCATION, NULL,
701			"socket: %s\n", strerror(errno));
702		return -1;
703	}
704	close_on_exec(lcconf->sock_admin);
705
706	unlink(sunaddr.sun_path);
707	if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
708			sizeof(sunaddr)) != 0) {
709		plog(LLV_ERROR, LOCATION, NULL,
710			"bind(sockname:%s): %s\n",
711			sunaddr.sun_path, strerror(errno));
712		(void)close(lcconf->sock_admin);
713		return -1;
714	}
715
716	if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
717		plog(LLV_ERROR, LOCATION, NULL,
718		    "chown(%s, %d, %d): %s\n",
719		    sunaddr.sun_path, adminsock_owner,
720		    adminsock_group, strerror(errno));
721		(void)close(lcconf->sock_admin);
722		return -1;
723	}
724
725	if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
726		plog(LLV_ERROR, LOCATION, NULL,
727		    "chmod(%s, 0%03o): %s\n",
728		    sunaddr.sun_path, adminsock_mode, strerror(errno));
729		(void)close(lcconf->sock_admin);
730		return -1;
731	}
732
733	if (listen(lcconf->sock_admin, 5) != 0) {
734		plog(LLV_ERROR, LOCATION, NULL,
735			"listen(sockname:%s): %s\n",
736			sunaddr.sun_path, strerror(errno));
737		(void)close(lcconf->sock_admin);
738		return -1;
739	}
740	plog(LLV_DEBUG, LOCATION, NULL,
741		"open %s as racoon management.\n", sunaddr.sun_path);
742
743	return 0;
744}
745
746int
747admin_close()
748{
749	close(lcconf->sock_admin);
750	return 0;
751}
752#endif
753
754