1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-17 15:27:36 +00:00

The SIOCSIFFLAGS ioctl handler runs if_up()/if_down() that notify

all interested parties in case if interface flag IFF_UP has changed.

  However, not only SIOCSIFFLAGS can raise the flag, but SIOCAIFADDR
and SIOCAIFADDR_IN6 can, too. The actual |= is done not in the protocol
code, but in code of interface drivers. To fix this historical layering
violation, we will check whether ifp->if_ioctl(SIOCSIFADDR) raised the
IFF_UP flag, and if it did, run the if_up() handler.

  This fixes configuring an address under CARP control on an interface
that was initially !IFF_UP.

P.S. I intentionally omitted handling the IFF_SMART flag. This flag was
never ever used in any driver since it was introduced, and since it
means another layering violation, it should be garbage collected instead
of pretended to be supported.
This commit is contained in:
Gleb Smirnoff 2012-12-25 13:01:58 +00:00
parent 56961fd794
commit 468e45f3bd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=244678
2 changed files with 17 additions and 3 deletions

View File

@ -819,14 +819,19 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
return (error);
/*
* Give the interface a chance to initialize
* if this is its first address,
* and to validate the address if necessary.
* Give the interface a chance to initialize if this is its first
* address, and to validate the address if necessary.
*
* Historically, drivers managed IFF_UP flag theirselves, so we
* need to check whether driver did that.
*/
flags = ifp->if_flags;
if (ifp->if_ioctl != NULL &&
(error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)) != 0)
/* LIST_REMOVE(ia, ia_hash) is done in in_control */
return (error);
if ((ifp->if_flags & IFF_UP) && (flags & IFF_UP) == 0)
if_up(ifp);
/*
* Be compatible with network classes, if netmask isn't supplied,

View File

@ -1874,9 +1874,18 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
ia->ia_addr = *sin6;
if (ifacount <= 1 && ifp->if_ioctl) {
int flags;
/*
* Historically, drivers managed IFF_UP flag theirselves, so we
* need to check whether driver did that.
*/
flags = ifp->if_flags;
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
if (error)
return (error);
if ((ifp->if_flags & IFF_UP) && (flags & IFF_UP) == 0)
if_up(ifp);
}
ia->ia_ifa.ifa_metric = ifp->if_metric;