xref: /titanic_51/usr/src/uts/common/io/mac/mac.c (revision 0ce6acb835f8cec2ed5d14a190db6e2f98ed6d69)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * MAC Services Module
30  */
31 
32 #include <sys/types.h>
33 #include <sys/conf.h>
34 #include <sys/stat.h>
35 #include <sys/stream.h>
36 #include <sys/strsun.h>
37 #include <sys/strsubr.h>
38 #include <sys/dlpi.h>
39 #include <sys/modhash.h>
40 #include <sys/mac.h>
41 #include <sys/mac_impl.h>
42 #include <sys/dls.h>
43 #include <sys/dld.h>
44 #include <sys/modctl.h>
45 
46 #define	IMPL_HASHSZ	67	/* prime */
47 
48 static kmem_cache_t	*i_mac_impl_cachep;
49 static mod_hash_t	*i_mac_impl_hash;
50 krwlock_t		i_mac_impl_lock;
51 uint_t			i_mac_impl_count;
52 
53 #define	MACTYPE_KMODDIR	"mac"
54 #define	MACTYPE_HASHSZ	67
55 static mod_hash_t	*i_mactype_hash;
56 
57 static void i_mac_notify_task(void *);
58 
59 /*
60  * Private functions.
61  */
62 
63 /*ARGSUSED*/
64 static int
65 i_mac_constructor(void *buf, void *arg, int kmflag)
66 {
67 	mac_impl_t	*mip = buf;
68 
69 	bzero(buf, sizeof (mac_impl_t));
70 
71 	mip->mi_linkstate = LINK_STATE_UNKNOWN;
72 
73 	rw_init(&mip->mi_state_lock, NULL, RW_DRIVER, NULL);
74 	rw_init(&mip->mi_data_lock, NULL, RW_DRIVER, NULL);
75 	rw_init(&mip->mi_notify_lock, NULL, RW_DRIVER, NULL);
76 	rw_init(&mip->mi_rx_lock, NULL, RW_DRIVER, NULL);
77 	rw_init(&mip->mi_txloop_lock, NULL, RW_DRIVER, NULL);
78 	rw_init(&mip->mi_resource_lock, NULL, RW_DRIVER, NULL);
79 	mutex_init(&mip->mi_activelink_lock, NULL, MUTEX_DEFAULT, NULL);
80 	mutex_init(&mip->mi_notify_ref_lock, NULL, MUTEX_DRIVER, NULL);
81 	cv_init(&mip->mi_notify_cv, NULL, CV_DRIVER, NULL);
82 	return (0);
83 }
84 
85 /*ARGSUSED*/
86 static void
87 i_mac_destructor(void *buf, void *arg)
88 {
89 	mac_impl_t	*mip = buf;
90 
91 	ASSERT(mip->mi_ref == 0);
92 	ASSERT(mip->mi_active == 0);
93 	ASSERT(mip->mi_linkstate == LINK_STATE_UNKNOWN);
94 	ASSERT(mip->mi_devpromisc == 0);
95 	ASSERT(mip->mi_promisc == 0);
96 	ASSERT(mip->mi_mmap == NULL);
97 	ASSERT(mip->mi_mnfp == NULL);
98 	ASSERT(mip->mi_resource_add == NULL);
99 	ASSERT(mip->mi_ksp == NULL);
100 	ASSERT(mip->mi_kstat_count == 0);
101 
102 	rw_destroy(&mip->mi_state_lock);
103 	rw_destroy(&mip->mi_data_lock);
104 	rw_destroy(&mip->mi_notify_lock);
105 	rw_destroy(&mip->mi_rx_lock);
106 	rw_destroy(&mip->mi_txloop_lock);
107 	rw_destroy(&mip->mi_resource_lock);
108 	mutex_destroy(&mip->mi_activelink_lock);
109 	mutex_destroy(&mip->mi_notify_ref_lock);
110 	cv_destroy(&mip->mi_notify_cv);
111 }
112 
113 static void
114 i_mac_notify(mac_impl_t *mip, mac_notify_type_t type)
115 {
116 	mac_notify_task_arg_t	*mnta;
117 
118 	rw_enter(&i_mac_impl_lock, RW_READER);
119 	if (mip->mi_disabled)
120 		goto exit;
121 
122 	if ((mnta = kmem_alloc(sizeof (*mnta), KM_NOSLEEP)) == NULL) {
123 		cmn_err(CE_WARN, "i_mac_notify(%s, 0x%x): memory "
124 		    "allocation failed", mip->mi_name, type);
125 		goto exit;
126 	}
127 
128 	mnta->mnt_mip = mip;
129 	mnta->mnt_type = type;
130 
131 	mutex_enter(&mip->mi_notify_ref_lock);
132 	mip->mi_notify_ref++;
133 	mutex_exit(&mip->mi_notify_ref_lock);
134 
135 	rw_exit(&i_mac_impl_lock);
136 
137 	if (taskq_dispatch(system_taskq, i_mac_notify_task, mnta,
138 	    TQ_NOSLEEP) == NULL) {
139 		cmn_err(CE_WARN, "i_mac_notify(%s, 0x%x): taskq dispatch "
140 		    "failed", mip->mi_name, type);
141 
142 		mutex_enter(&mip->mi_notify_ref_lock);
143 		if (--mip->mi_notify_ref == 0)
144 			cv_signal(&mip->mi_notify_cv);
145 		mutex_exit(&mip->mi_notify_ref_lock);
146 
147 		kmem_free(mnta, sizeof (*mnta));
148 	}
149 	return;
150 
151 exit:
152 	rw_exit(&i_mac_impl_lock);
153 }
154 
155 static void
156 i_mac_notify_task(void *notify_arg)
157 {
158 	mac_notify_task_arg_t	*mnta = (mac_notify_task_arg_t *)notify_arg;
159 	mac_impl_t		*mip;
160 	mac_notify_type_t	type;
161 	mac_notify_fn_t		*mnfp;
162 	mac_notify_t		notify;
163 	void			*arg;
164 
165 	mip = mnta->mnt_mip;
166 	type = mnta->mnt_type;
167 	kmem_free(mnta, sizeof (*mnta));
168 
169 	/*
170 	 * Walk the list of notifications.
171 	 */
172 	rw_enter(&mip->mi_notify_lock, RW_READER);
173 	for (mnfp = mip->mi_mnfp; mnfp != NULL; mnfp = mnfp->mnf_nextp) {
174 		notify = mnfp->mnf_fn;
175 		arg = mnfp->mnf_arg;
176 
177 		ASSERT(notify != NULL);
178 		notify(arg, type);
179 	}
180 	rw_exit(&mip->mi_notify_lock);
181 	mutex_enter(&mip->mi_notify_ref_lock);
182 	if (--mip->mi_notify_ref == 0)
183 		cv_signal(&mip->mi_notify_cv);
184 	mutex_exit(&mip->mi_notify_ref_lock);
185 }
186 
187 static mactype_t *
188 i_mactype_getplugin(const char *plugin_name)
189 {
190 	mactype_t	*mtype = NULL;
191 	boolean_t	tried_modload = B_FALSE;
192 
193 find_registered_mactype:
194 	if (mod_hash_find(i_mactype_hash, (mod_hash_key_t)plugin_name,
195 	    (mod_hash_val_t *)&mtype) == 0) {
196 		/*
197 		 * Because the reference count is initialized at 1 (see
198 		 * mactype_register()), we don't need to bump up the
199 		 * reference count if we're the first reference.
200 		 */
201 		if (!tried_modload)
202 			mtype->mt_ref++;
203 		return (mtype);
204 	} else if (tried_modload) {
205 		return (NULL);
206 	}
207 
208 	/*
209 	 * If the plugin has not yet been loaded, then attempt to load it
210 	 * now.  If modload succeeds, the plugin should have registered
211 	 * using mactype_register(), in which case we can go back and
212 	 * attempt to find it again.
213 	 */
214 	if (modload(MACTYPE_KMODDIR, (char *)plugin_name) != -1) {
215 		tried_modload = B_TRUE;
216 		goto find_registered_mactype;
217 	}
218 	return (NULL);
219 }
220 
221 /*
222  * Module initialization functions.
223  */
224 
225 void
226 mac_init(void)
227 {
228 	i_mac_impl_cachep = kmem_cache_create("mac_impl_cache",
229 	    sizeof (mac_impl_t), 0, i_mac_constructor, i_mac_destructor,
230 	    NULL, NULL, NULL, 0);
231 	ASSERT(i_mac_impl_cachep != NULL);
232 
233 	i_mac_impl_hash = mod_hash_create_extended("mac_impl_hash",
234 	    IMPL_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor,
235 	    mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
236 	rw_init(&i_mac_impl_lock, NULL, RW_DEFAULT, NULL);
237 	i_mac_impl_count = 0;
238 
239 	i_mactype_hash = mod_hash_create_extended("mactype_hash",
240 	    MACTYPE_HASHSZ,
241 	    mod_hash_null_keydtor, mod_hash_null_valdtor,
242 	    mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
243 }
244 
245 int
246 mac_fini(void)
247 {
248 	if (i_mac_impl_count > 0)
249 		return (EBUSY);
250 
251 	mod_hash_destroy_hash(i_mac_impl_hash);
252 	rw_destroy(&i_mac_impl_lock);
253 
254 	kmem_cache_destroy(i_mac_impl_cachep);
255 
256 	mod_hash_destroy_hash(i_mactype_hash);
257 	return (0);
258 }
259 
260 /*
261  * Client functions.
262  */
263 
264 int
265 mac_open(const char *macname, uint_t ddi_instance, mac_handle_t *mhp)
266 {
267 	char		driver[MAXNAMELEN];
268 	uint_t		instance;
269 	major_t		major;
270 	dev_info_t	*dip;
271 	mac_impl_t	*mip;
272 	int		err;
273 
274 	/*
275 	 * Check the device name length to make sure it won't overflow our
276 	 * buffer.
277 	 */
278 	if (strlen(macname) >= MAXNAMELEN)
279 		return (EINVAL);
280 
281 	/*
282 	 * Split the device name into driver and instance components.
283 	 */
284 	if (ddi_parse(macname, driver, &instance) != DDI_SUCCESS)
285 		return (EINVAL);
286 
287 	/*
288 	 * Get the major number of the driver.
289 	 */
290 	if ((major = ddi_name_to_major(driver)) == (major_t)-1)
291 		return (EINVAL);
292 
293 	/*
294 	 * Hold the given instance to prevent it from being detached.
295 	 * This will also attach the instance if it is not currently attached.
296 	 * Currently we ensure that mac_register() (called by the driver's
297 	 * attach entry point) and all code paths under it cannot possibly
298 	 * call mac_open() because this would lead to a recursive attach
299 	 * panic.
300 	 */
301 	if ((dip = ddi_hold_devi_by_instance(major, ddi_instance, 0)) == NULL)
302 		return (EINVAL);
303 
304 	/*
305 	 * Look up its entry in the global hash table.
306 	 */
307 again:
308 	rw_enter(&i_mac_impl_lock, RW_WRITER);
309 	err = mod_hash_find(i_mac_impl_hash, (mod_hash_key_t)macname,
310 	    (mod_hash_val_t *)&mip);
311 	if (err != 0) {
312 		err = ENOENT;
313 		goto failed;
314 	}
315 
316 	if (mip->mi_disabled) {
317 		rw_exit(&i_mac_impl_lock);
318 		goto again;
319 	}
320 
321 	mip->mi_ref++;
322 	rw_exit(&i_mac_impl_lock);
323 
324 	*mhp = (mac_handle_t)mip;
325 	return (0);
326 
327 failed:
328 	rw_exit(&i_mac_impl_lock);
329 	ddi_release_devi(dip);
330 	return (err);
331 }
332 
333 void
334 mac_close(mac_handle_t mh)
335 {
336 	mac_impl_t	*mip = (mac_impl_t *)mh;
337 	dev_info_t	*dip = mip->mi_dip;
338 
339 	rw_enter(&i_mac_impl_lock, RW_WRITER);
340 
341 	ASSERT(mip->mi_ref != 0);
342 	if (--mip->mi_ref == 0) {
343 		ASSERT(!mip->mi_activelink);
344 	}
345 	ddi_release_devi(dip);
346 	rw_exit(&i_mac_impl_lock);
347 }
348 
349 const mac_info_t *
350 mac_info(mac_handle_t mh)
351 {
352 	return (&((mac_impl_t *)mh)->mi_info);
353 }
354 
355 dev_info_t *
356 mac_devinfo_get(mac_handle_t mh)
357 {
358 	return (((mac_impl_t *)mh)->mi_dip);
359 }
360 
361 uint64_t
362 mac_stat_get(mac_handle_t mh, uint_t stat)
363 {
364 	mac_impl_t	*mip = (mac_impl_t *)mh;
365 	uint64_t	val;
366 	int		ret;
367 
368 	/*
369 	 * The range of stat determines where it is maintained.  Stat
370 	 * values from 0 up to (but not including) MAC_STAT_MIN are
371 	 * mainteined by the mac module itself.  Everything else is
372 	 * maintained by the driver.
373 	 */
374 	if (stat < MAC_STAT_MIN) {
375 		/* These stats are maintained by the mac module itself. */
376 		switch (stat) {
377 		case MAC_STAT_LINK_STATE:
378 			return (mip->mi_linkstate);
379 		case MAC_STAT_LINK_UP:
380 			return (mip->mi_linkstate == LINK_STATE_UP);
381 		case MAC_STAT_PROMISC:
382 			return (mip->mi_devpromisc != 0);
383 		default:
384 			ASSERT(B_FALSE);
385 		}
386 	}
387 
388 	/*
389 	 * Call the driver to get the given statistic.
390 	 */
391 	ret = mip->mi_getstat(mip->mi_driver, stat, &val);
392 	if (ret != 0) {
393 		/*
394 		 * The driver doesn't support this statistic.  Get the
395 		 * statistic's default value.
396 		 */
397 		val = mac_stat_default(mip, stat);
398 	}
399 	return (val);
400 }
401 
402 int
403 mac_start(mac_handle_t mh)
404 {
405 	mac_impl_t	*mip = (mac_impl_t *)mh;
406 	int		err;
407 
408 	ASSERT(mip->mi_start != NULL);
409 
410 	rw_enter(&(mip->mi_state_lock), RW_WRITER);
411 
412 	/*
413 	 * Check whether the device is already started.
414 	 */
415 	if (mip->mi_active++ != 0) {
416 		/*
417 		 * It's already started so there's nothing more to do.
418 		 */
419 		err = 0;
420 		goto done;
421 	}
422 
423 	/*
424 	 * Start the device.
425 	 */
426 	if ((err = mip->mi_start(mip->mi_driver)) != 0)
427 		--mip->mi_active;
428 
429 done:
430 	rw_exit(&(mip->mi_state_lock));
431 	return (err);
432 }
433 
434 void
435 mac_stop(mac_handle_t mh)
436 {
437 	mac_impl_t	*mip = (mac_impl_t *)mh;
438 
439 	ASSERT(mip->mi_stop != NULL);
440 
441 	rw_enter(&(mip->mi_state_lock), RW_WRITER);
442 
443 	/*
444 	 * Check whether the device is still needed.
445 	 */
446 	ASSERT(mip->mi_active != 0);
447 	if (--mip->mi_active != 0) {
448 		/*
449 		 * It's still needed so there's nothing more to do.
450 		 */
451 		goto done;
452 	}
453 
454 	/*
455 	 * Stop the device.
456 	 */
457 	mip->mi_stop(mip->mi_driver);
458 
459 done:
460 	rw_exit(&(mip->mi_state_lock));
461 }
462 
463 int
464 mac_multicst_add(mac_handle_t mh, const uint8_t *addr)
465 {
466 	mac_impl_t		*mip = (mac_impl_t *)mh;
467 	mac_multicst_addr_t	**pp;
468 	mac_multicst_addr_t	*p;
469 	int			err;
470 
471 	ASSERT(mip->mi_multicst != NULL);
472 
473 	/*
474 	 * Verify the address.
475 	 */
476 	if ((err = mip->mi_type->mt_ops.mtops_multicst_verify(addr,
477 	    mip->mi_pdata)) != 0) {
478 		return (err);
479 	}
480 
481 	/*
482 	 * Check whether the given address is already enabled.
483 	 */
484 	rw_enter(&(mip->mi_data_lock), RW_WRITER);
485 	for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) {
486 		if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) ==
487 		    0) {
488 			/*
489 			 * The address is already enabled so just bump the
490 			 * reference count.
491 			 */
492 			p->mma_ref++;
493 			err = 0;
494 			goto done;
495 		}
496 	}
497 
498 	/*
499 	 * Allocate a new list entry.
500 	 */
501 	if ((p = kmem_zalloc(sizeof (mac_multicst_addr_t),
502 	    KM_NOSLEEP)) == NULL) {
503 		err = ENOMEM;
504 		goto done;
505 	}
506 
507 	/*
508 	 * Enable a new multicast address.
509 	 */
510 	if ((err = mip->mi_multicst(mip->mi_driver, B_TRUE, addr)) != 0) {
511 		kmem_free(p, sizeof (mac_multicst_addr_t));
512 		goto done;
513 	}
514 
515 	/*
516 	 * Add the address to the list of enabled addresses.
517 	 */
518 	bcopy(addr, p->mma_addr, mip->mi_type->mt_addr_length);
519 	p->mma_ref++;
520 	*pp = p;
521 
522 done:
523 	rw_exit(&(mip->mi_data_lock));
524 	return (err);
525 }
526 
527 int
528 mac_multicst_remove(mac_handle_t mh, const uint8_t *addr)
529 {
530 	mac_impl_t		*mip = (mac_impl_t *)mh;
531 	mac_multicst_addr_t	**pp;
532 	mac_multicst_addr_t	*p;
533 	int			err;
534 
535 	ASSERT(mip->mi_multicst != NULL);
536 
537 	/*
538 	 * Find the entry in the list for the given address.
539 	 */
540 	rw_enter(&(mip->mi_data_lock), RW_WRITER);
541 	for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) {
542 		if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) ==
543 		    0) {
544 			if (--p->mma_ref == 0)
545 				break;
546 
547 			/*
548 			 * There is still a reference to this address so
549 			 * there's nothing more to do.
550 			 */
551 			err = 0;
552 			goto done;
553 		}
554 	}
555 
556 	/*
557 	 * We did not find an entry for the given address so it is not
558 	 * currently enabled.
559 	 */
560 	if (p == NULL) {
561 		err = ENOENT;
562 		goto done;
563 	}
564 	ASSERT(p->mma_ref == 0);
565 
566 	/*
567 	 * Disable the multicast address.
568 	 */
569 	if ((err = mip->mi_multicst(mip->mi_driver, B_FALSE, addr)) != 0) {
570 		p->mma_ref++;
571 		goto done;
572 	}
573 
574 	/*
575 	 * Remove it from the list.
576 	 */
577 	*pp = p->mma_nextp;
578 	kmem_free(p, sizeof (mac_multicst_addr_t));
579 
580 done:
581 	rw_exit(&(mip->mi_data_lock));
582 	return (err);
583 }
584 
585 int
586 mac_unicst_set(mac_handle_t mh, const uint8_t *addr)
587 {
588 	mac_impl_t	*mip = (mac_impl_t *)mh;
589 	int		err;
590 	boolean_t	notify = B_FALSE;
591 
592 	ASSERT(mip->mi_unicst != NULL);
593 
594 	/*
595 	 * Verify the address.
596 	 */
597 	if ((err = mip->mi_type->mt_ops.mtops_unicst_verify(addr,
598 	    mip->mi_pdata)) != 0) {
599 		return (err);
600 	}
601 
602 	/*
603 	 * Program the new unicast address.
604 	 */
605 	rw_enter(&(mip->mi_data_lock), RW_WRITER);
606 
607 	/*
608 	 * If address doesn't change, do nothing.
609 	 * This check is necessary otherwise it may call into mac_unicst_set
610 	 * recursively.
611 	 */
612 	if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) {
613 		err = 0;
614 		goto done;
615 	}
616 
617 	if ((err = mip->mi_unicst(mip->mi_driver, addr)) != 0)
618 		goto done;
619 
620 	/*
621 	 * Save the address and flag that we need to send a notification.
622 	 */
623 	bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length);
624 	notify = B_TRUE;
625 
626 done:
627 	rw_exit(&(mip->mi_data_lock));
628 
629 	if (notify)
630 		i_mac_notify(mip, MAC_NOTE_UNICST);
631 
632 	return (err);
633 }
634 
635 void
636 mac_unicst_get(mac_handle_t mh, uint8_t *addr)
637 {
638 	mac_impl_t	*mip = (mac_impl_t *)mh;
639 
640 	/*
641 	 * Copy out the current unicast source address.
642 	 */
643 	rw_enter(&(mip->mi_data_lock), RW_READER);
644 	bcopy(mip->mi_addr, addr, mip->mi_type->mt_addr_length);
645 	rw_exit(&(mip->mi_data_lock));
646 }
647 
648 void
649 mac_dest_get(mac_handle_t mh, uint8_t *addr)
650 {
651 	mac_impl_t	*mip = (mac_impl_t *)mh;
652 
653 	/*
654 	 * Copy out the current destination address.
655 	 */
656 	rw_enter(&(mip->mi_data_lock), RW_READER);
657 	bcopy(mip->mi_dstaddr, addr, mip->mi_type->mt_addr_length);
658 	rw_exit(&(mip->mi_data_lock));
659 }
660 
661 int
662 mac_promisc_set(mac_handle_t mh, boolean_t on, mac_promisc_type_t ptype)
663 {
664 	mac_impl_t	*mip = (mac_impl_t *)mh;
665 	int		err = 0;
666 
667 	ASSERT(mip->mi_setpromisc != NULL);
668 	ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC);
669 
670 	/*
671 	 * Determine whether we should enable or disable promiscuous mode.
672 	 * For details on the distinction between "device promiscuous mode"
673 	 * and "MAC promiscuous mode", see PSARC/2005/289.
674 	 */
675 	rw_enter(&(mip->mi_data_lock), RW_WRITER);
676 	if (on) {
677 		/*
678 		 * Enable promiscuous mode on the device if not yet enabled.
679 		 */
680 		if (mip->mi_devpromisc++ == 0) {
681 			err = mip->mi_setpromisc(mip->mi_driver, B_TRUE);
682 			if (err != 0) {
683 				mip->mi_devpromisc--;
684 				goto done;
685 			}
686 			i_mac_notify(mip, MAC_NOTE_DEVPROMISC);
687 		}
688 
689 		/*
690 		 * Enable promiscuous mode on the MAC if not yet enabled.
691 		 */
692 		if (ptype == MAC_PROMISC && mip->mi_promisc++ == 0)
693 			i_mac_notify(mip, MAC_NOTE_PROMISC);
694 	} else {
695 		if (mip->mi_devpromisc == 0) {
696 			err = EPROTO;
697 			goto done;
698 		}
699 
700 		/*
701 		 * Disable promiscuous mode on the device if this is the last
702 		 * enabling.
703 		 */
704 		if (--mip->mi_devpromisc == 0) {
705 			err = mip->mi_setpromisc(mip->mi_driver, B_FALSE);
706 			if (err != 0) {
707 				mip->mi_devpromisc++;
708 				goto done;
709 			}
710 			i_mac_notify(mip, MAC_NOTE_DEVPROMISC);
711 		}
712 
713 		/*
714 		 * Disable promiscuous mode on the MAC if this is the last
715 		 * enabling.
716 		 */
717 		if (ptype == MAC_PROMISC && --mip->mi_promisc == 0)
718 			i_mac_notify(mip, MAC_NOTE_PROMISC);
719 	}
720 
721 done:
722 	rw_exit(&(mip->mi_data_lock));
723 	return (err);
724 }
725 
726 boolean_t
727 mac_promisc_get(mac_handle_t mh, mac_promisc_type_t ptype)
728 {
729 	mac_impl_t		*mip = (mac_impl_t *)mh;
730 
731 	ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC);
732 
733 	/*
734 	 * Return the current promiscuity.
735 	 */
736 	if (ptype == MAC_DEVPROMISC)
737 		return (mip->mi_devpromisc != 0);
738 	else
739 		return (mip->mi_promisc != 0);
740 }
741 
742 void
743 mac_resources(mac_handle_t mh)
744 {
745 	mac_impl_t	*mip = (mac_impl_t *)mh;
746 
747 	/*
748 	 * If the driver supports resource registration, call the driver to
749 	 * ask it to register its resources.
750 	 */
751 	if (mip->mi_callbacks->mc_callbacks & MC_RESOURCES)
752 		mip->mi_resources(mip->mi_driver);
753 }
754 
755 void
756 mac_ioctl(mac_handle_t mh, queue_t *wq, mblk_t *bp)
757 {
758 	mac_impl_t	*mip = (mac_impl_t *)mh;
759 
760 	/*
761 	 * Call the driver to handle the ioctl.  The driver may not support
762 	 * any ioctls, in which case we reply with a NAK on its behalf.
763 	 */
764 	if (mip->mi_callbacks->mc_callbacks & MC_IOCTL)
765 		mip->mi_ioctl(mip->mi_driver, wq, bp);
766 	else
767 		miocnak(wq, bp, 0, EINVAL);
768 }
769 
770 const mac_txinfo_t *
771 mac_tx_get(mac_handle_t mh)
772 {
773 	mac_impl_t	*mip = (mac_impl_t *)mh;
774 	mac_txinfo_t	*mtp;
775 
776 	/*
777 	 * Grab the lock to prevent us from racing with MAC_PROMISC being
778 	 * changed.  This is sufficient since MAC clients are careful to always
779 	 * call mac_txloop_add() prior to enabling MAC_PROMISC, and to disable
780 	 * MAC_PROMISC prior to calling mac_txloop_remove().
781 	 */
782 	rw_enter(&mip->mi_txloop_lock, RW_READER);
783 
784 	if (mac_promisc_get(mh, MAC_PROMISC)) {
785 		ASSERT(mip->mi_mtfp != NULL);
786 		mtp = &mip->mi_txloopinfo;
787 	} else {
788 		/*
789 		 * Note that we cannot ASSERT() that mip->mi_mtfp is NULL,
790 		 * because to satisfy the above ASSERT(), we have to disable
791 		 * MAC_PROMISC prior to calling mac_txloop_remove().
792 		 */
793 		mtp = &mip->mi_txinfo;
794 	}
795 
796 	rw_exit(&mip->mi_txloop_lock);
797 	return (mtp);
798 }
799 
800 link_state_t
801 mac_link_get(mac_handle_t mh)
802 {
803 	return (((mac_impl_t *)mh)->mi_linkstate);
804 }
805 
806 mac_notify_handle_t
807 mac_notify_add(mac_handle_t mh, mac_notify_t notify, void *arg)
808 {
809 	mac_impl_t		*mip = (mac_impl_t *)mh;
810 	mac_notify_fn_t		*mnfp;
811 
812 	mnfp = kmem_zalloc(sizeof (mac_notify_fn_t), KM_SLEEP);
813 	mnfp->mnf_fn = notify;
814 	mnfp->mnf_arg = arg;
815 
816 	/*
817 	 * Add it to the head of the 'notify' callback list.
818 	 */
819 	rw_enter(&mip->mi_notify_lock, RW_WRITER);
820 	mnfp->mnf_nextp = mip->mi_mnfp;
821 	mip->mi_mnfp = mnfp;
822 	rw_exit(&mip->mi_notify_lock);
823 
824 	return ((mac_notify_handle_t)mnfp);
825 }
826 
827 void
828 mac_notify_remove(mac_handle_t mh, mac_notify_handle_t mnh)
829 {
830 	mac_impl_t		*mip = (mac_impl_t *)mh;
831 	mac_notify_fn_t		*mnfp = (mac_notify_fn_t *)mnh;
832 	mac_notify_fn_t		**pp;
833 	mac_notify_fn_t		*p;
834 
835 	/*
836 	 * Search the 'notify' callback list for the function closure.
837 	 */
838 	rw_enter(&mip->mi_notify_lock, RW_WRITER);
839 	for (pp = &(mip->mi_mnfp); (p = *pp) != NULL;
840 	    pp = &(p->mnf_nextp)) {
841 		if (p == mnfp)
842 			break;
843 	}
844 	ASSERT(p != NULL);
845 
846 	/*
847 	 * Remove it from the list.
848 	 */
849 	*pp = p->mnf_nextp;
850 	rw_exit(&mip->mi_notify_lock);
851 
852 	/*
853 	 * Free it.
854 	 */
855 	kmem_free(mnfp, sizeof (mac_notify_fn_t));
856 }
857 
858 void
859 mac_notify(mac_handle_t mh)
860 {
861 	mac_impl_t		*mip = (mac_impl_t *)mh;
862 	mac_notify_type_t	type;
863 
864 	for (type = 0; type < MAC_NNOTE; type++)
865 		i_mac_notify(mip, type);
866 }
867 
868 mac_rx_handle_t
869 mac_rx_add(mac_handle_t mh, mac_rx_t rx, void *arg)
870 {
871 	mac_impl_t	*mip = (mac_impl_t *)mh;
872 	mac_rx_fn_t	*mrfp;
873 
874 	mrfp = kmem_zalloc(sizeof (mac_rx_fn_t), KM_SLEEP);
875 	mrfp->mrf_fn = rx;
876 	mrfp->mrf_arg = arg;
877 
878 	/*
879 	 * Add it to the head of the 'rx' callback list.
880 	 */
881 	rw_enter(&(mip->mi_rx_lock), RW_WRITER);
882 	mrfp->mrf_nextp = mip->mi_mrfp;
883 	mip->mi_mrfp = mrfp;
884 	rw_exit(&(mip->mi_rx_lock));
885 
886 	return ((mac_rx_handle_t)mrfp);
887 }
888 
889 /*
890  * Unregister a receive function for this mac.  This removes the function
891  * from the list of receive functions for this mac.
892  */
893 void
894 mac_rx_remove(mac_handle_t mh, mac_rx_handle_t mrh)
895 {
896 	mac_impl_t		*mip = (mac_impl_t *)mh;
897 	mac_rx_fn_t		*mrfp = (mac_rx_fn_t *)mrh;
898 	mac_rx_fn_t		**pp;
899 	mac_rx_fn_t		*p;
900 
901 	/*
902 	 * Search the 'rx' callback list for the function closure.
903 	 */
904 	rw_enter(&(mip->mi_rx_lock), RW_WRITER);
905 	for (pp = &(mip->mi_mrfp); (p = *pp) != NULL; pp = &(p->mrf_nextp)) {
906 		if (p == mrfp)
907 			break;
908 	}
909 	ASSERT(p != NULL);
910 
911 	/* Remove it from the list. */
912 	*pp = p->mrf_nextp;
913 	kmem_free(mrfp, sizeof (mac_rx_fn_t));
914 	rw_exit(&(mip->mi_rx_lock));
915 }
916 
917 mac_txloop_handle_t
918 mac_txloop_add(mac_handle_t mh, mac_txloop_t tx, void *arg)
919 {
920 	mac_impl_t	*mip = (mac_impl_t *)mh;
921 	mac_txloop_fn_t	*mtfp;
922 
923 	mtfp = kmem_zalloc(sizeof (mac_txloop_fn_t), KM_SLEEP);
924 	mtfp->mtf_fn = tx;
925 	mtfp->mtf_arg = arg;
926 
927 	/*
928 	 * Add it to the head of the 'tx' callback list.
929 	 */
930 	rw_enter(&(mip->mi_txloop_lock), RW_WRITER);
931 	mtfp->mtf_nextp = mip->mi_mtfp;
932 	mip->mi_mtfp = mtfp;
933 	rw_exit(&(mip->mi_txloop_lock));
934 
935 	return ((mac_txloop_handle_t)mtfp);
936 }
937 
938 /*
939  * Unregister a transmit function for this mac.  This removes the function
940  * from the list of transmit functions for this mac.
941  */
942 void
943 mac_txloop_remove(mac_handle_t mh, mac_txloop_handle_t mth)
944 {
945 	mac_impl_t		*mip = (mac_impl_t *)mh;
946 	mac_txloop_fn_t		*mtfp = (mac_txloop_fn_t *)mth;
947 	mac_txloop_fn_t		**pp;
948 	mac_txloop_fn_t		*p;
949 
950 	/*
951 	 * Search the 'tx' callback list for the function.
952 	 */
953 	rw_enter(&(mip->mi_txloop_lock), RW_WRITER);
954 	for (pp = &(mip->mi_mtfp); (p = *pp) != NULL; pp = &(p->mtf_nextp)) {
955 		if (p == mtfp)
956 			break;
957 	}
958 	ASSERT(p != NULL);
959 
960 	/* Remove it from the list. */
961 	*pp = p->mtf_nextp;
962 	kmem_free(mtfp, sizeof (mac_txloop_fn_t));
963 	rw_exit(&(mip->mi_txloop_lock));
964 }
965 
966 void
967 mac_resource_set(mac_handle_t mh, mac_resource_add_t add, void *arg)
968 {
969 	mac_impl_t		*mip = (mac_impl_t *)mh;
970 
971 	/*
972 	 * Update the 'resource_add' callbacks.
973 	 */
974 	rw_enter(&(mip->mi_resource_lock), RW_WRITER);
975 	mip->mi_resource_add = add;
976 	mip->mi_resource_add_arg = arg;
977 	rw_exit(&(mip->mi_resource_lock));
978 }
979 
980 /*
981  * Driver support functions.
982  */
983 
984 mac_register_t *
985 mac_alloc(uint_t mac_version)
986 {
987 	mac_register_t *mregp;
988 
989 	/*
990 	 * Make sure there isn't a version mismatch between the driver and
991 	 * the framework.  In the future, if multiple versions are
992 	 * supported, this check could become more sophisticated.
993 	 */
994 	if (mac_version != MAC_VERSION)
995 		return (NULL);
996 
997 	mregp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP);
998 	mregp->m_version = mac_version;
999 	return (mregp);
1000 }
1001 
1002 void
1003 mac_free(mac_register_t *mregp)
1004 {
1005 	kmem_free(mregp, sizeof (mac_register_t));
1006 }
1007 
1008 /*
1009  * mac_register() is how drivers register new MACs with the GLDv3
1010  * framework.  The mregp argument is allocated by drivers using the
1011  * mac_alloc() function, and can be freed using mac_free() immediately upon
1012  * return from mac_register().  Upon success (0 return value), the mhp
1013  * opaque pointer becomes the driver's handle to its MAC interface, and is
1014  * the argument to all other mac module entry points.
1015  */
1016 /* ARGSUSED */
1017 int
1018 mac_register(mac_register_t *mregp, mac_handle_t *mhp)
1019 {
1020 	mac_impl_t	*mip;
1021 	mactype_t	*mtype;
1022 	int		err;
1023 	struct devnames *dnp;
1024 	minor_t		minor;
1025 	mod_hash_val_t	val;
1026 	boolean_t	style1_created = B_FALSE, style2_created = B_FALSE;
1027 
1028 	/* Find the required MAC-Type plugin. */
1029 	if ((mtype = i_mactype_getplugin(mregp->m_type_ident)) == NULL)
1030 		return (EINVAL);
1031 
1032 	/* Create a mac_impl_t to represent this MAC. */
1033 	mip = kmem_cache_alloc(i_mac_impl_cachep, KM_SLEEP);
1034 
1035 	/*
1036 	 * The mac is not ready for open yet.
1037 	 */
1038 	mip->mi_disabled = B_TRUE;
1039 
1040 	mip->mi_drvname = ddi_driver_name(mregp->m_dip);
1041 	/*
1042 	 * Some drivers such as aggr need to register multiple MACs.  Such
1043 	 * drivers must supply a non-zero "instance" argument so that each
1044 	 * MAC can be assigned a unique MAC name and can have unique
1045 	 * kstats.
1046 	 */
1047 	mip->mi_instance = ((mregp->m_instance == 0) ?
1048 	    ddi_get_instance(mregp->m_dip) : mregp->m_instance);
1049 
1050 	/* Construct the MAC name as <drvname><instance> */
1051 	(void) snprintf(mip->mi_name, sizeof (mip->mi_name), "%s%d",
1052 	    mip->mi_drvname, mip->mi_instance);
1053 
1054 	rw_enter(&i_mac_impl_lock, RW_WRITER);
1055 	if (mod_hash_insert(i_mac_impl_hash,
1056 	    (mod_hash_key_t)mip->mi_name, (mod_hash_val_t)mip) != 0) {
1057 		kmem_cache_free(i_mac_impl_cachep, mip);
1058 		rw_exit(&i_mac_impl_lock);
1059 		return (EEXIST);
1060 	}
1061 	i_mac_impl_count++;
1062 
1063 	mip->mi_driver = mregp->m_driver;
1064 
1065 	mip->mi_type = mtype;
1066 
1067 	mip->mi_info.mi_media = mtype->mt_type;
1068 	mip->mi_info.mi_sdu_min = mregp->m_min_sdu;
1069 	if (mregp->m_max_sdu <= mregp->m_min_sdu) {
1070 		err = EINVAL;
1071 		goto fail;
1072 	}
1073 	mip->mi_info.mi_sdu_max = mregp->m_max_sdu;
1074 	mip->mi_info.mi_addr_length = mip->mi_type->mt_addr_length;
1075 	/*
1076 	 * If the media supports a broadcast address, cache a pointer to it
1077 	 * in the mac_info_t so that upper layers can use it.
1078 	 */
1079 	mip->mi_info.mi_brdcst_addr = mip->mi_type->mt_brdcst_addr;
1080 
1081 	/*
1082 	 * Copy the unicast source address into the mac_info_t, but only if
1083 	 * the MAC-Type defines a non-zero address length.  We need to
1084 	 * handle MAC-Types that have an address length of 0
1085 	 * (point-to-point protocol MACs for example).
1086 	 */
1087 	if (mip->mi_type->mt_addr_length > 0) {
1088 		if (mregp->m_src_addr == NULL) {
1089 			err = EINVAL;
1090 			goto fail;
1091 		}
1092 		mip->mi_info.mi_unicst_addr =
1093 		    kmem_alloc(mip->mi_type->mt_addr_length, KM_SLEEP);
1094 		bcopy(mregp->m_src_addr, mip->mi_info.mi_unicst_addr,
1095 		    mip->mi_type->mt_addr_length);
1096 
1097 		/*
1098 		 * Copy the fixed 'factory' MAC address from the immutable
1099 		 * info.  This is taken to be the MAC address currently in
1100 		 * use.
1101 		 */
1102 		bcopy(mip->mi_info.mi_unicst_addr, mip->mi_addr,
1103 		    mip->mi_type->mt_addr_length);
1104 		/* Copy the destination address if one is provided. */
1105 		if (mregp->m_dst_addr != NULL) {
1106 			bcopy(mregp->m_dst_addr, mip->mi_dstaddr,
1107 			    mip->mi_type->mt_addr_length);
1108 		}
1109 	} else if (mregp->m_src_addr != NULL) {
1110 		err = EINVAL;
1111 		goto fail;
1112 	}
1113 
1114 	/*
1115 	 * The format of the m_pdata is specific to the plugin.  It is
1116 	 * passed in as an argument to all of the plugin callbacks.  The
1117 	 * driver can update this information by calling
1118 	 * mac_pdata_update().
1119 	 */
1120 	if (mregp->m_pdata != NULL) {
1121 		/*
1122 		 * Verify that the plugin supports MAC plugin data and that
1123 		 * the supplied data is valid.
1124 		 */
1125 		if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY)) {
1126 			err = EINVAL;
1127 			goto fail;
1128 		}
1129 		if (!mip->mi_type->mt_ops.mtops_pdata_verify(mregp->m_pdata,
1130 		    mregp->m_pdata_size)) {
1131 			err = EINVAL;
1132 			goto fail;
1133 		}
1134 		mip->mi_pdata = kmem_alloc(mregp->m_pdata_size, KM_SLEEP);
1135 		bcopy(mregp->m_pdata, mip->mi_pdata, mregp->m_pdata_size);
1136 		mip->mi_pdata_size = mregp->m_pdata_size;
1137 	}
1138 
1139 	/*
1140 	 * Stash the driver callbacks into the mac_impl_t, but first sanity
1141 	 * check to make sure all mandatory callbacks are set.
1142 	 */
1143 	if (mregp->m_callbacks->mc_getstat == NULL ||
1144 	    mregp->m_callbacks->mc_start == NULL ||
1145 	    mregp->m_callbacks->mc_stop == NULL ||
1146 	    mregp->m_callbacks->mc_setpromisc == NULL ||
1147 	    mregp->m_callbacks->mc_multicst == NULL ||
1148 	    mregp->m_callbacks->mc_unicst == NULL ||
1149 	    mregp->m_callbacks->mc_tx == NULL) {
1150 		err = EINVAL;
1151 		goto fail;
1152 	}
1153 	mip->mi_callbacks = mregp->m_callbacks;
1154 
1155 	mip->mi_dip = mregp->m_dip;
1156 
1157 	/*
1158 	 * Set up the two possible transmit routines.
1159 	 */
1160 	mip->mi_txinfo.mt_fn = mip->mi_tx;
1161 	mip->mi_txinfo.mt_arg = mip->mi_driver;
1162 	mip->mi_txloopinfo.mt_fn = mac_txloop;
1163 	mip->mi_txloopinfo.mt_arg = mip;
1164 
1165 	/*
1166 	 * Initialize the kstats for this device.
1167 	 */
1168 	mac_stat_create(mip);
1169 
1170 	err = EEXIST;
1171 	/* Create a style-2 DLPI device */
1172 	if (ddi_create_minor_node(mip->mi_dip, (char *)mip->mi_drvname,
1173 	    S_IFCHR, 0, DDI_NT_NET, CLONE_DEV) != DDI_SUCCESS)
1174 		goto fail;
1175 	style2_created = B_TRUE;
1176 
1177 	/* Create a style-1 DLPI device */
1178 	minor = (minor_t)mip->mi_instance + 1;
1179 	if (ddi_create_minor_node(mip->mi_dip, mip->mi_name, S_IFCHR, minor,
1180 	    DDI_NT_NET, 0) != DDI_SUCCESS)
1181 		goto fail;
1182 	style1_created = B_TRUE;
1183 
1184 	/*
1185 	 * Create a link for this MAC.  The link name will be the same as
1186 	 * the MAC name.
1187 	 */
1188 	err = dls_create(mip->mi_name, mip->mi_name,
1189 	    ddi_get_instance(mip->mi_dip));
1190 	if (err != 0)
1191 		goto fail;
1192 
1193 	/* set the gldv3 flag in dn_flags */
1194 	dnp = &devnamesp[ddi_driver_major(mip->mi_dip)];
1195 	LOCK_DEV_OPS(&dnp->dn_lock);
1196 	dnp->dn_flags |= DN_GLDV3_DRIVER;
1197 	UNLOCK_DEV_OPS(&dnp->dn_lock);
1198 
1199 	/*
1200 	 * Mark the MAC to be ready for open.
1201 	 */
1202 	mip->mi_disabled = B_FALSE;
1203 
1204 	cmn_err(CE_NOTE, "!%s registered", mip->mi_name);
1205 	rw_exit(&i_mac_impl_lock);
1206 	*mhp = (mac_handle_t)mip;
1207 	return (0);
1208 
1209 fail:
1210 	(void) mod_hash_remove(i_mac_impl_hash, (mod_hash_key_t)mip->mi_name,
1211 	    &val);
1212 	ASSERT(mip == (mac_impl_t *)val);
1213 	i_mac_impl_count--;
1214 
1215 	if (mip->mi_info.mi_unicst_addr != NULL) {
1216 		kmem_free(mip->mi_info.mi_unicst_addr,
1217 		    mip->mi_type->mt_addr_length);
1218 		mip->mi_info.mi_unicst_addr = NULL;
1219 	}
1220 	if (style1_created)
1221 		ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
1222 	if (style2_created)
1223 		ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname);
1224 
1225 	mac_stat_destroy(mip);
1226 
1227 	if (mip->mi_type != NULL) {
1228 		mip->mi_type->mt_ref--;
1229 		mip->mi_type = NULL;
1230 	}
1231 
1232 	if (mip->mi_pdata != NULL) {
1233 		kmem_free(mip->mi_pdata, mip->mi_pdata_size);
1234 		mip->mi_pdata = NULL;
1235 		mip->mi_pdata_size = 0;
1236 	}
1237 
1238 	kmem_cache_free(i_mac_impl_cachep, mip);
1239 	rw_exit(&i_mac_impl_lock);
1240 	return (err);
1241 }
1242 
1243 int
1244 mac_unregister(mac_handle_t mh)
1245 {
1246 	int			err;
1247 	mac_impl_t		*mip = (mac_impl_t *)mh;
1248 	mod_hash_val_t		val;
1249 	mac_multicst_addr_t	*p, *nextp;
1250 
1251 	/*
1252 	 * See if there are any other references to this mac_t (e.g., VLAN's).
1253 	 * If not, set mi_disabled to prevent any new VLAN's from being
1254 	 * created while we're destroying this mac.
1255 	 */
1256 	rw_enter(&i_mac_impl_lock, RW_WRITER);
1257 	if (mip->mi_ref > 0) {
1258 		rw_exit(&i_mac_impl_lock);
1259 		return (EBUSY);
1260 	}
1261 	mip->mi_disabled = B_TRUE;
1262 	rw_exit(&i_mac_impl_lock);
1263 
1264 	/*
1265 	 * Wait for all taskqs which process the mac notifications to finish.
1266 	 */
1267 	mutex_enter(&mip->mi_notify_ref_lock);
1268 	while (mip->mi_notify_ref != 0)
1269 		cv_wait(&mip->mi_notify_cv, &mip->mi_notify_ref_lock);
1270 	mutex_exit(&mip->mi_notify_ref_lock);
1271 
1272 	if ((err = dls_destroy(mip->mi_name)) != 0) {
1273 		rw_enter(&i_mac_impl_lock, RW_WRITER);
1274 		mip->mi_disabled = B_FALSE;
1275 		rw_exit(&i_mac_impl_lock);
1276 		return (err);
1277 	}
1278 
1279 	/*
1280 	 * Remove both style 1 and style 2 minor nodes
1281 	 */
1282 	ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname);
1283 	ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
1284 
1285 	ASSERT(!mip->mi_activelink);
1286 
1287 	mac_stat_destroy(mip);
1288 
1289 	(void) mod_hash_remove(i_mac_impl_hash, (mod_hash_key_t)mip->mi_name,
1290 	    &val);
1291 	ASSERT(mip == (mac_impl_t *)val);
1292 
1293 	ASSERT(i_mac_impl_count > 0);
1294 	i_mac_impl_count--;
1295 
1296 	if (mip->mi_pdata != NULL)
1297 		kmem_free(mip->mi_pdata, mip->mi_pdata_size);
1298 	mip->mi_pdata = NULL;
1299 	mip->mi_pdata_size = 0;
1300 
1301 	/*
1302 	 * Free the list of multicast addresses.
1303 	 */
1304 	for (p = mip->mi_mmap; p != NULL; p = nextp) {
1305 		nextp = p->mma_nextp;
1306 		kmem_free(p, sizeof (mac_multicst_addr_t));
1307 	}
1308 	mip->mi_mmap = NULL;
1309 
1310 	mip->mi_linkstate = LINK_STATE_UNKNOWN;
1311 	kmem_free(mip->mi_info.mi_unicst_addr, mip->mi_type->mt_addr_length);
1312 	mip->mi_info.mi_unicst_addr = NULL;
1313 
1314 	mip->mi_type->mt_ref--;
1315 	mip->mi_type = NULL;
1316 
1317 	cmn_err(CE_NOTE, "!%s unregistered", mip->mi_name);
1318 
1319 	kmem_cache_free(i_mac_impl_cachep, mip);
1320 
1321 	return (0);
1322 }
1323 
1324 void
1325 mac_rx(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *bp)
1326 {
1327 	mac_impl_t	*mip = (mac_impl_t *)mh;
1328 	mac_rx_fn_t	*mrfp;
1329 
1330 	/*
1331 	 * Call all registered receive functions.
1332 	 */
1333 	rw_enter(&mip->mi_rx_lock, RW_READER);
1334 	mrfp = mip->mi_mrfp;
1335 	if (mrfp == NULL) {
1336 		/* There are no registered receive functions. */
1337 		freemsgchain(bp);
1338 		rw_exit(&mip->mi_rx_lock);
1339 		return;
1340 	}
1341 	do {
1342 		mblk_t *recv_bp;
1343 
1344 		if (mrfp->mrf_nextp != NULL) {
1345 			/* XXX Do we bump a counter if copymsgchain() fails? */
1346 			recv_bp = copymsgchain(bp);
1347 		} else {
1348 			recv_bp = bp;
1349 		}
1350 		if (recv_bp != NULL)
1351 			mrfp->mrf_fn(mrfp->mrf_arg, mrh, recv_bp);
1352 		mrfp = mrfp->mrf_nextp;
1353 	} while (mrfp != NULL);
1354 	rw_exit(&mip->mi_rx_lock);
1355 }
1356 
1357 /*
1358  * Transmit function -- ONLY used when there are registered loopback listeners.
1359  */
1360 mblk_t *
1361 mac_txloop(void *arg, mblk_t *bp)
1362 {
1363 	mac_impl_t	*mip = arg;
1364 	mac_txloop_fn_t	*mtfp;
1365 	mblk_t		*loop_bp, *resid_bp, *next_bp;
1366 
1367 	while (bp != NULL) {
1368 		next_bp = bp->b_next;
1369 		bp->b_next = NULL;
1370 
1371 		if ((loop_bp = copymsg(bp)) == NULL)
1372 			goto noresources;
1373 
1374 		if ((resid_bp = mip->mi_tx(mip->mi_driver, bp)) != NULL) {
1375 			ASSERT(resid_bp == bp);
1376 			freemsg(loop_bp);
1377 			goto noresources;
1378 		}
1379 
1380 		rw_enter(&mip->mi_txloop_lock, RW_READER);
1381 		mtfp = mip->mi_mtfp;
1382 		while (mtfp != NULL && loop_bp != NULL) {
1383 			bp = loop_bp;
1384 
1385 			/* XXX counter bump if copymsg() fails? */
1386 			if (mtfp->mtf_nextp != NULL)
1387 				loop_bp = copymsg(bp);
1388 			else
1389 				loop_bp = NULL;
1390 
1391 			mtfp->mtf_fn(mtfp->mtf_arg, bp);
1392 			mtfp = mtfp->mtf_nextp;
1393 		}
1394 		rw_exit(&mip->mi_txloop_lock);
1395 
1396 		/*
1397 		 * It's possible we've raced with the disabling of promiscuous
1398 		 * mode, in which case we can discard our copy.
1399 		 */
1400 		if (loop_bp != NULL)
1401 			freemsg(loop_bp);
1402 
1403 		bp = next_bp;
1404 	}
1405 
1406 	return (NULL);
1407 
1408 noresources:
1409 	bp->b_next = next_bp;
1410 	return (bp);
1411 }
1412 
1413 void
1414 mac_link_update(mac_handle_t mh, link_state_t link)
1415 {
1416 	mac_impl_t	*mip = (mac_impl_t *)mh;
1417 
1418 	/*
1419 	 * Save the link state.
1420 	 */
1421 	mip->mi_linkstate = link;
1422 
1423 	/*
1424 	 * Send a MAC_NOTE_LINK notification.
1425 	 */
1426 	i_mac_notify(mip, MAC_NOTE_LINK);
1427 }
1428 
1429 void
1430 mac_unicst_update(mac_handle_t mh, const uint8_t *addr)
1431 {
1432 	mac_impl_t	*mip = (mac_impl_t *)mh;
1433 
1434 	if (mip->mi_type->mt_addr_length == 0)
1435 		return;
1436 
1437 	/*
1438 	 * Save the address.
1439 	 */
1440 	bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length);
1441 
1442 	/*
1443 	 * Send a MAC_NOTE_UNICST notification.
1444 	 */
1445 	i_mac_notify(mip, MAC_NOTE_UNICST);
1446 }
1447 
1448 void
1449 mac_tx_update(mac_handle_t mh)
1450 {
1451 	/*
1452 	 * Send a MAC_NOTE_TX notification.
1453 	 */
1454 	i_mac_notify((mac_impl_t *)mh, MAC_NOTE_TX);
1455 }
1456 
1457 void
1458 mac_resource_update(mac_handle_t mh)
1459 {
1460 	/*
1461 	 * Send a MAC_NOTE_RESOURCE notification.
1462 	 */
1463 	i_mac_notify((mac_impl_t *)mh, MAC_NOTE_RESOURCE);
1464 }
1465 
1466 mac_resource_handle_t
1467 mac_resource_add(mac_handle_t mh, mac_resource_t *mrp)
1468 {
1469 	mac_impl_t		*mip = (mac_impl_t *)mh;
1470 	mac_resource_handle_t	mrh;
1471 	mac_resource_add_t	add;
1472 	void			*arg;
1473 
1474 	rw_enter(&mip->mi_resource_lock, RW_READER);
1475 	add = mip->mi_resource_add;
1476 	arg = mip->mi_resource_add_arg;
1477 
1478 	if (add != NULL)
1479 		mrh = add(arg, mrp);
1480 	else
1481 		mrh = NULL;
1482 	rw_exit(&mip->mi_resource_lock);
1483 
1484 	return (mrh);
1485 }
1486 
1487 int
1488 mac_pdata_update(mac_handle_t mh, void *mac_pdata, size_t dsize)
1489 {
1490 	mac_impl_t	*mip = (mac_impl_t *)mh;
1491 
1492 	/*
1493 	 * Verify that the plugin supports MAC plugin data and that the
1494 	 * supplied data is valid.
1495 	 */
1496 	if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY))
1497 		return (EINVAL);
1498 	if (!mip->mi_type->mt_ops.mtops_pdata_verify(mac_pdata, dsize))
1499 		return (EINVAL);
1500 
1501 	if (mip->mi_pdata != NULL)
1502 		kmem_free(mip->mi_pdata, mip->mi_pdata_size);
1503 
1504 	mip->mi_pdata = kmem_alloc(dsize, KM_SLEEP);
1505 	bcopy(mac_pdata, mip->mi_pdata, dsize);
1506 	mip->mi_pdata_size = dsize;
1507 
1508 	/*
1509 	 * Since the MAC plugin data is used to construct MAC headers that
1510 	 * were cached in fast-path headers, we need to flush fast-path
1511 	 * information for links associated with this mac.
1512 	 */
1513 	i_mac_notify(mip, MAC_NOTE_FASTPATH_FLUSH);
1514 	return (0);
1515 }
1516 
1517 void
1518 mac_multicst_refresh(mac_handle_t mh, mac_multicst_t refresh, void *arg,
1519     boolean_t add)
1520 {
1521 	mac_impl_t		*mip = (mac_impl_t *)mh;
1522 	mac_multicst_addr_t	*p;
1523 
1524 	/*
1525 	 * If no specific refresh function was given then default to the
1526 	 * driver's m_multicst entry point.
1527 	 */
1528 	if (refresh == NULL) {
1529 		refresh = mip->mi_multicst;
1530 		arg = mip->mi_driver;
1531 	}
1532 	ASSERT(refresh != NULL);
1533 
1534 	/*
1535 	 * Walk the multicast address list and call the refresh function for
1536 	 * each address.
1537 	 */
1538 	rw_enter(&(mip->mi_data_lock), RW_READER);
1539 	for (p = mip->mi_mmap; p != NULL; p = p->mma_nextp)
1540 		refresh(arg, add, p->mma_addr);
1541 	rw_exit(&(mip->mi_data_lock));
1542 }
1543 
1544 void
1545 mac_unicst_refresh(mac_handle_t mh, mac_unicst_t refresh, void *arg)
1546 {
1547 	mac_impl_t	*mip = (mac_impl_t *)mh;
1548 	/*
1549 	 * If no specific refresh function was given then default to the
1550 	 * driver's mi_unicst entry point.
1551 	 */
1552 	if (refresh == NULL) {
1553 		refresh = mip->mi_unicst;
1554 		arg = mip->mi_driver;
1555 	}
1556 	ASSERT(refresh != NULL);
1557 
1558 	/*
1559 	 * Call the refresh function with the current unicast address.
1560 	 */
1561 	refresh(arg, mip->mi_addr);
1562 }
1563 
1564 void
1565 mac_promisc_refresh(mac_handle_t mh, mac_setpromisc_t refresh, void *arg)
1566 {
1567 	mac_impl_t	*mip = (mac_impl_t *)mh;
1568 
1569 	/*
1570 	 * If no specific refresh function was given then default to the
1571 	 * driver's m_promisc entry point.
1572 	 */
1573 	if (refresh == NULL) {
1574 		refresh = mip->mi_setpromisc;
1575 		arg = mip->mi_driver;
1576 	}
1577 	ASSERT(refresh != NULL);
1578 
1579 	/*
1580 	 * Call the refresh function with the current promiscuity.
1581 	 */
1582 	refresh(arg, (mip->mi_devpromisc != 0));
1583 }
1584 
1585 boolean_t
1586 mac_active_set(mac_handle_t mh)
1587 {
1588 	mac_impl_t *mip = (mac_impl_t *)mh;
1589 
1590 	mutex_enter(&mip->mi_activelink_lock);
1591 	if (mip->mi_activelink) {
1592 		mutex_exit(&mip->mi_activelink_lock);
1593 		return (B_FALSE);
1594 	}
1595 	mip->mi_activelink = B_TRUE;
1596 	mutex_exit(&mip->mi_activelink_lock);
1597 	return (B_TRUE);
1598 }
1599 
1600 void
1601 mac_active_clear(mac_handle_t mh)
1602 {
1603 	mac_impl_t *mip = (mac_impl_t *)mh;
1604 
1605 	mutex_enter(&mip->mi_activelink_lock);
1606 	ASSERT(mip->mi_activelink);
1607 	mip->mi_activelink = B_FALSE;
1608 	mutex_exit(&mip->mi_activelink_lock);
1609 }
1610 
1611 /*
1612  * mac_info_get() is used for retrieving the mac_info when a DL_INFO_REQ is
1613  * issued before a DL_ATTACH_REQ. we walk the i_mac_impl_hash table and find
1614  * the first mac_impl_t with a matching driver name; then we copy its mac_info_t
1615  * to the caller. we do all this with i_mac_impl_lock held so the mac_impl_t
1616  * cannot disappear while we are accessing it.
1617  */
1618 typedef struct i_mac_info_state_s {
1619 	const char	*mi_name;
1620 	mac_info_t	*mi_infop;
1621 } i_mac_info_state_t;
1622 
1623 /*ARGSUSED*/
1624 static uint_t
1625 i_mac_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
1626 {
1627 	i_mac_info_state_t	*statep = arg;
1628 	mac_impl_t		*mip = (mac_impl_t *)val;
1629 
1630 	if (mip->mi_disabled)
1631 		return (MH_WALK_CONTINUE);
1632 
1633 	if (strcmp(statep->mi_name,
1634 	    ddi_driver_name(mip->mi_dip)) != 0)
1635 		return (MH_WALK_CONTINUE);
1636 
1637 	statep->mi_infop = &mip->mi_info;
1638 	return (MH_WALK_TERMINATE);
1639 }
1640 
1641 boolean_t
1642 mac_info_get(const char *name, mac_info_t *minfop)
1643 {
1644 	i_mac_info_state_t	state;
1645 
1646 	rw_enter(&i_mac_impl_lock, RW_READER);
1647 	state.mi_name = name;
1648 	state.mi_infop = NULL;
1649 	mod_hash_walk(i_mac_impl_hash, i_mac_info_walker, &state);
1650 	if (state.mi_infop == NULL) {
1651 		rw_exit(&i_mac_impl_lock);
1652 		return (B_FALSE);
1653 	}
1654 	*minfop = *state.mi_infop;
1655 	rw_exit(&i_mac_impl_lock);
1656 	return (B_TRUE);
1657 }
1658 
1659 boolean_t
1660 mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data)
1661 {
1662 	mac_impl_t *mip = (mac_impl_t *)mh;
1663 
1664 	if (mip->mi_callbacks->mc_callbacks & MC_GETCAPAB)
1665 		return (mip->mi_getcapab(mip->mi_driver, cap, cap_data));
1666 	else
1667 		return (B_FALSE);
1668 }
1669 
1670 boolean_t
1671 mac_sap_verify(mac_handle_t mh, uint32_t sap, uint32_t *bind_sap)
1672 {
1673 	mac_impl_t	*mip = (mac_impl_t *)mh;
1674 	return (mip->mi_type->mt_ops.mtops_sap_verify(sap, bind_sap,
1675 	    mip->mi_pdata));
1676 }
1677 
1678 mblk_t *
1679 mac_header(mac_handle_t mh, const uint8_t *daddr, uint32_t sap, mblk_t *payload,
1680     size_t extra_len)
1681 {
1682 	mac_impl_t	*mip = (mac_impl_t *)mh;
1683 	return (mip->mi_type->mt_ops.mtops_header(mip->mi_addr, daddr, sap,
1684 	    mip->mi_pdata, payload, extra_len));
1685 }
1686 
1687 int
1688 mac_header_info(mac_handle_t mh, mblk_t *mp, mac_header_info_t *mhip)
1689 {
1690 	mac_impl_t	*mip = (mac_impl_t *)mh;
1691 	return (mip->mi_type->mt_ops.mtops_header_info(mp, mip->mi_pdata,
1692 	    mhip));
1693 }
1694 
1695 mblk_t *
1696 mac_header_cook(mac_handle_t mh, mblk_t *mp)
1697 {
1698 	mac_impl_t	*mip = (mac_impl_t *)mh;
1699 	if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_COOK) {
1700 		if (DB_REF(mp) > 1) {
1701 			mblk_t *newmp = copymsg(mp);
1702 			freemsg(mp);
1703 			mp = newmp;
1704 		}
1705 		return (mip->mi_type->mt_ops.mtops_header_cook(mp,
1706 		    mip->mi_pdata));
1707 	}
1708 	return (mp);
1709 }
1710 
1711 mblk_t *
1712 mac_header_uncook(mac_handle_t mh, mblk_t *mp)
1713 {
1714 	mac_impl_t	*mip = (mac_impl_t *)mh;
1715 	if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_UNCOOK) {
1716 		if (DB_REF(mp) > 1) {
1717 			mblk_t *newmp = copymsg(mp);
1718 			freemsg(mp);
1719 			mp = newmp;
1720 		}
1721 		return (mip->mi_type->mt_ops.mtops_header_uncook(mp,
1722 		    mip->mi_pdata));
1723 	}
1724 	return (mp);
1725 }
1726 
1727 void
1728 mac_init_ops(struct dev_ops *ops, const char *name)
1729 {
1730 	dld_init_ops(ops, name);
1731 }
1732 
1733 void
1734 mac_fini_ops(struct dev_ops *ops)
1735 {
1736 	dld_fini_ops(ops);
1737 }
1738 
1739 /*
1740  * MAC Type Plugin functions.
1741  */
1742 
1743 mactype_register_t *
1744 mactype_alloc(uint_t mactype_version)
1745 {
1746 	mactype_register_t *mtrp;
1747 
1748 	/*
1749 	 * Make sure there isn't a version mismatch between the plugin and
1750 	 * the framework.  In the future, if multiple versions are
1751 	 * supported, this check could become more sophisticated.
1752 	 */
1753 	if (mactype_version != MACTYPE_VERSION)
1754 		return (NULL);
1755 
1756 	mtrp = kmem_zalloc(sizeof (mactype_register_t), KM_SLEEP);
1757 	mtrp->mtr_version = mactype_version;
1758 	return (mtrp);
1759 }
1760 
1761 void
1762 mactype_free(mactype_register_t *mtrp)
1763 {
1764 	kmem_free(mtrp, sizeof (mactype_register_t));
1765 }
1766 
1767 int
1768 mactype_register(mactype_register_t *mtrp)
1769 {
1770 	mactype_t	*mtp;
1771 	mactype_ops_t	*ops = mtrp->mtr_ops;
1772 
1773 	/* Do some sanity checking before we register this MAC type. */
1774 	if (mtrp->mtr_ident == NULL || ops == NULL || mtrp->mtr_addrlen == 0)
1775 		return (EINVAL);
1776 
1777 	/*
1778 	 * Verify that all mandatory callbacks are set in the ops
1779 	 * vector.
1780 	 */
1781 	if (ops->mtops_unicst_verify == NULL ||
1782 	    ops->mtops_multicst_verify == NULL ||
1783 	    ops->mtops_sap_verify == NULL ||
1784 	    ops->mtops_header == NULL ||
1785 	    ops->mtops_header_info == NULL) {
1786 		return (EINVAL);
1787 	}
1788 
1789 	mtp = kmem_zalloc(sizeof (*mtp), KM_SLEEP);
1790 	mtp->mt_ident = mtrp->mtr_ident;
1791 	mtp->mt_ops = *ops;
1792 	mtp->mt_type = mtrp->mtr_mactype;
1793 	mtp->mt_addr_length = mtrp->mtr_addrlen;
1794 	if (mtrp->mtr_brdcst_addr != NULL) {
1795 		mtp->mt_brdcst_addr = kmem_alloc(mtrp->mtr_addrlen, KM_SLEEP);
1796 		bcopy(mtrp->mtr_brdcst_addr, mtp->mt_brdcst_addr,
1797 		    mtrp->mtr_addrlen);
1798 	}
1799 
1800 	mtp->mt_stats = mtrp->mtr_stats;
1801 	mtp->mt_statcount = mtrp->mtr_statcount;
1802 
1803 	/*
1804 	 * A MAC-Type plugin only registers when i_mactype_getplugin() does
1805 	 * an explicit modload() as a result of a driver requesting to use
1806 	 * that plugin in mac_register().  We pre-emptively set the initial
1807 	 * reference count to 1 here to prevent the plugin module from
1808 	 * unloading before the driver's mac_register() completes.  If we
1809 	 * were to initialize the reference count to 0, then there would be
1810 	 * a window during which the module could unload before the
1811 	 * reference count could be bumped up to 1.
1812 	 */
1813 	mtp->mt_ref = 1;
1814 
1815 	if (mod_hash_insert(i_mactype_hash,
1816 	    (mod_hash_key_t)mtp->mt_ident, (mod_hash_val_t)mtp) != 0) {
1817 		kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length);
1818 		kmem_free(mtp, sizeof (*mtp));
1819 		return (EEXIST);
1820 	}
1821 	return (0);
1822 }
1823 
1824 int
1825 mactype_unregister(const char *ident)
1826 {
1827 	mactype_t	*mtp;
1828 	mod_hash_val_t	val;
1829 	int 		err;
1830 
1831 	/*
1832 	 * Let's not allow MAC drivers to use this plugin while we're
1833 	 * trying to unregister it...
1834 	 */
1835 	rw_enter(&i_mac_impl_lock, RW_WRITER);
1836 
1837 	if ((err = mod_hash_find(i_mactype_hash, (mod_hash_key_t)ident,
1838 	    (mod_hash_val_t *)&mtp)) != 0) {
1839 		/* A plugin is trying to unregister, but it never registered. */
1840 		rw_exit(&i_mac_impl_lock);
1841 		return (ENXIO);
1842 	}
1843 
1844 	if (mtp->mt_ref > 0) {
1845 		rw_exit(&i_mac_impl_lock);
1846 		return (EBUSY);
1847 	}
1848 
1849 	err = mod_hash_remove(i_mactype_hash, (mod_hash_key_t)ident, &val);
1850 	ASSERT(err == 0);
1851 	if (err != 0) {
1852 		/* This should never happen, thus the ASSERT() above. */
1853 		rw_exit(&i_mac_impl_lock);
1854 		return (EINVAL);
1855 	}
1856 	ASSERT(mtp == (mactype_t *)val);
1857 
1858 	kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length);
1859 	kmem_free(mtp, sizeof (mactype_t));
1860 	rw_exit(&i_mac_impl_lock);
1861 
1862 	return (0);
1863 }
1864