1/* 2 * Copyright (c) 2004-2012 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 <sys/mcache.h> 41#include <sys/protosw.h> 42#include <net/if_var.h> 43#include <net/if_dl.h> 44#include <net/dlil.h> 45#include <net/if_types.h> 46#include <net/if_dl.h> 47#include <net/if_arp.h> 48#include <net/if_llreach.h> 49#include <net/route.h> 50#include <libkern/libkern.h> 51#include <libkern/OSAtomic.h> 52#include <kern/locks.h> 53#include <kern/clock.h> 54#include <sys/sockio.h> 55#include <sys/proc.h> 56#include <sys/sysctl.h> 57#include <sys/mbuf.h> 58#ifdef INET 59#include <netinet/igmp_var.h> 60#endif 61#ifdef INET6 62#include <netinet6/mld6_var.h> 63#endif 64 65#include "net/net_str_id.h" 66 67#if IF_LASTCHANGEUPTIME 68#define TOUCHLASTCHANGE(__if_lastchange) { \ 69 (__if_lastchange)->tv_sec = net_uptime(); \ 70 (__if_lastchange)->tv_usec = 0; \ 71} 72#else 73#define TOUCHLASTCHANGE(__if_lastchange) microtime(__if_lastchange) 74#endif 75 76#define _cast_non_const(p) ((void *)(uintptr_t)(p)) 77 78static errno_t ifnet_defrouter_llreachinfo(ifnet_t, int, 79 struct ifnet_llreach_info *); 80static void ifnet_kpi_free(ifnet_t); 81static errno_t ifnet_list_get_common(ifnet_family_t, boolean_t, ifnet_t **, 82 u_int32_t *); 83static errno_t ifnet_set_lladdr_internal(ifnet_t, const void *, size_t, 84 u_char, int); 85static errno_t ifnet_awdl_check_eflags(ifnet_t, u_int32_t *, u_int32_t *); 86 87/* 88 * Temporary work around until we have real reference counting 89 * 90 * We keep the bits about calling dlil_if_release (which should be 91 * called recycle) transparent by calling it from our if_free function 92 * pointer. We have to keep the client's original detach function 93 * somewhere so we can call it. 94 */ 95static void 96ifnet_kpi_free(ifnet_t ifp) 97{ 98 ifnet_detached_func detach_func = ifp->if_kpi_storage; 99 100 if (detach_func != NULL) 101 detach_func(ifp); 102 103 if (ifp->if_broadcast.length > sizeof (ifp->if_broadcast.u.buffer)) { 104 FREE(ifp->if_broadcast.u.ptr, M_IFADDR); 105 ifp->if_broadcast.u.ptr = NULL; 106 } 107 108 dlil_if_release(ifp); 109} 110 111errno_t 112ifnet_allocate(const struct ifnet_init_params *init, ifnet_t *interface) 113{ 114 struct ifnet_init_eparams einit; 115 116 bzero(&einit, sizeof (einit)); 117 118 einit.ver = IFNET_INIT_CURRENT_VERSION; 119 einit.len = sizeof (einit); 120 einit.flags = IFNET_INIT_LEGACY; 121 einit.uniqueid = init->uniqueid; 122 einit.uniqueid_len = init->uniqueid_len; 123 einit.name = init->name; 124 einit.unit = init->unit; 125 einit.family = init->family; 126 einit.type = init->type; 127 einit.output = init->output; 128 einit.demux = init->demux; 129 einit.add_proto = init->add_proto; 130 einit.del_proto = init->del_proto; 131 einit.check_multi = init->check_multi; 132 einit.framer = init->framer; 133 einit.softc = init->softc; 134 einit.ioctl = init->ioctl; 135 einit.set_bpf_tap = init->set_bpf_tap; 136 einit.detach = init->detach; 137 einit.event = init->event; 138 einit.broadcast_addr = init->broadcast_addr; 139 einit.broadcast_len = init->broadcast_len; 140 141 return (ifnet_allocate_extended(&einit, interface)); 142} 143 144errno_t 145ifnet_allocate_extended(const struct ifnet_init_eparams *einit0, 146 ifnet_t *interface) 147{ 148 struct ifnet_init_eparams einit; 149 struct ifnet *ifp = NULL; 150 int error; 151 152 einit = *einit0; 153 154 if (einit.ver != IFNET_INIT_CURRENT_VERSION || 155 einit.len < sizeof (einit)) 156 return (EINVAL); 157 158 if (einit.family == 0 || einit.name == NULL || 159 strlen(einit.name) >= IFNAMSIZ || 160 (einit.type & 0xFFFFFF00) != 0 || einit.type == 0) 161 return (EINVAL); 162 163 if (einit.flags & IFNET_INIT_LEGACY) { 164 if (einit.output == NULL || einit.flags != IFNET_INIT_LEGACY) 165 return (EINVAL); 166 167 einit.pre_enqueue = NULL; 168 einit.start = NULL; 169 einit.output_ctl = NULL; 170 einit.output_sched_model = IFNET_SCHED_MODEL_NORMAL; 171 einit.input_poll = NULL; 172 einit.input_ctl = NULL; 173 } else { 174 if (einit.start == NULL) 175 return (EINVAL); 176 177 einit.output = NULL; 178 if (einit.output_sched_model >= IFNET_SCHED_MODEL_MAX) 179 return (EINVAL); 180 181 if (einit.flags & IFNET_INIT_INPUT_POLL) { 182 if (einit.input_poll == NULL || einit.input_ctl == NULL) 183 return (EINVAL); 184 } else { 185 einit.input_poll = NULL; 186 einit.input_ctl = NULL; 187 } 188 } 189 190 error = dlil_if_acquire(einit.family, einit.uniqueid, 191 einit.uniqueid_len, &ifp); 192 193 if (error == 0) { 194 u_int64_t br; 195 196 /* 197 * Cast ifp->if_name as non const. dlil_if_acquire sets it up 198 * to point to storage of at least IFNAMSIZ bytes. It is safe 199 * to write to this. 200 */ 201 strncpy(_cast_non_const(ifp->if_name), einit.name, IFNAMSIZ); 202 ifp->if_type = einit.type; 203 ifp->if_family = einit.family; 204 ifp->if_unit = einit.unit; 205 ifp->if_output = einit.output; 206 ifp->if_pre_enqueue = einit.pre_enqueue; 207 ifp->if_start = einit.start; 208 ifp->if_output_ctl = einit.output_ctl; 209 ifp->if_output_sched_model = einit.output_sched_model; 210 ifp->if_output_bw.eff_bw = einit.output_bw; 211 ifp->if_output_bw.max_bw = einit.output_bw_max; 212 ifp->if_input_poll = einit.input_poll; 213 ifp->if_input_ctl = einit.input_ctl; 214 ifp->if_input_bw.eff_bw = einit.input_bw; 215 ifp->if_input_bw.max_bw = einit.input_bw_max; 216 ifp->if_demux = einit.demux; 217 ifp->if_add_proto = einit.add_proto; 218 ifp->if_del_proto = einit.del_proto; 219 ifp->if_check_multi = einit.check_multi; 220 ifp->if_framer = einit.framer; 221 ifp->if_softc = einit.softc; 222 ifp->if_ioctl = einit.ioctl; 223 ifp->if_set_bpf_tap = einit.set_bpf_tap; 224 ifp->if_free = ifnet_kpi_free; 225 ifp->if_event = einit.event; 226 ifp->if_kpi_storage = einit.detach; 227 228 if (ifp->if_output_bw.eff_bw > ifp->if_output_bw.max_bw) 229 ifp->if_output_bw.max_bw = ifp->if_output_bw.eff_bw; 230 else if (ifp->if_output_bw.eff_bw == 0) 231 ifp->if_output_bw.eff_bw = ifp->if_output_bw.max_bw; 232 233 if (ifp->if_input_bw.eff_bw > ifp->if_input_bw.max_bw) 234 ifp->if_input_bw.max_bw = ifp->if_input_bw.eff_bw; 235 else if (ifp->if_input_bw.eff_bw == 0) 236 ifp->if_input_bw.eff_bw = ifp->if_input_bw.max_bw; 237 238 if (ifp->if_output_bw.max_bw == 0) 239 ifp->if_output_bw = ifp->if_input_bw; 240 else if (ifp->if_input_bw.max_bw == 0) 241 ifp->if_input_bw = ifp->if_output_bw; 242 243 if (ifp->if_ioctl == NULL) 244 ifp->if_ioctl = ifp_if_ioctl; 245 246 /* Pin if_baudrate to 32 bits */ 247 br = MAX(ifp->if_output_bw.max_bw, ifp->if_input_bw.max_bw); 248 if (br != 0) 249 ifp->if_baudrate = (br > 0xFFFFFFFF) ? 0xFFFFFFFF : br; 250 251 if (ifp->if_start != NULL) { 252 ifp->if_eflags |= IFEF_TXSTART; 253 if (ifp->if_pre_enqueue == NULL) 254 ifp->if_pre_enqueue = ifnet_enqueue; 255 ifp->if_output = ifp->if_pre_enqueue; 256 } else { 257 ifp->if_eflags &= ~IFEF_TXSTART; 258 } 259 260 if (ifp->if_input_poll != NULL) 261 ifp->if_eflags |= IFEF_RXPOLL; 262 else 263 ifp->if_eflags &= ~IFEF_RXPOLL; 264 265 VERIFY(!(einit.flags & IFNET_INIT_LEGACY) || 266 (ifp->if_pre_enqueue == NULL && ifp->if_start == NULL && 267 ifp->if_output_ctl == NULL && ifp->if_input_poll == NULL && 268 ifp->if_input_ctl == NULL)); 269 VERIFY(!(einit.flags & IFNET_INIT_INPUT_POLL) || 270 (ifp->if_input_poll != NULL && ifp->if_input_ctl != NULL)); 271 272 if (einit.broadcast_len && einit.broadcast_addr) { 273 if (einit.broadcast_len > 274 sizeof (ifp->if_broadcast.u.buffer)) { 275 MALLOC(ifp->if_broadcast.u.ptr, u_char *, 276 einit.broadcast_len, M_IFADDR, M_NOWAIT); 277 if (ifp->if_broadcast.u.ptr == NULL) { 278 error = ENOMEM; 279 } else { 280 bcopy(einit.broadcast_addr, 281 ifp->if_broadcast.u.ptr, 282 einit.broadcast_len); 283 } 284 } else { 285 bcopy(einit.broadcast_addr, 286 ifp->if_broadcast.u.buffer, 287 einit.broadcast_len); 288 } 289 ifp->if_broadcast.length = einit.broadcast_len; 290 } else { 291 bzero(&ifp->if_broadcast, sizeof (ifp->if_broadcast)); 292 } 293 294 IFCQ_MAXLEN(&ifp->if_snd) = einit.sndq_maxlen; 295 296 if (error == 0) { 297 *interface = ifp; 298 // temporary - this should be done in dlil_if_acquire 299 ifnet_reference(ifp); 300 } else { 301 dlil_if_release(ifp); 302 *interface = NULL; 303 } 304 } 305 306 /* 307 * Note: We should do something here to indicate that we haven't been 308 * attached yet. By doing so, we can catch the case in ifnet_release 309 * where the reference count reaches zero and call the recycle 310 * function. If the interface is attached, the interface will be 311 * recycled when the interface's if_free function is called. If the 312 * interface is never attached, the if_free function will never be 313 * called and the interface will never be recycled. 314 */ 315 316 return (error); 317} 318 319errno_t 320ifnet_reference(ifnet_t ifp) 321{ 322 return (dlil_if_ref(ifp)); 323} 324 325errno_t 326ifnet_release(ifnet_t ifp) 327{ 328 return (dlil_if_free(ifp)); 329} 330 331errno_t 332ifnet_interface_family_find(const char *module_string, 333 ifnet_family_t *family_id) 334{ 335 if (module_string == NULL || family_id == NULL) 336 return (EINVAL); 337 338 return (net_str_id_find_internal(module_string, family_id, 339 NSI_IF_FAM_ID, 1)); 340} 341 342void * 343ifnet_softc(ifnet_t interface) 344{ 345 return ((interface == NULL) ? NULL : interface->if_softc); 346} 347 348const char * 349ifnet_name(ifnet_t interface) 350{ 351 return ((interface == NULL) ? NULL : interface->if_name); 352} 353 354ifnet_family_t 355ifnet_family(ifnet_t interface) 356{ 357 return ((interface == NULL) ? 0 : interface->if_family); 358} 359 360u_int32_t 361ifnet_unit(ifnet_t interface) 362{ 363 return ((interface == NULL) ? (u_int32_t)0xffffffff : 364 (u_int32_t)interface->if_unit); 365} 366 367u_int32_t 368ifnet_index(ifnet_t interface) 369{ 370 return ((interface == NULL) ? (u_int32_t)0xffffffff : 371 interface->if_index); 372} 373 374errno_t 375ifnet_set_flags(ifnet_t interface, u_int16_t new_flags, u_int16_t mask) 376{ 377 uint16_t old_flags; 378 379 if (interface == NULL) 380 return (EINVAL); 381 382 ifnet_lock_exclusive(interface); 383 384 /* If we are modifying the up/down state, call if_updown */ 385 if ((mask & IFF_UP) != 0) { 386 if_updown(interface, (new_flags & IFF_UP) == IFF_UP); 387 } 388 389 old_flags = interface->if_flags; 390 interface->if_flags = (new_flags & mask) | (interface->if_flags & ~mask); 391 /* If we are modifying the multicast flag, set/unset the silent flag */ 392 if ((old_flags & IFF_MULTICAST) != 393 (interface->if_flags & IFF_MULTICAST)) { 394#if INET 395 if (IGMP_IFINFO(interface) != NULL) 396 igmp_initsilent(interface, IGMP_IFINFO(interface)); 397#endif /* INET */ 398#if INET6 399 if (MLD_IFINFO(interface) != NULL) 400 mld6_initsilent(interface, MLD_IFINFO(interface)); 401#endif /* INET6 */ 402 } 403 404 ifnet_lock_done(interface); 405 406 return (0); 407} 408 409u_int16_t 410ifnet_flags(ifnet_t interface) 411{ 412 return ((interface == NULL) ? 0 : interface->if_flags); 413} 414 415/* 416 * This routine ensures the following: 417 * 418 * If IFEF_AWDL is set by the caller, also set the rest of flags as 419 * defined in IFEF_AWDL_MASK. 420 * 421 * If IFEF_AWDL has been set on the interface and the caller attempts 422 * to clear one or more of the associated flags in IFEF_AWDL_MASK, 423 * return failure. 424 * 425 * All other flags not associated with AWDL are not affected. 426 * 427 * See <net/if.h> for current definition of IFEF_AWDL_MASK. 428 */ 429static errno_t 430ifnet_awdl_check_eflags(ifnet_t ifp, u_int32_t *new_eflags, u_int32_t *mask) 431{ 432 u_int32_t eflags; 433 434 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE); 435 436 eflags = (*new_eflags & *mask) | (ifp->if_eflags & ~(*mask)); 437 438 if (ifp->if_eflags & IFEF_AWDL) { 439 if (eflags & IFEF_AWDL) { 440 if ((eflags & IFEF_AWDL_MASK) != IFEF_AWDL_MASK) 441 return (1); 442 } else { 443 *new_eflags &= ~IFEF_AWDL_MASK; 444 *mask |= IFEF_AWDL_MASK; 445 } 446 } else if (eflags & IFEF_AWDL) { 447 *new_eflags |= IFEF_AWDL_MASK; 448 *mask |= IFEF_AWDL_MASK; 449 } 450 451 return (0); 452} 453 454errno_t 455ifnet_set_eflags(ifnet_t interface, u_int32_t new_flags, u_int32_t mask) 456{ 457 if (interface == NULL) 458 return (EINVAL); 459 460 ifnet_lock_exclusive(interface); 461 /* 462 * Sanity checks for IFEF_AWDL and its related flags. 463 */ 464 if (ifnet_awdl_check_eflags(interface, &new_flags, &mask) != 0) { 465 ifnet_lock_done(interface); 466 return (EINVAL); 467 } 468 interface->if_eflags = 469 (new_flags & mask) | (interface->if_eflags & ~mask); 470 ifnet_lock_done(interface); 471 472 return (0); 473} 474 475u_int32_t 476ifnet_eflags(ifnet_t interface) 477{ 478 return ((interface == NULL) ? 0 : interface->if_eflags); 479} 480 481errno_t 482ifnet_set_idle_flags_locked(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask) 483{ 484 int before, after; 485 486 if (ifp == NULL) 487 return (EINVAL); 488 489 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED); 490 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE); 491 492 /* 493 * If this is called prior to ifnet attach, the actual work will 494 * be done at attach time. Otherwise, if it is called after 495 * ifnet detach, then it is a no-op. 496 */ 497 if (!ifnet_is_attached(ifp, 0)) { 498 ifp->if_idle_new_flags = new_flags; 499 ifp->if_idle_new_flags_mask = mask; 500 return (0); 501 } else { 502 ifp->if_idle_new_flags = ifp->if_idle_new_flags_mask = 0; 503 } 504 505 before = ifp->if_idle_flags; 506 ifp->if_idle_flags = (new_flags & mask) | (ifp->if_idle_flags & ~mask); 507 after = ifp->if_idle_flags; 508 509 if ((after - before) < 0 && ifp->if_idle_flags == 0 && 510 ifp->if_want_aggressive_drain != 0) { 511 ifp->if_want_aggressive_drain = 0; 512 if (ifnet_aggressive_drainers == 0) 513 panic("%s: ifp=%p negative aggdrain!", __func__, ifp); 514 if (--ifnet_aggressive_drainers == 0) 515 rt_aggdrain(0); 516 } else if ((after - before) > 0 && ifp->if_want_aggressive_drain == 0) { 517 ifp->if_want_aggressive_drain++; 518 if (++ifnet_aggressive_drainers == 0) 519 panic("%s: ifp=%p wraparound aggdrain!", __func__, ifp); 520 else if (ifnet_aggressive_drainers == 1) 521 rt_aggdrain(1); 522 } 523 524 return (0); 525} 526 527errno_t 528ifnet_set_idle_flags(ifnet_t ifp, u_int32_t new_flags, u_int32_t mask) 529{ 530 errno_t err; 531 532 lck_mtx_lock(rnh_lock); 533 ifnet_lock_exclusive(ifp); 534 err = ifnet_set_idle_flags_locked(ifp, new_flags, mask); 535 ifnet_lock_done(ifp); 536 lck_mtx_unlock(rnh_lock); 537 538 return (err); 539} 540 541u_int32_t 542ifnet_idle_flags(ifnet_t ifp) 543{ 544 return ((ifp == NULL) ? 0 : ifp->if_idle_flags); 545} 546 547errno_t 548ifnet_set_link_quality(ifnet_t ifp, int quality) 549{ 550 errno_t err = 0; 551 552 if (ifp == NULL || quality < IFNET_LQM_MIN || quality > IFNET_LQM_MAX) { 553 err = EINVAL; 554 goto done; 555 } 556 557 if (!ifnet_is_attached(ifp, 0)) { 558 err = ENXIO; 559 goto done; 560 } 561 562 if_lqm_update(ifp, quality); 563 564done: 565 return (err); 566} 567 568int 569ifnet_link_quality(ifnet_t ifp) 570{ 571 int lqm; 572 573 if (ifp == NULL) 574 return (IFNET_LQM_THRESH_OFF); 575 576 ifnet_lock_shared(ifp); 577 lqm = ifp->if_lqm; 578 ifnet_lock_done(ifp); 579 580 return (lqm); 581} 582 583static errno_t 584ifnet_defrouter_llreachinfo(ifnet_t ifp, int af, 585 struct ifnet_llreach_info *iflri) 586{ 587 if (ifp == NULL || iflri == NULL) 588 return (EINVAL); 589 590 VERIFY(af == AF_INET || af == AF_INET6); 591 592 return (ifnet_llreach_get_defrouter(ifp, af, iflri)); 593} 594 595errno_t 596ifnet_inet_defrouter_llreachinfo(ifnet_t ifp, struct ifnet_llreach_info *iflri) 597{ 598 return (ifnet_defrouter_llreachinfo(ifp, AF_INET, iflri)); 599} 600 601errno_t 602ifnet_inet6_defrouter_llreachinfo(ifnet_t ifp, struct ifnet_llreach_info *iflri) 603{ 604 return (ifnet_defrouter_llreachinfo(ifp, AF_INET6, iflri)); 605} 606 607errno_t 608ifnet_set_capabilities_supported(ifnet_t ifp, u_int32_t new_caps, 609 u_int32_t mask) 610{ 611 errno_t error = 0; 612 int tmp; 613 614 if (ifp == NULL) 615 return (EINVAL); 616 617 ifnet_lock_exclusive(ifp); 618 tmp = (new_caps & mask) | (ifp->if_capabilities & ~mask); 619 if ((tmp & ~IFCAP_VALID)) 620 error = EINVAL; 621 else 622 ifp->if_capabilities = tmp; 623 ifnet_lock_done(ifp); 624 625 return (error); 626} 627 628u_int32_t 629ifnet_capabilities_supported(ifnet_t ifp) 630{ 631 return ((ifp == NULL) ? 0 : ifp->if_capabilities); 632} 633 634 635errno_t 636ifnet_set_capabilities_enabled(ifnet_t ifp, u_int32_t new_caps, 637 u_int32_t mask) 638{ 639 errno_t error = 0; 640 int tmp; 641 struct kev_msg ev_msg; 642 struct net_event_data ev_data; 643 644 if (ifp == NULL) 645 return (EINVAL); 646 647 ifnet_lock_exclusive(ifp); 648 tmp = (new_caps & mask) | (ifp->if_capenable & ~mask); 649 if ((tmp & ~IFCAP_VALID) || (tmp & ~ifp->if_capabilities)) 650 error = EINVAL; 651 else 652 ifp->if_capenable = tmp; 653 ifnet_lock_done(ifp); 654 655 /* Notify application of the change */ 656 bzero(&ev_data, sizeof (struct net_event_data)); 657 bzero(&ev_msg, sizeof (struct kev_msg)); 658 ev_msg.vendor_code = KEV_VENDOR_APPLE; 659 ev_msg.kev_class = KEV_NETWORK_CLASS; 660 ev_msg.kev_subclass = KEV_DL_SUBCLASS; 661 662 ev_msg.event_code = KEV_DL_IFCAP_CHANGED; 663 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ); 664 ev_data.if_family = ifp->if_family; 665 ev_data.if_unit = (u_int32_t)ifp->if_unit; 666 ev_msg.dv[0].data_length = sizeof (struct net_event_data); 667 ev_msg.dv[0].data_ptr = &ev_data; 668 ev_msg.dv[1].data_length = 0; 669 kev_post_msg(&ev_msg); 670 671 return (error); 672} 673 674u_int32_t 675ifnet_capabilities_enabled(ifnet_t ifp) 676{ 677 return ((ifp == NULL) ? 0 : ifp->if_capenable); 678} 679 680static const ifnet_offload_t offload_mask = 681 (IFNET_CSUM_IP | IFNET_CSUM_TCP | IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT | 682 IFNET_IP_FRAGMENT | IFNET_CSUM_TCPIPV6 | IFNET_CSUM_UDPIPV6 | 683 IFNET_IPV6_FRAGMENT | IFNET_CSUM_SUM16 | IFNET_VLAN_TAGGING | 684 IFNET_VLAN_MTU | IFNET_MULTIPAGES | IFNET_TSO_IPV4 | IFNET_TSO_IPV6); 685 686static const ifnet_offload_t any_offload_csum = 687 (IFNET_CSUM_IP | IFNET_CSUM_TCP | IFNET_CSUM_UDP | IFNET_CSUM_FRAGMENT | 688 IFNET_CSUM_TCPIPV6 | IFNET_CSUM_UDPIPV6 | IFNET_CSUM_SUM16); 689 690errno_t 691ifnet_set_offload(ifnet_t interface, ifnet_offload_t offload) 692{ 693 u_int32_t ifcaps = 0; 694 695 if (interface == NULL) 696 return (EINVAL); 697 698 ifnet_lock_exclusive(interface); 699 interface->if_hwassist = (offload & offload_mask); 700 ifnet_lock_done(interface); 701 702 if ((offload & any_offload_csum)) 703 ifcaps |= IFCAP_HWCSUM; 704 if ((offload & IFNET_TSO_IPV4)) 705 ifcaps |= IFCAP_TSO4; 706 if ((offload & IFNET_TSO_IPV6)) 707 ifcaps |= IFCAP_TSO6; 708 if ((offload & IFNET_VLAN_MTU)) 709 ifcaps |= IFCAP_VLAN_MTU; 710 if ((offload & IFNET_VLAN_TAGGING)) 711 ifcaps |= IFCAP_VLAN_HWTAGGING; 712 if (ifcaps != 0) { 713 (void) ifnet_set_capabilities_supported(interface, ifcaps, 714 IFCAP_VALID); 715 (void) ifnet_set_capabilities_enabled(interface, ifcaps, 716 IFCAP_VALID); 717 } 718 719 return (0); 720} 721 722ifnet_offload_t 723ifnet_offload(ifnet_t interface) 724{ 725 return ((interface == NULL) ? 726 0 : (interface->if_hwassist & offload_mask)); 727} 728 729errno_t 730ifnet_set_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t mtuLen) 731{ 732 errno_t error = 0; 733 734 if (interface == NULL || mtuLen < interface->if_mtu) 735 return (EINVAL); 736 737 switch (family) { 738 case AF_INET: 739 if (interface->if_hwassist & IFNET_TSO_IPV4) 740 interface->if_tso_v4_mtu = mtuLen; 741 else 742 error = EINVAL; 743 break; 744 745 case AF_INET6: 746 if (interface->if_hwassist & IFNET_TSO_IPV6) 747 interface->if_tso_v6_mtu = mtuLen; 748 else 749 error = EINVAL; 750 break; 751 752 default: 753 error = EPROTONOSUPPORT; 754 break; 755 } 756 757 return (error); 758} 759 760errno_t 761ifnet_get_tso_mtu(ifnet_t interface, sa_family_t family, u_int32_t *mtuLen) 762{ 763 errno_t error = 0; 764 765 if (interface == NULL || mtuLen == NULL) 766 return (EINVAL); 767 768 switch (family) { 769 case AF_INET: 770 if (interface->if_hwassist & IFNET_TSO_IPV4) 771 *mtuLen = interface->if_tso_v4_mtu; 772 else 773 error = EINVAL; 774 break; 775 776 case AF_INET6: 777 if (interface->if_hwassist & IFNET_TSO_IPV6) 778 *mtuLen = interface->if_tso_v6_mtu; 779 else 780 error = EINVAL; 781 break; 782 783 default: 784 error = EPROTONOSUPPORT; 785 break; 786 } 787 788 return (error); 789} 790 791errno_t 792ifnet_set_wake_flags(ifnet_t interface, u_int32_t properties, u_int32_t mask) 793{ 794 struct kev_msg ev_msg; 795 struct net_event_data ev_data; 796 797 bzero(&ev_data, sizeof (struct net_event_data)); 798 bzero(&ev_msg, sizeof (struct kev_msg)); 799 800 if (interface == NULL) 801 return (EINVAL); 802 803 /* Do not accept wacky values */ 804 if ((properties & mask) & ~IF_WAKE_VALID_FLAGS) 805 return (EINVAL); 806 807 ifnet_lock_exclusive(interface); 808 809 interface->if_wake_properties = 810 (properties & mask) | (interface->if_wake_properties & ~mask); 811 812 ifnet_lock_done(interface); 813 814 (void) ifnet_touch_lastchange(interface); 815 816 /* Notify application of the change */ 817 ev_msg.vendor_code = KEV_VENDOR_APPLE; 818 ev_msg.kev_class = KEV_NETWORK_CLASS; 819 ev_msg.kev_subclass = KEV_DL_SUBCLASS; 820 821 ev_msg.event_code = KEV_DL_WAKEFLAGS_CHANGED; 822 strlcpy(&ev_data.if_name[0], interface->if_name, IFNAMSIZ); 823 ev_data.if_family = interface->if_family; 824 ev_data.if_unit = (u_int32_t)interface->if_unit; 825 ev_msg.dv[0].data_length = sizeof (struct net_event_data); 826 ev_msg.dv[0].data_ptr = &ev_data; 827 ev_msg.dv[1].data_length = 0; 828 kev_post_msg(&ev_msg); 829 830 return (0); 831} 832 833u_int32_t 834ifnet_get_wake_flags(ifnet_t interface) 835{ 836 return ((interface == NULL) ? 0 : interface->if_wake_properties); 837} 838 839/* 840 * Should MIB data store a copy? 841 */ 842errno_t 843ifnet_set_link_mib_data(ifnet_t interface, void *mibData, u_int32_t mibLen) 844{ 845 if (interface == NULL) 846 return (EINVAL); 847 848 ifnet_lock_exclusive(interface); 849 interface->if_linkmib = (void*)mibData; 850 interface->if_linkmiblen = mibLen; 851 ifnet_lock_done(interface); 852 return (0); 853} 854 855errno_t 856ifnet_get_link_mib_data(ifnet_t interface, void *mibData, u_int32_t *mibLen) 857{ 858 errno_t result = 0; 859 860 if (interface == NULL) 861 return (EINVAL); 862 863 ifnet_lock_shared(interface); 864 if (*mibLen < interface->if_linkmiblen) 865 result = EMSGSIZE; 866 if (result == 0 && interface->if_linkmib == NULL) 867 result = ENOTSUP; 868 869 if (result == 0) { 870 *mibLen = interface->if_linkmiblen; 871 bcopy(interface->if_linkmib, mibData, *mibLen); 872 } 873 ifnet_lock_done(interface); 874 875 return (result); 876} 877 878u_int32_t 879ifnet_get_link_mib_data_length(ifnet_t interface) 880{ 881 return ((interface == NULL) ? 0 : interface->if_linkmiblen); 882} 883 884errno_t 885ifnet_output(ifnet_t interface, protocol_family_t protocol_family, 886 mbuf_t m, void *route, const struct sockaddr *dest) 887{ 888 if (interface == NULL || protocol_family == 0 || m == NULL) { 889 if (m != NULL) 890 mbuf_freem_list(m); 891 return (EINVAL); 892 } 893 return (dlil_output(interface, protocol_family, m, route, dest, 0, NULL)); 894} 895 896errno_t 897ifnet_output_raw(ifnet_t interface, protocol_family_t protocol_family, mbuf_t m) 898{ 899 if (interface == NULL || m == NULL) { 900 if (m != NULL) 901 mbuf_freem_list(m); 902 return (EINVAL); 903 } 904 return (dlil_output(interface, protocol_family, m, NULL, NULL, 1, NULL)); 905} 906 907errno_t 908ifnet_set_mtu(ifnet_t interface, u_int32_t mtu) 909{ 910 if (interface == NULL) 911 return (EINVAL); 912 913 interface->if_mtu = mtu; 914 return (0); 915} 916 917u_int32_t 918ifnet_mtu(ifnet_t interface) 919{ 920 return ((interface == NULL) ? 0 : interface->if_mtu); 921} 922 923u_char 924ifnet_type(ifnet_t interface) 925{ 926 return ((interface == NULL) ? 0 : interface->if_data.ifi_type); 927} 928 929errno_t 930ifnet_set_addrlen(ifnet_t interface, u_char addrlen) 931{ 932 if (interface == NULL) 933 return (EINVAL); 934 935 interface->if_data.ifi_addrlen = addrlen; 936 return (0); 937} 938 939u_char 940ifnet_addrlen(ifnet_t interface) 941{ 942 return ((interface == NULL) ? 0 : interface->if_data.ifi_addrlen); 943} 944 945errno_t 946ifnet_set_hdrlen(ifnet_t interface, u_char hdrlen) 947{ 948 if (interface == NULL) 949 return (EINVAL); 950 951 interface->if_data.ifi_hdrlen = hdrlen; 952 return (0); 953} 954 955u_char 956ifnet_hdrlen(ifnet_t interface) 957{ 958 return ((interface == NULL) ? 0 : interface->if_data.ifi_hdrlen); 959} 960 961errno_t 962ifnet_set_metric(ifnet_t interface, u_int32_t metric) 963{ 964 if (interface == NULL) 965 return (EINVAL); 966 967 interface->if_data.ifi_metric = metric; 968 return (0); 969} 970 971u_int32_t 972ifnet_metric(ifnet_t interface) 973{ 974 return ((interface == NULL) ? 0 : interface->if_data.ifi_metric); 975} 976 977errno_t 978ifnet_set_baudrate(struct ifnet *ifp, u_int64_t baudrate) 979{ 980 if (ifp == NULL) 981 return (EINVAL); 982 983 ifp->if_output_bw.max_bw = ifp->if_input_bw.max_bw = 984 ifp->if_output_bw.eff_bw = ifp->if_input_bw.eff_bw = baudrate; 985 986 /* Pin if_baudrate to 32 bits until we can change the storage size */ 987 ifp->if_baudrate = (baudrate > 0xFFFFFFFF) ? 0xFFFFFFFF : baudrate; 988 989 return (0); 990} 991 992u_int64_t 993ifnet_baudrate(struct ifnet *ifp) 994{ 995 return ((ifp == NULL) ? 0 : ifp->if_baudrate); 996} 997 998errno_t 999ifnet_set_bandwidths(struct ifnet *ifp, struct if_bandwidths *output_bw, 1000 struct if_bandwidths *input_bw) 1001{ 1002 if (ifp == NULL) 1003 return (EINVAL); 1004 1005 if (input_bw != NULL) 1006 (void) ifnet_set_input_bandwidths(ifp, input_bw); 1007 1008 if (output_bw != NULL) 1009 (void) ifnet_set_output_bandwidths(ifp, output_bw, FALSE); 1010 1011 return (0); 1012} 1013 1014errno_t 1015ifnet_set_output_bandwidths(struct ifnet *ifp, struct if_bandwidths *bw, 1016 boolean_t locked) 1017{ 1018 struct if_bandwidths old_bw; 1019 struct ifclassq *ifq; 1020 u_int64_t br; 1021 1022 ifq = &ifp->if_snd; 1023 if (!locked) 1024 IFCQ_LOCK(ifq); 1025 IFCQ_LOCK_ASSERT_HELD(ifq); 1026 1027 old_bw = ifp->if_output_bw; 1028 if (bw != NULL) { 1029 if (bw->eff_bw != 0) 1030 ifp->if_output_bw.eff_bw = bw->eff_bw; 1031 if (bw->max_bw != 0) 1032 ifp->if_output_bw.max_bw = bw->max_bw; 1033 if (ifp->if_output_bw.eff_bw > ifp->if_output_bw.max_bw) 1034 ifp->if_output_bw.max_bw = ifp->if_output_bw.eff_bw; 1035 else if (ifp->if_output_bw.eff_bw == 0) 1036 ifp->if_output_bw.eff_bw = ifp->if_output_bw.max_bw; 1037 } 1038 1039 /* Pin if_baudrate to 32 bits */ 1040 br = MAX(ifp->if_output_bw.max_bw, ifp->if_input_bw.max_bw); 1041 if (br != 0) 1042 ifp->if_baudrate = (br > 0xFFFFFFFF) ? 0xFFFFFFFF : br; 1043 1044 /* Adjust queue parameters if needed */ 1045 if (old_bw.eff_bw != ifp->if_output_bw.eff_bw || 1046 old_bw.max_bw != ifp->if_output_bw.max_bw) 1047 ifnet_update_sndq(ifq, CLASSQ_EV_LINK_SPEED); 1048 1049 if (!locked) 1050 IFCQ_UNLOCK(ifq); 1051 1052 return (0); 1053} 1054 1055errno_t 1056ifnet_set_input_bandwidths(struct ifnet *ifp, struct if_bandwidths *bw) 1057{ 1058 struct if_bandwidths old_bw; 1059 1060 old_bw = ifp->if_input_bw; 1061 if (bw->eff_bw != 0) 1062 ifp->if_input_bw.eff_bw = bw->eff_bw; 1063 if (bw->max_bw != 0) 1064 ifp->if_input_bw.max_bw = bw->max_bw; 1065 if (ifp->if_input_bw.eff_bw > ifp->if_input_bw.max_bw) 1066 ifp->if_input_bw.max_bw = ifp->if_input_bw.eff_bw; 1067 else if (ifp->if_input_bw.eff_bw == 0) 1068 ifp->if_input_bw.eff_bw = ifp->if_input_bw.max_bw; 1069 1070 if (old_bw.eff_bw != ifp->if_input_bw.eff_bw || 1071 old_bw.max_bw != ifp->if_input_bw.max_bw) 1072 ifnet_update_rcv(ifp, CLASSQ_EV_LINK_SPEED); 1073 1074 return (0); 1075} 1076 1077u_int64_t 1078ifnet_output_linkrate(struct ifnet *ifp) 1079{ 1080 struct ifclassq *ifq = &ifp->if_snd; 1081 u_int64_t rate; 1082 1083 IFCQ_LOCK_ASSERT_HELD(ifq); 1084 1085 rate = ifp->if_output_bw.eff_bw; 1086 if (IFCQ_TBR_IS_ENABLED(ifq)) { 1087 u_int64_t tbr_rate = ifp->if_snd.ifcq_tbr.tbr_rate_raw; 1088 VERIFY(tbr_rate > 0); 1089 rate = MIN(rate, ifp->if_snd.ifcq_tbr.tbr_rate_raw); 1090 } 1091 1092 return (rate); 1093} 1094 1095u_int64_t 1096ifnet_input_linkrate(struct ifnet *ifp) 1097{ 1098 return (ifp->if_input_bw.eff_bw); 1099} 1100 1101errno_t 1102ifnet_bandwidths(struct ifnet *ifp, struct if_bandwidths *output_bw, 1103 struct if_bandwidths *input_bw) 1104{ 1105 if (ifp == NULL) 1106 return (EINVAL); 1107 1108 if (output_bw != NULL) 1109 *output_bw = ifp->if_output_bw; 1110 if (input_bw != NULL) 1111 *input_bw = ifp->if_input_bw; 1112 1113 return (0); 1114} 1115 1116errno_t 1117ifnet_stat_increment(struct ifnet *ifp, 1118 const struct ifnet_stat_increment_param *s) 1119{ 1120 if (ifp == NULL) 1121 return (EINVAL); 1122 1123 if (s->packets_in != 0) 1124 atomic_add_64(&ifp->if_data.ifi_ipackets, s->packets_in); 1125 if (s->bytes_in != 0) 1126 atomic_add_64(&ifp->if_data.ifi_ibytes, s->bytes_in); 1127 if (s->errors_in != 0) 1128 atomic_add_64(&ifp->if_data.ifi_ierrors, s->errors_in); 1129 1130 if (s->packets_out != 0) 1131 atomic_add_64(&ifp->if_data.ifi_opackets, s->packets_out); 1132 if (s->bytes_out != 0) 1133 atomic_add_64(&ifp->if_data.ifi_obytes, s->bytes_out); 1134 if (s->errors_out != 0) 1135 atomic_add_64(&ifp->if_data.ifi_oerrors, s->errors_out); 1136 1137 if (s->collisions != 0) 1138 atomic_add_64(&ifp->if_data.ifi_collisions, s->collisions); 1139 if (s->dropped != 0) 1140 atomic_add_64(&ifp->if_data.ifi_iqdrops, s->dropped); 1141 1142 /* Touch the last change time. */ 1143 TOUCHLASTCHANGE(&ifp->if_lastchange); 1144 1145 return (0); 1146} 1147 1148errno_t 1149ifnet_stat_increment_in(struct ifnet *ifp, u_int32_t packets_in, 1150 u_int32_t bytes_in, u_int32_t errors_in) 1151{ 1152 if (ifp == NULL) 1153 return (EINVAL); 1154 1155 if (packets_in != 0) 1156 atomic_add_64(&ifp->if_data.ifi_ipackets, packets_in); 1157 if (bytes_in != 0) 1158 atomic_add_64(&ifp->if_data.ifi_ibytes, bytes_in); 1159 if (errors_in != 0) 1160 atomic_add_64(&ifp->if_data.ifi_ierrors, errors_in); 1161 1162 TOUCHLASTCHANGE(&ifp->if_lastchange); 1163 1164 return (0); 1165} 1166 1167errno_t 1168ifnet_stat_increment_out(struct ifnet *ifp, u_int32_t packets_out, 1169 u_int32_t bytes_out, u_int32_t errors_out) 1170{ 1171 if (ifp == NULL) 1172 return (EINVAL); 1173 1174 if (packets_out != 0) 1175 atomic_add_64(&ifp->if_data.ifi_opackets, packets_out); 1176 if (bytes_out != 0) 1177 atomic_add_64(&ifp->if_data.ifi_obytes, bytes_out); 1178 if (errors_out != 0) 1179 atomic_add_64(&ifp->if_data.ifi_oerrors, errors_out); 1180 1181 TOUCHLASTCHANGE(&ifp->if_lastchange); 1182 1183 return (0); 1184} 1185 1186errno_t 1187ifnet_set_stat(struct ifnet *ifp, const struct ifnet_stats_param *s) 1188{ 1189 if (ifp == NULL) 1190 return (EINVAL); 1191 1192 atomic_set_64(&ifp->if_data.ifi_ipackets, s->packets_in); 1193 atomic_set_64(&ifp->if_data.ifi_ibytes, s->bytes_in); 1194 atomic_set_64(&ifp->if_data.ifi_imcasts, s->multicasts_in); 1195 atomic_set_64(&ifp->if_data.ifi_ierrors, s->errors_in); 1196 1197 atomic_set_64(&ifp->if_data.ifi_opackets, s->packets_out); 1198 atomic_set_64(&ifp->if_data.ifi_obytes, s->bytes_out); 1199 atomic_set_64(&ifp->if_data.ifi_omcasts, s->multicasts_out); 1200 atomic_set_64(&ifp->if_data.ifi_oerrors, s->errors_out); 1201 1202 atomic_set_64(&ifp->if_data.ifi_collisions, s->collisions); 1203 atomic_set_64(&ifp->if_data.ifi_iqdrops, s->dropped); 1204 atomic_set_64(&ifp->if_data.ifi_noproto, s->no_protocol); 1205 1206 /* Touch the last change time. */ 1207 TOUCHLASTCHANGE(&ifp->if_lastchange); 1208 1209 return (0); 1210} 1211 1212errno_t 1213ifnet_stat(struct ifnet *ifp, struct ifnet_stats_param *s) 1214{ 1215 if (ifp == NULL) 1216 return (EINVAL); 1217 1218 atomic_get_64(s->packets_in, &ifp->if_data.ifi_ipackets); 1219 atomic_get_64(s->bytes_in, &ifp->if_data.ifi_ibytes); 1220 atomic_get_64(s->multicasts_in, &ifp->if_data.ifi_imcasts); 1221 atomic_get_64(s->errors_in, &ifp->if_data.ifi_ierrors); 1222 1223 atomic_get_64(s->packets_out, &ifp->if_data.ifi_opackets); 1224 atomic_get_64(s->bytes_out, &ifp->if_data.ifi_obytes); 1225 atomic_get_64(s->multicasts_out, &ifp->if_data.ifi_omcasts); 1226 atomic_get_64(s->errors_out, &ifp->if_data.ifi_oerrors); 1227 1228 atomic_get_64(s->collisions, &ifp->if_data.ifi_collisions); 1229 atomic_get_64(s->dropped, &ifp->if_data.ifi_iqdrops); 1230 atomic_get_64(s->no_protocol, &ifp->if_data.ifi_noproto); 1231 1232 return (0); 1233} 1234 1235errno_t 1236ifnet_touch_lastchange(ifnet_t interface) 1237{ 1238 if (interface == NULL) 1239 return (EINVAL); 1240 1241 TOUCHLASTCHANGE(&interface->if_lastchange); 1242 1243 return (0); 1244} 1245 1246errno_t 1247ifnet_lastchange(ifnet_t interface, struct timeval *last_change) 1248{ 1249 if (interface == NULL) 1250 return (EINVAL); 1251 1252 *last_change = interface->if_data.ifi_lastchange; 1253#if IF_LASTCHANGEUPTIME 1254 /* Crude conversion from uptime to calendar time */ 1255 last_change->tv_sec += boottime_sec(); 1256#endif 1257 return (0); 1258} 1259 1260errno_t 1261ifnet_get_address_list(ifnet_t interface, ifaddr_t **addresses) 1262{ 1263 return (addresses == NULL ? EINVAL : 1264 ifnet_get_address_list_family(interface, addresses, 0)); 1265} 1266 1267struct ifnet_addr_list { 1268 SLIST_ENTRY(ifnet_addr_list) ifal_le; 1269 struct ifaddr *ifal_ifa; 1270}; 1271 1272errno_t 1273ifnet_get_address_list_family(ifnet_t interface, ifaddr_t **addresses, 1274 sa_family_t family) 1275{ 1276 return (ifnet_get_address_list_family_internal(interface, addresses, 1277 family, 0, M_NOWAIT)); 1278} 1279 1280__private_extern__ errno_t 1281ifnet_get_address_list_family_internal(ifnet_t interface, ifaddr_t **addresses, 1282 sa_family_t family, int detached, int how) 1283{ 1284 SLIST_HEAD(, ifnet_addr_list) ifal_head; 1285 struct ifnet_addr_list *ifal, *ifal_tmp; 1286 struct ifnet *ifp; 1287 int count = 0; 1288 errno_t err = 0; 1289 1290 SLIST_INIT(&ifal_head); 1291 1292 if (addresses == NULL) { 1293 err = EINVAL; 1294 goto done; 1295 } 1296 *addresses = NULL; 1297 1298 if (detached) { 1299 /* 1300 * Interface has been detached, so skip the lookup 1301 * at ifnet_head and go directly to inner loop. 1302 */ 1303 ifp = interface; 1304 if (ifp == NULL) { 1305 err = EINVAL; 1306 goto done; 1307 } 1308 goto one; 1309 } 1310 1311 ifnet_head_lock_shared(); 1312 TAILQ_FOREACH(ifp, &ifnet_head, if_link) { 1313 if (interface != NULL && ifp != interface) 1314 continue; 1315one: 1316 ifnet_lock_shared(ifp); 1317 if (interface == NULL || interface == ifp) { 1318 struct ifaddr *ifa; 1319 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 1320 IFA_LOCK(ifa); 1321 if (family != 0 && 1322 ifa->ifa_addr->sa_family != family) { 1323 IFA_UNLOCK(ifa); 1324 continue; 1325 } 1326 MALLOC(ifal, struct ifnet_addr_list *, 1327 sizeof (*ifal), M_TEMP, how); 1328 if (ifal == NULL) { 1329 IFA_UNLOCK(ifa); 1330 ifnet_lock_done(ifp); 1331 if (!detached) 1332 ifnet_head_done(); 1333 err = ENOMEM; 1334 goto done; 1335 } 1336 ifal->ifal_ifa = ifa; 1337 IFA_ADDREF_LOCKED(ifa); 1338 SLIST_INSERT_HEAD(&ifal_head, ifal, ifal_le); 1339 ++count; 1340 IFA_UNLOCK(ifa); 1341 } 1342 } 1343 ifnet_lock_done(ifp); 1344 if (detached) 1345 break; 1346 } 1347 if (!detached) 1348 ifnet_head_done(); 1349 1350 if (count == 0) { 1351 err = ENXIO; 1352 goto done; 1353 } 1354 MALLOC(*addresses, ifaddr_t *, sizeof (ifaddr_t) * (count + 1), 1355 M_TEMP, how); 1356 if (*addresses == NULL) { 1357 err = ENOMEM; 1358 goto done; 1359 } 1360 bzero(*addresses, sizeof (ifaddr_t) * (count + 1)); 1361 1362done: 1363 SLIST_FOREACH_SAFE(ifal, &ifal_head, ifal_le, ifal_tmp) { 1364 SLIST_REMOVE(&ifal_head, ifal, ifnet_addr_list, ifal_le); 1365 if (err == 0) 1366 (*addresses)[--count] = ifal->ifal_ifa; 1367 else 1368 IFA_REMREF(ifal->ifal_ifa); 1369 FREE(ifal, M_TEMP); 1370 } 1371 1372 return (err); 1373} 1374 1375void 1376ifnet_free_address_list(ifaddr_t *addresses) 1377{ 1378 int i; 1379 1380 if (addresses == NULL) 1381 return; 1382 1383 for (i = 0; addresses[i] != NULL; i++) 1384 IFA_REMREF(addresses[i]); 1385 1386 FREE(addresses, M_TEMP); 1387} 1388 1389void * 1390ifnet_lladdr(ifnet_t interface) 1391{ 1392 struct ifaddr *ifa; 1393 void *lladdr; 1394 1395 if (interface == NULL) 1396 return (NULL); 1397 1398 /* 1399 * if_lladdr points to the permanent link address of 1400 * the interface; it never gets deallocated. 1401 */ 1402 ifa = interface->if_lladdr; 1403 IFA_LOCK_SPIN(ifa); 1404 lladdr = LLADDR(SDL((void *)ifa->ifa_addr)); 1405 IFA_UNLOCK(ifa); 1406 1407 return (lladdr); 1408} 1409 1410errno_t 1411ifnet_llbroadcast_copy_bytes(ifnet_t interface, void *addr, size_t buffer_len, 1412 size_t *out_len) 1413{ 1414 if (interface == NULL || addr == NULL || out_len == NULL) 1415 return (EINVAL); 1416 1417 *out_len = interface->if_broadcast.length; 1418 1419 if (buffer_len < interface->if_broadcast.length) 1420 return (EMSGSIZE); 1421 1422 if (interface->if_broadcast.length == 0) 1423 return (ENXIO); 1424 1425 if (interface->if_broadcast.length <= 1426 sizeof (interface->if_broadcast.u.buffer)) { 1427 bcopy(interface->if_broadcast.u.buffer, addr, 1428 interface->if_broadcast.length); 1429 } else { 1430 bcopy(interface->if_broadcast.u.ptr, addr, 1431 interface->if_broadcast.length); 1432 } 1433 1434 return (0); 1435} 1436 1437errno_t 1438ifnet_lladdr_copy_bytes(ifnet_t interface, void *lladdr, size_t lladdr_len) 1439{ 1440 struct sockaddr_dl *sdl; 1441 struct ifaddr *ifa; 1442 1443 if (interface == NULL || lladdr == NULL) 1444 return (EINVAL); 1445 1446 /* 1447 * if_lladdr points to the permanent link address of 1448 * the interface; it never gets deallocated. 1449 */ 1450 ifa = interface->if_lladdr; 1451 IFA_LOCK_SPIN(ifa); 1452 sdl = SDL((void *)ifa->ifa_addr); 1453 if (lladdr_len != sdl->sdl_alen) { 1454 bzero(lladdr, lladdr_len); 1455 IFA_UNLOCK(ifa); 1456 return (EMSGSIZE); 1457 } 1458 bcopy(LLADDR(sdl), lladdr, lladdr_len); 1459 IFA_UNLOCK(ifa); 1460 1461 return (0); 1462} 1463 1464static errno_t 1465ifnet_set_lladdr_internal(ifnet_t interface, const void *lladdr, 1466 size_t lladdr_len, u_char new_type, int apply_type) 1467{ 1468 struct ifaddr *ifa; 1469 errno_t error = 0; 1470 1471 if (interface == NULL) 1472 return (EINVAL); 1473 1474 ifnet_head_lock_shared(); 1475 ifnet_lock_exclusive(interface); 1476 if (lladdr_len != 0 && 1477 (lladdr_len != interface->if_addrlen || lladdr == 0)) { 1478 ifnet_lock_done(interface); 1479 ifnet_head_done(); 1480 return (EINVAL); 1481 } 1482 ifa = ifnet_addrs[interface->if_index - 1]; 1483 if (ifa != NULL) { 1484 struct sockaddr_dl *sdl; 1485 1486 IFA_LOCK_SPIN(ifa); 1487 sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr; 1488 if (lladdr_len != 0) { 1489 bcopy(lladdr, LLADDR(sdl), lladdr_len); 1490 } else { 1491 bzero(LLADDR(sdl), interface->if_addrlen); 1492 } 1493 sdl->sdl_alen = lladdr_len; 1494 1495 if (apply_type) { 1496 sdl->sdl_type = new_type; 1497 } 1498 IFA_UNLOCK(ifa); 1499 } else { 1500 error = ENXIO; 1501 } 1502 ifnet_lock_done(interface); 1503 ifnet_head_done(); 1504 1505 /* Generate a kernel event */ 1506 if (error == 0) { 1507 dlil_post_msg(interface, KEV_DL_SUBCLASS, 1508 KEV_DL_LINK_ADDRESS_CHANGED, NULL, 0); 1509 } 1510 1511 return (error); 1512} 1513 1514errno_t 1515ifnet_set_lladdr(ifnet_t interface, const void* lladdr, size_t lladdr_len) 1516{ 1517 return (ifnet_set_lladdr_internal(interface, lladdr, lladdr_len, 0, 0)); 1518} 1519 1520errno_t 1521ifnet_set_lladdr_and_type(ifnet_t interface, const void* lladdr, 1522 size_t lladdr_len, u_char type) 1523{ 1524 return (ifnet_set_lladdr_internal(interface, lladdr, 1525 lladdr_len, type, 1)); 1526} 1527 1528errno_t 1529ifnet_add_multicast(ifnet_t interface, const struct sockaddr *maddr, 1530 ifmultiaddr_t *ifmap) 1531{ 1532 if (interface == NULL || maddr == NULL) 1533 return (EINVAL); 1534 1535 /* Don't let users screw up protocols' entries. */ 1536 if (maddr->sa_family != AF_UNSPEC && maddr->sa_family != AF_LINK) 1537 return (EINVAL); 1538 1539 return (if_addmulti_anon(interface, maddr, ifmap)); 1540} 1541 1542errno_t 1543ifnet_remove_multicast(ifmultiaddr_t ifma) 1544{ 1545 struct sockaddr *maddr; 1546 1547 if (ifma == NULL) 1548 return (EINVAL); 1549 1550 maddr = ifma->ifma_addr; 1551 /* Don't let users screw up protocols' entries. */ 1552 if (maddr->sa_family != AF_UNSPEC && maddr->sa_family != AF_LINK) 1553 return (EINVAL); 1554 1555 return (if_delmulti_anon(ifma->ifma_ifp, maddr)); 1556} 1557 1558errno_t 1559ifnet_get_multicast_list(ifnet_t ifp, ifmultiaddr_t **addresses) 1560{ 1561 int count = 0; 1562 int cmax = 0; 1563 struct ifmultiaddr *addr; 1564 1565 if (ifp == NULL || addresses == NULL) 1566 return (EINVAL); 1567 1568 ifnet_lock_shared(ifp); 1569 LIST_FOREACH(addr, &ifp->if_multiaddrs, ifma_link) { 1570 cmax++; 1571 } 1572 1573 MALLOC(*addresses, ifmultiaddr_t *, sizeof (ifmultiaddr_t) * (cmax + 1), 1574 M_TEMP, M_NOWAIT); 1575 if (*addresses == NULL) { 1576 ifnet_lock_done(ifp); 1577 return (ENOMEM); 1578 } 1579 1580 LIST_FOREACH(addr, &ifp->if_multiaddrs, ifma_link) { 1581 if (count + 1 > cmax) 1582 break; 1583 (*addresses)[count] = (ifmultiaddr_t)addr; 1584 ifmaddr_reference((*addresses)[count]); 1585 count++; 1586 } 1587 (*addresses)[cmax] = NULL; 1588 ifnet_lock_done(ifp); 1589 1590 return (0); 1591} 1592 1593void 1594ifnet_free_multicast_list(ifmultiaddr_t *addresses) 1595{ 1596 int i; 1597 1598 if (addresses == NULL) 1599 return; 1600 1601 for (i = 0; addresses[i] != NULL; i++) 1602 ifmaddr_release(addresses[i]); 1603 1604 FREE(addresses, M_TEMP); 1605} 1606 1607errno_t 1608ifnet_find_by_name(const char *ifname, ifnet_t *ifpp) 1609{ 1610 struct ifnet *ifp; 1611 int namelen; 1612 1613 if (ifname == NULL) 1614 return (EINVAL); 1615 1616 namelen = strlen(ifname); 1617 1618 *ifpp = NULL; 1619 1620 ifnet_head_lock_shared(); 1621 TAILQ_FOREACH(ifp, &ifnet_head, if_link) { 1622 struct ifaddr *ifa; 1623 struct sockaddr_dl *ll_addr; 1624 1625 ifa = ifnet_addrs[ifp->if_index - 1]; 1626 if (ifa == NULL) 1627 continue; 1628 1629 IFA_LOCK(ifa); 1630 ll_addr = (struct sockaddr_dl *)(void *)ifa->ifa_addr; 1631 1632 if (namelen == ll_addr->sdl_nlen && strncmp(ll_addr->sdl_data, 1633 ifname, ll_addr->sdl_nlen) == 0) { 1634 IFA_UNLOCK(ifa); 1635 *ifpp = ifp; 1636 ifnet_reference(*ifpp); 1637 break; 1638 } 1639 IFA_UNLOCK(ifa); 1640 } 1641 ifnet_head_done(); 1642 1643 return ((ifp == NULL) ? ENXIO : 0); 1644} 1645 1646errno_t 1647ifnet_list_get(ifnet_family_t family, ifnet_t **list, u_int32_t *count) 1648{ 1649 return (ifnet_list_get_common(family, FALSE, list, count)); 1650} 1651 1652__private_extern__ errno_t 1653ifnet_list_get_all(ifnet_family_t family, ifnet_t **list, u_int32_t *count) 1654{ 1655 return (ifnet_list_get_common(family, TRUE, list, count)); 1656} 1657 1658struct ifnet_list { 1659 SLIST_ENTRY(ifnet_list) ifl_le; 1660 struct ifnet *ifl_ifp; 1661}; 1662 1663static errno_t 1664ifnet_list_get_common(ifnet_family_t family, boolean_t get_all, ifnet_t **list, 1665 u_int32_t *count) 1666{ 1667#pragma unused(get_all) 1668 SLIST_HEAD(, ifnet_list) ifl_head; 1669 struct ifnet_list *ifl, *ifl_tmp; 1670 struct ifnet *ifp; 1671 int cnt = 0; 1672 errno_t err = 0; 1673 1674 SLIST_INIT(&ifl_head); 1675 1676 if (list == NULL || count == NULL) { 1677 err = EINVAL; 1678 goto done; 1679 } 1680 *count = 0; 1681 *list = NULL; 1682 1683 ifnet_head_lock_shared(); 1684 TAILQ_FOREACH(ifp, &ifnet_head, if_link) { 1685 if (family == IFNET_FAMILY_ANY || ifp->if_family == family) { 1686 MALLOC(ifl, struct ifnet_list *, sizeof (*ifl), 1687 M_TEMP, M_NOWAIT); 1688 if (ifl == NULL) { 1689 ifnet_head_done(); 1690 err = ENOMEM; 1691 goto done; 1692 } 1693 ifl->ifl_ifp = ifp; 1694 ifnet_reference(ifp); 1695 SLIST_INSERT_HEAD(&ifl_head, ifl, ifl_le); 1696 ++cnt; 1697 } 1698 } 1699 ifnet_head_done(); 1700 1701 if (cnt == 0) { 1702 err = ENXIO; 1703 goto done; 1704 } 1705 1706 MALLOC(*list, ifnet_t *, sizeof (ifnet_t) * (cnt + 1), 1707 M_TEMP, M_NOWAIT); 1708 if (*list == NULL) { 1709 err = ENOMEM; 1710 goto done; 1711 } 1712 bzero(*list, sizeof (ifnet_t) * (cnt + 1)); 1713 *count = cnt; 1714 1715done: 1716 SLIST_FOREACH_SAFE(ifl, &ifl_head, ifl_le, ifl_tmp) { 1717 SLIST_REMOVE(&ifl_head, ifl, ifnet_list, ifl_le); 1718 if (err == 0) 1719 (*list)[--cnt] = ifl->ifl_ifp; 1720 else 1721 ifnet_release(ifl->ifl_ifp); 1722 FREE(ifl, M_TEMP); 1723 } 1724 1725 return (err); 1726} 1727 1728void 1729ifnet_list_free(ifnet_t *interfaces) 1730{ 1731 int i; 1732 1733 if (interfaces == NULL) 1734 return; 1735 1736 for (i = 0; interfaces[i]; i++) 1737 ifnet_release(interfaces[i]); 1738 1739 FREE(interfaces, M_TEMP); 1740} 1741 1742void 1743ifnet_transmit_burst_start(ifnet_t ifp, mbuf_t pkt) 1744{ 1745 uint32_t orig_flags; 1746 1747 if (ifp == NULL || !(pkt->m_flags & M_PKTHDR)) 1748 return; 1749 1750 orig_flags = OSBitOrAtomic(IF_MEASURED_BW_INPROGRESS, 1751 &ifp->if_bw.flags); 1752 if (orig_flags & IF_MEASURED_BW_INPROGRESS) { 1753 /* There is already a measurement in progress; skip this one */ 1754 return; 1755 } 1756 1757 ifp->if_bw.start_seq = pkt->m_pkthdr.pf_mtag.pftag_pktseq; 1758 ifp->if_bw.start_ts = mach_absolute_time(); 1759} 1760 1761void 1762ifnet_transmit_burst_end(ifnet_t ifp, mbuf_t pkt) 1763{ 1764 uint64_t oseq, ots, bytes, ts, t; 1765 uint32_t flags; 1766 1767 if ( ifp == NULL || !(pkt->m_flags & M_PKTHDR)) 1768 return; 1769 1770 flags = OSBitOrAtomic(IF_MEASURED_BW_CALCULATION, &ifp->if_bw.flags); 1771 1772 /* If a calculation is already in progress, just return */ 1773 if (flags & IF_MEASURED_BW_CALCULATION) 1774 return; 1775 1776 /* Check if a measurement was started at all */ 1777 if (!(flags & IF_MEASURED_BW_INPROGRESS)) { 1778 /* 1779 * It is an error to call burst_end before burst_start. 1780 * Reset the calculation flag and return. 1781 */ 1782 goto done; 1783 } 1784 1785 oseq = pkt->m_pkthdr.pf_mtag.pftag_pktseq; 1786 ots = mach_absolute_time(); 1787 1788 if (ifp->if_bw.start_seq > 0 && oseq > ifp->if_bw.start_seq) { 1789 ts = ots - ifp->if_bw.start_ts; 1790 if (ts > 0 ) { 1791 absolutetime_to_nanoseconds(ts, &t); 1792 bytes = oseq - ifp->if_bw.start_seq; 1793 ifp->if_bw.bytes = bytes; 1794 ifp->if_bw.ts = ts; 1795 1796 if (t > 0) { 1797 uint64_t bw = 0; 1798 1799 /* Compute bandwidth as bytes/ms */ 1800 bw = (bytes * NSEC_PER_MSEC) / t; 1801 if (bw > 0) { 1802 if (ifp->if_bw.bw > 0) { 1803 u_int32_t shft; 1804 1805 shft = if_bw_smoothing_val; 1806 /* Compute EWMA of bw */ 1807 ifp->if_bw.bw = (bw + 1808 ((ifp->if_bw.bw << shft) - 1809 ifp->if_bw.bw)) >> shft; 1810 } else { 1811 ifp->if_bw.bw = bw; 1812 } 1813 } 1814 } 1815 ifp->if_bw.last_seq = oseq; 1816 ifp->if_bw.last_ts = ots; 1817 } 1818 } 1819 1820done: 1821 flags = ~(IF_MEASURED_BW_INPROGRESS | IF_MEASURED_BW_CALCULATION); 1822 OSBitAndAtomic(flags, &ifp->if_bw.flags); 1823} 1824 1825/****************************************************************************/ 1826/* ifaddr_t accessors */ 1827/****************************************************************************/ 1828 1829errno_t 1830ifaddr_reference(ifaddr_t ifa) 1831{ 1832 if (ifa == NULL) 1833 return (EINVAL); 1834 1835 IFA_ADDREF(ifa); 1836 return (0); 1837} 1838 1839errno_t 1840ifaddr_release(ifaddr_t ifa) 1841{ 1842 if (ifa == NULL) 1843 return (EINVAL); 1844 1845 IFA_REMREF(ifa); 1846 return (0); 1847} 1848 1849sa_family_t 1850ifaddr_address_family(ifaddr_t ifa) 1851{ 1852 sa_family_t family = 0; 1853 1854 if (ifa != NULL) { 1855 IFA_LOCK_SPIN(ifa); 1856 if (ifa->ifa_addr != NULL) 1857 family = ifa->ifa_addr->sa_family; 1858 IFA_UNLOCK(ifa); 1859 } 1860 return (family); 1861} 1862 1863errno_t 1864ifaddr_address(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size) 1865{ 1866 u_int32_t copylen; 1867 1868 if (ifa == NULL || out_addr == NULL) 1869 return (EINVAL); 1870 1871 IFA_LOCK_SPIN(ifa); 1872 if (ifa->ifa_addr == NULL) { 1873 IFA_UNLOCK(ifa); 1874 return (ENOTSUP); 1875 } 1876 1877 copylen = (addr_size >= ifa->ifa_addr->sa_len) ? 1878 ifa->ifa_addr->sa_len : addr_size; 1879 bcopy(ifa->ifa_addr, out_addr, copylen); 1880 1881 if (ifa->ifa_addr->sa_len > addr_size) { 1882 IFA_UNLOCK(ifa); 1883 return (EMSGSIZE); 1884 } 1885 1886 IFA_UNLOCK(ifa); 1887 return (0); 1888} 1889 1890errno_t 1891ifaddr_dstaddress(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size) 1892{ 1893 u_int32_t copylen; 1894 1895 if (ifa == NULL || out_addr == NULL) 1896 return (EINVAL); 1897 1898 IFA_LOCK_SPIN(ifa); 1899 if (ifa->ifa_dstaddr == NULL) { 1900 IFA_UNLOCK(ifa); 1901 return (ENOTSUP); 1902 } 1903 1904 copylen = (addr_size >= ifa->ifa_dstaddr->sa_len) ? 1905 ifa->ifa_dstaddr->sa_len : addr_size; 1906 bcopy(ifa->ifa_dstaddr, out_addr, copylen); 1907 1908 if (ifa->ifa_dstaddr->sa_len > addr_size) { 1909 IFA_UNLOCK(ifa); 1910 return (EMSGSIZE); 1911 } 1912 1913 IFA_UNLOCK(ifa); 1914 return (0); 1915} 1916 1917errno_t 1918ifaddr_netmask(ifaddr_t ifa, struct sockaddr *out_addr, u_int32_t addr_size) 1919{ 1920 u_int32_t copylen; 1921 1922 if (ifa == NULL || out_addr == NULL) 1923 return (EINVAL); 1924 1925 IFA_LOCK_SPIN(ifa); 1926 if (ifa->ifa_netmask == NULL) { 1927 IFA_UNLOCK(ifa); 1928 return (ENOTSUP); 1929 } 1930 1931 copylen = addr_size >= ifa->ifa_netmask->sa_len ? 1932 ifa->ifa_netmask->sa_len : addr_size; 1933 bcopy(ifa->ifa_netmask, out_addr, copylen); 1934 1935 if (ifa->ifa_netmask->sa_len > addr_size) { 1936 IFA_UNLOCK(ifa); 1937 return (EMSGSIZE); 1938 } 1939 1940 IFA_UNLOCK(ifa); 1941 return (0); 1942} 1943 1944ifnet_t 1945ifaddr_ifnet(ifaddr_t ifa) 1946{ 1947 struct ifnet *ifp; 1948 1949 if (ifa == NULL) 1950 return (NULL); 1951 1952 /* ifa_ifp is set once at creation time; it is never changed */ 1953 ifp = ifa->ifa_ifp; 1954 1955 return (ifp); 1956} 1957 1958ifaddr_t 1959ifaddr_withaddr(const struct sockaddr *address) 1960{ 1961 if (address == NULL) 1962 return (NULL); 1963 1964 return (ifa_ifwithaddr(address)); 1965} 1966 1967ifaddr_t 1968ifaddr_withdstaddr(const struct sockaddr *address) 1969{ 1970 if (address == NULL) 1971 return (NULL); 1972 1973 return (ifa_ifwithdstaddr(address)); 1974} 1975 1976ifaddr_t 1977ifaddr_withnet(const struct sockaddr *net) 1978{ 1979 if (net == NULL) 1980 return (NULL); 1981 1982 return (ifa_ifwithnet(net)); 1983} 1984 1985ifaddr_t 1986ifaddr_withroute(int flags, const struct sockaddr *destination, 1987 const struct sockaddr *gateway) 1988{ 1989 if (destination == NULL || gateway == NULL) 1990 return (NULL); 1991 1992 return (ifa_ifwithroute(flags, destination, gateway)); 1993} 1994 1995ifaddr_t 1996ifaddr_findbestforaddr(const struct sockaddr *addr, ifnet_t interface) 1997{ 1998 if (addr == NULL || interface == NULL) 1999 return (NULL); 2000 2001 return (ifaof_ifpforaddr(addr, interface)); 2002} 2003 2004errno_t 2005ifmaddr_reference(ifmultiaddr_t ifmaddr) 2006{ 2007 if (ifmaddr == NULL) 2008 return (EINVAL); 2009 2010 IFMA_ADDREF(ifmaddr); 2011 return (0); 2012} 2013 2014errno_t 2015ifmaddr_release(ifmultiaddr_t ifmaddr) 2016{ 2017 if (ifmaddr == NULL) 2018 return (EINVAL); 2019 2020 IFMA_REMREF(ifmaddr); 2021 return (0); 2022} 2023 2024errno_t 2025ifmaddr_address(ifmultiaddr_t ifma, struct sockaddr *out_addr, 2026 u_int32_t addr_size) 2027{ 2028 u_int32_t copylen; 2029 2030 if (ifma == NULL || out_addr == NULL) 2031 return (EINVAL); 2032 2033 IFMA_LOCK(ifma); 2034 if (ifma->ifma_addr == NULL) { 2035 IFMA_UNLOCK(ifma); 2036 return (ENOTSUP); 2037 } 2038 2039 copylen = (addr_size >= ifma->ifma_addr->sa_len ? 2040 ifma->ifma_addr->sa_len : addr_size); 2041 bcopy(ifma->ifma_addr, out_addr, copylen); 2042 2043 if (ifma->ifma_addr->sa_len > addr_size) { 2044 IFMA_UNLOCK(ifma); 2045 return (EMSGSIZE); 2046 } 2047 IFMA_UNLOCK(ifma); 2048 return (0); 2049} 2050 2051errno_t 2052ifmaddr_lladdress(ifmultiaddr_t ifma, struct sockaddr *out_addr, 2053 u_int32_t addr_size) 2054{ 2055 struct ifmultiaddr *ifma_ll; 2056 2057 if (ifma == NULL || out_addr == NULL) 2058 return (EINVAL); 2059 if ((ifma_ll = ifma->ifma_ll) == NULL) 2060 return (ENOTSUP); 2061 2062 return (ifmaddr_address(ifma_ll, out_addr, addr_size)); 2063} 2064 2065ifnet_t 2066ifmaddr_ifnet(ifmultiaddr_t ifma) 2067{ 2068 return ((ifma == NULL) ? NULL : ifma->ifma_ifp); 2069} 2070 2071/******************************************************************************/ 2072/* interface cloner */ 2073/******************************************************************************/ 2074 2075errno_t 2076ifnet_clone_attach(struct ifnet_clone_params *cloner_params, 2077 if_clone_t *ifcloner) 2078{ 2079 errno_t error = 0; 2080 struct if_clone *ifc = NULL; 2081 size_t namelen; 2082 2083 if (cloner_params == NULL || ifcloner == NULL || 2084 cloner_params->ifc_name == NULL || 2085 cloner_params->ifc_create == NULL || 2086 cloner_params->ifc_destroy == NULL || 2087 (namelen = strlen(cloner_params->ifc_name)) >= IFNAMSIZ) { 2088 error = EINVAL; 2089 goto fail; 2090 } 2091 2092 if (if_clone_lookup(cloner_params->ifc_name, NULL) != NULL) { 2093 printf("%s: already a cloner for %s\n", __func__, 2094 cloner_params->ifc_name); 2095 error = EEXIST; 2096 goto fail; 2097 } 2098 2099 /* Make room for name string */ 2100 ifc = _MALLOC(sizeof (struct if_clone) + IFNAMSIZ + 1, M_CLONE, 2101 M_WAITOK | M_ZERO); 2102 if (ifc == NULL) { 2103 printf("%s: _MALLOC failed\n", __func__); 2104 error = ENOBUFS; 2105 goto fail; 2106 } 2107 strlcpy((char *)(ifc + 1), cloner_params->ifc_name, IFNAMSIZ + 1); 2108 ifc->ifc_name = (char *)(ifc + 1); 2109 ifc->ifc_namelen = namelen; 2110 ifc->ifc_maxunit = IF_MAXUNIT; 2111 ifc->ifc_create = cloner_params->ifc_create; 2112 ifc->ifc_destroy = cloner_params->ifc_destroy; 2113 2114 error = if_clone_attach(ifc); 2115 if (error != 0) { 2116 printf("%s: if_clone_attach failed %d\n", __func__, error); 2117 goto fail; 2118 } 2119 *ifcloner = ifc; 2120 2121 return (0); 2122fail: 2123 if (ifc != NULL) 2124 FREE(ifc, M_CLONE); 2125 return (error); 2126} 2127 2128errno_t 2129ifnet_clone_detach(if_clone_t ifcloner) 2130{ 2131 errno_t error = 0; 2132 struct if_clone *ifc = ifcloner; 2133 2134 if (ifc == NULL || ifc->ifc_name == NULL) 2135 return (EINVAL); 2136 2137 if ((if_clone_lookup(ifc->ifc_name, NULL)) == NULL) { 2138 printf("%s: no cloner for %s\n", __func__, ifc->ifc_name); 2139 error = EINVAL; 2140 goto fail; 2141 } 2142 2143 if_clone_detach(ifc); 2144 2145 FREE(ifc, M_CLONE); 2146 2147fail: 2148 return (error); 2149} 2150 2151/******************************************************************************/ 2152/* misc */ 2153/******************************************************************************/ 2154 2155extern void udp_get_ports_used(unsigned int ifindex, uint8_t *bitfield); 2156extern void tcp_get_ports_used(unsigned int ifindex, uint8_t *bitfield); 2157 2158errno_t 2159ifnet_get_local_ports(ifnet_t ifp, uint8_t *bitfield) 2160{ 2161 if (bitfield == NULL) 2162 return (EINVAL); 2163 2164 bzero(bitfield, 8192); 2165 2166 udp_get_ports_used(ifp ? ifp->if_index : 0, bitfield); 2167 tcp_get_ports_used(ifp ? ifp->if_index : 0, bitfield); 2168 2169 return (0); 2170} 2171 2172errno_t 2173ifnet_notice_node_presence(ifnet_t ifp, struct sockaddr* sa, int32_t rssi, 2174 int lqm, int npm, u_int8_t srvinfo[48]) 2175{ 2176 if (ifp == NULL || sa == NULL || srvinfo == NULL) 2177 return(EINVAL); 2178 if (sa->sa_len > sizeof(struct sockaddr_storage)) 2179 return(EINVAL); 2180 if (sa->sa_family != AF_LINK && sa->sa_family != AF_INET6) 2181 return(EINVAL); 2182 2183 dlil_node_present(ifp, sa, rssi, lqm, npm, srvinfo); 2184 return (0); 2185} 2186 2187errno_t 2188ifnet_notice_node_absence(ifnet_t ifp, struct sockaddr* sa) 2189{ 2190 if (ifp == NULL || sa == NULL) 2191 return(EINVAL); 2192 if (sa->sa_len > sizeof(struct sockaddr_storage)) 2193 return(EINVAL); 2194 if (sa->sa_family != AF_LINK && sa->sa_family != AF_INET6) 2195 return(EINVAL); 2196 2197 dlil_node_absent(ifp, sa); 2198 return (0); 2199} 2200 2201errno_t 2202ifnet_notice_master_elected(ifnet_t ifp) 2203{ 2204 if (ifp == NULL) 2205 return(EINVAL); 2206 2207 dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_MASTER_ELECTED, NULL, 0); 2208 return (0); 2209} 2210