1 #include "defs.h"
2 
3 #include <linux/sysctl.h>
4 
5 #include "xlat/sysctl_root.h"
6 #include "xlat/sysctl_kern.h"
7 #include "xlat/sysctl_vm.h"
8 #include "xlat/sysctl_net.h"
9 #include "xlat/sysctl_net_core.h"
10 #include "xlat/sysctl_net_unix.h"
11 #include "xlat/sysctl_net_ipv4.h"
12 #include "xlat/sysctl_net_ipv4_route.h"
13 #include "xlat/sysctl_net_ipv4_conf.h"
14 #include "xlat/sysctl_net_ipv6.h"
15 #include "xlat/sysctl_net_ipv6_route.h"
16 
SYS_FUNC(sysctl)17 SYS_FUNC(sysctl)
18 {
19 	struct __sysctl_args info;
20 	int *name;
21 	unsigned long size;
22 
23 	if (umove(tcp, tcp->u_arg[0], &info) < 0)
24 		return printargs(tcp);
25 
26 	size = sizeof(int) * (unsigned long) info.nlen;
27 	name = (size / sizeof(int) != (unsigned long) info.nlen) ? NULL : malloc(size);
28 	if (name == NULL ||
29 	    umoven(tcp, (unsigned long) info.name, size, name) < 0) {
30 		free(name);
31 		if (entering(tcp))
32 			tprintf("{%p, %d, %p, %p, %p, %lu}",
33 				info.name, info.nlen, info.oldval,
34 				info.oldlenp, info.newval, (unsigned long)info.newlen);
35 		return 0;
36 	}
37 
38 	if (entering(tcp)) {
39 		unsigned int cnt = 0, max_cnt;
40 
41 		tprints("{{");
42 
43 		if (info.nlen == 0)
44 			goto out;
45 		printxval(sysctl_root, name[0], "CTL_???");
46 		++cnt;
47 
48 		if (info.nlen == 1)
49 			goto out;
50 		switch (name[0]) {
51 		case CTL_KERN:
52 			tprints(", ");
53 			printxval(sysctl_kern, name[1], "KERN_???");
54 			++cnt;
55 			break;
56 		case CTL_VM:
57 			tprints(", ");
58 			printxval(sysctl_vm, name[1], "VM_???");
59 			++cnt;
60 			break;
61 		case CTL_NET:
62 			tprints(", ");
63 			printxval(sysctl_net, name[1], "NET_???");
64 			++cnt;
65 
66 			if (info.nlen == 2)
67 				goto out;
68 			switch (name[1]) {
69 			case NET_CORE:
70 				tprints(", ");
71 				printxval(sysctl_net_core, name[2],
72 					  "NET_CORE_???");
73 				break;
74 			case NET_UNIX:
75 				tprints(", ");
76 				printxval(sysctl_net_unix, name[2],
77 					  "NET_UNIX_???");
78 				break;
79 			case NET_IPV4:
80 				tprints(", ");
81 				printxval(sysctl_net_ipv4, name[2],
82 					  "NET_IPV4_???");
83 
84 				if (info.nlen == 3)
85 					goto out;
86 				switch (name[2]) {
87 				case NET_IPV4_ROUTE:
88 					tprints(", ");
89 					printxval(sysctl_net_ipv4_route,
90 						  name[3],
91 						  "NET_IPV4_ROUTE_???");
92 					break;
93 				case NET_IPV4_CONF:
94 					tprints(", ");
95 					printxval(sysctl_net_ipv4_conf,
96 						  name[3],
97 						  "NET_IPV4_CONF_???");
98 					break;
99 				default:
100 					goto out;
101 				}
102 				break;
103 			case NET_IPV6:
104 				tprints(", ");
105 				printxval(sysctl_net_ipv6, name[2],
106 					  "NET_IPV6_???");
107 
108 				if (info.nlen == 3)
109 					goto out;
110 				switch (name[2]) {
111 				case NET_IPV6_ROUTE:
112 					tprints(", ");
113 					printxval(sysctl_net_ipv6_route,
114 						  name[3],
115 						  "NET_IPV6_ROUTE_???");
116 					break;
117 				default:
118 					goto out;
119 				}
120 				break;
121 			default:
122 				goto out;
123 			}
124 			break;
125 		default:
126 			goto out;
127 		}
128 	out:
129 		max_cnt = info.nlen;
130 		if (abbrev(tcp) && max_cnt > max_strlen)
131 			max_cnt = max_strlen;
132 		while (cnt < max_cnt)
133 			tprintf(", %x", name[cnt++]);
134 		if (cnt < (unsigned) info.nlen)
135 			tprints(", ...");
136 		tprintf("}, %d, ", info.nlen);
137 	} else {
138 		size_t oldlen = 0;
139 		if (info.oldval == NULL) {
140 			tprints("NULL");
141 		} else if (umove(tcp, (long)info.oldlenp, &oldlen) >= 0
142 			   && info.nlen >= 2
143 			   && ((name[0] == CTL_KERN
144 				&& (name[1] == KERN_OSRELEASE
145 				    || name[1] == KERN_OSTYPE
146 #ifdef KERN_JAVA_INTERPRETER
147 				    || name[1] == KERN_JAVA_INTERPRETER
148 #endif
149 #ifdef KERN_JAVA_APPLETVIEWER
150 				    || name[1] == KERN_JAVA_APPLETVIEWER
151 #endif
152 					)))) {
153 			printpath(tcp, (size_t)info.oldval);
154 		} else {
155 			tprintf("%p", info.oldval);
156 		}
157 		tprintf(", %lu, ", (unsigned long)oldlen);
158 		if (info.newval == NULL)
159 			tprints("NULL");
160 		else if (syserror(tcp))
161 			tprintf("%p", info.newval);
162 		else
163 			printpath(tcp, (size_t)info.newval);
164 		tprintf(", %lu", (unsigned long)info.newlen);
165 	}
166 
167 	free(name);
168 	return 0;
169 }
170