#include <net/xfrm.h>
#include <net/mip6.h>
-static xfrm_address_t *mip6_xfrm_addr(struct xfrm_state *x, xfrm_address_t *addr)
-{
- return x->coaddr;
-}
-
static inline unsigned int calc_padlen(unsigned int len, unsigned int n)
{
return (n - len + 16) & 0x7;
{
struct ipv6hdr *iph = ipv6_hdr(skb);
struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data;
+ int err = destopt->nexthdr;
+ spin_lock(&x->lock);
if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) &&
!ipv6_addr_any((struct in6_addr *)x->coaddr))
- return -ENOENT;
+ err = -ENOENT;
+ spin_unlock(&x->lock);
- return destopt->nexthdr;
+ return err;
}
/* Destination Option Header is inserted.
u8 nexthdr;
int len;
- iph = (struct ipv6hdr *)skb->data;
- iph->payload_len = htons(skb->len - sizeof(*iph));
+ skb_push(skb, -skb_network_offset(skb));
+ iph = ipv6_hdr(skb);
- nexthdr = *skb_network_header(skb);
- *skb_network_header(skb) = IPPROTO_DSTOPTS;
+ nexthdr = *skb_mac_header(skb);
+ *skb_mac_header(skb) = IPPROTO_DSTOPTS;
dstopt = (struct ipv6_destopt_hdr *)skb_transport_header(skb);
dstopt->nexthdr = nexthdr;
len = ((char *)hao - (char *)dstopt) + sizeof(*hao);
memcpy(&hao->addr, &iph->saddr, sizeof(hao->addr));
+ spin_lock_bh(&x->lock);
memcpy(&iph->saddr, x->coaddr, sizeof(iph->saddr));
+ spin_unlock_bh(&x->lock);
BUG_TRAP(len == x->props.header_len);
dstopt->hdrlen = (x->props.header_len >> 3) - 1;
{
}
-static struct xfrm_type mip6_destopt_type =
+static const struct xfrm_type mip6_destopt_type =
{
.description = "MIP6DESTOPT",
.owner = THIS_MODULE,
.proto = IPPROTO_DSTOPTS,
- .flags = XFRM_TYPE_NON_FRAGMENT,
+ .flags = XFRM_TYPE_NON_FRAGMENT | XFRM_TYPE_LOCAL_COADDR,
.init_state = mip6_destopt_init_state,
.destructor = mip6_destopt_destroy,
.input = mip6_destopt_input,
.output = mip6_destopt_output,
.reject = mip6_destopt_reject,
.hdr_offset = mip6_destopt_offset,
- .local_addr = mip6_xfrm_addr,
};
static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data;
+ int err = rt2->rt_hdr.nexthdr;
+ spin_lock(&x->lock);
if (!ipv6_addr_equal(&rt2->addr, (struct in6_addr *)x->coaddr) &&
!ipv6_addr_any((struct in6_addr *)x->coaddr))
- return -ENOENT;
+ err = -ENOENT;
+ spin_unlock(&x->lock);
- return rt2->rt_hdr.nexthdr;
+ return err;
}
/* Routing Header type 2 is inserted.
struct rt2_hdr *rt2;
u8 nexthdr;
- iph = (struct ipv6hdr *)skb->data;
- iph->payload_len = htons(skb->len - sizeof(*iph));
+ skb_push(skb, -skb_network_offset(skb));
+ iph = ipv6_hdr(skb);
- nexthdr = *skb_network_header(skb);
- *skb_network_header(skb) = IPPROTO_ROUTING;
+ nexthdr = *skb_mac_header(skb);
+ *skb_mac_header(skb) = IPPROTO_ROUTING;
rt2 = (struct rt2_hdr *)skb_transport_header(skb);
rt2->rt_hdr.nexthdr = nexthdr;
BUG_TRAP(rt2->rt_hdr.hdrlen == 2);
memcpy(&rt2->addr, &iph->daddr, sizeof(rt2->addr));
+ spin_lock_bh(&x->lock);
memcpy(&iph->daddr, x->coaddr, sizeof(iph->daddr));
+ spin_unlock_bh(&x->lock);
return 0;
}
{
}
-static struct xfrm_type mip6_rthdr_type =
+static const struct xfrm_type mip6_rthdr_type =
{
.description = "MIP6RT",
.owner = THIS_MODULE,
.proto = IPPROTO_ROUTING,
- .flags = XFRM_TYPE_NON_FRAGMENT,
+ .flags = XFRM_TYPE_NON_FRAGMENT | XFRM_TYPE_REMOTE_COADDR,
.init_state = mip6_rthdr_init_state,
.destructor = mip6_rthdr_destroy,
.input = mip6_rthdr_input,
.output = mip6_rthdr_output,
.hdr_offset = mip6_rthdr_offset,
- .remote_addr = mip6_xfrm_addr,
};
static int __init mip6_init(void)