• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* /proc routines for Host AP driver */
2 
3 #include <linux/types.h>
4 #include <linux/proc_fs.h>
5 #include <net/lib80211.h>
6 
7 #include "hostap_wlan.h"
8 #include "hostap.h"
9 
10 #define PROC_LIMIT (PAGE_SIZE - 80)
11 
12 
13 #ifndef PRISM2_NO_PROCFS_DEBUG
prism2_debug_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)14 static int prism2_debug_proc_read(char *page, char **start, off_t off,
15 				  int count, int *eof, void *data)
16 {
17 	char *p = page;
18 	local_info_t *local = (local_info_t *) data;
19 	int i;
20 
21 	if (off != 0) {
22 		*eof = 1;
23 		return 0;
24 	}
25 
26 	p += sprintf(p, "next_txfid=%d next_alloc=%d\n",
27 		     local->next_txfid, local->next_alloc);
28 	for (i = 0; i < PRISM2_TXFID_COUNT; i++)
29 		p += sprintf(p, "FID: tx=%04X intransmit=%04X\n",
30 			     local->txfid[i], local->intransmitfid[i]);
31 	p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control);
32 	p += sprintf(p, "beacon_int=%d\n", local->beacon_int);
33 	p += sprintf(p, "dtim_period=%d\n", local->dtim_period);
34 	p += sprintf(p, "wds_max_connections=%d\n",
35 		     local->wds_max_connections);
36 	p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
37 	p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
38 	for (i = 0; i < WEP_KEYS; i++) {
39 		if (local->crypt_info.crypt[i] &&
40 		    local->crypt_info.crypt[i]->ops) {
41 			p += sprintf(p, "crypt[%d]=%s\n", i,
42 				     local->crypt_info.crypt[i]->ops->name);
43 		}
44 	}
45 	p += sprintf(p, "pri_only=%d\n", local->pri_only);
46 	p += sprintf(p, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI);
47 	p += sprintf(p, "sram_type=%d\n", local->sram_type);
48 	p += sprintf(p, "no_pri=%d\n", local->no_pri);
49 
50 	return (p - page);
51 }
52 #endif /* PRISM2_NO_PROCFS_DEBUG */
53 
54 
prism2_stats_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)55 static int prism2_stats_proc_read(char *page, char **start, off_t off,
56 				  int count, int *eof, void *data)
57 {
58 	char *p = page;
59 	local_info_t *local = (local_info_t *) data;
60 	struct comm_tallies_sums *sums = (struct comm_tallies_sums *)
61 		&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",
74 		     sums->tx_deferred_transmissions);
75 	p += sprintf(p, "TxSingleRetryFrames=%u\n",
76 		     sums->tx_single_retry_frames);
77 	p += sprintf(p, "TxMultipleRetryFrames=%u\n",
78 		     sums->tx_multiple_retry_frames);
79 	p += sprintf(p, "TxRetryLimitExceeded=%u\n",
80 		     sums->tx_retry_limit_exceeded);
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",
92 		     sums->rx_discards_wep_undecryptable);
93 	p += sprintf(p, "RxMessageInMsgFragments=%u\n",
94 		     sums->rx_message_in_msg_fragments);
95 	p += sprintf(p, "RxMessageInBadMsgFragments=%u\n",
96 		     sums->rx_message_in_bad_msg_fragments);
97 	/* FIX: this may grow too long for one page(?) */
98 
99 	return (p - page);
100 }
101 
102 
prism2_wds_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)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 
prism2_bss_list_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)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 
prism2_crypt_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)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 
prism2_pda_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)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 
prism2_aux_dump_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)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
prism2_io_debug_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)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
prism2_scan_results_proc_read(char * page,char ** start,off_t off,int count,int * eof,void * data)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 
hostap_init_proc(local_info_t * local)388 void hostap_init_proc(local_info_t *local)
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 
hostap_remove_proc(local_info_t * local)432 void hostap_remove_proc(local_info_t *local)
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 
456 EXPORT_SYMBOL(hostap_init_proc);
457 EXPORT_SYMBOL(hostap_remove_proc);
458