📄 ieee80211_linux.c
字号:
if (pv->rbuf) vfree(pv->rbuf); if (pv->wbuf) vfree(pv->wbuf); kfree(pv); return 0;}static struct file_operations proc_ieee80211_ops = { .read = proc_ieee80211_read, .write = proc_ieee80211_write, .open = proc_ieee80211_open, .release = proc_ieee80211_close,};#ifdef IEEE80211_DEBUGstatic intIEEE80211_SYSCTL_DECL(ieee80211_sysctl_debug, ctl, write, filp, buffer, lenp, ppos){ struct ieee80211vap *vap = ctl->extra1; u_int val; int ret; ctl->data = &val; ctl->maxlen = sizeof(val); if (write) { ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos); if (ret == 0) vap->iv_debug = val; } else { val = vap->iv_debug; ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos); } return ret;}#endif /* IEEE80211_DEBUG */static intIEEE80211_SYSCTL_DECL(ieee80211_sysctl_dev_type, ctl, write, filp, buffer, lenp, ppos){ struct ieee80211vap *vap = ctl->extra1; u_int val; int ret; ctl->data = &val; ctl->maxlen = sizeof(val); if (write) { ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos); if (ret == 0 && vap->iv_opmode == IEEE80211_M_MONITOR) { if (val == ARPHRD_IEEE80211_RADIOTAP || val == ARPHRD_IEEE80211 || val == ARPHRD_IEEE80211_PRISM || val == ARPHRD_IEEE80211_ATHDESC) { vap->iv_dev->type = val; } } } else { val = vap->iv_dev->type; ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos); } return ret;}static intIEEE80211_SYSCTL_DECL(ieee80211_sysctl_monitor_nods_only, ctl, write, filp, buffer, lenp, ppos){ struct ieee80211vap *vap = ctl->extra1; u_int val; int ret; ctl->data = &val; ctl->maxlen = sizeof(val); if (write) { ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos); if (ret == 0) vap->iv_monitor_nods_only = val; } else { val = vap->iv_monitor_nods_only; ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos); } return ret;}static intIEEE80211_SYSCTL_DECL(ieee80211_sysctl_monitor_txf_len, ctl, write, filp, buffer, lenp, ppos){ struct ieee80211vap *vap = ctl->extra1; u_int val; int ret; ctl->data = &val; ctl->maxlen = sizeof(val); if (write) { ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos); if (ret == 0) vap->iv_monitor_txf_len = val; } else { val = vap->iv_monitor_txf_len; ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos); } return ret;}#define CTL_AUTO -2 /* cannot be CTL_ANY or CTL_NONE */static const ctl_table ieee80211_sysctl_template[] = {#ifdef IEEE80211_DEBUG { .ctl_name = CTL_AUTO, .procname = "debug", .mode = 0644, .proc_handler = ieee80211_sysctl_debug },#endif { .ctl_name = CTL_AUTO, .procname = "dev_type", .mode = 0644, .proc_handler = ieee80211_sysctl_dev_type }, { .ctl_name = CTL_AUTO, .procname = "monitor_nods_only", .mode = 0644, .proc_handler = ieee80211_sysctl_monitor_nods_only }, { .ctl_name = CTL_AUTO, .procname = "monitor_txf_len", .mode = 0644, .proc_handler = ieee80211_sysctl_monitor_txf_len }, /* NB: must be last entry before NULL */ { .ctl_name = CTL_AUTO, .procname = "%parent", .maxlen = IFNAMSIZ, .mode = 0444, .proc_handler = proc_dostring }, { 0 }};voidieee80211_sysctl_vattach(struct ieee80211vap *vap){ int i, space; char *devname = NULL; struct ieee80211_proc_entry *tmp=NULL; space = 5 * sizeof(struct ctl_table) + sizeof(ieee80211_sysctl_template); vap->iv_sysctls = kmalloc(space, GFP_KERNEL); if (vap->iv_sysctls == NULL) { printk("%s: no memory for sysctl table!\n", __func__); return; } /* * Reserve space for the device name outside the net_device structure * so that if the name changes we know what it used to be. */ devname = kmalloc((strlen(vap->iv_dev->name) + 1) * sizeof(char), GFP_KERNEL); if (devname == NULL) { printk("%s: no memory for VAP name!\n", __func__); return; } strncpy(devname, vap->iv_dev->name, strlen(vap->iv_dev->name) + 1); /* setup the table */ memset(vap->iv_sysctls, 0, space); vap->iv_sysctls[0].ctl_name = CTL_NET; vap->iv_sysctls[0].procname = "net"; vap->iv_sysctls[0].mode = 0555; vap->iv_sysctls[0].child = &vap->iv_sysctls[2]; /* [1] is NULL terminator */ vap->iv_sysctls[2].ctl_name = CTL_AUTO; vap->iv_sysctls[2].procname = devname; /* XXX bad idea? */ vap->iv_sysctls[2].mode = 0555; vap->iv_sysctls[2].child = &vap->iv_sysctls[4]; /* [3] is NULL terminator */ /* copy in pre-defined data */ memcpy(&vap->iv_sysctls[4], ieee80211_sysctl_template, sizeof(ieee80211_sysctl_template)); /* add in dynamic data references */ for (i = 4; vap->iv_sysctls[i].ctl_name; i++) if (vap->iv_sysctls[i].extra1 == NULL) vap->iv_sysctls[i].extra1 = vap; /* tack on back-pointer to parent device */ vap->iv_sysctls[i-1].data = vap->iv_ic->ic_dev->name; /* XXX? */ /* and register everything */ vap->iv_sysctl_header = register_sysctl_table(vap->iv_sysctls, 1); if (!vap->iv_sysctl_header) { printk("%s: failed to register sysctls!\n", vap->iv_dev->name); kfree(vap->iv_sysctls); vap->iv_sysctls = NULL; } /* Ensure the base madwifi directory exists */ if (!proc_madwifi && proc_net != NULL) { proc_madwifi = proc_mkdir("madwifi", proc_net); if (!proc_madwifi) printk(KERN_WARNING "Failed to mkdir /proc/net/madwifi\n"); } /* Create a proc directory named after the VAP */ if (proc_madwifi) { proc_madwifi_count++; vap->iv_proc = proc_mkdir(vap->iv_dev->name, proc_madwifi); } /* Create a proc entry listing the associated stations */ ieee80211_proc_vcreate(vap, &proc_ieee80211_ops, "associated_sta"); /* Recreate any other proc entries that have been registered */ if (vap->iv_proc) { tmp = vap->iv_proc_entries; while (tmp) { if (!tmp->entry) { tmp->entry = create_proc_entry(tmp->name, PROC_IEEE80211_PERM, vap->iv_proc); tmp->entry->data = vap; tmp->entry->proc_fops = tmp->fileops; } tmp = tmp->next; } }}/* Frees all memory used for the list of proc entries */void ieee80211_proc_cleanup(struct ieee80211vap *vap){ struct ieee80211_proc_entry *tmp=vap->iv_proc_entries; struct ieee80211_proc_entry *next = NULL; while (tmp) { next = tmp->next; kfree(tmp); tmp = next; }}/* Called by other modules to register a proc entry under the vap directory */int ieee80211_proc_vcreate(struct ieee80211vap *vap, struct file_operations *fileops, char *name){ struct ieee80211_proc_entry *entry; struct ieee80211_proc_entry *tmp=NULL; /* Ignore if already in the list */ if (vap->iv_proc_entries) { tmp = vap->iv_proc_entries; do { if (strcmp(tmp->name, name)==0) return -1; /* Check for end of list */ if (!tmp->next) break; /* Otherwise move on */ tmp = tmp->next; } while (1); } /* Create an item in our list for the new entry */ entry = kmalloc(sizeof(struct ieee80211_proc_entry), GFP_KERNEL); if (entry == NULL) { printk("%s: no memory for new proc entry (%s)!\n", __func__, name); return -1; } /* Replace null fileops pointers with our standard functions */ if (!fileops->open) fileops->open = proc_ieee80211_open; if (!fileops->release) fileops->release = proc_ieee80211_close; if (!fileops->read) fileops->read = proc_ieee80211_read; if (!fileops->write) fileops->write = proc_ieee80211_write; /* Create the entry record */ entry->name = name; entry->fileops = fileops; entry->next = NULL; entry->entry = NULL; /* Create the actual proc entry */ if (vap->iv_proc) { entry->entry = create_proc_entry(entry->name, PROC_IEEE80211_PERM, vap->iv_proc); entry->entry->data = vap; entry->entry->proc_fops = entry->fileops; } /* Add it to the list */ if (!tmp) { /* Add to the start */ vap->iv_proc_entries = entry; } else { /* Add to the end */ tmp->next = entry; } return 0;}EXPORT_SYMBOL(ieee80211_proc_vcreate);voidieee80211_sysctl_vdetach(struct ieee80211vap *vap){ struct ieee80211_proc_entry *tmp=NULL; if (vap->iv_sysctl_header) { unregister_sysctl_table(vap->iv_sysctl_header); vap->iv_sysctl_header = NULL; } if (vap->iv_proc) { /* Remove child proc entries but leave them in the list */ tmp = vap->iv_proc_entries; while (tmp) { if (tmp->entry) { remove_proc_entry(tmp->name, vap->iv_proc); tmp->entry = NULL; } tmp = tmp->next; } remove_proc_entry(vap->iv_proc->name, proc_madwifi); if (proc_madwifi_count == 1) { remove_proc_entry("madwifi", proc_net); proc_madwifi = NULL; } proc_madwifi_count--; } if (vap->iv_sysctls[2].procname) { kfree(vap->iv_sysctls[2].procname); vap->iv_sysctls[2].procname = NULL; } if (vap->iv_sysctls) { kfree(vap->iv_sysctls); vap->iv_sysctls = NULL; }}#endif /* CONFIG_SYSCTL *//* * Format an Ethernet MAC for printing. */const char*ether_sprintf(const u_int8_t *mac){ static char etherbuf[18]; /* XXX */ snprintf(etherbuf, sizeof(etherbuf), "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return etherbuf;}EXPORT_SYMBOL(ether_sprintf); /* XXX *//* Function to handle the device event notifications. * If the event is a NETDEV_CHANGENAME, and is for an interface * we are taking care of, then we want to remove its existing * proc entries (which now have the wrong names) and add * new, correct, entries. */static intieee80211_rcv_dev_event(struct notifier_block *this, unsigned long event, void *ptr){#ifdef CONFIG_SYSCTL struct net_device *dev = (struct net_device *) ptr; if (!dev || dev->open != &ieee80211_open) return 0; switch (event) { case NETDEV_CHANGENAME: ieee80211_sysctl_vdetach(dev->priv); ieee80211_sysctl_vattach(dev->priv); return NOTIFY_DONE; default: break; }#endif /* CONFIG_SYSCTL */ return 0;}static struct notifier_block ieee80211_event_block = { .notifier_call = ieee80211_rcv_dev_event};/* * Module glue. */#include "version.h"#include "release.h"static char *version = WLAN_VERSION " (" RELEASE_VERSION ")";static char *dev_info = "wlan";MODULE_AUTHOR("Errno Consulting, Sam Leffler");MODULE_DESCRIPTION("802.11 wireless LAN protocol support");#ifdef MODULE_VERSIONMODULE_VERSION(RELEASE_VERSION);#endif#ifdef MODULE_LICENSEMODULE_LICENSE("Dual BSD/GPL");#endifextern void ieee80211_auth_setup(void);static int __initinit_wlan(void){ register_netdevice_notifier(&ieee80211_event_block); printk(KERN_INFO "%s: %s\n", dev_info, version); return 0;}module_init(init_wlan);static void __exitexit_wlan(void){ unregister_netdevice_notifier(&ieee80211_event_block); printk(KERN_INFO "%s: driver unloaded\n", dev_info);}module_exit(exit_wlan);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -