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