📄 am930llc.c
字号:
(wlan_ie_ssid_t*)cmd.ssid, cmd.beacon_int, cmd.atim_win); break; } case WLAN_BSSJOIN: { wlan_bssjoin_t cmd; if (copy_from_user( &cmd, req->data, sizeof(cmd))) { result = -EFAULT; break; } req->result = am930mgr_joinbss( llc->mgr, cmd.bssid ); break; } case WLAN_AUTHENTICATE: { UINT32 timeout = 2 * HZ; /* default 2 second */ /* Call mgr to begin the authentication */ am930mgr_authen_begin_sta( llc->mgr, WLAN_AUTH_ALG_OPENSYSTEM); /* Set a timer for (mgmt_timeout) to make sure we return */ init_timer(&llc->cmdtimer); llc->cmdtimer.data = (unsigned long)llc; llc->cmdtimer.function = (timerfunc_t)am930llc_cmdtimerfunc; llc->cmdtimer.expires = jiffies + timeout; add_timer(&llc->cmdtimer); /* Now, do an interruptible_sleep, we'll be awakened by: */ /* a signal the process, cmdtimerfunc (timeout), or llc_scancomplete */ interruptible_sleep_on(&(llc->cmdwq)); llc->cmdwq = NULL; /* If sleep return is via signal */ if ( signal_pending(current) ) { /* stop authen and clean up */ am930mgr_authen_stop(llc->mgr); del_timer(&llc->cmdtimer); result = -EINTR; } else { /* If timeout */ if ( llc->cmdtimer.expires == 0 ) { /* stop authen and clean up */ am930mgr_authen_stop(llc->mgr); result = -ETIME; } else { /* Success */ /* clean up timer */ del_timer(&llc->cmdtimer); llc->cmdtimer.expires=0; req->result = llc->cmdstatus; /* return success */ result = 0; } } break; } case WLAN_ASSOCIATE: { UINT32 timeout = 2 * HZ; /* default 2 second */ /* Call mgr to begin the association */ am930mgr_assoc_begin_sta(llc->mgr); /* Set a timer for (mgmt_timeout) to make sure we return */ init_timer(&llc->cmdtimer); llc->cmdtimer.data = (unsigned long)llc; llc->cmdtimer.function = (timerfunc_t)am930llc_cmdtimerfunc; llc->cmdtimer.expires = jiffies + timeout; add_timer(&llc->cmdtimer); /* Now, do an interruptible_sleep, we'll be awakened by: */ /* a signal the process, cmdtimerfunc (timeout), or llc_scancomplete */ interruptible_sleep_on(&(llc->cmdwq)); llc->cmdwq = NULL; /* If sleep return is via signal */ if ( signal_pending(current) ) { /* stop assoc and clean up */ am930mgr_assoc_stop(llc->mgr); del_timer(&llc->cmdtimer); result = -EINTR; } else { /* If timeout */ if ( llc->cmdtimer.expires == 0 ) { /* stop assoc and clean up */ am930mgr_assoc_stop(llc->mgr); result = -ETIME; } else { /* Success */ /* clean up timer */ del_timer(&llc->cmdtimer); llc->cmdtimer.expires=0; req->result = llc->cmdstatus; /* return success */ result = 0; } } break; } case WLAN_GETMIB: { UINT8* p = NULL; UINT32 size = 0; UINT32 mibcode; p = kmalloc(req->len, GFP_KERNEL); if (p == NULL) { result = -ENOMEM; break; } if ( copy_from_user( &mibcode, req->data, 4 ) ) { kfree_s(p, req->len); result = -EFAULT; break; } switch(mibcode) { case SUMIB_LOCAL: size = sizeof(su_mib_local_t); break; case SUMIB_ADDR: size = sizeof(su_mib_mac_addr_stat_grp_t); break; case SUMIB_MAC: size = sizeof(su_mib_mac_t); break; case SUMIB_STAT: size = sizeof(su_mib_mac_statistics_t); break; case SUMIB_MGMT: size = sizeof(su_mib_mac_mgmt_t); break; case SUMIB_DRVR: /* size = sizeof(su_mib_local_t); */ size = 0; break; case SUMIB_PHY: size = sizeof(su_mib_phy_t); break; } am930mgr_mibget( llc->mgr, mibcode, size, p); if ( copy_to_user( ((UINT8*)(req->data)) + 4, p, size)) { result = -EFAULT; } kfree_s(p, req->len); break; } case WLAN_SETMIBITEM: case WLAN_GETMIBITEM: result = -ENOSYS; break; case WLAN_PRIVACY: { wlan_privacy_t cmd; int i; if ( copy_from_user( &cmd, req->data, sizeof(cmd)) ) { result = -EFAULT; break; } llc->mac->wep_defkeyid = cmd.defkey; llc->mac->exclude_unencrypted = cmd.exclude_unencrypted; for ( i = 0; i < WLAN_WEP_NKEYS; i++) { memcpy( llc->mac->wep_key[i], cmd.keys[i], WLAN_WEP_KEYLEN); } llc->mac->privacy_invoked = 1; WLAN_LOG_DEBUG2(2, "Wep set: defkey=%lu, exclude=%lu\n", (UINT32)llc->mac->wep_defkeyid, (UINT32)llc->mac->exclude_unencrypted); WLAN_LOG_DEBUG5(2, "Wep key0: %02x:%02x:%02x:%02x:%02x\n", llc->mac->wep_key[0][0], llc->mac->wep_key[0][1], llc->mac->wep_key[0][2], llc->mac->wep_key[0][3], llc->mac->wep_key[0][4] ); WLAN_LOG_DEBUG5(2, "Wep key1: %02x:%02x:%02x:%02x:%02x\n", llc->mac->wep_key[1][0], llc->mac->wep_key[1][1], llc->mac->wep_key[1][2], llc->mac->wep_key[1][3], llc->mac->wep_key[1][4] ); WLAN_LOG_DEBUG5(2, "Wep key2: %02x:%02x:%02x:%02x:%02x\n", llc->mac->wep_key[2][0], llc->mac->wep_key[2][1], llc->mac->wep_key[2][2], llc->mac->wep_key[2][3], llc->mac->wep_key[2][4] ); WLAN_LOG_DEBUG5(2, "Wep key3: %02x:%02x:%02x:%02x:%02x\n", llc->mac->wep_key[3][0], llc->mac->wep_key[3][1], llc->mac->wep_key[3][2], llc->mac->wep_key[3][3], llc->mac->wep_key[3][4] ); break; } case WLAN_ETHCONV: { wlan_ethconv_t cmd; if ( copy_from_user( &cmd, req->data, sizeof(cmd)) ) { result = -EFAULT; break; } llc->ethconv = cmd.ethconv_type; switch( llc->ethconv ) { case WLAN_ETHCONV_ENCAP: WLAN_LOG_NOTICE0("ethconv=encapsulation\n"); break; case WLAN_ETHCONV_RFC1042: WLAN_LOG_NOTICE0("ethconv=rfc1042\n"); break; case WLAN_ETHCONV_8021h: WLAN_LOG_NOTICE0("ethconv=802.1h\n"); break; default: WLAN_LOG_NOTICE0("ethconv=UNKNOWN...this is bad.\n"); break; } break; } case WLAN_SNIFFERCMD: { #ifdef WLAN_INCLUDE_SNIF wlan_sniffercmd_t cmd; if ( copy_from_user( &cmd, req->data, sizeof(cmd)) ) { result = -EFAULT; break; } cmd.result = 0; if ( cmd.cmd == SNIFFERCMD_REG ) { WLAN_LOG_DEBUG0(2, "Doing sniffer cmd reg.\n"); if ( llc->nlsk == NULL || llc->snifferpid != 0 ) { WLAN_LOG_DEBUG1(1, "llc->nlsk=%lx\n", (UINT32)llc->nlsk); WLAN_LOG_DEBUG1(1, "llc->snifferpid=%d\n", llc->snifferpid); WLAN_LOG_DEBUG0(1, "Failed to reg sniffer: no netlink or sniffer already reg.\n"); cmd.result = -1; } else { llc->snifferpid = cmd.pid; llc->mac->snifflags = SNIFFLAG_SNIFRX | cmd.flags; } } else if ( cmd.cmd == SNIFFERCMD_UNREG ) { WLAN_LOG_DEBUG0(2, "Doing sniffer cmd unreg.\n"); llc->snifferpid = 0; llc->mac->snifflags = 0; } if ( copy_to_user( req->data, &cmd, sizeof(cmd)) ) { result = -EFAULT; } #else result = -ENOSYS; #endif break; } default: printk(KERN_DEBUG "am930_cs: Unknown or unsupported wlan ioctl!\n"); break; } llc->currcmd = 0; } clear_bit( 0, (void*)&(llc->cmdbusy)); DBFEXIT; return result;}/*----------------------------------------------------------------* am930llc_devgetstats* getstats method for the linux net device. Called as a result* of a number of user mode utilities used to check the rx/tx* statistics of an interface.** returns: zero----------------------------------------------------------------*/enet_stats_t* am930llc_devgetstats(device_t *dev){ DBFENTER; DBFEXIT; return &(V2P(dev->priv)->stats);}/*----------------------------------------------------------------* am930llc_devhard_start_xmit* hard_start_xmint method for the linux net device. Called by * the higher level protocol code when it has a packet to xmit.** returns: zero----------------------------------------------------------------*/int am930llc_devhard_start_xmit( struct sk_buff *skb, device_t *dev){ int result = 0; int txresult = -1; wlan_pb_t *pb; am930llc_t *llc = V2P(dev->priv)->llc; DBFENTER; if ( dev->start == 1 ) { /* If some higher layer thinks we've missed a tx-done, we are passed NULL. Caution: dev_tint handles the cli/sti .. */#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,25)) if ( skb == NULL ) { dev->tbusy = 0; dev_tint(dev); return 0; }#endif if ( test_and_set_bit(0, (void*)&(dev->tbusy)) != 0 ) { /* TODO: add a f/w reset capability here. see skeleton.c */ WLAN_LOG_DEBUG2(1, "called when tbusy set," "txllc.len=%d txmac.len=%d\n", llc->mac->llcq->len, llc->mac->macq->len); result = 1; } else { dev->trans_start = jiffies; /* OK, now we setup the ether to 802.11 conversion */ pb = am930llc_pballoc(); if ( pb != NULL ) { pb->ethhostbuf = skb; pb->ethfree = am930llc_pbfreeskb; pb->ethbuf = skb->data; pb->ethbuflen = skb->len; pb->ethfrmlen = skb->len; pb->eth_hdr = (wlan_ethhdr_t*)pb->ethbuf; if ( am930llc_pb_ether_to_p80211( llc, pb) != 0 ) { /* convert failed */ result = 1; am930llc_pbfree(pb); } else { txresult = am930mac_txllc( llc->mac, pb->eth_hdr->daddr, pb->eth_hdr->saddr, pb); if ( txresult == 0) /* success and more buf avail, re: hw_txdata */ { dev->tbusy = 0; result = 0; } else if ( txresult == 1 ) /* success, no more avail */ { result = 0; } else if ( txresult == 2 ) /* alloc failure, drop frame */ { result = 0; am930llc_pbfree(pb); } else /* buffer full or queue busy */ { result = 1; pb->ethfree = NULL; } } } } } DBFEXIT; return result;}/*----------------------------------------------------------------* am930llc_devopen* open method for the linux net device. Called when ifconfig* is used to set up the interface.** returns: zero----------------------------------------------------------------*/int am930llc_devopen(device_t *dev){ int result = 0; DBFENTER; /* set the flags in the device object */ dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; #ifdef WLAN_PCMCIA MOD_INC_USE_COUNT; #endif DBFEXIT; return result;}/*----------------------------------------------------------------* am930llc_devstop* stop method for the linux net device. Called when ifconfig* is used to shut down an interface.** returns: zero----------------------------------------------------------------*/int am930llc_devstop(device_t *dev){ int result = 0; DBFENTER; /* set the flags in the device object */ dev->start = 0; dev->tbusy = 1; #ifdef WLAN_PCMCIA MOD_DEC_USE_COUNT; #endif DBFEXIT; return result;}/*----------------------------------------------------------------* am930llc_nlfunc* Called by netlink when an skb is ready on our netlink i/f.* Currently does nothing since we don't expect anything to be* coming in.* Arguments:* sk - sock representing our netlink i/f* len - buf len* returns: nothing----------------------------------------------------------------*/void am930llc_nlfunc(struct sock *sk, int len){ return;}/*----------------------------------------------------------------* am930llc_pb_ether_to_p80211* Uses the contents of the ether frame and the etherconv setting* to build the elements of the 802.11 frame. ** We don't actually set * up the frame header here. That's the MAC's job. We're only handling* conversion of DIXII or 802.3+LLC frames to something that works* with 802.11.** Assume the following are already set:* pb->ethfree* pb->ethhostbuf* pb->ethbuf;* pb->ethbuflen* pb->eth_hdr* returns: zero on success, non-zero on failure----------------------------------------------------------------*/int am930llc_pb_ether_to_p80211( am930llc_t *llc, wlan_pb_t *pb){ UINT16 proto; if ( llc->ethconv == WLAN_ETHCONV_ENCAP ) /* simplest case */ { /* here, we don't care what kind of ether frm. Just stick it */ /* in the 80211 payload */ pb->p80211hostbuf = kmalloc( WLAN_HDR_A3_LEN, GFP_ATOMIC); if ( pb->p80211hostbuf == NULL ) return 1; pb->p80211buflen = WLAN_HDR_A3_LEN; pb->p80211free = am930llc_pbkfree_s; pb->p80211buf = (UINT8*)(pb->p80211hostbuf); pb->p80211_hdr = (p80211_hdr_t*)pb->p80211buf; pb->p80211_payload = pb->ethbuf; pb->p80211_payloadlen = pb->ethbuflen; } else { /* step 1: classify ether frame, DIX or 802.3? */ proto = ntohs(pb->eth_hdr->type); if ( proto <= 0x05DC ) /* type|len <= 1500 ? */ { /* it's 802.3, pass ether payload unchanged, */ /* leave off any PAD octets. */ pb->p80211hostbuf = kmalloc( WLAN_HDR_A3_LEN, GFP_ATOMIC); if ( pb->p80211hostbuf == NULL ) return 1; pb->p80211buflen = WLAN_HDR_A3_LEN; pb->p80211free = am930llc_pbkfree_s; pb->p80211buf = (UINT8*)(pb->p80211hostbuf); pb->p80211_hdr = (p80211_hdr_t*)pb->p80211buf; /* setup the payload ptrs */ pb->p80211_payload = pb->ethbuf + sizeof(wlan_ethhdr_t); pb->p80211_payloadlen = ntohs(pb->eth_hdr->type); } else { /* it's DIXII, time for some conversion */ pb->p80211hostbuf = kmalloc( WLAN_HDR_A3_LEN + sizeof(wlan_llc_t) + sizeof(wlan_snap_t), GFP_ATOMIC); if ( pb->p80211hostbuf == NULL ) return 1; pb->p80211buflen = WLAN_HDR_A3_LEN + sizeof(wlan_llc_t) + sizeof(wlan_snap_t); pb->p80211free = am930llc_pbkfree_s; pb->p80211buf = (UINT8*)pb->p80211hostbuf; pb->p80211_hdr = (p80211_hdr_t*)pb->p80211buf; pb->p80211_llc = (wlan_llc_t*)(pb->p80211buf + WLAN_HDR_A3_LEN); pb->p80211_snap = (wlan_snap_t*)(((UINT8*)pb->p80211_llc) + sizeof(wlan_llc_t)); /* setup the LLC header */ pb->p80211_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */ pb->p80211_llc->ssap = 0xAA; pb->p80211_llc->ctl = 0x03; /* setup the SNAP header */ pb->p80211_snap->type = htons(proto); if ( llc->ethconv == WLAN_ETHCONV_8021h && am930llc_stt_findproto(llc, proto) ) { memcpy( pb->p80211_snap->oui, oui_8021h, WLAN_IEEE_OUI_LEN); } else { memcpy( pb->p80211_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN); } /* setup the payload ptrs */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -