netdev
[Top] [All Lists]

[PATCH][IPv6] separation xfrm_lookup from ip6_dst_lookup

To: davem@xxxxxxxxxx, herbert@xxxxxxxxxxxxxxxxxxx
Subject: [PATCH][IPv6] separation xfrm_lookup from ip6_dst_lookup
From: Kazunori Miyazawa <kazunori@xxxxxxxxxxxx>
Date: Fri, 30 Jul 2004 17:12:05 +0900
Cc: netdev@xxxxxxxxxxx, usagi-core@xxxxxxxxxxxxxx, kazunori@xxxxxxxxxxxx
Organization:
Sender: netdev-bounce@xxxxxxxxxxx
Hello,

This patch separates xfrm_lookup from ip6_dst_lookup
to support srcrt correctly. ip6_dst_lookup should be
called with next hop. however xfrm_lookup should be
called with final destination. It fixes them.

This patch makes AH support routing header with
previous Mr Hervert's patch. Of course this fixes ESP and IPcomp.

I consider copying flowi(fl_rt) uses too much stack at the moment.
I'll re-send the fixed patch again.

Thank you,

--Kazunori Miyazawa


diff -ruNBE a/net/ipv6/datagram.c b/net/ipv6/datagram.c
--- a/net/ipv6/datagram.c       2004-07-28 10:07:16.000000000 +0900
+++ b/net/ipv6/datagram.c       2004-07-28 10:29:13.000000000 +0900
@@ -40,7 +40,7 @@
        struct ipv6_pinfo       *np = inet6_sk(sk);
        struct in6_addr         *daddr;
        struct dst_entry        *dst;
-       struct flowi            fl;
+       struct flowi            fl, fl_rt, *flp = &fl;
        struct ip6_flowlabel    *flowlabel = NULL;
        int                     addr_type;
        int                     err;
@@ -157,17 +157,27 @@
        if (flowlabel) {
                if (flowlabel->opt && flowlabel->opt->srcrt) {
                        struct rt0_hdr *rt0 = (struct rt0_hdr *) 
flowlabel->opt->srcrt;
-                       ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+                       memcpy(&fl_rt, &fl, sizeof(fl_rt));
+                       ipv6_addr_copy(&fl_rt.fl6_dst, rt0->addr);
+                       flp = &fl_rt;
                }
        } else if (np->opt && np->opt->srcrt) {
                struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-               ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+               memcpy(&fl_rt, &fl, sizeof(fl_rt));
+               ipv6_addr_copy(&fl_rt.fl6_dst, rt0->addr);
+               flp = &fl_rt;
        }
 
-       err = ip6_dst_lookup(sk, &dst, &fl);
+       err = ip6_dst_lookup(sk, &dst, flp);
        if (err)
                goto out;
 
+       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+               dst_release(dst);
+               dst = NULL;
+               goto out;
+       }
+
        /* source address lookup done in ip6_dst_lookup */
 
        if (ipv6_addr_any(&np->saddr))
diff -ruNBE a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c     2004-07-28 10:07:09.000000000 +0900
+++ b/net/ipv6/ip6_output.c     2004-07-28 10:29:20.000000000 +0900
@@ -796,10 +796,6 @@
                        goto out_err_release;
                }
        }
-       if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) {
-               err = -ENETUNREACH;
-               goto out_err_release;
-        }
 
        return 0;
 
diff -ruNBE a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c    2004-07-28 10:08:26.000000000 +0900
+++ b/net/ipv6/raw.c    2004-07-28 10:30:22.000000000 +0900
@@ -567,7 +567,7 @@
        struct ipv6_txoptions *opt = NULL;
        struct ip6_flowlabel *flowlabel = NULL;
        struct dst_entry *dst = NULL;
-       struct flowi fl;
+       struct flowi fl, fl_rt, *flp = &fl;
        int addr_len = msg->msg_namelen;
        int hlimit = -1;
        u16 proto;
@@ -674,6 +674,7 @@
                opt = fl6_merge_options(&opt_space, flowlabel, opt);
 
        fl.proto = proto;
+ 
        ipv6_addr_copy(&fl.fl6_dst, daddr);
        if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
                ipv6_addr_copy(&fl.fl6_src, &np->saddr);
@@ -681,16 +682,24 @@
        /* merge ip6_build_xmit from ip6_output */
        if (opt && opt->srcrt) {
                struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-               ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+               memcpy(&fl_rt, &fl, sizeof(fl_rt));
+               ipv6_addr_copy(&fl_rt.fl6_dst, rt0->addr);
+               flp = &fl_rt;
        }
 
        if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
                fl.oif = np->mcast_oif;
 
-       err = ip6_dst_lookup(sk, &dst, &fl);
+       err = ip6_dst_lookup(sk, &dst, flp);
        if (err)
                goto out;
 
+       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+               dst_release(dst);
+               dst = NULL;
+               goto out;
+       }
+
        if (hlimit < 0) {
                if (ipv6_addr_is_multicast(&fl.fl6_dst))
                        hlimit = np->mcast_hops;
diff -ruNBE a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c       2004-07-28 10:09:10.000000000 +0900
+++ b/net/ipv6/tcp_ipv6.c       2004-07-28 10:29:37.000000000 +0900
@@ -550,7 +550,7 @@
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct tcp_opt *tp = tcp_sk(sk);
        struct in6_addr *saddr = NULL;
-       struct flowi fl;
+       struct flowi fl, fl_rt, *flp = &fl;
        struct dst_entry *dst;
        int addr_type;
        int err;
@@ -666,14 +666,21 @@
 
        if (np->opt && np->opt->srcrt) {
                struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
-               ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+               memcpy(&fl_rt, &fl, sizeof(fl_rt));
+               ipv6_addr_copy(&fl_rt.fl6_dst, rt0->addr);
+               flp = &fl_rt;
        }
 
-       err = ip6_dst_lookup(sk, &dst, &fl);
-
+       err = ip6_dst_lookup(sk, &dst, flp);
        if (err)
                goto failure;
 
+       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+               dst_release(dst);
+               dst = NULL;
+               goto failure;
+       }
+
        if (saddr == NULL) {
                saddr = &fl.fl6_src;
                ipv6_addr_copy(&np->rcv_saddr, saddr);
@@ -793,6 +800,14 @@
                                sk->sk_err_soft = -err;
                                goto out;
                        }
+
+                       if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+                               sk->sk_err_soft = -err;
+                               dst_release(dst);
+                               dst = NULL;
+                               goto out;
+                       }
+
                } else
                        dst_hold(dst);
 
@@ -863,7 +878,7 @@
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sk_buff * skb;
        struct ipv6_txoptions *opt = NULL;
-       struct flowi fl;
+       struct flowi fl, fl_rt, *flp = &fl;
        int err = -1;
 
        memset(&fl, 0, sizeof(fl));
@@ -888,12 +903,22 @@
 
                if (opt && opt->srcrt) {
                        struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-                       ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+                       memcpy(&fl_rt, &fl, sizeof(fl_rt));
+                       ipv6_addr_copy(&fl_rt.fl6_dst, rt0->addr);
+                       flp = &fl_rt;
                }
 
-               err = ip6_dst_lookup(sk, &dst, &fl);
+               err = ip6_dst_lookup(sk, &dst, flp);
                if (err)
                        goto done;
+
+               if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+                       dst_release(dst);
+                       dst = NULL;
+                       goto done;
+               }
+
+
        }
 
        skb = tcp_make_synack(sk, dst, req);
@@ -1021,6 +1046,12 @@
 
        /* sk = NULL, but it is safe for now. RST socket required. */
        if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+
+               if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
+                       dst_release(buff->dst);
+                       return;
+               }
+
                ip6_xmit(NULL, buff, &fl, NULL, 0);
                TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
                TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
@@ -1082,6 +1113,12 @@
        fl.fl_ip_sport = t1->source;
 
        if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+
+               if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
+                       dst_release(buff->dst);
+                       return;
+               }
+
                ip6_xmit(NULL, buff, &fl, NULL, 0);
                TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
                return;
@@ -1313,22 +1350,31 @@
        }
 
        if (dst == NULL) {
-               struct flowi fl;
+               struct flowi fl, fl_rt, *flp = &fl;
 
                memset(&fl, 0, sizeof(fl));
                fl.proto = IPPROTO_TCP;
                ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
                if (opt && opt->srcrt) {
                        struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-                       ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+                       memcpy(&fl_rt, &fl, sizeof(fl_rt));
+                       ipv6_addr_copy(&fl_rt.fl6_dst, rt0->addr);
+                       flp = &fl_rt;
                }
                ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
                fl.oif = sk->sk_bound_dev_if;
                fl.fl_ip_dport = req->rmt_port;
                fl.fl_ip_sport = inet_sk(sk)->sport;
 
-               if (ip6_dst_lookup(sk, &dst, &fl))
+               if (ip6_dst_lookup(sk, &dst, flp))
                        goto out;
+
+               if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+                       dst_release(dst);
+                       dst = NULL;
+                       goto out;
+               }
+
        } 
 
        newsk = tcp_create_openreq_child(sk, req, skb);
@@ -1710,7 +1756,7 @@
 
        if (dst == NULL) {
                struct inet_opt *inet = inet_sk(sk);
-               struct flowi fl;
+               struct flowi fl, fl_rt, *flp = &fl;
 
                memset(&fl, 0, sizeof(fl));
                fl.proto = IPPROTO_TCP;
@@ -1723,16 +1769,25 @@
 
                if (np->opt && np->opt->srcrt) {
                        struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
-                       ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+                       memcpy(&fl_rt, &fl, sizeof(fl_rt));
+                       ipv6_addr_copy(&fl_rt.fl6_dst, rt0->addr);
+                       flp = &fl_rt;
                }
 
-               err = ip6_dst_lookup(sk, &dst, &fl);
+               err = ip6_dst_lookup(sk, &dst, flp);
 
                if (err) {
                        sk->sk_route_caps = 0;
                        return err;
                }
 
+               if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+                       sk->sk_route_caps = 0;
+                       dst_release(dst);
+                       return err;
+               }
+
+
                ip6_dst_store(sk, dst, NULL);
                sk->sk_route_caps = dst->dev->features &
                        ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
@@ -1747,7 +1802,7 @@
        struct sock *sk = skb->sk;
        struct inet_opt *inet = inet_sk(sk);
        struct ipv6_pinfo *np = inet6_sk(sk);
-       struct flowi fl;
+       struct flowi fl, fl_rt, *flp = &fl;
        struct dst_entry *dst;
 
        memset(&fl, 0, sizeof(fl));
@@ -1762,19 +1817,27 @@
 
        if (np->opt && np->opt->srcrt) {
                struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
-               ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+               memcpy(&fl_rt, &fl, sizeof(fl_rt));
+               ipv6_addr_copy(&fl_rt.fl6_dst, rt0->addr);
+               flp = &fl_rt;
        }
 
        dst = __sk_dst_check(sk, np->dst_cookie);
 
        if (dst == NULL) {
-               int err = ip6_dst_lookup(sk, &dst, &fl);
+               int err = ip6_dst_lookup(sk, &dst, flp);
 
                if (err) {
                        sk->sk_err_soft = -err;
                        return err;
                }
 
+               if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+                       sk->sk_err_soft = -err;
+                       dst_release(dst);
+                       return err;
+               }
+
                ip6_dst_store(sk, dst, NULL);
                sk->sk_route_caps = dst->dev->features &
                        ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
diff -ruNBE a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c    2004-07-28 10:10:23.000000000 +0900
+++ b/net/ipv6/udp.c    2004-07-28 10:29:41.000000000 +0900
@@ -630,13 +630,13 @@
        struct in6_addr *daddr;
        struct ipv6_txoptions *opt = NULL;
        struct ip6_flowlabel *flowlabel = NULL;
-       struct flowi *fl = &inet->cork.fl;
-       struct dst_entry *dst;
+       struct flowi *fl = &inet->cork.fl, fl_rt, *flp = fl;
+       struct dst_entry *dst = NULL;
        int addr_len = msg->msg_namelen;
        int ulen = len;
        int hlimit = -1;
        int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
-       int err;
+       int err = 0;
 
        /* destination address check */
        if (sin6) {
@@ -779,20 +779,28 @@
        if (ipv6_addr_any(&fl->fl6_src) && !ipv6_addr_any(&np->saddr))
                ipv6_addr_copy(&fl->fl6_src, &np->saddr);
        fl->fl_ip_sport = inet->sport;
-       
+
        /* merge ip6_build_xmit from ip6_output */
        if (opt && opt->srcrt) {
                struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
-               ipv6_addr_copy(&fl->fl6_dst, rt0->addr);
+               memcpy(&fl_rt, &fl, sizeof(fl_rt));
+               ipv6_addr_copy(&fl_rt.fl6_dst, rt0->addr);
+               flp = &fl_rt;
        }
 
        if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst))
                fl->oif = np->mcast_oif;
 
-       err = ip6_dst_lookup(sk, &dst, fl);
+       err = ip6_dst_lookup(sk, &dst, flp);
        if (err)
                goto out;
 
+       if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
+               dst_release(dst);
+               dst = NULL;
+               goto out;
+       }
+
        if (hlimit < 0) {
                if (ipv6_addr_is_multicast(&fl->fl6_dst))
                        hlimit = np->mcast_hops;

<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH][IPv6] separation xfrm_lookup from ip6_dst_lookup, Kazunori Miyazawa <=