Subject: PATCH: update Solaris completions for Solaris 11 update 3
From: Oliver Kiddle <[email-masked]>
To: Zsh workers <[email-masked]>
Date: Fri, 19 Aug 2016 18:30:27 +0200
List-Id: Zsh Workers List <zsh-workers.zsh.org>

This updates some of the Solaris specific completion functions for
changes in Solaris 11.3. Many of these got reindented and descriptions
changed to remove initial caps. Also _sort needed tweaking as the
Solaris sort now supports -C. I've not updated zfs, zpool and zoneadm
completions as they're a bigger job. Also savecore's -? output indicates
changes but they're otherwise undocumented.

Where I've added $OSTYPE checks, I can't do much better than
solaris2.<11->. uname -v does return 11.3. I think illumos based systems
also still indicate solaris2.11

Oliver

diff --git a/Completion/Solaris/Command/_beadm b/Completion/Solaris/Command/_beadm
index 8422653..cdb324e 100644
--- a/Completion/Solaris/Command/_beadm
+++ b/Completion/Solaris/Command/_beadm
@@ -1,9 +1,10 @@
 #compdef beadm
 
-local cmd expl args
+local cmd expl args cmds
 
 if (( CURRENT == 2 )); then
-  _wanted subcommands expl 'subcommand' compadd \
+  [[ $OSTYPE = solaris* ]] && cmds=( set-policy )
+  _wanted subcommands expl 'subcommand' compadd $cmds \
       activate create destroy list mount rename unmount
   return
 fi
@@ -24,15 +25,16 @@ case $cmd in
       '*-o[property]:zfs property'
       '-p[create new BE in specified zfs pool]:zfs pool:_zfs_pool'
     )
-    _arguments -A "-*" $args \
+    _arguments -A "-*" -s $args \
       '-e[base BE]:BE name or snapshot:_be_name -t all' \
       ':new BE name:'
   ;;
   destroy)
     [[ $OSTYPE = solaris* ]] && args=(
       '-f[unmount BE if necessary]'
+      '(:)-O[destroy all orphaned boot environments]'
     )
-    _arguments -A "-*" \
+    _arguments -A "-*" $args \
       "-F[don't prompt for verification]" \
       ':BE or BE snapshot:_be_name'
   ;;
@@ -42,14 +44,16 @@ case $cmd in
     elif [[ $OSTYPE = freebsd* ]]; then
       args=( '-D[display space usage of boot environment]' )
     fi
-    _arguments -A "-*" \
+    _arguments -A "-*" -s $args \
       '-a[list subordinate filesystems and snapshots]' \
       '-s[list snapshots]' \
       '-H[parseable format]' \
       ':boot environment:_be_name'
   ;;
   mount)
-    _arguments -A "-*" \
+    [[ $OSTYPE = solaris* ]] &&
+        args=( '-b[mount associated boot pool dataset]' )
+    _arguments -A "-*" $args \
       ':BE name:_be_name' \
       ':mountpoint:_path_files -/'
   ;;
@@ -58,6 +62,11 @@ case $cmd in
       ':existing boot environment name:_be_name' \
       ':new boot environment:'
   ;;
+  set-policy)
+    _arguments -A "-*" \
+      '*-n[specify policy]:policy:(static -static noevict -noevict)' \
+      '*:BE name:_be_name'
+  ;;
   u(n|)mount)
     _arguments -A "-*" \
       '-f[force unmount]' \
diff --git a/Completion/Solaris/Command/_coreadm b/Completion/Solaris/Command/_coreadm
index c37e2b0..7262e64 100644
--- a/Completion/Solaris/Command/_coreadm
+++ b/Completion/Solaris/Command/_coreadm
@@ -1,48 +1,45 @@
 #compdef coreadm
 
-_coreadm() {
-	local -a content option
+local -a content option
 
-	content=(
-		"anon[anonymous private mappings]"
-		"ctf[CTF type information]"
-		"data[writable private file mappings]"
-		"dism[DISM mappings]"
-		"heap[process heap]"
-		"ism[ISM mappings]"
-		"rodata[read-only private file mappings]"
-		"shanon[anonymous shared mappings]"
-		"shfile[file-backed shared mappings]"
-		"shm[System V shared memory]"
-		"stack[process stack]"
-		"symtab[symbol table sections for loaded files]"
-		"text[readable and executable private file mappings]"
-	)
+content=(
+  "anon[anonymous private mappings]"
+  "ctf[CTF type information]"
+  "data[writable private file mappings]"
+  "dism[DISM mappings]"
+  "heap[process heap]"
+  "ism[ISM mappings]"
+  "rodata[read-only private file mappings]"
+  "shanon[anonymous shared mappings]"
+  "shfile[file-backed shared mappings]"
+  "shm[System V shared memory]"
+  "stack[process stack]"
+  "symtab[symbol table sections for loaded files]"
+  "text[readable and executable private file mappings]"
+)
 
-	option=(
-		"global"\:"Allow global core dumps"
-		"global-setid"\:"Allow set-id global core dumps"
-		"log"\:"Generate a syslog message on global core dump"
-		"process"\:"Allow per-process core dumps"
-		"proc-setid"\:"Allow set-id per-process core dumps"
-	)
+option=(
+  'global:allow global core dumps'
+  'process:allow per-process core dumps'
+  'global-setid:allow set-id global core dumps'
+  'proc-setid:allow set-id per-process core dumps'
+  'log:generate a syslog message on global core dump'
+  'kzone:allow kernel zone core dumps'
+)
 
-	# _values doesn't quite work for us here -- the separator can be either
-	# "+" or "-"
-	_arguments -s \
-		- set1 \
-		'-g[global core file name pattern]:' \
-		'-G[global core file content]:content:_values -s + "content" $content' \
-		'-i[per-process core file name pattern]:' \
-		'-I[per-process core file content]:content:_values -s + "content" $content' \
-		'*-d[disable core option]:option:(($option))' \
-		'*-e[enable core option]:option:(($option))' \
-		- set2 \
-		'-p[PID-specific per-process core file name pattern]:' \
-		'-P[PID-specific per-process core file content]:content:_values -s + "content" $content' \
-		'*:pids:_pids' \
-		- set3 \
-		'-u[update options from coreadm.conf]'
-}
-
-_coreadm "$@"
+# _values doesn't quite work for us here -- the separator can be either
+# "+" or "-"
+_arguments -s \
+  - set1 \
+  '-g[global core file name pattern]:' \
+  '-G[global core file content]:content:_values -s + "content" $content' \
+  '-i[per-process core file name pattern]:' \
+  '-I[per-process core file content]:content:_values -s + "content" $content' \
+  '*-d[disable core option]:option:(($option))' \
+  '*-e[enable core option]:option:(($option))' \
+  - set2 \
+  '-p[PID-specific per-process core file name pattern]:' \
+  '-P[PID-specific per-process core file content]:content:_values -s + "content" $content' \
+  '*:pids:_pids' \
+  - set3 \
+  '-u[update options from coreadm.conf]'
diff --git a/Completion/Solaris/Command/_dladm b/Completion/Solaris/Command/_dladm
index 5e5ab01..036c179 100644
--- a/Completion/Solaris/Command/_dladm
+++ b/Completion/Solaris/Command/_dladm
@@ -1,723 +1,734 @@
 #compdef dladm
-# Synced with the S11U1 build 19 man page
 
 _dladm_links() {
-	compadd "$@" - $(dladm show-link -p -o link)
+  compadd "$@" - $(_call_program links dladm show-link -p -o link)
 }
 
 _dladm_devs() {
-	compadd "$@" - $(dladm show-phys -p -o device)
+  compadd "$@" - $(_call_program devices dladm show-phys -p -o device)
 }
 
 _dladm_aggrs() {
-	compadd "$@" - $(dladm show-aggr -p -o link)
+  compadd "$@" - $(_call_program aggregations dladm show-aggr -p -o link)
 }
 
 _dladm_aggr_ports() {
-	compadd "$@" - $(dladm show-aggr -p -x -o ports)
+  compadd "$@" - $(_call_program ports dladm show-aggr -p -x -o ports)
 }
 
 _dladm_vlans() {
-	compadd "$@" - $(dladm show-vlan -p -o link)
+  compadd "$@" - $(_call_program vlans dladm show-vlan -p -o link)
 }
 
 _dladm_wifi_links() {
-	compadd "$@" - $(dladm show-wifi -p -o link)
+  compadd "$@" - $(_call_program wifi-links dladm show-wifi -p -o link)
 }
 
 _dladm_wifi_nets() {
-	compadd "$@" - ${(f)"$(dladm scan-wifi -p -o essid)"}
+  compadd "$@" - ${(f)"$(_call_program networks dladm scan-wifi -p -o essid)"}
 }
 
 _dladm_secobjs() {
-	compadd "$@" - ${(f)"$(dladm show-secobj -p -o object)"}
+  compadd "$@" - ${(f)"$(_call_program secure-objects dladm show-secobj -p -o object)"}
 }
 
 _dladm_ethers() {
-	compadd "$@" - $(dladm show-ether -p -o link)
+  compadd "$@" - $(_call_program ethers dladm show-ether -p -o link)
 }
 
 _dladm_vnics() {
-	compadd "$@" - $(dladm show-vnic -p -o link)
+  compadd "$@" - $(_call_program vnics dladm show-vnic -p -o link)
 }
 
 _dladm_etherstubs() {
-	compadd "$@" - $(dladm show-etherstub)
+  compadd "$@" - $(_call_program etherstubs dladm show-etherstub)
 }
 
 _dladm_bridges() {
-	compadd "$@" - $(dladm show-bridge -p -o bridge)
+  compadd "$@" - $(_call_program bridges dladm show-bridge -p -o bridge)
 }
 
 _dladm_iptuns() {
-	compadd "$@" - $(dladm show-iptun -p -o link)
+  compadd "$@" - $(_call_program ip-tunnels dladm show-iptun -p -o link)
 }
 
 _dladm_parts() {
-	compadd "$@" - $(dladm show-part -p -o link)
+  compadd "$@" - $(_call_program parts dladm show-part -p -o link)
 }
 
 _dladm_iblinks() {
-	compadd "$@" - $(dladm show-ib -p -o link)
+  compadd "$@" - $(_call_program iblinks dladm show-ib -p -o link)
 }
 
 _dladm() {
-	local context state line expl
-	typeset -A opt_args
-	local -a subcmds
-	local -a linkprops linkprops_general linkprops_nonvlanvnic linkprops_wifi
-	local -a linkprops_ether linkprops_ib linkprops_iptun
-	local -a link_properties link_stats_properties vnic_properties
-	local -a aggr_properties aggr_lacp_properties aggr_ext_properties
-	local -a vlan_properties wifi_properties wifi_connect_properties
-	local -a ether_properties linkprop_properties secobj_properties
-	local -a bridge_properties bridge_stats_properties bridge_link_properties
-	local -a bridge_link_stats_properties bridge_fwd_properties
-	local -a bridge_fwd_properties bridge_trill_properties
-	local -a iptun_properties tunnel_values part_properties ib_properties
-
-	# TODO: some subcommands can take multiple comma-separated targets
-	# TODO: some option sets may be different based on other commandline flags
-	# TODO: some subcommands may take different arguments based on options
-
-	subcmds=(
-		"help" "show-ether" "show-ib" "show-usage"
-		{"rename","show"}"-link"
-		{"add","create","delete","modify","remove","show"}"-aggr"
-		{"connect","disconnect","scan","show"}"-wifi"
-		{"reset","set","show"}"-linkprop"
-		{"create","delete","show"}"-secobj"
-		{"create","delete","modify","show"}"-vlan"
-		{"delete","show"}"-phys"
-		{"create","delete","modify","show"}"-vnic"
-		{"create","delete","show"}"-etherstub"
-		{"create","modify","delete","add","remove","show"}"-bridge"
-		{"create","modify","delete","show"}"-iptun"
-		{"create","delete","show"}"-part"
-	)
-
-	if [[ $service == "dladm" ]]; then
-		_arguments -C -A "-*" \
-			'-\?[Help]' \
-			'*::command:->subcmd' && return 0
-
-		if (( CURRENT == 1 )); then
-			_wanted commands expl "dladm subcommand" compadd -a subcmds
-			return
-		fi
-		service="$words[1]"
-		curcontext="${curcontext%:*}=$service:"
-	fi
-
-	link_properties=( "link" "zone" "class" "mtu" "state" "over" )
-	link_stats_properties=( "link" "ipackets" "rbytes" "ierrors" "opackets" "obytes" "oerrors" )
-
-	aggr_properties=( "link" "policy" "addrpolicy" "lacpactivity" "lacptimer" "mode" "flags" )
-	aggr_lacp_properties=( "link" "port" "aggregatable" "sync" "coll" "dist" "defaulted" "expired" )
-	aggr_ext_properties=( "link" "port" "speed" "duplex" "state" "address" "portstate" )
-
-	vlan_properties=( "link" "vid" "over" "flags" )
-
-	wifi_connect_properties=( "link" "essid" "bssid" "sec" "mode" "strength" "speed" "bsstype" )
-	wifi_properties=( $wifi_connect_properties "status" "auth" )
-
-	ether_properties=( "link" "ptype" "state" "auto" "speed-duplex" "pause" "rem_fault" )
-
-	linkprop_properties=( "link" "property" "value" "default" "possible" )
-
-	secobj_properties=( "object" "class" )
-
-	vnic_properties=( "link" "over" "speed" "macaddr" "macaddrtype" )
-
-	bridge_properties=( "bridge"  "address" "priority" "bmaxage" "bhellotime" "bfwddelay" 
-		"forceproto" "tctime" "tccount" "tchange" "desroot" "rootcost" "rootport"
-		"maxage" "hellotime" "fwddelay" "holdtime" )
-	bridge_stats_properties=( "bridge" "drops" "forwards" "mbcast" "recv" "sent" "unknown" )
-	bridge_link_properties=( "link" "index" "state" "uptime" "opercost" "operp2p" "operedge" 
-		"desroot" "descost" "desbridge" "desport" "tcack" )
-	bridge_link_stats_properties=( "link" "cfgbpdu" "tcnbpdu" "rstpbpdu" "txbpdu" "drops" "recv" "xmit" )
-	bridge_fwd_properties=( "dest" "age" "flags" "output" )
-	bridge_trill_properties=( "nick" "flags" "link" "nexthop" )
-
-	iptun_properties=( "link" "type" "flags" "local" "remote" )
-	tunnel_values=( "local:address/host: " "remote:address/host: " )
-
-	part_properties=( "link" "pkey" "over" "state" "flags" )
-
-	ib_properties=( "link" "hcaguid" "portguid" "port" "state" "pkeys" )
-
-	linkprops_general=(
-		"autopush:streams modules:"
-		"cos:value:(0 1 2 3 4 5 6 7)"
-		"cpus:processors:"
-		"cpus-effective"
-		"etsbw-lcl:percentage:"
-		"etsbw-lcl-advice"
-		"etsbw-lcl-effective"
-		"etsbw-rmt-effective"
-		"lro:value:(off on auto)"
-		"lro-effective"
-		"mac-address:MAC address:"
-		"maxbw:bandwith:"
-		"pool:pools:"
-		"pool-effective"
-		"priority:priority:(high medium low)"
-		"rxringsavail"
-		"rxrings:value:"
-		"rxhwclntavail"
-		"txringsavail"
-		"txrings:value:"
-		"txhwclntavail"
-		"forward:value:(0 1)"
-		"stp_priority:value:"
-		"stp_cost:value:"
-		"stp_edge:value:(0 1)"
-		"stp_p2p:value:(true false auto)"
-		"stp_mcheck:value:(0 1)"
-		"protection:value:(mac-nospoof ip-nospoof dhcp-nospoof restricted)"
-		"vsi-mgrid:IPv6 address:"
-		"vsi-mgrid-effective"
-		"vsi-mgrid-enc:encoding:(oracle_v1 none)"
-		"vsi-mgrid-enc-effective"
-		"vsi-typeid:value:"
-		"vsi-typeid-effective"
-		"vsi-vers:value:"
-		"vsi-vers-effective"
-		"zone:value:_zones"
-	)
-	linkprops_nonvlanvnic=(
-		"default_tag:value:"
-		"learn_decay:value:"
-		"learn_limit:value:"
-		"rxfanout:value:"
-		"rxfanout-effective:value:"
-		"stp:value:(0 1)"
-	)
-	linkprops_wifi=(
-		"channel:value:"
-		"powermode:value:(off max fast)"
-		"radio:value:(on off)"
-		"speed:value:"
-	)
-	linkprops_ether=(
-		"duplex"
-		"state"
-		"adv_autoneg_cap"
-		"adv_10gfdx_cap"
-		"adv_1000fdx_cap"
-		"adv_1000hdx_cap"
-		"adv_100fdx_cap"
-		"adv_100hdx_cap"
-		"adv_10fdx_cap"
-		"adv_10hdx_cap"
-		"en_10gfdx_cap:value:(0 1)"
-		"en_1000fdx_cap:value:(0 1)"
-		"en_1000hdx_cap:value:(0 1)"
-		"en_100fdx_cap:value:(0 1)"
-		"en_100hdx_cap:value:(0 1)"
-		"en_10fdx_cap:value:(0 1)"
-		"en_10hdx_cap:value:(0 1)"
-		"flowctrl:value:(auto no rx tx pfc bi)"
-		"flowctrl-effective"
-		"gvrp-timeout:value:"
-		"mtu:value:"
-		"ntcs"
-		"pfcmap:value:"
-		"pfcmap-lcl-effective"
-		"pfcmap-rmt-effective"
-		"speed"
-		"tagmode:value:(normal vlanonly)"
-		"vlan-announce:value:(off gvrp)"
-	)
-	linkprops_ib=(
-		"linkmode:value:(cm ud)"
-	)
-	linkprops_iptun=(
-		"hoplimit:value:"
-		"encaplimit:value:"
-	)
-	linkprops=(
-		$linkprops_general $linkprops_wifi $linkprops_ether
-		$linkprops_ib $linkprops_iptun
-	)
-
-	case $service in
-	("help")
-		_arguments ':subcommand:($subcmds)'
-		;;
-
-	("show-link")
-		_arguments -A "-*" \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent link configuration]' \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			- set1 \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $link_properties' \
-			- set2 \
-			'(-s --statistics)'{-s,--statistics}'[Display link statistics]' \
-			'(-i --interval)'{-i,--interval}'[Specify an interval]:interval:' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $link_stats_properties' \
-			':link name:_dladm_links'
-		;;
-
-	("rename-link")
-		_arguments -A "-*" \
-			'-R[Root directory]:directory:_path_files -/' \
-			':old link name:_dladm_links' \
-			':new link name:'
-		;;
-
-	("show-phys")
-		_arguments -A "-*" \
-			'-D[Show Data Center Bridging information]:featureset:(ets pfc)' \
-			'-H[Show hardware resource usage]' \
-			'-L[Display location information]' \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent link configuration]' \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'-m[Display MAC address information]' \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			'(-s --statistics)'{-s,--statistics}'[Display link statistics]' \
-			'(-i --interval)'{-i,--interval}'[Specify an interval]:interval:' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" link media state speed duplex device' \
-			':physical link name:_dladm_devs'
-		;;
-
-	("delete-phys")
-		_arguments -A "-*" \
-			':physical link name:_dladm_devs'
-		;;
-
-	("create-aggr")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Aggregation should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-l --link)'{-l,--link}'[Component link]:link:_dladm_links' \
-			'(-m --mode)'{-m,--mode}'[Aggregation mode]:mode:(dlmp trunk)' \
-			'(-P --policy)'{-P,--policy}'[Port selection policy]:policy:_values -s , "policy" L2 L3 L4' \
-			'(-L --lacp-mode)'{-L,--lacp-mode}'[LACP mode]:lacp mode:(off active passive)' \
-			'(-T --lacp-timer)'{-T,--lacp-timer}'[LACP timer]:lacp timer:(short long)' \
-			'(-u --unicast)'{-u,--unicast}'[Unicast address]:unicast address:' \
-			':aggregate link name:'
-		;;
-
-	("modify-aggr")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Aggregation should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-l --link)'{-l,--link}'[Component link]:link:_dladm_links' \
-			'(-m --mode)'{-m,--mode}'[Aggregation mode]:mode:(dlmp trunk)' \
-			'(-P --policy)'{-P,--policy}'[Port selection policy]:policy:_values -s , "policy" L2 L3 L4' \
-			'(-L --lacp-mode)'{-L,--lacp-mode}'[LACP mode]:lacp mode:(off active passive)' \
-			'(-T --lacp-timer)'{-T,--lacp-timer}'[LACP timer]:lacp timer:(short long)' \
-			'(-u --unicast)'{-u,--unicast}'[Unicast address]:unicast address:' \
-			':aggregate link name:_dladm_aggrs'
-		;;
-
-	("delete-aggr")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Deletion should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			':aggregate link name:_dladm_aggrs'
-		;;
-
-	("add-aggr")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Aggregation should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-l --link)'{-l,--link}'[Component link]:link:_dladm_links' \
-			':aggregate link name:_dladm_aggrs'
-		;;
-
-	("remove-aggr")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Aggregation should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-l --link)'{-l,--link}'[Component link]:link:_dladm_aggr_ports' \
-			':aggregate link name:_dladm_aggrs'
-		;;
-
-	("show-aggr")
-		_arguments -A "-*" \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent link configuration]' \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-s --statistics)'{-s,--statistics}'[Display link statistics]' \
-			'(-i --interval)'{-i,--interval}'[Specify an interval]:interval:' \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			':aggregate link name:_dladm_links' \
-			- set1 \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $aggr_properties' \
-			- lacp \
-			'(-L --lacp)'{-L,--lacp}'[LACP information]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $aggr_lacp_properties' \
-			- extended \
-			'(-x --extended)'{-x,--extended}'[Extended information]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $aggr_ext_properties'
-		;;
-
-	("create-vlan")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[VLAN should be temporary]' \
-			'(-f --force)'{-f,--force}'[Force VLAN creation]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-l --link)'{-l,--link}'[Component link]:link:_dladm_links' \
-			'-v[VLAN ID]:id:' \
-			':VLAN link name:'
-		;;
-
-	("delete-vlan")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Deletion should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			':VLAN link name:_dladm_vlans'
-		;;
-
-	("modify-vlan")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[VLAN should be temporary]' \
-			'(-f --force)'{-f,--force}'[Force VLAN creation]' \
-			'(-R --root-dir)'{-R,--root-dir}'[Root directory]:directory:_path_files -/' \
-			'(-l --link)'{-l,--link}'[Component link]:link:_dladm_links' \
-			'-v[VLAN ID]:id:' \
-			- set1 \
-			'-L[Source link]:link:_dladm_links' \
-			- set2 \
-			':VLAN link name:'
-		;;
-
-	("show-vlan")
-		_arguments -A "-*" \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent link configuration]' \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $vlan_properties' \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			':VLAN link name:_dladm_vlans'
-		;;
-
-	("scan-wifi")
-		_arguments -A "-*" \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $wifi_connect_properties' \
-			':wireless link name:_dladm_wifi_links'
-		;;
-
-	("connect-wifi")
-		_arguments -A "-*" \
-			'(-e --essid)'{-e,--essid}'[ESSID name]:network:_dladm_wifi_nets' \
-			'(-b --bsstype)'{-b,--bsstype}'[BSS type]:' \
-			'(-m --mode)'{-m,--mode}'[802.11 mode]:802.11 mode:(a b g n)' \
-			'(-k --key)'{-k,--key}'[Key name]:key:_dladm_secobjs' \
-			'(-s --sec)'{-s,--sec}'[Security mode]:security mode:(none wep wpa)' \
-			'(-a --auth)'{-a,--auth}'[Authentication mode]:authentication mode:(open shared)' \
-			'(-c --create-ibss)'{-c,--create-ibss}'[Create an ad-hoc network]' \
-			'(-T --timeout)'{-T,--timeout}'[Association timeout]:association timeout:(forever)' \
-			':wireless link name:_dladm_wifi_links'
-		;;
-
-	("disconnect-wifi")
-		_arguments -A "-*" \
-			- set1 \
-			'(-a --all-links)'{-a,--all-links}'[All links]' \
-			- set2 \
-			':wireless link name:_dladm_wifi_links'
-		;;
-
-	("show-wifi")
-		_arguments -A "-*" \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $wifi_properties' \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			':wireless link name:_dladm_wifi_links'
-		;;
-
-	("show-ether")
-		_arguments -A "-*" \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-x --extended)'{-x,--extended}'[Extended output]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $ether_properties' \
-			'-P[protocol]:protocol:(ecp vdp)' \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			':ethernet link name:_dladm_ethers'
-		;;
-
-	("set-linkprop")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Change should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-p --prop)'{-p,--prop}'[Properties]:property:_values -s , "property" ${(M)linkprops\:#*\:*}' \
-			':link name:_dladm_links'
-		;;
-
-	("reset-linkprop")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Change should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-p --prop)'{-p,--prop}'[Properties]:property:_values -s , "property" ${${(M)linkprops\:#*\:*}%%\:*}' \
-			':link name:_dladm_links'
-		;;
-
-	("show-linkprop")
-		_arguments -A "-*" \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent link properties]' \
-			'(-c --parseable)'{-c,--parseable}'[Parseable output]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $linkprop_properties' \
-			'(-p --prop)'{-p,--prop}'[Properties]:property:_values -s , "property" ${linkprops%%\:*}' \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			':link name:_dladm_links'
-		;;
-
-	("create-secobj")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Creation should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-c --class)'{-c,--class}'[Class]:class:(wep wpa)' \
-			'(-f --file)'{-f,--file}'[File containing object value]:file:_path_files' \
-			':object name:'
-		;;
-
-	("delete-secobj")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Deletion should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			':object name:_dladm_secobjs'
-		;;
-
-	("show-secobj")
-		_arguments -A "-*" \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent object information]' \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $secobj_properties' \
-			':object name:_dladm_secobjs'
-		;;
-
-	("create-vnic")
-		# TODO: MAC address completion could be richer
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Creation should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-l --link)'{-l,--link}'[Component link]:link:_dladm_links' \
-			'(-m --mac-address)'{-m,--mac-address}'[MAC address]:address:(factory random auto vrrp)' \
-			'-v[VLAN ID]:id:' \
-			'(-p --prop)'{-p,--prop}'[Property values]:value:_values -s , "property" ${(M)linkprops_general\:#*\:*}' \
-			':VNIC name:'
-		;;
-
-	("delete-vnic")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Deletion should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			':VNIC name:_dladm_vnics'
-		;;
-
-	("modify-vnic")
-		# TODO: MAC address completion could be richer
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Creation should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-l --link)'{-l,--link}'[Component link]:link:_dladm_links' \
-			'(-m --mac-address)'{-m,--mac-address}'[MAC address]:address:(factory random auto vrrp)' \
-			'-v[VLAN ID]:id:' \
-			'(-p --prop)'{-p,--prop}'[Property values]:value:_values -s , "property" ${(M)linkprops_general\:#*\:*}' \
-			- set1 \
-			'-L[Source link]:link:_dladm_links' \
-			- set2 \
-			':VNIC name:'
-		;;
-
-	("show-vnic")
-		_arguments -A "-*" \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent object information]' \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $vnic_properties' \
-			'(-l --link)'{-l,--link}'[Limit to VNICs on link]:link:_dladm_links' \
-			'(-s --statistics)'{-s,--statistics}'[Display VNIC statistics]' \
-			'(-i --interval)'{-i,--interval}'[Specify an interval]:interval:' \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			':VNIC name:_dladm_vnics'
-		;;
-
-	("create-etherstub")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Creation should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			':etherstub name:'
-		;;
-
-	("delete-etherstub")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Deletion should be temporary]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			':etherstub name:_dladm_etherstubs'
-		;;
-
-	("show-etherstub")
-		_arguments -A "-*" \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			':etherstub name:_dladm_etherstubs'
-		;;
-
-	("show-usage")
-		_arguments -A "-*" \
-			'(-f --file)'{-f,--file}'[Read records from file]:file:_path_files' \
-			'(-F --format)'{-F,--format}'[Plotfile format]:plotfile format:(gnuplot)' \
-			'(-p --plot)'{-p,--plot}'[Write plot to file]:' \
-			'(-e --start)'{-e,--start}'[Start time]:date/time (MM/DD/YYYY,hh\:mm\:ss)' \
-			'(-s --stop)'{-s,--stop}'[Stop time]:date/time (MM/DD/YYYY,hh\:mm\:ss)' \
-			':link name:_dladm_links'
-		;;
-
-	("create-bridge")
-		_arguments -A "-*" \
-			'(-P --protect)'{-P,--protect}'[Specify a protection method]:protection method:(stp trill)' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-p --priority)'{-p,--priority}'[Specify the bridge priority]:value' \
-			'(-m --max-age)'{-m,--max-age}'[Specify the max age for config info]:value' \
-			'(-h --hello-time)'{-h,--hello-time}'[Specify the hello time]:value' \
-			'(-d --forward-delay)'{-d,--forward-delay}'[Specify the forward delay]:value' \
-			'(-f --force-protocol)'{-f,--force-protocol}'[Specify forced maximum supported protocol]:value' \
-			'*'{-l,--link}'[Specify link to add]:link:_dladm_links' \
-			':bridge name:'
-		;;
-
-
-	("modify-bridge")
-		_arguments -A "-*" \
-			'(-P --protect)'{-P,--protect}'[Specify a protection method]:protection method:(stp trill)' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-p --priority)'{-p,--priority}'[Specify the bridge priority]:value' \
-			'(-m --max-age)'{-m,--max-age}'[Specify the max age for config info]:value' \
-			'(-h --hello-time)'{-h,--hello-time}'[Specify the hello time]:value' \
-			'(-d --forward-delay)'{-d,--forward-delay}'[Specify the forward delay]:value' \
-			'(-f --force-protocol)'{-f,--force-protocol}'[Specify forced maximum supported protocol]:value' \
-			':bridge name:_dladm_bridges'
-		;;
-
-
-	("delete-bridge")
-		_arguments -A "-*" \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			':bridge name:_dladm_bridges'
-		;;
-
-
-	("add-bridge"|"remove-bridge")
-		_arguments -A "-*" \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'*'{-l,--link}'[Specify link to add]:link:_dladm_links' \
-			':bridge name:_dladm_bridges'
-		;;
-
-
-	("show-bridge")
-		# XXX $bridge_stats_properties get added into -o completions for set1
-		# XXX $bridge_link_stats_properties get added into -o completions for set3
-		_arguments -A "-*" \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			- set1 \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $bridge_properties' \
-			- set2 \
-			'(-s --statistics)'{-s,--statistics}'[Display statistics]' \
-			'(-i --interval)'{-i,--interval}'[Specify an interval]:seconds' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $bridge_stats_properties' \
-			- set3 \
-			'(-l --link)'{-l,--link}'[Display link status or statistics]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $bridge_link_properties' \
-			- set4 \
-			'(-s --statistics)'{-s,--statistics}'[Display statistics]' \
-			'(-l --link)'{-l,--link}'[Display link status or statistics]' \
-			'(-i --interval)'{-i,--interval}'[Specify an interval]:seconds' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $bridge_link_stats_properties' \
-			- set5 \
-			'(-f --forwarding)'{-f,--forwarding}'[Display forwarding entries]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $bridge_fwd_properties' \
-			- set6 \
-			'(-t --trill)'{-t,--trill}'[Display TRILL nickname entries]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $bridge_trill_properties' \
-			':bridge name:_dladm_bridges'
-		;;
-
-
-	("create-iptun")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Temporary tunnel]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-T --type)'{-T,--type}'[Tunnel type]:tunnel type:(ipv4 ipv6 6to4)' \
-			'(-a --address)'{-a,--address}'[Endpoint addresses]:address/host:_values -s , "address/host" $tunnel_values' \
-			':tunnel name:'
-		;;
-
-	("modify-iptun")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Temporary modification]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-a --address)'{-a,--address}'[Endpoint addresses]:address/host:_values -s , "address/host" $tunnel_values' \
-			':tunnel name:_dladm_iptuns'
-		;;
-
-	("delete-iptun")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Temporary deletion]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			':tunnel name:_dladm_iptuns'
-		;;
-
-	("show-iptun")
-		_arguments -A "-*" \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent tunnel configuration]' \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $iptun_properties' \
-			'-Z[Display ZONE column in output]' \
-			'-z[zone]:zonename:_values -s , "zone" $(zoneadm list)' \
-			':tunnel name:_dladm_iptuns'
-		;;
-
-	("create-part")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Temporary partition]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			'(-f --force)'{-f,--force}'[Force partition creation]' \
-			'(-l --link)'{-l,--link}'[IP-over-IB physical link name]:IB link:_dladm_iblinks' \
-			'(-p --prop)'{-p,--prop}'[Set link properties]:link property:_values -s , "property" ${(M)linkprops_nonvlanvnic\:#*\:*} ${(M)linkprops_general\:#*\:*}' \
-			'(-P --pkey)'{-P,--pkey}'[Set parition key]:hex number:' \
-			':partition link name:'
-		;;
-
-	("delete-part")
-		_arguments -A "-*" \
-			'(-t --temporary)'{-t,--temporary}'[Temporary deletion]' \
-			'(-R --root)'{-R,--root}'[Root directory]:directory:_path_files -/' \
-			':link name:_dladm_parts'
-		;;
-
-	("show-part")
-		_arguments -A "-*" \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent partition configuration]' \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-l --link)'{-l,--link}'[Information for this link]:link name:_dladm_iblinks' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $part_properties' \
-			':partition link name:_dladm_parts'
-		;;
-
-	("show-ib")
-		_arguments -A "-*" \
-			'(-P --persistent)'{-P,--persistent}'[Display persistent partition configuration]' \
-			'(-p --parseable)'{-p,--parseable}'[Parseable output]' \
-			'(-o --output)'{-o,--output}'[Properties to display]:property:_values -s , "property" $ib_properties' \
-			':IB link name:_dladm_iblinks'
-		;;
-
-	(*)
-		_message "unknown dladm subcommand: $service"
-		;;
-	esac
+  local curcontext="$curcontext" state line expl
+  typeset -A opt_args
+  local -a subcmds
+  local -a linkprops linkprops_general linkprops_nonvlanvnic linkprops_wifi
+  local -a linkprops_ether linkprops_ib linkprops_iptun
+  local -a link_properties link_stats_properties vnic_properties
+  local -a aggr_properties aggr_lacp_properties aggr_ext_properties
+  local -a vlan_properties wifi_properties wifi_connect_properties
+  local -a ether_properties linkprop_properties secobj_properties
+  local -a bridge_properties bridge_stats_properties bridge_link_properties
+  local -a bridge_link_stats_properties bridge_fwd_properties
+  local -a bridge_fwd_properties bridge_trill_properties
+  local -a iptun_properties tunnel_values part_properties ib_properties
+
+  # TODO: some subcommands can take multiple comma-separated targets
+  # TODO: some option sets may be different based on other commandline flags
+  # TODO: some subcommands may take different arguments based on options
+
+  subcmds=(
+    help show-ether show-ib
+    {add,create,delete,modify,remove,show}-{aggr,bridge}
+    {rename,show}-link
+    {connect,disconnect,scan,show}-wifi
+    {reset,set,show}-linkprop
+    {create,delete,modify,show}-vlan
+    {delete,show}-phys
+    {create,delete,modify,show}-{vnic,iptun}
+    {create,delete,show}-{etherstub,secobj,part,cap}
+  )
+
+  if [[ $service == "dladm" ]]; then
+    _arguments -C -A "-*" \
+      '-\?[display help information]' \
+      '*::command:->subcmd' && return 0
+
+    if (( CURRENT == 1 )); then
+      _wanted commands expl "dladm subcommand" compadd -M 'r:|-=* r:|=*' -a subcmds
+      return
+    fi
+    service="$words[1]"
+    curcontext="${curcontext%:*}-$service:"
+  fi
+
+  link_properties=( link zone class mtu state over )
+  link_stats_properties=( link ipackets rbytes ierrors opackets obytes oerrors )
+
+  aggr_properties=( link policy addrpolicy lacpactivity lacptimer mode flags )
+  aggr_lacp_properties=( link port aggregatable sync coll dist defaulted expired )
+  aggr_ext_properties=( link port speed duplex state address portstate )
+
+  vlan_properties=( link vid over flags )
+
+  wifi_connect_properties=( link essid bssid sec mode strength speed bsstype )
+  wifi_properties=( $wifi_connect_properties status auth )
+
+  ether_properties=( link ptype state auto speed-duplex pause rem_fault )
+
+  linkprop_properties=( link property value default possible )
+
+  secobj_properties=( object class )
+
+  vnic_properties=( link over speed macaddr macaddrtype )
+
+  bridge_properties=( bridge  address priority bmaxage bhellotime bfwddelay
+    forceproto tctime tccount tchange desroot rootcost rootport
+    maxage hellotime fwddelay holdtime )
+  bridge_stats_properties=( bridge drops forwards mbcast recv sent unknown )
+  bridge_link_properties=( link index state uptime opercost operp2p operedge
+    desroot descost desbridge desport tcack )
+  bridge_link_stats_properties=( link cfgbpdu tcnbpdu rstpbpdu txbpdu drops recv xmit )
+  bridge_fwd_properties=( dest age flags output )
+  bridge_trill_properties=( nick flags link nexthop )
+
+  iptun_properties=( link type flags local remote )
+  tunnel_values=( 'local:address/host:' 'remote:address/host:' )
+
+  part_properties=( link pkey over state flags )
+
+  ib_properties=( link hcaguid portguid port state pkeys )
+
+  linkprops_general=(
+    'autopush:streams modules'
+    'cos:value:(0 1 2 3 4 5 6 7)'
+    'cpus:processors'
+    'cpus-effective'
+    'etsbw-lcl:percentage:'
+    'etsbw-lcl-advice'
+    'etsbw-lcl-effective'
+    'etsbw-rmt-effective'
+    'lro:value:(off on auto)'
+    'lro-effective'
+    'mac-address:MAC address'
+    'maxbw:bandwith'
+    'pool:pools'
+    'pool-effective'
+    'priority:priority:(high medium low)'
+    'rxringsavail'
+    'rxrings:value'
+    'rxhwclntavail'
+    'txringsavail'
+    'txrings:value'
+    'txhwclntavail'
+    'forward:value:(0 1)'
+    'stp_priority:value'
+    'stp_cost:value'
+    'stp_edge:value:(0 1)'
+    'stp_p2p:value:(true false auto)'
+    'stp_mcheck:value:(0 1)'
+    'protection:value:(mac-nospoof ip-nospoof dhcp-nospoof restricted)'
+    'vsi-mgrid:IPv6 address'
+    'vsi-mgrid-effective'
+    'vsi-mgrid-enc:encoding:(oracle_v1 none)'
+    'vsi-mgrid-enc-effective'
+    'vsi-typeid:value'
+    'vsi-typeid-effective'
+    'vsi-vers:value'
+    'vsi-vers-effective'
+    'zone:zone:_zones'
+  )
+  linkprops_nonvlanvnic=(
+    'default_tag:value'
+    'learn_decay:value'
+    'learn_limit:value'
+    'rxfanout:value'
+    'rxfanout-effective:value'
+    'stp:value:(0 1)'
+  )
+  linkprops_wifi=(
+    'channel:value'
+    'powermode:value:(off max fast)'
+    'radio:value:(on off)'
+    'speed:value'
+  )
+  linkprops_ether=(
+    'duplex'
+    'state'
+    'adv_autoneg_cap'
+    'adv_10gfdx_cap'
+    'adv_1000fdx_cap'
+    'adv_1000hdx_cap'
+    'adv_100fdx_cap'
+    'adv_100hdx_cap'
+    'adv_10fdx_cap'
+    'adv_10hdx_cap'
+    'en_10gfdx_cap:value:(0 1)'
+    'en_1000fdx_cap:value:(0 1)'
+    'en_1000hdx_cap:value:(0 1)'
+    'en_100fdx_cap:value:(0 1)'
+    'en_100hdx_cap:value:(0 1)'
+    'en_10fdx_cap:value:(0 1)'
+    'en_10hdx_cap:value:(0 1)'
+    'flowctrl:value:(auto no rx tx pfc bi)'
+    'flowctrl-effective'
+    'gvrp-timeout:value'
+    'mtu:value'
+    'ntcs'
+    'pfcmap:value'
+    'pfcmap-lcl-effective'
+    'pfcmap-rmt-effective'
+    'speed'
+    'tagmode:value:(normal vlanonly)'
+    'vlan-announce:value:(off gvrp)'
+  )
+  linkprops_ib=(
+    "linkmode:value:(cm ud)"
+  )
+  linkprops_iptun=(
+    "hoplimit:value"
+    "encaplimit:value"
+  )
+  linkprops=(
+    $linkprops_general $linkprops_wifi $linkprops_ether
+    $linkprops_ib $linkprops_iptun
+  )
+
+  case $service in
+  (help)
+    _wanted commands expl "dladm subcommand" compadd -M 'r:|-=* r:|=*' -a subcmds
+  ;;
+
+  (show-link)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[display persistent link configuration]' \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '-Z[display ZONE column in output]' \
+      '-z[zone]:zone:_sequence _zones' \
+      - set1 \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $link_properties' \
+      - set2 \
+      '(-s --statistics)'{-s,--statistics}'[display link statistics]' \
+      '(-i --interval)'{-i,--interval}'[specify an interval]:interval:' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $link_stats_properties' \
+      ':link name:_dladm_links'
+  ;;
+
+  (rename-link)
+    _arguments -A "-*" \
+      '-R[root directory]:directory:_path_files -/' \
+      ':old link name:_dladm_links' \
+      ':new link name:'
+  ;;
+
+  (show-phys)
+    _arguments -A "-*" \
+      '-D[show Data Center Bridging information]:featureset:(ets pfc)' \
+      '-H[show hardware resource usage]' \
+      '-L[display location information]' \
+      '(-P --persistent)'{-P,--persistent}'[display persistent link configuration]' \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '-m[display MAC address information]' \
+      '-Z[display ZONE column in output]' \
+      '-z[zone]:zone:_sequence _zones' \
+      '(-s --statistics)'{-s,--statistics}'[display link statistics]' \
+      '(-i --interval)'{-i,--interval}'[specify an interval]:interval:' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" link media state speed duplex device' \
+      ':physical link name:_dladm_devs'
+  ;;
+
+  (delete-phys)
+    _arguments -A "-*" \
+      ':physical link name:_dladm_devs'
+  ;;
+
+  (create-aggr)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[aggregation should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-l --link)'{-l,--link}'[component link]:link:_dladm_links' \
+      '(-m --mode)'{-m,--mode}'[aggregation mode]:mode:(dlmp trunk)' \
+      '(-P --policy)'{-P,--policy}'[port selection policy]:policy:_values -s , "policy" L2 L3 L4' \
+      '(-L --lacp-mode)'{-L,--lacp-mode}'[LACP mode]:lacp mode:(off active passive)' \
+      '(-T --lacp-timer)'{-T,--lacp-timer}'[LACP timer]:lacp timer:(short long)' \
+      '(-u --unicast)'{-u,--unicast}'[unicast address]:unicast address:' \
+      ':aggregate link name:'
+  ;;
+
+  (modify-aggr)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[aggregation should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-l --link)'{-l,--link}'[component link]:link:_dladm_links' \
+      '(-m --mode)'{-m,--mode}'[aggregation mode]:mode:(dlmp trunk)' \
+      '(-P --policy)'{-P,--policy}'[port selection policy]:policy:_values -s , "policy" L2 L3 L4' \
+      '(-L --lacp-mode)'{-L,--lacp-mode}'[LACP mode]:lacp mode:(off active passive)' \
+      '(-T --lacp-timer)'{-T,--lacp-timer}'[LACP timer]:lacp timer:(short long)' \
+      '(-u --unicast)'{-u,--unicast}'[unicast address]:unicast address:' \
+      ':aggregate link name:_dladm_aggrs'
+  ;;
+
+  (delete-aggr)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[deletion should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      ':aggregate link name:_dladm_aggrs'
+  ;;
+
+  (add-aggr)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[aggregation should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-l --link)'{-l,--link}'[component link]:link:_dladm_links' \
+      ':aggregate link name:_dladm_aggrs'
+  ;;
+
+  (remove-aggr)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[aggregation should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-l --link)'{-l,--link}'[component link]:link:_dladm_aggr_ports' \
+      ':aggregate link name:_dladm_aggrs'
+  ;;
+
+  (show-aggr)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[display persistent link configuration]' \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-s --statistics)'{-s,--statistics}'[display link statistics]' \
+      '(-i --interval)'{-i,--interval}'[specify an interval]:interval:' \
+      '-Z[display ZONE column in output]' \
+      '-z[zone]:zone:_sequence _zones' \
+      ':aggregate link name:_dladm_links' \
+      - set1 \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $aggr_properties' \
+      - lacp \
+      '(-L --lacp)'{-L,--lacp}'[LACP information]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $aggr_lacp_properties' \
+      - extended \
+      '(-x --extended)'{-x,--extended}'[extended information]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $aggr_ext_properties'
+  ;;
+
+  (create-vlan)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[VLAN should be temporary]' \
+      '(-f --force)'{-f,--force}'[force VLAN creation]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-l --link)'{-l,--link}'[component link]:link:_dladm_links' \
+      '-v[VLAN ID]:id:' \
+      ':VLAN link name:'
+  ;;
+
+  (delete-vlan)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[deletion should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      ':VLAN link name:_dladm_vlans'
+  ;;
+
+  (modify-vlan)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[VLAN should be temporary]' \
+      '(-f --force)'{-f,--force}'[force VLAN creation]' \
+      '(-R --root-dir)'{-R,--root-dir}'[root directory]:directory:_path_files -/' \
+      '(-l --link)'{-l,--link}'[component link]:link:_dladm_links' \
+      '-v[VLAN ID]:id:' \
+      - set1 \
+      '-L[source link]:link:_dladm_links' \
+      - set2 \
+      ':VLAN link name:'
+  ;;
+
+  (show-vlan)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[display persistent link configuration]' \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $vlan_properties' \
+      '-Z[display ZONE column in output]' \
+      '-z[zone]:zone:_sequence _zones' \
+      ':VLAN link name:_dladm_vlans'
+  ;;
+
+  (scan-wifi)
+    _arguments -A "-*" \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $wifi_connect_properties' \
+      ':wireless link name:_dladm_wifi_links'
+  ;;
+
+  (connect-wifi)
+    _arguments -A "-*" \
+      '(-e --essid)'{-e,--essid}'[ESSID name]:network:_dladm_wifi_nets' \
+      '(-b --bsstype)'{-b,--bsstype}'[BSS type]:' \
+      '(-m --mode)'{-m,--mode}'[802.11 mode]:802.11 mode:(a b g n)' \
+      '(-k --key)'{-k,--key}'[key name]:key:_sequence _dladm_secobjs' \
+      '(-s --sec)'{-s,--sec}'[security mode]:security mode:(none wep wpa)' \
+      '(-a --auth)'{-a,--auth}'[authentication mode]:authentication mode:(open shared)' \
+      '(-c --create-ibss)'{-c,--create-ibss}'[create an ad-hoc network]' \
+      '(-T --timeout)'{-T,--timeout}'[association timeout]:association timeout:(forever)' \
+      ':wireless link name:_dladm_wifi_links'
+  ;;
+
+  (disconnect-wifi)
+    _arguments -A "-*" \
+      - set1 \
+      '(-a --all-links)'{-a,--all-links}'[all links]' \
+      - set2 \
+      ':wireless link name:_dladm_wifi_links'
+  ;;
+
+  (show-wifi)
+    _arguments -A "-*" \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $wifi_properties' \
+      '-Z[display ZONE column in output]' \
+      '-z[zone]:zone:_sequence _zones' \
+      ':wireless link name:_dladm_wifi_links'
+  ;;
+
+  (show-ether)
+    _arguments -A "-*" \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-x --extended)'{-x,--extended}'[extended output]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $ether_properties' \
+      '-P[protocol]:protocol:(ecp vdp)' \
+      '-Z[display ZONE column in output]' \
+      '-z[zone]:zone:_sequence _zones' \
+      ':ethernet link name:_dladm_ethers'
+  ;;
+
+  (set-linkprop)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[change should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-p --prop)'{-p,--prop}'[properties]:property:_values -s , "property" ${(M)linkprops\:#*\:*}' \
+      ':link name:_dladm_links'
+  ;;
+
+  (reset-linkprop)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[change should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-p --prop)'{-p,--prop}'[properties]:property:_values -s , "property" ${${(M)linkprops\:#*\:*}%%\:*}' \
+      ':link name:_dladm_links'
+  ;;
+
+  (show-linkprop)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[display persistent link properties]' \
+      '(-c --parseable)'{-c,--parseable}'[parseable output]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $linkprop_properties' \
+      '(-p --prop)'{-p,--prop}'[properties]:property:_values -s , "property" ${linkprops%%\:*}' \
+      '-Z[display ZONE column in output]' \
+      '-z[zone]:zone:_sequence _zones' \
+      ':link name:_dladm_links'
+  ;;
+
+  (create-secobj)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[creation should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-c --class)'{-c,--class}'[class]:class:(wep wpa)' \
+      '(-f --file)'{-f,--file}'[file containing object value]:file:_path_files' \
+      ':object name:'
+  ;;
+
+  (delete-secobj)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[deletion should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      ':object name:_sequence _dladm_secobjs'
+  ;;
+
+  (show-secobj)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[display persistent object information]' \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $secobj_properties' \
+      ':object name:_sequence _dladm_secobjs'
+  ;;
+
+  (create-vnic)
+    # TODO: MAC address completion could be richer
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[creation should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-l --link)'{-l,--link}'[component link]:link:_dladm_links' \
+      '(-m --mac-address)'{-m,--mac-address}'[MAC address]:address:(factory random auto vrrp)' \
+      '-v[VLAN ID]:id:' \
+      '(-p --prop)'{-p,--prop}'[property values]:value:_values -s , "property" ${(M)linkprops_general\:#*\:*}' \
+      ':VNIC name:'
+  ;;
+
+  (delete-vnic)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[deletion should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      ':VNIC name:_dladm_vnics'
+  ;;
+
+  (modify-vnic)
+    # TODO: MAC address completion could be richer
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[creation should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-l --link)'{-l,--link}'[component link]:link:_dladm_links' \
+      '(-m --mac-address)'{-m,--mac-address}'[MAC address]:address:(factory random auto vrrp)' \
+      '-v[VLAN ID]:id:' \
+      '(-p --prop)'{-p,--prop}'[property values]:value:_values -s , "property" ${(M)linkprops_general\:#*\:*}' \
+      - set1 \
+      '-L[source link]:link:_dladm_links' \
+      - set2 \
+      ':VNIC name:'
+  ;;
+
+  (show-vnic)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[display persistent object information]' \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $vnic_properties' \
+      '(-l --link)'{-l,--link}'[limit to VNICs on link]:link:_dladm_links' \
+      '(-s --statistics)'{-s,--statistics}'[display VNIC statistics]' \
+      '(-i --interval)'{-i,--interval}'[specify an interval]:interval:' \
+      '-Z[display ZONE column in output]' \
+      '-v[display all VLAN information]' \
+      '-z[zone]:zone:_sequence _zones' \
+      ':VNIC name:_dladm_vnics'
+  ;;
+
+  (create-etherstub)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[creation should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      ':etherstub name:'
+  ;;
+
+  (delete-etherstub)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[deletion should be temporary]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      ':etherstub name:_dladm_etherstubs'
+  ;;
+
+  (show-etherstub)
+    _arguments -A "-*" \
+      '-Z[display ZONE column in output]' \
+      '-z[zone]:zone:_sequence _zones' \
+      ':etherstub name:_dladm_etherstubs'
+  ;;
+
+  (show-usage)
+    _arguments -A "-*" \
+      '(-f --file)'{-f,--file}'[read records from file]:file:_path_files' \
+      '(-F --format)'{-F,--format}'[plotfile format]:plotfile format:(gnuplot)' \
+      '(-p --plot)'{-p,--plot}'[write plot to file]:' \
+      '(-e --start)'{-e,--start}'[start time]:date/time (MM/DD/YYYY,hh\:mm\:ss)' \
+      '(-s --stop)'{-s,--stop}'[stop time]:date/time (MM/DD/YYYY,hh\:mm\:ss)' \
+      ':link name:_dladm_links'
+  ;;
+
+  (create-bridge)
+    _arguments -A "-*" \
+      '(-P --protect)'{-P,--protect}'[specify a protection method]:protection method:(stp trill)' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-p --priority)'{-p,--priority}'[specify the bridge priority]:value' \
+      '(-m --max-age)'{-m,--max-age}'[specify the max age for config info]:value' \
+      '(-h --hello-time)'{-h,--hello-time}'[specify the hello time]:value' \
+      '(-d --forward-delay)'{-d,--forward-delay}'[specify the forward delay]:value' \
+      '(-f --force-protocol)'{-f,--force-protocol}'[specify forced maximum supported protocol]:value' \
+      '*'{-l,--link}'[specify link to add]:link:_dladm_links' \
+      ':bridge name:'
+  ;;
+
+
+  (modify-bridge)
+    _arguments -A "-*" \
+      '(-P --protect)'{-P,--protect}'[specify a protection method]:protection method:(stp trill)' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-p --priority)'{-p,--priority}'[specify the bridge priority]:value' \
+      '(-m --max-age)'{-m,--max-age}'[specify the max age for config info]:value' \
+      '(-h --hello-time)'{-h,--hello-time}'[specify the hello time]:value' \
+      '(-d --forward-delay)'{-d,--forward-delay}'[specify the forward delay]:value' \
+      '(-f --force-protocol)'{-f,--force-protocol}'[specify forced maximum supported protocol]:value' \
+      ':bridge name:_dladm_bridges'
+  ;;
+
+
+  (delete-bridge)
+    _arguments -A "-*" \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      ':bridge name:_dladm_bridges'
+  ;;
+
+
+  (add-bridge|remove-bridge)
+    _arguments -A "-*" \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '*'{-l,--link}'[specify link to add]:link:_dladm_links' \
+      ':bridge name:_dladm_bridges'
+  ;;
+
+
+  (show-bridge)
+    # XXX $bridge_stats_properties get added into -o completions for set1
+    # XXX $bridge_link_stats_properties get added into -o completions for set3
+    _arguments -A "-*" \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      - set1 \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $bridge_properties' \
+      - set2 \
+      '(-s --statistics)'{-s,--statistics}'[display statistics]' \
+      '(-i --interval)'{-i,--interval}'[specify an interval]:seconds' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $bridge_stats_properties' \
+      - set3 \
+      '(-l --link)'{-l,--link}'[display link status or statistics]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $bridge_link_properties' \
+      - set4 \
+      '(-s --statistics)'{-s,--statistics}'[display statistics]' \
+      '(-l --link)'{-l,--link}'[display link status or statistics]' \
+      '(-i --interval)'{-i,--interval}'[specify an interval]:seconds' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $bridge_link_stats_properties' \
+      - set5 \
+      '(-f --forwarding)'{-f,--forwarding}'[display forwarding entries]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $bridge_fwd_properties' \
+      - set6 \
+      '(-t --trill)'{-t,--trill}'[display TRILL nickname entries]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $bridge_trill_properties' \
+      ':bridge name:_dladm_bridges'
+    ;
+
+
+  (create-iptun)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[temporary tunnel]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-T --type)'{-T,--type}'[tunnel type]:tunnel type:(ipv4 ipv6 6to4)' \
+      '(-a --address)'{-a,--address}'[endpoint addresses]:address/host:_values -s , "address/host" $tunnel_values' \
+      ':tunnel name'
+  ;;
+
+  (modify-iptun)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[temporary modification]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-a --address)'{-a,--address}'[endpoint addresses]:address/host:_values -s , "address/host" $tunnel_values' \
+      ':tunnel name:_dladm_iptuns'
+  ;;
+
+  (delete-iptun)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[temporary deletion]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      ':tunnel name:_dladm_iptuns'
+  ;;
+
+  (show-iptun)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[display persistent tunnel configuration]' \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $iptun_properties' \
+      '-Z[display ZONE column in output]' \
+      '-z[zone]:zone:_sequence _zones' \
+      ':tunnel name:_dladm_iptuns'
+  ;;
+
+  (create-part)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[temporary partition]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      '(-f --force)'{-f,--force}'[force partition creation]' \
+      '(-l --link)'{-l,--link}'[IP-over-IB physical link name]:IB link:_dladm_iblinks' \
+      '(-p --prop)'{-p,--prop}'[set link properties]:link property:_values -s , "property" ${(M)linkprops_nonvlanvnic\:#*\:*} ${(M)linkprops_general\:#*\:*}' \
+      '(-P --pkey)'{-P,--pkey}'[set parition key]:hex number:' \
+      ':partition link name:'
+  ;;
+
+  (delete-part)
+    _arguments -A "-*" \
+      '(-t --temporary)'{-t,--temporary}'[temporary deletion]' \
+      '(-R --root)'{-R,--root}'[root directory]:directory:_path_files -/' \
+      ':link name:_dladm_parts'
+  ;;
+
+  (show-part)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[display persistent partition configuration]' \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-l --link)'{-l,--link}'[information for this link]:link name:_dladm_iblinks' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $part_properties' \
+      ':partition link name:_dladm_parts'
+  ;;
+
+  (show-ib)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[display persistent partition configuration]' \
+      '(-p --parseable)'{-p,--parseable}'[parseable output]' \
+      '(-o --output)'{-o,--output}'[properties to display]:property:_values -s , "property" $ib_properties' \
+      ':IB link name:_dladm_iblinks'
+  ;;
+
+  ((create|delete)-cap)
+    _arguments -A "-*" \
+      '(-R --root)'{-R,--root}'[specify root directory]:directory:_directories' \
+      '(-t --temporary)'{-t,--temporary}'[capture  datalink is temporary\: until next reboot]' \
+      ':cap link'
+  ;;
+
+  (show-cap)
+    _arguments -A "-*" \
+      '(-P --persistent)'{-P,--persistent}'[show persistent datalink configuration]' \
+      '(-p --parseable)'{-p,--parseable}'[output using a stable machine-parseable format]' \
+      '(-o --output)'{-o,--output}'[specify output fields]: _values -s , "field" LINK ZONE TYPE MTU' \
+      ':cap link'
+  ;;
+
+  (*)
+    _default
+  ;;
+  esac
 }
 
 _dladm "$@"
diff --git a/Completion/Solaris/Command/_dumpadm b/Completion/Solaris/Command/_dumpadm
index 02c63f6..44d681a 100644
--- a/Completion/Solaris/Command/_dumpadm
+++ b/Completion/Solaris/Command/_dumpadm
@@ -1,23 +1,22 @@
 #compdef dumpadm
 
-_dumpadm() {
-	local -a content
+local -a content
 
-	content=(
-		"kernel"\:"Kernel memory pages only"
-		"all"\:"All memory pages"
-		"curproc"\:"Kernel memory pages plus curproc pages"
-	)
-
-	_arguments -s \
-		'-n[dont run savecore on reboot]' \
-		'-u[update dump configuration from dumpadm.conf]' \
-		'-y[run savecore on reboot]' \
-		'-c[set dump content]:dump content:(($content))' \
-		'-d[set dump device]:block devices:_files -g "*(-%b)"' \
-		'-m[set minfree size ]:' \
-		'-s[set the savecore directory]:directory:_files -/' \
-		'-r[alternate root directory]:directory:_files -/'
-}
-
-_dumpadm "$@"
+content=(
+  'kernel:kernel memory pages only'
+  'all:all memory pages'
+  'curproc:kernel memory pages plus curproc pages'
+  'allproc:kernel memory pages and all process pages'
+)
+_arguments -s \
+  '-e[print estimate of disk space required to store compressed crash dump]' \
+  "-n[don't run savecore on reboot]" \
+  '-p[produce machine parseable output]' \
+  '-u[update dump configuration from dumpadm.conf]' \
+  '-y[run savecore on reboot]' \
+  '-c[set dump content]:dump content:(($content))' \
+  '-d[set dump device]: : _alternative "tokens\:token\:(swap none)" "files\:block device\:_files -g \*\(-%b\)"' \
+  '-m[set minfree size]:size' \
+  '-s[set the savecore directory]:directory:_files -/' \
+  '-r[alternate root directory]:directory:_files -/' \
+  '-z[enable saving core files in a compressed format]:compression:(on off)'
diff --git a/Completion/Solaris/Command/_flowadm b/Completion/Solaris/Command/_flowadm
index 53a9f22..e4d682f 100644
--- a/Completion/Solaris/Command/_flowadm
+++ b/Completion/Solaris/Command/_flowadm
@@ -1,41 +1,18 @@
 #compdef flowadm
-# Synced with the S11U1 build 19 man page
-
-_flowadm() {
 
 local -a subcmds tr props
 local expl
 
 _flowadm_flow(){
-	compadd "$@" - $(flowadm show-flow -p -o flow)
-}
-
-_flowadm_flow_int(){
-	compadd "$@" - $(flowadm show-flow -p -o flow)
-	compadd "$@" - $(dladm show-phys -p -o device)
+  compadd "$@" - $(_call_program flows flowadm show-flow -p -o flow)
 }
 
 subcmds=(
-	"help"
-	"show-flow"
-	"add-flow"
-	"remove-flow"
-	"set-flowprop"
-	"reset-flowprop"
-	"show-flowprop"
-)
-	
-tr=(
-	"tcp"
-	"udp"
-	"sctp"
-	"icmp"
-	"icmpv6"
-)
-
-props=(
-	"maxbw"
+  help show-flow add-flow match-flow remove-flow set-flowprop
+  reset-flowprop show-flowprop
 )
+tr=( tcp udp sctp icmp icmpv6 )
+props=( maxbw )
 
 if [[ $service == "flowadm" ]]; then
 	_arguments -C -A "-*" \
@@ -46,7 +23,7 @@ if [[ $service == "flowadm" ]]; then
 		return
 	fi
 	service="$words[1]"
-	curcontext="${curcontext%:*}=$service:"
+	curcontext="${curcontext%:*}-$service:"
 fi
 case $service in
 
@@ -65,6 +42,16 @@ case $service in
 		':flow:_flowadm_flow' \
 	;;
 
+	(match-flow)
+	_arguments -A "-*" \
+		'-o[specify field to display]:field:(flow link ipaddr proto port dsfield)' \
+		'-p[parsable output]' \
+		'-P[persistent flow property information]' \
+		'-a[specify attribute]:attribute:(local_ip= remote_ip= transport=$tr local_port= dsfield=)' \
+		'(:)-l[display information for link]:link or flow:_net_interfaces' \
+		'(-l):flow:_flowadm_flow' \
+	;;
+
 	("add-flow")
 	_arguments -A "-*" \
 		'-t[temporary changes - do not persist across reboots]' \
@@ -110,6 +97,3 @@ case $service in
 	;;
 
 esac
-}
-
-_flowadm "$@"
diff --git a/Completion/Solaris/Command/_fmadm b/Completion/Solaris/Command/_fmadm
index 56dac4f..2a28f7a 100644
--- a/Completion/Solaris/Command/_fmadm
+++ b/Completion/Solaris/Command/_fmadm
@@ -1,8 +1,7 @@
 #compdef fmadm
-# Synced with the Nevada build 168 man page
 
 _fm_modules() {
-	compadd "$@" - $(fmadm config 2> /dev/null | awk 'NR == 1 {continue} {print $1}')
+  compadd "$@" - ${${(f)"$(_call_program modules fmadm config)"}[2,-1]// */}
 }
 
 _fm_faulted_fmris() {
@@ -14,7 +13,7 @@ _fm_faulted_uuids() {
 }
 
 _fm_faulted_labels() {
-	local q='"'
+	local line q='"'
 	compadd "$@" - $(fmadm faulty -f 2> /dev/null | while read line; do
 		if [[ $line == "----"* ]]; then
 			read line
@@ -25,87 +24,101 @@ _fm_faulted_labels() {
 	done)
 }
 
-_fmadm() {
-	local context state line expl
-	local -A opt_args
-	local -a subcmds
+local curcontext="$curcontext" state line expl ret=1
+local -A opt_args
+local -a subcmds args
 
-	# TODO: lookup-alias and remove-alias need completion based on the
-	# output of list-alias, but I have no examples of that output.
+# TODO: lookup-alias and remove-alias need completion based on the
+# output of list-alias, but I have no examples of that output.
 
-	subcmds=(
-		"acquit" "config" "faulty" "flush" "load" "unload"
-		"repaired" "replaced" "reset" "rotate"
-		"add-alias" "remove-alias" "lookup-alias" "list-alias" "sync-alias"
-	)
+subcmds=(
+  faulty list acquit replaced repaired list-alert clear
+  list-defect list-fault
+  add-alias remove-alias lookup-alias list-alias sync-alias
+  config load unload reset rotate flush
+)
 
-	if [[ $service == "fmadm" ]]; then
-		_arguments -C -A "-*" \
-			'-q[Quite mode]' \
-			'*::command:->subcmd' && return 0
+_arguments -C -A "-*" \
+  '-q[quiet mode]' \
+  '1:fmadm subcommand:compadd -M "r:|-=* r:|=*" -a subcmds' \
+  '*::command:->subcmd' && ret=0
 
-		if (( CURRENT == 1 )); then
-			_wanted commands expl "fmadm subcommand" compadd -a subcmds
-			return
-		fi
-		service="$words[1]"
-		curcontext="${curcontext%:*}=$service:"
-	fi
+service="$words[1]"
+curcontext="${curcontext%:*}-$service:"
 
-	case $service in
-	("acquit")
-		_alternative \
-			"fmadm-acquit-label:label:_fm_faulted_labels" \
-			"fmadm-acquit-uuid:uuid:_fm_faulted_uuids" \
-			"fmadm-acquit-fmri:fmri:_fm_faulted_fmris"
-		;;
+case $service in
+  (faulty|list|list-alert|list-defect|list-fault)
+    args+=(
+      '-f[display faulty FRUs]'
+      '-i[display persistent cache IDs]'
+      '-p[page output]'
+      '-r[display resources]'
+      '-s[display one-line summaries]'
+      '-u[only display fault with given uuid]:uuid:_fm_faulted_uuids'
+      '-v[display full output]'
+    )
+  ;|
 
-	("config")
-		;;
+  (faulty)
+    _arguments -A "-*" $args \
+      '-a[display all faults]' \
+      '-g[group faults]' \
+      '-n[limit output to n entries]:number'
+  ;;
 
-	("faulty")
-		_arguments -A "-*" \
-			'-a[Display all faults]' \
-			'-f[Display faulty FRUs]' \
-			'-g[Group faults]' \
-			'-i[Display persistent cache IDs]' \
-			'-n[Limit output to n entries]:number:' \
-			'-p[Page output]' \
-			'-r[Display resources]' \
-			'-s[Display one-line summaries]' \
-			'-u[Only display fault with given uuid]:uuid:_fm_faulted_uuids' \
-			'-v[Display full output]'
-		;;
+  (list|list-alert|list-defect|list-fault)
+    _arguments -A "-*" $args \
+      '-a[display all resources]'
+  ;;
 
-	("flush")
-		_fm_faulted_fmris
-		;;
+  (acquit)
+    _alternative \
+      'fmadm-acquit-label:label:_fm_faulted_labels' \
+      'fmadm-acquit-uuid:uuid:_fm_faulted_uuids' \
+      'fmadm-acquit-fmri:fmri:_fm_faulted_fmris' && ret=0
+  ;;
 
-	("load")
-		_path_files -g "/*"
-		;;
+  (repaired|replaced)
+    _alternative \
+      'fmadm-acquit-label:label:_fm_faulted_labels' \
+      'fmadm-acquit-fmri:fmri:_fm_faulted_fmris' && ret=0
+  ;;
 
-	("unload")
-		_fm_modules
-		;;
+  (add-alias)
+    _arguments :chassis :alias-id :comment && ret=0
+  ;;
 
-	("repaired"|"replaced")
-		_alternative \
-			"fmadm-acquit-label:label:_fm_faulted_labels" \
-			"fmadm-acquit-fmri:fmri:_fm_faulted_fmris"
-		;;
+  (remove-alias|lookup-alias)
+    _message -e aliases 'chassis or alias-id'
+  ;;
 
-	("reset")
-		_arguments -A "-*" \
-			'-s[Reset named SERD]:serd:' \
-			':module:_fm_modules'
-		;;
+  (load)
+    _directories && ret=0
+  ;;
 
-	("rotate")
-		_values "logfile" "errlog" "fltlog" "infolog" "infolog_hival"
-		;;
+  (unload)
+    _fm_modules && ret=0
+  ;;
 
-	esac
-}
+  (reset)
+    _arguments -A "-*" \
+      '-s[reset named SERD]:serd' \
+      ':module:_fm_modules' && ret=0
+  ;;
 
-_fmadm "$@"
+  (rotate)
+    _values 'logfile' errlog fltlog infolog infolog_hival && ret=0
+  ;;
+
+  (flush)
+    _fm_faulted_fmris && ret=0
+  ;;
+
+  (list-alias|config|sync-aliases) _message 'no more arguments' ;;
+
+  (*) # fallback to defaults for any new or unhandled subcommand
+    _default && ret=0
+  ;;
+esac
+
+return ret
diff --git a/Completion/Solaris/Command/_svcs b/Completion/Solaris/Command/_svcs
index 7c148fa..c1f01ad 100644
--- a/Completion/Solaris/Command/_svcs
+++ b/Completion/Solaris/Command/_svcs
@@ -1,32 +1,28 @@
 #compdef svcs
 
-_svcs() {
-	local -a cols
+local -a cols
 
-	cols=(
-		ctid\:"Contract ID" desc\:"Description" fmri\:"FMRI"
-		inst\:"Instance name" nsta\:"Next state (abbr)" nstate\:"Next state"
-		scope\:"Scope name" svc\:"Service name" sta\:"State (abbr)"
-		state\:"State" stime\:"Start time"
-	)
+cols=(
+  ctid\:"contract id" desc\:"description" fmri\:"fmri"
+  inst\:"instance name" nsta\:"next state (abbr)" nstate\:"next state"
+  scope\:"scope name" svc\:"service name" sta\:"state (abbr)"
+  state\:"state" stime\:"start time" astate\:"name for current auxiliary state"
+  nrun\:"time of next scheduled run for periodic services"
+  lrun\:"time of the last run for periodic services"
+)
 
-	_arguments -s \
-		'(-l -x -d -D)-a[list all instances]' \
-		'(-l -x -D -a -R)-d[list dependencies]' \
-		'(-l -x -d -a -R)-D[list dependents]' \
-		'(-l -x)-H[suppress header line]' \
-		'(-x -d -D -a -R -s)-l[print detailed status about services and instances]' \
-		'(-l -x)-o[display specific columns]:column:_values -s , "column" ${^cols/\:/[}\]' \
-		'(-l -x)-p[list processes]' \
-		'(-l -x -d -D)-R[list services with the given restarter]:instance FMRI:_svcs_fmri -i' \
-		'(-l -x)-s[sort by a column]:column:(($cols))' \
-		'(-l -x)-S[reverse sort by a column]:column:(($cols))' \
-		'-v[verbose columns]' \
-		'(-l)-x[display explanation for service states]' \
-		'(-l -x)-\?[print help]' \
-		'*:FMRI or pattern:_svcs_fmri -i'
-}
-
-_svcs "$@"
-
-# vi:tw=0
+_arguments -s \
+  '(-l -x -d -D)-a[list all instances]' \
+  '(-l -x -D -a -R)-d[list dependencies]' \
+  '(-l -x -d -a -R)-D[list dependents]' \
+  '(-l -x)-H[suppress header line]' \
+  '(-x -d -D -a -R -s)-l[print detailed status about services and instances]' \
+  '(-l -x)-o[display specific columns]:column:_values -s , "column" ${^cols/\:/[}\]' \
+  '(-l -x)-p[list processes]' \
+  '(-l -x -d -D)-R[list services with the given restarter]:instance FMRI:_svcs_fmri -i' \
+  '(-l -x)-s[sort by a column]:column:(($cols))' \
+  '(-l -x)-S[reverse sort by a column]:column:(($cols))' \
+  '-v[verbose columns]' \
+  '(-l)-x[display explanation for service states]' \
+  '(-l -x)-\?[print help]' \
+  '*:FMRI or pattern:_svcs_fmri -i'
diff --git a/Completion/Unix/Command/_sort b/Completion/Unix/Command/_sort
index a35de17..91e9132 100644
--- a/Completion/Unix/Command/_sort
+++ b/Completion/Unix/Command/_sort
@@ -4,8 +4,8 @@ local args variant
 local ordering='(-d --dictionary-order -g --general-numeric-sort -M --month-sort -h --human-numeric-sort -n --numeric-sort --sort -V --version-sort --help --version)'
 
 args=(
-  '(-c --check -C)-c[check whether input is sorted; do not sort]'
-  '(-m --merge)'{-m,--merge}'[merge already sorted files; do not sort]'
+  "(-c --check -C)-c[check whether input is sorted; don't sort]"
+  '(-m --merge)'{-m,--merge}"[merge already sorted files; don't sort]"
   '(-o --output)'{-o+,--output=}'[write result to file instead of standard output]:output file:_files'
   \*{-T+,--temporary-directory=}'[specify directory for temporary files]:directory:_directories'
   '(-u --unique)'{-u,--unique}'[with -c, check for strict ordering; without -c, output only the first of an equal run]'
@@ -26,15 +26,19 @@ case $variant in
       '(-s --stable)'{-s,--stable}'[preserve original order of lines with the same key]'
     )
   ;|
+  openbsd*|freebsd*|gnu|solaris2.<11->)
+    args+=(
+      "(-c --check -C)-C[check whether input is sorted silently; don't sort]"
+    )
+  ;|
   openbsd*|freebsd*|gnu)
     args+=(
-      '(-c --check -C)-C[check whether input is sorted; do not sort]'
       '(-z --zero-terminated)'{-z,--zero-terminated}'[end lines with 0 byte, not newline]'
     )
   ;|
   freebsd*|gnu)
     args+=(
-      '(-c --check -C)--check=-[check whether input is sorted; do not sort]::bad line handling:(diagnose-first silent quiet)'
+      "(-c --check -C)--check=-[check whether input is sorted; don't sort]::bad line handling:(diagnose-first silent quiet)"
       "$ordering"{-g,--general-numeric-sort}'[compare according to general numeric value]'
       "$ordering"{-M,--month-sort}"[compare (unknown) < 'JAN' < ... < 'DEC']"
       "$ordering"{-h,--human-numeric-sort}'[compare human readable numbers (e.g., 2K 1G)]'