1 1.56 simonb /* $NetBSD: netbsd32_socket.c,v 1.56 2021/01/19 03:41:22 simonb Exp $ */ 2 1.1 mrg 3 1.1 mrg /* 4 1.1 mrg * Copyright (c) 1998, 2001 Matthew R. Green 5 1.1 mrg * All rights reserved. 6 1.1 mrg * 7 1.1 mrg * Redistribution and use in source and binary forms, with or without 8 1.1 mrg * modification, are permitted provided that the following conditions 9 1.1 mrg * are met: 10 1.1 mrg * 1. Redistributions of source code must retain the above copyright 11 1.1 mrg * notice, this list of conditions and the following disclaimer. 12 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 mrg * notice, this list of conditions and the following disclaimer in the 14 1.1 mrg * documentation and/or other materials provided with the distribution. 15 1.1 mrg * 16 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 mrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 mrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.1 mrg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.1 mrg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.1 mrg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.1 mrg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 mrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 mrg * SUCH DAMAGE. 27 1.1 mrg */ 28 1.6 lukem 29 1.6 lukem #include <sys/cdefs.h> 30 1.56 simonb __KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.56 2021/01/19 03:41:22 simonb Exp $"); 31 1.1 mrg 32 1.1 mrg #include <sys/param.h> 33 1.1 mrg #include <sys/systm.h> 34 1.1 mrg #define msg __msg /* Don't ask me! */ 35 1.1 mrg #include <sys/mount.h> 36 1.1 mrg #include <sys/socket.h> 37 1.1 mrg #include <sys/sockio.h> 38 1.1 mrg #include <sys/socketvar.h> 39 1.1 mrg #include <sys/mbuf.h> 40 1.1 mrg #include <sys/ktrace.h> 41 1.1 mrg #include <sys/file.h> 42 1.1 mrg #include <sys/filedesc.h> 43 1.1 mrg #include <sys/syscallargs.h> 44 1.1 mrg #include <sys/proc.h> 45 1.15 christos #include <sys/dirent.h> 46 1.1 mrg 47 1.1 mrg #include <compat/netbsd32/netbsd32.h> 48 1.1 mrg #include <compat/netbsd32/netbsd32_syscallargs.h> 49 1.1 mrg #include <compat/netbsd32/netbsd32_conv.h> 50 1.1 mrg 51 1.37 rmind /* 52 1.39 joerg * XXX Assumes that struct sockaddr is compatible. 53 1.37 rmind */ 54 1.39 joerg 55 1.39 joerg #define CMSG32_ALIGN(n) (((n) + ALIGNBYTES32) & ~ALIGNBYTES32) 56 1.45 christos #define CMSG32_ASIZE CMSG32_ALIGN(sizeof(struct cmsghdr)) 57 1.45 christos #define CMSG32_DATA(cmsg) (__CASTV(u_char *, cmsg) + CMSG32_ASIZE) 58 1.45 christos #define CMSG32_MSGNEXT(ucmsg, kcmsg) \ 59 1.45 christos (__CASTV(char *, kcmsg) + CMSG32_ALIGN((ucmsg)->cmsg_len)) 60 1.45 christos #define CMSG32_MSGEND(mhdr) \ 61 1.45 christos (__CASTV(char *, (mhdr)->msg_control) + (mhdr)->msg_controllen) 62 1.45 christos 63 1.45 christos #define CMSG32_NXTHDR(mhdr, ucmsg, kcmsg) \ 64 1.45 christos __CASTV(struct cmsghdr *, \ 65 1.45 christos CMSG32_MSGNEXT(ucmsg, kcmsg) + \ 66 1.45 christos CMSG32_ASIZE > CMSG32_MSGEND(mhdr) ? 0 : \ 67 1.45 christos CMSG32_MSGNEXT(ucmsg, kcmsg)) 68 1.39 joerg #define CMSG32_FIRSTHDR(mhdr) \ 69 1.45 christos __CASTV(struct cmsghdr *, \ 70 1.45 christos (mhdr)->msg_controllen < sizeof(struct cmsghdr) ? 0 : \ 71 1.45 christos (mhdr)->msg_control) 72 1.39 joerg 73 1.39 joerg #define CMSG32_SPACE(l) (CMSG32_ALIGN(sizeof(struct cmsghdr)) + CMSG32_ALIGN(l)) 74 1.39 joerg #define CMSG32_LEN(l) (CMSG32_ALIGN(sizeof(struct cmsghdr)) + (l)) 75 1.39 joerg 76 1.39 joerg static int 77 1.50 christos copyout32_msg_control_mbuf(struct lwp *l, struct msghdr *mp, u_int *len, 78 1.45 christos struct mbuf *m, char **q, bool *truncated) 79 1.39 joerg { 80 1.39 joerg struct cmsghdr *cmsg, cmsg32; 81 1.50 christos size_t i, j; 82 1.50 christos int error; 83 1.39 joerg 84 1.39 joerg *truncated = false; 85 1.39 joerg cmsg = mtod(m, struct cmsghdr *); 86 1.39 joerg do { 87 1.39 joerg if ((char *)cmsg == mtod(m, char *) + m->m_len) 88 1.39 joerg break; 89 1.39 joerg if ((char *)cmsg > mtod(m, char *) + m->m_len - sizeof(*cmsg)) 90 1.39 joerg return EINVAL; 91 1.39 joerg cmsg32 = *cmsg; 92 1.39 joerg j = cmsg->cmsg_len - CMSG_LEN(0); 93 1.39 joerg i = cmsg32.cmsg_len = CMSG32_LEN(j); 94 1.39 joerg if (i > *len) { 95 1.39 joerg mp->msg_flags |= MSG_CTRUNC; 96 1.39 joerg if (cmsg->cmsg_level == SOL_SOCKET 97 1.39 joerg && cmsg->cmsg_type == SCM_RIGHTS) { 98 1.39 joerg *truncated = true; 99 1.39 joerg return 0; 100 1.39 joerg } 101 1.39 joerg j -= i - *len; 102 1.39 joerg i = *len; 103 1.39 joerg } 104 1.39 joerg 105 1.45 christos ktrkuser(mbuftypes[MT_CONTROL], cmsg, cmsg->cmsg_len); 106 1.48 maxv error = copyout(&cmsg32, *q, MIN(i, sizeof(cmsg32))); 107 1.39 joerg if (error) 108 1.55 simonb return error; 109 1.39 joerg if (i > CMSG32_LEN(0)) { 110 1.45 christos error = copyout(CMSG_DATA(cmsg), *q + CMSG32_LEN(0), 111 1.45 christos i - CMSG32_LEN(0)); 112 1.39 joerg if (error) 113 1.55 simonb return error; 114 1.39 joerg } 115 1.39 joerg j = CMSG32_SPACE(cmsg->cmsg_len - CMSG_LEN(0)); 116 1.39 joerg if (*len >= j) { 117 1.39 joerg *len -= j; 118 1.39 joerg *q += j; 119 1.39 joerg } else { 120 1.39 joerg *q += i; 121 1.39 joerg *len = 0; 122 1.39 joerg } 123 1.39 joerg cmsg = (void *)((char *)cmsg + CMSG_ALIGN(cmsg->cmsg_len)); 124 1.39 joerg } while (*len > 0); 125 1.39 joerg 126 1.39 joerg return 0; 127 1.39 joerg } 128 1.39 joerg 129 1.39 joerg static int 130 1.39 joerg copyout32_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control) 131 1.39 joerg { 132 1.39 joerg int len, error = 0; 133 1.39 joerg struct mbuf *m; 134 1.39 joerg char *q; 135 1.39 joerg bool truncated; 136 1.39 joerg 137 1.39 joerg len = mp->msg_controllen; 138 1.39 joerg if (len <= 0 || control == 0) { 139 1.39 joerg mp->msg_controllen = 0; 140 1.39 joerg free_control_mbuf(l, control, control); 141 1.39 joerg return 0; 142 1.39 joerg } 143 1.39 joerg 144 1.39 joerg q = (char *)mp->msg_control; 145 1.39 joerg 146 1.40 matt for (m = control; len > 0 && m != NULL; m = m->m_next) { 147 1.45 christos error = copyout32_msg_control_mbuf(l, mp, &len, m, &q, 148 1.45 christos &truncated); 149 1.39 joerg if (truncated) { 150 1.39 joerg m = control; 151 1.39 joerg break; 152 1.39 joerg } 153 1.39 joerg if (error) 154 1.39 joerg break; 155 1.39 joerg } 156 1.39 joerg 157 1.39 joerg free_control_mbuf(l, control, m); 158 1.39 joerg 159 1.39 joerg mp->msg_controllen = q - (char *)mp->msg_control; 160 1.39 joerg return error; 161 1.39 joerg } 162 1.39 joerg 163 1.46 christos static int 164 1.46 christos msg_recv_copyin(struct lwp *l, const struct netbsd32_msghdr *msg32, 165 1.46 christos struct msghdr *msg, struct iovec *aiov) 166 1.46 christos { 167 1.46 christos int error; 168 1.46 christos size_t iovsz; 169 1.46 christos struct iovec *iov = aiov; 170 1.46 christos 171 1.46 christos iovsz = msg32->msg_iovlen * sizeof(struct iovec); 172 1.46 christos if (msg32->msg_iovlen > UIO_SMALLIOV) { 173 1.46 christos if (msg32->msg_iovlen > IOV_MAX) 174 1.46 christos return EMSGSIZE; 175 1.46 christos iov = kmem_alloc(iovsz, KM_SLEEP); 176 1.46 christos } 177 1.46 christos 178 1.46 christos error = netbsd32_to_iovecin(NETBSD32PTR64(msg32->msg_iov), iov, 179 1.46 christos msg32->msg_iovlen); 180 1.46 christos if (error) 181 1.46 christos goto out; 182 1.46 christos 183 1.46 christos netbsd32_to_msghdr(msg32, msg); 184 1.46 christos msg->msg_iov = iov; 185 1.46 christos out: 186 1.46 christos if (iov != aiov) 187 1.46 christos kmem_free(iov, iovsz); 188 1.46 christos return error; 189 1.46 christos } 190 1.46 christos 191 1.46 christos static int 192 1.46 christos msg_recv_copyout(struct lwp *l, struct netbsd32_msghdr *msg32, 193 1.46 christos struct msghdr *msg, struct netbsd32_msghdr *arg, 194 1.46 christos struct mbuf *from, struct mbuf *control) 195 1.46 christos { 196 1.46 christos int error = 0; 197 1.46 christos 198 1.46 christos if (msg->msg_control != NULL) 199 1.46 christos error = copyout32_msg_control(l, msg, control); 200 1.46 christos 201 1.46 christos if (error == 0) 202 1.46 christos error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0, 203 1.46 christos from); 204 1.46 christos 205 1.46 christos if (from != NULL) 206 1.46 christos m_free(from); 207 1.46 christos if (error) 208 1.46 christos return error; 209 1.46 christos 210 1.46 christos msg32->msg_namelen = msg->msg_namelen; 211 1.46 christos msg32->msg_controllen = msg->msg_controllen; 212 1.46 christos msg32->msg_flags = msg->msg_flags; 213 1.46 christos ktrkuser("msghdr", msg, sizeof(*msg)); 214 1.46 christos if (arg == NULL) 215 1.46 christos return 0; 216 1.46 christos return copyout(msg32, arg, sizeof(*arg)); 217 1.46 christos } 218 1.46 christos 219 1.1 mrg int 220 1.45 christos netbsd32_recvmsg(struct lwp *l, const struct netbsd32_recvmsg_args *uap, 221 1.45 christos register_t *retval) 222 1.1 mrg { 223 1.30 dsl /* { 224 1.1 mrg syscallarg(int) s; 225 1.1 mrg syscallarg(netbsd32_msghdrp_t) msg; 226 1.1 mrg syscallarg(int) flags; 227 1.30 dsl } */ 228 1.38 joerg struct netbsd32_msghdr msg32; 229 1.46 christos struct iovec aiov[UIO_SMALLIOV]; 230 1.38 joerg struct msghdr msg; 231 1.38 joerg int error; 232 1.38 joerg struct mbuf *from, *control; 233 1.1 mrg 234 1.38 joerg error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32)); 235 1.1 mrg if (error) 236 1.55 simonb return error; 237 1.38 joerg 238 1.46 christos if ((error = msg_recv_copyin(l, &msg32, &msg, aiov)) != 0) 239 1.46 christos return error; 240 1.1 mrg 241 1.38 joerg msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS; 242 1.45 christos error = do_sys_recvmsg(l, SCARG(uap, s), &msg, 243 1.44 martin &from, msg.msg_control != NULL ? &control : NULL, retval); 244 1.38 joerg if (error != 0) 245 1.46 christos goto out; 246 1.46 christos 247 1.46 christos error = msg_recv_copyout(l, &msg32, &msg, SCARG_P32(uap, msg), 248 1.46 christos from, control); 249 1.46 christos out: 250 1.46 christos if (msg.msg_iov != aiov) 251 1.46 christos kmem_free(msg.msg_iov, msg.msg_iovlen * sizeof(struct iovec)); 252 1.46 christos return error; 253 1.46 christos } 254 1.46 christos 255 1.46 christos int 256 1.46 christos netbsd32_recvmmsg(struct lwp *l, const struct netbsd32_recvmmsg_args *uap, 257 1.46 christos register_t *retval) 258 1.46 christos { 259 1.46 christos /* { 260 1.46 christos syscallarg(int) s; 261 1.46 christos syscallarg(netbsd32_mmsghdr_t) mmsg; 262 1.46 christos syscallarg(unsigned int) vlen; 263 1.46 christos syscallarg(unsigned int) flags; 264 1.46 christos syscallarg(netbsd32_timespecp_t) timeout; 265 1.46 christos } */ 266 1.46 christos struct mmsghdr mmsg; 267 1.46 christos struct netbsd32_mmsghdr mmsg32, *mmsg32p = SCARG_P32(uap, mmsg); 268 1.46 christos struct netbsd32_msghdr *msg32 = &mmsg32.msg_hdr; 269 1.46 christos struct socket *so; 270 1.46 christos struct msghdr *msg = &mmsg.msg_hdr; 271 1.46 christos int error, s; 272 1.46 christos struct mbuf *from, *control; 273 1.46 christos struct timespec ts, now; 274 1.46 christos struct netbsd32_timespec ts32; 275 1.46 christos unsigned int vlen, flags, dg; 276 1.46 christos struct iovec aiov[UIO_SMALLIOV]; 277 1.46 christos 278 1.46 christos ts.tv_sec = 0; // XXX: gcc 279 1.46 christos ts.tv_nsec = 0; 280 1.46 christos if (SCARG_P32(uap, timeout)) { 281 1.46 christos if ((error = copyin(SCARG_P32(uap, timeout), &ts32, 282 1.46 christos sizeof(ts32))) != 0) 283 1.46 christos return error; 284 1.46 christos getnanotime(&now); 285 1.46 christos netbsd32_to_timespec(&ts32, &ts); 286 1.46 christos timespecadd(&now, &ts, &ts); 287 1.46 christos } 288 1.46 christos 289 1.46 christos s = SCARG(uap, s); 290 1.46 christos if ((error = fd_getsock(s, &so)) != 0) 291 1.46 christos return error; 292 1.46 christos 293 1.49 hannken /* 294 1.49 hannken * If so->so_rerror holds a deferred error return it now. 295 1.49 hannken */ 296 1.49 hannken if (so->so_rerror) { 297 1.49 hannken error = so->so_rerror; 298 1.49 hannken so->so_rerror = 0; 299 1.49 hannken fd_putfile(s); 300 1.49 hannken return error; 301 1.49 hannken } 302 1.49 hannken 303 1.46 christos vlen = SCARG(uap, vlen); 304 1.46 christos if (vlen > 1024) 305 1.46 christos vlen = 1024; 306 1.1 mrg 307 1.46 christos from = NULL; 308 1.46 christos flags = SCARG(uap, flags) & MSG_USERFLAGS; 309 1.46 christos 310 1.46 christos for (dg = 0; dg < vlen;) { 311 1.46 christos error = copyin(mmsg32p + dg, &mmsg32, sizeof(mmsg32)); 312 1.46 christos if (error) 313 1.46 christos break; 314 1.46 christos 315 1.46 christos if ((error = msg_recv_copyin(l, msg32, msg, aiov)) != 0) 316 1.46 christos return error; 317 1.46 christos 318 1.46 christos msg->msg_flags = flags & ~MSG_WAITFORONE; 319 1.46 christos 320 1.46 christos if (from != NULL) { 321 1.46 christos m_free(from); 322 1.46 christos from = NULL; 323 1.46 christos } 324 1.46 christos 325 1.46 christos error = do_sys_recvmsg_so(l, s, so, msg, &from, 326 1.46 christos msg->msg_control != NULL ? &control : NULL, retval); 327 1.46 christos if (error) { 328 1.46 christos if (error == EAGAIN && dg > 0) 329 1.46 christos error = 0; 330 1.46 christos break; 331 1.46 christos } 332 1.46 christos error = msg_recv_copyout(l, msg32, msg, NULL, 333 1.46 christos from, control); 334 1.46 christos from = NULL; 335 1.46 christos if (error) 336 1.46 christos break; 337 1.46 christos 338 1.46 christos mmsg32.msg_len = *retval; 339 1.46 christos 340 1.46 christos error = copyout(&mmsg32, mmsg32p + dg, sizeof(mmsg32)); 341 1.46 christos if (error) 342 1.46 christos break; 343 1.46 christos 344 1.46 christos dg++; 345 1.46 christos if (msg->msg_flags & MSG_OOB) 346 1.46 christos break; 347 1.46 christos 348 1.46 christos if (SCARG_P32(uap, timeout)) { 349 1.46 christos getnanotime(&now); 350 1.46 christos timespecsub(&now, &ts, &now); 351 1.46 christos if (now.tv_sec > 0) 352 1.46 christos break; 353 1.46 christos } 354 1.46 christos 355 1.46 christos if (flags & MSG_WAITFORONE) 356 1.46 christos flags |= MSG_DONTWAIT; 357 1.46 christos 358 1.46 christos } 359 1.27 ad 360 1.38 joerg if (from != NULL) 361 1.38 joerg m_free(from); 362 1.27 ad 363 1.46 christos *retval = dg; 364 1.46 christos 365 1.46 christos /* 366 1.49 hannken * If we succeeded at least once, return 0, hopefully so->so_rerror 367 1.46 christos * will catch it next time. 368 1.46 christos */ 369 1.49 hannken if (error && dg > 0) { 370 1.49 hannken so->so_rerror = error; 371 1.49 hannken error = 0; 372 1.49 hannken } 373 1.49 hannken 374 1.49 hannken fd_putfile(s); 375 1.46 christos 376 1.46 christos return error; 377 1.1 mrg } 378 1.1 mrg 379 1.39 joerg static int 380 1.39 joerg copyin32_msg_control(struct lwp *l, struct msghdr *mp) 381 1.39 joerg { 382 1.39 joerg /* 383 1.39 joerg * Handle cmsg if there is any. 384 1.39 joerg */ 385 1.39 joerg struct cmsghdr *cmsg, cmsg32, *cc; 386 1.39 joerg struct mbuf *ctl_mbuf; 387 1.39 joerg ssize_t resid = mp->msg_controllen; 388 1.39 joerg size_t clen, cidx = 0, cspace; 389 1.54 simonb uint8_t *control; 390 1.39 joerg int error; 391 1.39 joerg 392 1.39 joerg ctl_mbuf = m_get(M_WAIT, MT_CONTROL); 393 1.39 joerg clen = MLEN; 394 1.39 joerg control = mtod(ctl_mbuf, void *); 395 1.39 joerg memset(control, 0, clen); 396 1.39 joerg 397 1.45 christos for (cc = CMSG32_FIRSTHDR(mp); cc; cc = CMSG32_NXTHDR(mp, &cmsg32, cc)) 398 1.45 christos { 399 1.39 joerg error = copyin(cc, &cmsg32, sizeof(cmsg32)); 400 1.39 joerg if (error) 401 1.39 joerg goto failure; 402 1.39 joerg 403 1.39 joerg /* 404 1.39 joerg * Sanity check the control message length. 405 1.39 joerg */ 406 1.52 mlelstv if (resid < 0 || 407 1.52 mlelstv cmsg32.cmsg_len > (size_t)resid || 408 1.39 joerg cmsg32.cmsg_len < sizeof(cmsg32)) { 409 1.39 joerg error = EINVAL; 410 1.39 joerg goto failure; 411 1.39 joerg } 412 1.39 joerg 413 1.39 joerg cspace = CMSG_SPACE(cmsg32.cmsg_len - CMSG32_LEN(0)); 414 1.39 joerg 415 1.39 joerg /* Check the buffer is big enough */ 416 1.39 joerg if (__predict_false(cidx + cspace > clen)) { 417 1.54 simonb uint8_t *nc; 418 1.39 joerg size_t nclen; 419 1.39 joerg 420 1.39 joerg nclen = cidx + cspace; 421 1.53 mlelstv if (nclen >= (size_t)PAGE_SIZE) { 422 1.39 joerg error = EINVAL; 423 1.39 joerg goto failure; 424 1.39 joerg } 425 1.39 joerg nc = realloc(clen <= MLEN ? NULL : control, 426 1.39 joerg nclen, M_TEMP, M_WAITOK); 427 1.39 joerg if (!nc) { 428 1.39 joerg error = ENOMEM; 429 1.39 joerg goto failure; 430 1.39 joerg } 431 1.39 joerg if (cidx <= MLEN) { 432 1.39 joerg /* Old buffer was in mbuf... */ 433 1.39 joerg memcpy(nc, control, cidx); 434 1.39 joerg memset(nc + cidx, 0, nclen - cidx); 435 1.39 joerg } else { 436 1.39 joerg memset(nc + nclen, 0, nclen - clen); 437 1.39 joerg } 438 1.39 joerg control = nc; 439 1.39 joerg clen = nclen; 440 1.39 joerg } 441 1.39 joerg 442 1.39 joerg /* Copy header */ 443 1.39 joerg cmsg = (void *)&control[cidx]; 444 1.39 joerg cmsg->cmsg_len = CMSG_LEN(cmsg32.cmsg_len - CMSG32_LEN(0)); 445 1.39 joerg cmsg->cmsg_level = cmsg32.cmsg_level; 446 1.39 joerg cmsg->cmsg_type = cmsg32.cmsg_type; 447 1.39 joerg 448 1.39 joerg /* Copyin the data */ 449 1.39 joerg error = copyin(CMSG32_DATA(cc), CMSG_DATA(cmsg), 450 1.39 joerg cmsg32.cmsg_len - CMSG32_LEN(0)); 451 1.39 joerg if (error) 452 1.39 joerg goto failure; 453 1.45 christos ktrkuser(mbuftypes[MT_CONTROL], cmsg, cmsg->cmsg_len); 454 1.39 joerg 455 1.39 joerg resid -= CMSG32_ALIGN(cmsg32.cmsg_len); 456 1.45 christos cidx += CMSG_ALIGN(cmsg->cmsg_len); 457 1.45 christos } 458 1.39 joerg 459 1.39 joerg /* If we allocated a buffer, attach to mbuf */ 460 1.39 joerg if (cidx > MLEN) { 461 1.39 joerg MEXTADD(ctl_mbuf, control, clen, M_MBUF, NULL, NULL); 462 1.39 joerg ctl_mbuf->m_flags |= M_EXT_RW; 463 1.39 joerg } 464 1.39 joerg control = NULL; 465 1.39 joerg mp->msg_controllen = ctl_mbuf->m_len = CMSG_ALIGN(cidx); 466 1.39 joerg 467 1.39 joerg mp->msg_control = ctl_mbuf; 468 1.39 joerg mp->msg_flags |= MSG_CONTROLMBUF; 469 1.39 joerg 470 1.39 joerg 471 1.39 joerg return 0; 472 1.39 joerg 473 1.39 joerg failure: 474 1.39 joerg if (control != mtod(ctl_mbuf, void *)) 475 1.39 joerg free(control, M_MBUF); 476 1.39 joerg m_free(ctl_mbuf); 477 1.39 joerg return error; 478 1.39 joerg } 479 1.39 joerg 480 1.46 christos static int 481 1.46 christos msg_send_copyin(struct lwp *l, const struct netbsd32_msghdr *msg32, 482 1.46 christos struct msghdr *msg, struct iovec *aiov) 483 1.46 christos { 484 1.46 christos int error; 485 1.46 christos struct iovec *iov = aiov; 486 1.46 christos struct netbsd32_iovec *iov32; 487 1.46 christos size_t iovsz; 488 1.46 christos 489 1.46 christos netbsd32_to_msghdr(msg32, msg); 490 1.46 christos msg->msg_flags = 0; 491 1.46 christos 492 1.46 christos if (CMSG32_FIRSTHDR(msg)) { 493 1.46 christos error = copyin32_msg_control(l, msg); 494 1.46 christos if (error) 495 1.46 christos return error; 496 1.46 christos /* From here on, msg->msg_control is allocated */ 497 1.46 christos } else { 498 1.46 christos msg->msg_control = NULL; 499 1.46 christos msg->msg_controllen = 0; 500 1.46 christos } 501 1.46 christos 502 1.46 christos iovsz = msg->msg_iovlen * sizeof(struct iovec); 503 1.46 christos if ((u_int)msg->msg_iovlen > UIO_SMALLIOV) { 504 1.46 christos if ((u_int)msg->msg_iovlen > IOV_MAX) { 505 1.46 christos error = EMSGSIZE; 506 1.46 christos goto out; 507 1.46 christos } 508 1.46 christos iov = kmem_alloc(iovsz, KM_SLEEP); 509 1.46 christos } 510 1.46 christos 511 1.46 christos iov32 = NETBSD32PTR64(msg32->msg_iov); 512 1.46 christos error = netbsd32_to_iovecin(iov32, iov, msg->msg_iovlen); 513 1.46 christos if (error) 514 1.46 christos goto out; 515 1.46 christos msg->msg_iov = iov; 516 1.47 christos return 0; 517 1.46 christos out: 518 1.46 christos if (msg->msg_control) 519 1.46 christos m_free(msg->msg_control); 520 1.46 christos if (iov != aiov) 521 1.46 christos kmem_free(iov, iovsz); 522 1.46 christos return error; 523 1.46 christos } 524 1.46 christos 525 1.1 mrg int 526 1.45 christos netbsd32_sendmsg(struct lwp *l, const struct netbsd32_sendmsg_args *uap, 527 1.45 christos register_t *retval) 528 1.1 mrg { 529 1.30 dsl /* { 530 1.1 mrg syscallarg(int) s; 531 1.1 mrg syscallarg(const netbsd32_msghdrp_t) msg; 532 1.1 mrg syscallarg(int) flags; 533 1.30 dsl } */ 534 1.1 mrg struct msghdr msg; 535 1.1 mrg struct netbsd32_msghdr msg32; 536 1.46 christos struct iovec aiov[UIO_SMALLIOV]; 537 1.1 mrg int error; 538 1.1 mrg 539 1.24 dsl error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32)); 540 1.1 mrg if (error) 541 1.46 christos return error; 542 1.46 christos 543 1.46 christos if ((error = msg_send_copyin(l, &msg32, &msg, aiov)) != 0) 544 1.46 christos return error; 545 1.46 christos 546 1.46 christos error = do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), 547 1.46 christos retval); 548 1.46 christos /* msg.msg_control freed by do_sys_sendmsg() */ 549 1.46 christos 550 1.46 christos if (msg.msg_iov != aiov) 551 1.46 christos kmem_free(msg.msg_iov, msg.msg_iovlen * sizeof(struct iovec)); 552 1.46 christos return error; 553 1.46 christos } 554 1.46 christos 555 1.46 christos int 556 1.46 christos netbsd32_sendmmsg(struct lwp *l, const struct netbsd32_sendmmsg_args *uap, 557 1.46 christos register_t *retval) 558 1.46 christos { 559 1.46 christos /* { 560 1.46 christos syscallarg(int) s; 561 1.46 christos syscallarg(const netbsd32_mmsghdr_t) mmsg; 562 1.46 christos syscallarg(unsigned int) vlen; 563 1.46 christos syscallarg(unsigned int) flags; 564 1.46 christos } */ 565 1.46 christos struct mmsghdr mmsg; 566 1.46 christos struct netbsd32_mmsghdr mmsg32, *mmsg32p = SCARG_P32(uap, mmsg); 567 1.46 christos struct netbsd32_msghdr *msg32 = &mmsg32.msg_hdr; 568 1.46 christos struct socket *so; 569 1.46 christos file_t *fp; 570 1.46 christos struct msghdr *msg = &mmsg.msg_hdr; 571 1.46 christos int error, s; 572 1.46 christos unsigned int vlen, flags, dg; 573 1.46 christos struct iovec aiov[UIO_SMALLIOV]; 574 1.46 christos 575 1.46 christos s = SCARG(uap, s); 576 1.46 christos if ((error = fd_getsock1(s, &so, &fp)) != 0) 577 1.46 christos return error; 578 1.46 christos 579 1.46 christos vlen = SCARG(uap, vlen); 580 1.46 christos if (vlen > 1024) 581 1.46 christos vlen = 1024; 582 1.46 christos 583 1.46 christos flags = SCARG(uap, flags) & MSG_USERFLAGS; 584 1.39 joerg 585 1.46 christos for (dg = 0; dg < vlen;) { 586 1.46 christos error = copyin(mmsg32p + dg, &mmsg32, sizeof(mmsg32)); 587 1.39 joerg if (error) 588 1.46 christos break; 589 1.46 christos if ((error = msg_send_copyin(l, msg32, msg, aiov)) != 0) 590 1.46 christos break; 591 1.46 christos 592 1.46 christos msg->msg_flags = flags; 593 1.26 dsl 594 1.46 christos error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval); 595 1.46 christos if (msg->msg_iov != aiov) { 596 1.46 christos kmem_free(msg->msg_iov, 597 1.46 christos msg->msg_iovlen * sizeof(struct iovec)); 598 1.42 maxv } 599 1.46 christos if (error) 600 1.46 christos break; 601 1.46 christos 602 1.46 christos ktrkuser("msghdr", msg, sizeof(*msg)); 603 1.46 christos mmsg.msg_len = *retval; 604 1.46 christos netbsd32_from_mmsghdr(&mmsg32, &mmsg); 605 1.46 christos error = copyout(&mmsg32, mmsg32p + dg, sizeof(mmsg32)); 606 1.46 christos if (error) 607 1.46 christos break; 608 1.46 christos dg++; 609 1.42 maxv } 610 1.26 dsl 611 1.46 christos *retval = dg; 612 1.42 maxv 613 1.46 christos fd_putfile(s); 614 1.42 maxv 615 1.46 christos /* 616 1.49 hannken * If we succeeded at least once, return 0. 617 1.46 christos */ 618 1.46 christos if (dg) 619 1.46 christos return 0; 620 1.42 maxv return error; 621 1.1 mrg } 622 1.1 mrg 623 1.1 mrg int 624 1.45 christos netbsd32_recvfrom(struct lwp *l, const struct netbsd32_recvfrom_args *uap, 625 1.45 christos register_t *retval) 626 1.1 mrg { 627 1.30 dsl /* { 628 1.1 mrg syscallarg(int) s; 629 1.1 mrg syscallarg(netbsd32_voidp) buf; 630 1.1 mrg syscallarg(netbsd32_size_t) len; 631 1.1 mrg syscallarg(int) flags; 632 1.1 mrg syscallarg(netbsd32_sockaddrp_t) from; 633 1.1 mrg syscallarg(netbsd32_intp) fromlenaddr; 634 1.30 dsl } */ 635 1.38 joerg struct msghdr msg; 636 1.38 joerg struct iovec aiov; 637 1.38 joerg int error; 638 1.38 joerg struct mbuf *from; 639 1.1 mrg 640 1.56 simonb if (SCARG(uap, len) > NETBSD32_SSIZE_MAX) 641 1.56 simonb return EINVAL; 642 1.56 simonb 643 1.38 joerg msg.msg_name = NULL; 644 1.38 joerg msg.msg_iov = &aiov; 645 1.1 mrg msg.msg_iovlen = 1; 646 1.24 dsl aiov.iov_base = SCARG_P32(uap, buf); 647 1.38 joerg aiov.iov_len = SCARG(uap, len); 648 1.38 joerg msg.msg_control = NULL; 649 1.38 joerg msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS; 650 1.38 joerg 651 1.45 christos error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval); 652 1.38 joerg if (error != 0) 653 1.38 joerg return error; 654 1.38 joerg 655 1.45 christos error = copyout_sockname(SCARG_P32(uap, from), 656 1.45 christos SCARG_P32(uap, fromlenaddr), MSG_LENUSRSPACE, from); 657 1.38 joerg if (from != NULL) 658 1.38 joerg m_free(from); 659 1.38 joerg return error; 660 1.1 mrg } 661 1.1 mrg 662 1.1 mrg int 663 1.45 christos netbsd32_sendto(struct lwp *l, const struct netbsd32_sendto_args *uap, 664 1.45 christos register_t *retval) 665 1.1 mrg { 666 1.30 dsl /* { 667 1.1 mrg syscallarg(int) s; 668 1.1 mrg syscallarg(const netbsd32_voidp) buf; 669 1.1 mrg syscallarg(netbsd32_size_t) len; 670 1.1 mrg syscallarg(int) flags; 671 1.1 mrg syscallarg(const netbsd32_sockaddrp_t) to; 672 1.1 mrg syscallarg(int) tolen; 673 1.30 dsl } */ 674 1.1 mrg struct msghdr msg; 675 1.1 mrg struct iovec aiov; 676 1.1 mrg 677 1.56 simonb if (SCARG(uap, len) > NETBSD32_SSIZE_MAX) 678 1.56 simonb return EINVAL; 679 1.56 simonb 680 1.24 dsl msg.msg_name = SCARG_P32(uap, to); /* XXX kills const */ 681 1.1 mrg msg.msg_namelen = SCARG(uap, tolen); 682 1.1 mrg msg.msg_iov = &aiov; 683 1.1 mrg msg.msg_iovlen = 1; 684 1.1 mrg msg.msg_control = 0; 685 1.24 dsl aiov.iov_base = SCARG_P32(uap, buf); /* XXX kills const */ 686 1.1 mrg aiov.iov_len = SCARG(uap, len); 687 1.26 dsl msg.msg_flags = 0; 688 1.44 martin return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), 689 1.45 christos retval); 690 1.1 mrg } 691