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