--- old/usr/src/cmd/dladm/dladm.c	2014-02-09 05:30:58.771469266 +0000
+++ new/usr/src/cmd/dladm/dladm.c	2014-02-09 05:30:58.785765021 +0000
@@ -83,6 +83,7 @@
 #define	SMF_UPGRADEDATALINK_FILE	"/var/svc/profile/upgrade_datalink"
 #define	SMF_DLADM_UPGRADE_MSG		" # added by dladm(1M)"
 #define	DLADM_DEFAULT_COL	80
+#define	DLADM_DEFAULT_CMD	"show-link"
 
 /*
  * used by the wifi show-* commands to set up ofmt_field_t structures.
@@ -219,6 +220,7 @@
 static cmdfunc_t do_add_bridge, do_remove_bridge, do_show_bridge;
 static cmdfunc_t do_create_iptun, do_modify_iptun, do_delete_iptun;
 static cmdfunc_t do_show_iptun, do_up_iptun, do_down_iptun;
+static cmdfunc_t do_help;
 
 static void 	do_up_vnic_common(int, char **, const char *, boolean_t);
 
@@ -267,8 +269,8 @@
 	{ "rename-link",	do_rename_link,
 	    "    rename-link      <oldlink> <newlink>"			},
 	{ "show-link",		do_show_link,
-	    "    show-link        [-pP] [-o <field>,..] [-s [-i <interval>]] "
-	    "[<link>]\n"						},
+	    "    show-link        [-P] [[-p] -o <field>,..] "
+	    "[-s [-i <interval>]] [<link>]"				},
 	{ "create-aggr",	do_create_aggr,
 	    "    create-aggr      [-t] [-P <policy>] [-L <mode>] [-T <time>] "
 	    "[-u <address>]\n"
@@ -284,11 +286,11 @@
 	    "[-u <address>]\n"
 	    "\t\t     <link>"						},
 	{ "show-aggr",		do_show_aggr,
-	    "    show-aggr        [-pPLx] [-o <field>,..] [-s [-i <interval>]] "
-	    "[<link>]\n"						},
+	    "    show-aggr        [-PLx] [[-p] -o <field>,..] "
+	    "[-s [-i <interval>]] [<link>]"				},
 	{ "up-aggr",		do_up_aggr,	NULL			},
 	{ "scan-wifi",		do_scan_wifi,
-	    "    scan-wifi        [-p] [-o <field>,...] [<link>]"	},
+	    "    scan-wifi        [[-p] -o <field>,...] [<link>]"	},
 	{ "connect-wifi",	do_connect_wifi,
 	    "    connect-wifi     [-e <essid>] [-i <bssid>] [-k <key>,...] "
 	    "[-s wep|wpa]\n"
@@ -298,22 +300,22 @@
 	{ "disconnect-wifi",	do_disconnect_wifi,
 	    "    disconnect-wifi  [-a] [<link>]"			},
 	{ "show-wifi",		do_show_wifi,
-	    "    show-wifi        [-p] [-o <field>,...] [<link>]\n"	},
+	    "    show-wifi        [[-p] -o <field>,...] [<link>]"	},
 	{ "set-linkprop",	do_set_linkprop,
 	    "    set-linkprop     [-t] -p <prop>=<value>[,...] <name>"	},
 	{ "reset-linkprop",	do_reset_linkprop,
 	    "    reset-linkprop   [-t] [-p <prop>,...] <name>"		},
 	{ "show-linkprop",	do_show_linkprop,
 	    "    show-linkprop    [-cP] [-o <field>,...] [-p <prop>,...] "
-	    "<name>\n"							},
+	    "<name>"							},
 	{ "show-ether",		do_show_ether,
-	    "    show-ether       [-px][-o <field>,...] <link>\n"	},
+	    "    show-ether       [-x] [[-p] -o <field>,...] <link>"	},
 	{ "create-secobj",	do_create_secobj,
 	    "    create-secobj    [-t] [-f <file>] -c <class> <secobj>"	},
 	{ "delete-secobj",	do_delete_secobj,
 	    "    delete-secobj    [-t] <secobj>[,...]"			},
 	{ "show-secobj",	do_show_secobj,
-	    "    show-secobj      [-pP] [-o <field>,...] [<secobj>,...]\n" },
+	    "    show-secobj      [-P] [[-p] -o <field>,...] [<secobj>,...]" },
 	{ "init-linkprop",	do_init_linkprop,	NULL		},
 	{ "init-secobj",	do_init_secobj,		NULL		},
 	{ "create-vlan", 	do_create_vlan,
@@ -321,7 +323,7 @@
 	{ "delete-vlan", 	do_delete_vlan,
 	    "    delete-vlan      [-t] <link>"				},
 	{ "show-vlan",		do_show_vlan,
-	    "    show-vlan        [-pP] [-o <field>,..] [<link>]\n"	},
+	    "    show-vlan        [-P] [[-p] -o <field>,...] [<link>]"	},
 	{ "up-vlan",		do_up_vlan,		NULL		},
 	{ "create-iptun",	do_create_iptun,
 	    "    create-iptun     [-t] -T <type> "
@@ -331,25 +333,25 @@
 	{ "modify-iptun",	do_modify_iptun,
 	    "    modify-iptun     [-t] -a {local|remote}=<addr>,... <link>" },
 	{ "show-iptun",		do_show_iptun,
-	    "    show-iptun       [-pP] [-o <field>,..] [<link>]\n"	},
+	    "    show-iptun       [-P] [[-p] -o <field>,...] [<link>]"	},
 	{ "up-iptun",		do_up_iptun,		NULL		},
 	{ "down-iptun",		do_down_iptun,		NULL		},
 	{ "delete-phys",	do_delete_phys,
 	    "    delete-phys      <link>"				},
 	{ "show-phys",		do_show_phys,
-	    "    show-phys        [-pP] [-o <field>,..] [-H] [<link>]\n"},
+	    "    show-phys        [-P] [[-p] -o <field>,...] [-H] [<link>]" },
 	{ "init-phys",		do_init_phys,		NULL		},
 	{ "show-linkmap",	do_show_linkmap,	NULL		},
 	{ "create-vnic",	do_create_vnic,
 	    "    create-vnic      [-t] -l <link> [-m <value> | auto |\n"
 	    "\t\t     {factory [-n <slot-id>]} | {random [-r <prefix>]} |\n"
 	    "\t\t     {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n"
-	    "\t\t     [-p <prop>=<value>[,...]] <vnic-link>"	},
+	    "\t\t     [-p <prop>=<value>[,...]] [-R root-dir] <vnic-link>" },
 	{ "delete-vnic",	do_delete_vnic,
 	    "    delete-vnic      [-t] <vnic-link>"			},
 	{ "show-vnic",		do_show_vnic,
-	    "    show-vnic        [-pP] [-l <link>] [-s [-i <interval>]] "
-	    "[<link>]\n"						},
+	    "    show-vnic        [-P] [[-p] -o <field>,...] [-l <link>] "
+	    "[-s [-i <interval>]] [<link>]"				},
 	{ "up-vnic",		do_up_vnic,		NULL		},
 	{ "create-part",	do_create_part,
 	    "    create-part      [-t] [-f] -l <link> [-P <pkey>]\n"
@@ -357,10 +359,10 @@
 	{ "delete-part",	do_delete_part,
 	    "    delete-part      [-t] [-R <root-dir>] <part-link>"},
 	{ "show-part",		do_show_part,
-	    "    show-part        [-pP] [-o <field>,...][-l <linkover>]\n"
+	    "    show-part        [-P] [[-p] -o <field>,...] [-l <linkover>]\n"
 	    "\t\t     [<part-link>]"		},
 	{ "show-ib",		do_show_ib,
-	    "    show-ib          [-p] [-o <field>,...] [<link>]\n"	},
+	    "    show-ib          [[-p] -o <field>,...] [<link>]"	},
 	{ "up-part",		do_up_part,		NULL		},
 	{ "create-etherstub",	do_create_etherstub,
 	    "    create-etherstub [-t] <link>"				},
@@ -392,18 +394,20 @@
 	    "    remove-bridge    [-R <root-dir>] -l <link> [-l <link>]... "
 	    "<bridge>"							},
 	{ "show-bridge",	do_show_bridge,
-	    "    show-bridge      [-p] [-o <field>,...] [-s [-i <interval>]] "
+	    "    show-bridge      [[-p] -o <field>,...] [-s [-i <interval>]] "
 	    "[<bridge>]\n"
-	    "    show-bridge      -l [-p] [-o <field>,...] [-s [-i <interval>]]"
+	    "    show-bridge      -l [[-p] -o <field>,...] [-s [-i <interval>]]"
 	    " <bridge>\n"
-	    "    show-bridge      -f [-p] [-o <field>,...] [-s [-i <interval>]]"
+	    "    show-bridge      -f [[-p] -o <field>,...] [-s [-i <interval>]]"
 	    " <bridge>\n"
-	    "    show-bridge      -t [-p] [-o <field>,...] [-s [-i <interval>]]"
-	    " <bridge>\n"						},
+	    "    show-bridge      -t [[-p] -o <field>,...] [-s [-i <interval>]]"
+	    " <bridge>"							},
 	{ "show-usage",		do_show_usage,
 	    "    show-usage       [-a] [-d | -F <format>] "
 	    "[-s <DD/MM/YYYY,HH:MM:SS>]\n"
-	    "\t\t     [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]"	}
+	    "\t\t     [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]"	},
+	{ "help",		do_help,
+	    "    help		  [<subcommand>]"			}
 };
 
 static const struct option lopts[] = {
@@ -1136,7 +1140,6 @@
 { NULL,		0, 0, NULL}}
 ;
 
-
 /*
  * structures for 'dladm show-usage link'
  */
@@ -1439,15 +1442,8 @@
 static void
 usage(void)
 {
-	int	i;
-	cmd_t	*cmdp;
-	(void) fprintf(stderr, gettext("usage:  dladm <subcommand> <args> ..."
-	    "\n"));
-	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
-		cmdp = &cmds[i];
-		if (cmdp->c_usage != NULL)
-			(void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
-	}
+	(void) fprintf(stderr, gettext("For more information, run: %s help\n"),
+	    progname);
 
 	/* close dladm handle if it was opened */
 	if (handle != NULL)
@@ -1471,8 +1467,10 @@
 
 	progname = argv[0];
 
-	if (argc < 2)
-		usage();
+	if (argc < 2) {
+		argv[1] = DLADM_DEFAULT_CMD;
+		argc++;
+	}
 
 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
 		cmdp = &cmds[i];
@@ -1496,6 +1494,64 @@
 	return (EXIT_FAILURE);
 }
 
+static int
+help_compare(const void *cmd1, const void *cmd2)
+{
+	cmd_t	*cmd1p = (cmd_t *)cmd1;
+	cmd_t	*cmd2p = (cmd_t *)cmd2;
+
+	return (strcmp(cmd1p->c_name, cmd2p->c_name));
+}
+
+static void
+do_help(int argc, char *argv[], const char *use)
+{
+	size_t		nelems;
+	int		i, j, ncols = 3;
+	boolean_t	found = B_FALSE;
+
+	_NOTE(ARGUNUSED(use));
+
+	nelems = sizeof (cmds) / sizeof (cmd_t);
+
+	if (argc < 2) {
+		qsort(cmds, nelems, sizeof (cmd_t), help_compare);
+
+		(void) fprintf(stderr, gettext(
+		    "usage: dladm help <subcommand>\n"
+		    "Subcommands are:\n"));
+
+		for (i = 0, j = 0; i < nelems; i++) {
+			if (cmds[i].c_usage == NULL)
+				continue;
+
+			(void) fprintf(stderr, "%-20s", cmds[i].c_name);
+
+			if (++j % ncols == 0)
+				(void) putc('\n', stderr);
+		}
+
+		if (j % ncols != 0)
+			(void) putc('\n', stderr);
+	} else {
+		for (i = 0; i < nelems; i++) {
+			if (strcmp(argv[1], cmds[i].c_name) == 0) {
+				(void) fprintf(stderr, "usage:\n%s\n",
+				    gettext(cmds[i].c_usage));
+				found = B_TRUE;
+				break;
+			}
+		}
+
+		if (!found) {
+			(void) fprintf(stderr, gettext(
+			    "%s: unknown subcommand '%s'\n"),
+			    progname, argv[1]);
+			usage();
+		}
+	}
+}
+
 /*ARGSUSED*/
 static int
 show_usage_date(dladm_usage_t *usage, void *arg)
