aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/exthdrs.c
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2006-11-04 06:11:37 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:22:08 -0500
commita11d206d0f88e092419877c7f706cafb5e1c2e57 (patch)
treeed96428bb52765198d5c5b7ccbc1f1b6516ffb3f /net/ipv6/exthdrs.c
parent7a3025b1b3a0173be5de6ced18754b909da27b38 (diff)
[IPV6]: Per-interface statistics support.
For IP MIB (RFC4293). Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Diffstat (limited to 'net/ipv6/exthdrs.c')
-rw-r--r--net/ipv6/exthdrs.c57
1 files changed, 38 insertions, 19 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 88c96b10684c..27829cc4ce88 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -284,10 +284,12 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
284#ifdef CONFIG_IPV6_MIP6 284#ifdef CONFIG_IPV6_MIP6
285 __u16 dstbuf; 285 __u16 dstbuf;
286#endif 286#endif
287 struct dst_entry *dst;
287 288
288 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || 289 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
289 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { 290 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
290 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 291 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
292 IPSTATS_MIB_INHDRERRORS);
291 kfree_skb(skb); 293 kfree_skb(skb);
292 return -1; 294 return -1;
293 } 295 }
@@ -298,7 +300,9 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
298 dstbuf = opt->dst1; 300 dstbuf = opt->dst1;
299#endif 301#endif
300 302
303 dst = dst_clone(skb->dst);
301 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { 304 if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) {
305 dst_release(dst);
302 skb = *skbp; 306 skb = *skbp;
303 skb->h.raw += ((skb->h.raw[1]+1)<<3); 307 skb->h.raw += ((skb->h.raw[1]+1)<<3);
304 opt = IP6CB(skb); 308 opt = IP6CB(skb);
@@ -310,7 +314,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
310 return 1; 314 return 1;
311 } 315 }
312 316
313 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 317 IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
318 dst_release(dst);
314 return -1; 319 return -1;
315} 320}
316 321
@@ -365,7 +370,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
365 370
366 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || 371 if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
367 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { 372 !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
368 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 373 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
374 IPSTATS_MIB_INHDRERRORS);
369 kfree_skb(skb); 375 kfree_skb(skb);
370 return -1; 376 return -1;
371 } 377 }
@@ -374,7 +380,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
374 380
375 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || 381 if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) ||
376 skb->pkt_type != PACKET_HOST) { 382 skb->pkt_type != PACKET_HOST) {
377 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); 383 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
384 IPSTATS_MIB_INADDRERRORS);
378 kfree_skb(skb); 385 kfree_skb(skb);
379 return -1; 386 return -1;
380 } 387 }
@@ -388,7 +395,8 @@ looped_back:
388 * processed by own 395 * processed by own
389 */ 396 */
390 if (!addr) { 397 if (!addr) {
391 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); 398 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
399 IPSTATS_MIB_INADDRERRORS);
392 kfree_skb(skb); 400 kfree_skb(skb);
393 return -1; 401 return -1;
394 } 402 }
@@ -410,7 +418,8 @@ looped_back:
410 switch (hdr->type) { 418 switch (hdr->type) {
411 case IPV6_SRCRT_TYPE_0: 419 case IPV6_SRCRT_TYPE_0:
412 if (hdr->hdrlen & 0x01) { 420 if (hdr->hdrlen & 0x01) {
413 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 421 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
422 IPSTATS_MIB_INHDRERRORS);
414 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); 423 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
415 return -1; 424 return -1;
416 } 425 }
@@ -419,14 +428,16 @@ looped_back:
419 case IPV6_SRCRT_TYPE_2: 428 case IPV6_SRCRT_TYPE_2:
420 /* Silently discard invalid RTH type 2 */ 429 /* Silently discard invalid RTH type 2 */
421 if (hdr->hdrlen != 2 || hdr->segments_left != 1) { 430 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
422 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 431 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
432 IPSTATS_MIB_INHDRERRORS);
423 kfree_skb(skb); 433 kfree_skb(skb);
424 return -1; 434 return -1;
425 } 435 }
426 break; 436 break;
427#endif 437#endif
428 default: 438 default:
429 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 439 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
440 IPSTATS_MIB_INHDRERRORS);
430 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); 441 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
431 return -1; 442 return -1;
432 } 443 }
@@ -439,7 +450,8 @@ looped_back:
439 n = hdr->hdrlen >> 1; 450 n = hdr->hdrlen >> 1;
440 451
441 if (hdr->segments_left > n) { 452 if (hdr->segments_left > n) {
442 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 453 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
454 IPSTATS_MIB_INHDRERRORS);
443 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); 455 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
444 return -1; 456 return -1;
445 } 457 }
@@ -449,12 +461,14 @@ looped_back:
449 */ 461 */
450 if (skb_cloned(skb)) { 462 if (skb_cloned(skb)) {
451 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); 463 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
452 kfree_skb(skb);
453 /* the copy is a forwarded packet */ 464 /* the copy is a forwarded packet */
454 if (skb2 == NULL) { 465 if (skb2 == NULL) {
455 IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS); 466 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
467 IPSTATS_MIB_OUTDISCARDS);
468 kfree_skb(skb);
456 return -1; 469 return -1;
457 } 470 }
471 kfree_skb(skb);
458 *skbp = skb = skb2; 472 *skbp = skb = skb2;
459 opt = IP6CB(skb2); 473 opt = IP6CB(skb2);
460 hdr = (struct ipv6_rt_hdr *) skb2->h.raw; 474 hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
@@ -475,12 +489,14 @@ looped_back:
475 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, 489 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
476 (xfrm_address_t *)&skb->nh.ipv6h->saddr, 490 (xfrm_address_t *)&skb->nh.ipv6h->saddr,
477 IPPROTO_ROUTING) < 0) { 491 IPPROTO_ROUTING) < 0) {
478 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); 492 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
493 IPSTATS_MIB_INADDRERRORS);
479 kfree_skb(skb); 494 kfree_skb(skb);
480 return -1; 495 return -1;
481 } 496 }
482 if (!ipv6_chk_home_addr(addr)) { 497 if (!ipv6_chk_home_addr(addr)) {
483 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); 498 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
499 IPSTATS_MIB_INADDRERRORS);
484 kfree_skb(skb); 500 kfree_skb(skb);
485 return -1; 501 return -1;
486 } 502 }
@@ -491,7 +507,8 @@ looped_back:
491 } 507 }
492 508
493 if (ipv6_addr_is_multicast(addr)) { 509 if (ipv6_addr_is_multicast(addr)) {
494 IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); 510 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
511 IPSTATS_MIB_INADDRERRORS);
495 kfree_skb(skb); 512 kfree_skb(skb);
496 return -1; 513 return -1;
497 } 514 }
@@ -510,7 +527,8 @@ looped_back:
510 527
511 if (skb->dst->dev->flags&IFF_LOOPBACK) { 528 if (skb->dst->dev->flags&IFF_LOOPBACK) {
512 if (skb->nh.ipv6h->hop_limit <= 1) { 529 if (skb->nh.ipv6h->hop_limit <= 1) {
513 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 530 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
531 IPSTATS_MIB_INHDRERRORS);
514 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 532 icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
515 0, skb->dev); 533 0, skb->dev);
516 kfree_skb(skb); 534 kfree_skb(skb);
@@ -632,24 +650,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff)
632 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { 650 if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {
633 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", 651 LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
634 skb->nh.raw[optoff+1]); 652 skb->nh.raw[optoff+1]);
635 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 653 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
654 IPSTATS_MIB_INHDRERRORS);
636 goto drop; 655 goto drop;
637 } 656 }
638 657
639 pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); 658 pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));
640 if (pkt_len <= IPV6_MAXPLEN) { 659 if (pkt_len <= IPV6_MAXPLEN) {
641 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 660 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
642 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); 661 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
643 return 0; 662 return 0;
644 } 663 }
645 if (skb->nh.ipv6h->payload_len) { 664 if (skb->nh.ipv6h->payload_len) {
646 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 665 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
647 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); 666 icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
648 return 0; 667 return 0;
649 } 668 }
650 669
651 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { 670 if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
652 IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); 671 IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
653 goto drop; 672 goto drop;
654 } 673 }
655 674