wl_linux.c
来自「wi-fi sources for asus wl138g v2 pci car」· C语言 代码 · 共 1,790 行 · 第 1/3 页
C
1,790 行
/* call common first level interrupt handler */ if ((ours = wlc_isr(wl->wlc, &wantdpc))) { /* if more to do... */ if (wantdpc) { /* ...disable interrupts... */ wlc_intrsoff_isr(wl->wlc); /* ...and call the second level interrupt handler */#if WL_TASKLET /* schedule dpc */ ASSERT(wl->resched == FALSE); tasklet_schedule(&wl->tasklet);#else wlc_dpc(wl->wlc, FALSE); wlc_intrson(wl->wlc);#endif /* WL_TASKLET */ } } spin_unlock(&wl->lock); return IRQ_RETVAL(ours);}#if WL_TASKLETstatic voidwl_dpc(ulong data){ wl_info_t *wl; wl = (wl_info_t*) data; WL_LOCK(wl); /* call the common second level interrupt handler */ if (wl->pub->up) { if (wl->resched) wlc_intrsupd(wl->wlc); wl->resched = wlc_dpc(wl->wlc, TRUE); } /* wlc_dpc() may bring the driver down */ if (!wl->pub->up) goto done; /* re-schedule dpc */ if (wl->resched) tasklet_schedule(&wl->tasklet); /* re-enable interrupts */ else wlc_intrson(wl->wlc);done: WL_UNLOCK(wl);}#endif /* WL_TASKLET */voidwl_sendup(wl_info_t *wl, wl_if_t *wlif, void *p){ struct sk_buff *skb; WL_TRACE(("wl%d: wl_sendup: %d bytes\n", wl->pub->unit, PKTLEN(wl->osh, p))); /* route packet to the appropriate interface */ if (wlif) { /* drop if the interface is not up yet */ if (!netif_device_present(wlif->dev)) { WL_ERROR(("wl%d: wl_sendup: interface not ready\n", wl->pub->unit)); PKTFREE(wl->osh, p, FALSE); return; } /* Convert the packet, mainly detach the pkttag */ skb = PKTTONATIVE(wl->osh, p); skb->dev = wlif->dev; } else { /* Convert the packet, mainly detach the pkttag */ skb = PKTTONATIVE(wl->osh, p); skb->dev = wl->dev; } skb->protocol = eth_type_trans(skb, wl->dev); ASSERT(ISALIGNED((uintptr)skb->data, 4)); /* send it up */ netif_rx(skb);}intwl_dump(wl_info_t *wl, char *buf, uint len){ /* big enough? */ if (len < WLC_IOCTL_MAXLEN) return (WLC_IOCTL_MAXLEN); sprintf(buf, "wl%d: %s %s version %s\n", wl->pub->unit, __DATE__, __TIME__, EPI_VERSION_STR); wlc_tinydump(wl->wlc, &buf[strlen(buf)]); ASSERT(strlen(buf) < len); return (strlen(buf));}static voidwl_link_up(wl_info_t *wl){ WL_ERROR(("wl%d: link up\n", wl->pub->unit));}static voidwl_link_down(wl_info_t *wl){ WL_ERROR(("wl%d: link down\n", wl->pub->unit));}voidwl_event(wl_info_t *wl, wlc_event_t *e){#ifdef CONFIG_NET_RADIO wl_iw_event(wl->dev, e);#endif /* CONFIG_NET_RADIO */ switch (e->event.event_type) { case WLC_E_LINK: case WLC_E_NDIS_LINK: if (e->event.flags&WLC_EVENT_MSG_LINK) wl_link_up(wl); else wl_link_down(wl); break; case WLC_E_MIC_ERROR: wl_tkipmic_error(wl, e->addr, e->event.flags&WLC_EVENT_MSG_GROUP, e->event.flags&WLC_EVENT_MSG_FLUSHTXQ); break; }}static voidwl_timer(ulong data){ wl_timer_t *t; t = (wl_timer_t*) data; WL_LOCK(t->wl); if (t->set) { if (t->periodic) { t->timer.expires = jiffies + t->ms*HZ/1000; t->wl->callbacks++; add_timer(&t->timer); t->set = TRUE; } else t->set = FALSE; t->fn(t->wl->wlc); } t->wl->callbacks--; WL_UNLOCK(t->wl);}wl_timer_t *wl_init_timer(wl_info_t *wl, void (*fn)(void *wlc)){ wl_timer_t *t; if (!(t = MALLOC(wl->osh, sizeof(wl_timer_t)))) { WL_ERROR(("wl%d: wl_init_timer: out of memory, malloced %d bytes\n", wl->pub->unit, MALLOCED(wl->osh))); return 0; } init_timer(&t->timer); t->timer.data = (ulong) t; t->timer.function = wl_timer; t->wl = wl; t->fn = fn; t->set = FALSE; t->periodic = FALSE; t->ms = 0; t->next = wl->timers; wl->timers = t; return t;}voidwl_add_timer(wl_info_t *wl, wl_timer_t *t, uint ms, int periodic){ ASSERT(!t->set); t->ms = ms; t->periodic = (bool) periodic; t->set = TRUE; t->timer.expires = jiffies + ms*HZ/1000; wl->callbacks++; add_timer(&t->timer);}/* return TRUE if timer successfully deleted, FALSE if still pending */boolwl_del_timer(wl_info_t *wl, wl_timer_t *t){ if (t->set) { t->set = FALSE; if (!del_timer(&t->timer)) return FALSE; wl->callbacks--; } return TRUE;}voidwl_free_timer(wl_info_t *wl, wl_timer_t *t){ ASSERT(!t->set);}static voidwl_tkipmic_error(wl_info_t *wl, struct ether_addr *ea, bool group, bool flush_txq){ WL_WSEC(("wl%d: mic error using %s key\n", wl->pub->unit, (group) ? "group" : "pairwise"));}voidwl_monitor(wl_info_t *wl, wl_rxsts_t *rxsts, void *p){ struct sk_buff *oskb = (struct sk_buff *)p; p80211msg_t *phdr; struct sk_buff *skb; uint len; uchar *pdata; WL_TRACE(("wl%d: wl_monitor\n", wl->pub->unit)); if (!wl->monitor) return; len = sizeof(p80211msg_t) + oskb->len - D11_PHY_HDR_LEN; if ((skb = dev_alloc_skb(len)) == NULL) return; skb_put(skb, len); phdr = (p80211msg_t*)skb->data; /* Initialize the message members */ phdr->msgcode = WL_MON_FRAME; phdr->msglen = sizeof(p80211msg_t); strcpy(phdr->devname, wl->dev->name); phdr->hosttime.did = WL_MON_FRAME_HOSTTIME; phdr->hosttime.status = P80211ITEM_OK; phdr->hosttime.len = 4; phdr->hosttime.data = jiffies; phdr->channel.did = WL_MON_FRAME_CHANNEL; phdr->channel.status = P80211ITEM_NO_VALUE; phdr->channel.len = 4; phdr->channel.data = 0; phdr->signal.did = WL_MON_FRAME_SIGNAL; phdr->signal.status = P80211ITEM_NO_VALUE; phdr->signal.len = 4; phdr->signal.data = (rxsts->preamble == WL_RXS_PREAMBLE_SHORT) ? 1 : 0; phdr->noise.did = WL_MON_FRAME_NOISE; phdr->noise.status = P80211ITEM_NO_VALUE; phdr->noise.len = 4; phdr->noise.data = 0; phdr->rate.did = WL_MON_FRAME_RATE; phdr->rate.status = P80211ITEM_OK; phdr->rate.len = 4; phdr->rate.data = rxsts->datarate; phdr->istx.did = WL_MON_FRAME_ISTX; phdr->istx.status = P80211ITEM_NO_VALUE; phdr->istx.len = 4; phdr->istx.data = 0; phdr->mactime.did = WL_MON_FRAME_MACTIME; phdr->mactime.status = P80211ITEM_OK; phdr->mactime.len = 4; phdr->mactime.data = rxsts->mactime; phdr->rssi.did = WL_MON_FRAME_RSSI; phdr->rssi.status = P80211ITEM_OK; phdr->rssi.len = 4; phdr->rssi.data = rxsts->signal; /* to dbm */ phdr->sq.did = WL_MON_FRAME_SQ; phdr->sq.status = P80211ITEM_OK; phdr->sq.len = 4; phdr->sq.data = rxsts->sq; phdr->frmlen.did = WL_MON_FRAME_FRMLEN; phdr->frmlen.status = P80211ITEM_OK; phdr->frmlen.status = P80211ITEM_OK; phdr->frmlen.len = 4; phdr->frmlen.data = rxsts->pktlength; pdata = skb->data + sizeof(p80211msg_t); bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN); skb->dev = wl->monitor; skb->dev->last_rx = jiffies; skb->mac.raw = skb->data; skb->ip_summed = CHECKSUM_NONE; skb->pkt_type = PACKET_OTHERHOST; skb->protocol = htons(ETH_P_80211_RAW); netif_rx(skb);}static intwl_monitor_start(struct sk_buff *skb, struct net_device *dev){ dev_kfree_skb(skb); return 0;}static voidwl_add_monitor(wl_task_t *task){ wl_info_t *wl = (wl_info_t *) task->context; WL_LOCK(wl); if (wl->monitor) goto done; if (!(wl->monitor = MALLOC(wl->osh, sizeof(struct net_device)))) goto done; bzero(wl->monitor, sizeof(struct net_device)); DEV_WLPTR(wl->monitor) = wl; wl->monitor->hard_start_xmit = wl_monitor_start; wl->monitor->do_ioctl = wl_ioctl; sprintf(wl->monitor->name, "prism%d", wl->pub->unit); bcopy(wl->dev->dev_addr, wl->monitor->dev_addr, ETHER_ADDR_LEN); wl->monitor->type = ARPHRD_IEEE80211_PRISM; wl->monitor->flags = wl->dev->flags; if (register_netdev(wl->monitor)) { MFREE(wl->osh, wl->monitor, sizeof(struct net_device)); wl->monitor = NULL; goto done; }done: WL_ERROR(("wl%d: wl_add_monitor: out of memory, malloced %d bytes\n", wl->pub->unit, MALLOCED(wl->osh))); MFREE(wl->osh, task, sizeof(wl_task_t)); wl->callbacks--; WL_UNLOCK(wl);}static voidwl_del_monitor(wl_task_t *task){ wl_info_t *wl = (wl_info_t *) task->context; WL_LOCK(wl); if (!wl->monitor) goto done; unregister_netdev(wl->monitor); MFREE(wl->osh, wl->monitor, sizeof(struct net_device)); wl->monitor = NULL;done: MFREE(wl->osh, task, sizeof(wl_task_t)); wl->callbacks--; WL_UNLOCK(wl);}/* * Create a dedicated monitor interface since libpcap caches the * packet type when it opens the device. The protocol type in the skb * is dropped somewhere in libpcap, and every received frame is tagged * with the DLT/ARPHRD type that's read by libpcap when the device is * opened. * * If libpcap was fixed to handle per-packet link types, we might not * need to create a pseudo device at all, wl_set_monitor() would be * unnecessary, and wlc->monitor could just get set in wlc_ioctl(). */voidwl_set_monitor(wl_info_t *wl, int val){ WL_TRACE(("wl%d: wl_set_monitor: val %d\n", wl->pub->unit, val)); if (val && !wl->monitor) (void) wl_schedule_task(wl, wl_add_monitor, wl); else if (!val && wl->monitor) (void) wl_schedule_task(wl, wl_del_monitor, wl);}struct net_device *wl_netdev_get(wl_info_t *wl){ return wl->dev;}intwl_tkip_miccheck(wl_info_t *wl, void *p, int hdr_len, bool group_key, int key_index){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) struct sk_buff *skb; skb = PKTTONATIVE(wl->osh, p); if (wl->tkipmodops) { if (group_key && wl->tkip_bcast_data) return(wl->tkipmodops->decrypt_msdu(skb, key_index, hdr_len, wl->tkip_bcast_data)); else if (!group_key && wl->tkip_ucast_data) return(wl->tkipmodops->decrypt_msdu(skb, key_index, hdr_len, wl->tkip_ucast_data)); }#endif /* Error */ WL_ERROR(("%s: No tkip mod ops\n", __FUNCTION__)); return -1;}intwl_tkip_micadd(wl_info_t *wl, void *p, int hdr_len){ int error = -1;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) struct sk_buff *skb; skb = PKTTONATIVE(wl->osh, p); if (wl->tkipmodops) { if (wl->tkip_ucast_data) error = wl->tkipmodops->encrypt_msdu(skb, hdr_len, wl->tkip_ucast_data); if (error) WL_ERROR(("Error encrypting MSDU %d\n", error)); } else #endif WL_ERROR(("%s: No tkip mod ops\n", __FUNCTION__)); return error; }intwl_tkip_encrypt(wl_info_t *wl, void *p, int hdr_len){ int error = -1;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) struct sk_buff *skb; skb = PKTTONATIVE(wl->osh, p); if (wl->tkipmodops) { if (wl->tkip_ucast_data) error = wl->tkipmodops->encrypt_mpdu(skb, hdr_len, wl->tkip_ucast_data); if (error) { WL_ERROR(("Error encrypting MPDU %d\n", error)); } } else #endif WL_ERROR(("%s: No tkip mod ops\n", __FUNCTION__)); return error; }intwl_tkip_decrypt(wl_info_t *wl, void *p, int hdr_len, bool group_key){ int err = -1;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) struct sk_buff *skb; skb = PKTTONATIVE(wl->osh, p); if (wl->tkipmodops) { if (group_key && wl->tkip_bcast_data) err = wl->tkipmodops->decrypt_mpdu(skb, hdr_len, wl->tkip_bcast_data); else if (!group_key && wl->tkip_ucast_data) err = wl->tkipmodops->decrypt_mpdu(skb, hdr_len, wl->tkip_ucast_data); } else WL_ERROR(("%s: No tkip mod ops\n", __FUNCTION__));#endif /* Error */ return err;}intwl_tkip_keyset(wl_info_t *wl, wsec_key_t *key){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) bool group_key = FALSE; uchar rxseq[IW_ENCODE_SEQ_MAX_SIZE]; if (key->len != 0) { WL_WSEC(("%s: Key Length is Not zero\n", __FUNCTION__)); if (key->algo != CRYPTO_ALGO_TKIP) { WL_WSEC(("%s: Algo is Not TKIP %d\n", __FUNCTION__, key->algo)); return 0; } WL_WSEC(("%s: Trying to set a key in TKIP Mod\n", __FUNCTION__)); } else WL_WSEC(("%s: Trying to Remove a Key from TKIP Mod\n", __FUNCTION__)); if (ETHER_ISNULLADDR(&key->ea) || ETHER_ISBCAST(&key->ea)) { group_key = TRUE; WL_WSEC(("Group Key index %d\n", key->id)); } else WL_WSEC(("Unicast Key index %d\n", key->id)); if (wl->tkipmodops) { if (group_key) { if (key->len) { if (!wl->tkip_bcast_data) { WL_WSEC(("Init TKIP Bcast Module\n")); WL_UNLOCK(wl); wl->tkip_bcast_data = wl->tkipmodops->init(key->id); WL_LOCK(wl); } if (wl->tkip_bcast_data) { bzero(rxseq, IW_ENCODE_SEQ_MAX_SIZE); bcopy(&key->rxiv, rxseq, 6); wl->tkipmodops->set_key(&key->data, key->len, (uint8 *)&key->rxiv, wl->tkip_bcast_data); } } else { if (wl->tkip_bcast_data) { WL_WSEC(("Deinit TKIP Bcast Module\n")); wl->tkipmodops->deinit(wl->tkip_bcast_data); wl->tkip_bcast_data = NULL; } } } else { if (key->len) { if (!wl->tkip_ucast_data) { WL_WSEC(("Init TKIP Ucast Module\n")); WL_UNLOCK(wl); wl->tkip_ucast_data = wl->tkipmodops->init(key->id); WL_LOCK(wl); } if (wl->tkip_ucast_data) { bzero(rxseq, IW_ENCODE_SEQ_MAX_SIZE); bcopy(&key->rxiv, rxseq, 6); wl->tkipmodops->set_key(&key->data, key->len, (uint8 *)&key->rxiv, wl->tkip_ucast_data); } } else { if (wl->tkip_ucast_data) { WL_WSEC(("Deinit TKIP Ucast Module\n")); wl->tkipmodops->deinit(wl->tkip_ucast_data); wl->tkip_ucast_data = NULL; } } } } else #endif WL_WSEC(("%s: No tkip mod ops\n", __FUNCTION__)); return 0;}void wl_tkip_printstats(wl_info_t *wl, bool group_key){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) char debug_buf[512]; if (wl->tkipmodops) { if (group_key && wl->tkip_bcast_data) wl->tkipmodops->print_stats(debug_buf, wl->tkip_bcast_data); else if (!group_key && wl->tkip_ucast_data) wl->tkipmodops->print_stats(debug_buf, wl->tkip_ucast_data); else return; printk("%s: TKIP stats from module: %s\n", debug_buf, group_key?"Bcast":"Ucast"); }#endif}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?