|
@@ -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;
|
|
|
}
|
|
|
|
|
@@ -3091,10 +2952,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;
|
|
@@ -3143,29 +3000,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 */
|
|
@@ -3177,29 +3016,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));
|
|
@@ -3325,10 +3146,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);
|
|
@@ -3392,29 +3209,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) */
|
|
@@ -3433,28 +3232,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) */
|
|
@@ -3472,10 +3254,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;
|
|
@@ -3484,50 +3262,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;
|
|
@@ -3542,10 +3286,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) +
|
|
@@ -3559,38 +3301,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;
|
|
|
}
|