diff -Naru ipsec-tools-0.3.1.orig/configure.ac ipsec-tools-0.3.1/configure.ac --- ipsec-tools-0.3.1.orig/configure.ac 2004-04-21 20:44:15.349779137 -0700 +++ ipsec-tools-0.3.1/configure.ac 2004-04-30 23:00:54.728013784 -0700 @@ -64,6 +64,11 @@ ], [])], []) +AC_CHECK_MEMBER(struct sadb_x_policy.sadb_x_policy_priority, + [AC_DEFINE(HAVE_PFKEY_POLICY_PRIORITY, [], + [Are PF_KEY policy priorities supported?])], [], + [#include "$KERNEL_INCLUDE/linux/pfkeyv2.h"]) + AC_CONFIG_SUBDIRS([src/racoon]) AC_CONFIG_FILES([ Makefile diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/ipsec_dump_policy.c ipsec-tools-0.3.1/src/libipsec/ipsec_dump_policy.c --- ipsec-tools-0.3.1.orig/src/libipsec/ipsec_dump_policy.c 2004-04-21 20:44:15.360776121 -0700 +++ ipsec-tools-0.3.1/src/libipsec/ipsec_dump_policy.c 2004-04-24 19:20:05.913100196 -0700 @@ -43,6 +43,8 @@ #include #include +#include "config.h" + #include "ipsec_strerror.h" #include "libpfkey.h" @@ -77,6 +79,12 @@ char isrbuf[1024]; char *newbuf; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + int32_t priority_offset; + char *priority_str; + char operator; +#endif + /* sanity check */ if (policy == NULL) return NULL; @@ -89,6 +97,46 @@ if (delimiter == NULL) delimiter = " "; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + if (xpl->sadb_x_policy_priority == 0) + { + priority_offset = 0; + priority_str = ""; + } + /* find which constant the priority is closest to */ + else if (xpl->sadb_x_policy_priority < + (u_int32_t) (PRIORITY_DEFAULT / 4) * 3) + { + priority_offset = xpl->sadb_x_policy_priority - PRIORITY_HIGH; + priority_str = "prio high"; + } + else if (xpl->sadb_x_policy_priority >= + (u_int32_t) (PRIORITY_DEFAULT / 4) * 3 && + xpl->sadb_x_policy_priority < + (u_int32_t) (PRIORITY_DEFAULT / 4) * 5) + { + priority_offset = xpl->sadb_x_policy_priority - PRIORITY_DEFAULT; + priority_str = "prio def"; + } + else + { + priority_offset = xpl->sadb_x_policy_priority - PRIORITY_LOW; + priority_str = "prio low"; + } + + /* fix sign to match the way it is input */ + priority_offset *= -1; + if (priority_offset < 0) + { + operator = '-'; + priority_offset *= -1; + } + else + { + operator = '+'; + } +#endif + switch (xpl->sadb_x_policy_dir) { case IPSEC_DIR_ANY: case IPSEC_DIR_INBOUND: @@ -114,6 +162,11 @@ buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir]) + 1 /* space */ +#ifdef HAVE_PFKEY_POLICY_PRIORITY + + strlen(priority_str) + + ((priority_offset != 0) ? 13 : 0) /* [space operator space int] */ + + ((strlen(priority_str) != 0) ? 1 : 0) /* space */ +#endif + strlen(ipsp_policy_strs[xpl->sadb_x_policy_type]) + 1; /* NUL */ @@ -121,8 +174,29 @@ __ipsec_errcode = EIPSEC_NO_BUFS; return NULL; } +#ifdef HAVE_PFKEY_POLICY_PRIORITY + if (priority_offset != 0) + { + snprintf(buf, buflen, "%s %s %c %u %s", + ipsp_dir_strs[xpl->sadb_x_policy_dir], priority_str, operator, + priority_offset, ipsp_policy_strs[xpl->sadb_x_policy_type]); + } + else if (strlen (priority_str) != 0) + { + snprintf(buf, buflen, "%s %s %s", + ipsp_dir_strs[xpl->sadb_x_policy_dir], priority_str, + ipsp_policy_strs[xpl->sadb_x_policy_type]); + } + else + { + snprintf(buf, buflen, "%s %s", + ipsp_dir_strs[xpl->sadb_x_policy_dir], + ipsp_policy_strs[xpl->sadb_x_policy_type]); + } +#else snprintf(buf, buflen, "%s %s", ipsp_dir_strs[xpl->sadb_x_policy_dir], ipsp_policy_strs[xpl->sadb_x_policy_type]); +#endif if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) { __ipsec_errcode = EIPSEC_NO_ERROR; diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/ipsec_set_policy.3 ipsec-tools-0.3.1/src/libipsec/ipsec_set_policy.3 --- ipsec-tools-0.3.1.orig/src/libipsec/ipsec_set_policy.3 2004-04-21 20:44:15.361775847 -0700 +++ ipsec-tools-0.3.1/src/libipsec/ipsec_set_policy.3 2004-04-24 19:31:19.462296583 -0700 @@ -93,7 +93,7 @@ .Fa policy is formatted as either of the following: .Bl -tag -width "discard" -.It Ar direction Li discard +.It Ar direction [priority specification] Li discard .Ar direction must be .Li in @@ -101,20 +101,49 @@ .Li out . .Ar direction specifies which direction the policy needs to be applied. +.Ar priority specification +is used to control the placement of the policy within the SPD. It can only +be specified when libipsec has been compiled against kernel headers that +support policy priorities (>= 2.6.6). It takes one of the following formats: +.Bl -tag -width "discard" +.It Xo +.Ar {priority,prio} offset +.Xc +.Ar offset +is a signed 32-bit integer specifying the offset from the default priority with +positive offsets indicating higher priorities (policy is placed closer to +the beginning of the list) and negative offsets indicating lower priorities +(policy is placed closer to the end of the list) +.It Xo +.Ar {priority,prio} base {+,-} offset +.Xc +.Ar base +is either +.Li low, +.Li def, +or +.Li high +.Pp +.Ar offset +is an unsigned integer no larger than INT32_MAX +that is an offset from the base with the same meaning as above +.El +.Pp With .Li discard policy, packets will be dropped if they match the policy. -.It Ar direction Li entrust +.It Ar direction [priority specification] Li entrust .Li entrust means to consult to SPD defined by .Xr setkey 8 . -.It Ar direction Li bypass +.It Ar direction [priority specification] Li bypass .Li bypass means to be bypassed the IPsec processing. .Pq packet will be transmitted in clear . This is for privileged socket. .It Xo .Ar direction +.Ar [priority specification] .Li ipsec .Ar request ... .Xc @@ -230,7 +259,6 @@ is omitted, it will be interpreted as .Li default . .El -.El .Pp Note that there is a bit difference of specification from .Xr setkey 8 . diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/ipsec_strerror.c ipsec-tools-0.3.1/src/libipsec/ipsec_strerror.c --- ipsec-tools-0.3.1.orig/src/libipsec/ipsec_strerror.c 2004-04-21 20:44:15.360776121 -0700 +++ ipsec-tools-0.3.1/src/libipsec/ipsec_strerror.c 2004-04-24 19:59:20.959366138 -0700 @@ -67,6 +67,8 @@ "Family mismatch", /*EIPSEC_FAMILY_MISMATCH*/ "Too few arguments", /*EIPSEC_FEW_ARGUMENTS*/ NULL, /*EIPSEC_SYSTEM_ERROR*/ +"Priority offset not in valid range [-2147483647, 2147483648]", /*EIPSEC_INVAL_PRIORITY_OFFSET*/ +"Policy priority not compiled in", /*EIPSEC_PRIORITY_NOT_COMPILED*/ "Unknown error", /*EIPSEC_MAX*/ }; diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/ipsec_strerror.h ipsec-tools-0.3.1/src/libipsec/ipsec_strerror.h --- ipsec-tools-0.3.1.orig/src/libipsec/ipsec_strerror.h 2004-04-21 20:44:15.359776396 -0700 +++ ipsec-tools-0.3.1/src/libipsec/ipsec_strerror.h 2004-04-24 19:52:51.030500215 -0700 @@ -59,4 +59,6 @@ #define EIPSEC_FAMILY_MISMATCH 24 /*family mismatch*/ #define EIPSEC_FEW_ARGUMENTS 25 /*Too few arguments*/ #define EIPSEC_SYSTEM_ERROR 26 /*system error*/ -#define EIPSEC_MAX 27 /*unknown error*/ +#define EIPSEC_INVAL_PRIORITY_OFFSET 27 /*priority offset out of range*/ +#define EIPSEC_PRIORITY_NOT_COMPILED 28 /*no priority support in libipsec*/ +#define EIPSEC_MAX 29 /*unknown error*/ diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/key_debug.c ipsec-tools-0.3.1/src/libipsec/key_debug.c --- ipsec-tools-0.3.1.orig/src/libipsec/key_debug.c 2004-04-21 20:44:15.360776121 -0700 +++ ipsec-tools-0.3.1/src/libipsec/key_debug.c 2004-04-24 13:43:29.446594520 -0700 @@ -58,6 +58,7 @@ #include #endif /* !_KERNEL */ +#include "config.h" #include "libpfkey.h" static void kdebug_sadb_prop __P((struct sadb_ext *)); @@ -425,9 +426,17 @@ if (ext == NULL) panic("kdebug_sadb_x_policy: NULL pointer was passed.\n"); +#ifdef HAVE_PFKEY_POLICY_PRIORITY + printf("sadb_x_policy{ type=%u dir=%u id=%x priority=%u }\n", +#else printf("sadb_x_policy{ type=%u dir=%u id=%x }\n", +#endif xpl->sadb_x_policy_type, xpl->sadb_x_policy_dir, +#ifdef HAVE_PFKEY_POLICY_PRIORITY + xpl->sadb_x_policy_id, xpl->sadb_x_policy_priority); +#else xpl->sadb_x_policy_id); +#endif if (xpl->sadb_x_policy_type == IPSEC_POLICY_IPSEC) { int tlen; diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/libpfkey.h ipsec-tools-0.3.1/src/libipsec/libpfkey.h --- ipsec-tools-0.3.1.orig/src/libipsec/libpfkey.h 2004-04-21 20:44:15.359776396 -0700 +++ ipsec-tools-0.3.1/src/libipsec/libpfkey.h 2004-04-24 19:40:00.952054794 -0700 @@ -32,6 +32,10 @@ #ifndef KAME_LIBPFKEY_H #define KAME_LIBPFKEY_H +#define PRIORITY_LOW 0xC0000000 +#define PRIORITY_DEFAULT 0x80000000 +#define PRIORITY_HIGH 0x40000000 + struct sadb_msg; extern void pfkey_sadump __P((struct sadb_msg *)); extern void pfkey_spdump __P((struct sadb_msg *)); diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/Makefile.in ipsec-tools-0.3.1/src/libipsec/Makefile.in --- ipsec-tools-0.3.1.orig/src/libipsec/Makefile.in 2004-04-21 20:44:15.359776396 -0700 +++ ipsec-tools-0.3.1/src/libipsec/Makefile.in 2004-04-30 23:32:28.395479088 -0700 @@ -293,10 +293,14 @@ mostlyclean-compile: -rm -f *.$(OBJEXT) + -rm -f test-policy-priority distclean-compile: -rm -f *.tab.c +test-policy-priority: test-policy-priority.c + $(COMPILE) -o $@ $< .libs/libipsec.a + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_dump_policy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_get_policylen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_strerror.Plo@am__quote@ diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/policy_parse.y ipsec-tools-0.3.1/src/libipsec/policy_parse.y --- ipsec-tools-0.3.1.orig/src/libipsec/policy_parse.y 2004-04-21 20:44:15.361775847 -0700 +++ ipsec-tools-0.3.1/src/libipsec/policy_parse.y 2004-04-24 19:59:12.882585123 -0700 @@ -31,8 +31,20 @@ /* * IN/OUT bound policy configuration take place such below: - * in - * out + * in + * out + * + * is one of the following: + * priority where the integer is an offset from the default + * priority, where negative numbers indicate lower + * priority (towards end of list) and positive numbers + * indicate higher priority (towards beginning of list) + * + * priority {low,def,high} {+,-} where low and high are + * constants which are closer + * to the end of the list and + * beginning of the list, + * respectively * * is one of following: * "discard", "none", "ipsec ", "entrust", "bypass", @@ -61,6 +73,8 @@ #include #include +#include "config.h" + #include "ipsec_strerror.h" #include "libpfkey.h" @@ -71,6 +85,8 @@ static int tlen = 0; /* total length of pbuf */ static int offset = 0; /* offset of pbuf */ static int p_dir, p_type, p_protocol, p_mode, p_level, p_reqid; +static u_int32_t p_priority = 0; +static long p_priority_offset = 0; static struct sockaddr *p_src = NULL; static struct sockaddr *p_dst = NULL; @@ -95,17 +111,21 @@ %union { u_int num; + u_int32_t num32; struct _val { int len; char *buf; } val; } -%token DIR ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY -%token IPADDRESS +%token DIR +%token PRIORITY PLUS +%token PRIO_BASE +%token PRIO_OFFSET +%token ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY IPADDRESS %token ME ANY %token SLASH HYPHEN -%type DIR ACTION PROTOCOL MODE LEVEL +%type DIR PRIORITY ACTION PROTOCOL MODE LEVEL %type IPADDRESS LEVEL_SPECIFY %% @@ -115,6 +135,107 @@ p_dir = $1; p_type = $2; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + p_priority = PRIORITY_DEFAULT; +#else + p_priority = 0; +#endif + + if (init_x_policy()) + return -1; + } + rules + | DIR PRIORITY PRIO_OFFSET ACTION + { + p_dir = $1; + p_type = $4; + + p_priority_offset = atol($3.buf); + + if (p_priority_offset > INT32_MAX) + { + __ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET; + return -1; + } + + /* positive input value means higher priority, therefore lower + actual value so that is closer to the beginning of the list */ + p_priority = PRIORITY_DEFAULT - (u_int32_t) p_priority_offset; + + if (init_x_policy()) + return -1; + } + rules + | DIR PRIORITY HYPHEN PRIO_OFFSET ACTION + { + p_dir = $1; + p_type = $5; + + p_priority_offset = atol($4.buf); + + if (p_priority_offset > ((u_int32_t) INT32_MAX) + 1) + { + __ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET; + return -1; + } + + /* negative input value means lower priority, therefore higher + actual value so that is closer to the end of the list */ + p_priority = PRIORITY_DEFAULT + (u_int32_t) p_priority_offset; + + if (init_x_policy()) + return -1; + } + rules + | DIR PRIORITY PRIO_BASE ACTION + { + p_dir = $1; + p_type = $4; + + p_priority = $3; + + if (init_x_policy()) + return -1; + } + rules + | DIR PRIORITY PRIO_BASE PLUS PRIO_OFFSET ACTION + { + p_dir = $1; + p_type = $6; + + p_priority_offset = atol($5.buf); + + if (p_priority_offset > INT32_MAX) + { + __ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET; + return -1; + } + + /* adding value means higher priority, therefore lower + actual value so that is closer to the beginning of the list */ + p_priority = $3 - (u_int32_t) p_priority_offset; + + if (init_x_policy()) + return -1; + } + rules + | DIR PRIORITY PRIO_BASE HYPHEN PRIO_OFFSET ACTION + { + p_dir = $1; + p_type = $6; + + p_priority_offset = atol($5.buf); + + if (p_priority_offset < INT32_MIN) + { + __ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET; + return -1; + } + + /* subtracting value means lower priority, therefore higher + actual value so that is closer to the end of the list */ + p_priority = $3 + (u_int32_t) p_priority_offset; + if (init_x_policy()) return -1; } @@ -124,6 +245,8 @@ p_dir = $1; p_type = 0; /* ignored it by kernel */ + p_priority = 0; + if (init_x_policy()) return -1; } @@ -312,6 +435,17 @@ p->sadb_x_policy_type = p_type; p->sadb_x_policy_dir = p_dir; p->sadb_x_policy_id = 0; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + p->sadb_x_policy_priority = p_priority; +#else + /* fail if given a priority and libipsec was not compiled with + priority support */ + if (p_priority != 0) + { + __ipsec_errcode = EIPSEC_PRIORITY_NOT_COMPILED; + return -1; + } +#endif offset = tlen; diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/policy_token.l ipsec-tools-0.3.1/src/libipsec/policy_token.l --- ipsec-tools-0.3.1.orig/src/libipsec/policy_token.l 2004-04-21 20:44:15.361775847 -0700 +++ ipsec-tools-0.3.1/src/libipsec/policy_token.l 2004-04-23 21:34:42.273677705 -0700 @@ -75,6 +75,7 @@ elcl \] percent \% semi \; +plus \+ usec {dot}{digit}{1,6} comment \#.* ccomment "/*" @@ -92,6 +93,18 @@ out { yylval.num = IPSEC_DIR_OUTBOUND; return(DIR); } fwd { yylval.num = IPSEC_DIR_FWD; return(DIR); } +priority { return(PRIORITY); } +prio { return(PRIORITY); } +low { yylval.num32 = PRIORITY_LOW; return(PRIO_BASE); } +def { yylval.num32 = PRIORITY_DEFAULT; return(PRIO_BASE); } +high { yylval.num32 = PRIORITY_HIGH; return(PRIO_BASE); } +{plus} { return(PLUS); } +{decstring} { + yylval.val.len = strlen(yytext); + yylval.val.buf = yytext; + return(PRIO_OFFSET); +} + discard { yylval.num = IPSEC_POLICY_DISCARD; return(ACTION); } none { yylval.num = IPSEC_POLICY_NONE; return(ACTION); } ipsec { yylval.num = IPSEC_POLICY_IPSEC; return(ACTION); } diff -Naru ipsec-tools-0.3.1.orig/src/libipsec/test-policy-priority.c ipsec-tools-0.3.1/src/libipsec/test-policy-priority.c --- ipsec-tools-0.3.1.orig/src/libipsec/test-policy-priority.c 1969-12-31 16:00:00.000000000 -0800 +++ ipsec-tools-0.3.1/src/libipsec/test-policy-priority.c 2004-04-24 13:51:46.010206117 -0700 @@ -0,0 +1,171 @@ +/* $KAME: test-policy.c,v 1.16 2003/08/26 03:24:08 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. + * 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 +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include "libpfkey.h" + +struct req_t { + int result; /* expected result; 0:ok 1:ng */ + int dump_result; /* dumped result expected to match original: 1:yes 0:no */ + char *str; + u_int32_t expected_priority; +} reqs[] = { +#ifdef HAVE_PFKEY_POLICY_PRIORITY +{ 0, 0, "out ipsec esp/transport//require", PRIORITY_DEFAULT }, +{ 0, 0, "out prio -1 ipsec esp/transport//require", PRIORITY_DEFAULT + 1 }, +{ 0, 0, "out priority 2147483648 ipsec esp/transport//require", + PRIORITY_DEFAULT - 2147483647 }, +{ 0, 1, "in prio def ipsec esp/transport//require", PRIORITY_DEFAULT }, +{ 0, 1, "in prio low ipsec esp/transport//require", PRIORITY_LOW }, +{ 0, 1, "in prio high ipsec esp/transport//require", PRIORITY_HIGH }, +{ 0, 1, "in prio def + 1 ipsec esp/transport//require", PRIORITY_DEFAULT - 1 }, +{ 0, 1, "in prio def - 1 ipsec esp/transport//require", PRIORITY_DEFAULT + 1}, +{ 0, 1, "in prio low + 1 ipsec esp/transport//require", PRIORITY_LOW - 1 }, +{ 0, 1, "in prio low - 1 ipsec esp/transport//require", PRIORITY_LOW + 1 }, +{ 0, 1, "in prio high + 1 ipsec esp/transport//require", PRIORITY_HIGH - 1 }, +{ 0, 1, "in prio high - 1 ipsec esp/transport//require", PRIORITY_HIGH + 1 }, +{ 1, 0, "in prio low - -1 ipsec esp/transport//require", 0 }, +{ 1, 0, "in prio low + high ipsec esp/transport//require", 0 }, +#else +{ 0, 1, "out ipsec esp/transport//require", 0 }, +{ 1, 0, "out prio -1 ipsec esp/transport//require", 0 }, +{ 1, 0, "in prio def ipsec esp/transport//require", 0 }, +{ 1, 0, "in prio def + 1 ipsec esp/transport//require", 0 }, +#endif +}; + +int test1 __P((void)); +int test1sub1 __P((struct req_t *)); +int test1sub2 __P((char *, int)); +int test2 __P((void)); +int test2sub __P((int)); + +int +main(ac, av) + int ac; + char **av; +{ + return test1(); +} + +int +test1() +{ + int i; + int result; + int error = 0; + + printf("TEST1\n"); + for (i = 0; i < sizeof(reqs)/sizeof(reqs[0]); i++) { + printf("#%d [%s]\n", i + 1, reqs[i].str); + + result = test1sub1(&reqs[i]); + if (result == 0 && reqs[i].result == 1) { + error = 1; + warnx("ERROR: expecting failure."); + } else if (result == 1 && reqs[i].result == 0) { + error = 1; + warnx("ERROR: expecting success."); + } + } + + return error; +} + +int +test1sub1(req) + struct req_t *req; +{ + char *policy; + char *policy_str; + struct sadb_x_policy *xpl; + + int len; + + policy = ipsec_set_policy(req->str, strlen(req->str)); + if (policy == NULL) { + if (req->result == 0) { + printf("ipsec_set_policy: %s\n", ipsec_strerror()); + } + return 1; + } + +#ifdef HAVE_PFKEY_POLICY_PRIORITY + /* check priority matches expected */ + xpl = (struct sadb_x_policy *)policy; + if (xpl->sadb_x_policy_priority != req->expected_priority) { + printf("Actual priority %u does not match expected priority %u\n", + xpl->sadb_x_policy_priority, req->expected_priority); + free(policy); + return 1; + } +#endif + + if (req->dump_result) { + /* invert policy */ + len = ipsec_get_policylen(policy); + if ((policy_str = ipsec_dump_policy(policy, NULL)) == NULL) { + printf("%s\n", ipsec_strerror()); + free(policy); + return 1; + } + + /* check that they match */ + if (strcmp(req->str, policy_str) != 0) { + printf("ipsec_dump_policy result (%s) does not match original " + "(%s)\n", policy_str, req->str); + free(policy_str); + free(policy); + return 1; + } + + free(policy_str); + } + + free(policy); + return 0; +} diff -Naru ipsec-tools-0.3.1.orig/src/racoon/configure.in ipsec-tools-0.3.1/src/racoon/configure.in --- ipsec-tools-0.3.1.orig/src/racoon/configure.in 2004-04-21 20:44:15.380770639 -0700 +++ ipsec-tools-0.3.1/src/racoon/configure.in 2004-04-30 23:29:52.031303631 -0700 @@ -774,9 +774,29 @@ [have_netinet_ipsec=no]) if test "$have_net_pfkey$have_netinet_ipsec" = nono; then + AC_ARG_WITH(kernel-headers, + AC_HELP_STRING([--with-kernel-headers=/lib/modules//build/include], + [where your Linux Kernel headers are installed]), + [ KERNEL_INCLUDE="$with_kernel_headers" + CONFIGURE_AMFLAGS="--with-kernel-headers=$with_kernel_headers" + AC_SUBST(CONFIGURE_AMFLAGS) ], + [ KERNEL_INCLUDE="/lib/modules/`uname -r`/build/include" ]) + + AC_CHECK_FILE($KERNEL_INCLUDE/linux/pfkeyv2.h, , + [ AC_CHECK_FILE(/usr/src/linux/include/linux/pfkeyv2.h, + KERNEL_INCLUDE=/usr/src/linux/include , + [ AC_MSG_ERROR(Unable to find linux-2.6 kernel headers) ] ) ] ) + AC_SUBST(KERNEL_INCLUDE) + + AC_CHECK_MEMBER(struct sadb_x_policy.sadb_x_policy_priority, + [AC_DEFINE(HAVE_PFKEY_POLICY_PRIORITY, [], + [Are PF_KEY policy priorities supported?])], [], + [#include "$KERNEL_INCLUDE/linux/pfkeyv2.h"]) + CPPFLAGS="-I${srcdir}/../include-glibc -I../include-glibc -include ${srcdir}/../include-glibc/glibc-bugs.h $CPPFLAGS" fi fi + AC_SUBST(INSTALL_OPTS) AC_OUTPUT(Makefile samples/psk.txt samples/racoon.conf) diff -Naru ipsec-tools-0.3.1.orig/src/racoon/pfkey.c ipsec-tools-0.3.1/src/racoon/pfkey.c --- ipsec-tools-0.3.1.orig/src/racoon/pfkey.c 2004-04-21 20:44:15.366774477 -0700 +++ ipsec-tools-0.3.1/src/racoon/pfkey.c 2004-04-30 23:31:44.676452930 -0700 @@ -1878,6 +1878,9 @@ xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC; xpl->sadb_x_policy_dir = spidx->dir; xpl->sadb_x_policy_id = 0; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + xpl->sadb_x_policy_priority = PRIORITY_DEFAULT; +#endif /* no need to append policy information any more if type is SPDDELETE */ if (type == SADB_X_SPDDELETE) @@ -2005,13 +2008,24 @@ daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; +#ifdef HAVE_PFKEY_POLICY_PRIORITY KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, saddr + 1, daddr + 1, saddr->sadb_address_prefixlen, daddr->sadb_address_prefixlen, saddr->sadb_address_proto, + xpl->sadb_x_policy_priority, &spidx); +#else + KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, + saddr + 1, + daddr + 1, + saddr->sadb_address_prefixlen, + daddr->sadb_address_prefixlen, + saddr->sadb_address_proto, + &spidx); +#endif sp = getsp(&spidx); if (sp == NULL) { @@ -2095,13 +2109,24 @@ daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; +#ifdef HAVE_PFKEY_POLICY_PRIORITY KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, saddr + 1, daddr + 1, saddr->sadb_address_prefixlen, daddr->sadb_address_prefixlen, saddr->sadb_address_proto, + xpl->sadb_x_policy_priority, &spidx); +#else + KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, + saddr + 1, + daddr + 1, + saddr->sadb_address_prefixlen, + daddr->sadb_address_prefixlen, + saddr->sadb_address_proto, + &spidx); +#endif sp = getsp(&spidx); if (sp != NULL) { @@ -2180,6 +2205,16 @@ daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, + saddr + 1, + daddr + 1, + saddr->sadb_address_prefixlen, + daddr->sadb_address_prefixlen, + saddr->sadb_address_proto, + xpl->sadb_x_policy_priority, + &spidx); +#else KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, saddr + 1, daddr + 1, @@ -2187,6 +2222,7 @@ daddr->sadb_address_prefixlen, saddr->sadb_address_proto, &spidx); +#endif sp = getsp(&spidx); if (sp == NULL) { @@ -2224,13 +2260,24 @@ daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; +#ifdef HAVE_PFKEY_POLICY_PRIORITY KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, saddr + 1, daddr + 1, saddr->sadb_address_prefixlen, daddr->sadb_address_prefixlen, saddr->sadb_address_proto, + xpl->sadb_x_policy_priority, &spidx); +#else + KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, + saddr + 1, + daddr + 1, + saddr->sadb_address_prefixlen, + daddr->sadb_address_prefixlen, + saddr->sadb_address_proto, + &spidx); +#endif sp = getsp(&spidx); if (sp == NULL) { @@ -2288,13 +2335,24 @@ return -1; } +#ifdef HAVE_PFKEY_POLICY_PRIORITY KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, saddr + 1, daddr + 1, saddr->sadb_address_prefixlen, daddr->sadb_address_prefixlen, saddr->sadb_address_proto, + xpl->sadb_x_policy_priority, &spidx); +#else + KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, + saddr + 1, + daddr + 1, + saddr->sadb_address_prefixlen, + daddr->sadb_address_prefixlen, + saddr->sadb_address_proto, + &spidx); +#endif sp = getsp(&spidx); if (sp != NULL) { @@ -2626,6 +2684,16 @@ return -1; } +#ifdef HAVE_PFKEY_POLICY_PRIORITY + KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, + saddr + 1, + daddr + 1, + saddr->sadb_address_prefixlen, + daddr->sadb_address_prefixlen, + saddr->sadb_address_proto, + xpl->sadb_x_policy_priority, + &new->spidx); +#else KEY_SETSECSPIDX(xpl->sadb_x_policy_dir, saddr + 1, daddr + 1, @@ -2633,6 +2701,7 @@ daddr->sadb_address_prefixlen, saddr->sadb_address_proto, &new->spidx); +#endif inssp(new); diff -Naru ipsec-tools-0.3.1.orig/src/racoon/policy.c ipsec-tools-0.3.1/src/racoon/policy.c --- ipsec-tools-0.3.1.orig/src/racoon/policy.c 2004-04-21 20:44:15.368773928 -0700 +++ ipsec-tools-0.3.1/src/racoon/policy.c 2004-04-30 23:31:41.308375378 -0700 @@ -336,7 +336,18 @@ inssp(new) struct secpolicy *new; { - TAILQ_INSERT_TAIL(&sptree, new, chain); + struct secpolicy *p; + + TAILQ_FOREACH(p, &sptree, chain) { + if (new->spidx.priority < p->spidx.priority) { + TAILQ_INSERT_BEFORE(p, new, chain); + return; + } + } + if (p == NULL) + TAILQ_INSERT_TAIL(&sptree, new, chain); + + return; } void diff -Naru ipsec-tools-0.3.1.orig/src/racoon/policy.h ipsec-tools-0.3.1/src/racoon/policy.h --- ipsec-tools-0.3.1.orig/src/racoon/policy.h 2004-04-21 20:44:15.375772010 -0700 +++ ipsec-tools-0.3.1/src/racoon/policy.h 2004-04-24 19:47:40.846734114 -0700 @@ -46,6 +46,7 @@ u_int8_t prefs; /* prefix length in bits for src */ u_int8_t prefd; /* prefix length in bits for dst */ u_int16_t ul_proto; /* upper layer Protocol */ + u_int32_t priority; /* priority for the policy */ }; /* Security Policy Data Base */ @@ -85,16 +86,30 @@ struct secpolicy *sp; /* back pointer to SP */ }; -#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, idx) \ +#ifdef HAVE_PFKEY_POLICY_PRIORITY +#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, _priority, idx) \ do { \ bzero((idx), sizeof(struct policyindex)); \ (idx)->dir = (_dir); \ (idx)->prefs = (ps); \ (idx)->prefd = (pd); \ (idx)->ul_proto = (ulp); \ + (idx)->priority = (_priority); \ memcpy(&(idx)->src, (s), sysdep_sa_len((struct sockaddr *)(s))); \ memcpy(&(idx)->dst, (d), sysdep_sa_len((struct sockaddr *)(d))); \ } while (0) +#else +#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, idx) \ +do { \ + bzero((idx), sizeof(struct policyindex)); \ + (idx)->dir = (_dir); \ + (idx)->prefs = (ps); \ + (idx)->prefd = (pd); \ + (idx)->ul_proto = (ulp); \ + memcpy(&(idx)->src, (s), sysdep_sa_len((struct sockaddr *)(s))); \ + memcpy(&(idx)->dst, (d), sysdep_sa_len((struct sockaddr *)(d))); \ +} while (0) +#endif struct ph2handle; struct policyindex; diff -Naru ipsec-tools-0.3.1.orig/src/setkey/parse.y ipsec-tools-0.3.1/src/setkey/parse.y --- ipsec-tools-0.3.1.orig/src/setkey/parse.y 2004-04-21 20:44:15.363775299 -0700 +++ ipsec-tools-0.3.1/src/setkey/parse.y 2004-04-24 19:12:50.546517811 -0700 @@ -47,6 +47,7 @@ #include #include +#include "config.h" #include "libpfkey.h" #include "vchar.h" @@ -67,6 +68,11 @@ time_t p_lt_hard, p_lt_soft; size_t p_lb_hard, p_lb_soft; +#ifdef HAVE_PFKEY_POLICY_PRIORITY +extern int last_msg_type; +extern u_int32_t last_priority; +#endif + extern int exit_now; static u_int p_natt_type; @@ -523,6 +529,10 @@ int status; struct addrinfo *src, *dst; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + last_msg_type = SADB_X_SPDADD; +#endif + /* fixed port fields if ulp is icmpv6 */ if ($10.buf != NULL) { if ($9 != IPPROTO_ICMPV6) @@ -770,6 +780,9 @@ : F_POLICY policy_requests { char *policy; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + struct sadb_x_policy *xpl; +#endif policy = ipsec_set_policy($2.buf, $2.len); if (policy == NULL) { @@ -779,6 +792,11 @@ $$.buf = policy; $$.len = ipsec_get_policylen(policy); + +#ifdef HAVE_PFKEY_POLICY_PRIORITY + xpl = (struct sadb_x_policy *) $$.buf; + last_priority = xpl->sadb_x_policy_priority; +#endif } ; diff -Naru ipsec-tools-0.3.1.orig/src/setkey/setkey.8 ipsec-tools-0.3.1/src/setkey/setkey.8 --- ipsec-tools-0.3.1.orig/src/setkey/setkey.8 2004-04-21 20:44:15.363775299 -0700 +++ ipsec-tools-0.3.1/src/setkey/setkey.8 2004-04-24 13:27:43.024458280 -0700 @@ -458,9 +458,9 @@ .Ar policy is the one of the following three formats: .Bd -literal -offset indent -.It Fl P Ar direction Li discard -.It Fl P Ar direction Li none -.It Xo Fl P Ar direction Li ipsec +.It Fl P Ar direction [priority specification] Li discard +.It Fl P Ar direction [priority specification] Li none +.It Xo Fl P Ar direction [priority specification] Li ipsec .Ar protocol/mode/src-dst/level Op ... .Xc .Ed @@ -472,6 +472,38 @@ or .Li in are used. +.Ar priority specification +is used to control the placement of the policy within the SPD. It can only +be specified when libipsec has been compiled against kernel headers that +support policy priorities (>= 2.6.6). If the kernel does not support priorities, +a warning message will be printed the first time a priority specification is +used. +.Ar priority specification +takes one of the following formats: +.Bl -tag -width "discard" +.It Xo +.Ar {priority,prio} offset +.Xc +.Ar offset +is a signed 32-bit integer specifying the offset from the default priority with +positive offsets indicating higher priorities (policy is placed closer to +the beginning of the list) and negative offsets indicating lower priorities +(policy is placed closer to the end of the list) +.It Xo +.Ar {priority,prio} base {+,-} offset +.Xc +.Ar base +is either +.Li low, +.Li def, +or +.Li high +.Pp +.Ar offset +is an unsigned integer no larger than INT32_MAX +that is an offset from the base with the same meaning as above +.Pp +.El .Li discard means the packet matching indexes will be discarded. .Li none diff -Naru ipsec-tools-0.3.1.orig/src/setkey/setkey.c ipsec-tools-0.3.1/src/setkey/setkey.c --- ipsec-tools-0.3.1.orig/src/setkey/setkey.c 2004-04-21 20:44:15.362775573 -0700 +++ ipsec-tools-0.3.1/src/setkey/setkey.c 2004-04-24 19:40:43.398396559 -0700 @@ -60,6 +60,7 @@ #include #endif +#include "config.h" #include "libpfkey.h" #include "../../package_version.h" @@ -72,6 +73,7 @@ void promisc __P((void)); int sendkeymsg __P((char *, size_t)); int postproc __P((struct sadb_msg *, int)); +int verifypriority __P((struct sadb_msg *m)); int fileproc __P((const char *)); const char *numstr __P((int)); void shortdump_hdr __P((void)); @@ -99,6 +101,15 @@ static time_t thiszone; extern int lineno; + +#ifdef HAVE_PFKEY_POLICY_PRIORITY +extern int last_msg_type; +int last_msg_type = -1; + +extern u_int32_t last_priority; +u_int32_t last_priority = 0; +#endif + extern int exit_now; int exit_now = 0; @@ -284,6 +295,11 @@ #ifdef HAVE_READLINE add_history (line); #endif + +#ifdef HAVE_PFKEY_POLICY_PRIORITY + last_msg_type = -1; /* invalid message type */ +#endif + parse_string (line); if (exit_now) return; @@ -466,6 +482,9 @@ struct sadb_msg *msg; int len; { +#ifdef HAVE_PFKEY_POLICY_PRIORITY + static int priority_support_check = 0; +#endif if (msg->sadb_msg_errno != 0) { char inf[80]; @@ -542,11 +561,54 @@ printf("\n"); } break; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + case SADB_X_SPDADD: + if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && + msg->sadb_msg_pid == getpid() && !priority_support_check) { + priority_support_check = 1; + if (!verifypriority(msg)) + printf ("WARNING: Kernel does not support policy priorities\n"); + } + break; +#endif } return (0); } +#ifdef HAVE_PFKEY_POLICY_PRIORITY +int +verifypriority(m) + struct sadb_msg *m; +{ + caddr_t mhp[SADB_EXT_MAX + 1]; + struct sadb_x_policy *xpl; + + /* check pfkey message. */ + if (pfkey_align(m, mhp)) { + printf("(%s\n", ipsec_strerror()); + return 0; + } + if (pfkey_check(mhp)) { + printf("%s\n", ipsec_strerror()); + return 0; + } + + xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY]; + + if (xpl == NULL) { + printf("no X_POLICY extension.\n"); + return 0; + } + + /* now make sure they match */ + if (last_priority != xpl->sadb_x_policy_priority) + return 0; + + return 1; +} +#endif + int fileproc(filename) const char *filename; diff -Naru ipsec-tools-0.3.1.orig/src/setkey/token.l ipsec-tools-0.3.1/src/setkey/token.l --- ipsec-tools-0.3.1.orig/src/setkey/token.l 2004-04-21 20:44:15.363775299 -0700 +++ ipsec-tools-0.3.1/src/setkey/token.l 2004-04-24 13:54:42.616694238 -0700 @@ -130,7 +130,7 @@ spdflush { return(SPDFLUSH); } tagged { return(TAGGED); } {hyphen}P { BEGIN S_PL; return(F_POLICY); } -[a-zA-Z0-9:\.\-_/ \n\t][a-zA-Z0-9:\.%\-_/ \n\t]* { +[a-zA-Z0-9:\.\-_/ \n\t][a-zA-Z0-9:\.%\-+_/ \n\t]* { yymore(); /* count up for nl */