Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Aug 2004 20:03:14 +0900
From:      Pyun YongHyeon <yongari@kt-is.co.kr>
To:        sparc64@freebsd.org
Subject:   Re: ifconfig(8) mediaopt bug and temporary fix
Message-ID:  <20040804110314.GA9602@kt-is.co.kr>
In-Reply-To: <20040731061132.GC19761@kt-is.co.kr>
References:  <20040731061132.GC19761@kt-is.co.kr>

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

--FCuugMFkClbJLl1L
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sat, Jul 31, 2004 at 03:11:32PM +0900, To sparc64@freebsd.org wrote:
 > Hi,
 > 
 > Normally, users with hme(4) + DP83840 PHY forcly set media type to
 > full-duplex since that combination lacks auto-negotiation. However,
 > this has side-effect of bind(2) problem. Typical phenomenon is 
 > binding error(EADDRNOTAVAIL) for locally assgined address.(INADDR_ANY
 > works though). I guess this issue had been there for a long time and
 > triggered by ifconfig mediaopt command in big-endian arch.
 > 
 > The root cause of the problem seems to be in ifconfig(8) itself.
 > When ifconfig(8) sets media with user-supplied one, it also sets
 > its internal global variable(ifr_media) in 'struct ifreq ifr' to
 > selected one. Since the member variable ifr_media in 'struct ifreq ifr'
 > is shared with all other attributes, subsequent evaluation of
 > 'ifr.ifr_addr.sa_family' is wrong. Under Ultra2, usually I see
 > "atalk 0.0 range 0-0 phase 2" message when I try to set media with command
 > "ifconfig hme0 media 100baseTX mediaopt full-duplex".(i.e. ifconfig(8)
 > thinks I had set AF_APPLETALK.) I guess this affects little-endian
 > machine too. But due to its endian-nature it's not triggered.
 > 
 > Here is temporary fix for that issue. Since ifconfig(8) is too complex
 > and very difficult to verify correct operations, I patched domediaopt()
 > which is *not* correct fix.
 > I'd like to see correct fix from commiters with thorough knowledge
 > of ifconfig(8).
 > 

Here is better patch. This should fix the two bugs of ifconfig(8)
on big-endian machines.


bug #1
 When mediaopt full-duplex was set, global variable ifr.ifr_media
 is set to selected media option. Therefore the next reference to
 "ifr.ifr_addr.sa_family" is wrong since the value was overwritten
 by selected media option.

bug #2
 According to bug #1, "ifr.ifr_addr.sa_family" now has the value               
 AF_APPLETALK. So checkatrange() is called and "addreq.ifra_addr"
 is modified. Now if ifconfig(8) has a new address to set, it
 incorrectly use the corrupted "addreq". This yield bind(2)
 error(EADDRNOTAVAIL) for assigned IP address.

Thanks.
Regards,
Pyun YongHyeon
-- 
Pyun YongHyeon <http://www.kr.freebsd.org/~yongari>;

--FCuugMFkClbJLl1L
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ifconfig.patch"

--- ifconfig.c.orig	Mon Aug  2 10:24:34 2004
+++ ifconfig.c	Wed Aug  4 19:33:32 2004
@@ -653,14 +653,15 @@
 int
 ifconfig(int argc, char *const *argv, const struct afswtch *afp)
 {
-	int s;
+	int af, s;
 
 	if (afp == NULL)
 		afp = &afs[0];
 	ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af;
+	af = afp->af_af;
 	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
 
-	if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
+	if ((s = socket(af, SOCK_DGRAM, 0)) < 0)
 		err(1, "socket");
 
 	while (argc > 0) {
@@ -690,7 +691,7 @@
 		argc--, argv++;
 	}
 #ifdef INET6
-	if (ifr.ifr_addr.sa_family == AF_INET6 && explicit_prefix == 0) {
+	if (af == AF_INET6 && explicit_prefix == 0) {
 		/* Aggregatable address architecture defines all prefixes
 		   are 64. So, it is convenient to set prefixlen to 64 if
 		   it is not specified. */
@@ -699,7 +700,7 @@
 	}
 #endif
 #ifndef NO_IPX
-	if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) {
+	if (setipdst && af == AF_IPX) {
 		struct ipxip_req rq;
 		int size = sizeof(rq);
 
@@ -710,7 +711,7 @@
 			Perror("Encapsulation Routing");
 	}
 #endif
-	if (ifr.ifr_addr.sa_family == AF_APPLETALK)
+	if (af == AF_APPLETALK)
 		checkatrange((struct sockaddr_at *) &addreq.ifra_addr);
 	if (clearaddr) {
 		if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {

--FCuugMFkClbJLl1L--



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