Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / net / ipv4 / xfrm4_policy.c
index cebc847..c63de0a 100644 (file)
@@ -36,7 +36,7 @@ static struct dst_entry *xfrm4_dst_lookup(int tos, xfrm_address_t *saddr,
        if (saddr)
                fl.fl4_src = saddr->a4;
 
-       err = __ip_route_output_key(&rt, &fl);
+       err = __ip_route_output_key(&init_net, &rt, &fl);
        dst = &rt->u.dst;
        if (err)
                dst = ERR_PTR(err);
@@ -79,126 +79,49 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
        return dst;
 }
 
-/* Allocate chain of dst_entry's, attach known xfrm's, calculate
- * all the metrics... Shortly, bundle a bundle.
- */
-
-static int
-__xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
-                     struct flowi *fl, struct dst_entry **dst_p)
+static int xfrm4_get_tos(struct flowi *fl)
 {
-       struct dst_entry *dst, *dst_prev;
-       struct rtable *rt0 = (struct rtable*)(*dst_p);
-       struct rtable *rt = rt0;
-       int tos = fl->fl4_tos;
-       int i;
-       int err;
-       int header_len = 0;
-       int trailer_len = 0;
-
-       dst = dst_prev = NULL;
-       dst_hold(&rt->u.dst);
-
-       for (i = 0; i < nx; i++) {
-               struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
-               struct xfrm_dst *xdst;
-
-               if (unlikely(dst1 == NULL)) {
-                       err = -ENOBUFS;
-                       dst_release(&rt->u.dst);
-                       goto error;
-               }
+       return fl->fl4_tos;
+}
 
-               if (!dst)
-                       dst = dst1;
-               else {
-                       dst_prev->child = dst1;
-                       dst1->flags |= DST_NOHASH;
-                       dst_clone(dst1);
-               }
+static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst,
+                          int nfheader_len)
+{
+       return 0;
+}
 
-               xdst = (struct xfrm_dst *)dst1;
-               xdst->route = &rt->u.dst;
-               xdst->genid = xfrm[i]->genid;
+static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev)
+{
+       struct rtable *rt = (struct rtable *)xdst->route;
 
-               dst1->next = dst_prev;
-               dst_prev = dst1;
+       xdst->u.rt.fl = rt->fl;
 
-               header_len += xfrm[i]->props.header_len;
-               trailer_len += xfrm[i]->props.trailer_len;
+       xdst->u.dst.dev = dev;
+       dev_hold(dev);
 
-               if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
-                       dst1 = xfrm_dst_lookup(xfrm[i], tos);
-                       err = PTR_ERR(dst1);
-                       if (IS_ERR(dst1))
-                               goto error;
+       xdst->u.rt.idev = in_dev_get(dev);
+       if (!xdst->u.rt.idev)
+               return -ENODEV;
 
-                       rt = (struct rtable *)dst1;
-               } else
-                       dst_hold(&rt->u.dst);
-       }
+       xdst->u.rt.peer = rt->peer;
+       if (rt->peer)
+               atomic_inc(&rt->peer->refcnt);
 
-       dst_prev->child = &rt->u.dst;
-       dst->path = &rt->u.dst;
-
-       /* Copy neighbout for reachability confirmation */
-       dst->neighbour = neigh_clone(rt->u.dst.neighbour);
-
-       *dst_p = dst;
-       dst = dst_prev;
-
-       dst_prev = *dst_p;
-       i = 0;
-       err = -ENODEV;
-       for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
-               struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
-               x->u.rt.fl = *fl;
-
-               dst_prev->xfrm = xfrm[i++];
-               dst_prev->dev = rt->u.dst.dev;
-               if (!rt->u.dst.dev)
-                       goto error;
-               dev_hold(rt->u.dst.dev);
-
-               x->u.rt.idev = in_dev_get(rt->u.dst.dev);
-               if (!x->u.rt.idev)
-                       goto error;
-
-               dst_prev->obsolete      = -1;
-               dst_prev->flags        |= DST_HOST;
-               dst_prev->lastuse       = jiffies;
-               dst_prev->header_len    = header_len;
-               dst_prev->trailer_len   = trailer_len;
-               memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
-
-               dst_prev->input = dst_discard;
-               dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
-               if (rt0->peer)
-                       atomic_inc(&rt0->peer->refcnt);
-               x->u.rt.peer = rt0->peer;
-               /* Sheit... I remember I did this right. Apparently,
-                * it was magically lost, so this code needs audit */
-               x->u.rt.rt_flags = rt0->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
-               x->u.rt.rt_type = rt0->rt_type;
-               x->u.rt.rt_src = rt0->rt_src;
-               x->u.rt.rt_dst = rt0->rt_dst;
-               x->u.rt.rt_gateway = rt0->rt_gateway;
-               x->u.rt.rt_spec_dst = rt0->rt_spec_dst;
-               header_len -= x->u.dst.xfrm->props.header_len;
-               trailer_len -= x->u.dst.xfrm->props.trailer_len;
-       }
+       /* Sheit... I remember I did this right. Apparently,
+        * it was magically lost, so this code needs audit */
+       xdst->u.rt.rt_flags = rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST |
+                                             RTCF_LOCAL);
+       xdst->u.rt.rt_type = rt->rt_type;
+       xdst->u.rt.rt_src = rt->rt_src;
+       xdst->u.rt.rt_dst = rt->rt_dst;
+       xdst->u.rt.rt_gateway = rt->rt_gateway;
+       xdst->u.rt.rt_spec_dst = rt->rt_spec_dst;
 
-       xfrm_init_pmtu(dst);
        return 0;
-
-error:
-       if (dst)
-               dst_free(dst);
-       return err;
 }
 
 static void
-_decode_session4(struct sk_buff *skb, struct flowi *fl)
+_decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 {
        struct iphdr *iph = ip_hdr(skb);
        u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
@@ -214,8 +137,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
                        if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
                                __be16 *ports = (__be16 *)xprth;
 
-                               fl->fl_ip_sport = ports[0];
-                               fl->fl_ip_dport = ports[1];
+                               fl->fl_ip_sport = ports[!!reverse];
+                               fl->fl_ip_dport = ports[!reverse];
                        }
                        break;
 
@@ -257,12 +180,12 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
                }
        }
        fl->proto = iph->protocol;
-       fl->fl4_dst = iph->daddr;
-       fl->fl4_src = iph->saddr;
+       fl->fl4_dst = reverse ? iph->saddr : iph->daddr;
+       fl->fl4_src = reverse ? iph->daddr : iph->saddr;
        fl->fl4_tos = iph->tos;
 }
 
-static inline int xfrm4_garbage_collect(void)
+static inline int xfrm4_garbage_collect(struct dst_ops *ops)
 {
        xfrm4_policy_afinfo.garbage_collect();
        return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
@@ -297,7 +220,8 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 
        xdst = (struct xfrm_dst *)dst;
        if (xdst->u.rt.idev->dev == dev) {
-               struct in_device *loopback_idev = in_dev_get(init_net.loopback_dev);
+               struct in_device *loopback_idev =
+                       in_dev_get(dev_net(dev)->loopback_dev);
                BUG_ON(!loopback_idev);
 
                do {
@@ -320,8 +244,10 @@ static struct dst_ops xfrm4_dst_ops = {
        .update_pmtu =          xfrm4_update_pmtu,
        .destroy =              xfrm4_dst_destroy,
        .ifdown =               xfrm4_dst_ifdown,
+       .local_out =            __ip_local_out,
        .gc_thresh =            1024,
        .entry_size =           sizeof(struct xfrm_dst),
+       .entries =              ATOMIC_INIT(0),
 };
 
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
@@ -330,8 +256,10 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
        .dst_lookup =           xfrm4_dst_lookup,
        .get_saddr =            xfrm4_get_saddr,
        .find_bundle =          __xfrm4_find_bundle,
-       .bundle_create =        __xfrm4_bundle_create,
        .decode_session =       _decode_session4,
+       .get_tos =              xfrm4_get_tos,
+       .init_path =            xfrm4_init_path,
+       .fill_dst =             xfrm4_fill_dst,
 };
 
 static void __init xfrm4_policy_init(void)