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