summaryrefslogtreecommitdiffstats
path: root/net/key/af_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/key/af_key.c')
-rw-r--r--net/key/af_key.c626
1 files changed, 170 insertions, 456 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 7470e367272b..d628df97e02e 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -96,8 +96,8 @@ static void pfkey_sock_destruct(struct sock *sk)
return;
}
- BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
- BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
+ WARN_ON(atomic_read(&sk->sk_rmem_alloc));
+ WARN_ON(atomic_read(&sk->sk_wmem_alloc));
atomic_dec(&pfkey_socks_nr);
}
@@ -579,25 +579,43 @@ static uint8_t pfkey_proto_from_xfrm(uint8_t proto)
return (proto ? proto : IPSEC_PROTO_ANY);
}
-static int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr,
- xfrm_address_t *xaddr)
+static inline int pfkey_sockaddr_len(sa_family_t family)
{
- switch (((struct sockaddr*)(addr + 1))->sa_family) {
+ switch (family) {
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+#endif
+ }
+ return 0;
+}
+
+static
+int pfkey_sockaddr_extract(const struct sockaddr *sa, xfrm_address_t *xaddr)
+{
+ switch (sa->sa_family) {
case AF_INET:
xaddr->a4 =
- ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr;
+ ((struct sockaddr_in *)sa)->sin_addr.s_addr;
return AF_INET;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
memcpy(xaddr->a6,
- &((struct sockaddr_in6 *)(addr + 1))->sin6_addr,
+ &((struct sockaddr_in6 *)sa)->sin6_addr,
sizeof(struct in6_addr));
return AF_INET6;
#endif
- default:
- return 0;
}
- /* NOTREACHED */
+ return 0;
+}
+
+static
+int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, xfrm_address_t *xaddr)
+{
+ return pfkey_sockaddr_extract((struct sockaddr *)(addr + 1),
+ xaddr);
}
static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs)
@@ -642,20 +660,11 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **
}
#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
+
static int
pfkey_sockaddr_size(sa_family_t family)
{
- switch (family) {
- case AF_INET:
- return PFKEY_ALIGN8(sizeof(struct sockaddr_in));
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- case AF_INET6:
- return PFKEY_ALIGN8(sizeof(struct sockaddr_in6));
-#endif
- default:
- return 0;
- }
- /* NOTREACHED */
+ return PFKEY_ALIGN8(pfkey_sockaddr_len(family));
}
static inline int pfkey_mode_from_xfrm(int mode)
@@ -687,6 +696,36 @@ static inline int pfkey_mode_to_xfrm(int mode)
}
}
+static unsigned int pfkey_sockaddr_fill(xfrm_address_t *xaddr, __be16 port,
+ struct sockaddr *sa,
+ unsigned short family)
+{
+ switch (family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ sin->sin_family = AF_INET;
+ sin->sin_port = port;
+ sin->sin_addr.s_addr = xaddr->a4;
+ memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+ return 32;
+ }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = port;
+ sin6->sin6_flowinfo = 0;
+ ipv6_addr_copy(&sin6->sin6_addr, (struct in6_addr *)xaddr->a6);
+ sin6->sin6_scope_id = 0;
+ return 128;
+ }
+#endif
+ }
+ return 0;
+}
+
static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,
int add_keys, int hsc)
{
@@ -697,13 +736,9 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,
struct sadb_address *addr;
struct sadb_key *key;
struct sadb_x_sa2 *sa2;
- struct sockaddr_in *sin;
struct sadb_x_sec_ctx *sec_ctx;
struct xfrm_sec_ctx *xfrm_ctx;
int ctx_size = 0;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct sockaddr_in6 *sin6;
-#endif
int size;
int auth_key_size = 0;
int encrypt_key_size = 0;
@@ -732,14 +767,7 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,
}
/* identity & sensitivity */
-
- if ((x->props.family == AF_INET &&
- x->sel.saddr.a4 != x->props.saddr.a4)
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- || (x->props.family == AF_INET6 &&
- memcmp (x->sel.saddr.a6, x->props.saddr.a6, sizeof (struct in6_addr)))
-#endif
- )
+ if (xfrm_addr_cmp(&x->sel.saddr, &x->props.saddr, x->props.family))
size += sizeof(struct sadb_address) + sockaddr_size;
if (add_keys) {
@@ -861,29 +889,12 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,
protocol's number." - RFC2367 */
addr->sadb_address_proto = 0;
addr->sadb_address_reserved = 0;
- if (x->props.family == AF_INET) {
- addr->sadb_address_prefixlen = 32;
- sin = (struct sockaddr_in *) (addr + 1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = x->props.saddr.a4;
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (x->props.family == AF_INET6) {
- addr->sadb_address_prefixlen = 128;
-
- sin6 = (struct sockaddr_in6 *) (addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, x->props.saddr.a6,
- sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
- }
-#endif
- else
+ addr->sadb_address_prefixlen =
+ pfkey_sockaddr_fill(&x->props.saddr, 0,
+ (struct sockaddr *) (addr + 1),
+ x->props.family);
+ if (!addr->sadb_address_prefixlen)
BUG();
/* dst address */
@@ -894,70 +905,32 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,
sizeof(uint64_t);
addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
addr->sadb_address_proto = 0;
- addr->sadb_address_prefixlen = 32; /* XXX */
addr->sadb_address_reserved = 0;
- if (x->props.family == AF_INET) {
- sin = (struct sockaddr_in *) (addr + 1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = x->id.daddr.a4;
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- if (x->sel.saddr.a4 != x->props.saddr.a4) {
- addr = (struct sadb_address*) skb_put(skb,
- sizeof(struct sadb_address)+sockaddr_size);
- addr->sadb_address_len =
- (sizeof(struct sadb_address)+sockaddr_size)/
- sizeof(uint64_t);
- addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
- addr->sadb_address_proto =
- pfkey_proto_from_xfrm(x->sel.proto);
- addr->sadb_address_prefixlen = x->sel.prefixlen_s;
- addr->sadb_address_reserved = 0;
-
- sin = (struct sockaddr_in *) (addr + 1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = x->sel.saddr.a4;
- sin->sin_port = x->sel.sport;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (x->props.family == AF_INET6) {
- addr->sadb_address_prefixlen = 128;
+ addr->sadb_address_prefixlen =
+ pfkey_sockaddr_fill(&x->id.daddr, 0,
+ (struct sockaddr *) (addr + 1),
+ x->props.family);
+ if (!addr->sadb_address_prefixlen)
+ BUG();
- sin6 = (struct sockaddr_in6 *) (addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, x->id.daddr.a6, sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
+ if (xfrm_addr_cmp(&x->sel.saddr, &x->props.saddr,
+ x->props.family)) {
+ addr = (struct sadb_address*) skb_put(skb,
+ sizeof(struct sadb_address)+sockaddr_size);
+ addr->sadb_address_len =
+ (sizeof(struct sadb_address)+sockaddr_size)/
+ sizeof(uint64_t);
+ addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
+ addr->sadb_address_proto =
+ pfkey_proto_from_xfrm(x->sel.proto);
+ addr->sadb_address_prefixlen = x->sel.prefixlen_s;
+ addr->sadb_address_reserved = 0;
- if (memcmp (x->sel.saddr.a6, x->props.saddr.a6,
- sizeof(struct in6_addr))) {
- addr = (struct sadb_address *) skb_put(skb,
- sizeof(struct sadb_address)+sockaddr_size);
- addr->sadb_address_len =
- (sizeof(struct sadb_address)+sockaddr_size)/
- sizeof(uint64_t);
- addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
- addr->sadb_address_proto =
- pfkey_proto_from_xfrm(x->sel.proto);
- addr->sadb_address_prefixlen = x->sel.prefixlen_s;
- addr->sadb_address_reserved = 0;
-
- sin6 = (struct sockaddr_in6 *) (addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = x->sel.sport;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, x->sel.saddr.a6,
- sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
- }
+ pfkey_sockaddr_fill(&x->sel.saddr, x->sel.sport,
+ (struct sockaddr *) (addr + 1),
+ x->props.family);
}
-#endif
- else
- BUG();
/* auth key */
if (add_keys && auth_key_size) {
@@ -1853,10 +1826,6 @@ static int
parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
{
struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr;
- struct sockaddr_in *sin;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct sockaddr_in6 *sin6;
-#endif
int mode;
if (xp->xfrm_nr >= XFRM_MAX_DEPTH)
@@ -1881,31 +1850,19 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
/* addresses present only in tunnel mode */
if (t->mode == XFRM_MODE_TUNNEL) {
- struct sockaddr *sa;
- sa = (struct sockaddr *)(rq+1);
- switch(sa->sa_family) {
- case AF_INET:
- sin = (struct sockaddr_in*)sa;
- t->saddr.a4 = sin->sin_addr.s_addr;
- sin++;
- if (sin->sin_family != AF_INET)
- return -EINVAL;
- t->id.daddr.a4 = sin->sin_addr.s_addr;
- break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- case AF_INET6:
- sin6 = (struct sockaddr_in6*)sa;
- memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr));
- sin6++;
- if (sin6->sin6_family != AF_INET6)
- return -EINVAL;
- memcpy(t->id.daddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr));
- break;
-#endif
- default:
+ u8 *sa = (u8 *) (rq + 1);
+ int family, socklen;
+
+ family = pfkey_sockaddr_extract((struct sockaddr *)sa,
+ &t->saddr);
+ if (!family)
return -EINVAL;
- }
- t->encap_family = sa->sa_family;
+
+ socklen = pfkey_sockaddr_len(family);
+ if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
+ &t->id.daddr) != family)
+ return -EINVAL;
+ t->encap_family = family;
} else
t->encap_family = xp->family;
@@ -1952,9 +1909,7 @@ static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
for (i=0; i<xp->xfrm_nr; i++) {
t = xp->xfrm_vec + i;
- socklen += (t->encap_family == AF_INET ?
- sizeof(struct sockaddr_in) :
- sizeof(struct sockaddr_in6));
+ socklen += pfkey_sockaddr_len(t->encap_family);
}
return sizeof(struct sadb_msg) +
@@ -1987,18 +1942,12 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in
struct sadb_address *addr;
struct sadb_lifetime *lifetime;
struct sadb_x_policy *pol;
- struct sockaddr_in *sin;
struct sadb_x_sec_ctx *sec_ctx;
struct xfrm_sec_ctx *xfrm_ctx;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct sockaddr_in6 *sin6;
-#endif
int i;
int size;
int sockaddr_size = pfkey_sockaddr_size(xp->family);
- int socklen = (xp->family == AF_INET ?
- sizeof(struct sockaddr_in) :
- sizeof(struct sockaddr_in6));
+ int socklen = pfkey_sockaddr_len(xp->family);
size = pfkey_xfrm_policy2msg_size(xp);
@@ -2016,26 +1965,10 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in
addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto);
addr->sadb_address_prefixlen = xp->selector.prefixlen_s;
addr->sadb_address_reserved = 0;
- /* src address */
- if (xp->family == AF_INET) {
- sin = (struct sockaddr_in *) (addr + 1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = xp->selector.saddr.a4;
- sin->sin_port = xp->selector.sport;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (xp->family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *) (addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = xp->selector.sport;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, xp->selector.saddr.a6,
- sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
- }
-#endif
- else
+ if (!pfkey_sockaddr_fill(&xp->selector.saddr,
+ xp->selector.sport,
+ (struct sockaddr *) (addr + 1),
+ xp->family))
BUG();
/* dst address */
@@ -2048,26 +1981,10 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in
addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto);
addr->sadb_address_prefixlen = xp->selector.prefixlen_d;
addr->sadb_address_reserved = 0;
- if (xp->family == AF_INET) {
- sin = (struct sockaddr_in *) (addr + 1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = xp->selector.daddr.a4;
- sin->sin_port = xp->selector.dport;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (xp->family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *) (addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = xp->selector.dport;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, xp->selector.daddr.a6,
- sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
- }
-#endif
- else
- BUG();
+
+ pfkey_sockaddr_fill(&xp->selector.daddr, xp->selector.dport,
+ (struct sockaddr *) (addr + 1),
+ xp->family);
/* hard time */
lifetime = (struct sadb_lifetime *) skb_put(skb,
@@ -2121,12 +2038,13 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in
int mode;
req_size = sizeof(struct sadb_x_ipsecrequest);
- if (t->mode == XFRM_MODE_TUNNEL)
- req_size += ((t->encap_family == AF_INET ?
- sizeof(struct sockaddr_in) :
- sizeof(struct sockaddr_in6)) * 2);
- else
+ if (t->mode == XFRM_MODE_TUNNEL) {
+ socklen = pfkey_sockaddr_len(t->encap_family);
+ req_size += socklen * 2;
+ } else {
size -= 2*socklen;
+ socklen = 0;
+ }
rq = (void*)skb_put(skb, req_size);
pol->sadb_x_policy_len += req_size/8;
memset(rq, 0, sizeof(*rq));
@@ -2141,42 +2059,15 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in
if (t->optional)
rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE;
rq->sadb_x_ipsecrequest_reqid = t->reqid;
+
if (t->mode == XFRM_MODE_TUNNEL) {
- switch (t->encap_family) {
- case AF_INET:
- sin = (void*)(rq+1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = t->saddr.a4;
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- sin++;
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = t->id.daddr.a4;
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- case AF_INET6:
- sin6 = (void*)(rq+1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, t->saddr.a6,
- sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
-
- sin6++;
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, t->id.daddr.a6,
- sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
- break;
-#endif
- default:
- break;
- }
+ u8 *sa = (void *)(rq + 1);
+ pfkey_sockaddr_fill(&t->saddr, 0,
+ (struct sockaddr *)sa,
+ t->encap_family);
+ pfkey_sockaddr_fill(&t->id.daddr, 0,
+ (struct sockaddr *) (sa + socklen),
+ t->encap_family);
}
}
@@ -2459,61 +2350,31 @@ out:
#ifdef CONFIG_NET_KEY_MIGRATE
static int pfkey_sockaddr_pair_size(sa_family_t family)
{
- switch (family) {
- case AF_INET:
- return PFKEY_ALIGN8(sizeof(struct sockaddr_in) * 2);
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- case AF_INET6:
- return PFKEY_ALIGN8(sizeof(struct sockaddr_in6) * 2);
-#endif
- default:
- return 0;
- }
- /* NOTREACHED */
+ return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
}
static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq,
xfrm_address_t *saddr, xfrm_address_t *daddr,
u16 *family)
{
- struct sockaddr *sa = (struct sockaddr *)(rq + 1);
+ u8 *sa = (u8 *) (rq + 1);
+ int af, socklen;
+
if (rq->sadb_x_ipsecrequest_len <
- pfkey_sockaddr_pair_size(sa->sa_family))
+ pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family))
return -EINVAL;
- switch (sa->sa_family) {
- case AF_INET:
- {
- struct sockaddr_in *sin;
- sin = (struct sockaddr_in *)sa;
- if ((sin+1)->sin_family != AF_INET)
- return -EINVAL;
- memcpy(&saddr->a4, &sin->sin_addr, sizeof(saddr->a4));
- sin++;
- memcpy(&daddr->a4, &sin->sin_addr, sizeof(daddr->a4));
- *family = AF_INET;
- break;
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- case AF_INET6:
- {
- struct sockaddr_in6 *sin6;
- sin6 = (struct sockaddr_in6 *)sa;
- if ((sin6+1)->sin6_family != AF_INET6)
- return -EINVAL;
- memcpy(&saddr->a6, &sin6->sin6_addr,
- sizeof(saddr->a6));
- sin6++;
- memcpy(&daddr->a6, &sin6->sin6_addr,
- sizeof(daddr->a6));
- *family = AF_INET6;
- break;
- }
-#endif
- default:
+ af = pfkey_sockaddr_extract((struct sockaddr *) sa,
+ saddr);
+ if (!af)
return -EINVAL;
- }
+ socklen = pfkey_sockaddr_len(af);
+ if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen),
+ daddr) != af)
+ return -EINVAL;
+
+ *family = af;
return 0;
}
@@ -3094,10 +2955,6 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
struct sadb_msg *hdr;
struct sadb_address *addr;
struct sadb_x_policy *pol;
- struct sockaddr_in *sin;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct sockaddr_in6 *sin6;
-#endif
int sockaddr_size;
int size;
struct sadb_x_sec_ctx *sec_ctx;
@@ -3146,29 +3003,11 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
addr->sadb_address_proto = 0;
addr->sadb_address_reserved = 0;
- if (x->props.family == AF_INET) {
- addr->sadb_address_prefixlen = 32;
-
- sin = (struct sockaddr_in *) (addr + 1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = x->props.saddr.a4;
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (x->props.family == AF_INET6) {
- addr->sadb_address_prefixlen = 128;
-
- sin6 = (struct sockaddr_in6 *) (addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr,
- x->props.saddr.a6, sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
- }
-#endif
- else
+ addr->sadb_address_prefixlen =
+ pfkey_sockaddr_fill(&x->props.saddr, 0,
+ (struct sockaddr *) (addr + 1),
+ x->props.family);
+ if (!addr->sadb_address_prefixlen)
BUG();
/* dst address */
@@ -3180,29 +3019,11 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
addr->sadb_address_proto = 0;
addr->sadb_address_reserved = 0;
- if (x->props.family == AF_INET) {
- addr->sadb_address_prefixlen = 32;
-
- sin = (struct sockaddr_in *) (addr + 1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = x->id.daddr.a4;
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (x->props.family == AF_INET6) {
- addr->sadb_address_prefixlen = 128;
-
- sin6 = (struct sockaddr_in6 *) (addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr,
- x->id.daddr.a6, sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
- }
-#endif
- else
+ addr->sadb_address_prefixlen =
+ pfkey_sockaddr_fill(&x->id.daddr, 0,
+ (struct sockaddr *) (addr + 1),
+ x->props.family);
+ if (!addr->sadb_address_prefixlen)
BUG();
pol = (struct sadb_x_policy *) skb_put(skb, sizeof(struct sadb_x_policy));
@@ -3328,10 +3149,6 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
struct sadb_sa *sa;
struct sadb_address *addr;
struct sadb_x_nat_t_port *n_port;
- struct sockaddr_in *sin;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct sockaddr_in6 *sin6;
-#endif
int sockaddr_size;
int size;
__u8 satype = (x->id.proto == IPPROTO_ESP ? SADB_SATYPE_ESP : 0);
@@ -3395,29 +3212,11 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
addr->sadb_address_proto = 0;
addr->sadb_address_reserved = 0;
- if (x->props.family == AF_INET) {
- addr->sadb_address_prefixlen = 32;
-
- sin = (struct sockaddr_in *) (addr + 1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = x->props.saddr.a4;
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (x->props.family == AF_INET6) {
- addr->sadb_address_prefixlen = 128;
-
- sin6 = (struct sockaddr_in6 *) (addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr,
- x->props.saddr.a6, sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
- }
-#endif
- else
+ addr->sadb_address_prefixlen =
+ pfkey_sockaddr_fill(&x->props.saddr, 0,
+ (struct sockaddr *) (addr + 1),
+ x->props.family);
+ if (!addr->sadb_address_prefixlen)
BUG();
/* NAT_T_SPORT (old port) */
@@ -3436,28 +3235,11 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
addr->sadb_address_proto = 0;
addr->sadb_address_reserved = 0;
- if (x->props.family == AF_INET) {
- addr->sadb_address_prefixlen = 32;
-
- sin = (struct sockaddr_in *) (addr + 1);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = ipaddr->a4;
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (x->props.family == AF_INET6) {
- addr->sadb_address_prefixlen = 128;
-
- sin6 = (struct sockaddr_in6 *) (addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- memcpy(&sin6->sin6_addr, &ipaddr->a6, sizeof(struct in6_addr));
- sin6->sin6_scope_id = 0;
- }
-#endif
- else
+ addr->sadb_address_prefixlen =
+ pfkey_sockaddr_fill(ipaddr, 0,
+ (struct sockaddr *) (addr + 1),
+ x->props.family);
+ if (!addr->sadb_address_prefixlen)
BUG();
/* NAT_T_DPORT (new port) */
@@ -3475,10 +3257,6 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type,
struct xfrm_selector *sel)
{
struct sadb_address *addr;
- struct sockaddr_in *sin;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct sockaddr_in6 *sin6;
-#endif
addr = (struct sadb_address *)skb_put(skb, sizeof(struct sadb_address) + sasize);
addr->sadb_address_len = (sizeof(struct sadb_address) + sasize)/8;
addr->sadb_address_exttype = type;
@@ -3487,50 +3265,16 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type,
switch (type) {
case SADB_EXT_ADDRESS_SRC:
- if (sel->family == AF_INET) {
- addr->sadb_address_prefixlen = sel->prefixlen_s;
- sin = (struct sockaddr_in *)(addr + 1);
- sin->sin_family = AF_INET;
- memcpy(&sin->sin_addr.s_addr, &sel->saddr,
- sizeof(sin->sin_addr.s_addr));
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (sel->family == AF_INET6) {
- addr->sadb_address_prefixlen = sel->prefixlen_s;
- sin6 = (struct sockaddr_in6 *)(addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- sin6->sin6_scope_id = 0;
- memcpy(&sin6->sin6_addr.s6_addr, &sel->saddr,
- sizeof(sin6->sin6_addr.s6_addr));
- }
-#endif
+ addr->sadb_address_prefixlen = sel->prefixlen_s;
+ pfkey_sockaddr_fill(&sel->saddr, 0,
+ (struct sockaddr *)(addr + 1),
+ sel->family);
break;
case SADB_EXT_ADDRESS_DST:
- if (sel->family == AF_INET) {
- addr->sadb_address_prefixlen = sel->prefixlen_d;
- sin = (struct sockaddr_in *)(addr + 1);
- sin->sin_family = AF_INET;
- memcpy(&sin->sin_addr.s_addr, &sel->daddr,
- sizeof(sin->sin_addr.s_addr));
- sin->sin_port = 0;
- memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
- }
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- else if (sel->family == AF_INET6) {
- addr->sadb_address_prefixlen = sel->prefixlen_d;
- sin6 = (struct sockaddr_in6 *)(addr + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- sin6->sin6_scope_id = 0;
- memcpy(&sin6->sin6_addr.s6_addr, &sel->daddr,
- sizeof(sin6->sin6_addr.s6_addr));
- }
-#endif
+ addr->sadb_address_prefixlen = sel->prefixlen_d;
+ pfkey_sockaddr_fill(&sel->daddr, 0,
+ (struct sockaddr *)(addr + 1),
+ sel->family);
break;
default:
return -EINVAL;
@@ -3545,10 +3289,8 @@ static int set_ipsecrequest(struct sk_buff *skb,
xfrm_address_t *src, xfrm_address_t *dst)
{
struct sadb_x_ipsecrequest *rq;
- struct sockaddr_in *sin;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct sockaddr_in6 *sin6;
-#endif
+ u8 *sa;
+ int socklen = pfkey_sockaddr_len(family);
int size_req;
size_req = sizeof(struct sadb_x_ipsecrequest) +
@@ -3562,38 +3304,10 @@ static int set_ipsecrequest(struct sk_buff *skb,
rq->sadb_x_ipsecrequest_level = level;
rq->sadb_x_ipsecrequest_reqid = reqid;
- switch (family) {
- case AF_INET:
- sin = (struct sockaddr_in *)(rq + 1);
- sin->sin_family = AF_INET;
- memcpy(&sin->sin_addr.s_addr, src,
- sizeof(sin->sin_addr.s_addr));
- sin++;
- sin->sin_family = AF_INET;
- memcpy(&sin->sin_addr.s_addr, dst,
- sizeof(sin->sin_addr.s_addr));
- break;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *)(rq + 1);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- sin6->sin6_scope_id = 0;
- memcpy(&sin6->sin6_addr.s6_addr, src,
- sizeof(sin6->sin6_addr.s6_addr));
- sin6++;
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = 0;
- sin6->sin6_flowinfo = 0;
- sin6->sin6_scope_id = 0;
- memcpy(&sin6->sin6_addr.s6_addr, dst,
- sizeof(sin6->sin6_addr.s6_addr));
- break;
-#endif
- default:
+ sa = (u8 *) (rq + 1);
+ if (!pfkey_sockaddr_fill(src, 0, (struct sockaddr *)sa, family) ||
+ !pfkey_sockaddr_fill(dst, 0, (struct sockaddr *)(sa + socklen), family))
return -EINVAL;
- }
return 0;
}