1 /* $NetBSD: prop_kern.c,v 1.12 2009/10/10 21:27:46 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 _prop_object_externalize_to_pref(prop_object_t obj
, struct plistref
*pref
, char **bufp
)
51 switch (prop_object_type(obj
)) {
52 case PROP_TYPE_DICTIONARY
:
53 buf
= prop_dictionary_externalize(obj
);
56 buf
= prop_array_externalize(obj
);
62 /* Assume we ran out of memory. */
65 pref
->pref_plist
= buf
;
66 pref
->pref_len
= strlen(buf
) + 1;
74 * prop_array_externalize_to_pref --
75 * Externalize an array into a plistref for sending to the kernel.
78 prop_array_externalize_to_pref(prop_array_t array
, struct plistref
*prefp
)
83 rv
= _prop_object_externalize_to_pref(array
, prefp
, &buf
);
85 errno
= rv
; /* pass up error value in errno */
90 * prop_dictionary_externalize_to_pref --
91 * Externalize an dictionary into a plistref for sending to the kernel.
94 prop_dictionary_externalize_to_pref(prop_dictionary_t dict
, struct plistref
*prefp
)
99 rv
= _prop_object_externalize_to_pref(dict
, prefp
, &buf
);
101 errno
= rv
; /* pass up error value in errno */
106 _prop_object_send_ioctl(prop_object_t obj
, int fd
, unsigned long cmd
)
108 struct plistref pref
;
112 error
= _prop_object_externalize_to_pref(obj
, &pref
, &buf
);
116 if (ioctl(fd
, cmd
, &pref
) == -1)
127 * prop_array_send_ioctl --
128 * Send an array to the kernel using the specified ioctl.
131 prop_array_send_ioctl(prop_array_t array
, int fd
, unsigned long cmd
)
134 return (_prop_object_send_ioctl(array
, fd
, cmd
));
138 * prop_dictionary_send_ioctl --
139 * Send a dictionary to the kernel using the specified ioctl.
142 prop_dictionary_send_ioctl(prop_dictionary_t dict
, int fd
, unsigned long cmd
)
145 return (_prop_object_send_ioctl(dict
, fd
, cmd
));
149 _prop_object_internalize_from_pref(const struct plistref
*pref
, prop_type_t type
,
152 prop_object_t obj
= NULL
;
156 if (pref
->pref_len
== 0) {
158 * This should never happen; we should always get the XML
159 * for an empty dictionary if it's really empty.
164 buf
= pref
->pref_plist
;
165 buf
[pref
->pref_len
- 1] = '\0'; /* extra insurance */
167 case PROP_TYPE_DICTIONARY
:
168 obj
= prop_dictionary_internalize(buf
);
170 case PROP_TYPE_ARRAY
:
171 obj
= prop_array_internalize(buf
);
176 (void) munmap(buf
, pref
->pref_len
);
177 if (obj
== NULL
&& error
== 0)
188 * prop_array_recv_ioctl --
189 * Receive an array from the kernel using the specified ioctl.
192 prop_array_recv_ioctl(int fd
, unsigned long cmd
, prop_array_t
*arrayp
)
194 struct plistref pref
;
196 if (ioctl(fd
, cmd
, &pref
) == -1)
199 return (_prop_object_internalize_from_pref(&pref
, PROP_TYPE_ARRAY
,
200 (prop_object_t
*)arrayp
));
204 * prop_dictionary_recv_ioctl --
205 * Receive a dictionary from the kernel using the specified ioctl.
208 prop_dictionary_recv_ioctl(int fd
, unsigned long cmd
, prop_dictionary_t
*dictp
)
210 struct plistref pref
;
212 if (ioctl(fd
, cmd
, &pref
) == -1)
215 return (_prop_object_internalize_from_pref(&pref
, PROP_TYPE_DICTIONARY
,
216 (prop_object_t
*)dictp
));
220 * prop_dictionary_sendrecv_ioctl --
221 * Combination send/receive a dictionary to/from the kernel using
222 * the specified ioctl.
225 prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict
, int fd
,
226 unsigned long cmd
, prop_dictionary_t
*dictp
)
228 struct plistref pref
;
232 error
= _prop_object_externalize_to_pref(dict
, &pref
, &buf
);
236 if (ioctl(fd
, cmd
, &pref
) == -1)
246 return (_prop_object_internalize_from_pref(&pref
, PROP_TYPE_DICTIONARY
,
247 (prop_object_t
*)dictp
));
249 #endif /* !_KERNEL && !_STANDALONE */
252 #include <sys/param.h>
253 #include <sys/mman.h>
254 #include <sys/errno.h>
255 #include <sys/malloc.h>
256 #include <sys/systm.h>
257 #include <sys/proc.h>
258 #include <sys/resource.h>
259 #include <sys/pool.h>
263 #include "prop_object_impl.h"
265 /* Arbitrary limit ioctl input to 64KB */
266 unsigned int prop_object_copyin_limit
= 65536;
268 /* initialize proplib for use in the kernel */
272 __link_set_decl(prop_linkpools
, struct prop_pool_init
);
273 struct prop_pool_init
* const *pi
;
275 __link_set_foreach(pi
, prop_linkpools
)
276 pool_init((*pi
)->pp
, (*pi
)->size
, 0, 0, 0, (*pi
)->wchan
,
277 &pool_allocator_nointr
, IPL_NONE
);
281 _prop_object_copyin(const struct plistref
*pref
, const prop_type_t type
,
284 prop_object_t obj
= NULL
;
289 * Allocate an extra byte so we can guarantee NUL-termination.
291 * Allow malloc to fail in case pmap would be exhausted.
293 buf
= malloc(pref
->pref_len
+ 1, M_TEMP
, M_WAITOK
| M_CANFAIL
);
296 error
= copyin(pref
->pref_plist
, buf
, pref
->pref_len
);
301 buf
[pref
->pref_len
] = '\0';
304 case PROP_TYPE_ARRAY
:
305 obj
= prop_array_internalize(buf
);
307 case PROP_TYPE_DICTIONARY
:
308 obj
= prop_dictionary_internalize(buf
);
326 _prop_object_copyin_ioctl(const struct plistref
*pref
, const prop_type_t type
,
327 const u_long cmd
, prop_object_t
*objp
)
329 if ((cmd
& IOC_IN
) == 0)
332 return _prop_object_copyin(pref
, type
, objp
);
336 * prop_array_copyin --
337 * Copy in an array passed as a syscall arg.
340 prop_array_copyin(const struct plistref
*pref
, prop_array_t
*arrayp
)
342 return (_prop_object_copyin(pref
, PROP_TYPE_ARRAY
,
343 (prop_object_t
*)arrayp
));
347 * prop_dictionary_copyin --
348 * Copy in a dictionary passed as a syscall arg.
351 prop_dictionary_copyin(const struct plistref
*pref
, prop_dictionary_t
*dictp
)
353 return (_prop_object_copyin(pref
, PROP_TYPE_DICTIONARY
,
354 (prop_object_t
*)dictp
));
359 * prop_array_copyin_ioctl --
360 * Copy in an array send with an ioctl.
363 prop_array_copyin_ioctl(const struct plistref
*pref
, const u_long cmd
,
364 prop_array_t
*arrayp
)
366 return (_prop_object_copyin_ioctl(pref
, PROP_TYPE_ARRAY
,
367 cmd
, (prop_object_t
*)arrayp
));
371 * prop_dictionary_copyin_ioctl --
372 * Copy in a dictionary sent with an ioctl.
375 prop_dictionary_copyin_ioctl(const struct plistref
*pref
, const u_long cmd
,
376 prop_dictionary_t
*dictp
)
378 return (_prop_object_copyin_ioctl(pref
, PROP_TYPE_DICTIONARY
,
379 cmd
, (prop_object_t
*)dictp
));
383 _prop_object_copyout_ioctl(struct plistref
*pref
, const u_long cmd
,
386 struct lwp
*l
= curlwp
; /* XXX */
387 struct proc
*p
= l
->l_proc
;
393 if ((cmd
& IOC_OUT
) == 0)
396 switch (prop_object_type(obj
)) {
397 case PROP_TYPE_ARRAY
:
398 buf
= prop_array_externalize(obj
);
400 case PROP_TYPE_DICTIONARY
:
401 buf
= prop_dictionary_externalize(obj
);
409 len
= strlen(buf
) + 1;
410 rlen
= round_page(len
);
413 * See sys_mmap() in sys/uvm/uvm_mmap.c.
414 * Let's act as if we were calling mmap(0, ...)
416 uaddr
= p
->p_emul
->e_vm_default_addr(p
,
417 (vaddr_t
)p
->p_vmspace
->vm_daddr
, rlen
);
419 error
= uvm_mmap(&p
->p_vmspace
->vm_map
,
421 VM_PROT_READ
|VM_PROT_WRITE
,
422 VM_PROT_READ
|VM_PROT_WRITE
,
423 MAP_PRIVATE
|MAP_ANON
,
425 p
->p_rlimit
[RLIMIT_MEMLOCK
].rlim_cur
);
428 error
= copyout(buf
, (char *)uaddr
, len
);
430 pref
->pref_plist
= (char *)uaddr
;
431 pref
->pref_len
= len
;
441 * prop_array_copyout_ioctl --
442 * Copy out an array being received with an ioctl.
445 prop_array_copyout_ioctl(struct plistref
*pref
, const u_long cmd
,
448 return (_prop_object_copyout_ioctl(pref
, cmd
, array
));
452 * prop_dictionary_copyout_ioctl --
453 * Copy out a dictionary being received with an ioctl.
456 prop_dictionary_copyout_ioctl(struct plistref
*pref
, const u_long cmd
,
457 prop_dictionary_t dict
)
459 return (_prop_object_copyout_ioctl(pref
, cmd
, dict
));
463 #endif /* __NetBSD__ */