diff --git a/freebsd/sys/kern/uipc_syscalls.c b/freebsd/sys/kern/uipc_syscalls.c index a52de3aa..fbec5462 100644 --- a/freebsd/sys/kern/uipc_syscalls.c +++ b/freebsd/sys/kern/uipc_syscalls.c @@ -401,7 +401,11 @@ listen(int socket, int backlog) } #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() */ @@ -456,12 +460,40 @@ accept1(td, uap, compat) free(name, M_SONAME); 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 kern_accept(struct thread *td, int s, struct sockaddr **name, socklen_t *namelen, struct file **fp) { +#ifndef __rtems__ struct filedesc *fdp; +#endif /* __rtems__ */ struct file *headfp, *nfp = NULL; struct sockaddr *sa = NULL; int error; @@ -478,7 +510,9 @@ kern_accept(struct thread *td, int s, struct sockaddr **name, } AUDIT_ARG_FD(s); +#ifndef __rtems__ fdp = td->td_proc->p_fd; +#endif /* __rtems__ */ error = getsock(fdp, s, &headfp, &fflag); if (error) return (error); @@ -614,6 +648,7 @@ done: return (error); } +#ifndef __rtems__ int accept(td, uap) struct thread *td; diff --git a/freebsd/sys/sys/sysproto.h b/freebsd/sys/sys/sysproto.h index 69365322..eff4528c 100644 --- a/freebsd/sys/sys/sysproto.h +++ b/freebsd/sys/sys/sysproto.h @@ -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 fromlenaddr_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict fromlenaddr; char fromlenaddr_r_[PADR_(__socklen_t *__restrict)]; }; +#endif /* __rtems__ */ struct accept_args { 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 anamelen_l_[PADL_(__socklen_t *__restrict)]; __socklen_t *__restrict anamelen; char anamelen_r_[PADR_(__socklen_t *__restrict)]; }; +#ifndef __rtems__ struct getpeername_args { 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)]; diff --git a/rtemsbsd/include/machine/rtems-bsd-syscall-api.h b/rtemsbsd/include/machine/rtems-bsd-syscall-api.h index fc45b7dc..db9781c6 100644 --- a/rtemsbsd/include/machine/rtems-bsd-syscall-api.h +++ b/rtemsbsd/include/machine/rtems-bsd-syscall-api.h @@ -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); diff --git a/rtemsbsd/rtems/rtems-bsd-syscalls.c b/rtemsbsd/rtems/rtems-bsd-syscalls.c index d9c84afc..0669a70e 100644 --- a/rtemsbsd/rtems/rtems-bsd-syscalls.c +++ b/rtemsbsd/rtems/rtems-bsd-syscalls.c @@ -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; diff --git a/testsuite/syscalls01/test_main.c b/testsuite/syscalls01/test_main.c index 21bd869b..c82602c3 100644 --- a/testsuite/syscalls01/test_main.c +++ b/testsuite/syscalls01/test_main.c @@ -676,6 +676,57 @@ test_socket_listen(void) 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 test_main(void) { @@ -688,6 +739,7 @@ test_main(void) test_socket_bind(); test_socket_connect(); test_socket_listen(); + test_socket_accept(); puts("*** END OF " TEST_NAME " TEST ***"); exit(0);