Author: freqlabs Date: Mon Nov 2 20:00:50 2020 New Revision: 367283 URL: https://svnweb.freebsd.org/changeset/base/367283
Log: MFC r366465, r367003, r367006, r367009 Enable iterating all sysctls, even ones with CTLFLAG_SKIP kern_sysctl: Misc code cleanup sysctl: Misc code cleanup sysctl+kern_sysctl: Honor SKIP for descendant nodes Modified: stable/12/sbin/sysctl/sysctl.c stable/12/sys/kern/kern_sysctl.c stable/12/sys/sys/sysctl.h stable/12/usr.bin/truss/syscalls.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sbin/sysctl/sysctl.c ============================================================================== --- stable/12/sbin/sysctl/sysctl.c Mon Nov 2 19:56:15 2020 (r367282) +++ stable/12/sbin/sysctl/sysctl.c Mon Nov 2 20:00:50 2020 (r367283) @@ -29,20 +29,9 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); -#ifndef lint -#if 0 -static char sccsid[] = "@(#)from: sysctl.c 8.1 (Berkeley) 6/6/93"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> #include <sys/time.h> #include <sys/resource.h> @@ -81,7 +70,7 @@ static int Nflag, nflag, oflag, qflag, tflag, Tflag, W static int oidfmt(int *, int, char *, u_int *); static int parsefile(const char *); static int parse(const char *, int); -static int show_var(int *, int); +static int show_var(int *, int, bool); static int sysctl_all(int *oid, int len); static int name2oid(const char *, int *); @@ -221,7 +210,7 @@ main(int argc, char **argv) if (Nflag && nflag) usage(); if (aflag && argc == 0) - exit(sysctl_all(0, 0)); + exit(sysctl_all(NULL, 0)); if (argc == 0 && conffile == NULL) usage(); @@ -369,6 +358,13 @@ parse(const char *string, int lineno) else line[0] = '\0'; + /* + * Split the string into name and value. + * + * Either = or : may be used as the delimiter. + * Whitespace surrounding the delimiter is trimmed. + * Quotes around the value are stripped. + */ cp = buf; if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) { warnx("oid too long: '%s'%s", string, line); @@ -381,6 +377,7 @@ parse(const char *string, int lineno) warnx("Can't set variables when using -T or -W"); usage(); } + /* Trim whitespace before the value. */ while (isspace(*cp)) cp++; /* Strip a pair of " or ' if any. */ @@ -394,14 +391,17 @@ parse(const char *string, int lineno) newvalstr = cp; newsize = strlen(cp); } - /* Trim spaces */ + /* Trim whitespace after the name. */ cp = bufp + strlen(bufp) - 1; while (cp >= bufp && isspace((int)*cp)) { *cp = '\0'; cp--; } - len = name2oid(bufp, mib); + /* + * Check the name is a useable oid. + */ + len = name2oid(bufp, mib); if (len < 0) { if (iflag) return (0); @@ -425,118 +425,126 @@ parse(const char *string, int lineno) exit(1); } + /* + * We have a useable oid to work with. If there is no value given, + * show the node and its children. Otherwise, set the new value. + */ if (newvalstr == NULL || dflag) { if ((kind & CTLTYPE) == CTLTYPE_NODE) { if (dflag) { - i = show_var(mib, len); + i = show_var(mib, len, false); if (!i && !bflag) putchar('\n'); } sysctl_all(mib, len); } else { - i = show_var(mib, len); + i = show_var(mib, len, false); if (!i && !bflag) putchar('\n'); } - } else { - if ((kind & CTLTYPE) == CTLTYPE_NODE) { - warnx("oid '%s' isn't a leaf node%s", bufp, line); - return (1); - } + return (0); + } - if (!(kind & CTLFLAG_WR)) { - if (kind & CTLFLAG_TUN) { - warnx("oid '%s' is a read only tunable%s", bufp, line); - warnx("Tunable values are set in /boot/loader.conf"); - } else - warnx("oid '%s' is read only%s", bufp, line); - return (1); - } + /* + * We have a new value to set. Check its validity and parse if numeric. + */ + if ((kind & CTLTYPE) == CTLTYPE_NODE) { + warnx("oid '%s' isn't a leaf node%s", bufp, line); + return (1); + } - switch (kind & CTLTYPE) { - case CTLTYPE_INT: - case CTLTYPE_UINT: - case CTLTYPE_LONG: - case CTLTYPE_ULONG: - case CTLTYPE_S8: - case CTLTYPE_S16: - case CTLTYPE_S32: - case CTLTYPE_S64: - case CTLTYPE_U8: - case CTLTYPE_U16: - case CTLTYPE_U32: - case CTLTYPE_U64: - if (strlen(newvalstr) == 0) { - warnx("empty numeric value"); - return (1); - } - /* FALLTHROUGH */ - case CTLTYPE_STRING: - break; - default: - warnx("oid '%s' is type %d," - " cannot set that%s", bufp, - kind & CTLTYPE, line); + if (!(kind & CTLFLAG_WR)) { + if (kind & CTLFLAG_TUN) { + warnx("oid '%s' is a read only tunable%s", bufp, line); + warnx("Tunable values are set in /boot/loader.conf"); + } else + warnx("oid '%s' is read only%s", bufp, line); + return (1); + } + + switch (kind & CTLTYPE) { + case CTLTYPE_INT: + case CTLTYPE_UINT: + case CTLTYPE_LONG: + case CTLTYPE_ULONG: + case CTLTYPE_S8: + case CTLTYPE_S16: + case CTLTYPE_S32: + case CTLTYPE_S64: + case CTLTYPE_U8: + case CTLTYPE_U16: + case CTLTYPE_U32: + case CTLTYPE_U64: + if (strlen(newvalstr) == 0) { + warnx("empty numeric value"); return (1); } + /* FALLTHROUGH */ + case CTLTYPE_STRING: + break; + default: + warnx("oid '%s' is type %d, cannot set that%s", + bufp, kind & CTLTYPE, line); + return (1); + } - newbuf = NULL; + newbuf = NULL; - switch (kind & CTLTYPE) { - case CTLTYPE_STRING: - newval = newvalstr; - break; - default: - newsize = 0; - while ((cp = strsep(&newvalstr, " ,")) != NULL) { - if (*cp == '\0') - continue; - if (!parse_numeric(cp, fmt, kind, &newbuf, - &newsize)) { - warnx("invalid %s '%s'%s", - ctl_typename[kind & CTLTYPE], - cp, line); - free(newbuf); - return (1); - } - } - newval = newbuf; - break; - } - - i = show_var(mib, len); - if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { - free(newbuf); - if (!i && !bflag) - putchar('\n'); - switch (errno) { - case EOPNOTSUPP: - warnx("%s: value is not available%s", - string, line); + switch (kind & CTLTYPE) { + case CTLTYPE_STRING: + newval = newvalstr; + break; + default: + newsize = 0; + while ((cp = strsep(&newvalstr, " ,")) != NULL) { + if (*cp == '\0') + continue; + if (!parse_numeric(cp, fmt, kind, &newbuf, &newsize)) { + warnx("invalid %s '%s'%s", + ctl_typename[kind & CTLTYPE], cp, line); + free(newbuf); return (1); - case ENOTDIR: - warnx("%s: specification is incomplete%s", - string, line); - return (1); - case ENOMEM: - warnx("%s: type is unknown to this program%s", - string, line); - return (1); - default: - warn("%s%s", string, line); - return (1); } } + newval = newbuf; + break; + } + + /* + * Show the current value, then set and show the new value. + */ + i = show_var(mib, len, false); + if (sysctl(mib, len, 0, 0, newval, newsize) == -1) { free(newbuf); - if (!bflag) - printf(" -> "); - i = nflag; - nflag = 1; - j = show_var(mib, len); - if (!j && !bflag) + if (!i && !bflag) putchar('\n'); - nflag = i; + switch (errno) { + case EOPNOTSUPP: + warnx("%s: value is not available%s", + string, line); + return (1); + case ENOTDIR: + warnx("%s: specification is incomplete%s", + string, line); + return (1); + case ENOMEM: + warnx("%s: type is unknown to this program%s", + string, line); + return (1); + default: + warn("%s%s", string, line); + return (1); + } } + free(newbuf); + if (!bflag) + printf(" -> "); + i = nflag; + nflag = 1; + j = show_var(mib, len, false); + if (!j && !bflag) + putchar('\n'); + nflag = i; return (0); } @@ -875,8 +883,8 @@ name2oid(const char *name, int *oidp) int i; size_t j; - oid[0] = 0; - oid[1] = 3; + oid[0] = CTL_SYSCTL; + oid[1] = CTL_SYSCTL_NAME2OID; j = CTL_MAXNAME * sizeof(int); i = sysctl(oid, 2, oidp, &j, name, strlen(name)); @@ -894,8 +902,8 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind) int i; size_t j; - qoid[0] = 0; - qoid[1] = 4; + qoid[0] = CTL_SYSCTL; + qoid[1] = CTL_SYSCTL_OIDFMT; memcpy(qoid + 2, oid, len * sizeof(int)); j = sizeof(buf); @@ -919,8 +927,9 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind) * Return minus one if we had errors. */ static int -show_var(int *oid, int nlen) +show_var(int *oid, int nlen, bool honor_skip) { + static int skip_len = 0, skip_oid[CTL_MAXNAME]; u_char buf[BUFSIZ], *val, *oval, *p; char name[BUFSIZ], fmt[BUFSIZ]; const char *sep, *sep1, *prntype; @@ -941,10 +950,10 @@ show_var(int *oid, int nlen) bzero(buf, BUFSIZ); bzero(fmt, BUFSIZ); bzero(name, BUFSIZ); - qoid[0] = 0; + qoid[0] = CTL_SYSCTL; memcpy(qoid + 2, oid, nlen * sizeof(int)); - qoid[1] = 1; + qoid[1] = CTL_SYSCTL_NAME; j = sizeof(name); i = sysctl(qoid, nlen + 2, name, &j, 0, 0); if (i || !j) @@ -953,11 +962,11 @@ show_var(int *oid, int nlen) oidfmt(oid, nlen, fmt, &kind); /* if Wflag then only list sysctls that are writeable and not stats. */ if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0)) - return 1; + return (1); /* if Tflag then only list sysctls that are tuneables. */ if (Tflag && (kind & CTLFLAG_TUN) == 0) - return 1; + return (1); if (Nflag) { printf("%s", name); @@ -983,13 +992,29 @@ show_var(int *oid, int nlen) printf("%s", prntype); return (0); } - qoid[1] = 5; + qoid[1] = CTL_SYSCTL_OIDDESCR; j = sizeof(buf); i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); printf("%s", buf); return (0); } + /* keep track of encountered skip nodes, ignoring descendants */ + if (skip_len == 0 && (kind & CTLFLAG_SKIP) != 0) { + /* Save this oid so we can skip descendants. */ + skip_len = nlen * sizeof(int); + memcpy(skip_oid, oid, skip_len); + } + + /* bail before fetching the value if we're honoring skip */ + if (honor_skip) { + if (0 < skip_len && skip_len <= nlen * (int)sizeof(int) && + memcmp(skip_oid, oid, skip_len) == 0) + return (1); + /* Not a skip node or descendant of a skip node. */ + skip_len = 0; + } + /* don't fetch opaques that we don't know how to print */ if (ctltype == CTLTYPE_OPAQUE) { if (strcmp(fmt, "S,clockinfo") == 0) @@ -1170,15 +1195,17 @@ sysctl_all(int *oid, int len) int name1[22], name2[22]; int i, j; size_t l1, l2; + bool honor_skip = false; - name1[0] = 0; - name1[1] = 2; + name1[0] = CTL_SYSCTL; + name1[1] = (oid != NULL || Nflag || dflag || tflag) ? + CTL_SYSCTL_NEXTNOSKIP : CTL_SYSCTL_NEXT; l1 = 2; if (len) { - memcpy(name1+2, oid, len * sizeof(int)); + memcpy(name1 + 2, oid, len * sizeof(int)); l1 += len; } else { - name1[2] = 1; + name1[2] = CTL_KERN; l1++; } for (;;) { @@ -1196,15 +1223,15 @@ sysctl_all(int *oid, int len) if (len < 0 || l2 < (unsigned int)len) return (0); - for (i = 0; i < len; i++) - if (name2[i] != oid[i]) - return (0); + if (memcmp(name2, oid, len * sizeof(int)) != 0) + return (0); - i = show_var(name2, l2); + i = show_var(name2, l2, honor_skip); if (!i && !bflag) putchar('\n'); - memcpy(name1+2, name2, l2 * sizeof(int)); + memcpy(name1 + 2, name2, l2 * sizeof(int)); l1 = 2 + l2; + honor_skip = true; } } Modified: stable/12/sys/kern/kern_sysctl.c ============================================================================== --- stable/12/sys/kern/kern_sysctl.c Mon Nov 2 19:56:15 2020 (r367282) +++ stable/12/sys/kern/kern_sysctl.c Mon Nov 2 20:00:50 2020 (r367283) @@ -937,7 +937,8 @@ SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_re * {CTL_SYSCTL, CTL_SYSCTL_DEBUG} printf the entire MIB-tree. * {CTL_SYSCTL, CTL_SYSCTL_NAME, ...} return the name of the "..." * OID. - * {CTL_SYSCTL, CTL_SYSCTL_NEXT, ...} return the next OID. + * {CTL_SYSCTL, CTL_SYSCTL_NEXT, ...} return the next OID, honoring + * CTLFLAG_SKIP. * {CTL_SYSCTL, CTL_SYSCTL_NAME2OID} return the OID of the name in * "new" * {CTL_SYSCTL, CTL_SYSCTL_OIDFMT, ...} return the kind & format info @@ -946,6 +947,8 @@ SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_re * "..." OID. * {CTL_SYSCTL, CTL_SYSCTL_OIDLABEL, ...} return the aggregation label of * the "..." OID. + * {CTL_SYSCTL, CTL_SYSCTL_NEXTNOSKIP, ...} return the next OID, ignoring + * CTLFLAG_SKIP. */ #ifdef SYSCTL_DEBUG @@ -1086,9 +1089,13 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NAME, name, CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_name, ""); +/* + * Walk the sysctl subtree at lsp until we find the given name, + * and return the next name in order by oid_number. + */ static int sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen, - int *next, int *len, int level, struct sysctl_oid **oidpp) + int *next, int *len, int level, bool honor_skip) { struct sysctl_oid *oidp; @@ -1096,54 +1103,95 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *len = level; SLIST_FOREACH(oidp, lsp, oid_link) { *next = oidp->oid_number; - *oidpp = oidp; - if ((oidp->oid_kind & (CTLFLAG_SKIP | CTLFLAG_DORMANT)) != 0) + if ((oidp->oid_kind & CTLFLAG_DORMANT) != 0) continue; - if (!namelen) { + if (honor_skip && (oidp->oid_kind & CTLFLAG_SKIP) != 0) + continue; + + if (namelen == 0) { + /* + * We have reached a node with a full name match and are + * looking for the next oid in its children. + * + * For CTL_SYSCTL_NEXTNOSKIP we are done. + * + * For CTL_SYSCTL_NEXT we skip CTLTYPE_NODE (unless it + * has a handler) and move on to the children. + */ + if (!honor_skip) + return (0); if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) return (0); if (oidp->oid_handler) - /* We really should call the handler here...*/ return (0); lsp = SYSCTL_CHILDREN(oidp); - if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, - len, level+1, oidpp)) + if (!sysctl_sysctl_next_ls(lsp, NULL, 0, next + 1, len, + level + 1, honor_skip)) return (0); + /* + * There were no useable children in this node. + * Continue searching for the next oid at this level. + */ goto emptynode; } + /* + * No match yet. Continue seeking the given name. + * + * We are iterating in order by oid_number, so skip oids lower + * than the one we are looking for. + * + * When the current oid_number is higher than the one we seek, + * that means we have reached the next oid in the sequence and + * should return it. + * + * If the oid_number matches the name at this level then we + * have to find a node to continue searching at the next level. + */ if (oidp->oid_number < *name) continue; - if (oidp->oid_number > *name) { + /* + * We have reached the next oid. + * + * For CTL_SYSCTL_NEXTNOSKIP we are done. + * + * For CTL_SYSCTL_NEXT we skip CTLTYPE_NODE (unless it + * has a handler) and move on to the children. + */ + if (!honor_skip) + return (0); if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) return (0); if (oidp->oid_handler) return (0); lsp = SYSCTL_CHILDREN(oidp); - if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, - next+1, len, level+1, oidpp)) + if (!sysctl_sysctl_next_ls(lsp, name + 1, namelen - 1, + next + 1, len, level + 1, honor_skip)) return (0); goto next; } if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) continue; - if (oidp->oid_handler) continue; - lsp = SYSCTL_CHILDREN(oidp); - if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, - len, level+1, oidpp)) + if (!sysctl_sysctl_next_ls(lsp, name + 1, namelen - 1, + next + 1, len, level + 1, honor_skip)) return (0); next: + /* + * There were no useable children in this node. + * Continue searching for the next oid at the root level. + */ namelen = 1; emptynode: + /* Reset len in case a failed recursive call changed it. */ *len = level; } - return (1); + return (ENOENT); } static int @@ -1151,18 +1199,18 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS) { int *name = (int *) arg1; u_int namelen = arg2; - int i, j, error; - struct sysctl_oid *oid; + int len, error; struct sysctl_oid_list *lsp = &sysctl__children; struct rm_priotracker tracker; - int newoid[CTL_MAXNAME]; + int next[CTL_MAXNAME]; SYSCTL_RLOCK(&tracker); - i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid); + error = sysctl_sysctl_next_ls(lsp, name, namelen, next, &len, 1, + oidp->oid_number == CTL_SYSCTL_NEXT); SYSCTL_RUNLOCK(&tracker); - if (i) - return (ENOENT); - error = SYSCTL_OUT(req, newoid, j * sizeof (int)); + if (error) + return (error); + error = SYSCTL_OUT(req, next, len * sizeof (int)); return (error); } @@ -1171,6 +1219,9 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS) * capability mode. */ static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXT, next, CTLFLAG_RD | + CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, ""); + +static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXTNOSKIP, nextnoskip, CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, ""); static int Modified: stable/12/sys/sys/sysctl.h ============================================================================== --- stable/12/sys/sys/sysctl.h Mon Nov 2 19:56:15 2020 (r367282) +++ stable/12/sys/sys/sysctl.h Mon Nov 2 20:00:50 2020 (r367283) @@ -867,11 +867,12 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); */ #define CTL_SYSCTL_DEBUG 0 /* printf all nodes */ #define CTL_SYSCTL_NAME 1 /* string name of OID */ -#define CTL_SYSCTL_NEXT 2 /* next OID */ +#define CTL_SYSCTL_NEXT 2 /* next OID, honoring CTLFLAG_SKIP */ #define CTL_SYSCTL_NAME2OID 3 /* int array of name */ #define CTL_SYSCTL_OIDFMT 4 /* OID's kind and format */ #define CTL_SYSCTL_OIDDESCR 5 /* OID's description */ #define CTL_SYSCTL_OIDLABEL 6 /* aggregation label */ +#define CTL_SYSCTL_NEXTNOSKIP 7 /* next OID, ignoring CTLFLAG_SKIP */ /* * CTL_KERN identifiers Modified: stable/12/usr.bin/truss/syscalls.c ============================================================================== --- stable/12/usr.bin/truss/syscalls.c Mon Nov 2 19:56:15 2020 (r367282) +++ stable/12/usr.bin/truss/syscalls.c Mon Nov 2 20:00:50 2020 (r367283) @@ -2339,6 +2339,9 @@ print_arg(struct syscall_args *sc, unsigned long *args fprintf(fp, "oidlabel "); print_sysctl(fp, oid + 2, len - 2); break; + case CTL_SYSCTL_NEXTNOSKIP: + fprintf(fp, "nextnoskip"); + break; default: print_sysctl(fp, oid + 1, len - 1); } _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"