diff options
author | Robert Mustacchi <rm@joyent.com> | 2013-09-29 14:27:52 -0700 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2013-11-06 08:09:36 -0800 |
commit | fe77cc0407fb667ddc04e1a8f2e203bb7b9c80e1 (patch) | |
tree | b5723fc87b94e5c73aa9c243dc40e6dac6ef5440 /usr/src/cmd | |
parent | c6d054cbc999e5c8b9ad1aa01dbb4800b84f06bd (diff) | |
download | illumos-joyent-fe77cc0407fb667ddc04e1a8f2e203bb7b9c80e1.tar.gz |
4236 Internet Packet Disturber
4237 net_* and hook_* man pages are wrong
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Brendan Gregg <brendan.gregg@joyent.com>
Reviewed by: Keith M Wesolowski <wesolows@foobazco.org>
Reviewed by: Sebastien Roy <seb@delphix.com>
Approved by: Dan McDonald <danmcd@nexenta.com>
Diffstat (limited to 'usr/src/cmd')
-rw-r--r-- | usr/src/cmd/Makefile | 3 | ||||
-rw-r--r-- | usr/src/cmd/devfsadm/misc_link.c | 4 | ||||
-rw-r--r-- | usr/src/cmd/ipdadm/Makefile | 45 | ||||
-rw-r--r-- | usr/src/cmd/ipdadm/ipdadm.c | 435 |
4 files changed, 486 insertions, 1 deletions
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile index 1fa2a43e8f..d04b74d498 100644 --- a/usr/src/cmd/Makefile +++ b/usr/src/cmd/Makefile @@ -21,7 +21,7 @@ # Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2010 Nexenta Systems, Inc. All rights reserved. -# Copyright 2011 Joyent, Inc. All rights reserved. +# Copyright (c) 2012 Joyent, Inc. All rights reserved. # Copyright (c) 2012 by Delphix. All rights reserved. # Copyright (c) 2013 DEY Storage Systems, Inc. All rights reserved. @@ -207,6 +207,7 @@ COMMON_SUBDIRS= \ intrstat \ ipcrm \ ipcs \ + ipdadm \ ipf \ isainfo \ isalist \ diff --git a/usr/src/cmd/devfsadm/misc_link.c b/usr/src/cmd/devfsadm/misc_link.c index 9465e2c886..b7aef8b00d 100644 --- a/usr/src/cmd/devfsadm/misc_link.c +++ b/usr/src/cmd/devfsadm/misc_link.c @@ -21,6 +21,7 @@ /* * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #include <regex.h> @@ -107,6 +108,9 @@ static devfsadm_create_t misc_cbt[] = { "(^nca$)|(^rds$)|(^sdp$)|(^ipnet$)|(^dlpistub$)|(^bpf$)", TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name }, + { "pseudo", "ddi_pseudo", "ipd", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name + }, { "pseudo", "ddi_pseudo", "(^ipf$)|(^ipnat$)|(^ipstate$)|(^ipauth$)|" "(^ipsync$)|(^ipscan$)|(^iplookup$)", diff --git a/usr/src/cmd/ipdadm/Makefile b/usr/src/cmd/ipdadm/Makefile new file mode 100644 index 0000000000..349899e5f6 --- /dev/null +++ b/usr/src/cmd/ipdadm/Makefile @@ -0,0 +1,45 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# + +PROG= ipdadm +OBJS = ipdadm.o +SRCS = $(OBJS:%.o=../%.c) + + +include ../Makefile.cmd +include ../Makefile.ctf + +CLEANFILES += $(OBJS) +CFLAGS += $(CCVERBOSE) +LDLIBS += -lipd + +.KEEP_STATE: + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +clean: + -$(RM) $(CLEANFILES) + +lint: lint_PROG + +%.o: ../%.c + $(COMPILE.c) $< + $(POST_PROCESS_O) + +install: $(PROG) $(ROOTUSRSBINPROG) + +include ../Makefile.targ diff --git a/usr/src/cmd/ipdadm/ipdadm.c b/usr/src/cmd/ipdadm/ipdadm.c new file mode 100644 index 0000000000..ca68541690 --- /dev/null +++ b/usr/src/cmd/ipdadm/ipdadm.c @@ -0,0 +1,435 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + + +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <values.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <strings.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stropts.h> +#include <zone.h> +#include <libgen.h> +#include <assert.h> + +#include <libipd.h> + +static char *g_pname; +static char g_zonename[ZONENAME_MAX]; +static zoneid_t g_zid; + +#define E_SUCCESS 0 +#define E_ERROR 1 +#define E_USAGE 2 + +typedef int (*idc_cmd_func_t)(int, char *[]); +typedef struct ipdadm_cmd { + const char *idc_name; /* subcommand name */ + idc_cmd_func_t idc_func; /* subcommand function */ + const char *idc_usage; /* subcommand help */ +} ipdadm_cmd_t; + +static int ipdadm_list(int, char *[]); +static int ipdadm_info(int, char *[]); +static int ipdadm_corrupt(int, char *[]); +static int ipdadm_delay(int, char *[]); +static int ipdadm_drop(int, char *[]); +static int ipdadm_remove(int, char *[]); + +#define IPDADM_NCMDS 6 +static ipdadm_cmd_t ipdadm_cmds[] = { + { "list", ipdadm_list, "list [-v]" }, + { "info", ipdadm_info, "info" }, + { "corrupt", ipdadm_corrupt, "corrupt <percentage>" }, + { "delay", ipdadm_delay, "delay <microseconds>" }, + { "drop", ipdadm_drop, "drop <percentage>" }, + { "remove", ipdadm_remove, "remove [corrupt|delay|drop]" } +}; + +static int +usage(FILE *fp) +{ + int ii; + ipdadm_cmd_t *cmd; + + (void) fprintf(fp, "Usage: %s [-z zonename] subcommand " + "[subcommand opts]\n\n", g_pname); + (void) fprintf(fp, "Subcommands:\n"); + for (ii = 0; ii < IPDADM_NCMDS; ii++) { + cmd = &ipdadm_cmds[ii]; + (void) fprintf(fp, "\t%s\n", cmd->idc_usage); + } + + return (E_USAGE); +} + +static void +ipdadm_list_one(zoneid_t z, const ipd_config_t *icp, void *arg) +{ + char zonename[ZONENAME_MAX]; + int opt_v = (int)(intptr_t)arg; + + if (getzonenamebyid(z, zonename, sizeof (zonename)) < 0) + (void) printf("%ld", z); + else + (void) printf("%s", zonename); + + if (!opt_v) { + (void) printf("\n"); + return; + } + + (void) printf("\t%u\t%u\t%u\n", icp->ic_corrupt, icp->ic_drop, + icp->ic_delay); +} + +static int +ipdadm_list(int argc, char *argv[]) +{ + int opt_v = 0; + int fd, rval; + ipd_stathdl_t hdl; + + if (argc > 1) + return (usage(stderr)); + + if (argc == 1) { + if (strcmp(argv[0], "-v") == 0) + ++opt_v; + else + return (usage(stderr)); + } + + fd = ipd_open(NULL); + rval = ipd_status_read(fd, &hdl); + (void) ipd_close(fd); + + if (rval != 0) { + (void) fprintf(stderr, "%s: failed to get list info: %s\n", + g_pname, ipd_errmsg); + return (E_ERROR); + } + + ipd_status_foreach_zone(hdl, ipdadm_list_one, (void *)(intptr_t)opt_v); + ipd_status_free(hdl); + + return (E_SUCCESS); +} + +/*ARGSUSED*/ +static int +ipdadm_info(int argc, char *argv[]) +{ + int rval, fd; + ipd_stathdl_t hdl; + ipd_config_t *icp; + + if (argc != 0) + return (usage(stderr)); + + fd = ipd_open(NULL); + rval = ipd_status_read(fd, &hdl); + (void) ipd_close(fd); + if (rval != 0) { + (void) fprintf(stderr, "%s: failed to get info: %s\n", + g_pname, ipd_errmsg); + return (E_ERROR); + } + + if (ipd_status_get_config(hdl, g_zid, &icp) != 0) { + if (ipd_errno == EIPD_ZC_NOENT) { + (void) printf("zone %s does not exist or has no " + "ipd actions enabled\n", g_zonename); + return (E_SUCCESS); + } + (void) fprintf(stderr, "%s: failed to get info: %s\n", + g_pname, ipd_errmsg); + return (E_ERROR); + } + + (void) printf("ipd information for zone %s:\n", + g_zonename); + (void) printf("\tcorrupt:\t%u%% chance of packet corruption\n", + icp->ic_corrupt); + (void) printf("\tdrop:\t\t%u%% chance of packet drop\n", + icp->ic_drop); + (void) printf("\tdelay:\t\t%u microsecond delay per packet\n", + icp->ic_delay); + + ipd_status_free(hdl); + + return (E_SUCCESS); +} + +static long +ipdadm_parse_long(const char *str, const char *name, long min, long max) +{ + long val; + char *end; + + errno = 0; + val = strtol(str, &end, 10); + if (errno != 0) { + (void) fprintf(stderr, "%s: invalid value for %s: %s\n", + g_pname, name, str); + exit(E_ERROR); + } + + /* + * We want to make sure that we got the whole string. If not that's an + * error. e.g. 23.42 should not be valid. + */ + if (*end != '\0') { + (void) fprintf(stderr, "%s: %s value must be an integer\n", + g_pname, name); + exit(E_ERROR); + } + + if (val < min || val > max) { + (void) fprintf(stderr, "%s: %s value must be between %ld and " + "%ld inclusive\n", g_pname, name, min, max); + exit(E_ERROR); + } + + return (val); +} + +static int +ipdadm_corrupt(int argc, char *argv[]) +{ + int rval, fd; + long val; + ipd_config_t ic; + + if (argc != 1) { + (void) fprintf(stderr, "%s: corrupt <percentage>\n", + g_pname); + return (usage(stderr)); + } + + val = ipdadm_parse_long(argv[0], "corrupt", 0, 100); + bzero(&ic, sizeof (ic)); + ic.ic_mask = IPDM_CORRUPT; + ic.ic_corrupt = val; + + fd = ipd_open(NULL); + rval = ipd_ctl(fd, g_zid, &ic); + (void) ipd_close(fd); + + if (rval != 0) { + (void) fprintf(stderr, "%s: failed to change corrupt " + "value: %s\n", g_pname, ipd_errmsg); + return (E_ERROR); + } + + return (E_SUCCESS); +} + +static int +ipdadm_delay(int argc, char *argv[]) +{ + long val; + int fd, rval; + ipd_config_t ic; + + if (argc != 1) { + (void) fprintf(stderr, "%s: delay <microseconds>\n", + g_pname); + return (usage(stderr)); + } + + val = ipdadm_parse_long(argv[0], "delay", 0, MAXLONG); + bzero(&ic, sizeof (ic)); + ic.ic_mask = IPDM_DELAY; + ic.ic_delay = val; + + fd = ipd_open(NULL); + rval = ipd_ctl(fd, g_zid, &ic); + (void) ipd_close(fd); + + if (rval != 0) { + (void) fprintf(stderr, "%s: failed to change delay value: %s\n", + g_pname, ipd_errmsg); + return (E_ERROR); + } + + return (E_SUCCESS); +} + +static int +ipdadm_drop(int argc, char *argv[]) +{ + long val; + int fd, rval; + ipd_config_t ic; + + if (argc != 1) { + (void) fprintf(stderr, "%s: drop <percentage>\n", + g_pname); + return (usage(stderr)); + } + + val = ipdadm_parse_long(argv[0], "drop", 0, 100); + bzero(&ic, sizeof (ic)); + ic.ic_mask = IPDM_DROP; + ic.ic_drop = val; + + fd = ipd_open(NULL); + rval = ipd_ctl(fd, g_zid, &ic); + (void) ipd_close(fd); + + if (rval != 0) { + (void) fprintf(stderr, "%s: failed to change drop value: %s\n", + g_pname, ipd_errmsg); + return (E_ERROR); + } + + return (E_SUCCESS); +} + +static int +ipdadm_remove_valid(const char *str) +{ + if (strcmp(str, "corrupt") == 0) { + return (IPDM_CORRUPT); + } else if (strcmp(str, "drop") == 0) { + return (IPDM_DROP); + } else if (strcmp(str, "delay") == 0) { + return (IPDM_DELAY); + } + + return (0); +} + +static int +ipdadm_remove(int argc, char *argv[]) +{ + ipd_config_t ic; + char *cur, *res; + int rval, fd; + + if (argc < 1) { + (void) fprintf(stderr, "%s: remove <arguments>\n", + g_pname); + return (usage(stderr)); + } + + if (argc > 1) { + (void) fprintf(stderr, "%s: remove's arguments must be " + "comma seperated\n", g_pname); + return (E_ERROR); + } + + bzero(&ic, sizeof (ic)); + + cur = argv[0]; + while ((res = strchr(cur, ',')) != NULL) { + *res = '\0'; + if ((rval = ipdadm_remove_valid(cur)) == 0) { + (void) fprintf(stderr, "%s: unknown remove " + "argument: %s\n", g_pname, cur); + return (E_ERROR); + } + ic.ic_mask |= rval; + cur = res + 1; + } + + if ((rval = ipdadm_remove_valid(cur)) == 0) { + (void) fprintf(stderr, "%s: unknown remove argument: %s\n", + g_pname, cur); + return (E_ERROR); + } + ic.ic_mask |= rval; + + fd = ipd_open(NULL); + rval = ipd_ctl(fd, g_zid, &ic); + (void) ipd_close(fd); + if (rval == -1) { + (void) fprintf(stderr, "%s: failed to remove instances: %s\n", + g_pname, ipd_errmsg); + return (E_ERROR); + } + + return (E_SUCCESS); +} + + +int +main(int argc, char *argv[]) +{ + int ii; + ipdadm_cmd_t *cmd; + + g_pname = basename(argv[0]); + + if (argc < 2) + return (usage(stderr)); + argc--; + argv++; + + g_zid = getzoneid(); + if (strcmp("-z", argv[0]) == 0) { + argc--; + argv++; + if (argc < 1) { + (void) fprintf(stderr, "%s: -z requires an argument\n", + g_pname); + return (usage(stderr)); + } + + if (g_zid != GLOBAL_ZONEID) { + (void) fprintf(stderr, "%s: -z option only permitted " + "in global zone\n", g_pname); + return (usage(stderr)); + } + + g_zid = getzoneidbyname(argv[0]); + if (g_zid == -1) { + (void) fprintf(stderr, "%s: %s: invalid zone\n", + g_pname, argv[0]); + return (E_ERROR); + } + argc--; + argv++; + } + + if (getzonenamebyid(g_zid, g_zonename, sizeof (g_zonename)) < 0) { + (void) fprintf(stderr, "%s: failed to get zonename: %s\n", + g_pname, strerror(errno)); + return (E_ERROR); + } + + if (argc < 1) + return (usage(stderr)); + + for (ii = 0; ii < IPDADM_NCMDS; ii++) { + cmd = &ipdadm_cmds[ii]; + if (strcmp(argv[0], cmd->idc_name) == 0) { + argv++; + argc--; + assert(cmd->idc_func != NULL); + return (cmd->idc_func(argc, argv)); + } + } + + (void) fprintf(stderr, "%s: %s: unknown command\n", g_pname, argv[0]); + return (usage(stderr)); +} |