+/*
+ * Indicate whether or not the immediate interface, or the interface delegated
+ * by it, is an ETHERNET interface.
+ */
+#define IFNET_IS_ETHERNET(_ifp) \
+ ((_ifp)->if_family == IFNET_FAMILY_ETHERNET || \
+ (_ifp)->if_delegated.family == IFNET_FAMILY_ETHERNET)
+/*
+ * Indicate whether or not the immediate interface, or the interface delegated
+ * by it, is a Wi-Fi interface (IFNET_SUBFAMILY_WIFI). Delegated interface
+ * subfamily is set/cleared along with the delegated ifp; we cache the subfamily
+ * for performance to avoid dereferencing delegated ifp each time.
+ *
+ * Note that this is meant to be used only for accounting and policy purposes;
+ * certain places need to explicitly know the immediate interface type, and
+ * this macro should not be used there.
+ *
+ * The test is done against IFNET_SUBFAMILY_WIFI as the family may be set to
+ * IFNET_FAMILY_ETHERNET (as well as type to IFT_ETHER) which is too generic.
+ */
+#define IFNET_IS_WIFI(_ifp) \
+ ((_ifp)->if_subfamily == IFNET_SUBFAMILY_WIFI || \
+ (_ifp)->if_delegated.subfamily == IFNET_SUBFAMILY_WIFI)
+
+/*
+ * Indicate whether or not the immediate interface, or the interface delegated
+ * by it, is a Wired interface (several families). Delegated interface
+ * family is set/cleared along with the delegated ifp; we cache the family
+ * for performance to avoid dereferencing delegated ifp each time.
+ *
+ * Note that this is meant to be used only for accounting and policy purposes;
+ * certain places need to explicitly know the immediate interface type, and
+ * this macro should not be used there.
+ */
+#define IFNET_IS_WIRED(_ifp) \
+ ((_ifp)->if_family == IFNET_FAMILY_ETHERNET || \
+ (_ifp)->if_delegated.family == IFNET_FAMILY_ETHERNET || \
+ (_ifp)->if_family == IFNET_FAMILY_FIREWIRE || \
+ (_ifp)->if_delegated.family == IFNET_FAMILY_FIREWIRE)
+
+/*
+ * Indicate whether or not the immediate WiFi interface is on an infrastructure
+ * network
+ */
+#define IFNET_IS_WIFI_INFRA(_ifp) \
+ ((_ifp)->if_family == IFNET_FAMILY_ETHERNET && \
+ (_ifp)->if_subfamily == IFNET_SUBFAMILY_WIFI && \
+ !((_ifp)->if_eflags & IFEF_AWDL))
+
+/*
+ * Indicate whether or not the immediate interface, or the interface delegated
+ * by it, is marked as expensive. The delegated interface is set/cleared
+ * along with the delegated ifp; we cache the flag for performance to avoid
+ * dereferencing delegated ifp each time.
+ *
+ * Note that this is meant to be used only for policy purposes.
+ */
+#define IFNET_IS_EXPENSIVE(_ifp) \
+ ((_ifp)->if_eflags & IFEF_EXPENSIVE || \
+ (_ifp)->if_delegated.expensive)
+
+/*
+ * We don't support AWDL interface delegation.
+ */
+#define IFNET_IS_AWDL_RESTRICTED(_ifp) \
+ (((_ifp)->if_eflags & (IFEF_AWDL|IFEF_AWDL_RESTRICTED)) == \
+ (IFEF_AWDL|IFEF_AWDL_RESTRICTED))
+
+#define IFNET_IS_INTCOPROC(_ifp) \
+ ((_ifp)->if_family == IFNET_FAMILY_ETHERNET && \
+ (_ifp)->if_subfamily == IFNET_SUBFAMILY_INTCOPROC)
+
+extern struct ifnethead ifnet_head;
+extern struct ifnethead ifnet_ordered_head;
+extern struct ifnet **ifindex2ifnet;
+extern u_int32_t if_sndq_maxlen;
+extern u_int32_t if_rcvq_maxlen;
+extern int if_index;
+extern struct ifaddr **ifnet_addrs;
+extern lck_attr_t *ifa_mtx_attr;
+extern lck_grp_t *ifa_mtx_grp;
+extern lck_grp_t *ifnet_lock_group;
+extern lck_attr_t *ifnet_lock_attr;
+extern ifnet_t lo_ifp;
+
+extern int if_addmulti(struct ifnet *, const struct sockaddr *,
+ struct ifmultiaddr **);
+extern int if_addmulti_anon(struct ifnet *, const struct sockaddr *,
+ struct ifmultiaddr **);
+extern int if_allmulti(struct ifnet *, int);
+extern int if_delmulti(struct ifnet *, const struct sockaddr *);
+extern int if_delmulti_ifma(struct ifmultiaddr *);
+extern int if_delmulti_anon(struct ifnet *, const struct sockaddr *);
+extern void if_down(struct ifnet *);
+extern int if_down_all(void);
+extern void if_up(struct ifnet *);
+__private_extern__ void if_updown(struct ifnet *ifp, int up);
+extern int ifioctl(struct socket *, u_long, caddr_t, struct proc *);
+extern int ifioctllocked(struct socket *, u_long, caddr_t, struct proc *);
+extern struct ifnet *ifunit(const char *);
+extern struct ifnet *ifunit_ref(const char *);
+extern int ifunit_extract(const char *src, char *dst, size_t dstlen, int *unit);
+extern struct ifnet *if_withname(struct sockaddr *);
+extern void if_qflush(struct ifnet *, int);
+extern void if_qflush_sc(struct ifnet *, mbuf_svc_class_t, u_int32_t,
+ u_int32_t *, u_int32_t *, int);
+
+extern struct if_clone *if_clone_lookup(const char *, u_int32_t *);
+extern int if_clone_attach(struct if_clone *);
+extern void if_clone_detach(struct if_clone *);
+
+extern u_int32_t if_functional_type(struct ifnet *, bool);
+
+extern errno_t if_mcasts_update(struct ifnet *);
+
+typedef enum {
+ IFNET_LCK_ASSERT_EXCLUSIVE, /* RW: held as writer */
+ IFNET_LCK_ASSERT_SHARED, /* RW: held as reader */
+ IFNET_LCK_ASSERT_OWNED, /* RW: writer/reader, MTX: held */
+ IFNET_LCK_ASSERT_NOTOWNED /* not held */
+} ifnet_lock_assert_t;
+
+#define IF_LLADDR(_ifp) \
+ (LLADDR(SDL(((_ifp)->if_lladdr)->ifa_addr)))
+
+#define IF_INDEX_IN_RANGE(_ind_) ((_ind_) > 0 && \
+ (unsigned int)(_ind_) <= (unsigned int)if_index)
+
+__private_extern__ void ifnet_lock_assert(struct ifnet *, ifnet_lock_assert_t);
+__private_extern__ void ifnet_lock_shared(struct ifnet *ifp);
+__private_extern__ void ifnet_lock_exclusive(struct ifnet *ifp);
+__private_extern__ void ifnet_lock_done(struct ifnet *ifp);
+
+#if INET
+__private_extern__ void if_inetdata_lock_shared(struct ifnet *ifp);
+__private_extern__ void if_inetdata_lock_exclusive(struct ifnet *ifp);
+__private_extern__ void if_inetdata_lock_done(struct ifnet *ifp);
+#endif
+
+#if INET6
+__private_extern__ void if_inet6data_lock_shared(struct ifnet *ifp);
+__private_extern__ void if_inet6data_lock_exclusive(struct ifnet *ifp);
+__private_extern__ void if_inet6data_lock_done(struct ifnet *ifp);
+#endif
+
+__private_extern__ void ifnet_head_lock_shared(void);
+__private_extern__ void ifnet_head_lock_exclusive(void);
+__private_extern__ void ifnet_head_done(void);
+__private_extern__ void ifnet_head_assert_exclusive(void);
+
+__private_extern__ errno_t ifnet_set_idle_flags_locked(ifnet_t, u_int32_t,
+ u_int32_t);
+__private_extern__ int ifnet_is_attached(struct ifnet *, int refio);
+__private_extern__ void ifnet_incr_iorefcnt(struct ifnet *);
+__private_extern__ void ifnet_decr_iorefcnt(struct ifnet *);
+__private_extern__ void ifnet_set_start_cycle(struct ifnet *,
+ struct timespec *);
+__private_extern__ void ifnet_set_poll_cycle(struct ifnet *,
+ struct timespec *);
+
+__private_extern__ void if_attach_ifa(struct ifnet *, struct ifaddr *);
+__private_extern__ void if_attach_link_ifa(struct ifnet *, struct ifaddr *);
+__private_extern__ void if_detach_ifa(struct ifnet *, struct ifaddr *);
+__private_extern__ void if_detach_link_ifa(struct ifnet *, struct ifaddr *);
+
+__private_extern__ void dlil_if_lock(void);
+__private_extern__ void dlil_if_unlock(void);
+__private_extern__ void dlil_if_lock_assert(void);
+
+extern struct ifaddr *ifa_ifwithaddr(const struct sockaddr *);
+extern struct ifaddr *ifa_ifwithaddr_locked(const struct sockaddr *);
+extern struct ifaddr *ifa_ifwithaddr_scoped(const struct sockaddr *,
+ unsigned int);
+extern struct ifaddr *ifa_ifwithaddr_scoped_locked(const struct sockaddr *,
+ unsigned int);
+extern struct ifaddr *ifa_ifwithdstaddr(const struct sockaddr *);
+extern struct ifaddr *ifa_ifwithnet(const struct sockaddr *);
+extern struct ifaddr *ifa_ifwithnet_scoped(const struct sockaddr *,
+ unsigned int);
+extern struct ifaddr *ifa_ifwithroute(int, const struct sockaddr *,
+ const struct sockaddr *);
+extern struct ifaddr *ifa_ifwithroute_locked(int, const struct sockaddr *,
+ const struct sockaddr *);
+extern struct ifaddr *ifa_ifwithroute_scoped_locked(int,
+ const struct sockaddr *, const struct sockaddr *, unsigned int);
+extern struct ifaddr *ifaof_ifpforaddr_select(const struct sockaddr *, struct ifnet *);
+extern struct ifaddr *ifaof_ifpforaddr(const struct sockaddr *, struct ifnet *);
+__private_extern__ struct ifaddr *ifa_ifpgetprimary(struct ifnet *, int);
+extern void ifa_addref(struct ifaddr *, int);
+extern struct ifaddr *ifa_remref(struct ifaddr *, int);
+extern void ifa_lock_init(struct ifaddr *);
+extern void ifa_lock_destroy(struct ifaddr *);
+extern void ifma_addref(struct ifmultiaddr *, int);
+extern void ifma_remref(struct ifmultiaddr *);
+
+extern void ifa_init(void);
+
+__private_extern__ struct in_ifaddr *ifa_foraddr(unsigned int);
+__private_extern__ struct in_ifaddr *ifa_foraddr_scoped(unsigned int,
+ unsigned int);
+
+struct ifreq;
+extern errno_t ifnet_getset_opportunistic(struct ifnet *, u_long,
+ struct ifreq *, struct proc *);
+extern int ifnet_get_throttle(struct ifnet *, u_int32_t *);
+extern int ifnet_set_throttle(struct ifnet *, u_int32_t);
+extern errno_t ifnet_getset_log(struct ifnet *, u_long,
+ struct ifreq *, struct proc *);
+extern int ifnet_set_log(struct ifnet *, int32_t, uint32_t, int32_t, int32_t);
+extern int ifnet_get_log(struct ifnet *, int32_t *, uint32_t *, int32_t *,
+ int32_t *);
+extern int ifnet_notify_address(struct ifnet *, int);
+extern void ifnet_notify_data_threshold(struct ifnet *);
+
+#define IF_AFDATA_RLOCK if_afdata_rlock
+#define IF_AFDATA_RUNLOCK if_afdata_unlock
+#define IF_AFDATA_WLOCK if_afdata_wlock
+#define IF_AFDATA_WUNLOCK if_afdata_unlock
+#define IF_AFDATA_WLOCK_ASSERT if_afdata_wlock_assert
+#define IF_AFDATA_LOCK_ASSERT if_afdata_lock_assert
+#define IF_AFDATA_UNLOCK_ASSERT if_afdata_unlock_assert
+
+static inline void
+if_afdata_rlock (struct ifnet *ifp, int af)
+{
+ switch (af) {
+#if INET
+ case AF_INET:
+ lck_rw_lock_shared(&ifp->if_inetdata_lock);
+ break;
+#endif
+#if INET6
+ case AF_INET6:
+ lck_rw_lock_shared(&ifp->if_inet6data_lock);
+ break;
+#endif
+ default:
+ VERIFY(0);
+ /* NOTREACHED */
+ }
+ return;
+}
+
+static inline void
+if_afdata_runlock (struct ifnet *ifp, int af)
+{
+ switch (af) {
+#if INET
+ case AF_INET:
+ lck_rw_done(&ifp->if_inetdata_lock);
+ break;
+#endif
+#if INET6
+ case AF_INET6:
+ lck_rw_done(&ifp->if_inet6data_lock);
+ break;
+#endif
+ default:
+ VERIFY(0);
+ /* NOTREACHED */
+ }
+ return;
+}
+
+static inline void
+if_afdata_wlock (struct ifnet *ifp, int af)
+{
+ switch (af) {
+#if INET
+ case AF_INET:
+ lck_rw_lock_exclusive(&ifp->if_inetdata_lock);
+ break;
+#endif
+#if INET6
+ case AF_INET6:
+ lck_rw_lock_exclusive(&ifp->if_inet6data_lock);
+ break;
+#endif
+ default:
+ VERIFY(0);
+ /* NOTREACHED */
+ }
+ return;
+}
+
+static inline void
+if_afdata_unlock (struct ifnet *ifp, int af)
+{
+ switch (af) {
+#if INET
+ case AF_INET:
+ lck_rw_done(&ifp->if_inetdata_lock);
+ break;
+#endif
+#if INET6
+ case AF_INET6:
+ lck_rw_done(&ifp->if_inet6data_lock);
+ break;
+#endif
+ default:
+ VERIFY(0);
+ /* NOTREACHED */
+ }
+ return;
+}
+
+static inline void
+if_afdata_wlock_assert (struct ifnet *ifp, int af)
+{
+#if !MACH_ASSERT
+#pragma unused(ifp)
+#endif
+ switch (af) {
+#if INET
+ case AF_INET:
+ LCK_RW_ASSERT(&ifp->if_inetdata_lock, LCK_RW_ASSERT_EXCLUSIVE);
+ break;
+#endif
+#if INET6
+ case AF_INET6:
+ LCK_RW_ASSERT(&ifp->if_inet6data_lock, LCK_RW_ASSERT_EXCLUSIVE);
+ break;
+#endif
+ default:
+ VERIFY(0);
+ /* NOTREACHED */
+ }
+ return;
+}
+
+static inline void
+if_afdata_unlock_assert (struct ifnet *ifp, int af)
+{
+#if !MACH_ASSERT
+#pragma unused(ifp)
+#endif
+ switch (af) {
+#if INET
+ case AF_INET:
+ LCK_RW_ASSERT(&ifp->if_inetdata_lock, LCK_RW_ASSERT_NOTHELD);
+ break;
+#endif
+#if INET6
+ case AF_INET6:
+ LCK_RW_ASSERT(&ifp->if_inet6data_lock, LCK_RW_ASSERT_NOTHELD);
+ break;
+#endif
+ default:
+ VERIFY(0);
+ /* NOTREACHED */
+ }
+ return;
+}
+
+static inline void
+if_afdata_lock_assert (struct ifnet *ifp, int af)
+{
+#if !MACH_ASSERT
+#pragma unused(ifp)
+#endif
+ switch (af) {
+#if INET
+ case AF_INET:
+ LCK_RW_ASSERT(&ifp->if_inetdata_lock, LCK_RW_ASSERT_HELD);
+ break;
+#endif
+#if INET6
+ case AF_INET6:
+ LCK_RW_ASSERT(&ifp->if_inet6data_lock, LCK_RW_ASSERT_HELD);
+ break;
+#endif
+ default:
+ VERIFY(0);
+ /* NOTREACHED */
+ }
+ return;
+}
+
+#if INET6
+struct in6_addr;
+__private_extern__ struct in6_ifaddr *ifa_foraddr6(struct in6_addr *);
+__private_extern__ struct in6_ifaddr *ifa_foraddr6_scoped(struct in6_addr *,
+ unsigned int);
+#endif /* INET6 */
+
+__private_extern__ void if_data_internal_to_if_data(struct ifnet *ifp,
+ const struct if_data_internal *if_data_int, struct if_data *if_data);
+__private_extern__ void if_data_internal_to_if_data64(struct ifnet *ifp,
+ const struct if_data_internal *if_data_int, struct if_data64 *if_data64);
+__private_extern__ void if_copy_traffic_class(struct ifnet *ifp,
+ struct if_traffic_class *if_tc);
+__private_extern__ void if_copy_data_extended(struct ifnet *ifp,
+ struct if_data_extended *if_de);
+__private_extern__ void if_copy_packet_stats(struct ifnet *ifp,
+ struct if_packet_stats *if_ps);
+__private_extern__ void if_copy_rxpoll_stats(struct ifnet *ifp,
+ struct if_rxpoll_stats *if_rs);
+
+__private_extern__ struct rtentry *ifnet_cached_rtlookup_inet(struct ifnet *,
+ struct in_addr);
+#if INET6
+__private_extern__ struct rtentry *ifnet_cached_rtlookup_inet6(struct ifnet *,
+ struct in6_addr *);
+#endif /* INET6 */
+
+__private_extern__ u_int32_t if_get_protolist(struct ifnet * ifp,
+ u_int32_t *protolist, u_int32_t count);
+__private_extern__ void if_free_protolist(u_int32_t *list);
+__private_extern__ errno_t if_state_update(struct ifnet *,
+ struct if_interface_state *);
+__private_extern__ void if_get_state(struct ifnet *,
+ struct if_interface_state *);
+__private_extern__ errno_t if_probe_connectivity(struct ifnet *ifp,
+ u_int32_t conn_probe);
+__private_extern__ void if_lqm_update(struct ifnet *, int32_t, int);
+__private_extern__ void ifnet_update_sndq(struct ifclassq *, cqev_t);
+__private_extern__ void ifnet_update_rcv(struct ifnet *, cqev_t);
+
+__private_extern__ void ifnet_flowadv(uint32_t);
+
+__private_extern__ errno_t ifnet_set_input_bandwidths(struct ifnet *,
+ struct if_bandwidths *);
+__private_extern__ errno_t ifnet_set_output_bandwidths(struct ifnet *,
+ struct if_bandwidths *, boolean_t);
+__private_extern__ u_int64_t ifnet_output_linkrate(struct ifnet *);
+__private_extern__ u_int64_t ifnet_input_linkrate(struct ifnet *);
+
+__private_extern__ errno_t ifnet_set_input_latencies(struct ifnet *,
+ struct if_latencies *);
+__private_extern__ errno_t ifnet_set_output_latencies(struct ifnet *,
+ struct if_latencies *, boolean_t);
+
+__private_extern__ void ifnet_clear_netagent(uuid_t);
+
+__private_extern__ int ifnet_set_netsignature(struct ifnet *, uint8_t,
+ uint8_t, uint16_t, uint8_t *);
+__private_extern__ int ifnet_get_netsignature(struct ifnet *, uint8_t,
+ uint8_t *, uint16_t *, uint8_t *);
+
+#if INET6
+struct ipv6_prefix;
+__private_extern__ int ifnet_set_nat64prefix(struct ifnet *,
+ struct ipv6_prefix *);
+__private_extern__ int ifnet_get_nat64prefix(struct ifnet *,
+ struct ipv6_prefix *);
+#endif
+
+/* Required exclusive ifnet_head lock */
+__private_extern__ void ifnet_remove_from_ordered_list(struct ifnet *);
+
+__private_extern__ void ifnet_increment_generation(struct ifnet *);
+__private_extern__ u_int32_t ifnet_get_generation(struct ifnet *);
+
+/* Adding and deleting netagents will take ifnet lock */
+__private_extern__ int if_add_netagent(struct ifnet *, uuid_t);
+__private_extern__ int if_delete_netagent(struct ifnet *, uuid_t);
+__private_extern__ boolean_t if_check_netagent(struct ifnet *, uuid_t);
+
+
+extern int if_set_qosmarking_mode(struct ifnet *, u_int32_t);
+__private_extern__ uint32_t ifnet_mbuf_packetpreamblelen(struct ifnet *);
+__private_extern__ void intf_event_enqueue_nwk_wq_entry(struct ifnet *ifp,
+ struct sockaddr *addrp, uint32_t intf_event_code);
+__private_extern__ void ifnet_update_stats_per_flow(struct ifnet_stats_per_flow *,
+ struct ifnet *);
+#if !CONFIG_EMBEDDED
+__private_extern__ errno_t ifnet_framer_stub(struct ifnet *, struct mbuf **,
+ const struct sockaddr *, const char *, const char *, u_int32_t *,
+ u_int32_t *);
+#endif /* !CONFIG_EMBEDDED */
+__private_extern__ void ifnet_enqueue_multi_setup(struct ifnet *, uint16_t,
+ uint16_t);
+__private_extern__ errno_t ifnet_enqueue_mbuf(struct ifnet *, struct mbuf *,
+ boolean_t, boolean_t *);