1/*
2 * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#include "kpi_interface.h"
30
31#include <sys/queue.h>
32#include <sys/param.h>	/* for definition of NULL */
33#include <kern/debug.h> /* for panic */
34#include <sys/errno.h>
35#include <sys/socket.h>
36#include <sys/kern_event.h>
37#include <sys/kernel.h>
38#include <sys/malloc.h>
39#include <sys/kpi_mbuf.h>
40#include <sys/mcache.h>
41#include <sys/protosw.h>
42#include <net/if_var.h>
43#include <net/if_dl.h>
44#include <net/dlil.h>
45#include <net/if_types.h>
46#include <net/if_dl.h>
47#include <net/if_arp.h>
48#include <net/if_llreach.h>
49#include <net/route.h>
50#include <libkern/libkern.h>
51#include <libkern/OSAtomic.h>
52#include <kern/locks.h>
53#include <kern/clock.h>
54#include <sys/sockio.h>
55#include <sys/proc.h>
56#include <sys/sysctl.h>
57#include <sys/mbuf.h>
58#ifdef INET
59#include <netinet/igmp_var.h>
60#endif
61#ifdef INET6
62#include <netinet6/mld6_var.h>
63#endif
64
65#include "net/net_str_id.h"
66
67#if IF_LASTCHANGEUPTIME
68#define	TOUCHLASTCHANGE(__if_lastchange) {				\
69	(__if_lastchange)->tv_sec = net_uptime();			\
70	(__if_lastchange)->tv_usec = 0;					\
71}
72#else
73#define	TOUCHLASTCHANGE(__if_lastchange) microtime(__if_lastchange)
74#endif
75
76#define	_cast_non_const(p) ((void *)(uintptr_t)(p))
77
78static errno_t ifnet_defrouter_llreachinfo(ifnet_t, int,
79    struct ifnet_llreach_info *);
80static void ifnet_kpi_free(ifnet_t);
81static errno_t ifnet_list_get_common(ifnet_family_t, boolean_t, ifnet_t **,
82    u_int32_t *);
83static errno_t ifnet_set_lladdr_internal(ifnet_t, const void *, size_t,
84    u_char, int);
85static errno_t ifnet_awdl_check_eflags(ifnet_t, u_int32_t *, u_int32_t *);
86
87/*
88 * Temporary work around until we have real reference counting
89 *
90 * We keep the bits about calling dlil_if_release (which should be
91 * called recycle) transparent by calling it from our if_free function
92 * pointer. We have to keep the client's original detach function
93 * somewhere so we can call it.
94 */
95static void
96ifnet_kpi_free(ifnet_t ifp)
97{
98	ifnet_detached_func detach_func = ifp->if_kpi_storage;
99
100	if (detach_func != NULL)
101		detach_func(ifp);
102
103	if (ifp->if_broadcast.length > sizeof (ifp->if_broadcast.u.buffer)) {
104		FREE(ifp->if_broadcast.u.ptr, M_IFADDR);
105		ifp->if_broadcast.u.ptr = NULL;
106	}
107
108	dlil_if_release(ifp);
109}
110
111errno_t
112ifnet_allocate(const struct ifnet_init_params *init, ifnet_t *interface)
113{
114	struct ifnet_init_eparams einit;
115
116	bzero(&einit, sizeof (einit));
117
118	einit.ver		= IFNET_INIT_CURRENT_VERSION;
119	einit.len		= sizeof (einit);
120	einit.flags		= IFNET_INIT_LEGACY;
121	einit.uniqueid		= init->uniqueid;
122	einit.uniqueid_len	= init->uniqueid_len;
123	einit.name		= init->name;
124	einit.unit		= init->unit;
125	einit.family		= init->family;
126	einit.type		= init->type;
127	einit.output		= init->output;
128	einit.demux		= init->demux;
129	einit.add_proto		= init->add_proto;
130	einit.del_proto		= init->del_proto;
131	einit.check_multi	= init->check_multi;
132	einit.framer		= init->framer;
133	einit.softc		= init->softc;
134	einit.ioctl		= init->ioctl;
135	einit.set_bpf_tap	= init->set_bpf_tap;
136	einit.detach		= init->detach;
137	einit.event		= init->event;
138	einit.broadcast_addr	= init->broadcast_addr;
139	einit.broadcast_len	= init->broadcast_len;
140
141	return (ifnet_allocate_extended(&einit, interface));
142}
143
144errno_t
145ifnet_allocate_extended(const struct ifnet_init_eparams *einit0,
146    ifnet_t *interface)
147{
148	struct ifnet_init_eparams einit;
149	struct ifnet *ifp = NULL;
150	int error;
151
152	einit = *einit0;
153
154	if (einit.ver != IFNET_INIT_CURRENT_VERSION ||
155	    einit.len < sizeof (einit))
156		return (EINVAL);
157
158	if (einit.family == 0 || einit.name == NULL ||
159	    strlen(einit.name) >= IFNAMSIZ ||
160	    (einit.type & 0xFFFFFF00) != 0 || einit.type == 0)
161		return (EINVAL);
162
163	if (einit.flags & IFNET_INIT_LEGACY) {
164		if (einit.output == NULL || einit.flags != IFNET_INIT_LEGACY)
165			return (EINVAL);
166
167		einit.pre_enqueue = NULL;
168		einit.start = NULL;
169		einit.output_ctl = NULL;
170		einit.output_sched_model = IFNET_SCHED_MODEL_NORMAL;
171		einit.input_poll = NULL;
172		einit.input_ctl = NULL;
173	} else {
174		if (einit.start == NULL)
175			return (EINVAL);
176
177		einit.output = NULL;
178		if (einit.output_sched_model >= IFNET_SCHED_MODEL_MAX)
179			return (EINVAL);
180
181		if (einit.flags & IFNET_INIT_INPUT_POLL) {
182			if (einit.input_poll == NULL || einit.input_ctl == NULL)
183				return (EINVAL);
184		} else {
185			einit.input_poll = NULL;
186			einit.input_ctl = NULL;
187		}
188	}
189
190	error = dlil_if_acquire(einit.family, einit.uniqueid,
191	    einit.uniqueid_len, &ifp);
192
193	if (error == 0) {
194		u_int64_t br;
195
196		/*
197		 * Cast ifp->if_name as non const. dlil_if_acquire sets it up
198		 * to point to storage of at least IFNAMSIZ bytes. It is safe
199		 * to write to this.
200		 */
201		strncpy(_cast_non_const(ifp->if_name), einit.name, IFNAMSIZ);
202		ifp->if_type		= einit.type;
203		ifp->if_family		= einit.family;
204		ifp->if_unit		= einit.unit;
205		ifp->if_output		= einit.output;
206		ifp->if_pre_enqueue	= einit.pre_enqueue;
207		ifp->if_start		= einit.start;
208		ifp->if_output_ctl	= einit.output_ctl;
209		ifp->if_output_sched_model = einit.output_sched_model;
210		ifp->if_output_bw.eff_bw = einit.output_bw;
211		ifp->if_output_bw.max_bw = einit.output_bw_max;
212		ifp->if_input_poll	= einit.input_poll;
213		ifp->if_input_ctl	= einit.input_ctl;
214		ifp->if_input_bw.eff_bw	= einit.input_bw;
215		ifp->if_input_bw.max_bw	= einit.input_bw_max;
216		ifp->if_demux		= einit.demux;
217		ifp->if_add_proto	= einit.add_proto;
218		ifp->if_del_proto	= einit.del_proto;
219		ifp->if_check_multi	= einit.check_multi;
220		ifp->if_framer		= einit.framer;
221		ifp->if_softc		= einit.softc;
222		ifp->if_ioctl		= einit.ioctl;
223		ifp->if_set_bpf_tap	= einit.set_bpf_tap;
224		ifp->if_free		= ifnet_kpi_free;
225		ifp->if_event		= einit.event;
226		ifp->if_kpi_storage	= einit.detach;
227
228		if (ifp->if_output_bw.eff_bw > ifp->if_output_bw.max_bw)
229			ifp->if_output_bw.max_bw = ifp->if_output_bw.eff_bw;
230		else if (ifp->if_output_bw.eff_bw == 0)
231			ifp->if_output_bw.eff_bw = ifp->if_output_bw.max_bw;
232
233		if (ifp->if_input_bw.eff_bw > ifp->if_input_bw.max_bw)
234			ifp->if_input_bw.max_bw = ifp->if_input_bw.eff_bw;
235		else if (ifp->if_input_bw.eff_bw == 0)
236			ifp->if_input_bw.eff_bw = ifp->if_input_bw.max_bw;
237
238		if (ifp->if_output_bw.max_bw == 0)
239			ifp->if_output_bw = ifp->if_input_bw;
240		else if (ifp->if_input_bw.max_bw == 0)
241			ifp->if_input_bw = ifp->if_output_bw;
242
243		if (ifp->if_ioctl == NULL)
244			ifp->if_ioctl = ifp_if_ioctl;
245
246		/* Pin if_baudrate to 32 bits */
247		br = MAX(ifp->if_output_bw.max_bw, ifp->if_input_bw.max_bw);
248		if (br != 0)
249			ifp->if_baudrate = (br > 0xFFFFFFFF) ? 0xFFFFFFFF : br;
250
251		if (ifp->if_start != NULL) {
252			ifp->if_eflags |= IFEF_TXSTART;
253			if (ifp->if_pre_enqueue == NULL)
254				ifp->if_pre_enqueue = ifnet_enqueue;
255			ifp->if_output = ifp->if_pre_enqueue;
256		} else {
257			ifp->if_eflags &= ~IFEF_TXSTART;
258		}
259
260		if (ifp->if_input_poll != NULL)
261			ifp->if_eflags |= IFEF_RXPOLL;
262		else
263			ifp->if_eflags &= ~IFEF_RXPOLL;
264
265		VERIFY(!(einit.flags & IFNET_INIT_LEGACY) ||
266		    (ifp->if_pre_enqueue == NULL && ifp->if_start == NULL &&
267		    ifp->if_output_ctl == NULL && ifp->if_input_poll == NULL &&
268		    ifp->if_input_ctl == NULL));
269		VERIFY(!(einit.flags & IFNET_INIT_INPUT_POLL) ||
270		    (ifp->if_input_poll != NULL && ifp->if_input_ctl != NULL));
271
272		if (einit.broadcast_len && einit.broadcast_addr) {
273			if (einit.broadcast_len >
274			    sizeof (ifp->if_broadcast.u.buffer)) {
275				MALLOC(ifp->if_broadcast.u.ptr, u_char *,
276				    einit.broadcast_len, M_IFADDR, M_NOWAIT);
277				if (ifp->if_broadcast.u.ptr == NULL) {
278					error = ENOMEM;
279				} else {
280					bcopy(einit.broadcast_addr,
281					    ifp->if_broadcast.u.ptr,
282					    einit.broadcast_len);
283				}
284			} else {
285				bcopy(einit.broadcast_addr,
286				    ifp->if_broadcast.u.buffer,
287				    einit.broadcast_len);
288			}
289			ifp->if_broadcast.length = einit.broadcast_len;
290		} else {
291			bzero(&ifp->if_broadcast, sizeof (ifp->if_broadcast));
292		}
293
294		IFCQ_MAXLEN(&ifp->if_snd) = einit.sndq_maxlen;
295
296		if (error == 0) {
297			*interface = ifp;
298			// temporary - this should be done in dlil_if_acquire
299			ifnet_reference(ifp);
300		} else {
301			dlil_if_release(ifp);
302			*interface = NULL;
303		}
304	}
305
306	/*
307	 * Note: We should do something here to indicate that we haven't been
308	 * attached yet. By doing so, we can catch the case in ifnet_release
309	 * where the reference count reaches zero and call the recycle
310	 * function. If the interface is attached, the interface will be
311	 * recycled when the interface's if_free function is called. If the
312	 * interface is never attached, the if_free function will never be
313	 * called and the interface will never be recycled.
314	 */
315
316	return (error);
317}
318
319errno_t
320ifnet_reference(ifnet_t ifp)
321{
322	return (dlil_if_ref(ifp));
323}
324
325errno_t
326ifnet_release(ifnet_t ifp)
327{
328	return (dlil_if_free(ifp));
329}
330
331errno_t
332ifnet_interface_family_find(const char *module_string,
333    ifnet_family_t *family_id)
334{
335	if (module_string == NULL || family_id == NULL)
336		return (EINVAL);
337
338	return (net_str_id_find_internal(module_string, family_id,
339	    NSI_IF_FAM_ID, 1));
340}
341
342void *
343ifnet_softc(ifnet_t interface)
344{
345	return ((interface == NULL) ? NULL : interface->if_softc);
346}
347
348const char *
349ifnet_name(ifnet_t interface)
350{
351	return ((interface == NULL) ? NULL : interface->if_name);
352}
353
354ifnet_family_t
355ifnet_family(ifnet_t interface)
356{
357	return ((interface == NULL) ? 0 : interface->if_family);
358}
359
360u_int32_t
361ifnet_unit(ifnet_t interface)
362{
363	return ((interface == NULL) ? (u_int32_t)0xffffffff :
364	    (u_int32_t)interface->if_unit);
365}
366
367u_int32_t
368ifnet_index(ifnet_t interface)
369{
370	return ((interface == NULL) ? (u_int32_t)0xffffffff :
371	    interface->if_index);
372}
373
374errno_t
375ifnet_set_flags(ifnet_t interface, u_int16_t new_flags, u_int16_t mask)
376{
377	uint16_t old_flags;
378
379	if (interface == NULL)
380		return (EINVAL);
381
382	ifnet_lock_exclusive(interface);
383
384	/* If we are modifying the up/down state, call if_updown */
385	if ((mask & IFF_UP) != 0) {
386		if_updown(interface, (new_flags & IFF_UP) == IFF_UP);
387	}
388
389	old_flags = interface->if_flags;
390	interface->if_flags = (new_flags & mask) | (interface->if_flags & ~mask);
391	/* If we are modifying the multicast flag, set/unset the silent flag */
392	if ((old_flags & IFF_MULTICAST) !=
393	    (interface->if_flags & IFF_MULTICAST)) {
394#if INET
395		if (IGMP_IFINFO(interface) != NULL)
396			igmp_initsilent(interface, IGMP_IFINFO(interface));
397#endif /* INET */
398#if INET6
399		if (MLD_IFINFO(interface) != NULL)
400			mld6_initsilent(interface, MLD_IFINFO(interface));
401#endif /* INET6 */
402	}
403
404	ifnet_lock_done(interface);
405
406	return (0);
407}
408
409u_int16_t
410ifnet_flags(ifnet_t interface)
411{
412	return ((interface == NULL) ? 0 : interface->if_flags);
413}
414
415/*
416 * This routine ensures the following:
417 *
418 * If IFEF_AWDL is set by the caller, also set the rest of flags as
419 * defined in IFEF_AWDL_MASK.
420 *
421 * If IFEF_AWDL has been set on the interface and the caller attempts
422 * to clear one or more of the associated flags in IFEF_AWDL_MASK,
423 * return failure.
424 *
425 * All other flags not associated with AWDL are not affected.
426 *
427 * See <net/if.h> for current definition of IFEF_AWDL_MASK.
428 */
429static errno_t
430ifnet_awdl_check_eflags(ifnet_t ifp, u_int32_t *new_eflags, u_int32_t *mask)
431{
432	u_int32_t eflags;
433
434	ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
435
436	eflags = (*new_eflags & *mask) | (ifp->if_eflags & ~(*mask));
437
438	if (ifp->if_eflags & IFEF_AWDL) {
439		if (eflags & IFEF_AWDL) {
440			if ((eflags & IFEF_AWDL_MASK) != IFEF_AWDL_MASK)
441				return (1);
442		} else {
443			*new_eflags &= ~IFEF_AWDL_MASK;
444			*mask |= IFEF_AWDL_MASK;
445		}
446	} else if (eflags & IFEF_AWDL) {
447		*new_eflags |= IFEF_AWDL_MASK;
448		*mask |= IFEF_AWDL_MASK;
449	}
450
451	return (0);
452}
453
454errno_t
455ifnet_set_eflags(ifnet_t interface, u_int32_t new_flags, u_int32_t mask)
456{
457	if (interface == NULL)
458		return (EINVAL);
459
460	ifnet_lock_exclusive(interface);
461	/*
462	 * Sanity checks for IFEF_AWDL and its related flags.
463	 */
464	if (ifnet_awdl_check_eflags(interface, &new_flags, &mask) != 0) {
465		ifnet_lock_done(interface);
466		return (EINVAL);
467	}
468	interface->if_eflags =
469	    (new_flags & mask) | (interface->if_eflags & ~mask);
470	ifnet_lock_done(interface);
471
472	return (0);
473}
474
475u_int32_t
476ifnet_eflags(ifnet_t interface)
477{
478	return ((interface == NULL) ? 0 : interface->if_eflags);
479}
480
481errno_t
482ifnet_set_idle_flags_locked(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask)
483{
484	int before, after;
485
486	if (ifp == NULL)
487		return (EINVAL);
488
489	lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
490	ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
491
492	/*
493	 * If this is called prior to ifnet attach, the actual work will
494	 * be done at attach time.  Otherwise, if it is called after
495	 * ifnet detach, then it is a no-op.
496	 */
497	if (!ifnet_is_attached(ifp, 0)) {
498		ifp->if_idle_new_flags = new_flags;
499		ifp->if_idle_new_flags_mask = mask;
500		return (0);
501	} else {
502		ifp->if_idle_new_flags = ifp->if_idle_new_flags_mask = 0;
503	}
504
505	before = ifp->if_idle_flags;
506	ifp->if_idle_flags = (new_flags & mask) | (ifp->if_idle_flags & ~mask);
507	after = ifp->if_idle_flags;
508
509	if ((after - before) < 0 && ifp->if_idle_flags == 0 &&
510	    ifp->if_want_aggressive_drain != 0) {
511		ifp->if_want_aggressive_drain = 0;
512		if (ifnet_aggressive_drainers == 0)
513			panic("%s: ifp=%p negative aggdrain!", __func__, ifp);
514		if (--ifnet_aggressive_drainers == 0)
515			rt_aggdrain(0);
516	} else if ((after - before) > 0 && ifp->if_want_aggressive_drain == 0) {
517		ifp->if_want_aggressive_drain++;
518		if (++ifnet_aggressive_drainers == 0)
519			panic("%s: ifp=%p wraparound aggdrain!", __func__, ifp);
520		else if (ifnet_aggressive_drainers == 1)
521			rt_aggdrain(1);
522	}
523
524	return (0);
525}
526
527errno_t
528ifnet_set_idle_flags(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask)
529{
530	errno_t err;
531
532	lck_mtx_lock(rnh_lock);
533	ifnet_lock_exclusive(ifp);
534	err = ifnet_set_idle_flags_locked(ifp, new_flags, mask);
535	ifnet_lock_done(ifp);
536	lck_mtx_unlock(rnh_lock);
537
538	return (err);
539}
540
541u_int32_t
542ifnet_idle_flags(ifnet_t ifp)
543{
544	return ((ifp == NULL) ? 0 : ifp->if_idle_flags);
545}
546
547errno_t
548ifnet_set_link_quality(ifnet_t ifp, int quality)
549{
550	errno_t err = 0;
551
552	if (ifp == NULL || quality < IFNET_LQM_MIN || quality > IFNET_LQM_MAX) {
553		err = EINVAL;
554		goto done;
555	}
556
557	if (!ifnet_is_attached(ifp, 0)) {
558		err = ENXIO;
559		goto done;
560	}
561
562	if_lqm_update(ifp, quality);
563
564done:
565	return (err);
566}
567
568int
569ifnet_link_quality(ifnet_t ifp)
570{
571	int lqm;
572
573	if (ifp == NULL)
574		return (IFNET_LQM_THRESH_OFF);
575
576	ifnet_lock_shared(ifp);
577	lqm = ifp->if_lqm;
578	ifnet_lock_done(ifp);
579
580	return (lqm);
581}
582
583static errno_t
584ifnet_defrouter_llreachinfo(ifnet_t ifp, int af,
585    struct ifnet_llreach_info *iflri)
586{
587	if (ifp == NULL || iflri == NULL)
588		return (EINVAL);
589
590	VERIFY(af == AF_INET || af == AF_INET6);
591
592	return (ifnet_llreach_get_defrouter(ifp, af, iflri));
593}
594
595errno_t
596ifnet_inet_defrouter_llreachinfo(ifnet_t ifp, struct ifnet_llreach_info *iflri)
597{
598	return (ifnet_defrouter_llreachinfo(ifp, AF_INET, iflri));
599}
600
601errno_t
602ifnet_inet6_defrouter_llreachinfo(ifnet_t ifp, struct ifnet_llreach_info *iflri)
603{
604	return (ifnet_defrouter_llreachinfo(ifp, AF_INET6, iflri));
605}
606
607errno_t
608ifnet_set_capabilities_supported(ifnet_t ifp, u_int32_t new_caps,
609    u_int32_t mask)
610{
611	errno_t error = 0;
612	int tmp;
613
614	if (ifp == NULL)
615		return (EINVAL);
616
617	ifnet_lock_exclusive(ifp);
618	tmp = (new_caps & mask) | (ifp->if_capabilities & ~mask);
619	if ((tmp & ~IFCAP_VALID))
620		error = EINVAL;
621	else
622		ifp->if_capabilities = tmp;
623	ifnet_lock_done(ifp);
624
625	return (error);
626}
627
628u_int32_t
629ifnet_capabilities_supported(ifnet_t ifp)
630{
631	return ((ifp == NULL) ? 0 : ifp->if_capabilities);
632}
633
634
635errno_t
636ifnet_set_capabilities_enabled(ifnet_t ifp, u_int32_t new_caps,
637    u_int32_t mask)
638{
639	errno_t error = 0;
640	int tmp;
641	struct kev_msg ev_msg;
642	struct net_event_data ev_data;
643
644	if (ifp == NULL)
645		return (EINVAL);
646
647	ifnet_lock_exclusive(ifp);
648	tmp = (new_caps & mask) | (ifp->if_capenable & ~mask);
649	if ((tmp & ~IFCAP_VALID) || (tmp & ~ifp->if_capabilities))
650		error = EINVAL;
651	else
652		ifp->if_capenable = tmp;
653	ifnet_lock_done(ifp);
654
655	/* Notify application of the change */
656	bzero(&ev_data, sizeof (struct net_event_data));
657	bzero(&ev_msg, sizeof (struct kev_msg));
658	ev_msg.vendor_code	= KEV_VENDOR_APPLE;
659	ev_msg.kev_class	= KEV_NETWORK_CLASS;
660	ev_msg.kev_subclass	= KEV_DL_SUBCLASS;
661
662	ev_msg.event_code	= KEV_DL_IFCAP_CHANGED;
663	strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
664	ev_data.if_family	= ifp->if_family;
665	ev_data.if_unit		= (u_int32_t)ifp->if_unit;
666	ev_msg.dv[0].data_length = sizeof (struct net_event_data);
667	ev_msg.dv[0].data_ptr = &ev_data;
668	ev_msg.dv[1].data_length = 0;
669	kev_post_msg(&ev_msg);
670
671	return (error);
672}
673
674u_int32_t
675ifnet_capabilities_enabled(ifnet_t ifp)
676{
677	return ((ifp == NULL) ? 0 : ifp->if_capenable);
678}
679
680static const ifnet_offload_t offload_mask =
681	(IFNET_CSUM_IP | IFNET_CSUM_TCP | IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT |
682	IFNET_IP_FRAGMENT | IFNET_CSUM_TCPIPV6 | IFNET_CSUM_UDPIPV6 |
683	IFNET_IPV6_FRAGMENT | IFNET_CSUM_SUM16 | IFNET_VLAN_TAGGING |
684	IFNET_VLAN_MTU | IFNET_MULTIPAGES | IFNET_TSO_IPV4 | IFNET_TSO_IPV6);
685
686static const ifnet_offload_t any_offload_csum =
687	(IFNET_CSUM_IP | IFNET_CSUM_TCP | IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT |
688	IFNET_CSUM_TCPIPV6 | IFNET_CSUM_UDPIPV6 | IFNET_CSUM_SUM16);
689
690errno_t
691ifnet_set_offload(ifnet_t interface, ifnet_offload_t offload)
692{
693	u_int32_t ifcaps = 0;
694
695	if (interface == NULL)
696		return (EINVAL);
697
698	ifnet_lock_exclusive(interface);
699	interface->if_hwassist = (offload & offload_mask);
700	ifnet_lock_done(interface);
701
702	if ((offload & any_offload_csum))
703		ifcaps |= IFCAP_HWCSUM;
704	if ((offload & IFNET_TSO_IPV4))
705		ifcaps |= IFCAP_TSO4;
706	if ((offload & IFNET_TSO_IPV6))
707		ifcaps |= IFCAP_TSO6;
708	if ((offload & IFNET_VLAN_MTU))
709		ifcaps |= IFCAP_VLAN_MTU;
710	if ((offload & IFNET_VLAN_TAGGING))
711		ifcaps |= IFCAP_VLAN_HWTAGGING;
712	if (ifcaps != 0) {
713		(void) ifnet_set_capabilities_supported(interface, ifcaps,
714		    IFCAP_VALID);
715		(void) ifnet_set_capabilities_enabled(interface, ifcaps,
716		    IFCAP_VALID);
717	}
718
719	return (0);
720}
721
722ifnet_offload_t
723ifnet_offload(ifnet_t interface)
724{
725	return ((interface == NULL) ?
726	    0 : (interface->if_hwassist & offload_mask));
727}
728
729errno_t
730ifnet_set_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t mtuLen)
731{
732	errno_t error = 0;
733
734	if (interface == NULL || mtuLen < interface->if_mtu)
735		return (EINVAL);
736
737	switch (family) {
738	case AF_INET:
739		if (interface->if_hwassist & IFNET_TSO_IPV4)
740			interface->if_tso_v4_mtu = mtuLen;
741		else
742			error = EINVAL;
743		break;
744
745	case AF_INET6:
746		if (interface->if_hwassist & IFNET_TSO_IPV6)
747			interface->if_tso_v6_mtu = mtuLen;
748		else
749			error = EINVAL;
750		break;
751
752	default:
753		error = EPROTONOSUPPORT;
754		break;
755	}
756
757	return (error);
758}
759
760errno_t
761ifnet_get_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t *mtuLen)
762{
763	errno_t error = 0;
764
765	if (interface == NULL || mtuLen == NULL)
766		return (EINVAL);
767
768	switch (family) {
769	case AF_INET:
770		if (interface->if_hwassist & IFNET_TSO_IPV4)
771			*mtuLen = interface->if_tso_v4_mtu;
772		else
773			error = EINVAL;
774		break;
775
776	case AF_INET6:
777		if (interface->if_hwassist & IFNET_TSO_IPV6)
778			*mtuLen = interface->if_tso_v6_mtu;
779		else
780			error = EINVAL;
781		break;
782
783	default:
784		error = EPROTONOSUPPORT;
785		break;
786	}
787
788	return (error);
789}
790
791errno_t
792ifnet_set_wake_flags(ifnet_t interface, u_int32_t properties, u_int32_t mask)
793{
794	struct kev_msg ev_msg;
795	struct net_event_data ev_data;
796
797	bzero(&ev_data, sizeof (struct net_event_data));
798	bzero(&ev_msg, sizeof (struct kev_msg));
799
800	if (interface == NULL)
801		return (EINVAL);
802
803	/* Do not accept wacky values */
804	if ((properties & mask) & ~IF_WAKE_VALID_FLAGS)
805		return (EINVAL);
806
807	ifnet_lock_exclusive(interface);
808
809	interface->if_wake_properties =
810	    (properties & mask) | (interface->if_wake_properties & ~mask);
811
812	ifnet_lock_done(interface);
813
814	(void) ifnet_touch_lastchange(interface);
815
816	/* Notify application of the change */
817	ev_msg.vendor_code	= KEV_VENDOR_APPLE;
818	ev_msg.kev_class	= KEV_NETWORK_CLASS;
819	ev_msg.kev_subclass	= KEV_DL_SUBCLASS;
820
821	ev_msg.event_code	= KEV_DL_WAKEFLAGS_CHANGED;
822	strlcpy(&ev_data.if_name[0], interface->if_name, IFNAMSIZ);
823	ev_data.if_family	= interface->if_family;
824	ev_data.if_unit		= (u_int32_t)interface->if_unit;
825	ev_msg.dv[0].data_length = sizeof (struct net_event_data);
826	ev_msg.dv[0].data_ptr	= &ev_data;
827	ev_msg.dv[1].data_length = 0;
828	kev_post_msg(&ev_msg);
829
830	return (0);
831}
832
833u_int32_t
834ifnet_get_wake_flags(ifnet_t interface)
835{
836	return ((interface == NULL) ? 0 : interface->if_wake_properties);
837}
838
839/*
840 * Should MIB data store a copy?
841 */
842errno_t
843ifnet_set_link_mib_data(ifnet_t interface, void *mibData, u_int32_t mibLen)
844{
845	if (interface == NULL)
846		return (EINVAL);
847
848	ifnet_lock_exclusive(interface);
849	interface->if_linkmib = (void*)mibData;
850	interface->if_linkmiblen = mibLen;
851	ifnet_lock_done(interface);
852	return (0);
853}
854
855errno_t
856ifnet_get_link_mib_data(ifnet_t interface, void *mibData, u_int32_t *mibLen)
857{
858	errno_t	result = 0;
859
860	if (interface == NULL)
861		return (EINVAL);
862
863	ifnet_lock_shared(interface);
864	if (*mibLen < interface->if_linkmiblen)
865		result = EMSGSIZE;
866	if (result == 0 && interface->if_linkmib == NULL)
867		result = ENOTSUP;
868
869	if (result == 0) {
870		*mibLen = interface->if_linkmiblen;
871		bcopy(interface->if_linkmib, mibData, *mibLen);
872	}
873	ifnet_lock_done(interface);
874
875	return (result);
876}
877
878u_int32_t
879ifnet_get_link_mib_data_length(ifnet_t interface)
880{
881	return ((interface == NULL) ? 0 : interface->if_linkmiblen);
882}
883
884errno_t
885ifnet_output(ifnet_t interface, protocol_family_t protocol_family,
886    mbuf_t m, void *route, const struct sockaddr *dest)
887{
888	if (interface == NULL || protocol_family == 0 || m == NULL) {
889		if (m != NULL)
890			mbuf_freem_list(m);
891		return (EINVAL);
892	}
893	return (dlil_output(interface, protocol_family, m, route, dest, 0, NULL));
894}
895
896errno_t
897ifnet_output_raw(ifnet_t interface, protocol_family_t protocol_family, mbuf_t m)
898{
899	if (interface == NULL || m == NULL) {
900		if (m != NULL)
901			mbuf_freem_list(m);
902		return (EINVAL);
903	}
904	return (dlil_output(interface, protocol_family, m, NULL, NULL, 1, NULL));
905}
906
907errno_t
908ifnet_set_mtu(ifnet_t interface, u_int32_t mtu)
909{
910	if (interface == NULL)
911		return (EINVAL);
912
913	interface->if_mtu = mtu;
914	return (0);
915}
916
917u_int32_t
918ifnet_mtu(ifnet_t interface)
919{
920	return ((interface == NULL) ? 0 : interface->if_mtu);
921}
922
923u_char
924ifnet_type(ifnet_t interface)
925{
926	return ((interface == NULL) ? 0 : interface->if_data.ifi_type);
927}
928
929errno_t
930ifnet_set_addrlen(ifnet_t interface, u_char addrlen)
931{
932	if (interface == NULL)
933		return (EINVAL);
934
935	interface->if_data.ifi_addrlen = addrlen;
936	return (0);
937}
938
939u_char
940ifnet_addrlen(ifnet_t interface)
941{
942	return ((interface == NULL) ? 0 : interface->if_data.ifi_addrlen);
943}
944
945errno_t
946ifnet_set_hdrlen(ifnet_t interface, u_char hdrlen)
947{
948	if (interface == NULL)
949		return (EINVAL);
950
951	interface->if_data.ifi_hdrlen = hdrlen;
952	return (0);
953}
954
955u_char
956ifnet_hdrlen(ifnet_t interface)
957{
958	return ((interface == NULL) ? 0 : interface->if_data.ifi_hdrlen);
959}
960
961errno_t
962ifnet_set_metric(ifnet_t interface, u_int32_t metric)
963{
964	if (interface == NULL)
965		return (EINVAL);
966
967	interface->if_data.ifi_metric = metric;
968	return (0);
969}
970
971u_int32_t
972ifnet_metric(ifnet_t interface)
973{
974	return ((interface == NULL) ? 0 : interface->if_data.ifi_metric);
975}
976
977errno_t
978ifnet_set_baudrate(struct ifnet *ifp, u_int64_t baudrate)
979{
980	if (ifp == NULL)
981		return (EINVAL);
982
983	ifp->if_output_bw.max_bw = ifp->if_input_bw.max_bw =
984	    ifp->if_output_bw.eff_bw = ifp->if_input_bw.eff_bw = baudrate;
985
986	/* Pin if_baudrate to 32 bits until we can change the storage size */
987	ifp->if_baudrate = (baudrate > 0xFFFFFFFF) ? 0xFFFFFFFF : baudrate;
988
989	return (0);
990}
991
992u_int64_t
993ifnet_baudrate(struct ifnet *ifp)
994{
995	return ((ifp == NULL) ? 0 : ifp->if_baudrate);
996}
997
998errno_t
999ifnet_set_bandwidths(struct ifnet *ifp, struct if_bandwidths *output_bw,
1000    struct if_bandwidths *input_bw)
1001{
1002	if (ifp == NULL)
1003		return (EINVAL);
1004
1005	if (input_bw != NULL)
1006		(void) ifnet_set_input_bandwidths(ifp, input_bw);
1007
1008	if (output_bw != NULL)
1009		(void) ifnet_set_output_bandwidths(ifp, output_bw, FALSE);
1010
1011	return (0);
1012}
1013
1014errno_t
1015ifnet_set_output_bandwidths(struct ifnet *ifp, struct if_bandwidths *bw,
1016    boolean_t locked)
1017{
1018	struct if_bandwidths old_bw;
1019	struct ifclassq *ifq;
1020	u_int64_t br;
1021
1022	ifq = &ifp->if_snd;
1023	if (!locked)
1024		IFCQ_LOCK(ifq);
1025	IFCQ_LOCK_ASSERT_HELD(ifq);
1026
1027	old_bw = ifp->if_output_bw;
1028	if (bw != NULL) {
1029		if (bw->eff_bw != 0)
1030			ifp->if_output_bw.eff_bw = bw->eff_bw;
1031		if (bw->max_bw != 0)
1032			ifp->if_output_bw.max_bw = bw->max_bw;
1033		if (ifp->if_output_bw.eff_bw > ifp->if_output_bw.max_bw)
1034			ifp->if_output_bw.max_bw = ifp->if_output_bw.eff_bw;
1035		else if (ifp->if_output_bw.eff_bw == 0)
1036			ifp->if_output_bw.eff_bw = ifp->if_output_bw.max_bw;
1037	}
1038
1039	/* Pin if_baudrate to 32 bits */
1040	br = MAX(ifp->if_output_bw.max_bw, ifp->if_input_bw.max_bw);
1041	if (br != 0)
1042		ifp->if_baudrate = (br > 0xFFFFFFFF) ? 0xFFFFFFFF : br;
1043
1044	/* Adjust queue parameters if needed */
1045	if (old_bw.eff_bw != ifp->if_output_bw.eff_bw ||
1046	    old_bw.max_bw != ifp->if_output_bw.max_bw)
1047		ifnet_update_sndq(ifq, CLASSQ_EV_LINK_SPEED);
1048
1049	if (!locked)
1050		IFCQ_UNLOCK(ifq);
1051
1052	return (0);
1053}
1054
1055errno_t
1056ifnet_set_input_bandwidths(struct ifnet *ifp, struct if_bandwidths *bw)
1057{
1058	struct if_bandwidths old_bw;
1059
1060	old_bw = ifp->if_input_bw;
1061	if (bw->eff_bw != 0)
1062		ifp->if_input_bw.eff_bw = bw->eff_bw;
1063	if (bw->max_bw != 0)
1064		ifp->if_input_bw.max_bw = bw->max_bw;
1065	if (ifp->if_input_bw.eff_bw > ifp->if_input_bw.max_bw)
1066		ifp->if_input_bw.max_bw = ifp->if_input_bw.eff_bw;
1067	else if (ifp->if_input_bw.eff_bw == 0)
1068		ifp->if_input_bw.eff_bw = ifp->if_input_bw.max_bw;
1069
1070	if (old_bw.eff_bw != ifp->if_input_bw.eff_bw ||
1071	    old_bw.max_bw != ifp->if_input_bw.max_bw)
1072		ifnet_update_rcv(ifp, CLASSQ_EV_LINK_SPEED);
1073
1074	return (0);
1075}
1076
1077u_int64_t
1078ifnet_output_linkrate(struct ifnet *ifp)
1079{
1080	struct ifclassq *ifq = &ifp->if_snd;
1081	u_int64_t rate;
1082
1083	IFCQ_LOCK_ASSERT_HELD(ifq);
1084
1085	rate = ifp->if_output_bw.eff_bw;
1086	if (IFCQ_TBR_IS_ENABLED(ifq)) {
1087		u_int64_t tbr_rate = ifp->if_snd.ifcq_tbr.tbr_rate_raw;
1088		VERIFY(tbr_rate > 0);
1089		rate = MIN(rate, ifp->if_snd.ifcq_tbr.tbr_rate_raw);
1090	}
1091
1092	return (rate);
1093}
1094
1095u_int64_t
1096ifnet_input_linkrate(struct ifnet *ifp)
1097{
1098	return (ifp->if_input_bw.eff_bw);
1099}
1100
1101errno_t
1102ifnet_bandwidths(struct ifnet *ifp, struct if_bandwidths *output_bw,
1103    struct if_bandwidths *input_bw)
1104{
1105	if (ifp == NULL)
1106		return (EINVAL);
1107
1108	if (output_bw != NULL)
1109		*output_bw = ifp->if_output_bw;
1110	if (input_bw != NULL)
1111		*input_bw = ifp->if_input_bw;
1112
1113	return (0);
1114}
1115
1116errno_t
1117ifnet_stat_increment(struct ifnet *ifp,
1118    const struct ifnet_stat_increment_param *s)
1119{
1120	if (ifp == NULL)
1121		return (EINVAL);
1122
1123	if (s->packets_in != 0)
1124		atomic_add_64(&ifp->if_data.ifi_ipackets, s->packets_in);
1125	if (s->bytes_in != 0)
1126		atomic_add_64(&ifp->if_data.ifi_ibytes, s->bytes_in);
1127	if (s->errors_in != 0)
1128		atomic_add_64(&ifp->if_data.ifi_ierrors, s->errors_in);
1129
1130	if (s->packets_out != 0)
1131		atomic_add_64(&ifp->if_data.ifi_opackets, s->packets_out);
1132	if (s->bytes_out != 0)
1133		atomic_add_64(&ifp->if_data.ifi_obytes, s->bytes_out);
1134	if (s->errors_out != 0)
1135		atomic_add_64(&ifp->if_data.ifi_oerrors, s->errors_out);
1136
1137	if (s->collisions != 0)
1138		atomic_add_64(&ifp->if_data.ifi_collisions, s->collisions);
1139	if (s->dropped != 0)
1140		atomic_add_64(&ifp->if_data.ifi_iqdrops, s->dropped);
1141
1142	/* Touch the last change time. */
1143	TOUCHLASTCHANGE(&ifp->if_lastchange);
1144
1145	return (0);
1146}
1147
1148errno_t
1149ifnet_stat_increment_in(struct ifnet *ifp, u_int32_t packets_in,
1150    u_int32_t bytes_in, u_int32_t errors_in)
1151{
1152	if (ifp == NULL)
1153		return (EINVAL);
1154
1155	if (packets_in != 0)
1156		atomic_add_64(&ifp->if_data.ifi_ipackets, packets_in);
1157	if (bytes_in != 0)
1158		atomic_add_64(&ifp->if_data.ifi_ibytes, bytes_in);
1159	if (errors_in != 0)
1160		atomic_add_64(&ifp->if_data.ifi_ierrors, errors_in);
1161
1162	TOUCHLASTCHANGE(&ifp->if_lastchange);
1163
1164	return (0);
1165}
1166
1167errno_t
1168ifnet_stat_increment_out(struct ifnet *ifp, u_int32_t packets_out,
1169    u_int32_t bytes_out, u_int32_t errors_out)
1170{
1171	if (ifp == NULL)
1172		return (EINVAL);
1173
1174	if (packets_out != 0)
1175		atomic_add_64(&ifp->if_data.ifi_opackets, packets_out);
1176	if (bytes_out != 0)
1177		atomic_add_64(&ifp->if_data.ifi_obytes, bytes_out);
1178	if (errors_out != 0)
1179		atomic_add_64(&ifp->if_data.ifi_oerrors, errors_out);
1180
1181	TOUCHLASTCHANGE(&ifp->if_lastchange);
1182
1183	return (0);
1184}
1185
1186errno_t
1187ifnet_set_stat(struct ifnet *ifp, const struct ifnet_stats_param *s)
1188{
1189	if (ifp == NULL)
1190		return (EINVAL);
1191
1192	atomic_set_64(&ifp->if_data.ifi_ipackets, s->packets_in);
1193	atomic_set_64(&ifp->if_data.ifi_ibytes, s->bytes_in);
1194	atomic_set_64(&ifp->if_data.ifi_imcasts, s->multicasts_in);
1195	atomic_set_64(&ifp->if_data.ifi_ierrors, s->errors_in);
1196
1197	atomic_set_64(&ifp->if_data.ifi_opackets, s->packets_out);
1198	atomic_set_64(&ifp->if_data.ifi_obytes, s->bytes_out);
1199	atomic_set_64(&ifp->if_data.ifi_omcasts, s->multicasts_out);
1200	atomic_set_64(&ifp->if_data.ifi_oerrors, s->errors_out);
1201
1202	atomic_set_64(&ifp->if_data.ifi_collisions, s->collisions);
1203	atomic_set_64(&ifp->if_data.ifi_iqdrops, s->dropped);
1204	atomic_set_64(&ifp->if_data.ifi_noproto, s->no_protocol);
1205
1206	/* Touch the last change time. */
1207	TOUCHLASTCHANGE(&ifp->if_lastchange);
1208
1209	return (0);
1210}
1211
1212errno_t
1213ifnet_stat(struct ifnet *ifp, struct ifnet_stats_param *s)
1214{
1215	if (ifp == NULL)
1216		return (EINVAL);
1217
1218	atomic_get_64(s->packets_in, &ifp->if_data.ifi_ipackets);
1219	atomic_get_64(s->bytes_in, &ifp->if_data.ifi_ibytes);
1220	atomic_get_64(s->multicasts_in, &ifp->if_data.ifi_imcasts);
1221	atomic_get_64(s->errors_in, &ifp->if_data.ifi_ierrors);
1222
1223	atomic_get_64(s->packets_out, &ifp->if_data.ifi_opackets);
1224	atomic_get_64(s->bytes_out, &ifp->if_data.ifi_obytes);
1225	atomic_get_64(s->multicasts_out, &ifp->if_data.ifi_omcasts);
1226	atomic_get_64(s->errors_out, &ifp->if_data.ifi_oerrors);
1227
1228	atomic_get_64(s->collisions, &ifp->if_data.ifi_collisions);
1229	atomic_get_64(s->dropped, &ifp->if_data.ifi_iqdrops);
1230	atomic_get_64(s->no_protocol, &ifp->if_data.ifi_noproto);
1231
1232	return (0);
1233}
1234
1235errno_t
1236ifnet_touch_lastchange(ifnet_t interface)
1237{
1238	if (interface == NULL)
1239		return (EINVAL);
1240
1241	TOUCHLASTCHANGE(&interface->if_lastchange);
1242
1243	return (0);
1244}
1245
1246errno_t
1247ifnet_lastchange(ifnet_t interface, struct timeval *last_change)
1248{
1249	if (interface == NULL)
1250		return (EINVAL);
1251
1252	*last_change = interface->if_data.ifi_lastchange;
1253#if IF_LASTCHANGEUPTIME
1254	/* Crude conversion from uptime to calendar time */
1255	last_change->tv_sec += boottime_sec();
1256#endif
1257	return (0);
1258}
1259
1260errno_t
1261ifnet_get_address_list(ifnet_t interface, ifaddr_t **addresses)
1262{
1263	return (addresses == NULL ? EINVAL :
1264	    ifnet_get_address_list_family(interface, addresses, 0));
1265}
1266
1267struct ifnet_addr_list {
1268	SLIST_ENTRY(ifnet_addr_list)	ifal_le;
1269	struct ifaddr			*ifal_ifa;
1270};
1271
1272errno_t
1273ifnet_get_address_list_family(ifnet_t interface, ifaddr_t **addresses,
1274    sa_family_t family)
1275{
1276	return (ifnet_get_address_list_family_internal(interface, addresses,
1277	    family, 0, M_NOWAIT));
1278}
1279
1280__private_extern__ errno_t
1281ifnet_get_address_list_family_internal(ifnet_t interface, ifaddr_t **addresses,
1282    sa_family_t family, int detached, int how)
1283{
1284	SLIST_HEAD(, ifnet_addr_list) ifal_head;
1285	struct ifnet_addr_list *ifal, *ifal_tmp;
1286	struct ifnet *ifp;
1287	int count = 0;
1288	errno_t err = 0;
1289
1290	SLIST_INIT(&ifal_head);
1291
1292	if (addresses == NULL) {
1293		err = EINVAL;
1294		goto done;
1295	}
1296	*addresses = NULL;
1297
1298	if (detached) {
1299		/*
1300		 * Interface has been detached, so skip the lookup
1301		 * at ifnet_head and go directly to inner loop.
1302		 */
1303		ifp = interface;
1304		if (ifp == NULL) {
1305			err = EINVAL;
1306			goto done;
1307		}
1308		goto one;
1309	}
1310
1311	ifnet_head_lock_shared();
1312	TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1313		if (interface != NULL && ifp != interface)
1314			continue;
1315one:
1316		ifnet_lock_shared(ifp);
1317		if (interface == NULL || interface == ifp) {
1318			struct ifaddr *ifa;
1319			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1320				IFA_LOCK(ifa);
1321				if (family != 0 &&
1322				    ifa->ifa_addr->sa_family != family) {
1323					IFA_UNLOCK(ifa);
1324					continue;
1325				}
1326				MALLOC(ifal, struct ifnet_addr_list *,
1327				    sizeof (*ifal), M_TEMP, how);
1328				if (ifal == NULL) {
1329					IFA_UNLOCK(ifa);
1330					ifnet_lock_done(ifp);
1331					if (!detached)
1332						ifnet_head_done();
1333					err = ENOMEM;
1334					goto done;
1335				}
1336				ifal->ifal_ifa = ifa;
1337				IFA_ADDREF_LOCKED(ifa);
1338				SLIST_INSERT_HEAD(&ifal_head, ifal, ifal_le);
1339				++count;
1340				IFA_UNLOCK(ifa);
1341			}
1342		}
1343		ifnet_lock_done(ifp);
1344		if (detached)
1345			break;
1346	}
1347	if (!detached)
1348		ifnet_head_done();
1349
1350	if (count == 0) {
1351		err = ENXIO;
1352		goto done;
1353	}
1354	MALLOC(*addresses, ifaddr_t *, sizeof (ifaddr_t) * (count + 1),
1355	    M_TEMP, how);
1356	if (*addresses == NULL) {
1357		err = ENOMEM;
1358		goto done;
1359	}
1360	bzero(*addresses, sizeof (ifaddr_t) * (count + 1));
1361
1362done:
1363	SLIST_FOREACH_SAFE(ifal, &ifal_head, ifal_le, ifal_tmp) {
1364		SLIST_REMOVE(&ifal_head, ifal, ifnet_addr_list, ifal_le);
1365		if (err == 0)
1366			(*addresses)[--count] = ifal->ifal_ifa;
1367		else
1368			IFA_REMREF(ifal->ifal_ifa);
1369		FREE(ifal, M_TEMP);
1370	}
1371
1372	return (err);
1373}
1374
1375void
1376ifnet_free_address_list(ifaddr_t *addresses)
1377{
1378	int i;
1379
1380	if (addresses == NULL)
1381		return;
1382
1383	for (i = 0; addresses[i] != NULL; i++)
1384		IFA_REMREF(addresses[i]);
1385
1386	FREE(addresses, M_TEMP);
1387}
1388
1389void *
1390ifnet_lladdr(ifnet_t interface)
1391{
1392	struct ifaddr *ifa;
1393	void *lladdr;
1394
1395	if (interface == NULL)
1396		return (NULL);
1397
1398	/*
1399	 * if_lladdr points to the permanent link address of
1400	 * the interface; it never gets deallocated.
1401	 */
1402	ifa = interface->if_lladdr;
1403	IFA_LOCK_SPIN(ifa);
1404	lladdr = LLADDR(SDL((void *)ifa->ifa_addr));
1405	IFA_UNLOCK(ifa);
1406
1407	return (lladdr);
1408}
1409
1410errno_t
1411ifnet_llbroadcast_copy_bytes(ifnet_t interface, void *addr, size_t buffer_len,
1412    size_t *out_len)
1413{
1414	if (interface == NULL || addr == NULL || out_len == NULL)
1415		return (EINVAL);
1416
1417	*out_len = interface->if_broadcast.length;
1418
1419	if (buffer_len < interface->if_broadcast.length)
1420		return (EMSGSIZE);
1421
1422	if (interface->if_broadcast.length == 0)
1423		return (ENXIO);
1424
1425	if (interface->if_broadcast.length <=
1426	    sizeof (interface->if_broadcast.u.buffer)) {
1427		bcopy(interface->if_broadcast.u.buffer, addr,
1428		    interface->if_broadcast.length);
1429	} else {
1430		bcopy(interface->if_broadcast.u.ptr, addr,
1431		    interface->if_broadcast.length);
1432	}
1433
1434	return (0);
1435}
1436
1437errno_t
1438ifnet_lladdr_copy_bytes(ifnet_t interface, void *lladdr, size_t	lladdr_len)
1439{
1440	struct sockaddr_dl *sdl;
1441	struct ifaddr *ifa;
1442
1443	if (interface == NULL || lladdr == NULL)
1444		return (EINVAL);
1445
1446	/*
1447	 * if_lladdr points to the permanent link address of
1448	 * the interface; it never gets deallocated.
1449	 */
1450	ifa = interface->if_lladdr;
1451	IFA_LOCK_SPIN(ifa);
1452	sdl = SDL((void *)ifa->ifa_addr);
1453	if (lladdr_len != sdl->sdl_alen) {
1454		bzero(lladdr, lladdr_len);
1455		IFA_UNLOCK(ifa);
1456		return (EMSGSIZE);
1457	}
1458	bcopy(LLADDR(sdl), lladdr, lladdr_len);
1459	IFA_UNLOCK(ifa);
1460
1461	return (0);
1462}
1463
1464static errno_t
1465ifnet_set_lladdr_internal(ifnet_t interface, const void *lladdr,
1466    size_t lladdr_len, u_char new_type, int apply_type)
1467{
1468	struct ifaddr *ifa;
1469	errno_t	error = 0;
1470
1471	if (interface == NULL)
1472		return (EINVAL);
1473
1474	ifnet_head_lock_shared();
1475	ifnet_lock_exclusive(interface);
1476	if (lladdr_len != 0 &&
1477	    (lladdr_len != interface->if_addrlen || lladdr == 0)) {
1478		ifnet_lock_done(interface);
1479		ifnet_head_done();
1480		return (EINVAL);
1481	}
1482	ifa = ifnet_addrs[interface->if_index - 1];
1483	if (ifa != NULL) {
1484		struct sockaddr_dl *sdl;
1485
1486		IFA_LOCK_SPIN(ifa);
1487		sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
1488		if (lladdr_len != 0) {
1489			bcopy(lladdr, LLADDR(sdl), lladdr_len);
1490		} else {
1491			bzero(LLADDR(sdl), interface->if_addrlen);
1492		}
1493		sdl->sdl_alen = lladdr_len;
1494
1495		if (apply_type) {
1496			sdl->sdl_type = new_type;
1497		}
1498		IFA_UNLOCK(ifa);
1499	} else {
1500		error = ENXIO;
1501	}
1502	ifnet_lock_done(interface);
1503	ifnet_head_done();
1504
1505	/* Generate a kernel event */
1506	if (error == 0) {
1507		dlil_post_msg(interface, KEV_DL_SUBCLASS,
1508		    KEV_DL_LINK_ADDRESS_CHANGED, NULL, 0);
1509	}
1510
1511	return (error);
1512}
1513
1514errno_t
1515ifnet_set_lladdr(ifnet_t interface, const void* lladdr, size_t lladdr_len)
1516{
1517	return (ifnet_set_lladdr_internal(interface, lladdr, lladdr_len, 0, 0));
1518}
1519
1520errno_t
1521ifnet_set_lladdr_and_type(ifnet_t interface, const void* lladdr,
1522    size_t lladdr_len, u_char type)
1523{
1524	return (ifnet_set_lladdr_internal(interface, lladdr,
1525	    lladdr_len, type, 1));
1526}
1527
1528errno_t
1529ifnet_add_multicast(ifnet_t interface, const struct sockaddr *maddr,
1530    ifmultiaddr_t *ifmap)
1531{
1532	if (interface == NULL || maddr == NULL)
1533		return (EINVAL);
1534
1535	/* Don't let users screw up protocols' entries. */
1536	if (maddr->sa_family != AF_UNSPEC && maddr->sa_family != AF_LINK)
1537		return (EINVAL);
1538
1539	return (if_addmulti_anon(interface, maddr, ifmap));
1540}
1541
1542errno_t
1543ifnet_remove_multicast(ifmultiaddr_t ifma)
1544{
1545	struct sockaddr *maddr;
1546
1547	if (ifma == NULL)
1548		return (EINVAL);
1549
1550	maddr = ifma->ifma_addr;
1551	/* Don't let users screw up protocols' entries. */
1552	if (maddr->sa_family != AF_UNSPEC && maddr->sa_family != AF_LINK)
1553		return (EINVAL);
1554
1555	return (if_delmulti_anon(ifma->ifma_ifp, maddr));
1556}
1557
1558errno_t
1559ifnet_get_multicast_list(ifnet_t ifp, ifmultiaddr_t **addresses)
1560{
1561	int count = 0;
1562	int cmax = 0;
1563	struct ifmultiaddr *addr;
1564
1565	if (ifp == NULL || addresses == NULL)
1566		return (EINVAL);
1567
1568	ifnet_lock_shared(ifp);
1569	LIST_FOREACH(addr, &ifp->if_multiaddrs, ifma_link) {
1570		cmax++;
1571	}
1572
1573	MALLOC(*addresses, ifmultiaddr_t *, sizeof (ifmultiaddr_t) * (cmax + 1),
1574	    M_TEMP, M_NOWAIT);
1575	if (*addresses == NULL) {
1576		ifnet_lock_done(ifp);
1577		return (ENOMEM);
1578	}
1579
1580	LIST_FOREACH(addr, &ifp->if_multiaddrs, ifma_link) {
1581		if (count + 1 > cmax)
1582			break;
1583		(*addresses)[count] = (ifmultiaddr_t)addr;
1584		ifmaddr_reference((*addresses)[count]);
1585		count++;
1586	}
1587	(*addresses)[cmax] = NULL;
1588	ifnet_lock_done(ifp);
1589
1590	return (0);
1591}
1592
1593void
1594ifnet_free_multicast_list(ifmultiaddr_t *addresses)
1595{
1596	int i;
1597
1598	if (addresses == NULL)
1599		return;
1600
1601	for (i = 0; addresses[i] != NULL; i++)
1602		ifmaddr_release(addresses[i]);
1603
1604	FREE(addresses, M_TEMP);
1605}
1606
1607errno_t
1608ifnet_find_by_name(const char *ifname, ifnet_t *ifpp)
1609{
1610	struct ifnet *ifp;
1611	int	namelen;
1612
1613	if (ifname == NULL)
1614		return (EINVAL);
1615
1616	namelen = strlen(ifname);
1617
1618	*ifpp = NULL;
1619
1620	ifnet_head_lock_shared();
1621	TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1622		struct ifaddr *ifa;
1623		struct sockaddr_dl *ll_addr;
1624
1625		ifa = ifnet_addrs[ifp->if_index - 1];
1626		if (ifa == NULL)
1627			continue;
1628
1629		IFA_LOCK(ifa);
1630		ll_addr = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
1631
1632		if (namelen == ll_addr->sdl_nlen && strncmp(ll_addr->sdl_data,
1633		    ifname, ll_addr->sdl_nlen) == 0) {
1634			IFA_UNLOCK(ifa);
1635			*ifpp = ifp;
1636			ifnet_reference(*ifpp);
1637			break;
1638		}
1639		IFA_UNLOCK(ifa);
1640	}
1641	ifnet_head_done();
1642
1643	return ((ifp == NULL) ? ENXIO : 0);
1644}
1645
1646errno_t
1647ifnet_list_get(ifnet_family_t family, ifnet_t **list, u_int32_t *count)
1648{
1649	return (ifnet_list_get_common(family, FALSE, list, count));
1650}
1651
1652__private_extern__ errno_t
1653ifnet_list_get_all(ifnet_family_t family, ifnet_t **list, u_int32_t *count)
1654{
1655	return (ifnet_list_get_common(family, TRUE, list, count));
1656}
1657
1658struct ifnet_list {
1659	SLIST_ENTRY(ifnet_list)	ifl_le;
1660	struct ifnet		*ifl_ifp;
1661};
1662
1663static errno_t
1664ifnet_list_get_common(ifnet_family_t family, boolean_t get_all, ifnet_t **list,
1665    u_int32_t *count)
1666{
1667#pragma unused(get_all)
1668	SLIST_HEAD(, ifnet_list) ifl_head;
1669	struct ifnet_list *ifl, *ifl_tmp;
1670	struct ifnet *ifp;
1671	int cnt = 0;
1672	errno_t err = 0;
1673
1674	SLIST_INIT(&ifl_head);
1675
1676	if (list == NULL || count == NULL) {
1677		err = EINVAL;
1678		goto done;
1679	}
1680	*count = 0;
1681	*list = NULL;
1682
1683	ifnet_head_lock_shared();
1684	TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1685		if (family == IFNET_FAMILY_ANY || ifp->if_family == family) {
1686			MALLOC(ifl, struct ifnet_list *, sizeof (*ifl),
1687			    M_TEMP, M_NOWAIT);
1688			if (ifl == NULL) {
1689				ifnet_head_done();
1690				err = ENOMEM;
1691				goto done;
1692			}
1693			ifl->ifl_ifp = ifp;
1694			ifnet_reference(ifp);
1695			SLIST_INSERT_HEAD(&ifl_head, ifl, ifl_le);
1696			++cnt;
1697		}
1698	}
1699	ifnet_head_done();
1700
1701	if (cnt == 0) {
1702		err = ENXIO;
1703		goto done;
1704	}
1705
1706	MALLOC(*list, ifnet_t *, sizeof (ifnet_t) * (cnt + 1),
1707	    M_TEMP, M_NOWAIT);
1708	if (*list == NULL) {
1709		err = ENOMEM;
1710		goto done;
1711	}
1712	bzero(*list, sizeof (ifnet_t) * (cnt + 1));
1713	*count = cnt;
1714
1715done:
1716	SLIST_FOREACH_SAFE(ifl, &ifl_head, ifl_le, ifl_tmp) {
1717		SLIST_REMOVE(&ifl_head, ifl, ifnet_list, ifl_le);
1718		if (err == 0)
1719			(*list)[--cnt] = ifl->ifl_ifp;
1720		else
1721			ifnet_release(ifl->ifl_ifp);
1722		FREE(ifl, M_TEMP);
1723	}
1724
1725	return (err);
1726}
1727
1728void
1729ifnet_list_free(ifnet_t *interfaces)
1730{
1731	int i;
1732
1733	if (interfaces == NULL)
1734		return;
1735
1736	for (i = 0; interfaces[i]; i++)
1737		ifnet_release(interfaces[i]);
1738
1739	FREE(interfaces, M_TEMP);
1740}
1741
1742void
1743ifnet_transmit_burst_start(ifnet_t ifp, mbuf_t pkt)
1744{
1745	uint32_t orig_flags;
1746
1747	if (ifp == NULL || !(pkt->m_flags & M_PKTHDR))
1748		return;
1749
1750	orig_flags = OSBitOrAtomic(IF_MEASURED_BW_INPROGRESS,
1751	    &ifp->if_bw.flags);
1752	if (orig_flags & IF_MEASURED_BW_INPROGRESS) {
1753		/* There is already a measurement in progress; skip this one */
1754		return;
1755	}
1756
1757	ifp->if_bw.start_seq = pkt->m_pkthdr.pf_mtag.pftag_pktseq;
1758	ifp->if_bw.start_ts = mach_absolute_time();
1759}
1760
1761void
1762ifnet_transmit_burst_end(ifnet_t ifp, mbuf_t pkt)
1763{
1764	uint64_t oseq, ots, bytes, ts, t;
1765	uint32_t flags;
1766
1767	if ( ifp == NULL || !(pkt->m_flags & M_PKTHDR))
1768		return;
1769
1770	flags = OSBitOrAtomic(IF_MEASURED_BW_CALCULATION, &ifp->if_bw.flags);
1771
1772	/* If a calculation is already in progress, just return */
1773	if (flags & IF_MEASURED_BW_CALCULATION)
1774		return;
1775
1776	/* Check if a measurement was started at all */
1777	if (!(flags & IF_MEASURED_BW_INPROGRESS)) {
1778		/*
1779		 * It is an error to call burst_end before burst_start.
1780		 * Reset the calculation flag and return.
1781		 */
1782		goto done;
1783	}
1784
1785	oseq = pkt->m_pkthdr.pf_mtag.pftag_pktseq;
1786	ots = mach_absolute_time();
1787
1788	if (ifp->if_bw.start_seq > 0 && oseq > ifp->if_bw.start_seq) {
1789		ts = ots - ifp->if_bw.start_ts;
1790		if (ts > 0 ) {
1791			absolutetime_to_nanoseconds(ts, &t);
1792			bytes = oseq - ifp->if_bw.start_seq;
1793			ifp->if_bw.bytes = bytes;
1794			ifp->if_bw.ts = ts;
1795
1796			if (t > 0) {
1797				uint64_t bw = 0;
1798
1799				/* Compute bandwidth as bytes/ms */
1800				bw = (bytes * NSEC_PER_MSEC) / t;
1801				if (bw > 0) {
1802					if (ifp->if_bw.bw > 0) {
1803						u_int32_t shft;
1804
1805						shft = if_bw_smoothing_val;
1806						/* Compute EWMA of bw */
1807						ifp->if_bw.bw = (bw +
1808						    ((ifp->if_bw.bw << shft) -
1809						    ifp->if_bw.bw)) >> shft;
1810					} else {
1811						ifp->if_bw.bw = bw;
1812					}
1813				}
1814			}
1815			ifp->if_bw.last_seq = oseq;
1816			ifp->if_bw.last_ts = ots;
1817		}
1818	}
1819
1820done:
1821	flags = ~(IF_MEASURED_BW_INPROGRESS | IF_MEASURED_BW_CALCULATION);
1822	OSBitAndAtomic(flags, &ifp->if_bw.flags);
1823}
1824
1825/****************************************************************************/
1826/* ifaddr_t accessors							    */
1827/****************************************************************************/
1828
1829errno_t
1830ifaddr_reference(ifaddr_t ifa)
1831{
1832	if (ifa == NULL)
1833		return (EINVAL);
1834
1835	IFA_ADDREF(ifa);
1836	return (0);
1837}
1838
1839errno_t
1840ifaddr_release(ifaddr_t ifa)
1841{
1842	if (ifa == NULL)
1843		return (EINVAL);
1844
1845	IFA_REMREF(ifa);
1846	return (0);
1847}
1848
1849sa_family_t
1850ifaddr_address_family(ifaddr_t ifa)
1851{
1852	sa_family_t family = 0;
1853
1854	if (ifa != NULL) {
1855		IFA_LOCK_SPIN(ifa);
1856		if (ifa->ifa_addr != NULL)
1857			family = ifa->ifa_addr->sa_family;
1858		IFA_UNLOCK(ifa);
1859	}
1860	return (family);
1861}
1862
1863errno_t
1864ifaddr_address(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
1865{
1866	u_int32_t copylen;
1867
1868	if (ifa == NULL || out_addr == NULL)
1869		return (EINVAL);
1870
1871	IFA_LOCK_SPIN(ifa);
1872	if (ifa->ifa_addr == NULL) {
1873		IFA_UNLOCK(ifa);
1874		return (ENOTSUP);
1875	}
1876
1877	copylen = (addr_size >= ifa->ifa_addr->sa_len) ?
1878	    ifa->ifa_addr->sa_len : addr_size;
1879	bcopy(ifa->ifa_addr, out_addr, copylen);
1880
1881	if (ifa->ifa_addr->sa_len > addr_size) {
1882		IFA_UNLOCK(ifa);
1883		return (EMSGSIZE);
1884	}
1885
1886	IFA_UNLOCK(ifa);
1887	return (0);
1888}
1889
1890errno_t
1891ifaddr_dstaddress(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
1892{
1893	u_int32_t copylen;
1894
1895	if (ifa == NULL || out_addr == NULL)
1896		return (EINVAL);
1897
1898	IFA_LOCK_SPIN(ifa);
1899	if (ifa->ifa_dstaddr == NULL) {
1900		IFA_UNLOCK(ifa);
1901		return (ENOTSUP);
1902	}
1903
1904	copylen = (addr_size >= ifa->ifa_dstaddr->sa_len) ?
1905	    ifa->ifa_dstaddr->sa_len : addr_size;
1906	bcopy(ifa->ifa_dstaddr, out_addr, copylen);
1907
1908	if (ifa->ifa_dstaddr->sa_len > addr_size) {
1909		IFA_UNLOCK(ifa);
1910		return (EMSGSIZE);
1911	}
1912
1913	IFA_UNLOCK(ifa);
1914	return (0);
1915}
1916
1917errno_t
1918ifaddr_netmask(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
1919{
1920	u_int32_t copylen;
1921
1922	if (ifa == NULL || out_addr == NULL)
1923		return (EINVAL);
1924
1925	IFA_LOCK_SPIN(ifa);
1926	if (ifa->ifa_netmask == NULL) {
1927		IFA_UNLOCK(ifa);
1928		return (ENOTSUP);
1929	}
1930
1931	copylen = addr_size >= ifa->ifa_netmask->sa_len ?
1932	    ifa->ifa_netmask->sa_len : addr_size;
1933	bcopy(ifa->ifa_netmask, out_addr, copylen);
1934
1935	if (ifa->ifa_netmask->sa_len > addr_size) {
1936		IFA_UNLOCK(ifa);
1937		return (EMSGSIZE);
1938	}
1939
1940	IFA_UNLOCK(ifa);
1941	return (0);
1942}
1943
1944ifnet_t
1945ifaddr_ifnet(ifaddr_t ifa)
1946{
1947	struct ifnet *ifp;
1948
1949	if (ifa == NULL)
1950		return (NULL);
1951
1952	/* ifa_ifp is set once at creation time; it is never changed */
1953	ifp = ifa->ifa_ifp;
1954
1955	return (ifp);
1956}
1957
1958ifaddr_t
1959ifaddr_withaddr(const struct sockaddr *address)
1960{
1961	if (address == NULL)
1962		return (NULL);
1963
1964	return (ifa_ifwithaddr(address));
1965}
1966
1967ifaddr_t
1968ifaddr_withdstaddr(const struct sockaddr *address)
1969{
1970	if (address == NULL)
1971		return (NULL);
1972
1973	return (ifa_ifwithdstaddr(address));
1974}
1975
1976ifaddr_t
1977ifaddr_withnet(const struct sockaddr *net)
1978{
1979	if (net == NULL)
1980		return (NULL);
1981
1982	return (ifa_ifwithnet(net));
1983}
1984
1985ifaddr_t
1986ifaddr_withroute(int flags, const struct sockaddr *destination,
1987    const struct sockaddr *gateway)
1988{
1989	if (destination == NULL || gateway == NULL)
1990		return (NULL);
1991
1992	return (ifa_ifwithroute(flags, destination, gateway));
1993}
1994
1995ifaddr_t
1996ifaddr_findbestforaddr(const struct sockaddr *addr, ifnet_t interface)
1997{
1998	if (addr == NULL || interface == NULL)
1999		return (NULL);
2000
2001	return (ifaof_ifpforaddr(addr, interface));
2002}
2003
2004errno_t
2005ifmaddr_reference(ifmultiaddr_t ifmaddr)
2006{
2007	if (ifmaddr == NULL)
2008		return (EINVAL);
2009
2010	IFMA_ADDREF(ifmaddr);
2011	return (0);
2012}
2013
2014errno_t
2015ifmaddr_release(ifmultiaddr_t ifmaddr)
2016{
2017	if (ifmaddr == NULL)
2018		return (EINVAL);
2019
2020	IFMA_REMREF(ifmaddr);
2021	return (0);
2022}
2023
2024errno_t
2025ifmaddr_address(ifmultiaddr_t ifma, struct sockaddr *out_addr,
2026    u_int32_t addr_size)
2027{
2028	u_int32_t copylen;
2029
2030	if (ifma == NULL || out_addr == NULL)
2031		return (EINVAL);
2032
2033	IFMA_LOCK(ifma);
2034	if (ifma->ifma_addr == NULL) {
2035		IFMA_UNLOCK(ifma);
2036		return (ENOTSUP);
2037	}
2038
2039	copylen = (addr_size >= ifma->ifma_addr->sa_len ?
2040	    ifma->ifma_addr->sa_len : addr_size);
2041	bcopy(ifma->ifma_addr, out_addr, copylen);
2042
2043	if (ifma->ifma_addr->sa_len > addr_size) {
2044		IFMA_UNLOCK(ifma);
2045		return (EMSGSIZE);
2046	}
2047	IFMA_UNLOCK(ifma);
2048	return (0);
2049}
2050
2051errno_t
2052ifmaddr_lladdress(ifmultiaddr_t ifma, struct sockaddr *out_addr,
2053    u_int32_t addr_size)
2054{
2055	struct ifmultiaddr *ifma_ll;
2056
2057	if (ifma == NULL || out_addr == NULL)
2058		return (EINVAL);
2059	if ((ifma_ll = ifma->ifma_ll) == NULL)
2060		return (ENOTSUP);
2061
2062	return (ifmaddr_address(ifma_ll, out_addr, addr_size));
2063}
2064
2065ifnet_t
2066ifmaddr_ifnet(ifmultiaddr_t ifma)
2067{
2068	return ((ifma == NULL) ? NULL : ifma->ifma_ifp);
2069}
2070
2071/******************************************************************************/
2072/* interface cloner                                                           */
2073/******************************************************************************/
2074
2075errno_t
2076ifnet_clone_attach(struct ifnet_clone_params *cloner_params,
2077    if_clone_t *ifcloner)
2078{
2079	errno_t error = 0;
2080	struct if_clone *ifc = NULL;
2081	size_t namelen;
2082
2083	if (cloner_params == NULL || ifcloner == NULL ||
2084	    cloner_params->ifc_name == NULL ||
2085	    cloner_params->ifc_create == NULL ||
2086	    cloner_params->ifc_destroy == NULL ||
2087	    (namelen = strlen(cloner_params->ifc_name)) >= IFNAMSIZ) {
2088		error = EINVAL;
2089		goto fail;
2090	}
2091
2092	if (if_clone_lookup(cloner_params->ifc_name, NULL) != NULL) {
2093		printf("%s: already a cloner for %s\n", __func__,
2094		    cloner_params->ifc_name);
2095		error = EEXIST;
2096		goto fail;
2097	}
2098
2099	/* Make room for name string */
2100	ifc = _MALLOC(sizeof (struct if_clone) + IFNAMSIZ + 1, M_CLONE,
2101	    M_WAITOK | M_ZERO);
2102	if (ifc == NULL) {
2103		printf("%s: _MALLOC failed\n", __func__);
2104		error = ENOBUFS;
2105		goto fail;
2106	}
2107	strlcpy((char *)(ifc + 1), cloner_params->ifc_name, IFNAMSIZ + 1);
2108	ifc->ifc_name = (char *)(ifc + 1);
2109	ifc->ifc_namelen = namelen;
2110	ifc->ifc_maxunit = IF_MAXUNIT;
2111	ifc->ifc_create = cloner_params->ifc_create;
2112	ifc->ifc_destroy = cloner_params->ifc_destroy;
2113
2114	error = if_clone_attach(ifc);
2115	if (error != 0) {
2116		printf("%s: if_clone_attach failed %d\n", __func__, error);
2117		goto fail;
2118	}
2119	*ifcloner = ifc;
2120
2121	return (0);
2122fail:
2123	if (ifc != NULL)
2124		FREE(ifc, M_CLONE);
2125	return (error);
2126}
2127
2128errno_t
2129ifnet_clone_detach(if_clone_t ifcloner)
2130{
2131	errno_t error = 0;
2132	struct if_clone *ifc = ifcloner;
2133
2134	if (ifc == NULL || ifc->ifc_name == NULL)
2135		return (EINVAL);
2136
2137	if ((if_clone_lookup(ifc->ifc_name, NULL)) == NULL) {
2138		printf("%s: no cloner for %s\n", __func__, ifc->ifc_name);
2139		error = EINVAL;
2140		goto fail;
2141	}
2142
2143	if_clone_detach(ifc);
2144
2145	FREE(ifc, M_CLONE);
2146
2147fail:
2148	return (error);
2149}
2150
2151/******************************************************************************/
2152/* misc                                                                       */
2153/******************************************************************************/
2154
2155extern void udp_get_ports_used(unsigned int ifindex, uint8_t *bitfield);
2156extern void tcp_get_ports_used(unsigned int ifindex, uint8_t *bitfield);
2157
2158errno_t
2159ifnet_get_local_ports(ifnet_t ifp, uint8_t *bitfield)
2160{
2161	if (bitfield == NULL)
2162		return (EINVAL);
2163
2164	bzero(bitfield, 8192);
2165
2166	udp_get_ports_used(ifp ? ifp->if_index : 0, bitfield);
2167	tcp_get_ports_used(ifp ? ifp->if_index : 0, bitfield);
2168
2169	return (0);
2170}
2171
2172errno_t
2173ifnet_notice_node_presence(ifnet_t ifp, struct sockaddr* sa, int32_t rssi,
2174    int lqm, int npm, u_int8_t srvinfo[48])
2175{
2176	if (ifp == NULL || sa == NULL || srvinfo == NULL)
2177		return(EINVAL);
2178	if (sa->sa_len > sizeof(struct sockaddr_storage))
2179		return(EINVAL);
2180	if (sa->sa_family != AF_LINK && sa->sa_family != AF_INET6)
2181		return(EINVAL);
2182
2183	dlil_node_present(ifp, sa, rssi, lqm, npm, srvinfo);
2184	return (0);
2185}
2186
2187errno_t
2188ifnet_notice_node_absence(ifnet_t ifp, struct sockaddr* sa)
2189{
2190	if (ifp == NULL || sa == NULL)
2191		return(EINVAL);
2192	if (sa->sa_len > sizeof(struct sockaddr_storage))
2193		return(EINVAL);
2194	if (sa->sa_family != AF_LINK && sa->sa_family != AF_INET6)
2195		return(EINVAL);
2196
2197	dlil_node_absent(ifp, sa);
2198	return (0);
2199}
2200
2201errno_t
2202ifnet_notice_master_elected(ifnet_t ifp)
2203{
2204	if (ifp == NULL)
2205		return(EINVAL);
2206
2207	dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_MASTER_ELECTED, NULL, 0);
2208	return (0);
2209}
2210