diff -ruh sys/amd64/linux32/syscalls.master sys/amd64/linux32/syscalls.master --- sys/amd64/linux32/syscalls.master Wed Jul 4 11:47:57 2007 +++ sys/amd64/linux32/syscalls.master Fri Jun 29 08:50:04 2007 @@ -136,9 +137,8 @@ 72 AUE_NULL MSTD { int linux_sigsuspend(l_int hist0, \ l_int hist1, l_osigset_t mask); } 73 AUE_NULL MSTD { int linux_sigpending(l_osigset_t *mask); } -74 AUE_NULL MNOPROTO { int osethostname(char *hostname, \ - u_int len); } osethostname \ - sethostname_args int +74 AUE_NULL MSTD { int linux_sethostname(char *hostname, \ + u_int len); } 75 AUE_NULL MSTD { int linux_setrlimit(l_uint resource, \ struct l_rlimit *rlim); } 76 AUE_NULL MSTD { int linux_old_getrlimit(l_uint resource, \ @@ -173,7 +174,7 @@ 91 AUE_NULL MNOPROTO { int munmap(caddr_t addr, int len); } 92 AUE_NULL MSTD { int linux_truncate(char *path, \ l_ulong length); } -93 AUE_NULL MNOPROTO { int oftruncate(int fd, long length); } +93 AUE_NULL MSTD { int linux_ftruncate(int fd, long length); } 94 AUE_NULL MNOPROTO { int fchmod(int fd, int mode); } 95 AUE_NULL MNOPROTO { int fchown(int fd, int uid, int gid); } 96 AUE_NULL MSTD { int linux_getpriority(int which, int who); } diff -ruh sys/compat/linux/linux_file.c sys/compat/linux/linux_file.c --- sys/compat/linux/linux_file.c Wed Jul 4 12:18:55 2007 +++ sys/compat/linux/linux_file.c Wed Jun 20 13:18:30 2007 @@ -683,6 +683,21 @@ } int +linux_ftruncate(struct thread *td, struct linux_ftruncate_args *args) +{ + struct ftruncate_args /* { + int fd; + int pad; + off_t length; + } */ nuap; + + nuap.fd = args->fd; + nuap.pad = 0; + nuap.length = args->length; + return (ftruncate(td, &nuap)); +} + +int linux_link(struct thread *td, struct linux_link_args *args) { char *path, *to; diff -ruh sys/compat/linux/linux_ioctl.c sys/compat/linux/linux_ioctl.c --- sys/compat/linux/linux_ioctl.c Wed Jul 4 11:47:57 2007 +++ sys/compat/linux/linux_ioctl.c Wed Jun 20 13:27:49 2007 @@ -1014,7 +1014,15 @@ args->cmd = TIOCCBRK; error = (ioctl(td, (struct ioctl_args *)args)); break; - + case LINUX_TIOCGPTN: { + int nb; + + error = fo_ioctl(fp, LINUX_TIOCGPTN, (caddr_t)&nb, td->td_ucred, td); + if (!error) + error = copyout(&nb, (void *)args->arg, + sizeof(int)); + break; + } default: error = ENOIOCTL; break; @@ -2281,6 +2289,29 @@ return (ENOENT); } + + /* +* If we fault in bsd_to_linux_ifreq() then we will fault when we call +* the native ioctl(). Thus, we don't really need to check the return +* value of this function. +*/ +static int +bsd_to_linux_ifreq(struct ifreq *arg) +{ + struct ifreq ifr; + size_t ifr_len = sizeof(struct ifreq); + int error; + + if ((error = copyin(arg, &ifr, ifr_len))) + return (error); + + *(u_short *)&ifr.ifr_addr = ifr.ifr_addr.sa_family; + + error = copyout(&ifr, arg, ifr_len); + + return (error); +} + /* * Socket related ioctls */ @@ -2412,8 +2443,9 @@ break; case LINUX_SIOCGIFADDR: - args->cmd = OSIOCGIFADDR; + args->cmd = SIOCGIFADDR; error = ioctl(td, (struct ioctl_args *)args); + bsd_to_linux_ifreq((struct ifreq *)args->arg); break; case LINUX_SIOCSIFADDR: @@ -2423,18 +2455,21 @@ break; case LINUX_SIOCGIFDSTADDR: - args->cmd = OSIOCGIFDSTADDR; + args->cmd = SIOCGIFDSTADDR; error = ioctl(td, (struct ioctl_args *)args); + bsd_to_linux_ifreq((struct ifreq *)args->arg); break; case LINUX_SIOCGIFBRDADDR: - args->cmd = OSIOCGIFBRDADDR; + args->cmd = SIOCGIFBRDADDR; error = ioctl(td, (struct ioctl_args *)args); + bsd_to_linux_ifreq((struct ifreq *)args->arg); break; case LINUX_SIOCGIFNETMASK: - args->cmd = OSIOCGIFNETMASK; + args->cmd = SIOCGIFNETMASK; error = ioctl(td, (struct ioctl_args *)args); + bsd_to_linux_ifreq((struct ifreq *)args->arg); break; case LINUX_SIOCSIFNETMASK: diff -ruh sys/compat/linux/linux_ioctl.h sys/compat/linux/linux_ioctl.h --- sys/compat/linux/linux_ioctl.h Wed Jul 4 11:47:57 2007 +++ sys/compat/linux/linux_ioctl.h Wed Jun 20 13:23:47 2007 @@ -396,6 +396,8 @@ #define LINUX_TIOCSBRK 0x5427 #define LINUX_TIOCCBRK 0x5428 +#define LINUX_TIOCGPTN 0x5430 + #ifdef __alpha__ #define LINUX_FIOCLEX 0x6601 #define LINUX_FIONCLEX 0x6602 diff -ruh sys/compat/linux/linux_misc.c sys/compat/linux/linux_misc.c --- sys/compat/linux/linux_misc.c Wed Jul 4 12:18:55 2007 +++ sys/compat/linux/linux_misc.c Mon Jun 25 09:25:55 2007 @@ -1468,3 +1500,20 @@ td->td_retval[0] = 20 - td->td_retval[0]; return error; } + +int +linux_sethostname(struct thread *td, struct linux_sethostname_args *args) +{ + int name[2]; + +#ifdef DEBUG + if (ldebug(sethostname)) + printf(ARGS(sethostname, "*, %i"), args->len); +#endif + + name[0] = CTL_KERN; + name[1] = KERN_HOSTNAME; + return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname, + args->len, 0, 0)); +} + diff -ruh sys/compat/linux/linux_socket.c sys/compat/linux/linux_socket.c --- sys/compat/linux/linux_socket.c Wed Jul 4 12:18:55 2007 +++ sys/compat/linux/linux_socket.c Fri May 11 15:49:38 2007 @@ -358,6 +358,48 @@ return ret_flags; } +/* +* If bsd_to_linux_sockaddr() or linux_to_bsd_sockaddr() faults, then the +* native syscall will fault. Thus, we don't really need to check the +* return values for these functions. +*/ + +static int +bsd_to_linux_sockaddr(struct sockaddr *arg) +{ + struct sockaddr sa; + size_t sa_len = sizeof(struct sockaddr); + int error; + + if ((error = copyin(arg, &sa, sa_len))) + return (error); + + *(u_short *)&sa = sa.sa_family; + + error = copyout(&sa, arg, sa_len); + + return (error); +} + +static int +linux_to_bsd_sockaddr(struct sockaddr *arg, int len) +{ + struct sockaddr sa; + size_t sa_len = sizeof(struct sockaddr); + int error; + + if ((error = copyin(arg, &sa, sa_len))) + return (error); + + sa.sa_family = *(sa_family_t *)&sa; + sa.sa_len = len; + + error = copyout(&sa, arg, sa_len); + + return (error); +} + + static int linux_sa_put(struct osockaddr *osa) { @@ -589,7 +631,11 @@ if (error) return (error); - return (kern_bind(td, linux_args.s, sa)); + error = kern_bind(td, linux_args.s, sa); + free(sa, M_SONAME); + if (error == EADDRNOTAVAIL && linux_args.namelen != sizeof(struct sockaddr_in)) + return (EINVAL); + return (error); } struct linux_connect_args { @@ -623,6 +669,7 @@ return (error); error = kern_connect(td, linux_args.s, sa); + free(sa, M_SONAME); if (error != EISCONN) return (error); @@ -692,9 +739,6 @@ struct sockaddr * __restrict name; socklen_t * __restrict anamelen; } */ bsd_args; - struct close_args /* { - int fd; - } */ c_args; int error, fd; if ((error = copyin(args, &linux_args, sizeof(linux_args)))) @@ -704,14 +748,17 @@ /* XXX: */ bsd_args.name = (struct sockaddr * __restrict)PTRIN(linux_args.addr); bsd_args.anamelen = PTRIN(linux_args.namelen);/* XXX */ - error = oaccept(td, &bsd_args); - if (error) + error = accept(td, &bsd_args); + bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.name); + if (error) { + if (error == EFAULT && linux_args.namelen != sizeof(struct sockaddr_in)) + return (EINVAL); return (error); + } if (linux_args.addr) { error = linux_sa_put(PTRIN(linux_args.addr)); if (error) { - c_args.fd = td->td_retval[0]; - (void)close(td, &c_args); + (void)kern_close(td, td->td_retval[0]); return (error); } } @@ -751,7 +798,8 @@ /* XXX: */ bsd_args.asa = (struct sockaddr * __restrict)PTRIN(linux_args.addr); bsd_args.alen = PTRIN(linux_args.namelen); /* XXX */ - error = ogetsockname(td, &bsd_args); + error = getsockname(td, &bsd_args); + bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa); if (error) return (error); error = linux_sa_put(PTRIN(linux_args.addr)); @@ -770,7 +818,7 @@ linux_getpeername(struct thread *td, struct linux_getpeername_args *args) { struct linux_getpeername_args linux_args; - struct ogetpeername_args /* { + struct getpeername_args /* { int fdes; caddr_t asa; int *alen; @@ -781,9 +829,10 @@ return (error); bsd_args.fdes = linux_args.s; - bsd_args.asa = (caddr_t)PTRIN(linux_args.addr); + bsd_args.asa = (struct sockaddr *)PTRIN(linux_args.addr); bsd_args.alen = (int *)PTRIN(linux_args.namelen); - error = ogetpeername(td, &bsd_args); + error = getpeername(td, &bsd_args); + bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa); if (error) return (error); error = linux_sa_put(PTRIN(linux_args.addr)); @@ -955,7 +1004,11 @@ /* XXX: */ bsd_args.from = (struct sockaddr * __restrict)PTRIN(linux_args.from); bsd_args.fromlenaddr = PTRIN(linux_args.fromlen);/* XXX */ - error = orecvfrom(td, &bsd_args); + + linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.from, len); + error = recvfrom(td, &bsd_args); + bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.from); + if (error) return (error); if (linux_args.from) { @@ -1034,10 +1087,19 @@ if ((error = copyin(args, &linux_args, sizeof(linux_args)))) return (error); + if ((error = copyin(PTRIN(args->msg), &msg, sizeof (msg)))) + return (error); + bsd_args.s = linux_args.s; bsd_args.msg = PTRIN(linux_args.msg); bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); - error = recvmsg(td, &bsd_args); + if (msg.msg_name) { + linux_to_bsd_sockaddr((struct sockaddr *)msg.msg_name, + msg.msg_namelen); + error = recvmsg(td, &bsd_args); + bsd_to_linux_sockaddr((struct sockaddr *)msg.msg_name); + } else + error = recvmsg(td, &bsd_args); if (error) return (error); @@ -1120,12 +1182,21 @@ break; } if (name == -1) - return (EINVAL); + return (ENOPROTOOPT); bsd_args.name = name; bsd_args.val = PTRIN(linux_args.optval); bsd_args.valsize = linux_args.optlen; - return (setsockopt(td, &bsd_args)); + + if (name == IPV6_NEXTHOP) { + linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.val, + bsd_args.valsize); + error = setsockopt(td, &bsd_args); + bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val); + } else + error = setsockopt(td, &bsd_args); + + return (error); } struct linux_getsockopt_args { @@ -1175,7 +1246,14 @@ bsd_args.name = name; bsd_args.val = PTRIN(linux_args.optval); bsd_args.avalsize = PTRIN(linux_args.optlen); - return (getsockopt(td, &bsd_args)); + + if (name == IPV6_NEXTHOP) { + error = getsockopt(td, &bsd_args); + bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val); + } else + error = getsockopt(td, &bsd_args); + + return (error); } int diff -ruh sys/i386/linux/syscalls.master sys/i386/linux/syscalls.master --- sys/i386/linux/syscalls.master Wed Jul 4 11:47:57 2007 +++ sys/i386/linux/syscalls.master Tue Jun 26 12:57:36 2007 @@ -139,9 +139,8 @@ 72 AUE_NULL MSTD { int linux_sigsuspend(l_int hist0, \ l_int hist1, l_osigset_t mask); } 73 AUE_NULL MSTD { int linux_sigpending(l_osigset_t *mask); } -74 AUE_NULL MNOPROTO { int osethostname(char *hostname, \ - u_int len); } osethostname \ - sethostname_args int +74 AUE_NULL MSTD { int linux_sethostname(char *hostname, \ + u_int len); } 75 AUE_NULL MSTD { int linux_setrlimit(l_uint resource, \ struct l_rlimit *rlim); } 76 AUE_NULL MSTD { int linux_old_getrlimit(l_uint resource, \ @@ -172,7 +172,7 @@ 91 AUE_NULL MNOPROTO { int munmap(caddr_t addr, int len); } 92 AUE_NULL MSTD { int linux_truncate(char *path, \ l_ulong length); } -93 AUE_NULL MNOPROTO { int oftruncate(int fd, long length); } +93 AUE_NULL MSTD { int linux_ftruncate(int fd, long length); } 94 AUE_NULL MNOPROTO { int fchmod(int fd, int mode); } 95 AUE_NULL MNOPROTO { int fchown(int fd, int uid, int gid); } 96 AUE_NULL MSTD { int linux_getpriority(int which, int who); }