2 * Received Data frame processing for IPv4 packets
3 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
10 #include <netinet/ip.h>
11 #include <netinet/ip_icmp.h>
13 #include "utils/common.h"
17 static void ping_update(struct wlantest_sta
*sta
, int req
, u32 src
, u32 dst
,
21 sta
->icmp_echo_req_src
= src
;
22 sta
->icmp_echo_req_dst
= dst
;
23 sta
->icmp_echo_req_id
= id
;
24 sta
->icmp_echo_req_seq
= seq
;
28 if (sta
->icmp_echo_req_src
== dst
&&
29 sta
->icmp_echo_req_dst
== src
&&
30 sta
->icmp_echo_req_id
== id
&&
31 sta
->icmp_echo_req_seq
== seq
) {
32 sta
->counters
[WLANTEST_STA_COUNTER_PING_OK
]++;
33 if (sta
->counters
[WLANTEST_STA_COUNTER_ASSOCREQ_TX
] == 0 &&
34 sta
->counters
[WLANTEST_STA_COUNTER_REASSOCREQ_TX
] == 0)
36 WLANTEST_STA_COUNTER_PING_OK_FIRST_ASSOC
]++;
37 wpa_printf(MSG_DEBUG
, "ICMP echo (ping) match for STA " MACSTR
,
43 static void rx_data_icmp(struct wlantest
*wt
, const u8
*bssid
,
44 const u8
*sta_addr
, u32 dst
, u32 src
,
45 const u8
*data
, size_t len
, const u8
*peer_addr
)
49 const struct icmphdr
*hdr
;
51 struct wlantest_bss
*bss
;
52 struct wlantest_sta
*sta
;
54 hdr
= (const struct icmphdr
*) data
;
58 /* TODO: check hdr->checksum */
60 if (hdr
->type
!= ICMP_ECHOREPLY
&& hdr
->type
!= ICMP_ECHO
)
65 id
= ntohs(hdr
->un
.echo
.id
);
66 seq
= ntohs(hdr
->un
.echo
.sequence
);
69 snprintf(buf
, sizeof(buf
), "%s", inet_ntoa(addr
));
71 wpa_printf(MSG_DEBUG
, "ICMP echo %s %s -> %s id=%04x seq=%u len=%u%s",
72 hdr
->type
== ICMP_ECHO
? "request" : "response",
73 inet_ntoa(addr
), buf
, id
, seq
, (unsigned) len
- 8,
74 peer_addr
? " [DL]" : "");
76 bss
= bss_find(wt
, bssid
);
78 wpa_printf(MSG_INFO
, "No BSS " MACSTR
" known for ICMP packet",
84 return; /* FromDS broadcast ping */
86 sta
= sta_find(bss
, sta_addr
);
88 wpa_printf(MSG_INFO
, "No STA " MACSTR
" known for ICMP packet",
93 ping_update(sta
, hdr
->type
== ICMP_ECHO
, src
, dst
, id
, seq
);
94 if (peer_addr
&& (sta
= sta_find(bss
, peer_addr
)))
95 ping_update(sta
, hdr
->type
== ICMP_ECHO
, src
, dst
, id
, seq
);
99 void rx_data_ip(struct wlantest
*wt
, const u8
*bssid
, const u8
*sta_addr
,
100 const u8
*dst
, const u8
*src
, const u8
*data
, size_t len
,
103 const struct iphdr
*ip
;
106 u16 frag_off
, tot_len
;
108 ip
= (const struct iphdr
*) data
;
109 if (len
< sizeof(*ip
))
111 if (ip
->version
!= 4) {
112 wpa_printf(MSG_DEBUG
, "Unexpected IP protocol version %u in "
113 "IPv4 packet (bssid=" MACSTR
" str=" MACSTR
114 " dst=" MACSTR
")", ip
->version
, MAC2STR(bssid
),
115 MAC2STR(src
), MAC2STR(dst
));
118 if (ip
->ihl
* 4 < sizeof(*ip
)) {
119 wpa_printf(MSG_DEBUG
, "Unexpected IP header length %u in "
120 "IPv4 packet (bssid=" MACSTR
" str=" MACSTR
121 " dst=" MACSTR
")", ip
->ihl
, MAC2STR(bssid
),
122 MAC2STR(src
), MAC2STR(dst
));
125 if (ip
->ihl
* 4 > len
) {
126 wpa_printf(MSG_DEBUG
, "Truncated IP header (ihl=%u len=%u) in "
127 "IPv4 packet (bssid=" MACSTR
" str=" MACSTR
128 " dst=" MACSTR
")", ip
->ihl
, (unsigned) len
,
129 MAC2STR(bssid
), MAC2STR(src
), MAC2STR(dst
));
133 /* TODO: check header checksum in ip->check */
135 frag_off
= be_to_host16(ip
->frag_off
);
136 if (frag_off
& 0x1fff) {
137 wpa_printf(MSG_EXCESSIVE
, "IP fragment reassembly not yet "
142 tot_len
= be_to_host16(ip
->tot_len
);
148 payload
= data
+ 4 * ip
->ihl
;
149 plen
= len
- 4 * ip
->ihl
;
151 switch (ip
->protocol
) {
153 rx_data_icmp(wt
, bssid
, sta_addr
, ip
->daddr
, ip
->saddr
,
154 payload
, plen
, peer_addr
);