Skip to content

Commit 21e27f2

Browse files
committed
Merge branch 'IP-cleanup-LSRR-option-processing'
Paolo Abeni says: ==================== IP: cleanup LSRR option processing The __ip_options_echo() function expect a valid dst entry in skb->dst; as result we sometimes need to preserve the dst entry for the whole IP RX path. The current usage of skb->dst looks more a relic from ancient past that a real functional constraint. This patchset tries to remove such usage, and than drops some hacks currently in place in the IP code to keep skb->dst around. __ip_options_echo() uses of skb->dst for two different purposes: retrieving the netns assicated with the skb, and modify the ingress packet LSRR address list. The first patch removes the code modifying the ingress packet, and the second one provides an explicit netns argument to __ip_options_echo(). The following patches cleanup the current code keeping arund skb->dst for __ip_options_echo's sake. Updating the __ip_options_echo() function has been previously discussed here: http://marc.info/?l=linux-netdev&m=150064533516348&w=2 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents a54df68 + 3bdefdf commit 21e27f2

File tree

9 files changed

+26
-36
lines changed

9 files changed

+26
-36
lines changed

include/net/ip.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,12 @@ int ip_forward(struct sk_buff *skb);
567567
void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
568568
__be32 daddr, struct rtable *rt, int is_frag);
569569

570-
int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
571-
const struct ip_options *sopt);
572-
static inline int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb)
570+
int __ip_options_echo(struct net *net, struct ip_options *dopt,
571+
struct sk_buff *skb, const struct ip_options *sopt);
572+
static inline int ip_options_echo(struct net *net, struct ip_options *dopt,
573+
struct sk_buff *skb)
573574
{
574-
return __ip_options_echo(dopt, skb, &IPCB(skb)->opt);
575+
return __ip_options_echo(net, dopt, skb, &IPCB(skb)->opt);
575576
}
576577

577578
void ip_options_fragment(struct sk_buff *skb);

include/net/tcp.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,7 +1885,8 @@ extern void tcp_rack_reo_timeout(struct sock *sk);
18851885
/*
18861886
* Save and compile IPv4 options, return a pointer to it
18871887
*/
1888-
static inline struct ip_options_rcu *tcp_v4_save_options(struct sk_buff *skb)
1888+
static inline struct ip_options_rcu *tcp_v4_save_options(struct net *net,
1889+
struct sk_buff *skb)
18891890
{
18901891
const struct ip_options *opt = &TCP_SKB_CB(skb)->header.h4.opt;
18911892
struct ip_options_rcu *dopt = NULL;
@@ -1894,7 +1895,7 @@ static inline struct ip_options_rcu *tcp_v4_save_options(struct sk_buff *skb)
18941895
int opt_size = sizeof(*dopt) + opt->optlen;
18951896

18961897
dopt = kmalloc(opt_size, GFP_ATOMIC);
1897-
if (dopt && __ip_options_echo(&dopt->opt, skb, opt)) {
1898+
if (dopt && __ip_options_echo(net, &dopt->opt, skb, opt)) {
18981899
kfree(dopt);
18991900
dopt = NULL;
19001901
}

net/ipv4/icmp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
412412
int type = icmp_param->data.icmph.type;
413413
int code = icmp_param->data.icmph.code;
414414

415-
if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb))
415+
if (ip_options_echo(net, &icmp_param->replyopts.opt.opt, skb))
416416
return;
417417

418418
/* 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)
694694
iph->tos;
695695
mark = IP4_REPLY_MARK(net, skb_in->mark);
696696

697-
if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in))
697+
if (ip_options_echo(net, &icmp_param.replyopts.opt.opt, skb_in))
698698
goto out_unlock;
699699

700700

net/ipv4/ip_options.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
8686
* NOTE: dopt cannot point to skb.
8787
*/
8888

89-
int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
90-
const struct ip_options *sopt)
89+
int __ip_options_echo(struct net *net, struct ip_options *dopt,
90+
struct sk_buff *skb, const struct ip_options *sopt)
9191
{
9292
unsigned char *sptr, *dptr;
9393
int soffset, doffset;
@@ -140,7 +140,7 @@ int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
140140
__be32 addr;
141141

142142
memcpy(&addr, dptr+soffset-1, 4);
143-
if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) {
143+
if (inet_addr_type(net, addr) != RTN_UNICAST) {
144144
dopt->ts_needtime = 1;
145145
soffset += 8;
146146
}
@@ -174,9 +174,6 @@ int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
174174
doffset -= 4;
175175
}
176176
if (doffset > 3) {
177-
__be32 daddr = fib_compute_spec_dst(skb);
178-
179-
memcpy(&start[doffset-1], &daddr, 4);
180177
dopt->faddr = faddr;
181178
dptr[0] = start[0];
182179
dptr[1] = doffset+3;

net/ipv4/ip_output.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1525,7 +1525,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
15251525
int err;
15261526
int oif;
15271527

1528-
if (__ip_options_echo(&replyopts.opt.opt, skb, sopt))
1528+
if (__ip_options_echo(net, &replyopts.opt.opt, skb, sopt))
15291529
return;
15301530

15311531
ipc.addr = daddr;

net/ipv4/ip_sockglue.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,16 @@ static void ip_cmsg_recv_opts(struct msghdr *msg, struct sk_buff *skb)
8080
}
8181

8282

83-
static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
83+
static void ip_cmsg_recv_retopts(struct net *net, struct msghdr *msg,
84+
struct sk_buff *skb)
8485
{
8586
unsigned char optbuf[sizeof(struct ip_options) + 40];
8687
struct ip_options *opt = (struct ip_options *)optbuf;
8788

8889
if (IPCB(skb)->opt.optlen == 0)
8990
return;
9091

91-
if (ip_options_echo(opt, skb)) {
92+
if (ip_options_echo(net, opt, skb)) {
9293
msg->msg_flags |= MSG_CTRUNC;
9394
return;
9495
}
@@ -204,7 +205,7 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
204205
}
205206

206207
if (flags & IP_CMSG_RETOPTS) {
207-
ip_cmsg_recv_retopts(msg, skb);
208+
ip_cmsg_recv_retopts(sock_net(sk), msg, skb);
208209

209210
flags &= ~IP_CMSG_RETOPTS;
210211
if (!flags)
@@ -1227,14 +1228,7 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
12271228
pktinfo->ipi_ifindex = 0;
12281229
pktinfo->ipi_spec_dst.s_addr = 0;
12291230
}
1230-
/* We need to keep the dst for __ip_options_echo()
1231-
* We could restrict the test to opt.ts_needtime || opt.srr,
1232-
* but the following is good enough as IP options are not often used.
1233-
*/
1234-
if (unlikely(IPCB(skb)->opt.optlen))
1235-
skb_dst_force(skb);
1236-
else
1237-
skb_dst_drop(skb);
1231+
skb_dst_drop(skb);
12381232
}
12391233

12401234
int ip_setsockopt(struct sock *sk, int level,

net/ipv4/syncookies.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
355355
/* We throwed the options of the initial SYN away, so we hope
356356
* the ACK carries the same options again (see RFC1122 4.2.3.8)
357357
*/
358-
ireq->opt = tcp_v4_save_options(skb);
358+
ireq->opt = tcp_v4_save_options(sock_net(sk), skb);
359359

360360
if (security_inet_conn_request(sk, skb, req)) {
361361
reqsk_free(req);

net/ipv4/tcp_ipv4.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1267,7 +1267,7 @@ static void tcp_v4_init_req(struct request_sock *req,
12671267

12681268
sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr);
12691269
sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr);
1270-
ireq->opt = tcp_v4_save_options(skb);
1270+
ireq->opt = tcp_v4_save_options(sock_net(sk_listener), skb);
12711271
}
12721272

12731273
static struct dst_entry *tcp_v4_route_req(const struct sock *sk,

net/ipv4/udp.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,11 @@ static void udp_set_dev_scratch(struct sk_buff *skb)
11761176
scratch->csum_unnecessary = !!skb_csum_unnecessary(skb);
11771177
scratch->is_linear = !skb_is_nonlinear(skb);
11781178
#endif
1179-
if (likely(!skb->_skb_refdst))
1179+
/* all head states execept sp (dst, sk, nf) are always cleared by
1180+
* udp_rcv() and we need to preserve secpath, if present, to eventually
1181+
* process IP_CMSG_PASSSEC at recvmsg() time
1182+
*/
1183+
if (likely(!skb_sec_path(skb)))
11801184
scratch->_tsize_state |= UDP_SKB_IS_STATELESS;
11811185
}
11821186

@@ -1782,13 +1786,6 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
17821786
sk_mark_napi_id_once(sk, skb);
17831787
}
17841788

1785-
/* At recvmsg() time we may access skb->dst or skb->sp depending on
1786-
* the IP options and the cmsg flags, elsewhere can we clear all
1787-
* pending head states while they are hot in the cache
1788-
*/
1789-
if (likely(IPCB(skb)->opt.optlen == 0 && !skb_sec_path(skb)))
1790-
skb_release_head_state(skb);
1791-
17921789
rc = __udp_enqueue_schedule_skb(sk, skb);
17931790
if (rc < 0) {
17941791
int is_udplite = IS_UDPLITE(sk);

0 commit comments

Comments
 (0)