]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/kpi_interface.c
xnu-2422.1.72.tar.gz
[apple/xnu.git] / bsd / net / kpi_interface.c
CommitLineData
91447636 1/*
39236c6e 2 * Copyright (c) 2004-2013 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>
39236c6e 42#include <sys/syslog.h>
91447636
A
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>
316670eb 49#include <net/if_llreach.h>
39236c6e 50#include <net/if_ether.h>
316670eb 51#include <net/route.h>
91447636 52#include <libkern/libkern.h>
2d21ac55 53#include <libkern/OSAtomic.h>
91447636 54#include <kern/locks.h>
316670eb
A
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>
39236c6e
A
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>
316670eb
A
65#ifdef INET
66#include <netinet/igmp_var.h>
67#endif
68#ifdef INET6
69#include <netinet6/mld6_var.h>
70#endif
91447636 71
b0d623f7
A
72#include "net/net_str_id.h"
73
39236c6e
A
74#if CONFIG_MACF
75#include <sys/kauth.h>
76#include <security/mac_framework.h>
77#endif
78
316670eb
A
79#define TOUCHLASTCHANGE(__if_lastchange) { \
80 (__if_lastchange)->tv_sec = net_uptime(); \
81 (__if_lastchange)->tv_usec = 0; \
82}
316670eb
A
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 *);
4a3eedf9 92
91447636 93/*
316670eb
A
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.
91447636
A
100 */
101static void
316670eb 102ifnet_kpi_free(ifnet_t ifp)
91447636 103{
316670eb
A
104 ifnet_detached_func detach_func = ifp->if_kpi_storage;
105
106 if (detach_func != NULL)
91447636 107 detach_func(ifp);
316670eb
A
108
109 if (ifp->if_broadcast.length > sizeof (ifp->if_broadcast.u.buffer)) {
91447636
A
110 FREE(ifp->if_broadcast.u.ptr, M_IFADDR);
111 ifp->if_broadcast.u.ptr = NULL;
112 }
316670eb 113
91447636
A
114 dlil_if_release(ifp);
115}
116
316670eb
A
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));
2d21ac55
A
148}
149
91447636 150errno_t
316670eb
A
151ifnet_allocate_extended(const struct ifnet_init_eparams *einit0,
152 ifnet_t *interface)
91447636 153{
316670eb 154 struct ifnet_init_eparams einit;
91447636 155 struct ifnet *ifp = NULL;
316670eb
A
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
2d21ac55
A
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 */
39236c6e 207 strncpy(__DECONST(char *, ifp->if_name), einit.name, IFNAMSIZ);
316670eb
A
208 ifp->if_type = einit.type;
209 ifp->if_family = einit.family;
39236c6e 210 ifp->if_subfamily = einit.subfamily;
316670eb
A
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;
39236c6e
A
219 ifp->if_output_lt.eff_lt = einit.output_lt;
220 ifp->if_output_lt.max_lt = einit.output_lt_max;
316670eb
A
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;
39236c6e
A
225 ifp->if_input_lt.eff_lt = einit.input_lt;
226 ifp->if_input_lt.max_lt = einit.input_lt_max;
316670eb
A
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;
39236c6e
A
231 ifp->if_framer_legacy = einit.framer;
232 ifp->if_framer = einit.framer_extended;
316670eb
A
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
39236c6e
A
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
316670eb
A
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
316670eb
A
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
39236c6e
A
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
316670eb
A
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);
91447636
A
331 if (ifp->if_broadcast.u.ptr == NULL) {
332 error = ENOMEM;
316670eb
A
333 } else {
334 bcopy(einit.broadcast_addr,
335 ifp->if_broadcast.u.ptr,
336 einit.broadcast_len);
91447636 337 }
316670eb
A
338 } else {
339 bcopy(einit.broadcast_addr,
340 ifp->if_broadcast.u.buffer,
341 einit.broadcast_len);
91447636 342 }
316670eb
A
343 ifp->if_broadcast.length = einit.broadcast_len;
344 } else {
345 bzero(&ifp->if_broadcast, sizeof (ifp->if_broadcast));
91447636 346 }
316670eb
A
347
348 IFCQ_MAXLEN(&ifp->if_snd) = einit.sndq_maxlen;
349
91447636
A
350 if (error == 0) {
351 *interface = ifp;
316670eb
A
352 // temporary - this should be done in dlil_if_acquire
353 ifnet_reference(ifp);
354 } else {
91447636 355 dlil_if_release(ifp);
316670eb 356 *interface = NULL;
91447636
A
357 }
358 }
316670eb 359
91447636 360 /*
316670eb
A
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);
91447636
A
371}
372
373errno_t
6d2010ae 374ifnet_reference(ifnet_t ifp)
91447636 375{
6d2010ae 376 return (dlil_if_ref(ifp));
91447636
A
377}
378
379errno_t
6d2010ae 380ifnet_release(ifnet_t ifp)
91447636 381{
6d2010ae 382 return (dlil_if_free(ifp));
91447636
A
383}
384
316670eb
A
385errno_t
386ifnet_interface_family_find(const char *module_string,
387 ifnet_family_t *family_id)
b0d623f7
A
388{
389 if (module_string == NULL || family_id == NULL)
316670eb
A
390 return (EINVAL);
391
392 return (net_str_id_find_internal(module_string, family_id,
393 NSI_IF_FAM_ID, 1));
b0d623f7
A
394}
395
316670eb
A
396void *
397ifnet_softc(ifnet_t interface)
91447636 398{
316670eb 399 return ((interface == NULL) ? NULL : interface->if_softc);
91447636
A
400}
401
316670eb
A
402const char *
403ifnet_name(ifnet_t interface)
91447636 404{
316670eb 405 return ((interface == NULL) ? NULL : interface->if_name);
91447636
A
406}
407
408ifnet_family_t
316670eb 409ifnet_family(ifnet_t interface)
91447636 410{
316670eb 411 return ((interface == NULL) ? 0 : interface->if_family);
91447636
A
412}
413
39236c6e
A
414ifnet_subfamily_t
415ifnet_subfamily(ifnet_t interface)
416{
417 return ((interface == NULL) ? 0 : interface->if_subfamily);
418}
419
91447636 420u_int32_t
316670eb 421ifnet_unit(ifnet_t interface)
91447636 422{
316670eb
A
423 return ((interface == NULL) ? (u_int32_t)0xffffffff :
424 (u_int32_t)interface->if_unit);
91447636
A
425}
426
427u_int32_t
316670eb 428ifnet_index(ifnet_t interface)
91447636 429{
316670eb
A
430 return ((interface == NULL) ? (u_int32_t)0xffffffff :
431 interface->if_index);
91447636
A
432}
433
434errno_t
6d2010ae 435ifnet_set_flags(ifnet_t interface, u_int16_t new_flags, u_int16_t mask)
91447636 436{
316670eb
A
437 uint16_t old_flags;
438
6d2010ae
A
439 if (interface == NULL)
440 return (EINVAL);
441
442 ifnet_lock_exclusive(interface);
443
91447636 444 /* If we are modifying the up/down state, call if_updown */
6d2010ae 445 if ((mask & IFF_UP) != 0) {
91447636
A
446 if_updown(interface, (new_flags & IFF_UP) == IFF_UP);
447 }
6d2010ae 448
316670eb 449 old_flags = interface->if_flags;
91447636 450 interface->if_flags = (new_flags & mask) | (interface->if_flags & ~mask);
316670eb
A
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
6d2010ae
A
464 ifnet_lock_done(interface);
465
466 return (0);
91447636
A
467}
468
469u_int16_t
316670eb 470ifnet_flags(ifnet_t interface)
91447636 471{
316670eb
A
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);
91447636
A
512}
513
514errno_t
6d2010ae 515ifnet_set_eflags(ifnet_t interface, u_int32_t new_flags, u_int32_t mask)
91447636 516{
6d2010ae
A
517 if (interface == NULL)
518 return (EINVAL);
519
520 ifnet_lock_exclusive(interface);
316670eb
A
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);
6d2010ae
A
530 ifnet_lock_done(interface);
531
532 return (0);
91447636
A
533}
534
535u_int32_t
316670eb 536ifnet_eflags(ifnet_t interface)
91447636 537{
316670eb 538 return ((interface == NULL) ? 0 : interface->if_eflags);
91447636
A
539}
540
d1ecb069 541errno_t
6d2010ae 542ifnet_set_idle_flags_locked(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask)
d1ecb069 543{
6d2010ae 544 int before, after;
d1ecb069
A
545
546 if (ifp == NULL)
547 return (EINVAL);
548
6d2010ae
A
549 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
550 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
d1ecb069 551
6d2010ae
A
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 }
d1ecb069
A
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);
d1ecb069
A
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);
d1ecb069
A
578 }
579
6d2010ae
A
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;
d1ecb069 587
6d2010ae
A
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);
d1ecb069
A
592 lck_mtx_unlock(rnh_lock);
593
6d2010ae 594 return (err);
d1ecb069
A
595}
596
597u_int32_t
598ifnet_idle_flags(ifnet_t ifp)
599{
d1ecb069 600 return ((ifp == NULL) ? 0 : ifp->if_idle_flags);
6d2010ae
A
601}
602
316670eb
A
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,
6d2010ae
A
665 u_int32_t mask)
666{
667 errno_t error = 0;
668 int tmp;
669
670 if (ifp == NULL)
316670eb
A
671 return (EINVAL);
672
6d2010ae
A
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);
316670eb
A
680
681 return (error);
6d2010ae
A
682}
683
316670eb
A
684u_int32_t
685ifnet_capabilities_supported(ifnet_t ifp)
6d2010ae
A
686{
687 return ((ifp == NULL) ? 0 : ifp->if_capabilities);
688}
689
690
316670eb
A
691errno_t
692ifnet_set_capabilities_enabled(ifnet_t ifp, u_int32_t new_caps,
6d2010ae
A
693 u_int32_t mask)
694{
695 errno_t error = 0;
696 int tmp;
316670eb 697 struct kev_msg ev_msg;
6d2010ae
A
698 struct net_event_data ev_data;
699
700 if (ifp == NULL)
316670eb
A
701 return (EINVAL);
702
6d2010ae
A
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);
316670eb 710
6d2010ae 711 /* Notify application of the change */
316670eb
A
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;
6d2010ae 717
316670eb 718 ev_msg.event_code = KEV_DL_IFCAP_CHANGED;
6d2010ae 719 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
316670eb
A
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;
6d2010ae
A
724 ev_msg.dv[1].data_length = 0;
725 kev_post_msg(&ev_msg);
726
316670eb 727 return (error);
6d2010ae
A
728}
729
316670eb
A
730u_int32_t
731ifnet_capabilities_enabled(ifnet_t ifp)
6d2010ae
A
732{
733 return ((ifp == NULL) ? 0 : ifp->if_capenable);
d1ecb069
A
734}
735
316670eb
A
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 |
39236c6e
A
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);
6d2010ae 742
316670eb
A
743static const ifnet_offload_t any_offload_csum =
744 (IFNET_CSUM_IP | IFNET_CSUM_TCP | IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT |
39236c6e 745 IFNET_CSUM_TCPIPV6 | IFNET_CSUM_UDPIPV6 | IFNET_CSUM_PARTIAL);
6d2010ae 746
91447636 747errno_t
6d2010ae 748ifnet_set_offload(ifnet_t interface, ifnet_offload_t offload)
91447636 749{
6d2010ae 750 u_int32_t ifcaps = 0;
316670eb 751
6d2010ae
A
752 if (interface == NULL)
753 return (EINVAL);
754
755 ifnet_lock_exclusive(interface);
316670eb 756 interface->if_hwassist = (offload & offload_mask);
39236c6e
A
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 }
6d2010ae
A
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;
39236c6e
A
784 if ((offload & IFNET_TX_STATUS))
785 ifcaps |= IFNET_TX_STATUS;
6d2010ae 786 if (ifcaps != 0) {
316670eb
A
787 (void) ifnet_set_capabilities_supported(interface, ifcaps,
788 IFCAP_VALID);
789 (void) ifnet_set_capabilities_enabled(interface, ifcaps,
790 IFCAP_VALID);
6d2010ae
A
791 }
792
793 return (0);
91447636
A
794}
795
796ifnet_offload_t
316670eb 797ifnet_offload(ifnet_t interface)
91447636 798{
316670eb
A
799 return ((interface == NULL) ?
800 0 : (interface->if_hwassist & offload_mask));
91447636
A
801}
802
316670eb
A
803errno_t
804ifnet_set_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t mtuLen)
b0d623f7
A
805{
806 errno_t error = 0;
807
316670eb
A
808 if (interface == NULL || mtuLen < interface->if_mtu)
809 return (EINVAL);
b0d623f7
A
810
811 switch (family) {
316670eb
A
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;
b0d623f7 818
316670eb
A
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;
b0d623f7 825
316670eb
A
826 default:
827 error = EPROTONOSUPPORT;
828 break;
b0d623f7
A
829 }
830
316670eb 831 return (error);
b0d623f7 832}
316670eb
A
833
834errno_t
835ifnet_get_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t *mtuLen)
b0d623f7
A
836{
837 errno_t error = 0;
838
316670eb
A
839 if (interface == NULL || mtuLen == NULL)
840 return (EINVAL);
841
b0d623f7 842 switch (family) {
316670eb
A
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;
b0d623f7 849
316670eb
A
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;
b0d623f7 856
316670eb
A
857 default:
858 error = EPROTONOSUPPORT;
859 break;
b0d623f7
A
860 }
861
316670eb 862 return (error);
b0d623f7
A
863}
864
6d2010ae 865errno_t
b0d623f7
A
866ifnet_set_wake_flags(ifnet_t interface, u_int32_t properties, u_int32_t mask)
867{
316670eb 868 struct kev_msg ev_msg;
6d2010ae
A
869 struct net_event_data ev_data;
870
316670eb
A
871 bzero(&ev_data, sizeof (struct net_event_data));
872 bzero(&ev_msg, sizeof (struct kev_msg));
873
b0d623f7 874 if (interface == NULL)
316670eb 875 return (EINVAL);
b0d623f7
A
876
877 /* Do not accept wacky values */
878 if ((properties & mask) & ~IF_WAKE_VALID_FLAGS)
316670eb 879 return (EINVAL);
b0d623f7 880
6d2010ae 881 ifnet_lock_exclusive(interface);
b0d623f7 882
316670eb
A
883 interface->if_wake_properties =
884 (properties & mask) | (interface->if_wake_properties & ~mask);
b0d623f7 885
6d2010ae 886 ifnet_lock_done(interface);
b0d623f7
A
887
888 (void) ifnet_touch_lastchange(interface);
889
890 /* Notify application of the change */
316670eb
A
891 ev_msg.vendor_code = KEV_VENDOR_APPLE;
892 ev_msg.kev_class = KEV_NETWORK_CLASS;
893 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
b0d623f7 894
316670eb 895 ev_msg.event_code = KEV_DL_WAKEFLAGS_CHANGED;
b0d623f7 896 strlcpy(&ev_data.if_name[0], interface->if_name, IFNAMSIZ);
316670eb
A
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;
b0d623f7
A
901 ev_msg.dv[1].data_length = 0;
902 kev_post_msg(&ev_msg);
6d2010ae 903
316670eb 904 return (0);
b0d623f7
A
905}
906
907u_int32_t
908ifnet_get_wake_flags(ifnet_t interface)
909{
316670eb 910 return ((interface == NULL) ? 0 : interface->if_wake_properties);
b0d623f7
A
911}
912
91447636
A
913/*
914 * Should MIB data store a copy?
915 */
916errno_t
6d2010ae 917ifnet_set_link_mib_data(ifnet_t interface, void *mibData, u_int32_t mibLen)
91447636 918{
6d2010ae
A
919 if (interface == NULL)
920 return (EINVAL);
921
922 ifnet_lock_exclusive(interface);
91447636
A
923 interface->if_linkmib = (void*)mibData;
924 interface->if_linkmiblen = mibLen;
6d2010ae
A
925 ifnet_lock_done(interface);
926 return (0);
91447636
A
927}
928
929errno_t
6d2010ae 930ifnet_get_link_mib_data(ifnet_t interface, void *mibData, u_int32_t *mibLen)
91447636
A
931{
932 errno_t result = 0;
6d2010ae
A
933
934 if (interface == NULL)
935 return (EINVAL);
936
937 ifnet_lock_shared(interface);
91447636
A
938 if (*mibLen < interface->if_linkmiblen)
939 result = EMSGSIZE;
940 if (result == 0 && interface->if_linkmib == NULL)
941 result = ENOTSUP;
6d2010ae 942
91447636
A
943 if (result == 0) {
944 *mibLen = interface->if_linkmiblen;
945 bcopy(interface->if_linkmib, mibData, *mibLen);
946 }
6d2010ae
A
947 ifnet_lock_done(interface);
948
949 return (result);
91447636
A
950}
951
952u_int32_t
316670eb 953ifnet_get_link_mib_data_length(ifnet_t interface)
91447636 954{
316670eb 955 return ((interface == NULL) ? 0 : interface->if_linkmiblen);
91447636
A
956}
957
91447636 958errno_t
316670eb
A
959ifnet_output(ifnet_t interface, protocol_family_t protocol_family,
960 mbuf_t m, void *route, const struct sockaddr *dest)
91447636
A
961{
962 if (interface == NULL || protocol_family == 0 || m == NULL) {
316670eb 963 if (m != NULL)
91447636 964 mbuf_freem_list(m);
316670eb 965 return (EINVAL);
91447636 966 }
316670eb 967 return (dlil_output(interface, protocol_family, m, route, dest, 0, NULL));
91447636
A
968}
969
970errno_t
316670eb 971ifnet_output_raw(ifnet_t interface, protocol_family_t protocol_family, mbuf_t m)
91447636 972{
2d21ac55 973 if (interface == NULL || m == NULL) {
316670eb 974 if (m != NULL)
91447636 975 mbuf_freem_list(m);
316670eb 976 return (EINVAL);
91447636 977 }
316670eb 978 return (dlil_output(interface, protocol_family, m, NULL, NULL, 1, NULL));
91447636
A
979}
980
91447636 981errno_t
316670eb 982ifnet_set_mtu(ifnet_t interface, u_int32_t mtu)
91447636 983{
316670eb
A
984 if (interface == NULL)
985 return (EINVAL);
986
987 interface->if_mtu = mtu;
988 return (0);
91447636
A
989}
990
991u_int32_t
316670eb 992ifnet_mtu(ifnet_t interface)
91447636 993{
316670eb 994 return ((interface == NULL) ? 0 : interface->if_mtu);
91447636
A
995}
996
997u_char
316670eb 998ifnet_type(ifnet_t interface)
91447636 999{
316670eb 1000 return ((interface == NULL) ? 0 : interface->if_data.ifi_type);
91447636
A
1001}
1002
91447636 1003errno_t
316670eb 1004ifnet_set_addrlen(ifnet_t interface, u_char addrlen)
91447636 1005{
316670eb
A
1006 if (interface == NULL)
1007 return (EINVAL);
1008
1009 interface->if_data.ifi_addrlen = addrlen;
6d2010ae 1010 return (0);
91447636
A
1011}
1012
1013u_char
316670eb 1014ifnet_addrlen(ifnet_t interface)
91447636 1015{
316670eb 1016 return ((interface == NULL) ? 0 : interface->if_data.ifi_addrlen);
91447636 1017}
91447636
A
1018
1019errno_t
316670eb 1020ifnet_set_hdrlen(ifnet_t interface, u_char hdrlen)
91447636 1021{
316670eb
A
1022 if (interface == NULL)
1023 return (EINVAL);
1024
1025 interface->if_data.ifi_hdrlen = hdrlen;
1026 return (0);
91447636
A
1027}
1028
1029u_char
316670eb 1030ifnet_hdrlen(ifnet_t interface)
91447636 1031{
316670eb 1032 return ((interface == NULL) ? 0 : interface->if_data.ifi_hdrlen);
91447636
A
1033}
1034
1035errno_t
316670eb 1036ifnet_set_metric(ifnet_t interface, u_int32_t metric)
91447636 1037{
316670eb
A
1038 if (interface == NULL)
1039 return (EINVAL);
1040
1041 interface->if_data.ifi_metric = metric;
1042 return (0);
91447636
A
1043}
1044
316670eb
A
1045u_int32_t
1046ifnet_metric(ifnet_t interface)
91447636 1047{
316670eb 1048 return ((interface == NULL) ? 0 : interface->if_data.ifi_metric);
91447636
A
1049}
1050
1051errno_t
316670eb 1052ifnet_set_baudrate(struct ifnet *ifp, u_int64_t baudrate)
91447636 1053{
316670eb
A
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);
91447636
A
1064}
1065
316670eb
A
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)
91447636 1075{
316670eb
A
1076 if (ifp == NULL)
1077 return (EINVAL);
1078
39236c6e 1079 /* set input values first (if any), as output values depend on them */
316670eb
A
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
39236c6e
A
1097 VERIFY(ifp != NULL && bw != NULL);
1098
316670eb
A
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;
39236c6e
A
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;
316670eb
A
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)
39236c6e 1122 ifnet_update_sndq(ifq, CLASSQ_EV_LINK_BANDWIDTH);
316670eb
A
1123
1124 if (!locked)
1125 IFCQ_UNLOCK(ifq);
1126
1127 return (0);
91447636
A
1128}
1129
1130errno_t
316670eb 1131ifnet_set_input_bandwidths(struct ifnet *ifp, struct if_bandwidths *bw)
91447636 1132{
316670eb
A
1133 struct if_bandwidths old_bw;
1134
39236c6e
A
1135 VERIFY(ifp != NULL && bw != NULL);
1136
316670eb
A
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)
39236c6e 1149 ifnet_update_rcv(ifp, CLASSQ_EV_LINK_BANDWIDTH);
316670eb
A
1150
1151 return (0);
91447636
A
1152}
1153
1154u_int64_t
316670eb 1155ifnet_output_linkrate(struct ifnet *ifp)
91447636 1156{
316670eb
A
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);
91447636
A
1176}
1177
1178errno_t
316670eb
A
1179ifnet_bandwidths(struct ifnet *ifp, struct if_bandwidths *output_bw,
1180 struct if_bandwidths *input_bw)
91447636 1181{
316670eb 1182 if (ifp == NULL)
6d2010ae 1183 return (EINVAL);
2d21ac55 1184
316670eb
A
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}
91447636 1192
39236c6e
A
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
316670eb
A
1319errno_t
1320ifnet_stat_increment(struct ifnet *ifp,
1321 const struct ifnet_stat_increment_param *s)
1322{
1323 if (ifp == NULL)
1324 return (EINVAL);
91447636 1325
316670eb
A
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);
91447636 1344
91447636 1345 /* Touch the last change time. */
316670eb 1346 TOUCHLASTCHANGE(&ifp->if_lastchange);
91447636 1347
6d2010ae 1348 return (0);
91447636
A
1349}
1350
1351errno_t
316670eb 1352ifnet_stat_increment_in(struct ifnet *ifp, u_int32_t packets_in,
6d2010ae 1353 u_int32_t bytes_in, u_int32_t errors_in)
91447636 1354{
316670eb 1355 if (ifp == NULL)
6d2010ae 1356 return (EINVAL);
91447636 1357
316670eb
A
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);
91447636 1364
316670eb 1365 TOUCHLASTCHANGE(&ifp->if_lastchange);
91447636 1366
6d2010ae 1367 return (0);
91447636
A
1368}
1369
1370errno_t
316670eb 1371ifnet_stat_increment_out(struct ifnet *ifp, u_int32_t packets_out,
6d2010ae 1372 u_int32_t bytes_out, u_int32_t errors_out)
91447636 1373{
316670eb 1374 if (ifp == NULL)
6d2010ae 1375 return (EINVAL);
91447636 1376
316670eb
A
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);
91447636 1383
316670eb 1384 TOUCHLASTCHANGE(&ifp->if_lastchange);
91447636 1385
6d2010ae 1386 return (0);
91447636
A
1387}
1388
1389errno_t
316670eb 1390ifnet_set_stat(struct ifnet *ifp, const struct ifnet_stats_param *s)
91447636 1391{
316670eb 1392 if (ifp == NULL)
6d2010ae 1393 return (EINVAL);
2d21ac55 1394
316670eb
A
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);
2d21ac55 1399
316670eb
A
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);
91447636 1404
316670eb
A
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);
91447636
A
1408
1409 /* Touch the last change time. */
316670eb 1410 TOUCHLASTCHANGE(&ifp->if_lastchange);
91447636 1411
316670eb 1412 return (0);
91447636
A
1413}
1414
1415errno_t
316670eb 1416ifnet_stat(struct ifnet *ifp, struct ifnet_stats_param *s)
91447636 1417{
316670eb 1418 if (ifp == NULL)
6d2010ae 1419 return (EINVAL);
91447636 1420
316670eb
A
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);
91447636 1425
316670eb
A
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);
91447636 1430
316670eb
A
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);
91447636 1434
6d2010ae 1435 return (0);
91447636
A
1436}
1437
1438errno_t
6d2010ae 1439ifnet_touch_lastchange(ifnet_t interface)
91447636 1440{
6d2010ae
A
1441 if (interface == NULL)
1442 return (EINVAL);
2d21ac55 1443
91447636 1444 TOUCHLASTCHANGE(&interface->if_lastchange);
2d21ac55 1445
6d2010ae 1446 return (0);
91447636
A
1447}
1448
1449errno_t
6d2010ae 1450ifnet_lastchange(ifnet_t interface, struct timeval *last_change)
91447636 1451{
6d2010ae
A
1452 if (interface == NULL)
1453 return (EINVAL);
2d21ac55 1454
91447636 1455 *last_change = interface->if_data.ifi_lastchange;
91447636
A
1456 /* Crude conversion from uptime to calendar time */
1457 last_change->tv_sec += boottime_sec();
39236c6e 1458
6d2010ae 1459 return (0);
91447636
A
1460}
1461
1462errno_t
6d2010ae 1463ifnet_get_address_list(ifnet_t interface, ifaddr_t **addresses)
91447636 1464{
6d2010ae
A
1465 return (addresses == NULL ? EINVAL :
1466 ifnet_get_address_list_family(interface, addresses, 0));
91447636
A
1467}
1468
6d2010ae
A
1469struct ifnet_addr_list {
1470 SLIST_ENTRY(ifnet_addr_list) ifal_le;
1471 struct ifaddr *ifal_ifa;
1472};
1473
91447636 1474errno_t
6d2010ae
A
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,
39236c6e 1479 family, 0, M_NOWAIT, 0));
6d2010ae
A
1480}
1481
39236c6e
A
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
6d2010ae
A
1494__private_extern__ errno_t
1495ifnet_get_address_list_family_internal(ifnet_t interface, ifaddr_t **addresses,
39236c6e 1496 sa_family_t family, int detached, int how, int return_inuse_addrs)
91447636 1497{
6d2010ae
A
1498 SLIST_HEAD(, ifnet_addr_list) ifal_head;
1499 struct ifnet_addr_list *ifal, *ifal_tmp;
91447636
A
1500 struct ifnet *ifp;
1501 int count = 0;
6d2010ae 1502 errno_t err = 0;
39236c6e
A
1503 int usecount = 0;
1504 int index = 0;
6d2010ae
A
1505
1506 SLIST_INIT(&ifal_head);
1507
1508 if (addresses == NULL) {
1509 err = EINVAL;
1510 goto done;
1511 }
91447636 1512 *addresses = NULL;
6d2010ae
A
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
91447636 1527 ifnet_head_lock_shared();
6d2010ae
A
1528 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1529 if (interface != NULL && ifp != interface)
1530 continue;
1531one:
91447636 1532 ifnet_lock_shared(ifp);
6d2010ae
A
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;
91447636 1541 }
6d2010ae
A
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);
91447636
A
1557 }
1558 }
91447636 1559 ifnet_lock_done(ifp);
6d2010ae
A
1560 if (detached)
1561 break;
91447636 1562 }
6d2010ae 1563 if (!detached)
91447636 1564 ifnet_head_done();
6d2010ae
A
1565
1566 if (count == 0) {
1567 err = ENXIO;
1568 goto done;
91447636 1569 }
6d2010ae
A
1570 MALLOC(*addresses, ifaddr_t *, sizeof (ifaddr_t) * (count + 1),
1571 M_TEMP, how);
1572 if (*addresses == NULL) {
1573 err = ENOMEM;
1574 goto done;
91447636 1575 }
6d2010ae
A
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);
39236c6e
A
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 {
6d2010ae 1596 IFA_REMREF(ifal->ifal_ifa);
39236c6e 1597 }
6d2010ae
A
1598 FREE(ifal, M_TEMP);
1599 }
1600
39236c6e
A
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 }
6d2010ae 1607 return (err);
91447636
A
1608}
1609
1610void
6d2010ae 1611ifnet_free_address_list(ifaddr_t *addresses)
91447636
A
1612{
1613 int i;
6d2010ae
A
1614
1615 if (addresses == NULL)
1616 return;
1617
91447636 1618 for (i = 0; addresses[i] != NULL; i++)
6d2010ae
A
1619 IFA_REMREF(addresses[i]);
1620
91447636
A
1621 FREE(addresses, M_TEMP);
1622}
1623
6d2010ae
A
1624void *
1625ifnet_lladdr(ifnet_t interface)
91447636 1626{
6d2010ae
A
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
39236c6e
A
1635 * the interface and it never gets deallocated; internal
1636 * code should simply use IF_LLADDR() for performance.
6d2010ae
A
1637 */
1638 ifa = interface->if_lladdr;
1639 IFA_LOCK_SPIN(ifa);
316670eb 1640 lladdr = LLADDR(SDL((void *)ifa->ifa_addr));
6d2010ae
A
1641 IFA_UNLOCK(ifa);
1642
1643 return (lladdr);
91447636
A
1644}
1645
1646errno_t
316670eb
A
1647ifnet_llbroadcast_copy_bytes(ifnet_t interface, void *addr, size_t buffer_len,
1648 size_t *out_len)
91447636 1649{
316670eb
A
1650 if (interface == NULL || addr == NULL || out_len == NULL)
1651 return (EINVAL);
1652
91447636 1653 *out_len = interface->if_broadcast.length;
316670eb
A
1654
1655 if (buffer_len < interface->if_broadcast.length)
1656 return (EMSGSIZE);
1657
91447636 1658 if (interface->if_broadcast.length == 0)
316670eb
A
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);
91447636 1668 }
316670eb
A
1669
1670 return (0);
91447636
A
1671}
1672
39236c6e
A
1673static errno_t
1674ifnet_lladdr_copy_bytes_internal(ifnet_t interface, void *lladdr,
1675 size_t lladdr_len, kauth_cred_t *credp)
91447636 1676{
39236c6e
A
1677 const u_int8_t *bytes;
1678 size_t bytes_len;
6d2010ae 1679 struct ifaddr *ifa;
39236c6e
A
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));
6d2010ae
A
1688
1689 if (interface == NULL || lladdr == NULL)
1690 return (EINVAL);
1691
6d2010ae
A
1692 ifa = interface->if_lladdr;
1693 IFA_LOCK_SPIN(ifa);
39236c6e
A
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) {
6d2010ae 1699 bzero(lladdr, lladdr_len);
39236c6e
A
1700 error = EMSGSIZE;
1701 } else {
1702 bcopy(bytes, lladdr, bytes_len);
91447636 1703 }
6d2010ae 1704
39236c6e
A
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);
91447636
A
1743}
1744
1745static errno_t
6d2010ae
A
1746ifnet_set_lladdr_internal(ifnet_t interface, const void *lladdr,
1747 size_t lladdr_len, u_char new_type, int apply_type)
91447636
A
1748{
1749 struct ifaddr *ifa;
91447636 1750 errno_t error = 0;
6d2010ae
A
1751
1752 if (interface == NULL)
1753 return (EINVAL);
1754
91447636 1755 ifnet_head_lock_shared();
6d2010ae
A
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 }
91447636
A
1763 ifa = ifnet_addrs[interface->if_index - 1];
1764 if (ifa != NULL) {
6d2010ae
A
1765 struct sockaddr_dl *sdl;
1766
1767 IFA_LOCK_SPIN(ifa);
316670eb 1768 sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
91447636
A
1769 if (lladdr_len != 0) {
1770 bcopy(lladdr, LLADDR(sdl), lladdr_len);
6d2010ae 1771 } else {
91447636
A
1772 bzero(LLADDR(sdl), interface->if_addrlen);
1773 }
1774 sdl->sdl_alen = lladdr_len;
6d2010ae 1775
91447636
A
1776 if (apply_type) {
1777 sdl->sdl_type = new_type;
1778 }
6d2010ae
A
1779 IFA_UNLOCK(ifa);
1780 } else {
91447636
A
1781 error = ENXIO;
1782 }
6d2010ae 1783 ifnet_lock_done(interface);
91447636 1784 ifnet_head_done();
6d2010ae 1785
91447636
A
1786 /* Generate a kernel event */
1787 if (error == 0) {
1788 dlil_post_msg(interface, KEV_DL_SUBCLASS,
316670eb 1789 KEV_DL_LINK_ADDRESS_CHANGED, NULL, 0);
91447636 1790 }
6d2010ae
A
1791
1792 return (error);
91447636
A
1793}
1794
1795errno_t
316670eb 1796ifnet_set_lladdr(ifnet_t interface, const void* lladdr, size_t lladdr_len)
91447636 1797{
316670eb 1798 return (ifnet_set_lladdr_internal(interface, lladdr, lladdr_len, 0, 0));
91447636
A
1799}
1800
1801errno_t
316670eb
A
1802ifnet_set_lladdr_and_type(ifnet_t interface, const void* lladdr,
1803 size_t lladdr_len, u_char type)
91447636 1804{
316670eb
A
1805 return (ifnet_set_lladdr_internal(interface, lladdr,
1806 lladdr_len, type, 1));
91447636
A
1807}
1808
1809errno_t
6d2010ae
A
1810ifnet_add_multicast(ifnet_t interface, const struct sockaddr *maddr,
1811 ifmultiaddr_t *ifmap)
91447636 1812{
6d2010ae
A
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));
91447636
A
1821}
1822
1823errno_t
6d2010ae 1824ifnet_remove_multicast(ifmultiaddr_t ifma)
91447636 1825{
6d2010ae
A
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));
91447636
A
1837}
1838
6d2010ae
A
1839errno_t
1840ifnet_get_multicast_list(ifnet_t ifp, ifmultiaddr_t **addresses)
91447636
A
1841{
1842 int count = 0;
1843 int cmax = 0;
1844 struct ifmultiaddr *addr;
6d2010ae
A
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++;
91447636 1852 }
6d2010ae
A
1853
1854 MALLOC(*addresses, ifmultiaddr_t *, sizeof (ifmultiaddr_t) * (cmax + 1),
1855 M_TEMP, M_NOWAIT);
0c530ab8 1856 if (*addresses == NULL) {
6d2010ae
A
1857 ifnet_lock_done(ifp);
1858 return (ENOMEM);
0c530ab8 1859 }
6d2010ae
A
1860
1861 LIST_FOREACH(addr, &ifp->if_multiaddrs, ifma_link) {
91447636
A
1862 if (count + 1 > cmax)
1863 break;
1864 (*addresses)[count] = (ifmultiaddr_t)addr;
1865 ifmaddr_reference((*addresses)[count]);
1866 count++;
1867 }
6d2010ae
A
1868 (*addresses)[cmax] = NULL;
1869 ifnet_lock_done(ifp);
1870
1871 return (0);
91447636
A
1872}
1873
1874void
316670eb 1875ifnet_free_multicast_list(ifmultiaddr_t *addresses)
91447636
A
1876{
1877 int i;
316670eb
A
1878
1879 if (addresses == NULL)
1880 return;
1881
91447636 1882 for (i = 0; addresses[i] != NULL; i++)
91447636 1883 ifmaddr_release(addresses[i]);
316670eb 1884
91447636
A
1885 FREE(addresses, M_TEMP);
1886}
1887
1888errno_t
6d2010ae 1889ifnet_find_by_name(const char *ifname, ifnet_t *ifpp)
91447636
A
1890{
1891 struct ifnet *ifp;
1892 int namelen;
6d2010ae
A
1893
1894 if (ifname == NULL)
1895 return (EINVAL);
1896
91447636 1897 namelen = strlen(ifname);
6d2010ae
A
1898
1899 *ifpp = NULL;
1900
91447636 1901 ifnet_head_lock_shared();
6d2010ae
A
1902 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1903 struct ifaddr *ifa;
13fec989 1904 struct sockaddr_dl *ll_addr;
2d21ac55 1905
6d2010ae
A
1906 ifa = ifnet_addrs[ifp->if_index - 1];
1907 if (ifa == NULL)
13fec989 1908 continue;
2d21ac55 1909
6d2010ae 1910 IFA_LOCK(ifa);
316670eb 1911 ll_addr = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
2d21ac55 1912
316670eb
A
1913 if (namelen == ll_addr->sdl_nlen && strncmp(ll_addr->sdl_data,
1914 ifname, ll_addr->sdl_nlen) == 0) {
6d2010ae
A
1915 IFA_UNLOCK(ifa);
1916 *ifpp = ifp;
1917 ifnet_reference(*ifpp);
91447636
A
1918 break;
1919 }
6d2010ae 1920 IFA_UNLOCK(ifa);
91447636
A
1921 }
1922 ifnet_head_done();
6d2010ae
A
1923
1924 return ((ifp == NULL) ? ENXIO : 0);
91447636
A
1925}
1926
1927errno_t
4a3eedf9
A
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
6d2010ae
A
1939struct ifnet_list {
1940 SLIST_ENTRY(ifnet_list) ifl_le;
1941 struct ifnet *ifl_ifp;
1942};
1943
4a3eedf9
A
1944static errno_t
1945ifnet_list_get_common(ifnet_family_t family, boolean_t get_all, ifnet_t **list,
1946 u_int32_t *count)
91447636 1947{
6d2010ae
A
1948#pragma unused(get_all)
1949 SLIST_HEAD(, ifnet_list) ifl_head;
1950 struct ifnet_list *ifl, *ifl_tmp;
91447636 1951 struct ifnet *ifp;
6d2010ae
A
1952 int cnt = 0;
1953 errno_t err = 0;
4a3eedf9 1954
6d2010ae 1955 SLIST_INIT(&ifl_head);
4a3eedf9 1956
6d2010ae
A
1957 if (list == NULL || count == NULL) {
1958 err = EINVAL;
1959 goto done;
91447636 1960 }
6d2010ae
A
1961 *count = 0;
1962 *list = NULL;
91447636 1963
6d2010ae
A
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;
91447636 1973 }
6d2010ae
A
1974 ifl->ifl_ifp = ifp;
1975 ifnet_reference(ifp);
1976 SLIST_INSERT_HEAD(&ifl_head, ifl, ifl_le);
1977 ++cnt;
91447636 1978 }
91447636
A
1979 }
1980 ifnet_head_done();
4a3eedf9 1981
6d2010ae
A
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);
91447636
A
2007}
2008
2009void
4a3eedf9 2010ifnet_list_free(ifnet_t *interfaces)
91447636
A
2011{
2012 int i;
4a3eedf9
A
2013
2014 if (interfaces == NULL)
2015 return;
2016
6d2010ae 2017 for (i = 0; interfaces[i]; i++)
91447636 2018 ifnet_release(interfaces[i]);
4a3eedf9 2019
91447636
A
2020 FREE(interfaces, M_TEMP);
2021}
2022
316670eb
A
2023void
2024ifnet_transmit_burst_start(ifnet_t ifp, mbuf_t pkt)
2025{
39236c6e 2026#if MEASURE_BW
316670eb
A
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
39236c6e 2039 ifp->if_bw.start_seq = pkt->m_pkthdr.pkt_bwseq;
316670eb 2040 ifp->if_bw.start_ts = mach_absolute_time();
39236c6e
A
2041#else /*!MEASURE_BW */
2042#pragma unused(ifp, pkt)
2043#endif /* !MEASURE_BW */
316670eb
A
2044}
2045
2046void
2047ifnet_transmit_burst_end(ifnet_t ifp, mbuf_t pkt)
2048{
39236c6e 2049#if MEASURE_BW
316670eb
A
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
39236c6e 2071 oseq = pkt->m_pkthdr.pkt_bwseq;
316670eb
A
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);
39236c6e
A
2109#else /* !MEASURE_BW */
2110#pragma unused(ifp, pkt)
2111#endif /* !MEASURE_BW */
316670eb
A
2112}
2113
91447636 2114/****************************************************************************/
316670eb 2115/* ifaddr_t accessors */
91447636
A
2116/****************************************************************************/
2117
2118errno_t
6d2010ae 2119ifaddr_reference(ifaddr_t ifa)
91447636 2120{
6d2010ae
A
2121 if (ifa == NULL)
2122 return (EINVAL);
2123
2124 IFA_ADDREF(ifa);
2125 return (0);
91447636
A
2126}
2127
2128errno_t
6d2010ae 2129ifaddr_release(ifaddr_t ifa)
91447636 2130{
6d2010ae
A
2131 if (ifa == NULL)
2132 return (EINVAL);
2133
2134 IFA_REMREF(ifa);
2135 return (0);
91447636
A
2136}
2137
2138sa_family_t
6d2010ae 2139ifaddr_address_family(ifaddr_t ifa)
91447636 2140{
6d2010ae
A
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);
91447636
A
2150}
2151
2152errno_t
6d2010ae 2153ifaddr_address(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
91447636
A
2154{
2155 u_int32_t copylen;
6d2010ae
A
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;
91447636 2168 bcopy(ifa->ifa_addr, out_addr, copylen);
6d2010ae
A
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);
91447636
A
2177}
2178
2179errno_t
6d2010ae 2180ifaddr_dstaddress(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
91447636
A
2181{
2182 u_int32_t copylen;
6d2010ae
A
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;
91447636
A
2195 bcopy(ifa->ifa_dstaddr, out_addr, copylen);
2196
6d2010ae
A
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);
91447636
A
2204}
2205
2206errno_t
6d2010ae 2207ifaddr_netmask(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size)
91447636
A
2208{
2209 u_int32_t copylen;
6d2010ae
A
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;
91447636 2222 bcopy(ifa->ifa_netmask, out_addr, copylen);
6d2010ae
A
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);
91447636
A
2231}
2232
2233ifnet_t
6d2010ae 2234ifaddr_ifnet(ifaddr_t ifa)
91447636
A
2235{
2236 struct ifnet *ifp;
6d2010ae
A
2237
2238 if (ifa == NULL)
2239 return (NULL);
2240
2241 /* ifa_ifp is set once at creation time; it is never changed */
91447636 2242 ifp = ifa->ifa_ifp;
6d2010ae
A
2243
2244 return (ifp);
91447636
A
2245}
2246
2247ifaddr_t
316670eb 2248ifaddr_withaddr(const struct sockaddr *address)
91447636 2249{
316670eb
A
2250 if (address == NULL)
2251 return (NULL);
2252
2253 return (ifa_ifwithaddr(address));
91447636
A
2254}
2255
2256ifaddr_t
316670eb 2257ifaddr_withdstaddr(const struct sockaddr *address)
91447636 2258{
316670eb
A
2259 if (address == NULL)
2260 return (NULL);
2261
2262 return (ifa_ifwithdstaddr(address));
91447636
A
2263}
2264
2265ifaddr_t
316670eb 2266ifaddr_withnet(const struct sockaddr *net)
91447636 2267{
316670eb
A
2268 if (net == NULL)
2269 return (NULL);
2270
2271 return (ifa_ifwithnet(net));
91447636
A
2272}
2273
2274ifaddr_t
316670eb
A
2275ifaddr_withroute(int flags, const struct sockaddr *destination,
2276 const struct sockaddr *gateway)
91447636 2277{
316670eb
A
2278 if (destination == NULL || gateway == NULL)
2279 return (NULL);
2280
2281 return (ifa_ifwithroute(flags, destination, gateway));
91447636
A
2282}
2283
2284ifaddr_t
316670eb 2285ifaddr_findbestforaddr(const struct sockaddr *addr, ifnet_t interface)
91447636 2286{
316670eb
A
2287 if (addr == NULL || interface == NULL)
2288 return (NULL);
2289
2290 return (ifaof_ifpforaddr(addr, interface));
91447636
A
2291}
2292
2293errno_t
6d2010ae 2294ifmaddr_reference(ifmultiaddr_t ifmaddr)
91447636 2295{
6d2010ae
A
2296 if (ifmaddr == NULL)
2297 return (EINVAL);
2298
2299 IFMA_ADDREF(ifmaddr);
2300 return (0);
91447636
A
2301}
2302
2303errno_t
6d2010ae 2304ifmaddr_release(ifmultiaddr_t ifmaddr)
91447636 2305{
6d2010ae
A
2306 if (ifmaddr == NULL)
2307 return (EINVAL);
2308
2309 IFMA_REMREF(ifmaddr);
2310 return (0);
91447636
A
2311}
2312
2313errno_t
6d2010ae
A
2314ifmaddr_address(ifmultiaddr_t ifma, struct sockaddr *out_addr,
2315 u_int32_t addr_size)
91447636
A
2316{
2317 u_int32_t copylen;
6d2010ae
A
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);
91447636
A
2338}
2339
2340errno_t
6d2010ae
A
2341ifmaddr_lladdress(ifmultiaddr_t ifma, struct sockaddr *out_addr,
2342 u_int32_t addr_size)
91447636 2343{
6d2010ae
A
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));
91447636
A
2352}
2353
2354ifnet_t
6d2010ae 2355ifmaddr_ifnet(ifmultiaddr_t ifma)
91447636 2356{
316670eb 2357 return ((ifma == NULL) ? NULL : ifma->ifma_ifp);
91447636 2358}
d1ecb069
A
2359
2360/******************************************************************************/
2361/* interface cloner */
2362/******************************************************************************/
2363
316670eb
A
2364errno_t
2365ifnet_clone_attach(struct ifnet_clone_params *cloner_params,
2366 if_clone_t *ifcloner)
d1ecb069
A
2367{
2368 errno_t error = 0;
2369 struct if_clone *ifc = NULL;
2370 size_t namelen;
316670eb
A
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) {
d1ecb069
A
2377 error = EINVAL;
2378 goto fail;
2379 }
316670eb 2380
d1ecb069 2381 if (if_clone_lookup(cloner_params->ifc_name, NULL) != NULL) {
316670eb
A
2382 printf("%s: already a cloner for %s\n", __func__,
2383 cloner_params->ifc_name);
d1ecb069
A
2384 error = EEXIST;
2385 goto fail;
2386 }
2387
2388 /* Make room for name string */
316670eb
A
2389 ifc = _MALLOC(sizeof (struct if_clone) + IFNAMSIZ + 1, M_CLONE,
2390 M_WAITOK | M_ZERO);
d1ecb069 2391 if (ifc == NULL) {
316670eb 2392 printf("%s: _MALLOC failed\n", __func__);
d1ecb069
A
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) {
316670eb 2405 printf("%s: if_clone_attach failed %d\n", __func__, error);
d1ecb069
A
2406 goto fail;
2407 }
2408 *ifcloner = ifc;
316670eb
A
2409
2410 return (0);
d1ecb069
A
2411fail:
2412 if (ifc != NULL)
2413 FREE(ifc, M_CLONE);
316670eb 2414 return (error);
d1ecb069
A
2415}
2416
316670eb 2417errno_t
d1ecb069
A
2418ifnet_clone_detach(if_clone_t ifcloner)
2419{
2420 errno_t error = 0;
2421 struct if_clone *ifc = ifcloner;
316670eb 2422
d1ecb069 2423 if (ifc == NULL || ifc->ifc_name == NULL)
316670eb
A
2424 return (EINVAL);
2425
d1ecb069 2426 if ((if_clone_lookup(ifc->ifc_name, NULL)) == NULL) {
316670eb 2427 printf("%s: no cloner for %s\n", __func__, ifc->ifc_name);
d1ecb069
A
2428 error = EINVAL;
2429 goto fail;
2430 }
2431
2432 if_clone_detach(ifc);
316670eb 2433
d1ecb069
A
2434 FREE(ifc, M_CLONE);
2435
d1ecb069 2436fail:
316670eb 2437 return (error);
d1ecb069
A
2438}
2439
316670eb
A
2440/******************************************************************************/
2441/* misc */
2442/******************************************************************************/
d1ecb069 2443
316670eb 2444errno_t
39236c6e
A
2445ifnet_get_local_ports_extended(ifnet_t ifp, protocol_family_t protocol,
2446 u_int32_t wildcardok, u_int8_t *bitfield)
316670eb 2447{
39236c6e
A
2448 u_int32_t ifindex;
2449
316670eb
A
2450 if (bitfield == NULL)
2451 return (EINVAL);
2452
39236c6e
A
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));
316670eb 2464
39236c6e
A
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);
316670eb
A
2469
2470 return (0);
2471}
2472
39236c6e
A
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
316670eb
A
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);
39236c6e 2489
316670eb
A
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);
39236c6e 2503
316670eb
A
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);
39236c6e 2513
316670eb
A
2514 dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_MASTER_ELECTED, NULL, 0);
2515 return (0);
2516}
39236c6e
A
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}