Date: Tue, 30 Oct 2007 10:32:26 -0500
From: Venkat Yekkirala <vyekkirala@TrustedCS.com>
To:  <dev@openswan.org>
Subject: [Openswan dev] [RFC 1/1] Labeled IPsec communication

Hello,

This patch adds the ability for pluto to negotiate labeled security
associations (racoon already supports this) for use by SELinux and
such LSMs.

For background please see, particularly under FUNCTIONAL DESCRIPTION at:
http://marc.info/?l=linux-netdev&m=115324352321637&w=2

This has yet to be modified to use a compatible format for the security
context for inter-operation with racoon, but I would appreciate your
review and comments.

Thanks,

venkat

---
--- openswan-2.4.9.orig/programs/pluto/whack.h	2004-12-15 19:22:44.000000000 -0600
+++ openswan-2.4.9/programs/pluto/whack.h	2007-10-30 08:40:08.000000000 -0500
@@ -127,6 +127,7 @@ struct whack_message {
     char *ike;		/* ike algo string (separated by commas) */
     char *pfsgroup;	/* pfsgroup will be "encapsulated" in esp string for pluto */
     char *esp;		/* esp algo string (separated by commas) */
+    char *ctx;		/* SELinux security context */
 
     /* for WHACK_KEY: */
     bool whack_key;
--- openswan-2.4.9.orig/programs/pluto/whack.c	2006-10-27 15:05:09.000000000 -0500
+++ openswan-2.4.9/programs/pluto/whack.c	2007-10-30 08:40:08.000000000 -0500
@@ -465,7 +465,8 @@ enum option_enums {
     CD_FORCEENCAPS,
     CD_IKE,
     CD_PFSGROUP,
-    CD_ESP	
+    CD_ESP,
+    CD_CTX
 #   define CD_LAST CD_ESP	/* last connection description */
 
 #ifdef DEBUG	/* must be last so others are less than 32 to fit in lset_t */
@@ -666,6 +667,7 @@ static const struct option long_opts[] =
     { "ike", required_argument, NULL, CD_IKE + OO },
     { "pfsgroup", required_argument, NULL, CD_PFSGROUP + OO },
     { "esp", required_argument, NULL, CD_ESP + OO },
+    { "ctx", required_argument, NULL, CD_CTX + OO },
 #ifdef DEBUG
     { "debug-none", no_argument, NULL, DBGOPT_NONE + OO },
     { "debug-all]", no_argument, NULL, DBGOPT_ALL + OO },
@@ -932,6 +934,7 @@ main(int argc, char **argv)
     msg.esp = NULL;
     msg.ike = NULL;
     msg.pfsgroup = NULL;
+    msg.ctx = NULL;
 
     msg.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
     msg.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT;
@@ -1525,6 +1528,10 @@ main(int argc, char **argv)
 	    msg.esp = optarg;
 	    continue;
 
+	case CD_CTX:	/* --ctx <context_str> */
+	    msg.ctx = optarg;
+	    continue;
+
 	case CD_CONNIPV4:
 	    if (LHAS(cd_seen, CD_CONNIPV6 - CD_FIRST))
 		diag("--ipv4 conflicts with --ipv6");
@@ -1806,6 +1813,7 @@ main(int argc, char **argv)
     || !pack_str(&msg.myid)		/* string 13 */
     || !pack_str(&msg.ike)		/* string 14 */
     || !pack_str(&msg.esp)		/* string 15 */
+    || !pack_str(&msg.ctx)		/* string 16 */
     || str_roof - next_str < (ptrdiff_t)msg.keyval.len)    /* chunk (sort of string 5) */
 	diag("too many bytes of strings to fit in message to pluto");
 
--- openswan-2.4.9.orig/programs/pluto/whacklib.c	2004-12-15 19:21:59.000000000 -0600
+++ openswan-2.4.9/programs/pluto/whacklib.c	2007-10-30 08:40:08.000000000 -0500
@@ -181,6 +181,7 @@ err_t unpack_whack_msg (struct whackpack
 	|| !unpack_str(wp, &wp->msg->myid)        /* string 15 */
     	|| !unpack_str(wp, &wp->msg->ike)         /* string 16 */
     	|| !unpack_str(wp, &wp->msg->esp)         /* string 17 */
+    	|| !unpack_str(wp, &wp->msg->ctx)         /* string 18 */
 
        || wp->str_roof - wp->str_next != (ptrdiff_t)wp->msg->keyval.len)	/* check chunk */
     {
--- openswan-2.4.9.orig/programs/pluto/connections.h	2005-11-16 19:44:12.000000000 -0600
+++ openswan-2.4.9/programs/pluto/connections.h	2007-10-30 08:40:08.000000000 -0500
@@ -176,6 +176,7 @@ struct spd_route {
     so_serial_t eroute_owner;
     enum routing_t routing;	/* level of routing in place */
     uint32_t reqid;
+    char *ctx;			/* SELinux security context */
 };
 
 struct connection {
@@ -265,7 +266,8 @@ extern void initiate_connection(const ch
 				, lset_t moredebug
 				, enum crypto_importance importance);
 extern void initiate_opportunistic(const ip_address *our_client
-    , const ip_address *peer_client, int transport_proto, bool held, int whackfd, err_t why);
+    , const ip_address *peer_client, int transport_proto, bool held, int whackfd
+    , char *ctx, err_t why);
 extern void terminate_connection(const char *nm);
 extern void release_connection(struct connection *c, bool relations);
 extern void delete_connection(struct connection *c, bool relations);
@@ -313,7 +315,8 @@ extern struct connection *
 find_connection_for_clients(struct spd_route **srp
 			    , const ip_address *our_client
 			    , const ip_address *peer_client
- 			    , int transport_proto);
+ 			    , int transport_proto
+ 			    , char *sa_ctx);
 			    
 
 /* instantiating routines
--- openswan-2.4.9.orig/programs/pluto/connections.c	2007-06-05 11:48:58.000000000 -0500
+++ openswan-2.4.9/programs/pluto/connections.c	2007-10-30 08:42:24.000000000 -0500
@@ -67,6 +67,7 @@
 #include "kernel_alg.h"
 #include "plutoalg.h"
 #include "xauth.h"
+#include "security.h"
 #ifdef NAT_TRAVERSAL
 #include "nat_traversal.h"
 #endif
@@ -883,6 +884,7 @@ unshare_connection_strings(struct connec
 	alg_info_addref(ESPTOINFO(c->alg_info_esp));
     }
 
+    c->spd.ctx = clone_str(c->spd.ctx, "security context");
 }
 
 static void
@@ -1236,6 +1238,8 @@ add_connection(const struct whack_messag
 
 	c->policy = wm->policy;
 
+	c->spd.ctx = NULL;
+
 	DBG(DBG_CONTROL,
 	    DBG_log("Added new connection %s with policy %s"
 		    , c->name
@@ -1398,6 +1402,8 @@ add_connection(const struct whack_messag
 	}
 #endif
 
+	c->spd.ctx = wm->ctx;
+
 	unshare_connection_strings(c);
 #ifdef KERNEL_ALG
 	alg_info_addref((struct alg_info *)c->alg_info_esp);
@@ -1410,7 +1416,8 @@ add_connection(const struct whack_messag
 	connect_to_host_pair(c);
 
 	/* log all about this connection */
-	openswan_log("added connection description \"%s\"", c->name);
+	openswan_log("added connection description \"%s\""
+			" with context \"%s\"", c->name, c->spd.ctx?:"");
 	DBG(DBG_CONTROL,
 	    char topo[CONNECTION_BUF];
 
@@ -1776,6 +1783,12 @@ fmt_conn_instance(const struct connectio
 	    *p++ = ' ';
 	    addrtot(&c->spd.that.host_addr, 0, p, ADDRTOT_BUF);
 	}
+
+	if (c->spd.ctx)
+	{
+	    p += strlen(p);
+	    snprintf(p, CONN_INST_BUF-strlen(buf)-1, " ctx=[%s]", c->spd.ctx);
+	}
     }
 }
 
@@ -1798,7 +1811,8 @@ struct connection *
 find_connection_for_clients(struct spd_route **srp,
 			    const ip_address *our_client,
 			    const ip_address *peer_client,
-			    int transport_proto)
+			    int transport_proto,
+			    char *sa_ctx)
 {
     struct connection *c = connections, *best = NULL;
     policy_prio_t best_prio = BOTTOM_PRIO;
@@ -1835,7 +1849,8 @@ find_connection_for_clients(struct spd_r
  	    && addrinsubnet(peer_client, &sr->that.client)
  	    && (!sr->this.protocol || transport_proto == sr->this.protocol)
  	    && (!sr->this.port || our_port == sr->this.port)
- 	    && (!sr->that.port || peer_port == sr->that.port))
+ 	    && (!sr->that.port || peer_port == sr->that.port)
+ 	    && security_polmatch(sa_ctx, sr->ctx))
 	    {
 		char cib[CONN_INST_BUF];
 		char cib2[CONN_INST_BUF];
@@ -2152,7 +2167,7 @@ initiate_connection(const char *name, in
 #endif
 	    {
 		ipsecdoi_initiate(whackfd, c, c->policy, 1
-				  , SOS_NOBODY, importance);
+				  , SOS_NOBODY, importance, NULL);
 		whackfd = NULL_FD;	/* protect from close */
 	    }
 	}
@@ -2345,13 +2360,13 @@ cannot_oppo(struct connection *c
 	    , b->failure_shunt
 	    , b->failure_shunt != 0
 	    , b->transport_proto
-	    , ugh);
+	    , ugh, c->spd.ctx);
     }
 #endif
 }
 
 static void initiate_opportunistic_body(struct find_oppo_bundle *b
-    , struct adns_continuation *ac, err_t ac_ugh);	/* forward */
+    , struct adns_continuation *ac, err_t ac_ugh, char *ctx);	/* forward */
 
 void
 initiate_opportunistic(const ip_address *our_client
@@ -2359,6 +2374,7 @@ initiate_opportunistic(const ip_address 
 , int transport_proto UNUSED
 , bool held
 , int whackfd
+, char *ctx
 , err_t why)
 {
     struct find_oppo_bundle b;
@@ -2373,7 +2389,7 @@ initiate_opportunistic(const ip_address 
     b.failure_shunt = 0;
     b.whackfd = whackfd;
     b.step = fos_start;
-    initiate_opportunistic_body(&b, NULL, NULL);
+    initiate_opportunistic_body(&b, NULL, NULL, ctx);
 }
 
 static void
@@ -2419,7 +2435,7 @@ continue_oppo(struct adns_continuation *
     if (!cr->b.failure_ok && ugh != NULL)
     {
 	c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client
-	    , cr->b.transport_proto);
+	    , cr->b.transport_proto, NULL);
 	cannot_oppo(c, &cr->b
 		    , builddiag("%s: %s", cr->b.want, ugh));
     }
@@ -2442,7 +2458,7 @@ continue_oppo(struct adns_continuation *
     }
     else
     {
-	initiate_opportunistic_body(&cr->b, &cr->ac, ugh);
+	initiate_opportunistic_body(&cr->b, &cr->ac, ugh, NULL);
 	whackfd = NULL_FD;	/* was handed off */
     }
 
@@ -2567,7 +2583,8 @@ check_txt_recs(enum myid_state try_state
 static void
 initiate_opportunistic_body(struct find_oppo_bundle *b
 , struct adns_continuation *ac
-, err_t ac_ugh)
+, err_t ac_ugh
+, char *ctx)
 {
     struct connection *c;
     struct spd_route *sr;
@@ -2588,9 +2605,10 @@ initiate_opportunistic_body(struct find_
     ourport = ntohs(portof(&b->our_client));
     hisport = ntohs(portof(&b->peer_client));
 
-    snprintf(demandbuf, 256, "initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s"
+    snprintf(demandbuf, 256, "initiate on demand from %s:%d to %s:%d"
+	     " proto=%d state: %s because: %s; ctx=[%s]"
 	     , ours, ourport, his, hisport, b->transport_proto
-	     , oppo_step_name[b->step], b->want);
+	     , oppo_step_name[b->step], b->want, ctx?:"");
     
     if(DBGP(DBG_OPPO)) {
 	DBG_log("%s", demandbuf);
@@ -2607,7 +2625,8 @@ initiate_opportunistic_body(struct find_
     else if ((c = find_connection_for_clients(&sr
 					      , &b->our_client
 					      , &b->peer_client
-					      , b->transport_proto)) == NULL)
+					      , b->transport_proto
+					      , ctx)) == NULL)
     {
 	/* No connection explicitly handles the clients and there
 	 * are no Opportunistic connections -- whine and give up.
@@ -2661,9 +2680,10 @@ initiate_opportunistic_body(struct find_
 	}
 #endif
 
+	    /* what should we do on failure? */
 	if(!loggedit) { openswan_log("%s", demandbuf); loggedit=TRUE; }
 	ipsecdoi_initiate(b->whackfd, c, c->policy, 1
-			  , SOS_NOBODY, pcim_local_crypto);
+			  , SOS_NOBODY, pcim_local_crypto, ctx);
 	b->whackfd = NULL_FD;	/* protect from close */
     }
     else
@@ -3059,7 +3079,8 @@ initiate_opportunistic_body(struct find_
 			    , BOTTOM_PRIO
 			    , SPI_PASS	/* fail into PASS */
 			    , TRUE, b->transport_proto
-			    , "no suitable connection");
+			    , "no suitable connection"
+			    , ctx);
 		    }
 #endif
 		}
@@ -3081,12 +3102,12 @@ initiate_opportunistic_body(struct find_
 #endif
 		    c->gw_info->key->last_tried_time = now();
 		    DBG(DBG_CONTROL,
-			DBG_log("initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s"
+			DBG_log("initiate on demand from %s:%d to %s:%d proto=%d state: %s because: %s; ctx=[%s]"
 				 , ours, ourport, his, hisport, b->transport_proto
-				 , oppo_step_name[b->step], b->want));
+				 , oppo_step_name[b->step], b->want, ctx?:""));
 
 		    ipsecdoi_initiate(b->whackfd, c, c->policy, 1
-				      , SOS_NOBODY, pcim_local_crypto);
+				      , SOS_NOBODY, pcim_local_crypto, NULL);
 		    b->whackfd = NULL_FD;	/* protect from close */
 		}
 	    }
@@ -3104,8 +3125,8 @@ initiate_opportunistic_body(struct find_
 
 	    addrtot(&b->our_client, 0, ours, sizeof(ours));
 	    addrtot(&b->peer_client, 0, his, sizeof(his));
-	    DBG_log("initiate on demand from %s to %s new state: %s with ugh: %s"
-		    , ours, his, oppo_step_name[b->step], ugh ? ugh : "ok");
+	    DBG_log("initiate on demand from %s to %s new state: %s with ugh: %s; ctx=[%s]"
+		    , ours, his, oppo_step_name[b->step], ugh ? ugh : "ok", ctx?:"");
 	});
 
 	if (ugh != NULL)
--- openswan-2.4.9.orig/programs/pluto/kernel.h	2005-07-25 21:11:23.000000000 -0500
+++ openswan-2.4.9/programs/pluto/kernel.h	2007-10-30 08:40:08.000000000 -0500
@@ -99,8 +99,15 @@ struct kernel_ops {
 			   const struct pfkey_proto_info *proto_info,
 			   time_t use_lifetime,
 			   unsigned int op,
-			   const char *text_said);
-	bool (*add_sa)(const struct kernel_sa *sa, bool replace);
+			   const char *text_said,
+			   u_int8_t ctx_doi,
+			   u_int8_t ctx_alg,
+			   char *ctx,
+			   u_int16_t ctx_len);
+	bool (*add_sa)(const struct kernel_sa *sa, bool replace,
+			   u_int8_t ctx_doi,
+			   u_int8_t ctx_alg,
+			   char *ctx);
 	bool (*grp_sa)(const struct kernel_sa *sa_outer,
 		       const struct kernel_sa *sa_inner);
 	bool (*del_sa)(const struct kernel_sa *sa);
@@ -151,6 +158,7 @@ extern void show_shunt_status(void);
 extern void record_and_initiate_opportunistic(const ip_subnet *
 					      , const ip_subnet *
 					      , int transport_proto
+					      , char * ctx
 					      , const char *why);
 
 extern void init_kernel(void);
@@ -169,7 +177,8 @@ extern bool replace_bare_shunt(const ip_
 			       , ipsec_spi_t shunt_spi	/* in host order! */
 			       , bool repl
 			       , int transport_proto
-			       , const char *why);
+			       , const char *why
+			       , const char *ctx);
 
 extern bool assign_hold(struct connection *c
 			, struct spd_route *sr
--- openswan-2.4.9.orig/programs/pluto/kernel.c	2006-10-02 20:16:11.000000000 -0500
+++ openswan-2.4.9/programs/pluto/kernel.c	2007-10-30 08:40:08.000000000 -0500
@@ -187,6 +187,7 @@ void
 record_and_initiate_opportunistic(const ip_subnet *ours
                                   , const ip_subnet *his
                                   , int transport_proto
+                                  , char *ctx
                                   , const char *why)
 {
     passert(samesubnettype(ours, his));
@@ -222,7 +223,7 @@ record_and_initiate_opportunistic(const 
 
         networkof(ours, &src);
         networkof(his, &dst);
-        initiate_opportunistic(&src, &dst, transport_proto, TRUE, NULL_FD, "acquire");
+        initiate_opportunistic(&src, &dst, transport_proto, TRUE, NULL_FD, ctx, "acquire");
     }
 
     /*
@@ -715,7 +716,11 @@ raw_eroute(const ip_address *this_host
            , const struct pfkey_proto_info *proto_info
            , time_t use_lifetime
            , unsigned int op
-           , const char *opname USED_BY_DEBUG)
+           , const char *opname USED_BY_DEBUG
+           , u_int8_t ctx_doi
+           , u_int8_t ctx_alg
+           , char *ctx
+           , u_int16_t ctx_len)
 {
     char text_said[SATOT_BUF];
     int sport = ntohs(portof(&this_client->addr));
@@ -730,9 +735,9 @@ raw_eroute(const ip_address *this_host
 
             subnettot(this_client, 0, mybuf, sizeof(mybuf));
             subnettot(that_client, 0, peerbuf, sizeof(peerbuf));
-            DBG_log("%s eroute %s:%d --%d-> %s:%d => %s (raw_eroute)"
+            DBG_log("%s eroute %s:%d --%d-> %s:%d => %s (raw_eroute) ctx=[%s]"
                     , opname, mybuf, sport, transport_proto, peerbuf, dport
-                    , text_said);
+                    , text_said, ctx?:"");
         });
 
     return kernel_ops->raw_eroute(this_host, this_client
@@ -740,7 +745,8 @@ raw_eroute(const ip_address *this_host
                                   , spi, proto
                                   , transport_proto
                                   , satype, proto_info
-                                  , use_lifetime, op, text_said);
+                                  , use_lifetime, op, text_said
+                                  , ctx_doi, ctx_alg, ctx, ctx_len);
 }
 
 /* test to see if %hold remains */
@@ -768,7 +774,8 @@ replace_bare_shunt(const ip_address *src
                    , ipsec_spi_t shunt_spi      /* in host order! */
                    , bool repl  /* if TRUE, replace; if FALSE, delete */
                    , int transport_proto
-                   , const char *why)
+                   , const char *why
+                   , const char *ctx)
 {
     ip_subnet this_client, that_client;
     const ip_address *null_host = aftoinfo(addrtypeof(src))->any;
@@ -777,6 +784,10 @@ replace_bare_shunt(const ip_address *src
     happy(addrtosubnet(src, &this_client));
     happy(addrtosubnet(dst, &that_client));
 
+    DBG(DBG_CONTROL,
+	DBG_log("IN replace_bare_shunt (%d) (%s) (ctx=%s)", repl,
+		why?:"", ctx?:""));
+
     /*
      * if the transport protocol is not the wildcard, then we need
      * to look for a host<->host shunt, and replace that with the
@@ -807,7 +818,8 @@ replace_bare_shunt(const ip_address *src
                                        , htonl(shunt_spi), SA_INT
                                        , transport_proto
                                        , SADB_X_SATYPE_INT, narrow_proto_info
-                                       , SHUNT_PATIENCE, ERO_REPLACE, why))
+                                       , SHUNT_PATIENCE, ERO_REPLACE, why
+                                       , 1, 1, ctx, ctx?strlen(ctx):0))
                             {
                                 struct bare_shunt *bs = alloc_thing(struct bare_shunt, "bare shunt");
                                 
@@ -834,7 +846,8 @@ replace_bare_shunt(const ip_address *src
                        , SA_INT
                        , transport_proto
                        , SADB_X_SATYPE_INT, narrow_proto_info
-                       , SHUNT_PATIENCE, ERO_ADD, why))
+                       , SHUNT_PATIENCE, ERO_ADD, why
+                       , 1, 1, ctx, ctx?strlen(ctx):0))
             {
                 struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client, &that_client
                                                            , transport_proto);
@@ -856,7 +869,8 @@ replace_bare_shunt(const ip_address *src
                        , htonl(shunt_spi), SA_INT
                        , 0 /* transport_proto */
                        , SADB_X_SATYPE_INT, narrow_proto_info
-                       , SHUNT_PATIENCE, op, why))
+                       , SHUNT_PATIENCE, op, why
+                       , 1, 1, ctx, ctx?strlen(ctx):0))
             {
                 struct bare_shunt **bs_pp = bare_shunt_ptr(&this_client
                                                            , &that_client, 0);
@@ -913,7 +927,8 @@ eroute_connection(struct spd_route *sr
                       , proto
                       , sr->this.protocol
                       , satype
-                      , proto_info, 0, op, buf2);
+                      , proto_info, 0, op, buf2
+                      , 1, 1, sr->ctx, sr->ctx?strlen(sr->ctx):0);
 }
 
 /* assign a bare hold to a connection */
@@ -987,7 +1002,8 @@ assign_hold(struct connection *c USED_BY
                                 , SPI_HOLD
                                 , FALSE
                                 , transport_proto
-                                , "delete narrow %hold"))
+                                , "delete narrow %hold"
+                                , sr->ctx))
             return FALSE;
     }
     sr->routing = rn;
@@ -1199,7 +1215,8 @@ shunt_eroute(struct connection *c
                         , SADB_X_SATYPE_INT, broad_proto_info
                         , 0      /* use lifetime */
                         , op | (SADB_X_SAFLAGS_INFLOW << ERO_FLAG_SHIFT)
-                        , opname);
+                        , opname
+                        , 1, 1, c->spd.ctx, c->spd.ctx? strlen(c->spd.ctx):0);
     }
     return eroute_connection(sr, htonl(spi), SA_INT, SADB_X_SATYPE_INT
         , broad_proto_info, op, opname) && ok;
@@ -1502,7 +1519,7 @@ scan_proc_shunts(void)
         (void) replace_bare_shunt(&src, &dst
             , BOTTOM_PRIO       /* not used because we are deleting.  This value is a filler */
             , SPI_PASS  /* not used because we are deleting.  This value is a filler */
-            , FALSE, p->transport_proto, "delete expired bare shunts");
+            , FALSE, p->transport_proto, "delete expired bare shunts", NULL);
         expired = p->next;
         pfree(p);
     }
@@ -1625,8 +1642,8 @@ setup_half_ipsec_sa(struct state *st, bo
         said_next->satype = SADB_X_SATYPE_IPIP;
         said_next->text_said = text_said;
 
-        if (!kernel_ops->add_sa(said_next, replace)) {
-	    DBG_log("add_sa tunnel failed");
+        if (!kernel_ops->add_sa(said_next, replace, 1, 1, st->ctx)) {
+	    DBG_log("add_sa tunnel failed [ctx=%s]", st->ctx?:"");
             goto fail;
 	}
 
@@ -1669,8 +1686,8 @@ setup_half_ipsec_sa(struct state *st, bo
         said_next->reqid = c->spd.reqid + 2;
         said_next->text_said = text_said;
 
-        if (!kernel_ops->add_sa(said_next, replace)) {
-	    DBG_log("add_sa ipcomp failed");
+        if (!kernel_ops->add_sa(said_next, replace, 1, 1, st->ctx)) {
+	    DBG_log("add_sa ipcomp failed [ctx=%s]", st->ctx?:"");
             goto fail;
 	}
 
@@ -1862,8 +1879,10 @@ setup_half_ipsec_sa(struct state *st, bo
 #endif  
         said_next->text_said = text_said;
 
-        if (!kernel_ops->add_sa(said_next, replace))
+        if (!kernel_ops->add_sa(said_next, replace, 1, 1, st->ctx)) {
+	    DBG_log("add_sa esp failed [ctx=%s]", st->ctx?:"");
             goto fail;
+	}
 
         said_next++;
 
@@ -1913,8 +1932,10 @@ setup_half_ipsec_sa(struct state *st, bo
         said_next->reqid = c->spd.reqid;
         said_next->text_said = text_said;
 
-        if (!kernel_ops->add_sa(said_next, replace))
+        if (!kernel_ops->add_sa(said_next, replace, 1, 1, st->ctx)) {
+	    DBG_log("add_sa ah failed [ctx=%s]", st->ctx?:"");
             goto fail;
+	}
 
         said_next++;
 
@@ -1984,7 +2005,8 @@ setup_half_ipsec_sa(struct state *st, bo
                               , c->spd.this.protocol
                               , satype
                               , proto_info, 0
-                              , ERO_ADD_INBOUND, "add inbound");
+                              , ERO_ADD_INBOUND, "add inbound"
+                              , 1, 1, c->spd.ctx, c->spd.ctx? strlen(c->spd.ctx):0);
         }
     }
 
@@ -2070,7 +2092,8 @@ teardown_half_ipsec_sa(struct state *st,
                           , c->spd.this.protocol
                           , SADB_SATYPE_UNSPEC
                           , narrow_proto_info, 0
-                          , ERO_DEL_INBOUND, "delete inbound");
+                          , ERO_DEL_INBOUND, "delete inbound"
+                          , 1, 1, c->spd.ctx, c->spd.ctx? strlen(c->spd.ctx):0);
     }
 
     if (!kernel_ops->grp_sa)
@@ -2524,7 +2547,8 @@ route_and_eroute(struct connection *c US
                     , SADB_X_SATYPE_INT
                     , narrow_proto_info
                     , SHUNT_PATIENCE
-                    , ERO_REPLACE, "restore");
+                    , ERO_REPLACE, "restore"
+                    , 1, 1, c->spd.ctx, c->spd.ctx? strlen(c->spd.ctx):0);
             }
             else if (ero != NULL)
             {
@@ -2706,6 +2730,8 @@ static bool update_nat_t_ipsec_esp_sa (s
         struct connection *c = st->st_connection;
         char text_said[SATOT_BUF];
         struct kernel_sa sa;
+	int ret;
+
         ip_address
                 src = inbound? c->spd.that.host_addr : c->spd.this.host_addr,
                 dst = inbound? c->spd.this.host_addr : c->spd.that.host_addr;
@@ -2729,8 +2755,11 @@ static bool update_nat_t_ipsec_esp_sa (s
         sa.natt_dport = natt_dport;
         sa.transid = st->st_esp.attrs.transid;
 
-        return kernel_ops->add_sa(&sa, TRUE);
-
+        ret = kernel_ops->add_sa(&sa, TRUE, 1, 1, st->ctx);
+        if (!ret)
+		DBG_log("add_sa failed for %s [ctx=%s]", __FUNCTION__,
+					st->ctx?:"");
+	return ret;
 }
 #endif
 
--- openswan-2.4.9.orig/programs/pluto/kernel_netlink.c	2006-10-03 00:32:55.000000000 -0500
+++ openswan-2.4.9/programs/pluto/kernel_netlink.c	2007-10-30 08:40:08.000000000 -0500
@@ -347,6 +347,11 @@ netlink_policy(struct nlmsghdr *hdr, boo
 	return TRUE;
     }
 
+    if (error == EEXIST)
+    {
+	return TRUE;
+    }
+
     loglog(RC_LOG_SERIOUS
 	, "ERROR: netlink %s response for flow %s included errno %d: %s"
 	, sparse_val_show(xfrm_type_names, hdr->nlmsg_type)
@@ -383,7 +388,11 @@ netlink_raw_eroute(const ip_address *thi
 		   , const struct pfkey_proto_info *proto_info
 		   , time_t use_lifetime UNUSED
 		   , unsigned int op
-		   , const char *text_said)
+		   , const char *text_said
+		   , u_int8_t ctx_doi
+		   , u_int8_t ctx_alg
+		   , char *ctx_str
+		   , u_int16_t ctx_len)
 {
     struct {
 	struct nlmsghdr n;
@@ -490,6 +499,28 @@ netlink_raw_eroute(const ip_address *thi
 	req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.p)));
     }
 
+    if (ctx_str)
+    {
+	struct rtattr *attr;
+	struct xfrm_user_sec_ctx ctx;
+
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.len = sizeof(ctx) + strlen(ctx_str);
+	ctx.ctx_alg = ctx_alg;
+	ctx.ctx_doi = ctx_doi;
+	ctx.ctx_len = strlen(ctx_str);
+
+	attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
+	attr->rta_type = XFRMA_SEC_CTX;
+	attr->rta_len = RTA_ALIGN(RTA_LENGTH(ctx.len));
+	memcpy(RTA_DATA(attr), &ctx, sizeof(ctx));
+	memcpy(((char *)(RTA_DATA(attr)))+sizeof(ctx), ctx_str, strlen(ctx_str));
+	DBG(DBG_CONTROL | DBG_KLIPS,
+	    DBG_log("%s: policy= %d; INSERTING CTX (%s) (%d) (%d) (%d)!!!", __FUNCTION__,
+		policy, ctx_str, ctx.len, attr->rta_len, RTA_ALIGN(attr->rta_len)));
+	req.n.nlmsg_len += attr->rta_len;
+    }
+
     if (policy == IPSEC_POLICY_IPSEC && (op & ERO_MASK) != ERO_DELETE)
     {
 	struct rtattr *attr;
@@ -521,6 +552,9 @@ netlink_raw_eroute(const ip_address *thi
 	memcpy(RTA_DATA(attr), tmpl, attr->rta_len);
 	attr->rta_len = RTA_LENGTH(attr->rta_len);
 	req.n.nlmsg_len += attr->rta_len;
+	DBG(DBG_CONTROL | DBG_KLIPS,
+	    DBG_log("%s: RTA LEN FOR TMPL IS  (%d) (%d)!!!", __FUNCTION__,
+			attr->rta_len, RTA_ALIGN(attr->rta_len)));
     }
 
     enoent_ok = FALSE;
@@ -569,7 +603,10 @@ netlink_raw_eroute(const ip_address *thi
  * @return bool True if successfull
  */
 static bool
-netlink_add_sa(const struct kernel_sa *sa, bool replace)
+netlink_add_sa(const struct kernel_sa *sa, bool replace
+		   , u_int8_t ctx_doi
+		   , u_int8_t ctx_alg
+		   , char *ctx_str)
 {
     struct {
 	struct nlmsghdr n;
@@ -677,6 +714,28 @@ netlink_add_sa(const struct kernel_sa *s
 	attr = (struct rtattr *)((char *)attr + attr->rta_len);
     }
 
+    if (ctx_str)
+    {
+	struct xfrm_user_sec_ctx ctx;
+
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.len = sizeof(ctx) + strlen(ctx_str);
+	ctx.ctx_alg = ctx_alg;
+	ctx.ctx_doi = ctx_doi;
+	ctx.ctx_len = strlen(ctx_str);
+
+	attr->rta_type = XFRMA_SEC_CTX;
+	attr->rta_len = RTA_ALIGN(RTA_LENGTH(ctx.len));
+	memcpy(RTA_DATA(attr), &ctx, sizeof(ctx));
+	memcpy(((char *)(RTA_DATA(attr)))+sizeof(ctx), ctx_str, strlen(ctx_str));
+	DBG(DBG_CONTROL | DBG_KLIPS,
+	    DBG_log("%s: CTX (%s) (%d) (%d) (%d)!!!", __FUNCTION__, ctx_str, ctx.len,
+			attr->rta_len, RTA_ALIGN(attr->rta_len)));
+	req.n.nlmsg_len += attr->rta_len;
+	attr = (struct rtattr *)((char *)attr + attr->rta_len);
+    }
+
+
 #ifdef NAT_TRAVERSAL
     if (sa->natt_type)
     {
@@ -793,6 +852,9 @@ netlink_acquire(struct nlmsghdr *n)
     unsigned family;
     unsigned transport_proto;
     err_t ugh = NULL;
+    int hdr_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct xfrm_user_acquire)));
+    int attrlen = n->nlmsg_len - hdr_len;
+    char *ctx_str = NULL;
 
     if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*acquire)))
     {
@@ -846,7 +908,42 @@ netlink_acquire(struct nlmsghdr *n)
 	return;
     }
 
-    record_and_initiate_opportunistic(&ours, &his, transport_proto
+    if (attrlen)
+    {
+	struct rtattr *attr = (struct rtattr *) (((char *) n) + hdr_len);
+	struct xfrm_user_sec_ctx *uctx = NULL;
+
+	while (RTA_OK(attr, attrlen))
+	{
+		if (attr->rta_type == XFRMA_SEC_CTX)
+		{
+			uctx = RTA_DATA(attr);
+			break;
+		}
+		else
+			attr = RTA_NEXT(attr, attrlen);
+	}
+
+	if (uctx)
+	{
+		/* TODO: verify lengths, etc. */
+		ctx_str = (char *) alloc_bytes(uctx->ctx_len+1,
+					"acquire context string");
+		if (!ctx_str)
+		{
+			loglog(RC_LOG_SERIOUS,
+				"Couldn't allocate for acquire ctx str; len (%d)",
+				uctx->ctx_len+1);
+			return;
+		}
+		strncpy(ctx_str, ((char *)uctx) + sizeof(*uctx), uctx->ctx_len);
+		ctx_str[uctx->ctx_len] = '\0';
+		DBG(DBG_CONTROL | DBG_KLIPS,
+		    DBG_log("ACQUIRE CTX STR (%s) !!!", ctx_str));
+	}
+    }
+
+    record_and_initiate_opportunistic(&ours, &his, transport_proto, ctx_str
 				      , "%acquire-netlink");
 }
 
@@ -876,7 +973,8 @@ netlink_shunt_expire(struct xfrm_userpol
 		       , SPI_PASS
 		       , FALSE
 		       , transport_proto
-		       , "delete expired bare shunt");
+		       , "delete expired bare shunt"
+		       , NULL);
 }
 
 static void
@@ -893,6 +991,9 @@ netlink_policy_expire(struct nlmsghdr *n
 	char data[1024];
     } rsp;
 
+    DBG(DBG_CONTROL | DBG_KLIPS,
+	DBG_log("netlink_policy_expire!!!"));
+
     if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*upe)))
     {
 	openswan_log("netlink_policy_expire got message with length %lu < %lu bytes; ignore message"
@@ -949,6 +1050,8 @@ netlink_policy_expire(struct nlmsghdr *n
     switch (upe->pol.dir)
     {
     case XFRM_POLICY_OUT:
+    DBG(DBG_CONTROL | DBG_KLIPS,
+	DBG_log("netlink_policy_expire invoking netlink_shunt_expire!!!"));
 	netlink_shunt_expire(&rsp.pol);
 	break;
     }
--- openswan-2.4.9.orig/programs/pluto/kernel_noklips.c	2005-07-08 12:55:28.000000000 -0500
+++ openswan-2.4.9/programs/pluto/kernel_noklips.c	2007-10-30 08:40:08.000000000 -0500
@@ -83,14 +83,21 @@ noklips_raw_eroute(const ip_address *thi
 		   , const struct pfkey_proto_info *proto_info UNUSED
 		   , time_t use_lifetime UNUSED
 		   , unsigned int op UNUSED
-		   , const char *text_said UNUSED)
+		   , const char *text_said UNUSED
+		   , u_int8_t ctx_doi UNUSED
+		   , u_int8_t ctx_alg UNUSED
+		   , char *ctx_str UNUSED
+		   , u_int16_t ctx_len UNUSED)
 {
   return TRUE;
 }
 
 static bool
 noklips_add_sa(const struct kernel_sa *sa UNUSED
-	       , bool replace UNUSED)
+	       , bool replace UNUSED
+	       , u_int8_t ctx_doi UNUSED
+	       , u_int8_t ctx_alg UNUSED
+	       , char *ctx_str UNUSED)
 {
   return TRUE;
 }
--- openswan-2.4.9.orig/programs/pluto/linux26/xfrm.h	2003-09-01 20:14:07.000000000 -0500
+++ openswan-2.4.9/programs/pluto/linux26/xfrm.h	2007-10-30 08:40:08.000000000 -0500
@@ -1,7 +1,7 @@
 #ifndef _LINUX_XFRM_H
 #define _LINUX_XFRM_H
 
-#include <stdint.h>
+#include <linux/types.h>
 
 /* All of the structures in this file may not change size as they are
  * passed into the kernel from userspace via netlink sockets.
@@ -12,8 +12,8 @@
  */
 typedef union
 {
-	uint32_t	a4;
-	uint32_t	a6[4];
+	__u32		a4;
+	__u32		a6[4];
 } xfrm_address_t;
 
 /* Ident of a specific xfrm_state. It is used on input to lookup
@@ -23,55 +23,71 @@ typedef union
 struct xfrm_id
 {
 	xfrm_address_t	daddr;
-	uint32_t	spi;
-	uint8_t		proto;
+	__u32		spi;
+	__u8		proto;
 };
 
+struct xfrm_sec_ctx {
+	__u8	ctx_doi;
+	__u8	ctx_alg;
+	__u16	ctx_len;
+	__u32	ctx_sid;
+	char	ctx_str[0];
+};
+
+/* Security Context Domains of Interpretation */
+#define XFRM_SC_DOI_RESERVED 0
+#define XFRM_SC_DOI_LSM 1
+
+/* Security Context Algorithms */
+#define XFRM_SC_ALG_RESERVED 0
+#define XFRM_SC_ALG_SELINUX 1
+
 /* Selector, used as selector both on policy rules (SPD) and SAs. */
 
 struct xfrm_selector
 {
 	xfrm_address_t	daddr;
 	xfrm_address_t	saddr;
-	uint16_t	dport;
-	uint16_t	dport_mask;
-	uint16_t	sport;
-	uint16_t	sport_mask;
-	uint16_t	family;
-	uint8_t		prefixlen_d;
-	uint8_t		prefixlen_s;
-	uint8_t		proto;
-	int		ifindex;
-	uid_t		user;
+	__u16	dport;
+	__u16	dport_mask;
+	__u16	sport;
+	__u16	sport_mask;
+	__u16	family;
+	__u8	prefixlen_d;
+	__u8	prefixlen_s;
+	__u8	proto;
+	int	ifindex;
+	uid_t	user;
 };
 
-#define XFRM_INF (~(uint64_t)0)
+#define XFRM_INF (~(__u64)0)
 
 struct xfrm_lifetime_cfg
 {
-	uint64_t	soft_byte_limit;
-	uint64_t	hard_byte_limit;
-	uint64_t	soft_packet_limit;
-	uint64_t	hard_packet_limit;
-	uint64_t	soft_add_expires_seconds;
-	uint64_t	hard_add_expires_seconds;
-	uint64_t	soft_use_expires_seconds;
-	uint64_t	hard_use_expires_seconds;
+	__u64	soft_byte_limit;
+	__u64	hard_byte_limit;
+	__u64	soft_packet_limit;
+	__u64	hard_packet_limit;
+	__u64	soft_add_expires_seconds;
+	__u64	hard_add_expires_seconds;
+	__u64	soft_use_expires_seconds;
+	__u64	hard_use_expires_seconds;
 };
 
 struct xfrm_lifetime_cur
 {
-	uint64_t	bytes;
-	uint64_t	packets;
-	uint64_t	add_time;
-	uint64_t	use_time;
+	__u64	bytes;
+	__u64	packets;
+	__u64	add_time;
+	__u64	use_time;
 };
 
 struct xfrm_replay_state
 {
-	uint32_t	oseq;
-	uint32_t	seq;
-	uint32_t	bitmap;
+	__u32	oseq;
+	__u32	seq;
+	__u32	bitmap;
 };
 
 struct xfrm_algo {
@@ -81,9 +97,9 @@ struct xfrm_algo {
 };
 
 struct xfrm_stats {
-	uint32_t	replay_window;
-	uint32_t	replay;
-	uint32_t	integrity_failed;
+	__u32	replay_window;
+	__u32	replay;
+	__u32	integrity_failed;
 };
 
 enum
@@ -102,46 +118,103 @@ enum
 	XFRM_SHARE_UNIQUE	/* Use once */
 };
 
-/* Netlink configuration messages.  */
-#define XFRM_MSG_BASE		0x10
-
-#define XFRM_MSG_NEWSA		(XFRM_MSG_BASE + 0)
-#define XFRM_MSG_DELSA		(XFRM_MSG_BASE + 1)
-#define XFRM_MSG_GETSA		(XFRM_MSG_BASE + 2)
-
-#define XFRM_MSG_NEWPOLICY	(XFRM_MSG_BASE + 3)
-#define XFRM_MSG_DELPOLICY	(XFRM_MSG_BASE + 4)
-#define XFRM_MSG_GETPOLICY	(XFRM_MSG_BASE + 5)
-
-#define XFRM_MSG_ALLOCSPI	(XFRM_MSG_BASE + 6)
-#define XFRM_MSG_ACQUIRE	(XFRM_MSG_BASE + 7)
-#define XFRM_MSG_EXPIRE		(XFRM_MSG_BASE + 8)
+#define XFRM_MODE_TRANSPORT 0
+#define XFRM_MODE_TUNNEL 1
+#define XFRM_MODE_MAX 2
 
-#define XFRM_MSG_UPDPOLICY	(XFRM_MSG_BASE + 9)
-#define XFRM_MSG_UPDSA		(XFRM_MSG_BASE + 10)
-
-#define XFRM_MSG_POLEXPIRE	(XFRM_MSG_BASE + 11)
+/* Netlink configuration messages.  */
+enum {
+	XFRM_MSG_BASE = 0x10,
 
-#define XFRM_MSG_MAX		(XFRM_MSG_POLEXPIRE+1)
+	XFRM_MSG_NEWSA = 0x10,
+#define XFRM_MSG_NEWSA XFRM_MSG_NEWSA
+	XFRM_MSG_DELSA,
+#define XFRM_MSG_DELSA XFRM_MSG_DELSA
+	XFRM_MSG_GETSA,
+#define XFRM_MSG_GETSA XFRM_MSG_GETSA
+
+	XFRM_MSG_NEWPOLICY,
+#define XFRM_MSG_NEWPOLICY XFRM_MSG_NEWPOLICY
+	XFRM_MSG_DELPOLICY,
+#define XFRM_MSG_DELPOLICY XFRM_MSG_DELPOLICY
+	XFRM_MSG_GETPOLICY,
+#define XFRM_MSG_GETPOLICY XFRM_MSG_GETPOLICY
+
+	XFRM_MSG_ALLOCSPI,
+#define XFRM_MSG_ALLOCSPI XFRM_MSG_ALLOCSPI
+	XFRM_MSG_ACQUIRE,
+#define XFRM_MSG_ACQUIRE XFRM_MSG_ACQUIRE
+	XFRM_MSG_EXPIRE,
+#define XFRM_MSG_EXPIRE XFRM_MSG_EXPIRE
+
+	XFRM_MSG_UPDPOLICY,
+#define XFRM_MSG_UPDPOLICY XFRM_MSG_UPDPOLICY
+	XFRM_MSG_UPDSA,
+#define XFRM_MSG_UPDSA XFRM_MSG_UPDSA
+
+	XFRM_MSG_POLEXPIRE,
+#define XFRM_MSG_POLEXPIRE XFRM_MSG_POLEXPIRE
+
+	XFRM_MSG_FLUSHSA,
+#define XFRM_MSG_FLUSHSA XFRM_MSG_FLUSHSA
+	XFRM_MSG_FLUSHPOLICY,
+#define XFRM_MSG_FLUSHPOLICY XFRM_MSG_FLUSHPOLICY
+
+	XFRM_MSG_NEWAE,
+#define XFRM_MSG_NEWAE XFRM_MSG_NEWAE
+	XFRM_MSG_GETAE,
+#define XFRM_MSG_GETAE XFRM_MSG_GETAE
+	__XFRM_MSG_MAX
+};
+#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
+
+#define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
+
+/*
+ * Generic LSM security context for comunicating to user space
+ * NOTE: Same format as sadb_x_sec_ctx
+ */
+struct xfrm_user_sec_ctx {
+	__u16			len;
+	__u16			exttype;
+	__u8			ctx_alg;  /* LSMs: e.g., selinux == 1 */
+	__u8			ctx_doi;
+	__u16			ctx_len;
+};
 
 struct xfrm_user_tmpl {
 	struct xfrm_id		id;
-	uint16_t		family;
+	__u16			family;
 	xfrm_address_t		saddr;
-	uint32_t		reqid;
-	uint8_t			mode;
-	uint8_t			share;
-	uint8_t			optional;
-	uint32_t		aalgos;
-	uint32_t		ealgos;
-	uint32_t		calgos;
+	__u32			reqid;
+	__u8			mode;
+	__u8			share;
+	__u8			optional;
+	__u32			aalgos;
+	__u32			ealgos;
+	__u32			calgos;
 };
 
 struct xfrm_encap_tmpl {
-	uint16_t		encap_type;
-	uint16_t		encap_sport;
-	uint16_t		encap_dport;
-	xfrm_address_t		encap_oa;
+	__u16		encap_type;
+	__u16		encap_sport;
+	__u16		encap_dport;
+	xfrm_address_t	encap_oa;
+};
+
+/* AEVENT flags  */
+enum xfrm_ae_ftype_t {
+	XFRM_AE_UNSPEC,
+	XFRM_AE_RTHR=1,	/* replay threshold*/
+	XFRM_AE_RVAL=2, /* replay value */
+	XFRM_AE_LVAL=4, /* lifetime value */
+	XFRM_AE_ETHR=8, /* expiry timer threshold */
+	XFRM_AE_CR=16, /* Event cause is replay update */
+	XFRM_AE_CE=32, /* Event cause is timer expiry */
+	XFRM_AE_CU=64, /* Event cause is policy update */
+	__XFRM_AE_MAX
+
+#define XFRM_AE_MAX (__XFRM_AE_MAX - 1)
 };
 
 /* Netlink message attributes.  */
@@ -152,8 +225,16 @@ enum xfrm_attr_type_t {
 	XFRMA_ALG_COMP,		/* struct xfrm_algo */
 	XFRMA_ENCAP,		/* struct xfrm_algo + struct xfrm_encap_tmpl */
 	XFRMA_TMPL,		/* 1 or more struct xfrm_user_tmpl */
+	XFRMA_SA,
+	XFRMA_POLICY,
+	XFRMA_SEC_CTX,		/* struct xfrm_sec_ctx */
+	XFRMA_LTIME_VAL,
+	XFRMA_REPLAY_VAL,
+	XFRMA_REPLAY_THRESH,
+	XFRMA_ETIMER_THRESH,
+	__XFRMA_MAX
 
-#define XFRMA_MAX XFRMA_TMPL
+#define XFRMA_MAX (__XFRMA_MAX - 1)
 };
 
 struct xfrm_usersa_info {
@@ -163,47 +244,54 @@ struct xfrm_usersa_info {
 	struct xfrm_lifetime_cfg	lft;
 	struct xfrm_lifetime_cur	curlft;
 	struct xfrm_stats		stats;
-	uint32_t			seq;
-	uint32_t			reqid;
-	uint16_t			family;
-	uint8_t				mode; /* 0=transport,1=tunnel */
-	uint8_t				replay_window;
-	uint8_t				flags;
+	__u32				seq;
+	__u32				reqid;
+	__u16				family;
+	__u8				mode; /* 0=transport,1=tunnel */
+	__u8				replay_window;
+	__u8				flags;
 #define XFRM_STATE_NOECN	1
+#define XFRM_STATE_DECAP_DSCP	2
+#define XFRM_STATE_NOPMTUDISC	4
 };
 
 struct xfrm_usersa_id {
 	xfrm_address_t			daddr;
-	uint32_t			spi;
-	uint16_t			family;
-	uint8_t				proto;
+	__u32				spi;
+	__u16				family;
+	__u8				proto;
+};
+
+struct xfrm_aevent_id {
+	struct xfrm_usersa_id		sa_id;
+	__u32				flags;
 };
 
 struct xfrm_userspi_info {
 	struct xfrm_usersa_info		info;
-	uint32_t			min;
-	uint32_t			max;
+	__u32				min;
+	__u32				max;
 };
 
 struct xfrm_userpolicy_info {
 	struct xfrm_selector		sel;
 	struct xfrm_lifetime_cfg	lft;
 	struct xfrm_lifetime_cur	curlft;
-	uint32_t			priority;
-	uint32_t			index;
-	uint8_t				dir;
-	uint8_t				action;
+	__u32				priority;
+	__u32				index;
+	__u8				dir;
+	__u8				action;
 #define XFRM_POLICY_ALLOW	0
 #define XFRM_POLICY_BLOCK	1
-	uint8_t				flags;
+	__u8				flags;
 #define XFRM_POLICY_LOCALOK	1	/* Allow user to override global policy */
-	uint8_t				share;
+	__u8				share;
 };
 
 struct xfrm_userpolicy_id {
 	struct xfrm_selector		sel;
-	uint32_t			index;
-	uint8_t				dir;
+	__u32				index;
+	__u8				dir;
 };
 
 struct xfrm_user_acquire {
@@ -211,23 +299,47 @@ struct xfrm_user_acquire {
 	xfrm_address_t			saddr;
 	struct xfrm_selector		sel;
 	struct xfrm_userpolicy_info	policy;
-	uint32_t			aalgos;
-	uint32_t			ealgos;
-	uint32_t			calgos;
-	uint32_t			seq;
+	__u32				aalgos;
+	__u32				ealgos;
+	__u32				calgos;
+	__u32				seq;
 };
 
 struct xfrm_user_expire {
 	struct xfrm_usersa_info		state;
-	uint8_t				hard;
+	__u8				hard;
 };
 
 struct xfrm_user_polexpire {
 	struct xfrm_userpolicy_info	pol;
-	uint8_t				hard;
+	__u8				hard;
 };
 
+struct xfrm_usersa_flush {
+	__u8				proto;
+};
+
+/* backwards compatibility for userspace */
 #define XFRMGRP_ACQUIRE		1
 #define XFRMGRP_EXPIRE		2
+#define XFRMGRP_SA		4
+#define XFRMGRP_POLICY		8
+
+enum xfrm_nlgroups {
+	XFRMNLGRP_NONE,
+#define XFRMNLGRP_NONE		XFRMNLGRP_NONE
+	XFRMNLGRP_ACQUIRE,
+#define XFRMNLGRP_ACQUIRE	XFRMNLGRP_ACQUIRE
+	XFRMNLGRP_EXPIRE,
+#define XFRMNLGRP_EXPIRE	XFRMNLGRP_EXPIRE
+	XFRMNLGRP_SA,
+#define XFRMNLGRP_SA		XFRMNLGRP_SA
+	XFRMNLGRP_POLICY,
+#define XFRMNLGRP_POLICY	XFRMNLGRP_POLICY
+	XFRMNLGRP_AEVENTS,
+#define XFRMNLGRP_AEVENTS	XFRMNLGRP_AEVENTS
+	__XFRMNLGRP_MAX
+};
+#define XFRMNLGRP_MAX	(__XFRMNLGRP_MAX - 1)
 
 #endif /* _LINUX_XFRM_H */
--- openswan-2.4.9.orig/programs/pluto/linux26/netlink.h	2003-07-31 18:49:00.000000000 -0500
+++ openswan-2.4.9/programs/pluto/linux26/netlink.h	2007-10-30 08:40:08.000000000 -0500
@@ -1,21 +1,28 @@
 #ifndef __LINUX_NETLINK_H
 #define __LINUX_NETLINK_H
 
-#include <stdint.h>
-#include <sys/socket.h> /* for sa_family_t */
+#include <linux/socket.h> /* for sa_family_t */
+#include <linux/types.h>
 
 #define NETLINK_ROUTE		0	/* Routing/device hook				*/
-#define NETLINK_SKIP		1	/* Reserved for ENskip  			*/
+#define NETLINK_UNUSED		1	/* Unused number				*/
 #define NETLINK_USERSOCK	2	/* Reserved for user mode socket protocols 	*/
 #define NETLINK_FIREWALL	3	/* Firewalling hook				*/
-#define NETLINK_TCPDIAG		4	/* TCP socket monitoring			*/
+#define NETLINK_INET_DIAG	4	/* INET socket monitoring			*/
 #define NETLINK_NFLOG		5	/* netfilter/iptables ULOG */
 #define NETLINK_XFRM		6	/* ipsec */
-#define NETLINK_ARPD		8
-#define NETLINK_ROUTE6		11	/* af_inet6 route comm channel */
+#define NETLINK_SELINUX		7	/* SELinux event notifications */
+#define NETLINK_ISCSI		8	/* Open-iSCSI */
+#define NETLINK_AUDIT		9	/* auditing */
+#define NETLINK_FIB_LOOKUP	10	
+#define NETLINK_CONNECTOR	11
+#define NETLINK_NETFILTER	12	/* netfilter subsystem */
 #define NETLINK_IP6_FW		13
 #define NETLINK_DNRTMSG		14	/* DECnet routing messages */
-#define NETLINK_TAPBASE		16	/* 16 to 31 are ethertap */
+#define NETLINK_KOBJECT_UEVENT	15	/* Kernel messages to userspace */
+#define NETLINK_GENERIC		16
+/* leave room for NETLINK_DM (DM Events) */
+#define NETLINK_SCSITRANSPORT	18	/* SCSI Transports */
 
 #define MAX_LINKS 32		
 
@@ -23,17 +30,17 @@ struct sockaddr_nl
 {
 	sa_family_t	nl_family;	/* AF_NETLINK	*/
 	unsigned short	nl_pad;		/* zero		*/
-	uint32_t	nl_pid;		/* process pid	*/
-       	uint32_t	nl_groups;	/* multicast groups mask */
+	__u32		nl_pid;		/* process pid	*/
+       	__u32		nl_groups;	/* multicast groups mask */
 };
 
 struct nlmsghdr
 {
-	uint32_t	nlmsg_len;	/* Length of message including header */
-	uint16_t	nlmsg_type;	/* Message content */
-	uint16_t	nlmsg_flags;	/* Additional flags */
-	uint32_t	nlmsg_seq;	/* Sequence number */
-	uint32_t	nlmsg_pid;	/* Sending process PID */
+	__u32		nlmsg_len;	/* Length of message including header */
+	__u16		nlmsg_type;	/* Message content */
+	__u16		nlmsg_flags;	/* Additional flags */
+	__u32		nlmsg_seq;	/* Sequence number */
+	__u32		nlmsg_pid;	/* Sending process PID */
 };
 
 /* Flags values */
@@ -66,12 +73,14 @@ struct nlmsghdr
 
 #define NLMSG_ALIGNTO	4
 #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
-#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#define NLMSG_HDRLEN	 ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
 #define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
 #define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
 #define NLMSG_NEXT(nlh,len)	 ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
 				  (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
-#define NLMSG_OK(nlh,len) ((len) > 0 && (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
+#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
+			   (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
 			   (nlh)->nlmsg_len <= (len))
 #define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
 
@@ -80,11 +89,48 @@ struct nlmsghdr
 #define NLMSG_DONE		0x3	/* End of a dump	*/
 #define NLMSG_OVERRUN		0x4	/* Data lost		*/
 
+#define NLMSG_MIN_TYPE		0x10	/* < 0x10: reserved control messages */
+
 struct nlmsgerr
 {
 	int		error;
 	struct nlmsghdr msg;
 };
 
+#define NETLINK_ADD_MEMBERSHIP	1
+#define NETLINK_DROP_MEMBERSHIP	2
+#define NETLINK_PKTINFO		3
+
+struct nl_pktinfo
+{
+	__u32	group;
+};
+
 #define NET_MAJOR 36		/* Major 36 is reserved for networking 						*/
+
+enum {
+	NETLINK_UNCONNECTED = 0,
+	NETLINK_CONNECTED,
+};
+
+/*
+ *  <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
+ * +---------------------+- - -+- - - - - - - - - -+- - -+
+ * |        Header       | Pad |     Payload       | Pad |
+ * |   (struct nlattr)   | ing |                   | ing |
+ * +---------------------+- - -+- - - - - - - - - -+- - -+
+ *  <-------------- nlattr->nla_len -------------->
+ */
+
+struct nlattr
+{
+	__u16           nla_len;
+	__u16           nla_type;
+};
+
+#define NLA_ALIGNTO		4
+#define NLA_ALIGN(len)		(((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
+#define NLA_HDRLEN		((int) NLA_ALIGN(sizeof(struct nlattr)))
+
+
 #endif	/* __LINUX_NETLINK_H */
--- openswan-2.4.9.orig/programs/pluto/linux26/rtnetlink.h	2003-07-31 18:49:00.000000000 -0500
+++ openswan-2.4.9/programs/pluto/linux26/rtnetlink.h	2007-10-30 08:40:08.000000000 -0500
@@ -1,11 +1,7 @@
 #ifndef __LINUX_RTNETLINK_H
 #define __LINUX_RTNETLINK_H
 
-#include "netlink.h"
-#include <stdint.h>
-
-#define RTNL_DEBUG 1
-
+#include <linux/netlink.h>
 
 /****
  *		Routing/neighbour discovery messages.
@@ -13,45 +9,103 @@
 
 /* Types of messages */
 
-#define RTM_BASE	0x10
-
-#define	RTM_NEWLINK	(RTM_BASE+0)
-#define	RTM_DELLINK	(RTM_BASE+1)
-#define	RTM_GETLINK	(RTM_BASE+2)
-#define	RTM_SETLINK	(RTM_BASE+3)
-
-#define	RTM_NEWADDR	(RTM_BASE+4)
-#define	RTM_DELADDR	(RTM_BASE+5)
-#define	RTM_GETADDR	(RTM_BASE+6)
-
-#define	RTM_NEWROUTE	(RTM_BASE+8)
-#define	RTM_DELROUTE	(RTM_BASE+9)
-#define	RTM_GETROUTE	(RTM_BASE+10)
-
-#define	RTM_NEWNEIGH	(RTM_BASE+12)
-#define	RTM_DELNEIGH	(RTM_BASE+13)
-#define	RTM_GETNEIGH	(RTM_BASE+14)
-
-#define	RTM_NEWRULE	(RTM_BASE+16)
-#define	RTM_DELRULE	(RTM_BASE+17)
-#define	RTM_GETRULE	(RTM_BASE+18)
-
-#define	RTM_NEWQDISC	(RTM_BASE+20)
-#define	RTM_DELQDISC	(RTM_BASE+21)
-#define	RTM_GETQDISC	(RTM_BASE+22)
-
-#define	RTM_NEWTCLASS	(RTM_BASE+24)
-#define	RTM_DELTCLASS	(RTM_BASE+25)
-#define	RTM_GETTCLASS	(RTM_BASE+26)
-
-#define	RTM_NEWTFILTER	(RTM_BASE+28)
-#define	RTM_DELTFILTER	(RTM_BASE+29)
-#define	RTM_GETTFILTER	(RTM_BASE+30)
-
-#define	RTM_MAX		(RTM_BASE+31)
+enum {
+	RTM_BASE	= 16,
+#define RTM_BASE	RTM_BASE
+
+	RTM_NEWLINK	= 16,
+#define RTM_NEWLINK	RTM_NEWLINK
+	RTM_DELLINK,
+#define RTM_DELLINK	RTM_DELLINK
+	RTM_GETLINK,
+#define RTM_GETLINK	RTM_GETLINK
+	RTM_SETLINK,
+#define RTM_SETLINK	RTM_SETLINK
+
+	RTM_NEWADDR	= 20,
+#define RTM_NEWADDR	RTM_NEWADDR
+	RTM_DELADDR,
+#define RTM_DELADDR	RTM_DELADDR
+	RTM_GETADDR,
+#define RTM_GETADDR	RTM_GETADDR
+
+	RTM_NEWROUTE	= 24,
+#define RTM_NEWROUTE	RTM_NEWROUTE
+	RTM_DELROUTE,
+#define RTM_DELROUTE	RTM_DELROUTE
+	RTM_GETROUTE,
+#define RTM_GETROUTE	RTM_GETROUTE
+
+	RTM_NEWNEIGH	= 28,
+#define RTM_NEWNEIGH	RTM_NEWNEIGH
+	RTM_DELNEIGH,
+#define RTM_DELNEIGH	RTM_DELNEIGH
+	RTM_GETNEIGH,
+#define RTM_GETNEIGH	RTM_GETNEIGH
+
+	RTM_NEWRULE	= 32,
+#define RTM_NEWRULE	RTM_NEWRULE
+	RTM_DELRULE,
+#define RTM_DELRULE	RTM_DELRULE
+	RTM_GETRULE,
+#define RTM_GETRULE	RTM_GETRULE
+
+	RTM_NEWQDISC	= 36,
+#define RTM_NEWQDISC	RTM_NEWQDISC
+	RTM_DELQDISC,
+#define RTM_DELQDISC	RTM_DELQDISC
+	RTM_GETQDISC,
+#define RTM_GETQDISC	RTM_GETQDISC
+
+	RTM_NEWTCLASS	= 40,
+#define RTM_NEWTCLASS	RTM_NEWTCLASS
+	RTM_DELTCLASS,
+#define RTM_DELTCLASS	RTM_DELTCLASS
+	RTM_GETTCLASS,
+#define RTM_GETTCLASS	RTM_GETTCLASS
+
+	RTM_NEWTFILTER	= 44,
+#define RTM_NEWTFILTER	RTM_NEWTFILTER
+	RTM_DELTFILTER,
+#define RTM_DELTFILTER	RTM_DELTFILTER
+	RTM_GETTFILTER,
+#define RTM_GETTFILTER	RTM_GETTFILTER
+
+	RTM_NEWACTION	= 48,
+#define RTM_NEWACTION   RTM_NEWACTION
+	RTM_DELACTION,
+#define RTM_DELACTION   RTM_DELACTION
+	RTM_GETACTION,
+#define RTM_GETACTION   RTM_GETACTION
+
+	RTM_NEWPREFIX	= 52,
+#define RTM_NEWPREFIX	RTM_NEWPREFIX
+	RTM_GETPREFIX	= 54,
+#define RTM_GETPREFIX	RTM_GETPREFIX
+
+	RTM_GETMULTICAST = 58,
+#define RTM_GETMULTICAST RTM_GETMULTICAST
+
+	RTM_GETANYCAST	= 62,
+#define RTM_GETANYCAST	RTM_GETANYCAST
+
+	RTM_NEWNEIGHTBL	= 64,
+#define RTM_NEWNEIGHTBL	RTM_NEWNEIGHTBL
+	RTM_GETNEIGHTBL	= 66,
+#define RTM_GETNEIGHTBL	RTM_GETNEIGHTBL
+	RTM_SETNEIGHTBL,
+#define RTM_SETNEIGHTBL	RTM_SETNEIGHTBL
+
+	__RTM_MAX,
+#define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
+};
+
+#define RTM_NR_MSGTYPES	(RTM_MAX + 1 - RTM_BASE)
+#define RTM_NR_FAMILIES	(RTM_NR_MSGTYPES >> 2)
+#define RTM_FAM(cmd)	(((cmd) - RTM_BASE) >> 2)
 
 /* 
-   Generic structure for encapsulation optional route information.
+   Generic structure for encapsulation of optional route information.
    It is reminiscent of sockaddr, but with sa_family replaced
    with attribute type.
  */
@@ -66,7 +120,8 @@ struct rtattr
 
 #define RTA_ALIGNTO	4
 #define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
-#define RTA_OK(rta,len) ((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \
+#define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \
+			 (rta)->rta_len >= sizeof(struct rtattr) && \
 			 (rta)->rta_len <= (len))
 #define RTA_NEXT(rta,attrlen)	((attrlen) -= RTA_ALIGN((rta)->rta_len), \
 				 (struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len)))
@@ -79,7 +134,7 @@ struct rtattr
 
 
 /******************************************************************************
- *		Definitions used in routing table administation.
+ *		Definitions used in routing table administration.
  ****/
 
 struct rtmsg
@@ -115,9 +170,10 @@ enum
 	RTN_THROW,		/* Not in this table		*/
 	RTN_NAT,		/* Translate this address	*/
 	RTN_XRESOLVE,		/* Use external resolver	*/
+	__RTN_MAX
 };
 
-#define RTN_MAX RTN_XRESOLVE
+#define RTN_MAX (__RTN_MAX - 1)
 
 
 /* rtm_protocol */
@@ -130,18 +186,20 @@ enum
 #define RTPROT_STATIC	4	/* Route installed by administrator	*/
 
 /* Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
-   they just passed from user and back as is.
+   they are just passed from user and back as is.
    It will be used by hypothetical multiple routing daemons.
    Note that protocol values should be standardized in order to
    avoid conflicts.
  */
 
 #define RTPROT_GATED	8	/* Apparently, GateD */
-#define RTPROT_RA	9	/* RDISC/ND router advertisments */
+#define RTPROT_RA	9	/* RDISC/ND router advertisements */
 #define RTPROT_MRT	10	/* Merit MRT */
 #define RTPROT_ZEBRA	11	/* Zebra */
 #define RTPROT_BIRD	12	/* BIRD */
 #define RTPROT_DNROUTED	13	/* DECnet routing daemon */
+#define RTPROT_XORP	14	/* XORP */
+#define RTPROT_NTK	15	/* Netsukuku */
 
 /* rtm_scope
 
@@ -169,6 +227,7 @@ enum rt_scope_t
 #define RTM_F_NOTIFY		0x100	/* Notify user of route change	*/
 #define RTM_F_CLONED		0x200	/* This route is cloned		*/
 #define RTM_F_EQUALIZE		0x400	/* Multipath equalizer: NI	*/
+#define RTM_F_PREFIX		0x800	/* Prefix addresses		*/
 
 /* Reserved table identifiers */
 
@@ -178,10 +237,9 @@ enum rt_class_t
 /* User defined values */
 	RT_TABLE_DEFAULT=253,
 	RT_TABLE_MAIN=254,
-	RT_TABLE_LOCAL=255
+	RT_TABLE_LOCAL=255,
+	RT_TABLE_MAX=0xFFFFFFFF
 };
-#define RT_TABLE_MAX RT_TABLE_LOCAL
-
 
 
 /* Routing message attributes */
@@ -202,17 +260,20 @@ enum rtattr_type_t
 	RTA_FLOW,
 	RTA_CACHEINFO,
 	RTA_SESSION,
+	RTA_MP_ALGO,
+	RTA_TABLE,
+	__RTA_MAX
 };
 
-#define RTA_MAX RTA_SESSION
+#define RTA_MAX (__RTA_MAX - 1)
 
 #define RTM_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
 #define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
 
 /* RTM_MULTIPATH --- array of struct rtnexthop.
  *
- * "struct rtnexthop" describres all necessary nexthop information,
- * i.e. parameters of path to a destination via this nextop.
+ * "struct rtnexthop" describes all necessary nexthop information,
+ * i.e. parameters of path to a destination via this nexthop.
  *
  * At the moment it is impossible to set different prefsrc, mtu, window
  * and rtt for different paths from multipath.
@@ -247,16 +308,16 @@ struct rtnexthop
 
 struct rta_cacheinfo
 {
-	uint32_t	rta_clntref;
-	uint32_t	rta_lastuse;
-	int32_t	rta_expires;
-	uint32_t	rta_error;
-	uint32_t	rta_used;
+	__u32	rta_clntref;
+	__u32	rta_lastuse;
+	__s32	rta_expires;
+	__u32	rta_error;
+	__u32	rta_used;
 
 #define RTNETLINK_HAVE_PEERINFO 1
-	uint32_t	rta_id;
-	uint32_t	rta_ts;
-	uint32_t	rta_tsage;
+	__u32	rta_id;
+	__u32	rta_ts;
+	__u32	rta_tsage;
 };
 
 /* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
@@ -283,27 +344,41 @@ enum
 #define RTAX_ADVMSS RTAX_ADVMSS
 	RTAX_REORDERING,
 #define RTAX_REORDERING RTAX_REORDERING
+	RTAX_HOPLIMIT,
+#define RTAX_HOPLIMIT RTAX_HOPLIMIT
+	RTAX_INITCWND,
+#define RTAX_INITCWND RTAX_INITCWND
+	RTAX_FEATURES,
+#define RTAX_FEATURES RTAX_FEATURES
+	__RTAX_MAX
 };
 
-#define RTAX_MAX RTAX_REORDERING
+#define RTAX_MAX (__RTAX_MAX - 1)
+
+#define RTAX_FEATURE_ECN	0x00000001
+#define RTAX_FEATURE_SACK	0x00000002
+#define RTAX_FEATURE_TIMESTAMP	0x00000004
+#define RTAX_FEATURE_ALLFRAG	0x00000008
 
 struct rta_session
 {
-	uint8_t	proto;
+	__u8	proto;
+	__u8	pad1;
+	__u16	pad2;
 
 	union {
 		struct {
-			uint16_t	sport;
-			uint16_t	dport;
+			__u16	sport;
+			__u16	dport;
 		} ports;
 
 		struct {
-			uint8_t		type;
-			uint8_t		code;
-			uint16_t	ident;
+			__u8	type;
+			__u8	code;
+			__u16	ident;
 		} icmpt;
 
-		uint32_t		spi;
+		__u32		spi;
 	} u;
 };
 
@@ -329,10 +404,12 @@ enum
 	IFA_LABEL,
 	IFA_BROADCAST,
 	IFA_ANYCAST,
-	IFA_CACHEINFO
+	IFA_CACHEINFO,
+	IFA_MULTICAST,
+	__IFA_MAX
 };
 
-#define IFA_MAX IFA_CACHEINFO
+#define IFA_MAX (__IFA_MAX - 1)
 
 /* ifa_flags */
 
@@ -345,8 +422,10 @@ enum
 
 struct ifa_cacheinfo
 {
-	int32_t	ifa_prefered;
-	int32_t	ifa_valid;
+	__u32	ifa_prefered;
+	__u32	ifa_valid;
+	__u32	cstamp; /* created timestamp, hundredths of seconds */
+	__u32	tstamp; /* updated timestamp, hundredths of seconds */
 };
 
 
@@ -371,9 +450,9 @@ struct ndmsg
 	unsigned char	ndm_pad1;
 	unsigned short	ndm_pad2;
 	int		ndm_ifindex;	/* Link index			*/
-	uint16_t	ndm_state;
-	uint8_t		ndm_flags;
-	uint8_t		ndm_type;
+	__u16		ndm_state;
+	__u8		ndm_flags;
+	__u8		ndm_type;
 };
 
 enum
@@ -381,10 +460,12 @@ enum
 	NDA_UNSPEC,
 	NDA_DST,
 	NDA_LLADDR,
-	NDA_CACHEINFO
+	NDA_CACHEINFO,
+	NDA_PROBES,
+	__NDA_MAX
 };
 
-#define NDA_MAX NDA_CACHEINFO
+#define NDA_MAX (__NDA_MAX - 1)
 
 #define NDA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
 #define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
@@ -415,12 +496,112 @@ enum
 
 struct nda_cacheinfo
 {
-	uint32_t		ndm_confirmed;
-	uint32_t		ndm_used;
-	uint32_t		ndm_updated;
-	uint32_t		ndm_refcnt;
+	__u32		ndm_confirmed;
+	__u32		ndm_used;
+	__u32		ndm_updated;
+	__u32		ndm_refcnt;
 };
 
+
+/*****************************************************************
+ *		Neighbour tables specific messages.
+ *
+ * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
+ * NLM_F_DUMP flag set. Every neighbour table configuration is
+ * spread over multiple messages to avoid running into message
+ * size limits on systems with many interfaces. The first message
+ * in the sequence transports all not device specific data such as
+ * statistics, configuration, and the default parameter set.
+ * This message is followed by 0..n messages carrying device
+ * specific parameter sets.
+ * Although the ordering should be sufficient, NDTA_NAME can be
+ * used to identify sequences. The initial message can be identified
+ * by checking for NDTA_CONFIG. The device specific messages do
+ * not contain this TLV but have NDTPA_IFINDEX set to the
+ * corresponding interface index.
+ *
+ * To change neighbour table attributes, send RTM_SETNEIGHTBL
+ * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
+ * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
+ * otherwise. Device specific parameter sets can be changed by
+ * setting NDTPA_IFINDEX to the interface index of the corresponding
+ * device.
+ ****/
+
+struct ndt_stats
+{
+	__u64		ndts_allocs;
+	__u64		ndts_destroys;
+	__u64		ndts_hash_grows;
+	__u64		ndts_res_failed;
+	__u64		ndts_lookups;
+	__u64		ndts_hits;
+	__u64		ndts_rcv_probes_mcast;
+	__u64		ndts_rcv_probes_ucast;
+	__u64		ndts_periodic_gc_runs;
+	__u64		ndts_forced_gc_runs;
+};
+
+enum {
+	NDTPA_UNSPEC,
+	NDTPA_IFINDEX,			/* u32, unchangeable */
+	NDTPA_REFCNT,			/* u32, read-only */
+	NDTPA_REACHABLE_TIME,		/* u64, read-only, msecs */
+	NDTPA_BASE_REACHABLE_TIME,	/* u64, msecs */
+	NDTPA_RETRANS_TIME,		/* u64, msecs */
+	NDTPA_GC_STALETIME,		/* u64, msecs */
+	NDTPA_DELAY_PROBE_TIME,		/* u64, msecs */
+	NDTPA_QUEUE_LEN,		/* u32 */
+	NDTPA_APP_PROBES,		/* u32 */
+	NDTPA_UCAST_PROBES,		/* u32 */
+	NDTPA_MCAST_PROBES,		/* u32 */
+	NDTPA_ANYCAST_DELAY,		/* u64, msecs */
+	NDTPA_PROXY_DELAY,		/* u64, msecs */
+	NDTPA_PROXY_QLEN,		/* u32 */
+	NDTPA_LOCKTIME,			/* u64, msecs */
+	__NDTPA_MAX
+};
+#define NDTPA_MAX (__NDTPA_MAX - 1)
+
+struct ndtmsg
+{
+	__u8		ndtm_family;
+	__u8		ndtm_pad1;
+	__u16		ndtm_pad2;
+};
+
+struct ndt_config
+{
+	__u16		ndtc_key_len;
+	__u16		ndtc_entry_size;
+	__u32		ndtc_entries;
+	__u32		ndtc_last_flush;	/* delta to now in msecs */
+	__u32		ndtc_last_rand;		/* delta to now in msecs */
+	__u32		ndtc_hash_rnd;
+	__u32		ndtc_hash_mask;
+	__u32		ndtc_hash_chain_gc;
+	__u32		ndtc_proxy_qlen;
+};
+
+enum {
+	NDTA_UNSPEC,
+	NDTA_NAME,			/* char *, unchangeable */
+	NDTA_THRESH1,			/* u32 */
+	NDTA_THRESH2,			/* u32 */
+	NDTA_THRESH3,			/* u32 */
+	NDTA_CONFIG,			/* struct ndt_config, read-only */
+	NDTA_PARMS,			/* nested TLV NDTPA_* */
+	NDTA_STATS,			/* struct ndt_stats, read-only */
+	NDTA_GC_INTERVAL,		/* u64, msecs */
+	__NDTA_MAX
+};
+#define NDTA_MAX (__NDTA_MAX - 1)
+
+#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \
+		     NLMSG_ALIGN(sizeof(struct ndtmsg))))
+#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
+
+
 /****
  *		General form of address family dependent message.
  ****/
@@ -449,6 +630,83 @@ struct ifinfomsg
 	unsigned	ifi_change;		/* IFF_* change mask */
 };
 
+/********************************************************************
+ *		prefix information 
+ ****/
+
+struct prefixmsg
+{
+	unsigned char	prefix_family;
+	unsigned char	prefix_pad1;
+	unsigned short	prefix_pad2;
+	int		prefix_ifindex;
+	unsigned char	prefix_type;
+	unsigned char	prefix_len;
+	unsigned char	prefix_flags;
+	unsigned char	prefix_pad3;
+};
+
+enum 
+{
+	PREFIX_UNSPEC,
+	PREFIX_ADDRESS,
+	PREFIX_CACHEINFO,
+	__PREFIX_MAX
+};
+
+#define PREFIX_MAX	(__PREFIX_MAX - 1)
+
+struct prefix_cacheinfo
+{
+	__u32	preferred_time;
+	__u32	valid_time;
+};
+
+/* The struct should be in sync with struct net_device_stats */
+struct rtnl_link_stats
+{
+	__u32	rx_packets;		/* total packets received	*/
+	__u32	tx_packets;		/* total packets transmitted	*/
+	__u32	rx_bytes;		/* total bytes received 	*/
+	__u32	tx_bytes;		/* total bytes transmitted	*/
+	__u32	rx_errors;		/* bad packets received		*/
+	__u32	tx_errors;		/* packet transmit problems	*/
+	__u32	rx_dropped;		/* no space in linux buffers	*/
+	__u32	tx_dropped;		/* no space available in linux	*/
+	__u32	multicast;		/* multicast packets received	*/
+	__u32	collisions;
+
+	/* detailed rx_errors: */
+	__u32	rx_length_errors;
+	__u32	rx_over_errors;		/* receiver ring buff overflow	*/
+	__u32	rx_crc_errors;		/* recved pkt with crc error	*/
+	__u32	rx_frame_errors;	/* recv'd frame alignment error */
+	__u32	rx_fifo_errors;		/* recv'r fifo overrun		*/
+	__u32	rx_missed_errors;	/* receiver missed packet	*/
+
+	/* detailed tx_errors */
+	__u32	tx_aborted_errors;
+	__u32	tx_carrier_errors;
+	__u32	tx_fifo_errors;
+	__u32	tx_heartbeat_errors;
+	__u32	tx_window_errors;
+	
+	/* for cslip etc */
+	__u32	rx_compressed;
+	__u32	tx_compressed;
+};
+
+/* The struct should be in sync with struct ifmap */
+struct rtnl_link_ifmap
+{
+	__u64	mem_start;
+	__u64	mem_end;
+	__u64	base_addr;
+	__u16	irq;
+	__u8	dma;
+	__u8	port;
+};
+
 enum
 {
 	IFLA_UNSPEC,
@@ -467,10 +725,21 @@ enum
 #define IFLA_MASTER IFLA_MASTER
 	IFLA_WIRELESS,		/* Wireless Extension event - see wireless.h */
 #define IFLA_WIRELESS IFLA_WIRELESS
+	IFLA_PROTINFO,		/* Protocol specific information for a link */
+#define IFLA_PROTINFO IFLA_PROTINFO
+	IFLA_TXQLEN,
+#define IFLA_TXQLEN IFLA_TXQLEN
+	IFLA_MAP,
+#define IFLA_MAP IFLA_MAP
+	IFLA_WEIGHT,
+#define IFLA_WEIGHT IFLA_WEIGHT
+	IFLA_OPERSTATE,
+	IFLA_LINKMODE,
+	__IFLA_MAX
 };
 
 
-#define IFLA_MAX IFLA_WIRELESS
+#define IFLA_MAX (__IFLA_MAX - 1)
 
 #define IFLA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
 #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
@@ -486,7 +755,7 @@ enum
 
    Comments:
    - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
-   - If neiher of these three flags are set;
+   - If neither of these three flags are set;
      the interface is NBMA.
 
    - IFF_MULTICAST does not mean anything special:
@@ -504,6 +773,28 @@ enum
    for IPIP tunnels, when route to endpoint is allowed to change)
  */
 
+/* Subtype attributes for IFLA_PROTINFO */
+enum
+{
+	IFLA_INET6_UNSPEC,
+	IFLA_INET6_FLAGS,	/* link flags			*/
+	IFLA_INET6_CONF,	/* sysctl parameters		*/
+	IFLA_INET6_STATS,	/* statistics			*/
+	IFLA_INET6_MCAST,	/* MC things. What of them?	*/
+	IFLA_INET6_CACHEINFO,	/* time values and max reasm size */
+	__IFLA_INET6_MAX
+};
+
+#define IFLA_INET6_MAX	(__IFLA_INET6_MAX - 1)
+
+struct ifla_cacheinfo
+{
+	__u32	max_reasm_len;
+	__u32	tstamp;		/* ipv6InterfaceTable updated timestamp */
+	__u32	reachable_time;
+	__u32	retrans_time;
+};
+
 /*****************************************************************
  *		Traffic control messages.
  ****/
@@ -514,9 +805,9 @@ struct tcmsg
 	unsigned char	tcm__pad1;
 	unsigned short	tcm__pad2;
 	int		tcm_ifindex;
-	uint32_t	tcm_handle;
-	uint32_t	tcm_parent;
-	uint32_t	tcm_info;
+	__u32		tcm_handle;
+	__u32		tcm_parent;
+	__u32		tcm_info;
 };
 
 enum
@@ -527,20 +818,17 @@ enum
 	TCA_STATS,
 	TCA_XSTATS,
 	TCA_RATE,
+	TCA_FCNT,
+	TCA_STATS2,
+	__TCA_MAX
 };
 
-#define TCA_MAX TCA_RATE
+#define TCA_MAX (__TCA_MAX - 1)
 
 #define TCA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
 #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
 
-
-/* SUMMARY: maximal rtattr understood by kernel */
-
-#define RTATTR_MAX		RTA_MAX
-
-/* RTnetlink multicast groups */
-
+/* RTnetlink multicast groups - backwards compatibility for userspace */
 #define RTMGRP_LINK		1
 #define RTMGRP_NOTIFY		2
 #define RTMGRP_NEIGH		4
@@ -549,14 +837,76 @@ enum
 #define RTMGRP_IPV4_IFADDR	0x10
 #define RTMGRP_IPV4_MROUTE	0x20
 #define RTMGRP_IPV4_ROUTE	0x40
+#define RTMGRP_IPV4_RULE	0x80
 
 #define RTMGRP_IPV6_IFADDR	0x100
 #define RTMGRP_IPV6_MROUTE	0x200
 #define RTMGRP_IPV6_ROUTE	0x400
+#define RTMGRP_IPV6_IFINFO	0x800
 
 #define RTMGRP_DECnet_IFADDR    0x1000
 #define RTMGRP_DECnet_ROUTE     0x4000
 
+#define RTMGRP_IPV6_PREFIX	0x20000
+
+/* RTnetlink multicast groups */
+enum rtnetlink_groups {
+	RTNLGRP_NONE,
+#define RTNLGRP_NONE		RTNLGRP_NONE
+	RTNLGRP_LINK,
+#define RTNLGRP_LINK		RTNLGRP_LINK
+	RTNLGRP_NOTIFY,
+#define RTNLGRP_NOTIFY		RTNLGRP_NOTIFY
+	RTNLGRP_NEIGH,
+#define RTNLGRP_NEIGH		RTNLGRP_NEIGH
+	RTNLGRP_TC,
+#define RTNLGRP_TC		RTNLGRP_TC
+	RTNLGRP_IPV4_IFADDR,
+#define RTNLGRP_IPV4_IFADDR	RTNLGRP_IPV4_IFADDR
+	RTNLGRP_IPV4_MROUTE,
+#define	RTNLGRP_IPV4_MROUTE	RTNLGRP_IPV4_MROUTE
+	RTNLGRP_IPV4_ROUTE,
+#define RTNLGRP_IPV4_ROUTE	RTNLGRP_IPV4_ROUTE
+	RTNLGRP_IPV4_RULE,
+#define RTNLGRP_IPV4_RULE	RTNLGRP_IPV4_RULE
+	RTNLGRP_IPV6_IFADDR,
+#define RTNLGRP_IPV6_IFADDR	RTNLGRP_IPV6_IFADDR
+	RTNLGRP_IPV6_MROUTE,
+#define RTNLGRP_IPV6_MROUTE	RTNLGRP_IPV6_MROUTE
+	RTNLGRP_IPV6_ROUTE,
+#define RTNLGRP_IPV6_ROUTE	RTNLGRP_IPV6_ROUTE
+	RTNLGRP_IPV6_IFINFO,
+#define RTNLGRP_IPV6_IFINFO	RTNLGRP_IPV6_IFINFO
+	RTNLGRP_DECnet_IFADDR,
+#define RTNLGRP_DECnet_IFADDR	RTNLGRP_DECnet_IFADDR
+	RTNLGRP_NOP2,
+	RTNLGRP_DECnet_ROUTE,
+#define RTNLGRP_DECnet_ROUTE	RTNLGRP_DECnet_ROUTE
+	RTNLGRP_DECnet_RULE,
+#define RTNLGRP_DECnet_RULE	RTNLGRP_DECnet_RULE
+	RTNLGRP_NOP4,
+	RTNLGRP_IPV6_PREFIX,
+#define RTNLGRP_IPV6_PREFIX	RTNLGRP_IPV6_PREFIX
+	RTNLGRP_IPV6_RULE,
+#define RTNLGRP_IPV6_RULE	RTNLGRP_IPV6_RULE
+	__RTNLGRP_MAX
+};
+#define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)
+
+/* TC action piece */
+struct tcamsg
+{
+	unsigned char	tca_family;
+	unsigned char	tca__pad1;
+	unsigned short	tca__pad2;
+};
+#define TA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg))))
+#define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg))
+#define TCA_ACT_TAB 1 /* attr type must be >=1 */	
+#define TCAA_MAX 1
+
 /* End of information exported to user level */
 
+
+
 #endif	/* __LINUX_RTNETLINK_H */
--- openswan-2.4.9.orig/programs/_confread/_confread.in	2006-04-12 14:55:42.000000000 -0500
+++ openswan-2.4.9/programs/_confread/_confread.in	2007-10-30 08:40:08.000000000 -0500
@@ -133,6 +133,7 @@ awk 'BEGIN {
 	good = "also alsoflip type auto authby _plutodevel"
 	good = good " connaddrfamily forceencaps"
 	good = good " modecfgpull"
+	good = good " context"
 	left = " left leftsubnet leftnexthop leftupdown"
 	akey = " keyexchange auth pfs pfsgroup keylife rekey rekeymargin"
         akey = akey " rekeyfuzz dpddelay dpdtimeout dpdaction"
--- openswan-2.4.9.orig/programs/auto/auto.in	2006-01-05 16:50:45.000000000 -0600
+++ openswan-2.4.9/programs/auto/auto.in	2007-10-30 08:40:08.000000000 -0500
@@ -538,6 +538,9 @@ awk '	BEGIN {
 		rid = ""
 		if ("rightid" in s)
 			rid = "--id " qs("rightid")
+		ctx = ""
+		if ("context" in s)
+			ctx = "--ctx " qs("context")
 
 		lsip = ""
 		if ("leftsourceip" in s)
@@ -632,7 +635,7 @@ awk '	BEGIN {
 			rca, rxauth, rmodecfg, rsip, rgr, "\\"
 		print "\t--ipseclifetime", qs("keylife"),
 			"--rekeymargin", qs("rekeymargin"), "\\"
-		print "\t--keyingtries", qs("keyingtries"), fuzz, rk, pd, "\\"
+		print "\t--keyingtries", qs("keyingtries"), fuzz, rk, pd, ctx, "\\"
 		print "\t|| exit $?"
 	}
 	END {
--- openswan-2.4.9.orig/programs/pluto/demux.c	2007-07-09 18:08:47.000000000 -0500
+++ openswan-2.4.9/programs/pluto/demux.c	2007-10-30 08:40:08.000000000 -0500
@@ -2848,7 +2848,7 @@ complete_state_transition(struct msg_dig
 	    {
 		st->st_state = STATE_MAIN_R3;	    /* ISAKMP is up... */
 	        set_cur_state(st);
-	        quick_outI1(st->st_whack_sock, st, st->st_connection, st->st_connection->policy, 1, SOS_NOBODY);
+	        quick_outI1(st->st_whack_sock, st, st->st_connection, st->st_connection->policy, 1, SOS_NOBODY, NULL);
 		break;
 	    }	    
 
--- openswan-2.4.9.orig/programs/pluto/rcv_whack.c	2005-05-19 09:58:55.000000000 -0500
+++ openswan-2.4.9/programs/pluto/rcv_whack.c	2007-10-30 08:40:08.000000000 -0500
@@ -576,7 +576,7 @@ whack_handle(int whackctlfd)
 	else
 	    initiate_opportunistic(&msg.oppo_my_client, &msg.oppo_peer_client, 0
 		, FALSE
-		, msg.whack_async? NULL_FD : dup_any(whackfd), "whack");
+		, msg.whack_async? NULL_FD : dup_any(whackfd), NULL, "whack");
     }
 
     if (msg.whack_terminate)
--- openswan-2.4.9.orig/programs/pluto/ipsec_doi.c	2007-01-22 15:05:12.000000000 -0600
+++ openswan-2.4.9/programs/pluto/ipsec_doi.c	2007-10-30 08:40:08.000000000 -0500
@@ -1039,7 +1039,8 @@ ipsecdoi_initiate(int whack_sock
 		  , lset_t policy
 		  , unsigned long try
 		  , so_serial_t replacing
-		  , enum crypto_importance importance)
+		  , enum crypto_importance importance
+		  , char *ctx)
 {
     /* If there's already an ISAKMP SA established, use that and
      * go directly to Quick Mode.  We are even willing to use one
@@ -1078,7 +1079,7 @@ ipsecdoi_initiate(int whack_sock
 	 * It isn't clear what to do with the error return.
 	 */
 	(void) quick_outI1(whack_sock, st, c, policy, try
-			   , replacing);
+			   , replacing, ctx);
       }
     }
     else
@@ -1143,7 +1144,7 @@ ipsecdoi_replace(struct state *st, unsig
 	}
 	passert(HAS_IPSEC_POLICY(policy));
 	ipsecdoi_initiate(whack_sock, st->st_connection, policy, try
-			  , st->st_serialno, st->st_import);
+			  , st->st_serialno, st->st_import, NULL);
     }
 }
 
--- openswan-2.4.9.orig/programs/pluto/ikev1_quick.h	2005-03-19 20:27:50.000000000 -0600
+++ openswan-2.4.9/programs/pluto/ikev1_quick.h	2007-10-30 08:40:08.000000000 -0500
@@ -20,7 +20,8 @@ extern stf_status quick_outI1(int whack_
     , struct connection *c
     , lset_t policy
     , unsigned long try
-    , so_serial_t replacing);
+    , so_serial_t replacing
+    , char *ctx);
 
 extern state_transition_fn
     quick_inI1_outR1,
--- openswan-2.4.9.orig/programs/pluto/state.h	2006-11-23 22:21:42.000000000 -0600
+++ openswan-2.4.9/programs/pluto/state.h	2007-10-30 08:40:08.000000000 -0500
@@ -270,7 +270,7 @@ struct state
     u_int32_t	      st_seen_vendorid;	  /* Bit field about recognized Vendor ID */
     struct isakmp_quirks quirks;          /* work arounds for faults in other
  					   * products */
-    
+    char *ctx;				  /* SELinux security context */
 };
 
 /* global variables */
--- openswan-2.4.9.orig/programs/pluto/ipsec_doi.h	2005-03-19 20:27:50.000000000 -0600
+++ openswan-2.4.9/programs/pluto/ipsec_doi.h	2007-10-30 08:40:08.000000000 -0500
@@ -19,7 +19,8 @@ extern void echo_hdr(struct msg_digest *
 extern void ipsecdoi_initiate(int whack_sock, struct connection *c
 			      , lset_t policy, unsigned long try
 			      , so_serial_t replacing
-			      , enum crypto_importance importance);
+			      , enum crypto_importance importance
+			      , char *ctx);
 
 extern void ipsecdoi_replace(struct state *st, unsigned long try);
 
--- openswan-2.4.9.orig/programs/pluto/ikev1_quick.c	2006-04-04 17:17:49.000000000 -0500
+++ openswan-2.4.9/programs/pluto/ikev1_quick.c	2007-10-30 08:40:08.000000000 -0500
@@ -676,7 +676,8 @@ quick_outI1(int whack_sock
 	    , struct connection *c
 	    , lset_t policy
 	    , unsigned long try
-	    , so_serial_t replacing)
+	    , so_serial_t replacing
+	    , char *ctx)
 {
     struct state *st = duplicate_state(isakmp_sa);
     struct qke_continuation *qke = alloc_thing(struct qke_continuation
@@ -702,18 +703,21 @@ quick_outI1(int whack_sock
 
     st->st_msgid = generate_msgid(isakmp_sa);
     st->st_state = STATE_QUICK_I1;
+    st->ctx = ctx;
 
     insert_state(st);	/* needs cookies, connection, and msgid */
 
     if (replacing == SOS_NOBODY)
-	openswan_log("initiating Quick Mode %s {using isakmp#%lu}"
+	openswan_log("initiating Quick Mode %s {using isakmp#%lu} {ctx=%s}"
 		     , prettypolicy(policy)
-		     , isakmp_sa->st_serialno);
+		     , isakmp_sa->st_serialno
+		     , ctx?:"");
     else
-	openswan_log("initiating Quick Mode %s to replace #%lu {using isakmp#%lu}"
+	openswan_log("initiating Quick Mode %s to replace #%lu {using isakmp#%lu} {ctx=%s}"
 		     , prettypolicy(policy)
 		     , replacing
-		     , isakmp_sa->st_serialno);
+		     , isakmp_sa->st_serialno
+		     , ctx?:"");
 
     /* 
      * See if pfs_group has been specified for this conn,
@@ -1871,7 +1875,8 @@ quick_inI1_outR1_cryptotail(struct qke_c
 	return STF_FAIL + NO_PROPOSAL_CHOSEN;	/* ??? */
     }
     
-    openswan_log("responding to Quick Mode {msgid:%08x}", st->st_msgid);
+    openswan_log("responding to Quick Mode {msgid:%08x} {ctx=%s}", st->st_msgid,
+			st->ctx?:"");
 
     /**** finish reply packet: Nr [, KE ] [, IDci, IDcr ] ****/
     
--- openswan-2.4.9.orig/programs/pluto/kernel_pfkey.c	2005-07-08 12:55:28.000000000 -0500
+++ openswan-2.4.9/programs/pluto/kernel_pfkey.c	2007-10-30 08:40:08.000000000 -0500
@@ -398,7 +398,7 @@ process_pfkey_acquire(pfkey_buf *buf, st
 	&& !(ugh = addrtypeof(src) == addrtypeof(dst)? NULL : "conflicting address types")
 	&& !(ugh = addrtosubnet(src, &ours))
 	&& !(ugh = addrtosubnet(dst, &his)))
-      record_and_initiate_opportunistic(&ours, &his, 0, "%acquire-pfkey");
+      record_and_initiate_opportunistic(&ours, &his, 0, NULL, "%acquire-pfkey");
 
     if (ugh != NULL)
 	plog("SADB_ACQUIRE message from KLIPS malformed: %s", ugh);
@@ -480,6 +480,7 @@ pfkey_dequeue(void)
       record_and_initiate_opportunistic(&orphaned_holds->ours
 					, &orphaned_holds->his
 					, orphaned_holds->transport_proto
+					, NULL
 					, "%hold found-pfkey");
 
 }
@@ -743,7 +744,11 @@ pfkey_raw_eroute(const ip_address *this_
 		 , const struct pfkey_proto_info *proto_info UNUSED
 		 , time_t use_lifetime UNUSED
 		 , unsigned int op
-		 , const char *text_said)
+		 , const char *text_said
+		 , u_int8_t ctx_doi
+		 , u_int8_t ctx_alg
+		 , char *ctx_str
+		 , u_int16_t ctx_len)
 {
     struct sadb_ext *extensions[SADB_EXT_MAX + 1];
     ip_address
@@ -822,7 +827,10 @@ pfkey_raw_eroute(const ip_address *this_
 }
 
 static bool
-pfkey_add_sa(const struct kernel_sa *sa, bool replace)
+pfkey_add_sa(const struct kernel_sa *sa, bool replace
+		, u_int8_t ctx_doi
+		, u_int8_t ctx_alg
+		, char *ctx_str)
 {
     struct sadb_ext *extensions[SADB_EXT_MAX + 1];
     bool success = FALSE;
--- openswan-2.4.9.orig/programs/pluto/spdb_struct.c	2007-05-13 16:56:48.000000000 -0500
+++ openswan-2.4.9/programs/pluto/spdb_struct.c	2007-10-30 08:40:08.000000000 -0500
@@ -452,6 +452,25 @@ out_sa(pb_stream *outs
 			, st->st_connection->sa_ipsec_life_seconds
 			, attr_desc, attr_val_descs
 			, &trans_pbs);
+
+		    /* SELinux Security Context */
+		    if (st->ctx)
+		    {
+			struct isakmp_attribute attr;
+			pb_stream attrval;
+
+			attr.isaat_af_type = SECURITY_CONTEXT | ISAKMP_ATTR_AF_TLV;
+			DBG(DBG_EMITTING, 
+			    DBG_log("%s: SENDING SECURITY CONTEXT (%s) (%u)",
+				    __FUNCTION__, st->ctx, attr.isaat_af_type));
+			attr.isaat_lv = strlen(st->ctx) *sizeof(char);
+			if (!out_struct(&attr, attr_desc, &trans_pbs, &attrval))
+				return_on(ret, FALSE);
+			if (!out_raw(st->ctx, strlen(st->ctx) *sizeof(char)
+				 ,&attrval, "SELinux security context"))
+				return_on(ret, FALSE);
+			close_output_pbs(&attrval);
+		    }
 		}
 
 		/* spit out attributes from table */
@@ -1327,6 +1346,7 @@ parse_ipsec_transform(struct isakmp_tran
 	, seen_durations = 0;
     u_int16_t life_type;
     const struct oakley_group_desc *pfs_group = NULL;
+    chunk_t sec_ctx;
 
     life_type = 0;
 
@@ -1417,6 +1437,14 @@ parse_ipsec_transform(struct isakmp_tran
 		seen_durations |= LELEM(val);
 		life_type = val;
 		break;
+	    case SECURITY_CONTEXT | ISAKMP_ATTR_AF_TLV:
+		clonetochunk(sec_ctx,attr_pbs.cur,a.isaat_lv+1,"security context");
+		sec_ctx.ptr[sec_ctx.len-1] = 0;
+		DBG(DBG_PARSING,
+		    DBG_log("%s: RECEIVED SECURITY CONTEXT (%s)", __FUNCTION__, sec_ctx.ptr));
+		/* TODO: Check to see if there's ctx in st already */
+		st->ctx = (char *)sec_ctx.ptr;
+		break;
 	    case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:
 		val = decode_long_duration(&attr_pbs);
 		/* fall through */
--- openswan-2.4.9.orig/programs/pluto/pending.c	2007-01-23 09:37:06.000000000 -0600
+++ openswan-2.4.9/programs/pluto/pending.c	2007-10-30 08:40:08.000000000 -0500
@@ -215,7 +215,7 @@ unpend(struct state *st)
 
 	    p->pend_time = time(NULL);
 	    (void) quick_outI1(p->whack_sock, st, p->connection, p->policy
-		, p->try, p->replacing);
+		, p->try, p->replacing, NULL);
 	    p->whack_sock = NULL_FD;	/* ownership transferred */
 	    p->connection = NULL;	/* ownership transferred */
 	    delete_pending(pp);
--- openswan-2.4.9.orig/programs/pluto/plutomain.c	2007-04-06 12:10:37.000000000 -0500
+++ openswan-2.4.9/programs/pluto/plutomain.c	2007-10-30 08:40:08.000000000 -0500
@@ -71,6 +71,8 @@
 #include "vendor.h"
 #include "pluto_crypt.h"
 
+#include "security.h"
+
 #ifdef VIRTUAL_IP
 #include "virtual.h"
 #endif
@@ -764,6 +766,7 @@ main(int argc, char **argv)
     init_kernel();
     init_adns();
     init_id();
+    init_avc();
 
 #ifdef HAVE_THREADS
     init_fetch();
--- openswan-2.4.9.orig/programs/pluto/security.c	1969-12-31 18:00:00.000000000 -0600
+++ openswan-2.4.9/programs/pluto/security.c	2007-10-30 08:40:08.000000000 -0500
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2005 International Business Machines Corporation
+ * Copyright (c) 2005 by Trusted Computer Solutions, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <selinux/selinux.h>
+#include <selinux/flask.h>
+#include <selinux/av_permissions.h>
+#include <selinux/avc.h>
+#include <selinux/context.h>
+
+#include "log.h"
+#include "security.h"
+
+/*
+ * function: 	init_avc
+ * description:	function performs the steps necessary to initialize the
+ *		userspace avc.
+ * input:	void
+ * return:	0	if avc was successfully initialized
+ * 		1	if the avc could not be initialized
+ */
+
+static int mls_ready = -1;
+
+void
+init_avc(void)
+{
+	if (!is_selinux_mls_enabled()) {
+ 		loglog(RC_LOG_SERIOUS, "pluto: MLS support is not"
+ 				" enabled.");
+		mls_ready = 0;
+		return;
+	}
+
+	if (avc_init("pluto", NULL, NULL, NULL, NULL) == 0)
+		mls_ready = 1;
+	else
+		loglog(RC_LOG_SERIOUS, "pluto: could not initialize avc.");
+}
+
+/*
+ * function: 	security_polmatch
+ * description:	function determines if the specified SA's security context
+ *		matches the configured context for an IPSec policy rule.
+ * input:	security_context *sa
+ * 		char *pol
+ * return:	1	if the SA's context matches with the policy's context.
+ * 		0	if the SA does NOT match the policy or an error
+ * 			occurred which prevented the determination.
+ */
+
+int
+security_polmatch(security_context_t sa, security_context_t pol)
+{
+	int rtn = 1;
+	security_id_t sasid;
+	security_id_t polsid;
+	struct av_decision avd;
+	security_class_t tclass;
+	access_vector_t av;
+
+	if (mls_ready == -1) {
+		loglog(RC_LOG_SERIOUS, "AVC not initialized; unable to polmatch");
+		return 0;
+	} else if (!mls_ready)
+		return 1;
+
+	if (!sa && !pol)
+		return 1;
+
+	if (!sa || !*sa || !pol || !*pol)
+		return 0;
+
+	DBG(DBG_CONTROL,
+	    DBG_log("%s: POLMATCHING (%s) and (%s)", __FUNCTION__, sa, pol));
+
+	/*
+	 * Get the sids for the sa and pol contexts
+	 */
+	rtn = avc_context_to_sid(sa, &sasid);
+	if (rtn != 0) {
+		loglog(RC_LOG_SERIOUS, "security_polmatch: Unable to retrieve "
+				"sid for sl context (%s).", sa);
+		return 0;
+	}
+	rtn = avc_context_to_sid(pol, &polsid);
+	if (rtn != 0) {
+		loglog(RC_LOG_SERIOUS, "security_polmatch: Unable to retrieve "
+				"sid for pol context (%s).", pol);
+		sidput(sasid);
+		return 0;
+	}
+
+	/* 
+	 * Straight up test between sl and pol
+	 */
+	tclass = SECCLASS_ASSOCIATION;
+	av = ASSOCIATION__POLMATCH;
+	rtn = avc_has_perm(sasid, polsid, tclass, av, NULL, &avd);
+	if (rtn != 0) {
+		loglog(RC_LOG,
+			"security_polmatch: The sa context doesn't match pol context");
+		sidput(sasid);
+		sidput(polsid);
+		return 0;
+	}
+	DBG(DBG_CONTROL,
+	    DBG_log("%s: The SA's context (%s) matches" " the policy's (%s)",
+			__FUNCTION__, sa, pol));
+	return 1;
+}
--- openswan-2.4.9.orig/programs/pluto/security.h	1969-12-31 18:00:00.000000000 -0600
+++ openswan-2.4.9/programs/pluto/security.h	2007-10-30 08:40:08.000000000 -0500
@@ -0,0 +1,3 @@
+#include <selinux/selinux.h>
+void init_avc(void);
+int security_polmatch(security_context_t sa, security_context_t pol);
--- openswan-2.4.9.orig/programs/pluto/Makefile	2006-11-07 09:55:52.000000000 -0600
+++ openswan-2.4.9/programs/pluto/Makefile	2007-10-30 08:40:08.000000000 -0500
@@ -266,6 +266,7 @@ LIBSPLUTO+=$(HAVE_THREADS_LIBS) ${XAUTHP
 LIBSPLUTO+=${CURL_LIBS} 
 LIBSPLUTO+=${EXTRA_CRYPTO_LIBS}
 LIBSPLUTO+= -lgmp -lresolv # -lefence
+LIBSPLUTO+= -lselinux
 
 ifneq ($(LD_LIBRARY_PATH),)
 LDFLAGS=-L$(LD_LIBRARY_PATH)
@@ -342,6 +343,7 @@ DISTSRC = \
 	vendor.c nat_traversal.c virtual.c \
 	adns.c adns.h \
 	whack.c whack.h whackinit.c whacklib.c\
+	security.c\
 	${XAUTH_DIST_SRCS} \
 	${AGGRESSIVE_DIST_SRCS} 
 
@@ -367,6 +369,7 @@ OBJSPLUTO += vendor.o nat_traversal.o vi
 OBJSPLUTO += ike_alg_aes.o ike_alginit.o
 OBJSPLUTO += ${EXTRA_CRYPTO_OBJS}
 OBJSPLUTO += ike_alg.o db_ops.o 
+OBJSPLUTO += security.o
 OBJSPLUTO += ${XAUTH_OBJS}
 OBJSPLUTO += ${AGGRESSIVE_OBJS}
 OBJSPLUTO += ${SMARTCARD_OBJS} ${X509_OBJS} ${HAVE_THREADS_OBJS}
--- openswan-2.4.9.orig/include/pluto_constants.h	2005-11-16 16:41:30.000000000 -0600
+++ openswan-2.4.9/include/pluto_constants.h	2007-10-30 08:40:08.000000000 -0500
@@ -471,6 +471,7 @@ extern enum_names ipsec_attr_names;
 #define KEY_ROUNDS               7
 #define COMPRESS_DICT_SIZE       8
 #define COMPRESS_PRIVATE_ALG     9	/* B/V */
+#define SECURITY_CONTEXT         10	/* V */
 
 /* for each IPsec attribute, which enum_names describes its values? */
 extern enum_names *ipsec_attr_val_descs[];
--- openswan-2.4.9.orig/lib/libopenswan/constants.c	2006-11-02 12:36:29.000000000 -0600
+++ openswan-2.4.9/lib/libopenswan/constants.c	2007-10-30 08:40:08.000000000 -0500
@@ -392,6 +392,7 @@ static const char *const ipsec_attr_name
 	"KEY_ROUNDS",
 	"COMPRESS_DICT_SIZE",
 	"COMPRESS_PRIVATE_ALG",
+	"SECURITY_CONTEXT",
     };
 
 static const char *const ipsec_var_attr_name[] = {
@@ -403,6 +404,7 @@ static const char *const ipsec_var_attr_
 	NULL,
 	NULL,
 	"COMPRESS_PRIVATE_ALG (variable length)",
+	"SECURITY_CONTEXT (variable length)",
     };
 
 static enum_names ipsec_attr_desc_tv = {
@@ -411,7 +413,7 @@ static enum_names ipsec_attr_desc_tv = {
     ipsec_attr_name, NULL };
 
 enum_names ipsec_attr_names = {
-    SA_LIFE_DURATION, COMPRESS_PRIVATE_ALG,
+    SA_LIFE_DURATION, SECURITY_CONTEXT,
     ipsec_var_attr_name, &ipsec_attr_desc_tv };
 
 /* for each IPsec attribute, which enum_names describes its values? */
@@ -426,6 +428,7 @@ enum_names *ipsec_attr_val_descs[] = {
 	NULL,			/* KEY_ROUNDS */
 	NULL,			/* COMPRESS_DICT_SIZE */
 	NULL,			/* COMPRESS_PRIVATE_ALG */
+	NULL,			/* SECURITY_CONTEXT */
     };
 
 /* SA Lifetime Type attribute */
_______________________________________________
Dev mailing list
Dev@openswan.org
http://lists.openswan.org/mailman/listinfo/dev
