@@ -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 */
@@ -2620,29 +2661,39 @@ int decode_icmp_ipv6(
26202661 if (verbose_flag ) {
26212662 char buf [INET6_ADDRSTRLEN ];
26222663 getnameinfo (response_addr , response_addr_len , buf , INET6_ADDRSTRLEN , NULL , 0 , NI_NUMERICHOST );
2623- printf ("received packet too short for ICMP (%d bytes from %s)\n" , (int )reply_buf_len , buf );
2664+ printf ("received packet too short for ICMPv6 (%d bytes from %s)\n" , (int )reply_buf_len , buf );
26242665 }
26252666 return 0 ; /* too short */
26262667 }
26272668
26282669 icp = (struct icmp6_hdr * )reply_buf ;
26292670
26302671 if (icp -> icmp6_type != ICMP6_ECHO_REPLY ) {
2631- /* Handle other ICMP packets */
2672+ /* Handle other ICMPv6 packets */
2673+ struct ip6_hdr * sent_ipv6 ;
26322674 struct icmp6_hdr * sent_icmp ;
26332675 SEQMAP_VALUE * seqmap_value ;
26342676 char addr_ascii [INET6_ADDRSTRLEN ];
26352677 HOST_ENTRY * h ;
26362678
2637- /* reply icmp packet (ICMP_MINLEN ) followed by "sent packet" (ip + icmp headers ) */
2638- if (reply_buf_len < ICMP_MINLEN + sizeof (struct ip ) + ICMP_MINLEN ) {
2639- /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
2679+ /* reply icmp packet (ICMPv6 header ) followed by "sent packet" (IPv6 + ICMPv6 header ) */
2680+ if (reply_buf_len < ICMP_MINLEN + sizeof (struct ip6_hdr ) + sizeof ( struct icmp6_hdr ) ) {
2681+ /* discard ICMPv6 message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
26402682 return 0 ;
26412683 }
26422684
2643- sent_icmp = (struct icmp6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ) + sizeof (struct ip ));
2685+ sent_ipv6 = (struct ip6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ));
2686+ if (sent_ipv6 -> ip6_nxt != IPPROTO_ICMPV6 ) {
2687+ /* discard ICMPv6 message if we can't tell that it was caused by
2688+ * us, because the IPv6 header is not directly followed by an
2689+ * ICMPv6 header
2690+ */
2691+ dbg_printf ("invoking packet next header is %d\n" , sent_ipv6 -> ip6_nxt );
2692+ return 0 ;
2693+ }
2694+ sent_icmp = (struct icmp6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ) + sizeof (struct ip6_hdr ));
26442695
2645- if (sent_icmp -> icmp6_type != ICMP_ECHO || sent_icmp -> icmp6_id != ident6 ) {
2696+ if (sent_icmp -> icmp6_type != ICMP6_ECHO_REQUEST || sent_icmp -> icmp6_id != ident6 ) {
26462697 /* not caused by us */
26472698 return 0 ;
26482699 }
@@ -2653,39 +2704,56 @@ int decode_icmp_ipv6(
26532704 }
26542705
26552706 getnameinfo (response_addr , response_addr_len , addr_ascii , INET6_ADDRSTRLEN , NULL , 0 , NI_NUMERICHOST );
2707+ h = table [seqmap_value -> host_nr ];
26562708
26572709 switch (icp -> icmp6_type ) {
2658- case ICMP_UNREACH :
2659- h = table [seqmap_value -> host_nr ];
2660- if (icp -> icmp6_code > ICMP_UNREACH_MAXTYPE ) {
2661- print_warning ("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s" ,
2662- addr_ascii , h -> host );
2663- }
2664- else {
2665- print_warning ("%s from %s for ICMP Echo sent to %s" ,
2666- icmp_unreach_str [icp -> icmp6_code ], addr_ascii , h -> host );
2710+ case ICMP6_DST_UNREACH :
2711+ if (icp -> icmp6_code > ICMP6_UNREACH_MAXCODE ) {
2712+ print_warning ("ICMPv6 Destination Unreachable (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2713+ icp -> icmp6_code , addr_ascii , h -> host );
2714+ } else {
2715+ print_warning ("ICMPv6 Destination Unreachable (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2716+ icmp6_unreach_str [icp -> icmp6_code ], addr_ascii , h -> host );
26672717 }
2668-
26692718 print_warning ("\n" );
26702719 num_othericmprcvd ++ ;
26712720 break ;
26722721
2673- case ICMP_SOURCEQUENCH :
2674- case ICMP_REDIRECT :
2675- case ICMP_TIMXCEED :
2676- case ICMP_PARAMPROB :
2677- h = table [seqmap_value -> host_nr ];
2678- if (icp -> icmp6_type <= ICMP_TYPE_STR_MAX ) {
2679- print_warning ("%s from %s for ICMP Echo sent to %s" ,
2680- icmp_type_str [icp -> icmp6_type ], addr_ascii , h -> host );
2722+ case ICMP6_PACKET_TOO_BIG :
2723+ print_warning ("ICMPv6 Packet Too Big from %s for ICMPv6 Echo Request sent to %s\n" ,
2724+ addr_ascii , h -> host );
2725+ num_othericmprcvd ++ ;
2726+ break ;
2727+
2728+ case ICMP6_TIME_EXCEEDED :
2729+ if (icp -> icmp6_code > ICMP6_TIME_EXCEEDED_MAXCODE ) {
2730+ print_warning ("ICMPv6 Time Exceeded (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2731+ icp -> icmp6_code , addr_ascii , h -> host );
2732+ } else {
2733+ print_warning ("ICMPv6 Time Exceeded (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2734+ icmp6_time_exceeded_str [icp -> icmp6_code ], addr_ascii , h -> host );
26812735 }
2682- else {
2683- print_warning ("ICMP %d from %s for ICMP Echo sent to %s" ,
2684- icp -> icmp6_type , addr_ascii , h -> host );
2736+ print_warning ("\n" );
2737+ num_othericmprcvd ++ ;
2738+ break ;
2739+
2740+ case ICMP6_PARAM_PROB :
2741+ if (icp -> icmp6_code > ICMP6_PARAM_PROB_MAXCODE ) {
2742+ print_warning ("ICMPv6 Parameter Problem (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2743+ icp -> icmp6_code , addr_ascii , h -> host );
2744+ } else {
2745+ print_warning ("ICMPv6 Parameter Problem (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2746+ icmp6_param_prob_str [icp -> icmp6_code ], addr_ascii , h -> host );
26852747 }
26862748 print_warning ("\n" );
26872749 num_othericmprcvd ++ ;
26882750 break ;
2751+
2752+ default :
2753+ print_warning ("ICMPv6 Type %d Code %d from %s for ICMPv6 Echo Request sent to %s\n" ,
2754+ icp -> icmp6_type , icp -> icmp6_code , addr_ascii , h -> host );
2755+ num_othericmprcvd ++ ;
2756+ break ;
26892757 }
26902758
26912759 return 0 ;
0 commit comments