Huw Davies : nsiproxy: Add support for parsing other icmp packets.

Alexandre Julliard julliard at winehq.org
Tue Oct 5 15:51:40 CDT 2021


Module: wine
Branch: master
Commit: 881577deaf508f48cbcedc64739073c9a245f472
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=881577deaf508f48cbcedc64739073c9a245f472

Author: Huw Davies <huw at codeweavers.com>
Date:   Tue Oct  5 07:37:52 2021 +0100

nsiproxy: Add support for parsing other icmp packets.

Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/nsiproxy.sys/icmp_echo.c | 63 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 62 insertions(+), 1 deletion(-)

diff --git a/dlls/nsiproxy.sys/icmp_echo.c b/dlls/nsiproxy.sys/icmp_echo.c
index abcccdb4c73..cef5c04a6c7 100644
--- a/dlls/nsiproxy.sys/icmp_echo.c
+++ b/dlls/nsiproxy.sys/icmp_echo.c
@@ -297,6 +297,30 @@ static BOOL ipv4_linux_ping_parse_ip_hdr( struct msghdr *msg, int recvd,
 static int ipv4_parse_icmp_hdr_( struct icmp_data *data, struct icmp_hdr *icmp, int icmp_size,
                                  struct nsiproxy_icmp_echo_reply *reply, int ping_socket )
 {
+    static const IP_STATUS unreach_codes[] =
+    {
+        IP_DEST_NET_UNREACHABLE,  /* ICMP_UNREACH_NET */
+        IP_DEST_HOST_UNREACHABLE, /* ICMP_UNREACH_HOST */
+        IP_DEST_PROT_UNREACHABLE, /* ICMP_UNREACH_PROTOCOL */
+        IP_DEST_PORT_UNREACHABLE, /* ICMP_UNREACH_PORT */
+        IP_PACKET_TOO_BIG,        /* ICMP_UNREACH_NEEDFRAG */
+        IP_BAD_ROUTE,             /* ICMP_UNREACH_SRCFAIL */
+        IP_DEST_NET_UNREACHABLE,  /* ICMP_UNREACH_NET_UNKNOWN */
+        IP_DEST_HOST_UNREACHABLE, /* ICMP_UNREACH_HOST_UNKNOWN */
+        IP_DEST_HOST_UNREACHABLE, /* ICMP_UNREACH_ISOLATED */
+        IP_DEST_NET_UNREACHABLE,  /* ICMP_UNREACH_NET_PROHIB */
+        IP_DEST_HOST_UNREACHABLE, /* ICMP_UNREACH_HOST_PROHIB */
+        IP_DEST_NET_UNREACHABLE,  /* ICMP_UNREACH_TOSNET */
+        IP_DEST_HOST_UNREACHABLE, /* ICMP_UNREACH_TOSHOST */
+        IP_DEST_HOST_UNREACHABLE, /* ICMP_UNREACH_FILTER_PROHIB */
+        IP_DEST_HOST_UNREACHABLE, /* ICMP_UNREACH_HOST_PRECEDENCE */
+        IP_DEST_HOST_UNREACHABLE  /* ICMP_UNREACH_PRECEDENCE_CUTOFF */
+    };
+    const struct ip_hdr *orig_ip_hdr;
+    const struct icmp_hdr *orig_icmp_hdr;
+    int orig_ip_hdr_len;
+    IP_STATUS status;
+
     switch (icmp->type)
     {
     case ICMP4_ECHO_REPLY:
@@ -306,11 +330,48 @@ static int ipv4_parse_icmp_hdr_( struct icmp_data *data, struct icmp_hdr *icmp,
         reply->status = IP_SUCCESS;
         return icmp_size - sizeof(*icmp);
 
-    /* FIXME: handle other icmp messages */
+    case ICMP4_DST_UNREACH:
+        if (icmp->code < ARRAY_SIZE(unreach_codes))
+            status = unreach_codes[icmp->code];
+        else
+            status = IP_DEST_HOST_UNREACHABLE;
+        break;
+
+    case ICMP4_TIME_EXCEEDED:
+        if (icmp->code == 1) /* ICMP_TIMXCEED_REASS */
+            status = IP_TTL_EXPIRED_REASSEM;
+        else
+            status = IP_TTL_EXPIRED_TRANSIT;
+        break;
+
+    case ICMP4_PARAM_PROB:
+        status = IP_PARAM_PROBLEM;
+        break;
+
+    case ICMP4_SOURCE_QUENCH:
+        status = IP_SOURCE_QUENCH;
+        break;
 
     default:
         return -1;
     }
+
+    /* Check that the appended packet is really ours -
+     * all handled icmp replies have an 8-byte header
+     * followed by the original ip hdr. */
+    if (icmp_size < sizeof(*icmp) + sizeof(*orig_ip_hdr)) return -1;
+    orig_ip_hdr = (struct ip_hdr *)(icmp + 1);
+    if (orig_ip_hdr->v_hl >> 4 != 4 || orig_ip_hdr->protocol != IPPROTO_ICMP) return -1;
+    orig_ip_hdr_len = (orig_ip_hdr->v_hl & 0xf) << 2;
+    if (icmp_size < sizeof(*icmp) + orig_ip_hdr_len + sizeof(*orig_icmp_hdr)) return -1;
+    orig_icmp_hdr = (const struct icmp_hdr *)((const BYTE *)orig_ip_hdr + orig_ip_hdr_len);
+    if (orig_icmp_hdr->type != ICMP4_ECHO_REQUEST ||
+        orig_icmp_hdr->code != 0 ||
+        (!ping_socket && orig_icmp_hdr->un.echo.id != data->id) ||
+        orig_icmp_hdr->un.echo.sequence != data->seq) return -1;
+
+    reply->status = status;
+    return 0;
 }
 
 static int ipv4_parse_icmp_hdr( struct icmp_data *data, struct icmp_hdr *icmp, int icmp_size,




More information about the wine-cvs mailing list