aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/exthdrs.c47
1 files changed, 16 insertions, 31 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 173a4bb52255..fc3a961fc5ba 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -372,22 +372,13 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
372 struct rt0_hdr *rthdr; 372 struct rt0_hdr *rthdr;
373 int accept_source_route = ipv6_devconf.accept_source_route; 373 int accept_source_route = ipv6_devconf.accept_source_route;
374 374
375 if (accept_source_route < 0 || 375 idev = in6_dev_get(skb->dev);
376 ((idev = in6_dev_get(skb->dev)) == NULL)) { 376 if (idev) {
377 kfree_skb(skb); 377 if (accept_source_route > idev->cnf.accept_source_route)
378 return -1; 378 accept_source_route = idev->cnf.accept_source_route;
379 }
380 if (idev->cnf.accept_source_route < 0) {
381 in6_dev_put(idev); 379 in6_dev_put(idev);
382 kfree_skb(skb);
383 return -1;
384 } 380 }
385 381
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);
390
391 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || 382 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
392 !pskb_may_pull(skb, (skb_transport_offset(skb) + 383 !pskb_may_pull(skb, (skb_transport_offset(skb) +
393 ((skb_transport_header(skb)[1] + 1) << 3)))) { 384 ((skb_transport_header(skb)[1] + 1) << 3)))) {
@@ -399,24 +390,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
399 390
400 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb); 391 hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
401 392
402 switch (hdr->type) {
403#ifdef CONFIG_IPV6_MIP6
404 case IPV6_SRCRT_TYPE_2:
405 break;
406#endif
407 case IPV6_SRCRT_TYPE_0:
408 if (accept_source_route > 0)
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);
415 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
416 (&hdr->type) - skb_network_header(skb));
417 return -1;
418 }
419
420 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) || 393 if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
421 skb->pkt_type != PACKET_HOST) { 394 skb->pkt_type != PACKET_HOST) {
422 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 395 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
@@ -455,6 +428,8 @@ looped_back:
455 428
456 switch (hdr->type) { 429 switch (hdr->type) {
457 case IPV6_SRCRT_TYPE_0: 430 case IPV6_SRCRT_TYPE_0:
431 if (accept_source_route <= 0)
432 goto unknown_rh;
458 if (hdr->hdrlen & 0x01) { 433 if (hdr->hdrlen & 0x01) {
459 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 434 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
460 IPSTATS_MIB_INHDRERRORS); 435 IPSTATS_MIB_INHDRERRORS);
@@ -466,6 +441,8 @@ looped_back:
466 break; 441 break;
467#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 442#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
468 case IPV6_SRCRT_TYPE_2: 443 case IPV6_SRCRT_TYPE_2:
444 if (accept_source_route < 0)
445 goto unknown_rh;
469 /* Silently discard invalid RTH type 2 */ 446 /* Silently discard invalid RTH type 2 */
470 if (hdr->hdrlen != 2 || hdr->segments_left != 1) { 447 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
471 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), 448 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
@@ -475,6 +452,8 @@ looped_back:
475 } 452 }
476 break; 453 break;
477#endif 454#endif
455 default:
456 goto unknown_rh;
478 } 457 }
479 458
480 /* 459 /*
@@ -578,6 +557,12 @@ looped_back:
578 skb_push(skb, skb->data - skb_network_header(skb)); 557 skb_push(skb, skb->data - skb_network_header(skb));
579 dst_input(skb); 558 dst_input(skb);
580 return -1; 559 return -1;
560
561unknown_rh:
562 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
563 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
564 (&hdr->type) - skb_network_header(skb));
565 return -1;
581} 566}
582 567
583static struct inet6_protocol rthdr_protocol = { 568static struct inet6_protocol rthdr_protocol = {