/* uipc_socket.c 4.30 82/01/24 */
#include "../h/protosw.h"
#include "../h/socketvar.h"
#include "../net/in_systm.h"
* Socket support routines.
* DEAL WITH INTERRUPT NOTIFICATION.
socreate(aso
, type
, asp
, asa
, options
)
register struct protosw
*prp
;
register struct socket
*so
;
* Use process standard protocol/protocol family if none
* specified by address argument.
pf
= PF_INET
; /* should be u.u_protof */
proto
= asp
->sp_protocol
;
* If protocol specified, look for it, otherwise
* for a protocol of the correct type in the right family.
prp
= pffindproto(pf
, proto
);
prp
= pffindtype(pf
, type
);
return (EPROTONOSUPPORT
);
* Get a socket structure.
so
= mtod(m
, struct socket
*);
so
->so_options
= options
;
* Attach protocol to socket, initializing
* and reserving resources.
error
= (*prp
->pr_usrreq
)(so
, PRU_ATTACH
, 0, asa
);
if (so
->so_pcb
|| (so
->so_state
& SS_USERGONE
) == 0)
* Close a socket on last file table reference removal.
* Initiate disconnect if connected.
* Free socket when disconnect complete.
* THIS IS REALLY A UNIX INTERFACE ROUTINE
register struct socket
*so
;
int s
= splnet(); /* conservative */
if (so
->so_state
& SS_ISCONNECTED
) {
if ((so
->so_state
& SS_ISDISCONNECTING
) == 0) {
u
.u_error
= sodisconnect(so
, (struct sockaddr
*)0);
if ((so
->so_options
& SO_DONTLINGER
) == 0) {
if ((so
->so_state
& SS_ISDISCONNECTING
) &&
(so
->so_options
& SO_NONBLOCKING
) &&
/* should use tsleep here, for at most linger */
while (so
->so_state
& SS_ISCONNECTED
)
sleep((caddr_t
)&so
->so_timeo
, PZERO
+1);
u
.u_error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_DETACH
, 0, 0);
so
->so_state
|= SS_USERGONE
;
if (pso
->so_proto
->pr_family
!= PF_UNIX
) {
tso
= pso
; pso
= so
; so
= tso
;
if (pso
->so_proto
->pr_family
!= PF_UNIX
)
/* check types and buffer space */
bzero((caddr_t
)sb
, sizeof (*sb
)); /* XXX */
* Accept connection on a socket.
if ((so
->so_options
& SO_ACCEPTCONN
) == 0) {
error
= EINVAL
; /* XXX */
if ((so
->so_state
& SS_CONNAWAITING
) == 0) {
so
->so_state
&= ~SS_CONNAWAITING
;
error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_ACCEPT
, 0, (caddr_t
)asa
);
* Connect socket to a specified address.
* If already connected or connecting, then avoid
* the protocol entry, to keep its job simpler.
if (so
->so_state
& (SS_ISCONNECTED
|SS_ISCONNECTING
)) {
error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_CONNECT
, 0, (caddr_t
)asa
);
* Disconnect from a socket.
* Address parameter is from system call for later multicast
* protocols. Check to make sure that connected and no disconnect
* in progress (for protocol's sake), and then invoke protocol.
if ((so
->so_state
& SS_ISCONNECTED
) == 0) {
if (so
->so_state
& SS_ISDISCONNECTING
) {
error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_DISCONNECT
, 0, asa
);
* If send must go all at once and message is larger than
* send buffering, then hard error.
* Lock against other senders.
* If must go all at once and not enough room now, then
* inform user that this would block and do nothing.
register struct socket
*so
;
register struct mbuf
*m
, **mp
= &top
;
if (so
->so_state
& SS_CANTSENDMORE
)
if (sosendallatonce(so
) && u
.u_count
> so
->so_snd
.sb_hiwat
)
if ((so
->so_snd
.sb_flags
& SB_LOCK
) && (so
->so_options
& SO_NONBLOCKING
))
#define snderr(errno) { error = errno; splx(s); goto release; }
if ((so
->so_state
& SS_ISCONNECTED
) == 0) {
if (so
->so_proto
->pr_flags
& PR_CONNREQUIRED
)
error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_SEND
, top
, asa
);
space
= sbspace(&so
->so_snd
);
if (space
<= 0 || sosendallatonce(so
) && space
< u
.u_count
) {
if (so
->so_options
& SO_NONBLOCKING
)
while (u
.u_count
&& space
> 0) {
if (u
.u_count
>= CLBYTES
&& space
>= CLBYTES
) {
m
->m_off
= (int)p
- (int)m
;
len
= MIN(MLEN
, u
.u_count
);
iomove(mtod(m
, caddr_t
), len
, B_WRITE
);
space
= sbspace(&so
->so_snd
);
register struct socket
*so
;
register struct mbuf
*m
, *n
;
int eor
, s
, error
= 0, cnt
= u
.u_count
;
#define rcverr(errno) { error = errno; splx(s); goto release; }
if (so
->so_rcv
.sb_cc
== 0) {
if (so
->so_state
& SS_CANTRCVMORE
) {
if ((so
->so_state
& SS_ISCONNECTED
) == 0 &&
(so
->so_proto
->pr_flags
& PR_CONNREQUIRED
))
if (so
->so_options
& SO_NONBLOCKING
)
if (so
->so_proto
->pr_flags
& PR_ADDR
) {
if (m
->m_len
!= sizeof (struct sockaddr
))
bcopy(mtod(m
, caddr_t
), (caddr_t
)asa
, sizeof (*asa
));
so
->so_rcv
.sb_cc
-= m
->m_len
;
so
->so_rcv
.sb_mbcnt
-= MSIZE
;
so
->so_state
&= ~SS_RCVATMARK
;
if (so
->so_oobmark
&& cnt
> so
->so_oobmark
)
len
= MIN(m
->m_len
, cnt
);
so
->so_rcv
.sb_mb
= m
->m_next
;
iomove(mtod(m
, caddr_t
), len
, B_READ
);
} while ((m
= so
->so_rcv
.sb_mb
) && cnt
&& !eor
);
if ((so
->so_proto
->pr_flags
& PR_ATOMIC
) && eor
== 0)
so
->so_rcv
.sb_mb
= m
->m_next
;
if ((so
->so_proto
->pr_flags
& PR_WANTRCVD
) && so
->so_pcb
)
(*so
->so_proto
->pr_usrreq
)(so
, PRU_RCVD
, 0, 0);
so
->so_oobmark
-= u
.u_base
- base
;
so
->so_state
|= SS_RCVATMARK
;
gsignal(so
->so_pgrp
, SIGURG
);
struct proc
*p
= pfind(-so
->so_pgrp
);
register struct socket
*so
;
if (copyin(cmdp
, (caddr_t
)&nbio
, sizeof (nbio
))) {
so
->so_options
|= SO_NONBLOCKING
;
so
->so_options
&= ~SO_NONBLOCKING
;
if (copyin(cmdp
, (caddr_t
)&async
, sizeof (async
))) {
if (copyin(cmdp
, (caddr_t
)&keep
, sizeof (keep
))) {
so
->so_options
&= ~SO_NOKEEPALIVE
;
so
->so_options
|= SO_NOKEEPALIVE
;
int keep
= (so
->so_options
& SO_NOKEEPALIVE
) == 0;
if (copyout((caddr_t
)&keep
, cmdp
, sizeof (keep
)))
if (copyin(cmdp
, (caddr_t
)&linger
, sizeof (linger
))) {
so
->so_options
&= ~SO_DONTLINGER
;
so
->so_options
|= SO_DONTLINGER
;
int linger
= so
->so_linger
;
if (copyout((caddr_t
)&linger
, cmdp
, sizeof (linger
))) {
if (copyin(cmdp
, (caddr_t
)&pgrp
, sizeof (pgrp
))) {
if (copyout((caddr_t
)&pgrp
, cmdp
, sizeof (pgrp
))) {
if (copyin(cmdp
, (caddr_t
)&flags
, sizeof (flags
))) {
u
.u_error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_SHUTDOWN
, (struct mbuf
*)0, 0);
if (copyin(cmdp
, (caddr_t
)&oob
, sizeof (oob
))) {
(*so
->so_proto
->pr_usrreq
)(so
, PRU_SENDOOB
, m
, 0);
struct mbuf
*m
= m_get(M_DONTWAIT
);
m
->m_off
= MMINOFF
; *mtod(m
, caddr_t
) = 0;
(*so
->so_proto
->pr_usrreq
)(so
, PRU_RCVOOB
, m
, 0);
if (copyout(mtod(m
, caddr_t
), cmdp
, sizeof (char))) {
int atmark
= (so
->so_state
&SS_RCVATMARK
) != 0;
if (copyout((caddr_t
)&atmark
, cmdp
, sizeof (atmark
))) {
/* type/protocol specific ioctls */