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 FreeBSD.
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  
21 #include <sys/endian.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/types.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 #ifdef __DragonFly__
33 #include <netproto/802_11/ieee80211_ioctl.h>
34 #include <netproto/802_11/ieee80211_radiotap.h>
35 #include <netproto/802_11/ieee80211_dragonfly.h>
36 #else
37 #include <net80211/ieee80211_ioctl.h>
38 #include <net80211/ieee80211_radiotap.h>
39 #include <net80211/ieee80211_freebsd.h>
40 #endif
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <string.h>
45 #include <sys/uio.h>
46 #include <assert.h>
47 #include <ifaddrs.h>
48  
49 #include "osdep.h"
50  
51 struct priv_fbsd {
52 /* iface */
53 int pf_fd;
54  
55 /* rx */
56 int pf_nocrc;
57  
58 /* tx */
59 unsigned char pf_buf[4096];
60 unsigned char *pf_next;
61 int pf_totlen;
62 struct ieee80211_bpf_params pf_txparams;
63  
64 /* setchan */
65 int pf_s;
66 struct ifreq pf_ifr;
67 struct ieee80211req pf_ireq;
68 int pf_chan;
69 };
70  
71 /* from ifconfig */
72 static __inline int
73 mapgsm(u_int freq, u_int flags)
74 {
75 freq *= 10;
76 if (flags & IEEE80211_CHAN_QUARTER)
77 freq += 5;
78 else if (flags & IEEE80211_CHAN_HALF)
79 freq += 10;
80 else
81 freq += 20;
82 /* NB: there is no 907/20 wide but leave room */
83 return (freq - 906*10) / 5;
84 }
85  
86 static __inline int
87 mappsb(u_int freq)
88 {
89 return 37 + ((freq * 10) + ((freq % 5) == 2 ? 5 : 0) - 49400) / 5;
90 }
91  
92 /*
93 * Convert MHz frequency to IEEE channel number.
94 */
95 static u_int
96 ieee80211_mhz2ieee(u_int freq, u_int flags)
97 {
98 if ((flags & IEEE80211_CHAN_GSM) || (907 <= freq && freq <= 922))
99 return mapgsm(freq, flags);
100 if (freq == 2484)
101 return 14;
102 if (freq < 2484)
103 return (freq - 2407) / 5;
104 if (freq < 5000) {
105 if (flags & (IEEE80211_CHAN_HALF|IEEE80211_CHAN_QUARTER))
106 return mappsb(freq);
107 else if (freq > 4900)
108 return (freq - 4000) / 5;
109 else
110 return 15 + ((freq - 2512) / 20);
111 }
112 return (freq - 5000) / 5;
113 }
114 /* end of ifconfig */
115  
116 static void get_radiotap_info(struct priv_fbsd *pf,
117 struct ieee80211_radiotap_header *rth, int *plen,
118 struct rx_info *ri)
119 {
120 uint32_t present;
121 uint8_t rflags = 0;
122 int i;
123 unsigned char *body = (unsigned char*) (rth+1);
124 int dbm_power = 0, db_power = 0;
125  
126 /* reset control info */
127 if (ri)
128 memset(ri, 0, sizeof(*ri));
129  
130 /* get info */
131 present = le32toh(rth->it_present);
132 for (i = IEEE80211_RADIOTAP_TSFT; i <= IEEE80211_RADIOTAP_EXT; i++) {
133 if (!(present & (1 << i)))
134 continue;
135  
136 switch (i) {
137 case IEEE80211_RADIOTAP_TSFT:
138 body += sizeof(uint64_t);
139 break;
140  
141 case IEEE80211_RADIOTAP_FLAGS:
142 rflags = *((uint8_t*)body);
143 /* fall through */
144 case IEEE80211_RADIOTAP_RATE:
145 body += sizeof(uint8_t);
146 break;
147  
148 case IEEE80211_RADIOTAP_CHANNEL:
149 if (ri) {
150 uint16_t *p = (uint16_t*) body;
151 int c = ieee80211_mhz2ieee(*p, *(p+1));
152  
153 ri->ri_channel = c;
154 }
155 body += sizeof(uint16_t)*2;
156 break;
157  
158 case IEEE80211_RADIOTAP_FHSS:
159 body += sizeof(uint16_t);
160 break;
161  
162 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
163 dbm_power = *body++;
164 break;
165  
166 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
167 dbm_power -= *body++;
168 break;
169  
170 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
171 db_power = *body++;
172 break;
173  
174 case IEEE80211_RADIOTAP_DB_ANTNOISE:
175 db_power -= *body++;
176 break;
177  
178 default:
179 i = IEEE80211_RADIOTAP_EXT+1;
180 break;
181 }
182 }
183  
184 /* set power */
185 if (ri) {
186 if (dbm_power)
187 ri->ri_power = dbm_power;
188 else
189 ri->ri_power = db_power;
190 }
191  
192 /* XXX cache; drivers won't change this per-packet */
193 /* check if FCS/CRC is included in packet */
194 if (pf->pf_nocrc || (rflags & IEEE80211_RADIOTAP_F_FCS)) {
195 *plen -= IEEE80211_CRC_LEN;
196 pf->pf_nocrc = 1;
197 }
198 }
199  
200 static unsigned char *get_80211(struct priv_fbsd *pf, int *plen,
201 struct rx_info *ri)
202 {
203 struct bpf_hdr *bpfh;
204 struct ieee80211_radiotap_header *rth;
205 void *ptr;
206 unsigned char **data;
207 int *totlen;
208  
209 data = &pf->pf_next;
210 totlen = &pf->pf_totlen;
211 assert(*totlen);
212  
213 /* bpf hdr */
214 bpfh = (struct bpf_hdr*) (*data);
215 assert(bpfh->bh_caplen == bpfh->bh_datalen); /* XXX */
216 *totlen -= bpfh->bh_hdrlen;
217  
218 /* check if more packets */
219 if ((int)bpfh->bh_caplen < *totlen) {
220 int tot = bpfh->bh_hdrlen + bpfh->bh_caplen;
221 int offset = BPF_WORDALIGN(tot);
222  
223 *data = (unsigned char*)bpfh + offset;
224 *totlen -= offset - tot; /* take into account align bytes */
225 } else if ((int)bpfh->bh_caplen > *totlen)
226 abort();
227  
228 *plen = bpfh->bh_caplen;
229 *totlen -= bpfh->bh_caplen;
230 assert(*totlen >= 0);
231  
232 /* radiotap */
233 rth = (struct ieee80211_radiotap_header*)
234 ((char*)bpfh + bpfh->bh_hdrlen);
235 get_radiotap_info(pf, rth, plen, ri);
236 *plen -= rth->it_len;
237 assert(*plen > 0);
238  
239 /* data */
240 ptr = (char*)rth + rth->it_len;
241  
242 return ptr;
243 }
244  
245 static int fbsd_get_channel(struct wif *wi)
246 {
247 struct priv_fbsd *pf = wi_priv(wi);
248  
249 if(ioctl(pf->pf_s, SIOCG80211, &pf->pf_ireq) != 0) return -1;
250  
251 return pf->pf_ireq.i_val;
252 }
253  
254 static int fbsd_read(struct wif *wi, unsigned char *h80211, int len,
255 struct rx_info *ri)
256 {
257 struct priv_fbsd *pf = wi_priv(wi);
258 unsigned char *wh;
259 int plen;
260  
261 assert(len > 0);
262  
263 /* need to read more */
264 if (pf->pf_totlen == 0) {
265 pf->pf_totlen = read(pf->pf_fd, pf->pf_buf, sizeof(pf->pf_buf));
266 if (pf->pf_totlen == -1) {
267 pf->pf_totlen = 0;
268 return -1;
269 }
270 pf->pf_next = pf->pf_buf;
271 }
272  
273 /* read 802.11 packet */
274 wh = get_80211(pf, &plen, ri);
275 if (plen > len)
276 plen = len;
277 assert(plen > 0);
278 memcpy(h80211, wh, plen);
279  
280 if(ri && !ri->ri_channel)
281 ri->ri_channel = wi_get_channel(wi);
282  
283 return plen;
284 }
285  
286 static int fbsd_write(struct wif *wi, unsigned char *h80211, int len,
287 struct tx_info *ti)
288 {
289 struct iovec iov[2];
290 struct priv_fbsd *pf = wi_priv(wi);
291 int rc;
292  
293 /* XXX make use of ti */
294 if (ti) {}
295  
296 iov[0].iov_base = &pf->pf_txparams;
297 iov[0].iov_len = pf->pf_txparams.ibp_len;
298  
299 iov[1].iov_base = h80211;
300 iov[1].iov_len = len;
301  
302 rc = writev(pf->pf_fd, iov, 2);
303 if (rc == -1)
304 return rc;
305 if (rc < (int) iov[0].iov_len)
306 return 0;
307  
308 return rc - iov[0].iov_len;
309 }
310  
311 static int fbsd_set_channel(struct wif *wi, int chan)
312 {
313 struct priv_fbsd *pf = wi_priv(wi);
314  
315 pf->pf_ireq.i_val = chan;
316 if( ioctl(pf->pf_s, SIOCS80211, &pf->pf_ireq) != 0 )
317 return -1;
318  
319 pf->pf_chan = chan;
320 return 0;
321 }
322  
323 static void do_free(struct wif *wi)
324 {
325 assert(wi->wi_priv);
326 free(wi->wi_priv);
327 wi->wi_priv = 0;
328 free(wi);
329 }
330  
331 static void fbsd_close(struct wif *wi)
332 {
333 struct priv_fbsd *pf = wi_priv(wi);
334  
335 close(pf->pf_fd);
336 close(pf->pf_s);
337 do_free(wi);
338 }
339  
340 static int do_fbsd_open(struct wif *wi, char *iface)
341 {
342 int i;
343 char buf[64];
344 int fd = -1;
345 struct ifreq ifr;
346 unsigned int dlt = DLT_IEEE802_11_RADIO;
347 int s;
348 unsigned int flags;
349 struct ifmediareq ifmr;
350 int *mwords;
351 struct priv_fbsd *pf = wi_priv(wi);
352  
353 /* basic sanity check */
354 if (strlen(iface) >= sizeof(ifr.ifr_name))
355 return -1;
356  
357 /* open wifi */
358 s = socket(PF_INET, SOCK_DGRAM, 0);
359 if (s == -1)
360 return -1;
361 pf->pf_s = s;
362  
363 /* set iface up and promisc */
364 memset(&ifr, 0, sizeof(ifr));
365 strcpy(ifr.ifr_name, iface);
366 if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1)
367 goto close_sock;
368  
369 flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
370 flags |= IFF_UP | IFF_PPROMISC;
371 memset(&ifr, 0, sizeof(ifr));
372 strcpy(ifr.ifr_name, iface);
373 ifr.ifr_flags = flags & 0xffff;
374 ifr.ifr_flagshigh = flags >> 16;
375 if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1)
376 goto close_sock;
377  
378 /* monitor mode */
379 memset(&ifmr, 0, sizeof(ifmr));
380 strcpy(ifmr.ifm_name, iface);
381 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1)
382 goto close_sock;
383  
384 assert(ifmr.ifm_count != 0);
385  
386 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int));
387 if (!mwords)
388 goto close_sock;
389 ifmr.ifm_ulist = mwords;
390 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) {
391 free(mwords);
392 goto close_sock;
393 }
394 free(mwords);
395  
396 memset(&ifr, 0, sizeof(ifr));
397 strcpy(ifr.ifr_name, iface);
398 ifr.ifr_media = ifmr.ifm_current;
399 if (ioctl(s, SIOCSIFMEDIA, &ifr) == -1)
400 goto close_sock;
401  
402 /* setup ifreq for chan that may be used in future */
403 strcpy(pf->pf_ireq.i_name, iface);
404 pf->pf_ireq.i_type = IEEE80211_IOC_CHANNEL;
405  
406 /* same for ifreq [mac addr] */
407 strcpy(pf->pf_ifr.ifr_name, iface);
408  
409 /* open bpf */
410 for(i = 0; i < 256; i++) {
411 sprintf(buf, "/dev/bpf%d", i);
412  
413 fd = open(buf, O_RDWR);
414 if(fd < 0) {
415 if(errno != EBUSY)
416 return -1;
417 continue;
418 }
419 else
420 break;
421 }
422  
423 if(fd < 0)
424 goto close_sock;
425  
426 strcpy(ifr.ifr_name, iface);
427  
428 if(ioctl(fd, BIOCSETIF, &ifr) < 0)
429 goto close_bpf;
430  
431 if (ioctl(fd, BIOCSDLT, &dlt) < 0)
432 goto close_bpf;
433  
434 dlt = 1;
435 if (ioctl(fd, BIOCIMMEDIATE, &dlt) == -1)
436 goto close_bpf;
437  
438 return fd;
439  
440 close_sock:
441 close(s);
442 return -1;
443 close_bpf:
444 close(fd);
445 goto close_sock;
446 }
447  
448 static int fbsd_fd(struct wif *wi)
449 {
450 struct priv_fbsd *pf = wi_priv(wi);
451  
452 return pf->pf_fd;
453 }
454  
455 static int fbsd_get_mac(struct wif *wi, unsigned char *mac)
456 {
457 struct ifaddrs *ifa, *p;
458 char *name = wi_get_ifname(wi);
459 int rc = -1;
460 struct sockaddr_dl* sdp;
461  
462 if (getifaddrs(&ifa) == -1)
463 return -1;
464  
465 p = ifa;
466 while (p) {
467 if (p->ifa_addr->sa_family == AF_LINK &&
468 strcmp(name, p->ifa_name) == 0) {
469  
470 sdp = (struct sockaddr_dl*) p->ifa_addr;
471 memcpy(mac, sdp->sdl_data + sdp->sdl_nlen, 6);
472 rc = 0;
473 break;
474 }
475  
476 p = p->ifa_next;
477 }
478 freeifaddrs(ifa);
479  
480 return rc;
481 }
482  
483 static int fbsd_get_monitor(struct wif *wi)
484 {
485 if (wi) {} /* XXX unused */
486  
487 /* XXX */
488 return 0;
489 }
490  
491 static int fbsd_get_rate(struct wif *wi)
492 {
493 if (wi) {} /* XXX unused */
494  
495 /* XXX */
496 return 1000000;
497 }
498  
499 static int fbsd_set_rate(struct wif *wi, int rate)
500 {
501 if (wi || rate) {} /* XXX unused */
502  
503 /* XXX */
504 return 0;
505 }
506  
507 static int fbsd_set_mac(struct wif *wi, unsigned char *mac)
508 {
509 struct priv_fbsd *priv = wi_priv(wi);
510 struct ifreq *ifr = &priv->pf_ifr;
511  
512 ifr->ifr_addr.sa_family = AF_LINK;
513 ifr->ifr_addr.sa_len = 6;
514 memcpy(ifr->ifr_addr.sa_data, mac, 6);
515  
516 return ioctl(priv->pf_s, SIOCSIFLLADDR, ifr);
517 }
518  
519 static int fbsd_set_mtu(struct wif *wi, int mtu)
520 {
521 struct priv_fbsd *priv = wi_priv(wi);
522 struct ifreq *ifr = &priv->pf_ifr;
523  
524 memset(ifr, 0, sizeof(struct ifreq));
525  
526 strncpy(ifr->ifr_name, wi_get_ifname(wi), sizeof(ifr->ifr_name));
527 ifr->ifr_mtu = mtu;
528  
529 if(ioctl(priv->pf_s, SIOCSIFMTU, ifr) < 0)
530 return -1;
531  
532 return 0;
533 }
534  
535 static int fbsd_get_mtu(struct wif *wi)
536 {
537 struct priv_fbsd *priv = wi_priv(wi);
538 struct ifreq ifr;
539  
540 memset(&ifr, 0, sizeof(struct ifreq));
541  
542 ifr.ifr_addr.sa_family = AF_INET;
543  
544 strncpy(ifr.ifr_name, wi_get_ifname(wi), sizeof(ifr.ifr_name));
545  
546 if(ioctl(priv->pf_s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
547 return -1;
548  
549 return ifr.ifr_mtu;
550 }
551  
552 static struct wif *fbsd_open(char *iface)
553 {
554 struct wif *wi;
555 struct priv_fbsd *pf;
556 int fd;
557  
558 /* setup wi struct */
559 wi = wi_alloc(sizeof(*pf));
560 if (!wi)
561 return NULL;
562 wi->wi_read = fbsd_read;
563 wi->wi_write = fbsd_write;
564 wi->wi_set_channel = fbsd_set_channel;
565 wi->wi_get_channel = fbsd_get_channel;
566 wi->wi_close = fbsd_close;
567 wi->wi_fd = fbsd_fd;
568 wi->wi_get_mac = fbsd_get_mac;
569 wi->wi_set_mac = fbsd_set_mac;
570 wi->wi_get_rate = fbsd_get_rate;
571 wi->wi_set_rate = fbsd_set_rate;
572 wi->wi_get_monitor = fbsd_get_monitor;
573 wi->wi_get_mtu = fbsd_get_mtu;
574 wi->wi_set_mtu = fbsd_set_mtu;
575  
576 /* setup iface */
577 fd = do_fbsd_open(wi, iface);
578 if (fd == -1) {
579 do_free(wi);
580 return NULL;
581 }
582  
583 /* setup private state */
584 pf = wi_priv(wi);
585 pf->pf_fd = fd;
586 pf->pf_txparams.ibp_vers = IEEE80211_BPF_VERSION;
587 pf->pf_txparams.ibp_len = sizeof(struct ieee80211_bpf_params) - 6;
588 pf->pf_txparams.ibp_rate0 = 2; /* 1 MB/s XXX */
589 pf->pf_txparams.ibp_try0 = 1; /* no retransmits */
590 pf->pf_txparams.ibp_rate1 = 2; /* 1 MB/s XXX */
591 pf->pf_txparams.ibp_try1 = 1; /* no retransmits */
592 pf->pf_txparams.ibp_flags = IEEE80211_BPF_NOACK;
593 pf->pf_txparams.ibp_power = 100; /* nominal max */
594 pf->pf_txparams.ibp_pri = WME_AC_VO; /* high priority */
595  
596 return wi;
597 }
598  
599 struct wif *wi_open_osdep(char *iface)
600 {
601 return fbsd_open(iface);
602 }
603  
604 int get_battery_state(void)
605 {
606 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
607 int value;
608 size_t len;
609  
610 len = 4;
611 value = 0;
612 sysctlbyname("hw.acpi.acline", &value, &len, NULL, 0);
613 if (value == 0)
614 {
615 sysctlbyname("hw.acpi.battery.time", &value, &len, NULL, 0);
616 value = value * 60;
617 }
618 else
619 {
620 value = 0;
621 }
622  
623 return( value );
624 #elif defined(_BSD_SOURCE)
625 struct apm_power_info api;
626 int apmfd;
627 if ((apmfd = open("/dev/apm", O_RDONLY)) < 0)
628 return 0;
629 if (ioctl(apmfd, APM_IOC_GETPOWER, &api) < 0) {
630 close(apmfd);
631 return 0;
632 }
633 close(apmfd);
634 if (api.battery_state == APM_BATT_UNKNOWN ||
635 api.battery_state == APM_BATTERY_ABSENT ||
636 api.battery_state == APM_BATT_CHARGING ||
637 api.ac_state == APM_AC_ON) {
638 return 0;
639 }
640 return ((int)(api.minutes_left))*60;
641 #else
642 return 0;
643 #endif
644 }