1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * X.25 Packet Layer release 002
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This is ALPHA test software. This code may break your machine,
6*4882a593Smuzhiyun * randomly fail to work with new releases, misbehave and/or generally
7*4882a593Smuzhiyun * screw up. It might even work.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This code REQUIRES 2.4 with seq_file support
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * History
12*4882a593Smuzhiyun * 2002/10/06 Arnaldo Carvalho de Melo seq_file support
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/init.h>
16*4882a593Smuzhiyun #include <linux/proc_fs.h>
17*4882a593Smuzhiyun #include <linux/seq_file.h>
18*4882a593Smuzhiyun #include <linux/export.h>
19*4882a593Smuzhiyun #include <net/net_namespace.h>
20*4882a593Smuzhiyun #include <net/sock.h>
21*4882a593Smuzhiyun #include <net/x25.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #ifdef CONFIG_PROC_FS
24*4882a593Smuzhiyun
x25_seq_route_start(struct seq_file * seq,loff_t * pos)25*4882a593Smuzhiyun static void *x25_seq_route_start(struct seq_file *seq, loff_t *pos)
26*4882a593Smuzhiyun __acquires(x25_route_list_lock)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun read_lock_bh(&x25_route_list_lock);
29*4882a593Smuzhiyun return seq_list_start_head(&x25_route_list, *pos);
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun
x25_seq_route_next(struct seq_file * seq,void * v,loff_t * pos)32*4882a593Smuzhiyun static void *x25_seq_route_next(struct seq_file *seq, void *v, loff_t *pos)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun return seq_list_next(v, &x25_route_list, pos);
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun
x25_seq_route_stop(struct seq_file * seq,void * v)37*4882a593Smuzhiyun static void x25_seq_route_stop(struct seq_file *seq, void *v)
38*4882a593Smuzhiyun __releases(x25_route_list_lock)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun read_unlock_bh(&x25_route_list_lock);
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
x25_seq_route_show(struct seq_file * seq,void * v)43*4882a593Smuzhiyun static int x25_seq_route_show(struct seq_file *seq, void *v)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun struct x25_route *rt = list_entry(v, struct x25_route, node);
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun if (v == &x25_route_list) {
48*4882a593Smuzhiyun seq_puts(seq, "Address Digits Device\n");
49*4882a593Smuzhiyun goto out;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun rt = v;
53*4882a593Smuzhiyun seq_printf(seq, "%-15s %-6d %-5s\n",
54*4882a593Smuzhiyun rt->address.x25_addr, rt->sigdigits,
55*4882a593Smuzhiyun rt->dev ? rt->dev->name : "???");
56*4882a593Smuzhiyun out:
57*4882a593Smuzhiyun return 0;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
x25_seq_socket_start(struct seq_file * seq,loff_t * pos)60*4882a593Smuzhiyun static void *x25_seq_socket_start(struct seq_file *seq, loff_t *pos)
61*4882a593Smuzhiyun __acquires(x25_list_lock)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun read_lock_bh(&x25_list_lock);
64*4882a593Smuzhiyun return seq_hlist_start_head(&x25_list, *pos);
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
x25_seq_socket_next(struct seq_file * seq,void * v,loff_t * pos)67*4882a593Smuzhiyun static void *x25_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun return seq_hlist_next(v, &x25_list, pos);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
x25_seq_socket_stop(struct seq_file * seq,void * v)72*4882a593Smuzhiyun static void x25_seq_socket_stop(struct seq_file *seq, void *v)
73*4882a593Smuzhiyun __releases(x25_list_lock)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun read_unlock_bh(&x25_list_lock);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
x25_seq_socket_show(struct seq_file * seq,void * v)78*4882a593Smuzhiyun static int x25_seq_socket_show(struct seq_file *seq, void *v)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun struct sock *s;
81*4882a593Smuzhiyun struct x25_sock *x25;
82*4882a593Smuzhiyun struct net_device *dev;
83*4882a593Smuzhiyun const char *devname;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun if (v == SEQ_START_TOKEN) {
86*4882a593Smuzhiyun seq_printf(seq, "dest_addr src_addr dev lci st vs vr "
87*4882a593Smuzhiyun "va t t2 t21 t22 t23 Snd-Q Rcv-Q inode\n");
88*4882a593Smuzhiyun goto out;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun s = sk_entry(v);
92*4882a593Smuzhiyun x25 = x25_sk(s);
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (!x25->neighbour || (dev = x25->neighbour->dev) == NULL)
95*4882a593Smuzhiyun devname = "???";
96*4882a593Smuzhiyun else
97*4882a593Smuzhiyun devname = x25->neighbour->dev->name;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun seq_printf(seq, "%-10s %-10s %-5s %3.3X %d %d %d %d %3lu %3lu "
100*4882a593Smuzhiyun "%3lu %3lu %3lu %5d %5d %ld\n",
101*4882a593Smuzhiyun !x25->dest_addr.x25_addr[0] ? "*" : x25->dest_addr.x25_addr,
102*4882a593Smuzhiyun !x25->source_addr.x25_addr[0] ? "*" : x25->source_addr.x25_addr,
103*4882a593Smuzhiyun devname, x25->lci & 0x0FFF, x25->state, x25->vs, x25->vr,
104*4882a593Smuzhiyun x25->va, x25_display_timer(s) / HZ, x25->t2 / HZ,
105*4882a593Smuzhiyun x25->t21 / HZ, x25->t22 / HZ, x25->t23 / HZ,
106*4882a593Smuzhiyun sk_wmem_alloc_get(s),
107*4882a593Smuzhiyun sk_rmem_alloc_get(s),
108*4882a593Smuzhiyun s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L);
109*4882a593Smuzhiyun out:
110*4882a593Smuzhiyun return 0;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
x25_seq_forward_start(struct seq_file * seq,loff_t * pos)113*4882a593Smuzhiyun static void *x25_seq_forward_start(struct seq_file *seq, loff_t *pos)
114*4882a593Smuzhiyun __acquires(x25_forward_list_lock)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun read_lock_bh(&x25_forward_list_lock);
117*4882a593Smuzhiyun return seq_list_start_head(&x25_forward_list, *pos);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
x25_seq_forward_next(struct seq_file * seq,void * v,loff_t * pos)120*4882a593Smuzhiyun static void *x25_seq_forward_next(struct seq_file *seq, void *v, loff_t *pos)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun return seq_list_next(v, &x25_forward_list, pos);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
x25_seq_forward_stop(struct seq_file * seq,void * v)125*4882a593Smuzhiyun static void x25_seq_forward_stop(struct seq_file *seq, void *v)
126*4882a593Smuzhiyun __releases(x25_forward_list_lock)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun read_unlock_bh(&x25_forward_list_lock);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
x25_seq_forward_show(struct seq_file * seq,void * v)131*4882a593Smuzhiyun static int x25_seq_forward_show(struct seq_file *seq, void *v)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun struct x25_forward *f = list_entry(v, struct x25_forward, node);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun if (v == &x25_forward_list) {
136*4882a593Smuzhiyun seq_printf(seq, "lci dev1 dev2\n");
137*4882a593Smuzhiyun goto out;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun f = v;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun seq_printf(seq, "%d %-10s %-10s\n",
143*4882a593Smuzhiyun f->lci, f->dev1->name, f->dev2->name);
144*4882a593Smuzhiyun out:
145*4882a593Smuzhiyun return 0;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun static const struct seq_operations x25_seq_route_ops = {
149*4882a593Smuzhiyun .start = x25_seq_route_start,
150*4882a593Smuzhiyun .next = x25_seq_route_next,
151*4882a593Smuzhiyun .stop = x25_seq_route_stop,
152*4882a593Smuzhiyun .show = x25_seq_route_show,
153*4882a593Smuzhiyun };
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun static const struct seq_operations x25_seq_socket_ops = {
156*4882a593Smuzhiyun .start = x25_seq_socket_start,
157*4882a593Smuzhiyun .next = x25_seq_socket_next,
158*4882a593Smuzhiyun .stop = x25_seq_socket_stop,
159*4882a593Smuzhiyun .show = x25_seq_socket_show,
160*4882a593Smuzhiyun };
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun static const struct seq_operations x25_seq_forward_ops = {
163*4882a593Smuzhiyun .start = x25_seq_forward_start,
164*4882a593Smuzhiyun .next = x25_seq_forward_next,
165*4882a593Smuzhiyun .stop = x25_seq_forward_stop,
166*4882a593Smuzhiyun .show = x25_seq_forward_show,
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun
x25_proc_init(void)169*4882a593Smuzhiyun int __init x25_proc_init(void)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun if (!proc_mkdir("x25", init_net.proc_net))
172*4882a593Smuzhiyun return -ENOMEM;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (!proc_create_seq("x25/route", 0444, init_net.proc_net,
175*4882a593Smuzhiyun &x25_seq_route_ops))
176*4882a593Smuzhiyun goto out;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun if (!proc_create_seq("x25/socket", 0444, init_net.proc_net,
179*4882a593Smuzhiyun &x25_seq_socket_ops))
180*4882a593Smuzhiyun goto out;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun if (!proc_create_seq("x25/forward", 0444, init_net.proc_net,
183*4882a593Smuzhiyun &x25_seq_forward_ops))
184*4882a593Smuzhiyun goto out;
185*4882a593Smuzhiyun return 0;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun out:
188*4882a593Smuzhiyun remove_proc_subtree("x25", init_net.proc_net);
189*4882a593Smuzhiyun return -ENOMEM;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
x25_proc_exit(void)192*4882a593Smuzhiyun void __exit x25_proc_exit(void)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun remove_proc_subtree("x25", init_net.proc_net);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun #else /* CONFIG_PROC_FS */
198*4882a593Smuzhiyun
x25_proc_init(void)199*4882a593Smuzhiyun int __init x25_proc_init(void)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun return 0;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
x25_proc_exit(void)204*4882a593Smuzhiyun void __exit x25_proc_exit(void)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun #endif /* CONFIG_PROC_FS */
208