]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[ipv6] Disambiguate received ICMPv6 errors
authorMichael Brown <mcb30@ipxe.org>
Mon, 11 May 2015 11:45:14 +0000 (12:45 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 11 May 2015 11:45:14 +0000 (12:45 +0100)
Originally-implemented-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/icmpv6.h
src/net/icmpv6.c

index db5bec2d2b92030b76f38bd595c37e7889daec18..0474ddca83467053bb2151a429d5a2308dc38ba0 100644 (file)
@@ -40,6 +40,18 @@ struct icmpv6_handler {
 /** Declare an ICMPv6 handler */
 #define __icmpv6_handler __table_entry ( ICMPV6_HANDLERS, 01 )
 
+/** ICMPv6 destination unreachable */
+#define ICMPV6_DESTINATION_UNREACHABLE 1
+
+/** ICMPv6 packet too big */
+#define ICMPV6_PACKET_TOO_BIG 2
+
+/** ICMPv6 time exceeded */
+#define ICMPV6_TIME_EXCEEDED 3
+
+/** ICMPv6 parameter problem */
+#define ICMPV6_PARAMETER_PROBLEM 4
+
 /** ICMPv6 echo request */
 #define ICMPV6_ECHO_REQUEST 128
 
index 45a344407d0e053a9e5399eba1a80e69f169c627..8555aaf0b50894d652e76a1acaad1355a363e368 100644 (file)
@@ -38,6 +38,65 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  *
  */
 
+/* Disambiguate the various error causes */
+#define EHOSTUNREACH_ROUTE                                             \
+       __einfo_error ( EINFO_EHOSTUNREACH_ROUTE )
+#define EINFO_EHOSTUNREACH_ROUTE                                       \
+       __einfo_uniqify ( EINFO_EHOSTUNREACH, 0,                        \
+                         "No route to destination" )
+#define EHOSTUNREACH_PROHIBITED                                                \
+       __einfo_error ( EINFO_EHOSTUNREACH_PROHIBITED )
+#define EINFO_EHOSTUNREACH_PROHIBITED                                  \
+       __einfo_uniqify ( EINFO_EHOSTUNREACH, 1,                        \
+                         "Communication administratively prohibited" )
+#define EHOSTUNREACH_ADDRESS                                           \
+       __einfo_error ( EINFO_EHOSTUNREACH_ADDRESS )
+#define EINFO_EHOSTUNREACH_ADDRESS                                     \
+       __einfo_uniqify ( EINFO_EHOSTUNREACH, 3,                        \
+                         "Address unreachable" )
+#define EHOSTUNREACH_PORT                                              \
+       __einfo_error ( EINFO_EHOSTUNREACH_PORT )
+#define EINFO_EHOSTUNREACH_PORT                                                \
+       __einfo_uniqify ( EINFO_EHOSTUNREACH, 4,                        \
+                         "Port unreachable" )
+#define EHOSTUNREACH_CODE( code )                                      \
+       EUNIQ ( EINFO_EHOSTUNREACH, ( (code) & 0x1f ),                  \
+               EHOSTUNREACH_ROUTE, EHOSTUNREACH_PROHIBITED,            \
+               EHOSTUNREACH_ADDRESS, EHOSTUNREACH_PORT )
+
+#define ETIMEDOUT_HOP                                                  \
+       __einfo_error ( EINFO_ETIMEDOUT_HOP )
+#define EINFO_ETIMEDOUT_HOP                                            \
+       __einfo_uniqify ( EINFO_ETIMEDOUT, 0,                           \
+                         "Hop limit exceeded in transit" )
+#define ETIMEDOUT_REASSEMBLY                                           \
+       __einfo_error ( EINFO_ETIMEDOUT_REASSEMBLY )
+#define EINFO_ETIMEDOUT_REASSEMBLY                                     \
+       __einfo_uniqify ( EINFO_ETIMEDOUT, 1,                           \
+                         "Fragment reassembly time exceeded" )
+#define ETIMEDOUT_CODE( code )                                         \
+       EUNIQ ( EINFO_ETIMEDOUT, ( (code) & 0x1f ),                     \
+               ETIMEDOUT_HOP, ETIMEDOUT_REASSEMBLY )
+
+#define EPROTO_BAD_HEADER                                              \
+       __einfo_error ( EINFO_EPROTO_BAD_HEADER )
+#define EINFO_EPROTO_BAD_HEADER                                                \
+       __einfo_uniqify ( EINFO_EPROTO, 0,                              \
+                         "Erroneous header field" )
+#define EPROTO_NEXT_HEADER                                             \
+       __einfo_error ( EINFO_EPROTO_NEXT_HEADER )
+#define EINFO_EPROTO_NEXT_HEADER                                       \
+       __einfo_uniqify ( EINFO_EPROTO, 1,                              \
+                         "Unrecognised next header type" )
+#define EPROTO_OPTION                                                  \
+       __einfo_error ( EINFO_EPROTO_OPTION )
+#define EINFO_EPROTO_OPTION                                            \
+       __einfo_uniqify ( EINFO_EPROTO, 2,                              \
+                         "Unrecognised IPv6 option" )
+#define EPROTO_CODE( code )                                            \
+       EUNIQ ( EINFO_EPROTO, ( (code) & 0x1f ),                        \
+               EPROTO_BAD_HEADER, EPROTO_NEXT_HEADER, EPROTO_OPTION )
+
 struct icmp_echo_protocol icmpv6_echo_protocol __icmp_echo_protocol;
 
 /**
@@ -148,8 +207,25 @@ static int icmpv6_rx ( struct io_buffer *iobuf, struct net_device *netdev,
        /* Identify handler */
        handler = icmpv6_handler ( icmp->type );
        if ( ! handler ) {
-               DBGC ( netdev, "ICMPv6 unrecognised type %d\n", icmp->type );
-               rc = -ENOTSUP;
+               switch ( icmp->type ) {
+               case ICMPV6_DESTINATION_UNREACHABLE:
+                       rc = -EHOSTUNREACH_CODE ( icmp->code );
+                       break;
+               case ICMPV6_PACKET_TOO_BIG:
+                       rc = -ERANGE;
+                       break;
+               case ICMPV6_TIME_EXCEEDED:
+                       rc = -ETIMEDOUT_CODE ( icmp->code );
+                       break;
+               case ICMPV6_PARAMETER_PROBLEM:
+                       rc = -EPROTO_CODE ( icmp->code );
+                       break;
+               default:
+                       DBGC ( netdev, "ICMPv6 unrecognised type %d code %d\n",
+                              icmp->type, icmp->code );
+                       rc = -ENOTSUP;
+                       break;
+               };
                goto done;
        }