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