Index: ipsec-tools-cvs/src/racoon/pfkey.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/pfkey.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/pfkey.c 2008-01-04 15:18:21.000000000 +0200 @@ -92,6 +92,7 @@ #include "algorithm.h" #include "sainfo.h" #include "admin.h" +#include "evt.h" #include "privsep.h" #include "strnames.h" #include "backupsa.h" @@ -1263,9 +1264,10 @@ /* turn off the timer for calling pfkey_timeover() */ SCHED_KILL(iph2->sce); - + /* update status */ iph2->status = PHASE2ST_ESTABLISHED; + evt_phase2(iph2, EVTT_PHASE2_UP, NULL); #ifdef ENABLE_STATS gettimeofday(&iph2->end, NULL); @@ -1636,7 +1638,6 @@ struct ph2handle *iph2[MAXNESTEDSA]; struct sockaddr *src, *dst; int n; /* # of phase 2 handler */ - int remoteid=0; #ifdef HAVE_SECCTX struct sadb_x_sec_ctx *m_sec_ctx; #endif /* HAVE_SECCTX */ @@ -1825,63 +1826,12 @@ return -1; } - plog(LLV_DEBUG, LOCATION, NULL, - "new acquire %s\n", spidx2str(&sp_out->spidx)); - - /* get sainfo */ - { - vchar_t *idsrc, *iddst; - - idsrc = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.src, - sp_out->spidx.prefs, sp_out->spidx.ul_proto); - if (idsrc == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get ID for %s\n", - spidx2str(&sp_out->spidx)); - delph2(iph2[n]); - return -1; - } - iddst = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.dst, - sp_out->spidx.prefd, sp_out->spidx.ul_proto); - if (iddst == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get ID for %s\n", - spidx2str(&sp_out->spidx)); - vfree(idsrc); - delph2(iph2[n]); - return -1; - } - { - struct remoteconf *conf; - conf = getrmconf(iph2[n]->dst); - if (conf != NULL) - remoteid=conf->ph1id; - else{ - plog(LLV_DEBUG, LOCATION, NULL, "Warning: no valid rmconf !\n"); - remoteid=0; - } - } - iph2[n]->sainfo = getsainfo(idsrc, iddst, NULL, remoteid); - vfree(idsrc); - vfree(iddst); - if (iph2[n]->sainfo == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get sainfo.\n"); + if (isakmp_get_sainfo(iph2[n], sp_out, sp_in) < 0) { delph2(iph2[n]); return -1; - /* XXX should use the algorithm list from register message */ } - plog(LLV_DEBUG, LOCATION, NULL, - "selected sainfo: %s\n", sainfo2str(iph2[n]->sainfo)); - } - if (set_proposal_from_policy(iph2[n], sp_out, sp_in) < 0) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to create saprop.\n"); - delph2(iph2[n]); - return -1; - } #ifdef HAVE_SECCTX if (m_sec_ctx) { set_secctx_in_proposal(iph2[n], spidx); @@ -2814,7 +2764,7 @@ struct sadb_msg buf, *newmsg; int reallen; int retry = 0; - + *lenp = -1; do { @@ -2823,12 +2773,10 @@ retry++; } while (*lenp < 0 && errno == EAGAIN && retry < 3); + if (*lenp < 0) - { - if ( errno == EAGAIN ) *lenp = 0; /* non-fatal */ - return NULL; /*fatal*/ - } - + return NULL; /*fatal*/ + else if (*lenp < sizeof(buf)) return NULL; Index: ipsec-tools-cvs/src/racoon/evt.h =================================================================== --- ipsec-tools-cvs.orig/src/racoon/evt.h 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/evt.h 2008-01-04 15:18:21.000000000 +0200 @@ -4,6 +4,7 @@ /* * Copyright (C) 2004 Emmanuel Dreyfus + * Copyright (C) 2007 Timo Teras * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,12 +35,27 @@ #ifndef _EVT_H #define _EVT_H -struct evtdump { - size_t len; - struct sockaddr_storage src; - struct sockaddr_storage dst; - time_t timestamp; - int type; +#ifdef ENABLE_ADMINPORT + +struct evt_listener { + LIST_ENTRY(evt_listener) ll_chain; + LIST_ENTRY(evt_listener) fd_chain; + int fd; +}; +LIST_HEAD(evt_listener_list, evt_listener); +#define EVT_LISTENER_LIST(x) struct evt_listener_list x; + +struct ph1handle; +struct ph2handle; + +struct evt_common { + uint32_t ec_type; + time_t ec_timestamp; + + struct sockaddr_storage ec_ph1src; + struct sockaddr_storage ec_ph1dst; + u_int32_t ec_ph2msgid; + /* * Optionnal list of struct isakmp_data * for type EVTT_ISAKMP_CFG_DONE @@ -47,42 +63,48 @@ }; /* type */ -#define EVTT_UNSEPC 0 -#define EVTT_PHASE1_UP 1 -#define EVTT_PHASE1_DOWN 2 -#define EVTT_XAUTH_SUCCESS 3 -#define EVTT_ISAKMP_CFG_DONE 4 -#define EVTT_PHASE2_UP 5 -#define EVTT_PHASE2_DOWN 6 -#define EVTT_DPD_TIMEOUT 7 -#define EVTT_PEER_NO_RESPONSE 8 -#define EVTT_PEER_DELETE 9 -#define EVTT_RACOON_QUIT 10 -#define EVTT_XAUTH_FAILED 11 -#define EVTT_OVERFLOW 12 /* Event queue overflowed */ -#define EVTT_PEERPH1AUTH_FAILED 13 -#define EVTT_PEERPH1_NOPROP 14 /* NO_PROPOSAL_CHOSEN & friends */ -#define EVTT_NO_ISAKMP_CFG 15 /* no need to wait for mode_cfg */ - -struct evt { - struct evtdump *dump; - TAILQ_ENTRY(evt) next; -}; +#define EVTT_RACOON_QUIT 0x0001 -TAILQ_HEAD(evtlist, evt); +#define EVTT_PHASE1_UP 0x0100 +#define EVTT_PHASE1_DOWN 0x0101 +#define EVTT_PHASE1_NO_RESPONSE 0x0102 +#define EVTT_PHASE1_NO_PROPOSAL 0x0103 +#define EVTT_PHASE1_AUTH_FAILED 0x0104 +#define EVTT_PHASE1_DPD_TIMEOUT 0x0105 +#define EVTT_PHASE1_PEER_DELETED 0x0106 +#define EVTT_PHASE1_MODE_CFG 0x0107 +#define EVTT_PHASE1_XAUTH_SUCCESS 0x0108 +#define EVTT_PHASE1_XAUTH_FAILED 0x0109 + +#define EVTT_PHASE2_NO_PHASE1 0x0200 +#define EVTT_PHASE2_UP 0x0201 +#define EVTT_PHASE2_DOWN 0x0202 +#define EVTT_PHASE2_NO_RESPONSE 0x0203 + +void evt_generic __P((int type, vchar_t *optdata)); +void evt_phase1 __P((const struct ph1handle *ph1, int type, vchar_t *optdata)); +void evt_phase2 __P((const struct ph2handle *ph2, int type, vchar_t *optdata)); + +int evt_subscribe __P((struct evt_listener_list *list, int fd)); +void evt_list_init __P((struct evt_listener_list *list)); +void evt_list_cleanup __P((struct evt_listener_list *list)); +int evt_get_fdmask __P((int nfds, fd_set *fdset)); +void evt_handle_fdmask __P((fd_set *fdset)); -#define EVTLIST_MAX 32 +#else -#ifdef ENABLE_ADMINPORT -struct evtdump *evt_pop(void); -vchar_t *evt_dump(void); -void evt_push(struct sockaddr *, struct sockaddr *, int, vchar_t *); -#endif +#define EVT_LISTENER_LIST(x) -#ifdef ENABLE_ADMINPORT -#define EVT_PUSH(src, dst, type, optdata) evt_push(src, dst, type, optdata); -#else -#define EVT_PUSH(src, dst, type, optdata) ; -#endif +#define evt_generic(type, optdata) ; +#define evt_phase1(ph1, type, optdata) ; +#define evt_phase2(ph2, type, optdata) ; + +#define evt_subscribe(eventlist, fd) ; +#define evt_list_init(eventlist) ; +#define evt_list_cleanup(eventlist) ; +#define evt_get_fdmask(nfds, fdset) nfds +#define evt_handle_fdmask(fdset) ; + +#endif /* ENABLE_ADMINPORT */ #endif /* _EVT_H */ Index: ipsec-tools-cvs/src/racoon/evt.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/evt.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/evt.c 2008-01-04 15:18:21.000000000 +0200 @@ -4,6 +4,7 @@ /* * Copyright (C) 2004 Emmanuel Dreyfus + * Copyright (C) 2007 Timo Teras * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,113 +47,219 @@ #include "plog.h" #include "misc.h" #include "admin.h" +#include "handler.h" #include "gcmalloc.h" #include "evt.h" #ifdef ENABLE_ADMINPORT -struct evtlist evtlist = TAILQ_HEAD_INITIALIZER(evtlist); -int evtlist_len = 0; -void -evt_push(src, dst, type, optdata) - struct sockaddr *src; - struct sockaddr *dst; +static EVT_LISTENER_LIST(evt_listeners); +static EVT_LISTENER_LIST(evt_fds); + +struct evtdump { + struct admin_com adm; + struct evt_common evt; +}; + +static struct evtdump * +evtdump_create(type, optdata) int type; vchar_t *optdata; { - struct evtdump *evtdump; - struct evt *evt; + struct evtdump *e; size_t len; - /* If admin socket is disabled, silently discard anything */ - if (adminsock_path == NULL) - return; + len = sizeof(struct admin_com) + sizeof(struct evt_common); + if (optdata != NULL) + len += optdata->l; - /* If we are above the limit, don't record anything */ - if (evtlist_len > EVTLIST_MAX) { - plog(LLV_DEBUG, LOCATION, NULL, - "Cannot record event: event queue overflowed\n"); - return; + if ((e = racoon_malloc(len)) == NULL) { + plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate event: %s\n", + strerror(errno)); + return NULL; } - /* If we hit the limit, record an overflow event instead */ - if (evtlist_len == EVTLIST_MAX) { - plog(LLV_ERROR, LOCATION, NULL, - "Cannot record event: event queue overflow\n"); - src = NULL; - dst = NULL; - type = EVTT_OVERFLOW; - optdata = NULL; + memset(e, 0, sizeof(struct evtdump)); + e->adm.ac_len = len; + e->adm.ac_cmd = ADMIN_SHOW_EVT; + e->adm.ac_errno = 0; + e->adm.ac_proto = 0; + e->evt.ec_type = type; + time(&e->evt.ec_timestamp); + if (optdata != NULL) + memcpy(e + 1, optdata->v, optdata->l); + + return e; +} + +static void +evt_unsubscribe(l) + struct evt_listener *l; +{ + plog(LLV_DEBUG, LOCATION, NULL, + "[%d] admin connection released\n", l->fd); + + LIST_REMOVE(l, ll_chain); + LIST_REMOVE(l, fd_chain); + close(l->fd); + racoon_free(l); +} + +static void +evtdump_broadcast(ll, e) + const struct evt_listener_list *ll; + struct evtdump *e; +{ + struct evt_listener *l, *nl; + + for (l = LIST_FIRST(ll); l != NULL; l = nl) { + nl = LIST_NEXT(l, ll_chain); + + if (send(l->fd, e, e->adm.ac_len, + MSG_NOSIGNAL | MSG_DONTWAIT) < 0) { + plog(LLV_DEBUG, LOCATION, NULL, "Cannot send event to fd: %s\n", + strerror(errno)); + evt_unsubscribe(l); + } } +} - len = sizeof(*evtdump); - if (optdata) - len += optdata->l; +void +evt_generic(type, optdata) + int type; + vchar_t *optdata; +{ + struct evtdump *e; - if ((evtdump = racoon_malloc(len)) == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "Cannot record event: %s\n", - strerror(errno)); + if ((e = evtdump_create(type, optdata)) == NULL) return; - } - if ((evt = racoon_malloc(sizeof(*evt))) == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "Cannot record event: %s\n", - strerror(errno)); - racoon_free(evtdump); + evtdump_broadcast(&evt_listeners, e); + + racoon_free(e); +} + +void +evt_phase1(ph1, type, optdata) + const struct ph1handle *ph1; + int type; + vchar_t *optdata; +{ + struct evtdump *e; + + if ((e = evtdump_create(type, optdata)) == NULL) return; + + if (ph1->local) + memcpy(&e->evt.ec_ph1src, ph1->local, sysdep_sa_len(ph1->local)); + if (ph1->remote) + memcpy(&e->evt.ec_ph1dst, ph1->remote, sysdep_sa_len(ph1->remote)); + + evtdump_broadcast(&ph1->evt_listeners, e); + evtdump_broadcast(&evt_listeners, e); + + racoon_free(e); +} + +void +evt_phase2(ph2, type, optdata) + const struct ph2handle *ph2; + int type; + vchar_t *optdata; +{ + struct evtdump *e; + struct ph1handle *ph1 = ph2->ph1; + + if ((e = evtdump_create(type, optdata)) == NULL) + return; + + if (ph1) { + if (ph1->local) + memcpy(&e->evt.ec_ph1src, ph1->local, sysdep_sa_len(ph1->local)); + if (ph1->remote) + memcpy(&e->evt.ec_ph1dst, ph1->remote, sysdep_sa_len(ph1->remote)); + } + e->evt.ec_ph2msgid = ph2->msgid; + + evtdump_broadcast(&ph2->evt_listeners, e); + if (ph1) + evtdump_broadcast(&ph1->evt_listeners, e); + evtdump_broadcast(&evt_listeners, e); + + racoon_free(e); +} + +int +evt_subscribe(list, fd) + struct evt_listener_list *list; + int fd; +{ + struct evt_listener *l; + + if ((l = racoon_malloc(sizeof(*l))) == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "Cannot allocate event listener: %s\n", + strerror(errno)); + return errno; } - if (src) - memcpy(&evtdump->src, src, sysdep_sa_len(src)); - if (dst) - memcpy(&evtdump->dst, dst, sysdep_sa_len(dst)); - evtdump->len = len; - evtdump->type = type; - time(&evtdump->timestamp); + if (list == NULL) + list = &evt_listeners; - if (optdata) - memcpy(evtdump + 1, optdata->v, optdata->l); + LIST_INSERT_HEAD(list, l, ll_chain); + LIST_INSERT_HEAD(&evt_fds, l, fd_chain); + l->fd = fd; - evt->dump = evtdump; - TAILQ_INSERT_TAIL(&evtlist, evt, next); + plog(LLV_DEBUG, LOCATION, NULL, + "[%d] admin connection is polling events\n", fd); - evtlist_len++; + return -2; +} - return; +void +evt_list_init(list) + struct evt_listener_list *list; +{ + LIST_INIT(list); } -struct evtdump * -evt_pop(void) { - struct evtdump *evtdump; - struct evt *evt; +void +evt_list_cleanup(list) + struct evt_listener_list *list; +{ + while (!LIST_EMPTY(list)) + evt_unsubscribe(LIST_FIRST(list)); +} - if ((evt = TAILQ_FIRST(&evtlist)) == NULL) - return NULL; +int +evt_get_fdmask(nfds, fdset) + int nfds; + fd_set *fdset; +{ + struct evt_listener *l; - evtdump = evt->dump; - TAILQ_REMOVE(&evtlist, evt, next); - racoon_free(evt); - evtlist_len--; - - return evtdump; -} - -vchar_t * -evt_dump(void) { - struct evtdump *evtdump; - vchar_t *buf = NULL; - - if ((evtdump = evt_pop()) != NULL) { - if ((buf = vmalloc(evtdump->len)) == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "evt_dump failed: %s\n", strerror(errno)); - return NULL; - } - memcpy(buf->v, evtdump, evtdump->len); - racoon_free(evtdump); + LIST_FOREACH(l, &evt_fds, fd_chain) { + FD_SET(l->fd, fdset); + if (l->fd + 1 > nfds) + nfds = l->fd + 1; } - return buf; + return nfds; } +void +evt_handle_fdmask(fdset) + fd_set *fdset; +{ + struct evt_listener *l, *nl; + + for (l = LIST_FIRST(&evt_fds); l != NULL; l = nl) { + nl = LIST_NEXT(l, ll_chain); + + if (FD_ISSET(l->fd, fdset)) + evt_unsubscribe(l); + } +} + + #endif /* ENABLE_ADMINPORT */ Index: ipsec-tools-cvs/src/racoon/handler.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/handler.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/handler.c 2008-01-04 15:18:21.000000000 +0200 @@ -267,6 +267,7 @@ iph1->dpd_fails = 0; iph1->dpd_r_u = NULL; #endif + evt_list_init(&iph1->evt_listeners); return iph1; } @@ -283,8 +284,7 @@ /* SA down shell script hook */ script_hook(iph1, SCRIPT_PHASE1_DOWN); - - EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_DOWN, NULL); + evt_list_cleanup(&iph1->evt_listeners); #ifdef ENABLE_NATT if (iph1->natt_flags & NAT_KA_QUEUED) @@ -489,8 +489,8 @@ LIST_FOREACH(p, &ph2tree, chain) { if (spid == p->spid && - CMPSADDR(src, p->src) == 0 && - CMPSADDR(dst, p->dst) == 0){ + cmpsaddrwild(src, p->src) == 0 && + cmpsaddrwild(dst, p->dst) == 0){ /* Sanity check to detect zombie handlers * XXX Sould be done "somewhere" more interesting, * because we have lots of getph2byxxxx(), but this one @@ -576,6 +576,7 @@ return NULL; iph2->status = PHASE1ST_SPAWN; + evt_list_init(&iph2->evt_listeners); return iph2; } @@ -589,6 +590,8 @@ initph2(iph2) struct ph2handle *iph2; { + evt_list_cleanup(&iph2->evt_listeners); + sched_scrub_param(iph2); iph2->sce = NULL; iph2->scr = NULL; Index: ipsec-tools-cvs/src/racoon/isakmp_agg.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/isakmp_agg.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/isakmp_agg.c 2008-01-04 15:18:21.000000000 +0200 @@ -587,8 +587,7 @@ /* message printed inner oakley_validate_auth() */ goto end; } - EVT_PUSH(iph1->local, iph1->remote, - EVTT_PEERPH1AUTH_FAILED, NULL); + evt_phase1(iph1, EVTT_PHASE1_AUTH_FAILED, NULL); isakmp_info_send_n1(iph1, ptype, NULL); goto end; } @@ -1486,8 +1485,7 @@ /* message printed inner oakley_validate_auth() */ goto end; } - EVT_PUSH(iph1->local, iph1->remote, - EVTT_PEERPH1AUTH_FAILED, NULL); + evt_phase1(iph1, EVTT_PHASE1_AUTH_FAILED, NULL); isakmp_info_send_n1(iph1, ptype, NULL); goto end; } Index: ipsec-tools-cvs/src/racoon/isakmp_base.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/isakmp_base.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/isakmp_base.c 2008-01-04 15:18:21.000000000 +0200 @@ -716,8 +716,7 @@ /* message printed inner oakley_validate_auth() */ goto end; } - EVT_PUSH(iph1->local, iph1->remote, - EVTT_PEERPH1AUTH_FAILED, NULL); + evt_phase1(iph1, EVTT_PHASE1_AUTH_FAILED, NULL); isakmp_info_send_n1(iph1, ptype, NULL); goto end; } @@ -1242,8 +1241,7 @@ /* message printed inner oakley_validate_auth() */ goto end; } - EVT_PUSH(iph1->local, iph1->remote, - EVTT_PEERPH1AUTH_FAILED, NULL); + evt_phase1(iph1, EVTT_PHASE1_AUTH_FAILED, NULL); isakmp_info_send_n1(iph1, ptype, NULL); goto end; } Index: ipsec-tools-cvs/src/racoon/isakmp.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/isakmp.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/isakmp.c 2008-01-04 15:18:21.000000000 +0200 @@ -88,6 +88,9 @@ #include "pfkey.h" #include "crypto_openssl.h" #include "policy.h" +#include "algorithm.h" +#include "proposal.h" +#include "sainfo.h" #include "isakmp_ident.h" #include "isakmp_agg.h" #include "isakmp_base.h" @@ -1026,7 +1029,7 @@ } /* new negotiation of phase 1 for initiator */ -int +struct ph1handle * isakmp_ph1begin_i(rmconf, remote, local) struct remoteconf *rmconf; struct sockaddr *remote, *local; @@ -1039,7 +1042,7 @@ /* get new entry to isakmp status table. */ iph1 = newph1(); if (iph1 == NULL) - return -1; + return NULL; iph1->status = PHASE1ST_START; iph1->rmconf = rmconf; @@ -1055,7 +1058,7 @@ if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) { remph1(iph1); delph1(iph1); - return -1; + return NULL; } #endif #ifdef ENABLE_FRAG @@ -1072,7 +1075,7 @@ if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) { remph1(iph1); delph1(iph1); - return -1; + return NULL; } (void)insph1(iph1); @@ -1108,7 +1111,7 @@ remph1(iph1); delph1(iph1); - return -1; + return NULL; } #ifdef ENABLE_STATS @@ -1119,7 +1122,7 @@ timedelta(&start, &end)); #endif - return 0; + return iph1; } /* new negotiation of phase 1 for responder */ @@ -1929,8 +1932,7 @@ plog(LLV_ERROR, LOCATION, NULL, "phase1 negotiation failed due to time up. %s\n", isakmp_pindex(&iph1->index, iph1->msgid)); - EVT_PUSH(iph1->local, iph1->remote, - EVTT_PEER_NO_RESPONSE, NULL); + evt_phase1(iph1, EVTT_PHASE1_NO_RESPONSE, NULL); return -1; } @@ -1939,8 +1941,7 @@ plog(LLV_ERROR, LOCATION, NULL, "phase1 negotiation failed due to send error. %s\n", isakmp_pindex(&iph1->index, iph1->msgid)); - EVT_PUSH(iph1->local, iph1->remote, - EVTT_PEER_NO_RESPONSE, NULL); + evt_phase1(iph1, EVTT_PHASE1_NO_RESPONSE, NULL); return -1; } @@ -1989,7 +1990,7 @@ plog(LLV_ERROR, LOCATION, NULL, "phase2 negotiation failed due to time up. %s\n", isakmp_pindex(&iph2->ph1->index, iph2->msgid)); - EVT_PUSH(iph2->src, iph2->dst, EVTT_PEER_NO_RESPONSE, NULL); + evt_phase2(iph2, EVTT_PHASE2_NO_RESPONSE, NULL); unbindph12(iph2); return -1; } @@ -1998,8 +1999,7 @@ plog(LLV_ERROR, LOCATION, NULL, "phase2 negotiation failed due to send error. %s\n", isakmp_pindex(&iph2->ph1->index, iph2->msgid)); - EVT_PUSH(iph2->src, iph2->dst, EVTT_PEER_NO_RESPONSE, NULL); - + evt_phase2(iph2, EVTT_PHASE2_NO_RESPONSE, NULL); return -1; } @@ -2090,7 +2090,7 @@ plog(LLV_INFO, LOCATION, NULL, "ISAKMP-SA deleted %s-%s spi:%s\n", src, dst, isakmp_pindex(&iph1->index, 0)); - EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_DOWN, NULL); + evt_phase1(iph1, EVTT_PHASE1_DOWN, NULL); racoon_free(src); racoon_free(dst); @@ -2237,7 +2237,7 @@ saddrwop2str(iph2->dst)); /* start phase 1 negotiation as a initiator. */ - if (isakmp_ph1begin_i(rmconf, iph2->dst, iph2->src) < 0) { + if (isakmp_ph1begin_i(rmconf, iph2->dst, iph2->src) == NULL) { SCHED_KILL(sc); return -1; } @@ -2270,6 +2270,71 @@ return 0; } +int +isakmp_get_sainfo(iph2, sp_out, sp_in) + struct ph2handle *iph2; + struct secpolicy *sp_out, *sp_in; +{ + int remoteid=0; + + plog(LLV_DEBUG, LOCATION, NULL, + "new acquire %s\n", spidx2str(&sp_out->spidx)); + + /* get sainfo */ + { + vchar_t *idsrc, *iddst; + + idsrc = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.src, + sp_out->spidx.prefs, sp_out->spidx.ul_proto); + if (idsrc == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to get ID for %s\n", + spidx2str(&sp_out->spidx)); + return -1; + } + iddst = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.dst, + sp_out->spidx.prefd, sp_out->spidx.ul_proto); + if (iddst == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to get ID for %s\n", + spidx2str(&sp_out->spidx)); + vfree(idsrc); + return -1; + } + { + struct remoteconf *conf; + conf = getrmconf(iph2->dst); + if (conf != NULL) + remoteid=conf->ph1id; + else{ + plog(LLV_DEBUG, LOCATION, NULL, "Warning: no valid rmconf !\n"); + remoteid=0; + } + } + iph2->sainfo = getsainfo(idsrc, iddst, NULL, remoteid); + vfree(idsrc); + vfree(iddst); + if (iph2->sainfo == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to get sainfo.\n"); + return -1; + /* XXX should use the algorithm list from register message */ + } + + plog(LLV_DEBUG, LOCATION, NULL, + "selected sainfo: %s\n", sainfo2str(iph2->sainfo)); + } + + if (set_proposal_from_policy(iph2, sp_out, sp_in) < 0) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to create saprop.\n"); + return -1; + } + + return 0; +} + + /* * receive GETSPI from kernel. */ @@ -3021,9 +3086,9 @@ src, dst, isakmp_pindex(&iph1->index, 0)); - EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_UP, NULL); + evt_phase1(iph1, EVTT_PHASE1_UP, NULL); if(!iph1->rmconf->mode_cfg) - EVT_PUSH(iph1->local, iph1->remote, EVTT_NO_ISAKMP_CFG, NULL); + evt_phase1(iph1, EVTT_PHASE1_MODE_CFG, NULL); racoon_free(src); racoon_free(dst); Index: ipsec-tools-cvs/src/racoon/isakmp_cfg.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/isakmp_cfg.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/isakmp_cfg.c 2008-01-04 15:18:21.000000000 +0200 @@ -473,8 +473,7 @@ "Cannot allocate memory: %s\n", strerror(errno)); } else { memcpy(buf->v, attrpl + 1, buf->l); - EVT_PUSH(iph1->local, iph1->remote, - EVTT_ISAKMP_CFG_DONE, buf); + evt_phase1(iph1, EVTT_PHASE1_MODE_CFG, buf); vfree(buf); } } Index: ipsec-tools-cvs/src/racoon/isakmp_ident.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/isakmp_ident.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/isakmp_ident.c 2008-01-04 15:18:21.000000000 +0200 @@ -788,8 +788,7 @@ /* msg printed inner oakley_validate_auth() */ goto end; } - EVT_PUSH(iph1->local, iph1->remote, - EVTT_PEERPH1AUTH_FAILED, NULL); + evt_phase1(iph1, EVTT_PHASE1_AUTH_FAILED, NULL); isakmp_info_send_n1(iph1, type, NULL); goto end; } @@ -1537,8 +1536,7 @@ /* msg printed inner oakley_validate_auth() */ goto end; } - EVT_PUSH(iph1->local, iph1->remote, - EVTT_PEERPH1AUTH_FAILED, NULL); + evt_phase1(iph1, EVTT_PHASE1_AUTH_FAILED, NULL); isakmp_info_send_n1(iph1, type, NULL); goto end; } Index: ipsec-tools-cvs/src/racoon/isakmp_inf.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/isakmp_inf.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/isakmp_inf.c 2008-01-04 15:18:21.000000000 +0200 @@ -515,8 +515,7 @@ del_ph1=getph1byindex((isakmp_index *)(delete + 1)); if(del_ph1 != NULL){ - EVT_PUSH(del_ph1->local, del_ph1->remote, - EVTT_PEERPH1_NOPROP, NULL); + evt_phase1(iph1, EVTT_PHASE1_PEER_DELETED, NULL); if (del_ph1->scr) SCHED_KILL(del_ph1->scr); @@ -537,8 +536,6 @@ delete->spi_size, delete->proto_id); return 0; } - EVT_PUSH(iph1->local, iph1->remote, - EVTT_PEER_DELETE, NULL); purge_ipsec_spi(iph1->remote, delete->proto_id, (u_int32_t *)(delete + 1), num_spi); break; @@ -1615,7 +1612,7 @@ plog(LLV_DEBUG, LOCATION, iph1->remote, "DPD monitoring....\n"); if (iph1->dpd_fails >= iph1->rmconf->dpd_maxfails) { - EVT_PUSH(iph1->local, iph1->remote, EVTT_DPD_TIMEOUT, NULL); + evt_phase1(iph1, EVTT_PHASE1_DPD_TIMEOUT, NULL); purge_remote(iph1); plog(LLV_DEBUG, LOCATION, iph1->remote, "DPD: remote seems to be dead\n"); Index: ipsec-tools-cvs/src/racoon/isakmp_xauth.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/isakmp_xauth.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/isakmp_xauth.c 2008-01-04 15:18:21.000000000 +0200 @@ -1570,13 +1570,11 @@ plog(LLV_ERROR, LOCATION, NULL, "Xauth authentication failed\n"); - EVT_PUSH(iph1->local, iph1->remote, - EVTT_XAUTH_FAILED, NULL); + evt_phase1(iph1, EVTT_PHASE1_XAUTH_FAILED, NULL); iph1->mode_cfg->flags |= ISAKMP_CFG_DELETE_PH1; } else { - EVT_PUSH(iph1->local, iph1->remote, - EVTT_XAUTH_SUCCESS, NULL); + evt_phase1(iph1, EVTT_PHASE1_XAUTH_SUCCESS, NULL); } Index: ipsec-tools-cvs/src/racoon/session.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/session.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/session.c 2008-01-04 15:18:21.000000000 +0200 @@ -192,6 +192,7 @@ /* scheduling */ timeout = schedular(); + nfds = evt_get_fdmask(nfds, &rfds); error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout); if (error < 0) { switch (errno) { @@ -211,6 +212,7 @@ (FD_ISSET(lcconf->sock_admin, &rfds))) admin_handler(); #endif + evt_handle_fdmask(&rfds); for (p = lcconf->myaddrs; p; p = p->next) { if (!p->addr) @@ -451,7 +453,7 @@ case SIGTERM: plog(LLV_INFO, LOCATION, NULL, "caught signal %d\n", sig); - EVT_PUSH(NULL, NULL, EVTT_RACOON_QUIT, NULL); + evt_generic(EVTT_RACOON_QUIT, NULL); pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC); #ifdef ENABLE_FASTQUIT Index: ipsec-tools-cvs/src/racoon/handler.h =================================================================== --- ipsec-tools-cvs.orig/src/racoon/handler.h 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/handler.h 2008-01-04 15:18:21.000000000 +0200 @@ -41,6 +41,7 @@ #include "isakmp_var.h" #include "oakley.h" +#include "evt.h" /* Phase 1 handler */ /* @@ -211,7 +212,7 @@ #ifdef ENABLE_HYBRID struct isakmp_cfg_state *mode_cfg; /* ISAKMP mode config state */ #endif - + EVT_LISTENER_LIST(evt_listeners); }; /* Phase 2 handler */ @@ -320,6 +321,7 @@ LIST_ENTRY(ph2handle) chain; LIST_ENTRY(ph2handle) ph1bind; /* chain to ph1handle */ + EVT_LISTENER_LIST(evt_listeners); }; /* Index: ipsec-tools-cvs/src/racoon/isakmp_var.h =================================================================== --- ipsec-tools-cvs.orig/src/racoon/isakmp_var.h 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/isakmp_var.h 2008-01-04 15:18:21.000000000 +0200 @@ -35,6 +35,7 @@ #define _ISAKMP_VAR_H #include "vmbuf.h" +#include "policy.h" #define PORT_ISAKMP 500 #define PORT_ISAKMP_NATT 4500 @@ -62,8 +63,8 @@ struct isakmp_pl_nonce; /* XXX */ extern int isakmp_handler __P((int)); -extern int isakmp_ph1begin_i __P((struct remoteconf *, struct sockaddr *, - struct sockaddr *)); +extern struct ph1handle *isakmp_ph1begin_i __P((struct remoteconf *, + struct sockaddr *, struct sockaddr *)); extern vchar_t *isakmp_parsewoh __P((int, struct isakmp_gen *, int)); extern vchar_t *isakmp_parse __P((vchar_t *)); @@ -87,6 +88,7 @@ extern void isakmp_ph2delete_stub __P((void *)); extern void isakmp_ph2delete __P((struct ph2handle *)); +extern int isakmp_get_sainfo __P((struct ph2handle *, struct secpolicy *, struct secpolicy *)); extern int isakmp_post_acquire __P((struct ph2handle *)); extern int isakmp_post_getspi __P((struct ph2handle *)); extern void isakmp_chkph1there_stub __P((void *)); Index: ipsec-tools-cvs/src/racoon/racoonctl.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/racoonctl.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/racoonctl.c 2008-01-04 15:18:21.000000000 +0200 @@ -4,6 +4,7 @@ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * Copyright (C) 2007 Timo Teras. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -135,26 +136,24 @@ struct evtmsg { int type; char *msg; - enum { UNSPEC, ERROR, INFO } level; } evtmsg[] = { - { EVTT_PHASE1_UP, "Phase 1 established", INFO }, - { EVTT_PHASE1_DOWN, "Phase 1 deleted", INFO }, - { EVTT_XAUTH_SUCCESS, "Xauth exchange passed", INFO }, - { EVTT_ISAKMP_CFG_DONE, "ISAKMP mode config done", INFO }, - { EVTT_PHASE2_UP, "Phase 2 established", INFO }, - { EVTT_PHASE2_DOWN, "Phase 2 deleted", INFO }, - { EVTT_DPD_TIMEOUT, "Peer not reachable anymore", ERROR }, - { EVTT_PEER_NO_RESPONSE, "Peer not responding", ERROR }, - { EVTT_PEER_DELETE, "Peer terminated security association", ERROR }, - { EVTT_RACOON_QUIT, "Raccon terminated", ERROR }, - { EVTT_OVERFLOW, "Event queue overflow", ERROR }, - { EVTT_XAUTH_FAILED, "Xauth exchange failed", ERROR }, - { EVTT_PEERPH1AUTH_FAILED, "Peer failed phase 1 authentication " - "(certificate problem?)", ERROR }, - { EVTT_PEERPH1_NOPROP, "Peer failed phase 1 initiation " - "(proposal problem?)", ERROR }, - { 0, NULL, UNSPEC }, - { EVTT_NO_ISAKMP_CFG, "No need for ISAKMP mode config ", INFO }, + { EVTT_RACOON_QUIT, "Racoon terminated" }, + + { EVTT_PHASE1_UP, "Phase 1 established" }, + { EVTT_PHASE1_DOWN, "Phase 1 deleted" }, + { EVTT_PHASE1_NO_RESPONSE, "Phase 1 error: peer not responding" }, + { EVTT_PHASE1_NO_PROPOSAL, "Phase 1 error: no proposal chosen" }, + { EVTT_PHASE1_AUTH_FAILED, + "Phase 1 error: authentication failed (bad certificate?)" }, + { EVTT_PHASE1_DPD_TIMEOUT, "Phase 1 error: dead peer detected" }, + { EVTT_PHASE1_MODE_CFG, "Phase 1 mode configuration done" }, + { EVTT_PHASE1_XAUTH_SUCCESS, "Phase 1 Xauth succeeded" }, + { EVTT_PHASE1_XAUTH_FAILED, "Phase 1 Xauth failed" }, + + { EVTT_PHASE2_NO_PHASE1, "Phase 2 error: no suitable phase 1" }, + { EVTT_PHASE2_UP, "Phase 2 established" }, + { EVTT_PHASE2_DOWN, "Phase 2 deleted" }, + { EVTT_PHASE2_NO_RESPONSE, "Phase 2 error: no response" }, }; static int get_proto __P((char *)); @@ -184,6 +183,7 @@ { IPPROTO_ICMP, "icmp" }, { IPPROTO_TCP, "tcp" }, { IPPROTO_UDP, "udp" }, + { IPPROTO_GRE, "gre" }, { 0, NULL }, }; @@ -193,31 +193,13 @@ char *pname; int long_format = 0; - -#define EVTF_NONE 0x0000 /* Ignore any events */ -#define EVTF_LOOP 0x0001 /* Loop awaiting for new events */ -#define EVTF_CFG_STOP 0x0002 /* Stop after ISAKMP mode config */ -#define EVTF_CFG 0x0004 /* Print ISAKMP mode config info */ -#define EVTF_ALL 0x0008 /* Print any events */ -#define EVTF_PURGE 0x0010 /* Print all available events */ -#define EVTF_PH1DOWN_STOP 0x0020 /* Stop when phase 1 SA gets down */ -#define EVTF_PH1DOWN 0x0040 /* Print that phase 1 SA got down */ -#define EVTF_ERR 0x0080 /* Print any error */ -#define EVTF_ERR_STOP 0x0100 /* Stop on any error */ - -int evt_filter = EVTF_NONE; -time_t evt_start; +int evt_quit_event = 0; void dump_isakmp_sa __P((char *, int)); void dump_internal __P((char *, int)); char *pindex_isakmp __P((isakmp_index *)); void print_schedule __P((caddr_t, int)); -void print_evt __P((caddr_t, int)); -void print_cfg __P((caddr_t, int)); -void print_err __P((caddr_t, int)); -void print_ph1down __P((caddr_t, int)); -void print_ph1up __P((caddr_t, int)); -int evt_poll __P((void)); +void print_evt __P((struct evt_common *)); char * fixed_addr __P((char *, char *, int)); static void @@ -226,12 +208,15 @@ printf( "Usage:\n" " %s reload-config\n" +" %s show-schedule\n" " %s [-l [-l]] show-sa [protocol]\n" " %s flush-sa [protocol]\n" " %s delete-sa \n" -" %s establish-sa [-u identity] \n" +" %s establish-sa [-u identity] [-w] \n" " %s vpn-connect [-u identity] vpn_gateway\n" " %s vpn-disconnect vpn_gateway\n" +" %s show-event\n" +" %s logout-user login\n" "\n" " : \"isakmp\", \"esp\" or \"ah\".\n" " In the case of \"show-sa\" or \"flush-sa\", you can use \"ipsec\".\n" @@ -240,8 +225,8 @@ " : {\"esp\",\"ah\"} \n" " \n" " : \"inet\" or \"inet6\"\n" -" : \"icmp\", \"tcp\", \"udp\" or \"any\"\n", - pname, pname, pname, pname, pname, pname, pname); +" : \"icmp\", \"tcp\", \"udp\", \"gre\" or \"any\"\n", + pname, pname, pname, pname, pname, pname, pname, pname, pname, pname); } /* @@ -312,54 +297,24 @@ vfree(combuf); - if (com_recv(&combuf) != 0) - goto bad; - if (handle_recv(combuf) != 0) - goto bad; - - vfree(combuf); + do { + if (com_recv(&combuf) != 0) + goto bad; + if (handle_recv(combuf) != 0) + goto bad; + vfree(combuf); + } while (evt_quit_event != 0); - if (evt_filter != EVTF_NONE) - if (evt_poll() != 0) - goto bad; - + close(so); exit(0); - bad: +bad: + close(so); + if (errno == EEXIST) + exit(0); exit(1); } -int -evt_poll(void) { - struct timeval tv; - vchar_t *recvbuf; - vchar_t *sendbuf; - - if ((sendbuf = f_getevt(0, NULL)) == NULL) - errx(1, "Cannot make combuf"); - - - while (evt_filter & (EVTF_LOOP|EVTF_PURGE)) { - /* handle_recv closes the socket time, so open it each time */ - com_init(); - - if (com_send(sendbuf) != 0) - errx(1, "Cannot send combuf"); - - if (com_recv(&recvbuf) == 0) { - handle_recv(recvbuf); - vfree(recvbuf); - } - - tv.tv_sec = 0; - tv.tv_usec = 10; - (void)select(0, NULL, NULL, NULL, &tv); - } - - vfree(sendbuf); - return 0; -} - /* %%% */ /* * return command buffer. @@ -422,20 +377,8 @@ vchar_t *buf; struct admin_com *head; - /* - * There are 3 ways of getting here - * 1) racoonctl vc => evt_filter = (EVTF_LOOP|EVTF_CFG| ... ) - * 2) racoonctl es => evt_filter = EVTF_NONE - * 3) racoonctl es -l => evt_filter = EVTF_LOOP - * Catch the second case: show-event is here to purge all - */ - if (evt_filter == EVTF_NONE) - evt_filter = (EVTF_ALL|EVTF_PURGE); - - if ((ac >= 1) && (strcmp(av[0], "-l") == 0)) - evt_filter |= EVTF_LOOP; - - if (ac >= 2) + evt_quit_event = -1; + if (ac >= 1) errx(1, "too many arguments"); buf = vmalloc(sizeof(*head)); @@ -653,6 +596,7 @@ char *id = NULL; char *key = NULL; struct admin_com_psk *acp; + int wait = 0; if (ac < 1) errx(1, "insufficient arguments"); @@ -673,6 +617,12 @@ ac -= 2; } + if (ac >= 1 && strcmp(av[0], "-w") == 0) { + wait = 1; + av++; + ac--; + } + /* need protocol */ if (ac < 1) errx(1, "insufficient arguments"); @@ -687,12 +637,16 @@ index = get_index(ac, av); if (index == NULL) return NULL; + if (wait) + evt_quit_event = EVTT_PHASE1_MODE_CFG; break; case ADMIN_PROTO_AH: case ADMIN_PROTO_ESP: index = get_index(ac, av); if (index == NULL) return NULL; + if (wait) + evt_quit_event = EVTT_PHASE2_UP; break; default: errno = EPROTONOSUPPORT; @@ -749,8 +703,7 @@ if (ac < 1) errx(1, "insufficient arguments"); - evt_filter = (EVTF_LOOP|EVTF_CFG|EVTF_CFG_STOP|EVTF_ERR|EVTF_ERR_STOP); - time(&evt_start); + evt_quit_event = EVTT_PHASE1_MODE_CFG; /* Optional -u identity */ if (strcmp(av[0], "-u") == 0) { @@ -814,8 +767,7 @@ if (ac > 1) warnx("Extra arguments"); - evt_filter = - (EVTF_PH1DOWN|EVTF_PH1DOWN_STOP|EVTF_LOOP|EVTF_ERR|EVTF_ERR_STOP); + evt_quit_event = EVTT_PHASE1_DOWN; nav[nac++] = isakmp; nav[nac++] = inet; @@ -1335,84 +1287,32 @@ void -print_evt(buf, len) - caddr_t buf; - int len; +print_evt(evtdump) + struct evt_common *evtdump; { - struct evtdump *evtdump = (struct evtdump *)buf; int i; char *srcstr; char *dststr; - for (i = 0; evtmsg[i].msg; i++) - if (evtmsg[i].type == evtdump->type) - break; - - if (evtmsg[i].msg == NULL) - printf("Event %d: ", evtdump->type); + for (i = 0; i < sizeof(evtmsg) / sizeof(evtmsg[0]); i++) + if (evtmsg[i].type == evtdump->ec_type) + break; + + if (evtmsg[i].msg == NULL) + printf("Event %d: ", evtdump->ec_type); else printf("%s : ", evtmsg[i].msg); - if ((srcstr = saddr2str((struct sockaddr *)&evtdump->src)) == NULL) + if ((srcstr = saddr2str((struct sockaddr *)&evtdump->ec_ph1src)) == NULL) printf("unknown"); - else + else printf("%s", srcstr); printf(" -> "); - if ((dststr = saddr2str((struct sockaddr *)&evtdump->dst)) == NULL) + if ((dststr = saddr2str((struct sockaddr *)&evtdump->ec_ph1dst)) == NULL) printf("unknown"); - else + else printf("%s", dststr); printf("\n"); - - return; -} - -void -print_err(buf, len) - caddr_t buf; - int len; -{ - struct evtdump *evtdump = (struct evtdump *)buf; - int i; - - - for (i = 0; evtmsg[i].msg; i++) - if (evtmsg[i].type == evtdump->type) - break; - - if (evtmsg[i].level != ERROR) - return; - - if (evtmsg[i].msg == NULL) - printf("Error: Event %d\n", evtdump->type); - else - printf("Error: %s\n", evtmsg[i].msg); - - if (evt_filter & EVTF_ERR_STOP) - evt_filter &= ~EVTF_LOOP; - - return; -} - -/* - * Print a message when phase 1 SA goes down - */ -void -print_ph1down(buf, len) - caddr_t buf; - int len; -{ - struct evtdump *evtdump = (struct evtdump *)buf; - - if (evtdump->type != EVTT_PHASE1_DOWN) - return; - - printf("VPN connexion terminated\n"); - - if (evt_filter & EVTF_PH1DOWN_STOP) - evt_filter &= ~EVTF_LOOP; - - return; } /* @@ -1423,15 +1323,14 @@ caddr_t buf; int len; { - struct evtdump *evtdump = (struct evtdump *)buf; + struct evt_common *evtdump = (struct evt_common *)buf; struct isakmp_data *attr; char *banner = NULL; struct in_addr addr4; memset(&addr4, 0, sizeof(addr4)); - if (evtdump->type != EVTT_ISAKMP_CFG_DONE && - evtdump->type != EVTT_NO_ISAKMP_CFG) + if (evtdump->ec_type != EVTT_PHASE1_MODE_CFG) return; len -= sizeof(*evtdump); @@ -1484,12 +1383,12 @@ (n + sizeof(*attr) + ntohs(attr->lorv)); } } - - if (evtdump->type == EVTT_ISAKMP_CFG_DONE) + + if (len > 0) printf("Bound to address %s\n", inet_ntoa(addr4)); else printf("VPN connexion established\n"); - + if (banner) { struct winsize win; int col = 0; @@ -1506,13 +1405,8 @@ printf("\n"); racoon_free(banner); } - - if (evt_filter & EVTF_CFG_STOP) - evt_filter &= ~EVTF_LOOP; - - return; } - + char * fixed_addr(addr, port, len) @@ -1561,32 +1455,29 @@ break; case ADMIN_SHOW_EVT: { - struct evtdump *evtdump; + struct evt_common *ec; - /* We got no event */ - if (len == 0) { - /* If we were purging the queue, it is now done */ - if (evt_filter & EVTF_PURGE) - evt_filter &= ~EVTF_PURGE; + /* We got no event? */ + if (len == 0) break; - } - - if (len < sizeof(struct evtdump)) - errx(1, "Short buffer\n"); - /* Toss outdated events */ - evtdump = (struct evtdump *)buf; - if (evtdump->timestamp < evt_start) - break; + if (len < sizeof(struct evt_common)) + errx(1, "Short buffer\n"); - if (evt_filter & EVTF_ALL) - print_evt(buf, len); - if (evt_filter & EVTF_ERR) - print_err(buf, len); - if (evt_filter & EVTF_CFG) - print_cfg(buf, len); - if (evt_filter & EVTF_PH1DOWN) - print_ph1down(buf, len); + ec = (struct evt_common *) buf; + if (evt_quit_event <= 0) + print_evt(ec); + else if (evt_quit_event == ec->ec_type) { + switch (ec->ec_type) { + case EVTT_PHASE1_MODE_CFG: + print_cfg(ec, len); + break; + default: + print_evt(ec); + break; + }; + evt_quit_event = 0; + } break; } @@ -1643,10 +1534,8 @@ break; } - close(so); return 0; - bad: - close(so); +bad: return -1; } Index: ipsec-tools-cvs/src/racoon/admin.c =================================================================== --- ipsec-tools-cvs.orig/src/racoon/admin.c 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/admin.c 2008-01-04 15:18:21.000000000 +0200 @@ -76,6 +76,7 @@ #include "evt.h" #include "pfkey.h" #include "ipsec_doi.h" +#include "policy.h" #include "admin.h" #include "admin_var.h" #include "isakmp_inf.h" @@ -147,16 +148,18 @@ goto end; } - if (com.ac_cmd == ADMIN_RELOAD_CONF) { - /* reload does not work at all! */ - signal_handler(SIGHUP); - goto end; - } + plog(LLV_DEBUG, LOCATION, NULL, + "[%d] admin connection established\n", so2); error = admin_process(so2, combuf); - end: - (void)close(so2); +end: + if (error != -2) { + plog(LLV_DEBUG, LOCATION, NULL, + "[%d] admin connection closed\n", so2); + (void)close(so2); + } + if (combuf) racoon_free(combuf); @@ -177,13 +180,15 @@ vchar_t *key = NULL; int idtype = 0; int error = -1; + int send_events = 0; + struct evt_listener_list *event_list = NULL; com->ac_errno = 0; switch (com->ac_cmd) { case ADMIN_RELOAD_CONF: - /* don't entered because of proccessing it in other place. */ - plog(LLV_ERROR, LOCATION, NULL, "should never reach here\n"); + signal_handler(SIGHUP); + error = 0; goto out; case ADMIN_SHOW_SCHED: @@ -208,9 +213,7 @@ } case ADMIN_SHOW_EVT: - /* It's not really an error, don't force racoonctl to quit */ - if ((buf = evt_dump()) == NULL) - com->ac_errno = 0; + send_events = 1; break; case ADMIN_SHOW_SA: @@ -391,17 +394,17 @@ /* FALLTHROUGH */ case ADMIN_ESTABLISH_SA: { + struct admin_com_indexes *ndx; struct sockaddr *dst; struct sockaddr *src; - src = (struct sockaddr *) - &((struct admin_com_indexes *) - ((caddr_t)com + sizeof(*com)))->src; - dst = (struct sockaddr *) - &((struct admin_com_indexes *) - ((caddr_t)com + sizeof(*com)))->dst; + + ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com)); + src = (struct sockaddr *) &ndx->src; + dst = (struct sockaddr *) &ndx->dst; switch (com->ac_proto) { case ADMIN_PROTO_ISAKMP: { + struct ph1handle *ph1; struct remoteconf *rmconf; struct sockaddr *remote = NULL; struct sockaddr *local = NULL; @@ -409,6 +412,17 @@ com->ac_errno = -1; + /* connected already? */ + ph1 = getph1byaddrwop(src, dst); + if (ph1 != NULL) { + event_list = &ph1->evt_listeners; + if (ph1->status == PHASE1ST_ESTABLISHED) + com->ac_errno = EEXIST; + else + com->ac_errno = 0; + break; + } + /* search appropreate configuration */ rmconf = getrmconf(dst); if (rmconf == NULL) { @@ -459,9 +473,11 @@ "%s\n", saddrwop2str(remote)); /* begin ident mode */ - if (isakmp_ph1begin_i(rmconf, remote, local) < 0) + ph1 = isakmp_ph1begin_i(rmconf, remote, local); + if (ph1 == NULL) goto out1; + event_list = &ph1->evt_listeners; com->ac_errno = 0; out1: if (local != NULL) @@ -471,8 +487,105 @@ break; } case ADMIN_PROTO_AH: - case ADMIN_PROTO_ESP: + case ADMIN_PROTO_ESP: { + struct ph2handle *iph2; + struct secpolicy *sp_out = NULL, *sp_in = NULL; + struct policyindex spidx; + + com->ac_errno = -1; + + /* got outbound policy */ + memset(&spidx, 0, sizeof(spidx)); + spidx.dir = IPSEC_DIR_OUTBOUND; + memcpy(&spidx.src, src, sizeof(spidx.src)); + memcpy(&spidx.dst, dst, sizeof(spidx.dst)); + spidx.prefs = ndx->prefs; + spidx.prefd = ndx->prefd; + spidx.ul_proto = ndx->ul_proto; + + sp_out = getsp_r(&spidx); + if (sp_out) { + plog(LLV_DEBUG, LOCATION, NULL, + "suitable outbound SP found: %s.\n", + spidx2str(&sp_out->spidx)); + } else { + com->ac_errno = ENOENT; + plog(LLV_NOTIFY, LOCATION, NULL, + "no outbound policy found: %s\n", + spidx2str(&spidx)); + break; + } + + iph2 = getph2byid(src, dst, sp_out->id); + if (iph2 != NULL) { + event_list = &iph2->evt_listeners; + if (iph2->status == PHASE2ST_ESTABLISHED) + com->ac_errno = EEXIST; + else + com->ac_errno = 0; + break; + } + + /* get inbound policy */ + memset(&spidx, 0, sizeof(spidx)); + spidx.dir = IPSEC_DIR_INBOUND; + memcpy(&spidx.src, dst, sizeof(spidx.src)); + memcpy(&spidx.dst, src, sizeof(spidx.dst)); + spidx.prefs = ndx->prefd; + spidx.prefd = ndx->prefs; + spidx.ul_proto = ndx->ul_proto; + + sp_in = getsp_r(&spidx); + if (sp_in) { + plog(LLV_DEBUG, LOCATION, NULL, + "suitable inbound SP found: %s.\n", + spidx2str(&sp_in->spidx)); + } else { + com->ac_errno = ENOENT; + plog(LLV_NOTIFY, LOCATION, NULL, + "no inbound policy found: %s\n", + spidx2str(&spidx)); + break; + } + + /* allocate a phase 2 */ + iph2 = newph2(); + if (iph2 == NULL) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to allocate phase2 entry.\n"); + break; + } + iph2->side = INITIATOR; + iph2->satype = admin2pfkey_proto(com->ac_proto); + iph2->spid = sp_out->id; + iph2->seq = pk_getseq(); + iph2->status = PHASE2ST_STATUS2; + + /* set end addresses of SA */ + iph2->dst = dupsaddr(dst); + iph2->src = dupsaddr(src); + if (iph2->dst == NULL || iph2->src == NULL) { + delph2(iph2); + break; + } + + if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) { + delph2(iph2); + break; + } + + insph2(iph2); + if (isakmp_post_acquire(iph2) < 0) { + unbindph12(iph2); + remph2(iph2); + delph2(iph2); + break; + } + + event_list = &iph2->evt_listeners; + com->ac_errno = 0; break; + } default: /* ignore */ com->ac_errno = -1; @@ -489,7 +602,8 @@ if ((error = admin_reply(so2, com, buf)) != 0) goto out; - error = 0; + if (send_events || event_list != NULL) + error = evt_subscribe(event_list, so2); out: if (buf != NULL) vfree(buf); Index: ipsec-tools-cvs/src/racoon/racoonctl.8 =================================================================== --- ipsec-tools-cvs.orig/src/racoon/racoonctl.8 2008-01-04 15:17:50.000000000 +0200 +++ ipsec-tools-cvs/src/racoon/racoonctl.8 2008-01-04 15:18:21.000000000 +0200 @@ -55,17 +55,17 @@ .Nm establish-sa .Op Fl u Ar identity +.Op Fl w .Ar saopts .Nm vpn-connect -.Op Fl u identity +.Op Fl u Ar identity .Ar vpn_gateway .Nm vpn-disconnect .Ar vpn_gateway .Nm show-event -.Op Fl l .Nm logout-user .Ar login @@ -104,6 +104,8 @@ either ISAKMP SAs, IPsec ESP SAs, IPsec AH SAs, or all IPsec SAs. .It Xo establish-sa .Oo Fl u Ar username +.Oc +.Oo Fl w .Oc Ar saopts .Xc Establish an SA, either an ISAKMP SA, IPsec ESP SA, or IPsec AH SA. @@ -115,6 +117,11 @@ .Ar username and these credentials will be used in the Xauth exchange. .Pp +Specifying +.Fl w +will make racoonctl wait until the SA is actually established or +an error occurs. +.Pp .Ar saopts has the following format: .Bl -tag -width Bl @@ -135,16 +142,9 @@ This is a particular case of the previous command. It will kill all SAs associated with .Ar vpn_gateway . -.It show-event Op Fl l -Dump all events reported by -.Xr racoon 8 , -then quit. -The -.Fl l -flag causes -.Nm -to not stop once all the events have been read, but rather to loop -awaiting and reporting new events. +.It show-event +Listen for all events reported by +.Xr racoon 8 . .It logout-user Ar login Delete all SA established on behalf of the Xauth user .Ar login .