1 /* $NetBSD: prop_kern.c,v 1.19 2015/05/11 16:48:34 christos Exp $ */
4 * Copyright (c) 2006, 2009 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #if defined(__NetBSD__)
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
37 #include <prop/proplib.h>
39 #if !defined(_KERNEL) && !defined(_STANDALONE)
47 #include <rump/rump_syscalls.h>
48 #define ioctl(a,b,c) rump_sys_ioctl(a,b,c)
52 _prop_object_externalize_to_pref(prop_object_t obj
, struct plistref
*pref
,
57 switch (prop_object_type(obj
)) {
58 case PROP_TYPE_DICTIONARY
:
59 buf
= prop_dictionary_externalize(obj
);
62 buf
= prop_array_externalize(obj
);
68 /* Assume we ran out of memory. */
71 pref
->pref_plist
= buf
;
72 pref
->pref_len
= strlen(buf
) + 1;
80 prop_array_externalize_to_pref(prop_array_t array
, struct plistref
*prefp
)
85 rv
= _prop_object_externalize_to_pref(array
, prefp
, &buf
);
87 errno
= rv
; /* pass up error value in errno */
92 * prop_array_externalize_to_pref --
93 * Externalize an array into a plistref for sending to the kernel.
96 prop_array_send_syscall(prop_array_t array
, struct plistref
*prefp
)
98 if (prop_array_externalize_to_pref(array
, prefp
))
105 prop_dictionary_externalize_to_pref(prop_dictionary_t dict
,
106 struct plistref
*prefp
)
111 rv
= _prop_object_externalize_to_pref(dict
, prefp
, &buf
);
113 errno
= rv
; /* pass up error value in errno */
118 * prop_dictionary_externalize_to_pref --
119 * Externalize an dictionary into a plistref for sending to the kernel.
122 prop_dictionary_send_syscall(prop_dictionary_t dict
,
123 struct plistref
*prefp
)
125 if (prop_dictionary_externalize_to_pref(dict
, prefp
))
132 _prop_object_send_ioctl(prop_object_t obj
, int fd
, unsigned long cmd
)
134 struct plistref pref
;
138 error
= _prop_object_externalize_to_pref(obj
, &pref
, &buf
);
142 if (ioctl(fd
, cmd
, &pref
) == -1)
153 * prop_array_send_ioctl --
154 * Send an array to the kernel using the specified ioctl.
157 prop_array_send_ioctl(prop_array_t array
, int fd
, unsigned long cmd
)
161 rv
= _prop_object_send_ioctl(array
, fd
, cmd
);
163 errno
= rv
; /* pass up error value in errno */
170 * prop_dictionary_send_ioctl --
171 * Send a dictionary to the kernel using the specified ioctl.
174 prop_dictionary_send_ioctl(prop_dictionary_t dict
, int fd
, unsigned long cmd
)
178 rv
= _prop_object_send_ioctl(dict
, fd
, cmd
);
180 errno
= rv
; /* pass up error value in errno */
187 _prop_object_internalize_from_pref(const struct plistref
*pref
,
188 prop_type_t type
, prop_object_t
*objp
)
190 prop_object_t obj
= NULL
;
194 if (pref
->pref_len
== 0) {
196 * This should never happen; we should always get the XML
197 * for an empty dictionary if it's really empty.
202 buf
= pref
->pref_plist
;
203 buf
[pref
->pref_len
- 1] = '\0'; /* extra insurance */
205 case PROP_TYPE_DICTIONARY
:
206 obj
= prop_dictionary_internalize(buf
);
208 case PROP_TYPE_ARRAY
:
209 obj
= prop_array_internalize(buf
);
214 (void) munmap(buf
, pref
->pref_len
);
215 if (obj
== NULL
&& error
== 0)
226 * prop_array_internalize_from_pref --
227 * Internalize a pref into a prop_array_t object.
230 prop_array_internalize_from_pref(const struct plistref
*prefp
,
231 prop_array_t
*arrayp
)
235 rv
= _prop_object_internalize_from_pref(prefp
, PROP_TYPE_ARRAY
,
236 (prop_object_t
*)arrayp
);
238 errno
= rv
; /* pass up error value in errno */
243 * prop_array_recv_syscall --
244 * Internalize an array received from the kernel as pref.
247 prop_array_recv_syscall(const struct plistref
*prefp
,
248 prop_array_t
*arrayp
)
250 if (prop_array_internalize_from_pref(prefp
, arrayp
))
257 * prop_dictionary_internalize_from_pref --
258 * Internalize a pref into a prop_dictionary_t object.
261 prop_dictionary_internalize_from_pref(const struct plistref
*prefp
,
262 prop_dictionary_t
*dictp
)
266 rv
= _prop_object_internalize_from_pref(prefp
, PROP_TYPE_DICTIONARY
,
267 (prop_object_t
*)dictp
);
269 errno
= rv
; /* pass up error value in errno */
274 * prop_dictionary_recv_syscall --
275 * Internalize a dictionary received from the kernel as pref.
278 prop_dictionary_recv_syscall(const struct plistref
*prefp
,
279 prop_dictionary_t
*dictp
)
281 if (prop_dictionary_internalize_from_pref(prefp
, dictp
))
289 * prop_array_recv_ioctl --
290 * Receive an array from the kernel using the specified ioctl.
293 prop_array_recv_ioctl(int fd
, unsigned long cmd
, prop_array_t
*arrayp
)
296 struct plistref pref
;
298 rv
= ioctl(fd
, cmd
, &pref
);
302 rv
= _prop_object_internalize_from_pref(&pref
, PROP_TYPE_ARRAY
,
303 (prop_object_t
*)arrayp
);
305 errno
= rv
; /* pass up error value in errno */
312 * prop_dictionary_recv_ioctl --
313 * Receive a dictionary from the kernel using the specified ioctl.
316 prop_dictionary_recv_ioctl(int fd
, unsigned long cmd
, prop_dictionary_t
*dictp
)
319 struct plistref pref
;
321 rv
= ioctl(fd
, cmd
, &pref
);
325 rv
= _prop_object_internalize_from_pref(&pref
, PROP_TYPE_DICTIONARY
,
326 (prop_object_t
*)dictp
);
328 errno
= rv
; /* pass up error value in errno */
335 * prop_dictionary_sendrecv_ioctl --
336 * Combination send/receive a dictionary to/from the kernel using
337 * the specified ioctl.
340 prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict
, int fd
,
341 unsigned long cmd
, prop_dictionary_t
*dictp
)
343 struct plistref pref
;
347 error
= _prop_object_externalize_to_pref(dict
, &pref
, &buf
);
353 if (ioctl(fd
, cmd
, &pref
) == -1)
363 error
= _prop_object_internalize_from_pref(&pref
, PROP_TYPE_DICTIONARY
,
364 (prop_object_t
*)dictp
);
366 errno
= error
; /* pass up error value in errno */
371 #endif /* !_KERNEL && !_STANDALONE */
374 #include <sys/param.h>
375 #include <sys/mman.h>
376 #include <sys/errno.h>
377 #include <sys/malloc.h>
378 #include <sys/systm.h>
379 #include <sys/proc.h>
380 #include <sys/resource.h>
381 #include <sys/pool.h>
383 #include <uvm/uvm_extern.h>
385 #include "prop_object_impl.h"
387 /* Arbitrary limit ioctl input to 64KB */
388 unsigned int prop_object_copyin_limit
= 65536;
390 /* initialize proplib for use in the kernel */
394 __link_set_decl(prop_linkpools
, struct prop_pool_init
);
395 struct prop_pool_init
* const *pi
;
397 __link_set_foreach(pi
, prop_linkpools
)
398 pool_init((*pi
)->pp
, (*pi
)->size
, 0, 0, 0, (*pi
)->wchan
,
399 &pool_allocator_nointr
, IPL_NONE
);
403 _prop_object_copyin(const struct plistref
*pref
, const prop_type_t type
,
406 prop_object_t obj
= NULL
;
410 if (pref
->pref_len
>= prop_object_copyin_limit
)
414 * Allocate an extra byte so we can guarantee NUL-termination.
416 * Allow malloc to fail in case pmap would be exhausted.
418 buf
= malloc(pref
->pref_len
+ 1, M_TEMP
, M_WAITOK
| M_CANFAIL
);
421 error
= copyin(pref
->pref_plist
, buf
, pref
->pref_len
);
426 buf
[pref
->pref_len
] = '\0';
429 case PROP_TYPE_ARRAY
:
430 obj
= prop_array_internalize(buf
);
432 case PROP_TYPE_DICTIONARY
:
433 obj
= prop_dictionary_internalize(buf
);
451 _prop_object_copyin_ioctl(const struct plistref
*pref
, const prop_type_t type
,
452 const u_long cmd
, prop_object_t
*objp
)
454 if ((cmd
& IOC_IN
) == 0)
457 return _prop_object_copyin(pref
, type
, objp
);
461 * prop_array_copyin --
462 * Copy in an array passed as a syscall arg.
465 prop_array_copyin(const struct plistref
*pref
, prop_array_t
*arrayp
)
467 return (_prop_object_copyin(pref
, PROP_TYPE_ARRAY
,
468 (prop_object_t
*)arrayp
));
472 * prop_dictionary_copyin --
473 * Copy in a dictionary passed as a syscall arg.
476 prop_dictionary_copyin(const struct plistref
*pref
, prop_dictionary_t
*dictp
)
478 return (_prop_object_copyin(pref
, PROP_TYPE_DICTIONARY
,
479 (prop_object_t
*)dictp
));
484 * prop_array_copyin_ioctl --
485 * Copy in an array send with an ioctl.
488 prop_array_copyin_ioctl(const struct plistref
*pref
, const u_long cmd
,
489 prop_array_t
*arrayp
)
491 return (_prop_object_copyin_ioctl(pref
, PROP_TYPE_ARRAY
,
492 cmd
, (prop_object_t
*)arrayp
));
496 * prop_dictionary_copyin_ioctl --
497 * Copy in a dictionary sent with an ioctl.
500 prop_dictionary_copyin_ioctl(const struct plistref
*pref
, const u_long cmd
,
501 prop_dictionary_t
*dictp
)
503 return (_prop_object_copyin_ioctl(pref
, PROP_TYPE_DICTIONARY
,
504 cmd
, (prop_object_t
*)dictp
));
508 _prop_object_copyout(struct plistref
*pref
, prop_object_t obj
)
510 struct lwp
*l
= curlwp
; /* XXX */
511 struct proc
*p
= l
->l_proc
;
517 switch (prop_object_type(obj
)) {
518 case PROP_TYPE_ARRAY
:
519 buf
= prop_array_externalize(obj
);
521 case PROP_TYPE_DICTIONARY
:
522 buf
= prop_dictionary_externalize(obj
);
530 len
= strlen(buf
) + 1;
531 rlen
= round_page(len
);
533 error
= uvm_mmap_anon(p
, &uaddr
, rlen
);
535 error
= copyout(buf
, uaddr
, len
);
537 pref
->pref_plist
= uaddr
;
538 pref
->pref_len
= len
;
548 * prop_array_copyout --
549 * Copy out an array to a syscall arg.
552 prop_array_copyout(struct plistref
*pref
, prop_array_t array
)
554 return (_prop_object_copyout(pref
, array
));
558 * prop_dictionary_copyout --
559 * Copy out a dictionary to a syscall arg.
562 prop_dictionary_copyout(struct plistref
*pref
, prop_dictionary_t dict
)
564 return (_prop_object_copyout(pref
, dict
));
568 _prop_object_copyout_ioctl(struct plistref
*pref
, const u_long cmd
,
571 if ((cmd
& IOC_OUT
) == 0)
573 return _prop_object_copyout(pref
, obj
);
578 * prop_array_copyout_ioctl --
579 * Copy out an array being received with an ioctl.
582 prop_array_copyout_ioctl(struct plistref
*pref
, const u_long cmd
,
585 return (_prop_object_copyout_ioctl(pref
, cmd
, array
));
589 * prop_dictionary_copyout_ioctl --
590 * Copy out a dictionary being received with an ioctl.
593 prop_dictionary_copyout_ioctl(struct plistref
*pref
, const u_long cmd
,
594 prop_dictionary_t dict
)
597 _prop_object_copyout_ioctl(pref
, cmd
, dict
));
601 #endif /* __NetBSD__ */