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
));
122 rval
= ipd_status_read(fd
, &hdl
);
123 (void) ipd_close(fd
);
126 (void) fprintf(stderr
, "%s: failed to get list info: %s\n",
127 g_pname
, ipd_errmsg
);
131 ipd_status_foreach_zone(hdl
, ipdadm_list_one
, (void *)(intptr_t)opt_v
);
132 ipd_status_free(hdl
);
139 ipdadm_info(int argc
, char *argv
[])
146 return (usage(stderr
));
149 rval
= ipd_status_read(fd
, &hdl
);
150 (void) ipd_close(fd
);
152 (void) fprintf(stderr
, "%s: failed to get info: %s\n",
153 g_pname
, ipd_errmsg
);
157 if (ipd_status_get_config(hdl
, g_zid
, &icp
) != 0) {
158 if (ipd_errno
== EIPD_ZC_NOENT
) {
159 (void) printf("zone %s does not exist or has no "
160 "ipd actions enabled\n", g_zonename
);
163 (void) fprintf(stderr
, "%s: failed to get info: %s\n",
164 g_pname
, ipd_errmsg
);
168 (void) printf("ipd information for zone %s:\n",
170 (void) printf("\tcorrupt:\t%u%% chance of packet corruption\n",
172 (void) printf("\tdrop:\t\t%u%% chance of packet drop\n",
174 (void) printf("\tdelay:\t\t%u microsecond delay per packet\n",
177 ipd_status_free(hdl
);
183 ipdadm_parse_long(const char *str
, const char *name
, long min
, long max
)
189 val
= strtol(str
, &end
, 10);
191 (void) fprintf(stderr
, "%s: invalid value for %s: %s\n",
197 * We want to make sure that we got the whole string. If not that's an
198 * error. e.g. 23.42 should not be valid.
201 (void) fprintf(stderr
, "%s: %s value must be an integer\n",
206 if (val
< min
|| val
> max
) {
207 (void) fprintf(stderr
, "%s: %s value must be between %ld and "
208 "%ld inclusive\n", g_pname
, name
, min
, max
);
216 ipdadm_corrupt(int argc
, char *argv
[])
223 (void) fprintf(stderr
, "%s: corrupt <percentage>\n",
225 return (usage(stderr
));
228 val
= ipdadm_parse_long(argv
[0], "corrupt", 0, 100);
229 bzero(&ic
, sizeof (ic
));
230 ic
.ic_mask
= IPDM_CORRUPT
;
234 rval
= ipd_ctl(fd
, g_zid
, &ic
);
235 (void) ipd_close(fd
);
238 (void) fprintf(stderr
, "%s: failed to change corrupt "
239 "value: %s\n", g_pname
, ipd_errmsg
);
247 ipdadm_delay(int argc
, char *argv
[])
254 (void) fprintf(stderr
, "%s: delay <microseconds>\n",
256 return (usage(stderr
));
259 val
= ipdadm_parse_long(argv
[0], "delay", 0, MAXLONG
);
260 bzero(&ic
, sizeof (ic
));
261 ic
.ic_mask
= IPDM_DELAY
;
265 rval
= ipd_ctl(fd
, g_zid
, &ic
);
266 (void) ipd_close(fd
);
269 (void) fprintf(stderr
, "%s: failed to change delay value: %s\n",
270 g_pname
, ipd_errmsg
);
278 ipdadm_drop(int argc
, char *argv
[])
285 (void) fprintf(stderr
, "%s: drop <percentage>\n",
287 return (usage(stderr
));
290 val
= ipdadm_parse_long(argv
[0], "drop", 0, 100);
291 bzero(&ic
, sizeof (ic
));
292 ic
.ic_mask
= IPDM_DROP
;
296 rval
= ipd_ctl(fd
, g_zid
, &ic
);
297 (void) ipd_close(fd
);
300 (void) fprintf(stderr
, "%s: failed to change drop value: %s\n",
301 g_pname
, ipd_errmsg
);
309 ipdadm_remove_valid(const char *str
)
311 if (strcmp(str
, "corrupt") == 0) {
312 return (IPDM_CORRUPT
);
313 } else if (strcmp(str
, "drop") == 0) {
315 } else if (strcmp(str
, "delay") == 0) {
323 ipdadm_remove(int argc
, char *argv
[])
330 (void) fprintf(stderr
, "%s: remove <arguments>\n",
332 return (usage(stderr
));
336 (void) fprintf(stderr
, "%s: remove's arguments must be "
337 "comma seperated\n", g_pname
);
341 bzero(&ic
, sizeof (ic
));
344 while ((res
= strchr(cur
, ',')) != NULL
) {
346 if ((rval
= ipdadm_remove_valid(cur
)) == 0) {
347 (void) fprintf(stderr
, "%s: unknown remove "
348 "argument: %s\n", g_pname
, cur
);
355 if ((rval
= ipdadm_remove_valid(cur
)) == 0) {
356 (void) fprintf(stderr
, "%s: unknown remove argument: %s\n",
363 rval
= ipd_ctl(fd
, g_zid
, &ic
);
364 (void) ipd_close(fd
);
366 (void) fprintf(stderr
, "%s: failed to remove instances: %s\n",
367 g_pname
, ipd_errmsg
);
376 main(int argc
, char *argv
[])
381 g_pname
= basename(argv
[0]);
384 return (usage(stderr
));
389 if (strcmp("-z", argv
[0]) == 0) {
393 (void) fprintf(stderr
, "%s: -z requires an argument\n",
395 return (usage(stderr
));
398 if (g_zid
!= GLOBAL_ZONEID
) {
399 (void) fprintf(stderr
, "%s: -z option only permitted "
400 "in global zone\n", g_pname
);
401 return (usage(stderr
));
404 g_zid
= getzoneidbyname(argv
[0]);
406 (void) fprintf(stderr
, "%s: %s: invalid zone\n",
414 if (getzonenamebyid(g_zid
, g_zonename
, sizeof (g_zonename
)) < 0) {
415 (void) fprintf(stderr
, "%s: failed to get zonename: %s\n",
416 g_pname
, strerror(errno
));
421 return (usage(stderr
));
423 for (ii
= 0; ii
< IPDADM_NCMDS
; ii
++) {
424 cmd
= &ipdadm_cmds
[ii
];
425 if (strcmp(argv
[0], cmd
->idc_name
) == 0) {
428 assert(cmd
->idc_func
!= NULL
);
429 return (cmd
->idc_func(argc
, argv
));
433 (void) fprintf(stderr
, "%s: %s: unknown command\n", g_pname
, argv
[0]);
434 return (usage(stderr
));