New upstream snapshot.
[debian/madwifi.git] / net80211 / ieee80211_linux.c
1 /*-
2  * Copyright (c) 2003-2005 Sam Leffler, Errno Consulting
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * $Id: ieee80211_linux.c 4162 2011-08-03 06:25:42Z proski $
28  */
29 #ifndef EXPORT_SYMTAB
30 #define EXPORT_SYMTAB
31 #endif
32
33 /*
34  * IEEE 802.11 support (Linux-specific code)
35  */
36 #if !defined(AUTOCONF_INCLUDED) && !defined(CONFIG_LOCALVERSION)
37 #include <linux/config.h>
38 #endif
39 #include <linux/version.h>
40 #include <linux/module.h>
41 #include <linux/kmod.h>
42 #include <linux/init.h>
43 #include <linux/skbuff.h>
44 #include <linux/sysctl.h>
45 #include <linux/netdevice.h>
46 #include <linux/etherdevice.h>
47 #include <linux/if_vlan.h>
48 #include <linux/vmalloc.h>
49 #include <linux/proc_fs.h>
50
51 #include <net/iw_handler.h>
52 #include <linux/wireless.h>
53 #include <linux/if_arp.h>               /* XXX for ARPHRD_* */
54
55 #include <asm/uaccess.h>
56
57 #include "if_media.h"
58 #include "if_ethersubr.h"
59
60 #include <net80211/ieee80211_var.h>
61 #include <net80211/ieee80211_monitor.h>
62
63 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
64 #define proc_net init_net.proc_net
65 #endif
66
67 /*
68  * Print a console message with the device name prepended.
69  */
70 void
71 if_printf(struct net_device *dev, const char *fmt, ...)
72 {
73         va_list ap;
74         char buf[512];          /* XXX */
75
76         va_start(ap, fmt);
77         vsnprintf(buf, sizeof(buf), fmt, ap);
78         va_end(ap);
79
80         printk("%s: %s", dev->name, buf);
81 }
82
83 /*
84  * Allocate and setup a management frame of the specified
85  * size.  We return the sk_buff and a pointer to the start
86  * of the contiguous data area that's been reserved based
87  * on the packet length.  The data area is forced to 32-bit
88  * alignment and the buffer length to a multiple of 4 bytes.
89  * This is done mainly so beacon frames (that require this)
90  * can use this interface too.
91  */
92 struct sk_buff *
93 ieee80211_getmgtframe(u_int8_t **frm, u_int pktlen)
94 {
95         const u_int align = sizeof(u_int32_t);
96         struct ieee80211_cb *cb;
97         struct sk_buff *skb;
98         u_int len;
99
100         len = roundup(sizeof(struct ieee80211_frame) + pktlen, 4);
101         skb = dev_alloc_skb(len + align-1);
102         if (skb != NULL) {
103                 u_int off = ((unsigned long) skb->data) % align;
104                 if (off != 0)
105                         skb_reserve(skb, align - off);
106
107                 cb = (struct ieee80211_cb *)skb->cb;
108                 cb->ni = NULL;
109                 cb->flags = 0;
110                 cb->next = NULL;
111
112                 skb_reserve(skb, sizeof(struct ieee80211_frame));
113                 *frm = skb_put(skb, pktlen);
114         }
115         return skb;
116 }
117
118 #if 0
119 /*
120  * Drain a queue of sk_buff's.
121  */
122 void
123 __skb_queue_drain(struct sk_buff_head *q)
124 {
125         struct sk_buff *skb;
126
127         while ((skb = __skb_dequeue(q)) != NULL)
128                 dev_kfree_skb(skb);
129 }
130 #endif
131
132 #if IEEE80211_VLAN_TAG_USED
133 /*
134  * VLAN support.
135  */
136
137 /*
138  * Register a vlan group.
139  */
140 void
141 ieee80211_vlan_register(struct net_device *dev, struct vlan_group *grp)
142 {
143         struct ieee80211vap *vap = netdev_priv(dev);
144
145         vap->iv_vlgrp = grp;
146 }
147
148 /*
149  * Add an rx vlan identifier
150  */
151 void
152 ieee80211_vlan_add_vid(struct net_device *dev, unsigned short vid)
153 {
154         struct ieee80211vap *vap = netdev_priv(dev);
155
156         if (vap->iv_vlgrp != NULL)
157                 vap->iv_bss->ni_vlan = vid;
158 }
159
160 /*
161  * Kill (i.e. delete) a vlan identifier.
162  */
163 void
164 ieee80211_vlan_kill_vid(struct net_device *dev, unsigned short vid)
165 {
166         struct ieee80211vap *vap = netdev_priv(dev);
167
168         if (vap->iv_vlgrp != NULL)
169                 vlan_group_set_device(vap->iv_vlgrp, vid, NULL);
170 }
171 #endif /* IEEE80211_VLAN_TAG_USED */
172
173 void
174 ieee80211_vlan_vattach(struct ieee80211vap *vap)
175 {
176 #if IEEE80211_VLAN_TAG_USED
177         struct net_device *dev = vap->iv_dev;
178
179         dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
180                          NETIF_F_HW_VLAN_FILTER;
181 #endif /* IEEE80211_VLAN_TAG_USED */
182 }
183
184 void
185 ieee80211_vlan_vdetach(struct ieee80211vap *vap)
186 {
187 }
188
189 void
190 ieee80211_notify_node_join(struct ieee80211_node *ni, int newassoc)
191 {
192         struct ieee80211vap *vap = ni->ni_vap;
193         struct net_device *dev = vap->iv_dev;
194         union iwreq_data wreq;
195
196         if (ni == vap->iv_bss) { 
197                 if (newassoc) 
198                         netif_carrier_on(dev);
199                 memset(&wreq, 0, sizeof(wreq));
200                 IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_bssid);
201                 wreq.addr.sa_family = ARPHRD_ETHER;
202 #ifdef ATH_SUPERG_XR
203                 if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
204                         dev = vap->iv_xrvap->iv_dev;
205 #endif
206                 wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
207         } else {
208                 memset(&wreq, 0, sizeof(wreq));
209                 IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
210                 wreq.addr.sa_family = ARPHRD_ETHER;
211 #ifdef ATH_SUPERG_XR
212                 if (vap->iv_xrvap && vap->iv_flags & IEEE80211_F_XR)
213                         dev = vap->iv_xrvap->iv_dev;
214 #endif
215                 wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
216         }
217 }
218
219 void
220 ieee80211_notify_node_leave(struct ieee80211_node *ni)
221 {
222         struct ieee80211vap *vap = ni->ni_vap;
223         struct net_device *dev = vap->iv_dev;
224         union iwreq_data wreq;
225
226         if (ni == vap->iv_bss) {
227                 netif_carrier_off(dev);
228                 memset(wreq.ap_addr.sa_data, 0, ETHER_ADDR_LEN);
229                 wreq.ap_addr.sa_family = ARPHRD_ETHER;
230                 wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
231         } else {
232                 /* fire off wireless event station leaving */
233                 memset(&wreq, 0, sizeof(wreq));
234                 IEEE80211_ADDR_COPY(wreq.addr.sa_data, ni->ni_macaddr);
235                 wreq.addr.sa_family = ARPHRD_ETHER;
236                 wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL);
237         }
238 }
239
240 void
241 ieee80211_notify_sta_stats(struct ieee80211_node *ni)
242 {
243         struct ieee80211vap *vap = ni->ni_vap;
244         static const char *tag = "STA-TRAFFIC-STAT";
245         struct net_device *dev = vap->iv_dev;
246         union iwreq_data wreq;
247         char buf[256];
248
249         snprintf(buf, sizeof(buf), "%s\nmac=%s\nrx_packets=%u\nrx_bytes=%llu\n"
250                         "tx_packets=%u\ntx_bytes=%llu\n", tag, 
251                         ether_sprintf(ni->ni_macaddr), ni->ni_stats.ns_rx_data, 
252                         (unsigned long long)ni->ni_stats.ns_rx_bytes,
253                         ni->ni_stats.ns_tx_data,
254                         (unsigned long long)ni->ni_stats.ns_tx_bytes);
255         memset(&wreq, 0, sizeof(wreq));
256         wreq.data.length = strlen(buf);
257         wireless_send_event(dev, IWEVCUSTOM, &wreq, buf);
258 }
259
260 void
261 ieee80211_notify_scan_done(struct ieee80211vap *vap)
262 {
263         struct net_device *dev = vap->iv_dev;
264         union iwreq_data wreq;
265
266         IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s\n", "notify scan done");
267
268         /* dispatch wireless event indicating scan completed */
269         wreq.data.length = 0;
270         wreq.data.flags = 0;
271         wireless_send_event(dev, SIOCGIWSCAN, &wreq, NULL);
272 }
273
274 void
275 ieee80211_notify_replay_failure(struct ieee80211vap *vap,
276         const struct ieee80211_frame *wh, const struct ieee80211_key *k,
277         u_int64_t rsc)
278 {
279         static const char *tag = "MLME-REPLAYFAILURE.indication";
280         struct net_device *dev = vap->iv_dev;
281         union iwreq_data wrqu;
282         char buf[128];          /* XXX */
283
284         IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
285                 "%s replay detected <keyix %d, rsc %llu >",
286                 k->wk_cipher->ic_name, k->wk_keyix, rsc );
287
288         /* TODO: needed parameters: count, keyid, key type, src address, TSC */
289         snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag,
290                 k->wk_keyix,
291                 IEEE80211_IS_MULTICAST(wh->i_addr1) ?  "broad" : "uni",
292                 ether_sprintf(wh->i_addr1));
293         memset(&wrqu, 0, sizeof(wrqu));
294         wrqu.data.length = strlen(buf);
295         wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
296 }
297 EXPORT_SYMBOL(ieee80211_notify_replay_failure);
298
299 void
300 ieee80211_notify_michael_failure(struct ieee80211vap *vap,
301         const struct ieee80211_frame *wh, u_int keyix)
302 {
303         static const char *tag = "MLME-MICHAELMICFAILURE.indication";
304         struct net_device *dev = vap->iv_dev;
305         union iwreq_data wrqu;
306         char buf[128];          /* XXX */
307
308         IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
309                 "Michael MIC verification failed <keyix %d>", keyix);
310         vap->iv_stats.is_rx_tkipmic++;
311
312         /* TODO: needed parameters: count, keyid, key type, src address, TSC */
313         snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag,
314                 keyix, IEEE80211_IS_MULTICAST(wh->i_addr1) ?  "broad" : "uni",
315                 ether_sprintf(wh->i_addr1));
316         memset(&wrqu, 0, sizeof(wrqu));
317         wrqu.data.length = strlen(buf);
318         wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
319 }
320 EXPORT_SYMBOL(ieee80211_notify_michael_failure);
321
322 /*
323  * Note that a successful call to this function does not guarantee that
324  * the services provided by the requested module are available:
325  *
326  * "Note that a successful module load does not mean the module did not
327  * then unload and exit on an error of its own. Callers must check that
328  * the service they requested is now available not blindly invoke it."
329  * http://kernelnewbies.org/documents/kdoc/kernel-api/r7338.html
330  */
331 int
332 ieee80211_load_module(const char *modname)
333 {
334 #if defined(CONFIG_KMOD) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
335         int rv;
336         rv = request_module("%s", modname);
337         if (rv < 0)
338                 printk(KERN_ERR "failed to automatically load module: %s; " \
339                         "errno: %d\n", modname, rv);
340         return rv;
341 #else /* CONFIG_KMOD || 2.6.27+ */
342         printk(KERN_ERR "Unable to load needed module: %s; no support for " \
343                         "automatic module loading", modname );
344         return -ENOSYS;
345 #endif /* CONFIG_KMOD || 2.6.27+ */
346 }
347
348
349 #ifdef CONFIG_PROC_FS
350 static struct proc_dir_entry *proc_madwifi;
351 static int proc_madwifi_count = 0;
352
353 static int
354 proc_read_nodes(struct ieee80211vap *vap, char *buf, int space)
355 {
356         char *p = buf;
357         struct ieee80211_node *ni;
358         struct ieee80211_node_table *nt = (struct ieee80211_node_table *) &vap->iv_ic->ic_sta;
359
360         //IEEE80211_NODE_LOCK(nt);                                                                               
361         TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
362                 /* Assume each node needs 500 bytes */
363                 if (buf + space < p + 500)
364                         break;
365
366                 if (ni->ni_vap == vap &&
367                     0 != memcmp(vap->iv_myaddr, ni->ni_macaddr, IEEE80211_ADDR_LEN)) {
368                         struct timespec t;
369                         jiffies_to_timespec(jiffies - ni->ni_last_rx, &t);
370                         p += sprintf(p, "macaddr: <%s>\n", ether_sprintf(ni->ni_macaddr));
371                         p += sprintf(p, " rssi %d\n", ni->ni_rssi);
372                         
373                         p += sprintf(p, " last_rx %ld.%06ld\n", 
374                                      t.tv_sec, t.tv_nsec / 1000);
375
376                 }
377         }
378         //IEEE80211_NODE_UNLOCK(nt);                                                                             
379         return (p - buf);
380 }
381
382 static ssize_t
383 proc_ieee80211_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
384 {
385         loff_t pos = *offset;
386         struct proc_ieee80211_priv *pv = (struct proc_ieee80211_priv *) file->private_data;
387
388         if (!pv->rbuf)
389                 return -EINVAL;
390         if (pos < 0)
391                 return -EINVAL;
392         if (pos > pv->rlen)
393                 return -EFAULT;
394         if (len > pv->rlen - pos)
395                 len = pv->rlen - pos;
396         if (copy_to_user(buf, pv->rbuf + pos, len))
397                 return -EFAULT;
398         *offset = pos + len;
399         return len;
400 }
401
402 static int
403 proc_ieee80211_open(struct inode *inode, struct file *file)
404 {
405         struct proc_ieee80211_priv *pv = NULL;
406         struct proc_dir_entry *dp = PDE(inode);
407         struct ieee80211vap *vap = dp->data;
408
409         if (!(file->private_data = kmalloc(sizeof(struct proc_ieee80211_priv), GFP_KERNEL)))
410                 return -ENOMEM;
411         /* initially allocate both read and write buffers */
412         pv = (struct proc_ieee80211_priv *) file->private_data;
413         memset(pv, 0, sizeof(struct proc_ieee80211_priv));
414         pv->rbuf = vmalloc(MAX_PROC_IEEE80211_SIZE);
415         if (!pv->rbuf) {
416                 kfree(pv);
417                 return -ENOMEM;
418         }
419         pv->wbuf = vmalloc(MAX_PROC_IEEE80211_SIZE);
420         if (!pv->wbuf) {
421                 vfree(pv->rbuf);
422                 kfree(pv);
423                 return -ENOMEM;
424         }
425         memset(pv->wbuf, 0, MAX_PROC_IEEE80211_SIZE);
426         memset(pv->rbuf, 0, MAX_PROC_IEEE80211_SIZE);
427         pv->max_wlen = MAX_PROC_IEEE80211_SIZE;
428         pv->max_rlen = MAX_PROC_IEEE80211_SIZE;
429         /* now read the data into the buffer */
430         pv->rlen = proc_read_nodes(vap, pv->rbuf, MAX_PROC_IEEE80211_SIZE);
431         return 0;
432 }
433
434 static ssize_t
435 proc_ieee80211_write(struct file *file, const char __user *buf, size_t len, loff_t *offset)
436 {
437         loff_t pos = *offset;
438         struct proc_ieee80211_priv *pv =
439                 (struct proc_ieee80211_priv *) file->private_data;
440
441         if (!pv->wbuf)
442                 return -EINVAL;
443         if (pos < 0)
444                 return -EINVAL;
445         if (pos >= pv->max_wlen)
446                 return 0;
447         if (len > pv->max_wlen - pos)
448                 len = pv->max_wlen - pos;
449         if (copy_from_user(pv->wbuf + pos, buf, len))
450                 return -EFAULT;
451         if (pos + len > pv->wlen)
452                 pv->wlen = pos + len;
453         *offset = pos + len;
454
455         return len;
456 }
457
458 static int
459 proc_ieee80211_close(struct inode *inode, struct file *file)
460 {
461         struct proc_ieee80211_priv *pv =
462                 (struct proc_ieee80211_priv *) file->private_data;
463         if (pv->rbuf)
464                 vfree(pv->rbuf);
465         if (pv->wbuf)
466                 vfree(pv->wbuf);
467         kfree(pv);
468         return 0;
469 }
470
471 static struct file_operations proc_ieee80211_ops = {
472         .read = proc_ieee80211_read,
473         .write = proc_ieee80211_write,
474         .open = proc_ieee80211_open,
475         .release = proc_ieee80211_close,
476 };
477 #endif                  /* CONFIG_PROC_FS */
478
479 #ifdef IEEE80211_DEBUG
480 static int
481 IEEE80211_SYSCTL_DECL(ieee80211_sysctl_debug, ctl, write, filp, buffer,
482         lenp, ppos)
483 {
484         struct ieee80211vap *vap = ctl->extra1;
485         u_int val;
486         int ret;
487
488         ctl->data = &val;
489         ctl->maxlen = sizeof(val);
490         if (write) {
491                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
492                         lenp, ppos);
493                 if (ret == 0)
494                         vap->iv_debug = val;
495         } else {
496                 val = vap->iv_debug;
497                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
498                         lenp, ppos);
499         }
500         return ret;
501 }
502 #endif /* IEEE80211_DEBUG */
503
504 static int
505 IEEE80211_SYSCTL_DECL(ieee80211_sysctl_dev_type, ctl, write, filp, buffer,
506         lenp, ppos)
507 {
508         struct ieee80211vap *vap = ctl->extra1;
509         u_int val;
510         int ret;
511
512         ctl->data = &val;
513         ctl->maxlen = sizeof(val);
514         if (write) {
515                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
516                         lenp, ppos);
517                 if (ret == 0 && vap->iv_opmode == IEEE80211_M_MONITOR) {
518                         if (val == ARPHRD_IEEE80211_RADIOTAP ||
519                             val == ARPHRD_IEEE80211 ||
520                             val == ARPHRD_IEEE80211_PRISM ||
521                             val == ARPHRD_IEEE80211_ATHDESC) {
522                                 vap->iv_dev->type = val;
523                         }
524                 }
525         } else {
526                 val = vap->iv_dev->type;
527                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
528                         lenp, ppos);
529         }
530         return ret;
531 }
532 static int
533 IEEE80211_SYSCTL_DECL(ieee80211_sysctl_monitor_nods_only, ctl, write, filp, buffer,
534         lenp, ppos)
535 {
536         struct ieee80211vap *vap = ctl->extra1;
537         u_int val;
538         int ret;
539
540         ctl->data = &val;
541         ctl->maxlen = sizeof(val);
542         if (write) {
543                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
544                         lenp, ppos);
545                 if (ret == 0)
546                         vap->iv_monitor_nods_only = val;
547         } else {
548                 val = vap->iv_monitor_nods_only;
549                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
550                         lenp, ppos);
551         }
552         return ret;
553 }
554 static int
555 IEEE80211_SYSCTL_DECL(ieee80211_sysctl_monitor_txf_len, ctl, write, filp, buffer,
556         lenp, ppos)
557 {
558         struct ieee80211vap *vap = ctl->extra1;
559         u_int val;
560         int ret;
561
562         ctl->data = &val;
563         ctl->maxlen = sizeof(val);
564         if (write) {
565                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
566                         lenp, ppos);
567                 if (ret == 0)
568                         vap->iv_monitor_txf_len = val;
569         } else {
570                 val = vap->iv_monitor_txf_len;
571                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
572                         lenp, ppos);
573         }
574         return ret;
575 }
576 static int
577 IEEE80211_SYSCTL_DECL(ieee80211_sysctl_monitor_phy_errors, ctl, write, filp, buffer,
578         lenp, ppos)
579 {
580         struct ieee80211vap *vap = ctl->extra1;
581         u_int val;
582         int ret;
583
584         ctl->data = &val;
585         ctl->maxlen = sizeof(val);
586         if (write) {
587                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
588                         lenp, ppos);
589                 if (ret == 0)
590                         vap->iv_monitor_phy_errors = val;
591         } else {
592                 val = vap->iv_monitor_phy_errors;
593                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
594                         lenp, ppos);
595         }
596         return ret;
597 }
598
599 static int
600 IEEE80211_SYSCTL_DECL(ieee80211_sysctl_monitor_crc_errors, ctl, write, filp, buffer,
601         lenp, ppos)
602 {
603         struct ieee80211vap *vap = ctl->extra1;
604         u_int val;
605         int ret;
606
607         ctl->data = &val;
608         ctl->maxlen = sizeof(val);
609         if (write) {
610                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
611                         lenp, ppos);
612                 if (ret == 0)
613                         vap->iv_monitor_crc_errors = val;
614         } else {
615                 val = vap->iv_monitor_crc_errors;
616                 ret = IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer,
617                         lenp, ppos);
618         }
619         return ret;
620 }
621
622 static const ctl_table ieee80211_sysctl_template[] = {
623 #ifdef IEEE80211_DEBUG
624         { ATH_INIT_CTL_NAME(CTL_AUTO)
625           .procname     = "debug",
626           .mode         = 0644,
627           .proc_handler = ieee80211_sysctl_debug
628         },
629 #endif
630         { ATH_INIT_CTL_NAME(CTL_AUTO)
631           .procname     = "dev_type",
632           .mode         = 0644,
633           .proc_handler = ieee80211_sysctl_dev_type
634         },
635         { ATH_INIT_CTL_NAME(CTL_AUTO)
636           .procname     = "monitor_nods_only",
637           .mode         = 0644,
638           .proc_handler = ieee80211_sysctl_monitor_nods_only
639         },
640         { ATH_INIT_CTL_NAME(CTL_AUTO)
641           .procname     = "monitor_txf_len",
642           .mode         = 0644,
643           .proc_handler = ieee80211_sysctl_monitor_txf_len
644         },
645         { ATH_INIT_CTL_NAME(CTL_AUTO)
646           .procname     = "monitor_phy_errors",
647           .mode         = 0644,
648           .proc_handler = ieee80211_sysctl_monitor_phy_errors
649         },
650         { ATH_INIT_CTL_NAME(CTL_AUTO)
651           .procname     = "monitor_crc_errors",
652           .mode         = 0644,
653           .proc_handler = ieee80211_sysctl_monitor_crc_errors
654         },
655         /* NB: must be last entry before NULL */
656         { ATH_INIT_CTL_NAME(CTL_AUTO)
657           .procname     = "%parent",
658           .maxlen       = IFNAMSIZ,
659           .mode         = 0444,
660           .proc_handler = proc_dostring
661         },
662         { }
663 };
664
665 void
666 ieee80211_sysctl_vattach(struct ieee80211vap *vap)
667 {
668         int i, space;
669         char *devname = NULL;
670
671         space = 5 * sizeof(struct ctl_table) + sizeof(ieee80211_sysctl_template);
672         vap->iv_sysctls = kmalloc(space, GFP_KERNEL);
673         if (vap->iv_sysctls == NULL) {
674                 printk("%s: no memory for sysctl table!\n", __func__);
675                 return;
676         }
677
678         /*
679          * Reserve space for the device name outside the net_device structure
680          * so that if the name changes we know what it used to be. 
681          */
682         devname = kmalloc((strlen(vap->iv_dev->name) + 1) * sizeof(char), GFP_KERNEL);
683         if (devname == NULL) {
684                 printk("%s: no memory for VAP name!\n", __func__);
685                 return;
686         }
687         strncpy(devname, vap->iv_dev->name, strlen(vap->iv_dev->name) + 1);
688
689         /* setup the table */
690         memset(vap->iv_sysctls, 0, space);
691         ATH_SET_CTL_NAME(vap->iv_sysctls[0], CTL_NET);
692         vap->iv_sysctls[0].procname = "net";
693         vap->iv_sysctls[0].mode = 0555;
694         vap->iv_sysctls[0].child = &vap->iv_sysctls[2];
695         /* [1] is NULL terminator */
696         ATH_SET_CTL_NAME(vap->iv_sysctls[2], CTL_AUTO);
697         vap->iv_sysctls[2].procname = devname; /* XXX bad idea? */
698         vap->iv_sysctls[2].mode = 0555;
699         vap->iv_sysctls[2].child = &vap->iv_sysctls[4];
700         /* [3] is NULL terminator */
701         /* copy in pre-defined data */
702         memcpy(&vap->iv_sysctls[4], ieee80211_sysctl_template,
703                 sizeof(ieee80211_sysctl_template));
704
705         /* add in dynamic data references */
706         for (i = 4; vap->iv_sysctls[i].procname; i++)
707                 if (vap->iv_sysctls[i].extra1 == NULL)
708                         vap->iv_sysctls[i].extra1 = vap;
709
710         /* tack on back-pointer to parent device */
711         vap->iv_sysctls[i-1].data = vap->iv_ic->ic_dev->name;   /* XXX? */
712
713         /* and register everything */
714         vap->iv_sysctl_header = ATH_REGISTER_SYSCTL_TABLE(vap->iv_sysctls);
715         if (!vap->iv_sysctl_header) {
716                 printk("%s: failed to register sysctls!\n", vap->iv_dev->name);
717                 kfree(devname);
718                 kfree(vap->iv_sysctls);
719                 vap->iv_sysctls = NULL;
720         }
721
722 #ifdef CONFIG_PROC_FS
723         /* Ensure the base madwifi directory exists */
724         if (!proc_madwifi && proc_net != NULL) {
725                 proc_madwifi = proc_mkdir("madwifi", proc_net);
726                 if (!proc_madwifi)
727                         printk(KERN_WARNING "Failed to mkdir /proc/net/madwifi\n");
728         }
729
730         /* Create a proc directory named after the VAP */
731         if (proc_madwifi) {
732                 proc_madwifi_count++;
733                 vap->iv_proc = proc_mkdir(vap->iv_dev->name, proc_madwifi);
734         }
735         
736         /* Create a proc entry listing the associated stations */
737         ieee80211_proc_vcreate(vap, &proc_ieee80211_ops, "associated_sta");
738
739         /* Recreate any other proc entries that have been registered */
740         if (vap->iv_proc) {
741                 struct ieee80211_proc_entry *tmp = vap->iv_proc_entries;
742
743                 while (tmp) {
744                         if (!tmp->entry) {
745                                 tmp->entry = create_proc_entry(tmp->name, 
746                                 PROC_IEEE80211_PERM, vap->iv_proc);
747                                 tmp->entry->data = vap;
748                                 tmp->entry->proc_fops = tmp->fileops;
749                         }
750                         tmp = tmp->next;
751                 }
752         }
753 #endif                  /* CONFIG_PROC_FS */
754 }
755
756 #ifdef CONFIG_PROC_FS
757 /* Frees all memory used for the list of proc entries */
758 void 
759 ieee80211_proc_cleanup(struct ieee80211vap *vap)
760 {
761         struct ieee80211_proc_entry *tmp=vap->iv_proc_entries;
762         struct ieee80211_proc_entry *next = NULL;
763         while (tmp) {
764                 next = tmp->next;
765                 kfree(tmp);
766                 tmp = next;
767         }
768 }
769
770 /* Called by other modules to register a proc entry under the vap directory */
771 int 
772 ieee80211_proc_vcreate(struct ieee80211vap *vap, 
773                 struct file_operations *fileops, char *name)
774 {
775         struct ieee80211_proc_entry *entry;
776         struct ieee80211_proc_entry *tmp=NULL;
777
778         /* Ignore if already in the list */
779         if (vap->iv_proc_entries) {
780                 tmp = vap->iv_proc_entries;
781                 do {
782                         if (strcmp(tmp->name, name)==0)
783                                 return -1;
784                         /* Check for end of list */
785                         if (!tmp->next)
786                                 break;
787                         /* Otherwise move on */
788                         tmp = tmp->next;
789                 } while (1);
790         }
791         
792         /* Create an item in our list for the new entry */
793         entry = kmalloc(sizeof(struct ieee80211_proc_entry), GFP_KERNEL);
794         if (entry == NULL) {
795                 printk("%s: no memory for new proc entry (%s)!\n", __func__, 
796                                 name);
797                 return -1;
798         }
799
800         /* Replace null fileops pointers with our standard functions */
801         if (!fileops->open)
802                 fileops->open = proc_ieee80211_open;
803         if (!fileops->release)
804                 fileops->release = proc_ieee80211_close;
805         if (!fileops->read)
806                 fileops->read = proc_ieee80211_read;
807         if (!fileops->write)
808                 fileops->write = proc_ieee80211_write;
809         
810         /* Create the entry record */
811         entry->name = name;
812         entry->fileops = fileops;
813         entry->next = NULL;
814         entry->entry = NULL;
815
816         /* Create the actual proc entry */
817         if (vap->iv_proc) {
818                 entry->entry = create_proc_entry(entry->name, 
819                                 PROC_IEEE80211_PERM, vap->iv_proc);
820                 entry->entry->data = vap;
821                 entry->entry->proc_fops = entry->fileops;
822         }
823
824         /* Add it to the list */
825         if (!tmp) {
826                 /* Add to the start */
827                 vap->iv_proc_entries = entry;
828         } else {
829                 /* Add to the end */
830                 tmp->next = entry;
831         }
832
833         return 0;
834 }
835 EXPORT_SYMBOL(ieee80211_proc_vcreate);
836 #endif                  /* CONFIG_PROC_FS */
837
838 void
839 ieee80211_sysctl_vdetach(struct ieee80211vap *vap)
840 {
841         if (vap->iv_sysctl_header) {
842                 unregister_sysctl_table(vap->iv_sysctl_header);
843                 vap->iv_sysctl_header = NULL;
844         }
845
846 #ifdef CONFIG_PROC_FS
847         if (vap->iv_proc) {
848                 /* Remove child proc entries but leave them in the list */
849                 struct ieee80211_proc_entry *tmp = vap->iv_proc_entries;
850
851                 while (tmp) {
852                         if (tmp->entry) {
853                                 remove_proc_entry(tmp->name, vap->iv_proc);
854                                 tmp->entry = NULL;
855                         }
856                         tmp = tmp->next;
857                 }
858                 remove_proc_entry(vap->iv_proc->name, proc_madwifi);
859                 if (proc_madwifi_count == 1) {
860                         remove_proc_entry("madwifi", proc_net);
861                         proc_madwifi = NULL;
862                 }
863                 proc_madwifi_count--;
864         }
865 #endif                  /* CONFIG_PROC_FS */
866
867         if (vap->iv_sysctls && vap->iv_sysctls[2].procname) {
868                 kfree(vap->iv_sysctls[2].procname);
869                 vap->iv_sysctls[2].procname = NULL;
870         }
871         
872         if (vap->iv_sysctls) {
873                 kfree(vap->iv_sysctls);
874                 vap->iv_sysctls = NULL;
875         }
876 }
877
878 /*
879  * Format an Ethernet MAC for printing.
880  */
881 const char*
882 ether_sprintf(const u_int8_t *mac)
883 {
884         static char etherbuf[18];       /* XXX */
885         snprintf(etherbuf, sizeof(etherbuf), "%02x:%02x:%02x:%02x:%02x:%02x",
886                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
887         return etherbuf;
888 }
889 EXPORT_SYMBOL(ether_sprintf);           /* XXX */
890
891 /* Function to handle the device event notifications.
892  * If the event is a NETDEV_CHANGENAME, and is for an interface
893  * we are taking care of, then we want to remove its existing 
894  * proc entries (which now have the wrong names) and add
895  * new, correct, entries.
896  */
897 static int
898 ieee80211_rcv_dev_event(struct notifier_block *this, unsigned long event,
899         void *ptr)
900 {
901         struct net_device *dev = (struct net_device *) ptr;
902
903 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
904         if (!dev || dev->open != &ieee80211_open)
905                 return 0;
906 #else
907         if (!dev || dev->netdev_ops->ndo_open != &ieee80211_open)
908                 return 0;
909 #endif
910
911         switch (event) {
912         case NETDEV_CHANGENAME:
913                 ieee80211_sysctl_vdetach(netdev_priv(dev));
914                 ieee80211_sysctl_vattach(netdev_priv(dev));
915                 return NOTIFY_DONE;
916         default:
917                 break;
918         }
919         return 0;
920 }
921
922 static struct notifier_block ieee80211_event_block = {
923         .notifier_call = ieee80211_rcv_dev_event
924 };
925
926 /*
927  * Module glue.
928  */
929 #include "release.h"
930 static char *version = RELEASE_VERSION;
931 static char *dev_info = "wlan";
932
933 MODULE_AUTHOR("Errno Consulting, Sam Leffler");
934 MODULE_DESCRIPTION("802.11 wireless LAN protocol support");
935 #ifdef MODULE_VERSION
936 MODULE_VERSION(RELEASE_VERSION);
937 #endif
938 #ifdef MODULE_LICENSE
939 MODULE_LICENSE("Dual BSD/GPL");
940 #endif
941
942 extern  void ieee80211_auth_setup(void);
943
944 static int __init
945 init_wlan(void)
946 {
947         register_netdevice_notifier(&ieee80211_event_block);
948         printk(KERN_INFO "%s: %s\n", dev_info, version);
949         return 0;
950 }
951 module_init(init_wlan);
952
953 static void __exit
954 exit_wlan(void)
955 {
956         unregister_netdevice_notifier(&ieee80211_event_block);
957         printk(KERN_INFO "%s: driver unloaded\n", dev_info);
958 }
959 module_exit(exit_wlan);