mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-10-15 02:59:14 +08:00
Use accept() from FreeBSD
This commit is contained in:
@@ -55,6 +55,8 @@ int pselect(int, fd_set *__restrict, fd_set *__restrict, fd_set *__restrict,
|
||||
|
||||
int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
|
||||
|
||||
int accept(int, struct sockaddr * __restrict, socklen_t * __restrict);
|
||||
|
||||
int bind(int, const struct sockaddr *, socklen_t);
|
||||
|
||||
int connect(int, const struct sockaddr *, socklen_t);
|
||||
|
@@ -165,192 +165,6 @@ sockargs(mp, buf, buflen, type)
|
||||
*********************************************************************
|
||||
*/
|
||||
|
||||
int
|
||||
kern_accept(struct thread *td, int s, struct sockaddr **name, socklen_t *namelen)
|
||||
{
|
||||
struct sockaddr *sa = NULL;
|
||||
int error;
|
||||
struct socket *head, *so;
|
||||
int fd;
|
||||
u_int fflag;
|
||||
pid_t pgid;
|
||||
int tmp;
|
||||
|
||||
if (name) {
|
||||
*name = NULL;
|
||||
if (*namelen < 0)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if ((head = rtems_bsdnet_fdToSocket (s)) == NULL) {
|
||||
error = EBADF;
|
||||
return (error);
|
||||
}
|
||||
if ((head->so_options & SO_ACCEPTCONN) == 0) {
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
#ifdef MAC
|
||||
error = mac_socket_check_accept(td->td_ucred, head);
|
||||
if (error != 0)
|
||||
goto done;
|
||||
#endif
|
||||
ACCEPT_LOCK();
|
||||
if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) {
|
||||
ACCEPT_UNLOCK();
|
||||
error = EWOULDBLOCK;
|
||||
goto noconnection;
|
||||
}
|
||||
while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
|
||||
if (head->so_rcv.sb_state & SBS_CANTRCVMORE) {
|
||||
head->so_error = ECONNABORTED;
|
||||
break;
|
||||
}
|
||||
error = msleep(&head->so_timeo, &accept_mtx, PSOCK | PCATCH,
|
||||
"accept", 0);
|
||||
if (error) {
|
||||
ACCEPT_UNLOCK();
|
||||
goto noconnection;
|
||||
}
|
||||
}
|
||||
if (head->so_error) {
|
||||
error = head->so_error;
|
||||
head->so_error = 0;
|
||||
ACCEPT_UNLOCK();
|
||||
goto noconnection;
|
||||
}
|
||||
so = TAILQ_FIRST(&head->so_comp);
|
||||
KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
|
||||
KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));
|
||||
|
||||
/*
|
||||
* Before changing the flags on the socket, we have to bump the
|
||||
* reference count. Otherwise, if the protocol calls sofree(),
|
||||
* the socket will be released due to a zero refcount.
|
||||
*/
|
||||
SOCK_LOCK(so); /* soref() and so_state update */
|
||||
soref(so); /* file descriptor reference */
|
||||
|
||||
TAILQ_REMOVE(&head->so_comp, so, so_list);
|
||||
head->so_qlen--;
|
||||
|
||||
fd = rtems_bsdnet_makeFdForSocket (so);
|
||||
if (fd < 0) {
|
||||
TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
|
||||
head->so_qlen++;
|
||||
wakeup(head);
|
||||
error = EBADF;
|
||||
return (error);
|
||||
}
|
||||
|
||||
so->so_state |= (head->so_state & SS_NBIO);
|
||||
so->so_qstate &= ~SQ_COMP;
|
||||
so->so_head = NULL;
|
||||
|
||||
SOCK_UNLOCK(so);
|
||||
ACCEPT_UNLOCK();
|
||||
|
||||
td->td_retval[0] = fd;
|
||||
|
||||
sa = 0;
|
||||
CURVNET_SET(so->so_vnet);
|
||||
error = soaccept(so, &sa);
|
||||
CURVNET_RESTORE();
|
||||
if (error) {
|
||||
/*
|
||||
* return a namelen of zero for older code which might
|
||||
* ignore the return value from accept.
|
||||
*/
|
||||
if (name)
|
||||
*namelen = 0;
|
||||
goto noconnection;
|
||||
}
|
||||
if (sa == NULL) {
|
||||
if (name)
|
||||
*namelen = 0;
|
||||
goto done;
|
||||
}
|
||||
if (name) {
|
||||
/* check sa_len before it is destroyed */
|
||||
if (*namelen > sa->sa_len)
|
||||
*namelen = sa->sa_len;
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(td, KTR_STRUCT))
|
||||
ktrsockaddr(sa);
|
||||
#endif
|
||||
*name = sa;
|
||||
sa = NULL;
|
||||
}
|
||||
noconnection:
|
||||
if (sa)
|
||||
free(sa, M_SONAME);
|
||||
|
||||
done:
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
accept1(td, s, _name, _namelen, compat)
|
||||
struct thread *td;
|
||||
int s;
|
||||
struct sockaddr *_name;
|
||||
int *_namelen;
|
||||
int compat;
|
||||
{
|
||||
struct sockaddr *name;
|
||||
socklen_t namelen;
|
||||
int error;
|
||||
|
||||
if (_name == NULL)
|
||||
return (kern_accept(td, s, NULL, NULL));
|
||||
|
||||
error = copyin(_namelen, &namelen, sizeof (namelen));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = kern_accept(td, s, &name, &namelen);
|
||||
|
||||
/*
|
||||
* return a namelen of zero for older code which might
|
||||
* ignore the return value from accept.
|
||||
*/
|
||||
if (error) {
|
||||
(void) copyout(&namelen,
|
||||
_namelen, sizeof(*_namelen));
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (error == 0 && name != NULL) {
|
||||
#ifdef COMPAT_OLDSOCK
|
||||
if (compat)
|
||||
((struct osockaddr *)name)->sa_family =
|
||||
name->sa_family;
|
||||
#endif
|
||||
error = copyout(name, _name, namelen);
|
||||
}
|
||||
if (error == 0)
|
||||
error = copyout(&namelen, _namelen,
|
||||
sizeof(namelen));
|
||||
free(name, M_SONAME);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
accept (int s, struct sockaddr *name, int *namelen)
|
||||
{
|
||||
struct thread *td;
|
||||
int error;
|
||||
|
||||
td = curthread;
|
||||
error = accept1(td, s, name, namelen, 0);
|
||||
if( error == 0 )
|
||||
{
|
||||
return td->td_retval[0];
|
||||
}
|
||||
errno = error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
kern_sendit(td, s, mp, flags, control, segflg)
|
||||
struct thread *td;
|
||||
|
Reference in New Issue
Block a user