diff --git a/openbsd/sbin/sysctl/Makefile b/openbsd/sbin/sysctl/Makefile new file mode 100644 index 0000000000..dc7b875aca --- /dev/null +++ b/openbsd/sbin/sysctl/Makefile @@ -0,0 +1,15 @@ +# $OpenBSD: Makefile,v 1.6 2000/01/01 22:38:18 deraadt Exp $ + +PROG= sysctl +MAN= sysctl.8 + +CPPFLAGS+= -DINET6 + +afterinstall: + (cd ${DESTDIR}/usr/sbin; ln -sf ../../sbin/sysctl .) + +.include + +.if (${UVM} == "yes") +CFLAGS+=-DUVM +.endif diff --git a/openbsd/sbin/sysctl/pathconf.c b/openbsd/sbin/sysctl/pathconf.c new file mode 100644 index 0000000000..6879372feb --- /dev/null +++ b/openbsd/sbin/sysctl/pathconf.c @@ -0,0 +1,233 @@ +/* $NetBSD: pathconf.c,v 1.2 1995/09/30 07:12:47 thorpej Exp $ */ + +/* + * Copyright (c) 1993 + * The Regents of the University of California. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)pathconf.c 8.1 (Berkeley) 6/6/93"; +#else +static char rcsid[] = "$NetBSD: pathconf.c,v 1.2 1995/09/30 07:12:47 thorpej Exp $"; +#endif +#endif /* not lint */ + +#include +#include +#include + +#include +#include +#include +#include + +#define PC_NAMES { \ + { 0, 0 }, \ + { "link_max", CTLTYPE_INT }, \ + { "max_canon", CTLTYPE_INT }, \ + { "max_input", CTLTYPE_INT }, \ + { "name_max", CTLTYPE_INT }, \ + { "path_max", CTLTYPE_INT }, \ + { "pipe_buf", CTLTYPE_INT }, \ + { "chown_restricted", CTLTYPE_INT }, \ + { "no_trunc", CTLTYPE_INT }, \ + { "vdisable", CTLTYPE_INT }, \ +} +#define PC_MAXID 10 + +struct ctlname pcnames[] = PC_NAMES; +char names[BUFSIZ]; + +struct list { + struct ctlname *list; + int size; +}; +struct list pclist = { pcnames, PC_MAXID }; + +int Aflag, aflag, nflag, wflag, stdinflag; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char *path; + int ch; + + while ((ch = getopt(argc, argv, "Aan")) != -1) { + switch (ch) { + + case 'A': + Aflag = 1; + break; + + case 'a': + aflag = 1; + break; + + case 'n': + nflag = 1; + break; + + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc == 0) + usage(); + path = *argv++; + if (strcmp(path, "-") == 0) + stdinflag = 1; + argc--; + if (Aflag || aflag) { + listall(path, &pclist); + exit(0); + } + if (argc == 0) + usage(); + while (argc-- > 0) + parse(path, *argv, 1); + exit(0); +} + +/* + * List all variables known to the system. + */ +listall(path, lp) + char *path; + struct list *lp; +{ + int lvl2; + + if (lp->list == 0) + return; + for (lvl2 = 0; lvl2 < lp->size; lvl2++) { + if (lp->list[lvl2].ctl_name == 0) + continue; + parse(path, lp->list[lvl2].ctl_name, Aflag); + } +} + +/* + * Parse a name into an index. + * Lookup and print out the attribute if it exists. + */ +parse(pathname, string, flags) + char *pathname; + char *string; + int flags; +{ + int indx, value; + char *bufp, buf[BUFSIZ]; + + bufp = buf; + snprintf(buf, BUFSIZ, "%s", string); + if ((indx = findname(string, "top", &bufp, &pclist)) == -1) + return; + if (bufp) { + fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); + return; + } + if (stdinflag) + value = fpathconf(0, indx); + else + value = pathconf(pathname, indx); + if (value == -1) { + if (flags == 0) + return; + switch (errno) { + case EOPNOTSUPP: + fprintf(stderr, "%s: value is not available\n", string); + return; + case ENOTDIR: + fprintf(stderr, "%s: specification is incomplete\n", + string); + return; + case ENOMEM: + fprintf(stderr, "%s: type is unknown to this program\n", + string); + return; + default: + perror(string); + return; + } + } + if (!nflag) + fprintf(stdout, "%s = ", string); + fprintf(stdout, "%d\n", value); +} + +/* + * Scan a list of names searching for a particular name. + */ +findname(string, level, bufp, namelist) + char *string; + char *level; + char **bufp; + struct list *namelist; +{ + char *name; + int i; + + if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { + fprintf(stderr, "%s: incomplete specification\n", string); + return (-1); + } + for (i = 0; i < namelist->size; i++) + if (namelist->list[i].ctl_name != NULL && + strcmp(name, namelist->list[i].ctl_name) == 0) + break; + if (i == namelist->size) { + fprintf(stderr, "%s level name %s in %s is invalid\n", + level, name, string); + return (-1); + } + return (i); +} + +usage() +{ + + (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n", + "pathname [-n] variable ...", + "pathname [-n] -a", "pathname [-n] -A"); + exit(1); +} diff --git a/openbsd/sbin/sysctl/sysctl.8 b/openbsd/sbin/sysctl/sysctl.8 new file mode 100644 index 0000000000..bdab67b2eb --- /dev/null +++ b/openbsd/sbin/sysctl/sysctl.8 @@ -0,0 +1,369 @@ +.\" $OpenBSD: sysctl.8,v 1.45 2000/04/25 22:12:53 deraadt Exp $ +.\" $NetBSD: sysctl.8,v 1.4 1995/09/30 07:12:49 thorpej Exp $ +.\" +.\" Copyright (c) 1993 +.\" The Regents of the University of California. 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" @(#)sysctl.8 8.2 (Berkeley) 5/9/95 +.\" +.Dd May 9, 1995 +.Dt SYSCTL 8 +.Os +.Sh NAME +.Nm sysctl +.Nd get or set kernel state +.Sh SYNOPSIS +.Nm sysctl +.Op Fl n +.Ar name ... +.Nm sysctl +.Op Fl n +.Fl w +.Ar name=value ... +.Nm sysctl +.Op Fl n +.Fl aA +.Sh DESCRIPTION +The +.Nm sysctl +utility retrieves kernel state and allows processes with +appropriate privilege to set kernel state. +The state to be retrieved or set is described using a +``Management Information Base'' (``MIB'') style name, +described as a dotted set of components. +The +.Fl a +flag can be used to list all the currently available string or integer values. +The +.Fl A +flag will list all the known MIB names including tables. +Those with string or integer values will be printed as with the +.Fl a +flag; for the table values, +the name of the utility to retrieve them is given. +.Pp +The +.Fl n +flag specifies that the printing of the field name should be +suppressed and that only its value should be output. +This flag is useful for setting shell variables. +For example, to save the pagesize in variable psize, use: +.Bd -literal -offset indent -compact +set psize=`sysctl -n hw.pagesize` +.Ed +.Pp +If just a MIB style name is given, +the corresponding value is retrieved. +If a value is to be set, the +.Fl w +flag must be specified and the MIB name followed +by an equal sign and the new value to be used. +.Pp +The information available from +.Nm sysctl +consists of integers, strings, and tables. +The tabular information can only be retrieved by special +purpose programs such as +.Nm ps , +.Nm systat , +and +.Nm netstat . +The string and integer information is summarized below. +For a detailed description of these variable see +.Xr sysctl 3 . +The changeable column indicates whether a process with appropriate +privilege can change the value. +.Bl -column net.inet.ip.forwardingxxxxxx integerxxx +.It Sy Name Type Changeable +.It kern.ostype string no +.It kern.osrelease string no +.It kern.osrevision integer no +.It kern.osversion string no +.It kern.version string no +.It kern.maxvnodes integer yes +.It kern.maxproc integer yes +.It kern.maxfiles integer yes +.It kern.maxpartitions integer no +.It kern.rawpartition integer no +.It kern.argmax integer no +.It kern.securelevel integer raise only +.It kern.hostname string yes +.It kern.domainname string yes +.It kern.hostid u_int yes +.It kern.clockrate struct no +.It kern.posix1version integer no +.It kern.ngroups integer no +.It kern.job_control integer no +.It kern.saved_ids integer no +.It kern.link_max integer no +.It kern.max_canon integer no +.It kern.max_input integer no +.It kern.name_max integer no +.It kern.path_max integer no +.It kern.pipe_buf integer no +.It kern.chown_restricted integer no +.It kern.no_trunc integer no +.It kern.boottime struct no +.It kern.somaxconn integer yes +.It kern.sominconn integer yes +.It kern.usermount integer yes +.It kern.random struct no +.It kern.nosuidcoredump integer yes +.It kern.fsync integer no +.It kern.sysvmsg integer no +.It kern.sysvsem integer no +.It kern.sysvshm integer no +.It kern.arandom u_int no +.It vm.loadavg struct no +.It vm.psstrings struct no +.It vm.swapencrypt integer yes +.It fs.posix.setuid integer yes +.It net.inet.ip.forwarding integer yes +.It net.inet.ip.redirect integer yes +.It net.inet.ip.ttl integer yes +.\" .It net.inet.ip.mtu integer yes +.It net.inet.ip.sourceroute integer yes +.It net.inet.ip.directed-broadcast integer yes +.It net.inet.ip.portfirst integer yes +.It net.inet.ip.portlast integer yes +.It net.inet.ip.porthifirst integer yes +.It net.inet.ip.porthilast integer yes +.It net.inet.ip.maxqueue integer yes +.It net.inet.ip.encdebug integer yes +.It net.inet.ip.ipsec-acl integer yes +.It net.inet.ip.ipsec-pfs integer yes +.It net.inet.ip.ipsec-soft-allocs integer yes +.It net.inet.ip.ipsec-allocs integer yes +.It net.inet.ip.ipsec-soft-bytes integer yes +.It net.inet.ip.ipsec-bytes integer yes +.It net.inet.ip.ipsec-timeout integer yes +.It net.inet.ip.ipsec-soft-timeout integer yes +.It net.inet.ip.ipsec-soft-firstuse integer yes +.It net.inet.ip.ipsec-firstuse integer yes +.It net.inet.ip.ipsec-enc-alg string yes +.It net.inet.ip.ipsec-auth-alg string yes +.It net.inet.ip.ipsec-invalid-life integer yes +.It net.inet.icmp.maskrepl integer yes +.It net.inet.icmp.bmcastecho integer yes +.It net.inet.ipip.allow integer yes +.It net.inet.etherip.allow integer yes +.It net.inet.tcp.rfc1323 integer yes +.It net.inet.tcp.keepinittime integer yes +.It net.inet.tcp.keepidle integer yes +.It net.inet.tcp.keepintvl integer yes +.It net.inet.tcp.slowhz integer no +.It net.inet.tcp.baddynamic array yes +.It net.inet.tcp.sack integer yes +.It net.inet.tcp.mssdflt integer yes +.It net.inet.udp.checksum integer yes +.It net.inet.udp.baddynamic array yes +.It net.inet.esp.enable integer yes +.It net.inet.ah.enable integer yes +.It net.inet.gre.allow integer yes +.It net.inet.mobileip.allow integer yes +.It net.inet6.ipip.allow integer yes +.It net.inet6.ip6.forwarding integer yes +.It net.inet6.ip6.redirect integer yes +.It net.inet6.ip6.hlim integer yes +.It net.inet6.ip6.maxfragpackets integer yes +.It net.inet6.ip6.accept_rtadv integer yes +.It net.inet6.ip6.keepfaith integer yes +.It net.inet6.ip6.log_interval integer yes +.It net.inet6.ip6.hdrnestlimit integer yes +.It net.inet6.ip6.dad_count integer yes +.It net.inet6.ip6.auto_flowlabel integer yes +.It net.inet6.ip6.defmcasthlim integer yes +.It net.inet6.ip6.gifhlim integer yes +.It net.inet6.ip6.kame_version string no +.It net.inet6.ip6.use_deprecated integer yes +.It net.inet6.ip6.rr_prune integer yes +.It net.inet6.icmp6.rediraccept integer yes +.It net.inet6.icmp6.redirtimeout integer yes +.It net.inet6.icmp6.errratelimit integer yes +.It net.inet6.icmp6.nd6_prune integer yes +.It net.inet6.icmp6.nd6_delay integer yes +.It net.inet6.icmp6.nd6_umaxtries integer yes +.It net.inet6.icmp6.nd6_mmaxtries integer yes +.It net.inet6.icmp6.nd6_useloopback integer yes +.It net.inet6.icmp6.nd6_proxyall integer yes +.It net.inet6.icmp6.nodeinfo integer yes +.It net.ipx.ipx.checksum integer yes +.It net.ipx.ipx.forwarding integer yes +.It net.ipx.ipx.netbios integer yes +.It net.ipx.ipx.recvspace integer yes +.It net.ipx.ipx.sendspace integer yes +.It debug.syncprt integer yes +.It debug.busyprt integer yes +.It debug.doclusterread integer yes +.It debug.doclusterwrite integer yes +.It debug.doreallocblks integer yes +.It debug.doasyncfree integer yes +.It debug.prtrealloc integer yes +.It hw.machine string no +.It hw.model string no +.It hw.ncpu integer no +.It hw.byteorder integer no +.It hw.physmem integer no +.It hw.usermem integer no +.It hw.pagesize integer no +.It machdep.console_device dev_t no +.It machdep.apmwarn integer yes (i386 only) +.It machdep.kbdreset integer yes (i386 only) +.It machdep.allowaperture integer yes (i386 only, XFree86) +.It user.cs_path string no +.It user.bc_base_max integer no +.It user.bc_dim_max integer no +.It user.bc_scale_max integer no +.It user.bc_string_max integer no +.It user.coll_weights_max integer no +.It user.expr_nest_max integer no +.It user.line_max integer no +.It user.re_dup_max integer no +.It user.posix2_version integer no +.It user.posix2_c_bind integer no +.It user.posix2_c_dev integer no +.It user.posix2_char_term integer no +.It user.posix2_fort_dev integer no +.It user.posix2_fort_run integer no +.It user.posix2_localedef integer no +.It user.posix2_sw_dev integer no +.It user.posix2_upe integer no +.It user.stream_max integer no +.It user.tzname_max integer no +.It ddb.radix integer yes +.It ddb.max_width integer yes +.It ddb.max_line integer yes +.It ddb.tab_stop_width integer yes +.It ddb.panic integer yes +.It ddb.console integer yes +.El +.Pp +The +.Nm sysctl +program can get or set debugging variables +that have been identified for its display. +This information can be obtained by using the command: +.Bd -literal -offset indent +sysctl debug +.Ed +In addition, +.Nm sysctl +can extract information about the filesystems that have been compiled +into the running system. +This information can be obtained by using the command: +.Bd -literal -offset indent +sysctl vfs +.Ed +By default, only filesystems that are actively being used are listed. +Use of the +.Fl A +flag lists all the filesystems compiled into the running kernel. +.Sh EXAMPLES +For example, to retrieve the maximum number of processes allowed +in the system, one would use the follow request: +.Bd -literal -offset indent -compact +sysctl kern.maxproc +.Ed +.Pp +To set the maximum number of processes allowed +in the system to 1000, one would use the follow request: +.Bd -literal -offset indent -compact +sysctl -w kern.maxproc=1000 +.Ed +.Pp +Information about the system clock rate may be obtained with: +.Bd -literal -offset indent -compact +sysctl kern.clockrate +.Ed +.Pp +Information about the load average history may be obtained with +.Bd -literal -offset indent -compact +sysctl vm.loadavg +.Ed +.Pp +To make the +.Xr chown 2 +system call use traditional BSD semantics (don't clear setuid/setgid bits), +one would do the following: +.Bd -literal -offset indent -compact +sysctl -w fs.posix.setuid=0 +.Ed +.Pp +Set the list of reserved TCP ports that should not be allocated +by the kernel dynamically. +This can be used to keep daemons +from stealing a specific port that another program needs to function. +List elements may be separated by commas and/or whitespace. +.Bd -literal -offset indent -compact +sysctl -w net.inet.tcp.baddynamic=749,750,751,760,761,871 +.Ed +.Pp +It is also possible to add or remove ports from the current list. +.Bd -literal -offset indent -compact +sysctl -w net.inet.tcp.baddynamic=+748 +sysctl -w net.inet.tcp.baddynamic=-871 +.Ed +.Sh FILES +.Bl -tag -width -compact +.It Pa +definitions for top level identifiers, second level kernel and hardware +identifiers, and user level identifiers +.It Pa +definitions for +.Xr random 4 +device's statistics structure +.It Pa +definitions for second level network identifiers +.It Pa +definitions for third level profiling identifiers +.It Pa +definitions for second level virtual memory identifiers +.It Pa +definitions for third level Internet identifiers and +fourth level IP identifiers +.It Pa +definitions for fourth level ICMP identifiers +.It Pa +definitions for fourth level TCP identifiers +.It Pa +definitions for fourth level UDP identifiers +.It Pa +definitions for third level IPX identifiers and +fourth level IPX identifiers +.It Pa +definitions for second level ddb identifiers +.El +.Sh SEE ALSO +.Xr sysctl 3 +.Sh HISTORY +.Nm sysctl +first appeared in +.Bx 4.4 . diff --git a/openbsd/sbin/sysctl/sysctl.c b/openbsd/sbin/sysctl/sysctl.c new file mode 100644 index 0000000000..3b053f92bc --- /dev/null +++ b/openbsd/sbin/sysctl/sysctl.c @@ -0,0 +1,1282 @@ +/* $OpenBSD: sysctl.c,v 1.49 2000/04/10 19:50:50 mickey Exp $ */ +/* $NetBSD: sysctl.c,v 1.9 1995/09/30 07:12:50 thorpej Exp $ */ + +/* + * Copyright (c) 1993 + * The Regents of the University of California. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95"; +#else +static char *rcsid = "$OpenBSD: sysctl.c,v 1.49 2000/04/10 19:50:50 mickey Exp $"; +#endif +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef INET6 +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef CPU_BIOS +#include +#endif + +struct ctlname topname[] = CTL_NAMES; +struct ctlname kernname[] = CTL_KERN_NAMES; +struct ctlname vmname[] = CTL_VM_NAMES; +struct ctlname fsname[] = CTL_FS_NAMES; +struct ctlname netname[] = CTL_NET_NAMES; +struct ctlname hwname[] = CTL_HW_NAMES; +struct ctlname username[] = CTL_USER_NAMES; +struct ctlname debugname[CTL_DEBUG_MAXID]; +struct ctlname *vfsname; +#ifdef CTL_MACHDEP_NAMES +struct ctlname machdepname[] = CTL_MACHDEP_NAMES; +#endif +struct ctlname ddbname[] = CTL_DDB_NAMES; +char names[BUFSIZ]; +int lastused; + +struct list { + struct ctlname *list; + int size; +}; +struct list toplist = { topname, CTL_MAXID }; +struct list secondlevel[] = { + { 0, 0 }, /* CTL_UNSPEC */ + { kernname, KERN_MAXID }, /* CTL_KERN */ + { vmname, VM_MAXID }, /* CTL_VM */ + { fsname, FS_MAXID }, /* CTL_FS */ + { netname, NET_MAXID }, /* CTL_NET */ + { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ + { hwname, HW_MAXID }, /* CTL_HW */ +#ifdef CTL_MACHDEP_NAMES + { machdepname, CPU_MAXID }, /* CTL_MACHDEP */ +#else + { 0, 0 }, /* CTL_MACHDEP */ +#endif + { username, USER_MAXID }, /* CTL_USER_NAMES */ + { ddbname, DBCTL_MAXID }, /* CTL_DDB_NAMES */ + { 0, 0 }, /* CTL_VFS */ +}; + +int Aflag, aflag, nflag, wflag; + +/* + * Variables requiring special processing. + */ +#define CLOCK 0x00000001 +#define BOOTTIME 0x00000002 +#define CHRDEV 0x00000004 +#define BLKDEV 0x00000008 +#define RNDSTATS 0x00000010 +#define BADDYNAMIC 0x00000020 +#define BIOSGEO 0x00000040 +#define BIOSDEV 0x00000080 +#define MAJ2DEV 0x00000100 +#define UNSIGNED 0x00000200 + +/* prototypes */ +void debuginit __P((void)); +void listall __P((char *, struct list *)); +void parse __P((char *, int)); +void parse_baddynamic __P((int *, size_t, char *, void **, size_t *, int, int)); +void usage __P((void)); +int findname __P((char *, char *, char **, struct list *)); +int sysctl_inet __P((char *, char **, int *, int, int *)); +#ifdef INET6 +int sysctl_inet6 __P((char *, char **, int *, int, int *)); +#endif +int sysctl_ipx __P((char *, char **, int *, int, int *)); +int sysctl_fs __P((char *, char **, int *, int, int *)); +int sysctl_bios __P((char *, char **, int *, int, int *)); +void vfsinit __P((void)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int ch, lvl1; + + while ((ch = getopt(argc, argv, "Aanw")) != -1) { + switch (ch) { + + case 'A': + Aflag = 1; + break; + + case 'a': + aflag = 1; + break; + + case 'n': + nflag = 1; + break; + + case 'w': + wflag = 1; + break; + + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc == 0 && (Aflag || aflag)) { + debuginit(); + vfsinit(); + for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) + listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); + exit(0); + } + if (argc == 0) + usage(); + for (; *argv != NULL; ++argv) + parse(*argv, 1); + exit(0); +} + +/* + * List all variables known to the system. + */ +void +listall(prefix, lp) + char *prefix; + struct list *lp; +{ + int lvl2; + char *cp, name[BUFSIZ]; + + if (lp->list == NULL) + return; + (void)strncpy(name, prefix, BUFSIZ-1); + name[BUFSIZ-1] = '\0'; + cp = &name[strlen(name)]; + *cp++ = '.'; + for (lvl2 = 0; lvl2 < lp->size; lvl2++) { + if (lp->list[lvl2].ctl_name == NULL) + continue; + (void)strcpy(cp, lp->list[lvl2].ctl_name); + parse(name, Aflag); + } +} + +/* + * Parse a name into a MIB entry. + * Lookup and print out the MIB entry if it exists. + * Set a new value if requested. + */ +void +parse(string, flags) + char *string; + int flags; +{ + int indx, type, state, intval; + size_t size, len, newsize = 0; + int special = 0; + void *newval = 0; + quad_t quadval; + struct list *lp; + struct vfsconf vfc; + int mib[CTL_MAXNAME]; + char *cp, *bufp, buf[BUFSIZ]; + + (void)strncpy(buf, string, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + bufp = buf; + if ((cp = strchr(string, '=')) != NULL) { + if (!wflag) + errx(2, "must specify -w to set variables"); + *strchr(buf, '=') = '\0'; + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + newval = cp; + newsize = strlen(cp); + } + if ((indx = findname(string, "top", &bufp, &toplist)) == -1) + return; + mib[0] = indx; + if (indx == CTL_VFS) + vfsinit(); + if (indx == CTL_DEBUG) + debuginit(); + lp = &secondlevel[indx]; + if (lp->list == 0) { + warnx("%s: class is not implemented", topname[indx].ctl_name); + return; + } + if (bufp == NULL) { + listall(topname[indx].ctl_name, lp); + return; + } + if ((indx = findname(string, "second", &bufp, lp)) == -1) + return; + mib[1] = indx; + type = lp->list[indx].ctl_type; + len = 2; + switch (mib[0]) { + + case CTL_KERN: + switch (mib[1]) { + case KERN_PROF: + mib[2] = GPROF_STATE; + size = sizeof(state); + if (sysctl(mib, 3, &state, &size, NULL, 0) == -1) { + if (flags == 0) + return; + if (!nflag) + (void)printf("%s: ", string); + (void)puts("kernel is not compiled for profiling"); + return; + } + if (!nflag) + (void)printf("%s = %s\n", string, + state == GMON_PROF_OFF ? "off" : "running"); + return; + case KERN_VNODE: + case KERN_FILE: + if (flags == 0) + return; + warnx("use pstat to view %s information", string); + return; + case KERN_PROC: + if (flags == 0) + return; + warnx("use ps to view %s information", string); + return; + case KERN_NTPTIME: + if (flags == 0) + return; + warnx("use xntpdc to view %s information", string); + return; + case KERN_CLOCKRATE: + special |= CLOCK; + break; + case KERN_BOOTTIME: + special |= BOOTTIME; + break; + case KERN_RND: + special |= RNDSTATS; + break; + case KERN_HOSTID: + case KERN_ARND: + special |= UNSIGNED; + break; + } + break; + + case CTL_HW: + break; + + case CTL_VM: + if (mib[1] == VM_LOADAVG) { + double loads[3]; + + getloadavg(loads, 3); + if (!nflag) + (void)printf("%s = ", string); + (void)printf("%.2f %.2f %.2f\n", loads[0], + loads[1], loads[2]); + return; + } else if (mib[1] == VM_PSSTRINGS) { + struct _ps_strings _ps; + + len = sizeof(_ps); + if (sysctl(mib, 2, &_ps, &len, NULL, 0) == -1) { + if (flags == 0) + return; + if (!nflag) + (void)printf("%s: ", string); + (void)puts("can't find ps strings"); + return; + } + if (!nflag) + (void)printf("%s = ", string); + (void)printf("%p\n", _ps.val); + return; + } +#ifdef UVM + if (mib[1] != VM_SWAPENCRYPT) { +#endif + if (flags == 0) + return; + warnx("use vmstat or systat to view %s information", string); + return; +#ifdef UVM + } +#endif + break; + + case CTL_NET: + if (mib[1] == PF_INET) { + len = sysctl_inet(string, &bufp, mib, flags, &type); + if (len < 0) + return; + + if ((mib[2] == IPPROTO_TCP && + mib[3] == TCPCTL_BADDYNAMIC) || + (mib[2] == IPPROTO_UDP && + mib[3] == UDPCTL_BADDYNAMIC)) { + + special |= BADDYNAMIC; + + if (newval != NULL) + parse_baddynamic(mib, len, string, + &newval, &newsize, flags, nflag); + } + break; + } +#ifdef INET6 + if (mib[1] == PF_INET6) { + len = sysctl_inet6(string, &bufp, mib, flags, &type); + if (len < 0) + return; + + break; + } +#endif + if (mib[1] == PF_IPX) { + len = sysctl_ipx(string, &bufp, mib, flags, &type); + if (len >= 0) + break; + return; + } + if (flags == 0) + return; + warnx("use netstat to view %s information", string); + return; + + case CTL_DEBUG: + mib[2] = CTL_DEBUG_VALUE; + len = 3; + break; + + case CTL_MACHDEP: +#ifdef CPU_CONSDEV + if (mib[1] == CPU_CONSDEV) + special |= CHRDEV; +#endif +#ifdef CPU_BLK2CHR + if (mib[1] == CPU_BLK2CHR) { + if (bufp == NULL) + return; + mib[2] = makedev(atoi(bufp),0); + bufp = NULL; + len = 3; + special |= CHRDEV; + break; + } +#endif +#ifdef CPU_CHR2BLK + if (mib[1] == CPU_CHR2BLK) { + if (bufp == NULL) + return; + mib[2] = makedev(atoi(bufp),0); + bufp = NULL; + len = 3; + special |= BLKDEV; + break; + } +#endif +#ifdef CPU_BIOS + if (mib[1] == CPU_BIOS) { + len = sysctl_bios(string, &bufp, mib, flags, &type); + if (len < 0) + return; + if (mib[2] == BIOS_DEV) + special |= BIOSDEV; + if (mib[2] == BIOS_DISKINFO) + special |= BIOSGEO; + break; + } +#endif + break; + + case CTL_FS: + len = sysctl_fs(string, &bufp, mib, flags, &type); + if (len >= 0) + break; + return; + + case CTL_VFS: + mib[3] = mib[1]; + mib[1] = VFS_GENERIC; + mib[2] = VFS_CONF; + len = 4; + size = sizeof vfc; + if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) { + if (errno != EOPNOTSUPP) + perror("vfs print"); + return; + } + if (flags == 0 && vfc.vfc_refcount == 0) + return; + if (!nflag) + fprintf(stdout, "%s has %d mounted instance%s\n", + string, vfc.vfc_refcount, + vfc.vfc_refcount != 1 ? "s" : ""); + else + fprintf(stdout, "%d\n", vfc.vfc_refcount); + return; + + case CTL_USER: + case CTL_DDB: + break; + + default: + warnx("illegal top level value: %d", mib[0]); + return; + + } + if (bufp) { + warnx("name %s in %s is unknown", bufp, string); + return; + } + if (newsize > 0) { + switch (type) { + case CTLTYPE_INT: + errno = 0; + if (special & UNSIGNED) + intval = strtoul(newval, &cp, 10); + else + intval = strtol(newval, &cp, 10); + if (*cp != '\0') { + warnx("%s: illegal value: %s", string, + (char *)newval); + return; + } + if (errno == ERANGE) { + warnx("%s: value %s out of range", string, + (char *)newval); + return; + } + newval = &intval; + newsize = sizeof(intval); + break; + + case CTLTYPE_QUAD: + (void)sscanf(newval, "%qd", &quadval); + newval = &quadval; + newsize = sizeof(quadval); + break; + } + } + size = BUFSIZ; + if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) { + if (flags == 0) + return; + switch (errno) { + case EOPNOTSUPP: + warnx("%s: value is not available", string); + return; + case ENOTDIR: + warnx("%s: specification is incomplete", string); + return; + case ENOMEM: + warnx("%s: type is unknown to this program", string); + return; + case ENXIO: + if (special & BIOSGEO) + return; + default: + warn(string); + return; + } + } + if (special & CLOCK) { + struct clockinfo *clkp = (struct clockinfo *)buf; + + if (!nflag) + (void)printf("%s = ", string); + (void)printf( + "tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n", + clkp->tick, clkp->tickadj, clkp->hz, clkp->profhz, clkp->stathz); + return; + } + if (special & BOOTTIME) { + struct timeval *btp = (struct timeval *)buf; + time_t boottime; + + if (!nflag) { + boottime = btp->tv_sec; + (void)printf("%s = %s", string, ctime(&boottime)); + } else + (void)printf("%ld\n", btp->tv_sec); + return; + } + if (special & BLKDEV) { + dev_t dev = *(dev_t *)buf; + + if (!nflag) + (void)printf("%s = %s\n", string, + devname(dev, S_IFBLK)); + else + (void)printf("0x%x\n", dev); + return; + } + if (special & CHRDEV) { + dev_t dev = *(dev_t *)buf; + + if (!nflag) + (void)printf("%s = %s\n", string, + devname(dev, S_IFCHR)); + else + (void)printf("0x%x\n", dev); + return; + } +#ifdef CPU_BIOS + if (special & BIOSGEO) { + bios_diskinfo_t *pdi = (bios_diskinfo_t *)buf; + + if (!nflag) + (void)printf("%s = ", string); + (void)printf("bootdev = 0x%x, " + "cylinders = %u, heads = %u, sectors = %u\n", + pdi->bsd_dev, pdi->bios_cylinders, pdi->bios_heads, + pdi->bios_sectors); + return; + } + if (special & BIOSDEV) { + int dev = *(int*)buf; + + if (!nflag) + (void)printf("%s = ", string); + (void) printf("0x%02x\n", dev); + return; + } +#endif + if (special & UNSIGNED) { + if (newsize == 0) { + if (!nflag) + (void)printf("%s = ", string); + (void)printf("%u\n", *(u_int *)buf); + } else { + if (!nflag) + (void)printf("%s: %u -> ", string, + *(u_int *)buf); + (void)printf("%u\n", *(u_int *)newval); + } + return; + } + if (special & RNDSTATS) { + struct rndstats *rndstats = (struct rndstats *)buf; + int i; + + if (!nflag) + (void)printf("%s = ", string); + (void)printf( + "%qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu %qu", + rndstats->rnd_total, + rndstats->rnd_used, rndstats->rnd_reads, + rndstats->arc4_reads, rndstats->arc4_nstirs, + rndstats->arc4_stirs, + rndstats->rnd_pad[0], + rndstats->rnd_pad[1], + rndstats->rnd_pad[2], + rndstats->rnd_pad[3], + rndstats->rnd_pad[4], + rndstats->rnd_waits, + rndstats->rnd_enqs, rndstats->rnd_deqs, + rndstats->rnd_drops, rndstats->rnd_drople); + for (i = 0; i < sizeof(rndstats->rnd_ed)/sizeof(rndstats->rnd_ed[0]); i++) + (void)printf(" %qu", rndstats->rnd_ed[i]); + for (i = 0; i < sizeof(rndstats->rnd_sc)/sizeof(rndstats->rnd_sc[0]); i++) + (void)printf(" %qu", rndstats->rnd_sc[i]); + for (i = 0; i < sizeof(rndstats->rnd_sb)/sizeof(rndstats->rnd_sb[0]); i++) + (void)printf(" %qu", rndstats->rnd_sb[i]); + printf("\n"); + return; + } + if (special & BADDYNAMIC) { + in_port_t port, lastport; + u_int32_t *baddynamic = (u_int32_t *)buf; + + if (!nflag) + (void)printf("%s%s", string, newsize ? ": " : " = "); + lastport = 0; + for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; port++) + if (DP_ISSET(baddynamic, port)) { + (void)printf("%s%hd", lastport ? "," : "", + port); + lastport = port; + } + if (newsize != 0) { + if (!nflag) + fputs(" -> ", stdout); + baddynamic = (u_int32_t *)newval; + lastport = 0; + for (port = IPPORT_RESERVED/2; port < IPPORT_RESERVED; + port++) + if (DP_ISSET(baddynamic, port)) { + (void)printf("%s%hd", + lastport ? "," : "", port); + lastport = port; + } + } + (void)putchar('\n'); + return; + } + switch (type) { + case CTLTYPE_INT: + if (newsize == 0) { + if (!nflag) + (void)printf("%s = ", string); + (void)printf("%d\n", *(int *)buf); + } else { + if (!nflag) + (void)printf("%s: %d -> ", string, + *(int *)buf); + (void)printf("%d\n", *(int *)newval); + } + return; + + case CTLTYPE_STRING: + if (newsize == 0) { + if (!nflag) + (void)printf("%s = ", string); + (void)puts(buf); + } else { + if (!nflag) + (void)printf("%s: %s -> ", string, buf); + (void)puts((char *)newval); + } + return; + + case CTLTYPE_QUAD: + if (newsize == 0) { + if (!nflag) + (void)printf("%s = ", string); + (void)printf("%qd\n", *(quad_t *)buf); + } else { + if (!nflag) + (void)printf("%s: %qd -> ", string, + *(quad_t *)buf); + (void)printf("%qd\n", *(quad_t *)newval); + } + return; + + case CTLTYPE_STRUCT: + warnx("%s: unknown structure returned", string); + return; + + default: + case CTLTYPE_NODE: + warnx("%s: unknown type returned", string); + return; + } +} + +void +parse_baddynamic(mib, len, string, newvalp, newsizep, flags, nflag) + int mib[]; + size_t len; + char *string; + void **newvalp; + size_t *newsizep; + int flags; + int nflag; +{ + static u_int32_t newbaddynamic[DP_MAPSIZE]; + in_port_t port; + size_t size; + char action, *cp; + + if (strchr((char *)*newvalp, '+') || strchr((char *)*newvalp, '-')) { + size = sizeof(newbaddynamic); + if (sysctl(mib, len, newbaddynamic, &size, 0, 0) == -1) { + if (flags == 0) + return; + if (!nflag) + (void)printf("%s: ", string); + (void)puts("kernel does contain bad dynamic port tables"); + return; + } + + while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { + if (*cp != '+' && *cp != '-') + errx(1, "cannot mix +/- with full list"); + action = *cp++; + port = atoi(cp); + if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) + errx(1, "invalid port, range is %d to %d", + IPPORT_RESERVED/2, IPPORT_RESERVED-1); + if (action == '+') + DP_SET(newbaddynamic, port); + else + DP_CLR(newbaddynamic, port); + } + } else { + (void)memset((void *)newbaddynamic, 0, sizeof(newbaddynamic)); + while (*newvalp && (cp = strsep((char **)newvalp, ", \t")) && *cp) { + port = atoi(cp); + if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED) + errx(1, "invalid port, range is %d to %d", + IPPORT_RESERVED/2, IPPORT_RESERVED-1); + DP_SET(newbaddynamic, port); + } + } + + *newvalp = (void *)newbaddynamic; + *newsizep = sizeof(newbaddynamic); +} + +/* + * Initialize the set of debugging names + */ +void +debuginit() +{ + int mib[3], loc, i; + size_t size; + + if (secondlevel[CTL_DEBUG].list != 0) + return; + secondlevel[CTL_DEBUG].list = debugname; + mib[0] = CTL_DEBUG; + mib[2] = CTL_DEBUG_NAME; + for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) { + mib[1] = i; + size = BUFSIZ - loc; + if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) + continue; + debugname[i].ctl_name = &names[loc]; + debugname[i].ctl_type = CTLTYPE_INT; + loc += size; + } + lastused = loc; +} + +/* + * Initialize the set of filesystem names + */ +void +vfsinit() +{ + int mib[4], maxtypenum, cnt, loc, size; + struct vfsconf vfc; + size_t buflen; + + if (secondlevel[CTL_VFS].list != 0) + return; + mib[0] = CTL_VFS; + mib[1] = VFS_GENERIC; + mib[2] = VFS_MAXTYPENUM; + buflen = 4; + if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0) + return; + if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == 0) + return; + memset(vfsname, 0, maxtypenum * sizeof(*vfsname)); + mib[2] = VFS_CONF; + buflen = sizeof vfc; + for (loc = lastused, cnt = 0; cnt < maxtypenum; cnt++) { + mib[3] = cnt; + if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) { + if (errno == EOPNOTSUPP) + continue; + perror("vfsinit"); + free(vfsname); + return; + } + strcat(&names[loc], vfc.vfc_name); + vfsname[cnt].ctl_name = &names[loc]; + vfsname[cnt].ctl_type = CTLTYPE_INT; + size = strlen(vfc.vfc_name) + 1; + loc += size; + } + lastused = loc; + secondlevel[CTL_VFS].list = vfsname; + secondlevel[CTL_VFS].size = maxtypenum; + return; +} + +struct ctlname posixname[] = CTL_FS_POSIX_NAMES; +struct list fslist = { posixname, FS_POSIX_MAXID }; + +/* + * handle file system requests + */ +int +sysctl_fs(string, bufpp, mib, flags, typep) + char *string; + char **bufpp; + int mib[]; + int flags; + int *typep; +{ + int indx; + + if (*bufpp == NULL) { + listall(string, &fslist); + return(-1); + } + if ((indx = findname(string, "third", bufpp, &fslist)) == -1) + return(-1); + mib[2] = indx; + *typep = fslist.list[indx].ctl_type; + return(3); +} + +#ifdef CPU_BIOS +struct ctlname biosname[] = CTL_BIOS_NAMES; +struct list bioslist = { biosname, BIOS_MAXID }; + +/* + * handle BIOS requests + */ +int +sysctl_bios(string, bufpp, mib, flags, typep) + char *string; + char **bufpp; + int mib[]; + int flags; + int *typep; +{ + char *name; + int indx; + + if (*bufpp == NULL) { + listall(string, &bioslist); + return(-1); + } + if ((indx = findname(string, "third", bufpp, &bioslist)) == -1) + return(-1); + mib[2] = indx; + if (indx == BIOS_DISKINFO) { + if (*bufpp == NULL) { + char name[BUFSIZ]; + + /* scan all the bios devices */ + for (indx = 0; indx < 256; indx++) { + snprintf(name, sizeof(name), "%s.%u", + string, indx); + parse(name, 1); + } + return(-1); + } + if ((name = strsep(bufpp, ".")) == NULL) { + warnx("%s: incomplete specification", string); + return(-1); + } + mib[3] = atoi(name); + *typep = CTLTYPE_STRUCT; + return 4; + } else { + *typep = bioslist.list[indx].ctl_type; + return(3); + } +} +#endif + +struct ctlname inetname[] = CTL_IPPROTO_NAMES; +struct ctlname ipname[] = IPCTL_NAMES; +struct ctlname icmpname[] = ICMPCTL_NAMES; +struct ctlname ipipname[] = IPIPCTL_NAMES; +struct ctlname tcpname[] = TCPCTL_NAMES; +struct ctlname udpname[] = UDPCTL_NAMES; +struct ctlname espname[] = ESPCTL_NAMES; +struct ctlname ahname[] = AHCTL_NAMES; +struct ctlname etheripname[] = ETHERIPCTL_NAMES; +struct ctlname grename[] = GRECTL_NAMES; +struct ctlname mobileipname[] = MOBILEIPCTL_NAMES; +struct list inetlist = { inetname, IPPROTO_MAXID }; +struct list inetvars[] = { + { ipname, IPCTL_MAXID }, /* ip */ + { icmpname, ICMPCTL_MAXID }, /* icmp */ + { 0, 0 }, /* igmp */ + { 0, 0 }, /* ggmp */ + { ipipname, IPIPCTL_MAXID }, /* ipencap */ + { 0, 0 }, + { tcpname, TCPCTL_MAXID }, /* tcp */ + { 0, 0 }, + { 0, 0 }, /* egp */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, /* pup */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { udpname, UDPCTL_MAXID }, /* udp */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { grename, GRECTL_MAXID }, /* GRE */ + { 0, 0 }, + { 0, 0 }, + { espname, ESPCTL_MAXID }, /* esp */ + { ahname, AHCTL_MAXID }, /* ah */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { mobileipname, MOBILEIPCTL_MAXID }, /* mobileip */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { etheripname, ETHERIPCTL_MAXID }, +}; + +/* + * handle internet requests + */ +int +sysctl_inet(string, bufpp, mib, flags, typep) + char *string; + char **bufpp; + int mib[]; + int flags; + int *typep; +{ + struct list *lp; + int indx; + + if (*bufpp == NULL) { + listall(string, &inetlist); + return(-1); + } + if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) + return(-1); + mib[2] = indx; + if (indx < IPPROTO_MAXID && inetvars[indx].list != NULL) + lp = &inetvars[indx]; + else if (!flags) + return(-1); + else { + warnx("%s: no variables defined for this protocol", string); + return(-1); + } + if (*bufpp == NULL) { + listall(string, lp); + return(-1); + } + if ((indx = findname(string, "fourth", bufpp, lp)) == -1) + return(-1); + mib[3] = indx; + *typep = lp->list[indx].ctl_type; + return(4); +} + +#ifdef INET6 +struct ctlname inet6name[] = CTL_IPV6PROTO_NAMES; +struct ctlname ip6name[] = IPV6CTL_NAMES; +struct ctlname icmp6name[] = ICMPV6CTL_NAMES; +struct ctlname pim6name[] = PIMCTL_NAMES; +struct list inet6list = { inet6name, IPV6PROTO_MAXID }; +struct list inet6vars[] = { +/*0*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, +/*10*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, +/*20*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, +/*30*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, +/*40*/ { 0, 0 }, + { ip6name, IPV6CTL_MAXID }, /* ipv6 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, +/*50*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { icmp6name, ICMPV6CTL_MAXID }, /* icmp6 */ + { 0, 0 }, +/*60*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, +/*70*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, +/*80*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, +/*90*/ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, +/*100*/ { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { pim6name, PIMCTL_MAXID }, /* pim6 */ +}; + +/* + * handle internet6 requests + */ +int +sysctl_inet6(string, bufpp, mib, flags, typep) + char *string; + char **bufpp; + int mib[]; + int flags; + int *typep; +{ + struct list *lp; + int indx; + + if (*bufpp == NULL) { + listall(string, &inet6list); + return(-1); + } + if ((indx = findname(string, "third", bufpp, &inet6list)) == -1) + return(-1); + mib[2] = indx; + if (indx < IPV6PROTO_MAXID && inet6vars[indx].list != NULL) + lp = &inet6vars[indx]; + else if (!flags) + return(-1); + else { + warnx("%s: no variables defined for this protocol", string); + return(-1); + } + if (*bufpp == NULL) { + listall(string, lp); + return(-1); + } + if ((indx = findname(string, "fourth", bufpp, lp)) == -1) + return(-1); + mib[3] = indx; + *typep = lp->list[indx].ctl_type; + return(4); +} +#endif + +struct ctlname ipxname[] = CTL_IPXPROTO_NAMES; +struct ctlname ipxpname[] = IPXCTL_NAMES; +struct ctlname spxpname[] = SPXCTL_NAMES; +struct list ipxlist = { ipxname, IPXCTL_MAXID }; +struct list ipxvars[] = { + { ipxpname, IPXCTL_MAXID }, /* ipx */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { spxpname, SPXCTL_MAXID }, +}; + +/* + * Handle internet requests + */ +int +sysctl_ipx(string, bufpp, mib, flags, typep) + char *string; + char **bufpp; + int mib[]; + int flags; + int *typep; +{ + struct list *lp; + int indx; + + if (*bufpp == NULL) { + listall(string, &ipxlist); + return(-1); + } + if ((indx = findname(string, "third", bufpp, &ipxlist)) == -1) + return(-1); + mib[2] = indx; + if (indx <= IPXPROTO_SPX && ipxvars[indx].list != NULL) + lp = &ipxvars[indx]; + else if (!flags) + return(-1); + else { + warnx("%s: no variables defined for this protocol", string); + return(-1); + } + if (*bufpp == NULL) { + listall(string, lp); + return(-1); + } + if ((indx = findname(string, "fourth", bufpp, lp)) == -1) + return(-1); + mib[3] = indx; + *typep = lp->list[indx].ctl_type; + return(4); +} + +/* + * Scan a list of names searching for a particular name. + */ +int +findname(string, level, bufp, namelist) + char *string; + char *level; + char **bufp; + struct list *namelist; +{ + char *name; + int i; + + if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { + warnx("%s: incomplete specification", string); + return(-1); + } + for (i = 0; i < namelist->size; i++) + if (namelist->list[i].ctl_name != NULL && + strcmp(name, namelist->list[i].ctl_name) == 0) + break; + if (i == namelist->size) { + warnx("%s level name %s in %s is invalid", level, name, string); + return(-1); + } + return(i); +} + +void +usage() +{ + + (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", + "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", + "sysctl [-n] -a", "sysctl [-n] -A"); + exit(1); +}