These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / net / icmpv6.c
index 479800e..8555aaf 100644 (file)
  * 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;
        }