📄 p80211netdev.c
字号:
}/*----------------------------------------------------------------* register_wlandev** Roughly matches the functionality of register_netdev. This function* is called after the driver has successfully probed and set up the* resources for the device. It's now ready to become a named device* in the Linux system.** First we allocate a name for the device (if not already set), then* we call the Linux function register_netdevice.** Arguments:* wlandev ptr to the wlandev structure for the* interface.* Returns: * zero on success, non-zero otherwise.* Call Context:* Can be either interrupt or not.----------------------------------------------------------------*/int register_wlandev(wlandevice_t *wlandev){ int i = 0; netdevice_t *dev = wlandev->netdev; DBFENTER; i = dev_alloc_name(wlandev->netdev, "wlan%d"); if (i >= 0) { i = register_netdev(wlandev->netdev); } if (i != 0) { return -EIO; }#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) ) dev->name = wlandev->name;#else strcpy(wlandev->name, dev->name);#endif#ifdef CONFIG_PROC_FS if (proc_p80211) { wlandev->procdir = proc_mkdir(wlandev->name, proc_p80211); if ( wlandev->procdir ) wlandev->procwlandev = create_proc_read_entry("wlandev", 0, wlandev->procdir, p80211netdev_proc_read, wlandev); if (wlandev->nsd_proc_read) create_proc_read_entry("nsd", 0, wlandev->procdir, wlandev->nsd_proc_read, wlandev); }#endif#ifdef CONFIG_HOTPLUG p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_REGISTER);#endif DBFEXIT; return 0;}/*----------------------------------------------------------------* unregister_wlandev** Roughly matches the functionality of unregister_netdev. This* function is called to remove a named device from the system.** First we tell linux that the device should no longer exist.* Then we remove it from the list of known wlan devices.** Arguments:* wlandev ptr to the wlandev structure for the* interface.* Returns: * zero on success, non-zero otherwise.* Call Context:* Can be either interrupt or not.----------------------------------------------------------------*/int unregister_wlandev(wlandevice_t *wlandev){ struct sk_buff *skb; DBFENTER;#ifdef CONFIG_HOTPLUG p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_REMOVE);#endif#ifdef CONFIG_PROC_FS if ( wlandev->procwlandev ) { remove_proc_entry("wlandev", wlandev->procdir); } if ( wlandev->nsd_proc_read ) { remove_proc_entry("nsd", wlandev->procdir); } if (wlandev->procdir) { remove_proc_entry(wlandev->name, proc_p80211); }#endif unregister_netdev(wlandev->netdev); /* Now to clean out the rx queue */ while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) { dev_kfree_skb(skb); } DBFEXIT; return 0;}#ifdef CONFIG_PROC_FS/*----------------------------------------------------------------* proc_read** Read function for /proc/net/p80211/<device>/wlandev** Arguments:* buf* start * offset * count* eof* data* Returns: * zero on success, non-zero otherwise.* Call Context:* Can be either interrupt or not.----------------------------------------------------------------*/static intp80211netdev_proc_read( char *page, char **start, off_t offset, int count, int *eof, void *data){ char *p = page; wlandevice_t *wlandev = (wlandevice_t *) data; DBFENTER; if (offset != 0) { *eof = 1; goto exit; } p += sprintf(p, "p80211 version: %s (%s)\n\n", WLAN_RELEASE, WLAN_BUILD_DATE); p += sprintf(p, "name : %s\n", wlandev->name); p += sprintf(p, "nsd name : %s\n", wlandev->nsdname); p += sprintf(p, "address : %02x:%02x:%02x:%02x:%02x:%02x\n", wlandev->netdev->dev_addr[0], wlandev->netdev->dev_addr[1], wlandev->netdev->dev_addr[2], wlandev->netdev->dev_addr[3], wlandev->netdev->dev_addr[4], wlandev->netdev->dev_addr[5]); p += sprintf(p, "nsd caps : %s%s%s%s%s%s%s%s%s%s\n", (wlandev->nsdcaps & P80211_NSDCAP_HARDWAREWEP) ? "wep_hw " : "", (wlandev->nsdcaps & P80211_NSDCAP_TIEDWEP) ? "wep_tied " : "", (wlandev->nsdcaps & P80211_NSDCAP_NOHOSTWEP) ? "wep_hw_only " : "", (wlandev->nsdcaps & P80211_NSDCAP_PBCC) ? "pbcc " : "", (wlandev->nsdcaps & P80211_NSDCAP_SHORT_PREAMBLE) ? "short_preamble " : "", (wlandev->nsdcaps & P80211_NSDCAP_AGILITY) ? "agility " : "", (wlandev->nsdcaps & P80211_NSDCAP_AP_RETRANSMIT) ? "ap_retransmit " : "", (wlandev->nsdcaps & P80211_NSDCAP_HWFRAGMENT) ? "hw_frag " : "", (wlandev->nsdcaps & P80211_NSDCAP_AUTOJOIN) ? "autojoin " : "", (wlandev->nsdcaps & P80211_NSDCAP_NOSCAN) ? "" : "scan "); p += sprintf(p, "bssid : %02x:%02x:%02x:%02x:%02x:%02x\n", wlandev->bssid[0], wlandev->bssid[1], wlandev->bssid[2], wlandev->bssid[3], wlandev->bssid[4], wlandev->bssid[5]); p += sprintf(p, "Enabled : %s%s\n", (wlandev->shortpreamble) ? "short_preamble " : "", (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) ? "privacy" : ""); exit: DBFEXIT; return (p - page);}#endif/*----------------------------------------------------------------* p80211netdev_hwremoved** Hardware removed notification. This function should be called* immediately after an MSD has detected that the underlying hardware* has been yanked out from under us. The primary things we need* to do are:* - Mark the wlandev* - Prevent any further traffic from the knetdev i/f* - Prevent any further requests from mgmt i/f* - If there are any waitq'd mgmt requests or mgmt-frame exchanges,* shut them down.* - Call the MSD hwremoved function.** The remainder of the cleanup will be handled by unregister().* Our primary goal here is to prevent as much tickling of the MSD* as possible since the MSD is already in a 'wounded' state.** TODO: As new features are added, this function should be * updated.** Arguments:* wlandev WLAN network device structure* Returns: * nothing* Side effects:** Call context:* Usually interrupt.----------------------------------------------------------------*/void p80211netdev_hwremoved(wlandevice_t *wlandev){ DBFENTER; wlandev->hwremoved = 1; if ( wlandev->state == WLAN_DEVICE_OPEN) { p80211netdev_stop_queue(wlandev); } netif_device_detach(wlandev->netdev); DBFEXIT;}/*----------------------------------------------------------------* p80211_rx_typedrop** Classifies the frame, increments the appropriate counter, and* returns 0|1|2 indicating whether the driver should handle, ignore, or* drop the frame** Arguments:* wlandev wlan device structure* fc frame control field** Returns: * zero if the frame should be handled by the driver,* one if the frame should be ignored* anything else means we drop it.** Side effects:** Call context:* interrupt----------------------------------------------------------------*/int p80211_rx_typedrop( wlandevice_t *wlandev, UINT16 fc){ UINT16 ftype; UINT16 fstype; int drop = 0; /* Classify frame, increment counter */ ftype = WLAN_GET_FC_FTYPE(fc); fstype = WLAN_GET_FC_FSTYPE(fc);#if 0 WLAN_LOG_DEBUG(4, "rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype);#endif switch ( ftype ) { case WLAN_FTYPE_MGMT: if ((wlandev->netdev->flags & IFF_PROMISC) || (wlandev->netdev->flags & IFF_ALLMULTI)) { drop = 1; break; } WLAN_LOG_DEBUG(3, "rx'd mgmt:\n"); wlandev->rx.mgmt++; switch( fstype ) { case WLAN_FSTYPE_ASSOCREQ: /* printk("assocreq"); */ wlandev->rx.assocreq++; break; case WLAN_FSTYPE_ASSOCRESP: /* printk("assocresp"); */ wlandev->rx.assocresp++; break; case WLAN_FSTYPE_REASSOCREQ: /* printk("reassocreq"); */ wlandev->rx.reassocreq++; break; case WLAN_FSTYPE_REASSOCRESP: /* printk("reassocresp"); */ wlandev->rx.reassocresp++; break; case WLAN_FSTYPE_PROBEREQ: /* printk("probereq"); */ wlandev->rx.probereq++; break; case WLAN_FSTYPE_PROBERESP: /* printk("proberesp"); */ wlandev->rx.proberesp++; break; case WLAN_FSTYPE_BEACON: /* printk("beacon"); */ wlandev->rx.beacon++; break; case WLAN_FSTYPE_ATIM: /* printk("atim"); */ wlandev->rx.atim++; break; case WLAN_FSTYPE_DISASSOC: /* printk("disassoc"); */ wlandev->rx.disassoc++; break; case WLAN_FSTYPE_AUTHEN: /* printk("authen"); */ wlandev->rx.authen++; break; case WLAN_FSTYPE_DEAUTHEN: /* printk("deauthen"); */ wlandev->rx.deauthen++; break; default: /* printk("unknown"); */ wlandev->rx.mgmt_unknown++; break; } /* printk("\n"); */ drop = 2; break; case WLAN_FTYPE_CTL: if ((wlandev->netdev->flags & IFF_PROMISC) || (wlandev->netdev->flags & IFF_ALLMULTI)) { drop = 1; break; } WLAN_LOG_DEBUG(3, "rx'd ctl:\n"); wlandev->rx.ctl++; switch( fstype ) { case WLAN_FSTYPE_PSPOLL: /* printk("pspoll"); */ wlandev->rx.pspoll++; break; case WLAN_FSTYPE_RTS: /* printk("rts"); */ wlandev->rx.rts++; break; case WLAN_FSTYPE_CTS: /* printk("cts"); */ wlandev->rx.cts++; break; case WLAN_FSTYPE_ACK: /* printk("ack"); */ wlandev->rx.ack++; break; case WLAN_FSTYPE_CFEND: /* printk("cfend"); */ wlandev->rx.cfend++; break; case WLAN_FSTYPE_CFENDCFACK: /* printk("cfendcfack"); */ wlandev->rx.cfendcfack++; break; default: /* printk("unknown"); */ wlandev->rx.ctl_unknown++; break; } /* printk("\n"); */ drop = 2; break; case WLAN_FTYPE_DATA: wlandev->rx.data++; switch( fstype ) { case WLAN_FSTYPE_DATAONLY: wlandev->rx.dataonly++; break; case WLAN_FSTYPE_DATA_CFACK: wlandev->rx.data_cfack++; break; case WLAN_FSTYPE_DATA_CFPOLL: wlandev->rx.data_cfpoll++; break; case WLAN_FSTYPE_DATA_CFACK_CFPOLL: wlandev->rx.data__cfack_cfpoll++; break; case WLAN_FSTYPE_NULL: WLAN_LOG_DEBUG(3, "rx'd data:null\n"); wlandev->rx.null++; break; case WLAN_FSTYPE_CFACK: WLAN_LOG_DEBUG(3, "rx'd data:cfack\n"); wlandev->rx.cfack++; break; case WLAN_FSTYPE_CFPOLL: WLAN_LOG_DEBUG(3, "rx'd data:cfpoll\n"); wlandev->rx.cfpoll++; break; case WLAN_FSTYPE_CFACK_CFPOLL: WLAN_LOG_DEBUG(3, "rx'd data:cfack_cfpoll\n"); wlandev->rx.cfack_cfpoll++; break; default: /* printk("unknown"); */ wlandev->rx.data_unknown++; break; } break; } return drop;}#ifdef CONFIG_HOTPLUG/* Notify userspace when a netdevice event occurs, * by running '/sbin/hotplug net' with certain * environment variables set. */int p80211_run_sbin_hotplug(wlandevice_t *wlandev, char *action){ char *argv[3], *envp[7], ifname[12 + IFNAMSIZ], action_str[32]; char nsdname[32], wlan_wext[32]; int i; if (wlandev) { sprintf(ifname, "INTERFACE=%s", wlandev->name); sprintf(nsdname, "NSDNAME=%s", wlandev->nsdname); } else { sprintf(ifname, "INTERFACE=null"); sprintf(nsdname, "NSDNAME=null"); } sprintf(wlan_wext, "WLAN_WEXT=%s", wlan_wext_write ? "y" : ""); sprintf(action_str, "ACTION=%s", action); i = 0; argv[i++] = hotplug_path; argv[i++] = "wlan"; argv[i] = NULL; i = 0; /* minimal command environment */ envp [i++] = "HOME=/"; envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp [i++] = ifname; envp [i++] = action_str; envp [i++] = nsdname; envp [i++] = wlan_wext; envp [i] = NULL; #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,62)) return call_usermodehelper(argv [0], argv, envp);#else return call_usermodehelper(argv [0], argv, envp, 0);#endif}#endifvoid p80211_suspend(wlandevice_t *wlandev){ DBFENTER; #ifdef CONFIG_HOTPLUG p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_SUSPEND);#endif DBFEXIT;} void p80211_resume(wlandevice_t *wlandev){ DBFENTER;#ifdef CONFIG_HOTPLUG p80211_run_sbin_hotplug(wlandev, WLAN_HOTPLUG_RESUME);#endif DBFEXIT;}void p80211knetdev_tx_timeout( netdevice_t *netdev) { wlandevice_t *wlandev = (wlandevice_t*)netdev->priv; DBFENTER; if (wlandev->tx_timeout) { wlandev->tx_timeout(wlandev); } else { WLAN_LOG_WARNING("Implement tx_timeout for %s\n", wlandev->nsdname); p80211netdev_wake_queue(wlandev); } DBFEXIT;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -