/*
kHTTPd -- the next generation
Sysctl interface
*/
/****************************************************************
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
****************************************************************/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/net.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/smp_lock.h>
#include <linux/sysctl.h>
#include <linux/un.h>
#include <linux/unistd.h>
#include <net/ip.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <linux/file.h>
#include "prototypes.h"
char sysctl_khttpd_docroot[200] = "/var/www";
int sysctl_khttpd_stop = 0;
int sysctl_khttpd_start = 0;
int sysctl_khttpd_unload = 0;
int sysctl_khttpd_clientport = 80;
int sysctl_khttpd_permreq = S_IROTH; /* "other" read-access is required by default*/
int sysctl_khttpd_permforbid = S_IFDIR | S_ISVTX | S_IXOTH | S_IXGRP | S_IXUSR;
/* forbidden is execute, directory and sticky*/
int sysctl_khttpd_logging = 0;
int sysctl_khttpd_serverport= 8080;
char sysctl_khttpd_dynamicstring[200];
int sysctl_khttpd_sloppymime= 0;
int sysctl_khttpd_threads = 2;
int sysctl_khttpd_maxconnect = 1000;
atomic_t khttpd_stopCount;
static struct ctl_table_header *khttpd_table_header;
static int sysctl_SecureString(ctl_table *table, int *name, int nlen,
void *oldval, size_t *oldlenp,
void *newval, size_t newlen, void **context);
static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp);
static int khttpd_stop_wrap_proc_dointvec(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp);
static ctl_table khttpd_table[] = {
{ NET_KHTTPD_DOCROOT,
"documentroot",
&sysctl_khttpd_docroot,
sizeof(sysctl_khttpd_docroot),
0644,
NULL,
proc_dostring,
&sysctl_string,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_STOP,
"stop",
&sysctl_khttpd_stop,
sizeof(int),
0644,
NULL,
khttpd_stop_wrap_proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_START,
"start",
&sysctl_khttpd_start,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_UNLOAD,
"unload",
&sysctl_khttpd_unload,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_THREADS,
"threads",
&sysctl_khttpd_threads,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_MAXCONNECT,
"maxconnect",
&sysctl_khttpd_maxconnect,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_SLOPPYMIME,
"sloppymime",
&sysctl_khttpd_sloppymime,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_CLIENTPORT,
"clientport",
&sysctl_khttpd_clientport,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_PERMREQ,
"perm_required",
&sysctl_khttpd_permreq,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_PERMFORBID,
"perm_forbid",
&sysctl_khttpd_permforbid,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_LOGGING,
"logging",
&sysctl_khttpd_logging,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_SERVERPORT,
"serverport",
&sysctl_khttpd_serverport,
sizeof(int),
0644,
NULL,
proc_dointvec,
&sysctl_intvec,
NULL,
NULL,
NULL
},
{ NET_KHTTPD_DYNAMICSTRING,
"dynamic",
&sysctl_khttpd_dynamicstring,
sizeof(sysctl_khttpd_dynamicstring),
0644,
NULL,
proc_dosecurestring,
&sysctl_SecureString,
NULL,
NULL,
NULL
},
{0,0,0,0,0,0,0,0,0,0,0} };
static ctl_table khttpd_dir_table[] = {
{NET_KHTTPD, "khttpd", NULL, 0, 0555, khttpd_table,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0}
};
static ctl_table khttpd_root_table[] = {
{CTL_NET, "net", NULL, 0, 0555, khttpd_dir_table,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0}
};
void StartSysctl(void)
{
khttpd_table_header = register_sysctl_table(khttpd_root_table,1);
}
void EndSysctl(void)
{
unregister_sysctl_table(khttpd_table_header);
}
static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp)
{
size_t len;
char *p, c=0;
char String[256];
if ((table->data==0) || (table->maxlen==0) || (*lenp==0) ||
((filp->f_pos!=0) && (write==0))) {
*lenp = 0;
return 0;
}
if (write!=0) {
len = 0;
p = buffer;
while (len < *lenp) {
if(get_user(c, p++))
return -EFAULT;
if (c == 0 || c == '\n')
break;
len++;
}
if (len >= table->maxlen)
len = table->maxlen-1;
if(copy_from_user(String, buffer,(unsigned long)len))
return -EFAULT;
((char *) String)[len] = 0;
filp->f_pos += *lenp;
AddDynamicString(String);
} else {
GetSecureString(String);
len = strlen(String);
if (len > table->maxlen)
len = table->maxlen;
if (len > *lenp)
len = *lenp;
if (len!=0)
if(copy_to_user(buffer, String,(unsigned long)len))
return -EFAULT;
if (len < *lenp) {
if(put_user('\n', ((char *) buffer) + len))
return -EFAULT;
len++;
}
*lenp = len;
filp->f_pos += len;
}
return 0;
}
/* A wrapper around proc_dointvec that computes
* khttpd_stopCount = # of times sysctl_khttpd_stop has gone true
* Sensing sysctl_khttpd_stop in other threads is racy;
* sensing khttpd_stopCount in other threads is not.
*/
static int khttpd_stop_wrap_proc_dointvec(ctl_table *table, int write, struct file *filp,
void *buffer, size_t *lenp)
{
int rv;
int oldstop = sysctl_khttpd_stop;
rv = proc_dointvec(table, write, filp, buffer, lenp);
if (sysctl_khttpd_stop && !oldstop)
atomic_inc(&khttpd_stopCount);
return rv;
}
static int sysctl_SecureString (/*@unused@*/ctl_table *table,
/*@unused@*/int *name,
/*@unused@*/int nlen,
/*@unused@*/void *oldval,
/*@unused@*/size_t *oldlenp,
/*@unused@*/void *newval,
/*@unused@*/size_t newlen,
/*@unused@*/void **context)
{
return -ENOSYS;
}