#compdef iw # Some parameters to hold patterns that will be used later. local xp='[[:xdigit:]][[:xdigit:]]' local -a bssid devices flags fouraddr fouronoff frequency high_throughput ifacename ifacetype ifacetypes local -a matchany matchnum key lladdr lladdrs meshid meshidval ssid value # matches any word matchany=(/$'[^\0]##\0'/) # matches any number matchnum=(/$'[[:digit:]]##\0'/) # matches any BSSID bssid=($matchany ':bssid:BSSID:') # matches any devices devices=( /$'[[:alpha:]]##[[:digit:]]##(\.[[:digit:]]##)#\0'/ ':interfaces:network_interface:_net_interfaces' ) # matches the word 'flags' followed by a list of some of the following words: none fcsfail control otherbss cook flags=(/$'flags\0'/ ':flags:flags:(flags)' $matchany ':flags:flags:(none fcsfail control otherbss cook)' \#) # matches the word '4addr' followed by either 'on' or 'off' fouronoff=(/$'(on|off)\0'/ ':4addr:4addr:(on off)') fouraddr=( /$'4addr\0'/ ':4addr:4addr:(4addr)' $fouronoff ) # matches any number (description is 'frequency') frequency=($matchnum ':freq:frequency:') # matches one of HT20 HT40+ or HT40- high_throughput=(/$'HT[0-9]##(+|-)#\0'/ ':HT:high throughput:(HT20 HT40+ HT40-)') # matches any name (description is 'name') ifacename=($matchany ':name:name:') # matches the word 'type' followed by one of: managed ibss monitor mesh wds ifacetypes=(/$'(managed|ibss|monitor|mesh|wds)\0'/ ':type:type:(managed ibss monitor mesh wds)') ifacetype=(/$'type\0'/ ':type:type:(type)' $ifacetypes) # matches any word (description is 'key') key=($matchany ':key:key:') # matches a MAC address (i.e. a sequence of six 2-digit numbers separated by spaces), $xp is defined earlier. lladdr=(/"${xp}:${xp}:${xp}:${xp}:${xp}:${xp}"$'\0'/ ':lladdress:link layer (MAC) address:') # as above but with a different description lladdrs=(/"${xp}:${xp}:${xp}:${xp}:${xp}:${xp}"$'\0'/ ':lladdress:link layer (MAC) addresses (use - to match any octet):' \#) # matches the word 'mesh_id' followed by a number meshidval=($matchnum ':meshid:mesh ID:') meshid=(/$'mesh_id\0'/ ':meshid:meshid:(mesh_id)' $meshidval) # matches any word (description 'SSID') ssid=($matchany ':ssid:SSID:') # matches any word (description 'value') value=($matchany ':val:value:') # matches any number (description 'value') numvalue=($matchnum ':val:value:') # Use the _regex_words function to create a variable containing command words to go after "iw reg" local -a reg_cmds _regex_words regulatory-commands "reg command" \ 'g*et:print out the kernels current regulatory domain information'\ 's*et:notify the kernel about the current regulatory domain' reg_cmds=("$reply[@]") # Options for to go after "iw event" local -a event_opts _regex_words event-options "event option" \ '-t:print timestamp' \ '-r:print relative timestamp' \ '-f:print full frame for auth/assoc etc' event_opts=("$reply[@]") # Commands to go after "iw phy wowlan enable" local -a phy_wowlan_enable_cmds _regex_words phy-wowlan-enable-commands "phy WoWLAN enable commands" \ '4*way-handshake:enable WoWLAN with 4way handshake trigger' \ 'a*ny:enable WoWLAN with any trigger' \ 'd*isconnect:enable WoWLAN with disconnect trigger' \ 'e*ap-identity-request:enable WoWLAN with EAP identity request trigger' \ 'g*tk-rekey-failure:enable WoWLAN with gtk rekey failure trigger' \ 'm*agic-packet:enable WoWLAN with magic packet trigger' \ 'p*atterns:MAC address triggers:$lladdrs' \ 'r*fkill-release:enable WoWLAN with rfkill release trigger' phy_wowlan_enable_cmds=("$reply[@]") # Commands to go after "iw phy wowlan" local -a phy_wowlan_cmds _regex_words phy-wowlan-commands "phy WoWLAN commands" \ 's*how:show WoWLAN status' \ 'd*isable:disable WoWLAN' \ 'e*nable:enable WoWLAN:$phy_wowlan_enable_cmds' phy_wowlan_cmds=("$reply[@]") # Some parameters to hold patterns that will be used for "iw phy set" commands # (not perfect, but mostly OK). local -a phy_set_antenna phy_set_channel phy_set_coverage phy_set_frag phy_set_freq phy_set_distance local -a phy_set_name phy_set_netns phy_set_rts phy_set_txpower phy_txpower_opt phy_set_antenna=($matchany ':antenna:bitmap:') phy_set_channel=($matchnum ':channel:channel (1-14):' $high_throughput) phy_set_coverage=($matchnum ':coverage:coverage class (0-255):') phy_set_distance=($matchnum ':distance:valid values\: 0 - 114750:') phy_set_frag=(/$'([0-9]##|off)\0'/ ':channel:channel (1-14):(1 2 3 4 5 6 7 8 9 10 11 12 13 14 off)') phy_set_freq=($frequency $high_throughput) phy_set_name=($matchany ':name:device name:') phy_set_netns=($matchany ':netns:network namespace:') phy_set_rts=($matchnum ':rts:rts threshold:') phy_txpower_opt=($matchany ':txpower:tx power in mBm:') _regex_words phy-set-txpower "set txpower" \ 'a*uto:auto:' \ 'f*ixed:fixed:$phy_txpower_opt' \ 'l*imit:limit:$phy_txpower_opt' phy_set_txpower=("$reply[@]") # Commands to go after "iw phy set" local -a phy_set_cmds _regex_words phy-set-commands "phy set commands" \ 'a*ntenna:set a bitmap of allowed antennas to use for TX and RX:$phy_set_antenna' \ 'ch*annel:set channel:$phy_set_channel' \ 'co*verage:set coverage class (1 for every 3 usec of air propagation time):$phy_set_coverage' \ 'd*istance:set appropriate coverage class for given link distance in meters:$phy_set_distance' \ 'fra*g:set fragmentation threshold:$phy_set_frag' \ 'fre*q:set frequency/channel the hardware is using, including HT configuration:$phy_set_freq' \ 'na*me:rename this wireless device:$phy_set_name' \ 'ne*tns:set network namespace:$phy_set_netns' \ 'r*ts:set rts threshold:$phy_set_rts' \ 't*xpower:specify transmit power level and setting type:$phy_set_txpower' phy_set_cmds=("$reply[@]") # Commands to go after "iw phy interface" local -a phy_interface_cmds # This needs work (should not offer meshid, fouraddr of flags more than once, and need to accomodate multiple flag options) phy_interface_cmds=(\( /$'add\0'/ ':add:add a new virtual interface with the given configuration:(add)' $ifacename $ifacetype \ \( $meshid \| $fouraddr \| $flags \) \# \)) # Commands to go after "iw phy " local -a phy_cmds _regex_words phy-commands "phy command" \ 's*et:set/configure interface properties:$phy_set_cmds' \ 'inf*o:show capabilities for the specified wireless device' \ 'int*erface:add a new virtual interface with the given configuration:$phy_interface_cmds' \ 'w*owlan:WoWLAN commands:$phy_wowlan_cmds' phy_cmds=("$reply[@]") # Parameters to hold patterns for dev commands local -a dev_cmds_connect dev_cmds_cqm dev_cmds_get dev_cmds_ibss dev_cmds_interface dev_cmds_mesh dev_cmds_scan_options local -a dev_cmds_mpath dev_cmds_offchannel dev_cmds_roc dev_cmds_scan dev_cmds_set dev_cmds_station dev_cmds_survey dev_cmds_connect=($ssid $frequency $bssid $key) dev_cmds_cqm=(/$'rssi\0'/ ':rssi:rssi:(rssi)' $matchnum ':thresh:threshold:' $matchnum ':hysteresis:hysteresis:') dev_cmds_get=(/$'(mesh_param|power_save)\0'/ ':get:parameter:(mesh_param power_save)' $value) # TODO: THIS NEEDS WORK! THE FINAL OPTIONS FOR JOIN NEED WORK # dev ibss join [fixed-freq] [] [beacon-interval ] [basic-rates ] [mcast-rate ] [key d:0:abcde] dev_cmds_ibss=(\( /$'leave\0'/ ':cmd:command:((leave:"Leave the IBSS cell"))' \| \( /$'join\0'/ ':cmd:command:((join\:"Join an IBSS cell"))' $ssid $frequency \( /$'fixed-freq\0'/ ':opt:option:((fixed-freq\:"fixed frequency (no args)"))' \| $bssid \| /$'beacon-interval\0'/ ':opt:option:((beacon-interval\:"beacon interval (takes single arg)"))' $numvalue \| /$'basic-rates\0'/ ':opt:option:((basic-rates\:"basic rates (comma separated list of rates)"))' $numvalue \| /$'mcast-rate\0'/ ':opt:option:((mcast-rate\:"multicast rate (takes single arg)"))' $numvalue \| $key \) \# \) \)) dev_cmds_interface=(/$'add\0'/ ':add:add:(add)' $ifacename $ifacetype \( $meshid \| $fouraddr \| $flags \) \# ) dev_cmds_mesh=(\( /$'leave\0'/ ':leave:leave a mesh:(leave)' \| /$'join\0'/ ':join:join a mesh:(join)' \ $matchnum ':meshid:mesh ID:' $matchany ':parameter:mesh parameters [=]*:' \# \)) dev_cmds_mpath=(\( /$'(del|get)\0'/ ':mpath:mesh path command:((del\:"remove the mesh path to the given node" \ get\:"get information on mesh path to the given node"))' $lladdr \| /$'(new|set)\0'/ ':mpath:mesh path \ command:((new\:"create a new mesh path (instead of relying on automatic discovery)" set\:"set an existing mesh \ paths next hop"))' $lladdr /$'next_hop\0'/ ':nexthop:next hop:(next_hop)' $lladdr \| /$'dump\0'/ ':mpath:mesh path \ command:((dump\:"list known mesh paths"))' \)) dev_cmds_offchannel=($frequency $matchnum ':duration:duration:') dev_cmds_roc=(/$'start\0'/ ':start:start:(start)' $frequency $matchnum ':time:time:') dev_cmds_scan_options=(/$'freq\0'/ ':freq:freq:(freq)' $frequency $frequency \# /$'ies\0'/ ':ies:ies:(ies)' $lladdr \( /$'ssid\0'/ ':ssid:ssid:(ssid)' $ssid \# \| /$'passive\0'/ ':opt:passive:(passive)' \)) dev_cmds_scan=(\( $dev_cmds_scan_options \| $matchany -'! [[ $match[1] =~ "dump|trigger" ]]' ':opt:option:((-u\:"include unknown data in results" \:""))' $dev_cmds_scan_options \| /$'dump\0'/ ':cmd:command:((dump\:"dump the current scan results"))' $matchany ':opt:option:((-u\:"include unknown data in results" \:""))' \| /$'trigger\0'/ ':cmd:command:((trigger\:"trigger a scan on the given frequencies with probing for the given SSIDs (or wildcard if not given) unless passive scanning is requested"))' $dev_cmds_scan_options \)) local -a dev_cmds_set_bitrates dev_cmds_set_freq dev_cmds_set_mesh_param local -a dev_cmds_set_monitor dev_cmds_set_peer dev_cmds_set_power_save local -a dev_cmds_set_type dev_cmds_set_txpower # dev set bitrates [legacy-<2.4|5> *] dev_cmds_set_bitrates=(/$'legacy-*\0'/ ':opt:legacy:(legacy-2.4 legacy-2.5)' $matchnum ':rate:legacy rate in Mbps:') # dev set freq [HT20|HT40+|HT40-] dev_cmds_set_freq=($frequency $high_throughput) # dev set mesh_param = [=]* dev_cmds_set_mesh_param=( $matchany ':val:param=value:' \# ) # dev set monitor * dev_cmds_set_monitor=( $matchany ':flag:flag:((none\:"no special flags" fcsfail\:"show frames with FCS errors"\ control\:"show control frames" otherbss\:"show frames from other BSSes" cook\:"use cooked mode"))' \# ) # dev set peer dev_cmds_set_peer=($lladdr) # dev set power_save dev_cmds_set_power_save=(/$'(on|off)\0'/ ':opt:power save mode:(on off)') _regex_words setcmds "dev set commands" \ '4*addr:set interface 4addr (WDS) mode:$fouronoff'\ 'b*itrates:set/clear specified rate masks:$dev_cmds_set_bitrates'\ 'c*hannel:set channel:$phy_set_channel'\ 'f*req:set frequency:$dev_cmds_set_freq'\ 'mesh_param:set mesh parameters:$dev_cmds_set_mesh_param'\ 'meshid:set mesh id:$meshidval'\ 'mo*nitor:set monitor flags:$dev_cmds_set_monitor'\ 'pe*er:set interface WDS peer MAC address:$dev_cmds_set_peer'\ 'po*wer_save:set power save on/off:$dev_cmds_set_power_save'\ 'tx*power:set transmission power:$phy_set_txpower'\ 'ty*pe:set type:$ifacetypes' dev_cmds_set=("$reply[@]") local -a dev_cmds_station_plink dev_cmds_station_vlan dev_cmds_station_plink=(/$'(open|block)\0'/ ':opt::(open block)') dev_cmds_station_vlan=($matchnum ':val:ifindex:') local -a dev_cmds_station_set _regex_words stationsetcmds "dev station set commands"\ 'plink_action:set peer link action:$dev_cmds_station_plink'\ 'vlan:set AP VLAN:$dev_cmds_station_vlan' dev_cmds_station_set=(\( $lladdr \) "$reply[@]") _regex_words stationcmds "dev station commands" \ 'del:remove the given station entry (use with caution!):$lladdr'\ 'dump:list all stations known, e.g. the AP on managed interfaces:'\ 'get:get information for a specific station:$lladdr'\ 'set:set AP VLAN or mesh peer link action:$dev_cmds_station_set' dev_cmds_station=("$reply[@]") dev_cmds_survey=(/$'dump\0'/ ':dump:list all gathered channel survey data:(dump)') local -a dev_cmds _regex_words dev-commands "dev commands" \ 'co*nnect:join a network:$dev_cmds_connect' \ 'cq*m:set connection quality monitor RSSI threshold:$dev_cmds_cqm' \ 'de*l:remove this virtual interface' \ 'di*sconnect:disconnect from the current network' \ 'g*et:retrieve mesh parameter / power save state:$dev_cmds_get' \ 'ib*ss:join/leave IBSS cell:$dev_cmds_ibss' \ 'inf*o:show information for this interface' \ 'int*erface:add an interface:$dev_cmds_interface' \ 'l*ink:print information about the current link, if any' \ 'me*sh:join/leave a mesh:$dev_cmds_mesh' \ 'mp*ath:mesh path commands:$dev_cmds_mpath' \ 'o*ffchannel:leave operating channel and go to the given channel for a while:$dev_cmds_offchannel' \ 'r*oc:roc:$dev_cmds_roc' \ 'sc*an:scan:$dev_cmds_scan' \ 'se*t:set interface parameter:$dev_cmds_set' \ 'st*ation:station commands:$dev_cmds_station' \ 'su*rvey:list all gathered channel survey data:$dev_cmds_survey' dev_cmds=( $devices "$reply[@]") # Arguments to _regex_arguments, built up in array $args. local -a args reply # Command word. Don't care what that is. args=( $matchany ) local -a phydevs phy_devs=( \( $(iw list|grep '^[[:alnum:]]\+'|cut -f 2 -d ' ') \) ) phy_cmds=( \( $matchany ":test:test:$phy_devs[*]" \) "$phy_cmds[@]" ) _regex_words commands "iw command" \ 'd*ev:commands to control/list the software devices:$dev_cmds' \ 'e*vent:monitor events from the kernel:$event_opts' \ 'h*elp:print usage for each command' \ 'l*ist:list all wireless devices and their capabilities' \ 'p*hy:commands to control the physical device:$phy_cmds' \ 'r*eg:get/set regulatory domain:$reg_cmds' args+=("$reply[@]") _regex_arguments _iw "${args[@]}" _iw "$@" # Local Variables: # mode:shell-script # End: