diff options
author | Michael Brown | 2015-05-11 13:45:14 +0200 |
---|---|---|
committer | Michael Brown | 2015-05-11 13:45:14 +0200 |
commit | 86aa959561be5a1cc075c8c60c2f9fdc37ab9272 (patch) | |
tree | cf3279e296f4c56166eb9ffe9621fee140e734c8 /src/net/icmpv6.c | |
parent | [uhci] Use meaningful device names in debug messages (diff) | |
download | ipxe-86aa959561be5a1cc075c8c60c2f9fdc37ab9272.tar.gz ipxe-86aa959561be5a1cc075c8c60c2f9fdc37ab9272.tar.xz ipxe-86aa959561be5a1cc075c8c60c2f9fdc37ab9272.zip |
[ipv6] Disambiguate received ICMPv6 errors
Originally-implemented-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/icmpv6.c')
-rw-r--r-- | src/net/icmpv6.c | 80 |
1 files changed, 78 insertions, 2 deletions
diff --git a/src/net/icmpv6.c b/src/net/icmpv6.c index 45a34440..8555aaf0 100644 --- a/src/net/icmpv6.c +++ b/src/net/icmpv6.c @@ -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; } |