source: rtems-libbsd/ipsec-tools/src/racoon/admin.c @ b376ae1

55-freebsd-126-freebsd-12
Last change on this file since b376ae1 was b376ae1, checked in by Christian Mauderer <christian.mauderer@…>, on 05/03/18 at 12:15:11

ipsec-tools: Port libipsec, setkey and racoon.

Note that this replaces the libipsec from FreeBSD with the one provided
by ipsec-tools.

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