Add cap_sysctl(3) and cap_sysctlnametomib(3).

These complement cap_sysctlbyname(3) to provide a drop-in
replacement for the corresponding libc functions.

Also revise the libcap_sysctl limit interface to provide access
to sysctls by MIB, and to avoid direct manipulation of nvlists
by the caller.

Reviewed by:	oshogbo
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D17854
This commit is contained in:
Mark Johnston 2019-05-13 17:49:54 +00:00
parent d5368bf3df
commit 1608c46ea4
6 changed files with 1057 additions and 739 deletions

View File

@ -38,6 +38,8 @@
# xargs -n1 | sort | uniq -d;
# done
# 20190513: libcap_sysctl interface change
OLD_FILES+=lib/casper/libcap_sysctl.1
# 20190509: tests/sys/opencrypto requires the net/py-dpkt package.
OLD_FILES+=usr/tests/sys/opencrypto/dpkt.py
OLD_FILES+=usr/tests/sys/opencrypto/dpkt.pyc

View File

@ -6,7 +6,7 @@ SHLIBDIR?= /lib/casper
PACKAGE=libcasper
SHLIB_MAJOR= 1
SHLIB_MAJOR= 2
INCSDIR?= ${INCLUDEDIR}/casper
.if ${MK_CASPER} != "no"
@ -25,8 +25,12 @@ HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
MAN+= cap_sysctl.3
MLINKS+=cap_sysctl.3 libcap_sysctl.3
MLINKS+=cap_sysctl.3 cap_sysctlbyname.3
MLINKS+=cap_sysctl.3 libcap_sysctl.3 \
cap_sysctl.3 cap_sysctlbyname.3 \
cap_sysctl.3 cap_nametomib.3 \
cap_sysctl.3 cap_sysctl_limit_init.3 \
cap_sysctl.3 cap_sysctl_limit_mib.3 \
cap_sysctl.3 cap_sysctl_limit_name.3 \
cap_sysctl.3 cap_sysctl_limit.3
.include <bsd.lib.mk>

View File

@ -24,72 +24,113 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 18, 2018
.Dd May 13, 2019
.Dt CAP_SYSCTL 3
.Os
.Sh NAME
.Nm cap_sysctlbyname
.Nm cap_sysctl
.Nd "library for getting or setting system information in capability mode"
.Sh LIBRARY
.Lb libcap_sysctl
.Sh SYNOPSIS
.In sys/nv.h
.In libcasper.h
.In casper/cap_sysctl.h
.Ft int
.Fn cap_sysctlbyname "cap_channel_t *chan" " const char *name" " void *oldp" " size_t *oldlenp" " const void *newp" " size_t newlen"
.Fn cap_sysctl "cap_channel_t *chan" "const int *name" "u_int namelen" "void *oldp" "size_t *oldlenp" "const void *newp" "size_t newlen"
.Ft int
.Fn cap_sysctlbyname "cap_channel_t *chan" "const char *name" "void *oldp" "size_t *oldlenp" "const void *newp" "size_t newlen"
.Ft int
.Fn cap_sysctlnametomib "cap_channel_t *chan" "const char *name" "int *mibp" "size_t *sizep"
.Ft void *
.Fn cap_sysctl_limit_init "cap_channel_t *chan"
.Ft void *
.Fn cap_sysctl_limit_name "void *limit" "const char *name" "int flags"
.Ft void *
.Fn cap_sysctl_limit_mib "void *limit" "int *mibp" "u_int miblen" "int flags"
.Ft int
.Fn cap_sysctl_limit "void *limit"
.Sh DESCRIPTION
The function
The
.Fn cap_sysctl ,
.Fn cap_sysctlbyname
is equivalent to
and
.Fn cap_sysctlnametomib
functions are equivalent to
.Xr sysctl 3 ,
.Xr sysctlbyname 3
except that the connection to the
.Nm system.sysctl
service needs to be provided.
and
.Xr sysctlnametomib 3 ,
except that they are implemented by the
.Ql system.sysctl
.Xr libcasper 3
service and require a corresponding
.Xr libcasper 3
capability.
.Sh LIMITS
The service can be limited using
.Xr cap_limit_set 3
function.
By default, the
.Nm
capability provides unrestricted access to the sysctl namespace.
Applications typically only require access to a small number of sysctl
variables; the
.Fn cap_sysctl_limit
interface can be used to restrict the sysctls that can be accessed using
the
.Nm
capability.
.Fn cap_sysctl_limit_init
returns an opaque limit handle used to store a list of permitted sysctls
and access rights.
Rights are encoded using the following flags:
.Pp
.Bd -literal -offset indent -compact
CAP_SYSCTL_READ allow reads of the sysctl variable
CAP_SYSCTL_WRITE allow writes of the sysctl variable
CAP_SYSCTL_RDWR allow reads and writes of the sysctl variable
CAP_RECURSIVE permit access to any child of the sysctl variable
.Ed
.Pp
The
.Xr nvlist 9
for that function can contain the following values and types:
.Bl -ohang -offset indent
.It ( NV_TYPE_NUMBER )
The name of the element with type number will be treated as the limited sysctl.
The value of the element will describe the access rights for given sysctl.
There are four different rights
.Fn cap_sysctl_limit_name
function adds the sysctl identified by
.Ar name
to the limit list, and
.Fn cap_sysctl_limit_mib
function adds the sysctl identified by
.Ar mibp
to the limit list.
The access rights for the sysctl are specified in the
.Ar flags
parameter; at least one of
.Dv CAP_SYSCTL_READ ,
.Dv CAP_SYSCTL_WRITE ,
.Dv CAP_SYSCTL_RDWR ,
.Dv CAP_SYSCTL_WRITE
and
.Dv CAP_SYSCTL_RECURSIVE .
The
.Dv CAP_SYSCTL_READ
flag allows to fetch the value of a given sysctl.
The
.Dv CAP_SYSCTL_WIRTE
flag allows to override the value of a given sysctl.
The
.Dv CAP_SYSCTL_RDWR
is combination of the
.Dv CAP_SYSCTL_WIRTE
and
.Dv CAP_SYSCTL_READ
and allows to read and write the value of a given sysctl.
The
.Dv CAP_SYSCTL_RECURSIVE
allows access to all children of a given sysctl.
This right must be combined with at least one other right.
must be specified.
.Fn cap_sysctl_limit
applies a set of sysctl limits to the capability, denying access to sysctl
variables not belonging to the set.
.Pp
Once a set of limits is applied, subsequent calls to
.Fn cap_sysctl_limit
will fail unless the new set is a subset of the current set.
.Pp
.Fn cap_sysctlnametomib
will succeed so long as the named sysctl variable is present in the limit set,
regardless of its access rights.
When a sysctl variable name is added to a limit set, its MIB identifier is
automatically added to the set.
.Sh EXAMPLES
The following example first opens a capability to casper and then uses this
The following example first opens a capability to casper, uses this
capability to create the
.Nm system.sysctl
casper service and uses it to get the value of
casper service, and then uses the
.Nm
capability to get the value of
.Dv kern.trap_enotcap .
.Bd -literal
cap_channel_t *capcas, *capsysctl;
const char *name = "kern.trap_enotcap";
nvlist_t *limits;
void *limit;
int value;
size_t size;
@ -111,11 +152,11 @@ if (capsysctl == NULL)
cap_close(capcas);
/* Create limit for one MIB with read access only. */
limits = nvlist_create(0);
nvlist_add_number(limits, name, CAP_SYSCTL_READ);
limit = cap_sysctl_limit_init(capsysctl);
(void)cap_sysctl_limit_name(limit, name, CAP_SYSCTL_READ);
/* Limit system.sysctl. */
if (cap_limit_set(capsysctl, limits) < 0)
if (cap_sysctl_limit(limit) < 0)
err(1, "Unable to set limits");
/* Fetch value. */
@ -129,7 +170,9 @@ cap_close(capsysctl);
.Sh SEE ALSO
.Xr cap_enter 2 ,
.Xr err 3 ,
.Xr sysctl 3 ,
.Xr sysctlbyname 3 ,
.Xr sysctlnametomib 3 ,
.Xr capsicum 4 ,
.Xr nv 9
.Sh AUTHORS

View File

@ -1,12 +1,15 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2013 The FreeBSD Foundation
* Copyright (c) 2013, 2018 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
*
* Portions of this software were developed by Mark Johnston
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@ -32,9 +35,11 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/param.h>
#include <sys/cnv.h>
#include <sys/dnv.h>
#include <sys/nv.h>
#include <sys/sysctl.h>
#include <assert.h>
#include <errno.h>
@ -46,24 +51,117 @@ __FBSDID("$FreeBSD$");
#include "cap_sysctl.h"
int
cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp,
size_t *oldlenp, const void *newp, size_t newlen)
/*
* Limit interface.
*/
struct cap_sysctl_limit {
cap_channel_t *chan;
nvlist_t *nv;
};
cap_sysctl_limit_t *
cap_sysctl_limit_init(cap_channel_t *chan)
{
cap_sysctl_limit_t *limit;
int error;
limit = malloc(sizeof(*limit));
if (limit != NULL) {
limit->chan = chan;
limit->nv = nvlist_create(NV_FLAG_NO_UNIQUE);
if (limit->nv == NULL) {
error = errno;
free(limit);
limit = NULL;
errno = error;
}
}
return (limit);
}
cap_sysctl_limit_t *
cap_sysctl_limit_name(cap_sysctl_limit_t *limit, const char *name, int flags)
{
nvlist_t *lnv;
size_t mibsz;
int error, mib[CTL_MAXNAME];
lnv = nvlist_create(0);
if (lnv == NULL) {
error = errno;
if (limit->nv != NULL)
nvlist_destroy(limit->nv);
free(limit);
errno = error;
return (NULL);
}
nvlist_add_string(lnv, "name", name);
nvlist_add_number(lnv, "operation", flags);
mibsz = nitems(mib);
error = cap_sysctlnametomib(limit->chan, name, mib, &mibsz);
if (error == 0)
nvlist_add_binary(lnv, "mib", mib, mibsz * sizeof(int));
nvlist_move_nvlist(limit->nv, "limit", lnv);
return (limit);
}
cap_sysctl_limit_t *
cap_sysctl_limit_mib(cap_sysctl_limit_t *limit, int *mibp, u_int miblen,
int flags)
{
nvlist_t *lnv;
int error;
lnv = nvlist_create(0);
if (lnv == NULL) {
error = errno;
if (limit->nv != NULL)
nvlist_destroy(limit->nv);
free(limit);
errno = error;
return (NULL);
}
nvlist_add_binary(lnv, "mib", mibp, miblen * sizeof(int));
nvlist_add_number(lnv, "operation", flags);
nvlist_add_nvlist(limit->nv, "limit", lnv);
return (limit);
}
int
cap_sysctl_limit(cap_sysctl_limit_t *limit)
{
cap_channel_t *chan;
nvlist_t *lnv;
chan = limit->chan;
lnv = limit->nv;
free(limit);
/* cap_limit_set(3) will always free the nvlist. */
return (cap_limit_set(chan, lnv));
}
/*
* Service interface.
*/
static int
do_sysctl(cap_channel_t *chan, nvlist_t *nvl, void *oldp, size_t *oldlenp,
const void *newp, size_t newlen)
{
nvlist_t *nvl;
const uint8_t *retoldp;
uint8_t operation;
size_t oldlen;
int error;
uint8_t operation;
operation = 0;
if (oldp != NULL)
if (oldlenp != NULL)
operation |= CAP_SYSCTL_READ;
if (newp != NULL)
operation |= CAP_SYSCTL_WRITE;
nvl = nvlist_create(0);
nvlist_add_string(nvl, "cmd", "sysctl");
nvlist_add_string(nvl, "name", name);
nvlist_add_number(nvl, "operation", (uint64_t)operation);
if (oldp == NULL && oldlenp != NULL)
nvlist_add_null(nvl, "justsize");
@ -71,12 +169,14 @@ cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp,
nvlist_add_number(nvl, "oldlen", (uint64_t)*oldlenp);
if (newp != NULL)
nvlist_add_binary(nvl, "newp", newp, newlen);
nvl = cap_xfer_nvlist(chan, nvl);
if (nvl == NULL)
return (-1);
if (nvlist_get_number(nvl, "error") != 0) {
errno = (int)nvlist_get_number(nvl, "error");
error = (int)dnvlist_get_number(nvl, "error", 0);
if (error != 0) {
nvlist_destroy(nvl);
errno = error;
return (-1);
}
@ -88,21 +188,87 @@ cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp,
if (oldlenp != NULL)
*oldlenp = oldlen;
}
nvlist_destroy(nvl);
return (0);
}
int
cap_sysctl(cap_channel_t *chan, const int *name, u_int namelen, void *oldp,
size_t *oldlenp, const void *newp, size_t newlen)
{
nvlist_t *req;
req = nvlist_create(0);
nvlist_add_string(req, "cmd", "sysctl");
nvlist_add_binary(req, "mib", name, (size_t)namelen * sizeof(int));
return (do_sysctl(chan, req, oldp, oldlenp, newp, newlen));
}
int
cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp,
size_t *oldlenp, const void *newp, size_t newlen)
{
nvlist_t *req;
req = nvlist_create(0);
nvlist_add_string(req, "cmd", "sysctlbyname");
nvlist_add_string(req, "name", name);
return (do_sysctl(chan, req, oldp, oldlenp, newp, newlen));
}
int
cap_sysctlnametomib(cap_channel_t *chan, const char *name, int *mibp,
size_t *sizep)
{
nvlist_t *req;
const void *mib;
size_t mibsz;
int error;
req = nvlist_create(0);
nvlist_add_string(req, "cmd", "sysctlnametomib");
nvlist_add_string(req, "name", name);
nvlist_add_number(req, "operation", 0);
nvlist_add_number(req, "size", (uint64_t)*sizep);
req = cap_xfer_nvlist(chan, req);
if (req == NULL)
return (-1);
error = (int)dnvlist_get_number(req, "error", 0);
if (error != 0) {
nvlist_destroy(req);
errno = error;
return (-1);
}
mib = nvlist_get_binary(req, "mib", &mibsz);
*sizep = mibsz / sizeof(int);
memcpy(mibp, mib, mibsz);
nvlist_destroy(req);
return (0);
}
/*
* Service functions.
* Service implementation.
*/
/*
* Validate a sysctl description. This must consist of an nvlist with either a
* binary "mib" field or a string "name", and an operation.
*/
static int
sysctl_check_one(const nvlist_t *nvl, bool islimit)
sysctl_valid(const nvlist_t *nvl, bool limit)
{
const char *name;
void *cookie;
int type;
unsigned int fields;
size_t size;
unsigned int field, fields;
/* NULL nvl is of course invalid. */
if (nvl == NULL)
@ -111,83 +277,119 @@ sysctl_check_one(const nvlist_t *nvl, bool islimit)
return (nvlist_error(nvl));
#define HAS_NAME 0x01
#define HAS_OPERATION 0x02
#define HAS_MIB 0x02
#define HAS_ID (HAS_NAME | HAS_MIB)
#define HAS_OPERATION 0x04
fields = 0;
cookie = NULL;
while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
/* We accept only one 'name' and one 'operation' in nvl. */
if (strcmp(name, "name") == 0) {
if (type != NV_TYPE_STRING)
if ((strcmp(name, "name") == 0 && type == NV_TYPE_STRING) ||
(strcmp(name, "mib") == 0 && type == NV_TYPE_BINARY)) {
if (strcmp(name, "mib") == 0) {
/* A MIB must be an array of integers. */
(void)cnvlist_get_binary(cookie, &size);
if (size % sizeof(int) != 0)
return (EINVAL);
field = HAS_MIB;
} else
field = HAS_NAME;
/*
* A limit may contain both a name and a MIB identifier.
*/
if ((fields & field) != 0 ||
(!limit && (fields & HAS_ID) != 0))
return (EINVAL);
/* Only one 'name' can be present. */
if ((fields & HAS_NAME) != 0)
return (EINVAL);
fields |= HAS_NAME;
fields |= field;
} else if (strcmp(name, "operation") == 0) {
uint64_t operation;
uint64_t mask, operation;
if (type != NV_TYPE_NUMBER)
return (EINVAL);
operation = cnvlist_get_number(cookie);
/*
* We accept only CAP_SYSCTL_READ and
* CAP_SYSCTL_WRITE flags.
* Requests can only include the RDWR flags; limits may
* also include the RECURSIVE flag.
*/
operation = nvlist_get_number(nvl, name);
if ((operation & ~(CAP_SYSCTL_RDWR)) != 0)
return (EINVAL);
/* ...but there has to be at least one of them. */
if ((operation & (CAP_SYSCTL_RDWR)) == 0)
mask = limit ? (CAP_SYSCTL_RDWR |
CAP_SYSCTL_RECURSIVE) : CAP_SYSCTL_RDWR;
if ((operation & ~limit) != 0 ||
(operation & CAP_SYSCTL_RDWR) == 0)
return (EINVAL);
/* Only one 'operation' can be present. */
if ((fields & HAS_OPERATION) != 0)
return (EINVAL);
fields |= HAS_OPERATION;
} else if (islimit) {
/* If this is limit, there can be no other fields. */
} else if (limit)
return (EINVAL);
}
}
/* Both fields has to be there. */
if (fields != (HAS_NAME | HAS_OPERATION))
if ((fields & HAS_OPERATION) == 0 || (fields & HAS_ID) == 0)
return (EINVAL);
#undef HAS_OPERATION
#undef HAS_NAME
#undef HAS_OPERATION
#undef HAS_ID
#undef HAS_MIB
#undef HAS_NAME
return (0);
}
static bool
sysctl_allowed(const nvlist_t *limits, const char *chname, uint64_t choperation)
sysctl_allowed(const nvlist_t *limits, const nvlist_t *req)
{
uint64_t operation;
const char *name;
const nvlist_t *limit;
uint64_t op, reqop;
const char *lname, *name, *reqname;
void *cookie;
size_t lsize, reqsize;
const int *lmib, *reqmib;
int type;
if (limits == NULL)
return (true);
reqmib = dnvlist_get_binary(req, "mib", &reqsize, NULL, 0);
reqname = dnvlist_get_string(req, "name", NULL);
reqop = nvlist_get_number(req, "operation");
cookie = NULL;
while ((name = nvlist_next(limits, &type, &cookie)) != NULL) {
assert(type == NV_TYPE_NUMBER);
assert(type == NV_TYPE_NVLIST);
operation = nvlist_get_number(limits, name);
if ((operation & choperation) != choperation)
limit = cnvlist_get_nvlist(cookie);
op = nvlist_get_number(limit, "operation");
if ((reqop & op) != reqop)
continue;
if ((operation & CAP_SYSCTL_RECURSIVE) == 0) {
if (strcmp(name, chname) != 0)
if (reqname != NULL) {
lname = dnvlist_get_string(limit, "name", NULL);
if (lname == NULL)
continue;
} else {
size_t namelen;
if ((op & CAP_SYSCTL_RECURSIVE) == 0) {
if (strcmp(lname, reqname) != 0)
continue;
} else {
size_t namelen;
namelen = strlen(name);
if (strncmp(name, chname, namelen) != 0)
namelen = strlen(lname);
if (strncmp(lname, reqname, namelen) != 0)
continue;
if (reqname[namelen] != '.' &&
reqname[namelen] != '\0')
continue;
}
} else {
lmib = dnvlist_get_binary(limit, "mib", &lsize, NULL, 0);
if (lmib == NULL)
continue;
if (chname[namelen] != '.' && chname[namelen] != '\0')
if (lsize > reqsize || ((op & CAP_SYSCTL_RECURSIVE) == 0 &&
lsize < reqsize))
continue;
if (memcmp(lmib, reqmib, lsize) != 0)
continue;
}
@ -200,50 +402,80 @@ sysctl_allowed(const nvlist_t *limits, const char *chname, uint64_t choperation)
static int
sysctl_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits)
{
const nvlist_t *nvl;
const char *name;
void *cookie;
uint64_t operation;
int type;
int error, type;
cookie = NULL;
while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) {
if (type != NV_TYPE_NUMBER)
if (strcmp(name, "limit") != 0 || type != NV_TYPE_NVLIST)
return (EINVAL);
operation = nvlist_get_number(newlimits, name);
if ((operation & ~(CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE)) != 0)
return (EINVAL);
if ((operation & (CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE)) == 0)
return (EINVAL);
if (!sysctl_allowed(oldlimits, name, operation))
nvl = cnvlist_get_nvlist(cookie);
error = sysctl_valid(nvl, true);
if (error != 0)
return (error);
if (!sysctl_allowed(oldlimits, nvl))
return (ENOTCAPABLE);
}
return (0);
}
static int
nametomib(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout)
{
const char *name;
size_t size;
int error, *mibp;
if (!sysctl_allowed(limits, nvlin))
return (ENOTCAPABLE);
name = nvlist_get_string(nvlin, "name");
size = (size_t)nvlist_get_number(nvlin, "size");
mibp = malloc(size * sizeof(*mibp));
if (mibp == NULL)
return (ENOMEM);
error = sysctlnametomib(name, mibp, &size);
if (error != 0) {
error = errno;
free(mibp);
return (error);
}
nvlist_add_binary(nvlout, "mib", mibp, size * sizeof(*mibp));
return (0);
}
static int
sysctl_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
nvlist_t *nvlout)
{
const char *name;
const void *newp;
const int *mibp;
void *oldp;
uint64_t operation;
size_t oldlen, newlen;
size_t oldlen, newlen, size;
size_t *oldlenp;
int error;
if (strcmp(cmd, "sysctl") != 0)
if (strcmp(cmd, "sysctlnametomib") == 0)
return (nametomib(limits, nvlin, nvlout));
if (strcmp(cmd, "sysctlbyname") != 0 && strcmp(cmd, "sysctl") != 0)
return (EINVAL);
error = sysctl_check_one(nvlin, false);
error = sysctl_valid(nvlin, false);
if (error != 0)
return (error);
name = nvlist_get_string(nvlin, "name");
operation = nvlist_get_number(nvlin, "operation");
if (!sysctl_allowed(limits, name, operation))
if (!sysctl_allowed(limits, nvlin))
return (ENOTCAPABLE);
operation = nvlist_get_number(nvlin, "operation");
if ((operation & CAP_SYSCTL_WRITE) != 0) {
if (!nvlist_exists_binary(nvlin, "newp"))
return (EINVAL);
@ -276,7 +508,15 @@ sysctl_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
oldlenp = NULL;
}
if (sysctlbyname(name, oldp, oldlenp, newp, newlen) == -1) {
if (strcmp(cmd, "sysctlbyname") == 0) {
name = nvlist_get_string(nvlin, "name");
error = sysctlbyname(name, oldp, oldlenp, newp, newlen);
} else {
mibp = nvlist_get_binary(nvlin, "mib", &size);
error = sysctl(mibp, size / sizeof(*mibp), oldp, oldlenp, newp,
newlen);
}
if (error != 0) {
error = errno;
free(oldp);
return (error);

View File

@ -29,24 +29,47 @@
* $FreeBSD$
*/
#ifndef _CAP_SYSCTL_H_
#ifndef _CAP_SYSCTL_H_
#define _CAP_SYSCTL_H_
#ifdef HAVE_CASPER
#define WITH_CASPER
#define WITH_CASPER
#endif
#ifdef WITH_CASPER
#define CAP_SYSCTL_READ 0x01
#define CAP_SYSCTL_WRITE 0x02
#define CAP_SYSCTL_RDWR (CAP_SYSCTL_READ | CAP_SYSCTL_WRITE)
#define CAP_SYSCTL_RECURSIVE 0x04
#ifdef WITH_CASPER
int cap_sysctl(cap_channel_t *chan, const int *name, u_int namelen, void *oldp,
size_t *oldlenp, const void *newp, size_t newlen);
int cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp,
size_t *oldlenp, const void *newp, size_t newlen);
#else
#define cap_sysctlbyname(chan, name, oldp, oldlenp, newp, newlen) \
sysctlbyname(name, oldp, oldlenp, newp, newlen)
#endif
int cap_sysctlnametomib(cap_channel_t *chan, const char *name, int *mibp,
size_t *sizep);
#endif /* !_CAP_SYSCTL_H_ */
struct cap_sysctl_limit;
typedef struct cap_sysctl_limit cap_sysctl_limit_t;
cap_sysctl_limit_t *cap_sysctl_limit_init(cap_channel_t *);
cap_sysctl_limit_t *cap_sysctl_limit_name(cap_sysctl_limit_t *limit,
const char *name, int flags);
cap_sysctl_limit_t *cap_sysctl_limit_mib(cap_sysctl_limit_t *limit, int *mibp,
u_int miblen, int flags);
int cap_sysctl_limit(cap_sysctl_limit_t *limit);
#else /* !WITH_CASPER */
#define cap_sysctl(chan, name, namelen, oldp, oldlenp, newp, newlen) \
sysctl((name), (namelen), (oldp), (oldlenp), (newp), (newlen))
#define cap_sysctlbyname(chan, name, oldp, oldlenp, newp, newlen) \
sysctlbyname((name), (oldp), (oldlenp), (newp), (newlen))
#define cap_sysctlnametomib(chan, name, mibp, sizep) \
sysctlnametomib((name), (mibp), (sizep))
#define cap_sysctl_limit_init(chan) (NULL)
#define cap_sysctl_limit_name(limit, name, flags) (NULL)
#define cap_sysctl_limit_mib(limit, mibp, miblen, flags) (NULL)
#define cap_sysctl_limit(limit) (0)
#endif /* WITH_CASPER */
#endif /* !_CAP_SYSCTL_H_ */

File diff suppressed because it is too large Load Diff