1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
|
#compdef netstat
local Wopt Xopt nopt="[don't resolve addresses to names]"
local lopt='[show only listening sockets]'
local zopt='-z[reset statistic counters after displaying them]'
local popt='(-f)-p+[filter by protocol]:protocol:compadd -a plist'
local Iopt='(-i)-I+[show information about the specified interface]:interface:_net_interfaces'
local set sel tblopt
local -A sets
local -a Mopts families flist plist args sockets extend interval verbose
local -a {sel_,}{bpf,dhcp,groups,interfaces,masquerade,media,memory,multicast,pcb,queues,rdomains,routing,statistics,wireless}
case $OSTYPE in
linux-gnu)
families=(
'(-4 --inet)'{-4,--inet}
'(-6 --inet)'{-4,--inet6}
'(-A --protocol)'{-A+,--protocol=}':protocol:_sequence compadd - inet inet6 unix ipx ax25 netrom ddp bluetooth'
--unix -x --ip --tcpip --ax25 --x25 --rose --ash
--bluetooth --ipx --netrom --ddp --appletalk --econet --ec
)
extend=( \*{-e,--extend}'[show additional information]' )
verbose=( '(-v --verbose)'{-v,--verbose}'[show what is going on]' )
args=(
'(-c --continuous)'{-c,--continuous}'[repeat information every second]'
'!(-n --numeric)'{-N,--symbolic}
'(-n --numeric)'{-n,--numeric}"$nopt"
--numeric-hosts --numeric-ports --numeric-users
'1: :_guard "[0-9]#" "repeat interval (seconds)"'
- '(help)'
'(- 1)'{-h,--help}'[display usage information]'
'(- 1)'{-V,--version}'[display version information]'
)
sets=(
routing '(--route|-[^-]#r*)'
groups '(--groups|-[^-]#g*)'
interfaces '(--interfaces|-[^-]#[iI]*)'
statistics '(--statistics|-[^-]#s*)'
masquerade '(--masquerade|-[^-]#M*)'
)
sel_routing=( '(-r --route)'{-r,--route}'[display routing table]' )
sel_interfaces=(
'(-I --interfaces)-i[display interface table]'
'(-i -I --interfaces)'{--interface=-,-I=-}'[display interface table]::interface:_net_interfaces'
)
sel_groups=( '(-g --groups)'{-g,--groups}'[display multicast group memberships]' )
sel_masquerade=( '(-M --masquerade)'{-M,--masquerade}'[display masqueraded connections]' )
[[ -e /proc/net/ip_masquerade ]] || sel_masquerade=( \!${^sel_masquerade} )
sel_statistics=( '(-s --statistics -c --continuous -n --numeric --numeric-hosts --numeric-ports --numeric-users)'{-s,--statistics}'[display networking statistics]' )
sockets=(
$families $verbose
--tcp -t --udp -u --udplite -U --sctp -S --raw -w
'(-2 --l2cap)'{-2,--l2cap}
'(-f --rfcomm)'{-f,--rfcomm}
'(-a --all -l --listening)'{-l,--listening}$lopt
'(-a --all -l --listening)'{-a,--all}'[show all sockets]'
--symbolic -N --extend -e
'(--timers -o)'{--timers,-o}'[show information on networking timers]'
'(--program -p)'{--program,-p}'[show process id and program name for sockets]'
'(--wide -W)'{--wide,-W}"[don't truncate IP addresses in output]"
'(-Z --context)'{-Z,--context}'[display SELinux security context for sockets]'
)
routing=(
$families $extend $verbose
'-C[display routing cache instead of FIB]'
)
interfaces=(
$extend $verbose
'(-a --all)'{-a,--all}'[show interfaces that are not up]'
)
groups=()
masquerade=( $extend )
statistics=( $families )
;;
solaris*|darwin*|dragonfly*|freebsd*)
families=( '(-p -4 -6)-f+[specify address family]:address family:compadd -a flist' )
;|
freebsd*)
families+=(
'(-6 -f)-4[show IPv4 only]'
'(-4 -f)-6[show IPv6 only]'
)
;|
(open|net)bsd*)
popt='(-f)-p+[filter by protocol]:protocol:compadd - ${(M)${(f)"$(</etc/protocols)"}##[a-z0-9]#}'
families=(
'(-u)-f+[specify address family]:address family:_sequence compadd - -a flist'
'(-f)-u[limit reports to the unix address family]' # undocumented on NetBSD
)
;|
*) # everything except linux
sets=(
routing '-[^-]#r*'
groups '-[^-]#g*'
interfaces '-[^-]#[iIw]*'
memory '-[^-]#m*'
statistics '-[^-]#s*'
)
flist=( inet inet6 unix )
verbose=( '-v[verbose]' )
sel_routing=( '-r[display routing table]' )
sel_groups=( '-g[display multicast group memberships]' )
sel_interfaces=( $Iopt '-i[display interface table]' )
sel_statistics=( '*-s[display per protocol statistics]' )
sockets=( $families -n$nopt '-a[show all sockets]' )
routing=( -n$nopt )
interfaces=( $families -n$nopt )
statistics=( $families )
;|
(open|net)bsd*)
sets+=( pcb '-[^-]#P*' )
sel_pcb=( '-P+[display contents of the protocol control block]:pcb' )
routing+=( $verbose '(-L)-s[show routing statistics]' )
groups+=( $families
'(-s)-l[display wider fields for the IPv6 multicast routing table]'
'(-l)-s[show multicast routing statistics]'
)
interfaces+=(
'(-p)-s[show interface statistics]'
)
;|
darwin*|dragonfly*|(net|free|open)bsd*)
sockets+=( '-A[show address of a PCB associated with sockets]' )
interfaces+=(
'-b[show the number of bytes in and out]'
'-d[show the number of dropped packets]'
'1: :_guard "[0-9]#" "repeat interval (seconds)"'
)
routing=( $families )
sel_memory=( '-m[display statistics recorded by the memory management routines]' )
sel_interfaces+=( '(1 -a -f -i -p -s -u)-w+[display packet traffic at intervals]:interval (seconds)' )
;|
darwin*|dragonfly*|(net|free)bsd*)
interfaces+=( '-a[show multicast addresses currently in use]' )
;|
dragonfly*|(net|free|open)bsd*)
Mopts=(
'-M+[extract values from specified core]:core file:_files'
'-N+[extract name list from specified system image]:system image:_files'
)
interfaces+=(
'-h[print all counters in human readable form]'
)
sockets+=( $Mopts )
;|
darwin*|dragonfly*|freebsd*)
Wopt='-W+[avoid truncating fields even if it causes overflow]'
sockets+=( $Wopt
'-L[show size of listen queues]'
)
groups+=( $Wopt )
;|
dragonfly*|netbsd*|freebsd*)
sockets+=( '(-n)-S[show network addresses as numbers but show ports symbolically]' )
;|
netbsd*|freebsd*)
sets+=( bpf '-[^-]#B*' )
sel_bpf=( '-B[display statistics about bpf(4) peers]' )
;|
dragonfly*|freebsd*)
plist=( divert icmp igmp ip ipsec pim tcp udp icmp6 ip6 rip6 tcp udp pfkey ctrl data )
sockets+=( $popt )
statistics+=( $popt $zopt $Mopts )
memory+=( $Mopts )
routing+=( $Mopts $zopt
'(-A -a -f -l -n -W)*-s[show routing statistics]'
'-W[show path MTU for each route]'
)
groups+=( $families $Mopts
'(-W)*-s[show multicast routing statistics; repeat to suppress those with zero counters]'
)
;|
solaris2.<11->)
sets+=( dcache '-[^-]#d*' )
sel_dcache=( '-d[display the destination cache entry table]' )
dcache=( $families )
args=( '-T+[specify time format]:time format:((u\:seconds\ since\ epoch d\:standard\ date\ format))' )
sockets+=(
'-u[list user, pid and program that created network endpoint]'
'-k[show only sockets with kernel data path bypass enabled]'
'-L[only show state of sockets using SO_REUSEPORT load balancing]'
)
;&
solaris*)
args=( -A '-*' $args )
interval=(
'1: :_guard "[0-9]#" "repeat interval (seconds)"'
'2: :_guard "[0-9]#" "count"'
)
sets+=(
dhcp '-[^-]#D*'
media '-[^-]#p*'
multicast '-[^-]#M*'
)
sel_media=( '-p[display net to media tables]' )
sel_memory=( '-m[display STREAMS memory statistics]' )
sel_multicast=( '-M[display multicast routing tables]' )
sel_dhcp=( '-D[display status of DHCP configured interfaces]' )
sockets+=(
$verbose
'-R[show extended security attributes]'
'-P[specify protocol]:protocol:(ip ipv6 icmp icmpv6 igmp udp tcp rawip)'
)
routing+=( $verbose
'*-f+[filter routing table]:rule:_values -S \: "filter rule" $flist
"af[specify address family]\:family\:(inet inet6 unix)"
"outif[specify output interface]\:interface\:_net_interfaces"
"dst[specify destination IP]\:IP address"
"flags[select routes tagged with flags]\:flags"' \
'-a[show state of all routing tables]'
'-R[show extended security attributes]'
)
groups+=( $families -n$nopt $verbose )
interfaces+=( $interval
'-a[show state of all interfaces]'
)
statistics+=(
'-P[specify protocol]:protocol:(ip ipv6 icmp icmpv6 igmp udp tcp rawip)'
)
media=( -n$nopt $families )
memory+=( $verbose $interval )
multicast+=(
-n$nopt $families
'-s[show per protocol statistics]'
)
dhcp=( $families $Iopt )
;;
darwin*)
sets+=( queues '-[^-]#q*' )
sel_queues=( '*-q[display network interface send queue statistics]' )
sel_memory=( \*$sel_memory )
sockets+=(
'-l[show full IPv6 address]'
'-W[avoid truncating addresses]'
)
routing+=( '-l[show mtu and use wider display]' )
interfaces+=(
'(-x)-R[show reachability information]'
'-S[show interface link status and state]'
'(-R)-x[show extended reachability information]'
)
queues=( $Iopt
'-c+[limit statistics to specified queue]:queue'
)
groups+=( $families
'*-v[show link-layer memberships; repeat for timers and counters]'
)
;;
dragonfly*)
plist+=( carp )
sockets+=(
'-P[show additional protocol-specific information]'
'-c+[access cpu specific route table]:cpu'
)
interfaces+=( $zopt
'-B[show maximum buffer sizes instead of current buffer usage]'
'-t[show the contents of watchdog timers]'
'(-a -B -b -d -h -n -t -w)*-s[show protocol statistics; repeat to suppress those with zero counters]'
)
routing+=(
'-A[show contents of internal Patricia tree structures]'
'-a[show protocol-cloned routes]'
)
;;
openbsd*)
sets+=( wireless '-W*' rdomains '-R' )
sel_rdomains=( '-R[show all rdomains with associated interfaces and routing tables]' )
sel_wireless=( '-W+[display per-interface IEEE 802.11 wireless statistics]:interface' )
flist+=( local mpls )
tblopt='-T+[select an alternate routing table to query]:routing table'
sockets+=( -l$lopt $tblopt '-B[show buffer sizes for TCP sockets]' )
routing+=( $Mopts $tblopt
'-A[show the internal addresses of the routing table]'
'-F[only show routes with gateway in the same address family as the destination]'
)
interfaces+=(
'-c+[show specified number of updates, then exit]:count'
'-e[show only the number of errors on the interface]'
'-q[only show interfaces that have seen packets]'
'-t[show current value of the watchdog timer function]'
)
statistics+=( $popt '-r[display routing statistics]' )
groups+=( -n$nopt )
pcb+=( $Mopts $verbose )
;;
netbsd*)
popt='(-f)-p+[filter by protocol]:protocol:compadd - ${(M)${(f)"$(</etc/protocols)"}##[a-z0-9]#}'
Xopt='-X[force use of sysctl(3) when retrieving information]'
flist+=( arp ns atalk mpls local )
sets+=( queues '-[^-]#q*' )
sel_queues=( '-q[display software interrupt queue details for all protocols]' )
routing+=( $Xopt
"(-s)-L[don't show link-level routes]"
'-T[show MPLS tags for the routing tables]'
)
bpf+=( $Xopt $Iopt
'-s[show bpf(4) statistics]'
)
interfaces+=( $Xopt )
memory+=( $Xopt) statistics+=( $Xopt )
pcb+=( $Mopts $popt )
;;
freebsd<13->.*)
sockets+=(
'-c[show TCP stack used for each session]'
'-C[show TCP congestion control algorithm and diagnostic]'
)
;&
freebsd<11->.*)
routing+=( '-F+[show specified routing table]:routing table' )
bpf=( '-z[reset statistic counters after displaying them]' )
statistics+=( $bpf[-1] )
;&
freebsd*)
flist+=( pfkey netgraph ng link )
plist+=( sctp ipsec6 pfkey )
sets+=( netisr '-[^-]#Q*' )
sel_netisr=( '-Q[display netisr(9) statistics]' )
sockets+=(
'-R[show flowid and flowtype for each socket]'
'-T[show diagnostic information from the TCP control block]'
'-x[show socket buffer and TCP timer statistics]'
)
interfaces+=(
$popt $Mopts $Iopt $Wopt
'-q+[exit after specified number of outputs]:number'
)
bpf+=( $Iopt $zopt )
;;
esac
# Ignore display specific options except the default (socket) display until a
# display has been selected. This is not strictly correct (options can be in
# any order) but makes the completion much more useful. Descriptions for
# options that select a specific display (option set) typically start with
# "display" to set them apart from other options.
sock=''
for set in ${(k)sets}; do
sel=sel_$set
if [[ -z $words[(r)$~sets[$set]] ]]; then
ign='!'
else
sock='!'
ign=''
fi
args+=( - "$set" ${(P)sel} ${ign}${(P)^set} )
done
args+=( - sockets ${sock}${sockets} )
_arguments -s -S $args
|