Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[ipv6] Disambiguate received ICMPv6 errors
Originally-implemented-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed May 11, 2015
1 parent bb6d7be commit 86aa959
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 2 deletions.
12 changes: 12 additions & 0 deletions src/include/ipxe/icmpv6.h
Expand Up @@ -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

Expand Down
80 changes: 78 additions & 2 deletions src/net/icmpv6.c
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 86aa959

Please sign in to comment.