patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / net / ipv6 / exthdrs.c
1 /*
2  *      Extension Header handling for IPv6
3  *      Linux INET6 implementation
4  *
5  *      Authors:
6  *      Pedro Roque             <roque@di.fc.ul.pt>
7  *      Andi Kleen              <ak@muc.de>
8  *      Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
9  *
10  *      $Id: exthdrs.c,v 1.13 2001/06/19 15:58:56 davem Exp $
11  *
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.
16  */
17
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{}.
24  */
25
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>
35
36 #include <net/sock.h>
37 #include <net/snmp.h>
38
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>
46
47 #include <asm/uaccess.h>
48
49 /*
50  *      Parsing tlv encoded headers.
51  *
52  *      Parsing function "func" returns 1, if parsing succeed
53  *      and 0, if it failed.
54  *      It MUST NOT touch skb->h.
55  */
56
57 struct tlvtype_proc {
58         int     type;
59         int     (*func)(struct sk_buff *skb, int offset);
60 };
61
62 /*********************
63   Generic functions
64  *********************/
65
66 /* An unknown option is detected, decide what to do */
67
68 static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff)
69 {
70         switch ((skb->nh.raw[optoff] & 0xC0) >> 6) {
71         case 0: /* ignore */
72                 return 1;
73
74         case 1: /* drop packet */
75                 break;
76
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.
80                  */
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;
86         };
87
88         kfree_skb(skb);
89         return 0;
90 }
91
92 /* Parse tlv encoded option header (hop-by-hop or destination) */
93
94 static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb)
95 {
96         struct tlvtype_proc *curr;
97         int off = skb->h.raw - skb->nh.raw;
98         int len = ((skb->h.raw[1]+1)<<3);
99
100         if ((skb->h.raw + len) - skb->data > skb_headlen(skb))
101                 goto bad;
102
103         off += 2;
104         len -= 2;
105
106         while (len > 0) {
107                 int optlen = skb->nh.raw[off+1]+2;
108
109                 switch (skb->nh.raw[off]) {
110                 case IPV6_TLV_PAD0:
111                         optlen = 1;
112                         break;
113
114                 case IPV6_TLV_PADN:
115                         break;
116
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;
128                                 }
129                         }
130                         if (curr->type < 0) {
131                                 if (ip6_tlvopt_unknown(skb, off) == 0)
132                                         return 0;
133                         }
134                         break;
135                 }
136                 off += optlen;
137                 len -= optlen;
138         }
139         if (len == 0)
140                 return 1;
141 bad:
142         kfree_skb(skb);
143         return 0;
144 }
145
146 /*****************************
147   Destination options header.
148  *****************************/
149
150 static struct tlvtype_proc tlvprocdestopt_lst[] = {
151         /* No destination options are defined now */
152         {-1,                    NULL}
153 };
154
155 static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
156 {
157         struct sk_buff *skb = *skbp;
158         struct inet6_skb_parm *opt = IP6CB(skb);
159
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(InHdrErrors);
163                 kfree_skb(skb);
164                 return -1;
165         }
166
167         opt->dst1 = skb->h.raw - skb->nh.raw;
168
169         if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
170                 skb->h.raw += ((skb->h.raw[1]+1)<<3);
171                 *nhoffp = opt->dst1;
172                 return 1;
173         }
174
175         IP6_INC_STATS_BH(InHdrErrors);
176         return -1;
177 }
178
179 static struct inet6_protocol destopt_protocol = {
180         .handler        =       ipv6_destopt_rcv,
181         .flags          =       INET6_PROTO_NOPOLICY,
182 };
183
184 void __init ipv6_destopt_init(void)
185 {
186         if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
187                 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
188 }
189
190 /********************************
191   NONE header. No data in packet.
192  ********************************/
193
194 static int ipv6_nodata_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
195 {
196         struct sk_buff *skb = *skbp;
197
198         kfree_skb(skb);
199         return 0;
200 }
201
202 static struct inet6_protocol nodata_protocol = {
203         .handler        =       ipv6_nodata_rcv,
204         .flags          =       INET6_PROTO_NOPOLICY,
205 };
206
207 void __init ipv6_nodata_init(void)
208 {
209         if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
210                 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
211 }
212
213 /********************************
214   Routing header.
215  ********************************/
216
217 static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
218 {
219         struct sk_buff *skb = *skbp;
220         struct inet6_skb_parm *opt = IP6CB(skb);
221         struct in6_addr *addr;
222         struct in6_addr daddr;
223         int n, i;
224
225         struct ipv6_rt_hdr *hdr;
226         struct rt0_hdr *rthdr;
227
228         if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
229             !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
230                 IP6_INC_STATS_BH(InHdrErrors);
231                 kfree_skb(skb);
232                 return -1;
233         }
234
235         hdr = (struct ipv6_rt_hdr *) skb->h.raw;
236
237         if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
238             skb->pkt_type != PACKET_HOST) {
239                 IP6_INC_STATS_BH(InAddrErrors);
240                 kfree_skb(skb);
241                 return -1;
242         }
243
244 looped_back:
245         if (hdr->segments_left == 0) {
246                 opt->srcrt = skb->h.raw - skb->nh.raw;
247                 skb->h.raw += (hdr->hdrlen + 1) << 3;
248                 opt->dst0 = opt->dst1;
249                 opt->dst1 = 0;
250                 *nhoffp = (&hdr->nexthdr) - skb->nh.raw;
251                 return 1;
252         }
253
254         if (hdr->type != IPV6_SRCRT_TYPE_0) {
255                 IP6_INC_STATS_BH(InHdrErrors);
256                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
257                 return -1;
258         }
259         
260         if (hdr->hdrlen & 0x01) {
261                 IP6_INC_STATS_BH(InHdrErrors);
262                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
263                 return -1;
264         }
265
266         /*
267          *      This is the routing header forwarding algorithm from
268          *      RFC 2460, page 16.
269          */
270
271         n = hdr->hdrlen >> 1;
272
273         if (hdr->segments_left > n) {
274                 IP6_INC_STATS_BH(InHdrErrors);
275                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
276                 return -1;
277         }
278
279         /* We are about to mangle packet header. Be careful!
280            Do not damage packets queued somewhere.
281          */
282         if (skb_cloned(skb)) {
283                 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
284                 kfree_skb(skb);
285                 /* the copy is a forwarded packet */
286                 if (skb2 == NULL) {
287                         IP6_INC_STATS_BH(OutDiscards);  
288                         return -1;
289                 }
290                 *skbp = skb = skb2;
291                 opt = IP6CB(skb2);
292                 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
293         }
294
295         if (skb->ip_summed == CHECKSUM_HW)
296                 skb->ip_summed = CHECKSUM_NONE;
297
298         i = n - --hdr->segments_left;
299
300         rthdr = (struct rt0_hdr *) hdr;
301         addr = rthdr->addr;
302         addr += i - 1;
303
304         if (ipv6_addr_is_multicast(addr)) {
305                 IP6_INC_STATS_BH(InAddrErrors);
306                 kfree_skb(skb);
307                 return -1;
308         }
309
310         ipv6_addr_copy(&daddr, addr);
311         ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr);
312         ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr);
313
314         dst_release(xchg(&skb->dst, NULL));
315         ip6_route_input(skb);
316         if (skb->dst->error) {
317                 dst_input(skb);
318                 return -1;
319         }
320         if (skb->dst->dev->flags&IFF_LOOPBACK) {
321                 if (skb->nh.ipv6h->hop_limit <= 1) {
322                         IP6_INC_STATS_BH(InHdrErrors);
323                         icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
324                                     0, skb->dev);
325                         kfree_skb(skb);
326                         return -1;
327                 }
328                 skb->nh.ipv6h->hop_limit--;
329                 goto looped_back;
330         }
331
332         dst_input(skb);
333         return -1;
334 }
335
336 static struct inet6_protocol rthdr_protocol = {
337         .handler        =       ipv6_rthdr_rcv,
338         .flags          =       INET6_PROTO_NOPOLICY,
339 };
340
341 void __init ipv6_rthdr_init(void)
342 {
343         if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
344                 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
345 };
346
347 /*
348    This function inverts received rthdr.
349    NOTE: specs allow to make it automatically only if
350    packet authenticated.
351
352    I will not discuss it here (though, I am really pissed off at
353    this stupid requirement making rthdr idea useless)
354
355    Actually, it creates severe problems  for us.
356    Embryonic requests has no associated sockets,
357    so that user have no control over it and
358    cannot not only to set reply options, but
359    even to know, that someone wants to connect
360    without success. :-(
361
362    For now we need to test the engine, so that I created
363    temporary (or permanent) backdoor.
364    If listening socket set IPV6_RTHDR to 2, then we invert header.
365                                                    --ANK (980729)
366  */
367
368 struct ipv6_txoptions *
369 ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
370 {
371         /* Received rthdr:
372
373            [ H1 -> H2 -> ... H_prev ]  daddr=ME
374
375            Inverted result:
376            [ H_prev -> ... -> H1 ] daddr =sender
377
378            Note, that IP output engine will rewrite this rthdr
379            by rotating it left by one addr.
380          */
381
382         int n, i;
383         struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
384         struct rt0_hdr *irthdr;
385         struct ipv6_txoptions *opt;
386         int hdrlen = ipv6_optlen(hdr);
387
388         if (hdr->segments_left ||
389             hdr->type != IPV6_SRCRT_TYPE_0 ||
390             hdr->hdrlen & 0x01)
391                 return NULL;
392
393         n = hdr->hdrlen >> 1;
394         opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
395         if (opt == NULL)
396                 return NULL;
397         memset(opt, 0, sizeof(*opt));
398         opt->tot_len = sizeof(*opt) + hdrlen;
399         opt->srcrt = (void*)(opt+1);
400         opt->opt_nflen = hdrlen;
401
402         memcpy(opt->srcrt, hdr, sizeof(*hdr));
403         irthdr = (struct rt0_hdr*)opt->srcrt;
404         /* Obsolete field, MBZ, when originated by us */
405         irthdr->bitmap = 0;
406         opt->srcrt->segments_left = n;
407         for (i=0; i<n; i++)
408                 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
409         return opt;
410 }
411
412 /**********************************
413   Hop-by-hop options.
414  **********************************/
415
416 /* Router Alert as of RFC 2711 */
417
418 static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
419 {
420         if (skb->nh.raw[optoff+1] == 2) {
421                 IP6CB(skb)->ra = optoff;
422                 return 1;
423         }
424         LIMIT_NETDEBUG(
425                  printk(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", skb->nh.raw[optoff+1]));
426         kfree_skb(skb);
427         return 0;
428 }
429
430 /* Jumbo payload */
431
432 static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
433 {
434         u32 pkt_len;
435
436         if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
437                 LIMIT_NETDEBUG(
438                          printk(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]));
439                 IP6_INC_STATS_BH(InHdrErrors);
440                 goto drop;
441         }
442
443         pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
444         if (pkt_len <= IPV6_MAXPLEN) {
445                 IP6_INC_STATS_BH(InHdrErrors);
446                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
447                 return 0;
448         }
449         if (skb->nh.ipv6h->payload_len) {
450                 IP6_INC_STATS_BH(InHdrErrors);
451                 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
452                 return 0;
453         }
454
455         if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
456                 IP6_INC_STATS_BH(InTruncatedPkts);
457                 goto drop;
458         }
459         if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
460                 __pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr));
461                 if (skb->ip_summed == CHECKSUM_HW)
462                         skb->ip_summed = CHECKSUM_NONE;
463         }
464         return 1;
465
466 drop:
467         kfree_skb(skb);
468         return 0;
469 }
470
471 static struct tlvtype_proc tlvprochopopt_lst[] = {
472         {
473                 .type   = IPV6_TLV_ROUTERALERT,
474                 .func   = ipv6_hop_ra,
475         },
476         {
477                 .type   = IPV6_TLV_JUMBO,
478                 .func   = ipv6_hop_jumbo,
479         },
480         { -1, }
481 };
482
483 int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
484 {
485         IP6CB(skb)->hop = sizeof(struct ipv6hdr);
486         if (ip6_parse_tlv(tlvprochopopt_lst, skb))
487                 return sizeof(struct ipv6hdr);
488         return -1;
489 }
490
491 /*
492  *      Creating outbound headers.
493  *
494  *      "build" functions work when skb is filled from head to tail (datagram)
495  *      "push"  functions work when headers are added from tail to head (tcp)
496  *
497  *      In both cases we assume, that caller reserved enough room
498  *      for headers.
499  */
500
501 static u8 *ipv6_build_rthdr(struct sk_buff *skb, u8 *prev_hdr,
502                      struct ipv6_rt_hdr *opt, struct in6_addr *addr)
503 {
504         struct rt0_hdr *phdr, *ihdr;
505         int hops;
506
507         ihdr = (struct rt0_hdr *) opt;
508         
509         phdr = (struct rt0_hdr *) skb_put(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
510         memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
511
512         hops = ihdr->rt_hdr.hdrlen >> 1;
513
514         if (hops > 1)
515                 memcpy(phdr->addr, ihdr->addr + 1,
516                        (hops - 1) * sizeof(struct in6_addr));
517
518         ipv6_addr_copy(phdr->addr + (hops - 1), addr);
519
520         phdr->rt_hdr.nexthdr = *prev_hdr;
521         *prev_hdr = NEXTHDR_ROUTING;
522         return &phdr->rt_hdr.nexthdr;
523 }
524
525 static u8 *ipv6_build_exthdr(struct sk_buff *skb, u8 *prev_hdr, u8 type, struct ipv6_opt_hdr *opt)
526 {
527         struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, ipv6_optlen(opt));
528
529         memcpy(h, opt, ipv6_optlen(opt));
530         h->nexthdr = *prev_hdr;
531         *prev_hdr = type;
532         return &h->nexthdr;
533 }
534
535 u8 *ipv6_build_nfrag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt,
536                           struct in6_addr *daddr, u32 jumbolen)
537 {
538         struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb->data;
539
540         if (opt && opt->hopopt)
541                 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_HOP, opt->hopopt);
542
543         if (jumbolen) {
544                 u8 *jumboopt = (u8 *)skb_put(skb, 8);
545
546                 if (opt && opt->hopopt) {
547                         *jumboopt++ = IPV6_TLV_PADN;
548                         *jumboopt++ = 0;
549                         h->hdrlen++;
550                 } else {
551                         h = (struct ipv6_opt_hdr *)jumboopt;
552                         h->nexthdr = *prev_hdr;
553                         h->hdrlen = 0;
554                         jumboopt += 2;
555                         *prev_hdr = NEXTHDR_HOP;
556                         prev_hdr = &h->nexthdr;
557                 }
558                 jumboopt[0] = IPV6_TLV_JUMBO;
559                 jumboopt[1] = 4;
560                 *(u32*)(jumboopt+2) = htonl(jumbolen);
561         }
562         if (opt) {
563                 if (opt->dst0opt)
564                         prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt);
565                 if (opt->srcrt)
566                         prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr);
567         }
568         return prev_hdr;
569 }
570
571 u8 *ipv6_build_frag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt)
572 {
573         if (opt->dst1opt)
574                 prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst1opt);
575         return prev_hdr;
576 }
577
578 static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
579                             struct ipv6_rt_hdr *opt,
580                             struct in6_addr **addr_p)
581 {
582         struct rt0_hdr *phdr, *ihdr;
583         int hops;
584
585         ihdr = (struct rt0_hdr *) opt;
586         
587         phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
588         memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
589
590         hops = ihdr->rt_hdr.hdrlen >> 1;
591
592         if (hops > 1)
593                 memcpy(phdr->addr, ihdr->addr + 1,
594                        (hops - 1) * sizeof(struct in6_addr));
595
596         ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
597         *addr_p = ihdr->addr;
598
599         phdr->rt_hdr.nexthdr = *proto;
600         *proto = NEXTHDR_ROUTING;
601 }
602
603 static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
604 {
605         struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
606
607         memcpy(h, opt, ipv6_optlen(opt));
608         h->nexthdr = *proto;
609         *proto = type;
610 }
611
612 void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
613                           u8 *proto,
614                           struct in6_addr **daddr)
615 {
616         if (opt->srcrt)
617                 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
618         if (opt->dst0opt)
619                 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
620         if (opt->hopopt)
621                 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
622 }
623
624 void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
625 {
626         if (opt->dst1opt)
627                 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
628 }
629
630 struct ipv6_txoptions *
631 ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
632 {
633         struct ipv6_txoptions *opt2;
634
635         opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
636         if (opt2) {
637                 long dif = (char*)opt2 - (char*)opt;
638                 memcpy(opt2, opt, opt->tot_len);
639                 if (opt2->hopopt)
640                         *((char**)&opt2->hopopt) += dif;
641                 if (opt2->dst0opt)
642                         *((char**)&opt2->dst0opt) += dif;
643                 if (opt2->dst1opt)
644                         *((char**)&opt2->dst1opt) += dif;
645                 if (opt2->srcrt)
646                         *((char**)&opt2->srcrt) += dif;
647         }
648         return opt2;
649 }