From c0e542217e211e45e688b76358f942b60a127c55 Mon Sep 17 00:00:00 2001 From: jimharris Date: Fri, 12 Apr 2013 17:56:47 +0000 Subject: Remove the NVME_IDENTIFY_CONTROLLER and NVME_IDENTIFY_NAMESPACE IOCTLs and replace them with the NVMe passthrough equivalent. Sponsored by: Intel --- sbin/nvmecontrol/nvmecontrol.c | 120 +++++++++++++++++++++++++++++------------ 1 file changed, 86 insertions(+), 34 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index cbb365b..fd55b42 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -210,6 +210,53 @@ ns_get_sector_size(struct nvme_namespace_data *nsdata) return (1 << nsdata->lbaf[0].lbads); } +static void +read_controller_data(int fd, struct nvme_controller_data *cdata) +{ + struct nvme_pt_command pt; + + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_IDENTIFY; + pt.cmd.cdw10 = 1; + pt.buf = cdata; + pt.len = sizeof(*cdata); + pt.is_read = 1; + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { + printf("Identify request failed. errno=%d (%s)\n", + errno, strerror(errno)); + exit(EX_IOERR); + } + + if (nvme_completion_is_error(&pt.cpl)) { + printf("Passthrough command returned error.\n"); + exit(EX_IOERR); + } +} + +static void +read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata) +{ + struct nvme_pt_command pt; + + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_IDENTIFY; + pt.cmd.nsid = nsid; + pt.buf = nsdata; + pt.len = sizeof(*nsdata); + pt.is_read = 1; + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { + printf("Identify request failed. errno=%d (%s)\n", + errno, strerror(errno)); + exit(EX_IOERR); + } + + if (nvme_completion_is_error(&pt.cpl)) { + printf("Passthrough command returned error.\n"); + exit(EX_IOERR); + } +} static void devlist(int argc, char *argv[]) @@ -251,33 +298,12 @@ devlist(int argc, char *argv[]) continue; } - if (ioctl(fd, NVME_IDENTIFY_CONTROLLER, &cdata) < 0) { - printf("Identify request to %s failed. errno=%d (%s)\n", - path, errno, strerror(errno)); - exit_code = EX_IOERR; - continue; - } - + read_controller_data(fd, &cdata); printf("%6s: %s\n", name, cdata.mn); for (i = 0; i < cdata.nn; i++) { sprintf(name, "nvme%dns%d", ctrlr, i+1); - sprintf(path, "/dev/%s", name); - - fd = open(path, O_RDWR); - if (fd < 0) { - printf("Could not open %s. errno=%d (%s)\n", - path, errno, strerror(errno)); - exit_code = EX_NOPERM; - continue; - } - if (ioctl(fd, NVME_IDENTIFY_NAMESPACE, &nsdata) < 0) { - printf("Identify request to %s failed. " - "errno=%d (%s)\n", path, errno, - strerror(errno)); - exit_code = EX_IOERR; - continue; - } + read_namespace_data(fd, i+1, &nsdata); printf(" %10s (%lldGB)\n", name, nsdata.nsze * @@ -329,11 +355,7 @@ identify_ctrlr(int argc, char *argv[]) exit(EX_NOPERM); } - if (ioctl(fd, NVME_IDENTIFY_CONTROLLER, &cdata) < 0) { - printf("Identify request to %s failed. errno=%d (%s)\n", path, - errno, strerror(errno)); - exit(EX_IOERR); - } + read_controller_data(fd, &cdata); if (hexflag == 1) { if (verboseflag == 1) @@ -360,7 +382,8 @@ identify_ns(int argc, char *argv[]) struct nvme_namespace_data nsdata; struct stat devstat; char path[64]; - int ch, fd, hexflag = 0, hexlength; + char *nsloc; + int ch, fd, hexflag = 0, hexlength, nsid; int verboseflag = 0; while ((ch = getopt(argc, argv, "vx")) != -1) { @@ -376,8 +399,41 @@ identify_ns(int argc, char *argv[]) } } + /* + * Check if the specified device node exists before continuing. + * This is a cleaner check for cases where the correct controller + * is specified, but an invalid namespace on that controller. + */ sprintf(path, "/dev/%s", argv[optind]); + if (stat(path, &devstat) < 0) { + printf("Invalid device node %s. errno=%d (%s)\n", path, errno, + strerror(errno)); + exit(EX_IOERR); + } + nsloc = strstr(argv[optind], "ns"); + if (nsloc == NULL) { + printf("Invalid namepsace %s.\n", argv[optind]); + exit(EX_IOERR); + } + + /* + * Pull the namespace id from the string. +2 skips past the "ns" part + * of the string. + */ + nsid = strtol(nsloc + 2, NULL, 10); + if (nsid == 0 && errno != 0) { + printf("Invalid namespace ID %s.\n", argv[optind]); + exit(EX_IOERR); + } + + /* + * We send IDENTIFY commands to the controller, not the namespace, + * since it is an admin cmd. So the path should only include the + * nvmeX part of the nvmeXnsY string. + */ + sprintf(path, "/dev/"); + strncat(path, argv[optind], nsloc - argv[optind]); if (stat(path, &devstat) < 0) { printf("Invalid device node %s. errno=%d (%s)\n", path, errno, strerror(errno)); @@ -391,11 +447,7 @@ identify_ns(int argc, char *argv[]) exit(EX_NOPERM); } - if (ioctl(fd, NVME_IDENTIFY_NAMESPACE, &nsdata) < 0) { - printf("Identify request to %s failed. errno=%d (%s)\n", path, - errno, strerror(errno)); - exit(EX_IOERR); - } + read_namespace_data(fd, nsid, &nsdata); if (hexflag == 1) { if (verboseflag == 1) -- cgit v1.1 From 8d0d0606e61c046adcc9920f7ddf17cb31c7d01b Mon Sep 17 00:00:00 2001 From: jmg Date: Sun, 14 Apr 2013 16:20:25 +0000 Subject: update information about debugging sysctl... MFC after: 1 week --- sbin/geom/class/nop/gnop.8 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/geom/class/nop/gnop.8 b/sbin/geom/class/nop/gnop.8 index 892212c..2bcbef3 100644 --- a/sbin/geom/class/nop/gnop.8 +++ b/sbin/geom/class/nop/gnop.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 17, 2009 +.Dd April 14, 2013 .Dt GNOP 8 .Os .Sh NAME @@ -139,8 +139,11 @@ Debug level of the .Nm NOP GEOM class. This can be set to a number between 0 and 2 inclusive. -If set to 0 minimal debug information is printed, and if set to 2 the -maximum amount of debug information is printed. +If set to 0, minimal debug information is printed. +If set to 1, basic debug information is logged along with the I/O requests +that were returned as errors. +If set to 2, the maximum amount of debug information is printed including +all I/O requests. .El .Sh EXIT STATUS Exit status is 0 on success, and 1 if the command fails. -- cgit v1.1 From db5542d7fa522a2b2fb4e545b84e44e32a1cc82d Mon Sep 17 00:00:00 2001 From: delphij Date: Mon, 15 Apr 2013 05:39:21 +0000 Subject: Use arc4random() instead of random(). MFC after: 2 weeks --- sbin/growfs/growfs.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'sbin') diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c index 745e9e9..fe49efb 100644 --- a/sbin/growfs/growfs.c +++ b/sbin/growfs/growfs.c @@ -141,14 +141,9 @@ growfs(int fsi, int fso, unsigned int Nflag) uint cylno; int i, j, width; char tmpbuf[100]; - static int randinit = 0; DBG_ENTER; - if (!randinit) { - randinit = 1; - srandomdev(); - } time(&modtime); /* @@ -407,7 +402,7 @@ initcg(int cylno, time_t modtime, int fso, unsigned int Nflag) i += sblock.fs_frag) { dp1 = (struct ufs1_dinode *)(void *)iobuf; for (j = 0; j < INOPB(&sblock); j++) { - dp1->di_gen = random(); + dp1->di_gen = arc4random(); dp1++; } wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), -- cgit v1.1 From 120125784a1ca698c656c6ef5e21e219df994f64 Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 19 Apr 2013 19:45:00 +0000 Subject: Add the Clang specific -Wmissing-variable-declarations to WARNS=6. This compiler flag enforces that that people either mark variables static or use an external declarations for the variable, similar to how -Wmissing-prototypes works for functions. Due to the fact that Yacc/Lex generate code that cannot trivially be changed to not warn because of this (lots of yy* variables), add a NO_WMISSING_VARIABLE_DECLARATIONS that can be used to turn off this specific compiler warning. Announced on: toolchain@ --- sbin/gbde/Makefile | 1 + sbin/geom/class/Makefile.inc | 2 ++ sbin/hastctl/Makefile | 1 + sbin/hastd/Makefile | 1 + sbin/md5/Makefile | 1 + 5 files changed, 6 insertions(+) (limited to 'sbin') diff --git a/sbin/gbde/Makefile b/sbin/gbde/Makefile index 3975eb6..019ee18 100644 --- a/sbin/gbde/Makefile +++ b/sbin/gbde/Makefile @@ -10,6 +10,7 @@ SRCS+= g_bde_lock.c # rijndael-fst.c does evil casting things which can results in warnings, # the test-vectors check out however, so it works right. NO_WCAST_ALIGN= +NO_WMISSING_VARIABLE_DECLARATIONS= CFLAGS+= -I${.CURDIR}/../../sys .PATH: ${.CURDIR}/../../sys/geom/bde \ diff --git a/sbin/geom/class/Makefile.inc b/sbin/geom/class/Makefile.inc index 6f0141e..06b733f 100644 --- a/sbin/geom/class/Makefile.inc +++ b/sbin/geom/class/Makefile.inc @@ -6,6 +6,8 @@ LINKS= ${BINDIR}/geom ${BINDIR}/g${GEOM_CLASS} MAN= g${GEOM_CLASS}.8 SRCS+= geom_${GEOM_CLASS}.c subr.c +NO_WMISSING_VARIABLE_DECLARATIONS= + CFLAGS+= -I${.CURDIR}/../.. .include "../Makefile.inc" diff --git a/sbin/hastctl/Makefile b/sbin/hastctl/Makefile index e7cd9cb..2be817e 100644 --- a/sbin/hastctl/Makefile +++ b/sbin/hastctl/Makefile @@ -21,6 +21,7 @@ MAN= hastctl.8 NO_WFORMAT= NO_WCAST_ALIGN= +NO_WMISSING_VARIABLE_DECLARATIONS= CFLAGS+=-I${.CURDIR}/../hastd CFLAGS+=-DHAVE_CAPSICUM CFLAGS+=-DINET diff --git a/sbin/hastd/Makefile b/sbin/hastd/Makefile index 2a4a9ce..43c7a52 100644 --- a/sbin/hastd/Makefile +++ b/sbin/hastd/Makefile @@ -21,6 +21,7 @@ MAN= hastd.8 hast.conf.5 NO_WFORMAT= NO_WCAST_ALIGN= +NO_WMISSING_VARIABLE_DECLARATIONS= CFLAGS+=-I${.CURDIR} CFLAGS+=-DHAVE_CAPSICUM CFLAGS+=-DPROTO_TCP_DEFAULT_PORT=8457 diff --git a/sbin/md5/Makefile b/sbin/md5/Makefile index c3c5a9f..eabf129 100644 --- a/sbin/md5/Makefile +++ b/sbin/md5/Makefile @@ -13,6 +13,7 @@ MLINKS= md5.1 rmd160.1 \ md5.1 sha256.1 \ md5.1 sha512.1 +NO_WMISSING_VARIABLE_DECLARATIONS= WFORMAT?= 1 DPADD= ${LIBMD} -- cgit v1.1 From e461d813e53d52450ec451244eaa91ff5bc66e31 Mon Sep 17 00:00:00 2001 From: joel Date: Sun, 21 Apr 2013 10:08:33 +0000 Subject: Move EXAMPLES descriptions to before the actual command. PR: 177870 Submitted by: Bjorn Heidotting --- sbin/devfs/devfs.8 | 69 +++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) (limited to 'sbin') diff --git a/sbin/devfs/devfs.8 b/sbin/devfs/devfs.8 index 8c41b13..6e0c210 100644 --- a/sbin/devfs/devfs.8 +++ b/sbin/devfs/devfs.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 21, 2010 +.Dd April 21, 2013 .Dt DEVFS 8 .Os .Sh NAME @@ -269,13 +269,11 @@ the operations are performed on .Pa /dev (this only matters for things that might change the properties of nodes). .Pp -.Dl "devfs ruleset 10" -.Pp Specify that ruleset 10 should be the current ruleset for .Pa /dev -(if it does not already exist, it is created). +(if it does not already exist, it is created): .Pp -.Dl "devfs rule add path speaker mode 666" +.Dl "devfs ruleset 10" .Pp Add a rule that causes all nodes that have a path that matches .Dq Li speaker @@ -291,22 +289,19 @@ be changed if the node is created the rule is added (e.g., the .Pa atspeaker -module is loaded after the above rule is added). +module is loaded after the above rule is added): .Pp -.Dl "devfs rule applyset" +.Dl "devfs rule add path speaker mode 666" .Pp Apply all the rules in the current ruleset to all the existing nodes. -E.g., if the above rule was added after +E.g., if the below rule was added after .Pa /dev/speaker was created, this command will cause its file mode to be changed to 666 -as prescribed by the rule. +as prescribed by the rule: .Pp -.Dl devfs rule add path "snp*" mode 660 group snoopers +.Dl "devfs rule applyset" .Pp -(Quoting the argument to -.Cm path -is often necessary to disable the shell's globbing features.) For all devices with a path that matches .Dq Li snp* , set the file mode to 660 and the GID to @@ -315,53 +310,57 @@ This permits users in the .Dq Li snoopers group to use the .Xr snp 4 -devices. +devices +(quoting the argument to +.Cm path +is often necessary to disable the shell's globbing features): .Pp -.Dl "devfs rule -s 20 add type disk group wheel" +.Dl devfs rule add path "snp*" mode 660 group snoopers .Pp Add a rule to ruleset number 20. Since this ruleset is not the current ruleset for any mount-points, this rule is never applied automatically (unless ruleset 20 becomes -a current ruleset for some mount-point at a later time). -However, it can be applied explicitly, as such: +a current ruleset for some mount-point at a later time): .Pp -.Dl "devfs -m /my/jail/dev rule -s 20 applyset" +.Dl "devfs rule -s 20 add type disk group wheel" .Pp -This will apply all rules in ruleset number 20 to the DEVFS mount on +Explicitly apply all rules in ruleset number 20 to the DEVFS mount on .Pa /my/jail/dev . It does not matter that ruleset 20 is not the current ruleset for that -mount-point; the rules are still applied. +mount-point; the rules are still applied: .Pp -.Dl "devfs rule apply hide" +.Dl "devfs -m /my/jail/dev rule -s 20 applyset" .Pp -Since this rule has no conditions, the action +Since the following rule has no conditions, the action .Pq Cm hide -will be applied to all nodes. -Since hiding all nodes is not very useful, we can undo it: +will be applied to all nodes: .Pp -.Dl "devfs rule apply unhide" +.Dl "devfs rule apply hide" .Pp -which applies +Since hiding all nodes is not very useful, we can undo it. +The following applies .Cm unhide to all the nodes, -causing them to reappear. +causing them to reappear: .Pp -.Dl "devfs rule -s 10 add - < my_rules" +.Dl "devfs rule apply unhide" .Pp Add all the rules from the file .Pa my_rules -to ruleset 10. +to ruleset 10: .Pp -.Dl "devfs rule -s 20 show | devfs rule -s 10 add -" +.Dl "devfs rule -s 10 add - < my_rules" .Pp -Since -.Cm show -outputs valid rules, -this feature can be used to copy rulesets. -The above copies all the rules from ruleset 20 into ruleset 10. +The below copies all the rules from ruleset 20 into ruleset 10. The rule numbers are preserved, but ruleset 10 may already have rules with non-conflicting numbers (these will be preserved). +Since +.Cm show +outputs valid rules, +this feature can be used to copy rulesets: +.Pp +.Dl "devfs rule -s 20 show | devfs rule -s 10 add -" .Sh SEE ALSO .Xr chmod 1 , .Xr jail 2 , -- cgit v1.1 From 761a3d22a7f983f7055431f4d002c59554d8df87 Mon Sep 17 00:00:00 2001 From: trociny Date: Sun, 21 Apr 2013 20:51:53 +0000 Subject: Remove code duplication. --- sbin/hastctl/hastctl.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sbin') diff --git a/sbin/hastctl/hastctl.c b/sbin/hastctl/hastctl.c index 883a298..6fe55fa 100644 --- a/sbin/hastctl/hastctl.c +++ b/sbin/hastctl/hastctl.c @@ -504,18 +504,8 @@ main(int argc, char *argv[]) nv_add_string(nv, argv[ii + 1], "resource%d", ii); break; case CMD_LIST: - /* Obtain verbose status of the given resources. */ - nv = nv_alloc(); - nv_add_uint8(nv, HASTCTL_CMD_STATUS, "cmd"); - if (argc == 0) - nv_add_string(nv, "all", "resource%d", 0); - else { - for (ii = 0; ii < argc; ii++) - nv_add_string(nv, argv[ii], "resource%d", ii); - } - break; case CMD_STATUS: - /* Obtain brief status of the given resources. */ + /* Obtain status of the given resources. */ nv = nv_alloc(); nv_add_uint8(nv, HASTCTL_CMD_STATUS, "cmd"); if (argc == 0) -- cgit v1.1 From bfbcc24aa4cc1a4a1fe92ae99b6212662578f804 Mon Sep 17 00:00:00 2001 From: ed Date: Sun, 21 Apr 2013 22:36:14 +0000 Subject: Unbreak the build of newfs_nandfs. Mark global variables static. While there, make some small style(9) cleanups and remove a variable that is unused. --- sbin/newfs_nandfs/newfs_nandfs.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'sbin') diff --git a/sbin/newfs_nandfs/newfs_nandfs.c b/sbin/newfs_nandfs/newfs_nandfs.c index c996674..5242318 100644 --- a/sbin/newfs_nandfs/newfs_nandfs.c +++ b/sbin/newfs_nandfs/newfs_nandfs.c @@ -80,15 +80,18 @@ struct file_info { struct nandfs_inode *inode; }; -struct file_info user_files[] = -{ - {NANDFS_ROOT_INO, NULL, S_IFDIR | 0755, 0, 1, NULL, NULL}, +static struct file_info user_files[] = { + { NANDFS_ROOT_INO, NULL, S_IFDIR | 0755, 0, 1, NULL, NULL }, }; -struct file_info ifile = {NANDFS_IFILE_INO, NULL, 0, 0, -1, NULL, NULL}; -struct file_info sufile = {NANDFS_SUFILE_INO, NULL, 0, 0, -1, NULL, NULL}; -struct file_info cpfile = {NANDFS_CPFILE_INO, NULL, 0, 0, -1, NULL, NULL}; -struct file_info datfile = {NANDFS_DAT_INO, NULL, 0, 0, -1, NULL, NULL}; +static struct file_info ifile = + { NANDFS_IFILE_INO, NULL, 0, 0, -1, NULL, NULL }; +static struct file_info sufile = + { NANDFS_SUFILE_INO, NULL, 0, 0, -1, NULL, NULL }; +static struct file_info cpfile = + { NANDFS_CPFILE_INO, NULL, 0, 0, -1, NULL, NULL }; +static struct file_info datfile = + { NANDFS_DAT_INO, NULL, 0, 0, -1, NULL, NULL }; struct nandfs_block { LIST_ENTRY(nandfs_block) block_link; @@ -97,7 +100,8 @@ struct nandfs_block { void *data; }; -static LIST_HEAD(, nandfs_block) block_head = LIST_HEAD_INITIALIZER(&block_head); +static LIST_HEAD(, nandfs_block) block_head = + LIST_HEAD_INITIALIZER(&block_head); /* Storage geometry */ static off_t mediasize; @@ -106,8 +110,8 @@ static uint64_t nsegments; static uint64_t erasesize; static uint64_t segsize; -struct nandfs_fsdata fsdata; -struct nandfs_super_block super_block; +static struct nandfs_fsdata fsdata; +static struct nandfs_super_block super_block; static int is_nand; @@ -120,14 +124,13 @@ static uint32_t bad_segments_count = 0; static uint32_t *bad_segments = NULL; static uint8_t fsdata_blocks_state[NANDFS_NFSAREAS]; -u_char *volumelabel = NULL; +static u_char *volumelabel = NULL; -struct nandfs_super_root *sr; +static struct nandfs_super_root *sr; -uint32_t nuserfiles; -uint32_t seg_segsum_size; -uint32_t seg_nblocks; -uint32_t seg_endblock; +static uint32_t nuserfiles; +static uint32_t seg_nblocks; +static uint32_t seg_endblock; #define SIZE_TO_BLOCK(size) (((size) + (blocksize - 1)) / blocksize) -- cgit v1.1 From 13b5f44804e74c0740d22aa1e2f1fbbda1d19278 Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 22 Apr 2013 05:27:13 +0000 Subject: Initialise this to zero before using it to configure the vlangroup information. PR: kern/177871 Submitted by: Luiz Otavio O Souza --- sbin/etherswitchcfg/etherswitchcfg.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sbin') diff --git a/sbin/etherswitchcfg/etherswitchcfg.c b/sbin/etherswitchcfg/etherswitchcfg.c index ea2cec8..b7ee02c 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.c +++ b/sbin/etherswitchcfg/etherswitchcfg.c @@ -139,6 +139,7 @@ set_port_vlangroup(struct cfg *cfg, char *argv[]) v = strtol(argv[1], NULL, 0); if (v < 0 || v >= cfg->info.es_nvlangroups) errx(EX_USAGE, "vlangroup must be between 0 and %d", cfg->info.es_nvlangroups-1); + bzero(&p, sizeof(p)); p.es_port = cfg->unit; if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); -- cgit v1.1 From d7b15c7958aa79252071abde38d22cb8252dd849 Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 22 Apr 2013 05:30:20 +0000 Subject: etherswitchcfg(8) crashes when you don't set vlangroup members. Fix this to require an argument. PR: kern/177872 Submitted by: Luiz Otavio O Souza --- sbin/etherswitchcfg/etherswitchcfg.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/etherswitchcfg/etherswitchcfg.c b/sbin/etherswitchcfg/etherswitchcfg.c index b7ee02c..a3f286e 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.c +++ b/sbin/etherswitchcfg/etherswitchcfg.c @@ -467,8 +467,11 @@ main(int argc, char *argv[]) case MODE_PORT: case MODE_VLANGROUP: for(i=0; cmds[i].name != NULL; i++) { - if (cfg.mode == cmds[i].mode && strcmp(argv[0], cmds[i].name) == 0 - && argc >= cmds[i].args) { + if (cfg.mode == cmds[i].mode && strcmp(argv[0], cmds[i].name) == 0) { + if (argc < (cmds[i].args + 1)) { + printf("%s needs an argument\n", cmds[i].name); + break; + } (cmds[i].f)(&cfg, argv); argc -= cmds[i].args; argv += cmds[i].args; -- cgit v1.1 From 38a1025029f2645291d940ab9f0b7c9c808e2c92 Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 22 Apr 2013 05:52:18 +0000 Subject: Convert over the etherswitch framework to use VLAN IDs per port, rather than VLAN groups. Some chips (eg this rtl8366rb) has a VLAN group per port - you first define a set of VLANs in a vlan group, then you assign a VLAN group to a port. Other chips (eg the AR8xxx switch chips) have a VLAN ID array per port - there's no group per se, just a list of vlans that can be configured. So for now, the switch API will use the latter and rely on drivers doing the heavy lifting if one wishes to use the VLAN group method. Maybe later on both can be supported. PR: kern/177878 PR: kern/177873 Submitted by: Luiz Otavio O Souza Reviewed by: ray --- sbin/etherswitchcfg/etherswitchcfg.8 | 8 ++++---- sbin/etherswitchcfg/etherswitchcfg.c | 13 +++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'sbin') diff --git a/sbin/etherswitchcfg/etherswitchcfg.8 b/sbin/etherswitchcfg/etherswitchcfg.8 index 4f3bc92..88e06f7 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.8 +++ b/sbin/etherswitchcfg/etherswitchcfg.8 @@ -62,9 +62,9 @@ To set the register value, use the form instance.register=value. .Ss port The port command selects one of the ports of the switch. It supports the following commands: -.Bl -tag -width ".Ar vlangroup number" -compact -.It Ar vlangroup number -Sets the VLAN group number that is used to process incoming frames that are not tagged. +.Bl -tag -width ".Ar pvid number" -compact +.It Ar pvid number +Sets the default port VID that is used to process incoming frames that are not tagged. .It Ar media mediaspec Specifies the physical media configuration to be configured for a port. .It Ar mediaopt mediaoption @@ -104,7 +104,7 @@ Configure VLAN group 1 with a VID of 2 and makes ports 0 and 5 members, while excluding all other ports. Port 5 will send and receive tagged frames, while port 0 will be untagged. Incoming untagged frames on port 0 are assigned to vlangroup1. -.Dl # etherswitchcfg vlangroup1 vlan 2 members 0,5t port0 vlangroup 1 +.Dl # etherswitchcfg vlangroup1 vlan 2 members 0,5t port0 pvid 2 .Sh SEE ALSO .Xr etherswitch 4 .Sh HISTORY diff --git a/sbin/etherswitchcfg/etherswitchcfg.c b/sbin/etherswitchcfg/etherswitchcfg.c index a3f286e..3e0b451 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.c +++ b/sbin/etherswitchcfg/etherswitchcfg.c @@ -131,19 +131,20 @@ write_phyregister(struct cfg *cfg, int phy, int reg, int val) } static void -set_port_vlangroup(struct cfg *cfg, char *argv[]) +set_port_vid(struct cfg *cfg, char *argv[]) { int v; etherswitch_port_t p; v = strtol(argv[1], NULL, 0); - if (v < 0 || v >= cfg->info.es_nvlangroups) - errx(EX_USAGE, "vlangroup must be between 0 and %d", cfg->info.es_nvlangroups-1); + if (v < 0 || v > IEEE802DOT1Q_VID_MAX) + errx(EX_USAGE, "pvid must be between 0 and %d", + IEEE802DOT1Q_VID_MAX); bzero(&p, sizeof(p)); p.es_port = cfg->unit; if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); - p.es_vlangroup = v; + p.es_pvid = v; if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0) err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)"); } @@ -302,7 +303,7 @@ print_port(struct cfg *cfg, int port) if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); printf("port%d:\n", port); - printf("\tvlangroup: %d\n", p.es_vlangroup); + printf("\tpvid: %d\n", p.es_pvid); printf("\tmedia: "); print_media_word(p.es_ifmr.ifm_current, 1); if (p.es_ifmr.ifm_active != p.es_ifmr.ifm_current) { @@ -506,7 +507,7 @@ main(int argc, char *argv[]) } static struct cmds cmds[] = { - { MODE_PORT, "vlangroup", 1, set_port_vlangroup }, + { MODE_PORT, "pvid", 1, set_port_vid }, { MODE_PORT, "media", 1, set_port_media }, { MODE_PORT, "mediaopt", 1, set_port_mediaopt }, { MODE_VLANGROUP, "vlan", 1, set_vlangroup_vid }, -- cgit v1.1 From 4373fbb501b6b8d794e42adb82c98df282ba17f7 Mon Sep 17 00:00:00 2001 From: jhb Date: Mon, 22 Apr 2013 15:02:32 +0000 Subject: Use a higher TTL (128) for DHCP packets. This matches the ISC DHCP client. PR: bin/170279 MFC after: 1 week --- sbin/dhclient/packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/dhclient/packet.c b/sbin/dhclient/packet.c index 2e90cc8..b7a4f21 100644 --- a/sbin/dhclient/packet.c +++ b/sbin/dhclient/packet.c @@ -128,7 +128,7 @@ assemble_udp_ip_header(unsigned char *buf, int *bufix, u_int32_t from, ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len); ip.ip_id = 0; ip.ip_off = 0; - ip.ip_ttl = 16; + ip.ip_ttl = 128; ip.ip_p = IPPROTO_UDP; ip.ip_sum = 0; ip.ip_src.s_addr = from; -- cgit v1.1 From a0b7a4476c1eaa2769188f5463c0c9c31caec91f Mon Sep 17 00:00:00 2001 From: joel Date: Mon, 22 Apr 2013 17:38:26 +0000 Subject: Minor clarificiation. PR: 177455 --- sbin/geom/class/label/glabel.8 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/geom/class/label/glabel.8 b/sbin/geom/class/label/glabel.8 index fff9205..c1c7bc4 100644 --- a/sbin/geom/class/label/glabel.8 +++ b/sbin/geom/class/label/glabel.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 13, 2009 +.Dd April 22, 2013 .Dt GLABEL 8 .Os .Sh NAME @@ -81,7 +81,7 @@ The method uses on-disk metadata to store the label and detect it automatically in the future. .Pp -This class also provides volume label detection for file systems. +This GEOM class also provides volume label detection for file systems. Those labels cannot be set with .Nm , but must be set with the appropriate file system utility, e.g.\& for UFS -- cgit v1.1 From e04d23c5df0966fb23528fe546616c55361dd54f Mon Sep 17 00:00:00 2001 From: mckusick Date: Tue, 23 Apr 2013 06:37:50 +0000 Subject: Fix error check. Submitted by: Andrey Chernov (ache@) MFC after: 3 days --- sbin/tunefs/tunefs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c index 0671d1d..2ad01c0 100644 --- a/sbin/tunefs/tunefs.c +++ b/sbin/tunefs/tunefs.c @@ -174,7 +174,7 @@ main(int argc, char *argv[]) found_arg = 1; name = "space to hold for metadata blocks"; kvalue = atoi(optarg); - if (mvalue < 0) + if (kvalue < 0) errx(10, "bad %s (%s)", name, optarg); kflag = 1; break; -- cgit v1.1 From 2f83e51ae7e4463d05a7666abbff4f7f9f9779b4 Mon Sep 17 00:00:00 2001 From: smh Date: Thu, 25 Apr 2013 14:11:38 +0000 Subject: Adds Host Protected Area (HPA) support for ATA disks to camcontrol Reviewed by: mav Approved by: pjd (mentor) MFC after: 2 weeks --- sbin/camcontrol/camcontrol.8 | 105 ++++++- sbin/camcontrol/camcontrol.c | 682 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 785 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 index 7a13aa4..f9e9663 100644 --- a/sbin/camcontrol/camcontrol.8 +++ b/sbin/camcontrol/camcontrol.8 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 4, 2012 +.Dd April 24, 2013 .Dt CAMCONTROL 8 .Os .Sh NAME @@ -243,6 +243,18 @@ .Op Fl U Ar user|master .Op Fl y .Nm +.Ic hpa +.Op device id +.Op generic args +.Op Fl f +.Op Fl l +.Op Fl P +.Op Fl p Ar pwd +.Op Fl q +.Op Fl s Ar max_sectors +.Op Fl U Ar pwd +.Op Fl y +.Nm .Ic help .Sh DESCRIPTION The @@ -1205,6 +1217,73 @@ password for the specified user the command will fail. .Pp The password in all cases is limited to 32 characters, longer passwords will fail. +.It Ic hpa +Update or report Host Protected Area details. +By default +.Nm +will print out the HPA support and associated settings of the device. +The +.Ic hpa +command takes several optional arguments: +.Bl -tag -width 0n +.It Fl f +.Pp +Freeze the HPA configuration of the specified device. +.Pp +After command completion any other commands that update the HPA configuration +shall be command aborted. +Frozen mode is disabled by power-off or hardware reset. +.It Fl l +.Pp +Lock the HPA configuration of the device until a successful call to unlock or +the next power-on reset occurs. +.It Fl P +.Pp +Make the HPA max sectors persist across power-on reset or a hardware reset. +This must be used in combination with +.Fl s Ar max_sectors +. +.It Fl p Ar pwd +.Pp +Set the HPA configuration password required for unlock calls. +.It Fl q +.Pp +Be quiet, do not print any status messages. +This option will not disable the questions. +To disable questions, use the +.Fl y +argument, below. +.It Fl s Ar max_sectors +.Pp +Configures the maximum user accessible sectors of the device. +This will change the number of sectors the device reports. +.Pp +.Em WARNING! WARNING! WARNING! +.Pp +Changing the max sectors of a device using this option will make the data on +the device beyond the specified value inaccessible. +.Pp +Only one successful +.Fl s Ar max_sectors +call can be made without a power-on reset or a hardware reset of the device. +.It Fl U Ar pwd +.Pp +Unlock the HPA configuration of the specified device using the given password. +If the password specified doesn't match the password configured via +.Fl p Ar pwd +the command will fail. +.Pp +After 5 failed unlock calls, due to password miss-match, the device will refuse +additional unlock calls until after a power-on reset. +.It Fl y +.Pp +Confirm yes to dangerous options such as +.Fl e +without prompting for confirmation +.Pp +.El +The password for all HPA commands is limited to 32 characters, longer passwords +will fail. .It Ic fwdownload Program firmware of the named SCSI device using the image file provided. .Pp @@ -1397,6 +1476,30 @@ data from the device, so backup your data before using! .Pp This command can be used used against an SSD drive to restoring it to factory default write performance. +.Pp +.Bd -literal -offset indent +camcontrol hpa ada0 +.Ed +.Pp +Report HPA support and settings for ada0 (also reported via +identify). +.Pp +.Bd -literal -offset indent +camcontrol hpa ada0 -s 10240 +.Ed +.Pp +Enables HPA on ada0 setting the maximum reported sectors to 10240. +.Pp +.Em WARNING! WARNING! WARNING! +.Pp +This will +.Em PREVENT ACCESS +to all data on the device beyond this limit until HPA is disabled by setting +HPA to native max sectors of the device, which can only be done after a +power-on or hardware reset! +.Pp +.Em DO NOT +use this on a device which has an active filesystem! .Sh SEE ALSO .Xr cam 3 , .Xr cam_cdbparse 3 , diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 90ceb9a..7f13520 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -45,6 +45,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifndef MINIMALISTIC +#include +#include +#endif #include #include @@ -88,7 +92,8 @@ typedef enum { CAM_CMD_SMP_PHYLIST = 0x0000001a, CAM_CMD_SMP_MANINFO = 0x0000001b, CAM_CMD_DOWNLOAD_FW = 0x0000001c, - CAM_CMD_SECURITY = 0x0000001d + CAM_CMD_SECURITY = 0x0000001d, + CAM_CMD_HPA = 0x0000001e } cam_cmdmask; typedef enum { @@ -135,6 +140,29 @@ struct camcontrol_opts { }; #ifndef MINIMALISTIC +struct ata_res_pass16 { + u_int16_t reserved[5]; + u_int8_t flags; + u_int8_t error; + u_int8_t sector_count_exp; + u_int8_t sector_count; + u_int8_t lba_low_exp; + u_int8_t lba_low; + u_int8_t lba_mid_exp; + u_int8_t lba_mid; + u_int8_t lba_high_exp; + u_int8_t lba_high; + u_int8_t device; + u_int8_t status; +}; + +struct ata_set_max_pwd +{ + u_int16_t reserved1; + u_int8_t password[32]; + u_int16_t reserved2[239]; +}; + static const char scsicmd_opts[] = "a:c:dfi:o:r"; static const char readdefect_opts[] = "f:GP"; static const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; @@ -186,6 +214,7 @@ static struct camcontrol_opts option_table[] = { {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""}, {"fwdownload", CAM_CMD_DOWNLOAD_FW, CAM_ARG_NONE, "f:ys"}, {"security", CAM_CMD_SECURITY, CAM_ARG_NONE, "d:e:fh:k:l:qs:T:U:y"}, + {"hpa", CAM_CMD_HPA, CAM_ARG_NONE, "Pflp:qs:U:y"}, #endif /* MINIMALISTIC */ {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, @@ -280,6 +309,8 @@ static int atapm(struct cam_device *device, int argc, char **argv, char *combinedopt, int retry_count, int timeout); static int atasecurity(struct cam_device *device, int retry_count, int timeout, int argc, char **argv, char *combinedopt); +static int atahpa(struct cam_device *device, int retry_count, int timeout, + int argc, char **argv, char *combinedopt); #endif /* MINIMALISTIC */ #ifndef min @@ -1128,6 +1159,38 @@ xferrate_bailout: } static void +atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header) +{ + u_int32_t lbasize = (u_int32_t)parm->lba_size_1 | + ((u_int32_t)parm->lba_size_2 << 16); + + u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) | + ((u_int64_t)parm->lba_size48_2 << 16) | + ((u_int64_t)parm->lba_size48_3 << 32) | + ((u_int64_t)parm->lba_size48_4 << 48); + + if (header) { + printf("\nFeature " + "Support Enabled Value\n"); + } + + printf("Host Protected Area (HPA) "); + if (parm->support.command1 & ATA_SUPPORT_PROTECTED) { + u_int64_t lba = lbasize48 ? lbasize48 : lbasize; + printf("yes %s %ju/%ju\n", (hpasize > lba) ? "yes" : "no ", + lba, hpasize); + + printf("HPA - Security "); + if (parm->support.command1 & ATA_SUPPORT_MAXSECURITY) + printf("yes\n"); + else + printf("no\n"); + } else { + printf("no\n"); + } +} + +static void atacapprint(struct ata_params *parm) { u_int32_t lbasize = (u_int32_t)parm->lba_size_1 | @@ -1554,6 +1617,83 @@ ata_do_28bit_cmd(struct cam_device *device, union ccb *ccb, int retries, return ata_cam_send(device, ccb, quiet); } +static int +ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries, + u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags, + u_int8_t tag_action, u_int8_t command, u_int8_t features, + u_int64_t lba, u_int8_t sector_count, u_int8_t *data_ptr, + u_int16_t dxfer_len, int timeout, int force48bit) +{ + int retval; + + retval = ata_try_pass_16(device); + if (retval == -1) + return (1); + + if (retval == 1) { + int error; + + /* Try using SCSI Passthrough */ + error = ata_do_pass_16(device, ccb, retries, flags, protocol, + ata_flags, tag_action, command, features, + lba, sector_count, data_ptr, dxfer_len, + timeout, 0); + + if (ata_flags & AP_FLAG_CHK_COND) { + /* Decode ata_res from sense data */ + struct ata_res_pass16 *res_pass16; + struct ata_res *res; + u_int i; + u_int16_t *ptr; + + /* sense_data is 4 byte aligned */ + ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data; + for (i = 0; i < sizeof(*res_pass16) / 2; i++) + ptr[i] = le16toh(ptr[i]); + + /* sense_data is 4 byte aligned */ + res_pass16 = (struct ata_res_pass16 *)(uintptr_t) + &ccb->csio.sense_data; + res = &ccb->ataio.res; + res->flags = res_pass16->flags; + res->status = res_pass16->status; + res->error = res_pass16->error; + res->lba_low = res_pass16->lba_low; + res->lba_mid = res_pass16->lba_mid; + res->lba_high = res_pass16->lba_high; + res->device = res_pass16->device; + res->lba_low_exp = res_pass16->lba_low_exp; + res->lba_mid_exp = res_pass16->lba_mid_exp; + res->lba_high_exp = res_pass16->lba_high_exp; + res->sector_count = res_pass16->sector_count; + res->sector_count_exp = res_pass16->sector_count_exp; + } + + return (error); + } + + bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) - + sizeof(struct ccb_hdr)); + cam_fill_ataio(&ccb->ataio, + retries, + NULL, + flags, + tag_action, + data_ptr, + dxfer_len, + timeout); + + if (force48bit || lba > ATA_MAX_28BIT_LBA) + ata_48bit_cmd(&ccb->ataio, command, features, lba, sector_count); + else + ata_28bit_cmd(&ccb->ataio, command, features, lba, sector_count); + + if (ata_flags & AP_FLAG_CHK_COND) + ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT; + + return ata_cam_send(device, ccb, 0); +} + static void dump_data(uint16_t *ptr, uint32_t len) { @@ -1571,6 +1711,278 @@ dump_data(uint16_t *ptr, uint32_t len) } static int +atahpa_proc_resp(struct cam_device *device, union ccb *ccb, + int is48bit, u_int64_t *hpasize) +{ + struct ata_res *res; + + res = &ccb->ataio.res; + if (res->status & ATA_STATUS_ERROR) { + if (arglist & CAM_ARG_VERBOSE) { + cam_error_print(device, ccb, CAM_ESF_ALL, + CAM_EPF_ALL, stderr); + printf("error = 0x%02x, sector_count = 0x%04x, " + "device = 0x%02x, status = 0x%02x\n", + res->error, res->sector_count, + res->device, res->status); + } + + if (res->error & ATA_ERROR_ID_NOT_FOUND) { + warnx("Max address has already been set since " + "last power-on or hardware reset"); + } + + return (1); + } + + if (arglist & CAM_ARG_VERBOSE) { + fprintf(stdout, "%s%d: Raw native max data:\n", + device->device_name, device->dev_unit_num); + /* res is 4 byte aligned */ + dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res)); + + printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, " + "status = 0x%02x\n", res->error, res->sector_count, + res->device, res->status); + } + + if (hpasize != NULL) { + if (is48bit) { + *hpasize = (((u_int64_t)((res->lba_high_exp << 16) | + (res->lba_mid_exp << 8) | res->lba_low_exp) << 24) | + ((res->lba_high << 16) | (res->lba_mid << 8) | + res->lba_low)) + 1; + } else { + *hpasize = (((res->device & 0x0f) << 24) | + (res->lba_high << 16) | (res->lba_mid << 8) | + res->lba_low) + 1; + } + } + + return (0); +} + +static int +ata_read_native_max(struct cam_device *device, int retry_count, + u_int32_t timeout, union ccb *ccb, + struct ata_params *parm, u_int64_t *hpasize) +{ + int error; + u_int cmd, is48bit; + u_int8_t protocol; + + is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48; + protocol = AP_PROTO_NON_DATA; + + if (is48bit) { + cmd = ATA_READ_NATIVE_MAX_ADDRESS48; + protocol |= AP_EXTEND; + } else { + cmd = ATA_READ_NATIVE_MAX_ADDRESS; + } + + error = ata_do_cmd(device, + ccb, + retry_count, + /*flags*/CAM_DIR_IN, + /*protocol*/protocol, + /*ata_flags*/AP_FLAG_CHK_COND, + /*tag_action*/MSG_SIMPLE_Q_TAG, + /*command*/cmd, + /*features*/0, + /*lba*/0, + /*sector_count*/0, + /*data_ptr*/NULL, + /*dxfer_len*/0, + timeout ? timeout : 1000, + is48bit); + + if (error) + return (error); + + return atahpa_proc_resp(device, ccb, is48bit, hpasize); +} + +static int +atahpa_set_max(struct cam_device *device, int retry_count, + u_int32_t timeout, union ccb *ccb, + int is48bit, u_int64_t maxsize, int persist) +{ + int error; + u_int cmd; + u_int8_t protocol; + + protocol = AP_PROTO_NON_DATA; + + if (is48bit) { + cmd = ATA_SET_MAX_ADDRESS48; + protocol |= AP_EXTEND; + } else { + cmd = ATA_SET_MAX_ADDRESS; + } + + /* lba's are zero indexed so the max lba is requested max - 1 */ + if (maxsize) + maxsize--; + + error = ata_do_cmd(device, + ccb, + retry_count, + /*flags*/CAM_DIR_OUT, + /*protocol*/protocol, + /*ata_flags*/AP_FLAG_CHK_COND, + /*tag_action*/MSG_SIMPLE_Q_TAG, + /*command*/cmd, + /*features*/ATA_HPA_FEAT_MAX_ADDR, + /*lba*/maxsize, + /*sector_count*/persist, + /*data_ptr*/NULL, + /*dxfer_len*/0, + timeout ? timeout : 1000, + is48bit); + + if (error) + return (error); + + return atahpa_proc_resp(device, ccb, is48bit, NULL); +} + +static int +atahpa_password(struct cam_device *device, int retry_count, + u_int32_t timeout, union ccb *ccb, + int is48bit, struct ata_set_max_pwd *pwd) +{ + int error; + u_int cmd; + u_int8_t protocol; + + protocol = AP_PROTO_PIO_OUT; + cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; + + error = ata_do_cmd(device, + ccb, + retry_count, + /*flags*/CAM_DIR_OUT, + /*protocol*/protocol, + /*ata_flags*/AP_FLAG_CHK_COND, + /*tag_action*/MSG_SIMPLE_Q_TAG, + /*command*/cmd, + /*features*/ATA_HPA_FEAT_SET_PWD, + /*lba*/0, + /*sector_count*/0, + /*data_ptr*/(u_int8_t*)pwd, + /*dxfer_len*/sizeof(struct ata_set_max_pwd), + timeout ? timeout : 1000, + is48bit); + + if (error) + return (error); + + return atahpa_proc_resp(device, ccb, is48bit, NULL); +} + +static int +atahpa_lock(struct cam_device *device, int retry_count, + u_int32_t timeout, union ccb *ccb, int is48bit) +{ + int error; + u_int cmd; + u_int8_t protocol; + + protocol = AP_PROTO_NON_DATA; + cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; + + error = ata_do_cmd(device, + ccb, + retry_count, + /*flags*/CAM_DIR_OUT, + /*protocol*/protocol, + /*ata_flags*/AP_FLAG_CHK_COND, + /*tag_action*/MSG_SIMPLE_Q_TAG, + /*command*/cmd, + /*features*/ATA_HPA_FEAT_LOCK, + /*lba*/0, + /*sector_count*/0, + /*data_ptr*/NULL, + /*dxfer_len*/0, + timeout ? timeout : 1000, + is48bit); + + if (error) + return (error); + + return atahpa_proc_resp(device, ccb, is48bit, NULL); +} + +static int +atahpa_unlock(struct cam_device *device, int retry_count, + u_int32_t timeout, union ccb *ccb, + int is48bit, struct ata_set_max_pwd *pwd) +{ + int error; + u_int cmd; + u_int8_t protocol; + + protocol = AP_PROTO_PIO_OUT; + cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; + + error = ata_do_cmd(device, + ccb, + retry_count, + /*flags*/CAM_DIR_OUT, + /*protocol*/protocol, + /*ata_flags*/AP_FLAG_CHK_COND, + /*tag_action*/MSG_SIMPLE_Q_TAG, + /*command*/cmd, + /*features*/ATA_HPA_FEAT_UNLOCK, + /*lba*/0, + /*sector_count*/0, + /*data_ptr*/(u_int8_t*)pwd, + /*dxfer_len*/sizeof(struct ata_set_max_pwd), + timeout ? timeout : 1000, + is48bit); + + if (error) + return (error); + + return atahpa_proc_resp(device, ccb, is48bit, NULL); +} + +static int +atahpa_freeze_lock(struct cam_device *device, int retry_count, + u_int32_t timeout, union ccb *ccb, int is48bit) +{ + int error; + u_int cmd; + u_int8_t protocol; + + protocol = AP_PROTO_NON_DATA; + cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS; + + error = ata_do_cmd(device, + ccb, + retry_count, + /*flags*/CAM_DIR_OUT, + /*protocol*/protocol, + /*ata_flags*/AP_FLAG_CHK_COND, + /*tag_action*/MSG_SIMPLE_Q_TAG, + /*command*/cmd, + /*features*/ATA_HPA_FEAT_FREEZE, + /*lba*/0, + /*sector_count*/0, + /*data_ptr*/NULL, + /*dxfer_len*/0, + timeout ? timeout : 1000, + is48bit); + + if (error) + return (error); + + return atahpa_proc_resp(device, ccb, is48bit, NULL); +} + + +static int ata_do_identify(struct cam_device *device, int retry_count, int timeout, union ccb *ccb, struct ata_params** ident_bufp) { @@ -1701,6 +2113,7 @@ ataidentify(struct cam_device *device, int retry_count, int timeout) { union ccb *ccb; struct ata_params *ident_buf; + u_int64_t hpasize; if ((ccb = cam_getccb(device)) == NULL) { warnx("couldn't allocate CCB"); @@ -1712,10 +2125,21 @@ ataidentify(struct cam_device *device, int retry_count, int timeout) return (1); } + if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) { + if (ata_read_native_max(device, retry_count, timeout, ccb, + ident_buf, &hpasize) != 0) { + cam_freeccb(ccb); + return (1); + } + } else { + hpasize = 0; + } + printf("%s%d: ", device->device_name, device->dev_unit_num); ata_print_ident(ident_buf); camxferrate(device); atacapprint(ident_buf); + atahpa_print(ident_buf, hpasize, 0); free(ident_buf); cam_freeccb(ccb); @@ -2044,6 +2468,245 @@ ata_getpwd(u_int8_t *passwd, int max, char opt) return (0); } +enum { + ATA_HPA_ACTION_PRINT, + ATA_HPA_ACTION_SET_MAX, + ATA_HPA_ACTION_SET_PWD, + ATA_HPA_ACTION_LOCK, + ATA_HPA_ACTION_UNLOCK, + ATA_HPA_ACTION_FREEZE_LOCK +}; + +static int +atahpa_set_confirm(struct cam_device *device, struct ata_params* ident_buf, + u_int64_t maxsize, int persist) +{ + printf("\nYou are about to configure HPA to limit the user accessible\n" + "sectors to %ju %s on the device:\n%s%d,%s%d: ", maxsize, + persist ? "persistently" : "temporarily", + device->device_name, device->dev_unit_num, + device->given_dev_name, device->given_unit_number); + ata_print_ident(ident_buf); + + for(;;) { + char str[50]; + printf("\nAre you SURE you want to configure HPA? (yes/no) "); + + if (NULL != fgets(str, sizeof(str), stdin)) { + if (0 == strncasecmp(str, "yes", 3)) { + return (1); + } else if (0 == strncasecmp(str, "no", 2)) { + return (0); + } else { + printf("Please answer \"yes\" or " + "\"no\"\n"); + } + } + } + + /* NOTREACHED */ + return (0); +} + +static int +atahpa(struct cam_device *device, int retry_count, int timeout, + int argc, char **argv, char *combinedopt) +{ + union ccb *ccb; + struct ata_params *ident_buf; + struct ccb_getdev cgd; + struct ata_set_max_pwd pwd; + int error, confirm, quiet, c, action, actions, setpwd, persist; + int security, is48bit, pwdsize; + u_int64_t hpasize, maxsize; + + actions = 0; + setpwd = 0; + confirm = 0; + quiet = 0; + maxsize = 0; + persist = 0; + security = 0; + + memset(&pwd, 0, sizeof(pwd)); + + /* default action is to print hpa information */ + action = ATA_HPA_ACTION_PRINT; + pwdsize = sizeof(pwd.password); + + while ((c = getopt(argc, argv, combinedopt)) != -1) { + switch(c){ + case 's': + action = ATA_HPA_ACTION_SET_MAX; + maxsize = strtoumax(optarg, NULL, 0); + actions++; + break; + + case 'p': + if (ata_getpwd(pwd.password, pwdsize, c) != 0) + return (1); + action = ATA_HPA_ACTION_SET_PWD; + security = 1; + actions++; + break; + + case 'l': + action = ATA_HPA_ACTION_LOCK; + security = 1; + actions++; + break; + + case 'U': + if (ata_getpwd(pwd.password, pwdsize, c) != 0) + return (1); + action = ATA_HPA_ACTION_UNLOCK; + security = 1; + actions++; + break; + + case 'f': + action = ATA_HPA_ACTION_FREEZE_LOCK; + security = 1; + actions++; + break; + + case 'P': + persist = 1; + break; + + case 'y': + confirm++; + break; + + case 'q': + quiet++; + break; + } + } + + if (actions > 1) { + warnx("too many hpa actions specified"); + return (1); + } + + if (get_cgd(device, &cgd) != 0) { + warnx("couldn't get CGD"); + return (1); + } + + ccb = cam_getccb(device); + if (ccb == NULL) { + warnx("couldn't allocate CCB"); + return (1); + } + + error = ata_do_identify(device, retry_count, timeout, ccb, &ident_buf); + if (error != 0) { + cam_freeccb(ccb); + return (1); + } + + if (quiet == 0) { + printf("%s%d: ", device->device_name, device->dev_unit_num); + ata_print_ident(ident_buf); + camxferrate(device); + } + + if (action == ATA_HPA_ACTION_PRINT) { + error = ata_read_native_max(device, retry_count, timeout, ccb, + ident_buf, &hpasize); + if (error == 0) + atahpa_print(ident_buf, hpasize, 1); + + cam_freeccb(ccb); + free(ident_buf); + return (error); + } + + if (!(ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)) { + warnx("HPA is not supported by this device"); + cam_freeccb(ccb); + free(ident_buf); + return (1); + } + + if (security && !(ident_buf->support.command1 & ATA_SUPPORT_MAXSECURITY)) { + warnx("HPA Security is not supported by this device"); + cam_freeccb(ccb); + free(ident_buf); + return (1); + } + + is48bit = ident_buf->support.command2 & ATA_SUPPORT_ADDRESS48; + + /* + * The ATA spec requires: + * 1. Read native max addr is called directly before set max addr + * 2. Read native max addr is NOT called before any other set max call + */ + switch(action) { + case ATA_HPA_ACTION_SET_MAX: + if (confirm == 0 && + atahpa_set_confirm(device, ident_buf, maxsize, + persist) == 0) { + cam_freeccb(ccb); + free(ident_buf); + return (1); + } + + error = ata_read_native_max(device, retry_count, timeout, + ccb, ident_buf, &hpasize); + if (error == 0) { + error = atahpa_set_max(device, retry_count, timeout, + ccb, is48bit, maxsize, persist); + if (error == 0) { + /* redo identify to get new lba values */ + error = ata_do_identify(device, retry_count, + timeout, ccb, + &ident_buf); + atahpa_print(ident_buf, hpasize, 1); + } + } + break; + + case ATA_HPA_ACTION_SET_PWD: + error = atahpa_password(device, retry_count, timeout, + ccb, is48bit, &pwd); + if (error == 0) + printf("HPA password has been set\n"); + break; + + case ATA_HPA_ACTION_LOCK: + error = atahpa_lock(device, retry_count, timeout, + ccb, is48bit); + if (error == 0) + printf("HPA has been locked\n"); + break; + + case ATA_HPA_ACTION_UNLOCK: + error = atahpa_unlock(device, retry_count, timeout, + ccb, is48bit, &pwd); + if (error == 0) + printf("HPA has been unlocked\n"); + break; + + case ATA_HPA_ACTION_FREEZE_LOCK: + error = atahpa_freeze_lock(device, retry_count, timeout, + ccb, is48bit); + if (error == 0) + printf("HPA has been frozen\n"); + break; + + default: + errx(1, "Option currently not supported"); + } + + cam_freeccb(ccb); + free(ident_buf); + + return (error); +} + static int atasecurity(struct cam_device *device, int retry_count, int timeout, int argc, char **argv, char *combinedopt) @@ -6702,6 +7365,8 @@ usage(int printlong) " <-d pwd | -e pwd | -f | -h pwd | -k pwd>\n" " [-l ] [-q] [-s pwd] [-T timeout]\n" " [-U ] [-y]\n" +" camcontrol hpa [dev_id][generic args] [-f] [-l] [-P] [-p pwd]\n" +" [-q] [-s max_sectors] [-U pwd] [-y]\n" #endif /* MINIMALISTIC */ " camcontrol help\n"); if (!printlong) @@ -6852,6 +7517,17 @@ usage(int printlong) "-T timeout overrides the timeout (seconds) used for erase operation\n" "-U specifies which user to set: user or master\n" "-y don't ask any questions\n" +"hpa arguments:\n" +"-f freeze the HPA configuration of the device\n" +"-l lock the HPA configuration of the device\n" +"-P make the HPA max sectors persist\n" +"-p pwd Set the HPA configuration password required for unlock\n" +" calls\n" +"-q be quiet, do not print any status messages\n" +"-s sectors configures the maximum user accessible sectors of the\n" +" device\n" +"-U pwd unlock the HPA configuration of the device\n" +"-y don't ask any questions\n" ); #endif /* MINIMALISTIC */ } @@ -7076,6 +7752,10 @@ main(int argc, char **argv) case CAM_CMD_DEVLIST: error = getdevlist(cam_dev); break; + case CAM_CMD_HPA: + error = atahpa(cam_dev, retry_count, timeout, + argc, argv, combinedopt); + break; #endif /* MINIMALISTIC */ case CAM_CMD_DEVTREE: error = getdevtree(); -- cgit v1.1 From e31cb18360919b0c74c607ca1d3983020b8e033f Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 25 Apr 2013 16:34:04 +0000 Subject: Don't free memory that is going to be used as error string. PR: bin/178121 Submitted by: Garrett Cooper --- sbin/ifconfig/iflagg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/ifconfig/iflagg.c b/sbin/ifconfig/iflagg.c index a474729..29b8574 100644 --- a/sbin/ifconfig/iflagg.c +++ b/sbin/ifconfig/iflagg.c @@ -98,10 +98,8 @@ setlagghash(const char *val, int d, int s, const struct afswtch *afp) rf.rf_flags |= LAGG_F_HASHL3; else if (strcmp(tok, "l4") == 0) rf.rf_flags |= LAGG_F_HASHL4; - else { - free(str); + else errx(1, "Invalid lagghash option: %s", tok); - } } free(str); if (rf.rf_flags == 0) -- cgit v1.1 From 4e9b65bc12036784e379d8920ccaef545812074d Mon Sep 17 00:00:00 2001 From: joel Date: Thu, 25 Apr 2013 20:23:22 +0000 Subject: mdoc: remove superfluous paragraph macro. --- sbin/camcontrol/camcontrol.8 | 2 -- 1 file changed, 2 deletions(-) (limited to 'sbin') diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 index f9e9663..df0b3e7 100644 --- a/sbin/camcontrol/camcontrol.8 +++ b/sbin/camcontrol/camcontrol.8 @@ -1476,14 +1476,12 @@ data from the device, so backup your data before using! .Pp This command can be used used against an SSD drive to restoring it to factory default write performance. -.Pp .Bd -literal -offset indent camcontrol hpa ada0 .Ed .Pp Report HPA support and settings for ada0 (also reported via identify). -.Pp .Bd -literal -offset indent camcontrol hpa ada0 -s 10240 .Ed -- cgit v1.1 From 2f761a801bd037951c90dbb5521c75ef53954678 Mon Sep 17 00:00:00 2001 From: asomers Date: Fri, 26 Apr 2013 19:49:37 +0000 Subject: According to devctl(4), clients must read events whole; they may not piece them together from multiple reads(). It's as if /dev/devctl is a datagram device instead of a stream device. However, devd's internal buffer was too small (1025 bytes) to read an entire ereport.fs.zfs.checksum event (variable, up to ~1300 bytes). This commit enlarges the buffer to 8k. Reviewed by: imp Approved by: ken (mentor) MFC after: 2 weeks --- sbin/devd/devd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/devd/devd.h b/sbin/devd/devd.h index a8d113b..becfe82 100644 --- a/sbin/devd/devd.h +++ b/sbin/devd/devd.h @@ -53,6 +53,6 @@ int yyparse(void); __END_DECLS #define PATH_DEVCTL "/dev/devctl" -#define DEVCTL_MAXBUF 1025 +#define DEVCTL_MAXBUF 8192 #endif /* DEVD_H */ -- cgit v1.1 From e8028497402579e4a7f85d8714e9038ace9d44d2 Mon Sep 17 00:00:00 2001 From: ed Date: Sat, 27 Apr 2013 05:01:29 +0000 Subject: Use C11 instead of our non-standard . Reviewed by: pjd --- sbin/hastd/primary.c | 13 +++++++------ sbin/hastd/refcnt.h | 19 ++++++++++++++----- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'sbin') diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c index a9dfa2b..92d1d9e 100644 --- a/sbin/hastd/primary.c +++ b/sbin/hastd/primary.c @@ -78,7 +78,7 @@ struct hio { * kernel. Each component has to decrease this counter by one * even on failure. */ - unsigned int hio_countdown; + refcnt_t hio_countdown; /* * Each component has a place to store its own error. * Once the request is handled by all components we can decide if the @@ -415,7 +415,7 @@ init_environment(struct hast_resource *res __unused) "Unable to allocate %zu bytes of memory for hio request.", sizeof(*hio)); } - hio->hio_countdown = 0; + refcnt_init(&hio->hio_countdown, 0); hio->hio_errors = malloc(sizeof(hio->hio_errors[0]) * ncomps); if (hio->hio_errors == NULL) { primary_exitx(EX_TEMPFAIL, @@ -1300,11 +1300,12 @@ ggate_recv_thread(void *arg) } pjdlog_debug(2, "ggate_recv: (%p) Moving request to the send queues.", hio); - hio->hio_countdown = ncomps; if (hio->hio_replication == HAST_REPLICATION_MEMSYNC && ggio->gctl_cmd == BIO_WRITE) { /* Each remote request needs two responses in memsync. */ - hio->hio_countdown++; + refcnt_init(&hio->hio_countdown, ncomps + 1); + } else { + refcnt_init(&hio->hio_countdown, ncomps); } for (ii = ncomp; ii < ncomps; ii++) QUEUE_INSERT1(hio, send, ii); @@ -2139,7 +2140,7 @@ sync_thread(void *arg __unused) ncomp = 1; } mtx_unlock(&metadata_lock); - hio->hio_countdown = 1; + refcnt_init(&hio->hio_countdown, 1); QUEUE_INSERT1(hio, send, ncomp); /* @@ -2189,7 +2190,7 @@ sync_thread(void *arg __unused) pjdlog_debug(2, "sync: (%p) Moving request to the send queue.", hio); - hio->hio_countdown = 1; + refcnt_init(&hio->hio_countdown, 1); QUEUE_INSERT1(hio, send, ncomp); /* diff --git a/sbin/hastd/refcnt.h b/sbin/hastd/refcnt.h index a989df0..5e3fb34 100644 --- a/sbin/hastd/refcnt.h +++ b/sbin/hastd/refcnt.h @@ -32,24 +32,33 @@ #ifndef __REFCNT_H__ #define __REFCNT_H__ -#include +#include #include "pjdlog.h" +typedef atomic_uint refcnt_t; + +static __inline void +refcnt_init(refcnt_t *count, unsigned int v) +{ + + atomic_init(count, v); +} + static __inline void -refcnt_acquire(volatile unsigned int *count) +refcnt_acquire(refcnt_t *count) { - atomic_add_acq_int(count, 1); + atomic_fetch_add_explicit(count, 1, memory_order_acquire); } static __inline unsigned int -refcnt_release(volatile unsigned int *count) +refcnt_release(refcnt_t *count) { unsigned int old; /* XXX: Should this have a rel membar? */ - old = atomic_fetchadd_int(count, -1); + old = atomic_fetch_sub(count, 1); PJDLOG_ASSERT(old > 0); return (old - 1); } -- cgit v1.1 From a09c9f55503eb5b4686f83908992db66e59fe595 Mon Sep 17 00:00:00 2001 From: ed Date: Sat, 27 Apr 2013 05:06:25 +0000 Subject: Partially revert my last change. I forgot that I still had a locally applied patch to my copy of Clang that needs to be pushed in before we should use C11 atomics. --- sbin/hastd/refcnt.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sbin') diff --git a/sbin/hastd/refcnt.h b/sbin/hastd/refcnt.h index 5e3fb34..1246043 100644 --- a/sbin/hastd/refcnt.h +++ b/sbin/hastd/refcnt.h @@ -32,24 +32,24 @@ #ifndef __REFCNT_H__ #define __REFCNT_H__ -#include +#include #include "pjdlog.h" -typedef atomic_uint refcnt_t; +typedef unsigned int refcnt_t; static __inline void refcnt_init(refcnt_t *count, unsigned int v) { - atomic_init(count, v); + *count = v; } static __inline void refcnt_acquire(refcnt_t *count) { - atomic_fetch_add_explicit(count, 1, memory_order_acquire); + atomic_add_acq_int(count, 1); } static __inline unsigned int @@ -58,7 +58,7 @@ refcnt_release(refcnt_t *count) unsigned int old; /* XXX: Should this have a rel membar? */ - old = atomic_fetch_sub(count, 1); + old = atomic_fetchadd_int(count, -1); PJDLOG_ASSERT(old > 0); return (old - 1); } -- cgit v1.1 From a44b26897fe945895cdaceab1334e351f45d0901 Mon Sep 17 00:00:00 2001 From: des Date: Mon, 29 Apr 2013 20:13:09 +0000 Subject: Add a -Z option which zeroes unused blocks. It can be combined with -E, in which case unused blocks are first zeroed and then erased. Reviewed by: mckusick MFC after: 3 weeks --- sbin/fsck_ffs/fsck.h | 5 ++++- sbin/fsck_ffs/fsck_ffs.8 | 11 ++++++++++- sbin/fsck_ffs/fsutil.c | 29 +++++++++++++++++++++++++++++ sbin/fsck_ffs/main.c | 6 +++++- sbin/fsck_ffs/pass5.c | 12 ++++++++---- 5 files changed, 56 insertions(+), 7 deletions(-) (limited to 'sbin') diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 7b45d48..45b242c 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -74,6 +74,7 @@ #define MINBUFS 10 /* minimum number of buffers required */ #define MAXBUFS 40 /* maximum space to allocate to buffers */ #define INOBUFSIZE 64*1024 /* size of buffer to read inodes in pass1 */ +#define ZEROBUFSIZE (dev_bsize * 128) /* size of zero buffer used by -Z */ union dinode { struct ufs1_dinode dp1; @@ -306,7 +307,8 @@ char yflag; /* assume a yes response */ int bkgrdflag; /* use a snapshot to run on an active system */ int bflag; /* location of alternate super block */ int debug; /* output debugging info */ -int Eflag; /* zero out empty data blocks */ +int Eflag; /* delete empty data blocks */ +int Zflag; /* zero empty data blocks */ int inoopt; /* trim out unused inodes */ char ckclean; /* only do work if not cleanly unmounted */ int cvtlevel; /* convert to newer file system format */ @@ -402,6 +404,7 @@ int blread(int fd, char *buf, ufs2_daddr_t blk, long size); void bufinit(void); void blwrite(int fd, char *buf, ufs2_daddr_t blk, ssize_t size); void blerase(int fd, ufs2_daddr_t blk, long size); +void blzero(int fd, ufs2_daddr_t blk, long size); void cacheino(union dinode *dp, ino_t inumber); void catch(int); void catchquit(int); diff --git a/sbin/fsck_ffs/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8 index 0513017..0b3f992 100644 --- a/sbin/fsck_ffs/fsck_ffs.8 +++ b/sbin/fsck_ffs/fsck_ffs.8 @@ -38,7 +38,7 @@ .Nd file system consistency check and interactive repair .Sh SYNOPSIS .Nm -.Op Fl BEFfnpry +.Op Fl BEFfnpryZ .Op Fl b Ar block .Op Fl c Ar level .Op Fl m Ar mode @@ -280,6 +280,15 @@ Assume a yes response to all questions asked by .Nm ; this should be used with great caution as this is a free license to continue after essentially unlimited trouble has been encountered. +.It Fl Z +Similar to +.Fl E , +but overwrites unused blocks with zeroes. +If both +.Fl E +and +.Fl Z +are specified, blocks are first zeroed and then erased. .El .Pp Inconsistencies checked are as follows: diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index 9ebc342..f177408 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -618,6 +618,35 @@ blerase(int fd, ufs2_daddr_t blk, long size) return; } +void +blzero(int fd, ufs2_daddr_t blk, long size) +{ + static char *zero; + off_t offset, len; + + if (fd < 0) + return; + len = ZEROBUFSIZE; + if (zero == NULL) { + zero = calloc(len, 1); + if (zero == NULL) + errx(EEXIT, "cannot allocate buffer pool"); + } + offset = blk * dev_bsize; + if (lseek(fd, offset, 0) < 0) + rwerror("SEEK BLK", blk); + while (size > 0) { + if (size > len) + size = len; + else + len = size; + if (write(fd, zero, len) != len) + rwerror("WRITE BLK", blk); + blk += len / dev_bsize; + size -= len; + } +} + /* * Verify cylinder group's magic number and other parameters. If the * test fails, offer an option to rebuild the whole cylinder group. diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index 27f17db..d074447 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -82,7 +82,7 @@ main(int argc, char *argv[]) sync(); skipclean = 1; inoopt = 0; - while ((ch = getopt(argc, argv, "b:Bc:CdEfFm:npry")) != -1) { + while ((ch = getopt(argc, argv, "b:Bc:CdEfFm:npryZ")) != -1) { switch (ch) { case 'b': skipclean = 0; @@ -147,6 +147,10 @@ main(int argc, char *argv[]) nflag = 0; break; + case 'Z': + Zflag++; + break; + default: usage(); } diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c index 146acec..38068eb 100644 --- a/sbin/fsck_ffs/pass5.c +++ b/sbin/fsck_ffs/pass5.c @@ -252,7 +252,7 @@ pass5(void) frags = 0; for (j = 0; j < fs->fs_frag; j++) { if (testbmap(d + j)) { - if (Eflag && start != -1) { + if ((Eflag || Zflag) && start != -1) { clear_blocks(start, d + j - 1); start = -1; } @@ -274,7 +274,7 @@ pass5(void) ffs_fragacct(fs, blk, newcg->cg_frsum, 1); } } - if (Eflag && start != -1) + if ((Eflag || Zflag) && start != -1) clear_blocks(start, d - 1); if (fs->fs_contigsumsize > 0) { int32_t *sump = cg_clustersum(newcg); @@ -586,6 +586,10 @@ static void clear_blocks(ufs2_daddr_t start, ufs2_daddr_t end) if (debug) printf("Zero frags %jd to %jd\n", start, end); - blerase(fswritefd, fsbtodb(&sblock, start), - lfragtosize(&sblock, end - start + 1)); + if (Zflag) + blzero(fswritefd, fsbtodb(&sblock, start), + lfragtosize(&sblock, end - start + 1)); + if (Eflag) + blerase(fswritefd, fsbtodb(&sblock, start), + lfragtosize(&sblock, end - start + 1)); } -- cgit v1.1 From baeb59f05a9b972abc208ef0ded5c6c1d3983581 Mon Sep 17 00:00:00 2001 From: des Date: Mon, 29 Apr 2013 20:14:11 +0000 Subject: Style nit. --- sbin/fsck_ffs/pass5.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c index 38068eb..13ef86d 100644 --- a/sbin/fsck_ffs/pass5.c +++ b/sbin/fsck_ffs/pass5.c @@ -581,7 +581,8 @@ check_maps( } } -static void clear_blocks(ufs2_daddr_t start, ufs2_daddr_t end) +static void +clear_blocks(ufs2_daddr_t start, ufs2_daddr_t end) { if (debug) -- cgit v1.1 From 7272c2592ce2d657f96e6897dad0a6b26b63d303 Mon Sep 17 00:00:00 2001 From: joel Date: Tue, 30 Apr 2013 07:22:03 +0000 Subject: Adapt to the fact that minidumps are now on by default. PR: 177188 --- sbin/dumpon/dumpon.8 | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'sbin') diff --git a/sbin/dumpon/dumpon.8 b/sbin/dumpon/dumpon.8 index 2c09e85..6be8090 100644 --- a/sbin/dumpon/dumpon.8 +++ b/sbin/dumpon/dumpon.8 @@ -28,7 +28,7 @@ .\" From: @(#)swapon.8 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd May 12, 1995 +.Dd April 29, 2013 .Dt DUMPON 8 .Os .Sh NAME @@ -59,14 +59,21 @@ controlled by the variable in the boot time configuration file .Pa /etc/rc.conf . .Pp -For most systems the size of the specified dump device must be at +The default type of kernel crash dump is the mini crash dump. +Mini crash dumps hold only memory pages in use by the kernel. +Alternatively, full memory dumps can be enabled by setting the +.Va debug.minidump +.Xr sysctl 8 +variable to 0. +.Pp +For systems using full memory dumps, the size of the specified dump +device must be at least the size of physical memory. Even though an additional 64 kB header is added to the dump, the BIOS for a platform typically holds back some memory, so it is not usually necessary to size the dump device larger than the actual amount of RAM available in the machine. -.Pp -The +Also, when using full memory dumps, the .Nm utility will refuse to enable a dump device which is smaller than the total amount of physical memory as reported by the -- cgit v1.1 From ce753441d59d3ea068e08e808214672f9e9ebb75 Mon Sep 17 00:00:00 2001 From: eadler Date: Thu, 2 May 2013 17:02:50 +0000 Subject: Prefer using the C++ version of the standard headers. These place the names within the std namespace (and possibly within the global namespace). The main advantage is that the C++ versions can provide optimized versions or simplified interfaces. --- sbin/devd/devd.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'sbin') diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index 9448775..b227589 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -73,19 +73,20 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include +#include +#include +#include +#include +#include + #include -#include #include #include #include #include #include #include -#include -#include -#include -#include #include #include -- cgit v1.1 From eb004e0f1388470d70a4c8ffc653d593cc372887 Mon Sep 17 00:00:00 2001 From: jkim Date: Fri, 3 May 2013 23:51:32 +0000 Subject: Improve compatibility with recent flex from flex.sourceforge.net. --- sbin/devd/token.l | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/devd/token.l b/sbin/devd/token.l index 7a63bec..b3441c3 100644 --- a/sbin/devd/token.l +++ b/sbin/devd/token.l @@ -37,8 +37,6 @@ #include "y.tab.h" int lineno = 1; -#define YY_NO_UNPUT -#define YY_NO_INPUT static void update_lineno(const char *cp) @@ -50,6 +48,9 @@ update_lineno(const char *cp) %} +%option nounput +%option noinput + %% [ \t]+ ; -- cgit v1.1 From 6473a2540f9533d31ae4872e4485cd1f7eb2e402 Mon Sep 17 00:00:00 2001 From: crees Date: Sat, 4 May 2013 14:00:16 +0000 Subject: Introduce and use new flag -L to mount for mounting only late filesystems. Previously, rc.d/mountlate mounted *all* filesystems, causing problems with background NFS mounts being mounted twice. PR: conf/137629 Submitted by: eadler (original concept) Reviewed by: mjg Approved by: hrs --- sbin/mount/mount.8 | 7 +++++++ sbin/mount/mount.c | 11 +++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/mount/mount.8 b/sbin/mount/mount.8 index 6bc4b5c..2770658 100644 --- a/sbin/mount/mount.8 +++ b/sbin/mount/mount.8 @@ -106,6 +106,13 @@ a file system mount status from read-write to read-only. Also forces the R/W mount of an unclean file system (dangerous; use with caution). +.It Fl L +When used in conjunction with the +.Fl a +option, mount +.Em only +those file systems which are marked as +.Dq Li late . .It Fl l When used in conjunction with the .Fl a diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c index 1984eac..a156089 100644 --- a/sbin/mount/mount.c +++ b/sbin/mount/mount.c @@ -245,14 +245,15 @@ main(int argc, char *argv[]) struct fstab *fs; struct statfs *mntbuf; int all, ch, i, init_flags, late, failok, mntsize, rval, have_fstab, ro; + int onlylate; char *cp, *ep, *options; - all = init_flags = late = 0; + all = init_flags = late = onlylate = 0; ro = 0; options = NULL; vfslist = NULL; vfstype = "ufs"; - while ((ch = getopt(argc, argv, "adF:flo:prt:uvw")) != -1) + while ((ch = getopt(argc, argv, "adF:fLlo:prt:uvw")) != -1) switch (ch) { case 'a': all = 1; @@ -266,6 +267,10 @@ main(int argc, char *argv[]) case 'f': init_flags |= MNT_FORCE; break; + case 'L': + onlylate = 1; + late = 1; + break; case 'l': late = 1; break; @@ -327,6 +332,8 @@ main(int argc, char *argv[]) continue; if (hasopt(fs->fs_mntops, "noauto")) continue; + if (!hasopt(fs->fs_mntops, "late") && onlylate) + continue; if (hasopt(fs->fs_mntops, "late") && !late) continue; if (hasopt(fs->fs_mntops, "failok")) -- cgit v1.1 From d9d71436d975a7ec598297c564219c530aa41138 Mon Sep 17 00:00:00 2001 From: hrs Date: Sat, 4 May 2013 19:16:26 +0000 Subject: Use FF02:0:0:0:0:2:FF00::/104 prefix for IPv6 Node Information Group Address. Although KAME implementation used FF02:0:0:0:0:2::/96 based on older versions of draft-ietf-ipngwg-icmp-name-lookup, it has been changed in RFC 4620. The kernel always joins the /104-prefixed address, and additionally does /96-prefixed one only when net.inet6.icmp6.nodeinfo_oldmcprefix=1. The default value of the sysctl is 1. ping6(8) -N flag now uses /104-prefixed one. When this flag is specified twice, it uses /96-prefixed one instead. Reviewed by: ume Based on work by: Thomas Scheffler PR: conf/174957 MFC after: 2 weeks --- sbin/ping6/ping6.8 | 15 ++++++++++++--- sbin/ping6/ping6.c | 29 +++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 9 deletions(-) (limited to 'sbin') diff --git a/sbin/ping6/ping6.8 b/sbin/ping6/ping6.8 index b720aef..0d1e5f0 100644 --- a/sbin/ping6/ping6.8 +++ b/sbin/ping6/ping6.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 20, 2010 +.Dd May 5, 2013 .Dt PING6 8 .Os .Sh NAME @@ -215,8 +215,8 @@ unicast and multicast packets. Numeric output only. No attempt will be made to lookup symbolic names from addresses in the reply. .It Fl N -Probe node information multicast group -.Pq Li ff02::2:xxxx:xxxx . +Probe node information multicast group address +.Pq Li ff02::2:ffxx:xxxx . .Ar host must be string hostname of the target (must not be a numeric IPv6 address). @@ -227,6 +227,15 @@ Since node information multicast group is a link-local multicast group, outgoing interface needs to be specified by .Fl I option. +.Pp +When specified twice, the address +.Pq Li ff02::2:xxxx:xxxx +is used instead. +The former is in RFC 4620, the latter is in an old Internet Draft +draft-ietf-ipngwg-icmp-name-lookup. +Note that KAME-derived implementations including +.Fx +use the latter. .It Fl o Exit successfully after receiving one reply packet. .It Fl p Ar pattern diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c index 8c3e16b..01e29a1 100644 --- a/sbin/ping6/ping6.c +++ b/sbin/ping6/ping6.c @@ -287,7 +287,7 @@ void pr_retip(struct ip6_hdr *, u_char *); void summary(void); void tvsub(struct timeval *, struct timeval *); int setpolicy(int, char *); -char *nigroup(char *); +char *nigroup(char *, int); void usage(void); int @@ -306,6 +306,7 @@ main(int argc, char *argv[]) struct addrinfo hints; int cc, i; int ch, hold, packlen, preload, optval, ret_ga; + int nig_oldmcprefix = -1; u_char *datap; char *e, *target, *ifname = NULL, *gateway = NULL; int ip6optlen = 0; @@ -490,6 +491,7 @@ main(int argc, char *argv[]) break; case 'N': options |= F_NIGROUP; + nig_oldmcprefix++; break; case 'o': options |= F_ONCE; @@ -605,7 +607,7 @@ main(int argc, char *argv[]) } if (options & F_NIGROUP) { - target = nigroup(argv[argc - 1]); + target = nigroup(argv[argc - 1], nig_oldmcprefix); if (target == NULL) { usage(); /*NOTREACHED*/ @@ -2723,7 +2725,7 @@ setpolicy(int so __unused, char *policy) #endif char * -nigroup(char *name) +nigroup(char *name, int nig_oldmcprefix) { char *p; char *q; @@ -2733,6 +2735,7 @@ nigroup(char *name) size_t l; char hbuf[NI_MAXHOST]; struct in6_addr in6; + int valid; p = strchr(name, '.'); if (!p) @@ -2748,7 +2751,7 @@ nigroup(char *name) *q = tolower(*(unsigned char *)q); } - /* generate 8 bytes of pseudo-random value. */ + /* generate 16 bytes of pseudo-random value. */ memset(&ctxt, 0, sizeof(ctxt)); MD5Init(&ctxt); c = l & 0xff; @@ -2756,9 +2759,23 @@ nigroup(char *name) MD5Update(&ctxt, (unsigned char *)name, l); MD5Final(digest, &ctxt); - if (inet_pton(AF_INET6, "ff02::2:0000:0000", &in6) != 1) + if (nig_oldmcprefix) { + /* draft-ietf-ipngwg-icmp-name-lookup */ + valid = inet_pton(AF_INET6, "ff02::2:0000:0000", &in6); + } else { + /* RFC 4620 */ + valid = inet_pton(AF_INET6, "ff02::2:ff00:0000", &in6); + } + if (valid != 1) return NULL; /*XXX*/ - bcopy(digest, &in6.s6_addr[12], 4); + + if (nig_oldmcprefix) { + /* draft-ietf-ipngwg-icmp-name-lookup */ + bcopy(digest, &in6.s6_addr[12], 4); + } else { + /* RFC 4620 */ + bcopy(digest, &in6.s6_addr[13], 3); + } if (inet_ntop(AF_INET6, &in6, hbuf, sizeof(hbuf)) == NULL) return NULL; -- cgit v1.1 From fb6ba90052397de5bf2026022b978edba1ec71bb Mon Sep 17 00:00:00 2001 From: eadler Date: Mon, 6 May 2013 17:44:12 +0000 Subject: Remove includes for old versions of FreeBSD. Reviewed by: stass Obtained From: DragonFlyBSD MFC After: 1 week --- sbin/iscontrol/auth_subr.c | 3 --- sbin/iscontrol/fsm.c | 3 --- sbin/iscontrol/login.c | 3 --- sbin/iscontrol/misc.c | 3 --- 4 files changed, 12 deletions(-) (limited to 'sbin') diff --git a/sbin/iscontrol/auth_subr.c b/sbin/iscontrol/auth_subr.c index 375d06d..9ced1d7 100644 --- a/sbin/iscontrol/auth_subr.c +++ b/sbin/iscontrol/auth_subr.c @@ -40,9 +40,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#if __FreeBSD_version < 500000 -#include -#endif #include #include #include diff --git a/sbin/iscontrol/fsm.c b/sbin/iscontrol/fsm.c index b74daa0..794fb8b 100644 --- a/sbin/iscontrol/fsm.c +++ b/sbin/iscontrol/fsm.c @@ -40,9 +40,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#if __FreeBSD_version < 500000 -#include -#endif #include #include #include diff --git a/sbin/iscontrol/login.c b/sbin/iscontrol/login.c index e2a9e5f..76937a8 100644 --- a/sbin/iscontrol/login.c +++ b/sbin/iscontrol/login.c @@ -39,9 +39,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#if __FreeBSD_version < 500000 -#include -#endif #include #include #include diff --git a/sbin/iscontrol/misc.c b/sbin/iscontrol/misc.c index 1c7a1ad..1f9dd12 100644 --- a/sbin/iscontrol/misc.c +++ b/sbin/iscontrol/misc.c @@ -40,9 +40,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#if __FreeBSD_version < 500000 -#include -#endif #include #include #include -- cgit v1.1 From b41b20fa98c09c611a80ebcfebd518bafebb3198 Mon Sep 17 00:00:00 2001 From: eadler Date: Wed, 8 May 2013 18:55:38 +0000 Subject: Allow the use of lowercase 'yes' PR: bin/178422 Submitted by: Garrett Cooper --- sbin/growfs/growfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c index fe49efb..b8a81c2 100644 --- a/sbin/growfs/growfs.c +++ b/sbin/growfs/growfs.c @@ -1544,7 +1544,7 @@ main(int argc, char **argv) printf(" from %s to %s? [Yes/No] ", oldsizebuf, newsizebuf); fflush(stdout); fgets(reply, (int)sizeof(reply), stdin); - if (strcmp(reply, "Yes\n")){ + if (strcasecmp(reply, "Yes\n")){ printf("\nNothing done\n"); exit (0); } -- cgit v1.1 From 27529b110232c0d902ca720d41c4918c80c4f63e Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 8 May 2013 20:52:22 +0000 Subject: Add vlan configuration support to etherswitchcfg. This adds the support to the config keyword (vlan operation mode), ports flags, prints the vlan mode and vlan capabilities. It also adds some basic information to usage() and support the keyword 'help' as a shortcut to usage(). The manual page is also updated with the new options. Submitted by: Luiz Otavio O Souza Reviewed by: ray --- sbin/etherswitchcfg/etherswitchcfg.8 | 45 +++++++- sbin/etherswitchcfg/etherswitchcfg.c | 207 +++++++++++++++++++++++++++++++++-- 2 files changed, 242 insertions(+), 10 deletions(-) (limited to 'sbin') diff --git a/sbin/etherswitchcfg/etherswitchcfg.8 b/sbin/etherswitchcfg/etherswitchcfg.8 index 88e06f7..0d18638 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.8 +++ b/sbin/etherswitchcfg/etherswitchcfg.8 @@ -11,12 +11,16 @@ .Ar info .Nm .Op Fl "f control file" +.Ar config +.Ar command parameter +.Nm +.Op Fl "f control file" .Ar phy .Ar phy.register[=value] .Nm .Op Fl "f control file" .Ar port%d -.Ar command parameter +.Ar [flags] command parameter .Nm .Op Fl "f control file" .Ar reg @@ -46,6 +50,14 @@ Produce more verbose output. Without this flag, lines that represent inactive or empty configuration options are omitted. .El +.Ss config +The config command provides access to global switch configuration +parameters. +It support the following commands: +.Bl -tag -width ".Ar vlan_mode mode" -compact +.It Ar vlan_mode mode +Sets the switch VLAN mode (depends on the hardware). +.El .Ss phy The phy command provides access to the registers of the PHYs attached to or integrated into the switch controller. @@ -75,6 +87,37 @@ for details on and .Ar mediaopt . .El +And the following flags (please note that not all flags +are supporterd by all switch drivers): +.Bl -tag -width ".Ar addtag" -compact +.It Ar addtag +Add VLAN tag to each packet sent by the port. +.It Ar -addtag +Disable the add VLAN tag option. +.It Ar striptag +Strip the VLAN tags from the packets sent by the port. +.It Ar -striptag +Disable the strip VLAN tag option. +.It Ar firstlock +This options makes the switch port lock on the first MAC address it seems. +After that, usually you need to reset the switch to learn different +MAC addresses. +.It Ar -firstlock +Disable the first lock option. Note that sometimes you need to reset the +switch to really disable this option. +.It Ar dropuntagged +Drop packets without a VLAN tag. +.It Ar -dropuntagged +Disable the drop untagged packets option. +.It Ar doubletag +Enable QinQ for the port. +.It Ar -doubletag +Disable QinQ for the port. +.It Ar ingress +Enable the ingress filter on the port. +.It Ar -ingress +Disable the ingress filter. +.El .Ss reg The reg command provides access to the registers of the switch controller. .Ss vlangroup diff --git a/sbin/etherswitchcfg/etherswitchcfg.c b/sbin/etherswitchcfg/etherswitchcfg.c index 3e0b451..e117580 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.c +++ b/sbin/etherswitchcfg/etherswitchcfg.c @@ -58,6 +58,7 @@ void print_media_word_ifconfig(int); enum cmdmode { MODE_NONE = 0, MODE_PORT, + MODE_CONFIG, MODE_VLANGROUP, MODE_REGISTER, MODE_PHYREG @@ -68,6 +69,7 @@ struct cfg { int verbose; int mediatypes; const char *controlfile; + etherswitch_conf_t conf; etherswitch_info_t info; enum cmdmode mode; int unit; @@ -82,7 +84,37 @@ struct cmds { static struct cmds cmds[]; -static void usage(void); +/* + * Print a value a la the %b format of the kernel's printf. + * Stolen from ifconfig.c. + */ +static void +printb(const char *s, unsigned v, const char *bits) +{ + int i, any = 0; + char c; + + if (bits && *bits == 8) + printf("%s=%o", s, v); + else + printf("%s=%x", s, v); + bits++; + if (bits) { + putchar('<'); + while ((i = *bits++) != '\0') { + if (v & (1 << (i-1))) { + if (any) + putchar(','); + any = 1; + for (; (c = *bits) > 32; bits++) + putchar(c); + } else + for (; *bits > 32; bits++) + ; + } + putchar('>'); + } +} static int read_register(struct cfg *cfg, int r) @@ -150,6 +182,47 @@ set_port_vid(struct cfg *cfg, char *argv[]) } static void +set_port_flag(struct cfg *cfg, char *argv[]) +{ + char *flag; + int n; + uint32_t f; + etherswitch_port_t p; + + n = 0; + f = 0; + flag = argv[0]; + if (strcmp(flag, "none") != 0) { + if (*flag == '-') { + n++; + flag++; + } + if (strcasecmp(flag, "striptag") == 0) + f = ETHERSWITCH_PORT_STRIPTAG; + else if (strcasecmp(flag, "addtag") == 0) + f = ETHERSWITCH_PORT_ADDTAG; + else if (strcasecmp(flag, "firstlock") == 0) + f = ETHERSWITCH_PORT_FIRSTLOCK; + else if (strcasecmp(flag, "dropuntagged") == 0) + f = ETHERSWITCH_PORT_DROPUNTAGGED; + else if (strcasecmp(flag, "doubletag") == 0) + f = ETHERSWITCH_PORT_DOUBLE_TAG; + else if (strcasecmp(flag, "ingress") == 0) + f = ETHERSWITCH_PORT_INGRESS; + } + bzero(&p, sizeof(p)); + p.es_port = cfg->unit; + if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) + err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); + if (n) + p.es_flags &= ~f; + else + p.es_flags |= f; + if (ioctl(cfg->fd, IOETHERSWITCHSETPORT, &p) != 0) + err(EX_OSERR, "ioctl(IOETHERSWITCHSETPORT)"); +} + +static void set_port_media(struct cfg *cfg, char *argv[]) { etherswitch_port_t p; @@ -290,6 +363,66 @@ set_phyregister(struct cfg *cfg, char *arg) } static void +set_vlan_mode(struct cfg *cfg, char *argv[]) +{ + etherswitch_conf_t conf; + + bzero(&conf, sizeof(conf)); + conf.cmd = ETHERSWITCH_CONF_VLAN_MODE; + if (strcasecmp(argv[1], "isl") == 0) + conf.vlan_mode = ETHERSWITCH_VLAN_ISL; + else if (strcasecmp(argv[1], "port") == 0) + conf.vlan_mode = ETHERSWITCH_VLAN_PORT; + else if (strcasecmp(argv[1], "dot1q") == 0) + conf.vlan_mode = ETHERSWITCH_VLAN_DOT1Q; + else if (strcasecmp(argv[1], "dot1q4k") == 0) + conf.vlan_mode = ETHERSWITCH_VLAN_DOT1Q_4K; + else if (strcasecmp(argv[1], "qinq") == 0) + conf.vlan_mode = ETHERSWITCH_VLAN_DOUBLE_TAG; + else + conf.vlan_mode = 0; + if (ioctl(cfg->fd, IOETHERSWITCHSETCONF, &conf) != 0) + err(EX_OSERR, "ioctl(IOETHERSWITCHSETCONF)"); +} + +static void +print_config(struct cfg *cfg) +{ + const char *c; + + /* Get the device name. */ + c = strrchr(cfg->controlfile, '/'); + if (c != NULL) + c = c + 1; + else + c = cfg->controlfile; + + /* Print VLAN mode. */ + if (cfg->conf.cmd & ETHERSWITCH_CONF_VLAN_MODE) { + printf("%s: VLAN mode: ", c); + switch (cfg->conf.vlan_mode) { + case ETHERSWITCH_VLAN_ISL: + printf("ISL\n"); + break; + case ETHERSWITCH_VLAN_PORT: + printf("PORT\n"); + break; + case ETHERSWITCH_VLAN_DOT1Q: + printf("DOT1Q\n"); + break; + case ETHERSWITCH_VLAN_DOT1Q_4K: + printf("DOT1Q4K\n"); + break; + case ETHERSWITCH_VLAN_DOUBLE_TAG: + printf("QinQ\n"); + break; + default: + printf("none\n"); + } + } +} + +static void print_port(struct cfg *cfg, int port) { etherswitch_port_t p; @@ -303,7 +436,10 @@ print_port(struct cfg *cfg, int port) if (ioctl(cfg->fd, IOETHERSWITCHGETPORT, &p) != 0) err(EX_OSERR, "ioctl(IOETHERSWITCHGETPORT)"); printf("port%d:\n", port); - printf("\tpvid: %d\n", p.es_pvid); + if (cfg->conf.vlan_mode == ETHERSWITCH_VLAN_DOT1Q) + printf("\tpvid: %d\n", p.es_pvid); + printb("\tflags", p.es_flags, ETHERSWITCH_PORT_FLAGS_BITS); + printf("\n"); printf("\tmedia: "); print_media_word(p.es_ifmr.ifm_current, 1); if (p.es_ifmr.ifm_active != p.es_ifmr.ifm_current) { @@ -335,10 +471,13 @@ print_vlangroup(struct cfg *cfg, int vlangroup) vg.es_vlangroup = vlangroup; if (ioctl(cfg->fd, IOETHERSWITCHGETVLANGROUP, &vg) != 0) err(EX_OSERR, "ioctl(IOETHERSWITCHGETVLANGROUP)"); - if (cfg->verbose == 0 && vg.es_member_ports == 0) + if (vg.es_vid == 0 && vg.es_member_ports == 0) return; printf("vlangroup%d:\n", vlangroup); - printf("\tvlan: %d\n", vg.es_vid); + if (cfg->conf.vlan_mode == ETHERSWITCH_VLAN_PORT) + printf("\tport: %d\n", vg.es_vid); + else + printf("\tvlan: %d\n", vg.es_vid); printf("\tmembers "); comma = 0; if (vg.es_member_ports != 0) @@ -368,9 +507,16 @@ print_info(struct cfg *cfg) c = c + 1; else c = cfg->controlfile; - if (cfg->verbose) - printf("%s: %s with %d ports and %d VLAN groups\n", - c, cfg->info.es_name, cfg->info.es_nports, cfg->info.es_nvlangroups); + if (cfg->verbose) { + printf("%s: %s with %d ports and %d VLAN groups\n", c, + cfg->info.es_name, cfg->info.es_nports, + cfg->info.es_nvlangroups); + printf("%s: ", c); + printb("VLAN capabilities", cfg->info.es_vlan_caps, + ETHERSWITCH_VLAN_CAPS_BITS); + printf("\n"); + } + print_config(cfg); for (i=0; iinfo.es_nports; i++) { print_port(cfg, i); } @@ -380,9 +526,23 @@ print_info(struct cfg *cfg) } static void -usage(void) +usage(struct cfg *cfg __unused, char *argv[] __unused) { fprintf(stderr, "usage: etherswitchctl\n"); + fprintf(stderr, "\tetherswitchcfg [-f control file] info\n"); + fprintf(stderr, "\tetherswitchcfg [-f control file] config " + "command parameter\n"); + fprintf(stderr, "\t\tconfig commands: vlan_mode\n"); + fprintf(stderr, "\tetherswitchcfg [-f control file] phy " + "phy.register[=value]\n"); + fprintf(stderr, "\tetherswitchcfg [-f control file] portX " + "[flags] command parameter\n"); + fprintf(stderr, "\t\tport commands: pvid, media, mediaopt\n"); + fprintf(stderr, "\tetherswitchcfg [-f control file] reg " + "register[=value]\n"); + fprintf(stderr, "\tetherswitchcfg [-f control file] vlangroupX " + "command parameter\n"); + fprintf(stderr, "\t\tvlangroup commands: vlan, members\n"); exit(EX_USAGE); } @@ -394,6 +554,15 @@ newmode(struct cfg *cfg, enum cmdmode mode) switch (cfg->mode) { case MODE_NONE: break; + case MODE_CONFIG: + /* + * Read the updated the configuration (it can be different + * from the last time we read it). + */ + if (ioctl(cfg->fd, IOETHERSWITCHGETCONF, &cfg->conf) != 0) + err(EX_OSERR, "ioctl(IOETHERSWITCHGETCONF)"); + print_config(cfg); + break; case MODE_PORT: print_port(cfg, cfg->unit); break; @@ -430,7 +599,7 @@ main(int argc, char *argv[]) case '?': /* FALLTHROUGH */ default: - usage(); + usage(&cfg, argv); } argc -= optind; argv += optind; @@ -439,6 +608,8 @@ main(int argc, char *argv[]) err(EX_UNAVAILABLE, "Can't open control file: %s", cfg.controlfile); if (ioctl(cfg.fd, IOETHERSWITCHGETINFO, &cfg.info) != 0) err(EX_OSERR, "ioctl(IOETHERSWITCHGETINFO)"); + if (ioctl(cfg.fd, IOETHERSWITCHGETCONF, &cfg.conf) != 0) + err(EX_OSERR, "ioctl(IOETHERSWITCHGETCONF)"); if (argc == 0) { print_info(&cfg); return (0); @@ -457,15 +628,20 @@ main(int argc, char *argv[]) if (cfg.unit < 0 || cfg.unit >= cfg.info.es_nvlangroups) errx(EX_USAGE, "port unit must be between 0 and %d", cfg.info.es_nvlangroups); newmode(&cfg, MODE_VLANGROUP); + } else if (strcmp(argv[0], "config") == 0) { + newmode(&cfg, MODE_CONFIG); } else if (strcmp(argv[0], "phy") == 0) { newmode(&cfg, MODE_PHYREG); } else if (strcmp(argv[0], "reg") == 0) { newmode(&cfg, MODE_REGISTER); + } else if (strcmp(argv[0], "help") == 0) { + usage(&cfg, argv); } else { errx(EX_USAGE, "Unknown command \"%s\"", argv[0]); } break; case MODE_PORT: + case MODE_CONFIG: case MODE_VLANGROUP: for(i=0; cmds[i].name != NULL; i++) { if (cfg.mode == cmds[i].mode && strcmp(argv[0], cmds[i].name) == 0) { @@ -510,6 +686,19 @@ static struct cmds cmds[] = { { MODE_PORT, "pvid", 1, set_port_vid }, { MODE_PORT, "media", 1, set_port_media }, { MODE_PORT, "mediaopt", 1, set_port_mediaopt }, + { MODE_PORT, "addtag", 0, set_port_flag }, + { MODE_PORT, "-addtag", 0, set_port_flag }, + { MODE_PORT, "ingress", 0, set_port_flag }, + { MODE_PORT, "-ingress", 0, set_port_flag }, + { MODE_PORT, "striptag", 0, set_port_flag }, + { MODE_PORT, "-striptag", 0, set_port_flag }, + { MODE_PORT, "doubletag", 0, set_port_flag }, + { MODE_PORT, "-doubletag", 0, set_port_flag }, + { MODE_PORT, "firstlock", 0, set_port_flag }, + { MODE_PORT, "-firstlock", 0, set_port_flag }, + { MODE_PORT, "dropuntagged", 0, set_port_flag }, + { MODE_PORT, "-dropuntagged", 0, set_port_flag }, + { MODE_CONFIG, "vlan_mode", 1, set_vlan_mode }, { MODE_VLANGROUP, "vlan", 1, set_vlangroup_vid }, { MODE_VLANGROUP, "members", 1, set_vlangroup_members }, { 0, NULL, 0, NULL } -- cgit v1.1 From ce5597df9f6934fa9c3aee66c21ee116380a03fb Mon Sep 17 00:00:00 2001 From: joel Date: Wed, 8 May 2013 21:02:48 +0000 Subject: mdoc: new sentence, new line. --- sbin/etherswitchcfg/etherswitchcfg.8 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/etherswitchcfg/etherswitchcfg.8 b/sbin/etherswitchcfg/etherswitchcfg.8 index 0d18638..a4ffb0b 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.8 +++ b/sbin/etherswitchcfg/etherswitchcfg.8 @@ -80,7 +80,8 @@ Sets the default port VID that is used to process incoming frames that are not t .It Ar media mediaspec Specifies the physical media configuration to be configured for a port. .It Ar mediaopt mediaoption -Specifies a list of media options for a port. See +Specifies a list of media options for a port. +See .Xr ifconfig 8 for details on .Ar media @@ -103,7 +104,8 @@ This options makes the switch port lock on the first MAC address it seems. After that, usually you need to reset the switch to learn different MAC addresses. .It Ar -firstlock -Disable the first lock option. Note that sometimes you need to reset the +Disable the first lock option. +Note that sometimes you need to reset the switch to really disable this option. .It Ar dropuntagged Drop packets without a VLAN tag. -- cgit v1.1 From cbecbe42ad9440e6461b8f10839857a378ad62bb Mon Sep 17 00:00:00 2001 From: joel Date: Wed, 8 May 2013 21:04:19 +0000 Subject: Remove EOL whitespace. --- sbin/ping6/ping6.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/ping6/ping6.8 b/sbin/ping6/ping6.8 index 0d1e5f0..60a6980 100644 --- a/sbin/ping6/ping6.8 +++ b/sbin/ping6/ping6.8 @@ -234,7 +234,7 @@ is used instead. The former is in RFC 4620, the latter is in an old Internet Draft draft-ietf-ipngwg-icmp-name-lookup. Note that KAME-derived implementations including -.Fx +.Fx use the latter. .It Fl o Exit successfully after receiving one reply packet. -- cgit v1.1 From 56def3d68d612ab479869fc64af58e12ff1fb811 Mon Sep 17 00:00:00 2001 From: eadler Date: Fri, 10 May 2013 03:42:48 +0000 Subject: Add support for 'dmesg -c' which clears the dmesg buffer after it has been printed. This provides compatibility with other *nix systems (including Linux). While here use stdbool booleans for 'all'. PR: bin/178295 Submitted by: Levent Serinol Reviewed by: will --- sbin/dmesg/dmesg.8 | 4 +++- sbin/dmesg/dmesg.c | 20 +++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'sbin') diff --git a/sbin/dmesg/dmesg.8 b/sbin/dmesg/dmesg.8 index 9d05e6c..b5004f5 100644 --- a/sbin/dmesg/dmesg.8 +++ b/sbin/dmesg/dmesg.8 @@ -36,7 +36,7 @@ .Nd "display the system message buffer" .Sh SYNOPSIS .Nm -.Op Fl a +.Op Fl ac .Op Fl M Ar core Op Fl N Ar system .Sh DESCRIPTION The @@ -59,6 +59,8 @@ Show all data in the message buffer. This includes any syslog records and .Pa /dev/console output. +.It Fl c +Clear the kernel buffer after printing. .It Fl M Extract values associated with the name list from the specified core. .It Fl N diff --git a/sbin/dmesg/dmesg.c b/sbin/dmesg/dmesg.c index 002732c..1d548a7 100644 --- a/sbin/dmesg/dmesg.c +++ b/sbin/dmesg/dmesg.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -79,15 +80,20 @@ main(int argc, char *argv[]) kvm_t *kd; size_t buflen, bufpos; long pri; - int all, ch; + int ch, clear; + bool all; - all = 0; + all = false; + clear = false; (void) setlocale(LC_CTYPE, ""); memf = nlistf = NULL; - while ((ch = getopt(argc, argv, "aM:N:")) != -1) + while ((ch = getopt(argc, argv, "acM:N:")) != -1) switch(ch) { case 'a': - all++; + all = true; + break; + case 'c': + clear = true; break; case 'M': memf = optarg; @@ -190,12 +196,16 @@ main(int argc, char *argv[]) (void)strvisx(visbp, p, nextp - p, 0); (void)printf("%s", visbp); } + if (clear) + if (sysctlbyname("kern.msgbuf_clear", NULL, NULL, &clear, sizeof(int))) + err(1, "sysctl kern.msgbuf_clear"); + exit(0); } void usage(void) { - (void)fprintf(stderr, "usage: dmesg [-a] [-M core [-N system]]\n"); + fprintf(stderr, "usage: dmesg [-ac] [-M core [-N system]]\n"); exit(1); } -- cgit v1.1 From d81843f847fef936517c04f60d72155bad92110b Mon Sep 17 00:00:00 2001 From: eadler Date: Fri, 10 May 2013 12:49:16 +0000 Subject: Bump .Dd for recent content change. Reported by: delphij --- sbin/dmesg/dmesg.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/dmesg/dmesg.8 b/sbin/dmesg/dmesg.8 index b5004f5..35446fb 100644 --- a/sbin/dmesg/dmesg.8 +++ b/sbin/dmesg/dmesg.8 @@ -28,7 +28,7 @@ .\" @(#)dmesg.8 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd June 5, 1993 +.Dd May 9, 2013 .Dt DMESG 8 .Os .Sh NAME -- cgit v1.1 From f39c963dc20905c14324b9992ee87c4ad66a15e6 Mon Sep 17 00:00:00 2001 From: trociny Date: Sat, 11 May 2013 09:51:44 +0000 Subject: Get rid of libl dependency. We needed it only to provide yywrap. But yywrap is not necessary when parsing a single hast.conf file. Suggested by: kib Reviewed by: pjd --- sbin/hastctl/Makefile | 4 ++-- sbin/hastd/Makefile | 2 +- sbin/hastd/token.l | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/hastctl/Makefile b/sbin/hastctl/Makefile index 2be817e..02531e6 100644 --- a/sbin/hastctl/Makefile +++ b/sbin/hastctl/Makefile @@ -32,8 +32,8 @@ CFLAGS+=-DINET6 CFLAGS+=-DYY_NO_UNPUT CFLAGS+=-DYY_NO_INPUT -DPADD= ${LIBL} ${LIBUTIL} -LDADD= -ll -lutil +DPADD= ${LIBUTIL} +LDADD= -lutil .if ${MK_OPENSSL} != "no" DPADD+= ${LIBCRYPTO} LDADD+= -lcrypto diff --git a/sbin/hastd/Makefile b/sbin/hastd/Makefile index 43c7a52..7ff6ee8 100644 --- a/sbin/hastd/Makefile +++ b/sbin/hastd/Makefile @@ -31,7 +31,7 @@ CFLAGS+=-DINET6 .endif DPADD= ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} ${LIBL} ${LIBPTHREAD} ${LIBUTIL} -LDADD= -lgeom -lbsdxml -lsbuf -ll -lpthread -lutil +LDADD= -lgeom -lbsdxml -lsbuf -lpthread -lutil .if ${MK_OPENSSL} != "no" DPADD+= ${LIBCRYPTO} LDADD+= -lcrypto diff --git a/sbin/hastd/token.l b/sbin/hastd/token.l index 38bf8d6..a20efd7 100644 --- a/sbin/hastd/token.l +++ b/sbin/hastd/token.l @@ -46,6 +46,7 @@ int lineno; %option noinput %option nounput +%option noyywrap %% control { DP; return CONTROL; } -- cgit v1.1 From 05a725b2d7d8814e7c9604b2ee91737853586bb3 Mon Sep 17 00:00:00 2001 From: joel Date: Sun, 12 May 2013 22:22:12 +0000 Subject: mdoc sweep. --- sbin/iscontrol/iscsi.conf.5 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/iscontrol/iscsi.conf.5 b/sbin/iscontrol/iscsi.conf.5 index 1e2c7f0..e6a776d 100644 --- a/sbin/iscontrol/iscsi.conf.5 +++ b/sbin/iscontrol/iscsi.conf.5 @@ -173,7 +173,9 @@ same as the none counterpart, but to authenticate the target. .El .Sh FILES -.Pa /etc/iscsi.conf +.Bl -tag -width indent +.It Pa /etc/iscsi.conf +.El .Sh EXAMPLES .Bd -literal # -- cgit v1.1 From d1ce45a46f7a9b89b123dcde2d66f0ece46d880a Mon Sep 17 00:00:00 2001 From: joel Date: Mon, 13 May 2013 18:13:50 +0000 Subject: mdoc sweep --- sbin/ifconfig/ifconfig.8 | 12 +++++++++--- sbin/routed/routed.8 | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'sbin') diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 9c74980..d0d8671 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -1054,7 +1054,9 @@ can be used on a channel are defined by this setting. Country/Region codes are specified as a 2-character abbreviation defined by ISO 3166 or using a longer, but possibly ambiguous, spelling; e.g., "ES" and "Spain". -The set of country codes are taken from /etc/regdomain.xml and can also +The set of country codes are taken from +.Pa /etc/regdomain.xml +and can also be viewed with the ``list countries'' request. Note that not all devices support changing the country code from a default setting; typically stored in EEPROM. @@ -1072,7 +1074,9 @@ according to a least-congested criteria. DFS support is mandatory for some 5GHz frequencies in certain locales (e.g., ETSI). By default DFS is enabled according to the regulatory definitions -specified in /etc/regdomain.xml and the current country code, regdomain, +specified in +.Pa /etc/regdomain.xml +and the current country code, regdomain, and channel. Note the underlying device (and driver) must support radar detection for full DFS support to work. @@ -1578,7 +1582,9 @@ for operation. In particular the set of available channels, how the wireless device will operation on the channels, and the maximum transmit power that can be used on a channel are defined by this setting. -Regdomain codes (SKU's) are taken from /etc/regdomain.xml and can also +Regdomain codes (SKU's) are taken from +.Pa /etc/regdomain.xml +and can also be viewed with the ``list countries'' request. Note that not all devices support changing the regdomain from a default setting; typically stored in EEPROM. diff --git a/sbin/routed/routed.8 b/sbin/routed/routed.8 index 570e20b..2f8a021 100644 --- a/sbin/routed/routed.8 +++ b/sbin/routed/routed.8 @@ -576,7 +576,7 @@ Incoming packets can carry any password that is valid, will be valid within the next 24 hours, or that was valid within the preceding 24 hours. To protect the secrets, the passwd settings are valid only in the -.Em /etc/gateways +.Pa /etc/gateways file and only when that file is readable only by UID 0. .It Cm md5_passwd Ns \&= Ns Ar XXX|KeyID[start|stop] specifies a RIPv2 MD5 password. -- cgit v1.1 From d8aa05d9721062c5d7ee6fa22d937ed4cf50db04 Mon Sep 17 00:00:00 2001 From: asomers Date: Wed, 15 May 2013 17:26:50 +0000 Subject: sbin/camcontrol/camcontrol.c If an expander returns 0x00 (no device attached) in the ATTACHED DEVICE field of the SMP DISCOVER response, ignore the value of ATTACHED SAS ADDRESS, because it is invalid. Some expanders zero out the address when the attached device is removed, but others do not. Section 9.4.3.10 of the SAS Protocol Layer 2 revision 04b does not require them to do so. Approved by: ken (mentor) MFC after: 3 weeks --- sbin/camcontrol/camcontrol.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 7f13520..7a374a4 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -7138,8 +7138,12 @@ smpphylist(struct cam_device *device, int argc, char **argv, continue; } - item = findsasdevice(&devlist, - scsi_8btou64(disresponse->attached_sas_address)); + if (disresponse->attached_device == SMP_DIS_AD_TYPE_NONE) { + item = NULL; + } else { + item = findsasdevice(&devlist, + scsi_8btou64(disresponse->attached_sas_address)); + } if ((quiet == 0) || (item != NULL)) { -- cgit v1.1 From 0750e3e86451d76b599bad457e005e92b1dd9c60 Mon Sep 17 00:00:00 2001 From: mckusick Date: Thu, 16 May 2013 19:39:11 +0000 Subject: Clean up trailing whitespace. Submitted by: Andy Kosela MFC after: 1 week --- sbin/dumpfs/dumpfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c index 6669d53..d04558c 100644 --- a/sbin/dumpfs/dumpfs.c +++ b/sbin/dumpfs/dumpfs.c @@ -197,15 +197,15 @@ dumpfs(const char *name) "maxbsize", afs.fs_maxbsize, afs.fs_maxbpg, afs.fs_maxcontig, afs.fs_contigsumsize); printf("nbfree\t%jd\tndir\t%jd\tnifree\t%jd\tnffree\t%jd\n", - (intmax_t)afs.fs_cstotal.cs_nbfree, + (intmax_t)afs.fs_cstotal.cs_nbfree, (intmax_t)afs.fs_cstotal.cs_ndir, - (intmax_t)afs.fs_cstotal.cs_nifree, + (intmax_t)afs.fs_cstotal.cs_nifree, (intmax_t)afs.fs_cstotal.cs_nffree); printf("bpg\t%d\tfpg\t%d\tipg\t%d\tunrefs\t%jd\n", afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg, (intmax_t)afs.fs_unrefs); printf("nindir\t%d\tinopb\t%d\tmaxfilesize\t%ju\n", - afs.fs_nindir, afs.fs_inopb, + afs.fs_nindir, afs.fs_inopb, (uintmax_t)afs.fs_maxfilesize); printf("sbsize\t%d\tcgsize\t%d\tcsaddr\t%jd\tcssize\t%d\n", afs.fs_sbsize, afs.fs_cgsize, (intmax_t)afs.fs_csaddr, -- cgit v1.1 From 31f4b526a608382b0969c11ebab85aabd2f06b35 Mon Sep 17 00:00:00 2001 From: mckusick Date: Thu, 16 May 2013 20:07:08 +0000 Subject: When running the -m option to generate a newfs(8) command suitable for recreating the filesystem, check for and output the -i, -k, and -l options if appropriate. Note the remaining deficiencies of the -m option in the dumpfs(8) manual page. Specifically that newfs(8) options -E, -R, -S, and -T options are not handled and that -p is not useful so is omitted. Also document that newfs(8) options -n and -r are neither checked for nor output but should be. The -r flag is needed if the filesystem uses gjournal(8). PR: bin/163992 Reported by: Dieter Submitted by: Andy Kosela MFC after: 1 week --- sbin/dumpfs/dumpfs.8 | 23 ++++++++++++++++++++++- sbin/dumpfs/dumpfs.c | 7 +++++-- 2 files changed, 27 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/dumpfs/dumpfs.8 b/sbin/dumpfs/dumpfs.8 index 858881a..feb8758 100644 --- a/sbin/dumpfs/dumpfs.8 +++ b/sbin/dumpfs/dumpfs.8 @@ -28,7 +28,7 @@ .\" @(#)dumpfs.8 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd Jul 14, 2011 +.Dd May 16, 2013 .Dt DUMPFS 8 .Os .Sh NAME @@ -76,6 +76,27 @@ is specified, a .Xr newfs 8 command is printed that can be used to generate a new file system with equivalent settings. +Please note that +.Xr newfs 8 +options +.Fl E , +.Fl R , +.Fl S , +and +.Fl T +are not handled and +.Fl p +is not useful in this case so is omitted. +.Xr Newfs 8 +options +.Fl n +and +.Fl r +are neither checked for nor output but should be. +The +.Fl r +flag is needed if the filesystem uses +.Xr gjournal 8 . .Sh SEE ALSO .Xr disktab 5 , .Xr fs 5 , diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c index d04558c..baf3d99 100644 --- a/sbin/dumpfs/dumpfs.c +++ b/sbin/dumpfs/dumpfs.c @@ -417,12 +417,15 @@ marshal(const char *name) printf("-f %d ", fs->fs_fsize); printf("-g %d ", fs->fs_avgfilesize); printf("-h %d ", fs->fs_avgfpdir); - /* -i is dumb */ + printf("-i %jd ", fragroundup(fs, lblktosize(fs, fragstoblks(fs, + fs->fs_fpg)) / fs->fs_ipg)); if (fs->fs_flags & FS_SUJ) printf("-j "); if (fs->fs_flags & FS_GJOURNAL) printf("-J "); - /* -k..l unimplemented */ + printf("-k %jd ", fs->fs_metaspace); + if (fs->fs_flags & FS_MULTILABEL) + printf("-l "); printf("-m %d ", fs->fs_minfree); /* -n unimplemented */ printf("-o "); -- cgit v1.1 From 1d06cba9f7ba5d8236e7e8617cd610b6b303e631 Mon Sep 17 00:00:00 2001 From: delphij Date: Thu, 16 May 2013 21:04:56 +0000 Subject: Constify string pointers. Verified with: sha256(1) MFC after: 2 weeks --- sbin/tunefs/tunefs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c index 2ad01c0..15c6cf0 100644 --- a/sbin/tunefs/tunefs.c +++ b/sbin/tunefs/tunefs.c @@ -84,8 +84,8 @@ static void sbdirty(void); int main(int argc, char *argv[]) { - char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue; - char *tvalue; + const char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue; + const char *tvalue; const char *special, *on; const char *name; int active; @@ -711,7 +711,7 @@ journal_findfile(void) } static void -dir_clear_block(char *block, off_t off) +dir_clear_block(const char *block, off_t off) { struct direct *dp; -- cgit v1.1 From 960402d8a4c86e0690805d08a9234d62a335662e Mon Sep 17 00:00:00 2001 From: melifaro Date: Sat, 18 May 2013 04:49:00 +0000 Subject: Fix ipfw(8) sets of ipv6 addresses handling. Conditionally use stack buffer instead of calling strdup(). PR: bin/104921 MFC after: 2 weeks --- sbin/ipfw/ipfw2.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'sbin') diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 5b37995..577d644 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -2779,13 +2779,19 @@ static ipfw_insn * add_src(ipfw_insn *cmd, char *av, u_char proto, int cblen) { struct in6_addr a; - char *host, *ch; + char *host, *ch, buf[INET6_ADDRSTRLEN]; ipfw_insn *ret = NULL; - - if ((host = strdup(av)) == NULL) - return NULL; - if ((ch = strrchr(host, '/')) != NULL) - *ch = '\0'; + int len; + + /* Copy first address in set if needed */ + if ((ch = strpbrk(av, "/,")) != NULL) { + len = ch - av; + strlcpy(buf, av, sizeof(buf)); + if (len < sizeof(buf)) + buf[len] = '\0'; + host = buf; + } else + host = av; if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 || inet_pton(AF_INET6, host, &a) == 1) @@ -2797,7 +2803,6 @@ add_src(ipfw_insn *cmd, char *av, u_char proto, int cblen) if (ret == NULL && strcmp(av, "any") != 0) ret = cmd; - free(host); return ret; } @@ -2805,13 +2810,19 @@ static ipfw_insn * add_dst(ipfw_insn *cmd, char *av, u_char proto, int cblen) { struct in6_addr a; - char *host, *ch; + char *host, *ch, buf[INET6_ADDRSTRLEN]; ipfw_insn *ret = NULL; - - if ((host = strdup(av)) == NULL) - return NULL; - if ((ch = strrchr(host, '/')) != NULL) - *ch = '\0'; + int len; + + /* Copy first address in set if needed */ + if ((ch = strpbrk(av, "/,")) != NULL) { + len = ch - av; + strlcpy(buf, av, sizeof(buf)); + if (len < sizeof(buf)) + buf[len] = '\0'; + host = buf; + } else + host = av; if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 || inet_pton(AF_INET6, host, &a) == 1) @@ -2823,7 +2834,6 @@ add_dst(ipfw_insn *cmd, char *av, u_char proto, int cblen) if (ret == NULL && strcmp(av, "any") != 0) ret = cmd; - free(host); return ret; } -- cgit v1.1 From d752b745dff91558b15bd929d1f9aa8266169f60 Mon Sep 17 00:00:00 2001 From: jkim Date: Wed, 22 May 2013 17:47:45 +0000 Subject: Improve compatibility with old flex and fix build with GCC. --- sbin/hastd/hast.h | 3 --- sbin/hastd/parse.y | 2 ++ sbin/hastd/token.l | 3 +++ 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/hastd/hast.h b/sbin/hastd/hast.h index b757994..381e195 100644 --- a/sbin/hastd/hast.h +++ b/sbin/hastd/hast.h @@ -259,7 +259,4 @@ struct hast_resource { struct hastd_config *yy_config_parse(const char *config, bool exitonerror); void yy_config_free(struct hastd_config *config); -void yyerror(const char *); -int yylex(void); - #endif /* !_HAST_H_ */ diff --git a/sbin/hastd/parse.y b/sbin/hastd/parse.y index bd0690a..6bfb537 100644 --- a/sbin/hastd/parse.y +++ b/sbin/hastd/parse.y @@ -75,6 +75,8 @@ static char depth1_provname[PATH_MAX]; static char depth1_localpath[PATH_MAX]; static int depth1_metaflush; +extern void yyerror(const char *); +extern int yylex(void); extern void yyrestart(FILE *); static int isitme(const char *name); diff --git a/sbin/hastd/token.l b/sbin/hastd/token.l index a20efd7..e8f6760 100644 --- a/sbin/hastd/token.l +++ b/sbin/hastd/token.l @@ -42,6 +42,9 @@ int depth; int lineno; #define DP do { } while (0) +#define YY_DECL int yylex(void) + +extern int yylex(void); %} %option noinput -- cgit v1.1 From bbed7eb4ffad6ce27570f6efc1384efdb9ca5a4b Mon Sep 17 00:00:00 2001 From: jh Date: Fri, 7 Jun 2013 07:17:46 +0000 Subject: Revert r238399. The "failok" option doesn't have any effect at all unless specified in fstab(5) and combined with the -a flag. The "failok" option is already documented in fstab(5). PR: 177630 No objection: eadler MFC after: 1 week --- sbin/mount/mount.8 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'sbin') diff --git a/sbin/mount/mount.8 b/sbin/mount/mount.8 index 2770658..7cd8026 100644 --- a/sbin/mount/mount.8 +++ b/sbin/mount/mount.8 @@ -28,7 +28,7 @@ .\" @(#)mount.8 8.8 (Berkeley) 6/16/94 .\" $FreeBSD$ .\" -.Dd July 12, 2012 +.Dd June 6, 2011 .Dt MOUNT 8 .Os .Sh NAME @@ -152,11 +152,6 @@ When used with the .Fl u flag, this is the same as specifying the options currently in effect for the mounted file system. -.It Cm failok -If this option is specified, -.Nm -will return 0 even if an error occurs -during the mount of the filesystem. .It Cm force The same as .Fl f ; -- cgit v1.1 From 64a7278134b4fcca2717b660dc511d4b792d12c4 Mon Sep 17 00:00:00 2001 From: hrs Date: Sun, 9 Jun 2013 17:40:06 +0000 Subject: Fix a bug that the gateway address was not shown when a -gateway modifier was used. --- sbin/route/route.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index 48f90a7..c751657 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -848,6 +848,7 @@ newroute(int argc, char **argv) if (!--argc) usage(NULL); getaddr(RTA_GATEWAY, *++argv, 0, nrflags); + gateway = *argv; break; case K_DST: if (!--argc) -- cgit v1.1 From 0c3f6d383d180e43ea57dcf68a41ce554c2ce8d5 Mon Sep 17 00:00:00 2001 From: marcel Date: Sun, 9 Jun 2013 23:34:26 +0000 Subject: Change the set and unset ctlreqs by making the index argument optional. This allows setting attributes on tables. One simply does not provide an index in that case. Otherwise the entry corresponding the index has the attribute set or unset. Use this change to fix a relatively longstanding bug in our GPT scheme that's the result of rev 198097 (relatively harmless) followed by rev 237057 (damaging). The damaging part being that our GPT scheme always has the active flag set on the PMBR slice. This is in violation with EFI. Existing EFI implementions for both x86 and ia64 reject the GPT. As such, GPT disks created by us aren't usable under EFI because of that. After this change, GPT disks never have the active flag set on the PMBR slice. In order to make the GPT disk bootable under some x86 BIOSes, the reason of rev 198097, one must now set the active attribute on the gpt table. The kernel will apply this to the PMBR slice For (S)ATA: gpart set -a active ada0 To fix an existing GPT disk that has the active flag set in the PMBR, and that does not need the flag, use (again for (S)ATA): gpart unset -a active ada0 The EBR, MBR & PC98 schemes, which also impement at least 1 attribute, now check to make sure the entry passed is valid. They do not have attributes that apply to the table. --- sbin/geom/class/part/geom_part.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sbin') diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c index 8a57ca4..9b3e0e5 100644 --- a/sbin/geom/class/part/geom_part.c +++ b/sbin/geom/class/part/geom_part.c @@ -147,10 +147,10 @@ struct g_command PUBSYM(class_commands)[] = { }, { "set", 0, gpart_issue, { { 'a', "attrib", NULL, G_TYPE_STRING }, - { 'i', GPART_PARAM_INDEX, NULL, G_TYPE_NUMBER }, + { 'i', GPART_PARAM_INDEX, G_VAL_OPTIONAL, G_TYPE_NUMBER }, { 'f', "flags", GPART_FLAGS, G_TYPE_STRING }, G_OPT_SENTINEL }, - "-a attrib -i index [-f flags] geom" + "-a attrib [-i index] [-f flags] geom" }, { "show", 0, gpart_show, { { 'l', "show_label", NULL, G_TYPE_BOOL }, @@ -164,10 +164,10 @@ struct g_command PUBSYM(class_commands)[] = { }, { "unset", 0, gpart_issue, { { 'a', "attrib", NULL, G_TYPE_STRING }, - { 'i', GPART_PARAM_INDEX, NULL, G_TYPE_NUMBER }, + { 'i', GPART_PARAM_INDEX, G_VAL_OPTIONAL, G_TYPE_NUMBER }, { 'f', "flags", GPART_FLAGS, G_TYPE_STRING }, G_OPT_SENTINEL }, - "-a attrib -i index [-f flags] geom" + "-a attrib [-i index] [-f flags] geom" }, { "resize", 0, gpart_issue, { { 'a', "alignment", GPART_AUTOFILL, G_TYPE_STRING }, -- cgit v1.1 From e6f73328423acdce70b5f1692dd903c3076b6224 Mon Sep 17 00:00:00 2001 From: flo Date: Tue, 11 Jun 2013 17:46:32 +0000 Subject: Move the check whether the clear flag is set. This has 2 advantages - When operating on a core file (-M) and -c is specified we don't clear the message buffer of the running system. - If we don't have permission to clear the buffer print the error message only. That's what Linux does in this case, where this feature was ported from, and it ensures that the error message doesn't get lost in the noise. Discussed with: antoine, cognet Approved by: cognet --- sbin/dmesg/dmesg.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sbin') diff --git a/sbin/dmesg/dmesg.c b/sbin/dmesg/dmesg.c index 1d548a7..f0fcb81 100644 --- a/sbin/dmesg/dmesg.c +++ b/sbin/dmesg/dmesg.c @@ -120,6 +120,9 @@ main(int argc, char *argv[]) errx(1, "malloc failed"); if (sysctlbyname("kern.msgbuf", bp, &buflen, NULL, 0) == -1) err(1, "sysctl kern.msgbuf"); + if (clear) + if (sysctlbyname("kern.msgbuf_clear", NULL, NULL, &clear, sizeof(int))) + err(1, "sysctl kern.msgbuf_clear"); } else { /* Read in kernel message buffer and do sanity checks. */ kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg"); @@ -196,10 +199,6 @@ main(int argc, char *argv[]) (void)strvisx(visbp, p, nextp - p, 0); (void)printf("%s", visbp); } - if (clear) - if (sysctlbyname("kern.msgbuf_clear", NULL, NULL, &clear, sizeof(int))) - err(1, "sysctl kern.msgbuf_clear"); - exit(0); } -- cgit v1.1 From efd62e8968170842115fd3214dacd8c6daca3e19 Mon Sep 17 00:00:00 2001 From: mav Date: Wed, 12 Jun 2013 16:13:05 +0000 Subject: Use CAM_DIR_NONE for requests without data. Wrong values there confuse some drivers. MFC after: 1 week --- sbin/camcontrol/camcontrol.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sbin') diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 7a374a4..db84ddb 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -1784,7 +1784,7 @@ ata_read_native_max(struct cam_device *device, int retry_count, error = ata_do_cmd(device, ccb, retry_count, - /*flags*/CAM_DIR_IN, + /*flags*/CAM_DIR_NONE, /*protocol*/protocol, /*ata_flags*/AP_FLAG_CHK_COND, /*tag_action*/MSG_SIMPLE_Q_TAG, @@ -1828,7 +1828,7 @@ atahpa_set_max(struct cam_device *device, int retry_count, error = ata_do_cmd(device, ccb, retry_count, - /*flags*/CAM_DIR_OUT, + /*flags*/CAM_DIR_NONE, /*protocol*/protocol, /*ata_flags*/AP_FLAG_CHK_COND, /*tag_action*/MSG_SIMPLE_Q_TAG, @@ -1895,7 +1895,7 @@ atahpa_lock(struct cam_device *device, int retry_count, error = ata_do_cmd(device, ccb, retry_count, - /*flags*/CAM_DIR_OUT, + /*flags*/CAM_DIR_NONE, /*protocol*/protocol, /*ata_flags*/AP_FLAG_CHK_COND, /*tag_action*/MSG_SIMPLE_Q_TAG, @@ -1962,7 +1962,7 @@ atahpa_freeze_lock(struct cam_device *device, int retry_count, error = ata_do_cmd(device, ccb, retry_count, - /*flags*/CAM_DIR_OUT, + /*flags*/CAM_DIR_NONE, /*protocol*/protocol, /*ata_flags*/AP_FLAG_CHK_COND, /*tag_action*/MSG_SIMPLE_Q_TAG, -- cgit v1.1 From 42bc6c11c813277bf772a78e759cc8c79746e7fd Mon Sep 17 00:00:00 2001 From: mav Date: Wed, 12 Jun 2013 19:21:23 +0000 Subject: Fix build after r251654. --- sbin/camcontrol/camcontrol.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sbin') diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index db84ddb..35826c5 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -6947,18 +6947,18 @@ findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr) struct cam_devitem *item; STAILQ_FOREACH(item, &devlist->dev_queue, links) { - uint8_t *item_addr; + struct scsi_vpd_id_descriptor *idd; /* * XXX KDM look for LUN IDs as well? */ - item_addr = scsi_get_devid(item->device_id, + idd = scsi_get_devid(item->device_id, item->device_id_len, scsi_devid_is_sas_target); - if (item_addr == NULL) + if (idd == NULL) continue; - if (scsi_8btou64(item_addr) == sasaddr) + if (scsi_8btou64(idd->identifier) == sasaddr) return (item); } -- cgit v1.1 From 5abd78284cc4ac0a203a37fcbdacb389c96dc55e Mon Sep 17 00:00:00 2001 From: mav Date: Fri, 14 Jun 2013 08:26:58 +0000 Subject: Improve firmware download status check. Previous check was insufficient for ATA since it ignored transport errors like command timeouts, while for SCSI it was just wrong. --- sbin/camcontrol/fwdownload.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'sbin') diff --git a/sbin/camcontrol/fwdownload.c b/sbin/camcontrol/fwdownload.c index daa1520..2fa9ba4 100644 --- a/sbin/camcontrol/fwdownload.c +++ b/sbin/camcontrol/fwdownload.c @@ -370,17 +370,15 @@ fw_download_img(struct cam_device *cam_dev, const struct fw_vendor *vp, } if (!sim_mode) { /* Execute the command. */ - if (cam_send_ccb(cam_dev, ccb) < 0) { + if (cam_send_ccb(cam_dev, ccb) < 0 || + (ccb->ccb_h.status & CAM_STATUS_MASK) != + CAM_REQ_CMP) { warnx("Error writing image to device"); if (printerrors) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); goto bailout; } - if (ccb->ataio.res.status != 0 /*&& !last_pkt*/) { - cam_error_print(cam_dev, ccb, CAM_ESF_ALL, - CAM_EPF_ALL, stderr); - } } /* Prepare next round. */ pkt_count++; -- cgit v1.1 From 4ea862e26e350153cca8c335600598f96a5eb125 Mon Sep 17 00:00:00 2001 From: ed Date: Sat, 15 Jun 2013 22:17:59 +0000 Subject: Let hastd use C11 atomics. C11 atomics now work on all the architectures. Have at least a single piece of software in our base system that uses C11 atomics. This somewhat makes it less likely that we break it because of LLVM imports, etc. --- sbin/hastd/refcnt.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sbin') diff --git a/sbin/hastd/refcnt.h b/sbin/hastd/refcnt.h index 1246043..5e3fb34 100644 --- a/sbin/hastd/refcnt.h +++ b/sbin/hastd/refcnt.h @@ -32,24 +32,24 @@ #ifndef __REFCNT_H__ #define __REFCNT_H__ -#include +#include #include "pjdlog.h" -typedef unsigned int refcnt_t; +typedef atomic_uint refcnt_t; static __inline void refcnt_init(refcnt_t *count, unsigned int v) { - *count = v; + atomic_init(count, v); } static __inline void refcnt_acquire(refcnt_t *count) { - atomic_add_acq_int(count, 1); + atomic_fetch_add_explicit(count, 1, memory_order_acquire); } static __inline unsigned int @@ -58,7 +58,7 @@ refcnt_release(refcnt_t *count) unsigned int old; /* XXX: Should this have a rel membar? */ - old = atomic_fetchadd_int(count, -1); + old = atomic_fetch_sub(count, 1); PJDLOG_ASSERT(old > 0); return (old - 1); } -- cgit v1.1 From 7d32f7dfe8a0f0c6e71a6a3de35fa0d21ca1fef4 Mon Sep 17 00:00:00 2001 From: hrs Date: Thu, 20 Jun 2013 14:30:16 +0000 Subject: - Add "-f file" support to listing mode (-l). When a -f option is specified, only md(4) devices which have the specified file as backing store are displayed. - Use MD_NAME instead of "md". - Use _PATH_DEV instead of "/dev/". MFC after: 1 week --- sbin/mdconfig/mdconfig.8 | 16 +++++++++++++- sbin/mdconfig/mdconfig.c | 54 +++++++++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 25 deletions(-) (limited to 'sbin') diff --git a/sbin/mdconfig/mdconfig.8 b/sbin/mdconfig/mdconfig.8 index c18027c..b3cc110 100644 --- a/sbin/mdconfig/mdconfig.8 +++ b/sbin/mdconfig/mdconfig.8 @@ -41,7 +41,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 3, 2012 +.Dd June 20, 2013 .Dt MDCONFIG 8 .Os .Sh NAME @@ -72,6 +72,7 @@ .Fl l .Op Fl n .Op Fl v +.Op Fl f Ar file .Op Fl u Ar unit .Nm .Ar file @@ -131,6 +132,19 @@ List configured devices. If given with .Fl u , display details about that particular device. +If given with +.Fl f Ar file , +display +.Xr md 4 +device names of which +.Ar file +is used as the backing store. +If both of +.Fl u +and +.Fl f +options are specified, +display devices which match the two conditions. If the .Fl v option is specified, show all details. diff --git a/sbin/mdconfig/mdconfig.c b/sbin/mdconfig/mdconfig.c index 70cefe9..c04b876 100644 --- a/sbin/mdconfig/mdconfig.c +++ b/sbin/mdconfig/mdconfig.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -59,9 +60,9 @@ static int nflag; static void usage(void); static void md_set_file(const char *); -static int md_find(char *, const char *); -static int md_query(char *name); -static int md_list(char *units, int opt); +static int md_find(const char *, const char *); +static int md_query(const char *, const int, const char *); +static int md_list(const char *, int, const char *); static char *geom_config_get(struct gconf *g, const char *name); static void md_prthumanval(char *length); @@ -82,7 +83,7 @@ usage(void) " [-x sectors/track] [-y heads/cylinder]\n" " mdconfig -d -u unit [-o [no]force]\n" " mdconfig -r -u unit -s size [-o [no]force]\n" -" mdconfig -l [-v] [-n] [-u unit]\n" +" mdconfig -l [-v] [-n] [-f file] [-u unit]\n" " mdconfig file\n"); fprintf(stderr, "\t\ttype = {malloc, vnode, swap}\n"); fprintf(stderr, "\t\toption = {cluster, compress, reserve}\n"); @@ -215,7 +216,7 @@ main(int argc, char **argv) errx(1, "unknown suffix on -s argument"); break; case 'u': - if (!strncmp(optarg, "/dev/", 5)) + if (!strncmp(optarg, _PATH_DEV, 5)) optarg += 5; if (!strncmp(optarg, MD_NAME, sizeof(MD_NAME) - 1)) optarg += sizeof(MD_NAME) - 1; @@ -298,8 +299,8 @@ main(int argc, char **argv) errx(1, "-x can only be used with -a"); if (mdio.md_fwheads != 0) errx(1, "-y can only be used with -a"); - if (fflag != NULL) - errx(1, "-f can only be used with -a"); + if (fflag != NULL && action != LIST) + errx(1, "-f can only be used with -a and -l"); if (tflag != NULL) errx(1, "-t can only be used with -a"); if (argc > 0) @@ -333,14 +334,14 @@ main(int argc, char **argv) if (!kld_isloaded("g_md") && kld_load("geom_md") == -1) err(1, "failed to load geom_md module"); - fd = open("/dev/" MDCTL_NAME, O_RDWR, 0); + fd = open(_PATH_DEV MDCTL_NAME, O_RDWR, 0); if (fd < 0) - err(1, "open(/dev/%s)", MDCTL_NAME); + err(1, "open(%s%s)", _PATH_DEV, MDCTL_NAME); if (action == ATTACH) { i = ioctl(fd, MDIOCATTACH, &mdio); if (i < 0) - err(1, "ioctl(/dev/%s)", MDCTL_NAME); + err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); if (mdio.md_options & MD_AUTOUNIT) printf("%s%d\n", nflag ? "" : MD_NAME, mdio.md_unit); } else if (action == DETACH) { @@ -348,22 +349,22 @@ main(int argc, char **argv) errx(1, "-d requires -u"); i = ioctl(fd, MDIOCDETACH, &mdio); if (i < 0) - err(1, "ioctl(/dev/%s)", MDCTL_NAME); + err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); } else if (action == RESIZE) { if (mdio.md_options & MD_AUTOUNIT) errx(1, "-r requires -u"); i = ioctl(fd, MDIOCRESIZE, &mdio); if (i < 0) - err(1, "ioctl(/dev/%s)", MDCTL_NAME); + err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME); } else if (action == LIST) { if (mdio.md_options & MD_AUTOUNIT) { /* * Listing all devices. This is why we pass NULL * together with OPT_LIST. */ - md_list(NULL, OPT_LIST | vflag); + md_list(NULL, OPT_LIST | vflag, fflag); } else - return (md_query(uflag)); + return (md_query(uflag, vflag, fflag)); } else usage(); close(fd); @@ -397,7 +398,7 @@ md_set_file(const char *fn) * between list and query mode. */ static int -md_list(char *units, int opt) +md_list(const char *units, int opt, const char *fflag) { struct gmesh gm; struct gprovider *pp; @@ -441,15 +442,20 @@ md_list(char *units, int opt) found = 1; } gc = &pp->lg_config; - if (nflag && strncmp(pp->lg_name, "md", 2) == 0) + type = geom_config_get(gc, "type"); + if (strcmp(type, "vnode") == 0) { + file = geom_config_get(gc, "file"); + if (fflag != NULL && + strcmp(fflag, file) != 0) + continue; + } + if (nflag && strncmp(pp->lg_name, MD_NAME, 2) == 0) printf("%s", pp->lg_name + 2); else printf("%s", pp->lg_name); - if (opt & OPT_VERBOSE || opt & OPT_UNIT) { - type = geom_config_get(gc, "type"); - if (strcmp(type, "vnode") == 0) - file = geom_config_get(gc, "file"); + if (opt & OPT_VERBOSE || + ((opt & OPT_UNIT) && fflag == NULL)) { length = geom_config_get(gc, "length"); printf("\t%s\t", type); if (length != NULL) @@ -497,7 +503,7 @@ geom_config_get(struct gconf *g, const char *name) * otherwise. */ static int -md_find(char *list, const char *name) +md_find(const char *list, const char *name) { int ret; char num[16]; @@ -508,7 +514,7 @@ md_find(char *list, const char *name) if (ptr == NULL) return (-1); for (p = ptr; (u = strsep(&p, ",")) != NULL;) { - if (strncmp(u, "/dev/", 5) == 0) + if (strncmp(u, _PATH_DEV, 5) == 0) u += 5; /* Just in case user specified number instead of full name */ snprintf(num, sizeof(num), "md%s", u); @@ -538,8 +544,8 @@ md_prthumanval(char *length) } static int -md_query(char *name) +md_query(const char *name, const int opt, const char *fflag) { - return (md_list(name, OPT_UNIT)); + return (md_list(name, opt | OPT_UNIT, fflag)); } -- cgit v1.1 From 53795e137482aa52cde35040e4111b75cb2296a1 Mon Sep 17 00:00:00 2001 From: hrs Date: Thu, 20 Jun 2013 17:01:02 +0000 Subject: eturn -1 when the specified backing store file is not found in the md device list. MFC after: 1 week --- sbin/mdconfig/mdconfig.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'sbin') diff --git a/sbin/mdconfig/mdconfig.c b/sbin/mdconfig/mdconfig.c index c04b876..28221d4 100644 --- a/sbin/mdconfig/mdconfig.c +++ b/sbin/mdconfig/mdconfig.c @@ -362,7 +362,7 @@ main(int argc, char **argv) * Listing all devices. This is why we pass NULL * together with OPT_LIST. */ - md_list(NULL, OPT_LIST | vflag, fflag); + return (md_list(NULL, OPT_LIST | vflag, fflag)); } else return (md_query(uflag, vflag, fflag)); } else @@ -408,7 +408,7 @@ md_list(const char *units, int opt, const char *fflag) struct ggeom *gg; struct gclass *gcl; void *sq; - int retcode, found; + int retcode, ffound, ufound; char *type, *file, *length; type = file = length = NULL; @@ -423,7 +423,7 @@ md_list(const char *units, int opt, const char *fflag) if (sq == NULL) return (-1); - found = 0; + ffound = ufound = 0; while ((gsp = geom_stats_snapshot_next(sq)) != NULL) { gid = geom_lookupid(&gm, gsp->id); if (gid == NULL) @@ -439,7 +439,7 @@ md_list(const char *units, int opt, const char *fflag) if (retcode != 1) continue; else - found = 1; + ufound = 1; } gc = &pp->lg_config; type = geom_config_get(gc, "type"); @@ -448,6 +448,8 @@ md_list(const char *units, int opt, const char *fflag) if (fflag != NULL && strcmp(fflag, file) != 0) continue; + else + ffound = 1; } if (nflag && strncmp(pp->lg_name, MD_NAME, 2) == 0) printf("%s", pp->lg_name + 2); @@ -476,7 +478,9 @@ md_list(const char *units, int opt, const char *fflag) printf("\n"); /* XXX: Check if it's enough to clean everything. */ geom_stats_snapshot_free(sq); - if ((opt & OPT_UNIT) && found) + if (((opt & OPT_UNIT) && (fflag == NULL) && ufound) || + ((opt & OPT_UNIT) == 0 && (fflag != NULL) && ffound) || + ((opt & OPT_UNIT) && (fflag != NULL) && ufound && ffound)) return (0); else return (-1); -- cgit v1.1 From 0743eae837977d96ffb4caa1d0c2045acf4781a1 Mon Sep 17 00:00:00 2001 From: hrs Date: Fri, 21 Jun 2013 01:47:22 +0000 Subject: - Use length of _PATH_DEV instead of a hardcoded value[*]. - Use MD_NAME for "md". Pointed out by: trasz [*] MFC after: 1 week --- sbin/mdconfig/mdconfig.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sbin') diff --git a/sbin/mdconfig/mdconfig.c b/sbin/mdconfig/mdconfig.c index 28221d4..1a33905 100644 --- a/sbin/mdconfig/mdconfig.c +++ b/sbin/mdconfig/mdconfig.c @@ -216,8 +216,8 @@ main(int argc, char **argv) errx(1, "unknown suffix on -s argument"); break; case 'u': - if (!strncmp(optarg, _PATH_DEV, 5)) - optarg += 5; + if (!strncmp(optarg, _PATH_DEV, sizeof(_PATH_DEV) - 1)) + optarg += sizeof(_PATH_DEV) - 1; if (!strncmp(optarg, MD_NAME, sizeof(MD_NAME) - 1)) optarg += sizeof(MD_NAME) - 1; uflag = optarg; @@ -510,7 +510,7 @@ static int md_find(const char *list, const char *name) { int ret; - char num[16]; + char num[PATH_MAX]; char *ptr, *p, *u; ret = 0; @@ -518,10 +518,10 @@ md_find(const char *list, const char *name) if (ptr == NULL) return (-1); for (p = ptr; (u = strsep(&p, ",")) != NULL;) { - if (strncmp(u, _PATH_DEV, 5) == 0) - u += 5; + if (strncmp(u, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) + u += sizeof(_PATH_DEV) - 1; /* Just in case user specified number instead of full name */ - snprintf(num, sizeof(num), "md%s", u); + snprintf(num, sizeof(num), "%s%s", MD_NAME, u); if (strcmp(u, name) == 0 || strcmp(num, name) == 0) { ret = 1; break; -- cgit v1.1 From 247f8065f6cb2f359273faf17f2082f1db74ea8a Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 22:50:49 +0000 Subject: Add an open_dev() helper function to be used in the various places where nvmecontrol needs to open a handle to a controller or namespace device node. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/nvmecontrol.c | 166 ++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 103 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index fd55b42..9e0b8ec 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -1,5 +1,5 @@ /*- - * Copyright (C) 2012 Intel Corporation + * Copyright (C) 2012-2013 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -258,13 +258,42 @@ read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata) } } +static int +open_dev(const char *str, int *fd, int show_error, int exit_on_error) +{ + struct stat devstat; + char full_path[64]; + + snprintf(full_path, sizeof(full_path), "/dev/%s", str); + if (stat(full_path, &devstat) != 0) { + if (show_error) + fprintf(stderr, "error\n"); + if (exit_on_error) + exit(EX_NOINPUT); + else + return (EX_NOINPUT); + } + + *fd = open(full_path, O_RDWR); + if (*fd < 0) { + if (show_error) + printf("Could not open %s. errno=%d (%s)\n", full_path, + errno, strerror(errno)); + if (exit_on_error) + exit(EX_NOPERM); + else + return (EX_NOPERM); + } + + return (EX_OK); +} + static void devlist(int argc, char *argv[]) { struct nvme_controller_data cdata; struct nvme_namespace_data nsdata; - struct stat devstat; - char name[64], path[64]; + char name[64]; uint32_t i; int ch, ctrlr, exit_code, fd, found; @@ -283,21 +312,18 @@ devlist(int argc, char *argv[]) while (1) { ctrlr++; sprintf(name, "nvme%d", ctrlr); - sprintf(path, "/dev/%s", name); - if (stat(path, &devstat) != 0) - break; + exit_code = open_dev(name, &fd, 0, 0); - found++; - - fd = open(path, O_RDWR); - if (fd < 0) { - printf("Could not open %s. errno=%d (%s)\n", path, - errno, strerror(errno)); - exit_code = EX_NOPERM; + if (exit_code == EX_NOINPUT) + break; + else if (exit_code == EX_NOPERM) { + printf("Could not open /dev/%s, errno = %d (%s)\n", + name, errno, strerror(errno)); continue; } + found++; read_controller_data(fd, &cdata); printf("%6s: %s\n", name, cdata.mn); @@ -310,20 +336,20 @@ devlist(int argc, char *argv[]) (long long)ns_get_sector_size(&nsdata) / 1024 / 1024 / 1024); } + + close(fd); } if (found == 0) printf("No NVMe controllers found.\n"); - exit(exit_code); + exit(EX_OK); } static void identify_ctrlr(int argc, char *argv[]) { struct nvme_controller_data cdata; - struct stat devstat; - char path[64]; int ch, fd, hexflag = 0, hexlength; int verboseflag = 0; @@ -340,22 +366,9 @@ identify_ctrlr(int argc, char *argv[]) } } - sprintf(path, "/dev/%s", argv[optind]); - - if (stat(path, &devstat) < 0) { - printf("Invalid device node %s. errno=%d (%s)\n", path, errno, - strerror(errno)); - exit(EX_IOERR); - } - - fd = open(path, O_RDWR); - if (fd < 0) { - printf("Could not open %s. errno=%d (%s)\n", path, errno, - strerror(errno)); - exit(EX_NOPERM); - } - + open_dev(argv[optind], &fd, 1, 1); read_controller_data(fd, &cdata); + close(fd); if (hexflag == 1) { if (verboseflag == 1) @@ -380,7 +393,6 @@ static void identify_ns(int argc, char *argv[]) { struct nvme_namespace_data nsdata; - struct stat devstat; char path[64]; char *nsloc; int ch, fd, hexflag = 0, hexlength, nsid; @@ -404,25 +416,18 @@ identify_ns(int argc, char *argv[]) * This is a cleaner check for cases where the correct controller * is specified, but an invalid namespace on that controller. */ - sprintf(path, "/dev/%s", argv[optind]); - if (stat(path, &devstat) < 0) { - printf("Invalid device node %s. errno=%d (%s)\n", path, errno, - strerror(errno)); - exit(EX_IOERR); - } - - nsloc = strstr(argv[optind], "ns"); - if (nsloc == NULL) { - printf("Invalid namepsace %s.\n", argv[optind]); - exit(EX_IOERR); - } + open_dev(argv[optind], &fd, 1, 1); + close(fd); /* * Pull the namespace id from the string. +2 skips past the "ns" part - * of the string. + * of the string. Don't search past 10 characters into the string, + * otherwise we know it is malformed. */ - nsid = strtol(nsloc + 2, NULL, 10); - if (nsid == 0 && errno != 0) { + nsloc = strnstr(argv[optind], "ns", 10); + if (nsloc != NULL) + nsid = strtol(nsloc + 2, NULL, 10); + if (nsloc == NULL || (nsid == 0 && errno != 0)) { printf("Invalid namespace ID %s.\n", argv[optind]); exit(EX_IOERR); } @@ -432,22 +437,10 @@ identify_ns(int argc, char *argv[]) * since it is an admin cmd. So the path should only include the * nvmeX part of the nvmeXnsY string. */ - sprintf(path, "/dev/"); - strncat(path, argv[optind], nsloc - argv[optind]); - if (stat(path, &devstat) < 0) { - printf("Invalid device node %s. errno=%d (%s)\n", path, errno, - strerror(errno)); - exit(EX_IOERR); - } - - fd = open(path, O_RDWR); - if (fd < 0) { - printf("Could not open %s. errno=%d (%s)\n", path, errno, - strerror(errno)); - exit(EX_NOPERM); - } - + snprintf(path, nsloc - argv[optind] + 1, "%s", argv[optind]); + open_dev(path, &fd, 1, 1); read_namespace_data(fd, nsid, &nsdata); + close(fd); if (hexflag == 1) { if (verboseflag == 1) @@ -480,12 +473,6 @@ identify(int argc, char *argv[]) target = argv[optind]; - /* Specified device node must have "nvme" in it. */ - if (strstr(argv[optind], "nvme") == NULL) { - printf("Invalid device node '%s'.\n", argv[optind]); - exit(EX_IOERR); - } - optreset = 1; optind = 1; @@ -538,14 +525,11 @@ perftest(int argc, char *argv[]) int fd; char ch; char *p; - const char *name; - char path[64]; u_long ioctl_cmd = NVME_IO_TEST; bool nflag, oflag, sflag, tflag; int perthread = 0; nflag = oflag = sflag = tflag = false; - name = NULL; memset(&io_test, 0, sizeof(io_test)); @@ -623,26 +607,18 @@ perftest(int argc, char *argv[]) } } - name = argv[optind]; - - if (!nflag || !oflag || !sflag || !tflag || name == NULL) + if (!nflag || !oflag || !sflag || !tflag || optind >= argc) perftest_usage(); - sprintf(path, "/dev/%s", name); - - fd = open(path, O_RDWR); - if (fd < 0) { - fprintf(stderr, "%s not valid device. errno=%d (%s)\n", path, - errno, strerror(errno)); - perftest_usage(); - } - + open_dev(argv[optind], &fd, 1, 1); if (ioctl(fd, ioctl_cmd, &io_test) < 0) { fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno, strerror(errno)); + close(fd); exit(EX_IOERR); } + close(fd); print_perftest(&io_test, perthread); exit(EX_OK); } @@ -650,9 +626,7 @@ perftest(int argc, char *argv[]) static void reset_ctrlr(int argc, char *argv[]) { - struct stat devstat; - char path[64]; - int ch, fd; + int ch, fd; while ((ch = getopt(argc, argv, "")) != -1) { switch ((char)ch) { @@ -661,24 +635,10 @@ reset_ctrlr(int argc, char *argv[]) } } - sprintf(path, "/dev/%s", argv[optind]); - - if (stat(path, &devstat) < 0) { - printf("Invalid device node %s. errno=%d (%s)\n", path, errno, - strerror(errno)); - exit(EX_IOERR); - } - - fd = open(path, O_RDWR); - if (fd < 0) { - printf("Could not open %s. errno=%d (%s)\n", path, errno, - strerror(errno)); - exit(EX_NOPERM); - } - + open_dev(argv[optind], &fd, 1, 1); if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) { - printf("Reset request to %s failed. errno=%d (%s)\n", path, - errno, strerror(errno)); + printf("Reset request to %s failed. errno=%d (%s)\n", + argv[optind], errno, strerror(errno)); exit(EX_IOERR); } -- cgit v1.1 From d44eb52f68b14bcc0506717efc547a9699e12ca1 Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 22:53:21 +0000 Subject: Add separate *_usage() functions for each nvmecontrol command. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/nvmecontrol.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 9e0b8ec..9ac5d19 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -289,6 +289,14 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) } static void +devlist_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, DEVLIST_USAGE); + exit(EX_USAGE); +} + +static void devlist(int argc, char *argv[]) { struct nvme_controller_data cdata; @@ -302,7 +310,7 @@ devlist(int argc, char *argv[]) while ((ch = getopt(argc, argv, "")) != -1) { switch ((char)ch) { default: - usage(); + devlist_usage(); } } @@ -347,6 +355,14 @@ devlist(int argc, char *argv[]) } static void +identify_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, IDENTIFY_USAGE); + exit(EX_USAGE); +} + +static void identify_ctrlr(int argc, char *argv[]) { struct nvme_controller_data cdata; @@ -362,7 +378,7 @@ identify_ctrlr(int argc, char *argv[]) hexflag = 1; break; default: - usage(); + identify_usage(); } } @@ -382,7 +398,7 @@ identify_ctrlr(int argc, char *argv[]) if (verboseflag == 1) { printf("-v not currently supported without -x.\n"); - usage(); + identify_usage(); } print_controller(&cdata); @@ -407,7 +423,7 @@ identify_ns(int argc, char *argv[]) hexflag = 1; break; default: - usage(); + identify_usage(); } } @@ -454,7 +470,7 @@ identify_ns(int argc, char *argv[]) if (verboseflag == 1) { printf("-v not currently supported without -x.\n"); - usage(); + identify_usage(); } print_namespace(&nsdata); @@ -467,7 +483,7 @@ identify(int argc, char *argv[]) char *target; if (argc < 2) - usage(); + identify_usage(); while (getopt(argc, argv, "vx") != -1) ; @@ -624,6 +640,14 @@ perftest(int argc, char *argv[]) } static void +reset_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, RESET_USAGE); + exit(EX_USAGE); +} + +static void reset_ctrlr(int argc, char *argv[]) { int ch, fd; @@ -631,7 +655,7 @@ reset_ctrlr(int argc, char *argv[]) while ((ch = getopt(argc, argv, "")) != -1) { switch ((char)ch) { default: - usage(); + reset_usage(); } } -- cgit v1.1 From 9be98f32603c4fcdf33df3e8835aacd52634c434 Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 22:58:59 +0000 Subject: Break out code related to the devlist command into a separate source file. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/Makefile | 1 + sbin/nvmecontrol/devlist.c | 114 +++++++++++++++++++++++++++++++++++++++++ sbin/nvmecontrol/nvmecontrol.c | 96 ++-------------------------------- sbin/nvmecontrol/nvmecontrol.h | 56 ++++++++++++++++++++ 4 files changed, 175 insertions(+), 92 deletions(-) create mode 100644 sbin/nvmecontrol/devlist.c create mode 100644 sbin/nvmecontrol/nvmecontrol.h (limited to 'sbin') diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index 04cefaa..4440c6f 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -1,6 +1,7 @@ # $FreeBSD$ PROG= nvmecontrol +SRCS= nvmecontrol.c devlist.c MAN= nvmecontrol.8 .include diff --git a/sbin/nvmecontrol/devlist.c b/sbin/nvmecontrol/devlist.c new file mode 100644 index 0000000..4085e7e --- /dev/null +++ b/sbin/nvmecontrol/devlist.c @@ -0,0 +1,114 @@ +/*- + * Copyright (C) 2012-2013 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nvmecontrol.h" + +static void +devlist_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, DEVLIST_USAGE); + exit(EX_USAGE); +} + +static inline uint32_t +ns_get_sector_size(struct nvme_namespace_data *nsdata) +{ + + return (1 << nsdata->lbaf[0].lbads); +} + +void +devlist(int argc, char *argv[]) +{ + struct nvme_controller_data cdata; + struct nvme_namespace_data nsdata; + char name[64]; + uint32_t i; + int ch, ctrlr, exit_code, fd, found; + + exit_code = EX_OK; + + while ((ch = getopt(argc, argv, "")) != -1) { + switch ((char)ch) { + default: + devlist_usage(); + } + } + + ctrlr = -1; + found = 0; + + while (1) { + ctrlr++; + sprintf(name, "nvme%d", ctrlr); + + exit_code = open_dev(name, &fd, 0, 0); + + if (exit_code == EX_NOINPUT) + break; + else if (exit_code == EX_NOPERM) { + printf("Could not open /dev/%s, errno = %d (%s)\n", + name, errno, strerror(errno)); + continue; + } + + found++; + read_controller_data(fd, &cdata); + printf("%6s: %s\n", name, cdata.mn); + + for (i = 0; i < cdata.nn; i++) { + sprintf(name, "nvme%dns%d", ctrlr, i+1); + read_namespace_data(fd, i+1, &nsdata); + printf(" %10s (%lldGB)\n", + name, + nsdata.nsze * + (long long)ns_get_sector_size(&nsdata) / + 1024 / 1024 / 1024); + } + + close(fd); + } + + if (found == 0) + printf("No NVMe controllers found.\n"); + + exit(EX_OK); +} diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 9ac5d19..a3286c1 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -31,8 +31,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include #include #include @@ -44,20 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include -#define DEVLIST_USAGE \ -" nvmecontrol devlist\n" - -#define IDENTIFY_USAGE \ -" nvmecontrol identify \n" - -#define PERFTEST_USAGE \ -" nvmecontrol perftest <-n num_threads> <-o read|write>\n" \ -" <-s size_in_bytes> <-t time_in_seconds>\n" \ -" <-i intr|wait> [-f refthread] [-p]\n" \ -" \n" - -#define RESET_USAGE \ -" nvmecontrol reset \n" +#include "nvmecontrol.h" static void perftest_usage(void); @@ -203,14 +188,7 @@ print_namespace(struct nvme_namespace_data *nsdata) } } -static uint32_t -ns_get_sector_size(struct nvme_namespace_data *nsdata) -{ - - return (1 << nsdata->lbaf[0].lbads); -} - -static void +void read_controller_data(int fd, struct nvme_controller_data *cdata) { struct nvme_pt_command pt; @@ -234,7 +212,7 @@ read_controller_data(int fd, struct nvme_controller_data *cdata) } } -static void +void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata) { struct nvme_pt_command pt; @@ -258,7 +236,7 @@ read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata) } } -static int +int open_dev(const char *str, int *fd, int show_error, int exit_on_error) { struct stat devstat; @@ -289,72 +267,6 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) } static void -devlist_usage(void) -{ - fprintf(stderr, "usage:\n"); - fprintf(stderr, DEVLIST_USAGE); - exit(EX_USAGE); -} - -static void -devlist(int argc, char *argv[]) -{ - struct nvme_controller_data cdata; - struct nvme_namespace_data nsdata; - char name[64]; - uint32_t i; - int ch, ctrlr, exit_code, fd, found; - - exit_code = EX_OK; - - while ((ch = getopt(argc, argv, "")) != -1) { - switch ((char)ch) { - default: - devlist_usage(); - } - } - - ctrlr = -1; - found = 0; - - while (1) { - ctrlr++; - sprintf(name, "nvme%d", ctrlr); - - exit_code = open_dev(name, &fd, 0, 0); - - if (exit_code == EX_NOINPUT) - break; - else if (exit_code == EX_NOPERM) { - printf("Could not open /dev/%s, errno = %d (%s)\n", - name, errno, strerror(errno)); - continue; - } - - found++; - read_controller_data(fd, &cdata); - printf("%6s: %s\n", name, cdata.mn); - - for (i = 0; i < cdata.nn; i++) { - sprintf(name, "nvme%dns%d", ctrlr, i+1); - read_namespace_data(fd, i+1, &nsdata); - printf(" %10s (%lldGB)\n", - name, - nsdata.nsze * - (long long)ns_get_sector_size(&nsdata) / - 1024 / 1024 / 1024); - } - - close(fd); - } - - if (found == 0) - printf("No NVMe controllers found.\n"); - - exit(EX_OK); -} - -static void identify_usage(void) { fprintf(stderr, "usage:\n"); diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h new file mode 100644 index 0000000..a026ced --- /dev/null +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -0,0 +1,56 @@ +/*- + * Copyright (C) 2012-2013 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __NVMECONTROL_H__ +#define __NVMECONTROL_H__ + +#include + +#define DEVLIST_USAGE \ +" nvmecontrol devlist\n" + +#define IDENTIFY_USAGE \ +" nvmecontrol identify \n" + +#define PERFTEST_USAGE \ +" nvmecontrol perftest <-n num_threads> <-o read|write>\n" \ +" <-s size_in_bytes> <-t time_in_seconds>\n" \ +" <-i intr|wait> [-f refthread] [-p]\n" \ +" \n" + +#define RESET_USAGE \ +" nvmecontrol reset \n" + +int open_dev(const char *str, int *fd, int show_error, int exit_on_error); +void read_controller_data(int fd, struct nvme_controller_data *cdata); +void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); + +void devlist(int argc, char *argv[]); + +#endif + -- cgit v1.1 From b1ea6d920cace0d525411064ebed4d92092d9074 Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 23:00:42 +0000 Subject: Break out code related to the identify command into a separate source file. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/Makefile | 2 +- sbin/nvmecontrol/identify.c | 321 +++++++++++++++++++++++++++++++++++++++++ sbin/nvmecontrol/nvmecontrol.c | 279 ----------------------------------- sbin/nvmecontrol/nvmecontrol.h | 1 + 4 files changed, 323 insertions(+), 280 deletions(-) create mode 100644 sbin/nvmecontrol/identify.c (limited to 'sbin') diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index 4440c6f..e710942 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= nvmecontrol -SRCS= nvmecontrol.c devlist.c +SRCS= nvmecontrol.c devlist.c identify.c MAN= nvmecontrol.8 .include diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c new file mode 100644 index 0000000..6dcbebd --- /dev/null +++ b/sbin/nvmecontrol/identify.c @@ -0,0 +1,321 @@ +/*- + * Copyright (C) 2012-2013 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nvmecontrol.h" + +static void +print_controller_hex(struct nvme_controller_data *cdata, uint32_t length) +{ + uint32_t *p; + uint32_t i, j; + + p = (uint32_t *)cdata; + length /= sizeof(uint32_t); + + for (i = 0; i < length; i+=8) { + printf("%03x: ", i*4); + for (j = 0; j < 8; j++) + printf("%08x ", p[i+j]); + printf("\n"); + } + + printf("\n"); +} + +static void +print_controller(struct nvme_controller_data *cdata) +{ + printf("Controller Capabilities/Features\n"); + printf("================================\n"); + printf("Vendor ID: %04x\n", cdata->vid); + printf("Subsystem Vendor ID: %04x\n", cdata->ssvid); + printf("Serial Number: %s\n", cdata->sn); + printf("Model Number: %s\n", cdata->mn); + printf("Firmware Version: %s\n", cdata->fr); + printf("Recommended Arb Burst: %d\n", cdata->rab); + printf("IEEE OUI Identifier: %02x %02x %02x\n", + cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]); + printf("Multi-Interface Cap: %02x\n", cdata->mic); + /* TODO: Use CAP.MPSMIN to determine true memory page size. */ + printf("Max Data Transfer Size: "); + if (cdata->mdts == 0) + printf("Unlimited\n"); + else + printf("%d\n", PAGE_SIZE * (1 << cdata->mdts)); + printf("\n"); + + printf("Admin Command Set Attributes\n"); + printf("============================\n"); + printf("Security Send/Receive: %s\n", + cdata->oacs.security ? "Supported" : "Not Supported"); + printf("Format NVM: %s\n", + cdata->oacs.format ? "Supported" : "Not Supported"); + printf("Firmware Activate/Download: %s\n", + cdata->oacs.firmware ? "Supported" : "Not Supported"); + printf("Abort Command Limit: %d\n", cdata->acl+1); + printf("Async Event Request Limit: %d\n", cdata->aerl+1); + printf("Number of Firmware Slots: "); + if (cdata->oacs.firmware != 0) + printf("%d\n", cdata->frmw.num_slots); + else + printf("N/A\n"); + printf("Firmware Slot 1 Read-Only: "); + if (cdata->oacs.firmware != 0) + printf("%s\n", cdata->frmw.slot1_ro ? "Yes" : "No"); + else + printf("N/A\n"); + printf("Per-Namespace SMART Log: %s\n", + cdata->lpa.ns_smart ? "Yes" : "No"); + printf("Error Log Page Entries: %d\n", cdata->elpe+1); + printf("Number of Power States: %d\n", cdata->npss+1); + printf("\n"); + + printf("NVM Command Set Attributes\n"); + printf("==========================\n"); + printf("Submission Queue Entry Size\n"); + printf(" Max: %d\n", 1 << cdata->sqes.max); + printf(" Min: %d\n", 1 << cdata->sqes.min); + printf("Completion Queue Entry Size\n"); + printf(" Max: %d\n", 1 << cdata->cqes.max); + printf(" Min: %d\n", 1 << cdata->cqes.min); + printf("Number of Namespaces: %d\n", cdata->nn); + printf("Compare Command: %s\n", + cdata->oncs.compare ? "Supported" : "Not Supported"); + printf("Write Uncorrectable Command: %s\n", + cdata->oncs.write_unc ? "Supported" : "Not Supported"); + printf("Dataset Management Command: %s\n", + cdata->oncs.dsm ? "Supported" : "Not Supported"); + printf("Volatile Write Cache: %s\n", + cdata->vwc.present ? "Present" : "Not Present"); +} + +static void +print_namespace_hex(struct nvme_namespace_data *nsdata, uint32_t length) +{ + uint32_t *p; + uint32_t i, j; + + p = (uint32_t *)nsdata; + length /= sizeof(uint32_t); + + for (i = 0; i < length; i+=8) { + printf("%03x: ", i*4); + for (j = 0; j < 8; j++) + printf("%08x ", p[i+j]); + printf("\n"); + } + + printf("\n"); +} + +static void +print_namespace(struct nvme_namespace_data *nsdata) +{ + uint32_t i; + + printf("Size (in LBAs): %lld (%lldM)\n", + (long long)nsdata->nsze, + (long long)nsdata->nsze / 1024 / 1024); + printf("Capacity (in LBAs): %lld (%lldM)\n", + (long long)nsdata->ncap, + (long long)nsdata->ncap / 1024 / 1024); + printf("Utilization (in LBAs): %lld (%lldM)\n", + (long long)nsdata->nuse, + (long long)nsdata->nuse / 1024 / 1024); + printf("Thin Provisioning: %s\n", + nsdata->nsfeat.thin_prov ? "Supported" : "Not Supported"); + printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1); + printf("Current LBA Format: LBA Format #%d\n", + nsdata->flbas.format); + for (i = 0; i <= nsdata->nlbaf; i++) { + printf("LBA Format #%d:\n", i); + printf(" LBA Data Size: %d\n", + 1 << nsdata->lbaf[i].lbads); + } +} + +static void +identify_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, IDENTIFY_USAGE); + exit(EX_USAGE); +} + +static void +identify_ctrlr(int argc, char *argv[]) +{ + struct nvme_controller_data cdata; + int ch, fd, hexflag = 0, hexlength; + int verboseflag = 0; + + while ((ch = getopt(argc, argv, "vx")) != -1) { + switch ((char)ch) { + case 'v': + verboseflag = 1; + break; + case 'x': + hexflag = 1; + break; + default: + identify_usage(); + } + } + + open_dev(argv[optind], &fd, 1, 1); + read_controller_data(fd, &cdata); + close(fd); + + if (hexflag == 1) { + if (verboseflag == 1) + hexlength = sizeof(struct nvme_controller_data); + else + hexlength = offsetof(struct nvme_controller_data, + reserved5); + print_controller_hex(&cdata, hexlength); + exit(EX_OK); + } + + if (verboseflag == 1) { + printf("-v not currently supported without -x.\n"); + identify_usage(); + } + + print_controller(&cdata); + exit(EX_OK); +} + +static void +identify_ns(int argc, char *argv[]) +{ + struct nvme_namespace_data nsdata; + char path[64]; + char *nsloc; + int ch, fd, hexflag = 0, hexlength, nsid; + int verboseflag = 0; + + while ((ch = getopt(argc, argv, "vx")) != -1) { + switch ((char)ch) { + case 'v': + verboseflag = 1; + break; + case 'x': + hexflag = 1; + break; + default: + identify_usage(); + } + } + + /* + * Check if the specified device node exists before continuing. + * This is a cleaner check for cases where the correct controller + * is specified, but an invalid namespace on that controller. + */ + open_dev(argv[optind], &fd, 1, 1); + close(fd); + + /* + * Pull the namespace id from the string. +2 skips past the "ns" part + * of the string. Don't search past 10 characters into the string, + * otherwise we know it is malformed. + */ + nsloc = strnstr(argv[optind], "ns", 10); + if (nsloc != NULL) + nsid = strtol(nsloc + 2, NULL, 10); + if (nsloc == NULL || (nsid == 0 && errno != 0)) { + printf("Invalid namespace ID %s.\n", argv[optind]); + exit(EX_IOERR); + } + + /* + * We send IDENTIFY commands to the controller, not the namespace, + * since it is an admin cmd. So the path should only include the + * nvmeX part of the nvmeXnsY string. + */ + snprintf(path, nsloc - argv[optind] + 1, "%s", argv[optind]); + open_dev(path, &fd, 1, 1); + read_namespace_data(fd, nsid, &nsdata); + close(fd); + + if (hexflag == 1) { + if (verboseflag == 1) + hexlength = sizeof(struct nvme_namespace_data); + else + hexlength = offsetof(struct nvme_namespace_data, + reserved6); + print_namespace_hex(&nsdata, hexlength); + exit(EX_OK); + } + + if (verboseflag == 1) { + printf("-v not currently supported without -x.\n"); + identify_usage(); + } + + print_namespace(&nsdata); + exit(EX_OK); +} + +void +identify(int argc, char *argv[]) +{ + char *target; + + if (argc < 2) + identify_usage(); + + while (getopt(argc, argv, "vx") != -1) ; + + target = argv[optind]; + + optreset = 1; + optind = 1; + + /* + * If device node contains "ns", we consider it a namespace, + * otherwise, consider it a controller. + */ + if (strstr(target, "ns") == NULL) + identify_ctrlr(argc, argv); + else + identify_ns(argc, argv); +} diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index a3286c1..18cd9e9 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -57,137 +57,6 @@ usage(void) exit(EX_USAGE); } -static void -print_controller_hex(struct nvme_controller_data *cdata, uint32_t length) -{ - uint32_t *p; - uint32_t i, j; - - p = (uint32_t *)cdata; - length /= sizeof(uint32_t); - - for (i = 0; i < length; i+=8) { - printf("%03x: ", i*4); - for (j = 0; j < 8; j++) - printf("%08x ", p[i+j]); - printf("\n"); - } - - printf("\n"); -} - -static void -print_controller(struct nvme_controller_data *cdata) -{ - printf("Controller Capabilities/Features\n"); - printf("================================\n"); - printf("Vendor ID: %04x\n", cdata->vid); - printf("Subsystem Vendor ID: %04x\n", cdata->ssvid); - printf("Serial Number: %s\n", cdata->sn); - printf("Model Number: %s\n", cdata->mn); - printf("Firmware Version: %s\n", cdata->fr); - printf("Recommended Arb Burst: %d\n", cdata->rab); - printf("IEEE OUI Identifier: %02x %02x %02x\n", - cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]); - printf("Multi-Interface Cap: %02x\n", cdata->mic); - /* TODO: Use CAP.MPSMIN to determine true memory page size. */ - printf("Max Data Transfer Size: "); - if (cdata->mdts == 0) - printf("Unlimited\n"); - else - printf("%d\n", PAGE_SIZE * (1 << cdata->mdts)); - printf("\n"); - - printf("Admin Command Set Attributes\n"); - printf("============================\n"); - printf("Security Send/Receive: %s\n", - cdata->oacs.security ? "Supported" : "Not Supported"); - printf("Format NVM: %s\n", - cdata->oacs.format ? "Supported" : "Not Supported"); - printf("Firmware Activate/Download: %s\n", - cdata->oacs.firmware ? "Supported" : "Not Supported"); - printf("Abort Command Limit: %d\n", cdata->acl+1); - printf("Async Event Request Limit: %d\n", cdata->aerl+1); - printf("Number of Firmware Slots: "); - if (cdata->oacs.firmware != 0) - printf("%d\n", cdata->frmw.num_slots); - else - printf("N/A\n"); - printf("Firmware Slot 1 Read-Only: "); - if (cdata->oacs.firmware != 0) - printf("%s\n", cdata->frmw.slot1_ro ? "Yes" : "No"); - else - printf("N/A\n"); - printf("Per-Namespace SMART Log: %s\n", - cdata->lpa.ns_smart ? "Yes" : "No"); - printf("Error Log Page Entries: %d\n", cdata->elpe+1); - printf("Number of Power States: %d\n", cdata->npss+1); - printf("\n"); - - printf("NVM Command Set Attributes\n"); - printf("==========================\n"); - printf("Submission Queue Entry Size\n"); - printf(" Max: %d\n", 1 << cdata->sqes.max); - printf(" Min: %d\n", 1 << cdata->sqes.min); - printf("Completion Queue Entry Size\n"); - printf(" Max: %d\n", 1 << cdata->cqes.max); - printf(" Min: %d\n", 1 << cdata->cqes.min); - printf("Number of Namespaces: %d\n", cdata->nn); - printf("Compare Command: %s\n", - cdata->oncs.compare ? "Supported" : "Not Supported"); - printf("Write Uncorrectable Command: %s\n", - cdata->oncs.write_unc ? "Supported" : "Not Supported"); - printf("Dataset Management Command: %s\n", - cdata->oncs.dsm ? "Supported" : "Not Supported"); - printf("Volatile Write Cache: %s\n", - cdata->vwc.present ? "Present" : "Not Present"); -} - -static void -print_namespace_hex(struct nvme_namespace_data *nsdata, uint32_t length) -{ - uint32_t *p; - uint32_t i, j; - - p = (uint32_t *)nsdata; - length /= sizeof(uint32_t); - - for (i = 0; i < length; i+=8) { - printf("%03x: ", i*4); - for (j = 0; j < 8; j++) - printf("%08x ", p[i+j]); - printf("\n"); - } - - printf("\n"); -} - -static void -print_namespace(struct nvme_namespace_data *nsdata) -{ - uint32_t i; - - printf("Size (in LBAs): %lld (%lldM)\n", - (long long)nsdata->nsze, - (long long)nsdata->nsze / 1024 / 1024); - printf("Capacity (in LBAs): %lld (%lldM)\n", - (long long)nsdata->ncap, - (long long)nsdata->ncap / 1024 / 1024); - printf("Utilization (in LBAs): %lld (%lldM)\n", - (long long)nsdata->nuse, - (long long)nsdata->nuse / 1024 / 1024); - printf("Thin Provisioning: %s\n", - nsdata->nsfeat.thin_prov ? "Supported" : "Not Supported"); - printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1); - printf("Current LBA Format: LBA Format #%d\n", - nsdata->flbas.format); - for (i = 0; i <= nsdata->nlbaf; i++) { - printf("LBA Format #%d:\n", i); - printf(" LBA Data Size: %d\n", - 1 << nsdata->lbaf[i].lbads); - } -} - void read_controller_data(int fd, struct nvme_controller_data *cdata) { @@ -267,154 +136,6 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) } static void -identify_usage(void) -{ - fprintf(stderr, "usage:\n"); - fprintf(stderr, IDENTIFY_USAGE); - exit(EX_USAGE); -} - -static void -identify_ctrlr(int argc, char *argv[]) -{ - struct nvme_controller_data cdata; - int ch, fd, hexflag = 0, hexlength; - int verboseflag = 0; - - while ((ch = getopt(argc, argv, "vx")) != -1) { - switch ((char)ch) { - case 'v': - verboseflag = 1; - break; - case 'x': - hexflag = 1; - break; - default: - identify_usage(); - } - } - - open_dev(argv[optind], &fd, 1, 1); - read_controller_data(fd, &cdata); - close(fd); - - if (hexflag == 1) { - if (verboseflag == 1) - hexlength = sizeof(struct nvme_controller_data); - else - hexlength = offsetof(struct nvme_controller_data, - reserved5); - print_controller_hex(&cdata, hexlength); - exit(EX_OK); - } - - if (verboseflag == 1) { - printf("-v not currently supported without -x.\n"); - identify_usage(); - } - - print_controller(&cdata); - exit(EX_OK); -} - -static void -identify_ns(int argc, char *argv[]) -{ - struct nvme_namespace_data nsdata; - char path[64]; - char *nsloc; - int ch, fd, hexflag = 0, hexlength, nsid; - int verboseflag = 0; - - while ((ch = getopt(argc, argv, "vx")) != -1) { - switch ((char)ch) { - case 'v': - verboseflag = 1; - break; - case 'x': - hexflag = 1; - break; - default: - identify_usage(); - } - } - - /* - * Check if the specified device node exists before continuing. - * This is a cleaner check for cases where the correct controller - * is specified, but an invalid namespace on that controller. - */ - open_dev(argv[optind], &fd, 1, 1); - close(fd); - - /* - * Pull the namespace id from the string. +2 skips past the "ns" part - * of the string. Don't search past 10 characters into the string, - * otherwise we know it is malformed. - */ - nsloc = strnstr(argv[optind], "ns", 10); - if (nsloc != NULL) - nsid = strtol(nsloc + 2, NULL, 10); - if (nsloc == NULL || (nsid == 0 && errno != 0)) { - printf("Invalid namespace ID %s.\n", argv[optind]); - exit(EX_IOERR); - } - - /* - * We send IDENTIFY commands to the controller, not the namespace, - * since it is an admin cmd. So the path should only include the - * nvmeX part of the nvmeXnsY string. - */ - snprintf(path, nsloc - argv[optind] + 1, "%s", argv[optind]); - open_dev(path, &fd, 1, 1); - read_namespace_data(fd, nsid, &nsdata); - close(fd); - - if (hexflag == 1) { - if (verboseflag == 1) - hexlength = sizeof(struct nvme_namespace_data); - else - hexlength = offsetof(struct nvme_namespace_data, - reserved6); - print_namespace_hex(&nsdata, hexlength); - exit(EX_OK); - } - - if (verboseflag == 1) { - printf("-v not currently supported without -x.\n"); - identify_usage(); - } - - print_namespace(&nsdata); - exit(EX_OK); -} - -static void -identify(int argc, char *argv[]) -{ - char *target; - - if (argc < 2) - identify_usage(); - - while (getopt(argc, argv, "vx") != -1) ; - - target = argv[optind]; - - optreset = 1; - optind = 1; - - /* - * If device node contains "ns", we consider it a namespace, - * otherwise, consider it a controller. - */ - if (strstr(target, "ns") == NULL) - identify_ctrlr(argc, argv); - else - identify_ns(argc, argv); -} - -static void print_perftest(struct nvme_io_test *io_test, bool perthread) { uint32_t i, io_completed = 0, iops, mbps; diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index a026ced..40e048e 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -51,6 +51,7 @@ void read_controller_data(int fd, struct nvme_controller_data *cdata); void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); void devlist(int argc, char *argv[]); +void identify(int argc, char *argv[]); #endif -- cgit v1.1 From 39388a678883e38b78d67404df046d224aaad6cf Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 23:02:48 +0000 Subject: Break out code related to the perftest command into a separate file. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/Makefile | 2 +- sbin/nvmecontrol/nvmecontrol.c | 139 ------------------------------- sbin/nvmecontrol/nvmecontrol.h | 1 + sbin/nvmecontrol/perftest.c | 181 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 140 deletions(-) create mode 100644 sbin/nvmecontrol/perftest.c (limited to 'sbin') diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index e710942..b007bb1 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= nvmecontrol -SRCS= nvmecontrol.c devlist.c identify.c +SRCS= nvmecontrol.c devlist.c identify.c perftest.c MAN= nvmecontrol.8 .include diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 18cd9e9..e690110 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -44,8 +44,6 @@ __FBSDID("$FreeBSD$"); #include "nvmecontrol.h" -static void perftest_usage(void); - static void usage(void) { @@ -136,143 +134,6 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) } static void -print_perftest(struct nvme_io_test *io_test, bool perthread) -{ - uint32_t i, io_completed = 0, iops, mbps; - - for (i = 0; i < io_test->num_threads; i++) - io_completed += io_test->io_completed[i]; - - iops = io_completed/io_test->time; - mbps = iops * io_test->size / (1024*1024); - - printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7d MB/s: %4d\n", - io_test->num_threads, io_test->size, - io_test->opc == NVME_OPC_READ ? "READ" : "WRITE", - io_test->time, iops, mbps); - - if (perthread) - for (i = 0; i < io_test->num_threads; i++) - printf("\t%3d: %8d IO/s\n", i, - io_test->io_completed[i]/io_test->time); - - exit(1); -} - -static void -perftest_usage(void) -{ - fprintf(stderr, "usage:\n"); - fprintf(stderr, PERFTEST_USAGE); - exit(EX_USAGE); -} - -static void -perftest(int argc, char *argv[]) -{ - struct nvme_io_test io_test; - int fd; - char ch; - char *p; - u_long ioctl_cmd = NVME_IO_TEST; - bool nflag, oflag, sflag, tflag; - int perthread = 0; - - nflag = oflag = sflag = tflag = false; - - memset(&io_test, 0, sizeof(io_test)); - - while ((ch = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) { - switch (ch) { - case 'f': - if (!strcmp(optarg, "refthread")) - io_test.flags |= NVME_TEST_FLAG_REFTHREAD; - break; - case 'i': - if (!strcmp(optarg, "bio") || - !strcmp(optarg, "wait")) - ioctl_cmd = NVME_BIO_TEST; - else if (!strcmp(optarg, "io") || - !strcmp(optarg, "intr")) - ioctl_cmd = NVME_IO_TEST; - break; - case 'n': - nflag = true; - io_test.num_threads = strtoul(optarg, &p, 0); - if (p != NULL && *p != '\0') { - fprintf(stderr, - "\"%s\" not valid number of threads.\n", - optarg); - perftest_usage(); - } else if (io_test.num_threads == 0 || - io_test.num_threads > 128) { - fprintf(stderr, - "\"%s\" not valid number of threads.\n", - optarg); - perftest_usage(); - } - break; - case 'o': - oflag = true; - if (!strcmp(optarg, "read") || !strcmp(optarg, "READ")) - io_test.opc = NVME_OPC_READ; - else if (!strcmp(optarg, "write") || - !strcmp(optarg, "WRITE")) - io_test.opc = NVME_OPC_WRITE; - else { - fprintf(stderr, "\"%s\" not valid opcode.\n", - optarg); - perftest_usage(); - } - break; - case 'p': - perthread = 1; - break; - case 's': - sflag = true; - io_test.size = strtoul(optarg, &p, 0); - if (p == NULL || *p == '\0' || toupper(*p) == 'B') { - // do nothing - } else if (toupper(*p) == 'K') { - io_test.size *= 1024; - } else if (toupper(*p) == 'M') { - io_test.size *= 1024 * 1024; - } else { - fprintf(stderr, "\"%s\" not valid size.\n", - optarg); - perftest_usage(); - } - break; - case 't': - tflag = true; - io_test.time = strtoul(optarg, &p, 0); - if (p != NULL && *p != '\0') { - fprintf(stderr, - "\"%s\" not valid time duration.\n", - optarg); - perftest_usage(); - } - break; - } - } - - if (!nflag || !oflag || !sflag || !tflag || optind >= argc) - perftest_usage(); - - open_dev(argv[optind], &fd, 1, 1); - if (ioctl(fd, ioctl_cmd, &io_test) < 0) { - fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno, - strerror(errno)); - close(fd); - exit(EX_IOERR); - } - - close(fd); - print_perftest(&io_test, perthread); - exit(EX_OK); -} - -static void reset_usage(void) { fprintf(stderr, "usage:\n"); diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index 40e048e..2bb5784 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -52,6 +52,7 @@ void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); void devlist(int argc, char *argv[]); void identify(int argc, char *argv[]); +void perftest(int argc, char *argv[]); #endif diff --git a/sbin/nvmecontrol/perftest.c b/sbin/nvmecontrol/perftest.c new file mode 100644 index 0000000..c69da79 --- /dev/null +++ b/sbin/nvmecontrol/perftest.c @@ -0,0 +1,181 @@ +/*- + * Copyright (C) 2012-2013 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nvmecontrol.h" + +static void +print_perftest(struct nvme_io_test *io_test, bool perthread) +{ + uint32_t i, io_completed = 0, iops, mbps; + + for (i = 0; i < io_test->num_threads; i++) + io_completed += io_test->io_completed[i]; + + iops = io_completed/io_test->time; + mbps = iops * io_test->size / (1024*1024); + + printf("Threads: %2d Size: %6d %5s Time: %3d IO/s: %7d MB/s: %4d\n", + io_test->num_threads, io_test->size, + io_test->opc == NVME_OPC_READ ? "READ" : "WRITE", + io_test->time, iops, mbps); + + if (perthread) + for (i = 0; i < io_test->num_threads; i++) + printf("\t%3d: %8d IO/s\n", i, + io_test->io_completed[i]/io_test->time); + + exit(1); +} + +static void +perftest_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, PERFTEST_USAGE); + exit(EX_USAGE); +} + +void +perftest(int argc, char *argv[]) +{ + struct nvme_io_test io_test; + int fd; + char ch; + char *p; + u_long ioctl_cmd = NVME_IO_TEST; + bool nflag, oflag, sflag, tflag; + int perthread = 0; + + nflag = oflag = sflag = tflag = false; + + memset(&io_test, 0, sizeof(io_test)); + + while ((ch = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) { + switch (ch) { + case 'f': + if (!strcmp(optarg, "refthread")) + io_test.flags |= NVME_TEST_FLAG_REFTHREAD; + break; + case 'i': + if (!strcmp(optarg, "bio") || + !strcmp(optarg, "wait")) + ioctl_cmd = NVME_BIO_TEST; + else if (!strcmp(optarg, "io") || + !strcmp(optarg, "intr")) + ioctl_cmd = NVME_IO_TEST; + break; + case 'n': + nflag = true; + io_test.num_threads = strtoul(optarg, &p, 0); + if (p != NULL && *p != '\0') { + fprintf(stderr, + "\"%s\" not valid number of threads.\n", + optarg); + perftest_usage(); + } else if (io_test.num_threads == 0 || + io_test.num_threads > 128) { + fprintf(stderr, + "\"%s\" not valid number of threads.\n", + optarg); + perftest_usage(); + } + break; + case 'o': + oflag = true; + if (!strcmp(optarg, "read") || !strcmp(optarg, "READ")) + io_test.opc = NVME_OPC_READ; + else if (!strcmp(optarg, "write") || + !strcmp(optarg, "WRITE")) + io_test.opc = NVME_OPC_WRITE; + else { + fprintf(stderr, "\"%s\" not valid opcode.\n", + optarg); + perftest_usage(); + } + break; + case 'p': + perthread = 1; + break; + case 's': + sflag = true; + io_test.size = strtoul(optarg, &p, 0); + if (p == NULL || *p == '\0' || toupper(*p) == 'B') { + // do nothing + } else if (toupper(*p) == 'K') { + io_test.size *= 1024; + } else if (toupper(*p) == 'M') { + io_test.size *= 1024 * 1024; + } else { + fprintf(stderr, "\"%s\" not valid size.\n", + optarg); + perftest_usage(); + } + break; + case 't': + tflag = true; + io_test.time = strtoul(optarg, &p, 0); + if (p != NULL && *p != '\0') { + fprintf(stderr, + "\"%s\" not valid time duration.\n", + optarg); + perftest_usage(); + } + break; + } + } + + if (!nflag || !oflag || !sflag || !tflag || optind >= argc) + perftest_usage(); + + open_dev(argv[optind], &fd, 1, 1); + if (ioctl(fd, ioctl_cmd, &io_test) < 0) { + fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno, + strerror(errno)); + close(fd); + exit(EX_IOERR); + } + + close(fd); + print_perftest(&io_test, perthread); + exit(EX_OK); +} -- cgit v1.1 From 80f07df07fecb98013650d346f36fba697638bc9 Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 23:05:48 +0000 Subject: Break out code related to the reset command into a separate source file. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/Makefile | 2 +- sbin/nvmecontrol/nvmecontrol.c | 32 +------------------ sbin/nvmecontrol/nvmecontrol.h | 1 + sbin/nvmecontrol/reset.c | 71 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 32 deletions(-) create mode 100644 sbin/nvmecontrol/reset.c (limited to 'sbin') diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index b007bb1..bb01e64 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= nvmecontrol -SRCS= nvmecontrol.c devlist.c identify.c perftest.c +SRCS= nvmecontrol.c devlist.c identify.c perftest.c reset.c MAN= nvmecontrol.8 .include diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index e690110..f0ecb2f 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -133,36 +133,6 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) return (EX_OK); } -static void -reset_usage(void) -{ - fprintf(stderr, "usage:\n"); - fprintf(stderr, RESET_USAGE); - exit(EX_USAGE); -} - -static void -reset_ctrlr(int argc, char *argv[]) -{ - int ch, fd; - - while ((ch = getopt(argc, argv, "")) != -1) { - switch ((char)ch) { - default: - reset_usage(); - } - } - - open_dev(argv[optind], &fd, 1, 1); - if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) { - printf("Reset request to %s failed. errno=%d (%s)\n", - argv[optind], errno, strerror(errno)); - exit(EX_IOERR); - } - - exit(EX_OK); -} - int main(int argc, char *argv[]) { @@ -177,7 +147,7 @@ main(int argc, char *argv[]) else if (strcmp(argv[1], "perftest") == 0) perftest(argc-1, &argv[1]); else if (strcmp(argv[1], "reset") == 0) - reset_ctrlr(argc-1, &argv[1]); + reset(argc-1, &argv[1]); usage(); diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index 2bb5784..74430f9 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -53,6 +53,7 @@ void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); void devlist(int argc, char *argv[]); void identify(int argc, char *argv[]); void perftest(int argc, char *argv[]); +void reset(int argc, char *argv[]); #endif diff --git a/sbin/nvmecontrol/reset.c b/sbin/nvmecontrol/reset.c new file mode 100644 index 0000000..f197145 --- /dev/null +++ b/sbin/nvmecontrol/reset.c @@ -0,0 +1,71 @@ +/*- + * Copyright (C) 2012-2013 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "nvmecontrol.h" + +static void +reset_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, RESET_USAGE); + exit(EX_USAGE); +} + +void +reset(int argc, char *argv[]) +{ + int ch, fd; + + while ((ch = getopt(argc, argv, "")) != -1) { + switch ((char)ch) { + default: + reset_usage(); + } + } + + open_dev(argv[optind], &fd, 1, 1); + if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) { + printf("Reset request to %s failed. errno=%d (%s)\n", + argv[optind], errno, strerror(errno)); + exit(EX_IOERR); + } + + exit(EX_OK); +} -- cgit v1.1 From 57728d033757510c81668f7054bc1ccc5945933e Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 23:11:20 +0000 Subject: Add an nvme_function structure array, defining the name, C function and usage message for each nvmecontrol command. This helps reduce some code clutter both now and for future commits which will add logpage and firmware support to nvmecontrol(8). Also move helper function prototypes to the end of the header file, after the per-command functions. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/nvmecontrol.c | 40 ++++++++++++++++++++++++++++------------ sbin/nvmecontrol/nvmecontrol.h | 8 ++++---- 2 files changed, 32 insertions(+), 16 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index f0ecb2f..af5e148 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -44,14 +44,31 @@ __FBSDID("$FreeBSD$"); #include "nvmecontrol.h" +typedef void (*nvme_fn_t)(int argc, char *argv[]); + +struct nvme_function { + const char *name; + nvme_fn_t fn; + const char *usage; +} funcs[] = { + {"devlist", devlist, DEVLIST_USAGE}, + {"identify", identify, IDENTIFY_USAGE}, + {"perftest", perftest, PERFTEST_USAGE}, + {"reset", reset, RESET_USAGE}, + {NULL, NULL, NULL}, +}; + static void usage(void) { + struct nvme_function *f; + + f = funcs; fprintf(stderr, "usage:\n"); - fprintf(stderr, DEVLIST_USAGE); - fprintf(stderr, IDENTIFY_USAGE); - fprintf(stderr, RESET_USAGE); - fprintf(stderr, PERFTEST_USAGE); + while (f->name != NULL) { + fprintf(stderr, "%s", f->usage); + f++; + } exit(EX_USAGE); } @@ -136,18 +153,17 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) int main(int argc, char *argv[]) { + struct nvme_function *f; if (argc < 2) usage(); - if (strcmp(argv[1], "devlist") == 0) - devlist(argc-1, &argv[1]); - else if (strcmp(argv[1], "identify") == 0) - identify(argc-1, &argv[1]); - else if (strcmp(argv[1], "perftest") == 0) - perftest(argc-1, &argv[1]); - else if (strcmp(argv[1], "reset") == 0) - reset(argc-1, &argv[1]); + f = funcs; + while (f->name != NULL) { + if (strcmp(argv[1], f->name) == 0) + f->fn(argc-1, &argv[1]); + f++; + } usage(); diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index 74430f9..ec61e95 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -46,14 +46,14 @@ #define RESET_USAGE \ " nvmecontrol reset \n" -int open_dev(const char *str, int *fd, int show_error, int exit_on_error); -void read_controller_data(int fd, struct nvme_controller_data *cdata); -void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); - void devlist(int argc, char *argv[]); void identify(int argc, char *argv[]); void perftest(int argc, char *argv[]); void reset(int argc, char *argv[]); +int open_dev(const char *str, int *fd, int show_error, int exit_on_error); +void read_controller_data(int fd, struct nvme_controller_data *cdata); +void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); + #endif -- cgit v1.1 From 4d63e9a6042335ac179666efa53e626cb0d723c3 Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 23:20:08 +0000 Subject: Create #defines for NVME_CTRLR_PREFIX and NVME_NS_PREFIX for the "nvme" and "ns" strings, rather than hardcoding the string values throughout the nvmecontrol code base. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/devlist.c | 5 +++-- sbin/nvmecontrol/identify.c | 4 ++-- sbin/nvmecontrol/nvmecontrol.h | 3 +++ 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/devlist.c b/sbin/nvmecontrol/devlist.c index 4085e7e..8c99c99 100644 --- a/sbin/nvmecontrol/devlist.c +++ b/sbin/nvmecontrol/devlist.c @@ -78,7 +78,7 @@ devlist(int argc, char *argv[]) while (1) { ctrlr++; - sprintf(name, "nvme%d", ctrlr); + sprintf(name, "%s%d", NVME_CTRLR_PREFIX, ctrlr); exit_code = open_dev(name, &fd, 0, 0); @@ -95,7 +95,8 @@ devlist(int argc, char *argv[]) printf("%6s: %s\n", name, cdata.mn); for (i = 0; i < cdata.nn; i++) { - sprintf(name, "nvme%dns%d", ctrlr, i+1); + sprintf(name, "%s%d%s%d", NVME_CTRLR_PREFIX, ctrlr, + NVME_NS_PREFIX, i+1); read_namespace_data(fd, i+1, &nsdata); printf(" %10s (%lldGB)\n", name, diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index 6dcbebd..cd1d746 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -258,7 +258,7 @@ identify_ns(int argc, char *argv[]) * of the string. Don't search past 10 characters into the string, * otherwise we know it is malformed. */ - nsloc = strnstr(argv[optind], "ns", 10); + nsloc = strnstr(argv[optind], NVME_NS_PREFIX, 10); if (nsloc != NULL) nsid = strtol(nsloc + 2, NULL, 10); if (nsloc == NULL || (nsid == 0 && errno != 0)) { @@ -314,7 +314,7 @@ identify(int argc, char *argv[]) * If device node contains "ns", we consider it a namespace, * otherwise, consider it a controller. */ - if (strstr(target, "ns") == NULL) + if (strstr(target, NVME_NS_PREFIX) == NULL) identify_ctrlr(argc, argv); else identify_ns(argc, argv); diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index ec61e95..c05792e 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -31,6 +31,9 @@ #include +#define NVME_CTRLR_PREFIX "nvme" +#define NVME_NS_PREFIX "ns" + #define DEVLIST_USAGE \ " nvmecontrol devlist\n" -- cgit v1.1 From c089ab01fb8f33d060ae82f527fd60d9dfa9f084 Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 23:41:07 +0000 Subject: Ensure that a device node is specified when invoking the identify or reset commands. Also improve the checking of device node names, so that better error messages are displayed when incorrect names are specified. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/identify.c | 8 ++++++++ sbin/nvmecontrol/nvmecontrol.c | 18 +++++++++++++++--- sbin/nvmecontrol/reset.c | 4 ++++ 3 files changed, 27 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index cd1d746..c405508 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -200,6 +200,10 @@ identify_ctrlr(int argc, char *argv[]) } } + /* Check that a controller was specified. */ + if (optind >= argc) + identify_usage(); + open_dev(argv[optind], &fd, 1, 1); read_controller_data(fd, &cdata); close(fd); @@ -245,6 +249,10 @@ identify_ns(int argc, char *argv[]) } } + /* Check that a namespace was specified. */ + if (optind >= argc) + identify_usage(); + /* * Check if the specified device node exists before continuing. * This is a cleaner check for cases where the correct controller diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index af5e148..b95ff32 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -126,10 +126,22 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) struct stat devstat; char full_path[64]; + if (!strnstr(str, NVME_CTRLR_PREFIX, strlen(NVME_CTRLR_PREFIX))) { + if (show_error) + fprintf(stderr, + "Controller/namespace IDs must begin with '%s'.\n", + NVME_CTRLR_PREFIX); + if (exit_on_error) + exit(EX_USAGE); + else + return (EX_USAGE); + } + snprintf(full_path, sizeof(full_path), "/dev/%s", str); if (stat(full_path, &devstat) != 0) { if (show_error) - fprintf(stderr, "error\n"); + fprintf(stderr, "Could not stat %s. errno=%d (%s)\n", + full_path, errno, strerror(errno)); if (exit_on_error) exit(EX_NOINPUT); else @@ -139,8 +151,8 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) *fd = open(full_path, O_RDWR); if (*fd < 0) { if (show_error) - printf("Could not open %s. errno=%d (%s)\n", full_path, - errno, strerror(errno)); + fprintf(stderr, "Could not open %s. errno=%d (%s)\n", + full_path, errno, strerror(errno)); if (exit_on_error) exit(EX_NOPERM); else diff --git a/sbin/nvmecontrol/reset.c b/sbin/nvmecontrol/reset.c index f197145..a96722c 100644 --- a/sbin/nvmecontrol/reset.c +++ b/sbin/nvmecontrol/reset.c @@ -60,6 +60,10 @@ reset(int argc, char *argv[]) } } + /* Check that a controller was specified. */ + if (optind >= argc) + reset_usage(); + open_dev(argv[optind], &fd, 1, 1); if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) { printf("Reset request to %s failed. errno=%d (%s)\n", -- cgit v1.1 From d67aed2f532632a2528eefcb53d629a814b476b4 Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 23:46:31 +0000 Subject: Add generalized helper functions for printing hex data as part of nvmecontrol commands. Submitted by: Joe Golio Obtained from: EMC / Isilon Storage Division MFC after: 3 days --- sbin/nvmecontrol/identify.c | 42 ++---------------------------------- sbin/nvmecontrol/nvmecontrol.c | 48 ++++++++++++++++++++++++++++++++++++++++++ sbin/nvmecontrol/nvmecontrol.h | 1 + 3 files changed, 51 insertions(+), 40 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index c405508..afe5ac0 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -42,25 +42,6 @@ __FBSDID("$FreeBSD$"); #include "nvmecontrol.h" static void -print_controller_hex(struct nvme_controller_data *cdata, uint32_t length) -{ - uint32_t *p; - uint32_t i, j; - - p = (uint32_t *)cdata; - length /= sizeof(uint32_t); - - for (i = 0; i < length; i+=8) { - printf("%03x: ", i*4); - for (j = 0; j < 8; j++) - printf("%08x ", p[i+j]); - printf("\n"); - } - - printf("\n"); -} - -static void print_controller(struct nvme_controller_data *cdata) { printf("Controller Capabilities/Features\n"); @@ -128,25 +109,6 @@ print_controller(struct nvme_controller_data *cdata) } static void -print_namespace_hex(struct nvme_namespace_data *nsdata, uint32_t length) -{ - uint32_t *p; - uint32_t i, j; - - p = (uint32_t *)nsdata; - length /= sizeof(uint32_t); - - for (i = 0; i < length; i+=8) { - printf("%03x: ", i*4); - for (j = 0; j < 8; j++) - printf("%08x ", p[i+j]); - printf("\n"); - } - - printf("\n"); -} - -static void print_namespace(struct nvme_namespace_data *nsdata) { uint32_t i; @@ -214,7 +176,7 @@ identify_ctrlr(int argc, char *argv[]) else hexlength = offsetof(struct nvme_controller_data, reserved5); - print_controller_hex(&cdata, hexlength); + print_hex(&cdata, hexlength); exit(EX_OK); } @@ -290,7 +252,7 @@ identify_ns(int argc, char *argv[]) else hexlength = offsetof(struct nvme_namespace_data, reserved6); - print_namespace_hex(&nsdata, hexlength); + print_hex(&nsdata, hexlength); exit(EX_OK); } diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index b95ff32..eb41419 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -72,6 +72,54 @@ usage(void) exit(EX_USAGE); } +static void +print_bytes(void *data, uint32_t length) +{ + uint32_t i, j; + uint8_t *p, *end; + + end = (uint8_t *)data + length; + + for (i = 0; i < length; i++) { + p = (uint8_t *)data + (i*16); + printf("%03x: ", i*16); + for (j = 0; j < 16 && p < end; j++) + printf("%02x ", *p++); + if (p >= end) + break; + printf("\n"); + } + printf("\n"); +} + +static void +print_dwords(void *data, uint32_t length) +{ + uint32_t *p; + uint32_t i, j; + + p = (uint32_t *)data; + length /= sizeof(uint32_t); + + for (i = 0; i < length; i+=8) { + printf("%03x: ", i*4); + for (j = 0; j < 8; j++) + printf("%08x ", p[i+j]); + printf("\n"); + } + + printf("\n"); +} + +void +print_hex(void *data, uint32_t length) +{ + if (length >= sizeof(uint32_t) || length % sizeof(uint32_t) == 0) + print_dwords(data, length); + else + print_bytes(data, length); +} + void read_controller_data(int fd, struct nvme_controller_data *cdata) { diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index c05792e..422728b 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -57,6 +57,7 @@ void reset(int argc, char *argv[]); int open_dev(const char *str, int *fd, int show_error, int exit_on_error); void read_controller_data(int fd, struct nvme_controller_data *cdata); void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); +void print_hex(void *data, uint32_t length); #endif -- cgit v1.1 From 246ba1c3a87a263471fd5516bb5f329ab6143c1c Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 26 Jun 2013 23:53:54 +0000 Subject: Add log page support to nvmecontrol(8) through a new logpage command. This includes pretty printers for all of the standard NVMe log pages (Error, SMART/Health, Firmware), as well as hex output for non-standard or vendor-specific log pages. Submitted by: Joe Golio Obtained from: EMC / Isilon Storage Division MFC after: 3 days --- sbin/nvmecontrol/Makefile | 2 +- sbin/nvmecontrol/logpage.c | 388 +++++++++++++++++++++++++++++++++++++++++ sbin/nvmecontrol/nvmecontrol.8 | 16 ++ sbin/nvmecontrol/nvmecontrol.c | 1 + sbin/nvmecontrol/nvmecontrol.h | 6 + 5 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 sbin/nvmecontrol/logpage.c (limited to 'sbin') diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index bb01e64..66e92e9 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= nvmecontrol -SRCS= nvmecontrol.c devlist.c identify.c perftest.c reset.c +SRCS= nvmecontrol.c devlist.c identify.c logpage.c perftest.c reset.c MAN= nvmecontrol.8 .include diff --git a/sbin/nvmecontrol/logpage.c b/sbin/nvmecontrol/logpage.c new file mode 100644 index 0000000..9b698a8 --- /dev/null +++ b/sbin/nvmecontrol/logpage.c @@ -0,0 +1,388 @@ +/*- + * Copyright (c) 2013 EMC Corp. + * All rights reserved. + * + * Copyright (C) 2012-2013 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nvmecontrol.h" + +#define DEFAULT_SIZE (4096) +#define MAX_FW_SLOTS (7) + +typedef void (*print_fn_t)(void *buf, uint32_t size); + +static void * +get_log_buffer(size_t size) +{ + void *buf; + + if ((buf = malloc(size)) == NULL) { + fprintf(stderr, "Unable to malloc %zd bytes\n", size); + exit(EX_IOERR); + } + memset(buf, 0, size); + return (buf); +} + +void +read_logpage(int fd, uint8_t log_page, int nsid, void *payload, + uint32_t payload_size) +{ + struct nvme_pt_command pt; + + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_GET_LOG_PAGE; + pt.cmd.nsid = nsid; + pt.cmd.cdw10 = ((payload_size/sizeof(uint32_t)) - 1) << 16; + pt.cmd.cdw10 |= log_page; + pt.buf = payload; + pt.len = payload_size; + pt.is_read = 1; + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { + printf("Get log page request failed. errno=%d (%s)\n", + errno, strerror(errno)); + exit(EX_IOERR); + } + + if (nvme_completion_is_error(&pt.cpl)) { + printf("Passthrough command returned error.\n"); + exit(EX_IOERR); + } +} + +static void +print_log_error(void *buf, uint32_t size) +{ + int i, nentries; + struct nvme_error_information_entry *entry = buf; + struct nvme_status *status; + + printf("Error Information Log\n"); + printf("=====================\n"); + + if (entry->error_count == 0) { + printf("No error entries found\n"); + return; + } + + nentries = size/sizeof(struct nvme_error_information_entry); + for (i = 0; i < nentries; i++, entry++) { + if (entry->error_count == 0) + break; + + status = &entry->status; + printf("Entry %02d\n", i + 1); + printf("=========\n"); + printf(" Error count: %ju\n", entry->error_count); + printf(" Submission queue ID: %u\n", entry->sqid); + printf(" Command ID: %u\n", entry->cid); + /* TODO: Export nvme_status_string structures from kernel? */ + printf(" Status:\n"); + printf(" Phase tag: %d\n", status->p); + printf(" Status code: %d\n", status->sc); + printf(" Status code type: %d\n", status->sct); + printf(" More: %d\n", status->m); + printf(" DNR: %d\n", status->dnr); + printf(" Error location: %u\n", entry->error_location); + printf(" LBA: %ju\n", entry->lba); + printf(" Namespace ID: %u\n", entry->nsid); + printf(" Vendor specific info: %u\n", entry->vendor_specific); + } +} + +static void +print_log_health(void *buf, uint32_t size __unused) +{ + struct nvme_health_information_page *health = buf; + + printf("SMART/Health Information Log\n"); + printf("============================\n"); + + printf("Critical Warning State: 0x%02x\n", + health->critical_warning.raw); + printf(" Available spare: %d\n", + health->critical_warning.bits.available_spare); + printf(" Temperature: %d\n", + health->critical_warning.bits.temperature); + printf(" Device reliability: %d\n", + health->critical_warning.bits.device_reliability); + printf(" Read only: %d\n", + health->critical_warning.bits.read_only); + printf(" Volatile memory backup: %d\n", + health->critical_warning.bits.volatile_memory_backup); + printf("Temperature: %u K, %2.2f C, %3.2f F\n", + health->temperature, + (float)health->temperature - (float)273.15, + ((float)health->temperature * (float)9/5) - (float)459.67); + printf("Available spare: %u\n", + health->available_spare); + printf("Available spare threshold: %u\n", + health->available_spare_threshold); + printf("Percentage used: %u\n", + health->percentage_used); + + /* + * TODO: These are pretty ugly in hex. Is there a library that + * will convert 128-bit unsigned values to decimal? + */ + printf("Data units (512 byte) read: 0x%016jx%016jx\n", + health->data_units_read[1], + health->data_units_read[0]); + printf("Data units (512 byte) written: 0x%016jx%016jx\n", + health->data_units_written[1], + health->data_units_written[0]); + printf("Host read commands: 0x%016jx%016jx\n", + health->host_read_commands[1], + health->host_read_commands[0]); + printf("Host write commands: 0x%016jx%016jx\n", + health->host_write_commands[1], + health->host_write_commands[0]); + printf("Controller busy time (minutes): 0x%016jx%016jx\n", + health->controller_busy_time[1], + health->controller_busy_time[0]); + printf("Power cycles: 0x%016jx%016jx\n", + health->power_cycles[1], + health->power_cycles[0]); + printf("Power on hours: 0x%016jx%016jx\n", + health->power_on_hours[1], + health->power_on_hours[0]); + printf("Unsafe shutdowns: 0x%016jx%016jx\n", + health->unsafe_shutdowns[1], + health->unsafe_shutdowns[0]); + printf("Media errors: 0x%016jx%016jx\n", + health->media_errors[1], + health->media_errors[0]); + printf("No. error info log entries: 0x%016jx%016jx\n", + health->num_error_info_log_entries[1], + health->num_error_info_log_entries[0]); +} + +static void +print_log_firmware(void *buf, uint32_t size __unused) +{ + int i; + const char *status; + struct nvme_firmware_page *fw = buf; + + printf("Firmware Slot Log\n"); + printf("=================\n"); + + for (i = 0; i < MAX_FW_SLOTS; i++) { + printf("Slot %d: ", i + 1); + if (fw->afi.slot == i + 1) + status = " Active"; + else + status = "Inactive"; + + if (fw->revision[i] == 0LLU) + printf("Empty\n"); + else + if (isprint(*(char *)&fw->revision[i])) + printf("[%s] %.8s\n", status, + (char *)&fw->revision[i]); + else + printf("[%s] %016jx\n", status, + fw->revision[i]); + } +} + +struct logpage_function { + uint8_t log_page; + print_fn_t fn; +} logfuncs[] = { + {NVME_LOG_ERROR, print_log_error }, + {NVME_LOG_HEALTH_INFORMATION, print_log_health }, + {NVME_LOG_FIRMWARE_SLOT, print_log_firmware }, + {0, NULL }, +}; + +static void +logpage_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, LOGPAGE_USAGE); + exit(EX_USAGE); +} + +void +logpage(int argc, char *argv[]) +{ + int fd, nsid, len; + int log_page = 0, pageflag = false; + int hexflag = false; + int allow_ns = false; + char ch, *p, *nsloc = NULL; + char *cname = NULL; + size_t size; + void *buf; + struct logpage_function *f; + struct nvme_controller_data cdata; + print_fn_t print_fn; + + while ((ch = getopt(argc, argv, "p:x")) != -1) { + switch (ch) { + case 'p': + /* TODO: Add human-readable ASCII page IDs */ + log_page = strtol(optarg, &p, 0); + if (p != NULL && *p != '\0') { + fprintf(stderr, + "\"%s\" not valid log page id.\n", + optarg); + logpage_usage(); + /* TODO: Define valid log page id ranges in nvme.h? */ + } else if (log_page == 0 || + (log_page >= 0x04 && log_page <= 0x7F) || + (log_page >= 0x80 && log_page <= 0xBF)) { + fprintf(stderr, + "\"%s\" not valid log page id.\n", + optarg); + logpage_usage(); + } + pageflag = true; + break; + case 'x': + hexflag = true; + break; + } + } + + if (!pageflag) { + printf("Missing page_id (-p).\n"); + logpage_usage(); + } + + /* Check that a controller and/or namespace was specified. */ + if (optind >= argc) + logpage_usage(); + + /* + * The log page attribtues indicate whether or not the controller + * supports the SMART/Health information log page on a per + * namespace basis. + */ + cname = malloc(strlen(NVME_CTRLR_PREFIX) + 2); + len = strlen(NVME_CTRLR_PREFIX) + 1; + cname = strncpy(cname, argv[optind], len); + open_dev(cname, &fd, 1, 1); + read_controller_data(fd, &cdata); + + if (log_page == NVME_LOG_HEALTH_INFORMATION && cdata.lpa.ns_smart != 0) + allow_ns = true; + + /* If a namespace id was specified, validate it's use */ + if (strstr(argv[optind], NVME_NS_PREFIX) != NULL) { + if (!allow_ns) { + if (log_page != NVME_LOG_HEALTH_INFORMATION) { + fprintf(stderr, + "Namespace ID not valid for log page %d.\n", + log_page); + } else if (cdata.lpa.ns_smart == 0) { + fprintf(stderr, + "Controller does not support per " + "namespace SMART/Health information.\n"); + } + close(fd); + exit(EX_IOERR); + } + nsloc = strnstr(argv[optind], NVME_NS_PREFIX, 10); + if (nsloc != NULL) + nsid = strtol(nsloc + 2, NULL, 10); + if (nsloc == NULL || (nsid == 0 && errno != 0)) { + fprintf(stderr, + "Invalid namespace ID %s.\n", + argv[optind]); + close(fd); + exit(EX_IOERR); + } + + /* + * User is asking for per namespace log page information + * so close the controller and open up the namespace. + */ + close(fd); + open_dev(argv[optind], &fd, 1, 1); + } else + nsid = NVME_GLOBAL_NAMESPACE_TAG; + + print_fn = print_hex; + if (!hexflag) { + /* + * See if there is a pretty print function for the + * specified log page. If one isn't found, we + * just revert to the default (print_hex). + */ + f = logfuncs; + while (f->log_page > 0) { + if (log_page == f->log_page) { + print_fn = f->fn; + break; + } + f++; + } + } + + /* Read the log page */ + switch (log_page) { + case NVME_LOG_ERROR: + size = sizeof(struct nvme_error_information_entry); + size *= (cdata.elpe + 1); + break; + case NVME_LOG_HEALTH_INFORMATION: + size = sizeof(struct nvme_health_information_page); + break; + case NVME_LOG_FIRMWARE_SLOT: + size = sizeof(struct nvme_firmware_page); + break; + default: + size = DEFAULT_SIZE; + break; + } + + buf = get_log_buffer(size); + read_logpage(fd, log_page, nsid, buf, size); + print_fn(buf, size); + + close(fd); + exit(EX_OK); +} diff --git a/sbin/nvmecontrol/nvmecontrol.8 b/sbin/nvmecontrol/nvmecontrol.8 index 7e26240..fa7020d 100644 --- a/sbin/nvmecontrol/nvmecontrol.8 +++ b/sbin/nvmecontrol/nvmecontrol.8 @@ -58,6 +58,12 @@ .Nm .Ic reset .Aq controller id +.Nm +.Ic logpage +.Aq Fl p Ar page_id +.Op Fl x +.Aq device id +.Aq namespace id .Sh DESCRIPTION NVM Express (NVMe) is a storage protocol standard, for SSDs and other high-speed storage devices over PCI Express. @@ -84,6 +90,16 @@ stdout when 30 seconds expires. .Dl nvmecontrol reset nvme0 .Pp Perform a controller-level reset of the nvme0 controller. +.Pp +.Dl nvmecontrol logpage -p 1 nvme0 +.Pp +Display a human-readable summary of the nvme0 controller's Error Information Log. +Log pages defined by the NVMe specification include Error Information Log (ID=1), +SMART/Health Information Log (ID=2), and Firmware Slot Log (ID=3). +.Pp +.Dl nvmecontrol logpage -p 1 -x nvme0 +.Pp +Display a hexidecimal dump of the nvme0 controller's Error Information Log. .Sh AUTHORS .An -nosplit .Nm diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index eb41419..61bfc0a 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -55,6 +55,7 @@ struct nvme_function { {"identify", identify, IDENTIFY_USAGE}, {"perftest", perftest, PERFTEST_USAGE}, {"reset", reset, RESET_USAGE}, + {"logpage", logpage, LOGPAGE_USAGE}, {NULL, NULL, NULL}, }; diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index 422728b..1d02bc4 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -49,15 +49,21 @@ #define RESET_USAGE \ " nvmecontrol reset \n" +#define LOGPAGE_USAGE \ +" nvmecontrol logpage <-p page_id> [-x] \n" \ + void devlist(int argc, char *argv[]); void identify(int argc, char *argv[]); void perftest(int argc, char *argv[]); void reset(int argc, char *argv[]); +void logpage(int argc, char *argv[]); int open_dev(const char *str, int *fd, int show_error, int exit_on_error); void read_controller_data(int fd, struct nvme_controller_data *cdata); void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); void print_hex(void *data, uint32_t length); +void read_logpage(int fd, uint8_t log_page, int nsid, void *payload, + uint32_t payload_size); #endif -- cgit v1.1 From c15f698fb461ff5e7a9135b74eede196265fc6ca Mon Sep 17 00:00:00 2001 From: jimharris Date: Thu, 27 Jun 2013 00:08:25 +0000 Subject: Add firmware replacement and activation support to nvmecontrol(8) through a new firmware command. NVMe controllers may support up to 7 firmware slots for storing of different firmware revisions. This new firmware command supports firmware replacement (i.e. firmware download) with or without immediate activation, or activation of a previously stored firmware image. It also supports selection of the firmware slot during replacement operations, using IDENTIFY information from the controller to check that the specified slot is valid. Newly activated firmware does not take effect until the new controller reset, either via a reboot or separate 'nvmecontrol reset' command to the same controller. Submitted by: Joe Golio Obtained from: EMC / Isilon Storage Division MFC after: 3 days --- sbin/nvmecontrol/Makefile | 3 +- sbin/nvmecontrol/firmware.c | 335 +++++++++++++++++++++++++++++++++++++++++ sbin/nvmecontrol/nvmecontrol.8 | 20 +++ sbin/nvmecontrol/nvmecontrol.c | 1 + sbin/nvmecontrol/nvmecontrol.h | 4 + 5 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 sbin/nvmecontrol/firmware.c (limited to 'sbin') diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index 66e92e9..4682056 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -1,7 +1,8 @@ # $FreeBSD$ PROG= nvmecontrol -SRCS= nvmecontrol.c devlist.c identify.c logpage.c perftest.c reset.c +SRCS= nvmecontrol.c devlist.c firmware.c identify.c logpage.c \ + perftest.c reset.c MAN= nvmecontrol.8 .include diff --git a/sbin/nvmecontrol/firmware.c b/sbin/nvmecontrol/firmware.c new file mode 100644 index 0000000..f82b886 --- /dev/null +++ b/sbin/nvmecontrol/firmware.c @@ -0,0 +1,335 @@ +/*- + * Copyright (c) 2013 EMC Corp. + * All rights reserved. + * + * Copyright (C) 2012-2013 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nvmecontrol.h" + +static int +slot_has_valid_firmware(int fd, int slot) +{ + struct nvme_firmware_page fw; + int has_fw = false; + + read_logpage(fd, NVME_LOG_FIRMWARE_SLOT, + NVME_GLOBAL_NAMESPACE_TAG, &fw, sizeof(fw)); + + if (fw.revision[slot-1] != 0LLU) + has_fw = true; + + return (has_fw); +} + +static void +read_image_file(char *path, void **buf, ssize_t *size) +{ + struct stat sb; + int fd; + + *size = 0; + *buf = NULL; + + if ((fd = open(path, O_RDONLY)) < 0) { + fprintf(stderr, "Unable to open '%s'.\n", path); + exit(EX_IOERR); + } + if (fstat(fd, &sb) < 0) { + fprintf(stderr, "Unable to stat '%s'.\n", path); + close(fd); + exit(EX_IOERR); + } + if ((*buf = malloc(sb.st_size)) == NULL) { + fprintf(stderr, "Unable to malloc %zd bytes.\n", + sb.st_size); + close(fd); + exit(EX_IOERR); + } + if ((*size = read(fd, *buf, sb.st_size)) < 0) { + fprintf(stderr, "Error reading '%s', errno=%d (%s)\n", + path, errno, strerror(errno)); + close(fd); + exit(EX_IOERR); + } + if (*size != sb.st_size) { + fprintf(stderr, "Error reading '%s', " + "read %zd bytes, requested %zd bytes\n", + path, *size, sb.st_size); + close(fd); + exit(EX_IOERR); + } +} + +static void +update_firmware(int fd, uint8_t *payload, uint32_t payload_size) +{ + struct nvme_pt_command pt; + size_t size; + void *chunk; + uint32_t off, resid; + int exit_code = EX_OK; + + off = 0; + resid = payload_size; + + if ((chunk = malloc((size_t)NVME_MAX_XFER_SIZE)) == NULL) { + printf("Unable to malloc %d bytes.\n", NVME_MAX_XFER_SIZE); + exit(EX_IOERR); + } + + while (resid > 0) { + size = (resid >= NVME_MAX_XFER_SIZE) ? + NVME_MAX_XFER_SIZE : resid; + memcpy(chunk, payload + off, size); + + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD; + pt.cmd.cdw10 = (size / sizeof(uint32_t)) - 1; + pt.cmd.cdw11 = (off / sizeof(uint32_t)); + pt.buf = chunk; + pt.len = size; + pt.is_read = 0; + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { + printf("Firmware image download request failed. " + "errno=%d (%s)\n", + errno, strerror(errno)); + exit_code = EX_IOERR; + break; + } + + if (nvme_completion_is_error(&pt.cpl)) { + printf("Passthrough command returned error.\n"); + exit_code = EX_IOERR; + break; + } + + resid -= size; + off += size; + } + + if (exit_code != EX_OK) + exit(exit_code); +} + +static void +activate_firmware(int fd, int slot, int activate_action) +{ + struct nvme_pt_command pt; + + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_FIRMWARE_ACTIVATE; + pt.cmd.cdw10 = (activate_action << 3) | slot; + pt.is_read = 0; + + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { + printf("Firmware activate request failed. errno=%d (%s)\n", + errno, strerror(errno)); + exit(EX_IOERR); + } + + if (nvme_completion_is_error(&pt.cpl)) { + printf("Passthrough command returned error.\n"); + exit(EX_IOERR); + } +} + +static void +firmware_usage(void) +{ + fprintf(stderr, "usage:\n"); + fprintf(stderr, FIRMWARE_USAGE); + exit(EX_USAGE); +} + +void +firmware(int argc, char *argv[]) +{ + int fd = -1, slot = 0; + int a_flag, s_flag, f_flag; + char ch, *p, *image = NULL; + char *controller = NULL, prompt[64]; + void *buf = NULL; + ssize_t size; + struct nvme_controller_data cdata; + + a_flag = s_flag = f_flag = false; + + while ((ch = getopt(argc, argv, "af:s:")) != -1) { + switch (ch) { + case 'a': + a_flag = true; + break; + case 's': + slot = strtol(optarg, &p, 0); + if (p != NULL && *p != '\0') { + fprintf(stderr, + "\"%s\" not valid slot.\n", + optarg); + firmware_usage(); + } else if (slot == 0) { + fprintf(stderr, + "0 is not a valid slot number. " + "Slot numbers start at 1.\n"); + firmware_usage(); + } else if (slot > 7) { + fprintf(stderr, + "Slot number %s specified which is " + "greater than max allowed slot number of " + "7.\n", optarg); + firmware_usage(); + } + s_flag = true; + break; + case 'f': + image = optarg; + f_flag = true; + break; + } + } + + /* Check that a controller (and not a namespace) was specified. */ + if (optind >= argc || strstr(argv[optind], NVME_NS_PREFIX) != NULL) + firmware_usage(); + + if (!f_flag && !a_flag) { + fprintf(stderr, + "Neither a replace ([-f path_to_firmware]) nor " + "activate ([-a]) firmware image action\n" + "was specified.\n"); + firmware_usage(); + } + + if (!f_flag && a_flag && slot == 0) { + fprintf(stderr, + "Slot number to activate not specified.\n"); + firmware_usage(); + } + + controller = argv[optind]; + open_dev(controller, &fd, 1, 1); + read_controller_data(fd, &cdata); + + if (cdata.oacs.firmware == 0) { + fprintf(stderr, + "Controller does not support firmware " + "activate/download.\n"); + exit(EX_IOERR); + } + + if (f_flag && slot == 1 && cdata.frmw.slot1_ro) { + fprintf(stderr, "Slot %d is marked as read only.\n", slot); + exit(EX_IOERR); + } + + if (slot > cdata.frmw.num_slots) { + fprintf(stderr, + "Slot %d was specified but controller only " + "supports %d firmware slots.\n", + slot, cdata.frmw.num_slots); + exit(EX_IOERR); + } + + if (!slot_has_valid_firmware(fd, slot)) { + fprintf(stderr, + "Slot %d does not contain valid firmware.\n" + "Try 'nvmecontrol logpage -p 3 %s' to get a list " + "of available firmware images.\n", + slot, controller); + exit(EX_IOERR); + } + + if (f_flag && a_flag) + printf("You are about to download and activate " + "firmware image (%s) to controller %s.\n" + "This may damage your controller and/or " + "overwrite an existing firmware image.\n", + image, controller); + else if (a_flag) + printf("You are about to activate a new firmware " + "image on controller %s.\n" + "This may damage your controller.\n", + controller); + else if (f_flag) + printf("You are about to download firmware image " + "(%s) to controller %s.\n" + "This may damage your controller and/or " + "overwrite an existing firmware image.\n", + image, controller); + + printf("Are you sure you want to continue? (yes/no) "); + while (1) { + fgets(prompt, sizeof(prompt), stdin); + if (strncasecmp(prompt, "yes", 3) == 0) + break; + if (strncasecmp(prompt, "no", 2) == 0) + exit(EX_OK); + printf("Please answer \"yes\" or \"no\". "); + } + + if (f_flag) { + read_image_file(image, &buf, &size); + update_firmware(fd, buf, size); + if (a_flag) + activate_firmware(fd, slot, + NVME_AA_REPLACE_ACTIVATE); + else + activate_firmware(fd, slot, + NVME_AA_REPLACE_NO_ACTIVATE); + } else { + activate_firmware(fd, slot, NVME_AA_ACTIVATE); + } + + if (a_flag) { + printf("New firmware image activated and will take " + "effect after next controller reset.\n" + "Controller reset can be initiated via " + "'nvmecontrol reset %s'\n", + controller); + } + + close(fd); + exit(EX_OK); +} diff --git a/sbin/nvmecontrol/nvmecontrol.8 b/sbin/nvmecontrol/nvmecontrol.8 index fa7020d..010f106 100644 --- a/sbin/nvmecontrol/nvmecontrol.8 +++ b/sbin/nvmecontrol/nvmecontrol.8 @@ -64,6 +64,12 @@ .Op Fl x .Aq device id .Aq namespace id +.Nm +.Ic firmware +.Op Fl s Ar slot +.Op Fl f Ar path_to_firmware +.Op Fl a +.Aq device id .Sh DESCRIPTION NVM Express (NVMe) is a storage protocol standard, for SSDs and other high-speed storage devices over PCI Express. @@ -100,6 +106,20 @@ SMART/Health Information Log (ID=2), and Firmware Slot Log (ID=3). .Dl nvmecontrol logpage -p 1 -x nvme0 .Pp Display a hexidecimal dump of the nvme0 controller's Error Information Log. +.Pp +.Dl nvmecontrol firmware -s 2 -f /tmp/nvme_firmware nvme0 +.Pp +Download the firmware image contained in "/tmp/nvme_firmware" to slot 2 of the +nvme0 controller, but do not activate the image. +.Pp +.Dl nvmecontrol firmware -s 4 -a nvme0 +.Pp +Activate the firmware in slot 4 of the nvme0 controller on the next reset. +.Pp +.Dl nvmecontrol firmware -s 7 -f /tmp/nvme_firmware -a nvme0 +.Pp +Download the firmware image contained in "/tmp/nvme_firmware" to slot 7 of the +nvme0 controller and activate it on the next reset. .Sh AUTHORS .An -nosplit .Nm diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 61bfc0a..8dc0e36 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -56,6 +56,7 @@ struct nvme_function { {"perftest", perftest, PERFTEST_USAGE}, {"reset", reset, RESET_USAGE}, {"logpage", logpage, LOGPAGE_USAGE}, + {"firmware", firmware, FIRMWARE_USAGE}, {NULL, NULL, NULL}, }; diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index 1d02bc4..f7a35b4 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -52,11 +52,15 @@ #define LOGPAGE_USAGE \ " nvmecontrol logpage <-p page_id> [-x] \n" \ +#define FIRMWARE_USAGE \ +" nvmecontrol firmware [-s slot] [-f path_to_firmware] [-a] \n" + void devlist(int argc, char *argv[]); void identify(int argc, char *argv[]); void perftest(int argc, char *argv[]); void reset(int argc, char *argv[]); void logpage(int argc, char *argv[]); +void firmware(int argc, char *argv[]); int open_dev(const char *str, int *fd, int show_error, int exit_on_error); void read_controller_data(int fd, struct nvme_controller_data *cdata); -- cgit v1.1 From 7f729239c4bb884a13e00c42f6ad2bf2068059d0 Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 27 Jun 2013 10:42:09 +0000 Subject: Fix build. --- sbin/nvmecontrol/logpage.c | 2 +- sbin/nvmecontrol/nvmecontrol.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/logpage.c b/sbin/nvmecontrol/logpage.c index 9b698a8..dbc0e6b 100644 --- a/sbin/nvmecontrol/logpage.c +++ b/sbin/nvmecontrol/logpage.c @@ -227,7 +227,7 @@ print_log_firmware(void *buf, uint32_t size __unused) } } -struct logpage_function { +static struct logpage_function { uint8_t log_page; print_fn_t fn; } logfuncs[] = { diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 8dc0e36..c7452a1 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$"); typedef void (*nvme_fn_t)(int argc, char *argv[]); -struct nvme_function { +static struct nvme_function { const char *name; nvme_fn_t fn; const char *usage; -- cgit v1.1 From 8a3748f531c8740f607c4699474b610e9fd67f6c Mon Sep 17 00:00:00 2001 From: hrs Date: Thu, 27 Jun 2013 18:28:45 +0000 Subject: - Add vnode-backed swap space specification support. This is enabled when device names "md" or "md[0-9]*" and a "file" option are specified in /etc/fstab like this: md none swap sw,file=/swap.bin 0 0 - Add GBDE/GELI encrypted swap space specification support, which rc.d/encswap supported. The /etc/fstab lines are like the following: /dev/ada1p1.bde none swap sw 0 0 /dev/ada1p2.eli none swap sw 0 0 .eli devices accepts aalgo, ealgo, keylen, and sectorsize as options. swapctl(8) can understand an encrypted device in the command line like this: # swapctl -a /dev/ada2p1.bde - "-L" flag is added to support "late" option to defer swapon until rc.d/mountlate runs. - rc.d script change: rc.d/encswap -> removed rc.d/addswap -> just display a warning message if $swapfile is defined rc.d/swap1 -> renamed to rc.d/swap rc.d/swaplate -> newly added to support "late" option These changes alleviate a race condition between device creation/removal and swapon/swapoff. MFC after: 1 week Reviewed by: wblock (manual page) --- sbin/swapon/swapon.8 | 28 ++- sbin/swapon/swapon.c | 567 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 566 insertions(+), 29 deletions(-) (limited to 'sbin') diff --git a/sbin/swapon/swapon.8 b/sbin/swapon/swapon.8 index 5602a9a..ec2ad72 100644 --- a/sbin/swapon/swapon.8 +++ b/sbin/swapon/swapon.8 @@ -28,7 +28,7 @@ .\" @(#)swapon.8 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd June 23, 2008 +.Dd June 21, 2013 .Dt SWAPON 8 .Os .Sh NAME @@ -38,11 +38,11 @@ .Nm swapon .Oo Fl F Ar fstab .Oc -.Fl aq | Ar +.Fl aLq | Ar .Nm swapoff .Oo Fl F Ar fstab .Oc -.Fl aq | Ar +.Fl aLq | Ar .Nm swapctl .Op Fl AghklmsU .Oo @@ -74,10 +74,19 @@ option is used, all swap devices in .Pa /etc/fstab will be added, unless their .Dq noauto +or +.Dq late option is also set. If the +.Fl L +option is specified, +swap devices with the +.Dq late +option will be added as well as ones with no option. +If the .Fl q -option is used informational messages will not be +option is used, +informational messages will not be written to standard output when a swap device is added. .Pp The @@ -89,10 +98,19 @@ option is used, all swap devices in .Pa /etc/fstab will be removed, unless their .Dq noauto +or +.Dq late option is also set. If the +.Fl L +option is specified, +swap devices with the +.Dq late +option will be removed as well as ones with no option. +If the .Fl q -option is used informational messages will not be +option is used, +informational messages will not be written to standard output when a swap device is removed. Note that .Nm swapoff diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c index 5b9a0ed..55beb5b 100644 --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -41,35 +41,51 @@ static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93"; #include __FBSDID("$FreeBSD$"); -#include #include +#include +#include +#include #include +#include #include #include #include +#include +#include #include +#include +#include +#include +#include +#include #include #include #include #include -#include -#include static void usage(void); -static int swap_on_off(char *name, int ignoreebusy); +static const char *swap_on_off(char *, int, char *); +static const char *swap_on_off_gbde(char *, int); +static const char *swap_on_off_geli(char *, char *, int); +static const char *swap_on_off_md(char *, char *, int); +static const char *swap_on_off_sfile(char *, int); static void swaplist(int, int, int); +static int run_cmd(int *, const char *, ...) __printflike(2, 3); static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; +static int qflag; + int main(int argc, char **argv) { struct fstab *fsp; + const char *swfile; char *ptr; int ret; int ch, doall; - int sflag = 0, lflag = 0, hflag = 0, qflag = 0; + int sflag = 0, lflag = 0, late = 0, hflag = 0; const char *etc_fstab; if ((ptr = strrchr(argv[0], '/')) == NULL) @@ -82,7 +98,7 @@ main(int argc, char **argv) doall = 0; etc_fstab = NULL; - while ((ch = getopt(argc, argv, "AadghklmqsUF:")) != -1) { + while ((ch = getopt(argc, argv, "AadghklLmqsUF:")) != -1) { switch(ch) { case 'A': if (which_prog == SWAPCTL) { @@ -116,6 +132,9 @@ main(int argc, char **argv) case 'l': lflag = 1; break; + case 'L': + late = 1; + break; case 'm': hflag = 'M'; break; @@ -145,6 +164,7 @@ main(int argc, char **argv) argv += optind; ret = 0; + swfile = NULL; if (etc_fstab != NULL) setfstab(etc_fstab); if (which_prog == SWAPON || which_prog == SWAPOFF) { @@ -154,27 +174,37 @@ main(int argc, char **argv) continue; if (strstr(fsp->fs_mntops, "noauto")) continue; - if (swap_on_off(fsp->fs_spec, 1)) { + if (which_prog != SWAPOFF && + strstr(fsp->fs_mntops, "late") && + !late) + continue; + swfile = swap_on_off(fsp->fs_spec, 1, + fsp->fs_mntops); + if (swfile == NULL) { ret = 1; - } else { - if (!qflag) { - printf("%s: %sing %s as swap device\n", - getprogname(), - which_prog == SWAPOFF ? "remov" : "add", - fsp->fs_spec); - } + continue; + } + if (!qflag) { + printf("%s: %sing %s as swap device\n", + getprogname(), + (which_prog == SWAPOFF) ? + "remov" : "add", swfile); } } } else if (!*argv) usage(); for (; *argv; ++argv) { - if (swap_on_off(*argv, 0)) { + swfile = swap_on_off(*argv, 0, NULL); + if (swfile == NULL) { ret = 1; - } else if (orig_prog == SWAPCTL) { + continue; + } + if (orig_prog == SWAPCTL) { printf("%s: %sing %s as swap device\n", - getprogname(), which_prog == SWAPOFF ? "remov" : "add", - *argv); + getprogname(), + (which_prog == SWAPOFF) ? "remov" : "add", + swfile); } } } else { @@ -186,14 +216,503 @@ main(int argc, char **argv) exit(ret); } +static const char * +swap_on_off(char *name, int doingall, char *mntops) +{ + char base[PATH_MAX]; + + /* Swap on vnode-backed md(4) device. */ + if (mntops != NULL && + (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) != FNM_NOMATCH || + fnmatch(MD_NAME "[0-9]*", name, 0) != FNM_NOMATCH || + strncmp(_PATH_DEV MD_NAME, name, + sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 || + strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0)) + return (swap_on_off_md(name, mntops, doingall)); + + /* Swap on encrypted device by GEOM_BDE. */ + basename_r(name, base); + if (fnmatch("*.bde", base, 0) != FNM_NOMATCH) + return (swap_on_off_gbde(name, doingall)); + + /* Swap on encrypted device by GEOM_ELI. */ + if (fnmatch("*.eli", base, 0) != FNM_NOMATCH) + return (swap_on_off_geli(name, mntops, doingall)); + + /* Swap on special file. */ + return (swap_on_off_sfile(name, doingall)); +} + +static const char * +swap_on_off_gbde(char *name, int doingall) +{ + const char *ret; + char pass[64 * 2 + 1], bpass[64]; + char *devname, *p; + int i, fd, error; + + devname = strdup(name); + p = strrchr(devname, '.'); + if (p == NULL) { + warnx("%s: Malformed device name", name); + return (NULL); + } + *p = '\0'; + + fd = -1; + switch (which_prog) { + case SWAPON: + arc4random_buf(bpass, sizeof(bpass)); + for (i = 0; i < (int)sizeof(bpass); i++) + sprintf(&pass[2 * i], "%02x", bpass[i]); + pass[sizeof(pass) - 1] = '\0'; + + error = run_cmd(&fd, "%s init %s -P %s", _PATH_GBDE, + devname, pass); + if (error) { + /* bde device found. Ignore it. */ + close(fd); + if (!qflag) + warnx("%s: Device already in use", name); + return (NULL); + } + close(fd); + error = run_cmd(&fd, "%s attach %s -p %s", _PATH_GBDE, + devname, pass); + if (error) { + close(fd); + warnx("gbde (attach) error: %s", name); + return (NULL); + } + break; + case SWAPOFF: + break; + default: + return (NULL); + break; + } + if (fd != -1) + close(fd); + ret = swap_on_off_sfile(name, doingall); + + fd = -1; + switch (which_prog) { + case SWAPOFF: + error = run_cmd(&fd, "%s detach %s", _PATH_GBDE, devname); + if (error) { + /* bde device not found. Ignore it. */ + if (!qflag) + warnx("%s: Device not found", devname); + return (NULL); + } + break; + default: + return (NULL); + break; + } + + if (fd != -1) + close(fd); + return (ret); +} + +static const char * +swap_on_off_geli(char *name, char *mntops, int doingall) +{ + const char *ops, *aalgo, *ealgo, *keylen_str, *sectorsize_str; + char *devname, *p; + char args[4096]; + struct stat sb; + int fd, error, keylen, sectorsize; + u_long ul; + + devname = strdup(name); + p = strrchr(devname, '.'); + if (p == NULL) { + warnx("%s: Malformed device name", name); + return (NULL); + } + *p = '\0'; + + ops = strdup(mntops); + + /* Default parameters for geli(8). */ + aalgo = "hmac/sha256"; + ealgo = "aes"; + keylen = 256; + sectorsize = 4096; + + if ((p = strstr(ops, "aalgo=")) != NULL) { + aalgo = p + sizeof("aalgo=") - 1; + p = strchr(aalgo, ','); + if (p != NULL) + *p = '\0'; + } + if ((p = strstr(ops, "ealgo=")) != NULL) { + ealgo = p + sizeof("ealgo=") - 1; + p = strchr(ealgo, ','); + if (p != NULL) + *p = '\0'; + } + if ((p = strstr(ops, "keylen=")) != NULL) { + keylen_str = p + sizeof("keylen=") - 1; + p = strchr(keylen_str, ','); + if (p != NULL) + *p = '\0'; + errno = 0; + ul = strtoul(keylen_str, &p, 10); + if (errno == 0) { + if (*p != '\0' || ul > INT_MAX) + errno = EINVAL; + } + if (errno) { + warn("Invalid keylen: %s", keylen_str); + return (NULL); + } + keylen = (int)ul; + } + if ((p = strstr(ops, "sectorsize=")) != NULL) { + sectorsize_str = p + sizeof("sectorsize=") - 1; + p = strchr(sectorsize_str, ','); + if (p != NULL) + *p = '\0'; + errno = 0; + ul = strtoul(sectorsize_str, &p, 10); + if (errno == 0) { + if (*p != '\0' || ul > INT_MAX) + errno = EINVAL; + } + if (errno) { + warn("Invalid sectorsize: %s", sectorsize_str); + return (NULL); + } + sectorsize = (int)ul; + } + snprintf(args, sizeof(args), "-a %s -e %s -l %d -s %d -d", + aalgo, ealgo, keylen, sectorsize); + args[sizeof(args) - 1] = '\0'; + free((void *)ops); + + fd = -1; + switch (which_prog) { + case SWAPON: + error = run_cmd(&fd, "%s onetime %s %s", _PATH_GELI, args, + devname); + if (error) { + /* eli device found. Ignore it. */ + close(fd); + if (!qflag) + warnx("%s: Device already in use " + "or invalid parameters", name); + return (NULL); + } + break; + case SWAPOFF: + if (stat(name, &sb) == -1 && errno == ENOENT) { + if (!qflag) + warnx("%s: Device not found", name); + return (NULL); + } + break; + default: + return (NULL); + break; + } + if (fd != -1) + close(fd); + + return (swap_on_off_sfile(name, doingall)); +} + +static const char * +swap_on_off_md(char *name, char *mntops, int doingall) +{ + FILE *sfd; + int fd, mdunit, error; + const char *ret; + char mdpath[PATH_MAX], linebuf[PATH_MAX]; + char *p, *vnodefile; + size_t linelen; + u_long ul; + + fd = -1; + sfd = NULL; + if (strlen(name) == (sizeof(MD_NAME) - 1)) + mdunit = -1; + else { + errno = 0; + ul = strtoul(name + 2, &p, 10); + if (errno == 0) { + if (*p != '\0' || ul > INT_MAX) + errno = EINVAL; + } + if (errno) { + warn("Bad device unit: %s", name); + return (NULL); + } + mdunit = (int)ul; + } + + vnodefile = NULL; + if ((p = strstr(mntops, "file=")) != NULL) { + vnodefile = strdup(p + sizeof("file=") - 1); + p = strchr(vnodefile, ','); + if (p != NULL) + *p = '\0'; + } + if (vnodefile == NULL) { + warnx("file option not found for %s", name); + return (NULL); + } + + switch (which_prog) { + case SWAPON: + if (mdunit == -1) { + error = run_cmd(&fd, "%s -l -n -f %s", + _PATH_MDCONFIG, vnodefile); + if (error == 0) { + /* md device found. Ignore it. */ + close(fd); + if (!qflag) + warnx("%s: Device already in use", + vnodefile); + return (NULL); + } + error = run_cmd(&fd, "%s -a -t vnode -n -f %s", + _PATH_MDCONFIG, vnodefile); + if (error) { + warnx("mdconfig (attach) error: file=%s", + vnodefile); + return (NULL); + } + sfd = fdopen(fd, "r"); + if (sfd == NULL) { + warn("mdconfig (attach) fdopen error"); + ret = NULL; + goto err; + } + p = fgetln(sfd, &linelen); + if (p == NULL && + (linelen < 2 || linelen > sizeof(linebuf))) { + warn("mdconfig (attach) unexpected output"); + ret = NULL; + goto err; + } + strncpy(linebuf, p, linelen); + linebuf[linelen - 1] = '\0'; + errno = 0; + ul = strtoul(linebuf, &p, 10); + if (errno == 0) { + if (*p != '\0' || ul > INT_MAX) + errno = EINVAL; + } + if (errno) { + warn("mdconfig (attach) unexpected output: %s", + linebuf); + ret = NULL; + goto err; + } + mdunit = (int)ul; + } else { + error = run_cmd(&fd, "%s -l -n -f %s -u %d", + _PATH_MDCONFIG, vnodefile, mdunit); + if (error == 0) { + /* md device found. Ignore it. */ + close(fd); + if (!qflag) + warnx("md%d on %s: Device already " + "in use", mdunit, vnodefile); + return (NULL); + } + error = run_cmd(NULL, "%s -a -t vnode -u %d -f %s", + _PATH_MDCONFIG, mdunit, vnodefile); + if (error) { + warnx("mdconfig (attach) error: " + "md%d on file=%s", mdunit, vnodefile); + return (NULL); + } + } + break; + case SWAPOFF: + if (mdunit == -1) { + error = run_cmd(&fd, "%s -l -n -f %s", + _PATH_MDCONFIG, vnodefile); + if (error) { + /* md device not found. Ignore it. */ + close(fd); + if (!qflag) + warnx("md on %s: Device not found", + vnodefile); + return (NULL); + } + sfd = fdopen(fd, "r"); + if (sfd == NULL) { + warn("mdconfig (list) fdopen error"); + ret = NULL; + goto err; + } + p = fgetln(sfd, &linelen); + if (p == NULL && + (linelen < 2 || linelen > sizeof(linebuf) - 1)) { + warn("mdconfig (list) unexpected output"); + ret = NULL; + goto err; + } + strncpy(linebuf, p, linelen); + linebuf[linelen - 1] = '\0'; + p = strchr(linebuf, ' '); + if (p != NULL) + *p = '\0'; + errno = 0; + ul = strtoul(linebuf, &p, 10); + if (errno == 0) { + if (*p != '\0' || ul > INT_MAX) + errno = EINVAL; + } + if (errno) { + warn("mdconfig (list) unexpected output: %s", + linebuf); + ret = NULL; + goto err; + } + mdunit = (int)ul; + } else { + error = run_cmd(&fd, "%s -l -n -f %s -u %d", + _PATH_MDCONFIG, vnodefile, mdunit); + if (error) { + /* md device not found. Ignore it. */ + close(fd); + if (!qflag) + warnx("md%d on %s: Device not found", + mdunit, vnodefile); + return (NULL); + } + } + break; + default: + return (NULL); + } + snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV, + MD_NAME, mdunit); + mdpath[sizeof(mdpath) - 1] = '\0'; + ret = swap_on_off_sfile(mdpath, doingall); + + switch (which_prog) { + case SWAPOFF: + if (ret != NULL) { + error = run_cmd(NULL, "%s -d -u %d", + _PATH_MDCONFIG, mdunit); + if (error) + warn("mdconfig (detach) detach failed: %s%s%d", + _PATH_DEV, MD_NAME, mdunit); + } + break; + default: + break; + } +err: + if (sfd != NULL) + fclose(sfd); + if (fd != -1) + close(fd); + return (ret); +} + static int -swap_on_off(char *name, int doingall) +run_cmd(int *ofd, const char *cmdline, ...) { - if ((which_prog == SWAPOFF ? swapoff(name) : swapon(name)) == -1) { + va_list ap; + char **argv, **argvp, *cmd, *p; + int argc, pid, status, rv; + int pfd[2], nfd, dup2dn; + + va_start(ap, cmdline); + rv = vasprintf(&cmd, cmdline, ap); + if (rv == -1) { + warn("%s", __func__); + return (rv); + } + va_end(ap); + + for (argc = 1, p = cmd; (p = strchr(p, ' ')) != NULL; p++) + argc++; + argv = (char **)malloc(sizeof(*argv) * (argc + 1)); + for (p = cmd, argvp = argv; (*argvp = strsep(&p, " ")) != NULL;) + if (**argvp != '\0' && (++argvp > &argv[argc])) { + *argvp = NULL; + break; + } + /* The argv array ends up NULL-terminated here. */ +#if 0 + { + int i; + + fprintf(stderr, "DEBUG: running:"); + /* Should be equivalent to 'cmd' (before strsep, of course). */ + for (i = 0; argv[i] != NULL; i++) + fprintf(stderr, " %s", argv[i]); + fprintf(stderr, "\n"); + } +#endif + dup2dn = 1; + if (ofd != NULL) { + if (pipe(&pfd[0]) == -1) { + warn("%s: pipe", __func__); + return (-1); + } + *ofd = pfd[0]; + dup2dn = 0; + } + pid = fork(); + switch (pid) { + case 0: + /* Child process. */ + if (ofd != NULL) + if (dup2(pfd[1], STDOUT_FILENO) < 0) + err(1, "dup2 in %s", __func__); + nfd = open(_PATH_DEVNULL, O_RDWR); + if (nfd == -1) + err(1, "%s: open %s", __func__, _PATH_DEVNULL); + if (dup2(nfd, STDIN_FILENO) < 0) + err(1, "%s: dup2", __func__); + if (dup2dn && dup2(nfd, STDOUT_FILENO) < 0) + err(1, "%s: dup2", __func__); + if (dup2(nfd, STDERR_FILENO) < 0) + err(1, "%s: dup2", __func__); + execv(argv[0], argv); + warn("exec: %s", argv[0]); + _exit(-1); + case -1: + err(1, "%s: fork", __func__); + } + free(cmd); + free(argv); + while (waitpid(pid, &status, 0) != pid) + ; + return (WEXITSTATUS(status)); +} + +static const char * +swap_on_off_sfile(char *name, int doingall) +{ + int error; + + switch (which_prog) { + case SWAPON: + error = swapon(name); + break; + case SWAPOFF: + error = swapoff(name); + break; + default: + error = 0; + break; + } + if (error == -1) { switch (errno) { case EBUSY: if (!doingall) - warnx("%s: device already in use", name); + warnx("%s: Device already in use", name); break; case EINVAL: if (which_prog == SWAPON) @@ -205,9 +724,9 @@ swap_on_off(char *name, int doingall) warn("%s", name); break; } - return(1); + return (NULL); } - return(0); + return (name); } static void @@ -217,7 +736,7 @@ usage(void) switch(orig_prog) { case SWAPON: case SWAPOFF: - fprintf(stderr, "[-F fstab] -aq | file ...\n"); + fprintf(stderr, "[-F fstab] -aLq | file ...\n"); break; case SWAPCTL: fprintf(stderr, "[-AghklmsU] [-a file ... | -d file ...]\n"); -- cgit v1.1 From 78ac9f10ca59607e46586237fe505d58c3ffe518 Mon Sep 17 00:00:00 2001 From: hrs Date: Fri, 28 Jun 2013 05:09:01 +0000 Subject: Fix build. Spotted by: gjb --- sbin/swapon/swapon.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'sbin') diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c index 55beb5b..84c9b42 100644 --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -248,11 +248,11 @@ swap_on_off_gbde(char *name, int doingall) { const char *ret; char pass[64 * 2 + 1], bpass[64]; - char *devname, *p; + char *dname, *p; int i, fd, error; - devname = strdup(name); - p = strrchr(devname, '.'); + dname = strdup(name); + p = strrchr(dname, '.'); if (p == NULL) { warnx("%s: Malformed device name", name); return (NULL); @@ -268,7 +268,7 @@ swap_on_off_gbde(char *name, int doingall) pass[sizeof(pass) - 1] = '\0'; error = run_cmd(&fd, "%s init %s -P %s", _PATH_GBDE, - devname, pass); + dname, pass); if (error) { /* bde device found. Ignore it. */ close(fd); @@ -278,7 +278,7 @@ swap_on_off_gbde(char *name, int doingall) } close(fd); error = run_cmd(&fd, "%s attach %s -p %s", _PATH_GBDE, - devname, pass); + dname, pass); if (error) { close(fd); warnx("gbde (attach) error: %s", name); @@ -298,11 +298,11 @@ swap_on_off_gbde(char *name, int doingall) fd = -1; switch (which_prog) { case SWAPOFF: - error = run_cmd(&fd, "%s detach %s", _PATH_GBDE, devname); + error = run_cmd(&fd, "%s detach %s", _PATH_GBDE, dname); if (error) { /* bde device not found. Ignore it. */ if (!qflag) - warnx("%s: Device not found", devname); + warnx("%s: Device not found", dname); return (NULL); } break; @@ -320,14 +320,14 @@ static const char * swap_on_off_geli(char *name, char *mntops, int doingall) { const char *ops, *aalgo, *ealgo, *keylen_str, *sectorsize_str; - char *devname, *p; + char *dname, *p; char args[4096]; struct stat sb; int fd, error, keylen, sectorsize; u_long ul; - devname = strdup(name); - p = strrchr(devname, '.'); + dname = strdup(name); + p = strrchr(dname, '.'); if (p == NULL) { warnx("%s: Malformed device name", name); return (NULL); @@ -397,7 +397,7 @@ swap_on_off_geli(char *name, char *mntops, int doingall) switch (which_prog) { case SWAPON: error = run_cmd(&fd, "%s onetime %s %s", _PATH_GELI, args, - devname); + dname); if (error) { /* eli device found. Ignore it. */ close(fd); -- cgit v1.1 From 09fe89cd96bbc75840d8dbf963f10ebc16f4083d Mon Sep 17 00:00:00 2001 From: hrs Date: Fri, 28 Jun 2013 16:24:14 +0000 Subject: Fix build with gcc. --- sbin/swapon/swapon.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c index 84c9b42..cf9b979 100644 --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -76,6 +76,8 @@ static int run_cmd(int *, const char *, ...) __printflike(2, 3); static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; static int qflag; +static char aalgo_default[] = "hmac/sha256"; +static char ealgo_default[] = "aes"; int main(int argc, char **argv) @@ -319,7 +321,7 @@ swap_on_off_gbde(char *name, int doingall) static const char * swap_on_off_geli(char *name, char *mntops, int doingall) { - const char *ops, *aalgo, *ealgo, *keylen_str, *sectorsize_str; + char *ops, *aalgo, *ealgo, *keylen_str, *sectorsize_str; char *dname, *p; char args[4096]; struct stat sb; @@ -337,8 +339,8 @@ swap_on_off_geli(char *name, char *mntops, int doingall) ops = strdup(mntops); /* Default parameters for geli(8). */ - aalgo = "hmac/sha256"; - ealgo = "aes"; + aalgo = aalgo_default; + ealgo = ealgo_default; keylen = 256; sectorsize = 4096; -- cgit v1.1 From 0dd1d9c578ddc35507ac2072c5062f5d57c53147 Mon Sep 17 00:00:00 2001 From: davide Date: Fri, 28 Jun 2013 21:00:08 +0000 Subject: - Trim an unused and bogus Makefile for mount_smbfs. - Reconnect with some minor modifications, in particular now selsocket() internals are adapted to use sbintime units after recent'ish calloutng switch. --- sbin/mount/mount.8 | 2 ++ sbin/mount/mount.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/mount/mount.8 b/sbin/mount/mount.8 index 7cd8026..5b670ee 100644 --- a/sbin/mount/mount.8 +++ b/sbin/mount/mount.8 @@ -450,6 +450,7 @@ However, for the following file system types: .Cm nfs , .Cm nullfs , .Cm oldnfs , +.Cm smbfs , .Cm udf , and .Cm unionfs . @@ -544,6 +545,7 @@ support for a particular file system might be provided either on a static .Xr mount_msdosfs 8 , .Xr mount_nfs 8 , .Xr mount_nullfs 8 , +.Xr mount_smbfs 8 , .Xr mount_udf 8 , .Xr mount_unionfs 8 , .Xr umount 8 , diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c index a156089..6284822 100644 --- a/sbin/mount/mount.c +++ b/sbin/mount/mount.c @@ -143,7 +143,7 @@ use_mountprog(const char *vfstype) unsigned int i; const char *fs[] = { "cd9660", "mfs", "msdosfs", "nfs", - "nullfs", "oldnfs", "udf", "unionfs", + "nullfs", "oldnfs", "smbfs", "udf", "unionfs", NULL }; -- cgit v1.1 From fb34da0b96a663c25696aa4cd28d87b579d9ccde Mon Sep 17 00:00:00 2001 From: joel Date: Sat, 29 Jun 2013 16:05:44 +0000 Subject: mdoc: remove EOL whitespace. --- sbin/mdconfig/mdconfig.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/mdconfig/mdconfig.8 b/sbin/mdconfig/mdconfig.8 index b3cc110..9e30896 100644 --- a/sbin/mdconfig/mdconfig.8 +++ b/sbin/mdconfig/mdconfig.8 @@ -144,7 +144,7 @@ If both of and .Fl f options are specified, -display devices which match the two conditions. +display devices which match the two conditions. If the .Fl v option is specified, show all details. -- cgit v1.1 From 3764c06cce8e6850a99963792d57f39f931683f0 Mon Sep 17 00:00:00 2001 From: ed Date: Sat, 29 Jun 2013 20:13:39 +0000 Subject: Don't let hastd use C11 atomics. Due to possible concerns about the stability of C11 atomics, use our existing atomics API instead. Requested by: pjd --- sbin/hastd/refcnt.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sbin') diff --git a/sbin/hastd/refcnt.h b/sbin/hastd/refcnt.h index 5e3fb34..1246043 100644 --- a/sbin/hastd/refcnt.h +++ b/sbin/hastd/refcnt.h @@ -32,24 +32,24 @@ #ifndef __REFCNT_H__ #define __REFCNT_H__ -#include +#include #include "pjdlog.h" -typedef atomic_uint refcnt_t; +typedef unsigned int refcnt_t; static __inline void refcnt_init(refcnt_t *count, unsigned int v) { - atomic_init(count, v); + *count = v; } static __inline void refcnt_acquire(refcnt_t *count) { - atomic_fetch_add_explicit(count, 1, memory_order_acquire); + atomic_add_acq_int(count, 1); } static __inline unsigned int @@ -58,7 +58,7 @@ refcnt_release(refcnt_t *count) unsigned int old; /* XXX: Should this have a rel membar? */ - old = atomic_fetch_sub(count, 1); + old = atomic_fetchadd_int(count, -1); PJDLOG_ASSERT(old > 0); return (old - 1); } -- cgit v1.1 From 3a5f04c7d205b865306e8b05adc113860ab18684 Mon Sep 17 00:00:00 2001 From: delphij Date: Sat, 29 Jun 2013 22:04:04 +0000 Subject: - Modify swapon(8) so that it uses most of geli(8) defaults for swap, which is presently: AES-XTS, no authentication. Create provider with pagesize as sectorsize by default. - Rewrite parsing code for geli(8)-backed swap options, now options are required to be exact match, and unrecognized options will trigger a warning. - Don't initialize GELI device if it's already initialized. This restores previous behavior. - Don't duplicate file descriptor when working with geli(8) and gbde(8) as there is no need to communicate with the utility other than exit status. - When calling swap_on_off_* routines, which_prog can only be SWAP_ON or SWAP_OFF. Eliminate unneeded case branches by replacing switch with if's. - Plug a few memory leaks. Reviewed by: hrs (but bugs are mine) MFC after: 1 week X-MFC-with: r252310, r252332, r252345 --- sbin/swapon/swapon.c | 319 +++++++++++++++++++++++++-------------------------- 1 file changed, 159 insertions(+), 160 deletions(-) (limited to 'sbin') diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c index cf9b979..6e80097 100644 --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -65,19 +65,17 @@ __FBSDID("$FreeBSD$"); #include static void usage(void); -static const char *swap_on_off(char *, int, char *); -static const char *swap_on_off_gbde(char *, int); -static const char *swap_on_off_geli(char *, char *, int); -static const char *swap_on_off_md(char *, char *, int); -static const char *swap_on_off_sfile(char *, int); +static const char *swap_on_off(const char *, int, char *); +static const char *swap_on_off_gbde(const char *, int); +static const char *swap_on_off_geli(const char *, char *, int); +static const char *swap_on_off_md(const char *, char *, int); +static const char *swap_on_off_sfile(const char *, int); static void swaplist(int, int, int); static int run_cmd(int *, const char *, ...) __printflike(2, 3); static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL; static int qflag; -static char aalgo_default[] = "hmac/sha256"; -static char ealgo_default[] = "aes"; int main(int argc, char **argv) @@ -219,215 +217,231 @@ main(int argc, char **argv) } static const char * -swap_on_off(char *name, int doingall, char *mntops) +swap_on_off(const char *name, int doingall, char *mntops) { char base[PATH_MAX]; /* Swap on vnode-backed md(4) device. */ if (mntops != NULL && - (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) != FNM_NOMATCH || - fnmatch(MD_NAME "[0-9]*", name, 0) != FNM_NOMATCH || + (fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) == 0 || + fnmatch(MD_NAME "[0-9]*", name, 0) == 0 || strncmp(_PATH_DEV MD_NAME, name, sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 || strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0)) return (swap_on_off_md(name, mntops, doingall)); - /* Swap on encrypted device by GEOM_BDE. */ basename_r(name, base); - if (fnmatch("*.bde", base, 0) != FNM_NOMATCH) + + /* Swap on encrypted device by GEOM_BDE. */ + if (fnmatch("*.bde", base, 0) == 0) return (swap_on_off_gbde(name, doingall)); /* Swap on encrypted device by GEOM_ELI. */ - if (fnmatch("*.eli", base, 0) != FNM_NOMATCH) + if (fnmatch("*.eli", base, 0) == 0) return (swap_on_off_geli(name, mntops, doingall)); /* Swap on special file. */ return (swap_on_off_sfile(name, doingall)); } -static const char * -swap_on_off_gbde(char *name, int doingall) +/* Strip off .bde or .eli suffix from swap device name */ +static char * +swap_basename(const char *name) { - const char *ret; - char pass[64 * 2 + 1], bpass[64]; char *dname, *p; - int i, fd, error; dname = strdup(name); p = strrchr(dname, '.'); - if (p == NULL) { - warnx("%s: Malformed device name", name); - return (NULL); - } + /* assert(p != NULL); */ *p = '\0'; - fd = -1; - switch (which_prog) { - case SWAPON: + return (dname); +} + +static const char * +swap_on_off_gbde(const char *name, int doingall) +{ + const char *ret; + char pass[64 * 2 + 1], bpass[64]; + char *dname; + int i, error; + + dname = swap_basename(name); + if (dname == NULL) + return (NULL); + + if (which_prog == SWAPON) { arc4random_buf(bpass, sizeof(bpass)); for (i = 0; i < (int)sizeof(bpass); i++) sprintf(&pass[2 * i], "%02x", bpass[i]); pass[sizeof(pass) - 1] = '\0'; - error = run_cmd(&fd, "%s init %s -P %s", _PATH_GBDE, + error = run_cmd(NULL, "%s init %s -P %s", _PATH_GBDE, dname, pass); if (error) { /* bde device found. Ignore it. */ - close(fd); + free(dname); if (!qflag) warnx("%s: Device already in use", name); return (NULL); } - close(fd); - error = run_cmd(&fd, "%s attach %s -p %s", _PATH_GBDE, + error = run_cmd(NULL, "%s attach %s -p %s", _PATH_GBDE, dname, pass); + free(dname); if (error) { - close(fd); warnx("gbde (attach) error: %s", name); return (NULL); } - break; - case SWAPOFF: - break; - default: - return (NULL); - break; } - if (fd != -1) - close(fd); + ret = swap_on_off_sfile(name, doingall); - fd = -1; - switch (which_prog) { - case SWAPOFF: - error = run_cmd(&fd, "%s detach %s", _PATH_GBDE, dname); + if (which_prog == SWAPOFF) { + error = run_cmd(NULL, "%s detach %s", _PATH_GBDE, dname); + free(dname); if (error) { /* bde device not found. Ignore it. */ if (!qflag) - warnx("%s: Device not found", dname); + warnx("%s: Device not found", name); return (NULL); } - break; - default: - return (NULL); - break; } - if (fd != -1) - close(fd); return (ret); } -static const char * -swap_on_off_geli(char *name, char *mntops, int doingall) +/* Build geli(8) arguments from mntopts */ +static char * +swap_on_geli_args(const char *mntops) { - char *ops, *aalgo, *ealgo, *keylen_str, *sectorsize_str; - char *dname, *p; - char args[4096]; - struct stat sb; - int fd, error, keylen, sectorsize; + const char *aalgo, *ealgo, *keylen_str, *sectorsize_str; + const char *aflag, *eflag, *lflag, *sflag; + char *p; + char *args; + char *token, *string, *ops; + int argsize, pagesize; + size_t pagesize_len; u_long ul; - dname = strdup(name); - p = strrchr(dname, '.'); - if (p == NULL) { - warnx("%s: Malformed device name", name); - return (NULL); + /* Use built-in defaults for geli(8) */ + aalgo = ealgo = keylen_str = ""; + aflag = eflag = lflag = ""; + + /* We will always specify sectorsize */ + sflag = " -s "; + sectorsize_str = NULL; + + if (mntops != NULL) { + string = ops = strdup(mntops); + + while ((token = strsep(&string, ",")) != NULL) { + if ((p = strstr(token, "aalgo=")) == token) { + aalgo = p + sizeof("aalgo=") - 1; + aflag = " -a "; + } else if ((p = strstr(token, "ealgo=")) == token) { + ealgo = p + sizeof("ealgo=") - 1; + eflag = " -e "; + } else if ((p = strstr(token, "keylen=")) == token) { + keylen_str = p + sizeof("keylen=") - 1; + errno = 0; + ul = strtoul(keylen_str, &p, 10); + if (errno == 0) { + if (*p != '\0' || ul > INT_MAX) + errno = EINVAL; + } + if (errno) { + warn("Invalid keylen: %s", keylen_str); + free(ops); + return (NULL); + } + lflag = " -l "; + } else if ((p = strstr(token, "sectorsize=")) == token) { + sectorsize_str = p + sizeof("sectorsize=") - 1; + errno = 0; + ul = strtoul(sectorsize_str, &p, 10); + if (errno == 0) { + if (*p != '\0' || ul > INT_MAX) + errno = EINVAL; + } + if (errno) { + warn("Invalid sectorsize: %s", sectorsize_str); + free(ops); + return (NULL); + } + } else if (strcmp(token, "sw") != 0) { + warnx("Invalid option: %s", token); + free(ops); + return (NULL); + } + } + } else + ops = NULL; + + /* + * If we do not have a sector size at this point, fill in + * pagesize as sector size. + */ + if (sectorsize_str == NULL) { + /* Use pagesize as default sectorsize */ + pagesize = getpagesize(); + pagesize_len = snprintf(NULL, 0, "%d", pagesize) + 1; + p = alloca(pagesize_len); + snprintf(p, pagesize_len, "%d", pagesize); + sectorsize_str = p; } - *p = '\0'; - ops = strdup(mntops); + argsize = asprintf(&args, "%s%s%s%s%s%s%s%s -d", + aflag, aalgo, eflag, ealgo, lflag, keylen_str, + sflag, sectorsize_str); - /* Default parameters for geli(8). */ - aalgo = aalgo_default; - ealgo = ealgo_default; - keylen = 256; - sectorsize = 4096; + free(ops); + return (args); +} - if ((p = strstr(ops, "aalgo=")) != NULL) { - aalgo = p + sizeof("aalgo=") - 1; - p = strchr(aalgo, ','); - if (p != NULL) - *p = '\0'; - } - if ((p = strstr(ops, "ealgo=")) != NULL) { - ealgo = p + sizeof("ealgo=") - 1; - p = strchr(ealgo, ','); - if (p != NULL) - *p = '\0'; - } - if ((p = strstr(ops, "keylen=")) != NULL) { - keylen_str = p + sizeof("keylen=") - 1; - p = strchr(keylen_str, ','); - if (p != NULL) - *p = '\0'; - errno = 0; - ul = strtoul(keylen_str, &p, 10); - if (errno == 0) { - if (*p != '\0' || ul > INT_MAX) - errno = EINVAL; - } - if (errno) { - warn("Invalid keylen: %s", keylen_str); +static const char * +swap_on_off_geli(const char *name, char *mntops, int doingall) +{ + char *dname; + char *args; + struct stat sb; + int error; + + error = stat(name, &sb); + + if (which_prog == SWAPON) do { + /* Skip if the .eli device already exists */ + if (error == 0) + break; + + args = swap_on_geli_args(mntops); + if (args == NULL) return (NULL); - } - keylen = (int)ul; - } - if ((p = strstr(ops, "sectorsize=")) != NULL) { - sectorsize_str = p + sizeof("sectorsize=") - 1; - p = strchr(sectorsize_str, ','); - if (p != NULL) - *p = '\0'; - errno = 0; - ul = strtoul(sectorsize_str, &p, 10); - if (errno == 0) { - if (*p != '\0' || ul > INT_MAX) - errno = EINVAL; - } - if (errno) { - warn("Invalid sectorsize: %s", sectorsize_str); + + dname = swap_basename(name); + if (dname == NULL) { + free(args); return (NULL); } - sectorsize = (int)ul; - } - snprintf(args, sizeof(args), "-a %s -e %s -l %d -s %d -d", - aalgo, ealgo, keylen, sectorsize); - args[sizeof(args) - 1] = '\0'; - free((void *)ops); - fd = -1; - switch (which_prog) { - case SWAPON: - error = run_cmd(&fd, "%s onetime %s %s", _PATH_GELI, args, + error = run_cmd(NULL, "%s onetime%s %s", _PATH_GELI, args, dname); + + free(dname); + free(args); + if (error) { - /* eli device found. Ignore it. */ - close(fd); + /* error occured during creation */ if (!qflag) - warnx("%s: Device already in use " - "or invalid parameters", name); + warnx("%s: Invalid parameters", name); return (NULL); } - break; - case SWAPOFF: - if (stat(name, &sb) == -1 && errno == ENOENT) { - if (!qflag) - warnx("%s: Device not found", name); - return (NULL); - } - break; - default: - return (NULL); - break; - } - if (fd != -1) - close(fd); + } while (0); return (swap_on_off_sfile(name, doingall)); } static const char * -swap_on_off_md(char *name, char *mntops, int doingall) +swap_on_off_md(const char *name, char *mntops, int doingall) { FILE *sfd; int fd, mdunit, error; @@ -467,8 +481,7 @@ swap_on_off_md(char *name, char *mntops, int doingall) return (NULL); } - switch (which_prog) { - case SWAPON: + if (which_prog == SWAPON) { if (mdunit == -1) { error = run_cmd(&fd, "%s -l -n -f %s", _PATH_MDCONFIG, vnodefile); @@ -534,8 +547,7 @@ swap_on_off_md(char *name, char *mntops, int doingall) return (NULL); } } - break; - case SWAPOFF: + } else /* SWAPOFF */ { if (mdunit == -1) { error = run_cmd(&fd, "%s -l -n -f %s", _PATH_MDCONFIG, vnodefile); @@ -590,17 +602,13 @@ swap_on_off_md(char *name, char *mntops, int doingall) return (NULL); } } - break; - default: - return (NULL); } snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV, MD_NAME, mdunit); mdpath[sizeof(mdpath) - 1] = '\0'; ret = swap_on_off_sfile(mdpath, doingall); - switch (which_prog) { - case SWAPOFF: + if (which_prog == SWAPOFF) { if (ret != NULL) { error = run_cmd(NULL, "%s -d -u %d", _PATH_MDCONFIG, mdunit); @@ -608,9 +616,6 @@ swap_on_off_md(char *name, char *mntops, int doingall) warn("mdconfig (detach) detach failed: %s%s%d", _PATH_DEV, MD_NAME, mdunit); } - break; - default: - break; } err: if (sfd != NULL) @@ -695,21 +700,15 @@ run_cmd(int *ofd, const char *cmdline, ...) } static const char * -swap_on_off_sfile(char *name, int doingall) +swap_on_off_sfile(const char *name, int doingall) { int error; - switch (which_prog) { - case SWAPON: + if (which_prog == SWAPON) error = swapon(name); - break; - case SWAPOFF: + else /* SWAPOFF */ error = swapoff(name); - break; - default: - error = 0; - break; - } + if (error == -1) { switch (errno) { case EBUSY: -- cgit v1.1 From 86e2a6aa52b322e694431e4ddc508c6317492044 Mon Sep 17 00:00:00 2001 From: hrs Date: Sun, 30 Jun 2013 07:37:31 +0000 Subject: Do not display a warning message in a jail without AF_INET6 support. MFC after: 3 days --- sbin/ifconfig/af_nd6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c index 5c46452..ace07ab 100644 --- a/sbin/ifconfig/af_nd6.c +++ b/sbin/ifconfig/af_nd6.c @@ -148,7 +148,7 @@ nd6_status(int s) memset(&nd, 0, sizeof(nd)); strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname)); if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - if (errno != EAFNOSUPPORT) + if (errno != EAFNOSUPPORT && error != EPROTONOSUPPORT) warn("socket(AF_INET6, SOCK_DGRAM)"); return; } -- cgit v1.1 From 19b98edeaa547dba0c26311a323dd0ebba0a0860 Mon Sep 17 00:00:00 2001 From: schweikh Date: Sun, 30 Jun 2013 17:59:40 +0000 Subject: Correct some grammar. --- sbin/hastd/hastd.8 | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'sbin') diff --git a/sbin/hastd/hastd.8 b/sbin/hastd/hastd.8 index b614f36..017e895 100644 --- a/sbin/hastd/hastd.8 +++ b/sbin/hastd/hastd.8 @@ -70,18 +70,18 @@ hastd: () .Pp If (and only if) .Nm -operates in primary role for the given resource, corresponding +operates in primary role for the given resource, a corresponding .Pa /dev/hast/ disk-like device (GEOM provider) is created. File systems and applications can use this provider to send I/O requests to. Every write, delete and flush operation .Dv ( BIO_WRITE , BIO_DELETE , BIO_FLUSH ) -is send to local component and replicated to the remote (secondary) node if it -is available. +is sent to the local component and replicated on the remote (secondary) node +if it is available. Read operations .Dv ( BIO_READ ) -are handled locally unless I/O error occurs or local version of the data +are handled locally unless an I/O error occurs or the local version of the data is not up-to-date yet (synchronization is in progress). .Pp The @@ -100,38 +100,38 @@ The connection between two .Nm daemons is always initiated from the one running as primary to the one running as secondary. -When primary +When the primary .Nm -is unable to connect or connection fails, it will try to re-establish -connection every few seconds. -Once connection is established, primary +is unable to connect or the connection fails, it will try to re-establish +the connection every few seconds. +Once the connection is established, the primary .Nm will synchronize every extent that was modified during connection outage to the secondary .Nm . .Pp -It is possible that in case of connection outage between the nodes +It is possible that in the case of a connection outage between the nodes the .Nm primary role for the given resource will be configured on both nodes. This in turn leads to incompatible data modifications. -Such condition is called split-brain and cannot be automatically +Such a condition is called a split-brain and cannot be automatically resolved by the .Nm -daemon as this will lead most likely to data corruption or lost of +daemon as this will lead most likely to data corruption or loss of important changes. Even though it cannot be fixed by .Nm -itself, it will be detected and further connection between independently +itself, it will be detected and a further connection between independently modified nodes will not be possible. -Once this situation is manually resolved by an administrator, resource +Once this situation is manually resolved by an administrator, the resource on one of the nodes can be initialized (erasing local data), which makes -connection to the remote node possible again. -Connection of freshly initialized component will trigger full resource +a connection to the remote node possible again. +Connection of the freshly initialized component will trigger full resource synchronization. .Pp -The +A .Nm -daemon itself never picks his role up automatically. +daemon never picks its role automatically. The role has to be configured with the .Xr hastctl 8 control utility by additional software like @@ -139,7 +139,7 @@ control utility by additional software like or .Nm heartbeat that can reliably manage role separation and switch secondary node to -primary role in case of original primary failure. +primary role in case of the primary's failure. .Pp The .Nm -- cgit v1.1 From 5092fcd6407b7957943a19df1a41c997dce8a9cf Mon Sep 17 00:00:00 2001 From: trociny Date: Mon, 1 Jul 2013 18:41:07 +0000 Subject: Make hastctl(1) ('list' command) output a worker pid. Reviewed by: pjd MFC after: 3 days --- sbin/hastctl/hastctl.c | 4 ++++ sbin/hastd/control.c | 1 + 2 files changed, 5 insertions(+) (limited to 'sbin') diff --git a/sbin/hastctl/hastctl.c b/sbin/hastctl/hastctl.c index 6fe55fa..11b5b8d 100644 --- a/sbin/hastctl/hastctl.c +++ b/sbin/hastctl/hastctl.c @@ -293,6 +293,7 @@ control_set_role(struct nv *nv, const char *newrole) static int control_list(struct nv *nv) { + pid_t pid; unsigned int ii; const char *str; int error, ret; @@ -331,6 +332,9 @@ control_list(struct nv *nv) str = nv_get_string(nv, "status%u", ii); if (str != NULL) printf(" status: %s\n", str); + pid = nv_get_int32(nv, "workerpid%u", ii); + if (pid != 0) + printf(" workerpid: %d\n", pid); printf(" dirty: %ju (%NB)\n", (uintmax_t)nv_get_uint64(nv, "dirty%u", ii), (intmax_t)nv_get_uint64(nv, "dirty%u", ii)); diff --git a/sbin/hastd/control.c b/sbin/hastd/control.c index 3619fc6..922f507 100644 --- a/sbin/hastd/control.c +++ b/sbin/hastd/control.c @@ -271,6 +271,7 @@ control_status(struct hastd_config *cfg, struct nv *nvout, nv_add_string(nvout, compression_name(res->hr_compression), "compression%u", no); nv_add_string(nvout, role2str(res->hr_role), "role%u", no); + nv_add_int32(nvout, res->hr_workerpid, "workerpid%u", no); switch (res->hr_role) { case HAST_ROLE_PRIMARY: -- cgit v1.1 From c646da3daf521a7bfe3e2d3ea2851f17b5923b11 Mon Sep 17 00:00:00 2001 From: delphij Date: Mon, 1 Jul 2013 21:18:39 +0000 Subject: Correct a typo in comment. --- sbin/swapon/swapon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c index 6e80097..b0b43d6 100644 --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -310,7 +310,7 @@ swap_on_off_gbde(const char *name, int doingall) return (ret); } -/* Build geli(8) arguments from mntopts */ +/* Build geli(8) arguments from mntops */ static char * swap_on_geli_args(const char *mntops) { -- cgit v1.1 From 16596db60f50f7a2f26b1e45158d41df037b88c3 Mon Sep 17 00:00:00 2001 From: asomers Date: Mon, 1 Jul 2013 21:20:17 +0000 Subject: Add syslog(3) support to devd(8). sbin/devd/devd.cc All output will now go to syslog(3) if devd is daemonized, or stderr if it's running in the foreground. sbin/devd/devd.8 Remove the "-D" flag. Filtering messages by priority now happens in the usual syslog way. For performance reasons, a few extra-verbose debugging statements are now conditional on the "-d" (do not daemonize) flag. etc/syslog.conf etc/newsyslog.conf Direct messages from devd(8) to /var/log/devd.log, but leave it disabled by default Reviewed by: eadler Approved by: gibbs (co-mentor) MFC after: never (removed a command-line option from devd) --- sbin/devd/devd.8 | 6 ++-- sbin/devd/devd.cc | 90 +++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 60 insertions(+), 36 deletions(-) (limited to 'sbin') diff --git a/sbin/devd/devd.8 b/sbin/devd/devd.8 index 8e33236..1869de6 100644 --- a/sbin/devd/devd.8 +++ b/sbin/devd/devd.8 @@ -33,7 +33,7 @@ .Nd "device state change daemon" .Sh SYNOPSIS .Nm -.Op Fl Ddn +.Op Fl dn .Op Fl f Ar file .Op Fl l Ar num .Sh DESCRIPTION @@ -44,10 +44,8 @@ kernel events happen. .Pp The following options are accepted. .Bl -tag -width ".Fl f Ar file" -.It Fl D -Enable debugging messages. .It Fl d -Run in the foreground instead of becoming a daemon. +Run in the foreground instead of becoming a daemon and log additional information for debugging. .It Fl f Ar file Use configuration file .Ar file diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index b227589..3673493 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -114,13 +115,13 @@ static const char detach = '-'; static struct pidfh *pfh; -int Dflag; int dflag; int nflag; static volatile sig_atomic_t romeo_must_die = 0; static const char *configfile = CF; +static void devdlog(int priority, const char* message, ...); static void event_loop(void); static void usage(void); @@ -243,8 +244,7 @@ bool action::do_action(config &c) { string s = c.expand_string(_cmd.c_str()); - if (Dflag) - fprintf(stderr, "Executing '%s'\n", s.c_str()); + devdlog(LOG_NOTICE, "Executing '%s'\n", s.c_str()); my_system(s.c_str()); return (true); } @@ -268,9 +268,16 @@ match::do_match(config &c) const string &value = c.get_variable(_var); bool retval; - if (Dflag) - fprintf(stderr, "Testing %s=%s against %s, invert=%d\n", + /* + * This function gets called WAY too often to justify calling syslog() + * each time, even at LOG_DEBUG. Because if syslogd isn't running, it + * can consume excessive amounts of systime inside of connect(). Only + * log when we're in -d mode. + */ + if (dflag) { + devdlog(LOG_DEBUG, "Testing %s=%s against %s, invert=%d\n", _var.c_str(), value.c_str(), _re.c_str(), _inv); + } retval = (regexec(&_regex, value.c_str(), 0, NULL, 0) == 0); if (_inv == 1) @@ -322,8 +329,7 @@ media::do_match(config &c) value = c.get_variable("device-name"); if (value.empty()) value = c.get_variable("subsystem"); - if (Dflag) - fprintf(stderr, "Testing media type of %s against 0x%x\n", + devdlog(LOG_DEBUG, "Testing media type of %s against 0x%x\n", value.c_str(), _type); retval = false; @@ -335,13 +341,11 @@ media::do_match(config &c) if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0 && ifmr.ifm_status & IFM_AVALID) { - if (Dflag) - fprintf(stderr, "%s has media type 0x%x\n", + devdlog(LOG_DEBUG, "%s has media type 0x%x\n", value.c_str(), IFM_TYPE(ifmr.ifm_active)); retval = (IFM_TYPE(ifmr.ifm_active) == _type); } else if (_type == -1) { - if (Dflag) - fprintf(stderr, "%s has unknown media type\n", + devdlog(LOG_DEBUG, "%s has unknown media type\n", value.c_str()); retval = true; } @@ -374,8 +378,14 @@ var_list::is_set(const string &var) const void var_list::set_variable(const string &var, const string &val) { - if (Dflag) - fprintf(stderr, "setting %s=%s\n", var.c_str(), val.c_str()); + /* + * This function gets called WAY too often to justify calling syslog() + * each time, even at LOG_DEBUG. Because if syslogd isn't running, it + * can consume excessive amounts of systime inside of connect(). Only + * log when we're in -d mode. + */ + if (dflag) + devdlog(LOG_DEBUG, "setting %s=%s\n", var.c_str(), val.c_str()); _vars[var] = val; } @@ -393,8 +403,7 @@ config::reset(void) void config::parse_one_file(const char *fn) { - if (Dflag) - fprintf(stderr, "Parsing %s\n", fn); + devdlog(LOG_DEBUG, "Parsing %s\n", fn); yyin = fopen(fn, "r"); if (yyin == NULL) err(1, "Cannot open config file %s", fn); @@ -411,8 +420,7 @@ config::parse_files_in_dir(const char *dirname) struct dirent *dp; char path[PATH_MAX]; - if (Dflag) - fprintf(stderr, "Parsing files in %s\n", dirname); + devdlog(LOG_DEBUG, "Parsing files in %s\n", dirname); dirp = opendir(dirname); if (dirp == NULL) return; @@ -539,8 +547,7 @@ config::push_var_table() vl = new var_list(); _var_list_table.push_back(vl); - if (Dflag) - fprintf(stderr, "Pushing table\n"); + devdlog(LOG_DEBUG, "Pushing table\n"); } void @@ -548,8 +555,7 @@ config::pop_var_table() { delete _var_list_table.back(); _var_list_table.pop_back(); - if (Dflag) - fprintf(stderr, "Popping table\n"); + devdlog(LOG_DEBUG, "Popping table\n"); } void @@ -731,8 +737,7 @@ config::find_and_execute(char type) s = "detach"; break; } - if (Dflag) - fprintf(stderr, "Processing %s event\n", s); + devdlog(LOG_DEBUG, "Processing %s event\n", s); for (i = l->begin(); i != l->end(); ++i) { if ((*i)->matches(*this)) { (*i)->run(*this); @@ -750,8 +755,7 @@ process_event(char *buffer) char *sp; sp = buffer + 1; - if (Dflag) - fprintf(stderr, "Processing event '%s'\n", buffer); + devdlog(LOG_DEBUG, "Processing event '%s'\n", buffer); type = *buffer++; cfg.push_var_table(); // No match doesn't have a device, and the format is a little @@ -843,6 +847,8 @@ notify_clients(const char *data, int len) --num_clients; close(*i); i = clients.erase(i); + devdlog(LOG_WARNING, "notify_clients: write() failed; " + "dropping unresponsive client\n"); } else ++i; } @@ -871,6 +877,8 @@ check_clients(void) --num_clients; close(*i); i = clients.erase(i); + devdlog(LOG_NOTICE, "check_clients: " + "dropping disconnected client\n"); } else ++i; } @@ -923,8 +931,7 @@ event_loop(void) rv = select(fd + 1, &fds, &fds, &fds, &tv); // No events -> we've processed all pending events if (rv == 0) { - if (Dflag) - fprintf(stderr, "Calling daemon\n"); + devdlog(LOG_DEBUG, "Calling daemon\n"); cfg.remove_pidfile(); cfg.open_pidfile(); daemon(0, 0); @@ -967,6 +974,11 @@ event_loop(void) if (FD_ISSET(fd, &fds)) { rv = read(fd, buffer, sizeof(buffer) - 1); if (rv > 0) { + if (rv == sizeof(buffer) - 1) { + devdlog(LOG_WARNING, "Warning: " + "available event data exceeded " + "buffer space\n"); + } notify_clients(buffer, rv); buffer[rv] = '\0'; while (buffer[--rv] == '\n') @@ -1078,10 +1090,27 @@ gensighand(int) romeo_must_die = 1; } +/* + * Local logging function. Prints to syslog if we're daemonized; syslog + * otherwise. + */ +static void +devdlog(int priority, const char* fmt, ...) +{ + va_list argp; + + va_start(argp, fmt); + if (dflag) + vfprintf(stderr, fmt, argp); + else + vsyslog(priority, fmt, argp); + va_end(argp); +} + static void usage() { - fprintf(stderr, "usage: %s [-Ddn] [-l connlimit] [-f file]\n", + fprintf(stderr, "usage: %s [-dn] [-l connlimit] [-f file]\n", getprogname()); exit(1); } @@ -1111,11 +1140,8 @@ main(int argc, char **argv) int ch; check_devd_enabled(); - while ((ch = getopt(argc, argv, "Ddf:l:n")) != -1) { + while ((ch = getopt(argc, argv, "df:l:n")) != -1) { switch (ch) { - case 'D': - Dflag++; - break; case 'd': dflag++; break; -- cgit v1.1 From ac1ae1504aee457d87f82dbf667b995a1fa6a4ac Mon Sep 17 00:00:00 2001 From: asomers Date: Mon, 1 Jul 2013 21:33:05 +0000 Subject: Add a SIGINFO handler to devd. It will send useful statistics to syslog or stderr as appropriate. Currently, the only statistic printed is the number of events received. Reviewed by: eadler Approved by: gibbs (co-mentor) --- sbin/devd/devd.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'sbin') diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index 3673493..35dbae6 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -117,6 +117,8 @@ static struct pidfh *pfh; int dflag; int nflag; +static unsigned total_events = 0; +static volatile sig_atomic_t got_siginfo = 0; static volatile sig_atomic_t romeo_must_die = 0; static const char *configfile = CF; @@ -965,6 +967,11 @@ event_loop(void) tv.tv_usec = 0; } rv = select(max_fd, &fds, NULL, NULL, &tv); + if (got_siginfo) { + devdlog(LOG_INFO, "Events received so far=%ld\n", + total_events); + got_siginfo = 0; + } if (rv == -1) { if (errno == EINTR) continue; @@ -974,6 +981,7 @@ event_loop(void) if (FD_ISSET(fd, &fds)) { rv = read(fd, buffer, sizeof(buffer) - 1); if (rv > 0) { + total_events++; if (rv == sizeof(buffer) - 1) { devdlog(LOG_WARNING, "Warning: " "available event data exceeded " @@ -1091,6 +1099,16 @@ gensighand(int) } /* + * SIGINFO handler. Will print useful statistics to the syslog or stderr + * as appropriate + */ +static void +siginfohand(int) +{ + got_siginfo = 1; +} + +/* * Local logging function. Prints to syslog if we're daemonized; syslog * otherwise. */ @@ -1169,6 +1187,7 @@ main(int argc, char **argv) signal(SIGHUP, gensighand); signal(SIGINT, gensighand); signal(SIGTERM, gensighand); + signal(SIGINFO, siginfohand); event_loop(); return (0); } -- cgit v1.1 From 43aec3b2a7b84716825ba1dc95941aaa100bf03c Mon Sep 17 00:00:00 2001 From: asomers Date: Mon, 1 Jul 2013 21:49:17 +0000 Subject: style(9) fixes, including the removal of page break characters. No functional changes. Approved by: gibbs (co-mentor) --- sbin/devd/devd.cc | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'sbin') diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index 35dbae6..1bd9afe 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -170,7 +170,7 @@ bool event_proc::run(config &c) const { vector::const_iterator i; - + for (i = _epsvec.begin(); i != _epsvec.end(); ++i) if (!(*i)->do_action(c)) return (false); @@ -178,7 +178,7 @@ event_proc::run(config &c) const } action::action(const char *cmd) - : _cmd(cmd) + : _cmd(cmd) { // nothing } @@ -197,7 +197,7 @@ my_system(const char *command) sigset_t newsigblock, oldsigblock; if (!command) /* just checking... */ - return(1); + return (1); /* * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save @@ -270,7 +270,7 @@ match::do_match(config &c) const string &value = c.get_variable(_var); bool retval; - /* + /* * This function gets called WAY too often to justify calling syslog() * each time, even at LOG_DEBUG. Because if syslogd isn't running, it * can consume excessive amounts of systime inside of connect(). Only @@ -285,7 +285,7 @@ match::do_match(config &c) if (_inv == 1) retval = (retval == 0) ? 1 : 0; - return retval; + return (retval); } #include @@ -354,7 +354,7 @@ media::do_match(config &c) close(s); } - return retval; + return (retval); } const string var_list::bogus = "_$_$_$_$_B_O_G_U_S_$_$_$_$_"; @@ -470,7 +470,7 @@ void config::open_pidfile() { pid_t otherpid; - + if (_pidfile.empty()) return; pfh = pidfile_open(_pidfile.c_str(), 0600, &otherpid); @@ -484,21 +484,21 @@ config::open_pidfile() void config::write_pidfile() { - + pidfile_write(pfh); } void config::close_pidfile() { - + pidfile_close(pfh); } void config::remove_pidfile() { - + pidfile_remove(pfh); } @@ -546,7 +546,7 @@ void config::push_var_table() { var_list *vl; - + vl = new var_list(); _var_list_table.push_back(vl); devdlog(LOG_DEBUG, "Pushing table\n"); @@ -581,7 +581,7 @@ config::get_variable(const string &var) bool config::is_id_char(char ch) const { - return (ch != '\0' && (isalpha(ch) || isdigit(ch) || ch == '_' || + return (ch != '\0' && (isalpha(ch) || isdigit(ch) || ch == '_' || ch == '-')); } @@ -597,7 +597,7 @@ config::expand_one(const char *&src, string &dst) dst += *src++; return; } - + // $(foo) -> $(foo) // Not sure if I want to support this or not, so for now we just pass // it through. @@ -614,7 +614,7 @@ config::expand_one(const char *&src, string &dst) } return; } - + // $[^A-Za-z] -> $\1 if (!isalpha(*src)) { dst += '$'; @@ -665,7 +665,7 @@ bool config::chop_var(char *&buffer, char *&lhs, char *&rhs) const { char *walker; - + if (*buffer == '\0') return (false); walker = lhs = buffer; @@ -749,7 +749,7 @@ config::find_and_execute(char type) } - + static void process_event(char *buffer) { @@ -800,7 +800,7 @@ process_event(char *buffer) cfg.set_variable("bus", sp + 3); break; } - + cfg.find_and_execute(type); cfg.pop_var_table(); } @@ -1005,7 +1005,7 @@ event_loop(void) } close(fd); } - + /* * functions that the parser uses. */ @@ -1090,7 +1090,7 @@ set_variable(const char *var, const char *val) free(const_cast(val)); } - + static void gensighand(int) -- cgit v1.1 From e997c4f73e2321b11519e1780bccb90cdba46151 Mon Sep 17 00:00:00 2001 From: wblock Date: Mon, 1 Jul 2013 22:38:36 +0000 Subject: Add a new gptboot(8) man page. Factor out the redundant information in gpart(8) and boot(8), adding references to gptboot(8) in both. Reviewed by: jhb, ae, pjd, Paul Schenkeveld , david_a_bright@dell.com (portions), gjb MFC after: 1 week --- sbin/geom/class/part/gpart.8 | 90 ++++++++++++-------------------------------- sbin/reboot/boot_i386.8 | 3 +- 2 files changed, 27 insertions(+), 66 deletions(-) (limited to 'sbin') diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8 index 7386900..3ce79a8 100644 --- a/sbin/geom/class/part/gpart.8 +++ b/sbin/geom/class/part/gpart.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 25, 2013 +.Dd July 1, 2013 .Dt GPART 8 .Os .Sh NAME @@ -645,14 +645,12 @@ The scheme-specific attributes for GPT: When set, the .Nm gptboot stage 1 boot loader will try to boot the system from this partition. -Multiple partitions might be marked with the +Multiple partitions can be marked with the .Cm bootme attribute. -In such scenario the -.Nm gptboot -will try all -.Cm bootme -partitions one by one, until the next boot stage is successfully entered. +See +.Xr gptboot 8 +for more details. .It Cm bootonce Setting this attribute automatically sets the .Cm bootme @@ -660,49 +658,14 @@ attribute. When set, the .Nm gptboot stage 1 boot loader will try to boot the system from this partition only once. -Partitions with both -.Cm bootonce -and -.Cm bootme -attributes are tried before partitions with only the -.Cm bootme -attribute. -Before -.Cm bootonce -partition is tried, the -.Nm gptboot -removes the -.Cm bootme -attribute and tries to execute the next boot stage. -If it fails, the -.Cm bootonce -attribute that is now alone is replaced with the -.Cm bootfailed -attribute. -If the execution of the next boot stage succeeds, but the system is not fully -booted, the -.Nm gptboot -will look for -.Cm bootonce -attributes alone (without the -.Cm bootme -attribute) on the next system boot and will replace those with the -.Cm bootfailed -attribute. -If the system is fully booted, the -.Pa /etc/rc.d/gptboot -start-up script will look for partition with the -.Cm bootonce -attribute alone, will remove the attribute and log that the system was -successfully booted from this partition. -There should be at most one -.Cm bootonce -partition when system is successfully booted. -Multiple partitions might be marked with the +Multiple partitions can be marked with the .Cm bootonce and .Cm bootme attribute pairs. +See +.Xr gptboot 8 +for more details. .It Cm bootfailed This attribute should not be manually managed. It is managed by the @@ -710,14 +673,9 @@ It is managed by the stage 1 boot loader and the .Pa /etc/rc.d/gptboot start-up script. -This attribute is used to mark partitions that had the -.Cm bootonce -attribute set, but we failed to boot from them. -Once we successfully boot, the -.Pa /etc/rc.d/gptboot -script will log all the partitions we failed to boot from and will remove the -.Cm bootfailed -attributes. +See +.Xr gptboot 8 +for more details. .El .Pp The scheme-specific attributes for MBR: @@ -795,20 +753,17 @@ There are two variants of bootstrap code to write to this partition: .Pa /boot/gptboot and .Pa /boot/gptzfsboot . +.Pp .Pa /boot/gptboot -is used to boot from UFS. -It searches through +is used to boot from UFS partitions. +.Cm gptboot +searches through .Cm freebsd-ufs -partitions in the GPT and boots from the first one with the +partitions in the GPT and selects one to boot based on the .Cm bootonce -attribute set. -If that attribute is not found, -.Pa /boot/gptboot -boots from the first -.Cm freebsd-ufs -partition with the +and .Cm bootme -attribute set. +attributes. If neither attribute is found, .Pa /boot/gptboot boots from the first @@ -817,6 +772,10 @@ partition. .Pa /boot/loader .Pq the third bootstrap stage is loaded from the first partition that matches these conditions. +See +.Xr gptboot 8 +for more information. +.Pp .Pa /boot/gptzfsboot is used to boot from ZFS. It searches through the GPT for @@ -1105,7 +1064,8 @@ and .Xr dd 1 , .Xr geom 4 , .Xr boot0cfg 8 , -.Xr geom 8 +.Xr geom 8 , +.Xr gptboot 8 .Sh HISTORY The .Nm diff --git a/sbin/reboot/boot_i386.8 b/sbin/reboot/boot_i386.8 index 33ad8fe..e21e53f 100644 --- a/sbin/reboot/boot_i386.8 +++ b/sbin/reboot/boot_i386.8 @@ -36,7 +36,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 4, 2010 +.Dd July 1, 2013 .Dt BOOT 8 i386 .Os .Sh NAME @@ -351,6 +351,7 @@ requirement has not been adhered to. .Xr bsdlabel 8 , .Xr btxld 8 , .Xr config 8 , +.Xr gptboot 8 , .Xr halt 8 , .Xr loader 8 , .Xr nextboot 8 , -- cgit v1.1 From 6529e87c61a9c60000112cf67afaf6544205f2d7 Mon Sep 17 00:00:00 2001 From: bms Date: Tue, 2 Jul 2013 13:24:37 +0000 Subject: When acquiring a lease, record the value of the BOOTP siaddr field contained in the DHCP offer, and write it out to the lease file as an unquoted value of the "next-server" keyword. The value is ignored when the lease is read back by dhclient, however other applications are free to parse it. The intent behind this change is to allow easier interoperability with automated installation systems e.g. Cobbler, Foreman, Razor; FreeBSD installation kernels can automatically probe the network to discover deployment servers. There are no plans to MFC this change unless a backport is specifically requested. The syntax of the "next-server " lease keyword is intended to be identical to that used by the ISC DHCPD server in its configuration files. The required defines are already present in dhclient but were unused before this change. (Note: This is NOT the same as Option 66, tftp-server-name). It has been exercised in a university protocol testbed environment, with Cobbler and an mfsBSD image containing pc-sysinstall (driven by Cobbler Cheetah templates). The SYSLINUX memdisk driver is used to boot mfsBSD. Currently this approach requires that a dedicated system profile has been created for the node where FreeBSD is to be deployed. If this is not present, the pc-sysinstall wrapper will be unable to obtain a node configuration. There is code in progress to allow mfsBSD images to obtain the required hints from the memdisk environment by parsing the MBFT ACPI chunk. This is non-standard as it is not linked into the platform's ACPI RSDT. Reviewed by: des --- sbin/dhclient/clparse.c | 4 ++++ sbin/dhclient/dhclient.c | 8 ++++++++ sbin/dhclient/dhcpd.h | 1 + 3 files changed, 13 insertions(+) (limited to 'sbin') diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c index 58de8cc..4f234c7 100644 --- a/sbin/dhclient/clparse.c +++ b/sbin/dhclient/clparse.c @@ -642,6 +642,10 @@ parse_client_lease_declaration(FILE *cfile, struct client_lease *lease, case FILENAME: lease->filename = parse_string(cfile); return; + case NEXT_SERVER: + if (!parse_ip_addr(cfile, &lease->nextserver)) + return; + break; case SERVER_NAME: lease->server_name = parse_string(cfile); return; diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index f71c8c8..a6ee6db 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1063,6 +1063,9 @@ packet_to_lease(struct packet *packet) lease->address.len = sizeof(packet->raw->yiaddr); memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len); + lease->nextserver.len = sizeof(packet->raw->siaddr); + memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len); + /* If the server name was filled out, copy it. Do not attempt to validate the server name as a host name. RFC 2131 merely states that sname is NUL-terminated (which do @@ -1874,6 +1877,11 @@ write_client_lease(struct interface_info *ip, struct client_lease *lease, fprintf(leaseFile, " bootp;\n"); fprintf(leaseFile, " interface \"%s\";\n", ip->name); fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address)); + if (lease->nextserver.len == sizeof(inaddr_any) && + 0 != memcmp(lease->nextserver.iabuf, &inaddr_any, + sizeof(inaddr_any))) + fprintf(leaseFile, " next-server %s;\n", + piaddr(lease->nextserver)); if (lease->filename) fprintf(leaseFile, " filename \"%s\";\n", lease->filename); if (lease->server_name) diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 4762cbd..0644149 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -121,6 +121,7 @@ struct client_lease { struct client_lease *next; time_t expiry, renewal, rebind; struct iaddr address; + struct iaddr nextserver; char *server_name; char *filename; struct string_list *medium; -- cgit v1.1 From 9906aefa83b151c15370d858dc46d32cdd26ddf2 Mon Sep 17 00:00:00 2001 From: asomers Date: Tue, 2 Jul 2013 14:48:39 +0000 Subject: Explicitly include to fix compilation with libc++. It is implicitly included by libstdc++. Reported By: Oliver Hartmann Approved by: gibbs (co-mentor, implicit) --- sbin/devd/devd.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'sbin') diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index 1bd9afe..0f11a83 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -79,6 +79,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include -- cgit v1.1 From 63b9166cda11513191c2994745dd279a2d264169 Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 2 Jul 2013 17:34:34 +0000 Subject: Plug a memory leak. --- sbin/swapon/swapon.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sbin') diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c index b0b43d6..5dcb18d 100644 --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -491,6 +491,7 @@ swap_on_off_md(const char *name, char *mntops, int doingall) if (!qflag) warnx("%s: Device already in use", vnodefile); + free(vnodefile); return (NULL); } error = run_cmd(&fd, "%s -a -t vnode -n -f %s", @@ -498,6 +499,7 @@ swap_on_off_md(const char *name, char *mntops, int doingall) if (error) { warnx("mdconfig (attach) error: file=%s", vnodefile); + free(vnodefile); return (NULL); } sfd = fdopen(fd, "r"); @@ -537,6 +539,7 @@ swap_on_off_md(const char *name, char *mntops, int doingall) if (!qflag) warnx("md%d on %s: Device already " "in use", mdunit, vnodefile); + free(vnodefile); return (NULL); } error = run_cmd(NULL, "%s -a -t vnode -u %d -f %s", @@ -544,6 +547,7 @@ swap_on_off_md(const char *name, char *mntops, int doingall) if (error) { warnx("mdconfig (attach) error: " "md%d on file=%s", mdunit, vnodefile); + free(vnodefile); return (NULL); } } @@ -557,6 +561,7 @@ swap_on_off_md(const char *name, char *mntops, int doingall) if (!qflag) warnx("md on %s: Device not found", vnodefile); + free(vnodefile); return (NULL); } sfd = fdopen(fd, "r"); @@ -599,6 +604,7 @@ swap_on_off_md(const char *name, char *mntops, int doingall) if (!qflag) warnx("md%d on %s: Device not found", mdunit, vnodefile); + free(vnodefile); return (NULL); } } @@ -622,6 +628,7 @@ err: fclose(sfd); if (fd != -1) close(fd); + free(vnodefile); return (ret); } -- cgit v1.1 From 1559c2306ba6423667366b9d4ac8cb3a89498f07 Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 2 Jul 2013 19:42:47 +0000 Subject: When listing with -f, skip all memory disks that are not vnode-backed. Noticed by: kevlo MFC after: 3 days --- sbin/mdconfig/mdconfig.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/mdconfig/mdconfig.c b/sbin/mdconfig/mdconfig.c index 1a33905..6ba4cd6 100644 --- a/sbin/mdconfig/mdconfig.c +++ b/sbin/mdconfig/mdconfig.c @@ -450,7 +450,8 @@ md_list(const char *units, int opt, const char *fflag) continue; else ffound = 1; - } + } else if (fflag != NULL) + continue; if (nflag && strncmp(pp->lg_name, MD_NAME, 2) == 0) printf("%s", pp->lg_name + 2); else -- cgit v1.1 From 175de3296169e6480f853e2e9c8dc7686b28415c Mon Sep 17 00:00:00 2001 From: hrs Date: Wed, 3 Jul 2013 09:50:59 +0000 Subject: Fix a typo (s/error/errno/). --- sbin/ifconfig/af_nd6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c index ace07ab..b3db0a8 100644 --- a/sbin/ifconfig/af_nd6.c +++ b/sbin/ifconfig/af_nd6.c @@ -148,7 +148,7 @@ nd6_status(int s) memset(&nd, 0, sizeof(nd)); strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname)); if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - if (errno != EAFNOSUPPORT && error != EPROTONOSUPPORT) + if (errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT) warn("socket(AF_INET6, SOCK_DGRAM)"); return; } -- cgit v1.1 From 52ee09ff73267443a51540ba46a21d07f6b50fc7 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 21:41:35 +0000 Subject: MFp4: @229469: Garbage-collect dead prototypes. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/dhcpd.h | 6 ------ sbin/dhclient/packet.c | 5 ----- 2 files changed, 11 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 0644149..09941df 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -413,12 +413,6 @@ ssize_t decode_hw_header(unsigned char *, int, struct hardware *); ssize_t decode_udp_ip_header(unsigned char *, int, struct sockaddr_in *, unsigned char *, int); -/* ethernet.c */ -void assemble_ethernet_header(struct interface_info *, unsigned char *, - int *, struct hardware *); -ssize_t decode_ethernet_header(struct interface_info *, unsigned char *, - int, struct hardware *); - /* clparse.c */ int read_client_conf(void); void read_client_leases(void); diff --git a/sbin/dhclient/packet.c b/sbin/dhclient/packet.c index b7a4f21..39cf16d 100644 --- a/sbin/dhclient/packet.c +++ b/sbin/dhclient/packet.c @@ -55,11 +55,6 @@ __FBSDID("$FreeBSD$"); u_int32_t checksum(unsigned char *, unsigned, u_int32_t); u_int32_t wrapsum(u_int32_t); -void assemble_ethernet_header(struct interface_info *, unsigned char *, - int *, struct hardware *); -ssize_t decode_ethernet_header(struct interface_info *, unsigned char *, - int bufix, struct hardware *); - u_int32_t checksum(unsigned char *buf, unsigned nbytes, u_int32_t sum) { -- cgit v1.1 From e5e94b722420572a67052e000b5342a26cb616a4 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 21:45:29 +0000 Subject: MFp4 @229470: Remove unused argument from send_packet(). Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/bpf.c | 5 ++--- sbin/dhclient/dhclient.c | 6 +++--- sbin/dhclient/dhcpd.h | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index 9f8e45f..4dfe1f0 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -251,8 +251,7 @@ if_register_receive(struct interface_info *info) ssize_t send_packet(struct interface_info *interface, struct dhcp_packet *raw, - size_t len, struct in_addr from, struct sockaddr_in *to, - struct hardware *hto) + size_t len, struct in_addr from, struct sockaddr_in *to) { unsigned char buf[256]; struct iovec iov[2]; @@ -261,7 +260,7 @@ send_packet(struct interface_info *interface, struct dhcp_packet *raw, /* Assemble the headers... */ if (to->sin_addr.s_addr == INADDR_BROADCAST) - assemble_hw_header(interface, buf, &bufp, hto); + assemble_hw_header(interface, buf, &bufp, NULL); assemble_udp_ip_header(buf, &bufp, from.s_addr, to->sin_addr.s_addr, to->sin_port, (unsigned char *)raw, len); diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index a6ee6db..3069253 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1232,7 +1232,7 @@ again: /* Send out a packet. */ (void)send_packet(ip, &ip->client->packet, ip->client->packet_length, - inaddr_any, &sockaddr_broadcast, NULL); + inaddr_any, &sockaddr_broadcast); add_timeout(cur_time + ip->client->interval, send_discover, ip); } @@ -1463,7 +1463,7 @@ cancel: /* Send out a packet. */ (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, - from, &destination, NULL); + from, &destination); add_timeout(cur_time + ip->client->interval, send_request, ip); } @@ -1479,7 +1479,7 @@ send_decline(void *ipp) /* Send out a packet. */ (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, - inaddr_any, &sockaddr_broadcast, NULL); + inaddr_any, &sockaddr_broadcast); } void diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 09941df..346e2ce 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -301,7 +301,7 @@ int if_register_bpf(struct interface_info *); void if_register_send(struct interface_info *); void if_register_receive(struct interface_info *); ssize_t send_packet(struct interface_info *, struct dhcp_packet *, size_t, - struct in_addr, struct sockaddr_in *, struct hardware *); + struct in_addr, struct sockaddr_in *); ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *); -- cgit v1.1 From b1d67fde75321e5b768664986d6418424a830675 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 21:49:10 +0000 Subject: MFp4 @229471: Remove unused argument from assemble_hw_header(). Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/bpf.c | 2 +- sbin/dhclient/dhcpd.h | 3 +-- sbin/dhclient/packet.c | 7 ++----- 3 files changed, 4 insertions(+), 8 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index 4dfe1f0..6cf4358 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -260,7 +260,7 @@ send_packet(struct interface_info *interface, struct dhcp_packet *raw, /* Assemble the headers... */ if (to->sin_addr.s_addr == INADDR_BROADCAST) - assemble_hw_header(interface, buf, &bufp, NULL); + assemble_hw_header(interface, buf, &bufp); assemble_udp_ip_header(buf, &bufp, from.s_addr, to->sin_addr.s_addr, to->sin_port, (unsigned char *)raw, len); diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 346e2ce..920235b 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -405,8 +405,7 @@ void bootp(struct packet *); void dhcp(struct packet *); /* packet.c */ -void assemble_hw_header(struct interface_info *, unsigned char *, - int *, struct hardware *); +void assemble_hw_header(struct interface_info *, unsigned char *, int *); void assemble_udp_ip_header(unsigned char *, int *, u_int32_t, u_int32_t, unsigned int, unsigned char *, int); ssize_t decode_hw_header(unsigned char *, int, struct hardware *); diff --git a/sbin/dhclient/packet.c b/sbin/dhclient/packet.c index 39cf16d..f79ca2f 100644 --- a/sbin/dhclient/packet.c +++ b/sbin/dhclient/packet.c @@ -90,14 +90,11 @@ wrapsum(u_int32_t sum) void assemble_hw_header(struct interface_info *interface, unsigned char *buf, - int *bufix, struct hardware *to) + int *bufix) { struct ether_header eh; - if (to != NULL && to->hlen == 6) /* XXX */ - memcpy(eh.ether_dhost, to->haddr, sizeof(eh.ether_dhost)); - else - memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost)); + memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost)); if (interface->hw_address.hlen == sizeof(eh.ether_shost)) memcpy(eh.ether_shost, interface->hw_address.haddr, sizeof(eh.ether_shost)); -- cgit v1.1 From ca2a1d2a81b8f55541ac0c4ccc211bbe649c25ff Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 21:53:54 +0000 Subject: MFp4 @229472: Use the same type for 'from' and 'to' argument in send_packet(). Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/bpf.c | 21 ++++++++++++++------- sbin/dhclient/dhclient.c | 39 +++++++++++++-------------------------- sbin/dhclient/dhcpd.h | 2 +- 3 files changed, 28 insertions(+), 34 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index 6cf4358..920932e 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -251,7 +251,7 @@ if_register_receive(struct interface_info *info) ssize_t send_packet(struct interface_info *interface, struct dhcp_packet *raw, - size_t len, struct in_addr from, struct sockaddr_in *to) + size_t len, struct in_addr from, struct in_addr to) { unsigned char buf[256]; struct iovec iov[2]; @@ -259,10 +259,10 @@ send_packet(struct interface_info *interface, struct dhcp_packet *raw, int result, bufp = 0; /* Assemble the headers... */ - if (to->sin_addr.s_addr == INADDR_BROADCAST) + if (to.s_addr == INADDR_BROADCAST) assemble_hw_header(interface, buf, &bufp); - assemble_udp_ip_header(buf, &bufp, from.s_addr, - to->sin_addr.s_addr, to->sin_port, (unsigned char *)raw, len); + assemble_udp_ip_header(buf, &bufp, from.s_addr, to.s_addr, + htons(REMOTE_PORT), (unsigned char *)raw, len); iov[0].iov_base = (char *)buf; iov[0].iov_len = bufp; @@ -270,12 +270,19 @@ send_packet(struct interface_info *interface, struct dhcp_packet *raw, iov[1].iov_len = len; /* Fire it off */ - if (to->sin_addr.s_addr == INADDR_BROADCAST) + if (to.s_addr == INADDR_BROADCAST) result = writev(interface->wfdesc, iov, 2); else { + struct sockaddr_in sato; + + sato.sin_addr = to; + sato.sin_port = htons(REMOTE_PORT); + sato.sin_family = AF_INET; + sato.sin_len = sizeof(sato); + memset(&msg, 0, sizeof(msg)); - msg.msg_name = (struct sockaddr *)to; - msg.msg_namelen = sizeof(*to); + msg.msg_name = (struct sockaddr *)&sato; + msg.msg_namelen = sizeof(sato); msg.msg_iov = iov; msg.msg_iovlen = 2; result = sendmsg(interface->ufdesc, &msg, 0); diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 3069253..f17c11e 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -92,8 +92,7 @@ int privfd; int nullfd = -1; struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } }; -struct in_addr inaddr_any; -struct sockaddr_in sockaddr_broadcast; +struct in_addr inaddr_any, inaddr_broadcast; char *path_dhclient_pidfile; struct pidfh *pidfile; @@ -410,11 +409,7 @@ main(int argc, char *argv[]) tzset(); time(&cur_time); - memset(&sockaddr_broadcast, 0, sizeof(sockaddr_broadcast)); - sockaddr_broadcast.sin_family = AF_INET; - sockaddr_broadcast.sin_port = htons(REMOTE_PORT); - sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST; - sockaddr_broadcast.sin_len = sizeof(sockaddr_broadcast); + inaddr_broadcast.s_addr = INADDR_BROADCAST; inaddr_any.s_addr = INADDR_ANY; read_client_conf(); @@ -1226,13 +1221,12 @@ again: ip->client->secs = ip->client->packet.secs; note("DHCPDISCOVER on %s to %s port %d interval %d", - ip->name, inet_ntoa(sockaddr_broadcast.sin_addr), - ntohs(sockaddr_broadcast.sin_port), + ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT, (int)ip->client->interval); /* Send out a packet. */ (void)send_packet(ip, &ip->client->packet, ip->client->packet_length, - inaddr_any, &sockaddr_broadcast); + inaddr_any, inaddr_broadcast); add_timeout(cur_time + ip->client->interval, send_discover, ip); } @@ -1340,8 +1334,7 @@ void send_request(void *ipp) { struct interface_info *ip = ipp; - struct sockaddr_in destination; - struct in_addr from; + struct in_addr from, to; int interval; /* Figure out how long it's been since we started transmitting. */ @@ -1429,18 +1422,13 @@ cancel: /* If the lease T2 time has elapsed, or if we're not yet bound, broadcast the DHCPREQUEST rather than unicasting. */ - memset(&destination, 0, sizeof(destination)); if (ip->client->state == S_REQUESTING || ip->client->state == S_REBOOTING || cur_time > ip->client->active->rebind) - destination.sin_addr.s_addr = INADDR_BROADCAST; + to.s_addr = INADDR_BROADCAST; else - memcpy(&destination.sin_addr.s_addr, - ip->client->destination.iabuf, - sizeof(destination.sin_addr.s_addr)); - destination.sin_port = htons(REMOTE_PORT); - destination.sin_family = AF_INET; - destination.sin_len = sizeof(destination); + memcpy(&to.s_addr, ip->client->destination.iabuf, + sizeof(to.s_addr)); if (ip->client->state != S_REQUESTING) memcpy(&from, ip->client->active->address.iabuf, @@ -1458,12 +1446,12 @@ cancel: ip->client->packet.secs = htons(65535); } - note("DHCPREQUEST on %s to %s port %d", ip->name, - inet_ntoa(destination.sin_addr), ntohs(destination.sin_port)); + note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to), + REMOTE_PORT); /* Send out a packet. */ (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, - from, &destination); + from, to); add_timeout(cur_time + ip->client->interval, send_request, ip); } @@ -1474,12 +1462,11 @@ send_decline(void *ipp) struct interface_info *ip = ipp; note("DHCPDECLINE on %s to %s port %d", ip->name, - inet_ntoa(sockaddr_broadcast.sin_addr), - ntohs(sockaddr_broadcast.sin_port)); + inet_ntoa(inaddr_broadcast), REMOTE_PORT); /* Send out a packet. */ (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, - inaddr_any, &sockaddr_broadcast); + inaddr_any, inaddr_broadcast); } void diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 920235b..d642692 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -301,7 +301,7 @@ int if_register_bpf(struct interface_info *); void if_register_send(struct interface_info *); void if_register_receive(struct interface_info *); ssize_t send_packet(struct interface_info *, struct dhcp_packet *, size_t, - struct in_addr, struct sockaddr_in *); + struct in_addr, struct in_addr); ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *); -- cgit v1.1 From 1bb08cf6ef3fc73abf64cccbfb8383d67b2adedb Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 21:57:24 +0000 Subject: MFp4 @229473: No caller checks send_packet() return value, so make it void. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/bpf.c | 3 +-- sbin/dhclient/dhclient.c | 6 +++--- sbin/dhclient/dhcpd.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index 920932e..a840294 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -249,7 +249,7 @@ if_register_receive(struct interface_info *info) error("Cannot lock bpf"); } -ssize_t +void send_packet(struct interface_info *interface, struct dhcp_packet *raw, size_t len, struct in_addr from, struct in_addr to) { @@ -290,7 +290,6 @@ send_packet(struct interface_info *interface, struct dhcp_packet *raw, if (result < 0) warning("send_packet: %m"); - return (result); } ssize_t diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index f17c11e..2de8d39 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1225,7 +1225,7 @@ again: (int)ip->client->interval); /* Send out a packet. */ - (void)send_packet(ip, &ip->client->packet, ip->client->packet_length, + send_packet(ip, &ip->client->packet, ip->client->packet_length, inaddr_any, inaddr_broadcast); add_timeout(cur_time + ip->client->interval, send_discover, ip); @@ -1450,7 +1450,7 @@ cancel: REMOTE_PORT); /* Send out a packet. */ - (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, + send_packet(ip, &ip->client->packet, ip->client->packet_length, from, to); add_timeout(cur_time + ip->client->interval, send_request, ip); @@ -1465,7 +1465,7 @@ send_decline(void *ipp) inet_ntoa(inaddr_broadcast), REMOTE_PORT); /* Send out a packet. */ - (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, + send_packet(ip, &ip->client->packet, ip->client->packet_length, inaddr_any, inaddr_broadcast); } diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index d642692..1d0898d 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -300,7 +300,7 @@ struct hash_bucket *new_hash_bucket(void); int if_register_bpf(struct interface_info *); void if_register_send(struct interface_info *); void if_register_receive(struct interface_info *); -ssize_t send_packet(struct interface_info *, struct dhcp_packet *, size_t, +void send_packet(struct interface_info *, struct dhcp_packet *, size_t, struct in_addr, struct in_addr); ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *); -- cgit v1.1 From 837e9b7cac292f9c8c6bc6e015ee55a6b35a7ce5 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 21:58:26 +0000 Subject: MFp4 @229474: iov_base field is 'void *' in FreeBSD, no need to cast. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/bpf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index a840294..93410a8 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -264,9 +264,9 @@ send_packet(struct interface_info *interface, struct dhcp_packet *raw, assemble_udp_ip_header(buf, &bufp, from.s_addr, to.s_addr, htons(REMOTE_PORT), (unsigned char *)raw, len); - iov[0].iov_base = (char *)buf; + iov[0].iov_base = buf; iov[0].iov_len = bufp; - iov[1].iov_base = (char *)raw; + iov[1].iov_base = raw; iov[1].iov_len = len; /* Fire it off */ -- cgit v1.1 From e538ac2c30e98e93f2457669fa9c74e6522edf8a Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:01:52 +0000 Subject: MFp4 @229476,229478: Make use of two fields: rfdesc and wfdesc to keep bpf descriptor open for reading only in rfdesc and bpf descriptor open for writing only in wfdesc. In the end they will be used by two different processes. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/bpf.c | 128 +++++++++++++++++++++++++++----------------------- sbin/dhclient/dhcpd.h | 2 +- 2 files changed, 70 insertions(+), 60 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index 93410a8..c16e477 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -61,15 +61,15 @@ __FBSDID("$FreeBSD$"); * mask. */ int -if_register_bpf(struct interface_info *info) +if_register_bpf(struct interface_info *info, int flags) { char filename[50]; int sock, b; /* Open a BPF device */ - for (b = 0; 1; b++) { + for (b = 0;; b++) { snprintf(filename, sizeof(filename), BPF_FORMAT, b); - sock = open(filename, O_RDWR, 0); + sock = open(filename, flags); if (sock < 0) { if (errno == EBUSY) continue; @@ -87,16 +87,76 @@ if_register_bpf(struct interface_info *info) return (sock); } +/* + * Packet write filter program: + * 'ip and udp and src port bootps and dst port (bootps or bootpc)' + */ +struct bpf_insn dhcp_bpf_wfilter[] = { + BPF_STMT(BPF_LD + BPF_B + BPF_IND, 14), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (IPVERSION << 4) + 5, 0, 12), + + /* Make sure this is an IP packet... */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10), + + /* Make sure it's a UDP packet... */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8), + + /* Make sure this isn't a fragment... */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), + BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0), /* patched */ + + /* Get the IP header length... */ + BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14), + + /* Make sure it's from the right port... */ + BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 68, 0, 3), + + /* Make sure it is to the right ports ... */ + BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), + + /* If we passed all the tests, ask for the whole packet. */ + BPF_STMT(BPF_RET+BPF_K, (u_int)-1), + + /* Otherwise, drop it. */ + BPF_STMT(BPF_RET+BPF_K, 0), +}; + +int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn); + void if_register_send(struct interface_info *info) { + struct bpf_version v; + struct bpf_program p; int sock, on = 1; - /* - * If we're using the bpf API for sending and receiving, we - * don't need to register this interface twice. - */ - info->wfdesc = info->rfdesc; + /* Open a BPF device and hang it on this interface... */ + info->wfdesc = if_register_bpf(info, O_WRONLY); + + /* Make sure the BPF version is in range... */ + if (ioctl(info->wfdesc, BIOCVERSION, &v) < 0) + error("Can't get BPF version: %m"); + + if (v.bv_major != BPF_MAJOR_VERSION || + v.bv_minor < BPF_MINOR_VERSION) + error("Kernel BPF version out of range - recompile dhcpd!"); + + /* Set up the bpf write filter program structure. */ + p.bf_len = dhcp_bpf_wfilter_len; + p.bf_insns = dhcp_bpf_wfilter; + + if (dhcp_bpf_wfilter[7].k == 0x1fff) + dhcp_bpf_wfilter[7].k = htons(IP_MF|IP_OFFMASK); + + if (ioctl(info->wfdesc, BIOCSETWF, &p) < 0) + error("Can't install write filter program: %m"); + + if (ioctl(info->wfdesc, BIOCLOCK, NULL) < 0) + error("Cannot lock bpf"); /* * Use raw socket for unicast send. @@ -144,46 +204,6 @@ struct bpf_insn dhcp_bpf_filter[] = { int dhcp_bpf_filter_len = sizeof(dhcp_bpf_filter) / sizeof(struct bpf_insn); -/* - * Packet write filter program: - * 'ip and udp and src port bootps and dst port (bootps or bootpc)' - */ -struct bpf_insn dhcp_bpf_wfilter[] = { - BPF_STMT(BPF_LD + BPF_B + BPF_IND, 14), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (IPVERSION << 4) + 5, 0, 12), - - /* Make sure this is an IP packet... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10), - - /* Make sure it's a UDP packet... */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8), - - /* Make sure this isn't a fragment... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20), - BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0), /* patched */ - - /* Get the IP header length... */ - BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14), - - /* Make sure it's from the right port... */ - BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 68, 0, 3), - - /* Make sure it is to the right ports ... */ - BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), - - /* If we passed all the tests, ask for the whole packet. */ - BPF_STMT(BPF_RET+BPF_K, (u_int)-1), - - /* Otherwise, drop it. */ - BPF_STMT(BPF_RET+BPF_K, 0), -}; - -int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn); - void if_register_receive(struct interface_info *info) { @@ -192,7 +212,7 @@ if_register_receive(struct interface_info *info) int flag = 1, sz; /* Open a BPF device and hang it on this interface... */ - info->rfdesc = if_register_bpf(info); + info->rfdesc = if_register_bpf(info, O_RDONLY); /* Make sure the BPF version is in range... */ if (ioctl(info->rfdesc, BIOCVERSION, &v) < 0) @@ -235,16 +255,6 @@ if_register_receive(struct interface_info *info) if (ioctl(info->rfdesc, BIOCSETF, &p) < 0) error("Can't install packet filter program: %m"); - /* Set up the bpf write filter program structure. */ - p.bf_len = dhcp_bpf_wfilter_len; - p.bf_insns = dhcp_bpf_wfilter; - - if (dhcp_bpf_wfilter[7].k == 0x1fff) - dhcp_bpf_wfilter[7].k = htons(IP_MF|IP_OFFMASK); - - if (ioctl(info->rfdesc, BIOCSETWF, &p) < 0) - error("Can't install write filter program: %m"); - if (ioctl(info->rfdesc, BIOCLOCK, NULL) < 0) error("Cannot lock bpf"); } diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 1d0898d..7747d03 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -297,7 +297,7 @@ struct hash_table *new_hash_table(int); struct hash_bucket *new_hash_bucket(void); /* bpf.c */ -int if_register_bpf(struct interface_info *); +int if_register_bpf(struct interface_info *, int); void if_register_send(struct interface_info *); void if_register_receive(struct interface_info *); void send_packet(struct interface_info *, struct dhcp_packet *, size_t, -- cgit v1.1 From 981cfd3abf27bfd6fac8935eff7d28dc79ff5aed Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:03:19 +0000 Subject: Remove redundant white-spaces. --- sbin/dhclient/dhclient.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 2de8d39..fa9a49b 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1523,7 +1523,7 @@ make_discover(struct interface_info *ip, struct client_lease *lease) ip->client->config->send_options[i].len; options[i]->timeout = 0xFFFFFFFF; } - + /* send host name if not set via config file. */ char hostname[_POSIX_HOST_NAME_MAX+1]; if (!options[DHO_HOST_NAME]) { @@ -1548,7 +1548,7 @@ make_discover(struct interface_info *ip, struct client_lease *lease) int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ? ip->hw_address.hlen : sizeof(client_ident)-1; client_ident[0] = ip->hw_address.htype; - memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); + memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER]; options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident; options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1; @@ -1647,7 +1647,7 @@ make_request(struct interface_info *ip, struct client_lease * lease) ip->client->config->send_options[i].len; options[i]->timeout = 0xFFFFFFFF; } - + /* send host name if not set via config file. */ char hostname[_POSIX_HOST_NAME_MAX+1]; if (!options[DHO_HOST_NAME]) { @@ -1672,7 +1672,7 @@ make_request(struct interface_info *ip, struct client_lease * lease) int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ? ip->hw_address.hlen : sizeof(client_ident)-1; client_ident[0] = ip->hw_address.htype; - memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); + memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER]; options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident; options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1; @@ -2489,19 +2489,19 @@ check_classless_option(unsigned char *data, int len) i += 4; continue; } else if (width < 9) { - addr = (in_addr_t)(data[i] << 24); + addr = (in_addr_t)(data[i] << 24); i += 1; } else if (width < 17) { - addr = (in_addr_t)(data[i] << 24) + + addr = (in_addr_t)(data[i] << 24) + (in_addr_t)(data[i + 1] << 16); i += 2; } else if (width < 25) { - addr = (in_addr_t)(data[i] << 24) + + addr = (in_addr_t)(data[i] << 24) + (in_addr_t)(data[i + 1] << 16) + (in_addr_t)(data[i + 2] << 8); i += 3; } else if (width < 33) { - addr = (in_addr_t)(data[i] << 24) + + addr = (in_addr_t)(data[i] << 24) + (in_addr_t)(data[i + 1] << 16) + (in_addr_t)(data[i + 2] << 8) + data[i + 3]; @@ -2525,7 +2525,7 @@ check_classless_option(unsigned char *data, int len) addr &= mask; data[i - 1] = (unsigned char)( (addr >> (((32 - width)/8)*8)) & 0xFF); - } + } i += 4; } if (i > len) { -- cgit v1.1 From 696dccfa35428931d01adb8d8f67e42c801baf33 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:05:36 +0000 Subject: MFp4 @229477: The gethostname(3) function won't work in capability mode, because reading kern.hostname sysctl is not permitted there. Cache hostname early and use cached value later. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/dhclient.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index fa9a49b..0380020 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -91,6 +91,8 @@ int log_perror = 1; int privfd; int nullfd = -1; +char hostname[_POSIX_HOST_NAME_MAX + 1]; + struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } }; struct in_addr inaddr_any, inaddr_broadcast; @@ -446,6 +448,13 @@ main(int argc, char *argv[]) error("no such user: nobody"); } + /* + * Obtain hostname before entering capability mode - it won't be + * possible then, as reading kern.hostname is not permitted. + */ + if (gethostname(hostname, sizeof(hostname)) < 0) + hostname[0] = '\0'; + if (pipe(pipe_fd) == -1) error("pipe"); @@ -1525,9 +1534,8 @@ make_discover(struct interface_info *ip, struct client_lease *lease) } /* send host name if not set via config file. */ - char hostname[_POSIX_HOST_NAME_MAX+1]; if (!options[DHO_HOST_NAME]) { - if (gethostname(hostname, sizeof(hostname)) == 0) { + if (hostname[0] != '\0') { size_t len; char* posDot = strchr(hostname, '.'); if (posDot != NULL) @@ -1649,9 +1657,8 @@ make_request(struct interface_info *ip, struct client_lease * lease) } /* send host name if not set via config file. */ - char hostname[_POSIX_HOST_NAME_MAX+1]; if (!options[DHO_HOST_NAME]) { - if (gethostname(hostname, sizeof(hostname)) == 0) { + if (hostname[0] != '\0') { size_t len; char* posDot = strchr(hostname, '.'); if (posDot != NULL) -- cgit v1.1 From c7760760050ab0a6f9f5d231505dd6df281090a4 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:07:55 +0000 Subject: MFp4 @229479: - Add new request (IMSG_SEND_PACKET) that will be handled by privileged process. - Add $FreeBSD$. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/privsep.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/dhclient/privsep.h b/sbin/dhclient/privsep.h index f30284e..d464da4 100644 --- a/sbin/dhclient/privsep.h +++ b/sbin/dhclient/privsep.h @@ -14,6 +14,8 @@ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ */ #include @@ -33,7 +35,8 @@ enum imsg_code { IMSG_SCRIPT_INIT, IMSG_SCRIPT_WRITE_PARAMS, IMSG_SCRIPT_GO, - IMSG_SCRIPT_GO_RET + IMSG_SCRIPT_GO_RET, + IMSG_SEND_PACKET }; struct imsg_hdr { -- cgit v1.1 From f92ee0c897d1cd0cdbb0c8e2cb5f63869f1a0946 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:09:02 +0000 Subject: MFp4 @229480: Shutdown write direction of the routing socket. We only need to read from it. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/dhclient.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 0380020..43e0c16 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -476,6 +476,8 @@ main(int argc, char *argv[]) if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1) add_protocol("AF_ROUTE", routefd, routehandler, ifi); + if (shutdown(routefd, SHUT_WR) < 0) + error("can't shutdown route socket: %m"); /* set up the interface */ discover_interfaces(ifi); -- cgit v1.1 From d5113e2f2801e517733035a8d22216b334385537 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:12:54 +0000 Subject: MFp4 @229481: Currently it was allowed to send any UDP packets from unprivileged process and possibly any packets because /dev/bpf was open for writing. Move sending packets to privileged process. Unprivileged process has no longer access to not connected UDP socket and has only access to /dev/bpf in read-only mode. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/bpf.c | 53 ++++++++++++++++++++++++++++++++++++++++++++---- sbin/dhclient/dhclient.c | 27 +++++++++++++++--------- sbin/dhclient/dhcpd.h | 8 +++++--- sbin/dhclient/privsep.c | 5 ++++- 4 files changed, 75 insertions(+), 18 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index c16e477..8964279 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include "dhcpd.h" +#include "privsep.h" #include #include @@ -260,23 +261,67 @@ if_register_receive(struct interface_info *info) } void -send_packet(struct interface_info *interface, struct dhcp_packet *raw, - size_t len, struct in_addr from, struct in_addr to) +send_packet_unpriv(int privfd, struct dhcp_packet *raw, size_t len, + struct in_addr from, struct in_addr to) +{ + struct imsg_hdr hdr; + struct buf *buf; + int errs; + + hdr.code = IMSG_SEND_PACKET; + hdr.len = sizeof(hdr) + + sizeof(size_t) + len + + sizeof(from) + sizeof(to); + + if ((buf = buf_open(hdr.len)) == NULL) + error("buf_open: %m"); + + errs = 0; + errs += buf_add(buf, &hdr, sizeof(hdr)); + errs += buf_add(buf, &len, sizeof(len)); + errs += buf_add(buf, raw, len); + errs += buf_add(buf, &from, sizeof(from)); + errs += buf_add(buf, &to, sizeof(to)); + if (errs) + error("buf_add: %m"); + + if (buf_close(privfd, buf) == -1) + error("buf_close: %m"); +} + +void +send_packet_priv(struct interface_info *interface, struct imsg_hdr *hdr, int fd) { unsigned char buf[256]; struct iovec iov[2]; struct msghdr msg; + struct dhcp_packet raw; + size_t len; + struct in_addr from, to; int result, bufp = 0; + if (hdr->len < sizeof(*hdr) + sizeof(size_t)) + error("corrupted message received"); + buf_read(fd, &len, sizeof(len)); + if (hdr->len != sizeof(*hdr) + sizeof(size_t) + len + + sizeof(from) + sizeof(to)) { + error("corrupted message received"); + } + if (len > sizeof(raw)) + error("corrupted message received"); + buf_read(fd, &raw, len); + buf_read(fd, &from, sizeof(from)); + buf_read(fd, &to, sizeof(to)); + /* Assemble the headers... */ if (to.s_addr == INADDR_BROADCAST) assemble_hw_header(interface, buf, &bufp); assemble_udp_ip_header(buf, &bufp, from.s_addr, to.s_addr, - htons(REMOTE_PORT), (unsigned char *)raw, len); + htons(REMOTE_PORT), (unsigned char *)&raw, len); iov[0].iov_base = buf; iov[0].iov_len = bufp; - iov[1].iov_base = raw; + iov[1].iov_base = &raw; iov[1].iov_len = len; /* Fire it off */ diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 43e0c16..8dc9736 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -455,11 +455,19 @@ main(int argc, char *argv[]) if (gethostname(hostname, sizeof(hostname)) < 0) hostname[0] = '\0'; + /* set up the interface */ + discover_interfaces(ifi); + if (pipe(pipe_fd) == -1) error("pipe"); fork_privchld(pipe_fd[0], pipe_fd[1]); + close(ifi->ufdesc); + ifi->ufdesc = -1; + close(ifi->wfdesc); + ifi->wfdesc = -1; + close(pipe_fd[0]); privfd = pipe_fd[1]; @@ -479,9 +487,6 @@ main(int argc, char *argv[]) if (shutdown(routefd, SHUT_WR) < 0) error("can't shutdown route socket: %m"); - /* set up the interface */ - discover_interfaces(ifi); - if (chroot(_PATH_VAREMPTY) == -1) error("chroot"); if (chdir("/") == -1) @@ -1236,8 +1241,8 @@ again: (int)ip->client->interval); /* Send out a packet. */ - send_packet(ip, &ip->client->packet, ip->client->packet_length, - inaddr_any, inaddr_broadcast); + send_packet_unpriv(privfd, &ip->client->packet, + ip->client->packet_length, inaddr_any, inaddr_broadcast); add_timeout(cur_time + ip->client->interval, send_discover, ip); } @@ -1461,8 +1466,8 @@ cancel: REMOTE_PORT); /* Send out a packet. */ - send_packet(ip, &ip->client->packet, ip->client->packet_length, - from, to); + send_packet_unpriv(privfd, &ip->client->packet, + ip->client->packet_length, from, to); add_timeout(cur_time + ip->client->interval, send_request, ip); } @@ -1476,8 +1481,8 @@ send_decline(void *ipp) inet_ntoa(inaddr_broadcast), REMOTE_PORT); /* Send out a packet. */ - send_packet(ip, &ip->client->packet, ip->client->packet_length, - inaddr_any, inaddr_broadcast); + send_packet_unpriv(privfd, &ip->client->packet, + ip->client->packet_length, inaddr_any, inaddr_broadcast); } void @@ -2698,6 +2703,8 @@ fork_privchld(int fd, int fd2) dup2(nullfd, STDERR_FILENO); close(nullfd); close(fd2); + close(ifi->rfdesc); + ifi->rfdesc = -1; for (;;) { pfd[0].fd = fd; @@ -2709,6 +2716,6 @@ fork_privchld(int fd, int fd2) if (nfds == 0 || !(pfd[0].revents & POLLIN)) continue; - dispatch_imsg(fd); + dispatch_imsg(ifi, fd); } } diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 7747d03..479753e 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -300,8 +300,10 @@ struct hash_bucket *new_hash_bucket(void); int if_register_bpf(struct interface_info *, int); void if_register_send(struct interface_info *); void if_register_receive(struct interface_info *); -void send_packet(struct interface_info *, struct dhcp_packet *, size_t, - struct in_addr, struct in_addr); +void send_packet_unpriv(int, struct dhcp_packet *, size_t, struct in_addr, + struct in_addr); +struct imsg_hdr; +void send_packet_priv(struct interface_info *, struct imsg_hdr *, int); ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *); @@ -435,4 +437,4 @@ struct buf *buf_open(size_t); int buf_add(struct buf *, void *, size_t); int buf_close(int, struct buf *); ssize_t buf_read(int, void *, size_t); -void dispatch_imsg(int); +void dispatch_imsg(struct interface_info *, int); diff --git a/sbin/dhclient/privsep.c b/sbin/dhclient/privsep.c index b42572f..a0521a6 100644 --- a/sbin/dhclient/privsep.c +++ b/sbin/dhclient/privsep.c @@ -101,7 +101,7 @@ buf_read(int sock, void *buf, size_t nbytes) } void -dispatch_imsg(int fd) +dispatch_imsg(struct interface_info *ifi, int fd) { struct imsg_hdr hdr; char *medium, *reason, *filename, @@ -232,6 +232,9 @@ dispatch_imsg(int fd) if (buf_close(fd, buf) == -1) error("buf_close: %m"); break; + case IMSG_SEND_PACKET: + send_packet_priv(ifi, &hdr, fd); + break; default: error("received unknown message, code %d", hdr.code); } -- cgit v1.1 From 11d993e6946901df0579895d876a7aa1d4cc9b98 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:16:02 +0000 Subject: MFp4 @229482: - Limit bpf descriptor in unprivileged process to CAP_POLL_EVENT, CAP_READ and allow for SIOCGIFFLAGS, SIOCGIFMEDIA ioctls. - While here limit bpf descriptor in privileged process to only CAP_WRITE. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/bpf.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sbin') diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index 8964279..f435028 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include "dhcpd.h" #include "privsep.h" +#include #include #include @@ -159,6 +160,9 @@ if_register_send(struct interface_info *info) if (ioctl(info->wfdesc, BIOCLOCK, NULL) < 0) error("Cannot lock bpf"); + if (cap_rights_limit(info->wfdesc, CAP_WRITE) < 0 && errno != ENOSYS) + error("Can't limit bpf descriptor: %m"); + /* * Use raw socket for unicast send. */ @@ -208,6 +212,7 @@ int dhcp_bpf_filter_len = sizeof(dhcp_bpf_filter) / sizeof(struct bpf_insn); void if_register_receive(struct interface_info *info) { + static const unsigned long cmds[2] = { SIOCGIFFLAGS, SIOCGIFMEDIA }; struct bpf_version v; struct bpf_program p; int flag = 1, sz; @@ -258,6 +263,13 @@ if_register_receive(struct interface_info *info) if (ioctl(info->rfdesc, BIOCLOCK, NULL) < 0) error("Cannot lock bpf"); + + if (cap_rights_limit(info->rfdesc, + CAP_IOCTL | CAP_POLL_EVENT | CAP_READ) < 0 && errno != ENOSYS) { + error("Can't limit bpf descriptor: %m"); + } + if (cap_ioctls_limit(info->rfdesc, cmds, 2) < 0 && errno != ENOSYS) + error("Can't limit ioctls for bpf descriptor: %m"); } void -- cgit v1.1 From 6526d2e66afdac969c9cf66a338ca6aba259bc9f Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:17:29 +0000 Subject: MFp4 @229483: Limit communication pipe with privileged process to CAP_READ and CAP_WRITE. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/dhclient.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 8dc9736..ad0d02e 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$"); #include "dhcpd.h" #include "privsep.h" +#include + #include #ifndef _PATH_VAREMPTY @@ -470,6 +472,10 @@ main(int argc, char *argv[]) close(pipe_fd[0]); privfd = pipe_fd[1]; + if (cap_rights_limit(privfd, CAP_READ | CAP_WRITE) < 0 && + errno != ENOSYS) { + error("can't limit private descriptor: %m"); + } if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1) error("can't open and lock %s: %m", path_dhclient_db); -- cgit v1.1 From 157b58cb300b2659ec65eee45aef27bfdcda91b6 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:18:40 +0000 Subject: MFp4 @229484: Limit routing socket so only poll(2) and read(2) are allowed (CAP_POLL_EVENT and CAP_READ). This prevents unprivileged process from adding, removing or modifying system routes. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/dhclient.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index ad0d02e..34ff853 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -492,6 +492,10 @@ main(int argc, char *argv[]) add_protocol("AF_ROUTE", routefd, routehandler, ifi); if (shutdown(routefd, SHUT_WR) < 0) error("can't shutdown route socket: %m"); + if (cap_rights_limit(routefd, CAP_POLL_EVENT | CAP_READ) < 0 && + errno != ENOSYS) { + error("can't limit route socket: %m"); + } if (chroot(_PATH_VAREMPTY) == -1) error("chroot"); -- cgit v1.1 From 745563514be1c4a53986276e837d351f916f2788 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:19:43 +0000 Subject: MFp4 @229485: Only allow to overwrite lease file. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/dhclient.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 34ff853..ead20b4 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1842,6 +1842,11 @@ rewrite_client_leases(void) leaseFile = fopen(path_dhclient_db, "w"); if (!leaseFile) error("can't create %s: %m", path_dhclient_db); + if (cap_rights_limit(fileno(leaseFile), CAP_FSTAT | CAP_FSYNC | + CAP_FTRUNCATE | CAP_SEEK | CAP_WRITE) < 0 && + errno != ENOSYS) { + error("can't limit lease descriptor: %m"); + } } else { fflush(leaseFile); rewind(leaseFile); -- cgit v1.1 From 671bf2da4323dd91bdb6ab81d384220e0af44c3c Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:21:11 +0000 Subject: MFp4 @229486: Once PID is written to the pidfile, revoke all capability rights. We just want to keep the pidfile open. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/dhclient.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index ead20b4..b695f6a 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -2363,8 +2363,13 @@ go_daemon(void) if (daemon(1, 0) == -1) error("daemon"); - if (pidfile != NULL) + if (pidfile != NULL) { pidfile_write(pidfile); + if (cap_rights_limit(pidfile_fileno(pidfile), CAP_NONE) < 0 && + errno != ENOSYS) { + error("can't limit pidfile descriptor: %m"); + } + } /* we are chrooted, daemon(3) fails to open /dev/null */ if (nullfd != -1) { -- cgit v1.1 From b93b6961b07bfcedd1fb84284a72573c66fe8b36 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:22:29 +0000 Subject: MFp4 @229487: Revoke all capability rights from STDIN and allow only for write to STDOUT and STDERR. All those descriptors are redirected to /dev/null. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/dhclient.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index b695f6a..2305d97 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -2379,6 +2379,13 @@ go_daemon(void) close(nullfd); nullfd = -1; } + + if (cap_rights_limit(STDIN_FILENO, CAP_NONE) < 0 && errno != ENOSYS) + error("can't limit stdin: %m"); + if (cap_rights_limit(STDOUT_FILENO, CAP_WRITE) < 0 && errno != ENOSYS) + error("can't limit stdout: %m"); + if (cap_rights_limit(STDERR_FILENO, CAP_WRITE) < 0 && errno != ENOSYS) + error("can't limit stderr: %m"); } int -- cgit v1.1 From 85ce2c58ff0686d38588441ec3e73ec11e901a71 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 22:23:25 +0000 Subject: MFp4 @229488: Sandbox unprivileged process using capability mode. Reviewed by: brooks Sponsored by: The FreeBSD Foundation --- sbin/dhclient/dhclient.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 2305d97..cd4a41b 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -511,6 +511,9 @@ main(int argc, char *argv[]) setproctitle("%s", ifi->name); + if (cap_enter() < 0 && errno != ENOSYS) + error("can't enter capability mode: %m"); + if (immediate_daemon) go_daemon(); -- cgit v1.1 From 4a1b5780c0e7276bbd15a6222f0453ac75a6e7d5 Mon Sep 17 00:00:00 2001 From: jimharris Date: Thu, 4 Jul 2013 00:26:24 +0000 Subject: Fix printf argument mismatch reported by gcc on i386. Reported by: kargl --- sbin/nvmecontrol/firmware.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/firmware.c b/sbin/nvmecontrol/firmware.c index f82b886..4678301 100644 --- a/sbin/nvmecontrol/firmware.c +++ b/sbin/nvmecontrol/firmware.c @@ -82,7 +82,7 @@ read_image_file(char *path, void **buf, ssize_t *size) exit(EX_IOERR); } if ((*buf = malloc(sb.st_size)) == NULL) { - fprintf(stderr, "Unable to malloc %zd bytes.\n", + fprintf(stderr, "Unable to malloc %jd bytes.\n", sb.st_size); close(fd); exit(EX_IOERR); @@ -95,7 +95,7 @@ read_image_file(char *path, void **buf, ssize_t *size) } if (*size != sb.st_size) { fprintf(stderr, "Error reading '%s', " - "read %zd bytes, requested %zd bytes\n", + "read %zd bytes, requested %jd bytes\n", path, *size, sb.st_size); close(fd); exit(EX_IOERR); -- cgit v1.1 From e71a9f5bfa78184fcc3776a5603940f09cf23e66 Mon Sep 17 00:00:00 2001 From: pjd Date: Thu, 4 Jul 2013 12:27:10 +0000 Subject: Fix dhclient for interfaces that are down. The discover_interfaces() function that looks for interface skips interfaces that are not UP. We need to call dhclient-script PREINIT before we call discover_interfaces(), so the script has a chance to bring the interface UP. Reported by: alfred --- sbin/dhclient/dhclient.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index cd4a41b..c8f05b5 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -457,6 +457,11 @@ main(int argc, char *argv[]) if (gethostname(hostname, sizeof(hostname)) < 0) hostname[0] = '\0'; + priv_script_init("PREINIT", NULL); + if (ifi->client->alias) + priv_script_write_params("alias_", ifi->client->alias); + priv_script_go(); + /* set up the interface */ discover_interfaces(ifi); @@ -483,11 +488,6 @@ main(int argc, char *argv[]) rewrite_client_leases(); close(fd); - priv_script_init("PREINIT", NULL); - if (ifi->client->alias) - priv_script_write_params("alias_", ifi->client->alias); - priv_script_go(); - if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1) add_protocol("AF_ROUTE", routefd, routehandler, ifi); if (shutdown(routefd, SHUT_WR) < 0) -- cgit v1.1 From 801a6742bc5d69b3293dc04787d4cd932512f6de Mon Sep 17 00:00:00 2001 From: asomers Date: Mon, 8 Jul 2013 21:10:30 +0000 Subject: Correct the printf format specifier for total_events. Add __printflike argument checking for devdlog(). Reported by: pjd Approved by: gibbs (co-mentor) --- sbin/devd/devd.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index 0f11a83..447ab87 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -124,7 +124,8 @@ static volatile sig_atomic_t romeo_must_die = 0; static const char *configfile = CF; -static void devdlog(int priority, const char* message, ...); +static void devdlog(int priority, const char* message, ...) + __printflike(2, 3); static void event_loop(void); static void usage(void); @@ -969,7 +970,7 @@ event_loop(void) } rv = select(max_fd, &fds, NULL, NULL, &tv); if (got_siginfo) { - devdlog(LOG_INFO, "Events received so far=%ld\n", + devdlog(LOG_INFO, "Events received so far=%u\n", total_events); got_siginfo = 0; } -- cgit v1.1 From d7f19ee1e272f366d22ef2853f239f4cf7f800c5 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Tue, 9 Jul 2013 01:31:36 +0000 Subject: Document the "gssname" and "allgssname" mount options added by the host-based initiator credential patches. This is a content change. --- sbin/mount_nfs/mount_nfs.8 | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/mount_nfs/mount_nfs.8 b/sbin/mount_nfs/mount_nfs.8 index 26ed091..216b248 100644 --- a/sbin/mount_nfs/mount_nfs.8 +++ b/sbin/mount_nfs/mount_nfs.8 @@ -28,7 +28,7 @@ .\" @(#)mount_nfs.8 8.3 (Berkeley) 3/29/95 .\" $FreeBSD$ .\" -.Dd December 9, 2012 +.Dd July 8, 2013 .Dt MOUNT_NFS 8 .Os .Sh NAME @@ -118,6 +118,13 @@ for regular files, and 30 -> 60 seconds for directories. The algorithm to calculate the timeout is based on the age of the file. The older the file, the longer the cache is considered valid, subject to the limits above. +.It Cm allgssname +This option can be used along with +.Fl o Cm gssname +to specify that all operations should use the host-based initiator +credential. +This may be used for clients that run system daemons that need to +access files on the NFSv4 mounted volume. .It Cm bg If an initial attempt to contact the server fails, fork off a child to keep trying the mount in the background. @@ -138,6 +145,23 @@ short. .It Cm fg Same as not specifying .Cm bg . +.It Cm gssname Ns = Ns Aq Ar service-principal-name +This option can be used with the KerberosV security flavors for NFSv4 mounts +to specify the +.Dq "service-principal-name" +of a host-based entry in the default +keytab file that is used for system operations. +It allows the mount to be performed by +.Dq "root" +and avoids problems with +cached credentials for the system operations expiring. +The +.Dq "service-prinicpal-name" +should be specified without instance or domain and is typically +.Dq "host" , +.Dq "nfs" +or +.Dq "root" . .It Cm hard Same as not specifying .Cm soft . -- cgit v1.1 From 7ed5b42834802b6170f1ef289f5ee704ff41c093 Mon Sep 17 00:00:00 2001 From: jimharris Date: Tue, 9 Jul 2013 21:14:15 +0000 Subject: Incorporate feedback from bde@ based on r252672 changes: * Use 0/1 instead of sysexits. Man pages are confusing on this topic, but 0/1 is sufficient for nvmecontrol. * Use err function family where possible instead of fprintf/exit. * Fix some typing errors. * Clean up some error message inconsistencies. Sponsored by: Intel Submitted by: bde (parts of firmware.c changes) MFC after: 3 days --- sbin/nvmecontrol/devlist.c | 25 +++---- sbin/nvmecontrol/firmware.c | 152 +++++++++++++++++------------------------ sbin/nvmecontrol/identify.c | 22 +++--- sbin/nvmecontrol/logpage.c | 56 ++++++--------- sbin/nvmecontrol/nvmecontrol.c | 54 ++++++--------- sbin/nvmecontrol/perftest.c | 15 ++-- sbin/nvmecontrol/reset.c | 14 ++-- 7 files changed, 134 insertions(+), 204 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/devlist.c b/sbin/nvmecontrol/devlist.c index 8c99c99..849b364 100644 --- a/sbin/nvmecontrol/devlist.c +++ b/sbin/nvmecontrol/devlist.c @@ -29,13 +29,12 @@ __FBSDID("$FreeBSD$"); #include -#include +#include #include #include #include #include #include -#include #include #include "nvmecontrol.h" @@ -45,7 +44,7 @@ devlist_usage(void) { fprintf(stderr, "usage:\n"); fprintf(stderr, DEVLIST_USAGE); - exit(EX_USAGE); + exit(1); } static inline uint32_t @@ -62,9 +61,7 @@ devlist(int argc, char *argv[]) struct nvme_namespace_data nsdata; char name[64]; uint32_t i; - int ch, ctrlr, exit_code, fd, found; - - exit_code = EX_OK; + int ch, ctrlr, fd, found, ret; while ((ch = getopt(argc, argv, "")) != -1) { switch ((char)ch) { @@ -80,14 +77,14 @@ devlist(int argc, char *argv[]) ctrlr++; sprintf(name, "%s%d", NVME_CTRLR_PREFIX, ctrlr); - exit_code = open_dev(name, &fd, 0, 0); + ret = open_dev(name, &fd, 0, 0); - if (exit_code == EX_NOINPUT) - break; - else if (exit_code == EX_NOPERM) { - printf("Could not open /dev/%s, errno = %d (%s)\n", - name, errno, strerror(errno)); - continue; + if (ret != 0) { + if (fd < 0) { + warnx("could not open /dev/%s\n", name); + continue; + } else + break; } found++; @@ -111,5 +108,5 @@ devlist(int argc, char *argv[]) if (found == 0) printf("No NVMe controllers found.\n"); - exit(EX_OK); + exit(1); } diff --git a/sbin/nvmecontrol/firmware.c b/sbin/nvmecontrol/firmware.c index 4678301..c297f90 100644 --- a/sbin/nvmecontrol/firmware.c +++ b/sbin/nvmecontrol/firmware.c @@ -36,14 +36,14 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include +#include #include #include #include #include #include -#include #include #include "nvmecontrol.h" @@ -64,60 +64,58 @@ slot_has_valid_firmware(int fd, int slot) } static void -read_image_file(char *path, void **buf, ssize_t *size) +read_image_file(char *path, void **buf, int32_t *size) { struct stat sb; + int32_t filesize; int fd; *size = 0; *buf = NULL; - if ((fd = open(path, O_RDONLY)) < 0) { - fprintf(stderr, "Unable to open '%s'.\n", path); - exit(EX_IOERR); - } - if (fstat(fd, &sb) < 0) { - fprintf(stderr, "Unable to stat '%s'.\n", path); - close(fd); - exit(EX_IOERR); - } - if ((*buf = malloc(sb.st_size)) == NULL) { - fprintf(stderr, "Unable to malloc %jd bytes.\n", - sb.st_size); - close(fd); - exit(EX_IOERR); - } - if ((*size = read(fd, *buf, sb.st_size)) < 0) { - fprintf(stderr, "Error reading '%s', errno=%d (%s)\n", - path, errno, strerror(errno)); - close(fd); - exit(EX_IOERR); - } - if (*size != sb.st_size) { - fprintf(stderr, "Error reading '%s', " - "read %zd bytes, requested %jd bytes\n", - path, *size, sb.st_size); - close(fd); - exit(EX_IOERR); - } + if ((fd = open(path, O_RDONLY)) < 0) + err(1, "unable to open '%s'", path); + if (fstat(fd, &sb) < 0) + err(1, "unable to stat '%s'", path); + + /* + * The NVMe spec does not explicitly state a maximum firmware image + * size, although one can be inferred from the dword size limitation + * for the size and offset fields in the Firmware Image Download + * command. + * + * Technically, the max is UINT32_MAX * sizeof(uint32_t), since the + * size and offsets are specified in terms of dwords (not bytes), but + * realistically INT32_MAX is sufficient here and simplifies matters + * a bit. + */ + if (sb.st_size > INT32_MAX) + errx(1, "size of file '%s' is too large (%jd bytes)", + path, (intmax_t)sb.st_size); + filesize = (int32_t)sb.st_size; + if ((*buf = malloc(filesize)) == NULL) + errx(1, "unable to malloc %zd bytes", filesize); + if ((*size = read(fd, *buf, filesize)) < 0) + err(1, "error reading '%s'", path); + /* XXX assuming no short reads */ + if (*size != filesize) + errx(1, + "error reading '%s' (read %d bytes, requested %d bytes)", + path, *size, filesize); } static void -update_firmware(int fd, uint8_t *payload, uint32_t payload_size) +update_firmware(int fd, uint8_t *payload, int32_t payload_size) { struct nvme_pt_command pt; - size_t size; + int32_t off, resid, size; void *chunk; - uint32_t off, resid; - int exit_code = EX_OK; off = 0; resid = payload_size; - if ((chunk = malloc((size_t)NVME_MAX_XFER_SIZE)) == NULL) { - printf("Unable to malloc %d bytes.\n", NVME_MAX_XFER_SIZE); - exit(EX_IOERR); - } + if ((chunk = malloc(NVME_MAX_XFER_SIZE)) == NULL) + errx(1, "unable to malloc %d bytes", NVME_MAX_XFER_SIZE); while (resid > 0) { size = (resid >= NVME_MAX_XFER_SIZE) ? @@ -132,26 +130,15 @@ update_firmware(int fd, uint8_t *payload, uint32_t payload_size) pt.len = size; pt.is_read = 0; - if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { - printf("Firmware image download request failed. " - "errno=%d (%s)\n", - errno, strerror(errno)); - exit_code = EX_IOERR; - break; - } + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "firmware download request failed"); - if (nvme_completion_is_error(&pt.cpl)) { - printf("Passthrough command returned error.\n"); - exit_code = EX_IOERR; - break; - } + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "firmware download request returned error"); resid -= size; off += size; } - - if (exit_code != EX_OK) - exit(exit_code); } static void @@ -164,16 +151,11 @@ activate_firmware(int fd, int slot, int activate_action) pt.cmd.cdw10 = (activate_action << 3) | slot; pt.is_read = 0; - if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { - printf("Firmware activate request failed. errno=%d (%s)\n", - errno, strerror(errno)); - exit(EX_IOERR); - } + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "firmware activate request failed"); - if (nvme_completion_is_error(&pt.cpl)) { - printf("Passthrough command returned error.\n"); - exit(EX_IOERR); - } + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "firmware activate request returned error"); } static void @@ -181,7 +163,7 @@ firmware_usage(void) { fprintf(stderr, "usage:\n"); fprintf(stderr, FIRMWARE_USAGE); - exit(EX_USAGE); + exit(1); } void @@ -192,7 +174,7 @@ firmware(int argc, char *argv[]) char ch, *p, *image = NULL; char *controller = NULL, prompt[64]; void *buf = NULL; - ssize_t size; + int32_t size = 0; struct nvme_controller_data cdata; a_flag = s_flag = f_flag = false; @@ -252,34 +234,24 @@ firmware(int argc, char *argv[]) open_dev(controller, &fd, 1, 1); read_controller_data(fd, &cdata); - if (cdata.oacs.firmware == 0) { - fprintf(stderr, - "Controller does not support firmware " - "activate/download.\n"); - exit(EX_IOERR); - } + if (cdata.oacs.firmware == 0) + errx(1, + "controller does not support firmware activate/download"); - if (f_flag && slot == 1 && cdata.frmw.slot1_ro) { - fprintf(stderr, "Slot %d is marked as read only.\n", slot); - exit(EX_IOERR); - } + if (f_flag && slot == 1 && cdata.frmw.slot1_ro) + errx(1, "slot %d is marked as read only", slot); - if (slot > cdata.frmw.num_slots) { - fprintf(stderr, - "Slot %d was specified but controller only " - "supports %d firmware slots.\n", + if (slot > cdata.frmw.num_slots) + errx(1, + "slot %d specified but controller only supports %d slots", slot, cdata.frmw.num_slots); - exit(EX_IOERR); - } - if (!slot_has_valid_firmware(fd, slot)) { - fprintf(stderr, - "Slot %d does not contain valid firmware.\n" - "Try 'nvmecontrol logpage -p 3 %s' to get a list " - "of available firmware images.\n", + if (!slot_has_valid_firmware(fd, slot)) + errx(1, + "slot %d does not contain valid firmware,\n" + "try 'nvmecontrol logpage -p 3 %s' to get a list " + "of available images\n", slot, controller); - exit(EX_IOERR); - } if (f_flag && a_flag) printf("You are about to download and activate " @@ -305,7 +277,7 @@ firmware(int argc, char *argv[]) if (strncasecmp(prompt, "yes", 3) == 0) break; if (strncasecmp(prompt, "no", 2) == 0) - exit(EX_OK); + exit(1); printf("Please answer \"yes\" or \"no\". "); } @@ -331,5 +303,5 @@ firmware(int argc, char *argv[]) } close(fd); - exit(EX_OK); + exit(0); } diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index afe5ac0..1fe2a34 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -30,13 +30,13 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include #include -#include #include #include "nvmecontrol.h" @@ -139,7 +139,7 @@ identify_usage(void) { fprintf(stderr, "usage:\n"); fprintf(stderr, IDENTIFY_USAGE); - exit(EX_USAGE); + exit(1); } static void @@ -177,16 +177,16 @@ identify_ctrlr(int argc, char *argv[]) hexlength = offsetof(struct nvme_controller_data, reserved5); print_hex(&cdata, hexlength); - exit(EX_OK); + exit(0); } if (verboseflag == 1) { - printf("-v not currently supported without -x.\n"); + fprintf(stderr, "-v not currently supported without -x\n"); identify_usage(); } print_controller(&cdata); - exit(EX_OK); + exit(0); } static void @@ -231,10 +231,8 @@ identify_ns(int argc, char *argv[]) nsloc = strnstr(argv[optind], NVME_NS_PREFIX, 10); if (nsloc != NULL) nsid = strtol(nsloc + 2, NULL, 10); - if (nsloc == NULL || (nsid == 0 && errno != 0)) { - printf("Invalid namespace ID %s.\n", argv[optind]); - exit(EX_IOERR); - } + if (nsloc == NULL || (nsid == 0 && errno != 0)) + errx(1, "invalid namespace ID '%s'", argv[optind]); /* * We send IDENTIFY commands to the controller, not the namespace, @@ -253,16 +251,16 @@ identify_ns(int argc, char *argv[]) hexlength = offsetof(struct nvme_namespace_data, reserved6); print_hex(&nsdata, hexlength); - exit(EX_OK); + exit(0); } if (verboseflag == 1) { - printf("-v not currently supported without -x.\n"); + fprintf(stderr, "-v not currently supported without -x\n"); identify_usage(); } print_namespace(&nsdata); - exit(EX_OK); + exit(0); } void diff --git a/sbin/nvmecontrol/logpage.c b/sbin/nvmecontrol/logpage.c index dbc0e6b..a26ce04 100644 --- a/sbin/nvmecontrol/logpage.c +++ b/sbin/nvmecontrol/logpage.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -41,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include "nvmecontrol.h" @@ -52,14 +52,13 @@ __FBSDID("$FreeBSD$"); typedef void (*print_fn_t)(void *buf, uint32_t size); static void * -get_log_buffer(size_t size) +get_log_buffer(uint32_t size) { void *buf; - if ((buf = malloc(size)) == NULL) { - fprintf(stderr, "Unable to malloc %zd bytes\n", size); - exit(EX_IOERR); - } + if ((buf = malloc(size)) == NULL) + errx(1, "unable to malloc %u bytes", size); + memset(buf, 0, size); return (buf); } @@ -79,16 +78,11 @@ read_logpage(int fd, uint8_t log_page, int nsid, void *payload, pt.len = payload_size; pt.is_read = 1; - if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { - printf("Get log page request failed. errno=%d (%s)\n", - errno, strerror(errno)); - exit(EX_IOERR); - } + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "get log page request failed"); - if (nvme_completion_is_error(&pt.cpl)) { - printf("Passthrough command returned error.\n"); - exit(EX_IOERR); - } + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "get log page request returned error"); } static void @@ -242,7 +236,7 @@ logpage_usage(void) { fprintf(stderr, "usage:\n"); fprintf(stderr, LOGPAGE_USAGE); - exit(EX_USAGE); + exit(1); } void @@ -254,7 +248,7 @@ logpage(int argc, char *argv[]) int allow_ns = false; char ch, *p, *nsloc = NULL; char *cname = NULL; - size_t size; + uint32_t size; void *buf; struct logpage_function *f; struct nvme_controller_data cdata; @@ -313,28 +307,20 @@ logpage(int argc, char *argv[]) /* If a namespace id was specified, validate it's use */ if (strstr(argv[optind], NVME_NS_PREFIX) != NULL) { if (!allow_ns) { - if (log_page != NVME_LOG_HEALTH_INFORMATION) { - fprintf(stderr, - "Namespace ID not valid for log page %d.\n", + if (log_page != NVME_LOG_HEALTH_INFORMATION) + errx(1, + "log page %d valid only at controller level", log_page); - } else if (cdata.lpa.ns_smart == 0) { - fprintf(stderr, - "Controller does not support per " - "namespace SMART/Health information.\n"); - } - close(fd); - exit(EX_IOERR); + else if (cdata.lpa.ns_smart == 0) + errx(1, + "controller does not support per " + "namespace smart/health information"); } nsloc = strnstr(argv[optind], NVME_NS_PREFIX, 10); if (nsloc != NULL) nsid = strtol(nsloc + 2, NULL, 10); - if (nsloc == NULL || (nsid == 0 && errno != 0)) { - fprintf(stderr, - "Invalid namespace ID %s.\n", - argv[optind]); - close(fd); - exit(EX_IOERR); - } + if (nsloc == NULL || (nsid == 0 && errno != 0)) + errx(1, "invalid namespace id '%s'", argv[optind]); /* * User is asking for per namespace log page information @@ -384,5 +370,5 @@ logpage(int argc, char *argv[]) print_fn(buf, size); close(fd); - exit(EX_OK); + exit(0); } diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index c7452a1..c566bb3 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -32,14 +32,13 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include #include #include #include #include -#include #include #include "nvmecontrol.h" @@ -71,7 +70,7 @@ usage(void) fprintf(stderr, "%s", f->usage); f++; } - exit(EX_USAGE); + exit(1); } static void @@ -134,16 +133,11 @@ read_controller_data(int fd, struct nvme_controller_data *cdata) pt.len = sizeof(*cdata); pt.is_read = 1; - if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { - printf("Identify request failed. errno=%d (%s)\n", - errno, strerror(errno)); - exit(EX_IOERR); - } + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "identify request failed"); - if (nvme_completion_is_error(&pt.cpl)) { - printf("Passthrough command returned error.\n"); - exit(EX_IOERR); - } + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "identify request returned error"); } void @@ -158,16 +152,11 @@ read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata) pt.len = sizeof(*nsdata); pt.is_read = 1; - if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) { - printf("Identify request failed. errno=%d (%s)\n", - errno, strerror(errno)); - exit(EX_IOERR); - } + if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) + err(1, "identify request failed"); - if (nvme_completion_is_error(&pt.cpl)) { - printf("Passthrough command returned error.\n"); - exit(EX_IOERR); - } + if (nvme_completion_is_error(&pt.cpl)) + errx(1, "identify request returned error"); } int @@ -178,38 +167,35 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) if (!strnstr(str, NVME_CTRLR_PREFIX, strlen(NVME_CTRLR_PREFIX))) { if (show_error) - fprintf(stderr, - "Controller/namespace IDs must begin with '%s'.\n", + warnx("controller/namespace ids must begin with '%s'", NVME_CTRLR_PREFIX); if (exit_on_error) - exit(EX_USAGE); + exit(1); else - return (EX_USAGE); + return (1); } snprintf(full_path, sizeof(full_path), "/dev/%s", str); if (stat(full_path, &devstat) != 0) { if (show_error) - fprintf(stderr, "Could not stat %s. errno=%d (%s)\n", - full_path, errno, strerror(errno)); + warn("could not stat %s", full_path); if (exit_on_error) - exit(EX_NOINPUT); + exit(1); else - return (EX_NOINPUT); + return (1); } *fd = open(full_path, O_RDWR); if (*fd < 0) { if (show_error) - fprintf(stderr, "Could not open %s. errno=%d (%s)\n", - full_path, errno, strerror(errno)); + warn("could not open %s", full_path); if (exit_on_error) - exit(EX_NOPERM); + exit(1); else - return (EX_NOPERM); + return (1); } - return (EX_OK); + return (0); } int diff --git a/sbin/nvmecontrol/perftest.c b/sbin/nvmecontrol/perftest.c index c69da79..a7339bf 100644 --- a/sbin/nvmecontrol/perftest.c +++ b/sbin/nvmecontrol/perftest.c @@ -31,14 +31,13 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include #include #include #include #include -#include #include #include "nvmecontrol.h" @@ -72,7 +71,7 @@ perftest_usage(void) { fprintf(stderr, "usage:\n"); fprintf(stderr, PERFTEST_USAGE); - exit(EX_USAGE); + exit(1); } void @@ -168,14 +167,10 @@ perftest(int argc, char *argv[]) perftest_usage(); open_dev(argv[optind], &fd, 1, 1); - if (ioctl(fd, ioctl_cmd, &io_test) < 0) { - fprintf(stderr, "NVME_IO_TEST failed. errno=%d (%s)\n", errno, - strerror(errno)); - close(fd); - exit(EX_IOERR); - } + if (ioctl(fd, ioctl_cmd, &io_test) < 0) + err(1, "ioctl NVME_IO_TEST failed"); close(fd); print_perftest(&io_test, perthread); - exit(EX_OK); + exit(0); } diff --git a/sbin/nvmecontrol/reset.c b/sbin/nvmecontrol/reset.c index a96722c..8ce597e 100644 --- a/sbin/nvmecontrol/reset.c +++ b/sbin/nvmecontrol/reset.c @@ -30,12 +30,11 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include #include #include -#include #include #include "nvmecontrol.h" @@ -45,7 +44,7 @@ reset_usage(void) { fprintf(stderr, "usage:\n"); fprintf(stderr, RESET_USAGE); - exit(EX_USAGE); + exit(1); } void @@ -65,11 +64,8 @@ reset(int argc, char *argv[]) reset_usage(); open_dev(argv[optind], &fd, 1, 1); - if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) { - printf("Reset request to %s failed. errno=%d (%s)\n", - argv[optind], errno, strerror(errno)); - exit(EX_IOERR); - } + if (ioctl(fd, NVME_RESET_CONTROLLER) < 0) + err(1, "reset request to %s failed", argv[optind]); - exit(EX_OK); + exit(0); } -- cgit v1.1 From cf34871a462ef3ef67391f4b2782cb0d51d2fe2c Mon Sep 17 00:00:00 2001 From: jimharris Date: Tue, 9 Jul 2013 21:20:08 +0000 Subject: Try to read firmware image before prompting the user to confirm firmware download. This correctly prints an error and exits for an incorrect firmware image name before prompting the user to confirm the download. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/firmware.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/firmware.c b/sbin/nvmecontrol/firmware.c index c297f90..79adfb6 100644 --- a/sbin/nvmecontrol/firmware.c +++ b/sbin/nvmecontrol/firmware.c @@ -253,6 +253,9 @@ firmware(int argc, char *argv[]) "of available images\n", slot, controller); + if (f_flag) + read_image_file(image, &buf, &size); + if (f_flag && a_flag) printf("You are about to download and activate " "firmware image (%s) to controller %s.\n" @@ -282,7 +285,6 @@ firmware(int argc, char *argv[]) } if (f_flag) { - read_image_file(image, &buf, &size); update_firmware(fd, buf, size); if (a_flag) activate_firmware(fd, slot, -- cgit v1.1 From e9bddbcfa54c66d580d0e618ff4212c3a548837a Mon Sep 17 00:00:00 2001 From: jimharris Date: Tue, 9 Jul 2013 21:31:21 +0000 Subject: Send per-namespace logpage commands to the controller devnode, so they are processed as admin commands, not I/O commands. As part of this change, pull out the code for parsing a namespace node string into a separate function, since it is used for both identify and logpage commands. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/identify.c | 20 +++---------- sbin/nvmecontrol/logpage.c | 65 ++++++++++++++++-------------------------- sbin/nvmecontrol/nvmecontrol.c | 24 ++++++++++++++++ sbin/nvmecontrol/nvmecontrol.h | 1 + 4 files changed, 53 insertions(+), 57 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index 1fe2a34..189f164 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -194,7 +193,6 @@ identify_ns(int argc, char *argv[]) { struct nvme_namespace_data nsdata; char path[64]; - char *nsloc; int ch, fd, hexflag = 0, hexlength, nsid; int verboseflag = 0; @@ -224,22 +222,12 @@ identify_ns(int argc, char *argv[]) close(fd); /* - * Pull the namespace id from the string. +2 skips past the "ns" part - * of the string. Don't search past 10 characters into the string, - * otherwise we know it is malformed. - */ - nsloc = strnstr(argv[optind], NVME_NS_PREFIX, 10); - if (nsloc != NULL) - nsid = strtol(nsloc + 2, NULL, 10); - if (nsloc == NULL || (nsid == 0 && errno != 0)) - errx(1, "invalid namespace ID '%s'", argv[optind]); - - /* * We send IDENTIFY commands to the controller, not the namespace, - * since it is an admin cmd. So the path should only include the - * nvmeX part of the nvmeXnsY string. + * since it is an admin cmd. The namespace ID will be specified in + * the IDENTIFY command itself. So parse the namespace's device node + * string to get the controller substring and namespace ID. */ - snprintf(path, nsloc - argv[optind] + 1, "%s", argv[optind]); + parse_ns_str(argv[optind], path, &nsid); open_dev(path, &fd, 1, 1); read_namespace_data(fd, nsid, &nsdata); close(fd); diff --git a/sbin/nvmecontrol/logpage.c b/sbin/nvmecontrol/logpage.c index a26ce04..e330988 100644 --- a/sbin/nvmecontrol/logpage.c +++ b/sbin/nvmecontrol/logpage.c @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -242,12 +241,11 @@ logpage_usage(void) void logpage(int argc, char *argv[]) { - int fd, nsid, len; + int fd, nsid; int log_page = 0, pageflag = false; - int hexflag = false; - int allow_ns = false; - char ch, *p, *nsloc = NULL; - char *cname = NULL; + int hexflag = false, ns_specified; + char ch, *p; + char cname[64]; uint32_t size; void *buf; struct logpage_function *f; @@ -290,46 +288,31 @@ logpage(int argc, char *argv[]) if (optind >= argc) logpage_usage(); + if (strstr(argv[optind], NVME_NS_PREFIX) != NULL) { + ns_specified = true; + parse_ns_str(argv[optind], cname, &nsid); + open_dev(cname, &fd, 1, 1); + } else { + ns_specified = false; + nsid = NVME_GLOBAL_NAMESPACE_TAG; + open_dev(argv[optind], &fd, 1, 1); + } + /* * The log page attribtues indicate whether or not the controller * supports the SMART/Health information log page on a per * namespace basis. */ - cname = malloc(strlen(NVME_CTRLR_PREFIX) + 2); - len = strlen(NVME_CTRLR_PREFIX) + 1; - cname = strncpy(cname, argv[optind], len); - open_dev(cname, &fd, 1, 1); - read_controller_data(fd, &cdata); - - if (log_page == NVME_LOG_HEALTH_INFORMATION && cdata.lpa.ns_smart != 0) - allow_ns = true; - - /* If a namespace id was specified, validate it's use */ - if (strstr(argv[optind], NVME_NS_PREFIX) != NULL) { - if (!allow_ns) { - if (log_page != NVME_LOG_HEALTH_INFORMATION) - errx(1, - "log page %d valid only at controller level", - log_page); - else if (cdata.lpa.ns_smart == 0) - errx(1, - "controller does not support per " - "namespace smart/health information"); - } - nsloc = strnstr(argv[optind], NVME_NS_PREFIX, 10); - if (nsloc != NULL) - nsid = strtol(nsloc + 2, NULL, 10); - if (nsloc == NULL || (nsid == 0 && errno != 0)) - errx(1, "invalid namespace id '%s'", argv[optind]); - - /* - * User is asking for per namespace log page information - * so close the controller and open up the namespace. - */ - close(fd); - open_dev(argv[optind], &fd, 1, 1); - } else - nsid = NVME_GLOBAL_NAMESPACE_TAG; + if (ns_specified) { + if (log_page != NVME_LOG_HEALTH_INFORMATION) + errx(1, "log page %d valid only at controller level", + log_page); + read_controller_data(fd, &cdata); + if (cdata.lpa.ns_smart == 0) + errx(1, + "controller does not support per namespace " + "smart/health information"); + } print_fn = print_hex; if (!hexflag) { diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index c566bb3..63cec3c 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -198,6 +199,29 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) return (0); } +void +parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid) +{ + char *nsloc; + + /* + * Pull the namespace id from the string. +2 skips past the "ns" part + * of the string. Don't search past 10 characters into the string, + * otherwise we know it is malformed. + */ + nsloc = strnstr(ns_str, NVME_NS_PREFIX, 10); + if (nsloc != NULL) + *nsid = strtol(nsloc + 2, NULL, 10); + if (nsloc == NULL || (*nsid == 0 && errno != 0)) + errx(1, "invalid namespace ID '%s'", ns_str); + + /* + * The controller string will include only the nvmX part of the + * nvmeXnsY string. + */ + snprintf(ctrlr_str, nsloc - ns_str + 1, "%s", ns_str); +} + int main(int argc, char *argv[]) { diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index f7a35b4..99075f6 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -63,6 +63,7 @@ void logpage(int argc, char *argv[]); void firmware(int argc, char *argv[]); int open_dev(const char *str, int *fd, int show_error, int exit_on_error); +void parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid); void read_controller_data(int fd, struct nvme_controller_data *cdata); void read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata); void print_hex(void *data, uint32_t length); -- cgit v1.1 From dc13e388c88acb97133f1c3e9e81cb561ee239af Mon Sep 17 00:00:00 2001 From: jimharris Date: Tue, 9 Jul 2013 21:31:58 +0000 Subject: Condense the output for displaying LBA formats. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/identify.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index 189f164..ab6b85f 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -124,13 +124,11 @@ print_namespace(struct nvme_namespace_data *nsdata) printf("Thin Provisioning: %s\n", nsdata->nsfeat.thin_prov ? "Supported" : "Not Supported"); printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1); - printf("Current LBA Format: LBA Format #%d\n", + printf("Current LBA Format: LBA Format #%02d\n", nsdata->flbas.format); - for (i = 0; i <= nsdata->nlbaf; i++) { - printf("LBA Format #%d:\n", i); - printf(" LBA Data Size: %d\n", - 1 << nsdata->lbaf[i].lbads); - } + for (i = 0; i <= nsdata->nlbaf; i++) + printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d\n", + i, 1 << nsdata->lbaf[i].lbads, nsdata->lbaf[i].ms); } static void -- cgit v1.1 From adb4bd8e2c75d8b7a4fb20eb8c3518398be929a7 Mon Sep 17 00:00:00 2001 From: jimharris Date: Tue, 9 Jul 2013 21:33:12 +0000 Subject: Ensure controller or namespace node name is specified before trying to access it. While here, also fix the identify usage message to show the -v and -x parameters. Sponsored by: Intel MFC after: 3 days --- sbin/nvmecontrol/identify.c | 4 ++++ sbin/nvmecontrol/nvmecontrol.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index ab6b85f..7cc499c 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -259,6 +259,10 @@ identify(int argc, char *argv[]) while (getopt(argc, argv, "vx") != -1) ; + /* Check that a controller or namespace was specified. */ + if (optind >= argc) + identify_usage(); + target = argv[optind]; optreset = 1; diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index 99075f6..8401dd7 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -38,7 +38,7 @@ " nvmecontrol devlist\n" #define IDENTIFY_USAGE \ -" nvmecontrol identify \n" +" nvmecontrol identify [-x [-v]] \n" #define PERFTEST_USAGE \ " nvmecontrol perftest <-n num_threads> <-o read|write>\n" \ -- cgit v1.1 From e5c75edd62eb00cf58d339ad18419c62cb045ef5 Mon Sep 17 00:00:00 2001 From: jh Date: Fri, 12 Jul 2013 06:03:25 +0000 Subject: Clarify how "hide" and "unhide" commands work on directories. --- sbin/devfs/devfs.8 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/devfs/devfs.8 b/sbin/devfs/devfs.8 index 6e0c210..8bbdfcc 100644 --- a/sbin/devfs/devfs.8 +++ b/sbin/devfs/devfs.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 21, 2013 +.Dd July 12, 2013 .Dt DEVFS 8 .Os .Sh NAME @@ -190,6 +190,7 @@ Nodes may later be revived manually with or with the .Cm unhide action. +Hiding a directory node effectively hides all of its child nodes. .It Cm include Ar ruleset Apply all the rules in ruleset number .Ar ruleset @@ -213,6 +214,8 @@ which may be a user name or number. .It Cm unhide Unhide the node. +If the node resides in a subdirectory, +all parent directory nodes must be visible to be able to access the node. .El .Sh IMPLEMENTATION NOTES Rulesets are created by the kernel at the first reference -- cgit v1.1 From 151aa0ccc8689d78ec53e8c2ae8c3eb78e06205e Mon Sep 17 00:00:00 2001 From: oleg Date: Fri, 12 Jul 2013 09:20:55 +0000 Subject: Fix 'SEE ALSO' list. --- sbin/recoverdisk/recoverdisk.1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/recoverdisk/recoverdisk.1 b/sbin/recoverdisk/recoverdisk.1 index ef1241b..1661ab8 100644 --- a/sbin/recoverdisk/recoverdisk.1 +++ b/sbin/recoverdisk/recoverdisk.1 @@ -125,9 +125,9 @@ recoverdisk -b 0 /dev/ad3 /somewhere .Ed .Sh SEE ALSO .Xr dd 1 , -.Xr ada 4, -.Xr cam 4, -.Xr cd 4, +.Xr ada 4 , +.Xr cam 4 , +.Xr cd 4 , .Xr da 4 .Sh HISTORY The -- cgit v1.1 From 9b5eb8f860e576727754c92deb610ae7ef286651 Mon Sep 17 00:00:00 2001 From: jimharris Date: Fri, 12 Jul 2013 18:13:41 +0000 Subject: %d should be used for printing int32_t instead of %zd. clang does not complain about this - only gcc. MFC after: 3 days --- sbin/nvmecontrol/firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/firmware.c b/sbin/nvmecontrol/firmware.c index 79adfb6..66c7517 100644 --- a/sbin/nvmecontrol/firmware.c +++ b/sbin/nvmecontrol/firmware.c @@ -94,7 +94,7 @@ read_image_file(char *path, void **buf, int32_t *size) path, (intmax_t)sb.st_size); filesize = (int32_t)sb.st_size; if ((*buf = malloc(filesize)) == NULL) - errx(1, "unable to malloc %zd bytes", filesize); + errx(1, "unable to malloc %d bytes", filesize); if ((*size = read(fd, *buf, filesize)) < 0) err(1, "error reading '%s'", path); /* XXX assuming no short reads */ -- cgit v1.1 From 80fcd6f6829e197908c788c8acc29c253765035f Mon Sep 17 00:00:00 2001 From: rmh Date: Mon, 15 Jul 2013 21:57:21 +0000 Subject: Add -n flag for compatibility with Linux version of mount(8). Reviewed by: freebsd-fs, eadler, mckusick, jh, wblock --- sbin/mount/mount.8 | 3 +++ sbin/mount/mount.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/mount/mount.8 b/sbin/mount/mount.8 index 5b670ee..50c5a8b 100644 --- a/sbin/mount/mount.8 +++ b/sbin/mount/mount.8 @@ -118,6 +118,9 @@ When used in conjunction with the .Fl a option, also mount those file systems which are marked as .Dq Li late . +.It Fl n +For compatibility with some other implementations, this flag is +currently a no-op. .It Fl o Options are specified with a .Fl o diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c index 6284822..91c7d7c 100644 --- a/sbin/mount/mount.c +++ b/sbin/mount/mount.c @@ -253,7 +253,7 @@ main(int argc, char *argv[]) options = NULL; vfslist = NULL; vfstype = "ufs"; - while ((ch = getopt(argc, argv, "adF:fLlo:prt:uvw")) != -1) + while ((ch = getopt(argc, argv, "adF:fLlno:prt:uvw")) != -1) switch (ch) { case 'a': all = 1; @@ -274,6 +274,9 @@ main(int argc, char *argv[]) case 'l': late = 1; break; + case 'n': + /* For compatibility with the Linux version of mount. */ + break; case 'o': if (*optarg) { options = catopt(options, optarg); -- cgit v1.1 From 306e14bae389ddad05452ba4aaab074dd0002e44 Mon Sep 17 00:00:00 2001 From: jimharris Date: Tue, 16 Jul 2013 15:45:37 +0000 Subject: Do not throw an error if the user requests to activate the image from an empty firmware slot, as long as the user has specified a firmware image to download into the empty firmware slot. Sponsored by: Intel Reported by: Joe Golio MFC after: 3 days --- sbin/nvmecontrol/firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/firmware.c b/sbin/nvmecontrol/firmware.c index 66c7517..cb7fb0f 100644 --- a/sbin/nvmecontrol/firmware.c +++ b/sbin/nvmecontrol/firmware.c @@ -246,7 +246,7 @@ firmware(int argc, char *argv[]) "slot %d specified but controller only supports %d slots", slot, cdata.frmw.num_slots); - if (!slot_has_valid_firmware(fd, slot)) + if (a_flag && !f_flag && !slot_has_valid_firmware(fd, slot)) errx(1, "slot %d does not contain valid firmware,\n" "try 'nvmecontrol logpage -p 3 %s' to get a list " -- cgit v1.1 From c86c82ce526c1a0c63a20c69687e8d71d0c5f5d4 Mon Sep 17 00:00:00 2001 From: hrs Date: Wed, 17 Jul 2013 13:47:13 +0000 Subject: Simplify keywords.h generation. --- sbin/route/Makefile | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'sbin') diff --git a/sbin/route/Makefile b/sbin/route/Makefile index 0f4cd67..231c3da 100644 --- a/sbin/route/Makefile +++ b/sbin/route/Makefile @@ -7,7 +7,7 @@ PROG= route MAN= route.8 SRCS= route.c keywords.h WARNS?= 3 -CLEANFILES+=keywords.h _keywords.tmp +CLEANFILES+=keywords.h CFLAGS+= -DNS @@ -18,13 +18,9 @@ CFLAGS+= -DINET6 CFLAGS+= -I. keywords.h: keywords - sed -e '/^#/d' -e '/^$$/d' ${.CURDIR}/keywords > _keywords.tmp - LC_ALL=C tr 'a-z' 'A-Z' < _keywords.tmp | paste _keywords.tmp - | \ - awk '{ \ - if (NF > 1) \ - printf "#define\tK_%s\t%d\n\t{\"%s\", K_%s},\n", \ - $$2, NR, $$1, $$2 }' \ - > ${.TARGET} - rm -f _keywords.tmp + LC_ALL=C awk '!/^#|^$$/ { \ + printf "#define\tK_%s\t%d\n\t{\"%s\", K_%s},\n", \ + toupper($$1), ++L, $$1, toupper($$1); \ + }' < ${.CURDIR}/keywords > ${.TARGET} || (rm -f ${.TARGET}; false) .include -- cgit v1.1 From 9542c4065e347b47bdfeee6635ab0598e64bab9d Mon Sep 17 00:00:00 2001 From: hrs Date: Wed, 17 Jul 2013 14:05:20 +0000 Subject: - Add support of MK_INET_SUPPORT=no. - Fix a bug in sodump() which prevented struct sockaddr_in6 from displaying. - Fix a bug in in fiboptlist_csv() which could cause free() of uninitialized pointer. - Style cleanups: . Add missing "static" keywords. . Use an array of struct sockaddr_storage instead of sockunion for rtmsg. . Use err() and errx() instead of pair of fprintf(stderr, "...") + exit(1). . Use nitems() macro. . Various style(9) fixes. --- sbin/route/Makefile | 5 +- sbin/route/route.c | 541 ++++++++++++++++++++++++++-------------------------- 2 files changed, 278 insertions(+), 268 deletions(-) (limited to 'sbin') diff --git a/sbin/route/Makefile b/sbin/route/Makefile index 231c3da..569d21a 100644 --- a/sbin/route/Makefile +++ b/sbin/route/Makefile @@ -10,11 +10,12 @@ WARNS?= 3 CLEANFILES+=keywords.h CFLAGS+= -DNS - +.if ${MK_INET_SUPPORT} != "no" +CFLAGS+= -DINET +.endif .if ${MK_INET6_SUPPORT} != "no" CFLAGS+= -DINET6 .endif - CFLAGS+= -I. keywords.h: keywords diff --git a/sbin/route/route.c b/sbin/route/route.c index c751657..2186482 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -70,7 +70,7 @@ __FBSDID("$FreeBSD$"); #include #include -struct keytab { +static struct keytab { const char *kt_cp; int kt_i; } keywords[] = { @@ -78,42 +78,33 @@ struct keytab { {0, 0} }; -union sockunion { - struct sockaddr sa; - struct sockaddr_in sin; -#ifdef INET6 - struct sockaddr_in6 sin6; -#endif - struct sockaddr_at sat; - struct sockaddr_dl sdl; - struct sockaddr_storage ss; /* added to avoid memory overrun */ -} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp; - -typedef union sockunion *sup; -int pid, rtm_addrs; -int s; -int forcehost, forcenet, doflush, nflag, af, qflag, tflag; -int verbose, aflen = sizeof (struct sockaddr_in); -int locking, lockrest, debugonly; -struct rt_metrics rt_metrics; -u_long rtm_inits; -uid_t uid; +static struct sockaddr_storage so[RTAX_MAX]; +static int pid, rtm_addrs; +static int s; +static int forcehost, forcenet, nflag, af, qflag, tflag; +static int verbose, aflen; +static int locking, lockrest, debugonly; +static struct rt_metrics rt_metrics; +static u_long rtm_inits; +static uid_t uid; static int defaultfib; static int numfibs; static int atalk_aton(const char *, struct at_addr *); static char *atalk_ntoa(struct at_addr); -static void bprintf(FILE *, int, u_char *); +static void printb(int, const char *); static void flushroutes(int argc, char *argv[]); static int flushroutes_fib(int); static int getaddr(int, char *, struct hostent **, int); static int keyword(const char *); -static void inet_makenetandmask(u_long, struct sockaddr_in *, u_long); +#ifdef INET +static void inet_makenetandmask(u_long, struct sockaddr_in *, + struct sockaddr_in *, u_long); +#endif #ifdef INET6 -static int inet6_makenetandmask(struct sockaddr_in6 *, const char *); +static int inet6_makenetandmask(struct sockaddr_in6 *, const char *); #endif static void interfaces(void); -static void mask_addr(void); static void monitor(int, char*[]); static const char *netname(struct sockaddr *); static void newroute(int, char **); @@ -128,8 +119,8 @@ static int rtmsg(int, int, int); static void set_metric(char *, int); static int set_sofib(int); static int set_procfib(int); -static void sockaddr(char *, struct sockaddr *); -static void sodump(sup, const char *); +static void sockaddr(char *, struct sockaddr *, size_t); +static void sodump(struct sockaddr *, const char *); extern char *iso_ntoa(void); struct fibl { @@ -139,7 +130,7 @@ struct fibl { int fl_error; int fl_errno; }; -TAILQ_HEAD(fibl_head_t, fibl) fibl_head; +static TAILQ_HEAD(fibl_head_t, fibl) fibl_head; static int fiboptlist_csv(const char *, struct fibl_head_t *); static int fiboptlist_range(const char *, struct fibl_head_t *); @@ -151,9 +142,7 @@ usage(const char *cp) { if (cp != NULL) warnx("bad keyword: %s", cp); - (void) fprintf(stderr, - "usage: route [-dnqtv] command [[modifiers] args]\n"); - exit(EX_USAGE); + errx(EX_USAGE, "usage: route [-dnqtv] command [[modifiers] args]"); /* NOTREACHED */ } @@ -313,6 +302,7 @@ fiboptlist_csv(const char *arg, struct fibl_head_t *flh) char *str0, *str, *token, *endptr; int fib, error; + str0 = str = NULL; if (strcmp("all", arg) == 0) { str = calloc(1, ALLSTRLEN); if (str == NULL) { @@ -362,7 +352,8 @@ fiboptlist_csv(const char *arg, struct fibl_head_t *flh) } } fiboptlist_csv_ret: - free(str0); + if (str0 != NULL) + free(str0); return (error); } @@ -376,9 +367,8 @@ flushroutes(int argc, char *argv[]) struct fibl *fl; int error; - if (uid != 0 && !debugonly && !tflag) { + if (uid != 0 && !debugonly && !tflag) errx(EX_NOPERM, "must be root to alter routing table"); - } shutdown(s, SHUT_RD); /* Don't want to read back our messages */ TAILQ_INIT(&fibl_head); @@ -388,9 +378,11 @@ flushroutes(int argc, char *argv[]) if (**argv != '-') usage(*argv); switch (keyword(*argv + 1)) { +#ifdef INET case K_INET: af = AF_INET; break; +#endif #ifdef INET6 case K_INET6: af = AF_INET6; @@ -442,14 +434,14 @@ retry: mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; /* protocol */ - mib[3] = 0; /* wildcard address family */ + mib[3] = AF_UNSPEC; mib[4] = NET_RT_DUMP; mib[5] = 0; /* no flags */ - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) err(EX_OSERR, "route-sysctl-estimate"); if ((buf = malloc(needed)) == NULL) errx(EX_OSERR, "malloc failed"); - if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) { if (errno == ENOMEM && count++ < 10) { warnx("Routing table grew, retrying"); sleep(1); @@ -460,7 +452,7 @@ retry: } lim = buf + needed; if (verbose) - (void) printf("Examining routing table from sysctl\n"); + (void)printf("Examining routing table from sysctl\n"); seqno = 0; /* ??? */ for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; @@ -483,7 +475,7 @@ retry: err(1, "write to routing socket"); if (rlen < (int)rtm->rtm_msglen) { warn("write to routing socket"); - (void) printf("got only %d for rlen\n", rlen); + (void)printf("got only %d for rlen\n", rlen); free(buf); goto retry; break; @@ -513,7 +505,9 @@ routename(struct sockaddr *sa) { const char *cp; static char line[MAXHOSTNAMELEN + 1]; +#ifdef INET struct hostent *hp; +#endif static char domain[MAXHOSTNAMELEN + 1]; static int first = 1, n; @@ -522,19 +516,22 @@ routename(struct sockaddr *sa) if (gethostname(domain, MAXHOSTNAMELEN) == 0 && (cp = strchr(domain, '.'))) { domain[MAXHOSTNAMELEN] = '\0'; - (void) strcpy(domain, cp + 1); + (void)strcpy(domain, cp + 1); } else - domain[0] = 0; + domain[0] = '\0'; } - if (sa->sa_len == 0) + if (sa->sa_len == 0) { strcpy(line, "default"); - else switch (sa->sa_family) { - + return (line); + } + switch (sa->sa_family) { +#ifdef INET case AF_INET: - { struct in_addr in; - in = ((struct sockaddr_in *)sa)->sin_addr; + { + struct in_addr in; + in = ((struct sockaddr_in *)sa)->sin_addr; cp = NULL; if (in.s_addr == INADDR_ANY || sa->sa_len < 4) cp = "default"; @@ -554,10 +551,11 @@ routename(struct sockaddr *sa) strncpy(line, cp, sizeof(line) - 1); line[sizeof(line) - 1] = '\0'; } else - (void) sprintf(line, "%s", inet_ntoa(in)); + (void)sprintf(line, "%s", inet_ntoa(in)); break; - } + } +#endif #ifdef INET6 case AF_INET6: { @@ -574,17 +572,18 @@ routename(struct sockaddr *sa) line, sizeof(line), NULL, 0, niflags) != 0) strncpy(line, "invalid", sizeof(line)); - return(line); + return (line); } #endif case AF_APPLETALK: - (void) snprintf(line, sizeof(line), "atalk %s", - atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); + (void)snprintf(line, sizeof(line), "atalk %s", + atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); break; case AF_LINK: return (link_ntoa((struct sockaddr_dl *)sa)); + break; default: { @@ -611,18 +610,21 @@ routename(struct sockaddr *sa) const char * netname(struct sockaddr *sa) { - const char *cp = NULL; static char line[MAXHOSTNAMELEN + 1]; + int n; +#ifdef INET struct netent *np = NULL; + const char *cp = NULL; u_long i; - int n; +#endif switch (sa->sa_family) { - +#ifdef INET case AF_INET: - { struct in_addr in; - in = ((struct sockaddr_in *)sa)->sin_addr; + { + struct in_addr in; + in = ((struct sockaddr_in *)sa)->sin_addr; i = in.s_addr = ntohl(in.s_addr); if (in.s_addr == 0) cp = "default"; @@ -635,30 +637,30 @@ netname(struct sockaddr *sa) if (cp != NULL) strncpy(line, cp, sizeof(line)); else if ((in.s_addr & 0xffffff) == 0) - (void) sprintf(line, "%u", C(in.s_addr >> 24)); + (void)sprintf(line, "%u", C(in.s_addr >> 24)); else if ((in.s_addr & 0xffff) == 0) - (void) sprintf(line, "%u.%u", C(in.s_addr >> 24), + (void)sprintf(line, "%u.%u", C(in.s_addr >> 24), C(in.s_addr >> 16)); else if ((in.s_addr & 0xff) == 0) - (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), + (void)sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), C(in.s_addr >> 16), C(in.s_addr >> 8)); else - (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), + (void)sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); #undef C break; - } - + } +#endif #ifdef INET6 case AF_INET6: { - struct sockaddr_in6 sin6; /* use static var for safety */ + struct sockaddr_in6 sin6; int niflags = 0; memset(&sin6, 0, sizeof(sin6)); memcpy(&sin6, sa, sa->sa_len); - sin6.sin6_len = sizeof(struct sockaddr_in6); + sin6.sin6_len = sizeof(sin6); sin6.sin6_family = AF_INET6; if (nflag) niflags |= NI_NUMERICHOST; @@ -671,13 +673,13 @@ netname(struct sockaddr *sa) #endif case AF_APPLETALK: - (void) snprintf(line, sizeof(line), "atalk %s", - atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); + (void)snprintf(line, sizeof(line), "atalk %s", + atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); break; case AF_LINK: return (link_ntoa((struct sockaddr_dl *)sa)); - + break; default: { @@ -738,10 +740,8 @@ newroute(int argc, char **argv) const char *dest, *gateway, *errmsg; int key, error, flags, nrflags, fibnum; - if (uid != 0 && !debugonly && !tflag) { + if (uid != 0 && !debugonly && !tflag) errx(EX_NOPERM, "must be root to alter routing table"); - } - dest = NULL; gateway = NULL; flags = RTF_STATIC; @@ -752,7 +752,6 @@ newroute(int argc, char **argv) cmd = argv[0]; if (*cmd != 'g' && *cmd != 's') shutdown(s, SHUT_RD); /* Don't want to read back our messages */ - while (--argc > 0) { if (**(++argv)== '-') { switch (key = keyword(1 + *argv)) { @@ -760,10 +759,12 @@ newroute(int argc, char **argv) af = AF_LINK; aflen = sizeof(struct sockaddr_dl); break; +#ifdef INET case K_INET: af = AF_INET; aflen = sizeof(struct sockaddr_in); break; +#endif #ifdef INET6 case K_INET6: af = AF_INET6; @@ -776,7 +777,7 @@ newroute(int argc, char **argv) break; case K_SA: af = PF_ROUTE; - aflen = sizeof(union sockunion); + aflen = sizeof(struct sockaddr_storage); break; case K_IFACE: case K_INTERFACE: @@ -912,7 +913,7 @@ newroute(int argc, char **argv) #ifdef INET6 if (af == AF_INET6) { rtm_addrs &= ~RTA_NETMASK; - memset((void *)&so_mask, 0, sizeof(so_mask)); + memset(&so[RTAX_NETMASK], 0, sizeof(so[RTAX_NETMASK])); } #endif } @@ -1035,11 +1036,12 @@ newroute_fib(int fib, char *cmd, int flags) return (error); } +#ifdef INET static void -inet_makenetandmask(u_long net, struct sockaddr_in *sin, u_long bits) +inet_makenetandmask(u_long net, struct sockaddr_in *sin, + struct sockaddr_in *sin_mask, u_long bits) { u_long mask = 0; - char *cp; rtm_addrs |= RTA_NETMASK; @@ -1056,7 +1058,8 @@ inet_makenetandmask(u_long net, struct sockaddr_in *sin, u_long bits) */ if ((bits == 0) && (net != 0)) { u_long i, j; - for(i=0,j=0xff; i<4; i++) { + + for(i = 0, j = 0xff; i < 4; i++) { if (net & j) { break; } @@ -1069,15 +1072,11 @@ inet_makenetandmask(u_long net, struct sockaddr_in *sin, u_long bits) mask = 0xffffffff << (32 - bits); sin->sin_addr.s_addr = htonl(net); - sin = &so_mask.sin; - sin->sin_addr.s_addr = htonl(mask); - sin->sin_len = 0; - sin->sin_family = 0; - cp = (char *)(&sin->sin_addr + 1); - while (*--cp == 0 && cp > (char *)sin) - ; - sin->sin_len = 1 + cp - (char *)sin; + sin_mask->sin_addr.s_addr = htonl(mask); + sin_mask->sin_len = sizeof(struct sockaddr_in); + sin_mask->sin_family = AF_INET; } +#endif #ifdef INET6 /* @@ -1116,31 +1115,66 @@ inet6_makenetandmask(struct sockaddr_in6 *sin6, const char *plen) static int getaddr(int which, char *str, struct hostent **hpp, int nrflags) { - sup su; + struct sockaddr *sa; +#if defined(INET) + struct sockaddr_in *sin; struct hostent *hp; struct netent *np; u_long val; char *q; - int afamily; /* local copy of af so we can change it */ +#elif defined(INET6) + char *q; +#endif if (af == 0) { +#if defined(INET) af = AF_INET; aflen = sizeof(struct sockaddr_in); +#elif defined(INET6) + af = AF_INET6; + aflen = sizeof(struct sockaddr_in6); +#else + af = AF_LINK; + aflen = sizeof(struct sockaddr_dl); +#endif } - afamily = af; rtm_addrs |= which; + switch (which) { case RTA_DST: - su = &so_dst; + sa = (struct sockaddr *)&so[RTAX_DST]; break; case RTA_GATEWAY: - su = &so_gate; + sa = (struct sockaddr *)&so[RTAX_GATEWAY]; + break; + case RTA_NETMASK: + sa = (struct sockaddr *)&so[RTAX_NETMASK]; + break; + case RTA_GENMASK: + sa = (struct sockaddr *)&so[RTAX_GENMASK]; + break; + case RTA_IFA: + sa = (struct sockaddr *)&so[RTAX_IFA]; + break; + case RTA_IFP: + sa = (struct sockaddr *)&so[RTAX_IFP]; + break; + default: + usage("internal error"); + /*NOTREACHED*/ + } + sa->sa_family = af; + sa->sa_len = aflen; + + switch (which) { + case RTA_GATEWAY: if (nrflags & F_INTERFACE) { struct ifaddrs *ifap, *ifa; + struct sockaddr_dl *sdl0 = (struct sockaddr_dl *)sa; struct sockaddr_dl *sdl = NULL; if (getifaddrs(&ifap)) - err(1, "getifaddrs"); + err(EX_OSERR, "getifaddrs"); for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != AF_LINK) @@ -1154,37 +1188,20 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) /* If we found it, then use it */ if (sdl != NULL) { /* - * Copy is safe since we have a - * sockaddr_storage member in sockunion{}. * Note that we need to copy before calling * freeifaddrs(). */ - memcpy(&su->sdl, sdl, sdl->sdl_len); + memcpy(sdl0, sdl, sdl->sdl_len); } freeifaddrs(ifap); if (sdl != NULL) return(1); } break; - case RTA_NETMASK: - su = &so_mask; - break; - case RTA_GENMASK: - su = &so_genmask; - break; case RTA_IFP: - su = &so_ifp; - afamily = AF_LINK; + sa->sa_family = AF_LINK; break; - case RTA_IFA: - su = &so_ifa; - break; - default: - usage("internal error"); - /*NOTREACHED*/ } - su->sa.sa_len = aflen; - su->sa.sa_family = afamily; /* cases that don't want it have left already */ if (strcmp(str, "default") == 0) { /* * Default is net 0.0.0.0/0 @@ -1192,20 +1209,12 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) switch (which) { case RTA_DST: forcenet++; -#if 0 - bzero(su, sizeof(*su)); /* for readability */ -#endif getaddr(RTA_NETMASK, str, 0, nrflags); break; -#if 0 - case RTA_NETMASK: - case RTA_GENMASK: - bzero(su, sizeof(*su)); /* for readability */ -#endif } return (0); } - switch (afamily) { + switch (sa->sa_family) { #ifdef INET6 case AF_INET6: { @@ -1216,46 +1225,48 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) if (which == RTA_DST && (q = strchr(str, '/')) != NULL) *q = '\0'; memset(&hints, 0, sizeof(hints)); - hints.ai_family = afamily; /*AF_INET6*/ - hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_family = sa->sa_family; + hints.ai_socktype = SOCK_DGRAM; ecode = getaddrinfo(str, NULL, &hints, &res); if (ecode != 0 || res->ai_family != AF_INET6 || - res->ai_addrlen != sizeof(su->sin6)) { - (void) fprintf(stderr, "%s: %s\n", str, - gai_strerror(ecode)); - exit(1); - } - memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6)); + res->ai_addrlen != sizeof(struct sockaddr_in6)) + errx(EX_OSERR, "%s: %s", str, gai_strerror(ecode)); + memcpy(sa, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); if (q != NULL) *q++ = '/'; if (which == RTA_DST) - return (inet6_makenetandmask(&su->sin6, q)); + return (inet6_makenetandmask((struct sockaddr_in6 *)sa, + q)); return (0); } #endif /* INET6 */ case AF_APPLETALK: - if (!atalk_aton(str, &su->sat.sat_addr)) + { + struct sockaddr_at *sat = (struct sockaddr_at *)sa; + + if (!atalk_aton(str, &sat->sat_addr)) errx(EX_NOHOST, "bad address: %s", str); rtm_addrs |= RTA_NETMASK; - return(forcehost || su->sat.sat_addr.s_node != 0); - + return(forcehost || sat->sat_addr.s_node != 0); + } case AF_LINK: - link_addr(str, &su->sdl); + link_addr(str, (struct sockaddr_dl *)sa); return (1); - case PF_ROUTE: - su->sa.sa_len = sizeof(*su); - sockaddr(str, &su->sa); + sockaddr(str, sa, sizeof(struct sockaddr_storage)); return (1); - +#ifdef INET case AF_INET: +#endif default: break; } +#ifdef INET + sin = (struct sockaddr_in *)sa; if (hpp == NULL) hpp = &hp; *hpp = NULL; @@ -1264,17 +1275,18 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) if (q != NULL && which == RTA_DST) { *q = '\0'; if ((val = inet_network(str)) != INADDR_NONE) { - inet_makenetandmask( - val, &su->sin, strtoul(q+1, 0, 0)); + inet_makenetandmask(val, sin, + (struct sockaddr_in *)&so[RTAX_NETMASK], + strtoul(q+1, 0, 0)); return (0); } *q = '/'; } if ((which != RTA_DST || forcenet == 0) && - inet_aton(str, &su->sin.sin_addr)) { - val = su->sin.sin_addr.s_addr; + inet_aton(str, &sin->sin_addr)) { + val = sin->sin_addr.s_addr; if (which != RTA_DST || forcehost || - inet_lnaof(su->sin.sin_addr) != INADDR_ANY) + inet_lnaof(sin->sin_addr) != INADDR_ANY) return (1); else { val = ntohl(val); @@ -1285,17 +1297,19 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) ((val = inet_network(str)) != INADDR_NONE || ((np = getnetbyname(str)) != NULL && (val = np->n_net) != 0))) { netdone: - inet_makenetandmask(val, &su->sin, 0); + inet_makenetandmask(val, sin, + (struct sockaddr_in *)&so[RTAX_NETMASK], 0); return (0); } hp = gethostbyname(str); if (hp != NULL) { *hpp = hp; - su->sin.sin_family = hp->h_addrtype; - memmove((char *)&su->sin.sin_addr, hp->h_addr, - MIN((size_t)hp->h_length, sizeof(su->sin.sin_addr))); + sin->sin_family = hp->h_addrtype; + memmove((char *)&sin->sin_addr, hp->h_addr, + MIN((size_t)hp->h_length, sizeof(sin->sin_addr))); return (1); } +#endif errx(EX_NOHOST, "bad address: %s", str); } @@ -1310,28 +1324,39 @@ prefixlen(const char *str) switch (af) { #ifdef INET6 case AF_INET6: + { + struct sockaddr_in6 *sin6 = + (struct sockaddr_in6 *)&so[RTAX_NETMASK]; + max = 128; - p = (char *)&so_mask.sin6.sin6_addr; + p = (char *)&sin6->sin6_addr; + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(*sin6); break; + } #endif +#ifdef INET case AF_INET: + { + struct sockaddr_in *sin = + (struct sockaddr_in *)&so[RTAX_NETMASK]; + max = 32; - p = (char *)&so_mask.sin.sin_addr; + p = (char *)&sin->sin_addr; + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); break; + } +#endif default: - fprintf(stderr, "prefixlen not supported in this af\n"); - exit(1); + errx(EX_OSERR, "prefixlen not supported in this af"); } - if (len < 0 || max < len) { - fprintf(stderr, "%s: bad value\n", str); - exit(1); - } + if (len < 0 || max < len) + errx(EX_USAGE, "%s: invalid prefixlen", str); q = len >> 3; r = len & 7; - so_mask.sa.sa_family = af; - so_mask.sa.sa_len = aflen; memset((void *)p, 0, max / 8); if (q > 0) memset((void *)p, 0xff, q); @@ -1355,14 +1380,14 @@ retry2: mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; /* protocol */ - mib[3] = 0; /* wildcard address family */ + mib[3] = AF_UNSPEC; mib[4] = NET_RT_IFLIST; mib[5] = 0; /* no flags */ - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) err(EX_OSERR, "route-sysctl-estimate"); if ((buf = malloc(needed)) == NULL) errx(EX_OSERR, "malloc failed"); - if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) { if (errno == ENOMEM && count++ < 10) { warnx("Routing table grew, retrying"); sleep(1); @@ -1422,12 +1447,12 @@ monitor(int argc, char *argv[]) time_t now; n = read(s, msg, 2048); now = time(NULL); - (void) printf("\ngot message of size %d on %s", n, ctime(&now)); + (void)printf("\ngot message of size %d on %s", n, ctime(&now)); print_rtmsg((struct rt_msghdr *)msg, n); } } -struct { +static struct { struct rt_msghdr m_rtm; char m_space[512]; } m_rtmsg; @@ -1440,10 +1465,13 @@ rtmsg(int cmd, int flags, int fib) char *cp = m_rtmsg.m_space; int l; -#define NEXTADDR(w, u) \ - if (rtm_addrs & (w)) {\ - l = SA_SIZE(&(u.sa)); memmove(cp, &(u), l); cp += l;\ - if (verbose) sodump(&(u),#u);\ +#define NEXTADDR(w, u) \ + if (rtm_addrs & (w)) { \ + l = SA_SIZE((struct sockaddr *)&(u)); \ + memmove(cp, (char *)&(u), l); \ + cp += l; \ + if (verbose) \ + sodump((struct sockaddr *)&(u), #w); \ } errno = 0; @@ -1454,9 +1482,9 @@ rtmsg(int cmd, int flags, int fib) cmd = RTM_CHANGE; else if (cmd == 'g' || cmd == 's') { cmd = RTM_GET; - if (so_ifp.sa.sa_family == 0) { - so_ifp.sa.sa_family = AF_LINK; - so_ifp.sa.sa_len = sizeof(struct sockaddr_dl); + if (so[RTAX_IFP].ss_family == 0) { + so[RTAX_IFP].ss_family = AF_LINK; + so[RTAX_IFP].ss_len = sizeof(struct sockaddr_dl); rtm_addrs |= RTA_IFP; } } else @@ -1470,14 +1498,12 @@ rtmsg(int cmd, int flags, int fib) rtm.rtm_rmx = rt_metrics; rtm.rtm_inits = rtm_inits; - if (rtm_addrs & RTA_NETMASK) - mask_addr(); - NEXTADDR(RTA_DST, so_dst); - NEXTADDR(RTA_GATEWAY, so_gate); - NEXTADDR(RTA_NETMASK, so_mask); - NEXTADDR(RTA_GENMASK, so_genmask); - NEXTADDR(RTA_IFP, so_ifp); - NEXTADDR(RTA_IFA, so_ifa); + NEXTADDR(RTA_DST, so[RTAX_DST]); + NEXTADDR(RTA_GATEWAY, so[RTAX_GATEWAY]); + NEXTADDR(RTA_NETMASK, so[RTAX_NETMASK]); + NEXTADDR(RTA_GENMASK, so[RTAX_GENMASK]); + NEXTADDR(RTA_IFP, so[RTAX_IFP]); + NEXTADDR(RTA_IFA, so[RTAX_IFA]); rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; if (verbose) print_rtmsg(&rtm, l); @@ -1502,38 +1528,7 @@ rtmsg(int cmd, int flags, int fib) return (0); } -static void -mask_addr(void) -{ - int olen = so_mask.sa.sa_len; - char *cp1 = olen + (char *)&so_mask, *cp2; - - for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; ) - if (*--cp1 != 0) { - so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask; - break; - } - if ((rtm_addrs & RTA_DST) == 0) - return; - switch (so_dst.sa.sa_family) { - case AF_INET: -#ifdef INET6 - case AF_INET6: -#endif - case AF_APPLETALK: - case 0: - return; - } - cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst; - cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst; - while (cp2 > cp1) - *--cp2 = 0; - cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask; - while (cp1 > so_dst.sa.sa_data) - *--cp1 &= *--cp2; -} - -const char *msgtypes[] = { +static const char *msgtypes[] = { "", "RTM_ADD: Add Route", "RTM_DELETE: Delete Route", @@ -1555,23 +1550,23 @@ const char *msgtypes[] = { "RTM_IEEE80211: IEEE 802.11 wireless event", }; -char metricnames[] = -"\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire" -"\1mtu"; -char routeflags[] = -"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE" -"\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE" -"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3" -"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\035STICKY"; -char ifnetflags[] = -"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP" -"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1" -"\017LINK2\020MULTICAST"; -char addrnames[] = -"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; +static const char metricnames[] = + "\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire" + "\1mtu"; +static const char routeflags[] = + "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE" + "\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE" + "\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3" + "\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\035STICKY"; +static const char ifnetflags[] = + "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP" + "\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1" + "\017LINK2\020MULTICAST"; +static const char addrnames[] = + "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; static const char errfmt[] = -"\n%s: truncated route message, only %zu bytes left\n"; + "\n%s: truncated route message, only %zu bytes left\n"; static void print_rtmsg(struct rt_msghdr *rtm, size_t msglen) @@ -1587,7 +1582,7 @@ print_rtmsg(struct rt_msghdr *rtm, size_t msglen) if (verbose == 0) return; if (rtm->rtm_version != RTM_VERSION) { - (void) printf("routing message version %d not understood\n", + (void)printf("routing message version %d not understood\n", rtm->rtm_version); return; } @@ -1608,7 +1603,7 @@ print_rtmsg(struct rt_msghdr *rtm, size_t msglen) case RTM_IFINFO: REQUIRE(struct if_msghdr); ifm = (struct if_msghdr *)rtm; - (void) printf("if# %d, ", ifm->ifm_index); + (void)printf("if# %d, ", ifm->ifm_index); switch (ifm->ifm_data.ifi_link_state) { case LINK_STATE_DOWN: state = "down"; @@ -1620,16 +1615,16 @@ print_rtmsg(struct rt_msghdr *rtm, size_t msglen) state = "unknown"; break; } - (void) printf("link: %s, flags:", state); - bprintf(stdout, ifm->ifm_flags, ifnetflags); + (void)printf("link: %s, flags:", state); + printb(ifm->ifm_flags, ifnetflags); pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs, msglen); break; case RTM_NEWADDR: case RTM_DELADDR: REQUIRE(struct ifa_msghdr); ifam = (struct ifa_msghdr *)rtm; - (void) printf("metric %d, flags:", ifam->ifam_metric); - bprintf(stdout, ifam->ifam_flags, routeflags); + (void)printf("metric %d, flags:", ifam->ifam_metric); + printb(ifam->ifam_flags, routeflags); pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs, msglen); break; #ifdef RTM_NEWMADDR @@ -1643,10 +1638,10 @@ print_rtmsg(struct rt_msghdr *rtm, size_t msglen) case RTM_IFANNOUNCE: REQUIRE(struct if_announcemsghdr); ifan = (struct if_announcemsghdr *)rtm; - (void) printf("if# %d, what: ", ifan->ifan_index); + (void)printf("if# %d, what: ", ifan->ifan_index); switch (ifan->ifan_what) { case IFAN_ARRIVAL: - printf("arrival"); + (void)printf("arrival"); break; case IFAN_DEPARTURE: printf("departure"); @@ -1660,9 +1655,9 @@ print_rtmsg(struct rt_msghdr *rtm, size_t msglen) break; default: - (void) printf("pid: %ld, seq %d, errno %d, flags:", + printf("pid: %ld, seq %d, errno %d, flags:", (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno); - bprintf(stdout, rtm->rtm_flags, routeflags); + printb(rtm->rtm_flags, routeflags); pmsg_common(rtm, msglen); } @@ -1682,8 +1677,8 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) char *cp; int i; - (void) printf(" route to: %s\n", - routename((struct sockaddr *)&so_dst)); + (void)printf(" route to: %s\n", + routename((struct sockaddr *)&so[RTAX_DST])); if (rtm->rtm_version != RTM_VERSION) { warnx("routing message version %d not understood", rtm->rtm_version); @@ -1740,12 +1735,12 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) (void)printf(" interface: %.*s\n", ifp->sdl_nlen, ifp->sdl_data); (void)printf(" flags: "); - bprintf(stdout, rtm->rtm_flags, routeflags); + printb(rtm->rtm_flags, routeflags); #define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') #define msec(u) (((u) + 500) / 1000) /* usec to msec */ - (void) printf("\n%s\n", "\ + printf("\n%s\n", "\ recvpipe sendpipe ssthresh rtt,msec mtu weight expire"); printf("%8ld%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE)); printf("%8ld%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE)); @@ -1762,8 +1757,8 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) if (verbose) pmsg_common(rtm, msglen); else if (rtm->rtm_addrs &~ RTA_IGN) { - (void) printf("sockaddrs: "); - bprintf(stdout, rtm->rtm_addrs, addrnames); + (void)printf("sockaddrs: "); + printb(rtm->rtm_addrs, addrnames); putchar('\n'); } #undef RTA_IGN @@ -1772,15 +1767,16 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) static void pmsg_common(struct rt_msghdr *rtm, size_t msglen) { - (void) printf("\nlocks: "); - bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); - (void) printf(" inits: "); - bprintf(stdout, rtm->rtm_inits, metricnames); + + (void)printf("\nlocks: "); + printb(rtm->rtm_rmx.rmx_locks, metricnames); + (void)printf(" inits: "); + printb(rtm->rtm_inits, metricnames); if (msglen > sizeof(struct rt_msghdr)) pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs, msglen - sizeof(struct rt_msghdr)); else - (void) fflush(stdout); + (void)fflush(stdout); } static void @@ -1790,29 +1786,29 @@ pmsg_addrs(char *cp, int addrs, size_t len) int i; if (addrs == 0) { - (void) putchar('\n'); + (void)putchar('\n'); return; } - (void) printf("\nsockaddrs: "); - bprintf(stdout, addrs, addrnames); - (void) putchar('\n'); + (void)printf("\nsockaddrs: "); + printb(addrs, addrnames); + putchar('\n'); for (i = 1; i != 0; i <<= 1) if (i & addrs) { sa = (struct sockaddr *)cp; if (len == 0 || len < SA_SIZE(sa)) { - (void) printf(errfmt, __func__, len); + (void)printf(errfmt, __func__, len); break; } - (void) printf(" %s", routename(sa)); + (void)printf(" %s", routename(sa)); len -= SA_SIZE(sa); cp += SA_SIZE(sa); } - (void) putchar('\n'); - (void) fflush(stdout); + (void)putchar('\n'); + (void)fflush(stdout); } static void -bprintf(FILE *fp, int b, u_char *str) +printb(int b, const char *str) { int i; int gotsome = 0; @@ -1825,16 +1821,16 @@ bprintf(FILE *fp, int b, u_char *str) i = '<'; else i = ','; - (void) putc(i, fp); + putchar(i); gotsome = 1; for (; (i = *str) > 32; str++) - (void) putc(i, fp); + putchar(i); } else while (*str > 32) str++; } if (gotsome) - (void) putc('>', fp); + putchar('>'); } int @@ -1848,23 +1844,36 @@ keyword(const char *cp) } static void -sodump(sup su, const char *which) +sodump(struct sockaddr *sa, const char *which) { - switch (su->sa.sa_family) { +#ifdef INET6 + char nbuf[INET6_ADDRSTRLEN]; +#endif + + switch (sa->sa_family) { case AF_LINK: - (void) printf("%s: link %s; ", - which, link_ntoa(&su->sdl)); + (void)printf("%s: link %s; ", which, + link_ntoa((struct sockaddr_dl *)sa)); break; +#ifdef INET case AF_INET: - (void) printf("%s: inet %s; ", - which, inet_ntoa(su->sin.sin_addr)); + (void)printf("%s: inet %s; ", which, + inet_ntoa(((struct sockaddr_in *)sa)->sin_addr)); break; +#endif +#ifdef INET6 + case AF_INET6: + (void)printf("%s: inet6 %s; ", which, inet_ntop(sa->sa_family, + &((struct sockaddr_in6 *)sa)->sin6_addr, nbuf, + sizeof(nbuf))); + break; +#endif case AF_APPLETALK: - (void) printf("%s: atalk %s; ", - which, atalk_ntoa(su->sat.sat_addr)); + (void)printf("%s: atalk %s; ", which, + atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); break; } - (void) fflush(stdout); + (void)fflush(stdout); } /* States*/ @@ -1877,10 +1886,9 @@ sodump(sup su, const char *which) #define DELIM (4*2) static void -sockaddr(char *addr, struct sockaddr *sa) +sockaddr(char *addr, struct sockaddr *sa, size_t size) { char *cp = (char *)sa; - int size = sa->sa_len; char *cplim = cp + size; int byte = 0, state = VIRGIN, new = 0 /* foil gcc */; @@ -1936,6 +1944,7 @@ atalk_ntoa(struct at_addr at) { static char buf[20]; - (void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node); + (void)snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node); + buf[sizeof(buf) - 1] = '\0'; return(buf); } -- cgit v1.1 From 96df60d2ef9ce30d58326c976f08e66c0c066c01 Mon Sep 17 00:00:00 2001 From: hrs Date: Wed, 17 Jul 2013 14:15:00 +0000 Subject: Use NET_RT_DUMP.0.FIB leaf node instead of setting td_proc->p_fibnum. --- sbin/route/route.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index 2186482..6e3b257 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -118,7 +118,6 @@ static const char *routename(struct sockaddr *); static int rtmsg(int, int, int); static void set_metric(char *, int); static int set_sofib(int); -static int set_procfib(int); static void sockaddr(char *, struct sockaddr *, size_t); static void sodump(struct sockaddr *, const char *); extern char *iso_ntoa(void); @@ -236,15 +235,6 @@ set_sofib(int fib) } static int -set_procfib(int fib) -{ - - if (fib < 0) - return (0); - return (setfib(fib)); -} - -static int fiboptlist_range(const char *arg, struct fibl_head_t *flh) { struct fibl *fl; @@ -420,11 +410,10 @@ flushroutes_fib(int fib) struct rt_msghdr *rtm; size_t needed; char *buf, *next, *lim; - int mib[6], rlen, seqno, count = 0; + int mib[7], rlen, seqno, count = 0; int error; error = set_sofib(fib); - error += set_procfib(fib); if (error) { warn("fib number %d is ignored", fib); return (error); @@ -437,6 +426,7 @@ retry: mib[3] = AF_UNSPEC; mib[4] = NET_RT_DUMP; mib[5] = 0; /* no flags */ + mib[6] = fib; if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) err(EX_OSERR, "route-sysctl-estimate"); if ((buf = malloc(needed)) == NULL) -- cgit v1.1 From 0af9d56f461ca358ef7ae053c612c45bfc7c7f9e Mon Sep 17 00:00:00 2001 From: rodrigc Date: Wed, 17 Jul 2013 19:32:07 +0000 Subject: In this GRN, Marcel Moolenaar overhauled the logic for mounting the root file system on bootup: |------------------------------------------------------------------------ |r214006 | marcel | 2010-10-17 22:01:53 -0700 (Sun, 17 Oct 2010) | 20 lines | | Re-implement the root mount logic using a recursive approach, whereby each |root file system (starting with devfs and a synthesized configuration) can |contain directives for mounting another file system as root. |------------------------------------------------------------------------ This commit adds a mount.conf(8) man page which documents the root mount logic. mount.conf(8) also provides some examples for the /.mount.conf file, which can be used to change the root mount behavior. Reviewed by: marcel bjk --- sbin/mount/Makefile | 2 +- sbin/mount/mount.conf.8 | 252 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 sbin/mount/mount.conf.8 (limited to 'sbin') diff --git a/sbin/mount/Makefile b/sbin/mount/Makefile index 8f6299a..c4d98f0 100644 --- a/sbin/mount/Makefile +++ b/sbin/mount/Makefile @@ -3,7 +3,7 @@ PROG= mount SRCS= mount.c mount_fs.c getmntopts.c vfslist.c -MAN= mount.8 +MAN= mount.8 mount.conf.8 # We do NOT install the getmntopts.3 man page. DPADD= ${LIBUTIL} diff --git a/sbin/mount/mount.conf.8 b/sbin/mount/mount.conf.8 new file mode 100644 index 0000000..fa9183c --- /dev/null +++ b/sbin/mount/mount.conf.8 @@ -0,0 +1,252 @@ +.\" Copyright (c) 2013 Marcel Moolenaar +.\" Copyright (c) 2013 Craig Rodrigues +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.\" +.Dd July 7, 2013 +.Dt MOUNT.CONF 8 +.Os +.Sh NAME +.Nm mount.conf +.Nd root file system mount configuration file +.Sh SYNOPSIS +.Pa /.mount.conf +.Sh DESCRIPTION +During the bootup process, the +.Fx +kernel will try to mount the root file system +using the logic in the +.Fn vfs_mountroot +function in +.Pa src/sys/kern/vfs_mountroot.c . +The root mount logic can be described as follows: +.Bl -enum +.It +The kernel will synthesize in memory a config file +with default directives for mounting +the root file system. +The logic for this is in +.Fn vfs_mountroot_conf0 . +.It +The kernel will first mount +.Xr devfs 8 +as the root file system. +.It +Next, the kernel will parse the in-memory config file created in step 1 +and try to mount the actual root file system. +See +.Sx FILE FORMAT +for the format of the config file. +.It +When the actual root file system is mounted, +.Xr devfs +will be re-mounted on the +.Pa /dev +directory. +.It +If a +.Pa /.mount.conf +file does not exist in the root file system which was +just mounted, the root mount logic stops here. +.It +If a +.Pa /.mount.conf +file exists in the root file system which was just mounted, +this file will be parsed, and the kernel will use this new config +file to try to re-mount the root file system. +See +.Sx FILE FORMAT +for the format of the config file. +.It +If the new root file system has a +.Pa /.mount +directory, the old root file system will be re-mounted +on +.Pa /.mount . +.It +The root mount logic will go back to step 4. +.El +.Pp +The root mount logic is recursive, and step 8 will +be repeated as long as each new root file system +which is mounted has a +.Pa /.mount.conf +file. +.Sh FILE FORMAT +The kernel parses each line in +.Pa .mount.conf +and then tries to perform the action specified on that line as soon as it is parsed. +.Bl -tag -width "XXXXXXXXXX" +.It Ic # +A line beginning with a # is a comment and is ignored. +.It Ic {FS}:{MOUNTPOINT} {OPTIONS} +The kernel will try to mount this in an +operation equivalent to: +.Bd -literal -offset indent +mount -t {FS} -o {OPTIONS} {MOUNTPOINT} / +.Ed +.Pp +If this is successfully mounted, +further lines in +.Pa .mount.conf +are ignored. +If all lines in +.Pa .mount.conf +have been processed and no root file system has been successfully +mounted, then the action specified by +.Ic .onfail +is performed. +.It Ic .ask +When the kernel processes this line, a +.Li mountroot> +command-line prompt is displayed. +At this prompt, the operator can enter the +the root mount. +.It Ic .md Ar file +Create a memory backed +.Xr md 4 +virtual disk, using +.Ar file +as the backing store. +.It Ic .onfail Ar [panic|reboot|retry|continue] +If after parsing all the lines in +.Pa .mount.conf +the kernel is unable to mount a root file system, +the +.Ic .onfail +directive tells the kernel what action to perform. +.It Ic .timeout Ar N +Before trying to mount a root file system, +if the root mount device does not exist, wait at most +.Ar N +seconds for the device to appear before trying to mount it. +If +.Ic .timeout +is not specified, the default timeout is 3 seconds. +.El +.Sh EXAMPLES +The following example +.Pa .mount.conf +will direct the kernel to try mounting the root file system +first as an ISO CD9660 file system on +.Pa /dev/cd0 , +then if that does not work, as an ISO CD9660 file system on +.Pa /dev/acd0 , +and then if that does not work, as a UFS file system on +.Pa /dev/ada0s1a . +If that does not work, a +.Li mountroot> +command-line prompt will be displayed where the operator +can manually enter the root file system to mount. +Finally if that does not work, the kernel will panic. +.Bd -literal -offset indent +.Li .onfail panic +.LI .timeout 3 +cd9660:/dev/cd0 ro +.Li .timeout 0 +cd9660:/dev/acd0 ro +.Li .timeout 3 +ufs:/dev/ada0s1a +.Li .ask +.Ed +.Pp +The following example +.Pa .mount.conf +will direct the kernel to create a +.Xr md 4 +memory disk attached to the file +.Pa /data/OS-1.0.iso +and then mount the ISO CD9660 file system +on the md device which was just created. +The last line is a comment which is ignored. +.Bd -literal -offset indent +.Li .timeout 3 +.Li .md /data/OS-1.0.iso +.Li cd9600:/dev/md# ro +.Li # Can also use cd9660:/dev/md0 ro +.Ed +.Pp +The following example +.Pa .mount.conf +will direct the kernel to create a +.Xr md 4 +memory disk attached to the file +.Pa /data/base.ufs.uzip +and then mount the UFS file system +on the md uzip device which was just created +by the +.Xr geom_uzip 4 +driver. +.Bd -literal -offset indent +.Li .md /data/base.ufs.uzip +.Li ufs:/dev/md#.uzip ro +.Li # Can also use ufs:/dev/md0.uzip ro +.Ed +.Pp +The following example +.Pa .mount.conf +will direct the kernel to do a unionfs +mount on a directory +.Pa /jail/freebsd-8-stable +which has a +.Xr chroot 2 +environment. +.Bd -literal -offset indent +.Li .timeout 3 +.Li unionfs:/jail/freebsd-8-stable +.Ed +.Sh NOTES +For each root file system which is mounted, a +.Pa /dev +directory +.Em must +exist so that the root mount logic can properly re-mount +.Xr devfs 8 . +If this directory does not exist, the system +may hang during the bootup process. +.Sh SEE ALSO +.Xr boot 8 , +.Xr boot.config 5 , +.Xr fstab 5 , +.Xr loader 8 , +.Xr mount 8 , +.Xr md 4 , +.Xr nmount 2 +.Sh HISTORY +The +.Nm +file first appeared in +.Fx 9.0 . +.Sh AUTHORS +.An -nosplit +The root mount logic in the +.Fx +kernel which parses +.Pa /.mount.conf +was written by +.An Marcel Moolenaar Aq marcel@FreeBSD.org . +This man page was written by +.An Craig Rodrigues Aq rodrigc@FreeBSD.org . -- cgit v1.1 From 6ded7d8bc2691570cfdd7fc32187f20214d14279 Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 17 Jul 2013 23:14:41 +0000 Subject: Always initialize fd to 0 in open_dev(). Sponsored by: Intel Reviewed by: carl MFC after: 3 days --- sbin/nvmecontrol/nvmecontrol.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sbin') diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 63cec3c..826195d 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -166,6 +166,8 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) struct stat devstat; char full_path[64]; + *fd = 0; + if (!strnstr(str, NVME_CTRLR_PREFIX, strlen(NVME_CTRLR_PREFIX))) { if (show_error) warnx("controller/namespace ids must begin with '%s'", -- cgit v1.1 From 8281445679a1a40c3039155ced18766cc7635428 Mon Sep 17 00:00:00 2001 From: jimharris Date: Wed, 17 Jul 2013 23:23:38 +0000 Subject: Define constants for the lengths of the serial number, model number and firmware revision in the controller's identify structure. Also modify consumers of these fields to ensure they only use the specified number of bytes for their respective fields. Sponsored by: Intel Reviewed by: carl MFC after: 3 days --- sbin/nvmecontrol/devlist.c | 2 +- sbin/nvmecontrol/identify.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/devlist.c b/sbin/nvmecontrol/devlist.c index 849b364..46879db 100644 --- a/sbin/nvmecontrol/devlist.c +++ b/sbin/nvmecontrol/devlist.c @@ -89,7 +89,7 @@ devlist(int argc, char *argv[]) found++; read_controller_data(fd, &cdata); - printf("%6s: %s\n", name, cdata.mn); + printf("%6s: %.*s\n", name, NVME_MODEL_NUMBER_LENGTH, cdata.mn); for (i = 0; i < cdata.nn; i++) { sprintf(name, "%s%d%s%d", NVME_CTRLR_PREFIX, ctrlr, diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index 7cc499c..6585430 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -47,9 +47,12 @@ print_controller(struct nvme_controller_data *cdata) printf("================================\n"); printf("Vendor ID: %04x\n", cdata->vid); printf("Subsystem Vendor ID: %04x\n", cdata->ssvid); - printf("Serial Number: %s\n", cdata->sn); - printf("Model Number: %s\n", cdata->mn); - printf("Firmware Version: %s\n", cdata->fr); + printf("Serial Number: %.*s\n", + NVME_SERIAL_NUMBER_LENGTH, cdata->sn); + printf("Model Number: %.*s\n", + NVME_MODEL_NUMBER_LENGTH, cdata->mn); + printf("Firmware Version: %.*s\n", + NVME_FIRMWARE_REVISION_LENGTH, cdata->fr); printf("Recommended Arb Burst: %d\n", cdata->rab); printf("IEEE OUI Identifier: %02x %02x %02x\n", cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]); -- cgit v1.1 From 6ccba3847e97bb18e337664bb2649b134868b172 Mon Sep 17 00:00:00 2001 From: hrs Date: Thu, 18 Jul 2013 02:34:25 +0000 Subject: Fix a gcc warning. Pointy hat to: hrs --- sbin/route/route.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index 6e3b257..b829bd2 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -1457,7 +1457,10 @@ rtmsg(int cmd, int flags, int fib) #define NEXTADDR(w, u) \ if (rtm_addrs & (w)) { \ - l = SA_SIZE((struct sockaddr *)&(u)); \ + l = (((struct sockaddr *)&(u))->sa_len == 0) ? \ + sizeof(long) : \ + 1 + ((((struct sockaddr *)&(u))->sa_len - 1) \ + | (sizeof(long) - 1)); \ memmove(cp, (char *)&(u), l); \ cp += l; \ if (verbose) \ -- cgit v1.1 From 74c92804d73997b872c8a225bc369fc239be4694 Mon Sep 17 00:00:00 2001 From: joel Date: Thu, 18 Jul 2013 05:46:33 +0000 Subject: Minor mdoc fixes. --- sbin/mount/mount.conf.8 | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'sbin') diff --git a/sbin/mount/mount.conf.8 b/sbin/mount/mount.conf.8 index fa9183c..c3296c3 100644 --- a/sbin/mount/mount.conf.8 +++ b/sbin/mount/mount.conf.8 @@ -43,7 +43,7 @@ using the logic in the function in .Pa src/sys/kern/vfs_mountroot.c . The root mount logic can be described as follows: -.Bl -enum +.Bl -enum .It The kernel will synthesize in memory a config file with default directives for mounting @@ -58,7 +58,7 @@ as the root file system. Next, the kernel will parse the in-memory config file created in step 1 and try to mount the actual root file system. See -.Sx FILE FORMAT +.Sx FILE FORMAT for the format of the config file. .It When the actual root file system is mounted, @@ -67,7 +67,7 @@ will be re-mounted on the .Pa /dev directory. .It -If a +If a .Pa /.mount.conf file does not exist in the root file system which was just mounted, the root mount logic stops here. @@ -110,7 +110,7 @@ mount -t {FS} -o {OPTIONS} {MOUNTPOINT} / .Ed .Pp If this is successfully mounted, -further lines in +further lines in .Pa .mount.conf are ignored. If all lines in @@ -164,7 +164,7 @@ can manually enter the root file system to mount. Finally if that does not work, the kernel will panic. .Bd -literal -offset indent .Li .onfail panic -.LI .timeout 3 +.Li .timeout 3 cd9660:/dev/cd0 ro .Li .timeout 0 cd9660:/dev/acd0 ro @@ -211,7 +211,7 @@ The following example will direct the kernel to do a unionfs mount on a directory .Pa /jail/freebsd-8-stable -which has a +which has a .Xr chroot 2 environment. .Bd -literal -offset indent @@ -228,13 +228,13 @@ exist so that the root mount logic can properly re-mount If this directory does not exist, the system may hang during the bootup process. .Sh SEE ALSO -.Xr boot 8 , +.Xr nmount 2 , +.Xr md 4 , .Xr boot.config 5 , .Xr fstab 5 , +.Xr boot 8 , .Xr loader 8 , -.Xr mount 8 , -.Xr md 4 , -.Xr nmount 2 +.Xr mount 8 .Sh HISTORY The .Nm -- cgit v1.1 From 3e18e4fbf6a97737356dbbed8ef7bbdb2e644b0b Mon Sep 17 00:00:00 2001 From: jimharris Date: Thu, 18 Jul 2013 23:12:44 +0000 Subject: Simplify open_dev() by returning errno values rather than just 0 or 1. Also remove stat() call and just rely on errno from open() call to discern whether dev node exists or not. Sponsored by: Intel Reviewed by: kib, carl MFC after: 3 days --- sbin/nvmecontrol/devlist.c | 3 ++- sbin/nvmecontrol/nvmecontrol.c | 16 ++-------------- 2 files changed, 4 insertions(+), 15 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/devlist.c b/sbin/nvmecontrol/devlist.c index 46879db..2a95832 100644 --- a/sbin/nvmecontrol/devlist.c +++ b/sbin/nvmecontrol/devlist.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -80,7 +81,7 @@ devlist(int argc, char *argv[]) ret = open_dev(name, &fd, 0, 0); if (ret != 0) { - if (fd < 0) { + if (ret == EACCES) { warnx("could not open /dev/%s\n", name); continue; } else diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 826195d..333bb62 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -163,11 +163,8 @@ read_namespace_data(int fd, int nsid, struct nvme_namespace_data *nsdata) int open_dev(const char *str, int *fd, int show_error, int exit_on_error) { - struct stat devstat; char full_path[64]; - *fd = 0; - if (!strnstr(str, NVME_CTRLR_PREFIX, strlen(NVME_CTRLR_PREFIX))) { if (show_error) warnx("controller/namespace ids must begin with '%s'", @@ -175,19 +172,10 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) if (exit_on_error) exit(1); else - return (1); + return (EINVAL); } snprintf(full_path, sizeof(full_path), "/dev/%s", str); - if (stat(full_path, &devstat) != 0) { - if (show_error) - warn("could not stat %s", full_path); - if (exit_on_error) - exit(1); - else - return (1); - } - *fd = open(full_path, O_RDWR); if (*fd < 0) { if (show_error) @@ -195,7 +183,7 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) if (exit_on_error) exit(1); else - return (1); + return (errno); } return (0); -- cgit v1.1 From 1b0750b86c77afe56bc851b72ab13a0d7536d066 Mon Sep 17 00:00:00 2001 From: jimharris Date: Thu, 18 Jul 2013 23:25:57 +0000 Subject: Use _PATH_DEV (from paths.h) for the "/dev/" string, rather than hard-coding it. Sponsored by: Intel Suggested by: kib Reviewed by: kib, carl MFC after: 3 days --- sbin/nvmecontrol/devlist.c | 3 ++- sbin/nvmecontrol/nvmecontrol.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/devlist.c b/sbin/nvmecontrol/devlist.c index 2a95832..29c0475 100644 --- a/sbin/nvmecontrol/devlist.c +++ b/sbin/nvmecontrol/devlist.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -82,7 +83,7 @@ devlist(int argc, char *argv[]) if (ret != 0) { if (ret == EACCES) { - warnx("could not open /dev/%s\n", name); + warnx("could not open "_PATH_DEV"%s\n", name); continue; } else break; diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c index 333bb62..4dee190 100644 --- a/sbin/nvmecontrol/nvmecontrol.c +++ b/sbin/nvmecontrol/nvmecontrol.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -175,7 +176,7 @@ open_dev(const char *str, int *fd, int show_error, int exit_on_error) return (EINVAL); } - snprintf(full_path, sizeof(full_path), "/dev/%s", str); + snprintf(full_path, sizeof(full_path), _PATH_DEV"%s", str); *fd = open(full_path, O_RDWR); if (*fd < 0) { if (show_error) -- cgit v1.1 From c3dfb166eeb405887a8fbe7666d2436133a39c0b Mon Sep 17 00:00:00 2001 From: jimharris Date: Fri, 19 Jul 2013 21:33:24 +0000 Subject: Fix nvme(4) and nvd(4) to support non 512-byte sector sizes. Recent testing with QEMU that has variable sector size support for NVMe uncovered some of these issues. Chatham prototype boards supported only 512 byte sectors. Sponsored by: Intel Reviewed by: carl MFC after: 3 days --- sbin/nvmecontrol/devlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/devlist.c b/sbin/nvmecontrol/devlist.c index 29c0475..eb40434 100644 --- a/sbin/nvmecontrol/devlist.c +++ b/sbin/nvmecontrol/devlist.c @@ -53,7 +53,7 @@ static inline uint32_t ns_get_sector_size(struct nvme_namespace_data *nsdata) { - return (1 << nsdata->lbaf[0].lbads); + return (1 << nsdata->lbaf[nsdata->flbas.format].lbads); } void -- cgit v1.1 From 52bfa150c78aa1855a2cc5fccfc5beb84f57b16d Mon Sep 17 00:00:00 2001 From: jimharris Date: Fri, 19 Jul 2013 21:40:57 +0000 Subject: Add message when nvd disks are attached and detached. As part of this commit, add an nvme_strvis() function which borrows heavily from cam_strvis(). This will allow stripping of leading/trailing whitespace and also handle unprintable characters in model/serial numbers. This function goes into a new nvme_util.c file which is used by both the driver and nvmecontrol. Sponsored by: Intel Reviewed by: carl MFC after: 3 days --- sbin/nvmecontrol/Makefile | 4 +++- sbin/nvmecontrol/devlist.c | 4 +++- sbin/nvmecontrol/identify.c | 14 ++++++++------ 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'sbin') diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile index 4682056..ea60da3 100644 --- a/sbin/nvmecontrol/Makefile +++ b/sbin/nvmecontrol/Makefile @@ -2,7 +2,9 @@ PROG= nvmecontrol SRCS= nvmecontrol.c devlist.c firmware.c identify.c logpage.c \ - perftest.c reset.c + perftest.c reset.c nvme_util.c MAN= nvmecontrol.8 +.PATH: ${.CURDIR}/../../sys/dev/nvme + .include diff --git a/sbin/nvmecontrol/devlist.c b/sbin/nvmecontrol/devlist.c index eb40434..f73d643 100644 --- a/sbin/nvmecontrol/devlist.c +++ b/sbin/nvmecontrol/devlist.c @@ -62,6 +62,7 @@ devlist(int argc, char *argv[]) struct nvme_controller_data cdata; struct nvme_namespace_data nsdata; char name[64]; + uint8_t mn[64]; uint32_t i; int ch, ctrlr, fd, found, ret; @@ -91,7 +92,8 @@ devlist(int argc, char *argv[]) found++; read_controller_data(fd, &cdata); - printf("%6s: %.*s\n", name, NVME_MODEL_NUMBER_LENGTH, cdata.mn); + nvme_strvis(mn, cdata.mn, sizeof(mn), NVME_MODEL_NUMBER_LENGTH); + printf("%6s: %s\n", name, mn); for (i = 0; i < cdata.nn; i++) { sprintf(name, "%s%d%s%d", NVME_CTRLR_PREFIX, ctrlr, diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index 6585430..58492e2 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -43,16 +43,18 @@ __FBSDID("$FreeBSD$"); static void print_controller(struct nvme_controller_data *cdata) { + uint8_t str[128]; + printf("Controller Capabilities/Features\n"); printf("================================\n"); printf("Vendor ID: %04x\n", cdata->vid); printf("Subsystem Vendor ID: %04x\n", cdata->ssvid); - printf("Serial Number: %.*s\n", - NVME_SERIAL_NUMBER_LENGTH, cdata->sn); - printf("Model Number: %.*s\n", - NVME_MODEL_NUMBER_LENGTH, cdata->mn); - printf("Firmware Version: %.*s\n", - NVME_FIRMWARE_REVISION_LENGTH, cdata->fr); + nvme_strvis(str, cdata->sn, sizeof(str), NVME_SERIAL_NUMBER_LENGTH); + printf("Serial Number: %s\n", str); + nvme_strvis(str, cdata->mn, sizeof(str), NVME_MODEL_NUMBER_LENGTH); + printf("Model Number: %s\n", str); + nvme_strvis(str, cdata->fr, sizeof(str), NVME_FIRMWARE_REVISION_LENGTH); + printf("Firmware Version: %s\n", str); printf("Recommended Arb Burst: %d\n", cdata->rab); printf("IEEE OUI Identifier: %02x %02x %02x\n", cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]); -- cgit v1.1 From 9a338a2bf532e8fa6b584e77b88d6fc1ac9358c2 Mon Sep 17 00:00:00 2001 From: hrs Date: Sat, 20 Jul 2013 15:23:42 +0000 Subject: Add cast to (void *) to the following cases to suppress warnings by -Wcast-align. These do not increase the alignment requirement: - rtm = (struct rt_msghdr *)(rtm + rtm->rtm_msglen) - struct sockaddr *sa = &sa0; sX = (struct sockaddr_X *)sa --- sbin/route/route.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index b829bd2..4e218b4 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -445,7 +445,7 @@ retry: (void)printf("Examining routing table from sysctl\n"); seqno = 0; /* ??? */ for (next = buf; next < lim; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)next; + rtm = (struct rt_msghdr *)(void *)next; if (verbose) print_rtmsg(rtm, rtm->rtm_msglen); if ((rtm->rtm_flags & RTF_GATEWAY) == 0) @@ -521,7 +521,7 @@ routename(struct sockaddr *sa) { struct in_addr in; - in = ((struct sockaddr_in *)sa)->sin_addr; + in = ((struct sockaddr_in *)(void *)sa)->sin_addr; cp = NULL; if (in.s_addr == INADDR_ANY || sa->sa_len < 4) cp = "default"; @@ -568,16 +568,16 @@ routename(struct sockaddr *sa) case AF_APPLETALK: (void)snprintf(line, sizeof(line), "atalk %s", - atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); + atalk_ntoa(((struct sockaddr_at *)(void *)sa)->sat_addr)); break; case AF_LINK: - return (link_ntoa((struct sockaddr_dl *)sa)); + return (link_ntoa((struct sockaddr_dl *)(void *)sa)); break; default: { - u_short *sp = (u_short *)sa; + u_short *sp = (u_short *)(void *)sa; u_short *splim = sp + ((sa->sa_len + 1) >> 1); char *cps = line + sprintf(line, "(%d)", sa->sa_family); char *cpe = line + sizeof(line); @@ -614,7 +614,7 @@ netname(struct sockaddr *sa) { struct in_addr in; - in = ((struct sockaddr_in *)sa)->sin_addr; + in = ((struct sockaddr_in *)(void *)sa)->sin_addr; i = in.s_addr = ntohl(in.s_addr); if (in.s_addr == 0) cp = "default"; @@ -664,16 +664,16 @@ netname(struct sockaddr *sa) case AF_APPLETALK: (void)snprintf(line, sizeof(line), "atalk %s", - atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); + atalk_ntoa(((struct sockaddr_at *)(void *)sa)->sat_addr)); break; case AF_LINK: - return (link_ntoa((struct sockaddr_dl *)sa)); + return (link_ntoa((struct sockaddr_dl *)(void *)sa)); break; default: { - u_short *sp = (u_short *)sa->sa_data; + u_short *sp = (u_short *)(void *)sa->sa_data; u_short *splim = sp + ((sa->sa_len + 1)>>1); char *cps = line + sprintf(line, "af %d:", sa->sa_family); char *cpe = line + sizeof(line); @@ -1160,7 +1160,7 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) case RTA_GATEWAY: if (nrflags & F_INTERFACE) { struct ifaddrs *ifap, *ifa; - struct sockaddr_dl *sdl0 = (struct sockaddr_dl *)sa; + struct sockaddr_dl *sdl0 = (struct sockaddr_dl *)(void *)sa; struct sockaddr_dl *sdl = NULL; if (getifaddrs(&ifap)) @@ -1173,7 +1173,7 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) if (strcmp(str, ifa->ifa_name) != 0) continue; - sdl = (struct sockaddr_dl *)ifa->ifa_addr; + sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr; } /* If we found it, then use it */ if (sdl != NULL) { @@ -1226,15 +1226,14 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) if (q != NULL) *q++ = '/'; if (which == RTA_DST) - return (inet6_makenetandmask((struct sockaddr_in6 *)sa, - q)); + return (inet6_makenetandmask((struct sockaddr_in6 *)(void *)sa, q)); return (0); } #endif /* INET6 */ case AF_APPLETALK: { - struct sockaddr_at *sat = (struct sockaddr_at *)sa; + struct sockaddr_at *sat = (struct sockaddr_at *)(void *)sa; if (!atalk_aton(str, &sat->sat_addr)) errx(EX_NOHOST, "bad address: %s", str); @@ -1242,7 +1241,7 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) return(forcehost || sat->sat_addr.s_node != 0); } case AF_LINK: - link_addr(str, (struct sockaddr_dl *)sa); + link_addr(str, (struct sockaddr_dl *)(void *)sa); return (1); case PF_ROUTE: @@ -1256,7 +1255,7 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) } #ifdef INET - sin = (struct sockaddr_in *)sa; + sin = (struct sockaddr_in *)(void *)sa; if (hpp == NULL) hpp = &hp; *hpp = NULL; @@ -1388,7 +1387,7 @@ retry2: } lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { - rtm = (struct rt_msghdr *)next; + rtm = (struct rt_msghdr *)(void *)next; print_rtmsg(rtm, rtm->rtm_msglen); } } @@ -1438,7 +1437,7 @@ monitor(int argc, char *argv[]) n = read(s, msg, 2048); now = time(NULL); (void)printf("\ngot message of size %d on %s", n, ctime(&now)); - print_rtmsg((struct rt_msghdr *)msg, n); + print_rtmsg((struct rt_msghdr *)(void *)msg, n); } } @@ -1703,8 +1702,8 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) break; case RTA_IFP: if (sa->sa_family == AF_LINK && - ((struct sockaddr_dl *)sa)->sdl_nlen) - ifp = (struct sockaddr_dl *)sa; + ((struct sockaddr_dl *)(void *)sa)->sdl_nlen) + ifp = (struct sockaddr_dl *)(void *)sa; break; } cp += SA_SIZE(sa); @@ -1846,24 +1845,24 @@ sodump(struct sockaddr *sa, const char *which) switch (sa->sa_family) { case AF_LINK: (void)printf("%s: link %s; ", which, - link_ntoa((struct sockaddr_dl *)sa)); + link_ntoa((struct sockaddr_dl *)(void *)sa)); break; #ifdef INET case AF_INET: (void)printf("%s: inet %s; ", which, - inet_ntoa(((struct sockaddr_in *)sa)->sin_addr)); + inet_ntoa(((struct sockaddr_in *)(void *)sa)->sin_addr)); break; #endif #ifdef INET6 case AF_INET6: (void)printf("%s: inet6 %s; ", which, inet_ntop(sa->sa_family, - &((struct sockaddr_in6 *)sa)->sin6_addr, nbuf, + &((struct sockaddr_in6 *)(void *)sa)->sin6_addr, nbuf, sizeof(nbuf))); break; #endif case AF_APPLETALK: (void)printf("%s: atalk %s; ", which, - atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); + atalk_ntoa(((struct sockaddr_at *)(void *)sa)->sat_addr)); break; } (void)fflush(stdout); -- cgit v1.1 From 8b427c6ea9843f49e51ad12fa613e19c11a3a805 Mon Sep 17 00:00:00 2001 From: hrs Date: Sat, 20 Jul 2013 15:58:43 +0000 Subject: Show "default" for the zero-filled address consistently when nflag == 0. --- sbin/route/route.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index 4e218b4..6da4deb 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -511,10 +511,8 @@ routename(struct sockaddr *sa) domain[0] = '\0'; } - if (sa->sa_len == 0) { - strcpy(line, "default"); - return (line); - } + if (sa->sa_len == 0 && nflag == 0) + return ("default"); switch (sa->sa_family) { #ifdef INET case AF_INET: @@ -523,9 +521,9 @@ routename(struct sockaddr *sa) in = ((struct sockaddr_in *)(void *)sa)->sin_addr; cp = NULL; - if (in.s_addr == INADDR_ANY || sa->sa_len < 4) - cp = "default"; - if (cp == NULL && !nflag) { + if (in.s_addr == INADDR_ANY && nflag == 0) + return ("default"); + if (nflag != 0) { hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), AF_INET); if (hp != NULL) { @@ -552,6 +550,10 @@ routename(struct sockaddr *sa) struct sockaddr_in6 sin6; /* use static var for safety */ int niflags = 0; + /* Check if the address is ::. If true, use "default". */ + if (nflag == 0 && + IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(void *)sa)->sin6_addr)) + return("default"); memset(&sin6, 0, sizeof(sin6)); memcpy(&sin6, sa, sa->sa_len); sin6.sin6_len = sizeof(struct sockaddr_in6); @@ -1712,13 +1714,8 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) mask->sa_family = dst->sa_family; /* XXX */ if (dst) (void)printf("destination: %s\n", routename(dst)); - if (mask) { - int savenflag = nflag; - - nflag = 1; + if (mask) (void)printf(" mask: %s\n", routename(mask)); - nflag = savenflag; - } if (gate && rtm->rtm_flags & RTF_GATEWAY) (void)printf(" gateway: %s\n", routename(gate)); if (fib >= 0) -- cgit v1.1 From cdafd4ecfd87de54cc7a0c3e20f229603df4dc92 Mon Sep 17 00:00:00 2001 From: hrs Date: Sat, 20 Jul 2013 16:46:51 +0000 Subject: - Simplify getaddr() and print_getmsg() by using RTAX_* instead of RTA_* as the argument. - Reduce unnecessary loop in print_getmsg(). --- sbin/route/route.c | 128 ++++++++++++++++++++--------------------------------- 1 file changed, 48 insertions(+), 80 deletions(-) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index 6da4deb..672838e 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -825,35 +825,35 @@ newroute(int argc, char **argv) case K_IFA: if (!--argc) usage(NULL); - getaddr(RTA_IFA, *++argv, 0, nrflags); + getaddr(RTAX_IFA, *++argv, 0, nrflags); break; case K_IFP: if (!--argc) usage(NULL); - getaddr(RTA_IFP, *++argv, 0, nrflags); + getaddr(RTAX_IFP, *++argv, 0, nrflags); break; case K_GENMASK: if (!--argc) usage(NULL); - getaddr(RTA_GENMASK, *++argv, 0, nrflags); + getaddr(RTAX_GENMASK, *++argv, 0, nrflags); break; case K_GATEWAY: if (!--argc) usage(NULL); - getaddr(RTA_GATEWAY, *++argv, 0, nrflags); + getaddr(RTAX_GATEWAY, *++argv, 0, nrflags); gateway = *argv; break; case K_DST: if (!--argc) usage(NULL); - if (getaddr(RTA_DST, *++argv, &hp, nrflags)) + if (getaddr(RTAX_DST, *++argv, &hp, nrflags)) nrflags |= F_ISHOST; dest = *argv; break; case K_NETMASK: if (!--argc) usage(NULL); - getaddr(RTA_NETMASK, *++argv, 0, nrflags); + getaddr(RTAX_NETMASK, *++argv, 0, nrflags); /* FALLTHROUGH */ case K_NET: nrflags |= F_FORCENET; @@ -888,13 +888,13 @@ newroute(int argc, char **argv) } else { if ((rtm_addrs & RTA_DST) == 0) { dest = *argv; - if (getaddr(RTA_DST, *argv, &hp, nrflags)) + if (getaddr(RTAX_DST, *argv, &hp, nrflags)) nrflags |= F_ISHOST; } else if ((rtm_addrs & RTA_GATEWAY) == 0) { gateway = *argv; - getaddr(RTA_GATEWAY, *argv, &hp, nrflags); + getaddr(RTAX_GATEWAY, *argv, &hp, nrflags); } else { - getaddr(RTA_NETMASK, *argv, 0, nrflags); + getaddr(RTAX_NETMASK, *argv, 0, nrflags); nrflags |= F_FORCENET; } } @@ -1105,7 +1105,7 @@ inet6_makenetandmask(struct sockaddr_in6 *sin6, const char *plen) * returning 1 if a host address, 0 if a network address. */ static int -getaddr(int which, char *str, struct hostent **hpp, int nrflags) +getaddr(int idx, char *str, struct hostent **hpp, int nrflags) { struct sockaddr *sa; #if defined(INET) @@ -1130,36 +1130,16 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) aflen = sizeof(struct sockaddr_dl); #endif } - rtm_addrs |= which; + rtm_addrs |= (1 << idx); - switch (which) { - case RTA_DST: - sa = (struct sockaddr *)&so[RTAX_DST]; - break; - case RTA_GATEWAY: - sa = (struct sockaddr *)&so[RTAX_GATEWAY]; - break; - case RTA_NETMASK: - sa = (struct sockaddr *)&so[RTAX_NETMASK]; - break; - case RTA_GENMASK: - sa = (struct sockaddr *)&so[RTAX_GENMASK]; - break; - case RTA_IFA: - sa = (struct sockaddr *)&so[RTAX_IFA]; - break; - case RTA_IFP: - sa = (struct sockaddr *)&so[RTAX_IFP]; - break; - default: + if (idx > RTAX_MAX) usage("internal error"); - /*NOTREACHED*/ - } + sa = (struct sockaddr *)&so[idx]; sa->sa_family = af; sa->sa_len = aflen; - switch (which) { - case RTA_GATEWAY: + switch (idx) { + case RTAX_GATEWAY: if (nrflags & F_INTERFACE) { struct ifaddrs *ifap, *ifa; struct sockaddr_dl *sdl0 = (struct sockaddr_dl *)(void *)sa; @@ -1190,7 +1170,7 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) return(1); } break; - case RTA_IFP: + case RTAX_IFP: sa->sa_family = AF_LINK; break; } @@ -1198,10 +1178,10 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) /* * Default is net 0.0.0.0/0 */ - switch (which) { - case RTA_DST: + switch (idx) { + case RTAX_DST: forcenet++; - getaddr(RTA_NETMASK, str, 0, nrflags); + getaddr(RTAX_NETMASK, str, 0, nrflags); break; } return (0); @@ -1214,7 +1194,7 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) int ecode; q = NULL; - if (which == RTA_DST && (q = strchr(str, '/')) != NULL) + if (idx == RTAX_DST && (q = strchr(str, '/')) != NULL) *q = '\0'; memset(&hints, 0, sizeof(hints)); hints.ai_family = sa->sa_family; @@ -1227,7 +1207,7 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) freeaddrinfo(res); if (q != NULL) *q++ = '/'; - if (which == RTA_DST) + if (idx == RTAX_DST) return (inet6_makenetandmask((struct sockaddr_in6 *)(void *)sa, q)); return (0); } @@ -1263,7 +1243,7 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) *hpp = NULL; q = strchr(str,'/'); - if (q != NULL && which == RTA_DST) { + if (q != NULL && idx == RTAX_DST) { *q = '\0'; if ((val = inet_network(str)) != INADDR_NONE) { inet_makenetandmask(val, sin, @@ -1273,10 +1253,10 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) } *q = '/'; } - if ((which != RTA_DST || forcenet == 0) && + if ((idx != RTAX_DST || forcenet == 0) && inet_aton(str, &sin->sin_addr)) { val = sin->sin_addr.s_addr; - if (which != RTA_DST || forcehost || + if (idx != RTAX_DST || forcehost || inet_lnaof(sin->sin_addr) != INADDR_ANY) return (1); else { @@ -1284,7 +1264,7 @@ getaddr(int which, char *str, struct hostent **hpp, int nrflags) goto netdone; } } - if (which == RTA_DST && forcehost == 0 && + if (idx == RTAX_DST && forcehost == 0 && ((val = inet_network(str)) != INADDR_NONE || ((np = getnetbyname(str)) != NULL && (val = np->n_net) != 0))) { netdone: @@ -1665,12 +1645,11 @@ badlen: static void print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) { - struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL; - struct sockaddr_dl *ifp = NULL; - struct sockaddr *sa; + struct sockaddr *sp[RTAX_MAX]; char *cp; int i; + memset(sp, 0, sizeof(sp)); (void)printf(" route to: %s\n", routename((struct sockaddr *)&so[RTAX_DST])); if (rtm->rtm_version != RTM_VERSION) { @@ -1688,41 +1667,30 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) return; } cp = ((char *)(rtm + 1)); - if (rtm->rtm_addrs) - for (i = 1; i; i <<= 1) - if (i & rtm->rtm_addrs) { - sa = (struct sockaddr *)cp; - switch (i) { - case RTA_DST: - dst = sa; - break; - case RTA_GATEWAY: - gate = sa; - break; - case RTA_NETMASK: - mask = sa; - break; - case RTA_IFP: - if (sa->sa_family == AF_LINK && - ((struct sockaddr_dl *)(void *)sa)->sdl_nlen) - ifp = (struct sockaddr_dl *)(void *)sa; - break; - } - cp += SA_SIZE(sa); - } - if (dst && mask) - mask->sa_family = dst->sa_family; /* XXX */ - if (dst) - (void)printf("destination: %s\n", routename(dst)); - if (mask) - (void)printf(" mask: %s\n", routename(mask)); - if (gate && rtm->rtm_flags & RTF_GATEWAY) - (void)printf(" gateway: %s\n", routename(gate)); + for (i = 0; i < RTAX_MAX; i++) { + if (rtm->rtm_addrs & (1 << i)) + sp[i] = (struct sockaddr *)cp; + cp += SA_SIZE((struct sockaddr *)cp); + } + if (rtm->rtm_addrs & RTA_IFP) { + if (sp[RTAX_IFP]->sa_family != AF_LINK || + ((struct sockaddr_dl *)(void *)sp[RTAX_IFP])->sdl_nlen == 0) + sp[RTAX_IFP] = NULL; + } + if (sp[RTAX_DST] && sp[RTAX_NETMASK]) + sp[RTAX_NETMASK]->sa_family = sp[RTAX_DST]->sa_family; /* XXX */ + if (sp[RTAX_DST]) + (void)printf("destination: %s\n", routename(sp[RTAX_DST])); + if (sp[RTAX_NETMASK]) + (void)printf(" mask: %s\n", routename(sp[RTAX_NETMASK])); + if (sp[RTAX_GATEWAY] && (rtm->rtm_flags & RTF_GATEWAY)) + (void)printf(" gateway: %s\n", routename(sp[RTAX_GATEWAY])); if (fib >= 0) (void)printf(" fib: %u\n", (unsigned int)fib); - if (ifp) + if (sp[RTAX_IFP]) (void)printf(" interface: %.*s\n", - ifp->sdl_nlen, ifp->sdl_data); + ((struct sockaddr_dl *)(void *)sp[RTAX_IFP])->sdl_nlen, + ((struct sockaddr_dl *)(void *)sp[RTAX_IFP])->sdl_data); (void)printf(" flags: "); printb(rtm->rtm_flags, routeflags); -- cgit v1.1 From f9052e5539810cb72cf7a43461e9c6b3653662b7 Mon Sep 17 00:00:00 2001 From: hrs Date: Sun, 21 Jul 2013 11:59:41 +0000 Subject: - Fix nflag in routename(). - Display a AF_LINK address in #linkN when sdl_{nlen,alen,slen) == 0 and sdl_index != 0. - Reduce unnecessary loop in pmsg_addrs(). - Remove iso_ntoa(). This is not used. --- sbin/route/route.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index 672838e..9d3ba94 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -120,7 +120,6 @@ static void set_metric(char *, int); static int set_sofib(int); static void sockaddr(char *, struct sockaddr *, size_t); static void sodump(struct sockaddr *, const char *); -extern char *iso_ntoa(void); struct fibl { TAILQ_ENTRY(fibl) fl_next; @@ -493,6 +492,7 @@ retry: const char * routename(struct sockaddr *sa) { + struct sockaddr_dl *sdl; const char *cp; static char line[MAXHOSTNAMELEN + 1]; #ifdef INET @@ -523,7 +523,7 @@ routename(struct sockaddr *sa) cp = NULL; if (in.s_addr == INADDR_ANY && nflag == 0) return ("default"); - if (nflag != 0) { + if (nflag == 0) { hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), AF_INET); if (hp != NULL) { @@ -574,7 +574,18 @@ routename(struct sockaddr *sa) break; case AF_LINK: - return (link_ntoa((struct sockaddr_dl *)(void *)sa)); + sdl = (struct sockaddr_dl *)(void *)sa; + + if (sdl->sdl_nlen == 0 && + sdl->sdl_alen == 0 && + sdl->sdl_slen == 0) { + n = snprintf(line, sizeof(line), "link#%d", + sdl->sdl_index); + if (n > (int)sizeof(line)) + line[0] = '\0'; + return (line); + } else + return (link_ntoa(sdl)); break; default: @@ -602,6 +613,7 @@ routename(struct sockaddr *sa) const char * netname(struct sockaddr *sa) { + struct sockaddr_dl *sdl; static char line[MAXHOSTNAMELEN + 1]; int n; #ifdef INET @@ -670,7 +682,18 @@ netname(struct sockaddr *sa) break; case AF_LINK: - return (link_ntoa((struct sockaddr_dl *)(void *)sa)); + sdl = (struct sockaddr_dl *)(void *)sa; + + if (sdl->sdl_nlen == 0 && + sdl->sdl_alen == 0 && + sdl->sdl_slen == 0) { + n = snprintf(line, sizeof(line), "link#%d", + sdl->sdl_index); + if (n > (int)sizeof(line)) + line[0] = '\0'; + return (line); + } else + return (link_ntoa(sdl)); break; default: @@ -1560,7 +1583,7 @@ print_rtmsg(struct rt_msghdr *rtm, size_t msglen) rtm->rtm_version); return; } - if (rtm->rtm_type < sizeof(msgtypes) / sizeof(msgtypes[0])) + if (rtm->rtm_type < nitems(msgtypes)) (void)printf("%s: ", msgtypes[rtm->rtm_type]); else (void)printf("unknown type %d: ", rtm->rtm_type); @@ -1660,6 +1683,7 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) if (rtm->rtm_msglen > msglen) { warnx("message length mismatch, in packet %d, returned %d", rtm->rtm_msglen, msglen); + return; } if (rtm->rtm_errno) { errno = rtm->rtm_errno; @@ -1696,9 +1720,8 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) #define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') #define msec(u) (((u) + 500) / 1000) /* usec to msec */ - - printf("\n%s\n", "\ - recvpipe sendpipe ssthresh rtt,msec mtu weight expire"); + printf("\n%9s %9s %9s %9s %9s %10s %9s\n", "recvpipe", + "sendpipe", "ssthresh", "rtt,msec", "mtu ", "weight", "expire"); printf("%8ld%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE)); printf("%8ld%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE)); printf("%8ld%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH)); @@ -1749,8 +1772,8 @@ pmsg_addrs(char *cp, int addrs, size_t len) (void)printf("\nsockaddrs: "); printb(addrs, addrnames); putchar('\n'); - for (i = 1; i != 0; i <<= 1) - if (i & addrs) { + for (i = 0; i < RTAX_MAX; i++) + if (addrs & (1 << i)) { sa = (struct sockaddr *)cp; if (len == 0 || len < SA_SIZE(sa)) { (void)printf(errfmt, __func__, len); -- cgit v1.1 From 9aa295ffbf98b8fc9802c7611e5f0f999a17dd57 Mon Sep 17 00:00:00 2001 From: hrs Date: Sun, 21 Jul 2013 14:27:07 +0000 Subject: - Use getnameinfo() for both of AF_INET and AF_INET6 in routename(). - Add missing "static". --- sbin/route/route.c | 100 +++++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 46 deletions(-) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index 9d3ba94..6bfca13 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -135,7 +135,7 @@ static int fiboptlist_range(const char *, struct fibl_head_t *); static void usage(const char *) __dead2; -void +static void usage(const char *cp) { if (cp != NULL) @@ -489,15 +489,12 @@ retry: return (error); } -const char * +static const char * routename(struct sockaddr *sa) { struct sockaddr_dl *sdl; const char *cp; - static char line[MAXHOSTNAMELEN + 1]; -#ifdef INET - struct hostent *hp; -#endif + static char line[NI_MAXHOST]; static char domain[MAXHOSTNAMELEN + 1]; static int first = 1, n; @@ -511,63 +508,71 @@ routename(struct sockaddr *sa) domain[0] = '\0'; } + /* If the address is zero-filled, use "default". */ if (sa->sa_len == 0 && nflag == 0) return ("default"); +#if defined(INET) || defined(INET6) switch (sa->sa_family) { #ifdef INET case AF_INET: - { - struct in_addr in; - - in = ((struct sockaddr_in *)(void *)sa)->sin_addr; - cp = NULL; - if (in.s_addr == INADDR_ANY && nflag == 0) - return ("default"); - if (nflag == 0) { - hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), - AF_INET); - if (hp != NULL) { - char *cptr; - cptr = strchr(hp->h_name, '.'); - if (cptr != NULL && - strcmp(cptr + 1, domain) == 0) - *cptr = '\0'; - cp = hp->h_name; - } - } - if (cp != NULL) { - strncpy(line, cp, sizeof(line) - 1); - line[sizeof(line) - 1] = '\0'; - } else - (void)sprintf(line, "%s", inet_ntoa(in)); + /* If the address is zero-filled, use "default". */ + if (nflag == 0 && + ((struct sockaddr_in *)(void *)sa)->sin_addr.s_addr == + INADDR_ANY) + return("default"); break; +#endif +#ifdef INET6 + case AF_INET6: + /* If the address is zero-filled, use "default". */ + if (nflag == 0 && + IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(void *)sa)->sin6_addr)) + return("default"); + break; +#endif } +#endif + switch (sa->sa_family) { +#if defined(INET) || defined(INET6) +#ifdef INET + case AF_INET: #endif #ifdef INET6 case AF_INET6: +#endif { - struct sockaddr_in6 sin6; /* use static var for safety */ - int niflags = 0; + struct sockaddr_storage ss; + int error; + char *p; - /* Check if the address is ::. If true, use "default". */ - if (nflag == 0 && - IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(void *)sa)->sin6_addr)) - return("default"); - memset(&sin6, 0, sizeof(sin6)); - memcpy(&sin6, sa, sa->sa_len); - sin6.sin6_len = sizeof(struct sockaddr_in6); - sin6.sin6_family = AF_INET6; - if (nflag) - niflags |= NI_NUMERICHOST; - if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, - line, sizeof(line), NULL, 0, niflags) != 0) + memset(&ss, 0, sizeof(ss)); + if (sa->sa_len == 0) + ss.ss_family = sa->sa_family; + else + memcpy(&ss, sa, sa->sa_len); + /* Expand sa->sa_len because it could be shortened. */ + if (sa->sa_family == AF_INET) + ss.ss_len = sizeof(struct sockaddr_in); + else if (sa->sa_family == AF_INET6) + ss.ss_len = sizeof(struct sockaddr_in6); + error = getnameinfo((struct sockaddr *)&ss, ss.ss_len, + line, sizeof(line), NULL, 0, + (nflag == 0) ? 0 : NI_NUMERICHOST); + if (error) { + warnx("getnameinfo(): %s", gai_strerror(error)); strncpy(line, "invalid", sizeof(line)); + } + + /* Remove the domain part if any. */ + p = strchr(line, '.'); + if (p != NULL && strcmp(p + 1, domain) == 0) + *p = '\0'; return (line); + break; } #endif - case AF_APPLETALK: (void)snprintf(line, sizeof(line), "atalk %s", atalk_ntoa(((struct sockaddr_at *)(void *)sa)->sat_addr)); @@ -610,7 +615,7 @@ routename(struct sockaddr *sa) * Return the name of the network whose address is given. * The address is assumed to be that of a net, not a host. */ -const char * +static const char * netname(struct sockaddr *sa) { struct sockaddr_dl *sdl; @@ -1153,6 +1158,9 @@ getaddr(int idx, char *str, struct hostent **hpp, int nrflags) aflen = sizeof(struct sockaddr_dl); #endif } +#ifndef INET + hpp = NULL; +#endif rtm_addrs |= (1 << idx); if (idx > RTAX_MAX) -- cgit v1.1 From 88d161491f8f0902491f8df563668a7f3524d4f7 Mon Sep 17 00:00:00 2001 From: loos Date: Tue, 23 Jul 2013 13:40:26 +0000 Subject: Fix the usage error message. The valid range is up to max. vlan - 1 since vlangroups starts at 0. Approved by: adrian (mentor) --- sbin/etherswitchcfg/etherswitchcfg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/etherswitchcfg/etherswitchcfg.c b/sbin/etherswitchcfg/etherswitchcfg.c index e117580..a67dac0 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.c +++ b/sbin/etherswitchcfg/etherswitchcfg.c @@ -626,7 +626,9 @@ main(int argc, char *argv[]) newmode(&cfg, MODE_PORT); } else if (sscanf(argv[0], "vlangroup%d", &cfg.unit) == 1) { if (cfg.unit < 0 || cfg.unit >= cfg.info.es_nvlangroups) - errx(EX_USAGE, "port unit must be between 0 and %d", cfg.info.es_nvlangroups); + errx(EX_USAGE, + "vlangroup unit must be between 0 and %d", + cfg.info.es_nvlangroups - 1); newmode(&cfg, MODE_VLANGROUP); } else if (strcmp(argv[0], "config") == 0) { newmode(&cfg, MODE_CONFIG); -- cgit v1.1 From e4f13850f70c2edd8f1918455575694b72741b3e Mon Sep 17 00:00:00 2001 From: loos Date: Tue, 23 Jul 2013 13:56:38 +0000 Subject: Add a new flag (ETHERSWITCH_VID_VALID) to say what vlangroups are in use. This fix the case when etherswitch is printing the information of port 0 vlan group (in port based vlan mode) with no member ports. Add the ETHERSWITCH_VID_VALID support to ip17x driver. Add the ETHERSWITCH_VID_VALID support to rt8366 driver. arswitch doesn't need to be updated as it doesn't support vlans management yet. Approved by: adrian (mentor) --- sbin/etherswitchcfg/etherswitchcfg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/etherswitchcfg/etherswitchcfg.c b/sbin/etherswitchcfg/etherswitchcfg.c index a67dac0..1eef832 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.c +++ b/sbin/etherswitchcfg/etherswitchcfg.c @@ -471,8 +471,9 @@ print_vlangroup(struct cfg *cfg, int vlangroup) vg.es_vlangroup = vlangroup; if (ioctl(cfg->fd, IOETHERSWITCHGETVLANGROUP, &vg) != 0) err(EX_OSERR, "ioctl(IOETHERSWITCHGETVLANGROUP)"); - if (vg.es_vid == 0 && vg.es_member_ports == 0) + if ((vg.es_vid & ETHERSWITCH_VID_VALID) == 0) return; + vg.es_vid &= ETHERSWITCH_VID_MASK; printf("vlangroup%d:\n", vlangroup); if (cfg->conf.vlan_mode == ETHERSWITCH_VLAN_PORT) printf("\tport: %d\n", vg.es_vid); -- cgit v1.1 From 512fdf0a5e5fc67140a2137d3923a289e4a06d1f Mon Sep 17 00:00:00 2001 From: hrs Date: Wed, 24 Jul 2013 04:05:48 +0000 Subject: Fix a bug in cp += SA_SIZE() in RTA_* loop. This could prevent RTA_IFP from displaying correctly in route get subcommand. Spotted by: dim --- sbin/route/route.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index 6bfca13..ebf95c6 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -1699,16 +1699,15 @@ print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) return; } cp = ((char *)(rtm + 1)); - for (i = 0; i < RTAX_MAX; i++) { - if (rtm->rtm_addrs & (1 << i)) + for (i = 0; i < RTAX_MAX; i++) + if (rtm->rtm_addrs & (1 << i)) { sp[i] = (struct sockaddr *)cp; - cp += SA_SIZE((struct sockaddr *)cp); - } - if (rtm->rtm_addrs & RTA_IFP) { - if (sp[RTAX_IFP]->sa_family != AF_LINK || - ((struct sockaddr_dl *)(void *)sp[RTAX_IFP])->sdl_nlen == 0) + cp += SA_SIZE((struct sockaddr *)cp); + } + if ((rtm->rtm_addrs & RTA_IFP) && + (sp[RTAX_IFP]->sa_family != AF_LINK || + ((struct sockaddr_dl *)(void *)sp[RTAX_IFP])->sdl_nlen == 0)) sp[RTAX_IFP] = NULL; - } if (sp[RTAX_DST] && sp[RTAX_NETMASK]) sp[RTAX_NETMASK]->sa_family = sp[RTAX_DST]->sa_family; /* XXX */ if (sp[RTAX_DST]) -- cgit v1.1 From fd85b64785483b1b7165ece977583df11da022aa Mon Sep 17 00:00:00 2001 From: se Date: Wed, 24 Jul 2013 08:36:29 +0000 Subject: Remove duplicated parapgraph. MFC after: 3 days --- sbin/ipfw/ipfw.8 | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'sbin') diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index 2047385..65fa334 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -3049,16 +3049,6 @@ option could be used to (re)mark user traffic, by adding the following to the appropriate place in ruleset: .Pp .Dl "ipfw add setdscp be ip from any to any dscp af11,af21" -.Pp -This rule drops all incoming packets that appear to be coming from another -directly connected system but on the wrong interface. -For example, a packet with a source address of -.Li 192.168.0.0/24 , -configured on -.Li fxp0 , -but coming in on -.Li fxp1 -would be dropped. .Ss DYNAMIC RULES In order to protect a site from flood attacks involving fake TCP packets, it is safer to use dynamic rules: -- cgit v1.1 From c8737cbf1c0d4bef13135c8c3b4c38fa73c2ccfd Mon Sep 17 00:00:00 2001 From: avg Date: Sun, 28 Jul 2013 18:35:43 +0000 Subject: remove needless inclusion of machine/cpu.h in userland MFC after: 21 days --- sbin/adjkerntz/adjkerntz.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sbin') diff --git a/sbin/adjkerntz/adjkerntz.c b/sbin/adjkerntz/adjkerntz.c index c42379d..3451447 100644 --- a/sbin/adjkerntz/adjkerntz.c +++ b/sbin/adjkerntz/adjkerntz.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include "pathnames.h" -- cgit v1.1 From 4e6c4b2a3693b3ff3713bff0906a243d1acbc284 Mon Sep 17 00:00:00 2001 From: avg Date: Sun, 28 Jul 2013 18:44:17 +0000 Subject: Revert r253748,253749 This WIP should not have been committed yet. Pointyhat to: avg --- sbin/adjkerntz/adjkerntz.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sbin') diff --git a/sbin/adjkerntz/adjkerntz.c b/sbin/adjkerntz/adjkerntz.c index 3451447..c42379d 100644 --- a/sbin/adjkerntz/adjkerntz.c +++ b/sbin/adjkerntz/adjkerntz.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include "pathnames.h" -- cgit v1.1 From d13c0062851638685f23ad2a414ca3b0e71ba340 Mon Sep 17 00:00:00 2001 From: scottl Date: Tue, 30 Jul 2013 22:57:12 +0000 Subject: Add a 'surrender' mode to fsck_ffs. With the -S flag, once hard read errors are encountered, the fsck will stop instead of wasting time chewing through possibly other errors. Obtained from: Netflix MFC after: 3 days --- sbin/fsck_ffs/fsck.h | 1 + sbin/fsck_ffs/fsutil.c | 13 ++++++++++++- sbin/fsck_ffs/main.c | 6 +++++- 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'sbin') diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 45b242c..632d454 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -324,6 +324,7 @@ char skipclean; /* skip clean file systems if preening */ int fsmodified; /* 1 => write done to file system */ int fsreadfd; /* file descriptor for reading file system */ int fswritefd; /* file descriptor for writing file system */ +int surrender; /* Give up if reads fail */ ufs2_daddr_t maxfsblock; /* number of blocks in the file system */ char *blockmap; /* ptr to primary blk allocation map */ diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index f177408..abc987a 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -549,7 +549,18 @@ blread(int fd, char *buf, ufs2_daddr_t blk, long size) slowio_end(); return (0); } - rwerror("READ BLK", blk); + + /* + * This is handled specially here instead of in rwerror because + * rwerror is used for all sorts of errors, not just true read/write + * errors. It should be refactored and fixed. + */ + if (surrender) { + pfatal("CANNOT READ_BLK: %ld", (long)blk); + errx(EEXIT, "ABORTING DUE TO READ ERRORS"); + } else + rwerror("READ BLK", blk); + if (lseek(fd, offset, 0) < 0) rwerror("SEEK BLK", blk); errs = 0; diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index d074447..1a1c03b 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -82,7 +82,7 @@ main(int argc, char *argv[]) sync(); skipclean = 1; inoopt = 0; - while ((ch = getopt(argc, argv, "b:Bc:CdEfFm:npryZ")) != -1) { + while ((ch = getopt(argc, argv, "b:Bc:CdEfFm:nprSyZ")) != -1) { switch (ch) { case 'b': skipclean = 0; @@ -142,6 +142,10 @@ main(int argc, char *argv[]) inoopt++; break; + case 'S': + surrender = 1; + break; + case 'y': yflag++; nflag = 0; -- cgit v1.1 From f1fd54caa14224e6b972e0f1a44b447925d82613 Mon Sep 17 00:00:00 2001 From: scottl Date: Wed, 31 Jul 2013 04:51:12 +0000 Subject: Document the -S flag to fsck_ffs Obtained from: Netflix --- sbin/fsck_ffs/fsck_ffs.8 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/fsck_ffs/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8 index 0b3f992..adf08d7 100644 --- a/sbin/fsck_ffs/fsck_ffs.8 +++ b/sbin/fsck_ffs/fsck_ffs.8 @@ -29,7 +29,7 @@ .\" @(#)fsck.8 8.4 (Berkeley) 5/9/95 .\" $FreeBSD$ .\" -.Dd February 10, 2012 +.Dd July 30, 2013 .Dt FSCK_FFS 8 .Os .Sh NAME @@ -275,6 +275,11 @@ and frees up space that can allocated to files. The .Fl r option is ignored when running in preen mode. +.It Fl S +Surrender on error. +With this flag enabled, a hard error returned on disk i/o will cause +.Nm +to abort instead of continuing on and possibly tripping over more i/o errors. .It Fl y Assume a yes response to all questions asked by .Nm ; -- cgit v1.1 From e07cc719808308b44f63f6fd6236d4580948b5e7 Mon Sep 17 00:00:00 2001 From: delphij Date: Wed, 31 Jul 2013 07:06:58 +0000 Subject: Resolve fflag with realpath(). MFC after: 2 weeks --- sbin/mdconfig/mdconfig.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/mdconfig/mdconfig.c b/sbin/mdconfig/mdconfig.c index 6ba4cd6..233058d 100644 --- a/sbin/mdconfig/mdconfig.c +++ b/sbin/mdconfig/mdconfig.c @@ -161,7 +161,9 @@ main(int argc, char **argv) case 'f': if (fflag != NULL) errx(1, "-f can be passed only once"); - fflag = optarg; + fflag = realpath(optarg, NULL); + if (fflag == NULL) + err(1, "realpath"); break; case 'o': if (!strcmp(optarg, "async")) -- cgit v1.1 From cf0d40cd38c7fa6da7d1def7031f6aaa7684b4d2 Mon Sep 17 00:00:00 2001 From: delphij Date: Wed, 31 Jul 2013 07:09:35 +0000 Subject: Make two buffer variables static for now. It is not safe to reference stack memory after return. MFC after: 2 weeks --- sbin/swapon/swapon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c index 5dcb18d..d93277c 100644 --- a/sbin/swapon/swapon.c +++ b/sbin/swapon/swapon.c @@ -446,7 +446,7 @@ swap_on_off_md(const char *name, char *mntops, int doingall) FILE *sfd; int fd, mdunit, error; const char *ret; - char mdpath[PATH_MAX], linebuf[PATH_MAX]; + static char mdpath[PATH_MAX], linebuf[PATH_MAX]; char *p, *vnodefile; size_t linelen; u_long ul; -- cgit v1.1 From ae539b49caf1adee4cd732dfedf805927f64a692 Mon Sep 17 00:00:00 2001 From: hrs Date: Thu, 1 Aug 2013 04:50:46 +0000 Subject: Fix boundary check of sockaddr array. Reported by: uqs --- sbin/route/route.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/route/route.c b/sbin/route/route.c index ebf95c6..e575c71 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -1146,6 +1146,8 @@ getaddr(int idx, char *str, struct hostent **hpp, int nrflags) char *q; #endif + if (idx < 0 || idx >= RTAX_MAX) + usage("internal error"); if (af == 0) { #if defined(INET) af = AF_INET; @@ -1162,9 +1164,6 @@ getaddr(int idx, char *str, struct hostent **hpp, int nrflags) hpp = NULL; #endif rtm_addrs |= (1 << idx); - - if (idx > RTAX_MAX) - usage("internal error"); sa = (struct sockaddr *)&so[idx]; sa->sa_family = af; sa->sa_len = aflen; -- cgit v1.1 From 08061c3f1e43cdc5bba4b98a08da51432d3ba18c Mon Sep 17 00:00:00 2001 From: crees Date: Mon, 5 Aug 2013 10:38:34 +0000 Subject: Note NULL encryption method for GELI PR: docs/180551 Submitted by: r4721@tormail.org Approved by: gjb (mentor) --- sbin/geom/class/eli/geli.8 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/geom/class/eli/geli.8 b/sbin/geom/class/eli/geli.8 index 263b8b2..ad70798 100644 --- a/sbin/geom/class/eli/geli.8 +++ b/sbin/geom/class/eli/geli.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 18, 2012 +.Dd July 5, 2013 .Dt GELI 8 .Os .Sh NAME @@ -285,11 +285,14 @@ Currently supported algorithms are: .Nm AES-XTS , .Nm AES-CBC , .Nm Blowfish-CBC , -.Nm Camellia-CBC +.Nm Camellia-CBC , +.Nm 3DES-CBC , and -.Nm 3DES-CBC . +.Nm NULL . The default and recommended algorithm is .Nm AES-XTS . +.Nm NULL +is unencrypted. .It Fl i Ar iterations Number of iterations to use with PKCS#5v2 when processing User Key passphrase component. -- cgit v1.1 From 9f2f2e171a6de4c6d713a50366f3572946665fb5 Mon Sep 17 00:00:00 2001 From: marcel Date: Wed, 7 Aug 2013 00:00:48 +0000 Subject: Change to not redefine the same symbols that are being defined in . Instead give the symbols here a "PC98_" prefix. This way, both and can be included in the same C source file. The renaming is trivial. The only gotcha is that DOSBBSECTOR is also redefined from 0 to 1. This because DOSBBSECTOR was always used in conjunction with an addition of 1. The PC98_BBSECTOR symbol is defined as 1 and the expression is simplified. Note: it is not believed that ports are seriously impacted; or at all for that matter. Approved by: nyan@ --- sbin/fdisk_pc98/fdisk.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sbin') diff --git a/sbin/fdisk_pc98/fdisk.c b/sbin/fdisk_pc98/fdisk.c index b66bad4..479e1e4 100644 --- a/sbin/fdisk_pc98/fdisk.c +++ b/sbin/fdisk_pc98/fdisk.c @@ -254,7 +254,7 @@ main(int argc, char *argv[]) dos_sectors); printf("Part %11s %11s %4s %4s %-16s\n", "Start", "Size", "MID", "SID", "Name"); - for (i = 0; i < NDOSPART; i++) { + for (i = 0; i < PC98_NPARTS; i++) { partp = ((struct pc98_partition *) &mboot.parts) + i; if (partp->dp_sid == 0) continue; @@ -310,7 +310,7 @@ main(int argc, char *argv[]) printf("Warning: BIOS sector numbering starts with sector 1\n"); printf("Information from DOS bootblock is:\n"); if (partition == -1) - for (i = 1; i <= NDOSPART; i++) + for (i = 1; i <= PC98_NPARTS; i++) change_part(i, v_flag); else change_part(partition, 1); @@ -367,7 +367,7 @@ print_s0(int which) print_params(); printf("Information from DOS bootblock is:\n"); if (which == -1) { - for (i = 1; i <= NDOSPART; i++) + for (i = 1; i <= PC98_NPARTS; i++) if (v_flag || !part_unused(i)) { printf("%d: ", i); print_part(i); @@ -414,7 +414,7 @@ static void init_boot(void) { - mboot.signature = DOSMAGIC; + mboot.signature = PC98_MAGIC; } @@ -517,7 +517,7 @@ change_active(int which) int active, i, new, tmp; active = -1; - for (i = 0; i < NDOSPART; i++) { + for (i = 0; i < PC98_NPARTS; i++) { if ((partp[i].dp_sid & PC98_SID_ACTIVE) == 0) continue; printf("Partition %d is marked active\n", i + 1); @@ -672,7 +672,7 @@ write_disk(off_t sector, void *buf) if (error == sz) return (0); - for (i = 0; i < NDOSPART; i++) { + for (i = 0; i < PC98_NPARTS; i++) { sprintf(fbuf, "%ss%d", disk, i + 1); fdw = open(fbuf, O_RDWR, 0); if (fdw < 0) @@ -731,7 +731,7 @@ read_s0() warnx("can't read fdisk partition table"); return -1; } - if (mboot.signature != DOSMAGIC) { + if (mboot.signature != PC98_MAGIC) { warnx("invalid fdisk partition table found"); /* So should we initialize things */ return -1; @@ -911,7 +911,7 @@ reset_boot(void) struct pc98_partition *partp; init_boot(); - for (i = 1; i <= NDOSPART; i++) { + for (i = 1; i <= PC98_NPARTS; i++) { partp = ((struct pc98_partition *) &mboot.parts) + i - 1; bzero((char *)partp, sizeof (struct pc98_partition)); } -- cgit v1.1 From cf48481217da0cd44a453cc420f3f74cd4820b24 Mon Sep 17 00:00:00 2001 From: jilles Date: Tue, 13 Aug 2013 18:51:26 +0000 Subject: init: Set kernel login class and CPU mask on new processes. In particular, this makes the kernel login class on processes started from /etc/rc "daemon" instead of "default". Reviewed by: trasz --- sbin/init/init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/init/init.c b/sbin/init/init.c index c19b070..99041c9 100644 --- a/sbin/init/init.c +++ b/sbin/init/init.c @@ -1729,7 +1729,8 @@ setprocresources(const char *cname) login_cap_t *lc; if ((lc = login_getclassbyname(cname, NULL)) != NULL) { setusercontext(lc, (struct passwd*)NULL, 0, - LOGIN_SETPRIORITY | LOGIN_SETRESOURCES); + LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | + LOGIN_SETLOGINCLASS | LOGIN_SETCPUMASK); login_close(lc); } } -- cgit v1.1 From 8501201ddfa94ba53490d55b57c052ea6c0a2872 Mon Sep 17 00:00:00 2001 From: des Date: Tue, 20 Aug 2013 07:19:58 +0000 Subject: Fix the zeroing loop. I must have been drunk when I wrote this... MFC after: 3 days --- sbin/fsck_ffs/fsutil.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sbin') diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index abc987a..16ef819 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -629,6 +629,10 @@ blerase(int fd, ufs2_daddr_t blk, long size) return; } +/* + * Fill a contiguous region with all-zeroes. Note ZEROBUFSIZE is by + * definition a multiple of dev_bsize. + */ void blzero(int fd, ufs2_daddr_t blk, long size) { @@ -637,9 +641,8 @@ blzero(int fd, ufs2_daddr_t blk, long size) if (fd < 0) return; - len = ZEROBUFSIZE; if (zero == NULL) { - zero = calloc(len, 1); + zero = calloc(ZEROBUFSIZE, 1); if (zero == NULL) errx(EEXIT, "cannot allocate buffer pool"); } @@ -647,10 +650,7 @@ blzero(int fd, ufs2_daddr_t blk, long size) if (lseek(fd, offset, 0) < 0) rwerror("SEEK BLK", blk); while (size > 0) { - if (size > len) - size = len; - else - len = size; + len = size > ZEROBUFSIZE ? ZEROBUFSIZE : size; if (write(fd, zero, len) != len) rwerror("WRITE BLK", blk); blk += len / dev_bsize; -- cgit v1.1 From 4639378b96541fe61d6a45cb69ed3522c8f31874 Mon Sep 17 00:00:00 2001 From: trasz Date: Thu, 22 Aug 2013 14:02:34 +0000 Subject: Move the old iSCSI initiator source to a more appropriate place (sys/dev/iscsi_initiator/ instead of sys/dev/iscsi/initiator/), to make room for the new one. This is also more logical location (kernel module being named iscsi_initiator.ko, for example). There is no ongoing work on this I know of, so it shouldn't make life harder for anyone. There are no functional changes, apart from "svn mv" and adjusting paths. --- sbin/iscontrol/auth_subr.c | 2 +- sbin/iscontrol/config.c | 2 +- sbin/iscontrol/fsm.c | 2 +- sbin/iscontrol/iscontrol.c | 2 +- sbin/iscontrol/login.c | 2 +- sbin/iscontrol/misc.c | 2 +- sbin/iscontrol/pdu.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'sbin') diff --git a/sbin/iscontrol/auth_subr.c b/sbin/iscontrol/auth_subr.c index 9ced1d7..5f82929 100644 --- a/sbin/iscontrol/auth_subr.c +++ b/sbin/iscontrol/auth_subr.c @@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include "iscontrol.h" static int diff --git a/sbin/iscontrol/config.c b/sbin/iscontrol/config.c index 6307f66..e8fd309 100644 --- a/sbin/iscontrol/config.c +++ b/sbin/iscontrol/config.c @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include "iscontrol.h" /* diff --git a/sbin/iscontrol/fsm.c b/sbin/iscontrol/fsm.c index 794fb8b..a4660bb 100644 --- a/sbin/iscontrol/fsm.c +++ b/sbin/iscontrol/fsm.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include "iscontrol.h" typedef enum { diff --git a/sbin/iscontrol/iscontrol.c b/sbin/iscontrol/iscontrol.c index c6ce21c..2e8f2ea 100644 --- a/sbin/iscontrol/iscontrol.c +++ b/sbin/iscontrol/iscontrol.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include "iscontrol.h" static char version[] = "2.3.1"; // keep in sync with iscsi_initiator diff --git a/sbin/iscontrol/login.c b/sbin/iscontrol/login.c index 76937a8..92bbc64b 100644 --- a/sbin/iscontrol/login.c +++ b/sbin/iscontrol/login.c @@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include "iscontrol.h" static char *status_class1[] = { diff --git a/sbin/iscontrol/misc.c b/sbin/iscontrol/misc.c index 1f9dd12..b6fe6df 100644 --- a/sbin/iscontrol/misc.c +++ b/sbin/iscontrol/misc.c @@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include "iscontrol.h" static inline char diff --git a/sbin/iscontrol/pdu.c b/sbin/iscontrol/pdu.c index c4d3a2a..7ce90ea 100644 --- a/sbin/iscontrol/pdu.c +++ b/sbin/iscontrol/pdu.c @@ -43,7 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include "iscontrol.h" static void pukeText(char *it, pdu_t *pp); -- cgit v1.1 From dfd07d8821f7b5e2045ff827d8650c7c266e014c Mon Sep 17 00:00:00 2001 From: mav Date: Tue, 27 Aug 2013 06:50:46 +0000 Subject: Add missing newlines to Fibre Channel attributes output. --- sbin/camcontrol/camcontrol.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sbin') diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 35826c5..76b3939 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -4488,13 +4488,13 @@ cts_print(struct cam_device *device, struct ccb_trans_settings *cts) &cts->xport_specific.fc; if (fc->valid & CTS_FC_VALID_WWNN) - fprintf(stdout, "%sWWNN: 0x%llx", pathstr, + fprintf(stdout, "%sWWNN: 0x%llx\n", pathstr, (long long) fc->wwnn); if (fc->valid & CTS_FC_VALID_WWPN) - fprintf(stdout, "%sWWPN: 0x%llx", pathstr, + fprintf(stdout, "%sWWPN: 0x%llx\n", pathstr, (long long) fc->wwpn); if (fc->valid & CTS_FC_VALID_PORT) - fprintf(stdout, "%sPortID: 0x%x", pathstr, fc->port); + fprintf(stdout, "%sPortID: 0x%x\n", pathstr, fc->port); if (fc->valid & CTS_FC_VALID_SPEED) fprintf(stdout, "%stransfer speed: %d.%03dMB/s\n", pathstr, fc->bitrate / 1000, fc->bitrate % 1000); -- cgit v1.1 From 79ac01d192518923ff35984ca6cf99063106d933 Mon Sep 17 00:00:00 2001 From: pluknet Date: Fri, 30 Aug 2013 10:01:19 +0000 Subject: Typo in strtol(3). Noticed by: bde --- sbin/etherswitchcfg/etherswitchcfg.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sbin') diff --git a/sbin/etherswitchcfg/etherswitchcfg.8 b/sbin/etherswitchcfg/etherswitchcfg.8 index a4ffb0b..a8b8d1a 100644 --- a/sbin/etherswitchcfg/etherswitchcfg.8 +++ b/sbin/etherswitchcfg/etherswitchcfg.8 @@ -69,7 +69,7 @@ is usually the port number, and is the register number. Both can be provided as decimal, octal or hexadecimal numbers in any of the formats understood by -.Xr strtol 4 . +.Xr strtol 3 . To set the register value, use the form instance.register=value. .Ss port The port command selects one of the ports of the switch. -- cgit v1.1 From 029a6f5d92dc57925b5f155d94d6e01fdab7a45d Mon Sep 17 00:00:00 2001 From: pjd Date: Thu, 5 Sep 2013 00:09:56 +0000 Subject: Change the cap_rights_t type from uint64_t to a structure that we can extend in the future in a backward compatible (API and ABI) way. The cap_rights_t represents capability rights. We used to use one bit to represent one right, but we are running out of spare bits. Currently the new structure provides place for 114 rights (so 50 more than the previous cap_rights_t), but it is possible to grow the structure to hold at least 285 rights, although we can make it even larger if 285 rights won't be enough. The structure definition looks like this: struct cap_rights { uint64_t cr_rights[CAP_RIGHTS_VERSION + 2]; }; The initial CAP_RIGHTS_VERSION is 0. The top two bits in the first element of the cr_rights[] array contain total number of elements in the array - 2. This means if those two bits are equal to 0, we have 2 array elements. The top two bits in all remaining array elements should be 0. The next five bits in all array elements contain array index. Only one bit is used and bit position in this five-bits range defines array index. This means there can be at most five array elements in the future. To define new right the CAPRIGHT() macro must be used. The macro takes two arguments - an array index and a bit to set, eg. #define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL) We still support aliases that combine few rights, but the rights have to belong to the same array element, eg: #define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL) #define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL) #define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP) There is new API to manage the new cap_rights_t structure: cap_rights_t *cap_rights_init(cap_rights_t *rights, ...); void cap_rights_set(cap_rights_t *rights, ...); void cap_rights_clear(cap_rights_t *rights, ...); bool cap_rights_is_set(const cap_rights_t *rights, ...); bool cap_rights_is_valid(const cap_rights_t *rights); void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src); void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src); bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little); Capability rights to the cap_rights_init(), cap_rights_set(), cap_rights_clear() and cap_rights_is_set() functions are provided by separating them with commas, eg: cap_rights_t rights; cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT); There is no need to terminate the list of rights, as those functions are actually macros that take care of the termination, eg: #define cap_rights_set(rights, ...) \ __cap_rights_set((rights), __VA_ARGS__, 0ULL) void __cap_rights_set(cap_rights_t *rights, ...); Thanks to using one bit as an array index we can assert in those functions that there are no two rights belonging to different array elements provided together. For example this is illegal and will be detected, because CAP_LOOKUP belongs to element 0 and CAP_PDKILL to element 1: cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL); Providing several rights that belongs to the same array's element this way is correct, but is not advised. It should only be used for aliases definition. This commit also breaks compatibility with some existing Capsicum system calls, but I see no other way to do that. This should be fine as Capsicum is still experimental and this change is not going to 9.x. Sponsored by: The FreeBSD Foundation --- sbin/dhclient/bpf.c | 12 ++++++++---- sbin/dhclient/dhclient.c | 31 +++++++++++++++++++------------ sbin/hastd/subr.c | 9 ++++++--- 3 files changed, 33 insertions(+), 19 deletions(-) (limited to 'sbin') diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index f435028..c0a1720 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -43,6 +43,8 @@ #include __FBSDID("$FreeBSD$"); +#include + #include "dhcpd.h" #include "privsep.h" #include @@ -132,6 +134,7 @@ int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn); void if_register_send(struct interface_info *info) { + cap_rights_t rights; struct bpf_version v; struct bpf_program p; int sock, on = 1; @@ -160,7 +163,8 @@ if_register_send(struct interface_info *info) if (ioctl(info->wfdesc, BIOCLOCK, NULL) < 0) error("Cannot lock bpf"); - if (cap_rights_limit(info->wfdesc, CAP_WRITE) < 0 && errno != ENOSYS) + cap_rights_init(&rights, CAP_WRITE); + if (cap_rights_limit(info->wfdesc, &rights) < 0 && errno != ENOSYS) error("Can't limit bpf descriptor: %m"); /* @@ -213,6 +217,7 @@ void if_register_receive(struct interface_info *info) { static const unsigned long cmds[2] = { SIOCGIFFLAGS, SIOCGIFMEDIA }; + cap_rights_t rights; struct bpf_version v; struct bpf_program p; int flag = 1, sz; @@ -264,10 +269,9 @@ if_register_receive(struct interface_info *info) if (ioctl(info->rfdesc, BIOCLOCK, NULL) < 0) error("Cannot lock bpf"); - if (cap_rights_limit(info->rfdesc, - CAP_IOCTL | CAP_POLL_EVENT | CAP_READ) < 0 && errno != ENOSYS) { + cap_rights_init(&rights, CAP_IOCTL, CAP_POLL_EVENT, CAP_READ); + if (cap_rights_limit(info->rfdesc, &rights) < 0 && errno != ENOSYS) error("Can't limit bpf descriptor: %m"); - } if (cap_ioctls_limit(info->rfdesc, cmds, 2) < 0 && errno != ENOSYS) error("Can't limit ioctls for bpf descriptor: %m"); } diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index c8f05b5..e16e464 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -56,6 +56,8 @@ #include __FBSDID("$FreeBSD$"); +#include + #include "dhcpd.h" #include "privsep.h" @@ -346,6 +348,7 @@ main(int argc, char *argv[]) int immediate_daemon = 0; struct passwd *pw; pid_t otherpid; + cap_rights_t rights; /* Initially, log errors to stderr as well as to syslogd. */ openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY); @@ -477,10 +480,9 @@ main(int argc, char *argv[]) close(pipe_fd[0]); privfd = pipe_fd[1]; - if (cap_rights_limit(privfd, CAP_READ | CAP_WRITE) < 0 && - errno != ENOSYS) { + cap_rights_init(&rights, CAP_READ, CAP_WRITE); + if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS) error("can't limit private descriptor: %m"); - } if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1) error("can't open and lock %s: %m", path_dhclient_db); @@ -492,10 +494,9 @@ main(int argc, char *argv[]) add_protocol("AF_ROUTE", routefd, routehandler, ifi); if (shutdown(routefd, SHUT_WR) < 0) error("can't shutdown route socket: %m"); - if (cap_rights_limit(routefd, CAP_POLL_EVENT | CAP_READ) < 0 && - errno != ENOSYS) { + cap_rights_init(&rights, CAP_POLL_EVENT, CAP_READ); + if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS) error("can't limit route socket: %m"); - } if (chroot(_PATH_VAREMPTY) == -1) error("chroot"); @@ -1840,13 +1841,15 @@ void rewrite_client_leases(void) { struct client_lease *lp; + cap_rights_t rights; if (!leaseFile) { leaseFile = fopen(path_dhclient_db, "w"); if (!leaseFile) error("can't create %s: %m", path_dhclient_db); - if (cap_rights_limit(fileno(leaseFile), CAP_FSTAT | CAP_FSYNC | - CAP_FTRUNCATE | CAP_SEEK | CAP_WRITE) < 0 && + cap_rights_init(&rights, CAP_FSTAT, CAP_FSYNC, CAP_FTRUNCATE, + CAP_SEEK, CAP_WRITE); + if (cap_rights_limit(fileno(leaseFile), &rights) < 0 && errno != ENOSYS) { error("can't limit lease descriptor: %m"); } @@ -2354,6 +2357,7 @@ void go_daemon(void) { static int state = 0; + cap_rights_t rights; if (no_daemon || state) return; @@ -2366,9 +2370,11 @@ go_daemon(void) if (daemon(1, 0) == -1) error("daemon"); + cap_rights_init(&rights); + if (pidfile != NULL) { pidfile_write(pidfile); - if (cap_rights_limit(pidfile_fileno(pidfile), CAP_NONE) < 0 && + if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 && errno != ENOSYS) { error("can't limit pidfile descriptor: %m"); } @@ -2383,11 +2389,12 @@ go_daemon(void) nullfd = -1; } - if (cap_rights_limit(STDIN_FILENO, CAP_NONE) < 0 && errno != ENOSYS) + if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) error("can't limit stdin: %m"); - if (cap_rights_limit(STDOUT_FILENO, CAP_WRITE) < 0 && errno != ENOSYS) + cap_rights_init(&rights, CAP_WRITE); + if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) error("can't limit stdout: %m"); - if (cap_rights_limit(STDERR_FILENO, CAP_WRITE) < 0 && errno != ENOSYS) + if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) error("can't limit stderr: %m"); } diff --git a/sbin/hastd/subr.c b/sbin/hastd/subr.c index 440061e..0e9930b 100644 --- a/sbin/hastd/subr.c +++ b/sbin/hastd/subr.c @@ -231,6 +231,7 @@ drop_privs(const struct hast_resource *res) pjdlog_common(LOG_DEBUG, 1, errno, "Unable to sandbox using capsicum"); } else if (res != NULL) { + cap_rights_t rights; static const unsigned long geomcmds[] = { DIOCGDELETE, DIOCGFLUSH @@ -239,8 +240,9 @@ drop_privs(const struct hast_resource *res) PJDLOG_ASSERT(res->hr_role == HAST_ROLE_PRIMARY || res->hr_role == HAST_ROLE_SECONDARY); - if (cap_rights_limit(res->hr_localfd, - CAP_FLOCK | CAP_IOCTL | CAP_PREAD | CAP_PWRITE) == -1) { + cap_rights_init(&rights, CAP_FLOCK, CAP_IOCTL, CAP_PREAD, + CAP_PWRITE); + if (cap_rights_limit(res->hr_localfd, &rights) == -1) { pjdlog_errno(LOG_ERR, "Unable to limit capability rights on local descriptor"); } @@ -258,7 +260,8 @@ drop_privs(const struct hast_resource *res) G_GATE_CMD_DESTROY }; - if (cap_rights_limit(res->hr_ggatefd, CAP_IOCTL) == -1) { + cap_rights_init(&rights, CAP_IOCTL); + if (cap_rights_limit(res->hr_ggatefd, &rights) == -1) { pjdlog_errno(LOG_ERR, "Unable to limit capability rights to CAP_IOCTL on ggate descriptor"); } -- cgit v1.1