Blame view

net/ipv4/af_inet.c 48.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   * 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.
   *
   *		PF_INET protocol family socket handler.
   *
02c30a84e   Jesper Juhl   [PATCH] update Ro...
8
   * Authors:	Ross Biro
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
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
   *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *		Florian La Roche, <flla@stud.uni-sb.de>
   *		Alan Cox, <A.Cox@swansea.ac.uk>
   *
   * Changes (see also sock.c)
   *
   *		piggy,
   *		Karl Knutson	:	Socket protocol table
   *		A.N.Kuznetsov	:	Socket death error in accept().
   *		John Richardson :	Fix non blocking error in connect()
   *					so sockets that fail to connect
   *					don't return -EINPROGRESS.
   *		Alan Cox	:	Asynchronous I/O support
   *		Alan Cox	:	Keep correct socket pointer on sock
   *					structures
   *					when accept() ed
   *		Alan Cox	:	Semantics of SO_LINGER aren't state
   *					moved to close when you look carefully.
   *					With this fixed and the accept bug fixed
   *					some RPC stuff seems happier.
   *		Niibe Yutaka	:	4.4BSD style write async I/O
   *		Alan Cox,
   *		Tony Gale 	:	Fixed reuse semantics.
   *		Alan Cox	:	bind() shouldn't abort existing but dead
   *					sockets. Stops FTP netin:.. I hope.
   *		Alan Cox	:	bind() works correctly for RAW sockets.
   *					Note that FreeBSD at least was broken
   *					in this respect so be careful with
   *					compatibility tests...
   *		Alan Cox	:	routing cache support
   *		Alan Cox	:	memzero the socket structure for
   *					compactness.
   *		Matt Day	:	nonblock connect error handler
   *		Alan Cox	:	Allow large numbers of pending sockets
   *					(eg for big web sites), but only if
   *					specifically application requested.
   *		Alan Cox	:	New buffering throughout IP. Used
   *					dumbly.
   *		Alan Cox	:	New buffering now used smartly.
   *		Alan Cox	:	BSD rather than common sense
   *					interpretation of listen.
   *		Germano Caronni	:	Assorted small races.
   *		Alan Cox	:	sendmsg/recvmsg basic support.
   *		Alan Cox	:	Only sendmsg/recvmsg now supported.
   *		Alan Cox	:	Locked down bind (see security list).
   *		Alan Cox	:	Loosened bind a little.
   *		Mike McLagan	:	ADD/DEL DLCI Ioctls
   *	Willy Konynenberg	:	Transparent proxying support.
   *		David S. Miller	:	New socket lookup architecture.
   *					Some other random speedups.
   *		Cyrus Durgin	:	Cleaned up file for kmod hacks.
   *		Andi Kleen	:	Fix inet_stream_connect TCP race.
   *
   *		This program is free software; you can redistribute it and/or
   *		modify it under the terms of the GNU General Public License
   *		as published by the Free Software Foundation; either version
   *		2 of the License, or (at your option) any later version.
   */
afd465030   Joe Perches   net: ipv4: Standa...
67
  #define pr_fmt(fmt) "IPv4: " fmt
f4c50d990   Herbert Xu   [NET]: Add softwa...
68
  #include <linux/err.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/in.h>
  #include <linux/kernel.h>
d3fc0353f   Paul Gortmaker   ipv4: af_inet: ma...
74
  #include <linux/kmod.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
  #include <linux/sched.h>
  #include <linux/timer.h>
  #include <linux/string.h>
  #include <linux/sockios.h>
  #include <linux/net.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
80
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
84
85
86
87
  #include <linux/fcntl.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
  #include <linux/stat.h>
  #include <linux/init.h>
  #include <linux/poll.h>
  #include <linux/netfilter_ipv4.h>
b3da2cf37   David S. Miller   [INET]: Use jhash...
88
  #include <linux/random.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
89
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
91
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
  #include <linux/inet.h>
  #include <linux/igmp.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
95
  #include <linux/inetdevice.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  #include <linux/netdevice.h>
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
97
  #include <net/checksum.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
102
  #include <net/ip.h>
  #include <net/protocol.h>
  #include <net/arp.h>
  #include <net/route.h>
  #include <net/ip_fib.h>
295f7324f   Arnaldo Carvalho de Melo   [ICSK]: Introduce...
103
  #include <net/inet_connection_sock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
  #include <net/tcp.h>
  #include <net/udp.h>
ba4e58eca   Gerrit Renker   [NET]: Supporting...
106
  #include <net/udplite.h>
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
107
  #include <net/ping.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
110
111
  #include <linux/skbuff.h>
  #include <net/sock.h>
  #include <net/raw.h>
  #include <net/icmp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  #include <net/inet_common.h>
045a0fa0c   Thomas Graf   ip_tunnel: Call i...
113
  #include <net/ip_tunnels.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  #include <net/xfrm.h>
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
115
  #include <net/net_namespace.h>
aebda156a   Eric Dumazet   net: defer net_se...
116
  #include <net/secure_seq.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
  #ifdef CONFIG_IP_MROUTE
  #include <linux/mroute.h>
  #endif
3236b0042   David Ahern   net: Replace vrf_...
120
  #include <net/l3mdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  
  /* The inetsw table contains everything that inet_create needs to
   * build a new socket.
   */
  static struct list_head inetsw[SOCK_MAX];
  static DEFINE_SPINLOCK(inetsw_lock);
  
  /* New destruction routine */
  
  void inet_sock_destruct(struct sock *sk)
  {
  	struct inet_sock *inet = inet_sk(sk);
  
  	__skb_queue_purge(&sk->sk_receive_queue);
  	__skb_queue_purge(&sk->sk_error_queue);
95766fff6   Hideo Aoki   [UDP]: Add memory...
137
  	sk_mem_reclaim(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  	if (sk->sk_type == SOCK_STREAM && sk->sk_state != TCP_CLOSE) {
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
139
140
  		pr_err("Attempt to release TCP socket in state %d %p
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
144
  		       sk->sk_state, sk);
  		return;
  	}
  	if (!sock_flag(sk, SOCK_DEAD)) {
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
145
146
  		pr_err("Attempt to release alive inet socket %p
  ", sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
  		return;
  	}
547b792ca   Ilpo Järvinen   net: convert BUG_...
149
  	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
14afee4b6   Reshetova, Elena   net: convert sock...
150
  	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
547b792ca   Ilpo Järvinen   net: convert BUG_...
151
152
  	WARN_ON(sk->sk_wmem_queued);
  	WARN_ON(sk->sk_forward_alloc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153

f6d8bd051   Eric Dumazet   inet: add RCU pro...
154
  	kfree(rcu_dereference_protected(inet->inet_opt, 1));
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
155
  	dst_release(rcu_dereference_check(sk->sk_dst_cache, 1));
41063e9dd   David S. Miller   ipv4: Early TCP s...
156
  	dst_release(sk->sk_rx_dst);
e6848976b   Arnaldo Carvalho de Melo   [NET]: Cleanup IN...
157
  	sk_refcnt_debug_dec(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
159
  EXPORT_SYMBOL(inet_sock_destruct);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  
  /*
   *	The routines beyond this point handle the behaviour of an AF_INET
   *	socket object. Mostly it punts to the subprotocols of IP to do
   *	the work.
   */
  
  /*
   *	Automatically bind an unbound socket.
   */
  
  static int inet_autobind(struct sock *sk)
  {
  	struct inet_sock *inet;
  	/* We may need to bind the socket. */
  	lock_sock(sk);
  	inet = inet_sk(sk);
c720c7e83   Eric Dumazet   inet: rename some...
177
  	if (!inet->inet_num) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
  		if (sk->sk_prot->get_port(sk, 0)) {
  			release_sock(sk);
  			return -EAGAIN;
  		}
c720c7e83   Eric Dumazet   inet: rename some...
182
  		inet->inet_sport = htons(inet->inet_num);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  	}
  	release_sock(sk);
  	return 0;
  }
  
  /*
   *	Move a socket into listening state.
   */
  int inet_listen(struct socket *sock, int backlog)
  {
  	struct sock *sk = sock->sk;
  	unsigned char old_state;
  	int err;
  
  	lock_sock(sk);
  
  	err = -EINVAL;
  	if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
  		goto out;
  
  	old_state = sk->sk_state;
  	if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN)))
  		goto out;
  
  	/* Really, if the socket is already in listen state
  	 * we can only allow the backlog to be adjusted.
  	 */
  	if (old_state != TCP_LISTEN) {
cebc5cbab   Yuchung Cheng   net-tcp: retire T...
211
  		/* Enable TFO w/o requiring TCP_FASTOPEN socket option.
8336886f7   Jerry Chu   tcp: TCP Fast Ope...
212
  		 * Note that only TCP sockets (SOCK_STREAM) will reach here.
cebc5cbab   Yuchung Cheng   net-tcp: retire T...
213
214
215
  		 * Also fastopen backlog may already been set via the option
  		 * because the socket was in TCP_LISTEN state previously but
  		 * was shutdown() rather than close().
8336886f7   Jerry Chu   tcp: TCP Fast Ope...
216
  		 */
cebc5cbab   Yuchung Cheng   net-tcp: retire T...
217
218
  		if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) &&
  		    (sysctl_tcp_fastopen & TFO_SERVER_ENABLE) &&
0536fcc03   Eric Dumazet   tcp: prepare fast...
219
  		    !inet_csk(sk)->icsk_accept_queue.fastopenq.max_qlen) {
cebc5cbab   Yuchung Cheng   net-tcp: retire T...
220
  			fastopen_queue_tune(sk, backlog);
dfea2aa65   Christoph Paasch   tcp: Do not call ...
221
  			tcp_fastopen_init_key_once(true);
8336886f7   Jerry Chu   tcp: TCP Fast Ope...
222
  		}
cebc5cbab   Yuchung Cheng   net-tcp: retire T...
223

72a3effaf   Eric Dumazet   [NET]: Size liste...
224
  		err = inet_csk_listen_start(sk, backlog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
229
230
231
232
233
234
  		if (err)
  			goto out;
  	}
  	sk->sk_max_ack_backlog = backlog;
  	err = 0;
  
  out:
  	release_sock(sk);
  	return err;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
235
  EXPORT_SYMBOL(inet_listen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
238
239
  
  /*
   *	Create an inet socket.
   */
3f378b684   Eric Paris   net: pass kern to...
240
241
  static int inet_create(struct net *net, struct socket *sock, int protocol,
  		       int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
  {
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
246
247
  	struct inet_protosw *answer;
  	struct inet_sock *inet;
  	struct proto *answer_prot;
  	unsigned char answer_flags;
bb97d31f5   Arnaldo Carvalho de Melo   [INET]: Make inet...
248
  	int try_loading_module = 0;
86c8f9d15   Herbert Xu   [IPV4] Fix EPROTO...
249
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250

79462ad02   Hannes Frederic Sowa   net: add validati...
251
252
  	if (protocol < 0 || protocol >= IPPROTO_MAX)
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
  	sock->state = SS_UNCONNECTED;
  
  	/* Look for the requested type/protocol pair. */
bb97d31f5   Arnaldo Carvalho de Melo   [INET]: Make inet...
256
  lookup_protocol:
86c8f9d15   Herbert Xu   [IPV4] Fix EPROTO...
257
  	err = -ESOCKTNOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  	rcu_read_lock();
696adfe84   Paul E. McKenney   list_for_each_rcu...
259
  	list_for_each_entry_rcu(answer, &inetsw[sock->type], list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260

696adfe84   Paul E. McKenney   list_for_each_rcu...
261
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
265
266
267
268
269
270
271
272
273
274
  		/* Check the non-wild match. */
  		if (protocol == answer->protocol) {
  			if (protocol != IPPROTO_IP)
  				break;
  		} else {
  			/* Check for the two wild cases. */
  			if (IPPROTO_IP == protocol) {
  				protocol = answer->protocol;
  				break;
  			}
  			if (IPPROTO_IP == answer->protocol)
  				break;
  		}
86c8f9d15   Herbert Xu   [IPV4] Fix EPROTO...
275
  		err = -EPROTONOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  	}
696adfe84   Paul E. McKenney   list_for_each_rcu...
277
  	if (unlikely(err)) {
bb97d31f5   Arnaldo Carvalho de Melo   [INET]: Make inet...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  		if (try_loading_module < 2) {
  			rcu_read_unlock();
  			/*
  			 * Be more specific, e.g. net-pf-2-proto-132-type-1
  			 * (net-pf-PF_INET-proto-IPPROTO_SCTP-type-SOCK_STREAM)
  			 */
  			if (++try_loading_module == 1)
  				request_module("net-pf-%d-proto-%d-type-%d",
  					       PF_INET, protocol, sock->type);
  			/*
  			 * Fall back to generic, e.g. net-pf-2-proto-132
  			 * (net-pf-PF_INET-proto-IPPROTO_SCTP)
  			 */
  			else
  				request_module("net-pf-%d-proto-%d",
  					       PF_INET, protocol);
  			goto lookup_protocol;
  		} else
  			goto out_rcu_unlock;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  	err = -EPERM;
52e804c6d   Eric W. Biederman   net: Allow userns...
299
300
  	if (sock->type == SOCK_RAW && !kern &&
  	    !ns_capable(net->user_ns, CAP_NET_RAW))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  		goto out_rcu_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
  
  	sock->ops = answer->ops;
  	answer_prot = answer->prot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
  	answer_flags = answer->flags;
  	rcu_read_unlock();
51456b291   Ian Morris   ipv4: coding styl...
307
  	WARN_ON(!answer_prot->slab);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
  
  	err = -ENOBUFS;
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
310
  	sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot, kern);
51456b291   Ian Morris   ipv4: coding styl...
311
  	if (!sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
  		goto out;
  
  	err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  	if (INET_PROTOSW_REUSE & answer_flags)
4a17fd522   Pavel Emelyanov   sock: Introduce n...
316
  		sk->sk_reuse = SK_CAN_REUSE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
  
  	inet = inet_sk(sk);
469de9b90   Paul Moore   [INET]: style upd...
319
  	inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320

7b2ff18ee   Jiri Olsa   net - IP_NODEFRAG...
321
  	inet->nodefrag = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  	if (SOCK_RAW == sock->type) {
c720c7e83   Eric Dumazet   inet: rename some...
323
  		inet->inet_num = protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
  		if (IPPROTO_RAW == protocol)
  			inet->hdrincl = 1;
  	}
974eda11c   Hannes Frederic Sowa   inet: make no_pmt...
327
  	if (net->ipv4.sysctl_ip_no_pmtu_disc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
  		inet->pmtudisc = IP_PMTUDISC_DONT;
  	else
  		inet->pmtudisc = IP_PMTUDISC_WANT;
c720c7e83   Eric Dumazet   inet: rename some...
331
  	inet->inet_id = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
334
335
  
  	sock_init_data(sock, sk);
  
  	sk->sk_destruct	   = inet_sock_destruct;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
339
340
341
  	sk->sk_protocol	   = protocol;
  	sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
  
  	inet->uc_ttl	= -1;
  	inet->mc_loop	= 1;
  	inet->mc_ttl	= 1;
f771bef98   Nivedita Singhvi   ipv4: New multica...
342
  	inet->mc_all	= 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
  	inet->mc_index	= 0;
  	inet->mc_list	= NULL;
4c507d289   Jiri Benc   net: implement IP...
345
  	inet->rcv_tos	= 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346

e6848976b   Arnaldo Carvalho de Melo   [NET]: Cleanup IN...
347
  	sk_refcnt_debug_inc(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348

c720c7e83   Eric Dumazet   inet: rename some...
349
  	if (inet->inet_num) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
353
354
  		/* It assumes that any protocol which allows
  		 * the user to assign a number at socket
  		 * creation time automatically
  		 * shares.
  		 */
c720c7e83   Eric Dumazet   inet: rename some...
355
  		inet->inet_sport = htons(inet->inet_num);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  		/* Add to protocol hash chains. */
086c653f5   Craig Gallek   sock: struct prot...
357
358
359
360
361
  		err = sk->sk_prot->hash(sk);
  		if (err) {
  			sk_common_release(sk);
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
  	}
  
  	if (sk->sk_prot->init) {
  		err = sk->sk_prot->init(sk);
610236587   David Ahern   bpf: Add new cgro...
366
367
368
369
370
371
372
373
374
  		if (err) {
  			sk_common_release(sk);
  			goto out;
  		}
  	}
  
  	if (!kern) {
  		err = BPF_CGROUP_RUN_PROG_INET_SOCK(sk);
  		if (err) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
  			sk_common_release(sk);
610236587   David Ahern   bpf: Add new cgro...
376
377
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  	}
  out:
  	return err;
  out_rcu_unlock:
  	rcu_read_unlock();
  	goto out;
  }
  
  
  /*
   *	The peer socket should always be NULL (or else). When we call this
   *	function we are destroying the object and from then on nobody
   *	should refer to it.
   */
  int inet_release(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
  
  	if (sk) {
  		long timeout;
  
  		/* Applications forget to leave groups before exiting */
  		ip_mc_drop_socket(sk);
  
  		/* If linger is set, we don't return until the close
  		 * is complete.  Otherwise we return immediately. The
  		 * actually closing is done the same either way.
  		 *
  		 * If the close is due to the process exiting, we never
  		 * linger..
  		 */
  		timeout = 0;
  		if (sock_flag(sk, SOCK_LINGER) &&
  		    !(current->flags & PF_EXITING))
  			timeout = sk->sk_lingertime;
  		sock->sk = NULL;
  		sk->sk_prot->close(sk, timeout);
  	}
  	return 0;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
418
  EXPORT_SYMBOL(inet_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
424
  int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
  {
  	struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
  	struct sock *sk = sock->sk;
  	struct inet_sock *inet = inet_sk(sk);
3594698a1   Eric W. Biederman   net: Make CAP_NET...
425
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
  	unsigned short snum;
  	int chk_addr_ret;
9b8ff5182   David Ahern   net: Make table i...
428
  	u32 tb_id = RT_TABLE_LOCAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
433
434
435
436
437
438
  	int err;
  
  	/* If the socket has its own bind function then use it. (RAW) */
  	if (sk->sk_prot->bind) {
  		err = sk->sk_prot->bind(sk, uaddr, addr_len);
  		goto out;
  	}
  	err = -EINVAL;
  	if (addr_len < sizeof(struct sockaddr_in))
  		goto out;
c349a528c   Marcus Meissner   net: bind() fix e...
439
  	if (addr->sin_family != AF_INET) {
29c486df6   Eric Dumazet   net: ipv4: relax ...
440
441
442
  		/* Compatibility games : accept AF_UNSPEC (mapped to AF_INET)
  		 * only if s_addr is INADDR_ANY.
  		 */
c349a528c   Marcus Meissner   net: bind() fix e...
443
  		err = -EAFNOSUPPORT;
29c486df6   Eric Dumazet   net: ipv4: relax ...
444
445
446
  		if (addr->sin_family != AF_UNSPEC ||
  		    addr->sin_addr.s_addr != htonl(INADDR_ANY))
  			goto out;
c349a528c   Marcus Meissner   net: bind() fix e...
447
  	}
d0733d2e2   Marcus Meissner   net/ipv4: Check f...
448

3236b0042   David Ahern   net: Replace vrf_...
449
  	tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ? : tb_id;
30bbaa195   David Ahern   net: Fix up inet_...
450
  	chk_addr_ret = inet_addr_type_table(net, addr->sin_addr.s_addr, tb_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
455
456
457
458
459
  
  	/* Not specified by any standard per-se, however it breaks too
  	 * many applications when removed.  It is unfortunate since
  	 * allowing applications to make a non-local bind solves
  	 * several problems with systems using dynamic addressing.
  	 * (ie. your servers still start up even if your ISDN link
  	 *  is temporarily down)
  	 */
  	err = -EADDRNOTAVAIL;
49a601589   Vincent Bernat   net/ipv4: bind ip...
460
  	if (!net->ipv4.sysctl_ip_nonlocal_bind &&
b9fb15067   Tóth László Attila   ipv4: Allow bindi...
461
  	    !(inet->freebind || inet->transparent) &&
e6f1cebf7   Al Viro   [NET] endianness ...
462
  	    addr->sin_addr.s_addr != htonl(INADDR_ANY) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
466
467
468
469
  	    chk_addr_ret != RTN_LOCAL &&
  	    chk_addr_ret != RTN_MULTICAST &&
  	    chk_addr_ret != RTN_BROADCAST)
  		goto out;
  
  	snum = ntohs(addr->sin_port);
  	err = -EACCES;
4548b683b   Krister Johansen   Introduce a sysct...
470
  	if (snum && snum < inet_prot_sock(net) &&
3594698a1   Eric W. Biederman   net: Make CAP_NET...
471
  	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
475
476
477
478
479
480
481
482
483
484
  		goto out;
  
  	/*      We keep a pair of addresses. rcv_saddr is the one
  	 *      used by hash lookups, and saddr is used for transmit.
  	 *
  	 *      In the BSD API these are the same except where it
  	 *      would be illegal to use them (multicast/broadcast) in
  	 *      which case the sending device address is used.
  	 */
  	lock_sock(sk);
  
  	/* Check these errors (active socket, double bind). */
  	err = -EINVAL;
c720c7e83   Eric Dumazet   inet: rename some...
485
  	if (sk->sk_state != TCP_CLOSE || inet->inet_num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
  		goto out_release_sock;
c720c7e83   Eric Dumazet   inet: rename some...
487
  	inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
  	if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
c720c7e83   Eric Dumazet   inet: rename some...
489
  		inet->inet_saddr = 0;  /* Use device */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
  
  	/* Make sure we are allowed to bind here. */
90c337da1   Eric Dumazet   inet: add IP_BIND...
492
493
  	if ((snum || !inet->bind_address_no_port) &&
  	    sk->sk_prot->get_port(sk, snum)) {
c720c7e83   Eric Dumazet   inet: rename some...
494
  		inet->inet_saddr = inet->inet_rcv_saddr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
  		err = -EADDRINUSE;
  		goto out_release_sock;
  	}
c720c7e83   Eric Dumazet   inet: rename some...
498
  	if (inet->inet_rcv_saddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
501
  		sk->sk_userlocks |= SOCK_BINDADDR_LOCK;
  	if (snum)
  		sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
c720c7e83   Eric Dumazet   inet: rename some...
502
503
504
  	inet->inet_sport = htons(inet->inet_num);
  	inet->inet_daddr = 0;
  	inet->inet_dport = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
506
507
508
509
510
511
  	sk_dst_reset(sk);
  	err = 0;
  out_release_sock:
  	release_sock(sk);
  out:
  	return err;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
512
  EXPORT_SYMBOL(inet_bind);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513

5e73ea1a3   Daniel Baluta   ipv4: fix checkpa...
514
  int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
  		       int addr_len, int flags)
  {
  	struct sock *sk = sock->sk;
6503d9616   Changli Gao   net: check the le...
518
519
  	if (addr_len < sizeof(uaddr->sa_family))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
  	if (uaddr->sa_family == AF_UNSPEC)
  		return sk->sk_prot->disconnect(sk, flags);
c720c7e83   Eric Dumazet   inet: rename some...
522
  	if (!inet_sk(sk)->inet_num && inet_autobind(sk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
  		return -EAGAIN;
e3192690a   Joe Perches   net: Remove casts...
524
  	return sk->sk_prot->connect(sk, uaddr, addr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
526
  EXPORT_SYMBOL(inet_dgram_connect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527

783237e8d   Yuchung Cheng   net-tcp: Fast Ope...
528
  static long inet_wait_for_connect(struct sock *sk, long timeo, int writebias)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
  {
14135f30e   WANG Cong   inet: fix sleepin...
530
  	DEFINE_WAIT_FUNC(wait, woken_wake_function);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531

14135f30e   WANG Cong   inet: fix sleepin...
532
  	add_wait_queue(sk_sleep(sk), &wait);
783237e8d   Yuchung Cheng   net-tcp: Fast Ope...
533
  	sk->sk_write_pending += writebias;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
538
539
540
541
  
  	/* Basic assumption: if someone sets sk->sk_err, he _must_
  	 * change state of the socket from TCP_SYN_*.
  	 * Connect() does not allow to get error notifications
  	 * without closing the socket.
  	 */
  	while ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
  		release_sock(sk);
14135f30e   WANG Cong   inet: fix sleepin...
542
  		timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
544
545
  		lock_sock(sk);
  		if (signal_pending(current) || !timeo)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
  	}
14135f30e   WANG Cong   inet: fix sleepin...
547
  	remove_wait_queue(sk_sleep(sk), &wait);
783237e8d   Yuchung Cheng   net-tcp: Fast Ope...
548
  	sk->sk_write_pending -= writebias;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
551
552
553
554
555
  	return timeo;
  }
  
  /*
   *	Connect to a remote host. There is regrettably still a little
   *	TCP 'magic' in here.
   */
cf60af03c   Yuchung Cheng   net-tcp: Fast Ope...
556
  int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
3979ad7e8   Willy Tarreau   net/tcp-fastopen:...
557
  			  int addr_len, int flags, int is_sendmsg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
560
561
  {
  	struct sock *sk = sock->sk;
  	int err;
  	long timeo;
19f6d3f3c   Wei Wang   net/tcp-fastopen:...
562
563
564
565
566
567
568
569
570
571
572
573
  	/*
  	 * uaddr can be NULL and addr_len can be 0 if:
  	 * sk is a TCP fastopen active socket and
  	 * TCP_FASTOPEN_CONNECT sockopt is set and
  	 * we already have a valid cookie for this socket.
  	 * In this case, user can call write() after connect().
  	 * write() will invoke tcp_sendmsg_fastopen() which calls
  	 * __inet_stream_connect().
  	 */
  	if (uaddr) {
  		if (addr_len < sizeof(uaddr->sa_family))
  			return -EINVAL;
6503d9616   Changli Gao   net: check the le...
574

19f6d3f3c   Wei Wang   net/tcp-fastopen:...
575
576
577
578
579
  		if (uaddr->sa_family == AF_UNSPEC) {
  			err = sk->sk_prot->disconnect(sk, flags);
  			sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
585
586
587
588
589
  	}
  
  	switch (sock->state) {
  	default:
  		err = -EINVAL;
  		goto out;
  	case SS_CONNECTED:
  		err = -EISCONN;
  		goto out;
  	case SS_CONNECTING:
19f6d3f3c   Wei Wang   net/tcp-fastopen:...
590
  		if (inet_sk(sk)->defer_connect)
3979ad7e8   Willy Tarreau   net/tcp-fastopen:...
591
  			err = is_sendmsg ? -EINPROGRESS : -EISCONN;
19f6d3f3c   Wei Wang   net/tcp-fastopen:...
592
593
  		else
  			err = -EALREADY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
596
597
598
599
600
601
602
603
  		/* Fall out of switch with err, set for this state */
  		break;
  	case SS_UNCONNECTED:
  		err = -EISCONN;
  		if (sk->sk_state != TCP_CLOSE)
  			goto out;
  
  		err = sk->sk_prot->connect(sk, uaddr, addr_len);
  		if (err < 0)
  			goto out;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
604
  		sock->state = SS_CONNECTING;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605

19f6d3f3c   Wei Wang   net/tcp-fastopen:...
606
607
  		if (!err && inet_sk(sk)->defer_connect)
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
609
610
611
612
613
614
615
616
617
618
  		/* Just entered SS_CONNECTING state; the only
  		 * difference is that return value in non-blocking
  		 * case is EINPROGRESS, rather than EALREADY.
  		 */
  		err = -EINPROGRESS;
  		break;
  	}
  
  	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
  
  	if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
783237e8d   Yuchung Cheng   net-tcp: Fast Ope...
619
620
621
  		int writebias = (sk->sk_protocol == IPPROTO_TCP) &&
  				tcp_sk(sk)->fastopen_req &&
  				tcp_sk(sk)->fastopen_req->data ? 1 : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
  		/* Error code is set above */
783237e8d   Yuchung Cheng   net-tcp: Fast Ope...
623
  		if (!timeo || !inet_wait_for_connect(sk, timeo, writebias))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
  			goto out;
  
  		err = sock_intr_errno(timeo);
  		if (signal_pending(current))
  			goto out;
  	}
  
  	/* Connection was closed by RST, timeout, ICMP error
  	 * or another process disconnected us.
  	 */
  	if (sk->sk_state == TCP_CLOSE)
  		goto sock_error;
  
  	/* sk->sk_err may be not zero now, if RECVERR was ordered by user
  	 * and error was received after socket entered established state.
  	 * Hence, it is handled normally after connect() return successfully.
  	 */
  
  	sock->state = SS_CONNECTED;
  	err = 0;
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
646
647
648
649
650
651
652
653
  	return err;
  
  sock_error:
  	err = sock_error(sk) ? : -ECONNABORTED;
  	sock->state = SS_UNCONNECTED;
  	if (sk->sk_prot->disconnect(sk, flags))
  		sock->state = SS_DISCONNECTING;
  	goto out;
  }
cf60af03c   Yuchung Cheng   net-tcp: Fast Ope...
654
655
656
657
658
659
660
661
  EXPORT_SYMBOL(__inet_stream_connect);
  
  int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
  			int addr_len, int flags)
  {
  	int err;
  
  	lock_sock(sock->sk);
3979ad7e8   Willy Tarreau   net/tcp-fastopen:...
662
  	err = __inet_stream_connect(sock, uaddr, addr_len, flags, 0);
cf60af03c   Yuchung Cheng   net-tcp: Fast Ope...
663
664
665
  	release_sock(sock->sk);
  	return err;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
666
  EXPORT_SYMBOL(inet_stream_connect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
669
670
  
  /*
   *	Accept a pending connection. The TCP layer now gives BSD semantics.
   */
cdfbabfb2   David Howells   net: Work around ...
671
672
  int inet_accept(struct socket *sock, struct socket *newsock, int flags,
  		bool kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
675
  {
  	struct sock *sk1 = sock->sk;
  	int err = -EINVAL;
cdfbabfb2   David Howells   net: Work around ...
676
  	struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err, kern);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
679
680
681
  
  	if (!sk2)
  		goto do_err;
  
  	lock_sock(sk2);
1eddceadb   Eric Dumazet   net: rfs: enable ...
682
  	sock_rps_record_flow(sk2);
547b792ca   Ilpo Järvinen   net: convert BUG_...
683
  	WARN_ON(!((1 << sk2->sk_state) &
8336886f7   Jerry Chu   tcp: TCP Fast Ope...
684
685
  		  (TCPF_ESTABLISHED | TCPF_SYN_RECV |
  		  TCPF_CLOSE_WAIT | TCPF_CLOSE)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
689
690
691
692
693
694
  
  	sock_graft(sk2, newsock);
  
  	newsock->state = SS_CONNECTED;
  	err = 0;
  	release_sock(sk2);
  do_err:
  	return err;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
695
  EXPORT_SYMBOL(inet_accept);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
698
699
700
701
702
703
704
705
  
  
  /*
   *	This does both peername and sockname.
   */
  int inet_getname(struct socket *sock, struct sockaddr *uaddr,
  			int *uaddr_len, int peer)
  {
  	struct sock *sk		= sock->sk;
  	struct inet_sock *inet	= inet_sk(sk);
38bfd8f5b   Cyrill Gorcunov   net,socket: intro...
706
  	DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
708
709
  
  	sin->sin_family = AF_INET;
  	if (peer) {
c720c7e83   Eric Dumazet   inet: rename some...
710
  		if (!inet->inet_dport ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
712
713
  		    (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) &&
  		     peer == 1))
  			return -ENOTCONN;
c720c7e83   Eric Dumazet   inet: rename some...
714
715
  		sin->sin_port = inet->inet_dport;
  		sin->sin_addr.s_addr = inet->inet_daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
  	} else {
c720c7e83   Eric Dumazet   inet: rename some...
717
  		__be32 addr = inet->inet_rcv_saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
  		if (!addr)
c720c7e83   Eric Dumazet   inet: rename some...
719
720
  			addr = inet->inet_saddr;
  		sin->sin_port = inet->inet_sport;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
722
723
724
725
726
  		sin->sin_addr.s_addr = addr;
  	}
  	memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
  	*uaddr_len = sizeof(*sin);
  	return 0;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
727
  EXPORT_SYMBOL(inet_getname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728

1b7841404   Ying Xue   net: Remove iocb ...
729
  int inet_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
731
  {
  	struct sock *sk = sock->sk;
c58dc01ba   David S. Miller   net: Make RFS soc...
732
  	sock_rps_record_flow(sk);
fec5e652e   Tom Herbert   rfs: Receive Flow...
733

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  	/* We may need to bind the socket. */
7ba429100   Changli Gao   inet, inet6: make...
735
736
  	if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind &&
  	    inet_autobind(sk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
  		return -EAGAIN;
1b7841404   Ying Xue   net: Remove iocb ...
738
  	return sk->sk_prot->sendmsg(sk, msg, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
740
  EXPORT_SYMBOL(inet_sendmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741

7ba429100   Changli Gao   inet, inet6: make...
742
743
  ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,
  		      size_t size, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
  {
  	struct sock *sk = sock->sk;
c58dc01ba   David S. Miller   net: Make RFS soc...
746
  	sock_rps_record_flow(sk);
fec5e652e   Tom Herbert   rfs: Receive Flow...
747

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  	/* We may need to bind the socket. */
7ba429100   Changli Gao   inet, inet6: make...
749
750
  	if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind &&
  	    inet_autobind(sk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
752
753
754
755
756
  		return -EAGAIN;
  
  	if (sk->sk_prot->sendpage)
  		return sk->sk_prot->sendpage(sk, page, offset, size, flags);
  	return sock_no_sendpage(sock, page, offset, size, flags);
  }
7ba429100   Changli Gao   inet, inet6: make...
757
  EXPORT_SYMBOL(inet_sendpage);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758

1b7841404   Ying Xue   net: Remove iocb ...
759
760
  int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
  		 int flags)
fec5e652e   Tom Herbert   rfs: Receive Flow...
761
762
763
764
  {
  	struct sock *sk = sock->sk;
  	int addr_len = 0;
  	int err;
c58dc01ba   David S. Miller   net: Make RFS soc...
765
  	sock_rps_record_flow(sk);
fec5e652e   Tom Herbert   rfs: Receive Flow...
766

1b7841404   Ying Xue   net: Remove iocb ...
767
  	err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT,
fec5e652e   Tom Herbert   rfs: Receive Flow...
768
769
770
771
772
773
  				   flags & ~MSG_DONTWAIT, &addr_len);
  	if (err >= 0)
  		msg->msg_namelen = addr_len;
  	return err;
  }
  EXPORT_SYMBOL(inet_recvmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
  
  int inet_shutdown(struct socket *sock, int how)
  {
  	struct sock *sk = sock->sk;
  	int err = 0;
  
  	/* This should really check to make sure
  	 * the socket is a TCP socket. (WHY AC...)
  	 */
  	how++; /* maps 0->1 has the advantage of making bit 1 rcvs and
  		       1->2 bit 2 snds.
  		       2->3 */
  	if ((how & ~SHUTDOWN_MASK) || !how)	/* MAXINT->0 */
  		return -EINVAL;
  
  	lock_sock(sk);
  	if (sock->state == SS_CONNECTING) {
  		if ((1 << sk->sk_state) &
  		    (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE))
  			sock->state = SS_DISCONNECTING;
  		else
  			sock->state = SS_CONNECTED;
  	}
  
  	switch (sk->sk_state) {
  	case TCP_CLOSE:
  		err = -ENOTCONN;
  		/* Hack to wake up other listeners, who can poll for
  		   POLLHUP, even on eg. unconnected UDP sockets -- RR */
  	default:
  		sk->sk_shutdown |= how;
  		if (sk->sk_prot->shutdown)
  			sk->sk_prot->shutdown(sk, how);
  		break;
  
  	/* Remaining two branches are temporary solution for missing
  	 * close() in multithreaded environment. It is _not_ a good idea,
  	 * but we have no choice until close() is repaired at VFS level.
  	 */
  	case TCP_LISTEN:
  		if (!(how & RCV_SHUTDOWN))
  			break;
  		/* Fall through */
  	case TCP_SYN_SENT:
  		err = sk->sk_prot->disconnect(sk, O_NONBLOCK);
  		sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;
  		break;
  	}
  
  	/* Wake up anyone sleeping in poll. */
  	sk->sk_state_change(sk);
  	release_sock(sk);
  	return err;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
828
  EXPORT_SYMBOL(inet_shutdown);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
  
  /*
   *	ioctl() calls you can issue on an INET socket. Most of these are
   *	device configuration and stuff and very rarely used. Some ioctls
   *	pass on to the socket itself.
   *
   *	NOTE: I like the idea of a module for the config stuff. ie ifconfig
   *	loads the devconfigure module does its configuring and unloads it.
   *	There's a good 20K of config code hanging around the kernel.
   */
  
  int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
  {
  	struct sock *sk = sock->sk;
  	int err = 0;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
844
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
846
  
  	switch (cmd) {
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
  	case SIOCGSTAMP:
  		err = sock_get_timestamp(sk, (struct timeval __user *)arg);
  		break;
  	case SIOCGSTAMPNS:
  		err = sock_get_timestampns(sk, (struct timespec __user *)arg);
  		break;
  	case SIOCADDRT:
  	case SIOCDELRT:
  	case SIOCRTMSG:
  		err = ip_rt_ioctl(net, cmd, (void __user *)arg);
  		break;
  	case SIOCDARP:
  	case SIOCGARP:
  	case SIOCSARP:
  		err = arp_ioctl(net, cmd, (void __user *)arg);
  		break;
  	case SIOCGIFADDR:
  	case SIOCSIFADDR:
  	case SIOCGIFBRDADDR:
  	case SIOCSIFBRDADDR:
  	case SIOCGIFNETMASK:
  	case SIOCSIFNETMASK:
  	case SIOCGIFDSTADDR:
  	case SIOCSIFDSTADDR:
  	case SIOCSIFPFLAGS:
  	case SIOCGIFPFLAGS:
  	case SIOCSIFFLAGS:
  		err = devinet_ioctl(net, cmd, (void __user *)arg);
  		break;
  	default:
  		if (sk->sk_prot->ioctl)
  			err = sk->sk_prot->ioctl(sk, cmd, arg);
  		else
  			err = -ENOIOCTLCMD;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
884
  	}
  	return err;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
885
  EXPORT_SYMBOL(inet_ioctl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886

709b46e8d   Eric W. Biederman   net: Add compat i...
887
  #ifdef CONFIG_COMPAT
686dc6b64   Gerrit Renker   ipv4: compat_ioct...
888
  static int inet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
709b46e8d   Eric W. Biederman   net: Add compat i...
889
890
891
892
893
894
895
896
897
898
  {
  	struct sock *sk = sock->sk;
  	int err = -ENOIOCTLCMD;
  
  	if (sk->sk_prot->compat_ioctl)
  		err = sk->sk_prot->compat_ioctl(sk, cmd, arg);
  
  	return err;
  }
  #endif
90ddc4f04   Eric Dumazet   [NET]: move struc...
899
  const struct proto_ops inet_stream_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
900
901
902
903
904
905
906
907
908
909
910
911
912
913
  	.family		   = PF_INET,
  	.owner		   = THIS_MODULE,
  	.release	   = inet_release,
  	.bind		   = inet_bind,
  	.connect	   = inet_stream_connect,
  	.socketpair	   = sock_no_socketpair,
  	.accept		   = inet_accept,
  	.getname	   = inet_getname,
  	.poll		   = tcp_poll,
  	.ioctl		   = inet_ioctl,
  	.listen		   = inet_listen,
  	.shutdown	   = inet_shutdown,
  	.setsockopt	   = sock_common_setsockopt,
  	.getsockopt	   = sock_common_getsockopt,
7ba429100   Changli Gao   inet, inet6: make...
914
  	.sendmsg	   = inet_sendmsg,
fec5e652e   Tom Herbert   rfs: Receive Flow...
915
  	.recvmsg	   = inet_recvmsg,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
916
  	.mmap		   = sock_no_mmap,
7ba429100   Changli Gao   inet, inet6: make...
917
  	.sendpage	   = inet_sendpage,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
918
  	.splice_read	   = tcp_splice_read,
320355858   Tom Herbert   tcp: Set read_soc...
919
  	.read_sock	   = tcp_read_sock,
306b13eb3   Tom Herbert   proto_ops: Add lo...
920
921
  	.sendmsg_locked    = tcp_sendmsg_locked,
  	.sendpage_locked   = tcp_sendpage_locked,
320355858   Tom Herbert   tcp: Set read_soc...
922
  	.peek_len	   = tcp_peek_len,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
923
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
924
925
  	.compat_setsockopt = compat_sock_common_setsockopt,
  	.compat_getsockopt = compat_sock_common_getsockopt,
709b46e8d   Eric W. Biederman   net: Add compat i...
926
  	.compat_ioctl	   = inet_compat_ioctl,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
927
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  };
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
929
  EXPORT_SYMBOL(inet_stream_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930

90ddc4f04   Eric Dumazet   [NET]: move struc...
931
  const struct proto_ops inet_dgram_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
  	.family		   = PF_INET,
  	.owner		   = THIS_MODULE,
  	.release	   = inet_release,
  	.bind		   = inet_bind,
  	.connect	   = inet_dgram_connect,
  	.socketpair	   = sock_no_socketpair,
  	.accept		   = sock_no_accept,
  	.getname	   = inet_getname,
  	.poll		   = udp_poll,
  	.ioctl		   = inet_ioctl,
  	.listen		   = sock_no_listen,
  	.shutdown	   = inet_shutdown,
  	.setsockopt	   = sock_common_setsockopt,
  	.getsockopt	   = sock_common_getsockopt,
  	.sendmsg	   = inet_sendmsg,
fec5e652e   Tom Herbert   rfs: Receive Flow...
947
  	.recvmsg	   = inet_recvmsg,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
948
949
  	.mmap		   = sock_no_mmap,
  	.sendpage	   = inet_sendpage,
627d2d6b5   samanthakumar   udp: enable MSG_P...
950
  	.set_peek_off	   = sk_set_peek_off,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
951
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
952
953
  	.compat_setsockopt = compat_sock_common_setsockopt,
  	.compat_getsockopt = compat_sock_common_getsockopt,
709b46e8d   Eric W. Biederman   net: Add compat i...
954
  	.compat_ioctl	   = inet_compat_ioctl,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
955
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
  };
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
957
  EXPORT_SYMBOL(inet_dgram_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
959
960
961
962
  
  /*
   * For SOCK_RAW sockets; should be the same as inet_dgram_ops but without
   * udp_poll
   */
90ddc4f04   Eric Dumazet   [NET]: move struc...
963
  static const struct proto_ops inet_sockraw_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
  	.family		   = PF_INET,
  	.owner		   = THIS_MODULE,
  	.release	   = inet_release,
  	.bind		   = inet_bind,
  	.connect	   = inet_dgram_connect,
  	.socketpair	   = sock_no_socketpair,
  	.accept		   = sock_no_accept,
  	.getname	   = inet_getname,
  	.poll		   = datagram_poll,
  	.ioctl		   = inet_ioctl,
  	.listen		   = sock_no_listen,
  	.shutdown	   = inet_shutdown,
  	.setsockopt	   = sock_common_setsockopt,
  	.getsockopt	   = sock_common_getsockopt,
  	.sendmsg	   = inet_sendmsg,
fec5e652e   Tom Herbert   rfs: Receive Flow...
979
  	.recvmsg	   = inet_recvmsg,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
980
981
  	.mmap		   = sock_no_mmap,
  	.sendpage	   = inet_sendpage,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
982
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
983
984
  	.compat_setsockopt = compat_sock_common_setsockopt,
  	.compat_getsockopt = compat_sock_common_getsockopt,
709b46e8d   Eric W. Biederman   net: Add compat i...
985
  	.compat_ioctl	   = inet_compat_ioctl,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
986
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
  };
ec1b4cf74   Stephen Hemminger   net: mark net_pro...
988
  static const struct net_proto_family inet_family_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
990
991
992
  	.family = PF_INET,
  	.create = inet_create,
  	.owner	= THIS_MODULE,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
995
996
997
  /* Upon startup we insert all the elements in inetsw_array[] into
   * the linked list inetsw.
   */
  static struct inet_protosw inetsw_array[] =
  {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
998
999
1000
1001
1002
  	{
  		.type =       SOCK_STREAM,
  		.protocol =   IPPROTO_TCP,
  		.prot =       &tcp_prot,
  		.ops =        &inet_stream_ops,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1003
  		.flags =      INET_PROTOSW_PERMANENT |
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
1004
  			      INET_PROTOSW_ICSK,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1005
1006
1007
1008
1009
1010
1011
  	},
  
  	{
  		.type =       SOCK_DGRAM,
  		.protocol =   IPPROTO_UDP,
  		.prot =       &udp_prot,
  		.ops =        &inet_dgram_ops,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1012
  		.flags =      INET_PROTOSW_PERMANENT,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
         },
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1014

c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1015
1016
1017
1018
         {
  		.type =       SOCK_DGRAM,
  		.protocol =   IPPROTO_ICMP,
  		.prot =       &ping_prot,
77d4b1d36   Eric Dumazet   net: ping: do not...
1019
  		.ops =        &inet_sockraw_ops,
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1020
1021
  		.flags =      INET_PROTOSW_REUSE,
         },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
1023
  
         {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1024
1025
1026
1027
  	       .type =       SOCK_RAW,
  	       .protocol =   IPPROTO_IP,	/* wild card */
  	       .prot =       &raw_prot,
  	       .ops =        &inet_sockraw_ops,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1028
  	       .flags =      INET_PROTOSW_REUSE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1029
1030
         }
  };
c40f6fff4   Denis Cheng   [IPV4] af_inet.c:...
1031
  #define INETSW_ARRAY_LEN ARRAY_SIZE(inetsw_array)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  
  void inet_register_protosw(struct inet_protosw *p)
  {
  	struct list_head *lh;
  	struct inet_protosw *answer;
  	int protocol = p->protocol;
  	struct list_head *last_perm;
  
  	spin_lock_bh(&inetsw_lock);
  
  	if (p->type >= SOCK_MAX)
  		goto out_illegal;
  
  	/* If we are trying to override a permanent protocol, bail. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046
1047
1048
  	last_perm = &inetsw[p->type];
  	list_for_each(lh, &inetsw[p->type]) {
  		answer = list_entry(lh, struct inet_protosw, list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049
  		/* Check only the non-wild match. */
f6c53334d   Junwei Zhang   net: only check p...
1050
1051
1052
1053
1054
  		if ((INET_PROTOSW_PERMANENT & answer->flags) == 0)
  			break;
  		if (protocol == answer->protocol)
  			goto out_permanent;
  		last_perm = lh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
1057
1058
1059
  
  	/* Add the new entry after the last permanent entry if any, so that
  	 * the new entry does not override a permanent entry when matched with
  	 * a wild-card protocol. But it is allowed to override any existing
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1060
  	 * non-permanent entry.  This means that when we remove this entry, the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
1062
1063
1064
1065
  	 * system automatically returns to the old behavior.
  	 */
  	list_add_rcu(&p->list, last_perm);
  out:
  	spin_unlock_bh(&inetsw_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
1067
1068
  	return;
  
  out_permanent:
058bd4d2a   Joe Perches   net: Convert prin...
1069
1070
  	pr_err("Attempt to override permanent protocol %d
  ", protocol);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1071
1072
1073
  	goto out;
  
  out_illegal:
058bd4d2a   Joe Perches   net: Convert prin...
1074
1075
  	pr_err("Ignoring attempt to register invalid socket type %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
1078
  	       p->type);
  	goto out;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
1079
  EXPORT_SYMBOL(inet_register_protosw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1080
1081
1082
1083
  
  void inet_unregister_protosw(struct inet_protosw *p)
  {
  	if (INET_PROTOSW_PERMANENT & p->flags) {
058bd4d2a   Joe Perches   net: Convert prin...
1084
1085
  		pr_err("Attempt to unregister permanent protocol %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
1087
1088
1089
1090
1091
1092
1093
1094
  		       p->protocol);
  	} else {
  		spin_lock_bh(&inetsw_lock);
  		list_del_rcu(&p->list);
  		spin_unlock_bh(&inetsw_lock);
  
  		synchronize_net();
  	}
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
1095
  EXPORT_SYMBOL(inet_unregister_protosw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096

32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1097
1098
1099
  static int inet_sk_reselect_saddr(struct sock *sk)
  {
  	struct inet_sock *inet = inet_sk(sk);
c720c7e83   Eric Dumazet   inet: rename some...
1100
  	__be32 old_saddr = inet->inet_saddr;
c720c7e83   Eric Dumazet   inet: rename some...
1101
  	__be32 daddr = inet->inet_daddr;
6e8691381   David S. Miller   ipv4: Use cork fl...
1102
  	struct flowi4 *fl4;
b23dd4fe4   David S. Miller   ipv4: Make output...
1103
1104
  	struct rtable *rt;
  	__be32 new_saddr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1105
  	struct ip_options_rcu *inet_opt;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1106

f6d8bd051   Eric Dumazet   inet: add RCU pro...
1107
  	inet_opt = rcu_dereference_protected(inet->inet_opt,
1e1d04e67   Hannes Frederic Sowa   net: introduce lo...
1108
  					     lockdep_sock_is_held(sk));
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1109
1110
  	if (inet_opt && inet_opt->opt.srr)
  		daddr = inet_opt->opt.faddr;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1111
1112
  
  	/* Query new route. */
6e8691381   David S. Miller   ipv4: Use cork fl...
1113
1114
  	fl4 = &inet->cork.fl.u.ip4;
  	rt = ip_route_connect(fl4, daddr, 0, RT_CONN_FLAGS(sk),
b23dd4fe4   David S. Miller   ipv4: Make output...
1115
  			      sk->sk_bound_dev_if, sk->sk_protocol,
0e0d44ab4   Steffen Klassert   net: Remove FLOWI...
1116
  			      inet->inet_sport, inet->inet_dport, sk);
b23dd4fe4   David S. Miller   ipv4: Make output...
1117
1118
  	if (IS_ERR(rt))
  		return PTR_ERR(rt);
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1119

d8d1f30b9   Changli Gao   net-next: remove ...
1120
  	sk_setup_caps(sk, &rt->dst);
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1121

6e8691381   David S. Miller   ipv4: Use cork fl...
1122
  	new_saddr = fl4->saddr;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1123
1124
1125
  
  	if (new_saddr == old_saddr)
  		return 0;
287b7f38f   Nikolay Borisov   ipv4: Namespacify...
1126
  	if (sock_net(sk)->ipv4.sysctl_ip_dynaddr > 1) {
058bd4d2a   Joe Perches   net: Convert prin...
1127
1128
1129
  		pr_info("%s(): shifting inet->saddr from %pI4 to %pI4
  ",
  			__func__, &old_saddr, &new_saddr);
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1130
  	}
c720c7e83   Eric Dumazet   inet: rename some...
1131
  	inet->inet_saddr = inet->inet_rcv_saddr = new_saddr;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1132
1133
1134
1135
1136
1137
1138
1139
1140
  
  	/*
  	 * XXX The only one ugly spot where we need to
  	 * XXX really change the sockets identity after
  	 * XXX it has entered the hashes. -DaveM
  	 *
  	 * Besides that, it does not check for connection
  	 * uniqueness. Wait for troubles.
  	 */
086c653f5   Craig Gallek   sock: struct prot...
1141
  	return __sk_prot_rehash(sk);
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1142
1143
1144
1145
1146
1147
  }
  
  int inet_sk_rebuild_header(struct sock *sk)
  {
  	struct inet_sock *inet = inet_sk(sk);
  	struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
3ca3c68e7   Al Viro   [IPV4]: struct ip...
1148
  	__be32 daddr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1149
  	struct ip_options_rcu *inet_opt;
6e8691381   David S. Miller   ipv4: Use cork fl...
1150
  	struct flowi4 *fl4;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1151
1152
1153
1154
1155
1156
1157
  	int err;
  
  	/* Route is OK, nothing to do. */
  	if (rt)
  		return 0;
  
  	/* Reroute. */
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1158
1159
  	rcu_read_lock();
  	inet_opt = rcu_dereference(inet->inet_opt);
c720c7e83   Eric Dumazet   inet: rename some...
1160
  	daddr = inet->inet_daddr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1161
1162
1163
  	if (inet_opt && inet_opt->opt.srr)
  		daddr = inet_opt->opt.faddr;
  	rcu_read_unlock();
6e8691381   David S. Miller   ipv4: Use cork fl...
1164
1165
  	fl4 = &inet->cork.fl.u.ip4;
  	rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr,
78fbfd8a6   David S. Miller   ipv4: Create and ...
1166
1167
1168
  				   inet->inet_dport, inet->inet_sport,
  				   sk->sk_protocol, RT_CONN_FLAGS(sk),
  				   sk->sk_bound_dev_if);
b23dd4fe4   David S. Miller   ipv4: Make output...
1169
1170
  	if (!IS_ERR(rt)) {
  		err = 0;
d8d1f30b9   Changli Gao   net-next: remove ...
1171
  		sk_setup_caps(sk, &rt->dst);
b23dd4fe4   David S. Miller   ipv4: Make output...
1172
1173
  	} else {
  		err = PTR_ERR(rt);
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1174
1175
1176
1177
1178
1179
  		/* Routing failed... */
  		sk->sk_route_caps = 0;
  		/*
  		 * Other protocols have to map its equivalent state to TCP_SYN_SENT.
  		 * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme
  		 */
287b7f38f   Nikolay Borisov   ipv4: Namespacify...
1180
  		if (!sock_net(sk)->ipv4.sysctl_ip_dynaddr ||
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1181
1182
1183
1184
1185
1186
1187
1188
  		    sk->sk_state != TCP_SYN_SENT ||
  		    (sk->sk_userlocks & SOCK_BINDADDR_LOCK) ||
  		    (err = inet_sk_reselect_saddr(sk)) != 0)
  			sk->sk_err_soft = -err;
  	}
  
  	return err;
  }
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1189
  EXPORT_SYMBOL(inet_sk_rebuild_header);
b8921ca83   Tom Herbert   ip4ip6: Support f...
1190
1191
  struct sk_buff *inet_gso_segment(struct sk_buff *skb,
  				 netdev_features_t features)
f4c50d990   Herbert Xu   [NET]: Add softwa...
1192
  {
60335608e   Willem de Bruijn   net: accept UFO d...
1193
  	bool udpfrag = false, fixedid = false, gso_partial, encap;
f4c50d990   Herbert Xu   [NET]: Add softwa...
1194
  	struct sk_buff *segs = ERR_PTR(-EINVAL);
bca49f843   Vlad Yasevich   ipv4: Switch to u...
1195
  	const struct net_offload *ops;
60335608e   Willem de Bruijn   net: accept UFO d...
1196
  	unsigned int offset = 0;
f9242b6b2   David S. Miller   inet: Sanitize in...
1197
  	struct iphdr *iph;
802ab55ad   Alexander Duyck   GSO: Support part...
1198
  	int proto, tot_len;
3347c9602   Eric Dumazet   ipv4: gso: make i...
1199
  	int nhoff;
f4c50d990   Herbert Xu   [NET]: Add softwa...
1200
1201
  	int ihl;
  	int id;
3347c9602   Eric Dumazet   ipv4: gso: make i...
1202
1203
  	skb_reset_network_header(skb);
  	nhoff = skb_network_header(skb) - skb_mac_header(skb);
bbcf467da   Herbert Xu   [NET]: Verify gso...
1204
  	if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
f4c50d990   Herbert Xu   [NET]: Add softwa...
1205
  		goto out;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1206
  	iph = ip_hdr(skb);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1207
1208
1209
  	ihl = iph->ihl * 4;
  	if (ihl < sizeof(*iph))
  		goto out;
47d27aad4   Eric Dumazet   ipv4: gso: send_c...
1210
1211
1212
1213
  	id = ntohs(iph->id);
  	proto = iph->protocol;
  
  	/* Warning: after this point, iph might be no longer valid */
bbcf467da   Herbert Xu   [NET]: Verify gso...
1214
  	if (unlikely(!pskb_may_pull(skb, ihl)))
f4c50d990   Herbert Xu   [NET]: Add softwa...
1215
  		goto out;
47d27aad4   Eric Dumazet   ipv4: gso: send_c...
1216
  	__skb_pull(skb, ihl);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1217

8c3a897bf   Eric Dumazet   inet: restore gso...
1218
1219
  	encap = SKB_GSO_CB(skb)->encap_level > 0;
  	if (encap)
1e16aa3dd   Florian Westphal   net: gso: use fea...
1220
  		features &= skb->dev->hw_enc_features;
3347c9602   Eric Dumazet   ipv4: gso: make i...
1221
  	SKB_GSO_CB(skb)->encap_level += ihl;
731362674   Pravin B Shelar   tunneling: Add ge...
1222

badff6d01   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1223
  	skb_reset_transport_header(skb);
47d27aad4   Eric Dumazet   ipv4: gso: send_c...
1224

f4c50d990   Herbert Xu   [NET]: Add softwa...
1225
  	segs = ERR_PTR(-EPROTONOSUPPORT);
cbc53e08a   Alexander Duyck   GSO: Add GSO type...
1226
  	if (!skb->encapsulation || encap) {
60335608e   Willem de Bruijn   net: accept UFO d...
1227
  		udpfrag = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP);
cbc53e08a   Alexander Duyck   GSO: Add GSO type...
1228
1229
1230
  		fixedid = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID);
  
  		/* fixed ID is invalid if DF bit is not set */
a51088782   Arnaldo Carvalho de Melo   GSO: Reload iph a...
1231
  		if (fixedid && !(ip_hdr(skb)->frag_off & htons(IP_DF)))
cbc53e08a   Alexander Duyck   GSO: Add GSO type...
1232
1233
  			goto out;
  	}
dcd607718   Eric Dumazet   inet: fix a UFO r...
1234

bca49f843   Vlad Yasevich   ipv4: Switch to u...
1235
  	ops = rcu_dereference(inet_offloads[proto]);
f191a1d17   Vlad Yasevich   net: Remove code ...
1236
1237
  	if (likely(ops && ops->callbacks.gso_segment))
  		segs = ops->callbacks.gso_segment(skb, features);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1238

50c3a487d   YOSHIFUJI Hideaki / 吉藤英明   ipv4: Use IS_ERR_...
1239
  	if (IS_ERR_OR_NULL(segs))
f4c50d990   Herbert Xu   [NET]: Add softwa...
1240
  		goto out;
07b26c945   Steffen Klassert   gso: Support part...
1241
  	gso_partial = !!(skb_shinfo(segs)->gso_type & SKB_GSO_PARTIAL);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1242
1243
  	skb = segs;
  	do {
3347c9602   Eric Dumazet   ipv4: gso: make i...
1244
  		iph = (struct iphdr *)(skb_mac_header(skb) + nhoff);
60335608e   Willem de Bruijn   net: accept UFO d...
1245
1246
1247
1248
1249
1250
1251
  		if (udpfrag) {
  			iph->frag_off = htons(offset >> 3);
  			if (skb->next)
  				iph->frag_off |= htons(IP_MF);
  			offset += skb->len - nhoff - ihl;
  			tot_len = skb->len - nhoff;
  		} else if (skb_is_gso(skb)) {
802ab55ad   Alexander Duyck   GSO: Support part...
1252
1253
1254
1255
  			if (!fixedid) {
  				iph->id = htons(id);
  				id += skb_shinfo(skb)->gso_segs;
  			}
07b26c945   Steffen Klassert   gso: Support part...
1256
1257
1258
1259
1260
1261
1262
  
  			if (gso_partial)
  				tot_len = skb_shinfo(skb)->gso_size +
  					  SKB_GSO_CB(skb)->data_offset +
  					  skb->head - (unsigned char *)iph;
  			else
  				tot_len = skb->len - nhoff;
802ab55ad   Alexander Duyck   GSO: Support part...
1263
1264
1265
1266
  		} else {
  			if (!fixedid)
  				iph->id = htons(id++);
  			tot_len = skb->len - nhoff;
490ab0812   Pravin B Shelar   IP_GRE: Fix IP-Id...
1267
  		}
802ab55ad   Alexander Duyck   GSO: Support part...
1268
  		iph->tot_len = htons(tot_len);
47d27aad4   Eric Dumazet   ipv4: gso: send_c...
1269
  		ip_send_check(iph);
8c3a897bf   Eric Dumazet   inet: restore gso...
1270
  		if (encap)
3347c9602   Eric Dumazet   ipv4: gso: make i...
1271
  			skb_reset_inner_headers(skb);
3347c9602   Eric Dumazet   ipv4: gso: make i...
1272
  		skb->network_header = (u8 *)iph - skb->head;
13a47054f   Toke Høiland-Jørgensen   gso_segment: Rese...
1273
  		skb_reset_mac_len(skb);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1274
1275
1276
1277
1278
  	} while ((skb = skb->next));
  
  out:
  	return segs;
  }
b8921ca83   Tom Herbert   ip4ip6: Support f...
1279
  EXPORT_SYMBOL(inet_gso_segment);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1280

b8921ca83   Tom Herbert   ip4ip6: Support f...
1281
  struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb)
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1282
  {
bca49f843   Vlad Yasevich   ipv4: Switch to u...
1283
  	const struct net_offload *ops;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1284
1285
  	struct sk_buff **pp = NULL;
  	struct sk_buff *p;
b71d1d426   Eric Dumazet   inet: constify ip...
1286
  	const struct iphdr *iph;
a5b1cf288   Herbert Xu   gro: Avoid unnece...
1287
1288
  	unsigned int hlen;
  	unsigned int off;
1075f3f65   Herbert Xu   ipv4: Use 32-bit ...
1289
  	unsigned int id;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1290
1291
  	int flush = 1;
  	int proto;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1292

a5b1cf288   Herbert Xu   gro: Avoid unnece...
1293
1294
1295
1296
1297
1298
1299
1300
  	off = skb_gro_offset(skb);
  	hlen = off + sizeof(*iph);
  	iph = skb_gro_header_fast(skb, off);
  	if (skb_gro_header_hard(skb, hlen)) {
  		iph = skb_gro_header_slow(skb, hlen, off);
  		if (unlikely(!iph))
  			goto out;
  	}
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1301

f9242b6b2   David S. Miller   inet: Sanitize in...
1302
  	proto = iph->protocol;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1303
1304
  
  	rcu_read_lock();
bca49f843   Vlad Yasevich   ipv4: Switch to u...
1305
  	ops = rcu_dereference(inet_offloads[proto]);
f191a1d17   Vlad Yasevich   net: Remove code ...
1306
  	if (!ops || !ops->callbacks.gro_receive)
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1307
  		goto out_unlock;
a5ad24be7   Herbert Xu   gro: Optimise IPv...
1308
  	if (*(u8 *)iph != 0x45)
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1309
  		goto out_unlock;
9b83e0319   Steffen Klassert   ipv4: Don't pass ...
1310
1311
  	if (ip_is_fragment(iph))
  		goto out_unlock;
a9e050f4e   Eric Dumazet   net: tcp: GRO sho...
1312
  	if (unlikely(ip_fast_csum((u8 *)iph, 5)))
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1313
  		goto out_unlock;
0eae88f31   Eric Dumazet   net: Fix various ...
1314
  	id = ntohl(*(__be32 *)&iph->id);
db8caf3db   Eric Dumazet   gro: should aggre...
1315
  	flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF));
1075f3f65   Herbert Xu   ipv4: Use 32-bit ...
1316
  	id >>= 16;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1317
1318
1319
  
  	for (p = *head; p; p = p->next) {
  		struct iphdr *iph2;
1530545ed   Alexander Duyck   GRO: Add support ...
1320
  		u16 flush_id;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1321
1322
1323
  
  		if (!NAPI_GRO_CB(p)->same_flow)
  			continue;
299603e83   Jerry Chu   net-gro: Prepare ...
1324
1325
1326
1327
1328
1329
  		iph2 = (struct iphdr *)(p->data + off);
  		/* The above works because, with the exception of the top
  		 * (inner most) layer, we only aggregate pkts with the same
  		 * hdr length so all the hdrs we'll need to verify will start
  		 * at the same offset.
  		 */
a5ad24be7   Herbert Xu   gro: Optimise IPv...
1330
  		if ((iph->protocol ^ iph2->protocol) |
0eae88f31   Eric Dumazet   net: Fix various ...
1331
1332
  		    ((__force u32)iph->saddr ^ (__force u32)iph2->saddr) |
  		    ((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) {
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1333
1334
1335
1336
1337
1338
  			NAPI_GRO_CB(p)->same_flow = 0;
  			continue;
  		}
  
  		/* All fields must match except length and checksum. */
  		NAPI_GRO_CB(p)->flush |=
a5ad24be7   Herbert Xu   gro: Optimise IPv...
1339
  			(iph->ttl ^ iph2->ttl) |
a9e050f4e   Eric Dumazet   net: tcp: GRO sho...
1340
  			(iph->tos ^ iph2->tos) |
bf5a755f5   Jerry Chu   net-gre-gro: Add ...
1341
  			((iph->frag_off ^ iph2->frag_off) & htons(IP_DF));
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1342
1343
  
  		NAPI_GRO_CB(p)->flush |= flush;
1530545ed   Alexander Duyck   GRO: Add support ...
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
  
  		/* We need to store of the IP ID check to be included later
  		 * when we can verify that this packet does in fact belong
  		 * to a given flow.
  		 */
  		flush_id = (u16)(id - ntohs(iph2->id));
  
  		/* This bit of code makes it much easier for us to identify
  		 * the cases where we are doing atomic vs non-atomic IP ID
  		 * checks.  Specifically an atomic check can return IP ID
  		 * values 0 - 0xFFFF, while a non-atomic check can only
  		 * return 0 or 0xFFFF.
  		 */
  		if (!NAPI_GRO_CB(p)->is_atomic ||
  		    !(iph->frag_off & htons(IP_DF))) {
  			flush_id ^= NAPI_GRO_CB(p)->count;
  			flush_id = flush_id ? 0xFFFF : 0;
  		}
  
  		/* If the previous IP ID value was based on an atomic
  		 * datagram we can overwrite the value and ignore it.
  		 */
  		if (NAPI_GRO_CB(skb)->is_atomic)
  			NAPI_GRO_CB(p)->flush_id = flush_id;
  		else
  			NAPI_GRO_CB(p)->flush_id |= flush_id;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1370
  	}
1530545ed   Alexander Duyck   GRO: Add support ...
1371
  	NAPI_GRO_CB(skb)->is_atomic = !!(iph->frag_off & htons(IP_DF));
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1372
  	NAPI_GRO_CB(skb)->flush |= flush;
299603e83   Jerry Chu   net-gro: Prepare ...
1373
1374
1375
1376
  	skb_set_network_header(skb, off);
  	/* The above will be needed by the transport layer if there is one
  	 * immediately following this IP hdr.
  	 */
2c804d0f8   Eric Dumazet   ipv4: mentions sk...
1377
1378
1379
  	/* Note : No need to call skb_gro_postpull_rcsum() here,
  	 * as we already checked checksum over ipv4 header was 0
  	 */
86911732d   Herbert Xu   gro: Avoid copyin...
1380
1381
  	skb_gro_pull(skb, sizeof(*iph));
  	skb_set_transport_header(skb, skb_gro_offset(skb));
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1382

fcd91dd44   Sabrina Dubroca   net: add recursio...
1383
  	pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1384
1385
1386
1387
1388
  
  out_unlock:
  	rcu_read_unlock();
  
  out:
5f114163f   Steffen Klassert   net: Add a skb_gr...
1389
  	skb_gro_flush_final(skb, pp, flush);
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1390
1391
1392
  
  	return pp;
  }
b8921ca83   Tom Herbert   ip4ip6: Support f...
1393
  EXPORT_SYMBOL(inet_gro_receive);
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1394

fac8e0f57   Jesse Gross   tunnels: Don't ap...
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
  static struct sk_buff **ipip_gro_receive(struct sk_buff **head,
  					 struct sk_buff *skb)
  {
  	if (NAPI_GRO_CB(skb)->encap_mark) {
  		NAPI_GRO_CB(skb)->flush = 1;
  		return NULL;
  	}
  
  	NAPI_GRO_CB(skb)->encap_mark = 1;
  
  	return inet_gro_receive(head, skb);
  }
822c86853   Deepa Dinamani   net: ipv4: Conver...
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
  #define SECONDS_PER_DAY	86400
  
  /* inet_current_timestamp - Return IP network timestamp
   *
   * Return milliseconds since midnight in network byte order.
   */
  __be32 inet_current_timestamp(void)
  {
  	u32 secs;
  	u32 msecs;
  	struct timespec64 ts;
  
  	ktime_get_real_ts64(&ts);
  
  	/* Get secs since midnight. */
  	(void)div_u64_rem(ts.tv_sec, SECONDS_PER_DAY, &secs);
  	/* Convert to msecs. */
  	msecs = secs * MSEC_PER_SEC;
  	/* Convert nsec to msec. */
  	msecs += (u32)ts.tv_nsec / NSEC_PER_MSEC;
  
  	/* Convert to network byte order. */
3ba9d300c   Deepa Dinamani   net: ipv4: Fix tr...
1429
  	return htonl(msecs);
822c86853   Deepa Dinamani   net: ipv4: Conver...
1430
1431
  }
  EXPORT_SYMBOL(inet_current_timestamp);
f4713a3df   Willem de Bruijn   net-timestamp: ma...
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
  int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
  {
  	if (sk->sk_family == AF_INET)
  		return ip_recv_error(sk, msg, len, addr_len);
  #if IS_ENABLED(CONFIG_IPV6)
  	if (sk->sk_family == AF_INET6)
  		return pingv6_ops.ipv6_recv_error(sk, msg, len, addr_len);
  #endif
  	return -EINVAL;
  }
b8921ca83   Tom Herbert   ip4ip6: Support f...
1442
  int inet_gro_complete(struct sk_buff *skb, int nhoff)
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1443
  {
299603e83   Jerry Chu   net-gro: Prepare ...
1444
1445
  	__be16 newlen = htons(skb->len - nhoff);
  	struct iphdr *iph = (struct iphdr *)(skb->data + nhoff);
bca49f843   Vlad Yasevich   ipv4: Switch to u...
1446
  	const struct net_offload *ops;
f9242b6b2   David S. Miller   inet: Sanitize in...
1447
  	int proto = iph->protocol;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1448
  	int err = -ENOSYS;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1449

294acf1c0   Paolo Abeni   net/tunnel: set i...
1450
1451
  	if (skb->encapsulation) {
  		skb_set_inner_protocol(skb, cpu_to_be16(ETH_P_IP));
c3caf1192   Jerry Chu   net-gre-gro: Fix ...
1452
  		skb_set_inner_network_header(skb, nhoff);
294acf1c0   Paolo Abeni   net/tunnel: set i...
1453
  	}
c3caf1192   Jerry Chu   net-gre-gro: Fix ...
1454

73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1455
1456
1457
1458
  	csum_replace2(&iph->check, iph->tot_len, newlen);
  	iph->tot_len = newlen;
  
  	rcu_read_lock();
bca49f843   Vlad Yasevich   ipv4: Switch to u...
1459
  	ops = rcu_dereference(inet_offloads[proto]);
f191a1d17   Vlad Yasevich   net: Remove code ...
1460
  	if (WARN_ON(!ops || !ops->callbacks.gro_complete))
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1461
  		goto out_unlock;
299603e83   Jerry Chu   net-gro: Prepare ...
1462
1463
1464
1465
1466
  	/* Only need to add sizeof(*iph) to get to the next hdr below
  	 * because any hdr with option will have been flushed in
  	 * inet_gro_receive().
  	 */
  	err = ops->callbacks.gro_complete(skb, nhoff + sizeof(*iph));
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1467
1468
1469
1470
1471
1472
  
  out_unlock:
  	rcu_read_unlock();
  
  	return err;
  }
b8921ca83   Tom Herbert   ip4ip6: Support f...
1473
  EXPORT_SYMBOL(inet_gro_complete);
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1474

b8cba75bd   Jesse Gross   ipip: Properly ma...
1475
1476
1477
  static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
  {
  	skb->encapsulation = 1;
7e13318da   Tom Herbert   net: define gso t...
1478
  	skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4;
b8cba75bd   Jesse Gross   ipip: Properly ma...
1479
1480
  	return inet_gro_complete(skb, nhoff);
  }
eee4fe4de   Denis V. Lunev   [INET]: Let inet_...
1481
  int inet_ctl_sock_create(struct sock **sk, unsigned short family,
5677242f4   Denis V. Lunev   [NETNS]: Inet con...
1482
1483
  			 unsigned short type, unsigned char protocol,
  			 struct net *net)
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1484
  {
eee4fe4de   Denis V. Lunev   [INET]: Let inet_...
1485
  	struct socket *sock;
26abe1437   Eric W. Biederman   net: Modify sk_al...
1486
  	int rc = sock_create_kern(net, family, type, protocol, &sock);
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1487
1488
  
  	if (rc == 0) {
eee4fe4de   Denis V. Lunev   [INET]: Let inet_...
1489
1490
  		*sk = sock->sk;
  		(*sk)->sk_allocation = GFP_ATOMIC;
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1491
1492
1493
1494
  		/*
  		 * Unhash it so that IP input processing does not even see it,
  		 * we do not wish this socket to see incoming packets.
  		 */
eee4fe4de   Denis V. Lunev   [INET]: Let inet_...
1495
  		(*sk)->sk_prot->unhash(*sk);
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1496
1497
1498
  	}
  	return rc;
  }
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1499
  EXPORT_SYMBOL_GPL(inet_ctl_sock_create);
c4c6bc314   Raghavendra K T   net: Introduce he...
1500
1501
1502
1503
1504
  u64 snmp_get_cpu_field(void __percpu *mib, int cpu, int offt)
  {
  	return  *(((unsigned long *)per_cpu_ptr(mib, cpu)) + offt);
  }
  EXPORT_SYMBOL_GPL(snmp_get_cpu_field);
698365fa1   WANG Cong   net: clean up snm...
1505
  unsigned long snmp_fold_field(void __percpu *mib, int offt)
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1506
1507
  {
  	unsigned long res = 0;
698365fa1   WANG Cong   net: clean up snm...
1508
  	int i;
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1509

698365fa1   WANG Cong   net: clean up snm...
1510
  	for_each_possible_cpu(i)
c4c6bc314   Raghavendra K T   net: Introduce he...
1511
  		res += snmp_get_cpu_field(mib, i, offt);
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1512
1513
1514
  	return res;
  }
  EXPORT_SYMBOL_GPL(snmp_fold_field);
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
1515
  #if BITS_PER_LONG==32
80ec1927b   David S. Miller   ipv4: Fix 32-bit ...
1516
  u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offt,
c4c6bc314   Raghavendra K T   net: Introduce he...
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
  			 size_t syncp_offset)
  {
  	void *bhptr;
  	struct u64_stats_sync *syncp;
  	u64 v;
  	unsigned int start;
  
  	bhptr = per_cpu_ptr(mib, cpu);
  	syncp = (struct u64_stats_sync *)(bhptr + syncp_offset);
  	do {
  		start = u64_stats_fetch_begin_irq(syncp);
  		v = *(((u64 *)bhptr) + offt);
  	} while (u64_stats_fetch_retry_irq(syncp, start));
  
  	return v;
  }
  EXPORT_SYMBOL_GPL(snmp_get_cpu_field64);
698365fa1   WANG Cong   net: clean up snm...
1534
  u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_offset)
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
1535
1536
1537
1538
1539
  {
  	u64 res = 0;
  	int cpu;
  
  	for_each_possible_cpu(cpu) {
d1bfc6259   Madalin Bucur   ipv4: fix 32b build
1540
  		res += snmp_get_cpu_field64(mib, cpu, offt, syncp_offset);
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
1541
1542
1543
1544
1545
  	}
  	return res;
  }
  EXPORT_SYMBOL_GPL(snmp_fold_field64);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1546
  #ifdef CONFIG_IP_MULTICAST
32613090a   Alexey Dobriyan   net: constify str...
1547
  static const struct net_protocol igmp_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548
  	.handler =	igmp_rcv,
b4ee07df3   Alexey Dobriyan   netns: igmp: allo...
1549
  	.netns_ok =	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
1551
  };
  #endif
a8e3bb347   David Ahern   net: Add comment ...
1552
1553
1554
  /* thinking of making this const? Don't.
   * early_demux can change based on sysctl.
   */
03157937f   David Ahern   Revert "ipv4: mak...
1555
  static struct net_protocol tcp_protocol = {
41063e9dd   David S. Miller   ipv4: Early TCP s...
1556
  	.early_demux	=	tcp_v4_early_demux,
dddb64bcb   subashab@codeaurora.org   net: Add sysctl t...
1557
  	.early_demux_handler =  tcp_v4_early_demux,
41063e9dd   David S. Miller   ipv4: Early TCP s...
1558
1559
  	.handler	=	tcp_v4_rcv,
  	.err_handler	=	tcp_v4_err,
41063e9dd   David S. Miller   ipv4: Early TCP s...
1560
1561
  	.no_policy	=	1,
  	.netns_ok	=	1,
8ed1dc44d   Hannes Frederic Sowa   ipv4: introduce h...
1562
  	.icmp_strict_tag_validation = 1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1563
  };
a8e3bb347   David Ahern   net: Add comment ...
1564
1565
1566
  /* thinking of making this const? Don't.
   * early_demux can change based on sysctl.
   */
03157937f   David Ahern   Revert "ipv4: mak...
1567
  static struct net_protocol udp_protocol = {
421b3885b   Shawn Bohrer   udp: ipv4: Add ud...
1568
  	.early_demux =	udp_v4_early_demux,
dddb64bcb   subashab@codeaurora.org   net: Add sysctl t...
1569
  	.early_demux_handler =	udp_v4_early_demux,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1570
1571
1572
  	.handler =	udp_rcv,
  	.err_handler =	udp_err,
  	.no_policy =	1,
92f1fecb4   Denis V. Lunev   [NETNS]: Enable T...
1573
  	.netns_ok =	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1574
  };
32613090a   Alexey Dobriyan   net: constify str...
1575
  static const struct net_protocol icmp_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
  	.handler =	icmp_rcv,
5b0520425   Li Wei   ipv4: fix error h...
1577
  	.err_handler =	icmp_err,
8b7817f3a   Herbert Xu   [IPSEC]: Add ICMP...
1578
  	.no_policy =	1,
92f1fecb4   Denis V. Lunev   [NETNS]: Enable T...
1579
  	.netns_ok =	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1580
  };
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
1581
1582
  static __net_init int ipv4_mib_init_net(struct net *net)
  {
827da44c6   John Stultz   net: Explicitly i...
1583
  	int i;
698365fa1   WANG Cong   net: clean up snm...
1584
1585
  	net->mib.tcp_statistics = alloc_percpu(struct tcp_mib);
  	if (!net->mib.tcp_statistics)
57ef42d59   Pavel Emelyanov   mib: put tcp stat...
1586
  		goto err_tcp_mib;
698365fa1   WANG Cong   net: clean up snm...
1587
1588
  	net->mib.ip_statistics = alloc_percpu(struct ipstats_mib);
  	if (!net->mib.ip_statistics)
a20f5799c   Pavel Emelyanov   mib: put ip stati...
1589
  		goto err_ip_mib;
827da44c6   John Stultz   net: Explicitly i...
1590
1591
1592
  
  	for_each_possible_cpu(i) {
  		struct ipstats_mib *af_inet_stats;
698365fa1   WANG Cong   net: clean up snm...
1593
  		af_inet_stats = per_cpu_ptr(net->mib.ip_statistics, i);
827da44c6   John Stultz   net: Explicitly i...
1594
  		u64_stats_init(&af_inet_stats->syncp);
827da44c6   John Stultz   net: Explicitly i...
1595
  	}
698365fa1   WANG Cong   net: clean up snm...
1596
1597
  	net->mib.net_statistics = alloc_percpu(struct linux_mib);
  	if (!net->mib.net_statistics)
61a7e2602   Pavel Emelyanov   mib: put net stat...
1598
  		goto err_net_mib;
698365fa1   WANG Cong   net: clean up snm...
1599
1600
  	net->mib.udp_statistics = alloc_percpu(struct udp_mib);
  	if (!net->mib.udp_statistics)
2f275f91a   Pavel Emelyanov   mib: put udp stat...
1601
  		goto err_udp_mib;
698365fa1   WANG Cong   net: clean up snm...
1602
1603
  	net->mib.udplite_statistics = alloc_percpu(struct udp_mib);
  	if (!net->mib.udplite_statistics)
386019d35   Pavel Emelyanov   mib: put udplite ...
1604
  		goto err_udplite_mib;
698365fa1   WANG Cong   net: clean up snm...
1605
1606
  	net->mib.icmp_statistics = alloc_percpu(struct icmp_mib);
  	if (!net->mib.icmp_statistics)
b60538a0d   Pavel Emelyanov   mib: put icmp sta...
1607
  		goto err_icmp_mib;
acb32ba3d   Eric Dumazet   ipv4: reduce perc...
1608
1609
1610
  	net->mib.icmpmsg_statistics = kzalloc(sizeof(struct icmpmsg_mib),
  					      GFP_KERNEL);
  	if (!net->mib.icmpmsg_statistics)
923c6586b   Pavel Emelyanov   mib: put icmpmsg ...
1611
  		goto err_icmpmsg_mib;
57ef42d59   Pavel Emelyanov   mib: put tcp stat...
1612
1613
  
  	tcp_mib_init(net);
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
1614
  	return 0;
57ef42d59   Pavel Emelyanov   mib: put tcp stat...
1615

923c6586b   Pavel Emelyanov   mib: put icmpmsg ...
1616
  err_icmpmsg_mib:
698365fa1   WANG Cong   net: clean up snm...
1617
  	free_percpu(net->mib.icmp_statistics);
b60538a0d   Pavel Emelyanov   mib: put icmp sta...
1618
  err_icmp_mib:
698365fa1   WANG Cong   net: clean up snm...
1619
  	free_percpu(net->mib.udplite_statistics);
386019d35   Pavel Emelyanov   mib: put udplite ...
1620
  err_udplite_mib:
698365fa1   WANG Cong   net: clean up snm...
1621
  	free_percpu(net->mib.udp_statistics);
2f275f91a   Pavel Emelyanov   mib: put udp stat...
1622
  err_udp_mib:
698365fa1   WANG Cong   net: clean up snm...
1623
  	free_percpu(net->mib.net_statistics);
61a7e2602   Pavel Emelyanov   mib: put net stat...
1624
  err_net_mib:
698365fa1   WANG Cong   net: clean up snm...
1625
  	free_percpu(net->mib.ip_statistics);
a20f5799c   Pavel Emelyanov   mib: put ip stati...
1626
  err_ip_mib:
698365fa1   WANG Cong   net: clean up snm...
1627
  	free_percpu(net->mib.tcp_statistics);
57ef42d59   Pavel Emelyanov   mib: put tcp stat...
1628
1629
  err_tcp_mib:
  	return -ENOMEM;
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
1630
1631
1632
1633
  }
  
  static __net_exit void ipv4_mib_exit_net(struct net *net)
  {
acb32ba3d   Eric Dumazet   ipv4: reduce perc...
1634
  	kfree(net->mib.icmpmsg_statistics);
698365fa1   WANG Cong   net: clean up snm...
1635
1636
1637
1638
1639
1640
  	free_percpu(net->mib.icmp_statistics);
  	free_percpu(net->mib.udplite_statistics);
  	free_percpu(net->mib.udp_statistics);
  	free_percpu(net->mib.net_statistics);
  	free_percpu(net->mib.ip_statistics);
  	free_percpu(net->mib.tcp_statistics);
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
1641
1642
1643
1644
1645
1646
  }
  
  static __net_initdata struct pernet_operations ipv4_mib_ops = {
  	.init = ipv4_mib_init_net,
  	.exit = ipv4_mib_exit_net,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1647
1648
  static int __init init_ipv4_mibs(void)
  {
d89cbbb1e   Pavel Emelyanov   ipv4: clean the i...
1649
  	return register_pernet_subsys(&ipv4_mib_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650
  }
c9d8f1a64   Cong Wang   ipv4: move local_...
1651
1652
1653
1654
1655
1656
1657
  static __net_init int inet_init_net(struct net *net)
  {
  	/*
  	 * Set defaults for local port range
  	 */
  	seqlock_init(&net->ipv4.ip_local_ports.lock);
  	net->ipv4.ip_local_ports.range[0] =  32768;
07f4c9006   Eric Dumazet   tcp/dccp: try to ...
1658
  	net->ipv4.ip_local_ports.range[1] =  60999;
ba6b918ab   Cong Wang   ping: move ping_g...
1659
1660
1661
1662
1663
1664
1665
1666
  
  	seqlock_init(&net->ipv4.ping_group_range.lock);
  	/*
  	 * Sane defaults - nobody may create ping sockets.
  	 * Boot scripts should set this to distro-specific group.
  	 */
  	net->ipv4.ping_group_range.range[0] = make_kgid(&init_user_ns, 1);
  	net->ipv4.ping_group_range.range[1] = make_kgid(&init_user_ns, 0);
049bbf589   Ezequiel Garcia   ipv4: Fix non-ini...
1667
1668
1669
1670
1671
1672
1673
  
  	/* Default values for sysctl-controlled parameters.
  	 * We set them here, in case sysctl is not compiled.
  	 */
  	net->ipv4.sysctl_ip_default_ttl = IPDEFTTL;
  	net->ipv4.sysctl_ip_dynaddr = 0;
  	net->ipv4.sysctl_ip_early_demux = 1;
dddb64bcb   subashab@codeaurora.org   net: Add sysctl t...
1674
1675
  	net->ipv4.sysctl_udp_early_demux = 1;
  	net->ipv4.sysctl_tcp_early_demux = 1;
4548b683b   Krister Johansen   Introduce a sysct...
1676
1677
1678
  #ifdef CONFIG_SYSCTL
  	net->ipv4.sysctl_ip_prot_sock = PROT_SOCK;
  #endif
049bbf589   Ezequiel Garcia   ipv4: Fix non-ini...
1679

1714020e4   Nikolay Borisov   igmp: Fix regress...
1680
1681
1682
1683
1684
1685
  	/* Some igmp sysctl, whose values are always used */
  	net->ipv4.sysctl_igmp_max_memberships = 20;
  	net->ipv4.sysctl_igmp_max_msf = 10;
  	/* IGMP reports for link-local multicast groups are enabled by default */
  	net->ipv4.sysctl_igmp_llm_reports = 1;
  	net->ipv4.sysctl_igmp_qrv = 2;
c9d8f1a64   Cong Wang   ipv4: move local_...
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
  	return 0;
  }
  
  static __net_exit void inet_exit_net(struct net *net)
  {
  }
  
  static __net_initdata struct pernet_operations af_inet_ops = {
  	.init = inet_init_net,
  	.exit = inet_exit_net,
  };
  
  static int __init init_inet_pernet_ops(void)
  {
  	return register_pernet_subsys(&af_inet_ops);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702
  static int ipv4_proc_init(void);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703

30e224d76   Herbert Xu   [IPV4]: Fix crash...
1704
1705
1706
  /*
   *	IP protocol layer initialiser
   */
22061d801   Vlad Yasevich   net: Switch to us...
1707
1708
  static struct packet_offload ip_packet_offload __read_mostly = {
  	.type = cpu_to_be16(ETH_P_IP),
f191a1d17   Vlad Yasevich   net: Remove code ...
1709
  	.callbacks = {
f191a1d17   Vlad Yasevich   net: Remove code ...
1710
1711
1712
1713
  		.gso_segment = inet_gso_segment,
  		.gro_receive = inet_gro_receive,
  		.gro_complete = inet_gro_complete,
  	},
30e224d76   Herbert Xu   [IPV4]: Fix crash...
1714
  };
cb32f511a   Eric Dumazet   ipip: add GSO/TSO...
1715
1716
  static const struct net_offload ipip_offload = {
  	.callbacks = {
cb32f511a   Eric Dumazet   ipip: add GSO/TSO...
1717
  		.gso_segment	= inet_gso_segment,
fac8e0f57   Jesse Gross   tunnels: Don't ap...
1718
  		.gro_receive	= ipip_gro_receive,
b8cba75bd   Jesse Gross   ipip: Properly ma...
1719
  		.gro_complete	= ipip_gro_complete,
cb32f511a   Eric Dumazet   ipip: add GSO/TSO...
1720
1721
  	},
  };
93b1b31f8   Tonghao Zhang   ipv4: Introduce i...
1722
1723
1724
1725
  static int __init ipip_offload_init(void)
  {
  	return inet_add_offload(&ipip_offload, IPPROTO_IPIP);
  }
808a8f884   Vlad Yasevich   ipv4: Pull GSO re...
1726
1727
1728
1729
1730
  static int __init ipv4_offload_init(void)
  {
  	/*
  	 * Add offloads
  	 */
da5bab079   Daniel Borkmann   net: udp4: move G...
1731
  	if (udpv4_offload_init() < 0)
808a8f884   Vlad Yasevich   ipv4: Pull GSO re...
1732
1733
  		pr_crit("%s: Cannot add UDP protocol offload
  ", __func__);
28850dc7c   Daniel Borkmann   net: tcp: move GR...
1734
1735
1736
  	if (tcpv4_offload_init() < 0)
  		pr_crit("%s: Cannot add TCP protocol offload
  ", __func__);
93b1b31f8   Tonghao Zhang   ipv4: Introduce i...
1737
1738
1739
  	if (ipip_offload_init() < 0)
  		pr_crit("%s: Cannot add IPIP protocol offload
  ", __func__);
808a8f884   Vlad Yasevich   ipv4: Pull GSO re...
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
  
  	dev_add_offload(&ip_packet_offload);
  	return 0;
  }
  
  fs_initcall(ipv4_offload_init);
  
  static struct packet_type ip_packet_type __read_mostly = {
  	.type = cpu_to_be16(ETH_P_IP),
  	.func = ip_rcv,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751
1752
  static int __init inet_init(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1753
1754
1755
  	struct inet_protosw *q;
  	struct list_head *r;
  	int rc = -EINVAL;
b4772ef87   Eyal Birger   net: use common m...
1756
  	sock_skb_cb_check_size(sizeof(struct inet_skb_parm));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1757
1758
1759
  
  	rc = proto_register(&tcp_prot, 1);
  	if (rc)
122ff243f   WANG Cong   ipv4: make ip_loc...
1760
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1761
1762
1763
1764
1765
1766
1767
1768
  
  	rc = proto_register(&udp_prot, 1);
  	if (rc)
  		goto out_unregister_tcp_proto;
  
  	rc = proto_register(&raw_prot, 1);
  	if (rc)
  		goto out_unregister_udp_proto;
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1769
1770
1771
  	rc = proto_register(&ping_prot, 1);
  	if (rc)
  		goto out_unregister_raw_proto;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1772
  	/*
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1773
  	 *	Tell SOCKET that we are alive...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1774
  	 */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1775
  	(void)sock_register(&inet_family_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1776

bd7b1533c   Al Viro   [PATCH] sysctl: m...
1777
1778
1779
  #ifdef CONFIG_SYSCTL
  	ip_static_sysctl_init();
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780
1781
1782
1783
1784
  	/*
  	 *	Add all the base protocols.
  	 */
  
  	if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)
058bd4d2a   Joe Perches   net: Convert prin...
1785
1786
  		pr_crit("%s: Cannot add ICMP protocol
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1787
  	if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0)
058bd4d2a   Joe Perches   net: Convert prin...
1788
1789
  		pr_crit("%s: Cannot add UDP protocol
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1790
  	if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0)
058bd4d2a   Joe Perches   net: Convert prin...
1791
1792
  		pr_crit("%s: Cannot add TCP protocol
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1793
1794
  #ifdef CONFIG_IP_MULTICAST
  	if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0)
058bd4d2a   Joe Perches   net: Convert prin...
1795
1796
  		pr_crit("%s: Cannot add IGMP protocol
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
  #endif
  
  	/* Register the socket-side information for inet_create. */
  	for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
  		INIT_LIST_HEAD(r);
  
  	for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
  		inet_register_protosw(q);
  
  	/*
  	 *	Set the ARP module up
  	 */
  
  	arp_init();
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1811
1812
1813
  	/*
  	 *	Set the IP module up
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1814
1815
  
  	ip_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1816
1817
  	/* Setup TCP slab cache for open requests. */
  	tcp_init();
95766fff6   Hideo Aoki   [UDP]: Add memory...
1818
1819
  	/* Setup UDP memory threshold */
  	udp_init();
ba4e58eca   Gerrit Renker   [NET]: Supporting...
1820
1821
  	/* Add UDP-Lite (RFC 3828) */
  	udplite4_register();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1822

c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1823
  	ping_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1824
1825
1826
  	/*
  	 *	Set the ICMP layer up
  	 */
a5710d658   Denis V. Lunev   [ICMP]: Add retur...
1827
1828
1829
  	if (icmp_init() < 0)
  		panic("Failed to create the ICMP control socket.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
1831
1832
1833
1834
  
  	/*
  	 *	Initialise the multicast router
  	 */
  #if defined(CONFIG_IP_MROUTE)
03d2f897e   Wang Chen   ipv4: Do cleanup ...
1835
  	if (ip_mr_init())
058bd4d2a   Joe Perches   net: Convert prin...
1836
1837
  		pr_crit("%s: Cannot init ipv4 mroute
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1838
  #endif
c9d8f1a64   Cong Wang   ipv4: move local_...
1839
1840
1841
1842
  
  	if (init_inet_pernet_ops())
  		pr_crit("%s: Cannot init ipv4 inet pernet ops
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1843
1844
  	/*
  	 *	Initialise per-cpu ipv4 mibs
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1845
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1846

132adf546   Stephen Hemminger   [IPV4]: cleanup
1847
  	if (init_ipv4_mibs())
058bd4d2a   Joe Perches   net: Convert prin...
1848
1849
  		pr_crit("%s: Cannot init ipv4 mibs
  ", __func__);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1850

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1851
1852
1853
  	ipv4_proc_init();
  
  	ipfrag_init();
30e224d76   Herbert Xu   [IPV4]: Fix crash...
1854
  	dev_add_pack(&ip_packet_type);
045a0fa0c   Thomas Graf   ip_tunnel: Call i...
1855
  	ip_tunnel_core_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1856
1857
1858
  	rc = 0;
  out:
  	return rc;
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1859
1860
  out_unregister_raw_proto:
  	proto_unregister(&raw_prot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1861
1862
  out_unregister_udp_proto:
  	proto_unregister(&udp_prot);
321efff7c   Olaf Kirch   [IPV4]: Fix order...
1863
1864
  out_unregister_tcp_proto:
  	proto_unregister(&tcp_prot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1865
1866
  	goto out;
  }
a536e0778   Heiko Carstens   [IPV4]: inet_init...
1867
  fs_initcall(inet_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868
1869
1870
1871
  
  /* ------------------------------------------------------------------------ */
  
  #ifdef CONFIG_PROC_FS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
  static int __init ipv4_proc_init(void)
  {
  	int rc = 0;
  
  	if (raw_proc_init())
  		goto out_raw;
  	if (tcp4_proc_init())
  		goto out_tcp;
  	if (udp4_proc_init())
  		goto out_udp;
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1882
1883
  	if (ping_proc_init())
  		goto out_ping;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1884
1885
1886
1887
1888
  	if (ip_misc_proc_init())
  		goto out_misc;
  out:
  	return rc;
  out_misc:
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1889
1890
  	ping_proc_exit();
  out_ping:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
  	udp4_proc_exit();
  out_udp:
  	tcp4_proc_exit();
  out_tcp:
  	raw_proc_exit();
  out_raw:
  	rc = -ENOMEM;
  	goto out;
  }
  
  #else /* CONFIG_PROC_FS */
  static int __init ipv4_proc_init(void)
  {
  	return 0;
  }
  #endif /* CONFIG_PROC_FS */