xref: /openbsd-src/distrib/special/sysctl/sysctl.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*	$OpenBSD: sysctl.c,v 1.12 2018/06/25 16:29:00 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 2009 Theo de Raadt <deraadt@openbsd.org>
5  * Copyright (c) 2007 Kenneth R. Westerback <krw@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/sysctl.h>
23 #include <sys/uio.h>
24 
25 #include <netinet/in.h>
26 
27 #include <ctype.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 
33 #define SOIIKEY_LEN 16
34 
35 struct var {
36 	char *name;
37 	int (*print)(struct var *);
38 	int nmib;
39 	int mib[3];
40 };
41 
42 int	pstring(struct var *);
43 int	pint(struct var *);
44 
45 struct var vars[] = {
46 	{ "kern.osrelease", pstring, 2,
47 	    { CTL_KERN, KERN_OSRELEASE }},
48 	{ "hw.machine", pstring, 2,
49 	    { CTL_HW, HW_MACHINE }},
50 	{ "hw.model", pstring, 2,
51 	    { CTL_HW, HW_MODEL }},
52 	{ "hw.product", pstring, 2,
53 	    { CTL_HW, HW_PRODUCT }},
54 	{ "hw.disknames", pstring, 2,
55 	    { CTL_HW, HW_DISKNAMES }},
56 	{ "hw.ncpufound", pint, 2,
57 	    { CTL_HW, HW_NCPUFOUND }},
58 };
59 
60 int	nflag;
61 char	*name;
62 
63 int
64 pint(struct var *v)
65 {
66 	int n;
67 	size_t len = sizeof(n);
68 
69 	if (sysctl(v->mib, v->nmib, &n, &len, NULL, 0) != -1) {
70 		if (nflag == 0)
71 			printf("%s=", v->name);
72 		printf("%d\n", n);
73 		return (0);
74 	}
75 	return (1);
76 }
77 
78 int
79 pstring(struct var *v)
80 {
81 	char *p;
82 	size_t len;
83 
84 	if (sysctl(v->mib, v->nmib, NULL, &len, NULL, 0) != -1)
85 		if ((p = malloc(len)) != NULL)
86 			if (sysctl(v->mib, v->nmib, p, &len, NULL, 0) != -1) {
87 				if (nflag == 0)
88 					printf("%s=", v->name);
89 				printf("%s\n", p);
90 				return (0);
91 			}
92 	return (1);
93 }
94 
95 int
96 parse_hex_char(char ch)
97 {
98 	if (ch >= '0' && ch <= '9')
99 		return (ch - '0');
100 
101 	ch = tolower((unsigned char)ch);
102 	if (ch >= 'a' && ch <= 'f')
103 		return (ch - 'a' + 10);
104 
105 	return (-1);
106 }
107 
108 int
109 set_soii_key(char *src)
110 {
111 	uint8_t key[SOIIKEY_LEN];
112 	int mib[4] = {CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_SOIIKEY};
113 	int i, c;
114 
115 	for(i = 0; i < SOIIKEY_LEN; i++) {
116 		if ((c = parse_hex_char(src[2 * i])) == -1)
117 			return (-1);
118 		key[i] = c << 4;
119 		if ((c = parse_hex_char(src[2 * i + 1])) == -1)
120 			return (-1);
121 		key[i] |= c;
122 	}
123 
124 	return sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, NULL, key,
125 	    SOIIKEY_LEN);
126 }
127 
128 int
129 main(int argc, char *argv[])
130 {
131 	int ch, i;
132 
133 	while ((ch = getopt(argc, argv, "n")) != -1) {
134 		switch (ch) {
135 		case 'n':
136 			nflag = 1;
137 			break;
138 		default:
139 			fprintf(stderr, "usage: sysctl [-n] name\n");
140 			exit(1);
141 		}
142 	}
143 
144 	argc -= optind;
145 	argv += optind;
146 
147 	if (argc == 0) {
148 		for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++)
149 			(vars[i].print)(&vars[i]);
150 		exit(0);
151 	}
152 
153 	while (argc--) {
154 		name = *argv++;
155 		/*
156 		 * strlen("net.inet6.ip6.soiikey="
157 		 *     "00000000000000000000000000000000") == 54
158 		 * strlen("net.inet6.ip6.soiikey=") == 22
159 		 */
160 		if (strlen(name) == 54 && strncmp(name,
161 		    "net.inet6.ip6.soiikey=", 22) == 0) {
162 			set_soii_key(name + 22);
163 			continue;
164 		}
165 
166 		for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
167 			if (strcmp(name, vars[i].name) == 0) {
168 				(vars[i].print)(&vars[i]);
169 				break;
170 			}
171 		}
172 	}
173 
174 	exit(0);
175 }
176