changeset 14003:d4552e4ac833

3677 /dev/ipnet can duplicate packets Reviewed by: Carlos Cardenas <carlos.cardenas@joyent.com> Reviewed by: Jason King <jason.brian.king@gmail.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Sebastien Roy <sebastien.roy@delphix.com> Approved by: Dan McDonald <danmcd@nexenta.com>
author Robert Mustacchi <rm@joyent.com>
date Tue, 02 Apr 2013 19:04:36 -0700
parents af551fdf9db5
children dd91fed709a7
files usr/src/uts/common/io/dls/dls.c
diffstat 1 files changed, 23 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/dls/dls.c	Wed Apr 03 11:07:46 2013 -0700
+++ b/usr/src/uts/common/io/dls/dls.c	Tue Apr 02 19:04:36 2013 -0700
@@ -25,6 +25,10 @@
  */
 
 /*
+ * Copyright (c) 2013 Joyent, Inc.  All rights reserved.
+ */
+
+/*
  * Data-Link Services Module
  */
 
@@ -244,18 +248,26 @@
 {
 	int err = 0;
 	uint32_t old_flags = dsp->ds_promisc;
+	mac_client_promisc_type_t mptype = MAC_CLIENT_PROMISC_ALL;
 
 	ASSERT(MAC_PERIM_HELD(dsp->ds_mh));
 	ASSERT(!(new_flags & ~(DLS_PROMISC_SAP | DLS_PROMISC_MULTI |
 	    DLS_PROMISC_PHYS)));
 
+	/*
+	 * If the user has only requested DLS_PROMISC_MULTI then we need to make
+	 * sure that they don't see all packets.
+	 */
+	if (new_flags == DLS_PROMISC_MULTI)
+		mptype = MAC_CLIENT_PROMISC_MULTI;
+
 	if (dsp->ds_promisc == 0 && new_flags != 0) {
 		/*
 		 * If only DLS_PROMISC_SAP, we don't turn on the
 		 * physical promisc mode
 		 */
 		dsp->ds_promisc = new_flags;
-		err = mac_promisc_add(dsp->ds_mch, MAC_CLIENT_PROMISC_ALL,
+		err = mac_promisc_add(dsp->ds_mch, mptype,
 		    dls_rx_promisc, dsp, &dsp->ds_mph,
 		    (new_flags != DLS_PROMISC_SAP) ? 0 :
 		    MAC_PROMISC_FLAGS_NO_PHYS);
@@ -295,7 +307,7 @@
 		mac_promisc_remove(dsp->ds_mph);
 		/* Honors both after-remove and before-add semantics! */
 		dsp->ds_promisc = new_flags;
-		err = mac_promisc_add(dsp->ds_mch, MAC_CLIENT_PROMISC_ALL,
+		err = mac_promisc_add(dsp->ds_mch, mptype,
 		    dls_rx_promisc, dsp, &dsp->ds_mph, 0);
 		if (err != 0)
 			dsp->ds_promisc = old_flags;
@@ -531,9 +543,16 @@
 	if (dsp->ds_promisc != 0) {
 		/*
 		 * Filter out packets that arrived from the data path
-		 * (i_dls_link_rx) when promisc mode is on.
+		 * (i_dls_link_rx) when promisc mode is on. We need to correlate
+		 * the ds_promisc flags with the mac header destination type. If
+		 * only DLS_PROMISC_MULTI is enabled, we need to only reject
+		 * multicast packets as those are the only ones which filter up
+		 * the promiscuous path. If we have DLS_PROMISC_PHYS or
+		 * DLS_PROMISC_SAP set, then we know that we'll be seeing
+		 * everything, so we should drop it now.
 		 */
-		if (!promisc)
+		if (!promisc && !(dsp->ds_promisc == DLS_PROMISC_MULTI &&
+		    mhip->mhi_dsttype != MAC_ADDRTYPE_MULTICAST))
 			goto refuse;
 		/*
 		 * If the dls_impl_t is in 'all physical' mode then