Module Name:    src
Committed By:   dyoung
Date:           Wed Dec 28 02:14:57 UTC 2011

Modified Files:
        src/sys/net: if.c

Log Message:
Fix ifpromisc() regression: if ifpromisc(ifp, 1) is called, do set
IFF_PROMISC whether ifp is IFF_UP or not, but do not call ifp->if_ioctl
unless ifp is IFF_UP.


To generate a diff of this commit:
cvs rdiff -u -r1.258 -r1.259 src/sys/net/if.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/if.c
diff -u src/sys/net/if.c:1.258 src/sys/net/if.c:1.259
--- src/sys/net/if.c:1.258	Sun Nov 27 14:55:57 2011
+++ src/sys/net/if.c	Wed Dec 28 02:14:57 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.258 2011/11/27 14:55:57 jakllsch Exp $	*/
+/*	$NetBSD: if.c,v 1.259 2011/12/28 02:14:57 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.258 2011/11/27 14:55:57 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.259 2011/12/28 02:14:57 dyoung Exp $");
 
 #include "opt_inet.h"
 
@@ -1415,10 +1415,9 @@ int
 ifpromisc(struct ifnet *ifp, int pswitch)
 {
 	int pcount, ret;
-	short flags, nflags;
+	short nflags;
 
 	pcount = ifp->if_pcount;
-	flags = ifp->if_flags;
 	if (pswitch) {
 		/*
 		 * Allow the device to be "placed" into promiscuous
@@ -1428,20 +1427,10 @@ ifpromisc(struct ifnet *ifp, int pswitch
 		if (ifp->if_pcount++ != 0)
 			return 0;
 		nflags = ifp->if_flags | IFF_PROMISC;
-		if ((nflags & IFF_UP) == 0)
-			return 0;
 	} else {
 		if (--ifp->if_pcount > 0)
 			return 0;
 		nflags = ifp->if_flags & ~IFF_PROMISC;
-		/*
-		 * If the device is not configured up, we should not need to
-		 * turn off promiscuous mode (device should have turned it
-		 * off when interface went down; and will look at IFF_PROMISC
-		 * again next time interface comes up).
-		 */
-		if ((nflags & IFF_UP) == 0)
-			return 0;
 	}
 	ret = if_flags_set(ifp, nflags);
 	/* Restore interface state if not successful. */
@@ -2160,15 +2149,24 @@ if_flags_set(ifnet_t *ifp, const short f
 	if (ifp->if_setflags != NULL)
 		rc = (*ifp->if_setflags)(ifp, flags);
 	else {
-		short cantflags;
+		short cantflags, chgdflags;
 		struct ifreq ifr;
 
-		memset(&ifr, 0, sizeof(ifr));
+		chgdflags = ifp->if_flags ^ flags;
+		cantflags = chgdflags & IFF_CANTCHANGE;
 
-		cantflags = (ifp->if_flags ^ flags) & IFF_CANTCHANGE;
 		if (cantflags != 0)
 			ifp->if_flags ^= cantflags;
 
+                /* Traditionally, we do not call if_ioctl after
+                 * setting/clearing only IFF_PROMISC if the interface
+                 * isn't IFF_UP.  Uphold that tradition.
+		 */
+		if (chgdflags == IFF_PROMISC && (ifp->if_flags & IFF_UP) == 0)
+			return 0;
+
+		memset(&ifr, 0, sizeof(ifr));
+
 		ifr.ifr_flags = flags & ~IFF_CANTCHANGE;
 		rc = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, &ifr);
 

Reply via email to