Blame view

net/ipv4/af_inet.c 42.7 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.
   */
f4c50d990   Herbert Xu   [NET]: Add softwa...
67
  #include <linux/err.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
71
72
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/in.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
77
78
  #include <linux/module.h>
  #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...
79
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
83
84
85
86
  #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...
87
  #include <linux/random.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
88
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
  
  #include <asm/uaccess.h>
  #include <asm/system.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
  #include <linux/inet.h>
  #include <linux/igmp.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
94
  #include <linux/inetdevice.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  #include <linux/netdevice.h>
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
96
  #include <net/checksum.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
100
101
  #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...
102
  #include <net/inet_connection_sock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
  #include <net/tcp.h>
  #include <net/udp.h>
ba4e58eca   Gerrit Renker   [NET]: Supporting...
105
  #include <net/udplite.h>
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
106
  #include <net/ping.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
113
  #include <linux/skbuff.h>
  #include <net/sock.h>
  #include <net/raw.h>
  #include <net/icmp.h>
  #include <net/ipip.h>
  #include <net/inet_common.h>
  #include <net/xfrm.h>
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
114
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
  #ifdef CONFIG_IP_MROUTE
  #include <linux/mroute.h>
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
120
121
122
123
  
  /* 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);
9ba639797   Pavel Emelyanov   [IPV4]: Cleanup t...
124
  struct ipv4_config ipv4_config;
9ba639797   Pavel Emelyanov   [IPV4]: Cleanup t...
125
  EXPORT_SYMBOL(ipv4_config);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
130
131
132
133
  /* 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...
134
  	sk_mem_reclaim(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  	if (sk->sk_type == SOCK_STREAM && sk->sk_state != TCP_CLOSE) {
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
136
137
  		pr_err("Attempt to release TCP socket in state %d %p
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
141
  		       sk->sk_state, sk);
  		return;
  	}
  	if (!sock_flag(sk, SOCK_DEAD)) {
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
142
143
  		pr_err("Attempt to release alive inet socket %p
  ", sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
  		return;
  	}
547b792ca   Ilpo Järvinen   net: convert BUG_...
146
147
148
149
  	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
  	WARN_ON(atomic_read(&sk->sk_wmem_alloc));
  	WARN_ON(sk->sk_wmem_queued);
  	WARN_ON(sk->sk_forward_alloc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150

f6d8bd051   Eric Dumazet   inet: add RCU pro...
151
  	kfree(rcu_dereference_protected(inet->inet_opt, 1));
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
152
  	dst_release(rcu_dereference_check(sk->sk_dst_cache, 1));
e6848976b   Arnaldo Carvalho de Melo   [NET]: Cleanup IN...
153
  	sk_refcnt_debug_dec(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
155
  EXPORT_SYMBOL(inet_sock_destruct);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  
  /*
   *	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...
173
  	if (!inet->inet_num) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
  		if (sk->sk_prot->get_port(sk, 0)) {
  			release_sock(sk);
  			return -EAGAIN;
  		}
c720c7e83   Eric Dumazet   inet: rename some...
178
  		inet->inet_sport = htons(inet->inet_num);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  	}
  	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) {
72a3effaf   Eric Dumazet   [NET]: Size liste...
207
  		err = inet_csk_listen_start(sk, backlog);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
211
212
213
214
215
216
217
  		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...
218
  EXPORT_SYMBOL(inet_listen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219

be776281a   Eric Dumazet   [NET]: inet_ehash...
220
  u32 inet_ehash_secret __read_mostly;
b3da2cf37   David S. Miller   [INET]: Use jhash...
221
  EXPORT_SYMBOL(inet_ehash_secret);
be776281a   Eric Dumazet   [NET]: inet_ehash...
222
223
  /*
   * inet_ehash_secret must be set exactly once
be776281a   Eric Dumazet   [NET]: inet_ehash...
224
   */
b3da2cf37   David S. Miller   [INET]: Use jhash...
225
226
  void build_ehash_secret(void)
  {
be776281a   Eric Dumazet   [NET]: inet_ehash...
227
  	u32 rnd;
49e8ab03e   Eric Dumazet   net: build_ehash_...
228

be776281a   Eric Dumazet   [NET]: inet_ehash...
229
230
231
  	do {
  		get_random_bytes(&rnd, sizeof(rnd));
  	} while (rnd == 0);
49e8ab03e   Eric Dumazet   net: build_ehash_...
232
233
  
  	cmpxchg(&inet_ehash_secret, 0, rnd);
b3da2cf37   David S. Miller   [INET]: Use jhash...
234
235
  }
  EXPORT_SYMBOL(build_ehash_secret);
2342fd7e1   Denis V. Lunev   [NETNS]: Allow to...
236
237
238
  static inline int inet_netns_ok(struct net *net, int protocol)
  {
  	int hash;
32613090a   Alexey Dobriyan   net: constify str...
239
  	const struct net_protocol *ipprot;
2342fd7e1   Denis V. Lunev   [NETNS]: Allow to...
240

04f258ce7   Eric Dumazet   net: some optimiz...
241
  	if (net_eq(net, &init_net))
2342fd7e1   Denis V. Lunev   [NETNS]: Allow to...
242
243
244
245
246
247
248
249
250
251
  		return 1;
  
  	hash = protocol & (MAX_INET_PROTOS - 1);
  	ipprot = rcu_dereference(inet_protos[hash]);
  
  	if (ipprot == NULL)
  		/* raw IP is OK */
  		return 1;
  	return ipprot->netns_ok;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
254
  /*
   *	Create an inet socket.
   */
3f378b684   Eric Paris   net: pass kern to...
255
256
  static int inet_create(struct net *net, struct socket *sock, int protocol,
  		       int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
  {
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
262
263
  	struct inet_protosw *answer;
  	struct inet_sock *inet;
  	struct proto *answer_prot;
  	unsigned char answer_flags;
  	char answer_no_check;
bb97d31f5   Arnaldo Carvalho de Melo   [INET]: Make inet...
264
  	int try_loading_module = 0;
86c8f9d15   Herbert Xu   [IPV4] Fix EPROTO...
265
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266

04f258ce7   Eric Dumazet   net: some optimiz...
267
268
269
  	if (unlikely(!inet_ehash_secret))
  		if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
  			build_ehash_secret();
b3da2cf37   David S. Miller   [INET]: Use jhash...
270

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
  	sock->state = SS_UNCONNECTED;
  
  	/* Look for the requested type/protocol pair. */
bb97d31f5   Arnaldo Carvalho de Melo   [INET]: Make inet...
274
  lookup_protocol:
86c8f9d15   Herbert Xu   [IPV4] Fix EPROTO...
275
  	err = -ESOCKTNOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  	rcu_read_lock();
696adfe84   Paul E. McKenney   list_for_each_rcu...
277
  	list_for_each_entry_rcu(answer, &inetsw[sock->type], list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

696adfe84   Paul E. McKenney   list_for_each_rcu...
279
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
284
285
286
287
288
289
290
291
292
  		/* 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...
293
  		err = -EPROTONOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
  	}
696adfe84   Paul E. McKenney   list_for_each_rcu...
295
  	if (unlikely(err)) {
bb97d31f5   Arnaldo Carvalho de Melo   [INET]: Make inet...
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  		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
316
  	err = -EPERM;
c84b3268d   Eric Paris   net: check kern b...
317
  	if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
  		goto out_rcu_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319

2342fd7e1   Denis V. Lunev   [NETNS]: Allow to...
320
321
322
  	err = -EAFNOSUPPORT;
  	if (!inet_netns_ok(net, protocol))
  		goto out_rcu_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
326
327
  	sock->ops = answer->ops;
  	answer_prot = answer->prot;
  	answer_no_check = answer->no_check;
  	answer_flags = answer->flags;
  	rcu_read_unlock();
547b792ca   Ilpo Järvinen   net: convert BUG_...
328
  	WARN_ON(answer_prot->slab == NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
  
  	err = -ENOBUFS;
6257ff217   Pavel Emelyanov   [NET]: Forget the...
331
  	sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
334
335
336
337
338
339
340
  	if (sk == NULL)
  		goto out;
  
  	err = 0;
  	sk->sk_no_check = answer_no_check;
  	if (INET_PROTOSW_REUSE & answer_flags)
  		sk->sk_reuse = 1;
  
  	inet = inet_sk(sk);
469de9b90   Paul Moore   [INET]: style upd...
341
  	inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342

7b2ff18ee   Jiri Olsa   net - IP_NODEFRAG...
343
  	inet->nodefrag = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  	if (SOCK_RAW == sock->type) {
c720c7e83   Eric Dumazet   inet: rename some...
345
  		inet->inet_num = protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
351
352
353
  		if (IPPROTO_RAW == protocol)
  			inet->hdrincl = 1;
  	}
  
  	if (ipv4_config.no_pmtu_disc)
  		inet->pmtudisc = IP_PMTUDISC_DONT;
  	else
  		inet->pmtudisc = IP_PMTUDISC_WANT;
c720c7e83   Eric Dumazet   inet: rename some...
354
  	inet->inet_id = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
356
357
358
  
  	sock_init_data(sock, sk);
  
  	sk->sk_destruct	   = inet_sock_destruct;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
361
362
363
364
  	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...
365
  	inet->mc_all	= 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
  	inet->mc_index	= 0;
  	inet->mc_list	= NULL;
e6848976b   Arnaldo Carvalho de Melo   [NET]: Cleanup IN...
368
  	sk_refcnt_debug_inc(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369

c720c7e83   Eric Dumazet   inet: rename some...
370
  	if (inet->inet_num) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
375
  		/* 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...
376
  		inet->inet_sport = htons(inet->inet_num);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
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
  		/* Add to protocol hash chains. */
  		sk->sk_prot->hash(sk);
  	}
  
  	if (sk->sk_prot->init) {
  		err = sk->sk_prot->init(sk);
  		if (err)
  			sk_common_release(sk);
  	}
  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;
c58dc01ba   David S. Miller   net: Make RFS soc...
405
  		sock_rps_reset_flow(sk);
fec5e652e   Tom Herbert   rfs: Receive Flow...
406

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  		/* 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...
426
  EXPORT_SYMBOL(inet_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
  
  /* It is off by default, see below. */
ab32ea5d8   Brian Haley   [NET/IPV4/IPV6]: ...
429
  int sysctl_ip_nonlocal_bind __read_mostly;
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
430
  EXPORT_SYMBOL(sysctl_ip_nonlocal_bind);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
  
  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);
  	unsigned short snum;
  	int chk_addr_ret;
  	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...
449
  	if (addr->sin_family != AF_INET) {
29c486df6   Eric Dumazet   net: ipv4: relax ...
450
451
452
  		/* Compatibility games : accept AF_UNSPEC (mapped to AF_INET)
  		 * only if s_addr is INADDR_ANY.
  		 */
c349a528c   Marcus Meissner   net: bind() fix e...
453
  		err = -EAFNOSUPPORT;
29c486df6   Eric Dumazet   net: ipv4: relax ...
454
455
456
  		if (addr->sin_family != AF_UNSPEC ||
  		    addr->sin_addr.s_addr != htonl(INADDR_ANY))
  			goto out;
c349a528c   Marcus Meissner   net: bind() fix e...
457
  	}
d0733d2e2   Marcus Meissner   net/ipv4: Check f...
458

3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
459
  	chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
462
463
464
465
466
467
468
469
  
  	/* 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;
  	if (!sysctl_ip_nonlocal_bind &&
b9fb15067   Tóth László Attila   ipv4: Allow bindi...
470
  	    !(inet->freebind || inet->transparent) &&
e6f1cebf7   Al Viro   [NET] endianness ...
471
  	    addr->sin_addr.s_addr != htonl(INADDR_ANY) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  	    chk_addr_ret != RTN_LOCAL &&
  	    chk_addr_ret != RTN_MULTICAST &&
  	    chk_addr_ret != RTN_BROADCAST)
  		goto out;
  
  	snum = ntohs(addr->sin_port);
  	err = -EACCES;
  	if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
  		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...
493
  	if (sk->sk_state != TCP_CLOSE || inet->inet_num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
  		goto out_release_sock;
c720c7e83   Eric Dumazet   inet: rename some...
495
  	inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
  	if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
c720c7e83   Eric Dumazet   inet: rename some...
497
  		inet->inet_saddr = 0;  /* Use device */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
500
  
  	/* Make sure we are allowed to bind here. */
  	if (sk->sk_prot->get_port(sk, snum)) {
c720c7e83   Eric Dumazet   inet: rename some...
501
  		inet->inet_saddr = inet->inet_rcv_saddr = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
  		err = -EADDRINUSE;
  		goto out_release_sock;
  	}
c720c7e83   Eric Dumazet   inet: rename some...
505
  	if (inet->inet_rcv_saddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
  		sk->sk_userlocks |= SOCK_BINDADDR_LOCK;
  	if (snum)
  		sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
c720c7e83   Eric Dumazet   inet: rename some...
509
510
511
  	inet->inet_sport = htons(inet->inet_num);
  	inet->inet_daddr = 0;
  	inet->inet_dport = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
513
514
515
516
517
518
  	sk_dst_reset(sk);
  	err = 0;
  out_release_sock:
  	release_sock(sk);
  out:
  	return err;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
519
  EXPORT_SYMBOL(inet_bind);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
522
523
524
  
  int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr,
  		       int addr_len, int flags)
  {
  	struct sock *sk = sock->sk;
6503d9616   Changli Gao   net: check the le...
525
526
  	if (addr_len < sizeof(uaddr->sa_family))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
  	if (uaddr->sa_family == AF_UNSPEC)
  		return sk->sk_prot->disconnect(sk, flags);
c720c7e83   Eric Dumazet   inet: rename some...
529
  	if (!inet_sk(sk)->inet_num && inet_autobind(sk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
532
  		return -EAGAIN;
  	return sk->sk_prot->connect(sk, (struct sockaddr *)uaddr, addr_len);
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
533
  EXPORT_SYMBOL(inet_dgram_connect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
  
  static long inet_wait_for_connect(struct sock *sk, long timeo)
  {
  	DEFINE_WAIT(wait);
aa3951451   Eric Dumazet   net: sk_sleep() h...
538
  	prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539
540
541
542
543
544
545
546
547
548
549
550
  
  	/* 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);
  		timeo = schedule_timeout(timeo);
  		lock_sock(sk);
  		if (signal_pending(current) || !timeo)
  			break;
aa3951451   Eric Dumazet   net: sk_sleep() h...
551
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
  	}
aa3951451   Eric Dumazet   net: sk_sleep() h...
553
  	finish_wait(sk_sleep(sk), &wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
556
557
558
559
560
561
562
563
564
565
566
  	return timeo;
  }
  
  /*
   *	Connect to a remote host. There is regrettably still a little
   *	TCP 'magic' in here.
   */
  int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
  			int addr_len, int flags)
  {
  	struct sock *sk = sock->sk;
  	int err;
  	long timeo;
6503d9616   Changli Gao   net: check the le...
567
568
  	if (addr_len < sizeof(uaddr->sa_family))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
  	lock_sock(sk);
  
  	if (uaddr->sa_family == AF_UNSPEC) {
  		err = sk->sk_prot->disconnect(sk, flags);
  		sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;
  		goto out;
  	}
  
  	switch (sock->state) {
  	default:
  		err = -EINVAL;
  		goto out;
  	case SS_CONNECTED:
  		err = -EISCONN;
  		goto out;
  	case SS_CONNECTING:
  		err = -EALREADY;
  		/* 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...
596
  		sock->state = SS_CONNECTING;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
  
  		/* 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)) {
  		/* Error code is set above */
  		if (!timeo || !inet_wait_for_connect(sk, timeo))
  			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:
  	release_sock(sk);
  	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;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
642
  EXPORT_SYMBOL(inet_stream_connect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
  
  /*
   *	Accept a pending connection. The TCP layer now gives BSD semantics.
   */
  
  int inet_accept(struct socket *sock, struct socket *newsock, int flags)
  {
  	struct sock *sk1 = sock->sk;
  	int err = -EINVAL;
  	struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err);
  
  	if (!sk2)
  		goto do_err;
  
  	lock_sock(sk2);
1eddceadb   Eric Dumazet   net: rfs: enable ...
658
  	sock_rps_record_flow(sk2);
547b792ca   Ilpo Järvinen   net: convert BUG_...
659
660
  	WARN_ON(!((1 << sk2->sk_state) &
  		  (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
663
664
665
666
667
668
669
  
  	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...
670
  EXPORT_SYMBOL(inet_accept);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
673
674
675
676
677
678
679
680
  
  
  /*
   *	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...
681
  	DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
  
  	sin->sin_family = AF_INET;
  	if (peer) {
c720c7e83   Eric Dumazet   inet: rename some...
685
  		if (!inet->inet_dport ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
  		    (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) &&
  		     peer == 1))
  			return -ENOTCONN;
c720c7e83   Eric Dumazet   inet: rename some...
689
690
  		sin->sin_port = inet->inet_dport;
  		sin->sin_addr.s_addr = inet->inet_daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
  	} else {
c720c7e83   Eric Dumazet   inet: rename some...
692
  		__be32 addr = inet->inet_rcv_saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  		if (!addr)
c720c7e83   Eric Dumazet   inet: rename some...
694
695
  			addr = inet->inet_saddr;
  		sin->sin_port = inet->inet_sport;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
698
699
700
701
  		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...
702
  EXPORT_SYMBOL(inet_getname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
705
706
707
  
  int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
  		 size_t size)
  {
  	struct sock *sk = sock->sk;
c58dc01ba   David S. Miller   net: Make RFS soc...
708
  	sock_rps_record_flow(sk);
fec5e652e   Tom Herbert   rfs: Receive Flow...
709

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
  	/* We may need to bind the socket. */
7ba429100   Changli Gao   inet, inet6: make...
711
712
  	if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind &&
  	    inet_autobind(sk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
715
716
  		return -EAGAIN;
  
  	return sk->sk_prot->sendmsg(iocb, sk, msg, size);
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
717
  EXPORT_SYMBOL(inet_sendmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718

7ba429100   Changli Gao   inet, inet6: make...
719
720
  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
721
722
  {
  	struct sock *sk = sock->sk;
c58dc01ba   David S. Miller   net: Make RFS soc...
723
  	sock_rps_record_flow(sk);
fec5e652e   Tom Herbert   rfs: Receive Flow...
724

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
  	/* We may need to bind the socket. */
7ba429100   Changli Gao   inet, inet6: make...
726
727
  	if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind &&
  	    inet_autobind(sk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
730
731
732
733
  		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...
734
  EXPORT_SYMBOL(inet_sendpage);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735

fec5e652e   Tom Herbert   rfs: Receive Flow...
736
737
738
739
740
741
  int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
  		 size_t size, int flags)
  {
  	struct sock *sk = sock->sk;
  	int addr_len = 0;
  	int err;
c58dc01ba   David S. Miller   net: Make RFS soc...
742
  	sock_rps_record_flow(sk);
fec5e652e   Tom Herbert   rfs: Receive Flow...
743
744
745
746
747
748
749
750
  
  	err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,
  				   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
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
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
  
  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...
805
  EXPORT_SYMBOL(inet_shutdown);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
  
  /*
   *	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...
821
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
  
  	switch (cmd) {
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
  	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
859
860
861
  	}
  	return err;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
862
  EXPORT_SYMBOL(inet_ioctl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863

709b46e8d   Eric W. Biederman   net: Add compat i...
864
  #ifdef CONFIG_COMPAT
686dc6b64   Gerrit Renker   ipv4: compat_ioct...
865
  static int inet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
709b46e8d   Eric W. Biederman   net: Add compat i...
866
867
868
869
870
871
872
873
874
875
  {
  	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...
876
  const struct proto_ops inet_stream_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
  	.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...
891
  	.sendmsg	   = inet_sendmsg,
fec5e652e   Tom Herbert   rfs: Receive Flow...
892
  	.recvmsg	   = inet_recvmsg,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
893
  	.mmap		   = sock_no_mmap,
7ba429100   Changli Gao   inet, inet6: make...
894
  	.sendpage	   = inet_sendpage,
9c55e01c0   Jens Axboe   [TCP]: Splice rec...
895
  	.splice_read	   = tcp_splice_read,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
896
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
897
898
  	.compat_setsockopt = compat_sock_common_setsockopt,
  	.compat_getsockopt = compat_sock_common_getsockopt,
709b46e8d   Eric W. Biederman   net: Add compat i...
899
  	.compat_ioctl	   = inet_compat_ioctl,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
900
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
  };
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
902
  EXPORT_SYMBOL(inet_stream_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903

90ddc4f04   Eric Dumazet   [NET]: move struc...
904
  const struct proto_ops inet_dgram_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
  	.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...
920
  	.recvmsg	   = inet_recvmsg,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
921
922
  	.mmap		   = sock_no_mmap,
  	.sendpage	   = inet_sendpage,
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_dgram_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
931
932
933
934
  
  /*
   * For SOCK_RAW sockets; should be the same as inet_dgram_ops but without
   * udp_poll
   */
90ddc4f04   Eric Dumazet   [NET]: move struc...
935
  static const struct proto_ops inet_sockraw_ops = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
  	.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...
951
  	.recvmsg	   = inet_recvmsg,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
952
953
  	.mmap		   = sock_no_mmap,
  	.sendpage	   = inet_sendpage,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
954
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
955
956
  	.compat_setsockopt = compat_sock_common_setsockopt,
  	.compat_getsockopt = compat_sock_common_getsockopt,
709b46e8d   Eric W. Biederman   net: Add compat i...
957
  	.compat_ioctl	   = inet_compat_ioctl,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
958
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
  };
ec1b4cf74   Stephen Hemminger   net: mark net_pro...
960
  static const struct net_proto_family inet_family_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
962
963
964
  	.family = PF_INET,
  	.create = inet_create,
  	.owner	= THIS_MODULE,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
966
967
968
969
  /* 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...
970
971
972
973
974
  	{
  		.type =       SOCK_STREAM,
  		.protocol =   IPPROTO_TCP,
  		.prot =       &tcp_prot,
  		.ops =        &inet_stream_ops,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
975
976
  		.no_check =   0,
  		.flags =      INET_PROTOSW_PERMANENT |
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
977
  			      INET_PROTOSW_ICSK,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
978
979
980
981
982
983
984
  	},
  
  	{
  		.type =       SOCK_DGRAM,
  		.protocol =   IPPROTO_UDP,
  		.prot =       &udp_prot,
  		.ops =        &inet_dgram_ops,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
985
986
  		.no_check =   UDP_CSUM_DEFAULT,
  		.flags =      INET_PROTOSW_PERMANENT,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
         },
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
988

c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
989
990
991
992
993
994
995
996
         {
  		.type =       SOCK_DGRAM,
  		.protocol =   IPPROTO_ICMP,
  		.prot =       &ping_prot,
  		.ops =        &inet_dgram_ops,
  		.no_check =   UDP_CSUM_DEFAULT,
  		.flags =      INET_PROTOSW_REUSE,
         },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997
998
  
         {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
999
1000
1001
1002
  	       .type =       SOCK_RAW,
  	       .protocol =   IPPROTO_IP,	/* wild card */
  	       .prot =       &raw_prot,
  	       .ops =        &inet_sockraw_ops,
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1003
1004
  	       .no_check =   UDP_CSUM_DEFAULT,
  	       .flags =      INET_PROTOSW_REUSE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
1006
         }
  };
c40f6fff4   Denis Cheng   [IPV4] af_inet.c:...
1007
  #define INETSW_ARRAY_LEN ARRAY_SIZE(inetsw_array)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
  
  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. */
  	answer = NULL;
  	last_perm = &inetsw[p->type];
  	list_for_each(lh, &inetsw[p->type]) {
  		answer = list_entry(lh, struct inet_protosw, list);
  
  		/* Check only the non-wild match. */
  		if (INET_PROTOSW_PERMANENT & answer->flags) {
  			if (protocol == answer->protocol)
  				break;
  			last_perm = lh;
  		}
  
  		answer = NULL;
  	}
  	if (answer)
  		goto out_permanent;
  
  	/* 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...
1042
  	 * non-permanent entry.  This means that when we remove this entry, the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
1044
1045
1046
1047
  	 * 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
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
  	return;
  
  out_permanent:
  	printk(KERN_ERR "Attempt to override permanent protocol %d.
  ",
  	       protocol);
  	goto out;
  
  out_illegal:
  	printk(KERN_ERR
  	       "Ignoring attempt to register invalid socket type %d.
  ",
  	       p->type);
  	goto out;
  }
3d1427f87   Eric Dumazet   ipv4: af_inet.c c...
1063
  EXPORT_SYMBOL(inet_register_protosw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
  
  void inet_unregister_protosw(struct inet_protosw *p)
  {
  	if (INET_PROTOSW_PERMANENT & p->flags) {
  		printk(KERN_ERR
  		       "Attempt to unregister permanent protocol %d.
  ",
  		       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...
1080
  EXPORT_SYMBOL(inet_unregister_protosw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1081

32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1082
1083
1084
  /*
   *      Shall we try to damage output packets if routing dev changes?
   */
ab32ea5d8   Brian Haley   [NET/IPV4/IPV6]: ...
1085
  int sysctl_ip_dynaddr __read_mostly;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1086
1087
1088
1089
  
  static int inet_sk_reselect_saddr(struct sock *sk)
  {
  	struct inet_sock *inet = inet_sk(sk);
c720c7e83   Eric Dumazet   inet: rename some...
1090
  	__be32 old_saddr = inet->inet_saddr;
c720c7e83   Eric Dumazet   inet: rename some...
1091
  	__be32 daddr = inet->inet_daddr;
6e8691381   David S. Miller   ipv4: Use cork fl...
1092
  	struct flowi4 *fl4;
b23dd4fe4   David S. Miller   ipv4: Make output...
1093
1094
  	struct rtable *rt;
  	__be32 new_saddr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1095
  	struct ip_options_rcu *inet_opt;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1096

f6d8bd051   Eric Dumazet   inet: add RCU pro...
1097
1098
1099
1100
  	inet_opt = rcu_dereference_protected(inet->inet_opt,
  					     sock_owned_by_user(sk));
  	if (inet_opt && inet_opt->opt.srr)
  		daddr = inet_opt->opt.faddr;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1101
1102
  
  	/* Query new route. */
6e8691381   David S. Miller   ipv4: Use cork fl...
1103
1104
  	fl4 = &inet->cork.fl.u.ip4;
  	rt = ip_route_connect(fl4, daddr, 0, RT_CONN_FLAGS(sk),
b23dd4fe4   David S. Miller   ipv4: Make output...
1105
1106
1107
1108
  			      sk->sk_bound_dev_if, sk->sk_protocol,
  			      inet->inet_sport, inet->inet_dport, sk, false);
  	if (IS_ERR(rt))
  		return PTR_ERR(rt);
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1109

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

6e8691381   David S. Miller   ipv4: Use cork fl...
1112
  	new_saddr = fl4->saddr;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1113
1114
1115
1116
1117
  
  	if (new_saddr == old_saddr)
  		return 0;
  
  	if (sysctl_ip_dynaddr > 1) {
673d57e72   Harvey Harrison   net: replace NIPQ...
1118
1119
1120
  		printk(KERN_INFO "%s(): shifting inet->saddr from %pI4 to %pI4
  ",
  		       __func__, &old_saddr, &new_saddr);
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1121
  	}
c720c7e83   Eric Dumazet   inet: rename some...
1122
  	inet->inet_saddr = inet->inet_rcv_saddr = new_saddr;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
  
  	/*
  	 * 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.
  	 */
  	__sk_prot_rehash(sk);
  	return 0;
  }
  
  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...
1140
  	__be32 daddr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1141
  	struct ip_options_rcu *inet_opt;
6e8691381   David S. Miller   ipv4: Use cork fl...
1142
  	struct flowi4 *fl4;
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1143
1144
1145
1146
1147
1148
1149
  	int err;
  
  	/* Route is OK, nothing to do. */
  	if (rt)
  		return 0;
  
  	/* Reroute. */
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1150
1151
  	rcu_read_lock();
  	inet_opt = rcu_dereference(inet->inet_opt);
c720c7e83   Eric Dumazet   inet: rename some...
1152
  	daddr = inet->inet_daddr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1153
1154
1155
  	if (inet_opt && inet_opt->opt.srr)
  		daddr = inet_opt->opt.faddr;
  	rcu_read_unlock();
6e8691381   David S. Miller   ipv4: Use cork fl...
1156
1157
  	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 ...
1158
1159
1160
  				   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...
1161
1162
  	if (!IS_ERR(rt)) {
  		err = 0;
d8d1f30b9   Changli Gao   net-next: remove ...
1163
  		sk_setup_caps(sk, &rt->dst);
b23dd4fe4   David S. Miller   ipv4: Make output...
1164
1165
  	} else {
  		err = PTR_ERR(rt);
32519f11d   Arnaldo Carvalho de Melo   [INET]: Introduce...
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
  		/* 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
  		 */
  		if (!sysctl_ip_dynaddr ||
  		    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...
1181
  EXPORT_SYMBOL(inet_sk_rebuild_header);
a430a43d0   Herbert Xu   [NET] gso: Fix up...
1182
1183
  static int inet_gso_send_check(struct sk_buff *skb)
  {
b71d1d426   Eric Dumazet   inet: constify ip...
1184
  	const struct iphdr *iph;
32613090a   Alexey Dobriyan   net: constify str...
1185
  	const struct net_protocol *ops;
a430a43d0   Herbert Xu   [NET] gso: Fix up...
1186
1187
1188
1189
1190
1191
  	int proto;
  	int ihl;
  	int err = -EINVAL;
  
  	if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
  		goto out;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1192
  	iph = ip_hdr(skb);
a430a43d0   Herbert Xu   [NET] gso: Fix up...
1193
1194
1195
1196
1197
1198
  	ihl = iph->ihl * 4;
  	if (ihl < sizeof(*iph))
  		goto out;
  
  	if (unlikely(!pskb_may_pull(skb, ihl)))
  		goto out;
badff6d01   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1199
1200
  	__skb_pull(skb, ihl);
  	skb_reset_transport_header(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1201
  	iph = ip_hdr(skb);
a430a43d0   Herbert Xu   [NET] gso: Fix up...
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
  	proto = iph->protocol & (MAX_INET_PROTOS - 1);
  	err = -EPROTONOSUPPORT;
  
  	rcu_read_lock();
  	ops = rcu_dereference(inet_protos[proto]);
  	if (likely(ops && ops->gso_send_check))
  		err = ops->gso_send_check(skb);
  	rcu_read_unlock();
  
  out:
  	return err;
  }
c8f44affb   Michał Mirosław   net: introduce an...
1214
1215
  static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
  	netdev_features_t features)
f4c50d990   Herbert Xu   [NET]: Add softwa...
1216
1217
1218
  {
  	struct sk_buff *segs = ERR_PTR(-EINVAL);
  	struct iphdr *iph;
32613090a   Alexey Dobriyan   net: constify str...
1219
  	const struct net_protocol *ops;
f4c50d990   Herbert Xu   [NET]: Add softwa...
1220
1221
1222
  	int proto;
  	int ihl;
  	int id;
d7ca4cc01   Sridhar Samudrala   udpv4: Handle lar...
1223
  	unsigned int offset = 0;
f4c50d990   Herbert Xu   [NET]: Add softwa...
1224

d212f87b0   Stephen Hemminger   [NET]: IPV6 check...
1225
1226
  	if (!(features & NETIF_F_V4_CSUM))
  		features &= ~NETIF_F_SG;
bbcf467da   Herbert Xu   [NET]: Verify gso...
1227
1228
1229
1230
1231
1232
1233
1234
1235
  	if (unlikely(skb_shinfo(skb)->gso_type &
  		     ~(SKB_GSO_TCPV4 |
  		       SKB_GSO_UDP |
  		       SKB_GSO_DODGY |
  		       SKB_GSO_TCP_ECN |
  		       0)))
  		goto out;
  
  	if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
f4c50d990   Herbert Xu   [NET]: Add softwa...
1236
  		goto out;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1237
  	iph = ip_hdr(skb);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1238
1239
1240
  	ihl = iph->ihl * 4;
  	if (ihl < sizeof(*iph))
  		goto out;
bbcf467da   Herbert Xu   [NET]: Verify gso...
1241
  	if (unlikely(!pskb_may_pull(skb, ihl)))
f4c50d990   Herbert Xu   [NET]: Add softwa...
1242
  		goto out;
badff6d01   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1243
1244
  	__skb_pull(skb, ihl);
  	skb_reset_transport_header(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1245
  	iph = ip_hdr(skb);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1246
1247
1248
1249
1250
1251
  	id = ntohs(iph->id);
  	proto = iph->protocol & (MAX_INET_PROTOS - 1);
  	segs = ERR_PTR(-EPROTONOSUPPORT);
  
  	rcu_read_lock();
  	ops = rcu_dereference(inet_protos[proto]);
bbcf467da   Herbert Xu   [NET]: Verify gso...
1252
  	if (likely(ops && ops->gso_segment))
576a30eb6   Herbert Xu   [NET]: Added GSO ...
1253
  		segs = ops->gso_segment(skb, features);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1254
  	rcu_read_unlock();
801678c5a   Hirofumi Nakagawa   Remove duplicated...
1255
  	if (!segs || IS_ERR(segs))
f4c50d990   Herbert Xu   [NET]: Add softwa...
1256
1257
1258
1259
  		goto out;
  
  	skb = segs;
  	do {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1260
  		iph = ip_hdr(skb);
d7ca4cc01   Sridhar Samudrala   udpv4: Handle lar...
1261
1262
1263
1264
1265
1266
1267
1268
  		if (proto == IPPROTO_UDP) {
  			iph->id = htons(id);
  			iph->frag_off = htons(offset >> 3);
  			if (skb->next != NULL)
  				iph->frag_off |= htons(IP_MF);
  			offset += (skb->len - skb->mac_len - iph->ihl * 4);
  		} else
  			iph->id = htons(id++);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1269
1270
  		iph->tot_len = htons(skb->len - skb->mac_len);
  		iph->check = 0;
d56f90a7c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1271
  		iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
f4c50d990   Herbert Xu   [NET]: Add softwa...
1272
1273
1274
1275
1276
  	} while ((skb = skb->next));
  
  out:
  	return segs;
  }
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1277
1278
1279
  static struct sk_buff **inet_gro_receive(struct sk_buff **head,
  					 struct sk_buff *skb)
  {
32613090a   Alexey Dobriyan   net: constify str...
1280
  	const struct net_protocol *ops;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1281
1282
  	struct sk_buff **pp = NULL;
  	struct sk_buff *p;
b71d1d426   Eric Dumazet   inet: constify ip...
1283
  	const struct iphdr *iph;
a5b1cf288   Herbert Xu   gro: Avoid unnece...
1284
1285
  	unsigned int hlen;
  	unsigned int off;
1075f3f65   Herbert Xu   ipv4: Use 32-bit ...
1286
  	unsigned int id;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1287
1288
  	int flush = 1;
  	int proto;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1289

a5b1cf288   Herbert Xu   gro: Avoid unnece...
1290
1291
1292
1293
1294
1295
1296
1297
  	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...
1298

73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1299
1300
1301
1302
1303
1304
  	proto = iph->protocol & (MAX_INET_PROTOS - 1);
  
  	rcu_read_lock();
  	ops = rcu_dereference(inet_protos[proto]);
  	if (!ops || !ops->gro_receive)
  		goto out_unlock;
a5ad24be7   Herbert Xu   gro: Optimise IPv...
1305
  	if (*(u8 *)iph != 0x45)
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1306
1307
1308
1309
  		goto out_unlock;
  
  	if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
  		goto out_unlock;
0eae88f31   Eric Dumazet   net: Fix various ...
1310
1311
  	id = ntohl(*(__be32 *)&iph->id);
  	flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF));
1075f3f65   Herbert Xu   ipv4: Use 32-bit ...
1312
  	id >>= 16;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1313
1314
1315
1316
1317
1318
1319
1320
  
  	for (p = *head; p; p = p->next) {
  		struct iphdr *iph2;
  
  		if (!NAPI_GRO_CB(p)->same_flow)
  			continue;
  
  		iph2 = ip_hdr(p);
a5ad24be7   Herbert Xu   gro: Optimise IPv...
1321
1322
  		if ((iph->protocol ^ iph2->protocol) |
  		    (iph->tos ^ iph2->tos) |
0eae88f31   Eric Dumazet   net: Fix various ...
1323
1324
  		    ((__force u32)iph->saddr ^ (__force u32)iph2->saddr) |
  		    ((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) {
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1325
1326
1327
1328
1329
1330
  			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...
1331
1332
  			(iph->ttl ^ iph2->ttl) |
  			((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id);
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1333
1334
1335
1336
1337
  
  		NAPI_GRO_CB(p)->flush |= flush;
  	}
  
  	NAPI_GRO_CB(skb)->flush |= flush;
86911732d   Herbert Xu   gro: Avoid copyin...
1338
1339
  	skb_gro_pull(skb, sizeof(*iph));
  	skb_set_transport_header(skb, skb_gro_offset(skb));
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
  
  	pp = ops->gro_receive(head, skb);
  
  out_unlock:
  	rcu_read_unlock();
  
  out:
  	NAPI_GRO_CB(skb)->flush |= flush;
  
  	return pp;
  }
  
  static int inet_gro_complete(struct sk_buff *skb)
  {
32613090a   Alexey Dobriyan   net: constify str...
1354
  	const struct net_protocol *ops;
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
  	struct iphdr *iph = ip_hdr(skb);
  	int proto = iph->protocol & (MAX_INET_PROTOS - 1);
  	int err = -ENOSYS;
  	__be16 newlen = htons(skb->len - skb_network_offset(skb));
  
  	csum_replace2(&iph->check, iph->tot_len, newlen);
  	iph->tot_len = newlen;
  
  	rcu_read_lock();
  	ops = rcu_dereference(inet_protos[proto]);
  	if (WARN_ON(!ops || !ops->gro_complete))
  		goto out_unlock;
  
  	err = ops->gro_complete(skb);
  
  out_unlock:
  	rcu_read_unlock();
  
  	return err;
  }
eee4fe4de   Denis V. Lunev   [INET]: Let inet_...
1375
  int inet_ctl_sock_create(struct sock **sk, unsigned short family,
5677242f4   Denis V. Lunev   [NETNS]: Inet con...
1376
1377
  			 unsigned short type, unsigned char protocol,
  			 struct net *net)
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1378
  {
eee4fe4de   Denis V. Lunev   [INET]: Let inet_...
1379
1380
  	struct socket *sock;
  	int rc = sock_create_kern(family, type, protocol, &sock);
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1381
1382
  
  	if (rc == 0) {
eee4fe4de   Denis V. Lunev   [INET]: Let inet_...
1383
1384
  		*sk = sock->sk;
  		(*sk)->sk_allocation = GFP_ATOMIC;
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1385
1386
1387
1388
  		/*
  		 * 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_...
1389
  		(*sk)->sk_prot->unhash(*sk);
5677242f4   Denis V. Lunev   [NETNS]: Inet con...
1390
1391
  
  		sk_change_net(*sk, net);
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1392
1393
1394
  	}
  	return rc;
  }
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
1395
  EXPORT_SYMBOL_GPL(inet_ctl_sock_create);
7d720c3e4   Tejun Heo   percpu: add __per...
1396
  unsigned long snmp_fold_field(void __percpu *mib[], int offt)
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1397
1398
  {
  	unsigned long res = 0;
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1399
  	int i, j;
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1400
1401
  
  	for_each_possible_cpu(i) {
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1402
1403
  		for (j = 0; j < SNMP_ARRAY_SZ; j++)
  			res += *(((unsigned long *) per_cpu_ptr(mib[j], i)) + offt);
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1404
1405
1406
1407
  	}
  	return res;
  }
  EXPORT_SYMBOL_GPL(snmp_fold_field);
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
1408
1409
1410
1411
1412
1413
1414
1415
  #if BITS_PER_LONG==32
  
  u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t syncp_offset)
  {
  	u64 res = 0;
  	int cpu;
  
  	for_each_possible_cpu(cpu) {
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1416
  		void *bhptr;
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
1417
  		struct u64_stats_sync *syncp;
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1418
  		u64 v;
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
1419
  		unsigned int start;
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1420
  		bhptr = per_cpu_ptr(mib[0], cpu);
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
1421
1422
1423
  		syncp = (struct u64_stats_sync *)(bhptr + syncp_offset);
  		do {
  			start = u64_stats_fetch_begin_bh(syncp);
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1424
  			v = *(((u64 *) bhptr) + offt);
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
1425
  		} while (u64_stats_fetch_retry_bh(syncp, start));
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1426
  		res += v;
4ce3c183f   Eric Dumazet   snmp: 64bit ipsta...
1427
1428
1429
1430
1431
  	}
  	return res;
  }
  EXPORT_SYMBOL_GPL(snmp_fold_field64);
  #endif
1823e4c80   Eric Dumazet   snmp: add align p...
1432
  int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align)
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1433
1434
  {
  	BUG_ON(ptr == NULL);
1823e4c80   Eric Dumazet   snmp: add align p...
1435
  	ptr[0] = __alloc_percpu(mibsize, align);
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1436
  	if (!ptr[0])
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1437
1438
  		return -ENOMEM;
  #if SNMP_ARRAY_SZ == 2
1823e4c80   Eric Dumazet   snmp: add align p...
1439
  	ptr[1] = __alloc_percpu(mibsize, align);
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1440
1441
1442
1443
1444
1445
  	if (!ptr[1]) {
  		free_percpu(ptr[0]);
  		ptr[0] = NULL;
  		return -ENOMEM;
  	}
  #endif
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1446
  	return 0;
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1447
1448
  }
  EXPORT_SYMBOL_GPL(snmp_mib_init);
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1449
  void snmp_mib_free(void __percpu *ptr[SNMP_ARRAY_SZ])
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1450
  {
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1451
  	int i;
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1452
  	BUG_ON(ptr == NULL);
8f0ea0fe3   Eric Dumazet   snmp: reduce perc...
1453
1454
1455
1456
  	for (i = 0; i < SNMP_ARRAY_SZ; i++) {
  		free_percpu(ptr[i]);
  		ptr[i] = NULL;
  	}
5e0f04351   Herbert Xu   [IPV4]: Consolida...
1457
1458
  }
  EXPORT_SYMBOL_GPL(snmp_mib_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459
  #ifdef CONFIG_IP_MULTICAST
32613090a   Alexey Dobriyan   net: constify str...
1460
  static const struct net_protocol igmp_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
  	.handler =	igmp_rcv,
b4ee07df3   Alexey Dobriyan   netns: igmp: allo...
1462
  	.netns_ok =	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1463
1464
  };
  #endif
32613090a   Alexey Dobriyan   net: constify str...
1465
  static const struct net_protocol tcp_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1466
1467
  	.handler =	tcp_v4_rcv,
  	.err_handler =	tcp_v4_err,
a430a43d0   Herbert Xu   [NET] gso: Fix up...
1468
  	.gso_send_check = tcp_v4_gso_send_check,
f4c50d990   Herbert Xu   [NET]: Add softwa...
1469
  	.gso_segment =	tcp_tso_segment,
bf296b125   Herbert Xu   tcp: Add GRO support
1470
1471
  	.gro_receive =	tcp4_gro_receive,
  	.gro_complete =	tcp4_gro_complete,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1472
  	.no_policy =	1,
92f1fecb4   Denis V. Lunev   [NETNS]: Enable T...
1473
  	.netns_ok =	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
  };
32613090a   Alexey Dobriyan   net: constify str...
1475
  static const struct net_protocol udp_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
1477
  	.handler =	udp_rcv,
  	.err_handler =	udp_err,
d7ca4cc01   Sridhar Samudrala   udpv4: Handle lar...
1478
1479
  	.gso_send_check = udp4_ufo_send_check,
  	.gso_segment = udp4_ufo_fragment,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1480
  	.no_policy =	1,
92f1fecb4   Denis V. Lunev   [NETNS]: Enable T...
1481
  	.netns_ok =	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482
  };
32613090a   Alexey Dobriyan   net: constify str...
1483
  static const struct net_protocol icmp_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
  	.handler =	icmp_rcv,
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1485
  	.err_handler =	ping_err,
8b7817f3a   Herbert Xu   [IPSEC]: Add ICMP...
1486
  	.no_policy =	1,
92f1fecb4   Denis V. Lunev   [NETNS]: Enable T...
1487
  	.netns_ok =	1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488
  };
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
1489
1490
  static __net_init int ipv4_mib_init_net(struct net *net)
  {
7d720c3e4   Tejun Heo   percpu: add __per...
1491
  	if (snmp_mib_init((void __percpu **)net->mib.tcp_statistics,
1823e4c80   Eric Dumazet   snmp: add align p...
1492
1493
  			  sizeof(struct tcp_mib),
  			  __alignof__(struct tcp_mib)) < 0)
57ef42d59   Pavel Emelyanov   mib: put tcp stat...
1494
  		goto err_tcp_mib;
7d720c3e4   Tejun Heo   percpu: add __per...
1495
  	if (snmp_mib_init((void __percpu **)net->mib.ip_statistics,
1823e4c80   Eric Dumazet   snmp: add align p...
1496
1497
  			  sizeof(struct ipstats_mib),
  			  __alignof__(struct ipstats_mib)) < 0)
a20f5799c   Pavel Emelyanov   mib: put ip stati...
1498
  		goto err_ip_mib;
7d720c3e4   Tejun Heo   percpu: add __per...
1499
  	if (snmp_mib_init((void __percpu **)net->mib.net_statistics,
1823e4c80   Eric Dumazet   snmp: add align p...
1500
1501
  			  sizeof(struct linux_mib),
  			  __alignof__(struct linux_mib)) < 0)
61a7e2602   Pavel Emelyanov   mib: put net stat...
1502
  		goto err_net_mib;
7d720c3e4   Tejun Heo   percpu: add __per...
1503
  	if (snmp_mib_init((void __percpu **)net->mib.udp_statistics,
1823e4c80   Eric Dumazet   snmp: add align p...
1504
1505
  			  sizeof(struct udp_mib),
  			  __alignof__(struct udp_mib)) < 0)
2f275f91a   Pavel Emelyanov   mib: put udp stat...
1506
  		goto err_udp_mib;
7d720c3e4   Tejun Heo   percpu: add __per...
1507
  	if (snmp_mib_init((void __percpu **)net->mib.udplite_statistics,
1823e4c80   Eric Dumazet   snmp: add align p...
1508
1509
  			  sizeof(struct udp_mib),
  			  __alignof__(struct udp_mib)) < 0)
386019d35   Pavel Emelyanov   mib: put udplite ...
1510
  		goto err_udplite_mib;
7d720c3e4   Tejun Heo   percpu: add __per...
1511
  	if (snmp_mib_init((void __percpu **)net->mib.icmp_statistics,
1823e4c80   Eric Dumazet   snmp: add align p...
1512
1513
  			  sizeof(struct icmp_mib),
  			  __alignof__(struct icmp_mib)) < 0)
b60538a0d   Pavel Emelyanov   mib: put icmp sta...
1514
  		goto err_icmp_mib;
acb32ba3d   Eric Dumazet   ipv4: reduce perc...
1515
1516
1517
  	net->mib.icmpmsg_statistics = kzalloc(sizeof(struct icmpmsg_mib),
  					      GFP_KERNEL);
  	if (!net->mib.icmpmsg_statistics)
923c6586b   Pavel Emelyanov   mib: put icmpmsg ...
1518
  		goto err_icmpmsg_mib;
57ef42d59   Pavel Emelyanov   mib: put tcp stat...
1519
1520
  
  	tcp_mib_init(net);
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
1521
  	return 0;
57ef42d59   Pavel Emelyanov   mib: put tcp stat...
1522

923c6586b   Pavel Emelyanov   mib: put icmpmsg ...
1523
  err_icmpmsg_mib:
7d720c3e4   Tejun Heo   percpu: add __per...
1524
  	snmp_mib_free((void __percpu **)net->mib.icmp_statistics);
b60538a0d   Pavel Emelyanov   mib: put icmp sta...
1525
  err_icmp_mib:
7d720c3e4   Tejun Heo   percpu: add __per...
1526
  	snmp_mib_free((void __percpu **)net->mib.udplite_statistics);
386019d35   Pavel Emelyanov   mib: put udplite ...
1527
  err_udplite_mib:
7d720c3e4   Tejun Heo   percpu: add __per...
1528
  	snmp_mib_free((void __percpu **)net->mib.udp_statistics);
2f275f91a   Pavel Emelyanov   mib: put udp stat...
1529
  err_udp_mib:
7d720c3e4   Tejun Heo   percpu: add __per...
1530
  	snmp_mib_free((void __percpu **)net->mib.net_statistics);
61a7e2602   Pavel Emelyanov   mib: put net stat...
1531
  err_net_mib:
7d720c3e4   Tejun Heo   percpu: add __per...
1532
  	snmp_mib_free((void __percpu **)net->mib.ip_statistics);
a20f5799c   Pavel Emelyanov   mib: put ip stati...
1533
  err_ip_mib:
7d720c3e4   Tejun Heo   percpu: add __per...
1534
  	snmp_mib_free((void __percpu **)net->mib.tcp_statistics);
57ef42d59   Pavel Emelyanov   mib: put tcp stat...
1535
1536
  err_tcp_mib:
  	return -ENOMEM;
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
1537
1538
1539
1540
  }
  
  static __net_exit void ipv4_mib_exit_net(struct net *net)
  {
acb32ba3d   Eric Dumazet   ipv4: reduce perc...
1541
  	kfree(net->mib.icmpmsg_statistics);
7d720c3e4   Tejun Heo   percpu: add __per...
1542
1543
1544
1545
1546
1547
  	snmp_mib_free((void __percpu **)net->mib.icmp_statistics);
  	snmp_mib_free((void __percpu **)net->mib.udplite_statistics);
  	snmp_mib_free((void __percpu **)net->mib.udp_statistics);
  	snmp_mib_free((void __percpu **)net->mib.net_statistics);
  	snmp_mib_free((void __percpu **)net->mib.ip_statistics);
  	snmp_mib_free((void __percpu **)net->mib.tcp_statistics);
9b4661bd6   Pavel Emelyanov   ipv4: add pernet ...
1548
1549
1550
1551
1552
1553
  }
  
  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
1554
1555
  static int __init init_ipv4_mibs(void)
  {
d89cbbb1e   Pavel Emelyanov   ipv4: clean the i...
1556
  	return register_pernet_subsys(&ipv4_mib_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1557
1558
1559
  }
  
  static int ipv4_proc_init(void);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1560

30e224d76   Herbert Xu   [IPV4]: Fix crash...
1561
1562
1563
  /*
   *	IP protocol layer initialiser
   */
7546dd97d   Stephen Hemminger   net: convert usag...
1564
  static struct packet_type ip_packet_type __read_mostly = {
09640e636   Harvey Harrison   net: replace uses...
1565
  	.type = cpu_to_be16(ETH_P_IP),
30e224d76   Herbert Xu   [IPV4]: Fix crash...
1566
  	.func = ip_rcv,
a430a43d0   Herbert Xu   [NET] gso: Fix up...
1567
  	.gso_send_check = inet_gso_send_check,
f4c50d990   Herbert Xu   [NET]: Add softwa...
1568
  	.gso_segment = inet_gso_segment,
73cc19f15   Herbert Xu   ipv4: Add GRO inf...
1569
1570
  	.gro_receive = inet_gro_receive,
  	.gro_complete = inet_gro_complete,
30e224d76   Herbert Xu   [IPV4]: Fix crash...
1571
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1572
1573
1574
1575
1576
1577
  static int __init inet_init(void)
  {
  	struct sk_buff *dummy_skb;
  	struct inet_protosw *q;
  	struct list_head *r;
  	int rc = -EINVAL;
ef047f5e1   YOSHIFUJI Hideaki   [NET]: Use BUILD_...
1578
  	BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1579

e3826f1e9   Amerigo Wang   net: reserve port...
1580
1581
1582
  	sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL);
  	if (!sysctl_local_reserved_ports)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
1584
  	rc = proto_register(&tcp_prot, 1);
  	if (rc)
e3826f1e9   Amerigo Wang   net: reserve port...
1585
  		goto out_free_reserved_ports;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1586
1587
1588
1589
1590
1591
1592
1593
  
  	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...
1594
1595
1596
  	rc = proto_register(&ping_prot, 1);
  	if (rc)
  		goto out_unregister_raw_proto;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1597
  	/*
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1598
  	 *	Tell SOCKET that we are alive...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1599
  	 */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1600
  	(void)sock_register(&inet_family_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1601

bd7b1533c   Al Viro   [PATCH] sysctl: m...
1602
1603
1604
  #ifdef CONFIG_SYSCTL
  	ip_static_sysctl_init();
  #endif
3dc43e3e4   Glauber Costa   per-netns ipv4 sy...
1605
  	tcp_prot.sysctl_mem = init_net.ipv4.sysctl_tcp_mem;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
  	/*
  	 *	Add all the base protocols.
  	 */
  
  	if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)
  		printk(KERN_CRIT "inet_init: Cannot add ICMP protocol
  ");
  	if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0)
  		printk(KERN_CRIT "inet_init: Cannot add UDP protocol
  ");
  	if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0)
  		printk(KERN_CRIT "inet_init: Cannot add TCP protocol
  ");
  #ifdef CONFIG_IP_MULTICAST
  	if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0)
  		printk(KERN_CRIT "inet_init: Cannot add IGMP protocol
  ");
  #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...
1637
1638
1639
  	/*
  	 *	Set the IP module up
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640
1641
  
  	ip_init();
9b0f976f2   Denis V. Lunev   [INET]: Remove st...
1642
  	tcp_v4_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1643
1644
1645
  
  	/* Setup TCP slab cache for open requests. */
  	tcp_init();
95766fff6   Hideo Aoki   [UDP]: Add memory...
1646
1647
  	/* Setup UDP memory threshold */
  	udp_init();
ba4e58eca   Gerrit Renker   [NET]: Supporting...
1648
1649
  	/* Add UDP-Lite (RFC 3828) */
  	udplite4_register();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650

c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1651
  	ping_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1652
1653
1654
  	/*
  	 *	Set the ICMP layer up
  	 */
a5710d658   Denis V. Lunev   [ICMP]: Add retur...
1655
1656
1657
  	if (icmp_init() < 0)
  		panic("Failed to create the ICMP control socket.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1658
1659
1660
1661
1662
  
  	/*
  	 *	Initialise the multicast router
  	 */
  #if defined(CONFIG_IP_MROUTE)
03d2f897e   Wang Chen   ipv4: Do cleanup ...
1663
1664
1665
  	if (ip_mr_init())
  		printk(KERN_CRIT "inet_init: Cannot init ipv4 mroute
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1666
1667
1668
  #endif
  	/*
  	 *	Initialise per-cpu ipv4 mibs
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1669
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670

132adf546   Stephen Hemminger   [IPV4]: cleanup
1671
  	if (init_ipv4_mibs())
03d2f897e   Wang Chen   ipv4: Do cleanup ...
1672
1673
  		printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs
  ");
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1674

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1675
1676
1677
  	ipv4_proc_init();
  
  	ipfrag_init();
30e224d76   Herbert Xu   [IPV4]: Fix crash...
1678
  	dev_add_pack(&ip_packet_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1679
1680
1681
  	rc = 0;
  out:
  	return rc;
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1682
1683
  out_unregister_raw_proto:
  	proto_unregister(&raw_prot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1684
1685
  out_unregister_udp_proto:
  	proto_unregister(&udp_prot);
321efff7c   Olaf Kirch   [IPV4]: Fix order...
1686
1687
  out_unregister_tcp_proto:
  	proto_unregister(&tcp_prot);
e3826f1e9   Amerigo Wang   net: reserve port...
1688
1689
  out_free_reserved_ports:
  	kfree(sysctl_local_reserved_ports);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690
1691
  	goto out;
  }
a536e0778   Heiko Carstens   [IPV4]: inet_init...
1692
  fs_initcall(inet_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1693
1694
1695
1696
  
  /* ------------------------------------------------------------------------ */
  
  #ifdef CONFIG_PROC_FS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
  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...
1707
1708
  	if (ping_proc_init())
  		goto out_ping;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1709
1710
1711
1712
1713
  	if (ip_misc_proc_init())
  		goto out_misc;
  out:
  	return rc;
  out_misc:
c319b4d76   Vasiliy Kulikov   net: ipv4: add IP...
1714
1715
  	ping_proc_exit();
  out_ping:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
  	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 */
  
  MODULE_ALIAS_NETPROTO(PF_INET);