@@ -70,6 +70,7 @@ extern "C" {
7070
7171#ifdef IPV6
7272#include <netinet/icmp6.h>
73+ #include <netinet/ip6.h>
7374#endif
7475#include <netinet/in_systm.h>
7576
@@ -218,6 +219,46 @@ char *icmp_unreach_str[16] = {
218219
219220#define ICMP_UNREACH_MAXTYPE 15
220221
222+ #ifdef IPV6
223+ /* Long names for ICMPv6 unreachable codes */
224+ #define ICMP6_UNREACH_MAXCODE 9
225+ char * icmp6_unreach_str [ICMP6_UNREACH_MAXCODE + 1 ] = {
226+ "No route to destination" , /* 0 */
227+ "Communication with destination administratively prohibited" , /* 1 */
228+ "Beyond scope of source address" , /* 2 */
229+ "Address unreachable" , /* 3 */
230+ "Port unreachable" , /* 4 */
231+ "Source address failed ingress/egress policy" , /* 5 */
232+ "Reject route to destination" , /* 6 */
233+ "Error in Source Routing Header" , /* 7 */
234+ "Headers too long" , /* 8 */
235+ "Error in P-Route" , /* 9 */
236+ };
237+
238+ /* Long names for ICMPv6 time exceeded codes */
239+ #define ICMP6_TIME_EXCEEDED_MAXCODE 1
240+ char * icmp6_time_exceeded_str [ICMP6_TIME_EXCEEDED_MAXCODE + 1 ] = {
241+ "Hop limit exceeded in transit" , /* 0 */
242+ "Fragment reassembly time exceeded" , /* 1 */
243+ };
244+
245+ /* Long names for ICMPv6 parameter problem codes */
246+ #define ICMP6_PARAM_PROB_MAXCODE 10
247+ char * icmp6_param_prob_str [ICMP6_PARAM_PROB_MAXCODE + 1 ] = {
248+ "Erroneous header field encountered" , /* 0 */
249+ "Unrecognized Next Header type encountered" , /* 1 */
250+ "Unrecognized IPv6 option encountered" , /* 2 */
251+ "IPv6 First Fragment has incomplete IPv6 Header Chain" , /* 3 */
252+ "SR Upper-layer Header Error" , /* 4 */
253+ "Unrecognized Next Header type encountered by intermediate node" , /* 5 */
254+ "Extension header too big" , /* 6 */
255+ "Extension header chain too long" , /* 7 */
256+ "Too many extension headers" , /* 8 */
257+ "Too many options in extension header" , /* 9 */
258+ "Option too big" , /* 10 */
259+ };
260+ #endif
261+
221262struct event ;
222263typedef struct host_entry {
223264 int i ; /* index into array */
@@ -2629,29 +2670,39 @@ int decode_icmp_ipv6(
26292670 if (verbose_flag ) {
26302671 char buf [INET6_ADDRSTRLEN ];
26312672 getnameinfo (response_addr , response_addr_len , buf , INET6_ADDRSTRLEN , NULL , 0 , NI_NUMERICHOST );
2632- printf ("received packet too short for ICMP (%d bytes from %s)\n" , (int )reply_buf_len , buf );
2673+ printf ("received packet too short for ICMPv6 (%d bytes from %s)\n" , (int )reply_buf_len , buf );
26332674 }
26342675 return 0 ; /* too short */
26352676 }
26362677
26372678 icp = (struct icmp6_hdr * )reply_buf ;
26382679
26392680 if (icp -> icmp6_type != ICMP6_ECHO_REPLY ) {
2640- /* Handle other ICMP packets */
2681+ /* Handle other ICMPv6 packets */
2682+ struct ip6_hdr * sent_ipv6 ;
26412683 struct icmp6_hdr * sent_icmp ;
26422684 SEQMAP_VALUE * seqmap_value ;
26432685 char addr_ascii [INET6_ADDRSTRLEN ];
26442686 HOST_ENTRY * h ;
26452687
2646- /* reply icmp packet (ICMP_MINLEN ) followed by "sent packet" (ip + icmp headers ) */
2647- if (reply_buf_len < ICMP_MINLEN + sizeof (struct ip ) + ICMP_MINLEN ) {
2648- /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
2688+ /* reply icmp packet (ICMPv6 header ) followed by "sent packet" (IPv6 + ICMPv6 header ) */
2689+ if (reply_buf_len < ICMP_MINLEN + sizeof (struct ip6_hdr ) + sizeof ( struct icmp6_hdr ) ) {
2690+ /* discard ICMPv6 message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
26492691 return 0 ;
26502692 }
26512693
2652- sent_icmp = (struct icmp6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ) + sizeof (struct ip ));
2694+ sent_ipv6 = (struct ip6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ));
2695+ if (sent_ipv6 -> ip6_nxt != IPPROTO_ICMPV6 ) {
2696+ /* discard ICMPv6 message if we can't tell that it was caused by
2697+ * us, because the IPv6 header is not directly followed by an
2698+ * ICMPv6 header
2699+ */
2700+ dbg_printf ("invoking packet next header is %d\n" , sent_ipv6 -> ip6_nxt );
2701+ return 0 ;
2702+ }
2703+ sent_icmp = (struct icmp6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ) + sizeof (struct ip6_hdr ));
26532704
2654- if (sent_icmp -> icmp6_type != ICMP_ECHO || sent_icmp -> icmp6_id != ident6 ) {
2705+ if (sent_icmp -> icmp6_type != ICMP6_ECHO_REQUEST || sent_icmp -> icmp6_id != ident6 ) {
26552706 /* not caused by us */
26562707 return 0 ;
26572708 }
@@ -2662,39 +2713,56 @@ int decode_icmp_ipv6(
26622713 }
26632714
26642715 getnameinfo (response_addr , response_addr_len , addr_ascii , INET6_ADDRSTRLEN , NULL , 0 , NI_NUMERICHOST );
2716+ h = table [seqmap_value -> host_nr ];
26652717
26662718 switch (icp -> icmp6_type ) {
2667- case ICMP_UNREACH :
2668- h = table [seqmap_value -> host_nr ];
2669- if (icp -> icmp6_code > ICMP_UNREACH_MAXTYPE ) {
2670- print_warning ("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s" ,
2671- addr_ascii , h -> host );
2672- }
2673- else {
2674- print_warning ("%s from %s for ICMP Echo sent to %s" ,
2675- icmp_unreach_str [icp -> icmp6_code ], addr_ascii , h -> host );
2719+ case ICMP6_DST_UNREACH :
2720+ if (icp -> icmp6_code > ICMP6_UNREACH_MAXCODE ) {
2721+ print_warning ("ICMPv6 Destination Unreachable (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2722+ icp -> icmp6_code , addr_ascii , h -> host );
2723+ } else {
2724+ print_warning ("ICMPv6 Destination Unreachable (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2725+ icmp6_unreach_str [icp -> icmp6_code ], addr_ascii , h -> host );
26762726 }
2677-
26782727 print_warning ("\n" );
26792728 num_othericmprcvd ++ ;
26802729 break ;
26812730
2682- case ICMP_SOURCEQUENCH :
2683- case ICMP_REDIRECT :
2684- case ICMP_TIMXCEED :
2685- case ICMP_PARAMPROB :
2686- h = table [seqmap_value -> host_nr ];
2687- if (icp -> icmp6_type <= ICMP_TYPE_STR_MAX ) {
2688- print_warning ("%s from %s for ICMP Echo sent to %s" ,
2689- icmp_type_str [icp -> icmp6_type ], addr_ascii , h -> host );
2731+ case ICMP6_PACKET_TOO_BIG :
2732+ print_warning ("ICMPv6 Packet Too Big from %s for ICMPv6 Echo Request sent to %s\n" ,
2733+ addr_ascii , h -> host );
2734+ num_othericmprcvd ++ ;
2735+ break ;
2736+
2737+ case ICMP6_TIME_EXCEEDED :
2738+ if (icp -> icmp6_code > ICMP6_TIME_EXCEEDED_MAXCODE ) {
2739+ print_warning ("ICMPv6 Time Exceeded (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2740+ icp -> icmp6_code , addr_ascii , h -> host );
2741+ } else {
2742+ print_warning ("ICMPv6 Time Exceeded (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2743+ icmp6_time_exceeded_str [icp -> icmp6_code ], addr_ascii , h -> host );
26902744 }
2691- else {
2692- print_warning ("ICMP %d from %s for ICMP Echo sent to %s" ,
2693- icp -> icmp6_type , addr_ascii , h -> host );
2745+ print_warning ("\n" );
2746+ num_othericmprcvd ++ ;
2747+ break ;
2748+
2749+ case ICMP6_PARAM_PROB :
2750+ if (icp -> icmp6_code > ICMP6_PARAM_PROB_MAXCODE ) {
2751+ print_warning ("ICMPv6 Parameter Problem (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2752+ icp -> icmp6_code , addr_ascii , h -> host );
2753+ } else {
2754+ print_warning ("ICMPv6 Parameter Problem (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2755+ icmp6_param_prob_str [icp -> icmp6_code ], addr_ascii , h -> host );
26942756 }
26952757 print_warning ("\n" );
26962758 num_othericmprcvd ++ ;
26972759 break ;
2760+
2761+ default :
2762+ print_warning ("ICMPv6 Type %d Code %d from %s for ICMPv6 Echo Request sent to %s\n" ,
2763+ icp -> icmp6_type , icp -> icmp6_code , addr_ascii , h -> host );
2764+ num_othericmprcvd ++ ;
2765+ break ;
26982766 }
26992767
27002768 return 0 ;
0 commit comments