]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/kpi_interface.c
xnu-2050.22.13.tar.gz
[apple/xnu.git] / bsd / net / kpi_interface.c
CommitLineData
91447636 1/*
316670eb 2 * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
316670eb 5 *
2d21ac55
A
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.
316670eb 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
316670eb 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
316670eb 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
91447636
A
27 */
28
29#include "kpi_interface.h"
30
31#include <sys/queue.h>
32#include <sys/param.h> /* for definition of NULL */
2d21ac55 33#include <kern/debug.h> /* for panic */
91447636
A
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>
6d2010ae 40#include <sys/mcache.h>
316670eb 41#include <sys/protosw.h>
91447636
A
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>
316670eb
A
48#include <net/if_llreach.h>
49#include <net/route.h>
91447636 50#include <libkern/libkern.h>
2d21ac55 51#include <libkern/OSAtomic.h>
91447636 52#include <kern/locks.h>
316670eb
A
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
91447636 64
b0d623f7
A
65#include "net/net_str_id.h"
66
91447636 67#if IF_LASTCHANGEUPTIME
316670eb
A
68#define TOUCHLASTCHANGE(__if_lastchange) { \
69 (__if_lastchange)->tv_sec = net_uptime(); \
70 (__if_lastchange)->tv_usec = 0; \
71}
91447636 72#else
316670eb 73#define TOUCHLASTCHANGE(__if_lastchange) microtime(__if_lastchange)
91447636
A
74#endif
75
316670eb
A
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 *);
4a3eedf9 86
91447636 87/*
316670eb
A
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.
91447636
A
94 */
95static void
316670eb 96ifnet_kpi_free(ifnet_t ifp)
91447636 97{
316670eb
A
98 ifnet_detached_func detach_func = ifp->if_kpi_storage;
99
100 if (detach_func != NULL)
91447636 101 detach_func(ifp);
316670eb
A
102
103 if (ifp->if_broadcast.length > sizeof (ifp->if_broadcast.u.buffer)) {
91447636
A
104 FREE(ifp->if_broadcast.u.ptr, M_IFADDR);
105 ifp->if_broadcast.u.ptr = NULL;
106 }
316670eb 107
91447636
A
108 dlil_if_release(ifp);
109}
110
316670eb
A
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));
2d21ac55
A
142}
143
91447636 144errno_t
316670eb
A
145ifnet_allocate_extended(const struct ifnet_init_eparams *einit0,
146 ifnet_t *interface)
91447636 147{
316670eb 148 struct ifnet_init_eparams einit;
91447636 149 struct ifnet *ifp = NULL;
316670eb
A
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
2d21ac55
A
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 */
316670eb
A
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);
91447636
A
277 if (ifp->if_broadcast.u.ptr == NULL) {
278 error = ENOMEM;
316670eb
A
279 } else {
280 bcopy(einit.broadcast_addr,
281 ifp->if_broadcast.u.ptr,
282 einit.broadcast_len);
91447636 283 }
316670eb
A
284 } else {
285 bcopy(einit.broadcast_addr,
286 ifp->if_broadcast.u.buffer,
287 einit.broadcast_len);
91447636 288 }
316670eb
A
289 ifp->if_broadcast.length = einit.broadcast_len;
290 } else {
291 bzero(&ifp->if_broadcast, sizeof (ifp->if_broadcast));
91447636 292 }
316670eb
A
293
294 IFCQ_MAXLEN(&ifp->if_snd) = einit.sndq_maxlen;
295
91447636
A
296 if (error == 0) {
297 *interface = ifp;
316670eb
A
298 // temporary - this should be done in dlil_if_acquire
299 ifnet_reference(ifp);
300 } else {
91447636 301 dlil_if_release(ifp);
316670eb 302 *interface = NULL;
91447636
A
303 }
304 }
316670eb 305
91447636 306 /*
316670eb
A
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);
91447636
A
317}
318
319errno_t
6d2010ae 320ifnet_reference(ifnet_t ifp)
91447636 321{
6d2010ae 322 return (dlil_if_ref(ifp));
91447636
A
323}
324
325errno_t
6d2010ae 326ifnet_release(ifnet_t ifp)
91447636 327{
6d2010ae 328 return (dlil_if_free(ifp));
91447636
A
329}
330
316670eb
A
331errno_t
332ifnet_interface_family_find(const char *module_string,
333 ifnet_family_t *family_id)
b0d623f7
A
334{
335 if (module_string == NULL || family_id == NULL)
316670eb
A
336 return (EINVAL);
337
338 return (net_str_id_find_internal(module_string, family_id,
339 NSI_IF_FAM_ID, 1));
b0d623f7
A
340}
341
316670eb
A
342void *
343ifnet_softc(ifnet_t interface)
91447636 344{
316670eb 345 return ((interface == NULL) ? NULL : interface->if_softc);
91447636
A
346}
347
316670eb
A
348const char *
349ifnet_name(ifnet_t interface)
91447636 350{
316670eb 351 return ((interface == NULL) ? NULL : interface->if_name);
91447636
A
352}
353
354ifnet_family_t
316670eb 355ifnet_family(ifnet_t interface)
91447636 356{
316670eb 357 return ((interface == NULL) ? 0 : interface->if_family);
91447636
A
358}
359
360u_int32_t
316670eb 361ifnet_unit(ifnet_t interface)
91447636 362{
316670eb
A
363 return ((interface == NULL) ? (u_int32_t)0xffffffff :
364 (u_int32_t)interface->if_unit);
91447636
A
365}
366
367u_int32_t
316670eb 368ifnet_index(ifnet_t interface)
91447636 369{
316670eb
A
370 return ((interface == NULL) ? (u_int32_t)0xffffffff :
371 interface->if_index);
91447636
A
372}
373
374errno_t
6d2010ae 375ifnet_set_flags(ifnet_t interface, u_int16_t new_flags, u_int16_t mask)
91447636 376{
316670eb
A
377 uint16_t old_flags;
378
6d2010ae
A
379 if (interface == NULL)
380 return (EINVAL);
381
382 ifnet_lock_exclusive(interface);
383
91447636 384 /* If we are modifying the up/down state, call if_updown */
6d2010ae 385 if ((mask & IFF_UP) != 0) {
91447636
A
386 if_updown(interface, (new_flags & IFF_UP) == IFF_UP);
387 }
6d2010ae 388
316670eb 389 old_flags = interface->if_flags;
91447636 390 interface->if_flags = (new_flags & mask) | (interface->if_flags & ~mask);
316670eb
A
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
6d2010ae
A
404 ifnet_lock_done(interface);
405
406 return (0);
91447636
A
407}
408
409u_int16_t
316670eb 410ifnet_flags(ifnet_t interface)
91447636 411{
316670eb
A
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);
91447636
A
452}
453
454errno_t
6d2010ae 455ifnet_set_eflags(ifnet_t interface, u_int32_t new_flags, u_int32_t mask)
91447636 456{
6d2010ae
A
457 if (interface == NULL)
458 return (EINVAL);
459
460 ifnet_lock_exclusive(interface);
316670eb
A
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);
6d2010ae
A
470 ifnet_lock_done(interface);
471
472 return (0);
91447636
A
473}
474
475u_int32_t
316670eb 476ifnet_eflags(ifnet_t interface)
91447636 477{
316670eb 478 return ((interface == NULL) ? 0 : interface->if_eflags);
91447636
A
479}
480
d1ecb069 481errno_t
6d2010ae 482ifnet_set_idle_flags_locked(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask)
d1ecb069 483{
6d2010ae 484 int before, after;
d1ecb069
A
485
486 if (ifp == NULL)
487 return (EINVAL);
488
6d2010ae
A
489 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
490 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
d1ecb069 491
6d2010ae
A
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 }
d1ecb069
A
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
6d2010ae
A
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;
d1ecb069 531
6d2010ae
A
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);
d1ecb069
A
536 lck_mtx_unlock(rnh_lock);
537
6d2010ae 538 return (err);
d1ecb069
A
539}
540
541u_int32_t
542ifnet_idle_flags(ifnet_t ifp)
543{
d1ecb069 544 return ((ifp == NULL) ? 0 : ifp->if_idle_flags);
6d2010ae
A
545}
546
316670eb
A
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,
6d2010ae
A
609 u_int32_t mask)
610{
611 errno_t error = 0;
612 int tmp;
613
614 if (ifp == NULL)
316670eb
A
615 return (EINVAL);
616
6d2010ae
A
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);
316670eb
A
624
625 return (error);
6d2010ae
A
626}
627
316670eb
A
628u_int32_t
629ifnet_capabilities_supported(ifnet_t ifp)
6d2010ae
A
630{
631 return ((ifp == NULL) ? 0 : ifp->if_capabilities);
632}
633
634
316670eb
A
635errno_t
636ifnet_set_capabilities_enabled(ifnet_t ifp, u_int32_t new_caps,
6d2010ae
A
637 u_int32_t mask)
638{
639 errno_t error = 0;
640 int tmp;
316670eb 641 struct kev_msg ev_msg;
6d2010ae
A
642 struct net_event_data ev_data;
643
644 if (ifp == NULL)
316670eb
A
645 return (EINVAL);
646
6d2010ae
A
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);
316670eb 654
6d2010ae 655 /* Notify application of the change */
316670eb
A
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;
6d2010ae 661
316670eb 662 ev_msg.event_code = KEV_DL_IFCAP_CHANGED;
6d2010ae 663 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
316670eb
A
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;
6d2010ae
A
668 ev_msg.dv[1].data_length = 0;
669 kev_post_msg(&ev_msg);
670
316670eb 671 return (error);
6d2010ae
A
672}
673
316670eb
A
674u_int32_t
675ifnet_capabilities_enabled(ifnet_t ifp)
6d2010ae
A
676{
677 return ((ifp == NULL) ? 0 : ifp->if_capenable);
d1ecb069
A
678}
679
316670eb
A
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);
6d2010ae 685
316670eb
A
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);
6d2010ae 689
91447636 690errno_t
6d2010ae 691ifnet_set_offload(ifnet_t interface, ifnet_offload_t offload)
91447636 692{
6d2010ae 693 u_int32_t ifcaps = 0;
316670eb 694
6d2010ae
A
695 if (interface == NULL)
696 return (EINVAL);
697
698 ifnet_lock_exclusive(interface);
316670eb 699 interface->if_hwassist = (offload & offload_mask);
6d2010ae
A
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) {
316670eb
A
713 (void) ifnet_set_capabilities_supported(interface, ifcaps,
714 IFCAP_VALID);
715 (void) ifnet_set_capabilities_enabled(interface, ifcaps,
716 IFCAP_VALID);
6d2010ae
A
717 }
718
719 return (0);
91447636
A
720}
721
722ifnet_offload_t
316670eb 723ifnet_offload(ifnet_t interface)
91447636 724{
316670eb
A
725 return ((interface == NULL) ?
726 0 : (interface->if_hwassist & offload_mask));
91447636
A
727}
728
316670eb
A
729errno_t
730ifnet_set_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t mtuLen)
b0d623f7
A
731{
732 errno_t error = 0;
733
316670eb
A
734 if (interface == NULL || mtuLen < interface->if_mtu)
735 return (EINVAL);
b0d623f7
A
736
737 switch (family) {
316670eb
A
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;
b0d623f7 744
316670eb
A
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;
b0d623f7 751
316670eb
A
752 default:
753 error = EPROTONOSUPPORT;
754 break;
b0d623f7
A
755 }
756
316670eb 757 return (error);
b0d623f7 758}
316670eb
A
759
760errno_t
761ifnet_get_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t *mtuLen)
b0d623f7
A
762{
763 errno_t error = 0;
764
316670eb
A
765 if (interface == NULL || mtuLen == NULL)
766 return (EINVAL);
767
b0d623f7 768 switch (family) {
316670eb
A
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;
b0d623f7 775
316670eb
A
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;
b0d623f7 782
316670eb
A
783 default:
784 error = EPROTONOSUPPORT;
785 break;
b0d623f7
A
786 }
787
316670eb 788 return (error);
b0d623f7
A
789}
790
6d2010ae 791errno_t
b0d623f7
A
792ifnet_set_wake_flags(ifnet_t interface, u_int32_t properties, u_int32_t mask)
793{
316670eb 794 struct kev_msg ev_msg;
6d2010ae
A
795 struct net_event_data ev_data;
796
316670eb
A
797 bzero(&ev_data, sizeof (struct net_event_data));
798 bzero(&ev_msg, sizeof (struct kev_msg));
799
b0d623f7 800 if (interface == NULL)
316670eb 801 return (EINVAL);
b0d623f7
A
802
803 /* Do not accept wacky values */
804 if ((properties & mask) & ~IF_WAKE_VALID_FLAGS)
316670eb 805 return (EINVAL);
b0d623f7 806
6d2010ae 807 ifnet_lock_exclusive(interface);
b0d623f7 808
316670eb
A
809 interface->if_wake_properties =
810 (properties & mask) | (interface->if_wake_properties & ~mask);
b0d623f7 811
6d2010ae 812 ifnet_lock_done(interface);
b0d623f7
A
813
814 (void) ifnet_touch_lastchange(interface);
815
816 /* Notify application of the change */
316670eb
A
817 ev_msg.vendor_code = KEV_VENDOR_APPLE;
818 ev_msg.kev_class = KEV_NETWORK_CLASS;
819 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
b0d623f7 820
316670eb 821 ev_msg.event_code = KEV_DL_WAKEFLAGS_CHANGED;
b0d623f7 822 strlcpy(&ev_data.if_name[0], interface->if_name, IFNAMSIZ);
316670eb
A
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;
b0d623f7
A
827 ev_msg.dv[1].data_length = 0;
828 kev_post_msg(&ev_msg);
6d2010ae 829
316670eb 830 return (0);
b0d623f7
A
831}
832
833u_int32_t
834ifnet_get_wake_flags(ifnet_t interface)
835{
316670eb 836 return ((interface == NULL) ? 0 : interface->if_wake_properties);
b0d623f7
A
837}
838
91447636
A
839/*
840 * Should MIB data store a copy?
841 */
842errno_t
6d2010ae 843ifnet_set_link_mib_data(ifnet_t interface, void *mibData, u_int32_t mibLen)
91447636 844{
6d2010ae
A
845 if (interface == NULL)
846 return (EINVAL);
847
848 ifnet_lock_exclusive(interface);
91447636
A
849 interface->if_linkmib = (void*)mibData;
850 interface->if_linkmiblen = mibLen;
6d2010ae
A
851 ifnet_lock_done(interface);
852 return (0);
91447636
A
853}
854
855errno_t
6d2010ae 856ifnet_get_link_mib_data(ifnet_t interface, void *mibData, u_int32_t *mibLen)
91447636
A
857{
858 errno_t result = 0;
6d2010ae
A
859
860 if (interface == NULL)
861 return (EINVAL);
862
863 ifnet_lock_shared(interface);
91447636
A
864 if (*mibLen < interface->if_linkmiblen)
865 result = EMSGSIZE;
866 if (result == 0 && interface->if_linkmib == NULL)
867 result = ENOTSUP;
6d2010ae 868
91447636
A
869 if (result == 0) {
870 *mibLen = interface->if_linkmiblen;
871 bcopy(interface->if_linkmib, mibData, *mibLen);
872 }
6d2010ae
A
873 ifnet_lock_done(interface);
874
875 return (result);
91447636
A
876}
877
878u_int32_t
316670eb 879ifnet_get_link_mib_data_length(ifnet_t interface)
91447636 880{
316670eb 881 return ((interface == NULL) ? 0 : interface->if_linkmiblen);
91447636
A
882}
883
91447636 884errno_t
316670eb
A
885ifnet_output(ifnet_t interface, protocol_family_t protocol_family,
886 mbuf_t m, void *route, const struct sockaddr *dest)
91447636
A
887{
888 if (interface == NULL || protocol_family == 0 || m == NULL) {
316670eb 889 if (m != NULL)
91447636 890 mbuf_freem_list(m);
316670eb 891 return (EINVAL);
91447636 892 }
316670eb 893 return (dlil_output(interface, protocol_family, m, route, dest, 0, NULL));
91447636
A
894}
895
896errno_t
316670eb 897ifnet_output_raw(ifnet_t interface, protocol_family_t protocol_family, mbuf_t m)
91447636 898{
2d21ac55 899 if (interface == NULL || m == NULL) {
316670eb 900 if (m != NULL)
91447636 901 mbuf_freem_list(m);
316670eb 902 return (EINVAL);
91447636 903 }
316670eb 904 return (dlil_output(interface, protocol_family, m, NULL, NULL, 1, NULL));
91447636
A
905}
906
91447636 907errno_t
316670eb 908ifnet_set_mtu(ifnet_t interface, u_int32_t mtu)
91447636 909{
316670eb
A
910 if (interface == NULL)
911 return (EINVAL);
912
913 interface->if_mtu = mtu;
914 return (0);
91447636
A
915}
916
917u_int32_t
316670eb 918ifnet_mtu(ifnet_t interface)
91447636 919{
316670eb 920 return ((interface == NULL) ? 0 : interface->if_mtu);
91447636
A
921}
922
923u_char
316670eb 924ifnet_type(ifnet_t interface)
91447636 925{
316670eb 926 return ((interface == NULL) ? 0 : interface->if_data.ifi_type);
91447636
A
927}
928
91447636 929errno_t
316670eb 930ifnet_set_addrlen(ifnet_t interface, u_char addrlen)
91447636 931{
316670eb
A
932 if (interface == NULL)
933 return (EINVAL);
934
935 interface->if_data.ifi_addrlen = addrlen;
6d2010ae 936 return (0);
91447636
A
937}
938
939u_char
316670eb 940ifnet_addrlen(ifnet_t interface)
91447636 941{
316670eb 942 return ((interface == NULL) ? 0 : interface->if_data.ifi_addrlen);
91447636 943}
91447636
A
944
945errno_t
316670eb 946ifnet_set_hdrlen(ifnet_t interface, u_char hdrlen)
91447636 947{
316670eb
A
948 if (interface == NULL)
949 return (EINVAL);
950
951 interface->if_data.ifi_hdrlen = hdrlen;
952 return (0);
91447636
A
953}
954
955u_char
316670eb 956ifnet_hdrlen(ifnet_t interface)
91447636 957{
316670eb 958 return ((interface == NULL) ? 0 : interface->if_data.ifi_hdrlen);
91447636
A
959}
960
961errno_t
316670eb 962ifnet_set_metric(ifnet_t interface, u_int32_t metric)
91447636 963{
316670eb
A
964 if (interface == NULL)
965 return (EINVAL);
966
967 interface->if_data.ifi_metric = metric;
968 return (0);
91447636
A
969}
970
316670eb
A
971u_int32_t
972ifnet_metric(ifnet_t interface)
91447636 973{
316670eb 974 return ((interface == NULL) ? 0 : interface->if_data.ifi_metric);
91447636
A
975}
976
977errno_t
316670eb 978ifnet_set_baudrate(struct ifnet *ifp, u_int64_t baudrate)
91447636 979{
316670eb
A
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);
91447636
A
990}
991
316670eb
A
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)
91447636 1001{
316670eb
A
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);
91447636
A
1053}
1054
1055errno_t
316670eb 1056ifnet_set_input_bandwidths(struct ifnet *ifp, struct if_bandwidths *bw)
91447636 1057{
316670eb
A
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);
91447636
A
1075}
1076
1077u_int64_t
316670eb 1078ifnet_output_linkrate(struct ifnet *ifp)
91447636 1079{
316670eb
A
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);
91447636
A
1099}
1100
1101errno_t
316670eb
A
1102ifnet_bandwidths(struct ifnet *ifp, struct if_bandwidths *output_bw,
1103 struct if_bandwidths *input_bw)
91447636 1104{
316670eb 1105 if (ifp == NULL)
6d2010ae 1106 return (EINVAL);
2d21ac55 1107
316670eb
A
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}
91447636 1115
316670eb
A
1116errno_t
1117ifnet_stat_increment(struct ifnet *ifp,
1118 const struct ifnet_stat_increment_param *s)
1119{
1120 if (ifp == NULL)
1121 return (EINVAL);
91447636 1122
316670eb
A
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);
91447636 1141
91447636 1142 /* Touch the last change time. */
316670eb 1143 TOUCHLASTCHANGE(&ifp->if_lastchange);
91447636 1144
6d2010ae 1145 return (0);
91447636
A
1146}
1147
1148errno_t
316670eb 1149ifnet_stat_increment_in(struct ifnet *ifp, u_int32_t packets_in,
6d2010ae 1150 u_int32_t bytes_in, u_int32_t errors_in)
91447636 1151{
316670eb 1152 if (ifp == NULL)
6d2010ae 1153 return (EINVAL);
91447636 1154
316670eb
A
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);
91447636 1161
316670eb 1162 TOUCHLASTCHANGE(&ifp->if_lastchange);
91447636 1163
6d2010ae 1164 return (0);
91447636
A
1165}
1166
1167errno_t
316670eb 1168ifnet_stat_increment_out(struct ifnet *ifp, u_int32_t packets_out,
6d2010ae 1169 u_int32_t bytes_out, u_int32_t errors_out)
91447636 1170{
316670eb 1171 if (ifp == NULL)
6d2010ae 1172 return (EINVAL);
91447636 1173
316670eb
A
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);
91447636 1180
316670eb 1181 TOUCHLASTCHANGE(&ifp->if_lastchange);
91447636 1182
6d2010ae 1183 return (0);
91447636
A
1184}
1185
1186errno_t
316670eb 1187ifnet_set_stat(struct ifnet *ifp, const struct ifnet_stats_param *s)
91447636 1188{
316670eb 1189 if (ifp == NULL)
6d2010ae 1190 return (EINVAL);
2d21ac55 1191
316670eb
A
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);
2d21ac55 1196
316670eb
A
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);
91447636 1201
316670eb
A
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);
91447636
A
1205
1206 /* Touch the last change time. */
316670eb 1207 TOUCHLASTCHANGE(&ifp->if_lastchange);
91447636 1208
316670eb 1209 return (0);
91447636
A
1210}
1211
1212errno_t
316670eb 1213ifnet_stat(struct ifnet *ifp, struct ifnet_stats_param *s)
91447636 1214{
316670eb 1215 if (ifp == NULL)
6d2010ae 1216 return (EINVAL);
91447636 1217
316670eb
A
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);
91447636 1222
316670eb
A
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);
91447636 1227
316670eb
A
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);
91447636 1231
6d2010ae 1232 return (0);
91447636
A
1233}
1234
1235errno_t
6d2010ae 1236ifnet_touch_lastchange(ifnet_t interface)
91447636 1237{
6d2010ae
A
1238 if (interface == NULL)
1239 return (EINVAL);
2d21ac55 1240
91447636 1241 TOUCHLASTCHANGE(&interface->if_lastchange);
2d21ac55 1242
6d2010ae 1243 return (0);
91447636
A
1244}
1245
1246errno_t
6d2010ae 1247ifnet_lastchange(ifnet_t interface, struct timeval *last_change)
91447636 1248{
6d2010ae
A
1249 if (interface == NULL)
1250 return (EINVAL);
2d21ac55 1251
91447636 1252 *last_change = interface->if_data.ifi_lastchange;
91447636
A
1253#if IF_LASTCHANGEUPTIME
1254 /* Crude conversion from uptime to calendar time */
1255 last_change->tv_sec += boottime_sec();
1256#endif
6d2010ae 1257 return (0);
91447636
A
1258}
1259
1260errno_t
6d2010ae 1261ifnet_get_address_list(ifnet_t interface, ifaddr_t **addresses)
91447636 1262{
6d2010ae
A
1263 return (addresses == NULL ? EINVAL :
1264 ifnet_get_address_list_family(interface, addresses, 0));
91447636
A
1265}
1266
6d2010ae
A
1267struct ifnet_addr_list {
1268 SLIST_ENTRY(ifnet_addr_list) ifal_le;
1269 struct ifaddr *ifal_ifa;
1270};
1271
91447636 1272errno_t
6d2010ae
A
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)
91447636 1283{
6d2010ae
A
1284 SLIST_HEAD(, ifnet_addr_list) ifal_head;
1285 struct ifnet_addr_list *ifal, *ifal_tmp;
91447636
A
1286 struct ifnet *ifp;
1287 int count = 0;
6d2010ae
A
1288 errno_t err = 0;
1289
1290 SLIST_INIT(&ifal_head);
1291
1292 if (addresses == NULL) {
1293 err = EINVAL;
1294 goto done;
1295 }
91447636 1296 *addresses = NULL;
6d2010ae
A
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
91447636 1311 ifnet_head_lock_shared();
6d2010ae
A
1312 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1313 if (interface != NULL && ifp != interface)
1314 continue;
1315one:
91447636 1316 ifnet_lock_shared(ifp);
6d2010ae
A
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;
91447636 1325 }
6d2010ae
A
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);
91447636
A
1341 }
1342 }
91447636 1343 ifnet_lock_done(ifp);
6d2010ae
A
1344 if (detached)
1345 break;
91447636 1346 }
6d2010ae 1347 if (!detached)
91447636 1348 ifnet_head_done();
6d2010ae
A
1349
1350 if (count == 0) {
1351 err = ENXIO;
1352 goto done;
91447636 1353 }
6d2010ae
A
1354 MALLOC(*addresses, ifaddr_t *, sizeof (ifaddr_t) * (count + 1),
1355 M_TEMP, how);
1356 if (*addresses == NULL) {
1357 err = ENOMEM;
1358 goto done;
91447636 1359 }
6d2010ae
A
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);
91447636
A
1373}
1374
1375void
6d2010ae 1376ifnet_free_address_list(ifaddr_t *addresses)
91447636
A
1377{
1378 int i;
6d2010ae
A
1379
1380 if (addresses == NULL)
1381 return;
1382
91447636 1383 for (i = 0; addresses[i] != NULL; i++)
6d2010ae
A
1384 IFA_REMREF(addresses[i]);
1385
91447636
A
1386 FREE(addresses, M_TEMP);
1387}
1388
6d2010ae
A
1389void *
1390ifnet_lladdr(ifnet_t interface)
91447636 1391{
6d2010ae
A
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);
316670eb 1404 lladdr = LLADDR(SDL((void *)ifa->ifa_addr));
6d2010ae
A
1405 IFA_UNLOCK(ifa);
1406
1407 return (lladdr);
91447636
A
1408}
1409
1410errno_t
316670eb
A
1411ifnet_llbroadcast_copy_bytes(ifnet_t interface, void *addr, size_t buffer_len,
1412 size_t *out_len)
91447636 1413{
316670eb
A
1414 if (interface == NULL || addr == NULL || out_len == NULL)
1415 return (EINVAL);
1416
91447636 1417 *out_len = interface->if_broadcast.length;
316670eb
A
1418
1419 if (buffer_len < interface->if_broadcast.length)
1420 return (EMSGSIZE);
1421
91447636 1422 if (interface->if_broadcast.length == 0)
316670eb
A
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);
91447636 1432 }
316670eb
A
1433
1434 return (0);
91447636
A
1435}
1436
1437errno_t
6d2010ae 1438ifnet_lladdr_copy_bytes(ifnet_t interface, void *lladdr, size_t lladdr_len)
91447636
A
1439{
1440 struct sockaddr_dl *sdl;
6d2010ae
A
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);
316670eb 1452 sdl = SDL((void *)ifa->ifa_addr);
6d2010ae
A
1453 if (lladdr_len != sdl->sdl_alen) {
1454 bzero(lladdr, lladdr_len);
1455 IFA_UNLOCK(ifa);
1456 return (EMSGSIZE);
91447636 1457 }
6d2010ae
A
1458 bcopy(LLADDR(sdl), lladdr, lladdr_len);
1459 IFA_UNLOCK(ifa);
1460
1461 return (0);
91447636
A
1462}
1463
1464static errno_t
6d2010ae
A
1465ifnet_set_lladdr_internal(ifnet_t interface, const void *lladdr,
1466 size_t lladdr_len, u_char new_type, int apply_type)
91447636
A
1467{
1468 struct ifaddr *ifa;
91447636 1469 errno_t error = 0;
6d2010ae
A
1470
1471 if (interface == NULL)
1472 return (EINVAL);
1473
91447636 1474 ifnet_head_lock_shared();
6d2010ae
A
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 }
91447636
A
1482 ifa = ifnet_addrs[interface->if_index - 1];
1483 if (ifa != NULL) {
6d2010ae
A
1484 struct sockaddr_dl *sdl;
1485
1486 IFA_LOCK_SPIN(ifa);
316670eb 1487 sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
91447636
A
1488 if (lladdr_len != 0) {
1489 bcopy(lladdr, LLADDR(sdl), lladdr_len);
6d2010ae 1490 } else {
91447636
A
1491 bzero(LLADDR(sdl), interface->if_addrlen);
1492 }
1493 sdl->sdl_alen = lladdr_len;
6d2010ae 1494
91447636
A
1495 if (apply_type) {
1496 sdl->sdl_type = new_type;
1497 }
6d2010ae
A
1498 IFA_UNLOCK(ifa);
1499 } else {
91447636
A
1500 error = ENXIO;
1501 }
6d2010ae 1502 ifnet_lock_done(interface);
91447636 1503 ifnet_head_done();
6d2010ae 1504
91447636
A
1505 /* Generate a kernel event */
1506 if (error == 0) {
1507 dlil_post_msg(interface, KEV_DL_SUBCLASS,
316670eb 1508 KEV_DL_LINK_ADDRESS_CHANGED, NULL, 0);
91447636 1509 }
6d2010ae
A
1510
1511 return (error);
91447636
A
1512}
1513
1514errno_t
316670eb 1515ifnet_set_lladdr(ifnet_t interface, const void* lladdr, size_t lladdr_len)
91447636 1516{
316670eb 1517 return (ifnet_set_lladdr_internal(interface, lladdr, lladdr_len, 0, 0));
91447636
A
1518}
1519
1520errno_t
316670eb
A
1521ifnet_set_lladdr_and_type(ifnet_t interface, const void* lladdr,
1522 size_t lladdr_len, u_char type)
91447636 1523{
316670eb
A
1524 return (ifnet_set_lladdr_internal(interface, lladdr,
1525 lladdr_len, type, 1));
91447636
A
1526}
1527
1528errno_t
6d2010ae
A
1529ifnet_add_multicast(ifnet_t interface, const struct sockaddr *maddr,
1530 ifmultiaddr_t *ifmap)
91447636 1531{
6d2010ae
A
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));
91447636
A
1540}
1541
1542errno_t
6d2010ae 1543ifnet_remove_multicast(ifmultiaddr_t ifma)
91447636 1544{
6d2010ae
A
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));
91447636
A
1556}
1557
6d2010ae
A
1558errno_t
1559ifnet_get_multicast_list(ifnet_t ifp, ifmultiaddr_t **addresses)
91447636
A
1560{
1561 int count = 0;
1562 int cmax = 0;
1563 struct ifmultiaddr *addr;
6d2010ae
A
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++;
91447636 1571 }
6d2010ae
A
1572
1573 MALLOC(*addresses, ifmultiaddr_t *, sizeof (ifmultiaddr_t) * (cmax + 1),
1574 M_TEMP, M_NOWAIT);
0c530ab8 1575 if (*addresses == NULL) {
6d2010ae
A
1576 ifnet_lock_done(ifp);
1577 return (ENOMEM);
0c530ab8 1578 }
6d2010ae
A
1579
1580 LIST_FOREACH(addr, &ifp->if_multiaddrs, ifma_link) {
91447636
A
1581 if (count + 1 > cmax)
1582 break;
1583 (*addresses)[count] = (ifmultiaddr_t)addr;
1584 ifmaddr_reference((*addresses)[count]);
1585 count++;
1586 }
6d2010ae
A
1587 (*addresses)[cmax] = NULL;
1588 ifnet_lock_done(ifp);
1589
1590 return (0);
91447636
A
1591}
1592
1593void
316670eb 1594ifnet_free_multicast_list(ifmultiaddr_t *addresses)
91447636
A
1595{
1596 int i;
316670eb
A
1597
1598 if (addresses == NULL)
1599 return;
1600
91447636 1601 for (i = 0; addresses[i] != NULL; i++)
91447636 1602 ifmaddr_release(addresses[i]);
316670eb 1603
91447636
A
1604 FREE(addresses, M_TEMP);
1605}
1606
1607errno_t
6d2010ae 1608ifnet_find_by_name(const char *ifname, ifnet_t *ifpp)
91447636
A
1609{
1610 struct ifnet *ifp;
1611 int namelen;
6d2010ae
A
1612
1613 if (ifname == NULL)
1614 return (EINVAL);
1615
91447636 1616 namelen = strlen(ifname);
6d2010ae
A
1617
1618 *ifpp = NULL;
1619
91447636 1620 ifnet_head_lock_shared();
6d2010ae
A
1621 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1622 struct ifaddr *ifa;
13fec989 1623 struct sockaddr_dl *ll_addr;
2d21ac55 1624
6d2010ae
A
1625 ifa = ifnet_addrs[ifp->if_index - 1];
1626 if (ifa == NULL)
13fec989 1627 continue;
2d21ac55 1628
6d2010ae 1629 IFA_LOCK(ifa);
316670eb 1630 ll_addr = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
2d21ac55 1631
316670eb
A
1632 if (namelen == ll_addr->sdl_nlen && strncmp(ll_addr->sdl_data,
1633 ifname, ll_addr->sdl_nlen) == 0) {
6d2010ae
A
1634 IFA_UNLOCK(ifa);
1635 *ifpp = ifp;
1636 ifnet_reference(*ifpp);
91447636
A
1637 break;
1638 }
6d2010ae 1639 IFA_UNLOCK(ifa);
91447636
A
1640 }
1641 ifnet_head_done();
6d2010ae
A
1642
1643 return ((ifp == NULL) ? ENXIO : 0);
91447636
A
1644}
1645
1646errno_t
4a3eedf9
A
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
6d2010ae
A
1658struct ifnet_list {
1659 SLIST_ENTRY(ifnet_list) ifl_le;
1660 struct ifnet *ifl_ifp;
1661};
1662
4a3eedf9
A
1663static errno_t
1664ifnet_list_get_common(ifnet_family_t family, boolean_t get_all, ifnet_t **list,
1665 u_int32_t *count)
91447636 1666{
6d2010ae
A
1667#pragma unused(get_all)
1668 SLIST_HEAD(, ifnet_list) ifl_head;
1669 struct ifnet_list *ifl, *ifl_tmp;
91447636 1670 struct ifnet *ifp;
6d2010ae
A
1671 int cnt = 0;
1672 errno_t err = 0;
4a3eedf9 1673
6d2010ae 1674 SLIST_INIT(&ifl_head);
4a3eedf9 1675
6d2010ae
A
1676 if (list == NULL || count == NULL) {
1677 err = EINVAL;
1678 goto done;
91447636 1679 }
6d2010ae
A
1680 *count = 0;
1681 *list = NULL;
91447636 1682
6d2010ae
A
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;
91447636 1692 }
6d2010ae
A
1693 ifl->ifl_ifp = ifp;
1694 ifnet_reference(ifp);
1695 SLIST_INSERT_HEAD(&ifl_head, ifl, ifl_le);
1696 ++cnt;
91447636 1697 }
91447636
A
1698 }
1699 ifnet_head_done();
4a3eedf9 1700
6d2010ae
A
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);
91447636
A
1726}
1727
1728void
4a3eedf9 1729ifnet_list_free(ifnet_t *interfaces)
91447636
A
1730{
1731 int i;
4a3eedf9
A
1732
1733 if (interfaces == NULL)
1734 return;
1735
6d2010ae 1736 for (i = 0; interfaces[i]; i++)
91447636 1737 ifnet_release(interfaces[i]);
4a3eedf9 1738
91447636
A
1739 FREE(interfaces, M_TEMP);
1740}
1741
316670eb
A
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
91447636 1825/****************************************************************************/
316670eb 1826/* ifaddr_t accessors */
91447636
A
1827/****************************************************************************/
1828
1829errno_t
6d2010ae 1830ifaddr_reference(ifaddr_t ifa)
91447636 1831{
6d2010ae
A
1832 if (ifa == NULL)
1833 return (EINVAL);
1834
1835 IFA_ADDREF(ifa);
1836 return (0);
91447636
A
1837}
1838
1839errno_t
6d2010ae 1840ifaddr_release(ifaddr_t ifa)
91447636 1841{
6d2010ae
A
1842 if (ifa == NULL)
1843 return (EINVAL);
1844
1845 IFA_REMREF(ifa);
1846 return (0);
91447636
A
1847}
1848
1849sa_family_t
6d2010ae 1850ifaddr_address_family(ifaddr_t ifa)
91447636 1851{
6d2010ae
A
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);
91447636
A
1861}
1862
1863errno_t
6d2010ae 1864ifaddr_address(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
91447636
A
1865{
1866 u_int32_t copylen;
6d2010ae
A
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;
91447636 1879 bcopy(ifa->ifa_addr, out_addr, copylen);
6d2010ae
A
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);
91447636
A
1888}
1889
1890errno_t
6d2010ae 1891ifaddr_dstaddress(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
91447636
A
1892{
1893 u_int32_t copylen;
6d2010ae
A
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;
91447636
A
1906 bcopy(ifa->ifa_dstaddr, out_addr, copylen);
1907
6d2010ae
A
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);
91447636
A
1915}
1916
1917errno_t
6d2010ae 1918ifaddr_netmask(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
91447636
A
1919{
1920 u_int32_t copylen;
6d2010ae
A
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;
91447636 1933 bcopy(ifa->ifa_netmask, out_addr, copylen);
6d2010ae
A
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);
91447636
A
1942}
1943
1944ifnet_t
6d2010ae 1945ifaddr_ifnet(ifaddr_t ifa)
91447636
A
1946{
1947 struct ifnet *ifp;
6d2010ae
A
1948
1949 if (ifa == NULL)
1950 return (NULL);
1951
1952 /* ifa_ifp is set once at creation time; it is never changed */
91447636 1953 ifp = ifa->ifa_ifp;
6d2010ae
A
1954
1955 return (ifp);
91447636
A
1956}
1957
1958ifaddr_t
316670eb 1959ifaddr_withaddr(const struct sockaddr *address)
91447636 1960{
316670eb
A
1961 if (address == NULL)
1962 return (NULL);
1963
1964 return (ifa_ifwithaddr(address));
91447636
A
1965}
1966
1967ifaddr_t
316670eb 1968ifaddr_withdstaddr(const struct sockaddr *address)
91447636 1969{
316670eb
A
1970 if (address == NULL)
1971 return (NULL);
1972
1973 return (ifa_ifwithdstaddr(address));
91447636
A
1974}
1975
1976ifaddr_t
316670eb 1977ifaddr_withnet(const struct sockaddr *net)
91447636 1978{
316670eb
A
1979 if (net == NULL)
1980 return (NULL);
1981
1982 return (ifa_ifwithnet(net));
91447636
A
1983}
1984
1985ifaddr_t
316670eb
A
1986ifaddr_withroute(int flags, const struct sockaddr *destination,
1987 const struct sockaddr *gateway)
91447636 1988{
316670eb
A
1989 if (destination == NULL || gateway == NULL)
1990 return (NULL);
1991
1992 return (ifa_ifwithroute(flags, destination, gateway));
91447636
A
1993}
1994
1995ifaddr_t
316670eb 1996ifaddr_findbestforaddr(const struct sockaddr *addr, ifnet_t interface)
91447636 1997{
316670eb
A
1998 if (addr == NULL || interface == NULL)
1999 return (NULL);
2000
2001 return (ifaof_ifpforaddr(addr, interface));
91447636
A
2002}
2003
2004errno_t
6d2010ae 2005ifmaddr_reference(ifmultiaddr_t ifmaddr)
91447636 2006{
6d2010ae
A
2007 if (ifmaddr == NULL)
2008 return (EINVAL);
2009
2010 IFMA_ADDREF(ifmaddr);
2011 return (0);
91447636
A
2012}
2013
2014errno_t
6d2010ae 2015ifmaddr_release(ifmultiaddr_t ifmaddr)
91447636 2016{
6d2010ae
A
2017 if (ifmaddr == NULL)
2018 return (EINVAL);
2019
2020 IFMA_REMREF(ifmaddr);
2021 return (0);
91447636
A
2022}
2023
2024errno_t
6d2010ae
A
2025ifmaddr_address(ifmultiaddr_t ifma, struct sockaddr *out_addr,
2026 u_int32_t addr_size)
91447636
A
2027{
2028 u_int32_t copylen;
6d2010ae
A
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);
91447636
A
2049}
2050
2051errno_t
6d2010ae
A
2052ifmaddr_lladdress(ifmultiaddr_t ifma, struct sockaddr *out_addr,
2053 u_int32_t addr_size)
91447636 2054{
6d2010ae
A
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));
91447636
A
2063}
2064
2065ifnet_t
6d2010ae 2066ifmaddr_ifnet(ifmultiaddr_t ifma)
91447636 2067{
316670eb 2068 return ((ifma == NULL) ? NULL : ifma->ifma_ifp);
91447636 2069}
d1ecb069
A
2070
2071/******************************************************************************/
2072/* interface cloner */
2073/******************************************************************************/
2074
316670eb
A
2075errno_t
2076ifnet_clone_attach(struct ifnet_clone_params *cloner_params,
2077 if_clone_t *ifcloner)
d1ecb069
A
2078{
2079 errno_t error = 0;
2080 struct if_clone *ifc = NULL;
2081 size_t namelen;
316670eb
A
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) {
d1ecb069
A
2088 error = EINVAL;
2089 goto fail;
2090 }
316670eb 2091
d1ecb069 2092 if (if_clone_lookup(cloner_params->ifc_name, NULL) != NULL) {
316670eb
A
2093 printf("%s: already a cloner for %s\n", __func__,
2094 cloner_params->ifc_name);
d1ecb069
A
2095 error = EEXIST;
2096 goto fail;
2097 }
2098
2099 /* Make room for name string */
316670eb
A
2100 ifc = _MALLOC(sizeof (struct if_clone) + IFNAMSIZ + 1, M_CLONE,
2101 M_WAITOK | M_ZERO);
d1ecb069 2102 if (ifc == NULL) {
316670eb 2103 printf("%s: _MALLOC failed\n", __func__);
d1ecb069
A
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) {
316670eb 2116 printf("%s: if_clone_attach failed %d\n", __func__, error);
d1ecb069
A
2117 goto fail;
2118 }
2119 *ifcloner = ifc;
316670eb
A
2120
2121 return (0);
d1ecb069
A
2122fail:
2123 if (ifc != NULL)
2124 FREE(ifc, M_CLONE);
316670eb 2125 return (error);
d1ecb069
A
2126}
2127
316670eb 2128errno_t
d1ecb069
A
2129ifnet_clone_detach(if_clone_t ifcloner)
2130{
2131 errno_t error = 0;
2132 struct if_clone *ifc = ifcloner;
316670eb 2133
d1ecb069 2134 if (ifc == NULL || ifc->ifc_name == NULL)
316670eb
A
2135 return (EINVAL);
2136
d1ecb069 2137 if ((if_clone_lookup(ifc->ifc_name, NULL)) == NULL) {
316670eb 2138 printf("%s: no cloner for %s\n", __func__, ifc->ifc_name);
d1ecb069
A
2139 error = EINVAL;
2140 goto fail;
2141 }
2142
2143 if_clone_detach(ifc);
316670eb 2144
d1ecb069
A
2145 FREE(ifc, M_CLONE);
2146
d1ecb069 2147fail:
316670eb 2148 return (error);
d1ecb069
A
2149}
2150
316670eb
A
2151/******************************************************************************/
2152/* misc */
2153/******************************************************************************/
d1ecb069 2154
316670eb
A
2155extern void udp_get_ports_used(unsigned int ifindex, uint8_t *bitfield);
2156extern void tcp_get_ports_used(unsigned int ifindex, uint8_t *bitfield);
d1ecb069 2157
316670eb
A
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}