Example #1
0
static int schar_read_proc_2(ctl_table *ctl, int write, struct file *file,
			   void *buffer, size_t *lenp, loff_t *ppos)
{
	int len = 0;

	/* someone is writing data to us */
	/* v2.6remove
 	if (write) {
		char *tmp = (char *) get_free_page(GFP_KERNEL);
		//	MSG("proc: someone wrote %u bytes\n", (unsigned)*lenp);
		if (tmp) {
			free_page((unsigned long)tmp);
			file->f_pos += *lenp;
		}
		return 0;
	}
	v2.6remove */
	len += sprintf(schar_proc_string_2, "GIGABIT DRIVER ETH2: mm \n\n");
	len += sprintf(schar_proc_string_2+len, " RECEIVE: \n");
	len += sprintf(schar_proc_string_2+len, "  recieve\t\t%ld packets\n",proc_rpackets_2);
      len += sprintf(schar_proc_string_2+len, "  receive    \t\t\t%04d%09ld bytes\n",proc_rbytesH_2,proc_rbytesL_2); 
      len += sprintf(schar_proc_string_2+len, "  memory  \t\t\t%09ld bytes\n",(BIGPHYS_PAGES_2*PAGE_SIZE));
      len += sprintf(schar_proc_string_2+len, "  rate  \t\t\t%6ld KBits/s \n",proc_rate_2/1000);
      len += sprintf(schar_proc_string_2+len, "  loop %d count %ld\n\n",ring_loop_2,ring_pnt_2);
	len += sprintf(schar_proc_string_2+len, " TRANSMIT: \n");
      len += sprintf(schar_proc_string_2+len, "  transmit\t\t%d packets \n",proc_tpackets_2);
      len += sprintf(schar_proc_string_2+len, "  transmit    \t\t\t%d%08ld bytes\n\n",proc_tbytesH_2,proc_tbytesL_2); 
  	len += sprintf(schar_proc_string_2+len, " ERROR STATISTICS: \n");
      len += sprintf(schar_proc_string_2+len, "  missing packets \t\t%ld\n",proc_pmissing_2);
	*lenp = len;
	return proc_dostring(ctl, write, file, buffer, lenp, ppos);
}
Example #2
0
static int schar_read_proc(ctl_table *ctl, int write, struct file *file,
			   void *buffer, size_t *lenp, loff_t *ppos)
{
	int len = 0;
	
	//	MSG("proc: %s\n", write ? "write" : "read");

	/* someone is writing data to us */
	/* v2.6remove
	if (write) {
		char *tmp = (char *) get_free_page(GFP_KERNEL);
		//	MSG("proc: someone wrote %u bytes\n", (unsigned)*lenp);
		if (tmp) {
		        free_page((unsigned long)tmp);
			file->f_pos += *lenp;
		}
		return 0;
	}
	v2.6remove */
	len += sprintf(schar_proc_string, "GIGABIT DRIVER SIMPLE JTAG\n\n");
	len += sprintf(schar_proc_string+len, " LEFT TO READ: \n");
        len += sprintf(schar_proc_string+len," pack_left\t\t%d packets\n",pack_left); 
	len += sprintf(schar_proc_string+len, " RECEIVE: \n");
	len += sprintf(schar_proc_string+len, "  recieve\t\t%ld packets\n",proc_rpackets);
        len += sprintf(schar_proc_string+len, "  receive    \t\t\t%02d%09ld bytes\n",proc_rbytesH,proc_rbytesL); 
        len += sprintf(schar_proc_string+len, "  memory  \t\t\t%09d bytes\n",MMT_BUF_SIZE);
 	len += sprintf(schar_proc_string+len, " TRANSMIT: \n");
        len += sprintf(schar_proc_string+len, "  transmit\t\t%d packets \n",proc_tpackets);
        len += sprintf(schar_proc_string+len, "  transmit    \t\t\t%02d%09ld bytes\n\n",proc_tbytesH,proc_tbytesL); 
	*lenp = len;
	return proc_dostring(ctl, write, file, buffer, lenp, ppos);
	
	
}
Example #3
0
static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write,
				 void __user *buffer, size_t *lenp,
				 loff_t *ppos)
{
	struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) };
	struct tcp_fastopen_context *ctxt;
	int ret;
	u32  user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */

	tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL);
	if (!tbl.data)
		return -ENOMEM;

	rcu_read_lock();
	ctxt = rcu_dereference(tcp_fastopen_ctx);
	if (ctxt)
		memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH);
	else
		memset(user_key, 0, sizeof(user_key));
	rcu_read_unlock();

	snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x",
		user_key[0], user_key[1], user_key[2], user_key[3]);
	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);

	if (write && ret == 0) {
		if (sscanf(tbl.data, "%x-%x-%x-%x", user_key, user_key + 1,
			   user_key + 2, user_key + 3) != 4) {
			ret = -EINVAL;
			goto bad_key;
		}
		/* Generate a dummy secret but don't publish it. This
		 * is needed so we don't regenerate a new key on the
		 * first invocation of tcp_fastopen_cookie_gen
		 */
		tcp_fastopen_init_key_once(false);
		tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH);
	}

bad_key:
	pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n",
	       user_key[0], user_key[1], user_key[2], user_key[3],
	       (char *)tbl.data, ret);
	kfree(tbl.data);
	return ret;
}

static struct ctl_table ipv4_table[] = {
	{
		.procname	= "tcp_timestamps",
		.data		= &sysctl_tcp_timestamps,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec
	},
	{
		.procname	= "tcp_window_scaling",
Example #4
0
// TODO: functions are almost the same, should abstract them to wrapper with proc_handler and data printer parameters
static int t1_proc_dostring(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) {
    int result;

    LOG(LC_PROC, 0, "t1: gona read %s from procfs entry, old value is: %s\n", table->procname, (char*)table->data);
    result = proc_dostring(table, write, buffer, lenp, ppos);
    LOG(LC_PROC, 0, "t1: read %s from procfs, new value is: %s\n", table->procname, (char*)table->data);
    
    return result;
}
Example #5
0
/* /proc/sys entry point for injecting up/down nid event
 * <up|down> <nid>
 */
static int
proc_peer_state(struct ctl_table *table, int write, void __user *buffer,
		size_t *lenp, loff_t *ppos)
{
	int             rc;
	int             nid;
	int             node_down;
	char            command[10];
	ENTRY;

	rc = proc_dostring(table, write, buffer, lenp, ppos);

	if (!write) {
		/* read */
		RETURN(rc);
	}

	if (kgnilnd_data.kgn_init != GNILND_INIT_ALL) {
		rc = -EINVAL;
		RETURN(rc);
	}

	/* convert to nid, up/down values */
	rc = sscanf(kgnilnd_sysctl.ksd_peer_state, "%s %d", command, &nid);
	CDEBUG(D_INFO, "command %s, nid %d\n", command, nid);

	if (rc != 2) {
		CDEBUG(D_ERROR, "invalid parameter\n");
		RETURN(rc);
	} else {
		switch (command[0]) {
		case 'd': /* down */
			node_down = 1;
			CDEBUG(D_INFO, "take node %d down\n", nid);
			break;
		case 'u': /* up */
			node_down = 0;
			CDEBUG(D_INFO, "bring node %d up\n", nid);
			break;
		default:
			CDEBUG(D_ERROR, "invalid command %s\n", command);
			RETURN(-EINVAL);
		}
	}

	CDEBUG(D_INFO, "proc_peer_state: reporting node_down %d, nid %d\n",
		      node_down, nid);
	rc = kgnilnd_report_node_state(nid, node_down);

	if (rc) {
		rc = -EINVAL;
	}

	RETURN(rc);
}
Example #6
0
static int nf_log_proc_dostring(struct ctl_table *table, int write,
			 void __user *buffer, size_t *lenp, loff_t *ppos)
{
	const struct nf_logger *logger;
	char buf[NFLOGGER_NAME_LEN];
	int r = 0;
	int tindex = (unsigned long)table->extra1;
	struct net *net = current->nsproxy->net_ns;

	if (write) {
		struct ctl_table tmp = *table;

		tmp.data = buf;
		r = proc_dostring(&tmp, write, buffer, lenp, ppos);
		if (r)
			return r;

		if (!strcmp(buf, "NONE")) {
			nf_log_unbind_pf(net, tindex);
			return 0;
		}
		mutex_lock(&nf_log_mutex);
		logger = __find_logger(tindex, buf);
		if (logger == NULL) {
			mutex_unlock(&nf_log_mutex);
			return -ENOENT;
		}
		rcu_assign_pointer(net->nf.nf_loggers[tindex], logger);
		mutex_unlock(&nf_log_mutex);
	} else {
		mutex_lock(&nf_log_mutex);
		logger = nft_log_dereference(net->nf.nf_loggers[tindex]);
		if (!logger)
			table->data = "NONE";
		else
			table->data = logger->name;
		r = proc_dostring(table, write, buffer, lenp, ppos);
		mutex_unlock(&nf_log_mutex);
	}

	return r;
}
/*
 *	Special case of dostring for the UTS structure. This has locks
 *	to observe. Should this be in kernel/sys.c ????
 */
static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	struct ctl_table uts_table;
	int r;
	memcpy(&uts_table, table, sizeof(uts_table));
	uts_table.data = get_uts(table, write);
	r = proc_dostring(&uts_table,write,filp,buffer,lenp, ppos);
	put_uts(table, write, uts_table.data);
	return r;
}
Example #8
0
static int proc_do_rss_key(struct ctl_table *table, int write,
			   void __user *buffer, size_t *lenp, loff_t *ppos)
{
	struct ctl_table fake_table;
	char buf[NETDEV_RSS_KEY_LEN * 3];

	snprintf(buf, sizeof(buf), "%*phC", NETDEV_RSS_KEY_LEN, netdev_rss_key);
	fake_table.data = buf;
	fake_table.maxlen = sizeof(buf);
	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
}
Example #9
0
/* Validate changes from /proc interface. */
static int ipv4_ping_group_range(ctl_table *table, int write,
				 void __user *buffer,
				 size_t *lenp, loff_t *ppos)
{
	struct user_namespace *user_ns = current_user_ns();
	int ret;
	gid_t urange[2];
	kgid_t low, high;
	ctl_table tmp = {
		.data = &urange,
		.maxlen = sizeof(urange),
		.mode = table->mode,
		.extra1 = &ip_ping_group_range_min,
		.extra2 = &ip_ping_group_range_max,
	};

	inet_get_ping_group_range_table(table, &low, &high);
	urange[0] = from_kgid_munged(user_ns, low);
	urange[1] = from_kgid_munged(user_ns, high);
	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);

	if (write && ret == 0) {
		low = make_kgid(user_ns, urange[0]);
		high = make_kgid(user_ns, urange[1]);
		if (!gid_valid(low) || !gid_valid(high) ||
		    (urange[1] < urange[0]) || gid_lt(high, low)) {
			low = make_kgid(&init_user_ns, 1);
			high = make_kgid(&init_user_ns, 0);
		}
		set_ping_group_range(table, low, high);
	}

	return ret;
}

static int proc_tcp_congestion_control(ctl_table *ctl, int write,
				       void __user *buffer, size_t *lenp, loff_t *ppos)
{
	char val[TCP_CA_NAME_MAX];
	ctl_table tbl = {
		.data = val,
		.maxlen = TCP_CA_NAME_MAX,
	};
	int ret;

	tcp_get_default_congestion_control(val);

	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
	if (write && ret == 0)
		ret = tcp_set_default_congestion_control(val);
	return ret;
}
Example #10
0
/* And the same for proc */
int proc_dolasatstring(ctl_table *table, int write,
		       void *buffer, size_t *lenp, loff_t *ppos)
{
	int r;

	r = proc_dostring(table, write, buffer, lenp, ppos);
	if ((!write) || r)
		return r;

	lasat_write_eeprom_info();

	return 0;
}
Example #11
0
/* And the same for proc */
int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
                       void *buffer, size_t *lenp, loff_t *ppos)
{
    int r;
    mutex_lock(&lasat_info_mutex);
    r = proc_dostring(table, write, filp, buffer, lenp, ppos);
    if ( (!write) || r) {
        mutex_unlock(&lasat_info_mutex);
        return r;
    }
    lasat_write_eeprom_info();
    mutex_unlock(&lasat_info_mutex);
    return 0;
}
Example #12
0
static int do_devname(struct ctl_table *table, int write,
		      void __user *buffer, size_t *lenp, loff_t *ppos)
{
	int ret;

	ret = proc_dostring(table, write, buffer, lenp, ppos);
	if (ret == 0 && write) {
		struct ias_value *val;

		val = irias_new_string_value(sysctl_devname);
		if (val)
			irias_object_change_attribute("Device", "DeviceName", val);
	}
	return ret;
}
Example #13
0
/*
 *	Special case of dostring for the UTS structure. This has locks
 *	to observe. Should this be in kernel/sys.c ????
 */
static int proc_do_uts_string(ctl_table *table, int write,
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	struct ctl_table uts_table;
	int r;
	memcpy(&uts_table, table, sizeof(uts_table));
	uts_table.data = get_uts(table, write);
	r = proc_dostring(&uts_table,write,buffer,lenp, ppos);
	put_uts(table, write, uts_table.data);

	if (write)
		proc_sys_poll_notify(table->poll);

	return r;
}
Example #14
0
static int do_devname(ctl_table *table, int write, struct file *filp,
		      void *buffer, size_t *lenp)
{
	int ret;

	ret = proc_dostring(table, write, filp, buffer, lenp);
	if (ret == 0 && write) {
		struct ias_value *val;

		val = irias_new_string_value(sysctl_devname);
		if (val)
			irias_object_change_attribute("Device", "DeviceName", val);
	}
	return ret;
}
Example #15
0
static int proc_tcp_available_congestion_control(struct ctl_table *ctl,
						 int write,
						 void __user *buffer, size_t *lenp,
						 loff_t *ppos)
{
	struct ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX, };
	int ret;

	tbl.data = kmalloc(tbl.maxlen, GFP_USER);
	if (!tbl.data)
		return -ENOMEM;
	tcp_get_available_congestion_control(tbl.data, TCP_CA_BUF_MAX);
	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
	kfree(tbl.data);
	return ret;
}
Example #16
0
static int proc_sctp_do_hmac_alg(ctl_table *ctl,
				int write,
				void __user *buffer, size_t *lenp,
				loff_t *ppos)
{
	struct net *net = current->nsproxy->net_ns;
	char tmp[8];
	ctl_table tbl;
	int ret;
	int changed = 0;
	char *none = "none";

	memset(&tbl, 0, sizeof(struct ctl_table));

	if (write) {
		tbl.data = tmp;
		tbl.maxlen = 8;
	} else {
		tbl.data = net->sctp.sctp_hmac_alg ? : none;
		tbl.maxlen = strlen(tbl.data);
	}
		ret = proc_dostring(&tbl, write, buffer, lenp, ppos);

	if (write) {
#ifdef CONFIG_CRYPTO_MD5
		if (!strncmp(tmp, "md5", 3)) {
			net->sctp.sctp_hmac_alg = "md5";
			changed = 1;
		}
#endif
#ifdef CONFIG_CRYPTO_SHA1
		if (!strncmp(tmp, "sha1", 4)) {
			net->sctp.sctp_hmac_alg = "sha1";
			changed = 1;
		}
#endif
		if (!strncmp(tmp, "none", 4)) {
			net->sctp.sctp_hmac_alg = NULL;
			changed = 1;
		}

		if (!changed)
			ret = -EINVAL;
	}

	return ret;
}
Example #17
0
static int proc_tcp_congestion_control(ctl_table *ctl, int write,
				       void __user *buffer, size_t *lenp, loff_t *ppos)
{
	char val[TCP_CA_NAME_MAX];
	ctl_table tbl = {
		.data = val,
		.maxlen = TCP_CA_NAME_MAX,
	};
	int ret;

	tcp_get_default_congestion_control(val);

	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
	if (write && ret == 0)
		ret = tcp_set_default_congestion_control(val);
	return ret;
}
Example #18
0
static int set_default_qdisc(struct ctl_table *table, int write,
			     void __user *buffer, size_t *lenp, loff_t *ppos)
{
	char id[IFNAMSIZ];
	struct ctl_table tbl = {
		.data = id,
		.maxlen = IFNAMSIZ,
	};
	int ret;

	qdisc_get_default(id, IFNAMSIZ);

	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
	if (write && ret == 0)
		ret = qdisc_set_default(id);
	return ret;
}
/* Validate changes from /proc interface. */
static int ipv4_local_port_range(ctl_table *table, int write,
				 void __user *buffer,
				 size_t *lenp, loff_t *ppos)
{
	int ret;
	int range[2];
	ctl_table tmp = {
		.data = &range,
		.maxlen = sizeof(range),
		.mode = table->mode,
		.extra1 = &ip_local_port_range_min,
		.extra2 = &ip_local_port_range_max,
	};

	inet_get_local_port_range(range, range + 1);
	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);

	if (write && ret == 0) {
		if (range[1] < range[0])
			ret = -EINVAL;
		else
			set_local_port_range(range);
	}

	return ret;
}

static int proc_tcp_congestion_control(ctl_table *ctl, int write,
				       void __user *buffer, size_t *lenp, loff_t *ppos)
{
	char val[TCP_CA_NAME_MAX];
	ctl_table tbl = {
		.data = val,
		.maxlen = TCP_CA_NAME_MAX,
	};
	int ret;

	tcp_get_default_congestion_control(val);

	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
	if (write && ret == 0)
		ret = tcp_set_default_congestion_control(val);
	return ret;
}
Example #20
0
static int utsmod_proc_do_string(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) {
  struct ctl_table utsmod_table;
  int r;

  if (write) {
    // init_uts_ns is read only
    if (current->nsproxy->uts_ns == &init_uts_ns)
      return -EPERM;

    // require CAP_SYS_ADMIN
    if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
      return -EPERM;
  }

  // update current utsns
  memcpy(&utsmod_table, table, sizeof(utsmod_table));
  utsmod_table.data = utsmod_get_uts(table, write);
  r = proc_dostring(&utsmod_table, write, buffer, lenp, ppos);
  utsmod_put_uts(table, write, utsmod_table.data);

  return r;
}
Example #21
0
/*
 *	Special case of dostring for the UTS structure. This has locks
 *	to observe. Should this be in kernel/sys.c ????
 */
static int proc_do_uts_string(struct ctl_table *table, int write,
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	struct ctl_table uts_table;
	int r;
	char tmp_data[__NEW_UTS_LEN + 1];

	memcpy(&uts_table, table, sizeof(uts_table));
	uts_table.data = tmp_data;

	/*
	 * Buffer the value in tmp_data so that proc_dostring() can be called
	 * without holding any locks.
	 * We also need to read the original value in the write==1 case to
	 * support partial writes.
	 */
	down_read(&uts_sem);
	memcpy(tmp_data, get_uts(table), sizeof(tmp_data));
	up_read(&uts_sem);
	r = proc_dostring(&uts_table, write, buffer, lenp, ppos);

	if (write) {
		/*
		 * Write back the new value.
		 * Note that, since we dropped uts_sem, the result can
		 * theoretically be incorrect if there are two parallel writes
		 * at non-zero offsets to the same sysctl.
		 */
		down_write(&uts_sem);
		memcpy(get_uts(table), tmp_data, sizeof(tmp_data));
		up_write(&uts_sem);
		proc_sys_poll_notify(table->poll);
	}

	return r;
}
Example #22
0
static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write,
				 void __user *buffer, size_t *lenp,
				 loff_t *ppos)
{
	struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) };
	struct tcp_fastopen_context *ctxt;
	int ret;
	u32  user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */

	tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL);
	if (!tbl.data)
		return -ENOMEM;

	rcu_read_lock();
	ctxt = rcu_dereference(tcp_fastopen_ctx);
	if (ctxt)
		memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH);
	else
		memset(user_key, 0, sizeof(user_key));
	rcu_read_unlock();

	snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x",
		user_key[0], user_key[1], user_key[2], user_key[3]);
	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);

	if (write && ret == 0) {
		if (sscanf(tbl.data, "%x-%x-%x-%x", user_key, user_key + 1,
			   user_key + 2, user_key + 3) != 4) {
			ret = -EINVAL;
			goto bad_key;
		}
		/* Generate a dummy secret but don't publish it. This
		 * is needed so we don't regenerate a new key on the
		 * first invocation of tcp_fastopen_cookie_gen
		 */
		tcp_fastopen_init_key_once(false);
		tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH);
	}

bad_key:
	pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n",
	       user_key[0], user_key[1], user_key[2], user_key[3],
	       (char *)tbl.data, ret);
	kfree(tbl.data);
	return ret;
}

static void proc_configure_early_demux(int enabled, int protocol)
{
	struct net_protocol *ipprot;
#if IS_ENABLED(CONFIG_IPV6)
	struct inet6_protocol *ip6prot;
#endif

	rcu_read_lock();

	ipprot = rcu_dereference(inet_protos[protocol]);
	if (ipprot)
		ipprot->early_demux = enabled ? ipprot->early_demux_handler :
						NULL;

#if IS_ENABLED(CONFIG_IPV6)
	ip6prot = rcu_dereference(inet6_protos[protocol]);
	if (ip6prot)
		ip6prot->early_demux = enabled ? ip6prot->early_demux_handler :
						 NULL;
#endif
	rcu_read_unlock();
}

static int proc_tcp_early_demux(struct ctl_table *table, int write,
				void __user *buffer, size_t *lenp, loff_t *ppos)
{
	int ret = 0;

	ret = proc_dointvec(table, write, buffer, lenp, ppos);

	if (write && !ret) {
		int enabled = init_net.ipv4.sysctl_tcp_early_demux;

		proc_configure_early_demux(enabled, IPPROTO_TCP);
	}

	return ret;
}
/* 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(ctl_table *ctl, int write, struct file * filp,
				       void __user *buffer, size_t *lenp, loff_t *ppos)
{
	char val[TCP_CA_NAME_MAX];
	ctl_table tbl = {
		.data = val,
		.maxlen = TCP_CA_NAME_MAX,
	};
	int ret;

	tcp_get_default_congestion_control(val);

	ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos);
	if (write && ret == 0)
		ret = tcp_set_default_congestion_control(val);
	return ret;
}
static int adam2_setenv_sysctl(ctl_table *ctl, int write, struct file * filp,
			void *buffer, size_t *lenp)
{
	char *var, *val, *ptr;
        int ret, i;
        size_t total, len;
	

	if (!*lenp || (filp->f_pos && !write))
	{
		*lenp = 0;
		return 0;
	}
        
	if(ctl->ctl_name != DEV_ADAM2_ENV)
        {
                return -ENODEV;
        }

	if(write)
	{
		ret = proc_dostring(ctl, write, filp, buffer, lenp);

                ptr = strpbrk(info, " \t");
                if(!ptr)	
		{
			/* We have no way to distinguish between unsetting a 
			 * variable and setting a non-value variable.
			 * 
			 * Consequently, we will treat any variable
			 * without a value as an unset request.
			 */
			adam2_env_unset_variable(info);
		}
		else
		{
			/* Set the variable-value pair in flash */
			*ptr++ = 0;
			if(adam2_env_set_variable(info, ptr) != 0)
			{
				printk(KERN_NOTICE "Defragging the environment variable region.\n");
				adam2_env_defrag();
				if( adam2_env_set_variable(info, ptr) != 0 )
					printk(KERN_WARNING "Failed to write %s to environment variable region.\n", info);
			}
		}

	}
	else
	{
		total=0;
		len=0;
		/* Scan thru the flash, looking for each possible variable index */
		for(i = 0; i < MAX_ENV_ENTRY; i++)
		{
    			if( (var=adam2_env_get_variable(i))!=NULL )
    			{
				if( (val=adam2_env_get_value(var)) != NULL) {
					len = sprintf(info, "%s\t%s\n", var, val);
					kfree(val);
				}

				kfree(var);

				if(len > *lenp - total)
					len = *lenp - total;
			        
				if(len)
				{
					if(copy_to_user(buffer+total, info, len))
						return -EFAULT;
				}
				else
				{
					break;
				}
				total += len;
			} 
		}
		*lenp = total;
		filp->f_pos += total;
	}
	
        return 0;
}
Example #25
0
static int ipv4_tcp_mem(struct ctl_table *ctl, int write,
			   void __user *buffer, size_t *lenp,
			   loff_t *ppos)
{
	int ret;
	unsigned long vec[3];
	struct net *net = current->nsproxy->net_ns;
#ifdef CONFIG_MEMCG_KMEM
	struct mem_cgroup *memcg;
#endif

	struct ctl_table tmp = {
		.data = &vec,
		.maxlen = sizeof(vec),
		.mode = ctl->mode,
	};

	if (!write) {
		ctl->data = &net->ipv4.sysctl_tcp_mem;
		return proc_doulongvec_minmax(ctl, write, buffer, lenp, ppos);
	}

	ret = proc_doulongvec_minmax(&tmp, write, buffer, lenp, ppos);
	if (ret)
		return ret;

#ifdef CONFIG_MEMCG_KMEM
	rcu_read_lock();
	memcg = mem_cgroup_from_task(current);

	tcp_prot_mem(memcg, vec[0], 0);
	tcp_prot_mem(memcg, vec[1], 1);
	tcp_prot_mem(memcg, vec[2], 2);
	rcu_read_unlock();
#endif

	net->ipv4.sysctl_tcp_mem[0] = vec[0];
	net->ipv4.sysctl_tcp_mem[1] = vec[1];
	net->ipv4.sysctl_tcp_mem[2] = vec[2];

	return 0;
}

static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write,
				 void __user *buffer, size_t *lenp,
				 loff_t *ppos)
{
	struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) };
	struct tcp_fastopen_context *ctxt;
	int ret;
	u32  user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */

	tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL);
	if (!tbl.data)
		return -ENOMEM;

	rcu_read_lock();
	ctxt = rcu_dereference(tcp_fastopen_ctx);
	if (ctxt)
		memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH);
	else
		memset(user_key, 0, sizeof(user_key));
	rcu_read_unlock();

	snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x",
		user_key[0], user_key[1], user_key[2], user_key[3]);
	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);

	if (write && ret == 0) {
		if (sscanf(tbl.data, "%x-%x-%x-%x", user_key, user_key + 1,
			   user_key + 2, user_key + 3) != 4) {
			ret = -EINVAL;
			goto bad_key;
		}
		tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH);
	}

bad_key:
	pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n",
	       user_key[0], user_key[1], user_key[2], user_key[3],
	       (char *)tbl.data, ret);
	kfree(tbl.data);
	return ret;
}

static struct ctl_table ipv4_table[] = {
	{
		.procname	= "tcp_timestamps",
		.data		= &sysctl_tcp_timestamps,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec
	},
	{
		.procname	= "tcp_window_scaling",
		.data		= &sysctl_tcp_window_scaling,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec
	},
	{
		.procname	= "tcp_sack",
Example #26
0
/* Validate changes from /proc interface. */
static int ipv4_ping_group_range(struct ctl_table *table, int write,
				 void __user *buffer,
				 size_t *lenp, loff_t *ppos)
{
	struct user_namespace *user_ns = current_user_ns();
	int ret;
	gid_t urange[2];
	kgid_t low, high;
	struct ctl_table tmp = {
		.data = &urange,
		.maxlen = sizeof(urange),
		.mode = table->mode,
		.extra1 = &ip_ping_group_range_min,
		.extra2 = &ip_ping_group_range_max,
	};

	inet_get_ping_group_range_table(table, &low, &high);
	urange[0] = from_kgid_munged(user_ns, low);
	urange[1] = from_kgid_munged(user_ns, high);
	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);

	if (write && ret == 0) {
		low = make_kgid(user_ns, urange[0]);
		high = make_kgid(user_ns, urange[1]);
		if (!gid_valid(low) || !gid_valid(high))
			return -EINVAL;
		if (urange[1] < urange[0] || gid_lt(high, low)) {
			low = make_kgid(&init_user_ns, 1);
			high = make_kgid(&init_user_ns, 0);
		}
		set_ping_group_range(table, low, high);
	}

	return ret;
}

static int ipv4_fwd_update_priority(struct ctl_table *table, int write,
				    void __user *buffer,
				    size_t *lenp, loff_t *ppos)
{
	struct net *net;
	int ret;

	net = container_of(table->data, struct net,
			   ipv4.sysctl_ip_fwd_update_priority);
	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
	if (write && ret == 0)
		call_netevent_notifiers(NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE,
					net);

	return ret;
}

static int proc_tcp_congestion_control(struct ctl_table *ctl, int write,
				       void __user *buffer, size_t *lenp, loff_t *ppos)
{
	struct net *net = container_of(ctl->data, struct net,
				       ipv4.tcp_congestion_control);
	char val[TCP_CA_NAME_MAX];
	struct ctl_table tbl = {
		.data = val,
		.maxlen = TCP_CA_NAME_MAX,
	};
	int ret;

	tcp_get_default_congestion_control(net, val);

	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
	if (write && ret == 0)
		ret = tcp_set_default_congestion_control(net, val);
	return ret;
}

static int proc_tcp_available_congestion_control(struct ctl_table *ctl,
						 int write,
						 void __user *buffer, size_t *lenp,
						 loff_t *ppos)
{
	struct ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX, };
	int ret;

	tbl.data = kmalloc(tbl.maxlen, GFP_USER);
	if (!tbl.data)
		return -ENOMEM;
	tcp_get_available_congestion_control(tbl.data, TCP_CA_BUF_MAX);
	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
	kfree(tbl.data);
	return ret;
}

static int proc_allowed_congestion_control(struct ctl_table *ctl,
					   int write,
					   void __user *buffer, size_t *lenp,
					   loff_t *ppos)
{
	struct ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX };
	int ret;

	tbl.data = kmalloc(tbl.maxlen, GFP_USER);
	if (!tbl.data)
		return -ENOMEM;

	tcp_get_allowed_congestion_control(tbl.data, tbl.maxlen);
	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
	if (write && ret == 0)
		ret = tcp_set_allowed_congestion_control(tbl.data);
	kfree(tbl.data);
	return ret;
}

static int proc_tcp_fastopen_key(struct ctl_table *table, int write,
				 void __user *buffer, size_t *lenp,
				 loff_t *ppos)
{
	struct net *net = container_of(table->data, struct net,
	    ipv4.sysctl_tcp_fastopen);
	struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) };
	struct tcp_fastopen_context *ctxt;
	u32  user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */
	__le32 key[4];
	int ret, i;

	tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL);
	if (!tbl.data)
		return -ENOMEM;

	rcu_read_lock();
	ctxt = rcu_dereference(net->ipv4.tcp_fastopen_ctx);
	if (ctxt)
		memcpy(key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH);
	else
		memset(key, 0, sizeof(key));
	rcu_read_unlock();

	for (i = 0; i < ARRAY_SIZE(key); i++)
		user_key[i] = le32_to_cpu(key[i]);

	snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x",
		user_key[0], user_key[1], user_key[2], user_key[3]);
	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);

	if (write && ret == 0) {
		if (sscanf(tbl.data, "%x-%x-%x-%x", user_key, user_key + 1,
			   user_key + 2, user_key + 3) != 4) {
			ret = -EINVAL;
			goto bad_key;
		}

		for (i = 0; i < ARRAY_SIZE(user_key); i++)
			key[i] = cpu_to_le32(user_key[i]);

		tcp_fastopen_reset_cipher(net, NULL, key,
					  TCP_FASTOPEN_KEY_LENGTH);
	}

bad_key:
	pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n",
		user_key[0], user_key[1], user_key[2], user_key[3],
	       (char *)tbl.data, ret);
	kfree(tbl.data);
	return ret;
}

static void proc_configure_early_demux(int enabled, int protocol)
{
	struct net_protocol *ipprot;
#if IS_ENABLED(CONFIG_IPV6)
	struct inet6_protocol *ip6prot;
#endif

	rcu_read_lock();

	ipprot = rcu_dereference(inet_protos[protocol]);
	if (ipprot)
		ipprot->early_demux = enabled ? ipprot->early_demux_handler :
						NULL;

#if IS_ENABLED(CONFIG_IPV6)
	ip6prot = rcu_dereference(inet6_protos[protocol]);
	if (ip6prot)
		ip6prot->early_demux = enabled ? ip6prot->early_demux_handler :
						 NULL;
#endif
	rcu_read_unlock();
}

static int proc_tcp_early_demux(struct ctl_table *table, int write,
				void __user *buffer, size_t *lenp, loff_t *ppos)
{
	int ret = 0;

	ret = proc_dointvec(table, write, buffer, lenp, ppos);

	if (write && !ret) {
		int enabled = init_net.ipv4.sysctl_tcp_early_demux;

		proc_configure_early_demux(enabled, IPPROTO_TCP);
	}

	return ret;
}

static int proc_udp_early_demux(struct ctl_table *table, int write,
				void __user *buffer, size_t *lenp, loff_t *ppos)
{
	int ret = 0;

	ret = proc_dointvec(table, write, buffer, lenp, ppos);

	if (write && !ret) {
		int enabled = init_net.ipv4.sysctl_udp_early_demux;

		proc_configure_early_demux(enabled, IPPROTO_UDP);
	}

	return ret;
}