]> Pileus Git - ~andy/linux/blobdiff - net/dccp/ipv4.c
net: ip_expire() must revalidate route
[~andy/linux] / net / dccp / ipv4.c
index 45a434f94169f13daf1addc73cdb809d77fae213..ae451c6d83baa468596e136c3001cabc96edf1cd 100644 (file)
@@ -43,9 +43,9 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        struct inet_sock *inet = inet_sk(sk);
        struct dccp_sock *dp = dccp_sk(sk);
        const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
+       __be16 orig_sport, orig_dport;
        struct rtable *rt;
        __be32 daddr, nexthop;
-       int tmp;
        int err;
 
        dp->dccps_role = DCCP_ROLE_CLIENT;
@@ -63,12 +63,14 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                nexthop = inet->opt->faddr;
        }
 
-       tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr,
-                              RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
-                              IPPROTO_DCCP,
-                              inet->inet_sport, usin->sin_port, sk, 1);
-       if (tmp < 0)
-               return tmp;
+       orig_sport = inet->inet_sport;
+       orig_dport = usin->sin_port;
+       rt = ip_route_connect(nexthop, inet->inet_saddr,
+                             RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
+                             IPPROTO_DCCP,
+                             orig_sport, orig_dport, sk, true);
+       if (IS_ERR(rt))
+               return PTR_ERR(rt);
 
        if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
                ip_rt_put(rt);
@@ -99,11 +101,13 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (err != 0)
                goto failure;
 
-       err = ip_route_newports(&rt, IPPROTO_DCCP, inet->inet_sport,
-                               inet->inet_dport, sk);
-       if (err != 0)
+       rt = ip_route_newports(rt, IPPROTO_DCCP,
+                              orig_sport, orig_dport,
+                              inet->inet_sport, inet->inet_dport, sk);
+       if (IS_ERR(rt)) {
+               rt = NULL;
                goto failure;
-
+       }
        /* OK, now commit destination to socket.  */
        sk_setup_caps(sk, &rt->dst);
 
@@ -461,17 +465,19 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
                                           struct sk_buff *skb)
 {
        struct rtable *rt;
-       struct flowi fl = { .oif = skb_rtable(skb)->rt_iif,
-                           .fl4_dst = ip_hdr(skb)->saddr,
-                           .fl4_src = ip_hdr(skb)->daddr,
-                           .fl4_tos = RT_CONN_FLAGS(sk),
-                           .proto = sk->sk_protocol,
-                           .fl_ip_sport = dccp_hdr(skb)->dccph_dport,
-                           .fl_ip_dport = dccp_hdr(skb)->dccph_sport
-                         };
-
-       security_skb_classify_flow(skb, &fl);
-       if (ip_route_output_flow(net, &rt, &fl, sk, 0)) {
+       struct flowi4 fl4 = {
+               .flowi4_oif = skb_rtable(skb)->rt_iif,
+               .daddr = ip_hdr(skb)->saddr,
+               .saddr = ip_hdr(skb)->daddr,
+               .flowi4_tos = RT_CONN_FLAGS(sk),
+               .flowi4_proto = sk->sk_protocol,
+               .fl4_sport = dccp_hdr(skb)->dccph_dport,
+               .fl4_dport = dccp_hdr(skb)->dccph_sport,
+       };
+
+       security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
+       rt = ip_route_output_flow(net, &fl4, sk);
+       if (IS_ERR(rt)) {
                IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
                return NULL;
        }