summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/net/icmpv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/ipxe/src/net/icmpv6.c')
-rw-r--r--qemu/roms/ipxe/src/net/icmpv6.c86
1 files changed, 83 insertions, 3 deletions
diff --git a/qemu/roms/ipxe/src/net/icmpv6.c b/qemu/roms/ipxe/src/net/icmpv6.c
index 479800e7d..8555aaf0b 100644
--- a/qemu/roms/ipxe/src/net/icmpv6.c
+++ b/qemu/roms/ipxe/src/net/icmpv6.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <errno.h>
@@ -34,6 +38,65 @@ FILE_LICENCE ( GPL2_OR_LATER );
*
*/
+/* 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;
/**
@@ -144,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;
}