[SK_BUFF]: Introduce arp_hdr(), remove skb->nh.arph
[deliverable/linux.git] / net / ipv6 / exthdrs.c
CommitLineData
1da177e4
LT
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:
1ab1457c 19 * yoshfuji : ensure not to overrun while parsing
1da177e4
LT
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>
1da177e4
LT
30#include <linux/net.h>
31#include <linux/netdevice.h>
32#include <linux/in6.h>
33#include <linux/icmpv6.h>
34
35#include <net/sock.h>
36#include <net/snmp.h>
37
38#include <net/ipv6.h>
39#include <net/protocol.h>
40#include <net/transp_v6.h>
41#include <net/rawv6.h>
42#include <net/ndisc.h>
43#include <net/ip6_route.h>
44#include <net/addrconf.h>
65d4ed92
MN
45#ifdef CONFIG_IPV6_MIP6
46#include <net/xfrm.h>
47#endif
1da177e4
LT
48
49#include <asm/uaccess.h>
50
c61a4043
MN
51int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
52{
d56f90a7
ACM
53 const unsigned char *nh = skb_network_header(skb);
54 int packet_len = skb->tail - nh;
c61a4043
MN
55 struct ipv6_opt_hdr *hdr;
56 int len;
57
58 if (offset + 2 > packet_len)
59 goto bad;
d56f90a7 60 hdr = (struct ipv6_opt_hdr *)(nh + offset);
c61a4043
MN
61 len = ((hdr->hdrlen + 1) << 3);
62
63 if (offset + len > packet_len)
64 goto bad;
65
66 offset += 2;
67 len -= 2;
68
69 while (len > 0) {
d56f90a7 70 int opttype = nh[offset];
c61a4043
MN
71 int optlen;
72
73 if (opttype == type)
74 return offset;
75
76 switch (opttype) {
77 case IPV6_TLV_PAD0:
78 optlen = 1;
79 break;
80 default:
d56f90a7 81 optlen = nh[offset + 1] + 2;
c61a4043
MN
82 if (optlen > len)
83 goto bad;
84 break;
85 }
86 offset += optlen;
87 len -= optlen;
88 }
89 /* not_found */
c61a4043
MN
90 bad:
91 return -1;
92}
93
1da177e4
LT
94/*
95 * Parsing tlv encoded headers.
96 *
97 * Parsing function "func" returns 1, if parsing succeed
98 * and 0, if it failed.
99 * It MUST NOT touch skb->h.
100 */
101
102struct tlvtype_proc {
103 int type;
a80ff03e 104 int (*func)(struct sk_buff **skbp, int offset);
1da177e4
LT
105};
106
107/*********************
108 Generic functions
109 *********************/
110
111/* An unknown option is detected, decide what to do */
112
a80ff03e 113static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
1da177e4 114{
a80ff03e
MN
115 struct sk_buff *skb = *skbp;
116
d56f90a7 117 switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
1da177e4
LT
118 case 0: /* ignore */
119 return 1;
120
121 case 1: /* drop packet */
122 break;
123
124 case 3: /* Send ICMP if not a multicast address and drop packet */
125 /* Actually, it is redundant check. icmp_send
126 will recheck in any case.
127 */
128 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
129 break;
130 case 2: /* send ICMP PARM PROB regardless and drop packet */
131 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
132 return 0;
133 };
134
135 kfree_skb(skb);
136 return 0;
137}
138
139/* Parse tlv encoded option header (hop-by-hop or destination) */
140
a80ff03e 141static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
1da177e4 142{
a80ff03e 143 struct sk_buff *skb = *skbp;
1da177e4 144 struct tlvtype_proc *curr;
d56f90a7 145 const unsigned char *nh = skb_network_header(skb);
1da177e4
LT
146 int off = skb->h.raw - skb->nh.raw;
147 int len = ((skb->h.raw[1]+1)<<3);
148
149 if ((skb->h.raw + len) - skb->data > skb_headlen(skb))
150 goto bad;
151
152 off += 2;
153 len -= 2;
154
155 while (len > 0) {
d56f90a7 156 int optlen = nh[off + 1] + 2;
1da177e4 157
d56f90a7 158 switch (nh[off]) {
1da177e4
LT
159 case IPV6_TLV_PAD0:
160 optlen = 1;
161 break;
162
163 case IPV6_TLV_PADN:
164 break;
165
166 default: /* Other TLV code so scan list */
167 if (optlen > len)
168 goto bad;
169 for (curr=procs; curr->type >= 0; curr++) {
d56f90a7 170 if (curr->type == nh[off]) {
1ab1457c
YH
171 /* type specific length/alignment
172 checks will be performed in the
1da177e4 173 func(). */
a80ff03e 174 if (curr->func(skbp, off) == 0)
1da177e4
LT
175 return 0;
176 break;
177 }
178 }
179 if (curr->type < 0) {
a80ff03e 180 if (ip6_tlvopt_unknown(skbp, off) == 0)
1da177e4
LT
181 return 0;
182 }
183 break;
184 }
185 off += optlen;
186 len -= optlen;
187 }
188 if (len == 0)
189 return 1;
190bad:
191 kfree_skb(skb);
192 return 0;
193}
194
195/*****************************
196 Destination options header.
197 *****************************/
198
a831f5bb
MN
199#ifdef CONFIG_IPV6_MIP6
200static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
201{
202 struct sk_buff *skb = *skbp;
203 struct ipv6_destopt_hao *hao;
204 struct inet6_skb_parm *opt = IP6CB(skb);
57effc70 205 struct ipv6hdr *ipv6h = skb->nh.ipv6h;
a831f5bb
MN
206 struct in6_addr tmp_addr;
207 int ret;
208
209 if (opt->dsthao) {
210 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
211 goto discard;
212 }
213 opt->dsthao = opt->dst1;
214 opt->dst1 = 0;
215
d56f90a7 216 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff);
a831f5bb
MN
217
218 if (hao->length != 16) {
219 LIMIT_NETDEBUG(
220 KERN_DEBUG "hao invalid option length = %d\n", hao->length);
221 goto discard;
222 }
223
224 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
225 LIMIT_NETDEBUG(
226 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
227 goto discard;
228 }
229
230 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
231 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
232 if (unlikely(ret < 0))
233 goto discard;
234
235 if (skb_cloned(skb)) {
236 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
dc435e6d
MN
237 struct inet6_skb_parm *opt2;
238
a831f5bb
MN
239 if (skb2 == NULL)
240 goto discard;
241
dc435e6d
MN
242 opt2 = IP6CB(skb2);
243 memcpy(opt2, opt, sizeof(*opt2));
244
a831f5bb
MN
245 kfree_skb(skb);
246
247 /* update all variable using below by copied skbuff */
248 *skbp = skb = skb2;
d56f90a7
ACM
249 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) +
250 optoff);
251 ipv6h = skb2->nh.ipv6h;
a831f5bb
MN
252 }
253
254 if (skb->ip_summed == CHECKSUM_COMPLETE)
255 skb->ip_summed = CHECKSUM_NONE;
256
257 ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
258 ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
259 ipv6_addr_copy(&hao->addr, &tmp_addr);
260
b7aa0bf7 261 if (skb->tstamp.tv64 == 0)
a831f5bb
MN
262 __net_timestamp(skb);
263
264 return 1;
265
266 discard:
267 kfree_skb(skb);
268 return 0;
269}
270#endif
271
1da177e4 272static struct tlvtype_proc tlvprocdestopt_lst[] = {
a831f5bb
MN
273#ifdef CONFIG_IPV6_MIP6
274 {
275 .type = IPV6_TLV_HAO,
276 .func = ipv6_dest_hao,
277 },
278#endif
1da177e4
LT
279 {-1, NULL}
280};
281
951dbc8a 282static int ipv6_destopt_rcv(struct sk_buff **skbp)
1da177e4
LT
283{
284 struct sk_buff *skb = *skbp;
285 struct inet6_skb_parm *opt = IP6CB(skb);
a831f5bb
MN
286#ifdef CONFIG_IPV6_MIP6
287 __u16 dstbuf;
288#endif
a11d206d 289 struct dst_entry *dst;
1da177e4
LT
290
291 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
292 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
a11d206d
YH
293 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
294 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
295 kfree_skb(skb);
296 return -1;
297 }
298
333fad53 299 opt->lastopt = skb->h.raw - skb->nh.raw;
1da177e4 300 opt->dst1 = skb->h.raw - skb->nh.raw;
a831f5bb
MN
301#ifdef CONFIG_IPV6_MIP6
302 dstbuf = opt->dst1;
303#endif
1da177e4 304
a11d206d 305 dst = dst_clone(skb->dst);
a80ff03e 306 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
a11d206d 307 dst_release(dst);
a80ff03e 308 skb = *skbp;
1da177e4 309 skb->h.raw += ((skb->h.raw[1]+1)<<3);
dc435e6d 310 opt = IP6CB(skb);
a831f5bb
MN
311#ifdef CONFIG_IPV6_MIP6
312 opt->nhoff = dstbuf;
313#else
951dbc8a 314 opt->nhoff = opt->dst1;
a831f5bb 315#endif
1da177e4
LT
316 return 1;
317 }
318
a11d206d
YH
319 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
320 dst_release(dst);
1da177e4
LT
321 return -1;
322}
323
324static struct inet6_protocol destopt_protocol = {
325 .handler = ipv6_destopt_rcv,
adcfc7d0 326 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
1da177e4
LT
327};
328
329void __init ipv6_destopt_init(void)
330{
331 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
332 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
333}
334
335/********************************
336 NONE header. No data in packet.
337 ********************************/
338
951dbc8a 339static int ipv6_nodata_rcv(struct sk_buff **skbp)
1da177e4
LT
340{
341 struct sk_buff *skb = *skbp;
342
343 kfree_skb(skb);
344 return 0;
345}
346
347static struct inet6_protocol nodata_protocol = {
348 .handler = ipv6_nodata_rcv,
349 .flags = INET6_PROTO_NOPOLICY,
350};
351
352void __init ipv6_nodata_init(void)
353{
354 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
355 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
356}
357
358/********************************
359 Routing header.
360 ********************************/
361
951dbc8a 362static int ipv6_rthdr_rcv(struct sk_buff **skbp)
1da177e4
LT
363{
364 struct sk_buff *skb = *skbp;
365 struct inet6_skb_parm *opt = IP6CB(skb);
65d4ed92 366 struct in6_addr *addr = NULL;
1da177e4 367 struct in6_addr daddr;
0bcbc926 368 struct inet6_dev *idev;
1da177e4 369 int n, i;
1da177e4
LT
370 struct ipv6_rt_hdr *hdr;
371 struct rt0_hdr *rthdr;
0bcbc926
YH
372 int accept_source_route = ipv6_devconf.accept_source_route;
373
374 if (accept_source_route < 0 ||
375 ((idev = in6_dev_get(skb->dev)) == NULL)) {
376 kfree_skb(skb);
377 return -1;
378 }
379 if (idev->cnf.accept_source_route < 0) {
380 in6_dev_put(idev);
381 kfree_skb(skb);
382 return -1;
383 }
384
385 if (accept_source_route > idev->cnf.accept_source_route)
386 accept_source_route = idev->cnf.accept_source_route;
387
388 in6_dev_put(idev);
1da177e4
LT
389
390 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
391 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
a11d206d
YH
392 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
393 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
394 kfree_skb(skb);
395 return -1;
396 }
397
398 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
399
0bcbc926
YH
400 switch (hdr->type) {
401#ifdef CONFIG_IPV6_MIP6
402 break;
403#endif
404 case IPV6_SRCRT_TYPE_0:
a23cf14b 405 if (accept_source_route > 0)
0bcbc926
YH
406 break;
407 kfree_skb(skb);
408 return -1;
409 default:
410 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
411 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
412 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
413 (&hdr->type) - skb_network_header(skb));
0bcbc926
YH
414 return -1;
415 }
416
1da177e4
LT
417 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
418 skb->pkt_type != PACKET_HOST) {
a11d206d
YH
419 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
420 IPSTATS_MIB_INADDRERRORS);
1da177e4
LT
421 kfree_skb(skb);
422 return -1;
423 }
424
425looped_back:
426 if (hdr->segments_left == 0) {
65d4ed92
MN
427 switch (hdr->type) {
428#ifdef CONFIG_IPV6_MIP6
429 case IPV6_SRCRT_TYPE_2:
430 /* Silently discard type 2 header unless it was
431 * processed by own
432 */
433 if (!addr) {
a11d206d
YH
434 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
435 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
436 kfree_skb(skb);
437 return -1;
438 }
439 break;
440#endif
441 default:
442 break;
443 }
444
333fad53 445 opt->lastopt = skb->h.raw - skb->nh.raw;
1da177e4
LT
446 opt->srcrt = skb->h.raw - skb->nh.raw;
447 skb->h.raw += (hdr->hdrlen + 1) << 3;
448 opt->dst0 = opt->dst1;
449 opt->dst1 = 0;
d56f90a7 450 opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
1da177e4
LT
451 return 1;
452 }
453
65d4ed92
MN
454 switch (hdr->type) {
455 case IPV6_SRCRT_TYPE_0:
456 if (hdr->hdrlen & 0x01) {
a11d206d
YH
457 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
458 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
459 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
460 ((&hdr->hdrlen) -
461 skb_network_header(skb)));
65d4ed92
MN
462 return -1;
463 }
464 break;
465#ifdef CONFIG_IPV6_MIP6
466 case IPV6_SRCRT_TYPE_2:
467 /* Silently discard invalid RTH type 2 */
468 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
a11d206d
YH
469 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
470 IPSTATS_MIB_INHDRERRORS);
65d4ed92
MN
471 kfree_skb(skb);
472 return -1;
473 }
474 break;
475#endif
1da177e4 476 }
1da177e4
LT
477
478 /*
479 * This is the routing header forwarding algorithm from
480 * RFC 2460, page 16.
481 */
482
483 n = hdr->hdrlen >> 1;
484
485 if (hdr->segments_left > n) {
a11d206d
YH
486 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
487 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
488 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
489 ((&hdr->segments_left) -
490 skb_network_header(skb)));
1da177e4
LT
491 return -1;
492 }
493
494 /* We are about to mangle packet header. Be careful!
495 Do not damage packets queued somewhere.
496 */
497 if (skb_cloned(skb)) {
498 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
1da177e4
LT
499 /* the copy is a forwarded packet */
500 if (skb2 == NULL) {
a11d206d
YH
501 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
502 IPSTATS_MIB_OUTDISCARDS);
503 kfree_skb(skb);
1da177e4
LT
504 return -1;
505 }
a11d206d 506 kfree_skb(skb);
1da177e4
LT
507 *skbp = skb = skb2;
508 opt = IP6CB(skb2);
509 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
510 }
511
84fa7933 512 if (skb->ip_summed == CHECKSUM_COMPLETE)
1da177e4
LT
513 skb->ip_summed = CHECKSUM_NONE;
514
515 i = n - --hdr->segments_left;
516
517 rthdr = (struct rt0_hdr *) hdr;
518 addr = rthdr->addr;
519 addr += i - 1;
520
65d4ed92
MN
521 switch (hdr->type) {
522#ifdef CONFIG_IPV6_MIP6
523 case IPV6_SRCRT_TYPE_2:
524 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
525 (xfrm_address_t *)&skb->nh.ipv6h->saddr,
526 IPPROTO_ROUTING) < 0) {
a11d206d
YH
527 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
528 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
529 kfree_skb(skb);
530 return -1;
531 }
532 if (!ipv6_chk_home_addr(addr)) {
a11d206d
YH
533 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
534 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
535 kfree_skb(skb);
536 return -1;
537 }
538 break;
539#endif
540 default:
541 break;
542 }
543
1da177e4 544 if (ipv6_addr_is_multicast(addr)) {
a11d206d
YH
545 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
546 IPSTATS_MIB_INADDRERRORS);
1da177e4
LT
547 kfree_skb(skb);
548 return -1;
549 }
550
551 ipv6_addr_copy(&daddr, addr);
552 ipv6_addr_copy(addr, &skb->nh.ipv6h->daddr);
553 ipv6_addr_copy(&skb->nh.ipv6h->daddr, &daddr);
554
555 dst_release(xchg(&skb->dst, NULL));
556 ip6_route_input(skb);
557 if (skb->dst->error) {
d56f90a7 558 skb_push(skb, skb->data - skb_network_header(skb));
1da177e4
LT
559 dst_input(skb);
560 return -1;
561 }
562
563 if (skb->dst->dev->flags&IFF_LOOPBACK) {
564 if (skb->nh.ipv6h->hop_limit <= 1) {
a11d206d
YH
565 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
566 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
567 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
568 0, skb->dev);
569 kfree_skb(skb);
570 return -1;
571 }
572 skb->nh.ipv6h->hop_limit--;
573 goto looped_back;
574 }
575
d56f90a7 576 skb_push(skb, skb->data - skb_network_header(skb));
1da177e4
LT
577 dst_input(skb);
578 return -1;
579}
580
581static struct inet6_protocol rthdr_protocol = {
582 .handler = ipv6_rthdr_rcv,
adcfc7d0 583 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
1da177e4
LT
584};
585
586void __init ipv6_rthdr_init(void)
587{
588 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
589 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
590};
591
592/*
593 This function inverts received rthdr.
594 NOTE: specs allow to make it automatically only if
595 packet authenticated.
596
597 I will not discuss it here (though, I am really pissed off at
598 this stupid requirement making rthdr idea useless)
599
600 Actually, it creates severe problems for us.
601 Embryonic requests has no associated sockets,
602 so that user have no control over it and
603 cannot not only to set reply options, but
604 even to know, that someone wants to connect
605 without success. :-(
606
607 For now we need to test the engine, so that I created
608 temporary (or permanent) backdoor.
609 If listening socket set IPV6_RTHDR to 2, then we invert header.
1ab1457c 610 --ANK (980729)
1da177e4
LT
611 */
612
613struct ipv6_txoptions *
614ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
615{
616 /* Received rthdr:
617
618 [ H1 -> H2 -> ... H_prev ] daddr=ME
619
620 Inverted result:
621 [ H_prev -> ... -> H1 ] daddr =sender
622
623 Note, that IP output engine will rewrite this rthdr
624 by rotating it left by one addr.
625 */
626
627 int n, i;
628 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
629 struct rt0_hdr *irthdr;
630 struct ipv6_txoptions *opt;
631 int hdrlen = ipv6_optlen(hdr);
632
633 if (hdr->segments_left ||
634 hdr->type != IPV6_SRCRT_TYPE_0 ||
635 hdr->hdrlen & 0x01)
636 return NULL;
637
638 n = hdr->hdrlen >> 1;
639 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
640 if (opt == NULL)
641 return NULL;
642 memset(opt, 0, sizeof(*opt));
643 opt->tot_len = sizeof(*opt) + hdrlen;
644 opt->srcrt = (void*)(opt+1);
645 opt->opt_nflen = hdrlen;
646
647 memcpy(opt->srcrt, hdr, sizeof(*hdr));
648 irthdr = (struct rt0_hdr*)opt->srcrt;
e6df439b 649 irthdr->reserved = 0;
1da177e4
LT
650 opt->srcrt->segments_left = n;
651 for (i=0; i<n; i++)
652 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
653 return opt;
654}
655
3cf3dc6c
ACM
656EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
657
1da177e4
LT
658/**********************************
659 Hop-by-hop options.
660 **********************************/
661
662/* Router Alert as of RFC 2711 */
663
a80ff03e 664static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
1da177e4 665{
a80ff03e 666 struct sk_buff *skb = *skbp;
d56f90a7 667 const unsigned char *nh = skb_network_header(skb);
a80ff03e 668
d56f90a7 669 if (nh[optoff + 1] == 2) {
1da177e4
LT
670 IP6CB(skb)->ra = optoff;
671 return 1;
672 }
64ce2073 673 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
d56f90a7 674 nh[optoff + 1]);
1da177e4
LT
675 kfree_skb(skb);
676 return 0;
677}
678
679/* Jumbo payload */
680
a80ff03e 681static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
1da177e4 682{
a80ff03e 683 struct sk_buff *skb = *skbp;
d56f90a7 684 const unsigned char *nh = skb_network_header(skb);
1da177e4
LT
685 u32 pkt_len;
686
d56f90a7 687 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
64ce2073 688 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
d56f90a7 689 nh[optoff+1]);
a11d206d
YH
690 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
691 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
692 goto drop;
693 }
694
d56f90a7 695 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
1da177e4 696 if (pkt_len <= IPV6_MAXPLEN) {
a11d206d 697 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
698 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
699 return 0;
700 }
701 if (skb->nh.ipv6h->payload_len) {
a11d206d 702 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
703 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
704 return 0;
705 }
706
707 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
a11d206d 708 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
1da177e4
LT
709 goto drop;
710 }
42ca89c1
SH
711
712 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
713 goto drop;
714
1da177e4
LT
715 return 1;
716
717drop:
718 kfree_skb(skb);
719 return 0;
720}
721
722static struct tlvtype_proc tlvprochopopt_lst[] = {
723 {
724 .type = IPV6_TLV_ROUTERALERT,
725 .func = ipv6_hop_ra,
726 },
727 {
728 .type = IPV6_TLV_JUMBO,
729 .func = ipv6_hop_jumbo,
730 },
731 { -1, }
732};
733
a80ff03e 734int ipv6_parse_hopopts(struct sk_buff **skbp)
1da177e4 735{
a80ff03e 736 struct sk_buff *skb = *skbp;
951dbc8a
PM
737 struct inet6_skb_parm *opt = IP6CB(skb);
738
ec670095 739 /*
d56f90a7 740 * skb_network_header(skb) is equal to skb->data, and
ec670095
YH
741 * skb->h.raw - skb->nh.raw is always equal to
742 * sizeof(struct ipv6hdr) by definition of
743 * hop-by-hop options.
744 */
745 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
746 !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
747 kfree_skb(skb);
748 return -1;
749 }
750
951dbc8a 751 opt->hop = sizeof(struct ipv6hdr);
a80ff03e
MN
752 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
753 skb = *skbp;
951dbc8a 754 skb->h.raw += (skb->h.raw[1]+1)<<3;
dc435e6d 755 opt = IP6CB(skb);
951dbc8a 756 opt->nhoff = sizeof(struct ipv6hdr);
b809739a 757 return 1;
951dbc8a 758 }
1da177e4
LT
759 return -1;
760}
761
762/*
763 * Creating outbound headers.
764 *
765 * "build" functions work when skb is filled from head to tail (datagram)
766 * "push" functions work when headers are added from tail to head (tcp)
767 *
768 * In both cases we assume, that caller reserved enough room
769 * for headers.
770 */
771
772static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
773 struct ipv6_rt_hdr *opt,
774 struct in6_addr **addr_p)
775{
776 struct rt0_hdr *phdr, *ihdr;
777 int hops;
778
779 ihdr = (struct rt0_hdr *) opt;
1ab1457c 780
1da177e4
LT
781 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
782 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
783
784 hops = ihdr->rt_hdr.hdrlen >> 1;
785
786 if (hops > 1)
787 memcpy(phdr->addr, ihdr->addr + 1,
788 (hops - 1) * sizeof(struct in6_addr));
789
790 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
791 *addr_p = ihdr->addr;
792
793 phdr->rt_hdr.nexthdr = *proto;
794 *proto = NEXTHDR_ROUTING;
795}
796
797static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
798{
799 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
800
801 memcpy(h, opt, ipv6_optlen(opt));
802 h->nexthdr = *proto;
803 *proto = type;
804}
805
806void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
807 u8 *proto,
808 struct in6_addr **daddr)
809{
333fad53 810 if (opt->srcrt) {
1da177e4 811 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
333fad53
YH
812 /*
813 * IPV6_RTHDRDSTOPTS is ignored
814 * unless IPV6_RTHDR is set (RFC3542).
815 */
816 if (opt->dst0opt)
817 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
818 }
1da177e4
LT
819 if (opt->hopopt)
820 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
821}
822
7159039a
YH
823EXPORT_SYMBOL(ipv6_push_nfrag_opts);
824
1da177e4
LT
825void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
826{
827 if (opt->dst1opt)
828 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
829}
830
831struct ipv6_txoptions *
832ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
833{
834 struct ipv6_txoptions *opt2;
835
836 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
837 if (opt2) {
838 long dif = (char*)opt2 - (char*)opt;
839 memcpy(opt2, opt, opt->tot_len);
840 if (opt2->hopopt)
841 *((char**)&opt2->hopopt) += dif;
842 if (opt2->dst0opt)
843 *((char**)&opt2->dst0opt) += dif;
844 if (opt2->dst1opt)
845 *((char**)&opt2->dst1opt) += dif;
846 if (opt2->srcrt)
847 *((char**)&opt2->srcrt) += dif;
848 }
849 return opt2;
850}
333fad53 851
3cf3dc6c
ACM
852EXPORT_SYMBOL_GPL(ipv6_dup_options);
853
333fad53
YH
854static int ipv6_renew_option(void *ohdr,
855 struct ipv6_opt_hdr __user *newopt, int newoptlen,
856 int inherit,
857 struct ipv6_opt_hdr **hdr,
858 char **p)
859{
860 if (inherit) {
861 if (ohdr) {
862 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
863 *hdr = (struct ipv6_opt_hdr *)*p;
864 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
865 }
866 } else {
867 if (newopt) {
868 if (copy_from_user(*p, newopt, newoptlen))
869 return -EFAULT;
870 *hdr = (struct ipv6_opt_hdr *)*p;
871 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
872 return -EINVAL;
873 *p += CMSG_ALIGN(newoptlen);
874 }
875 }
876 return 0;
877}
878
879struct ipv6_txoptions *
880ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
881 int newtype,
882 struct ipv6_opt_hdr __user *newopt, int newoptlen)
883{
884 int tot_len = 0;
885 char *p;
886 struct ipv6_txoptions *opt2;
887 int err;
888
99c7bc01
YH
889 if (opt) {
890 if (newtype != IPV6_HOPOPTS && opt->hopopt)
891 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
892 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
893 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
894 if (newtype != IPV6_RTHDR && opt->srcrt)
895 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
896 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
897 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
898 }
899
333fad53
YH
900 if (newopt && newoptlen)
901 tot_len += CMSG_ALIGN(newoptlen);
902
903 if (!tot_len)
904 return NULL;
905
8b8aa4b5 906 tot_len += sizeof(*opt2);
333fad53
YH
907 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
908 if (!opt2)
909 return ERR_PTR(-ENOBUFS);
910
911 memset(opt2, 0, tot_len);
912
913 opt2->tot_len = tot_len;
914 p = (char *)(opt2 + 1);
915
99c7bc01 916 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
333fad53
YH
917 newtype != IPV6_HOPOPTS,
918 &opt2->hopopt, &p);
919 if (err)
920 goto out;
921
99c7bc01 922 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
333fad53
YH
923 newtype != IPV6_RTHDRDSTOPTS,
924 &opt2->dst0opt, &p);
925 if (err)
926 goto out;
927
99c7bc01 928 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
333fad53 929 newtype != IPV6_RTHDR,
99c7bc01 930 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
333fad53
YH
931 if (err)
932 goto out;
933
99c7bc01 934 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
333fad53
YH
935 newtype != IPV6_DSTOPTS,
936 &opt2->dst1opt, &p);
937 if (err)
938 goto out;
939
940 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
941 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
942 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
943 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
944
945 return opt2;
946out:
8b8aa4b5 947 sock_kfree_s(sk, opt2, opt2->tot_len);
333fad53
YH
948 return ERR_PTR(err);
949}
950
df9890c3
YH
951struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
952 struct ipv6_txoptions *opt)
953{
954 /*
955 * ignore the dest before srcrt unless srcrt is being included.
956 * --yoshfuji
957 */
958 if (opt && opt->dst0opt && !opt->srcrt) {
959 if (opt_space != opt) {
960 memcpy(opt_space, opt, sizeof(*opt_space));
961 opt = opt_space;
962 }
963 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
964 opt->dst0opt = NULL;
965 }
966
967 return opt;
968}
969
This page took 0.347089 seconds and 5 git commands to generate.