1 /*
2
3 kHTTPd -- the next generation
4
5 Sysctl interface
6
7 */
8 /****************************************************************
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 ****************************************************************/
24
25
26 #include <linux/kernel.h>
27 #include <linux/errno.h>
28 #include <linux/slab.h>
29 #include <linux/net.h>
30 #include <linux/sched.h>
31 #include <linux/skbuff.h>
32 #include <linux/smp_lock.h>
33 #include <linux/sysctl.h>
34 #include <linux/un.h>
35 #include <linux/unistd.h>
36
37 #include <net/ip.h>
38 #include <net/sock.h>
39 #include <net/tcp.h>
40
41 #include <asm/atomic.h>
42 #include <asm/semaphore.h>
43 #include <asm/processor.h>
44 #include <asm/uaccess.h>
45
46 #include <linux/file.h>
47 #include "prototypes.h"
48
49
50
51 char sysctl_khttpd_docroot[200] = "/var/www";
52 int sysctl_khttpd_stop = 0;
53 int sysctl_khttpd_start = 0;
54 int sysctl_khttpd_unload = 0;
55 int sysctl_khttpd_clientport = 80;
56 int sysctl_khttpd_permreq = S_IROTH; /* "other" read-access is required by default*/
57 int sysctl_khttpd_permforbid = S_IFDIR | S_ISVTX | S_IXOTH | S_IXGRP | S_IXUSR;
58 /* forbidden is execute, directory and sticky*/
59 int sysctl_khttpd_logging = 0;
60 int sysctl_khttpd_serverport= 8080;
61
62 char sysctl_khttpd_dynamicstring[200];
63 int sysctl_khttpd_sloppymime= 0;
64 int sysctl_khttpd_threads = 2;
65 int sysctl_khttpd_maxconnect = 1000;
66
67 atomic_t khttpd_stopCount;
68
69 static struct ctl_table_header *khttpd_table_header;
70
71 static int sysctl_SecureString(ctl_table *table, int *name, int nlen,
72 void *oldval, size_t *oldlenp,
73 void *newval, size_t newlen, void **context);
74 static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
75 void *buffer, size_t *lenp);
76 static int khttpd_stop_wrap_proc_dointvec(ctl_table *table, int write, struct file *filp,
77 void *buffer, size_t *lenp);
78
79
80 static ctl_table khttpd_table[] = {
81 { NET_KHTTPD_DOCROOT,
82 "documentroot",
83 &sysctl_khttpd_docroot,
84 sizeof(sysctl_khttpd_docroot),
85 0644,
86 NULL,
87 proc_dostring,
88 &sysctl_string,
89 NULL,
90 NULL,
91 NULL
92 },
93 { NET_KHTTPD_STOP,
94 "stop",
95 &sysctl_khttpd_stop,
96 sizeof(int),
97 0644,
98 NULL,
99 khttpd_stop_wrap_proc_dointvec,
100 &sysctl_intvec,
101 NULL,
102 NULL,
103 NULL
104 },
105 { NET_KHTTPD_START,
106 "start",
107 &sysctl_khttpd_start,
108 sizeof(int),
109 0644,
110 NULL,
111 proc_dointvec,
112 &sysctl_intvec,
113 NULL,
114 NULL,
115 NULL
116 },
117 { NET_KHTTPD_UNLOAD,
118 "unload",
119 &sysctl_khttpd_unload,
120 sizeof(int),
121 0644,
122 NULL,
123 proc_dointvec,
124 &sysctl_intvec,
125 NULL,
126 NULL,
127 NULL
128 },
129 { NET_KHTTPD_THREADS,
130 "threads",
131 &sysctl_khttpd_threads,
132 sizeof(int),
133 0644,
134 NULL,
135 proc_dointvec,
136 &sysctl_intvec,
137 NULL,
138 NULL,
139 NULL
140 },
141 { NET_KHTTPD_MAXCONNECT,
142 "maxconnect",
143 &sysctl_khttpd_maxconnect,
144 sizeof(int),
145 0644,
146 NULL,
147 proc_dointvec,
148 &sysctl_intvec,
149 NULL,
150 NULL,
151 NULL
152 },
153 { NET_KHTTPD_SLOPPYMIME,
154 "sloppymime",
155 &sysctl_khttpd_sloppymime,
156 sizeof(int),
157 0644,
158 NULL,
159 proc_dointvec,
160 &sysctl_intvec,
161 NULL,
162 NULL,
163 NULL
164 },
165 { NET_KHTTPD_CLIENTPORT,
166 "clientport",
167 &sysctl_khttpd_clientport,
168 sizeof(int),
169 0644,
170 NULL,
171 proc_dointvec,
172 &sysctl_intvec,
173 NULL,
174 NULL,
175 NULL
176 },
177 { NET_KHTTPD_PERMREQ,
178 "perm_required",
179 &sysctl_khttpd_permreq,
180 sizeof(int),
181 0644,
182 NULL,
183 proc_dointvec,
184 &sysctl_intvec,
185 NULL,
186 NULL,
187 NULL
188 },
189 { NET_KHTTPD_PERMFORBID,
190 "perm_forbid",
191 &sysctl_khttpd_permforbid,
192 sizeof(int),
193 0644,
194 NULL,
195 proc_dointvec,
196 &sysctl_intvec,
197 NULL,
198 NULL,
199 NULL
200 },
201 { NET_KHTTPD_LOGGING,
202 "logging",
203 &sysctl_khttpd_logging,
204 sizeof(int),
205 0644,
206 NULL,
207 proc_dointvec,
208 &sysctl_intvec,
209 NULL,
210 NULL,
211 NULL
212 },
213 { NET_KHTTPD_SERVERPORT,
214 "serverport",
215 &sysctl_khttpd_serverport,
216 sizeof(int),
217 0644,
218 NULL,
219 proc_dointvec,
220 &sysctl_intvec,
221 NULL,
222 NULL,
223 NULL
224 },
225 { NET_KHTTPD_DYNAMICSTRING,
226 "dynamic",
227 &sysctl_khttpd_dynamicstring,
228 sizeof(sysctl_khttpd_dynamicstring),
229 0644,
230 NULL,
231 proc_dosecurestring,
232 &sysctl_SecureString,
233 NULL,
234 NULL,
235 NULL
236 },
237 {0,0,0,0,0,0,0,0,0,0,0} };
238
239
240 static ctl_table khttpd_dir_table[] = {
241 {NET_KHTTPD, "khttpd", NULL, 0, 0555, khttpd_table,0,0,0,0,0},
242 {0,0,0,0,0,0,0,0,0,0,0}
243 };
244
245 static ctl_table khttpd_root_table[] = {
246 {CTL_NET, "net", NULL, 0, 0555, khttpd_dir_table,0,0,0,0,0},
247 {0,0,0,0,0,0,0,0,0,0,0}
248 };
249
250
StartSysctl(void)251 void StartSysctl(void)
252 {
253 khttpd_table_header = register_sysctl_table(khttpd_root_table,1);
254 }
255
256
EndSysctl(void)257 void EndSysctl(void)
258 {
259 unregister_sysctl_table(khttpd_table_header);
260 }
261
proc_dosecurestring(ctl_table * table,int write,struct file * filp,void * buffer,size_t * lenp)262 static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
263 void *buffer, size_t *lenp)
264 {
265 size_t len;
266 char *p, c=0;
267 char String[256];
268
269 if ((table->data==0) || (table->maxlen==0) || (*lenp==0) ||
270 ((filp->f_pos!=0) && (write==0))) {
271 *lenp = 0;
272 return 0;
273 }
274
275 if (write!=0) {
276 len = 0;
277 p = buffer;
278 while (len < *lenp) {
279 if(get_user(c, p++))
280 return -EFAULT;
281 if (c == 0 || c == '\n')
282 break;
283 len++;
284 }
285 if (len >= table->maxlen)
286 len = table->maxlen-1;
287 if(copy_from_user(String, buffer,(unsigned long)len))
288 return -EFAULT;
289 ((char *) String)[len] = 0;
290 filp->f_pos += *lenp;
291 AddDynamicString(String);
292 } else {
293 GetSecureString(String);
294 len = strlen(String);
295 if (len > table->maxlen)
296 len = table->maxlen;
297 if (len > *lenp)
298 len = *lenp;
299 if (len!=0)
300 if(copy_to_user(buffer, String,(unsigned long)len))
301 return -EFAULT;
302 if (len < *lenp) {
303 if(put_user('\n', ((char *) buffer) + len))
304 return -EFAULT;
305 len++;
306 }
307 *lenp = len;
308 filp->f_pos += len;
309 }
310 return 0;
311 }
312
313 /* A wrapper around proc_dointvec that computes
314 * khttpd_stopCount = # of times sysctl_khttpd_stop has gone true
315 * Sensing sysctl_khttpd_stop in other threads is racy;
316 * sensing khttpd_stopCount in other threads is not.
317 */
khttpd_stop_wrap_proc_dointvec(ctl_table * table,int write,struct file * filp,void * buffer,size_t * lenp)318 static int khttpd_stop_wrap_proc_dointvec(ctl_table *table, int write, struct file *filp,
319 void *buffer, size_t *lenp)
320 {
321 int rv;
322 int oldstop = sysctl_khttpd_stop;
323 rv = proc_dointvec(table, write, filp, buffer, lenp);
324 if (sysctl_khttpd_stop && !oldstop)
325 atomic_inc(&khttpd_stopCount);
326
327 return rv;
328 }
329
330
sysctl_SecureString(ctl_table * table,int * name,int nlen,void * oldval,size_t * oldlenp,void * newval,size_t newlen,void ** context)331 static int sysctl_SecureString (/*@unused@*/ctl_table *table,
332 /*@unused@*/int *name,
333 /*@unused@*/int nlen,
334 /*@unused@*/void *oldval,
335 /*@unused@*/size_t *oldlenp,
336 /*@unused@*/void *newval,
337 /*@unused@*/size_t newlen,
338 /*@unused@*/void **context)
339 {
340 return -ENOSYS;
341 }
342