3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <dlfcn.h>
28 #include <locale.h>
29 #include <signal.h>
30 #include <stdarg.h>
31 #include <stdlib.h>
32 #include <fcntl.h>
33 #include <string.h>
34 #include <stropts.h>
35 #include <sys/stat.h>
36 #include <errno.h>
37 #include <kstat.h>
38 #include <strings.h>
39 #include <getopt.h>
40 #include <unistd.h>
41 #include <priv.h>
42 #include <limits.h>
137 ofmt_handle_t gs_ofmt;
138 } show_grp_state_t;
139
140 typedef struct show_vnic_state {
141 datalink_id_t vs_vnic_id;
142 datalink_id_t vs_link_id;
143 char vs_vnic[MAXLINKNAMELEN];
144 char vs_link[MAXLINKNAMELEN];
145 boolean_t vs_parsable;
146 boolean_t vs_found;
147 boolean_t vs_firstonly;
148 boolean_t vs_donefirst;
149 boolean_t vs_stats;
150 boolean_t vs_printstats;
151 pktsum_t vs_totalstats;
152 pktsum_t vs_prevstats[MAXVNIC];
153 boolean_t vs_etherstub;
154 dladm_status_t vs_status;
155 uint32_t vs_flags;
156 ofmt_handle_t vs_ofmt;
157 } show_vnic_state_t;
158
159 typedef struct show_part_state {
160 datalink_id_t ps_over_id;
161 char ps_part[MAXLINKNAMELEN];
162 boolean_t ps_parsable;
163 boolean_t ps_found;
164 dladm_status_t ps_status;
165 uint32_t ps_flags;
166 ofmt_handle_t ps_ofmt;
167 } show_part_state_t;
168
169 typedef struct show_ib_state {
170 datalink_id_t is_link_id;
171 char is_link[MAXLINKNAMELEN];
172 boolean_t is_parsable;
173 dladm_status_t is_status;
174 uint32_t is_flags;
175 ofmt_handle_t is_ofmt;
176 } show_ib_state_t;
248 static int show_etherprop(dladm_handle_t, datalink_id_t, void *);
249 static void show_ether_xprop(void *, dladm_ether_info_t *);
250 static boolean_t link_is_ether(const char *, datalink_id_t *);
251
252 static boolean_t str2int(const char *, int *);
253 static void die(const char *, ...);
254 static void die_optdup(int);
255 static void die_opterr(int, int, const char *);
256 static void die_dlerr(dladm_status_t, const char *, ...);
257 static void warn(const char *, ...);
258 static void warn_dlerr(dladm_status_t, const char *, ...);
259
260 typedef struct cmd {
261 char *c_name;
262 cmdfunc_t *c_fn;
263 const char *c_usage;
264 } cmd_t;
265
266 static cmd_t cmds[] = {
267 { "rename-link", do_rename_link,
268 " rename-link <oldlink> <newlink>" },
269 { "show-link", do_show_link,
270 " show-link [-pP] [-o <field>,..] [-s [-i <interval>]] "
271 "[<link>]\n" },
272 { "create-aggr", do_create_aggr,
273 " create-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] "
274 "[-u <address>]\n"
275 "\t\t -l <link> [-l <link>...] <link>" },
276 { "delete-aggr", do_delete_aggr,
277 " delete-aggr [-t] <link>" },
278 { "add-aggr", do_add_aggr,
279 " add-aggr [-t] -l <link> [-l <link>...] <link>" },
280 { "remove-aggr", do_remove_aggr,
281 " remove-aggr [-t] -l <link> [-l <link>...] <link>" },
282 { "modify-aggr", do_modify_aggr,
283 " modify-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] "
284 "[-u <address>]\n"
285 "\t\t <link>" },
286 { "show-aggr", do_show_aggr,
287 " show-aggr [-pPLx] [-o <field>,..] [-s [-i <interval>]] "
288 "[<link>]\n" },
289 { "up-aggr", do_up_aggr, NULL },
290 { "scan-wifi", do_scan_wifi,
291 " scan-wifi [-p] [-o <field>,...] [<link>]" },
292 { "connect-wifi", do_connect_wifi,
293 " connect-wifi [-e <essid>] [-i <bssid>] [-k <key>,...] "
294 "[-s wep|wpa]\n"
295 "\t\t [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g] "
296 "[-T <time>]\n"
297 "\t\t [<link>]" },
298 { "disconnect-wifi", do_disconnect_wifi,
299 " disconnect-wifi [-a] [<link>]" },
300 { "show-wifi", do_show_wifi,
301 " show-wifi [-p] [-o <field>,...] [<link>]\n" },
302 { "set-linkprop", do_set_linkprop,
303 " set-linkprop [-t] -p <prop>=<value>[,...] <name>" },
304 { "reset-linkprop", do_reset_linkprop,
305 " reset-linkprop [-t] [-p <prop>,...] <name>" },
306 { "show-linkprop", do_show_linkprop,
307 " show-linkprop [-cP] [-o <field>,...] [-p <prop>,...] "
308 "<name>\n" },
309 { "show-ether", do_show_ether,
310 " show-ether [-px][-o <field>,...] <link>\n" },
311 { "create-secobj", do_create_secobj,
312 " create-secobj [-t] [-f <file>] -c <class> <secobj>" },
313 { "delete-secobj", do_delete_secobj,
314 " delete-secobj [-t] <secobj>[,...]" },
315 { "show-secobj", do_show_secobj,
316 " show-secobj [-pP] [-o <field>,...] [<secobj>,...]\n" },
317 { "init-linkprop", do_init_linkprop, NULL },
318 { "init-secobj", do_init_secobj, NULL },
319 { "create-vlan", do_create_vlan,
320 " create-vlan [-ft] -l <link> -v <vid> [link]" },
321 { "delete-vlan", do_delete_vlan,
322 " delete-vlan [-t] <link>" },
323 { "show-vlan", do_show_vlan,
324 " show-vlan [-pP] [-o <field>,..] [<link>]\n" },
325 { "up-vlan", do_up_vlan, NULL },
326 { "create-iptun", do_create_iptun,
327 " create-iptun [-t] -T <type> "
328 "[-a {local|remote}=<addr>,...] <link>]" },
330 " delete-iptun [-t] <link>" },
331 { "modify-iptun", do_modify_iptun,
332 " modify-iptun [-t] -a {local|remote}=<addr>,... <link>" },
333 { "show-iptun", do_show_iptun,
334 " show-iptun [-pP] [-o <field>,..] [<link>]\n" },
335 { "up-iptun", do_up_iptun, NULL },
336 { "down-iptun", do_down_iptun, NULL },
337 { "delete-phys", do_delete_phys,
338 " delete-phys <link>" },
339 { "show-phys", do_show_phys,
340 " show-phys [-m | -H | -P] [[-p] [-o <field>[,...]] "
341 "[<link>]\n" },
342 { "init-phys", do_init_phys, NULL },
343 { "show-linkmap", do_show_linkmap, NULL },
344 { "create-vnic", do_create_vnic,
345 " create-vnic [-t] -l <link> [-m <value> | auto |\n"
346 "\t\t {factory [-n <slot-id>]} | {random [-r <prefix>]} |\n"
347 "\t\t {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n"
348 "\t\t [-p <prop>=<value>[,...]] <vnic-link>" },
349 { "delete-vnic", do_delete_vnic,
350 " delete-vnic [-t] <vnic-link>" },
351 { "show-vnic", do_show_vnic,
352 " show-vnic [-pP] [-l <link>] [-s [-i <interval>]] "
353 "[<link>]\n" },
354 { "up-vnic", do_up_vnic, NULL },
355 { "create-part", do_create_part,
356 " create-part [-t] [-f] -l <link> [-P <pkey>]\n"
357 "\t\t [-R <root-dir>] <part-link>" },
358 { "delete-part", do_delete_part,
359 " delete-part [-t] [-R <root-dir>] <part-link>"},
360 { "show-part", do_show_part,
361 " show-part [-pP] [-o <field>,...][-l <linkover>]\n"
362 "\t\t [<part-link>]" },
363 { "show-ib", do_show_ib,
364 " show-ib [-p] [-o <field>,...] [<link>]\n" },
365 { "up-part", do_up_part, NULL },
366 { "create-etherstub", do_create_etherstub,
367 " create-etherstub [-t] <link>" },
368 { "delete-etherstub", do_delete_etherstub,
369 " delete-etherstub [-t] <link>" },
370 { "show-etherstub", do_show_etherstub,
371 " show-etherstub [-t] [<link>]\n" },
372 { "create-simnet", do_create_simnet, NULL },
373 { "modify-simnet", do_modify_simnet, NULL },
942 LINKPROP_POSSIBLE
943 } linkprop_field_index_t;
944
945 static const ofmt_field_t linkprop_fields[] = {
946 /* name, field width, index */
947 { "LINK", 13, LINKPROP_LINK, print_linkprop_cb},
948 { "PROPERTY", 16, LINKPROP_PROPERTY, print_linkprop_cb},
949 { "PERM", 5, LINKPROP_PERM, print_linkprop_cb},
950 { "VALUE", 15, LINKPROP_VALUE, print_linkprop_cb},
951 { "DEFAULT", 15, LINKPROP_DEFAULT, print_linkprop_cb},
952 { "POSSIBLE", 20, LINKPROP_POSSIBLE, print_linkprop_cb},
953 { NULL, 0, 0, NULL}}
954 ;
955
956 #define MAX_PROP_LINE 512
957
958 typedef struct show_linkprop_state {
959 char ls_link[MAXLINKNAMELEN];
960 char *ls_line;
961 char **ls_propvals;
962 dladm_arg_list_t *ls_proplist;
963 boolean_t ls_parsable;
964 boolean_t ls_persist;
965 boolean_t ls_header;
966 dladm_status_t ls_status;
967 dladm_status_t ls_retstatus;
968 ofmt_handle_t ls_ofmt;
969 } show_linkprop_state_t;
970
971 typedef struct set_linkprop_state {
972 const char *ls_name;
973 boolean_t ls_reset;
974 boolean_t ls_temp;
975 dladm_status_t ls_status;
976 } set_linkprop_state_t;
977
978 typedef struct linkprop_args_s {
979 show_linkprop_state_t *ls_state;
980 char *ls_propname;
981 datalink_id_t ls_linkid;
994 { "OBJECT", 21,
995 offsetof(secobj_fields_buf_t, ss_obj_name), print_default_cb},
996 { "CLASS", 21,
997 offsetof(secobj_fields_buf_t, ss_class), print_default_cb},
998 { "VALUE", 31,
999 offsetof(secobj_fields_buf_t, ss_val), print_default_cb},
1000 { NULL, 0, 0, NULL}}
1001 ;
1002
1003 /*
1004 * structures for 'dladm show-vnic'
1005 */
1006 typedef struct vnic_fields_buf_s
1007 {
1008 char vnic_link[DLPI_LINKNAME_MAX];
1009 char vnic_over[DLPI_LINKNAME_MAX];
1010 char vnic_speed[6];
1011 char vnic_macaddr[18];
1012 char vnic_macaddrtype[19];
1013 char vnic_vid[6];
1014 } vnic_fields_buf_t;
1015
1016 static const ofmt_field_t vnic_fields[] = {
1017 { "LINK", 13,
1018 offsetof(vnic_fields_buf_t, vnic_link), print_default_cb},
1019 { "OVER", 13,
1020 offsetof(vnic_fields_buf_t, vnic_over), print_default_cb},
1021 { "SPEED", 7,
1022 offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb},
1023 { "MACADDRESS", 18,
1024 offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb},
1025 { "MACADDRTYPE", 20,
1026 offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb},
1027 { "VID", 7,
1028 offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb},
1029 { NULL, 0, 0, NULL}}
1030 ;
1031
1032 /*
1033 * structures for 'dladm show-ib'
1034 */
1035 typedef struct ib_fields_buf_s
1036 {
1037 char ib_link[DLPI_LINKNAME_MAX];
1038 char ib_hcaguid[17];
1039 char ib_portguid[17];
1040 char ib_portnum[4];
1041 char ib_state[6];
1042 char ib_pkeys[MAXPKEYSTRSZ];
1043 } ib_fields_buf_t;
1044
1045 static const ofmt_field_t ib_fields[] = {
1046 { "LINK", 13,
1047 offsetof(ib_fields_buf_t, ib_link), print_default_cb},
1048 { "HCAGUID", IBGUIDSTRLEN,
2478 status = dladm_vlan_delete(handle, linkid, flags);
2479 done:
2480 if (status != DLADM_STATUS_OK)
2481 die_dlerr(status, "delete operation failed");
2482 }
2483
2484 /*ARGSUSED*/
2485 static void
2486 do_up_vlan(int argc, char *argv[], const char *use)
2487 {
2488 do_up_vnic_common(argc, argv, use, B_TRUE);
2489 }
2490
2491 static void
2492 do_rename_link(int argc, char *argv[], const char *use)
2493 {
2494 int option;
2495 char *link1, *link2;
2496 char *altroot = NULL;
2497 dladm_status_t status;
2498
2499 opterr = 0;
2500 while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) {
2501 switch (option) {
2502 case 'R':
2503 altroot = optarg;
2504 break;
2505 default:
2506 die_opterr(optopt, option, use);
2507 break;
2508 }
2509 }
2510
2511 /* get link1 and link2 name (required the last 2 arguments) */
2512 if (optind != (argc - 2))
2513 usage();
2514
2515 if (altroot != NULL)
2516 altroot_cmd(altroot, argc, argv);
2517
2518 link1 = argv[optind++];
2519 link2 = argv[optind];
2520 if ((status = dladm_rename_link(handle, link1, link2)) !=
2521 DLADM_STATUS_OK)
2522 die_dlerr(status, "rename operation failed");
2523 }
2524
2525 /*ARGSUSED*/
2526 static void
2527 do_delete_phys(int argc, char *argv[], const char *use)
2528 {
2529 datalink_id_t linkid = DATALINK_ALL_LINKID;
2530 dladm_status_t status;
2531
2532 /* get link name (required the last argument) */
2533 if (argc > 2)
2534 usage();
2535
2536 if (argc == 2) {
2537 if ((status = dladm_name2info(handle, argv[1], &linkid, NULL,
2538 NULL, NULL)) != DLADM_STATUS_OK)
2539 die_dlerr(status, "cannot delete '%s'", argv[1]);
2540 }
3390 int option;
3391 boolean_t s_arg = B_FALSE;
3392 boolean_t S_arg = B_FALSE;
3393 boolean_t i_arg = B_FALSE;
3394 uint32_t flags = DLADM_OPT_ACTIVE;
3395 boolean_t p_arg = B_FALSE;
3396 datalink_id_t linkid = DATALINK_ALL_LINKID;
3397 char linkname[MAXLINKNAMELEN];
3398 uint32_t interval = 0;
3399 show_state_t state;
3400 dladm_status_t status;
3401 boolean_t o_arg = B_FALSE;
3402 char *fields_str = NULL;
3403 char *all_active_fields = "link,class,mtu,state,bridge,over";
3404 char *all_inactive_fields = "link,class,bridge,over";
3405 char *allstat_fields =
3406 "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors";
3407 ofmt_handle_t ofmt;
3408 ofmt_status_t oferr;
3409 uint_t ofmtflags = 0;
3410
3411 bzero(&state, sizeof (state));
3412
3413 opterr = 0;
3414 while ((option = getopt_long(argc, argv, ":pPsSi:o:",
3415 show_lopts, NULL)) != -1) {
3416 switch (option) {
3417 case 'p':
3418 if (p_arg)
3419 die_optdup(option);
3420
3421 p_arg = B_TRUE;
3422 break;
3423 case 's':
3424 if (s_arg)
3425 die_optdup(option);
3426
3427 s_arg = B_TRUE;
3428 break;
3429 case 'P':
3430 if (flags != DLADM_OPT_ACTIVE)
3431 die_optdup(option);
3432
3433 flags = DLADM_OPT_PERSIST;
3434 break;
3435 case 'S':
3436 if (S_arg)
3437 die_optdup(option);
3438
3439 S_arg = B_TRUE;
3440 break;
3441 case 'o':
3442 o_arg = B_TRUE;
3443 fields_str = optarg;
3444 break;
3445 case 'i':
3446 if (i_arg)
3447 die_optdup(option);
3448
3449 i_arg = B_TRUE;
3450 if (!dladm_str2interval(optarg, &interval))
3451 die("invalid interval value '%s'", optarg);
3452 break;
3453 default:
3454 die_opterr(optopt, option, use);
3455 break;
3456 }
3457 }
3458
3459 if (i_arg && !(s_arg || S_arg))
3460 die("the option -i can be used only with -s or -S");
3461
3462 if (s_arg && S_arg)
3463 die("the -s option cannot be used with -S");
3464
3465 if (s_arg && flags != DLADM_OPT_ACTIVE)
3466 die("the option -P cannot be used with -s");
3467
3468 if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE))
3469 die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P');
3470
3471 /* get link name (optional last argument) */
3472 if (optind == (argc-1)) {
3473 uint32_t f;
3474
3475 if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) >=
3476 MAXLINKNAMELEN)
3477 die("link name too long");
3478 if ((status = dladm_name2info(handle, linkname, &linkid, &f,
3479 NULL, NULL)) != DLADM_STATUS_OK) {
3480 die_dlerr(status, "link %s is not valid", linkname);
3481 }
3482
3483 if (!(f & flags)) {
3484 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s",
3485 argv[optind], flags == DLADM_OPT_PERSIST ?
3486 "a temporary link" : "temporarily removed");
3487 }
3488 } else if (optind != argc) {
3489 usage();
3490 }
3491
3492 if (p_arg && !o_arg)
3493 die("-p requires -o");
3494
3495 if (S_arg) {
3496 dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT);
3497 return;
3498 }
3499
4724 die("invalid VLAN identifier '%s'", optarg);
4725
4726 break;
4727 case 'f':
4728 flags |= DLADM_OPT_FORCE;
4729 break;
4730 default:
4731 die_opterr(optopt, option, use);
4732 }
4733 }
4734
4735 if (mac_addr_type == VNIC_MAC_ADDR_TYPE_UNKNOWN)
4736 mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO;
4737
4738 /*
4739 * 'f' - force, flag can be specified only with 'v' - vlan.
4740 */
4741 if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0)
4742 die("-f option can only be used with -v");
4743
4744 if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM &&
4745 mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED)
4746 usage();
4747
4748 if (mac_addr_type == VNIC_MAC_ADDR_TYPE_VRID) {
4749 if (vrid == VRRP_VRID_NONE || af == AF_UNSPEC ||
4750 mac_addr != NULL || maclen != 0 || mac_slot != -1 ||
4751 mac_prefix_len != 0) {
4752 usage();
4753 }
4754 } else if ((af != AF_UNSPEC || vrid != VRRP_VRID_NONE)) {
4755 usage();
4756 }
4757
4758 /* check required options */
4759 if (!l_arg)
4760 usage();
4761
4762 if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY)
4763 usage();
4815 * Let the delete continue anyway.
4816 */
4817 return;
4818 }
4819 is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID);
4820 if (is_etherstub != etherstub) {
4821 die("'%s' is not %s", name,
4822 (is_etherstub ? "a vnic" : "an etherstub"));
4823 }
4824 }
4825
4826 static void
4827 do_delete_vnic_common(int argc, char *argv[], const char *use,
4828 boolean_t etherstub)
4829 {
4830 int option;
4831 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4832 datalink_id_t linkid;
4833 char *altroot = NULL;
4834 dladm_status_t status;
4835
4836 opterr = 0;
4837 while ((option = getopt_long(argc, argv, ":R:t", lopts,
4838 NULL)) != -1) {
4839 switch (option) {
4840 case 't':
4841 flags &= ~DLADM_OPT_PERSIST;
4842 break;
4843 case 'R':
4844 altroot = optarg;
4845 break;
4846 default:
4847 die_opterr(optopt, option, use);
4848 }
4849 }
4850
4851 /* get vnic name (required last argument) */
4852 if (optind != (argc - 1))
4853 usage();
4854
4855 if (altroot != NULL)
4856 altroot_cmd(altroot, argc, argv);
4857
4858 status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
4859 NULL);
4860 if (status != DLADM_STATUS_OK)
4861 die("invalid link name '%s'", argv[optind]);
4862
4863 if ((flags & DLADM_OPT_ACTIVE) != 0) {
4864 do_etherstub_check(argv[optind], linkid, etherstub,
4865 DLADM_OPT_ACTIVE);
4866 }
4867 if ((flags & DLADM_OPT_PERSIST) != 0) {
4868 do_etherstub_check(argv[optind], linkid, etherstub,
4869 DLADM_OPT_PERSIST);
4870 }
4871
4872 status = dladm_vnic_delete(handle, linkid, flags);
4873 if (status != DLADM_STATUS_OK)
4874 die_dlerr(status, "vnic deletion failed");
4875 }
4876
4877 static void
4878 do_delete_vnic(int argc, char *argv[], const char *use)
4879 {
4971 }
4972 (void) printf("\n");
4973
4974 *old_stats = *vnic_stats;
4975 }
4976
4977 /*
4978 * Called from the walker dladm_vnic_walk_sys() for each vnic to display
4979 * vnic information or statistics.
4980 */
4981 static dladm_status_t
4982 print_vnic(show_vnic_state_t *state, datalink_id_t linkid)
4983 {
4984 dladm_vnic_attr_t attr, *vnic = &attr;
4985 dladm_status_t status;
4986 boolean_t is_etherstub;
4987 char devname[MAXLINKNAMELEN];
4988 char vnic_name[MAXLINKNAMELEN];
4989 char mstr[MAXMACADDRLEN * 3];
4990 vnic_fields_buf_t vbuf;
4991
4992 if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) !=
4993 DLADM_STATUS_OK)
4994 return (status);
4995
4996 is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID);
4997 if (state->vs_etherstub != is_etherstub) {
4998 /*
4999 * Want all etherstub but it's not one, or want
5000 * non-etherstub and it's one.
5001 */
5002 return (DLADM_STATUS_OK);
5003 }
5004
5005 if (state->vs_link_id != DATALINK_ALL_LINKID) {
5006 if (state->vs_link_id != vnic->va_link_id)
5007 return (DLADM_STATUS_OK);
5008 }
5009
5010 if (dladm_datalink_id2info(handle, linkid, NULL, NULL,
5011 NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK)
5012 return (DLADM_STATUS_BADARG);
5013
5014 bzero(devname, sizeof (devname));
5015 if (!is_etherstub &&
5016 dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL,
5017 NULL, devname, sizeof (devname)) != DLADM_STATUS_OK)
5018 (void) sprintf(devname, "?");
5019
5020 state->vs_found = B_TRUE;
5021 if (state->vs_stats) {
5022 /* print vnic statistics */
5023 pktsum_t vnic_stats;
5024
5025 if (state->vs_firstonly) {
5026 if (state->vs_donefirst)
5027 return (0);
5028 state->vs_donefirst = B_TRUE;
5029 }
5030
5031 if (!state->vs_printstats) {
5032 /*
5033 * get vnic statistics and add to the sum for the
5034 * named device.
5035 */
5036 get_link_stats(vnic_name, &vnic_stats);
5037 dladm_stats_total(&state->vs_totalstats, &vnic_stats,
5038 &state->vs_prevstats[vnic->va_vnic_id]);
5039 } else {
5075 vnic->va_mac_slot);
5076 break;
5077 case VNIC_MAC_ADDR_TYPE_VRID:
5078 (void) snprintf(vbuf.vnic_macaddrtype,
5079 sizeof (vbuf.vnic_macaddrtype),
5080 gettext("vrrp, %d/%s"),
5081 vnic->va_vrid, vnic->va_af == AF_INET ?
5082 "inet" : "inet6");
5083 break;
5084 }
5085
5086 if (strlen(vbuf.vnic_macaddrtype) > 0) {
5087 (void) snprintf(vbuf.vnic_macaddr,
5088 sizeof (vbuf.vnic_macaddr), "%s",
5089 dladm_aggr_macaddr2str(vnic->va_mac_addr,
5090 mstr));
5091 }
5092
5093 (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid),
5094 "%d", vnic->va_vid);
5095 }
5096
5097 ofmt_print(state->vs_ofmt, &vbuf);
5098
5099 return (DLADM_STATUS_OK);
5100 }
5101 }
5102
5103 /* ARGSUSED */
5104 static int
5105 show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg)
5106 {
5107 show_vnic_state_t *state = arg;
5108
5109 state->vs_status = print_vnic(state, linkid);
5110 return (DLADM_WALK_CONTINUE);
5111 }
5112
5113 static void
5114 do_show_vnic_common(int argc, char *argv[], const char *use,
5115 boolean_t etherstub)
5116 {
5117 int option;
5118 boolean_t s_arg = B_FALSE;
5119 boolean_t i_arg = B_FALSE;
5120 boolean_t l_arg = B_FALSE;
5121 uint32_t interval = 0, flags = DLADM_OPT_ACTIVE;
5122 datalink_id_t linkid = DATALINK_ALL_LINKID;
5123 datalink_id_t dev_linkid = DATALINK_ALL_LINKID;
5124 show_vnic_state_t state;
5125 dladm_status_t status;
5126 boolean_t o_arg = B_FALSE;
5127 char *fields_str = NULL;
5128 const ofmt_field_t *pf;
5129 char *all_e_fields = "link";
5130 ofmt_handle_t ofmt;
5131 ofmt_status_t oferr;
5132 uint_t ofmtflags = 0;
5133
5134 bzero(&state, sizeof (state));
5135 opterr = 0;
5136 while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts,
5137 NULL)) != -1) {
5138 switch (option) {
5139 case 'p':
5140 state.vs_parsable = B_TRUE;
5141 break;
5142 case 'P':
5143 flags = DLADM_OPT_PERSIST;
5144 break;
5145 case 'l':
5146 if (etherstub)
5147 die("option not supported for this command");
5148
5149 if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >=
5150 MAXLINKNAMELEN)
5151 die("link name too long");
5152
5153 l_arg = B_TRUE;
5154 break;
5155 case 's':
5156 if (s_arg) {
5157 die("the option -s cannot be specified "
5158 "more than once");
5159 }
5160 s_arg = B_TRUE;
5161 break;
5162 case 'i':
5163 if (i_arg) {
5164 die("the option -i cannot be specified "
5165 "more than once");
5166 }
5167 i_arg = B_TRUE;
5168 if (!dladm_str2interval(optarg, &interval))
5169 die("invalid interval value '%s'", optarg);
5170 break;
5171 case 'o':
5172 o_arg = B_TRUE;
5173 fields_str = optarg;
5174 break;
5175 default:
5176 die_opterr(optopt, option, use);
5177 }
5178 }
5179
5180 if (i_arg && !s_arg)
5181 die("the option -i can be used only with -s");
5182
5183 /* get vnic ID (optional last argument) */
5184 if (optind == (argc - 1)) {
5185 status = dladm_name2info(handle, argv[optind], &linkid, NULL,
5186 NULL, NULL);
5187 if (status != DLADM_STATUS_OK) {
5188 die_dlerr(status, "invalid vnic name '%s'",
5189 argv[optind]);
5190 }
5191 (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN);
5192 } else if (optind != argc) {
5193 usage();
5194 }
5195
5196 if (l_arg) {
5197 status = dladm_name2info(handle, state.vs_link, &dev_linkid,
5198 NULL, NULL, NULL);
5199 if (status != DLADM_STATUS_OK) {
5200 die_dlerr(status, "invalid link name '%s'",
5201 state.vs_link);
5202 }
5203 }
5204
5205 state.vs_vnic_id = linkid;
5206 state.vs_link_id = dev_linkid;
5207 state.vs_etherstub = etherstub;
5208 state.vs_found = B_FALSE;
5209 state.vs_flags = flags;
5210
5211 if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
5212 if (etherstub)
5213 fields_str = all_e_fields;
5214 }
5215 pf = vnic_fields;
5216
5217 if (state.vs_parsable)
5218 ofmtflags |= OFMT_PARSABLE;
5219 oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
5220 dladm_ofmt_check(oferr, state.vs_parsable, ofmt);
5221 state.vs_ofmt = ofmt;
5222
5223 if (s_arg) {
5224 /* Display vnic statistics */
5225 vnic_stats(&state, interval);
5226 ofmt_close(ofmt);
5227 return;
5228 }
5229
6678
6679 ofmt_print(statep->ls_ofmt, &ls_arg);
6680
6681 return (DLADM_WALK_CONTINUE);
6682 }
6683
6684 static void
6685 do_show_linkprop(int argc, char **argv, const char *use)
6686 {
6687 int option;
6688 char propstr[DLADM_STRSIZE];
6689 dladm_arg_list_t *proplist = NULL;
6690 datalink_id_t linkid = DATALINK_ALL_LINKID;
6691 show_linkprop_state_t state;
6692 uint32_t flags = DLADM_OPT_ACTIVE;
6693 dladm_status_t status;
6694 char *fields_str = NULL;
6695 ofmt_handle_t ofmt;
6696 ofmt_status_t oferr;
6697 uint_t ofmtflags = 0;
6698
6699 bzero(propstr, DLADM_STRSIZE);
6700 opterr = 0;
6701 state.ls_propvals = NULL;
6702 state.ls_line = NULL;
6703 state.ls_parsable = B_FALSE;
6704 state.ls_persist = B_FALSE;
6705 state.ls_header = B_TRUE;
6706 state.ls_retstatus = DLADM_STATUS_OK;
6707
6708 while ((option = getopt_long(argc, argv, ":p:cPo:",
6709 prop_longopts, NULL)) != -1) {
6710 switch (option) {
6711 case 'p':
6712 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
6713 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
6714 DLADM_STRSIZE)
6715 die("property list too long '%s'", propstr);
6716 break;
6717 case 'c':
6718 state.ls_parsable = B_TRUE;
6719 break;
6720 case 'P':
6721 state.ls_persist = B_TRUE;
6722 flags = DLADM_OPT_PERSIST;
6723 break;
6724 case 'o':
6725 fields_str = optarg;
6726 break;
6727 default:
6728 die_opterr(optopt, option, use);
6729 break;
6730 }
6731 }
6732
6733 if (optind == (argc - 1)) {
6734 if ((status = dladm_name2info(handle, argv[optind], &linkid,
6735 NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6736 die_dlerr(status, "link %s is not valid", argv[optind]);
6737 }
6738 } else if (optind != argc) {
6739 usage();
6740 }
6741
6742 if (dladm_parse_link_props(propstr, &proplist, B_TRUE)
6743 != DLADM_STATUS_OK)
6744 die("invalid link properties specified");
6745 state.ls_proplist = proplist;
6746 state.ls_status = DLADM_STATUS_OK;
6747
6748 if (state.ls_parsable)
6749 ofmtflags |= OFMT_PARSABLE;
6750 else
6751 ofmtflags |= OFMT_WRAP;
6752
6753 oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt);
6754 dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
6755 state.ls_ofmt = ofmt;
6756
6757 if (linkid == DATALINK_ALL_LINKID) {
6758 (void) dladm_walk_datalink_id(show_linkprop_onelink, handle,
6759 &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
6760 } else {
6761 (void) show_linkprop_onelink(handle, linkid, &state);
6762 }
6763 ofmt_close(ofmt);
6764 dladm_free_props(proplist);
6765
6770 }
6771
6772 static int
6773 show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
6774 {
6775 int i;
6776 char *buf;
6777 uint32_t flags;
6778 dladm_arg_list_t *proplist = NULL;
6779 show_linkprop_state_t *statep = arg;
6780 dlpi_handle_t dh = NULL;
6781
6782 statep->ls_status = DLADM_STATUS_OK;
6783
6784 if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL,
6785 statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) {
6786 statep->ls_status = DLADM_STATUS_NOTFOUND;
6787 return (DLADM_WALK_CONTINUE);
6788 }
6789
6790 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) ||
6791 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) {
6792 statep->ls_status = DLADM_STATUS_BADARG;
6793 return (DLADM_WALK_CONTINUE);
6794 }
6795
6796 proplist = statep->ls_proplist;
6797
6798 /*
6799 * When some WiFi links are opened for the first time, their hardware
6800 * automatically scans for APs and does other slow operations. Thus,
6801 * if there are no open links, the retrieval of link properties
6802 * (below) will proceed slowly unless we hold the link open.
6803 *
6804 * Note that failure of dlpi_open() does not necessarily mean invalid
6805 * link properties, because dlpi_open() may fail because of incorrect
6806 * autopush configuration. Therefore, we ingore the return value of
6807 * dlpi_open().
6808 */
6809 if (!statep->ls_persist)
6852 status != DLADM_STATUS_NOTSUP) {
6853 warn_dlerr(status, "cannot reset link property '%s' on '%s'",
6854 propname, statep->ls_name);
6855 statep->ls_status = status;
6856 }
6857
6858 return (DLADM_WALK_CONTINUE);
6859 }
6860
6861 static void
6862 set_linkprop(int argc, char **argv, boolean_t reset, const char *use)
6863 {
6864 int i, option;
6865 char errmsg[DLADM_STRSIZE];
6866 char *altroot = NULL;
6867 datalink_id_t linkid;
6868 boolean_t temp = B_FALSE;
6869 dladm_status_t status = DLADM_STATUS_OK;
6870 char propstr[DLADM_STRSIZE];
6871 dladm_arg_list_t *proplist = NULL;
6872
6873 opterr = 0;
6874 bzero(propstr, DLADM_STRSIZE);
6875
6876 while ((option = getopt_long(argc, argv, ":p:R:t",
6877 prop_longopts, NULL)) != -1) {
6878 switch (option) {
6879 case 'p':
6880 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
6881 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
6882 DLADM_STRSIZE)
6883 die("property list too long '%s'", propstr);
6884 break;
6885 case 't':
6886 temp = B_TRUE;
6887 break;
6888 case 'R':
6889 altroot = optarg;
6890 break;
6891 default:
6892 die_opterr(optopt, option, use);
6893
6894 }
6895 }
6896
6897 /* get link name (required last argument) */
6898 if (optind != (argc - 1))
6899 usage();
6900
6901 if (dladm_parse_link_props(propstr, &proplist, reset) !=
6902 DLADM_STATUS_OK)
6903 die("invalid link properties specified");
6904
6905 if (proplist == NULL && !reset)
6906 die("link property must be specified");
6907
6908 if (altroot != NULL) {
6909 dladm_free_props(proplist);
6910 altroot_cmd(altroot, argc, argv);
6911 }
6912
6913 status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
6914 NULL);
6915 if (status != DLADM_STATUS_OK)
6916 die_dlerr(status, "link %s is not valid", argv[optind]);
6917
6918 if (proplist == NULL) {
6919 set_linkprop_state_t state;
6920
6921 state.ls_name = argv[optind];
6922 state.ls_reset = reset;
6923 state.ls_temp = temp;
6924 state.ls_status = DLADM_STATUS_OK;
6925
6926 (void) dladm_walk_linkprop(handle, linkid, &state,
6927 reset_one_linkprop);
6928
6929 status = state.ls_status;
6930 goto done;
6931 }
6932
6933 for (i = 0; i < proplist->al_count; i++) {
6934 dladm_arg_info_t *aip = &proplist->al_info[i];
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012 Joyent, Inc. All rights reserved.
24 */
25
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <dlfcn.h>
29 #include <locale.h>
30 #include <signal.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <fcntl.h>
34 #include <string.h>
35 #include <stropts.h>
36 #include <sys/stat.h>
37 #include <errno.h>
38 #include <kstat.h>
39 #include <strings.h>
40 #include <getopt.h>
41 #include <unistd.h>
42 #include <priv.h>
43 #include <limits.h>
138 ofmt_handle_t gs_ofmt;
139 } show_grp_state_t;
140
141 typedef struct show_vnic_state {
142 datalink_id_t vs_vnic_id;
143 datalink_id_t vs_link_id;
144 char vs_vnic[MAXLINKNAMELEN];
145 char vs_link[MAXLINKNAMELEN];
146 boolean_t vs_parsable;
147 boolean_t vs_found;
148 boolean_t vs_firstonly;
149 boolean_t vs_donefirst;
150 boolean_t vs_stats;
151 boolean_t vs_printstats;
152 pktsum_t vs_totalstats;
153 pktsum_t vs_prevstats[MAXVNIC];
154 boolean_t vs_etherstub;
155 dladm_status_t vs_status;
156 uint32_t vs_flags;
157 ofmt_handle_t vs_ofmt;
158 char *vs_zonename;
159 } show_vnic_state_t;
160
161 typedef struct show_part_state {
162 datalink_id_t ps_over_id;
163 char ps_part[MAXLINKNAMELEN];
164 boolean_t ps_parsable;
165 boolean_t ps_found;
166 dladm_status_t ps_status;
167 uint32_t ps_flags;
168 ofmt_handle_t ps_ofmt;
169 } show_part_state_t;
170
171 typedef struct show_ib_state {
172 datalink_id_t is_link_id;
173 char is_link[MAXLINKNAMELEN];
174 boolean_t is_parsable;
175 dladm_status_t is_status;
176 uint32_t is_flags;
177 ofmt_handle_t is_ofmt;
178 } show_ib_state_t;
250 static int show_etherprop(dladm_handle_t, datalink_id_t, void *);
251 static void show_ether_xprop(void *, dladm_ether_info_t *);
252 static boolean_t link_is_ether(const char *, datalink_id_t *);
253
254 static boolean_t str2int(const char *, int *);
255 static void die(const char *, ...);
256 static void die_optdup(int);
257 static void die_opterr(int, int, const char *);
258 static void die_dlerr(dladm_status_t, const char *, ...);
259 static void warn(const char *, ...);
260 static void warn_dlerr(dladm_status_t, const char *, ...);
261
262 typedef struct cmd {
263 char *c_name;
264 cmdfunc_t *c_fn;
265 const char *c_usage;
266 } cmd_t;
267
268 static cmd_t cmds[] = {
269 { "rename-link", do_rename_link,
270 " rename-link [-z zonename] <oldlink> <newlink>" },
271 { "show-link", do_show_link,
272 " show-link [-pP] [-o <field>,..] [-s [-i <interval>]] "
273 "[<link>]\n" },
274 { "create-aggr", do_create_aggr,
275 " create-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] "
276 "[-u <address>]\n"
277 "\t\t -l <link> [-l <link>...] <link>" },
278 { "delete-aggr", do_delete_aggr,
279 " delete-aggr [-t] <link>" },
280 { "add-aggr", do_add_aggr,
281 " add-aggr [-t] -l <link> [-l <link>...] <link>" },
282 { "remove-aggr", do_remove_aggr,
283 " remove-aggr [-t] -l <link> [-l <link>...] <link>" },
284 { "modify-aggr", do_modify_aggr,
285 " modify-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] "
286 "[-u <address>]\n"
287 "\t\t <link>" },
288 { "show-aggr", do_show_aggr,
289 " show-aggr [-pPLx] [-o <field>,..] [-s [-i <interval>]] "
290 "[<link>]\n" },
291 { "up-aggr", do_up_aggr, NULL },
292 { "scan-wifi", do_scan_wifi,
293 " scan-wifi [-p] [-o <field>,...] [<link>]" },
294 { "connect-wifi", do_connect_wifi,
295 " connect-wifi [-e <essid>] [-i <bssid>] [-k <key>,...] "
296 "[-s wep|wpa]\n"
297 "\t\t [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g] "
298 "[-T <time>]\n"
299 "\t\t [<link>]" },
300 { "disconnect-wifi", do_disconnect_wifi,
301 " disconnect-wifi [-a] [<link>]" },
302 { "show-wifi", do_show_wifi,
303 " show-wifi [-p] [-o <field>,...] [<link>]\n" },
304 { "set-linkprop", do_set_linkprop,
305 " set-linkprop [-t] [-z zonename] -p <prop>=<value>[,...] "
306 "<name>" },
307 { "reset-linkprop", do_reset_linkprop,
308 " reset-linkprop [-t] [-z zonename] [-p <prop>,...] <name>"},
309 { "show-linkprop", do_show_linkprop,
310 " show-linkprop [-cP] [-o <field>,...] [-z zonename] "
311 "[-p <prop>,...] <name>\n" },
312 { "show-ether", do_show_ether,
313 " show-ether [-px][-o <field>,...] <link>\n" },
314 { "create-secobj", do_create_secobj,
315 " create-secobj [-t] [-f <file>] -c <class> <secobj>" },
316 { "delete-secobj", do_delete_secobj,
317 " delete-secobj [-t] <secobj>[,...]" },
318 { "show-secobj", do_show_secobj,
319 " show-secobj [-pP] [-o <field>,...] [<secobj>,...]\n" },
320 { "init-linkprop", do_init_linkprop, NULL },
321 { "init-secobj", do_init_secobj, NULL },
322 { "create-vlan", do_create_vlan,
323 " create-vlan [-ft] -l <link> -v <vid> [link]" },
324 { "delete-vlan", do_delete_vlan,
325 " delete-vlan [-t] <link>" },
326 { "show-vlan", do_show_vlan,
327 " show-vlan [-pP] [-o <field>,..] [<link>]\n" },
328 { "up-vlan", do_up_vlan, NULL },
329 { "create-iptun", do_create_iptun,
330 " create-iptun [-t] -T <type> "
331 "[-a {local|remote}=<addr>,...] <link>]" },
333 " delete-iptun [-t] <link>" },
334 { "modify-iptun", do_modify_iptun,
335 " modify-iptun [-t] -a {local|remote}=<addr>,... <link>" },
336 { "show-iptun", do_show_iptun,
337 " show-iptun [-pP] [-o <field>,..] [<link>]\n" },
338 { "up-iptun", do_up_iptun, NULL },
339 { "down-iptun", do_down_iptun, NULL },
340 { "delete-phys", do_delete_phys,
341 " delete-phys <link>" },
342 { "show-phys", do_show_phys,
343 " show-phys [-m | -H | -P] [[-p] [-o <field>[,...]] "
344 "[<link>]\n" },
345 { "init-phys", do_init_phys, NULL },
346 { "show-linkmap", do_show_linkmap, NULL },
347 { "create-vnic", do_create_vnic,
348 " create-vnic [-t] -l <link> [-m <value> | auto |\n"
349 "\t\t {factory [-n <slot-id>]} | {random [-r <prefix>]} |\n"
350 "\t\t {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n"
351 "\t\t [-p <prop>=<value>[,...]] <vnic-link>" },
352 { "delete-vnic", do_delete_vnic,
353 " delete-vnic [-t] [-z zonename] <vnic-link>" },
354 { "show-vnic", do_show_vnic,
355 " show-vnic [-pP] [-l <link>] [-z zonename] "
356 "[-s [-i <interval>]] [<link>]\n" },
357 { "up-vnic", do_up_vnic, NULL },
358 { "create-part", do_create_part,
359 " create-part [-t] [-f] -l <link> [-P <pkey>]\n"
360 "\t\t [-R <root-dir>] <part-link>" },
361 { "delete-part", do_delete_part,
362 " delete-part [-t] [-R <root-dir>] <part-link>"},
363 { "show-part", do_show_part,
364 " show-part [-pP] [-o <field>,...][-l <linkover>]\n"
365 "\t\t [<part-link>]" },
366 { "show-ib", do_show_ib,
367 " show-ib [-p] [-o <field>,...] [<link>]\n" },
368 { "up-part", do_up_part, NULL },
369 { "create-etherstub", do_create_etherstub,
370 " create-etherstub [-t] <link>" },
371 { "delete-etherstub", do_delete_etherstub,
372 " delete-etherstub [-t] <link>" },
373 { "show-etherstub", do_show_etherstub,
374 " show-etherstub [-t] [<link>]\n" },
375 { "create-simnet", do_create_simnet, NULL },
376 { "modify-simnet", do_modify_simnet, NULL },
945 LINKPROP_POSSIBLE
946 } linkprop_field_index_t;
947
948 static const ofmt_field_t linkprop_fields[] = {
949 /* name, field width, index */
950 { "LINK", 13, LINKPROP_LINK, print_linkprop_cb},
951 { "PROPERTY", 16, LINKPROP_PROPERTY, print_linkprop_cb},
952 { "PERM", 5, LINKPROP_PERM, print_linkprop_cb},
953 { "VALUE", 15, LINKPROP_VALUE, print_linkprop_cb},
954 { "DEFAULT", 15, LINKPROP_DEFAULT, print_linkprop_cb},
955 { "POSSIBLE", 20, LINKPROP_POSSIBLE, print_linkprop_cb},
956 { NULL, 0, 0, NULL}}
957 ;
958
959 #define MAX_PROP_LINE 512
960
961 typedef struct show_linkprop_state {
962 char ls_link[MAXLINKNAMELEN];
963 char *ls_line;
964 char **ls_propvals;
965 char *ls_zonename;
966 dladm_arg_list_t *ls_proplist;
967 boolean_t ls_parsable;
968 boolean_t ls_persist;
969 boolean_t ls_header;
970 dladm_status_t ls_status;
971 dladm_status_t ls_retstatus;
972 ofmt_handle_t ls_ofmt;
973 } show_linkprop_state_t;
974
975 typedef struct set_linkprop_state {
976 const char *ls_name;
977 boolean_t ls_reset;
978 boolean_t ls_temp;
979 dladm_status_t ls_status;
980 } set_linkprop_state_t;
981
982 typedef struct linkprop_args_s {
983 show_linkprop_state_t *ls_state;
984 char *ls_propname;
985 datalink_id_t ls_linkid;
998 { "OBJECT", 21,
999 offsetof(secobj_fields_buf_t, ss_obj_name), print_default_cb},
1000 { "CLASS", 21,
1001 offsetof(secobj_fields_buf_t, ss_class), print_default_cb},
1002 { "VALUE", 31,
1003 offsetof(secobj_fields_buf_t, ss_val), print_default_cb},
1004 { NULL, 0, 0, NULL}}
1005 ;
1006
1007 /*
1008 * structures for 'dladm show-vnic'
1009 */
1010 typedef struct vnic_fields_buf_s
1011 {
1012 char vnic_link[DLPI_LINKNAME_MAX];
1013 char vnic_over[DLPI_LINKNAME_MAX];
1014 char vnic_speed[6];
1015 char vnic_macaddr[18];
1016 char vnic_macaddrtype[19];
1017 char vnic_vid[6];
1018 char vnic_zone[ZONENAME_MAX];
1019 } vnic_fields_buf_t;
1020
1021 static const ofmt_field_t vnic_fields[] = {
1022 { "LINK", 13,
1023 offsetof(vnic_fields_buf_t, vnic_link), print_default_cb},
1024 { "OVER", 11,
1025 offsetof(vnic_fields_buf_t, vnic_over), print_default_cb},
1026 { "SPEED", 6,
1027 offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb},
1028 { "MACADDRESS", 18,
1029 offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb},
1030 { "MACADDRTYPE", 12,
1031 offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb},
1032 { "VID", 5,
1033 offsetof(vnic_fields_buf_t, vnic_vid), print_default_cb},
1034 { "ZONE", 20,
1035 offsetof(vnic_fields_buf_t, vnic_zone), print_default_cb},
1036 { NULL, 0, 0, NULL}}
1037 ;
1038
1039 /*
1040 * structures for 'dladm show-ib'
1041 */
1042 typedef struct ib_fields_buf_s
1043 {
1044 char ib_link[DLPI_LINKNAME_MAX];
1045 char ib_hcaguid[17];
1046 char ib_portguid[17];
1047 char ib_portnum[4];
1048 char ib_state[6];
1049 char ib_pkeys[MAXPKEYSTRSZ];
1050 } ib_fields_buf_t;
1051
1052 static const ofmt_field_t ib_fields[] = {
1053 { "LINK", 13,
1054 offsetof(ib_fields_buf_t, ib_link), print_default_cb},
1055 { "HCAGUID", IBGUIDSTRLEN,
2485 status = dladm_vlan_delete(handle, linkid, flags);
2486 done:
2487 if (status != DLADM_STATUS_OK)
2488 die_dlerr(status, "delete operation failed");
2489 }
2490
2491 /*ARGSUSED*/
2492 static void
2493 do_up_vlan(int argc, char *argv[], const char *use)
2494 {
2495 do_up_vnic_common(argc, argv, use, B_TRUE);
2496 }
2497
2498 static void
2499 do_rename_link(int argc, char *argv[], const char *use)
2500 {
2501 int option;
2502 char *link1, *link2;
2503 char *altroot = NULL;
2504 dladm_status_t status;
2505 char *zonename = NULL;
2506
2507 opterr = 0;
2508 while ((option = getopt_long(argc, argv, ":R:z:", lopts, NULL)) != -1) {
2509 switch (option) {
2510 case 'R':
2511 altroot = optarg;
2512 break;
2513 case 'z':
2514 zonename = optarg;
2515 break;
2516 default:
2517 die_opterr(optopt, option, use);
2518 break;
2519 }
2520 }
2521
2522 /* get link1 and link2 name (required the last 2 arguments) */
2523 if (optind != (argc - 2))
2524 usage();
2525
2526 if (altroot != NULL)
2527 altroot_cmd(altroot, argc, argv);
2528
2529 link1 = argv[optind++];
2530 link2 = argv[optind];
2531 if ((status = dladm_rename_link(handle, zonename, link1, link2)) !=
2532 DLADM_STATUS_OK)
2533 die_dlerr(status, "rename operation failed");
2534 }
2535
2536 /*ARGSUSED*/
2537 static void
2538 do_delete_phys(int argc, char *argv[], const char *use)
2539 {
2540 datalink_id_t linkid = DATALINK_ALL_LINKID;
2541 dladm_status_t status;
2542
2543 /* get link name (required the last argument) */
2544 if (argc > 2)
2545 usage();
2546
2547 if (argc == 2) {
2548 if ((status = dladm_name2info(handle, argv[1], &linkid, NULL,
2549 NULL, NULL)) != DLADM_STATUS_OK)
2550 die_dlerr(status, "cannot delete '%s'", argv[1]);
2551 }
3401 int option;
3402 boolean_t s_arg = B_FALSE;
3403 boolean_t S_arg = B_FALSE;
3404 boolean_t i_arg = B_FALSE;
3405 uint32_t flags = DLADM_OPT_ACTIVE;
3406 boolean_t p_arg = B_FALSE;
3407 datalink_id_t linkid = DATALINK_ALL_LINKID;
3408 char linkname[MAXLINKNAMELEN];
3409 uint32_t interval = 0;
3410 show_state_t state;
3411 dladm_status_t status;
3412 boolean_t o_arg = B_FALSE;
3413 char *fields_str = NULL;
3414 char *all_active_fields = "link,class,mtu,state,bridge,over";
3415 char *all_inactive_fields = "link,class,bridge,over";
3416 char *allstat_fields =
3417 "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors";
3418 ofmt_handle_t ofmt;
3419 ofmt_status_t oferr;
3420 uint_t ofmtflags = 0;
3421 char *zonename = NULL;
3422
3423 bzero(&state, sizeof (state));
3424
3425 opterr = 0;
3426 while ((option = getopt_long(argc, argv, ":pPsSi:o:z:",
3427 show_lopts, NULL)) != -1) {
3428 switch (option) {
3429 case 'p':
3430 if (p_arg)
3431 die_optdup(option);
3432
3433 p_arg = B_TRUE;
3434 break;
3435 case 's':
3436 if (s_arg)
3437 die_optdup(option);
3438
3439 s_arg = B_TRUE;
3440 break;
3441 case 'P':
3442 if (flags != DLADM_OPT_ACTIVE)
3443 die_optdup(option);
3444
3445 flags = DLADM_OPT_PERSIST;
3446 break;
3447 case 'S':
3448 if (S_arg)
3449 die_optdup(option);
3450
3451 S_arg = B_TRUE;
3452 break;
3453 case 'o':
3454 o_arg = B_TRUE;
3455 fields_str = optarg;
3456 break;
3457 case 'i':
3458 if (i_arg)
3459 die_optdup(option);
3460
3461 i_arg = B_TRUE;
3462 if (!dladm_str2interval(optarg, &interval))
3463 die("invalid interval value '%s'", optarg);
3464 break;
3465 case 'z':
3466 zonename = optarg;
3467 break;
3468 default:
3469 die_opterr(optopt, option, use);
3470 break;
3471 }
3472 }
3473
3474 if (i_arg && !(s_arg || S_arg))
3475 die("the option -i can be used only with -s or -S");
3476
3477 if (s_arg && S_arg)
3478 die("the -s option cannot be used with -S");
3479
3480 if (s_arg && flags != DLADM_OPT_ACTIVE)
3481 die("the option -P cannot be used with -s");
3482
3483 if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE))
3484 die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P');
3485
3486 /* get link name (optional last argument) */
3487 if (optind == (argc-1)) {
3488 uint32_t f;
3489
3490 if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) >=
3491 MAXLINKNAMELEN)
3492 die("link name too long");
3493 if ((status = dladm_zname2info(handle, zonename, linkname,
3494 &linkid, &f, NULL, NULL)) != DLADM_STATUS_OK) {
3495 die_dlerr(status, "link %s is not valid", linkname);
3496 }
3497
3498 if (!(f & flags)) {
3499 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s",
3500 argv[optind], flags == DLADM_OPT_PERSIST ?
3501 "a temporary link" : "temporarily removed");
3502 }
3503 } else if (optind != argc) {
3504 usage();
3505 }
3506
3507 if (p_arg && !o_arg)
3508 die("-p requires -o");
3509
3510 if (S_arg) {
3511 dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT);
3512 return;
3513 }
3514
4739 die("invalid VLAN identifier '%s'", optarg);
4740
4741 break;
4742 case 'f':
4743 flags |= DLADM_OPT_FORCE;
4744 break;
4745 default:
4746 die_opterr(optopt, option, use);
4747 }
4748 }
4749
4750 if (mac_addr_type == VNIC_MAC_ADDR_TYPE_UNKNOWN)
4751 mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO;
4752
4753 /*
4754 * 'f' - force, flag can be specified only with 'v' - vlan.
4755 */
4756 if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0)
4757 die("-f option can only be used with -v");
4758
4759 /*
4760 * If creating a transient VNIC for a zone, mark it in the kernel.
4761 */
4762 if (strstr(propstr, "zone=") != NULL && !(flags & DLADM_OPT_PERSIST))
4763 flags |= DLADM_OPT_TRANSIENT;
4764
4765 if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM &&
4766 mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED)
4767 usage();
4768
4769 if (mac_addr_type == VNIC_MAC_ADDR_TYPE_VRID) {
4770 if (vrid == VRRP_VRID_NONE || af == AF_UNSPEC ||
4771 mac_addr != NULL || maclen != 0 || mac_slot != -1 ||
4772 mac_prefix_len != 0) {
4773 usage();
4774 }
4775 } else if ((af != AF_UNSPEC || vrid != VRRP_VRID_NONE)) {
4776 usage();
4777 }
4778
4779 /* check required options */
4780 if (!l_arg)
4781 usage();
4782
4783 if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY)
4784 usage();
4836 * Let the delete continue anyway.
4837 */
4838 return;
4839 }
4840 is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID);
4841 if (is_etherstub != etherstub) {
4842 die("'%s' is not %s", name,
4843 (is_etherstub ? "a vnic" : "an etherstub"));
4844 }
4845 }
4846
4847 static void
4848 do_delete_vnic_common(int argc, char *argv[], const char *use,
4849 boolean_t etherstub)
4850 {
4851 int option;
4852 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4853 datalink_id_t linkid;
4854 char *altroot = NULL;
4855 dladm_status_t status;
4856 char *zonename = NULL;
4857
4858 opterr = 0;
4859 while ((option = getopt_long(argc, argv, ":R:tz:", lopts,
4860 NULL)) != -1) {
4861 switch (option) {
4862 case 't':
4863 flags &= ~DLADM_OPT_PERSIST;
4864 break;
4865 case 'R':
4866 altroot = optarg;
4867 break;
4868 case 'z':
4869 zonename = optarg;
4870 break;
4871 default:
4872 die_opterr(optopt, option, use);
4873 }
4874 }
4875
4876 /* get vnic name (required last argument) */
4877 if (optind != (argc - 1))
4878 usage();
4879
4880 if (altroot != NULL)
4881 altroot_cmd(altroot, argc, argv);
4882
4883 status = dladm_zname2info(handle, zonename, argv[optind], &linkid, NULL,
4884 NULL, NULL);
4885 if (status != DLADM_STATUS_OK)
4886 die("invalid link name '%s'", argv[optind]);
4887
4888 if ((flags & DLADM_OPT_ACTIVE) != 0) {
4889 do_etherstub_check(argv[optind], linkid, etherstub,
4890 DLADM_OPT_ACTIVE);
4891 }
4892 if ((flags & DLADM_OPT_PERSIST) != 0) {
4893 do_etherstub_check(argv[optind], linkid, etherstub,
4894 DLADM_OPT_PERSIST);
4895 }
4896
4897 status = dladm_vnic_delete(handle, linkid, flags);
4898 if (status != DLADM_STATUS_OK)
4899 die_dlerr(status, "vnic deletion failed");
4900 }
4901
4902 static void
4903 do_delete_vnic(int argc, char *argv[], const char *use)
4904 {
4996 }
4997 (void) printf("\n");
4998
4999 *old_stats = *vnic_stats;
5000 }
5001
5002 /*
5003 * Called from the walker dladm_vnic_walk_sys() for each vnic to display
5004 * vnic information or statistics.
5005 */
5006 static dladm_status_t
5007 print_vnic(show_vnic_state_t *state, datalink_id_t linkid)
5008 {
5009 dladm_vnic_attr_t attr, *vnic = &attr;
5010 dladm_status_t status;
5011 boolean_t is_etherstub;
5012 char devname[MAXLINKNAMELEN];
5013 char vnic_name[MAXLINKNAMELEN];
5014 char mstr[MAXMACADDRLEN * 3];
5015 vnic_fields_buf_t vbuf;
5016 uint_t valcnt = 1;
5017 char zonename[DLADM_PROP_VAL_MAX + 1];
5018 char *valptr[1];
5019
5020 if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) !=
5021 DLADM_STATUS_OK)
5022 return (status);
5023
5024 is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID);
5025 if (state->vs_etherstub != is_etherstub) {
5026 /*
5027 * Want all etherstub but it's not one, or want
5028 * non-etherstub and it's one.
5029 */
5030 return (DLADM_STATUS_OK);
5031 }
5032
5033 if (state->vs_link_id != DATALINK_ALL_LINKID) {
5034 if (state->vs_link_id != vnic->va_link_id)
5035 return (DLADM_STATUS_OK);
5036 }
5037
5038 if (dladm_datalink_id2info(handle, linkid, NULL, NULL,
5039 NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK)
5040 return (DLADM_STATUS_BADARG);
5041
5042 bzero(devname, sizeof (devname));
5043 if (!is_etherstub &&
5044 dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL,
5045 NULL, devname, sizeof (devname)) != DLADM_STATUS_OK)
5046 (void) sprintf(devname, "?");
5047
5048
5049 zonename[0] = '\0';
5050 if (!is_etherstub) {
5051 valptr[0] = zonename;
5052 (void) dladm_get_linkprop(handle, linkid,
5053 DLADM_PROP_VAL_CURRENT, "zone", (char **)valptr, &valcnt);
5054 }
5055
5056 if (state->vs_zonename != NULL &&
5057 strcmp(state->vs_zonename, zonename) != 0)
5058 return (DLADM_STATUS_OK);
5059
5060 state->vs_found = B_TRUE;
5061 if (state->vs_stats) {
5062 /* print vnic statistics */
5063 pktsum_t vnic_stats;
5064
5065 if (state->vs_firstonly) {
5066 if (state->vs_donefirst)
5067 return (0);
5068 state->vs_donefirst = B_TRUE;
5069 }
5070
5071 if (!state->vs_printstats) {
5072 /*
5073 * get vnic statistics and add to the sum for the
5074 * named device.
5075 */
5076 get_link_stats(vnic_name, &vnic_stats);
5077 dladm_stats_total(&state->vs_totalstats, &vnic_stats,
5078 &state->vs_prevstats[vnic->va_vnic_id]);
5079 } else {
5115 vnic->va_mac_slot);
5116 break;
5117 case VNIC_MAC_ADDR_TYPE_VRID:
5118 (void) snprintf(vbuf.vnic_macaddrtype,
5119 sizeof (vbuf.vnic_macaddrtype),
5120 gettext("vrrp, %d/%s"),
5121 vnic->va_vrid, vnic->va_af == AF_INET ?
5122 "inet" : "inet6");
5123 break;
5124 }
5125
5126 if (strlen(vbuf.vnic_macaddrtype) > 0) {
5127 (void) snprintf(vbuf.vnic_macaddr,
5128 sizeof (vbuf.vnic_macaddr), "%s",
5129 dladm_aggr_macaddr2str(vnic->va_mac_addr,
5130 mstr));
5131 }
5132
5133 (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid),
5134 "%d", vnic->va_vid);
5135
5136 if (zonename[0] != '\0')
5137 (void) snprintf(vbuf.vnic_zone,
5138 sizeof (vbuf.vnic_zone), "%s", zonename);
5139 else
5140 (void) strlcpy(vbuf.vnic_zone, "--",
5141 sizeof (vbuf.vnic_zone));
5142 }
5143
5144 ofmt_print(state->vs_ofmt, &vbuf);
5145
5146 return (DLADM_STATUS_OK);
5147 }
5148 }
5149
5150 /* ARGSUSED */
5151 static int
5152 show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg)
5153 {
5154 show_vnic_state_t *state = arg;
5155
5156 state->vs_status = print_vnic(state, linkid);
5157 return (DLADM_WALK_CONTINUE);
5158 }
5159
5160 static void
5161 do_show_vnic_common(int argc, char *argv[], const char *use,
5162 boolean_t etherstub)
5163 {
5164 int option;
5165 boolean_t s_arg = B_FALSE;
5166 boolean_t i_arg = B_FALSE;
5167 boolean_t l_arg = B_FALSE;
5168 uint32_t interval = 0, flags = DLADM_OPT_ACTIVE;
5169 datalink_id_t linkid = DATALINK_ALL_LINKID;
5170 datalink_id_t dev_linkid = DATALINK_ALL_LINKID;
5171 show_vnic_state_t state;
5172 dladm_status_t status;
5173 boolean_t o_arg = B_FALSE;
5174 char *fields_str = NULL;
5175 const ofmt_field_t *pf;
5176 char *all_e_fields = "link";
5177 ofmt_handle_t ofmt;
5178 ofmt_status_t oferr;
5179 uint_t ofmtflags = 0;
5180 char *zonename = NULL;
5181
5182 bzero(&state, sizeof (state));
5183 opterr = 0;
5184 while ((option = getopt_long(argc, argv, ":pPl:si:o:z:", lopts,
5185 NULL)) != -1) {
5186 switch (option) {
5187 case 'p':
5188 state.vs_parsable = B_TRUE;
5189 break;
5190 case 'P':
5191 flags = DLADM_OPT_PERSIST;
5192 break;
5193 case 'l':
5194 if (etherstub)
5195 die("option not supported for this command");
5196
5197 if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >=
5198 MAXLINKNAMELEN)
5199 die("link name too long");
5200
5201 l_arg = B_TRUE;
5202 break;
5203 case 's':
5204 if (s_arg) {
5205 die("the option -s cannot be specified "
5206 "more than once");
5207 }
5208 s_arg = B_TRUE;
5209 break;
5210 case 'i':
5211 if (i_arg) {
5212 die("the option -i cannot be specified "
5213 "more than once");
5214 }
5215 i_arg = B_TRUE;
5216 if (!dladm_str2interval(optarg, &interval))
5217 die("invalid interval value '%s'", optarg);
5218 break;
5219 case 'o':
5220 o_arg = B_TRUE;
5221 fields_str = optarg;
5222 break;
5223 case 'z':
5224 zonename = optarg;
5225 break;
5226 default:
5227 die_opterr(optopt, option, use);
5228 }
5229 }
5230
5231 if (i_arg && !s_arg)
5232 die("the option -i can be used only with -s");
5233
5234 /* get vnic ID (optional last argument) */
5235 if (optind == (argc - 1)) {
5236 status = dladm_zname2info(handle, zonename, argv[optind],
5237 &linkid, NULL, NULL, NULL);
5238 if (status != DLADM_STATUS_OK) {
5239 die_dlerr(status, "invalid vnic name '%s'",
5240 argv[optind]);
5241 }
5242 (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN);
5243 } else if (optind != argc) {
5244 usage();
5245 }
5246
5247 if (l_arg) {
5248 status = dladm_zname2info(handle, zonename, state.vs_link,
5249 &dev_linkid, NULL, NULL, NULL);
5250 if (status != DLADM_STATUS_OK) {
5251 die_dlerr(status, "invalid link name '%s'",
5252 state.vs_link);
5253 }
5254 }
5255
5256 state.vs_vnic_id = linkid;
5257 state.vs_link_id = dev_linkid;
5258 state.vs_etherstub = etherstub;
5259 state.vs_found = B_FALSE;
5260 state.vs_flags = flags;
5261 state.vs_zonename = zonename;
5262
5263 if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
5264 if (etherstub)
5265 fields_str = all_e_fields;
5266 }
5267 pf = vnic_fields;
5268
5269 if (state.vs_parsable)
5270 ofmtflags |= OFMT_PARSABLE;
5271 oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
5272 dladm_ofmt_check(oferr, state.vs_parsable, ofmt);
5273 state.vs_ofmt = ofmt;
5274
5275 if (s_arg) {
5276 /* Display vnic statistics */
5277 vnic_stats(&state, interval);
5278 ofmt_close(ofmt);
5279 return;
5280 }
5281
6730
6731 ofmt_print(statep->ls_ofmt, &ls_arg);
6732
6733 return (DLADM_WALK_CONTINUE);
6734 }
6735
6736 static void
6737 do_show_linkprop(int argc, char **argv, const char *use)
6738 {
6739 int option;
6740 char propstr[DLADM_STRSIZE];
6741 dladm_arg_list_t *proplist = NULL;
6742 datalink_id_t linkid = DATALINK_ALL_LINKID;
6743 show_linkprop_state_t state;
6744 uint32_t flags = DLADM_OPT_ACTIVE;
6745 dladm_status_t status;
6746 char *fields_str = NULL;
6747 ofmt_handle_t ofmt;
6748 ofmt_status_t oferr;
6749 uint_t ofmtflags = 0;
6750 char *zonename = NULL;
6751
6752 bzero(propstr, DLADM_STRSIZE);
6753 opterr = 0;
6754 state.ls_propvals = NULL;
6755 state.ls_line = NULL;
6756 state.ls_parsable = B_FALSE;
6757 state.ls_persist = B_FALSE;
6758 state.ls_header = B_TRUE;
6759 state.ls_retstatus = DLADM_STATUS_OK;
6760
6761 while ((option = getopt_long(argc, argv, ":p:cPo:z:",
6762 prop_longopts, NULL)) != -1) {
6763 switch (option) {
6764 case 'p':
6765 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
6766 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
6767 DLADM_STRSIZE)
6768 die("property list too long '%s'", propstr);
6769 break;
6770 case 'c':
6771 state.ls_parsable = B_TRUE;
6772 break;
6773 case 'P':
6774 state.ls_persist = B_TRUE;
6775 flags = DLADM_OPT_PERSIST;
6776 break;
6777 case 'o':
6778 fields_str = optarg;
6779 break;
6780 case 'z':
6781 zonename = optarg;
6782 break;
6783 default:
6784 die_opterr(optopt, option, use);
6785 break;
6786 }
6787 }
6788
6789 if (optind == (argc - 1)) {
6790 if ((status = dladm_zname2info(handle, zonename, argv[optind],
6791 &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6792 die_dlerr(status, "link %s is not valid", argv[optind]);
6793 }
6794 } else if (optind != argc) {
6795 usage();
6796 }
6797
6798 if (dladm_parse_link_props(propstr, &proplist, B_TRUE)
6799 != DLADM_STATUS_OK)
6800 die("invalid link properties specified");
6801 state.ls_proplist = proplist;
6802 state.ls_zonename = zonename;
6803 state.ls_status = DLADM_STATUS_OK;
6804
6805 if (state.ls_parsable)
6806 ofmtflags |= OFMT_PARSABLE;
6807 else
6808 ofmtflags |= OFMT_WRAP;
6809
6810 oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt);
6811 dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
6812 state.ls_ofmt = ofmt;
6813
6814 if (linkid == DATALINK_ALL_LINKID) {
6815 (void) dladm_walk_datalink_id(show_linkprop_onelink, handle,
6816 &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
6817 } else {
6818 (void) show_linkprop_onelink(handle, linkid, &state);
6819 }
6820 ofmt_close(ofmt);
6821 dladm_free_props(proplist);
6822
6827 }
6828
6829 static int
6830 show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
6831 {
6832 int i;
6833 char *buf;
6834 uint32_t flags;
6835 dladm_arg_list_t *proplist = NULL;
6836 show_linkprop_state_t *statep = arg;
6837 dlpi_handle_t dh = NULL;
6838
6839 statep->ls_status = DLADM_STATUS_OK;
6840
6841 if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL,
6842 statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) {
6843 statep->ls_status = DLADM_STATUS_NOTFOUND;
6844 return (DLADM_WALK_CONTINUE);
6845 }
6846
6847 if (statep->ls_zonename != NULL) {
6848 datalink_id_t tlinkid;
6849
6850 if (dladm_zname2info(hdl, statep->ls_zonename, statep->ls_link,
6851 &tlinkid, NULL, NULL, NULL) != DLADM_STATUS_OK ||
6852 linkid != tlinkid) {
6853 statep->ls_status = DLADM_STATUS_NOTFOUND;
6854 return (DLADM_WALK_CONTINUE);
6855 }
6856 }
6857
6858 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) ||
6859 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) {
6860 statep->ls_status = DLADM_STATUS_BADARG;
6861 return (DLADM_WALK_CONTINUE);
6862 }
6863
6864 proplist = statep->ls_proplist;
6865
6866 /*
6867 * When some WiFi links are opened for the first time, their hardware
6868 * automatically scans for APs and does other slow operations. Thus,
6869 * if there are no open links, the retrieval of link properties
6870 * (below) will proceed slowly unless we hold the link open.
6871 *
6872 * Note that failure of dlpi_open() does not necessarily mean invalid
6873 * link properties, because dlpi_open() may fail because of incorrect
6874 * autopush configuration. Therefore, we ingore the return value of
6875 * dlpi_open().
6876 */
6877 if (!statep->ls_persist)
6920 status != DLADM_STATUS_NOTSUP) {
6921 warn_dlerr(status, "cannot reset link property '%s' on '%s'",
6922 propname, statep->ls_name);
6923 statep->ls_status = status;
6924 }
6925
6926 return (DLADM_WALK_CONTINUE);
6927 }
6928
6929 static void
6930 set_linkprop(int argc, char **argv, boolean_t reset, const char *use)
6931 {
6932 int i, option;
6933 char errmsg[DLADM_STRSIZE];
6934 char *altroot = NULL;
6935 datalink_id_t linkid;
6936 boolean_t temp = B_FALSE;
6937 dladm_status_t status = DLADM_STATUS_OK;
6938 char propstr[DLADM_STRSIZE];
6939 dladm_arg_list_t *proplist = NULL;
6940 char *zonename = NULL;
6941
6942 opterr = 0;
6943 bzero(propstr, DLADM_STRSIZE);
6944
6945 while ((option = getopt_long(argc, argv, ":p:R:tz:",
6946 prop_longopts, NULL)) != -1) {
6947 switch (option) {
6948 case 'p':
6949 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
6950 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
6951 DLADM_STRSIZE)
6952 die("property list too long '%s'", propstr);
6953 break;
6954 case 't':
6955 temp = B_TRUE;
6956 break;
6957 case 'R':
6958 altroot = optarg;
6959 break;
6960 case 'z':
6961 zonename = optarg;
6962 break;
6963 default:
6964 die_opterr(optopt, option, use);
6965
6966 }
6967 }
6968
6969 /* get link name (required last argument) */
6970 if (optind != (argc - 1))
6971 usage();
6972
6973 if (dladm_parse_link_props(propstr, &proplist, reset) !=
6974 DLADM_STATUS_OK)
6975 die("invalid link properties specified");
6976
6977 if (proplist == NULL && !reset)
6978 die("link property must be specified");
6979
6980 if (altroot != NULL) {
6981 dladm_free_props(proplist);
6982 altroot_cmd(altroot, argc, argv);
6983 }
6984
6985 status = dladm_zname2info(handle, zonename, argv[optind], &linkid,
6986 NULL, NULL, NULL);
6987 if (status != DLADM_STATUS_OK)
6988 die_dlerr(status, "link %s is not valid", argv[optind]);
6989
6990 if (proplist == NULL) {
6991 set_linkprop_state_t state;
6992
6993 state.ls_name = argv[optind];
6994 state.ls_reset = reset;
6995 state.ls_temp = temp;
6996 state.ls_status = DLADM_STATUS_OK;
6997
6998 (void) dladm_walk_linkprop(handle, linkid, &state,
6999 reset_one_linkprop);
7000
7001 status = state.ls_status;
7002 goto done;
7003 }
7004
7005 for (i = 0; i < proplist->al_count; i++) {
7006 dladm_arg_info_t *aip = &proplist->al_info[i];
|