[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20071212032352.GA12890@hestia>
Date: Tue, 11 Dec 2007 19:23:52 -0800
From: Tyler Hicks <tyhicks@...edu>
To: linux netdev <netdev@...r.kernel.org>,
David Miller <davem@...emloft.net>
CC: Herbert Xu <herbert@...dor.apana.org.au>,
Joy Latten <latten@...ibm.com>
Subject: [PATCH] [IPSEC]: Add populate from packet (PFP) support
RFC 4301 requires us to associate each SPD entry with a set of flags to
determine how to assign the selector values when creating a new SAD entry.
Each selector in the new xfrm_state can either be assigned using the
corresponding selector in the xfrm_policy or with the corresponding value
in the flowi. Prior to this patch, the fields in the flowi were always
used.
Signed-off-by: Tyler Hicks <tyhicks@...edu>
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index b58adc5..ce6b1b5 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -362,6 +362,11 @@ struct xfrm_userpolicy_info {
#define XFRM_POLICY_BLOCK 1
__u8 flags;
#define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */
+#define XFRM_POLICY_PFP_SADDR 2
+#define XFRM_POLICY_PFP_DADDR 4
+#define XFRM_POLICY_PFP_PROTO 8
+#define XFRM_POLICY_PFP_SPORT 16
+#define XFRM_POLICY_PFP_DPORT 32
__u8 share;
};
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 58dfa82..5a039a2 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -261,9 +261,12 @@ struct xfrm_state_afinfo {
struct xfrm_type *type_map[IPPROTO_MAX];
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
int (*init_flags)(struct xfrm_state *x);
- void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
+ void (*init_tempsel)(struct xfrm_state *x,
+ struct flowi *fl,
struct xfrm_tmpl *tmpl,
- xfrm_address_t *daddr, xfrm_address_t *saddr);
+ struct xfrm_policy *pol,
+ xfrm_address_t *daddr,
+ xfrm_address_t *saddr);
int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
int (*output)(struct sk_buff *skb);
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 13d54a1..0fb1092 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -23,18 +23,39 @@ static int xfrm4_init_flags(struct xfrm_state *x)
static void
__xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
- struct xfrm_tmpl *tmpl,
+ struct xfrm_tmpl *tmpl, struct xfrm_policy *pol,
xfrm_address_t *daddr, xfrm_address_t *saddr)
{
- x->sel.daddr.a4 = fl->fl4_dst;
- x->sel.saddr.a4 = fl->fl4_src;
- x->sel.dport = xfrm_flowi_dport(fl);
- x->sel.dport_mask = htons(0xffff);
- x->sel.sport = xfrm_flowi_sport(fl);
- x->sel.sport_mask = htons(0xffff);
- x->sel.prefixlen_d = 32;
- x->sel.prefixlen_s = 32;
- x->sel.proto = fl->proto;
+ if (pol->flags & XFRM_POLICY_PFP_DADDR) {
+ x->sel.daddr.a4 = fl->fl4_dst;
+ x->sel.prefixlen_d = 32;
+ } else {
+ x->sel.daddr.a4 = pol->selector.daddr.a4;
+ x->sel.prefixlen_d = pol->selector.prefixlen_d;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_SADDR) {
+ x->sel.saddr.a4 = fl->fl4_src;
+ x->sel.prefixlen_s = 32;
+ } else {
+ x->sel.saddr.a4 = pol->selector.saddr.a4;
+ x->sel.prefixlen_s = pol->selector.prefixlen_s;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_DPORT) {
+ x->sel.dport = xfrm_flowi_dport(fl);
+ x->sel.dport_mask = htons(0xffff);
+ } else {
+ x->sel.dport = pol->selector.dport;
+ x->sel.dport_mask = pol->selector.dport_mask;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_SPORT) {
+ x->sel.sport = xfrm_flowi_sport(fl);
+ x->sel.sport_mask = htons(0xffff);
+ } else {
+ x->sel.sport = pol->selector.sport;
+ x->sel.sport = pol->selector.sport_mask;
+ }
+ x->sel.proto = pol->flags & XFRM_POLICY_PFP_PROTO ?
+ fl->proto : pol->selector.proto;
x->sel.ifindex = fl->oif;
x->id = tmpl->id;
if (x->id.daddr.a4 == 0)
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index b392bee..213d92d 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -21,20 +21,43 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo;
static void
__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
- struct xfrm_tmpl *tmpl,
+ struct xfrm_tmpl *tmpl, struct xfrm_policy *pol,
xfrm_address_t *daddr, xfrm_address_t *saddr)
{
/* Initialize temporary selector matching only
* to current session. */
- ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
- ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
- x->sel.dport = xfrm_flowi_dport(fl);
- x->sel.dport_mask = htons(0xffff);
- x->sel.sport = xfrm_flowi_sport(fl);
- x->sel.sport_mask = htons(0xffff);
- x->sel.prefixlen_d = 128;
- x->sel.prefixlen_s = 128;
- x->sel.proto = fl->proto;
+ if (pol->flags & XFRM_POLICY_PFP_DADDR) {
+ ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
+ x->sel.prefixlen_d = 128;
+ } else {
+ ipv6_addr_copy((struct in6_addr *)&x->sel.daddr,
+ (struct in6_addr *)&pol->selector.daddr);
+ x->sel.prefixlen_d = pol->selector.prefixlen_d;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_SADDR) {
+ ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
+ x->sel.prefixlen_s = 128;
+ } else {
+ ipv6_addr_copy((struct in6_addr *)&x->sel.saddr,
+ (struct in6_addr *)&pol->selector.saddr);
+ x->sel.prefixlen_s = pol->selector.prefixlen_s;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_DPORT) {
+ x->sel.dport = xfrm_flowi_dport(fl);
+ x->sel.dport_mask = htons(0xffff);
+ } else {
+ x->sel.dport = pol->selector.dport;
+ x->sel.dport_mask = pol->selector.dport_mask;
+ }
+ if (pol->flags & XFRM_POLICY_PFP_SPORT) {
+ x->sel.sport = xfrm_flowi_sport(fl);
+ x->sel.sport_mask = htons(0xffff);
+ } else {
+ x->sel.sport = pol->selector.sport;
+ x->sel.sport_mask = pol->selector.sport_mask;
+ }
+ x->sel.proto = pol->flags & XFRM_POLICY_PFP_PROTO ?
+ fl->proto : pol->selector.proto;
x->sel.ifindex = fl->oif;
x->id = tmpl->id;
if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 224b44e..2dab50e 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -654,14 +654,14 @@ EXPORT_SYMBOL(xfrm_sad_getinfo);
static int
xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
- struct xfrm_tmpl *tmpl,
+ struct xfrm_tmpl *tmpl, struct xfrm_policy *pol,
xfrm_address_t *daddr, xfrm_address_t *saddr,
unsigned short family)
{
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
if (!afinfo)
return -1;
- afinfo->init_tempsel(x, fl, tmpl, daddr, saddr);
+ afinfo->init_tempsel(x, fl, tmpl, pol, daddr, saddr);
xfrm_state_put_afinfo(afinfo);
return 0;
}
@@ -824,7 +824,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
}
/* Initialize temporary selector matching only
* to current session. */
- xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
+ xfrm_init_tempsel(x, fl, tmpl, pol, daddr, saddr, family);
error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
if (error) {
--
1.5.3.4
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists