From owner-svn-src-all@FreeBSD.ORG Tue Dec 25 13:01:59 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 5259783C; Tue, 25 Dec 2012 13:01:59 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 1D0218FC0C; Tue, 25 Dec 2012 13:01:59 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qBPD1weH059214; Tue, 25 Dec 2012 13:01:58 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qBPD1wfA059212; Tue, 25 Dec 2012 13:01:58 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201212251301.qBPD1wfA059212@svn.freebsd.org> From: Gleb Smirnoff Date: Tue, 25 Dec 2012 13:01:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r244678 - in head/sys: netinet netinet6 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Dec 2012 13:01:59 -0000 Author: glebius Date: Tue Dec 25 13:01:58 2012 New Revision: 244678 URL: http://svnweb.freebsd.org/changeset/base/244678 Log: 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. Modified: head/sys/netinet/in.c head/sys/netinet6/in6.c Modified: head/sys/netinet/in.c ============================================================================== --- head/sys/netinet/in.c Tue Dec 25 13:00:19 2012 (r244677) +++ head/sys/netinet/in.c Tue Dec 25 13:01:58 2012 (r244678) @@ -819,14 +819,19 @@ in_ifinit(struct ifnet *ifp, struct in_i 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, Modified: head/sys/netinet6/in6.c ============================================================================== --- head/sys/netinet6/in6.c Tue Dec 25 13:00:19 2012 (r244677) +++ head/sys/netinet6/in6.c Tue Dec 25 13:01:58 2012 (r244678) @@ -1874,9 +1874,18 @@ in6_ifinit(struct ifnet *ifp, struct in6 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;