2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
5 * Copyright (C) 2005 - 2007 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24 * Mach Operating System
25 * Copyright (c) 1992 Carnegie Mellon University
26 * All Rights Reserved.
28 * Permission to use, copy, modify and distribute this software and its
29 * documentation is hereby granted, provided that both the copyright
30 * notice and this permission notice appear in all copies of the
31 * software, derivative works or modified versions, and any portions
32 * thereof, and that both notices appear in supporting documentation.
34 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
35 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
36 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
38 * Carnegie Mellon requests users of this software to return to
40 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
41 * School of Computer Science
42 * Carnegie Mellon University
43 * Pittsburgh PA 15213-3890
45 * any improvements or extensions that they make and grant Carnegie Mellon
46 * the rights to redistribute these changes.
50 * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
51 * All rights reserved.
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
56 * 1. Redistributions of source code must retain the above copyright
57 * notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 * notice, this list of conditions and the following disclaimer in the
60 * documentation and/or other materials provided with the distribution.
61 * 3. All advertising materials mentioning features or use of this software
62 * must display the following acknowledgement:
63 * This product includes software developed by the University of
64 * California, Berkeley and its contributors.
65 * 4. Neither the name of the University nor the names of its contributors
66 * may be used to endorse or promote products derived from this software
67 * without specific prior written permission.
69 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
81 * @(#)uipc_socket.c 7.28 (Berkeley) 5/4/91
86 #include <sys/param.h>
87 #include <sys/systm.h>
88 #include <sys/malloc.h>
90 #include <sys/domain.h>
91 #include <sys/kernel.h>
92 #include <sys/protosw.h>
93 #include <sys/socket.h>
94 #include <sys/socketvar.h>
96 #include <sys/synch.h>
97 #include <api/amiga_api.h>
99 #include <kern/amiga_includes.h>
101 #include <kern/uipc_socket_protos.h>
102 #include <kern/uipc_socket2_protos.h>
103 #include <kern/uipc_domain_protos.h>
104 #include <kern/amiga_select_protos.h>
109 * Socket operation routines.
110 * These routines are called by the routines in
111 * sys_socket.c or from a system process, and
112 * implement the semantics of socket operations by
113 * switching out to the protocol specific routines.
116 socreate(dom
, aso
, type
, proto
)
123 struct proc
*p
= (struct proc
*)cthread_data(cthread_self());
125 register struct protosw
*prp
;
126 register struct socket
*so
;
130 prp
= pffindproto(dom
, proto
, type
);
132 prp
= pffindtype(dom
, type
);
134 return (EPROTONOSUPPORT
);
135 if (prp
->pr_type
!= type
)
137 MALLOC(so
, struct socket
*, sizeof(*so
), M_SOCKET
, M_WAIT
);
138 aligned_bzero_const((caddr_t
)so
, sizeof(*so
));
141 if (p
->p_ucred
->cr_uid
== 0)
143 so
->so_state
= SS_PRIV
; /* all sockets have the force now */
146 (*prp
->pr_usrreq
)(so
, PRU_ATTACH
,
147 (struct mbuf
*)0, (struct mbuf
*)(long)proto
, (struct mbuf
*)0);
149 so
->so_state
|= SS_NOFDREF
;
166 (*so
->so_proto
->pr_usrreq
)(so
, PRU_BIND
,
167 (struct mbuf
*)0, nam
, (struct mbuf
*)0);
173 solisten(so
, backlog
)
174 register struct socket
*so
;
177 spl_t s
= splnet(), error
;
180 (*so
->so_proto
->pr_usrreq
)(so
, PRU_LISTEN
,
181 (struct mbuf
*)0, (struct mbuf
*)0, (struct mbuf
*)0);
187 so
->so_options
|= SO_ACCEPTCONN
;
190 so
->so_qlimit
= MIN(backlog
, SOMAXCONN
);
197 register struct socket
*so
;
200 if (so
->so_pcb
|| (so
->so_state
& SS_NOFDREF
) == 0)
203 if (!soqremque(so
, 0) && !soqremque(so
, 1))
207 sbrelease(&so
->so_snd
);
213 * Close a socket on last file table reference removal.
214 * Initiate disconnect if connected.
215 * Free socket when disconnect complete.
219 register struct socket
*so
;
221 spl_t s
= splnet(); /* conservative */
223 struct SocketBase
*socketBase
;
224 struct timeval
*timeo
;
226 if (so
->so_options
& SO_ACCEPTCONN
) {
228 (void) soabort(so
->so_q0
);
230 (void) soabort(so
->so_q
);
234 if (so
->so_state
& SS_ISCONNECTED
) {
235 if ((so
->so_state
& SS_ISDISCONNECTING
) == 0) {
236 error
= sodisconnect(so
);
240 if (so
->so_options
& SO_LINGER
) {
241 if ((so
->so_state
& SS_ISDISCONNECTING
) &&
242 (so
->so_state
& SS_NBIO
))
245 * Find socket base for the tsleep()
247 if ((socketBase
= FindSocketBase(FindTask(NULL
)))
249 goto drop
; /* couldn't find */
250 timeo
= (so
->so_linger
.tv_sec
251 || so
->so_linger
.tv_usec
) ?
252 &so
->so_linger
: NULL
;
253 while (so
->so_state
& SS_ISCONNECTED
)
254 if (error
= tsleep(socketBase
,
255 (caddr_t
)&so
->so_timeo
,
263 (*so
->so_proto
->pr_usrreq
)(so
, PRU_DETACH
,
264 (struct mbuf
*)0, (struct mbuf
*)0, (struct mbuf
*)0);
269 if (so
->so_state
& SS_NOFDREF
)
270 panic("soclose: NOFDREF");
271 so
->so_state
|= SS_NOFDREF
;
278 * Must be called at splnet...
286 (*so
->so_proto
->pr_usrreq
)(so
, PRU_ABORT
,
287 (struct mbuf
*)0, (struct mbuf
*)0, (struct mbuf
*)0));
292 register struct socket
*so
;
298 if ((so
->so_state
& SS_NOFDREF
) == 0)
299 panic("soaccept: !NOFDREF");
300 so
->so_state
&= ~SS_NOFDREF
;
301 error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_ACCEPT
,
302 (struct mbuf
*)0, nam
, (struct mbuf
*)0);
309 register struct socket
*so
;
315 if (so
->so_options
& SO_ACCEPTCONN
)
319 * If protocol is connection-based, can only connect once.
320 * Otherwise, if connected, try to disconnect first.
321 * This allows user to disconnect by connecting to, e.g.,
324 if (so
->so_state
& (SS_ISCONNECTED
|SS_ISCONNECTING
) &&
325 ((so
->so_proto
->pr_flags
& PR_CONNREQUIRED
) ||
326 (error
= sodisconnect(so
))))
329 error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_CONNECT
,
330 (struct mbuf
*)0, nam
, (struct mbuf
*)0);
337 register struct socket
*so1
;
343 error
= (*so1
->so_proto
->pr_usrreq
)(so1
, PRU_CONNECT2
,
344 (struct mbuf
*)0, (struct mbuf
*)so2
, (struct mbuf
*)0);
352 register struct socket
*so
;
357 if ((so
->so_state
& SS_ISCONNECTED
) == 0) {
361 if (so
->so_state
& SS_ISDISCONNECTING
) {
365 error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_DISCONNECT
,
366 (struct mbuf
*)0, (struct mbuf
*)0, (struct mbuf
*)0);
374 * uioread() replaces uiomove() in sosend
377 static inline void uioread(caddr_t cp
, int n
, struct uio
*uio
)
382 while (n
> 0 && uio
->uio_resid
) {
393 bcopy(iov
->iov_base
, cp
, cnt
); /* wrong direction //pp */
395 iov
->iov_base
+= cnt
;
397 uio
->uio_resid
-= cnt
;
408 * If send must go all at once and message is larger than
409 * send buffering, then hard error.
410 * Lock against other senders.
411 * If must go all at once and not enough room now, then
412 * inform user that this would block and do nothing.
413 * Otherwise, if nonblocking, send as much as possible.
414 * The data to be sent is described by "uio" if nonzero,
415 * otherwise by the mbuf chain "top" (which must be null
416 * if uio is not). Data provided in mbuf chain must be small
417 * enough to send all at once.
419 * Returns nonzero on error, timeout or signal; callers
420 * must check for short counts if EINTR/ERESTART are returned.
421 * Data and control buffers are freed on return.
424 sosend(so
, addr
, uio
, top
, control
, flags
)
425 register struct socket
*so
;
429 struct mbuf
*control
;
432 #ifndef AMITCP /* proc not defined */
433 struct proc
*p
= (struct proc
*)cthread_data(cthread_self());
436 register struct mbuf
*m
;
437 register long space
, len
, resid
;
438 int clen
= 0, error
, dontroute
, mlen
;
440 int atomic
= sosendallatonce(so
) || top
;
443 resid
= uio
->uio_resid
;
445 resid
= top
->m_pkthdr
.len
;
448 (flags
& MSG_DONTROUTE
) && (so
->so_options
& SO_DONTROUTE
) == 0 &&
449 (so
->so_proto
->pr_flags
& PR_ATOMIC
);
451 p
->p_stats
->p_ru
.ru_msgsnd
++;
454 clen
= control
->m_len
;
455 #define snderr(errno) { error = errno; splx(s); goto release; }
458 if (error
= sblock(&so
->so_snd
, uio
->uio_procp
))
462 if (so
->so_state
& SS_CANTSENDMORE
)
465 snderr(so
->so_error
);
466 if ((so
->so_state
& SS_ISCONNECTED
) == 0) {
467 if (so
->so_proto
->pr_flags
& PR_CONNREQUIRED
) {
468 if ((so
->so_state
& SS_ISCONFIRMING
) == 0 &&
469 !(resid
== 0 && clen
!= 0))
471 } else if (addr
== 0)
472 snderr(EDESTADDRREQ
);
474 space
= sbspace(&so
->so_snd
);
477 if (space
< resid
+ clen
&&
478 (atomic
|| space
< so
->so_snd
.sb_lowat
|| space
< clen
)) {
479 if ((atomic
&& resid
> so
->so_snd
.sb_hiwat
) ||
480 clen
> so
->so_snd
.sb_hiwat
)
482 if (so
->so_state
& SS_NBIO
)
484 sbunlock(&so
->so_snd
);
485 error
= sbwait(&so
->so_snd
, uio
->uio_procp
);
497 * Data is prepackaged in "top".
502 top
->m_flags
|= M_EOR
;
506 MGETHDR(m
, M_WAIT
, MT_DATA
);
509 m
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
511 MGET(m
, M_WAIT
, MT_DATA
);
514 if (resid
>= mlen
&& space
>= mbconf
.mclbytes
) {
516 if ((m
->m_flags
& M_EXT
) == 0)
518 mlen
= mbconf
.mclbytes
;
520 len
= MIN(mbconf
.mclbytes
, resid
);
523 len
= MIN(mbconf
.mclbytes
- max_hdr
, resid
);
524 m
->m_data
+= max_hdr
;
526 len
= MIN(mbconf
.mclbytes
, resid
);
528 space
-= mbconf
.mclbytes
;
532 len
= MIN(MIN(mlen
, resid
), space
);
535 * For datagram protocols, leave room
536 * for protocol headers in first mbuf.
538 if (atomic
&& top
== 0 && len
< mlen
)
541 uioread(mtod(m
, caddr_t
), (int)len
, uio
);
542 resid
= uio
->uio_resid
;
545 top
->m_pkthdr
.len
+= len
;
552 top
->m_flags
|= M_EOR
;
557 #if defined(AMITCP) && 0
558 /* all the data in 1 mbuf chain */
561 while (space
> 0 && atomic
);
564 so
->so_options
|= SO_DONTROUTE
;
565 s
= splnet(); /* XXX */
566 error
= (*so
->so_proto
->pr_usrreq
)(so
,
567 (flags
& MSG_OOB
) ? PRU_SENDOOB
: //PRU_SEND,
569 * If the user set MSG_EOF, the protocol
570 * understands this flag and nothing left to
571 * send then use PRU_SEND_EOF instead of PRU_SEND.
573 ((flags
& MSG_EOF
) &&
574 (so
->so_proto
->pr_flags
& PR_IMPLOPCL
) &&
576 PRU_SEND_EOF
: PRU_SEND
,
580 so
->so_options
&= ~SO_DONTROUTE
;
587 } while (resid
&& space
> 0);
591 sbunlock(&so
->so_snd
);
603 * uiowrite() replaces uiomove() in soreceive
606 static inline void uiowrite(caddr_t cp
, int n
, struct uio
*uio
)
611 while (n
> 0 && uio
->uio_resid
) {
622 bcopy(cp
, iov
->iov_base
, cnt
);
624 iov
->iov_base
+= cnt
;
626 uio
->uio_resid
-= cnt
;
634 * Implement receive operations on a socket.
635 * We depend on the way that records are added to the sockbuf
636 * by sbappend*. In particular, each record (mbufs linked through m_next)
637 * must begin with an address if the protocol so specifies,
638 * followed by an optional mbuf or mbufs containing ancillary data,
639 * and then zero or more mbufs of data.
640 * In order to avoid blocking network interrupts for the entire time here,
641 * we splx() while doing the actual copy to user space.
642 * Although the sockbuf is locked, new data may still be appended,
643 * and thus we must maintain consistency of the sockbuf during that time.
645 * The caller may receive the data as a single mbuf chain by supplying
646 * an mbuf **mp0 for use in returning the chain. The uio is then used
647 * only for the count in uio_resid.
650 soreceive(so
, paddr
, uio
, mp0
, controlp
, flagsp
)
651 register struct socket
*so
;
655 struct mbuf
**controlp
;
659 struct proc
*p
= (struct proc
*)cthread_data(cthread_self());
661 register struct mbuf
*m
, **mp
;
662 register int flags
, len
, error
, offset
;
664 struct protosw
*pr
= so
->so_proto
;
665 struct mbuf
*nextrecord
;
674 flags
= *flagsp
&~ MSG_EOR
;
677 if (flags
& MSG_OOB
) {
678 m
= m_get(M_WAIT
, MT_DATA
);
679 error
= (*pr
->pr_usrreq
)(so
, PRU_RCVOOB
,
680 m
, (struct mbuf
*)(long)(flags
& MSG_PEEK
), (struct mbuf
*)0);
685 uiowrite(mtod(m
, caddr_t
),
686 (int) MIN(uio
->uio_resid
, m
->m_len
), uio
);
688 } while (uio
->uio_resid
&& error
== 0 && m
);
696 *mp
= (struct mbuf
*)0;
698 if (so
->so_state
& SS_ISCONFIRMING
&& uio
->uio_resid
)
699 (*pr
->pr_usrreq
)(so
, PRU_RCVD
, (struct mbuf
*)0,
700 (struct mbuf
*)0, (struct mbuf
*)0);
704 if (error
= sblock(&so
->so_rcv
, uio
->uio_procp
))
708 m
= so
->so_rcv
.sb_mb
;
710 * If we have less data than requested, block awaiting more
711 * (subject to any timeout) if:
712 * 1. the current count is less than the low water mark, or
713 * 2. MSG_WAITALL is set, and it is possible to do the entire
714 * receive operation at once if we block (resid <= hiwat).
715 * If MSG_WAITALL is set but resid is larger than the receive buffer,
716 * we have to do the receive in sections, and thus risk returning
717 * a short count if a timeout or signal occurs after we start.
720 while (m
== 0 || (so
->so_rcv
.sb_cc
< uio
->uio_resid
&&
721 (so
->so_rcv
.sb_cc
< so
->so_rcv
.sb_lowat
||
722 ((flags
& MSG_WAITALL
)
723 && uio
->uio_resid
<= so
->so_rcv
.sb_hiwat
)) &&
724 m
->m_nextpkt
== 0)) {
726 if (m
== 0 && so
->so_rcv
.sb_cc
)
732 error
= so
->so_error
;
733 if ((flags
& MSG_PEEK
) == 0)
737 if (so
->so_state
& SS_CANTRCVMORE
) {
743 for (; m
; m
= m
->m_next
)
744 if (m
->m_type
== MT_OOBDATA
746 || (m
->m_flags
& M_EOR
)
749 m
= so
->so_rcv
.sb_mb
;
752 if ((so
->so_state
& (SS_ISCONNECTED
|SS_ISCONNECTING
)) == 0 &&
753 (so
->so_proto
->pr_flags
& PR_CONNREQUIRED
)) {
758 if (uio
->uio_resid
== 0)
761 if (so
->so_state
& SS_NBIO
) {
765 sbunlock(&so
->so_rcv
);
766 error
= sbwait(&so
->so_rcv
, uio
->uio_procp
);
774 p
->p_stats
->p_ru
.ru_msgrcv
++;
776 nextrecord
= m
->m_nextpkt
;
777 if (pr
->pr_flags
& PR_ADDR
) {
779 if (m
->m_type
!= MT_SONAME
)
782 if (flags
& MSG_PEEK
) {
784 *paddr
= m_copy(m
, 0, m
->m_len
);
787 sbfree(&so
->so_rcv
, m
);
790 so
->so_rcv
.sb_mb
= m
->m_next
;
792 m
= so
->so_rcv
.sb_mb
;
794 MFREE(m
, so
->so_rcv
.sb_mb
);
795 m
= so
->so_rcv
.sb_mb
;
799 while (m
&& m
->m_type
== MT_CONTROL
&& error
== 0) {
800 if (flags
& MSG_PEEK
) {
802 *controlp
= m_copy(m
, 0, m
->m_len
);
805 sbfree(&so
->so_rcv
, m
);
807 if (pr
->pr_domain
->dom_externalize
&&
808 mtod(m
, struct cmsghdr
*)->cmsg_type
==
810 error
= (*pr
->pr_domain
->dom_externalize
)(m
);
812 so
->so_rcv
.sb_mb
= m
->m_next
;
814 m
= so
->so_rcv
.sb_mb
;
816 MFREE(m
, so
->so_rcv
.sb_mb
);
817 m
= so
->so_rcv
.sb_mb
;
821 controlp
= &(*controlp
)->m_next
;
824 if ((flags
& MSG_PEEK
) == 0)
825 m
->m_nextpkt
= nextrecord
;
827 if (type
== MT_OOBDATA
)
832 while (m
&& uio
->uio_resid
> 0 && error
== 0) {
833 if (m
->m_type
== MT_OOBDATA
) {
834 if (type
!= MT_OOBDATA
)
836 } else if (type
== MT_OOBDATA
)
839 else if (m
->m_type
!= MT_DATA
&& m
->m_type
!= MT_HEADER
)
842 so
->so_state
&= ~SS_RCVATMARK
;
844 len
= uio
->uio_resid
;
846 if (so
->so_oobmark
&& len
> so
->so_oobmark
- offset
)
847 len
= so
->so_oobmark
- offset
;
848 if (len
> m
->m_len
- moff
)
849 len
= m
->m_len
- moff
;
851 * If mp is set, just pass back the mbufs.
852 * Otherwise copy them out via the uio, then free.
853 * Sockbuf must be consistent here (points to current mbuf,
854 * it points to next record) when we drop priority;
855 * we must note any additions to the sockbuf when we
856 * block interrupts again.
861 uiowrite(mtod(m
, caddr_t
) + moff
, (int)len
, uio
);
864 uio
->uio_resid
-= len
;
866 if (len
== m
->m_len
- moff
) {
868 if (m
->m_flags
& M_EOR
)
871 if (flags
& MSG_PEEK
) {
875 nextrecord
= m
->m_nextpkt
;
876 sbfree(&so
->so_rcv
, m
);
880 so
->so_rcv
.sb_mb
= m
= m
->m_next
;
881 *mp
= (struct mbuf
*)0;
883 MFREE(m
, so
->so_rcv
.sb_mb
);
884 m
= so
->so_rcv
.sb_mb
;
887 m
->m_nextpkt
= nextrecord
;
890 if (flags
& MSG_PEEK
)
894 *mp
= m_copym(m
, 0, len
, M_WAIT
);
897 so
->so_rcv
.sb_cc
-= len
;
900 if (so
->so_oobmark
) {
901 if ((flags
& MSG_PEEK
) == 0) {
902 so
->so_oobmark
-= len
;
903 if (so
->so_oobmark
== 0) {
904 so
->so_state
|= SS_RCVATMARK
;
913 * If the MSG_WAITALL flag is set (for non-atomic socket),
914 * we must not quit until "uio->uio_resid == 0" or an error
915 * termination. If a signal/timeout occurs, return
916 * with a short count but without error.
917 * Keep sockbuf locked against other readers.
919 while (flags
& MSG_WAITALL
&& m
== 0 && uio
->uio_resid
> 0 &&
920 !sosendallatonce(so
)) {
921 if (so
->so_error
|| so
->so_state
& SS_CANTRCVMORE
)
923 error
= sbwait(&so
->so_rcv
, uio
->uio_procp
);
925 sbunlock(&so
->so_rcv
);
929 if (m
= so
->so_rcv
.sb_mb
)
930 nextrecord
= m
->m_nextpkt
;
933 if ((flags
& MSG_PEEK
) == 0) {
935 so
->so_rcv
.sb_mb
= nextrecord
;
936 else if (pr
->pr_flags
& PR_ATOMIC
) {
938 (void) sbdroprecord(&so
->so_rcv
);
940 if (pr
->pr_flags
& PR_WANTRCVD
&& so
->so_pcb
)
941 (*pr
->pr_usrreq
)(so
, PRU_RCVD
, (struct mbuf
*)0,
942 (struct mbuf
*)(long)flags
, /* (struct mbuf *)0, */
943 (struct mbuf
*)0); /* BUG! One extra arg! */
948 sbunlock(&so
->so_rcv
);
955 register struct socket
*so
;
958 register struct protosw
*pr
= so
->so_proto
;
960 how
++; /* now how: 1 - no receives, 2 - no sends, 3 - no either */
964 return ((*pr
->pr_usrreq
)(so
, PRU_SHUTDOWN
, (struct mbuf
*)0,
965 (struct mbuf
*)0, (struct mbuf
*)0));
971 register struct socket
*so
;
973 register struct sockbuf
*sb
= &so
->so_rcv
;
974 register struct protosw
*pr
= so
->so_proto
;
978 sb
->sb_flags
|= SB_NOINTR
;
979 (void) sblock(sb
, NULL
);
984 aligned_bzero_const((caddr_t
)sb
, sizeof (*sb
));
986 if (pr
->pr_flags
& PR_RIGHTS
&& pr
->pr_domain
->dom_dispose
)
987 (*pr
->pr_domain
->dom_dispose
)(asb
.sb_mb
);
992 * in some fields of socket structure previous short fields of ticks are
993 * changed to struct timeval fields. (actually so_linger and sb_timeo)
994 * sosetopt() and sogetopt() does transformations needed for those.
998 sosetopt(so
, level
, optname
, m0
)
999 register struct socket
*so
;
1004 register struct mbuf
*m
= m0
;
1006 #ifdef ENABLE_TTCP_SHUTUP
1007 if ((optname
== TCP_NOPUSH
) && (level
== IPPROTO_TCP
)) {
1008 if (m
== NULL
|| m
->m_len
< sizeof (int))
1011 if (*mtod(m
, int *))
1012 so
->so_options
|= SO_TTCP_SHUTUP
;
1014 so
->so_options
&= ~SO_TTCP_SHUTUP
;
1019 if (level
!= SOL_SOCKET
) {
1020 if (so
->so_proto
&& so
->so_proto
->pr_ctloutput
)
1021 return ((*so
->so_proto
->pr_ctloutput
)
1022 (PRCO_SETOPT
, so
, level
, optname
, &m0
));
1023 error
= ENOPROTOOPT
;
1028 if (m
== NULL
|| m
->m_len
!= sizeof (struct linger
)) {
1033 int val
= mtod(m
, struct linger
*)->l_linger
;
1036 * l_linger is in seconds
1038 so
->so_linger
.tv_sec
= val
;
1039 so
->so_linger
.tv_usec
= 0;
1041 so
->so_linger
.tv_sec
= val
/ hz
;
1042 so
->so_linger
.tv_usec
= (val
% hz
) * tick
;
1050 case SO_USELOOPBACK
:
1055 if (m
== NULL
|| m
->m_len
< sizeof (int)) {
1059 if (*mtod(m
, int *))
1060 so
->so_options
|= optname
;
1062 so
->so_options
&= ~optname
;
1070 if (m
== NULL
|| m
->m_len
< sizeof (int)) {
1078 if (sbreserve(optname
== SO_SNDBUF
?
1079 &so
->so_snd
: &so
->so_rcv
,
1080 (u_long
) *mtod(m
, int *)) == 0) {
1087 so
->so_snd
.sb_lowat
= *mtod(m
, int *);
1090 so
->so_rcv
.sb_lowat
= *mtod(m
, int *);
1093 so
->so_eventmask
= *mtod(m
, int *);
1094 so
->so_state
|= SS_ASYNC
;
1095 so
->so_rcv
.sb_flags
|= SB_ASYNC
;
1096 so
->so_snd
.sb_flags
|= SB_ASYNC
;
1097 DEVENTS(log(LOG_DEBUG
, "Setting SO_EVENTMASK = 0x%08lx", so
->so_eventmask
);)
1106 if (m
== NULL
|| m
->m_len
< sizeof (*tv
)) {
1110 tv
= mtod(m
, struct timeval
*);
1115 so
->so_snd
.sb_timeo
= *tv
;
1118 so
->so_rcv
.sb_timeo
= *tv
;
1125 error
= ENOPROTOOPT
;
1136 sogetopt(so
, level
, optname
, mp
)
1137 register struct socket
*so
;
1141 register struct mbuf
*m
;
1143 if (level
!= SOL_SOCKET
) {
1144 if (so
->so_proto
&& so
->so_proto
->pr_ctloutput
) {
1145 return ((*so
->so_proto
->pr_ctloutput
)
1146 (PRCO_GETOPT
, so
, level
, optname
, mp
));
1148 return (ENOPROTOOPT
);
1150 m
= m_get(M_WAIT
, MT_SOOPTS
);
1151 m
->m_len
= sizeof (int);
1156 m
->m_len
= sizeof (struct linger
);
1157 mtod(m
, struct linger
*)->l_onoff
=
1158 so
->so_options
& SO_LINGER
;
1159 mtod(m
, struct linger
*)->l_linger
=
1161 so
->so_linger
.tv_sec
* hz
+
1162 so
->so_linger
.tv_usec
/ tick
;
1165 * l_linger is in seconds
1167 so
->so_linger
.tv_sec
;
1171 case SO_USELOOPBACK
:
1179 *mtod(m
, int *) = so
->so_options
& optname
;
1183 *mtod(m
, int *) = so
->so_type
;
1187 *mtod(m
, int *) = so
->so_error
;
1192 *mtod(m
, int *) = so
->so_snd
.sb_hiwat
;
1196 *mtod(m
, int *) = so
->so_rcv
.sb_hiwat
;
1200 *mtod(m
, int *) = so
->so_snd
.sb_lowat
;
1204 *mtod(m
, int *) = so
->so_rcv
.sb_lowat
;
1208 DEVENTS(log(LOG_DEBUG
, "Getting SO_EVENTMASK = 0x%08lx", so
->so_eventmask
);)
1209 *mtod(m
, int *) = so
->so_eventmask
;
1215 struct timeval
*tv
= (optname
== SO_SNDTIMEO
?
1216 &so
->so_snd
.sb_timeo
: &so
->so_rcv
.sb_timeo
);
1218 m
->m_len
= sizeof(struct timeval
);
1219 mtod(m
, struct timeval
*)->tv_sec
= tv
->tv_sec
;
1220 mtod(m
, struct timeval
*)->tv_usec
= tv
->tv_usec
;
1226 return (ENOPROTOOPT
);
1235 register struct socket
*so
;
1239 Signal(so
->so_pgid
->thisTask
, so
->so_pgid
->sigUrgMask
);
1240 soevent(so
, FD_OOB
);
1244 if (so
->so_pgid
< 0)
1245 gsignal(-so
->so_pgid
, SIGURG
);
1246 else if (so
->so_pgid
> 0 && (p
= pfind(so
->so_pgid
)) != 0)
1249 if (so
->so_rcv
.sb_flags
& SB_SEL
) {
1250 so
->so_rcv
.sb_flags
&= ~SB_SEL
; /* do not notify us any more */
1251 selwakeup(&so
->so_rcv
.sb_sel
);