llc_proc.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * proc_llc.c - proc interface for LLC
  3. *
  4. * Copyright (c) 2001 by Jay Schulist <jschlst@samba.org>
  5. * 2002-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  6. *
  7. * This program can be redistributed or modified under the terms of the
  8. * GNU General Public License as published by the Free Software Foundation.
  9. * This program is distributed without any warranty or implied warranty
  10. * of merchantability or fitness for a particular purpose.
  11. *
  12. * See the GNU General Public License for more details.
  13. */
  14. #include <linux/init.h>
  15. #include <linux/kernel.h>
  16. #include <linux/proc_fs.h>
  17. #include <linux/errno.h>
  18. #include <linux/seq_file.h>
  19. #include <net/net_namespace.h>
  20. #include <net/sock.h>
  21. #include <net/llc.h>
  22. #include <net/llc_c_ac.h>
  23. #include <net/llc_c_ev.h>
  24. #include <net/llc_c_st.h>
  25. #include <net/llc_conn.h>
  26. static void llc_ui_format_mac(struct seq_file *seq, u8 *addr)
  27. {
  28. DECLARE_MAC_BUF(mac);
  29. seq_printf(seq, "%s", print_mac(mac, addr));
  30. }
  31. static struct sock *llc_get_sk_idx(loff_t pos)
  32. {
  33. struct list_head *sap_entry;
  34. struct llc_sap *sap;
  35. struct hlist_node *node;
  36. struct sock *sk = NULL;
  37. list_for_each(sap_entry, &llc_sap_list) {
  38. sap = list_entry(sap_entry, struct llc_sap, node);
  39. read_lock_bh(&sap->sk_list.lock);
  40. sk_for_each(sk, node, &sap->sk_list.list) {
  41. if (!pos)
  42. goto found;
  43. --pos;
  44. }
  45. read_unlock_bh(&sap->sk_list.lock);
  46. }
  47. sk = NULL;
  48. found:
  49. return sk;
  50. }
  51. static void *llc_seq_start(struct seq_file *seq, loff_t *pos)
  52. {
  53. loff_t l = *pos;
  54. read_lock_bh(&llc_sap_list_lock);
  55. return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN;
  56. }
  57. static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  58. {
  59. struct sock* sk, *next;
  60. struct llc_sock *llc;
  61. struct llc_sap *sap;
  62. ++*pos;
  63. if (v == SEQ_START_TOKEN) {
  64. sk = llc_get_sk_idx(0);
  65. goto out;
  66. }
  67. sk = v;
  68. next = sk_next(sk);
  69. if (next) {
  70. sk = next;
  71. goto out;
  72. }
  73. llc = llc_sk(sk);
  74. sap = llc->sap;
  75. read_unlock_bh(&sap->sk_list.lock);
  76. sk = NULL;
  77. for (;;) {
  78. if (sap->node.next == &llc_sap_list)
  79. break;
  80. sap = list_entry(sap->node.next, struct llc_sap, node);
  81. read_lock_bh(&sap->sk_list.lock);
  82. if (!hlist_empty(&sap->sk_list.list)) {
  83. sk = sk_head(&sap->sk_list.list);
  84. break;
  85. }
  86. read_unlock_bh(&sap->sk_list.lock);
  87. }
  88. out:
  89. return sk;
  90. }
  91. static void llc_seq_stop(struct seq_file *seq, void *v)
  92. {
  93. if (v && v != SEQ_START_TOKEN) {
  94. struct sock *sk = v;
  95. struct llc_sock *llc = llc_sk(sk);
  96. struct llc_sap *sap = llc->sap;
  97. read_unlock_bh(&sap->sk_list.lock);
  98. }
  99. read_unlock_bh(&llc_sap_list_lock);
  100. }
  101. static int llc_seq_socket_show(struct seq_file *seq, void *v)
  102. {
  103. struct sock* sk;
  104. struct llc_sock *llc;
  105. if (v == SEQ_START_TOKEN) {
  106. seq_puts(seq, "SKt Mc local_mac_sap remote_mac_sap "
  107. " tx_queue rx_queue st uid link\n");
  108. goto out;
  109. }
  110. sk = v;
  111. llc = llc_sk(sk);
  112. /* FIXME: check if the address is multicast */
  113. seq_printf(seq, "%2X %2X ", sk->sk_type, 0);
  114. if (llc->dev)
  115. llc_ui_format_mac(seq, llc->dev->dev_addr);
  116. else {
  117. u8 addr[6] = {0,0,0,0,0,0};
  118. llc_ui_format_mac(seq, addr);
  119. }
  120. seq_printf(seq, "@%02X ", llc->sap->laddr.lsap);
  121. llc_ui_format_mac(seq, llc->daddr.mac);
  122. seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap,
  123. atomic_read(&sk->sk_wmem_alloc),
  124. atomic_read(&sk->sk_rmem_alloc) - llc->copied_seq,
  125. sk->sk_state,
  126. sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1,
  127. llc->link);
  128. out:
  129. return 0;
  130. }
  131. static char *llc_conn_state_names[] = {
  132. [LLC_CONN_STATE_ADM] = "adm",
  133. [LLC_CONN_STATE_SETUP] = "setup",
  134. [LLC_CONN_STATE_NORMAL] = "normal",
  135. [LLC_CONN_STATE_BUSY] = "busy",
  136. [LLC_CONN_STATE_REJ] = "rej",
  137. [LLC_CONN_STATE_AWAIT] = "await",
  138. [LLC_CONN_STATE_AWAIT_BUSY] = "await_busy",
  139. [LLC_CONN_STATE_AWAIT_REJ] = "await_rej",
  140. [LLC_CONN_STATE_D_CONN] = "d_conn",
  141. [LLC_CONN_STATE_RESET] = "reset",
  142. [LLC_CONN_STATE_ERROR] = "error",
  143. [LLC_CONN_STATE_TEMP] = "temp",
  144. };
  145. static int llc_seq_core_show(struct seq_file *seq, void *v)
  146. {
  147. struct sock* sk;
  148. struct llc_sock *llc;
  149. if (v == SEQ_START_TOKEN) {
  150. seq_puts(seq, "Connection list:\n"
  151. "dsap state retr txw rxw pf ff sf df rs cs "
  152. "tack tpfc trs tbs blog busr\n");
  153. goto out;
  154. }
  155. sk = v;
  156. llc = llc_sk(sk);
  157. seq_printf(seq, " %02X %-10s %3d %3d %3d %2d %2d %2d %2d %2d %2d "
  158. "%4d %4d %3d %3d %4d %4d\n",
  159. llc->daddr.lsap, llc_conn_state_names[llc->state],
  160. llc->retry_count, llc->k, llc->rw, llc->p_flag, llc->f_flag,
  161. llc->s_flag, llc->data_flag, llc->remote_busy_flag,
  162. llc->cause_flag, timer_pending(&llc->ack_timer.timer),
  163. timer_pending(&llc->pf_cycle_timer.timer),
  164. timer_pending(&llc->rej_sent_timer.timer),
  165. timer_pending(&llc->busy_state_timer.timer),
  166. !!sk->sk_backlog.tail, !!sock_owned_by_user(sk));
  167. out:
  168. return 0;
  169. }
  170. static const struct seq_operations llc_seq_socket_ops = {
  171. .start = llc_seq_start,
  172. .next = llc_seq_next,
  173. .stop = llc_seq_stop,
  174. .show = llc_seq_socket_show,
  175. };
  176. static const struct seq_operations llc_seq_core_ops = {
  177. .start = llc_seq_start,
  178. .next = llc_seq_next,
  179. .stop = llc_seq_stop,
  180. .show = llc_seq_core_show,
  181. };
  182. static int llc_seq_socket_open(struct inode *inode, struct file *file)
  183. {
  184. return seq_open(file, &llc_seq_socket_ops);
  185. }
  186. static int llc_seq_core_open(struct inode *inode, struct file *file)
  187. {
  188. return seq_open(file, &llc_seq_core_ops);
  189. }
  190. static const struct file_operations llc_seq_socket_fops = {
  191. .owner = THIS_MODULE,
  192. .open = llc_seq_socket_open,
  193. .read = seq_read,
  194. .llseek = seq_lseek,
  195. .release = seq_release,
  196. };
  197. static const struct file_operations llc_seq_core_fops = {
  198. .owner = THIS_MODULE,
  199. .open = llc_seq_core_open,
  200. .read = seq_read,
  201. .llseek = seq_lseek,
  202. .release = seq_release,
  203. };
  204. static struct proc_dir_entry *llc_proc_dir;
  205. int __init llc_proc_init(void)
  206. {
  207. int rc = -ENOMEM;
  208. struct proc_dir_entry *p;
  209. llc_proc_dir = proc_mkdir("llc", init_net.proc_net);
  210. if (!llc_proc_dir)
  211. goto out;
  212. llc_proc_dir->owner = THIS_MODULE;
  213. p = proc_create("socket", S_IRUGO, llc_proc_dir, &llc_seq_socket_fops);
  214. if (!p)
  215. goto out_socket;
  216. p = proc_create("core", S_IRUGO, llc_proc_dir, &llc_seq_core_fops);
  217. if (!p)
  218. goto out_core;
  219. rc = 0;
  220. out:
  221. return rc;
  222. out_core:
  223. remove_proc_entry("socket", llc_proc_dir);
  224. out_socket:
  225. remove_proc_entry("llc", init_net.proc_net);
  226. goto out;
  227. }
  228. void llc_proc_exit(void)
  229. {
  230. remove_proc_entry("socket", llc_proc_dir);
  231. remove_proc_entry("core", llc_proc_dir);
  232. remove_proc_entry("llc", init_net.proc_net);
  233. }