Bug 91399

Summary: ifconfig(8): the setifmediacallback function is not returning the saved media data before making the ioctl call
Product: Base System Reporter: Spencer Minear <minear>
Component: binAssignee: Doug Ambrisko <ambrisko>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   

Description Spencer Minear 2006-01-06 15:50:06 UTC
The 1.19 version of ifconfig/ifmedia.c added the use of setifmediacallback
so that media setting gets done only once at the end of the sequence of changes.

The change carefully made sure the that new media value was saved in the ifmr
structure which is held in the callback structure.

However the new setifmediacallback structure fails to return media information
saved in the ifmr structure to the ifr structure before the ioctl call is made.
This depending on the order of parameters on the ifconfig command this can
result in making a SIOCSIFMEDIA call with parameters from a previous operation.

Fix: 

I think the fix is simple.  Add

		ifr.ifr_media = ifmr->ifm_current;
following line 242.

The code should look like:

	if (!did_it) {
		ifr.ifr_media = ifmr->ifm_current;
		if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)

It isn't quite this simple since that will nuke the media setting.
The problem appears to be the SIOCSIFMEDIA is not just looking at the
media settings like it should ... it should ignore the other attributes.

I agree this is a side-effect of my change since before everything
was banged into the NIC one at a time which caused its own problems
when the media didn't really changed but it forced the NIC to change
it.  This requires more digging to see if this is a problem in the
ifmedia ioctl to prevent gross hacking of ifconfig.
How-To-Repeat: Use a command like:

ifconfig <IF> inet <addr> netmask <mask> media <mediasetting> mtu 1500

In this case the mtu ioctl gets done before the media ioctl.  In this case
the medial ioctl call contains the 1500 left over from the mtu ioctl call
and returns an ENXIO error.
Comment 1 Gleb Smirnoff freebsd_committer freebsd_triage 2006-01-10 13:26:55 UTC
Responsible Changed
From-To: freebsd-bugs->ambrisko

Looks like Doug's change has introduced this.
Comment 2 Doug Ambrisko freebsd_committer freebsd_triage 2006-01-11 22:38:14 UTC
State Changed
From-To: open->closed

You were right.  It's been a while since I worked in this.  Yes 
I forgot to put the modified value into the global structure. 
I probably thought ifmr and ifr were the same :-( 

Thanks for the fix.