2 * Received Data frame processing for IPv4 packets
3 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
15 #include "utils/includes.h"
16 #include <netinet/ip.h>
17 #include <netinet/ip_icmp.h>
19 #include "utils/common.h"
23 static void rx_data_icmp(struct wlantest *wt, const u8 *bssid,
24 const u8 *sta_addr, u32 dst, u32 src,
25 const u8 *data, size_t len)
29 const struct icmphdr *hdr;
31 struct wlantest_bss *bss;
32 struct wlantest_sta *sta;
34 hdr = (const struct icmphdr *) data;
38 /* TODO: check hdr->checksum */
40 if (hdr->type != ICMP_ECHOREPLY && hdr->type != ICMP_ECHO)
45 id = ntohs(hdr->un.echo.id);
46 seq = ntohs(hdr->un.echo.sequence);
49 snprintf(buf, sizeof(buf), "%s", inet_ntoa(addr));
51 wpa_printf(MSG_DEBUG, "ICMP echo %s %s -> %s id=%04x seq=%u len=%u",
52 hdr->type == ICMP_ECHO ? "request" : "response",
53 inet_ntoa(addr), buf, id, seq, (unsigned) len - 8);
55 bss = bss_find(wt, bssid);
57 wpa_printf(MSG_INFO, "No BSS " MACSTR " known for ICMP packet",
63 return; /* FromDS broadcast ping */
65 sta = sta_find(bss, sta_addr);
67 wpa_printf(MSG_INFO, "No STA " MACSTR " known for ICMP packet",
72 if (hdr->type == ICMP_ECHO) {
73 sta->icmp_echo_req_src = src;
74 sta->icmp_echo_req_dst = dst;
75 sta->icmp_echo_req_id = id;
76 sta->icmp_echo_req_seq = seq;
80 if (sta->icmp_echo_req_src == dst &&
81 sta->icmp_echo_req_dst == src &&
82 sta->icmp_echo_req_id == id &&
83 sta->icmp_echo_req_seq == seq) {
84 sta->counters[WLANTEST_STA_COUNTER_PING_OK]++;
85 if (sta->counters[WLANTEST_STA_COUNTER_ASSOCREQ_TX] == 0 &&
86 sta->counters[WLANTEST_STA_COUNTER_REASSOCREQ_TX] == 0)
88 WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC]++;
89 wpa_printf(MSG_DEBUG, "ICMP echo (ping) match for STA " MACSTR,
95 void rx_data_ip(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr,
96 const u8 *dst, const u8 *src, const u8 *data, size_t len)
98 const struct iphdr *ip;
101 u16 frag_off, tot_len;
103 ip = (const struct iphdr *) data;
104 if (len < sizeof(*ip))
106 if (ip->version != 4) {
107 wpa_printf(MSG_DEBUG, "Unexpected IP protocol version %u in "
108 "IPv4 packet (bssid=" MACSTR " str=" MACSTR
109 " dst=" MACSTR ")", ip->version, MAC2STR(bssid),
110 MAC2STR(src), MAC2STR(dst));
113 if (ip->ihl * 4 < sizeof(*ip)) {
114 wpa_printf(MSG_DEBUG, "Unexpected IP header length %u in "
115 "IPv4 packet (bssid=" MACSTR " str=" MACSTR
116 " dst=" MACSTR ")", ip->ihl, MAC2STR(bssid),
117 MAC2STR(src), MAC2STR(dst));
120 if (ip->ihl * 4 > len) {
121 wpa_printf(MSG_DEBUG, "Truncated IP header (ihl=%u len=%u) in "
122 "IPv4 packet (bssid=" MACSTR " str=" MACSTR
123 " dst=" MACSTR ")", ip->ihl, (unsigned) len,
124 MAC2STR(bssid), MAC2STR(src), MAC2STR(dst));
128 /* TODO: check header checksum in ip->check */
130 frag_off = be_to_host16(ip->frag_off);
131 if (frag_off & 0x1fff) {
132 wpa_printf(MSG_EXCESSIVE, "IP fragment reassembly not yet "
137 tot_len = be_to_host16(ip->tot_len);
143 payload = data + 4 * ip->ihl;
144 plen = len - 4 * ip->ihl;
146 switch (ip->protocol) {
148 rx_data_icmp(wt, bssid, sta_addr, ip->daddr, ip->saddr,