]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/kpi_interface.c
xnu-1504.7.4.tar.gz
[apple/xnu.git] / bsd / net / kpi_interface.c
1 /*
2 * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include "kpi_interface.h"
30
31 #include <sys/queue.h>
32 #include <sys/param.h> /* for definition of NULL */
33 #include <kern/debug.h> /* for panic */
34 #include <sys/errno.h>
35 #include <sys/socket.h>
36 #include <sys/kern_event.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/kpi_mbuf.h>
40 #include <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>
47 #include <libkern/OSAtomic.h>
48 #include <kern/locks.h>
49
50 #include "net/net_str_id.h"
51
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
58 extern struct dlil_threading_info *dlil_lo_thread_ptr;
59 extern int dlil_multithreaded_input;
60
61 static errno_t
62 ifnet_list_get_common(ifnet_family_t, boolean_t, ifnet_t **, u_int32_t *);
63
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 */
72 static void
73 ifnet_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
89 static __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
100 errno_t
101 ifnet_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)
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);
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;
132 ifp->if_add_proto = init->add_proto;
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
186 errno_t
187 ifnet_reference(
188 ifnet_t ifp)
189 {
190 int oldval;
191
192 if (ifp == NULL) return EINVAL;
193
194 oldval = OSIncrementAtomic(&ifp->if_refcnt);
195
196 return 0;
197 }
198
199 errno_t
200 ifnet_release(
201 ifnet_t ifp)
202 {
203 int oldval;
204
205 if (ifp == NULL) return EINVAL;
206
207 oldval = OSDecrementAtomic(&ifp->if_refcnt);
208 if (oldval == 0)
209 panic("ifnet_release - refcount decremented past zero!");
210
211 return 0;
212 }
213
214 errno_t
215 ifnet_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
223 void*
224 ifnet_softc(
225 ifnet_t interface)
226 {
227 return interface == NULL ? NULL : interface->if_softc;
228 }
229
230 const char*
231 ifnet_name(
232 ifnet_t interface)
233 {
234 return interface == NULL ? NULL : interface->if_name;
235 }
236
237 ifnet_family_t
238 ifnet_family(
239 ifnet_t interface)
240 {
241 return interface == NULL ? 0 : interface->if_family;
242 }
243
244 u_int32_t
245 ifnet_unit(
246 ifnet_t interface)
247 {
248 return interface == NULL ? (u_int32_t)0xffffffff : (u_int32_t)interface->if_unit;
249 }
250
251 u_int32_t
252 ifnet_index(
253 ifnet_t interface)
254 {
255 return interface == NULL ? (u_int32_t)0xffffffff : interface->if_index;
256 }
257
258 errno_t
259 ifnet_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
282 u_int16_t
283 ifnet_flags(
284 ifnet_t interface)
285 {
286 return interface == NULL ? 0 : interface->if_flags;
287 }
288
289 errno_t
290 ifnet_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
307 u_int32_t
308 ifnet_eflags(
309 ifnet_t interface)
310 {
311 return interface == NULL ? 0 : interface->if_eflags;
312 }
313
314 errno_t
315 ifnet_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
360 u_int32_t
361 ifnet_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
371 static const ifnet_offload_t offload_mask = IFNET_CSUM_IP | IFNET_CSUM_TCP |
372 IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT | IFNET_IP_FRAGMENT |
373 IFNET_CSUM_SUM16 | IFNET_VLAN_TAGGING | IFNET_VLAN_MTU |
374 IFNET_MULTIPAGES | IFNET_TSO_IPV4 | IFNET_TSO_IPV6;
375
376 errno_t
377 ifnet_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
393 ifnet_offload_t
394 ifnet_offload(
395 ifnet_t interface)
396 {
397 return interface == NULL ? 0 : (interface->if_hwassist & offload_mask);
398 }
399
400 errno_t
401 ifnet_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
437 errno_t
438 ifnet_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
469 errno_t
470 ifnet_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
512 u_int32_t
513 ifnet_get_wake_flags(ifnet_t interface)
514 {
515 return interface == NULL ? 0 : interface->if_wake_properties;
516 }
517
518
519
520
521 /*
522 * Should MIB data store a copy?
523 */
524 errno_t
525 ifnet_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
542 errno_t
543 ifnet_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
569 u_int32_t
570 ifnet_get_link_mib_data_length(
571 ifnet_t interface)
572 {
573 return interface == NULL ? 0 : interface->if_linkmiblen;
574 }
575
576 errno_t
577 ifnet_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
592 errno_t
593 ifnet_output_raw(
594 ifnet_t interface,
595 protocol_family_t protocol_family,
596 mbuf_t m)
597 {
598 if (interface == NULL || m == NULL) {
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
606 errno_t
607 ifnet_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
616 u_int32_t
617 ifnet_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
625 u_char
626 ifnet_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
636 errno_t
637 ifnet_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
648 u_char
649 ifnet_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
658 errno_t
659 ifnet_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
668 u_char
669 ifnet_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
677 errno_t
678 ifnet_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
687 u_char
688 ifnet_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
696 errno_t
697 ifnet_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
706 u_int32_t
707 ifnet_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
715 errno_t
716 ifnet_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
726 u_int64_t
727 ifnet_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
735 errno_t
736 ifnet_stat_increment(
737 ifnet_t interface,
738 const struct ifnet_stat_increment_param *counts)
739 {
740 struct dlil_threading_info *thread;
741 if (interface == NULL) return EINVAL;
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);
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
762 lck_mtx_unlock(thread->input_lck);
763
764 return 0;
765 }
766
767 errno_t
768 ifnet_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 {
774 struct dlil_threading_info *thread;
775
776 if (interface == NULL) return EINVAL;
777
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);
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
789 lck_mtx_unlock(thread->input_lck);
790
791 return 0;
792 }
793
794 errno_t
795 ifnet_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 {
801 struct dlil_threading_info *thread;
802 if (interface == NULL) return EINVAL;
803
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);
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
815 lck_mtx_unlock(thread->input_lck);
816
817 return 0;
818 }
819
820 errno_t
821 ifnet_set_stat(
822 ifnet_t interface,
823 const struct ifnet_stats_param *stats)
824 {
825 struct dlil_threading_info *thread;
826
827 if (interface == NULL) return EINVAL;
828
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);
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
851 lck_mtx_unlock(thread->input_lck);
852
853 return 0;
854 }
855
856 errno_t
857 ifnet_stat(
858 ifnet_t interface,
859 struct ifnet_stats_param *stats)
860 {
861 struct dlil_threading_info *thread;
862
863 if (interface == NULL) return EINVAL;
864
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);
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
884 lck_mtx_unlock(thread->input_lck);
885
886 return 0;
887 }
888
889 errno_t
890 ifnet_touch_lastchange(
891 ifnet_t interface)
892 {
893 struct dlil_threading_info *thread;
894
895 if (interface == NULL) return EINVAL;
896
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
902 TOUCHLASTCHANGE(&interface->if_lastchange);
903
904 lck_mtx_unlock(thread->input_lck);
905
906 return 0;
907 }
908
909 errno_t
910 ifnet_lastchange(
911 ifnet_t interface,
912 struct timeval *last_change)
913 {
914 struct dlil_threading_info *thread;
915
916 if (interface == NULL) return EINVAL;
917
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
923 *last_change = interface->if_data.ifi_lastchange;
924
925 lck_mtx_unlock(thread->input_lck);
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
935 errno_t
936 ifnet_get_address_list(
937 ifnet_t interface,
938 ifaddr_t **addresses)
939 {
940 if (addresses == NULL) return EINVAL;
941 return ifnet_get_address_list_family(interface, addresses, 0);
942 }
943
944 errno_t
945 ifnet_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
954 if (addresses == NULL) return EINVAL;
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
1018 void
1019 ifnet_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
1034 void*
1035 ifnet_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
1042 errno_t
1043 ifnet_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
1070 errno_t
1071 ifnet_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
1094 static errno_t
1095 ifnet_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
1141 errno_t
1142 ifnet_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
1150 errno_t
1151 ifnet_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
1160 errno_t
1161 ifnet_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
1170 errno_t
1171 ifnet_remove_multicast(
1172 ifmultiaddr_t address)
1173 {
1174 if (address == NULL) return EINVAL;
1175 return if_delmultiaddr(address, 0);
1176 }
1177
1178 errno_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);
1202 if (*addresses == NULL) {
1203 if (lock) ifnet_lock_done(interface);
1204 return ENOMEM;
1205 }
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
1221 void
1222 ifnet_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
1237 errno_t
1238 ifnet_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 {
1254 struct ifaddr *ifa = ifnet_addrs[ifp->if_index - 1];
1255 struct sockaddr_dl *ll_addr;
1256
1257 if (!ifa || !ifa->ifa_addr)
1258 continue;
1259
1260 ll_addr = (struct sockaddr_dl *)ifa->ifa_addr;
1261
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
1278 errno_t
1279 ifnet_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
1285 ifnet_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
1290 static errno_t
1291 ifnet_list_get_common(ifnet_family_t family, boolean_t get_all, ifnet_t **list,
1292 u_int32_t *count)
1293 {
1294 struct ifnet *ifp;
1295 u_int32_t cmax = 0;
1296 *count = 0;
1297 errno_t result = 0;
1298
1299 if (list == NULL || count == NULL)
1300 return (EINVAL);
1301
1302 ifnet_head_lock_shared();
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)
1307 cmax++;
1308 }
1309
1310 if (cmax == 0)
1311 result = ENXIO;
1312
1313 if (result == 0) {
1314 MALLOC(*list, ifnet_t*, sizeof(ifnet_t) * (cmax + 1),
1315 M_TEMP, M_NOWAIT);
1316 if (*list == NULL)
1317 result = ENOMEM;
1318 }
1319
1320 if (result == 0) {
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) {
1328 (*list)[*count] = (ifnet_t)ifp;
1329 ifnet_reference((*list)[*count]);
1330 (*count)++;
1331 }
1332 }
1333 (*list)[*count] = NULL;
1334 }
1335 ifnet_head_done();
1336
1337 return (result);
1338 }
1339
1340 void
1341 ifnet_list_free(ifnet_t *interfaces)
1342 {
1343 int i;
1344
1345 if (interfaces == NULL)
1346 return;
1347
1348 for (i = 0; interfaces[i]; i++) {
1349 ifnet_release(interfaces[i]);
1350 }
1351
1352 FREE(interfaces, M_TEMP);
1353 }
1354
1355 /****************************************************************************/
1356 /* ifaddr_t accessors */
1357 /****************************************************************************/
1358
1359 errno_t
1360 ifaddr_reference(
1361 ifaddr_t ifa)
1362 {
1363 if (ifa == NULL) return EINVAL;
1364 ifaref(ifa);
1365 return 0;
1366 }
1367
1368 errno_t
1369 ifaddr_release(
1370 ifaddr_t ifa)
1371 {
1372 if (ifa == NULL) return EINVAL;
1373 ifafree(ifa);
1374 return 0;
1375 }
1376
1377 sa_family_t
1378 ifaddr_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
1387 errno_t
1388 ifaddr_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
1406 errno_t
1407 ifaddr_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
1424 errno_t
1425 ifaddr_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
1442 ifnet_t
1443 ifaddr_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
1453 ifaddr_t
1454 ifaddr_withaddr(
1455 const struct sockaddr* address)
1456 {
1457 if (address == NULL) return NULL;
1458 return ifa_ifwithaddr(address);
1459 }
1460
1461 ifaddr_t
1462 ifaddr_withdstaddr(
1463 const struct sockaddr* address)
1464 {
1465 if (address == NULL) return NULL;
1466 return ifa_ifwithdstaddr(address);
1467 }
1468
1469 ifaddr_t
1470 ifaddr_withnet(
1471 const struct sockaddr* net)
1472 {
1473 if (net == NULL) return NULL;
1474 return ifa_ifwithnet(net);
1475 }
1476
1477 ifaddr_t
1478 ifaddr_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
1487 ifaddr_t
1488 ifaddr_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
1496 errno_t
1497 ifmaddr_reference(
1498 ifmultiaddr_t ifmaddr)
1499 {
1500 if (ifmaddr == NULL) return EINVAL;
1501 ifma_reference(ifmaddr);
1502 return 0;
1503 }
1504
1505 errno_t
1506 ifmaddr_release(
1507 ifmultiaddr_t ifmaddr)
1508 {
1509 if (ifmaddr == NULL) return EINVAL;
1510 ifma_release(ifmaddr);
1511 return 0;
1512 }
1513
1514 errno_t
1515 ifmaddr_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
1533 errno_t
1534 ifmaddr_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
1545 ifnet_t
1546 ifmaddr_ifnet(
1547 ifmultiaddr_t ifmaddr)
1548 {
1549 if (ifmaddr == NULL || ifmaddr->ifma_ifp == NULL) return NULL;
1550 return ifmaddr->ifma_ifp;
1551 }
1552
1553 /******************************************************************************/
1554 /* interface cloner */
1555 /******************************************************************************/
1556
1557 errno_t
1558 ifnet_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;
1599 fail:
1600 if (ifc != NULL)
1601 FREE(ifc, M_CLONE);
1602 return error;
1603 }
1604
1605 errno_t
1606 ifnet_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;
1625 fail:
1626 return error;
1627 }
1628
1629
1630