Blame view

net/ipv4/raw.c 25.6 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.
   *
   *		RAW - implementation of IP "raw" sockets.
   *
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
   *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *
   * Fixes:
   *		Alan Cox	:	verify_area() fixed up
   *		Alan Cox	:	ICMP error handling
   *		Alan Cox	:	EMSGSIZE if you send too big a packet
   *		Alan Cox	: 	Now uses generic datagrams and shared
   *					skbuff library. No more peek crashes,
   *					no more backlogs
   *		Alan Cox	:	Checks sk->broadcast.
   *		Alan Cox	:	Uses skb_free_datagram/skb_copy_datagram
   *		Alan Cox	:	Raw passes ip options too
   *		Alan Cox	:	Setsocketopt added
   *		Alan Cox	:	Fixed error return for broadcasts
   *		Alan Cox	:	Removed wake_up calls
   *		Alan Cox	:	Use ttl/tos
   *		Alan Cox	:	Cleaned up old debugging
   *		Alan Cox	:	Use new kernel side addresses
   *	Arnt Gulbrandsen	:	Fixed MSG_DONTROUTE in raw sockets.
   *		Alan Cox	:	BSD style RAW socket demultiplexing.
   *		Alan Cox	:	Beginnings of mrouted support.
   *		Alan Cox	:	Added IP_HDRINCL option.
   *		Alan Cox	:	Skip broadcast check if BSDism set.
   *		David S. Miller	:	New socket lookup architecture.
   *
   *		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.
   */
bf0d52492   Dave Jones   [NET]: Remove unn...
39

715b49ef2   Alan Cox   [PATCH] EDAC: ato...
40
  #include <linux/types.h>
60063497a   Arun Sharma   atomic: use <linu...
41
  #include <linux/atomic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
  #include <asm/byteorder.h>
  #include <asm/current.h>
  #include <asm/uaccess.h>
  #include <asm/ioctls.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
  #include <linux/stddef.h>
  #include <linux/slab.h>
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  #include <linux/kernel.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
50
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
56
57
58
  #include <linux/spinlock.h>
  #include <linux/sockios.h>
  #include <linux/socket.h>
  #include <linux/in.h>
  #include <linux/mroute.h>
  #include <linux/netdevice.h>
  #include <linux/in_route.h>
  #include <linux/route.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  #include <linux/skbuff.h>
f5220d639   Quentin Armitage   ipv4: Make IP_MUL...
60
  #include <linux/igmp.h>
457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
61
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
  #include <net/dst.h>
  #include <net/sock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
70
  #include <linux/ip.h>
  #include <linux/net.h>
  #include <net/ip.h>
  #include <net/icmp.h>
  #include <net/udp.h>
  #include <net/raw.h>
  #include <net/snmp.h>
c752f0739   Arnaldo Carvalho de Melo   [TCP]: Move the t...
71
  #include <net/tcp_states.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
79
  #include <net/inet_common.h>
  #include <net/checksum.h>
  #include <net/xfrm.h>
  #include <linux/rtnetlink.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <linux/netfilter.h>
  #include <linux/netfilter_ipv4.h>
709b46e8d   Eric W. Biederman   net: Add compat i...
80
  #include <linux/compat.h>
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
81
82
83
  #include <linux/uio.h>
  
  struct raw_frag_vec {
b61e9dcc5   Al Viro   raw.c: stick msgh...
84
  	struct msghdr *msg;
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
85
86
87
88
89
90
  	union {
  		struct icmphdr icmph;
  		char c[1];
  	} hdr;
  	int hlen;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91

b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
92
  static struct raw_hashinfo raw_v4_hashinfo = {
938b93adb   Robert P. J. Day   [NET]: Add debugg...
93
  	.lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
94
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95

086c653f5   Craig Gallek   sock: struct prot...
96
  int raw_hash_sk(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  {
fc8717baa   Pavel Emelyanov   [RAW]: Add raw_ha...
98
  	struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
65b4c50b4   Pavel Emelyanov   [RAW]: Consolidat...
99
  	struct hlist_head *head;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100

c720c7e83   Eric Dumazet   inet: rename some...
101
  	head = &h->ht[inet_sk(sk)->inet_num & (RAW_HTABLE_SIZE - 1)];
65b4c50b4   Pavel Emelyanov   [RAW]: Consolidat...
102
103
  
  	write_lock_bh(&h->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  	sk_add_node(sk, head);
c29a0bc4d   Pavel Emelyanov   [SOCK][NETNS]: Ad...
105
  	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
65b4c50b4   Pavel Emelyanov   [RAW]: Consolidat...
106
  	write_unlock_bh(&h->lock);
086c653f5   Craig Gallek   sock: struct prot...
107
108
  
  	return 0;
65b4c50b4   Pavel Emelyanov   [RAW]: Consolidat...
109
110
  }
  EXPORT_SYMBOL_GPL(raw_hash_sk);
fc8717baa   Pavel Emelyanov   [RAW]: Add raw_ha...
111
  void raw_unhash_sk(struct sock *sk)
ab70768ec   Pavel Emelyanov   [RAW]: Consolidat...
112
  {
fc8717baa   Pavel Emelyanov   [RAW]: Add raw_ha...
113
  	struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
ab70768ec   Pavel Emelyanov   [RAW]: Consolidat...
114
115
  	write_lock_bh(&h->lock);
  	if (sk_del_node_init(sk))
c29a0bc4d   Pavel Emelyanov   [SOCK][NETNS]: Ad...
116
  		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
ab70768ec   Pavel Emelyanov   [RAW]: Consolidat...
117
118
119
  	write_unlock_bh(&h->lock);
  }
  EXPORT_SYMBOL_GPL(raw_unhash_sk);
be185884b   Pavel Emelyanov   [NETNS][RAW]: Mak...
120
121
  static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
  		unsigned short num, __be32 raddr, __be32 laddr, int dif)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  {
b67bfe0d4   Sasha Levin   hlist: drop the n...
123
  	sk_for_each_from(sk) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  		struct inet_sock *inet = inet_sk(sk);
c720c7e83   Eric Dumazet   inet: rename some...
125
126
127
  		if (net_eq(sock_net(sk), net) && inet->inet_num == num	&&
  		    !(inet->inet_daddr && inet->inet_daddr != raddr) 	&&
  		    !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
132
133
134
135
136
137
138
139
  		    !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
  			goto found; /* gotcha */
  	}
  	sk = NULL;
  found:
  	return sk;
  }
  
  /*
   *	0 - deliver
   *	1 - block
   */
ab43ed8b7   Eric Dumazet   ipv4: raw: fix ic...
140
  static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  {
ab43ed8b7   Eric Dumazet   ipv4: raw: fix ic...
142
143
  	struct icmphdr _hdr;
  	const struct icmphdr *hdr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144

ab43ed8b7   Eric Dumazet   ipv4: raw: fix ic...
145
146
147
  	hdr = skb_header_pointer(skb, skb_transport_offset(skb),
  				 sizeof(_hdr), &_hdr);
  	if (!hdr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  		return 1;
ab43ed8b7   Eric Dumazet   ipv4: raw: fix ic...
149
  	if (hdr->type < 32) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  		__u32 data = raw_sk(sk)->filter.data;
ab43ed8b7   Eric Dumazet   ipv4: raw: fix ic...
151
  		return ((1U << hdr->type) & data) != 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
157
158
159
160
161
162
163
  	}
  
  	/* Do not block unknown ICMP types */
  	return 0;
  }
  
  /* IP input processing comes here for RAW socket delivery.
   * Caller owns SKB, so we must make clones.
   *
   * RFC 1122: SHOULD pass TOS value up to the transport layer.
   * -> It does. And not only TOS, but all IP header.
   */
b71d1d426   Eric Dumazet   inet: constify ip...
164
  static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
  {
  	struct sock *sk;
  	struct hlist_head *head;
d13964f44   Patrick McHardy   [IPV4/6]: Check i...
168
  	int delivered = 0;
be185884b   Pavel Emelyanov   [NETNS][RAW]: Mak...
169
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170

b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
171
172
  	read_lock(&raw_v4_hashinfo.lock);
  	head = &raw_v4_hashinfo.ht[hash];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
  	if (hlist_empty(head))
  		goto out;
be185884b   Pavel Emelyanov   [NETNS][RAW]: Mak...
175

c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
176
  	net = dev_net(skb->dev);
be185884b   Pavel Emelyanov   [NETNS][RAW]: Mak...
177
  	sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
  			     iph->saddr, iph->daddr,
  			     skb->dev->ifindex);
  
  	while (sk) {
d13964f44   Patrick McHardy   [IPV4/6]: Check i...
182
  		delivered = 1;
f5220d639   Quentin Armitage   ipv4: Make IP_MUL...
183
184
185
  		if ((iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) &&
  		    ip_mc_sf_allow(sk, iph->daddr, iph->saddr,
  				   skb->dev->ifindex)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
  			struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
  
  			/* Not releasing hash table! */
  			if (clone)
  				raw_rcv(sk, clone);
  		}
be185884b   Pavel Emelyanov   [NETNS][RAW]: Mak...
192
  		sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
196
  				     iph->saddr, iph->daddr,
  				     skb->dev->ifindex);
  	}
  out:
b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
197
  	read_unlock(&raw_v4_hashinfo.lock);
d13964f44   Patrick McHardy   [IPV4/6]: Check i...
198
  	return delivered;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  }
7bc54c903   Pavel Emelyanov   [IPv4] RAW: Compa...
200
201
202
203
  int raw_local_deliver(struct sk_buff *skb, int protocol)
  {
  	int hash;
  	struct sock *raw_sk;
b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
204
205
  	hash = protocol & (RAW_HTABLE_SIZE - 1);
  	raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
7bc54c903   Pavel Emelyanov   [IPv4] RAW: Compa...
206
207
208
209
210
211
212
213
214
215
216
217
  
  	/* If there maybe a raw socket we must check - if not we
  	 * don't care less
  	 */
  	if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash))
  		raw_sk = NULL;
  
  	return raw_sk != NULL;
  
  }
  
  static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
  {
  	struct inet_sock *inet = inet_sk(sk);
88c7664f1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
220
221
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
  	int err = 0;
  	int harderr = 0;
363933955   David S. Miller   ipv4: Handle PMTU...
224
225
  	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
  		ipv4_sk_update_pmtu(skb, sk, info);
8d65b1190   Duan Jiong   net: raw: do not ...
226
  	else if (type == ICMP_REDIRECT) {
55be7a9c6   David S. Miller   ipv4: Add redirec...
227
  		ipv4_sk_redirect(skb, sk);
8d65b1190   Duan Jiong   net: raw: do not ...
228
229
  		return;
  	}
363933955   David S. Miller   ipv4: Handle PMTU...
230

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  	/* Report error on raw socket, if:
  	   1. User requested ip_recverr.
  	   2. Socket is connected (otherwise the error indication
  	      is useless without ip_recverr and error is hard.
  	 */
  	if (!inet->recverr && sk->sk_state != TCP_ESTABLISHED)
  		return;
  
  	switch (type) {
  	default:
  	case ICMP_TIME_EXCEEDED:
  		err = EHOSTUNREACH;
  		break;
  	case ICMP_SOURCE_QUENCH:
  		return;
  	case ICMP_PARAMETERPROB:
  		err = EPROTO;
  		harderr = 1;
  		break;
  	case ICMP_DEST_UNREACH:
  		err = EHOSTUNREACH;
  		if (code > NR_ICMP_UNREACH)
  			break;
  		err = icmp_err_convert[code].errno;
  		harderr = icmp_err_convert[code].fatal;
  		if (code == ICMP_FRAG_NEEDED) {
  			harderr = inet->pmtudisc != IP_PMTUDISC_DONT;
  			err = EMSGSIZE;
  		}
  	}
  
  	if (inet->recverr) {
b71d1d426   Eric Dumazet   inet: constify ip...
263
  		const struct iphdr *iph = (const struct iphdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
265
266
267
268
269
270
271
272
273
274
275
  		u8 *payload = skb->data + (iph->ihl << 2);
  
  		if (inet->hdrincl)
  			payload = skb->data;
  		ip_icmp_error(sk, skb, err, 0, info, payload);
  	}
  
  	if (inet->recverr || harderr) {
  		sk->sk_err = err;
  		sk->sk_error_report(sk);
  	}
  }
7bc54c903   Pavel Emelyanov   [IPv4] RAW: Compa...
276
277
278
279
  void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
  {
  	int hash;
  	struct sock *raw_sk;
b71d1d426   Eric Dumazet   inet: constify ip...
280
  	const struct iphdr *iph;
be185884b   Pavel Emelyanov   [NETNS][RAW]: Mak...
281
  	struct net *net;
7bc54c903   Pavel Emelyanov   [IPv4] RAW: Compa...
282

b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
283
  	hash = protocol & (RAW_HTABLE_SIZE - 1);
7bc54c903   Pavel Emelyanov   [IPv4] RAW: Compa...
284

b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
285
286
  	read_lock(&raw_v4_hashinfo.lock);
  	raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
00db41243   Ian Morris   ipv4: coding styl...
287
  	if (raw_sk) {
b71d1d426   Eric Dumazet   inet: constify ip...
288
  		iph = (const struct iphdr *)skb->data;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
289
  		net = dev_net(skb->dev);
be185884b   Pavel Emelyanov   [NETNS][RAW]: Mak...
290
291
292
  
  		while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol,
  						iph->daddr, iph->saddr,
7bc54c903   Pavel Emelyanov   [IPv4] RAW: Compa...
293
294
295
  						skb->dev->ifindex)) != NULL) {
  			raw_err(raw_sk, skb, info);
  			raw_sk = sk_next(raw_sk);
b71d1d426   Eric Dumazet   inet: constify ip...
296
  			iph = (const struct iphdr *)skb->data;
7bc54c903   Pavel Emelyanov   [IPv4] RAW: Compa...
297
298
  		}
  	}
b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
299
  	read_unlock(&raw_v4_hashinfo.lock);
7bc54c903   Pavel Emelyanov   [IPv4] RAW: Compa...
300
  }
5e73ea1a3   Daniel Baluta   ipv4: fix checkpa...
301
  static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
  {
  	/* Charge it to the socket. */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
304

fbf8866d6   Shawn Bohrer   net: ipv4 only po...
305
  	ipv4_pktinfo_prepare(sk, skb);
d826eb14e   Eric Dumazet   ipv4: PKTINFO doe...
306
  	if (sock_queue_rcv_skb(sk, skb) < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
310
311
312
313
314
315
316
  		kfree_skb(skb);
  		return NET_RX_DROP;
  	}
  
  	return NET_RX_SUCCESS;
  }
  
  int raw_rcv(struct sock *sk, struct sk_buff *skb)
  {
  	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) {
33c732c36   Wang Chen   [IPV4]: Add raw d...
317
  		atomic_inc(&sk->sk_drops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
  		kfree_skb(skb);
  		return NET_RX_DROP;
  	}
b59c27010   Patrick McHardy   [NETFILTER]: Keep...
321
  	nf_reset(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322

d56f90a7c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
323
  	skb_push(skb, skb->data - skb_network_header(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
  
  	raw_rcv_skb(sk, skb);
  	return 0;
  }
77968b782   David S. Miller   ipv4: Pass flow k...
328
  static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
7ae9abfd9   Al Viro   ipv4: raw_send_hd...
329
  			   struct msghdr *msg, size_t length,
c14ac9451   Soheil Hassas Yeganeh   sock: enable time...
330
331
  			   struct rtable **rtp, unsigned int flags,
  			   const struct sockcm_cookie *sockc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
  {
  	struct inet_sock *inet = inet_sk(sk);
0388b0042   Pavel Emelyanov   icmp: add struct ...
334
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
  	struct iphdr *iph;
  	struct sk_buff *skb;
f844c74fe   Herbert Xu   [IPV4] raw: Stren...
337
  	unsigned int iphlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
  	int err;
1789a640f   Eric Dumazet   raw: avoid two at...
339
  	struct rtable *rt = *rtp;
660882432   Herbert Xu   ipv4: Remove all ...
340
  	int hlen, tlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341

d8d1f30b9   Changli Gao   net-next: remove ...
342
  	if (length > rt->dst.dev->mtu) {
77968b782   David S. Miller   ipv4: Pass flow k...
343
  		ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
d8d1f30b9   Changli Gao   net-next: remove ...
344
  			       rt->dst.dev->mtu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
346
347
348
  		return -EMSGSIZE;
  	}
  	if (flags&MSG_PROBE)
  		goto out;
660882432   Herbert Xu   ipv4: Remove all ...
349
350
  	hlen = LL_RESERVED_SPACE(rt->dst.dev);
  	tlen = rt->dst.dev->needed_tailroom;
f5184d267   Johannes Berg   net: Allow netdev...
351
  	skb = sock_alloc_send_skb(sk,
660882432   Herbert Xu   ipv4: Remove all ...
352
  				  length + hlen + tlen + 15,
f5184d267   Johannes Berg   net: Allow netdev...
353
  				  flags & MSG_DONTWAIT, &err);
51456b291   Ian Morris   ipv4: coding styl...
354
  	if (!skb)
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
355
  		goto error;
660882432   Herbert Xu   ipv4: Remove all ...
356
  	skb_reserve(skb, hlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
  
  	skb->priority = sk->sk_priority;
4a19ec580   Laszlo Attila Toth   [NET]: Introducin...
359
  	skb->mark = sk->sk_mark;
d8d1f30b9   Changli Gao   net-next: remove ...
360
  	skb_dst_set(skb, &rt->dst);
1789a640f   Eric Dumazet   raw: avoid two at...
361
  	*rtp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362

7e28ecc28   Arnaldo Carvalho de Melo   [SK_BUFF]: Use sk...
363
  	skb_reset_network_header(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
364
  	iph = ip_hdr(skb);
7e28ecc28   Arnaldo Carvalho de Melo   [SK_BUFF]: Use sk...
365
  	skb_put(skb, length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
  
  	skb->ip_summed = CHECKSUM_NONE;
c14ac9451   Soheil Hassas Yeganeh   sock: enable time...
368
  	sock_tx_timestamp(sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags);
11878b40e   Willem de Bruijn   net-timestamp: SO...
369

b0e380b1d   Arnaldo Carvalho de Melo   [SK_BUFF]: unions...
370
  	skb->transport_header = skb->network_header;
55888dfb6   Neil Horman   AF_RAW: Augment r...
371
  	err = -EFAULT;
21226abb4   Al Viro   net: switch memcp...
372
  	if (memcpy_from_msg(iph, msg, length))
55888dfb6   Neil Horman   AF_RAW: Augment r...
373
  		goto error_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374

f844c74fe   Herbert Xu   [IPV4] raw: Stren...
375
  	iphlen = iph->ihl * 4;
55888dfb6   Neil Horman   AF_RAW: Augment r...
376
377
378
379
380
381
382
383
384
385
386
387
388
  
  	/*
  	 * We don't want to modify the ip header, but we do need to
  	 * be sure that it won't cause problems later along the network
  	 * stack.  Specifically we want to make sure that iph->ihl is a
  	 * sane value.  If ihl points beyond the length of the buffer passed
  	 * in, reject the frame as invalid
  	 */
  	err = -EINVAL;
  	if (iphlen > length)
  		goto error_free;
  
  	if (iphlen >= sizeof(*iph)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  		if (!iph->saddr)
77968b782   David S. Miller   ipv4: Pass flow k...
390
  			iph->saddr = fl4->saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
393
  		iph->check   = 0;
  		iph->tot_len = htons(length);
  		if (!iph->id)
b6a7719ae   Hannes Frederic Sowa   ipv4: hash net pt...
394
  			ip_select_ident(net, skb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
  
  		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
027ac58e3   Ben Cartwright-Cox   raw: increment co...
397
398
399
400
401
  		skb->transport_header += iphlen;
  		if (iph->protocol == IPPROTO_ICMP &&
  		    length >= iphlen + sizeof(struct icmphdr))
  			icmp_out_count(net, ((struct icmphdr *)
  				skb_transport_header(skb))->type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  	}
29a26a568   Eric W. Biederman   netfilter: Pass s...
403
404
  	err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
  		      net, sk, skb, NULL, rt->dst.dev,
13206b6bf   Eric W. Biederman   net: Pass net int...
405
  		      dst_output);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  	if (err > 0)
6ce9e7b5f   Eric Dumazet   ip: Report qdisc ...
407
  		err = net_xmit_errno(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
410
411
  	if (err)
  		goto error;
  out:
  	return 0;
55888dfb6   Neil Horman   AF_RAW: Augment r...
412
  error_free:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
  	kfree_skb(skb);
  error:
5e38e2704   Pavel Emelyanov   mib: add net to I...
415
  	IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
6ce9e7b5f   Eric Dumazet   ip: Report qdisc ...
416
417
  	if (err == -ENOBUFS && !inet->recverr)
  		err = 0;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
418
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  }
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
420
  static int raw_probe_proto_opt(struct raw_frag_vec *rfv, struct flowi4 *fl4)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
  {
32b5913a9   Herbert Xu   ipv4: Use standar...
422
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423

32b5913a9   Herbert Xu   ipv4: Use standar...
424
  	if (fl4->flowi4_proto != IPPROTO_ICMP)
a27b58fed   Heiko Carstens   [NET]: fix uacces...
425
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426

32b5913a9   Herbert Xu   ipv4: Use standar...
427
  	/* We only need the first two bytes. */
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
428
  	rfv->hlen = 2;
b61e9dcc5   Al Viro   raw.c: stick msgh...
429
  	err = memcpy_from_msg(rfv->hdr.c, rfv->msg, rfv->hlen);
32b5913a9   Herbert Xu   ipv4: Use standar...
430
431
  	if (err)
  		return err;
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
432
433
  	fl4->fl4_icmp_type = rfv->hdr.icmph.type;
  	fl4->fl4_icmp_code = rfv->hdr.icmph.code;
32b5913a9   Herbert Xu   ipv4: Use standar...
434

a27b58fed   Heiko Carstens   [NET]: fix uacces...
435
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
  }
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  static int raw_getfrag(void *from, char *to, int offset, int len, int odd,
  		       struct sk_buff *skb)
  {
  	struct raw_frag_vec *rfv = from;
  
  	if (offset < rfv->hlen) {
  		int copy = min(rfv->hlen - offset, len);
  
  		if (skb->ip_summed == CHECKSUM_PARTIAL)
  			memcpy(to, rfv->hdr.c + offset, copy);
  		else
  			skb->csum = csum_block_add(
  				skb->csum,
  				csum_partial_copy_nocheck(rfv->hdr.c + offset,
  							  to, copy, 0),
  				odd);
  
  		odd = 0;
  		offset += copy;
  		to += copy;
  		len -= copy;
  
  		if (!len)
  			return 0;
  	}
  
  	offset -= rfv->hlen;
f69e6d131   Al Viro   ip_generic_getfra...
464
  	return ip_generic_getfrag(rfv->msg, to, offset, len, odd, skb);
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
465
  }
1b7841404   Ying Xue   net: Remove iocb ...
466
  static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
  {
  	struct inet_sock *inet = inet_sk(sk);
bb191c3e8   David Ahern   net: Add l3mdev s...
469
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
  	struct ipcm_cookie ipc;
  	struct rtable *rt = NULL;
77968b782   David S. Miller   ipv4: Pass flow k...
472
  	struct flowi4 fl4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  	int free = 0;
3ca3c68e7   Al Viro   [IPV4]: struct ip...
474
  	__be32 daddr;
c1d18f9fa   Al Viro   [IPV4]: struct ip...
475
  	__be32 saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
  	u8  tos;
  	int err;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
478
  	struct ip_options_data opt_copy;
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
479
  	struct raw_frag_vec rfv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
  
  	err = -EMSGSIZE;
926d4b812   Jesper Juhl   [IPV4]: [2/4] sig...
482
  	if (len > 0xFFFF)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
484
485
486
487
488
489
490
491
  		goto out;
  
  	/*
  	 *	Check the flags.
  	 */
  
  	err = -EOPNOTSUPP;
  	if (msg->msg_flags & MSG_OOB)	/* Mirror BSD error message */
  		goto out;               /* compatibility */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
492

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  	/*
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
494
  	 *	Get and verify the address.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
  	 */
  
  	if (msg->msg_namelen) {
342dfc306   Steffen Hurrle   net: add build-ti...
498
  		DECLARE_SOCKADDR(struct sockaddr_in *, usin, msg->msg_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
501
502
  		err = -EINVAL;
  		if (msg->msg_namelen < sizeof(*usin))
  			goto out;
  		if (usin->sin_family != AF_INET) {
058bd4d2a   Joe Perches   net: Convert prin...
503
504
505
  			pr_info_once("%s: %s forgot to set AF_INET. Fix it!
  ",
  				     __func__, current->comm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
509
510
511
512
513
514
515
516
  			err = -EAFNOSUPPORT;
  			if (usin->sin_family)
  				goto out;
  		}
  		daddr = usin->sin_addr.s_addr;
  		/* ANK: I did not forget to get protocol from port field.
  		 * I just do not know, who uses this weirdness.
  		 * IP_HDRINCL is much more convenient.
  		 */
  	} else {
  		err = -EDESTADDRREQ;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
517
  		if (sk->sk_state != TCP_ESTABLISHED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
  			goto out;
c720c7e83   Eric Dumazet   inet: rename some...
519
  		daddr = inet->inet_daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  	}
c14ac9451   Soheil Hassas Yeganeh   sock: enable time...
521
  	ipc.sockc.tsflags = sk->sk_tsflags;
c720c7e83   Eric Dumazet   inet: rename some...
522
  	ipc.addr = inet->inet_saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
  	ipc.opt = NULL;
2244d07bf   Oliver Hartkopp   net: simplify fla...
524
  	ipc.tx_flags = 0;
aa6615814   Francesco Fusco   ipv4: processing ...
525
526
  	ipc.ttl = 0;
  	ipc.tos = -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
  	ipc.oif = sk->sk_bound_dev_if;
  
  	if (msg->msg_controllen) {
24025c465   Soheil Hassas Yeganeh   ipv4: process soc...
530
  		err = ip_cmsg_send(sk, msg, &ipc, false);
919483096   Eric Dumazet   ipv4: fix memory ...
531
532
  		if (unlikely(err)) {
  			kfree(ipc.opt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
  			goto out;
919483096   Eric Dumazet   ipv4: fix memory ...
534
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
540
  		if (ipc.opt)
  			free = 1;
  	}
  
  	saddr = ipc.addr;
  	ipc.addr = daddr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
541
542
543
544
545
546
547
548
549
550
551
552
  	if (!ipc.opt) {
  		struct ip_options_rcu *inet_opt;
  
  		rcu_read_lock();
  		inet_opt = rcu_dereference(inet->inet_opt);
  		if (inet_opt) {
  			memcpy(&opt_copy, inet_opt,
  			       sizeof(*inet_opt) + inet_opt->opt.optlen);
  			ipc.opt = &opt_copy.opt;
  		}
  		rcu_read_unlock();
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
554
555
556
557
558
559
560
  
  	if (ipc.opt) {
  		err = -EINVAL;
  		/* Linux does not mangle headers on raw sockets,
  		 * so that IP options + IP_HDRINCL is non-sense.
  		 */
  		if (inet->hdrincl)
  			goto done;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
561
  		if (ipc.opt->opt.srr) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
  			if (!daddr)
  				goto done;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
564
  			daddr = ipc.opt->opt.faddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
566
  		}
  	}
aa6615814   Francesco Fusco   ipv4: processing ...
567
  	tos = get_rtconn_flags(&ipc, sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
  	if (msg->msg_flags & MSG_DONTROUTE)
  		tos |= RTO_ONLINK;
f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
570
  	if (ipv4_is_multicast(daddr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
573
574
  		if (!ipc.oif)
  			ipc.oif = inet->mc_index;
  		if (!saddr)
  			saddr = inet->mc_addr;
76e21053b   Erich E. Hoover   ipv4: Implement I...
575
576
  	} else if (!ipc.oif)
  		ipc.oif = inet->uc_index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577

77968b782   David S. Miller   ipv4: Pass flow k...
578
579
580
  	flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
  			   RT_SCOPE_UNIVERSE,
  			   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
0e0d44ab4   Steffen Klassert   net: Remove FLOWI...
581
  			   inet_sk_flowi_flags(sk) |
c27c9322d   Chris Clark   ipv4: sendto/hdri...
582
  			    (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
47670b767   Julian Anastasov   ipv4: route non-l...
583
  			   daddr, saddr, 0, 0);
ef164ae35   David S. Miller   ipv4: Use flowi4_...
584

77968b782   David S. Miller   ipv4: Pass flow k...
585
  	if (!inet->hdrincl) {
b61e9dcc5   Al Viro   raw.c: stick msgh...
586
  		rfv.msg = msg;
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
587
588
589
  		rfv.hlen = 0;
  
  		err = raw_probe_proto_opt(&rfv, &fl4);
77968b782   David S. Miller   ipv4: Pass flow k...
590
  		if (err)
b23dd4fe4   David S. Miller   ipv4: Make output...
591
  			goto done;
77968b782   David S. Miller   ipv4: Pass flow k...
592
593
594
  	}
  
  	security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
bb191c3e8   David Ahern   net: Add l3mdev s...
595
  	rt = ip_route_output_flow(net, &fl4, sk);
77968b782   David S. Miller   ipv4: Pass flow k...
596
597
598
599
  	if (IS_ERR(rt)) {
  		err = PTR_ERR(rt);
  		rt = NULL;
  		goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
602
603
604
605
606
607
608
609
610
  
  	err = -EACCES;
  	if (rt->rt_flags & RTCF_BROADCAST && !sock_flag(sk, SOCK_BROADCAST))
  		goto done;
  
  	if (msg->msg_flags & MSG_CONFIRM)
  		goto do_confirm;
  back_from_confirm:
  
  	if (inet->hdrincl)
7ae9abfd9   Al Viro   ipv4: raw_send_hd...
611
  		err = raw_send_hdrinc(sk, &fl4, msg, len,
c14ac9451   Soheil Hassas Yeganeh   sock: enable time...
612
  				      &rt, msg->msg_flags, &ipc.sockc);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
613

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
  	 else {
c14ac9451   Soheil Hassas Yeganeh   sock: enable time...
615
  		sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags);
11878b40e   Willem de Bruijn   net-timestamp: SO...
616

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
  		if (!ipc.addr)
77968b782   David S. Miller   ipv4: Pass flow k...
618
  			ipc.addr = fl4.daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  		lock_sock(sk);
c008ba5bd   Herbert Xu   ipv4: Avoid readi...
620
621
  		err = ip_append_data(sk, &fl4, raw_getfrag,
  				     &rfv, len, 0,
77968b782   David S. Miller   ipv4: Pass flow k...
622
  				     &ipc, &rt, msg->msg_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
624
  		if (err)
  			ip_flush_pending_frames(sk);
6ce9e7b5f   Eric Dumazet   ip: Report qdisc ...
625
  		else if (!(msg->msg_flags & MSG_MORE)) {
77968b782   David S. Miller   ipv4: Pass flow k...
626
  			err = ip_push_pending_frames(sk, &fl4);
6ce9e7b5f   Eric Dumazet   ip: Report qdisc ...
627
628
629
  			if (err == -ENOBUFS && !inet->recverr)
  				err = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
631
632
633
634
635
  		release_sock(sk);
  	}
  done:
  	if (free)
  		kfree(ipc.opt);
  	ip_rt_put(rt);
5418c6926   Jesper Juhl   [IPV4]: [1/4] sig...
636
637
638
639
  out:
  	if (err < 0)
  		return err;
  	return len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
641
  
  do_confirm:
d8d1f30b9   Changli Gao   net-next: remove ...
642
  	dst_confirm(&rt->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
645
646
647
648
649
650
  	if (!(msg->msg_flags & MSG_PROBE) || len)
  		goto back_from_confirm;
  	err = 0;
  	goto done;
  }
  
  static void raw_close(struct sock *sk, long timeout)
  {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
651
  	/*
25985edce   Lucas De Marchi   Fix common misspe...
652
  	 * Raw sockets may have direct kernel references. Kill them.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
656
657
  	 */
  	ip_ra_control(sk, 0, NULL);
  
  	sk_common_release(sk);
  }
7d06b2e05   Brian Haley   net: change proto...
658
  static void raw_destroy(struct sock *sk)
22dd48502   Denis V. Lunev   raw: Raw socket l...
659
660
661
662
  {
  	lock_sock(sk);
  	ip_flush_pending_frames(sk);
  	release_sock(sk);
22dd48502   Denis V. Lunev   raw: Raw socket l...
663
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
665
666
667
668
669
670
671
672
673
  /* This gets rid of all the nasties in af_inet. -DaveM */
  static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
  {
  	struct inet_sock *inet = inet_sk(sk);
  	struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
  	int ret = -EINVAL;
  	int chk_addr_ret;
  
  	if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
  		goto out;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
674
  	chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
677
678
  	ret = -EADDRNOTAVAIL;
  	if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
  	    chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
  		goto out;
c720c7e83   Eric Dumazet   inet: rename some...
679
  	inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
  	if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
c720c7e83   Eric Dumazet   inet: rename some...
681
  		inet->inet_saddr = 0;  /* Use device */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
685
686
687
688
689
690
  	sk_dst_reset(sk);
  	ret = 0;
  out:	return ret;
  }
  
  /*
   *	This should be easy, if there is something there
   *	we return it, otherwise we block.
   */
1b7841404   Ying Xue   net: Remove iocb ...
691
692
  static int raw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
  		       int noblock, int flags, int *addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
694
695
696
  {
  	struct inet_sock *inet = inet_sk(sk);
  	size_t copied = 0;
  	int err = -EOPNOTSUPP;
342dfc306   Steffen Hurrle   net: add build-ti...
697
  	DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
699
700
701
  	struct sk_buff *skb;
  
  	if (flags & MSG_OOB)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  	if (flags & MSG_ERRQUEUE) {
85fbaa750   Hannes Frederic Sowa   inet: fix addr_le...
703
  		err = ip_recv_error(sk, msg, len, addr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
706
707
708
709
710
711
712
713
714
715
  		goto out;
  	}
  
  	skb = skb_recv_datagram(sk, flags, noblock, &err);
  	if (!skb)
  		goto out;
  
  	copied = skb->len;
  	if (len < copied) {
  		msg->msg_flags |= MSG_TRUNC;
  		copied = len;
  	}
51f3d02b9   David S. Miller   net: Add and use ...
716
  	err = skb_copy_datagram_msg(skb, 0, msg, copied);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
  	if (err)
  		goto done;
3b885787e   Neil Horman   net: Generalize s...
719
  	sock_recv_ts_and_drops(msg, sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
722
723
  
  	/* Copy the address. */
  	if (sin) {
  		sin->sin_family = AF_INET;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
724
  		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
f59fc7f30   Tetsuo Handa   [IPV4/IPV6]: Sett...
725
  		sin->sin_port = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
  		memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
bceaa9024   Hannes Frederic Sowa   inet: prevent lea...
727
  		*addr_len = sizeof(*sin);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
730
731
732
733
734
  	}
  	if (inet->cmsg_flags)
  		ip_cmsg_recv(msg, skb);
  	if (flags & MSG_TRUNC)
  		copied = skb->len;
  done:
  	skb_free_datagram(sk, skb);
5418c6926   Jesper Juhl   [IPV4]: [1/4] sig...
735
736
737
738
  out:
  	if (err)
  		return err;
  	return copied;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
740
741
742
743
  }
  
  static int raw_init(struct sock *sk)
  {
  	struct raw_sock *rp = raw_sk(sk);
c720c7e83   Eric Dumazet   inet: rename some...
744
  	if (inet_sk(sk)->inet_num == IPPROTO_ICMP)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
746
747
748
749
750
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
  		memset(&rp->filter, 0, sizeof(rp->filter));
  	return 0;
  }
  
  static int raw_seticmpfilter(struct sock *sk, char __user *optval, int optlen)
  {
  	if (optlen > sizeof(struct icmp_filter))
  		optlen = sizeof(struct icmp_filter);
  	if (copy_from_user(&raw_sk(sk)->filter, optval, optlen))
  		return -EFAULT;
  	return 0;
  }
  
  static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *optlen)
  {
  	int len, ret = -EFAULT;
  
  	if (get_user(len, optlen))
  		goto out;
  	ret = -EINVAL;
  	if (len < 0)
  		goto out;
  	if (len > sizeof(struct icmp_filter))
  		len = sizeof(struct icmp_filter);
  	ret = -EFAULT;
  	if (put_user(len, optlen) ||
  	    copy_to_user(optval, &raw_sk(sk)->filter, len))
  		goto out;
  	ret = 0;
  out:	return ret;
  }
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
776
  static int do_raw_setsockopt(struct sock *sk, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
777
  			  char __user *optval, unsigned int optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
  	if (optname == ICMP_FILTER) {
c720c7e83   Eric Dumazet   inet: rename some...
780
  		if (inet_sk(sk)->inet_num != IPPROTO_ICMP)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
783
784
785
786
  			return -EOPNOTSUPP;
  		else
  			return raw_seticmpfilter(sk, optval, optlen);
  	}
  	return -ENOPROTOOPT;
  }
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
787
  static int raw_setsockopt(struct sock *sk, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
788
  			  char __user *optval, unsigned int optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
790
  {
  	if (level != SOL_RAW)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
791
792
793
  		return ip_setsockopt(sk, level, optname, optval, optlen);
  	return do_raw_setsockopt(sk, level, optname, optval, optlen);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794

3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
795
796
  #ifdef CONFIG_COMPAT
  static int compat_raw_setsockopt(struct sock *sk, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
797
  				 char __user *optval, unsigned int optlen)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
798
799
  {
  	if (level != SOL_RAW)
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
800
  		return compat_ip_setsockopt(sk, level, optname, optval, optlen);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
801
802
803
804
805
806
807
  	return do_raw_setsockopt(sk, level, optname, optval, optlen);
  }
  #endif
  
  static int do_raw_getsockopt(struct sock *sk, int level, int optname,
  			  char __user *optval, int __user *optlen)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  	if (optname == ICMP_FILTER) {
c720c7e83   Eric Dumazet   inet: rename some...
809
  		if (inet_sk(sk)->inet_num != IPPROTO_ICMP)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
811
812
813
814
815
  			return -EOPNOTSUPP;
  		else
  			return raw_geticmpfilter(sk, optval, optlen);
  	}
  	return -ENOPROTOOPT;
  }
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
816
817
818
819
820
821
822
823
824
825
  static int raw_getsockopt(struct sock *sk, int level, int optname,
  			  char __user *optval, int __user *optlen)
  {
  	if (level != SOL_RAW)
  		return ip_getsockopt(sk, level, optname, optval, optlen);
  	return do_raw_getsockopt(sk, level, optname, optval, optlen);
  }
  
  #ifdef CONFIG_COMPAT
  static int compat_raw_getsockopt(struct sock *sk, int level, int optname,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
826
  				 char __user *optval, int __user *optlen)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
827
828
  {
  	if (level != SOL_RAW)
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
829
  		return compat_ip_getsockopt(sk, level, optname, optval, optlen);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
830
831
832
  	return do_raw_getsockopt(sk, level, optname, optval, optlen);
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
834
835
  static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
  {
  	switch (cmd) {
4500ebf8d   Joe Perches   ipv4: Reduce swit...
836
837
  	case SIOCOUTQ: {
  		int amount = sk_wmem_alloc_get(sk);
31e6d363a   Eric Dumazet   net: correct off-...
838

4500ebf8d   Joe Perches   ipv4: Reduce swit...
839
840
841
842
843
844
845
846
  		return put_user(amount, (int __user *)arg);
  	}
  	case SIOCINQ: {
  		struct sk_buff *skb;
  		int amount = 0;
  
  		spin_lock_bh(&sk->sk_receive_queue.lock);
  		skb = skb_peek(&sk->sk_receive_queue);
00db41243   Ian Morris   ipv4: coding styl...
847
  		if (skb)
4500ebf8d   Joe Perches   ipv4: Reduce swit...
848
849
850
851
  			amount = skb->len;
  		spin_unlock_bh(&sk->sk_receive_queue.lock);
  		return put_user(amount, (int __user *)arg);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852

4500ebf8d   Joe Perches   ipv4: Reduce swit...
853
  	default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
  #ifdef CONFIG_IP_MROUTE
4500ebf8d   Joe Perches   ipv4: Reduce swit...
855
  		return ipmr_ioctl(sk, cmd, (void __user *)arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
  #else
4500ebf8d   Joe Perches   ipv4: Reduce swit...
857
  		return -ENOIOCTLCMD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
859
860
  #endif
  	}
  }
709b46e8d   Eric W. Biederman   net: Add compat i...
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
  #ifdef CONFIG_COMPAT
  static int compat_raw_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
  {
  	switch (cmd) {
  	case SIOCOUTQ:
  	case SIOCINQ:
  		return -ENOIOCTLCMD;
  	default:
  #ifdef CONFIG_IP_MROUTE
  		return ipmr_compat_ioctl(sk, cmd, compat_ptr(arg));
  #else
  		return -ENOIOCTLCMD;
  #endif
  	}
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
  struct proto raw_prot = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
878
879
880
  	.name		   = "RAW",
  	.owner		   = THIS_MODULE,
  	.close		   = raw_close,
22dd48502   Denis V. Lunev   raw: Raw socket l...
881
  	.destroy	   = raw_destroy,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
882
  	.connect	   = ip4_datagram_connect,
286c72dea   Eric Dumazet   udp: must lock th...
883
  	.disconnect	   = __udp_disconnect,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
884
885
886
887
888
889
890
891
  	.ioctl		   = raw_ioctl,
  	.init		   = raw_init,
  	.setsockopt	   = raw_setsockopt,
  	.getsockopt	   = raw_getsockopt,
  	.sendmsg	   = raw_sendmsg,
  	.recvmsg	   = raw_recvmsg,
  	.bind		   = raw_bind,
  	.backlog_rcv	   = raw_rcv_skb,
8141ed9fc   Steffen Klassert   ipv4: Add a socke...
892
  	.release_cb	   = ip4_datagram_release_cb,
fc8717baa   Pavel Emelyanov   [RAW]: Add raw_ha...
893
894
  	.hash		   = raw_hash_sk,
  	.unhash		   = raw_unhash_sk,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
895
  	.obj_size	   = sizeof(struct raw_sock),
fc8717baa   Pavel Emelyanov   [RAW]: Add raw_ha...
896
  	.h.raw_hash	   = &raw_v4_hashinfo,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
897
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
898
899
  	.compat_setsockopt = compat_raw_setsockopt,
  	.compat_getsockopt = compat_raw_getsockopt,
709b46e8d   Eric W. Biederman   net: Add compat i...
900
  	.compat_ioctl	   = compat_raw_ioctl,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
901
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
903
904
  };
  
  #ifdef CONFIG_PROC_FS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
906
907
  static struct sock *raw_get_first(struct seq_file *seq)
  {
  	struct sock *sk;
5a5f3a8db   Jianjun Kong   net: clean up net...
908
  	struct raw_iter_state *state = raw_seq_private(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909

b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
910
911
  	for (state->bucket = 0; state->bucket < RAW_HTABLE_SIZE;
  			++state->bucket) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
912
  		sk_for_each(sk, &state->h->ht[state->bucket])
1218854af   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
913
  			if (sock_net(sk) == seq_file_net(seq))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
916
917
918
919
920
921
922
  				goto found;
  	}
  	sk = NULL;
  found:
  	return sk;
  }
  
  static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk)
  {
5a5f3a8db   Jianjun Kong   net: clean up net...
923
  	struct raw_iter_state *state = raw_seq_private(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
925
926
927
928
  
  	do {
  		sk = sk_next(sk);
  try_again:
  		;
1218854af   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
929
  	} while (sk && sock_net(sk) != seq_file_net(seq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930

b673e4dfc   Pavel Emelyanov   [RAW]: Introduce ...
931
  	if (!sk && ++state->bucket < RAW_HTABLE_SIZE) {
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
932
  		sk = sk_head(&state->h->ht[state->bucket]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
933
934
935
936
937
938
939
940
941
942
943
944
945
946
  		goto try_again;
  	}
  	return sk;
  }
  
  static struct sock *raw_get_idx(struct seq_file *seq, loff_t pos)
  {
  	struct sock *sk = raw_get_first(seq);
  
  	if (sk)
  		while (pos && (sk = raw_get_next(seq, sk)) != NULL)
  			--pos;
  	return pos ? NULL : sk;
  }
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
947
  void *raw_seq_start(struct seq_file *seq, loff_t *pos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948
  {
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
949
950
951
  	struct raw_iter_state *state = raw_seq_private(seq);
  
  	read_lock(&state->h->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
  	return *pos ? raw_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
  }
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
954
  EXPORT_SYMBOL_GPL(raw_seq_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955

42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
956
  void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
958
959
960
961
962
963
964
965
966
  {
  	struct sock *sk;
  
  	if (v == SEQ_START_TOKEN)
  		sk = raw_get_first(seq);
  	else
  		sk = raw_get_next(seq, v);
  	++*pos;
  	return sk;
  }
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
967
  EXPORT_SYMBOL_GPL(raw_seq_next);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968

42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
969
  void raw_seq_stop(struct seq_file *seq, void *v)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
  {
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
971
972
973
  	struct raw_iter_state *state = raw_seq_private(seq);
  
  	read_unlock(&state->h->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974
  }
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
975
  EXPORT_SYMBOL_GPL(raw_seq_stop);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976

8cd850efa   Denis V. Lunev   [RAW]: Cleanup IP...
977
  static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
979
  {
  	struct inet_sock *inet = inet_sk(sp);
c720c7e83   Eric Dumazet   inet: rename some...
980
981
  	__be32 dest = inet->inet_daddr,
  	       src = inet->inet_rcv_saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
  	__u16 destp = 0,
c720c7e83   Eric Dumazet   inet: rename some...
983
  	      srcp  = inet->inet_num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984

8cd850efa   Denis V. Lunev   [RAW]: Cleanup IP...
985
  	seq_printf(seq, "%4d: %08X:%04X %08X:%04X"
d14c5ab6b   Francesco Fusco   net: proc_fs: tri...
986
987
  		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d
  ",
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
988
  		i, src, srcp, dest, destp, sp->sk_state,
31e6d363a   Eric Dumazet   net: correct off-...
989
990
  		sk_wmem_alloc_get(sp),
  		sk_rmem_alloc_get(sp),
a7cb5a49b   Eric W. Biederman   userns: Print out...
991
992
993
  		0, 0L, 0,
  		from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
  		0, sock_i_ino(sp),
33c732c36   Wang Chen   [IPV4]: Add raw d...
994
  		atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
996
997
998
  }
  
  static int raw_seq_show(struct seq_file *seq, void *v)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
999
  	if (v == SEQ_START_TOKEN)
8cd850efa   Denis V. Lunev   [RAW]: Cleanup IP...
1000
1001
  		seq_printf(seq, "  sl  local_address rem_address   st tx_queue "
  				"rx_queue tr tm->when retrnsmt   uid  timeout "
cb61cb9b8   Eric Dumazet   udp: sk_drops han...
1002
1003
  				"inode ref pointer drops
  ");
8cd850efa   Denis V. Lunev   [RAW]: Cleanup IP...
1004
1005
  	else
  		raw_sock_seq_show(seq, v, raw_seq_private(seq)->bucket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
1007
  	return 0;
  }
f690808e1   Stephen Hemminger   [NET]: make seq_o...
1008
  static const struct seq_operations raw_seq_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1009
1010
1011
1012
1013
  	.start = raw_seq_start,
  	.next  = raw_seq_next,
  	.stop  = raw_seq_stop,
  	.show  = raw_seq_show,
  };
3046d7674   Denis V. Lunev   [RAW]: Wrong cont...
1014
1015
  int raw_seq_open(struct inode *ino, struct file *file,
  		 struct raw_hashinfo *h, const struct seq_operations *ops)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1016
  {
f51d599fb   Pavel Emelyanov   [NETNS][RAW]: Mak...
1017
  	int err;
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
1018
  	struct raw_iter_state *i;
3046d7674   Denis V. Lunev   [RAW]: Wrong cont...
1019
  	err = seq_open_net(ino, file, ops, sizeof(struct raw_iter_state));
f51d599fb   Pavel Emelyanov   [NETNS][RAW]: Mak...
1020
1021
  	if (err < 0)
  		return err;
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
1022

f51d599fb   Pavel Emelyanov   [NETNS][RAW]: Mak...
1023
  	i = raw_seq_private((struct seq_file *)file->private_data);
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
1024
  	i->h = h;
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
1025
1026
1027
1028
1029
1030
  	return 0;
  }
  EXPORT_SYMBOL_GPL(raw_seq_open);
  
  static int raw_v4_seq_open(struct inode *inode, struct file *file)
  {
3046d7674   Denis V. Lunev   [RAW]: Wrong cont...
1031
  	return raw_seq_open(inode, file, &raw_v4_hashinfo, &raw_seq_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
  }
9a32144e9   Arjan van de Ven   [PATCH] mark stru...
1033
  static const struct file_operations raw_seq_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
  	.owner	 = THIS_MODULE,
42a73808e   Pavel Emelyanov   [RAW]: Consolidat...
1035
  	.open	 = raw_v4_seq_open,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
  	.read	 = seq_read,
  	.llseek	 = seq_lseek,
f51d599fb   Pavel Emelyanov   [NETNS][RAW]: Mak...
1038
  	.release = seq_release_net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
  };
a308da162   Pavel Emelyanov   [NETNS][RAW]: Cre...
1040
  static __net_init int raw_init_net(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1041
  {
d4beaa66a   Gao feng   net: proc: change...
1042
  	if (!proc_create("raw", S_IRUGO, net->proc_net, &raw_seq_fops))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
  		return -ENOMEM;
a308da162   Pavel Emelyanov   [NETNS][RAW]: Cre...
1044

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
1046
  	return 0;
  }
a308da162   Pavel Emelyanov   [NETNS][RAW]: Cre...
1047
1048
  static __net_exit void raw_exit_net(struct net *net)
  {
ece31ffd5   Gao feng   net: proc: change...
1049
  	remove_proc_entry("raw", net->proc_net);
a308da162   Pavel Emelyanov   [NETNS][RAW]: Cre...
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
  }
  
  static __net_initdata struct pernet_operations raw_net_ops = {
  	.init = raw_init_net,
  	.exit = raw_exit_net,
  };
  
  int __init raw_proc_init(void)
  {
  	return register_pernet_subsys(&raw_net_ops);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
1062
  void __init raw_proc_exit(void)
  {
a308da162   Pavel Emelyanov   [NETNS][RAW]: Cre...
1063
  	unregister_pernet_subsys(&raw_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
1065
  }
  #endif /* CONFIG_PROC_FS */