]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/kpi_interface.c
xnu-1504.15.3.tar.gz
[apple/xnu.git] / bsd / net / kpi_interface.c
CommitLineData
91447636 1/*
d1ecb069 2 * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
91447636 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.
8f6c56a5 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.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
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.
8f6c56a5 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>
40#include <net/if_var.h>
41#include <net/if_dl.h>
42#include <net/dlil.h>
43#include <net/if_types.h>
44#include <net/if_dl.h>
45#include <net/if_arp.h>
46#include <libkern/libkern.h>
2d21ac55 47#include <libkern/OSAtomic.h>
91447636
A
48#include <kern/locks.h>
49
b0d623f7
A
50#include "net/net_str_id.h"
51
91447636
A
52#if IF_LASTCHANGEUPTIME
53#define TOUCHLASTCHANGE(__if_lastchange) microuptime(__if_lastchange)
54#else
55#define TOUCHLASTCHANGE(__if_lastchange) microtime(__if_lastchange)
56#endif
57
2d21ac55
A
58extern struct dlil_threading_info *dlil_lo_thread_ptr;
59extern int dlil_multithreaded_input;
91447636 60
4a3eedf9
A
61static errno_t
62ifnet_list_get_common(ifnet_family_t, boolean_t, ifnet_t **, u_int32_t *);
63
91447636
A
64/*
65 Temporary work around until we have real reference counting
66
67 We keep the bits about calling dlil_if_release (which should be
68 called recycle) transparent by calling it from our if_free function
69 pointer. We have to keep the client's original detach function
70 somewhere so we can call it.
71 */
72static void
73ifnet_kpi_free(
74 ifnet_t ifp)
75{
76 ifnet_detached_func detach_func = ifp->if_kpi_storage;
77
78 if (detach_func)
79 detach_func(ifp);
80
81 if (ifp->if_broadcast.length > sizeof(ifp->if_broadcast.u.buffer)) {
82 FREE(ifp->if_broadcast.u.ptr, M_IFADDR);
83 ifp->if_broadcast.u.ptr = NULL;
84 }
85
86 dlil_if_release(ifp);
87}
88
2d21ac55
A
89static __inline__ void*
90_cast_non_const(const void * ptr) {
91 union {
92 const void* cval;
93 void* val;
94 } ret;
95
96 ret.cval = ptr;
97 return (ret.val);
98}
99
91447636
A
100errno_t
101ifnet_allocate(
102 const struct ifnet_init_params *init,
103 ifnet_t *interface)
104{
105 int error;
106 struct ifnet *ifp = NULL;
107
108 if (init->family == 0)
109 return EINVAL;
110 if (init->name == NULL ||
111 init->output == NULL)
112 return EINVAL;
113 if (strlen(init->name) >= IFNAMSIZ)
114 return EINVAL;
115 if ((init->type & 0xFFFFFF00) != 0 || init->type == 0)
116 return EINVAL;
117
118 error = dlil_if_acquire(init->family, init->uniqueid, init->uniqueid_len, &ifp);
119 if (error == 0)
2d21ac55
A
120 {
121 /*
122 * Cast ifp->if_name as non const. dlil_if_acquire sets it up
123 * to point to storage of at least IFNAMSIZ bytes. It is safe
124 * to write to this.
125 */
126 strncpy(_cast_non_const(ifp->if_name), init->name, IFNAMSIZ);
91447636
A
127 ifp->if_type = init->type;
128 ifp->if_family = init->family;
129 ifp->if_unit = init->unit;
130 ifp->if_output = init->output;
131 ifp->if_demux = init->demux;
2d21ac55 132 ifp->if_add_proto = init->add_proto;
91447636
A
133 ifp->if_del_proto = init->del_proto;
134 ifp->if_check_multi = init->check_multi;
135 ifp->if_framer = init->framer;
136 ifp->if_softc = init->softc;
137 ifp->if_ioctl = init->ioctl;
138 ifp->if_set_bpf_tap = init->set_bpf_tap;
139 ifp->if_free = ifnet_kpi_free;
140 ifp->if_event = init->event;
141 ifp->if_kpi_storage = init->detach;
142 ifp->if_eflags |= IFEF_USEKPI;
143
144 if (init->broadcast_len && init->broadcast_addr) {
145 if (init->broadcast_len > sizeof(ifp->if_broadcast.u.buffer)) {
146 MALLOC(ifp->if_broadcast.u.ptr, u_char*, init->broadcast_len, M_IFADDR, M_NOWAIT);
147 if (ifp->if_broadcast.u.ptr == NULL) {
148 error = ENOMEM;
149 }
150 else {
151 bcopy(init->broadcast_addr, ifp->if_broadcast.u.ptr, init->broadcast_len);
152 }
153 }
154 else {
155 bcopy(init->broadcast_addr, ifp->if_broadcast.u.buffer, init->broadcast_len);
156 }
157 ifp->if_broadcast.length = init->broadcast_len;
158 }
159 else {
160 bzero(&ifp->if_broadcast, sizeof(ifp->if_broadcast));
161 }
162
163 if (error == 0) {
164 *interface = ifp;
165 ifnet_reference(ifp); // temporary - this should be done in dlil_if_acquire
166 }
167 else {
168 dlil_if_release(ifp);
169 *interface = 0;
170 }
171 }
172
173 /*
174 Note: We should do something here to indicate that we haven't been
175 attached yet. By doing so, we can catch the case in ifnet_release
176 where the reference count reaches zero and call the recycle
177 function. If the interface is attached, the interface will be
178 recycled when the interface's if_free function is called. If the
179 interface is never attached, the if_free function will never be
180 called and the interface will never be recycled.
181 */
182
183 return error;
184}
185
186errno_t
187ifnet_reference(
2d21ac55 188 ifnet_t ifp)
91447636 189{
2d21ac55
A
190 int oldval;
191
192 if (ifp == NULL) return EINVAL;
193
b0d623f7 194 oldval = OSIncrementAtomic(&ifp->if_refcnt);
2d21ac55 195
91447636
A
196 return 0;
197}
198
199errno_t
200ifnet_release(
2d21ac55 201 ifnet_t ifp)
91447636 202{
2d21ac55 203 int oldval;
91447636 204
2d21ac55 205 if (ifp == NULL) return EINVAL;
91447636 206
b0d623f7 207 oldval = OSDecrementAtomic(&ifp->if_refcnt);
2d21ac55
A
208 if (oldval == 0)
209 panic("ifnet_release - refcount decremented past zero!");
91447636 210
2d21ac55 211 return 0;
91447636
A
212}
213
b0d623f7
A
214errno_t
215ifnet_interface_family_find(const char *module_string, ifnet_family_t *family_id)
216{
217 if (module_string == NULL || family_id == NULL)
218 return EINVAL;
219 return net_str_id_find_internal(module_string, family_id, NSI_IF_FAM_ID, 1);
220
221}
222
91447636
A
223void*
224ifnet_softc(
225 ifnet_t interface)
226{
227 return interface == NULL ? NULL : interface->if_softc;
228}
229
230const char*
231ifnet_name(
232 ifnet_t interface)
233{
234 return interface == NULL ? NULL : interface->if_name;
235}
236
237ifnet_family_t
238ifnet_family(
239 ifnet_t interface)
240{
241 return interface == NULL ? 0 : interface->if_family;
242}
243
244u_int32_t
245ifnet_unit(
246 ifnet_t interface)
247{
248 return interface == NULL ? (u_int32_t)0xffffffff : (u_int32_t)interface->if_unit;
249}
250
251u_int32_t
252ifnet_index(
253 ifnet_t interface)
254{
255 return interface == NULL ? (u_int32_t)0xffffffff : interface->if_index;
256}
257
258errno_t
259ifnet_set_flags(
260 ifnet_t interface,
261 u_int16_t new_flags,
262 u_int16_t mask)
263{
264 int lock;
265
266 if (interface == NULL) return EINVAL;
267 lock = (interface->if_lock != 0);
268
269 if (lock) ifnet_lock_exclusive(interface);
270
271 /* If we are modifying the up/down state, call if_updown */
272 if (lock && (mask & IFF_UP) != 0) {
273 if_updown(interface, (new_flags & IFF_UP) == IFF_UP);
274 }
275
276 interface->if_flags = (new_flags & mask) | (interface->if_flags & ~mask);
277 if (lock) ifnet_lock_done(interface);
278
279 return 0;
280}
281
282u_int16_t
283ifnet_flags(
284 ifnet_t interface)
285{
286 return interface == NULL ? 0 : interface->if_flags;
287}
288
289errno_t
290ifnet_set_eflags(
291 ifnet_t interface,
292 u_int32_t new_flags,
293 u_int32_t mask)
294{
295 int lock;
296
297 if (interface == NULL) return EINVAL;
298 lock = (interface->if_lock != 0);
299
300 if (lock) ifnet_lock_exclusive(interface);
301 interface->if_eflags = (new_flags & mask) | (interface->if_eflags & ~mask);
302 if (lock) ifnet_lock_done(interface);
303
304 return 0;
305}
306
307u_int32_t
308ifnet_eflags(
309 ifnet_t interface)
310{
311 return interface == NULL ? 0 : interface->if_eflags;
312}
313
d1ecb069
A
314errno_t
315ifnet_set_idle_flags(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask)
316{
317#if IFNET_ROUTE_REFCNT
318 int lock, before, after;
319
320 if (ifp == NULL)
321 return (EINVAL);
322
323 lck_mtx_lock(rnh_lock);
324
325 lock = (ifp->if_lock != NULL);
326 if (lock)
327 ifnet_lock_exclusive(ifp);
328
329 before = ifp->if_idle_flags;
330 ifp->if_idle_flags = (new_flags & mask) | (ifp->if_idle_flags & ~mask);
331 after = ifp->if_idle_flags;
332
333 if ((after - before) < 0 && ifp->if_idle_flags == 0 &&
334 ifp->if_want_aggressive_drain != 0) {
335 ifp->if_want_aggressive_drain = 0;
336 if (ifnet_aggressive_drainers == 0)
337 panic("%s: ifp=%p negative aggdrain!", __func__, ifp);
338 if (--ifnet_aggressive_drainers == 0)
339 rt_aggdrain(0);
340 } else if ((after - before) > 0 && ifp->if_want_aggressive_drain == 0) {
341 ifp->if_want_aggressive_drain++;
342 if (++ifnet_aggressive_drainers == 0)
343 panic("%s: ifp=%p wraparound aggdrain!", __func__, ifp);
344 else if (ifnet_aggressive_drainers == 1)
345 rt_aggdrain(1);
346 }
347
348 if (lock)
349 ifnet_lock_done(ifp);
350
351 lck_mtx_unlock(rnh_lock);
352
353 return (0);
354#else
355#pragma unused(ifp, new_flags, mask)
356 return (ENOTSUP);
357#endif /* IFNET_ROUTE_REFCNT */
358}
359
360u_int32_t
361ifnet_idle_flags(ifnet_t ifp)
362{
363#if IFNET_ROUTE_REFCNT
364 return ((ifp == NULL) ? 0 : ifp->if_idle_flags);
365#else
366#pragma unused(ifp)
367 return (0);
368#endif /* IFNET_ROUTE_REFCNT */
369}
370
91447636
A
371static const ifnet_offload_t offload_mask = IFNET_CSUM_IP | IFNET_CSUM_TCP |
372 IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT | IFNET_IP_FRAGMENT |
2d21ac55 373 IFNET_CSUM_SUM16 | IFNET_VLAN_TAGGING | IFNET_VLAN_MTU |
b0d623f7 374 IFNET_MULTIPAGES | IFNET_TSO_IPV4 | IFNET_TSO_IPV6;
91447636
A
375
376errno_t
377ifnet_set_offload(
378 ifnet_t interface,
379 ifnet_offload_t offload)
380{
381 int lock;
382
383 if (interface == NULL) return EINVAL;
384 lock = (interface->if_lock != 0);
385
386 if (lock) ifnet_lock_exclusive(interface);
387 interface->if_hwassist = (offload & offload_mask);
388 if (lock) ifnet_lock_done(interface);
389
390 return 0;
391}
392
393ifnet_offload_t
394ifnet_offload(
395 ifnet_t interface)
396{
397 return interface == NULL ? 0 : (interface->if_hwassist & offload_mask);
398}
399
b0d623f7
A
400errno_t
401ifnet_set_tso_mtu(
402 ifnet_t interface,
403 sa_family_t family,
404 u_int32_t mtuLen)
405{
406 errno_t error = 0;
407
408 if (interface == NULL) return EINVAL;
409
410 if (mtuLen < interface->if_mtu)
411 return EINVAL;
412
413
414 switch (family) {
415
416 case AF_INET:
417 if (interface->if_hwassist & IFNET_TSO_IPV4)
418 interface->if_tso_v4_mtu = mtuLen;
419 else
420 error = EINVAL;
421 break;
422
423 case AF_INET6:
424 if (interface->if_hwassist & IFNET_TSO_IPV6)
425 interface->if_tso_v6_mtu = mtuLen;
426 else
427 error = EINVAL;
428 break;
429
430 default:
431 error = EPROTONOSUPPORT;
432 }
433
434 return error;
435}
436
437errno_t
438ifnet_get_tso_mtu(
439 ifnet_t interface,
440 sa_family_t family,
441 u_int32_t *mtuLen)
442{
443 errno_t error = 0;
444
445 if (interface == NULL || mtuLen == NULL) return EINVAL;
446
447 switch (family) {
448
449 case AF_INET:
450 if (interface->if_hwassist & IFNET_TSO_IPV4)
451 *mtuLen = interface->if_tso_v4_mtu;
452 else
453 error = EINVAL;
454 break;
455
456 case AF_INET6:
457 if (interface->if_hwassist & IFNET_TSO_IPV6)
458 *mtuLen = interface->if_tso_v6_mtu;
459 else
460 error = EINVAL;
461 break;
462 default:
463 error = EPROTONOSUPPORT;
464 }
465
466 return error;
467}
468
469errno_t
470ifnet_set_wake_flags(ifnet_t interface, u_int32_t properties, u_int32_t mask)
471{
472 int lock;
473 struct kev_msg ev_msg;
474 struct net_event_data ev_data;
475
476 if (interface == NULL)
477 return EINVAL;
478
479 /* Do not accept wacky values */
480 if ((properties & mask) & ~IF_WAKE_VALID_FLAGS)
481 return EINVAL;
482
483 lock = (interface->if_lock != 0);
484
485 if (lock)
486 ifnet_lock_exclusive(interface);
487
488 interface->if_wake_properties = (properties & mask) | (interface->if_wake_properties & ~mask);
489
490 if (lock)
491 ifnet_lock_done(interface);
492
493 (void) ifnet_touch_lastchange(interface);
494
495 /* Notify application of the change */
496 ev_msg.vendor_code = KEV_VENDOR_APPLE;
497 ev_msg.kev_class = KEV_NETWORK_CLASS;
498 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
499
500 ev_msg.event_code = KEV_DL_WAKEFLAGS_CHANGED;
501 strlcpy(&ev_data.if_name[0], interface->if_name, IFNAMSIZ);
502 ev_data.if_family = interface->if_family;
503 ev_data.if_unit = (u_int32_t) interface->if_unit;
504 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
505 ev_msg.dv[0].data_ptr = &ev_data;
506 ev_msg.dv[1].data_length = 0;
507 kev_post_msg(&ev_msg);
508
509 return 0;
510}
511
512u_int32_t
513ifnet_get_wake_flags(ifnet_t interface)
514{
515 return interface == NULL ? 0 : interface->if_wake_properties;
516}
517
518
519
520
91447636
A
521/*
522 * Should MIB data store a copy?
523 */
524errno_t
525ifnet_set_link_mib_data(
526 ifnet_t interface,
527 void* mibData,
528 u_int32_t mibLen)
529{
530 int lock;
531
532 if (interface == NULL) return EINVAL;
533 lock = (interface->if_lock != 0);
534
535 if (lock) ifnet_lock_exclusive(interface);
536 interface->if_linkmib = (void*)mibData;
537 interface->if_linkmiblen = mibLen;
538 if (lock) ifnet_lock_done(interface);
539 return 0;
540}
541
542errno_t
543ifnet_get_link_mib_data(
544 ifnet_t interface,
545 void *mibData,
546 u_int32_t *mibLen)
547{
548 errno_t result = 0;
549 int lock;
550
551 if (interface == NULL) return EINVAL;
552 lock = (interface->if_lock != NULL);
553
554 if (lock) ifnet_lock_shared(interface);
555 if (*mibLen < interface->if_linkmiblen)
556 result = EMSGSIZE;
557 if (result == 0 && interface->if_linkmib == NULL)
558 result = ENOTSUP;
559
560 if (result == 0) {
561 *mibLen = interface->if_linkmiblen;
562 bcopy(interface->if_linkmib, mibData, *mibLen);
563 }
564 if (lock) ifnet_lock_done(interface);
565
566 return result;
567}
568
569u_int32_t
570ifnet_get_link_mib_data_length(
571 ifnet_t interface)
572{
573 return interface == NULL ? 0 : interface->if_linkmiblen;
574}
575
91447636
A
576errno_t
577ifnet_output(
578 ifnet_t interface,
579 protocol_family_t protocol_family,
580 mbuf_t m,
581 void *route,
582 const struct sockaddr *dest)
583{
584 if (interface == NULL || protocol_family == 0 || m == NULL) {
585 if (m)
586 mbuf_freem_list(m);
587 return EINVAL;
588 }
589 return dlil_output(interface, protocol_family, m, route, dest, 0);
590}
591
592errno_t
593ifnet_output_raw(
594 ifnet_t interface,
595 protocol_family_t protocol_family,
596 mbuf_t m)
597{
2d21ac55 598 if (interface == NULL || m == NULL) {
91447636
A
599 if (m)
600 mbuf_freem_list(m);
601 return EINVAL;
602 }
603 return dlil_output(interface, protocol_family, m, NULL, NULL, 1);
604}
605
91447636
A
606errno_t
607ifnet_set_mtu(
608 ifnet_t interface,
609 u_int32_t mtu)
610{
611 if (interface == NULL) return EINVAL;
612 interface->if_data.ifi_mtu = mtu;
613 return 0;
614}
615
616u_int32_t
617ifnet_mtu(
618 ifnet_t interface)
619{
620 u_int32_t retval;
621 retval = interface == NULL ? 0 : interface->if_data.ifi_mtu;
622 return retval;
623}
624
625u_char
626ifnet_type(
627 ifnet_t interface)
628{
629 u_char retval;
630
631 retval = interface == NULL ? 0 : interface->if_data.ifi_type;
632 return retval;
633}
634
635#if 0
636errno_t
637ifnet_set_typelen(
638 ifnet_t interface,
639 u_char typelen)
640{
641 int lock = (interface->if_lock != 0);
642 if (lock) ifnet_lock_exclusive(interface);
643 interface->if_data.ifi_typelen = typelen;
644 if (lock) ifnet_lock_done(interface);
645 return 0;
646}
647
648u_char
649ifnet_typelen(
650 ifnet_t interface)
651{
652 u_char retval;
653 retval = interface == NULL ? 0 : interface->if_data.ifi_typelen;
654 return retval;
655}
656#endif
657
658errno_t
659ifnet_set_addrlen(
660 ifnet_t interface,
661 u_char addrlen)
662{
663 if (interface == NULL) return EINVAL;
664 interface->if_data.ifi_addrlen = addrlen;
665 return 0;
666}
667
668u_char
669ifnet_addrlen(
670 ifnet_t interface)
671{
672 u_char retval;
673 retval = interface == NULL ? 0 : interface->if_data.ifi_addrlen;
674 return retval;
675}
676
677errno_t
678ifnet_set_hdrlen(
679 ifnet_t interface,
680 u_char hdrlen)
681{
682 if (interface == NULL) return EINVAL;
683 interface->if_data.ifi_hdrlen = hdrlen;
684 return 0;
685}
686
687u_char
688ifnet_hdrlen(
689 ifnet_t interface)
690{
691 u_char retval;
692 retval = interface == NULL ? 0 : interface->if_data.ifi_hdrlen;
693 return retval;
694}
695
696errno_t
697ifnet_set_metric(
698 ifnet_t interface,
699 u_int32_t metric)
700{
701 if (interface == NULL) return EINVAL;
702 interface->if_data.ifi_metric = metric;
703 return 0;
704}
705
706u_int32_t
707ifnet_metric(
708 ifnet_t interface)
709{
710 u_int32_t retval;
711 retval = interface == NULL ? 0 : interface->if_data.ifi_metric;
712 return retval;
713}
714
715errno_t
716ifnet_set_baudrate(
717 ifnet_t interface,
718 u_int64_t baudrate)
719{
720 if (interface == NULL) return EINVAL;
721 /* Pin baudrate to 32 bits until we can change the storage size */
722 interface->if_data.ifi_baudrate = baudrate > 0xFFFFFFFF ? 0xFFFFFFFF : baudrate;
723 return 0;
724}
725
726u_int64_t
727ifnet_baudrate(
728 ifnet_t interface)
729{
730 u_int64_t retval;
731 retval = interface == NULL ? 0 : interface->if_data.ifi_baudrate;
732 return retval;
733}
734
735errno_t
736ifnet_stat_increment(
737 ifnet_t interface,
738 const struct ifnet_stat_increment_param *counts)
739{
2d21ac55 740 struct dlil_threading_info *thread;
91447636 741 if (interface == NULL) return EINVAL;
2d21ac55
A
742
743 if ((thread = interface->if_input_thread) == NULL || (dlil_multithreaded_input == 0))
744 thread = dlil_lo_thread_ptr;
745
746 lck_mtx_lock(thread->input_lck);
91447636
A
747
748 interface->if_data.ifi_ipackets += counts->packets_in;
749 interface->if_data.ifi_ibytes += counts->bytes_in;
750 interface->if_data.ifi_ierrors += counts->errors_in;
751
752 interface->if_data.ifi_opackets += counts->packets_out;
753 interface->if_data.ifi_obytes += counts->bytes_out;
754 interface->if_data.ifi_oerrors += counts->errors_out;
755
756 interface->if_data.ifi_collisions += counts->collisions;
757 interface->if_data.ifi_iqdrops += counts->dropped;
758
759 /* Touch the last change time. */
760 TOUCHLASTCHANGE(&interface->if_lastchange);
761
2d21ac55 762 lck_mtx_unlock(thread->input_lck);
91447636
A
763
764 return 0;
765}
766
767errno_t
768ifnet_stat_increment_in(
769 ifnet_t interface,
770 u_int32_t packets_in,
771 u_int32_t bytes_in,
772 u_int32_t errors_in)
773{
2d21ac55
A
774 struct dlil_threading_info *thread;
775
91447636
A
776 if (interface == NULL) return EINVAL;
777
2d21ac55
A
778 if ((thread = interface->if_input_thread) == NULL || (dlil_multithreaded_input == 0))
779 thread = dlil_lo_thread_ptr;
780
781 lck_mtx_lock(thread->input_lck);
91447636
A
782
783 interface->if_data.ifi_ipackets += packets_in;
784 interface->if_data.ifi_ibytes += bytes_in;
785 interface->if_data.ifi_ierrors += errors_in;
786
787 TOUCHLASTCHANGE(&interface->if_lastchange);
788
2d21ac55 789 lck_mtx_unlock(thread->input_lck);
91447636
A
790
791 return 0;
792}
793
794errno_t
795ifnet_stat_increment_out(
796 ifnet_t interface,
797 u_int32_t packets_out,
798 u_int32_t bytes_out,
799 u_int32_t errors_out)
800{
2d21ac55 801 struct dlil_threading_info *thread;
91447636
A
802 if (interface == NULL) return EINVAL;
803
2d21ac55
A
804 if ((thread = interface->if_input_thread) == NULL || (dlil_multithreaded_input == 0))
805 thread = dlil_lo_thread_ptr;
806
807 lck_mtx_lock(thread->input_lck);
91447636
A
808
809 interface->if_data.ifi_opackets += packets_out;
810 interface->if_data.ifi_obytes += bytes_out;
811 interface->if_data.ifi_oerrors += errors_out;
812
813 TOUCHLASTCHANGE(&interface->if_lastchange);
814
2d21ac55 815 lck_mtx_unlock(thread->input_lck);
91447636
A
816
817 return 0;
818}
819
820errno_t
821ifnet_set_stat(
822 ifnet_t interface,
823 const struct ifnet_stats_param *stats)
824{
2d21ac55
A
825 struct dlil_threading_info *thread;
826
91447636
A
827 if (interface == NULL) return EINVAL;
828
2d21ac55
A
829 if ((thread = interface->if_input_thread) == NULL || (dlil_multithreaded_input == 0))
830 thread = dlil_lo_thread_ptr;
831
832 lck_mtx_lock(thread->input_lck);
91447636
A
833
834 interface->if_data.ifi_ipackets = stats->packets_in;
835 interface->if_data.ifi_ibytes = stats->bytes_in;
836 interface->if_data.ifi_imcasts = stats->multicasts_in;
837 interface->if_data.ifi_ierrors = stats->errors_in;
838
839 interface->if_data.ifi_opackets = stats->packets_out;
840 interface->if_data.ifi_obytes = stats->bytes_out;
841 interface->if_data.ifi_omcasts = stats->multicasts_out;
842 interface->if_data.ifi_oerrors = stats->errors_out;
843
844 interface->if_data.ifi_collisions = stats->collisions;
845 interface->if_data.ifi_iqdrops = stats->dropped;
846 interface->if_data.ifi_noproto = stats->no_protocol;
847
848 /* Touch the last change time. */
849 TOUCHLASTCHANGE(&interface->if_lastchange);
850
2d21ac55 851 lck_mtx_unlock(thread->input_lck);
91447636
A
852
853 return 0;
854}
855
856errno_t
857ifnet_stat(
858 ifnet_t interface,
859 struct ifnet_stats_param *stats)
860{
2d21ac55
A
861 struct dlil_threading_info *thread;
862
91447636
A
863 if (interface == NULL) return EINVAL;
864
2d21ac55
A
865 if ((thread = interface->if_input_thread) == NULL || (dlil_multithreaded_input == 0))
866 thread = dlil_lo_thread_ptr;
867
868 lck_mtx_lock(thread->input_lck);
91447636
A
869
870 stats->packets_in = interface->if_data.ifi_ipackets;
871 stats->bytes_in = interface->if_data.ifi_ibytes;
872 stats->multicasts_in = interface->if_data.ifi_imcasts;
873 stats->errors_in = interface->if_data.ifi_ierrors;
874
875 stats->packets_out = interface->if_data.ifi_opackets;
876 stats->bytes_out = interface->if_data.ifi_obytes;
877 stats->multicasts_out = interface->if_data.ifi_omcasts;
878 stats->errors_out = interface->if_data.ifi_oerrors;
879
880 stats->collisions = interface->if_data.ifi_collisions;
881 stats->dropped = interface->if_data.ifi_iqdrops;
882 stats->no_protocol = interface->if_data.ifi_noproto;
883
2d21ac55 884 lck_mtx_unlock(thread->input_lck);
91447636
A
885
886 return 0;
887}
888
889errno_t
890ifnet_touch_lastchange(
891 ifnet_t interface)
892{
2d21ac55
A
893 struct dlil_threading_info *thread;
894
91447636
A
895 if (interface == NULL) return EINVAL;
896
2d21ac55
A
897 if ((thread = interface->if_input_thread) == NULL || (dlil_multithreaded_input == 0))
898 thread = dlil_lo_thread_ptr;
899
900 lck_mtx_lock(thread->input_lck);
901
91447636 902 TOUCHLASTCHANGE(&interface->if_lastchange);
2d21ac55
A
903
904 lck_mtx_unlock(thread->input_lck);
91447636
A
905
906 return 0;
907}
908
909errno_t
910ifnet_lastchange(
911 ifnet_t interface,
912 struct timeval *last_change)
913{
2d21ac55
A
914 struct dlil_threading_info *thread;
915
91447636
A
916 if (interface == NULL) return EINVAL;
917
2d21ac55
A
918 if ((thread = interface->if_input_thread) == NULL || (dlil_multithreaded_input == 0))
919 thread = dlil_lo_thread_ptr;
920
921 lck_mtx_lock(thread->input_lck);
922
91447636 923 *last_change = interface->if_data.ifi_lastchange;
2d21ac55
A
924
925 lck_mtx_unlock(thread->input_lck);
91447636
A
926
927#if IF_LASTCHANGEUPTIME
928 /* Crude conversion from uptime to calendar time */
929 last_change->tv_sec += boottime_sec();
930#endif
931
932 return 0;
933}
934
935errno_t
936ifnet_get_address_list(
937 ifnet_t interface,
938 ifaddr_t **addresses)
939{
2d21ac55 940 if (addresses == NULL) return EINVAL;
91447636
A
941 return ifnet_get_address_list_family(interface, addresses, 0);
942}
943
944errno_t
945ifnet_get_address_list_family(
946 ifnet_t interface,
947 ifaddr_t **addresses,
948 sa_family_t family)
949{
950 struct ifnet *ifp;
951 int count = 0;
952 int cmax = 0;
953
2d21ac55 954 if (addresses == NULL) return EINVAL;
91447636
A
955 *addresses = NULL;
956
957 ifnet_head_lock_shared();
958 TAILQ_FOREACH(ifp, &ifnet, if_link)
959 {
960 if (interface && ifp != interface) continue;
961
962 ifnet_lock_shared(ifp);
963 if ((ifp->if_eflags & IFEF_DETACHING) == 0) {
964 if (interface == NULL || interface == ifp)
965 {
966 struct ifaddr *addr;
967 TAILQ_FOREACH(addr, &ifp->if_addrhead, ifa_link)
968 {
969 if (family == 0 || addr->ifa_addr->sa_family == family)
970 cmax++;
971 }
972 }
973 }
974 else if (interface != NULL) {
975 ifnet_lock_done(ifp);
976 ifnet_head_done();
977 return ENXIO;
978 }
979 ifnet_lock_done(ifp);
980 }
981
982 MALLOC(*addresses, ifaddr_t*, sizeof(ifaddr_t) * (cmax + 1), M_TEMP, M_NOWAIT);
983 if (*addresses == NULL) {
984 ifnet_head_done();
985 return ENOMEM;
986 }
987
988 TAILQ_FOREACH(ifp, &ifnet, if_link)
989 {
990 if (interface && ifp != interface) continue;
991
992 ifnet_lock_shared(ifp);
993 if ((ifp->if_eflags & IFEF_DETACHING) == 0) {
994 if (interface == NULL || (struct ifnet*)interface == ifp)
995 {
996 struct ifaddr *addr;
997 TAILQ_FOREACH(addr, &ifp->if_addrhead, ifa_link)
998 {
999 if (count + 1 > cmax) break;
1000 if (family == 0 || addr->ifa_addr->sa_family == family) {
1001 (*addresses)[count] = (ifaddr_t)addr;
1002 ifaddr_reference((*addresses)[count]);
1003 count++;
1004 }
1005 }
1006 }
1007 }
1008 ifnet_lock_done(ifp);
1009 if (interface || count == cmax)
1010 break;
1011 }
1012 ifnet_head_done();
1013 (*addresses)[cmax] = 0;
1014
1015 return 0;
1016}
1017
1018void
1019ifnet_free_address_list(
1020 ifaddr_t *addresses)
1021{
1022 int i;
1023
1024 if (addresses == NULL) return;
1025
1026 for (i = 0; addresses[i] != NULL; i++)
1027 {
1028 ifaddr_release(addresses[i]);
1029 }
1030
1031 FREE(addresses, M_TEMP);
1032}
1033
1034void*
1035ifnet_lladdr(
1036 ifnet_t interface)
1037{
1038 if (interface == NULL) return NULL;
1039 return LLADDR(SDL(interface->if_addrhead.tqh_first->ifa_addr));
1040}
1041
1042errno_t
1043ifnet_llbroadcast_copy_bytes(
1044 ifnet_t interface,
1045 void *addr,
1046 size_t buffer_len,
1047 size_t *out_len)
1048{
1049 if (interface == NULL || addr == NULL || out_len == NULL) return EINVAL;
1050
1051 *out_len = interface->if_broadcast.length;
1052
1053 if (buffer_len < interface->if_broadcast.length) {
1054 return EMSGSIZE;
1055 }
1056
1057 if (interface->if_broadcast.length == 0)
1058 return ENXIO;
1059
1060 if (interface->if_broadcast.length <= sizeof(interface->if_broadcast.u.buffer)) {
1061 bcopy(interface->if_broadcast.u.buffer, addr, interface->if_broadcast.length);
1062 }
1063 else {
1064 bcopy(interface->if_broadcast.u.ptr, addr, interface->if_broadcast.length);
1065 }
1066
1067 return 0;
1068}
1069
1070errno_t
1071ifnet_lladdr_copy_bytes(
1072 ifnet_t interface,
1073 void* lladdr,
1074 size_t lladdr_len)
1075{
1076 struct sockaddr_dl *sdl;
1077 if (interface == NULL || lladdr == NULL) return EINVAL;
1078
1079 sdl = SDL(interface->if_addrhead.tqh_first->ifa_addr);
1080
1081 while (1) {
1082 if (lladdr_len != sdl->sdl_alen) {
1083 bzero(lladdr, lladdr_len);
1084 return EMSGSIZE;
1085 }
1086 bcopy(LLADDR(sdl), lladdr, lladdr_len);
1087 if (bcmp(lladdr, LLADDR(sdl), lladdr_len) == 0 &&
1088 lladdr_len == sdl->sdl_alen)
1089 break;
1090 }
1091 return 0;
1092}
1093
1094static errno_t
1095ifnet_set_lladdr_internal(
1096 ifnet_t interface,
1097 const void *lladdr,
1098 size_t lladdr_len,
1099 u_char new_type,
1100 int apply_type)
1101{
1102 struct ifaddr *ifa;
1103 struct sockaddr_dl *sdl;
1104 errno_t error = 0;
1105
1106 if (interface == NULL) return EINVAL;
1107
1108 if (lladdr_len != 0 && (lladdr_len != interface->if_addrlen || lladdr == 0))
1109 return EINVAL;
1110
1111 ifnet_head_lock_shared();
1112 ifa = ifnet_addrs[interface->if_index - 1];
1113 if (ifa != NULL) {
1114 sdl = (struct sockaddr_dl*)ifa->ifa_addr;
1115 if (lladdr_len != 0) {
1116 bcopy(lladdr, LLADDR(sdl), lladdr_len);
1117 }
1118 else {
1119 bzero(LLADDR(sdl), interface->if_addrlen);
1120 }
1121 sdl->sdl_alen = lladdr_len;
1122
1123 if (apply_type) {
1124 sdl->sdl_type = new_type;
1125 }
1126 }
1127 else {
1128 error = ENXIO;
1129 }
1130 ifnet_head_done();
1131
1132 /* Generate a kernel event */
1133 if (error == 0) {
1134 dlil_post_msg(interface, KEV_DL_SUBCLASS,
1135 KEV_DL_LINK_ADDRESS_CHANGED, NULL, 0);
1136 }
1137
1138 return error;
1139}
1140
1141errno_t
1142ifnet_set_lladdr(
1143 ifnet_t interface,
1144 const void* lladdr,
1145 size_t lladdr_len)
1146{
1147 return ifnet_set_lladdr_internal(interface, lladdr, lladdr_len, 0, 0);
1148}
1149
1150errno_t
1151ifnet_set_lladdr_and_type(
1152 ifnet_t interface,
1153 const void* lladdr,
1154 size_t lladdr_len,
1155 u_char type)
1156{
1157 return ifnet_set_lladdr_internal(interface, lladdr, lladdr_len, type, 1);
1158}
1159
1160errno_t
1161ifnet_add_multicast(
1162 ifnet_t interface,
1163 const struct sockaddr *maddr,
1164 ifmultiaddr_t *address)
1165{
1166 if (interface == NULL || maddr == NULL) return EINVAL;
1167 return if_addmulti(interface, maddr, address);
1168}
1169
1170errno_t
1171ifnet_remove_multicast(
1172 ifmultiaddr_t address)
1173{
1174 if (address == NULL) return EINVAL;
1175 return if_delmultiaddr(address, 0);
1176}
1177
1178errno_t ifnet_get_multicast_list(ifnet_t interface, ifmultiaddr_t **addresses)
1179{
1180 int count = 0;
1181 int cmax = 0;
1182 struct ifmultiaddr *addr;
1183 int lock;
1184
1185 if (interface == NULL || addresses == NULL)
1186 return EINVAL;
1187
1188 lock = (interface->if_lock != 0);
1189 if (lock) ifnet_lock_shared(interface);
1190 if ((interface->if_eflags & IFEF_DETACHING) == 0) {
1191 LIST_FOREACH(addr, &interface->if_multiaddrs, ifma_link)
1192 {
1193 cmax++;
1194 }
1195 }
1196 else {
1197 if (lock) ifnet_lock_done(interface);
1198 return ENXIO;
1199 }
1200
1201 MALLOC(*addresses, ifmultiaddr_t*, sizeof(ifmultiaddr_t) * (cmax + 1), M_TEMP, M_NOWAIT);
0c530ab8
A
1202 if (*addresses == NULL) {
1203 if (lock) ifnet_lock_done(interface);
1204 return ENOMEM;
1205 }
91447636
A
1206
1207 LIST_FOREACH(addr, &interface->if_multiaddrs, ifma_link)
1208 {
1209 if (count + 1 > cmax)
1210 break;
1211 (*addresses)[count] = (ifmultiaddr_t)addr;
1212 ifmaddr_reference((*addresses)[count]);
1213 count++;
1214 }
1215 (*addresses)[cmax] = 0;
1216 if (lock) ifnet_lock_done(interface);
1217
1218 return 0;
1219}
1220
1221void
1222ifnet_free_multicast_list(
1223 ifmultiaddr_t *addresses)
1224{
1225 int i;
1226
1227 if (addresses == NULL) return;
1228
1229 for (i = 0; addresses[i] != NULL; i++)
1230 {
1231 ifmaddr_release(addresses[i]);
1232 }
1233
1234 FREE(addresses, M_TEMP);
1235}
1236
1237errno_t
1238ifnet_find_by_name(
1239 const char *ifname,
1240 ifnet_t *interface)
1241{
1242 struct ifnet *ifp;
1243 int namelen;
1244
1245 if (ifname == NULL) return EINVAL;
1246
1247 namelen = strlen(ifname);
1248
1249 *interface = NULL;
1250
1251 ifnet_head_lock_shared();
1252 TAILQ_FOREACH(ifp, &ifnet, if_link)
1253 {
13fec989
A
1254 struct ifaddr *ifa = ifnet_addrs[ifp->if_index - 1];
1255 struct sockaddr_dl *ll_addr;
2d21ac55 1256
13fec989
A
1257 if (!ifa || !ifa->ifa_addr)
1258 continue;
2d21ac55 1259
13fec989 1260 ll_addr = (struct sockaddr_dl *)ifa->ifa_addr;
2d21ac55 1261
91447636
A
1262 if ((ifp->if_eflags & IFEF_DETACHING) == 0 &&
1263 namelen == ll_addr->sdl_nlen &&
1264 (strncmp(ll_addr->sdl_data, ifname, ll_addr->sdl_nlen) == 0))
1265 {
1266 break;
1267 }
1268 }
1269 if (ifp) {
1270 *interface = ifp;
1271 ifnet_reference(*interface);
1272 }
1273 ifnet_head_done();
1274
1275 return (ifp == NULL) ? ENXIO : 0;
1276}
1277
1278errno_t
4a3eedf9
A
1279ifnet_list_get(ifnet_family_t family, ifnet_t **list, u_int32_t *count)
1280{
1281 return (ifnet_list_get_common(family, FALSE, list, count));
1282}
1283
1284__private_extern__ errno_t
1285ifnet_list_get_all(ifnet_family_t family, ifnet_t **list, u_int32_t *count)
1286{
1287 return (ifnet_list_get_common(family, TRUE, list, count));
1288}
1289
1290static errno_t
1291ifnet_list_get_common(ifnet_family_t family, boolean_t get_all, ifnet_t **list,
1292 u_int32_t *count)
91447636
A
1293{
1294 struct ifnet *ifp;
1295 u_int32_t cmax = 0;
1296 *count = 0;
1297 errno_t result = 0;
4a3eedf9
A
1298
1299 if (list == NULL || count == NULL)
1300 return (EINVAL);
1301
91447636 1302 ifnet_head_lock_shared();
4a3eedf9
A
1303 TAILQ_FOREACH(ifp, &ifnet, if_link) {
1304 if ((ifp->if_eflags & IFEF_DETACHING) && !get_all)
1305 continue;
1306 if (family == IFNET_FAMILY_ANY || ifp->if_family == family)
91447636
A
1307 cmax++;
1308 }
4a3eedf9 1309
91447636
A
1310 if (cmax == 0)
1311 result = ENXIO;
4a3eedf9 1312
91447636 1313 if (result == 0) {
4a3eedf9
A
1314 MALLOC(*list, ifnet_t*, sizeof(ifnet_t) * (cmax + 1),
1315 M_TEMP, M_NOWAIT);
91447636
A
1316 if (*list == NULL)
1317 result = ENOMEM;
1318 }
1319
1320 if (result == 0) {
4a3eedf9
A
1321 TAILQ_FOREACH(ifp, &ifnet, if_link) {
1322 if ((ifp->if_eflags & IFEF_DETACHING) && !get_all)
1323 continue;
1324 if (*count + 1 > cmax)
1325 break;
1326 if (family == IFNET_FAMILY_ANY ||
1327 ((ifnet_family_t)ifp->if_family) == family) {
91447636
A
1328 (*list)[*count] = (ifnet_t)ifp;
1329 ifnet_reference((*list)[*count]);
1330 (*count)++;
1331 }
1332 }
1333 (*list)[*count] = NULL;
1334 }
1335 ifnet_head_done();
4a3eedf9
A
1336
1337 return (result);
91447636
A
1338}
1339
1340void
4a3eedf9 1341ifnet_list_free(ifnet_t *interfaces)
91447636
A
1342{
1343 int i;
4a3eedf9
A
1344
1345 if (interfaces == NULL)
1346 return;
1347
1348 for (i = 0; interfaces[i]; i++) {
91447636
A
1349 ifnet_release(interfaces[i]);
1350 }
4a3eedf9 1351
91447636
A
1352 FREE(interfaces, M_TEMP);
1353}
1354
1355/****************************************************************************/
1356/* ifaddr_t accessors */
1357/****************************************************************************/
1358
1359errno_t
1360ifaddr_reference(
1361 ifaddr_t ifa)
1362{
1363 if (ifa == NULL) return EINVAL;
1364 ifaref(ifa);
1365 return 0;
1366}
1367
1368errno_t
1369ifaddr_release(
1370 ifaddr_t ifa)
1371{
1372 if (ifa == NULL) return EINVAL;
1373 ifafree(ifa);
1374 return 0;
1375}
1376
1377sa_family_t
1378ifaddr_address_family(
1379 ifaddr_t ifa)
1380{
1381 if (ifa && ifa->ifa_addr)
1382 return ifa->ifa_addr->sa_family;
1383
1384 return 0;
1385}
1386
1387errno_t
1388ifaddr_address(
1389 ifaddr_t ifa,
1390 struct sockaddr *out_addr,
1391 u_int32_t addr_size)
1392{
1393 u_int32_t copylen;
1394
1395 if (ifa == NULL || out_addr == NULL) return EINVAL;
1396 if (ifa->ifa_addr == NULL) return ENOTSUP;
1397
1398 copylen = (addr_size >= ifa->ifa_addr->sa_len) ? ifa->ifa_addr->sa_len : addr_size;
1399 bcopy(ifa->ifa_addr, out_addr, copylen);
1400
1401 if (ifa->ifa_addr->sa_len > addr_size) return EMSGSIZE;
1402
1403 return 0;
1404}
1405
1406errno_t
1407ifaddr_dstaddress(
1408 ifaddr_t ifa,
1409 struct sockaddr *out_addr,
1410 u_int32_t addr_size)
1411{
1412 u_int32_t copylen;
1413 if (ifa == NULL || out_addr == NULL) return EINVAL;
1414 if (ifa->ifa_dstaddr == NULL) return ENOTSUP;
1415
1416 copylen = (addr_size >= ifa->ifa_dstaddr->sa_len) ? ifa->ifa_dstaddr->sa_len : addr_size;
1417 bcopy(ifa->ifa_dstaddr, out_addr, copylen);
1418
1419 if (ifa->ifa_dstaddr->sa_len > addr_size) return EMSGSIZE;
1420
1421 return 0;
1422}
1423
1424errno_t
1425ifaddr_netmask(
1426 ifaddr_t ifa,
1427 struct sockaddr *out_addr,
1428 u_int32_t addr_size)
1429{
1430 u_int32_t copylen;
1431 if (ifa == NULL || out_addr == NULL) return EINVAL;
1432 if (ifa->ifa_netmask == NULL) return ENOTSUP;
1433
1434 copylen = addr_size >= ifa->ifa_netmask->sa_len ? ifa->ifa_netmask->sa_len : addr_size;
1435 bcopy(ifa->ifa_netmask, out_addr, copylen);
1436
1437 if (ifa->ifa_netmask->sa_len > addr_size) return EMSGSIZE;
1438
1439 return 0;
1440}
1441
1442ifnet_t
1443ifaddr_ifnet(
1444 ifaddr_t ifa)
1445{
1446 struct ifnet *ifp;
1447 if (ifa == NULL) return NULL;
1448 ifp = ifa->ifa_ifp;
1449
1450 return (ifnet_t)ifp;
1451}
1452
1453ifaddr_t
1454ifaddr_withaddr(
1455 const struct sockaddr* address)
1456{
1457 if (address == NULL) return NULL;
1458 return ifa_ifwithaddr(address);
1459}
1460
1461ifaddr_t
1462ifaddr_withdstaddr(
1463 const struct sockaddr* address)
1464{
1465 if (address == NULL) return NULL;
1466 return ifa_ifwithdstaddr(address);
1467}
1468
1469ifaddr_t
1470ifaddr_withnet(
1471 const struct sockaddr* net)
1472{
1473 if (net == NULL) return NULL;
1474 return ifa_ifwithnet(net);
1475}
1476
1477ifaddr_t
1478ifaddr_withroute(
1479 int flags,
1480 const struct sockaddr* destination,
1481 const struct sockaddr* gateway)
1482{
1483 if (destination == NULL || gateway == NULL) return NULL;
1484 return ifa_ifwithroute(flags, destination, gateway);
1485}
1486
1487ifaddr_t
1488ifaddr_findbestforaddr(
1489 const struct sockaddr *addr,
1490 ifnet_t interface)
1491{
1492 if (addr == NULL || interface == NULL) return NULL;
1493 return ifaof_ifpforaddr(addr, interface);
1494}
1495
1496errno_t
1497ifmaddr_reference(
1498 ifmultiaddr_t ifmaddr)
1499{
1500 if (ifmaddr == NULL) return EINVAL;
1501 ifma_reference(ifmaddr);
1502 return 0;
1503}
1504
1505errno_t
1506ifmaddr_release(
1507 ifmultiaddr_t ifmaddr)
1508{
1509 if (ifmaddr == NULL) return EINVAL;
1510 ifma_release(ifmaddr);
1511 return 0;
1512}
1513
1514errno_t
1515ifmaddr_address(
1516 ifmultiaddr_t ifmaddr,
1517 struct sockaddr *out_addr,
1518 u_int32_t addr_size)
1519{
1520 u_int32_t copylen;
1521
1522 if (ifmaddr == NULL || out_addr == NULL) return EINVAL;
1523 if (ifmaddr->ifma_addr == NULL) return ENOTSUP;
1524
1525 copylen = addr_size >= ifmaddr->ifma_addr->sa_len ? ifmaddr->ifma_addr->sa_len : addr_size;
1526 bcopy(ifmaddr->ifma_addr, out_addr, copylen);
1527
1528 if (ifmaddr->ifma_addr->sa_len > addr_size) return EMSGSIZE;
1529
1530 return 0;
1531}
1532
1533errno_t
1534ifmaddr_lladdress(
1535 ifmultiaddr_t ifmaddr,
1536 struct sockaddr *out_addr,
1537 u_int32_t addr_size)
1538{
1539 if (ifmaddr == NULL || out_addr == NULL) return EINVAL;
1540 if (ifmaddr->ifma_ll == NULL) return ENOTSUP;
1541
1542 return ifmaddr_address(ifmaddr->ifma_ll, out_addr, addr_size);
1543}
1544
1545ifnet_t
1546ifmaddr_ifnet(
1547 ifmultiaddr_t ifmaddr)
1548{
1549 if (ifmaddr == NULL || ifmaddr->ifma_ifp == NULL) return NULL;
1550 return ifmaddr->ifma_ifp;
1551}
d1ecb069
A
1552
1553/******************************************************************************/
1554/* interface cloner */
1555/******************************************************************************/
1556
1557errno_t
1558ifnet_clone_attach(struct ifnet_clone_params *cloner_params, if_clone_t *ifcloner)
1559{
1560 errno_t error = 0;
1561 struct if_clone *ifc = NULL;
1562 size_t namelen;
1563
1564 if (cloner_params == NULL || ifcloner == NULL || cloner_params->ifc_name == NULL ||
1565 cloner_params->ifc_create == NULL || cloner_params->ifc_destroy == NULL ||
1566 (namelen = strlen(cloner_params->ifc_name)) >= IFNAMSIZ) {
1567 error = EINVAL;
1568 goto fail;
1569 }
1570
1571 if (if_clone_lookup(cloner_params->ifc_name, NULL) != NULL) {
1572 printf("ifnet_clone_attach: already a cloner for %s\n", cloner_params->ifc_name);
1573 error = EEXIST;
1574 goto fail;
1575 }
1576
1577 /* Make room for name string */
1578 ifc = _MALLOC(sizeof(struct if_clone) + IFNAMSIZ + 1, M_CLONE, M_WAITOK | M_ZERO);
1579 if (ifc == NULL) {
1580 printf("ifnet_clone_attach: _MALLOC failed\n");
1581 error = ENOBUFS;
1582 goto fail;
1583 }
1584 strlcpy((char *)(ifc + 1), cloner_params->ifc_name, IFNAMSIZ + 1);
1585 ifc->ifc_name = (char *)(ifc + 1);
1586 ifc->ifc_namelen = namelen;
1587 ifc->ifc_maxunit = IF_MAXUNIT;
1588 ifc->ifc_create = cloner_params->ifc_create;
1589 ifc->ifc_destroy = cloner_params->ifc_destroy;
1590
1591 error = if_clone_attach(ifc);
1592 if (error != 0) {
1593 printf("ifnet_clone_attach: if_clone_attach failed %d\n", error);
1594 goto fail;
1595 }
1596 *ifcloner = ifc;
1597
1598 return 0;
1599fail:
1600 if (ifc != NULL)
1601 FREE(ifc, M_CLONE);
1602 return error;
1603}
1604
1605errno_t
1606ifnet_clone_detach(if_clone_t ifcloner)
1607{
1608 errno_t error = 0;
1609 struct if_clone *ifc = ifcloner;
1610
1611 if (ifc == NULL || ifc->ifc_name == NULL)
1612 return EINVAL;
1613
1614 if ((if_clone_lookup(ifc->ifc_name, NULL)) == NULL) {
1615 printf("ifnet_clone_attach: no cloner for %s\n", ifc->ifc_name);
1616 error = EINVAL;
1617 goto fail;
1618 }
1619
1620 if_clone_detach(ifc);
1621
1622 FREE(ifc, M_CLONE);
1623
1624 return 0;
1625fail:
1626 return error;
1627}
1628
1629
1630