Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hostap_proc.c
Go to the documentation of this file.
1 /* /proc routines for Host AP driver */
2 
3 #include <linux/types.h>
4 #include <linux/proc_fs.h>
5 #include <linux/export.h>
6 #include <net/lib80211.h>
7 
8 #include "hostap_wlan.h"
9 #include "hostap.h"
10 
11 #define PROC_LIMIT (PAGE_SIZE - 80)
12 
13 
14 #ifndef PRISM2_NO_PROCFS_DEBUG
15 static int prism2_debug_proc_read(char *page, char **start, off_t off,
16  int count, int *eof, void *data)
17 {
18  char *p = page;
19  local_info_t *local = (local_info_t *) data;
20  int i;
21 
22  if (off != 0) {
23  *eof = 1;
24  return 0;
25  }
26 
27  p += sprintf(p, "next_txfid=%d next_alloc=%d\n",
28  local->next_txfid, local->next_alloc);
29  for (i = 0; i < PRISM2_TXFID_COUNT; i++)
30  p += sprintf(p, "FID: tx=%04X intransmit=%04X\n",
31  local->txfid[i], local->intransmitfid[i]);
32  p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control);
33  p += sprintf(p, "beacon_int=%d\n", local->beacon_int);
34  p += sprintf(p, "dtim_period=%d\n", local->dtim_period);
35  p += sprintf(p, "wds_max_connections=%d\n",
36  local->wds_max_connections);
37  p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
38  p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
39  for (i = 0; i < WEP_KEYS; i++) {
40  if (local->crypt_info.crypt[i] &&
41  local->crypt_info.crypt[i]->ops) {
42  p += sprintf(p, "crypt[%d]=%s\n", i,
43  local->crypt_info.crypt[i]->ops->name);
44  }
45  }
46  p += sprintf(p, "pri_only=%d\n", local->pri_only);
47  p += sprintf(p, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI);
48  p += sprintf(p, "sram_type=%d\n", local->sram_type);
49  p += sprintf(p, "no_pri=%d\n", local->no_pri);
50 
51  return (p - page);
52 }
53 #endif /* PRISM2_NO_PROCFS_DEBUG */
54 
55 
56 static int prism2_stats_proc_read(char *page, char **start, off_t off,
57  int count, int *eof, void *data)
58 {
59  char *p = page;
60  local_info_t *local = (local_info_t *) data;
61  struct comm_tallies_sums *sums = &local->comm_tallies;
62 
63  if (off != 0) {
64  *eof = 1;
65  return 0;
66  }
67 
68  p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames);
69  p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames);
70  p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments);
71  p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets);
72  p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets);
73  p += sprintf(p, "TxDeferredTransmissions=%u\n",
75  p += sprintf(p, "TxSingleRetryFrames=%u\n",
77  p += sprintf(p, "TxMultipleRetryFrames=%u\n",
79  p += sprintf(p, "TxRetryLimitExceeded=%u\n",
81  p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards);
82  p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames);
83  p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames);
84  p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments);
85  p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets);
86  p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets);
87  p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors);
88  p += sprintf(p, "RxDiscardsNoBuffer=%u\n",
89  sums->rx_discards_no_buffer);
90  p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa);
91  p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n",
93  p += sprintf(p, "RxMessageInMsgFragments=%u\n",
95  p += sprintf(p, "RxMessageInBadMsgFragments=%u\n",
97  /* FIX: this may grow too long for one page(?) */
98 
99  return (p - page);
100 }
101 
102 
103 static int prism2_wds_proc_read(char *page, char **start, off_t off,
104  int count, int *eof, void *data)
105 {
106  char *p = page;
107  local_info_t *local = (local_info_t *) data;
108  struct list_head *ptr;
109  struct hostap_interface *iface;
110 
111  if (off > PROC_LIMIT) {
112  *eof = 1;
113  return 0;
114  }
115 
116  read_lock_bh(&local->iface_lock);
117  list_for_each(ptr, &local->hostap_interfaces) {
118  iface = list_entry(ptr, struct hostap_interface, list);
119  if (iface->type != HOSTAP_INTERFACE_WDS)
120  continue;
121  p += sprintf(p, "%s\t%pM\n",
122  iface->dev->name,
123  iface->u.wds.remote_addr);
124  if ((p - page) > PROC_LIMIT) {
125  printk(KERN_DEBUG "%s: wds proc did not fit\n",
126  local->dev->name);
127  break;
128  }
129  }
130  read_unlock_bh(&local->iface_lock);
131 
132  if ((p - page) <= off) {
133  *eof = 1;
134  return 0;
135  }
136 
137  *start = page + off;
138 
139  return (p - page - off);
140 }
141 
142 
143 static int prism2_bss_list_proc_read(char *page, char **start, off_t off,
144  int count, int *eof, void *data)
145 {
146  char *p = page;
147  local_info_t *local = (local_info_t *) data;
148  struct list_head *ptr;
149  struct hostap_bss_info *bss;
150  int i;
151 
152  if (off > PROC_LIMIT) {
153  *eof = 1;
154  return 0;
155  }
156 
157  p += sprintf(p, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
158  "SSID(hex)\tWPA IE\n");
159  spin_lock_bh(&local->lock);
160  list_for_each(ptr, &local->bss_list) {
161  bss = list_entry(ptr, struct hostap_bss_info, list);
162  p += sprintf(p, "%pM\t%lu\t%u\t0x%x\t",
163  bss->bssid, bss->last_update,
164  bss->count, bss->capab_info);
165  for (i = 0; i < bss->ssid_len; i++) {
166  p += sprintf(p, "%c",
167  bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
168  bss->ssid[i] : '_');
169  }
170  p += sprintf(p, "\t");
171  for (i = 0; i < bss->ssid_len; i++) {
172  p += sprintf(p, "%02x", bss->ssid[i]);
173  }
174  p += sprintf(p, "\t");
175  for (i = 0; i < bss->wpa_ie_len; i++) {
176  p += sprintf(p, "%02x", bss->wpa_ie[i]);
177  }
178  p += sprintf(p, "\n");
179  if ((p - page) > PROC_LIMIT) {
180  printk(KERN_DEBUG "%s: BSS proc did not fit\n",
181  local->dev->name);
182  break;
183  }
184  }
185  spin_unlock_bh(&local->lock);
186 
187  if ((p - page) <= off) {
188  *eof = 1;
189  return 0;
190  }
191 
192  *start = page + off;
193 
194  return (p - page - off);
195 }
196 
197 
198 static int prism2_crypt_proc_read(char *page, char **start, off_t off,
199  int count, int *eof, void *data)
200 {
201  char *p = page;
202  local_info_t *local = (local_info_t *) data;
203  int i;
204 
205  if (off > PROC_LIMIT) {
206  *eof = 1;
207  return 0;
208  }
209 
210  p += sprintf(p, "tx_keyidx=%d\n", local->crypt_info.tx_keyidx);
211  for (i = 0; i < WEP_KEYS; i++) {
212  if (local->crypt_info.crypt[i] &&
213  local->crypt_info.crypt[i]->ops &&
214  local->crypt_info.crypt[i]->ops->print_stats) {
215  p = local->crypt_info.crypt[i]->ops->print_stats(
216  p, local->crypt_info.crypt[i]->priv);
217  }
218  }
219 
220  if ((p - page) <= off) {
221  *eof = 1;
222  return 0;
223  }
224 
225  *start = page + off;
226 
227  return (p - page - off);
228 }
229 
230 
231 static int prism2_pda_proc_read(char *page, char **start, off_t off,
232  int count, int *eof, void *data)
233 {
234  local_info_t *local = (local_info_t *) data;
235 
236  if (local->pda == NULL || off >= PRISM2_PDA_SIZE) {
237  *eof = 1;
238  return 0;
239  }
240 
241  if (off + count > PRISM2_PDA_SIZE)
242  count = PRISM2_PDA_SIZE - off;
243 
244  memcpy(page, local->pda + off, count);
245  return count;
246 }
247 
248 
249 static int prism2_aux_dump_proc_read(char *page, char **start, off_t off,
250  int count, int *eof, void *data)
251 {
252  local_info_t *local = (local_info_t *) data;
253 
254  if (local->func->read_aux == NULL) {
255  *eof = 1;
256  return 0;
257  }
258 
259  if (local->func->read_aux(local->dev, off, count, page)) {
260  *eof = 1;
261  return 0;
262  }
263  *start = page;
264 
265  return count;
266 }
267 
268 
269 #ifdef PRISM2_IO_DEBUG
270 static int prism2_io_debug_proc_read(char *page, char **start, off_t off,
271  int count, int *eof, void *data)
272 {
273  local_info_t *local = (local_info_t *) data;
274  int head = local->io_debug_head;
275  int start_bytes, left, copy, copied;
276 
277  if (off + count > PRISM2_IO_DEBUG_SIZE * 4) {
278  *eof = 1;
279  if (off >= PRISM2_IO_DEBUG_SIZE * 4)
280  return 0;
281  count = PRISM2_IO_DEBUG_SIZE * 4 - off;
282  }
283 
284  copied = 0;
285  start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4;
286  left = count;
287 
288  if (off < start_bytes) {
289  copy = start_bytes - off;
290  if (copy > count)
291  copy = count;
292  memcpy(page, ((u8 *) &local->io_debug[head]) + off, copy);
293  left -= copy;
294  if (left > 0)
295  memcpy(&page[copy], local->io_debug, left);
296  } else {
297  memcpy(page, ((u8 *) local->io_debug) + (off - start_bytes),
298  left);
299  }
300 
301  *start = page;
302 
303  return count;
304 }
305 #endif /* PRISM2_IO_DEBUG */
306 
307 
308 #ifndef PRISM2_NO_STATION_MODES
309 static int prism2_scan_results_proc_read(char *page, char **start, off_t off,
310  int count, int *eof, void *data)
311 {
312  char *p = page;
313  local_info_t *local = (local_info_t *) data;
314  int entry, i, len, total = 0;
315  struct hfa384x_hostscan_result *scanres;
316  u8 *pos;
317 
318  p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
319  "SSID\n");
320 
321  spin_lock_bh(&local->lock);
322  for (entry = 0; entry < local->last_scan_results_count; entry++) {
323  scanres = &local->last_scan_results[entry];
324 
325  if (total + (p - page) <= off) {
326  total += p - page;
327  p = page;
328  }
329  if (total + (p - page) > off + count)
330  break;
331  if ((p - page) > (PAGE_SIZE - 200))
332  break;
333 
334  p += sprintf(p, "%d %d %d %d 0x%02x %d %pM %d ",
335  le16_to_cpu(scanres->chid),
336  (s16) le16_to_cpu(scanres->anl),
337  (s16) le16_to_cpu(scanres->sl),
338  le16_to_cpu(scanres->beacon_interval),
339  le16_to_cpu(scanres->capability),
340  le16_to_cpu(scanres->rate),
341  scanres->bssid,
342  le16_to_cpu(scanres->atim));
343 
344  pos = scanres->sup_rates;
345  for (i = 0; i < sizeof(scanres->sup_rates); i++) {
346  if (pos[i] == 0)
347  break;
348  p += sprintf(p, "<%02x>", pos[i]);
349  }
350  p += sprintf(p, " ");
351 
352  pos = scanres->ssid;
353  len = le16_to_cpu(scanres->ssid_len);
354  if (len > 32)
355  len = 32;
356  for (i = 0; i < len; i++) {
357  unsigned char c = pos[i];
358  if (c >= 32 && c < 127)
359  p += sprintf(p, "%c", c);
360  else
361  p += sprintf(p, "<%02x>", c);
362  }
363  p += sprintf(p, "\n");
364  }
365  spin_unlock_bh(&local->lock);
366 
367  total += (p - page);
368  if (total >= off + count)
369  *eof = 1;
370 
371  if (total < off) {
372  *eof = 1;
373  return 0;
374  }
375 
376  len = total - off;
377  if (len > (p - page))
378  len = p - page;
379  *start = p - len;
380  if (len > count)
381  len = count;
382 
383  return len;
384 }
385 #endif /* PRISM2_NO_STATION_MODES */
386 
387 
389 {
390  local->proc = NULL;
391 
392  if (hostap_proc == NULL) {
393  printk(KERN_WARNING "%s: hostap proc directory not created\n",
394  local->dev->name);
395  return;
396  }
397 
398  local->proc = proc_mkdir(local->ddev->name, hostap_proc);
399  if (local->proc == NULL) {
400  printk(KERN_INFO "/proc/net/hostap/%s creation failed\n",
401  local->ddev->name);
402  return;
403  }
404 
405 #ifndef PRISM2_NO_PROCFS_DEBUG
406  create_proc_read_entry("debug", 0, local->proc,
407  prism2_debug_proc_read, local);
408 #endif /* PRISM2_NO_PROCFS_DEBUG */
409  create_proc_read_entry("stats", 0, local->proc,
410  prism2_stats_proc_read, local);
411  create_proc_read_entry("wds", 0, local->proc,
412  prism2_wds_proc_read, local);
413  create_proc_read_entry("pda", 0, local->proc,
414  prism2_pda_proc_read, local);
415  create_proc_read_entry("aux_dump", 0, local->proc,
416  prism2_aux_dump_proc_read, local);
417  create_proc_read_entry("bss_list", 0, local->proc,
418  prism2_bss_list_proc_read, local);
419  create_proc_read_entry("crypt", 0, local->proc,
420  prism2_crypt_proc_read, local);
421 #ifdef PRISM2_IO_DEBUG
422  create_proc_read_entry("io_debug", 0, local->proc,
423  prism2_io_debug_proc_read, local);
424 #endif /* PRISM2_IO_DEBUG */
425 #ifndef PRISM2_NO_STATION_MODES
426  create_proc_read_entry("scan_results", 0, local->proc,
427  prism2_scan_results_proc_read, local);
428 #endif /* PRISM2_NO_STATION_MODES */
429 }
430 
431 
433 {
434  if (local->proc != NULL) {
435 #ifndef PRISM2_NO_STATION_MODES
436  remove_proc_entry("scan_results", local->proc);
437 #endif /* PRISM2_NO_STATION_MODES */
438 #ifdef PRISM2_IO_DEBUG
439  remove_proc_entry("io_debug", local->proc);
440 #endif /* PRISM2_IO_DEBUG */
441  remove_proc_entry("pda", local->proc);
442  remove_proc_entry("aux_dump", local->proc);
443  remove_proc_entry("wds", local->proc);
444  remove_proc_entry("stats", local->proc);
445  remove_proc_entry("bss_list", local->proc);
446  remove_proc_entry("crypt", local->proc);
447 #ifndef PRISM2_NO_PROCFS_DEBUG
448  remove_proc_entry("debug", local->proc);
449 #endif /* PRISM2_NO_PROCFS_DEBUG */
450  if (hostap_proc != NULL)
451  remove_proc_entry(local->proc->name, hostap_proc);
452  }
453 }
454 
455