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