183221Smarcel/*- 283221Smarcel * Copyright (c) 2001 Marcel Moolenaar 383221Smarcel * All rights reserved. 483221Smarcel * 583221Smarcel * Redistribution and use in source and binary forms, with or without 683221Smarcel * modification, are permitted provided that the following conditions 783221Smarcel * are met: 883221Smarcel * 1. Redistributions of source code must retain the above copyright 9111798Sdes * notice, this list of conditions and the following disclaimer 1083221Smarcel * in this position and unchanged. 1183221Smarcel * 2. Redistributions in binary form must reproduce the above copyright 1283221Smarcel * notice, this list of conditions and the following disclaimer in the 1383221Smarcel * documentation and/or other materials provided with the distribution. 1483221Smarcel * 3. The name of the author may not be used to endorse or promote products 1583221Smarcel * derived from this software without specific prior written permission. 1683221Smarcel * 1783221Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1883221Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1983221Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2083221Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2183221Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2283221Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2383221Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2483221Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2583221Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2683221Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2783221Smarcel */ 2883221Smarcel 29116173Sobrien#include <sys/cdefs.h> 30116173Sobrien__FBSDID("$FreeBSD$"); 31116173Sobrien 32156874Sru#include "opt_compat.h" 33235063Snetchild#include "opt_kdtrace.h" 34156874Sru 3583221Smarcel#include <sys/param.h> 36235063Snetchild#include <sys/kernel.h> 37103839Smini#include <sys/lock.h> 38102954Sbde#include <sys/malloc.h> 39103839Smini#include <sys/mutex.h> 40103839Smini#include <sys/proc.h> 41235063Snetchild#include <sys/sdt.h> 42103839Smini#include <sys/sysctl.h> 4383221Smarcel#include <sys/systm.h> 44108541Salfred#include <sys/sbuf.h> 4583221Smarcel 46140214Sobrien#ifdef COMPAT_LINUX32 47140214Sobrien#include <machine/../linux32/linux.h> 48140214Sobrien#include <machine/../linux32/linux32_proto.h> 49140214Sobrien#else 5083221Smarcel#include <machine/../linux/linux.h> 5183221Smarcel#include <machine/../linux/linux_proto.h> 52133816Stjr#endif 5383221Smarcel 54235063Snetchild#include <compat/linux/linux_dtrace.h> 55246085Sjhb#include <compat/linux/linux_misc.h> 56108541Salfred#include <compat/linux/linux_util.h> 57108541Salfred 5883221Smarcel#define LINUX_CTL_KERN 1 5983221Smarcel#define LINUX_CTL_VM 2 6083221Smarcel#define LINUX_CTL_NET 3 6183221Smarcel#define LINUX_CTL_PROC 4 6283221Smarcel#define LINUX_CTL_FS 5 6383221Smarcel#define LINUX_CTL_DEBUG 6 6483221Smarcel#define LINUX_CTL_DEV 7 6583221Smarcel#define LINUX_CTL_BUS 8 6683221Smarcel 6783221Smarcel/* CTL_KERN names */ 6883221Smarcel#define LINUX_KERN_OSTYPE 1 6983221Smarcel#define LINUX_KERN_OSRELEASE 2 7083221Smarcel#define LINUX_KERN_OSREV 3 7183221Smarcel#define LINUX_KERN_VERSION 4 7283221Smarcel 73235063Snetchild/* DTrace init */ 74235063SnetchildLIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); 75235063Snetchild 76235063Snetchild/** 77235063Snetchild * DTrace probes in this module. 78235063Snetchild */ 79235063SnetchildLIN_SDT_PROBE_DEFINE2(sysctl, handle_string, entry, "struct l___sysctl_args *", 80235063Snetchild "char *"); 81235063SnetchildLIN_SDT_PROBE_DEFINE1(sysctl, handle_string, copyout_error, "int"); 82235063SnetchildLIN_SDT_PROBE_DEFINE1(sysctl, handle_string, return, "int"); 83235063SnetchildLIN_SDT_PROBE_DEFINE2(sysctl, linux_sysctl, entry, "struct l___sysctl_args *", 84235063Snetchild "struct thread *"); 85235063SnetchildLIN_SDT_PROBE_DEFINE1(sysctl, linux_sysctl, copyin_error, "int"); 86235063SnetchildLIN_SDT_PROBE_DEFINE2(sysctl, linux_sysctl, wrong_length, "int", "int"); 87235063SnetchildLIN_SDT_PROBE_DEFINE1(sysctl, linux_sysctl, unsupported_sysctl, "char *"); 88235063SnetchildLIN_SDT_PROBE_DEFINE1(sysctl, linux_sysctl, return, "int"); 89235063Snetchild 9083221Smarcelstatic int 9183221Smarcelhandle_string(struct l___sysctl_args *la, char *value) 9283221Smarcel{ 9383221Smarcel int error; 9483221Smarcel 95235063Snetchild LIN_SDT_PROBE2(sysctl, handle_string, entry, la, value); 96235063Snetchild 97133816Stjr if (la->oldval != 0) { 9883221Smarcel l_int len = strlen(value); 99133816Stjr error = copyout(value, PTRIN(la->oldval), len + 1); 100133816Stjr if (!error && la->oldlenp != 0) 101133816Stjr error = copyout(&len, PTRIN(la->oldlenp), sizeof(len)); 102235063Snetchild if (error) { 103235063Snetchild LIN_SDT_PROBE1(sysctl, handle_string, copyout_error, 104235063Snetchild error); 105235063Snetchild LIN_SDT_PROBE1(sysctl, handle_string, return, error); 10683221Smarcel return (error); 107235063Snetchild } 10883221Smarcel } 10983221Smarcel 110235063Snetchild if (la->newval != 0) { 111235063Snetchild LIN_SDT_PROBE1(sysctl, handle_string, return, ENOTDIR); 11283221Smarcel return (ENOTDIR); 113235063Snetchild } 11483221Smarcel 115235063Snetchild LIN_SDT_PROBE1(sysctl, handle_string, return, 0); 11683221Smarcel return (0); 11783221Smarcel} 11883221Smarcel 11983221Smarcelint 12083366Sjulianlinux_sysctl(struct thread *td, struct linux_sysctl_args *args) 12183221Smarcel{ 12283221Smarcel struct l___sysctl_args la; 123108541Salfred struct sbuf *sb; 12483221Smarcel l_int *mib; 125235063Snetchild char *sysctl_string; 12683221Smarcel int error, i; 12783221Smarcel 128235063Snetchild LIN_SDT_PROBE2(sysctl, linux_sysctl, entry, td, args->args); 129235063Snetchild 130111797Sdes error = copyin(args->args, &la, sizeof(la)); 131235063Snetchild if (error) { 132235063Snetchild LIN_SDT_PROBE1(sysctl, linux_sysctl, copyin_error, error); 133235063Snetchild LIN_SDT_PROBE1(sysctl, linux_sysctl, return, error); 13483221Smarcel return (error); 135235063Snetchild } 13683221Smarcel 137235063Snetchild if (la.nlen <= 0 || la.nlen > LINUX_CTL_MAXNAME) { 138235063Snetchild LIN_SDT_PROBE2(sysctl, linux_sysctl, wrong_length, la.nlen, 139235063Snetchild LINUX_CTL_MAXNAME); 140235063Snetchild LIN_SDT_PROBE1(sysctl, linux_sysctl, return, ENOTDIR); 14183221Smarcel return (ENOTDIR); 142235063Snetchild } 14383221Smarcel 144111119Simp mib = malloc(la.nlen * sizeof(l_int), M_TEMP, M_WAITOK); 145133816Stjr error = copyin(PTRIN(la.name), mib, la.nlen * sizeof(l_int)); 146102814Siedowse if (error) { 147235063Snetchild LIN_SDT_PROBE1(sysctl, linux_sysctl, copyin_error, error); 148235063Snetchild LIN_SDT_PROBE1(sysctl, linux_sysctl, return, error); 149102814Siedowse free(mib, M_TEMP); 15083221Smarcel return (error); 151102814Siedowse } 15283221Smarcel 15383221Smarcel switch (mib[0]) { 15483221Smarcel case LINUX_CTL_KERN: 15583221Smarcel if (la.nlen < 2) 15683221Smarcel break; 15783221Smarcel 15883221Smarcel switch (mib[1]) { 15983221Smarcel case LINUX_KERN_VERSION: 160102814Siedowse error = handle_string(&la, version); 161102814Siedowse free(mib, M_TEMP); 162235063Snetchild LIN_SDT_PROBE1(sysctl, linux_sysctl, return, error); 163102814Siedowse return (error); 16483221Smarcel default: 16583221Smarcel break; 16683221Smarcel } 16783221Smarcel break; 16883221Smarcel default: 16983221Smarcel break; 17083221Smarcel } 17183221Smarcel 172108541Salfred sb = sbuf_new(NULL, NULL, 20 + la.nlen * 5, SBUF_AUTOEXTEND); 173108541Salfred if (sb == NULL) { 174108541Salfred linux_msg(td, "sysctl is not implemented"); 175235063Snetchild LIN_SDT_PROBE1(sysctl, linux_sysctl, unsupported_sysctl, 176235063Snetchild "unknown sysctl, ENOMEM during lookup"); 177108541Salfred } else { 178108541Salfred sbuf_printf(sb, "sysctl "); 179108541Salfred for (i = 0; i < la.nlen; i++) 180108541Salfred sbuf_printf(sb, "%c%d", (i) ? ',' : '{', mib[i]); 181108541Salfred sbuf_printf(sb, "} is not implemented"); 182108541Salfred sbuf_finish(sb); 183235063Snetchild sysctl_string = sbuf_data(sb); 184108541Salfred linux_msg(td, "%s", sbuf_data(sb)); 185235063Snetchild LIN_SDT_PROBE1(sysctl, linux_sysctl, unsupported_sysctl, 186235063Snetchild sysctl_string); 187108541Salfred sbuf_delete(sb); 188108541Salfred } 18983221Smarcel 190102814Siedowse free(mib, M_TEMP); 191235063Snetchild 192235063Snetchild LIN_SDT_PROBE1(sysctl, linux_sysctl, return, ENOTDIR); 19383221Smarcel return (ENOTDIR); 19483221Smarcel} 195