18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * X.25 Packet Layer release 002 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This is ALPHA test software. This code may break your machine, 68c2ecf20Sopenharmony_ci * randomly fail to work with new releases, misbehave and/or generally 78c2ecf20Sopenharmony_ci * screw up. It might even work. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This code REQUIRES 2.4 with seq_file support 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * History 128c2ecf20Sopenharmony_ci * 2002/10/06 Arnaldo Carvalho de Melo seq_file support 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 178c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 188c2ecf20Sopenharmony_ci#include <linux/export.h> 198c2ecf20Sopenharmony_ci#include <net/net_namespace.h> 208c2ecf20Sopenharmony_ci#include <net/sock.h> 218c2ecf20Sopenharmony_ci#include <net/x25.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic void *x25_seq_route_start(struct seq_file *seq, loff_t *pos) 268c2ecf20Sopenharmony_ci __acquires(x25_route_list_lock) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci read_lock_bh(&x25_route_list_lock); 298c2ecf20Sopenharmony_ci return seq_list_start_head(&x25_route_list, *pos); 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic void *x25_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci return seq_list_next(v, &x25_route_list, pos); 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic void x25_seq_route_stop(struct seq_file *seq, void *v) 388c2ecf20Sopenharmony_ci __releases(x25_route_list_lock) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci read_unlock_bh(&x25_route_list_lock); 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic int x25_seq_route_show(struct seq_file *seq, void *v) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct x25_route *rt = list_entry(v, struct x25_route, node); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (v == &x25_route_list) { 488c2ecf20Sopenharmony_ci seq_puts(seq, "Address Digits Device\n"); 498c2ecf20Sopenharmony_ci goto out; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci rt = v; 538c2ecf20Sopenharmony_ci seq_printf(seq, "%-15s %-6d %-5s\n", 548c2ecf20Sopenharmony_ci rt->address.x25_addr, rt->sigdigits, 558c2ecf20Sopenharmony_ci rt->dev ? rt->dev->name : "???"); 568c2ecf20Sopenharmony_ciout: 578c2ecf20Sopenharmony_ci return 0; 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic void *x25_seq_socket_start(struct seq_file *seq, loff_t *pos) 618c2ecf20Sopenharmony_ci __acquires(x25_list_lock) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci read_lock_bh(&x25_list_lock); 648c2ecf20Sopenharmony_ci return seq_hlist_start_head(&x25_list, *pos); 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic void *x25_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci return seq_hlist_next(v, &x25_list, pos); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic void x25_seq_socket_stop(struct seq_file *seq, void *v) 738c2ecf20Sopenharmony_ci __releases(x25_list_lock) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci read_unlock_bh(&x25_list_lock); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int x25_seq_socket_show(struct seq_file *seq, void *v) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct sock *s; 818c2ecf20Sopenharmony_ci struct x25_sock *x25; 828c2ecf20Sopenharmony_ci struct net_device *dev; 838c2ecf20Sopenharmony_ci const char *devname; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (v == SEQ_START_TOKEN) { 868c2ecf20Sopenharmony_ci seq_printf(seq, "dest_addr src_addr dev lci st vs vr " 878c2ecf20Sopenharmony_ci "va t t2 t21 t22 t23 Snd-Q Rcv-Q inode\n"); 888c2ecf20Sopenharmony_ci goto out; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci s = sk_entry(v); 928c2ecf20Sopenharmony_ci x25 = x25_sk(s); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (!x25->neighbour || (dev = x25->neighbour->dev) == NULL) 958c2ecf20Sopenharmony_ci devname = "???"; 968c2ecf20Sopenharmony_ci else 978c2ecf20Sopenharmony_ci devname = x25->neighbour->dev->name; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci seq_printf(seq, "%-10s %-10s %-5s %3.3X %d %d %d %d %3lu %3lu " 1008c2ecf20Sopenharmony_ci "%3lu %3lu %3lu %5d %5d %ld\n", 1018c2ecf20Sopenharmony_ci !x25->dest_addr.x25_addr[0] ? "*" : x25->dest_addr.x25_addr, 1028c2ecf20Sopenharmony_ci !x25->source_addr.x25_addr[0] ? "*" : x25->source_addr.x25_addr, 1038c2ecf20Sopenharmony_ci devname, x25->lci & 0x0FFF, x25->state, x25->vs, x25->vr, 1048c2ecf20Sopenharmony_ci x25->va, x25_display_timer(s) / HZ, x25->t2 / HZ, 1058c2ecf20Sopenharmony_ci x25->t21 / HZ, x25->t22 / HZ, x25->t23 / HZ, 1068c2ecf20Sopenharmony_ci sk_wmem_alloc_get(s), 1078c2ecf20Sopenharmony_ci sk_rmem_alloc_get(s), 1088c2ecf20Sopenharmony_ci s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L); 1098c2ecf20Sopenharmony_ciout: 1108c2ecf20Sopenharmony_ci return 0; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic void *x25_seq_forward_start(struct seq_file *seq, loff_t *pos) 1148c2ecf20Sopenharmony_ci __acquires(x25_forward_list_lock) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci read_lock_bh(&x25_forward_list_lock); 1178c2ecf20Sopenharmony_ci return seq_list_start_head(&x25_forward_list, *pos); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic void *x25_seq_forward_next(struct seq_file *seq, void *v, loff_t *pos) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci return seq_list_next(v, &x25_forward_list, pos); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic void x25_seq_forward_stop(struct seq_file *seq, void *v) 1268c2ecf20Sopenharmony_ci __releases(x25_forward_list_lock) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci read_unlock_bh(&x25_forward_list_lock); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic int x25_seq_forward_show(struct seq_file *seq, void *v) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct x25_forward *f = list_entry(v, struct x25_forward, node); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (v == &x25_forward_list) { 1368c2ecf20Sopenharmony_ci seq_printf(seq, "lci dev1 dev2\n"); 1378c2ecf20Sopenharmony_ci goto out; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci f = v; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci seq_printf(seq, "%d %-10s %-10s\n", 1438c2ecf20Sopenharmony_ci f->lci, f->dev1->name, f->dev2->name); 1448c2ecf20Sopenharmony_ciout: 1458c2ecf20Sopenharmony_ci return 0; 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic const struct seq_operations x25_seq_route_ops = { 1498c2ecf20Sopenharmony_ci .start = x25_seq_route_start, 1508c2ecf20Sopenharmony_ci .next = x25_seq_route_next, 1518c2ecf20Sopenharmony_ci .stop = x25_seq_route_stop, 1528c2ecf20Sopenharmony_ci .show = x25_seq_route_show, 1538c2ecf20Sopenharmony_ci}; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic const struct seq_operations x25_seq_socket_ops = { 1568c2ecf20Sopenharmony_ci .start = x25_seq_socket_start, 1578c2ecf20Sopenharmony_ci .next = x25_seq_socket_next, 1588c2ecf20Sopenharmony_ci .stop = x25_seq_socket_stop, 1598c2ecf20Sopenharmony_ci .show = x25_seq_socket_show, 1608c2ecf20Sopenharmony_ci}; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic const struct seq_operations x25_seq_forward_ops = { 1638c2ecf20Sopenharmony_ci .start = x25_seq_forward_start, 1648c2ecf20Sopenharmony_ci .next = x25_seq_forward_next, 1658c2ecf20Sopenharmony_ci .stop = x25_seq_forward_stop, 1668c2ecf20Sopenharmony_ci .show = x25_seq_forward_show, 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ciint __init x25_proc_init(void) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci if (!proc_mkdir("x25", init_net.proc_net)) 1728c2ecf20Sopenharmony_ci return -ENOMEM; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci if (!proc_create_seq("x25/route", 0444, init_net.proc_net, 1758c2ecf20Sopenharmony_ci &x25_seq_route_ops)) 1768c2ecf20Sopenharmony_ci goto out; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if (!proc_create_seq("x25/socket", 0444, init_net.proc_net, 1798c2ecf20Sopenharmony_ci &x25_seq_socket_ops)) 1808c2ecf20Sopenharmony_ci goto out; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (!proc_create_seq("x25/forward", 0444, init_net.proc_net, 1838c2ecf20Sopenharmony_ci &x25_seq_forward_ops)) 1848c2ecf20Sopenharmony_ci goto out; 1858c2ecf20Sopenharmony_ci return 0; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ciout: 1888c2ecf20Sopenharmony_ci remove_proc_subtree("x25", init_net.proc_net); 1898c2ecf20Sopenharmony_ci return -ENOMEM; 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_civoid __exit x25_proc_exit(void) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci remove_proc_subtree("x25", init_net.proc_net); 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci#else /* CONFIG_PROC_FS */ 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ciint __init x25_proc_init(void) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci return 0; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_civoid __exit x25_proc_exit(void) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci#endif /* CONFIG_PROC_FS */ 208