/*-
* Copyright (c) 2006, 2009, 2025 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* This file is only for native NetBSD. No build tools should use it. */
#if defined(__NetBSD__) && !defined(HAVE_NBTOOL_CONFIG_H)
#include "prop_object_impl.h" /* for _PROP_EXPORT */
/*
* prop_object_externalize_to_pref --
* Externalize an object into a plistref for sending to the kernel.
*/
static int
_prop_object_externalize_to_pref(prop_object_t obj, struct plistref *pref,
char **bufp)
{
char *buf = prop_object_externalize(obj);
if (buf == NULL) {
/* Assume we ran out of memory. */
return (ENOMEM);
}
pref->pref_plist = buf;
pref->pref_len = strlen(buf) + 1;
if (bufp != NULL) {
*bufp = buf;
}
return (0);
}
static bool
prop_object_externalize_to_pref(prop_object_t obj, struct plistref *prefp)
{
int rv = _prop_object_externalize_to_pref(obj, prefp, NULL);
if (rv != 0)
errno = rv; /* pass up error value in errno */
return (rv == 0);
}
/*
* prop_object_send_ioctl --
* Send an array to the kernel using the specified ioctl.
*/
static int
_prop_object_send_ioctl(prop_object_t obj, int fd, unsigned long cmd)
{
struct plistref pref;
char *buf;
int error;
error = _prop_object_externalize_to_pref(obj, &pref, &buf);
if (error)
return (error);
_PROP_EXPORT int
prop_object_send_ioctl(prop_object_t obj, int fd, unsigned long cmd)
{
int rv;
rv = _prop_object_send_ioctl(obj, fd, cmd);
if (rv != 0) {
errno = rv; /* pass up error value in errno */
return rv;
} else
return 0;
}
__strong_alias(prop_array_send_ioctl, prop_object_send_ioctl)
__strong_alias(prop_dictionary_send_ioctl, prop_object_send_ioctl)
/*
* prop_object_internalize_from_pref --
* Internalize a pref into an object.
*/
static int
_prop_object_internalize_from_pref_with_type(const struct plistref *pref,
prop_object_t *objp,
prop_type_t type)
{
prop_object_t obj = NULL;
char *buf;
int error = 0;
if (pref->pref_len == 0) {
/*
* This should never happen; we should always get the XML
* for an empty dictionary if it's really empty.
*/
error = EIO;
goto out;
} else {
buf = pref->pref_plist;
buf[pref->pref_len - 1] = '\0'; /* extra insurance */
obj = prop_object_internalize(buf);
(void) munmap(buf, pref->pref_len);
if (obj != NULL && type != PROP_TYPE_UNKNOWN &&
prop_object_type(obj) != type) {
prop_object_release(obj);
obj = NULL;
}
if (obj == NULL)
error = EIO;
}
/*
* prop_object_recv_ioctl --
* Receive an array from the kernel using the specified ioctl.
*/
static int
_prop_object_recv_ioctl(int fd, unsigned long cmd, prop_object_t *objp,
prop_type_t type)
{
int rv;
struct plistref pref;
rv = _prop_object_internalize_from_pref_with_type(&pref, objp, type);
if (rv != 0) {
errno = rv; /* pass up error value in errno */
return rv;
} else
return 0;
}
_PROP_EXPORT int
prop_object_recv_ioctl(int fd, unsigned long cmd, prop_object_t *objp)
{
return _prop_object_recv_ioctl(fd, cmd, objp, PROP_TYPE_UNKNOWN);
}
_PROP_EXPORT int
prop_array_recv_ioctl(int fd, unsigned long cmd, prop_array_t *arrayp)
{
return _prop_object_recv_ioctl(fd, cmd,
(prop_object_t *)arrayp, PROP_TYPE_ARRAY);
}
_PROP_EXPORT int
prop_dictionary_recv_ioctl(int fd, unsigned long cmd, prop_dictionary_t *dictp)
{
return _prop_object_recv_ioctl(fd, cmd,
(prop_object_t *)dictp, PROP_TYPE_DICTIONARY);
}
/*
* prop_object_sendrecv_ioctl --
* Combination send/receive an object to/from the kernel using
* the specified ioctl.
*/
static int
_prop_object_sendrecv_ioctl(prop_object_t obj, int fd,
unsigned long cmd, prop_object_t *objp,
prop_type_t type)
{
struct plistref pref;
char *buf;
int error;
/* Arbitrary limit ioctl input to 128KB */
unsigned int prop_object_copyin_limit = 128 * 1024;
/* initialize proplib for use in the kernel */
void
prop_kern_init(void)
{
__link_set_decl(prop_linkpools, struct prop_pool_init);
struct prop_pool_init * const *pi;