xref: /netbsd-src/common/lib/libprop/prop_kern.c (revision 1ad9454efb13a65cd7535ccf867508cb14d9d30e)
1 /*	$NetBSD: prop_kern.c,v 1.4 2006/09/22 23:58:36 dogcow Exp $	*/
2 
3 /*-
4  * Copyright (c) 2006 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the NetBSD
21  *      Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #if defined(__NetBSD__)
40 
41 #include <sys/types.h>
42 #include <sys/ioctl.h>
43 
44 #include <prop/proplib.h>
45 
46 #if !defined(_KERNEL) && !defined(_STANDALONE)
47 #include <sys/mman.h>
48 #include <errno.h>
49 #include <string.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 
53 static int
54 prop_dictionary_pack_pref(prop_dictionary_t dict, struct plistref *pref,
55 			  char **bufp)
56 {
57 	char *buf;
58 
59 	buf = prop_dictionary_externalize(dict);
60 	if (buf == NULL) {
61 		/* Assume we ran out of memory. */
62 		return (ENOMEM);
63 	}
64 	pref->pref_plist = buf;
65 	pref->pref_len = strlen(buf) + 1;
66 
67 	*bufp = buf;
68 
69 	return (0);
70 }
71 
72 /*
73  * prop_dictionary_send_ioctl --
74  *	Send a dictionary to the kernel using the specified ioctl.
75  */
76 int
77 prop_dictionary_send_ioctl(prop_dictionary_t dict, int fd, unsigned long cmd)
78 {
79 	struct plistref pref;
80 	char *buf;
81 	int error;
82 
83 	error = prop_dictionary_pack_pref(dict, &pref, &buf);
84 	if (error)
85 		return (error);
86 
87 	if (ioctl(fd, cmd, &pref) == -1)
88 		error = errno;
89 	else
90 		error = 0;
91 
92 	free(buf);
93 
94 	return (error);
95 }
96 
97 static int
98 prop_dictionary_unpack_pref(const struct plistref *pref,
99 			    prop_dictionary_t *dictp)
100 {
101 	prop_dictionary_t dict;
102 	char *buf;
103 	int error;
104 
105 	if (pref->pref_len == 0) {
106 		/*
107 		 * This should never happen; we should always get the XML
108 		 * for an empty dictionary if it's really empty.
109 		 */
110 		error = EIO;
111 		goto out;
112 	} else {
113 		buf = pref->pref_plist;
114 		buf[pref->pref_len - 1] = '\0';	/* extra insurance */
115 		dict = prop_dictionary_internalize(buf);
116 		(void) munmap(buf, pref->pref_len);
117 		if (dict == NULL)
118 			error = EIO;
119 		else
120 			error = 0;
121 	}
122 
123  out:
124 	if (error == 0)
125 		*dictp = dict;
126 	return (error);
127 }
128 
129 /*
130  * prop_dictionary_recv_ioctl --
131  *	Receive a dictionary from the kernel using the specified ioctl.
132  */
133 int
134 prop_dictionary_recv_ioctl(int fd, unsigned long cmd, prop_dictionary_t *dictp)
135 {
136 	struct plistref pref;
137 
138 	if (ioctl(fd, cmd, &pref) == -1)
139 		return (errno);
140 
141 	return (prop_dictionary_unpack_pref(&pref, dictp));
142 }
143 
144 /*
145  * prop_dictionary_sendrecv_ioctl --
146  *	Combination send/receive a dictionary to/from the kernel using
147  *	the specified ioctl.
148  */
149 int
150 prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict, int fd,
151 			       unsigned long cmd, prop_dictionary_t *dictp)
152 {
153 	struct plistref pref;
154 	char *buf;
155 	int error;
156 
157 	error = prop_dictionary_pack_pref(dict, &pref, &buf);
158 	if (error)
159 		return (error);
160 
161 	if (ioctl(fd, cmd, &pref) == -1)
162 		error = errno;
163 	else
164 		error = 0;
165 
166 	free(buf);
167 
168 	if (error)
169 		return (error);
170 
171 	return (prop_dictionary_unpack_pref(&pref, dictp));
172 }
173 #endif /* !_KERNEL && !_STANDALONE */
174 
175 #if defined(_KERNEL)
176 #include <sys/param.h>
177 #include <sys/mman.h>
178 #include <sys/errno.h>
179 #include <sys/malloc.h>
180 #include <sys/systm.h>
181 #include <sys/proc.h>
182 #include <sys/resource.h>
183 
184 #include <uvm/uvm.h>
185 
186 /*
187  * prop_dictionary_copyin_ioctl --
188  *	Copy in a dictionary sent with an ioctl.
189  */
190 int
191 prop_dictionary_copyin_ioctl(const struct plistref *pref, const u_long cmd,
192 			     prop_dictionary_t *dictp)
193 {
194 	prop_dictionary_t dict;
195 	char *buf;
196 	int error;
197 
198 	if ((cmd & IOC_IN) == 0)
199 		return (EFAULT);
200 
201 	/*
202 	 * Allocate an extra byte so we can guarantee NUL-termination.
203 	 * XXX Some sanity check on the size?
204 	 */
205 	buf = malloc(pref->pref_len + 1, M_TEMP, M_WAITOK);
206 	error = copyin(pref->pref_plist, buf, pref->pref_len);
207 	if (error) {
208 		free(buf, M_TEMP);
209 		return (error);
210 	}
211 	buf[pref->pref_len] = '\0';
212 
213 	dict = prop_dictionary_internalize(buf);
214 	free(buf, M_TEMP);
215 	if (dict == NULL)
216 		return (EIO);
217 
218 	*dictp = dict;
219 	return (0);
220 }
221 
222 /*
223  * prop_dictionary_copyout_ioctl --
224  *	Copy out a dictionary being received with an ioctl.
225  */
226 int
227 prop_dictionary_copyout_ioctl(struct plistref *pref, const u_long cmd,
228 			      prop_dictionary_t dict)
229 {
230 	struct lwp *l = curlwp;		/* XXX */
231 	struct proc *p = l->l_proc;
232 	char *buf;
233 	size_t len;
234 	int error = 0;
235 	vaddr_t uaddr;
236 
237 	if ((cmd & IOC_OUT) == 0)
238 		return (EFAULT);
239 
240 	buf = prop_dictionary_externalize(dict);
241 	if (buf == NULL)
242 		return (ENOMEM);
243 
244 	len = strlen(buf) + 1;
245 
246 	error = uvm_mmap(&p->p_vmspace->vm_map,
247 			 &uaddr, round_page(len),
248 			 VM_PROT_READ|VM_PROT_WRITE,
249 			 VM_PROT_READ|VM_PROT_WRITE,
250 			 MAP_PRIVATE|MAP_ANON,
251 			 NULL, 0,
252 			 p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
253 
254 	if (error == 0) {
255 		error = copyout(buf, (char *)uaddr, len);
256 		if (error == 0) {
257 			pref->pref_plist = (char *)uaddr;
258 			pref->pref_len   = len;
259 		}
260 	}
261 
262 	free(buf, M_TEMP);
263 
264 	return (error);
265 }
266 #endif /* _KERNEL */
267 
268 #endif /* __NetBSD__ */
269