change gdium conf to print message out both on uart and lcd
[pmon-gdium.git] / sys / kern / uipc_syscalls.c
blob0fe891a62d2cebd14d715d9dfbca0d12d3a72821
1 /* $Id: uipc_syscalls.c,v 1.1.1.1 2006/09/14 01:59:08 root Exp $ */
2 /* $OpenBSD: uipc_syscalls.c,v 1.28 1999/07/13 15:17:51 provos Exp $ */
3 /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */
5 /*
6 * Copyright (c) 1982, 1986, 1989, 1990, 1993
7 * The Regents of the University of California. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
37 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/filedesc.h>
43 #include <sys/proc.h>
44 #include <sys/file.h>
45 #include <sys/buf.h>
46 #include <sys/malloc.h>
47 #include <sys/mbuf.h>
48 #include <sys/protosw.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/signalvar.h>
52 #if 0
53 #include <sys/un.h>
54 #endif
55 #ifdef KTRACE
56 #include <sys/ktrace.h>
57 #endif
59 #if 0
60 #include <sys/mount.h>
61 #endif
62 #include <sys/syscallargs.h>
65 * System call interface to the socket abstraction.
67 extern struct fileops socketops;
69 int
70 sys_socket(p, v, retval)
71 struct proc *p;
72 void *v;
73 register_t *retval;
75 register struct sys_socket_args /* {
76 syscallarg(int) domain;
77 syscallarg(int) type;
78 syscallarg(int) protocol;
79 } */ *uap = v;
80 struct filedesc *fdp = p->p_fd;
81 struct socket *so;
82 struct file *fp;
83 int fd, error;
85 if ((error = falloc(p, &fp, &fd)) != 0)
86 return (error);
87 fp->f_flag = FREAD|FWRITE;
88 fp->f_type = DTYPE_SOCKET;
89 fp->f_ops = &socketops;
90 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
91 SCARG(uap, protocol));
92 if (error) {
93 fdremove(fdp, fd);
94 ffree(fp);
95 } else {
96 fp->f_data = (caddr_t)so;
97 *retval = fd;
99 return (error);
102 /* ARGSUSED */
104 sys_bind(p, v, retval)
105 struct proc *p;
106 void *v;
107 register_t *retval;
109 register struct sys_bind_args /* {
110 syscallarg(int) s;
111 syscallarg(struct sockaddr *) name;
112 syscallarg(socklen_t) namelen;
113 } */ *uap = v;
114 struct file *fp;
115 struct mbuf *nam;
116 int error;
118 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
119 return (error);
120 error = sockargs(&nam, (caddr_t)SCARG(uap, name), SCARG(uap, namelen),
121 MT_SONAME);
122 if (error)
123 return (error);
124 error = sobind((struct socket *)fp->f_data, nam);
125 m_freem(nam);
126 return (error);
129 /* ARGSUSED */
131 sys_listen(p, v, retval)
132 struct proc *p;
133 void *v;
134 register_t *retval;
136 register struct sys_listen_args /* {
137 syscallarg(int) s;
138 syscallarg(int) backlog;
139 } */ *uap = v;
140 struct file *fp;
141 int error;
143 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
144 return (error);
145 return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog)));
149 sys_accept(p, v, retval)
150 struct proc *p;
151 void *v;
152 register_t *retval;
154 register struct sys_accept_args /* {
155 syscallarg(int) s;
156 syscallarg(struct sockaddr *) name;
157 syscallarg(socklen_t *) anamelen;
158 } */ *uap = v;
159 struct file *fp;
160 struct mbuf *nam;
161 socklen_t namelen;
162 int error, s, tmpfd;
163 register struct socket *so;
165 if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
166 (caddr_t)&namelen, sizeof (namelen))))
167 return (error);
168 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
169 return (error);
170 s = splsoftnet();
171 so = (struct socket *)fp->f_data;
172 if ((so->so_options & SO_ACCEPTCONN) == 0) {
173 splx(s);
174 return (EINVAL);
176 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
177 splx(s);
178 return (EWOULDBLOCK);
180 while (so->so_qlen == 0 && so->so_error == 0) {
181 if (so->so_state & SS_CANTRCVMORE) {
182 so->so_error = ECONNABORTED;
183 break;
185 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
186 netcon, 0);
187 if (error) {
188 splx(s);
189 return (error);
192 if (so->so_error) {
193 error = so->so_error;
194 so->so_error = 0;
195 splx(s);
196 return (error);
198 if ((error = falloc(p, &fp, &tmpfd)) != 0) {
199 splx(s);
200 return (error);
202 *retval = tmpfd;
203 { struct socket *aso = so->so_q;
204 if (soqremque(aso, 1) == 0)
205 panic("accept");
206 so = aso;
208 fp->f_type = DTYPE_SOCKET;
209 fp->f_flag = FREAD|FWRITE;
210 fp->f_ops = &socketops;
211 fp->f_data = (caddr_t)so;
212 nam = m_get(M_WAIT, MT_SONAME);
213 (void) soaccept(so, nam);
214 if (SCARG(uap, name)) {
215 if (namelen > nam->m_len)
216 namelen = nam->m_len;
217 /* SHOULD COPY OUT A CHAIN HERE */
218 if ((error = copyout(mtod(nam, caddr_t),
219 (caddr_t)SCARG(uap, name), namelen)) == 0)
220 error = copyout((caddr_t)&namelen,
221 (caddr_t)SCARG(uap, anamelen),
222 sizeof (*SCARG(uap, anamelen)));
224 m_freem(nam);
225 splx(s);
226 return (error);
229 /* ARGSUSED */
231 sys_connect(p, v, retval)
232 struct proc *p;
233 void *v;
234 register_t *retval;
236 register struct sys_connect_args /* {
237 syscallarg(int) s;
238 syscallarg(struct sockaddr *) name;
239 syscallarg(socklen_t) namelen;
240 } */ *uap = v;
241 struct file *fp;
242 register struct socket *so;
243 struct mbuf *nam;
244 int error, s;
246 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
247 return (error);
248 so = (struct socket *)fp->f_data;
249 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
250 return (EALREADY);
251 error = sockargs(&nam, (caddr_t)SCARG(uap, name), SCARG(uap, namelen),
252 MT_SONAME);
253 if (error)
254 return (error);
255 error = soconnect(so, nam);
256 if (error)
257 goto bad;
258 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
259 m_freem(nam);
260 return (EINPROGRESS);
262 s = splsoftnet();
263 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
264 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
265 netcon, 0);
266 if (error)
267 break;
269 if (error == 0) {
270 error = so->so_error;
271 so->so_error = 0;
273 splx(s);
274 bad:
275 so->so_state &= ~SS_ISCONNECTING;
276 m_freem(nam);
277 if (error == ERESTART)
278 error = EINTR;
279 return (error);
282 #ifdef NOTUSED_BY_PMON
284 sys_socketpair(p, v, retval)
285 struct proc *p;
286 void *v;
287 register_t *retval;
289 register struct sys_socketpair_args /* {
290 syscallarg(int) domain;
291 syscallarg(int) type;
292 syscallarg(int) protocol;
293 syscallarg(int *) rsv;
294 } */ *uap = v;
295 register struct filedesc *fdp = p->p_fd;
296 struct file *fp1, *fp2;
297 struct socket *so1, *so2;
298 int fd, error, sv[2];
300 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
301 SCARG(uap, protocol));
302 if (error)
303 return (error);
304 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
305 SCARG(uap, protocol));
306 if (error)
307 goto free1;
308 if ((error = falloc(p, &fp1, &fd)) != 0)
309 goto free2;
310 sv[0] = fd;
311 fp1->f_flag = FREAD|FWRITE;
312 fp1->f_type = DTYPE_SOCKET;
313 fp1->f_ops = &socketops;
314 fp1->f_data = (caddr_t)so1;
315 if ((error = falloc(p, &fp2, &fd)) != 0)
316 goto free3;
317 fp2->f_flag = FREAD|FWRITE;
318 fp2->f_type = DTYPE_SOCKET;
319 fp2->f_ops = &socketops;
320 fp2->f_data = (caddr_t)so2;
321 sv[1] = fd;
322 if ((error = soconnect2(so1, so2)) != 0)
323 goto free4;
324 if (SCARG(uap, type) == SOCK_DGRAM) {
326 * Datagram socket connection is asymmetric.
328 if ((error = soconnect2(so2, so1)) != 0)
329 goto free4;
331 error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
332 2 * sizeof (int));
333 if (error == 0)
334 return (error);
335 free4:
336 ffree(fp2);
337 fdremove(fdp, sv[1]);
338 free3:
339 ffree(fp1);
340 fdremove(fdp, sv[0]);
341 free2:
342 (void)soclose(so2);
343 free1:
344 (void)soclose(so1);
345 return (error);
347 #endif /* NOTUSED_BU_PMON */
350 sys_sendto(p, v, retval)
351 struct proc *p;
352 void *v;
353 register_t *retval;
355 register struct sys_sendto_args /* {
356 syscallarg(int) s;
357 syscallarg(caddr_t) buf;
358 syscallarg(size_t) len;
359 syscallarg(int) flags;
360 syscallarg(struct sockaddr *) to;
361 syscallarg(socklen_t) tolen;
362 } */ *uap = v;
363 struct msghdr msg;
364 struct iovec aiov;
366 msg.msg_name = (caddr_t)SCARG(uap, to);
367 msg.msg_namelen = SCARG(uap, tolen);
368 msg.msg_iov = &aiov;
369 msg.msg_iovlen = 1;
370 msg.msg_control = 0;
371 #ifdef COMPAT_OLDSOCK
372 msg.msg_flags = 0;
373 #endif
374 aiov.iov_base = (char *)SCARG(uap, buf);
375 aiov.iov_len = SCARG(uap, len);
376 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
380 sys_sendmsg(p, v, retval)
381 struct proc *p;
382 void *v;
383 register_t *retval;
385 register struct sys_sendmsg_args /* {
386 syscallarg(int) s;
387 syscallarg(caddr_t) msg;
388 syscallarg(int) flags;
389 } */ *uap = v;
390 struct msghdr msg;
391 struct iovec aiov[UIO_SMALLIOV], *iov;
392 int error;
394 error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof (msg));
395 if (error)
396 return (error);
397 if (msg.msg_iovlen <= 0 || msg.msg_iovlen > IOV_MAX)
398 return (EMSGSIZE);
399 if (msg.msg_iovlen > UIO_SMALLIOV)
400 MALLOC(iov, struct iovec *,
401 sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
402 else
403 iov = aiov;
404 if (msg.msg_iovlen &&
405 (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
406 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
407 goto done;
408 msg.msg_iov = iov;
409 #ifdef COMPAT_OLDSOCK
410 msg.msg_flags = 0;
411 #endif
412 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
413 done:
414 if (iov != aiov)
415 FREE(iov, M_IOV);
416 return (error);
420 sendit(p, s, mp, flags, retsize)
421 register struct proc *p;
422 int s;
423 register struct msghdr *mp;
424 int flags;
425 register_t *retsize;
427 struct file *fp;
428 struct uio auio;
429 register struct iovec *iov;
430 register int i;
431 struct mbuf *to, *control;
432 int len, error;
433 #ifdef KTRACE
434 struct iovec *ktriov = NULL;
435 #endif
437 if ((error = getsock(p->p_fd, s, &fp)) != 0)
438 return (error);
439 auio.uio_iov = mp->msg_iov;
440 auio.uio_iovcnt = mp->msg_iovlen;
441 auio.uio_segflg = UIO_USERSPACE;
442 auio.uio_rw = UIO_WRITE;
443 auio.uio_procp = p;
444 auio.uio_offset = 0; /* XXX */
445 auio.uio_resid = 0;
446 iov = mp->msg_iov;
447 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
448 /* Don't allow sum > SSIZE_MAX */
449 if (iov->iov_len > SSIZE_MAX ||
450 (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
451 return (EINVAL);
453 if (mp->msg_name) {
454 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
455 MT_SONAME);
456 if (error)
457 return (error);
458 } else
459 to = 0;
460 if (mp->msg_control) {
461 if (mp->msg_controllen < sizeof(struct cmsghdr)
462 #ifdef COMPAT_OLDSOCK
463 && mp->msg_flags != MSG_COMPAT
464 #endif
466 error = EINVAL;
467 goto bad;
469 error = sockargs(&control, mp->msg_control,
470 mp->msg_controllen, MT_CONTROL);
471 if (error)
472 goto bad;
473 #ifdef COMPAT_OLDSOCK
474 if (mp->msg_flags == MSG_COMPAT) {
475 register struct cmsghdr *cm;
477 M_PREPEND(control, sizeof(*cm), M_WAIT);
478 if (control == 0) {
479 error = ENOBUFS;
480 goto bad;
481 } else {
482 cm = mtod(control, struct cmsghdr *);
483 cm->cmsg_len = control->m_len;
484 cm->cmsg_level = SOL_SOCKET;
485 cm->cmsg_type = SCM_RIGHTS;
488 #endif
489 } else
490 control = 0;
491 #ifdef KTRACE
492 if (KTRPOINT(p, KTR_GENIO)) {
493 int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
495 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
496 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
498 #endif
499 len = auio.uio_resid;
500 error = sosend((struct socket *)fp->f_data, to, &auio,
501 NULL, control, flags);
502 if (error) {
503 if (auio.uio_resid != len && (error == ERESTART ||
504 error == EINTR || error == EWOULDBLOCK))
505 error = 0;
506 if (error == EPIPE)
507 psignal(p, SIGPIPE);
509 if (error == 0)
510 *retsize = len - auio.uio_resid;
511 #ifdef KTRACE
512 if (ktriov != NULL) {
513 if (error == 0)
514 ktrgenio(p->p_tracep, s, UIO_WRITE,
515 ktriov, *retsize, error);
516 FREE(ktriov, M_TEMP);
518 #endif
519 bad:
520 if (to)
521 m_freem(to);
522 return (error);
526 sys_recvfrom(p, v, retval)
527 struct proc *p;
528 void *v;
529 register_t *retval;
531 register struct sys_recvfrom_args /* {
532 syscallarg(int) s;
533 syscallarg(caddr_t) buf;
534 syscallarg(size_t) len;
535 syscallarg(int) flags;
536 syscallarg(struct sockaddr *) from;
537 syscallarg(socklen_t *) fromlenaddr;
538 } */ *uap = v;
539 struct msghdr msg;
540 struct iovec aiov;
541 int error;
543 if (SCARG(uap, fromlenaddr)) {
544 error = copyin((caddr_t)SCARG(uap, fromlenaddr),
545 (caddr_t)&msg.msg_namelen,
546 sizeof (msg.msg_namelen));
547 if (error)
548 return (error);
549 } else
550 msg.msg_namelen = 0;
551 msg.msg_name = (caddr_t)SCARG(uap, from);
552 msg.msg_iov = &aiov;
553 msg.msg_iovlen = 1;
554 aiov.iov_base = SCARG(uap, buf);
555 aiov.iov_len = SCARG(uap, len);
556 msg.msg_control = 0;
557 msg.msg_flags = SCARG(uap, flags);
558 return (recvit(p, SCARG(uap, s), &msg,
559 (caddr_t)SCARG(uap, fromlenaddr), retval));
563 sys_recvmsg(p, v, retval)
564 struct proc *p;
565 void *v;
566 register_t *retval;
568 register struct sys_recvmsg_args /* {
569 syscallarg(int) s;
570 syscallarg(struct msghdr *) msg;
571 syscallarg(int) flags;
572 } */ *uap = v;
573 struct msghdr msg;
574 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
575 register int error;
577 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
578 sizeof (msg));
579 if (error)
580 return (error);
581 if (msg.msg_iovlen <= 0 || msg.msg_iovlen > IOV_MAX)
582 return (EMSGSIZE);
583 if (msg.msg_iovlen > UIO_SMALLIOV)
584 MALLOC(iov, struct iovec *,
585 sizeof(struct iovec) * msg.msg_iovlen, M_IOV, M_WAITOK);
586 else
587 iov = aiov;
588 #ifdef COMPAT_OLDSOCK
589 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
590 #else
591 msg.msg_flags = SCARG(uap, flags);
592 #endif
593 uiov = msg.msg_iov;
594 msg.msg_iov = iov;
595 error = copyin((caddr_t)uiov, (caddr_t)iov,
596 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
597 if (error)
598 goto done;
599 if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
600 msg.msg_iov = uiov;
601 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
602 sizeof(msg));
604 done:
605 if (iov != aiov)
606 FREE(iov, M_IOV);
607 return (error);
611 recvit(p, s, mp, namelenp, retsize)
612 register struct proc *p;
613 int s;
614 register struct msghdr *mp;
615 caddr_t namelenp;
616 register_t *retsize;
618 struct file *fp;
619 struct uio auio;
620 register struct iovec *iov;
621 register int i;
622 size_t len;
623 int error;
624 struct mbuf *from = 0, *control = 0;
625 #ifdef KTRACE
626 struct iovec *ktriov = NULL;
627 #endif
629 if ((error = getsock(p->p_fd, s, &fp)) != 0)
630 return (error);
631 auio.uio_iov = mp->msg_iov;
632 auio.uio_iovcnt = mp->msg_iovlen;
633 auio.uio_segflg = UIO_USERSPACE;
634 auio.uio_rw = UIO_READ;
635 auio.uio_procp = p;
636 auio.uio_offset = 0; /* XXX */
637 auio.uio_resid = 0;
638 iov = mp->msg_iov;
639 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
640 /* Don't allow sum > SSIZE_MAX */
641 if (iov->iov_len > SSIZE_MAX ||
642 (auio.uio_resid += iov->iov_len) > SSIZE_MAX)
643 return (EINVAL);
645 #ifdef KTRACE
646 if (KTRPOINT(p, KTR_GENIO)) {
647 int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
649 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
650 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
652 #endif
653 len = auio.uio_resid;
654 error = soreceive((struct socket *)fp->f_data, &from, &auio,
655 NULL, mp->msg_control ? &control : NULL,
656 &mp->msg_flags);
657 if (error) {
658 if (auio.uio_resid != len && (error == ERESTART ||
659 error == EINTR || error == EWOULDBLOCK))
660 error = 0;
662 #ifdef KTRACE
663 if (ktriov != NULL) {
664 if (error == 0)
665 ktrgenio(p->p_tracep, s, UIO_READ,
666 ktriov, len - auio.uio_resid, error);
667 FREE(ktriov, M_TEMP);
669 #endif
670 if (error)
671 goto out;
672 *retsize = len - auio.uio_resid;
673 if (mp->msg_name) {
674 len = mp->msg_namelen;
675 if (len <= 0 || from == 0)
676 len = 0;
677 else {
678 /* save sa_len before it is destroyed by MSG_COMPAT */
679 if (len > from->m_len)
680 len = from->m_len;
681 /* else if len < from->m_len ??? */
682 #ifdef COMPAT_OLDSOCK
683 if (mp->msg_flags & MSG_COMPAT)
684 mtod(from, struct osockaddr *)->sa_family =
685 mtod(from, struct sockaddr *)->sa_family;
686 #endif
687 error = copyout(mtod(from, caddr_t),
688 (caddr_t)mp->msg_name, (unsigned)len);
689 if (error)
690 goto out;
692 mp->msg_namelen = len;
693 if (namelenp &&
694 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
695 #ifdef COMPAT_OLDSOCK
696 if (mp->msg_flags & MSG_COMPAT)
697 error = 0; /* old recvfrom didn't check */
698 else
699 #endif
700 goto out;
703 if (mp->msg_control) {
704 #ifdef COMPAT_OLDSOCK
706 * We assume that old recvmsg calls won't receive access
707 * rights and other control info, esp. as control info
708 * is always optional and those options didn't exist in 4.3.
709 * If we receive rights, trim the cmsghdr; anything else
710 * is tossed.
712 if (control && mp->msg_flags & MSG_COMPAT) {
713 if (mtod(control, struct cmsghdr *)->cmsg_level !=
714 SOL_SOCKET ||
715 mtod(control, struct cmsghdr *)->cmsg_type !=
716 SCM_RIGHTS) {
717 mp->msg_controllen = 0;
718 goto out;
720 control->m_len -= sizeof (struct cmsghdr);
721 control->m_data += sizeof (struct cmsghdr);
723 #endif
724 len = mp->msg_controllen;
725 if (len <= 0 || control == 0)
726 len = 0;
727 else {
728 if (len >= control->m_len)
729 len = control->m_len;
730 else
731 mp->msg_flags |= MSG_CTRUNC;
732 error = copyout((caddr_t)mtod(control, caddr_t),
733 (caddr_t)mp->msg_control, (unsigned)len);
735 mp->msg_controllen = len;
737 out:
738 if (from)
739 m_freem(from);
740 if (control)
741 m_freem(control);
742 return (error);
745 /* ARGSUSED */
747 sys_shutdown(p, v, retval)
748 struct proc *p;
749 void *v;
750 register_t *retval;
752 register struct sys_shutdown_args /* {
753 syscallarg(int) s;
754 syscallarg(int) how;
755 } */ *uap = v;
756 struct file *fp;
757 int error;
759 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
760 return (error);
761 return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how)));
764 /* ARGSUSED */
766 sys_setsockopt(p, v, retval)
767 struct proc *p;
768 void *v;
769 register_t *retval;
771 register struct sys_setsockopt_args /* {
772 syscallarg(int) s;
773 syscallarg(int) level;
774 syscallarg(int) name;
775 syscallarg(caddr_t) val;
776 syscallarg(socklen_t) valsize;
777 } */ *uap = v;
778 struct file *fp;
779 struct mbuf *m = NULL;
780 int error;
782 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
783 return (error);
784 if (SCARG(uap, valsize) > MLEN)
785 return (EINVAL);
786 if (SCARG(uap, val)) {
787 m = m_get(M_WAIT, MT_SOOPTS);
788 if (m == NULL)
789 return (ENOBUFS);
790 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
791 SCARG(uap, valsize));
792 if (error) {
793 (void) m_free(m);
794 return (error);
796 m->m_len = SCARG(uap, valsize);
798 return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
799 SCARG(uap, name), m));
802 /* ARGSUSED */
804 sys_getsockopt(p, v, retval)
805 struct proc *p;
806 void *v;
807 register_t *retval;
809 register struct sys_getsockopt_args /* {
810 syscallarg(int) s;
811 syscallarg(int) level;
812 syscallarg(int) name;
813 syscallarg(caddr_t) val;
814 syscallarg(socklen_t *) avalsize;
815 } */ *uap = v;
816 struct file *fp;
817 struct mbuf *m = NULL;
818 socklen_t valsize;
819 int error;
821 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
822 return (error);
823 if (SCARG(uap, val)) {
824 error = copyin((caddr_t)SCARG(uap, avalsize),
825 (caddr_t)&valsize, sizeof (valsize));
826 if (error)
827 return (error);
828 } else
829 valsize = 0;
830 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
831 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
832 m != NULL) {
833 if (valsize > m->m_len)
834 valsize = m->m_len;
835 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize);
836 if (error == 0)
837 error = copyout((caddr_t)&valsize,
838 (caddr_t)SCARG(uap, avalsize), sizeof (valsize));
840 if (m != NULL)
841 (void) m_free(m);
842 return (error);
845 #ifdef NOTUSED_BY_PMON
847 sys_pipe(p, v, retval)
848 struct proc *p;
849 void *v;
850 register_t *retval;
852 register struct sys_pipe_args /* {
853 syscallarg(int *) fdp;
854 } */ *uap = v;
855 int error, fds[2];
856 register_t rval[2];
858 if ((error = sys_opipe(p, v, rval)) == -1)
859 return (error);
861 fds[0] = rval[0];
862 fds[1] = rval[1];
863 error = copyout((caddr_t)fds, (caddr_t)SCARG(uap, fdp),
864 2 * sizeof (int));
865 if (error) {
866 fdrelease(p, retval[0]);
867 fdrelease(p, retval[1]);
869 return (error);
872 #ifdef OLD_PIPE
874 /* ARGSUSED */
876 sys_opipe(p, v, retval)
877 struct proc *p;
878 void *v;
879 register_t *retval;
881 register struct filedesc *fdp = p->p_fd;
882 struct file *rf, *wf;
883 struct socket *rso, *wso;
884 int fd, error;
886 if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0)
887 return (error);
888 if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0)
889 goto free1;
890 if ((error = falloc(p, &rf, &fd)) != 0)
891 goto free2;
892 retval[0] = fd;
893 rf->f_flag = FREAD;
894 rf->f_type = DTYPE_SOCKET;
895 rf->f_ops = &socketops;
896 rf->f_data = (caddr_t)rso;
897 if ((error = falloc(p, &wf, &fd)) != 0)
898 goto free3;
899 wf->f_flag = FWRITE;
900 wf->f_type = DTYPE_SOCKET;
901 wf->f_ops = &socketops;
902 wf->f_data = (caddr_t)wso;
903 retval[1] = fd;
904 if ((error = unp_connect2(wso, rso)) != 0)
905 goto free4;
906 return (0);
907 free4:
908 ffree(wf);
909 fdremove(fdp, retval[1]);
910 free3:
911 ffree(rf);
912 fdremove(fdp, retval[0]);
913 free2:
914 (void)soclose(wso);
915 free1:
916 (void)soclose(rso);
917 return (error);
919 #endif
920 #endif /* NOTUSED_BY_PMON */
923 * Get socket name.
925 /* ARGSUSED */
927 sys_getsockname(p, v, retval)
928 struct proc *p;
929 void *v;
930 register_t *retval;
932 register struct sys_getsockname_args /* {
933 syscallarg(int) fdes;
934 syscallarg(caddr_t) asa;
935 syscallarg(socklen_t *) alen;
936 } */ *uap = v;
937 struct file *fp;
938 register struct socket *so;
939 struct mbuf *m;
940 socklen_t len;
941 int error;
943 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
944 return (error);
945 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len));
946 if (error)
947 return (error);
948 so = (struct socket *)fp->f_data;
949 m = m_getclr(M_WAIT, MT_SONAME);
950 if (m == NULL)
951 return (ENOBUFS);
952 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
953 if (error)
954 goto bad;
955 if (len > m->m_len)
956 len = m->m_len;
957 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
958 if (error == 0)
959 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
960 sizeof (len));
961 bad:
962 m_freem(m);
963 return (error);
967 * Get name of peer for connected socket.
969 /* ARGSUSED */
971 sys_getpeername(p, v, retval)
972 struct proc *p;
973 void *v;
974 register_t *retval;
976 register struct sys_getpeername_args /* {
977 syscallarg(int) fdes;
978 syscallarg(caddr_t) asa;
979 syscallarg(socklen_t *) alen;
980 } */ *uap = v;
981 struct file *fp;
982 register struct socket *so;
983 struct mbuf *m;
984 socklen_t len;
985 int error;
987 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
988 return (error);
989 so = (struct socket *)fp->f_data;
990 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
991 return (ENOTCONN);
992 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len));
993 if (error)
994 return (error);
995 m = m_getclr(M_WAIT, MT_SONAME);
996 if (m == NULL)
997 return (ENOBUFS);
998 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
999 if (error)
1000 goto bad;
1001 if (len > m->m_len)
1002 len = m->m_len;
1003 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1004 if (error == 0)
1005 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
1006 sizeof (len));
1007 bad:
1008 m_freem(m);
1009 return (error);
1013 sockargs(mp, buf, buflen, type)
1014 struct mbuf **mp;
1015 caddr_t buf;
1016 socklen_t buflen;
1017 int type;
1019 register struct sockaddr *sa;
1020 register struct mbuf *m;
1021 int error;
1023 if (buflen > MLEN) {
1024 #ifdef COMPAT_OLDSOCK
1025 if (type == MT_SONAME && buflen <= 112)
1026 buflen = MLEN; /* unix domain compat. hack */
1027 else
1028 #endif
1029 return (EINVAL);
1031 m = m_get(M_WAIT, type);
1032 if (m == NULL)
1033 return (ENOBUFS);
1034 m->m_len = buflen;
1035 error = copyin(buf, mtod(m, caddr_t), buflen);
1036 if (error) {
1037 (void) m_free(m);
1038 return (error);
1040 *mp = m;
1041 if (type == MT_SONAME) {
1042 sa = mtod(m, struct sockaddr *);
1044 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1045 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1046 sa->sa_family = sa->sa_len;
1047 #endif
1048 sa->sa_len = buflen;
1050 return (0);
1054 getsock(fdp, fdes, fpp)
1055 struct filedesc *fdp;
1056 int fdes;
1057 struct file **fpp;
1059 register struct file *fp;
1061 if ((unsigned)fdes >= fdp->fd_nfiles ||
1062 (fp = fdp->fd_ofiles[fdes]) == NULL)
1063 return (EBADF);
1064 if (fp->f_type != DTYPE_SOCKET)
1065 return (ENOTSOCK);
1066 *fpp = fp;
1067 return (0);