Blame view

net/ipv4/ip_input.c 18.3 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
  /*
   * INET		An implementation of the TCP/IP protocol suite for the LINUX
   *		operating system.  INET is implemented using the  BSD Socket
   *		interface as the means of communication with the user level.
   *
   *		The Internet Protocol (IP) module.
   *
02c30a84e   Jesper Juhl   [PATCH] update Ro...
9
   * Authors:	Ross Biro
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
   *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *		Donald Becker, <becker@super.org>
113aa838e   Alan Cox   net: Rationalise ...
12
   *		Alan Cox, <alan@lxorguk.ukuu.org.uk>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
16
   *		Richard Underwood
   *		Stefan Becker, <stefanb@yello.ping.de>
   *		Jorge Cwik, <jorge@laser.satlink.net>
   *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
17
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
   * Fixes:
   *		Alan Cox	:	Commented a couple of minor bits of surplus code
   *		Alan Cox	:	Undefining IP_FORWARD doesn't include the code
   *					(just stops a compiler warning).
   *		Alan Cox	:	Frames with >=MAX_ROUTE record routes, strict routes or loose routes
   *					are junked rather than corrupting things.
   *		Alan Cox	:	Frames to bad broadcast subnets are dumped
   *					We used to process them non broadcast and
   *					boy could that cause havoc.
   *		Alan Cox	:	ip_forward sets the free flag on the
   *					new frame it queues. Still crap because
   *					it copies the frame but at least it
   *					doesn't eat memory too.
   *		Alan Cox	:	Generic queue code and memory fixes.
   *		Fred Van Kempen :	IP fragment support (borrowed from NET2E)
   *		Gerhard Koerting:	Forward fragmented frames correctly.
   *		Gerhard Koerting: 	Fixes to my fix of the above 8-).
   *		Gerhard Koerting:	IP interface addressing fix.
   *		Linus Torvalds	:	More robustness checks
   *		Alan Cox	:	Even more checks: Still not as robust as it ought to be
   *		Alan Cox	:	Save IP header pointer for later
   *		Alan Cox	:	ip option setting
   *		Alan Cox	:	Use ip_tos/ip_ttl settings
   *		Alan Cox	:	Fragmentation bogosity removed
   *					(Thanks to Mark.Bush@prg.ox.ac.uk)
   *		Dmitry Gorodchanin :	Send of a raw packet crash fix.
   *		Alan Cox	:	Silly ip bug when an overlength
   *					fragment turns up. Now frees the
   *					queue.
   *		Linus Torvalds/ :	Memory leakage on fragmentation
   *		Alan Cox	:	handling.
   *		Gerhard Koerting:	Forwarding uses IP priority hints
   *		Teemu Rantanen	:	Fragment problems.
   *		Alan Cox	:	General cleanup, comments and reformat
   *		Alan Cox	:	SNMP statistics
   *		Alan Cox	:	BSD address rule semantics. Also see
   *					UDP as there is a nasty checksum issue
   *					if you do things the wrong way.
   *		Alan Cox	:	Always defrag, moved IP_FORWARD to the config.in file
   *		Alan Cox	: 	IP options adjust sk->priority.
   *		Pedro Roque	:	Fix mtu/length error in ip_forward.
   *		Alan Cox	:	Avoid ip_chk_addr when possible.
   *	Richard Underwood	:	IP multicasting.
   *		Alan Cox	:	Cleaned up multicast handlers.
   *		Alan Cox	:	RAW sockets demultiplex in the BSD style.
   *		Gunther Mayer	:	Fix the SNMP reporting typo
   *		Alan Cox	:	Always in group 224.0.0.1
   *	Pauline Middelink	:	Fast ip_checksum update when forwarding
   *					Masquerading support.
   *		Alan Cox	:	Multicast loopback error for 224.0.0.1
   *		Alan Cox	:	IP_MULTICAST_LOOP option.
   *		Alan Cox	:	Use notifiers.
   *		Bjorn Ekwall	:	Removed ip_csum (from slhc.c too)
   *		Bjorn Ekwall	:	Moved ip_fast_csum to ip.h (inline!)
   *		Stefan Becker   :       Send out ICMP HOST REDIRECT
   *	Arnt Gulbrandsen	:	ip_build_xmit
   *		Alan Cox	:	Per socket routing cache
   *		Alan Cox	:	Fixed routing cache, added header cache.
   *		Alan Cox	:	Loopback didn't work right in original ip_build_xmit - fixed it.
   *		Alan Cox	:	Only send ICMP_REDIRECT if src/dest are the same net.
   *		Alan Cox	:	Incoming IP option handling.
   *		Alan Cox	:	Set saddr on raw output frames as per BSD.
   *		Alan Cox	:	Stopped broadcast source route explosions.
   *		Alan Cox	:	Can disable source routing
   *		Takeshi Sone    :	Masquerading didn't work.
   *	Dave Bonn,Alan Cox	:	Faster IP forwarding whenever possible.
   *		Alan Cox	:	Memory leaks, tramples, misc debugging.
   *		Alan Cox	:	Fixed multicast (by popular demand 8))
   *		Alan Cox	:	Fixed forwarding (by even more popular demand 8))
   *		Alan Cox	:	Fixed SNMP statistics [I think]
   *	Gerhard Koerting	:	IP fragmentation forwarding fix
   *		Alan Cox	:	Device lock against page fault.
   *		Alan Cox	:	IP_HDRINCL facility.
   *	Werner Almesberger	:	Zero fragment bug
   *		Alan Cox	:	RAW IP frame length bug
   *		Alan Cox	:	Outgoing firewall on build_xmit
   *		A.N.Kuznetsov	:	IP_OPTIONS support throughout the kernel
   *		Alan Cox	:	Multicast routing hooks
   *		Jos Vos		:	Do accounting *before* call_in_firewall
   *	Willy Konynenberg	:	Transparent proxying support
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
101
102
   * To Fix:
   *		IP fragmentation wants rewriting cleanly. The RFC815 algorithm is much more efficient
   *		and could be made very efficient with the addition of some virtual memory hacks to permit
   *		the allocation of a buffer that can then be 'grown' by twiddling page tables.
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
103
   *		Output fragmentation wants updating along with the buffer management to use a single
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
   *		interleaved copy algorithm so that fragmenting has a one copy overhead. Actual packet
   *		output should probably do its own fragmentation at the UDP/RAW layer. TCP shouldn't cause
   *		fragmentation anyway.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
   */
afd465030   Joe Perches   net: ipv4: Standa...
108
  #define pr_fmt(fmt) "IPv4: " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/string.h>
  #include <linux/errno.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
114
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
119
120
  
  #include <linux/net.h>
  #include <linux/socket.h>
  #include <linux/sockios.h>
  #include <linux/in.h>
  #include <linux/inet.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
121
  #include <linux/inetdevice.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
0e219ae48   Paolo Abeni   net: use indirect...
124
  #include <linux/indirect_call_wrapper.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
128
129
130
131
132
133
134
135
  
  #include <net/snmp.h>
  #include <net/ip.h>
  #include <net/protocol.h>
  #include <net/route.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
  #include <net/arp.h>
  #include <net/icmp.h>
  #include <net/raw.h>
  #include <net/checksum.h>
1f07d03e2   Eric Dumazet   net: add SNMP cou...
136
  #include <net/inet_ecn.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
  #include <linux/netfilter_ipv4.h>
  #include <net/xfrm.h>
  #include <linux/mroute.h>
  #include <linux/netlink.h>
f38a9eb1f   Thomas Graf   dst: Metadata des...
141
  #include <net/dst_metadata.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
  
  /*
66018506e   Eric Dumazet   ip: Router Alert ...
144
   *	Process Router Attention IP option (RFC 2113)
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
145
   */
ba57b4db2   David S. Miller   ipv4: Make ip_cal...
146
  bool ip_call_ra_chain(struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
  {
  	struct ip_ra_chain *ra;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
149
  	u8 protocol = ip_hdr(skb)->protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  	struct sock *last = NULL;
cb84663e4   Denis V. Lunev   [NETNS]: Process ...
151
  	struct net_device *dev = skb->dev;
37fcbab61   Eric W. Biederman   ipv4: Only comput...
152
  	struct net *net = dev_net(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153

5796ef75e   Kirill Tkhai   net: Make ip_ra_c...
154
  	for (ra = rcu_dereference(net->ipv4.ra_chain); ra; ra = rcu_dereference(ra->next)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
157
158
159
  		struct sock *sk = ra->sk;
  
  		/* If socket is bound to an interface, only report
  		 * the packet if it came  from that interface.
  		 */
c720c7e83   Eric Dumazet   inet: rename some...
160
  		if (sk && inet_sk(sk)->inet_num == protocol &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  		    (!sk->sk_bound_dev_if ||
5796ef75e   Kirill Tkhai   net: Make ip_ra_c...
162
  		     sk->sk_bound_dev_if == dev->ifindex)) {
56f8a75c1   Paul Gortmaker   ip: introduce ip_...
163
  			if (ip_is_fragment(ip_hdr(skb))) {
19bcf9f20   Eric W. Biederman   ipv4: Pass struct...
164
  				if (ip_defrag(net, skb, IP_DEFRAG_CALL_RA_CHAIN))
ba57b4db2   David S. Miller   ipv4: Make ip_cal...
165
  					return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
169
170
171
172
173
174
175
176
177
  			}
  			if (last) {
  				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
  				if (skb2)
  					raw_rcv(last, skb2);
  			}
  			last = sk;
  		}
  	}
  
  	if (last) {
  		raw_rcv(last, skb);
ba57b4db2   David S. Miller   ipv4: Make ip_cal...
178
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  	}
ba57b4db2   David S. Miller   ipv4: Make ip_cal...
180
  	return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  }
0e219ae48   Paolo Abeni   net: use indirect...
182
183
  INDIRECT_CALLABLE_DECLARE(int udp_rcv(struct sk_buff *));
  INDIRECT_CALLABLE_DECLARE(int tcp_v4_rcv(struct sk_buff *));
68cb7d531   Paolo Abeni   ip: factor out pr...
184
  void ip_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int protocol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  {
68cb7d531   Paolo Abeni   ip: factor out pr...
186
187
  	const struct net_protocol *ipprot;
  	int raw, ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188

68cb7d531   Paolo Abeni   ip: factor out pr...
189
190
191
192
193
194
195
196
197
  resubmit:
  	raw = raw_local_deliver(skb, protocol);
  
  	ipprot = rcu_dereference(inet_protos[protocol]);
  	if (ipprot) {
  		if (!ipprot->no_policy) {
  			if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
  				kfree_skb(skb);
  				return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  			}
895b5c9f2   Florian Westphal   netfilter: drop b...
199
  			nf_reset_ct(skb);
68cb7d531   Paolo Abeni   ip: factor out pr...
200
  		}
0e219ae48   Paolo Abeni   net: use indirect...
201
202
  		ret = INDIRECT_CALL_2(ipprot->handler, tcp_v4_rcv, udp_rcv,
  				      skb);
68cb7d531   Paolo Abeni   ip: factor out pr...
203
204
205
206
207
208
209
210
211
212
213
  		if (ret < 0) {
  			protocol = -ret;
  			goto resubmit;
  		}
  		__IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS);
  	} else {
  		if (!raw) {
  			if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
  				__IP_INC_STATS(net, IPSTATS_MIB_INUNKNOWNPROTOS);
  				icmp_send(skb, ICMP_DEST_UNREACH,
  					  ICMP_PROT_UNREACH, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  			}
68cb7d531   Paolo Abeni   ip: factor out pr...
215
  			kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
  		} else {
68cb7d531   Paolo Abeni   ip: factor out pr...
217
218
  			__IP_INC_STATS(net, IPSTATS_MIB_INDELIVERS);
  			consume_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
  		}
  	}
68cb7d531   Paolo Abeni   ip: factor out pr...
221
222
223
224
225
226
227
228
  }
  
  static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
  {
  	__skb_pull(skb, skb_network_header_len(skb));
  
  	rcu_read_lock();
  	ip_protocol_deliver_rcu(net, skb, ip_hdr(skb)->protocol);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
232
233
234
235
  	rcu_read_unlock();
  
  	return 0;
  }
  
  /*
   * 	Deliver IP Packets to the higher protocol layers.
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
236
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
  int ip_local_deliver(struct sk_buff *skb)
  {
  	/*
  	 *	Reassemble IP fragments.
  	 */
19bcf9f20   Eric W. Biederman   ipv4: Pass struct...
242
  	struct net *net = dev_net(skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

56f8a75c1   Paul Gortmaker   ip: introduce ip_...
244
  	if (ip_is_fragment(ip_hdr(skb))) {
19bcf9f20   Eric W. Biederman   ipv4: Pass struct...
245
  		if (ip_defrag(net, skb, IP_DEFRAG_LOCAL_DELIVER))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
  			return 0;
  	}
29a26a568   Eric W. Biederman   netfilter: Pass s...
248
  	return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN,
19bcf9f20   Eric W. Biederman   ipv4: Pass struct...
249
  		       net, NULL, skb, skb->dev, NULL,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
  		       ip_local_deliver_finish);
  }
8c83f2df9   Stephen Suryaputra   vrf: check accept...
252
  static inline bool ip_rcv_options(struct sk_buff *skb, struct net_device *dev)
d245407e7   Thomas Graf   [IPV4]: Move ip o...
253
254
  {
  	struct ip_options *opt;
b71d1d426   Eric Dumazet   inet: constify ip...
255
  	const struct iphdr *iph;
d245407e7   Thomas Graf   [IPV4]: Move ip o...
256
257
258
259
260
261
262
263
264
  
  	/* It looks as overkill, because not all
  	   IP options require packet mangling.
  	   But it is the easiest for now, especially taking
  	   into account that combination of IP options
  	   and running sniffer is extremely rare condition.
  					      --ANK (980813)
  	*/
  	if (skb_cow(skb, skb_headroom(skb))) {
b45386efa   Eric Dumazet   net: rename IP_IN...
265
  		__IP_INC_STATS(dev_net(dev), IPSTATS_MIB_INDISCARDS);
d245407e7   Thomas Graf   [IPV4]: Move ip o...
266
267
  		goto drop;
  	}
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
268
  	iph = ip_hdr(skb);
22aba383c   Denis V. Lunev   [IPV4]: Always pa...
269
270
  	opt = &(IPCB(skb)->opt);
  	opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
d245407e7   Thomas Graf   [IPV4]: Move ip o...
271

c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
272
  	if (ip_options_compile(dev_net(dev), opt, skb)) {
b45386efa   Eric Dumazet   net: rename IP_IN...
273
  		__IP_INC_STATS(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
d245407e7   Thomas Graf   [IPV4]: Move ip o...
274
275
  		goto drop;
  	}
d245407e7   Thomas Graf   [IPV4]: Move ip o...
276
  	if (unlikely(opt->srr)) {
6e8b11b43   Eric Dumazet   net: avoid two at...
277
  		struct in_device *in_dev = __in_dev_get_rcu(dev);
d245407e7   Thomas Graf   [IPV4]: Move ip o...
278
279
  		if (in_dev) {
  			if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
e87cc4728   Joe Perches   net: Convert net_...
280
281
282
283
284
  				if (IN_DEV_LOG_MARTIANS(in_dev))
  					net_info_ratelimited("source route option %pI4 -> %pI4
  ",
  							     &iph->saddr,
  							     &iph->daddr);
d245407e7   Thomas Graf   [IPV4]: Move ip o...
285
286
  				goto drop;
  			}
d245407e7   Thomas Graf   [IPV4]: Move ip o...
287
  		}
8c83f2df9   Stephen Suryaputra   vrf: check accept...
288
  		if (ip_options_rcv_srr(skb, dev))
d245407e7   Thomas Graf   [IPV4]: Move ip o...
289
290
  			goto drop;
  	}
6a91395f2   David S. Miller   ipv4: Make ip_rcv...
291
  	return false;
d245407e7   Thomas Graf   [IPV4]: Move ip o...
292
  drop:
6a91395f2   David S. Miller   ipv4: Make ip_rcv...
293
  	return true;
d245407e7   Thomas Graf   [IPV4]: Move ip o...
294
  }
02b249416   Paolo Abeni   ipv4: use dst hin...
295
296
297
298
299
300
  static bool ip_can_use_hint(const struct sk_buff *skb, const struct iphdr *iph,
  			    const struct sk_buff *hint)
  {
  	return hint && !skb_dst(skb) && ip_hdr(hint)->daddr == iph->daddr &&
  	       ip_hdr(hint)->tos == iph->tos;
  }
97ff7ffb1   Paolo Abeni   net: use indirect...
301
302
  INDIRECT_CALLABLE_DECLARE(int udp_v4_early_demux(struct sk_buff *));
  INDIRECT_CALLABLE_DECLARE(int tcp_v4_early_demux(struct sk_buff *));
5fa12739a   Edward Cree   net: ipv4: listif...
303
  static int ip_rcv_finish_core(struct net *net, struct sock *sk,
02b249416   Paolo Abeni   ipv4: use dst hin...
304
305
  			      struct sk_buff *skb, struct net_device *dev,
  			      const struct sk_buff *hint)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
307
  	const struct iphdr *iph = ip_hdr(skb);
7487449c8   Paolo Abeni   IPv4: early demux...
308
  	int (*edemux)(struct sk_buff *skb);
7487449c8   Paolo Abeni   IPv4: early demux...
309
310
  	struct rtable *rt;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311

02b249416   Paolo Abeni   ipv4: use dst hin...
312
313
314
315
316
317
  	if (ip_can_use_hint(skb, iph, hint)) {
  		err = ip_route_use_hint(skb, iph->daddr, iph->saddr, iph->tos,
  					dev, hint);
  		if (unlikely(err))
  			goto drop_error;
  	}
e21145a98   Nikolay Borisov   ipv4: namespacify...
318
  	if (net->ipv4.sysctl_ip_early_demux &&
63e51b6a2   Eric Dumazet   ipv4: early demux...
319
320
321
  	    !skb_dst(skb) &&
  	    !skb->sk &&
  	    !ip_is_fragment(iph)) {
160eb5a6b   David S. Miller   ipv4: Kill early ...
322
323
  		const struct net_protocol *ipprot;
  		int protocol = iph->protocol;
160eb5a6b   David S. Miller   ipv4: Kill early ...
324
  		ipprot = rcu_dereference(inet_protos[protocol]);
dddb64bcb   subashab@codeaurora.org   net: Add sysctl t...
325
  		if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) {
97ff7ffb1   Paolo Abeni   net: use indirect...
326
327
  			err = INDIRECT_CALL_2(edemux, tcp_v4_early_demux,
  					      udp_v4_early_demux, skb);
7487449c8   Paolo Abeni   IPv4: early demux...
328
329
  			if (unlikely(err))
  				goto drop_error;
9cb429d69   Eric Dumazet   tcp: early_demux ...
330
331
332
  			/* must reload iph, skb->head might have changed */
  			iph = ip_hdr(skb);
  		}
160eb5a6b   David S. Miller   ipv4: Kill early ...
333
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
  	/*
  	 *	Initialise the virtual path cache for the packet. It describes
  	 *	how the packet travels inside Linux networking.
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
337
  	 */
f38a9eb1f   Thomas Graf   dst: Metadata des...
338
  	if (!skb_valid_dst(skb)) {
7487449c8   Paolo Abeni   IPv4: early demux...
339
340
341
342
  		err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
  					   iph->tos, dev);
  		if (unlikely(err))
  			goto drop_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
  	}
c7066f70d   Patrick McHardy   netfilter: fix Kc...
344
  #ifdef CONFIG_IP_ROUTE_CLASSID
adf30907d   Eric Dumazet   net: skb->dst acc...
345
  	if (unlikely(skb_dst(skb)->tclassid)) {
7a9b2d595   Eric Dumazet   net: use this_cpu...
346
  		struct ip_rt_acct *st = this_cpu_ptr(ip_rt_acct);
adf30907d   Eric Dumazet   net: skb->dst acc...
347
  		u32 idx = skb_dst(skb)->tclassid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  		st[idx&0xFF].o_packets++;
fd3f8c4cb   Jianjun Kong   net: clean up net...
349
  		st[idx&0xFF].o_bytes += skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
  		st[(idx>>16)&0xFF].i_packets++;
fd3f8c4cb   Jianjun Kong   net: clean up net...
351
  		st[(idx>>16)&0xFF].i_bytes += skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
  	}
  #endif
8c83f2df9   Stephen Suryaputra   vrf: check accept...
354
  	if (iph->ihl > 5 && ip_rcv_options(skb, dev))
d245407e7   Thomas Graf   [IPV4]: Move ip o...
355
  		goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356

511c3f92a   Eric Dumazet   net: skb->rtable ...
357
  	rt = skb_rtable(skb);
edf391ff1   Neil Horman   snmp: add missing...
358
  	if (rt->rt_type == RTN_MULTICAST) {
b15084ec7   Eric Dumazet   net: rename IP_UP...
359
  		__IP_UPD_PO_STATS(net, IPSTATS_MIB_INMCAST, skb->len);
12b74dfad   Johannes Berg   ipv4: add option ...
360
  	} else if (rt->rt_type == RTN_BROADCAST) {
b15084ec7   Eric Dumazet   net: rename IP_UP...
361
  		__IP_UPD_PO_STATS(net, IPSTATS_MIB_INBCAST, skb->len);
12b74dfad   Johannes Berg   ipv4: add option ...
362
363
  	} else if (skb->pkt_type == PACKET_BROADCAST ||
  		   skb->pkt_type == PACKET_MULTICAST) {
d6f64d725   Mark Tomlinson   net: VRF: Pass or...
364
  		struct in_device *in_dev = __in_dev_get_rcu(dev);
12b74dfad   Johannes Berg   ipv4: add option ...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  
  		/* RFC 1122 3.3.6:
  		 *
  		 *   When a host sends a datagram to a link-layer broadcast
  		 *   address, the IP destination address MUST be a legal IP
  		 *   broadcast or IP multicast address.
  		 *
  		 *   A host SHOULD silently discard a datagram that is received
  		 *   via a link-layer broadcast (see Section 2.4) but does not
  		 *   specify an IP multicast or broadcast destination address.
  		 *
  		 * This doesn't explicitly say L2 *broadcast*, but broadcast is
  		 * in a way a form of multicast and the most common use case for
  		 * this is 802.11 protecting against cross-station spoofing (the
  		 * so-called "hole-196" attack) so do it for both.
  		 */
  		if (in_dev &&
  		    IN_DEV_ORCONF(in_dev, DROP_UNICAST_IN_L2_MULTICAST))
  			goto drop;
  	}
5506b54b3   Mitsuru Chinen   [IPV4] SNMP: Supp...
385

5fa12739a   Edward Cree   net: ipv4: listif...
386
  	return NET_RX_SUCCESS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
  drop:
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
389
390
  	kfree_skb(skb);
  	return NET_RX_DROP;
7487449c8   Paolo Abeni   IPv4: early demux...
391
392
393
394
395
  
  drop_error:
  	if (err == -EXDEV)
  		__NET_INC_STATS(net, LINUX_MIB_IPRPFILTER);
  	goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
  }
5fa12739a   Edward Cree   net: ipv4: listif...
397
398
  static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
  {
a1fd1ad25   David Ahern   ipv4: Pass origin...
399
  	struct net_device *dev = skb->dev;
efe6aaca6   Edward Cree   net: ipv4: fix li...
400
401
402
403
404
405
406
407
  	int ret;
  
  	/* if ingress device is enslaved to an L3 master device pass the
  	 * skb to its handler for processing
  	 */
  	skb = l3mdev_ip_rcv(skb);
  	if (!skb)
  		return NET_RX_SUCCESS;
5fa12739a   Edward Cree   net: ipv4: listif...
408

02b249416   Paolo Abeni   ipv4: use dst hin...
409
  	ret = ip_rcv_finish_core(net, sk, skb, dev, NULL);
5fa12739a   Edward Cree   net: ipv4: listif...
410
411
412
413
  	if (ret != NET_RX_DROP)
  		ret = dst_input(skb);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
415
  /*
   * 	Main IP Receive routine.
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
416
   */
17266ee93   Edward Cree   net: ipv4: listif...
417
  static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  {
b71d1d426   Eric Dumazet   inet: constify ip...
419
  	const struct iphdr *iph;
586152424   Thomas Graf   [IPV4]: Consisten...
420
  	u32 len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
423
424
425
426
  
  	/* When the interface is in promisc. mode, drop all the crap
  	 * that it receives, do not try to analyse it.
  	 */
  	if (skb->pkt_type == PACKET_OTHERHOST)
  		goto drop;
b15084ec7   Eric Dumazet   net: rename IP_UP...
427
  	__IP_UPD_PO_STATS(net, IPSTATS_MIB_IN, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428

51456b291   Ian Morris   ipv4: coding styl...
429
430
  	skb = skb_share_check(skb, GFP_ATOMIC);
  	if (!skb) {
b45386efa   Eric Dumazet   net: rename IP_IN...
431
  		__IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
435
436
  		goto out;
  	}
  
  	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
  		goto inhdr_error;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
437
  	iph = ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
  
  	/*
c67fa0279   J.H.M. Dassen (Ray)   net/ipv4: correct...
440
  	 *	RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
444
445
446
447
448
449
450
  	 *
  	 *	Is the datagram acceptable?
  	 *
  	 *	1.	Length at least the size of an ip header
  	 *	2.	Version of 4
  	 *	3.	Checksums correctly. [Speed optimisation for later, skip loopback checksums]
  	 *	4.	Doesn't have a bogus length
  	 */
  
  	if (iph->ihl < 5 || iph->version != 4)
586152424   Thomas Graf   [IPV4]: Consisten...
451
  		goto inhdr_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452

1f07d03e2   Eric Dumazet   net: add SNMP cou...
453
454
455
  	BUILD_BUG_ON(IPSTATS_MIB_ECT1PKTS != IPSTATS_MIB_NOECTPKTS + INET_ECN_ECT_1);
  	BUILD_BUG_ON(IPSTATS_MIB_ECT0PKTS != IPSTATS_MIB_NOECTPKTS + INET_ECN_ECT_0);
  	BUILD_BUG_ON(IPSTATS_MIB_CEPKTS != IPSTATS_MIB_NOECTPKTS + INET_ECN_CE);
98f619957   Eric Dumazet   net: rename IP_AD...
456
457
458
  	__IP_ADD_STATS(net,
  		       IPSTATS_MIB_NOECTPKTS + (iph->tos & INET_ECN_MASK),
  		       max_t(unsigned short, 1, skb_shinfo(skb)->gso_segs));
1f07d03e2   Eric Dumazet   net: add SNMP cou...
459

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
  	if (!pskb_may_pull(skb, iph->ihl*4))
  		goto inhdr_error;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
462
  	iph = ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463

e9c604227   Thomas Graf   [IPV4]: Avoid com...
464
  	if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
6a5dc9e59   Eric Dumazet   net: Add MIB coun...
465
  		goto csum_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466

586152424   Thomas Graf   [IPV4]: Consisten...
467
  	len = ntohs(iph->tot_len);
704aed53b   Mitsuru Chinen   [IPV4] SNMP: Supp...
468
  	if (skb->len < len) {
b45386efa   Eric Dumazet   net: rename IP_IN...
469
  		__IP_INC_STATS(net, IPSTATS_MIB_INTRUNCATEDPKTS);
704aed53b   Mitsuru Chinen   [IPV4] SNMP: Supp...
470
471
  		goto drop;
  	} else if (len < (iph->ihl*4))
586152424   Thomas Graf   [IPV4]: Consisten...
472
  		goto inhdr_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473

586152424   Thomas Graf   [IPV4]: Consisten...
474
475
476
477
478
  	/* Our transport medium may have padded the buffer out. Now we know it
  	 * is IP we can trim to the true length of the frame.
  	 * Note this now means skb->len holds ntohs(iph->tot_len).
  	 */
  	if (pskb_trim_rcsum(skb, len)) {
b45386efa   Eric Dumazet   net: rename IP_IN...
479
  		__IP_INC_STATS(net, IPSTATS_MIB_INDISCARDS);
586152424   Thomas Graf   [IPV4]: Consisten...
480
  		goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
  	}
6c57f0458   Ross Lagerwall   net: Fix usage of...
482
  	iph = ip_hdr(skb);
21d1196a3   Eric Dumazet   ipv4: set transpo...
483
  	skb->transport_header = skb->network_header + iph->ihl*4;
53602f92d   Stephen Hemminger   [IPV4]: Clear skb...
484
  	/* Remove any debris in the socket control block */
d569f1d72   Guillaume Chazarain   [IPV4]: Clear the...
485
  	memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
0b922b7a8   David Ahern   net: original ing...
486
  	IPCB(skb)->iif = skb->skb_iif;
53602f92d   Stephen Hemminger   [IPV4]: Clear skb...
487

71f9dacd2   Herbert Xu   inet: Call skb_or...
488
  	/* Must drop socket now because of tproxy. */
cf7fbe660   Joe Stringer   bpf: Add socket a...
489
490
  	if (!skb_sk_is_prefetched(skb))
  		skb_orphan(skb);
71f9dacd2   Herbert Xu   inet: Call skb_or...
491

17266ee93   Edward Cree   net: ipv4: listif...
492
  	return skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493

6a5dc9e59   Eric Dumazet   net: Add MIB coun...
494
  csum_error:
b45386efa   Eric Dumazet   net: rename IP_IN...
495
  	__IP_INC_STATS(net, IPSTATS_MIB_CSUMERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
  inhdr_error:
b45386efa   Eric Dumazet   net: rename IP_IN...
497
  	__IP_INC_STATS(net, IPSTATS_MIB_INHDRERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  drop:
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
499
  	kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
  out:
17266ee93   Edward Cree   net: ipv4: listif...
501
502
503
504
505
506
507
508
509
510
511
512
513
514
  	return NULL;
  }
  
  /*
   * IP receive entry point
   */
  int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
  	   struct net_device *orig_dev)
  {
  	struct net *net = dev_net(dev);
  
  	skb = ip_rcv_core(skb, net);
  	if (skb == NULL)
  		return NET_RX_DROP;
fb1b69999   Yang Wei   net: ipv4: ip_inp...
515

17266ee93   Edward Cree   net: ipv4: listif...
516
517
518
519
  	return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,
  		       net, NULL, skb, dev, NULL,
  		       ip_rcv_finish);
  }
5fa12739a   Edward Cree   net: ipv4: listif...
520
  static void ip_sublist_rcv_finish(struct list_head *head)
17266ee93   Edward Cree   net: ipv4: listif...
521
522
  {
  	struct sk_buff *skb, *next;
0761680d5   Jesper Dangaard Brouer   net: ipv4: fix li...
523
  	list_for_each_entry_safe(skb, next, head, list) {
992cba7e2   David S. Miller   net: Add and use ...
524
  		skb_list_del_init(skb);
5fa12739a   Edward Cree   net: ipv4: listif...
525
  		dst_input(skb);
0761680d5   Jesper Dangaard Brouer   net: ipv4: fix li...
526
  	}
5fa12739a   Edward Cree   net: ipv4: listif...
527
  }
02b249416   Paolo Abeni   ipv4: use dst hin...
528
529
530
531
532
533
534
535
  static struct sk_buff *ip_extract_route_hint(const struct net *net,
  					     struct sk_buff *skb, int rt_type)
  {
  	if (fib4_has_custom_rules(net) || rt_type == RTN_BROADCAST)
  		return NULL;
  
  	return skb;
  }
5fa12739a   Edward Cree   net: ipv4: listif...
536
537
538
  static void ip_list_rcv_finish(struct net *net, struct sock *sk,
  			       struct list_head *head)
  {
02b249416   Paolo Abeni   ipv4: use dst hin...
539
  	struct sk_buff *skb, *next, *hint = NULL;
5fa12739a   Edward Cree   net: ipv4: listif...
540
  	struct dst_entry *curr_dst = NULL;
5fa12739a   Edward Cree   net: ipv4: listif...
541
  	struct list_head sublist;
a4ca8b7df   Edward Cree   net: ipv4: fix dr...
542
  	INIT_LIST_HEAD(&sublist);
5fa12739a   Edward Cree   net: ipv4: listif...
543
  	list_for_each_entry_safe(skb, next, head, list) {
a1fd1ad25   David Ahern   ipv4: Pass origin...
544
  		struct net_device *dev = skb->dev;
5fa12739a   Edward Cree   net: ipv4: listif...
545
  		struct dst_entry *dst;
22f6bbb7b   Edward Cree   net: use skb_list...
546
  		skb_list_del_init(skb);
efe6aaca6   Edward Cree   net: ipv4: fix li...
547
548
549
550
551
552
  		/* if ingress device is enslaved to an L3 master device pass the
  		 * skb to its handler for processing
  		 */
  		skb = l3mdev_ip_rcv(skb);
  		if (!skb)
  			continue;
02b249416   Paolo Abeni   ipv4: use dst hin...
553
  		if (ip_rcv_finish_core(net, sk, skb, dev, hint) == NET_RX_DROP)
5fa12739a   Edward Cree   net: ipv4: listif...
554
555
556
557
  			continue;
  
  		dst = skb_dst(skb);
  		if (curr_dst != dst) {
02b249416   Paolo Abeni   ipv4: use dst hin...
558
559
  			hint = ip_extract_route_hint(net, skb,
  					       ((struct rtable *)dst)->rt_type);
5fa12739a   Edward Cree   net: ipv4: listif...
560
  			/* dispatch old sublist */
5fa12739a   Edward Cree   net: ipv4: listif...
561
562
563
  			if (!list_empty(&sublist))
  				ip_sublist_rcv_finish(&sublist);
  			/* start new sublist */
a4ca8b7df   Edward Cree   net: ipv4: fix dr...
564
  			INIT_LIST_HEAD(&sublist);
5fa12739a   Edward Cree   net: ipv4: listif...
565
566
  			curr_dst = dst;
  		}
a4ca8b7df   Edward Cree   net: ipv4: fix dr...
567
  		list_add_tail(&skb->list, &sublist);
5fa12739a   Edward Cree   net: ipv4: listif...
568
569
  	}
  	/* dispatch final sublist */
a4ca8b7df   Edward Cree   net: ipv4: fix dr...
570
  	ip_sublist_rcv_finish(&sublist);
5fa12739a   Edward Cree   net: ipv4: listif...
571
572
573
574
575
  }
  
  static void ip_sublist_rcv(struct list_head *head, struct net_device *dev,
  			   struct net *net)
  {
17266ee93   Edward Cree   net: ipv4: listif...
576
577
  	NF_HOOK_LIST(NFPROTO_IPV4, NF_INET_PRE_ROUTING, net, NULL,
  		     head, dev, NULL, ip_rcv_finish);
5fa12739a   Edward Cree   net: ipv4: listif...
578
  	ip_list_rcv_finish(net, NULL, head);
17266ee93   Edward Cree   net: ipv4: listif...
579
580
581
582
583
584
585
586
587
588
  }
  
  /* Receive a list of IP packets */
  void ip_list_rcv(struct list_head *head, struct packet_type *pt,
  		 struct net_device *orig_dev)
  {
  	struct net_device *curr_dev = NULL;
  	struct net *curr_net = NULL;
  	struct sk_buff *skb, *next;
  	struct list_head sublist;
a4ca8b7df   Edward Cree   net: ipv4: fix dr...
589
  	INIT_LIST_HEAD(&sublist);
17266ee93   Edward Cree   net: ipv4: listif...
590
591
592
  	list_for_each_entry_safe(skb, next, head, list) {
  		struct net_device *dev = skb->dev;
  		struct net *net = dev_net(dev);
22f6bbb7b   Edward Cree   net: use skb_list...
593
  		skb_list_del_init(skb);
17266ee93   Edward Cree   net: ipv4: listif...
594
595
596
597
598
599
  		skb = ip_rcv_core(skb, net);
  		if (skb == NULL)
  			continue;
  
  		if (curr_dev != dev || curr_net != net) {
  			/* dispatch old sublist */
17266ee93   Edward Cree   net: ipv4: listif...
600
  			if (!list_empty(&sublist))
a4ca8b7df   Edward Cree   net: ipv4: fix dr...
601
  				ip_sublist_rcv(&sublist, curr_dev, curr_net);
17266ee93   Edward Cree   net: ipv4: listif...
602
  			/* start new sublist */
a4ca8b7df   Edward Cree   net: ipv4: fix dr...
603
  			INIT_LIST_HEAD(&sublist);
17266ee93   Edward Cree   net: ipv4: listif...
604
605
606
  			curr_dev = dev;
  			curr_net = net;
  		}
a4ca8b7df   Edward Cree   net: ipv4: fix dr...
607
  		list_add_tail(&skb->list, &sublist);
17266ee93   Edward Cree   net: ipv4: listif...
608
609
  	}
  	/* dispatch final sublist */
51210ad5a   Florian Westphal   inet: do not call...
610
611
  	if (!list_empty(&sublist))
  		ip_sublist_rcv(&sublist, curr_dev, curr_net);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
  }