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