diff options
Diffstat (limited to 'drivers/net/wireless/hostap/hostap_ap.c')
-rw-r--r-- | drivers/net/wireless/hostap/hostap_ap.c | 375 |
1 files changed, 219 insertions, 156 deletions
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index dd9a18f8dbca..19c45e363aa7 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/proc_fs.h> | 19 | #include <linux/proc_fs.h> |
20 | #include <linux/seq_file.h> | ||
20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
21 | #include <linux/random.h> | 22 | #include <linux/random.h> |
22 | #include <linux/if_arp.h> | 23 | #include <linux/if_arp.h> |
@@ -64,28 +65,32 @@ static void prism2_send_mgmt(struct net_device *dev, | |||
64 | 65 | ||
65 | 66 | ||
66 | #ifndef PRISM2_NO_PROCFS_DEBUG | 67 | #ifndef PRISM2_NO_PROCFS_DEBUG |
67 | static int ap_debug_proc_read(char *page, char **start, off_t off, | 68 | static int ap_debug_proc_show(struct seq_file *m, void *v) |
68 | int count, int *eof, void *data) | 69 | { |
69 | { | 70 | struct ap_data *ap = m->private; |
70 | char *p = page; | 71 | |
71 | struct ap_data *ap = (struct ap_data *) data; | 72 | seq_printf(m, "BridgedUnicastFrames=%u\n", ap->bridged_unicast); |
72 | 73 | seq_printf(m, "BridgedMulticastFrames=%u\n", ap->bridged_multicast); | |
73 | if (off != 0) { | 74 | seq_printf(m, "max_inactivity=%u\n", ap->max_inactivity / HZ); |
74 | *eof = 1; | 75 | seq_printf(m, "bridge_packets=%u\n", ap->bridge_packets); |
75 | return 0; | 76 | seq_printf(m, "nullfunc_ack=%u\n", ap->nullfunc_ack); |
76 | } | 77 | seq_printf(m, "autom_ap_wds=%u\n", ap->autom_ap_wds); |
77 | 78 | seq_printf(m, "auth_algs=%u\n", ap->local->auth_algs); | |
78 | p += sprintf(p, "BridgedUnicastFrames=%u\n", ap->bridged_unicast); | 79 | seq_printf(m, "tx_drop_nonassoc=%u\n", ap->tx_drop_nonassoc); |
79 | p += sprintf(p, "BridgedMulticastFrames=%u\n", ap->bridged_multicast); | 80 | return 0; |
80 | p += sprintf(p, "max_inactivity=%u\n", ap->max_inactivity / HZ); | 81 | } |
81 | p += sprintf(p, "bridge_packets=%u\n", ap->bridge_packets); | ||
82 | p += sprintf(p, "nullfunc_ack=%u\n", ap->nullfunc_ack); | ||
83 | p += sprintf(p, "autom_ap_wds=%u\n", ap->autom_ap_wds); | ||
84 | p += sprintf(p, "auth_algs=%u\n", ap->local->auth_algs); | ||
85 | p += sprintf(p, "tx_drop_nonassoc=%u\n", ap->tx_drop_nonassoc); | ||
86 | 82 | ||
87 | return (p - page); | 83 | static int ap_debug_proc_open(struct inode *inode, struct file *file) |
84 | { | ||
85 | return single_open(file, ap_debug_proc_show, PDE_DATA(inode)); | ||
88 | } | 86 | } |
87 | |||
88 | static const struct file_operations ap_debug_proc_fops = { | ||
89 | .open = ap_debug_proc_open, | ||
90 | .read = seq_read, | ||
91 | .llseek = seq_lseek, | ||
92 | .release = seq_release, | ||
93 | }; | ||
89 | #endif /* PRISM2_NO_PROCFS_DEBUG */ | 94 | #endif /* PRISM2_NO_PROCFS_DEBUG */ |
90 | 95 | ||
91 | 96 | ||
@@ -325,50 +330,81 @@ void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap, | |||
325 | } | 330 | } |
326 | 331 | ||
327 | 332 | ||
328 | static int ap_control_proc_read(char *page, char **start, off_t off, | 333 | static int ap_control_proc_show(struct seq_file *m, void *v) |
329 | int count, int *eof, void *data) | ||
330 | { | 334 | { |
331 | char *p = page; | 335 | struct ap_data *ap = m->private; |
332 | struct ap_data *ap = (struct ap_data *) data; | ||
333 | char *policy_txt; | 336 | char *policy_txt; |
334 | struct mac_entry *entry; | 337 | struct mac_entry *entry; |
335 | 338 | ||
336 | if (off != 0) { | 339 | if (v == SEQ_START_TOKEN) { |
337 | *eof = 1; | 340 | switch (ap->mac_restrictions.policy) { |
341 | case MAC_POLICY_OPEN: | ||
342 | policy_txt = "open"; | ||
343 | break; | ||
344 | case MAC_POLICY_ALLOW: | ||
345 | policy_txt = "allow"; | ||
346 | break; | ||
347 | case MAC_POLICY_DENY: | ||
348 | policy_txt = "deny"; | ||
349 | break; | ||
350 | default: | ||
351 | policy_txt = "unknown"; | ||
352 | break; | ||
353 | } | ||
354 | seq_printf(m, "MAC policy: %s\n", policy_txt); | ||
355 | seq_printf(m, "MAC entries: %u\n", ap->mac_restrictions.entries); | ||
356 | seq_puts(m, "MAC list:\n"); | ||
338 | return 0; | 357 | return 0; |
339 | } | 358 | } |
340 | 359 | ||
341 | switch (ap->mac_restrictions.policy) { | 360 | entry = v; |
342 | case MAC_POLICY_OPEN: | 361 | seq_printf(m, "%pM\n", entry->addr); |
343 | policy_txt = "open"; | 362 | return 0; |
344 | break; | 363 | } |
345 | case MAC_POLICY_ALLOW: | 364 | |
346 | policy_txt = "allow"; | 365 | static void *ap_control_proc_start(struct seq_file *m, loff_t *_pos) |
347 | break; | 366 | { |
348 | case MAC_POLICY_DENY: | 367 | struct ap_data *ap = m->private; |
349 | policy_txt = "deny"; | ||
350 | break; | ||
351 | default: | ||
352 | policy_txt = "unknown"; | ||
353 | break; | ||
354 | } | ||
355 | p += sprintf(p, "MAC policy: %s\n", policy_txt); | ||
356 | p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries); | ||
357 | p += sprintf(p, "MAC list:\n"); | ||
358 | spin_lock_bh(&ap->mac_restrictions.lock); | 368 | spin_lock_bh(&ap->mac_restrictions.lock); |
359 | list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) { | 369 | return seq_list_start_head(&ap->mac_restrictions.mac_list, *_pos); |
360 | if (p - page > PAGE_SIZE - 80) { | 370 | } |
361 | p += sprintf(p, "All entries did not fit one page.\n"); | ||
362 | break; | ||
363 | } | ||
364 | 371 | ||
365 | p += sprintf(p, "%pM\n", entry->addr); | 372 | static void *ap_control_proc_next(struct seq_file *m, void *v, loff_t *_pos) |
366 | } | 373 | { |
374 | struct ap_data *ap = m->private; | ||
375 | return seq_list_next(v, &ap->mac_restrictions.mac_list, _pos); | ||
376 | } | ||
377 | |||
378 | static void ap_control_proc_stop(struct seq_file *m, void *v) | ||
379 | { | ||
380 | struct ap_data *ap = m->private; | ||
367 | spin_unlock_bh(&ap->mac_restrictions.lock); | 381 | spin_unlock_bh(&ap->mac_restrictions.lock); |
382 | } | ||
368 | 383 | ||
369 | return (p - page); | 384 | static const struct seq_operations ap_control_proc_seqops = { |
385 | .start = ap_control_proc_start, | ||
386 | .next = ap_control_proc_next, | ||
387 | .stop = ap_control_proc_stop, | ||
388 | .show = ap_control_proc_show, | ||
389 | }; | ||
390 | |||
391 | static int ap_control_proc_open(struct inode *inode, struct file *file) | ||
392 | { | ||
393 | int ret = seq_open(file, &ap_control_proc_seqops); | ||
394 | if (ret == 0) { | ||
395 | struct seq_file *m = file->private_data; | ||
396 | m->private = PDE_DATA(inode); | ||
397 | } | ||
398 | return ret; | ||
370 | } | 399 | } |
371 | 400 | ||
401 | static const struct file_operations ap_control_proc_fops = { | ||
402 | .open = ap_control_proc_open, | ||
403 | .read = seq_read, | ||
404 | .llseek = seq_lseek, | ||
405 | .release = seq_release, | ||
406 | }; | ||
407 | |||
372 | 408 | ||
373 | int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac) | 409 | int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac) |
374 | { | 410 | { |
@@ -510,61 +546,84 @@ void ap_control_kickall(struct ap_data *ap) | |||
510 | 546 | ||
511 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT | 547 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT |
512 | 548 | ||
513 | #define PROC_LIMIT (PAGE_SIZE - 80) | 549 | static int prism2_ap_proc_show(struct seq_file *m, void *v) |
514 | |||
515 | static int prism2_ap_proc_read(char *page, char **start, off_t off, | ||
516 | int count, int *eof, void *data) | ||
517 | { | 550 | { |
518 | char *p = page; | 551 | struct sta_info *sta = v; |
519 | struct ap_data *ap = (struct ap_data *) data; | ||
520 | struct sta_info *sta; | ||
521 | int i; | 552 | int i; |
522 | 553 | ||
523 | if (off > PROC_LIMIT) { | 554 | if (v == SEQ_START_TOKEN) { |
524 | *eof = 1; | 555 | seq_printf(m, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n"); |
525 | return 0; | 556 | return 0; |
526 | } | 557 | } |
527 | 558 | ||
528 | p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n"); | 559 | if (!sta->ap) |
529 | spin_lock_bh(&ap->sta_table_lock); | 560 | return 0; |
530 | list_for_each_entry(sta, &ap->sta_list, list) { | ||
531 | if (!sta->ap) | ||
532 | continue; | ||
533 | 561 | ||
534 | p += sprintf(p, "%pM %d %d %d %d '", | 562 | seq_printf(m, "%pM %d %d %d %d '", |
535 | sta->addr, | 563 | sta->addr, |
536 | sta->u.ap.channel, sta->last_rx_signal, | 564 | sta->u.ap.channel, sta->last_rx_signal, |
537 | sta->last_rx_silence, sta->last_rx_rate); | 565 | sta->last_rx_silence, sta->last_rx_rate); |
538 | for (i = 0; i < sta->u.ap.ssid_len; i++) | ||
539 | p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 && | ||
540 | sta->u.ap.ssid[i] < 127) ? | ||
541 | "%c" : "<%02x>"), | ||
542 | sta->u.ap.ssid[i]); | ||
543 | p += sprintf(p, "'"); | ||
544 | if (sta->capability & WLAN_CAPABILITY_ESS) | ||
545 | p += sprintf(p, " [ESS]"); | ||
546 | if (sta->capability & WLAN_CAPABILITY_IBSS) | ||
547 | p += sprintf(p, " [IBSS]"); | ||
548 | if (sta->capability & WLAN_CAPABILITY_PRIVACY) | ||
549 | p += sprintf(p, " [WEP]"); | ||
550 | p += sprintf(p, "\n"); | ||
551 | |||
552 | if ((p - page) > PROC_LIMIT) { | ||
553 | printk(KERN_DEBUG "hostap: ap proc did not fit\n"); | ||
554 | break; | ||
555 | } | ||
556 | } | ||
557 | spin_unlock_bh(&ap->sta_table_lock); | ||
558 | 566 | ||
559 | if ((p - page) <= off) { | 567 | for (i = 0; i < sta->u.ap.ssid_len; i++) { |
560 | *eof = 1; | 568 | if (sta->u.ap.ssid[i] >= 32 && sta->u.ap.ssid[i] < 127) |
561 | return 0; | 569 | seq_putc(m, sta->u.ap.ssid[i]); |
570 | else | ||
571 | seq_printf(m, "<%02x>", sta->u.ap.ssid[i]); | ||
562 | } | 572 | } |
563 | 573 | ||
564 | *start = page + off; | 574 | seq_putc(m, '\''); |
575 | if (sta->capability & WLAN_CAPABILITY_ESS) | ||
576 | seq_puts(m, " [ESS]"); | ||
577 | if (sta->capability & WLAN_CAPABILITY_IBSS) | ||
578 | seq_puts(m, " [IBSS]"); | ||
579 | if (sta->capability & WLAN_CAPABILITY_PRIVACY) | ||
580 | seq_puts(m, " [WEP]"); | ||
581 | seq_putc(m, '\n'); | ||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static void *prism2_ap_proc_start(struct seq_file *m, loff_t *_pos) | ||
586 | { | ||
587 | struct ap_data *ap = m->private; | ||
588 | spin_lock_bh(&ap->sta_table_lock); | ||
589 | return seq_list_start_head(&ap->sta_list, *_pos); | ||
590 | } | ||
565 | 591 | ||
566 | return (p - page - off); | 592 | static void *prism2_ap_proc_next(struct seq_file *m, void *v, loff_t *_pos) |
593 | { | ||
594 | struct ap_data *ap = m->private; | ||
595 | return seq_list_next(v, &ap->sta_list, _pos); | ||
567 | } | 596 | } |
597 | |||
598 | static void prism2_ap_proc_stop(struct seq_file *m, void *v) | ||
599 | { | ||
600 | struct ap_data *ap = m->private; | ||
601 | spin_unlock_bh(&ap->sta_table_lock); | ||
602 | } | ||
603 | |||
604 | static const struct seq_operations prism2_ap_proc_seqops = { | ||
605 | .start = prism2_ap_proc_start, | ||
606 | .next = prism2_ap_proc_next, | ||
607 | .stop = prism2_ap_proc_stop, | ||
608 | .show = prism2_ap_proc_show, | ||
609 | }; | ||
610 | |||
611 | static int prism2_ap_proc_open(struct inode *inode, struct file *file) | ||
612 | { | ||
613 | int ret = seq_open(file, &prism2_ap_proc_seqops); | ||
614 | if (ret == 0) { | ||
615 | struct seq_file *m = file->private_data; | ||
616 | m->private = PDE_DATA(inode); | ||
617 | } | ||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | static const struct file_operations prism2_ap_proc_fops = { | ||
622 | .open = prism2_ap_proc_open, | ||
623 | .read = seq_read, | ||
624 | .llseek = seq_lseek, | ||
625 | .release = seq_release, | ||
626 | }; | ||
568 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ | 627 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ |
569 | 628 | ||
570 | 629 | ||
@@ -836,15 +895,12 @@ void hostap_init_ap_proc(local_info_t *local) | |||
836 | return; | 895 | return; |
837 | 896 | ||
838 | #ifndef PRISM2_NO_PROCFS_DEBUG | 897 | #ifndef PRISM2_NO_PROCFS_DEBUG |
839 | create_proc_read_entry("ap_debug", 0, ap->proc, | 898 | proc_create_data("ap_debug", 0, ap->proc, &ap_debug_proc_fops, ap); |
840 | ap_debug_proc_read, ap); | ||
841 | #endif /* PRISM2_NO_PROCFS_DEBUG */ | 899 | #endif /* PRISM2_NO_PROCFS_DEBUG */ |
842 | 900 | ||
843 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT | 901 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT |
844 | create_proc_read_entry("ap_control", 0, ap->proc, | 902 | proc_create_data("ap_control", 0, ap->proc, &ap_control_proc_fops, ap); |
845 | ap_control_proc_read, ap); | 903 | proc_create_data("ap", 0, ap->proc, &prism2_ap_proc_fops, ap); |
846 | create_proc_read_entry("ap", 0, ap->proc, | ||
847 | prism2_ap_proc_read, ap); | ||
848 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ | 904 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ |
849 | 905 | ||
850 | } | 906 | } |
@@ -982,79 +1038,86 @@ static void prism2_send_mgmt(struct net_device *dev, | |||
982 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ | 1038 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ |
983 | 1039 | ||
984 | 1040 | ||
985 | static int prism2_sta_proc_read(char *page, char **start, off_t off, | 1041 | static int prism2_sta_proc_show(struct seq_file *m, void *v) |
986 | int count, int *eof, void *data) | ||
987 | { | 1042 | { |
988 | char *p = page; | 1043 | struct sta_info *sta = m->private; |
989 | struct sta_info *sta = (struct sta_info *) data; | ||
990 | int i; | 1044 | int i; |
991 | 1045 | ||
992 | /* FIX: possible race condition.. the STA data could have just expired, | 1046 | /* FIX: possible race condition.. the STA data could have just expired, |
993 | * but proc entry was still here so that the read could have started; | 1047 | * but proc entry was still here so that the read could have started; |
994 | * some locking should be done here.. */ | 1048 | * some locking should be done here.. */ |
995 | 1049 | ||
996 | if (off != 0) { | 1050 | seq_printf(m, |
997 | *eof = 1; | 1051 | "%s=%pM\nusers=%d\naid=%d\n" |
998 | return 0; | 1052 | "flags=0x%04x%s%s%s%s%s%s%s\n" |
999 | } | 1053 | "capability=0x%02x\nlisten_interval=%d\nsupported_rates=", |
1000 | 1054 | sta->ap ? "AP" : "STA", | |
1001 | p += sprintf(p, "%s=%pM\nusers=%d\naid=%d\n" | 1055 | sta->addr, atomic_read(&sta->users), sta->aid, |
1002 | "flags=0x%04x%s%s%s%s%s%s%s\n" | 1056 | sta->flags, |
1003 | "capability=0x%02x\nlisten_interval=%d\nsupported_rates=", | 1057 | sta->flags & WLAN_STA_AUTH ? " AUTH" : "", |
1004 | sta->ap ? "AP" : "STA", | 1058 | sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "", |
1005 | sta->addr, atomic_read(&sta->users), sta->aid, | 1059 | sta->flags & WLAN_STA_PS ? " PS" : "", |
1006 | sta->flags, | 1060 | sta->flags & WLAN_STA_TIM ? " TIM" : "", |
1007 | sta->flags & WLAN_STA_AUTH ? " AUTH" : "", | 1061 | sta->flags & WLAN_STA_PERM ? " PERM" : "", |
1008 | sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "", | 1062 | sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "", |
1009 | sta->flags & WLAN_STA_PS ? " PS" : "", | 1063 | sta->flags & WLAN_STA_PENDING_POLL ? " POLL" : "", |
1010 | sta->flags & WLAN_STA_TIM ? " TIM" : "", | 1064 | sta->capability, sta->listen_interval); |
1011 | sta->flags & WLAN_STA_PERM ? " PERM" : "", | ||
1012 | sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "", | ||
1013 | sta->flags & WLAN_STA_PENDING_POLL ? " POLL" : "", | ||
1014 | sta->capability, sta->listen_interval); | ||
1015 | /* supported_rates: 500 kbit/s units with msb ignored */ | 1065 | /* supported_rates: 500 kbit/s units with msb ignored */ |
1016 | for (i = 0; i < sizeof(sta->supported_rates); i++) | 1066 | for (i = 0; i < sizeof(sta->supported_rates); i++) |
1017 | if (sta->supported_rates[i] != 0) | 1067 | if (sta->supported_rates[i] != 0) |
1018 | p += sprintf(p, "%d%sMbps ", | 1068 | seq_printf(m, "%d%sMbps ", |
1019 | (sta->supported_rates[i] & 0x7f) / 2, | 1069 | (sta->supported_rates[i] & 0x7f) / 2, |
1020 | sta->supported_rates[i] & 1 ? ".5" : ""); | 1070 | sta->supported_rates[i] & 1 ? ".5" : ""); |
1021 | p += sprintf(p, "\njiffies=%lu\nlast_auth=%lu\nlast_assoc=%lu\n" | 1071 | seq_printf(m, |
1022 | "last_rx=%lu\nlast_tx=%lu\nrx_packets=%lu\n" | 1072 | "\njiffies=%lu\nlast_auth=%lu\nlast_assoc=%lu\n" |
1023 | "tx_packets=%lu\n" | 1073 | "last_rx=%lu\nlast_tx=%lu\nrx_packets=%lu\n" |
1024 | "rx_bytes=%lu\ntx_bytes=%lu\nbuffer_count=%d\n" | 1074 | "tx_packets=%lu\n" |
1025 | "last_rx: silence=%d dBm signal=%d dBm rate=%d%s Mbps\n" | 1075 | "rx_bytes=%lu\ntx_bytes=%lu\nbuffer_count=%d\n" |
1026 | "tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n" | 1076 | "last_rx: silence=%d dBm signal=%d dBm rate=%d%s Mbps\n" |
1027 | "tx[11M]=%d\n" | 1077 | "tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n" |
1028 | "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n", | 1078 | "tx[11M]=%d\n" |
1029 | jiffies, sta->last_auth, sta->last_assoc, sta->last_rx, | 1079 | "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n", |
1030 | sta->last_tx, | 1080 | jiffies, sta->last_auth, sta->last_assoc, sta->last_rx, |
1031 | sta->rx_packets, sta->tx_packets, sta->rx_bytes, | 1081 | sta->last_tx, |
1032 | sta->tx_bytes, skb_queue_len(&sta->tx_buf), | 1082 | sta->rx_packets, sta->tx_packets, sta->rx_bytes, |
1033 | sta->last_rx_silence, | 1083 | sta->tx_bytes, skb_queue_len(&sta->tx_buf), |
1034 | sta->last_rx_signal, sta->last_rx_rate / 10, | 1084 | sta->last_rx_silence, |
1035 | sta->last_rx_rate % 10 ? ".5" : "", | 1085 | sta->last_rx_signal, sta->last_rx_rate / 10, |
1036 | sta->tx_rate, sta->tx_count[0], sta->tx_count[1], | 1086 | sta->last_rx_rate % 10 ? ".5" : "", |
1037 | sta->tx_count[2], sta->tx_count[3], sta->rx_count[0], | 1087 | sta->tx_rate, sta->tx_count[0], sta->tx_count[1], |
1038 | sta->rx_count[1], sta->rx_count[2], sta->rx_count[3]); | 1088 | sta->tx_count[2], sta->tx_count[3], sta->rx_count[0], |
1089 | sta->rx_count[1], sta->rx_count[2], sta->rx_count[3]); | ||
1039 | if (sta->crypt && sta->crypt->ops && sta->crypt->ops->print_stats) | 1090 | if (sta->crypt && sta->crypt->ops && sta->crypt->ops->print_stats) |
1040 | p = sta->crypt->ops->print_stats(p, sta->crypt->priv); | 1091 | sta->crypt->ops->print_stats(m, sta->crypt->priv); |
1041 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT | 1092 | #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT |
1042 | if (sta->ap) { | 1093 | if (sta->ap) { |
1043 | if (sta->u.ap.channel >= 0) | 1094 | if (sta->u.ap.channel >= 0) |
1044 | p += sprintf(p, "channel=%d\n", sta->u.ap.channel); | 1095 | seq_printf(m, "channel=%d\n", sta->u.ap.channel); |
1045 | p += sprintf(p, "ssid="); | 1096 | seq_puts(m, "ssid="); |
1046 | for (i = 0; i < sta->u.ap.ssid_len; i++) | 1097 | for (i = 0; i < sta->u.ap.ssid_len; i++) { |
1047 | p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 && | 1098 | if (sta->u.ap.ssid[i] >= 32 && sta->u.ap.ssid[i] < 127) |
1048 | sta->u.ap.ssid[i] < 127) ? | 1099 | seq_putc(m, sta->u.ap.ssid[i]); |
1049 | "%c" : "<%02x>"), | 1100 | else |
1050 | sta->u.ap.ssid[i]); | 1101 | seq_printf(m, "<%02x>", sta->u.ap.ssid[i]); |
1051 | p += sprintf(p, "\n"); | 1102 | } |
1103 | seq_putc(m, '\n'); | ||
1052 | } | 1104 | } |
1053 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ | 1105 | #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ |
1054 | 1106 | ||
1055 | return (p - page); | 1107 | return 0; |
1108 | } | ||
1109 | |||
1110 | static int prism2_sta_proc_open(struct inode *inode, struct file *file) | ||
1111 | { | ||
1112 | return single_open(file, prism2_sta_proc_show, PDE_DATA(inode)); | ||
1056 | } | 1113 | } |
1057 | 1114 | ||
1115 | static const struct file_operations prism2_sta_proc_fops = { | ||
1116 | .open = prism2_sta_proc_open, | ||
1117 | .read = seq_read, | ||
1118 | .llseek = seq_lseek, | ||
1119 | .release = seq_release, | ||
1120 | }; | ||
1058 | 1121 | ||
1059 | static void handle_add_proc_queue(struct work_struct *work) | 1122 | static void handle_add_proc_queue(struct work_struct *work) |
1060 | { | 1123 | { |
@@ -1076,9 +1139,9 @@ static void handle_add_proc_queue(struct work_struct *work) | |||
1076 | 1139 | ||
1077 | if (sta) { | 1140 | if (sta) { |
1078 | sprintf(name, "%pM", sta->addr); | 1141 | sprintf(name, "%pM", sta->addr); |
1079 | sta->proc = create_proc_read_entry( | 1142 | sta->proc = proc_create_data( |
1080 | name, 0, ap->proc, | 1143 | name, 0, ap->proc, |
1081 | prism2_sta_proc_read, sta); | 1144 | &prism2_sta_proc_fops, sta); |
1082 | 1145 | ||
1083 | atomic_dec(&sta->users); | 1146 | atomic_dec(&sta->users); |
1084 | } | 1147 | } |