[NET_SCHED]: Make HTB scheduler work with TSO.
[GitHub/mt8127/android_kernel_alcatel_ttab.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>
59fbb3a6 45#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
65d4ed92
MN
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 53 const unsigned char *nh = skb_network_header(skb);
27a884dc 54 int packet_len = skb->tail - skb->network_header;
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}
59fbb3a6 93EXPORT_SYMBOL_GPL(ipv6_find_tlv);
c61a4043 94
1da177e4
LT
95/*
96 * Parsing tlv encoded headers.
97 *
98 * Parsing function "func" returns 1, if parsing succeed
99 * and 0, if it failed.
100 * It MUST NOT touch skb->h.
101 */
102
103struct tlvtype_proc {
104 int type;
a80ff03e 105 int (*func)(struct sk_buff **skbp, int offset);
1da177e4
LT
106};
107
108/*********************
109 Generic functions
110 *********************/
111
112/* An unknown option is detected, decide what to do */
113
a80ff03e 114static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff)
1da177e4 115{
a80ff03e
MN
116 struct sk_buff *skb = *skbp;
117
d56f90a7 118 switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
1da177e4
LT
119 case 0: /* ignore */
120 return 1;
121
122 case 1: /* drop packet */
123 break;
124
125 case 3: /* Send ICMP if not a multicast address and drop packet */
126 /* Actually, it is redundant check. icmp_send
127 will recheck in any case.
128 */
0660e03f 129 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
1da177e4
LT
130 break;
131 case 2: /* send ICMP PARM PROB regardless and drop packet */
132 icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
133 return 0;
3ff50b79 134 }
1da177e4
LT
135
136 kfree_skb(skb);
137 return 0;
138}
139
140/* Parse tlv encoded option header (hop-by-hop or destination) */
141
a80ff03e 142static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp)
1da177e4 143{
a80ff03e 144 struct sk_buff *skb = *skbp;
1da177e4 145 struct tlvtype_proc *curr;
d56f90a7 146 const unsigned char *nh = skb_network_header(skb);
cfe1fc77 147 int off = skb_network_header_len(skb);
9c70220b 148 int len = (skb_transport_header(skb)[1] + 1) << 3;
1da177e4 149
ea2ae17d 150 if (skb_transport_offset(skb) + len > skb_headlen(skb))
1da177e4
LT
151 goto bad;
152
153 off += 2;
154 len -= 2;
155
156 while (len > 0) {
d56f90a7 157 int optlen = nh[off + 1] + 2;
1da177e4 158
d56f90a7 159 switch (nh[off]) {
1da177e4
LT
160 case IPV6_TLV_PAD0:
161 optlen = 1;
162 break;
163
164 case IPV6_TLV_PADN:
165 break;
166
167 default: /* Other TLV code so scan list */
168 if (optlen > len)
169 goto bad;
170 for (curr=procs; curr->type >= 0; curr++) {
d56f90a7 171 if (curr->type == nh[off]) {
1ab1457c
YH
172 /* type specific length/alignment
173 checks will be performed in the
1da177e4 174 func(). */
a80ff03e 175 if (curr->func(skbp, off) == 0)
1da177e4
LT
176 return 0;
177 break;
178 }
179 }
180 if (curr->type < 0) {
a80ff03e 181 if (ip6_tlvopt_unknown(skbp, off) == 0)
1da177e4
LT
182 return 0;
183 }
184 break;
185 }
186 off += optlen;
187 len -= optlen;
188 }
189 if (len == 0)
190 return 1;
191bad:
192 kfree_skb(skb);
193 return 0;
194}
195
196/*****************************
197 Destination options header.
198 *****************************/
199
59fbb3a6 200#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
a831f5bb
MN
201static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
202{
203 struct sk_buff *skb = *skbp;
204 struct ipv6_destopt_hao *hao;
205 struct inet6_skb_parm *opt = IP6CB(skb);
0660e03f 206 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
a831f5bb
MN
207 struct in6_addr tmp_addr;
208 int ret;
209
210 if (opt->dsthao) {
211 LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n");
212 goto discard;
213 }
214 opt->dsthao = opt->dst1;
215 opt->dst1 = 0;
216
d56f90a7 217 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff);
a831f5bb
MN
218
219 if (hao->length != 16) {
220 LIMIT_NETDEBUG(
221 KERN_DEBUG "hao invalid option length = %d\n", hao->length);
222 goto discard;
223 }
224
225 if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
226 LIMIT_NETDEBUG(
227 KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr));
228 goto discard;
229 }
230
231 ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
232 (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
233 if (unlikely(ret < 0))
234 goto discard;
235
236 if (skb_cloned(skb)) {
237 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
dc435e6d
MN
238 struct inet6_skb_parm *opt2;
239
a831f5bb
MN
240 if (skb2 == NULL)
241 goto discard;
242
dc435e6d
MN
243 opt2 = IP6CB(skb2);
244 memcpy(opt2, opt, sizeof(*opt2));
245
a831f5bb
MN
246 kfree_skb(skb);
247
248 /* update all variable using below by copied skbuff */
249 *skbp = skb = skb2;
d56f90a7
ACM
250 hao = (struct ipv6_destopt_hao *)(skb_network_header(skb2) +
251 optoff);
0660e03f 252 ipv6h = ipv6_hdr(skb2);
a831f5bb
MN
253 }
254
255 if (skb->ip_summed == CHECKSUM_COMPLETE)
256 skb->ip_summed = CHECKSUM_NONE;
257
258 ipv6_addr_copy(&tmp_addr, &ipv6h->saddr);
259 ipv6_addr_copy(&ipv6h->saddr, &hao->addr);
260 ipv6_addr_copy(&hao->addr, &tmp_addr);
261
b7aa0bf7 262 if (skb->tstamp.tv64 == 0)
a831f5bb
MN
263 __net_timestamp(skb);
264
265 return 1;
266
267 discard:
268 kfree_skb(skb);
269 return 0;
270}
271#endif
272
1da177e4 273static struct tlvtype_proc tlvprocdestopt_lst[] = {
59fbb3a6 274#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
a831f5bb
MN
275 {
276 .type = IPV6_TLV_HAO,
277 .func = ipv6_dest_hao,
278 },
279#endif
1da177e4
LT
280 {-1, NULL}
281};
282
951dbc8a 283static int ipv6_destopt_rcv(struct sk_buff **skbp)
1da177e4
LT
284{
285 struct sk_buff *skb = *skbp;
286 struct inet6_skb_parm *opt = IP6CB(skb);
59fbb3a6 287#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
a831f5bb
MN
288 __u16 dstbuf;
289#endif
a11d206d 290 struct dst_entry *dst;
1da177e4 291
ea2ae17d
ACM
292 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
293 !pskb_may_pull(skb, (skb_transport_offset(skb) +
9c70220b 294 ((skb_transport_header(skb)[1] + 1) << 3)))) {
a11d206d
YH
295 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
296 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
297 kfree_skb(skb);
298 return -1;
299 }
300
cfe1fc77 301 opt->lastopt = opt->dst1 = skb_network_header_len(skb);
59fbb3a6 302#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
a831f5bb
MN
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;
b0e380b1 310 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
dc435e6d 311 opt = IP6CB(skb);
59fbb3a6 312#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
a831f5bb
MN
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) +
9c70220b 393 ((skb_transport_header(skb)[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
9c70220b 400 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
1da177e4 401
0bcbc926
YH
402 switch (hdr->type) {
403#ifdef CONFIG_IPV6_MIP6
ebbd90a7 404 case IPV6_SRCRT_TYPE_2:
0bcbc926
YH
405 break;
406#endif
407 case IPV6_SRCRT_TYPE_0:
a23cf14b 408 if (accept_source_route > 0)
0bcbc926
YH
409 break;
410 kfree_skb(skb);
411 return -1;
412 default:
413 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
414 IPSTATS_MIB_INHDRERRORS);
d56f90a7
ACM
415 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
416 (&hdr->type) - skb_network_header(skb));
0bcbc926
YH
417 return -1;
418 }
419
0660e03f 420 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
1da177e4 421 skb->pkt_type != PACKET_HOST) {
a11d206d
YH
422 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
423 IPSTATS_MIB_INADDRERRORS);
1da177e4
LT
424 kfree_skb(skb);
425 return -1;
426 }
427
428looped_back:
429 if (hdr->segments_left == 0) {
65d4ed92 430 switch (hdr->type) {
59fbb3a6 431#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
65d4ed92
MN
432 case IPV6_SRCRT_TYPE_2:
433 /* Silently discard type 2 header unless it was
434 * processed by own
435 */
436 if (!addr) {
a11d206d
YH
437 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
438 IPSTATS_MIB_INADDRERRORS);
65d4ed92
MN
439 kfree_skb(skb);
440 return -1;
441 }
442 break;
443#endif
444 default:
445 break;
446 }
447
cfe1fc77 448 opt->lastopt = opt->srcrt = skb_network_header_len(skb);
b0e380b1 449 skb->transport_header += (hdr->hdrlen + 1) << 3;
1da177e4
LT
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;
59fbb3a6 467#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
65d4ed92
MN
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);
bff9b61c 511 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb2);
1da177e4
LT
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 523 switch (hdr->type) {
59fbb3a6 524#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
65d4ed92
MN
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
e76b2b25
YH
664/*
665 * Note: we cannot rely on skb->dst before we assign it in ip6_route_input().
666 */
667static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
668{
669 return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev);
670}
671
1da177e4
LT
672/* Router Alert as of RFC 2711 */
673
a80ff03e 674static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
1da177e4 675{
a80ff03e 676 struct sk_buff *skb = *skbp;
d56f90a7 677 const unsigned char *nh = skb_network_header(skb);
a80ff03e 678
d56f90a7 679 if (nh[optoff + 1] == 2) {
1da177e4
LT
680 IP6CB(skb)->ra = optoff;
681 return 1;
682 }
64ce2073 683 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n",
d56f90a7 684 nh[optoff + 1]);
1da177e4
LT
685 kfree_skb(skb);
686 return 0;
687}
688
689/* Jumbo payload */
690
a80ff03e 691static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
1da177e4 692{
a80ff03e 693 struct sk_buff *skb = *skbp;
d56f90a7 694 const unsigned char *nh = skb_network_header(skb);
1da177e4
LT
695 u32 pkt_len;
696
d56f90a7 697 if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
64ce2073 698 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
d56f90a7 699 nh[optoff+1]);
e76b2b25 700 IP6_INC_STATS_BH(ipv6_skb_idev(skb),
a11d206d 701 IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
702 goto drop;
703 }
704
d56f90a7 705 pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
1da177e4 706 if (pkt_len <= IPV6_MAXPLEN) {
e76b2b25 707 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
708 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
709 return 0;
710 }
0660e03f 711 if (ipv6_hdr(skb)->payload_len) {
e76b2b25 712 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
1da177e4
LT
713 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
714 return 0;
715 }
716
717 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
e76b2b25 718 IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS);
1da177e4
LT
719 goto drop;
720 }
42ca89c1
SH
721
722 if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
723 goto drop;
724
1da177e4
LT
725 return 1;
726
727drop:
728 kfree_skb(skb);
729 return 0;
730}
731
732static struct tlvtype_proc tlvprochopopt_lst[] = {
733 {
734 .type = IPV6_TLV_ROUTERALERT,
735 .func = ipv6_hop_ra,
736 },
737 {
738 .type = IPV6_TLV_JUMBO,
739 .func = ipv6_hop_jumbo,
740 },
741 { -1, }
742};
743
a80ff03e 744int ipv6_parse_hopopts(struct sk_buff **skbp)
1da177e4 745{
a80ff03e 746 struct sk_buff *skb = *skbp;
951dbc8a
PM
747 struct inet6_skb_parm *opt = IP6CB(skb);
748
ec670095 749 /*
d56f90a7 750 * skb_network_header(skb) is equal to skb->data, and
cfe1fc77 751 * skb_network_header_len(skb) is always equal to
ec670095
YH
752 * sizeof(struct ipv6hdr) by definition of
753 * hop-by-hop options.
754 */
755 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
9c70220b
ACM
756 !pskb_may_pull(skb, (sizeof(struct ipv6hdr) +
757 ((skb_transport_header(skb)[1] + 1) << 3)))) {
ec670095
YH
758 kfree_skb(skb);
759 return -1;
760 }
761
951dbc8a 762 opt->hop = sizeof(struct ipv6hdr);
a80ff03e
MN
763 if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) {
764 skb = *skbp;
b0e380b1 765 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
dc435e6d 766 opt = IP6CB(skb);
951dbc8a 767 opt->nhoff = sizeof(struct ipv6hdr);
b809739a 768 return 1;
951dbc8a 769 }
1da177e4
LT
770 return -1;
771}
772
773/*
774 * Creating outbound headers.
775 *
776 * "build" functions work when skb is filled from head to tail (datagram)
777 * "push" functions work when headers are added from tail to head (tcp)
778 *
779 * In both cases we assume, that caller reserved enough room
780 * for headers.
781 */
782
783static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
784 struct ipv6_rt_hdr *opt,
785 struct in6_addr **addr_p)
786{
787 struct rt0_hdr *phdr, *ihdr;
788 int hops;
789
790 ihdr = (struct rt0_hdr *) opt;
1ab1457c 791
1da177e4
LT
792 phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
793 memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
794
795 hops = ihdr->rt_hdr.hdrlen >> 1;
796
797 if (hops > 1)
798 memcpy(phdr->addr, ihdr->addr + 1,
799 (hops - 1) * sizeof(struct in6_addr));
800
801 ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);
802 *addr_p = ihdr->addr;
803
804 phdr->rt_hdr.nexthdr = *proto;
805 *proto = NEXTHDR_ROUTING;
806}
807
808static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
809{
810 struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
811
812 memcpy(h, opt, ipv6_optlen(opt));
813 h->nexthdr = *proto;
814 *proto = type;
815}
816
817void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
818 u8 *proto,
819 struct in6_addr **daddr)
820{
333fad53 821 if (opt->srcrt) {
1da177e4 822 ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);
333fad53
YH
823 /*
824 * IPV6_RTHDRDSTOPTS is ignored
825 * unless IPV6_RTHDR is set (RFC3542).
826 */
827 if (opt->dst0opt)
828 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
829 }
1da177e4
LT
830 if (opt->hopopt)
831 ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
832}
833
7159039a
YH
834EXPORT_SYMBOL(ipv6_push_nfrag_opts);
835
1da177e4
LT
836void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
837{
838 if (opt->dst1opt)
839 ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
840}
841
842struct ipv6_txoptions *
843ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
844{
845 struct ipv6_txoptions *opt2;
846
847 opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
848 if (opt2) {
849 long dif = (char*)opt2 - (char*)opt;
850 memcpy(opt2, opt, opt->tot_len);
851 if (opt2->hopopt)
852 *((char**)&opt2->hopopt) += dif;
853 if (opt2->dst0opt)
854 *((char**)&opt2->dst0opt) += dif;
855 if (opt2->dst1opt)
856 *((char**)&opt2->dst1opt) += dif;
857 if (opt2->srcrt)
858 *((char**)&opt2->srcrt) += dif;
859 }
860 return opt2;
861}
333fad53 862
3cf3dc6c
ACM
863EXPORT_SYMBOL_GPL(ipv6_dup_options);
864
333fad53
YH
865static int ipv6_renew_option(void *ohdr,
866 struct ipv6_opt_hdr __user *newopt, int newoptlen,
867 int inherit,
868 struct ipv6_opt_hdr **hdr,
869 char **p)
870{
871 if (inherit) {
872 if (ohdr) {
873 memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr));
874 *hdr = (struct ipv6_opt_hdr *)*p;
875 *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr));
876 }
877 } else {
878 if (newopt) {
879 if (copy_from_user(*p, newopt, newoptlen))
880 return -EFAULT;
881 *hdr = (struct ipv6_opt_hdr *)*p;
882 if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen)
883 return -EINVAL;
884 *p += CMSG_ALIGN(newoptlen);
885 }
886 }
887 return 0;
888}
889
890struct ipv6_txoptions *
891ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
892 int newtype,
893 struct ipv6_opt_hdr __user *newopt, int newoptlen)
894{
895 int tot_len = 0;
896 char *p;
897 struct ipv6_txoptions *opt2;
898 int err;
899
99c7bc01
YH
900 if (opt) {
901 if (newtype != IPV6_HOPOPTS && opt->hopopt)
902 tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
903 if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
904 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
905 if (newtype != IPV6_RTHDR && opt->srcrt)
906 tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
907 if (newtype != IPV6_DSTOPTS && opt->dst1opt)
908 tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
909 }
910
333fad53
YH
911 if (newopt && newoptlen)
912 tot_len += CMSG_ALIGN(newoptlen);
913
914 if (!tot_len)
915 return NULL;
916
8b8aa4b5 917 tot_len += sizeof(*opt2);
333fad53
YH
918 opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
919 if (!opt2)
920 return ERR_PTR(-ENOBUFS);
921
922 memset(opt2, 0, tot_len);
923
924 opt2->tot_len = tot_len;
925 p = (char *)(opt2 + 1);
926
99c7bc01 927 err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
333fad53
YH
928 newtype != IPV6_HOPOPTS,
929 &opt2->hopopt, &p);
930 if (err)
931 goto out;
932
99c7bc01 933 err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
333fad53
YH
934 newtype != IPV6_RTHDRDSTOPTS,
935 &opt2->dst0opt, &p);
936 if (err)
937 goto out;
938
99c7bc01 939 err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
333fad53 940 newtype != IPV6_RTHDR,
99c7bc01 941 (struct ipv6_opt_hdr **)&opt2->srcrt, &p);
333fad53
YH
942 if (err)
943 goto out;
944
99c7bc01 945 err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
333fad53
YH
946 newtype != IPV6_DSTOPTS,
947 &opt2->dst1opt, &p);
948 if (err)
949 goto out;
950
951 opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
952 (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
953 (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
954 opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
955
956 return opt2;
957out:
8b8aa4b5 958 sock_kfree_s(sk, opt2, opt2->tot_len);
333fad53
YH
959 return ERR_PTR(err);
960}
961
df9890c3
YH
962struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
963 struct ipv6_txoptions *opt)
964{
965 /*
966 * ignore the dest before srcrt unless srcrt is being included.
967 * --yoshfuji
968 */
969 if (opt && opt->dst0opt && !opt->srcrt) {
970 if (opt_space != opt) {
971 memcpy(opt_space, opt, sizeof(*opt_space));
972 opt = opt_space;
973 }
974 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
975 opt->dst0opt = NULL;
976 }
977
978 return opt;
979}
980