aboutsummaryrefslogtreecommitdiffstats
path: root/wlantest/rx_ip.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2010-11-20 20:34:42 (GMT)
committerJouni Malinen <j@w1.fi>2010-11-20 20:34:42 (GMT)
commitee3b84beb3829339107826add05dd3bc894f54f5 (patch)
tree9074281011ae3adf674675d10e232b6ac192672e /wlantest/rx_ip.c
parentaebe76594bea12ba7ae139e05853c7e8a678759e (diff)
downloadhostap-ee3b84beb3829339107826add05dd3bc894f54f5.zip
hostap-ee3b84beb3829339107826add05dd3bc894f54f5.tar.gz
hostap-ee3b84beb3829339107826add05dd3bc894f54f5.tar.bz2
wlantest: Parse ICMP echo packet and record STA ping success
Diffstat (limited to 'wlantest/rx_ip.c')
-rw-r--r--wlantest/rx_ip.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/wlantest/rx_ip.c b/wlantest/rx_ip.c
new file mode 100644
index 0000000..29874e6
--- /dev/null
+++ b/wlantest/rx_ip.c
@@ -0,0 +1,148 @@
+/*
+ * Received Data frame processing for IPv4 packets
+ * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "utils/includes.h"
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#include "utils/common.h"
+#include "wlantest.h"
+
+
+static void rx_data_icmp(struct wlantest *wt, const u8 *bssid,
+ const u8 *sta_addr, u32 dst, u32 src,
+ const u8 *data, size_t len)
+{
+ struct in_addr addr;
+ char buf[20];
+ const struct icmphdr *hdr;
+ u16 id, seq;
+ struct wlantest_bss *bss;
+ struct wlantest_sta *sta;
+
+ hdr = (const struct icmphdr *) data;
+ if (len < 4)
+ return;
+
+ /* TODO: check hdr->checksum */
+
+ if (hdr->type != ICMP_ECHOREPLY && hdr->type != ICMP_ECHO)
+ return;
+ if (len < 8)
+ return;
+
+ id = ntohs(hdr->un.echo.id);
+ seq = ntohs(hdr->un.echo.sequence);
+
+ addr.s_addr = dst;
+ snprintf(buf, sizeof(buf), "%s", inet_ntoa(addr));
+ addr.s_addr = src;
+ wpa_printf(MSG_DEBUG, "ICMP echo %s %s -> %s id=%04x seq=%u len=%u",
+ hdr->type == ICMP_ECHO ? "request" : "response",
+ inet_ntoa(addr), buf, id, seq, (unsigned) len - 8);
+
+ bss = bss_find(wt, bssid);
+ if (bss == NULL) {
+ wpa_printf(MSG_INFO, "No BSS " MACSTR " known for ICMP packet",
+ MAC2STR(bssid));
+ return;
+ }
+
+ if (sta_addr == NULL)
+ return; /* FromDS broadcast ping */
+
+ sta = sta_find(bss, sta_addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_INFO, "No STA " MACSTR " known for ICMP packet",
+ MAC2STR(sta_addr));
+ return;
+ }
+
+ if (hdr->type == ICMP_ECHO) {
+ sta->icmp_echo_req_src = src;
+ sta->icmp_echo_req_dst = dst;
+ sta->icmp_echo_req_id = id;
+ sta->icmp_echo_req_seq = seq;
+ return;
+ }
+
+ if (sta->icmp_echo_req_src == dst &&
+ sta->icmp_echo_req_dst == src &&
+ sta->icmp_echo_req_id == id &&
+ sta->icmp_echo_req_seq == seq) {
+ sta->counters[WLANTEST_STA_COUNTER_PING_OK]++;
+ wpa_printf(MSG_DEBUG, "ICMP echo (ping) match for STA " MACSTR,
+ MAC2STR(sta->addr));
+ }
+}
+
+
+void rx_data_ip(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr,
+ const u8 *dst, const u8 *src, const u8 *data, size_t len)
+{
+ const struct iphdr *ip;
+ const u8 *payload;
+ size_t plen;
+ u16 frag_off, tot_len;
+
+ ip = (const struct iphdr *) data;
+ if (len < sizeof(*ip))
+ return;
+ if (ip->version != 4) {
+ wpa_printf(MSG_DEBUG, "Unexpected IP protocol version %u in "
+ "IPv4 packet (bssid=" MACSTR " str=" MACSTR
+ " dst=" MACSTR ")", ip->version, MAC2STR(bssid),
+ MAC2STR(src), MAC2STR(dst));
+ return;
+ }
+ if (ip->ihl * 4 < sizeof(*ip)) {
+ wpa_printf(MSG_DEBUG, "Unexpected IP header length %u in "
+ "IPv4 packet (bssid=" MACSTR " str=" MACSTR
+ " dst=" MACSTR ")", ip->ihl, MAC2STR(bssid),
+ MAC2STR(src), MAC2STR(dst));
+ return;
+ }
+ if (ip->ihl * 4 > len) {
+ wpa_printf(MSG_DEBUG, "Truncated IP header (ihl=%u len=%u) in "
+ "IPv4 packet (bssid=" MACSTR " str=" MACSTR
+ " dst=" MACSTR ")", ip->ihl, (unsigned) len,
+ MAC2STR(bssid), MAC2STR(src), MAC2STR(dst));
+ return;
+ }
+
+ /* TODO: check header checksum in ip->check */
+
+ frag_off = be_to_host16(ip->frag_off);
+ if (frag_off & 0x1fff) {
+ wpa_printf(MSG_EXCESSIVE, "IP fragment reassembly not yet "
+ "supported");
+ return;
+ }
+
+ tot_len = be_to_host16(ip->tot_len);
+ if (tot_len > len)
+ return;
+ if (tot_len < len)
+ len = tot_len;
+
+ payload = data + 4 * ip->ihl;
+ plen = len - 4 * ip->ihl;
+
+ switch (ip->protocol) {
+ case IPPROTO_ICMP:
+ rx_data_icmp(wt, bssid, sta_addr, ip->daddr, ip->saddr,
+ payload, plen);
+ break;
+ }
+}