@@ -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 */
@@ -2577,29 +2618,39 @@ int decode_icmp_ipv6(
25772618 if (verbose_flag ) {
25782619 char buf [INET6_ADDRSTRLEN ];
25792620 getnameinfo (response_addr , response_addr_len , buf , INET6_ADDRSTRLEN , NULL , 0 , NI_NUMERICHOST );
2580- printf ("received packet too short for ICMP (%d bytes from %s)\n" , (int )reply_buf_len , buf );
2621+ printf ("received packet too short for ICMPv6 (%d bytes from %s)\n" , (int )reply_buf_len , buf );
25812622 }
25822623 return 0 ; /* too short */
25832624 }
25842625
25852626 icp = (struct icmp6_hdr * )reply_buf ;
25862627
25872628 if (icp -> icmp6_type != ICMP6_ECHO_REPLY ) {
2588- /* Handle other ICMP packets */
2629+ /* Handle other ICMPv6 packets */
2630+ struct ip6_hdr * sent_ipv6 ;
25892631 struct icmp6_hdr * sent_icmp ;
25902632 SEQMAP_VALUE * seqmap_value ;
25912633 char addr_ascii [INET6_ADDRSTRLEN ];
25922634 HOST_ENTRY * h ;
25932635
2594- /* reply icmp packet (ICMP_MINLEN ) followed by "sent packet" (ip + icmp headers ) */
2595- if (reply_buf_len < ICMP_MINLEN + sizeof (struct ip ) + ICMP_MINLEN ) {
2596- /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
2636+ /* reply icmp packet (ICMPv6 header ) followed by "sent packet" (IPv6 + ICMPv6 header ) */
2637+ if (reply_buf_len < ICMP_MINLEN + sizeof (struct ip6_hdr ) + sizeof ( struct icmp6_hdr ) ) {
2638+ /* discard ICMPv6 message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
25972639 return 0 ;
25982640 }
25992641
2600- sent_icmp = (struct icmp6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ) + sizeof (struct ip ));
2642+ sent_ipv6 = (struct ip6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ));
2643+ if (sent_ipv6 -> ip6_nxt != IPPROTO_ICMPV6 ) {
2644+ /* discard ICMPv6 message if we can't tell that it was caused by
2645+ * us, because the IPv6 header is not directly followed by an
2646+ * ICMPv6 header
2647+ */
2648+ dbg_printf ("invoking packet next header is %d\n" , sent_ipv6 -> ip6_nxt );
2649+ return 0 ;
2650+ }
2651+ sent_icmp = (struct icmp6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ) + sizeof (struct ip6_hdr ));
26012652
2602- if (sent_icmp -> icmp6_type != ICMP_ECHO || sent_icmp -> icmp6_id != ident6 ) {
2653+ if (sent_icmp -> icmp6_type != ICMP6_ECHO_REQUEST || sent_icmp -> icmp6_id != ident6 ) {
26032654 /* not caused by us */
26042655 return 0 ;
26052656 }
@@ -2610,39 +2661,56 @@ int decode_icmp_ipv6(
26102661 }
26112662
26122663 getnameinfo (response_addr , response_addr_len , addr_ascii , INET6_ADDRSTRLEN , NULL , 0 , NI_NUMERICHOST );
2664+ h = table [seqmap_value -> host_nr ];
26132665
26142666 switch (icp -> icmp6_type ) {
2615- case ICMP_UNREACH :
2616- h = table [seqmap_value -> host_nr ];
2617- if (icp -> icmp6_code > ICMP_UNREACH_MAXTYPE ) {
2618- print_warning ("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s" ,
2619- addr_ascii , h -> host );
2620- }
2621- else {
2622- print_warning ("%s from %s for ICMP Echo sent to %s" ,
2623- icmp_unreach_str [icp -> icmp6_code ], addr_ascii , h -> host );
2667+ case ICMP6_DST_UNREACH :
2668+ if (icp -> icmp6_code > ICMP6_UNREACH_MAXCODE ) {
2669+ print_warning ("ICMPv6 Destination Unreachable (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2670+ icp -> icmp6_code , addr_ascii , h -> host );
2671+ } else {
2672+ print_warning ("ICMPv6 Destination Unreachable (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2673+ icmp6_unreach_str [icp -> icmp6_code ], addr_ascii , h -> host );
26242674 }
2625-
26262675 print_warning ("\n" );
26272676 num_othericmprcvd ++ ;
26282677 break ;
26292678
2630- case ICMP_SOURCEQUENCH :
2631- case ICMP_REDIRECT :
2632- case ICMP_TIMXCEED :
2633- case ICMP_PARAMPROB :
2634- h = table [seqmap_value -> host_nr ];
2635- if (icp -> icmp6_type <= ICMP_TYPE_STR_MAX ) {
2636- print_warning ("%s from %s for ICMP Echo sent to %s" ,
2637- icmp_type_str [icp -> icmp6_type ], addr_ascii , h -> host );
2679+ case ICMP6_PACKET_TOO_BIG :
2680+ print_warning ("ICMPv6 Packet Too Big from %s for ICMPv6 Echo Request sent to %s\n" ,
2681+ addr_ascii , h -> host );
2682+ num_othericmprcvd ++ ;
2683+ break ;
2684+
2685+ case ICMP6_TIME_EXCEEDED :
2686+ if (icp -> icmp6_code > ICMP6_TIME_EXCEEDED_MAXCODE ) {
2687+ print_warning ("ICMPv6 Time Exceeded (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2688+ icp -> icmp6_code , addr_ascii , h -> host );
2689+ } else {
2690+ print_warning ("ICMPv6 Time Exceeded (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2691+ icmp6_time_exceeded_str [icp -> icmp6_code ], addr_ascii , h -> host );
26382692 }
2639- else {
2640- print_warning ("ICMP %d from %s for ICMP Echo sent to %s" ,
2641- icp -> icmp6_type , addr_ascii , h -> host );
2693+ print_warning ("\n" );
2694+ num_othericmprcvd ++ ;
2695+ break ;
2696+
2697+ case ICMP6_PARAM_PROB :
2698+ if (icp -> icmp6_code > ICMP6_PARAM_PROB_MAXCODE ) {
2699+ print_warning ("ICMPv6 Parameter Problem (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2700+ icp -> icmp6_code , addr_ascii , h -> host );
2701+ } else {
2702+ print_warning ("ICMPv6 Parameter Problem (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2703+ icmp6_param_prob_str [icp -> icmp6_code ], addr_ascii , h -> host );
26422704 }
26432705 print_warning ("\n" );
26442706 num_othericmprcvd ++ ;
26452707 break ;
2708+
2709+ default :
2710+ print_warning ("ICMPv6 Type %d Code %d from %s for ICMPv6 Echo Request sent to %s\n" ,
2711+ icp -> icmp6_type , icp -> icmp6_code , addr_ascii , h -> host );
2712+ num_othericmprcvd ++ ;
2713+ break ;
26462714 }
26472715
26482716 return 0 ;
0 commit comments