AMD64 - Refactor uio_resid and size_t assumptions.
[dragonfly.git] / sys / emulation / 43bsd / 43bsd_socket.c
CommitLineData
9eee10d0
DRJ
1/*
2 * 43BSD_SOCKET.C - 4.3BSD compatibility socket syscalls
3 *
4 * Copyright (c) 1982, 1986, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
b9cd15b9 35 * $DragonFly: src/sys/emulation/43bsd/43bsd_socket.c,v 1.10 2007/01/28 06:31:00 y0netan1 Exp $
9eee10d0
DRJ
36 * from: DragonFly kern/uipc_syscalls.c,v 1.13
37 *
38 * The original versions of these syscalls used to live in
39 * kern/uipc_syscalls.c. These are heavily modified to use the
40 * new split syscalls.
41 */
42
43#include "opt_compat.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/kernel.h>
48#include <sys/sysproto.h>
3e1837ce 49#include <sys/kern_syscall.h>
9eee10d0 50#include <sys/malloc.h>
35fbb1d9 51#include <sys/mbuf.h>
3e1837ce 52#include <sys/proc.h>
9eee10d0
DRJ
53#include <sys/socket.h>
54#include <sys/socketvar.h>
35fbb1d9 55#include <sys/uio.h>
9eee10d0
DRJ
56
57#include "43bsd_socket.h"
58
59/*
60 * System call interface to the socket abstraction.
61 */
62
63static int
64compat_43_getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len)
65{
66 struct sockaddr *sa;
67 int error;
68
69 *namp = NULL;
70 if (len > SOCK_MAXADDRLEN)
71 return ENAMETOOLONG;
72 if (len < offsetof(struct sockaddr, sa_data[0]))
73 return EDOM;
74 MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
75 error = copyin(uaddr, sa, len);
76 if (error) {
77 FREE(sa, M_SONAME);
78 } else {
79 /*
80 * Convert to the 4.4BSD sockaddr structure.
81 */
82 sa->sa_family = sa->sa_len;
83 sa->sa_len = len;
84 *namp = sa;
85 }
86 return error;
87}
88
89static int
35fbb1d9 90compat_43_copyout_sockaddr(struct sockaddr *sa, caddr_t uaddr, int sa_len)
9eee10d0 91{
35fbb1d9 92 int error;
9eee10d0 93
9eee10d0 94 ((struct osockaddr *)sa)->sa_family = sa->sa_family;
9eee10d0
DRJ
95 error = copyout(sa, uaddr, sa_len);
96
97 return (error);
98}
99
100int
753fd850 101sys_oaccept(struct accept_args *uap)
9eee10d0
DRJ
102{
103 struct sockaddr *sa = NULL;
104 int sa_len;
105 int error;
106
107 if (uap->name) {
108 error = copyin(uap->anamelen, &sa_len, sizeof(sa_len));
109 if (error)
110 return (error);
111
e54488bb
MD
112 error = kern_accept(uap->s, 0, &sa, &sa_len,
113 &uap->sysmsg_iresult);
9eee10d0
DRJ
114
115 if (error) {
116 /*
117 * return a namelen of zero for older code which
118 * might ignore the return value from accept.
119 */
120 sa_len = 0;
121 copyout(&sa_len, uap->anamelen, sizeof(*uap->anamelen));
122 } else {
35fbb1d9 123 compat_43_copyout_sockaddr(sa, uap->name, sa_len);
9eee10d0
DRJ
124 if (error == 0) {
125 error = copyout(&sa_len, uap->anamelen,
126 sizeof(*uap->anamelen));
127 }
128 }
129 if (sa)
130 FREE(sa, M_SONAME);
131 } else {
e54488bb 132 error = kern_accept(uap->s, 0, NULL, 0, &uap->sysmsg_iresult);
9eee10d0
DRJ
133 }
134 return (error);
135}
136
137int
753fd850 138sys_ogetsockname(struct getsockname_args *uap)
9eee10d0
DRJ
139{
140 struct sockaddr *sa = NULL;
141 int error, sa_len;
142
143 error = copyin(uap->alen, &sa_len, sizeof(sa_len));
144 if (error)
145 return (error);
146
147 error = kern_getsockname(uap->fdes, &sa, &sa_len);
148
149 if (error == 0)
35fbb1d9 150 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
9eee10d0
DRJ
151 if (error == 0) {
152 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
153 }
154 if (sa)
155 FREE(sa, M_SONAME);
156 return (error);
157}
158
159int
753fd850 160sys_ogetpeername(struct ogetpeername_args *uap)
9eee10d0
DRJ
161{
162 struct sockaddr *sa = NULL;
163 int error, sa_len;
164
165 error = copyin(uap->alen, &sa_len, sizeof(sa_len));
166 if (error)
167 return (error);
168
169 error = kern_getpeername(uap->fdes, &sa, &sa_len);
170
171 if (error == 0) {
35fbb1d9 172 error = compat_43_copyout_sockaddr(sa, uap->asa, sa_len);
9eee10d0
DRJ
173 }
174 if (error == 0)
175 error = copyout(&sa_len, uap->alen, sizeof(*uap->alen));
176 if (sa)
177 FREE(sa, M_SONAME);
178 return (error);
179}
35fbb1d9
DRJ
180
181int
753fd850 182sys_osend(struct osend_args *uap)
35fbb1d9 183{
3e1837ce
DRJ
184 struct thread *td = curthread;
185 struct uio auio;
35fbb1d9
DRJ
186 struct iovec aiov;
187 int error;
188
35fbb1d9
DRJ
189 aiov.iov_base = uap->buf;
190 aiov.iov_len = uap->len;
3e1837ce
DRJ
191 auio.uio_iov = &aiov;
192 auio.uio_iovcnt = 1;
193 auio.uio_offset = 0;
194 auio.uio_resid = uap->len;
195 auio.uio_segflg = UIO_USERSPACE;
196 auio.uio_rw = UIO_WRITE;
197 auio.uio_td = td;
35fbb1d9 198
3e1837ce 199 error = kern_sendmsg(uap->s, NULL, &auio, NULL, uap->flags,
e54488bb 200 &uap->sysmsg_szresult);
35fbb1d9
DRJ
201
202 return (error);
203}
204
205int
753fd850 206sys_osendmsg(struct osendmsg_args *uap)
35fbb1d9 207{
3e1837ce 208 struct thread *td = curthread;
35fbb1d9 209 struct msghdr msg;
3e1837ce 210 struct uio auio;
75a872f8 211 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
35fbb1d9
DRJ
212 struct sockaddr *sa = NULL;
213 struct mbuf *control = NULL;
214 struct cmsghdr *cm;
75a872f8 215 int error;
35fbb1d9
DRJ
216
217 error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
218 if (error)
219 return (error);
220
221 /*
222 * Conditionally copyin msg.msg_name.
223 */
224 if (msg.msg_name) {
225 error = compat_43_getsockaddr(&sa, msg.msg_name,
226 msg.msg_namelen);
227 if (error)
228 return (error);
35fbb1d9
DRJ
229 }
230
231 /*
3e1837ce
DRJ
232 * Populate auio.
233 */
75a872f8 234 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
ef5c76d7 235 &auio.uio_resid);
3e1837ce 236 if (error)
8130f673 237 goto cleanup2;
3e1837ce
DRJ
238 auio.uio_iov = iov;
239 auio.uio_iovcnt = msg.msg_iovlen;
240 auio.uio_offset = 0;
3e1837ce
DRJ
241 auio.uio_segflg = UIO_USERSPACE;
242 auio.uio_rw = UIO_WRITE;
243 auio.uio_td = td;
244
245 /*
35fbb1d9
DRJ
246 * Conditionally copyin msg.msg_control.
247 */
248 if (msg.msg_control) {
3e1837ce 249 if (msg.msg_controllen < 0 || msg.msg_controllen > MLEN) {
35fbb1d9
DRJ
250 error = EINVAL;
251 goto cleanup;
252 }
74f1caca 253 control = m_get(MB_WAIT, MT_CONTROL);
3e1837ce
DRJ
254 if (control == NULL) {
255 error = ENOBUFS;
35fbb1d9 256 goto cleanup;
3e1837ce
DRJ
257 }
258 control->m_len = msg.msg_controllen;
259 error = copyin(msg.msg_control, mtod(control, caddr_t),
260 msg.msg_controllen);
261 if (error) {
262 m_free(control);
263 goto cleanup;
264 }
35fbb1d9
DRJ
265 /*
266 * In 4.3BSD, the only type of ancillary data was
267 * access rights and this data did not use a header
268 * to identify it's type. Thus, we must prepend the
269 * control data with the proper cmsghdr structure
270 * so that the kernel recognizes it as access rights.
271 */
74f1caca 272 M_PREPEND(control, sizeof(*cm), MB_WAIT);
35fbb1d9
DRJ
273 if (control == NULL) {
274 error = ENOBUFS;
275 goto cleanup;
276 } else {
277 cm = mtod(control, struct cmsghdr *);
278 cm->cmsg_len = control->m_len;
279 cm->cmsg_level = SOL_SOCKET;
280 cm->cmsg_type = SCM_RIGHTS;
281 }
35fbb1d9
DRJ
282 }
283
3e1837ce 284 error = kern_sendmsg(uap->s, sa, &auio, control, uap->flags,
e54488bb 285 &uap->sysmsg_szresult);
35fbb1d9
DRJ
286
287cleanup:
8130f673
MD
288 iovec_free(&iov, aiov);
289cleanup2:
35fbb1d9
DRJ
290 if (sa)
291 FREE(sa, M_SONAME);
35fbb1d9
DRJ
292 return (error);
293}
294
295int
753fd850 296sys_orecv(struct orecv_args *uap)
35fbb1d9 297{
3e1837ce
DRJ
298 struct thread *td = curthread;
299 struct uio auio;
35fbb1d9
DRJ
300 struct iovec aiov;
301 int error;
302
35fbb1d9
DRJ
303 aiov.iov_base = uap->buf;
304 aiov.iov_len = uap->len;
3e1837ce
DRJ
305 auio.uio_iov = &aiov;
306 auio.uio_iovcnt = 1;
307 auio.uio_offset = 0;
308 auio.uio_resid = uap->len;
309 auio.uio_segflg = UIO_USERSPACE;
310 auio.uio_rw = UIO_READ;
311 auio.uio_td = td;
35fbb1d9 312
3e1837ce 313 error = kern_recvmsg(uap->s, NULL, &auio, NULL, &uap->flags,
e54488bb 314 &uap->sysmsg_szresult);
35fbb1d9
DRJ
315
316 return (error);
317}
318
319int
753fd850 320sys_orecvfrom(struct recvfrom_args *uap)
35fbb1d9 321{
3e1837ce
DRJ
322 struct thread *td = curthread;
323 struct uio auio;
35fbb1d9 324 struct iovec aiov;
3e1837ce 325 struct sockaddr *sa = NULL;
35fbb1d9
DRJ
326 int error, fromlen;
327
3e1837ce 328 if (uap->from && uap->fromlenaddr) {
35fbb1d9
DRJ
329 error = copyin(uap->fromlenaddr, &fromlen, sizeof(fromlen));
330 if (error)
331 return (error);
3e1837ce
DRJ
332 if (fromlen < 0)
333 return (EINVAL);
35fbb1d9
DRJ
334 } else {
335 fromlen = 0;
336 }
35fbb1d9
DRJ
337 aiov.iov_base = uap->buf;
338 aiov.iov_len = uap->len;
3e1837ce
DRJ
339 auio.uio_iov = &aiov;
340 auio.uio_iovcnt = 1;
341 auio.uio_offset = 0;
342 auio.uio_resid = uap->len;
343 auio.uio_segflg = UIO_USERSPACE;
344 auio.uio_rw = UIO_READ;
345 auio.uio_td = td;
346
347 error = kern_recvmsg(uap->s, uap->from ? &sa : NULL, &auio, NULL,
e54488bb 348 &uap->flags, &uap->sysmsg_szresult);
3e1837ce
DRJ
349
350 if (error == 0 && uap->from) {
b9cd15b9
YT
351 if (sa != NULL) {
352 fromlen = MIN(fromlen, sa->sa_len);
353 error = compat_43_copyout_sockaddr(sa, uap->from,
354 fromlen);
355 } else
356 fromlen = 0;
35fbb1d9
DRJ
357 if (error == 0)
358 /*
359 * Old recvfrom didn't signal an error if this
360 * next copyout failed.
361 */
362 copyout(&fromlen, uap->fromlenaddr, sizeof(fromlen));
363 }
3e1837ce
DRJ
364 if (sa)
365 FREE(sa, M_SONAME);
35fbb1d9
DRJ
366
367 return (error);
368}
369
370int
753fd850 371sys_orecvmsg(struct orecvmsg_args *uap)
35fbb1d9 372{
3e1837ce 373 struct thread *td = curthread;
35fbb1d9 374 struct msghdr msg;
3e1837ce 375 struct uio auio;
75a872f8
DRJ
376 struct iovec aiov[UIO_SMALLIOV], *iov = NULL;
377 struct mbuf *m, *control = NULL;
3e1837ce 378 struct sockaddr *sa = NULL;
35fbb1d9 379 caddr_t ctlbuf;
3e1837ce 380 socklen_t *ufromlenp, *ucontrollenp;
75a872f8 381 int error, fromlen, controllen, len, flags, *uflagsp;
35fbb1d9
DRJ
382
383 /*
384 * This copyin handles everything except the iovec.
385 */
386 error = copyin(uap->msg, &msg, sizeof(struct omsghdr));
387 if (error)
388 return (error);
389
3e1837ce
DRJ
390 if (msg.msg_name && msg.msg_namelen < 0)
391 return (EINVAL);
392 if (msg.msg_control && msg.msg_controllen < 0)
393 return (EINVAL);
394
395 ufromlenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
35fbb1d9 396 msg_namelen));
35fbb1d9
DRJ
397 ucontrollenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr,
398 msg_controllen));
3e1837ce
DRJ
399 uflagsp = (int *)((caddr_t)uap->msg + offsetof(struct msghdr,
400 msg_flags));
35fbb1d9
DRJ
401
402 /*
3e1837ce 403 * Populate auio.
35fbb1d9 404 */
75a872f8 405 error = iovec_copyin(msg.msg_iov, &iov, aiov, msg.msg_iovlen,
ef5c76d7 406 &auio.uio_resid);
35fbb1d9 407 if (error)
75a872f8 408 return (error);
3e1837ce
DRJ
409 auio.uio_iov = iov;
410 auio.uio_iovcnt = msg.msg_iovlen;
411 auio.uio_offset = 0;
3e1837ce
DRJ
412 auio.uio_segflg = UIO_USERSPACE;
413 auio.uio_rw = UIO_READ;
414 auio.uio_td = td;
35fbb1d9 415
3e1837ce 416 flags = msg.msg_flags;
35fbb1d9 417
e54488bb
MD
418 error = kern_recvmsg(uap->s, (msg.msg_name ? &sa : NULL), &auio,
419 (msg.msg_control ? &control : NULL), &flags,
420 &uap->sysmsg_szresult);
35fbb1d9
DRJ
421
422 /*
423 * Copyout msg.msg_name and msg.msg_namelen.
424 */
3e1837ce 425 if (error == 0 && msg.msg_name) {
b9cd15b9
YT
426 if (sa != NULL) {
427 fromlen = MIN(msg.msg_namelen, sa->sa_len);
428 error = compat_43_copyout_sockaddr(sa, msg.msg_name,
429 fromlen);
430 } else
431 fromlen = 0;
35fbb1d9
DRJ
432 if (error == 0)
433 /*
434 * Old recvfrom didn't signal an error if this
435 * next copyout failed.
436 */
3e1837ce 437 copyout(&fromlen, ufromlenp, sizeof(*ufromlenp));
35fbb1d9
DRJ
438 }
439
440 /*
441 * Copyout msg.msg_control and msg.msg_controllen.
442 */
3e1837ce 443 if (error == 0 && msg.msg_control) {
35fbb1d9
DRJ
444 /*
445 * If we receive access rights, trim the cmsghdr; anything
446 * else is tossed.
447 */
3e1837ce
DRJ
448 if (mtod((struct mbuf *)msg.msg_control,
449 struct cmsghdr *)->cmsg_level != SOL_SOCKET ||
450 mtod((struct mbuf *)msg.msg_control,
451 struct cmsghdr *)->cmsg_type != SCM_RIGHTS) {
452 int temp = 0;
453 error = copyout(&temp, ucontrollenp,
454 sizeof(*ucontrollenp));
455 goto cleanup;
35fbb1d9 456 }
3e1837ce
DRJ
457 ((struct mbuf *)msg.msg_control)->m_len -=
458 sizeof(struct cmsghdr);
459 ((struct mbuf *)msg.msg_control)->m_data +=
460 sizeof(struct cmsghdr);
35fbb1d9
DRJ
461
462 len = msg.msg_controllen;
3e1837ce
DRJ
463 m = control;
464 ctlbuf = (caddr_t)msg.msg_control;
35fbb1d9
DRJ
465
466 while(m && len > 0) {
467 unsigned int tocopy;
468
469 if (len >= m->m_len) {
470 tocopy = m->m_len;
471 } else {
472 msg.msg_flags |= MSG_CTRUNC;
473 tocopy = len;
474 }
475
476 error = copyout(mtod(m, caddr_t), ctlbuf,
477 tocopy);
478 if (error)
479 goto cleanup;
480
481 ctlbuf += tocopy;
482 len -= tocopy;
483 m = m->m_next;
484 }
3e1837ce
DRJ
485 controllen = ctlbuf - (caddr_t)msg.msg_control;
486 error = copyout(&controllen, ucontrollenp,
35fbb1d9
DRJ
487 sizeof(*ucontrollenp));
488 }
489
3e1837ce
DRJ
490 if (error == 0)
491 error = copyout(&flags, uflagsp, sizeof(*uflagsp));
492
35fbb1d9 493cleanup:
3e1837ce
DRJ
494 if (sa)
495 FREE(sa, M_SONAME);
75a872f8 496 iovec_free(&iov, aiov);
3e1837ce
DRJ
497 if (control)
498 m_freem(control);
35fbb1d9
DRJ
499 return (error);
500}
501