Subject: kern/9169: Linux emulation of SIOCGIFHWADDR
To: None <gnats-bugs@gnats.netbsd.org>
From: None <salvet@ics.muni.cz>
List: netbsd-bugs
Date: 01/11/2000 13:24:47
>Number:         9169
>Category:       kern
>Synopsis:       Linux ICA client does now work
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Jan 11 13:24:01 2000
>Last-Modified:
>Originator:     Zdenek Salvet
>Organization:
Institute of Computer Science, Masaryk University, Czech Republic
>Release:        1.4K
>Environment:
NetBSD/i386 1.4K


>Description:

1)
Linux ICA client (http://download.citrix.com/download.asp?client=LINUX)
does not work, because it is not able to get the MAC address
of the network interface with SIOCGIFHWADDR ioctl - it uses real interface
name, not eth*.

2) Linux kernel uses ENODEV errno for requests to unknown interfaces

>How-To-Repeat:
>Fix:

--- sys/compat/linux/common/linux_socket.c.orig	Tue Jan 11 21:15:25 2000
+++ sys/compat/linux/common/linux_socket.c	Tue Jan 11 22:07:51 2000
@@ -500,9 +500,39 @@
 	lreq.if_name[IF_NAME_LEN-1] = '\0';		/* just in case */
 
 	/*
-	 * Only support finding addresses for "ethX".  Should we
-	 * do otherwise? XXX
+	 * Try real interface name first, then fake "ethX"
 	 */
+	for (ifp = ifnet.tqh_first, found = 0;
+	     ifp != 0 && !found;
+	     ifp = ifp->if_list.tqe_next) {
+		if (strcmp(lreq.if_name, ifp->if_xname))
+			/* not this interface */
+			continue;
+		found=1;           
+		if ((ifa = ifp->if_addrlist.tqh_first) != 0) {
+			for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
+				sadl = (struct sockaddr_dl *)ifa->ifa_addr;
+				/* only return ethernet addresses */
+				/* XXX what about FDDI, etc. ? */
+				if (sadl->sdl_family != AF_LINK ||
+				    sadl->sdl_type != IFT_ETHER)
+					continue;
+				memcpy((caddr_t)&lreq.hwaddr.sa_data,
+				       LLADDR(sadl),
+				       MIN(sadl->sdl_alen,
+					   sizeof(lreq.hwaddr.sa_data)));
+				lreq.hwaddr.sa_family =
+					sadl->sdl_family;
+				error = copyout((caddr_t)&lreq, data,
+						sizeof(lreq));
+				goto out; 
+			}
+		} else {
+			error = ENODEV;
+			goto out;
+		}
+	}
+
 	if (lreq.if_name[0] == 'e' &&
 	    lreq.if_name[1] == 't' &&
 	    lreq.if_name[2] == 'h') {
@@ -546,8 +576,8 @@
 				}
 		}
 	} else
-		/* not an "eth*" name */
-		error = EINVAL;
+		/* unknown interface, not even an "eth*" name */
+		error = ENODEV;
     
 out:
 	FILE_UNUSE(fp, p);
>Audit-Trail:
>Unformatted: