Print this page
OS-792 dladm show-linkprop -z zonename doesn't restrict output to that zone, unless you also specify the vnic name
OS-406
OS-249
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/dladm/dladm.c
+++ new/usr/src/cmd/dladm/dladm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 + * Copyright (c) 2012 Joyent, Inc. All rights reserved.
23 24 */
24 25
25 26 #include <stdio.h>
26 27 #include <ctype.h>
27 28 #include <dlfcn.h>
28 29 #include <locale.h>
29 30 #include <signal.h>
30 31 #include <stdarg.h>
31 32 #include <stdlib.h>
32 33 #include <fcntl.h>
33 34 #include <string.h>
34 35 #include <stropts.h>
35 36 #include <sys/stat.h>
36 37 #include <errno.h>
37 38 #include <kstat.h>
38 39 #include <strings.h>
39 40 #include <getopt.h>
40 41 #include <unistd.h>
41 42 #include <priv.h>
42 43 #include <limits.h>
43 44 #include <termios.h>
44 45 #include <pwd.h>
45 46 #include <auth_attr.h>
46 47 #include <auth_list.h>
47 48 #include <libintl.h>
48 49 #include <libdevinfo.h>
49 50 #include <libdlpi.h>
50 51 #include <libdladm.h>
51 52 #include <libdllink.h>
52 53 #include <libdlstat.h>
53 54 #include <libdlaggr.h>
54 55 #include <libdlwlan.h>
55 56 #include <libdlvlan.h>
56 57 #include <libdlvnic.h>
57 58 #include <libdlib.h>
58 59 #include <libdlether.h>
59 60 #include <libdliptun.h>
60 61 #include <libdlsim.h>
61 62 #include <libdlbridge.h>
62 63 #include <libinetutil.h>
63 64 #include <libvrrpadm.h>
64 65 #include <bsm/adt.h>
65 66 #include <bsm/adt_event.h>
66 67 #include <libdlvnic.h>
67 68 #include <sys/types.h>
68 69 #include <sys/socket.h>
69 70 #include <sys/ib/ib_types.h>
70 71 #include <sys/processor.h>
71 72 #include <netinet/in.h>
72 73 #include <arpa/inet.h>
73 74 #include <net/if_types.h>
74 75 #include <stddef.h>
75 76 #include <stp_in.h>
76 77 #include <ofmt.h>
77 78
78 79 #define MAXPORT 256
79 80 #define MAXVNIC 256
80 81 #define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0)
81 82 #define MAXLINELEN 1024
82 83 #define SMF_UPGRADE_FILE "/var/svc/profile/upgrade"
83 84 #define SMF_UPGRADEDATALINK_FILE "/var/svc/profile/upgrade_datalink"
84 85 #define SMF_DLADM_UPGRADE_MSG " # added by dladm(1M)"
85 86 #define DLADM_DEFAULT_COL 80
86 87
87 88 /*
88 89 * used by the wifi show-* commands to set up ofmt_field_t structures.
89 90 */
90 91 #define WIFI_CMD_SCAN 0x00000001
91 92 #define WIFI_CMD_SHOW 0x00000002
92 93 #define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW)
93 94
94 95 /* No larger than pktsum_t */
95 96 typedef struct brsum_s {
96 97 uint64_t drops;
97 98 uint64_t forward_dir;
98 99 uint64_t forward_mb;
99 100 uint64_t forward_unk;
100 101 uint64_t recv;
101 102 uint64_t sent;
102 103 } brsum_t;
103 104
104 105 /* No larger than pktsum_t */
105 106 typedef struct brlsum_s {
106 107 uint32_t cfgbpdu;
107 108 uint32_t tcnbpdu;
108 109 uint32_t rstpbpdu;
109 110 uint32_t txbpdu;
110 111 uint64_t drops;
111 112 uint64_t recv;
112 113 uint64_t xmit;
113 114 } brlsum_t;
114 115
115 116 typedef struct show_state {
116 117 boolean_t ls_firstonly;
117 118 boolean_t ls_donefirst;
118 119 pktsum_t ls_prevstats;
119 120 uint32_t ls_flags;
120 121 dladm_status_t ls_status;
121 122 ofmt_handle_t ls_ofmt;
122 123 boolean_t ls_parsable;
123 124 boolean_t ls_mac;
124 125 boolean_t ls_hwgrp;
125 126 } show_state_t;
126 127
127 128 typedef struct show_grp_state {
128 129 pktsum_t gs_prevstats[MAXPORT];
129 130 uint32_t gs_flags;
130 131 dladm_status_t gs_status;
131 132 boolean_t gs_parsable;
132 133 boolean_t gs_lacp;
133 134 boolean_t gs_extended;
134 135 boolean_t gs_stats;
135 136 boolean_t gs_firstonly;
136 137 boolean_t gs_donefirst;
137 138 ofmt_handle_t gs_ofmt;
138 139 } show_grp_state_t;
139 140
140 141 typedef struct show_vnic_state {
141 142 datalink_id_t vs_vnic_id;
142 143 datalink_id_t vs_link_id;
143 144 char vs_vnic[MAXLINKNAMELEN];
144 145 char vs_link[MAXLINKNAMELEN];
145 146 boolean_t vs_parsable;
146 147 boolean_t vs_found;
|
↓ open down ↓ |
114 lines elided |
↑ open up ↑ |
147 148 boolean_t vs_firstonly;
148 149 boolean_t vs_donefirst;
149 150 boolean_t vs_stats;
150 151 boolean_t vs_printstats;
151 152 pktsum_t vs_totalstats;
152 153 pktsum_t vs_prevstats[MAXVNIC];
153 154 boolean_t vs_etherstub;
154 155 dladm_status_t vs_status;
155 156 uint32_t vs_flags;
156 157 ofmt_handle_t vs_ofmt;
158 + char *vs_zonename;
157 159 } show_vnic_state_t;
158 160
159 161 typedef struct show_part_state {
160 162 datalink_id_t ps_over_id;
161 163 char ps_part[MAXLINKNAMELEN];
162 164 boolean_t ps_parsable;
163 165 boolean_t ps_found;
164 166 dladm_status_t ps_status;
165 167 uint32_t ps_flags;
166 168 ofmt_handle_t ps_ofmt;
167 169 } show_part_state_t;
168 170
169 171 typedef struct show_ib_state {
170 172 datalink_id_t is_link_id;
171 173 char is_link[MAXLINKNAMELEN];
172 174 boolean_t is_parsable;
173 175 dladm_status_t is_status;
174 176 uint32_t is_flags;
175 177 ofmt_handle_t is_ofmt;
176 178 } show_ib_state_t;
177 179
178 180 typedef struct show_usage_state_s {
179 181 boolean_t us_plot;
180 182 boolean_t us_parsable;
181 183 boolean_t us_printheader;
182 184 boolean_t us_first;
183 185 boolean_t us_showall;
184 186 ofmt_handle_t us_ofmt;
185 187 } show_usage_state_t;
186 188
187 189 /*
188 190 * callback functions for printing output and error diagnostics.
189 191 */
190 192 static ofmt_cb_t print_default_cb, print_link_stats_cb, print_linkprop_cb;
191 193 static ofmt_cb_t print_lacp_cb, print_phys_one_mac_cb;
192 194 static ofmt_cb_t print_xaggr_cb, print_aggr_stats_cb;
193 195 static ofmt_cb_t print_phys_one_hwgrp_cb, print_wlan_attr_cb;
194 196 static ofmt_cb_t print_wifi_status_cb, print_link_attr_cb;
195 197 static void dladm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
196 198
197 199 typedef void cmdfunc_t(int, char **, const char *);
198 200
199 201 static cmdfunc_t do_show_link, do_show_wifi, do_show_phys;
200 202 static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr;
201 203 static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr;
202 204 static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi;
203 205 static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop;
204 206 static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj;
205 207 static cmdfunc_t do_init_linkprop, do_init_secobj;
206 208 static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan;
207 209 static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys;
208 210 static cmdfunc_t do_show_linkmap;
209 211 static cmdfunc_t do_show_ether;
210 212 static cmdfunc_t do_create_vnic, do_delete_vnic, do_show_vnic;
211 213 static cmdfunc_t do_up_vnic;
212 214 static cmdfunc_t do_create_part, do_delete_part, do_show_part, do_show_ib;
213 215 static cmdfunc_t do_up_part;
214 216 static cmdfunc_t do_create_etherstub, do_delete_etherstub, do_show_etherstub;
215 217 static cmdfunc_t do_create_simnet, do_modify_simnet;
216 218 static cmdfunc_t do_delete_simnet, do_show_simnet, do_up_simnet;
217 219 static cmdfunc_t do_show_usage;
218 220 static cmdfunc_t do_create_bridge, do_modify_bridge, do_delete_bridge;
219 221 static cmdfunc_t do_add_bridge, do_remove_bridge, do_show_bridge;
220 222 static cmdfunc_t do_create_iptun, do_modify_iptun, do_delete_iptun;
221 223 static cmdfunc_t do_show_iptun, do_up_iptun, do_down_iptun;
222 224
223 225 static void do_up_vnic_common(int, char **, const char *, boolean_t);
224 226
225 227 static int show_part(dladm_handle_t, datalink_id_t, void *);
226 228
227 229 static void altroot_cmd(char *, int, char **);
228 230 static int show_linkprop_onelink(dladm_handle_t, datalink_id_t, void *);
229 231
230 232 static void link_stats(datalink_id_t, uint_t, char *, show_state_t *);
231 233 static void aggr_stats(datalink_id_t, show_grp_state_t *, uint_t);
232 234 static void vnic_stats(show_vnic_state_t *, uint32_t);
233 235
234 236 static int get_one_kstat(const char *, const char *, uint8_t,
235 237 void *, boolean_t);
236 238 static void get_mac_stats(const char *, pktsum_t *);
237 239 static void get_link_stats(const char *, pktsum_t *);
238 240 static uint64_t get_ifspeed(const char *, boolean_t);
239 241 static const char *get_linkstate(const char *, boolean_t, char *);
240 242 static const char *get_linkduplex(const char *, boolean_t, char *);
241 243
242 244 static iptun_type_t iptun_gettypebyname(char *);
243 245 static const char *iptun_gettypebyvalue(iptun_type_t);
244 246 static dladm_status_t print_iptun(dladm_handle_t, datalink_id_t,
245 247 show_state_t *);
246 248 static int print_iptun_walker(dladm_handle_t, datalink_id_t, void *);
247 249
248 250 static int show_etherprop(dladm_handle_t, datalink_id_t, void *);
249 251 static void show_ether_xprop(void *, dladm_ether_info_t *);
250 252 static boolean_t link_is_ether(const char *, datalink_id_t *);
251 253
252 254 static boolean_t str2int(const char *, int *);
253 255 static void die(const char *, ...);
254 256 static void die_optdup(int);
255 257 static void die_opterr(int, int, const char *);
256 258 static void die_dlerr(dladm_status_t, const char *, ...);
257 259 static void warn(const char *, ...);
|
↓ open down ↓ |
91 lines elided |
↑ open up ↑ |
258 260 static void warn_dlerr(dladm_status_t, const char *, ...);
259 261
260 262 typedef struct cmd {
261 263 char *c_name;
262 264 cmdfunc_t *c_fn;
263 265 const char *c_usage;
264 266 } cmd_t;
265 267
266 268 static cmd_t cmds[] = {
267 269 { "rename-link", do_rename_link,
268 - " rename-link <oldlink> <newlink>" },
270 + " rename-link [-z zonename] <oldlink> <newlink>" },
269 271 { "show-link", do_show_link,
270 272 " show-link [-pP] [-o <field>,..] [-s [-i <interval>]] "
271 273 "[<link>]\n" },
272 274 { "create-aggr", do_create_aggr,
273 275 " create-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] "
274 276 "[-u <address>]\n"
275 277 "\t\t -l <link> [-l <link>...] <link>" },
276 278 { "delete-aggr", do_delete_aggr,
277 279 " delete-aggr [-t] <link>" },
278 280 { "add-aggr", do_add_aggr,
279 281 " add-aggr [-t] -l <link> [-l <link>...] <link>" },
280 282 { "remove-aggr", do_remove_aggr,
281 283 " remove-aggr [-t] -l <link> [-l <link>...] <link>" },
282 284 { "modify-aggr", do_modify_aggr,
283 285 " modify-aggr [-t] [-P <policy>] [-L <mode>] [-T <time>] "
284 286 "[-u <address>]\n"
285 287 "\t\t <link>" },
286 288 { "show-aggr", do_show_aggr,
287 289 " show-aggr [-pPLx] [-o <field>,..] [-s [-i <interval>]] "
288 290 "[<link>]\n" },
289 291 { "up-aggr", do_up_aggr, NULL },
290 292 { "scan-wifi", do_scan_wifi,
291 293 " scan-wifi [-p] [-o <field>,...] [<link>]" },
292 294 { "connect-wifi", do_connect_wifi,
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
293 295 " connect-wifi [-e <essid>] [-i <bssid>] [-k <key>,...] "
294 296 "[-s wep|wpa]\n"
295 297 "\t\t [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g] "
296 298 "[-T <time>]\n"
297 299 "\t\t [<link>]" },
298 300 { "disconnect-wifi", do_disconnect_wifi,
299 301 " disconnect-wifi [-a] [<link>]" },
300 302 { "show-wifi", do_show_wifi,
301 303 " show-wifi [-p] [-o <field>,...] [<link>]\n" },
302 304 { "set-linkprop", do_set_linkprop,
303 - " set-linkprop [-t] -p <prop>=<value>[,...] <name>" },
305 + " set-linkprop [-t] [-z zonename] -p <prop>=<value>[,...] "
306 + "<name>" },
304 307 { "reset-linkprop", do_reset_linkprop,
305 - " reset-linkprop [-t] [-p <prop>,...] <name>" },
308 + " reset-linkprop [-t] [-z zonename] [-p <prop>,...] <name>"},
306 309 { "show-linkprop", do_show_linkprop,
307 - " show-linkprop [-cP] [-o <field>,...] [-p <prop>,...] "
308 - "<name>\n" },
310 + " show-linkprop [-cP] [-o <field>,...] [-z zonename] "
311 + "[-p <prop>,...] <name>\n" },
309 312 { "show-ether", do_show_ether,
310 313 " show-ether [-px][-o <field>,...] <link>\n" },
311 314 { "create-secobj", do_create_secobj,
312 315 " create-secobj [-t] [-f <file>] -c <class> <secobj>" },
313 316 { "delete-secobj", do_delete_secobj,
314 317 " delete-secobj [-t] <secobj>[,...]" },
315 318 { "show-secobj", do_show_secobj,
316 319 " show-secobj [-pP] [-o <field>,...] [<secobj>,...]\n" },
317 320 { "init-linkprop", do_init_linkprop, NULL },
318 321 { "init-secobj", do_init_secobj, NULL },
319 322 { "create-vlan", do_create_vlan,
320 323 " create-vlan [-ft] -l <link> -v <vid> [link]" },
321 324 { "delete-vlan", do_delete_vlan,
322 325 " delete-vlan [-t] <link>" },
323 326 { "show-vlan", do_show_vlan,
324 327 " show-vlan [-pP] [-o <field>,..] [<link>]\n" },
325 328 { "up-vlan", do_up_vlan, NULL },
326 329 { "create-iptun", do_create_iptun,
327 330 " create-iptun [-t] -T <type> "
328 331 "[-a {local|remote}=<addr>,...] <link>]" },
329 332 { "delete-iptun", do_delete_iptun,
330 333 " delete-iptun [-t] <link>" },
331 334 { "modify-iptun", do_modify_iptun,
332 335 " modify-iptun [-t] -a {local|remote}=<addr>,... <link>" },
333 336 { "show-iptun", do_show_iptun,
334 337 " show-iptun [-pP] [-o <field>,..] [<link>]\n" },
335 338 { "up-iptun", do_up_iptun, NULL },
336 339 { "down-iptun", do_down_iptun, NULL },
337 340 { "delete-phys", do_delete_phys,
338 341 " delete-phys <link>" },
339 342 { "show-phys", do_show_phys,
|
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
340 343 " show-phys [-m | -H | -P] [[-p] [-o <field>[,...]] "
341 344 "[<link>]\n" },
342 345 { "init-phys", do_init_phys, NULL },
343 346 { "show-linkmap", do_show_linkmap, NULL },
344 347 { "create-vnic", do_create_vnic,
345 348 " create-vnic [-t] -l <link> [-m <value> | auto |\n"
346 349 "\t\t {factory [-n <slot-id>]} | {random [-r <prefix>]} |\n"
347 350 "\t\t {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n"
348 351 "\t\t [-p <prop>=<value>[,...]] <vnic-link>" },
349 352 { "delete-vnic", do_delete_vnic,
350 - " delete-vnic [-t] <vnic-link>" },
353 + " delete-vnic [-t] [-z zonename] <vnic-link>" },
351 354 { "show-vnic", do_show_vnic,
352 - " show-vnic [-pP] [-l <link>] [-s [-i <interval>]] "
353 - "[<link>]\n" },
355 + " show-vnic [-pP] [-l <link>] [-z zonename] "
356 + "[-s [-i <interval>]] [<link>]\n" },
354 357 { "up-vnic", do_up_vnic, NULL },
355 358 { "create-part", do_create_part,
356 359 " create-part [-t] [-f] -l <link> [-P <pkey>]\n"
357 360 "\t\t [-R <root-dir>] <part-link>" },
358 361 { "delete-part", do_delete_part,
359 362 " delete-part [-t] [-R <root-dir>] <part-link>"},
360 363 { "show-part", do_show_part,
361 364 " show-part [-pP] [-o <field>,...][-l <linkover>]\n"
362 365 "\t\t [<part-link>]" },
363 366 { "show-ib", do_show_ib,
364 367 " show-ib [-p] [-o <field>,...] [<link>]\n" },
365 368 { "up-part", do_up_part, NULL },
366 369 { "create-etherstub", do_create_etherstub,
367 370 " create-etherstub [-t] <link>" },
368 371 { "delete-etherstub", do_delete_etherstub,
369 372 " delete-etherstub [-t] <link>" },
370 373 { "show-etherstub", do_show_etherstub,
371 374 " show-etherstub [-t] [<link>]\n" },
372 375 { "create-simnet", do_create_simnet, NULL },
373 376 { "modify-simnet", do_modify_simnet, NULL },
374 377 { "delete-simnet", do_delete_simnet, NULL },
375 378 { "show-simnet", do_show_simnet, NULL },
376 379 { "up-simnet", do_up_simnet, NULL },
377 380 { "create-bridge", do_create_bridge,
378 381 " create-bridge [-R <root-dir>] [-P <protect>] "
379 382 "[-p <priority>]\n"
380 383 "\t\t [-m <max-age>] [-h <hello-time>] [-d <forward-delay>]\n"
381 384 "\t\t [-f <force-protocol>] [-l <link>]... <bridge>" },
382 385 { "modify-bridge", do_modify_bridge,
383 386 " modify-bridge [-R <root-dir>] [-P <protect>] "
384 387 "[-p <priority>]\n"
385 388 "\t\t [-m <max-age>] [-h <hello-time>] [-d <forward-delay>]\n"
386 389 "\t\t [-f <force-protocol>] <bridge>" },
387 390 { "delete-bridge", do_delete_bridge,
388 391 " delete-bridge [-R <root-dir>] <bridge>" },
389 392 { "add-bridge", do_add_bridge,
390 393 " add-bridge [-R <root-dir>] -l <link> [-l <link>]... "
391 394 "<bridge>" },
392 395 { "remove-bridge", do_remove_bridge,
393 396 " remove-bridge [-R <root-dir>] -l <link> [-l <link>]... "
394 397 "<bridge>" },
395 398 { "show-bridge", do_show_bridge,
396 399 " show-bridge [-p] [-o <field>,...] [-s [-i <interval>]] "
397 400 "[<bridge>]\n"
398 401 " show-bridge -l [-p] [-o <field>,...] [-s [-i <interval>]]"
399 402 " <bridge>\n"
400 403 " show-bridge -f [-p] [-o <field>,...] [-s [-i <interval>]]"
401 404 " <bridge>\n"
402 405 " show-bridge -t [-p] [-o <field>,...] [-s [-i <interval>]]"
403 406 " <bridge>\n" },
404 407 { "show-usage", do_show_usage,
405 408 " show-usage [-a] [-d | -F <format>] "
406 409 "[-s <DD/MM/YYYY,HH:MM:SS>]\n"
407 410 "\t\t [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]" }
408 411 };
409 412
410 413 static const struct option lopts[] = {
411 414 {"vlan-id", required_argument, 0, 'v'},
412 415 {"output", required_argument, 0, 'o'},
413 416 {"dev", required_argument, 0, 'd'},
414 417 {"policy", required_argument, 0, 'P'},
415 418 {"lacp-mode", required_argument, 0, 'L'},
416 419 {"lacp-timer", required_argument, 0, 'T'},
417 420 {"unicast", required_argument, 0, 'u'},
418 421 {"temporary", no_argument, 0, 't'},
419 422 {"root-dir", required_argument, 0, 'R'},
420 423 {"link", required_argument, 0, 'l'},
421 424 {"forcible", no_argument, 0, 'f'},
422 425 {"bw-limit", required_argument, 0, 'b'},
423 426 {"mac-address", required_argument, 0, 'm'},
424 427 {"slot", required_argument, 0, 'n'},
425 428 { 0, 0, 0, 0 }
426 429 };
427 430
428 431 static const struct option show_lopts[] = {
429 432 {"statistics", no_argument, 0, 's'},
430 433 {"continuous", no_argument, 0, 'S'},
431 434 {"interval", required_argument, 0, 'i'},
432 435 {"parsable", no_argument, 0, 'p'},
433 436 {"parseable", no_argument, 0, 'p'},
434 437 {"extended", no_argument, 0, 'x'},
435 438 {"output", required_argument, 0, 'o'},
436 439 {"persistent", no_argument, 0, 'P'},
437 440 {"lacp", no_argument, 0, 'L'},
438 441 { 0, 0, 0, 0 }
439 442 };
440 443
441 444 static const struct option iptun_lopts[] = {
442 445 {"output", required_argument, 0, 'o'},
443 446 {"tunnel-type", required_argument, 0, 'T'},
444 447 {"address", required_argument, 0, 'a'},
445 448 {"root-dir", required_argument, 0, 'R'},
446 449 {"parsable", no_argument, 0, 'p'},
447 450 {"parseable", no_argument, 0, 'p'},
448 451 {"persistent", no_argument, 0, 'P'},
449 452 { 0, 0, 0, 0 }
450 453 };
451 454
452 455 static char * const iptun_addropts[] = {
453 456 #define IPTUN_LOCAL 0
454 457 "local",
455 458 #define IPTUN_REMOTE 1
456 459 "remote",
457 460 NULL};
458 461
459 462 static const struct {
460 463 const char *type_name;
461 464 iptun_type_t type_value;
462 465 } iptun_types[] = {
463 466 {"ipv4", IPTUN_TYPE_IPV4},
464 467 {"ipv6", IPTUN_TYPE_IPV6},
465 468 {"6to4", IPTUN_TYPE_6TO4},
466 469 {NULL, 0}
467 470 };
468 471
469 472 static const struct option prop_longopts[] = {
470 473 {"temporary", no_argument, 0, 't' },
471 474 {"output", required_argument, 0, 'o' },
472 475 {"root-dir", required_argument, 0, 'R' },
473 476 {"prop", required_argument, 0, 'p' },
474 477 {"parsable", no_argument, 0, 'c' },
475 478 {"parseable", no_argument, 0, 'c' },
476 479 {"persistent", no_argument, 0, 'P' },
477 480 { 0, 0, 0, 0 }
478 481 };
479 482
480 483 static const struct option wifi_longopts[] = {
481 484 {"parsable", no_argument, 0, 'p' },
482 485 {"parseable", no_argument, 0, 'p' },
483 486 {"output", required_argument, 0, 'o' },
484 487 {"essid", required_argument, 0, 'e' },
485 488 {"bsstype", required_argument, 0, 'b' },
486 489 {"mode", required_argument, 0, 'm' },
487 490 {"key", required_argument, 0, 'k' },
488 491 {"sec", required_argument, 0, 's' },
489 492 {"auth", required_argument, 0, 'a' },
490 493 {"create-ibss", required_argument, 0, 'c' },
491 494 {"timeout", required_argument, 0, 'T' },
492 495 {"all-links", no_argument, 0, 'a' },
493 496 {"temporary", no_argument, 0, 't' },
494 497 {"root-dir", required_argument, 0, 'R' },
495 498 {"persistent", no_argument, 0, 'P' },
496 499 {"file", required_argument, 0, 'f' },
497 500 { 0, 0, 0, 0 }
498 501 };
499 502
500 503 static const struct option showeth_lopts[] = {
501 504 {"parsable", no_argument, 0, 'p' },
502 505 {"parseable", no_argument, 0, 'p' },
503 506 {"extended", no_argument, 0, 'x' },
504 507 {"output", required_argument, 0, 'o' },
505 508 { 0, 0, 0, 0 }
506 509 };
507 510
508 511 static const struct option vnic_lopts[] = {
509 512 {"temporary", no_argument, 0, 't' },
510 513 {"root-dir", required_argument, 0, 'R' },
511 514 {"dev", required_argument, 0, 'd' },
512 515 {"mac-address", required_argument, 0, 'm' },
513 516 {"cpus", required_argument, 0, 'c' },
514 517 {"bw-limit", required_argument, 0, 'b' },
515 518 {"slot", required_argument, 0, 'n' },
516 519 {"mac-prefix", required_argument, 0, 'r' },
517 520 {"vrid", required_argument, 0, 'V' },
518 521 {"address-family", required_argument, 0, 'A' },
519 522 { 0, 0, 0, 0 }
520 523 };
521 524
522 525 static const struct option part_lopts[] = {
523 526 {"temporary", no_argument, 0, 't' },
524 527 {"pkey", required_argument, 0, 'P' },
525 528 {"link", required_argument, 0, 'l' },
526 529 {"force", no_argument, 0, 'f' },
527 530 {"root-dir", required_argument, 0, 'R' },
528 531 {"prop", required_argument, 0, 'p' },
529 532 { 0, 0, 0, 0 }
530 533 };
531 534
532 535 static const struct option show_part_lopts[] = {
533 536 {"parsable", no_argument, 0, 'p' },
534 537 {"parseable", no_argument, 0, 'p' },
535 538 {"link", required_argument, 0, 'l' },
536 539 {"persistent", no_argument, 0, 'P' },
537 540 {"output", required_argument, 0, 'o' },
538 541 { 0, 0, 0, 0 }
539 542 };
540 543
541 544 static const struct option etherstub_lopts[] = {
542 545 {"temporary", no_argument, 0, 't' },
543 546 {"root-dir", required_argument, 0, 'R' },
544 547 { 0, 0, 0, 0 }
545 548 };
546 549
547 550 static const struct option usage_opts[] = {
548 551 {"file", required_argument, 0, 'f' },
549 552 {"format", required_argument, 0, 'F' },
550 553 {"start", required_argument, 0, 's' },
551 554 {"stop", required_argument, 0, 'e' },
552 555 { 0, 0, 0, 0 }
553 556 };
554 557
555 558 static const struct option simnet_lopts[] = {
556 559 {"temporary", no_argument, 0, 't' },
557 560 {"root-dir", required_argument, 0, 'R' },
558 561 {"media", required_argument, 0, 'm' },
559 562 {"peer", required_argument, 0, 'p' },
560 563 { 0, 0, 0, 0 }
561 564 };
562 565
563 566 static const struct option bridge_lopts[] = {
564 567 { "protect", required_argument, 0, 'P' },
565 568 { "root-dir", required_argument, 0, 'R' },
566 569 { "forward-delay", required_argument, 0, 'd' },
567 570 { "force-protocol", required_argument, 0, 'f' },
568 571 { "hello-time", required_argument, 0, 'h' },
569 572 { "link", required_argument, 0, 'l' },
570 573 { "max-age", required_argument, 0, 'm' },
571 574 { "priority", required_argument, 0, 'p' },
572 575 { NULL, NULL, 0, 0 }
573 576 };
574 577
575 578 static const struct option bridge_show_lopts[] = {
576 579 { "forwarding", no_argument, 0, 'f' },
577 580 { "interval", required_argument, 0, 'i' },
578 581 { "link", no_argument, 0, 'l' },
579 582 { "output", required_argument, 0, 'o' },
580 583 { "parsable", no_argument, 0, 'p' },
581 584 { "parseable", no_argument, 0, 'p' },
582 585 { "statistics", no_argument, 0, 's' },
583 586 { "trill", no_argument, 0, 't' },
584 587 { 0, 0, 0, 0 }
585 588 };
586 589
587 590 /*
588 591 * structures for 'dladm show-ether'
589 592 */
590 593 static const char *ptype[] = {LEI_ATTR_NAMES};
591 594
592 595 typedef struct ether_fields_buf_s
593 596 {
594 597 char eth_link[15];
595 598 char eth_ptype[8];
596 599 char eth_state[8];
597 600 char eth_autoneg[5];
598 601 char eth_spdx[31];
599 602 char eth_pause[6];
600 603 char eth_rem_fault[16];
601 604 } ether_fields_buf_t;
602 605
603 606 static const ofmt_field_t ether_fields[] = {
604 607 /* name, field width, offset callback */
605 608 { "LINK", 16,
606 609 offsetof(ether_fields_buf_t, eth_link), print_default_cb},
607 610 { "PTYPE", 9,
608 611 offsetof(ether_fields_buf_t, eth_ptype), print_default_cb},
609 612 { "STATE", 9,
610 613 offsetof(ether_fields_buf_t, eth_state),
611 614 print_default_cb},
612 615 { "AUTO", 6,
613 616 offsetof(ether_fields_buf_t, eth_autoneg), print_default_cb},
614 617 { "SPEED-DUPLEX", 32,
615 618 offsetof(ether_fields_buf_t, eth_spdx), print_default_cb},
616 619 { "PAUSE", 7,
617 620 offsetof(ether_fields_buf_t, eth_pause), print_default_cb},
618 621 { "REM_FAULT", 17,
619 622 offsetof(ether_fields_buf_t, eth_rem_fault), print_default_cb},
620 623 {NULL, 0,
621 624 0, NULL}}
622 625 ;
623 626
624 627 typedef struct print_ether_state {
625 628 const char *es_link;
626 629 boolean_t es_parsable;
627 630 boolean_t es_header;
628 631 boolean_t es_extended;
629 632 ofmt_handle_t es_ofmt;
630 633 } print_ether_state_t;
631 634
632 635 /*
633 636 * structures for 'dladm show-link -s' (print statistics)
634 637 */
635 638 typedef enum {
636 639 LINK_S_LINK,
637 640 LINK_S_IPKTS,
638 641 LINK_S_RBYTES,
639 642 LINK_S_IERRORS,
640 643 LINK_S_OPKTS,
641 644 LINK_S_OBYTES,
642 645 LINK_S_OERRORS
643 646 } link_s_field_index_t;
644 647
645 648 static const ofmt_field_t link_s_fields[] = {
646 649 /* name, field width, index, callback */
647 650 { "LINK", 15, LINK_S_LINK, print_link_stats_cb},
648 651 { "IPACKETS", 10, LINK_S_IPKTS, print_link_stats_cb},
649 652 { "RBYTES", 8, LINK_S_RBYTES, print_link_stats_cb},
650 653 { "IERRORS", 10, LINK_S_IERRORS, print_link_stats_cb},
651 654 { "OPACKETS", 12, LINK_S_OPKTS, print_link_stats_cb},
652 655 { "OBYTES", 12, LINK_S_OBYTES, print_link_stats_cb},
653 656 { "OERRORS", 8, LINK_S_OERRORS, print_link_stats_cb}}
654 657 ;
655 658
656 659 typedef struct link_args_s {
657 660 char *link_s_link;
658 661 pktsum_t *link_s_psum;
659 662 } link_args_t;
660 663
661 664 /*
662 665 * buffer used by print functions for show-{link,phys,vlan} commands.
663 666 */
664 667 typedef struct link_fields_buf_s {
665 668 char link_name[MAXLINKNAMELEN];
666 669 char link_class[DLADM_STRSIZE];
667 670 char link_mtu[11];
668 671 char link_state[DLADM_STRSIZE];
669 672 char link_bridge[MAXLINKNAMELEN];
670 673 char link_over[MAXLINKNAMELEN];
671 674 char link_phys_state[DLADM_STRSIZE];
672 675 char link_phys_media[DLADM_STRSIZE];
673 676 char link_phys_speed[DLADM_STRSIZE];
674 677 char link_phys_duplex[DLPI_LINKNAME_MAX];
675 678 char link_phys_device[DLPI_LINKNAME_MAX];
676 679 char link_flags[6];
677 680 char link_vlan_vid[6];
678 681 } link_fields_buf_t;
679 682
680 683 /*
681 684 * structures for 'dladm show-link'
682 685 */
683 686 static const ofmt_field_t link_fields[] = {
684 687 /* name, field width, index, callback */
685 688 { "LINK", 12,
686 689 offsetof(link_fields_buf_t, link_name), print_default_cb},
687 690 { "CLASS", 10,
688 691 offsetof(link_fields_buf_t, link_class), print_default_cb},
689 692 { "MTU", 7,
690 693 offsetof(link_fields_buf_t, link_mtu), print_default_cb},
691 694 { "STATE", 9,
692 695 offsetof(link_fields_buf_t, link_state), print_default_cb},
693 696 { "BRIDGE", 11,
694 697 offsetof(link_fields_buf_t, link_bridge), print_default_cb},
695 698 { "OVER", DLPI_LINKNAME_MAX,
696 699 offsetof(link_fields_buf_t, link_over), print_default_cb},
697 700 { NULL, 0, 0, NULL}}
698 701 ;
699 702
700 703 /*
701 704 * structures for 'dladm show-aggr'
702 705 */
703 706 typedef struct laggr_fields_buf_s {
704 707 char laggr_name[DLPI_LINKNAME_MAX];
705 708 char laggr_policy[9];
706 709 char laggr_addrpolicy[ETHERADDRL * 3 + 3];
707 710 char laggr_lacpactivity[14];
708 711 char laggr_lacptimer[DLADM_STRSIZE];
709 712 char laggr_flags[7];
710 713 } laggr_fields_buf_t;
711 714
712 715 typedef struct laggr_args_s {
713 716 int laggr_lport; /* -1 indicates the aggr itself */
714 717 const char *laggr_link;
715 718 dladm_aggr_grp_attr_t *laggr_ginfop;
716 719 dladm_status_t *laggr_status;
717 720 pktsum_t *laggr_pktsumtot; /* -s only */
718 721 pktsum_t *laggr_diffstats; /* -s only */
719 722 boolean_t laggr_parsable;
720 723 } laggr_args_t;
721 724
722 725 static const ofmt_field_t laggr_fields[] = {
723 726 /* name, field width, offset, callback */
724 727 { "LINK", 16,
725 728 offsetof(laggr_fields_buf_t, laggr_name), print_default_cb},
726 729 { "POLICY", 9,
727 730 offsetof(laggr_fields_buf_t, laggr_policy), print_default_cb},
728 731 { "ADDRPOLICY", ETHERADDRL * 3 + 3,
729 732 offsetof(laggr_fields_buf_t, laggr_addrpolicy), print_default_cb},
730 733 { "LACPACTIVITY", 14,
731 734 offsetof(laggr_fields_buf_t, laggr_lacpactivity), print_default_cb},
732 735 { "LACPTIMER", 12,
733 736 offsetof(laggr_fields_buf_t, laggr_lacptimer), print_default_cb},
734 737 { "FLAGS", 8,
735 738 offsetof(laggr_fields_buf_t, laggr_flags), print_default_cb},
736 739 { NULL, 0, 0, NULL}}
737 740 ;
738 741
739 742 /*
740 743 * structures for 'dladm show-aggr -x'.
741 744 */
742 745 typedef enum {
743 746 AGGR_X_LINK,
744 747 AGGR_X_PORT,
745 748 AGGR_X_SPEED,
746 749 AGGR_X_DUPLEX,
747 750 AGGR_X_STATE,
748 751 AGGR_X_ADDRESS,
749 752 AGGR_X_PORTSTATE
750 753 } aggr_x_field_index_t;
751 754
752 755 static const ofmt_field_t aggr_x_fields[] = {
753 756 /* name, field width, index callback */
754 757 { "LINK", 12, AGGR_X_LINK, print_xaggr_cb},
755 758 { "PORT", 15, AGGR_X_PORT, print_xaggr_cb},
756 759 { "SPEED", 5, AGGR_X_SPEED, print_xaggr_cb},
757 760 { "DUPLEX", 10, AGGR_X_DUPLEX, print_xaggr_cb},
758 761 { "STATE", 10, AGGR_X_STATE, print_xaggr_cb},
759 762 { "ADDRESS", 19, AGGR_X_ADDRESS, print_xaggr_cb},
760 763 { "PORTSTATE", 16, AGGR_X_PORTSTATE, print_xaggr_cb},
761 764 { NULL, 0, 0, NULL}}
762 765 ;
763 766
764 767 /*
765 768 * structures for 'dladm show-aggr -s'.
766 769 */
767 770 typedef enum {
768 771 AGGR_S_LINK,
769 772 AGGR_S_PORT,
770 773 AGGR_S_IPKTS,
771 774 AGGR_S_RBYTES,
772 775 AGGR_S_OPKTS,
773 776 AGGR_S_OBYTES,
774 777 AGGR_S_IPKTDIST,
775 778 AGGR_S_OPKTDIST
776 779 } aggr_s_field_index_t;
777 780
778 781 static const ofmt_field_t aggr_s_fields[] = {
779 782 { "LINK", 12, AGGR_S_LINK, print_aggr_stats_cb},
780 783 { "PORT", 10, AGGR_S_PORT, print_aggr_stats_cb},
781 784 { "IPACKETS", 8, AGGR_S_IPKTS, print_aggr_stats_cb},
782 785 { "RBYTES", 8, AGGR_S_RBYTES, print_aggr_stats_cb},
783 786 { "OPACKETS", 8, AGGR_S_OPKTS, print_aggr_stats_cb},
784 787 { "OBYTES", 8, AGGR_S_OBYTES, print_aggr_stats_cb},
785 788 { "IPKTDIST", 9, AGGR_S_IPKTDIST, print_aggr_stats_cb},
786 789 { "OPKTDIST", 15, AGGR_S_OPKTDIST, print_aggr_stats_cb},
787 790 { NULL, 0, 0, NULL}}
788 791 ;
789 792
790 793 /*
791 794 * structures for 'dladm show-aggr -L'.
792 795 */
793 796 typedef enum {
794 797 AGGR_L_LINK,
795 798 AGGR_L_PORT,
796 799 AGGR_L_AGGREGATABLE,
797 800 AGGR_L_SYNC,
798 801 AGGR_L_COLL,
799 802 AGGR_L_DIST,
800 803 AGGR_L_DEFAULTED,
801 804 AGGR_L_EXPIRED
802 805 } aggr_l_field_index_t;
803 806
804 807 static const ofmt_field_t aggr_l_fields[] = {
805 808 /* name, field width, index */
806 809 { "LINK", 12, AGGR_L_LINK, print_lacp_cb},
807 810 { "PORT", 13, AGGR_L_PORT, print_lacp_cb},
808 811 { "AGGREGATABLE", 13, AGGR_L_AGGREGATABLE, print_lacp_cb},
809 812 { "SYNC", 5, AGGR_L_SYNC, print_lacp_cb},
810 813 { "COLL", 5, AGGR_L_COLL, print_lacp_cb},
811 814 { "DIST", 5, AGGR_L_DIST, print_lacp_cb},
812 815 { "DEFAULTED", 10, AGGR_L_DEFAULTED, print_lacp_cb},
813 816 { "EXPIRED", 15, AGGR_L_EXPIRED, print_lacp_cb},
814 817 { NULL, 0, 0, NULL}}
815 818 ;
816 819
817 820 /*
818 821 * structures for 'dladm show-phys'
819 822 */
820 823
821 824 static const ofmt_field_t phys_fields[] = {
822 825 /* name, field width, offset */
823 826 { "LINK", 13,
824 827 offsetof(link_fields_buf_t, link_name), print_default_cb},
825 828 { "MEDIA", 21,
826 829 offsetof(link_fields_buf_t, link_phys_media), print_default_cb},
827 830 { "STATE", 11,
828 831 offsetof(link_fields_buf_t, link_phys_state), print_default_cb},
829 832 { "SPEED", 7,
830 833 offsetof(link_fields_buf_t, link_phys_speed), print_default_cb},
831 834 { "DUPLEX", 10,
832 835 offsetof(link_fields_buf_t, link_phys_duplex), print_default_cb},
833 836 { "DEVICE", 13,
834 837 offsetof(link_fields_buf_t, link_phys_device), print_default_cb},
835 838 { "FLAGS", 7,
836 839 offsetof(link_fields_buf_t, link_flags), print_default_cb},
837 840 { NULL, 0, NULL, 0}}
838 841 ;
839 842
840 843 /*
841 844 * structures for 'dladm show-phys -m'
842 845 */
843 846
844 847 typedef enum {
845 848 PHYS_M_LINK,
846 849 PHYS_M_SLOT,
847 850 PHYS_M_ADDRESS,
848 851 PHYS_M_INUSE,
849 852 PHYS_M_CLIENT
850 853 } phys_m_field_index_t;
851 854
852 855 static const ofmt_field_t phys_m_fields[] = {
853 856 /* name, field width, offset */
854 857 { "LINK", 13, PHYS_M_LINK, print_phys_one_mac_cb},
855 858 { "SLOT", 9, PHYS_M_SLOT, print_phys_one_mac_cb},
856 859 { "ADDRESS", 19, PHYS_M_ADDRESS, print_phys_one_mac_cb},
857 860 { "INUSE", 5, PHYS_M_INUSE, print_phys_one_mac_cb},
858 861 { "CLIENT", 13, PHYS_M_CLIENT, print_phys_one_mac_cb},
859 862 { NULL, 0, 0, NULL}}
860 863 ;
861 864
862 865 /*
863 866 * structures for 'dladm show-phys -H'
864 867 */
865 868
866 869 typedef enum {
867 870 PHYS_H_LINK,
868 871 PHYS_H_RINGTYPE,
869 872 PHYS_H_RINGS,
870 873 PHYS_H_CLIENTS
871 874 } phys_h_field_index_t;
872 875
873 876 #define RINGSTRLEN 21
874 877
875 878 static const ofmt_field_t phys_h_fields[] = {
876 879 { "LINK", 13, PHYS_H_LINK, print_phys_one_hwgrp_cb},
877 880 { "RINGTYPE", 9, PHYS_H_RINGTYPE, print_phys_one_hwgrp_cb},
878 881 { "RINGS", RINGSTRLEN, PHYS_H_RINGS, print_phys_one_hwgrp_cb},
879 882 { "CLIENTS", 24, PHYS_H_CLIENTS, print_phys_one_hwgrp_cb},
880 883 { NULL, 0, 0, NULL}}
881 884 ;
882 885
883 886 /*
884 887 * structures for 'dladm show-vlan'
885 888 */
886 889 static const ofmt_field_t vlan_fields[] = {
887 890 { "LINK", 16,
888 891 offsetof(link_fields_buf_t, link_name), print_default_cb},
889 892 { "VID", 9,
890 893 offsetof(link_fields_buf_t, link_vlan_vid), print_default_cb},
891 894 { "OVER", 13,
892 895 offsetof(link_fields_buf_t, link_over), print_default_cb},
893 896 { "FLAGS", 7,
894 897 offsetof(link_fields_buf_t, link_flags), print_default_cb},
895 898 { NULL, 0, 0, NULL}}
896 899 ;
897 900
898 901 /*
899 902 * structures common to 'dladm scan-wifi' and 'dladm show-wifi'
900 903 * callback will be determined in parse_wifi_fields.
901 904 */
902 905 static ofmt_field_t wifi_common_fields[] = {
903 906 { "LINK", 11, 0, NULL},
904 907 { "ESSID", 20, DLADM_WLAN_ATTR_ESSID, NULL},
905 908 { "BSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL},
906 909 { "IBSSID", 18, DLADM_WLAN_ATTR_BSSID, NULL},
907 910 { "MODE", 7, DLADM_WLAN_ATTR_MODE, NULL},
908 911 { "SPEED", 7, DLADM_WLAN_ATTR_SPEED, NULL},
909 912 { "BSSTYPE", 9, DLADM_WLAN_ATTR_BSSTYPE, NULL},
910 913 { "SEC", 7, DLADM_WLAN_ATTR_SECMODE, NULL},
911 914 { "STRENGTH", 11, DLADM_WLAN_ATTR_STRENGTH, NULL},
912 915 { NULL, 0, 0, NULL}};
913 916
914 917 /*
915 918 * the 'show-wifi' command supports all the fields in wifi_common_fields
916 919 * plus the AUTH and STATUS fields.
917 920 */
918 921 static ofmt_field_t wifi_show_fields[A_CNT(wifi_common_fields) + 2] = {
919 922 { "AUTH", 9, DLADM_WLAN_ATTR_AUTH, NULL},
920 923 { "STATUS", 18, DLADM_WLAN_LINKATTR_STATUS, print_wifi_status_cb},
921 924 /* copy wifi_common_fields here */
922 925 };
923 926
924 927 static char *all_scan_wifi_fields =
925 928 "link,essid,bssid,sec,strength,mode,speed,bsstype";
926 929 static char *all_show_wifi_fields =
927 930 "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype";
928 931 static char *def_scan_wifi_fields =
929 932 "link,essid,bssid,sec,strength,mode,speed";
930 933 static char *def_show_wifi_fields =
931 934 "link,status,essid,sec,strength,mode,speed";
932 935
933 936 /*
934 937 * structures for 'dladm show-linkprop'
935 938 */
936 939 typedef enum {
937 940 LINKPROP_LINK,
938 941 LINKPROP_PROPERTY,
939 942 LINKPROP_PERM,
940 943 LINKPROP_VALUE,
941 944 LINKPROP_DEFAULT,
942 945 LINKPROP_POSSIBLE
943 946 } linkprop_field_index_t;
944 947
945 948 static const ofmt_field_t linkprop_fields[] = {
946 949 /* name, field width, index */
947 950 { "LINK", 13, LINKPROP_LINK, print_linkprop_cb},
948 951 { "PROPERTY", 16, LINKPROP_PROPERTY, print_linkprop_cb},
949 952 { "PERM", 5, LINKPROP_PERM, print_linkprop_cb},
950 953 { "VALUE", 15, LINKPROP_VALUE, print_linkprop_cb},
951 954 { "DEFAULT", 15, LINKPROP_DEFAULT, print_linkprop_cb},
|
↓ open down ↓ |
588 lines elided |
↑ open up ↑ |
952 955 { "POSSIBLE", 20, LINKPROP_POSSIBLE, print_linkprop_cb},
953 956 { NULL, 0, 0, NULL}}
954 957 ;
955 958
956 959 #define MAX_PROP_LINE 512
957 960
958 961 typedef struct show_linkprop_state {
959 962 char ls_link[MAXLINKNAMELEN];
960 963 char *ls_line;
961 964 char **ls_propvals;
965 + char *ls_zonename;
962 966 dladm_arg_list_t *ls_proplist;
963 967 boolean_t ls_parsable;
964 968 boolean_t ls_persist;
965 969 boolean_t ls_header;
966 970 dladm_status_t ls_status;
967 971 dladm_status_t ls_retstatus;
968 972 ofmt_handle_t ls_ofmt;
969 973 } show_linkprop_state_t;
970 974
971 975 typedef struct set_linkprop_state {
972 976 const char *ls_name;
973 977 boolean_t ls_reset;
974 978 boolean_t ls_temp;
975 979 dladm_status_t ls_status;
976 980 } set_linkprop_state_t;
977 981
978 982 typedef struct linkprop_args_s {
979 983 show_linkprop_state_t *ls_state;
980 984 char *ls_propname;
981 985 datalink_id_t ls_linkid;
982 986 } linkprop_args_t;
983 987
984 988 /*
985 989 * structures for 'dladm show-secobj'
986 990 */
987 991 typedef struct secobj_fields_buf_s {
988 992 char ss_obj_name[DLADM_SECOBJ_VAL_MAX];
989 993 char ss_class[20];
990 994 char ss_val[30];
991 995 } secobj_fields_buf_t;
992 996
993 997 static const ofmt_field_t secobj_fields[] = {
994 998 { "OBJECT", 21,
995 999 offsetof(secobj_fields_buf_t, ss_obj_name), print_default_cb},
996 1000 { "CLASS", 21,
997 1001 offsetof(secobj_fields_buf_t, ss_class), print_default_cb},
998 1002 { "VALUE", 31,
999 1003 offsetof(secobj_fields_buf_t, ss_val), print_default_cb},
1000 1004 { NULL, 0, 0, NULL}}
1001 1005 ;
1002 1006
1003 1007 /*
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
1004 1008 * structures for 'dladm show-vnic'
1005 1009 */
1006 1010 typedef struct vnic_fields_buf_s
1007 1011 {
1008 1012 char vnic_link[DLPI_LINKNAME_MAX];
1009 1013 char vnic_over[DLPI_LINKNAME_MAX];
1010 1014 char vnic_speed[6];
1011 1015 char vnic_macaddr[18];
1012 1016 char vnic_macaddrtype[19];
1013 1017 char vnic_vid[6];
1018 + char vnic_zone[ZONENAME_MAX];
1014 1019 } vnic_fields_buf_t;
1015 1020
1016 1021 static const ofmt_field_t vnic_fields[] = {
1017 1022 { "LINK", 13,
1018 1023 offsetof(vnic_fields_buf_t, vnic_link), print_default_cb},
1019 -{ "OVER", 13,
1024 +{ "OVER", 11,
1020 1025 offsetof(vnic_fields_buf_t, vnic_over), print_default_cb},
1021 -{ "SPEED", 7,
1026 +{ "SPEED", 6,
1022 1027 offsetof(vnic_fields_buf_t, vnic_speed), print_default_cb},
1023 1028 { "MACADDRESS", 18,
1024 1029 offsetof(vnic_fields_buf_t, vnic_macaddr), print_default_cb},
1025 -{ "MACADDRTYPE", 20,
1030 +{ "MACADDRTYPE", 12,
1026 1031 offsetof(vnic_fields_buf_t, vnic_macaddrtype), print_default_cb},
1027 -{ "VID", 7,
1032 +{ "VID", 5,
1028 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},
1029 1036 { NULL, 0, 0, NULL}}
1030 1037 ;
1031 1038
1032 1039 /*
1033 1040 * structures for 'dladm show-ib'
1034 1041 */
1035 1042 typedef struct ib_fields_buf_s
1036 1043 {
1037 1044 char ib_link[DLPI_LINKNAME_MAX];
1038 1045 char ib_hcaguid[17];
1039 1046 char ib_portguid[17];
1040 1047 char ib_portnum[4];
1041 1048 char ib_state[6];
1042 1049 char ib_pkeys[MAXPKEYSTRSZ];
1043 1050 } ib_fields_buf_t;
1044 1051
1045 1052 static const ofmt_field_t ib_fields[] = {
1046 1053 { "LINK", 13,
1047 1054 offsetof(ib_fields_buf_t, ib_link), print_default_cb},
1048 1055 { "HCAGUID", IBGUIDSTRLEN,
1049 1056 offsetof(ib_fields_buf_t, ib_hcaguid), print_default_cb},
1050 1057 { "PORTGUID", IBGUIDSTRLEN,
1051 1058 offsetof(ib_fields_buf_t, ib_portguid), print_default_cb},
1052 1059 { "PORT", IBPORTSTRLEN,
1053 1060 offsetof(ib_fields_buf_t, ib_portnum), print_default_cb},
1054 1061 { "STATE", 7,
1055 1062 offsetof(ib_fields_buf_t, ib_state), print_default_cb},
1056 1063 { "PKEYS", 18,
1057 1064 offsetof(ib_fields_buf_t, ib_pkeys), print_default_cb},
1058 1065 { NULL, 0, 0, NULL}};
1059 1066
1060 1067 /*
1061 1068 * structures for 'dladm show-part'
1062 1069 */
1063 1070 typedef struct part_fields_buf_s
1064 1071 {
1065 1072 char part_link[DLPI_LINKNAME_MAX];
1066 1073 char part_pkey[5];
1067 1074 char part_over[DLPI_LINKNAME_MAX];
1068 1075 char part_state[8];
1069 1076 char part_flags[5];
1070 1077 } part_fields_buf_t;
1071 1078
1072 1079 static const ofmt_field_t part_fields[] = {
1073 1080 { "LINK", 13,
1074 1081 offsetof(part_fields_buf_t, part_link), print_default_cb},
1075 1082 { "PKEY", MAXPKEYLEN,
1076 1083 offsetof(part_fields_buf_t, part_pkey), print_default_cb},
1077 1084 { "OVER", 13,
1078 1085 offsetof(part_fields_buf_t, part_over), print_default_cb},
1079 1086 { "STATE", 9,
1080 1087 offsetof(part_fields_buf_t, part_state), print_default_cb},
1081 1088 { "FLAGS", 5,
1082 1089 offsetof(part_fields_buf_t, part_flags), print_default_cb},
1083 1090 { NULL, 0, 0, NULL}};
1084 1091
1085 1092 /*
1086 1093 * structures for 'dladm show-simnet'
1087 1094 */
1088 1095 typedef struct simnet_fields_buf_s
1089 1096 {
1090 1097 char simnet_name[DLPI_LINKNAME_MAX];
1091 1098 char simnet_media[DLADM_STRSIZE];
1092 1099 char simnet_macaddr[18];
1093 1100 char simnet_otherlink[DLPI_LINKNAME_MAX];
1094 1101 } simnet_fields_buf_t;
1095 1102
1096 1103 static const ofmt_field_t simnet_fields[] = {
1097 1104 { "LINK", 12,
1098 1105 offsetof(simnet_fields_buf_t, simnet_name), print_default_cb},
1099 1106 { "MEDIA", 20,
1100 1107 offsetof(simnet_fields_buf_t, simnet_media), print_default_cb},
1101 1108 { "MACADDRESS", 18,
1102 1109 offsetof(simnet_fields_buf_t, simnet_macaddr), print_default_cb},
1103 1110 { "OTHERLINK", 12,
1104 1111 offsetof(simnet_fields_buf_t, simnet_otherlink), print_default_cb},
1105 1112 { NULL, 0, 0, NULL}}
1106 1113 ;
1107 1114
1108 1115 /*
1109 1116 * structures for 'dladm show-usage'
1110 1117 */
1111 1118
1112 1119 typedef struct usage_fields_buf_s {
1113 1120 char usage_link[12];
1114 1121 char usage_duration[10];
1115 1122 char usage_ipackets[9];
1116 1123 char usage_rbytes[10];
1117 1124 char usage_opackets[9];
1118 1125 char usage_obytes[10];
1119 1126 char usage_bandwidth[14];
1120 1127 } usage_fields_buf_t;
1121 1128
1122 1129 static const ofmt_field_t usage_fields[] = {
1123 1130 { "LINK", 13,
1124 1131 offsetof(usage_fields_buf_t, usage_link), print_default_cb},
1125 1132 { "DURATION", 11,
1126 1133 offsetof(usage_fields_buf_t, usage_duration), print_default_cb},
1127 1134 { "IPACKETS", 10,
1128 1135 offsetof(usage_fields_buf_t, usage_ipackets), print_default_cb},
1129 1136 { "RBYTES", 11,
1130 1137 offsetof(usage_fields_buf_t, usage_rbytes), print_default_cb},
1131 1138 { "OPACKETS", 10,
1132 1139 offsetof(usage_fields_buf_t, usage_opackets), print_default_cb},
1133 1140 { "OBYTES", 11,
1134 1141 offsetof(usage_fields_buf_t, usage_obytes), print_default_cb},
1135 1142 { "BANDWIDTH", 15,
1136 1143 offsetof(usage_fields_buf_t, usage_bandwidth), print_default_cb},
1137 1144 { NULL, 0, 0, NULL}}
1138 1145 ;
1139 1146
1140 1147
1141 1148 /*
1142 1149 * structures for 'dladm show-usage link'
1143 1150 */
1144 1151
1145 1152 typedef struct usage_l_fields_buf_s {
1146 1153 char usage_l_link[12];
1147 1154 char usage_l_stime[13];
1148 1155 char usage_l_etime[13];
1149 1156 char usage_l_rbytes[8];
1150 1157 char usage_l_obytes[8];
1151 1158 char usage_l_bandwidth[14];
1152 1159 } usage_l_fields_buf_t;
1153 1160
1154 1161 static const ofmt_field_t usage_l_fields[] = {
1155 1162 /* name, field width, offset */
1156 1163 { "LINK", 13,
1157 1164 offsetof(usage_l_fields_buf_t, usage_l_link), print_default_cb},
1158 1165 { "START", 14,
1159 1166 offsetof(usage_l_fields_buf_t, usage_l_stime), print_default_cb},
1160 1167 { "END", 14,
1161 1168 offsetof(usage_l_fields_buf_t, usage_l_etime), print_default_cb},
1162 1169 { "RBYTES", 9,
1163 1170 offsetof(usage_l_fields_buf_t, usage_l_rbytes), print_default_cb},
1164 1171 { "OBYTES", 9,
1165 1172 offsetof(usage_l_fields_buf_t, usage_l_obytes), print_default_cb},
1166 1173 { "BANDWIDTH", 15,
1167 1174 offsetof(usage_l_fields_buf_t, usage_l_bandwidth), print_default_cb},
1168 1175 { NULL, 0, 0, NULL}}
1169 1176 ;
1170 1177
1171 1178 /* IPTUN_*FLAG_INDEX values are indices into iptun_flags below. */
1172 1179 enum { IPTUN_SFLAG_INDEX, IPTUN_IFLAG_INDEX, IPTUN_NUM_FLAGS };
1173 1180
1174 1181 /*
1175 1182 * structures for 'dladm show-iptun'
1176 1183 */
1177 1184 typedef struct iptun_fields_buf_s {
1178 1185 char iptun_name[MAXLINKNAMELEN];
1179 1186 char iptun_type[5];
1180 1187 char iptun_laddr[NI_MAXHOST];
1181 1188 char iptun_raddr[NI_MAXHOST];
1182 1189 char iptun_flags[IPTUN_NUM_FLAGS + 1];
1183 1190 } iptun_fields_buf_t;
1184 1191
1185 1192 static const ofmt_field_t iptun_fields[] = {
1186 1193 { "LINK", 16,
1187 1194 offsetof(iptun_fields_buf_t, iptun_name), print_default_cb },
1188 1195 { "TYPE", 6,
1189 1196 offsetof(iptun_fields_buf_t, iptun_type), print_default_cb },
1190 1197 { "FLAGS", 7,
1191 1198 offsetof(iptun_fields_buf_t, iptun_flags), print_default_cb },
1192 1199 { "LOCAL", 20,
1193 1200 offsetof(iptun_fields_buf_t, iptun_laddr), print_default_cb },
1194 1201 { "REMOTE", 20,
1195 1202 offsetof(iptun_fields_buf_t, iptun_raddr), print_default_cb },
1196 1203 { NULL, 0, 0, NULL}
1197 1204 };
1198 1205
1199 1206 /*
1200 1207 * structures for 'dladm show-bridge'. These are based on sections 14.8.1.1.3
1201 1208 * and 14.8.1.2.2 of IEEE 802.1D-2004.
1202 1209 */
1203 1210 typedef struct bridge_fields_buf_s {
1204 1211 char bridge_name[MAXLINKNAMELEN]; /* 14.4.1.2.3(b) */
1205 1212 char bridge_protect[7]; /* stp or trill */
1206 1213 char bridge_address[24]; /* 17.18.3, 7.12.5, 14.4.1.2.3(a) */
1207 1214 char bridge_priority[7]; /* 17.18.3 9.2.5 - only upper 4 bits */
1208 1215 char bridge_bmaxage[7]; /* 17.18.4 configured */
1209 1216 char bridge_bhellotime[7]; /* 17.18.4 configured */
1210 1217 char bridge_bfwddelay[7]; /* 17.18.4 configured */
1211 1218 char bridge_forceproto[3]; /* 17.13.4 configured */
1212 1219 char bridge_tctime[12]; /* 14.8.1.1.3(b) */
1213 1220 char bridge_tccount[12]; /* 17.17.8 */
1214 1221 char bridge_tchange[12]; /* 17.17.8 */
1215 1222 char bridge_desroot[24]; /* 17.18.6 priority "/" MAC */
1216 1223 char bridge_rootcost[12]; /* 17.18.6 */
1217 1224 char bridge_rootport[12]; /* 17.18.6 */
1218 1225 char bridge_maxage[7]; /* 17.18.7 for root */
1219 1226 char bridge_hellotime[7]; /* 17.13.6 for root */
1220 1227 char bridge_fwddelay[7]; /* 17.13.5 for root */
1221 1228 char bridge_holdtime[12]; /* 17.13.12 for root */
1222 1229 } bridge_fields_buf_t;
1223 1230
1224 1231 static ofmt_field_t bridge_fields[] = {
1225 1232 /* name, field width, offset, callback */
1226 1233 { "BRIDGE", 12,
1227 1234 offsetof(bridge_fields_buf_t, bridge_name), print_default_cb },
1228 1235 { "PROTECT", 8,
1229 1236 offsetof(bridge_fields_buf_t, bridge_protect), print_default_cb },
1230 1237 { "ADDRESS", 19,
1231 1238 offsetof(bridge_fields_buf_t, bridge_address), print_default_cb },
1232 1239 { "PRIORITY", 9,
1233 1240 offsetof(bridge_fields_buf_t, bridge_priority), print_default_cb },
1234 1241 { "BMAXAGE", 8,
1235 1242 offsetof(bridge_fields_buf_t, bridge_bmaxage), print_default_cb },
1236 1243 { "BHELLOTIME", 11,
1237 1244 offsetof(bridge_fields_buf_t, bridge_bhellotime), print_default_cb },
1238 1245 { "BFWDDELAY", 10,
1239 1246 offsetof(bridge_fields_buf_t, bridge_bfwddelay), print_default_cb },
1240 1247 { "FORCEPROTO", 11,
1241 1248 offsetof(bridge_fields_buf_t, bridge_forceproto), print_default_cb },
1242 1249 { "TCTIME", 10,
1243 1250 offsetof(bridge_fields_buf_t, bridge_tctime), print_default_cb },
1244 1251 { "TCCOUNT", 10,
1245 1252 offsetof(bridge_fields_buf_t, bridge_tccount), print_default_cb },
1246 1253 { "TCHANGE", 10,
1247 1254 offsetof(bridge_fields_buf_t, bridge_tchange), print_default_cb },
1248 1255 { "DESROOT", 23,
1249 1256 offsetof(bridge_fields_buf_t, bridge_desroot), print_default_cb },
1250 1257 { "ROOTCOST", 11,
1251 1258 offsetof(bridge_fields_buf_t, bridge_rootcost), print_default_cb },
1252 1259 { "ROOTPORT", 11,
1253 1260 offsetof(bridge_fields_buf_t, bridge_rootport), print_default_cb },
1254 1261 { "MAXAGE", 8,
1255 1262 offsetof(bridge_fields_buf_t, bridge_maxage), print_default_cb },
1256 1263 { "HELLOTIME", 10,
1257 1264 offsetof(bridge_fields_buf_t, bridge_hellotime), print_default_cb },
1258 1265 { "FWDDELAY", 9,
1259 1266 offsetof(bridge_fields_buf_t, bridge_fwddelay), print_default_cb },
1260 1267 { "HOLDTIME", 9,
1261 1268 offsetof(bridge_fields_buf_t, bridge_holdtime), print_default_cb },
1262 1269 { NULL, 0, 0, NULL}};
1263 1270
1264 1271 /*
1265 1272 * structures for 'dladm show-bridge -l'. These are based on 14.4.1.2.3 and
1266 1273 * 14.8.2.1.3 of IEEE 802.1D-2004.
1267 1274 */
1268 1275 typedef struct bridge_link_fields_buf_s {
1269 1276 char bridgel_link[MAXLINKNAMELEN];
1270 1277 char bridgel_index[7]; /* 14.4.1.2.3(d1) */
1271 1278 char bridgel_state[11]; /* 14.8.2.1.3(b) */
1272 1279 char bridgel_uptime[7]; /* 14.8.2.1.3(a) */
1273 1280 char bridgel_opercost[7] /* 14.8.2.1.3(d) */;
1274 1281 char bridgel_operp2p[4]; /* 14.8.2.1.3(p) */
1275 1282 char bridgel_operedge[4]; /* 14.8.2.1.3(k) */
1276 1283 char bridgel_desroot[23]; /* 14.8.2.1.3(e) */
1277 1284 char bridgel_descost[12]; /* 14.8.2.1.3(f) */
1278 1285 char bridgel_desbridge[23]; /* 14.8.2.1.3(g) */
1279 1286 char bridgel_desport[7]; /* 14.8.2.1.3(h) */
1280 1287 char bridgel_tcack[4]; /* 14.8.2.1.3(i) */
1281 1288 } bridge_link_fields_buf_t;
1282 1289
1283 1290 static ofmt_field_t bridge_link_fields[] = {
1284 1291 /* name, field width, offset, callback */
1285 1292 { "LINK", 12,
1286 1293 offsetof(bridge_link_fields_buf_t, bridgel_link), print_default_cb },
1287 1294 { "INDEX", 8,
1288 1295 offsetof(bridge_link_fields_buf_t, bridgel_index), print_default_cb },
1289 1296 { "STATE", 12,
1290 1297 offsetof(bridge_link_fields_buf_t, bridgel_state), print_default_cb },
1291 1298 { "UPTIME", 8,
1292 1299 offsetof(bridge_link_fields_buf_t, bridgel_uptime), print_default_cb },
1293 1300 { "OPERCOST", 9,
1294 1301 offsetof(bridge_link_fields_buf_t, bridgel_opercost), print_default_cb },
1295 1302 { "OPERP2P", 8,
1296 1303 offsetof(bridge_link_fields_buf_t, bridgel_operp2p), print_default_cb },
1297 1304 { "OPEREDGE", 9,
1298 1305 offsetof(bridge_link_fields_buf_t, bridgel_operedge), print_default_cb },
1299 1306 { "DESROOT", 22,
1300 1307 offsetof(bridge_link_fields_buf_t, bridgel_desroot), print_default_cb },
1301 1308 { "DESCOST", 11,
1302 1309 offsetof(bridge_link_fields_buf_t, bridgel_descost), print_default_cb },
1303 1310 { "DESBRIDGE", 22,
1304 1311 offsetof(bridge_link_fields_buf_t, bridgel_desbridge), print_default_cb },
1305 1312 { "DESPORT", 8,
1306 1313 offsetof(bridge_link_fields_buf_t, bridgel_desport), print_default_cb },
1307 1314 { "TCACK", 6,
1308 1315 offsetof(bridge_link_fields_buf_t, bridgel_tcack), print_default_cb },
1309 1316 { NULL, 0, 0, NULL}};
1310 1317
1311 1318 /*
1312 1319 * structures for 'dladm show-bridge -s'. These are not based on IEEE
1313 1320 * 802.1D-2004.
1314 1321 */
1315 1322 #define ULONG_DIG (((sizeof (ulong_t) * NBBY) * 3 / 10) + 1)
1316 1323 #define UINT64_DIG (((sizeof (uint64_t) * NBBY) * 3 / 10) + 1)
1317 1324 typedef struct bridge_statfields_buf_s {
1318 1325 char bridges_name[MAXLINKNAMELEN];
1319 1326 char bridges_drops[UINT64_DIG];
1320 1327 char bridges_forwards[UINT64_DIG];
1321 1328 char bridges_mbcast[UINT64_DIG];
1322 1329 char bridges_unknown[UINT64_DIG];
1323 1330 char bridges_recv[UINT64_DIG];
1324 1331 char bridges_sent[UINT64_DIG];
1325 1332 } bridge_statfields_buf_t;
1326 1333
1327 1334 static ofmt_field_t bridge_statfields[] = {
1328 1335 /* name, field width, offset, callback */
1329 1336 { "BRIDGE", 12,
1330 1337 offsetof(bridge_statfields_buf_t, bridges_name), print_default_cb },
1331 1338 { "DROPS", 12,
1332 1339 offsetof(bridge_statfields_buf_t, bridges_drops), print_default_cb },
1333 1340 { "FORWARDS", 12,
1334 1341 offsetof(bridge_statfields_buf_t, bridges_forwards), print_default_cb },
1335 1342 { "MBCAST", 12,
1336 1343 offsetof(bridge_statfields_buf_t, bridges_mbcast), print_default_cb },
1337 1344 { "UNKNOWN", 12,
1338 1345 offsetof(bridge_statfields_buf_t, bridges_unknown), print_default_cb },
1339 1346 { "RECV", 12,
1340 1347 offsetof(bridge_statfields_buf_t, bridges_recv), print_default_cb },
1341 1348 { "SENT", 12,
1342 1349 offsetof(bridge_statfields_buf_t, bridges_sent), print_default_cb },
1343 1350 { NULL, 0, 0, NULL}};
1344 1351
1345 1352 /*
1346 1353 * structures for 'dladm show-bridge -s -l'. These are based in part on
1347 1354 * section 14.6.1.1.3 of IEEE 802.1D-2004.
1348 1355 */
1349 1356 typedef struct bridge_link_statfields_buf_s {
1350 1357 char bridgels_link[MAXLINKNAMELEN];
1351 1358 char bridgels_cfgbpdu[ULONG_DIG];
1352 1359 char bridgels_tcnbpdu[ULONG_DIG];
1353 1360 char bridgels_rstpbpdu[ULONG_DIG];
1354 1361 char bridgels_txbpdu[ULONG_DIG];
1355 1362 char bridgels_drops[UINT64_DIG]; /* 14.6.1.1.3(d) */
1356 1363 char bridgels_recv[UINT64_DIG]; /* 14.6.1.1.3(a) */
1357 1364 char bridgels_xmit[UINT64_DIG]; /* 14.6.1.1.3(c) */
1358 1365 } bridge_link_statfields_buf_t;
1359 1366
1360 1367 static ofmt_field_t bridge_link_statfields[] = {
1361 1368 /* name, field width, offset, callback */
1362 1369 { "LINK", 12,
1363 1370 offsetof(bridge_link_statfields_buf_t, bridgels_link), print_default_cb },
1364 1371 { "CFGBPDU", 9,
1365 1372 offsetof(bridge_link_statfields_buf_t, bridgels_cfgbpdu),
1366 1373 print_default_cb },
1367 1374 { "TCNBPDU", 9,
1368 1375 offsetof(bridge_link_statfields_buf_t, bridgels_tcnbpdu),
1369 1376 print_default_cb },
1370 1377 { "RSTPBPDU", 9,
1371 1378 offsetof(bridge_link_statfields_buf_t, bridgels_rstpbpdu),
1372 1379 print_default_cb },
1373 1380 { "TXBPDU", 9,
1374 1381 offsetof(bridge_link_statfields_buf_t, bridgels_txbpdu), print_default_cb },
1375 1382 { "DROPS", 9,
1376 1383 offsetof(bridge_link_statfields_buf_t, bridgels_drops), print_default_cb },
1377 1384 { "RECV", 9,
1378 1385 offsetof(bridge_link_statfields_buf_t, bridgels_recv), print_default_cb },
1379 1386 { "XMIT", 9,
1380 1387 offsetof(bridge_link_statfields_buf_t, bridgels_xmit), print_default_cb },
1381 1388 { NULL, 0, 0, NULL}};
1382 1389
1383 1390 /*
1384 1391 * structures for 'dladm show-bridge -f'. These are based in part on
1385 1392 * section 14.7.6.3.3 of IEEE 802.1D-2004.
1386 1393 */
1387 1394 typedef struct bridge_fwd_fields_buf_s {
1388 1395 char bridgef_dest[18]; /* 14.7.6.3.3(a) */
1389 1396 char bridgef_age[8];
1390 1397 char bridgef_flags[6];
1391 1398 char bridgef_output[MAXLINKNAMELEN]; /* 14.7.6.3.3(c) */
1392 1399 } bridge_fwd_fields_buf_t;
1393 1400
1394 1401 static ofmt_field_t bridge_fwd_fields[] = {
1395 1402 /* name, field width, offset, callback */
1396 1403 { "DEST", 17,
1397 1404 offsetof(bridge_fwd_fields_buf_t, bridgef_dest), print_default_cb },
1398 1405 { "AGE", 7,
1399 1406 offsetof(bridge_fwd_fields_buf_t, bridgef_age), print_default_cb },
1400 1407 { "FLAGS", 6,
1401 1408 offsetof(bridge_fwd_fields_buf_t, bridgef_flags), print_default_cb },
1402 1409 { "OUTPUT", 12,
1403 1410 offsetof(bridge_fwd_fields_buf_t, bridgef_output), print_default_cb },
1404 1411 { NULL, 0, 0, NULL}};
1405 1412
1406 1413 /*
1407 1414 * structures for 'dladm show-bridge -t'.
1408 1415 */
1409 1416 typedef struct bridge_trill_fields_buf_s {
1410 1417 char bridget_nick[6];
1411 1418 char bridget_flags[6];
1412 1419 char bridget_link[MAXLINKNAMELEN];
1413 1420 char bridget_nexthop[18];
1414 1421 } bridge_trill_fields_buf_t;
1415 1422
1416 1423 static ofmt_field_t bridge_trill_fields[] = {
1417 1424 /* name, field width, offset, callback */
1418 1425 { "NICK", 5,
1419 1426 offsetof(bridge_trill_fields_buf_t, bridget_nick), print_default_cb },
1420 1427 { "FLAGS", 6,
1421 1428 offsetof(bridge_trill_fields_buf_t, bridget_flags), print_default_cb },
1422 1429 { "LINK", 12,
1423 1430 offsetof(bridge_trill_fields_buf_t, bridget_link), print_default_cb },
1424 1431 { "NEXTHOP", 17,
1425 1432 offsetof(bridge_trill_fields_buf_t, bridget_nexthop), print_default_cb },
1426 1433 { NULL, 0, 0, NULL}};
1427 1434
1428 1435 static char *progname;
1429 1436 static sig_atomic_t signalled;
1430 1437
1431 1438 /*
1432 1439 * Handle to libdladm. Opened in main() before the sub-command
1433 1440 * specific function is called.
1434 1441 */
1435 1442 static dladm_handle_t handle = NULL;
1436 1443
1437 1444 #define DLADM_ETHERSTUB_NAME "etherstub"
1438 1445 #define DLADM_IS_ETHERSTUB(id) (id == DATALINK_INVALID_LINKID)
1439 1446
1440 1447 static void
1441 1448 usage(void)
1442 1449 {
1443 1450 int i;
1444 1451 cmd_t *cmdp;
1445 1452 (void) fprintf(stderr, gettext("usage: dladm <subcommand> <args> ..."
1446 1453 "\n"));
1447 1454 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
1448 1455 cmdp = &cmds[i];
1449 1456 if (cmdp->c_usage != NULL)
1450 1457 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
1451 1458 }
1452 1459
1453 1460 /* close dladm handle if it was opened */
1454 1461 if (handle != NULL)
1455 1462 dladm_close(handle);
1456 1463
1457 1464 exit(EXIT_FAILURE);
1458 1465 }
1459 1466
1460 1467 int
1461 1468 main(int argc, char *argv[])
1462 1469 {
1463 1470 int i;
1464 1471 cmd_t *cmdp;
1465 1472 dladm_status_t status;
1466 1473
1467 1474 (void) setlocale(LC_ALL, "");
1468 1475 #if !defined(TEXT_DOMAIN)
1469 1476 #define TEXT_DOMAIN "SYS_TEST"
1470 1477 #endif
1471 1478 (void) textdomain(TEXT_DOMAIN);
1472 1479
1473 1480 progname = argv[0];
1474 1481
1475 1482 if (argc < 2)
1476 1483 usage();
1477 1484
1478 1485 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
1479 1486 cmdp = &cmds[i];
1480 1487 if (strcmp(argv[1], cmdp->c_name) == 0) {
1481 1488 /* Open the libdladm handle */
1482 1489 if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) {
1483 1490 die_dlerr(status,
1484 1491 "could not open /dev/dld");
1485 1492 }
1486 1493
1487 1494 cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage);
1488 1495
1489 1496 dladm_close(handle);
1490 1497 return (EXIT_SUCCESS);
1491 1498 }
1492 1499 }
1493 1500
1494 1501 (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
1495 1502 progname, argv[1]);
1496 1503 usage();
1497 1504 return (EXIT_FAILURE);
1498 1505 }
1499 1506
1500 1507 /*ARGSUSED*/
1501 1508 static int
1502 1509 show_usage_date(dladm_usage_t *usage, void *arg)
1503 1510 {
1504 1511 show_usage_state_t *state = (show_usage_state_t *)arg;
1505 1512 time_t stime;
1506 1513 char timebuf[20];
1507 1514 dladm_status_t status;
1508 1515 uint32_t flags;
1509 1516
1510 1517 /*
1511 1518 * Only show usage information for existing links unless '-a'
1512 1519 * is specified.
1513 1520 */
1514 1521 if (!state->us_showall) {
1515 1522 if ((status = dladm_name2info(handle, usage->du_name,
1516 1523 NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
1517 1524 return (status);
1518 1525 }
1519 1526 if ((flags & DLADM_OPT_ACTIVE) == 0)
1520 1527 return (DLADM_STATUS_LINKINVAL);
1521 1528 }
1522 1529
1523 1530 stime = usage->du_stime;
1524 1531 (void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y",
1525 1532 localtime(&stime));
1526 1533 (void) printf("%s\n", timebuf);
1527 1534
1528 1535 return (DLADM_STATUS_OK);
1529 1536 }
1530 1537
1531 1538 static int
1532 1539 show_usage_time(dladm_usage_t *usage, void *arg)
1533 1540 {
1534 1541 show_usage_state_t *state = (show_usage_state_t *)arg;
1535 1542 char buf[DLADM_STRSIZE];
1536 1543 usage_l_fields_buf_t ubuf;
1537 1544 time_t time;
1538 1545 double bw;
1539 1546 dladm_status_t status;
1540 1547 uint32_t flags;
1541 1548
1542 1549 /*
1543 1550 * Only show usage information for existing links unless '-a'
1544 1551 * is specified.
1545 1552 */
1546 1553 if (!state->us_showall) {
1547 1554 if ((status = dladm_name2info(handle, usage->du_name,
1548 1555 NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
1549 1556 return (status);
1550 1557 }
1551 1558 if ((flags & DLADM_OPT_ACTIVE) == 0)
1552 1559 return (DLADM_STATUS_LINKINVAL);
1553 1560 }
1554 1561
1555 1562 if (state->us_plot) {
1556 1563 if (!state->us_printheader) {
1557 1564 if (state->us_first) {
1558 1565 (void) printf("# Time");
1559 1566 state->us_first = B_FALSE;
1560 1567 }
1561 1568 (void) printf(" %s", usage->du_name);
1562 1569 if (usage->du_last) {
1563 1570 (void) printf("\n");
1564 1571 state->us_first = B_TRUE;
1565 1572 state->us_printheader = B_TRUE;
1566 1573 }
1567 1574 } else {
1568 1575 if (state->us_first) {
1569 1576 time = usage->du_etime;
1570 1577 (void) strftime(buf, sizeof (buf), "%T",
1571 1578 localtime(&time));
1572 1579 state->us_first = B_FALSE;
1573 1580 (void) printf("%s", buf);
1574 1581 }
1575 1582 bw = (double)usage->du_bandwidth/1000;
1576 1583 (void) printf(" %.2f", bw);
1577 1584 if (usage->du_last) {
1578 1585 (void) printf("\n");
1579 1586 state->us_first = B_TRUE;
1580 1587 }
1581 1588 }
1582 1589 return (DLADM_STATUS_OK);
1583 1590 }
1584 1591
1585 1592 bzero(&ubuf, sizeof (ubuf));
1586 1593
1587 1594 (void) snprintf(ubuf.usage_l_link, sizeof (ubuf.usage_l_link), "%s",
1588 1595 usage->du_name);
1589 1596 time = usage->du_stime;
1590 1597 (void) strftime(buf, sizeof (buf), "%T", localtime(&time));
1591 1598 (void) snprintf(ubuf.usage_l_stime, sizeof (ubuf.usage_l_stime), "%s",
1592 1599 buf);
1593 1600 time = usage->du_etime;
1594 1601 (void) strftime(buf, sizeof (buf), "%T", localtime(&time));
1595 1602 (void) snprintf(ubuf.usage_l_etime, sizeof (ubuf.usage_l_etime), "%s",
1596 1603 buf);
1597 1604 (void) snprintf(ubuf.usage_l_rbytes, sizeof (ubuf.usage_l_rbytes),
1598 1605 "%llu", usage->du_rbytes);
1599 1606 (void) snprintf(ubuf.usage_l_obytes, sizeof (ubuf.usage_l_obytes),
1600 1607 "%llu", usage->du_obytes);
1601 1608 (void) snprintf(ubuf.usage_l_bandwidth, sizeof (ubuf.usage_l_bandwidth),
1602 1609 "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
1603 1610
1604 1611 ofmt_print(state->us_ofmt, &ubuf);
1605 1612 return (DLADM_STATUS_OK);
1606 1613 }
1607 1614
1608 1615 static int
1609 1616 show_usage_res(dladm_usage_t *usage, void *arg)
1610 1617 {
1611 1618 show_usage_state_t *state = (show_usage_state_t *)arg;
1612 1619 char buf[DLADM_STRSIZE];
1613 1620 usage_fields_buf_t ubuf;
1614 1621 dladm_status_t status;
1615 1622 uint32_t flags;
1616 1623
1617 1624 /*
1618 1625 * Only show usage information for existing links unless '-a'
1619 1626 * is specified.
1620 1627 */
1621 1628 if (!state->us_showall) {
1622 1629 if ((status = dladm_name2info(handle, usage->du_name,
1623 1630 NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
1624 1631 return (status);
1625 1632 }
1626 1633 if ((flags & DLADM_OPT_ACTIVE) == 0)
1627 1634 return (DLADM_STATUS_LINKINVAL);
1628 1635 }
1629 1636
1630 1637 bzero(&ubuf, sizeof (ubuf));
1631 1638
1632 1639 (void) snprintf(ubuf.usage_link, sizeof (ubuf.usage_link), "%s",
1633 1640 usage->du_name);
1634 1641 (void) snprintf(ubuf.usage_duration, sizeof (ubuf.usage_duration),
1635 1642 "%llu", usage->du_duration);
1636 1643 (void) snprintf(ubuf.usage_ipackets, sizeof (ubuf.usage_ipackets),
1637 1644 "%llu", usage->du_ipackets);
1638 1645 (void) snprintf(ubuf.usage_rbytes, sizeof (ubuf.usage_rbytes),
1639 1646 "%llu", usage->du_rbytes);
1640 1647 (void) snprintf(ubuf.usage_opackets, sizeof (ubuf.usage_opackets),
1641 1648 "%llu", usage->du_opackets);
1642 1649 (void) snprintf(ubuf.usage_obytes, sizeof (ubuf.usage_obytes),
1643 1650 "%llu", usage->du_obytes);
1644 1651 (void) snprintf(ubuf.usage_bandwidth, sizeof (ubuf.usage_bandwidth),
1645 1652 "%s Mbps", dladm_bw2str(usage->du_bandwidth, buf));
1646 1653
1647 1654 ofmt_print(state->us_ofmt, &ubuf);
1648 1655
1649 1656 return (DLADM_STATUS_OK);
1650 1657 }
1651 1658
1652 1659 static boolean_t
1653 1660 valid_formatspec(char *formatspec_str)
1654 1661 {
1655 1662 if (strcmp(formatspec_str, "gnuplot") == 0)
1656 1663 return (B_TRUE);
1657 1664 return (B_FALSE);
1658 1665
1659 1666 }
1660 1667
1661 1668 /*ARGSUSED*/
1662 1669 static void
1663 1670 do_show_usage(int argc, char *argv[], const char *use)
1664 1671 {
1665 1672 char *file = NULL;
1666 1673 int opt;
1667 1674 dladm_status_t status;
1668 1675 boolean_t d_arg = B_FALSE;
1669 1676 char *stime = NULL;
1670 1677 char *etime = NULL;
1671 1678 char *resource = NULL;
1672 1679 show_usage_state_t state;
1673 1680 boolean_t o_arg = B_FALSE;
1674 1681 boolean_t F_arg = B_FALSE;
1675 1682 char *fields_str = NULL;
1676 1683 char *formatspec_str = NULL;
1677 1684 char *all_l_fields =
1678 1685 "link,start,end,rbytes,obytes,bandwidth";
1679 1686 ofmt_handle_t ofmt;
1680 1687 ofmt_status_t oferr;
1681 1688 uint_t ofmtflags = 0;
1682 1689
1683 1690 bzero(&state, sizeof (show_usage_state_t));
1684 1691 state.us_parsable = B_FALSE;
1685 1692 state.us_printheader = B_FALSE;
1686 1693 state.us_plot = B_FALSE;
1687 1694 state.us_first = B_TRUE;
1688 1695
1689 1696 while ((opt = getopt_long(argc, argv, "das:e:o:f:F:",
1690 1697 usage_opts, NULL)) != -1) {
1691 1698 switch (opt) {
1692 1699 case 'd':
1693 1700 d_arg = B_TRUE;
1694 1701 break;
1695 1702 case 'a':
1696 1703 state.us_showall = B_TRUE;
1697 1704 break;
1698 1705 case 'f':
1699 1706 file = optarg;
1700 1707 break;
1701 1708 case 's':
1702 1709 stime = optarg;
1703 1710 break;
1704 1711 case 'e':
1705 1712 etime = optarg;
1706 1713 break;
1707 1714 case 'o':
1708 1715 o_arg = B_TRUE;
1709 1716 fields_str = optarg;
1710 1717 break;
1711 1718 case 'F':
1712 1719 state.us_plot = F_arg = B_TRUE;
1713 1720 formatspec_str = optarg;
1714 1721 break;
1715 1722 default:
1716 1723 die_opterr(optopt, opt, use);
1717 1724 break;
1718 1725 }
1719 1726 }
1720 1727
1721 1728 if (file == NULL)
1722 1729 die("show-usage requires a file");
1723 1730
1724 1731 if (optind == (argc-1)) {
1725 1732 uint32_t flags;
1726 1733
1727 1734 resource = argv[optind];
1728 1735 if (!state.us_showall &&
1729 1736 (((status = dladm_name2info(handle, resource, NULL, &flags,
1730 1737 NULL, NULL)) != DLADM_STATUS_OK) ||
1731 1738 ((flags & DLADM_OPT_ACTIVE) == 0))) {
1732 1739 die("invalid link: '%s'", resource);
1733 1740 }
1734 1741 }
1735 1742
1736 1743 if (F_arg && d_arg)
1737 1744 die("incompatible -d and -F options");
1738 1745
1739 1746 if (F_arg && valid_formatspec(formatspec_str) == B_FALSE)
1740 1747 die("Format specifier %s not supported", formatspec_str);
1741 1748
1742 1749 if (state.us_parsable)
1743 1750 ofmtflags |= OFMT_PARSABLE;
1744 1751
1745 1752 if (resource == NULL && stime == NULL && etime == NULL) {
1746 1753 oferr = ofmt_open(fields_str, usage_fields, ofmtflags, 0,
1747 1754 &ofmt);
1748 1755 } else {
1749 1756 if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
1750 1757 fields_str = all_l_fields;
1751 1758 oferr = ofmt_open(fields_str, usage_l_fields, ofmtflags, 0,
1752 1759 &ofmt);
1753 1760
1754 1761 }
1755 1762 dladm_ofmt_check(oferr, state.us_parsable, ofmt);
1756 1763 state.us_ofmt = ofmt;
1757 1764
1758 1765 if (d_arg) {
1759 1766 /* Print log dates */
1760 1767 status = dladm_usage_dates(show_usage_date,
1761 1768 DLADM_LOGTYPE_LINK, file, resource, &state);
1762 1769 } else if (resource == NULL && stime == NULL && etime == NULL &&
1763 1770 !F_arg) {
1764 1771 /* Print summary */
1765 1772 status = dladm_usage_summary(show_usage_res,
1766 1773 DLADM_LOGTYPE_LINK, file, &state);
1767 1774 } else if (resource != NULL) {
1768 1775 /* Print log entries for named resource */
1769 1776 status = dladm_walk_usage_res(show_usage_time,
1770 1777 DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state);
1771 1778 } else {
1772 1779 /* Print time and information for each link */
1773 1780 status = dladm_walk_usage_time(show_usage_time,
1774 1781 DLADM_LOGTYPE_LINK, file, stime, etime, &state);
1775 1782 }
1776 1783
1777 1784 if (status != DLADM_STATUS_OK)
1778 1785 die_dlerr(status, "show-usage");
1779 1786 ofmt_close(ofmt);
1780 1787 }
1781 1788
1782 1789 static void
1783 1790 do_create_aggr(int argc, char *argv[], const char *use)
1784 1791 {
1785 1792 int option;
1786 1793 int key = 0;
1787 1794 uint32_t policy = AGGR_POLICY_L4;
1788 1795 aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF;
1789 1796 aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT;
1790 1797 dladm_aggr_port_attr_db_t port[MAXPORT];
1791 1798 uint_t n, ndev, nlink;
1792 1799 uint8_t mac_addr[ETHERADDRL];
1793 1800 boolean_t mac_addr_fixed = B_FALSE;
1794 1801 boolean_t P_arg = B_FALSE;
1795 1802 boolean_t l_arg = B_FALSE;
1796 1803 boolean_t u_arg = B_FALSE;
1797 1804 boolean_t T_arg = B_FALSE;
1798 1805 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
1799 1806 char *altroot = NULL;
1800 1807 char name[MAXLINKNAMELEN];
1801 1808 char *devs[MAXPORT];
1802 1809 char *links[MAXPORT];
1803 1810 dladm_status_t status;
1804 1811 dladm_status_t pstatus;
1805 1812 char propstr[DLADM_STRSIZE];
1806 1813 dladm_arg_list_t *proplist = NULL;
1807 1814 int i;
1808 1815 datalink_id_t linkid;
1809 1816
1810 1817 ndev = nlink = opterr = 0;
1811 1818 bzero(propstr, DLADM_STRSIZE);
1812 1819
1813 1820 while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:p:",
1814 1821 lopts, NULL)) != -1) {
1815 1822 switch (option) {
1816 1823 case 'd':
1817 1824 if (ndev + nlink >= MAXPORT)
1818 1825 die("too many ports specified");
1819 1826
1820 1827 devs[ndev++] = optarg;
1821 1828 break;
1822 1829 case 'P':
1823 1830 if (P_arg)
1824 1831 die_optdup(option);
1825 1832
1826 1833 P_arg = B_TRUE;
1827 1834 if (!dladm_aggr_str2policy(optarg, &policy))
1828 1835 die("invalid policy '%s'", optarg);
1829 1836 break;
1830 1837 case 'u':
1831 1838 if (u_arg)
1832 1839 die_optdup(option);
1833 1840
1834 1841 u_arg = B_TRUE;
1835 1842 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed,
1836 1843 mac_addr))
1837 1844 die("invalid MAC address '%s'", optarg);
1838 1845 break;
1839 1846 case 'l':
1840 1847 if (isdigit(optarg[strlen(optarg) - 1])) {
1841 1848
1842 1849 /*
1843 1850 * Ended with digit, possibly a link name.
1844 1851 */
1845 1852 if (ndev + nlink >= MAXPORT)
1846 1853 die("too many ports specified");
1847 1854
1848 1855 links[nlink++] = optarg;
1849 1856 break;
1850 1857 }
1851 1858 /* FALLTHROUGH */
1852 1859 case 'L':
1853 1860 if (l_arg)
1854 1861 die_optdup(option);
1855 1862
1856 1863 l_arg = B_TRUE;
1857 1864 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode))
1858 1865 die("invalid LACP mode '%s'", optarg);
1859 1866 break;
1860 1867 case 'T':
1861 1868 if (T_arg)
1862 1869 die_optdup(option);
1863 1870
1864 1871 T_arg = B_TRUE;
1865 1872 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer))
1866 1873 die("invalid LACP timer value '%s'", optarg);
1867 1874 break;
1868 1875 case 't':
1869 1876 flags &= ~DLADM_OPT_PERSIST;
1870 1877 break;
1871 1878 case 'f':
1872 1879 flags |= DLADM_OPT_FORCE;
1873 1880 break;
1874 1881 case 'R':
1875 1882 altroot = optarg;
1876 1883 break;
1877 1884 case 'p':
1878 1885 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
1879 1886 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
1880 1887 DLADM_STRSIZE)
1881 1888 die("property list too long '%s'", propstr);
1882 1889 break;
1883 1890
1884 1891 default:
1885 1892 die_opterr(optopt, option, use);
1886 1893 break;
1887 1894 }
1888 1895 }
1889 1896
1890 1897 if (ndev + nlink == 0)
1891 1898 usage();
1892 1899
1893 1900 /* get key value or the aggregation name (required last argument) */
1894 1901 if (optind != (argc-1))
1895 1902 usage();
1896 1903
1897 1904 if (!str2int(argv[optind], &key)) {
1898 1905 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >=
1899 1906 MAXLINKNAMELEN) {
1900 1907 die("link name too long '%s'", argv[optind]);
1901 1908 }
1902 1909
1903 1910 if (!dladm_valid_linkname(name))
1904 1911 die("invalid link name '%s'", argv[optind]);
1905 1912 } else {
1906 1913 (void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key);
1907 1914 }
1908 1915
1909 1916 if (altroot != NULL)
1910 1917 altroot_cmd(altroot, argc, argv);
1911 1918
1912 1919 for (n = 0; n < ndev; n++) {
1913 1920 if ((status = dladm_dev2linkid(handle, devs[n],
1914 1921 &port[n].lp_linkid)) != DLADM_STATUS_OK) {
1915 1922 die_dlerr(status, "invalid dev name '%s'", devs[n]);
1916 1923 }
1917 1924 }
1918 1925
1919 1926 for (n = 0; n < nlink; n++) {
1920 1927 if ((status = dladm_name2info(handle, links[n],
1921 1928 &port[ndev + n].lp_linkid, NULL, NULL, NULL)) !=
1922 1929 DLADM_STATUS_OK) {
1923 1930 die_dlerr(status, "invalid link name '%s'", links[n]);
1924 1931 }
1925 1932 }
1926 1933
1927 1934 status = dladm_aggr_create(handle, name, key, ndev + nlink, port,
1928 1935 policy, mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode,
1929 1936 lacp_timer, flags);
1930 1937 if (status != DLADM_STATUS_OK)
1931 1938 goto done;
1932 1939
1933 1940 if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
1934 1941 != DLADM_STATUS_OK)
1935 1942 die("invalid aggregation property");
1936 1943
1937 1944 if (proplist == NULL)
1938 1945 return;
1939 1946
1940 1947 status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL);
1941 1948 if (status != DLADM_STATUS_OK)
1942 1949 goto done;
1943 1950
1944 1951 for (i = 0; i < proplist->al_count; i++) {
1945 1952 dladm_arg_info_t *aip = &proplist->al_info[i];
1946 1953
1947 1954 pstatus = dladm_set_linkprop(handle, linkid, aip->ai_name,
1948 1955 aip->ai_val, aip->ai_count, flags);
1949 1956
1950 1957 if (pstatus != DLADM_STATUS_OK) {
1951 1958 die_dlerr(pstatus,
1952 1959 "aggr creation succeeded but "
1953 1960 "could not set property '%s'", aip->ai_name);
1954 1961 }
1955 1962 }
1956 1963 done:
1957 1964 dladm_free_props(proplist);
1958 1965 if (status != DLADM_STATUS_OK) {
1959 1966 if (status == DLADM_STATUS_NONOTIF) {
1960 1967 die("not all links have link up/down detection; must "
1961 1968 "use -f (see dladm(1M))");
1962 1969 } else {
1963 1970 die_dlerr(status, "create operation failed");
1964 1971 }
1965 1972 }
1966 1973 }
1967 1974
1968 1975 /*
1969 1976 * arg is either the key or the aggr name. Validate it and convert it to
1970 1977 * the linkid if altroot is NULL.
1971 1978 */
1972 1979 static dladm_status_t
1973 1980 i_dladm_aggr_get_linkid(const char *altroot, const char *arg,
1974 1981 datalink_id_t *linkidp, uint32_t flags)
1975 1982 {
1976 1983 int key = 0;
1977 1984 char *aggr = NULL;
1978 1985 dladm_status_t status;
1979 1986
1980 1987 if (!str2int(arg, &key))
1981 1988 aggr = (char *)arg;
1982 1989
1983 1990 if (aggr == NULL && key == 0)
1984 1991 return (DLADM_STATUS_LINKINVAL);
1985 1992
1986 1993 if (altroot != NULL)
1987 1994 return (DLADM_STATUS_OK);
1988 1995
1989 1996 if (aggr != NULL) {
1990 1997 status = dladm_name2info(handle, aggr, linkidp, NULL, NULL,
1991 1998 NULL);
1992 1999 } else {
1993 2000 status = dladm_key2linkid(handle, key, linkidp, flags);
1994 2001 }
1995 2002
1996 2003 return (status);
1997 2004 }
1998 2005
1999 2006 static void
2000 2007 do_delete_aggr(int argc, char *argv[], const char *use)
2001 2008 {
2002 2009 int option;
2003 2010 char *altroot = NULL;
2004 2011 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
2005 2012 dladm_status_t status;
2006 2013 datalink_id_t linkid;
2007 2014
2008 2015 opterr = 0;
2009 2016 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) {
2010 2017 switch (option) {
2011 2018 case 't':
2012 2019 flags &= ~DLADM_OPT_PERSIST;
2013 2020 break;
2014 2021 case 'R':
2015 2022 altroot = optarg;
2016 2023 break;
2017 2024 default:
2018 2025 die_opterr(optopt, option, use);
2019 2026 break;
2020 2027 }
2021 2028 }
2022 2029
2023 2030 /* get key value or the aggregation name (required last argument) */
2024 2031 if (optind != (argc-1))
2025 2032 usage();
2026 2033
2027 2034 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
2028 2035 if (status != DLADM_STATUS_OK)
2029 2036 goto done;
2030 2037
2031 2038 if (altroot != NULL)
2032 2039 altroot_cmd(altroot, argc, argv);
2033 2040
2034 2041 status = dladm_aggr_delete(handle, linkid, flags);
2035 2042 done:
2036 2043 if (status != DLADM_STATUS_OK)
2037 2044 die_dlerr(status, "delete operation failed");
2038 2045 }
2039 2046
2040 2047 static void
2041 2048 do_add_aggr(int argc, char *argv[], const char *use)
2042 2049 {
2043 2050 int option;
2044 2051 uint_t n, ndev, nlink;
2045 2052 char *altroot = NULL;
2046 2053 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
2047 2054 datalink_id_t linkid;
2048 2055 dladm_status_t status;
2049 2056 dladm_aggr_port_attr_db_t port[MAXPORT];
2050 2057 char *devs[MAXPORT];
2051 2058 char *links[MAXPORT];
2052 2059
2053 2060 ndev = nlink = opterr = 0;
2054 2061 while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts,
2055 2062 NULL)) != -1) {
2056 2063 switch (option) {
2057 2064 case 'd':
2058 2065 if (ndev + nlink >= MAXPORT)
2059 2066 die("too many ports specified");
2060 2067
2061 2068 devs[ndev++] = optarg;
2062 2069 break;
2063 2070 case 'l':
2064 2071 if (ndev + nlink >= MAXPORT)
2065 2072 die("too many ports specified");
2066 2073
2067 2074 links[nlink++] = optarg;
2068 2075 break;
2069 2076 case 't':
2070 2077 flags &= ~DLADM_OPT_PERSIST;
2071 2078 break;
2072 2079 case 'f':
2073 2080 flags |= DLADM_OPT_FORCE;
2074 2081 break;
2075 2082 case 'R':
2076 2083 altroot = optarg;
2077 2084 break;
2078 2085 default:
2079 2086 die_opterr(optopt, option, use);
2080 2087 break;
2081 2088 }
2082 2089 }
2083 2090
2084 2091 if (ndev + nlink == 0)
2085 2092 usage();
2086 2093
2087 2094 /* get key value or the aggregation name (required last argument) */
2088 2095 if (optind != (argc-1))
2089 2096 usage();
2090 2097
2091 2098 if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid,
2092 2099 flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) !=
2093 2100 DLADM_STATUS_OK) {
2094 2101 goto done;
2095 2102 }
2096 2103
2097 2104 if (altroot != NULL)
2098 2105 altroot_cmd(altroot, argc, argv);
2099 2106
2100 2107 for (n = 0; n < ndev; n++) {
2101 2108 if ((status = dladm_dev2linkid(handle, devs[n],
2102 2109 &(port[n].lp_linkid))) != DLADM_STATUS_OK) {
2103 2110 die_dlerr(status, "invalid <dev> '%s'", devs[n]);
2104 2111 }
2105 2112 }
2106 2113
2107 2114 for (n = 0; n < nlink; n++) {
2108 2115 if ((status = dladm_name2info(handle, links[n],
2109 2116 &port[n + ndev].lp_linkid, NULL, NULL, NULL)) !=
2110 2117 DLADM_STATUS_OK) {
2111 2118 die_dlerr(status, "invalid <link> '%s'", links[n]);
2112 2119 }
2113 2120 }
2114 2121
2115 2122 status = dladm_aggr_add(handle, linkid, ndev + nlink, port, flags);
2116 2123 done:
2117 2124 if (status != DLADM_STATUS_OK) {
2118 2125 /*
2119 2126 * checking DLADM_STATUS_NOTSUP is a temporary workaround
2120 2127 * and should be removed once 6399681 is fixed.
2121 2128 */
2122 2129 if (status == DLADM_STATUS_NOTSUP) {
2123 2130 die("add operation failed: link capabilities don't "
2124 2131 "match");
2125 2132 } else if (status == DLADM_STATUS_NONOTIF) {
2126 2133 die("not all links have link up/down detection; must "
2127 2134 "use -f (see dladm(1M))");
2128 2135 } else {
2129 2136 die_dlerr(status, "add operation failed");
2130 2137 }
2131 2138 }
2132 2139 }
2133 2140
2134 2141 static void
2135 2142 do_remove_aggr(int argc, char *argv[], const char *use)
2136 2143 {
2137 2144 int option;
2138 2145 dladm_aggr_port_attr_db_t port[MAXPORT];
2139 2146 uint_t n, ndev, nlink;
2140 2147 char *devs[MAXPORT];
2141 2148 char *links[MAXPORT];
2142 2149 char *altroot = NULL;
2143 2150 uint32_t flags;
2144 2151 datalink_id_t linkid;
2145 2152 dladm_status_t status;
2146 2153
2147 2154 flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
2148 2155 ndev = nlink = opterr = 0;
2149 2156 while ((option = getopt_long(argc, argv, ":d:l:R:t",
2150 2157 lopts, NULL)) != -1) {
2151 2158 switch (option) {
2152 2159 case 'd':
2153 2160 if (ndev + nlink >= MAXPORT)
2154 2161 die("too many ports specified");
2155 2162
2156 2163 devs[ndev++] = optarg;
2157 2164 break;
2158 2165 case 'l':
2159 2166 if (ndev + nlink >= MAXPORT)
2160 2167 die("too many ports specified");
2161 2168
2162 2169 links[nlink++] = optarg;
2163 2170 break;
2164 2171 case 't':
2165 2172 flags &= ~DLADM_OPT_PERSIST;
2166 2173 break;
2167 2174 case 'R':
2168 2175 altroot = optarg;
2169 2176 break;
2170 2177 default:
2171 2178 die_opterr(optopt, option, use);
2172 2179 break;
2173 2180 }
2174 2181 }
2175 2182
2176 2183 if (ndev + nlink == 0)
2177 2184 usage();
2178 2185
2179 2186 /* get key value or the aggregation name (required last argument) */
2180 2187 if (optind != (argc-1))
2181 2188 usage();
2182 2189
2183 2190 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
2184 2191 if (status != DLADM_STATUS_OK)
2185 2192 goto done;
2186 2193
2187 2194 if (altroot != NULL)
2188 2195 altroot_cmd(altroot, argc, argv);
2189 2196
2190 2197 for (n = 0; n < ndev; n++) {
2191 2198 if ((status = dladm_dev2linkid(handle, devs[n],
2192 2199 &(port[n].lp_linkid))) != DLADM_STATUS_OK) {
2193 2200 die_dlerr(status, "invalid <dev> '%s'", devs[n]);
2194 2201 }
2195 2202 }
2196 2203
2197 2204 for (n = 0; n < nlink; n++) {
2198 2205 if ((status = dladm_name2info(handle, links[n],
2199 2206 &port[n + ndev].lp_linkid, NULL, NULL, NULL)) !=
2200 2207 DLADM_STATUS_OK) {
2201 2208 die_dlerr(status, "invalid <link> '%s'", links[n]);
2202 2209 }
2203 2210 }
2204 2211
2205 2212 status = dladm_aggr_remove(handle, linkid, ndev + nlink, port, flags);
2206 2213 done:
2207 2214 if (status != DLADM_STATUS_OK)
2208 2215 die_dlerr(status, "remove operation failed");
2209 2216 }
2210 2217
2211 2218 static void
2212 2219 do_modify_aggr(int argc, char *argv[], const char *use)
2213 2220 {
2214 2221 int option;
2215 2222 uint32_t policy = AGGR_POLICY_L4;
2216 2223 aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF;
2217 2224 aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT;
2218 2225 uint8_t mac_addr[ETHERADDRL];
2219 2226 boolean_t mac_addr_fixed = B_FALSE;
2220 2227 uint8_t modify_mask = 0;
2221 2228 char *altroot = NULL;
2222 2229 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
2223 2230 datalink_id_t linkid;
2224 2231 dladm_status_t status;
2225 2232
2226 2233 opterr = 0;
2227 2234 while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts,
2228 2235 NULL)) != -1) {
2229 2236 switch (option) {
2230 2237 case 'P':
2231 2238 if (modify_mask & DLADM_AGGR_MODIFY_POLICY)
2232 2239 die_optdup(option);
2233 2240
2234 2241 modify_mask |= DLADM_AGGR_MODIFY_POLICY;
2235 2242
2236 2243 if (!dladm_aggr_str2policy(optarg, &policy))
2237 2244 die("invalid policy '%s'", optarg);
2238 2245 break;
2239 2246 case 'u':
2240 2247 if (modify_mask & DLADM_AGGR_MODIFY_MAC)
2241 2248 die_optdup(option);
2242 2249
2243 2250 modify_mask |= DLADM_AGGR_MODIFY_MAC;
2244 2251
2245 2252 if (!dladm_aggr_str2macaddr(optarg, &mac_addr_fixed,
2246 2253 mac_addr))
2247 2254 die("invalid MAC address '%s'", optarg);
2248 2255 break;
2249 2256 case 'l':
2250 2257 case 'L':
2251 2258 if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE)
2252 2259 die_optdup(option);
2253 2260
2254 2261 modify_mask |= DLADM_AGGR_MODIFY_LACP_MODE;
2255 2262
2256 2263 if (!dladm_aggr_str2lacpmode(optarg, &lacp_mode))
2257 2264 die("invalid LACP mode '%s'", optarg);
2258 2265 break;
2259 2266 case 'T':
2260 2267 if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER)
2261 2268 die_optdup(option);
2262 2269
2263 2270 modify_mask |= DLADM_AGGR_MODIFY_LACP_TIMER;
2264 2271
2265 2272 if (!dladm_aggr_str2lacptimer(optarg, &lacp_timer))
2266 2273 die("invalid LACP timer value '%s'", optarg);
2267 2274 break;
2268 2275 case 't':
2269 2276 flags &= ~DLADM_OPT_PERSIST;
2270 2277 break;
2271 2278 case 'R':
2272 2279 altroot = optarg;
2273 2280 break;
2274 2281 default:
2275 2282 die_opterr(optopt, option, use);
2276 2283 break;
2277 2284 }
2278 2285 }
2279 2286
2280 2287 if (modify_mask == 0)
2281 2288 die("at least one of the -PulT options must be specified");
2282 2289
2283 2290 /* get key value or the aggregation name (required last argument) */
2284 2291 if (optind != (argc-1))
2285 2292 usage();
2286 2293
2287 2294 status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
2288 2295 if (status != DLADM_STATUS_OK)
2289 2296 goto done;
2290 2297
2291 2298 if (altroot != NULL)
2292 2299 altroot_cmd(altroot, argc, argv);
2293 2300
2294 2301 status = dladm_aggr_modify(handle, linkid, modify_mask, policy,
2295 2302 mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode, lacp_timer,
2296 2303 flags);
2297 2304
2298 2305 done:
2299 2306 if (status != DLADM_STATUS_OK)
2300 2307 die_dlerr(status, "modify operation failed");
2301 2308 }
2302 2309
2303 2310 /*ARGSUSED*/
2304 2311 static void
2305 2312 do_up_aggr(int argc, char *argv[], const char *use)
2306 2313 {
2307 2314 datalink_id_t linkid = DATALINK_ALL_LINKID;
2308 2315 dladm_status_t status;
2309 2316
2310 2317 /*
2311 2318 * get the key or the name of the aggregation (optional last argument)
2312 2319 */
2313 2320 if (argc == 2) {
2314 2321 if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid,
2315 2322 DLADM_OPT_PERSIST)) != DLADM_STATUS_OK)
2316 2323 goto done;
2317 2324 } else if (argc > 2) {
2318 2325 usage();
2319 2326 }
2320 2327
2321 2328 status = dladm_aggr_up(handle, linkid);
2322 2329 done:
2323 2330 if (status != DLADM_STATUS_OK) {
2324 2331 if (argc == 2) {
2325 2332 die_dlerr(status,
2326 2333 "could not bring up aggregation '%s'", argv[1]);
2327 2334 } else {
2328 2335 die_dlerr(status, "could not bring aggregations up");
2329 2336 }
2330 2337 }
2331 2338 }
2332 2339
2333 2340 static void
2334 2341 do_create_vlan(int argc, char *argv[], const char *use)
2335 2342 {
2336 2343 char *link = NULL;
2337 2344 char drv[DLPI_LINKNAME_MAX];
2338 2345 uint_t ppa;
2339 2346 datalink_id_t linkid;
2340 2347 datalink_id_t dev_linkid;
2341 2348 int vid = 0;
2342 2349 int option;
2343 2350 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
2344 2351 char *altroot = NULL;
2345 2352 char vlan[MAXLINKNAMELEN];
2346 2353 char propstr[DLADM_STRSIZE];
2347 2354 dladm_arg_list_t *proplist = NULL;
2348 2355 dladm_status_t status;
2349 2356
2350 2357 opterr = 0;
2351 2358 bzero(propstr, DLADM_STRSIZE);
2352 2359
2353 2360 while ((option = getopt_long(argc, argv, ":tfR:l:v:p:",
2354 2361 lopts, NULL)) != -1) {
2355 2362 switch (option) {
2356 2363 case 'v':
2357 2364 if (vid != 0)
2358 2365 die_optdup(option);
2359 2366
2360 2367 if (!str2int(optarg, &vid) || vid < 1 || vid > 4094)
2361 2368 die("invalid VLAN identifier '%s'", optarg);
2362 2369
2363 2370 break;
2364 2371 case 'l':
2365 2372 if (link != NULL)
2366 2373 die_optdup(option);
2367 2374
2368 2375 link = optarg;
2369 2376 break;
2370 2377 case 't':
2371 2378 flags &= ~DLADM_OPT_PERSIST;
2372 2379 break;
2373 2380 case 'R':
2374 2381 altroot = optarg;
2375 2382 break;
2376 2383 case 'p':
2377 2384 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
2378 2385 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
2379 2386 DLADM_STRSIZE)
2380 2387 die("property list too long '%s'", propstr);
2381 2388 break;
2382 2389 case 'f':
2383 2390 flags |= DLADM_OPT_FORCE;
2384 2391 break;
2385 2392 default:
2386 2393 die_opterr(optopt, option, use);
2387 2394 break;
2388 2395 }
2389 2396 }
2390 2397
2391 2398 /* get vlan name if there is any */
2392 2399 if ((vid == 0) || (link == NULL) || (argc - optind > 1))
2393 2400 usage();
2394 2401
2395 2402 if (optind == (argc - 1)) {
2396 2403 if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >=
2397 2404 MAXLINKNAMELEN) {
2398 2405 die("vlan name too long '%s'", argv[optind]);
2399 2406 }
2400 2407 } else {
2401 2408 if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) ||
2402 2409 (ppa >= 1000) ||
2403 2410 (dlpi_makelink(vlan, drv, vid * 1000 + ppa) !=
2404 2411 DLPI_SUCCESS)) {
2405 2412 die("invalid link name '%s'", link);
2406 2413 }
2407 2414 }
2408 2415
2409 2416 if (altroot != NULL)
2410 2417 altroot_cmd(altroot, argc, argv);
2411 2418
2412 2419 if (dladm_name2info(handle, link, &dev_linkid, NULL, NULL, NULL) !=
2413 2420 DLADM_STATUS_OK) {
2414 2421 die("invalid link name '%s'", link);
2415 2422 }
2416 2423
2417 2424 if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
2418 2425 != DLADM_STATUS_OK)
2419 2426 die("invalid vlan property");
2420 2427
2421 2428 status = dladm_vlan_create(handle, vlan, dev_linkid, vid, proplist,
2422 2429 flags, &linkid);
2423 2430 switch (status) {
2424 2431 case DLADM_STATUS_OK:
2425 2432 break;
2426 2433
2427 2434 case DLADM_STATUS_NOTSUP:
2428 2435 die("VLAN over '%s' may require lowered MTU; must use -f (see "
2429 2436 "dladm(1M))", link);
2430 2437 break;
2431 2438
2432 2439 case DLADM_STATUS_LINKBUSY:
2433 2440 die("VLAN over '%s' may not use default_tag ID "
2434 2441 "(see dladm(1M))", link);
2435 2442 break;
2436 2443
2437 2444 default:
2438 2445 die_dlerr(status, "create operation failed");
2439 2446 }
2440 2447 }
2441 2448
2442 2449 static void
2443 2450 do_delete_vlan(int argc, char *argv[], const char *use)
2444 2451 {
2445 2452 int option;
2446 2453 uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
2447 2454 char *altroot = NULL;
2448 2455 datalink_id_t linkid;
2449 2456 dladm_status_t status;
2450 2457
2451 2458 opterr = 0;
2452 2459 while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) {
2453 2460 switch (option) {
2454 2461 case 't':
2455 2462 flags &= ~DLADM_OPT_PERSIST;
2456 2463 break;
2457 2464 case 'R':
2458 2465 altroot = optarg;
2459 2466 break;
2460 2467 default:
2461 2468 die_opterr(optopt, option, use);
2462 2469 break;
2463 2470 }
2464 2471 }
2465 2472
2466 2473 /* get VLAN link name (required last argument) */
2467 2474 if (optind != (argc - 1))
2468 2475 usage();
2469 2476
2470 2477 if (altroot != NULL)
2471 2478 altroot_cmd(altroot, argc, argv);
2472 2479
2473 2480 status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
2474 2481 NULL);
2475 2482 if (status != DLADM_STATUS_OK)
2476 2483 goto done;
2477 2484
2478 2485 status = dladm_vlan_delete(handle, linkid, flags);
2479 2486 done:
2480 2487 if (status != DLADM_STATUS_OK)
2481 2488 die_dlerr(status, "delete operation failed");
2482 2489 }
2483 2490
2484 2491 /*ARGSUSED*/
2485 2492 static void
2486 2493 do_up_vlan(int argc, char *argv[], const char *use)
2487 2494 {
|
↓ open down ↓ |
1449 lines elided |
↑ open up ↑ |
2488 2495 do_up_vnic_common(argc, argv, use, B_TRUE);
2489 2496 }
2490 2497
2491 2498 static void
2492 2499 do_rename_link(int argc, char *argv[], const char *use)
2493 2500 {
2494 2501 int option;
2495 2502 char *link1, *link2;
2496 2503 char *altroot = NULL;
2497 2504 dladm_status_t status;
2505 + char *zonename = NULL;
2498 2506
2499 2507 opterr = 0;
2500 - while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) {
2508 + while ((option = getopt_long(argc, argv, ":R:z:", lopts, NULL)) != -1) {
2501 2509 switch (option) {
2502 2510 case 'R':
2503 2511 altroot = optarg;
2504 2512 break;
2513 + case 'z':
2514 + zonename = optarg;
2515 + break;
2505 2516 default:
2506 2517 die_opterr(optopt, option, use);
2507 2518 break;
2508 2519 }
2509 2520 }
2510 2521
2511 2522 /* get link1 and link2 name (required the last 2 arguments) */
2512 2523 if (optind != (argc - 2))
2513 2524 usage();
2514 2525
2515 2526 if (altroot != NULL)
2516 2527 altroot_cmd(altroot, argc, argv);
2517 2528
2518 2529 link1 = argv[optind++];
2519 2530 link2 = argv[optind];
2520 - if ((status = dladm_rename_link(handle, link1, link2)) !=
2531 + if ((status = dladm_rename_link(handle, zonename, link1, link2)) !=
2521 2532 DLADM_STATUS_OK)
2522 2533 die_dlerr(status, "rename operation failed");
2523 2534 }
2524 2535
2525 2536 /*ARGSUSED*/
2526 2537 static void
2527 2538 do_delete_phys(int argc, char *argv[], const char *use)
2528 2539 {
2529 2540 datalink_id_t linkid = DATALINK_ALL_LINKID;
2530 2541 dladm_status_t status;
2531 2542
2532 2543 /* get link name (required the last argument) */
2533 2544 if (argc > 2)
2534 2545 usage();
2535 2546
2536 2547 if (argc == 2) {
2537 2548 if ((status = dladm_name2info(handle, argv[1], &linkid, NULL,
2538 2549 NULL, NULL)) != DLADM_STATUS_OK)
2539 2550 die_dlerr(status, "cannot delete '%s'", argv[1]);
2540 2551 }
2541 2552
2542 2553 if ((status = dladm_phys_delete(handle, linkid)) != DLADM_STATUS_OK) {
2543 2554 if (argc == 2)
2544 2555 die_dlerr(status, "cannot delete '%s'", argv[1]);
2545 2556 else
2546 2557 die_dlerr(status, "delete operation failed");
2547 2558 }
2548 2559 }
2549 2560
2550 2561 /*ARGSUSED*/
2551 2562 static int
2552 2563 i_dladm_walk_linkmap(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2553 2564 {
2554 2565 char name[MAXLINKNAMELEN];
2555 2566 char mediabuf[DLADM_STRSIZE];
2556 2567 char classbuf[DLADM_STRSIZE];
2557 2568 datalink_class_t class;
2558 2569 uint32_t media;
2559 2570 uint32_t flags;
2560 2571
2561 2572 if (dladm_datalink_id2info(dh, linkid, &flags, &class, &media, name,
2562 2573 MAXLINKNAMELEN) == DLADM_STATUS_OK) {
2563 2574 (void) dladm_class2str(class, classbuf);
2564 2575 (void) dladm_media2str(media, mediabuf);
2565 2576 (void) printf("%-12s%8d %-12s%-20s %6d\n", name,
2566 2577 linkid, classbuf, mediabuf, flags);
2567 2578 }
2568 2579 return (DLADM_WALK_CONTINUE);
2569 2580 }
2570 2581
2571 2582 /*ARGSUSED*/
2572 2583 static void
2573 2584 do_show_linkmap(int argc, char *argv[], const char *use)
2574 2585 {
2575 2586 if (argc != 1)
2576 2587 die("invalid arguments");
2577 2588
2578 2589 (void) printf("%-12s%8s %-12s%-20s %6s\n", "NAME", "LINKID",
2579 2590 "CLASS", "MEDIA", "FLAGS");
2580 2591
2581 2592 (void) dladm_walk_datalink_id(i_dladm_walk_linkmap, handle, NULL,
2582 2593 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
2583 2594 DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
2584 2595 }
2585 2596
2586 2597 /*
2587 2598 * Delete inactive physical links.
2588 2599 */
2589 2600 /*ARGSUSED*/
2590 2601 static int
2591 2602 purge_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2592 2603 {
2593 2604 datalink_class_t class;
2594 2605 uint32_t flags;
2595 2606
2596 2607 if (dladm_datalink_id2info(dh, linkid, &flags, &class, NULL, NULL, 0)
2597 2608 != DLADM_STATUS_OK) {
2598 2609 return (DLADM_WALK_CONTINUE);
2599 2610 }
2600 2611
2601 2612 if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE))
2602 2613 (void) dladm_phys_delete(dh, linkid);
2603 2614
2604 2615 return (DLADM_WALK_CONTINUE);
2605 2616 }
2606 2617
2607 2618 /*ARGSUSED*/
2608 2619 static void
2609 2620 do_init_phys(int argc, char *argv[], const char *use)
2610 2621 {
2611 2622 di_node_t devtree;
2612 2623
2613 2624 if (argc > 1)
2614 2625 usage();
2615 2626
2616 2627 /*
2617 2628 * Force all the devices to attach, therefore all the network physical
2618 2629 * devices can be known to the dlmgmtd daemon.
2619 2630 */
2620 2631 if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL)
2621 2632 di_fini(devtree);
2622 2633
2623 2634 (void) dladm_walk_datalink_id(purge_phys, handle, NULL,
2624 2635 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
2625 2636 }
2626 2637
2627 2638 /*
2628 2639 * Print the active topology information.
2629 2640 */
2630 2641 void
2631 2642 print_link_topology(show_state_t *state, datalink_id_t linkid,
2632 2643 datalink_class_t class, link_fields_buf_t *lbuf)
2633 2644 {
2634 2645 uint32_t flags = state->ls_flags;
2635 2646 dladm_status_t status;
2636 2647 char tmpbuf[MAXLINKNAMELEN];
2637 2648
2638 2649 lbuf->link_over[0] = '\0';
2639 2650 lbuf->link_bridge[0] = '\0';
2640 2651
2641 2652 switch (class) {
2642 2653 case DATALINK_CLASS_AGGR:
2643 2654 case DATALINK_CLASS_PHYS:
2644 2655 case DATALINK_CLASS_ETHERSTUB:
2645 2656 status = dladm_bridge_getlink(handle, linkid, lbuf->link_bridge,
2646 2657 sizeof (lbuf->link_bridge));
2647 2658 if (status != DLADM_STATUS_OK &&
2648 2659 status != DLADM_STATUS_NOTFOUND)
2649 2660 (void) strcpy(lbuf->link_bridge, "?");
2650 2661 break;
2651 2662 }
2652 2663
2653 2664 switch (class) {
2654 2665 case DATALINK_CLASS_VLAN: {
2655 2666 dladm_vlan_attr_t vinfo;
2656 2667
2657 2668 if (dladm_vlan_info(handle, linkid, &vinfo, flags) !=
2658 2669 DLADM_STATUS_OK) {
2659 2670 (void) strcpy(lbuf->link_over, "?");
2660 2671 break;
2661 2672 }
2662 2673 if (dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL, NULL,
2663 2674 NULL, lbuf->link_over, sizeof (lbuf->link_over)) !=
2664 2675 DLADM_STATUS_OK)
2665 2676 (void) strcpy(lbuf->link_over, "?");
2666 2677 break;
2667 2678 }
2668 2679 case DATALINK_CLASS_AGGR: {
2669 2680 dladm_aggr_grp_attr_t ginfo;
2670 2681 int i;
2671 2682
2672 2683 if (dladm_aggr_info(handle, linkid, &ginfo, flags) !=
2673 2684 DLADM_STATUS_OK || ginfo.lg_nports == 0) {
2674 2685 (void) strcpy(lbuf->link_over, "?");
2675 2686 break;
2676 2687 }
2677 2688 for (i = 0; i < ginfo.lg_nports; i++) {
2678 2689 if (dladm_datalink_id2info(handle,
2679 2690 ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL,
2680 2691 tmpbuf, sizeof (tmpbuf)) != DLADM_STATUS_OK) {
2681 2692 (void) strcpy(lbuf->link_over, "?");
2682 2693 break;
2683 2694 }
2684 2695 (void) strlcat(lbuf->link_over, tmpbuf,
2685 2696 sizeof (lbuf->link_over));
2686 2697 if (i != (ginfo.lg_nports - 1)) {
2687 2698 (void) strlcat(lbuf->link_over, " ",
2688 2699 sizeof (lbuf->link_over));
2689 2700 }
2690 2701 }
2691 2702 free(ginfo.lg_ports);
2692 2703 break;
2693 2704 }
2694 2705 case DATALINK_CLASS_VNIC: {
2695 2706 dladm_vnic_attr_t vinfo;
2696 2707
2697 2708 if (dladm_vnic_info(handle, linkid, &vinfo, flags) !=
2698 2709 DLADM_STATUS_OK) {
2699 2710 (void) strcpy(lbuf->link_over, "?");
2700 2711 break;
2701 2712 }
2702 2713 if (dladm_datalink_id2info(handle, vinfo.va_link_id, NULL, NULL,
2703 2714 NULL, lbuf->link_over, sizeof (lbuf->link_over)) !=
2704 2715 DLADM_STATUS_OK)
2705 2716 (void) strcpy(lbuf->link_over, "?");
2706 2717 break;
2707 2718 }
2708 2719
2709 2720 case DATALINK_CLASS_PART: {
2710 2721 dladm_part_attr_t pinfo;
2711 2722
2712 2723 if (dladm_part_info(handle, linkid, &pinfo, flags) !=
2713 2724 DLADM_STATUS_OK) {
2714 2725 (void) strcpy(lbuf->link_over, "?");
2715 2726 break;
2716 2727 }
2717 2728 if (dladm_datalink_id2info(handle, pinfo.dia_physlinkid, NULL,
2718 2729 NULL, NULL, lbuf->link_over, sizeof (lbuf->link_over)) !=
2719 2730 DLADM_STATUS_OK)
2720 2731 (void) strcpy(lbuf->link_over, "?");
2721 2732 break;
2722 2733 }
2723 2734
2724 2735 case DATALINK_CLASS_BRIDGE: {
2725 2736 datalink_id_t *dlp;
2726 2737 uint_t i, nports;
2727 2738
2728 2739 if (dladm_datalink_id2info(handle, linkid, NULL, NULL,
2729 2740 NULL, tmpbuf, sizeof (tmpbuf)) != DLADM_STATUS_OK) {
2730 2741 (void) strcpy(lbuf->link_over, "?");
2731 2742 break;
2732 2743 }
2733 2744 if (tmpbuf[0] != '\0')
2734 2745 tmpbuf[strlen(tmpbuf) - 1] = '\0';
2735 2746 dlp = dladm_bridge_get_portlist(tmpbuf, &nports);
2736 2747 if (dlp == NULL) {
2737 2748 (void) strcpy(lbuf->link_over, "?");
2738 2749 break;
2739 2750 }
2740 2751 for (i = 0; i < nports; i++) {
2741 2752 if (dladm_datalink_id2info(handle, dlp[i], NULL,
2742 2753 NULL, NULL, tmpbuf, sizeof (tmpbuf)) !=
2743 2754 DLADM_STATUS_OK) {
2744 2755 (void) strcpy(lbuf->link_over, "?");
2745 2756 break;
2746 2757 }
2747 2758 (void) strlcat(lbuf->link_over, tmpbuf,
2748 2759 sizeof (lbuf->link_over));
2749 2760 if (i != nports - 1) {
2750 2761 (void) strlcat(lbuf->link_over, " ",
2751 2762 sizeof (lbuf->link_over));
2752 2763 }
2753 2764 }
2754 2765 dladm_bridge_free_portlist(dlp);
2755 2766 break;
2756 2767 }
2757 2768
2758 2769 case DATALINK_CLASS_SIMNET: {
2759 2770 dladm_simnet_attr_t slinfo;
2760 2771
2761 2772 if (dladm_simnet_info(handle, linkid, &slinfo, flags) !=
2762 2773 DLADM_STATUS_OK) {
2763 2774 (void) strcpy(lbuf->link_over, "?");
2764 2775 break;
2765 2776 }
2766 2777 if (slinfo.sna_peer_link_id != DATALINK_INVALID_LINKID) {
2767 2778 if (dladm_datalink_id2info(handle,
2768 2779 slinfo.sna_peer_link_id, NULL, NULL, NULL,
2769 2780 lbuf->link_over, sizeof (lbuf->link_over)) !=
2770 2781 DLADM_STATUS_OK)
2771 2782 (void) strcpy(lbuf->link_over, "?");
2772 2783 }
2773 2784 break;
2774 2785 }
2775 2786 }
2776 2787 }
2777 2788
2778 2789 static dladm_status_t
2779 2790 print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf)
2780 2791 {
2781 2792 char link[MAXLINKNAMELEN];
2782 2793 datalink_class_t class;
2783 2794 uint_t mtu;
2784 2795 uint32_t flags;
2785 2796 dladm_status_t status;
2786 2797
2787 2798 if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
2788 2799 NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
2789 2800 goto done;
2790 2801 }
2791 2802
2792 2803 if (!(state->ls_flags & flags)) {
2793 2804 status = DLADM_STATUS_NOTFOUND;
2794 2805 goto done;
2795 2806 }
2796 2807
2797 2808 if (state->ls_flags == DLADM_OPT_ACTIVE) {
2798 2809 dladm_attr_t dlattr;
2799 2810
2800 2811 if (class == DATALINK_CLASS_PHYS) {
2801 2812 dladm_phys_attr_t dpa;
2802 2813 dlpi_handle_t dh;
2803 2814 dlpi_info_t dlinfo;
2804 2815
2805 2816 if ((status = dladm_phys_info(handle, linkid, &dpa,
2806 2817 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
2807 2818 goto done;
2808 2819 }
2809 2820
2810 2821 if (!dpa.dp_novanity)
2811 2822 goto link_mtu;
2812 2823
2813 2824 /*
2814 2825 * This is a physical link that does not have
2815 2826 * vanity naming support.
2816 2827 */
2817 2828 if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) !=
2818 2829 DLPI_SUCCESS) {
2819 2830 status = DLADM_STATUS_NOTFOUND;
2820 2831 goto done;
2821 2832 }
2822 2833
2823 2834 if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) {
2824 2835 dlpi_close(dh);
2825 2836 status = DLADM_STATUS_BADARG;
2826 2837 goto done;
2827 2838 }
2828 2839
2829 2840 dlpi_close(dh);
2830 2841 mtu = dlinfo.di_max_sdu;
2831 2842 } else {
2832 2843 link_mtu:
2833 2844 status = dladm_info(handle, linkid, &dlattr);
2834 2845 if (status != DLADM_STATUS_OK)
2835 2846 goto done;
2836 2847 mtu = dlattr.da_max_sdu;
2837 2848 }
2838 2849 }
2839 2850
2840 2851 (void) snprintf(lbuf->link_name, sizeof (lbuf->link_name),
2841 2852 "%s", link);
2842 2853 (void) dladm_class2str(class, lbuf->link_class);
2843 2854 if (state->ls_flags == DLADM_OPT_ACTIVE) {
2844 2855 (void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu),
2845 2856 "%u", mtu);
2846 2857 (void) get_linkstate(link, B_TRUE, lbuf->link_state);
2847 2858 }
2848 2859
2849 2860 print_link_topology(state, linkid, class, lbuf);
2850 2861 done:
2851 2862 return (status);
2852 2863 }
2853 2864
2854 2865 /* ARGSUSED */
2855 2866 static int
2856 2867 show_link(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2857 2868 {
2858 2869 show_state_t *state = (show_state_t *)arg;
2859 2870 dladm_status_t status;
2860 2871 link_fields_buf_t lbuf;
2861 2872
2862 2873 /*
2863 2874 * first get all the link attributes into lbuf;
2864 2875 */
2865 2876 bzero(&lbuf, sizeof (link_fields_buf_t));
2866 2877 if ((status = print_link(state, linkid, &lbuf)) == DLADM_STATUS_OK)
2867 2878 ofmt_print(state->ls_ofmt, &lbuf);
2868 2879 state->ls_status = status;
2869 2880 return (DLADM_WALK_CONTINUE);
2870 2881 }
2871 2882
2872 2883 static boolean_t
2873 2884 print_link_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2874 2885 {
2875 2886 link_args_t *largs = ofarg->ofmt_cbarg;
2876 2887 pktsum_t *diff_stats = largs->link_s_psum;
2877 2888
2878 2889 switch (ofarg->ofmt_id) {
2879 2890 case LINK_S_LINK:
2880 2891 (void) snprintf(buf, bufsize, "%s", largs->link_s_link);
2881 2892 break;
2882 2893 case LINK_S_IPKTS:
2883 2894 (void) snprintf(buf, bufsize, "%llu", diff_stats->ipackets);
2884 2895 break;
2885 2896 case LINK_S_RBYTES:
2886 2897 (void) snprintf(buf, bufsize, "%llu", diff_stats->rbytes);
2887 2898 break;
2888 2899 case LINK_S_IERRORS:
2889 2900 (void) snprintf(buf, bufsize, "%u", diff_stats->ierrors);
2890 2901 break;
2891 2902 case LINK_S_OPKTS:
2892 2903 (void) snprintf(buf, bufsize, "%llu", diff_stats->opackets);
2893 2904 break;
2894 2905 case LINK_S_OBYTES:
2895 2906 (void) snprintf(buf, bufsize, "%llu", diff_stats->obytes);
2896 2907 break;
2897 2908 case LINK_S_OERRORS:
2898 2909 (void) snprintf(buf, bufsize, "%u", diff_stats->oerrors);
2899 2910 break;
2900 2911 default:
2901 2912 die("invalid input");
2902 2913 break;
2903 2914 }
2904 2915 return (B_TRUE);
2905 2916 }
2906 2917
2907 2918 static int
2908 2919 show_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
2909 2920 {
2910 2921 char link[DLPI_LINKNAME_MAX];
2911 2922 datalink_class_t class;
2912 2923 show_state_t *state = arg;
2913 2924 pktsum_t stats, diff_stats;
2914 2925 dladm_phys_attr_t dpa;
2915 2926 link_args_t largs;
2916 2927
2917 2928 if (state->ls_firstonly) {
2918 2929 if (state->ls_donefirst)
2919 2930 return (DLADM_WALK_CONTINUE);
2920 2931 state->ls_donefirst = B_TRUE;
2921 2932 } else {
2922 2933 bzero(&state->ls_prevstats, sizeof (state->ls_prevstats));
2923 2934 }
2924 2935
2925 2936 if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, link,
2926 2937 DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
2927 2938 return (DLADM_WALK_CONTINUE);
2928 2939 }
2929 2940
2930 2941 if (class == DATALINK_CLASS_PHYS) {
2931 2942 if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) !=
2932 2943 DLADM_STATUS_OK) {
2933 2944 return (DLADM_WALK_CONTINUE);
2934 2945 }
2935 2946 if (dpa.dp_novanity)
2936 2947 get_mac_stats(dpa.dp_dev, &stats);
2937 2948 else
2938 2949 get_link_stats(link, &stats);
2939 2950 } else {
2940 2951 get_link_stats(link, &stats);
2941 2952 }
2942 2953 dladm_stats_diff(&diff_stats, &stats, &state->ls_prevstats);
2943 2954
2944 2955 largs.link_s_link = link;
2945 2956 largs.link_s_psum = &diff_stats;
2946 2957 ofmt_print(state->ls_ofmt, &largs);
2947 2958
2948 2959 state->ls_prevstats = stats;
2949 2960 return (DLADM_WALK_CONTINUE);
2950 2961 }
2951 2962
2952 2963
2953 2964 static dladm_status_t
2954 2965 print_aggr_info(show_grp_state_t *state, const char *link,
2955 2966 dladm_aggr_grp_attr_t *ginfop)
2956 2967 {
2957 2968 char addr_str[ETHERADDRL * 3];
2958 2969 laggr_fields_buf_t lbuf;
2959 2970
2960 2971 (void) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name),
2961 2972 "%s", link);
2962 2973
2963 2974 (void) dladm_aggr_policy2str(ginfop->lg_policy,
2964 2975 lbuf.laggr_policy);
2965 2976
2966 2977 if (ginfop->lg_mac_fixed) {
2967 2978 (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str);
2968 2979 (void) snprintf(lbuf.laggr_addrpolicy,
2969 2980 sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str);
2970 2981 } else {
2971 2982 (void) snprintf(lbuf.laggr_addrpolicy,
2972 2983 sizeof (lbuf.laggr_addrpolicy), "auto");
2973 2984 }
2974 2985
2975 2986 (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode,
2976 2987 lbuf.laggr_lacpactivity);
2977 2988 (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer,
2978 2989 lbuf.laggr_lacptimer);
2979 2990 (void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----",
2980 2991 ginfop->lg_force ? 'f' : '-');
2981 2992
2982 2993 ofmt_print(state->gs_ofmt, &lbuf);
2983 2994
2984 2995 return (DLADM_STATUS_OK);
2985 2996 }
2986 2997
2987 2998 static boolean_t
2988 2999 print_xaggr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2989 3000 {
2990 3001 const laggr_args_t *l = ofarg->ofmt_cbarg;
2991 3002 boolean_t is_port = (l->laggr_lport >= 0);
2992 3003 char tmpbuf[DLADM_STRSIZE];
2993 3004 const char *objname;
2994 3005 dladm_aggr_port_attr_t *portp;
2995 3006 dladm_phys_attr_t dpa;
2996 3007
2997 3008 if (is_port) {
2998 3009 portp = &(l->laggr_ginfop->lg_ports[l->laggr_lport]);
2999 3010 if (dladm_phys_info(handle, portp->lp_linkid, &dpa,
3000 3011 DLADM_OPT_ACTIVE) != DLADM_STATUS_OK)
3001 3012 objname = "?";
3002 3013 else
3003 3014 objname = dpa.dp_dev;
3004 3015 } else {
3005 3016 objname = l->laggr_link;
3006 3017 }
3007 3018
3008 3019 switch (ofarg->ofmt_id) {
3009 3020 case AGGR_X_LINK:
3010 3021 (void) snprintf(buf, bufsize, "%s",
3011 3022 (is_port && !l->laggr_parsable ? " " : l->laggr_link));
3012 3023 break;
3013 3024 case AGGR_X_PORT:
3014 3025 if (is_port) {
3015 3026 if (dladm_datalink_id2info(handle, portp->lp_linkid,
3016 3027 NULL, NULL, NULL, buf, bufsize) != DLADM_STATUS_OK)
3017 3028 (void) sprintf(buf, "?");
3018 3029 }
3019 3030 break;
3020 3031
3021 3032 case AGGR_X_SPEED:
3022 3033 (void) snprintf(buf, bufsize, "%uMb",
3023 3034 (uint_t)((get_ifspeed(objname, !is_port)) / 1000000ull));
3024 3035 break;
3025 3036
3026 3037 case AGGR_X_DUPLEX:
3027 3038 (void) get_linkduplex(objname, !is_port, tmpbuf);
3028 3039 (void) strlcpy(buf, tmpbuf, bufsize);
3029 3040 break;
3030 3041
3031 3042 case AGGR_X_STATE:
3032 3043 (void) get_linkstate(objname, !is_port, tmpbuf);
3033 3044 (void) strlcpy(buf, tmpbuf, bufsize);
3034 3045 break;
3035 3046 case AGGR_X_ADDRESS:
3036 3047 (void) dladm_aggr_macaddr2str(
3037 3048 (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac),
3038 3049 tmpbuf);
3039 3050 (void) strlcpy(buf, tmpbuf, bufsize);
3040 3051 break;
3041 3052 case AGGR_X_PORTSTATE:
3042 3053 if (is_port) {
3043 3054 (void) dladm_aggr_portstate2str(portp->lp_state,
3044 3055 tmpbuf);
3045 3056 (void) strlcpy(buf, tmpbuf, bufsize);
3046 3057 }
3047 3058 break;
3048 3059 }
3049 3060 err:
3050 3061 *(l->laggr_status) = DLADM_STATUS_OK;
3051 3062 return (B_TRUE);
3052 3063 }
3053 3064
3054 3065 static dladm_status_t
3055 3066 print_aggr_extended(show_grp_state_t *state, const char *link,
3056 3067 dladm_aggr_grp_attr_t *ginfop)
3057 3068 {
3058 3069 int i;
3059 3070 dladm_status_t status;
3060 3071 laggr_args_t largs;
3061 3072
3062 3073 largs.laggr_lport = -1;
3063 3074 largs.laggr_link = link;
3064 3075 largs.laggr_ginfop = ginfop;
3065 3076 largs.laggr_status = &status;
3066 3077 largs.laggr_parsable = state->gs_parsable;
3067 3078
3068 3079 ofmt_print(state->gs_ofmt, &largs);
3069 3080
3070 3081 if (status != DLADM_STATUS_OK)
3071 3082 goto done;
3072 3083
3073 3084 for (i = 0; i < ginfop->lg_nports; i++) {
3074 3085 largs.laggr_lport = i;
3075 3086 ofmt_print(state->gs_ofmt, &largs);
3076 3087 if (status != DLADM_STATUS_OK)
3077 3088 goto done;
3078 3089 }
3079 3090
3080 3091 status = DLADM_STATUS_OK;
3081 3092 done:
3082 3093 return (status);
3083 3094 }
3084 3095
3085 3096 static boolean_t
3086 3097 print_lacp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3087 3098 {
3088 3099 const laggr_args_t *l = ofarg->ofmt_cbarg;
3089 3100 int portnum;
3090 3101 boolean_t is_port = (l->laggr_lport >= 0);
3091 3102 dladm_aggr_port_attr_t *portp;
3092 3103 aggr_lacp_state_t *lstate;
3093 3104
3094 3105 if (!is_port)
3095 3106 return (B_FALSE); /* cannot happen! */
3096 3107
3097 3108 portnum = l->laggr_lport;
3098 3109 portp = &(l->laggr_ginfop->lg_ports[portnum]);
3099 3110 lstate = &(portp->lp_lacp_state);
3100 3111
3101 3112 switch (ofarg->ofmt_id) {
3102 3113 case AGGR_L_LINK:
3103 3114 (void) snprintf(buf, bufsize, "%s",
3104 3115 (portnum > 0 ? "" : l->laggr_link));
3105 3116 break;
3106 3117
3107 3118 case AGGR_L_PORT:
3108 3119 if (dladm_datalink_id2info(handle, portp->lp_linkid, NULL, NULL,
3109 3120 NULL, buf, bufsize) != DLADM_STATUS_OK)
3110 3121 (void) sprintf(buf, "?");
3111 3122 break;
3112 3123
3113 3124 case AGGR_L_AGGREGATABLE:
3114 3125 (void) snprintf(buf, bufsize, "%s",
3115 3126 (lstate->bit.aggregation ? "yes" : "no"));
3116 3127 break;
3117 3128
3118 3129 case AGGR_L_SYNC:
3119 3130 (void) snprintf(buf, bufsize, "%s",
3120 3131 (lstate->bit.sync ? "yes" : "no"));
3121 3132 break;
3122 3133
3123 3134 case AGGR_L_COLL:
3124 3135 (void) snprintf(buf, bufsize, "%s",
3125 3136 (lstate->bit.collecting ? "yes" : "no"));
3126 3137 break;
3127 3138
3128 3139 case AGGR_L_DIST:
3129 3140 (void) snprintf(buf, bufsize, "%s",
3130 3141 (lstate->bit.distributing ? "yes" : "no"));
3131 3142 break;
3132 3143
3133 3144 case AGGR_L_DEFAULTED:
3134 3145 (void) snprintf(buf, bufsize, "%s",
3135 3146 (lstate->bit.defaulted ? "yes" : "no"));
3136 3147 break;
3137 3148
3138 3149 case AGGR_L_EXPIRED:
3139 3150 (void) snprintf(buf, bufsize, "%s",
3140 3151 (lstate->bit.expired ? "yes" : "no"));
3141 3152 break;
3142 3153 }
3143 3154
3144 3155 *(l->laggr_status) = DLADM_STATUS_OK;
3145 3156 return (B_TRUE);
3146 3157 }
3147 3158
3148 3159 static dladm_status_t
3149 3160 print_aggr_lacp(show_grp_state_t *state, const char *link,
3150 3161 dladm_aggr_grp_attr_t *ginfop)
3151 3162 {
3152 3163 int i;
3153 3164 dladm_status_t status;
3154 3165 laggr_args_t largs;
3155 3166
3156 3167 largs.laggr_link = link;
3157 3168 largs.laggr_ginfop = ginfop;
3158 3169 largs.laggr_status = &status;
3159 3170
3160 3171 for (i = 0; i < ginfop->lg_nports; i++) {
3161 3172 largs.laggr_lport = i;
3162 3173 ofmt_print(state->gs_ofmt, &largs);
3163 3174 if (status != DLADM_STATUS_OK)
3164 3175 goto done;
3165 3176 }
3166 3177
3167 3178 status = DLADM_STATUS_OK;
3168 3179 done:
3169 3180 return (status);
3170 3181 }
3171 3182
3172 3183 static boolean_t
3173 3184 print_aggr_stats_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3174 3185 {
3175 3186 const laggr_args_t *l = ofarg->ofmt_cbarg;
3176 3187 int portnum;
3177 3188 boolean_t is_port = (l->laggr_lport >= 0);
3178 3189 dladm_aggr_port_attr_t *portp;
3179 3190 dladm_status_t *stat, status;
3180 3191 pktsum_t *diff_stats;
3181 3192
3182 3193 stat = l->laggr_status;
3183 3194 *stat = DLADM_STATUS_OK;
3184 3195
3185 3196 if (is_port) {
3186 3197 portnum = l->laggr_lport;
3187 3198 portp = &(l->laggr_ginfop->lg_ports[portnum]);
3188 3199
3189 3200 if ((status = dladm_datalink_id2info(handle,
3190 3201 portp->lp_linkid, NULL, NULL, NULL, buf, bufsize)) !=
3191 3202 DLADM_STATUS_OK) {
3192 3203 goto err;
3193 3204 }
3194 3205 diff_stats = l->laggr_diffstats;
3195 3206 }
3196 3207
3197 3208 switch (ofarg->ofmt_id) {
3198 3209 case AGGR_S_LINK:
3199 3210 (void) snprintf(buf, bufsize, "%s",
3200 3211 (is_port ? "" : l->laggr_link));
3201 3212 break;
3202 3213 case AGGR_S_PORT:
3203 3214 /*
3204 3215 * if (is_port), buf has port name. Otherwise we print
3205 3216 * STR_UNDEF_VAL
3206 3217 */
3207 3218 break;
3208 3219
3209 3220 case AGGR_S_IPKTS:
3210 3221 if (is_port) {
3211 3222 (void) snprintf(buf, bufsize, "%llu",
3212 3223 diff_stats->ipackets);
3213 3224 } else {
3214 3225 (void) snprintf(buf, bufsize, "%llu",
3215 3226 l->laggr_pktsumtot->ipackets);
3216 3227 }
3217 3228 break;
3218 3229
3219 3230 case AGGR_S_RBYTES:
3220 3231 if (is_port) {
3221 3232 (void) snprintf(buf, bufsize, "%llu",
3222 3233 diff_stats->rbytes);
3223 3234 } else {
3224 3235 (void) snprintf(buf, bufsize, "%llu",
3225 3236 l->laggr_pktsumtot->rbytes);
3226 3237 }
3227 3238 break;
3228 3239
3229 3240 case AGGR_S_OPKTS:
3230 3241 if (is_port) {
3231 3242 (void) snprintf(buf, bufsize, "%llu",
3232 3243 diff_stats->opackets);
3233 3244 } else {
3234 3245 (void) snprintf(buf, bufsize, "%llu",
3235 3246 l->laggr_pktsumtot->opackets);
3236 3247 }
3237 3248 break;
3238 3249 case AGGR_S_OBYTES:
3239 3250 if (is_port) {
3240 3251 (void) snprintf(buf, bufsize, "%llu",
3241 3252 diff_stats->obytes);
3242 3253 } else {
3243 3254 (void) snprintf(buf, bufsize, "%llu",
3244 3255 l->laggr_pktsumtot->obytes);
3245 3256 }
3246 3257 break;
3247 3258
3248 3259 case AGGR_S_IPKTDIST:
3249 3260 if (is_port) {
3250 3261 (void) snprintf(buf, bufsize, "%-6.1f",
3251 3262 (double)diff_stats->ipackets/
3252 3263 (double)l->laggr_pktsumtot->ipackets * 100);
3253 3264 }
3254 3265 break;
3255 3266 case AGGR_S_OPKTDIST:
3256 3267 if (is_port) {
3257 3268 (void) snprintf(buf, bufsize, "%-6.1f",
3258 3269 (double)diff_stats->opackets/
3259 3270 (double)l->laggr_pktsumtot->opackets * 100);
3260 3271 }
3261 3272 break;
3262 3273 }
3263 3274 return (B_TRUE);
3264 3275
3265 3276 err:
3266 3277 *stat = status;
3267 3278 return (B_TRUE);
3268 3279 }
3269 3280
3270 3281 static dladm_status_t
3271 3282 print_aggr_stats(show_grp_state_t *state, const char *link,
3272 3283 dladm_aggr_grp_attr_t *ginfop)
3273 3284 {
3274 3285 dladm_phys_attr_t dpa;
3275 3286 dladm_aggr_port_attr_t *portp;
3276 3287 pktsum_t pktsumtot, *port_stat;
3277 3288 dladm_status_t status;
3278 3289 int i;
3279 3290 laggr_args_t largs;
3280 3291
3281 3292 /* sum the ports statistics */
3282 3293 bzero(&pktsumtot, sizeof (pktsumtot));
3283 3294
3284 3295 /* Allocate memory to keep stats of each port */
3285 3296 port_stat = malloc(ginfop->lg_nports * sizeof (pktsum_t));
3286 3297 if (port_stat == NULL) {
3287 3298 /* Bail out; no memory */
3288 3299 return (DLADM_STATUS_NOMEM);
3289 3300 }
3290 3301
3291 3302
3292 3303 for (i = 0; i < ginfop->lg_nports; i++) {
3293 3304
3294 3305 portp = &(ginfop->lg_ports[i]);
3295 3306 if ((status = dladm_phys_info(handle, portp->lp_linkid, &dpa,
3296 3307 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
3297 3308 goto done;
3298 3309 }
3299 3310
3300 3311 get_mac_stats(dpa.dp_dev, &port_stat[i]);
3301 3312
3302 3313 /*
3303 3314 * Let's re-use gs_prevstats[] to store the difference of the
3304 3315 * counters since last use. We will store the new stats from
3305 3316 * port_stat[] once we have the stats displayed.
3306 3317 */
3307 3318
3308 3319 dladm_stats_diff(&state->gs_prevstats[i], &port_stat[i],
3309 3320 &state->gs_prevstats[i]);
3310 3321 dladm_stats_total(&pktsumtot, &pktsumtot,
3311 3322 &state->gs_prevstats[i]);
3312 3323 }
3313 3324
3314 3325 largs.laggr_lport = -1;
3315 3326 largs.laggr_link = link;
3316 3327 largs.laggr_ginfop = ginfop;
3317 3328 largs.laggr_status = &status;
3318 3329 largs.laggr_pktsumtot = &pktsumtot;
3319 3330
3320 3331 ofmt_print(state->gs_ofmt, &largs);
3321 3332
3322 3333 if (status != DLADM_STATUS_OK)
3323 3334 goto done;
3324 3335
3325 3336 for (i = 0; i < ginfop->lg_nports; i++) {
3326 3337 largs.laggr_lport = i;
3327 3338 largs.laggr_diffstats = &state->gs_prevstats[i];
3328 3339 ofmt_print(state->gs_ofmt, &largs);
3329 3340 if (status != DLADM_STATUS_OK)
3330 3341 goto done;
3331 3342 }
3332 3343
3333 3344 status = DLADM_STATUS_OK;
3334 3345 for (i = 0; i < ginfop->lg_nports; i++)
3335 3346 state->gs_prevstats[i] = port_stat[i];
3336 3347
3337 3348 done:
3338 3349 free(port_stat);
3339 3350 return (status);
3340 3351 }
3341 3352
3342 3353 static dladm_status_t
3343 3354 print_aggr(show_grp_state_t *state, datalink_id_t linkid)
3344 3355 {
3345 3356 char link[MAXLINKNAMELEN];
3346 3357 dladm_aggr_grp_attr_t ginfo;
3347 3358 uint32_t flags;
3348 3359 dladm_status_t status;
3349 3360
3350 3361 bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t));
3351 3362 if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
3352 3363 NULL, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
3353 3364 return (status);
3354 3365 }
3355 3366
3356 3367 if (!(state->gs_flags & flags))
3357 3368 return (DLADM_STATUS_NOTFOUND);
3358 3369
3359 3370 status = dladm_aggr_info(handle, linkid, &ginfo, state->gs_flags);
3360 3371 if (status != DLADM_STATUS_OK)
3361 3372 return (status);
3362 3373
3363 3374 if (state->gs_lacp)
3364 3375 status = print_aggr_lacp(state, link, &ginfo);
3365 3376 else if (state->gs_extended)
3366 3377 status = print_aggr_extended(state, link, &ginfo);
3367 3378 else if (state->gs_stats)
3368 3379 status = print_aggr_stats(state, link, &ginfo);
3369 3380 else
3370 3381 status = print_aggr_info(state, link, &ginfo);
3371 3382
3372 3383 done:
3373 3384 free(ginfo.lg_ports);
3374 3385 return (status);
3375 3386 }
3376 3387
3377 3388 /* ARGSUSED */
3378 3389 static int
3379 3390 show_aggr(dladm_handle_t dh, datalink_id_t linkid, void *arg)
3380 3391 {
3381 3392 show_grp_state_t *state = arg;
3382 3393
3383 3394 state->gs_status = print_aggr(state, linkid);
3384 3395 return (DLADM_WALK_CONTINUE);
3385 3396 }
3386 3397
3387 3398 static void
3388 3399 do_show_link(int argc, char *argv[], const char *use)
3389 3400 {
3390 3401 int option;
3391 3402 boolean_t s_arg = B_FALSE;
3392 3403 boolean_t S_arg = B_FALSE;
3393 3404 boolean_t i_arg = B_FALSE;
3394 3405 uint32_t flags = DLADM_OPT_ACTIVE;
3395 3406 boolean_t p_arg = B_FALSE;
3396 3407 datalink_id_t linkid = DATALINK_ALL_LINKID;
3397 3408 char linkname[MAXLINKNAMELEN];
3398 3409 uint32_t interval = 0;
3399 3410 show_state_t state;
|
↓ open down ↓ |
869 lines elided |
↑ open up ↑ |
3400 3411 dladm_status_t status;
3401 3412 boolean_t o_arg = B_FALSE;
3402 3413 char *fields_str = NULL;
3403 3414 char *all_active_fields = "link,class,mtu,state,bridge,over";
3404 3415 char *all_inactive_fields = "link,class,bridge,over";
3405 3416 char *allstat_fields =
3406 3417 "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors";
3407 3418 ofmt_handle_t ofmt;
3408 3419 ofmt_status_t oferr;
3409 3420 uint_t ofmtflags = 0;
3421 + char *zonename = NULL;
3410 3422
3411 3423 bzero(&state, sizeof (state));
3412 3424
3413 3425 opterr = 0;
3414 - while ((option = getopt_long(argc, argv, ":pPsSi:o:",
3426 + while ((option = getopt_long(argc, argv, ":pPsSi:o:z:",
3415 3427 show_lopts, NULL)) != -1) {
3416 3428 switch (option) {
3417 3429 case 'p':
3418 3430 if (p_arg)
3419 3431 die_optdup(option);
3420 3432
3421 3433 p_arg = B_TRUE;
3422 3434 break;
3423 3435 case 's':
3424 3436 if (s_arg)
3425 3437 die_optdup(option);
3426 3438
3427 3439 s_arg = B_TRUE;
3428 3440 break;
3429 3441 case 'P':
3430 3442 if (flags != DLADM_OPT_ACTIVE)
3431 3443 die_optdup(option);
3432 3444
3433 3445 flags = DLADM_OPT_PERSIST;
3434 3446 break;
3435 3447 case 'S':
3436 3448 if (S_arg)
3437 3449 die_optdup(option);
3438 3450
3439 3451 S_arg = B_TRUE;
3440 3452 break;
3441 3453 case 'o':
3442 3454 o_arg = B_TRUE;
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
3443 3455 fields_str = optarg;
3444 3456 break;
3445 3457 case 'i':
3446 3458 if (i_arg)
3447 3459 die_optdup(option);
3448 3460
3449 3461 i_arg = B_TRUE;
3450 3462 if (!dladm_str2interval(optarg, &interval))
3451 3463 die("invalid interval value '%s'", optarg);
3452 3464 break;
3465 + case 'z':
3466 + zonename = optarg;
3467 + break;
3453 3468 default:
3454 3469 die_opterr(optopt, option, use);
3455 3470 break;
3456 3471 }
3457 3472 }
3458 3473
3459 3474 if (i_arg && !(s_arg || S_arg))
3460 3475 die("the option -i can be used only with -s or -S");
3461 3476
3462 3477 if (s_arg && S_arg)
3463 3478 die("the -s option cannot be used with -S");
3464 3479
3465 3480 if (s_arg && flags != DLADM_OPT_ACTIVE)
3466 3481 die("the option -P cannot be used with -s");
3467 3482
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
3468 3483 if (S_arg && (p_arg || flags != DLADM_OPT_ACTIVE))
3469 3484 die("the option -%c cannot be used with -S", p_arg ? 'p' : 'P');
3470 3485
3471 3486 /* get link name (optional last argument) */
3472 3487 if (optind == (argc-1)) {
3473 3488 uint32_t f;
3474 3489
3475 3490 if (strlcpy(linkname, argv[optind], MAXLINKNAMELEN) >=
3476 3491 MAXLINKNAMELEN)
3477 3492 die("link name too long");
3478 - if ((status = dladm_name2info(handle, linkname, &linkid, &f,
3479 - NULL, NULL)) != DLADM_STATUS_OK) {
3493 + if ((status = dladm_zname2info(handle, zonename, linkname,
3494 + &linkid, &f, NULL, NULL)) != DLADM_STATUS_OK) {
3480 3495 die_dlerr(status, "link %s is not valid", linkname);
3481 3496 }
3482 3497
3483 3498 if (!(f & flags)) {
3484 3499 die_dlerr(DLADM_STATUS_BADARG, "link %s is %s",
3485 3500 argv[optind], flags == DLADM_OPT_PERSIST ?
3486 3501 "a temporary link" : "temporarily removed");
3487 3502 }
3488 3503 } else if (optind != argc) {
3489 3504 usage();
3490 3505 }
3491 3506
3492 3507 if (p_arg && !o_arg)
3493 3508 die("-p requires -o");
3494 3509
3495 3510 if (S_arg) {
3496 3511 dladm_continuous(handle, linkid, NULL, interval, LINK_REPORT);
3497 3512 return;
3498 3513 }
3499 3514
3500 3515 if (p_arg && strcasecmp(fields_str, "all") == 0)
3501 3516 die("\"-o all\" is invalid with -p");
3502 3517
3503 3518 if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
3504 3519 if (s_arg)
3505 3520 fields_str = allstat_fields;
3506 3521 else if (flags & DLADM_OPT_ACTIVE)
3507 3522 fields_str = all_active_fields;
3508 3523 else
3509 3524 fields_str = all_inactive_fields;
3510 3525 }
3511 3526
3512 3527 state.ls_parsable = p_arg;
3513 3528 state.ls_flags = flags;
3514 3529 state.ls_donefirst = B_FALSE;
3515 3530
3516 3531 if (s_arg) {
3517 3532 link_stats(linkid, interval, fields_str, &state);
3518 3533 return;
3519 3534 }
3520 3535 if (state.ls_parsable)
3521 3536 ofmtflags |= OFMT_PARSABLE;
3522 3537 oferr = ofmt_open(fields_str, link_fields, ofmtflags, 0, &ofmt);
3523 3538 dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
3524 3539 state.ls_ofmt = ofmt;
3525 3540
3526 3541 if (linkid == DATALINK_ALL_LINKID) {
3527 3542 (void) dladm_walk_datalink_id(show_link, handle, &state,
3528 3543 DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
3529 3544 } else {
3530 3545 (void) show_link(handle, linkid, &state);
3531 3546 if (state.ls_status != DLADM_STATUS_OK) {
3532 3547 die_dlerr(state.ls_status, "failed to show link %s",
3533 3548 argv[optind]);
3534 3549 }
3535 3550 }
3536 3551 ofmt_close(ofmt);
3537 3552 }
3538 3553
3539 3554 static void
3540 3555 do_show_aggr(int argc, char *argv[], const char *use)
3541 3556 {
3542 3557 boolean_t L_arg = B_FALSE;
3543 3558 boolean_t s_arg = B_FALSE;
3544 3559 boolean_t i_arg = B_FALSE;
3545 3560 boolean_t p_arg = B_FALSE;
3546 3561 boolean_t x_arg = B_FALSE;
3547 3562 show_grp_state_t state;
3548 3563 uint32_t flags = DLADM_OPT_ACTIVE;
3549 3564 datalink_id_t linkid = DATALINK_ALL_LINKID;
3550 3565 int option;
3551 3566 uint32_t interval = 0;
3552 3567 int key;
3553 3568 dladm_status_t status;
3554 3569 boolean_t o_arg = B_FALSE;
3555 3570 char *fields_str = NULL;
3556 3571 char *all_fields =
3557 3572 "link,policy,addrpolicy,lacpactivity,lacptimer,flags";
3558 3573 char *all_lacp_fields =
3559 3574 "link,port,aggregatable,sync,coll,dist,defaulted,expired";
3560 3575 char *all_stats_fields =
3561 3576 "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist";
3562 3577 char *all_extended_fields =
3563 3578 "link,port,speed,duplex,state,address,portstate";
3564 3579 const ofmt_field_t *pf;
3565 3580 ofmt_handle_t ofmt;
3566 3581 ofmt_status_t oferr;
3567 3582 uint_t ofmtflags = 0;
3568 3583
3569 3584 opterr = 0;
3570 3585 while ((option = getopt_long(argc, argv, ":LpPxsi:o:",
3571 3586 show_lopts, NULL)) != -1) {
3572 3587 switch (option) {
3573 3588 case 'L':
3574 3589 if (L_arg)
3575 3590 die_optdup(option);
3576 3591
3577 3592 L_arg = B_TRUE;
3578 3593 break;
3579 3594 case 'p':
3580 3595 if (p_arg)
3581 3596 die_optdup(option);
3582 3597
3583 3598 p_arg = B_TRUE;
3584 3599 break;
3585 3600 case 'x':
3586 3601 if (x_arg)
3587 3602 die_optdup(option);
3588 3603
3589 3604 x_arg = B_TRUE;
3590 3605 break;
3591 3606 case 'P':
3592 3607 if (flags != DLADM_OPT_ACTIVE)
3593 3608 die_optdup(option);
3594 3609
3595 3610 flags = DLADM_OPT_PERSIST;
3596 3611 break;
3597 3612 case 's':
3598 3613 if (s_arg)
3599 3614 die_optdup(option);
3600 3615
3601 3616 s_arg = B_TRUE;
3602 3617 break;
3603 3618 case 'o':
3604 3619 o_arg = B_TRUE;
3605 3620 fields_str = optarg;
3606 3621 break;
3607 3622 case 'i':
3608 3623 if (i_arg)
3609 3624 die_optdup(option);
3610 3625
3611 3626 i_arg = B_TRUE;
3612 3627 if (!dladm_str2interval(optarg, &interval))
3613 3628 die("invalid interval value '%s'", optarg);
3614 3629 break;
3615 3630 default:
3616 3631 die_opterr(optopt, option, use);
3617 3632 break;
3618 3633 }
3619 3634 }
3620 3635
3621 3636 if (p_arg && !o_arg)
3622 3637 die("-p requires -o");
3623 3638
3624 3639 if (p_arg && strcasecmp(fields_str, "all") == 0)
3625 3640 die("\"-o all\" is invalid with -p");
3626 3641
3627 3642 if (i_arg && !s_arg)
3628 3643 die("the option -i can be used only with -s");
3629 3644
3630 3645 if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) {
3631 3646 die("the option -%c cannot be used with -s",
3632 3647 L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P')));
3633 3648 }
3634 3649
3635 3650 if (L_arg && flags != DLADM_OPT_ACTIVE)
3636 3651 die("the option -P cannot be used with -L");
3637 3652
3638 3653 if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE))
3639 3654 die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P');
3640 3655
3641 3656 /* get aggregation key or aggrname (optional last argument) */
3642 3657 if (optind == (argc-1)) {
3643 3658 if (!str2int(argv[optind], &key)) {
3644 3659 status = dladm_name2info(handle, argv[optind],
3645 3660 &linkid, NULL, NULL, NULL);
3646 3661 } else {
3647 3662 status = dladm_key2linkid(handle, (uint16_t)key,
3648 3663 &linkid, DLADM_OPT_ACTIVE);
3649 3664 }
3650 3665
3651 3666 if (status != DLADM_STATUS_OK)
3652 3667 die("non-existent aggregation '%s'", argv[optind]);
3653 3668
3654 3669 } else if (optind != argc) {
3655 3670 usage();
3656 3671 }
3657 3672
3658 3673 bzero(&state, sizeof (state));
3659 3674 state.gs_lacp = L_arg;
3660 3675 state.gs_stats = s_arg;
3661 3676 state.gs_flags = flags;
3662 3677 state.gs_parsable = p_arg;
3663 3678 state.gs_extended = x_arg;
3664 3679
3665 3680 if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
3666 3681 if (state.gs_lacp)
3667 3682 fields_str = all_lacp_fields;
3668 3683 else if (state.gs_stats)
3669 3684 fields_str = all_stats_fields;
3670 3685 else if (state.gs_extended)
3671 3686 fields_str = all_extended_fields;
3672 3687 else
3673 3688 fields_str = all_fields;
3674 3689 }
3675 3690
3676 3691 if (state.gs_lacp) {
3677 3692 pf = aggr_l_fields;
3678 3693 } else if (state.gs_stats) {
3679 3694 pf = aggr_s_fields;
3680 3695 } else if (state.gs_extended) {
3681 3696 pf = aggr_x_fields;
3682 3697 } else {
3683 3698 pf = laggr_fields;
3684 3699 }
3685 3700
3686 3701 if (state.gs_parsable)
3687 3702 ofmtflags |= OFMT_PARSABLE;
3688 3703 oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
3689 3704 dladm_ofmt_check(oferr, state.gs_parsable, ofmt);
3690 3705 state.gs_ofmt = ofmt;
3691 3706
3692 3707 if (s_arg) {
3693 3708 aggr_stats(linkid, &state, interval);
3694 3709 ofmt_close(ofmt);
3695 3710 return;
3696 3711 }
3697 3712
3698 3713 if (linkid == DATALINK_ALL_LINKID) {
3699 3714 (void) dladm_walk_datalink_id(show_aggr, handle, &state,
3700 3715 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags);
3701 3716 } else {
3702 3717 (void) show_aggr(handle, linkid, &state);
3703 3718 if (state.gs_status != DLADM_STATUS_OK) {
3704 3719 die_dlerr(state.gs_status, "failed to show aggr %s",
3705 3720 argv[optind]);
3706 3721 }
3707 3722 }
3708 3723 ofmt_close(ofmt);
3709 3724 }
3710 3725
3711 3726 static dladm_status_t
3712 3727 print_phys_default(show_state_t *state, datalink_id_t linkid,
3713 3728 const char *link, uint32_t flags, uint32_t media)
3714 3729 {
3715 3730 dladm_phys_attr_t dpa;
3716 3731 dladm_status_t status;
3717 3732 link_fields_buf_t pattr;
3718 3733
3719 3734 status = dladm_phys_info(handle, linkid, &dpa, state->ls_flags);
3720 3735 if (status != DLADM_STATUS_OK)
3721 3736 goto done;
3722 3737
3723 3738 (void) snprintf(pattr.link_phys_device,
3724 3739 sizeof (pattr.link_phys_device), "%s", dpa.dp_dev);
3725 3740 (void) dladm_media2str(media, pattr.link_phys_media);
3726 3741 if (state->ls_flags == DLADM_OPT_ACTIVE) {
3727 3742 boolean_t islink;
3728 3743
3729 3744 if (!dpa.dp_novanity) {
3730 3745 (void) strlcpy(pattr.link_name, link,
3731 3746 sizeof (pattr.link_name));
3732 3747 islink = B_TRUE;
3733 3748 } else {
3734 3749 /*
3735 3750 * This is a physical link that does not have
3736 3751 * vanity naming support.
3737 3752 */
3738 3753 (void) strlcpy(pattr.link_name, dpa.dp_dev,
3739 3754 sizeof (pattr.link_name));
3740 3755 islink = B_FALSE;
3741 3756 }
3742 3757
3743 3758 (void) get_linkstate(pattr.link_name, islink,
3744 3759 pattr.link_phys_state);
3745 3760 (void) snprintf(pattr.link_phys_speed,
3746 3761 sizeof (pattr.link_phys_speed), "%u",
3747 3762 (uint_t)((get_ifspeed(pattr.link_name,
3748 3763 islink)) / 1000000ull));
3749 3764 (void) get_linkduplex(pattr.link_name, islink,
3750 3765 pattr.link_phys_duplex);
3751 3766 } else {
3752 3767 (void) snprintf(pattr.link_name, sizeof (pattr.link_name),
3753 3768 "%s", link);
3754 3769 (void) snprintf(pattr.link_flags, sizeof (pattr.link_flags),
3755 3770 "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r');
3756 3771 }
3757 3772
3758 3773 ofmt_print(state->ls_ofmt, &pattr);
3759 3774
3760 3775 done:
3761 3776 return (status);
3762 3777 }
3763 3778
3764 3779 typedef struct {
3765 3780 show_state_t *ms_state;
3766 3781 char *ms_link;
3767 3782 dladm_macaddr_attr_t *ms_mac_attr;
3768 3783 } print_phys_mac_state_t;
3769 3784
3770 3785 /*
3771 3786 * callback for ofmt_print()
3772 3787 */
3773 3788 static boolean_t
3774 3789 print_phys_one_mac_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3775 3790 {
3776 3791 print_phys_mac_state_t *mac_state = ofarg->ofmt_cbarg;
3777 3792 dladm_macaddr_attr_t *attr = mac_state->ms_mac_attr;
3778 3793 boolean_t is_primary = (attr->ma_slot == 0);
3779 3794 boolean_t is_parsable = mac_state->ms_state->ls_parsable;
3780 3795
3781 3796 switch (ofarg->ofmt_id) {
3782 3797 case PHYS_M_LINK:
3783 3798 (void) snprintf(buf, bufsize, "%s",
3784 3799 (is_primary || is_parsable) ? mac_state->ms_link : " ");
3785 3800 break;
3786 3801 case PHYS_M_SLOT:
3787 3802 if (is_primary)
3788 3803 (void) snprintf(buf, bufsize, gettext("primary"));
3789 3804 else
3790 3805 (void) snprintf(buf, bufsize, "%d", attr->ma_slot);
3791 3806 break;
3792 3807 case PHYS_M_ADDRESS:
3793 3808 (void) dladm_aggr_macaddr2str(attr->ma_addr, buf);
3794 3809 break;
3795 3810 case PHYS_M_INUSE:
3796 3811 (void) snprintf(buf, bufsize, "%s",
3797 3812 attr->ma_flags & DLADM_MACADDR_USED ? gettext("yes") :
3798 3813 gettext("no"));
3799 3814 break;
3800 3815 case PHYS_M_CLIENT:
3801 3816 /*
3802 3817 * CR 6678526: resolve link id to actual link name if
3803 3818 * it is valid.
3804 3819 */
3805 3820 (void) snprintf(buf, bufsize, "%s", attr->ma_client_name);
3806 3821 break;
3807 3822 }
3808 3823
3809 3824 return (B_TRUE);
3810 3825 }
3811 3826
3812 3827 typedef struct {
3813 3828 show_state_t *hs_state;
3814 3829 char *hs_link;
3815 3830 dladm_hwgrp_attr_t *hs_grp_attr;
3816 3831 } print_phys_hwgrp_state_t;
3817 3832
3818 3833 static boolean_t
3819 3834 print_phys_one_hwgrp_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
3820 3835 {
3821 3836 int i;
3822 3837 boolean_t first = B_TRUE;
3823 3838 int start = -1;
3824 3839 int end = -1;
3825 3840 char ringstr[RINGSTRLEN];
3826 3841 char ringsubstr[RINGSTRLEN];
3827 3842
3828 3843 print_phys_hwgrp_state_t *hg_state = ofarg->ofmt_cbarg;
3829 3844 dladm_hwgrp_attr_t *attr = hg_state->hs_grp_attr;
3830 3845
3831 3846 switch (ofarg->ofmt_id) {
3832 3847 case PHYS_H_LINK:
3833 3848 (void) snprintf(buf, bufsize, "%s", attr->hg_link_name);
3834 3849 break;
3835 3850 case PHYS_H_RINGTYPE:
3836 3851 (void) snprintf(buf, bufsize, "%s",
3837 3852 attr->hg_grp_type == DLADM_HWGRP_TYPE_RX ? "RX" : "TX");
3838 3853 break;
3839 3854 case PHYS_H_RINGS:
3840 3855 ringstr[0] = '\0';
3841 3856 for (i = 0; i < attr->hg_n_rings; i++) {
3842 3857 uint_t index = attr->hg_rings[i];
3843 3858
3844 3859 if (start == -1) {
3845 3860 start = index;
3846 3861 end = index;
3847 3862 } else if (index == end + 1) {
3848 3863 end = index;
3849 3864 } else {
3850 3865 if (start == end) {
3851 3866 if (first) {
3852 3867 (void) snprintf(
3853 3868 ringsubstr,
3854 3869 RINGSTRLEN, "%d",
3855 3870 start);
3856 3871 first = B_FALSE;
3857 3872 } else {
3858 3873 (void) snprintf(
3859 3874 ringsubstr,
3860 3875 RINGSTRLEN, ",%d",
3861 3876 start);
3862 3877 }
3863 3878 } else {
3864 3879 if (first) {
3865 3880 (void) snprintf(
3866 3881 ringsubstr,
3867 3882 RINGSTRLEN,
3868 3883 "%d-%d",
3869 3884 start, end);
3870 3885 first = B_FALSE;
3871 3886 } else {
3872 3887 (void) snprintf(
3873 3888 ringsubstr,
3874 3889 RINGSTRLEN,
3875 3890 ",%d-%d",
3876 3891 start, end);
3877 3892 }
3878 3893 }
3879 3894 (void) strlcat(ringstr, ringsubstr,
3880 3895 RINGSTRLEN);
3881 3896 start = index;
3882 3897 end = index;
3883 3898 }
3884 3899 }
3885 3900 /* The last one */
3886 3901 if (start != -1) {
3887 3902 if (first) {
3888 3903 if (start == end) {
3889 3904 (void) snprintf(buf, bufsize, "%d",
3890 3905 start);
3891 3906 } else {
3892 3907 (void) snprintf(buf, bufsize, "%d-%d",
3893 3908 start, end);
3894 3909 }
3895 3910 } else {
3896 3911 if (start == end) {
3897 3912 (void) snprintf(ringsubstr, RINGSTRLEN,
3898 3913 ",%d", start);
3899 3914 } else {
3900 3915 (void) snprintf(ringsubstr, RINGSTRLEN,
3901 3916 ",%d-%d", start, end);
3902 3917 }
3903 3918 (void) strlcat(ringstr, ringsubstr, RINGSTRLEN);
3904 3919 (void) snprintf(buf, bufsize, "%s", ringstr);
3905 3920 }
3906 3921 }
3907 3922 break;
3908 3923 case PHYS_H_CLIENTS:
3909 3924 if (attr->hg_client_names[0] == '\0') {
3910 3925 (void) snprintf(buf, bufsize, "--");
3911 3926 } else {
3912 3927 (void) snprintf(buf, bufsize, "%s ",
3913 3928 attr->hg_client_names);
3914 3929 }
3915 3930 break;
3916 3931 }
3917 3932
3918 3933 return (B_TRUE);
3919 3934 }
3920 3935
3921 3936 /*
3922 3937 * callback for dladm_walk_macaddr, invoked for each MAC address slot
3923 3938 */
3924 3939 static boolean_t
3925 3940 print_phys_mac_callback(void *arg, dladm_macaddr_attr_t *attr)
3926 3941 {
3927 3942 print_phys_mac_state_t *mac_state = arg;
3928 3943 show_state_t *state = mac_state->ms_state;
3929 3944
3930 3945 mac_state->ms_mac_attr = attr;
3931 3946 ofmt_print(state->ls_ofmt, mac_state);
3932 3947
3933 3948 return (B_TRUE);
3934 3949 }
3935 3950
3936 3951 /*
3937 3952 * invoked by show-phys -m for each physical data-link
3938 3953 */
3939 3954 static dladm_status_t
3940 3955 print_phys_mac(show_state_t *state, datalink_id_t linkid, char *link)
3941 3956 {
3942 3957 print_phys_mac_state_t mac_state;
3943 3958
3944 3959 mac_state.ms_state = state;
3945 3960 mac_state.ms_link = link;
3946 3961
3947 3962 return (dladm_walk_macaddr(handle, linkid, &mac_state,
3948 3963 print_phys_mac_callback));
3949 3964 }
3950 3965
3951 3966 /*
3952 3967 * callback for dladm_walk_hwgrp, invoked for each MAC hwgrp
3953 3968 */
3954 3969 static boolean_t
3955 3970 print_phys_hwgrp_callback(void *arg, dladm_hwgrp_attr_t *attr)
3956 3971 {
3957 3972 print_phys_hwgrp_state_t *hwgrp_state = arg;
3958 3973 show_state_t *state = hwgrp_state->hs_state;
3959 3974
3960 3975 hwgrp_state->hs_grp_attr = attr;
3961 3976 ofmt_print(state->ls_ofmt, hwgrp_state);
3962 3977
3963 3978 return (B_TRUE);
3964 3979 }
3965 3980
3966 3981 /* invoked by show-phys -H for each physical data-link */
3967 3982 static dladm_status_t
3968 3983 print_phys_hwgrp(show_state_t *state, datalink_id_t linkid, char *link)
3969 3984 {
3970 3985 print_phys_hwgrp_state_t hwgrp_state;
3971 3986
3972 3987 hwgrp_state.hs_state = state;
3973 3988 hwgrp_state.hs_link = link;
3974 3989 return (dladm_walk_hwgrp(handle, linkid, &hwgrp_state,
3975 3990 print_phys_hwgrp_callback));
3976 3991 }
3977 3992
3978 3993 /*
3979 3994 * Parse the "local=<laddr>,remote=<raddr>" sub-options for the -a option of
3980 3995 * *-iptun subcommands.
3981 3996 */
3982 3997 static void
3983 3998 iptun_process_addrarg(char *addrarg, iptun_params_t *params)
3984 3999 {
3985 4000 char *addrval;
3986 4001
3987 4002 while (*addrarg != '\0') {
3988 4003 switch (getsubopt(&addrarg, iptun_addropts, &addrval)) {
3989 4004 case IPTUN_LOCAL:
3990 4005 params->iptun_param_flags |= IPTUN_PARAM_LADDR;
3991 4006 if (strlcpy(params->iptun_param_laddr, addrval,
3992 4007 sizeof (params->iptun_param_laddr)) >=
3993 4008 sizeof (params->iptun_param_laddr))
3994 4009 die("tunnel source address is too long");
3995 4010 break;
3996 4011 case IPTUN_REMOTE:
3997 4012 params->iptun_param_flags |= IPTUN_PARAM_RADDR;
3998 4013 if (strlcpy(params->iptun_param_raddr, addrval,
3999 4014 sizeof (params->iptun_param_raddr)) >=
4000 4015 sizeof (params->iptun_param_raddr))
4001 4016 die("tunnel destination address is too long");
4002 4017 break;
4003 4018 default:
4004 4019 die("invalid address type: %s", addrval);
4005 4020 break;
4006 4021 }
4007 4022 }
4008 4023 }
4009 4024
4010 4025 /*
4011 4026 * Convenience routine to process iptun-create/modify/delete subcommand
4012 4027 * arguments.
4013 4028 */
4014 4029 static void
4015 4030 iptun_process_args(int argc, char *argv[], const char *opts,
4016 4031 iptun_params_t *params, uint32_t *flags, char *name, const char *use)
4017 4032 {
4018 4033 int option;
4019 4034 char *altroot = NULL;
4020 4035
4021 4036 if (params != NULL)
4022 4037 bzero(params, sizeof (*params));
4023 4038 *flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4024 4039
4025 4040 opterr = 0;
4026 4041 while ((option = getopt_long(argc, argv, opts, iptun_lopts, NULL)) !=
4027 4042 -1) {
4028 4043 switch (option) {
4029 4044 case 'a':
4030 4045 iptun_process_addrarg(optarg, params);
4031 4046 break;
4032 4047 case 'R':
4033 4048 altroot = optarg;
4034 4049 break;
4035 4050 case 't':
4036 4051 *flags &= ~DLADM_OPT_PERSIST;
4037 4052 break;
4038 4053 case 'T':
4039 4054 params->iptun_param_type = iptun_gettypebyname(optarg);
4040 4055 if (params->iptun_param_type == IPTUN_TYPE_UNKNOWN)
4041 4056 die("unknown tunnel type: %s", optarg);
4042 4057 params->iptun_param_flags |= IPTUN_PARAM_TYPE;
4043 4058 break;
4044 4059 default:
4045 4060 die_opterr(optopt, option, use);
4046 4061 break;
4047 4062 }
4048 4063 }
4049 4064
4050 4065 /* Get the required tunnel name argument. */
4051 4066 if (argc - optind != 1)
4052 4067 usage();
4053 4068
4054 4069 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
4055 4070 die("tunnel name is too long");
4056 4071
4057 4072 if (altroot != NULL)
4058 4073 altroot_cmd(altroot, argc, argv);
4059 4074 }
4060 4075
4061 4076 static void
4062 4077 do_create_iptun(int argc, char *argv[], const char *use)
4063 4078 {
4064 4079 iptun_params_t params;
4065 4080 dladm_status_t status;
4066 4081 uint32_t flags;
4067 4082 char name[MAXLINKNAMELEN];
4068 4083
4069 4084 iptun_process_args(argc, argv, ":a:R:tT:", ¶ms, &flags, name,
4070 4085 use);
4071 4086
4072 4087 status = dladm_iptun_create(handle, name, ¶ms, flags);
4073 4088 if (status != DLADM_STATUS_OK)
4074 4089 die_dlerr(status, "could not create tunnel");
4075 4090 }
4076 4091
4077 4092 static void
4078 4093 do_delete_iptun(int argc, char *argv[], const char *use)
4079 4094 {
4080 4095 uint32_t flags;
4081 4096 datalink_id_t linkid;
4082 4097 dladm_status_t status;
4083 4098 char name[MAXLINKNAMELEN];
4084 4099
4085 4100 iptun_process_args(argc, argv, ":R:t", NULL, &flags, name, use);
4086 4101
4087 4102 status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL);
4088 4103 if (status != DLADM_STATUS_OK)
4089 4104 die_dlerr(status, "could not delete tunnel");
4090 4105 status = dladm_iptun_delete(handle, linkid, flags);
4091 4106 if (status != DLADM_STATUS_OK)
4092 4107 die_dlerr(status, "could not delete tunnel");
4093 4108 }
4094 4109
4095 4110 static void
4096 4111 do_modify_iptun(int argc, char *argv[], const char *use)
4097 4112 {
4098 4113 iptun_params_t params;
4099 4114 uint32_t flags;
4100 4115 dladm_status_t status;
4101 4116 char name[MAXLINKNAMELEN];
4102 4117
4103 4118 iptun_process_args(argc, argv, ":a:R:t", ¶ms, &flags, name, use);
4104 4119
4105 4120 if ((status = dladm_name2info(handle, name, ¶ms.iptun_param_linkid,
4106 4121 NULL, NULL, NULL)) != DLADM_STATUS_OK)
4107 4122 die_dlerr(status, "could not modify tunnel");
4108 4123 status = dladm_iptun_modify(handle, ¶ms, flags);
4109 4124 if (status != DLADM_STATUS_OK)
4110 4125 die_dlerr(status, "could not modify tunnel");
4111 4126 }
4112 4127
4113 4128 static void
4114 4129 do_show_iptun(int argc, char *argv[], const char *use)
4115 4130 {
4116 4131 char option;
4117 4132 datalink_id_t linkid;
4118 4133 uint32_t flags = DLADM_OPT_ACTIVE;
4119 4134 char *name = NULL;
4120 4135 dladm_status_t status;
4121 4136 const char *fields_str = NULL;
4122 4137 show_state_t state;
4123 4138 ofmt_handle_t ofmt;
4124 4139 ofmt_status_t oferr;
4125 4140 uint_t ofmtflags = 0;
4126 4141
4127 4142 bzero(&state, sizeof (state));
4128 4143 opterr = 0;
4129 4144 while ((option = getopt_long(argc, argv, ":pPo:",
4130 4145 iptun_lopts, NULL)) != -1) {
4131 4146 switch (option) {
4132 4147 case 'o':
4133 4148 fields_str = optarg;
4134 4149 break;
4135 4150 case 'p':
4136 4151 state.ls_parsable = B_TRUE;
4137 4152 ofmtflags = OFMT_PARSABLE;
4138 4153 break;
4139 4154 case 'P':
4140 4155 flags = DLADM_OPT_PERSIST;
4141 4156 break;
4142 4157 default:
4143 4158 die_opterr(optopt, option, use);
4144 4159 break;
4145 4160 }
4146 4161 }
4147 4162
4148 4163 /*
4149 4164 * Get the optional tunnel name argument. If there is one, it must
4150 4165 * be the last thing remaining on the command-line.
4151 4166 */
4152 4167 if (argc - optind > 1)
4153 4168 die(gettext(use));
4154 4169 if (argc - optind == 1)
4155 4170 name = argv[optind];
4156 4171
4157 4172 oferr = ofmt_open(fields_str, iptun_fields, ofmtflags,
4158 4173 DLADM_DEFAULT_COL, &ofmt);
4159 4174 dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
4160 4175
4161 4176 state.ls_ofmt = ofmt;
4162 4177 state.ls_flags = flags;
4163 4178
4164 4179 if (name == NULL) {
4165 4180 (void) dladm_walk_datalink_id(print_iptun_walker, handle,
4166 4181 &state, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE,
4167 4182 flags);
4168 4183 status = state.ls_status;
4169 4184 } else {
4170 4185 if ((status = dladm_name2info(handle, name, &linkid, NULL, NULL,
4171 4186 NULL)) == DLADM_STATUS_OK)
4172 4187 status = print_iptun(handle, linkid, &state);
4173 4188 }
4174 4189
4175 4190 if (status != DLADM_STATUS_OK)
4176 4191 die_dlerr(status, "unable to obtain tunnel status");
4177 4192 }
4178 4193
4179 4194 /* ARGSUSED */
4180 4195 static void
4181 4196 do_up_iptun(int argc, char *argv[], const char *use)
4182 4197 {
4183 4198 datalink_id_t linkid = DATALINK_ALL_LINKID;
4184 4199 dladm_status_t status = DLADM_STATUS_OK;
4185 4200
4186 4201 /*
4187 4202 * Get the optional tunnel name argument. If there is one, it must
4188 4203 * be the last thing remaining on the command-line.
4189 4204 */
4190 4205 if (argc - optind > 1)
4191 4206 usage();
4192 4207 if (argc - optind == 1) {
4193 4208 status = dladm_name2info(handle, argv[optind], &linkid, NULL,
4194 4209 NULL, NULL);
4195 4210 }
4196 4211 if (status == DLADM_STATUS_OK)
4197 4212 status = dladm_iptun_up(handle, linkid);
4198 4213 if (status != DLADM_STATUS_OK)
4199 4214 die_dlerr(status, "unable to configure IP tunnel links");
4200 4215 }
4201 4216
4202 4217 /* ARGSUSED */
4203 4218 static void
4204 4219 do_down_iptun(int argc, char *argv[], const char *use)
4205 4220 {
4206 4221 datalink_id_t linkid = DATALINK_ALL_LINKID;
4207 4222 dladm_status_t status = DLADM_STATUS_OK;
4208 4223
4209 4224 /*
4210 4225 * Get the optional tunnel name argument. If there is one, it must
4211 4226 * be the last thing remaining on the command-line.
4212 4227 */
4213 4228 if (argc - optind > 1)
4214 4229 usage();
4215 4230 if (argc - optind == 1) {
4216 4231 status = dladm_name2info(handle, argv[optind], &linkid, NULL,
4217 4232 NULL, NULL);
4218 4233 }
4219 4234 if (status == DLADM_STATUS_OK)
4220 4235 status = dladm_iptun_down(handle, linkid);
4221 4236 if (status != DLADM_STATUS_OK)
4222 4237 die_dlerr(status, "unable to bring down IP tunnel links");
4223 4238 }
4224 4239
4225 4240 static iptun_type_t
4226 4241 iptun_gettypebyname(char *typestr)
4227 4242 {
4228 4243 int i;
4229 4244
4230 4245 for (i = 0; iptun_types[i].type_name != NULL; i++) {
4231 4246 if (strncmp(iptun_types[i].type_name, typestr,
4232 4247 strlen(iptun_types[i].type_name)) == 0) {
4233 4248 return (iptun_types[i].type_value);
4234 4249 }
4235 4250 }
4236 4251 return (IPTUN_TYPE_UNKNOWN);
4237 4252 }
4238 4253
4239 4254 static const char *
4240 4255 iptun_gettypebyvalue(iptun_type_t type)
4241 4256 {
4242 4257 int i;
4243 4258
4244 4259 for (i = 0; iptun_types[i].type_name != NULL; i++) {
4245 4260 if (iptun_types[i].type_value == type)
4246 4261 return (iptun_types[i].type_name);
4247 4262 }
4248 4263 return (NULL);
4249 4264 }
4250 4265
4251 4266 static dladm_status_t
4252 4267 print_iptun(dladm_handle_t dh, datalink_id_t linkid, show_state_t *state)
4253 4268 {
4254 4269 dladm_status_t status;
4255 4270 iptun_params_t params;
4256 4271 iptun_fields_buf_t lbuf;
4257 4272 const char *laddr;
4258 4273 const char *raddr;
4259 4274
4260 4275 params.iptun_param_linkid = linkid;
4261 4276 status = dladm_iptun_getparams(dh, ¶ms, state->ls_flags);
4262 4277 if (status != DLADM_STATUS_OK)
4263 4278 return (status);
4264 4279
4265 4280 /* LINK */
4266 4281 status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL,
4267 4282 lbuf.iptun_name, sizeof (lbuf.iptun_name));
4268 4283 if (status != DLADM_STATUS_OK)
4269 4284 return (status);
4270 4285
4271 4286 /* TYPE */
4272 4287 (void) strlcpy(lbuf.iptun_type,
4273 4288 iptun_gettypebyvalue(params.iptun_param_type),
4274 4289 sizeof (lbuf.iptun_type));
4275 4290
4276 4291 /* FLAGS */
4277 4292 (void) memset(lbuf.iptun_flags, '-', IPTUN_NUM_FLAGS);
4278 4293 lbuf.iptun_flags[IPTUN_NUM_FLAGS] = '\0';
4279 4294 if (params.iptun_param_flags & IPTUN_PARAM_IPSECPOL)
4280 4295 lbuf.iptun_flags[IPTUN_SFLAG_INDEX] = 's';
4281 4296 if (params.iptun_param_flags & IPTUN_PARAM_IMPLICIT)
4282 4297 lbuf.iptun_flags[IPTUN_IFLAG_INDEX] = 'i';
4283 4298
4284 4299 /* LOCAL */
4285 4300 if (params.iptun_param_flags & IPTUN_PARAM_LADDR)
4286 4301 laddr = params.iptun_param_laddr;
4287 4302 else
4288 4303 laddr = (state->ls_parsable) ? "" : "--";
4289 4304 (void) strlcpy(lbuf.iptun_laddr, laddr, sizeof (lbuf.iptun_laddr));
4290 4305
4291 4306 /* REMOTE */
4292 4307 if (params.iptun_param_flags & IPTUN_PARAM_RADDR)
4293 4308 raddr = params.iptun_param_raddr;
4294 4309 else
4295 4310 raddr = (state->ls_parsable) ? "" : "--";
4296 4311 (void) strlcpy(lbuf.iptun_raddr, raddr, sizeof (lbuf.iptun_raddr));
4297 4312
4298 4313 ofmt_print(state->ls_ofmt, &lbuf);
4299 4314
4300 4315 return (DLADM_STATUS_OK);
4301 4316 }
4302 4317
4303 4318 static int
4304 4319 print_iptun_walker(dladm_handle_t dh, datalink_id_t linkid, void *arg)
4305 4320 {
4306 4321 ((show_state_t *)arg)->ls_status = print_iptun(dh, linkid, arg);
4307 4322 return (DLADM_WALK_CONTINUE);
4308 4323 }
4309 4324
4310 4325 static dladm_status_t
4311 4326 print_phys(show_state_t *state, datalink_id_t linkid)
4312 4327 {
4313 4328 char link[MAXLINKNAMELEN];
4314 4329 uint32_t flags;
4315 4330 dladm_status_t status;
4316 4331 datalink_class_t class;
4317 4332 uint32_t media;
4318 4333
4319 4334 if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
4320 4335 &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
4321 4336 goto done;
4322 4337 }
4323 4338
4324 4339 if (class != DATALINK_CLASS_PHYS) {
4325 4340 status = DLADM_STATUS_BADARG;
4326 4341 goto done;
4327 4342 }
4328 4343
4329 4344 if (!(state->ls_flags & flags)) {
4330 4345 status = DLADM_STATUS_NOTFOUND;
4331 4346 goto done;
4332 4347 }
4333 4348
4334 4349 if (state->ls_mac)
4335 4350 status = print_phys_mac(state, linkid, link);
4336 4351 else if (state->ls_hwgrp)
4337 4352 status = print_phys_hwgrp(state, linkid, link);
4338 4353 else
4339 4354 status = print_phys_default(state, linkid, link, flags, media);
4340 4355
4341 4356 done:
4342 4357 return (status);
4343 4358 }
4344 4359
4345 4360 /* ARGSUSED */
4346 4361 static int
4347 4362 show_phys(dladm_handle_t dh, datalink_id_t linkid, void *arg)
4348 4363 {
4349 4364 show_state_t *state = arg;
4350 4365
4351 4366 state->ls_status = print_phys(state, linkid);
4352 4367 return (DLADM_WALK_CONTINUE);
4353 4368 }
4354 4369
4355 4370 /*
4356 4371 * Print the active topology information.
4357 4372 */
4358 4373 static dladm_status_t
4359 4374 print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l)
4360 4375 {
4361 4376 dladm_vlan_attr_t vinfo;
4362 4377 uint32_t flags;
4363 4378 dladm_status_t status;
4364 4379
4365 4380 if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL,
4366 4381 l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) {
4367 4382 goto done;
4368 4383 }
4369 4384
4370 4385 if (!(state->ls_flags & flags)) {
4371 4386 status = DLADM_STATUS_NOTFOUND;
4372 4387 goto done;
4373 4388 }
4374 4389
4375 4390 if ((status = dladm_vlan_info(handle, linkid, &vinfo,
4376 4391 state->ls_flags)) != DLADM_STATUS_OK ||
4377 4392 (status = dladm_datalink_id2info(handle, vinfo.dv_linkid, NULL,
4378 4393 NULL, NULL, l->link_over, sizeof (l->link_over))) !=
4379 4394 DLADM_STATUS_OK) {
4380 4395 goto done;
4381 4396 }
4382 4397
4383 4398 (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d",
4384 4399 vinfo.dv_vid);
4385 4400 (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c----",
4386 4401 vinfo.dv_force ? 'f' : '-');
4387 4402
4388 4403 done:
4389 4404 return (status);
4390 4405 }
4391 4406
4392 4407 /* ARGSUSED */
4393 4408 static int
4394 4409 show_vlan(dladm_handle_t dh, datalink_id_t linkid, void *arg)
4395 4410 {
4396 4411 show_state_t *state = arg;
4397 4412 dladm_status_t status;
4398 4413 link_fields_buf_t lbuf;
4399 4414
4400 4415 bzero(&lbuf, sizeof (link_fields_buf_t));
4401 4416 status = print_vlan(state, linkid, &lbuf);
4402 4417 if (status != DLADM_STATUS_OK)
4403 4418 goto done;
4404 4419
4405 4420 ofmt_print(state->ls_ofmt, &lbuf);
4406 4421
4407 4422 done:
4408 4423 state->ls_status = status;
4409 4424 return (DLADM_WALK_CONTINUE);
4410 4425 }
4411 4426
4412 4427 static void
4413 4428 do_show_phys(int argc, char *argv[], const char *use)
4414 4429 {
4415 4430 int option;
4416 4431 uint32_t flags = DLADM_OPT_ACTIVE;
4417 4432 boolean_t p_arg = B_FALSE;
4418 4433 boolean_t o_arg = B_FALSE;
4419 4434 boolean_t m_arg = B_FALSE;
4420 4435 boolean_t H_arg = B_FALSE;
4421 4436 datalink_id_t linkid = DATALINK_ALL_LINKID;
4422 4437 show_state_t state;
4423 4438 dladm_status_t status;
4424 4439 char *fields_str = NULL;
4425 4440 char *all_active_fields =
4426 4441 "link,media,state,speed,duplex,device";
4427 4442 char *all_inactive_fields = "link,device,media,flags";
4428 4443 char *all_mac_fields = "link,slot,address,inuse,client";
4429 4444 char *all_hwgrp_fields = "link,ringtype,rings,clients";
4430 4445 const ofmt_field_t *pf;
4431 4446 ofmt_handle_t ofmt;
4432 4447 ofmt_status_t oferr;
4433 4448 uint_t ofmtflags = 0;
4434 4449
4435 4450 bzero(&state, sizeof (state));
4436 4451 opterr = 0;
4437 4452 while ((option = getopt_long(argc, argv, ":pPo:mH",
4438 4453 show_lopts, NULL)) != -1) {
4439 4454 switch (option) {
4440 4455 case 'p':
4441 4456 if (p_arg)
4442 4457 die_optdup(option);
4443 4458
4444 4459 p_arg = B_TRUE;
4445 4460 break;
4446 4461 case 'P':
4447 4462 if (flags != DLADM_OPT_ACTIVE)
4448 4463 die_optdup(option);
4449 4464
4450 4465 flags = DLADM_OPT_PERSIST;
4451 4466 break;
4452 4467 case 'o':
4453 4468 o_arg = B_TRUE;
4454 4469 fields_str = optarg;
4455 4470 break;
4456 4471 case 'm':
4457 4472 m_arg = B_TRUE;
4458 4473 break;
4459 4474 case 'H':
4460 4475 H_arg = B_TRUE;
4461 4476 break;
4462 4477 default:
4463 4478 die_opterr(optopt, option, use);
4464 4479 break;
4465 4480 }
4466 4481 }
4467 4482
4468 4483 if (p_arg && !o_arg)
4469 4484 die("-p requires -o");
4470 4485
4471 4486 if (m_arg && H_arg)
4472 4487 die("-m cannot combine with -H");
4473 4488
4474 4489 if (p_arg && strcasecmp(fields_str, "all") == 0)
4475 4490 die("\"-o all\" is invalid with -p");
4476 4491
4477 4492 /* get link name (optional last argument) */
4478 4493 if (optind == (argc-1)) {
4479 4494 if ((status = dladm_name2info(handle, argv[optind], &linkid,
4480 4495 NULL, NULL, NULL)) != DLADM_STATUS_OK) {
4481 4496 die_dlerr(status, "link %s is not valid", argv[optind]);
4482 4497 }
4483 4498 } else if (optind != argc) {
4484 4499 usage();
4485 4500 }
4486 4501
4487 4502 state.ls_parsable = p_arg;
4488 4503 state.ls_flags = flags;
4489 4504 state.ls_donefirst = B_FALSE;
4490 4505 state.ls_mac = m_arg;
4491 4506 state.ls_hwgrp = H_arg;
4492 4507
4493 4508 if (m_arg && !(flags & DLADM_OPT_ACTIVE)) {
4494 4509 /*
4495 4510 * We can only display the factory MAC addresses of
4496 4511 * active data-links.
4497 4512 */
4498 4513 die("-m not compatible with -P");
4499 4514 }
4500 4515
4501 4516 if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
4502 4517 if (state.ls_mac)
4503 4518 fields_str = all_mac_fields;
4504 4519 else if (state.ls_hwgrp)
4505 4520 fields_str = all_hwgrp_fields;
4506 4521 else if (state.ls_flags & DLADM_OPT_ACTIVE) {
4507 4522 fields_str = all_active_fields;
4508 4523 } else {
4509 4524 fields_str = all_inactive_fields;
4510 4525 }
4511 4526 }
4512 4527
4513 4528 if (state.ls_mac) {
4514 4529 pf = phys_m_fields;
4515 4530 } else if (state.ls_hwgrp) {
4516 4531 pf = phys_h_fields;
4517 4532 } else {
4518 4533 pf = phys_fields;
4519 4534 }
4520 4535
4521 4536 if (state.ls_parsable)
4522 4537 ofmtflags |= OFMT_PARSABLE;
4523 4538 oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
4524 4539 dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
4525 4540 state.ls_ofmt = ofmt;
4526 4541
4527 4542 if (linkid == DATALINK_ALL_LINKID) {
4528 4543 (void) dladm_walk_datalink_id(show_phys, handle, &state,
4529 4544 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags);
4530 4545 } else {
4531 4546 (void) show_phys(handle, linkid, &state);
4532 4547 if (state.ls_status != DLADM_STATUS_OK) {
4533 4548 die_dlerr(state.ls_status,
4534 4549 "failed to show physical link %s", argv[optind]);
4535 4550 }
4536 4551 }
4537 4552 ofmt_close(ofmt);
4538 4553 }
4539 4554
4540 4555 static void
4541 4556 do_show_vlan(int argc, char *argv[], const char *use)
4542 4557 {
4543 4558 int option;
4544 4559 uint32_t flags = DLADM_OPT_ACTIVE;
4545 4560 boolean_t p_arg = B_FALSE;
4546 4561 datalink_id_t linkid = DATALINK_ALL_LINKID;
4547 4562 show_state_t state;
4548 4563 dladm_status_t status;
4549 4564 boolean_t o_arg = B_FALSE;
4550 4565 char *fields_str = NULL;
4551 4566 ofmt_handle_t ofmt;
4552 4567 ofmt_status_t oferr;
4553 4568 uint_t ofmtflags = 0;
4554 4569
4555 4570 bzero(&state, sizeof (state));
4556 4571
4557 4572 opterr = 0;
4558 4573 while ((option = getopt_long(argc, argv, ":pPo:",
4559 4574 show_lopts, NULL)) != -1) {
4560 4575 switch (option) {
4561 4576 case 'p':
4562 4577 if (p_arg)
4563 4578 die_optdup(option);
4564 4579
4565 4580 p_arg = B_TRUE;
4566 4581 break;
4567 4582 case 'P':
4568 4583 if (flags != DLADM_OPT_ACTIVE)
4569 4584 die_optdup(option);
4570 4585
4571 4586 flags = DLADM_OPT_PERSIST;
4572 4587 break;
4573 4588 case 'o':
4574 4589 o_arg = B_TRUE;
4575 4590 fields_str = optarg;
4576 4591 break;
4577 4592 default:
4578 4593 die_opterr(optopt, option, use);
4579 4594 break;
4580 4595 }
4581 4596 }
4582 4597
4583 4598 /* get link name (optional last argument) */
4584 4599 if (optind == (argc-1)) {
4585 4600 if ((status = dladm_name2info(handle, argv[optind], &linkid,
4586 4601 NULL, NULL, NULL)) != DLADM_STATUS_OK) {
4587 4602 die_dlerr(status, "link %s is not valid", argv[optind]);
4588 4603 }
4589 4604 } else if (optind != argc) {
4590 4605 usage();
4591 4606 }
4592 4607
4593 4608 state.ls_parsable = p_arg;
4594 4609 state.ls_flags = flags;
4595 4610 state.ls_donefirst = B_FALSE;
4596 4611
4597 4612 if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
4598 4613 fields_str = NULL;
4599 4614
4600 4615 if (state.ls_parsable)
4601 4616 ofmtflags |= OFMT_PARSABLE;
4602 4617 oferr = ofmt_open(fields_str, vlan_fields, ofmtflags, 0, &ofmt);
4603 4618 dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
4604 4619 state.ls_ofmt = ofmt;
4605 4620
4606 4621 if (linkid == DATALINK_ALL_LINKID) {
4607 4622 (void) dladm_walk_datalink_id(show_vlan, handle, &state,
4608 4623 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags);
4609 4624 } else {
4610 4625 (void) show_vlan(handle, linkid, &state);
4611 4626 if (state.ls_status != DLADM_STATUS_OK) {
4612 4627 die_dlerr(state.ls_status, "failed to show vlan %s",
4613 4628 argv[optind]);
4614 4629 }
4615 4630 }
4616 4631 ofmt_close(ofmt);
4617 4632 }
4618 4633
4619 4634 static void
4620 4635 do_create_vnic(int argc, char *argv[], const char *use)
4621 4636 {
4622 4637 datalink_id_t linkid, dev_linkid;
4623 4638 char devname[MAXLINKNAMELEN];
4624 4639 char name[MAXLINKNAMELEN];
4625 4640 boolean_t l_arg = B_FALSE;
4626 4641 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4627 4642 char *altroot = NULL;
4628 4643 int option;
4629 4644 char *endp = NULL;
4630 4645 dladm_status_t status;
4631 4646 vnic_mac_addr_type_t mac_addr_type = VNIC_MAC_ADDR_TYPE_UNKNOWN;
4632 4647 uchar_t *mac_addr = NULL;
4633 4648 int mac_slot = -1;
4634 4649 uint_t maclen = 0, mac_prefix_len = 0;
4635 4650 char propstr[DLADM_STRSIZE];
4636 4651 dladm_arg_list_t *proplist = NULL;
4637 4652 int vid = 0;
4638 4653 int af = AF_UNSPEC;
4639 4654 vrid_t vrid = VRRP_VRID_NONE;
4640 4655
4641 4656 opterr = 0;
4642 4657 bzero(propstr, DLADM_STRSIZE);
4643 4658
4644 4659 while ((option = getopt_long(argc, argv, ":tfR:l:m:n:p:r:v:V:A:H",
4645 4660 vnic_lopts, NULL)) != -1) {
4646 4661 switch (option) {
4647 4662 case 't':
4648 4663 flags &= ~DLADM_OPT_PERSIST;
4649 4664 break;
4650 4665 case 'R':
4651 4666 altroot = optarg;
4652 4667 break;
4653 4668 case 'l':
4654 4669 if (strlcpy(devname, optarg, MAXLINKNAMELEN) >=
4655 4670 MAXLINKNAMELEN)
4656 4671 die("link name too long");
4657 4672 l_arg = B_TRUE;
4658 4673 break;
4659 4674 case 'm':
4660 4675 if (mac_addr_type != VNIC_MAC_ADDR_TYPE_UNKNOWN)
4661 4676 die("cannot specify -m option twice");
4662 4677
4663 4678 if (strcmp(optarg, "fixed") == 0) {
4664 4679 /*
4665 4680 * A fixed MAC address must be specified
4666 4681 * by its value, not by the keyword 'fixed'.
4667 4682 */
4668 4683 die("'fixed' is not a valid MAC address");
4669 4684 }
4670 4685 if (dladm_vnic_str2macaddrtype(optarg,
4671 4686 &mac_addr_type) != DLADM_STATUS_OK) {
4672 4687 mac_addr_type = VNIC_MAC_ADDR_TYPE_FIXED;
4673 4688 /* MAC address specified by value */
4674 4689 mac_addr = _link_aton(optarg, (int *)&maclen);
4675 4690 if (mac_addr == NULL) {
4676 4691 if (maclen == (uint_t)-1)
4677 4692 die("invalid MAC address");
4678 4693 else
4679 4694 die("out of memory");
4680 4695 }
4681 4696 }
4682 4697 break;
4683 4698 case 'n':
4684 4699 errno = 0;
4685 4700 mac_slot = (int)strtol(optarg, &endp, 10);
4686 4701 if (errno != 0 || *endp != '\0')
4687 4702 die("invalid slot number");
4688 4703 break;
4689 4704 case 'p':
4690 4705 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
4691 4706 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
4692 4707 DLADM_STRSIZE)
4693 4708 die("property list too long '%s'", propstr);
4694 4709 break;
4695 4710 case 'r':
4696 4711 mac_addr = _link_aton(optarg, (int *)&mac_prefix_len);
4697 4712 if (mac_addr == NULL) {
4698 4713 if (mac_prefix_len == (uint_t)-1)
4699 4714 die("invalid MAC address");
4700 4715 else
4701 4716 die("out of memory");
4702 4717 }
4703 4718 break;
4704 4719 case 'V':
4705 4720 if (!str2int(optarg, (int *)&vrid) ||
4706 4721 vrid < VRRP_VRID_MIN || vrid > VRRP_VRID_MAX) {
4707 4722 die("invalid VRRP identifier '%s'", optarg);
4708 4723 }
4709 4724
4710 4725 break;
4711 4726 case 'A':
4712 4727 if (strcmp(optarg, "inet") == 0)
4713 4728 af = AF_INET;
4714 4729 else if (strcmp(optarg, "inet6") == 0)
4715 4730 af = AF_INET6;
4716 4731 else
4717 4732 die("invalid address family '%s'", optarg);
4718 4733 break;
4719 4734 case 'v':
4720 4735 if (vid != 0)
4721 4736 die_optdup(option);
4722 4737
4723 4738 if (!str2int(optarg, &vid) || vid < 1 || vid > 4094)
4724 4739 die("invalid VLAN identifier '%s'", optarg);
4725 4740
4726 4741 break;
4727 4742 case 'f':
4728 4743 flags |= DLADM_OPT_FORCE;
4729 4744 break;
4730 4745 default:
4731 4746 die_opterr(optopt, option, use);
4732 4747 }
4733 4748 }
|
↓ open down ↓ |
1244 lines elided |
↑ open up ↑ |
4734 4749
4735 4750 if (mac_addr_type == VNIC_MAC_ADDR_TYPE_UNKNOWN)
4736 4751 mac_addr_type = VNIC_MAC_ADDR_TYPE_AUTO;
4737 4752
4738 4753 /*
4739 4754 * 'f' - force, flag can be specified only with 'v' - vlan.
4740 4755 */
4741 4756 if ((flags & DLADM_OPT_FORCE) != 0 && vid == 0)
4742 4757 die("-f option can only be used with -v");
4743 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 +
4744 4765 if (mac_prefix_len != 0 && mac_addr_type != VNIC_MAC_ADDR_TYPE_RANDOM &&
4745 4766 mac_addr_type != VNIC_MAC_ADDR_TYPE_FIXED)
4746 4767 usage();
4747 4768
4748 4769 if (mac_addr_type == VNIC_MAC_ADDR_TYPE_VRID) {
4749 4770 if (vrid == VRRP_VRID_NONE || af == AF_UNSPEC ||
4750 4771 mac_addr != NULL || maclen != 0 || mac_slot != -1 ||
4751 4772 mac_prefix_len != 0) {
4752 4773 usage();
4753 4774 }
4754 4775 } else if ((af != AF_UNSPEC || vrid != VRRP_VRID_NONE)) {
4755 4776 usage();
4756 4777 }
4757 4778
4758 4779 /* check required options */
4759 4780 if (!l_arg)
4760 4781 usage();
4761 4782
4762 4783 if (mac_slot != -1 && mac_addr_type != VNIC_MAC_ADDR_TYPE_FACTORY)
4763 4784 usage();
4764 4785
4765 4786 /* the VNIC id is the required operand */
4766 4787 if (optind != (argc - 1))
4767 4788 usage();
4768 4789
4769 4790 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
4770 4791 die("link name too long '%s'", argv[optind]);
4771 4792
4772 4793 if (!dladm_valid_linkname(name))
4773 4794 die("invalid link name '%s'", argv[optind]);
4774 4795
4775 4796 if (altroot != NULL)
4776 4797 altroot_cmd(altroot, argc, argv);
4777 4798
4778 4799 if (dladm_name2info(handle, devname, &dev_linkid, NULL, NULL, NULL) !=
4779 4800 DLADM_STATUS_OK)
4780 4801 die("invalid link name '%s'", devname);
4781 4802
4782 4803 if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
4783 4804 != DLADM_STATUS_OK)
4784 4805 die("invalid vnic property");
4785 4806
4786 4807 status = dladm_vnic_create(handle, name, dev_linkid, mac_addr_type,
4787 4808 mac_addr, maclen, &mac_slot, mac_prefix_len, vid, vrid, af,
4788 4809 &linkid, proplist, flags);
4789 4810 switch (status) {
4790 4811 case DLADM_STATUS_OK:
4791 4812 break;
4792 4813
4793 4814 case DLADM_STATUS_LINKBUSY:
4794 4815 die("VLAN over '%s' may not use default_tag ID "
4795 4816 "(see dladm(1M))", devname);
4796 4817 break;
4797 4818
4798 4819 default:
4799 4820 die_dlerr(status, "vnic creation over %s failed", devname);
4800 4821 }
4801 4822
4802 4823 dladm_free_props(proplist);
4803 4824 free(mac_addr);
4804 4825 }
4805 4826
4806 4827 static void
4807 4828 do_etherstub_check(const char *name, datalink_id_t linkid, boolean_t etherstub,
4808 4829 uint32_t flags)
4809 4830 {
4810 4831 boolean_t is_etherstub;
4811 4832 dladm_vnic_attr_t attr;
4812 4833
4813 4834 if (dladm_vnic_info(handle, linkid, &attr, flags) != DLADM_STATUS_OK) {
4814 4835 /*
4815 4836 * Let the delete continue anyway.
4816 4837 */
4817 4838 return;
4818 4839 }
4819 4840 is_etherstub = (attr.va_link_id == DATALINK_INVALID_LINKID);
4820 4841 if (is_etherstub != etherstub) {
4821 4842 die("'%s' is not %s", name,
4822 4843 (is_etherstub ? "a vnic" : "an etherstub"));
4823 4844 }
4824 4845 }
|
↓ open down ↓ |
71 lines elided |
↑ open up ↑ |
4825 4846
4826 4847 static void
4827 4848 do_delete_vnic_common(int argc, char *argv[], const char *use,
4828 4849 boolean_t etherstub)
4829 4850 {
4830 4851 int option;
4831 4852 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
4832 4853 datalink_id_t linkid;
4833 4854 char *altroot = NULL;
4834 4855 dladm_status_t status;
4856 + char *zonename = NULL;
4835 4857
4836 4858 opterr = 0;
4837 - while ((option = getopt_long(argc, argv, ":R:t", lopts,
4859 + while ((option = getopt_long(argc, argv, ":R:tz:", lopts,
4838 4860 NULL)) != -1) {
4839 4861 switch (option) {
4840 4862 case 't':
4841 4863 flags &= ~DLADM_OPT_PERSIST;
4842 4864 break;
4843 4865 case 'R':
4844 4866 altroot = optarg;
4845 4867 break;
4868 + case 'z':
4869 + zonename = optarg;
4870 + break;
4846 4871 default:
4847 4872 die_opterr(optopt, option, use);
4848 4873 }
4849 4874 }
4850 4875
4851 4876 /* get vnic name (required last argument) */
4852 4877 if (optind != (argc - 1))
4853 4878 usage();
4854 4879
4855 4880 if (altroot != NULL)
4856 4881 altroot_cmd(altroot, argc, argv);
4857 4882
4858 - status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
4859 - NULL);
4883 + status = dladm_zname2info(handle, zonename, argv[optind], &linkid, NULL,
4884 + NULL, NULL);
4860 4885 if (status != DLADM_STATUS_OK)
4861 4886 die("invalid link name '%s'", argv[optind]);
4862 4887
4863 4888 if ((flags & DLADM_OPT_ACTIVE) != 0) {
4864 4889 do_etherstub_check(argv[optind], linkid, etherstub,
4865 4890 DLADM_OPT_ACTIVE);
4866 4891 }
4867 4892 if ((flags & DLADM_OPT_PERSIST) != 0) {
4868 4893 do_etherstub_check(argv[optind], linkid, etherstub,
4869 4894 DLADM_OPT_PERSIST);
4870 4895 }
4871 4896
4872 4897 status = dladm_vnic_delete(handle, linkid, flags);
4873 4898 if (status != DLADM_STATUS_OK)
4874 4899 die_dlerr(status, "vnic deletion failed");
4875 4900 }
4876 4901
4877 4902 static void
4878 4903 do_delete_vnic(int argc, char *argv[], const char *use)
4879 4904 {
4880 4905 do_delete_vnic_common(argc, argv, use, B_FALSE);
4881 4906 }
4882 4907
4883 4908 /* ARGSUSED */
4884 4909 static void
4885 4910 do_up_vnic_common(int argc, char *argv[], const char *use, boolean_t vlan)
4886 4911 {
4887 4912 datalink_id_t linkid = DATALINK_ALL_LINKID;
4888 4913 dladm_status_t status;
4889 4914 char *type;
4890 4915
4891 4916 type = vlan ? "vlan" : "vnic";
4892 4917
4893 4918 /*
4894 4919 * get the id or the name of the vnic/vlan (optional last argument)
4895 4920 */
4896 4921 if (argc == 2) {
4897 4922 status = dladm_name2info(handle, argv[1], &linkid, NULL, NULL,
4898 4923 NULL);
4899 4924 if (status != DLADM_STATUS_OK)
4900 4925 goto done;
4901 4926
4902 4927 } else if (argc > 2) {
4903 4928 usage();
4904 4929 }
4905 4930
4906 4931 if (vlan)
4907 4932 status = dladm_vlan_up(handle, linkid);
4908 4933 else
4909 4934 status = dladm_vnic_up(handle, linkid, 0);
4910 4935
4911 4936 done:
4912 4937 if (status != DLADM_STATUS_OK) {
4913 4938 if (argc == 2) {
4914 4939 die_dlerr(status,
4915 4940 "could not bring up %s '%s'", type, argv[1]);
4916 4941 } else {
4917 4942 die_dlerr(status, "could not bring %ss up", type);
4918 4943 }
4919 4944 }
4920 4945 }
4921 4946
4922 4947 static void
4923 4948 do_up_vnic(int argc, char *argv[], const char *use)
4924 4949 {
4925 4950 do_up_vnic_common(argc, argv, use, B_FALSE);
4926 4951 }
4927 4952
4928 4953 static void
4929 4954 dump_vnics_head(const char *dev)
4930 4955 {
4931 4956 if (strlen(dev))
4932 4957 (void) printf("%s", dev);
4933 4958
4934 4959 (void) printf("\tipackets rbytes opackets obytes ");
4935 4960
4936 4961 if (strlen(dev))
4937 4962 (void) printf("%%ipkts %%opkts\n");
4938 4963 else
4939 4964 (void) printf("\n");
4940 4965 }
4941 4966
4942 4967 static void
4943 4968 dump_vnic_stat(const char *name, datalink_id_t vnic_id,
4944 4969 show_vnic_state_t *state, pktsum_t *vnic_stats, pktsum_t *tot_stats)
4945 4970 {
4946 4971 pktsum_t diff_stats;
4947 4972 pktsum_t *old_stats = &state->vs_prevstats[vnic_id];
4948 4973
4949 4974 dladm_stats_diff(&diff_stats, vnic_stats, old_stats);
4950 4975
4951 4976 (void) printf("%s", name);
4952 4977
4953 4978 (void) printf("\t%-10llu", diff_stats.ipackets);
4954 4979 (void) printf("%-12llu", diff_stats.rbytes);
4955 4980 (void) printf("%-10llu", diff_stats.opackets);
4956 4981 (void) printf("%-12llu", diff_stats.obytes);
4957 4982
4958 4983 if (tot_stats) {
4959 4984 if (tot_stats->ipackets == 0) {
4960 4985 (void) printf("\t-");
4961 4986 } else {
4962 4987 (void) printf("\t%-6.1f", (double)diff_stats.ipackets/
4963 4988 (double)tot_stats->ipackets * 100);
4964 4989 }
4965 4990 if (tot_stats->opackets == 0) {
4966 4991 (void) printf("\t-");
4967 4992 } else {
4968 4993 (void) printf("\t%-6.1f", (double)diff_stats.opackets/
4969 4994 (double)tot_stats->opackets * 100);
4970 4995 }
4971 4996 }
4972 4997 (void) printf("\n");
4973 4998
4974 4999 *old_stats = *vnic_stats;
4975 5000 }
4976 5001
4977 5002 /*
4978 5003 * Called from the walker dladm_vnic_walk_sys() for each vnic to display
4979 5004 * vnic information or statistics.
4980 5005 */
|
↓ open down ↓ |
111 lines elided |
↑ open up ↑ |
4981 5006 static dladm_status_t
4982 5007 print_vnic(show_vnic_state_t *state, datalink_id_t linkid)
4983 5008 {
4984 5009 dladm_vnic_attr_t attr, *vnic = &attr;
4985 5010 dladm_status_t status;
4986 5011 boolean_t is_etherstub;
4987 5012 char devname[MAXLINKNAMELEN];
4988 5013 char vnic_name[MAXLINKNAMELEN];
4989 5014 char mstr[MAXMACADDRLEN * 3];
4990 5015 vnic_fields_buf_t vbuf;
5016 + uint_t valcnt = 1;
5017 + char zonename[DLADM_PROP_VAL_MAX + 1];
5018 + char *valptr[1];
4991 5019
4992 5020 if ((status = dladm_vnic_info(handle, linkid, vnic, state->vs_flags)) !=
4993 5021 DLADM_STATUS_OK)
4994 5022 return (status);
4995 5023
4996 5024 is_etherstub = (vnic->va_link_id == DATALINK_INVALID_LINKID);
4997 5025 if (state->vs_etherstub != is_etherstub) {
4998 5026 /*
4999 5027 * Want all etherstub but it's not one, or want
5000 5028 * non-etherstub and it's one.
5001 5029 */
5002 5030 return (DLADM_STATUS_OK);
5003 5031 }
5004 5032
5005 5033 if (state->vs_link_id != DATALINK_ALL_LINKID) {
5006 5034 if (state->vs_link_id != vnic->va_link_id)
5007 5035 return (DLADM_STATUS_OK);
5008 5036 }
5009 5037
|
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
5010 5038 if (dladm_datalink_id2info(handle, linkid, NULL, NULL,
5011 5039 NULL, vnic_name, sizeof (vnic_name)) != DLADM_STATUS_OK)
5012 5040 return (DLADM_STATUS_BADARG);
5013 5041
5014 5042 bzero(devname, sizeof (devname));
5015 5043 if (!is_etherstub &&
5016 5044 dladm_datalink_id2info(handle, vnic->va_link_id, NULL, NULL,
5017 5045 NULL, devname, sizeof (devname)) != DLADM_STATUS_OK)
5018 5046 (void) sprintf(devname, "?");
5019 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 +
5020 5060 state->vs_found = B_TRUE;
5021 5061 if (state->vs_stats) {
5022 5062 /* print vnic statistics */
5023 5063 pktsum_t vnic_stats;
5024 5064
5025 5065 if (state->vs_firstonly) {
5026 5066 if (state->vs_donefirst)
5027 5067 return (0);
5028 5068 state->vs_donefirst = B_TRUE;
5029 5069 }
5030 5070
5031 5071 if (!state->vs_printstats) {
5032 5072 /*
5033 5073 * get vnic statistics and add to the sum for the
5034 5074 * named device.
5035 5075 */
5036 5076 get_link_stats(vnic_name, &vnic_stats);
5037 5077 dladm_stats_total(&state->vs_totalstats, &vnic_stats,
5038 5078 &state->vs_prevstats[vnic->va_vnic_id]);
5039 5079 } else {
5040 5080 /* get and print vnic statistics */
5041 5081 get_link_stats(vnic_name, &vnic_stats);
5042 5082 dump_vnic_stat(vnic_name, linkid, state, &vnic_stats,
5043 5083 &state->vs_totalstats);
5044 5084 }
5045 5085 return (DLADM_STATUS_OK);
5046 5086 } else {
5047 5087 (void) snprintf(vbuf.vnic_link, sizeof (vbuf.vnic_link),
5048 5088 "%s", vnic_name);
5049 5089
5050 5090 if (!is_etherstub) {
5051 5091
5052 5092 (void) snprintf(vbuf.vnic_over, sizeof (vbuf.vnic_over),
5053 5093 "%s", devname);
5054 5094 (void) snprintf(vbuf.vnic_speed,
5055 5095 sizeof (vbuf.vnic_speed), "%u",
5056 5096 (uint_t)((get_ifspeed(vnic_name, B_TRUE))
5057 5097 / 1000000ull));
5058 5098
5059 5099 switch (vnic->va_mac_addr_type) {
5060 5100 case VNIC_MAC_ADDR_TYPE_FIXED:
5061 5101 case VNIC_MAC_ADDR_TYPE_PRIMARY:
5062 5102 (void) snprintf(vbuf.vnic_macaddrtype,
5063 5103 sizeof (vbuf.vnic_macaddrtype),
5064 5104 gettext("fixed"));
5065 5105 break;
5066 5106 case VNIC_MAC_ADDR_TYPE_RANDOM:
5067 5107 (void) snprintf(vbuf.vnic_macaddrtype,
5068 5108 sizeof (vbuf.vnic_macaddrtype),
5069 5109 gettext("random"));
5070 5110 break;
5071 5111 case VNIC_MAC_ADDR_TYPE_FACTORY:
5072 5112 (void) snprintf(vbuf.vnic_macaddrtype,
5073 5113 sizeof (vbuf.vnic_macaddrtype),
5074 5114 gettext("factory, slot %d"),
5075 5115 vnic->va_mac_slot);
5076 5116 break;
5077 5117 case VNIC_MAC_ADDR_TYPE_VRID:
5078 5118 (void) snprintf(vbuf.vnic_macaddrtype,
5079 5119 sizeof (vbuf.vnic_macaddrtype),
5080 5120 gettext("vrrp, %d/%s"),
5081 5121 vnic->va_vrid, vnic->va_af == AF_INET ?
5082 5122 "inet" : "inet6");
5083 5123 break;
5084 5124 }
|
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
5085 5125
5086 5126 if (strlen(vbuf.vnic_macaddrtype) > 0) {
5087 5127 (void) snprintf(vbuf.vnic_macaddr,
5088 5128 sizeof (vbuf.vnic_macaddr), "%s",
5089 5129 dladm_aggr_macaddr2str(vnic->va_mac_addr,
5090 5130 mstr));
5091 5131 }
5092 5132
5093 5133 (void) snprintf(vbuf.vnic_vid, sizeof (vbuf.vnic_vid),
5094 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));
5095 5142 }
5096 5143
5097 5144 ofmt_print(state->vs_ofmt, &vbuf);
5098 5145
5099 5146 return (DLADM_STATUS_OK);
5100 5147 }
5101 5148 }
5102 5149
5103 5150 /* ARGSUSED */
5104 5151 static int
5105 5152 show_vnic(dladm_handle_t dh, datalink_id_t linkid, void *arg)
5106 5153 {
5107 5154 show_vnic_state_t *state = arg;
5108 5155
5109 5156 state->vs_status = print_vnic(state, linkid);
5110 5157 return (DLADM_WALK_CONTINUE);
5111 5158 }
5112 5159
5113 5160 static void
5114 5161 do_show_vnic_common(int argc, char *argv[], const char *use,
5115 5162 boolean_t etherstub)
5116 5163 {
5117 5164 int option;
5118 5165 boolean_t s_arg = B_FALSE;
5119 5166 boolean_t i_arg = B_FALSE;
5120 5167 boolean_t l_arg = B_FALSE;
5121 5168 uint32_t interval = 0, flags = DLADM_OPT_ACTIVE;
5122 5169 datalink_id_t linkid = DATALINK_ALL_LINKID;
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
5123 5170 datalink_id_t dev_linkid = DATALINK_ALL_LINKID;
5124 5171 show_vnic_state_t state;
5125 5172 dladm_status_t status;
5126 5173 boolean_t o_arg = B_FALSE;
5127 5174 char *fields_str = NULL;
5128 5175 const ofmt_field_t *pf;
5129 5176 char *all_e_fields = "link";
5130 5177 ofmt_handle_t ofmt;
5131 5178 ofmt_status_t oferr;
5132 5179 uint_t ofmtflags = 0;
5180 + char *zonename = NULL;
5133 5181
5134 5182 bzero(&state, sizeof (state));
5135 5183 opterr = 0;
5136 - while ((option = getopt_long(argc, argv, ":pPl:si:o:", lopts,
5184 + while ((option = getopt_long(argc, argv, ":pPl:si:o:z:", lopts,
5137 5185 NULL)) != -1) {
5138 5186 switch (option) {
5139 5187 case 'p':
5140 5188 state.vs_parsable = B_TRUE;
5141 5189 break;
5142 5190 case 'P':
5143 5191 flags = DLADM_OPT_PERSIST;
5144 5192 break;
5145 5193 case 'l':
5146 5194 if (etherstub)
5147 5195 die("option not supported for this command");
5148 5196
5149 5197 if (strlcpy(state.vs_link, optarg, MAXLINKNAMELEN) >=
5150 5198 MAXLINKNAMELEN)
5151 5199 die("link name too long");
5152 5200
5153 5201 l_arg = B_TRUE;
5154 5202 break;
5155 5203 case 's':
5156 5204 if (s_arg) {
5157 5205 die("the option -s cannot be specified "
5158 5206 "more than once");
5159 5207 }
5160 5208 s_arg = B_TRUE;
5161 5209 break;
5162 5210 case 'i':
5163 5211 if (i_arg) {
5164 5212 die("the option -i cannot be specified "
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
5165 5213 "more than once");
5166 5214 }
5167 5215 i_arg = B_TRUE;
5168 5216 if (!dladm_str2interval(optarg, &interval))
5169 5217 die("invalid interval value '%s'", optarg);
5170 5218 break;
5171 5219 case 'o':
5172 5220 o_arg = B_TRUE;
5173 5221 fields_str = optarg;
5174 5222 break;
5223 + case 'z':
5224 + zonename = optarg;
5225 + break;
5175 5226 default:
5176 5227 die_opterr(optopt, option, use);
5177 5228 }
5178 5229 }
5179 5230
5180 5231 if (i_arg && !s_arg)
5181 5232 die("the option -i can be used only with -s");
5182 5233
5183 5234 /* get vnic ID (optional last argument) */
5184 5235 if (optind == (argc - 1)) {
5185 - status = dladm_name2info(handle, argv[optind], &linkid, NULL,
5186 - NULL, NULL);
5236 + status = dladm_zname2info(handle, zonename, argv[optind],
5237 + &linkid, NULL, NULL, NULL);
5187 5238 if (status != DLADM_STATUS_OK) {
5188 5239 die_dlerr(status, "invalid vnic name '%s'",
5189 5240 argv[optind]);
5190 5241 }
5191 5242 (void) strlcpy(state.vs_vnic, argv[optind], MAXLINKNAMELEN);
5192 5243 } else if (optind != argc) {
5193 5244 usage();
5194 5245 }
5195 5246
5196 5247 if (l_arg) {
5197 - status = dladm_name2info(handle, state.vs_link, &dev_linkid,
5198 - NULL, NULL, NULL);
5248 + status = dladm_zname2info(handle, zonename, state.vs_link,
5249 + &dev_linkid, NULL, NULL, NULL);
5199 5250 if (status != DLADM_STATUS_OK) {
5200 5251 die_dlerr(status, "invalid link name '%s'",
5201 5252 state.vs_link);
5202 5253 }
5203 5254 }
5204 5255
5205 5256 state.vs_vnic_id = linkid;
5206 5257 state.vs_link_id = dev_linkid;
5207 5258 state.vs_etherstub = etherstub;
5208 5259 state.vs_found = B_FALSE;
5209 5260 state.vs_flags = flags;
5261 + state.vs_zonename = zonename;
5210 5262
5211 5263 if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
5212 5264 if (etherstub)
5213 5265 fields_str = all_e_fields;
5214 5266 }
5215 5267 pf = vnic_fields;
5216 5268
5217 5269 if (state.vs_parsable)
5218 5270 ofmtflags |= OFMT_PARSABLE;
5219 5271 oferr = ofmt_open(fields_str, pf, ofmtflags, 0, &ofmt);
5220 5272 dladm_ofmt_check(oferr, state.vs_parsable, ofmt);
5221 5273 state.vs_ofmt = ofmt;
5222 5274
5223 5275 if (s_arg) {
5224 5276 /* Display vnic statistics */
5225 5277 vnic_stats(&state, interval);
5226 5278 ofmt_close(ofmt);
5227 5279 return;
5228 5280 }
5229 5281
5230 5282 /* Display vnic information */
5231 5283 state.vs_donefirst = B_FALSE;
5232 5284
5233 5285 if (linkid == DATALINK_ALL_LINKID) {
5234 5286 (void) dladm_walk_datalink_id(show_vnic, handle, &state,
5235 5287 DATALINK_CLASS_VNIC | DATALINK_CLASS_ETHERSTUB,
5236 5288 DATALINK_ANY_MEDIATYPE, flags);
5237 5289 } else {
5238 5290 (void) show_vnic(handle, linkid, &state);
5239 5291 if (state.vs_status != DLADM_STATUS_OK) {
5240 5292 ofmt_close(ofmt);
5241 5293 die_dlerr(state.vs_status, "failed to show vnic '%s'",
5242 5294 state.vs_vnic);
5243 5295 }
5244 5296 }
5245 5297 ofmt_close(ofmt);
5246 5298 }
5247 5299
5248 5300 static void
5249 5301 do_show_vnic(int argc, char *argv[], const char *use)
5250 5302 {
5251 5303 do_show_vnic_common(argc, argv, use, B_FALSE);
5252 5304 }
5253 5305
5254 5306 static void
5255 5307 do_create_etherstub(int argc, char *argv[], const char *use)
5256 5308 {
5257 5309 uint32_t flags;
5258 5310 char *altroot = NULL;
5259 5311 int option;
5260 5312 dladm_status_t status;
5261 5313 char name[MAXLINKNAMELEN];
5262 5314 uchar_t mac_addr[ETHERADDRL];
5263 5315
5264 5316 name[0] = '\0';
5265 5317 bzero(mac_addr, sizeof (mac_addr));
5266 5318 flags = DLADM_OPT_ANCHOR | DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
5267 5319
5268 5320 opterr = 0;
5269 5321 while ((option = getopt_long(argc, argv, "tR:",
5270 5322 etherstub_lopts, NULL)) != -1) {
5271 5323 switch (option) {
5272 5324 case 't':
5273 5325 flags &= ~DLADM_OPT_PERSIST;
5274 5326 break;
5275 5327 case 'R':
5276 5328 altroot = optarg;
5277 5329 break;
5278 5330 default:
5279 5331 die_opterr(optopt, option, use);
5280 5332 }
5281 5333 }
5282 5334
5283 5335 /* the etherstub id is the required operand */
5284 5336 if (optind != (argc - 1))
5285 5337 usage();
5286 5338
5287 5339 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
5288 5340 die("link name too long '%s'", argv[optind]);
5289 5341
5290 5342 if (!dladm_valid_linkname(name))
5291 5343 die("invalid link name '%s'", argv[optind]);
5292 5344
5293 5345 if (altroot != NULL)
5294 5346 altroot_cmd(altroot, argc, argv);
5295 5347
5296 5348 status = dladm_vnic_create(handle, name, DATALINK_INVALID_LINKID,
5297 5349 VNIC_MAC_ADDR_TYPE_AUTO, mac_addr, ETHERADDRL, NULL, 0, 0,
5298 5350 VRRP_VRID_NONE, AF_UNSPEC, NULL, NULL, flags);
5299 5351 if (status != DLADM_STATUS_OK)
5300 5352 die_dlerr(status, "etherstub creation failed");
5301 5353 }
5302 5354
5303 5355 static void
5304 5356 do_delete_etherstub(int argc, char *argv[], const char *use)
5305 5357 {
5306 5358 do_delete_vnic_common(argc, argv, use, B_TRUE);
5307 5359 }
5308 5360
5309 5361 /* ARGSUSED */
5310 5362 static void
5311 5363 do_show_etherstub(int argc, char *argv[], const char *use)
5312 5364 {
5313 5365 do_show_vnic_common(argc, argv, use, B_TRUE);
5314 5366 }
5315 5367
5316 5368 /* ARGSUSED */
5317 5369 static void
5318 5370 do_up_simnet(int argc, char *argv[], const char *use)
5319 5371 {
5320 5372 (void) dladm_simnet_up(handle, DATALINK_ALL_LINKID, 0);
5321 5373 }
5322 5374
5323 5375 static void
5324 5376 do_create_simnet(int argc, char *argv[], const char *use)
5325 5377 {
5326 5378 uint32_t flags;
5327 5379 char *altroot = NULL;
5328 5380 char *media = NULL;
5329 5381 uint32_t mtype = DL_ETHER;
5330 5382 int option;
5331 5383 dladm_status_t status;
5332 5384 char name[MAXLINKNAMELEN];
5333 5385
5334 5386 name[0] = '\0';
5335 5387 flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
5336 5388
5337 5389 opterr = 0;
5338 5390 while ((option = getopt_long(argc, argv, ":tR:m:",
5339 5391 simnet_lopts, NULL)) != -1) {
5340 5392 switch (option) {
5341 5393 case 't':
5342 5394 flags &= ~DLADM_OPT_PERSIST;
5343 5395 break;
5344 5396 case 'R':
5345 5397 altroot = optarg;
5346 5398 break;
5347 5399 case 'm':
5348 5400 media = optarg;
5349 5401 break;
5350 5402 default:
5351 5403 die_opterr(optopt, option, use);
5352 5404 }
5353 5405 }
5354 5406
5355 5407 /* the simnet id is the required operand */
5356 5408 if (optind != (argc - 1))
5357 5409 usage();
5358 5410
5359 5411 if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >= MAXLINKNAMELEN)
5360 5412 die("link name too long '%s'", argv[optind]);
5361 5413
5362 5414 if (!dladm_valid_linkname(name))
5363 5415 die("invalid link name '%s'", name);
5364 5416
5365 5417 if (media != NULL) {
5366 5418 mtype = dladm_str2media(media);
5367 5419 if (mtype != DL_ETHER && mtype != DL_WIFI)
5368 5420 die("media type '%s' is not supported", media);
5369 5421 }
5370 5422
5371 5423 if (altroot != NULL)
5372 5424 altroot_cmd(altroot, argc, argv);
5373 5425
5374 5426 status = dladm_simnet_create(handle, name, mtype, flags);
5375 5427 if (status != DLADM_STATUS_OK)
5376 5428 die_dlerr(status, "simnet creation failed");
5377 5429 }
5378 5430
5379 5431 static void
5380 5432 do_delete_simnet(int argc, char *argv[], const char *use)
5381 5433 {
5382 5434 int option;
5383 5435 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
5384 5436 datalink_id_t linkid;
5385 5437 char *altroot = NULL;
5386 5438 dladm_status_t status;
5387 5439 dladm_simnet_attr_t slinfo;
5388 5440
5389 5441 opterr = 0;
5390 5442 while ((option = getopt_long(argc, argv, ":tR:", simnet_lopts,
5391 5443 NULL)) != -1) {
5392 5444 switch (option) {
5393 5445 case 't':
5394 5446 flags &= ~DLADM_OPT_PERSIST;
5395 5447 break;
5396 5448 case 'R':
5397 5449 altroot = optarg;
5398 5450 break;
5399 5451 default:
5400 5452 die_opterr(optopt, option, use);
5401 5453 }
5402 5454 }
5403 5455
5404 5456 /* get simnet name (required last argument) */
5405 5457 if (optind != (argc - 1))
5406 5458 usage();
5407 5459
5408 5460 if (!dladm_valid_linkname(argv[optind]))
5409 5461 die("invalid link name '%s'", argv[optind]);
5410 5462
5411 5463 if (altroot != NULL)
5412 5464 altroot_cmd(altroot, argc, argv);
5413 5465
5414 5466 status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
5415 5467 NULL);
5416 5468 if (status != DLADM_STATUS_OK)
5417 5469 die("simnet '%s' not found", argv[optind]);
5418 5470
5419 5471 if ((status = dladm_simnet_info(handle, linkid, &slinfo,
5420 5472 flags)) != DLADM_STATUS_OK)
5421 5473 die_dlerr(status, "failed to retrieve simnet information");
5422 5474
5423 5475 status = dladm_simnet_delete(handle, linkid, flags);
5424 5476 if (status != DLADM_STATUS_OK)
5425 5477 die_dlerr(status, "simnet deletion failed");
5426 5478 }
5427 5479
5428 5480 static void
5429 5481 do_modify_simnet(int argc, char *argv[], const char *use)
5430 5482 {
5431 5483 int option;
5432 5484 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
5433 5485 datalink_id_t linkid;
5434 5486 datalink_id_t peer_linkid;
5435 5487 char *altroot = NULL;
5436 5488 dladm_status_t status;
5437 5489 boolean_t p_arg = B_FALSE;
5438 5490
5439 5491 opterr = 0;
5440 5492 while ((option = getopt_long(argc, argv, ":tR:p:", simnet_lopts,
5441 5493 NULL)) != -1) {
5442 5494 switch (option) {
5443 5495 case 't':
5444 5496 flags &= ~DLADM_OPT_PERSIST;
5445 5497 break;
5446 5498 case 'R':
5447 5499 altroot = optarg;
5448 5500 break;
5449 5501 case 'p':
5450 5502 if (p_arg)
5451 5503 die_optdup(option);
5452 5504 p_arg = B_TRUE;
5453 5505 if (strcasecmp(optarg, "none") == 0)
5454 5506 peer_linkid = DATALINK_INVALID_LINKID;
5455 5507 else if (dladm_name2info(handle, optarg, &peer_linkid,
5456 5508 NULL, NULL, NULL) != DLADM_STATUS_OK)
5457 5509 die("invalid peer link name '%s'", optarg);
5458 5510 break;
5459 5511 default:
5460 5512 die_opterr(optopt, option, use);
5461 5513 }
5462 5514 }
5463 5515
5464 5516 /* get simnet name (required last argument) */
5465 5517 if (optind != (argc - 1))
5466 5518 usage();
5467 5519
5468 5520 /* Nothing to do if no peer link argument */
5469 5521 if (!p_arg)
5470 5522 return;
5471 5523
5472 5524 if (altroot != NULL)
5473 5525 altroot_cmd(altroot, argc, argv);
5474 5526
5475 5527 status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
5476 5528 NULL);
5477 5529 if (status != DLADM_STATUS_OK)
5478 5530 die("invalid link name '%s'", argv[optind]);
5479 5531
5480 5532 status = dladm_simnet_modify(handle, linkid, peer_linkid, flags);
5481 5533 if (status != DLADM_STATUS_OK)
5482 5534 die_dlerr(status, "simnet modification failed");
5483 5535 }
5484 5536
5485 5537 static dladm_status_t
5486 5538 print_simnet(show_state_t *state, datalink_id_t linkid)
5487 5539 {
5488 5540 dladm_simnet_attr_t slinfo;
5489 5541 uint32_t flags;
5490 5542 dladm_status_t status;
5491 5543 simnet_fields_buf_t slbuf;
5492 5544 char mstr[ETHERADDRL * 3];
5493 5545
5494 5546 bzero(&slbuf, sizeof (slbuf));
5495 5547 if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, NULL,
5496 5548 slbuf.simnet_name, sizeof (slbuf.simnet_name)))
5497 5549 != DLADM_STATUS_OK)
5498 5550 return (status);
5499 5551
5500 5552 if (!(state->ls_flags & flags))
5501 5553 return (DLADM_STATUS_NOTFOUND);
5502 5554
5503 5555 if ((status = dladm_simnet_info(handle, linkid, &slinfo,
5504 5556 state->ls_flags)) != DLADM_STATUS_OK)
5505 5557 return (status);
5506 5558
5507 5559 if (slinfo.sna_peer_link_id != DATALINK_INVALID_LINKID &&
5508 5560 (status = dladm_datalink_id2info(handle, slinfo.sna_peer_link_id,
5509 5561 NULL, NULL, NULL, slbuf.simnet_otherlink,
5510 5562 sizeof (slbuf.simnet_otherlink))) !=
5511 5563 DLADM_STATUS_OK)
5512 5564 return (status);
5513 5565
5514 5566 if (slinfo.sna_mac_len > sizeof (slbuf.simnet_macaddr))
5515 5567 return (DLADM_STATUS_BADVAL);
5516 5568
5517 5569 (void) strlcpy(slbuf.simnet_macaddr,
5518 5570 dladm_aggr_macaddr2str(slinfo.sna_mac_addr, mstr),
5519 5571 sizeof (slbuf.simnet_macaddr));
5520 5572 (void) dladm_media2str(slinfo.sna_type, slbuf.simnet_media);
5521 5573
5522 5574 ofmt_print(state->ls_ofmt, &slbuf);
5523 5575 return (status);
5524 5576 }
5525 5577
5526 5578 /* ARGSUSED */
5527 5579 static int
5528 5580 show_simnet(dladm_handle_t dh, datalink_id_t linkid, void *arg)
5529 5581 {
5530 5582 show_state_t *state = arg;
5531 5583
5532 5584 state->ls_status = print_simnet(state, linkid);
5533 5585 return (DLADM_WALK_CONTINUE);
5534 5586 }
5535 5587
5536 5588 static void
5537 5589 do_show_simnet(int argc, char *argv[], const char *use)
5538 5590 {
5539 5591 int option;
5540 5592 uint32_t flags = DLADM_OPT_ACTIVE;
5541 5593 boolean_t p_arg = B_FALSE;
5542 5594 datalink_id_t linkid = DATALINK_ALL_LINKID;
5543 5595 show_state_t state;
5544 5596 dladm_status_t status;
5545 5597 boolean_t o_arg = B_FALSE;
5546 5598 ofmt_handle_t ofmt;
5547 5599 ofmt_status_t oferr;
5548 5600 char *all_fields = "link,media,macaddress,otherlink";
5549 5601 char *fields_str = all_fields;
5550 5602 uint_t ofmtflags = 0;
5551 5603
5552 5604 bzero(&state, sizeof (state));
5553 5605
5554 5606 opterr = 0;
5555 5607 while ((option = getopt_long(argc, argv, ":pPo:",
5556 5608 show_lopts, NULL)) != -1) {
5557 5609 switch (option) {
5558 5610 case 'p':
5559 5611 if (p_arg)
5560 5612 die_optdup(option);
5561 5613
5562 5614 p_arg = B_TRUE;
5563 5615 state.ls_parsable = p_arg;
5564 5616 break;
5565 5617 case 'P':
5566 5618 if (flags != DLADM_OPT_ACTIVE)
5567 5619 die_optdup(option);
5568 5620
5569 5621 flags = DLADM_OPT_PERSIST;
5570 5622 break;
5571 5623 case 'o':
5572 5624 o_arg = B_TRUE;
5573 5625 fields_str = optarg;
5574 5626 break;
5575 5627 default:
5576 5628 die_opterr(optopt, option, use);
5577 5629 break;
5578 5630 }
5579 5631 }
5580 5632
5581 5633 if (p_arg && !o_arg)
5582 5634 die("-p requires -o");
5583 5635
5584 5636 if (strcasecmp(fields_str, "all") == 0) {
5585 5637 if (p_arg)
5586 5638 die("\"-o all\" is invalid with -p");
5587 5639 fields_str = all_fields;
5588 5640 }
5589 5641
5590 5642 /* get link name (optional last argument) */
5591 5643 if (optind == (argc-1)) {
5592 5644 if ((status = dladm_name2info(handle, argv[optind], &linkid,
5593 5645 NULL, NULL, NULL)) != DLADM_STATUS_OK) {
5594 5646 die_dlerr(status, "link %s is not valid", argv[optind]);
5595 5647 }
5596 5648 } else if (optind != argc) {
5597 5649 usage();
5598 5650 }
5599 5651
5600 5652 state.ls_flags = flags;
5601 5653 state.ls_donefirst = B_FALSE;
5602 5654 if (state.ls_parsable)
5603 5655 ofmtflags |= OFMT_PARSABLE;
5604 5656 oferr = ofmt_open(fields_str, simnet_fields, ofmtflags, 0, &ofmt);
5605 5657 dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
5606 5658 state.ls_ofmt = ofmt;
5607 5659
5608 5660 if (linkid == DATALINK_ALL_LINKID) {
5609 5661 (void) dladm_walk_datalink_id(show_simnet, handle, &state,
5610 5662 DATALINK_CLASS_SIMNET, DATALINK_ANY_MEDIATYPE, flags);
5611 5663 } else {
5612 5664 (void) show_simnet(handle, linkid, &state);
5613 5665 if (state.ls_status != DLADM_STATUS_OK) {
5614 5666 ofmt_close(ofmt);
5615 5667 die_dlerr(state.ls_status, "failed to show simnet %s",
5616 5668 argv[optind]);
5617 5669 }
5618 5670 }
5619 5671 ofmt_close(ofmt);
5620 5672 }
5621 5673
5622 5674 static void
5623 5675 link_stats(datalink_id_t linkid, uint_t interval, char *fields_str,
5624 5676 show_state_t *state)
5625 5677 {
5626 5678 ofmt_handle_t ofmt;
5627 5679 ofmt_status_t oferr;
5628 5680 uint_t ofmtflags = 0;
5629 5681
5630 5682 if (state->ls_parsable)
5631 5683 ofmtflags |= OFMT_PARSABLE;
5632 5684 oferr = ofmt_open(fields_str, link_s_fields, ofmtflags, 0, &ofmt);
5633 5685 dladm_ofmt_check(oferr, state->ls_parsable, ofmt);
5634 5686 state->ls_ofmt = ofmt;
5635 5687
5636 5688 /*
5637 5689 * If an interval is specified, continuously show the stats
5638 5690 * only for the first MAC port.
5639 5691 */
5640 5692 state->ls_firstonly = (interval != 0);
5641 5693
5642 5694 for (;;) {
5643 5695 state->ls_donefirst = B_FALSE;
5644 5696 if (linkid == DATALINK_ALL_LINKID) {
5645 5697 (void) dladm_walk_datalink_id(show_link_stats, handle,
5646 5698 state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
5647 5699 DLADM_OPT_ACTIVE);
5648 5700 } else {
5649 5701 (void) show_link_stats(handle, linkid, state);
5650 5702 }
5651 5703
5652 5704 if (interval == 0)
5653 5705 break;
5654 5706
5655 5707 (void) fflush(stdout);
5656 5708 (void) sleep(interval);
5657 5709 }
5658 5710 ofmt_close(ofmt);
5659 5711 }
5660 5712
5661 5713 static void
5662 5714 aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval)
5663 5715 {
5664 5716 /*
5665 5717 * If an interval is specified, continuously show the stats
5666 5718 * only for the first group.
5667 5719 */
5668 5720 state->gs_firstonly = (interval != 0);
5669 5721
5670 5722 for (;;) {
5671 5723 state->gs_donefirst = B_FALSE;
5672 5724 if (linkid == DATALINK_ALL_LINKID)
5673 5725 (void) dladm_walk_datalink_id(show_aggr, handle, state,
5674 5726 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE,
5675 5727 DLADM_OPT_ACTIVE);
5676 5728 else
5677 5729 (void) show_aggr(handle, linkid, state);
5678 5730
5679 5731 if (interval == 0)
5680 5732 break;
5681 5733
5682 5734 (void) fflush(stdout);
5683 5735 (void) sleep(interval);
5684 5736 }
5685 5737 }
5686 5738
5687 5739 /* ARGSUSED */
5688 5740 static void
5689 5741 vnic_stats(show_vnic_state_t *sp, uint32_t interval)
5690 5742 {
5691 5743 show_vnic_state_t state;
5692 5744 boolean_t specific_link, specific_dev;
5693 5745
5694 5746 /* Display vnic statistics */
5695 5747 dump_vnics_head(sp->vs_link);
5696 5748
5697 5749 bzero(&state, sizeof (state));
5698 5750 state.vs_stats = B_TRUE;
5699 5751 state.vs_vnic_id = sp->vs_vnic_id;
5700 5752 state.vs_link_id = sp->vs_link_id;
5701 5753
5702 5754 /*
5703 5755 * If an interval is specified, and a vnic ID is not specified,
5704 5756 * continuously show the stats only for the first vnic.
5705 5757 */
5706 5758 specific_link = (sp->vs_vnic_id != DATALINK_ALL_LINKID);
5707 5759 specific_dev = (sp->vs_link_id != DATALINK_ALL_LINKID);
5708 5760
5709 5761 for (;;) {
5710 5762 /* Get stats for each vnic */
5711 5763 state.vs_found = B_FALSE;
5712 5764 state.vs_donefirst = B_FALSE;
5713 5765 state.vs_printstats = B_FALSE;
5714 5766 state.vs_flags = DLADM_OPT_ACTIVE;
5715 5767
5716 5768 if (!specific_link) {
5717 5769 (void) dladm_walk_datalink_id(show_vnic, handle, &state,
5718 5770 DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE,
5719 5771 DLADM_OPT_ACTIVE);
5720 5772 } else {
5721 5773 (void) show_vnic(handle, sp->vs_vnic_id, &state);
5722 5774 if (state.vs_status != DLADM_STATUS_OK) {
5723 5775 die_dlerr(state.vs_status,
5724 5776 "failed to show vnic '%s'", sp->vs_vnic);
5725 5777 }
5726 5778 }
5727 5779
5728 5780 if (specific_link && !state.vs_found)
5729 5781 die("non-existent vnic '%s'", sp->vs_vnic);
5730 5782 if (specific_dev && !state.vs_found)
5731 5783 die("device %s has no vnics", sp->vs_link);
5732 5784
5733 5785 /* Show totals */
5734 5786 if ((specific_link | specific_dev) && !interval) {
5735 5787 (void) printf("Total");
5736 5788 (void) printf("\t%-10llu",
5737 5789 state.vs_totalstats.ipackets);
5738 5790 (void) printf("%-12llu",
5739 5791 state.vs_totalstats.rbytes);
5740 5792 (void) printf("%-10llu",
5741 5793 state.vs_totalstats.opackets);
5742 5794 (void) printf("%-12llu\n",
5743 5795 state.vs_totalstats.obytes);
5744 5796 }
5745 5797
5746 5798 /* Show stats for each vnic */
5747 5799 state.vs_donefirst = B_FALSE;
5748 5800 state.vs_printstats = B_TRUE;
5749 5801
5750 5802 if (!specific_link) {
5751 5803 (void) dladm_walk_datalink_id(show_vnic, handle, &state,
5752 5804 DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE,
5753 5805 DLADM_OPT_ACTIVE);
5754 5806 } else {
5755 5807 (void) show_vnic(handle, sp->vs_vnic_id, &state);
5756 5808 if (state.vs_status != DLADM_STATUS_OK) {
5757 5809 die_dlerr(state.vs_status,
5758 5810 "failed to show vnic '%s'", sp->vs_vnic);
5759 5811 }
5760 5812 }
5761 5813
5762 5814 if (interval == 0)
5763 5815 break;
5764 5816
5765 5817 (void) fflush(stdout);
5766 5818 (void) sleep(interval);
5767 5819 }
5768 5820 }
5769 5821
5770 5822 static void
5771 5823 get_mac_stats(const char *dev, pktsum_t *stats)
5772 5824 {
5773 5825 kstat_ctl_t *kcp;
5774 5826 kstat_t *ksp;
5775 5827 char module[DLPI_LINKNAME_MAX];
5776 5828 uint_t instance;
5777 5829
5778 5830
5779 5831 bzero(stats, sizeof (*stats));
5780 5832
5781 5833 if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS)
5782 5834 return;
5783 5835
5784 5836 if ((kcp = kstat_open()) == NULL) {
5785 5837 warn("kstat open operation failed");
5786 5838 return;
5787 5839 }
5788 5840
5789 5841 ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL);
5790 5842 if (ksp != NULL)
5791 5843 dladm_get_stats(kcp, ksp, stats);
5792 5844
5793 5845 (void) kstat_close(kcp);
5794 5846
5795 5847 }
5796 5848
5797 5849 static void
5798 5850 get_link_stats(const char *link, pktsum_t *stats)
5799 5851 {
5800 5852 kstat_ctl_t *kcp;
5801 5853 kstat_t *ksp;
5802 5854
5803 5855 bzero(stats, sizeof (*stats));
5804 5856
5805 5857 if ((kcp = kstat_open()) == NULL) {
5806 5858 warn("kstat_open operation failed");
5807 5859 return;
5808 5860 }
5809 5861
5810 5862 ksp = dladm_kstat_lookup(kcp, "link", 0, link, NULL);
5811 5863
5812 5864 if (ksp != NULL)
5813 5865 dladm_get_stats(kcp, ksp, stats);
5814 5866
5815 5867 (void) kstat_close(kcp);
5816 5868 }
5817 5869
5818 5870 static int
5819 5871 query_kstat(char *module, int instance, const char *name, const char *stat,
5820 5872 uint8_t type, void *val)
5821 5873 {
5822 5874 kstat_ctl_t *kcp;
5823 5875 kstat_t *ksp;
5824 5876
5825 5877 if ((kcp = kstat_open()) == NULL) {
5826 5878 warn("kstat open operation failed");
5827 5879 return (-1);
5828 5880 }
5829 5881
5830 5882 if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) {
5831 5883 /*
5832 5884 * The kstat query could fail if the underlying MAC
5833 5885 * driver was already detached.
5834 5886 */
5835 5887 goto bail;
5836 5888 }
5837 5889
5838 5890 if (kstat_read(kcp, ksp, NULL) == -1) {
5839 5891 warn("kstat read failed");
5840 5892 goto bail;
5841 5893 }
5842 5894
5843 5895 if (dladm_kstat_value(ksp, stat, type, val) < 0)
5844 5896 goto bail;
5845 5897
5846 5898 (void) kstat_close(kcp);
5847 5899 return (0);
5848 5900
5849 5901 bail:
5850 5902 (void) kstat_close(kcp);
5851 5903 return (-1);
5852 5904 }
5853 5905
5854 5906 static int
5855 5907 get_one_kstat(const char *name, const char *stat, uint8_t type,
5856 5908 void *val, boolean_t islink)
5857 5909 {
5858 5910 char module[DLPI_LINKNAME_MAX];
5859 5911 uint_t instance;
5860 5912
5861 5913 if (islink) {
5862 5914 return (query_kstat("link", 0, name, stat, type, val));
5863 5915 } else {
5864 5916 if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS)
5865 5917 return (-1);
5866 5918
5867 5919 return (query_kstat(module, instance, "mac", stat, type, val));
5868 5920 }
5869 5921 }
5870 5922
5871 5923 static uint64_t
5872 5924 get_ifspeed(const char *name, boolean_t islink)
5873 5925 {
5874 5926 uint64_t ifspeed = 0;
5875 5927
5876 5928 (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64,
5877 5929 &ifspeed, islink);
5878 5930
5879 5931 return (ifspeed);
5880 5932 }
5881 5933
5882 5934 static const char *
5883 5935 get_linkstate(const char *name, boolean_t islink, char *buf)
5884 5936 {
5885 5937 link_state_t linkstate;
5886 5938
5887 5939 if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32,
5888 5940 &linkstate, islink) != 0) {
5889 5941 (void) strlcpy(buf, "?", DLADM_STRSIZE);
5890 5942 return (buf);
5891 5943 }
5892 5944 return (dladm_linkstate2str(linkstate, buf));
5893 5945 }
5894 5946
5895 5947 static const char *
5896 5948 get_linkduplex(const char *name, boolean_t islink, char *buf)
5897 5949 {
5898 5950 link_duplex_t linkduplex;
5899 5951
5900 5952 if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32,
5901 5953 &linkduplex, islink) != 0) {
5902 5954 (void) strlcpy(buf, "unknown", DLADM_STRSIZE);
5903 5955 return (buf);
5904 5956 }
5905 5957
5906 5958 return (dladm_linkduplex2str(linkduplex, buf));
5907 5959 }
5908 5960
5909 5961 static int
5910 5962 parse_wifi_fields(char *str, ofmt_handle_t *ofmt, uint_t cmdtype,
5911 5963 boolean_t parsable)
5912 5964 {
5913 5965 ofmt_field_t *template, *of;
5914 5966 ofmt_cb_t *fn;
5915 5967 ofmt_status_t oferr;
5916 5968
5917 5969 if (cmdtype == WIFI_CMD_SCAN) {
5918 5970 template = wifi_common_fields;
5919 5971 if (str == NULL)
5920 5972 str = def_scan_wifi_fields;
5921 5973 if (strcasecmp(str, "all") == 0)
5922 5974 str = all_scan_wifi_fields;
5923 5975 fn = print_wlan_attr_cb;
5924 5976 } else if (cmdtype == WIFI_CMD_SHOW) {
5925 5977 bcopy(wifi_common_fields, &wifi_show_fields[2],
5926 5978 sizeof (wifi_common_fields));
5927 5979 template = wifi_show_fields;
5928 5980 if (str == NULL)
5929 5981 str = def_show_wifi_fields;
5930 5982 if (strcasecmp(str, "all") == 0)
5931 5983 str = all_show_wifi_fields;
5932 5984 fn = print_link_attr_cb;
5933 5985 } else {
5934 5986 return (-1);
5935 5987 }
5936 5988
5937 5989 for (of = template; of->of_name != NULL; of++) {
5938 5990 if (of->of_cb == NULL)
5939 5991 of->of_cb = fn;
5940 5992 }
5941 5993
5942 5994 oferr = ofmt_open(str, template, (parsable ? OFMT_PARSABLE : 0),
5943 5995 0, ofmt);
5944 5996 dladm_ofmt_check(oferr, parsable, *ofmt);
5945 5997 return (0);
5946 5998 }
5947 5999
5948 6000 typedef struct print_wifi_state {
5949 6001 char *ws_link;
5950 6002 boolean_t ws_parsable;
5951 6003 boolean_t ws_header;
5952 6004 ofmt_handle_t ws_ofmt;
5953 6005 } print_wifi_state_t;
5954 6006
5955 6007 typedef struct wlan_scan_args_s {
5956 6008 print_wifi_state_t *ws_state;
5957 6009 void *ws_attr;
5958 6010 } wlan_scan_args_t;
5959 6011
5960 6012 static boolean_t
5961 6013 print_wlan_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
5962 6014 {
5963 6015 wlan_scan_args_t *w = ofarg->ofmt_cbarg;
5964 6016 print_wifi_state_t *statep = w->ws_state;
5965 6017 dladm_wlan_attr_t *attrp = w->ws_attr;
5966 6018 char tmpbuf[DLADM_STRSIZE];
5967 6019
5968 6020 if (ofarg->ofmt_id == 0) {
5969 6021 (void) strlcpy(buf, (char *)statep->ws_link, bufsize);
5970 6022 return (B_TRUE);
5971 6023 }
5972 6024
5973 6025 if ((ofarg->ofmt_id & attrp->wa_valid) == 0)
5974 6026 return (B_TRUE);
5975 6027
5976 6028 switch (ofarg->ofmt_id) {
5977 6029 case DLADM_WLAN_ATTR_ESSID:
5978 6030 (void) dladm_wlan_essid2str(&attrp->wa_essid, tmpbuf);
5979 6031 break;
5980 6032 case DLADM_WLAN_ATTR_BSSID:
5981 6033 (void) dladm_wlan_bssid2str(&attrp->wa_bssid, tmpbuf);
5982 6034 break;
5983 6035 case DLADM_WLAN_ATTR_SECMODE:
5984 6036 (void) dladm_wlan_secmode2str(&attrp->wa_secmode, tmpbuf);
5985 6037 break;
5986 6038 case DLADM_WLAN_ATTR_STRENGTH:
5987 6039 (void) dladm_wlan_strength2str(&attrp->wa_strength, tmpbuf);
5988 6040 break;
5989 6041 case DLADM_WLAN_ATTR_MODE:
5990 6042 (void) dladm_wlan_mode2str(&attrp->wa_mode, tmpbuf);
5991 6043 break;
5992 6044 case DLADM_WLAN_ATTR_SPEED:
5993 6045 (void) dladm_wlan_speed2str(&attrp->wa_speed, tmpbuf);
5994 6046 (void) strlcat(tmpbuf, "Mb", sizeof (tmpbuf));
5995 6047 break;
5996 6048 case DLADM_WLAN_ATTR_AUTH:
5997 6049 (void) dladm_wlan_auth2str(&attrp->wa_auth, tmpbuf);
5998 6050 break;
5999 6051 case DLADM_WLAN_ATTR_BSSTYPE:
6000 6052 (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, tmpbuf);
6001 6053 break;
6002 6054 }
6003 6055 (void) strlcpy(buf, tmpbuf, bufsize);
6004 6056
6005 6057 return (B_TRUE);
6006 6058 }
6007 6059
6008 6060 static boolean_t
6009 6061 print_scan_results(void *arg, dladm_wlan_attr_t *attrp)
6010 6062 {
6011 6063 print_wifi_state_t *statep = arg;
6012 6064 wlan_scan_args_t warg;
6013 6065
6014 6066 bzero(&warg, sizeof (warg));
6015 6067 warg.ws_state = statep;
6016 6068 warg.ws_attr = attrp;
6017 6069 ofmt_print(statep->ws_ofmt, &warg);
6018 6070 return (B_TRUE);
6019 6071 }
6020 6072
6021 6073 static int
6022 6074 scan_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6023 6075 {
6024 6076 print_wifi_state_t *statep = arg;
6025 6077 dladm_status_t status;
6026 6078 char link[MAXLINKNAMELEN];
6027 6079
6028 6080 if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link,
6029 6081 sizeof (link))) != DLADM_STATUS_OK) {
6030 6082 return (DLADM_WALK_CONTINUE);
6031 6083 }
6032 6084
6033 6085 statep->ws_link = link;
6034 6086 status = dladm_wlan_scan(dh, linkid, statep, print_scan_results);
6035 6087 if (status != DLADM_STATUS_OK)
6036 6088 die_dlerr(status, "cannot scan link '%s'", statep->ws_link);
6037 6089
6038 6090 return (DLADM_WALK_CONTINUE);
6039 6091 }
6040 6092
6041 6093 static boolean_t
6042 6094 print_wifi_status_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
6043 6095 {
6044 6096 static char tmpbuf[DLADM_STRSIZE];
6045 6097 wlan_scan_args_t *w = ofarg->ofmt_cbarg;
6046 6098 dladm_wlan_linkattr_t *attrp = w->ws_attr;
6047 6099
6048 6100 if ((ofarg->ofmt_id & attrp->la_valid) != 0) {
6049 6101 (void) dladm_wlan_linkstatus2str(&attrp->la_status, tmpbuf);
6050 6102 (void) strlcpy(buf, tmpbuf, bufsize);
6051 6103 }
6052 6104 return (B_TRUE);
6053 6105 }
6054 6106
6055 6107 static boolean_t
6056 6108 print_link_attr_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
6057 6109 {
6058 6110 wlan_scan_args_t *w = ofarg->ofmt_cbarg, w1;
6059 6111 print_wifi_state_t *statep = w->ws_state;
6060 6112 dladm_wlan_linkattr_t *attrp = w->ws_attr;
6061 6113
6062 6114 bzero(&w1, sizeof (w1));
6063 6115 w1.ws_state = statep;
6064 6116 w1.ws_attr = &attrp->la_wlan_attr;
6065 6117 ofarg->ofmt_cbarg = &w1;
6066 6118 return (print_wlan_attr_cb(ofarg, buf, bufsize));
6067 6119 }
6068 6120
6069 6121 static int
6070 6122 show_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6071 6123 {
6072 6124 print_wifi_state_t *statep = arg;
6073 6125 dladm_wlan_linkattr_t attr;
6074 6126 dladm_status_t status;
6075 6127 char link[MAXLINKNAMELEN];
6076 6128 wlan_scan_args_t warg;
6077 6129
6078 6130 if ((status = dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, link,
6079 6131 sizeof (link))) != DLADM_STATUS_OK) {
6080 6132 return (DLADM_WALK_CONTINUE);
6081 6133 }
6082 6134
6083 6135 /* dladm_wlan_get_linkattr() memsets attr with 0 */
6084 6136 status = dladm_wlan_get_linkattr(dh, linkid, &attr);
6085 6137 if (status != DLADM_STATUS_OK)
6086 6138 die_dlerr(status, "cannot get link attributes for %s", link);
6087 6139
6088 6140 statep->ws_link = link;
6089 6141
6090 6142 bzero(&warg, sizeof (warg));
6091 6143 warg.ws_state = statep;
6092 6144 warg.ws_attr = &attr;
6093 6145 ofmt_print(statep->ws_ofmt, &warg);
6094 6146 return (DLADM_WALK_CONTINUE);
6095 6147 }
6096 6148
6097 6149 static void
6098 6150 do_display_wifi(int argc, char **argv, int cmd, const char *use)
6099 6151 {
6100 6152 int option;
6101 6153 char *fields_str = NULL;
6102 6154 int (*callback)(dladm_handle_t, datalink_id_t, void *);
6103 6155 print_wifi_state_t state;
6104 6156 datalink_id_t linkid = DATALINK_ALL_LINKID;
6105 6157 dladm_status_t status;
6106 6158
6107 6159 if (cmd == WIFI_CMD_SCAN)
6108 6160 callback = scan_wifi;
6109 6161 else if (cmd == WIFI_CMD_SHOW)
6110 6162 callback = show_wifi;
6111 6163 else
6112 6164 return;
6113 6165
6114 6166 state.ws_parsable = B_FALSE;
6115 6167 state.ws_header = B_TRUE;
6116 6168 opterr = 0;
6117 6169 while ((option = getopt_long(argc, argv, ":o:p",
6118 6170 wifi_longopts, NULL)) != -1) {
6119 6171 switch (option) {
6120 6172 case 'o':
6121 6173 fields_str = optarg;
6122 6174 break;
6123 6175 case 'p':
6124 6176 state.ws_parsable = B_TRUE;
6125 6177 break;
6126 6178 default:
6127 6179 die_opterr(optopt, option, use);
6128 6180 }
6129 6181 }
6130 6182
6131 6183 if (state.ws_parsable && fields_str == NULL)
6132 6184 die("-p requires -o");
6133 6185
6134 6186 if (state.ws_parsable && strcasecmp(fields_str, "all") == 0)
6135 6187 die("\"-o all\" is invalid with -p");
6136 6188
6137 6189 if (optind == (argc - 1)) {
6138 6190 if ((status = dladm_name2info(handle, argv[optind], &linkid,
6139 6191 NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6140 6192 die_dlerr(status, "link %s is not valid", argv[optind]);
6141 6193 }
6142 6194 } else if (optind != argc) {
6143 6195 usage();
6144 6196 }
6145 6197
6146 6198 if (parse_wifi_fields(fields_str, &state.ws_ofmt, cmd,
6147 6199 state.ws_parsable) < 0)
6148 6200 die("invalid field(s) specified");
6149 6201
6150 6202 if (linkid == DATALINK_ALL_LINKID) {
6151 6203 (void) dladm_walk_datalink_id(callback, handle, &state,
6152 6204 DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
6153 6205 DL_WIFI, DLADM_OPT_ACTIVE);
6154 6206 } else {
6155 6207 (void) (*callback)(handle, linkid, &state);
6156 6208 }
6157 6209 ofmt_close(state.ws_ofmt);
6158 6210 }
6159 6211
6160 6212 static void
6161 6213 do_scan_wifi(int argc, char **argv, const char *use)
6162 6214 {
6163 6215 do_display_wifi(argc, argv, WIFI_CMD_SCAN, use);
6164 6216 }
6165 6217
6166 6218 static void
6167 6219 do_show_wifi(int argc, char **argv, const char *use)
6168 6220 {
6169 6221 do_display_wifi(argc, argv, WIFI_CMD_SHOW, use);
6170 6222 }
6171 6223
6172 6224 typedef struct wlan_count_attr {
6173 6225 uint_t wc_count;
6174 6226 datalink_id_t wc_linkid;
6175 6227 } wlan_count_attr_t;
6176 6228
6177 6229 /* ARGSUSED */
6178 6230 static int
6179 6231 do_count_wlan(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6180 6232 {
6181 6233 wlan_count_attr_t *cp = arg;
6182 6234
6183 6235 if (cp->wc_count == 0)
6184 6236 cp->wc_linkid = linkid;
6185 6237 cp->wc_count++;
6186 6238 return (DLADM_WALK_CONTINUE);
6187 6239 }
6188 6240
6189 6241 static int
6190 6242 parse_wlan_keys(char *str, dladm_wlan_key_t **keys, uint_t *key_countp)
6191 6243 {
6192 6244 uint_t i;
6193 6245 dladm_wlan_key_t *wk;
6194 6246 int nfields = 1;
6195 6247 char *field, *token, *lasts = NULL, c;
6196 6248
6197 6249 token = str;
6198 6250 while ((c = *token++) != NULL) {
6199 6251 if (c == ',')
6200 6252 nfields++;
6201 6253 }
6202 6254 token = strdup(str);
6203 6255 if (token == NULL)
6204 6256 return (-1);
6205 6257
6206 6258 wk = malloc(nfields * sizeof (dladm_wlan_key_t));
6207 6259 if (wk == NULL)
6208 6260 goto fail;
6209 6261
6210 6262 token = str;
6211 6263 for (i = 0; i < nfields; i++) {
6212 6264 char *s;
6213 6265 dladm_secobj_class_t class;
6214 6266 dladm_status_t status;
6215 6267
6216 6268 field = strtok_r(token, ",", &lasts);
6217 6269 token = NULL;
6218 6270
6219 6271 (void) strlcpy(wk[i].wk_name, field,
6220 6272 DLADM_WLAN_MAX_KEYNAME_LEN);
6221 6273
6222 6274 wk[i].wk_idx = 1;
6223 6275 if ((s = strrchr(wk[i].wk_name, ':')) != NULL) {
6224 6276 if (s[1] == '\0' || s[2] != '\0' || !isdigit(s[1]))
6225 6277 goto fail;
6226 6278
6227 6279 wk[i].wk_idx = (uint_t)(s[1] - '0');
6228 6280 *s = '\0';
6229 6281 }
6230 6282 wk[i].wk_len = DLADM_WLAN_MAX_KEY_LEN;
6231 6283
6232 6284 status = dladm_get_secobj(handle, wk[i].wk_name, &class,
6233 6285 wk[i].wk_val, &wk[i].wk_len, 0);
6234 6286 if (status != DLADM_STATUS_OK) {
6235 6287 if (status == DLADM_STATUS_NOTFOUND) {
6236 6288 status = dladm_get_secobj(handle, wk[i].wk_name,
6237 6289 &class, wk[i].wk_val, &wk[i].wk_len,
6238 6290 DLADM_OPT_PERSIST);
6239 6291 }
6240 6292 if (status != DLADM_STATUS_OK)
6241 6293 goto fail;
6242 6294 }
6243 6295 wk[i].wk_class = class;
6244 6296 }
6245 6297 *keys = wk;
6246 6298 *key_countp = i;
6247 6299 free(token);
6248 6300 return (0);
6249 6301 fail:
6250 6302 free(wk);
6251 6303 free(token);
6252 6304 return (-1);
6253 6305 }
6254 6306
6255 6307 static void
6256 6308 do_connect_wifi(int argc, char **argv, const char *use)
6257 6309 {
6258 6310 int option;
6259 6311 dladm_wlan_attr_t attr, *attrp;
6260 6312 dladm_status_t status = DLADM_STATUS_OK;
6261 6313 int timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT;
6262 6314 datalink_id_t linkid = DATALINK_ALL_LINKID;
6263 6315 dladm_wlan_key_t *keys = NULL;
6264 6316 uint_t key_count = 0;
6265 6317 uint_t flags = 0;
6266 6318 dladm_wlan_secmode_t keysecmode = DLADM_WLAN_SECMODE_NONE;
6267 6319 char buf[DLADM_STRSIZE];
6268 6320
6269 6321 opterr = 0;
6270 6322 (void) memset(&attr, 0, sizeof (attr));
6271 6323 while ((option = getopt_long(argc, argv, ":e:i:a:m:b:s:k:T:c",
6272 6324 wifi_longopts, NULL)) != -1) {
6273 6325 switch (option) {
6274 6326 case 'e':
6275 6327 status = dladm_wlan_str2essid(optarg, &attr.wa_essid);
6276 6328 if (status != DLADM_STATUS_OK)
6277 6329 die("invalid ESSID '%s'", optarg);
6278 6330
6279 6331 attr.wa_valid |= DLADM_WLAN_ATTR_ESSID;
6280 6332 /*
6281 6333 * Try to connect without doing a scan.
6282 6334 */
6283 6335 flags |= DLADM_WLAN_CONNECT_NOSCAN;
6284 6336 break;
6285 6337 case 'i':
6286 6338 status = dladm_wlan_str2bssid(optarg, &attr.wa_bssid);
6287 6339 if (status != DLADM_STATUS_OK)
6288 6340 die("invalid BSSID %s", optarg);
6289 6341
6290 6342 attr.wa_valid |= DLADM_WLAN_ATTR_BSSID;
6291 6343 break;
6292 6344 case 'a':
6293 6345 status = dladm_wlan_str2auth(optarg, &attr.wa_auth);
6294 6346 if (status != DLADM_STATUS_OK)
6295 6347 die("invalid authentication mode '%s'", optarg);
6296 6348
6297 6349 attr.wa_valid |= DLADM_WLAN_ATTR_AUTH;
6298 6350 break;
6299 6351 case 'm':
6300 6352 status = dladm_wlan_str2mode(optarg, &attr.wa_mode);
6301 6353 if (status != DLADM_STATUS_OK)
6302 6354 die("invalid mode '%s'", optarg);
6303 6355
6304 6356 attr.wa_valid |= DLADM_WLAN_ATTR_MODE;
6305 6357 break;
6306 6358 case 'b':
6307 6359 if ((status = dladm_wlan_str2bsstype(optarg,
6308 6360 &attr.wa_bsstype)) != DLADM_STATUS_OK) {
6309 6361 die("invalid bsstype '%s'", optarg);
6310 6362 }
6311 6363
6312 6364 attr.wa_valid |= DLADM_WLAN_ATTR_BSSTYPE;
6313 6365 break;
6314 6366 case 's':
6315 6367 if ((status = dladm_wlan_str2secmode(optarg,
6316 6368 &attr.wa_secmode)) != DLADM_STATUS_OK) {
6317 6369 die("invalid security mode '%s'", optarg);
6318 6370 }
6319 6371
6320 6372 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE;
6321 6373 break;
6322 6374 case 'k':
6323 6375 if (parse_wlan_keys(optarg, &keys, &key_count) < 0)
6324 6376 die("invalid key(s) '%s'", optarg);
6325 6377
6326 6378 if (keys[0].wk_class == DLADM_SECOBJ_CLASS_WEP)
6327 6379 keysecmode = DLADM_WLAN_SECMODE_WEP;
6328 6380 else
6329 6381 keysecmode = DLADM_WLAN_SECMODE_WPA;
6330 6382 break;
6331 6383 case 'T':
6332 6384 if (strcasecmp(optarg, "forever") == 0) {
6333 6385 timeout = -1;
6334 6386 break;
6335 6387 }
6336 6388 if (!str2int(optarg, &timeout) || timeout < 0)
6337 6389 die("invalid timeout value '%s'", optarg);
6338 6390 break;
6339 6391 case 'c':
6340 6392 flags |= DLADM_WLAN_CONNECT_CREATEIBSS;
6341 6393 flags |= DLADM_WLAN_CONNECT_CREATEIBSS;
6342 6394 break;
6343 6395 default:
6344 6396 die_opterr(optopt, option, use);
6345 6397 break;
6346 6398 }
6347 6399 }
6348 6400
6349 6401 if (keysecmode == DLADM_WLAN_SECMODE_NONE) {
6350 6402 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) {
6351 6403 die("key required for security mode '%s'",
6352 6404 dladm_wlan_secmode2str(&attr.wa_secmode, buf));
6353 6405 }
6354 6406 } else {
6355 6407 if ((attr.wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 &&
6356 6408 attr.wa_secmode != keysecmode)
6357 6409 die("incompatible -s and -k options");
6358 6410 attr.wa_valid |= DLADM_WLAN_ATTR_SECMODE;
6359 6411 attr.wa_secmode = keysecmode;
6360 6412 }
6361 6413
6362 6414 if (optind == (argc - 1)) {
6363 6415 if ((status = dladm_name2info(handle, argv[optind], &linkid,
6364 6416 NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6365 6417 die_dlerr(status, "link %s is not valid", argv[optind]);
6366 6418 }
6367 6419 } else if (optind != argc) {
6368 6420 usage();
6369 6421 }
6370 6422
6371 6423 if (linkid == DATALINK_ALL_LINKID) {
6372 6424 wlan_count_attr_t wcattr;
6373 6425
6374 6426 wcattr.wc_linkid = DATALINK_INVALID_LINKID;
6375 6427 wcattr.wc_count = 0;
6376 6428 (void) dladm_walk_datalink_id(do_count_wlan, handle, &wcattr,
6377 6429 DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
6378 6430 DL_WIFI, DLADM_OPT_ACTIVE);
6379 6431 if (wcattr.wc_count == 0) {
6380 6432 die("no wifi links are available");
6381 6433 } else if (wcattr.wc_count > 1) {
6382 6434 die("link name is required when more than one wifi "
6383 6435 "link is available");
6384 6436 }
6385 6437 linkid = wcattr.wc_linkid;
6386 6438 }
6387 6439 attrp = (attr.wa_valid == 0) ? NULL : &attr;
6388 6440 again:
6389 6441 if ((status = dladm_wlan_connect(handle, linkid, attrp, timeout, keys,
6390 6442 key_count, flags)) != DLADM_STATUS_OK) {
6391 6443 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) {
6392 6444 /*
6393 6445 * Try again with scanning and filtering.
6394 6446 */
6395 6447 flags &= ~DLADM_WLAN_CONNECT_NOSCAN;
6396 6448 goto again;
6397 6449 }
6398 6450
6399 6451 if (status == DLADM_STATUS_NOTFOUND) {
6400 6452 if (attr.wa_valid == 0) {
6401 6453 die("no wifi networks are available");
6402 6454 } else {
6403 6455 die("no wifi networks with the specified "
6404 6456 "criteria are available");
6405 6457 }
6406 6458 }
6407 6459 die_dlerr(status, "cannot connect");
6408 6460 }
6409 6461 free(keys);
6410 6462 }
6411 6463
6412 6464 /* ARGSUSED */
6413 6465 static int
6414 6466 do_all_disconnect_wifi(dladm_handle_t dh, datalink_id_t linkid, void *arg)
6415 6467 {
6416 6468 dladm_status_t status;
6417 6469
6418 6470 status = dladm_wlan_disconnect(dh, linkid);
6419 6471 if (status != DLADM_STATUS_OK)
6420 6472 warn_dlerr(status, "cannot disconnect link");
6421 6473
6422 6474 return (DLADM_WALK_CONTINUE);
6423 6475 }
6424 6476
6425 6477 static void
6426 6478 do_disconnect_wifi(int argc, char **argv, const char *use)
6427 6479 {
6428 6480 int option;
6429 6481 datalink_id_t linkid = DATALINK_ALL_LINKID;
6430 6482 boolean_t all_links = B_FALSE;
6431 6483 dladm_status_t status;
6432 6484 wlan_count_attr_t wcattr;
6433 6485
6434 6486 opterr = 0;
6435 6487 while ((option = getopt_long(argc, argv, ":a",
6436 6488 wifi_longopts, NULL)) != -1) {
6437 6489 switch (option) {
6438 6490 case 'a':
6439 6491 all_links = B_TRUE;
6440 6492 break;
6441 6493 default:
6442 6494 die_opterr(optopt, option, use);
6443 6495 break;
6444 6496 }
6445 6497 }
6446 6498
6447 6499 if (optind == (argc - 1)) {
6448 6500 if ((status = dladm_name2info(handle, argv[optind], &linkid,
6449 6501 NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6450 6502 die_dlerr(status, "link %s is not valid", argv[optind]);
6451 6503 }
6452 6504 } else if (optind != argc) {
6453 6505 usage();
6454 6506 }
6455 6507
6456 6508 if (linkid == DATALINK_ALL_LINKID) {
6457 6509 if (!all_links) {
6458 6510 wcattr.wc_linkid = linkid;
6459 6511 wcattr.wc_count = 0;
6460 6512 (void) dladm_walk_datalink_id(do_count_wlan, handle,
6461 6513 &wcattr,
6462 6514 DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
6463 6515 DL_WIFI, DLADM_OPT_ACTIVE);
6464 6516 if (wcattr.wc_count == 0) {
6465 6517 die("no wifi links are available");
6466 6518 } else if (wcattr.wc_count > 1) {
6467 6519 die("link name is required when more than "
6468 6520 "one wifi link is available");
6469 6521 }
6470 6522 linkid = wcattr.wc_linkid;
6471 6523 } else {
6472 6524 (void) dladm_walk_datalink_id(do_all_disconnect_wifi,
6473 6525 handle, NULL,
6474 6526 DATALINK_CLASS_PHYS | DATALINK_CLASS_SIMNET,
6475 6527 DL_WIFI, DLADM_OPT_ACTIVE);
6476 6528 return;
6477 6529 }
6478 6530 }
6479 6531 status = dladm_wlan_disconnect(handle, linkid);
6480 6532 if (status != DLADM_STATUS_OK)
6481 6533 die_dlerr(status, "cannot disconnect");
6482 6534 }
6483 6535
6484 6536 static void
6485 6537 print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
6486 6538 const char *propname, dladm_prop_type_t type, const char *format,
6487 6539 char **pptr)
6488 6540 {
6489 6541 int i;
6490 6542 char *ptr, *lim;
6491 6543 char buf[DLADM_STRSIZE];
6492 6544 char *unknown = "--", *notsup = "";
6493 6545 char **propvals = statep->ls_propvals;
6494 6546 uint_t valcnt = DLADM_MAX_PROP_VALCNT;
6495 6547 dladm_status_t status;
6496 6548
6497 6549 status = dladm_get_linkprop(handle, linkid, type, propname, propvals,
6498 6550 &valcnt);
6499 6551 if (status != DLADM_STATUS_OK) {
6500 6552 if (status == DLADM_STATUS_TEMPONLY) {
6501 6553 if (type == DLADM_PROP_VAL_MODIFIABLE &&
6502 6554 statep->ls_persist) {
6503 6555 valcnt = 1;
6504 6556 propvals = &unknown;
6505 6557 } else {
6506 6558 statep->ls_status = status;
6507 6559 statep->ls_retstatus = status;
6508 6560 return;
6509 6561 }
6510 6562 } else if (status == DLADM_STATUS_NOTSUP ||
6511 6563 statep->ls_persist) {
6512 6564 valcnt = 1;
6513 6565 if (type == DLADM_PROP_VAL_CURRENT ||
6514 6566 type == DLADM_PROP_VAL_PERM)
6515 6567 propvals = &unknown;
6516 6568 else
6517 6569 propvals = ¬sup;
6518 6570 } else if (status == DLADM_STATUS_NOTDEFINED) {
6519 6571 propvals = ¬sup; /* STR_UNDEF_VAL */
6520 6572 } else {
6521 6573 if (statep->ls_proplist &&
6522 6574 statep->ls_status == DLADM_STATUS_OK) {
6523 6575 warn_dlerr(status,
6524 6576 "cannot get link property '%s' for %s",
6525 6577 propname, statep->ls_link);
6526 6578 }
6527 6579 statep->ls_status = status;
6528 6580 statep->ls_retstatus = status;
6529 6581 return;
6530 6582 }
6531 6583 }
6532 6584
6533 6585 statep->ls_status = DLADM_STATUS_OK;
6534 6586
6535 6587 buf[0] = '\0';
6536 6588 ptr = buf;
6537 6589 lim = buf + DLADM_STRSIZE;
6538 6590 for (i = 0; i < valcnt; i++) {
6539 6591 if (propvals[i][0] == '\0' && !statep->ls_parsable)
6540 6592 ptr += snprintf(ptr, lim - ptr, "--,");
6541 6593 else
6542 6594 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]);
6543 6595 if (ptr >= lim)
6544 6596 break;
6545 6597 }
6546 6598 if (valcnt > 0)
6547 6599 buf[strlen(buf) - 1] = '\0';
6548 6600
6549 6601 lim = statep->ls_line + MAX_PROP_LINE;
6550 6602 if (statep->ls_parsable) {
6551 6603 *pptr += snprintf(*pptr, lim - *pptr,
6552 6604 "%s", buf);
6553 6605 } else {
6554 6606 *pptr += snprintf(*pptr, lim - *pptr, format, buf);
6555 6607 }
6556 6608 }
6557 6609
6558 6610 static boolean_t
6559 6611 print_linkprop_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
6560 6612 {
6561 6613 linkprop_args_t *arg = ofarg->ofmt_cbarg;
6562 6614 char *propname = arg->ls_propname;
6563 6615 show_linkprop_state_t *statep = arg->ls_state;
6564 6616 char *ptr = statep->ls_line;
6565 6617 char *lim = ptr + MAX_PROP_LINE;
6566 6618 datalink_id_t linkid = arg->ls_linkid;
6567 6619
6568 6620 switch (ofarg->ofmt_id) {
6569 6621 case LINKPROP_LINK:
6570 6622 (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link);
6571 6623 break;
6572 6624 case LINKPROP_PROPERTY:
6573 6625 (void) snprintf(ptr, lim - ptr, "%s", propname);
6574 6626 break;
6575 6627 case LINKPROP_VALUE:
6576 6628 print_linkprop(linkid, statep, propname,
6577 6629 statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT :
6578 6630 DLADM_PROP_VAL_CURRENT, "%s", &ptr);
6579 6631 /*
6580 6632 * If we failed to query the link property, for example, query
6581 6633 * the persistent value of a non-persistable link property,
6582 6634 * simply skip the output.
6583 6635 */
6584 6636 if (statep->ls_status != DLADM_STATUS_OK) {
6585 6637 /*
6586 6638 * Ignore the temponly error when we skip printing
6587 6639 * link properties to avoid returning failure on exit.
6588 6640 */
6589 6641 if (statep->ls_retstatus == DLADM_STATUS_TEMPONLY)
6590 6642 statep->ls_retstatus = DLADM_STATUS_OK;
6591 6643 goto skip;
6592 6644 }
6593 6645 ptr = statep->ls_line;
6594 6646 break;
6595 6647 case LINKPROP_PERM:
6596 6648 print_linkprop(linkid, statep, propname,
6597 6649 DLADM_PROP_VAL_PERM, "%s", &ptr);
6598 6650 if (statep->ls_status != DLADM_STATUS_OK)
6599 6651 goto skip;
6600 6652 ptr = statep->ls_line;
6601 6653 break;
6602 6654 case LINKPROP_DEFAULT:
6603 6655 print_linkprop(linkid, statep, propname,
6604 6656 DLADM_PROP_VAL_DEFAULT, "%s", &ptr);
6605 6657 if (statep->ls_status != DLADM_STATUS_OK)
6606 6658 goto skip;
6607 6659 ptr = statep->ls_line;
6608 6660 break;
6609 6661 case LINKPROP_POSSIBLE:
6610 6662 print_linkprop(linkid, statep, propname,
6611 6663 DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr);
6612 6664 if (statep->ls_status != DLADM_STATUS_OK)
6613 6665 goto skip;
6614 6666 ptr = statep->ls_line;
6615 6667 break;
6616 6668 default:
6617 6669 die("invalid input");
6618 6670 break;
6619 6671 }
6620 6672 (void) strlcpy(buf, ptr, bufsize);
6621 6673 return (B_TRUE);
6622 6674 skip:
6623 6675 return ((statep->ls_status == DLADM_STATUS_OK) ?
6624 6676 B_TRUE : B_FALSE);
6625 6677 }
6626 6678
6627 6679 static boolean_t
6628 6680 linkprop_is_supported(datalink_id_t linkid, const char *propname,
6629 6681 show_linkprop_state_t *statep)
6630 6682 {
6631 6683 dladm_status_t status;
6632 6684 uint_t valcnt = DLADM_MAX_PROP_VALCNT;
6633 6685
6634 6686 /* if used with -p flag, always print output */
6635 6687 if (statep->ls_proplist != NULL)
6636 6688 return (B_TRUE);
6637 6689
6638 6690 status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_DEFAULT,
6639 6691 propname, statep->ls_propvals, &valcnt);
6640 6692
6641 6693 if (status == DLADM_STATUS_OK)
6642 6694 return (B_TRUE);
6643 6695
6644 6696 /*
6645 6697 * A system wide default value is not available for the
6646 6698 * property. Check if current value can be retrieved.
6647 6699 */
6648 6700 status = dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT,
6649 6701 propname, statep->ls_propvals, &valcnt);
6650 6702
6651 6703 return (status == DLADM_STATUS_OK);
6652 6704 }
6653 6705
6654 6706 /* ARGSUSED */
6655 6707 static int
6656 6708 show_linkprop(dladm_handle_t dh, datalink_id_t linkid, const char *propname,
6657 6709 void *arg)
6658 6710 {
6659 6711 show_linkprop_state_t *statep = arg;
6660 6712 linkprop_args_t ls_arg;
6661 6713
6662 6714 bzero(&ls_arg, sizeof (ls_arg));
6663 6715 ls_arg.ls_state = statep;
6664 6716 ls_arg.ls_propname = (char *)propname;
6665 6717 ls_arg.ls_linkid = linkid;
6666 6718
6667 6719 /*
6668 6720 * This will need to be fixed when kernel interfaces are added
6669 6721 * to enable walking of all known private properties. For now,
6670 6722 * we are limited to walking persistent private properties only.
6671 6723 */
6672 6724 if ((propname[0] == '_') && !statep->ls_persist &&
6673 6725 (statep->ls_proplist == NULL))
6674 6726 return (DLADM_WALK_CONTINUE);
6675 6727 if (!statep->ls_parsable &&
6676 6728 !linkprop_is_supported(linkid, propname, statep))
6677 6729 return (DLADM_WALK_CONTINUE);
6678 6730
6679 6731 ofmt_print(statep->ls_ofmt, &ls_arg);
6680 6732
6681 6733 return (DLADM_WALK_CONTINUE);
6682 6734 }
6683 6735
6684 6736 static void
6685 6737 do_show_linkprop(int argc, char **argv, const char *use)
6686 6738 {
6687 6739 int option;
|
↓ open down ↓ |
1468 lines elided |
↑ open up ↑ |
6688 6740 char propstr[DLADM_STRSIZE];
6689 6741 dladm_arg_list_t *proplist = NULL;
6690 6742 datalink_id_t linkid = DATALINK_ALL_LINKID;
6691 6743 show_linkprop_state_t state;
6692 6744 uint32_t flags = DLADM_OPT_ACTIVE;
6693 6745 dladm_status_t status;
6694 6746 char *fields_str = NULL;
6695 6747 ofmt_handle_t ofmt;
6696 6748 ofmt_status_t oferr;
6697 6749 uint_t ofmtflags = 0;
6750 + char *zonename = NULL;
6698 6751
6699 6752 bzero(propstr, DLADM_STRSIZE);
6700 6753 opterr = 0;
6701 6754 state.ls_propvals = NULL;
6702 6755 state.ls_line = NULL;
6703 6756 state.ls_parsable = B_FALSE;
6704 6757 state.ls_persist = B_FALSE;
6705 6758 state.ls_header = B_TRUE;
6706 6759 state.ls_retstatus = DLADM_STATUS_OK;
6707 6760
6708 - while ((option = getopt_long(argc, argv, ":p:cPo:",
6761 + while ((option = getopt_long(argc, argv, ":p:cPo:z:",
6709 6762 prop_longopts, NULL)) != -1) {
6710 6763 switch (option) {
6711 6764 case 'p':
6712 6765 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
6713 6766 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
6714 6767 DLADM_STRSIZE)
6715 6768 die("property list too long '%s'", propstr);
6716 6769 break;
6717 6770 case 'c':
6718 6771 state.ls_parsable = B_TRUE;
6719 6772 break;
6720 6773 case 'P':
6721 6774 state.ls_persist = B_TRUE;
6722 6775 flags = DLADM_OPT_PERSIST;
6723 6776 break;
6724 6777 case 'o':
6725 6778 fields_str = optarg;
6726 6779 break;
6780 + case 'z':
6781 + zonename = optarg;
6782 + break;
6727 6783 default:
6728 6784 die_opterr(optopt, option, use);
6729 6785 break;
6730 6786 }
6731 6787 }
6732 6788
6733 6789 if (optind == (argc - 1)) {
6734 - if ((status = dladm_name2info(handle, argv[optind], &linkid,
6735 - NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6790 + if ((status = dladm_zname2info(handle, zonename, argv[optind],
6791 + &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) {
6736 6792 die_dlerr(status, "link %s is not valid", argv[optind]);
6737 6793 }
6738 6794 } else if (optind != argc) {
6739 6795 usage();
6740 6796 }
6741 6797
6742 6798 if (dladm_parse_link_props(propstr, &proplist, B_TRUE)
6743 6799 != DLADM_STATUS_OK)
6744 6800 die("invalid link properties specified");
6745 6801 state.ls_proplist = proplist;
6802 + state.ls_zonename = zonename;
6746 6803 state.ls_status = DLADM_STATUS_OK;
6747 6804
6748 6805 if (state.ls_parsable)
6749 6806 ofmtflags |= OFMT_PARSABLE;
6750 6807 else
6751 6808 ofmtflags |= OFMT_WRAP;
6752 6809
6753 6810 oferr = ofmt_open(fields_str, linkprop_fields, ofmtflags, 0, &ofmt);
6754 6811 dladm_ofmt_check(oferr, state.ls_parsable, ofmt);
6755 6812 state.ls_ofmt = ofmt;
6756 6813
6757 6814 if (linkid == DATALINK_ALL_LINKID) {
6758 6815 (void) dladm_walk_datalink_id(show_linkprop_onelink, handle,
6759 6816 &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
6760 6817 } else {
6761 6818 (void) show_linkprop_onelink(handle, linkid, &state);
6762 6819 }
6763 6820 ofmt_close(ofmt);
6764 6821 dladm_free_props(proplist);
6765 6822
6766 6823 if (state.ls_retstatus != DLADM_STATUS_OK) {
6767 6824 dladm_close(handle);
6768 6825 exit(EXIT_FAILURE);
6769 6826 }
6770 6827 }
6771 6828
6772 6829 static int
6773 6830 show_linkprop_onelink(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
6774 6831 {
6775 6832 int i;
6776 6833 char *buf;
6777 6834 uint32_t flags;
6778 6835 dladm_arg_list_t *proplist = NULL;
6779 6836 show_linkprop_state_t *statep = arg;
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
6780 6837 dlpi_handle_t dh = NULL;
6781 6838
6782 6839 statep->ls_status = DLADM_STATUS_OK;
6783 6840
6784 6841 if (dladm_datalink_id2info(hdl, linkid, &flags, NULL, NULL,
6785 6842 statep->ls_link, MAXLINKNAMELEN) != DLADM_STATUS_OK) {
6786 6843 statep->ls_status = DLADM_STATUS_NOTFOUND;
6787 6844 return (DLADM_WALK_CONTINUE);
6788 6845 }
6789 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 +
6790 6858 if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) ||
6791 6859 (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) {
6792 6860 statep->ls_status = DLADM_STATUS_BADARG;
6793 6861 return (DLADM_WALK_CONTINUE);
6794 6862 }
6795 6863
6796 6864 proplist = statep->ls_proplist;
6797 6865
6798 6866 /*
6799 6867 * When some WiFi links are opened for the first time, their hardware
6800 6868 * automatically scans for APs and does other slow operations. Thus,
6801 6869 * if there are no open links, the retrieval of link properties
6802 6870 * (below) will proceed slowly unless we hold the link open.
6803 6871 *
6804 6872 * Note that failure of dlpi_open() does not necessarily mean invalid
6805 6873 * link properties, because dlpi_open() may fail because of incorrect
6806 6874 * autopush configuration. Therefore, we ingore the return value of
6807 6875 * dlpi_open().
6808 6876 */
6809 6877 if (!statep->ls_persist)
6810 6878 (void) dlpi_open(statep->ls_link, &dh, 0);
6811 6879
6812 6880 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
6813 6881 DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE);
6814 6882 if (buf == NULL)
6815 6883 die("insufficient memory");
6816 6884
6817 6885 statep->ls_propvals = (char **)(void *)buf;
6818 6886 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
6819 6887 statep->ls_propvals[i] = buf +
6820 6888 sizeof (char *) * DLADM_MAX_PROP_VALCNT +
6821 6889 i * DLADM_PROP_VAL_MAX;
6822 6890 }
6823 6891 statep->ls_line = buf +
6824 6892 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
6825 6893
6826 6894 if (proplist != NULL) {
6827 6895 for (i = 0; i < proplist->al_count; i++) {
6828 6896 (void) show_linkprop(hdl, linkid,
6829 6897 proplist->al_info[i].ai_name, statep);
6830 6898 }
6831 6899 } else {
6832 6900 (void) dladm_walk_linkprop(hdl, linkid, statep,
6833 6901 show_linkprop);
6834 6902 }
6835 6903 if (dh != NULL)
6836 6904 dlpi_close(dh);
6837 6905 free(buf);
6838 6906 return (DLADM_WALK_CONTINUE);
6839 6907 }
6840 6908
6841 6909 static int
6842 6910 reset_one_linkprop(dladm_handle_t dh, datalink_id_t linkid,
6843 6911 const char *propname, void *arg)
6844 6912 {
6845 6913 set_linkprop_state_t *statep = arg;
6846 6914 dladm_status_t status;
6847 6915
6848 6916 status = dladm_set_linkprop(dh, linkid, propname, NULL, 0,
6849 6917 DLADM_OPT_ACTIVE | (statep->ls_temp ? 0 : DLADM_OPT_PERSIST));
6850 6918 if (status != DLADM_STATUS_OK &&
6851 6919 status != DLADM_STATUS_PROPRDONLY &&
6852 6920 status != DLADM_STATUS_NOTSUP) {
6853 6921 warn_dlerr(status, "cannot reset link property '%s' on '%s'",
6854 6922 propname, statep->ls_name);
6855 6923 statep->ls_status = status;
6856 6924 }
6857 6925
6858 6926 return (DLADM_WALK_CONTINUE);
6859 6927 }
6860 6928
6861 6929 static void
|
↓ open down ↓ |
62 lines elided |
↑ open up ↑ |
6862 6930 set_linkprop(int argc, char **argv, boolean_t reset, const char *use)
6863 6931 {
6864 6932 int i, option;
6865 6933 char errmsg[DLADM_STRSIZE];
6866 6934 char *altroot = NULL;
6867 6935 datalink_id_t linkid;
6868 6936 boolean_t temp = B_FALSE;
6869 6937 dladm_status_t status = DLADM_STATUS_OK;
6870 6938 char propstr[DLADM_STRSIZE];
6871 6939 dladm_arg_list_t *proplist = NULL;
6940 + char *zonename = NULL;
6872 6941
6873 6942 opterr = 0;
6874 6943 bzero(propstr, DLADM_STRSIZE);
6875 6944
6876 - while ((option = getopt_long(argc, argv, ":p:R:t",
6945 + while ((option = getopt_long(argc, argv, ":p:R:tz:",
6877 6946 prop_longopts, NULL)) != -1) {
6878 6947 switch (option) {
6879 6948 case 'p':
6880 6949 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
6881 6950 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
6882 6951 DLADM_STRSIZE)
6883 6952 die("property list too long '%s'", propstr);
6884 6953 break;
6885 6954 case 't':
6886 6955 temp = B_TRUE;
6887 6956 break;
6888 6957 case 'R':
6889 6958 altroot = optarg;
6890 6959 break;
6960 + case 'z':
6961 + zonename = optarg;
6962 + break;
6891 6963 default:
6892 6964 die_opterr(optopt, option, use);
6893 6965
6894 6966 }
6895 6967 }
6896 6968
6897 6969 /* get link name (required last argument) */
6898 6970 if (optind != (argc - 1))
6899 6971 usage();
6900 6972
6901 6973 if (dladm_parse_link_props(propstr, &proplist, reset) !=
6902 6974 DLADM_STATUS_OK)
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
6903 6975 die("invalid link properties specified");
6904 6976
6905 6977 if (proplist == NULL && !reset)
6906 6978 die("link property must be specified");
6907 6979
6908 6980 if (altroot != NULL) {
6909 6981 dladm_free_props(proplist);
6910 6982 altroot_cmd(altroot, argc, argv);
6911 6983 }
6912 6984
6913 - status = dladm_name2info(handle, argv[optind], &linkid, NULL, NULL,
6914 - NULL);
6985 + status = dladm_zname2info(handle, zonename, argv[optind], &linkid,
6986 + NULL, NULL, NULL);
6915 6987 if (status != DLADM_STATUS_OK)
6916 6988 die_dlerr(status, "link %s is not valid", argv[optind]);
6917 6989
6918 6990 if (proplist == NULL) {
6919 6991 set_linkprop_state_t state;
6920 6992
6921 6993 state.ls_name = argv[optind];
6922 6994 state.ls_reset = reset;
6923 6995 state.ls_temp = temp;
6924 6996 state.ls_status = DLADM_STATUS_OK;
6925 6997
6926 6998 (void) dladm_walk_linkprop(handle, linkid, &state,
6927 6999 reset_one_linkprop);
6928 7000
6929 7001 status = state.ls_status;
6930 7002 goto done;
6931 7003 }
6932 7004
6933 7005 for (i = 0; i < proplist->al_count; i++) {
6934 7006 dladm_arg_info_t *aip = &proplist->al_info[i];
6935 7007 char **val;
6936 7008 uint_t count;
6937 7009
6938 7010 if (reset) {
6939 7011 val = NULL;
6940 7012 count = 0;
6941 7013 } else {
6942 7014 val = aip->ai_val;
6943 7015 count = aip->ai_count;
6944 7016 if (count == 0) {
6945 7017 warn("no value specified for '%s'",
6946 7018 aip->ai_name);
6947 7019 status = DLADM_STATUS_BADARG;
6948 7020 continue;
6949 7021 }
6950 7022 }
6951 7023 status = dladm_set_linkprop(handle, linkid, aip->ai_name, val,
6952 7024 count, DLADM_OPT_ACTIVE | (temp ? 0 : DLADM_OPT_PERSIST));
6953 7025 switch (status) {
6954 7026 case DLADM_STATUS_OK:
6955 7027 break;
6956 7028 case DLADM_STATUS_NOTFOUND:
6957 7029 warn("invalid link property '%s'", aip->ai_name);
6958 7030 break;
6959 7031 case DLADM_STATUS_BADVAL: {
6960 7032 int j;
6961 7033 char *ptr, *lim;
6962 7034 char **propvals = NULL;
6963 7035 uint_t valcnt = DLADM_MAX_PROP_VALCNT;
6964 7036 dladm_status_t s;
6965 7037
6966 7038 ptr = malloc((sizeof (char *) +
6967 7039 DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT +
6968 7040 MAX_PROP_LINE);
6969 7041
6970 7042 propvals = (char **)(void *)ptr;
6971 7043 if (propvals == NULL)
6972 7044 die("insufficient memory");
6973 7045
6974 7046 for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) {
6975 7047 propvals[j] = ptr + sizeof (char *) *
6976 7048 DLADM_MAX_PROP_VALCNT +
6977 7049 j * DLADM_PROP_VAL_MAX;
6978 7050 }
6979 7051 s = dladm_get_linkprop(handle, linkid,
6980 7052 DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals,
6981 7053 &valcnt);
6982 7054
6983 7055 if (s != DLADM_STATUS_OK) {
6984 7056 warn_dlerr(status, "cannot set link property "
6985 7057 "'%s' on '%s'", aip->ai_name, argv[optind]);
6986 7058 free(propvals);
6987 7059 break;
6988 7060 }
6989 7061
6990 7062 ptr = errmsg;
6991 7063 lim = ptr + DLADM_STRSIZE;
6992 7064 *ptr = '\0';
6993 7065 for (j = 0; j < valcnt; j++) {
6994 7066 ptr += snprintf(ptr, lim - ptr, "%s,",
6995 7067 propvals[j]);
6996 7068 if (ptr >= lim)
6997 7069 break;
6998 7070 }
6999 7071 if (ptr > errmsg) {
7000 7072 *(ptr - 1) = '\0';
7001 7073 warn("link property '%s' must be one of: %s",
7002 7074 aip->ai_name, errmsg);
7003 7075 } else
7004 7076 warn("invalid link property '%s'", *val);
7005 7077 free(propvals);
7006 7078 break;
7007 7079 }
7008 7080 default:
7009 7081 if (reset) {
7010 7082 warn_dlerr(status, "cannot reset link property "
7011 7083 "'%s' on '%s'", aip->ai_name, argv[optind]);
7012 7084 } else {
7013 7085 warn_dlerr(status, "cannot set link property "
7014 7086 "'%s' on '%s'", aip->ai_name, argv[optind]);
7015 7087 }
7016 7088 break;
7017 7089 }
7018 7090 }
7019 7091 done:
7020 7092 dladm_free_props(proplist);
7021 7093 if (status != DLADM_STATUS_OK) {
7022 7094 dladm_close(handle);
7023 7095 exit(EXIT_FAILURE);
7024 7096 }
7025 7097 }
7026 7098
7027 7099 static void
7028 7100 do_set_linkprop(int argc, char **argv, const char *use)
7029 7101 {
7030 7102 set_linkprop(argc, argv, B_FALSE, use);
7031 7103 }
7032 7104
7033 7105 static void
7034 7106 do_reset_linkprop(int argc, char **argv, const char *use)
7035 7107 {
7036 7108 set_linkprop(argc, argv, B_TRUE, use);
7037 7109 }
7038 7110
7039 7111 static int
7040 7112 convert_secobj(char *buf, uint_t len, uint8_t *obj_val, uint_t *obj_lenp,
7041 7113 dladm_secobj_class_t class)
7042 7114 {
7043 7115 int error = 0;
7044 7116
7045 7117 if (class == DLADM_SECOBJ_CLASS_WPA) {
7046 7118 if (len < 8 || len > 63)
7047 7119 return (EINVAL);
7048 7120 (void) memcpy(obj_val, buf, len);
7049 7121 *obj_lenp = len;
7050 7122 return (error);
7051 7123 }
7052 7124
7053 7125 if (class == DLADM_SECOBJ_CLASS_WEP) {
7054 7126 switch (len) {
7055 7127 case 5: /* ASCII key sizes */
7056 7128 case 13:
7057 7129 (void) memcpy(obj_val, buf, len);
7058 7130 *obj_lenp = len;
7059 7131 break;
7060 7132 case 10: /* Hex key sizes, not preceded by 0x */
7061 7133 case 26:
7062 7134 error = hexascii_to_octet(buf, len, obj_val, obj_lenp);
7063 7135 break;
7064 7136 case 12: /* Hex key sizes, preceded by 0x */
7065 7137 case 28:
7066 7138 if (strncmp(buf, "0x", 2) != 0)
7067 7139 return (EINVAL);
7068 7140 error = hexascii_to_octet(buf + 2, len - 2,
7069 7141 obj_val, obj_lenp);
7070 7142 break;
7071 7143 default:
7072 7144 return (EINVAL);
7073 7145 }
7074 7146 return (error);
7075 7147 }
7076 7148
7077 7149 return (ENOENT);
7078 7150 }
7079 7151
7080 7152 static void
7081 7153 defersig(int sig)
7082 7154 {
7083 7155 signalled = sig;
7084 7156 }
7085 7157
7086 7158 static int
7087 7159 get_secobj_from_tty(uint_t try, const char *objname, char *buf)
7088 7160 {
7089 7161 uint_t len = 0;
7090 7162 int c;
7091 7163 struct termios stored, current;
7092 7164 void (*sigfunc)(int);
7093 7165
7094 7166 /*
7095 7167 * Turn off echo -- but before we do so, defer SIGINT handling
7096 7168 * so that a ^C doesn't leave the terminal corrupted.
7097 7169 */
7098 7170 sigfunc = signal(SIGINT, defersig);
7099 7171 (void) fflush(stdin);
7100 7172 (void) tcgetattr(0, &stored);
7101 7173 current = stored;
7102 7174 current.c_lflag &= ~(ICANON|ECHO);
7103 7175 current.c_cc[VTIME] = 0;
7104 7176 current.c_cc[VMIN] = 1;
7105 7177 (void) tcsetattr(0, TCSANOW, ¤t);
7106 7178 again:
7107 7179 if (try == 1)
7108 7180 (void) printf(gettext("provide value for '%s': "), objname);
7109 7181 else
7110 7182 (void) printf(gettext("confirm value for '%s': "), objname);
7111 7183
7112 7184 (void) fflush(stdout);
7113 7185 while (signalled == 0) {
7114 7186 c = getchar();
7115 7187 if (c == '\n' || c == '\r') {
7116 7188 if (len != 0)
7117 7189 break;
7118 7190 (void) putchar('\n');
7119 7191 goto again;
7120 7192 }
7121 7193
7122 7194 buf[len++] = c;
7123 7195 if (len >= DLADM_SECOBJ_VAL_MAX - 1)
7124 7196 break;
7125 7197 (void) putchar('*');
7126 7198 }
7127 7199
7128 7200 (void) putchar('\n');
7129 7201 (void) fflush(stdin);
7130 7202
7131 7203 /*
7132 7204 * Restore terminal setting and handle deferred signals.
7133 7205 */
7134 7206 (void) tcsetattr(0, TCSANOW, &stored);
7135 7207
7136 7208 (void) signal(SIGINT, sigfunc);
7137 7209 if (signalled != 0)
7138 7210 (void) kill(getpid(), signalled);
7139 7211
7140 7212 return (len);
7141 7213 }
7142 7214
7143 7215 static int
7144 7216 get_secobj_val(char *obj_name, uint8_t *obj_val, uint_t *obj_lenp,
7145 7217 dladm_secobj_class_t class, FILE *filep)
7146 7218 {
7147 7219 int rval;
7148 7220 uint_t len, len2;
7149 7221 char buf[DLADM_SECOBJ_VAL_MAX], buf2[DLADM_SECOBJ_VAL_MAX];
7150 7222
7151 7223 if (filep == NULL) {
7152 7224 len = get_secobj_from_tty(1, obj_name, buf);
7153 7225 rval = convert_secobj(buf, len, obj_val, obj_lenp, class);
7154 7226 if (rval == 0) {
7155 7227 len2 = get_secobj_from_tty(2, obj_name, buf2);
7156 7228 if (len != len2 || memcmp(buf, buf2, len) != 0)
7157 7229 rval = ENOTSUP;
7158 7230 }
7159 7231 return (rval);
7160 7232 } else {
7161 7233 for (;;) {
7162 7234 if (fgets(buf, sizeof (buf), filep) == NULL)
7163 7235 break;
7164 7236 if (isspace(buf[0]))
7165 7237 continue;
7166 7238
7167 7239 len = strlen(buf);
7168 7240 if (buf[len - 1] == '\n') {
7169 7241 buf[len - 1] = '\0';
7170 7242 len--;
7171 7243 }
7172 7244 break;
7173 7245 }
7174 7246 (void) fclose(filep);
7175 7247 }
7176 7248 return (convert_secobj(buf, len, obj_val, obj_lenp, class));
7177 7249 }
7178 7250
7179 7251 static boolean_t
7180 7252 check_auth(const char *auth)
7181 7253 {
7182 7254 struct passwd *pw;
7183 7255
7184 7256 if ((pw = getpwuid(getuid())) == NULL)
7185 7257 return (B_FALSE);
7186 7258
7187 7259 return (chkauthattr(auth, pw->pw_name) != 0);
7188 7260 }
7189 7261
7190 7262 static void
7191 7263 audit_secobj(char *auth, char *class, char *obj,
7192 7264 boolean_t success, boolean_t create)
7193 7265 {
7194 7266 adt_session_data_t *ah;
7195 7267 adt_event_data_t *event;
7196 7268 au_event_t flag;
7197 7269 char *errstr;
7198 7270
7199 7271 if (create) {
7200 7272 flag = ADT_dladm_create_secobj;
7201 7273 errstr = "ADT_dladm_create_secobj";
7202 7274 } else {
7203 7275 flag = ADT_dladm_delete_secobj;
7204 7276 errstr = "ADT_dladm_delete_secobj";
7205 7277 }
7206 7278
7207 7279 if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0)
7208 7280 die("adt_start_session: %s", strerror(errno));
7209 7281
7210 7282 if ((event = adt_alloc_event(ah, flag)) == NULL)
7211 7283 die("adt_alloc_event (%s): %s", errstr, strerror(errno));
7212 7284
7213 7285 /* fill in audit info */
7214 7286 if (create) {
7215 7287 event->adt_dladm_create_secobj.auth_used = auth;
7216 7288 event->adt_dladm_create_secobj.obj_class = class;
7217 7289 event->adt_dladm_create_secobj.obj_name = obj;
7218 7290 } else {
7219 7291 event->adt_dladm_delete_secobj.auth_used = auth;
7220 7292 event->adt_dladm_delete_secobj.obj_class = class;
7221 7293 event->adt_dladm_delete_secobj.obj_name = obj;
7222 7294 }
7223 7295
7224 7296 if (success) {
7225 7297 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
7226 7298 die("adt_put_event (%s, success): %s", errstr,
7227 7299 strerror(errno));
7228 7300 }
7229 7301 } else {
7230 7302 if (adt_put_event(event, ADT_FAILURE,
7231 7303 ADT_FAIL_VALUE_AUTH) != 0) {
7232 7304 die("adt_put_event: (%s, failure): %s", errstr,
7233 7305 strerror(errno));
7234 7306 }
7235 7307 }
7236 7308
7237 7309 adt_free_event(event);
7238 7310 (void) adt_end_session(ah);
7239 7311 }
7240 7312
7241 7313 static void
7242 7314 do_create_secobj(int argc, char **argv, const char *use)
7243 7315 {
7244 7316 int option, rval;
7245 7317 FILE *filep = NULL;
7246 7318 char *obj_name = NULL;
7247 7319 char *class_name = NULL;
7248 7320 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX];
7249 7321 uint_t obj_len;
7250 7322 boolean_t success, temp = B_FALSE;
7251 7323 dladm_status_t status;
7252 7324 dladm_secobj_class_t class = -1;
7253 7325 uid_t euid;
7254 7326
7255 7327 opterr = 0;
7256 7328 (void) memset(obj_val, 0, DLADM_SECOBJ_VAL_MAX);
7257 7329 while ((option = getopt_long(argc, argv, ":f:c:R:t",
7258 7330 wifi_longopts, NULL)) != -1) {
7259 7331 switch (option) {
7260 7332 case 'f':
7261 7333 euid = geteuid();
7262 7334 (void) seteuid(getuid());
7263 7335 filep = fopen(optarg, "r");
7264 7336 if (filep == NULL) {
7265 7337 die("cannot open %s: %s", optarg,
7266 7338 strerror(errno));
7267 7339 }
7268 7340 (void) seteuid(euid);
7269 7341 break;
7270 7342 case 'c':
7271 7343 class_name = optarg;
7272 7344 status = dladm_str2secobjclass(optarg, &class);
7273 7345 if (status != DLADM_STATUS_OK) {
7274 7346 die("invalid secure object class '%s', "
7275 7347 "valid values are: wep, wpa", optarg);
7276 7348 }
7277 7349 break;
7278 7350 case 't':
7279 7351 temp = B_TRUE;
7280 7352 break;
7281 7353 case 'R':
7282 7354 status = dladm_set_rootdir(optarg);
7283 7355 if (status != DLADM_STATUS_OK) {
7284 7356 die_dlerr(status, "invalid directory "
7285 7357 "specified");
7286 7358 }
7287 7359 break;
7288 7360 default:
7289 7361 die_opterr(optopt, option, use);
7290 7362 break;
7291 7363 }
7292 7364 }
7293 7365
7294 7366 if (optind == (argc - 1))
7295 7367 obj_name = argv[optind];
7296 7368 else if (optind != argc)
7297 7369 usage();
7298 7370
7299 7371 if (class == -1)
7300 7372 die("secure object class required");
7301 7373
7302 7374 if (obj_name == NULL)
7303 7375 die("secure object name required");
7304 7376
7305 7377 if (!dladm_valid_secobj_name(obj_name))
7306 7378 die("invalid secure object name '%s'", obj_name);
7307 7379
7308 7380 success = check_auth(LINK_SEC_AUTH);
7309 7381 audit_secobj(LINK_SEC_AUTH, class_name, obj_name, success, B_TRUE);
7310 7382 if (!success)
7311 7383 die("authorization '%s' is required", LINK_SEC_AUTH);
7312 7384
7313 7385 rval = get_secobj_val(obj_name, obj_val, &obj_len, class, filep);
7314 7386 if (rval != 0) {
7315 7387 switch (rval) {
7316 7388 case ENOENT:
7317 7389 die("invalid secure object class");
7318 7390 break;
7319 7391 case EINVAL:
7320 7392 die("invalid secure object value");
7321 7393 break;
7322 7394 case ENOTSUP:
7323 7395 die("verification failed");
7324 7396 break;
7325 7397 default:
7326 7398 die("invalid secure object: %s", strerror(rval));
7327 7399 break;
7328 7400 }
7329 7401 }
7330 7402
7331 7403 status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len,
7332 7404 DLADM_OPT_CREATE | DLADM_OPT_ACTIVE);
7333 7405 if (status != DLADM_STATUS_OK) {
7334 7406 die_dlerr(status, "could not create secure object '%s'",
7335 7407 obj_name);
7336 7408 }
7337 7409 if (temp)
7338 7410 return;
7339 7411
7340 7412 status = dladm_set_secobj(handle, obj_name, class, obj_val, obj_len,
7341 7413 DLADM_OPT_PERSIST);
7342 7414 if (status != DLADM_STATUS_OK) {
7343 7415 warn_dlerr(status, "could not persistently create secure "
7344 7416 "object '%s'", obj_name);
7345 7417 }
7346 7418 }
7347 7419
7348 7420 static void
7349 7421 do_delete_secobj(int argc, char **argv, const char *use)
7350 7422 {
7351 7423 int i, option;
7352 7424 boolean_t temp = B_FALSE;
7353 7425 boolean_t success;
7354 7426 dladm_status_t status, pstatus;
7355 7427 int nfields = 1;
7356 7428 char *field, *token, *lasts = NULL, c;
7357 7429
7358 7430 opterr = 0;
7359 7431 status = pstatus = DLADM_STATUS_OK;
7360 7432 while ((option = getopt_long(argc, argv, ":R:t",
7361 7433 wifi_longopts, NULL)) != -1) {
7362 7434 switch (option) {
7363 7435 case 't':
7364 7436 temp = B_TRUE;
7365 7437 break;
7366 7438 case 'R':
7367 7439 status = dladm_set_rootdir(optarg);
7368 7440 if (status != DLADM_STATUS_OK) {
7369 7441 die_dlerr(status, "invalid directory "
7370 7442 "specified");
7371 7443 }
7372 7444 break;
7373 7445 default:
7374 7446 die_opterr(optopt, option, use);
7375 7447 break;
7376 7448 }
7377 7449 }
7378 7450
7379 7451 if (optind != (argc - 1))
7380 7452 die("secure object name required");
7381 7453
7382 7454 token = argv[optind];
7383 7455 while ((c = *token++) != NULL) {
7384 7456 if (c == ',')
7385 7457 nfields++;
7386 7458 }
7387 7459 token = strdup(argv[optind]);
7388 7460 if (token == NULL)
7389 7461 die("no memory");
7390 7462
7391 7463 success = check_auth(LINK_SEC_AUTH);
7392 7464 audit_secobj(LINK_SEC_AUTH, "unknown", argv[optind], success, B_FALSE);
7393 7465 if (!success)
7394 7466 die("authorization '%s' is required", LINK_SEC_AUTH);
7395 7467
7396 7468 for (i = 0; i < nfields; i++) {
7397 7469
7398 7470 field = strtok_r(token, ",", &lasts);
7399 7471 token = NULL;
7400 7472 status = dladm_unset_secobj(handle, field, DLADM_OPT_ACTIVE);
7401 7473 if (!temp) {
7402 7474 pstatus = dladm_unset_secobj(handle, field,
7403 7475 DLADM_OPT_PERSIST);
7404 7476 } else {
7405 7477 pstatus = DLADM_STATUS_OK;
7406 7478 }
7407 7479
7408 7480 if (status != DLADM_STATUS_OK) {
7409 7481 warn_dlerr(status, "could not delete secure object "
7410 7482 "'%s'", field);
7411 7483 }
7412 7484 if (pstatus != DLADM_STATUS_OK) {
7413 7485 warn_dlerr(pstatus, "could not persistently delete "
7414 7486 "secure object '%s'", field);
7415 7487 }
7416 7488 }
7417 7489 free(token);
7418 7490
7419 7491 if (status != DLADM_STATUS_OK || pstatus != DLADM_STATUS_OK) {
7420 7492 dladm_close(handle);
7421 7493 exit(EXIT_FAILURE);
7422 7494 }
7423 7495 }
7424 7496
7425 7497 typedef struct show_secobj_state {
7426 7498 boolean_t ss_persist;
7427 7499 boolean_t ss_parsable;
7428 7500 boolean_t ss_header;
7429 7501 ofmt_handle_t ss_ofmt;
7430 7502 } show_secobj_state_t;
7431 7503
7432 7504
7433 7505 static boolean_t
7434 7506 show_secobj(dladm_handle_t dh, void *arg, const char *obj_name)
7435 7507 {
7436 7508 uint_t obj_len = DLADM_SECOBJ_VAL_MAX;
7437 7509 uint8_t obj_val[DLADM_SECOBJ_VAL_MAX];
7438 7510 char buf[DLADM_STRSIZE];
7439 7511 uint_t flags = 0;
7440 7512 dladm_secobj_class_t class;
7441 7513 show_secobj_state_t *statep = arg;
7442 7514 dladm_status_t status;
7443 7515 secobj_fields_buf_t sbuf;
7444 7516
7445 7517 bzero(&sbuf, sizeof (secobj_fields_buf_t));
7446 7518 if (statep->ss_persist)
7447 7519 flags |= DLADM_OPT_PERSIST;
7448 7520
7449 7521 status = dladm_get_secobj(dh, obj_name, &class, obj_val, &obj_len,
7450 7522 flags);
7451 7523 if (status != DLADM_STATUS_OK)
7452 7524 die_dlerr(status, "cannot get secure object '%s'", obj_name);
7453 7525
7454 7526 (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name),
7455 7527 obj_name);
7456 7528 (void) dladm_secobjclass2str(class, buf);
7457 7529 (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf);
7458 7530 if (getuid() == 0) {
7459 7531 char val[DLADM_SECOBJ_VAL_MAX * 2];
7460 7532 uint_t len = sizeof (val);
7461 7533
7462 7534 if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0)
7463 7535 (void) snprintf(sbuf.ss_val,
7464 7536 sizeof (sbuf.ss_val), "%s", val);
7465 7537 }
7466 7538 ofmt_print(statep->ss_ofmt, &sbuf);
7467 7539 return (B_TRUE);
7468 7540 }
7469 7541
7470 7542 static void
7471 7543 do_show_secobj(int argc, char **argv, const char *use)
7472 7544 {
7473 7545 int option;
7474 7546 show_secobj_state_t state;
7475 7547 dladm_status_t status;
7476 7548 boolean_t o_arg = B_FALSE;
7477 7549 uint_t i;
7478 7550 uint_t flags;
7479 7551 char *fields_str = NULL;
7480 7552 char *def_fields = "object,class";
7481 7553 char *all_fields = "object,class,value";
7482 7554 char *field, *token, *lasts = NULL, c;
7483 7555 ofmt_handle_t ofmt;
7484 7556 ofmt_status_t oferr;
7485 7557 uint_t ofmtflags = 0;
7486 7558
7487 7559 opterr = 0;
7488 7560 bzero(&state, sizeof (state));
7489 7561 state.ss_parsable = B_FALSE;
7490 7562 fields_str = def_fields;
7491 7563 state.ss_persist = B_FALSE;
7492 7564 state.ss_parsable = B_FALSE;
7493 7565 state.ss_header = B_TRUE;
7494 7566 while ((option = getopt_long(argc, argv, ":pPo:",
7495 7567 wifi_longopts, NULL)) != -1) {
7496 7568 switch (option) {
7497 7569 case 'p':
7498 7570 state.ss_parsable = B_TRUE;
7499 7571 break;
7500 7572 case 'P':
7501 7573 state.ss_persist = B_TRUE;
7502 7574 break;
7503 7575 case 'o':
7504 7576 o_arg = B_TRUE;
7505 7577 if (strcasecmp(optarg, "all") == 0)
7506 7578 fields_str = all_fields;
7507 7579 else
7508 7580 fields_str = optarg;
7509 7581 break;
7510 7582 default:
7511 7583 die_opterr(optopt, option, use);
7512 7584 break;
7513 7585 }
7514 7586 }
7515 7587
7516 7588 if (state.ss_parsable && !o_arg)
7517 7589 die("option -c requires -o");
7518 7590
7519 7591 if (state.ss_parsable && fields_str == all_fields)
7520 7592 die("\"-o all\" is invalid with -p");
7521 7593
7522 7594 if (state.ss_parsable)
7523 7595 ofmtflags |= OFMT_PARSABLE;
7524 7596 oferr = ofmt_open(fields_str, secobj_fields, ofmtflags, 0, &ofmt);
7525 7597 dladm_ofmt_check(oferr, state.ss_parsable, ofmt);
7526 7598 state.ss_ofmt = ofmt;
7527 7599
7528 7600 flags = state.ss_persist ? DLADM_OPT_PERSIST : 0;
7529 7601
7530 7602 if (optind == (argc - 1)) {
7531 7603 uint_t obj_fields = 1;
7532 7604
7533 7605 token = argv[optind];
7534 7606 if (token == NULL)
7535 7607 die("secure object name required");
7536 7608 while ((c = *token++) != NULL) {
7537 7609 if (c == ',')
7538 7610 obj_fields++;
7539 7611 }
7540 7612 token = strdup(argv[optind]);
7541 7613 if (token == NULL)
7542 7614 die("no memory");
7543 7615 for (i = 0; i < obj_fields; i++) {
7544 7616 field = strtok_r(token, ",", &lasts);
7545 7617 token = NULL;
7546 7618 if (!show_secobj(handle, &state, field))
7547 7619 break;
7548 7620 }
7549 7621 free(token);
7550 7622 ofmt_close(ofmt);
7551 7623 return;
7552 7624 } else if (optind != argc)
7553 7625 usage();
7554 7626
7555 7627 status = dladm_walk_secobj(handle, &state, show_secobj, flags);
7556 7628
7557 7629 if (status != DLADM_STATUS_OK)
7558 7630 die_dlerr(status, "show-secobj");
7559 7631 ofmt_close(ofmt);
7560 7632 }
7561 7633
7562 7634 /*ARGSUSED*/
7563 7635 static int
7564 7636 i_dladm_init_linkprop(dladm_handle_t dh, datalink_id_t linkid, void *arg)
7565 7637 {
7566 7638 (void) dladm_init_linkprop(dh, linkid, B_TRUE);
7567 7639 return (DLADM_WALK_CONTINUE);
7568 7640 }
7569 7641
7570 7642 /*ARGSUSED*/
7571 7643 void
7572 7644 do_init_linkprop(int argc, char **argv, const char *use)
7573 7645 {
7574 7646 int option;
7575 7647 dladm_status_t status;
7576 7648 datalink_id_t linkid = DATALINK_ALL_LINKID;
7577 7649 datalink_media_t media = DATALINK_ANY_MEDIATYPE;
7578 7650 uint_t any_media = B_TRUE;
7579 7651
7580 7652 opterr = 0;
7581 7653 while ((option = getopt(argc, argv, ":w")) != -1) {
7582 7654 switch (option) {
7583 7655 case 'w':
7584 7656 media = DL_WIFI;
7585 7657 any_media = B_FALSE;
7586 7658 break;
7587 7659 default:
7588 7660 /*
7589 7661 * Because init-linkprop is not a public command,
7590 7662 * print the usage instead.
7591 7663 */
7592 7664 usage();
7593 7665 break;
7594 7666 }
7595 7667 }
7596 7668
7597 7669 if (optind == (argc - 1)) {
7598 7670 if ((status = dladm_name2info(handle, argv[optind], &linkid,
7599 7671 NULL, NULL, NULL)) != DLADM_STATUS_OK)
7600 7672 die_dlerr(status, "link %s is not valid", argv[optind]);
7601 7673 } else if (optind != argc) {
7602 7674 usage();
7603 7675 }
7604 7676
7605 7677 if (linkid == DATALINK_ALL_LINKID) {
7606 7678 /*
7607 7679 * linkprops of links of other classes have been initialized as
7608 7680 * part of the dladm up-xxx operation.
7609 7681 */
7610 7682 (void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
7611 7683 NULL, DATALINK_CLASS_PHYS, media, DLADM_OPT_PERSIST);
7612 7684 } else {
7613 7685 (void) dladm_init_linkprop(handle, linkid, any_media);
7614 7686 }
7615 7687 }
7616 7688
7617 7689 static void
7618 7690 do_show_ether(int argc, char **argv, const char *use)
7619 7691 {
7620 7692 int option;
7621 7693 datalink_id_t linkid;
7622 7694 print_ether_state_t state;
7623 7695 char *fields_str = NULL;
7624 7696 ofmt_handle_t ofmt;
7625 7697 ofmt_status_t oferr;
7626 7698 uint_t ofmtflags = 0;
7627 7699
7628 7700 bzero(&state, sizeof (state));
7629 7701 state.es_link = NULL;
7630 7702 state.es_parsable = B_FALSE;
7631 7703
7632 7704 while ((option = getopt_long(argc, argv, "o:px",
7633 7705 showeth_lopts, NULL)) != -1) {
7634 7706 switch (option) {
7635 7707 case 'x':
7636 7708 state.es_extended = B_TRUE;
7637 7709 break;
7638 7710 case 'p':
7639 7711 state.es_parsable = B_TRUE;
7640 7712 break;
7641 7713 case 'o':
7642 7714 fields_str = optarg;
7643 7715 break;
7644 7716 default:
7645 7717 die_opterr(optopt, option, use);
7646 7718 break;
7647 7719 }
7648 7720 }
7649 7721
7650 7722 if (optind == (argc - 1))
7651 7723 state.es_link = argv[optind];
7652 7724
7653 7725 if (state.es_parsable)
7654 7726 ofmtflags |= OFMT_PARSABLE;
7655 7727 oferr = ofmt_open(fields_str, ether_fields, ofmtflags,
7656 7728 DLADM_DEFAULT_COL, &ofmt);
7657 7729 dladm_ofmt_check(oferr, state.es_parsable, ofmt);
7658 7730 state.es_ofmt = ofmt;
7659 7731
7660 7732 if (state.es_link == NULL) {
7661 7733 (void) dladm_walk_datalink_id(show_etherprop, handle, &state,
7662 7734 DATALINK_CLASS_PHYS, DL_ETHER, DLADM_OPT_ACTIVE);
7663 7735 } else {
7664 7736 if (!link_is_ether(state.es_link, &linkid))
7665 7737 die("invalid link specified");
7666 7738 (void) show_etherprop(handle, linkid, &state);
7667 7739 }
7668 7740 ofmt_close(ofmt);
7669 7741 }
7670 7742
7671 7743 static int
7672 7744 show_etherprop(dladm_handle_t dh, datalink_id_t linkid, void *arg)
7673 7745 {
7674 7746 print_ether_state_t *statep = arg;
7675 7747 ether_fields_buf_t ebuf;
7676 7748 dladm_ether_info_t eattr;
7677 7749 dladm_status_t status;
7678 7750
7679 7751 bzero(&ebuf, sizeof (ether_fields_buf_t));
7680 7752 if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL,
7681 7753 ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) {
7682 7754 return (DLADM_WALK_CONTINUE);
7683 7755 }
7684 7756
7685 7757 status = dladm_ether_info(dh, linkid, &eattr);
7686 7758 if (status != DLADM_STATUS_OK)
7687 7759 goto cleanup;
7688 7760
7689 7761 (void) strlcpy(ebuf.eth_ptype, "current", sizeof (ebuf.eth_ptype));
7690 7762
7691 7763 (void) dladm_ether_autoneg2str(ebuf.eth_autoneg,
7692 7764 sizeof (ebuf.eth_autoneg), &eattr, CURRENT);
7693 7765 (void) dladm_ether_pause2str(ebuf.eth_pause,
7694 7766 sizeof (ebuf.eth_pause), &eattr, CURRENT);
7695 7767 (void) dladm_ether_spdx2str(ebuf.eth_spdx,
7696 7768 sizeof (ebuf.eth_spdx), &eattr, CURRENT);
7697 7769 (void) strlcpy(ebuf.eth_state,
7698 7770 dladm_linkstate2str(eattr.lei_state, ebuf.eth_state),
7699 7771 sizeof (ebuf.eth_state));
7700 7772 (void) strlcpy(ebuf.eth_rem_fault,
7701 7773 (eattr.lei_attr[CURRENT].le_fault ? "fault" : "none"),
7702 7774 sizeof (ebuf.eth_rem_fault));
7703 7775
7704 7776 ofmt_print(statep->es_ofmt, &ebuf);
7705 7777
7706 7778 if (statep->es_extended)
7707 7779 show_ether_xprop(arg, &eattr);
7708 7780
7709 7781 cleanup:
7710 7782 dladm_ether_info_done(&eattr);
7711 7783 return (DLADM_WALK_CONTINUE);
7712 7784 }
7713 7785
7714 7786 /* ARGSUSED */
7715 7787 static void
7716 7788 do_init_secobj(int argc, char **argv, const char *use)
7717 7789 {
7718 7790 dladm_status_t status;
7719 7791
7720 7792 status = dladm_init_secobj(handle);
7721 7793 if (status != DLADM_STATUS_OK)
7722 7794 die_dlerr(status, "secure object initialization failed");
7723 7795 }
7724 7796
7725 7797 enum bridge_func {
7726 7798 brCreate, brAdd, brModify
7727 7799 };
7728 7800
7729 7801 static void
7730 7802 create_modify_add_bridge(int argc, char **argv, const char *use,
7731 7803 enum bridge_func func)
7732 7804 {
7733 7805 int option;
7734 7806 uint_t n, i, nlink;
7735 7807 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
7736 7808 char *altroot = NULL;
7737 7809 char *links[MAXPORT];
7738 7810 datalink_id_t linkids[MAXPORT];
7739 7811 dladm_status_t status;
7740 7812 const char *bridge;
7741 7813 UID_STP_CFG_T cfg, cfg_old;
7742 7814 dladm_bridge_prot_t brprot = DLADM_BRIDGE_PROT_UNKNOWN;
7743 7815 dladm_bridge_prot_t brprot_old;
7744 7816
7745 7817 /* Set up the default configuration values */
7746 7818 cfg.field_mask = 0;
7747 7819 cfg.bridge_priority = DEF_BR_PRIO;
7748 7820 cfg.max_age = DEF_BR_MAXAGE;
7749 7821 cfg.hello_time = DEF_BR_HELLOT;
7750 7822 cfg.forward_delay = DEF_BR_FWDELAY;
7751 7823 cfg.force_version = DEF_FORCE_VERS;
7752 7824
7753 7825 nlink = opterr = 0;
7754 7826 while ((option = getopt_long(argc, argv, ":P:R:d:f:h:l:m:p:",
7755 7827 bridge_lopts, NULL)) != -1) {
7756 7828 switch (option) {
7757 7829 case 'P':
7758 7830 if (func == brAdd)
7759 7831 die_opterr(optopt, option, use);
7760 7832 status = dladm_bridge_str2prot(optarg, &brprot);
7761 7833 if (status != DLADM_STATUS_OK)
7762 7834 die_dlerr(status, "protection %s", optarg);
7763 7835 break;
7764 7836 case 'R':
7765 7837 altroot = optarg;
7766 7838 break;
7767 7839 case 'd':
7768 7840 if (func == brAdd)
7769 7841 die_opterr(optopt, option, use);
7770 7842 if (cfg.field_mask & BR_CFG_DELAY)
7771 7843 die("forwarding delay set more than once");
7772 7844 if (!str2int(optarg, &cfg.forward_delay) ||
7773 7845 cfg.forward_delay < MIN_BR_FWDELAY ||
7774 7846 cfg.forward_delay > MAX_BR_FWDELAY)
7775 7847 die("incorrect forwarding delay");
7776 7848 cfg.field_mask |= BR_CFG_DELAY;
7777 7849 break;
7778 7850 case 'f':
7779 7851 if (func == brAdd)
7780 7852 die_opterr(optopt, option, use);
7781 7853 if (cfg.field_mask & BR_CFG_FORCE_VER)
7782 7854 die("force protocol set more than once");
7783 7855 if (!str2int(optarg, &cfg.force_version) ||
7784 7856 cfg.force_version < 0)
7785 7857 die("incorrect force protocol");
7786 7858 cfg.field_mask |= BR_CFG_FORCE_VER;
7787 7859 break;
7788 7860 case 'h':
7789 7861 if (func == brAdd)
7790 7862 die_opterr(optopt, option, use);
7791 7863 if (cfg.field_mask & BR_CFG_HELLO)
7792 7864 die("hello time set more than once");
7793 7865 if (!str2int(optarg, &cfg.hello_time) ||
7794 7866 cfg.hello_time < MIN_BR_HELLOT ||
7795 7867 cfg.hello_time > MAX_BR_HELLOT)
7796 7868 die("incorrect hello time");
7797 7869 cfg.field_mask |= BR_CFG_HELLO;
7798 7870 break;
7799 7871 case 'l':
7800 7872 if (func == brModify)
7801 7873 die_opterr(optopt, option, use);
7802 7874 if (nlink >= MAXPORT)
7803 7875 die("too many links specified");
7804 7876 links[nlink++] = optarg;
7805 7877 break;
7806 7878 case 'm':
7807 7879 if (func == brAdd)
7808 7880 die_opterr(optopt, option, use);
7809 7881 if (cfg.field_mask & BR_CFG_AGE)
7810 7882 die("max age set more than once");
7811 7883 if (!str2int(optarg, &cfg.max_age) ||
7812 7884 cfg.max_age < MIN_BR_MAXAGE ||
7813 7885 cfg.max_age > MAX_BR_MAXAGE)
7814 7886 die("incorrect max age");
7815 7887 cfg.field_mask |= BR_CFG_AGE;
7816 7888 break;
7817 7889 case 'p':
7818 7890 if (func == brAdd)
7819 7891 die_opterr(optopt, option, use);
7820 7892 if (cfg.field_mask & BR_CFG_PRIO)
7821 7893 die("priority set more than once");
7822 7894 if (!str2int(optarg, &cfg.bridge_priority) ||
7823 7895 cfg.bridge_priority < MIN_BR_PRIO ||
7824 7896 cfg.bridge_priority > MAX_BR_PRIO)
7825 7897 die("incorrect priority");
7826 7898 cfg.bridge_priority &= 0xF000;
7827 7899 cfg.field_mask |= BR_CFG_PRIO;
7828 7900 break;
7829 7901 default:
7830 7902 die_opterr(optopt, option, use);
7831 7903 break;
7832 7904 }
7833 7905 }
7834 7906
7835 7907 /* get the bridge name (required last argument) */
7836 7908 if (optind != (argc-1))
7837 7909 usage();
7838 7910
7839 7911 bridge = argv[optind];
7840 7912 if (!dladm_valid_bridgename(bridge))
7841 7913 die("invalid bridge name '%s'", bridge);
7842 7914
7843 7915 /*
7844 7916 * Get the current properties, if any, and merge in with changes. This
7845 7917 * is necessary (even with the field_mask feature) so that the
7846 7918 * value-checking macros will produce the right results with proposed
7847 7919 * changes to existing configuration. We only need it for those
7848 7920 * parameters, though.
7849 7921 */
7850 7922 (void) dladm_bridge_get_properties(bridge, &cfg_old, &brprot_old);
7851 7923 if (brprot == DLADM_BRIDGE_PROT_UNKNOWN)
7852 7924 brprot = brprot_old;
7853 7925 if (!(cfg.field_mask & BR_CFG_AGE))
7854 7926 cfg.max_age = cfg_old.max_age;
7855 7927 if (!(cfg.field_mask & BR_CFG_HELLO))
7856 7928 cfg.hello_time = cfg_old.hello_time;
7857 7929 if (!(cfg.field_mask & BR_CFG_DELAY))
7858 7930 cfg.forward_delay = cfg_old.forward_delay;
7859 7931
7860 7932 if (!CHECK_BRIDGE_CONFIG(cfg)) {
7861 7933 warn("illegal forward delay / max age / hello time "
7862 7934 "combination");
7863 7935 if (NO_MAXAGE(cfg)) {
7864 7936 die("no max age possible: need forward delay >= %d or "
7865 7937 "hello time <= %d", MIN_FWDELAY_NOM(cfg),
7866 7938 MAX_HELLOTIME_NOM(cfg));
7867 7939 } else if (SMALL_MAXAGE(cfg)) {
7868 7940 if (CAPPED_MAXAGE(cfg))
7869 7941 die("max age too small: need age >= %d and "
7870 7942 "<= %d or hello time <= %d",
7871 7943 MIN_MAXAGE(cfg), MAX_MAXAGE(cfg),
7872 7944 MAX_HELLOTIME(cfg));
7873 7945 else
7874 7946 die("max age too small: need age >= %d or "
7875 7947 "hello time <= %d",
7876 7948 MIN_MAXAGE(cfg), MAX_HELLOTIME(cfg));
7877 7949 } else if (FLOORED_MAXAGE(cfg)) {
7878 7950 die("max age too large: need age >= %d and <= %d or "
7879 7951 "forward delay >= %d",
7880 7952 MIN_MAXAGE(cfg), MAX_MAXAGE(cfg),
7881 7953 MIN_FWDELAY(cfg));
7882 7954 } else {
7883 7955 die("max age too large: need age <= %d or forward "
7884 7956 "delay >= %d",
7885 7957 MAX_MAXAGE(cfg), MIN_FWDELAY(cfg));
7886 7958 }
7887 7959 }
7888 7960
7889 7961 if (altroot != NULL)
7890 7962 altroot_cmd(altroot, argc, argv);
7891 7963
7892 7964 for (n = 0; n < nlink; n++) {
7893 7965 datalink_class_t class;
7894 7966 uint32_t media;
7895 7967 char pointless[DLADM_STRSIZE];
7896 7968
7897 7969 if (dladm_name2info(handle, links[n], &linkids[n], NULL, &class,
7898 7970 &media) != DLADM_STATUS_OK)
7899 7971 die("invalid link name '%s'", links[n]);
7900 7972 if (class & ~(DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR |
7901 7973 DATALINK_CLASS_ETHERSTUB | DATALINK_CLASS_SIMNET))
7902 7974 die("%s %s cannot be bridged",
7903 7975 dladm_class2str(class, pointless), links[n]);
7904 7976 if (media != DL_ETHER && media != DL_100VG &&
7905 7977 media != DL_ETH_CSMA && media != DL_100BT)
7906 7978 die("%s interface %s cannot be bridged",
7907 7979 dladm_media2str(media, pointless), links[n]);
7908 7980 }
7909 7981
7910 7982 if (func == brCreate)
7911 7983 flags |= DLADM_OPT_CREATE;
7912 7984
7913 7985 if (func != brAdd) {
7914 7986 status = dladm_bridge_configure(handle, bridge, &cfg, brprot,
7915 7987 flags);
7916 7988 if (status != DLADM_STATUS_OK)
7917 7989 die_dlerr(status, "create operation failed");
7918 7990 }
7919 7991
7920 7992 status = DLADM_STATUS_OK;
7921 7993 for (n = 0; n < nlink; n++) {
7922 7994 status = dladm_bridge_setlink(handle, linkids[n], bridge);
7923 7995 if (status != DLADM_STATUS_OK)
7924 7996 break;
7925 7997 }
7926 7998
7927 7999 if (n >= nlink) {
7928 8000 /*
7929 8001 * We were successful. If we're creating a new bridge, then
7930 8002 * there's just one more step: enabling. If we're modifying or
7931 8003 * just adding links, then we're done.
7932 8004 */
7933 8005 if (func != brCreate ||
7934 8006 (status = dladm_bridge_enable(bridge)) == DLADM_STATUS_OK)
7935 8007 return;
7936 8008 }
7937 8009
7938 8010 /* clean up the partial configuration */
7939 8011 for (i = 0; i < n; i++)
7940 8012 (void) dladm_bridge_setlink(handle, linkids[i], "");
7941 8013
7942 8014 /* if failure for brCreate, then delete the bridge */
7943 8015 if (func == brCreate)
7944 8016 (void) dladm_bridge_delete(handle, bridge, flags);
7945 8017
7946 8018 if (n < nlink)
7947 8019 die_dlerr(status, "unable to add link %s to bridge %s",
7948 8020 links[n], bridge);
7949 8021 else
7950 8022 die_dlerr(status, "unable to enable bridge %s", bridge);
7951 8023 }
7952 8024
7953 8025 static void
7954 8026 do_create_bridge(int argc, char **argv, const char *use)
7955 8027 {
7956 8028 create_modify_add_bridge(argc, argv, use, brCreate);
7957 8029 }
7958 8030
7959 8031 static void
7960 8032 do_modify_bridge(int argc, char **argv, const char *use)
7961 8033 {
7962 8034 create_modify_add_bridge(argc, argv, use, brModify);
7963 8035 }
7964 8036
7965 8037 static void
7966 8038 do_add_bridge(int argc, char **argv, const char *use)
7967 8039 {
7968 8040 create_modify_add_bridge(argc, argv, use, brAdd);
7969 8041 }
7970 8042
7971 8043 static void
7972 8044 do_delete_bridge(int argc, char **argv, const char *use)
7973 8045 {
7974 8046 char option;
7975 8047 char *altroot = NULL;
7976 8048 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
7977 8049 dladm_status_t status;
7978 8050
7979 8051 opterr = 0;
7980 8052 while ((option = getopt_long(argc, argv, ":R:", bridge_lopts, NULL)) !=
7981 8053 -1) {
7982 8054 switch (option) {
7983 8055 case 'R':
7984 8056 altroot = optarg;
7985 8057 break;
7986 8058 default:
7987 8059 die_opterr(optopt, option, use);
7988 8060 break;
7989 8061 }
7990 8062 }
7991 8063
7992 8064 /* get the bridge name (required last argument) */
7993 8065 if (optind != (argc-1))
7994 8066 usage();
7995 8067
7996 8068 if (altroot != NULL)
7997 8069 altroot_cmd(altroot, argc, argv);
7998 8070
7999 8071 status = dladm_bridge_delete(handle, argv[optind], flags);
8000 8072 if (status != DLADM_STATUS_OK)
8001 8073 die_dlerr(status, "delete operation failed");
8002 8074 }
8003 8075
8004 8076 static void
8005 8077 do_remove_bridge(int argc, char **argv, const char *use)
8006 8078 {
8007 8079 char option;
8008 8080 uint_t n, nlink;
8009 8081 char *links[MAXPORT];
8010 8082 datalink_id_t linkids[MAXPORT];
8011 8083 char *altroot = NULL;
8012 8084 dladm_status_t status;
8013 8085 boolean_t removed_one;
8014 8086
8015 8087 nlink = opterr = 0;
8016 8088 while ((option = getopt_long(argc, argv, ":R:l:", bridge_lopts,
8017 8089 NULL)) != -1) {
8018 8090 switch (option) {
8019 8091 case 'R':
8020 8092 altroot = optarg;
8021 8093 break;
8022 8094 case 'l':
8023 8095 if (nlink >= MAXPORT)
8024 8096 die("too many links specified");
8025 8097 links[nlink++] = optarg;
8026 8098 break;
8027 8099 default:
8028 8100 die_opterr(optopt, option, use);
8029 8101 break;
8030 8102 }
8031 8103 }
8032 8104
8033 8105 if (nlink == 0)
8034 8106 usage();
8035 8107
8036 8108 /* get the bridge name (required last argument) */
8037 8109 if (optind != (argc-1))
8038 8110 usage();
8039 8111
8040 8112 if (altroot != NULL)
8041 8113 altroot_cmd(altroot, argc, argv);
8042 8114
8043 8115 for (n = 0; n < nlink; n++) {
8044 8116 char bridge[MAXLINKNAMELEN];
8045 8117
8046 8118 if (dladm_name2info(handle, links[n], &linkids[n], NULL, NULL,
8047 8119 NULL) != DLADM_STATUS_OK)
8048 8120 die("invalid link name '%s'", links[n]);
8049 8121 status = dladm_bridge_getlink(handle, linkids[n], bridge,
8050 8122 sizeof (bridge));
8051 8123 if (status != DLADM_STATUS_OK &&
8052 8124 status != DLADM_STATUS_NOTFOUND) {
8053 8125 die_dlerr(status, "cannot get bridge status on %s",
8054 8126 links[n]);
8055 8127 }
8056 8128 if (status == DLADM_STATUS_NOTFOUND ||
8057 8129 strcmp(bridge, argv[optind]) != 0)
8058 8130 die("link %s is not on bridge %s", links[n],
8059 8131 argv[optind]);
8060 8132 }
8061 8133
8062 8134 removed_one = B_FALSE;
8063 8135 for (n = 0; n < nlink; n++) {
8064 8136 status = dladm_bridge_setlink(handle, linkids[n], "");
8065 8137 if (status == DLADM_STATUS_OK) {
8066 8138 removed_one = B_TRUE;
8067 8139 } else {
8068 8140 warn_dlerr(status,
8069 8141 "cannot remove link %s from bridge %s",
8070 8142 links[n], argv[optind]);
8071 8143 }
8072 8144 }
8073 8145 if (!removed_one)
8074 8146 die("unable to remove any links from bridge %s", argv[optind]);
8075 8147 }
8076 8148
8077 8149 static void
8078 8150 fmt_int(char *buf, size_t buflen, int value, int runvalue,
8079 8151 boolean_t printstar)
8080 8152 {
8081 8153 (void) snprintf(buf, buflen, "%d", value);
8082 8154 if (value != runvalue && printstar)
8083 8155 (void) strlcat(buf, "*", buflen);
8084 8156 }
8085 8157
8086 8158 static void
8087 8159 fmt_bridge_id(char *buf, size_t buflen, UID_BRIDGE_ID_T *bid)
8088 8160 {
8089 8161 (void) snprintf(buf, buflen, "%u/%x:%x:%x:%x:%x:%x", bid->prio,
8090 8162 bid->addr[0], bid->addr[1], bid->addr[2], bid->addr[3],
8091 8163 bid->addr[4], bid->addr[5]);
8092 8164 }
8093 8165
8094 8166 static dladm_status_t
8095 8167 print_bridge(show_state_t *state, datalink_id_t linkid,
8096 8168 bridge_fields_buf_t *bbuf)
8097 8169 {
8098 8170 char link[MAXLINKNAMELEN];
8099 8171 datalink_class_t class;
8100 8172 uint32_t flags;
8101 8173 dladm_status_t status;
8102 8174 UID_STP_CFG_T smfcfg, runcfg;
8103 8175 UID_STP_STATE_T stpstate;
8104 8176 dladm_bridge_prot_t smfprot, runprot;
8105 8177
8106 8178 if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
8107 8179 NULL, link, sizeof (link))) != DLADM_STATUS_OK)
8108 8180 return (status);
8109 8181
8110 8182 if (!(state->ls_flags & flags))
8111 8183 return (DLADM_STATUS_NOTFOUND);
8112 8184
8113 8185 /* Convert observability node name back to bridge name */
8114 8186 if (!dladm_observe_to_bridge(link))
8115 8187 return (DLADM_STATUS_NOTFOUND);
8116 8188 (void) strlcpy(bbuf->bridge_name, link, sizeof (bbuf->bridge_name));
8117 8189
8118 8190 /*
8119 8191 * If the running value differs from the one in SMF, and parsable
8120 8192 * output is not requested, then we show the running value with an
8121 8193 * asterisk.
8122 8194 */
8123 8195 (void) dladm_bridge_get_properties(bbuf->bridge_name, &smfcfg,
8124 8196 &smfprot);
8125 8197 (void) dladm_bridge_run_properties(bbuf->bridge_name, &runcfg,
8126 8198 &runprot);
8127 8199 (void) snprintf(bbuf->bridge_protect, sizeof (bbuf->bridge_protect),
8128 8200 "%s%s", state->ls_parsable || smfprot == runprot ? "" : "*",
8129 8201 dladm_bridge_prot2str(runprot));
8130 8202 fmt_int(bbuf->bridge_priority, sizeof (bbuf->bridge_priority),
8131 8203 smfcfg.bridge_priority, runcfg.bridge_priority,
8132 8204 !state->ls_parsable && (runcfg.field_mask & BR_CFG_AGE));
8133 8205 fmt_int(bbuf->bridge_bmaxage, sizeof (bbuf->bridge_bmaxage),
8134 8206 smfcfg.max_age, runcfg.max_age,
8135 8207 !state->ls_parsable && (runcfg.field_mask & BR_CFG_AGE));
8136 8208 fmt_int(bbuf->bridge_bhellotime,
8137 8209 sizeof (bbuf->bridge_bhellotime), smfcfg.hello_time,
8138 8210 runcfg.hello_time,
8139 8211 !state->ls_parsable && (runcfg.field_mask & BR_CFG_HELLO));
8140 8212 fmt_int(bbuf->bridge_bfwddelay, sizeof (bbuf->bridge_bfwddelay),
8141 8213 smfcfg.forward_delay, runcfg.forward_delay,
8142 8214 !state->ls_parsable && (runcfg.field_mask & BR_CFG_DELAY));
8143 8215 fmt_int(bbuf->bridge_forceproto, sizeof (bbuf->bridge_forceproto),
8144 8216 smfcfg.force_version, runcfg.force_version,
8145 8217 !state->ls_parsable && (runcfg.field_mask & BR_CFG_FORCE_VER));
8146 8218 fmt_int(bbuf->bridge_holdtime, sizeof (bbuf->bridge_holdtime),
8147 8219 smfcfg.hold_time, runcfg.hold_time,
8148 8220 !state->ls_parsable && (runcfg.field_mask & BR_CFG_HOLD_TIME));
8149 8221
8150 8222 if (dladm_bridge_state(bbuf->bridge_name, &stpstate) ==
8151 8223 DLADM_STATUS_OK) {
8152 8224 fmt_bridge_id(bbuf->bridge_address,
8153 8225 sizeof (bbuf->bridge_address), &stpstate.bridge_id);
8154 8226 (void) snprintf(bbuf->bridge_tctime,
8155 8227 sizeof (bbuf->bridge_tctime), "%lu",
8156 8228 stpstate.timeSince_Topo_Change);
8157 8229 (void) snprintf(bbuf->bridge_tccount,
8158 8230 sizeof (bbuf->bridge_tccount), "%lu",
8159 8231 stpstate.Topo_Change_Count);
8160 8232 (void) snprintf(bbuf->bridge_tchange,
8161 8233 sizeof (bbuf->bridge_tchange), "%u", stpstate.Topo_Change);
8162 8234 fmt_bridge_id(bbuf->bridge_desroot,
8163 8235 sizeof (bbuf->bridge_desroot), &stpstate.designated_root);
8164 8236 (void) snprintf(bbuf->bridge_rootcost,
8165 8237 sizeof (bbuf->bridge_rootcost), "%lu",
8166 8238 stpstate.root_path_cost);
8167 8239 (void) snprintf(bbuf->bridge_rootport,
8168 8240 sizeof (bbuf->bridge_rootport), "%u", stpstate.root_port);
8169 8241 (void) snprintf(bbuf->bridge_maxage,
8170 8242 sizeof (bbuf->bridge_maxage), "%d", stpstate.max_age);
8171 8243 (void) snprintf(bbuf->bridge_hellotime,
8172 8244 sizeof (bbuf->bridge_hellotime), "%d", stpstate.hello_time);
8173 8245 (void) snprintf(bbuf->bridge_fwddelay,
8174 8246 sizeof (bbuf->bridge_fwddelay), "%d",
8175 8247 stpstate.forward_delay);
8176 8248 }
8177 8249 return (DLADM_STATUS_OK);
8178 8250 }
8179 8251
8180 8252 static dladm_status_t
8181 8253 print_bridge_stats(show_state_t *state, datalink_id_t linkid,
8182 8254 bridge_statfields_buf_t *bbuf)
8183 8255 {
8184 8256 char link[MAXLINKNAMELEN];
8185 8257 datalink_class_t class;
8186 8258 uint32_t flags;
8187 8259 dladm_status_t status;
8188 8260 kstat_ctl_t *kcp;
8189 8261 kstat_t *ksp;
8190 8262 brsum_t *brsum = (brsum_t *)&state->ls_prevstats;
8191 8263 brsum_t newval;
8192 8264
8193 8265 #ifndef lint
8194 8266 /* This is a compile-time assertion; optimizer normally fixes this */
8195 8267 extern void brsum_t_is_too_large(void);
8196 8268
8197 8269 if (sizeof (*brsum) > sizeof (state->ls_prevstats))
8198 8270 brsum_t_is_too_large();
8199 8271 #endif
8200 8272
8201 8273 if (state->ls_firstonly) {
8202 8274 if (state->ls_donefirst)
8203 8275 return (DLADM_WALK_CONTINUE);
8204 8276 state->ls_donefirst = B_TRUE;
8205 8277 } else {
8206 8278 bzero(brsum, sizeof (*brsum));
8207 8279 }
8208 8280 bzero(&newval, sizeof (newval));
8209 8281
8210 8282 if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
8211 8283 NULL, link, sizeof (link))) != DLADM_STATUS_OK)
8212 8284 return (status);
8213 8285
8214 8286 if (!(state->ls_flags & flags))
8215 8287 return (DLADM_STATUS_NOTFOUND);
8216 8288
8217 8289 if ((kcp = kstat_open()) == NULL) {
8218 8290 warn("kstat open operation failed");
8219 8291 return (DLADM_STATUS_OK);
8220 8292 }
8221 8293 if ((ksp = kstat_lookup(kcp, "bridge", 0, link)) != NULL &&
8222 8294 kstat_read(kcp, ksp, NULL) != -1) {
8223 8295 if (dladm_kstat_value(ksp, "drops", KSTAT_DATA_UINT64,
8224 8296 &newval.drops) == DLADM_STATUS_OK) {
8225 8297 (void) snprintf(bbuf->bridges_drops,
8226 8298 sizeof (bbuf->bridges_drops), "%llu",
8227 8299 newval.drops - brsum->drops);
8228 8300 }
8229 8301 if (dladm_kstat_value(ksp, "forward_direct", KSTAT_DATA_UINT64,
8230 8302 &newval.forward_dir) == DLADM_STATUS_OK) {
8231 8303 (void) snprintf(bbuf->bridges_forwards,
8232 8304 sizeof (bbuf->bridges_forwards), "%llu",
8233 8305 newval.forward_dir - brsum->forward_dir);
8234 8306 }
8235 8307 if (dladm_kstat_value(ksp, "forward_mbcast", KSTAT_DATA_UINT64,
8236 8308 &newval.forward_mb) == DLADM_STATUS_OK) {
8237 8309 (void) snprintf(bbuf->bridges_mbcast,
8238 8310 sizeof (bbuf->bridges_mbcast), "%llu",
8239 8311 newval.forward_mb - brsum->forward_mb);
8240 8312 }
8241 8313 if (dladm_kstat_value(ksp, "forward_unknown", KSTAT_DATA_UINT64,
8242 8314 &newval.forward_unk) == DLADM_STATUS_OK) {
8243 8315 (void) snprintf(bbuf->bridges_unknown,
8244 8316 sizeof (bbuf->bridges_unknown), "%llu",
8245 8317 newval.forward_unk - brsum->forward_unk);
8246 8318 }
8247 8319 if (dladm_kstat_value(ksp, "recv", KSTAT_DATA_UINT64,
8248 8320 &newval.recv) == DLADM_STATUS_OK) {
8249 8321 (void) snprintf(bbuf->bridges_recv,
8250 8322 sizeof (bbuf->bridges_recv), "%llu",
8251 8323 newval.recv - brsum->recv);
8252 8324 }
8253 8325 if (dladm_kstat_value(ksp, "sent", KSTAT_DATA_UINT64,
8254 8326 &newval.sent) == DLADM_STATUS_OK) {
8255 8327 (void) snprintf(bbuf->bridges_sent,
8256 8328 sizeof (bbuf->bridges_sent), "%llu",
8257 8329 newval.sent - brsum->sent);
8258 8330 }
8259 8331 }
8260 8332 (void) kstat_close(kcp);
8261 8333
8262 8334 /* Convert observability node name back to bridge name */
8263 8335 if (!dladm_observe_to_bridge(link))
8264 8336 return (DLADM_STATUS_NOTFOUND);
8265 8337 (void) strlcpy(bbuf->bridges_name, link, sizeof (bbuf->bridges_name));
8266 8338
8267 8339 *brsum = newval;
8268 8340
8269 8341 return (DLADM_STATUS_OK);
8270 8342 }
8271 8343
8272 8344 /*
8273 8345 * This structure carries around extra state information for the show-bridge
8274 8346 * command and allows us to use common support functions.
8275 8347 */
8276 8348 typedef struct {
8277 8349 show_state_t state;
8278 8350 boolean_t show_stats;
8279 8351 const char *bridge;
8280 8352 } show_brstate_t;
8281 8353
8282 8354 /* ARGSUSED */
8283 8355 static int
8284 8356 show_bridge(dladm_handle_t handle, datalink_id_t linkid, void *arg)
8285 8357 {
8286 8358 show_brstate_t *brstate = arg;
8287 8359 void *buf;
8288 8360
8289 8361 if (brstate->show_stats) {
8290 8362 bridge_statfields_buf_t bbuf;
8291 8363
8292 8364 bzero(&bbuf, sizeof (bbuf));
8293 8365 brstate->state.ls_status = print_bridge_stats(&brstate->state,
8294 8366 linkid, &bbuf);
8295 8367 buf = &bbuf;
8296 8368 } else {
8297 8369 bridge_fields_buf_t bbuf;
8298 8370
8299 8371 bzero(&bbuf, sizeof (bbuf));
8300 8372 brstate->state.ls_status = print_bridge(&brstate->state, linkid,
8301 8373 &bbuf);
8302 8374 buf = &bbuf;
8303 8375 }
8304 8376 if (brstate->state.ls_status == DLADM_STATUS_OK)
8305 8377 ofmt_print(brstate->state.ls_ofmt, buf);
8306 8378 return (DLADM_WALK_CONTINUE);
8307 8379 }
8308 8380
8309 8381 static void
8310 8382 fmt_bool(char *buf, size_t buflen, int val)
8311 8383 {
8312 8384 (void) strlcpy(buf, val ? "yes" : "no", buflen);
8313 8385 }
8314 8386
8315 8387 static dladm_status_t
8316 8388 print_bridge_link(show_state_t *state, datalink_id_t linkid,
8317 8389 bridge_link_fields_buf_t *bbuf)
8318 8390 {
8319 8391 datalink_class_t class;
8320 8392 uint32_t flags;
8321 8393 dladm_status_t status;
8322 8394 UID_STP_PORT_STATE_T stpstate;
8323 8395
8324 8396 status = dladm_datalink_id2info(handle, linkid, &flags, &class, NULL,
8325 8397 bbuf->bridgel_link, sizeof (bbuf->bridgel_link));
8326 8398 if (status != DLADM_STATUS_OK)
8327 8399 return (status);
8328 8400
8329 8401 if (!(state->ls_flags & flags))
8330 8402 return (DLADM_STATUS_NOTFOUND);
8331 8403
8332 8404 if (dladm_bridge_link_state(handle, linkid, &stpstate) ==
8333 8405 DLADM_STATUS_OK) {
8334 8406 (void) snprintf(bbuf->bridgel_index,
8335 8407 sizeof (bbuf->bridgel_index), "%u", stpstate.port_no);
8336 8408 if (dlsym(RTLD_PROBE, "STP_IN_state2str")) {
8337 8409 (void) strlcpy(bbuf->bridgel_state,
8338 8410 STP_IN_state2str(stpstate.state),
8339 8411 sizeof (bbuf->bridgel_state));
8340 8412 } else {
8341 8413 (void) snprintf(bbuf->bridgel_state,
8342 8414 sizeof (bbuf->bridgel_state), "%u",
8343 8415 stpstate.state);
8344 8416 }
8345 8417 (void) snprintf(bbuf->bridgel_uptime,
8346 8418 sizeof (bbuf->bridgel_uptime), "%lu", stpstate.uptime);
8347 8419 (void) snprintf(bbuf->bridgel_opercost,
8348 8420 sizeof (bbuf->bridgel_opercost), "%lu",
8349 8421 stpstate.oper_port_path_cost);
8350 8422 fmt_bool(bbuf->bridgel_operp2p, sizeof (bbuf->bridgel_operp2p),
8351 8423 stpstate.oper_point2point);
8352 8424 fmt_bool(bbuf->bridgel_operedge,
8353 8425 sizeof (bbuf->bridgel_operedge), stpstate.oper_edge);
8354 8426 fmt_bridge_id(bbuf->bridgel_desroot,
8355 8427 sizeof (bbuf->bridgel_desroot), &stpstate.designated_root);
8356 8428 (void) snprintf(bbuf->bridgel_descost,
8357 8429 sizeof (bbuf->bridgel_descost), "%lu",
8358 8430 stpstate.designated_cost);
8359 8431 fmt_bridge_id(bbuf->bridgel_desbridge,
8360 8432 sizeof (bbuf->bridgel_desbridge),
8361 8433 &stpstate.designated_bridge);
8362 8434 (void) snprintf(bbuf->bridgel_desport,
8363 8435 sizeof (bbuf->bridgel_desport), "%u",
8364 8436 stpstate.designated_port);
8365 8437 fmt_bool(bbuf->bridgel_tcack, sizeof (bbuf->bridgel_tcack),
8366 8438 stpstate.top_change_ack);
8367 8439 }
8368 8440 return (DLADM_STATUS_OK);
8369 8441 }
8370 8442
8371 8443 static dladm_status_t
8372 8444 print_bridge_link_stats(show_state_t *state, datalink_id_t linkid,
8373 8445 bridge_link_statfields_buf_t *bbuf)
8374 8446 {
8375 8447 datalink_class_t class;
8376 8448 uint32_t flags;
8377 8449 dladm_status_t status;
8378 8450 UID_STP_PORT_STATE_T stpstate;
8379 8451 kstat_ctl_t *kcp;
8380 8452 kstat_t *ksp;
8381 8453 char bridge[MAXLINKNAMELEN];
8382 8454 char kstatname[MAXLINKNAMELEN*2 + 1];
8383 8455 brlsum_t *brlsum = (brlsum_t *)&state->ls_prevstats;
8384 8456 brlsum_t newval;
8385 8457
8386 8458 #ifndef lint
8387 8459 /* This is a compile-time assertion; optimizer normally fixes this */
8388 8460 extern void brlsum_t_is_too_large(void);
8389 8461
8390 8462 if (sizeof (*brlsum) > sizeof (state->ls_prevstats))
8391 8463 brlsum_t_is_too_large();
8392 8464 #endif
8393 8465
8394 8466 if (state->ls_firstonly) {
8395 8467 if (state->ls_donefirst)
8396 8468 return (DLADM_WALK_CONTINUE);
8397 8469 state->ls_donefirst = B_TRUE;
8398 8470 } else {
8399 8471 bzero(brlsum, sizeof (*brlsum));
8400 8472 }
8401 8473 bzero(&newval, sizeof (newval));
8402 8474
8403 8475 status = dladm_datalink_id2info(handle, linkid, &flags, &class, NULL,
8404 8476 bbuf->bridgels_link, sizeof (bbuf->bridgels_link));
8405 8477 if (status != DLADM_STATUS_OK)
8406 8478 return (status);
8407 8479
8408 8480 if (!(state->ls_flags & flags))
8409 8481 return (DLADM_STATUS_NOTFOUND);
8410 8482
8411 8483 if (dladm_bridge_link_state(handle, linkid, &stpstate) ==
8412 8484 DLADM_STATUS_OK) {
8413 8485 newval.cfgbpdu = stpstate.rx_cfg_bpdu_cnt;
8414 8486 newval.tcnbpdu = stpstate.rx_tcn_bpdu_cnt;
8415 8487 newval.rstpbpdu = stpstate.rx_rstp_bpdu_cnt;
8416 8488 newval.txbpdu = stpstate.txCount;
8417 8489
8418 8490 (void) snprintf(bbuf->bridgels_cfgbpdu,
8419 8491 sizeof (bbuf->bridgels_cfgbpdu), "%lu",
8420 8492 newval.cfgbpdu - brlsum->cfgbpdu);
8421 8493 (void) snprintf(bbuf->bridgels_tcnbpdu,
8422 8494 sizeof (bbuf->bridgels_tcnbpdu), "%lu",
8423 8495 newval.tcnbpdu - brlsum->tcnbpdu);
8424 8496 (void) snprintf(bbuf->bridgels_rstpbpdu,
8425 8497 sizeof (bbuf->bridgels_rstpbpdu), "%lu",
8426 8498 newval.rstpbpdu - brlsum->rstpbpdu);
8427 8499 (void) snprintf(bbuf->bridgels_txbpdu,
8428 8500 sizeof (bbuf->bridgels_txbpdu), "%lu",
8429 8501 newval.txbpdu - brlsum->txbpdu);
8430 8502 }
8431 8503
8432 8504 if ((status = dladm_bridge_getlink(handle, linkid, bridge,
8433 8505 sizeof (bridge))) != DLADM_STATUS_OK)
8434 8506 goto bls_out;
8435 8507 (void) snprintf(kstatname, sizeof (kstatname), "%s0-%s", bridge,
8436 8508 bbuf->bridgels_link);
8437 8509 if ((kcp = kstat_open()) == NULL) {
8438 8510 warn("kstat open operation failed");
8439 8511 goto bls_out;
8440 8512 }
8441 8513 if ((ksp = kstat_lookup(kcp, "bridge", 0, kstatname)) != NULL &&
8442 8514 kstat_read(kcp, ksp, NULL) != -1) {
8443 8515 if (dladm_kstat_value(ksp, "drops", KSTAT_DATA_UINT64,
8444 8516 &newval.drops) != -1) {
8445 8517 (void) snprintf(bbuf->bridgels_drops,
8446 8518 sizeof (bbuf->bridgels_drops), "%llu",
8447 8519 newval.drops - brlsum->drops);
8448 8520 }
8449 8521 if (dladm_kstat_value(ksp, "recv", KSTAT_DATA_UINT64,
8450 8522 &newval.recv) != -1) {
8451 8523 (void) snprintf(bbuf->bridgels_recv,
8452 8524 sizeof (bbuf->bridgels_recv), "%llu",
8453 8525 newval.recv - brlsum->recv);
8454 8526 }
8455 8527 if (dladm_kstat_value(ksp, "xmit", KSTAT_DATA_UINT64,
8456 8528 &newval.xmit) != -1) {
8457 8529 (void) snprintf(bbuf->bridgels_xmit,
8458 8530 sizeof (bbuf->bridgels_xmit), "%llu",
8459 8531 newval.xmit - brlsum->xmit);
8460 8532 }
8461 8533 }
8462 8534 (void) kstat_close(kcp);
8463 8535 bls_out:
8464 8536 *brlsum = newval;
8465 8537
8466 8538 return (status);
8467 8539 }
8468 8540
8469 8541 static void
8470 8542 show_bridge_link(datalink_id_t linkid, show_brstate_t *brstate)
8471 8543 {
8472 8544 void *buf;
8473 8545
8474 8546 if (brstate->show_stats) {
8475 8547 bridge_link_statfields_buf_t bbuf;
8476 8548
8477 8549 bzero(&bbuf, sizeof (bbuf));
8478 8550 brstate->state.ls_status = print_bridge_link_stats(
8479 8551 &brstate->state, linkid, &bbuf);
8480 8552 buf = &bbuf;
8481 8553 } else {
8482 8554 bridge_link_fields_buf_t bbuf;
8483 8555
8484 8556 bzero(&bbuf, sizeof (bbuf));
8485 8557 brstate->state.ls_status = print_bridge_link(&brstate->state,
8486 8558 linkid, &bbuf);
8487 8559 buf = &bbuf;
8488 8560 }
8489 8561 if (brstate->state.ls_status == DLADM_STATUS_OK)
8490 8562 ofmt_print(brstate->state.ls_ofmt, buf);
8491 8563 }
8492 8564
8493 8565 /* ARGSUSED */
8494 8566 static int
8495 8567 show_bridge_link_walk(dladm_handle_t handle, datalink_id_t linkid, void *arg)
8496 8568 {
8497 8569 show_brstate_t *brstate = arg;
8498 8570 char bridge[MAXLINKNAMELEN];
8499 8571
8500 8572 if (dladm_bridge_getlink(handle, linkid, bridge, sizeof (bridge)) ==
8501 8573 DLADM_STATUS_OK && strcmp(bridge, brstate->bridge) == 0) {
8502 8574 show_bridge_link(linkid, brstate);
8503 8575 }
8504 8576 return (DLADM_WALK_CONTINUE);
8505 8577 }
8506 8578
8507 8579 static void
8508 8580 show_bridge_fwd(dladm_handle_t handle, bridge_listfwd_t *blf,
8509 8581 show_state_t *state)
8510 8582 {
8511 8583 bridge_fwd_fields_buf_t bbuf;
8512 8584
8513 8585 bzero(&bbuf, sizeof (bbuf));
8514 8586 (void) snprintf(bbuf.bridgef_dest, sizeof (bbuf.bridgef_dest),
8515 8587 "%s", ether_ntoa((struct ether_addr *)blf->blf_dest));
8516 8588 if (blf->blf_is_local) {
8517 8589 (void) strlcpy(bbuf.bridgef_flags, "L",
8518 8590 sizeof (bbuf.bridgef_flags));
8519 8591 } else {
8520 8592 (void) snprintf(bbuf.bridgef_age, sizeof (bbuf.bridgef_age),
8521 8593 "%2d.%03d", blf->blf_ms_age / 1000, blf->blf_ms_age % 1000);
8522 8594 if (blf->blf_trill_nick != 0) {
8523 8595 (void) snprintf(bbuf.bridgef_output,
8524 8596 sizeof (bbuf.bridgef_output), "%u",
8525 8597 blf->blf_trill_nick);
8526 8598 }
8527 8599 }
8528 8600 if (blf->blf_linkid != DATALINK_INVALID_LINKID &&
8529 8601 blf->blf_trill_nick == 0) {
8530 8602 state->ls_status = dladm_datalink_id2info(handle,
8531 8603 blf->blf_linkid, NULL, NULL, NULL, bbuf.bridgef_output,
8532 8604 sizeof (bbuf.bridgef_output));
8533 8605 }
8534 8606 if (state->ls_status == DLADM_STATUS_OK)
8535 8607 ofmt_print(state->ls_ofmt, &bbuf);
8536 8608 }
8537 8609
8538 8610 static void
8539 8611 show_bridge_trillnick(trill_listnick_t *tln, show_state_t *state)
8540 8612 {
8541 8613 bridge_trill_fields_buf_t bbuf;
8542 8614
8543 8615 bzero(&bbuf, sizeof (bbuf));
8544 8616 (void) snprintf(bbuf.bridget_nick, sizeof (bbuf.bridget_nick),
8545 8617 "%u", tln->tln_nick);
8546 8618 if (tln->tln_ours) {
8547 8619 (void) strlcpy(bbuf.bridget_flags, "L",
8548 8620 sizeof (bbuf.bridget_flags));
8549 8621 } else {
8550 8622 state->ls_status = dladm_datalink_id2info(handle,
8551 8623 tln->tln_linkid, NULL, NULL, NULL, bbuf.bridget_link,
8552 8624 sizeof (bbuf.bridget_link));
8553 8625 (void) snprintf(bbuf.bridget_nexthop,
8554 8626 sizeof (bbuf.bridget_nexthop), "%s",
8555 8627 ether_ntoa((struct ether_addr *)tln->tln_nexthop));
8556 8628 }
8557 8629 if (state->ls_status == DLADM_STATUS_OK)
8558 8630 ofmt_print(state->ls_ofmt, &bbuf);
8559 8631 }
8560 8632
8561 8633 static void
8562 8634 do_show_bridge(int argc, char **argv, const char *use)
8563 8635 {
8564 8636 int option;
8565 8637 enum {
8566 8638 bridgeMode, linkMode, fwdMode, trillMode
8567 8639 } op_mode = bridgeMode;
8568 8640 uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
8569 8641 boolean_t parsable = B_FALSE;
8570 8642 datalink_id_t linkid = DATALINK_ALL_LINKID;
8571 8643 int interval = 0;
8572 8644 show_brstate_t brstate;
8573 8645 dladm_status_t status;
8574 8646 char *fields_str = NULL;
8575 8647 /* default: bridge-related data */
8576 8648 char *all_fields = "bridge,protect,address,priority,bmaxage,"
8577 8649 "bhellotime,bfwddelay,forceproto,tctime,tccount,tchange,"
8578 8650 "desroot,rootcost,rootport,maxage,hellotime,fwddelay,holdtime";
8579 8651 char *default_fields = "bridge,protect,address,priority,"
8580 8652 "desroot";
8581 8653 char *all_statfields = "bridge,drops,forwards,mbcast,"
8582 8654 "unknown,recv,sent";
8583 8655 char *default_statfields = "bridge,drops,forwards,mbcast,"
8584 8656 "unknown";
8585 8657 /* -l: link-related data */
8586 8658 char *all_link_fields = "link,index,state,uptime,opercost,"
8587 8659 "operp2p,operedge,desroot,descost,desbridge,desport,tcack";
8588 8660 char *default_link_fields = "link,state,uptime,desroot";
8589 8661 char *all_link_statfields = "link,cfgbpdu,tcnbpdu,rstpbpdu,"
8590 8662 "txbpdu,drops,recv,xmit";
8591 8663 char *default_link_statfields = "link,drops,recv,xmit";
8592 8664 /* -f: bridge forwarding table related data */
8593 8665 char *default_fwd_fields = "dest,age,flags,output";
8594 8666 /* -t: TRILL nickname table related data */
8595 8667 char *default_trill_fields = "nick,flags,link,nexthop";
8596 8668 char *default_str;
8597 8669 char *all_str;
8598 8670 ofmt_field_t *field_arr;
8599 8671 ofmt_handle_t ofmt;
8600 8672 ofmt_status_t oferr;
8601 8673 uint_t ofmtflags = 0;
8602 8674
8603 8675 bzero(&brstate, sizeof (brstate));
8604 8676
8605 8677 opterr = 0;
8606 8678 while ((option = getopt_long(argc, argv, ":fi:lo:pst",
8607 8679 bridge_show_lopts, NULL)) != -1) {
8608 8680 switch (option) {
8609 8681 case 'f':
8610 8682 if (op_mode != bridgeMode && op_mode != fwdMode)
8611 8683 die("-f is incompatible with -l or -t");
8612 8684 op_mode = fwdMode;
8613 8685 break;
8614 8686 case 'i':
8615 8687 if (interval != 0)
8616 8688 die_optdup(option);
8617 8689 if (!str2int(optarg, &interval) || interval == 0)
8618 8690 die("invalid interval value '%s'", optarg);
8619 8691 break;
8620 8692 case 'l':
8621 8693 if (op_mode != bridgeMode && op_mode != linkMode)
8622 8694 die("-l is incompatible with -f or -t");
8623 8695 op_mode = linkMode;
8624 8696 break;
8625 8697 case 'o':
8626 8698 fields_str = optarg;
8627 8699 break;
8628 8700 case 'p':
8629 8701 if (parsable)
8630 8702 die_optdup(option);
8631 8703 parsable = B_TRUE;
8632 8704 break;
8633 8705 case 's':
8634 8706 if (brstate.show_stats)
8635 8707 die_optdup(option);
8636 8708 brstate.show_stats = B_TRUE;
8637 8709 break;
8638 8710 case 't':
8639 8711 if (op_mode != bridgeMode && op_mode != trillMode)
8640 8712 die("-t is incompatible with -f or -l");
8641 8713 op_mode = trillMode;
8642 8714 break;
8643 8715 default:
8644 8716 die_opterr(optopt, option, use);
8645 8717 break;
8646 8718 }
8647 8719 }
8648 8720
8649 8721 if (interval != 0 && !brstate.show_stats)
8650 8722 die("the -i option can be used only with -s");
8651 8723
8652 8724 if ((op_mode == fwdMode || op_mode == trillMode) && brstate.show_stats)
8653 8725 die("the -f/-t and -s options cannot be used together");
8654 8726
8655 8727 /* get the bridge name (optional last argument) */
8656 8728 if (optind == (argc-1)) {
8657 8729 char lname[MAXLINKNAMELEN];
8658 8730 uint32_t lnkflg;
8659 8731 datalink_class_t class;
8660 8732
8661 8733 brstate.bridge = argv[optind];
8662 8734 (void) snprintf(lname, sizeof (lname), "%s0", brstate.bridge);
8663 8735 if ((status = dladm_name2info(handle, lname, &linkid, &lnkflg,
8664 8736 &class, NULL)) != DLADM_STATUS_OK) {
8665 8737 die_dlerr(status, "bridge %s is not valid",
8666 8738 brstate.bridge);
8667 8739 }
8668 8740
8669 8741 if (class != DATALINK_CLASS_BRIDGE)
8670 8742 die("%s is not a bridge", brstate.bridge);
8671 8743
8672 8744 if (!(lnkflg & flags)) {
8673 8745 die_dlerr(DLADM_STATUS_BADARG,
8674 8746 "bridge %s is temporarily removed", brstate.bridge);
8675 8747 }
8676 8748 } else if (optind != argc) {
8677 8749 usage();
8678 8750 } else if (op_mode != bridgeMode) {
8679 8751 die("bridge name required for -l, -f, or -t");
8680 8752 return;
8681 8753 }
8682 8754
8683 8755 brstate.state.ls_parsable = parsable;
8684 8756 brstate.state.ls_flags = flags;
8685 8757 brstate.state.ls_firstonly = (interval != 0);
8686 8758
8687 8759 switch (op_mode) {
8688 8760 case bridgeMode:
8689 8761 if (brstate.show_stats) {
8690 8762 default_str = default_statfields;
8691 8763 all_str = all_statfields;
8692 8764 field_arr = bridge_statfields;
8693 8765 } else {
8694 8766 default_str = default_fields;
8695 8767 all_str = all_fields;
8696 8768 field_arr = bridge_fields;
8697 8769 }
8698 8770 break;
8699 8771
8700 8772 case linkMode:
8701 8773 if (brstate.show_stats) {
8702 8774 default_str = default_link_statfields;
8703 8775 all_str = all_link_statfields;
8704 8776 field_arr = bridge_link_statfields;
8705 8777 } else {
8706 8778 default_str = default_link_fields;
8707 8779 all_str = all_link_fields;
8708 8780 field_arr = bridge_link_fields;
8709 8781 }
8710 8782 break;
8711 8783
8712 8784 case fwdMode:
8713 8785 default_str = all_str = default_fwd_fields;
8714 8786 field_arr = bridge_fwd_fields;
8715 8787 break;
8716 8788
8717 8789 case trillMode:
8718 8790 default_str = all_str = default_trill_fields;
8719 8791 field_arr = bridge_trill_fields;
8720 8792 break;
8721 8793 }
8722 8794
8723 8795 if (fields_str == NULL)
8724 8796 fields_str = default_str;
8725 8797 else if (strcasecmp(fields_str, "all") == 0)
8726 8798 fields_str = all_str;
8727 8799
8728 8800 if (parsable)
8729 8801 ofmtflags |= OFMT_PARSABLE;
8730 8802 oferr = ofmt_open(fields_str, field_arr, ofmtflags, 0, &ofmt);
8731 8803 dladm_ofmt_check(oferr, brstate.state.ls_parsable, ofmt);
8732 8804 brstate.state.ls_ofmt = ofmt;
8733 8805
8734 8806 for (;;) {
8735 8807 brstate.state.ls_donefirst = B_FALSE;
8736 8808 switch (op_mode) {
8737 8809 case bridgeMode:
8738 8810 if (linkid == DATALINK_ALL_LINKID) {
8739 8811 (void) dladm_walk_datalink_id(show_bridge,
8740 8812 handle, &brstate, DATALINK_CLASS_BRIDGE,
8741 8813 DATALINK_ANY_MEDIATYPE, flags);
8742 8814 } else {
8743 8815 (void) show_bridge(handle, linkid, &brstate);
8744 8816 if (brstate.state.ls_status !=
8745 8817 DLADM_STATUS_OK) {
8746 8818 die_dlerr(brstate.state.ls_status,
8747 8819 "failed to show bridge %s",
8748 8820 brstate.bridge);
8749 8821 }
8750 8822 }
8751 8823 break;
8752 8824
8753 8825 case linkMode: {
8754 8826 datalink_id_t *dlp;
8755 8827 uint_t i, nlinks;
8756 8828
8757 8829 dlp = dladm_bridge_get_portlist(brstate.bridge,
8758 8830 &nlinks);
8759 8831 if (dlp != NULL) {
8760 8832 for (i = 0; i < nlinks; i++)
8761 8833 show_bridge_link(dlp[i], &brstate);
8762 8834 dladm_bridge_free_portlist(dlp);
8763 8835 } else if (errno == ENOENT) {
8764 8836 /* bridge not running; iterate on libdladm */
8765 8837 (void) dladm_walk_datalink_id(
8766 8838 show_bridge_link_walk, handle,
8767 8839 &brstate, DATALINK_CLASS_PHYS |
8768 8840 DATALINK_CLASS_AGGR |
8769 8841 DATALINK_CLASS_ETHERSTUB,
8770 8842 DATALINK_ANY_MEDIATYPE, flags);
8771 8843 } else {
8772 8844 die("unable to get port list for bridge %s: %s",
8773 8845 brstate.bridge, strerror(errno));
8774 8846 }
8775 8847 break;
8776 8848 }
8777 8849
8778 8850 case fwdMode: {
8779 8851 bridge_listfwd_t *blf;
8780 8852 uint_t i, nfwd;
8781 8853
8782 8854 blf = dladm_bridge_get_fwdtable(handle, brstate.bridge,
8783 8855 &nfwd);
8784 8856 if (blf == NULL) {
8785 8857 die("unable to get forwarding entries for "
8786 8858 "bridge %s", brstate.bridge);
8787 8859 } else {
8788 8860 for (i = 0; i < nfwd; i++)
8789 8861 show_bridge_fwd(handle, blf + i,
8790 8862 &brstate.state);
8791 8863 dladm_bridge_free_fwdtable(blf);
8792 8864 }
8793 8865 break;
8794 8866 }
8795 8867
8796 8868 case trillMode: {
8797 8869 trill_listnick_t *tln;
8798 8870 uint_t i, nnick;
8799 8871
8800 8872 tln = dladm_bridge_get_trillnick(brstate.bridge,
8801 8873 &nnick);
8802 8874 if (tln == NULL) {
8803 8875 if (errno == ENOENT)
8804 8876 die("bridge %s is not running TRILL",
8805 8877 brstate.bridge);
8806 8878 else
8807 8879 die("unable to get TRILL nickname "
8808 8880 "entries for bridge %s",
8809 8881 brstate.bridge);
8810 8882 } else {
8811 8883 for (i = 0; i < nnick; i++)
8812 8884 show_bridge_trillnick(tln + i,
8813 8885 &brstate.state);
8814 8886 dladm_bridge_free_trillnick(tln);
8815 8887 }
8816 8888 break;
8817 8889 }
8818 8890 }
8819 8891 if (interval == 0)
8820 8892 break;
8821 8893 (void) sleep(interval);
8822 8894 }
8823 8895 }
8824 8896
8825 8897 /*
8826 8898 * "-R" option support. It is used for live upgrading. Append dladm commands
8827 8899 * to a upgrade script which will be run when the alternative root boots up:
8828 8900 *
8829 8901 * - If the /etc/dladm/datalink.conf file exists on the alternative root,
8830 8902 * append dladm commands to the <altroot>/var/svc/profile/upgrade_datalink
8831 8903 * script. This script will be run as part of the network/physical service.
8832 8904 * We cannot defer this to /var/svc/profile/upgrade because then the
8833 8905 * configuration will not be able to take effect before network/physical
8834 8906 * plumbs various interfaces.
8835 8907 *
8836 8908 * - If the /etc/dladm/datalink.conf file does not exist on the alternative
8837 8909 * root, append dladm commands to the <altroot>/var/svc/profile/upgrade script,
8838 8910 * which will be run in the manifest-import service.
8839 8911 *
8840 8912 * Note that the SMF team is considering to move the manifest-import service
8841 8913 * to be run at the very begining of boot. Once that is done, the need for
8842 8914 * the /var/svc/profile/upgrade_datalink script will not exist any more.
8843 8915 */
8844 8916 static void
8845 8917 altroot_cmd(char *altroot, int argc, char *argv[])
8846 8918 {
8847 8919 char path[MAXPATHLEN];
8848 8920 struct stat stbuf;
8849 8921 FILE *fp;
8850 8922 int i;
8851 8923
8852 8924 /*
8853 8925 * Check for the existence of the /etc/dladm/datalink.conf
8854 8926 * configuration file, and determine the name of script file.
8855 8927 */
8856 8928 (void) snprintf(path, MAXPATHLEN, "/%s/etc/dladm/datalink.conf",
8857 8929 altroot);
8858 8930 if (stat(path, &stbuf) < 0) {
8859 8931 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot,
8860 8932 SMF_UPGRADE_FILE);
8861 8933 } else {
8862 8934 (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot,
8863 8935 SMF_UPGRADEDATALINK_FILE);
8864 8936 }
8865 8937
8866 8938 if ((fp = fopen(path, "a+")) == NULL)
8867 8939 die("operation not supported on %s", altroot);
8868 8940
8869 8941 (void) fprintf(fp, "/sbin/dladm ");
8870 8942 for (i = 0; i < argc; i++) {
8871 8943 /*
8872 8944 * Directly write to the file if it is not the "-R <altroot>"
8873 8945 * option. In which case, skip it.
8874 8946 */
8875 8947 if (strcmp(argv[i], "-R") != 0)
8876 8948 (void) fprintf(fp, "%s ", argv[i]);
8877 8949 else
8878 8950 i ++;
8879 8951 }
8880 8952 (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG);
8881 8953 (void) fclose(fp);
8882 8954 dladm_close(handle);
8883 8955 exit(EXIT_SUCCESS);
8884 8956 }
8885 8957
8886 8958 /*
8887 8959 * Convert the string to an integer. Note that the string must not have any
8888 8960 * trailing non-integer characters.
8889 8961 */
8890 8962 static boolean_t
8891 8963 str2int(const char *str, int *valp)
8892 8964 {
8893 8965 int val;
8894 8966 char *endp = NULL;
8895 8967
8896 8968 errno = 0;
8897 8969 val = strtol(str, &endp, 10);
8898 8970 if (errno != 0 || *endp != '\0')
8899 8971 return (B_FALSE);
8900 8972
8901 8973 *valp = val;
8902 8974 return (B_TRUE);
8903 8975 }
8904 8976
8905 8977 /* PRINTFLIKE1 */
8906 8978 static void
8907 8979 warn(const char *format, ...)
8908 8980 {
8909 8981 va_list alist;
8910 8982
8911 8983 format = gettext(format);
8912 8984 (void) fprintf(stderr, "%s: warning: ", progname);
8913 8985
8914 8986 va_start(alist, format);
8915 8987 (void) vfprintf(stderr, format, alist);
8916 8988 va_end(alist);
8917 8989
8918 8990 (void) putc('\n', stderr);
8919 8991 }
8920 8992
8921 8993 /* PRINTFLIKE2 */
8922 8994 static void
8923 8995 warn_dlerr(dladm_status_t err, const char *format, ...)
8924 8996 {
8925 8997 va_list alist;
8926 8998 char errmsg[DLADM_STRSIZE];
8927 8999
8928 9000 format = gettext(format);
8929 9001 (void) fprintf(stderr, gettext("%s: warning: "), progname);
8930 9002
8931 9003 va_start(alist, format);
8932 9004 (void) vfprintf(stderr, format, alist);
8933 9005 va_end(alist);
8934 9006 (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
8935 9007 }
8936 9008
8937 9009 /*
8938 9010 * Also closes the dladm handle if it is not NULL.
8939 9011 */
8940 9012 /* PRINTFLIKE2 */
8941 9013 static void
8942 9014 die_dlerr(dladm_status_t err, const char *format, ...)
8943 9015 {
8944 9016 va_list alist;
8945 9017 char errmsg[DLADM_STRSIZE];
8946 9018
8947 9019 format = gettext(format);
8948 9020 (void) fprintf(stderr, "%s: ", progname);
8949 9021
8950 9022 va_start(alist, format);
8951 9023 (void) vfprintf(stderr, format, alist);
8952 9024 va_end(alist);
8953 9025 (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
8954 9026
8955 9027 /* close dladm handle if it was opened */
8956 9028 if (handle != NULL)
8957 9029 dladm_close(handle);
8958 9030
8959 9031 exit(EXIT_FAILURE);
8960 9032 }
8961 9033
8962 9034 /* PRINTFLIKE1 */
8963 9035 static void
8964 9036 die(const char *format, ...)
8965 9037 {
8966 9038 va_list alist;
8967 9039
8968 9040 format = gettext(format);
8969 9041 (void) fprintf(stderr, "%s: ", progname);
8970 9042
8971 9043 va_start(alist, format);
8972 9044 (void) vfprintf(stderr, format, alist);
8973 9045 va_end(alist);
8974 9046
8975 9047 (void) putc('\n', stderr);
8976 9048
8977 9049 /* close dladm handle if it was opened */
8978 9050 if (handle != NULL)
8979 9051 dladm_close(handle);
8980 9052
8981 9053 exit(EXIT_FAILURE);
8982 9054 }
8983 9055
8984 9056 static void
8985 9057 die_optdup(int opt)
8986 9058 {
8987 9059 die("the option -%c cannot be specified more than once", opt);
8988 9060 }
8989 9061
8990 9062 static void
8991 9063 die_opterr(int opt, int opterr, const char *usage)
8992 9064 {
8993 9065 switch (opterr) {
8994 9066 case ':':
8995 9067 die("option '-%c' requires a value\nusage: %s", opt,
8996 9068 gettext(usage));
8997 9069 break;
8998 9070 case '?':
8999 9071 default:
9000 9072 die("unrecognized option '-%c'\nusage: %s", opt,
9001 9073 gettext(usage));
9002 9074 break;
9003 9075 }
9004 9076 }
9005 9077
9006 9078 static void
9007 9079 show_ether_xprop(void *arg, dladm_ether_info_t *eattr)
9008 9080 {
9009 9081 print_ether_state_t *statep = arg;
9010 9082 ether_fields_buf_t ebuf;
9011 9083 int i;
9012 9084
9013 9085 for (i = CAPABLE; i <= PEERADV; i++) {
9014 9086 bzero(&ebuf, sizeof (ebuf));
9015 9087 (void) strlcpy(ebuf.eth_ptype, ptype[i],
9016 9088 sizeof (ebuf.eth_ptype));
9017 9089 (void) dladm_ether_autoneg2str(ebuf.eth_autoneg,
9018 9090 sizeof (ebuf.eth_autoneg), eattr, i);
9019 9091 (void) dladm_ether_spdx2str(ebuf.eth_spdx,
9020 9092 sizeof (ebuf.eth_spdx), eattr, i);
9021 9093 (void) dladm_ether_pause2str(ebuf.eth_pause,
9022 9094 sizeof (ebuf.eth_pause), eattr, i);
9023 9095 (void) strlcpy(ebuf.eth_rem_fault,
9024 9096 (eattr->lei_attr[i].le_fault ? "fault" : "none"),
9025 9097 sizeof (ebuf.eth_rem_fault));
9026 9098 ofmt_print(statep->es_ofmt, &ebuf);
9027 9099 }
9028 9100
9029 9101 }
9030 9102
9031 9103 static boolean_t
9032 9104 link_is_ether(const char *link, datalink_id_t *linkid)
9033 9105 {
9034 9106 uint32_t media;
9035 9107 datalink_class_t class;
9036 9108
9037 9109 if (dladm_name2info(handle, link, linkid, NULL, &class, &media) ==
9038 9110 DLADM_STATUS_OK) {
9039 9111 if (class == DATALINK_CLASS_PHYS && media == DL_ETHER)
9040 9112 return (B_TRUE);
9041 9113 }
9042 9114 return (B_FALSE);
9043 9115 }
9044 9116
9045 9117 /*
9046 9118 * default output callback function that, when invoked,
9047 9119 * prints string which is offset by ofmt_arg->ofmt_id within buf.
9048 9120 */
9049 9121 static boolean_t
9050 9122 print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
9051 9123 {
9052 9124 char *value;
9053 9125
9054 9126 value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id;
9055 9127 (void) strlcpy(buf, value, bufsize);
9056 9128 return (B_TRUE);
9057 9129 }
9058 9130
9059 9131 static void
9060 9132 dladm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
9061 9133 ofmt_handle_t ofmt)
9062 9134 {
9063 9135 char buf[OFMT_BUFSIZE];
9064 9136
9065 9137 if (oferr == OFMT_SUCCESS)
9066 9138 return;
9067 9139 (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
9068 9140 /*
9069 9141 * All errors are considered fatal in parsable mode.
9070 9142 * NOMEM errors are always fatal, regardless of mode.
9071 9143 * For other errors, we print diagnostics in human-readable
9072 9144 * mode and processs what we can.
9073 9145 */
9074 9146 if (parsable || oferr == OFMT_ENOFIELDS) {
9075 9147 ofmt_close(ofmt);
9076 9148 die(buf);
9077 9149 } else {
9078 9150 warn(buf);
9079 9151 }
9080 9152 }
9081 9153
9082 9154 /*
9083 9155 * Called from the walker dladm_walk_datalink_id() for each IB partition to
9084 9156 * display IB partition specific information.
9085 9157 */
9086 9158 static dladm_status_t
9087 9159 print_part(show_part_state_t *state, datalink_id_t linkid)
9088 9160 {
9089 9161 dladm_part_attr_t attr;
9090 9162 dladm_status_t status;
9091 9163 dladm_conf_t conf;
9092 9164 char part_over[MAXLINKNAMELEN];
9093 9165 char part_name[MAXLINKNAMELEN];
9094 9166 part_fields_buf_t pbuf;
9095 9167 boolean_t force_in_conf = B_FALSE;
9096 9168
9097 9169 /*
9098 9170 * Get the information about the IB partition from the partition
9099 9171 * datlink ID 'linkid'.
9100 9172 */
9101 9173 if ((status = dladm_part_info(handle, linkid, &attr, state->ps_flags))
9102 9174 != DLADM_STATUS_OK)
9103 9175 return (status);
9104 9176
9105 9177 /*
9106 9178 * If an IB Phys link name was provided on the command line we have
9107 9179 * the Phys link's datalink ID in the ps_over_id field of the state
9108 9180 * structure. Proceed only if the IB partition represented by 'linkid'
9109 9181 * was created over Phys link denoted by ps_over_id. The
9110 9182 * 'dia_physlinkid' field of dladm_part_attr_t represents the IB Phys
9111 9183 * link over which the partition was created.
9112 9184 */
9113 9185 if (state->ps_over_id != DATALINK_ALL_LINKID)
9114 9186 if (state->ps_over_id != attr.dia_physlinkid)
9115 9187 return (DLADM_STATUS_OK);
9116 9188
9117 9189 /*
9118 9190 * The linkid argument passed to this function is the datalink ID
9119 9191 * of the IB Partition. Get the partitions name from this linkid.
9120 9192 */
9121 9193 if (dladm_datalink_id2info(handle, linkid, NULL, NULL,
9122 9194 NULL, part_name, sizeof (part_name)) != DLADM_STATUS_OK)
9123 9195 return (DLADM_STATUS_BADARG);
9124 9196
9125 9197 bzero(part_over, sizeof (part_over));
9126 9198
9127 9199 /*
9128 9200 * The 'dia_physlinkid' field contains the datalink ID of the IB Phys
9129 9201 * link over which the partition was created. Use this linkid to get the
9130 9202 * linkover field.
9131 9203 */
9132 9204 if (dladm_datalink_id2info(handle, attr.dia_physlinkid, NULL, NULL,
9133 9205 NULL, part_over, sizeof (part_over)) != DLADM_STATUS_OK)
9134 9206 (void) sprintf(part_over, "?");
9135 9207 state->ps_found = B_TRUE;
9136 9208
9137 9209 /*
9138 9210 * Read the FFORCE field from this datalink's persistent configuration
9139 9211 * database line to determine if this datalink was created forcibly.
9140 9212 * If this datalink is a temporary datalink, then it will not have an
9141 9213 * entry in the persistent configuration, so check if force create flag
9142 9214 * is set in the partition attributes.
9143 9215 *
9144 9216 * We need this two level check since persistent partitions brought up
9145 9217 * by up-part during boot will have force create flag always set, since
9146 9218 * we want up-part to always succeed even if the port is currently down
9147 9219 * or P_Key is not yet available in the subnet.
9148 9220 */
9149 9221 if ((status = dladm_getsnap_conf(handle, linkid, &conf)) ==
9150 9222 DLADM_STATUS_OK) {
9151 9223 (void) dladm_get_conf_field(handle, conf, FFORCE,
9152 9224 &force_in_conf, sizeof (boolean_t));
9153 9225 dladm_destroy_conf(handle, conf);
9154 9226 } else if (status == DLADM_STATUS_NOTFOUND) {
9155 9227 /*
9156 9228 * for a temp link the force create flag will determine
9157 9229 * whether it was created with force flag.
9158 9230 */
9159 9231 force_in_conf = ((attr.dia_flags & DLADM_PART_FORCE_CREATE)
9160 9232 != 0);
9161 9233 }
9162 9234
9163 9235 (void) snprintf(pbuf.part_link, sizeof (pbuf.part_link),
9164 9236 "%s", part_name);
9165 9237
9166 9238 (void) snprintf(pbuf.part_over, sizeof (pbuf.part_over),
9167 9239 "%s", part_over);
9168 9240
9169 9241 (void) snprintf(pbuf.part_pkey, sizeof (pbuf.part_pkey),
9170 9242 "%X", attr.dia_pkey);
9171 9243
9172 9244 (void) get_linkstate(pbuf.part_link, B_TRUE, pbuf.part_state);
9173 9245
9174 9246 (void) snprintf(pbuf.part_flags, sizeof (pbuf.part_flags),
9175 9247 "%c----", force_in_conf ? 'f' : '-');
9176 9248
9177 9249 ofmt_print(state->ps_ofmt, &pbuf);
9178 9250
9179 9251 return (DLADM_STATUS_OK);
9180 9252 }
9181 9253
9182 9254 /* ARGSUSED */
9183 9255 static int
9184 9256 show_part(dladm_handle_t dh, datalink_id_t linkid, void *arg)
9185 9257 {
9186 9258 ((show_part_state_t *)arg)->ps_status = print_part(arg, linkid);
9187 9259 return (DLADM_WALK_CONTINUE);
9188 9260 }
9189 9261
9190 9262 /*
9191 9263 * Show the information about the IB partition objects.
9192 9264 */
9193 9265 static void
9194 9266 do_show_part(int argc, char *argv[], const char *use)
9195 9267 {
9196 9268 int option;
9197 9269 boolean_t l_arg = B_FALSE;
9198 9270 uint32_t flags = DLADM_OPT_ACTIVE;
9199 9271 datalink_id_t linkid = DATALINK_ALL_LINKID;
9200 9272 datalink_id_t over_linkid = DATALINK_ALL_LINKID;
9201 9273 char over_link[MAXLINKNAMELEN];
9202 9274 show_part_state_t state;
9203 9275 dladm_status_t status;
9204 9276 boolean_t o_arg = B_FALSE;
9205 9277 char *fields_str = NULL;
9206 9278 ofmt_handle_t ofmt;
9207 9279 ofmt_status_t oferr;
9208 9280 uint_t ofmtflags = 0;
9209 9281
9210 9282 bzero(&state, sizeof (state));
9211 9283 opterr = 0;
9212 9284 while ((option = getopt_long(argc, argv, ":pPl:o:", show_part_lopts,
9213 9285 NULL)) != -1) {
9214 9286 switch (option) {
9215 9287 case 'p':
9216 9288 state.ps_parsable = B_TRUE;
9217 9289 break;
9218 9290 case 'P':
9219 9291 flags = DLADM_OPT_PERSIST;
9220 9292 break;
9221 9293 case 'l':
9222 9294 /*
9223 9295 * The data link ID of the IB Phys link. When this
9224 9296 * argument is provided we list only the partition
9225 9297 * objects created over this IB Phys link.
9226 9298 */
9227 9299 if (strlcpy(over_link, optarg, MAXLINKNAMELEN) >=
9228 9300 MAXLINKNAMELEN)
9229 9301 die("link name too long");
9230 9302
9231 9303 l_arg = B_TRUE;
9232 9304 break;
9233 9305 case 'o':
9234 9306 o_arg = B_TRUE;
9235 9307 fields_str = optarg;
9236 9308 break;
9237 9309 default:
9238 9310 die_opterr(optopt, option, use);
9239 9311 }
9240 9312 }
9241 9313
9242 9314 /*
9243 9315 * Get the partition ID (optional last argument).
9244 9316 */
9245 9317 if (optind == (argc - 1)) {
9246 9318 status = dladm_name2info(handle, argv[optind], &linkid, NULL,
9247 9319 NULL, NULL);
9248 9320 if (status != DLADM_STATUS_OK) {
9249 9321 die_dlerr(status, "invalid partition link name '%s'",
9250 9322 argv[optind]);
9251 9323 }
9252 9324 (void) strlcpy(state.ps_part, argv[optind], MAXLINKNAMELEN);
9253 9325 } else if (optind != argc) {
9254 9326 usage();
9255 9327 }
9256 9328
9257 9329 if (state.ps_parsable && !o_arg)
9258 9330 die("-p requires -o");
9259 9331
9260 9332 /*
9261 9333 * If an IB Phys link name was provided as an argument, then get its
9262 9334 * datalink ID.
9263 9335 */
9264 9336 if (l_arg) {
9265 9337 status = dladm_name2info(handle, over_link, &over_linkid, NULL,
9266 9338 NULL, NULL);
9267 9339 if (status != DLADM_STATUS_OK) {
9268 9340 die_dlerr(status, "invalid link name '%s'", over_link);
9269 9341 }
9270 9342 }
9271 9343
9272 9344 state.ps_over_id = over_linkid; /* IB Phys link ID */
9273 9345 state.ps_found = B_FALSE;
9274 9346 state.ps_flags = flags;
9275 9347
9276 9348 if (state.ps_parsable)
9277 9349 ofmtflags |= OFMT_PARSABLE;
9278 9350 oferr = ofmt_open(fields_str, part_fields, ofmtflags, 0, &ofmt);
9279 9351 dladm_ofmt_check(oferr, state.ps_parsable, ofmt);
9280 9352 state.ps_ofmt = ofmt;
9281 9353
9282 9354 /*
9283 9355 * If a specific IB partition name was not provided as an argument,
9284 9356 * walk all the datalinks and display the information for all
9285 9357 * IB partitions. If IB Phys link was provided limit it to only
9286 9358 * IB partitions created over that IB Phys link.
9287 9359 */
9288 9360 if (linkid == DATALINK_ALL_LINKID) {
9289 9361 (void) dladm_walk_datalink_id(show_part, handle, &state,
9290 9362 DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, flags);
9291 9363 } else {
9292 9364 (void) show_part(handle, linkid, &state);
9293 9365 if (state.ps_status != DLADM_STATUS_OK) {
9294 9366 ofmt_close(ofmt);
9295 9367 die_dlerr(state.ps_status, "failed to show IB partition"
9296 9368 " '%s'", state.ps_part);
9297 9369 }
9298 9370 }
9299 9371 ofmt_close(ofmt);
9300 9372 }
9301 9373
9302 9374
9303 9375 /*
9304 9376 * Called from the walker dladm_walk_datalink_id() for each IB Phys link to
9305 9377 * display IB specific information for these Phys links.
9306 9378 */
9307 9379 static dladm_status_t
9308 9380 print_ib(show_ib_state_t *state, datalink_id_t phys_linkid)
9309 9381 {
9310 9382 dladm_ib_attr_t attr;
9311 9383 dladm_status_t status;
9312 9384 char linkname[MAXLINKNAMELEN];
9313 9385 char pkeystr[MAXPKEYLEN];
9314 9386 int i;
9315 9387 ib_fields_buf_t ibuf;
9316 9388
9317 9389 bzero(&attr, sizeof (attr));
9318 9390
9319 9391 /*
9320 9392 * Get the attributes of the IB Phys link from active/Persistent config
9321 9393 * based on the flag passed.
9322 9394 */
9323 9395 if ((status = dladm_ib_info(handle, phys_linkid, &attr,
9324 9396 state->is_flags)) != DLADM_STATUS_OK)
9325 9397 return (status);
9326 9398
9327 9399 if ((state->is_link_id != DATALINK_ALL_LINKID) && (state->is_link_id
9328 9400 != attr.dia_physlinkid)) {
9329 9401 dladm_free_ib_info(&attr);
9330 9402 return (DLADM_STATUS_OK);
9331 9403 }
9332 9404
9333 9405 /*
9334 9406 * Get the data link name for the phys_linkid. If we are doing show-ib
9335 9407 * for all IB Phys links, we have only the datalink IDs not the
9336 9408 * datalink name.
9337 9409 */
9338 9410 if (dladm_datalink_id2info(handle, phys_linkid, NULL, NULL, NULL,
9339 9411 linkname, MAXLINKNAMELEN) != DLADM_STATUS_OK)
9340 9412 return (status);
9341 9413
9342 9414 (void) snprintf(ibuf.ib_link, sizeof (ibuf.ib_link),
9343 9415 "%s", linkname);
9344 9416
9345 9417 (void) snprintf(ibuf.ib_portnum, sizeof (ibuf.ib_portnum),
9346 9418 "%d", attr.dia_portnum);
9347 9419
9348 9420 (void) snprintf(ibuf.ib_hcaguid, sizeof (ibuf.ib_hcaguid),
9349 9421 "%llX", attr.dia_hca_guid);
9350 9422
9351 9423 (void) snprintf(ibuf.ib_portguid, sizeof (ibuf.ib_portguid),
9352 9424 "%llX", attr.dia_port_guid);
9353 9425
9354 9426 (void) get_linkstate(linkname, B_TRUE, ibuf.ib_state);
9355 9427
9356 9428 /*
9357 9429 * Create a comma separated list of pkeys from the pkey table returned
9358 9430 * by the IP over IB driver instance.
9359 9431 */
9360 9432 bzero(ibuf.ib_pkeys, attr.dia_port_pkey_tbl_sz * sizeof (ib_pkey_t));
9361 9433 for (i = 0; i < attr.dia_port_pkey_tbl_sz; i++) {
9362 9434 if (attr.dia_port_pkeys[i] != IB_PKEY_INVALID_FULL &&
9363 9435 attr.dia_port_pkeys[i] != IB_PKEY_INVALID_LIMITED) {
9364 9436 if (i == 0)
9365 9437 (void) snprintf(pkeystr, MAXPKEYLEN, "%X",
9366 9438 attr.dia_port_pkeys[i]);
9367 9439 else
9368 9440 (void) snprintf(pkeystr, MAXPKEYLEN, ",%X",
9369 9441 attr.dia_port_pkeys[i]);
9370 9442 (void) strlcat(ibuf.ib_pkeys, pkeystr, MAXPKEYSTRSZ);
9371 9443 }
9372 9444 }
9373 9445
9374 9446 dladm_free_ib_info(&attr);
9375 9447
9376 9448 ofmt_print(state->is_ofmt, &ibuf);
9377 9449
9378 9450 return (DLADM_STATUS_OK);
9379 9451 }
9380 9452
9381 9453 /* ARGSUSED */
9382 9454 static int
9383 9455 show_ib(dladm_handle_t dh, datalink_id_t linkid, void *arg)
9384 9456 {
9385 9457 ((show_ib_state_t *)arg)->is_status = print_ib(arg, linkid);
9386 9458 return (DLADM_WALK_CONTINUE);
9387 9459 }
9388 9460
9389 9461 /*
9390 9462 * Show the properties of one/all IB Phys links. This is different from
9391 9463 * show-phys command since this will display IB specific information about the
9392 9464 * Phys link like, HCA GUID, PORT GUID, PKEYS active for this port etc.
9393 9465 */
9394 9466 static void
9395 9467 do_show_ib(int argc, char *argv[], const char *use)
9396 9468 {
9397 9469 int option;
9398 9470 uint32_t flags = DLADM_OPT_ACTIVE;
9399 9471 datalink_id_t linkid = DATALINK_ALL_LINKID;
9400 9472 show_ib_state_t state;
9401 9473 dladm_status_t status;
9402 9474 boolean_t o_arg = B_FALSE;
9403 9475 char *fields_str = NULL;
9404 9476 ofmt_handle_t ofmt;
9405 9477 ofmt_status_t oferr;
9406 9478 uint_t ofmtflags = 0;
9407 9479
9408 9480 bzero(&state, sizeof (state));
9409 9481 opterr = 0;
9410 9482 while ((option = getopt_long(argc, argv, ":po:", show_lopts,
9411 9483 NULL)) != -1) {
9412 9484 switch (option) {
9413 9485 case 'p':
9414 9486 state.is_parsable = B_TRUE;
9415 9487 break;
9416 9488 case 'o':
9417 9489 o_arg = B_TRUE;
9418 9490 fields_str = optarg;
9419 9491 break;
9420 9492 default:
9421 9493 die_opterr(optopt, option, use);
9422 9494 }
9423 9495 }
9424 9496
9425 9497 /* get IB Phys link ID (optional last argument) */
9426 9498 if (optind == (argc - 1)) {
9427 9499 status = dladm_name2info(handle, argv[optind], &linkid, NULL,
9428 9500 NULL, NULL);
9429 9501 if (status != DLADM_STATUS_OK) {
9430 9502 die_dlerr(status, "invalid IB port name '%s'",
9431 9503 argv[optind]);
9432 9504 }
9433 9505 (void) strlcpy(state.is_link, argv[optind], MAXLINKNAMELEN);
9434 9506 } else if (optind != argc) {
9435 9507 usage();
9436 9508 }
9437 9509
9438 9510 if (state.is_parsable && !o_arg)
9439 9511 die("-p requires -o");
9440 9512
9441 9513 /*
9442 9514 * linkid is the data link ID of the IB Phys link. By default it will
9443 9515 * be DATALINK_ALL_LINKID.
9444 9516 */
9445 9517 state.is_link_id = linkid;
9446 9518 state.is_flags = flags;
9447 9519
9448 9520 if (state.is_parsable)
9449 9521 ofmtflags |= OFMT_PARSABLE;
9450 9522 oferr = ofmt_open(fields_str, ib_fields, ofmtflags, 0, &ofmt);
9451 9523 dladm_ofmt_check(oferr, state.is_parsable, ofmt);
9452 9524 state.is_ofmt = ofmt;
9453 9525
9454 9526 /*
9455 9527 * If we are going to display the information for all IB Phys links
9456 9528 * then we'll walk through all the datalinks for datalinks of Phys
9457 9529 * class and media type IB.
9458 9530 */
9459 9531 if (linkid == DATALINK_ALL_LINKID) {
9460 9532 (void) dladm_walk_datalink_id(show_ib, handle, &state,
9461 9533 DATALINK_CLASS_PHYS, DL_IB, flags);
9462 9534 } else {
9463 9535 /*
9464 9536 * We need to display the information only for the IB phys link
9465 9537 * linkid. Call show_ib for this link.
9466 9538 */
9467 9539 (void) show_ib(handle, linkid, &state);
9468 9540 if (state.is_status != DLADM_STATUS_OK) {
9469 9541 ofmt_close(ofmt);
9470 9542 die_dlerr(state.is_status, "failed to show IB Phys link"
9471 9543 " '%s'", state.is_link);
9472 9544 }
9473 9545 }
9474 9546 ofmt_close(ofmt);
9475 9547 }
9476 9548
9477 9549 /*
9478 9550 * Create an IP over Infiniband partition object over an IB Phys link. The IB
9479 9551 * Phys link is associated with an Infiniband HCA port. The IB partition object
9480 9552 * is created over a port, pkey combination. This partition object represents
9481 9553 * an instance of IP over IB interface.
9482 9554 */
9483 9555 /* ARGSUSED */
9484 9556 static void
9485 9557 do_create_part(int argc, char *argv[], const char *use)
9486 9558 {
9487 9559 int status, option;
9488 9560 int flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
9489 9561 char *pname;
9490 9562 char *l_arg = NULL;
9491 9563 char *altroot = NULL;
9492 9564 datalink_id_t physlinkid = 0;
9493 9565 datalink_id_t partlinkid = 0;
9494 9566 unsigned long opt_pkey;
9495 9567 ib_pkey_t pkey = 0;
9496 9568 char *endp = NULL;
9497 9569 char propstr[DLADM_STRSIZE];
9498 9570 dladm_arg_list_t *proplist = NULL;
9499 9571
9500 9572 propstr[0] = '\0';
9501 9573 while ((option = getopt_long(argc, argv, ":tfl:P:R:p:",
9502 9574 part_lopts, NULL)) != -1) {
9503 9575 switch (option) {
9504 9576 case 't':
9505 9577 /*
9506 9578 * Create a temporary IB partition object. This
9507 9579 * instance is not entered into the persistent database
9508 9580 * so it will not be recreated automatically on a
9509 9581 * reboot.
9510 9582 */
9511 9583 flags &= ~DLADM_OPT_PERSIST;
9512 9584 break;
9513 9585 case 'l':
9514 9586 /*
9515 9587 * The IB phys link over which the partition object will
9516 9588 * be created.
9517 9589 */
9518 9590 l_arg = optarg;
9519 9591 break;
9520 9592 case 'R':
9521 9593 altroot = optarg;
9522 9594 break;
9523 9595 case 'p':
9524 9596 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
9525 9597 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
9526 9598 DLADM_STRSIZE)
9527 9599 die("property list too long '%s'", propstr);
9528 9600 break;
9529 9601 case 'P':
9530 9602 /*
9531 9603 * The P_Key for the port, pkey tuple of the partition
9532 9604 * object. This P_Key should exist in the IB subnet.
9533 9605 * The partition creation for a non-existent P_Key will
9534 9606 * fail unless the -f option is used.
9535 9607 *
9536 9608 * The P_Key is expected to be a hexadecimal number.
9537 9609 */
9538 9610 opt_pkey = strtoul(optarg, &endp, 16);
9539 9611 if (errno == ERANGE || opt_pkey > USHRT_MAX ||
9540 9612 *endp != '\0')
9541 9613 die("Invalid pkey");
9542 9614
9543 9615 pkey = (ib_pkey_t)opt_pkey;
9544 9616 break;
9545 9617 case 'f':
9546 9618 flags |= DLADM_OPT_FORCE;
9547 9619 break;
9548 9620 default:
9549 9621 die_opterr(optopt, option, use);
9550 9622 break;
9551 9623 }
9552 9624 }
9553 9625
9554 9626 /* check required options */
9555 9627 if (!l_arg)
9556 9628 usage();
9557 9629
9558 9630 /* the partition name is a required operand */
9559 9631 if (optind != (argc - 1))
9560 9632 usage();
9561 9633
9562 9634 pname = argv[argc - 1];
9563 9635
9564 9636 /*
9565 9637 * Verify that the partition object's name is in the valid link name
9566 9638 * format.
9567 9639 */
9568 9640 if (!dladm_valid_linkname(pname))
9569 9641 die("Invalid link name '%s'", pname);
9570 9642
9571 9643 /* pkey is a mandatory argument */
9572 9644 if (pkey == 0)
9573 9645 usage();
9574 9646
9575 9647 if (altroot != NULL)
9576 9648 altroot_cmd(altroot, argc, argv);
9577 9649
9578 9650 /*
9579 9651 * Get the data link id of the IB Phys link over which we will be
9580 9652 * creating partition object.
9581 9653 */
9582 9654 if (dladm_name2info(handle, l_arg,
9583 9655 &physlinkid, NULL, NULL, NULL) != DLADM_STATUS_OK)
9584 9656 die("invalid link name '%s'", l_arg);
9585 9657
9586 9658 /*
9587 9659 * parse the property list provided with -p option.
9588 9660 */
9589 9661 if (dladm_parse_link_props(propstr, &proplist, B_FALSE)
9590 9662 != DLADM_STATUS_OK)
9591 9663 die("invalid IB partition property");
9592 9664
9593 9665 /*
9594 9666 * Call the library routine to create the partition object.
9595 9667 */
9596 9668 status = dladm_part_create(handle, physlinkid, pkey, flags, pname,
9597 9669 &partlinkid, proplist);
9598 9670 if (status != DLADM_STATUS_OK)
9599 9671 die_dlerr(status,
9600 9672 "partition %x creation over %s failed", pkey, l_arg);
9601 9673 }
9602 9674
9603 9675 /*
9604 9676 * Delete an IP over Infiniband partition object. The partition object should
9605 9677 * be unplumbed before attempting the delete.
9606 9678 */
9607 9679 static void
9608 9680 do_delete_part(int argc, char *argv[], const char *use)
9609 9681 {
9610 9682 int option, flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
9611 9683 int status;
9612 9684 char *altroot = NULL;
9613 9685 datalink_id_t partid;
9614 9686
9615 9687 opterr = 0;
9616 9688 while ((option = getopt_long(argc, argv, "R:t", part_lopts,
9617 9689 NULL)) != -1) {
9618 9690 switch (option) {
9619 9691 case 't':
9620 9692 flags &= ~DLADM_OPT_PERSIST;
9621 9693 break;
9622 9694 case 'R':
9623 9695 altroot = optarg;
9624 9696 break;
9625 9697 default:
9626 9698 die_opterr(optopt, option, use);
9627 9699 }
9628 9700 }
9629 9701
9630 9702 /* get partition name (required last argument) */
9631 9703 if (optind != (argc - 1))
9632 9704 usage();
9633 9705
9634 9706 if (altroot != NULL)
9635 9707 altroot_cmd(altroot, argc, argv);
9636 9708
9637 9709 /*
9638 9710 * Get the data link id of the partition object given the partition
9639 9711 * name.
9640 9712 */
9641 9713 status = dladm_name2info(handle, argv[optind], &partid, NULL, NULL,
9642 9714 NULL);
9643 9715 if (status != DLADM_STATUS_OK)
9644 9716 die("invalid link name '%s'", argv[optind]);
9645 9717
9646 9718 /*
9647 9719 * Call the library routine to delete the IB partition. This will
9648 9720 * result in the IB partition object and all its resources getting
9649 9721 * deleted.
9650 9722 */
9651 9723 status = dladm_part_delete(handle, partid, flags);
9652 9724 if (status != DLADM_STATUS_OK)
9653 9725 die_dlerr(status, "%s: partition deletion failed",
9654 9726 argv[optind]);
9655 9727 }
9656 9728
9657 9729 /*
9658 9730 * Bring up all or one IB partition already present in the persistent database
9659 9731 * but not active yet.
9660 9732 *
9661 9733 * This sub-command is used during the system boot up to bring up all IB
9662 9734 * partitions present in the persistent database. This is similar to a
9663 9735 * create partition except that, the partitions are always created even if the
9664 9736 * HCA port is down or P_Key is not present in the IB subnet. This is similar
9665 9737 * to using the 'force' option while creating the partition except that the 'f'
9666 9738 * flag will be set in the flags field only if the create-part for this command
9667 9739 * was called with '-f' option.
9668 9740 */
9669 9741 /* ARGSUSED */
9670 9742 static void
9671 9743 do_up_part(int argc, char *argv[], const char *use)
9672 9744 {
9673 9745 datalink_id_t partid = DATALINK_ALL_LINKID;
9674 9746 dladm_status_t status;
9675 9747
9676 9748 /*
9677 9749 * If a partition name was passed as an argument, get its data link
9678 9750 * id. By default we'll attempt to bring up all IB partition data
9679 9751 * links.
9680 9752 */
9681 9753 if (argc == 2) {
9682 9754 status = dladm_name2info(handle, argv[argc - 1], &partid, NULL,
9683 9755 NULL, NULL);
9684 9756 if (status != DLADM_STATUS_OK)
9685 9757 return;
9686 9758 } else if (argc > 2) {
9687 9759 usage();
9688 9760 }
9689 9761
9690 9762 (void) dladm_part_up(handle, partid, 0);
9691 9763 }
|
↓ open down ↓ |
2767 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX