nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /*
2 * Copyright (c) 2007, 2008, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3 *
4 * OS dependent API for OpenBSD.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include <sys/types.h>
21 #include <sys/endian.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/param.h>
25 #include <sys/sysctl.h>
26 #include <net/bpf.h>
27 #include <sys/socket.h>
28 #include <net/if.h>
29 #include <net/if_media.h>
30 #include <sys/ioctl.h>
31 #include <net/if_dl.h>
32 #include <sys/queue.h>
33 #include <net/if_var.h>
34 #include <net80211/ieee80211.h>
35 #include <net80211/ieee80211_crypto.h>
36 #include <frame.h>
37 #include <sys/timeout.h>
38 #define _KERNEL
39 #include <machine/intr.h>
40 #undef _KERNEL
41 #include <net80211/ieee80211_node.h>
42 #include <net80211/ieee80211_ioctl.h>
43 #include <net80211/ieee80211_radiotap.h>
44 #include <net80211/ieee80211_proto.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <string.h>
49 #include <sys/uio.h>
50 #include <assert.h>
51 #include <ifaddrs.h>
52  
53 #include "osdep.h"
54  
55 #ifndef IEEE80211_RADIOTAP_F_FCS
56 #define IEEE80211_RADIOTAP_F_FCS 0x10 /* Frame includes FCS */
57 #endif
58  
59 #ifndef IEEE80211_IOC_CHANNEL
60 #define IEEE80211_IOC_CHANNEL 0
61 #endif
62  
63 #ifndef le32toh
64 #define le32toh(x) htole32(x)
65 #endif
66  
67 struct priv_obsd {
68 /* iface */
69 int po_fd;
70  
71 /* rx */
72 int po_nocrc;
73  
74 /* tx */
75 unsigned char po_buf[4096];
76 unsigned char *po_next;
77 int po_totlen;
78  
79 /* setchan */
80 int po_s;
81 struct ifreq po_ifr;
82 struct ieee80211chanreq po_ireq;
83 int po_chan;
84 };
85  
86 static void get_radiotap_info(struct priv_obsd *po,
87 struct ieee80211_radiotap_header *rth, int *plen,
88 struct rx_info *ri)
89 {
90 uint32_t present;
91 uint8_t rflags = 0;
92 int i;
93 unsigned char *body = (unsigned char*) (rth+1);
94 int dbm_power = 0, db_power = 0;
95  
96 /* reset control info */
97 if (ri)
98 memset(ri, 0, sizeof(*ri));
99  
100 /* get info */
101 present = le32toh(rth->it_present);
102 for (i = IEEE80211_RADIOTAP_TSFT; i <= IEEE80211_RADIOTAP_EXT; i++) {
103 if (!(present & (1 << i)))
104 continue;
105  
106 switch (i) {
107 case IEEE80211_RADIOTAP_TSFT:
108 body += sizeof(uint64_t);
109 break;
110  
111 case IEEE80211_RADIOTAP_FLAGS:
112 rflags = *((uint8_t*)body);
113 /* fall through */
114 case IEEE80211_RADIOTAP_RATE:
115 body += sizeof(uint8_t);
116 break;
117  
118 case IEEE80211_RADIOTAP_CHANNEL:
119 if (ri) {
120 ri->ri_channel = 1;
121 }
122 body += sizeof(uint16_t)*2;
123 break;
124  
125 case IEEE80211_RADIOTAP_FHSS:
126 body += sizeof(uint16_t);
127 break;
128  
129 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
130 dbm_power = *body++;
131 break;
132  
133 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
134 dbm_power -= *body++;
135 break;
136  
137 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
138 db_power = *body++;
139 break;
140  
141 case IEEE80211_RADIOTAP_DB_ANTNOISE:
142 db_power -= *body++;
143 break;
144  
145 default:
146 i = IEEE80211_RADIOTAP_EXT+1;
147 break;
148 }
149 }
150  
151 /* set power */
152 if (ri) {
153 if (dbm_power)
154 ri->ri_power = dbm_power;
155 else
156 ri->ri_power = db_power;
157 }
158  
159 /* XXX cache; drivers won't change this per-packet */
160 /* check if FCS/CRC is included in packet */
161 if (po->po_nocrc || (rflags & IEEE80211_RADIOTAP_F_FCS)) {
162 *plen -= IEEE80211_CRC_LEN;
163 po->po_nocrc = 1;
164 }
165 }
166  
167 static unsigned char *get_80211(struct priv_obsd *po, int *plen,
168 struct rx_info *ri)
169 {
170 struct bpf_hdr *bpfh;
171 struct ieee80211_radiotap_header *rth;
172 void *ptr;
173 unsigned char **data;
174 int *totlen;
175  
176 data = &po->po_next;
177 totlen = &po->po_totlen;
178 assert(*totlen);
179  
180 /* bpf hdr */
181 bpfh = (struct bpf_hdr*) (*data);
182 assert(bpfh->bh_caplen == bpfh->bh_datalen); /* XXX */
183 *totlen -= bpfh->bh_hdrlen;
184  
185 /* check if more packets */
186 if ((int)bpfh->bh_caplen < *totlen) {
187 int tot = bpfh->bh_hdrlen + bpfh->bh_caplen;
188 int offset = BPF_WORDALIGN(tot);
189  
190 *data = (unsigned char*)bpfh + offset;
191 *totlen -= offset - tot; /* take into account align bytes */
192 } else if ((int)bpfh->bh_caplen > *totlen)
193 abort();
194  
195 *plen = bpfh->bh_caplen;
196 *totlen -= bpfh->bh_caplen;
197 assert(*totlen >= 0);
198  
199 /* radiotap */
200 rth = (struct ieee80211_radiotap_header*)
201 ((char*)bpfh + bpfh->bh_hdrlen);
202 get_radiotap_info(po, rth, plen, ri);
203 *plen -= rth->it_len;
204 assert(*plen > 0);
205  
206 /* data */
207 ptr = (char*)rth + rth->it_len;
208  
209 return ptr;
210 }
211  
212 static int obsd_get_channel(struct wif *wi)
213 {
214 struct priv_obsd *po = wi_priv(wi);
215 struct ieee80211chanreq channel;
216  
217 memset(&channel, 0, sizeof(channel));
218 strlcpy(channel.i_name, wi_get_ifname(wi), sizeof(channel.i_name));
219  
220 if(ioctl(po->po_s, SIOCG80211CHANNEL, (caddr_t)&channel) < 0) return -1;
221  
222 return channel.i_channel;
223 }
224  
225 static int obsd_set_channel(struct wif *wi, int chan)
226 {
227 struct priv_obsd *po = wi_priv(wi);
228 struct ieee80211chanreq channel;
229  
230 memset(&channel, 0, sizeof(channel));
231 strlcpy(channel.i_name, wi_get_ifname(wi), sizeof(channel.i_name));
232 channel.i_channel = chan;
233 if(ioctl(po->po_s, SIOCS80211CHANNEL, (caddr_t)&channel) < 0) return -1;
234 po->po_chan = chan;
235  
236 return 0;
237 }
238  
239 static int obsd_read(struct wif *wi, unsigned char *h80211, int len,
240 struct rx_info *ri)
241 {
242 struct priv_obsd *po = wi_priv(wi);
243 unsigned char *wh;
244 int plen;
245  
246 assert(len > 0);
247  
248 /* need to read more */
249 while (po->po_totlen == 0) {
250 po->po_totlen = read(po->po_fd, po->po_buf, sizeof(po->po_buf));
251 if (po->po_totlen == -1) {
252 po->po_totlen = 0;
253 return -1;
254 }
255 po->po_next = po->po_buf;
256 }
257  
258 /* read 802.11 packet */
259 wh = get_80211(po, &plen, ri);
260 if (plen > len)
261 plen = len;
262 assert(plen > 0);
263 memcpy(h80211, wh, plen);
264  
265 if(ri && !ri->ri_channel)
266 ri->ri_channel = wi_get_channel(wi);
267  
268 return plen;
269 }
270  
271 static int obsd_write(struct wif *wi, unsigned char *h80211, int len,
272 struct tx_info *ti)
273 {
274 struct priv_obsd *po = wi_priv(wi);
275 int rc;
276  
277 /* XXX make use of ti */
278 if (ti) {}
279  
280 rc = write(po->po_fd, h80211, len);
281 if (rc == -1)
282 return rc;
283  
284 return 0;
285 }
286  
287 static void do_free(struct wif *wi)
288 {
289 assert(wi->wi_priv);
290 free(wi->wi_priv);
291 wi->wi_priv = 0;
292 free(wi);
293 }
294  
295 static void obsd_close(struct wif *wi)
296 {
297 struct priv_obsd *po = wi_priv(wi);
298  
299 close(po->po_fd);
300 close(po->po_s);
301 do_free(wi);
302 }
303  
304 static int do_obsd_open(struct wif *wi, char *iface)
305 {
306 int i;
307 char buf[64];
308 int fd = -1;
309 struct ifreq ifr;
310 unsigned int dlt = DLT_IEEE802_11_RADIO;
311 int s;
312 unsigned int flags;
313 struct ifmediareq ifmr;
314 int *mwords;
315 struct priv_obsd *po = wi_priv(wi);
316 unsigned int size=sizeof(po->po_buf);
317  
318 /* basic sanity check */
319 if (strlen(iface) >= sizeof(ifr.ifr_name))
320 return -1;
321  
322 /* open wifi */
323 s = socket(PF_INET, SOCK_DGRAM, 0);
324 if (s == -1)
325 return -1;
326 po->po_s = s;
327  
328 /* set iface up and promisc */
329 memset(&ifr, 0, sizeof(ifr));
330 strncpy(ifr.ifr_name, iface, IFNAMSIZ);
331 if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1)
332 goto close_sock;
333  
334 flags = ifr.ifr_flags;
335 flags |= IFF_UP | IFF_PROMISC;
336 memset(&ifr, 0, sizeof(ifr));
337 strncpy(ifr.ifr_name, iface, IFNAMSIZ);
338 ifr.ifr_flags = flags & 0xffff;
339 if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1)
340 goto close_sock;
341  
342 /* monitor mode */
343 memset(&ifmr, 0, sizeof(ifmr));
344 strncpy(ifmr.ifm_name, iface, IFNAMSIZ);
345 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1)
346 goto close_sock;
347  
348 assert(ifmr.ifm_count != 0);
349  
350 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int));
351 if (!mwords)
352 goto close_sock;
353 ifmr.ifm_ulist = mwords;
354 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) {
355 free(mwords);
356 goto close_sock;
357 }
358 free(mwords);
359  
360 memset(&ifr, 0, sizeof(ifr));
361 strncpy(ifr.ifr_name, iface, IFNAMSIZ);
362 ifr.ifr_media = ifmr.ifm_current | IFM_IEEE80211_MONITOR;
363 if (ioctl(s, SIOCSIFMEDIA, &ifr) == -1)
364 goto close_sock;
365  
366 /* setup ifreq for chan that may be used in future */
367 strncpy(po->po_ireq.i_name, iface, IFNAMSIZ);
368  
369 /* same for ifreq [mac addr] */
370 strncpy(po->po_ifr.ifr_name, iface, IFNAMSIZ);
371  
372 /* open bpf */
373 for(i = 0; i < 256; i++) {
374 snprintf(buf, sizeof(buf), "/dev/bpf%d", i);
375  
376 fd = open(buf, O_RDWR);
377 if(fd < 0) {
378 if(errno != EBUSY)
379 return -1;
380 continue;
381 }
382 else
383 break;
384 }
385  
386 if(fd < 0)
387 goto close_sock;
388  
389 if (ioctl(fd, BIOCSBLEN, &size) < 0)
390 goto close_bpf;
391  
392 strncpy(ifr.ifr_name, iface, IFNAMSIZ);
393  
394 if (ioctl(fd, BIOCSETIF, &ifr) < 0)
395 goto close_bpf;
396  
397 if (ioctl(fd, BIOCSDLT, &dlt) < 0)
398 goto close_bpf;
399  
400 if(ioctl(fd, BIOCPROMISC, NULL) < 0)
401 goto close_bpf;
402  
403 dlt = 1;
404 if (ioctl(fd, BIOCIMMEDIATE, &dlt) == -1)
405 goto close_bpf;
406  
407 return fd;
408  
409 close_sock:
410 close(s);
411 return -1;
412 close_bpf:
413 close(fd);
414 goto close_sock;
415 }
416  
417 static int obsd_fd(struct wif *wi)
418 {
419 struct priv_obsd *po = wi_priv(wi);
420  
421 return po->po_fd;
422 }
423  
424 static int obsd_get_mac(struct wif *wi, unsigned char *mac)
425 {
426 struct ifaddrs *ifa, *p;
427 char *name = wi_get_ifname(wi);
428 int rc = -1;
429 struct sockaddr_dl* sdp;
430  
431 if (getifaddrs(&ifa) == -1)
432 return -1;
433  
434 p = ifa;
435 while (p) {
436 if (p->ifa_addr->sa_family == AF_LINK &&
437 strcmp(name, p->ifa_name) == 0) {
438  
439 sdp = (struct sockaddr_dl*) p->ifa_addr;
440 memcpy(mac, sdp->sdl_data + sdp->sdl_nlen, 6);
441 rc = 0;
442 break;
443 }
444  
445 p = p->ifa_next;
446 }
447 freeifaddrs(ifa);
448  
449 return rc;
450 }
451  
452 static int obsd_get_monitor(struct wif *wi)
453 {
454 if (wi) {} /* XXX unused */
455  
456 /* XXX */
457 return 0;
458 }
459  
460 static int obsd_get_rate(struct wif *wi)
461 {
462 if (wi) {} /* XXX unused */
463  
464 /* XXX */
465 return 1000000;
466 }
467  
468 static int obsd_set_rate(struct wif *wi, int rate)
469 {
470 if (wi || rate) {} /* XXX unused */
471  
472 /* XXX */
473 return 0;
474 }
475  
476 static int obsd_set_mac(struct wif *wi, unsigned char *mac)
477 {
478 struct priv_obsd *po = wi_priv(wi);
479 struct ifreq *ifr = &po->po_ifr;
480  
481 ifr->ifr_addr.sa_family = AF_LINK;
482 ifr->ifr_addr.sa_len = 6;
483 memcpy(ifr->ifr_addr.sa_data, mac, 6);
484  
485 return ioctl(po->po_s, SIOCSIFLLADDR, ifr);
486 }
487  
488 static struct wif *obsd_open(char *iface)
489 {
490 struct wif *wi;
491 struct priv_obsd *po;
492 int fd;
493  
494 /* setup wi struct */
495 wi = wi_alloc(sizeof(*po));
496 if (!wi)
497 return NULL;
498 wi->wi_read = obsd_read;
499 wi->wi_write = obsd_write;
500 wi->wi_set_channel = obsd_set_channel;
501 wi->wi_get_channel = obsd_get_channel;
502 wi->wi_close = obsd_close;
503 wi->wi_fd = obsd_fd;
504 wi->wi_get_mac = obsd_get_mac;
505 wi->wi_set_mac = obsd_set_mac;
506 wi->wi_get_rate = obsd_get_rate;
507 wi->wi_set_rate = obsd_set_rate;
508 wi->wi_get_monitor = obsd_get_monitor;
509  
510 /* setup iface */
511 fd = do_obsd_open(wi, iface);
512 if (fd == -1) {
513 do_free(wi);
514 return NULL;
515 }
516  
517 /* setup private state */
518 po = wi_priv(wi);
519 po->po_fd = fd;
520  
521 return wi;
522 }
523  
524 struct wif *wi_open_osdep(char *iface)
525 {
526 return obsd_open(iface);
527 }
528  
529 int get_battery_state(void)
530 {
531 #if defined(__FreeBSD__)
532 int value;
533 size_t len;
534  
535 len = 1;
536 value = 0;
537 sysctlbyname("hw.acpi.acline", &value, &len, NULL, 0);
538 if (value == 0)
539 {
540 sysctlbyname("hw.acpi.battery.time", &value, &len, NULL, 0);
541 value = value * 60;
542 }
543 else
544 {
545 value = 0;
546 }
547  
548 return( value );
549 #elif defined(_BSD_SOURCE)
550 struct apm_power_info api;
551 int apmfd;
552 if ((apmfd = open("/dev/apm", O_RDONLY)) < 0)
553 return 0;
554 if (ioctl(apmfd, APM_IOC_GETPOWER, &api) < 0) {
555 close(apmfd);
556 return 0;
557 }
558 close(apmfd);
559 if (api.battery_state == APM_BATT_UNKNOWN ||
560 api.battery_state == APM_BATTERY_ABSENT ||
561 api.battery_state == APM_BATT_CHARGING ||
562 api.ac_state == APM_AC_ON) {
563 return 0;
564 }
565 return ((int)(api.minutes_left))*60;
566 #else
567 return 0;
568 #endif
569 }