]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - net/ipv6/exthdrs.c
[SCTP]: Eliminate some pointer attributions to the skb layer headers
[mirror_ubuntu-jammy-kernel.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 */
0660e03f 128 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
1da177e4
LT
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
ea2ae17d 149 if (skb_transport_offset(skb) + len > skb_headlen(skb))
1da177e4
LT
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);
0660e03f 205 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
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);
0660e03f 251 ipv6h = ipv6_hdr(skb2);
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 290
ea2ae17d
ACM
291 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
292 !pskb_may_pull(skb, (skb_transport_offset(skb) +
293 ((skb->h.raw[1] + 1) << 3)))) {
a11d206d
YH
294 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
295 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
296 kfree_skb(skb);
297 return -1;
298 }
299
333fad53 300 opt->lastopt = skb->h.raw - skb->nh.raw;
1da177e4 301 opt->dst1 = skb->h.raw - skb->nh.raw;
a831f5bb
MN
302#ifdef CONFIG_IPV6_MIP6
303 dstbuf = opt->dst1;
304#endif
1da177e4 305
a11d206d 306 dst = dst_clone(skb->dst);
a80ff03e 307 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
a11d206d 308 dst_release(dst);
a80ff03e 309 skb = *skbp;
1da177e4 310 skb->h.raw += ((skb->h.raw[1]+1)<<3);
dc435e6d 311 opt = IP6CB(skb);
a831f5bb
MN
312#ifdef CONFIG_IPV6_MIP6
313 opt->nhoff = dstbuf;
314#else
951dbc8a 315 opt->nhoff = opt->dst1;
a831f5bb 316#endif
1da177e4
LT
317 return 1;
318 }
319
a11d206d
YH
320 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
321 dst_release(dst);
1da177e4
LT
322 return -1;
323}
324
325static struct inet6_protocol destopt_protocol = {
326 .handler = ipv6_destopt_rcv,
adcfc7d0 327 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
1da177e4
LT
328};
329
330void __init ipv6_destopt_init(void)
331{
332 if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
333 printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
334}
335
336/********************************
337 NONE header. No data in packet.
338 ********************************/
339
951dbc8a 340static int ipv6_nodata_rcv(struct sk_buff **skbp)
1da177e4
LT
341{
342 struct sk_buff *skb = *skbp;
343
344 kfree_skb(skb);
345 return 0;
346}
347
348static struct inet6_protocol nodata_protocol = {
349 .handler = ipv6_nodata_rcv,
350 .flags = INET6_PROTO_NOPOLICY,
351};
352
353void __init ipv6_nodata_init(void)
354{
355 if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
356 printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
357}
358
359/********************************
360 Routing header.
361 ********************************/
362
951dbc8a 363static int ipv6_rthdr_rcv(struct sk_buff **skbp)
1da177e4
LT
364{
365 struct sk_buff *skb = *skbp;
366 struct inet6_skb_parm *opt = IP6CB(skb);
65d4ed92 367 struct in6_addr *addr = NULL;
1da177e4 368 struct in6_addr daddr;
0bcbc926 369 struct inet6_dev *idev;
1da177e4 370 int n, i;
1da177e4
LT
371 struct ipv6_rt_hdr *hdr;
372 struct rt0_hdr *rthdr;
0bcbc926
YH
373 int accept_source_route = ipv6_devconf.accept_source_route;
374
375 if (accept_source_route < 0 ||
376 ((idev = in6_dev_get(skb->dev)) == NULL)) {
377 kfree_skb(skb);
378 return -1;
379 }
380 if (idev->cnf.accept_source_route < 0) {
381 in6_dev_put(idev);
382 kfree_skb(skb);
383 return -1;
384 }
385
386 if (accept_source_route > idev->cnf.accept_source_route)
387 accept_source_route = idev->cnf.accept_source_route;
388
389 in6_dev_put(idev);
1da177e4 390
ea2ae17d
ACM
391 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
392 !pskb_may_pull(skb, (skb_transport_offset(skb) +
393 ((skb->h.raw[1] + 1) << 3)))) {
a11d206d
YH
394 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
395 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
396 kfree_skb(skb);
397 return -1;
398 }
399
400 hdr = (struct ipv6_rt_hdr *) skb->h.raw;
401
0bcbc926
YH
402 switch (hdr->type) {
403#ifdef CONFIG_IPV6_MIP6
404 break;
405#endif
406 case IPV6_SRCRT_TYPE_0:
a23cf14b 407 if (accept_source_route > 0)
0bcbc926
YH
408 break;
409 kfree_skb(skb);
410 return -1;
411 default:
412 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
413 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
414 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
415 (&hdr->type) - skb_network_header(skb));
0bcbc926
YH
416 return -1;
417 }
418
0660e03f 419 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
1da177e4 420 skb->pkt_type != PACKET_HOST) {
a11d206d
YH
421 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
422 IPSTATS_MIB_INADDRERRORS);
1da177e4
LT
423 kfree_skb(skb);
424 return -1;
425 }
426
427looped_back:
428 if (hdr->segments_left == 0) {
65d4ed92
MN
429 switch (hdr->type) {
430#ifdef CONFIG_IPV6_MIP6
431 case IPV6_SRCRT_TYPE_2:
432 /* Silently discard type 2 header unless it was
433 * processed by own
434 */
435 if (!addr) {
a11d206d
YH
436 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
437 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
438 kfree_skb(skb);
439 return -1;
440 }
441 break;
442#endif
443 default:
444 break;
445 }
446
333fad53 447 opt->lastopt = skb->h.raw - skb->nh.raw;
1da177e4
LT
448 opt->srcrt = skb->h.raw - skb->nh.raw;
449 skb->h.raw += (hdr->hdrlen + 1) << 3;
450 opt->dst0 = opt->dst1;
451 opt->dst1 = 0;
d56f90a7 452 opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
1da177e4
LT
453 return 1;
454 }
455
65d4ed92
MN
456 switch (hdr->type) {
457 case IPV6_SRCRT_TYPE_0:
458 if (hdr->hdrlen & 0x01) {
a11d206d
YH
459 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
460 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
461 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
462 ((&hdr->hdrlen) -
463 skb_network_header(skb)));
65d4ed92
MN
464 return -1;
465 }
466 break;
467#ifdef CONFIG_IPV6_MIP6
468 case IPV6_SRCRT_TYPE_2:
469 /* Silently discard invalid RTH type 2 */
470 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
a11d206d
YH
471 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
472 IPSTATS_MIB_INHDRERRORS);
65d4ed92
MN
473 kfree_skb(skb);
474 return -1;
475 }
476 break;
477#endif
1da177e4 478 }
1da177e4
LT
479
480 /*
481 * This is the routing header forwarding algorithm from
482 * RFC 2460, page 16.
483 */
484
485 n = hdr->hdrlen >> 1;
486
487 if (hdr->segments_left > n) {
a11d206d
YH
488 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
489 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
490 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
491 ((&hdr->segments_left) -
492 skb_network_header(skb)));
1da177e4
LT
493 return -1;
494 }
495
496 /* We are about to mangle packet header. Be careful!
497 Do not damage packets queued somewhere.
498 */
499 if (skb_cloned(skb)) {
500 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
1da177e4
LT
501 /* the copy is a forwarded packet */
502 if (skb2 == NULL) {
a11d206d
YH
503 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
504 IPSTATS_MIB_OUTDISCARDS);
505 kfree_skb(skb);
1da177e4
LT
506 return -1;
507 }
a11d206d 508 kfree_skb(skb);
1da177e4
LT
509 *skbp = skb = skb2;
510 opt = IP6CB(skb2);
511 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
512 }
513
84fa7933 514 if (skb->ip_summed == CHECKSUM_COMPLETE)
1da177e4
LT
515 skb->ip_summed = CHECKSUM_NONE;
516
517 i = n - --hdr->segments_left;
518
519 rthdr = (struct rt0_hdr *) hdr;
520 addr = rthdr->addr;
521 addr += i - 1;
522
65d4ed92
MN
523 switch (hdr->type) {
524#ifdef CONFIG_IPV6_MIP6
525 case IPV6_SRCRT_TYPE_2:
526 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
0660e03f 527 (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
65d4ed92 528 IPPROTO_ROUTING) < 0) {
a11d206d
YH
529 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
530 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
531 kfree_skb(skb);
532 return -1;
533 }
534 if (!ipv6_chk_home_addr(addr)) {
a11d206d
YH
535 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
536 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
537 kfree_skb(skb);
538 return -1;
539 }
540 break;
541#endif
542 default:
543 break;
544 }
545
1da177e4 546 if (ipv6_addr_is_multicast(addr)) {
a11d206d
YH
547 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
548 IPSTATS_MIB_INADDRERRORS);
1da177e4
LT
549 kfree_skb(skb);
550 return -1;
551 }
552
553 ipv6_addr_copy(&daddr, addr);
0660e03f
ACM
554 ipv6_addr_copy(addr, &ipv6_hdr(skb)->daddr);
555 ipv6_addr_copy(&ipv6_hdr(skb)->daddr, &daddr);
1da177e4
LT
556
557 dst_release(xchg(&skb->dst, NULL));
558 ip6_route_input(skb);
559 if (skb->dst->error) {
d56f90a7 560 skb_push(skb, skb->data - skb_network_header(skb));
1da177e4
LT
561 dst_input(skb);
562 return -1;
563 }
564
565 if (skb->dst->dev->flags&IFF_LOOPBACK) {
0660e03f 566 if (ipv6_hdr(skb)->hop_limit <= 1) {
a11d206d
YH
567 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
568 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
569 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
570 0, skb->dev);
571 kfree_skb(skb);
572 return -1;
573 }
0660e03f 574 ipv6_hdr(skb)->hop_limit--;
1da177e4
LT
575 goto looped_back;
576 }
577
d56f90a7 578 skb_push(skb, skb->data - skb_network_header(skb));
1da177e4
LT
579 dst_input(skb);
580 return -1;
581}
582
583static struct inet6_protocol rthdr_protocol = {
584 .handler = ipv6_rthdr_rcv,
adcfc7d0 585 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
1da177e4
LT
586};
587
588void __init ipv6_rthdr_init(void)
589{
590 if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
591 printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
592};
593
594/*
595 This function inverts received rthdr.
596 NOTE: specs allow to make it automatically only if
597 packet authenticated.
598
599 I will not discuss it here (though, I am really pissed off at
600 this stupid requirement making rthdr idea useless)
601
602 Actually, it creates severe problems for us.
603 Embryonic requests has no associated sockets,
604 so that user have no control over it and
605 cannot not only to set reply options, but
606 even to know, that someone wants to connect
607 without success. :-(
608
609 For now we need to test the engine, so that I created
610 temporary (or permanent) backdoor.
611 If listening socket set IPV6_RTHDR to 2, then we invert header.
1ab1457c 612 --ANK (980729)
1da177e4
LT
613 */
614
615struct ipv6_txoptions *
616ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
617{
618 /* Received rthdr:
619
620 [ H1 -> H2 -> ... H_prev ] daddr=ME
621
622 Inverted result:
623 [ H_prev -> ... -> H1 ] daddr =sender
624
625 Note, that IP output engine will rewrite this rthdr
626 by rotating it left by one addr.
627 */
628
629 int n, i;
630 struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
631 struct rt0_hdr *irthdr;
632 struct ipv6_txoptions *opt;
633 int hdrlen = ipv6_optlen(hdr);
634
635 if (hdr->segments_left ||
636 hdr->type != IPV6_SRCRT_TYPE_0 ||
637 hdr->hdrlen & 0x01)
638 return NULL;
639
640 n = hdr->hdrlen >> 1;
641 opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
642 if (opt == NULL)
643 return NULL;
644 memset(opt, 0, sizeof(*opt));
645 opt->tot_len = sizeof(*opt) + hdrlen;
646 opt->srcrt = (void*)(opt+1);
647 opt->opt_nflen = hdrlen;
648
649 memcpy(opt->srcrt, hdr, sizeof(*hdr));
650 irthdr = (struct rt0_hdr*)opt->srcrt;
e6df439b 651 irthdr->reserved = 0;
1da177e4
LT
652 opt->srcrt->segments_left = n;
653 for (i=0; i<n; i++)
654 memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
655 return opt;
656}
657
3cf3dc6c
ACM
658EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
659
1da177e4
LT
660/**********************************
661 Hop-by-hop options.
662 **********************************/
663
664/* Router Alert as of RFC 2711 */
665
a80ff03e 666static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
1da177e4 667{
a80ff03e 668 struct sk_buff *skb = *skbp;
d56f90a7 669 const unsigned char *nh = skb_network_header(skb);
a80ff03e 670
d56f90a7 671 if (nh[optoff + 1] == 2) {
1da177e4
LT
672 IP6CB(skb)->ra = optoff;
673 return 1;
674 }
64ce2073 675 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
d56f90a7 676 nh[optoff + 1]);
1da177e4
LT
677 kfree_skb(skb);
678 return 0;
679}
680
681/* Jumbo payload */
682
a80ff03e 683static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
1da177e4 684{
a80ff03e 685 struct sk_buff *skb = *skbp;
d56f90a7 686 const unsigned char *nh = skb_network_header(skb);
1da177e4
LT
687 u32 pkt_len;
688
d56f90a7 689 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
64ce2073 690 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
d56f90a7 691 nh[optoff+1]);
a11d206d
YH
692 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
693 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
694 goto drop;
695 }
696
d56f90a7 697 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
1da177e4 698 if (pkt_len <= IPV6_MAXPLEN) {
a11d206d 699 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
700 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
701 return 0;
702 }
0660e03f 703 if (ipv6_hdr(skb)->payload_len) {
a11d206d 704 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
705 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
706 return 0;
707 }
708
709 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
a11d206d 710 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
1da177e4
LT
711 goto drop;
712 }
42ca89c1
SH
713
714 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
715 goto drop;
716
1da177e4
LT
717 return 1;
718
719drop:
720 kfree_skb(skb);
721 return 0;
722}
723
724static struct tlvtype_proc tlvprochopopt_lst[] = {
725 {
726 .type = IPV6_TLV_ROUTERALERT,
727 .func = ipv6_hop_ra,
728 },
729 {
730 .type = IPV6_TLV_JUMBO,
731 .func = ipv6_hop_jumbo,
732 },
733 { -1, }
734};
735
a80ff03e 736int ipv6_parse_hopopts(struct sk_buff **skbp)
1da177e4 737{
a80ff03e 738 struct sk_buff *skb = *skbp;
951dbc8a
PM
739 struct inet6_skb_parm *opt = IP6CB(skb);
740
ec670095 741 /*
d56f90a7 742 * skb_network_header(skb) is equal to skb->data, and
ec670095
YH
743 * skb->h.raw - skb->nh.raw is always equal to
744 * sizeof(struct ipv6hdr) by definition of
745 * hop-by-hop options.
746 */
747 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
748 !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
749 kfree_skb(skb);
750 return -1;
751 }
752
951dbc8a 753 opt->hop = sizeof(struct ipv6hdr);
a80ff03e
MN
754 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
755 skb = *skbp;
951dbc8a 756 skb->h.raw += (skb->h.raw[1]+1)<<3;
dc435e6d 757 opt = IP6CB(skb);
951dbc8a 758 opt->nhoff = sizeof(struct ipv6hdr);
b809739a 759 return 1;
951dbc8a 760 }
1da177e4
LT
761 return -1;
762}
763
764/*
765 * Creating outbound headers.
766 *
767 * "build" functions work when skb is filled from head to tail (datagram)
768 * "push" functions work when headers are added from tail to head (tcp)
769 *
770 * In both cases we assume, that caller reserved enough room
771 * for headers.
772 */
773
774static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
775 struct ipv6_rt_hdr *opt,
776 struct in6_addr **addr_p)
777{
778 struct rt0_hdr *phdr, *ihdr;
779 int hops;
780
781 ihdr = (struct rt0_hdr *) opt;
1ab1457c 782
1da177e4
LT
783 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
784 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
785
786 hops = ihdr->rt_hdr.hdrlen >> 1;
787
788 if (hops > 1)
789 memcpy(phdr->addr, ihdr->addr + 1,
790 (hops - 1) * sizeof(struct in6_addr));
791
792 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
793 *addr_p = ihdr->addr;
794
795 phdr->rt_hdr.nexthdr = *proto;
796 *proto = NEXTHDR_ROUTING;
797}
798
799static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
800{
801 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
802
803 memcpy(h, opt, ipv6_optlen(opt));
804 h->nexthdr = *proto;
805 *proto = type;
806}
807
808void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
809 u8 *proto,
810 struct in6_addr **daddr)
811{
333fad53 812 if (opt->srcrt) {
1da177e4 813 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
333fad53
YH
814 /*
815 * IPV6_RTHDRDSTOPTS is ignored
816 * unless IPV6_RTHDR is set (RFC3542).
817 */
818 if (opt->dst0opt)
819 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
820 }
1da177e4
LT
821 if (opt->hopopt)
822 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
823}
824
7159039a
YH
825EXPORT_SYMBOL(ipv6_push_nfrag_opts);
826
1da177e4
LT
827void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
828{
829 if (opt->dst1opt)
830 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
831}
832
833struct ipv6_txoptions *
834ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
835{
836 struct ipv6_txoptions *opt2;
837
838 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
839 if (opt2) {
840 long dif = (char*)opt2 - (char*)opt;
841 memcpy(opt2, opt, opt->tot_len);
842 if (opt2->hopopt)
843 *((char**)&opt2->hopopt) += dif;
844 if (opt2->dst0opt)
845 *((char**)&opt2->dst0opt) += dif;
846 if (opt2->dst1opt)
847 *((char**)&opt2->dst1opt) += dif;
848 if (opt2->srcrt)
849 *((char**)&opt2->srcrt) += dif;
850 }
851 return opt2;
852}
333fad53 853
3cf3dc6c
ACM
854EXPORT_SYMBOL_GPL(ipv6_dup_options);
855
333fad53
YH
856static int ipv6_renew_option(void *ohdr,
857 struct ipv6_opt_hdr __user *newopt, int newoptlen,
858 int inherit,
859 struct ipv6_opt_hdr **hdr,
860 char **p)
861{
862 if (inherit) {
863 if (ohdr) {
864 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
865 *hdr = (struct ipv6_opt_hdr *)*p;
866 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
867 }
868 } else {
869 if (newopt) {
870 if (copy_from_user(*p, newopt, newoptlen))
871 return -EFAULT;
872 *hdr = (struct ipv6_opt_hdr *)*p;
873 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
874 return -EINVAL;
875 *p += CMSG_ALIGN(newoptlen);
876 }
877 }
878 return 0;
879}
880
881struct ipv6_txoptions *
882ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
883 int newtype,
884 struct ipv6_opt_hdr __user *newopt, int newoptlen)
885{
886 int tot_len = 0;
887 char *p;
888 struct ipv6_txoptions *opt2;
889 int err;
890
99c7bc01
YH
891 if (opt) {
892 if (newtype != IPV6_HOPOPTS && opt->hopopt)
893 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
894 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
895 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
896 if (newtype != IPV6_RTHDR && opt->srcrt)
897 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
898 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
899 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
900 }
901
333fad53
YH
902 if (newopt && newoptlen)
903 tot_len += CMSG_ALIGN(newoptlen);
904
905 if (!tot_len)
906 return NULL;
907
8b8aa4b5 908 tot_len += sizeof(*opt2);
333fad53
YH
909 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
910 if (!opt2)
911 return ERR_PTR(-ENOBUFS);
912
913 memset(opt2, 0, tot_len);
914
915 opt2->tot_len = tot_len;
916 p = (char *)(opt2 + 1);
917
99c7bc01 918 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
333fad53
YH
919 newtype != IPV6_HOPOPTS,
920 &opt2->hopopt, &p);
921 if (err)
922 goto out;
923
99c7bc01 924 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
333fad53
YH
925 newtype != IPV6_RTHDRDSTOPTS,
926 &opt2->dst0opt, &p);
927 if (err)
928 goto out;
929
99c7bc01 930 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
333fad53 931 newtype != IPV6_RTHDR,
99c7bc01 932 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
333fad53
YH
933 if (err)
934 goto out;
935
99c7bc01 936 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
333fad53
YH
937 newtype != IPV6_DSTOPTS,
938 &opt2->dst1opt, &p);
939 if (err)
940 goto out;
941
942 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
943 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
944 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
945 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
946
947 return opt2;
948out:
8b8aa4b5 949 sock_kfree_s(sk, opt2, opt2->tot_len);
333fad53
YH
950 return ERR_PTR(err);
951}
952
df9890c3
YH
953struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
954 struct ipv6_txoptions *opt)
955{
956 /*
957 * ignore the dest before srcrt unless srcrt is being included.
958 * --yoshfuji
959 */
960 if (opt && opt->dst0opt && !opt->srcrt) {
961 if (opt_space != opt) {
962 memcpy(opt_space, opt, sizeof(*opt_space));
963 opt = opt_space;
964 }
965 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
966 opt->dst0opt = NULL;
967 }
968
969 return opt;
970}
971