📄 p80211netdev.c
字号:
/* src/p80211/p80211knetdev.c** Linux Kernel net device interface** Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.* --------------------------------------------------------------------** linux-wlan** The contents of this file are subject to the Mozilla Public* License Version 1.1 (the "License"); you may not use this file* except in compliance with the License. You may obtain a copy of* the License at http://www.mozilla.org/MPL/** Software distributed under the License is distributed on an "AS* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or* implied. See the License for the specific language governing* rights and limitations under the License.** Alternatively, the contents of this file may be used under the* terms of the GNU Public License version 2 (the "GPL"), in which* case the provisions of the GPL are applicable instead of the* above. If you wish to allow the use of your version of this file* only under the terms of the GPL and not to allow others to use* your version of this file under the MPL, indicate your decision* by deleting the provisions above and replace them with the notice* and other provisions required by the GPL. If you do not delete* the provisions above, a recipient may use your version of this* file under either the MPL or the GPL.** --------------------------------------------------------------------** Inquiries regarding the linux-wlan Open Source project can be* made directly to:** AbsoluteValue Systems Inc.* info@linux-wlan.com* http://www.linux-wlan.com** --------------------------------------------------------------------** Portions of the development of this software were funded by * Intersil Corporation as part of PRISM(R) chipset product development.** --------------------------------------------------------------------** The functions required for a Linux network device are defined here.** --------------------------------------------------------------------*//*================================================================*//* System Includes */#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/skbuff.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/interrupt.h>#include <linux/netdevice.h>#include <linux/kmod.h>#include <linux/if_arp.h>#include <linux/wireless.h>#include <linux/sockios.h>#include <linux/etherdevice.h>#include <asm/bitops.h>#include <asm/uaccess.h>#include <asm/byteorder.h>#ifdef SIOCETHTOOL#include <linux/ethtool.h>#endif#if WIRELESS_EXT > 12#include <net/iw_handler.h>#endif/*================================================================*//* Project Includes */#include <wlan/version.h>#include <wlan/wlan_compat.h>#include <wlan/p80211types.h>#include <wlan/p80211hdr.h>#include <wlan/p80211conv.h>#include <wlan/p80211mgmt.h>#include <wlan/p80211msg.h>#include <wlan/p80211netdev.h>#include <wlan/p80211ioctl.h>#include <wlan/p80211req.h>#include <wlan/p80211metastruct.h>#include <wlan/p80211metadef.h>/*================================================================*//* Local Constants *//*================================================================*//* Local Macros *//*================================================================*//* Local Types *//*================================================================*//* Local Static Definitions */#define __NO_VERSION__ /* prevent the static definition */#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry *proc_p80211;#endif/*================================================================*//* Local Function Declarations *//* Support functions */static void p80211netdev_rx_bh(unsigned long arg);/* netdevice method functions */static int p80211knetdev_init( netdevice_t *netdev);static struct net_device_stats* p80211knetdev_get_stats(netdevice_t *netdev);static int p80211knetdev_open( netdevice_t *netdev);static int p80211knetdev_stop( netdevice_t *netdev );static int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev);static void p80211knetdev_set_multicast_list(netdevice_t *dev);static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd);static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr);static void p80211knetdev_tx_timeout(netdevice_t *netdev);static int p80211_rx_typedrop( wlandevice_t *wlandev, UINT16 fc);#ifdef CONFIG_PROC_FSstatic intp80211netdev_proc_read( char *page, char **start, off_t offset, int count, int *eof, void *data);#endif/*================================================================*//* Function Definitions *//*----------------------------------------------------------------* p80211knetdev_startup** Initialize the wlandevice/netdevice part of 802.11 services at * load time.** Arguments:* none** Returns: * nothing----------------------------------------------------------------*/void p80211netdev_startup(void){ DBFENTER;#ifdef CONFIG_PROC_FS if (proc_net != NULL) { proc_p80211 = create_proc_entry( "p80211", (S_IFDIR|S_IRUGO|S_IXUGO), proc_net); }#endif DBFEXIT; return;}/*----------------------------------------------------------------* p80211knetdev_shutdown** Shutdown the wlandevice/netdevice part of 802.11 services at * unload time.** Arguments:* none** Returns: * nothing----------------------------------------------------------------*/voidp80211netdev_shutdown(void){ DBFENTER;#ifdef CONFIG_PROC_FS if (proc_p80211 != NULL) { remove_proc_entry("p80211", proc_net); }#endif DBFEXIT;}/*----------------------------------------------------------------* p80211knetdev_init** Init method for a Linux netdevice. Called in response to* register_netdev.** Arguments:* none** Returns: * nothing----------------------------------------------------------------*/int p80211knetdev_init( netdevice_t *netdev){ DBFENTER; /* Called in response to register_netdev */ /* This is usually the probe function, but the probe has */ /* already been done by the MSD and the create_kdev */ /* function. All we do here is return success */ DBFEXIT; return 0;}/*----------------------------------------------------------------* p80211knetdev_get_stats** Statistics retrieval for linux netdevices. Here we're reporting* the Linux i/f level statistics. Hence, for the primary numbers,* we don't want to report the numbers from the MIB. Eventually,* it might be useful to collect some of the error counters though.** Arguments:* netdev Linux netdevice** Returns: * the address of the statistics structure----------------------------------------------------------------*/struct net_device_stats*p80211knetdev_get_stats(netdevice_t *netdev){ wlandevice_t *wlandev = (wlandevice_t*)netdev->priv; DBFENTER; /* TODO: review the MIB stats for items that correspond to linux stats */ DBFEXIT; return &(wlandev->linux_stats);}/*----------------------------------------------------------------* p80211knetdev_open** Linux netdevice open method. Following a successful call here,* the device is supposed to be ready for tx and rx. In our* situation that may not be entirely true due to the state of the* MAC below.** Arguments:* netdev Linux network device structure** Returns: * zero on success, non-zero otherwise----------------------------------------------------------------*/int p80211knetdev_open( netdevice_t *netdev ){ int result = 0; /* success */ wlandevice_t *wlandev = (wlandevice_t*)(netdev->priv); DBFENTER; /* Check to make sure the MSD is running */ if ( wlandev->msdstate != WLAN_MSD_RUNNING ) { return -ENODEV; } /* Tell the MSD to open */ if ( wlandev->open != NULL) { result = wlandev->open(wlandev); if ( result == 0 ) {#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) ) netdev->interrupt = 0;#endif p80211netdev_start_queue(wlandev); wlandev->state = WLAN_DEVICE_OPEN; } } else { result = -EAGAIN; } DBFEXIT; return result;}/*----------------------------------------------------------------* p80211knetdev_stop** Linux netdevice stop (close) method. Following this call,* no frames should go up or down through this interface.** Arguments:* netdev Linux network device structure** Returns: * zero on success, non-zero otherwise----------------------------------------------------------------*/int p80211knetdev_stop( netdevice_t *netdev ){ int result = 0; wlandevice_t *wlandev = (wlandevice_t*)(netdev->priv); DBFENTER; if ( wlandev->close != NULL ) { result = wlandev->close(wlandev); } p80211netdev_stop_queue(wlandev); wlandev->state = WLAN_DEVICE_CLOSED; DBFEXIT; return result;}/*----------------------------------------------------------------* p80211netdev_rx** Frame receive function called by the mac specific driver.** Arguments:* wlandev WLAN network device structure* skb skbuff containing a full 802.11 frame.* Returns: * nothing* Side effects:* ----------------------------------------------------------------*/void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb ) { DBFENTER; /* Enqueue for post-irq processing */ skb_queue_tail(&wlandev->nsd_rxq, skb); tasklet_schedule(&wlandev->rx_bh); DBFEXIT; return;}/*----------------------------------------------------------------* p80211netdev_rx_bh** Deferred processing of all received frames.** Arguments:* wlandev WLAN network device structure* skb skbuff containing a full 802.11 frame.* Returns: * nothing* Side effects:* ----------------------------------------------------------------*/void p80211netdev_rx_bh(unsigned long arg){ wlandevice_t *wlandev = (wlandevice_t *) arg; struct sk_buff *skb = NULL; netdevice_t *dev = wlandev->netdev; p80211_hdr_a3_t *hdr; UINT16 fc; DBFENTER; /* Let's empty our our queue */ while ( (skb = skb_dequeue(&wlandev->nsd_rxq)) ) { if (wlandev->state == WLAN_DEVICE_OPEN) { if (dev->type != ARPHRD_ETHER) { /* RAW frame; we shouldn't convert it */ // XXX Append the Prism Header here instead. /* set up various data fields */ skb->dev = dev; skb->mac.raw = skb->data ; skb->ip_summed = CHECKSUM_NONE; skb->pkt_type = PACKET_OTHERHOST; skb->protocol = htons(ETH_P_80211_RAW); dev->last_rx = jiffies; wlandev->linux_stats.rx_packets++; wlandev->linux_stats.rx_bytes += skb->len; netif_rx_ni(skb); continue; } else { hdr = (p80211_hdr_a3_t *)skb->data; fc = ieee2host16(hdr->fc); if (p80211_rx_typedrop(wlandev, fc)) { dev_kfree_skb(skb); continue; } /* perform mcast filtering */ if (wlandev->netdev->flags & IFF_ALLMULTI) { /* allow my local address through */ if (memcmp(hdr->a1, wlandev->netdev->dev_addr, WLAN_ADDR_LEN) != 0) { /* but reject anything else that isn't multicast */ if (!(hdr->a1[0] & 0x01)) { dev_kfree_skb(skb); continue; } } } if ( skb_p80211_to_ether(wlandev, wlandev->ethconv, skb) == 0 ) { skb->dev->last_rx = jiffies; wlandev->linux_stats.rx_packets++; wlandev->linux_stats.rx_bytes += skb->len; netif_rx_ni(skb); continue; } WLAN_LOG_DEBUG(1, "p80211_to_ether failed.\n"); } } dev_kfree_skb(skb); } DBFEXIT;}/*----------------------------------------------------------------* p80211knetdev_hard_start_xmit** Linux netdevice method for transmitting a frame.** Arguments:* skb Linux sk_buff containing the frame.* netdev Linux netdevice.** Side effects:* If the lower layers report that buffers are full. netdev->tbusy* will be set to prevent higher layers from sending more traffic.** Note: If this function returns non-zero, higher layers retain* ownership of the skb.** Returns: * zero on success, non-zero on failure.----------------------------------------------------------------*/int p80211knetdev_hard_start_xmit( struct sk_buff *skb, netdevice_t *netdev){ int result = 0; int txresult = -1; wlandevice_t *wlandev = (wlandevice_t*)netdev->priv; p80211_hdr_t p80211_hdr; p80211_metawep_t p80211_wep; DBFENTER; if (skb == NULL) { return 0; } if (wlandev->state != WLAN_DEVICE_OPEN) { result = 1; goto failed; } memset(&p80211_hdr, 0, sizeof(p80211_hdr_t)); memset(&p80211_wep, 0, sizeof(p80211_metawep_t));#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,38) ) if ( test_and_set_bit(0, (void*)&(netdev->tbusy)) != 0 ) { /* We've been called w/ tbusy set, has the tx */ /* path stalled? */ WLAN_LOG_DEBUG(1, "called when tbusy set\n"); result = 1; goto failed; } #else if ( netif_queue_stopped(netdev) ) { WLAN_LOG_DEBUG(1, "called when queue stopped.\n"); result = 1; goto failed; } netif_stop_queue(netdev); /* No timeout handling here, 2.3.38+ kernels call the * timeout function directly. * TODO: Add timeout handling. */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -