Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* L2TP subsystem debugfs
0003  *
0004  * Copyright (c) 2010 Katalix Systems Ltd
0005  */
0006 
0007 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0008 
0009 #include <linux/module.h>
0010 #include <linux/skbuff.h>
0011 #include <linux/socket.h>
0012 #include <linux/hash.h>
0013 #include <linux/l2tp.h>
0014 #include <linux/in.h>
0015 #include <linux/etherdevice.h>
0016 #include <linux/spinlock.h>
0017 #include <linux/debugfs.h>
0018 #include <net/sock.h>
0019 #include <net/ip.h>
0020 #include <net/icmp.h>
0021 #include <net/udp.h>
0022 #include <net/inet_common.h>
0023 #include <net/inet_hashtables.h>
0024 #include <net/tcp_states.h>
0025 #include <net/protocol.h>
0026 #include <net/xfrm.h>
0027 #include <net/net_namespace.h>
0028 #include <net/netns/generic.h>
0029 
0030 #include "l2tp_core.h"
0031 
0032 static struct dentry *rootdir;
0033 
0034 struct l2tp_dfs_seq_data {
0035     struct net  *net;
0036     netns_tracker   ns_tracker;
0037     int tunnel_idx;         /* current tunnel */
0038     int session_idx;        /* index of session within current tunnel */
0039     struct l2tp_tunnel *tunnel;
0040     struct l2tp_session *session;   /* NULL means get next tunnel */
0041 };
0042 
0043 static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd)
0044 {
0045     /* Drop reference taken during previous invocation */
0046     if (pd->tunnel)
0047         l2tp_tunnel_dec_refcount(pd->tunnel);
0048 
0049     pd->tunnel = l2tp_tunnel_get_nth(pd->net, pd->tunnel_idx);
0050     pd->tunnel_idx++;
0051 }
0052 
0053 static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd)
0054 {
0055     /* Drop reference taken during previous invocation */
0056     if (pd->session)
0057         l2tp_session_dec_refcount(pd->session);
0058 
0059     pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx);
0060     pd->session_idx++;
0061 
0062     if (!pd->session) {
0063         pd->session_idx = 0;
0064         l2tp_dfs_next_tunnel(pd);
0065     }
0066 }
0067 
0068 static void *l2tp_dfs_seq_start(struct seq_file *m, loff_t *offs)
0069 {
0070     struct l2tp_dfs_seq_data *pd = SEQ_START_TOKEN;
0071     loff_t pos = *offs;
0072 
0073     if (!pos)
0074         goto out;
0075 
0076     if (WARN_ON(!m->private)) {
0077         pd = NULL;
0078         goto out;
0079     }
0080     pd = m->private;
0081 
0082     if (!pd->tunnel)
0083         l2tp_dfs_next_tunnel(pd);
0084     else
0085         l2tp_dfs_next_session(pd);
0086 
0087     /* NULL tunnel and session indicates end of list */
0088     if (!pd->tunnel && !pd->session)
0089         pd = NULL;
0090 
0091 out:
0092     return pd;
0093 }
0094 
0095 static void *l2tp_dfs_seq_next(struct seq_file *m, void *v, loff_t *pos)
0096 {
0097     (*pos)++;
0098     return NULL;
0099 }
0100 
0101 static void l2tp_dfs_seq_stop(struct seq_file *p, void *v)
0102 {
0103     struct l2tp_dfs_seq_data *pd = v;
0104 
0105     if (!pd || pd == SEQ_START_TOKEN)
0106         return;
0107 
0108     /* Drop reference taken by last invocation of l2tp_dfs_next_session()
0109      * or l2tp_dfs_next_tunnel().
0110      */
0111     if (pd->session) {
0112         l2tp_session_dec_refcount(pd->session);
0113         pd->session = NULL;
0114     }
0115     if (pd->tunnel) {
0116         l2tp_tunnel_dec_refcount(pd->tunnel);
0117         pd->tunnel = NULL;
0118     }
0119 }
0120 
0121 static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v)
0122 {
0123     struct l2tp_tunnel *tunnel = v;
0124     struct l2tp_session *session;
0125     int session_count = 0;
0126     int hash;
0127 
0128     rcu_read_lock_bh();
0129     for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
0130         hlist_for_each_entry_rcu(session, &tunnel->session_hlist[hash], hlist) {
0131             /* Session ID of zero is a dummy/reserved value used by pppol2tp */
0132             if (session->session_id == 0)
0133                 continue;
0134 
0135             session_count++;
0136         }
0137     }
0138     rcu_read_unlock_bh();
0139 
0140     seq_printf(m, "\nTUNNEL %u peer %u", tunnel->tunnel_id, tunnel->peer_tunnel_id);
0141     if (tunnel->sock) {
0142         struct inet_sock *inet = inet_sk(tunnel->sock);
0143 
0144 #if IS_ENABLED(CONFIG_IPV6)
0145         if (tunnel->sock->sk_family == AF_INET6) {
0146             const struct ipv6_pinfo *np = inet6_sk(tunnel->sock);
0147 
0148             seq_printf(m, " from %pI6c to %pI6c\n",
0149                    &np->saddr, &tunnel->sock->sk_v6_daddr);
0150         }
0151 #endif
0152         if (tunnel->sock->sk_family == AF_INET)
0153             seq_printf(m, " from %pI4 to %pI4\n",
0154                    &inet->inet_saddr, &inet->inet_daddr);
0155 
0156         if (tunnel->encap == L2TP_ENCAPTYPE_UDP)
0157             seq_printf(m, " source port %hu, dest port %hu\n",
0158                    ntohs(inet->inet_sport), ntohs(inet->inet_dport));
0159     }
0160     seq_printf(m, " L2TPv%d, %s\n", tunnel->version,
0161            tunnel->encap == L2TP_ENCAPTYPE_UDP ? "UDP" :
0162            tunnel->encap == L2TP_ENCAPTYPE_IP ? "IP" :
0163            "");
0164     seq_printf(m, " %d sessions, refcnt %d/%d\n", session_count,
0165            tunnel->sock ? refcount_read(&tunnel->sock->sk_refcnt) : 0,
0166            refcount_read(&tunnel->ref_count));
0167     seq_printf(m, " %08x rx %ld/%ld/%ld rx %ld/%ld/%ld\n",
0168            0,
0169            atomic_long_read(&tunnel->stats.tx_packets),
0170            atomic_long_read(&tunnel->stats.tx_bytes),
0171            atomic_long_read(&tunnel->stats.tx_errors),
0172            atomic_long_read(&tunnel->stats.rx_packets),
0173            atomic_long_read(&tunnel->stats.rx_bytes),
0174            atomic_long_read(&tunnel->stats.rx_errors));
0175 }
0176 
0177 static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v)
0178 {
0179     struct l2tp_session *session = v;
0180 
0181     seq_printf(m, "  SESSION %u, peer %u, %s\n", session->session_id,
0182            session->peer_session_id,
0183            session->pwtype == L2TP_PWTYPE_ETH ? "ETH" :
0184            session->pwtype == L2TP_PWTYPE_PPP ? "PPP" :
0185            "");
0186     if (session->send_seq || session->recv_seq)
0187         seq_printf(m, "   nr %u, ns %u\n", session->nr, session->ns);
0188     seq_printf(m, "   refcnt %d\n", refcount_read(&session->ref_count));
0189     seq_printf(m, "   config 0/0/%c/%c/-/%s %08x %u\n",
0190            session->recv_seq ? 'R' : '-',
0191            session->send_seq ? 'S' : '-',
0192            session->lns_mode ? "LNS" : "LAC",
0193            0,
0194            jiffies_to_msecs(session->reorder_timeout));
0195     seq_printf(m, "   offset 0 l2specific %hu/%d\n",
0196            session->l2specific_type, l2tp_get_l2specific_len(session));
0197     if (session->cookie_len) {
0198         seq_printf(m, "   cookie %02x%02x%02x%02x",
0199                session->cookie[0], session->cookie[1],
0200                session->cookie[2], session->cookie[3]);
0201         if (session->cookie_len == 8)
0202             seq_printf(m, "%02x%02x%02x%02x",
0203                    session->cookie[4], session->cookie[5],
0204                    session->cookie[6], session->cookie[7]);
0205         seq_puts(m, "\n");
0206     }
0207     if (session->peer_cookie_len) {
0208         seq_printf(m, "   peer cookie %02x%02x%02x%02x",
0209                session->peer_cookie[0], session->peer_cookie[1],
0210                session->peer_cookie[2], session->peer_cookie[3]);
0211         if (session->peer_cookie_len == 8)
0212             seq_printf(m, "%02x%02x%02x%02x",
0213                    session->peer_cookie[4], session->peer_cookie[5],
0214                    session->peer_cookie[6], session->peer_cookie[7]);
0215         seq_puts(m, "\n");
0216     }
0217 
0218     seq_printf(m, "   %u/%u tx %ld/%ld/%ld rx %ld/%ld/%ld\n",
0219            session->nr, session->ns,
0220            atomic_long_read(&session->stats.tx_packets),
0221            atomic_long_read(&session->stats.tx_bytes),
0222            atomic_long_read(&session->stats.tx_errors),
0223            atomic_long_read(&session->stats.rx_packets),
0224            atomic_long_read(&session->stats.rx_bytes),
0225            atomic_long_read(&session->stats.rx_errors));
0226 
0227     if (session->show)
0228         session->show(m, session);
0229 }
0230 
0231 static int l2tp_dfs_seq_show(struct seq_file *m, void *v)
0232 {
0233     struct l2tp_dfs_seq_data *pd = v;
0234 
0235     /* display header on line 1 */
0236     if (v == SEQ_START_TOKEN) {
0237         seq_puts(m, "TUNNEL ID, peer ID from IP to IP\n");
0238         seq_puts(m, " L2TPv2/L2TPv3, UDP/IP\n");
0239         seq_puts(m, " sessions session-count, refcnt refcnt/sk->refcnt\n");
0240         seq_puts(m, " debug tx-pkts/bytes/errs rx-pkts/bytes/errs\n");
0241         seq_puts(m, "  SESSION ID, peer ID, PWTYPE\n");
0242         seq_puts(m, "   refcnt cnt\n");
0243         seq_puts(m, "   offset OFFSET l2specific TYPE/LEN\n");
0244         seq_puts(m, "   [ cookie ]\n");
0245         seq_puts(m, "   [ peer cookie ]\n");
0246         seq_puts(m, "   config mtu/mru/rcvseq/sendseq/dataseq/lns debug reorderto\n");
0247         seq_puts(m, "   nr/ns tx-pkts/bytes/errs rx-pkts/bytes/errs\n");
0248         goto out;
0249     }
0250 
0251     if (!pd->session)
0252         l2tp_dfs_seq_tunnel_show(m, pd->tunnel);
0253     else
0254         l2tp_dfs_seq_session_show(m, pd->session);
0255 
0256 out:
0257     return 0;
0258 }
0259 
0260 static const struct seq_operations l2tp_dfs_seq_ops = {
0261     .start      = l2tp_dfs_seq_start,
0262     .next       = l2tp_dfs_seq_next,
0263     .stop       = l2tp_dfs_seq_stop,
0264     .show       = l2tp_dfs_seq_show,
0265 };
0266 
0267 static int l2tp_dfs_seq_open(struct inode *inode, struct file *file)
0268 {
0269     struct l2tp_dfs_seq_data *pd;
0270     struct seq_file *seq;
0271     int rc = -ENOMEM;
0272 
0273     pd = kzalloc(sizeof(*pd), GFP_KERNEL);
0274     if (!pd)
0275         goto out;
0276 
0277     /* Derive the network namespace from the pid opening the
0278      * file.
0279      */
0280     pd->net = get_net_ns_by_pid(current->pid);
0281     if (IS_ERR(pd->net)) {
0282         rc = PTR_ERR(pd->net);
0283         goto err_free_pd;
0284     }
0285     netns_tracker_alloc(pd->net, &pd->ns_tracker, GFP_KERNEL);
0286     rc = seq_open(file, &l2tp_dfs_seq_ops);
0287     if (rc)
0288         goto err_free_net;
0289 
0290     seq = file->private_data;
0291     seq->private = pd;
0292 
0293 out:
0294     return rc;
0295 
0296 err_free_net:
0297     put_net_track(pd->net, &pd->ns_tracker);
0298 err_free_pd:
0299     kfree(pd);
0300     goto out;
0301 }
0302 
0303 static int l2tp_dfs_seq_release(struct inode *inode, struct file *file)
0304 {
0305     struct l2tp_dfs_seq_data *pd;
0306     struct seq_file *seq;
0307 
0308     seq = file->private_data;
0309     pd = seq->private;
0310     if (pd->net)
0311         put_net_track(pd->net, &pd->ns_tracker);
0312     kfree(pd);
0313     seq_release(inode, file);
0314 
0315     return 0;
0316 }
0317 
0318 static const struct file_operations l2tp_dfs_fops = {
0319     .owner      = THIS_MODULE,
0320     .open       = l2tp_dfs_seq_open,
0321     .read       = seq_read,
0322     .llseek     = seq_lseek,
0323     .release    = l2tp_dfs_seq_release,
0324 };
0325 
0326 static int __init l2tp_debugfs_init(void)
0327 {
0328     rootdir = debugfs_create_dir("l2tp", NULL);
0329 
0330     debugfs_create_file("tunnels", 0600, rootdir, NULL, &l2tp_dfs_fops);
0331 
0332     pr_info("L2TP debugfs support\n");
0333 
0334     return 0;
0335 }
0336 
0337 static void __exit l2tp_debugfs_exit(void)
0338 {
0339     debugfs_remove_recursive(rootdir);
0340 }
0341 
0342 module_init(l2tp_debugfs_init);
0343 module_exit(l2tp_debugfs_exit);
0344 
0345 MODULE_LICENSE("GPL");
0346 MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
0347 MODULE_DESCRIPTION("L2TP debugfs driver");
0348 MODULE_VERSION("1.0");