Index: sbin/sysctl/sysctl.c =================================================================== --- sbin/sysctl/sysctl.c +++ sbin/sysctl/sysctl.c @@ -1196,14 +1196,15 @@ int i, j; size_t l1, l2; - name1[0] = 0; - name1[1] = 2; + name1[0] = CTL_SYSCTL; + name1[1] = (oid || Nflag || dflag || tflag) ? CTL_SYSCTL_ALLNEXT : + 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 (;;) { Index: sys/kern/kern_sysctl.c =================================================================== --- sys/kern/kern_sysctl.c +++ sys/kern/kern_sysctl.c @@ -1099,7 +1099,7 @@ 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, struct sysctl_oid **oidpp, bool skip) { struct sysctl_oid *oidp; @@ -1109,7 +1109,10 @@ *next = oidp->oid_number; *oidpp = oidp; - if ((oidp->oid_kind & (CTLFLAG_SKIP | CTLFLAG_DORMANT)) != 0) + if ((oidp->oid_kind & CTLFLAG_DORMANT) != 0) + continue; + + if (skip && (oidp->oid_kind & CTLFLAG_SKIP) != 0) continue; if (!namelen) { @@ -1120,7 +1123,7 @@ return (0); lsp = SYSCTL_CHILDREN(oidp); if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, - len, level+1, oidpp)) + len, level+1, oidpp, skip)) return (0); goto emptynode; } @@ -1135,7 +1138,7 @@ return (0); lsp = SYSCTL_CHILDREN(oidp); if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, - next+1, len, level+1, oidpp)) + next+1, len, level+1, oidpp, skip)) return (0); goto next; } @@ -1147,14 +1150,14 @@ lsp = SYSCTL_CHILDREN(oidp); if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, - len, level+1, oidpp)) + len, level+1, oidpp, skip)) return (0); next: namelen = 1; emptynode: *len = level; } - return (1); + return (ENOENT); } static int @@ -1162,18 +1165,19 @@ { int *name = (int *) arg1; u_int namelen = arg2; - int i, j, error; + int len, error; struct sysctl_oid *oid; 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, &oid, + true); 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); } @@ -1184,6 +1188,34 @@ static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXT, next, CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, ""); +static int +sysctl_sysctl_allnext(SYSCTL_HANDLER_ARGS) +{ + int *name = (int *) arg1; + u_int namelen = arg2; + int len, error; + struct sysctl_oid *oid; + struct sysctl_oid_list *lsp = &sysctl__children; + struct rm_priotracker tracker; + int next[CTL_MAXNAME]; + + SYSCTL_RLOCK(&tracker); + error = sysctl_sysctl_next_ls(lsp, name, namelen, next, &len, 1, &oid, + false); + SYSCTL_RUNLOCK(&tracker); + if (error) + return (error); + error = SYSCTL_OUT(req, next, len * sizeof (int)); + return (error); +} + +/* + * XXXRW/JA: Shouldn't return next data for nodes that we don't permit in + * capability mode. + */ +static SYSCTL_NODE(_sysctl, CTL_SYSCTL_ALLNEXT, allnext, CTLFLAG_RD | + CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_allnext, ""); + static int name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp) { @@ -2723,13 +2755,13 @@ size_t l1, l2; name1[0] = CTL_SYSCTL; - name1[1] = CTL_SYSCTL_NEXT; + name1[1] = CTL_SYSCTL_ALLNEXT; l1 = 2; if (len) { - memcpy(name1+2, oid, len * sizeof(int)); - l1 +=len; + memcpy(name1 + 2, oid, len * sizeof(int)); + l1 += len; } else { - name1[2] = 1; + name1[2] = CTL_KERN; l1++; } for (;;) { Index: sys/sys/sysctl.h =================================================================== --- sys/sys/sysctl.h +++ sys/sys/sysctl.h @@ -939,6 +939,7 @@ #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_ALLNEXT 7 /* next OID, including CTLFLAG_SKIP */ /* * CTL_KERN identifiers