summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux/linux_socket.c
diff options
context:
space:
mode:
authordwmalone <dwmalone@FreeBSD.org>2004-07-17 21:06:36 +0000
committerdwmalone <dwmalone@FreeBSD.org>2004-07-17 21:06:36 +0000
commitc8c1b8f415a3f8e57219cf3587707d7d24b8d582 (patch)
treedca356ba37d0e4e58bfdf5b38929557fe4c9839d /sys/compat/linux/linux_socket.c
parent7beb6d42ceb4bcb8294f42ff6a0a292e434bcc88 (diff)
downloadFreeBSD-src-c8c1b8f415a3f8e57219cf3587707d7d24b8d582.zip
FreeBSD-src-c8c1b8f415a3f8e57219cf3587707d7d24b8d582.tar.gz
Add a kern_setsockopt and kern_getsockopt which can read the option
values from either user land or from the kernel. Use them for [gs]etsockopt and to clean up some calls to [gs]etsockopt in the Linux emulation code that uses the stackgap.
Diffstat (limited to 'sys/compat/linux/linux_socket.c')
-rw-r--r--sys/compat/linux/linux_socket.c84
1 files changed, 19 insertions, 65 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index c73a57a..85c71a6 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -402,35 +402,14 @@ bad:
/* Return 0 if IP_HDRINCL is set for the given socket. */
static int
-linux_check_hdrincl(struct thread *td, caddr_t *sg, int s)
+linux_check_hdrincl(struct thread *td, int s)
{
- struct getsockopt_args /* {
- int s;
- int level;
- int name;
- void * __restrict val;
- socklen_t * __restrict avalsize;
- } */ bsd_args;
- void * __restrict val;
- socklen_t * __restrict valsize;
int error, optval, size_val;
- val = stackgap_alloc(sg, sizeof(size_val));
- valsize = stackgap_alloc(sg, sizeof(socklen_t));
-
- size_val = sizeof(val);
- if ((error = copyout(&size_val, valsize, sizeof(size_val))))
- return (error);
-
- bsd_args.s = s;
- bsd_args.level = IPPROTO_IP;
- bsd_args.name = IP_HDRINCL;
- bsd_args.val = val;
- bsd_args.avalsize = valsize;
- if ((error = getsockopt(td, &bsd_args)))
- return (error);
-
- if ((error = copyin(val, &optval, sizeof(optval))))
+ size_val = sizeof(optval);
+ error = kern_getsockopt(td, s, IPPROTO_IP, IP_HDRINCL,
+ &optval, UIO_SYSSPACE, &size_val);
+ if (error)
return (error);
return (optval == 0);
@@ -461,6 +440,7 @@ linux_sendto_hdrincl(struct thread *td, caddr_t *sg, struct linux_sendto_args *l
#define linux_ip_copysize 8
struct ip *packet;
+ caddr_t sg = stackgap_init();
struct msghdr msg;
struct iovec aiov[2];
int error;
@@ -515,13 +495,6 @@ linux_socket(struct thread *td, struct linux_socket_args *args)
int type;
int protocol;
} */ bsd_args;
- struct setsockopt_args /* {
- int s;
- int level;
- int name;
- caddr_t val;
- int valsize;
- } */ bsd_setsockopt_args;
int error;
int retval_socket;
@@ -540,21 +513,12 @@ linux_socket(struct thread *td, struct linux_socket_args *args)
&& bsd_args.domain == AF_INET
&& retval_socket >= 0) {
/* It's a raw IP socket: set the IP_HDRINCL option. */
- caddr_t sg;
- int *hdrincl;
-
- sg = stackgap_init();
- hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl));
- *hdrincl = 1;
- bsd_setsockopt_args.s = td->td_retval[0];
- bsd_setsockopt_args.level = IPPROTO_IP;
- bsd_setsockopt_args.name = IP_HDRINCL;
- bsd_setsockopt_args.val = (caddr_t)hdrincl;
- bsd_setsockopt_args.valsize = sizeof(*hdrincl);
- /* We ignore any error returned by setsockopt() */
- setsockopt(td, &bsd_setsockopt_args);
- /* Copy back the return value from socket() */
- td->td_retval[0] = bsd_setsockopt_args.s;
+ int hdrincl;
+
+ hdrincl = 1;
+ /* We ignore any error returned by kern_setsockopt() */
+ kern_setsockopt(td, td->td_retval[0], IPPROTO_IP, IP_HDRINCL,
+ &hdrincl, UIO_SYSSPACE, sizeof(hdrincl));
}
#ifdef INET6
/*
@@ -571,21 +535,12 @@ linux_socket(struct thread *td, struct linux_socket_args *args)
&& ip6_v6only
#endif
) {
- caddr_t sg;
- int *v6only;
-
- sg = stackgap_init();
- v6only = (int *)stackgap_alloc(&sg, sizeof(*v6only));
- *v6only = 0;
- bsd_setsockopt_args.s = td->td_retval[0];
- bsd_setsockopt_args.level = IPPROTO_IPV6;
- bsd_setsockopt_args.name = IPV6_V6ONLY;
- bsd_setsockopt_args.val = (caddr_t)v6only;
- bsd_setsockopt_args.valsize = sizeof(*v6only);
+ int v6only;
+
+ v6only = 0;
/* We ignore any error returned by setsockopt() */
- setsockopt(td, &bsd_setsockopt_args);
- /* Copy back the return value from socket() */
- td->td_retval[0] = bsd_setsockopt_args.s;
+ kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY,
+ &v6only, UIO_SYSSPACE, sizeof(v6only));
}
#endif
@@ -916,15 +871,14 @@ linux_sendto(struct thread *td, struct linux_sendto_args *args)
struct linux_sendto_args linux_args;
struct msghdr msg;
struct iovec aiov;
- caddr_t sg = stackgap_init();
int error;
if ((error = copyin(args, &linux_args, sizeof(linux_args))))
return (error);
- if (linux_check_hdrincl(td, &sg, linux_args.s) == 0)
+ if (linux_check_hdrincl(td, linux_args.s) == 0)
/* IP_HDRINCL set, tweak the packet before sending */
- return (linux_sendto_hdrincl(td, &sg, &linux_args));
+ return (linux_sendto_hdrincl(td, &linux_args));
msg.msg_name = linux_args.to;
msg.msg_namelen = linux_args.tolen;
OpenPOWER on IntegriCloud