• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/net/ipv6/
1
2
3#include <linux/module.h>
4#include <linux/capability.h>
5#include <linux/errno.h>
6#include <linux/types.h>
7#include <linux/socket.h>
8#include <linux/sockios.h>
9#include <linux/net.h>
10#include <linux/in6.h>
11#include <linux/mroute6.h>
12#include <linux/netdevice.h>
13#include <linux/if_arp.h>
14#include <linux/init.h>
15#include <linux/sysctl.h>
16#include <linux/netfilter.h>
17#include <linux/slab.h>
18
19#include <net/sock.h>
20#include <net/snmp.h>
21#include <net/ipv6.h>
22#include <net/ndisc.h>
23#include <net/protocol.h>
24#include <net/transp_v6.h>
25#include <net/ip6_route.h>
26#include <net/addrconf.h>
27#include <net/inet_common.h>
28#include <net/tcp.h>
29#include <net/udp.h>
30#include <net/udplite.h>
31#include <net/xfrm.h>
32#include <net/compat.h>
33
34#include <asm/uaccess.h>
35
36struct ip6_ra_chain *ip6_ra_chain;
37DEFINE_RWLOCK(ip6_ra_lock);
38
39int ip6_ra_control(struct sock *sk, int sel)
40{
41	struct ip6_ra_chain *ra, *new_ra, **rap;
42
43	/* RA packet may be delivered ONLY to IPPROTO_RAW socket */
44	if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num != IPPROTO_RAW)
45		return -ENOPROTOOPT;
46
47	new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
48
49	write_lock_bh(&ip6_ra_lock);
50	for (rap = &ip6_ra_chain; (ra=*rap) != NULL; rap = &ra->next) {
51		if (ra->sk == sk) {
52			if (sel>=0) {
53				write_unlock_bh(&ip6_ra_lock);
54				kfree(new_ra);
55				return -EADDRINUSE;
56			}
57
58			*rap = ra->next;
59			write_unlock_bh(&ip6_ra_lock);
60
61			sock_put(sk);
62			kfree(ra);
63			return 0;
64		}
65	}
66	if (new_ra == NULL) {
67		write_unlock_bh(&ip6_ra_lock);
68		return -ENOBUFS;
69	}
70	new_ra->sk = sk;
71	new_ra->sel = sel;
72	new_ra->next = ra;
73	*rap = new_ra;
74	sock_hold(sk);
75	write_unlock_bh(&ip6_ra_lock);
76	return 0;
77}
78
79static
80struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
81					   struct ipv6_txoptions *opt)
82{
83	if (inet_sk(sk)->is_icsk) {
84		if (opt &&
85		    !((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
86		    inet_sk(sk)->inet_daddr != LOOPBACK4_IPV6) {
87			struct inet_connection_sock *icsk = inet_csk(sk);
88			icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen;
89			icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
90		}
91		opt = xchg(&inet6_sk(sk)->opt, opt);
92	} else {
93		spin_lock(&sk->sk_dst_lock);
94		opt = xchg(&inet6_sk(sk)->opt, opt);
95		spin_unlock(&sk->sk_dst_lock);
96	}
97	sk_dst_reset(sk);
98
99	return opt;
100}
101
102static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
103		    char __user *optval, unsigned int optlen)
104{
105	struct ipv6_pinfo *np = inet6_sk(sk);
106	struct net *net = sock_net(sk);
107	int val, valbool;
108	int retv = -ENOPROTOOPT;
109
110	if (optval == NULL)
111		val=0;
112	else {
113		if (optlen >= sizeof(int)) {
114			if (get_user(val, (int __user *) optval))
115				return -EFAULT;
116		} else
117			val = 0;
118	}
119
120	valbool = (val!=0);
121
122	if (ip6_mroute_opt(optname))
123		return ip6_mroute_setsockopt(sk, optname, optval, optlen);
124
125	lock_sock(sk);
126
127	switch (optname) {
128
129	case IPV6_ADDRFORM:
130		if (optlen < sizeof(int))
131			goto e_inval;
132		if (val == PF_INET) {
133			struct ipv6_txoptions *opt;
134			struct sk_buff *pktopt;
135
136			if (sk->sk_type == SOCK_RAW)
137				break;
138
139			if (sk->sk_protocol == IPPROTO_UDP ||
140			    sk->sk_protocol == IPPROTO_UDPLITE) {
141				struct udp_sock *up = udp_sk(sk);
142				if (up->pending == AF_INET6) {
143					retv = -EBUSY;
144					break;
145				}
146			} else if (sk->sk_protocol != IPPROTO_TCP)
147				break;
148
149			if (sk->sk_state != TCP_ESTABLISHED) {
150				retv = -ENOTCONN;
151				break;
152			}
153
154			if (ipv6_only_sock(sk) ||
155			    !ipv6_addr_v4mapped(&np->daddr)) {
156				retv = -EADDRNOTAVAIL;
157				break;
158			}
159
160			fl6_free_socklist(sk);
161			ipv6_sock_mc_close(sk);
162
163			/*
164			 * Sock is moving from IPv6 to IPv4 (sk_prot), so
165			 * remove it from the refcnt debug socks count in the
166			 * original family...
167			 */
168			sk_refcnt_debug_dec(sk);
169
170			if (sk->sk_protocol == IPPROTO_TCP) {
171				struct inet_connection_sock *icsk = inet_csk(sk);
172				local_bh_disable();
173				sock_prot_inuse_add(net, sk->sk_prot, -1);
174				sock_prot_inuse_add(net, &tcp_prot, 1);
175				local_bh_enable();
176				sk->sk_prot = &tcp_prot;
177				icsk->icsk_af_ops = &ipv4_specific;
178				sk->sk_socket->ops = &inet_stream_ops;
179				sk->sk_family = PF_INET;
180				tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
181			} else {
182				struct proto *prot = &udp_prot;
183
184				if (sk->sk_protocol == IPPROTO_UDPLITE)
185					prot = &udplite_prot;
186				local_bh_disable();
187				sock_prot_inuse_add(net, sk->sk_prot, -1);
188				sock_prot_inuse_add(net, prot, 1);
189				local_bh_enable();
190				sk->sk_prot = prot;
191				sk->sk_socket->ops = &inet_dgram_ops;
192				sk->sk_family = PF_INET;
193			}
194			opt = xchg(&np->opt, NULL);
195			if (opt)
196				sock_kfree_s(sk, opt, opt->tot_len);
197			pktopt = xchg(&np->pktoptions, NULL);
198			kfree_skb(pktopt);
199
200			sk->sk_destruct = inet_sock_destruct;
201			/*
202			 * ... and add it to the refcnt debug socks count
203			 * in the new family. -acme
204			 */
205			sk_refcnt_debug_inc(sk);
206			module_put(THIS_MODULE);
207			retv = 0;
208			break;
209		}
210		goto e_inval;
211
212	case IPV6_V6ONLY:
213		if (optlen < sizeof(int) ||
214		    inet_sk(sk)->inet_num)
215			goto e_inval;
216		np->ipv6only = valbool;
217		retv = 0;
218		break;
219
220	case IPV6_RECVPKTINFO:
221		if (optlen < sizeof(int))
222			goto e_inval;
223		np->rxopt.bits.rxinfo = valbool;
224		retv = 0;
225		break;
226
227	case IPV6_2292PKTINFO:
228		if (optlen < sizeof(int))
229			goto e_inval;
230		np->rxopt.bits.rxoinfo = valbool;
231		retv = 0;
232		break;
233
234	case IPV6_RECVHOPLIMIT:
235		if (optlen < sizeof(int))
236			goto e_inval;
237		np->rxopt.bits.rxhlim = valbool;
238		retv = 0;
239		break;
240
241	case IPV6_2292HOPLIMIT:
242		if (optlen < sizeof(int))
243			goto e_inval;
244		np->rxopt.bits.rxohlim = valbool;
245		retv = 0;
246		break;
247
248	case IPV6_RECVRTHDR:
249		if (optlen < sizeof(int))
250			goto e_inval;
251		np->rxopt.bits.srcrt = valbool;
252		retv = 0;
253		break;
254
255	case IPV6_2292RTHDR:
256		if (optlen < sizeof(int))
257			goto e_inval;
258		np->rxopt.bits.osrcrt = valbool;
259		retv = 0;
260		break;
261
262	case IPV6_RECVHOPOPTS:
263		if (optlen < sizeof(int))
264			goto e_inval;
265		np->rxopt.bits.hopopts = valbool;
266		retv = 0;
267		break;
268
269	case IPV6_2292HOPOPTS:
270		if (optlen < sizeof(int))
271			goto e_inval;
272		np->rxopt.bits.ohopopts = valbool;
273		retv = 0;
274		break;
275
276	case IPV6_RECVDSTOPTS:
277		if (optlen < sizeof(int))
278			goto e_inval;
279		np->rxopt.bits.dstopts = valbool;
280		retv = 0;
281		break;
282
283	case IPV6_2292DSTOPTS:
284		if (optlen < sizeof(int))
285			goto e_inval;
286		np->rxopt.bits.odstopts = valbool;
287		retv = 0;
288		break;
289
290	case IPV6_TCLASS:
291		if (optlen < sizeof(int))
292			goto e_inval;
293		if (val < -1 || val > 0xff)
294			goto e_inval;
295		/* RFC 3542, 6.5: default traffic class of 0x0 */
296		if (val == -1)
297			val = 0;
298		np->tclass = val;
299		retv = 0;
300		break;
301
302	case IPV6_RECVTCLASS:
303		if (optlen < sizeof(int))
304			goto e_inval;
305		np->rxopt.bits.rxtclass = valbool;
306		retv = 0;
307		break;
308
309	case IPV6_FLOWINFO:
310		if (optlen < sizeof(int))
311			goto e_inval;
312		np->rxopt.bits.rxflow = valbool;
313		retv = 0;
314		break;
315
316	case IPV6_RECVPATHMTU:
317		if (optlen < sizeof(int))
318			goto e_inval;
319		np->rxopt.bits.rxpmtu = valbool;
320		retv = 0;
321		break;
322
323	case IPV6_HOPOPTS:
324	case IPV6_RTHDRDSTOPTS:
325	case IPV6_RTHDR:
326	case IPV6_DSTOPTS:
327	{
328		struct ipv6_txoptions *opt;
329
330		/* remove any sticky options header with a zero option
331		 * length, per RFC3542.
332		 */
333		if (optlen == 0)
334			optval = NULL;
335		else if (optval == NULL)
336			goto e_inval;
337		else if (optlen < sizeof(struct ipv6_opt_hdr) ||
338			 optlen & 0x7 || optlen > 8 * 255)
339			goto e_inval;
340
341		/* hop-by-hop / destination options are privileged option */
342		retv = -EPERM;
343		if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
344			break;
345
346		opt = ipv6_renew_options(sk, np->opt, optname,
347					 (struct ipv6_opt_hdr __user *)optval,
348					 optlen);
349		if (IS_ERR(opt)) {
350			retv = PTR_ERR(opt);
351			break;
352		}
353
354		/* routing header option needs extra check */
355		retv = -EINVAL;
356		if (optname == IPV6_RTHDR && opt && opt->srcrt) {
357			struct ipv6_rt_hdr *rthdr = opt->srcrt;
358			switch (rthdr->type) {
359#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
360			case IPV6_SRCRT_TYPE_2:
361				if (rthdr->hdrlen != 2 ||
362				    rthdr->segments_left != 1)
363					goto sticky_done;
364
365				break;
366#endif
367			default:
368				goto sticky_done;
369			}
370		}
371
372		retv = 0;
373		opt = ipv6_update_options(sk, opt);
374sticky_done:
375		if (opt)
376			sock_kfree_s(sk, opt, opt->tot_len);
377		break;
378	}
379
380	case IPV6_PKTINFO:
381	{
382		struct in6_pktinfo pkt;
383
384		if (optlen == 0)
385			goto e_inval;
386		else if (optlen < sizeof(struct in6_pktinfo) || optval == NULL)
387			goto e_inval;
388
389		if (copy_from_user(&pkt, optval, sizeof(struct in6_pktinfo))) {
390				retv = -EFAULT;
391				break;
392		}
393		if (sk->sk_bound_dev_if && pkt.ipi6_ifindex != sk->sk_bound_dev_if)
394			goto e_inval;
395
396		np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex;
397		ipv6_addr_copy(&np->sticky_pktinfo.ipi6_addr, &pkt.ipi6_addr);
398		retv = 0;
399		break;
400	}
401
402	case IPV6_2292PKTOPTIONS:
403	{
404		struct ipv6_txoptions *opt = NULL;
405		struct msghdr msg;
406		struct flowi fl;
407		int junk;
408
409		fl.fl6_flowlabel = 0;
410		fl.oif = sk->sk_bound_dev_if;
411		fl.mark = sk->sk_mark;
412
413		if (optlen == 0)
414			goto update;
415
416		/* 1K is probably excessive
417		 * 1K is surely not enough, 2K per standard header is 16K.
418		 */
419		retv = -EINVAL;
420		if (optlen > 64*1024)
421			break;
422
423		opt = sock_kmalloc(sk, sizeof(*opt) + optlen, GFP_KERNEL);
424		retv = -ENOBUFS;
425		if (opt == NULL)
426			break;
427
428		memset(opt, 0, sizeof(*opt));
429		opt->tot_len = sizeof(*opt) + optlen;
430		retv = -EFAULT;
431		if (copy_from_user(opt+1, optval, optlen))
432			goto done;
433
434		msg.msg_controllen = optlen;
435		msg.msg_control = (void*)(opt+1);
436
437		retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk,
438					 &junk);
439		if (retv)
440			goto done;
441update:
442		retv = 0;
443		opt = ipv6_update_options(sk, opt);
444done:
445		if (opt)
446			sock_kfree_s(sk, opt, opt->tot_len);
447		break;
448	}
449	case IPV6_UNICAST_HOPS:
450		if (optlen < sizeof(int))
451			goto e_inval;
452		if (val > 255 || val < -1)
453			goto e_inval;
454		np->hop_limit = val;
455		retv = 0;
456		break;
457
458	case IPV6_MULTICAST_HOPS:
459		if (sk->sk_type == SOCK_STREAM)
460			break;
461		if (optlen < sizeof(int))
462			goto e_inval;
463		if (val > 255 || val < -1)
464			goto e_inval;
465		np->mcast_hops = val;
466		retv = 0;
467		break;
468
469	case IPV6_MULTICAST_LOOP:
470		if (optlen < sizeof(int))
471			goto e_inval;
472		if (val != valbool)
473			goto e_inval;
474		np->mc_loop = valbool;
475		retv = 0;
476		break;
477
478	case IPV6_MULTICAST_IF:
479		if (sk->sk_type == SOCK_STREAM)
480			break;
481		if (optlen < sizeof(int))
482			goto e_inval;
483
484		if (val) {
485			struct net_device *dev;
486
487			if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val)
488				goto e_inval;
489
490			dev = dev_get_by_index(net, val);
491			if (!dev) {
492				retv = -ENODEV;
493				break;
494			}
495			dev_put(dev);
496		}
497		np->mcast_oif = val;
498		retv = 0;
499		break;
500	case IPV6_ADD_MEMBERSHIP:
501	case IPV6_DROP_MEMBERSHIP:
502	{
503		struct ipv6_mreq mreq;
504
505		if (optlen < sizeof(struct ipv6_mreq))
506			goto e_inval;
507
508		retv = -EPROTO;
509		if (inet_sk(sk)->is_icsk)
510			break;
511
512		retv = -EFAULT;
513		if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
514			break;
515
516		if (optname == IPV6_ADD_MEMBERSHIP)
517			retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
518		else
519			retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
520		break;
521	}
522	case IPV6_JOIN_ANYCAST:
523	case IPV6_LEAVE_ANYCAST:
524	{
525		struct ipv6_mreq mreq;
526
527		if (optlen < sizeof(struct ipv6_mreq))
528			goto e_inval;
529
530		retv = -EFAULT;
531		if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
532			break;
533
534		if (optname == IPV6_JOIN_ANYCAST)
535			retv = ipv6_sock_ac_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr);
536		else
537			retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_acaddr);
538		break;
539	}
540	case MCAST_JOIN_GROUP:
541	case MCAST_LEAVE_GROUP:
542	{
543		struct group_req greq;
544		struct sockaddr_in6 *psin6;
545
546		if (optlen < sizeof(struct group_req))
547			goto e_inval;
548
549		retv = -EFAULT;
550		if (copy_from_user(&greq, optval, sizeof(struct group_req)))
551			break;
552		if (greq.gr_group.ss_family != AF_INET6) {
553			retv = -EADDRNOTAVAIL;
554			break;
555		}
556		psin6 = (struct sockaddr_in6 *)&greq.gr_group;
557		if (optname == MCAST_JOIN_GROUP)
558			retv = ipv6_sock_mc_join(sk, greq.gr_interface,
559				&psin6->sin6_addr);
560		else
561			retv = ipv6_sock_mc_drop(sk, greq.gr_interface,
562				&psin6->sin6_addr);
563		break;
564	}
565	case MCAST_JOIN_SOURCE_GROUP:
566	case MCAST_LEAVE_SOURCE_GROUP:
567	case MCAST_BLOCK_SOURCE:
568	case MCAST_UNBLOCK_SOURCE:
569	{
570		struct group_source_req greqs;
571		int omode, add;
572
573		if (optlen < sizeof(struct group_source_req))
574			goto e_inval;
575		if (copy_from_user(&greqs, optval, sizeof(greqs))) {
576			retv = -EFAULT;
577			break;
578		}
579		if (greqs.gsr_group.ss_family != AF_INET6 ||
580		    greqs.gsr_source.ss_family != AF_INET6) {
581			retv = -EADDRNOTAVAIL;
582			break;
583		}
584		if (optname == MCAST_BLOCK_SOURCE) {
585			omode = MCAST_EXCLUDE;
586			add = 1;
587		} else if (optname == MCAST_UNBLOCK_SOURCE) {
588			omode = MCAST_EXCLUDE;
589			add = 0;
590		} else if (optname == MCAST_JOIN_SOURCE_GROUP) {
591			struct sockaddr_in6 *psin6;
592
593			psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
594			retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
595				&psin6->sin6_addr);
596			/* prior join w/ different source is ok */
597			if (retv && retv != -EADDRINUSE)
598				break;
599			omode = MCAST_INCLUDE;
600			add = 1;
601		} else /* MCAST_LEAVE_SOURCE_GROUP */ {
602			omode = MCAST_INCLUDE;
603			add = 0;
604		}
605		retv = ip6_mc_source(add, omode, sk, &greqs);
606		break;
607	}
608	case MCAST_MSFILTER:
609	{
610		extern int sysctl_mld_max_msf;
611		struct group_filter *gsf;
612
613		if (optlen < GROUP_FILTER_SIZE(0))
614			goto e_inval;
615		if (optlen > sysctl_optmem_max) {
616			retv = -ENOBUFS;
617			break;
618		}
619		gsf = kmalloc(optlen,GFP_KERNEL);
620		if (!gsf) {
621			retv = -ENOBUFS;
622			break;
623		}
624		retv = -EFAULT;
625		if (copy_from_user(gsf, optval, optlen)) {
626			kfree(gsf);
627			break;
628		}
629		/* numsrc >= (4G-140)/128 overflow in 32 bits */
630		if (gsf->gf_numsrc >= 0x1ffffffU ||
631		    gsf->gf_numsrc > sysctl_mld_max_msf) {
632			kfree(gsf);
633			retv = -ENOBUFS;
634			break;
635		}
636		if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
637			kfree(gsf);
638			retv = -EINVAL;
639			break;
640		}
641		retv = ip6_mc_msfilter(sk, gsf);
642		kfree(gsf);
643
644		break;
645	}
646	case IPV6_ROUTER_ALERT:
647		if (optlen < sizeof(int))
648			goto e_inval;
649		retv = ip6_ra_control(sk, val);
650		break;
651	case IPV6_MTU_DISCOVER:
652		if (optlen < sizeof(int))
653			goto e_inval;
654		if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_PROBE)
655			goto e_inval;
656		np->pmtudisc = val;
657		retv = 0;
658		break;
659	case IPV6_MTU:
660		if (optlen < sizeof(int))
661			goto e_inval;
662		if (val && val < IPV6_MIN_MTU)
663			goto e_inval;
664		np->frag_size = val;
665		retv = 0;
666		break;
667	case IPV6_RECVERR:
668		if (optlen < sizeof(int))
669			goto e_inval;
670		np->recverr = valbool;
671		if (!val)
672			skb_queue_purge(&sk->sk_error_queue);
673		retv = 0;
674		break;
675	case IPV6_FLOWINFO_SEND:
676		if (optlen < sizeof(int))
677			goto e_inval;
678		np->sndflow = valbool;
679		retv = 0;
680		break;
681	case IPV6_FLOWLABEL_MGR:
682		retv = ipv6_flowlabel_opt(sk, optval, optlen);
683		break;
684	case IPV6_IPSEC_POLICY:
685	case IPV6_XFRM_POLICY:
686		retv = -EPERM;
687		if (!capable(CAP_NET_ADMIN))
688			break;
689		retv = xfrm_user_policy(sk, optname, optval, optlen);
690		break;
691
692	case IPV6_ADDR_PREFERENCES:
693	    {
694		unsigned int pref = 0;
695		unsigned int prefmask = ~0;
696
697		if (optlen < sizeof(int))
698			goto e_inval;
699
700		retv = -EINVAL;
701
702		/* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
703		switch (val & (IPV6_PREFER_SRC_PUBLIC|
704			       IPV6_PREFER_SRC_TMP|
705			       IPV6_PREFER_SRC_PUBTMP_DEFAULT)) {
706		case IPV6_PREFER_SRC_PUBLIC:
707			pref |= IPV6_PREFER_SRC_PUBLIC;
708			break;
709		case IPV6_PREFER_SRC_TMP:
710			pref |= IPV6_PREFER_SRC_TMP;
711			break;
712		case IPV6_PREFER_SRC_PUBTMP_DEFAULT:
713			break;
714		case 0:
715			goto pref_skip_pubtmp;
716		default:
717			goto e_inval;
718		}
719
720		prefmask &= ~(IPV6_PREFER_SRC_PUBLIC|
721			      IPV6_PREFER_SRC_TMP);
722pref_skip_pubtmp:
723
724		/* check HOME/COA conflicts */
725		switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) {
726		case IPV6_PREFER_SRC_HOME:
727			break;
728		case IPV6_PREFER_SRC_COA:
729			pref |= IPV6_PREFER_SRC_COA;
730		case 0:
731			goto pref_skip_coa;
732		default:
733			goto e_inval;
734		}
735
736		prefmask &= ~IPV6_PREFER_SRC_COA;
737pref_skip_coa:
738
739		/* check CGA/NONCGA conflicts */
740		switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) {
741		case IPV6_PREFER_SRC_CGA:
742		case IPV6_PREFER_SRC_NONCGA:
743		case 0:
744			break;
745		default:
746			goto e_inval;
747		}
748
749		np->srcprefs = (np->srcprefs & prefmask) | pref;
750		retv = 0;
751
752		break;
753	    }
754	case IPV6_MINHOPCOUNT:
755		if (optlen < sizeof(int))
756			goto e_inval;
757		if (val < 0 || val > 255)
758			goto e_inval;
759		np->min_hopcount = val;
760		break;
761	case IPV6_DONTFRAG:
762		np->dontfrag = valbool;
763		retv = 0;
764		break;
765	}
766
767	release_sock(sk);
768
769	return retv;
770
771e_inval:
772	release_sock(sk);
773	return -EINVAL;
774}
775
776int ipv6_setsockopt(struct sock *sk, int level, int optname,
777		    char __user *optval, unsigned int optlen)
778{
779	int err;
780
781	if (level == SOL_IP && sk->sk_type != SOCK_RAW)
782		return udp_prot.setsockopt(sk, level, optname, optval, optlen);
783
784	if (level != SOL_IPV6)
785		return -ENOPROTOOPT;
786
787	err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
788#ifdef CONFIG_NETFILTER
789	/* we need to exclude all possible ENOPROTOOPTs except default case */
790	if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
791			optname != IPV6_XFRM_POLICY) {
792		lock_sock(sk);
793		err = nf_setsockopt(sk, PF_INET6, optname, optval,
794				optlen);
795		release_sock(sk);
796	}
797#endif
798	return err;
799}
800
801EXPORT_SYMBOL(ipv6_setsockopt);
802
803#ifdef CONFIG_COMPAT
804int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
805			   char __user *optval, unsigned int optlen)
806{
807	int err;
808
809	if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
810		if (udp_prot.compat_setsockopt != NULL)
811			return udp_prot.compat_setsockopt(sk, level, optname,
812							  optval, optlen);
813		return udp_prot.setsockopt(sk, level, optname, optval, optlen);
814	}
815
816	if (level != SOL_IPV6)
817		return -ENOPROTOOPT;
818
819	if (optname >= MCAST_JOIN_GROUP && optname <= MCAST_MSFILTER)
820		return compat_mc_setsockopt(sk, level, optname, optval, optlen,
821			ipv6_setsockopt);
822
823	err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
824#ifdef CONFIG_NETFILTER
825	/* we need to exclude all possible ENOPROTOOPTs except default case */
826	if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY &&
827	    optname != IPV6_XFRM_POLICY) {
828		lock_sock(sk);
829		err = compat_nf_setsockopt(sk, PF_INET6, optname,
830					   optval, optlen);
831		release_sock(sk);
832	}
833#endif
834	return err;
835}
836
837EXPORT_SYMBOL(compat_ipv6_setsockopt);
838#endif
839
840static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
841				  int optname, char __user *optval, int len)
842{
843	struct ipv6_opt_hdr *hdr;
844
845	if (!opt)
846		return 0;
847
848	switch(optname) {
849	case IPV6_HOPOPTS:
850		hdr = opt->hopopt;
851		break;
852	case IPV6_RTHDRDSTOPTS:
853		hdr = opt->dst0opt;
854		break;
855	case IPV6_RTHDR:
856		hdr = (struct ipv6_opt_hdr *)opt->srcrt;
857		break;
858	case IPV6_DSTOPTS:
859		hdr = opt->dst1opt;
860		break;
861	default:
862		return -EINVAL;	/* should not happen */
863	}
864
865	if (!hdr)
866		return 0;
867
868	len = min_t(unsigned int, len, ipv6_optlen(hdr));
869	if (copy_to_user(optval, hdr, len))
870		return -EFAULT;
871	return len;
872}
873
874static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
875		    char __user *optval, int __user *optlen)
876{
877	struct ipv6_pinfo *np = inet6_sk(sk);
878	int len;
879	int val;
880
881	if (ip6_mroute_opt(optname))
882		return ip6_mroute_getsockopt(sk, optname, optval, optlen);
883
884	if (get_user(len, optlen))
885		return -EFAULT;
886	switch (optname) {
887	case IPV6_ADDRFORM:
888		if (sk->sk_protocol != IPPROTO_UDP &&
889		    sk->sk_protocol != IPPROTO_UDPLITE &&
890		    sk->sk_protocol != IPPROTO_TCP)
891			return -ENOPROTOOPT;
892		if (sk->sk_state != TCP_ESTABLISHED)
893			return -ENOTCONN;
894		val = sk->sk_family;
895		break;
896	case MCAST_MSFILTER:
897	{
898		struct group_filter gsf;
899		int err;
900
901		if (len < GROUP_FILTER_SIZE(0))
902			return -EINVAL;
903		if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0)))
904			return -EFAULT;
905		if (gsf.gf_group.ss_family != AF_INET6)
906			return -EADDRNOTAVAIL;
907		lock_sock(sk);
908		err = ip6_mc_msfget(sk, &gsf,
909			(struct group_filter __user *)optval, optlen);
910		release_sock(sk);
911		return err;
912	}
913
914	case IPV6_2292PKTOPTIONS:
915	{
916		struct msghdr msg;
917		struct sk_buff *skb;
918
919		if (sk->sk_type != SOCK_STREAM)
920			return -ENOPROTOOPT;
921
922		msg.msg_control = optval;
923		msg.msg_controllen = len;
924		msg.msg_flags = 0;
925
926		lock_sock(sk);
927		skb = np->pktoptions;
928		if (skb)
929			atomic_inc(&skb->users);
930		release_sock(sk);
931
932		if (skb) {
933			int err = datagram_recv_ctl(sk, &msg, skb);
934			kfree_skb(skb);
935			if (err)
936				return err;
937		} else {
938			if (np->rxopt.bits.rxinfo) {
939				struct in6_pktinfo src_info;
940				src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
941					np->sticky_pktinfo.ipi6_ifindex;
942				np->mcast_oif? ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr) :
943					ipv6_addr_copy(&src_info.ipi6_addr, &(np->sticky_pktinfo.ipi6_addr));
944				put_cmsg(&msg, SOL_IPV6, IPV6_PKTINFO, sizeof(src_info), &src_info);
945			}
946			if (np->rxopt.bits.rxhlim) {
947				int hlim = np->mcast_hops;
948				put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
949			}
950			if (np->rxopt.bits.rxoinfo) {
951				struct in6_pktinfo src_info;
952				src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
953					np->sticky_pktinfo.ipi6_ifindex;
954				np->mcast_oif? ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr) :
955					ipv6_addr_copy(&src_info.ipi6_addr, &(np->sticky_pktinfo.ipi6_addr));
956				put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info);
957			}
958			if (np->rxopt.bits.rxohlim) {
959				int hlim = np->mcast_hops;
960				put_cmsg(&msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim);
961			}
962		}
963		len -= msg.msg_controllen;
964		return put_user(len, optlen);
965	}
966	case IPV6_MTU:
967	{
968		struct dst_entry *dst;
969
970		val = 0;
971		rcu_read_lock();
972		dst = __sk_dst_get(sk);
973		if (dst)
974			val = dst_mtu(dst);
975		rcu_read_unlock();
976		if (!val)
977			return -ENOTCONN;
978		break;
979	}
980
981	case IPV6_V6ONLY:
982		val = np->ipv6only;
983		break;
984
985	case IPV6_RECVPKTINFO:
986		val = np->rxopt.bits.rxinfo;
987		break;
988
989	case IPV6_2292PKTINFO:
990		val = np->rxopt.bits.rxoinfo;
991		break;
992
993	case IPV6_RECVHOPLIMIT:
994		val = np->rxopt.bits.rxhlim;
995		break;
996
997	case IPV6_2292HOPLIMIT:
998		val = np->rxopt.bits.rxohlim;
999		break;
1000
1001	case IPV6_RECVRTHDR:
1002		val = np->rxopt.bits.srcrt;
1003		break;
1004
1005	case IPV6_2292RTHDR:
1006		val = np->rxopt.bits.osrcrt;
1007		break;
1008
1009	case IPV6_HOPOPTS:
1010	case IPV6_RTHDRDSTOPTS:
1011	case IPV6_RTHDR:
1012	case IPV6_DSTOPTS:
1013	{
1014
1015		lock_sock(sk);
1016		len = ipv6_getsockopt_sticky(sk, np->opt,
1017					     optname, optval, len);
1018		release_sock(sk);
1019		/* check if ipv6_getsockopt_sticky() returns err code */
1020		if (len < 0)
1021			return len;
1022		return put_user(len, optlen);
1023	}
1024
1025	case IPV6_RECVHOPOPTS:
1026		val = np->rxopt.bits.hopopts;
1027		break;
1028
1029	case IPV6_2292HOPOPTS:
1030		val = np->rxopt.bits.ohopopts;
1031		break;
1032
1033	case IPV6_RECVDSTOPTS:
1034		val = np->rxopt.bits.dstopts;
1035		break;
1036
1037	case IPV6_2292DSTOPTS:
1038		val = np->rxopt.bits.odstopts;
1039		break;
1040
1041	case IPV6_TCLASS:
1042		val = np->tclass;
1043		break;
1044
1045	case IPV6_RECVTCLASS:
1046		val = np->rxopt.bits.rxtclass;
1047		break;
1048
1049	case IPV6_FLOWINFO:
1050		val = np->rxopt.bits.rxflow;
1051		break;
1052
1053	case IPV6_RECVPATHMTU:
1054		val = np->rxopt.bits.rxpmtu;
1055		break;
1056
1057	case IPV6_PATHMTU:
1058	{
1059		struct dst_entry *dst;
1060		struct ip6_mtuinfo mtuinfo;
1061
1062		if (len < sizeof(mtuinfo))
1063			return -EINVAL;
1064
1065		len = sizeof(mtuinfo);
1066		memset(&mtuinfo, 0, sizeof(mtuinfo));
1067
1068		rcu_read_lock();
1069		dst = __sk_dst_get(sk);
1070		if (dst)
1071			mtuinfo.ip6m_mtu = dst_mtu(dst);
1072		rcu_read_unlock();
1073		if (!mtuinfo.ip6m_mtu)
1074			return -ENOTCONN;
1075
1076		if (put_user(len, optlen))
1077			return -EFAULT;
1078		if (copy_to_user(optval, &mtuinfo, len))
1079			return -EFAULT;
1080
1081		return 0;
1082		break;
1083	}
1084
1085	case IPV6_UNICAST_HOPS:
1086	case IPV6_MULTICAST_HOPS:
1087	{
1088		struct dst_entry *dst;
1089
1090		if (optname == IPV6_UNICAST_HOPS)
1091			val = np->hop_limit;
1092		else
1093			val = np->mcast_hops;
1094
1095		if (val < 0) {
1096			rcu_read_lock();
1097			dst = __sk_dst_get(sk);
1098			if (dst)
1099				val = ip6_dst_hoplimit(dst);
1100			rcu_read_unlock();
1101		}
1102
1103		if (val < 0)
1104			val = sock_net(sk)->ipv6.devconf_all->hop_limit;
1105		break;
1106	}
1107
1108	case IPV6_MULTICAST_LOOP:
1109		val = np->mc_loop;
1110		break;
1111
1112	case IPV6_MULTICAST_IF:
1113		val = np->mcast_oif;
1114		break;
1115
1116	case IPV6_MTU_DISCOVER:
1117		val = np->pmtudisc;
1118		break;
1119
1120	case IPV6_RECVERR:
1121		val = np->recverr;
1122		break;
1123
1124	case IPV6_FLOWINFO_SEND:
1125		val = np->sndflow;
1126		break;
1127
1128	case IPV6_ADDR_PREFERENCES:
1129		val = 0;
1130
1131		if (np->srcprefs & IPV6_PREFER_SRC_TMP)
1132			val |= IPV6_PREFER_SRC_TMP;
1133		else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC)
1134			val |= IPV6_PREFER_SRC_PUBLIC;
1135		else {
1136			val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT;
1137		}
1138
1139		if (np->srcprefs & IPV6_PREFER_SRC_COA)
1140			val |= IPV6_PREFER_SRC_COA;
1141		else
1142			val |= IPV6_PREFER_SRC_HOME;
1143		break;
1144
1145	case IPV6_MINHOPCOUNT:
1146		val = np->min_hopcount;
1147		break;
1148
1149	case IPV6_DONTFRAG:
1150		val = np->dontfrag;
1151		break;
1152
1153	default:
1154		return -ENOPROTOOPT;
1155	}
1156	len = min_t(unsigned int, sizeof(int), len);
1157	if(put_user(len, optlen))
1158		return -EFAULT;
1159	if(copy_to_user(optval,&val,len))
1160		return -EFAULT;
1161	return 0;
1162}
1163
1164int ipv6_getsockopt(struct sock *sk, int level, int optname,
1165		    char __user *optval, int __user *optlen)
1166{
1167	int err;
1168
1169	if (level == SOL_IP && sk->sk_type != SOCK_RAW)
1170		return udp_prot.getsockopt(sk, level, optname, optval, optlen);
1171
1172	if(level != SOL_IPV6)
1173		return -ENOPROTOOPT;
1174
1175	err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
1176#ifdef CONFIG_NETFILTER
1177	/* we need to exclude all possible ENOPROTOOPTs except default case */
1178	if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
1179		int len;
1180
1181		if (get_user(len, optlen))
1182			return -EFAULT;
1183
1184		lock_sock(sk);
1185		err = nf_getsockopt(sk, PF_INET6, optname, optval,
1186				&len);
1187		release_sock(sk);
1188		if (err >= 0)
1189			err = put_user(len, optlen);
1190	}
1191#endif
1192	return err;
1193}
1194
1195EXPORT_SYMBOL(ipv6_getsockopt);
1196
1197#ifdef CONFIG_COMPAT
1198int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
1199			   char __user *optval, int __user *optlen)
1200{
1201	int err;
1202
1203	if (level == SOL_IP && sk->sk_type != SOCK_RAW) {
1204		if (udp_prot.compat_getsockopt != NULL)
1205			return udp_prot.compat_getsockopt(sk, level, optname,
1206							  optval, optlen);
1207		return udp_prot.getsockopt(sk, level, optname, optval, optlen);
1208	}
1209
1210	if (level != SOL_IPV6)
1211		return -ENOPROTOOPT;
1212
1213	if (optname == MCAST_MSFILTER)
1214		return compat_mc_getsockopt(sk, level, optname, optval, optlen,
1215			ipv6_getsockopt);
1216
1217	err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
1218#ifdef CONFIG_NETFILTER
1219	/* we need to exclude all possible ENOPROTOOPTs except default case */
1220	if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
1221		int len;
1222
1223		if (get_user(len, optlen))
1224			return -EFAULT;
1225
1226		lock_sock(sk);
1227		err = compat_nf_getsockopt(sk, PF_INET6,
1228					   optname, optval, &len);
1229		release_sock(sk);
1230		if (err >= 0)
1231			err = put_user(len, optlen);
1232	}
1233#endif
1234	return err;
1235}
1236
1237EXPORT_SYMBOL(compat_ipv6_getsockopt);
1238#endif
1239