[package] add GRE support to ipsec-tools, so that opennhrp can work (#6926)
authorFlorian Fainelli <florian@openwrt.org>
Sun, 28 Mar 2010 16:58:17 +0000 (16:58 +0000)
committerFlorian Fainelli <florian@openwrt.org>
Sun, 28 Mar 2010 16:58:17 +0000 (16:58 +0000)
SVN-Revision: 20544

net/ipsec-tools/Makefile
net/ipsec-tools/patches/004-opennhrp.patch [new file with mode: 0644]

index 7b0577e..4aff93e 100644 (file)
@@ -10,7 +10,7 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=ipsec-tools
 PKG_VERSION:=0.7.3
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=@SF/ipsec-tools
diff --git a/net/ipsec-tools/patches/004-opennhrp.patch b/net/ipsec-tools/patches/004-opennhrp.patch
new file mode 100644 (file)
index 0000000..aa76f9f
--- /dev/null
@@ -0,0 +1,1659 @@
+Index: ipsec-tools-0.7.3/src/racoon/admin.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/admin.c  2009-04-20 15:32:57.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/admin.c       2010-03-28 17:07:57.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,6 +180,8 @@
+       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;
+@@ -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:
+@@ -393,17 +396,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;
+@@ -411,6 +414,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) {
+@@ -461,9 +475,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)
+@@ -473,8 +489,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;
+@@ -491,7 +604,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-0.7.3/src/racoon/evt.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/evt.c    2006-09-09 18:22:09.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/evt.c 2010-03-28 17:07:57.000000000 +0200
+@@ -46,113 +46,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;
++static EVT_LISTENER_LIST(evt_listeners);
++static EVT_LISTENER_LIST(evt_fds);
+-void
+-evt_push(src, dst, type, optdata)
+-      struct sockaddr *src;
+-      struct sockaddr *dst;
++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)
++      len = sizeof(struct admin_com) + sizeof(struct evt_common);
++      if (optdata != NULL)
++          len += optdata->l;
++
++      if ((e = racoon_malloc(len)) == NULL) {
++              plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate event: %s\n",
++              strerror(errno));
++              return 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);
++              }
++
++      }
++
++}
++
++void
++evt_generic(type, optdata)
++      int type;
++      vchar_t *optdata;
++{
++      struct evtdump *e;
++
++
++      if ((e = evtdump_create(type, optdata)) == NULL)
+               return;
+-      /* 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");
++      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;
+-      /* 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;
+-      }
+-
+-      len = sizeof(*evtdump);
+-      if (optdata)
+-              len += optdata->l;
+-
+-      if ((evtdump = racoon_malloc(len)) == NULL) {
+-              plog(LLV_ERROR, LOCATION, NULL, "Cannot record event: %s\n",
+-                  strerror(errno));
+-              return;
++      evtdump_broadcast(&ph2->evt_listeners, e);
++      if (ph1)
++              evtdump_broadcast(&ph1->evt_listeners, e);
++              evtdump_broadcast(&evt_listeners, e);
++
++              racoon_free(e);
+       }
+-      if ((evt = racoon_malloc(sizeof(*evt))) == NULL) {
+-              plog(LLV_ERROR, LOCATION, NULL, "Cannot record event: %s\n",
+-                  strerror(errno));
+-              racoon_free(evtdump);
+-              return;
++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;
+-      if ((evt = TAILQ_FIRST(&evtlist)) == NULL)
+-              return NULL;
++void
++evt_list_cleanup(list)
++      struct evt_listener_list *list;
++{
++      while (!LIST_EMPTY(list))
++              evt_unsubscribe(LIST_FIRST(list));
++}
+-      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);
++int
++evt_get_fdmask(nfds, fdset)
++      int nfds;
++      fd_set *fdset;
++{
++      struct evt_listener *l;
++      LIST_FOREACH(l, &evt_fds, fd_chain) {
++              FD_SET(l->fd, fdset);
++              if (l->fd + 1 > nfds)
++                      nfds = l->fd + 1;
+       }
++      return nfds;
++}
+-      return buf;
++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-0.7.3/src/racoon/evt.h
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/evt.h    2006-09-09 18:22:09.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/evt.h 2010-03-28 17:07:57.000000000 +0200
+@@ -34,12 +34,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 +62,46 @@
+ };
+ /* 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;
+-};
+-
+-TAILQ_HEAD(evtlist, evt);
+-
+-#define EVTLIST_MAX   32
++#define EVTT_RACOON_QUIT               0x0001
++#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));
++ 
++#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)
++#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) ;
+-#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
++#endif /* ENABLE_ADMINPORT */
+ #endif /* _EVT_H */
+Index: ipsec-tools-0.7.3/src/racoon/handler.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/handler.c        2009-04-20 15:25:27.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/handler.c     2010-03-28 17:07:57.000000000 +0200
+@@ -289,8 +289,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)
+Index: ipsec-tools-0.7.3/src/racoon/handler.h
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/handler.h        2008-01-11 15:12:01.000000000 +0100
++++ ipsec-tools-0.7.3/src/racoon/handler.h     2010-03-28 17:07:57.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-0.7.3/src/racoon/isakmp_agg.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/isakmp_agg.c     2006-09-30 23:49:37.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/isakmp_agg.c  2010-03-28 17:07:57.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-0.7.3/src/racoon/isakmp_base.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/isakmp_base.c    2006-10-02 23:51:33.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/isakmp_base.c 2010-03-28 17:07:57.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-0.7.3/src/racoon/isakmp.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/isakmp.c 2008-09-25 11:34:39.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/isakmp.c      2010-03-28 17:10:11.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"
+@@ -1015,7 +1018,7 @@
+ }
+ /* new negotiation of phase 1 for initiator */
+-int
++struct ph1handle *
+ isakmp_ph1begin_i(rmconf, remote, local)
+       struct remoteconf *rmconf;
+       struct sockaddr *remote, *local;
+@@ -1028,7 +1031,7 @@
+       /* get new entry to isakmp status table. */
+       iph1 = newph1();
+       if (iph1 == NULL)
+-              return -1;
++              return NULL;
+       iph1->status = PHASE1ST_START;
+       iph1->rmconf = rmconf;
+@@ -1043,7 +1046,7 @@
+ #ifdef ENABLE_HYBRID
+       if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) {
+               delph1(iph1);
+-              return -1;
++              return NULL;
+       }
+ #endif
+ #ifdef ENABLE_FRAG
+@@ -1059,7 +1062,7 @@
+       /* XXX copy remote address */
+       if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
+               delph1(iph1);
+-              return -1;
++              return NULL;
+       }
+       (void)insph1(iph1);
+@@ -1095,7 +1098,7 @@
+               remph1(iph1);
+               delph1(iph1);
+-              return -1;
++              return NULL;
+       }
+ #ifdef ENABLE_STATS
+@@ -1106,7 +1109,7 @@
+               timedelta(&start, &end));
+ #endif
+-      return 0;
++      return iph1;
+ }
+ /* new negotiation of phase 1 for responder */
+@@ -1887,8 +1890,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;
+       }
+@@ -1897,8 +1899,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;
+       }
+@@ -1947,7 +1948,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;
+       }
+@@ -1956,8 +1957,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;
+       }
+@@ -2048,7 +2048,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);
+@@ -2195,7 +2195,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;
+               }
+@@ -2228,6 +2228,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.
+  */
+@@ -2931,9 +2996,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-0.7.3/src/racoon/isakmp_cfg.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/isakmp_cfg.c     2008-11-27 16:25:20.000000000 +0100
++++ ipsec-tools-0.7.3/src/racoon/isakmp_cfg.c  2010-03-28 17:07:57.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-0.7.3/src/racoon/isakmp_ident.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/isakmp_ident.c   2006-10-02 23:41:59.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/isakmp_ident.c        2010-03-28 17:07:57.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-0.7.3/src/racoon/isakmp_inf.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/isakmp_inf.c     2009-05-18 19:07:46.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/isakmp_inf.c  2010-03-28 17:07:57.000000000 +0200
+@@ -510,8 +510,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);
+@@ -532,8 +531,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;
+@@ -1630,7 +1627,7 @@
+                       "DPD: remote (ISAKMP-SA spi=%s) seems to be dead.\n",
+                       isakmp_pindex(&iph1->index, 0));
+-              EVT_PUSH(iph1->local, iph1->remote, EVTT_DPD_TIMEOUT, NULL);
++              evt_phase1(iph1, EVTT_PHASE1_DPD_TIMEOUT, NULL);
+               purge_remote(iph1);
+               /* Do not reschedule here: phase1 is deleted,
+Index: ipsec-tools-0.7.3/src/racoon/isakmp_var.h
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/isakmp_var.h     2007-02-20 10:08:49.000000000 +0100
++++ ipsec-tools-0.7.3/src/racoon/isakmp_var.h  2010-03-28 17:07:57.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-0.7.3/src/racoon/isakmp_xauth.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/isakmp_xauth.c   2009-04-20 15:35:36.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/isakmp_xauth.c        2010-03-28 17:07:57.000000000 +0200
+@@ -1568,13 +1568,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-0.7.3/src/racoon/pfkey.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/pfkey.c  2008-03-05 23:14:24.000000000 +0100
++++ ipsec-tools-0.7.3/src/racoon/pfkey.c       2010-03-28 17:07:57.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"
+@@ -1266,6 +1267,7 @@
+       
+       /* 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,11 @@
+               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);
+Index: ipsec-tools-0.7.3/src/racoon/racoonctl.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/racoonctl.c      2009-04-20 15:32:57.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/racoonctl.c   2010-03-28 17:07:57.000000000 +0200
+@@ -135,26 +135,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 +182,7 @@
+       { IPPROTO_ICMP, "icmp" },
+       { IPPROTO_TCP,  "tcp" },
+       { IPPROTO_UDP,  "udp" },
++      { IPPROTO_GRE,  "gre" },
+       { 0, NULL },
+ };
+@@ -193,31 +192,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,13 +207,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"
+-"\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"
+ "\n"
+@@ -240,8 +223,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,53 +295,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;
+-}
+ /* %%% */
+ /*
+@@ -422,20 +376,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 +595,7 @@
+       char *id = NULL;
+       char *key = NULL;
+       struct admin_com_psk *acp;
++      int wait = 0;
+       if (ac < 1)
+               errx(1, "insufficient arguments");
+@@ -673,6 +616,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 +636,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 +702,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 +766,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;
+@@ -1337,84 +1288,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 
+               printf("%s", srcstr);
+       printf(" -> ");
+-      if ((dststr = saddr2str((struct sockaddr *)&evtdump->dst)) == NULL)
++      if ((dststr = saddr2str((struct sockaddr *)&evtdump->ec_ph1dst)) == NULL)
+               printf("unknown");
+       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;
+ }
+ /*
+@@ -1425,15 +1324,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);
+@@ -1487,7 +1385,7 @@
+               }
+       }
+       
+-      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");
+@@ -1508,11 +1406,6 @@
+               printf("\n");
+               racoon_free(banner);
+       }
+-      
+-      if (evt_filter & EVTF_CFG_STOP)
+-              evt_filter &= ~EVTF_LOOP;
+-      
+-      return;
+ }
+       
+@@ -1563,32 +1456,28 @@
+               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 evt_common))
++                      errx(1, "Short buffer\n");
+-              if (len < sizeof(struct evtdump))
+-                      errx(1, "Short buffer\n");              
+-
+-              /* Toss outdated events */
+-              evtdump = (struct evtdump *)buf;
+-              if (evtdump->timestamp < evt_start)
+-                      break;
+-
+-              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;
+       }
+@@ -1645,10 +1534,8 @@
+               break;
+       }
+-      close(so);
+       return 0;
+-    bad:
+-      close(so);
++bad:
+       return -1;
+ }
+Index: ipsec-tools-0.7.3/src/racoon/session.c
+===================================================================
+--- ipsec-tools-0.7.3.orig/src/racoon/session.c        2007-08-01 13:52:22.000000000 +0200
++++ ipsec-tools-0.7.3/src/racoon/session.c     2010-03-28 17:07:57.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