Unreachable code
File: net/ipv6/.tmp_ipv6_sockglue.o.preproc
Full description: The code is unreachable by any path. Superfluous semicolon, break or return statement.
Importance: 3
Checker: ReachabilityChecker
Trace:
This one is:
False positive index (the lower the better): 0
File contents (this file is distributed under the terms specified in the original file):
1|struct ip6_ra_chain *ip6_ra_chain;
2|rwlock_t ip6_ra_lock = (rwlock_t) { .raw_lock = { 0x01000000 }, .magic = 0xdeaf1eed, .owner = ((void *)-1L), .owner_cpu = -1, .dep_map = { .name = "ip6_ra_lock" } };
3|
4|int ip6_ra_control(struct sock *sk, int sel)
5|{
6| struct ip6_ra_chain *ra, *new_ra, **rap;
7|
8|
9| if (sk->sk_type != SOCK_RAW || inet_sk(sk)->inet_num != IPPROTO_RAW)
10| return -92;
11|
12| new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), __st_GFP_KERNEL_st__) : ((void *)0);
13|
14| __st_write_lock_bh_st__(&ip6_ra_lock);
15| for (rap = &ip6_ra_chain; (ra=*rap) != ((void *)0); rap = &ra->next) {
16| if (ra->sk == sk) {
17| if (sel>=0) {
18| __st_write_unlock_bh_st__(&ip6_ra_lock);
19| kfree(new_ra);
20| return -98;
21| }
22|
23| *rap = ra->next;
24| __st_write_unlock_bh_st__(&ip6_ra_lock);
25|
26| sock_put(sk);
27| kfree(ra);
28| return 0;
29| }
30| }
31| if (new_ra == ((void *)0)) {
32| __st_write_unlock_bh_st__(&ip6_ra_lock);
33| return -105;
34| }
35| new_ra->sk = sk;
36| new_ra->sel = sel;
37| new_ra->next = ra;
38| *rap = new_ra;
39| sock_hold(sk);
40| __st_write_unlock_bh_st__(&ip6_ra_lock);
41| return 0;
42|}
43|
44|static
45|struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
46| struct ipv6_txoptions *opt)
47|{
48| if (inet_sk(sk)->is_icsk) {
49| if (opt &&
50| !((1 << sk->__sk_common.skc_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
51| inet_sk(sk)->inet_daddr != (( __be32)(__builtin_constant_p((__u32)((0x7f000006))) ? ((__u32)( (((__u32)((0x7f000006)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0x7f000006)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0x7f000006)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0x7f000006)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0x7f000006))))) {
52| struct inet_connection_sock *icsk = inet_csk(sk);
53| icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen;
54| icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
55| }
56| opt = ({ __typeof(*((&inet6_sk(sk)->opt))) __x = ((opt)); switch (sizeof(*&inet6_sk(sk)->opt)) { case 1: { volatile u8 *__ptr = (volatile u8 *)((&inet6_sk(sk)->opt)); asm volatile("xchgb %0,%1" : "=q" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 2: { volatile u16 *__ptr = (volatile u16 *)((&inet6_sk(sk)->opt)); asm volatile("xchgw %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 4: { volatile u32 *__ptr = (volatile u32 *)((&inet6_sk(sk)->opt)); asm volatile("xchgl %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 8: { volatile u64 *__ptr = (volatile u64 *)((&inet6_sk(sk)->opt)); asm volatile("xchgq %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } default: __xchg_wrong_size(); } __x; });
57| } else {
58| __st_spin_lock_st__(&sk->sk_dst_lock);
59| opt = ({ __typeof(*((&inet6_sk(sk)->opt))) __x = ((opt)); switch (sizeof(*&inet6_sk(sk)->opt)) { case 1: { volatile u8 *__ptr = (volatile u8 *)((&inet6_sk(sk)->opt)); asm volatile("xchgb %0,%1" : "=q" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 2: { volatile u16 *__ptr = (volatile u16 *)((&inet6_sk(sk)->opt)); asm volatile("xchgw %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 4: { volatile u32 *__ptr = (volatile u32 *)((&inet6_sk(sk)->opt)); asm volatile("xchgl %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 8: { volatile u64 *__ptr = (volatile u64 *)((&inet6_sk(sk)->opt)); asm volatile("xchgq %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } default: __xchg_wrong_size(); } __x; });
60| __st_spin_unlock_st__(&sk->sk_dst_lock);
61| }
62| sk_dst_reset(sk);
63|
64| return opt;
65|}
66|
67|static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
68| char *optval, unsigned int optlen)
69|{
70| struct ipv6_pinfo *np = inet6_sk(sk);
71| struct net *net = sock_net(sk);
72| int val, valbool;
73| int retv = -92;
74|
75| if (optval == ((void *)0))
76| val=0;
77| else {
78| if (optlen >= sizeof(int)) {
79| if (__st_get_user_st__(val, (int *) optval))
80| return -14;
81| } else
82| val = 0;
83| }
84|
85| valbool = (val!=0);
86|
87| if (ip6_mroute_opt(optname))
88| return ip6_mroute_setsockopt(sk, optname, optval, optlen);
89|
90| lock_sock(sk);
91|
92| switch (optname) {
93|
94| case 1:
95| if (optlen < sizeof(int))
96| goto e_inval;
97| if (val == 2) {
98| struct ipv6_txoptions *opt;
99| struct sk_buff *pktopt;
100|
101| if (sk->sk_type == SOCK_RAW)
102| break;
103|
104| if (sk->sk_protocol == IPPROTO_UDP ||
105| sk->sk_protocol == IPPROTO_UDPLITE) {
106| struct udp_sock *up = udp_sk(sk);
107| if (up->pending == 10) {
108| retv = -16;
109| break;
110| }
111| } else if (sk->sk_protocol != IPPROTO_TCP)
112| break;
113|
114| if (sk->__sk_common.skc_state != TCP_ESTABLISHED) {
115| retv = -107;
116| break;
117| }
118|
119| if (((sk)->__sk_common.skc_family == 10 && (inet6_sk(sk)->ipv6only)) ||
120| !ipv6_addr_v4mapped(&np->daddr)) {
121| retv = -99;
122| break;
123| }
124|
125| fl6_free_socklist(sk);
126| ipv6_sock_mc_close(sk);
127|
128|
129|
130|
131|
132|
133| do { } while (0);
134|
135| if (sk->sk_protocol == IPPROTO_TCP) {
136| struct inet_connection_sock *icsk = inet_csk(sk);
137| local_bh_disable();
138| sock_prot_inuse_add(net, sk->__sk_common.skc_prot, -1);
139| sock_prot_inuse_add(net, &tcp_prot, 1);
140| local_bh_enable();
141| sk->__sk_common.skc_prot = &tcp_prot;
142| icsk->icsk_af_ops = &ipv4_specific;
143| sk->sk_socket->ops = &inet_stream_ops;
144| sk->__sk_common.skc_family = 2;
145| tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
146| } else {
147| struct proto *prot = &udp_prot;
148|
149| if (sk->sk_protocol == IPPROTO_UDPLITE)
150| prot = &udplite_prot;
151| local_bh_disable();
152| sock_prot_inuse_add(net, sk->__sk_common.skc_prot, -1);
153| sock_prot_inuse_add(net, prot, 1);
154| local_bh_enable();
155| sk->__sk_common.skc_prot = prot;
156| sk->sk_socket->ops = &inet_dgram_ops;
157| sk->__sk_common.skc_family = 2;
158| }
159| opt = ({ __typeof(*((&np->opt))) __x = ((((void *)0))); switch (sizeof(*&np->opt)) { case 1: { volatile u8 *__ptr = (volatile u8 *)((&np->opt)); asm volatile("xchgb %0,%1" : "=q" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 2: { volatile u16 *__ptr = (volatile u16 *)((&np->opt)); asm volatile("xchgw %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 4: { volatile u32 *__ptr = (volatile u32 *)((&np->opt)); asm volatile("xchgl %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 8: { volatile u64 *__ptr = (volatile u64 *)((&np->opt)); asm volatile("xchgq %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } default: __xchg_wrong_size(); } __x; });
160| if (opt)
161| sock_kfree_s(sk, opt, opt->tot_len);
162| pktopt = ({ __typeof(*((&np->pktoptions))) __x = ((((void *)0))); switch (sizeof(*&np->pktoptions)) { case 1: { volatile u8 *__ptr = (volatile u8 *)((&np->pktoptions)); asm volatile("xchgb %0,%1" : "=q" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 2: { volatile u16 *__ptr = (volatile u16 *)((&np->pktoptions)); asm volatile("xchgw %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 4: { volatile u32 *__ptr = (volatile u32 *)((&np->pktoptions)); asm volatile("xchgl %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } case 8: { volatile u64 *__ptr = (volatile u64 *)((&np->pktoptions)); asm volatile("xchgq %0,%1" : "=r" (__x), "+m" (*__ptr) : "0" (__x) : "memory"); break; } default: __xchg_wrong_size(); } __x; });
163| kfree_skb(pktopt);
164|
165| sk->sk_destruct = inet_sock_destruct;
166|
167|
168|
169|
170| do { } while (0);
171| module_put((&__this_module));
172| retv = 0;
173| break;
174| }
175| goto e_inval;
176|
177| case 26:
178| if (optlen < sizeof(int) ||
179| inet_sk(sk)->inet_num)
180| goto e_inval;
181| np->ipv6only = valbool;
182| retv = 0;
183| break;
184|
185| case 49:
186| if (optlen < sizeof(int))
187| goto e_inval;
188| np->rxopt.bits.rxinfo = valbool;
189| retv = 0;
190| break;
191|
192| case 2:
193| if (optlen < sizeof(int))
194| goto e_inval;
195| np->rxopt.bits.rxoinfo = valbool;
196| retv = 0;
197| break;
198|
199| case 51:
200| if (optlen < sizeof(int))
201| goto e_inval;
202| np->rxopt.bits.rxhlim = valbool;
203| retv = 0;
204| break;
205|
206| case 8:
207| if (optlen < sizeof(int))
208| goto e_inval;
209| np->rxopt.bits.rxohlim = valbool;
210| retv = 0;
211| break;
212|
213| case 56:
214| if (optlen < sizeof(int))
215| goto e_inval;
216| np->rxopt.bits.srcrt = valbool;
217| retv = 0;
218| break;
219|
220| case 5:
221| if (optlen < sizeof(int))
222| goto e_inval;
223| np->rxopt.bits.osrcrt = valbool;
224| retv = 0;
225| break;
226|
227| case 53:
228| if (optlen < sizeof(int))
229| goto e_inval;
230| np->rxopt.bits.hopopts = valbool;
231| retv = 0;
232| break;
233|
234| case 3:
235| if (optlen < sizeof(int))
236| goto e_inval;
237| np->rxopt.bits.ohopopts = valbool;
238| retv = 0;
239| break;
240|
241| case 58:
242| if (optlen < sizeof(int))
243| goto e_inval;
244| np->rxopt.bits.dstopts = valbool;
245| retv = 0;
246| break;
247|
248| case 4:
249| if (optlen < sizeof(int))
250| goto e_inval;
251| np->rxopt.bits.odstopts = valbool;
252| retv = 0;
253| break;
254|
255| case 67:
256| if (optlen < sizeof(int))
257| goto e_inval;
258| if (val < -1 || val > 0xff)
259| goto e_inval;
260|
261| if (val == -1)
262| val = 0;
263| np->tclass = val;
264| retv = 0;
265| break;
266|
267| case 66:
268| if (optlen < sizeof(int))
269| goto e_inval;
270| np->rxopt.bits.rxtclass = valbool;
271| retv = 0;
272| break;
273|
274| case 11:
275| if (optlen < sizeof(int))
276| goto e_inval;
277| np->rxopt.bits.rxflow = valbool;
278| retv = 0;
279| break;
280|
281| case 60:
282| if (optlen < sizeof(int))
283| goto e_inval;
284| np->rxopt.bits.rxpmtu = valbool;
285| retv = 0;
286| break;
287|
288| case 75:
289| if (!capable(12)) {
290| retv = -1;
291| break;
292| }
293| if (optlen < sizeof(int))
294| goto e_inval;
295|
296| inet_sk(sk)->transparent = valbool;
297| retv = 0;
298| break;
299|
300| case 74:
301| if (optlen < sizeof(int))
302| goto e_inval;
303| np->rxopt.bits.rxorigdstaddr = valbool;
304| retv = 0;
305| break;
306|
307| case 54:
308| case 55:
309| case 57:
310| case 59:
311| {
312| struct ipv6_txoptions *opt;
313|
314|
315|
316|
317| if (optlen == 0)
318| optval = ((void *)0);
319| else if (optval == ((void *)0))
320| goto e_inval;
321| else if (optlen < sizeof(struct ipv6_opt_hdr) ||
322| optlen & 0x7 || optlen > 8 * 255)
323| goto e_inval;
324|
325|
326| retv = -1;
327| if (optname != 57 && !capable(13))
328| break;
329|
330| opt = ipv6_renew_options(sk, np->opt, optname,
331| (struct ipv6_opt_hdr *)optval,
332| optlen);
333| if (IS_ERR(opt)) {
334| retv = PTR_ERR(opt);
335| break;
336| }
337|
338|
339| retv = -22;
340| if (optname == 57 && opt && opt->srcrt) {
341| struct ipv6_rt_hdr *rthdr = opt->srcrt;
342| switch (rthdr->type) {
343|
344| case 2:
345| if (rthdr->hdrlen != 2 ||
346| rthdr->segments_left != 1)
347| goto sticky_done;
348|
349| break;
350|
351| default:
352| goto sticky_done;
353| }
354| }
355|
356| retv = 0;
357| opt = ipv6_update_options(sk, opt);
358|sticky_done:
359| if (opt)
360| sock_kfree_s(sk, opt, opt->tot_len);
361| break;
362| }
363|
364| case 50:
365| {
366| struct in6_pktinfo pkt;
367|
368| if (optlen == 0)
369| goto e_inval;
370| else if (optlen < sizeof(struct in6_pktinfo) || optval == ((void *)0))
371| goto e_inval;
372|
373| if (copy_from_user(&pkt, optval, sizeof(struct in6_pktinfo))) {
374| retv = -14;
375| break;
376| }
377| if (sk->__sk_common.skc_bound_dev_if && pkt.ipi6_ifindex != sk->__sk_common.skc_bound_dev_if)
378| goto e_inval;
379|
380| np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex;
381| ipv6_addr_copy(&np->sticky_pktinfo.ipi6_addr, &pkt.ipi6_addr);
382| retv = 0;
383| break;
384| }
385|
386| case 6:
387| {
388| struct ipv6_txoptions *opt = ((void *)0);
389| struct msghdr msg;
390| struct flowi fl;
391| int junk;
392|
393| fl.nl_u.ip6_u.flowlabel = 0;
394| fl.oif = sk->__sk_common.skc_bound_dev_if;
395| fl.mark = sk->sk_mark;
396|
397| if (optlen == 0)
398| goto update;
399|
400|
401|
402|
403| retv = -22;
404| if (optlen > 64*1024)
405| break;
406|
407| opt = sock_kmalloc(sk, sizeof(*opt) + optlen, __st_GFP_KERNEL_st__);
408| retv = -105;
409| if (opt == ((void *)0))
410| break;
411|
412| __st_memset_st__(opt, 0, sizeof(*opt));
413| opt->tot_len = sizeof(*opt) + optlen;
414| retv = -14;
415| if (copy_from_user(opt+1, optval, optlen))
416| goto done;
417|
418| msg.msg_controllen = optlen;
419| msg.msg_control = (void*)(opt+1);
420|
421| retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk,
422| &junk);
423| if (retv)
424| goto done;
425|update:
426| retv = 0;
427| opt = ipv6_update_options(sk, opt);
428|done:
429| if (opt)
430| sock_kfree_s(sk, opt, opt->tot_len);
431| break;
432| }
433| case 16:
434| if (optlen < sizeof(int))
435| goto e_inval;
436| if (val > 255 || val < -1)
437| goto e_inval;
438| np->hop_limit = val;
439| retv = 0;
440| break;
441|
442| case 18:
443| if (sk->sk_type == SOCK_STREAM)
444| break;
445| if (optlen < sizeof(int))
446| goto e_inval;
447| if (val > 255 || val < -1)
448| goto e_inval;
449| np->mcast_hops = val;
450| retv = 0;
451| break;
452|
453| case 19:
454| if (optlen < sizeof(int))
455| goto e_inval;
456| if (val != valbool)
457| goto e_inval;
458| np->mc_loop = valbool;
459| retv = 0;
460| break;
461|
462| case 17:
463| if (sk->sk_type == SOCK_STREAM)
464| break;
465| if (optlen < sizeof(int))
466| goto e_inval;
467|
468| if (val) {
469| struct net_device *dev;
470|
471| if (sk->__sk_common.skc_bound_dev_if && sk->__sk_common.skc_bound_dev_if != val)
472| goto e_inval;
473|
474| dev = dev_get_by_index(net, val);
475| if (!dev) {
476| retv = -19;
477| break;
478| }
479| dev_put(dev);
480| }
481| np->mcast_oif = val;
482| retv = 0;
483| break;
484| case 20:
485| case 21:
486| {
487| struct ipv6_mreq mreq;
488|
489| if (optlen < sizeof(struct ipv6_mreq))
490| goto e_inval;
491|
492| retv = -71;
493| if (inet_sk(sk)->is_icsk)
494| break;
495|
496| retv = -14;
497| if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
498| break;
499|
500| if (optname == 20)
501| retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
502| else
503| retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
504| break;
505| }
506| case 27:
507| case 28:
508| {
509| struct ipv6_mreq mreq;
510|
511| if (optlen < sizeof(struct ipv6_mreq))
512| goto e_inval;
513|
514| retv = -14;
515| if (copy_from_user(&mreq, optval, sizeof(struct ipv6_mreq)))
516| break;
517|
518| if (optname == 27)
519| retv = ipv6_sock_ac_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
520| else
521| retv = ipv6_sock_ac_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
522| break;
523| }
524| case 42:
525| case 45:
526| {
527| struct group_req greq;
528| struct sockaddr_in6 *psin6;
529|
530| if (optlen < sizeof(struct group_req))
531| goto e_inval;
532|
533| retv = -14;
534| if (copy_from_user(&greq, optval, sizeof(struct group_req)))
535| break;
536| if (greq.gr_group.ss_family != 10) {
537| retv = -99;
538| break;
539| }
540| psin6 = (struct sockaddr_in6 *)&greq.gr_group;
541| if (optname == 42)
542| retv = ipv6_sock_mc_join(sk, greq.gr_interface,
543| &psin6->sin6_addr);
544| else
545| retv = ipv6_sock_mc_drop(sk, greq.gr_interface,
546| &psin6->sin6_addr);
547| break;
548| }
549| case 46:
550| case 47:
551| case 43:
552| case 44:
553| {
554| struct group_source_req greqs;
555| int omode, add;
556|
557| if (optlen < sizeof(struct group_source_req))
558| goto e_inval;
559| if (copy_from_user(&greqs, optval, sizeof(greqs))) {
560| retv = -14;
561| break;
562| }
563| if (greqs.gsr_group.ss_family != 10 ||
564| greqs.gsr_source.ss_family != 10) {
565| retv = -99;
566| break;
567| }
568| if (optname == 43) {
569| omode = 0;
570| add = 1;
571| } else if (optname == 44) {
572| omode = 0;
573| add = 0;
574| } else if (optname == 46) {
575| struct sockaddr_in6 *psin6;
576|
577| psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
578| retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
579| &psin6->sin6_addr);
580|
581| if (retv && retv != -98)
582| break;
583| omode = 1;
584| add = 1;
585| } else {
586| omode = 1;
587| add = 0;
588| }
589| retv = ip6_mc_source(add, omode, sk, &greqs);
590| break;
591| }
592| case 48:
593| {
594| extern int sysctl_mld_max_msf;
595| struct group_filter *gsf;
596|
597| if (optlen < (sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) + (0) * sizeof(struct __kernel_sockaddr_storage)))
598| goto e_inval;
599| if (optlen > sysctl_optmem_max) {
600| retv = -105;
601| break;
602| }
603| gsf = kmalloc(optlen,__st_GFP_KERNEL_st__);
604| if (!gsf) {
605| retv = -105;
606| break;
607| }
608| retv = -14;
609| if (copy_from_user(gsf, optval, optlen)) {
610| kfree(gsf);
611| break;
612| }
613|
614| if (gsf->gf_numsrc >= 0x1ffffffU ||
615| gsf->gf_numsrc > sysctl_mld_max_msf) {
616| kfree(gsf);
617| retv = -105;
618| break;
619| }
620| if ((sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) + (gsf->gf_numsrc) * sizeof(struct __kernel_sockaddr_storage)) > optlen) {
621| kfree(gsf);
622| retv = -22;
623| break;
624| }
625| retv = ip6_mc_msfilter(sk, gsf);
626| kfree(gsf);
627|
628| break;
629| }
630| case 22:
631| if (optlen < sizeof(int))
632| goto e_inval;
633| retv = ip6_ra_control(sk, val);
634| break;
635| case 23:
636| if (optlen < sizeof(int))
637| goto e_inval;
638| if (val < 0 || val > 3)
639| goto e_inval;
640| np->pmtudisc = val;
641| retv = 0;
642| break;
643| case 24:
644| if (optlen < sizeof(int))
645| goto e_inval;
646| if (val && val < 1280)
647| goto e_inval;
648| np->frag_size = val;
649| retv = 0;
650| break;
651| case 25:
652| if (optlen < sizeof(int))
653| goto e_inval;
654| np->recverr = valbool;
655| if (!val)
656| skb_queue_purge(&sk->sk_error_queue);
657| retv = 0;
658| break;
659| case 33:
660| if (optlen < sizeof(int))
661| goto e_inval;
662| np->sndflow = valbool;
663| retv = 0;
664| break;
665| case 32:
666| retv = ipv6_flowlabel_opt(sk, optval, optlen);
667| break;
668| case 34:
669| case 35:
670| retv = -1;
671| if (!capable(12))
672| break;
673| retv = xfrm_user_policy(sk, optname, optval, optlen);
674| break;
675|
676| case 72:
677| {
678| unsigned int pref = 0;
679| unsigned int prefmask = ~0;
680|
681| if (optlen < sizeof(int))
682| goto e_inval;
683|
684| retv = -22;
685|
686|
687| switch (val & (0x0002|
688| 0x0001|
689| 0x0100)) {
690| case 0x0002:
691| pref |= 0x0002;
692| break;
693| case 0x0001:
694| pref |= 0x0001;
695| break;
696| case 0x0100:
697| break;
698| case 0:
699| goto pref_skip_pubtmp;
700| default:
701| goto e_inval;
702| }
703|
704| prefmask &= ~(0x0002|
705| 0x0001);
706|pref_skip_pubtmp:
707|
708|
709| switch (val & (0x0400|0x0004)) {
710| case 0x0400:
711| break;
712| case 0x0004:
713| pref |= 0x0004;
714| case 0:
715| goto pref_skip_coa;
716| default:
717| goto e_inval;
718| }
719|
720| prefmask &= ~0x0004;
721|pref_skip_coa:
722|
723|
724| switch (val & (0x0008|0x0800)) {
725| case 0x0008:
726| case 0x0800:
727| case 0:
728| break;
729| default:
730| goto e_inval;
731| }
732|
733| np->srcprefs = (np->srcprefs & prefmask) | pref;
734| retv = 0;
735|
736| break;
737| }
738| case 73:
739| if (optlen < sizeof(int))
740| goto e_inval;
741| if (val < 0 || val > 255)
742| goto e_inval;
743| np->min_hopcount = val;
744| break;
745| case 62:
746| np->dontfrag = valbool;
747| retv = 0;
748| break;
749| }
750|
751| release_sock(sk);
752|
753| return retv;
754|
755|e_inval:
756| release_sock(sk);
757| return -22;
758|}
759|
760|int ipv6_setsockopt(struct sock *sk, int level, int optname,
761| char *optval, unsigned int optlen)
762|{
763| int err;
764|
765| if (level == 0 && sk->sk_type != SOCK_RAW)
766| return udp_prot.setsockopt(sk, level, optname, optval, optlen);
767|
768| if (level != 41)
769| return -92;
770|
771| err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
772|
773|
774| if (err == -92 && optname != 34 &&
775| optname != 35) {
776| lock_sock(sk);
777| err = nf_setsockopt(sk, 10, optname, optval,
778| optlen);
779| release_sock(sk);
780| }
781|
782| return err;
783|}
784|
785|extern typeof(ipv6_setsockopt) ipv6_setsockopt; extern void *__crc_ipv6_setsockopt ; static const unsigned long __kcrctab_ipv6_setsockopt = (unsigned long) &__crc_ipv6_setsockopt; static const char __kstrtab_ipv6_setsockopt[] = "" "ipv6_setsockopt"; static const struct kernel_symbol __ksymtab_ipv6_setsockopt = { (unsigned long)&ipv6_setsockopt, __kstrtab_ipv6_setsockopt };
786|
787|
788|int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
789| char *optval, unsigned int optlen)
790|{
791| int err;
792|
793| if (level == 0 && sk->sk_type != SOCK_RAW) {
794| if (udp_prot.compat_setsockopt != ((void *)0))
795| return udp_prot.compat_setsockopt(sk, level, optname,
796| optval, optlen);
797| return udp_prot.setsockopt(sk, level, optname, optval, optlen);
798| }
799|
800| if (level != 41)
801| return -92;
802|
803| if (optname >= 42 && optname <= 48)
804| return compat_mc_setsockopt(sk, level, optname, optval, optlen,
805| ipv6_setsockopt);
806|
807| err = do_ipv6_setsockopt(sk, level, optname, optval, optlen);
808|
809|
810| if (err == -92 && optname != 34 &&
811| optname != 35) {
812| lock_sock(sk);
813| err = compat_nf_setsockopt(sk, 10, optname,
814| optval, optlen);
815| release_sock(sk);
816| }
817|
818| return err;
819|}
820|
821|extern typeof(compat_ipv6_setsockopt) compat_ipv6_setsockopt; extern void *__crc_compat_ipv6_setsockopt ; static const unsigned long __kcrctab_compat_ipv6_setsockopt = (unsigned long) &__crc_compat_ipv6_setsockopt; static const char __kstrtab_compat_ipv6_setsockopt[] = "" "compat_ipv6_setsockopt"; static const struct kernel_symbol __ksymtab_compat_ipv6_setsockopt = { (unsigned long)&compat_ipv6_setsockopt, __kstrtab_compat_ipv6_setsockopt };
822|
823|
824|static int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_txoptions *opt,
825| int optname, char *optval, int len)
826|{
827| struct ipv6_opt_hdr *hdr;
828|
829| if (!opt)
830| return 0;
831|
832| switch(optname) {
833| case 54:
834| hdr = opt->hopopt;
835| break;
836| case 55:
837| hdr = opt->dst0opt;
838| break;
839| case 57:
840| hdr = (struct ipv6_opt_hdr *)opt->srcrt;
841| break;
842| case 59:
843| hdr = opt->dst1opt;
844| break;
845| default:
846| return -22;
847| }
848|
849| if (!hdr)
850| return 0;
851|
852| len = ({ unsigned int __min1 = (len); unsigned int __min2 = ((((hdr)->hdrlen+1) << 3)); __min1 < __min2 ? __min1: __min2; });
853| if (copy_to_user(optval, hdr, len))
854| return -14;
855| return len;
856|}
857|
858|static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
859| char *optval, int *optlen)
860|{
861| struct ipv6_pinfo *np = inet6_sk(sk);
862| int len;
863| int val;
864|
865| if (ip6_mroute_opt(optname))
866| return ip6_mroute_getsockopt(sk, optname, optval, optlen);
867|
868| if (__st_get_user_st__(len, optlen))
869| return -14;
870| switch (optname) {
871| case 1:
872| if (sk->sk_protocol != IPPROTO_UDP &&
873| sk->sk_protocol != IPPROTO_UDPLITE &&
874| sk->sk_protocol != IPPROTO_TCP)
875| return -92;
876| if (sk->__sk_common.skc_state != TCP_ESTABLISHED)
877| return -107;
878| val = sk->__sk_common.skc_family;
879| break;
880| case 48:
881| {
882| struct group_filter gsf;
883| int err;
884|
885| if (len < (sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) + (0) * sizeof(struct __kernel_sockaddr_storage)))
886| return -22;
887| if (copy_from_user(&gsf, optval, (sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) + (0) * sizeof(struct __kernel_sockaddr_storage))))
888| return -14;
889| if (gsf.gf_group.ss_family != 10)
890| return -99;
891| lock_sock(sk);
892| err = ip6_mc_msfget(sk, &gsf,
893| (struct group_filter *)optval, optlen);
894| release_sock(sk);
895| return err;
896| }
897|
898| case 6:
899| {
900| struct msghdr msg;
901| struct sk_buff *skb;
902|
903| if (sk->sk_type != SOCK_STREAM)
904| return -92;
905|
906| msg.msg_control = optval;
907| msg.msg_controllen = len;
908| msg.msg_flags = 0;
909|
910| lock_sock(sk);
911| skb = np->pktoptions;
912| if (skb)
913| atomic_inc(&skb->users);
914| release_sock(sk);
915|
916| if (skb) {
917| int err = datagram_recv_ctl(sk, &msg, skb);
918| kfree_skb(skb);
919| if (err)
920| return err;
921| } else {
922| if (np->rxopt.bits.rxinfo) {
923| struct in6_pktinfo src_info;
924| src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
925| np->sticky_pktinfo.ipi6_ifindex;
926| np->mcast_oif? ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr) :
927| ipv6_addr_copy(&src_info.ipi6_addr, &(np->sticky_pktinfo.ipi6_addr));
928| put_cmsg(&msg, 41, 50, sizeof(src_info), &src_info);
929| }
930| if (np->rxopt.bits.rxhlim) {
931| int hlim = np->mcast_hops;
932| put_cmsg(&msg, 41, 52, sizeof(hlim), &hlim);
933| }
934| if (np->rxopt.bits.rxoinfo) {
935| struct in6_pktinfo src_info;
936| src_info.ipi6_ifindex = np->mcast_oif ? np->mcast_oif :
937| np->sticky_pktinfo.ipi6_ifindex;
938| np->mcast_oif? ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr) :
939| ipv6_addr_copy(&src_info.ipi6_addr, &(np->sticky_pktinfo.ipi6_addr));
940| put_cmsg(&msg, 41, 2, sizeof(src_info), &src_info);
941| }
942| if (np->rxopt.bits.rxohlim) {
943| int hlim = np->mcast_hops;
944| put_cmsg(&msg, 41, 8, sizeof(hlim), &hlim);
945| }
946| }
947| len -= msg.msg_controllen;
948| return __st_put_user_st__(len, optlen);
949| }
950| case 24:
951| {
952| struct dst_entry *dst;
953|
954| val = 0;
955| __st_rcu_read_lock_st__();
956| dst = __sk_dst_get(sk);
957| if (dst)
958| val = dst_mtu(dst);
959| __st_rcu_read_unlock_st__();
960| if (!val)
961| return -107;
962| break;
963| }
964|
965| case 26:
966| val = np->ipv6only;
967| break;
968|
969| case 49:
970| val = np->rxopt.bits.rxinfo;
971| break;
972|
973| case 2:
974| val = np->rxopt.bits.rxoinfo;
975| break;
976|
977| case 51:
978| val = np->rxopt.bits.rxhlim;
979| break;
980|
981| case 8:
982| val = np->rxopt.bits.rxohlim;
983| break;
984|
985| case 56:
986| val = np->rxopt.bits.srcrt;
987| break;
988|
989| case 5:
990| val = np->rxopt.bits.osrcrt;
991| break;
992|
993| case 54:
994| case 55:
995| case 57:
996| case 59:
997| {
998|
999| lock_sock(sk);
1000| len = ipv6_getsockopt_sticky(sk, np->opt,
1001| optname, optval, len);
1002| release_sock(sk);
1003|
1004| if (len < 0)
1005| return len;
1006| return __st_put_user_st__(len, optlen);
1007| }
1008|
1009| case 53:
1010| val = np->rxopt.bits.hopopts;
1011| break;
1012|
1013| case 3:
1014| val = np->rxopt.bits.ohopopts;
1015| break;
1016|
1017| case 58:
1018| val = np->rxopt.bits.dstopts;
1019| break;
1020|
1021| case 4:
1022| val = np->rxopt.bits.odstopts;
1023| break;
1024|
1025| case 67:
1026| val = np->tclass;
1027| break;
1028|
1029| case 66:
1030| val = np->rxopt.bits.rxtclass;
1031| break;
1032|
1033| case 11:
1034| val = np->rxopt.bits.rxflow;
1035| break;
1036|
1037| case 60:
1038| val = np->rxopt.bits.rxpmtu;
1039| break;
1040|
1041| case 61:
1042| {
1043| struct dst_entry *dst;
1044| struct ip6_mtuinfo mtuinfo;
1045|
1046| if (len < sizeof(mtuinfo))
1047| return -22;
1048|
1049| len = sizeof(mtuinfo);
1050| __st_memset_st__(&mtuinfo, 0, sizeof(mtuinfo));
1051|
1052| __st_rcu_read_lock_st__();
1053| dst = __sk_dst_get(sk);
1054| if (dst)
1055| mtuinfo.ip6m_mtu = dst_mtu(dst);
1056| __st_rcu_read_unlock_st__();
1057| if (!mtuinfo.ip6m_mtu)
1058| return -107;
1059|
1060| if (__st_put_user_st__(len, optlen))
1061| return -14;
1062| if (copy_to_user(optval, &mtuinfo, len))
1063| return -14;
1064|
1065| return 0;
1066| break;
|This node is unreachable prev next
1067| }
1068|
1069| case 75:
1070| val = inet_sk(sk)->transparent;
1071| break;
1072|
1073| case 74:
1074| val = np->rxopt.bits.rxorigdstaddr;
1075| break;
1076|
1077| case 16:
1078| case 18:
1079| {
1080| struct dst_entry *dst;
1081|
1082| if (optname == 16)
1083| val = np->hop_limit;
1084| else
1085| val = np->mcast_hops;
1086|
1087| if (val < 0) {
1088| __st_rcu_read_lock_st__();
1089| dst = __sk_dst_get(sk);
1090| if (dst)
1091| val = ip6_dst_hoplimit(dst);
1092| __st_rcu_read_unlock_st__();
1093| }
1094|
1095| if (val < 0)
1096| val = sock_net(sk)->ipv6.devconf_all->hop_limit;
1097| break;
1098| }
1099|
1100| case 19:
1101| val = np->mc_loop;
1102| break;
1103|
1104| case 17:
1105| val = np->mcast_oif;
1106| break;
1107|
1108| case 23:
1109| val = np->pmtudisc;
1110| break;
1111|
1112| case 25:
1113| val = np->recverr;
1114| break;
1115|
1116| case 33:
1117| val = np->sndflow;
1118| break;
1119|
1120| case 72:
1121| val = 0;
1122|
1123| if (np->srcprefs & 0x0001)
1124| val |= 0x0001;
1125| else if (np->srcprefs & 0x0002)
1126| val |= 0x0002;
1127| else {
1128|
1129| val |= 0x0100;
1130| }
1131|
1132| if (np->srcprefs & 0x0004)
1133| val |= 0x0004;
1134| else
1135| val |= 0x0400;
1136| break;
1137|
1138| case 73:
1139| val = np->min_hopcount;
1140| break;
1141|
1142| case 62:
1143| val = np->dontfrag;
1144| break;
1145|
1146| default:
1147| return -92;
1148| }
1149| len = ({ unsigned int __min1 = (sizeof(int)); unsigned int __min2 = (len); __min1 < __min2 ? __min1: __min2; });
1150| if(__st_put_user_st__(len, optlen))
1151| return -14;
1152| if(copy_to_user(optval,&val,len))
1153| return -14;
1154| return 0;
1155|}
1156|
1157|int ipv6_getsockopt(struct sock *sk, int level, int optname,
1158| char *optval, int *optlen)
1159|{
1160| int err;
1161|
1162| if (level == 0 && sk->sk_type != SOCK_RAW)
1163| return udp_prot.getsockopt(sk, level, optname, optval, optlen);
1164|
1165| if(level != 41)
1166| return -92;
1167|
1168| err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
1169|
1170|
1171| if (err == -92 && optname != 6) {
1172| int len;
1173|
1174| if (__st_get_user_st__(len, optlen))
1175| return -14;
1176|
1177| lock_sock(sk);
1178| err = nf_getsockopt(sk, 10, optname, optval,
1179| &len);
1180| release_sock(sk);
1181| if (err >= 0)
1182| err = __st_put_user_st__(len, optlen);
1183| }
1184|
1185| return err;
1186|}
1187|
1188|extern typeof(ipv6_getsockopt) ipv6_getsockopt; extern void *__crc_ipv6_getsockopt ; static const unsigned long __kcrctab_ipv6_getsockopt = (unsigned long) &__crc_ipv6_getsockopt; static const char __kstrtab_ipv6_getsockopt[] = "" "ipv6_getsockopt"; static const struct kernel_symbol __ksymtab_ipv6_getsockopt = { (unsigned long)&ipv6_getsockopt, __kstrtab_ipv6_getsockopt };
1189|
1190|
1191|int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
1192| char *optval, int *optlen)
1193|{
1194| int err;
1195|
1196| if (level == 0 && sk->sk_type != SOCK_RAW) {
1197| if (udp_prot.compat_getsockopt != ((void *)0))
1198| return udp_prot.compat_getsockopt(sk, level, optname,
1199| optval, optlen);
1200| return udp_prot.getsockopt(sk, level, optname, optval, optlen);
1201| }
1202|
1203| if (level != 41)
1204| return -92;
1205|
1206| if (optname == 48)
1207| return compat_mc_getsockopt(sk, level, optname, optval, optlen,
1208| ipv6_getsockopt);
1209|
1210| err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
1211|
1212|
1213| if (err == -92 && optname != 6) {
1214| int len;
1215|
1216| if (__st_get_user_st__(len, optlen))
1217| return -14;
1218|
1219| lock_sock(sk);
1220| err = compat_nf_getsockopt(sk, 10,
1221| optname, optval, &len);
1222| release_sock(sk);
1223| if (err >= 0)
1224| err = __st_put_user_st__(len, optlen);
1225| }
1226|
1227| return err;
1228|}
1229|
1230|extern typeof(compat_ipv6_getsockopt) compat_ipv6_getsockopt; extern void *__crc_compat_ipv6_getsockopt ; static const unsigned long __kcrctab_compat_ipv6_getsockopt = (unsigned long) &__crc_compat_ipv6_getsockopt; static const char __kstrtab_compat_ipv6_getsockopt[] = "" "compat_ipv6_getsockopt"; static const struct kernel_symbol __ksymtab_compat_ipv6_getsockopt = { (unsigned long)&compat_ipv6_getsockopt, __kstrtab_compat_ipv6_getsockopt };