Subject: kern/31130: [PATCH] Fix vge(4) SIOC{ADD,DEL}MULTI handling
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <fun@naobsd.org>
List: netbsd-bugs
Date: 09/03/2005 18:24:00
>Number:         31130
>Category:       kern
>Synopsis:       [PATCH] Fix vge(4) SIOC{ADD,DEL}MULTI handling
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Sep 03 18:24:00 +0000 2005
>Originator:     FUKAUMI Naoki
>Release:        NetBSD 3.99.7
>Organization:
	FUKAUMI Naoki
>Environment:
System: NetBSD turion64.naobsd.org 3.99.7 NetBSD 3.99.7 (TURION64) #2: Tue Aug 16 19:43:57 JST 2005 root@turion64.naobsd.org:/usr/obj/amd64/sys/arch/amd64/compile/TURION64 amd64
Architecture: x86_64
Machine: amd64
>Description:
	vge(4) multicast handling is completely broken.
	(maybe vge_ioctl() should be overhauled entirely)
>How-To-Repeat:
	See if_vge.c::vge_ioctl().
>Fix:
	It isn't tested yet. I'll test on netbsd-3 machine.
	(Yes, please pull up, too. :)

Index: sys/dev/pci/if_vge.c
===================================================================
RCS file: /home/fun/cvsroot/NetBSD/src/sys/dev/pci/if_vge.c,v
retrieving revision 1.5
diff -u -p -r1.5 if_vge.c
--- sys/dev/pci/if_vge.c	2 May 2005 15:34:32 -0000	1.5
+++ sys/dev/pci/if_vge.c	3 Sep 2005 17:51:56 -0000
@@ -2060,7 +2060,9 @@ vge_ioctl(ifp, command, data)
 	struct vge_softc	*sc = ifp->if_softc;
 	struct ifreq		*ifr = (struct ifreq *) data;
 	struct mii_data		*mii;
-	int			error = 0;
+	int			s, error = 0;
+
+	s = splnet();
 
 	switch (command) {
 	case SIOCSIFMTU:
@@ -2092,7 +2094,19 @@ vge_ioctl(ifp, command, data)
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
-		vge_setmulti(sc);
+		error = (cmd == SIOCADDMULTI) ?
+		    ether_addmulti(ifr, &sc->sc_ethercom) :
+		    ether_delmulti(ifr, &sc->sc_ethercom);
+
+		if (error == ENETRESET) {
+			/*
+			 * Multicast list has changed; set the hardware filter
+			 * accordingly.
+			 */
+			if (ifp->if_flags & IFF_RUNNING)
+				vge_setmulti(sc);
+			error = 0;
+		}
 		break;
 	case SIOCGIFMEDIA:
 	case SIOCSIFMEDIA:
@@ -2104,6 +2118,7 @@ vge_ioctl(ifp, command, data)
 		break;
 	}
 
+	splx(s);
 	return (error);
 }