Annotation of embedaddon/ipsec-tools/src/racoon/admin.c, revision 1.1.1.2
1.1.1.2 ! misho 1: /* $NetBSD: admin.c,v 1.38.4.1 2013/06/03 05:49:59 tteras Exp $ */
1.1 misho 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
90: char *adminsock_path = ADMINSOCK_PATH;
91: uid_t adminsock_owner = 0;
92: gid_t adminsock_group = 0;
93: mode_t adminsock_mode = 0600;
94:
95: static struct sockaddr_un sunaddr;
96: static int admin_process __P((int, char *));
97: static int admin_reply __P((int, struct admin_com *, int, vchar_t *));
98:
99: static int
100: admin_handler(ctx, fd)
101: void *ctx;
102: int fd;
103: {
104: int so2;
105: struct sockaddr_storage from;
106: socklen_t fromlen = sizeof(from);
107: struct admin_com com;
108: char *combuf = NULL;
109: int len, error = -1;
110:
111: so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
112: if (so2 < 0) {
113: plog(LLV_ERROR, LOCATION, NULL,
114: "failed to accept admin command: %s\n",
115: strerror(errno));
116: return -1;
117: }
118: close_on_exec(so2);
119:
120: /* get buffer length */
121: while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
122: if (errno == EINTR)
123: continue;
124: plog(LLV_ERROR, LOCATION, NULL,
125: "failed to recv admin command: %s\n",
126: strerror(errno));
127: goto end;
128: }
129:
130: /* sanity check */
131: if (len < sizeof(com)) {
132: plog(LLV_ERROR, LOCATION, NULL,
133: "invalid header length of admin command\n");
134: goto end;
135: }
136:
137: /* get buffer to receive */
138: if ((combuf = racoon_malloc(com.ac_len)) == 0) {
139: plog(LLV_ERROR, LOCATION, NULL,
140: "failed to alloc buffer for admin command\n");
141: goto end;
142: }
143:
144: /* get real data */
145: while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
146: if (errno == EINTR)
147: continue;
148: plog(LLV_ERROR, LOCATION, NULL,
149: "failed to recv admin command: %s\n",
150: strerror(errno));
151: goto end;
152: }
153:
154: error = admin_process(so2, combuf);
155:
156: end:
157: if (error == -2) {
158: plog(LLV_DEBUG, LOCATION, NULL,
159: "[%d] admin connection established\n", so2);
160: } else {
161: (void)close(so2);
162: }
163:
164: if (combuf)
165: racoon_free(combuf);
166:
167: return error;
168: }
169:
170: static int admin_ph1_delete_sa(struct ph1handle *iph1, void *arg)
171: {
172: if (iph1->status >= PHASE1ST_ESTABLISHED)
173: isakmp_info_send_d1(iph1);
174: purge_remote(iph1);
175: return 0;
176: }
177:
178: /*
179: * main child's process.
180: */
181: static int
182: admin_process(so2, combuf)
183: int so2;
184: char *combuf;
185: {
186: struct admin_com *com = (struct admin_com *)combuf;
187: vchar_t *buf = NULL;
188: vchar_t *id = NULL;
189: vchar_t *key = NULL;
190: int idtype = 0;
191: int error = 0, l_ac_errno = 0;
192: struct evt_listener_list *event_list = NULL;
193:
194: if (com->ac_cmd & ADMIN_FLAG_VERSION)
195: com->ac_cmd &= ~ADMIN_FLAG_VERSION;
196: else
197: com->ac_version = 0;
198:
199: switch (com->ac_cmd) {
200: case ADMIN_RELOAD_CONF:
201: signal_handler(SIGHUP);
202: break;
203:
204: case ADMIN_SHOW_SCHED: {
205: caddr_t p = NULL;
206: int len;
207:
208: if (sched_dump(&p, &len) != -1) {
209: buf = vmalloc(len);
210: if (buf != NULL)
211: memcpy(buf->v, p, len);
212: else
213: l_ac_errno = ENOMEM;
214: racoon_free(p);
215: } else
216: l_ac_errno = ENOMEM;
217: break;
218: }
219:
220: case ADMIN_SHOW_EVT:
221: if (com->ac_version == 0) {
222: buf = evt_dump();
223: l_ac_errno = 0;
224: }
225: break;
226:
227: case ADMIN_SHOW_SA:
228: switch (com->ac_proto) {
229: case ADMIN_PROTO_ISAKMP:
230: buf = dumpph1();
231: if (buf == NULL)
232: l_ac_errno = ENOMEM;
233: break;
234: case ADMIN_PROTO_IPSEC:
235: case ADMIN_PROTO_AH:
236: case ADMIN_PROTO_ESP: {
237: u_int p;
238: p = admin2pfkey_proto(com->ac_proto);
239: if (p != -1) {
240: buf = pfkey_dump_sadb(p);
241: if (buf == NULL)
242: l_ac_errno = ENOMEM;
243: } else
244: l_ac_errno = EINVAL;
245: break;
246: }
247: case ADMIN_PROTO_INTERNAL:
248: default:
249: l_ac_errno = ENOTSUP;
250: break;
251: }
252: break;
253:
254: case ADMIN_GET_SA_CERT: {
255: struct admin_com_indexes *ndx;
256: struct sockaddr *src, *dst;
257: struct ph1handle *iph1;
258:
259: ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
260: src = (struct sockaddr *) &ndx->src;
261: dst = (struct sockaddr *) &ndx->dst;
262:
263: if (com->ac_proto != ADMIN_PROTO_ISAKMP) {
264: l_ac_errno = ENOTSUP;
265: break;
266: }
267:
268: iph1 = getph1byaddr(src, dst, 0);
269: if (iph1 == NULL) {
270: l_ac_errno = ENOENT;
271: break;
272: }
273:
274: if (iph1->cert_p != NULL) {
275: vchar_t tmp;
276: tmp.v = iph1->cert_p->v + 1;
277: tmp.l = iph1->cert_p->l - 1;
278: buf = vdup(&tmp);
279: }
280: break;
281: }
282:
283: case ADMIN_FLUSH_SA:
284: switch (com->ac_proto) {
285: case ADMIN_PROTO_ISAKMP:
286: flushph1();
287: break;
288: case ADMIN_PROTO_IPSEC:
289: case ADMIN_PROTO_AH:
290: case ADMIN_PROTO_ESP:
291: pfkey_flush_sadb(com->ac_proto);
292: break;
293: case ADMIN_PROTO_INTERNAL:
294: /*XXX flushph2();*/
295: default:
296: l_ac_errno = ENOTSUP;
297: break;
298: }
299: break;
300:
301: case ADMIN_DELETE_SA: {
302: char *loc, *rem;
303: struct ph1selector sel;
304:
305: memset(&sel, 0, sizeof(sel));
306: sel.local = (struct sockaddr *)
307: &((struct admin_com_indexes *)
308: ((caddr_t)com + sizeof(*com)))->src;
309: sel.remote = (struct sockaddr *)
310: &((struct admin_com_indexes *)
311: ((caddr_t)com + sizeof(*com)))->dst;
312:
313: loc = racoon_strdup(saddr2str(sel.local));
314: rem = racoon_strdup(saddr2str(sel.remote));
315: STRDUP_FATAL(loc);
316: STRDUP_FATAL(rem);
317:
318: plog(LLV_INFO, LOCATION, NULL,
319: "admin delete-sa %s %s\n", loc, rem);
320: enumph1(&sel, admin_ph1_delete_sa, NULL);
321: remcontacted(sel.remote);
322:
323: racoon_free(loc);
324: racoon_free(rem);
325: break;
326: }
327:
328: #ifdef ENABLE_HYBRID
329: case ADMIN_LOGOUT_USER: {
330: struct ph1handle *iph1;
331: char user[LOGINLEN+1];
332: int found = 0, len = com->ac_len - sizeof(*com);
333:
334: if (len > LOGINLEN) {
335: plog(LLV_ERROR, LOCATION, NULL,
336: "malformed message (login too long)\n");
337: break;
338: }
339:
340: memcpy(user, (char *)(com + 1), len);
341: user[len] = 0;
342:
343: found = purgeph1bylogin(user);
344: plog(LLV_INFO, LOCATION, NULL,
345: "deleted %d SA for user \"%s\"\n", found, user);
346:
347: break;
348: }
349: #endif
350:
351: case ADMIN_DELETE_ALL_SA_DST: {
352: struct ph1handle *iph1;
353: struct sockaddr *dst;
354: char *loc, *rem;
355:
356: dst = (struct sockaddr *)
357: &((struct admin_com_indexes *)
358: ((caddr_t)com + sizeof(*com)))->dst;
359:
360: rem = racoon_strdup(saddrwop2str(dst));
361: STRDUP_FATAL(rem);
362:
363: plog(LLV_INFO, LOCATION, NULL,
364: "Flushing all SAs for peer %s\n", rem);
365:
366: while ((iph1 = getph1bydstaddr(dst)) != NULL) {
367: loc = racoon_strdup(saddrwop2str(iph1->local));
368: STRDUP_FATAL(loc);
369:
370: if (iph1->status >= PHASE1ST_ESTABLISHED)
371: isakmp_info_send_d1(iph1);
372: purge_remote(iph1);
373:
374: racoon_free(loc);
375: }
376:
377: racoon_free(rem);
378: break;
379: }
380:
381: case ADMIN_ESTABLISH_SA_PSK: {
382: struct admin_com_psk *acp;
383: char *data;
384:
385: acp = (struct admin_com_psk *)
386: ((char *)com + sizeof(*com) +
387: sizeof(struct admin_com_indexes));
388:
389: idtype = acp->id_type;
390:
391: if ((id = vmalloc(acp->id_len)) == NULL) {
392: plog(LLV_ERROR, LOCATION, NULL,
393: "cannot allocate memory: %s\n",
394: strerror(errno));
395: break;
396: }
397: data = (char *)(acp + 1);
398: memcpy(id->v, data, id->l);
399:
400: if ((key = vmalloc(acp->key_len)) == NULL) {
401: plog(LLV_ERROR, LOCATION, NULL,
402: "cannot allocate memory: %s\n",
403: strerror(errno));
404: vfree(id);
405: id = NULL;
406: break;
407: }
408: data = (char *)(data + acp->id_len);
409: memcpy(key->v, data, key->l);
410: }
411: /* FALLTHROUGH */
412: case ADMIN_ESTABLISH_SA: {
413: struct admin_com_indexes *ndx;
414: struct sockaddr *dst;
415: struct sockaddr *src;
416: char *name = NULL;
417:
418: ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
419: src = (struct sockaddr *) &ndx->src;
420: dst = (struct sockaddr *) &ndx->dst;
421:
422: if (com->ac_cmd == ADMIN_ESTABLISH_SA &&
423: com->ac_len > sizeof(*com) + sizeof(*ndx))
424: name = (char *) ((caddr_t) ndx + sizeof(*ndx));
425:
426: switch (com->ac_proto) {
427: case ADMIN_PROTO_ISAKMP: {
428: struct ph1handle *ph1;
429: struct remoteconf *rmconf;
430: u_int16_t port;
431:
432: l_ac_errno = -1;
433:
434: /* connected already? */
435: ph1 = getph1byaddr(src, dst, 0);
436: if (ph1 != NULL) {
437: event_list = &ph1->evt_listeners;
438: if (ph1->status == PHASE1ST_ESTABLISHED)
439: l_ac_errno = EEXIST;
440: else
441: l_ac_errno = 0;
442: break;
443: }
444:
445: /* search appropreate configuration */
446: if (name == NULL)
447: rmconf = getrmconf(dst, 0);
448: else
449: rmconf = getrmconf_by_name(name);
450: if (rmconf == NULL) {
451: plog(LLV_ERROR, LOCATION, NULL,
452: "no configuration found "
453: "for %s\n", saddrwop2str(dst));
454: break;
455: }
456:
457: #ifdef ENABLE_HYBRID
458: /* XXX This overwrites rmconf information globally. */
459: /* Set the id and key */
460: if (id && key) {
461: if (xauth_rmconf_used(&rmconf->xauth) == -1)
462: break;
463:
464: if (rmconf->xauth->login != NULL) {
465: vfree(rmconf->xauth->login);
466: rmconf->xauth->login = NULL;
467: }
468: if (rmconf->xauth->pass != NULL) {
469: vfree(rmconf->xauth->pass);
470: rmconf->xauth->pass = NULL;
471: }
472:
473: rmconf->xauth->login = id;
474: rmconf->xauth->pass = key;
475: }
476: #endif
477:
478: plog(LLV_INFO, LOCATION, NULL,
479: "accept a request to establish IKE-SA: "
480: "%s\n", saddrwop2str(dst));
481:
482: /* begin ident mode */
483: ph1 = isakmp_ph1begin_i(rmconf, dst, src);
484: if (ph1 == NULL)
485: break;
486:
487: event_list = &ph1->evt_listeners;
488: l_ac_errno = 0;
489: break;
490: }
491: case ADMIN_PROTO_AH:
492: case ADMIN_PROTO_ESP: {
493: struct ph2handle *iph2;
494: struct secpolicy *sp_out = NULL, *sp_in = NULL;
495: struct policyindex spidx;
496:
497: l_ac_errno = -1;
498:
499: /* got outbound policy */
500: memset(&spidx, 0, sizeof(spidx));
501: spidx.dir = IPSEC_DIR_OUTBOUND;
502: memcpy(&spidx.src, src, sizeof(spidx.src));
503: memcpy(&spidx.dst, dst, sizeof(spidx.dst));
504: spidx.prefs = ndx->prefs;
505: spidx.prefd = ndx->prefd;
506: spidx.ul_proto = ndx->ul_proto;
507:
508: sp_out = getsp_r(&spidx);
509: if (sp_out) {
510: plog(LLV_DEBUG, LOCATION, NULL,
511: "suitable outbound SP found: %s.\n",
512: spidx2str(&sp_out->spidx));
513: } else {
514: l_ac_errno = ENOENT;
515: plog(LLV_NOTIFY, LOCATION, NULL,
516: "no outbound policy found: %s\n",
517: spidx2str(&spidx));
518: break;
519: }
520:
521: iph2 = getph2byid(src, dst, sp_out->id);
522: if (iph2 != NULL) {
523: event_list = &iph2->evt_listeners;
524: if (iph2->status == PHASE2ST_ESTABLISHED)
525: l_ac_errno = EEXIST;
526: else
527: l_ac_errno = 0;
528: break;
529: }
530:
531: /* get inbound policy */
532: memset(&spidx, 0, sizeof(spidx));
533: spidx.dir = IPSEC_DIR_INBOUND;
534: memcpy(&spidx.src, dst, sizeof(spidx.src));
535: memcpy(&spidx.dst, src, sizeof(spidx.dst));
536: spidx.prefs = ndx->prefd;
537: spidx.prefd = ndx->prefs;
538: spidx.ul_proto = ndx->ul_proto;
539:
540: sp_in = getsp_r(&spidx);
541: if (sp_in) {
542: plog(LLV_DEBUG, LOCATION, NULL,
543: "suitable inbound SP found: %s.\n",
544: spidx2str(&sp_in->spidx));
545: } else {
546: l_ac_errno = ENOENT;
547: plog(LLV_NOTIFY, LOCATION, NULL,
548: "no inbound policy found: %s\n",
549: spidx2str(&spidx));
550: break;
551: }
552:
553: /* allocate a phase 2 */
554: iph2 = newph2();
555: if (iph2 == NULL) {
556: plog(LLV_ERROR, LOCATION, NULL,
557: "failed to allocate phase2 entry.\n");
558: break;
559: }
560: iph2->side = INITIATOR;
561: iph2->satype = admin2pfkey_proto(com->ac_proto);
562: iph2->spid = sp_out->id;
563: iph2->seq = pk_getseq();
564: iph2->status = PHASE2ST_STATUS2;
565:
1.1.1.2 ! misho 566: if (sp_out->local && sp_out->remote) {
! 567: /* hints available, let's use them */
! 568: iph2->sa_dst = dupsaddr(dst);
! 569: iph2->sa_src = dupsaddr(src);
! 570: iph2->src = dupsaddr((struct sockaddr *)sp_out->local);
! 571: iph2->dst = dupsaddr((struct sockaddr *)sp_out->remote);
! 572: } else if (sp_out->req && sp_out->req->saidx.mode == IPSEC_MODE_TUNNEL) {
! 573: /* Tunnel mode and no hint, use endpoints */
! 574: iph2->src = dupsaddr((struct sockaddr *)&sp_out->req->saidx.src);
! 575: iph2->dst = dupsaddr((struct sockaddr *)&sp_out->req->saidx.dst);
! 576: } else {
! 577: /* default, use selectors as fallback */
! 578: iph2->sa_dst = dupsaddr(dst);
! 579: iph2->sa_src = dupsaddr(src);
! 580: iph2->dst = dupsaddr(dst);
! 581: iph2->src = dupsaddr(src);
! 582: }
! 583:
! 584: if (iph2->dst == NULL || iph2->src == NULL) {
! 585: delph2(iph2);
! 586: break;
! 587: }
! 588: set_port(iph2->dst, 0);
! 589: set_port(iph2->src, 0);
1.1 misho 590:
591: if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
592: delph2(iph2);
593: break;
594: }
595:
596: insph2(iph2);
597: if (isakmp_post_acquire(iph2, NULL, FALSE) < 0) {
598: remph2(iph2);
599: delph2(iph2);
600: break;
601: }
602:
603: event_list = &iph2->evt_listeners;
604: l_ac_errno = 0;
605: break;
606: }
607: default:
608: /* ignore */
609: l_ac_errno = ENOTSUP;
610: }
611: break;
612: }
613:
614: default:
615: plog(LLV_ERROR, LOCATION, NULL,
616: "invalid command: %d\n", com->ac_cmd);
617: l_ac_errno = ENOTSUP;
618: }
619:
620: if ((error = admin_reply(so2, com, l_ac_errno, buf)) != 0)
621: goto out;
622:
623: /* start pushing events if so requested */
624: if ((l_ac_errno == 0) &&
625: (com->ac_version >= 1) &&
626: (com->ac_cmd == ADMIN_SHOW_EVT || event_list != NULL))
627: error = evt_subscribe(event_list, so2);
628: out:
629: if (buf != NULL)
630: vfree(buf);
631:
632: return error;
633: }
634:
635: static int
636: admin_reply(so, req, l_ac_errno, buf)
637: int so, l_ac_errno;
638: struct admin_com *req;
639: vchar_t *buf;
640: {
641: int tlen;
642: struct admin_com *combuf;
643: char *retbuf = NULL;
644:
645: if (buf != NULL)
646: tlen = sizeof(*combuf) + buf->l;
647: else
648: tlen = sizeof(*combuf);
649:
650: retbuf = racoon_calloc(1, tlen);
651: if (retbuf == NULL) {
652: plog(LLV_ERROR, LOCATION, NULL,
653: "failed to allocate admin buffer\n");
654: return -1;
655: }
656:
657: combuf = (struct admin_com *) retbuf;
658: combuf->ac_len = (u_int16_t) tlen;
659: combuf->ac_cmd = req->ac_cmd & ~ADMIN_FLAG_VERSION;
660: if (tlen != (u_int32_t) combuf->ac_len &&
661: l_ac_errno == 0) {
662: combuf->ac_len_high = tlen >> 16;
663: combuf->ac_cmd |= ADMIN_FLAG_LONG_REPLY;
664: } else {
665: combuf->ac_errno = l_ac_errno;
666: }
667: combuf->ac_proto = req->ac_proto;
668:
669: if (buf != NULL)
670: memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
671:
672: tlen = send(so, retbuf, tlen, 0);
673: racoon_free(retbuf);
674: if (tlen < 0) {
675: plog(LLV_ERROR, LOCATION, NULL,
676: "failed to send admin command: %s\n",
677: strerror(errno));
678: return -1;
679: }
680:
681: return 0;
682: }
683:
684: /* ADMIN_PROTO -> SADB_SATYPE */
685: int
686: admin2pfkey_proto(proto)
687: u_int proto;
688: {
689: switch (proto) {
690: case ADMIN_PROTO_IPSEC:
691: return SADB_SATYPE_UNSPEC;
692: case ADMIN_PROTO_AH:
693: return SADB_SATYPE_AH;
694: case ADMIN_PROTO_ESP:
695: return SADB_SATYPE_ESP;
696: default:
697: plog(LLV_ERROR, LOCATION, NULL,
698: "unsupported proto for admin: %d\n", proto);
699: return -1;
700: }
701: /*NOTREACHED*/
702: }
703:
704: int
705: admin_init()
706: {
707: if (adminsock_path == NULL) {
708: lcconf->sock_admin = -1;
709: return 0;
710: }
711:
712: memset(&sunaddr, 0, sizeof(sunaddr));
713: sunaddr.sun_family = AF_UNIX;
714: snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
715: "%s", adminsock_path);
716:
717: lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
718: if (lcconf->sock_admin == -1) {
719: plog(LLV_ERROR, LOCATION, NULL,
720: "socket: %s\n", strerror(errno));
721: return -1;
722: }
723: close_on_exec(lcconf->sock_admin);
724:
725: unlink(sunaddr.sun_path);
726: if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
727: sizeof(sunaddr)) != 0) {
728: plog(LLV_ERROR, LOCATION, NULL,
729: "bind(sockname:%s): %s\n",
730: sunaddr.sun_path, strerror(errno));
731: (void)close(lcconf->sock_admin);
732: return -1;
733: }
734:
735: if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
736: plog(LLV_ERROR, LOCATION, NULL,
737: "chown(%s, %d, %d): %s\n",
738: sunaddr.sun_path, adminsock_owner,
739: adminsock_group, strerror(errno));
740: (void)close(lcconf->sock_admin);
741: return -1;
742: }
743:
744: if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
745: plog(LLV_ERROR, LOCATION, NULL,
746: "chmod(%s, 0%03o): %s\n",
747: sunaddr.sun_path, adminsock_mode, strerror(errno));
748: (void)close(lcconf->sock_admin);
749: return -1;
750: }
751:
752: if (listen(lcconf->sock_admin, 5) != 0) {
753: plog(LLV_ERROR, LOCATION, NULL,
754: "listen(sockname:%s): %s\n",
755: sunaddr.sun_path, strerror(errno));
756: (void)close(lcconf->sock_admin);
757: return -1;
758: }
759:
760: monitor_fd(lcconf->sock_admin, admin_handler, NULL, 0);
761: plog(LLV_DEBUG, LOCATION, NULL,
762: "open %s as racoon management.\n", sunaddr.sun_path);
763:
764: return 0;
765: }
766:
767: int
768: admin_close()
769: {
770: unmonitor_fd(lcconf->sock_admin);
771: close(lcconf->sock_admin);
772: return 0;
773: }
774:
775: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>