Print this page
OS-281
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/flowadm/flowadm.c
+++ new/usr/src/cmd/flowadm/flowadm.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
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
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 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + * Copyright 2011 Joyent, Inc. All rights reserved.
24 25 */
25 26
26 27 #include <stdio.h>
27 28 #include <locale.h>
28 29 #include <stdarg.h>
29 30 #include <stdlib.h>
30 31 #include <fcntl.h>
31 32 #include <string.h>
32 33 #include <stropts.h>
33 34 #include <errno.h>
34 35 #include <strings.h>
35 36 #include <getopt.h>
36 37 #include <unistd.h>
37 38 #include <priv.h>
38 39 #include <netdb.h>
39 40 #include <libintl.h>
40 41 #include <libdlflow.h>
41 42 #include <libdllink.h>
42 43 #include <libdlstat.h>
43 44 #include <sys/types.h>
44 45 #include <sys/socket.h>
45 46 #include <netinet/in.h>
46 47 #include <arpa/inet.h>
47 48 #include <sys/ethernet.h>
48 49 #include <inet/ip.h>
49 50 #include <inet/ip6.h>
50 51 #include <stddef.h>
51 52 #include <ofmt.h>
52 53
53 54 typedef struct show_flow_state {
54 55 dladm_status_t fs_status;
55 56 ofmt_handle_t fs_ofmt;
56 57 const char *fs_flow;
57 58 boolean_t fs_parsable;
58 59 boolean_t fs_persist;
59 60 } show_flow_state_t;
60 61
61 62 typedef void cmdfunc_t(int, char **);
62 63
63 64 static cmdfunc_t do_add_flow, do_remove_flow, do_init_flow, do_show_flow;
64 65 static cmdfunc_t do_show_flowprop, do_set_flowprop, do_reset_flowprop;
65 66
66 67 static int show_flow(dladm_handle_t, dladm_flow_attr_t *, void *);
67 68 static int show_flows_onelink(dladm_handle_t, datalink_id_t, void *);
68 69
69 70 static int remove_flow(dladm_handle_t, dladm_flow_attr_t *, void *);
70 71
71 72 static int show_flowprop(dladm_handle_t, dladm_flow_attr_t *, void *);
72 73 static void show_flowprop_one_flow(void *, const char *);
73 74 static int show_flowprop_onelink(dladm_handle_t, datalink_id_t, void *);
74 75
75 76 static void die(const char *, ...);
76 77 static void die_optdup(int);
77 78 static void die_opterr(int, int);
78 79 static void die_dlerr(dladm_status_t, const char *, ...);
79 80 static void warn(const char *, ...);
80 81 static void warn_dlerr(dladm_status_t, const char *, ...);
81 82
82 83 /* callback functions for printing output */
83 84 static ofmt_cb_t print_flowprop_cb, print_default_cb;
84 85 static void flowadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
85 86
86 87 typedef struct cmd {
87 88 char *c_name;
88 89 void (*c_fn)(int, char **);
89 90 } cmd_t;
90 91
91 92 static cmd_t cmds[] = {
92 93 { "add-flow", do_add_flow },
93 94 { "remove-flow", do_remove_flow },
94 95 { "show-flowprop", do_show_flowprop },
95 96 { "set-flowprop", do_set_flowprop },
96 97 { "reset-flowprop", do_reset_flowprop },
97 98 { "show-flow", do_show_flow },
98 99 { "init-flow", do_init_flow },
99 100 };
100 101
101 102 static const struct option longopts[] = {
102 103 {"link", required_argument, 0, 'l'},
103 104 {"parsable", no_argument, 0, 'p'},
104 105 {"parseable", no_argument, 0, 'p'},
105 106 {"temporary", no_argument, 0, 't'},
106 107 {"root-dir", required_argument, 0, 'R'},
107 108 { 0, 0, 0, 0 }
108 109 };
109 110
110 111 static const struct option prop_longopts[] = {
111 112 {"link", required_argument, 0, 'l'},
112 113 {"temporary", no_argument, 0, 't'},
113 114 {"root-dir", required_argument, 0, 'R'},
114 115 {"prop", required_argument, 0, 'p'},
115 116 {"attr", required_argument, 0, 'a'},
116 117 { 0, 0, 0, 0 }
117 118 };
118 119
119 120 /*
120 121 * structures for 'flowadm remove-flow'
121 122 */
122 123 typedef struct remove_flow_state {
123 124 boolean_t fs_tempop;
124 125 const char *fs_altroot;
125 126 dladm_status_t fs_status;
126 127 } remove_flow_state_t;
127 128
128 129 #define PROTO_MAXSTR_LEN 7
129 130 #define PORT_MAXSTR_LEN 6
130 131 #define DSFIELD_MAXSTR_LEN 10
131 132 #define NULL_OFMT {NULL, 0, 0, NULL}
132 133
133 134 typedef struct flow_fields_buf_s
134 135 {
135 136 char flow_name[MAXFLOWNAMELEN];
136 137 char flow_link[MAXLINKNAMELEN];
137 138 char flow_ipaddr[INET6_ADDRSTRLEN+4];
138 139 char flow_proto[PROTO_MAXSTR_LEN];
139 140 char flow_lport[PORT_MAXSTR_LEN];
140 141 char flow_rport[PORT_MAXSTR_LEN];
141 142 char flow_dsfield[DSFIELD_MAXSTR_LEN];
142 143 } flow_fields_buf_t;
143 144
144 145 static ofmt_field_t flow_fields[] = {
145 146 /* name, field width, index */
146 147 { "FLOW", 12,
147 148 offsetof(flow_fields_buf_t, flow_name), print_default_cb},
148 149 { "LINK", 12,
149 150 offsetof(flow_fields_buf_t, flow_link), print_default_cb},
150 151 { "IPADDR", 25,
151 152 offsetof(flow_fields_buf_t, flow_ipaddr), print_default_cb},
152 153 { "PROTO", 7,
153 154 offsetof(flow_fields_buf_t, flow_proto), print_default_cb},
154 155 { "LPORT", 8,
155 156 offsetof(flow_fields_buf_t, flow_lport), print_default_cb},
156 157 { "RPORT", 8,
157 158 offsetof(flow_fields_buf_t, flow_rport), print_default_cb},
158 159 { "DSFLD", 10,
159 160 offsetof(flow_fields_buf_t, flow_dsfield), print_default_cb},
160 161 NULL_OFMT}
161 162 ;
162 163
163 164 /*
164 165 * structures for 'flowadm show-flowprop'
165 166 */
166 167 typedef enum {
167 168 FLOWPROP_FLOW,
168 169 FLOWPROP_PROPERTY,
169 170 FLOWPROP_VALUE,
170 171 FLOWPROP_DEFAULT,
171 172 FLOWPROP_POSSIBLE
172 173 } flowprop_field_index_t;
173 174
174 175 static ofmt_field_t flowprop_fields[] = {
175 176 /* name, fieldwidth, index, callback */
176 177 { "FLOW", 13, FLOWPROP_FLOW, print_flowprop_cb},
177 178 { "PROPERTY", 16, FLOWPROP_PROPERTY, print_flowprop_cb},
178 179 { "VALUE", 15, FLOWPROP_VALUE, print_flowprop_cb},
179 180 { "DEFAULT", 15, FLOWPROP_DEFAULT, print_flowprop_cb},
180 181 { "POSSIBLE", 21, FLOWPROP_POSSIBLE, print_flowprop_cb},
181 182 NULL_OFMT}
182 183 ;
183 184
184 185 #define MAX_PROP_LINE 512
185 186
186 187 typedef struct show_flowprop_state {
187 188 const char *fs_flow;
188 189 datalink_id_t fs_linkid;
189 190 char *fs_line;
190 191 char **fs_propvals;
191 192 dladm_arg_list_t *fs_proplist;
192 193 boolean_t fs_parsable;
193 194 boolean_t fs_persist;
194 195 boolean_t fs_header;
195 196 dladm_status_t fs_status;
196 197 dladm_status_t fs_retstatus;
197 198 ofmt_handle_t fs_ofmt;
198 199 } show_flowprop_state_t;
199 200
200 201 typedef struct set_flowprop_state {
201 202 const char *fs_name;
202 203 boolean_t fs_reset;
203 204 boolean_t fs_temp;
204 205 dladm_status_t fs_status;
205 206 } set_flowprop_state_t;
206 207
207 208 typedef struct flowprop_args_s {
208 209 show_flowprop_state_t *fs_state;
209 210 char *fs_propname;
210 211 char *fs_flowname;
211 212 } flowprop_args_t;
212 213
213 214 static char *progname;
214 215
215 216 boolean_t t_arg = B_FALSE; /* changes are persistent */
216 217 char *altroot = NULL;
217 218
218 219 /*
219 220 * Handle to libdladm. Opened in main() before the sub-command
220 221 * specific function is called.
221 222 */
222 223 static dladm_handle_t handle = NULL;
223 224
224 225 static const char *attr_table[] =
225 226 {"local_ip", "remote_ip", "transport", "local_port", "remote_port",
|
↓ open down ↓ |
192 lines elided |
↑ open up ↑ |
226 227 "dsfield"};
227 228
228 229 #define NATTR (sizeof (attr_table)/sizeof (char *))
229 230
230 231 static void
231 232 usage(void)
232 233 {
233 234 (void) fprintf(stderr, gettext("usage: flowadm <subcommand>"
234 235 " <args>...\n"
235 236 " add-flow [-t] -l <link> -a <attr>=<value>[,...]\n"
236 - "\t\t [-p <prop>=<value>,...] <flow>\n"
237 - " remove-flow [-t] {-l <link> | <flow>}\n"
238 - " show-flow [-p] [-l <link>] "
237 + "\t\t [-p <prop>=<value>,...] [-z zonename] <flow>\n"
238 + " remove-flow [-t] [-z zonename] {-l <link> | <flow>}\n"
239 + " show-flow [-p] [-l <link>] [-z zonename] "
239 240 "[<flow>]\n\n"
240 241 " set-flowprop [-t] -p <prop>=<value>[,...] <flow>\n"
241 242 " reset-flowprop [-t] [-p <prop>,...] <flow>\n"
242 243 " show-flowprop [-cP] [-l <link>] [-p <prop>,...] "
243 244 "[<flow>]\n"));
244 245
245 246 /* close dladm handle if it was opened */
246 247 if (handle != NULL)
247 248 dladm_close(handle);
248 249
249 250 exit(1);
250 251 }
251 252
252 253 int
253 254 main(int argc, char *argv[])
254 255 {
255 256 int i, arglen, cmdlen;
256 257 cmd_t *cmdp;
257 258 dladm_status_t status;
258 259
259 260 (void) setlocale(LC_ALL, "");
260 261 #if !defined(TEXT_DOMAIN)
261 262 #define TEXT_DOMAIN "SYS_TEST"
262 263 #endif
263 264 (void) textdomain(TEXT_DOMAIN);
264 265
265 266 progname = argv[0];
266 267
267 268 if (argc < 2)
268 269 usage();
269 270
270 271 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
271 272 cmdp = &cmds[i];
272 273 arglen = strlen(argv[1]);
273 274 cmdlen = strlen(cmdp->c_name);
274 275 if ((arglen == cmdlen) && (strncmp(argv[1], cmdp->c_name,
275 276 cmdlen) == 0)) {
276 277 /* Open the libdladm handle */
277 278 if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) {
278 279 die_dlerr(status,
279 280 "could not open /dev/dld");
280 281 }
281 282
282 283 cmdp->c_fn(argc - 1, &argv[1]);
283 284
284 285 dladm_close(handle);
285 286 exit(EXIT_SUCCESS);
286 287 }
287 288 }
288 289
289 290 (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
290 291 progname, argv[1]);
291 292 usage();
292 293
293 294 return (0);
294 295 }
295 296
296 297 static const char *
297 298 match_attr(char *attr)
298 299 {
299 300 int i;
300 301
301 302 for (i = 0; i < NATTR; i++) {
302 303 if (strlen(attr) == strlen(attr_table[i]) &&
303 304 strncmp(attr, attr_table[i], strlen(attr_table[i])) == 0) {
304 305 return (attr);
305 306 }
306 307 }
307 308 return (NULL);
308 309 }
309 310
310 311 /* ARGSUSED */
311 312 static void
312 313 do_init_flow(int argc, char *argv[])
313 314 {
314 315 dladm_status_t status;
315 316
316 317 status = dladm_flow_init(handle);
317 318 if (status != DLADM_STATUS_OK)
318 319 die_dlerr(status, "flows initialization failed");
319 320 }
320 321
321 322 static void
322 323 do_add_flow(int argc, char *argv[])
323 324 {
324 325 char devname[MAXLINKNAMELEN];
325 326 char *name = NULL;
|
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
326 327 uint_t index;
327 328 datalink_id_t linkid;
328 329
329 330 char option;
330 331 boolean_t l_arg = B_FALSE;
331 332 char propstr[DLADM_STRSIZE];
332 333 char attrstr[DLADM_STRSIZE];
333 334 dladm_arg_list_t *proplist = NULL;
334 335 dladm_arg_list_t *attrlist = NULL;
335 336 dladm_status_t status;
337 + char *zonename = NULL;
336 338
337 339 bzero(propstr, DLADM_STRSIZE);
338 340 bzero(attrstr, DLADM_STRSIZE);
339 341
340 - while ((option = getopt_long(argc, argv, "tR:l:a:p:",
342 + while ((option = getopt_long(argc, argv, "tR:l:a:p:z:",
341 343 prop_longopts, NULL)) != -1) {
342 344 switch (option) {
343 345 case 't':
344 346 t_arg = B_TRUE;
345 347 break;
346 348 case 'R':
347 349 altroot = optarg;
348 350 break;
349 351 case 'l':
350 352 if (strlcpy(devname, optarg,
351 353 MAXLINKNAMELEN) >= MAXLINKNAMELEN) {
352 354 die("link name too long");
353 355 }
354 - if (dladm_name2info(handle, devname, &linkid, NULL,
355 - NULL, NULL) != DLADM_STATUS_OK)
356 - die("invalid link '%s'", devname);
357 356 l_arg = B_TRUE;
358 357 break;
359 358 case 'a':
360 359 (void) strlcat(attrstr, optarg, DLADM_STRSIZE);
361 360 if (strlcat(attrstr, ",", DLADM_STRSIZE) >=
362 361 DLADM_STRSIZE)
363 362 die("attribute list too long '%s'", attrstr);
364 363 break;
365 364 case 'p':
366 365 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
367 366 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
368 367 DLADM_STRSIZE)
369 368 die("property list too long '%s'", propstr);
370 369 break;
370 + case 'z':
371 + zonename = optarg;
372 + break;
371 373 default:
372 374 die_opterr(optopt, option);
373 375 }
374 376 }
375 377 if (!l_arg) {
376 378 die("link is required");
377 379 }
378 380
381 + if (dladm_zname2info(handle, zonename, devname, &linkid, NULL,
382 + NULL, NULL) != DLADM_STATUS_OK)
383 + die("invalid link '%s'", devname);
384 +
379 385 opterr = 0;
380 386 index = optind;
381 387
382 388 if ((index != (argc - 1)) || match_attr(argv[index]) != NULL) {
383 389 die("flow name is required");
384 390 } else {
385 391 /* get flow name; required last argument */
386 392 if (strlen(argv[index]) >= MAXFLOWNAMELEN)
387 393 die("flow name too long");
388 394 name = argv[index];
389 395 }
390 396
391 397 if (dladm_parse_flow_attrs(attrstr, &attrlist, B_FALSE)
392 398 != DLADM_STATUS_OK)
393 399 die("invalid flow attribute specified");
394 400 if (dladm_parse_flow_props(propstr, &proplist, B_FALSE)
395 401 != DLADM_STATUS_OK)
396 402 die("invalid flow property specified");
397 403
398 404 status = dladm_flow_add(handle, linkid, attrlist, proplist, name,
399 405 t_arg, altroot);
400 406 if (status != DLADM_STATUS_OK)
401 407 die_dlerr(status, "add flow failed");
402 408
403 409 dladm_free_attrs(attrlist);
404 410 dladm_free_props(proplist);
405 411 }
406 412
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
407 413 static void
408 414 do_remove_flow(int argc, char *argv[])
409 415 {
410 416 char option;
411 417 char *flowname = NULL;
412 418 char linkname[MAXLINKNAMELEN];
413 419 datalink_id_t linkid = DATALINK_ALL_LINKID;
414 420 boolean_t l_arg = B_FALSE;
415 421 remove_flow_state_t state;
416 422 dladm_status_t status;
423 + char *zonename = NULL;
417 424
418 425 bzero(&state, sizeof (state));
419 426
420 427 opterr = 0;
421 - while ((option = getopt_long(argc, argv, ":tR:l:",
428 + while ((option = getopt_long(argc, argv, ":tR:l:z:",
422 429 longopts, NULL)) != -1) {
423 430 switch (option) {
424 431 case 't':
425 432 t_arg = B_TRUE;
426 433 break;
427 434 case 'R':
428 435 altroot = optarg;
429 436 break;
430 437 case 'l':
431 438 if (strlcpy(linkname, optarg,
432 439 MAXLINKNAMELEN) >= MAXLINKNAMELEN) {
433 440 die("link name too long");
434 441 }
435 - if (dladm_name2info(handle, linkname, &linkid, NULL,
436 - NULL, NULL) != DLADM_STATUS_OK) {
437 - die("invalid link '%s'", linkname);
438 - }
439 442 l_arg = B_TRUE;
440 443 break;
444 + case 'z':
445 + zonename = optarg;
446 + break;
441 447 default:
442 448 die_opterr(optopt, option);
443 449 break;
444 450 }
445 451 }
446 452
447 453 /* when link not specified get flow name */
448 454 if (!l_arg) {
449 455 if (optind != (argc-1)) {
450 456 usage();
451 457 } else {
452 458 if (strlen(argv[optind]) >= MAXFLOWNAMELEN)
453 459 die("flow name too long");
454 460 flowname = argv[optind];
455 461 }
456 462 status = dladm_flow_remove(handle, flowname, t_arg, altroot);
457 463 } else {
458 464 /* if link is specified then flow name should not be there */
459 465 if (optind == argc-1)
460 466 usage();
467 +
468 + if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL,
469 + NULL, NULL) != DLADM_STATUS_OK) {
470 + die("invalid link '%s'", linkname);
471 + }
472 +
461 473 /* walk the link to find flows and remove them */
462 474 state.fs_tempop = t_arg;
463 475 state.fs_altroot = altroot;
464 476 state.fs_status = DLADM_STATUS_OK;
465 477 status = dladm_walk_flow(remove_flow, handle, linkid, &state,
466 478 B_FALSE);
467 479 /*
468 480 * check if dladm_walk_flow terminated early and see if the
469 481 * walker function as any status for us
470 482 */
471 483 if (status == DLADM_STATUS_OK)
472 484 status = state.fs_status;
473 485 }
474 486
475 487 if (status != DLADM_STATUS_OK)
476 488 die_dlerr(status, "remove flow failed");
477 489 }
478 490
479 491 /*
480 492 * Walker function for removing a flow through dladm_walk_flow();
481 493 */
482 494 /*ARGSUSED*/
483 495 static int
484 496 remove_flow(dladm_handle_t handle, dladm_flow_attr_t *attr, void *arg)
485 497 {
486 498 remove_flow_state_t *state = (remove_flow_state_t *)arg;
487 499
488 500 state->fs_status = dladm_flow_remove(handle, attr->fa_flowname,
489 501 state->fs_tempop, state->fs_altroot);
490 502
491 503 if (state->fs_status == DLADM_STATUS_OK)
492 504 return (DLADM_WALK_CONTINUE);
493 505 else
494 506 return (DLADM_WALK_TERMINATE);
495 507 }
496 508
497 509 /*ARGSUSED*/
498 510 static dladm_status_t
499 511 print_flow(show_flow_state_t *state, dladm_flow_attr_t *attr,
500 512 flow_fields_buf_t *fbuf)
501 513 {
502 514 char link[MAXLINKNAMELEN];
503 515 dladm_status_t status;
504 516
505 517 if ((status = dladm_datalink_id2info(handle, attr->fa_linkid, NULL,
506 518 NULL, NULL, link, sizeof (link))) != DLADM_STATUS_OK) {
507 519 return (status);
508 520 }
509 521
510 522 (void) snprintf(fbuf->flow_name, sizeof (fbuf->flow_name),
511 523 "%s", attr->fa_flowname);
512 524 (void) snprintf(fbuf->flow_link, sizeof (fbuf->flow_link),
513 525 "%s", link);
514 526
515 527 (void) dladm_flow_attr_ip2str(attr, fbuf->flow_ipaddr,
516 528 sizeof (fbuf->flow_ipaddr));
517 529 (void) dladm_flow_attr_proto2str(attr, fbuf->flow_proto,
518 530 sizeof (fbuf->flow_proto));
519 531 if ((attr->fa_flow_desc.fd_mask & FLOW_ULP_PORT_LOCAL) != 0) {
520 532 (void) dladm_flow_attr_port2str(attr, fbuf->flow_lport,
521 533 sizeof (fbuf->flow_lport));
522 534 }
523 535 if ((attr->fa_flow_desc.fd_mask & FLOW_ULP_PORT_REMOTE) != 0) {
524 536 (void) dladm_flow_attr_port2str(attr, fbuf->flow_rport,
525 537 sizeof (fbuf->flow_rport));
526 538 }
527 539 (void) dladm_flow_attr_dsfield2str(attr, fbuf->flow_dsfield,
528 540 sizeof (fbuf->flow_dsfield));
529 541
530 542 return (DLADM_STATUS_OK);
531 543 }
532 544
533 545 /*
534 546 * Walker function for showing flow attributes through dladm_walk_flow().
535 547 */
536 548 /*ARGSUSED*/
537 549 static int
538 550 show_flow(dladm_handle_t handle, dladm_flow_attr_t *attr, void *arg)
539 551 {
540 552 show_flow_state_t *statep = arg;
541 553 dladm_status_t status;
542 554 flow_fields_buf_t fbuf;
543 555
544 556 /*
545 557 * first get all the flow attributes into fbuf;
546 558 */
547 559 bzero(&fbuf, sizeof (fbuf));
548 560 status = print_flow(statep, attr, &fbuf);
549 561
550 562 if (status != DLADM_STATUS_OK)
551 563 goto done;
552 564
553 565 ofmt_print(statep->fs_ofmt, (void *)&fbuf);
554 566
555 567 done:
556 568 statep->fs_status = status;
557 569 return (DLADM_WALK_CONTINUE);
558 570 }
559 571
560 572 static void
561 573 show_one_flow(void *arg, const char *name)
562 574 {
563 575 dladm_flow_attr_t attr;
564 576
565 577 if (dladm_flow_info(handle, name, &attr) != DLADM_STATUS_OK)
566 578 die("invalid flow: '%s'", name);
567 579 else
568 580 (void) show_flow(handle, &attr, arg);
569 581 }
570 582
571 583 /*
572 584 * Wrapper of dladm_walk_flow(show_flow,...) to make it usable to
573 585 * dladm_walk_datalink_id(). Used for showing flow attributes for
574 586 * all flows on all links.
575 587 */
576 588 static int
577 589 show_flows_onelink(dladm_handle_t dh, datalink_id_t linkid, void *arg)
578 590 {
579 591 show_flow_state_t *state = arg;
580 592
581 593 (void) dladm_walk_flow(show_flow, dh, linkid, arg, state->fs_persist);
582 594
583 595 return (DLADM_WALK_CONTINUE);
584 596 }
585 597
586 598 static void
587 599 do_show_flow(int argc, char *argv[])
588 600 {
589 601 char flowname[MAXFLOWNAMELEN];
|
↓ open down ↓ |
119 lines elided |
↑ open up ↑ |
590 602 char linkname[MAXLINKNAMELEN];
591 603 datalink_id_t linkid = DATALINK_ALL_LINKID;
592 604 int option;
593 605 boolean_t l_arg = B_FALSE;
594 606 boolean_t o_arg = B_FALSE;
595 607 show_flow_state_t state;
596 608 char *fields_str = NULL;
597 609 ofmt_handle_t ofmt;
598 610 ofmt_status_t oferr;
599 611 uint_t ofmtflags = 0;
612 + char *zonename = NULL;
600 613
601 614 bzero(&state, sizeof (state));
602 615
603 616 opterr = 0;
604 - while ((option = getopt_long(argc, argv, ":pPl:o:",
617 + while ((option = getopt_long(argc, argv, ":pPl:o:z:",
605 618 longopts, NULL)) != -1) {
606 619 switch (option) {
607 620 case 'p':
608 621 state.fs_parsable = B_TRUE;
609 622 ofmtflags |= OFMT_PARSABLE;
610 623 break;
611 624 case 'P':
612 625 state.fs_persist = B_TRUE;
613 626 break;
614 627 case 'o':
615 628 if (o_arg)
616 629 die_optdup(option);
617 630
618 631 o_arg = B_TRUE;
619 632 fields_str = optarg;
620 633 break;
621 634 case 'l':
622 635 if (strlcpy(linkname, optarg, MAXLINKNAMELEN)
623 636 >= MAXLINKNAMELEN)
624 637 die("link name too long\n");
625 - if (dladm_name2info(handle, linkname, &linkid, NULL,
626 - NULL, NULL) != DLADM_STATUS_OK)
627 - die("invalid link '%s'", linkname);
628 638 l_arg = B_TRUE;
629 639 break;
640 + case 'z':
641 + zonename = optarg;
642 + break;
630 643 default:
631 644 die_opterr(optopt, option);
632 645 break;
633 646 }
634 647 }
635 648
649 + if (l_arg) {
650 + if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL,
651 + NULL, NULL) != DLADM_STATUS_OK)
652 + die("invalid link '%s'", linkname);
653 + }
654 +
636 655 /* get flow name (optional last argument */
637 656 if (optind == (argc-1)) {
638 657 if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN)
639 658 >= MAXFLOWNAMELEN)
640 659 die("flow name too long");
641 660 state.fs_flow = flowname;
642 661 }
643 662
644 663 oferr = ofmt_open(fields_str, flow_fields, ofmtflags, 0, &ofmt);
645 664 flowadm_ofmt_check(oferr, state.fs_parsable, ofmt);
646 665 state.fs_ofmt = ofmt;
647 666
648 667 /* Show attributes of one flow */
649 668 if (state.fs_flow != NULL) {
650 669 show_one_flow(&state, state.fs_flow);
651 670
652 671 /* Show attributes of flows on one link */
653 672 } else if (l_arg) {
654 673 (void) show_flows_onelink(handle, linkid, &state);
655 674
656 675 /* Show attributes of all flows on all links */
657 676 } else {
658 677 (void) dladm_walk_datalink_id(show_flows_onelink, handle,
659 678 &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
660 679 DLADM_OPT_ACTIVE);
661 680 }
662 681 ofmt_close(ofmt);
663 682 }
664 683
665 684 static dladm_status_t
666 685 set_flowprop_persist(const char *flow, const char *prop_name, char **prop_val,
667 686 uint_t val_cnt, boolean_t reset)
668 687 {
669 688 dladm_status_t status;
670 689 char *errprop;
671 690
672 691 status = dladm_set_flowprop(handle, flow, prop_name, prop_val, val_cnt,
673 692 DLADM_OPT_PERSIST, &errprop);
674 693
675 694 if (status != DLADM_STATUS_OK) {
676 695 warn_dlerr(status, "cannot persistently %s flow "
677 696 "property '%s' on '%s'", reset? "reset": "set",
678 697 errprop, flow);
679 698 }
680 699 return (status);
681 700 }
682 701
683 702 static void
684 703 set_flowprop(int argc, char **argv, boolean_t reset)
685 704 {
686 705 int i, option;
687 706 char errmsg[DLADM_STRSIZE];
688 707 const char *flow = NULL;
689 708 char propstr[DLADM_STRSIZE];
690 709 dladm_arg_list_t *proplist = NULL;
691 710 boolean_t temp = B_FALSE;
692 711 dladm_status_t status = DLADM_STATUS_OK;
693 712
694 713 opterr = 0;
695 714 bzero(propstr, DLADM_STRSIZE);
696 715
697 716 while ((option = getopt_long(argc, argv, ":p:R:t",
698 717 prop_longopts, NULL)) != -1) {
699 718 switch (option) {
700 719 case 'p':
701 720 (void) strlcat(propstr, optarg, DLADM_STRSIZE);
702 721 if (strlcat(propstr, ",", DLADM_STRSIZE) >=
703 722 DLADM_STRSIZE)
704 723 die("property list too long '%s'", propstr);
705 724 break;
706 725 case 't':
707 726 temp = B_TRUE;
708 727 break;
709 728 case 'R':
710 729 status = dladm_set_rootdir(optarg);
711 730 if (status != DLADM_STATUS_OK) {
712 731 die_dlerr(status, "invalid directory "
713 732 "specified");
714 733 }
715 734 break;
716 735 default:
717 736 die_opterr(optopt, option);
718 737 break;
719 738 }
720 739 }
721 740
722 741 if (optind == (argc - 1)) {
723 742 if (strlen(argv[optind]) >= MAXFLOWNAMELEN)
724 743 die("flow name too long");
725 744 flow = argv[optind];
726 745 } else if (optind != argc) {
727 746 usage();
728 747 }
729 748 if (flow == NULL)
730 749 die("flow name must be specified");
731 750
732 751 if (dladm_parse_flow_props(propstr, &proplist, reset)
733 752 != DLADM_STATUS_OK)
734 753 die("invalid flow property specified");
735 754
736 755 if (proplist == NULL) {
737 756 char *errprop;
738 757
739 758 if (!reset)
740 759 die("flow property must be specified");
741 760
742 761 status = dladm_set_flowprop(handle, flow, NULL, NULL, 0,
743 762 DLADM_OPT_ACTIVE, &errprop);
744 763 if (status != DLADM_STATUS_OK) {
745 764 warn_dlerr(status, "cannot reset flow property '%s' "
746 765 "on '%s'", errprop, flow);
747 766 }
748 767 if (!temp) {
749 768 dladm_status_t s;
750 769
751 770 s = set_flowprop_persist(flow, NULL, NULL, 0, reset);
752 771 if (s != DLADM_STATUS_OK)
753 772 status = s;
754 773 }
755 774 goto done;
756 775 }
757 776
758 777 for (i = 0; i < proplist->al_count; i++) {
759 778 dladm_arg_info_t *aip = &proplist->al_info[i];
760 779 char **val;
761 780 uint_t count;
762 781 dladm_status_t s;
763 782
764 783 if (reset) {
765 784 val = NULL;
766 785 count = 0;
767 786 } else {
768 787 val = aip->ai_val;
769 788 count = aip->ai_count;
770 789 if (count == 0) {
771 790 warn("no value specified for '%s'",
772 791 aip->ai_name);
773 792 status = DLADM_STATUS_BADARG;
774 793 continue;
775 794 }
776 795 }
777 796 s = dladm_set_flowprop(handle, flow, aip->ai_name, val, count,
778 797 DLADM_OPT_ACTIVE, NULL);
779 798 if (s == DLADM_STATUS_OK) {
780 799 if (!temp) {
781 800 s = set_flowprop_persist(flow,
782 801 aip->ai_name, val, count, reset);
783 802 if (s != DLADM_STATUS_OK)
784 803 status = s;
785 804 }
786 805 continue;
787 806 }
788 807 status = s;
789 808 switch (s) {
790 809 case DLADM_STATUS_NOTFOUND:
791 810 warn("invalid flow property '%s'", aip->ai_name);
792 811 break;
793 812 case DLADM_STATUS_BADVAL: {
794 813 int j;
795 814 char *ptr, *lim;
796 815 char **propvals = NULL;
797 816 uint_t valcnt = DLADM_MAX_PROP_VALCNT;
798 817
799 818 ptr = malloc((sizeof (char *) +
800 819 DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT +
801 820 MAX_PROP_LINE);
802 821
803 822 if (ptr == NULL)
804 823 die("insufficient memory");
805 824 propvals = (char **)(void *)ptr;
806 825
807 826 for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) {
808 827 propvals[j] = ptr + sizeof (char *) *
809 828 DLADM_MAX_PROP_VALCNT +
810 829 j * DLADM_PROP_VAL_MAX;
811 830 }
812 831 s = dladm_get_flowprop(handle, flow,
813 832 DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals,
814 833 &valcnt);
815 834
816 835 ptr = errmsg;
817 836 lim = ptr + DLADM_STRSIZE;
818 837 *ptr = '\0';
819 838 for (j = 0; j < valcnt && s == DLADM_STATUS_OK; j++) {
820 839 ptr += snprintf(ptr, lim - ptr, "%s,",
821 840 propvals[j]);
822 841 if (ptr >= lim)
823 842 break;
824 843 }
825 844 if (ptr > errmsg) {
826 845 *(ptr - 1) = '\0';
827 846 warn("flow property '%s' must be one of: %s",
828 847 aip->ai_name, errmsg);
829 848 } else
830 849 warn("%s is an invalid value for "
831 850 "flow property %s", *val, aip->ai_name);
832 851 free(propvals);
833 852 break;
834 853 }
835 854 default:
836 855 if (reset) {
837 856 warn_dlerr(status, "cannot reset flow property "
838 857 "'%s' on '%s'", aip->ai_name, flow);
839 858 } else {
840 859 warn_dlerr(status, "cannot set flow property "
841 860 "'%s' on '%s'", aip->ai_name, flow);
842 861 }
843 862 break;
844 863 }
845 864 }
846 865 done:
847 866 dladm_free_props(proplist);
848 867 if (status != DLADM_STATUS_OK) {
849 868 dladm_close(handle);
850 869 exit(EXIT_FAILURE);
851 870 }
852 871 }
853 872
854 873 static void
855 874 do_set_flowprop(int argc, char **argv)
856 875 {
857 876 set_flowprop(argc, argv, B_FALSE);
858 877 }
859 878
860 879 static void
861 880 do_reset_flowprop(int argc, char **argv)
862 881 {
863 882 set_flowprop(argc, argv, B_TRUE);
864 883 }
865 884
866 885 static void
867 886 warn(const char *format, ...)
868 887 {
869 888 va_list alist;
870 889
871 890 format = gettext(format);
872 891 (void) fprintf(stderr, "%s: warning: ", progname);
873 892
874 893 va_start(alist, format);
875 894 (void) vfprintf(stderr, format, alist);
876 895 va_end(alist);
877 896
878 897 (void) putc('\n', stderr);
879 898 }
880 899
881 900 /* PRINTFLIKE2 */
882 901 static void
883 902 warn_dlerr(dladm_status_t err, const char *format, ...)
884 903 {
885 904 va_list alist;
886 905 char errmsg[DLADM_STRSIZE];
887 906
888 907 format = gettext(format);
889 908 (void) fprintf(stderr, gettext("%s: warning: "), progname);
890 909
891 910 va_start(alist, format);
892 911 (void) vfprintf(stderr, format, alist);
893 912 va_end(alist);
894 913 (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
895 914 }
896 915
897 916 /* PRINTFLIKE1 */
898 917 static void
899 918 die(const char *format, ...)
900 919 {
901 920 va_list alist;
902 921
903 922 format = gettext(format);
904 923 (void) fprintf(stderr, "%s: ", progname);
905 924
906 925 va_start(alist, format);
907 926 (void) vfprintf(stderr, format, alist);
908 927 va_end(alist);
909 928
910 929 (void) putc('\n', stderr);
911 930
912 931 /* close dladm handle if it was opened */
913 932 if (handle != NULL)
914 933 dladm_close(handle);
915 934
916 935 exit(EXIT_FAILURE);
917 936 }
918 937
919 938 static void
920 939 die_optdup(int opt)
921 940 {
922 941 die("the option -%c cannot be specified more than once", opt);
923 942 }
924 943
925 944 static void
926 945 die_opterr(int opt, int opterr)
927 946 {
928 947 switch (opterr) {
929 948 case ':':
930 949 die("option '-%c' requires a value", opt);
931 950 break;
932 951 case '?':
933 952 default:
934 953 die("unrecognized option '-%c'", opt);
935 954 break;
936 955 }
937 956 }
938 957
939 958 /* PRINTFLIKE2 */
940 959 static void
941 960 die_dlerr(dladm_status_t err, const char *format, ...)
942 961 {
943 962 va_list alist;
944 963 char errmsg[DLADM_STRSIZE];
945 964
946 965 format = gettext(format);
947 966 (void) fprintf(stderr, "%s: ", progname);
948 967
949 968 va_start(alist, format);
950 969 (void) vfprintf(stderr, format, alist);
951 970 va_end(alist);
952 971 (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
953 972
954 973 /* close dladm handle if it was opened */
955 974 if (handle != NULL)
956 975 dladm_close(handle);
957 976
958 977 exit(EXIT_FAILURE);
959 978 }
960 979
961 980 static void
962 981 print_flowprop(const char *flowname, show_flowprop_state_t *statep,
963 982 const char *propname, dladm_prop_type_t type,
964 983 const char *format, char **pptr)
965 984 {
966 985 int i;
967 986 char *ptr, *lim;
968 987 char buf[DLADM_STRSIZE];
969 988 char *unknown = "--", *notsup = "";
970 989 char **propvals = statep->fs_propvals;
971 990 uint_t valcnt = DLADM_MAX_PROP_VALCNT;
972 991 dladm_status_t status;
973 992
974 993 status = dladm_get_flowprop(handle, flowname, type, propname, propvals,
975 994 &valcnt);
976 995 if (status != DLADM_STATUS_OK) {
977 996 if (status == DLADM_STATUS_TEMPONLY) {
978 997 if (type == DLADM_PROP_VAL_MODIFIABLE &&
979 998 statep->fs_persist) {
980 999 valcnt = 1;
981 1000 propvals = &unknown;
982 1001 } else {
983 1002 statep->fs_status = status;
984 1003 statep->fs_retstatus = status;
985 1004 return;
986 1005 }
987 1006 } else if (status == DLADM_STATUS_NOTSUP ||
988 1007 statep->fs_persist) {
989 1008 valcnt = 1;
990 1009 if (type == DLADM_PROP_VAL_CURRENT)
991 1010 propvals = &unknown;
992 1011 else
993 1012 propvals = ¬sup;
994 1013 } else {
995 1014 if ((statep->fs_proplist != NULL) &&
996 1015 statep->fs_status == DLADM_STATUS_OK) {
997 1016 warn("invalid flow property '%s'", propname);
998 1017 }
999 1018 statep->fs_status = status;
1000 1019 statep->fs_retstatus = status;
1001 1020 return;
1002 1021 }
1003 1022 }
1004 1023
1005 1024 statep->fs_status = DLADM_STATUS_OK;
1006 1025
1007 1026 ptr = buf;
1008 1027 lim = buf + DLADM_STRSIZE;
1009 1028 for (i = 0; i < valcnt; i++) {
1010 1029 if (propvals[i][0] == '\0' && !statep->fs_parsable)
1011 1030 ptr += snprintf(ptr, lim - ptr, "--,");
1012 1031 else
1013 1032 ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]);
1014 1033 if (ptr >= lim)
1015 1034 break;
1016 1035 }
1017 1036 if (valcnt > 0)
1018 1037 buf[strlen(buf) - 1] = '\0';
1019 1038
1020 1039 lim = statep->fs_line + MAX_PROP_LINE;
1021 1040 if (statep->fs_parsable) {
1022 1041 *pptr += snprintf(*pptr, lim - *pptr,
1023 1042 "%s", buf);
1024 1043 } else {
1025 1044 *pptr += snprintf(*pptr, lim - *pptr, format, buf);
1026 1045 }
1027 1046 }
1028 1047
1029 1048 static boolean_t
1030 1049 print_flowprop_cb(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
1031 1050 {
1032 1051 flowprop_args_t *arg = of_arg->ofmt_cbarg;
1033 1052 char *propname = arg->fs_propname;
1034 1053 show_flowprop_state_t *statep = arg->fs_state;
1035 1054 char *ptr = statep->fs_line;
1036 1055 char *lim = ptr + MAX_PROP_LINE;
1037 1056 char *flowname = arg->fs_flowname;
1038 1057
1039 1058 switch (of_arg->ofmt_id) {
1040 1059 case FLOWPROP_FLOW:
1041 1060 (void) snprintf(ptr, lim - ptr, "%s", statep->fs_flow);
1042 1061 break;
1043 1062 case FLOWPROP_PROPERTY:
1044 1063 (void) snprintf(ptr, lim - ptr, "%s", propname);
1045 1064 break;
1046 1065 case FLOWPROP_VALUE:
1047 1066 print_flowprop(flowname, statep, propname,
1048 1067 statep->fs_persist ? DLADM_PROP_VAL_PERSISTENT :
1049 1068 DLADM_PROP_VAL_CURRENT, "%s", &ptr);
1050 1069 /*
1051 1070 * If we failed to query the flow property, for example, query
1052 1071 * the persistent value of a non-persistable flow property,
1053 1072 * simply skip the output.
1054 1073 */
1055 1074 if (statep->fs_status != DLADM_STATUS_OK)
1056 1075 goto skip;
1057 1076 ptr = statep->fs_line;
1058 1077 break;
1059 1078 case FLOWPROP_DEFAULT:
1060 1079 print_flowprop(flowname, statep, propname,
1061 1080 DLADM_PROP_VAL_DEFAULT, "%s", &ptr);
1062 1081 if (statep->fs_status != DLADM_STATUS_OK)
1063 1082 goto skip;
1064 1083 ptr = statep->fs_line;
1065 1084 break;
1066 1085 case FLOWPROP_POSSIBLE:
1067 1086 print_flowprop(flowname, statep, propname,
1068 1087 DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr);
1069 1088 if (statep->fs_status != DLADM_STATUS_OK)
1070 1089 goto skip;
1071 1090 ptr = statep->fs_line;
1072 1091 break;
1073 1092 default:
1074 1093 die("invalid input");
1075 1094 break;
1076 1095 }
1077 1096 (void) strlcpy(buf, ptr, bufsize);
1078 1097 return (B_TRUE);
1079 1098 skip:
1080 1099 buf[0] = '\0';
1081 1100 return ((statep->fs_status == DLADM_STATUS_OK) ?
1082 1101 B_TRUE : B_FALSE);
1083 1102 }
1084 1103
1085 1104 static int
1086 1105 show_one_flowprop(void *arg, const char *propname)
1087 1106 {
1088 1107 show_flowprop_state_t *statep = arg;
1089 1108 flowprop_args_t fs_arg;
1090 1109
1091 1110 bzero(&fs_arg, sizeof (fs_arg));
1092 1111 fs_arg.fs_state = statep;
1093 1112 fs_arg.fs_propname = (char *)propname;
1094 1113 fs_arg.fs_flowname = (char *)statep->fs_flow;
1095 1114
1096 1115 ofmt_print(statep->fs_ofmt, (void *)&fs_arg);
1097 1116
1098 1117 return (DLADM_WALK_CONTINUE);
1099 1118 }
1100 1119
1101 1120 /*ARGSUSED*/
1102 1121 /* Walker function called by dladm_walk_flow to display flow properties */
1103 1122 static int
1104 1123 show_flowprop(dladm_handle_t handle, dladm_flow_attr_t *attr, void *arg)
1105 1124 {
1106 1125 show_flowprop_one_flow(arg, attr->fa_flowname);
1107 1126 return (DLADM_WALK_CONTINUE);
1108 1127 }
1109 1128
1110 1129 /*
1111 1130 * Wrapper of dladm_walk_flow(show_walk_fn,...) to make it
1112 1131 * usable to dladm_walk_datalink_id()
1113 1132 */
1114 1133 static int
1115 1134 show_flowprop_onelink(dladm_handle_t dh, datalink_id_t linkid, void *arg)
1116 1135 {
1117 1136 char name[MAXLINKNAMELEN];
1118 1137
1119 1138 if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, name,
1120 1139 sizeof (name)) != DLADM_STATUS_OK)
1121 1140 return (DLADM_WALK_TERMINATE);
1122 1141
1123 1142 (void) dladm_walk_flow(show_flowprop, dh, linkid, arg, B_FALSE);
1124 1143
1125 1144 return (DLADM_WALK_CONTINUE);
1126 1145 }
1127 1146
1128 1147 static void
1129 1148 do_show_flowprop(int argc, char **argv)
1130 1149 {
1131 1150 int option;
1132 1151 dladm_arg_list_t *proplist = NULL;
1133 1152 show_flowprop_state_t state;
1134 1153 char *fields_str = NULL;
1135 1154 ofmt_handle_t ofmt;
1136 1155 ofmt_status_t oferr;
1137 1156 uint_t ofmtflags = 0;
1138 1157
1139 1158 opterr = 0;
1140 1159 state.fs_propvals = NULL;
1141 1160 state.fs_line = NULL;
1142 1161 state.fs_parsable = B_FALSE;
1143 1162 state.fs_persist = B_FALSE;
1144 1163 state.fs_header = B_TRUE;
1145 1164 state.fs_retstatus = DLADM_STATUS_OK;
1146 1165 state.fs_linkid = DATALINK_INVALID_LINKID;
1147 1166 state.fs_flow = NULL;
1148 1167
1149 1168 while ((option = getopt_long(argc, argv, ":p:cPl:o:",
1150 1169 prop_longopts, NULL)) != -1) {
1151 1170 switch (option) {
1152 1171 case 'p':
1153 1172 if (dladm_parse_flow_props(optarg, &proplist, B_TRUE)
1154 1173 != DLADM_STATUS_OK)
1155 1174 die("invalid flow properties specified");
1156 1175 break;
1157 1176 case 'c':
1158 1177 state.fs_parsable = B_TRUE;
1159 1178 ofmtflags |= OFMT_PARSABLE;
1160 1179 break;
1161 1180 case 'P':
1162 1181 state.fs_persist = B_TRUE;
1163 1182 break;
1164 1183 case 'l':
1165 1184 if (dladm_name2info(handle, optarg, &state.fs_linkid,
1166 1185 NULL, NULL, NULL) != DLADM_STATUS_OK)
1167 1186 die("invalid link '%s'", optarg);
1168 1187 break;
1169 1188 case 'o':
1170 1189 fields_str = optarg;
1171 1190 break;
1172 1191 default:
1173 1192 die_opterr(optopt, option);
1174 1193 break;
1175 1194 }
1176 1195 }
1177 1196
1178 1197 if (optind == (argc - 1)) {
1179 1198 if (strlen(argv[optind]) >= MAXFLOWNAMELEN)
1180 1199 die("flow name too long");
1181 1200 state.fs_flow = argv[optind];
1182 1201 } else if (optind != argc) {
1183 1202 usage();
1184 1203 }
1185 1204 state.fs_proplist = proplist;
1186 1205 state.fs_status = DLADM_STATUS_OK;
1187 1206
1188 1207 oferr = ofmt_open(fields_str, flowprop_fields, ofmtflags, 0, &ofmt);
1189 1208 flowadm_ofmt_check(oferr, state.fs_parsable, ofmt);
1190 1209 state.fs_ofmt = ofmt;
1191 1210
1192 1211 /* Show properties for one flow */
1193 1212 if (state.fs_flow != NULL) {
1194 1213 show_flowprop_one_flow(&state, state.fs_flow);
1195 1214
1196 1215 /* Show properties for all flows on one link */
1197 1216 } else if (state.fs_linkid != DATALINK_INVALID_LINKID) {
1198 1217 (void) show_flowprop_onelink(handle, state.fs_linkid, &state);
1199 1218
1200 1219 /* Show properties for all flows on all links */
1201 1220 } else {
1202 1221 (void) dladm_walk_datalink_id(show_flowprop_onelink, handle,
1203 1222 &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
1204 1223 DLADM_OPT_ACTIVE);
1205 1224 }
1206 1225
1207 1226 dladm_free_props(proplist);
1208 1227 ofmt_close(ofmt);
1209 1228 }
1210 1229
1211 1230 static void
1212 1231 show_flowprop_one_flow(void *arg, const char *flow)
1213 1232 {
1214 1233 int i;
1215 1234 char *buf;
1216 1235 dladm_status_t status;
1217 1236 dladm_arg_list_t *proplist = NULL;
1218 1237 show_flowprop_state_t *statep = arg;
1219 1238 dladm_flow_attr_t attr;
1220 1239 const char *savep;
1221 1240
1222 1241 /*
1223 1242 * Do not print flow props for invalid flows.
1224 1243 */
1225 1244 if ((status = dladm_flow_info(handle, flow, &attr)) !=
1226 1245 DLADM_STATUS_OK) {
1227 1246 die("invalid flow: '%s'", flow);
1228 1247 }
1229 1248
1230 1249 savep = statep->fs_flow;
1231 1250 statep->fs_flow = flow;
1232 1251
1233 1252 proplist = statep->fs_proplist;
1234 1253
1235 1254 buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX)
1236 1255 * DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE);
1237 1256 if (buf == NULL)
1238 1257 die("insufficient memory");
1239 1258
1240 1259 statep->fs_propvals = (char **)(void *)buf;
1241 1260 for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
1242 1261 statep->fs_propvals[i] = buf +
1243 1262 sizeof (char *) * DLADM_MAX_PROP_VALCNT +
1244 1263 i * DLADM_PROP_VAL_MAX;
1245 1264 }
1246 1265 statep->fs_line = buf +
1247 1266 (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
1248 1267
1249 1268 /* show only specified flow properties */
1250 1269 if (proplist != NULL) {
1251 1270 for (i = 0; i < proplist->al_count; i++) {
1252 1271 if (show_one_flowprop(statep,
1253 1272 proplist->al_info[i].ai_name) != DLADM_STATUS_OK)
1254 1273 break;
1255 1274 }
1256 1275
1257 1276 /* show all flow properties */
1258 1277 } else {
1259 1278 status = dladm_walk_flowprop(show_one_flowprop, flow, statep);
1260 1279 if (status != DLADM_STATUS_OK)
1261 1280 die_dlerr(status, "show-flowprop");
1262 1281 }
1263 1282 free(buf);
1264 1283 statep->fs_flow = savep;
1265 1284 }
1266 1285
1267 1286 /*
1268 1287 * default output callback function that, when invoked from dladm_print_output,
1269 1288 * prints string which is offset by of_arg->ofmt_id within buf.
1270 1289 */
1271 1290 static boolean_t
1272 1291 print_default_cb(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
1273 1292 {
1274 1293 char *value;
1275 1294
1276 1295 value = (char *)of_arg->ofmt_cbarg + of_arg->ofmt_id;
1277 1296 (void) strlcpy(buf, value, bufsize);
1278 1297 return (B_TRUE);
1279 1298 }
1280 1299
1281 1300 static void
1282 1301 flowadm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
1283 1302 ofmt_handle_t ofmt)
1284 1303 {
1285 1304 char buf[OFMT_BUFSIZE];
1286 1305
1287 1306 if (oferr == OFMT_SUCCESS)
1288 1307 return;
1289 1308 (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
1290 1309 /*
1291 1310 * All errors are considered fatal in parsable mode.
1292 1311 * NOMEM errors are always fatal, regardless of mode.
1293 1312 * For other errors, we print diagnostics in human-readable
1294 1313 * mode and processs what we can.
1295 1314 */
1296 1315 if (parsable || oferr == OFMT_ENOFIELDS) {
1297 1316 ofmt_close(ofmt);
1298 1317 die(buf);
1299 1318 } else {
1300 1319 warn(buf);
1301 1320 }
1302 1321 }
|
↓ open down ↓ |
657 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX