llc_proc.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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/config.h>
  15. #include <linux/init.h>
  16. #include <linux/kernel.h>
  17. #include <linux/proc_fs.h>
  18. #include <linux/errno.h>
  19. #include <linux/seq_file.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, unsigned char *mac)
  27. {
  28. seq_printf(seq, "%02X:%02X:%02X:%02X:%02X:%02X",
  29. mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  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. seq_printf(seq, "00:00:00:00:00:00");
  118. seq_printf(seq, "@%02X ", llc->sap->laddr.lsap);
  119. llc_ui_format_mac(seq, llc->daddr.mac);
  120. seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap,
  121. atomic_read(&sk->sk_wmem_alloc),
  122. atomic_read(&sk->sk_rmem_alloc),
  123. sk->sk_state,
  124. sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1,
  125. llc->link);
  126. out:
  127. return 0;
  128. }
  129. static char *llc_conn_state_names[] = {
  130. [LLC_CONN_STATE_ADM] = "adm",
  131. [LLC_CONN_STATE_SETUP] = "setup",
  132. [LLC_CONN_STATE_NORMAL] = "normal",
  133. [LLC_CONN_STATE_BUSY] = "busy",
  134. [LLC_CONN_STATE_REJ] = "rej",
  135. [LLC_CONN_STATE_AWAIT] = "await",
  136. [LLC_CONN_STATE_AWAIT_BUSY] = "await_busy",
  137. [LLC_CONN_STATE_AWAIT_REJ] = "await_rej",
  138. [LLC_CONN_STATE_D_CONN] = "d_conn",
  139. [LLC_CONN_STATE_RESET] = "reset",
  140. [LLC_CONN_STATE_ERROR] = "error",
  141. [LLC_CONN_STATE_TEMP] = "temp",
  142. };
  143. static int llc_seq_core_show(struct seq_file *seq, void *v)
  144. {
  145. struct sock* sk;
  146. struct llc_sock *llc;
  147. if (v == SEQ_START_TOKEN) {
  148. seq_puts(seq, "Connection list:\n"
  149. "dsap state retr txw rxw pf ff sf df rs cs "
  150. "tack tpfc trs tbs blog busr\n");
  151. goto out;
  152. }
  153. sk = v;
  154. llc = llc_sk(sk);
  155. seq_printf(seq, " %02X %-10s %3d %3d %3d %2d %2d %2d %2d %2d %2d "
  156. "%4d %4d %3d %3d %4d %4d\n",
  157. llc->daddr.lsap, llc_conn_state_names[llc->state],
  158. llc->retry_count, llc->k, llc->rw, llc->p_flag, llc->f_flag,
  159. llc->s_flag, llc->data_flag, llc->remote_busy_flag,
  160. llc->cause_flag, timer_pending(&llc->ack_timer.timer),
  161. timer_pending(&llc->pf_cycle_timer.timer),
  162. timer_pending(&llc->rej_sent_timer.timer),
  163. timer_pending(&llc->busy_state_timer.timer),
  164. !!sk->sk_backlog.tail, !!sock_owned_by_user(sk));
  165. out:
  166. return 0;
  167. }
  168. static struct seq_operations llc_seq_socket_ops = {
  169. .start = llc_seq_start,
  170. .next = llc_seq_next,
  171. .stop = llc_seq_stop,
  172. .show = llc_seq_socket_show,
  173. };
  174. static struct seq_operations llc_seq_core_ops = {
  175. .start = llc_seq_start,
  176. .next = llc_seq_next,
  177. .stop = llc_seq_stop,
  178. .show = llc_seq_core_show,
  179. };
  180. static int llc_seq_socket_open(struct inode *inode, struct file *file)
  181. {
  182. return seq_open(file, &llc_seq_socket_ops);
  183. }
  184. static int llc_seq_core_open(struct inode *inode, struct file *file)
  185. {
  186. return seq_open(file, &llc_seq_core_ops);
  187. }
  188. static struct file_operations llc_seq_socket_fops = {
  189. .owner = THIS_MODULE,
  190. .open = llc_seq_socket_open,
  191. .read = seq_read,
  192. .llseek = seq_lseek,
  193. .release = seq_release,
  194. };
  195. static struct file_operations llc_seq_core_fops = {
  196. .owner = THIS_MODULE,
  197. .open = llc_seq_core_open,
  198. .read = seq_read,
  199. .llseek = seq_lseek,
  200. .release = seq_release,
  201. };
  202. static struct proc_dir_entry *llc_proc_dir;
  203. int __init llc_proc_init(void)
  204. {
  205. int rc = -ENOMEM;
  206. struct proc_dir_entry *p;
  207. llc_proc_dir = proc_mkdir("llc", proc_net);
  208. if (!llc_proc_dir)
  209. goto out;
  210. llc_proc_dir->owner = THIS_MODULE;
  211. p = create_proc_entry("socket", S_IRUGO, llc_proc_dir);
  212. if (!p)
  213. goto out_socket;
  214. p->proc_fops = &llc_seq_socket_fops;
  215. p = create_proc_entry("core", S_IRUGO, llc_proc_dir);
  216. if (!p)
  217. goto out_core;
  218. p->proc_fops = &llc_seq_core_fops;
  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", 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", proc_net);
  233. }