return 0;
}
+static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst,
+ int nfheader_len)
+{
+ if (dst->ops->family == AF_INET6) {
+ struct rt6_info *rt = (struct rt6_info*)dst;
+ if (rt->rt6i_node)
+ path->path_cookie = rt->rt6i_node->fn_sernum;
+ }
+
+ path->u.rt6.rt6i_nfheader_len = nfheader_len;
+
+ return 0;
+}
+
static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
{
struct rt6_info *rt = (struct rt6_info*)xdst->route;
RTF_LOCAL);
xdst->u.rt6.rt6i_metric = rt->rt6i_metric;
xdst->u.rt6.rt6i_node = rt->rt6i_node;
+ if (rt->rt6i_node)
+ xdst->route_cookie = rt->rt6i_node->fn_sernum;
xdst->u.rt6.rt6i_gateway = rt->rt6i_gateway;
xdst->u.rt6.rt6i_dst = rt->rt6i_dst;
xdst->u.rt6.rt6i_src = rt->rt6i_src;
}
static inline void
-_decode_session6(struct sk_buff *skb, struct flowi *fl)
+_decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
{
u16 offset = skb_network_header_len(skb);
struct ipv6hdr *hdr = ipv6_hdr(skb);
u8 nexthdr = nh[IP6CB(skb)->nhoff];
memset(fl, 0, sizeof(struct flowi));
- ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
- ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
+ ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr);
+ ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr);
while (pskb_may_pull(skb, nh + offset + 1 - skb->data)) {
nh = skb_network_header(skb);
if (pskb_may_pull(skb, nh + offset + 4 - skb->data)) {
__be16 *ports = (__be16 *)exthdr;
- fl->fl_ip_sport = ports[0];
- fl->fl_ip_dport = ports[1];
+ fl->fl_ip_sport = ports[!!reverse];
+ fl->fl_ip_dport = ports[!reverse];
}
fl->proto = nexthdr;
return;
.find_bundle = __xfrm6_find_bundle,
.decode_session = _decode_session6,
.get_tos = xfrm6_get_tos,
+ .init_path = xfrm6_init_path,
.fill_dst = xfrm6_fill_dst,
};
-static void __init xfrm6_policy_init(void)
+static int __init xfrm6_policy_init(void)
{
- xfrm_policy_register_afinfo(&xfrm6_policy_afinfo);
+ return xfrm_policy_register_afinfo(&xfrm6_policy_afinfo);
}
static void xfrm6_policy_fini(void)
xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo);
}
-void __init xfrm6_init(void)
+int __init xfrm6_init(void)
{
- xfrm6_policy_init();
- xfrm6_state_init();
+ int ret;
+
+ ret = xfrm6_policy_init();
+ if (ret)
+ goto out;
+
+ ret = xfrm6_state_init();
+ if (ret)
+ goto out_policy;
+out:
+ return ret;
+out_policy:
+ xfrm6_policy_fini();
+ goto out;
}
void xfrm6_fini(void)