]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/kpi_interface.c
bd5323801a8a419bfc8b430deb54c2488d67ac26
[apple/xnu.git] / bsd / net / kpi_interface.c
1 /*
2 * Copyright (c) 2004 Apple Computer, 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 <sys/errno.h>
34 #include <sys/socket.h>
35 #include <sys/kern_event.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/kpi_mbuf.h>
39 #include <net/if_var.h>
40 #include <net/if_dl.h>
41 #include <net/dlil.h>
42 #include <net/if_types.h>
43 #include <net/if_dl.h>
44 #include <net/if_arp.h>
45 #include <libkern/libkern.h>
46 #include <kern/locks.h>
47
48 #if IF_LASTCHANGEUPTIME
49 #define TOUCHLASTCHANGE(__if_lastchange) microuptime(__if_lastchange)
50 #else
51 #define TOUCHLASTCHANGE(__if_lastchange) microtime(__if_lastchange)
52 #endif
53
54 extern lck_spin_t *dlil_input_lock;
55
56 /*
57 Temporary work around until we have real reference counting
58
59 We keep the bits about calling dlil_if_release (which should be
60 called recycle) transparent by calling it from our if_free function
61 pointer. We have to keep the client's original detach function
62 somewhere so we can call it.
63 */
64 static void
65 ifnet_kpi_free(
66 ifnet_t ifp)
67 {
68 ifnet_detached_func detach_func = ifp->if_kpi_storage;
69
70 if (detach_func)
71 detach_func(ifp);
72
73 if (ifp->if_broadcast.length > sizeof(ifp->if_broadcast.u.buffer)) {
74 FREE(ifp->if_broadcast.u.ptr, M_IFADDR);
75 ifp->if_broadcast.u.ptr = NULL;
76 }
77
78 dlil_if_release(ifp);
79 }
80
81 errno_t
82 ifnet_allocate(
83 const struct ifnet_init_params *init,
84 ifnet_t *interface)
85 {
86 int error;
87 struct ifnet *ifp = NULL;
88
89 if (init->family == 0)
90 return EINVAL;
91 if (init->name == NULL ||
92 init->output == NULL)
93 return EINVAL;
94 if (strlen(init->name) >= IFNAMSIZ)
95 return EINVAL;
96 if ((init->type & 0xFFFFFF00) != 0 || init->type == 0)
97 return EINVAL;
98
99 error = dlil_if_acquire(init->family, init->uniqueid, init->uniqueid_len, &ifp);
100 if (error == 0)
101 {
102 strncpy(ifp->if_name, init->name, IFNAMSIZ);
103 ifp->if_type = init->type;
104 ifp->if_family = init->family;
105 ifp->if_unit = init->unit;
106 ifp->if_output = init->output;
107 ifp->if_demux = init->demux;
108 ifp->if_add_proto_u.kpi = init->add_proto;
109 ifp->if_del_proto = init->del_proto;
110 ifp->if_check_multi = init->check_multi;
111 ifp->if_framer = init->framer;
112 ifp->if_softc = init->softc;
113 ifp->if_ioctl = init->ioctl;
114 ifp->if_set_bpf_tap = init->set_bpf_tap;
115 ifp->if_free = ifnet_kpi_free;
116 ifp->if_event = init->event;
117 ifp->if_kpi_storage = init->detach;
118 ifp->if_eflags |= IFEF_USEKPI;
119
120 if (init->broadcast_len && init->broadcast_addr) {
121 if (init->broadcast_len > sizeof(ifp->if_broadcast.u.buffer)) {
122 MALLOC(ifp->if_broadcast.u.ptr, u_char*, init->broadcast_len, M_IFADDR, M_NOWAIT);
123 if (ifp->if_broadcast.u.ptr == NULL) {
124 error = ENOMEM;
125 }
126 else {
127 bcopy(init->broadcast_addr, ifp->if_broadcast.u.ptr, init->broadcast_len);
128 }
129 }
130 else {
131 bcopy(init->broadcast_addr, ifp->if_broadcast.u.buffer, init->broadcast_len);
132 }
133 ifp->if_broadcast.length = init->broadcast_len;
134 }
135 else {
136 bzero(&ifp->if_broadcast, sizeof(ifp->if_broadcast));
137 }
138
139 if (error == 0) {
140 *interface = ifp;
141 ifnet_reference(ifp); // temporary - this should be done in dlil_if_acquire
142 }
143 else {
144 dlil_if_release(ifp);
145 *interface = 0;
146 }
147 }
148
149 /*
150 Note: We should do something here to indicate that we haven't been
151 attached yet. By doing so, we can catch the case in ifnet_release
152 where the reference count reaches zero and call the recycle
153 function. If the interface is attached, the interface will be
154 recycled when the interface's if_free function is called. If the
155 interface is never attached, the if_free function will never be
156 called and the interface will never be recycled.
157 */
158
159 return error;
160 }
161
162 errno_t
163 ifnet_reference(
164 ifnet_t interface)
165 {
166 if (interface == NULL) return EINVAL;
167 ifp_reference(interface);
168 return 0;
169 }
170
171 errno_t
172 ifnet_release(
173 ifnet_t interface)
174 {
175 if (interface == NULL) return EINVAL;
176 ifp_release(interface);
177 return 0;
178 }
179
180 errno_t
181 ifnet_attach(
182 ifnet_t interface,
183 const struct sockaddr_dl *ll_addr)
184 {
185 if (interface == NULL) return EINVAL;
186 if (ll_addr && interface->if_addrlen == 0) {
187 interface->if_addrlen = ll_addr->sdl_alen;
188 }
189 else if (ll_addr && ll_addr->sdl_alen != interface->if_addrlen) {
190 return EINVAL;
191 }
192 return dlil_if_attach_with_address(interface, ll_addr);
193 }
194
195 errno_t
196 ifnet_detach(
197 ifnet_t interface)
198 {
199 errno_t error;
200
201 if (interface == NULL) return EINVAL;
202
203 error = dlil_if_detach(interface);
204 if (error == DLIL_WAIT_FOR_FREE) error = 0; /* Client should always wait for detach */
205
206 return error;
207 }
208
209 void*
210 ifnet_softc(
211 ifnet_t interface)
212 {
213 return interface == NULL ? NULL : interface->if_softc;
214 }
215
216 const char*
217 ifnet_name(
218 ifnet_t interface)
219 {
220 return interface == NULL ? NULL : interface->if_name;
221 }
222
223 ifnet_family_t
224 ifnet_family(
225 ifnet_t interface)
226 {
227 return interface == NULL ? 0 : interface->if_family;
228 }
229
230 u_int32_t
231 ifnet_unit(
232 ifnet_t interface)
233 {
234 return interface == NULL ? (u_int32_t)0xffffffff : (u_int32_t)interface->if_unit;
235 }
236
237 u_int32_t
238 ifnet_index(
239 ifnet_t interface)
240 {
241 return interface == NULL ? (u_int32_t)0xffffffff : interface->if_index;
242 }
243
244 errno_t
245 ifnet_set_flags(
246 ifnet_t interface,
247 u_int16_t new_flags,
248 u_int16_t mask)
249 {
250 int lock;
251
252 if (interface == NULL) return EINVAL;
253 lock = (interface->if_lock != 0);
254
255 if (lock) ifnet_lock_exclusive(interface);
256
257 /* If we are modifying the up/down state, call if_updown */
258 if (lock && (mask & IFF_UP) != 0) {
259 if_updown(interface, (new_flags & IFF_UP) == IFF_UP);
260 }
261
262 interface->if_flags = (new_flags & mask) | (interface->if_flags & ~mask);
263 if (lock) ifnet_lock_done(interface);
264
265 return 0;
266 }
267
268 u_int16_t
269 ifnet_flags(
270 ifnet_t interface)
271 {
272 return interface == NULL ? 0 : interface->if_flags;
273 }
274
275 errno_t
276 ifnet_set_eflags(
277 ifnet_t interface,
278 u_int32_t new_flags,
279 u_int32_t mask)
280 {
281 int lock;
282
283 if (interface == NULL) return EINVAL;
284 lock = (interface->if_lock != 0);
285
286 if (lock) ifnet_lock_exclusive(interface);
287 interface->if_eflags = (new_flags & mask) | (interface->if_eflags & ~mask);
288 if (lock) ifnet_lock_done(interface);
289
290 return 0;
291 }
292
293 u_int32_t
294 ifnet_eflags(
295 ifnet_t interface)
296 {
297 return interface == NULL ? 0 : interface->if_eflags;
298 }
299
300 static const ifnet_offload_t offload_mask = IFNET_CSUM_IP | IFNET_CSUM_TCP |
301 IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT | IFNET_IP_FRAGMENT |
302 IFNET_CSUM_SUM16 | IFNET_VLAN_TAGGING | IFNET_VLAN_MTU;
303
304 errno_t
305 ifnet_set_offload(
306 ifnet_t interface,
307 ifnet_offload_t offload)
308 {
309 int lock;
310
311 if (interface == NULL) return EINVAL;
312 lock = (interface->if_lock != 0);
313
314 if (lock) ifnet_lock_exclusive(interface);
315 interface->if_hwassist = (offload & offload_mask);
316 if (lock) ifnet_lock_done(interface);
317
318 return 0;
319 }
320
321 ifnet_offload_t
322 ifnet_offload(
323 ifnet_t interface)
324 {
325 return interface == NULL ? 0 : (interface->if_hwassist & offload_mask);
326 }
327
328 /*
329 * Should MIB data store a copy?
330 */
331 errno_t
332 ifnet_set_link_mib_data(
333 ifnet_t interface,
334 void* mibData,
335 u_int32_t mibLen)
336 {
337 int lock;
338
339 if (interface == NULL) return EINVAL;
340 lock = (interface->if_lock != 0);
341
342 if (lock) ifnet_lock_exclusive(interface);
343 interface->if_linkmib = (void*)mibData;
344 interface->if_linkmiblen = mibLen;
345 if (lock) ifnet_lock_done(interface);
346 return 0;
347 }
348
349 errno_t
350 ifnet_get_link_mib_data(
351 ifnet_t interface,
352 void *mibData,
353 u_int32_t *mibLen)
354 {
355 errno_t result = 0;
356 int lock;
357
358 if (interface == NULL) return EINVAL;
359 lock = (interface->if_lock != NULL);
360
361 if (lock) ifnet_lock_shared(interface);
362 if (*mibLen < interface->if_linkmiblen)
363 result = EMSGSIZE;
364 if (result == 0 && interface->if_linkmib == NULL)
365 result = ENOTSUP;
366
367 if (result == 0) {
368 *mibLen = interface->if_linkmiblen;
369 bcopy(interface->if_linkmib, mibData, *mibLen);
370 }
371 if (lock) ifnet_lock_done(interface);
372
373 return result;
374 }
375
376 u_int32_t
377 ifnet_get_link_mib_data_length(
378 ifnet_t interface)
379 {
380 return interface == NULL ? 0 : interface->if_linkmiblen;
381 }
382
383 errno_t
384 ifnet_attach_protocol(
385 ifnet_t interface,
386 protocol_family_t protocol,
387 const struct ifnet_attach_proto_param *proto_details)
388 {
389 if (interface == NULL || protocol == 0 || proto_details == NULL)
390 return EINVAL;
391 return dlil_attach_protocol_kpi(interface, protocol, proto_details);
392 }
393
394 errno_t
395 ifnet_detach_protocol(
396 ifnet_t interface,
397 protocol_family_t protocol)
398 {
399 if (interface == NULL || protocol == 0) return EINVAL;
400 return dlil_detach_protocol(interface, protocol);
401 }
402
403 errno_t
404 ifnet_output(
405 ifnet_t interface,
406 protocol_family_t protocol_family,
407 mbuf_t m,
408 void *route,
409 const struct sockaddr *dest)
410 {
411 if (interface == NULL || protocol_family == 0 || m == NULL) {
412 if (m)
413 mbuf_freem_list(m);
414 return EINVAL;
415 }
416 return dlil_output(interface, protocol_family, m, route, dest, 0);
417 }
418
419 errno_t
420 ifnet_output_raw(
421 ifnet_t interface,
422 protocol_family_t protocol_family,
423 mbuf_t m)
424 {
425 if (interface == NULL || protocol_family == 0 || m == NULL) {
426 if (m)
427 mbuf_freem_list(m);
428 return EINVAL;
429 }
430 return dlil_output(interface, protocol_family, m, NULL, NULL, 1);
431 }
432
433 errno_t
434 ifnet_input(
435 ifnet_t interface,
436 mbuf_t first_packet,
437 const struct ifnet_stat_increment_param *stats)
438 {
439 mbuf_t last_packet = first_packet;
440
441 if (interface == NULL || first_packet == NULL) {
442 if (first_packet)
443 mbuf_freem_list(first_packet);
444 return EINVAL;
445 }
446
447 while (mbuf_nextpkt(last_packet) != NULL)
448 last_packet = mbuf_nextpkt(last_packet);
449 return dlil_input_with_stats(interface, first_packet, last_packet, stats);
450 }
451
452 errno_t
453 ifnet_ioctl(
454 ifnet_t interface,
455 protocol_family_t protocol_family,
456 u_int32_t ioctl_code,
457 void *ioctl_arg)
458 {
459 if (interface == NULL || protocol_family == 0 || ioctl_code == 0)
460 return EINVAL;
461 return dlil_ioctl(protocol_family, interface,
462 ioctl_code, ioctl_arg);
463 }
464
465 errno_t
466 ifnet_event(
467 ifnet_t interface,
468 struct kern_event_msg* event_ptr)
469 {
470 if (interface == NULL || event_ptr == NULL) return EINVAL;
471 return dlil_event(interface, event_ptr);
472 }
473
474 errno_t
475 ifnet_set_mtu(
476 ifnet_t interface,
477 u_int32_t mtu)
478 {
479 if (interface == NULL) return EINVAL;
480 interface->if_data.ifi_mtu = mtu;
481 return 0;
482 }
483
484 u_int32_t
485 ifnet_mtu(
486 ifnet_t interface)
487 {
488 u_int32_t retval;
489 retval = interface == NULL ? 0 : interface->if_data.ifi_mtu;
490 return retval;
491 }
492
493 u_char
494 ifnet_type(
495 ifnet_t interface)
496 {
497 u_char retval;
498
499 retval = interface == NULL ? 0 : interface->if_data.ifi_type;
500 return retval;
501 }
502
503 #if 0
504 errno_t
505 ifnet_set_typelen(
506 ifnet_t interface,
507 u_char typelen)
508 {
509 int lock = (interface->if_lock != 0);
510 if (lock) ifnet_lock_exclusive(interface);
511 interface->if_data.ifi_typelen = typelen;
512 if (lock) ifnet_lock_done(interface);
513 return 0;
514 }
515
516 u_char
517 ifnet_typelen(
518 ifnet_t interface)
519 {
520 u_char retval;
521 retval = interface == NULL ? 0 : interface->if_data.ifi_typelen;
522 return retval;
523 }
524 #endif
525
526 errno_t
527 ifnet_set_addrlen(
528 ifnet_t interface,
529 u_char addrlen)
530 {
531 if (interface == NULL) return EINVAL;
532 interface->if_data.ifi_addrlen = addrlen;
533 return 0;
534 }
535
536 u_char
537 ifnet_addrlen(
538 ifnet_t interface)
539 {
540 u_char retval;
541 retval = interface == NULL ? 0 : interface->if_data.ifi_addrlen;
542 return retval;
543 }
544
545 errno_t
546 ifnet_set_hdrlen(
547 ifnet_t interface,
548 u_char hdrlen)
549 {
550 if (interface == NULL) return EINVAL;
551 interface->if_data.ifi_hdrlen = hdrlen;
552 return 0;
553 }
554
555 u_char
556 ifnet_hdrlen(
557 ifnet_t interface)
558 {
559 u_char retval;
560 retval = interface == NULL ? 0 : interface->if_data.ifi_hdrlen;
561 return retval;
562 }
563
564 errno_t
565 ifnet_set_metric(
566 ifnet_t interface,
567 u_int32_t metric)
568 {
569 if (interface == NULL) return EINVAL;
570 interface->if_data.ifi_metric = metric;
571 return 0;
572 }
573
574 u_int32_t
575 ifnet_metric(
576 ifnet_t interface)
577 {
578 u_int32_t retval;
579 retval = interface == NULL ? 0 : interface->if_data.ifi_metric;
580 return retval;
581 }
582
583 errno_t
584 ifnet_set_baudrate(
585 ifnet_t interface,
586 u_int64_t baudrate)
587 {
588 if (interface == NULL) return EINVAL;
589 /* Pin baudrate to 32 bits until we can change the storage size */
590 interface->if_data.ifi_baudrate = baudrate > 0xFFFFFFFF ? 0xFFFFFFFF : baudrate;
591 return 0;
592 }
593
594 u_int64_t
595 ifnet_baudrate(
596 ifnet_t interface)
597 {
598 u_int64_t retval;
599 retval = interface == NULL ? 0 : interface->if_data.ifi_baudrate;
600 return retval;
601 }
602
603 errno_t
604 ifnet_stat_increment(
605 ifnet_t interface,
606 const struct ifnet_stat_increment_param *counts)
607 {
608 if (interface == NULL) return EINVAL;
609
610 lck_spin_lock(dlil_input_lock);
611
612 interface->if_data.ifi_ipackets += counts->packets_in;
613 interface->if_data.ifi_ibytes += counts->bytes_in;
614 interface->if_data.ifi_ierrors += counts->errors_in;
615
616 interface->if_data.ifi_opackets += counts->packets_out;
617 interface->if_data.ifi_obytes += counts->bytes_out;
618 interface->if_data.ifi_oerrors += counts->errors_out;
619
620 interface->if_data.ifi_collisions += counts->collisions;
621 interface->if_data.ifi_iqdrops += counts->dropped;
622
623 /* Touch the last change time. */
624 TOUCHLASTCHANGE(&interface->if_lastchange);
625
626 lck_spin_unlock(dlil_input_lock);
627
628 return 0;
629 }
630
631 errno_t
632 ifnet_stat_increment_in(
633 ifnet_t interface,
634 u_int32_t packets_in,
635 u_int32_t bytes_in,
636 u_int32_t errors_in)
637 {
638 if (interface == NULL) return EINVAL;
639
640 lck_spin_lock(dlil_input_lock);
641
642 interface->if_data.ifi_ipackets += packets_in;
643 interface->if_data.ifi_ibytes += bytes_in;
644 interface->if_data.ifi_ierrors += errors_in;
645
646 TOUCHLASTCHANGE(&interface->if_lastchange);
647
648 lck_spin_unlock(dlil_input_lock);
649
650 return 0;
651 }
652
653 errno_t
654 ifnet_stat_increment_out(
655 ifnet_t interface,
656 u_int32_t packets_out,
657 u_int32_t bytes_out,
658 u_int32_t errors_out)
659 {
660 if (interface == NULL) return EINVAL;
661
662 lck_spin_lock(dlil_input_lock);
663
664 interface->if_data.ifi_opackets += packets_out;
665 interface->if_data.ifi_obytes += bytes_out;
666 interface->if_data.ifi_oerrors += errors_out;
667
668 TOUCHLASTCHANGE(&interface->if_lastchange);
669
670 lck_spin_unlock(dlil_input_lock);
671
672 return 0;
673 }
674
675 errno_t
676 ifnet_set_stat(
677 ifnet_t interface,
678 const struct ifnet_stats_param *stats)
679 {
680 if (interface == NULL) return EINVAL;
681
682 lck_spin_lock(dlil_input_lock);
683
684 interface->if_data.ifi_ipackets = stats->packets_in;
685 interface->if_data.ifi_ibytes = stats->bytes_in;
686 interface->if_data.ifi_imcasts = stats->multicasts_in;
687 interface->if_data.ifi_ierrors = stats->errors_in;
688
689 interface->if_data.ifi_opackets = stats->packets_out;
690 interface->if_data.ifi_obytes = stats->bytes_out;
691 interface->if_data.ifi_omcasts = stats->multicasts_out;
692 interface->if_data.ifi_oerrors = stats->errors_out;
693
694 interface->if_data.ifi_collisions = stats->collisions;
695 interface->if_data.ifi_iqdrops = stats->dropped;
696 interface->if_data.ifi_noproto = stats->no_protocol;
697
698 /* Touch the last change time. */
699 TOUCHLASTCHANGE(&interface->if_lastchange);
700
701 lck_spin_unlock(dlil_input_lock);
702
703 return 0;
704 }
705
706 errno_t
707 ifnet_stat(
708 ifnet_t interface,
709 struct ifnet_stats_param *stats)
710 {
711 if (interface == NULL) return EINVAL;
712
713 lck_spin_lock(dlil_input_lock);
714
715 stats->packets_in = interface->if_data.ifi_ipackets;
716 stats->bytes_in = interface->if_data.ifi_ibytes;
717 stats->multicasts_in = interface->if_data.ifi_imcasts;
718 stats->errors_in = interface->if_data.ifi_ierrors;
719
720 stats->packets_out = interface->if_data.ifi_opackets;
721 stats->bytes_out = interface->if_data.ifi_obytes;
722 stats->multicasts_out = interface->if_data.ifi_omcasts;
723 stats->errors_out = interface->if_data.ifi_oerrors;
724
725 stats->collisions = interface->if_data.ifi_collisions;
726 stats->dropped = interface->if_data.ifi_iqdrops;
727 stats->no_protocol = interface->if_data.ifi_noproto;
728
729 lck_spin_unlock(dlil_input_lock);
730
731 return 0;
732 }
733
734 errno_t
735 ifnet_touch_lastchange(
736 ifnet_t interface)
737 {
738 if (interface == NULL) return EINVAL;
739
740 lck_spin_lock(dlil_input_lock);
741 TOUCHLASTCHANGE(&interface->if_lastchange);
742 lck_spin_unlock(dlil_input_lock);
743
744 return 0;
745 }
746
747 errno_t
748 ifnet_lastchange(
749 ifnet_t interface,
750 struct timeval *last_change)
751 {
752 if (interface == NULL) return EINVAL;
753
754 lck_spin_lock(dlil_input_lock);
755 *last_change = interface->if_data.ifi_lastchange;
756 lck_spin_unlock(dlil_input_lock);
757
758 #if IF_LASTCHANGEUPTIME
759 /* Crude conversion from uptime to calendar time */
760 last_change->tv_sec += boottime_sec();
761 #endif
762
763 return 0;
764 }
765
766 errno_t
767 ifnet_get_address_list(
768 ifnet_t interface,
769 ifaddr_t **addresses)
770 {
771 if (interface == NULL || addresses == NULL) return EINVAL;
772 return ifnet_get_address_list_family(interface, addresses, 0);
773 }
774
775 errno_t
776 ifnet_get_address_list_family(
777 ifnet_t interface,
778 ifaddr_t **addresses,
779 sa_family_t family)
780 {
781 struct ifnet *ifp;
782 int count = 0;
783 int cmax = 0;
784
785 if (interface == NULL || addresses == NULL) return EINVAL;
786 *addresses = NULL;
787
788 ifnet_head_lock_shared();
789 TAILQ_FOREACH(ifp, &ifnet, if_link)
790 {
791 if (interface && ifp != interface) continue;
792
793 ifnet_lock_shared(ifp);
794 if ((ifp->if_eflags & IFEF_DETACHING) == 0) {
795 if (interface == NULL || interface == ifp)
796 {
797 struct ifaddr *addr;
798 TAILQ_FOREACH(addr, &ifp->if_addrhead, ifa_link)
799 {
800 if (family == 0 || addr->ifa_addr->sa_family == family)
801 cmax++;
802 }
803 }
804 }
805 else if (interface != NULL) {
806 ifnet_lock_done(ifp);
807 ifnet_head_done();
808 return ENXIO;
809 }
810 ifnet_lock_done(ifp);
811 }
812
813 MALLOC(*addresses, ifaddr_t*, sizeof(ifaddr_t) * (cmax + 1), M_TEMP, M_NOWAIT);
814 if (*addresses == NULL) {
815 ifnet_head_done();
816 return ENOMEM;
817 }
818
819 TAILQ_FOREACH(ifp, &ifnet, if_link)
820 {
821 if (interface && ifp != interface) continue;
822
823 ifnet_lock_shared(ifp);
824 if ((ifp->if_eflags & IFEF_DETACHING) == 0) {
825 if (interface == NULL || (struct ifnet*)interface == ifp)
826 {
827 struct ifaddr *addr;
828 TAILQ_FOREACH(addr, &ifp->if_addrhead, ifa_link)
829 {
830 if (count + 1 > cmax) break;
831 if (family == 0 || addr->ifa_addr->sa_family == family) {
832 (*addresses)[count] = (ifaddr_t)addr;
833 ifaddr_reference((*addresses)[count]);
834 count++;
835 }
836 }
837 }
838 }
839 ifnet_lock_done(ifp);
840 if (interface || count == cmax)
841 break;
842 }
843 ifnet_head_done();
844 (*addresses)[cmax] = 0;
845
846 return 0;
847 }
848
849 void
850 ifnet_free_address_list(
851 ifaddr_t *addresses)
852 {
853 int i;
854
855 if (addresses == NULL) return;
856
857 for (i = 0; addresses[i] != NULL; i++)
858 {
859 ifaddr_release(addresses[i]);
860 }
861
862 FREE(addresses, M_TEMP);
863 }
864
865 void*
866 ifnet_lladdr(
867 ifnet_t interface)
868 {
869 if (interface == NULL) return NULL;
870 return LLADDR(SDL(interface->if_addrhead.tqh_first->ifa_addr));
871 }
872
873 errno_t
874 ifnet_llbroadcast_copy_bytes(
875 ifnet_t interface,
876 void *addr,
877 size_t buffer_len,
878 size_t *out_len)
879 {
880 if (interface == NULL || addr == NULL || out_len == NULL) return EINVAL;
881
882 *out_len = interface->if_broadcast.length;
883
884 if (buffer_len < interface->if_broadcast.length) {
885 return EMSGSIZE;
886 }
887
888 if (interface->if_broadcast.length == 0)
889 return ENXIO;
890
891 if (interface->if_broadcast.length <= sizeof(interface->if_broadcast.u.buffer)) {
892 bcopy(interface->if_broadcast.u.buffer, addr, interface->if_broadcast.length);
893 }
894 else {
895 bcopy(interface->if_broadcast.u.ptr, addr, interface->if_broadcast.length);
896 }
897
898 return 0;
899 }
900
901 errno_t
902 ifnet_lladdr_copy_bytes(
903 ifnet_t interface,
904 void* lladdr,
905 size_t lladdr_len)
906 {
907 struct sockaddr_dl *sdl;
908 if (interface == NULL || lladdr == NULL) return EINVAL;
909
910 sdl = SDL(interface->if_addrhead.tqh_first->ifa_addr);
911
912 while (1) {
913 if (lladdr_len != sdl->sdl_alen) {
914 bzero(lladdr, lladdr_len);
915 return EMSGSIZE;
916 }
917 bcopy(LLADDR(sdl), lladdr, lladdr_len);
918 if (bcmp(lladdr, LLADDR(sdl), lladdr_len) == 0 &&
919 lladdr_len == sdl->sdl_alen)
920 break;
921 }
922 return 0;
923 }
924
925 static errno_t
926 ifnet_set_lladdr_internal(
927 ifnet_t interface,
928 const void *lladdr,
929 size_t lladdr_len,
930 u_char new_type,
931 int apply_type)
932 {
933 struct ifaddr *ifa;
934 struct sockaddr_dl *sdl;
935 errno_t error = 0;
936
937 if (interface == NULL) return EINVAL;
938
939 if (lladdr_len != 0 && (lladdr_len != interface->if_addrlen || lladdr == 0))
940 return EINVAL;
941
942 ifnet_head_lock_shared();
943 ifa = ifnet_addrs[interface->if_index - 1];
944 if (ifa != NULL) {
945 sdl = (struct sockaddr_dl*)ifa->ifa_addr;
946 if (lladdr_len != 0) {
947 bcopy(lladdr, LLADDR(sdl), lladdr_len);
948 }
949 else {
950 bzero(LLADDR(sdl), interface->if_addrlen);
951 }
952 sdl->sdl_alen = lladdr_len;
953
954 if (apply_type) {
955 sdl->sdl_type = new_type;
956 }
957 }
958 else {
959 error = ENXIO;
960 }
961 ifnet_head_done();
962
963 /* Generate a kernel event */
964 if (error == 0) {
965 dlil_post_msg(interface, KEV_DL_SUBCLASS,
966 KEV_DL_LINK_ADDRESS_CHANGED, NULL, 0);
967 }
968
969 return error;
970 }
971
972 errno_t
973 ifnet_set_lladdr(
974 ifnet_t interface,
975 const void* lladdr,
976 size_t lladdr_len)
977 {
978 return ifnet_set_lladdr_internal(interface, lladdr, lladdr_len, 0, 0);
979 }
980
981 errno_t
982 ifnet_set_lladdr_and_type(
983 ifnet_t interface,
984 const void* lladdr,
985 size_t lladdr_len,
986 u_char type)
987 {
988 return ifnet_set_lladdr_internal(interface, lladdr, lladdr_len, type, 1);
989 }
990
991 errno_t
992 ifnet_add_multicast(
993 ifnet_t interface,
994 const struct sockaddr *maddr,
995 ifmultiaddr_t *address)
996 {
997 if (interface == NULL || maddr == NULL) return EINVAL;
998 return if_addmulti(interface, maddr, address);
999 }
1000
1001 errno_t
1002 ifnet_remove_multicast(
1003 ifmultiaddr_t address)
1004 {
1005 if (address == NULL) return EINVAL;
1006 return if_delmultiaddr(address, 0);
1007 }
1008
1009 errno_t ifnet_get_multicast_list(ifnet_t interface, ifmultiaddr_t **addresses)
1010 {
1011 int count = 0;
1012 int cmax = 0;
1013 struct ifmultiaddr *addr;
1014 int lock;
1015
1016 if (interface == NULL || addresses == NULL)
1017 return EINVAL;
1018
1019 lock = (interface->if_lock != 0);
1020 if (lock) ifnet_lock_shared(interface);
1021 if ((interface->if_eflags & IFEF_DETACHING) == 0) {
1022 LIST_FOREACH(addr, &interface->if_multiaddrs, ifma_link)
1023 {
1024 cmax++;
1025 }
1026 }
1027 else {
1028 if (lock) ifnet_lock_done(interface);
1029 return ENXIO;
1030 }
1031
1032 MALLOC(*addresses, ifmultiaddr_t*, sizeof(ifmultiaddr_t) * (cmax + 1), M_TEMP, M_NOWAIT);
1033 if (*addresses == NULL) return ENOMEM;
1034
1035 LIST_FOREACH(addr, &interface->if_multiaddrs, ifma_link)
1036 {
1037 if (count + 1 > cmax)
1038 break;
1039 (*addresses)[count] = (ifmultiaddr_t)addr;
1040 ifmaddr_reference((*addresses)[count]);
1041 count++;
1042 }
1043 (*addresses)[cmax] = 0;
1044 if (lock) ifnet_lock_done(interface);
1045
1046 return 0;
1047 }
1048
1049 void
1050 ifnet_free_multicast_list(
1051 ifmultiaddr_t *addresses)
1052 {
1053 int i;
1054
1055 if (addresses == NULL) return;
1056
1057 for (i = 0; addresses[i] != NULL; i++)
1058 {
1059 ifmaddr_release(addresses[i]);
1060 }
1061
1062 FREE(addresses, M_TEMP);
1063 }
1064
1065 errno_t
1066 ifnet_find_by_name(
1067 const char *ifname,
1068 ifnet_t *interface)
1069 {
1070 struct ifnet *ifp;
1071 int namelen;
1072
1073 if (ifname == NULL) return EINVAL;
1074
1075 namelen = strlen(ifname);
1076
1077 *interface = NULL;
1078
1079 ifnet_head_lock_shared();
1080 TAILQ_FOREACH(ifp, &ifnet, if_link)
1081 {
1082 struct ifaddr *ifa = ifnet_addrs[ifp->if_index - 1];
1083 struct sockaddr_dl *ll_addr;
1084
1085 if (!ifa || !ifa->ifa_addr)
1086 continue;
1087
1088 ll_addr = (struct sockaddr_dl *)ifa->ifa_addr;
1089
1090 if ((ifp->if_eflags & IFEF_DETACHING) == 0 &&
1091 namelen == ll_addr->sdl_nlen &&
1092 (strncmp(ll_addr->sdl_data, ifname, ll_addr->sdl_nlen) == 0))
1093 {
1094 break;
1095 }
1096 }
1097 if (ifp) {
1098 *interface = ifp;
1099 ifnet_reference(*interface);
1100 }
1101 ifnet_head_done();
1102
1103 return (ifp == NULL) ? ENXIO : 0;
1104 }
1105
1106 errno_t
1107 ifnet_list_get(
1108 ifnet_family_t family,
1109 ifnet_t **list,
1110 u_int32_t *count)
1111 {
1112 struct ifnet *ifp;
1113 u_int32_t cmax = 0;
1114 *count = 0;
1115 errno_t result = 0;
1116
1117 if (list == NULL || count == NULL) return EINVAL;
1118
1119 ifnet_head_lock_shared();
1120 TAILQ_FOREACH(ifp, &ifnet, if_link)
1121 {
1122 if (ifp->if_eflags & IFEF_DETACHING) continue;
1123 if (family == 0 || ifp->if_family == family)
1124 cmax++;
1125 }
1126
1127 if (cmax == 0)
1128 result = ENXIO;
1129
1130 if (result == 0) {
1131 MALLOC(*list, ifnet_t*, sizeof(ifnet_t) * (cmax + 1), M_TEMP, M_NOWAIT);
1132 if (*list == NULL)
1133 result = ENOMEM;
1134 }
1135
1136 if (result == 0) {
1137 TAILQ_FOREACH(ifp, &ifnet, if_link)
1138 {
1139 if (ifp->if_eflags & IFEF_DETACHING) continue;
1140 if (*count + 1 > cmax) break;
1141 if (family == 0 || ((ifnet_family_t)ifp->if_family) == family)
1142 {
1143 (*list)[*count] = (ifnet_t)ifp;
1144 ifnet_reference((*list)[*count]);
1145 (*count)++;
1146 }
1147 }
1148 (*list)[*count] = NULL;
1149 }
1150 ifnet_head_done();
1151
1152 return 0;
1153 }
1154
1155 void
1156 ifnet_list_free(
1157 ifnet_t *interfaces)
1158 {
1159 int i;
1160
1161 if (interfaces == NULL) return;
1162
1163 for (i = 0; interfaces[i]; i++)
1164 {
1165 ifnet_release(interfaces[i]);
1166 }
1167
1168 FREE(interfaces, M_TEMP);
1169 }
1170
1171 /****************************************************************************/
1172 /* ifaddr_t accessors */
1173 /****************************************************************************/
1174
1175 errno_t
1176 ifaddr_reference(
1177 ifaddr_t ifa)
1178 {
1179 if (ifa == NULL) return EINVAL;
1180 ifaref(ifa);
1181 return 0;
1182 }
1183
1184 errno_t
1185 ifaddr_release(
1186 ifaddr_t ifa)
1187 {
1188 if (ifa == NULL) return EINVAL;
1189 ifafree(ifa);
1190 return 0;
1191 }
1192
1193 sa_family_t
1194 ifaddr_address_family(
1195 ifaddr_t ifa)
1196 {
1197 if (ifa && ifa->ifa_addr)
1198 return ifa->ifa_addr->sa_family;
1199
1200 return 0;
1201 }
1202
1203 errno_t
1204 ifaddr_address(
1205 ifaddr_t ifa,
1206 struct sockaddr *out_addr,
1207 u_int32_t addr_size)
1208 {
1209 u_int32_t copylen;
1210
1211 if (ifa == NULL || out_addr == NULL) return EINVAL;
1212 if (ifa->ifa_addr == NULL) return ENOTSUP;
1213
1214 copylen = (addr_size >= ifa->ifa_addr->sa_len) ? ifa->ifa_addr->sa_len : addr_size;
1215 bcopy(ifa->ifa_addr, out_addr, copylen);
1216
1217 if (ifa->ifa_addr->sa_len > addr_size) return EMSGSIZE;
1218
1219 return 0;
1220 }
1221
1222 errno_t
1223 ifaddr_dstaddress(
1224 ifaddr_t ifa,
1225 struct sockaddr *out_addr,
1226 u_int32_t addr_size)
1227 {
1228 u_int32_t copylen;
1229 if (ifa == NULL || out_addr == NULL) return EINVAL;
1230 if (ifa->ifa_dstaddr == NULL) return ENOTSUP;
1231
1232 copylen = (addr_size >= ifa->ifa_dstaddr->sa_len) ? ifa->ifa_dstaddr->sa_len : addr_size;
1233 bcopy(ifa->ifa_dstaddr, out_addr, copylen);
1234
1235 if (ifa->ifa_dstaddr->sa_len > addr_size) return EMSGSIZE;
1236
1237 return 0;
1238 }
1239
1240 errno_t
1241 ifaddr_netmask(
1242 ifaddr_t ifa,
1243 struct sockaddr *out_addr,
1244 u_int32_t addr_size)
1245 {
1246 u_int32_t copylen;
1247 if (ifa == NULL || out_addr == NULL) return EINVAL;
1248 if (ifa->ifa_netmask == NULL) return ENOTSUP;
1249
1250 copylen = addr_size >= ifa->ifa_netmask->sa_len ? ifa->ifa_netmask->sa_len : addr_size;
1251 bcopy(ifa->ifa_netmask, out_addr, copylen);
1252
1253 if (ifa->ifa_netmask->sa_len > addr_size) return EMSGSIZE;
1254
1255 return 0;
1256 }
1257
1258 ifnet_t
1259 ifaddr_ifnet(
1260 ifaddr_t ifa)
1261 {
1262 struct ifnet *ifp;
1263 if (ifa == NULL) return NULL;
1264 ifp = ifa->ifa_ifp;
1265
1266 return (ifnet_t)ifp;
1267 }
1268
1269 ifaddr_t
1270 ifaddr_withaddr(
1271 const struct sockaddr* address)
1272 {
1273 if (address == NULL) return NULL;
1274 return ifa_ifwithaddr(address);
1275 }
1276
1277 ifaddr_t
1278 ifaddr_withdstaddr(
1279 const struct sockaddr* address)
1280 {
1281 if (address == NULL) return NULL;
1282 return ifa_ifwithdstaddr(address);
1283 }
1284
1285 ifaddr_t
1286 ifaddr_withnet(
1287 const struct sockaddr* net)
1288 {
1289 if (net == NULL) return NULL;
1290 return ifa_ifwithnet(net);
1291 }
1292
1293 ifaddr_t
1294 ifaddr_withroute(
1295 int flags,
1296 const struct sockaddr* destination,
1297 const struct sockaddr* gateway)
1298 {
1299 if (destination == NULL || gateway == NULL) return NULL;
1300 return ifa_ifwithroute(flags, destination, gateway);
1301 }
1302
1303 ifaddr_t
1304 ifaddr_findbestforaddr(
1305 const struct sockaddr *addr,
1306 ifnet_t interface)
1307 {
1308 if (addr == NULL || interface == NULL) return NULL;
1309 return ifaof_ifpforaddr(addr, interface);
1310 }
1311
1312 errno_t
1313 ifmaddr_reference(
1314 ifmultiaddr_t ifmaddr)
1315 {
1316 if (ifmaddr == NULL) return EINVAL;
1317 ifma_reference(ifmaddr);
1318 return 0;
1319 }
1320
1321 errno_t
1322 ifmaddr_release(
1323 ifmultiaddr_t ifmaddr)
1324 {
1325 if (ifmaddr == NULL) return EINVAL;
1326 ifma_release(ifmaddr);
1327 return 0;
1328 }
1329
1330 errno_t
1331 ifmaddr_address(
1332 ifmultiaddr_t ifmaddr,
1333 struct sockaddr *out_addr,
1334 u_int32_t addr_size)
1335 {
1336 u_int32_t copylen;
1337
1338 if (ifmaddr == NULL || out_addr == NULL) return EINVAL;
1339 if (ifmaddr->ifma_addr == NULL) return ENOTSUP;
1340
1341 copylen = addr_size >= ifmaddr->ifma_addr->sa_len ? ifmaddr->ifma_addr->sa_len : addr_size;
1342 bcopy(ifmaddr->ifma_addr, out_addr, copylen);
1343
1344 if (ifmaddr->ifma_addr->sa_len > addr_size) return EMSGSIZE;
1345
1346 return 0;
1347 }
1348
1349 errno_t
1350 ifmaddr_lladdress(
1351 ifmultiaddr_t ifmaddr,
1352 struct sockaddr *out_addr,
1353 u_int32_t addr_size)
1354 {
1355 if (ifmaddr == NULL || out_addr == NULL) return EINVAL;
1356 if (ifmaddr->ifma_ll == NULL) return ENOTSUP;
1357
1358 return ifmaddr_address(ifmaddr->ifma_ll, out_addr, addr_size);
1359 }
1360
1361 ifnet_t
1362 ifmaddr_ifnet(
1363 ifmultiaddr_t ifmaddr)
1364 {
1365 if (ifmaddr == NULL || ifmaddr->ifma_ifp == NULL) return NULL;
1366 return ifmaddr->ifma_ifp;
1367 }