00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "includes.h"
00036 #include <pcap.h>
00037
00038 #include "common.h"
00039 #include "eloop.h"
00040 #include "l2_packet.h"
00041
00042
00043 static const u8 pae_group_addr[ETH_ALEN] =
00044 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
00045
00046
00047
00048
00049
00050
00051 static const size_t no_wait_count = 750;
00052
00053 struct l2_packet_data {
00054 pcap_t *pcap;
00055 unsigned int num_fast_poll;
00056 char ifname[100];
00057 u8 own_addr[ETH_ALEN];
00058 void (*rx_callback)(void *ctx, const u8 *src_addr,
00059 const u8 *buf, size_t len);
00060 void *rx_callback_ctx;
00061 int l2_hdr;
00062
00063 int running;
00064 HANDLE rx_avail, rx_done, rx_thread, rx_thread_done, rx_notify;
00065 u8 *rx_buf, *rx_src;
00066 size_t rx_len;
00067 size_t rx_no_wait;
00068 };
00069
00070
00071 int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
00072 {
00073 os_memcpy(addr, l2->own_addr, ETH_ALEN);
00074 return 0;
00075 }
00076
00077
00078 int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
00079 const u8 *buf, size_t len)
00080 {
00081 int ret;
00082 struct l2_ethhdr *eth;
00083
00084 if (l2 == NULL)
00085 return -1;
00086
00087 if (l2->l2_hdr) {
00088 ret = pcap_sendpacket(l2->pcap, buf, len);
00089 } else {
00090 size_t mlen = sizeof(*eth) + len;
00091 eth = os_malloc(mlen);
00092 if (eth == NULL)
00093 return -1;
00094
00095 os_memcpy(eth->h_dest, dst_addr, ETH_ALEN);
00096 os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN);
00097 eth->h_proto = htons(proto);
00098 os_memcpy(eth + 1, buf, len);
00099 ret = pcap_sendpacket(l2->pcap, (u8 *) eth, mlen);
00100 os_free(eth);
00101 }
00102
00103 return ret;
00104 }
00105
00106
00107
00108 static void l2_packet_receive_cb(u_char *user, const struct pcap_pkthdr *hdr,
00109 const u_char *pkt_data)
00110 {
00111 struct l2_packet_data *l2 = (struct l2_packet_data *) user;
00112 struct l2_ethhdr *ethhdr;
00113
00114 if (pkt_data == NULL || hdr->caplen < sizeof(*ethhdr))
00115 return;
00116
00117 ethhdr = (struct l2_ethhdr *) pkt_data;
00118 if (l2->l2_hdr) {
00119 l2->rx_buf = (u8 *) ethhdr;
00120 l2->rx_len = hdr->caplen;
00121 } else {
00122 l2->rx_buf = (u8 *) (ethhdr + 1);
00123 l2->rx_len = hdr->caplen - sizeof(*ethhdr);
00124 }
00125 l2->rx_src = ethhdr->h_source;
00126 SetEvent(l2->rx_avail);
00127 WaitForSingleObject(l2->rx_done, INFINITE);
00128 ResetEvent(l2->rx_done);
00129 l2->rx_no_wait = no_wait_count;
00130 }
00131
00132
00133
00134 static DWORD WINAPI l2_packet_receive_thread(LPVOID arg)
00135 {
00136 struct l2_packet_data *l2 = arg;
00137
00138 while (l2->running) {
00139 pcap_dispatch(l2->pcap, 1, l2_packet_receive_cb,
00140 (u_char *) l2);
00141 if (l2->rx_no_wait > 0)
00142 l2->rx_no_wait--;
00143 if (WaitForSingleObject(l2->rx_notify,
00144 l2->rx_no_wait ? 0 : 50) ==
00145 WAIT_OBJECT_0) {
00146 l2->rx_no_wait = no_wait_count;
00147 ResetEvent(l2->rx_notify);
00148 }
00149 }
00150 SetEvent(l2->rx_thread_done);
00151 ExitThread(0);
00152 return 0;
00153 }
00154
00155
00156
00157 static void l2_packet_rx_event(void *eloop_data, void *user_data)
00158 {
00159 struct l2_packet_data *l2 = eloop_data;
00160 l2->rx_callback(l2->rx_callback_ctx, l2->rx_src, l2->rx_buf,
00161 l2->rx_len);
00162 ResetEvent(l2->rx_avail);
00163 SetEvent(l2->rx_done);
00164 }
00165
00166
00167 static int l2_packet_init_libpcap(struct l2_packet_data *l2,
00168 unsigned short protocol)
00169 {
00170 bpf_u_int32 pcap_maskp, pcap_netp;
00171 char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE];
00172 struct bpf_program pcap_fp;
00173
00174 pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err);
00175 l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 1, pcap_err);
00176 if (l2->pcap == NULL) {
00177 fprintf(stderr, "pcap_open_live: %s\n", pcap_err);
00178 fprintf(stderr, "ifname='%s'\n", l2->ifname);
00179 return -1;
00180 }
00181 os_snprintf(pcap_filter, sizeof(pcap_filter),
00182 "not ether src " MACSTR " and "
00183 "( ether dst " MACSTR " or ether dst " MACSTR " ) and "
00184 "ether proto 0x%x",
00185 MAC2STR(l2->own_addr),
00186 MAC2STR(l2->own_addr), MAC2STR(pae_group_addr),
00187 protocol);
00188 if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) {
00189 fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap));
00190 return -1;
00191 }
00192
00193 if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) {
00194 fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap));
00195 return -1;
00196 }
00197
00198 pcap_freecode(&pcap_fp);
00199
00200 return 0;
00201 }
00202
00203
00204 struct l2_packet_data * l2_packet_init(
00205 const char *ifname, const u8 *own_addr, unsigned short protocol,
00206 void (*rx_callback)(void *ctx, const u8 *src_addr,
00207 const u8 *buf, size_t len),
00208 void *rx_callback_ctx, int l2_hdr)
00209 {
00210 struct l2_packet_data *l2;
00211 DWORD thread_id;
00212
00213 l2 = os_zalloc(sizeof(struct l2_packet_data));
00214 if (l2 == NULL)
00215 return NULL;
00216 if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0)
00217 os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname));
00218 else
00219 os_snprintf(l2->ifname, sizeof(l2->ifname), "\\Device\\NPF_%s",
00220 ifname);
00221 l2->rx_callback = rx_callback;
00222 l2->rx_callback_ctx = rx_callback_ctx;
00223 l2->l2_hdr = l2_hdr;
00224
00225 if (own_addr)
00226 os_memcpy(l2->own_addr, own_addr, ETH_ALEN);
00227
00228 if (l2_packet_init_libpcap(l2, protocol)) {
00229 os_free(l2);
00230 return NULL;
00231 }
00232
00233 l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL);
00234 l2->rx_done = CreateEvent(NULL, TRUE, FALSE, NULL);
00235 l2->rx_notify = CreateEvent(NULL, TRUE, FALSE, NULL);
00236 if (l2->rx_avail == NULL || l2->rx_done == NULL ||
00237 l2->rx_notify == NULL) {
00238 CloseHandle(l2->rx_avail);
00239 CloseHandle(l2->rx_done);
00240 CloseHandle(l2->rx_notify);
00241 pcap_close(l2->pcap);
00242 os_free(l2);
00243 return NULL;
00244 }
00245
00246 eloop_register_event(l2->rx_avail, sizeof(l2->rx_avail),
00247 l2_packet_rx_event, l2, NULL);
00248
00249 l2->running = 1;
00250 l2->rx_thread = CreateThread(NULL, 0, l2_packet_receive_thread, l2, 0,
00251 &thread_id);
00252
00253 return l2;
00254 }
00255
00256
00257 static void l2_packet_deinit_timeout(void *eloop_ctx, void *timeout_ctx)
00258 {
00259 struct l2_packet_data *l2 = eloop_ctx;
00260
00261 if (l2->rx_thread_done &&
00262 WaitForSingleObject(l2->rx_thread_done, 2000) != WAIT_OBJECT_0) {
00263 wpa_printf(MSG_DEBUG, "l2_packet_winpcap: RX thread did not "
00264 "exit - kill it\n");
00265 TerminateThread(l2->rx_thread, 0);
00266 }
00267 CloseHandle(l2->rx_thread_done);
00268 CloseHandle(l2->rx_thread);
00269 if (l2->pcap)
00270 pcap_close(l2->pcap);
00271 eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail));
00272 CloseHandle(l2->rx_avail);
00273 CloseHandle(l2->rx_done);
00274 CloseHandle(l2->rx_notify);
00275 os_free(l2);
00276 }
00277
00278
00279 void l2_packet_deinit(struct l2_packet_data *l2)
00280 {
00281 if (l2 == NULL)
00282 return;
00283
00284 l2->rx_thread_done = CreateEvent(NULL, TRUE, FALSE, NULL);
00285
00286 l2->running = 0;
00287 pcap_breakloop(l2->pcap);
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 eloop_register_timeout(0, 0, l2_packet_deinit_timeout, l2, NULL);
00298 }
00299
00300
00301 int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
00302 {
00303 pcap_if_t *devs, *dev;
00304 struct pcap_addr *addr;
00305 struct sockaddr_in *saddr;
00306 int found = 0;
00307 char err[PCAP_ERRBUF_SIZE + 1];
00308
00309 if (pcap_findalldevs(&devs, err) < 0) {
00310 wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err);
00311 return -1;
00312 }
00313
00314 for (dev = devs; dev && !found; dev = dev->next) {
00315 if (os_strcmp(dev->name, l2->ifname) != 0)
00316 continue;
00317
00318 addr = dev->addresses;
00319 while (addr) {
00320 saddr = (struct sockaddr_in *) addr->addr;
00321 if (saddr && saddr->sin_family == AF_INET) {
00322 os_strlcpy(buf, inet_ntoa(saddr->sin_addr),
00323 len);
00324 found = 1;
00325 break;
00326 }
00327 addr = addr->next;
00328 }
00329 }
00330
00331 pcap_freealldevs(devs);
00332
00333 return found ? 0 : -1;
00334 }
00335
00336
00337 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
00338 {
00339 if (l2)
00340 SetEvent(l2->rx_notify);
00341 }