[PATCH] nf_queue: Fix Ooops when no queue handler registered
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / net / ipv6 / exthdrs.c
blob922549581abc266100d6a3a28676665dd509f858
1 /*
2 * Extension Header handling for IPv6
3 * Linux INET6 implementation
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Andi Kleen <ak@muc.de>
8 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
10 * $Id: exthdrs.c,v 1.13 2001/06/19 15:58:56 davem Exp $
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
18 /* Changes:
19 * yoshfuji : ensure not to overrun while parsing
20 * tlv options.
21 * Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
22 * YOSHIFUJI Hideaki @USAGI Register inbound extension header
23 * handlers as inet6_protocol{}.
26 #include <linux/errno.h>
27 #include <linux/types.h>
28 #include <linux/socket.h>
29 #include <linux/sockios.h>
30 #include <linux/sched.h>
31 #include <linux/net.h>
32 #include <linux/netdevice.h>
33 #include <linux/in6.h>
34 #include <linux/icmpv6.h>
36 #include <net/sock.h>
37 #include <net/snmp.h>
39 #include <net/ipv6.h>
40 #include <net/protocol.h>
41 #include <net/transp_v6.h>
42 #include <net/rawv6.h>
43 #include <net/ndisc.h>
44 #include <net/ip6_route.h>
45 #include <net/addrconf.h>
47 #include <asm/uaccess.h>
50 * Parsing tlv encoded headers.
52 * Parsing function "func" returns 1, if parsing succeed
53 * and 0, if it failed.
54 * It MUST NOT touch skb->h.
57 struct tlvtype_proc {
58 int type;
59 int (*func)(struct sk_buff *skb, int offset);
62 /*********************
63 Generic functions
64 *********************/
66 /* An unknown option is detected, decide what to do */
68 static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
70 switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
71 case 0: /* ignore */
72 return 1;
74 case 1: /* drop packet */
75 break;
77 case 3: /* Send ICMP if not a multicast address and drop packet */
78 /* Actually, it is redundant check. icmp_send
79 will recheck in any case.
81 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
82 break;
83 case 2: /* send ICMP PARM PROB regardless and drop packet */
84 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
85 return 0;
88 kfree_skb(skb);
89 return 0;
92 /* Parse tlv encoded option header (hop-by-hop or destination) */
94 static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
96 struct tlvtype_proc *curr;
97 int off = skb->h.raw - skb->nh.raw;
98 int len = ((skb->h.raw[1]+1)<<3);
100 if ((skb->h.raw + len) - skb->data > skb_headlen(skb))
101 goto bad;
103 off += 2;
104 len -= 2;
106 while (len > 0) {
107 int optlen = skb->nh.raw[off+1]+2;
109 switch (skb->nh.raw[off]) {
110 case IPV6_TLV_PAD0:
111 optlen = 1;
112 break;
114 case IPV6_TLV_PADN:
115 break;
117 default: /* Other TLV code so scan list */
118 if (optlen > len)
119 goto bad;
120 for (curr=procs; curr->type >= 0; curr++) {
121 if (curr->type == skb->nh.raw[off]) {
122 /* type specific length/alignment
123 checks will be performed in the
124 func(). */
125 if (curr->func(skb, off) == 0)
126 return 0;
127 break;
130 if (curr->type < 0) {
131 if (ip6_tlvopt_unknown(skb, off) == 0)
132 return 0;
134 break;
136 off += optlen;
137 len -= optlen;
139 if (len == 0)
140 return 1;
141 bad:
142 kfree_skb(skb);
143 return 0;
146 /*****************************
147 Destination options header.
148 *****************************/
150 static struct tlvtype_proc tlvprocdestopt_lst[] = {
151 /* No destination options are defined now */
152 {-1, NULL}
155 static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
157 struct sk_buff *skb = *skbp;
158 struct inet6_skb_parm *opt = IP6CB(skb);
160 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
161 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
162 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
163 kfree_skb(skb);
164 return -1;
167 opt->lastopt = skb->h.raw - skb->nh.raw;
168 opt->dst1 = skb->h.raw - skb->nh.raw;
170 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
171 skb->h.raw += ((skb->h.raw[1]+1)<<3);
172 *nhoffp = opt->dst1;
173 return 1;
176 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
177 return -1;
180 static struct inet6_protocol destopt_protocol = {
181 .handler = ipv6_destopt_rcv,
182 .flags = INET6_PROTO_NOPOLICY,
185 void __init ipv6_destopt_init(void)
187 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
188 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
191 /********************************
192 NONE header. No data in packet.
193 ********************************/
195 static int ipv6_nodata_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
197 struct sk_buff *skb = *skbp;
199 kfree_skb(skb);
200 return 0;
203 static struct inet6_protocol nodata_protocol = {
204 .handler = ipv6_nodata_rcv,
205 .flags = INET6_PROTO_NOPOLICY,
208 void __init ipv6_nodata_init(void)
210 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
211 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
214 /********************************
215 Routing header.
216 ********************************/
218 static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
220 struct sk_buff *skb = *skbp;
221 struct inet6_skb_parm *opt = IP6CB(skb);
222 struct in6_addr *addr;
223 struct in6_addr daddr;
224 int n, i;
226 struct ipv6_rt_hdr *hdr;
227 struct rt0_hdr *rthdr;
229 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
230 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
231 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
232 kfree_skb(skb);
233 return -1;
236 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
238 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
239 skb->pkt_type != PACKET_HOST) {
240 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
241 kfree_skb(skb);
242 return -1;
245 looped_back:
246 if (hdr->segments_left == 0) {
247 opt->lastopt = skb->h.raw - skb->nh.raw;
248 opt->srcrt = skb->h.raw - skb->nh.raw;
249 skb->h.raw += (hdr->hdrlen + 1) << 3;
250 opt->dst0 = opt->dst1;
251 opt->dst1 = 0;
252 *nhoffp = (&hdr->nexthdr) - skb->nh.raw;
253 return 1;
256 if (hdr->type != IPV6_SRCRT_TYPE_0) {
257 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
258 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
259 return -1;
262 if (hdr->hdrlen & 0x01) {
263 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
264 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
265 return -1;
269 * This is the routing header forwarding algorithm from
270 * RFC 2460, page 16.
273 n = hdr->hdrlen >> 1;
275 if (hdr->segments_left > n) {
276 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
277 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
278 return -1;
281 /* We are about to mangle packet header. Be careful!
282 Do not damage packets queued somewhere.
284 if (skb_cloned(skb)) {
285 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
286 kfree_skb(skb);
287 /* the copy is a forwarded packet */
288 if (skb2 == NULL) {
289 IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS);
290 return -1;
292 *skbp = skb = skb2;
293 opt = IP6CB(skb2);
294 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
297 if (skb->ip_summed == CHECKSUM_HW)
298 skb->ip_summed = CHECKSUM_NONE;
300 i = n - --hdr->segments_left;
302 rthdr = (struct rt0_hdr *) hdr;
303 addr = rthdr->addr;
304 addr += i - 1;
306 if (ipv6_addr_is_multicast(addr)) {
307 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
308 kfree_skb(skb);
309 return -1;
312 ipv6_addr_copy(&daddr, addr);
313 ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr);
314 ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr);
316 dst_release(xchg(&skb->dst, NULL));
317 ip6_route_input(skb);
318 if (skb->dst->error) {
319 skb_push(skb, skb->data - skb->nh.raw);
320 dst_input(skb);
321 return -1;
324 if (skb->dst->dev->flags&IFF_LOOPBACK) {
325 if (skb->nh.ipv6h->hop_limit <= 1) {
326 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
327 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
328 0, skb->dev);
329 kfree_skb(skb);
330 return -1;
332 skb->nh.ipv6h->hop_limit--;
333 goto looped_back;
336 skb_push(skb, skb->data - skb->nh.raw);
337 dst_input(skb);
338 return -1;
341 static struct inet6_protocol rthdr_protocol = {
342 .handler = ipv6_rthdr_rcv,
343 .flags = INET6_PROTO_NOPOLICY,
346 void __init ipv6_rthdr_init(void)
348 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
349 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
353 This function inverts received rthdr.
354 NOTE: specs allow to make it automatically only if
355 packet authenticated.
357 I will not discuss it here (though, I am really pissed off at
358 this stupid requirement making rthdr idea useless)
360 Actually, it creates severe problems for us.
361 Embryonic requests has no associated sockets,
362 so that user have no control over it and
363 cannot not only to set reply options, but
364 even to know, that someone wants to connect
365 without success. :-(
367 For now we need to test the engine, so that I created
368 temporary (or permanent) backdoor.
369 If listening socket set IPV6_RTHDR to 2, then we invert header.
370 --ANK (980729)
373 struct ipv6_txoptions *
374 ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
376 /* Received rthdr:
378 [ H1 -> H2 -> ... H_prev ] daddr=ME
380 Inverted result:
381 [ H_prev -> ... -> H1 ] daddr =sender
383 Note, that IP output engine will rewrite this rthdr
384 by rotating it left by one addr.
387 int n, i;
388 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
389 struct rt0_hdr *irthdr;
390 struct ipv6_txoptions *opt;
391 int hdrlen = ipv6_optlen(hdr);
393 if (hdr->segments_left ||
394 hdr->type != IPV6_SRCRT_TYPE_0 ||
395 hdr->hdrlen & 0x01)
396 return NULL;
398 n = hdr->hdrlen >> 1;
399 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
400 if (opt == NULL)
401 return NULL;
402 memset(opt, 0, sizeof(*opt));
403 opt->tot_len = sizeof(*opt) + hdrlen;
404 opt->srcrt = (void*)(opt+1);
405 opt->opt_nflen = hdrlen;
407 memcpy(opt->srcrt, hdr, sizeof(*hdr));
408 irthdr = (struct rt0_hdr*)opt->srcrt;
409 irthdr->reserved = 0;
410 opt->srcrt->segments_left = n;
411 for (i=0; i<n; i++)
412 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
413 return opt;
416 /**********************************
417 Hop-by-hop options.
418 **********************************/
420 /* Router Alert as of RFC 2711 */
422 static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
424 if (skb->nh.raw[optoff+1] == 2) {
425 IP6CB(skb)->ra = optoff;
426 return 1;
428 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
429 skb->nh.raw[optoff+1]);
430 kfree_skb(skb);
431 return 0;
434 /* Jumbo payload */
436 static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
438 u32 pkt_len;
440 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
441 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
442 skb->nh.raw[optoff+1]);
443 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
444 goto drop;
447 pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
448 if (pkt_len <= IPV6_MAXPLEN) {
449 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
450 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
451 return 0;
453 if (skb->nh.ipv6h->payload_len) {
454 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
455 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
456 return 0;
459 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
460 IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS);
461 goto drop;
464 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
465 goto drop;
467 return 1;
469 drop:
470 kfree_skb(skb);
471 return 0;
474 static struct tlvtype_proc tlvprochopopt_lst[] = {
476 .type = IPV6_TLV_ROUTERALERT,
477 .func = ipv6_hop_ra,
480 .type = IPV6_TLV_JUMBO,
481 .func = ipv6_hop_jumbo,
483 { -1, }
486 int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
488 IP6CB(skb)->hop = sizeof(struct ipv6hdr);
489 if (ip6_parse_tlv(tlvprochopopt_lst, skb))
490 return sizeof(struct ipv6hdr);
491 return -1;
495 * Creating outbound headers.
497 * "build" functions work when skb is filled from head to tail (datagram)
498 * "push" functions work when headers are added from tail to head (tcp)
500 * In both cases we assume, that caller reserved enough room
501 * for headers.
504 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
505 struct ipv6_rt_hdr *opt,
506 struct in6_addr **addr_p)
508 struct rt0_hdr *phdr, *ihdr;
509 int hops;
511 ihdr = (struct rt0_hdr *) opt;
513 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
514 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
516 hops = ihdr->rt_hdr.hdrlen >> 1;
518 if (hops > 1)
519 memcpy(phdr->addr, ihdr->addr + 1,
520 (hops - 1) * sizeof(struct in6_addr));
522 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
523 *addr_p = ihdr->addr;
525 phdr->rt_hdr.nexthdr = *proto;
526 *proto = NEXTHDR_ROUTING;
529 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
531 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
533 memcpy(h, opt, ipv6_optlen(opt));
534 h->nexthdr = *proto;
535 *proto = type;
538 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
539 u8 *proto,
540 struct in6_addr **daddr)
542 if (opt->srcrt) {
543 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
545 * IPV6_RTHDRDSTOPTS is ignored
546 * unless IPV6_RTHDR is set (RFC3542).
548 if (opt->dst0opt)
549 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
551 if (opt->hopopt)
552 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
555 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
557 if (opt->dst1opt)
558 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
561 struct ipv6_txoptions *
562 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
564 struct ipv6_txoptions *opt2;
566 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
567 if (opt2) {
568 long dif = (char*)opt2 - (char*)opt;
569 memcpy(opt2, opt, opt->tot_len);
570 if (opt2->hopopt)
571 *((char**)&opt2->hopopt) += dif;
572 if (opt2->dst0opt)
573 *((char**)&opt2->dst0opt) += dif;
574 if (opt2->dst1opt)
575 *((char**)&opt2->dst1opt) += dif;
576 if (opt2->srcrt)
577 *((char**)&opt2->srcrt) += dif;
579 return opt2;
582 static int ipv6_renew_option(void *ohdr,
583 struct ipv6_opt_hdr __user *newopt, int newoptlen,
584 int inherit,
585 struct ipv6_opt_hdr **hdr,
586 char **p)
588 if (inherit) {
589 if (ohdr) {
590 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
591 *hdr = (struct ipv6_opt_hdr *)*p;
592 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
594 } else {
595 if (newopt) {
596 if (copy_from_user(*p, newopt, newoptlen))
597 return -EFAULT;
598 *hdr = (struct ipv6_opt_hdr *)*p;
599 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
600 return -EINVAL;
601 *p += CMSG_ALIGN(newoptlen);
604 return 0;
607 struct ipv6_txoptions *
608 ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
609 int newtype,
610 struct ipv6_opt_hdr __user *newopt, int newoptlen)
612 int tot_len = 0;
613 char *p;
614 struct ipv6_txoptions *opt2;
615 int err;
617 if (newtype != IPV6_HOPOPTS && opt->hopopt)
618 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
619 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
620 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
621 if (newtype != IPV6_RTHDR && opt->srcrt)
622 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
623 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
624 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
625 if (newopt && newoptlen)
626 tot_len += CMSG_ALIGN(newoptlen);
628 if (!tot_len)
629 return NULL;
631 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
632 if (!opt2)
633 return ERR_PTR(-ENOBUFS);
635 memset(opt2, 0, tot_len);
637 opt2->tot_len = tot_len;
638 p = (char *)(opt2 + 1);
640 err = ipv6_renew_option(opt->hopopt, newopt, newoptlen,
641 newtype != IPV6_HOPOPTS,
642 &opt2->hopopt, &p);
643 if (err)
644 goto out;
646 err = ipv6_renew_option(opt->dst0opt, newopt, newoptlen,
647 newtype != IPV6_RTHDRDSTOPTS,
648 &opt2->dst0opt, &p);
649 if (err)
650 goto out;
652 err = ipv6_renew_option(opt->srcrt, newopt, newoptlen,
653 newtype != IPV6_RTHDR,
654 (struct ipv6_opt_hdr **)opt2->srcrt, &p);
655 if (err)
656 goto out;
658 err = ipv6_renew_option(opt->dst1opt, newopt, newoptlen,
659 newtype != IPV6_DSTOPTS,
660 &opt2->dst1opt, &p);
661 if (err)
662 goto out;
664 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
665 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
666 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
667 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
669 return opt2;
670 out:
671 sock_kfree_s(sk, p, tot_len);
672 return ERR_PTR(err);