1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-17 15:27:36 +00:00

Deal with a few issues that cropped up following the recent changes

to the code for translating socket and private ioctls:

- Only perform socket ioctl translation if the file descriptor is a
  socket.
- Treat socket ioctls on non-sockets specially, and for now assume
  that these are directed at a tap/vmnet device, so translate the
  ioctl numbers as appropriate (the way if_tap abuses some socket
  ioctls to pass non-ifreq data is utterly bogus, but this is how
  VMware on FreeBSD has always "worked"; I will deal with this
  later).
- Add (untested) support for translating SIOCSIFADDR.
- In all cases where we fail to translate an ioctl, return ENOIOCTL
  so that other handlers have a chance to do the translation.

This should fix the "/dev/vmnet1: Invalid argument" errors that
users of VMware were experiencing, though I have only verified this
on RELENG_4.

Submitted by:	des (mostly)
MFC after:	3 days
This commit is contained in:
Ian Dowse 2001-11-19 15:43:50 +00:00
parent 123f65b0e9
commit b0cb4883b1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=86607
2 changed files with 70 additions and 14 deletions

View File

@ -67,6 +67,7 @@ static linux_ioctl_function_t linux_ioctl_socket;
static linux_ioctl_function_t linux_ioctl_sound;
static linux_ioctl_function_t linux_ioctl_termio;
static linux_ioctl_function_t linux_ioctl_private;
static linux_ioctl_function_t linux_ioctl_special;
static struct linux_ioctl_handler cdrom_handler =
{ linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX };
@ -1726,9 +1727,10 @@ linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
return (ENOIOCTL);
}
#define IFP_IS_ETH(ifp) ((ifp->if_flags & \
(IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST)) == \
IFF_BROADCAST)
/*
* Criteria for interface name translation
*/
#define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
/*
* Construct the Linux name for an interface
@ -1920,7 +1922,8 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
{
char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ];
struct ifnet *ifp;
int error;
struct file *fp;
int error, type;
KASSERT(LINUX_IFNAMSIZ == IFNAMSIZ,
(__FUNCTION__ "(): LINUX_IFNAMSIZ != IFNAMSIZ"));
@ -1928,6 +1931,27 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
ifp = NULL;
error = 0;
mtx_lock(&Giant);
if ((error = fget(td, args->fd, &fp)) != 0) {
mtx_unlock(&Giant);
return (error);
}
type = fp->f_type;
fdrop(fp, td);
mtx_unlock(&Giant);
if (type != DTYPE_SOCKET) {
/* not a socket - probably a tap / vmnet device */
switch (args->cmd) {
case LINUX_SIOCGIFADDR:
case LINUX_SIOCSIFADDR:
case LINUX_SIOCGIFFLAGS:
return (linux_ioctl_special(td, args));
default:
return (ENOIOCTL);
}
}
switch (args->cmd & 0xffff) {
case LINUX_FIOGETOWN:
@ -1947,6 +1971,7 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
case LINUX_SIOCGIFFLAGS:
case LINUX_SIOCGIFADDR:
case LINUX_SIOCSIFADDR:
case LINUX_SIOCGIFDSTADDR:
case LINUX_SIOCGIFBRDADDR:
case LINUX_SIOCGIFNETMASK:
@ -2031,6 +2056,12 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
error = ioctl(td, (struct ioctl_args *)args);
break;
case LINUX_SIOCSIFADDR:
/* XXX probably doesn't work, included for completeness */
args->cmd = SIOCSIFADDR;
error = ioctl(td, (struct ioctl_args *)args);
break;
case LINUX_SIOCGIFDSTADDR:
args->cmd = OSIOCGIFDSTADDR;
error = ioctl(td, (struct ioctl_args *)args);
@ -2113,24 +2144,48 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
static int
linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
{
struct filedesc *fdp;
struct file *fp;
int type;
int error, type;
/* XXX is it sufficient to PROC_LOCK td->td_proc? */
mtx_lock(&Giant);
fdp = td->td_proc->p_fd;
if (args->fd >= fdp->fd_nfiles ||
(fp = fdp->fd_ofiles[args->fd]) == NULL) {
if ((error = fget(td, args->fd, &fp)) != 0) {
mtx_unlock(&Giant);
return (EBADF);
} else {
type = fp->f_type;
return (error);
}
type = fp->f_type;
fdrop(fp, td);
mtx_unlock(&Giant);
if (type == DTYPE_SOCKET)
return (linux_ioctl_socket(td, args));
return (ioctl(td, (struct ioctl_args *)args));
return (ENOIOCTL);
}
/*
* Special ioctl handler
*/
static int
linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args)
{
int error;
switch (args->cmd) {
case LINUX_SIOCGIFADDR:
args->cmd = SIOCGIFADDR;
error = ioctl(td, (struct ioctl_args *)args);
break;
case LINUX_SIOCSIFADDR:
args->cmd = SIOCSIFADDR;
error = ioctl(td, (struct ioctl_args *)args);
break;
case LINUX_SIOCGIFFLAGS:
args->cmd = SIOCGIFFLAGS;
error = ioctl(td, (struct ioctl_args *)args);
break;
default:
error = ENOIOCTL;
}
return (error);
}
/*

View File

@ -166,6 +166,7 @@
#define LINUX_SIOCGIFCONF 0x8912
#define LINUX_SIOCGIFFLAGS 0x8913
#define LINUX_SIOCGIFADDR 0x8915
#define LINUX_SIOCSIFADDR 0x8916
#define LINUX_SIOCGIFDSTADDR 0x8917
#define LINUX_SIOCGIFBRDADDR 0x8919
#define LINUX_SIOCGIFNETMASK 0x891b