/* uipc_socket.c 4.2 81/11/08 */
#include "../h/protocol.h"
#include "../h/protosw.h"
#include "../h/socketvar.h"
#include "../net/inet_systm.h"
struct socket zerosocket
;
struct in_addr zeroin_addr
;
* Socket system call interface. Copy in arguments
* set up file descriptor and call internal socket
} *uap
= (struct a
*)u
.u_ap
;
register struct socket
*so
;
register struct file
*fp
;
if ((fp
= falloc()) == NULL
)
fp
->f_flag
= FSOCKET
|FREAD
|FWRITE
;
if (copyin((caddr_t
)uap
->ain
, &in
, sizeof (in
))) {
u
.u_error
= socket(&so0
, uap
->type
, &in
, uap
->options
);
u
.u_ofile
[u
.u_r
.r_val1
] = 0;
socket(aso
, type
, iap
, options
)
register struct in_addr
*iap
;
register struct protosw
*prp
;
register struct socket
*so
;
* Pin down protocol if possible.
* If no address specified, use a generic protocol.
* A specific protocol was requested. Look
* for the protocol. If not found, then we
prp
= pf_findproto(pf
, proto
);
return (EPROTONOSUPPORT
);
* No specific protocol was requested. Look
* in the specified (or generic) protocol set
* for a protocol of this type.
prp
= pf_findtype(pf
, type
);
return (pf
== PF_GENERIC
?
ESOCKTNOSUPPORT
: EPROTONOSUPPORT
);
* Get a socket structure.
so
= mtod(m
, struct socket
*);
so
->so_options
= options
;
* An early call to protocol initialization. If protocol
* actually hasn't been decided on yet (till we know
* peer), then the generic protocol allocated so far can
* just make sure a reasonable amount of resources will
* be available to it (say by allocating liberally now
* and returning some of the resources later).
(*prp
->pr_usrreq
)(so
, PRU_ATTACH
, 0, 0);
register struct socket
*so
;
(*so
->so_proto
->pr_usrreq
)(so
, PRU_DETACH
, 0, 0);
register struct socket
*so
;
if ((p
= so
->so_rcv
.sb_sel
) && p
->p_wchan
== (caddr_t
)select
)
so
->so_rcv
.sb_flags
|= SB_COLL
;
so
->so_rcv
.sb_sel
= u
.u_procp
;
* Wakeup read sleep/select'ers.
if (so
->so_rcv
.sb_cc
&& so
->so_rcv
.sb_sel
) {
selwakeup(so
->so_rcv
.sb_sel
, so
->so_rcv
.sb_flags
& SB_COLL
);
so
->so_rcv
.sb_flags
&= ~SB_COLL
;
if (so
->so_rcv
.sb_flags
& SB_WAIT
) {
so
->so_rcv
.sb_flags
&= ~SB_WAIT
;
wakeup((caddr_t
)&so
->so_rcv
.sb_cc
);
* Connect socket to foreign peer; system call
* interface. Copy in arguments and call internal routine.
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
register struct socket
*so
;
if (copyin((caddr_t
)uap
->a
, &in
, sizeof (in
))) {
if ((fp
->f_flag
& FSOCKET
) == 0) {
u
.u_error
= connect(so
, &in
);
/* should use tsleep here */
if ((*so
->so_proto
->pr_usrreq
)(so
, PRU_ISCONN
, 0, &in
) == 0)
sleep((caddr_t
)&so
->so_timeo
, PZERO
+1);
return ((*so
->so_proto
->pr_usrreq
)(so
, PRU_CONNECT
, 0, iap
));
* Disconnect socket from foreign peer; system call
* interface. Copy in arguments and call internal routine.
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
copyin((caddr_t
)uap
->addr
, (caddr_t
)&in
, sizeof (in
))) {
if ((fp
->f_flag
& FSOCKET
) == 0) {
disconnect(fp
->f_socket
, uap
->addr
? &in
: 0);
u
.u_error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_DISCONNECT
, 0, iap
);
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
if ((fp
->f_flag
& FSOCKET
) == 0) {
if (useracc(u
.u_base
, u
.u_count
, B_READ
) == 0 ||
uap
->ain
&& copyin((caddr_t
)uap
->ain
, (caddr_t
)&in
, sizeof (in
))) {
u
.u_error
= send(fp
->f_socket
, uap
->ain
? &in
: 0);
register struct socket
*so
;
register struct mbuf
*m
, **mp
;
if (so
->so_proto
->pr_flags
& PR_ATOMIC
) {
if (u
.u_count
> so
->so_snd
.sb_hiwat
) {
while (so
->so_snd
.sb_flags
& SB_LOCK
) {
so
->so_snd
.sb_flags
|= SB_WANT
;
sleep((caddr_t
)&so
->so_snd
.sb_flags
, PZERO
+1);
if (so
->so_snd
.sb_hiwat
- so
->so_snd
.sb_cc
< u
.u_count
) {
so
->so_snd
.sb_flags
|= SB_WAIT
;
sleep((caddr_t
)&so
->so_snd
.sb_cc
, PZERO
+1);
so
->so_snd
.sb_flags
|= SB_LOCK
;
register int bufs
= so
->so_snd
.sb_mbmax
- so
->so_snd
.sb_mbcnt
;
so
->so_snd
.sb_flags
|= SB_WAIT
;
sleep((caddr_t
)&so
->so_snd
.sb_cc
, PZERO
+1);
while (--bufs
>= 0 && u
.u_count
> 0) {
if (u
.u_count
>= PGSIZE
&& bufs
>= NMBPG
) {
m
->m_off
= (int)p
- (int)m
;
len
= MIN(MLEN
, u
.u_count
);
iomove(mtod(m
, caddr_t
), len
, B_WRITE
);
{ register int s
= splnet();
error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_SEND
, top
, iap
);
so
->so_snd
.sb_flags
&= ~SB_LOCK
;
if (so
->so_snd
.sb_flags
& SB_WANT
)
wakeup((caddr_t
)&so
->so_snd
.sb_flags
);
* Receive data on socket.
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
if ((fp
->f_flag
& FSOCKET
) == 0) {
if (useracc(u
.u_base
, u
.u_count
, B_WRITE
) == 0 ||
uap
->ain
&& copyin((caddr_t
)uap
->ain
, (caddr_t
)&in
, sizeof (in
))) {
receive(fp
->f_socket
, uap
->ain
? &in
: 0);
register struct socket
*so
;
register struct mbuf
*m
, *n
;
register int eor
, len
, s
;
while (so
->so_rcv
.sb_flags
& SB_LOCK
) {
so
->so_rcv
.sb_flags
|= SB_WANT
;
sleep((caddr_t
)&so
->so_rcv
.sb_flags
, PZERO
+1);
if (so
->so_rcv
.sb_cc
== 0) {
if ((so
->so_proto
->pr_usrreq
)(so
, PRU_ISDISCONN
, 0, 0) == 0)
so
->so_rcv
.sb_flags
|= SB_WAIT
;
sleep((caddr_t
)&so
->so_rcv
.sb_cc
, PZERO
+1);
so
->so_rcv
.sb_flags
|= SB_LOCK
;
len
= MIN(m
->m_len
, u
.u_count
);
so
->so_rcv
.sb_mb
= m
->m_next
;
if (so
->so_rcv
.sb_cc
< 0)
iomove(mtod(m
, caddr_t
), len
, B_READ
);
if (so
->so_rcv
.sb_cc
< 0)
} while ((m
= so
->so_rcv
.sb_mb
) && u
.u_count
&& !eor
);
if ((so
->so_proto
->pr_flags
& PR_ATOMIC
) && eor
== 0)
so
->so_rcv
.sb_cc
-= m
->m_len
;
if (so
->so_rcv
.sb_cc
< 0)
so
->so_rcv
.sb_mb
= m
->m_next
;
if ((so
->so_proto
->pr_flags
& PR_ADDR
)) {
so
->so_rcv
.sb_mb
= m
->m_next
;
so
->so_rcv
.sb_cc
-= m
->m_len
;
len
= MIN(m
->m_len
, sizeof (struct in_addr
));
bcopy(mtod(m
, caddr_t
), (caddr_t
)iap
, len
);
(*so
->so_proto
->pr_usrreq
)(so
, PRU_RCVD
, m
, 0);
register struct socket
*so
;
* Generic protocol handler.