Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
0e80ab36
Commit
0e80ab36
authored
Nov 25, 2002
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/home/acme/BK/net-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents
5b47557d
b53a0ade
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
596 additions
and
289 deletions
+596
-289
include/linux/mroute.h
include/linux/mroute.h
+2
-0
net/core/dev.c
net/core/dev.c
+163
-98
net/core/wireless.c
net/core/wireless.c
+64
-66
net/ipv4/af_inet.c
net/ipv4/af_inet.c
+4
-5
net/ipv4/raw.c
net/ipv4/raw.c
+1
-0
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_ipv4.c
+362
-120
No files found.
include/linux/mroute.h
View file @
0e80ab36
...
...
@@ -126,6 +126,8 @@ struct igmpmsg
*/
#ifdef __KERNEL__
#include <net/sock.h>
extern
int
ip_mroute_setsockopt
(
struct
sock
*
,
int
,
char
*
,
int
);
extern
int
ip_mroute_getsockopt
(
struct
sock
*
,
int
,
char
*
,
int
*
);
extern
int
ipmr_ioctl
(
struct
sock
*
sk
,
int
cmd
,
unsigned
long
arg
);
...
...
net/core/dev.c
View file @
0e80ab36
...
...
@@ -94,6 +94,7 @@
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/if_bridge.h>
#include <linux/divert.h>
...
...
@@ -114,6 +115,7 @@
extern
int
plip_init
(
void
);
#endif
#include <asm/current.h>
/* This define, if set, will randomly drop a packet when congestion
* is more than moderate. It helps fairness in the multi-interface
...
...
@@ -1719,128 +1721,196 @@ static int dev_ifconf(char *arg)
return
copy_to_user
(
arg
,
&
ifc
,
sizeof
(
struct
ifconf
))
?
-
EFAULT
:
0
;
}
#ifdef CONFIG_PROC_FS
/*
* This is invoked by the /proc filesystem handler to display a device
* in detail.
*/
static
__inline__
struct
net_device
*
dev_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
struct
net_device
*
dev
;
loff_t
i
;
#ifdef CONFIG_PROC_FS
for
(
i
=
0
,
dev
=
dev_base
;
dev
&&
i
<
pos
;
dev
=
dev
->
next
);
return
i
==
pos
?
dev
:
NULL
;
}
void
*
dev_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
read_lock
(
&
dev_base_lock
);
return
*
pos
?
dev_get_idx
(
seq
,
*
pos
)
:
(
void
*
)
1
;
}
static
int
sprintf_stats
(
char
*
buffer
,
struct
net_device
*
dev
)
void
*
dev_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
return
v
==
(
void
*
)
1
?
dev_base
:
((
struct
net_device
*
)
v
)
->
next
;
}
void
dev_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
read_unlock
(
&
dev_base_lock
);
}
static
void
dev_seq_printf_stats
(
struct
seq_file
*
seq
,
struct
net_device
*
dev
)
{
struct
net_device_stats
*
stats
=
dev
->
get_stats
?
dev
->
get_stats
(
dev
)
:
NULL
;
int
size
;
if
(
stats
)
size
=
sprintf
(
buffer
,
"%6s:%8lu %7lu %4lu %4lu %4lu %5lu "
"%10lu %9lu %8lu %7lu %4lu %4lu %4lu "
"%5lu %7lu %10lu
\n
"
,
dev
->
name
,
stats
->
rx_bytes
,
stats
->
rx_packets
,
stats
->
rx_errors
,
seq_printf
(
seq
,
"%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
"%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu
\n
"
,
dev
->
name
,
stats
->
rx_bytes
,
stats
->
rx_packets
,
stats
->
rx_errors
,
stats
->
rx_dropped
+
stats
->
rx_missed_errors
,
stats
->
rx_fifo_errors
,
stats
->
rx_length_errors
+
stats
->
rx_over_errors
+
stats
->
rx_crc_errors
+
stats
->
rx_frame_errors
,
stats
->
rx_compressed
,
stats
->
multicast
,
stats
->
tx_byte
s
,
stats
->
tx_packets
,
stats
->
tx_errors
,
stats
->
tx_dropped
,
stats
->
tx_bytes
,
stats
->
tx_packet
s
,
stats
->
tx_errors
,
stats
->
tx_dropped
,
stats
->
tx_fifo_errors
,
stats
->
collisions
,
stats
->
tx_carrier_errors
+
stats
->
tx_aborted_errors
+
stats
->
tx_window_errors
+
stats
->
tx_heartbeat_errors
,
stats
->
tx_carrier_errors
+
stats
->
tx_aborted_errors
+
stats
->
tx_window_errors
+
stats
->
tx_heartbeat_errors
,
stats
->
tx_compressed
);
else
size
=
sprintf
(
buffer
,
"%6s: No statistics available.
\n
"
,
dev
->
name
);
return
size
;
seq_printf
(
seq
,
"%6s: No statistics available.
\n
"
,
dev
->
name
);
}
/*
* Called from the PROCfs module. This now uses the new arbitrary sized
* /proc/net interface to create /proc/net/dev
*/
static
int
dev_
get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
int
dev_
seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
int
len
=
0
;
off_t
begin
=
0
;
off_t
pos
=
0
;
int
size
;
struct
net_device
*
dev
;
if
(
v
==
(
void
*
)
1
)
seq_printf
(
seq
,
"Inter-| Receive "
" | Transmit
\n
"
" face |bytes packets errs drop fifo frame "
"compressed multicast|bytes packets errs "
"drop fifo colls carrier compressed
\n
"
);
else
dev_seq_printf_stats
(
seq
,
v
);
return
0
;
}
size
=
sprintf
(
buffer
,
"Inter-| Receive | Transmit
\n
"
" face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
\n
"
)
;
static
struct
netif_rx_stats
*
softnet_get_online
(
loff_t
*
pos
)
{
struct
netif_rx_stats
*
rc
=
NULL
;
pos
+=
size
;
len
+=
size
;
while
(
*
pos
<
NR_CPUS
)
if
(
cpu_online
(
*
pos
))
{
rc
=
&
netdev_rx_stat
[
*
pos
];
break
;
}
else
++*
pos
;
return
rc
;
}
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
size
=
sprintf_stats
(
buffer
+
len
,
dev
);
len
+=
size
;
pos
=
begin
+
len
;
static
void
*
softnet_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
return
softnet_get_online
(
pos
);
}
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
}
if
(
pos
>
offset
+
length
)
break
;
}
read_unlock
(
&
dev_base_lock
);
static
void
*
softnet_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
++*
pos
;
return
softnet_get_online
(
pos
);
}
*
start
=
buffer
+
(
offset
-
begin
);
/* Start of wanted data */
len
-=
offset
-
begin
;
/* Start slop */
if
(
len
>
length
)
len
=
length
;
/* Ending slop */
if
(
len
<
0
)
len
=
0
;
return
len
;
static
void
softnet_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
}
static
int
dev_proc_stats
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
*
eof
,
void
*
data
)
static
int
softnet_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
int
i
;
int
len
=
0
;
struct
netif_rx_stats
*
s
=
v
;
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
{
if
(
!
cpu_online
(
i
))
continue
;
len
+=
sprintf
(
buffer
+
len
,
"%08x %08x %08x %08x %08x %08x "
"%08x %08x %08x
\n
"
,
netdev_rx_stat
[
i
].
total
,
netdev_rx_stat
[
i
].
dropped
,
netdev_rx_stat
[
i
].
time_squeeze
,
netdev_rx_stat
[
i
].
throttled
,
netdev_rx_stat
[
i
].
fastroute_hit
,
netdev_rx_stat
[
i
].
fastroute_success
,
netdev_rx_stat
[
i
].
fastroute_defer
,
netdev_rx_stat
[
i
].
fastroute_deferred_out
,
seq_printf
(
seq
,
"%08x %08x %08x %08x %08x %08x %08x %08x %08x
\n
"
,
s
->
total
,
s
->
dropped
,
s
->
time_squeeze
,
s
->
throttled
,
s
->
fastroute_hit
,
s
->
fastroute_success
,
s
->
fastroute_defer
,
s
->
fastroute_deferred_out
,
#if 0
netdev_rx_stat[i].
fastroute_latency_reduction
s->
fastroute_latency_reduction
#else
netdev_rx_stat
[
i
].
cpu_collision
s
->
cpu_collision
#endif
);
}
return
0
;
}
static
struct
seq_operations
dev_seq_ops
=
{
.
start
=
dev_seq_start
,
.
next
=
dev_seq_next
,
.
stop
=
dev_seq_stop
,
.
show
=
dev_seq_show
,
};
len
-=
offset
;
static
int
dev_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
dev_seq_ops
);
}
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
static
struct
file_operations
dev_seq_fops
=
{
.
open
=
dev_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
};
*
start
=
buffer
+
offset
;
*
eof
=
1
;
static
struct
seq_operations
softnet_seq_ops
=
{
.
start
=
softnet_seq_start
,
.
next
=
softnet_seq_next
,
.
stop
=
softnet_seq_stop
,
.
show
=
softnet_seq_show
,
};
return
len
;
static
int
softnet_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
softnet_seq_ops
);
}
static
struct
file_operations
softnet_seq_fops
=
{
.
open
=
softnet_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
};
#ifdef WIRELESS_EXT
extern
int
wireless_proc_init
(
void
);
#else
#define wireless_proc_init() 0
#endif
static
int
__init
dev_proc_init
(
void
)
{
struct
proc_dir_entry
*
p
;
int
rc
=
-
ENOMEM
;
p
=
create_proc_entry
(
"dev"
,
S_IRUGO
,
proc_net
);
if
(
!
p
)
goto
out
;
p
->
proc_fops
=
&
dev_seq_fops
;
p
=
create_proc_entry
(
"softnet_stat"
,
S_IRUGO
,
proc_net
);
if
(
!
p
)
goto
out_dev
;
p
->
proc_fops
=
&
softnet_seq_fops
;
if
(
wireless_proc_init
())
goto
out_softnet
;
rc
=
0
;
out:
return
rc
;
out_softnet:
remove_proc_entry
(
"softnet_stat"
,
proc_net
);
out_dev:
remove_proc_entry
(
"dev"
,
proc_net
);
goto
out
;
}
#else
#define dev_proc_init() 0
#endif
/* CONFIG_PROC_FS */
...
...
@@ -2680,10 +2750,13 @@ extern void dv_init(void);
static
int
__init
net_dev_init
(
void
)
{
struct
net_device
*
dev
,
**
dp
;
int
i
;
int
i
,
rc
=
-
ENOMEM
;
BUG_ON
(
!
dev_boot_phase
);
if
(
dev_proc_init
())
goto
out
;
#ifdef CONFIG_NET_DIVERT
dv_init
();
#endif
/* CONFIG_NET_DIVERT */
...
...
@@ -2787,15 +2860,6 @@ static int __init net_dev_init(void)
}
}
#ifdef CONFIG_PROC_FS
proc_net_create
(
"dev"
,
0
,
dev_get_info
);
create_proc_read_entry
(
"net/softnet_stat"
,
0
,
0
,
dev_proc_stats
,
NULL
);
#ifdef WIRELESS_EXT
/* Available in net/core/wireless.c */
proc_net_create
(
"wireless"
,
0
,
dev_get_wireless_info
);
#endif
/* WIRELESS_EXT */
#endif
/* CONFIG_PROC_FS */
dev_boot_phase
=
0
;
open_softirq
(
NET_TX_SOFTIRQ
,
net_tx_action
,
NULL
);
...
...
@@ -2812,8 +2876,9 @@ static int __init net_dev_init(void)
*/
net_device_init
();
return
0
;
rc
=
0
;
out:
return
rc
;
}
subsys_initcall
(
net_dev_init
);
...
...
net/core/wireless.c
View file @
0e80ab36
...
...
@@ -47,15 +47,18 @@
/***************************** INCLUDES *****************************/
#include <asm/uaccess.h>
/* copy_to_user() */
#include <linux/config.h>
/* Not needed ??? */
#include <linux/types.h>
/* off_t */
#include <linux/netdevice.h>
/* struct ifreq, dev_get_by_name() */
#include <linux/proc_fs.h>
#include <linux/rtnetlink.h>
/* rtnetlink stuff */
#include <linux/seq_file.h>
#include <linux/wireless.h>
/* Pretty obvious */
#include <net/iw_handler.h>
/* New driver API */
#include <asm/uaccess.h>
/* copy_to_user() */
/**************************** CONSTANTS ****************************/
/* Enough lenience, let's make sure things are proper... */
...
...
@@ -330,83 +333,78 @@ static inline int get_priv_size(__u16 args)
/*
* Print one entry (line) of /proc/net/wireless
*/
static
inline
int
sprintf_wireless_stats
(
char
*
buffer
,
struct
net_device
*
dev
)
static
__inline__
void
wireless_seq_printf_stats
(
struct
seq_file
*
seq
,
struct
net_device
*
dev
)
{
/* Get stats from the driver */
struct
iw_statistics
*
stats
;
int
size
;
struct
iw_statistics
*
stats
=
get_wireless_stats
(
dev
);
stats
=
get_wireless_stats
(
dev
);
if
(
stats
!=
(
struct
iw_statistics
*
)
NULL
)
{
size
=
sprintf
(
buffer
,
"%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d %6d %6d %6d
\n
"
,
dev
->
name
,
stats
->
status
,
stats
->
qual
.
qual
,
if
(
stats
)
{
seq_printf
(
seq
,
"%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d "
"%6d %6d %6d
\n
"
,
dev
->
name
,
stats
->
status
,
stats
->
qual
.
qual
,
stats
->
qual
.
updated
&
1
?
'.'
:
' '
,
((
__u8
)
stats
->
qual
.
level
),
stats
->
qual
.
updated
&
2
?
'.'
:
' '
,
((
__u8
)
stats
->
qual
.
noise
),
stats
->
qual
.
updated
&
4
?
'.'
:
' '
,
stats
->
discard
.
nwid
,
stats
->
discard
.
code
,
stats
->
discard
.
fragment
,
stats
->
discard
.
retries
,
stats
->
discard
.
misc
,
stats
->
miss
.
beacon
);
stats
->
discard
.
nwid
,
stats
->
discard
.
code
,
stats
->
discard
.
fragment
,
stats
->
discard
.
retries
,
stats
->
discard
.
misc
,
stats
->
miss
.
beacon
);
stats
->
qual
.
updated
=
0
;
}
else
size
=
0
;
return
size
;
}
/* ---------------------------------------------------------------- */
/*
* Print info for /proc/net/wireless (print all entries)
*/
int
dev_get_wireless_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
int
wireless_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
int
len
=
0
;
off_t
begin
=
0
;
off_t
pos
=
0
;
int
size
;
struct
net_device
*
dev
;
size
=
sprintf
(
buffer
,
"Inter-| sta-| Quality | Discarded packets | Missed
\n
"
" face | tus | link level noise | nwid crypt frag retry misc | beacon
\n
"
);
pos
+=
size
;
len
+=
size
;
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
!=
NULL
;
dev
=
dev
->
next
)
{
size
=
sprintf_wireless_stats
(
buffer
+
len
,
dev
);
len
+=
size
;
pos
=
begin
+
len
;
if
(
pos
<
offset
)
{
len
=
0
;
begin
=
pos
;
}
if
(
pos
>
offset
+
length
)
break
;
}
read_unlock
(
&
dev_base_lock
);
if
(
v
==
(
void
*
)
1
)
seq_printf
(
seq
,
"Inter-| sta-| Quality | Discarded "
"packets | Missed
\n
"
" face | tus | link level noise | nwid "
"crypt frag retry misc | beacon
\n
"
);
else
wireless_seq_printf_stats
(
seq
,
v
);
return
0
;
}
*
start
=
buffer
+
(
offset
-
begin
);
/* Start of wanted data */
len
-=
(
offset
-
begin
);
/* Start slop */
if
(
len
>
length
)
len
=
length
;
/* Ending slop */
if
(
len
<
0
)
len
=
0
;
extern
void
*
dev_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
);
extern
void
*
dev_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
);
extern
void
dev_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
);
return
len
;
static
struct
seq_operations
wireless_seq_ops
=
{
.
start
=
dev_seq_start
,
.
next
=
dev_seq_next
,
.
stop
=
dev_seq_stop
,
.
show
=
wireless_seq_show
,
};
static
int
wireless_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
wireless_seq_ops
);
}
static
struct
file_operations
wireless_seq_fops
=
{
.
open
=
wireless_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
};
int
__init
wireless_proc_init
(
void
)
{
struct
proc_dir_entry
*
p
;
int
rc
=
0
;
p
=
create_proc_entry
(
"wireless"
,
S_IRUGO
,
proc_net
);
if
(
p
)
p
->
proc_fops
=
&
wireless_seq_fops
;
else
rc
=
-
ENOMEM
;
return
rc
;
}
#endif
/* CONFIG_PROC_FS */
...
...
net/ipv4/af_inet.c
View file @
0e80ab36
...
...
@@ -103,8 +103,6 @@
#include <net/tcp.h>
#include <net/udp.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/sock.h>
#include <net/raw.h>
#include <net/icmp.h>
...
...
@@ -1165,7 +1163,8 @@ extern void fib_proc_exit(void);
extern
int
ip_misc_proc_init
(
void
);
extern
int
raw_proc_init
(
void
);
extern
void
raw_proc_exit
(
void
);
extern
int
tcp_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
);
extern
int
tcp_proc_init
(
void
);
extern
void
tcp_proc_exit
(
void
);
extern
int
udp_proc_init
(
void
);
extern
void
udp_proc_exit
(
void
);
...
...
@@ -1175,7 +1174,7 @@ int __init ipv4_proc_init(void)
if
(
raw_proc_init
())
goto
out_raw
;
if
(
!
proc_net_create
(
"tcp"
,
0
,
tcp_get_info
))
if
(
tcp_proc_init
(
))
goto
out_tcp
;
if
(
udp_proc_init
())
goto
out_udp
;
...
...
@@ -1190,7 +1189,7 @@ int __init ipv4_proc_init(void)
out_fib:
udp_proc_exit
();
out_udp:
proc_net_remove
(
"tcp"
);
tcp_proc_exit
(
);
out_tcp:
raw_proc_exit
();
out_raw:
...
...
net/ipv4/raw.c
View file @
0e80ab36
...
...
@@ -55,6 +55,7 @@
#include <linux/sockios.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/mroute.h>
#include <linux/netdevice.h>
#include <linux/in_route.h>
#include <linux/route.h>
...
...
net/ipv4/tcp_ipv4.c
View file @
0e80ab36
...
...
@@ -69,6 +69,8 @@
#include <linux/inet.h>
#include <linux/ipv6.h>
#include <linux/stddef.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
extern
int
sysctl_ip_dynaddr
;
extern
int
sysctl_ip_default_ttl
;
...
...
@@ -2131,7 +2133,295 @@ static int tcp_v4_destroy_sock(struct sock *sk)
return
0
;
}
#ifdef CONFIG_PROC_FS
/* Proc filesystem TCP sock list dumping. */
enum
tcp_seq_states
{
TCP_SEQ_STATE_LISTENING
,
TCP_SEQ_STATE_OPENREQ
,
TCP_SEQ_STATE_ESTABLISHED
,
TCP_SEQ_STATE_TIME_WAIT
,
};
struct
tcp_iter_state
{
enum
tcp_seq_states
state
;
struct
sock
*
syn_wait_sk
;
int
bucket
,
sbucket
,
num
,
uid
;
};
static
void
*
listening_get_first
(
struct
seq_file
*
seq
)
{
struct
tcp_iter_state
*
st
=
seq
->
private
;
void
*
rc
=
NULL
;
for
(
st
->
bucket
=
0
;
st
->
bucket
<
TCP_LHTABLE_SIZE
;
++
st
->
bucket
)
{
struct
open_request
*
req
;
struct
tcp_opt
*
tp
;
struct
sock
*
sk
=
tcp_listening_hash
[
st
->
bucket
];
if
(
!
sk
)
continue
;
++
st
->
num
;
if
(
TCP_INET_FAMILY
(
sk
->
family
))
{
rc
=
sk
;
goto
out
;
}
tp
=
tcp_sk
(
sk
);
read_lock_bh
(
&
tp
->
syn_wait_lock
);
if
(
tp
->
listen_opt
&&
tp
->
listen_opt
->
qlen
)
{
st
->
uid
=
sock_i_uid
(
sk
);
st
->
syn_wait_sk
=
sk
;
st
->
state
=
TCP_SEQ_STATE_OPENREQ
;
for
(
st
->
sbucket
=
0
;
st
->
sbucket
<
TCP_SYNQ_HSIZE
;
++
st
->
sbucket
)
{
for
(
req
=
tp
->
listen_opt
->
syn_table
[
st
->
sbucket
];
req
;
req
=
req
->
dl_next
,
++
st
->
num
)
{
if
(
!
TCP_INET_FAMILY
(
req
->
class
->
family
))
continue
;
rc
=
req
;
goto
out
;
}
}
st
->
state
=
TCP_SEQ_STATE_LISTENING
;
}
read_unlock_bh
(
&
tp
->
syn_wait_lock
);
}
out:
return
rc
;
}
static
void
*
listening_get_next
(
struct
seq_file
*
seq
,
void
*
cur
)
{
struct
tcp_opt
*
tp
;
struct
sock
*
sk
=
cur
;
struct
tcp_iter_state
*
st
=
seq
->
private
;
if
(
st
->
state
==
TCP_SEQ_STATE_OPENREQ
)
{
struct
open_request
*
req
=
cur
;
tp
=
tcp_sk
(
st
->
syn_wait_sk
);
req
=
req
->
dl_next
;
while
(
1
)
{
while
(
req
)
{
++
st
->
num
;
if
(
TCP_INET_FAMILY
(
req
->
class
->
family
))
{
cur
=
req
;
goto
out
;
}
req
=
req
->
dl_next
;
}
if
(
++
st
->
sbucket
>=
TCP_SYNQ_HSIZE
)
break
;
get_req:
req
=
tp
->
listen_opt
->
syn_table
[
st
->
sbucket
];
}
sk
=
st
->
syn_wait_sk
->
next
;
st
->
state
=
TCP_SEQ_STATE_LISTENING
;
read_unlock_bh
(
&
tp
->
syn_wait_lock
);
}
else
sk
=
sk
->
next
;
get_sk:
while
(
sk
)
{
if
(
TCP_INET_FAMILY
(
sk
->
family
))
{
cur
=
sk
;
goto
out
;
}
tp
=
tcp_sk
(
sk
);
read_lock_bh
(
&
tp
->
syn_wait_lock
);
if
(
tp
->
listen_opt
&&
tp
->
listen_opt
->
qlen
)
{
st
->
uid
=
sock_i_uid
(
sk
);
st
->
syn_wait_sk
=
sk
;
st
->
state
=
TCP_SEQ_STATE_OPENREQ
;
st
->
sbucket
=
0
;
goto
get_req
;
}
read_unlock_bh
(
&
tp
->
syn_wait_lock
);
}
if
(
++
st
->
bucket
<
TCP_LHTABLE_SIZE
)
{
sk
=
tcp_listening_hash
[
st
->
bucket
];
goto
get_sk
;
}
cur
=
NULL
;
out:
return
cur
;
}
static
void
*
listening_get_idx
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
void
*
rc
=
listening_get_first
(
seq
);
if
(
rc
)
while
(
*
pos
&&
(
rc
=
listening_get_next
(
seq
,
rc
)))
--*
pos
;
return
*
pos
?
NULL
:
rc
;
}
static
void
*
established_get_first
(
struct
seq_file
*
seq
)
{
struct
tcp_iter_state
*
st
=
seq
->
private
;
void
*
rc
=
NULL
;
for
(
st
->
bucket
=
0
;
st
->
bucket
<
tcp_ehash_size
;
++
st
->
bucket
)
{
struct
sock
*
sk
;
struct
tcp_tw_bucket
*
tw
;
read_lock
(
&
tcp_ehash
[
st
->
bucket
].
lock
);
for
(
sk
=
tcp_ehash
[
st
->
bucket
].
chain
;
sk
;
sk
=
sk
->
next
,
++
st
->
num
)
{
if
(
!
TCP_INET_FAMILY
(
sk
->
family
))
continue
;
rc
=
sk
;
goto
out
;
}
st
->
state
=
TCP_SEQ_STATE_TIME_WAIT
;
for
(
tw
=
(
struct
tcp_tw_bucket
*
)
tcp_ehash
[
st
->
bucket
+
tcp_ehash_size
].
chain
;
tw
;
tw
=
(
struct
tcp_tw_bucket
*
)
tw
->
next
,
++
st
->
num
)
{
if
(
!
TCP_INET_FAMILY
(
tw
->
family
))
continue
;
rc
=
tw
;
goto
out
;
}
read_unlock
(
&
tcp_ehash
[
st
->
bucket
].
lock
);
st
->
state
=
TCP_SEQ_STATE_ESTABLISHED
;
}
out:
return
rc
;
}
static
void
*
established_get_next
(
struct
seq_file
*
seq
,
void
*
cur
)
{
struct
sock
*
sk
=
cur
;
struct
tcp_tw_bucket
*
tw
;
struct
tcp_iter_state
*
st
=
seq
->
private
;
if
(
st
->
state
==
TCP_SEQ_STATE_TIME_WAIT
)
{
tw
=
cur
;
tw
=
(
struct
tcp_tw_bucket
*
)
tw
->
next
;
get_tw:
while
(
tw
&&
!
TCP_INET_FAMILY
(
tw
->
family
))
{
++
st
->
num
;
tw
=
(
struct
tcp_tw_bucket
*
)
tw
->
next
;
}
if
(
tw
)
{
cur
=
tw
;
goto
out
;
}
read_unlock
(
&
tcp_ehash
[
st
->
bucket
].
lock
);
st
->
state
=
TCP_SEQ_STATE_ESTABLISHED
;
if
(
++
st
->
bucket
<
tcp_ehash_size
)
{
read_lock
(
&
tcp_ehash
[
st
->
bucket
].
lock
);
sk
=
tcp_ehash
[
st
->
bucket
].
chain
;
}
else
{
cur
=
NULL
;
goto
out
;
}
}
else
sk
=
sk
->
next
;
while
(
sk
&&
!
TCP_INET_FAMILY
(
sk
->
family
))
{
++
st
->
num
;
sk
=
sk
->
next
;
}
if
(
!
sk
)
{
st
->
state
=
TCP_SEQ_STATE_TIME_WAIT
;
tw
=
(
struct
tcp_tw_bucket
*
)
tcp_ehash
[
st
->
bucket
+
tcp_ehash_size
].
chain
;
goto
get_tw
;
}
cur
=
sk
;
out:
return
cur
;
}
static
void
*
established_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
void
*
rc
=
established_get_first
(
seq
);
if
(
rc
)
while
(
pos
&&
(
rc
=
established_get_next
(
seq
,
rc
)))
--
pos
;
return
pos
?
NULL
:
rc
;
}
static
void
*
tcp_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
void
*
rc
;
struct
tcp_iter_state
*
st
=
seq
->
private
;
tcp_listen_lock
();
st
->
state
=
TCP_SEQ_STATE_LISTENING
;
rc
=
listening_get_idx
(
seq
,
&
pos
);
if
(
!
rc
)
{
tcp_listen_unlock
();
local_bh_disable
();
st
->
state
=
TCP_SEQ_STATE_ESTABLISHED
;
rc
=
established_get_idx
(
seq
,
pos
);
}
return
rc
;
}
static
void
*
tcp_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
return
*
pos
?
tcp_get_idx
(
seq
,
*
pos
-
1
)
:
(
void
*
)
1
;
}
static
void
*
tcp_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
void
*
rc
=
NULL
;
struct
tcp_iter_state
*
st
;
if
(
v
==
(
void
*
)
1
)
{
rc
=
tcp_get_idx
(
seq
,
0
);
goto
out
;
}
st
=
seq
->
private
;
switch
(
st
->
state
)
{
case
TCP_SEQ_STATE_OPENREQ
:
case
TCP_SEQ_STATE_LISTENING
:
rc
=
listening_get_next
(
seq
,
v
);
if
(
!
rc
)
{
tcp_listen_unlock
();
local_bh_disable
();
st
->
state
=
TCP_SEQ_STATE_ESTABLISHED
;
rc
=
established_get_first
(
seq
);
}
break
;
case
TCP_SEQ_STATE_ESTABLISHED
:
case
TCP_SEQ_STATE_TIME_WAIT
:
rc
=
established_get_next
(
seq
,
v
);
break
;
}
out:
++*
pos
;
return
rc
;
}
static
void
tcp_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
tcp_iter_state
*
st
=
seq
->
private
;
switch
(
st
->
state
)
{
case
TCP_SEQ_STATE_OPENREQ
:
if
(
v
)
{
struct
tcp_opt
*
tp
=
tcp_sk
(
st
->
syn_wait_sk
);
read_unlock_bh
(
&
tp
->
syn_wait_lock
);
}
case
TCP_SEQ_STATE_LISTENING
:
tcp_listen_unlock
();
break
;
case
TCP_SEQ_STATE_TIME_WAIT
:
case
TCP_SEQ_STATE_ESTABLISHED
:
if
(
v
)
read_unlock
(
&
tcp_ehash
[
st
->
bucket
].
lock
);
local_bh_enable
();
break
;
}
}
static
void
get_openreq
(
struct
sock
*
sk
,
struct
open_request
*
req
,
char
*
tmpbuf
,
int
i
,
int
uid
)
{
...
...
@@ -2219,137 +2509,89 @@ static void get_timewait_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
#define TMPSZ 150
int
tcp_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
int
tcp_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
int
len
=
0
,
num
=
0
,
i
;
off_t
begin
,
pos
=
0
;
struct
tcp_iter_state
*
st
;
char
tmpbuf
[
TMPSZ
+
1
];
if
(
offset
<
TMPSZ
)
len
+=
sprintf
(
buffer
,
"%-*s
\n
"
,
TMPSZ
-
1
,
if
(
v
==
(
void
*
)
1
)
{
seq_printf
(
seq
,
"%-*s
\n
"
,
TMPSZ
-
1
,
" sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
"inode"
);
pos
=
TMPSZ
;
/* First, walk listening socket table. */
tcp_listen_lock
();
for
(
i
=
0
;
i
<
TCP_LHTABLE_SIZE
;
i
++
)
{
struct
sock
*
sk
;
struct
tcp_listen_opt
*
lopt
;
int
k
;
for
(
sk
=
tcp_listening_hash
[
i
];
sk
;
sk
=
sk
->
next
,
num
++
)
{
struct
open_request
*
req
;
int
uid
;
struct
tcp_opt
*
tp
=
tcp_sk
(
sk
);
if
(
!
TCP_INET_FAMILY
(
sk
->
family
))
goto
skip_listen
;
pos
+=
TMPSZ
;
if
(
pos
>=
offset
)
{
get_tcp_sock
(
sk
,
tmpbuf
,
num
);
len
+=
sprintf
(
buffer
+
len
,
"%-*s
\n
"
,
TMPSZ
-
1
,
tmpbuf
);
if
(
pos
>=
offset
+
length
)
{
tcp_listen_unlock
();
goto
out_no_bh
;
}
}
skip_listen:
uid
=
sock_i_uid
(
sk
);
read_lock_bh
(
&
tp
->
syn_wait_lock
);
lopt
=
tp
->
listen_opt
;
if
(
lopt
&&
lopt
->
qlen
)
{
for
(
k
=
0
;
k
<
TCP_SYNQ_HSIZE
;
k
++
)
{
for
(
req
=
lopt
->
syn_table
[
k
];
req
;
req
=
req
->
dl_next
,
num
++
)
{
if
(
!
TCP_INET_FAMILY
(
req
->
class
->
family
))
continue
;
pos
+=
TMPSZ
;
if
(
pos
<=
offset
)
continue
;
get_openreq
(
sk
,
req
,
tmpbuf
,
num
,
uid
);
len
+=
sprintf
(
buffer
+
len
,
"%-*s
\n
"
,
TMPSZ
-
1
,
tmpbuf
);
if
(
pos
>=
offset
+
length
)
{
read_unlock_bh
(
&
tp
->
syn_wait_lock
);
tcp_listen_unlock
();
goto
out_no_bh
;
}
}
}
goto
out
;
}
read_unlock_bh
(
&
tp
->
syn_wait_lock
)
;
st
=
seq
->
private
;
/* Completed requests are in normal socket hash table */
}
switch
(
st
->
state
)
{
case
TCP_SEQ_STATE_LISTENING
:
case
TCP_SEQ_STATE_ESTABLISHED
:
get_tcp_sock
(
v
,
tmpbuf
,
st
->
num
);
break
;
case
TCP_SEQ_STATE_OPENREQ
:
get_openreq
(
st
->
syn_wait_sk
,
v
,
tmpbuf
,
st
->
num
,
st
->
uid
);
break
;
case
TCP_SEQ_STATE_TIME_WAIT
:
get_timewait_sock
(
v
,
tmpbuf
,
st
->
num
);
break
;
}
tcp_listen_unlock
();
seq_printf
(
seq
,
"%-*s
\n
"
,
TMPSZ
-
1
,
tmpbuf
);
out:
return
0
;
}
local_bh_disable
();
static
struct
seq_operations
tcp_seq_ops
=
{
.
start
=
tcp_seq_start
,
.
next
=
tcp_seq_next
,
.
stop
=
tcp_seq_stop
,
.
show
=
tcp_seq_show
,
};
/* Next, walk established hash chain. */
for
(
i
=
0
;
i
<
tcp_ehash_size
;
i
++
)
{
struct
tcp_ehash_bucket
*
head
=
&
tcp_ehash
[
i
]
;
struct
sock
*
sk
;
struct
tcp_tw_bucket
*
tw
;
static
int
tcp_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
tcp_iter_state
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
)
;
read_lock
(
&
head
->
lock
);
for
(
sk
=
head
->
chain
;
sk
;
sk
=
sk
->
next
,
num
++
)
{
if
(
!
TCP_INET_FAMILY
(
sk
->
family
))
continue
;
pos
+=
TMPSZ
;
if
(
pos
<=
offset
)
continue
;
get_tcp_sock
(
sk
,
tmpbuf
,
num
);
len
+=
sprintf
(
buffer
+
len
,
"%-*s
\n
"
,
TMPSZ
-
1
,
tmpbuf
);
if
(
pos
>=
offset
+
length
)
{
read_unlock
(
&
head
->
lock
);
if
(
!
s
)
goto
out
;
}
}
for
(
tw
=
(
struct
tcp_tw_bucket
*
)
tcp_ehash
[
i
+
tcp_ehash_size
].
chain
;
tw
;
tw
=
(
struct
tcp_tw_bucket
*
)
tw
->
next
,
num
++
)
{
if
(
!
TCP_INET_FAMILY
(
tw
->
family
))
continue
;
pos
+=
TMPSZ
;
if
(
pos
<=
offset
)
continue
;
get_timewait_sock
(
tw
,
tmpbuf
,
num
);
len
+=
sprintf
(
buffer
+
len
,
"%-*s
\n
"
,
TMPSZ
-
1
,
tmpbuf
);
if
(
pos
>=
offset
+
length
)
{
read_unlock
(
&
head
->
lock
);
rc
=
seq_open
(
file
,
&
tcp_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
}
read_unlock
(
&
head
->
lock
);
}
}
out:
local_bh_enable
();
out_no_bh:
static
struct
file_operations
tcp_seq_fops
=
{
.
open
=
tcp_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
ip_seq_release
,
};
begin
=
len
-
(
pos
-
offset
);
*
start
=
buffer
+
begin
;
len
-=
begin
;
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
int
__init
tcp_proc_init
(
void
)
{
int
rc
=
0
;
struct
proc_dir_entry
*
p
=
create_proc_entry
(
"tcp"
,
S_IRUGO
,
proc_net
);
if
(
p
)
p
->
proc_fops
=
&
tcp_seq_fops
;
else
rc
=
-
ENOMEM
;
return
rc
;
}
void
__init
tcp_proc_exit
(
void
)
{
remove_proc_entry
(
"tcp"
,
proc_net
);
}
#endif
/* CONFIG_PROC_FS */
struct
proto
tcp_prot
=
{
.
name
=
"TCP"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment