* Copyright (c) 1982, 1986 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)uipc_syscalls.c 7.5 (Berkeley) 6/29/88
* System call interface to the socket abstraction.
extern struct fileops socketops
;
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
if ((fp
= falloc()) == NULL
)
fp
->f_flag
= FREAD
|FWRITE
;
fp
->f_type
= DTYPE_SOCKET
;
u
.u_error
= socreate(uap
->domain
, &so
, uap
->type
, uap
->protocol
);
fp
->f_data
= (caddr_t
)so
;
u
.u_ofile
[u
.u_r
.r_val1
] = 0;
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
u
.u_error
= sockargs(&nam
, uap
->name
, uap
->namelen
, MT_SONAME
);
u
.u_error
= sobind((struct socket
*)fp
->f_data
, nam
);
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
u
.u_error
= solisten((struct socket
*)fp
->f_data
, uap
->backlog
);
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
register struct socket
*so
;
u
.u_error
= copyin((caddr_t
)uap
->anamelen
, (caddr_t
)&namelen
,
if (useracc((caddr_t
)uap
->name
, (u_int
)namelen
, B_WRITE
) == 0) {
so
= (struct socket
*)fp
->f_data
;
if ((so
->so_options
& SO_ACCEPTCONN
) == 0) {
if ((so
->so_state
& SS_NBIO
) && so
->so_qlen
== 0) {
while (so
->so_qlen
== 0 && so
->so_error
== 0) {
if (so
->so_state
& SS_CANTRCVMORE
) {
so
->so_error
= ECONNABORTED
;
sleep((caddr_t
)&so
->so_timeo
, PZERO
+1);
u
.u_error
= so
->so_error
;
u
.u_ofile
[u
.u_r
.r_val1
] = 0;
{ struct socket
*aso
= so
->so_q
;
if (soqremque(aso
, 1) == 0)
fp
->f_type
= DTYPE_SOCKET
;
fp
->f_flag
= FREAD
|FWRITE
;
fp
->f_data
= (caddr_t
)so
;
nam
= m_get(M_WAIT
, MT_SONAME
);
(void) soaccept(so
, nam
);
if (namelen
> nam
->m_len
)
/* SHOULD COPY OUT A CHAIN HERE */
(void) copyout(mtod(nam
, caddr_t
), (caddr_t
)uap
->name
,
(void) copyout((caddr_t
)&namelen
, (caddr_t
)uap
->anamelen
,
sizeof (*uap
->anamelen
));
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
register struct socket
*so
;
so
= (struct socket
*)fp
->f_data
;
if ((so
->so_state
& SS_NBIO
) &&
(so
->so_state
& SS_ISCONNECTING
)) {
u
.u_error
= sockargs(&nam
, uap
->name
, uap
->namelen
, MT_SONAME
);
u
.u_error
= soconnect(so
, nam
);
if ((so
->so_state
& SS_NBIO
) &&
(so
->so_state
& SS_ISCONNECTING
)) {
if (setjmp(&u
.u_qsave
)) {
while ((so
->so_state
& SS_ISCONNECTING
) && so
->so_error
== 0)
sleep((caddr_t
)&so
->so_timeo
, PZERO
+1);
u
.u_error
= so
->so_error
;
so
->so_state
&= ~SS_ISCONNECTING
;
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp1
, *fp2
;
struct socket
*so1
, *so2
;
if (useracc((caddr_t
)uap
->rsv
, 2 * sizeof (int), B_WRITE
) == 0) {
u
.u_error
= socreate(uap
->domain
, &so1
, uap
->type
, uap
->protocol
);
u
.u_error
= socreate(uap
->domain
, &so2
, uap
->type
, uap
->protocol
);
fp1
->f_flag
= FREAD
|FWRITE
;
fp1
->f_type
= DTYPE_SOCKET
;
fp1
->f_data
= (caddr_t
)so1
;
fp2
->f_flag
= FREAD
|FWRITE
;
fp2
->f_type
= DTYPE_SOCKET
;
fp2
->f_data
= (caddr_t
)so2
;
u
.u_error
= soconnect2(so1
, so2
);
if (uap
->type
== SOCK_DGRAM
) {
* Datagram socket connection is asymmetric.
u
.u_error
= soconnect2(so2
, so1
);
(void) copyout((caddr_t
)sv
, (caddr_t
)uap
->rsv
, 2 * sizeof (int));
} *uap
= (struct a
*)u
.u_ap
;
msg
.msg_namelen
= uap
->tolen
;
aiov
.iov_base
= uap
->buf
;
msg
.msg_accrightslen
= 0;
sendit(uap
->s
, &msg
, uap
->flags
);
} *uap
= (struct a
*)u
.u_ap
;
aiov
.iov_base
= uap
->buf
;
msg
.msg_accrightslen
= 0;
sendit(uap
->s
, &msg
, uap
->flags
);
} *uap
= (struct a
*)u
.u_ap
;
struct iovec aiov
[MSG_MAXIOVLEN
];
u
.u_error
= copyin(uap
->msg
, (caddr_t
)&msg
, sizeof (msg
));
if ((u_int
)msg
.msg_iovlen
>= sizeof (aiov
) / sizeof (aiov
[0])) {
copyin((caddr_t
)msg
.msg_iov
, (caddr_t
)aiov
,
(unsigned)(msg
.msg_iovlen
* sizeof (aiov
[0])));
sendit(uap
->s
, &msg
, uap
->flags
);
register struct msghdr
*mp
;
register struct file
*fp
;
register struct iovec
*iov
;
struct mbuf
*to
, *rights
;
auio
.uio_iov
= mp
->msg_iov
;
auio
.uio_iovcnt
= mp
->msg_iovlen
;
auio
.uio_segflg
= UIO_USERSPACE
;
auio
.uio_offset
= 0; /* XXX */
for (i
= 0; i
< mp
->msg_iovlen
; i
++, iov
++) {
if (useracc(iov
->iov_base
, (u_int
)iov
->iov_len
, B_READ
) == 0) {
auio
.uio_resid
+= iov
->iov_len
;
sockargs(&to
, mp
->msg_name
, mp
->msg_namelen
, MT_SONAME
);
sockargs(&rights
, mp
->msg_accrights
, mp
->msg_accrightslen
,
sosend((struct socket
*)fp
->f_data
, to
, &auio
, flags
, rights
);
u
.u_r
.r_val1
= len
- auio
.uio_resid
;
} *uap
= (struct a
*)u
.u_ap
;
u
.u_error
= copyin((caddr_t
)uap
->fromlenaddr
, (caddr_t
)&len
,
msg
.msg_name
= uap
->from
;
aiov
.iov_base
= uap
->buf
;
msg
.msg_accrightslen
= 0;
recvit(uap
->s
, &msg
, uap
->flags
, (caddr_t
)uap
->fromlenaddr
, (caddr_t
)0);
} *uap
= (struct a
*)u
.u_ap
;
aiov
.iov_base
= uap
->buf
;
msg
.msg_accrightslen
= 0;
recvit(uap
->s
, &msg
, uap
->flags
, (caddr_t
)0, (caddr_t
)0);
} *uap
= (struct a
*)u
.u_ap
;
struct iovec aiov
[MSG_MAXIOVLEN
];
u
.u_error
= copyin((caddr_t
)uap
->msg
, (caddr_t
)&msg
, sizeof (msg
));
if ((u_int
)msg
.msg_iovlen
>= sizeof (aiov
) / sizeof (aiov
[0])) {
copyin((caddr_t
)msg
.msg_iov
, (caddr_t
)aiov
,
(unsigned)(msg
.msg_iovlen
* sizeof (aiov
[0])));
if (useracc((caddr_t
)msg
.msg_accrights
,
(unsigned)msg
.msg_accrightslen
, B_WRITE
) == 0) {
recvit(uap
->s
, &msg
, uap
->flags
,
(caddr_t
)&uap
->msg
->msg_namelen
,
(caddr_t
)&uap
->msg
->msg_accrightslen
);
recvit(s
, mp
, flags
, namelenp
, rightslenp
)
register struct msghdr
*mp
;
caddr_t namelenp
, rightslenp
;
register struct file
*fp
;
register struct iovec
*iov
;
struct mbuf
*from
, *rights
;
auio
.uio_iov
= mp
->msg_iov
;
auio
.uio_iovcnt
= mp
->msg_iovlen
;
auio
.uio_segflg
= UIO_USERSPACE
;
auio
.uio_offset
= 0; /* XXX */
for (i
= 0; i
< mp
->msg_iovlen
; i
++, iov
++) {
if (useracc(iov
->iov_base
, (u_int
)iov
->iov_len
, B_WRITE
) == 0) {
auio
.uio_resid
+= iov
->iov_len
;
soreceive((struct socket
*)fp
->f_data
, &from
, &auio
,
u
.u_r
.r_val1
= len
- auio
.uio_resid
;
if (len
<= 0 || from
== 0)
(void) copyout((caddr_t
)mtod(from
, caddr_t
),
(caddr_t
)mp
->msg_name
, (unsigned)len
);
(void) copyout((caddr_t
)&len
, namelenp
, sizeof (int));
len
= mp
->msg_accrightslen
;
if (len
<= 0 || rights
== 0)
(void) copyout((caddr_t
)mtod(rights
, caddr_t
),
(caddr_t
)mp
->msg_accrights
, (unsigned)len
);
(void) copyout((caddr_t
)&len
, rightslenp
, sizeof (int));
} *uap
= (struct a
*)u
.u_ap
;
u
.u_error
= soshutdown((struct socket
*)fp
->f_data
, uap
->how
);
} *uap
= (struct a
*)u
.u_ap
;
if (uap
->valsize
> MLEN
) {
m
= m_get(M_WAIT
, MT_SOOPTS
);
copyin(uap
->val
, mtod(m
, caddr_t
), (u_int
)uap
->valsize
);
sosetopt((struct socket
*)fp
->f_data
, uap
->level
, uap
->name
, m
);
} *uap
= (struct a
*)u
.u_ap
;
u
.u_error
= copyin((caddr_t
)uap
->avalsize
, (caddr_t
)&valsize
,
sogetopt((struct socket
*)fp
->f_data
, uap
->level
, uap
->name
, &m
);
if (uap
->val
&& valsize
&& m
!= NULL
) {
u
.u_error
= copyout(mtod(m
, caddr_t
), uap
->val
, (u_int
)valsize
);
u
.u_error
= copyout((caddr_t
)&valsize
, (caddr_t
)uap
->avalsize
,
register struct file
*rf
, *wf
;
struct socket
*rso
, *wso
;
u
.u_error
= socreate(AF_UNIX
, &rso
, SOCK_STREAM
, 0);
u
.u_error
= socreate(AF_UNIX
, &wso
, SOCK_STREAM
, 0);
rf
->f_type
= DTYPE_SOCKET
;
rf
->f_data
= (caddr_t
)rso
;
wf
->f_type
= DTYPE_SOCKET
;
wf
->f_data
= (caddr_t
)wso
;
u
.u_r
.r_val2
= u
.u_r
.r_val1
;
if (u
.u_error
= unp_connect2(wso
, rso
))
wso
->so_state
|= SS_CANTRCVMORE
;
rso
->so_state
|= SS_CANTSENDMORE
;
u
.u_ofile
[u
.u_r
.r_val2
] = 0;
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
register struct socket
*so
;
u
.u_error
= copyin((caddr_t
)uap
->alen
, (caddr_t
)&len
, sizeof (len
));
so
= (struct socket
*)fp
->f_data
;
m
= m_getclr(M_WAIT
, MT_SONAME
);
u
.u_error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_SOCKADDR
, 0, m
, 0);
u
.u_error
= copyout(mtod(m
, caddr_t
), (caddr_t
)uap
->asa
, (u_int
)len
);
u
.u_error
= copyout((caddr_t
)&len
, (caddr_t
)uap
->alen
, sizeof (len
));
* Get name of peer for connected socket.
} *uap
= (struct a
*)u
.u_ap
;
register struct file
*fp
;
register struct socket
*so
;
so
= (struct socket
*)fp
->f_data
;
if ((so
->so_state
& SS_ISCONNECTED
) == 0) {
m
= m_getclr(M_WAIT
, MT_SONAME
);
u
.u_error
= copyin((caddr_t
)uap
->alen
, (caddr_t
)&len
, sizeof (len
));
u
.u_error
= (*so
->so_proto
->pr_usrreq
)(so
, PRU_PEERADDR
, 0, m
, 0);
u
.u_error
= copyout(mtod(m
, caddr_t
), (caddr_t
)uap
->asa
, (u_int
)len
);
u
.u_error
= copyout((caddr_t
)&len
, (caddr_t
)uap
->alen
, sizeof (len
));
sockargs(aname
, name
, namelen
, type
)
if ((u_int
)namelen
> MLEN
)
error
= copyin(name
, mtod(m
, caddr_t
), (u_int
)namelen
);
register struct file
*fp
;
if (fp
->f_type
!= DTYPE_SOCKET
) {