ifconfig(8) mediaopt bug and temporary fix
Pyun YongHyeon
yongari at kt-is.co.kr
Wed Aug 4 04:03:39 PDT 2004
On Sat, Jul 31, 2004 at 03:11:32PM +0900, To sparc64 at 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>
-------------- next part --------------
--- 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) {
More information about the freebsd-sparc64
mailing list