2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
14 * Copyright (c) 2012 Joyent, Inc. All rights reserved.
15 * Use is subject to license terms.
18 #include <sys/types.h>
36 static char g_zonename
[ZONENAME_MAX
];
37 static zoneid_t g_zid
;
43 typedef int (*idc_cmd_func_t
)(int, char *[]);
44 typedef struct ipdadm_cmd
{
45 const char *idc_name
; /* subcommand name */
46 idc_cmd_func_t idc_func
; /* subcommand function */
47 const char *idc_usage
; /* subcommand help */
50 static int ipdadm_list(int, char *[]);
51 static int ipdadm_info(int, char *[]);
52 static int ipdadm_corrupt(int, char *[]);
53 static int ipdadm_delay(int, char *[]);
54 static int ipdadm_drop(int, char *[]);
55 static int ipdadm_remove(int, char *[]);
57 #define IPDADM_NCMDS 6
58 static ipdadm_cmd_t ipdadm_cmds
[] = {
59 { "list", ipdadm_list
, "list [-v]" },
60 { "info", ipdadm_info
, "info" },
61 { "corrupt", ipdadm_corrupt
, "corrupt <percentage>" },
62 { "delay", ipdadm_delay
, "delay <microseconds>" },
63 { "drop", ipdadm_drop
, "drop <percentage>" },
64 { "remove", ipdadm_remove
, "remove [corrupt|delay|drop]" }
73 (void) fprintf(fp
, "Usage: %s [-z zonename] subcommand "
74 "[subcommand opts]\n\n", g_pname
);
75 (void) fprintf(fp
, "Subcommands:\n");
76 for (ii
= 0; ii
< IPDADM_NCMDS
; ii
++) {
77 cmd
= &ipdadm_cmds
[ii
];
78 (void) fprintf(fp
, "\t%s\n", cmd
->idc_usage
);
85 ipdadm_list_one(zoneid_t z
, const ipd_config_t
*icp
, void *arg
)
87 char zonename
[ZONENAME_MAX
];
88 int opt_v
= (int)(intptr_t)arg
;
90 if (getzonenamebyid(z
, zonename
, sizeof (zonename
)) < 0)
91 (void) printf("%ld", z
);
93 (void) printf("%s", zonename
);
100 (void) printf("\t%u\t%u\t%u\n", icp
->ic_corrupt
, icp
->ic_drop
,
105 ipdadm_list(int argc
, char *argv
[])
112 return (usage(stderr
));
115 if (strcmp(argv
[0], "-v") == 0)
118 return (usage(stderr
));
123 (void) fprintf(stderr
, "%s: failed to open ipd ctl node: %s\n",
124 g_pname
, ipd_errmsg
);
127 rval
= ipd_status_read(fd
, &hdl
);
128 (void) ipd_close(fd
);
131 (void) fprintf(stderr
, "%s: failed to get list info: %s\n",
132 g_pname
, ipd_errmsg
);
136 ipd_status_foreach_zone(hdl
, ipdadm_list_one
, (void *)(intptr_t)opt_v
);
137 ipd_status_free(hdl
);
144 ipdadm_info(int argc
, char *argv
[])
151 return (usage(stderr
));
155 (void) fprintf(stderr
, "%s: failed to open ipd ctl node: %s\n",
156 g_pname
, ipd_errmsg
);
159 rval
= ipd_status_read(fd
, &hdl
);
160 (void) ipd_close(fd
);
162 (void) fprintf(stderr
, "%s: failed to get info: %s\n",
163 g_pname
, ipd_errmsg
);
167 if (ipd_status_get_config(hdl
, g_zid
, &icp
) != 0) {
168 if (ipd_errno
== EIPD_ZC_NOENT
) {
169 (void) printf("zone %s does not exist or has no "
170 "ipd actions enabled\n", g_zonename
);
173 (void) fprintf(stderr
, "%s: failed to get info: %s\n",
174 g_pname
, ipd_errmsg
);
178 (void) printf("ipd information for zone %s:\n",
180 (void) printf("\tcorrupt:\t%u%% chance of packet corruption\n",
182 (void) printf("\tdrop:\t\t%u%% chance of packet drop\n",
184 (void) printf("\tdelay:\t\t%u microsecond delay per packet\n",
187 ipd_status_free(hdl
);
193 ipdadm_parse_long(const char *str
, const char *name
, long min
, long max
)
199 val
= strtol(str
, &end
, 10);
201 (void) fprintf(stderr
, "%s: invalid value for %s: %s\n",
207 * We want to make sure that we got the whole string. If not that's an
208 * error. e.g. 23.42 should not be valid.
211 (void) fprintf(stderr
, "%s: %s value must be an integer\n",
216 if (val
< min
|| val
> max
) {
217 (void) fprintf(stderr
, "%s: %s value must be between %ld and "
218 "%ld inclusive\n", g_pname
, name
, min
, max
);
226 ipdadm_corrupt(int argc
, char *argv
[])
233 (void) fprintf(stderr
, "%s: corrupt <percentage>\n",
235 return (usage(stderr
));
238 val
= ipdadm_parse_long(argv
[0], "corrupt", 0, 100);
239 bzero(&ic
, sizeof (ic
));
240 ic
.ic_mask
= IPDM_CORRUPT
;
245 (void) fprintf(stderr
, "%s: failed to open ipd ctl node: %s\n",
246 g_pname
, ipd_errmsg
);
249 rval
= ipd_ctl(fd
, g_zid
, &ic
);
250 (void) ipd_close(fd
);
253 (void) fprintf(stderr
, "%s: failed to change corrupt "
254 "value: %s\n", g_pname
, ipd_errmsg
);
262 ipdadm_delay(int argc
, char *argv
[])
269 (void) fprintf(stderr
, "%s: delay <microseconds>\n",
271 return (usage(stderr
));
274 val
= ipdadm_parse_long(argv
[0], "delay", 0, MAXLONG
);
275 bzero(&ic
, sizeof (ic
));
276 ic
.ic_mask
= IPDM_DELAY
;
281 (void) fprintf(stderr
, "%s: failed to open ipd ctl node: %s\n",
282 g_pname
, ipd_errmsg
);
285 rval
= ipd_ctl(fd
, g_zid
, &ic
);
286 (void) ipd_close(fd
);
289 (void) fprintf(stderr
, "%s: failed to change delay value: %s\n",
290 g_pname
, ipd_errmsg
);
298 ipdadm_drop(int argc
, char *argv
[])
305 (void) fprintf(stderr
, "%s: drop <percentage>\n",
307 return (usage(stderr
));
310 val
= ipdadm_parse_long(argv
[0], "drop", 0, 100);
311 bzero(&ic
, sizeof (ic
));
312 ic
.ic_mask
= IPDM_DROP
;
317 (void) fprintf(stderr
, "%s: failed to open ipd ctl node: %s\n",
318 g_pname
, ipd_errmsg
);
321 rval
= ipd_ctl(fd
, g_zid
, &ic
);
322 (void) ipd_close(fd
);
325 (void) fprintf(stderr
, "%s: failed to change drop value: %s\n",
326 g_pname
, ipd_errmsg
);
334 ipdadm_remove_valid(const char *str
)
336 if (strcmp(str
, "corrupt") == 0) {
337 return (IPDM_CORRUPT
);
338 } else if (strcmp(str
, "drop") == 0) {
340 } else if (strcmp(str
, "delay") == 0) {
348 ipdadm_remove(int argc
, char *argv
[])
355 (void) fprintf(stderr
, "%s: remove <arguments>\n",
357 return (usage(stderr
));
361 (void) fprintf(stderr
, "%s: remove's arguments must be "
362 "comma seperated\n", g_pname
);
366 bzero(&ic
, sizeof (ic
));
369 while ((res
= strchr(cur
, ',')) != NULL
) {
371 if ((rval
= ipdadm_remove_valid(cur
)) == 0) {
372 (void) fprintf(stderr
, "%s: unknown remove "
373 "argument: %s\n", g_pname
, cur
);
380 if ((rval
= ipdadm_remove_valid(cur
)) == 0) {
381 (void) fprintf(stderr
, "%s: unknown remove argument: %s\n",
389 (void) fprintf(stderr
, "%s: failed to open ipd ctl node: %s\n",
390 g_pname
, ipd_errmsg
);
393 rval
= ipd_ctl(fd
, g_zid
, &ic
);
394 (void) ipd_close(fd
);
396 (void) fprintf(stderr
, "%s: failed to remove instances: %s\n",
397 g_pname
, ipd_errmsg
);
406 main(int argc
, char *argv
[])
411 g_pname
= basename(argv
[0]);
414 return (usage(stderr
));
419 if (strcmp("-z", argv
[0]) == 0) {
423 (void) fprintf(stderr
, "%s: -z requires an argument\n",
425 return (usage(stderr
));
428 if (g_zid
!= GLOBAL_ZONEID
) {
429 (void) fprintf(stderr
, "%s: -z option only permitted "
430 "in global zone\n", g_pname
);
431 return (usage(stderr
));
434 g_zid
= getzoneidbyname(argv
[0]);
436 (void) fprintf(stderr
, "%s: %s: invalid zone\n",
444 if (getzonenamebyid(g_zid
, g_zonename
, sizeof (g_zonename
)) < 0) {
445 (void) fprintf(stderr
, "%s: failed to get zonename: %s\n",
446 g_pname
, strerror(errno
));
451 return (usage(stderr
));
453 for (ii
= 0; ii
< IPDADM_NCMDS
; ii
++) {
454 cmd
= &ipdadm_cmds
[ii
];
455 if (strcmp(argv
[0], cmd
->idc_name
) == 0) {
458 assert(cmd
->idc_func
!= NULL
);
459 return (cmd
->idc_func(argc
, argv
));
463 (void) fprintf(stderr
, "%s: %s: unknown command\n", g_pname
, argv
[0]);
464 return (usage(stderr
));