From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9554 invoked by alias); 16 Aug 2017 17:17:46 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 41556 Received: (qmail 18893 invoked by uid 1010); 16 Aug 2017 17:17:46 -0000 X-Qmail-Scanner-Diagnostics: from nm28-vm8.bullet.mail.ir2.yahoo.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(212.82.97.68):SA:0(-4.7/5.0):. Processed in 4.416726 secs); 16 Aug 2017 17:17:46 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_PASS,T_DKIM_INVALID autolearn=ham autolearn_force=no version=3.4.1 X-Envelope-From: okiddle@yahoo.co.uk X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.co.uk; s=s2048; t=1502903464; bh=yrYf25RBatqNwQ97yz5DRqUm9jbPRvF4BMzppn4ye5s=; h=From:To:Subject:Date:From:Subject; b=Rq58DvvXdSE2Qz8/NJo5CHtDAhjy4nfecVVqOG+qk9OKT6zAe4Xr9b+8ciBoP8nB/HNVeVV1arF6Yzyu+sj7rwjpSIJw8yGmHQhmMHIpHVGsulC5a+vV2Rqa00tozyJbL5dXZnwQ/PhqhpsaQXceDPT9PZPf52rZUfukXKAsWPBABOkrHXq+Q0nRrI7Gwko69CabkvBagSSogE/C5vZOx9rHuytHOHz+YxdJ7xbh5gPy9FA23j37m+WcUoWulmVTuPI2Ukmkb1TsAozt+S3HzZMIjBCwFwcP57vcvTDrkbp9gzsBPEoczhHI6JLWqtrCN/3wHxNnqhK0r00TBm8TPw== X-Yahoo-Newman-Id: 32840.66841.bm@smtp140.mail.ir2.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: 8r2zHIwVM1lfm3dposlvhxNLPLD_kvMQ3PjAtT47iof20Vk buALbWU2JbzPXY8Xfhr.Jk.B9jn17BINwKoUPeUzcc4YaHeJqTpi9cZwjfJW 7aJFow7z7WOv5vaD6VjbBpfswWTbsTzIsjbOWlwtsedrtbQNruUM5dMqYKjh WU4vvfQTZKJO5w6B5kyrXouwlew8IxI1o0GdoYIv6G1hBA8N4G3JcvZ_6hBn gvbuK7nO0NRChjannliOjcFUrnhxxPfekQ8c_b9xEjhs19_ZWcxmyXa_Q9yd VyxZ4U7N0dyP3ld8rV0HV0M741qwqjtD50aWuwi7j2Dfx7BKas0zY.9Lx8g3 mXCsA9gweZG6HRLS4KoJvCzr1t_u.ZA9f.5EaaQa7hxGgOhOAjgsmShhfHYr t98vOM1fNxI5z_0Tth98OSZysMwHIb5gMNC3kGmXEOFq3oHcjBhoqViHwFnc gauVbokikvyJ1x4q7QkyupnjO7PS_trTNCq_aK58h7WfvXg-- X-Yahoo-SMTP: opAkk_CswBAce_kJ3nIPlH80cJI- From: Oliver Kiddle To: Zsh workers Subject: PATCH: completion for tcpdump filters MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <22994.1502903462.1@thecus.kiddle.eu> Content-Transfer-Encoding: quoted-printable Date: Wed, 16 Aug 2017 19:11:02 +0200 Message-ID: <22995.1502903462@thecus.kiddle.eu> This adds a completion function for BPF (libpcap) filters which is what tcpdump uses. Aside from tcpdump, this also gets used for Solaris' snoop and a new ngrep completion. I also updated a few options for _tcpdump and cleaned up _snoop. This makes use of _regex_arguments because it's a good fit for this particular problem. The filters can't be fully described by a type-3 (regular) grammar but setting and checking variables in the guards and taking advantage of the naive backtracking regex parsing algorithm allows it to do the job. If you break it, _regex_arguments' fallback is to print "parse failed before current word". This isn't especially useful from a completion standpoint. Perhaps _regex_arguments could indicate such errors back via a return status or variable. In the case of BPF filters, it could strip off the beginning of $words, perhaps up to the next 'and'/'or', and try again. Also of note is that _regex_arguments strips quotes from $words[1,CURRENT-1] but not from $PREFIX. So in some cases patterns need to allow for backslashes but not others. Finally, I can't get it to work without an initial word in $words (normally the command name) that it immediately skips over. This looks like a bug but I need to investigate further. Oliver diff --git a/Completion/Solaris/Command/_snoop b/Completion/Solaris/Comman= d/_snoop index f734c2fb1..77798a730 100644 --- a/Completion/Solaris/Command/_snoop +++ b/Completion/Solaris/Command/_snoop @@ -1,87 +1,32 @@ #compdef snoop = -_snoop() { - local -a t_opt exp +local -a args = -t_opt=3D( - "r"\:"time relative to first packet" - "a"\:"absolute time" - "d"\:"delta time - time since receiving previous packet" +[[ $OSTYPE =3D solaris2.<11-> ]] && args=3D( + '-I+[capture packets from specified interface]:interface:_net_interface= s' ) - -exp=3D( - "ether" - "ethertype" - "host" - "from" - "to" - "ip" - "ip6" - "arp" - "rarp" - "pppoe" - "pppoed" - "pppoes" - "vlan" - "vlan-id" - "broadcast" - "multicast" - "bootp" - "dhcp" - "dhcp6" - "apple" - "decnet" - "greater" - "less" - "udp" - "tcp" - "icmp" - "icmp6" - "ah" - "esp" - "net" - "port" - "rpc" - "zone" - "ldap" - "gateway" - "nofrag" - ">" - ">=3D" - "<" - "<=3D" - "=3D" - "!=3D" - "and" - "or" - "not" - "slp" - "sctp" - "ospf" -) - - _arguments \ - '-a[generate audio signal on receiving packets]' \ - '-c[quit after capturing maxcount packets]:maxcount' \ - '-d[capture packets from specified device]:device:_net_interfaces' \ - '-i[display packets previously captured to file]:file:_files' \ - '-n[use file as IP address-to-name mapping table]:file:_files' \ - '-o[save captured packets to file]:file:_files' \ - '-p[display one or more packets from captured file]:first packet number= [ , last packet number]' \ - '-q[do not display packet counter when capturing to file]' \ - '-r[do not resolve IP addresses to names]' \ - '-s[truncate each packet after snaplen bytes]:snaplen' \ - '-t[time-stamp presentation]:time-stamp mode:(($t_opt))' \ - '-C[list code generated from filter expression]' \ - '-D[display number of packets dropped on the summary line]' \ - '-N[create IP-address-to-name mapping table file (used with -i)]' \ - '-I[capture packets from specified interface]:interface:_net_interfaces= ' \ - '-P[capture packets in non-promiscuous mode]' \ - '-S[display size of the entire link layer frame in bytes]' \ - '-V[verbose summary mode]' \ - '-v[verbose mode]' \ - '-x[display offset and length of packet in HEX and ASCII]:offset [ , le= ngth]' \ - '*:expression:(($exp))' \ -} - -_snoop "$@" +_arguments -s -S -A "-*" \ + '-a[generate audio signal on receiving packets]' \ + '-c+[quit after capturing specified number of packets]:number of packet= s' \ + '-d+[capture packets from specified device]:device:_net_interfaces' \ + '-i+[display packets previously captured to file]:file:_files' \ + '-n+[use file as IP address-to-name mapping table]:file:_files' \ + '-o+[save captured packets to file]:file:_files' \ + '-p+[display one or more packets from captured file]:first packet numbe= r [ , last packet number]' \ + "-q[don't display packet counter when capturing to file]" \ + "-r[don't resolve IP addresses to names]" \ + '-s[truncate each packet after specified number of bytes]:length (bytes= )' \ + '-t+[specify time-stamp presentation]:time-stamp mode:(( + r\:relative\ to\ first\ packet + a\:absolute + d\:delta\ -\ since\ previous\ packet + ))' \ + '-C[list code generated from filter expression]' \ + '-D[display number of packets dropped on the summary line]' \ + '-N[create IP-address-to-name mapping table file (used with -i)]' \ + '-P[capture packets in non-promiscuous mode]' \ + '-S[display size of the entire link layer frame in bytes]' \ + '-V[verbose summary mode]' \ + '-v[verbose mode]' \ + '-x+[display offset and length of packet in HEX and ASCII]:offset [ , l= ength]' \ + '*::expression:=3D _bpf_filters' diff --git a/Completion/Unix/Command/_ngrep b/Completion/Unix/Command/_ngr= ep new file mode 100644 index 000000000..924597826 --- /dev/null +++ b/Completion/Unix/Command/_ngrep @@ -0,0 +1,33 @@ +#compdef ngrep + +_arguments -s -S \ + '(- 1 *)-h[display help information]' \ + '(- 1 *)-V[display version information]' \ + "-q[be quiet (don't print packet reception hash marks)]" \ + '-e[show empty packets]' \ + '-i[ignore case]' \ + '-v[invert match]' \ + "-R[don't do privilege revocation logic]" \ + '(-W)-x[print in alternate hexdump format]' \ + '-X[interpret match expression as hexadecimal]' \ + '-w[word-regex (expression must match as a word)]' \ + "-p[don't go into promiscuous mode]" \ + '-l[make stdout line buffered]' \ + '-D[replay pcap_dumps with their recorded time intervals]' \ + '-t[print timestamp every time a packet is matched]' \ + '-T[print delta timestamp every time a packet is matched specify twice= for delta from first match]' \ + "-M[don't do multi-line match (do single-line match instead)]" \ + '(-d -s)-I+[read packet stream from pcap format file]:file:_files' \ + '-O+[dump matched packets in pcap format file]:file:_files' \ + '-n+[look at only specified number of packets]:packets' \ + '-A+[dump specified number of context packets after a match]:packets' = \ + '(-I)-s+[set the bpf caplen]:length (bytes) [65535]' \ + '-S+[set the upper limit on size of packets matched]:size (bytes)' \ + '(-x)-W+[set the dump format]:packet display format:(normal byline sin= gle none)' \ + '-c+[force the column width to the specified size]:columns' \ + '-P+[set the non-printable display char to what is specified]:characte= r [.]' \ + '-F+[read the bpf filter from the specified file]:file:_files' \ + '-N[show sub protocol number]' \ + '(-I)-d+[use specified device instead of the pcap default]:interface:_= net_interfaces' \ + '1: :_guard "^-*" pattern' \ + '*::expression:_bpf_filters' diff --git a/Completion/Unix/Command/_tcpdump b/Completion/Unix/Command/_t= cpdump index 2c1d82226..4b9950fa5 100644 --- a/Completion/Unix/Command/_tcpdump +++ b/Completion/Unix/Command/_tcpdump @@ -1,17 +1,25 @@ #compdef tcpdump = -typeset -A opt_args +local args ret=3D1 +local root +(( EUID )) && root=3D'!' = -_interfaces() { - local disp expl sep - _description interfaces expl 'network interface' - _net_interfaces "$expl[@]" - if zstyle -t ":completion:${curcontext}:interfaces" verbose; then - zstyle -s ":completion:${curcontext}:interfaces" list-separator sep |= | sep=3D-- - disp=3D( "any $sep capture on all interfaces" ) - compadd "$expl[@]" -ld disp any +_tcpdump_interfaces() { + local disp expl sep interfaces + [[ $OSTYPE !=3D openbsd* ]] && + interfaces=3D( ${${${${(f)"$(_call_program interfaces tcpdump -D)"}= #<->.}//[()]/}/ /:} ) + if (( $#interfaces )); then + _describe -t interfaces 'network interface' interfaces else - compadd "$expl[@]" any + _description interfaces expl 'network interface' + _net_interfaces "$expl[@]" + if zstyle -t ":completion:${curcontext}:interfaces" verbose; then + zstyle -s ":completion:${curcontext}:interfaces" list-separator sep= || sep=3D-- + disp=3D( "any $sep capture on all interfaces" ) + compadd "$expl[@]" -ld disp any + else + compadd "$expl[@]" any + fi fi } = @@ -40,43 +48,50 @@ _esp_secrets () { } = _packet_types () { + local -a types types=3D( - 'cnfp[Cisco NetFlow protocol]' - 'rpc[Remote Procedure Call]' - 'rtp[Real-Time Applications protocol]' - 'rtcp[Real-Time Applications control protocol]' - 'vat[Visual Audio Tool]' - 'wb[distributed White Board]' + 'cnfp:Cisco NetFlow protocol' + 'rpc:Remote Procedure Call' + 'rtp:Real-Time Applications protocol' + 'rtcp:Real-Time Applications control protocol' + 'vat:Visual Audio Tool' + 'wb:distributed White Board' ) if [[ $OSTYPE =3D openbsd* ]]; then types+=3D( - 'sack[RFC 2018 TCP Selective Acknowledgements Options]' - 'vrrp[Virtual Router Redundancy Protocol]' - 'tcp[Transmission Control Protocol]' + 'sack:RFC 2018 TCP Selective Acknowledgements Options' + 'vrrp:Virtual Router Redundancy Protocol' + 'tcp:Transmission Control Protocol' ) else types+=3D( - 'aodv[Ad-hoc On-demand Distance Vector protocol]' - 'carp[Common Address Redundancy Protocol]' - 'radius[RADIUS]' - 'snmp[Simple Network Management Protocol]' - 'tftp[Trivial File Transfer Protocol]' - 'vxlan[Virtual eXtensible Local Area Network]' - 'zmtpl[ZeroMQ Message Transport Protocol]' + 'aodv:Ad-hoc On-demand Distance Vector protocol' + 'carp:Common Address Redundancy Protocol' + 'radius:RADIUS' + 'snmp:Simple Network Management Protocol' + 'tftp:Trivial File Transfer Protocol' + 'vxlan:Virtual eXtensible Local Area Network' + 'zmtpl:ZeroMQ Message Transport Protocol' ) fi - _values 'Packets type' $types + _describe -t packet-types 'packet type' types +} + +_time_stamp_types () { + local vals + vals=3D( ${${${(ps:\n :)"$(_call_program time-stamp-types tcpdump -J $= {(kv)opt_args[(i)-i|--interface]} 2>&1)"}[2,-1]:#*cannot be set*}/ /:} ) + _describe -t time-stamp-types "time stamp type" vals } = _data_link_types () { - if (( $+opt_args[-i] )); then - vals=3D( ${${${(s: :)"$(_call_program data-link-types tcpdump -L -i $o= pt_args[-i] 2>&1)"}[2,-1]}/ /:} ) - _describe -t data-link-types "data link types ($opt_args[-i])" vals && = ret=3D0 - else - _values "Data link types (general)" \ - "EN10MB" \ - "LINUX_SLL" - fi + local vals expl + if (( $+opt_args[(i)-i|--interface] )); then + vals=3D( ${${${(s: :)"$(_call_program data-link-types tcpdump -L ${(= kv)opt_args[(i)-i|--interface]} 2>&1)"}[2,-1]}/ /:} ) + _describe -t data-link-types "data link type (${(v)opt_args[(i)-i|--i= nterface]})" vals + else + _wanted data-link-types expl "data link type (general)" \ + compadd EN10MB LINUX_SLL + fi } = _bpf_filter () { @@ -84,79 +99,95 @@ _bpf_filter () { = args=3D( '-A[print each packet in ASCII]' - '-c[exit after receiving specified number of packets]:number of packets= ' + '-c+[exit after receiving specified number of packets]:number of packet= s' '(-ddd)-d[dump the compiled packet-matching code in a human readable fo= rm]' '(-ddd)-dd[dump packet-matching code as a C program fragment]' '(-d -dd)-ddd[dump packet-matching code as decimal numbers (preceded wi= th a count)]' "-E[decrypting IPsec ESP packets]:spi@ipaddr::algo\:secret:_esp_secrets= " '-e[print the link-level header on each dump line]' - '-F[input file for the filter expression]:filter expression file:_files= ' + '-F+[specify input file for the filter expression]:filter expression fi= le:_files' "-f[print 'foreign' IPv4 addresses numerically]" '-l[make stdout line buffered]' "-N[don't print domain name qualification of host names]" - "-n[don't convert addresses to names]" + "(-nn)-n[don't convert addresses to names]" "-O[don't run the packet-matching code optimizer]" - "-p[don't put the interface into promiscuous mode]" + '(-p --no-promiscuous-mode)'{-p,--no-promiscuous-mode}"[don't put the i= nterface into promiscuous mode]" '-q[quick (quiet?) output]' - '-r[read packets from file]:input file:_files' - '-S[print absolute TCP sequence numbers]' - '-s[specify number of bytes of data to snarf from each packet]:number o= f bytes to snap' - '-T[interpret captured packets as specified type]:packet type:_packet_t= ypes' + '-r+[read packets from file]:input file:_files' + '(-S --absolute-tcp-sequence-numbers)'{-S,--absolute-tcp-sequence-numbe= rs}'[print absolute TCP sequence numbers]' + '-T+[interpret captured packets as specified type]:packet type:_packet_= types' "(-tt -ttt -tttt -ttttt)-t[don't print a timestamp on each dump line]" '(-t -ttt -tttt -ttttt)-tt[print an unformatted timestamp on each dump = line]' '(-vv -vvv)-v[slightly more verbose output]' '(-v -vvv)-vv[more verbose output]' - '-w[write the raw packets to file]:output file:_files' + '-w+[write the raw packets to file]:output file:_files' '-X[print each packet (minus its link level header) in hex and ASCII]' '-x[print each packet (minus its link level header) in hex]' - '-y[set the data link type to use while capturing packets]:data link ty= pe:_data_link_types' - '*:BPF filter:_bpf_filter' + '(-y --linktype)'{-y+,--linktype=3D}'[set the data link type to use whi= le capturing packets]: :_data_link_types' ) = if [[ $OSTYPE =3D openbsd* ]]; then - args+=3D( + args=3D( + '-i+[specify interface]:interface:_tcpdump_interfaces' + - listd + '-L[list data link types for the interface]' + - capture + ${(R)args:#(|\*)(|\(*\))--*} # removes any long-options '(-n)-a[attempt to convert network and broadcast addresses to names]' '-D[select packet flowing in specified direction]:direction:(in out)' '-I[print the interface on each dump line]' '-o[print a guess of the possible operating system(s)]' + '-s+[specify amount of data to snarf from each packet]:length (bytes)= [116]' '(-t -tt -tttt -ttttt)-ttt[print day and month in timestamp]' '(-t -tt -ttt -ttttt)-tttt[print timestamp difference between packets= ]' '(-t -tt -ttt -tttt)-ttttt[print timestamp difference since the first= packet]' ) else - args+=3D( - '-B[specify the capture buffer size in KiB]:capture buffer size' + args=3D( + '(-i --interface -D --list-interfaces)'{-i+,--interface=3D}'[specify = interface]:interface:_tcpdump_interfaces' + - listt + '(-J --list-time-stamp-types)'{-J,--list-time-stamp-types}'[list supp= orted time stamp types]' + - listd + '(-L --list-data-link-types)'{-L,--list-data-link-types}'[list data l= ink types for the interface]' + - capture + $args + '(-B --buffer-size)'{-B+,--buffer-size=3D}'[set the operating system = capture buffer size]:size (kiB)' '-b[print the AS number in BGP packets in ASDOT notation]' - '-C[specify output file size in MB (10e6 bytes)]:output file size' - '(-* *)'-D'[print the list of the network interfaces available on the= system]' - '-G[specify the interval to rotate the dump file in seconds]:dump fil= e rotate seconds' + '-C+[specify output file size]:output file size (MB)' + '(-)'{-D,--list-interfaces}'[print the list of the network interfaces= available on the system]' + '-G+[rotate dump file specified with -w at specified interval]:interv= al (seconds)' '-H[attempt to detect 802.11s draft mesh headers]' - '(-* *)-h[print version strings and a usage message]' + '(- *)'{-h,--help}'[display help information]' + '(- *)--version[display version information]' + '(-I --monitor-mode)'{-I,--monitor-mode}'[put the Wi-Fi interface in = monitor mode]' + '--immediate-mode[deliver packets to tcpdump as soon as they arrive w= ithout buffering]' '-I[put the interface in monitor mode]' - '(-* *)-J[list the supported timestamp types]' - '-j[set the timestamp type]:timestamp type' - "-K[don't attempt to verify checksums]" - '*-m[load SMI MIB module definitions]:SMI MIB module definitions:_fil= es' - '-M[shared secret for validating the digests in TCP segments with the= TCP-MD5 option]:secret' - '-R[assume ESP/AH packets to be based on old specification (RFC1825 t= o RFC1829)]' - '(-t -tt -tttt)-ttt[print a delta (in micro-seconds) between current = and previous line on each dump line]' - '(-t -tt -ttt)-tttt[print a timestamp in default format proceeded by = date on each dump line]' - '(-t -tt -ttt -tttt)-ttttt[print a delta (micro-second resolution) si= nce the first line on each dump line]' - '-U[make output packet-buffered when saving to file (-w)]' + '(-j --time-stamp-type)'{-j+,--time-stamp-type=3D}'[set the time stam= p type for the capture]: :_time_stamp_types' + '--time-stamp-precision=3D[set the time stamp precision for the captu= re]:precision [micro]:(micro nano)' + '(-K --dont-verify-checksums)'{-K,--dont-verify-checksums}"[don't ver= ify IP, TCP, or UDP checksums]" + '*-m+[load SMI MIB module definitions]:SMI MIB module definition:_fil= es' + "(-n)-nn[don't convert protocol and port numbers to names]" + '-M+[specify shared secret for validating the digests in TCP segments= with the TCP-MD5 option]:secret' + '(-# --number)'{-\#,--number}'[print an optional packet number at the= beginning of the line]' + '(-O --no-optimize)'{-O,--no-optimize}"[don't run the packet-matching= code optimizer]" + '(-s --snapshot-length)'{-s+,--snapshot-length=3D}'[specify amount of= data to snarf from each packet]:length (bytes) [65535]' + '(-t -tt -tttt -ttttt)-ttt[print a delta (in micro-seconds) on each l= ine since previous line]' + '(-t -tt -ttt -ttttt)-tttt[print a timestamp in default format preced= ed by date on each dump line]' + '(-t -tt -ttt -tttt)-ttttt[print a delta (in micro-seconds) on each l= ine since first line]' + '(-U --packet-buffered)'{-U,--packet-buffered}'[make output packet-bu= ffered when saving to file (-w)]' '-u[print undecoded NFS handles]' - '-V[Read a list of filenames from file]:file:_files' + '-V+[read a list of filenames from specified file]:file:_files' '(-v -vv)-vvv[most verbose output]' - '-W[limit the number of created files (-C)]:number of files' + '-W+[limit the number of created files (-C)]:number of files' '(-X)-XX[print each packet, including its link level header, in hex a= nd ASCII]' '(-x)-xx[print each packet, including its link level header, in hex]' - '-Z[drops privileges (if root) and changes user ID (along with primar= y group)]:user:_users' - '-z[command to run after file rotation]:command:_command_names' + "${root}(-Z --relinquish-privileges)"{-Z+,--relinquish-privileges=3D}= '[drop privileges and run as specified user]:user:_users' + '-z+[specify command to run on files (with -C or -G)]:command:_comman= d_names -e' ) fi +[[ $OSTYPE =3D freebsd* ]] && args+=3D( + '-R[assume ESP/AH packets to be based on old specification (RFC1825 to = RFC1829)]' +) = -_arguments : \ - '-i[interface]:interface:_interfaces' \ - - optL \ - '-L[list the known data link types for the interface]' \ - - default \ - $args +_arguments -s $args \ + '*::BPF filter:=3D _bpf_filters' diff --git a/Completion/Unix/Type/_bpf_filters b/Completion/Unix/Type/_bpf= _filters new file mode 100644 index 000000000..c62481e09 --- /dev/null +++ b/Completion/Unix/Type/_bpf_filters @@ -0,0 +1,215 @@ +# spaces are valid instead of word ends, perhaps better to just do compse= t -q + +local -a networks fields dirs protos relop +local -A subtypes flags +local values dir wlantype skip repeat=3D1 packet proto=3D0 +local suf=3D']' + +local WORD=3D$'[^ \0]##[ \0]##' + +networks=3D( + /$'[^/ \0]#'/ + \( + /$'[ \0]'/ ': _message -e networks network' + /$'mask[ \0]'/ ':masks:mask:(mask)' + /$WORD/ ':netmasks:netmask:' + \| + /// /$WORD/ ': _message -e masks "netmask length (bits)"' + \) +) +subtypes=3D( + mgt 'assoc-req assoc-resp reassoc-req reassoc-resp probe-req probe-resp= beacon atim disassoc auth deauth' + ctl 'ps-poll rts cts ack cf-end cf-end-ack' + data 'data data-cf-ack data-cf-poll data-cf-ack-poll null cf-ack cf-pol= l cf-ack-poll qos-data qos-data-cf-ack qos-data-cf-poll qos-data-cf-ack-po= ll qos qos-cf-poll and qos-cf-ack-poll' +) +flags=3D( + len len + tcp 'tcp-fin tcp-syn tcp-rst tcp-push tcp-ack tcp-urg' + icmp 'icmp-echoreply icmp-unreach icmp-sourcequench icmp-redirect icmp-= echo icmp-routeradvert icmp-routersolicit icmp-timxceed icmp-paramprob icm= p-tstamp icmp-tstampreply icmp-ireq icmp-ireqreply icmp-maskreq icmp-maskr= eply' +) + +case $OSTYPE in + solaris*) + fields=3D( ipaddr etheraddr atalkaddr ethertype rpc nofrag inet inet6= vlan-id ) + protos=3D( bootp dhcp dhcp6 apple pppoe ldap slp ospf ) + dirs=3D( from to ) + relop=3D( \^ % ) + ;| + solaris2.<11->) + fields+=3D( zone ) + ;| + (free|open)bsd*) # pf(4) specific filters + fields=3D( ifname on rnr rulenum srnr subruleset reason ruleset rset = action ) + ;| + ^(solaris|openbsd)*) + protos+=3D( mpls netbeui iso geneve aarp ipx llc ) + ;| + ^openbsd*) + protos+=3D( ah esp sctp pppoed pppoes ) + ;| + ^solaris*) + protos+=3D( fddi wlan atalk stp lat moprc mopdl ) + relop=3D( '>>' '<<' ) + ;; +esac + +compquote suf + +# the regex is essentially: +# ( [not]* ( expression | [protocol]? [standalone-field | direction field= ]? ) and|or ) * +# the proto variable ensures that and/or is not allowed if there is no +# protocol or field: it is one, the other or both but not neither + +_regex_arguments _bpf /$'[^\0]#\0'/ \( \ + /$'(not[ \0]#|![ \0]#|(\\\\|)\\([ \0]#)'/ ':operators:operator:(not ()'= \# \ + \(\ + \(\ + \(\ + /"(0x[0-9a-f]##|[0-9]##|${(j.|.)${=3Dflags}})"$'[ \0]#'/ -'((repe= at !=3D 2))' ":expressions:expression:compadd ${=3Dflags[$packet]}" \ + \|\ + /'[a-z]##(\\|)\[[^\]]##(\\|)\]'$'[ \0]#'/ \ + \|\ + /'[a-z]##(\\|)\[[^:\]]##:'/ /'[]'/ ':sizes:field size (bytes):com= padd -S "$suf" 1 2 4' \ + \|\ + /'tcp(\\|)\['/ -packet=3Dtcp \ + /'[]'/ ':offsets:header offset:compadd -S "$suf " tcpflags' \ + \|\ + /'icmp(\\|)\['/ -packet=3Dicmp \ + /'[]'/ ':offsets:header offset:compadd -S "$suf " icmptype icmpco= de' \ + \|\ + /'[a-z]##(\\|)\['/ /'[]'/ ':offsets:offset:' \ + \)\ + \(\ + /$'(\\\\|)([<>=3D!](\\\\|)[<>=3D]|[<>&|=3D+*/%^-])[ \0]#'/ -'repe= at=3D0' ":operators:operator:(+ - =3D !=3D < > <=3D >=3D & | $relop and or= )" \ + // ': _message -e expressions expression' \ + \|\ + // -'repeat=3D2' \ + \)\ + \) \# \ + // -'(( repeat =3D=3D 2))' \ + // -'repeat=3D1' \ + \|\ + /$'ether[ \0]proto[ \0]'/ \ + /$WORD/ ':protocols:protocol:(\ip \ip6 \arp \rarp \atalk \aarp \dec \= net \sca \lat \mopdl \moprc \iso \stp \ipx \netbeui)' \ + \|\ + /$'(less|greater)[ \0]'/ ':fields:field:(less greater)' \ + /$WORD/ ':numbers:length (bytes):' \ + \|\ + \(\ + /$'(tcp|udp|icmp|ether|ip|ip6|arp|rarp|decnet|bootp|dhcp|dhcp6|appl= e|pppoe|pppoed|ldap|ah|esp|slp|sctp|ospf|iso|clnp|esis|isis|atalk|aarp|iso= |stp|ipx|netbeui|lat|moprc|mopdl)[ \0]'/ ":protocols:protocol qualifier:(t= cp udp icmp ether tr ip ip6 arp rarp decnet $protos)" \ + \| /$'((fddi|tr|wlan)[ \0]|)'/ '-(( ++proto ))' \) \ + \(\ + /$'mpls[ \0]'/ \ + /$'((0x|)[0-9a-f]##[ \0]|)'/ ': _message -e labels "label number"' = \ + \|\ + /$'geneve[ \0]'/ \ + /$'((0x|)[0-9a-f]##[ \0]|)'/ ': _message -e vnis "vni"' \ + \|\ + /$'pppoes[ \0]'/ \ + /$'((0x|)[0-9a-f]##[ \0]|)'/ ': _message -e session-ids "session id= "' \ + \|\ + /$'proto[ \0]'/ ':fields:field:(proto)' \ + /$WORD/ ':protocols:protocol:(\icmp \icmp6 \igmp \igrp \pim \ah \es= p \vrrp \udp \tcp)' \ + \|\ + /$'(broad|multi)cast[ \0]'/ ':fields:field:(broadcast multicast)' \ + \|\ + /$'type[ \0]'/ ':fields:field:(type)' \ + /$WORD/ -'wlantype=3D${match%?}' ':wlan-types:wlan type:(mgt ctl da= ta)' \ + \(\ + /$'subtype[ \0]'/ ':fields:field:(subtype)' \ + /$WORD/ ':subtypes:subtype:compadd ${=3Dsubtypes[$wlantype]:-$sub= types}' \ + \| \)\ + \|\ + /$'protochain[ \0]'/ ':fields:field:(protochain)' \ + /$WORD/ ':protocols:protocol:' \ + \|\ + /$'vlan-id[ \0]'/ \ + /$WORD/ ':vlans:vlan:' \ + \|\ + /$'vlan[ \0]'/ ':fields:field:(vlan)' \ + \( /$WORD/ ': _message -e vlans vlan' \| \) \ + \|\ + \(\ + /$'(ra|ta|addr[1-4]|inbound|outbound)[ \0]'/ ":directions:directi= on qualifier:(src dst inbound outbound ra ta addr1 addr2 addr3 addr4 $dirs= )" \ + \|\ + /$'(src|from|dst|to)[ \0]'/ -'values=3D${values:-hosts};dir=3D$ma= tch' \ + \(\ + /$'(or|and)[ \0]'/ ':operators:operator:(or and)' \ + /$'(src|dst)[ \0]'/ ':directions:direction qualifier:compadd ${= ${${${dir%?}:/dst/to}:/(src|from)/dst}:/to/src}' \ + \| \)\ + \| \)\ + \(\ + /$'(host|gateway)[ \0]'/ ":fields:field:(host gateway $fields)" \ + /$WORD/ -values=3Dhosts ':hosts:host:_hosts' \ + \|\ + /$'inet(6|)[ \0]'/ \ + \( /$'host[ \0]'/ ':fields:field:(host)' \| \) \ + /$WORD/ -values=3Dhosts ':hosts:host:_hosts' \ + \|\ + /$'ethertype[ \0]'/ \ + /$WORD/ ':numbers:number:' \ + \|\ + /$'(ipaddr|etheraddr|atalkaddr)[ \0]'/ \ + /$WORD/ ':addresses:address:' \ + \|\ + /$'llc[ \0]'/\ + /$'((s|u|rr|rnr|rej|ui|ua|disc|sabme|test|xid|frmr)[ \0]|)'/ ':ty= pes:type:(s u rr rnr rej ui ua disc sabme test xid frmr)' \ + \|\ + /$'(ifname|on)[ \0]'/ \ + /$WORD/ ':interfaces:interface:_net_interfaces' \ + \|\ + /$'(rnr|rulenum|srnr|subruleset)[ \0]'/ \ + /$WORD/ ':rules:rule number:' \ + \|\ + /$'reason[ \0]'/ \ + /$WORD/ ':reasons:reason:(match bad-offset fragment short normali= ze memory)' \ + \|\ + /$'(rset|ruleset)[ \0]'/ \ + /$WORD/ ':rule-sets:rule set:' \ + \|\ + /$'action[ \0]'/ \ + /$WORD/ ':actions:action:(pass block nat rdr binat scrub)' \ + \|\ + /$'rpc[ \0]'/ \ + \(\ + /$'[^, \0]##[ \0]'/ ':programs:rpc program:compadd -qS, - ${${(= f)"$(