Use getsockopt() and setsockopt() from FreeBSD

This commit is contained in:
Sebastian Huber 2013-10-14 12:53:43 +02:00
parent 7c2b59c831
commit ac78dd2440
5 changed files with 182 additions and 137 deletions

View File

@ -1486,10 +1486,18 @@ shutdown(int socket, int how)
}
#endif /* __rtems__ */
#ifndef __rtems__
/* ARGSUSED */
#ifndef __rtems__
int
setsockopt(td, uap)
#else /* __rtems__ */
static int
kern_setsockopt( struct thread *td, int s, int level, int name, void *val,
enum uio_seg valseg, socklen_t valsize);
static int
rtems_bsd_setsockopt(td, uap)
#endif /* __rtems__ */
struct thread *td;
struct setsockopt_args /* {
int s;
@ -1503,6 +1511,30 @@ setsockopt(td, uap)
return (kern_setsockopt(td, uap->s, uap->level, uap->name,
uap->val, UIO_USERSPACE, uap->valsize));
}
#ifdef __rtems__
int
setsockopt(int socket, int level, int option_name, const void *option_value,
socklen_t option_len)
{
struct thread *td = rtems_bsd_get_curthread_or_null();
struct setsockopt_args ua = {
.s = socket,
.level = level,
.name = option_name,
.val = __DECONST(void *, option_value),
.valsize = option_len
};
int error;
if (td != NULL) {
error = rtems_bsd_setsockopt(td, &ua);
} else {
error = ENOMEM;
}
return rtems_bsd_error_to_status_and_errno(error);
}
#endif /* __rtems__ */
int
kern_setsockopt(td, s, level, name, val, valseg, valsize)
@ -1553,8 +1585,17 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize)
}
/* ARGSUSED */
#ifndef __rtems__
int
getsockopt(td, uap)
#else /* __rtems__ */
static int
kern_getsockopt( struct thread *td, int s, int level, int name, void *val,
enum uio_seg valseg, socklen_t *valsize);
static int
rtems_bsd_getsockopt(td, uap)
#endif /* __rtems__ */
struct thread *td;
struct getsockopt_args /* {
int s;
@ -1580,6 +1621,30 @@ getsockopt(td, uap)
error = copyout(&valsize, uap->avalsize, sizeof (valsize));
return (error);
}
#ifdef __rtems__
int
getsockopt(int socket, int level, int option_name, void *__restrict
option_value, socklen_t *__restrict option_len)
{
struct thread *td = rtems_bsd_get_curthread_or_null();
struct getsockopt_args ua = {
.s = socket,
.level = level,
.name = option_name,
.val = (caddr_t) option_value,
.avalsize = option_len
};
int error;
if (td != NULL) {
error = rtems_bsd_getsockopt(td, &ua);
} else {
error = ENOMEM;
}
return rtems_bsd_error_to_status_and_errno(error);
}
#endif /* __rtems__ */
/*
* Kernel version of getsockopt.
@ -1634,6 +1699,7 @@ kern_getsockopt(td, s, level, name, val, valseg, valsize)
return (error);
}
#ifndef __rtems__
/*
* getsockname1() - Get socket name.
*/

View File

@ -382,15 +382,17 @@ struct bind_args {
char namelen_l_[PADL_(__socklen_t)]; __socklen_t namelen; char namelen_r_[PADR_(__socklen_t)];
#endif /* __rtems__ */
};
#ifndef __rtems__
struct setsockopt_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
char level_l_[PADL_(int)]; int level; char level_r_[PADR_(int)];
char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)];
char val_l_[PADL_(caddr_t)]; caddr_t val; char val_r_[PADR_(caddr_t)];
#ifndef __rtems__
char valsize_l_[PADL_(int)]; int valsize; char valsize_r_[PADR_(int)];
};
#else /* __rtems__ */
char valsize_l_[PADL_(__socklen_t)]; __socklen_t valsize; char valsize_r_[PADR_(__socklen_t)];
#endif /* __rtems__ */
};
struct listen_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
char backlog_l_[PADL_(int)]; int backlog; char backlog_r_[PADR_(int)];
@ -404,13 +406,19 @@ struct getrusage_args {
char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)];
char rusage_l_[PADL_(struct rusage *)]; struct rusage * rusage; char rusage_r_[PADR_(struct rusage *)];
};
#endif /* __rtems__ */
struct getsockopt_args {
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
char level_l_[PADL_(int)]; int level; char level_r_[PADR_(int)];
char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)];
char val_l_[PADL_(caddr_t)]; caddr_t val; char val_r_[PADR_(caddr_t)];
#ifndef __rtems__
char avalsize_l_[PADL_(int *)]; int * avalsize; char avalsize_r_[PADR_(int *)];
#else /* __rtems__ */
char avalsize_l_[PADL_(__socklen_t *)]; __socklen_t * avalsize; char avalsize_r_[PADR_(__socklen_t *)];
#endif /* __rtems__ */
};
#ifndef __rtems__
struct readv_args {
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
char iovp_l_[PADL_(struct iovec *)]; struct iovec * iovp; char iovp_r_[PADR_(struct iovec *)];

View File

@ -61,8 +61,12 @@ int bind(int, const struct sockaddr *, socklen_t);
int connect(int, const struct sockaddr *, socklen_t);
int getsockopt(int, int, int, void * __restrict, socklen_t * __restrict);
int listen(int, int);
int setsockopt(int, int, int, const void *, socklen_t);
int shutdown(int, int);
int socket(int, int, int);

View File

@ -619,140 +619,6 @@ done2:
return -1;
}
int
kern_setsockopt(td, s, level, name, val, valseg, valsize)
struct thread *td;
int s;
int level;
int name;
void *val;
enum uio_seg valseg;
socklen_t valsize;
{
int error;
struct socket *so;
struct sockopt sopt;
if (val == NULL && valsize != 0)
return (EFAULT);
if ((int)valsize < 0)
return (EINVAL);
sopt.sopt_dir = SOPT_SET;
sopt.sopt_level = level;
sopt.sopt_name = name;
sopt.sopt_val = val;
sopt.sopt_valsize = valsize;
switch (valseg) {
case UIO_USERSPACE:
sopt.sopt_td = td;
break;
case UIO_SYSSPACE:
sopt.sopt_td = NULL;
break;
default:
panic("kern_setsockopt called with bad valseg");
}
if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
error = EBADF;
return error;
}
CURVNET_SET(so->so_vnet);
error = sosetopt(so, &sopt);
CURVNET_RESTORE();
return(error);
}
int
setsockopt (int s, int level, int name, const void *val, socklen_t valsize)
{
struct thread *td;
int error;
td = curthread;
error = kern_setsockopt(td, s, level, name, val, UIO_USERSPACE, valsize);
if( error == 0 )
{
return error;
}
errno = error;
return -1;
}
int
kern_getsockopt(td, s, level, name, val, valseg, valsize)
struct thread *td;
int s;
int level;
int name;
void *val;
enum uio_seg valseg;
socklen_t *valsize;
{
int error;
struct socket *so;
struct sockopt sopt;
if (val == NULL)
*valsize = 0;
if ((int)*valsize < 0)
return (EINVAL);
sopt.sopt_dir = SOPT_GET;
sopt.sopt_level = level;
sopt.sopt_name = name;
sopt.sopt_val = val;
sopt.sopt_valsize = (size_t)*valsize; /* checked non-negative above */
switch (valseg) {
case UIO_USERSPACE:
sopt.sopt_td = td;
break;
case UIO_SYSSPACE:
sopt.sopt_td = NULL;
break;
default:
panic("kern_getsockopt called with bad valseg");
}
if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
error = EBADF;
return error;
}
CURVNET_SET(so->so_vnet);
error = sogetopt(so, &sopt);
CURVNET_RESTORE();
*valsize = sopt.sopt_valsize;
return (error);
}
int
getsockopt (int s, int level, int name, void *val, socklen_t *avalsize)
{
struct thread *td;
socklen_t valsize;
int error = 0;
td = curthread;
if (val) {
error = copyin(avalsize, &valsize, sizeof (valsize));
}
if( error == 0 )
{
error = kern_getsockopt(td, s, level, name, val, UIO_USERSPACE, &valsize);
if (error == 0)
error = copyout(&valsize, avalsize, sizeof (valsize));
}
if( error == 0 )
{
return error;
}
errno = error;
return -1;
}
int
kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
socklen_t *alen)

View File

@ -727,6 +727,106 @@ test_socket_accept(void)
assert(rtems_resource_snapshot_check(&snapshot));
}
static void
no_mem_socket_getsockopt_and_setsockopt(int fd)
{
int rv;
int optval;
socklen_t optlen;
errno = 0;
optlen = sizeof(optval);
rv = getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, &optlen);
assert(rv == -1);
assert(errno == ENOMEM);
errno = 0;
optlen = sizeof(optval);
rv = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
assert(rv == -1);
assert(errno == ENOMEM);
}
static void
test_socket_getsockopt_and_setsockopt(void)
{
rtems_resource_snapshot snapshot;
int optval;
socklen_t optlen;
int sd;
int rv;
puts("test socket getsockopt and setsockopt");
rtems_resource_snapshot_take(&snapshot);
sd = socket(PF_INET, SOCK_STREAM, 0);
assert(sd >= 0);
do_no_mem_test(no_mem_socket_getsockopt_and_setsockopt, sd);
errno = 0;
optlen = sizeof(optval);
rv = getsockopt(sd, SOL_SOCKET, -1, &optval, &optlen);
assert(rv == -1);
assert(errno == ENOPROTOOPT);
errno = 0;
optlen = sizeof(optval);
rv = setsockopt(sd, SOL_SOCKET, -1, &optval, optlen);
assert(rv == -1);
assert(errno == ENOPROTOOPT);
errno = 0;
optlen = sizeof(optval);
rv = getsockopt(sd, -1, SO_REUSEADDR, &optval, &optlen);
assert(rv == -1);
assert(errno == EINVAL);
errno = 0;
optlen = sizeof(optval);
rv = setsockopt(sd, -1, SO_REUSEADDR, &optval, optlen);
assert(rv == -1);
assert(errno == EINVAL);
optval = -1;
optlen = sizeof(optval);
rv = getsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, &optlen);
assert(rv == 0);
assert(optval == 0);
assert(optlen == sizeof(optval));
optval = 1;
optlen = sizeof(optval);
rv = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
assert(rv == 0);
optval = 0;
optlen = sizeof(optval);
rv = getsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, &optlen);
assert(rv == 0);
assert(optval != 0);
assert(optlen == sizeof(optval));
rv = close(sd);
assert(rv == 0);
errno = 0;
optlen = sizeof(optval);
rv = getsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, &optlen);
assert(rv == -1);
assert(errno == EBADF);
errno = 0;
optval = 0;
optlen = sizeof(optval);
rv = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
assert(rv == -1);
assert(errno == EBADF);
assert(rtems_resource_snapshot_check(&snapshot));
}
static void
test_main(void)
{
@ -740,6 +840,7 @@ test_main(void)
test_socket_connect();
test_socket_listen();
test_socket_accept();
test_socket_getsockopt_and_setsockopt();
puts("*** END OF " TEST_NAME " TEST ***");
exit(0);