icmp6.c (191672) | icmp6.c (192923) |
---|---|
1/*- 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 47 unchanged lines hidden (view full) --- 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 61 */ 62 63#include <sys/cdefs.h> | 1/*- 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 47 unchanged lines hidden (view full) --- 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 61 */ 62 63#include <sys/cdefs.h> |
64__FBSDID("$FreeBSD: head/sys/netinet6/icmp6.c 191672 2009-04-29 19:19:13Z bms $"); | 64__FBSDID("$FreeBSD: head/sys/netinet6/icmp6.c 192923 2009-05-27 18:57:13Z bms $"); |
65 66#include "opt_inet.h" 67#include "opt_inet6.h" 68#include "opt_ipsec.h" 69#include "opt_route.h" 70 71#include <sys/param.h> 72#include <sys/domain.h> --- 325 unchanged lines hidden (view full) --- 398 * Process a received ICMP6 message. 399 */ 400int 401icmp6_input(struct mbuf **mp, int *offp, int proto) 402{ 403 INIT_VNET_INET6(curvnet); 404 INIT_VPROCG(TD_TO_VPROCG(curthread)); /* XXX V_hostname needs this */ 405 struct mbuf *m = *mp, *n; | 65 66#include "opt_inet.h" 67#include "opt_inet6.h" 68#include "opt_ipsec.h" 69#include "opt_route.h" 70 71#include <sys/param.h> 72#include <sys/domain.h> --- 325 unchanged lines hidden (view full) --- 398 * Process a received ICMP6 message. 399 */ 400int 401icmp6_input(struct mbuf **mp, int *offp, int proto) 402{ 403 INIT_VNET_INET6(curvnet); 404 INIT_VPROCG(TD_TO_VPROCG(curthread)); /* XXX V_hostname needs this */ 405 struct mbuf *m = *mp, *n; |
406 struct ifnet *ifp; |
|
406 struct ip6_hdr *ip6, *nip6; 407 struct icmp6_hdr *icmp6, *nicmp6; 408 int off = *offp; 409 int icmp6len = m->m_pkthdr.len - *offp; 410 int code, sum, noff; 411 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; 412 | 407 struct ip6_hdr *ip6, *nip6; 408 struct icmp6_hdr *icmp6, *nicmp6; 409 int off = *offp; 410 int icmp6len = m->m_pkthdr.len - *offp; 411 int code, sum, noff; 412 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; 413 |
414 ifp = m->m_pkthdr.rcvif; 415 |
|
413#ifndef PULLDOWN_TEST 414 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), IPPROTO_DONE); 415 /* m might change if M_LOOP. So, call mtod after this */ 416#endif 417 418 /* 419 * Locate icmp6 structure in mbuf, and check 420 * that not corrupted and of at least minimum length --- 5 unchanged lines hidden (view full) --- 426 goto freeit; 427 } 428 429 /* 430 * Check multicast group membership. 431 * Note: SSM filters are not applied for ICMPv6 traffic. 432 */ 433 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | 416#ifndef PULLDOWN_TEST 417 IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), IPPROTO_DONE); 418 /* m might change if M_LOOP. So, call mtod after this */ 419#endif 420 421 /* 422 * Locate icmp6 structure in mbuf, and check 423 * that not corrupted and of at least minimum length --- 5 unchanged lines hidden (view full) --- 429 goto freeit; 430 } 431 432 /* 433 * Check multicast group membership. 434 * Note: SSM filters are not applied for ICMPv6 traffic. 435 */ 436 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { |
434 struct ifnet *ifp; 435 struct in6_multi *inm; | 437 struct in6_multi *inm; |
436 | 438 |
437 ifp = m->m_pkthdr.rcvif; | |
438 inm = in6m_lookup(ifp, &ip6->ip6_dst); 439 if (inm == NULL) { 440 IP6STAT_INC(ip6s_notmember); 441 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 442 goto freeit; 443 } 444 } 445 --- 32 unchanged lines hidden (view full) --- 478 case ICMP6_TIME_EXCEEDED: 479 break; 480 default: 481 goto freeit; 482 } 483 } 484 485 ICMP6STAT_INC(icp6s_inhist[icmp6->icmp6_type]); | 439 inm = in6m_lookup(ifp, &ip6->ip6_dst); 440 if (inm == NULL) { 441 IP6STAT_INC(ip6s_notmember); 442 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 443 goto freeit; 444 } 445 } 446 --- 32 unchanged lines hidden (view full) --- 479 case ICMP6_TIME_EXCEEDED: 480 break; 481 default: 482 goto freeit; 483 } 484 } 485 486 ICMP6STAT_INC(icp6s_inhist[icmp6->icmp6_type]); |
486 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg); | 487 icmp6_ifstat_inc(ifp, ifs6_in_msg); |
487 if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK) | 488 if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK) |
488 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error); | 489 icmp6_ifstat_inc(ifp, ifs6_in_error); |
489 490 switch (icmp6->icmp6_type) { 491 case ICMP6_DST_UNREACH: | 490 491 switch (icmp6->icmp6_type) { 492 case ICMP6_DST_UNREACH: |
492 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach); | 493 icmp6_ifstat_inc(ifp, ifs6_in_dstunreach); |
493 switch (code) { 494 case ICMP6_DST_UNREACH_NOROUTE: 495 code = PRC_UNREACH_NET; 496 break; 497 case ICMP6_DST_UNREACH_ADMIN: | 494 switch (code) { 495 case ICMP6_DST_UNREACH_NOROUTE: 496 code = PRC_UNREACH_NET; 497 break; 498 case ICMP6_DST_UNREACH_ADMIN: |
498 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_adminprohib); | 499 icmp6_ifstat_inc(ifp, ifs6_in_adminprohib); |
499 code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ 500 break; 501 case ICMP6_DST_UNREACH_ADDR: 502 code = PRC_HOSTDEAD; 503 break; 504 case ICMP6_DST_UNREACH_BEYONDSCOPE: 505 /* I mean "source address was incorrect." */ 506 code = PRC_PARAMPROB; 507 break; 508 case ICMP6_DST_UNREACH_NOPORT: 509 code = PRC_UNREACH_PORT; 510 break; 511 default: 512 goto badcode; 513 } 514 goto deliver; 515 break; 516 517 case ICMP6_PACKET_TOO_BIG: | 500 code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ 501 break; 502 case ICMP6_DST_UNREACH_ADDR: 503 code = PRC_HOSTDEAD; 504 break; 505 case ICMP6_DST_UNREACH_BEYONDSCOPE: 506 /* I mean "source address was incorrect." */ 507 code = PRC_PARAMPROB; 508 break; 509 case ICMP6_DST_UNREACH_NOPORT: 510 code = PRC_UNREACH_PORT; 511 break; 512 default: 513 goto badcode; 514 } 515 goto deliver; 516 break; 517 518 case ICMP6_PACKET_TOO_BIG: |
518 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig); | 519 icmp6_ifstat_inc(ifp, ifs6_in_pkttoobig); |
519 520 /* validation is made in icmp6_mtudisc_update */ 521 522 code = PRC_MSGSIZE; 523 524 /* 525 * Updating the path MTU will be done after examining 526 * intermediate extension headers. 527 */ 528 goto deliver; 529 break; 530 531 case ICMP6_TIME_EXCEEDED: | 520 521 /* validation is made in icmp6_mtudisc_update */ 522 523 code = PRC_MSGSIZE; 524 525 /* 526 * Updating the path MTU will be done after examining 527 * intermediate extension headers. 528 */ 529 goto deliver; 530 break; 531 532 case ICMP6_TIME_EXCEEDED: |
532 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed); | 533 icmp6_ifstat_inc(ifp, ifs6_in_timeexceed); |
533 switch (code) { 534 case ICMP6_TIME_EXCEED_TRANSIT: 535 code = PRC_TIMXCEED_INTRANS; 536 break; 537 case ICMP6_TIME_EXCEED_REASSEMBLY: 538 code = PRC_TIMXCEED_REASS; 539 break; 540 default: 541 goto badcode; 542 } 543 goto deliver; 544 break; 545 546 case ICMP6_PARAM_PROB: | 534 switch (code) { 535 case ICMP6_TIME_EXCEED_TRANSIT: 536 code = PRC_TIMXCEED_INTRANS; 537 break; 538 case ICMP6_TIME_EXCEED_REASSEMBLY: 539 code = PRC_TIMXCEED_REASS; 540 break; 541 default: 542 goto badcode; 543 } 544 goto deliver; 545 break; 546 547 case ICMP6_PARAM_PROB: |
547 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob); | 548 icmp6_ifstat_inc(ifp, ifs6_in_paramprob); |
548 switch (code) { 549 case ICMP6_PARAMPROB_NEXTHEADER: 550 code = PRC_UNREACH_PROTOCOL; 551 break; 552 case ICMP6_PARAMPROB_HEADER: 553 case ICMP6_PARAMPROB_OPTION: 554 code = PRC_PARAMPROB; 555 break; 556 default: 557 goto badcode; 558 } 559 goto deliver; 560 break; 561 562 case ICMP6_ECHO_REQUEST: | 549 switch (code) { 550 case ICMP6_PARAMPROB_NEXTHEADER: 551 code = PRC_UNREACH_PROTOCOL; 552 break; 553 case ICMP6_PARAMPROB_HEADER: 554 case ICMP6_PARAMPROB_OPTION: 555 code = PRC_PARAMPROB; 556 break; 557 default: 558 goto badcode; 559 } 560 goto deliver; 561 break; 562 563 case ICMP6_ECHO_REQUEST: |
563 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo); | 564 icmp6_ifstat_inc(ifp, ifs6_in_echo); |
564 if (code != 0) 565 goto badcode; 566 if ((n = m_copy(m, 0, M_COPYALL)) == NULL) { 567 /* Give up remote */ 568 break; 569 } 570 if ((n->m_flags & M_EXT) != 0 571 || n->m_len < off + sizeof(struct icmp6_hdr)) { --- 46 unchanged lines hidden (view full) --- 618 if (n) { 619 ICMP6STAT_INC(icp6s_reflect); 620 ICMP6STAT_INC(icp6s_outhist[ICMP6_ECHO_REPLY]); 621 icmp6_reflect(n, noff); 622 } 623 break; 624 625 case ICMP6_ECHO_REPLY: | 565 if (code != 0) 566 goto badcode; 567 if ((n = m_copy(m, 0, M_COPYALL)) == NULL) { 568 /* Give up remote */ 569 break; 570 } 571 if ((n->m_flags & M_EXT) != 0 572 || n->m_len < off + sizeof(struct icmp6_hdr)) { --- 46 unchanged lines hidden (view full) --- 619 if (n) { 620 ICMP6STAT_INC(icp6s_reflect); 621 ICMP6STAT_INC(icp6s_outhist[ICMP6_ECHO_REPLY]); 622 icmp6_reflect(n, noff); 623 } 624 break; 625 626 case ICMP6_ECHO_REPLY: |
626 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply); | 627 icmp6_ifstat_inc(ifp, ifs6_in_echoreply); |
627 if (code != 0) 628 goto badcode; 629 break; 630 631 case MLD_LISTENER_QUERY: 632 case MLD_LISTENER_REPORT: 633 case MLD_LISTENER_DONE: 634 case MLDV2_LISTENER_REPORT: 635 /* | 628 if (code != 0) 629 goto badcode; 630 break; 631 632 case MLD_LISTENER_QUERY: 633 case MLD_LISTENER_REPORT: 634 case MLD_LISTENER_DONE: 635 case MLDV2_LISTENER_REPORT: 636 /* |
636 * Drop MLD traffic which is not link-local. | 637 * Drop MLD traffic which is not link-local, has a hop limit 638 * of greater than 1 hop, or which does not have the 639 * IPv6 HBH Router Alert option. 640 * As IPv6 HBH options are stripped in ip6_input() we must 641 * check an mbuf header flag. |
637 * XXX Should we also sanity check that these messages 638 * were directed to a link-local multicast prefix? 639 */ | 642 * XXX Should we also sanity check that these messages 643 * were directed to a link-local multicast prefix? 644 */ |
640 if (ip6->ip6_hlim != 1) | 645 if ((ip6->ip6_hlim != 1) || (m->m_flags & M_RTALERT_MLD) == 0) |
641 goto freeit; 642 if (mld_input(m, off, icmp6len) != 0) 643 return (IPPROTO_DONE); 644 /* m stays. */ 645 break; 646 647 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */ 648 { --- 94 unchanged lines hidden (view full) --- 743 } 744 745 case ICMP6_WRUREPLY: 746 if (code != 0) 747 goto badcode; 748 break; 749 750 case ND_ROUTER_SOLICIT: | 646 goto freeit; 647 if (mld_input(m, off, icmp6len) != 0) 648 return (IPPROTO_DONE); 649 /* m stays. */ 650 break; 651 652 case ICMP6_WRUREQUEST: /* ICMP6_FQDN_QUERY */ 653 { --- 94 unchanged lines hidden (view full) --- 748 } 749 750 case ICMP6_WRUREPLY: 751 if (code != 0) 752 goto badcode; 753 break; 754 755 case ND_ROUTER_SOLICIT: |
751 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit); | 756 icmp6_ifstat_inc(ifp, ifs6_in_routersolicit); |
752 if (code != 0) 753 goto badcode; 754 if (icmp6len < sizeof(struct nd_router_solicit)) 755 goto badlen; 756 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 757 /* give up local */ 758 nd6_rs_input(m, off, icmp6len); 759 m = NULL; 760 goto freeit; 761 } 762 nd6_rs_input(n, off, icmp6len); 763 /* m stays. */ 764 break; 765 766 case ND_ROUTER_ADVERT: | 757 if (code != 0) 758 goto badcode; 759 if (icmp6len < sizeof(struct nd_router_solicit)) 760 goto badlen; 761 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 762 /* give up local */ 763 nd6_rs_input(m, off, icmp6len); 764 m = NULL; 765 goto freeit; 766 } 767 nd6_rs_input(n, off, icmp6len); 768 /* m stays. */ 769 break; 770 771 case ND_ROUTER_ADVERT: |
767 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert); | 772 icmp6_ifstat_inc(ifp, ifs6_in_routeradvert); |
768 if (code != 0) 769 goto badcode; 770 if (icmp6len < sizeof(struct nd_router_advert)) 771 goto badlen; 772 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 773 /* give up local */ 774 nd6_ra_input(m, off, icmp6len); 775 m = NULL; 776 goto freeit; 777 } 778 nd6_ra_input(n, off, icmp6len); 779 /* m stays. */ 780 break; 781 782 case ND_NEIGHBOR_SOLICIT: | 773 if (code != 0) 774 goto badcode; 775 if (icmp6len < sizeof(struct nd_router_advert)) 776 goto badlen; 777 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 778 /* give up local */ 779 nd6_ra_input(m, off, icmp6len); 780 m = NULL; 781 goto freeit; 782 } 783 nd6_ra_input(n, off, icmp6len); 784 /* m stays. */ 785 break; 786 787 case ND_NEIGHBOR_SOLICIT: |
783 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit); | 788 icmp6_ifstat_inc(ifp, ifs6_in_neighborsolicit); |
784 if (code != 0) 785 goto badcode; 786 if (icmp6len < sizeof(struct nd_neighbor_solicit)) 787 goto badlen; 788 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 789 /* give up local */ 790 nd6_ns_input(m, off, icmp6len); 791 m = NULL; 792 goto freeit; 793 } 794 nd6_ns_input(n, off, icmp6len); 795 /* m stays. */ 796 break; 797 798 case ND_NEIGHBOR_ADVERT: | 789 if (code != 0) 790 goto badcode; 791 if (icmp6len < sizeof(struct nd_neighbor_solicit)) 792 goto badlen; 793 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 794 /* give up local */ 795 nd6_ns_input(m, off, icmp6len); 796 m = NULL; 797 goto freeit; 798 } 799 nd6_ns_input(n, off, icmp6len); 800 /* m stays. */ 801 break; 802 803 case ND_NEIGHBOR_ADVERT: |
799 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert); | 804 icmp6_ifstat_inc(ifp, ifs6_in_neighboradvert); |
800 if (code != 0) 801 goto badcode; 802 if (icmp6len < sizeof(struct nd_neighbor_advert)) 803 goto badlen; 804 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 805 /* give up local */ 806 nd6_na_input(m, off, icmp6len); 807 m = NULL; 808 goto freeit; 809 } 810 nd6_na_input(n, off, icmp6len); 811 /* m stays. */ 812 break; 813 814 case ND_REDIRECT: | 805 if (code != 0) 806 goto badcode; 807 if (icmp6len < sizeof(struct nd_neighbor_advert)) 808 goto badlen; 809 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 810 /* give up local */ 811 nd6_na_input(m, off, icmp6len); 812 m = NULL; 813 goto freeit; 814 } 815 nd6_na_input(n, off, icmp6len); 816 /* m stays. */ 817 break; 818 819 case ND_REDIRECT: |
815 icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect); | 820 icmp6_ifstat_inc(ifp, ifs6_in_redirect); |
816 if (code != 0) 817 goto badcode; 818 if (icmp6len < sizeof(struct nd_redirect)) 819 goto badlen; 820 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 821 /* give up local */ 822 icmp6_redirect_input(m, off); 823 m = NULL; --- 11 unchanged lines hidden (view full) --- 835 goto badlen; 836 break; 837 838 default: 839 nd6log((LOG_DEBUG, 840 "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n", 841 icmp6->icmp6_type, ip6_sprintf(ip6bufs, &ip6->ip6_src), 842 ip6_sprintf(ip6bufd, &ip6->ip6_dst), | 821 if (code != 0) 822 goto badcode; 823 if (icmp6len < sizeof(struct nd_redirect)) 824 goto badlen; 825 if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) { 826 /* give up local */ 827 icmp6_redirect_input(m, off); 828 m = NULL; --- 11 unchanged lines hidden (view full) --- 840 goto badlen; 841 break; 842 843 default: 844 nd6log((LOG_DEBUG, 845 "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n", 846 icmp6->icmp6_type, ip6_sprintf(ip6bufs, &ip6->ip6_src), 847 ip6_sprintf(ip6bufd, &ip6->ip6_dst), |
843 m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0)); | 848 ifp ? ifp->if_index : 0)); |
844 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { 845 /* ICMPv6 error: MUST deliver it by spec... */ 846 code = PRC_NCMDS; 847 /* deliver */ 848 } else { 849 /* ICMPv6 informational: MUST not deliver */ 850 break; 851 } --- 1991 unchanged lines hidden --- | 849 if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { 850 /* ICMPv6 error: MUST deliver it by spec... */ 851 code = PRC_NCMDS; 852 /* deliver */ 853 } else { 854 /* ICMPv6 informational: MUST not deliver */ 855 break; 856 } --- 1991 unchanged lines hidden --- |