Skip to content

Commit 7487449

Browse files
Paolo Abenidavem330
authored andcommitted
IPv4: early demux can return an error code
Currently no error is emitted, but this infrastructure will used by the next patch to allow source address validation for mcast sockets. Since early demux can do a route lookup and an ipv4 route lookup can return an error code this is consistent with the current ipv4 route infrastructure. Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d41bb33 commit 7487449

File tree

6 files changed

+30
-23
lines changed

6 files changed

+30
-23
lines changed

include/net/protocol.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939

4040
/* This is used to register protocols. */
4141
struct net_protocol {
42-
void (*early_demux)(struct sk_buff *skb);
43-
void (*early_demux_handler)(struct sk_buff *skb);
42+
int (*early_demux)(struct sk_buff *skb);
43+
int (*early_demux_handler)(struct sk_buff *skb);
4444
int (*handler)(struct sk_buff *skb);
4545
void (*err_handler)(struct sk_buff *skb, u32 info);
4646
unsigned int no_policy:1,

include/net/tcp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ void tcp_v4_err(struct sk_buff *skb, u32);
345345

346346
void tcp_shutdown(struct sock *sk, int how);
347347

348-
void tcp_v4_early_demux(struct sk_buff *skb);
348+
int tcp_v4_early_demux(struct sk_buff *skb);
349349
int tcp_v4_rcv(struct sk_buff *skb);
350350

351351
int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);

include/net/udp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ static inline struct sk_buff *skb_recv_udp(struct sock *sk, unsigned int flags,
259259
return __skb_recv_udp(sk, flags, noblock, &peeked, &off, err);
260260
}
261261

262-
void udp_v4_early_demux(struct sk_buff *skb);
262+
int udp_v4_early_demux(struct sk_buff *skb);
263263
bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst);
264264
int udp_get_port(struct sock *sk, unsigned short snum,
265265
int (*saddr_cmp)(const struct sock *,

net/ipv4/ip_input.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,10 @@ static inline bool ip_rcv_options(struct sk_buff *skb)
311311
static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
312312
{
313313
const struct iphdr *iph = ip_hdr(skb);
314-
struct rtable *rt;
314+
int (*edemux)(struct sk_buff *skb);
315315
struct net_device *dev = skb->dev;
316-
void (*edemux)(struct sk_buff *skb);
316+
struct rtable *rt;
317+
int err;
317318

318319
/* if ingress device is enslaved to an L3 master device pass the
319320
* skb to its handler for processing
@@ -331,7 +332,9 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
331332

332333
ipprot = rcu_dereference(inet_protos[protocol]);
333334
if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) {
334-
edemux(skb);
335+
err = edemux(skb);
336+
if (unlikely(err))
337+
goto drop_error;
335338
/* must reload iph, skb->head might have changed */
336339
iph = ip_hdr(skb);
337340
}
@@ -342,13 +345,10 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
342345
* how the packet travels inside Linux networking.
343346
*/
344347
if (!skb_valid_dst(skb)) {
345-
int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
346-
iph->tos, dev);
347-
if (unlikely(err)) {
348-
if (err == -EXDEV)
349-
__NET_INC_STATS(net, LINUX_MIB_IPRPFILTER);
350-
goto drop;
351-
}
348+
err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
349+
iph->tos, dev);
350+
if (unlikely(err))
351+
goto drop_error;
352352
}
353353

354354
#ifdef CONFIG_IP_ROUTE_CLASSID
@@ -399,6 +399,11 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
399399
drop:
400400
kfree_skb(skb);
401401
return NET_RX_DROP;
402+
403+
drop_error:
404+
if (err == -EXDEV)
405+
__NET_INC_STATS(net, LINUX_MIB_IPRPFILTER);
406+
goto drop;
402407
}
403408

404409
/*

net/ipv4/tcp_ipv4.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,23 +1503,23 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
15031503
}
15041504
EXPORT_SYMBOL(tcp_v4_do_rcv);
15051505

1506-
void tcp_v4_early_demux(struct sk_buff *skb)
1506+
int tcp_v4_early_demux(struct sk_buff *skb)
15071507
{
15081508
const struct iphdr *iph;
15091509
const struct tcphdr *th;
15101510
struct sock *sk;
15111511

15121512
if (skb->pkt_type != PACKET_HOST)
1513-
return;
1513+
return 0;
15141514

15151515
if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
1516-
return;
1516+
return 0;
15171517

15181518
iph = ip_hdr(skb);
15191519
th = tcp_hdr(skb);
15201520

15211521
if (th->doff < sizeof(struct tcphdr) / 4)
1522-
return;
1522+
return 0;
15231523

15241524
sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
15251525
iph->saddr, th->source,
@@ -1538,6 +1538,7 @@ void tcp_v4_early_demux(struct sk_buff *skb)
15381538
skb_dst_set_noref(skb, dst);
15391539
}
15401540
}
1541+
return 0;
15411542
}
15421543

15431544
bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)

net/ipv4/udp.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,7 +2221,7 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
22212221
return NULL;
22222222
}
22232223

2224-
void udp_v4_early_demux(struct sk_buff *skb)
2224+
int udp_v4_early_demux(struct sk_buff *skb)
22252225
{
22262226
struct net *net = dev_net(skb->dev);
22272227
const struct iphdr *iph;
@@ -2234,7 +2234,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
22342234

22352235
/* validate the packet */
22362236
if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)))
2237-
return;
2237+
return 0;
22382238

22392239
iph = ip_hdr(skb);
22402240
uh = udp_hdr(skb);
@@ -2244,14 +2244,14 @@ void udp_v4_early_demux(struct sk_buff *skb)
22442244
struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
22452245

22462246
if (!in_dev)
2247-
return;
2247+
return 0;
22482248

22492249
/* we are supposed to accept bcast packets */
22502250
if (skb->pkt_type == PACKET_MULTICAST) {
22512251
ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
22522252
iph->protocol);
22532253
if (!ours)
2254-
return;
2254+
return 0;
22552255
}
22562256

22572257
sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
@@ -2263,7 +2263,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
22632263
}
22642264

22652265
if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
2266-
return;
2266+
return 0;
22672267

22682268
skb->sk = sk;
22692269
skb->destructor = sock_efree;
@@ -2278,6 +2278,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
22782278
*/
22792279
skb_dst_set_noref(skb, dst);
22802280
}
2281+
return 0;
22812282
}
22822283

22832284
int udp_rcv(struct sk_buff *skb)

0 commit comments

Comments
 (0)