@@ -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 */
@@ -2864,29 +2905,39 @@ int decode_icmp_ipv6(
28642905 if (verbose_flag ) {
28652906 char buf [INET6_ADDRSTRLEN ];
28662907 getnameinfo (response_addr , response_addr_len , buf , INET6_ADDRSTRLEN , NULL , 0 , NI_NUMERICHOST );
2867- printf ("received packet too short for ICMP (%d bytes from %s)\n" , (int )reply_buf_len , buf );
2908+ printf ("received packet too short for ICMPv6 (%d bytes from %s)\n" , (int )reply_buf_len , buf );
28682909 }
28692910 return 0 ; /* too short */
28702911 }
28712912
28722913 icp = (struct icmp6_hdr * )reply_buf ;
28732914
28742915 if (icp -> icmp6_type != ICMP6_ECHO_REPLY ) {
2875- /* Handle other ICMP packets */
2916+ /* Handle other ICMPv6 packets */
2917+ struct ip6_hdr * sent_ipv6 ;
28762918 struct icmp6_hdr * sent_icmp ;
28772919 SEQMAP_VALUE * seqmap_value ;
28782920 char addr_ascii [INET6_ADDRSTRLEN ];
28792921 HOST_ENTRY * h ;
28802922
2881- /* reply icmp packet (ICMP_MINLEN ) followed by "sent packet" (ip + icmp headers ) */
2882- if (reply_buf_len < ICMP_MINLEN + sizeof (struct ip ) + ICMP_MINLEN ) {
2883- /* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
2923+ /* reply icmp packet (ICMPv6 header ) followed by "sent packet" (IPv6 + ICMPv6 header ) */
2924+ if (reply_buf_len < ICMP_MINLEN + sizeof (struct ip6_hdr ) + sizeof ( struct icmp6_hdr ) ) {
2925+ /* discard ICMPv6 message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
28842926 return 0 ;
28852927 }
28862928
2887- sent_icmp = (struct icmp6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ) + sizeof (struct ip ));
2929+ sent_ipv6 = (struct ip6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ));
2930+ if (sent_ipv6 -> ip6_nxt != IPPROTO_ICMPV6 ) {
2931+ /* discard ICMPv6 message if we can't tell that it was caused by
2932+ * us, because the IPv6 header is not directly followed by an
2933+ * ICMPv6 header
2934+ */
2935+ dbg_printf ("invoking packet next header is %d\n" , sent_ipv6 -> ip6_nxt );
2936+ return 0 ;
2937+ }
2938+ sent_icmp = (struct icmp6_hdr * )(reply_buf + sizeof (struct icmp6_hdr ) + sizeof (struct ip6_hdr ));
28882939
2889- if (sent_icmp -> icmp6_type != ICMP_ECHO || sent_icmp -> icmp6_id != ident6 ) {
2940+ if (sent_icmp -> icmp6_type != ICMP6_ECHO_REQUEST || sent_icmp -> icmp6_id != ident6 ) {
28902941 /* not caused by us */
28912942 return 0 ;
28922943 }
@@ -2897,39 +2948,56 @@ int decode_icmp_ipv6(
28972948 }
28982949
28992950 getnameinfo (response_addr , response_addr_len , addr_ascii , INET6_ADDRSTRLEN , NULL , 0 , NI_NUMERICHOST );
2951+ h = table [seqmap_value -> host_nr ];
29002952
29012953 switch (icp -> icmp6_type ) {
2902- case ICMP_UNREACH :
2903- h = table [seqmap_value -> host_nr ];
2904- if (icp -> icmp6_code > ICMP_UNREACH_MAXTYPE ) {
2905- print_warning ("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s" ,
2906- addr_ascii , h -> host );
2907- }
2908- else {
2909- print_warning ("%s from %s for ICMP Echo sent to %s" ,
2910- icmp_unreach_str [icp -> icmp6_code ], addr_ascii , h -> host );
2954+ case ICMP6_DST_UNREACH :
2955+ if (icp -> icmp6_code > ICMP6_UNREACH_MAXCODE ) {
2956+ print_warning ("ICMPv6 Destination Unreachable (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2957+ icp -> icmp6_code , addr_ascii , h -> host );
2958+ } else {
2959+ print_warning ("ICMPv6 Destination Unreachable (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2960+ icmp6_unreach_str [icp -> icmp6_code ], addr_ascii , h -> host );
29112961 }
2912-
29132962 print_warning ("\n" );
29142963 num_othericmprcvd ++ ;
29152964 break ;
29162965
2917- case ICMP_SOURCEQUENCH :
2918- case ICMP_REDIRECT :
2919- case ICMP_TIMXCEED :
2920- case ICMP_PARAMPROB :
2921- h = table [seqmap_value -> host_nr ];
2922- if (icp -> icmp6_type <= ICMP_TYPE_STR_MAX ) {
2923- print_warning ("%s from %s for ICMP Echo sent to %s" ,
2924- icmp_type_str [icp -> icmp6_type ], addr_ascii , h -> host );
2966+ case ICMP6_PACKET_TOO_BIG :
2967+ print_warning ("ICMPv6 Packet Too Big from %s for ICMPv6 Echo Request sent to %s\n" ,
2968+ addr_ascii , h -> host );
2969+ num_othericmprcvd ++ ;
2970+ break ;
2971+
2972+ case ICMP6_TIME_EXCEEDED :
2973+ if (icp -> icmp6_code > ICMP6_TIME_EXCEEDED_MAXCODE ) {
2974+ print_warning ("ICMPv6 Time Exceeded (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2975+ icp -> icmp6_code , addr_ascii , h -> host );
2976+ } else {
2977+ print_warning ("ICMPv6 Time Exceeded (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2978+ icmp6_time_exceeded_str [icp -> icmp6_code ], addr_ascii , h -> host );
29252979 }
2926- else {
2927- print_warning ("ICMP %d from %s for ICMP Echo sent to %s" ,
2928- icp -> icmp6_type , addr_ascii , h -> host );
2980+ print_warning ("\n" );
2981+ num_othericmprcvd ++ ;
2982+ break ;
2983+
2984+ case ICMP6_PARAM_PROB :
2985+ if (icp -> icmp6_code > ICMP6_PARAM_PROB_MAXCODE ) {
2986+ print_warning ("ICMPv6 Parameter Problem (Code %d) from %s for ICMPv6 Echo Request sent to %s" ,
2987+ icp -> icmp6_code , addr_ascii , h -> host );
2988+ } else {
2989+ print_warning ("ICMPv6 Parameter Problem (%s) from %s for ICMPv6 Echo Request sent to %s" ,
2990+ icmp6_param_prob_str [icp -> icmp6_code ], addr_ascii , h -> host );
29292991 }
29302992 print_warning ("\n" );
29312993 num_othericmprcvd ++ ;
29322994 break ;
2995+
2996+ default :
2997+ print_warning ("ICMPv6 Type %d Code %d from %s for ICMPv6 Echo Request sent to %s\n" ,
2998+ icp -> icmp6_type , icp -> icmp6_code , addr_ascii , h -> host );
2999+ num_othericmprcvd ++ ;
3000+ break ;
29333001 }
29343002
29353003 return 0 ;
0 commit comments