1 /* $NetBSD: prop_kern.c,v 1.17 2011/09/30 22:08:18 jym 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>
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
;
411 * Allocate an extra byte so we can guarantee NUL-termination.
413 * Allow malloc to fail in case pmap would be exhausted.
415 buf
= malloc(pref
->pref_len
+ 1, M_TEMP
, M_WAITOK
| M_CANFAIL
);
418 error
= copyin(pref
->pref_plist
, buf
, pref
->pref_len
);
423 buf
[pref
->pref_len
] = '\0';
426 case PROP_TYPE_ARRAY
:
427 obj
= prop_array_internalize(buf
);
429 case PROP_TYPE_DICTIONARY
:
430 obj
= prop_dictionary_internalize(buf
);
448 _prop_object_copyin_ioctl(const struct plistref
*pref
, const prop_type_t type
,
449 const u_long cmd
, prop_object_t
*objp
)
451 if ((cmd
& IOC_IN
) == 0)
454 return _prop_object_copyin(pref
, type
, objp
);
458 * prop_array_copyin --
459 * Copy in an array passed as a syscall arg.
462 prop_array_copyin(const struct plistref
*pref
, prop_array_t
*arrayp
)
464 return (_prop_object_copyin(pref
, PROP_TYPE_ARRAY
,
465 (prop_object_t
*)arrayp
));
469 * prop_dictionary_copyin --
470 * Copy in a dictionary passed as a syscall arg.
473 prop_dictionary_copyin(const struct plistref
*pref
, prop_dictionary_t
*dictp
)
475 return (_prop_object_copyin(pref
, PROP_TYPE_DICTIONARY
,
476 (prop_object_t
*)dictp
));
481 * prop_array_copyin_ioctl --
482 * Copy in an array send with an ioctl.
485 prop_array_copyin_ioctl(const struct plistref
*pref
, const u_long cmd
,
486 prop_array_t
*arrayp
)
488 return (_prop_object_copyin_ioctl(pref
, PROP_TYPE_ARRAY
,
489 cmd
, (prop_object_t
*)arrayp
));
493 * prop_dictionary_copyin_ioctl --
494 * Copy in a dictionary sent with an ioctl.
497 prop_dictionary_copyin_ioctl(const struct plistref
*pref
, const u_long cmd
,
498 prop_dictionary_t
*dictp
)
500 return (_prop_object_copyin_ioctl(pref
, PROP_TYPE_DICTIONARY
,
501 cmd
, (prop_object_t
*)dictp
));
505 _prop_object_copyout(struct plistref
*pref
, prop_object_t obj
)
507 struct lwp
*l
= curlwp
; /* XXX */
508 struct proc
*p
= l
->l_proc
;
514 switch (prop_object_type(obj
)) {
515 case PROP_TYPE_ARRAY
:
516 buf
= prop_array_externalize(obj
);
518 case PROP_TYPE_DICTIONARY
:
519 buf
= prop_dictionary_externalize(obj
);
527 len
= strlen(buf
) + 1;
528 rlen
= round_page(len
);
531 * See sys_mmap() in sys/uvm/uvm_mmap.c.
532 * Let's act as if we were calling mmap(0, ...)
534 uaddr
= p
->p_emul
->e_vm_default_addr(p
,
535 (vaddr_t
)p
->p_vmspace
->vm_daddr
, rlen
);
537 error
= uvm_mmap(&p
->p_vmspace
->vm_map
,
539 VM_PROT_READ
|VM_PROT_WRITE
,
540 VM_PROT_READ
|VM_PROT_WRITE
,
541 MAP_PRIVATE
|MAP_ANON
,
543 p
->p_rlimit
[RLIMIT_MEMLOCK
].rlim_cur
);
546 error
= copyout(buf
, (char *)uaddr
, len
);
548 pref
->pref_plist
= (char *)uaddr
;
549 pref
->pref_len
= len
;
559 * prop_array_copyout --
560 * Copy out an array to a syscall arg.
563 prop_array_copyout(struct plistref
*pref
, prop_array_t array
)
565 return (_prop_object_copyout(pref
, array
));
569 * prop_dictionary_copyout --
570 * Copy out a dictionary to a syscall arg.
573 prop_dictionary_copyout(struct plistref
*pref
, prop_dictionary_t dict
)
575 return (_prop_object_copyout(pref
, dict
));
579 _prop_object_copyout_ioctl(struct plistref
*pref
, const u_long cmd
,
582 if ((cmd
& IOC_OUT
) == 0)
584 return _prop_object_copyout(pref
, obj
);
589 * prop_array_copyout_ioctl --
590 * Copy out an array being received with an ioctl.
593 prop_array_copyout_ioctl(struct plistref
*pref
, const u_long cmd
,
596 return (_prop_object_copyout_ioctl(pref
, cmd
, array
));
600 * prop_dictionary_copyout_ioctl --
601 * Copy out a dictionary being received with an ioctl.
604 prop_dictionary_copyout_ioctl(struct plistref
*pref
, const u_long cmd
,
605 prop_dictionary_t dict
)
608 _prop_object_copyout_ioctl(pref
, cmd
, dict
));
612 #endif /* __NetBSD__ */