remove @EAP_LDFLAGS@, no longer exists
[mech_eap.orig] / libeap / mac80211_hwsim / tools / hwsim_test.c
1 /*
2  * hwsim_test - Data connectivity test for mac80211_hwsim
3  * Copyright (c) 2009, Atheros Communications
4  *
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.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <sys/ioctl.h>
20 #include <sys/socket.h>
21 #include <sys/select.h>
22 #include <netpacket/packet.h>
23 #include <net/ethernet.h>
24 #include <net/if.h>
25 #include <arpa/inet.h>
26
27 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
28 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
29
30 #define HWSIM_ETHERTYPE ETHERTYPE_IP
31 #define HWSIM_PACKETLEN 1500
32
33 static unsigned char addr1[ETH_ALEN], addr2[ETH_ALEN], bcast[ETH_ALEN];
34
35 static void tx(int s, const char *ifname, int ifindex,
36                const unsigned char *src, const unsigned char *dst)
37 {
38         char buf[HWSIM_PACKETLEN], *pos;
39         struct ether_header *eth;
40         int i;
41
42         printf("TX: %s(ifindex=%d) " MACSTR " -> " MACSTR "\n",
43                ifname, ifindex, MAC2STR(src), MAC2STR(dst));
44
45         eth = (struct ether_header *) buf;
46         memcpy(eth->ether_dhost, dst, ETH_ALEN);
47         memcpy(eth->ether_shost, src, ETH_ALEN);
48         eth->ether_type = htons(HWSIM_ETHERTYPE);
49         pos = (char *) (eth + 1);
50         for (i = 0; i < sizeof(buf) - sizeof(*eth); i++)
51                 *pos++ = i;
52
53         if (send(s, buf, sizeof(buf), 0) < 0)
54                 perror("send");
55 }
56
57
58 struct rx_result {
59         int rx_unicast1:1;
60         int rx_broadcast1:1;
61         int rx_unicast2:1;
62         int rx_broadcast2:1;
63 };
64
65
66 static void rx(int s, int iface, const char *ifname, int ifindex,
67                struct rx_result *res)
68 {
69         char buf[HWSIM_PACKETLEN + 1], *pos;
70         struct ether_header *eth;
71         int len, i;
72
73         len = recv(s, buf, sizeof(buf), 0);
74         if (len < 0) {
75                 perror("recv");
76                 return;
77         }
78         eth = (struct ether_header *) buf;
79
80         printf("RX: %s(ifindex=%d) " MACSTR " -> " MACSTR " (len=%d)\n",
81                ifname, ifindex,
82                MAC2STR(eth->ether_shost), MAC2STR(eth->ether_dhost), len);
83
84         if (len != HWSIM_PACKETLEN) {
85                 printf("Ignore frame with unexpected RX length\n");
86                 return;
87         }
88
89         pos = (char *) (eth + 1);
90         for (i = 0; i < sizeof(buf) - 1 - sizeof(*eth); i++) {
91                 if ((unsigned char) *pos != (unsigned char) i) {
92                         printf("Ignore frame with unexpected contents\n");
93                         printf("i=%d received=0x%x expected=0x%x\n",
94                                i, (unsigned char) *pos, (unsigned char) i);
95                         return;
96                 }
97                 pos++;
98         }
99
100         if (iface == 1 &&
101                    memcmp(eth->ether_dhost, addr1, ETH_ALEN) == 0 &&
102                    memcmp(eth->ether_shost, addr2, ETH_ALEN) == 0)
103                 res->rx_unicast1 = 1;
104         else if (iface == 1 &&
105                    memcmp(eth->ether_dhost, bcast, ETH_ALEN) == 0 &&
106                    memcmp(eth->ether_shost, addr2, ETH_ALEN) == 0)
107                 res->rx_broadcast1 = 1;
108         else if (iface == 2 &&
109                    memcmp(eth->ether_dhost, addr2, ETH_ALEN) == 0 &&
110                    memcmp(eth->ether_shost, addr1, ETH_ALEN) == 0)
111                 res->rx_unicast2 = 1;
112         else if (iface == 2 &&
113                    memcmp(eth->ether_dhost, bcast, ETH_ALEN) == 0 &&
114                    memcmp(eth->ether_shost, addr1, ETH_ALEN) == 0)
115                 res->rx_broadcast2 = 1;
116 }
117
118
119 int main(int argc, char *argv[])
120 {
121         int s1 = -1, s2 = -1, ret = -1;
122         struct ifreq ifr;
123         int ifindex1, ifindex2;
124         struct sockaddr_ll ll;
125         fd_set rfds;
126         struct timeval tv;
127         struct rx_result res;
128
129         if (argc != 3) {
130                 fprintf(stderr, "usage: hwsim_test <ifname1> <ifname2>\n");
131                 return -1;
132         }
133
134         memset(bcast, 0xff, ETH_ALEN);
135
136         s1 = socket(PF_PACKET, SOCK_RAW, htons(HWSIM_ETHERTYPE));
137         if (s1 < 0) {
138                 perror("socket");
139                 goto fail;
140         }
141
142         s2 = socket(PF_PACKET, SOCK_RAW, htons(HWSIM_ETHERTYPE));
143         if (s2 < 0) {
144                 perror("socket");
145                 goto fail;
146         }
147
148         memset(&ifr, 0, sizeof(ifr));
149         strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name));
150         if (ioctl(s1, SIOCGIFINDEX, &ifr) < 0) {
151                 perror("ioctl[SIOCGIFINDEX]");
152                 goto fail;
153         }
154         ifindex1 = ifr.ifr_ifindex;
155         if (ioctl(s1, SIOCGIFHWADDR, &ifr) < 0) {
156                 perror("ioctl[SIOCGIFHWADDR]");
157                 goto fail;
158         }
159         memcpy(addr1, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
160
161         memset(&ifr, 0, sizeof(ifr));
162         strncpy(ifr.ifr_name, argv[2], sizeof(ifr.ifr_name));
163         if (ioctl(s2, SIOCGIFINDEX, &ifr) < 0) {
164                 perror("ioctl[SIOCGIFINDEX]");
165                 goto fail;
166         }
167         ifindex2 = ifr.ifr_ifindex;
168         if (ioctl(s2, SIOCGIFHWADDR, &ifr) < 0) {
169                 perror("ioctl[SIOCGIFHWADDR]");
170                 goto fail;
171         }
172         memcpy(addr2, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
173
174         memset(&ll, 0, sizeof(ll));
175         ll.sll_family = PF_PACKET;
176         ll.sll_ifindex = ifindex1;
177         ll.sll_protocol = htons(HWSIM_ETHERTYPE);
178         if (bind(s1, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
179                 perror("bind");
180                 goto fail;
181         }
182
183         memset(&ll, 0, sizeof(ll));
184         ll.sll_family = PF_PACKET;
185         ll.sll_ifindex = ifindex2;
186         ll.sll_protocol = htons(HWSIM_ETHERTYPE);
187         if (bind(s2, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
188                 perror("bind");
189                 goto fail;
190         }
191
192         tx(s1, argv[1], ifindex1, addr1, addr2);
193         tx(s1, argv[1], ifindex1, addr1, bcast);
194         tx(s2, argv[2], ifindex2, addr2, addr1);
195         tx(s2, argv[2], ifindex2, addr2, bcast);
196
197         tv.tv_sec = 1;
198         tv.tv_usec = 0;
199
200         memset(&res, 0, sizeof(res));
201         for (;;) {
202                 int r;
203                 FD_ZERO(&rfds);
204                 FD_SET(s1, &rfds);
205                 FD_SET(s2, &rfds);
206
207                 r = select(s2 + 1, &rfds, NULL, NULL, &tv);
208                 if (r < 0) {
209                         perror("select");
210                         goto fail;
211                 }
212
213                 if (r == 0)
214                         break; /* timeout */
215
216                 if (FD_SET(s1, &rfds))
217                         rx(s1, 1, argv[1], ifindex1, &res);
218                 if (FD_SET(s2, &rfds))
219                         rx(s2, 2, argv[2], ifindex2, &res);
220
221                 if (res.rx_unicast1 && res.rx_broadcast1 &&
222                     res.rx_unicast2 && res.rx_broadcast2) {
223                         ret = 0;
224                         break;
225                 }
226         }
227
228         if (ret) {
229                 printf("Did not receive all expected frames:\n"
230                        "rx_unicast1=%d rx_broadcast1=%d "
231                        "rx_unicast2=%d rx_broadcast2=%d\n",
232                        res.rx_unicast1, res.rx_broadcast1,
233                        res.rx_unicast2, res.rx_broadcast2);
234         } else {
235                 printf("Both unicast and broadcast working in both "
236                        "directions\n");
237         }
238
239 fail:
240         close(s1);
241         close(s2);
242
243         return ret;
244 }