ip/options: explicitly provide net ns to __ip_options_echo()
authorPaolo Abeni <pabeni@redhat.com>
Thu, 3 Aug 2017 16:07:06 +0000 (18:07 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 7 Aug 2017 03:51:12 +0000 (20:51 -0700)
__ip_options_echo() uses the current network namespace, and
currently retrives it via skb->dst->dev.

This commit adds an explicit 'net' argument to __ip_options_echo()
and update all the call sites to provide it, usually via a simpler
sock_net().

After this change, __ip_options_echo() no more needs to access
skb->dst and we can drop a couple of hack to preserve such
info in the rx path.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip.h
include/net/tcp.h
net/ipv4/icmp.c
net/ipv4/ip_options.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/syncookies.c
net/ipv4/tcp_ipv4.c

index 821cedcc8e73b68af72d1918242c25d757c63d24..9e59dcf1787a88a06153dab81584cdafb9c8b8ba 100644 (file)
@@ -567,11 +567,12 @@ int ip_forward(struct sk_buff *skb);
 void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
                      __be32 daddr, struct rtable *rt, int is_frag);
 
-int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
-                     const struct ip_options *sopt);
-static inline int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb)
+int __ip_options_echo(struct net *net, struct ip_options *dopt,
+                     struct sk_buff *skb, const struct ip_options *sopt);
+static inline int ip_options_echo(struct net *net, struct ip_options *dopt,
+                                 struct sk_buff *skb)
 {
-       return __ip_options_echo(dopt, skb, &IPCB(skb)->opt);
+       return __ip_options_echo(net, dopt, skb, &IPCB(skb)->opt);
 }
 
 void ip_options_fragment(struct sk_buff *skb);
index bb1881b4ce486b38ade45e5a7d9a2ba03bb7c279..5173fecde495dc2201dbc26cab464e01d4308ab7 100644 (file)
@@ -1885,7 +1885,8 @@ extern void tcp_rack_reo_timeout(struct sock *sk);
 /*
  * Save and compile IPv4 options, return a pointer to it
  */
-static inline struct ip_options_rcu *tcp_v4_save_options(struct sk_buff *skb)
+static inline struct ip_options_rcu *tcp_v4_save_options(struct net *net,
+                                                        struct sk_buff *skb)
 {
        const struct ip_options *opt = &TCP_SKB_CB(skb)->header.h4.opt;
        struct ip_options_rcu *dopt = NULL;
@@ -1894,7 +1895,7 @@ static inline struct ip_options_rcu *tcp_v4_save_options(struct sk_buff *skb)
                int opt_size = sizeof(*dopt) + opt->optlen;
 
                dopt = kmalloc(opt_size, GFP_ATOMIC);
-               if (dopt && __ip_options_echo(&dopt->opt, skb, opt)) {
+               if (dopt && __ip_options_echo(net, &dopt->opt, skb, opt)) {
                        kfree(dopt);
                        dopt = NULL;
                }
index c2be26b98b5fc2ff4c3e3706ce179f4c0f332b69..681e33998e03b609fdca83a83e0fc62a3fee8c39 100644 (file)
@@ -412,7 +412,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
        int type = icmp_param->data.icmph.type;
        int code = icmp_param->data.icmph.code;
 
-       if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb))
+       if (ip_options_echo(net, &icmp_param->replyopts.opt.opt, skb))
                return;
 
        /* Needed by both icmp_global_allow and icmp_xmit_lock */
@@ -694,7 +694,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
                                          iph->tos;
        mark = IP4_REPLY_MARK(net, skb_in->mark);
 
-       if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in))
+       if (ip_options_echo(net, &icmp_param.replyopts.opt.opt, skb_in))
                goto out_unlock;
 
 
index fdda97308c0be6b4a4153e4d96b4efd9751a83dd..525ae88d1e586e0c5d3abf6c64a22e5367a01a8d 100644 (file)
@@ -86,8 +86,8 @@ void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
  * NOTE: dopt cannot point to skb.
  */
 
-int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
-                     const struct ip_options *sopt)
+int __ip_options_echo(struct net *net, struct ip_options *dopt,
+                     struct sk_buff *skb, const struct ip_options *sopt)
 {
        unsigned char *sptr, *dptr;
        int soffset, doffset;
@@ -140,7 +140,7 @@ int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
                                                __be32 addr;
 
                                                memcpy(&addr, dptr+soffset-1, 4);
-                                               if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) {
+                                               if (inet_addr_type(net, addr) != RTN_UNICAST) {
                                                        dopt->ts_needtime = 1;
                                                        soffset += 8;
                                                }
index b631ec685d7719f4229e8573e08795f78bd6881a..73b0b15245b62f6d674e289422a203cef2951e43 100644 (file)
@@ -1525,7 +1525,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
        int err;
        int oif;
 
-       if (__ip_options_echo(&replyopts.opt.opt, skb, sopt))
+       if (__ip_options_echo(net, &replyopts.opt.opt, skb, sopt))
                return;
 
        ipc.addr = daddr;
index ecc4b4a2413e337c059a3468f584575497b8457b..1c3354d028a428a95fdd44ff1c8b1a1acdf07e82 100644 (file)
@@ -80,7 +80,8 @@ static void ip_cmsg_recv_opts(struct msghdr *msg, struct sk_buff *skb)
 }
 
 
-static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
+static void ip_cmsg_recv_retopts(struct net *net, struct msghdr *msg,
+                                struct sk_buff *skb)
 {
        unsigned char optbuf[sizeof(struct ip_options) + 40];
        struct ip_options *opt = (struct ip_options *)optbuf;
@@ -88,7 +89,7 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
        if (IPCB(skb)->opt.optlen == 0)
                return;
 
-       if (ip_options_echo(opt, skb)) {
+       if (ip_options_echo(net, opt, skb)) {
                msg->msg_flags |= MSG_CTRUNC;
                return;
        }
@@ -204,7 +205,7 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
        }
 
        if (flags & IP_CMSG_RETOPTS) {
-               ip_cmsg_recv_retopts(msg, skb);
+               ip_cmsg_recv_retopts(sock_net(sk), msg, skb);
 
                flags &= ~IP_CMSG_RETOPTS;
                if (!flags)
index 03ad8778c395334ed53a250bccc0b991cd85c2f2..b1bb1b3a108232d56aa82383422d68b5ff9da3ed 100644 (file)
@@ -355,7 +355,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
        /* We throwed the options of the initial SYN away, so we hope
         * the ACK carries the same options again (see RFC1122 4.2.3.8)
         */
-       ireq->opt = tcp_v4_save_options(skb);
+       ireq->opt = tcp_v4_save_options(sock_net(sk), skb);
 
        if (security_inet_conn_request(sk, skb, req)) {
                reqsk_free(req);
index 9b51663cd5a409ae8c562ea2325498e0df63ea32..5f708c85110e33f82b0a0e44d7a60df1f3b0587f 100644 (file)
@@ -1267,7 +1267,7 @@ static void tcp_v4_init_req(struct request_sock *req,
 
        sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr);
        sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr);
-       ireq->opt = tcp_v4_save_options(skb);
+       ireq->opt = tcp_v4_save_options(sock_net(sk_listener), skb);
 }
 
 static struct dst_entry *tcp_v4_route_req(const struct sock *sk,