/*
* sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
*
* $Id: sysctl_net_ipv4.c,v 1.50 2001/10/20 00:00:11 davem Exp $
*
* Begun April 1, 1996, Mike Shaver.
* Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
*/
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/sysctl.h>
#include <linux/igmp.h>
#include <linux/inetdevice.h>
#include <linux/seqlock.h>
#include <net/snmp.h>
#include <net/icmp.h>
#include <net/ip.h>
#include <net/route.h>
#include <net/tcp.h>
#include <net/cipso_ipv4.h>
#include <net/inet_frag.h>
/* From af_inet.c */
extern int sysctl_ip_nonlocal_bind;
#ifdef CONFIG_SYSCTL
static int zero;
static int tcp_retr1_max = 255;
static int ip_local_port_range_min[] = { 1, 1 };
static int ip_local_port_range_max[] = { 65535, 65535 };
#endif
struct ipv4_config ipv4_config;
#ifdef CONFIG_SYSCTL
static
int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int val = IPV4_DEVCONF_ALL(FORWARDING);
int ret;
ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (write && IPV4_DEVCONF_ALL(FORWARDING) != val)
inet_forward_change();
return ret;
}
static int ipv4_sysctl_forward_strategy(ctl_table *table,
int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
int *valp = table->data;
int new;
if (!newval || !newlen)
return 0;
if (newlen != sizeof(int))
return -EINVAL;
if (get_user(new, (int __user *)newval))
return -EFAULT;
if (new == *valp)
return 0;
if (oldval && oldlenp) {
size_t len;
if (get_user(len, oldlenp))
return -EFAULT;
if (len) {
if (len > table->maxlen)
len = table->maxlen;
if (copy_to_user(oldval, valp, len))
return -EFAULT;
if (put_user(len, oldlenp))
return -EFAULT;
}
}
*valp = new;
inet_forward_change();
return 1;
}
extern seqlock_t sysctl_port_range_lock;
extern int sysctl_local_port_range[2];
/* Update system visible IP port range */
static void set_local_port_range(int range[2])
{
write_seqlock(&sysctl_port_range_lock);
sysctl_local_port_range[0] = range[0];
sysctl_local_port_range[1] = range[1];
write_sequnlock(&sysctl_port_range_lock);
}
/* Validate changes from /proc interface. */
static int ipv4_local_port_range(ctl_table *table, int write, struct file *filp,
void __user *buffer,
size_t *lenp, loff_t *ppos)
{
int ret;
int range[2] = { sysctl_local_port_range[0],
sysctl_local_port_range[1] };
ctl_table tmp = {
.data = &range,
.maxlen = sizeof(range),
.mode = table->mode,
.extra1 = &ip_local_port_range_min,
.extra2 = &ip_local_port_range_max,
};
ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos);
if (write && ret == 0) {
if (range[1] < range[0])
ret = -EINVAL;
else
set_local_port_range(range);
}
return ret;
}
/* Validate changes from sysctl interface. */
static int ipv4_sysctl_local_port_range(ctl_table *table, int __user *name,
int nlen, void __user *oldval,
size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
int ret;
int range[2] = { sysctl_local_port_range[0],
sysctl_local_port_range[1] };
ctl_table tmp = {
.data = &range,
.maxlen = sizeof(range),
.mode = table->mode,
.extra1 = &ip_local_port_range_min,
.extra2 = &ip_local_port_range_max,
};
ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen);
if (ret == 0 && newval && newlen) {
if (range[1] < range[0])
ret = -EINVAL;
else
set_local_port_range(range);
}
return ret;
}
static int proc_tcp_congestion_control