diff options
Diffstat (limited to 'patches/ipsec-tools-0.7.diff')
-rw-r--r-- | patches/ipsec-tools-0.7.diff | 1832 |
1 files changed, 1832 insertions, 0 deletions
diff --git a/patches/ipsec-tools-0.7.diff b/patches/ipsec-tools-0.7.diff new file mode 100644 index 0000000..1efba6c --- /dev/null +++ b/patches/ipsec-tools-0.7.diff @@ -0,0 +1,1832 @@ +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 <saopts>\n" +-" %s establish-sa [-u identity] <saopts>\n" ++" %s establish-sa [-u identity] [-w] <saopts>\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" + " <protocol>: \"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\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n" + " <ul_proto>\n" + " <family>: \"inet\" or \"inet6\"\n" +-" <ul_proto>: \"icmp\", \"tcp\", \"udp\" or \"any\"\n", +- pname, pname, pname, pname, pname, pname, pname); ++" <ul_proto>: \"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 . |