Blame view

net/ipv6/ipv6_sockglue.c 27.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   *	IPv6 BSD socket options interface
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
3
   *	Linux INET6 implementation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
   *
   *	Authors:
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
6
   *	Pedro Roque		<roque@di.fc.ul.pt>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
   *
   *	Based on linux/net/ipv4/ip_sockglue.c
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
15
16
   *	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.
   *
   *	FIXME: Make the setsockopt code POSIX compliant: That is
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
22
23
24
25
   *	o	Truncate getsockopt returns
   *	o	Return an optlen of the truncated length if need be
   *
   *	Changes:
   *	David L Stevens <dlstevens@us.ibm.com>:
   *		- added multicast source filtering API for MLDv2
   */
  
  #include <linux/module.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
26
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/sockios.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
  #include <linux/net.h>
  #include <linux/in6.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
33
  #include <linux/mroute6.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
  #include <linux/netdevice.h>
  #include <linux/if_arp.h>
  #include <linux/init.h>
  #include <linux/sysctl.h>
  #include <linux/netfilter.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
39
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
47
48
49
50
51
  
  #include <net/sock.h>
  #include <net/snmp.h>
  #include <net/ipv6.h>
  #include <net/ndisc.h>
  #include <net/protocol.h>
  #include <net/transp_v6.h>
  #include <net/ip6_route.h>
  #include <net/addrconf.h>
  #include <net/inet_common.h>
  #include <net/tcp.h>
  #include <net/udp.h>
ba4e58eca   Gerrit Renker   [NET]: Supporting...
52
  #include <net/udplite.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  #include <net/xfrm.h>
dae502954   David L Stevens   ipv4/ipv6 compat:...
54
  #include <net/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
  
  #include <asm/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
  struct ip6_ra_chain *ip6_ra_chain;
  DEFINE_RWLOCK(ip6_ra_lock);
725a8ff04   Denis V. Lunev   ipv6: remove unus...
59
  int ip6_ra_control(struct sock *sk, int sel)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
  {
  	struct ip6_ra_chain *ra, *new_ra, **rap;
  
  	/* RA packet may be delivered ONLY to IPPROTO_RAW socket */
c720c7e83   Eric Dumazet   inet: rename some...
64
  	if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num != IPPROTO_RAW)
1717699cd   YOSHIFUJI Hideaki   ipv6: Fail with a...
65
  		return -ENOPROTOOPT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
71
72
73
  
  	new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
  
  	write_lock_bh(&ip6_ra_lock);
  	for (rap = &ip6_ra_chain; (ra=*rap) != NULL; rap = &ra->next) {
  		if (ra->sk == sk) {
  			if (sel>=0) {
  				write_unlock_bh(&ip6_ra_lock);
a51482bde   Jesper Juhl   [NET]: kfree cleanup
74
  				kfree(new_ra);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
  				return -EADDRINUSE;
  			}
  
  			*rap = ra->next;
  			write_unlock_bh(&ip6_ra_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
83
84
85
86
87
88
89
90
  			sock_put(sk);
  			kfree(ra);
  			return 0;
  		}
  	}
  	if (new_ra == NULL) {
  		write_unlock_bh(&ip6_ra_lock);
  		return -ENOBUFS;
  	}
  	new_ra->sk = sk;
  	new_ra->sel = sel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
96
  	new_ra->next = ra;
  	*rap = new_ra;
  	sock_hold(sk);
  	write_unlock_bh(&ip6_ra_lock);
  	return 0;
  }
e7712f1a7   YOSHIFUJI Hideaki   [IPV6]: Share com...
97
98
99
100
101
102
103
  static
  struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
  					   struct ipv6_txoptions *opt)
  {
  	if (inet_sk(sk)->is_icsk) {
  		if (opt &&
  		    !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
c720c7e83   Eric Dumazet   inet: rename some...
104
  		    inet_sk(sk)->inet_daddr != LOOPBACK4_IPV6) {
e7712f1a7   YOSHIFUJI Hideaki   [IPV6]: Share com...
105
106
107
108
109
110
  			struct inet_connection_sock *icsk = inet_csk(sk);
  			icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen;
  			icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
  		}
  		opt = xchg(&inet6_sk(sk)->opt, opt);
  	} else {
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
111
  		spin_lock(&sk->sk_dst_lock);
e7712f1a7   YOSHIFUJI Hideaki   [IPV6]: Share com...
112
  		opt = xchg(&inet6_sk(sk)->opt, opt);
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
113
  		spin_unlock(&sk->sk_dst_lock);
e7712f1a7   YOSHIFUJI Hideaki   [IPV6]: Share com...
114
115
116
117
118
  	}
  	sk_dst_reset(sk);
  
  	return opt;
  }
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
119
  static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
120
  		    char __user *optval, unsigned int optlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
  {
  	struct ipv6_pinfo *np = inet6_sk(sk);
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
123
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
  	int val, valbool;
  	int retv = -ENOPROTOOPT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
  	if (optval == NULL)
  		val=0;
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
128
129
130
131
132
133
134
  	else {
  		if (optlen >= sizeof(int)) {
  			if (get_user(val, (int __user *) optval))
  				return -EFAULT;
  		} else
  			val = 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
  
  	valbool = (val!=0);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
137
138
  	if (ip6_mroute_opt(optname))
  		return ip6_mroute_setsockopt(sk, optname, optval, optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
  	lock_sock(sk);
  
  	switch (optname) {
  
  	case IPV6_ADDRFORM:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
144
145
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
  		if (val == PF_INET) {
  			struct ipv6_txoptions *opt;
  			struct sk_buff *pktopt;
49d074f40   Denis V. Lunev   [IPV6]: Do not ch...
149
150
  			if (sk->sk_type == SOCK_RAW)
  				break;
9596cc826   Denis V. Lunev   [IPV6]: Do not ch...
151
152
153
154
155
156
157
158
  			if (sk->sk_protocol == IPPROTO_UDP ||
  			    sk->sk_protocol == IPPROTO_UDPLITE) {
  				struct udp_sock *up = udp_sk(sk);
  				if (up->pending == AF_INET6) {
  					retv = -EBUSY;
  					break;
  				}
  			} else if (sk->sk_protocol != IPPROTO_TCP)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
162
163
164
165
166
  				break;
  
  			if (sk->sk_state != TCP_ESTABLISHED) {
  				retv = -ENOTCONN;
  				break;
  			}
  
  			if (ipv6_only_sock(sk) ||
e773e4faa   Brian Haley   [IPV6]: Add v4map...
167
  			    !ipv6_addr_v4mapped(&np->daddr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
  				retv = -EADDRNOTAVAIL;
  				break;
  			}
  
  			fl6_free_socklist(sk);
  			ipv6_sock_mc_close(sk);
e6848976b   Arnaldo Carvalho de Melo   [NET]: Cleanup IN...
174
175
176
177
178
179
  			/*
  			 * Sock is moving from IPv6 to IPv4 (sk_prot), so
  			 * remove it from the refcnt debug socks count in the
  			 * original family...
  			 */
  			sk_refcnt_debug_dec(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  			if (sk->sk_protocol == IPPROTO_TCP) {
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
181
  				struct inet_connection_sock *icsk = inet_csk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  				local_bh_disable();
c29a0bc4d   Pavel Emelyanov   [SOCK][NETNS]: Ad...
183
184
  				sock_prot_inuse_add(net, sk->sk_prot, -1);
  				sock_prot_inuse_add(net, &tcp_prot, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
  				local_bh_enable();
  				sk->sk_prot = &tcp_prot;
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
187
  				icsk->icsk_af_ops = &ipv4_specific;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
  				sk->sk_socket->ops = &inet_stream_ops;
  				sk->sk_family = PF_INET;
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
190
  				tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  			} else {
ba4e58eca   Gerrit Renker   [NET]: Supporting...
192
  				struct proto *prot = &udp_prot;
db8dac20d   David S. Miller   [UDP]: Revert udp...
193
  				if (sk->sk_protocol == IPPROTO_UDPLITE)
ba4e58eca   Gerrit Renker   [NET]: Supporting...
194
  					prot = &udplite_prot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  				local_bh_disable();
c29a0bc4d   Pavel Emelyanov   [SOCK][NETNS]: Ad...
196
197
  				sock_prot_inuse_add(net, sk->sk_prot, -1);
  				sock_prot_inuse_add(net, prot, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  				local_bh_enable();
ba4e58eca   Gerrit Renker   [NET]: Supporting...
199
  				sk->sk_prot = prot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
202
203
204
205
206
  				sk->sk_socket->ops = &inet_dgram_ops;
  				sk->sk_family = PF_INET;
  			}
  			opt = xchg(&np->opt, NULL);
  			if (opt)
  				sock_kfree_s(sk, opt, opt->tot_len);
  			pktopt = xchg(&np->pktoptions, NULL);
800d55f14   Wei Yongjun   ipv6: Remove some...
207
  			kfree_skb(pktopt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
  
  			sk->sk_destruct = inet_sock_destruct;
e6848976b   Arnaldo Carvalho de Melo   [NET]: Cleanup IN...
210
211
212
213
214
  			/*
  			 * ... and add it to the refcnt debug socks count
  			 * in the new family. -acme
  			 */
  			sk_refcnt_debug_inc(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
218
219
220
221
  			module_put(THIS_MODULE);
  			retv = 0;
  			break;
  		}
  		goto e_inval;
  
  	case IPV6_V6ONLY:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
222
  		if (optlen < sizeof(int) ||
c720c7e83   Eric Dumazet   inet: rename some...
223
  		    inet_sk(sk)->inet_num)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
  			goto e_inval;
  		np->ipv6only = valbool;
  		retv = 0;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
228
  	case IPV6_RECVPKTINFO:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
229
230
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
  		np->rxopt.bits.rxinfo = valbool;
  		retv = 0;
  		break;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
234

333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
235
  	case IPV6_2292PKTINFO:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
236
237
  		if (optlen < sizeof(int))
  			goto e_inval;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
238
239
240
  		np->rxopt.bits.rxoinfo = valbool;
  		retv = 0;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241

333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
242
  	case IPV6_RECVHOPLIMIT:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
243
244
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
  		np->rxopt.bits.rxhlim = valbool;
  		retv = 0;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
248
  	case IPV6_2292HOPLIMIT:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
249
250
  		if (optlen < sizeof(int))
  			goto e_inval;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
251
252
253
254
255
  		np->rxopt.bits.rxohlim = valbool;
  		retv = 0;
  		break;
  
  	case IPV6_RECVRTHDR:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
256
257
  		if (optlen < sizeof(int))
  			goto e_inval;
4c752098f   YOSHIFUJI Hideaki   [IPV6]: Make IPV6...
258
  		np->rxopt.bits.srcrt = valbool;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
  		retv = 0;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
261
  	case IPV6_2292RTHDR:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
262
263
  		if (optlen < sizeof(int))
  			goto e_inval;
4c752098f   YOSHIFUJI Hideaki   [IPV6]: Make IPV6...
264
  		np->rxopt.bits.osrcrt = valbool;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
265
266
267
268
  		retv = 0;
  		break;
  
  	case IPV6_RECVHOPOPTS:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
269
270
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
  		np->rxopt.bits.hopopts = valbool;
  		retv = 0;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
274
  	case IPV6_2292HOPOPTS:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
275
276
  		if (optlen < sizeof(int))
  			goto e_inval;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
277
278
279
280
281
  		np->rxopt.bits.ohopopts = valbool;
  		retv = 0;
  		break;
  
  	case IPV6_RECVDSTOPTS:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
282
283
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
286
  		np->rxopt.bits.dstopts = valbool;
  		retv = 0;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
287
  	case IPV6_2292DSTOPTS:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
288
289
  		if (optlen < sizeof(int))
  			goto e_inval;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
290
291
292
  		np->rxopt.bits.odstopts = valbool;
  		retv = 0;
  		break;
41a1f8ea4   YOSHIFUJI Hideaki   [IPV6]: Support I...
293
  	case IPV6_TCLASS:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
294
295
  		if (optlen < sizeof(int))
  			goto e_inval;
d0ee011f7   Rémi Denis-Courmont   [IPV6]: Accept -1...
296
  		if (val < -1 || val > 0xff)
41a1f8ea4   YOSHIFUJI Hideaki   [IPV6]: Support I...
297
  			goto e_inval;
26ced1e4a   Gerrit Renker   inet6: Set defaul...
298
299
300
  		/* RFC 3542, 6.5: default traffic class of 0x0 */
  		if (val == -1)
  			val = 0;
41a1f8ea4   YOSHIFUJI Hideaki   [IPV6]: Support I...
301
302
303
  		np->tclass = val;
  		retv = 0;
  		break;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
304

41a1f8ea4   YOSHIFUJI Hideaki   [IPV6]: Support I...
305
  	case IPV6_RECVTCLASS:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
306
307
  		if (optlen < sizeof(int))
  			goto e_inval;
41a1f8ea4   YOSHIFUJI Hideaki   [IPV6]: Support I...
308
309
310
  		np->rxopt.bits.rxtclass = valbool;
  		retv = 0;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  	case IPV6_FLOWINFO:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
312
313
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
  		np->rxopt.bits.rxflow = valbool;
  		retv = 0;
  		break;
793b14731   Brian Haley   IPv6: data struct...
317
318
319
320
321
322
  	case IPV6_RECVPATHMTU:
  		if (optlen < sizeof(int))
  			goto e_inval;
  		np->rxopt.bits.rxpmtu = valbool;
  		retv = 0;
  		break;
6c4686228   Balazs Scheidler   tproxy: added tpr...
323
  	case IPV6_TRANSPARENT:
6cc7a765c   Maciej Å»enczykowski   net: allow CAP_NE...
324
  		if (valbool && !capable(CAP_NET_ADMIN) && !capable(CAP_NET_RAW)) {
b889416b5   Balazs Scheidler   tproxy: Add missi...
325
326
327
  			retv = -EPERM;
  			break;
  		}
6c4686228   Balazs Scheidler   tproxy: added tpr...
328
329
330
331
332
333
334
335
336
337
338
339
340
  		if (optlen < sizeof(int))
  			goto e_inval;
  		/* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
  		inet_sk(sk)->transparent = valbool;
  		retv = 0;
  		break;
  
  	case IPV6_RECVORIGDSTADDR:
  		if (optlen < sizeof(int))
  			goto e_inval;
  		np->rxopt.bits.rxorigdstaddr = valbool;
  		retv = 0;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
341
342
343
344
345
346
  	case IPV6_HOPOPTS:
  	case IPV6_RTHDRDSTOPTS:
  	case IPV6_RTHDR:
  	case IPV6_DSTOPTS:
  	{
  		struct ipv6_txoptions *opt;
aea7427f7   Shan Wei   ipv6: Remove opti...
347
348
349
350
  
  		/* remove any sticky options header with a zero option
  		 * length, per RFC3542.
  		 */
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
351
  		if (optlen == 0)
cb422c464   Luiz Capitulino   [IPV6]: Fixes spa...
352
  			optval = NULL;
cfb266c0e   Yang Hongyang   ipv6: Fix the ret...
353
354
  		else if (optval == NULL)
  			goto e_inval;
aea7427f7   Shan Wei   ipv6: Remove opti...
355
356
357
  		else if (optlen < sizeof(struct ipv6_opt_hdr) ||
  			 optlen & 0x7 || optlen > 8 * 255)
  			goto e_inval;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
358
359
360
361
362
  
  		/* hop-by-hop / destination options are privileged option */
  		retv = -EPERM;
  		if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
  			break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
363
364
365
366
367
368
369
370
371
  		opt = ipv6_renew_options(sk, np->opt, optname,
  					 (struct ipv6_opt_hdr __user *)optval,
  					 optlen);
  		if (IS_ERR(opt)) {
  			retv = PTR_ERR(opt);
  			break;
  		}
  
  		/* routing header option needs extra check */
6e093d9df   Brian Haley   ipv6: routing hea...
372
  		retv = -EINVAL;
dfee0a725   Olaf Kirch   [IPV6]: Fix for i...
373
  		if (optname == IPV6_RTHDR && opt && opt->srcrt) {
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
374
  			struct ipv6_rt_hdr *rthdr = opt->srcrt;
280a9d340   Masahide NAKAMURA   [IPV6] MIP6: Add ...
375
  			switch (rthdr->type) {
59fbb3a61   Masahide NAKAMURA   [IPV6] MIP6: Load...
376
  #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
280a9d340   Masahide NAKAMURA   [IPV6] MIP6: Add ...
377
  			case IPV6_SRCRT_TYPE_2:
6e093d9df   Brian Haley   ipv6: routing hea...
378
379
380
  				if (rthdr->hdrlen != 2 ||
  				    rthdr->segments_left != 1)
  					goto sticky_done;
280a9d340   Masahide NAKAMURA   [IPV6] MIP6: Add ...
381
  				break;
bb4dbf9e6   YOSHIFUJI Hideaki   [IPV6]: Do not se...
382
  #endif
280a9d340   Masahide NAKAMURA   [IPV6] MIP6: Add ...
383
  			default:
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
384
  				goto sticky_done;
280a9d340   Masahide NAKAMURA   [IPV6] MIP6: Add ...
385
  			}
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
386
387
388
  		}
  
  		retv = 0;
e7712f1a7   YOSHIFUJI Hideaki   [IPV6]: Share com...
389
  		opt = ipv6_update_options(sk, opt);
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
390
391
392
393
394
  sticky_done:
  		if (opt)
  			sock_kfree_s(sk, opt, opt->tot_len);
  		break;
  	}
b24a2516d   Yang Hongyang   ipv6: Add IPV6_PK...
395
396
397
398
399
400
401
402
  	case IPV6_PKTINFO:
  	{
  		struct in6_pktinfo pkt;
  
  		if (optlen == 0)
  			goto e_inval;
  		else if (optlen < sizeof(struct in6_pktinfo) || optval == NULL)
  			goto e_inval;
914d11647   Ilpo Järvinen   ipv6: IPV6_PKTINF...
403
  		if (copy_from_user(&pkt, optval, sizeof(struct in6_pktinfo))) {
b24a2516d   Yang Hongyang   ipv6: Add IPV6_PK...
404
405
406
407
408
409
410
  				retv = -EFAULT;
  				break;
  		}
  		if (sk->sk_bound_dev_if && pkt.ipi6_ifindex != sk->sk_bound_dev_if)
  			goto e_inval;
  
  		np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
411
  		np->sticky_pktinfo.ipi6_addr = pkt.ipi6_addr;
b24a2516d   Yang Hongyang   ipv6: Add IPV6_PK...
412
413
414
  		retv = 0;
  		break;
  	}
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
415
  	case IPV6_2292PKTOPTIONS:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
418
  	{
  		struct ipv6_txoptions *opt = NULL;
  		struct msghdr msg;
4c9483b2f   David S. Miller   ipv6: Convert to ...
419
  		struct flowi6 fl6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
  		int junk;
4c9483b2f   David S. Miller   ipv6: Convert to ...
421
422
423
  		memset(&fl6, 0, sizeof(fl6));
  		fl6.flowi6_oif = sk->sk_bound_dev_if;
  		fl6.flowi6_mark = sk->sk_mark;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
  
  		if (optlen == 0)
  			goto update;
  
  		/* 1K is probably excessive
  		 * 1K is surely not enough, 2K per standard header is 16K.
  		 */
  		retv = -EINVAL;
  		if (optlen > 64*1024)
  			break;
  
  		opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL);
  		retv = -ENOBUFS;
  		if (opt == NULL)
  			break;
  
  		memset(opt, 0, sizeof(*opt));
  		opt->tot_len = sizeof(*opt) + optlen;
  		retv = -EFAULT;
  		if (copy_from_user(opt+1, optval, optlen))
  			goto done;
  
  		msg.msg_controllen = optlen;
  		msg.msg_control = (void*)(opt+1);
ec0506dbe   Maciej Å»enczykowski   net: relax PKTINF...
448
  		retv = datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, &junk,
13b52cd44   Brian Haley   IPv6: Add dontfra...
449
  					 &junk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
452
453
  		if (retv)
  			goto done;
  update:
  		retv = 0;
e7712f1a7   YOSHIFUJI Hideaki   [IPV6]: Share com...
454
  		opt = ipv6_update_options(sk, opt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
457
458
459
460
  done:
  		if (opt)
  			sock_kfree_s(sk, opt, opt->tot_len);
  		break;
  	}
  	case IPV6_UNICAST_HOPS:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
461
462
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
466
467
468
469
470
  		if (val > 255 || val < -1)
  			goto e_inval;
  		np->hop_limit = val;
  		retv = 0;
  		break;
  
  	case IPV6_MULTICAST_HOPS:
  		if (sk->sk_type == SOCK_STREAM)
1717699cd   YOSHIFUJI Hideaki   ipv6: Fail with a...
471
  			break;
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
472
473
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
  		if (val > 255 || val < -1)
  			goto e_inval;
2a38e6d5a   Li Wei   ipv6: Set mcast_h...
476
  		np->mcast_hops = (val == -1 ? IPV6_DEFAULT_MCASTHOPS : val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
479
480
  		retv = 0;
  		break;
  
  	case IPV6_MULTICAST_LOOP:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
481
482
  		if (optlen < sizeof(int))
  			goto e_inval;
28d448821   YOSHIFUJI Hideaki   ipv6: Check IPV6_...
483
484
  		if (val != valbool)
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
487
488
489
490
  		np->mc_loop = valbool;
  		retv = 0;
  		break;
  
  	case IPV6_MULTICAST_IF:
  		if (sk->sk_type == SOCK_STREAM)
1717699cd   YOSHIFUJI Hideaki   ipv6: Fail with a...
491
  			break;
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
492
493
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494

4953f0fcc   Brian Haley   [IPv6]: Update se...
495
  		if (val) {
55b805035   Eric Dumazet   net: Fix IP_MULTI...
496
  			struct net_device *dev;
4953f0fcc   Brian Haley   [IPv6]: Update se...
497
498
  			if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val)
  				goto e_inval;
55b805035   Eric Dumazet   net: Fix IP_MULTI...
499
500
  			dev = dev_get_by_index(net, val);
  			if (!dev) {
4953f0fcc   Brian Haley   [IPv6]: Update se...
501
502
503
  				retv = -ENODEV;
  				break;
  			}
55b805035   Eric Dumazet   net: Fix IP_MULTI...
504
  			dev_put(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
506
507
508
509
510
511
512
  		}
  		np->mcast_oif = val;
  		retv = 0;
  		break;
  	case IPV6_ADD_MEMBERSHIP:
  	case IPV6_DROP_MEMBERSHIP:
  	{
  		struct ipv6_mreq mreq;
a28398ba6   Wang Chen   [IPV6]: Check len...
513
514
  		if (optlen < sizeof(struct ipv6_mreq))
  			goto e_inval;
a96fb49be   Flavio Leitner   [NET]: Fix IP_ADD...
515
516
517
  		retv = -EPROTO;
  		if (inet_sk(sk)->is_icsk)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
521
522
523
524
525
526
527
528
529
530
531
  		retv = -EFAULT;
  		if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
  			break;
  
  		if (optname == IPV6_ADD_MEMBERSHIP)
  			retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
  		else
  			retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
  		break;
  	}
  	case IPV6_JOIN_ANYCAST:
  	case IPV6_LEAVE_ANYCAST:
  	{
  		struct ipv6_mreq mreq;
a28398ba6   Wang Chen   [IPV6]: Check len...
532
  		if (optlen < sizeof(struct ipv6_mreq))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
  			goto e_inval;
  
  		retv = -EFAULT;
  		if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
  			break;
  
  		if (optname == IPV6_JOIN_ANYCAST)
  			retv = ipv6_sock_ac_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr);
  		else
  			retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr);
  		break;
  	}
  	case MCAST_JOIN_GROUP:
  	case MCAST_LEAVE_GROUP:
  	{
  		struct group_req greq;
  		struct sockaddr_in6 *psin6;
a28398ba6   Wang Chen   [IPV6]: Check len...
550
551
  		if (optlen < sizeof(struct group_req))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  		retv = -EFAULT;
  		if (copy_from_user(&greq, optval, sizeof(struct group_req)))
  			break;
  		if (greq.gr_group.ss_family != AF_INET6) {
  			retv = -EADDRNOTAVAIL;
  			break;
  		}
  		psin6 = (struct sockaddr_in6 *)&greq.gr_group;
  		if (optname == MCAST_JOIN_GROUP)
  			retv = ipv6_sock_mc_join(sk, greq.gr_interface,
  				&psin6->sin6_addr);
  		else
  			retv = ipv6_sock_mc_drop(sk, greq.gr_interface,
  				&psin6->sin6_addr);
  		break;
  	}
  	case MCAST_JOIN_SOURCE_GROUP:
  	case MCAST_LEAVE_SOURCE_GROUP:
  	case MCAST_BLOCK_SOURCE:
  	case MCAST_UNBLOCK_SOURCE:
  	{
  		struct group_source_req greqs;
  		int omode, add;
a28398ba6   Wang Chen   [IPV6]: Check len...
575
  		if (optlen < sizeof(struct group_source_req))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
  			goto e_inval;
  		if (copy_from_user(&greqs, optval, sizeof(greqs))) {
  			retv = -EFAULT;
  			break;
  		}
  		if (greqs.gsr_group.ss_family != AF_INET6 ||
  		    greqs.gsr_source.ss_family != AF_INET6) {
  			retv = -EADDRNOTAVAIL;
  			break;
  		}
  		if (optname == MCAST_BLOCK_SOURCE) {
  			omode = MCAST_EXCLUDE;
  			add = 1;
  		} else if (optname == MCAST_UNBLOCK_SOURCE) {
  			omode = MCAST_EXCLUDE;
  			add = 0;
  		} else if (optname == MCAST_JOIN_SOURCE_GROUP) {
  			struct sockaddr_in6 *psin6;
  
  			psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
  			retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
  				&psin6->sin6_addr);
c9e3e8b69   David L Stevens   [IPV6]: multicast...
598
599
  			/* prior join w/ different source is ok */
  			if (retv && retv != -EADDRINUSE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
601
602
  				break;
  			omode = MCAST_INCLUDE;
  			add = 1;
c9e3e8b69   David L Stevens   [IPV6]: multicast...
603
  		} else /* MCAST_LEAVE_SOURCE_GROUP */ {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
606
607
608
609
610
611
  			omode = MCAST_INCLUDE;
  			add = 0;
  		}
  		retv = ip6_mc_source(add, omode, sk, &greqs);
  		break;
  	}
  	case MCAST_MSFILTER:
  	{
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
614
615
616
617
618
619
620
  		extern int sysctl_mld_max_msf;
  		struct group_filter *gsf;
  
  		if (optlen < GROUP_FILTER_SIZE(0))
  			goto e_inval;
  		if (optlen > sysctl_optmem_max) {
  			retv = -ENOBUFS;
  			break;
  		}
8b3a70058   Kris Katterjohn   [NET]: Remove mor...
621
  		gsf = kmalloc(optlen,GFP_KERNEL);
cfcabdcc2   Stephen Hemminger   [NET]: sparse war...
622
  		if (!gsf) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
  			retv = -ENOBUFS;
  			break;
  		}
  		retv = -EFAULT;
  		if (copy_from_user(gsf, optval, optlen)) {
  			kfree(gsf);
  			break;
  		}
  		/* numsrc >= (4G-140)/128 overflow in 32 bits */
  		if (gsf->gf_numsrc >= 0x1ffffffU ||
  		    gsf->gf_numsrc > sysctl_mld_max_msf) {
  			kfree(gsf);
  			retv = -ENOBUFS;
  			break;
  		}
  		if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
  			kfree(gsf);
  			retv = -EINVAL;
  			break;
  		}
  		retv = ip6_mc_msfilter(sk, gsf);
  		kfree(gsf);
  
  		break;
  	}
  	case IPV6_ROUTER_ALERT:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
649
650
  		if (optlen < sizeof(int))
  			goto e_inval;
725a8ff04   Denis V. Lunev   ipv6: remove unus...
651
  		retv = ip6_ra_control(sk, val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
653
  		break;
  	case IPV6_MTU_DISCOVER:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
654
655
  		if (optlen < sizeof(int))
  			goto e_inval;
0eae750e6   John Dykstra   IP: Cleanups
656
  		if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_PROBE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
659
660
661
  			goto e_inval;
  		np->pmtudisc = val;
  		retv = 0;
  		break;
  	case IPV6_MTU:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
662
663
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
665
666
667
668
669
  		if (val && val < IPV6_MIN_MTU)
  			goto e_inval;
  		np->frag_size = val;
  		retv = 0;
  		break;
  	case IPV6_RECVERR:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
670
671
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
674
675
676
677
  		np->recverr = valbool;
  		if (!val)
  			skb_queue_purge(&sk->sk_error_queue);
  		retv = 0;
  		break;
  	case IPV6_FLOWINFO_SEND:
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
678
679
  		if (optlen < sizeof(int))
  			goto e_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
681
682
683
684
685
686
687
  		np->sndflow = valbool;
  		retv = 0;
  		break;
  	case IPV6_FLOWLABEL_MGR:
  		retv = ipv6_flowlabel_opt(sk, optval, optlen);
  		break;
  	case IPV6_IPSEC_POLICY:
  	case IPV6_XFRM_POLICY:
6fc0b4a7a   Herbert Xu   [IPSEC]: Restrict...
688
689
690
  		retv = -EPERM;
  		if (!capable(CAP_NET_ADMIN))
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
  		retv = xfrm_user_policy(sk, optname, optval, optlen);
  		break;
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
693
694
695
696
  	case IPV6_ADDR_PREFERENCES:
  	    {
  		unsigned int pref = 0;
  		unsigned int prefmask = ~0;
b2a9d7c2f   YOSHIFUJI Hideaki   [IPV6]: Check len...
697
698
  		if (optlen < sizeof(int))
  			goto e_inval;
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
  		retv = -EINVAL;
  
  		/* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
  		switch (val & (IPV6_PREFER_SRC_PUBLIC|
  			       IPV6_PREFER_SRC_TMP|
  			       IPV6_PREFER_SRC_PUBTMP_DEFAULT)) {
  		case IPV6_PREFER_SRC_PUBLIC:
  			pref |= IPV6_PREFER_SRC_PUBLIC;
  			break;
  		case IPV6_PREFER_SRC_TMP:
  			pref |= IPV6_PREFER_SRC_TMP;
  			break;
  		case IPV6_PREFER_SRC_PUBTMP_DEFAULT:
  			break;
  		case 0:
  			goto pref_skip_pubtmp;
  		default:
  			goto e_inval;
  		}
  
  		prefmask &= ~(IPV6_PREFER_SRC_PUBLIC|
  			      IPV6_PREFER_SRC_TMP);
  pref_skip_pubtmp:
  
  		/* check HOME/COA conflicts */
  		switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) {
  		case IPV6_PREFER_SRC_HOME:
  			break;
  		case IPV6_PREFER_SRC_COA:
  			pref |= IPV6_PREFER_SRC_COA;
  		case 0:
  			goto pref_skip_coa;
  		default:
  			goto e_inval;
  		}
  
  		prefmask &= ~IPV6_PREFER_SRC_COA;
  pref_skip_coa:
  
  		/* check CGA/NONCGA conflicts */
  		switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) {
  		case IPV6_PREFER_SRC_CGA:
  		case IPV6_PREFER_SRC_NONCGA:
  		case 0:
  			break;
  		default:
  			goto e_inval;
  		}
  
  		np->srcprefs = (np->srcprefs & prefmask) | pref;
  		retv = 0;
  
  		break;
  	    }
e802af9ca   Stephen Hemminger   IPv6: Generic TTL...
753
754
755
756
757
758
  	case IPV6_MINHOPCOUNT:
  		if (optlen < sizeof(int))
  			goto e_inval;
  		if (val < 0 || val > 255)
  			goto e_inval;
  		np->min_hopcount = val;
793b14731   Brian Haley   IPv6: data struct...
759
760
761
  		break;
  	case IPV6_DONTFRAG:
  		np->dontfrag = valbool;
e802af9ca   Stephen Hemminger   IPv6: Generic TTL...
762
763
  		retv = 0;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  	}
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
765

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
768
769
770
771
772
  	return retv;
  
  e_inval:
  	release_sock(sk);
  	return -EINVAL;
  }
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
773
  int ipv6_setsockopt(struct sock *sk, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
774
  		    char __user *optval, unsigned int optlen)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
  {
  	int err;
  
  	if (level == SOL_IP && sk->sk_type != SOCK_RAW)
  		return udp_prot.setsockopt(sk, level, optname, optval, optlen);
  
  	if (level != SOL_IPV6)
  		return -ENOPROTOOPT;
  
  	err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
  #ifdef CONFIG_NETFILTER
  	/* we need to exclude all possible ENOPROTOOPTs except default case */
  	if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
  			optname != IPV6_XFRM_POLICY) {
  		lock_sock(sk);
  		err = nf_setsockopt(sk, PF_INET6, optname, optval,
  				optlen);
  		release_sock(sk);
  	}
  #endif
  	return err;
  }
7159039a1   YOSHIFUJI Hideaki   [IPV6]: Decentral...
797
  EXPORT_SYMBOL(ipv6_setsockopt);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
798
799
800
  
  #ifdef CONFIG_COMPAT
  int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
801
  			   char __user *optval, unsigned int optlen)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
802
803
804
805
  {
  	int err;
  
  	if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
806
807
808
809
  		if (udp_prot.compat_setsockopt != NULL)
  			return udp_prot.compat_setsockopt(sk, level, optname,
  							  optval, optlen);
  		return udp_prot.setsockopt(sk, level, optname, optval, optlen);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
810
811
812
813
  	}
  
  	if (level != SOL_IPV6)
  		return -ENOPROTOOPT;
dae502954   David L Stevens   ipv4/ipv6 compat:...
814
815
816
  	if (optname >= MCAST_JOIN_GROUP && optname <= MCAST_MSFILTER)
  		return compat_mc_setsockopt(sk, level, optname, optval, optlen,
  			ipv6_setsockopt);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
817
818
819
820
  	err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
  #ifdef CONFIG_NETFILTER
  	/* we need to exclude all possible ENOPROTOOPTs except default case */
  	if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
821
  	    optname != IPV6_XFRM_POLICY) {
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
822
  		lock_sock(sk);
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
823
824
  		err = compat_nf_setsockopt(sk, PF_INET6, optname,
  					   optval, optlen);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
825
826
827
828
829
  		release_sock(sk);
  	}
  #endif
  	return err;
  }
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
830
831
  
  EXPORT_SYMBOL(compat_ipv6_setsockopt);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
832
  #endif
286930797   David S. Miller   [IPV6]: Handle np...
833
  static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
4c6510a73   YOSHIFUJI Hideaki   [IPV6]: Return co...
834
  				  int optname, char __user *optval, int len)
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
835
  {
286930797   David S. Miller   [IPV6]: Handle np...
836
  	struct ipv6_opt_hdr *hdr;
4c6510a73   YOSHIFUJI Hideaki   [IPV6]: Return co...
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
  	if (!opt)
  		return 0;
  
  	switch(optname) {
  	case IPV6_HOPOPTS:
  		hdr = opt->hopopt;
  		break;
  	case IPV6_RTHDRDSTOPTS:
  		hdr = opt->dst0opt;
  		break;
  	case IPV6_RTHDR:
  		hdr = (struct ipv6_opt_hdr *)opt->srcrt;
  		break;
  	case IPV6_DSTOPTS:
  		hdr = opt->dst1opt;
  		break;
  	default:
  		return -EINVAL;	/* should not happen */
  	}
  
  	if (!hdr)
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
858
  		return 0;
286930797   David S. Miller   [IPV6]: Handle np...
859

d2b02ed94   Chris Wright   [IPV6] fix ipv6_g...
860
  	len = min_t(unsigned int, len, ipv6_optlen(hdr));
660adc6e6   Ilpo Järvinen   [IPv6]: Invalid s...
861
  	if (copy_to_user(optval, hdr, len))
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
862
  		return -EFAULT;
95b496b66   Yang Hongyang   [IPV6]: Fix the d...
863
  	return len;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
864
  }
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
865
  static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
98e77438a   Daniel Baluta   ipv6: Fix ipv6_ge...
866
  		    char __user *optval, int __user *optlen, unsigned flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
869
870
  {
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	int len;
  	int val;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
871
872
  	if (ip6_mroute_opt(optname))
  		return ip6_mroute_getsockopt(sk, optname, optval, optlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
874
875
876
877
  	if (get_user(len, optlen))
  		return -EFAULT;
  	switch (optname) {
  	case IPV6_ADDRFORM:
  		if (sk->sk_protocol != IPPROTO_UDP &&
ba4e58eca   Gerrit Renker   [NET]: Supporting...
878
  		    sk->sk_protocol != IPPROTO_UDPLITE &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
  		    sk->sk_protocol != IPPROTO_TCP)
1717699cd   YOSHIFUJI Hideaki   ipv6: Fail with a...
880
  			return -ENOPROTOOPT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
882
883
884
885
886
887
888
889
890
891
892
893
  		if (sk->sk_state != TCP_ESTABLISHED)
  			return -ENOTCONN;
  		val = sk->sk_family;
  		break;
  	case MCAST_MSFILTER:
  	{
  		struct group_filter gsf;
  		int err;
  
  		if (len < GROUP_FILTER_SIZE(0))
  			return -EINVAL;
  		if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0)))
  			return -EFAULT;
20c61fbd8   YOSHIFUJI Hideaki   ipv6 mcast: Check...
894
895
  		if (gsf.gf_group.ss_family != AF_INET6)
  			return -EADDRNOTAVAIL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
897
898
899
900
901
  		lock_sock(sk);
  		err = ip6_mc_msfget(sk, &gsf,
  			(struct group_filter __user *)optval, optlen);
  		release_sock(sk);
  		return err;
  	}
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
902
  	case IPV6_2292PKTOPTIONS:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
905
906
907
908
909
910
911
  	{
  		struct msghdr msg;
  		struct sk_buff *skb;
  
  		if (sk->sk_type != SOCK_STREAM)
  			return -ENOPROTOOPT;
  
  		msg.msg_control = optval;
  		msg.msg_controllen = len;
98e77438a   Daniel Baluta   ipv6: Fix ipv6_ge...
912
  		msg.msg_flags = flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  
  		lock_sock(sk);
  		skb = np->pktoptions;
  		if (skb)
  			atomic_inc(&skb->users);
  		release_sock(sk);
  
  		if (skb) {
  			int err = datagram_recv_ctl(sk, &msg, skb);
  			kfree_skb(skb);
  			if (err)
  				return err;
  		} else {
  			if (np->rxopt.bits.rxinfo) {
  				struct in6_pktinfo src_info;
f250dcdac   Yang Hongyang   ipv6: fix the ret...
928
929
  				src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
  					np->sticky_pktinfo.ipi6_ifindex;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
930
  				src_info.ipi6_addr = np->mcast_oif ? np->daddr : np->sticky_pktinfo.ipi6_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
933
934
935
936
  				put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info);
  			}
  			if (np->rxopt.bits.rxhlim) {
  				int hlim = np->mcast_hops;
  				put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
  			}
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
937
938
  			if (np->rxopt.bits.rxoinfo) {
  				struct in6_pktinfo src_info;
f250dcdac   Yang Hongyang   ipv6: fix the ret...
939
940
  				src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
  					np->sticky_pktinfo.ipi6_ifindex;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
941
  				src_info.ipi6_addr = np->mcast_oif ? np->daddr : np->sticky_pktinfo.ipi6_addr;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
942
943
944
945
946
947
  				put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info);
  			}
  			if (np->rxopt.bits.rxohlim) {
  				int hlim = np->mcast_hops;
  				put_cmsg(&msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948
949
950
951
952
953
954
  		}
  		len -= msg.msg_controllen;
  		return put_user(len, optlen);
  	}
  	case IPV6_MTU:
  	{
  		struct dst_entry *dst;
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
955

1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
956
  		val = 0;
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
957
958
959
  		rcu_read_lock();
  		dst = __sk_dst_get(sk);
  		if (dst)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
  			val = dst_mtu(dst);
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
961
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
963
964
965
966
967
968
969
  		if (!val)
  			return -ENOTCONN;
  		break;
  	}
  
  	case IPV6_V6ONLY:
  		val = np->ipv6only;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
970
  	case IPV6_RECVPKTINFO:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
972
  		val = np->rxopt.bits.rxinfo;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
973
974
975
976
977
  	case IPV6_2292PKTINFO:
  		val = np->rxopt.bits.rxoinfo;
  		break;
  
  	case IPV6_RECVHOPLIMIT:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
979
  		val = np->rxopt.bits.rxhlim;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
980
981
982
983
984
  	case IPV6_2292HOPLIMIT:
  		val = np->rxopt.bits.rxohlim;
  		break;
  
  	case IPV6_RECVRTHDR:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
986
  		val = np->rxopt.bits.srcrt;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
987
988
989
  	case IPV6_2292RTHDR:
  		val = np->rxopt.bits.osrcrt;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
  	case IPV6_HOPOPTS:
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
991
992
993
994
995
996
  	case IPV6_RTHDRDSTOPTS:
  	case IPV6_RTHDR:
  	case IPV6_DSTOPTS:
  	{
  
  		lock_sock(sk);
286930797   David S. Miller   [IPV6]: Handle np...
997
  		len = ipv6_getsockopt_sticky(sk, np->opt,
4c6510a73   YOSHIFUJI Hideaki   [IPV6]: Return co...
998
  					     optname, optval, len);
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
999
  		release_sock(sk);
05335c222   Yang Hongyang   [IPV6]: Fix the r...
1000
1001
1002
  		/* check if ipv6_getsockopt_sticky() returns err code */
  		if (len < 0)
  			return len;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
1003
1004
1005
1006
  		return put_user(len, optlen);
  	}
  
  	case IPV6_RECVHOPOPTS:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
  		val = np->rxopt.bits.hopopts;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
1009
1010
1011
1012
1013
  	case IPV6_2292HOPOPTS:
  		val = np->rxopt.bits.ohopopts;
  		break;
  
  	case IPV6_RECVDSTOPTS:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
1015
  		val = np->rxopt.bits.dstopts;
  		break;
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
1016
1017
1018
  	case IPV6_2292DSTOPTS:
  		val = np->rxopt.bits.odstopts;
  		break;
41a1f8ea4   YOSHIFUJI Hideaki   [IPV6]: Support I...
1019
1020
1021
1022
1023
1024
1025
  	case IPV6_TCLASS:
  		val = np->tclass;
  		break;
  
  	case IPV6_RECVTCLASS:
  		val = np->rxopt.bits.rxtclass;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
1027
1028
  	case IPV6_FLOWINFO:
  		val = np->rxopt.bits.rxflow;
  		break;
793b14731   Brian Haley   IPv6: data struct...
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
  	case IPV6_RECVPATHMTU:
  		val = np->rxopt.bits.rxpmtu;
  		break;
  
  	case IPV6_PATHMTU:
  	{
  		struct dst_entry *dst;
  		struct ip6_mtuinfo mtuinfo;
  
  		if (len < sizeof(mtuinfo))
  			return -EINVAL;
  
  		len = sizeof(mtuinfo);
  		memset(&mtuinfo, 0, sizeof(mtuinfo));
  
  		rcu_read_lock();
  		dst = __sk_dst_get(sk);
  		if (dst)
  			mtuinfo.ip6m_mtu = dst_mtu(dst);
  		rcu_read_unlock();
  		if (!mtuinfo.ip6m_mtu)
  			return -ENOTCONN;
  
  		if (put_user(len, optlen))
  			return -EFAULT;
  		if (copy_to_user(optval, &mtuinfo, len))
  			return -EFAULT;
  
  		return 0;
  		break;
  	}
6c4686228   Balazs Scheidler   tproxy: added tpr...
1060
1061
1062
1063
1064
1065
1066
  	case IPV6_TRANSPARENT:
  		val = inet_sk(sk)->transparent;
  		break;
  
  	case IPV6_RECVORIGDSTADDR:
  		val = np->rxopt.bits.rxorigdstaddr;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
  	case IPV6_UNICAST_HOPS:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068
  	case IPV6_MULTICAST_HOPS:
befffe901   Brian Haley   [IPV6]: Fix IPV6_...
1069
1070
1071
1072
1073
1074
1075
  	{
  		struct dst_entry *dst;
  
  		if (optname == IPV6_UNICAST_HOPS)
  			val = np->hop_limit;
  		else
  			val = np->mcast_hops;
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
1076
1077
1078
1079
  		if (val < 0) {
  			rcu_read_lock();
  			dst = __sk_dst_get(sk);
  			if (dst)
6b75d0908   YOSHIFUJI Hideaki   [IPV6]: Optimize ...
1080
  				val = ip6_dst_hoplimit(dst);
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
1081
  			rcu_read_unlock();
befffe901   Brian Haley   [IPV6]: Fix IPV6_...
1082
  		}
b6c6712a4   Eric Dumazet   net: sk_dst_cache...
1083

befffe901   Brian Haley   [IPV6]: Fix IPV6_...
1084
  		if (val < 0)
53b7997fd   YOSHIFUJI Hideaki   ipv6 netns: Make ...
1085
  			val = sock_net(sk)->ipv6.devconf_all->hop_limit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
  		break;
befffe901   Brian Haley   [IPV6]: Fix IPV6_...
1087
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
  
  	case IPV6_MULTICAST_LOOP:
  		val = np->mc_loop;
  		break;
  
  	case IPV6_MULTICAST_IF:
  		val = np->mcast_oif;
  		break;
  
  	case IPV6_MTU_DISCOVER:
  		val = np->pmtudisc;
  		break;
  
  	case IPV6_RECVERR:
  		val = np->recverr;
  		break;
  
  	case IPV6_FLOWINFO_SEND:
  		val = np->sndflow;
  		break;
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
  	case IPV6_ADDR_PREFERENCES:
  		val = 0;
  
  		if (np->srcprefs & IPV6_PREFER_SRC_TMP)
  			val |= IPV6_PREFER_SRC_TMP;
  		else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC)
  			val |= IPV6_PREFER_SRC_PUBLIC;
  		else {
  			/* XXX: should we return system default? */
  			val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT;
  		}
  
  		if (np->srcprefs & IPV6_PREFER_SRC_COA)
  			val |= IPV6_PREFER_SRC_COA;
  		else
  			val |= IPV6_PREFER_SRC_HOME;
  		break;
e802af9ca   Stephen Hemminger   IPv6: Generic TTL...
1125
1126
1127
1128
  
  	case IPV6_MINHOPCOUNT:
  		val = np->min_hopcount;
  		break;
793b14731   Brian Haley   IPv6: data struct...
1129
1130
1131
1132
  
  	case IPV6_DONTFRAG:
  		val = np->dontfrag;
  		break;
7cbca67c0   YOSHIFUJI Hideaki   [IPV6]: Support S...
1133

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
  	default:
cf6fc4a92   Wei Yongjun   [IPV6]: Fix the r...
1135
  		return -ENOPROTOOPT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
1137
1138
1139
1140
1141
1142
1143
  	}
  	len = min_t(unsigned int, sizeof(int), len);
  	if(put_user(len, optlen))
  		return -EFAULT;
  	if(copy_to_user(optval,&val,len))
  		return -EFAULT;
  	return 0;
  }
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
  int ipv6_getsockopt(struct sock *sk, int level, int optname,
  		    char __user *optval, int __user *optlen)
  {
  	int err;
  
  	if (level == SOL_IP && sk->sk_type != SOCK_RAW)
  		return udp_prot.getsockopt(sk, level, optname, optval, optlen);
  
  	if(level != SOL_IPV6)
  		return -ENOPROTOOPT;
98e77438a   Daniel Baluta   ipv6: Fix ipv6_ge...
1154
  	err = do_ipv6_getsockopt(sk, level, optname, optval, optlen, 0);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1155
  #ifdef CONFIG_NETFILTER
cf6fc4a92   Wei Yongjun   [IPV6]: Fix the r...
1156
1157
  	/* we need to exclude all possible ENOPROTOOPTs except default case */
  	if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
  		int len;
  
  		if (get_user(len, optlen))
  			return -EFAULT;
  
  		lock_sock(sk);
  		err = nf_getsockopt(sk, PF_INET6, optname, optval,
  				&len);
  		release_sock(sk);
  		if (err >= 0)
  			err = put_user(len, optlen);
  	}
  #endif
  	return err;
  }
7159039a1   YOSHIFUJI Hideaki   [IPV6]: Decentral...
1173
  EXPORT_SYMBOL(ipv6_getsockopt);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1174
1175
  #ifdef CONFIG_COMPAT
  int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1176
  			   char __user *optval, int __user *optlen)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1177
1178
1179
1180
  {
  	int err;
  
  	if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1181
1182
1183
1184
  		if (udp_prot.compat_getsockopt != NULL)
  			return udp_prot.compat_getsockopt(sk, level, optname,
  							  optval, optlen);
  		return udp_prot.getsockopt(sk, level, optname, optval, optlen);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1185
  	}
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1186
  	if (level != SOL_IPV6)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1187
  		return -ENOPROTOOPT;
809917903   Pavel Emelyanov   ipv6: Compilation...
1188
1189
1190
  	if (optname == MCAST_MSFILTER)
  		return compat_mc_getsockopt(sk, level, optname, optval, optlen,
  			ipv6_getsockopt);
98e77438a   Daniel Baluta   ipv6: Fix ipv6_ge...
1191
1192
  	err = do_ipv6_getsockopt(sk, level, optname, optval, optlen,
  				 MSG_CMSG_COMPAT);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1193
  #ifdef CONFIG_NETFILTER
cf6fc4a92   Wei Yongjun   [IPV6]: Fix the r...
1194
1195
  	/* we need to exclude all possible ENOPROTOOPTs except default case */
  	if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1196
1197
1198
1199
1200
1201
  		int len;
  
  		if (get_user(len, optlen))
  			return -EFAULT;
  
  		lock_sock(sk);
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1202
1203
  		err = compat_nf_getsockopt(sk, PF_INET6,
  					   optname, optval, &len);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1204
1205
1206
1207
1208
1209
1210
  		release_sock(sk);
  		if (err >= 0)
  			err = put_user(len, optlen);
  	}
  #endif
  	return err;
  }
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1211
1212
  
  EXPORT_SYMBOL(compat_ipv6_getsockopt);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1213
  #endif