llc_proc.c 6.4 KB

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