Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Apr 2001 15:12:53 -0700 (PDT)
From:      Doug Ambrisko <ambrisko@ambrisko.com>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/26546: Add ioctl support to linux emulation and permit ethX syntax
Message-ID:  <200104132212.f3DMCrS41923@ambrisko.com>

next in thread | raw e-mail | index | archive | help

>Number:         26546
>Category:       kern
>Synopsis:       Add ioctl support to linux emulation and permit ethX syntax
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Apr 13 15:20:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Doug Ambrisko
>Release:        FreeBSD 4.3-RC i386
>Organization:
Whistle/IBM
>Environment:
System: FreeBSD server2.ambrisko.com 4.3-RC FreeBSD 4.3-RC #3: Sat Apr 7 14:18:35 PDT 2001 ambrisko@server2.ambrisko.com:/usr/src/sys/compile/SERVER i386

>Description:
	Running the Cisco binary only Aironet configuration tool only
	talks to "eth<d>" devices.  Since this is in the binary we 
	can't change it.  So I added a mapping function in the 
	emulation that iterates through the hardware ethernet 
	devices and use the number in "eth<d>" to count the iteration.

	Interesting side effect is that if you have a Linux version of
	ifconfig on your machine you can do ifconfig eth0 and it will
	work.

	I put this in a funtion to isolate the interface scan if
	it saw an interface argument of "eth" type.  The substition
	is then done for the real FreeBSD interface and then the
	FreeBSD ioctl is called.  When the FreeBSD ioctl returns
	it restores the original interface name and returns the 
	result.

	I also implement to "Device Private" ioctls that the Cisco
	utility uses to talk to the Aironet driver.

	With this and my Aironet changes you can run the configuration
	binaries from Cisco for Linux and do things like upgrade the
	firmware on the card and things like that.

>How-To-Repeat:

>Fix:

Index: compat/linux/linux_ioctl.c
===================================================================
RCS file: /cvs/freebsd/src/sys/compat/linux/linux_ioctl.c,v
retrieving revision 1.55.2.4
diff -c -r1.55.2.4 linux_ioctl.c
*** linux_ioctl.c	2000/11/03 13:11:18	1.55.2.4
--- linux_ioctl.c	2001/04/13 21:58:45
***************
*** 71,76 ****
--- 71,77 ----
  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 struct linux_ioctl_handler cdrom_handler =
  { linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX };
***************
*** 84,89 ****
--- 85,92 ----
  { linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX };
  static struct linux_ioctl_handler termio_handler =
  { linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX };
+ static struct linux_ioctl_handler private_handler =
+ { linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX };
  
  DATA_SET(linux_ioctl_handler_set, cdrom_handler);
  DATA_SET(linux_ioctl_handler_set, console_handler);
***************
*** 91,96 ****
--- 94,100 ----
  DATA_SET(linux_ioctl_handler_set, socket_handler);
  DATA_SET(linux_ioctl_handler_set, sound_handler);
  DATA_SET(linux_ioctl_handler_set, termio_handler);
+ DATA_SET(linux_ioctl_handler_set, private_handler);
  
  struct handler_element 
  {
***************
*** 1315,1321 ****
--- 1319,1374 ----
   * Socket related ioctls
   */
  
+ /*
+  * Map "eth<d>" into valid FreeBSD name of hardware ethernet devices
+  * via present devices
+  */
+ 
  static int
+ linux_eth_to_bsd_ioctl(struct proc *p, struct linux_ioctl_args *args)
+ {
+ 	struct	ifnet *ifp;
+ 	int	count;
+ 	int	i;
+ 	int	remapped = 0;
+ 	char	temp[IFNAMSIZ];
+ 	char	*ptr;
+ 
+ 	ptr = (char *)(args->arg);
+ 
+ 	if ((strncmp(ptr,"eth",3)) == 0){
+ 		bcopy(ptr, temp, sizeof(temp));
+ 		count = ptr[3] - '0';
+ 
+ 		for (i=0, ifp = TAILQ_FIRST(&ifnet);
+ 		     ifp != NULL;
+ 		     ifp = TAILQ_NEXT(ifp, if_link)) {
+ 	    
+ 			if ((ifp->if_flags &
+ 			     (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)
+ 			    ) != IFF_BROADCAST)
+ 				continue;
+ 
+ 			if(i==count){
+ 				snprintf(ptr, IFNAMSIZ,
+ 				"%s%d", ifp->if_name, ifp->if_unit);
+ 
+ 				remapped = 1;
+ 				break;
+ 			}
+ 			i++;
+ 		}
+ 	}
+ 
+ 	i = ioctl(p, (struct ioctl_args *)args);
+ 	
+ 	if (remapped)
+ 		bcopy(temp, ptr, sizeof(temp));
+ 
+ 	return i;
+ }
+ 
+ static int
  linux_ioctl_socket(struct proc *p, struct linux_ioctl_args *args)
  {
  
***************
*** 1323,1371 ****
  
  	case LINUX_FIOSETOWN:
  		args->cmd = FIOSETOWN;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCSPGRP:
  		args->cmd = SIOCSPGRP;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_FIOGETOWN:
  		args->cmd = FIOGETOWN;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCGPGRP:
  		args->cmd = SIOCGPGRP;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCATMARK:
  		args->cmd = SIOCATMARK;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	/* LINUX_SIOCGSTAMP */
  
  	case LINUX_SIOCGIFCONF:
  		args->cmd = OSIOCGIFCONF;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCGIFFLAGS:
  		args->cmd = SIOCGIFFLAGS;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCGIFADDR:
  		args->cmd = OSIOCGIFADDR;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCGIFDSTADDR:
  		args->cmd = OSIOCGIFDSTADDR;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCGIFBRDADDR:
  		args->cmd = OSIOCGIFBRDADDR;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCGIFNETMASK:
  		args->cmd = OSIOCGIFNETMASK;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCGIFHWADDR: {
  		int ifn;
--- 1376,1424 ----
  
  	case LINUX_FIOSETOWN:
  		args->cmd = FIOSETOWN;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCSPGRP:
  		args->cmd = SIOCSPGRP;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_FIOGETOWN:
  		args->cmd = FIOGETOWN;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCGPGRP:
  		args->cmd = SIOCGPGRP;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCATMARK:
  		args->cmd = SIOCATMARK;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	/* LINUX_SIOCGSTAMP */
  
  	case LINUX_SIOCGIFCONF:
  		args->cmd = OSIOCGIFCONF;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCGIFFLAGS:
  		args->cmd = SIOCGIFFLAGS;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCGIFADDR:
  		args->cmd = OSIOCGIFADDR;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCGIFDSTADDR:
  		args->cmd = OSIOCGIFDSTADDR;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCGIFBRDADDR:
  		args->cmd = OSIOCGIFBRDADDR;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCGIFNETMASK:
  		args->cmd = OSIOCGIFNETMASK;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCGIFHWADDR: {
  		int ifn;
***************
*** 1399,1410 ****
  
  	case LINUX_SIOCADDMULTI:
  		args->cmd = SIOCADDMULTI;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	case LINUX_SIOCDELMULTI:
  		args->cmd = SIOCDELMULTI;
! 		return (ioctl(p, (struct ioctl_args *)args));
  
  	}
  
  	return (ENOIOCTL);
--- 1452,1484 ----
  
  	case LINUX_SIOCADDMULTI:
  		args->cmd = SIOCADDMULTI;
! 		return linux_eth_to_bsd_ioctl(p, args);
  
  	case LINUX_SIOCDELMULTI:
  		args->cmd = SIOCDELMULTI;
! 		return linux_eth_to_bsd_ioctl(p, args);
! 	}
  
+ 	return (ENOIOCTL);
+ }
+ 
+ /*
+  * Device Private ioctl 
+  */
+ 
+ static int
+ linux_ioctl_private(struct proc *p, struct linux_ioctl_args *args)
+ {
+ 
+ 	switch (args->cmd & 0xffff) {
+   
+ 	case SIOCDEVPRIVATE:
+ 		args->cmd = SIOCGPRIVATE_0;
+ 		return linux_eth_to_bsd_ioctl(p, args);
+ 
+ 	case SIOCDEVPRIVATE+1:
+ 		args->cmd = SIOCGPRIVATE_1;
+ 		return linux_eth_to_bsd_ioctl(p, args);
  	}
  
  	return (ENOIOCTL);
Index: compat/linux/linux_ioctl.h
===================================================================
RCS file: /cvs/freebsd/src/sys/compat/linux/linux_ioctl.h,v
retrieving revision 1.4.2.1
diff -c -r1.4.2.1 linux_ioctl.h
*** linux_ioctl.h	2000/10/30 10:51:37	1.4.2.1
--- linux_ioctl.h	2001/04/13 21:58:45
***************
*** 143,148 ****
--- 143,162 ----
  #define	LINUX_IOCTL_SOCKET_MIN	LINUX_FIOSETOWN
  #define	LINUX_IOCTL_SOCKET_MAX	LINUX_SIOCDELMULTI
  
+ /* Device private ioctl calls */
+ 
+ /*
+  *      These 16 ioctls are available to devices via the do_ioctl() device
+  *      vector. Each device should include this file and redefine these names
+  *      as their own. Because these are device dependent it is a good idea
+  *      _NOT_ to issue them to random objects and hope.
+  */
+ 
+ #define SIOCDEVPRIVATE  0x89F0  /* to 89FF */
+ 
+ #define	LINUX_IOCTL_PRIVATE_MIN	SIOCDEVPRIVATE
+ #define	LINUX_IOCTL_PRIVATE_MAX	SIOCDEVPRIVATE+0xf
+ 
  /*
   * sound
   */
Index: sys/sockio.h
===================================================================
RCS file: /cvs/freebsd/src/sys/sys/sockio.h,v
retrieving revision 1.14.2.2
diff -c -r1.14.2.2 sockio.h
*** sockio.h	2000/08/22 18:06:21	1.14.2.2
--- sockio.h	2001/04/13 21:58:45
***************
*** 98,101 ****
--- 98,104 ----
  #define	SIOCGIFSTATUS	_IOWR('i', 59, struct ifstat)	/* get IF status */
  #define	SIOCSIFLLADDR	_IOW('i', 60, struct ifreq)	/* set link level addr */
  
+ #define	SIOCGPRIVATE_0	_IOWR('i', 80, struct ifreq)	/* Linux Private + 0 */
+ #define	SIOCGPRIVATE_1	_IOWR('i', 81, struct ifreq)	/* Linux Private + 1 */
+ 
  #endif /* !_SYS_SOCKIO_H_ */
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200104132212.f3DMCrS41923>