mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-05-14 07:29:25 +08:00
Use accept() from FreeBSD
This commit is contained in:
parent
7c3625139f
commit
7c2b59c831
@ -401,7 +401,11 @@ listen(int socket, int backlog)
|
|||||||
}
|
}
|
||||||
#endif /* __rtems__ */
|
#endif /* __rtems__ */
|
||||||
|
|
||||||
#ifndef __rtems__
|
#ifdef __rtems__
|
||||||
|
static int
|
||||||
|
kern_accept(struct thread *td, int s, struct sockaddr **name,
|
||||||
|
socklen_t *namelen, struct file **fp);
|
||||||
|
#endif /* __rtems__ */
|
||||||
/*
|
/*
|
||||||
* accept1()
|
* accept1()
|
||||||
*/
|
*/
|
||||||
@ -456,12 +460,40 @@ accept1(td, uap, compat)
|
|||||||
free(name, M_SONAME);
|
free(name, M_SONAME);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
#ifdef __rtems__
|
||||||
|
int
|
||||||
|
accept(int socket, struct sockaddr *__restrict address,
|
||||||
|
socklen_t *__restrict address_len)
|
||||||
|
{
|
||||||
|
struct thread *td = rtems_bsd_get_curthread_or_null();
|
||||||
|
struct accept_args ua = {
|
||||||
|
.s = socket,
|
||||||
|
.name = address,
|
||||||
|
.anamelen = address_len
|
||||||
|
};
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (td != NULL) {
|
||||||
|
error = accept1(td, &ua);
|
||||||
|
} else {
|
||||||
|
error = ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error == 0) {
|
||||||
|
return td->td_retval[0];
|
||||||
|
} else {
|
||||||
|
rtems_set_errno_and_return_minus_one(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* __rtems__ */
|
||||||
|
|
||||||
int
|
int
|
||||||
kern_accept(struct thread *td, int s, struct sockaddr **name,
|
kern_accept(struct thread *td, int s, struct sockaddr **name,
|
||||||
socklen_t *namelen, struct file **fp)
|
socklen_t *namelen, struct file **fp)
|
||||||
{
|
{
|
||||||
|
#ifndef __rtems__
|
||||||
struct filedesc *fdp;
|
struct filedesc *fdp;
|
||||||
|
#endif /* __rtems__ */
|
||||||
struct file *headfp, *nfp = NULL;
|
struct file *headfp, *nfp = NULL;
|
||||||
struct sockaddr *sa = NULL;
|
struct sockaddr *sa = NULL;
|
||||||
int error;
|
int error;
|
||||||
@ -478,7 +510,9 @@ kern_accept(struct thread *td, int s, struct sockaddr **name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
AUDIT_ARG_FD(s);
|
AUDIT_ARG_FD(s);
|
||||||
|
#ifndef __rtems__
|
||||||
fdp = td->td_proc->p_fd;
|
fdp = td->td_proc->p_fd;
|
||||||
|
#endif /* __rtems__ */
|
||||||
error = getsock(fdp, s, &headfp, &fflag);
|
error = getsock(fdp, s, &headfp, &fflag);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
@ -614,6 +648,7 @@ done:
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __rtems__
|
||||||
int
|
int
|
||||||
accept(td, uap)
|
accept(td, uap)
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
|
@ -145,11 +145,13 @@ struct recvfrom_args {
|
|||||||
char from_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict from; char from_r_[PADR_(struct sockaddr *__restrict)];
|
char from_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict from; char from_r_[PADR_(struct sockaddr *__restrict)];
|
||||||
char fromlenaddr_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict fromlenaddr; char fromlenaddr_r_[PADR_(__socklen_t *__restrict)];
|
char fromlenaddr_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict fromlenaddr; char fromlenaddr_r_[PADR_(__socklen_t *__restrict)];
|
||||||
};
|
};
|
||||||
|
#endif /* __rtems__ */
|
||||||
struct accept_args {
|
struct accept_args {
|
||||||
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
|
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
|
||||||
char name_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict name; char name_r_[PADR_(struct sockaddr *__restrict)];
|
char name_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict name; char name_r_[PADR_(struct sockaddr *__restrict)];
|
||||||
char anamelen_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict anamelen; char anamelen_r_[PADR_(__socklen_t *__restrict)];
|
char anamelen_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict anamelen; char anamelen_r_[PADR_(__socklen_t *__restrict)];
|
||||||
};
|
};
|
||||||
|
#ifndef __rtems__
|
||||||
struct getpeername_args {
|
struct getpeername_args {
|
||||||
char fdes_l_[PADL_(int)]; int fdes; char fdes_r_[PADR_(int)];
|
char fdes_l_[PADL_(int)]; int fdes; char fdes_r_[PADR_(int)];
|
||||||
char asa_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict asa; char asa_r_[PADR_(struct sockaddr *__restrict)];
|
char asa_l_[PADL_(struct sockaddr *__restrict)]; struct sockaddr *__restrict asa; char asa_r_[PADR_(struct sockaddr *__restrict)];
|
||||||
|
@ -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 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 bind(int, const struct sockaddr *, socklen_t);
|
||||||
|
|
||||||
int connect(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
|
int
|
||||||
kern_sendit(td, s, mp, flags, control, segflg)
|
kern_sendit(td, s, mp, flags, control, segflg)
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
|
@ -676,6 +676,57 @@ test_socket_listen(void)
|
|||||||
assert(rtems_resource_snapshot_check(&snapshot));
|
assert(rtems_resource_snapshot_check(&snapshot));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
no_mem_socket_accept(int fd)
|
||||||
|
{
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
socklen_t addr_len;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
addr_len = sizeof(addr);
|
||||||
|
rv = accept(fd, (struct sockaddr *) &addr, &addr_len);
|
||||||
|
assert(rv == -1);
|
||||||
|
assert(errno == ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_socket_accept(void)
|
||||||
|
{
|
||||||
|
rtems_resource_snapshot snapshot;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
socklen_t addr_len;
|
||||||
|
int sd;
|
||||||
|
int ad;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
puts("test socket accept");
|
||||||
|
|
||||||
|
rtems_resource_snapshot_take(&snapshot);
|
||||||
|
|
||||||
|
sd = socket(PF_INET, SOCK_STREAM, 0);
|
||||||
|
assert(sd >= 0);
|
||||||
|
|
||||||
|
do_no_mem_test(no_mem_socket_accept, sd);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
addr_len = sizeof(addr);
|
||||||
|
ad = accept(sd, (struct sockaddr *) &addr, &addr_len);
|
||||||
|
assert(ad == -1);
|
||||||
|
assert(errno == EINVAL);
|
||||||
|
|
||||||
|
rv = close(sd);
|
||||||
|
assert(rv == 0);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
addr_len = sizeof(addr);
|
||||||
|
ad = accept(sd, (struct sockaddr *) &addr, &addr_len);
|
||||||
|
assert(ad == -1);
|
||||||
|
assert(errno == EBADF);
|
||||||
|
|
||||||
|
assert(rtems_resource_snapshot_check(&snapshot));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_main(void)
|
test_main(void)
|
||||||
{
|
{
|
||||||
@ -688,6 +739,7 @@ test_main(void)
|
|||||||
test_socket_bind();
|
test_socket_bind();
|
||||||
test_socket_connect();
|
test_socket_connect();
|
||||||
test_socket_listen();
|
test_socket_listen();
|
||||||
|
test_socket_accept();
|
||||||
|
|
||||||
puts("*** END OF " TEST_NAME " TEST ***");
|
puts("*** END OF " TEST_NAME " TEST ***");
|
||||||
exit(0);
|
exit(0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user