2346
2422
wl_monitor(wl_info_t *wl, wl_rxsts_t *rxsts, void *p)
2424
struct sk_buff *oskb = (struct sk_buff *)p;
2425
struct sk_buff *skb;
2431
WL_TRACE(("wl%d: wl_monitor\n", wl->pub->unit));
2433
if (!wl->monitor_dev)
2436
if (wl->monitor_type == ARPHRD_IEEE80211_PRISM) {
2439
len = sizeof(p80211msg_t) + oskb->len - D11_PHY_HDR_LEN;
2440
if ((skb = dev_alloc_skb(len)) == NULL)
2444
phdr = (p80211msg_t*)skb->data;
2446
phdr->msgcode = WL_MON_FRAME;
2447
phdr->msglen = sizeof(p80211msg_t);
2448
strcpy(phdr->devname, wl->dev->name);
2450
phdr->hosttime.did = WL_MON_FRAME_HOSTTIME;
2451
phdr->hosttime.status = P80211ITEM_OK;
2452
phdr->hosttime.len = 4;
2453
phdr->hosttime.data = jiffies;
2455
phdr->channel.did = WL_MON_FRAME_CHANNEL;
2456
phdr->channel.status = P80211ITEM_NO_VALUE;
2457
phdr->channel.len = 4;
2458
phdr->channel.data = 0;
2460
phdr->signal.did = WL_MON_FRAME_SIGNAL;
2461
phdr->signal.status = P80211ITEM_OK;
2462
phdr->signal.len = 4;
2464
phdr->signal.data = rxsts->preamble;
2466
phdr->noise.did = WL_MON_FRAME_NOISE;
2467
phdr->noise.status = P80211ITEM_NO_VALUE;
2468
phdr->noise.len = 4;
2469
phdr->noise.data = 0;
2471
phdr->rate.did = WL_MON_FRAME_RATE;
2472
phdr->rate.status = P80211ITEM_OK;
2474
phdr->rate.data = rxsts->datarate;
2476
phdr->istx.did = WL_MON_FRAME_ISTX;
2477
phdr->istx.status = P80211ITEM_NO_VALUE;
2479
phdr->istx.data = 0;
2481
phdr->mactime.did = WL_MON_FRAME_MACTIME;
2482
phdr->mactime.status = P80211ITEM_OK;
2483
phdr->mactime.len = 4;
2484
phdr->mactime.data = rxsts->mactime;
2486
phdr->rssi.did = WL_MON_FRAME_RSSI;
2487
phdr->rssi.status = P80211ITEM_OK;
2489
phdr->rssi.data = rxsts->signal;
2491
phdr->sq.did = WL_MON_FRAME_SQ;
2492
phdr->sq.status = P80211ITEM_OK;
2494
phdr->sq.data = rxsts->sq;
2496
phdr->frmlen.did = WL_MON_FRAME_FRMLEN;
2497
phdr->frmlen.status = P80211ITEM_OK;
2498
phdr->frmlen.status = P80211ITEM_OK;
2499
phdr->frmlen.len = 4;
2500
phdr->frmlen.data = rxsts->pktlength;
2502
pdata = skb->data + sizeof(p80211msg_t);
2503
bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN);
2505
} else if (wl->monitor_type == ARPHRD_IEEE80211_RADIOTAP) {
2506
int channel_frequency;
2507
uint16 channel_flags;
2510
struct dot11_header * mac_header;
2513
if (rxsts->datarate != 0)
2514
rtap_len = sizeof(struct wl_radiotap_legacy);
2516
rtap_len = sizeof(struct wl_radiotap_ht);
2518
len = rtap_len + (oskb->len - D11_PHY_HDR_LEN);
2519
if ((skb = dev_alloc_skb(len)) == NULL)
2524
if (CHSPEC_IS2G(rxsts->chanspec)) {
2525
channel_flags = IEEE80211_CHAN_2GHZ;
2526
channel_frequency = wf_channel2mhz(CHSPEC_CHANNEL(rxsts->chanspec),
2527
WF_CHAN_FACTOR_2_4_G);
2529
channel_flags = IEEE80211_CHAN_5GHZ;
2530
channel_frequency = wf_channel2mhz(CHSPEC_CHANNEL(rxsts->chanspec),
2531
WF_CHAN_FACTOR_5_G);
2534
mac_header = (struct dot11_header *)(oskb->data + D11_PHY_HDR_LEN);
2535
fc = ntoh16(mac_header->fc);
2537
flags = IEEE80211_RADIOTAP_F_FCS;
2539
if (rxsts->preamble == WL_RXS_PREAMBLE_SHORT)
2540
flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
2542
if (fc & (FC_WEP >> FC_WEP_SHIFT))
2543
flags |= IEEE80211_RADIOTAP_F_WEP;
2545
if (fc & (FC_MOREFRAG >> FC_MOREFRAG_SHIFT))
2546
flags |= IEEE80211_RADIOTAP_F_FRAG;
2548
if (rxsts->pkterror & WL_RXS_CRC_ERROR)
2549
flags |= IEEE80211_RADIOTAP_F_BADFCS;
2551
if (rxsts->datarate != 0) {
2552
struct wl_radiotap_legacy *rtl = (struct wl_radiotap_legacy*)skb->data;
2554
rtl->ieee_radiotap.it_version = 0;
2555
rtl->ieee_radiotap.it_pad = 0;
2556
rtl->ieee_radiotap.it_len = HTOL16(rtap_len);
2557
rtl->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_LEGACY);
2559
rtl->tsft_l = htol32(rxsts->mactime);
2561
rtl->rate = rxsts->datarate;
2562
rtl->channel_freq = HTOL16(channel_frequency);
2563
rtl->channel_flags = HTOL16(channel_flags);
2564
rtl->signal = (int8)rxsts->signal;
2565
rtl->noise = (int8)rxsts->noise;
2566
rtl->antenna = rxsts->antenna;
2568
struct wl_radiotap_ht *rtht = (struct wl_radiotap_ht*)skb->data;
2570
rtht->ieee_radiotap.it_version = 0;
2571
rtht->ieee_radiotap.it_pad = 0;
2572
rtht->ieee_radiotap.it_len = HTOL16(rtap_len);
2573
rtht->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_HT);
2574
rtht->it_present_ext = HTOL32(WL_RADIOTAP_BRCM_MCS);
2577
rtht->tsft_l = htol32(rxsts->mactime);
2578
rtht->flags = flags;
2580
rtht->channel_freq = HTOL16(channel_frequency);
2581
rtht->channel_flags = HTOL16(channel_flags);
2582
rtht->signal = (int8)rxsts->signal;
2583
rtht->noise = (int8)rxsts->noise;
2584
rtht->antenna = rxsts->antenna;
2587
memcpy(rtht->vend_oui, "\x00\x10\x18", 3);
2588
rtht->vend_sns = WL_RADIOTAP_BRCM_SNS;
2589
rtht->vend_skip_len = 2;
2591
rtht->mcs = rxsts->mcs;
2593
if (rxsts->htflags & WL_RXS_HTF_40)
2594
rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_40;
2595
if (rxsts->htflags & WL_RXS_HTF_SGI)
2596
rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_SGI;
2597
if (rxsts->preamble & WL_RXS_PREAMBLE_HT_GF)
2598
rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_GF;
2599
if (rxsts->htflags & WL_RXS_HTF_LDPC)
2600
rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_LDPC;
2602
(rxsts->htflags & WL_RXS_HTF_STBC_MASK) <<
2603
IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT;
2606
pdata = skb->data + rtap_len;
2607
bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN);
2610
skb->dev = wl->monitor_dev;
2611
skb->dev->last_rx = jiffies;
2612
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
2613
skb_reset_mac_header(skb);
2615
skb->mac.raw = skb->data;
2617
skb->ip_summed = CHECKSUM_NONE;
2618
skb->pkt_type = PACKET_OTHERHOST;
2619
skb->protocol = htons(ETH_P_80211_RAW);
2622
netif_receive_skb(skb);
2629
wl_monitor_start(struct sk_buff *skb, struct net_device *dev)
2633
wl = WL_DEV_IF(dev)->wl;
2634
PKTFREE(wl->osh, skb, FALSE);
2639
wl_add_monitor(wl_task_t *task)
2641
wl_info_t *wl = (wl_info_t *) task->context;
2642
struct net_device *dev;
2647
WL_TRACE(("wl%d: wl_add_monitor\n", wl->pub->unit));
2649
if (wl->monitor_dev)
2652
wlif = wl_alloc_if(wl, WL_IFTYPE_MON, wl->pub->unit, NULL);
2654
WL_ERROR(("wl%d: wl_add_monitor: alloc wlif failed\n", wl->pub->unit));
2659
wl->monitor_dev = dev;
2661
bcopy(wl->dev->dev_addr, dev->dev_addr, ETHER_ADDR_LEN);
2662
dev->flags = wl->dev->flags;
2663
dev->type = wl->monitor_type;
2664
if (wl->monitor_type == ARPHRD_IEEE80211_PRISM) {
2665
sprintf(dev->name, "prism%d", wl->pub->unit);
2667
sprintf(dev->name, "radiotap%d", wl->pub->unit);
2670
#if defined(WL_USE_NETDEV_OPS)
2671
dev->netdev_ops = &wl_netdev_monitor_ops;
2673
dev->hard_start_xmit = wl_monitor_start;
2674
dev->do_ioctl = wl_ioctl;
2675
dev->get_stats = wl_get_stats;
2679
if (register_netdev(dev)) {
2680
WL_ERROR(("wl%d: wl_add_monitor, register_netdev failed for \"%s\"\n",
2681
wl->pub->unit, wl->monitor_dev->name));
2682
wl->monitor_dev = NULL;
2683
wl_free_if(wl, wlif);
2685
wlif->dev_registed = TRUE;
2688
MFREE(wl->osh, task, sizeof(wl_task_t));
2689
atomic_dec(&wl->callbacks);
2694
wl_del_monitor(wl_task_t *task)
2696
wl_info_t *wl = (wl_info_t *) task->context;
2697
struct net_device *dev;
2698
wl_if_t *wlif = NULL;
2702
WL_TRACE(("wl%d: wl_del_monitor\n", wl->pub->unit));
2703
dev = wl->monitor_dev;
2706
wlif = WL_DEV_IF(dev);
2708
wl->monitor_dev = NULL;
2710
wl_free_if(wl, wlif);
2713
MFREE(wl->osh, task, sizeof(wl_task_t));
2715
atomic_dec(&wl->callbacks);
2351
2719
wl_set_monitor(wl_info_t *wl, int val)
2721
WL_TRACE(("wl%d: wl_set_monitor: val %d\n", wl->pub->unit, val));
2723
if (val && !wl->monitor_dev) {
2725
wl->monitor_type = ARPHRD_IEEE80211_PRISM;
2727
wl->monitor_type = ARPHRD_IEEE80211_RADIOTAP;
2729
WL_ERROR(("monitor type %d not supported\n", val));
2733
(void) wl_schedule_task(wl, wl_add_monitor, wl);
2734
} else if (!val && wl->monitor_dev) {
2735
(void) wl_schedule_task(wl, wl_del_monitor, wl);
2355
2739
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15)
3123
wl_proc_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
3125
wl_info_t * wl = (wl_info_t *)data;
3126
int bcmerror, to_user;
3135
WL_ERROR(("%s: Not enough return buf space\n", __FUNCTION__));
3139
bcmerror = wlc_ioctl(wl->wlc, WLC_GET_MONITOR, &to_user, sizeof(int), NULL);
3140
len = sprintf(buffer, "%d\n", to_user);
3146
wl_proc_write(struct file *filp, const char __user *buff, unsigned long length, void *data)
3148
wl_info_t * wl = (wl_info_t *)data;
3152
if (length == 0 || length > 2) {
3154
WL_ERROR(("%s: Invalid data length\n", __FUNCTION__));
3157
if (copy_from_user(&from_user, buff, 1)) {
3158
WL_ERROR(("%s: copy from user failed\n", __FUNCTION__));
3162
if (from_user >= 0x30)
3166
bcmerror = wlc_ioctl(wl->wlc, WLC_SET_MONITOR, &from_user, sizeof(int), NULL);
3170
WL_ERROR(("%s: SET_MONITOR failed with %d\n", __FUNCTION__, bcmerror));
3177
wl_reg_proc_entry(wl_info_t *wl)
3180
sprintf(tmp, "%s%d", HYBRID_PROC, wl->pub->unit);
3181
if ((wl->proc_entry = create_proc_entry(tmp, 0644, NULL)) == NULL) {
3182
WL_ERROR(("%s: create_proc_entry %s failed\n", __FUNCTION__, tmp));
3186
wl->proc_entry->read_proc = wl_proc_read;
3187
wl->proc_entry->write_proc = wl_proc_write;
3188
wl->proc_entry->data = wl;