2005-04-17 02:20:36 +04:00
/*
* proc_llc . c - proc interface for LLC
*
* Copyright ( c ) 2001 by Jay Schulist < jschlst @ samba . org >
* 2002 - 2003 by Arnaldo Carvalho de Melo < acme @ conectiva . com . br >
*
* This program can be redistributed or modified under the terms of the
* GNU General Public License as published by the Free Software Foundation .
* This program is distributed without any warranty or implied warranty
* of merchantability or fitness for a particular purpose .
*
* See the GNU General Public License for more details .
*/
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/proc_fs.h>
# include <linux/errno.h>
# include <linux/seq_file.h>
2011-07-15 19:47:34 +04:00
# include <linux/export.h>
2007-09-12 14:01:34 +04:00
# include <net/net_namespace.h>
2005-04-17 02:20:36 +04:00
# include <net/sock.h>
# include <net/llc.h>
# include <net/llc_c_ac.h>
# include <net/llc_c_ev.h>
# include <net/llc_c_st.h>
# include <net/llc_conn.h>
2021-10-12 18:58:37 +03:00
static void llc_ui_format_mac ( struct seq_file * seq , const u8 * addr )
2005-04-17 02:20:36 +04:00
{
2008-10-28 01:59:26 +03:00
seq_printf ( seq , " %pM " , addr ) ;
2005-04-17 02:20:36 +04:00
}
static struct sock * llc_get_sk_idx ( loff_t pos )
{
struct llc_sap * sap ;
struct sock * sk = NULL ;
2009-12-26 14:51:05 +03:00
int i ;
2005-04-17 02:20:36 +04:00
2009-12-26 14:51:06 +03:00
list_for_each_entry_rcu ( sap , & llc_sap_list , node ) {
2009-12-26 14:51:02 +03:00
spin_lock_bh ( & sap - > sk_lock ) ;
2009-12-26 14:51:05 +03:00
for ( i = 0 ; i < LLC_SK_LADDR_HASH_ENTRIES ; i + + ) {
struct hlist_nulls_head * head = & sap - > sk_laddr_hash [ i ] ;
struct hlist_nulls_node * node ;
sk_nulls_for_each ( sk , node , head ) {
if ( ! pos )
goto found ; /* keep the lock */
- - pos ;
}
2005-04-17 02:20:36 +04:00
}
2009-12-26 14:51:02 +03:00
spin_unlock_bh ( & sap - > sk_lock ) ;
2005-04-17 02:20:36 +04:00
}
sk = NULL ;
found :
return sk ;
}
2020-02-24 02:16:48 +03:00
static void * llc_seq_start ( struct seq_file * seq , loff_t * pos ) __acquires ( RCU )
2005-04-17 02:20:36 +04:00
{
loff_t l = * pos ;
2009-12-26 14:51:06 +03:00
rcu_read_lock_bh ( ) ;
2005-04-17 02:20:36 +04:00
return l ? llc_get_sk_idx ( - - l ) : SEQ_START_TOKEN ;
}
2009-12-26 14:51:05 +03:00
static struct sock * laddr_hash_next ( struct llc_sap * sap , int bucket )
{
struct hlist_nulls_node * node ;
struct sock * sk = NULL ;
while ( + + bucket < LLC_SK_LADDR_HASH_ENTRIES )
sk_nulls_for_each ( sk , node , & sap - > sk_laddr_hash [ bucket ] )
goto out ;
out :
return sk ;
}
2005-04-17 02:20:36 +04:00
static void * llc_seq_next ( struct seq_file * seq , void * v , loff_t * pos )
{
struct sock * sk , * next ;
struct llc_sock * llc ;
struct llc_sap * sap ;
+ + * pos ;
if ( v = = SEQ_START_TOKEN ) {
sk = llc_get_sk_idx ( 0 ) ;
goto out ;
}
sk = v ;
2009-12-26 14:51:02 +03:00
next = sk_nulls_next ( sk ) ;
2005-04-17 02:20:36 +04:00
if ( next ) {
sk = next ;
goto out ;
}
llc = llc_sk ( sk ) ;
sap = llc - > sap ;
2009-12-26 14:51:05 +03:00
sk = laddr_hash_next ( sap , llc_sk_laddr_hashfn ( sap , & llc - > laddr ) ) ;
if ( sk )
goto out ;
2009-12-26 14:51:02 +03:00
spin_unlock_bh ( & sap - > sk_lock ) ;
2009-12-26 14:51:06 +03:00
list_for_each_entry_continue_rcu ( sap , & llc_sap_list , node ) {
2009-12-26 14:51:02 +03:00
spin_lock_bh ( & sap - > sk_lock ) ;
2009-12-26 14:51:05 +03:00
sk = laddr_hash_next ( sap , - 1 ) ;
if ( sk )
break ; /* keep the lock */
2009-12-26 14:51:02 +03:00
spin_unlock_bh ( & sap - > sk_lock ) ;
2005-04-17 02:20:36 +04:00
}
out :
return sk ;
}
static void llc_seq_stop ( struct seq_file * seq , void * v )
{
if ( v & & v ! = SEQ_START_TOKEN ) {
struct sock * sk = v ;
struct llc_sock * llc = llc_sk ( sk ) ;
struct llc_sap * sap = llc - > sap ;
2009-12-26 14:51:02 +03:00
spin_unlock_bh ( & sap - > sk_lock ) ;
2005-04-17 02:20:36 +04:00
}
2009-12-26 14:51:06 +03:00
rcu_read_unlock_bh ( ) ;
2005-04-17 02:20:36 +04:00
}
static int llc_seq_socket_show ( struct seq_file * seq , void * v )
{
struct sock * sk ;
struct llc_sock * llc ;
if ( v = = SEQ_START_TOKEN ) {
seq_puts ( seq , " SKt Mc local_mac_sap remote_mac_sap "
" tx_queue rx_queue st uid link \n " ) ;
goto out ;
}
sk = v ;
llc = llc_sk ( sk ) ;
/* FIXME: check if the address is multicast */
seq_printf ( seq , " %2X %2X " , sk - > sk_type , 0 ) ;
if ( llc - > dev )
llc_ui_format_mac ( seq , llc - > dev - > dev_addr ) ;
2007-10-04 04:59:30 +04:00
else {
u8 addr [ 6 ] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
llc_ui_format_mac ( seq , addr ) ;
}
2005-04-17 02:20:36 +04:00
seq_printf ( seq , " @%02X " , llc - > sap - > laddr . lsap ) ;
llc_ui_format_mac ( seq , llc - > daddr . mac ) ;
2013-08-15 15:42:14 +04:00
seq_printf ( seq , " @%02X %8d %8d %2d %3u %4d \n " , llc - > daddr . lsap ,
2009-06-18 06:05:41 +04:00
sk_wmem_alloc_get ( sk ) ,
sk_rmem_alloc_get ( sk ) - llc - > copied_seq ,
2005-04-17 02:20:36 +04:00
sk - > sk_state ,
2012-05-24 11:10:10 +04:00
from_kuid_munged ( seq_user_ns ( seq ) , sock_i_uid ( sk ) ) ,
2005-04-17 02:20:36 +04:00
llc - > link ) ;
out :
return 0 ;
}
2009-08-05 21:42:58 +04:00
static const char * const llc_conn_state_names [ ] = {
2007-02-09 17:25:01 +03:00
[ LLC_CONN_STATE_ADM ] = " adm " ,
[ LLC_CONN_STATE_SETUP ] = " setup " ,
2005-04-17 02:20:36 +04:00
[ LLC_CONN_STATE_NORMAL ] = " normal " ,
2007-02-09 17:25:01 +03:00
[ LLC_CONN_STATE_BUSY ] = " busy " ,
[ LLC_CONN_STATE_REJ ] = " rej " ,
[ LLC_CONN_STATE_AWAIT ] = " await " ,
2005-04-17 02:20:36 +04:00
[ LLC_CONN_STATE_AWAIT_BUSY ] = " await_busy " ,
[ LLC_CONN_STATE_AWAIT_REJ ] = " await_rej " ,
[ LLC_CONN_STATE_D_CONN ] = " d_conn " ,
2007-02-09 17:25:01 +03:00
[ LLC_CONN_STATE_RESET ] = " reset " ,
[ LLC_CONN_STATE_ERROR ] = " error " ,
[ LLC_CONN_STATE_TEMP ] = " temp " ,
2005-04-17 02:20:36 +04:00
} ;
static int llc_seq_core_show ( struct seq_file * seq , void * v )
{
struct sock * sk ;
struct llc_sock * llc ;
if ( v = = SEQ_START_TOKEN ) {
seq_puts ( seq , " Connection list: \n "
" dsap state retr txw rxw pf ff sf df rs cs "
" tack tpfc trs tbs blog busr \n " ) ;
goto out ;
}
sk = v ;
llc = llc_sk ( sk ) ;
seq_printf ( seq , " %02X %-10s %3d %3d %3d %2d %2d %2d %2d %2d %2d "
" %4d %4d %3d %3d %4d %4d \n " ,
llc - > daddr . lsap , llc_conn_state_names [ llc - > state ] ,
llc - > retry_count , llc - > k , llc - > rw , llc - > p_flag , llc - > f_flag ,
llc - > s_flag , llc - > data_flag , llc - > remote_busy_flag ,
llc - > cause_flag , timer_pending ( & llc - > ack_timer . timer ) ,
timer_pending ( & llc - > pf_cycle_timer . timer ) ,
timer_pending ( & llc - > rej_sent_timer . timer ) ,
timer_pending ( & llc - > busy_state_timer . timer ) ,
2021-12-08 09:21:58 +03:00
! ! sk - > sk_backlog . tail , sock_owned_by_user_nocheck ( sk ) ) ;
2005-04-17 02:20:36 +04:00
out :
return 0 ;
}
2007-07-11 10:07:31 +04:00
static const struct seq_operations llc_seq_socket_ops = {
2005-04-17 02:20:36 +04:00
. start = llc_seq_start ,
. next = llc_seq_next ,
. stop = llc_seq_stop ,
. show = llc_seq_socket_show ,
} ;
2007-07-11 10:07:31 +04:00
static const struct seq_operations llc_seq_core_ops = {
2005-04-17 02:20:36 +04:00
. start = llc_seq_start ,
. next = llc_seq_next ,
. stop = llc_seq_stop ,
. show = llc_seq_core_show ,
} ;
static struct proc_dir_entry * llc_proc_dir ;
int __init llc_proc_init ( void )
{
int rc = - ENOMEM ;
struct proc_dir_entry * p ;
2007-09-12 14:01:34 +04:00
llc_proc_dir = proc_mkdir ( " llc " , init_net . proc_net ) ;
2005-04-17 02:20:36 +04:00
if ( ! llc_proc_dir )
goto out ;
2018-04-13 20:44:18 +03:00
p = proc_create_seq ( " socket " , 0444 , llc_proc_dir , & llc_seq_socket_ops ) ;
2005-04-17 02:20:36 +04:00
if ( ! p )
goto out_socket ;
2018-04-13 20:44:18 +03:00
p = proc_create_seq ( " core " , 0444 , llc_proc_dir , & llc_seq_core_ops ) ;
2005-04-17 02:20:36 +04:00
if ( ! p )
goto out_core ;
rc = 0 ;
out :
return rc ;
out_core :
remove_proc_entry ( " socket " , llc_proc_dir ) ;
out_socket :
2007-09-12 14:01:34 +04:00
remove_proc_entry ( " llc " , init_net . proc_net ) ;
2005-04-17 02:20:36 +04:00
goto out ;
}
void llc_proc_exit ( void )
{
remove_proc_entry ( " socket " , llc_proc_dir ) ;
remove_proc_entry ( " core " , llc_proc_dir ) ;
2007-09-12 14:01:34 +04:00
remove_proc_entry ( " llc " , init_net . proc_net ) ;
2005-04-17 02:20:36 +04:00
}