/* * Copyright (c) 2000-2012 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* $FreeBSD: src/sys/netinet6/nd6.h,v 1.2.2.3 2001/08/13 01:10:49 simokawa Exp $ */ /* $KAME: nd6.h,v 1.55 2001/04/27 15:09:49 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _NETINET6_ND6_H_ #define _NETINET6_ND6_H_ #include /* see net/route.h, or net/if_inarp.h */ #ifndef RTF_ANNOUNCE #define RTF_ANNOUNCE RTF_PROTO2 #endif #include #ifdef XNU_KERNEL_PRIVATE #include #include #include struct llinfo_nd6 { /* * The following are protected by rnh_lock */ struct llinfo_nd6 *ln_next; struct llinfo_nd6 *ln_prev; struct rtentry *ln_rt; /* * The following are protected by rt_lock */ struct mbuf *ln_hold; /* last packet until resolved/timeout */ long ln_asked; /* number of queries already sent for this addr */ u_int32_t ln_expire; /* lifetime for NDP state transition */ short ln_state; /* reachability state */ short ln_router; /* 2^0: ND6 router bit */ int ln_byhint; /* # of times we made it reachable by UL hint */ u_int32_t ln_flags; /* flags; see below */ struct if_llreach *ln_llreach; /* link-layer reachability record */ u_int64_t ln_lastused; /* last used timestamp */ }; /* Values for ln_flags */ #define ND6_LNF_TIMER_SKIP 0x1 /* modified by nd6_timer() */ #define ND6_LNF_IN_USE 0x2 /* currently in llinfo_nd6 list */ #endif /* XNU_KERNEL_PRIVATE */ #define ND6_LLINFO_PURGE -3 #define ND6_LLINFO_NOSTATE -2 /* * We don't need the WAITDELETE state any more, but we keep the definition * in a comment line instead of removing it. This is necessary to avoid * unintentionally reusing the value for another purpose, which might * affect backward compatibility with old applications. * (20000711 jinmei@kame.net) */ /* #define ND6_LLINFO_WAITDELETE -1 */ #define ND6_LLINFO_INCOMPLETE 0 #define ND6_LLINFO_REACHABLE 1 #define ND6_LLINFO_STALE 2 #define ND6_LLINFO_DELAY 3 #define ND6_LLINFO_PROBE 4 #ifdef XNU_KERNEL_PRIVATE #define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE) #define ND6_LLINFO_PERMANENT(n) (((n)->ln_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE)) #define ND6_EUI64_GBIT 0x01 #define ND6_EUI64_UBIT 0x02 #define ND6_EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= ND6_EUI64_UBIT; } while (0) #define ND6_EUI64_GROUP(in6) ((in6)->s6_addr[8] & ND6_EUI64_GBIT) #define ND6_EUI64_INDIVIDUAL(in6) (!ND6_EUI64_GROUP(in6)) #define ND6_EUI64_LOCAL(in6) ((in6)->s6_addr[8] & ND6_EUI64_UBIT) #define ND6_EUI64_UNIVERSAL(in6) (!ND6_EUI64_LOCAL(in6)) #define ND6_IFID_LOCAL(in6) (!ND6_EUI64_LOCAL(in6)) #define ND6_IFID_UNIVERSAL(in6) (!ND6_EUI64_UNIVERSAL(in6)) #endif /* XNU_KERNEL_PRIVATE */ #if !defined(XNU_KERNEL_PRIVATE) struct nd_ifinfo { #else /* For binary compatibility, this structure must not change */ struct nd_ifinfo_compat { #endif /* !XNU_KERNEL_PRIVATE */ u_int32_t linkmtu; /* LinkMTU */ u_int32_t maxmtu; /* Upper bound of LinkMTU */ u_int32_t basereachable; /* BaseReachableTime */ u_int32_t reachable; /* Reachable Time */ u_int32_t retrans; /* Retrans Timer */ u_int32_t flags; /* Flags */ int recalctm; /* BaseReacable re-calculation timer */ u_int8_t chlim; /* CurHopLimit */ u_int8_t receivedra; /* the following 3 members are for privacy extension for addrconf */ u_int8_t randomseed0[8]; /* upper 64 bits of SHA1 digest */ u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */ u_int8_t randomid[8]; /* current random ID */ }; #if defined(XNU_KERNEL_PRIVATE) struct nd_ifinfo { decl_lck_mtx_data(, lock); boolean_t initialized; /* Flag to see the entry is initialized */ u_int32_t linkmtu; /* LinkMTU */ u_int32_t maxmtu; /* Upper bound of LinkMTU */ u_int32_t basereachable; /* BaseReachableTime */ u_int32_t reachable; /* Reachable Time */ u_int32_t retrans; /* Retrans Timer */ u_int32_t flags; /* Flags */ int recalctm; /* BaseReacable re-calculation timer */ u_int8_t chlim; /* CurHopLimit */ u_int8_t _pad[3]; /* the following 3 members are for privacy extension for addrconf */ u_int8_t randomseed0[8]; /* upper 64 bits of SHA1 digest */ u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */ u_int8_t randomid[8]; /* current random ID */ /* keep track of routers and prefixes on this link */ int32_t nprefixes; int32_t ndefrouters; }; #endif /* XNU_KERNEL_PRIVATE */ #define ND6_IFF_PERFORMNUD 0x1 #if defined(PRIVATE) #define ND6_IFF_ACCEPT_RTADV 0x2 /* APPLE: not used. Innterface specific router * advertisments are handled with a specific ifnet * flag: IFEF_ACCEPT_RTADVD */ #define ND6_IFF_PREFER_SOURCE 0x4 /* APPLE: NOT USED not related to ND. */ #define ND6_IFF_IFDISABLED 0x8 /* IPv6 operation is disabled due to * DAD failure. (XXX: not ND-specific) */ #define ND6_IFF_DONT_SET_IFROUTE 0x10 /* NOT USED */ #endif /* PRIVATE */ #define ND6_IFF_PROXY_PREFIXES 0x20 #define ND6_IFF_IGNORE_NA 0x40 struct in6_nbrinfo { char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */ struct in6_addr addr; /* IPv6 address of the neighbor */ long asked; /* number of queries already sent for this addr */ int isrouter; /* if it acts as a router */ int state; /* reachability state */ int expire; /* lifetime for NDP state transition */ }; #if defined(XNU_KERNEL_PRIVATE) struct in6_nbrinfo_32 { char ifname[IFNAMSIZ]; struct in6_addr addr; u_int32_t asked; int isrouter; int state; int expire; }; struct in6_nbrinfo_64 { char ifname[IFNAMSIZ]; struct in6_addr addr; long asked; int isrouter __attribute__((aligned(8))); int state; int expire; } __attribute__((aligned(8))); #endif /* XNU_KERNEL_PRIVATE */ #define DRLSTSIZ 10 #define PRLSTSIZ 10 struct in6_drlist { char ifname[IFNAMSIZ]; struct { struct in6_addr rtaddr; u_char flags; u_short rtlifetime; u_long expire; u_short if_index; } defrouter[DRLSTSIZ]; }; #if defined(XNU_KERNEL_PRIVATE) struct in6_drlist_32 { char ifname[IFNAMSIZ]; struct { struct in6_addr rtaddr; u_char flags; u_short rtlifetime; u_int32_t expire; u_short if_index; } defrouter[DRLSTSIZ]; }; struct in6_drlist_64 { char ifname[IFNAMSIZ]; struct { struct in6_addr rtaddr; u_char flags; u_short rtlifetime; u_long expire __attribute__((aligned(8))); u_short if_index __attribute__((aligned(8))); } defrouter[DRLSTSIZ] __attribute__((aligned(8))); }; #endif /* XNU_KERNEL_PRIVATE */ /* valid values for stateflags */ #define NDDRF_INSTALLED 0x1 /* installed in the routing table */ #define NDDRF_IFSCOPE 0x2 /* installed as a scoped route */ #define NDDRF_STATIC 0x4 /* for internal use only */ #ifdef XNU_KERNEL_PRIVATE #define NDDRF_PROCESSED 0x10 #endif struct in6_defrouter { struct sockaddr_in6 rtaddr; u_char flags; u_char stateflags; u_short rtlifetime; u_long expire; u_short if_index; }; #if defined(XNU_KERNEL_PRIVATE) struct in6_defrouter_32 { struct sockaddr_in6 rtaddr; u_char flags; u_char stateflags; u_short rtlifetime; u_int32_t expire; u_short if_index; }; struct in6_defrouter_64 { struct sockaddr_in6 rtaddr; u_char flags; u_char stateflags; u_short rtlifetime; u_long expire __attribute__((aligned(8))); u_short if_index __attribute__((aligned(8))); } __attribute__((aligned(8))); #endif /* XNU_KERNEL_PRIVATE */ struct in6_prlist { char ifname[IFNAMSIZ]; struct { struct in6_addr prefix; struct prf_ra raflags; u_char prefixlen; u_char origin; u_long vltime; u_long pltime; u_long expire; u_short if_index; u_short advrtrs; /* number of advertisement routers */ struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */ } prefix[PRLSTSIZ]; }; #if defined(XNU_KERNEL_PRIVATE) struct in6_prlist_32 { char ifname[IFNAMSIZ]; struct { struct in6_addr prefix; struct prf_ra raflags; u_char prefixlen; u_char origin; u_int32_t vltime; u_int32_t pltime; u_int32_t expire; u_short if_index; u_short advrtrs; struct in6_addr advrtr[DRLSTSIZ]; } prefix[PRLSTSIZ]; }; struct in6_prlist_64 { char ifname[IFNAMSIZ]; struct { struct in6_addr prefix; struct prf_ra raflags; u_char prefixlen; u_char origin; u_long vltime __attribute__((aligned(8))); u_long pltime __attribute__((aligned(8))); u_long expire __attribute__((aligned(8))); u_short if_index; u_short advrtrs; u_int32_t pad; struct in6_addr advrtr[DRLSTSIZ]; } prefix[PRLSTSIZ]; }; #endif /* XNU_KERNEL_PRIVATE */ struct in6_prefix { struct sockaddr_in6 prefix; struct prf_ra raflags; u_char prefixlen; u_char origin; u_long vltime; u_long pltime; u_long expire; u_int32_t flags; int refcnt; u_short if_index; u_short advrtrs; /* number of advertisement routers */ /* struct sockaddr_in6 advrtr[] */ }; #if defined(XNU_KERNEL_PRIVATE) struct in6_prefix_32 { struct sockaddr_in6 prefix; struct prf_ra raflags; u_char prefixlen; u_char origin; u_int32_t vltime; u_int32_t pltime; u_int32_t expire; u_int32_t flags; int refcnt; u_short if_index; u_short advrtrs; /* number of advertisement routers */ /* struct sockaddr_in6 advrtr[] */ }; struct in6_prefix_64 { struct sockaddr_in6 prefix; struct prf_ra raflags; u_char prefixlen; u_char origin; u_long vltime __attribute__((aligned(8))); u_long pltime __attribute__((aligned(8))); u_long expire __attribute__((aligned(8))); u_int32_t flags __attribute__((aligned(8))); int refcnt; u_short if_index; u_short advrtrs; /* struct sockaddr_in6 advrtr[] */ }; #endif /* XNU_KERNEL_PRIVATE */ struct in6_ondireq { char ifname[IFNAMSIZ]; struct { u_int32_t linkmtu; /* LinkMTU */ u_int32_t maxmtu; /* Upper bound of LinkMTU */ u_int32_t basereachable; /* BaseReachableTime */ u_int32_t reachable; /* Reachable Time */ u_int32_t retrans; /* Retrans Timer */ u_int32_t flags; /* Flags */ int recalctm; /* BaseReacable re-calculation timer */ u_int8_t chlim; /* CurHopLimit */ u_int8_t receivedra; } ndi; }; #if !defined(XNU_KERNEL_PRIVATE) struct in6_ndireq { char ifname[IFNAMSIZ]; struct nd_ifinfo ndi; }; #else struct in6_ndireq { char ifname[IFNAMSIZ]; struct nd_ifinfo_compat ndi; }; #endif /* !XNU_KERNEL_PRIVATE */ struct in6_ndifreq { char ifname[IFNAMSIZ]; u_long ifindex; }; #define MAX_RTR_SOLICITATION_DELAY 1 /* 1sec */ #define RTR_SOLICITATION_INTERVAL 4 /* 4sec */ #if defined(XNU_KERNEL_PRIVATE) struct in6_ndifreq_32 { char ifname[IFNAMSIZ]; u_int32_t ifindex; }; struct in6_ndifreq_64 { char ifname[IFNAMSIZ]; u_long ifindex __attribute__((aligned(8))); }; #endif /* XNU_KERNEL_PRIVATE */ /* Prefix status */ #define NDPRF_ONLINK 0x1 #define NDPRF_DETACHED 0x2 #define NDPRF_STATIC 0x100 #define NDPRF_IFSCOPE 0x1000 #define NDPRF_PRPROXY 0x2000 #ifdef XNU_KERNEL_PRIVATE #define NDPRF_PROCESSED 0x08000 #endif /* protocol constants */ #define MAX_RTR_SOLICITATION_DELAY 1 /*1sec*/ #define RTR_SOLICITATION_INTERVAL 4 /*4sec*/ #define MAX_RTR_SOLICITATIONS 3 #define ND6_INFINITE_LIFETIME 0xffffffff #define ND6_MAX_LIFETIME 0x7fffffff #ifdef XNU_KERNEL_PRIVATE /* * Protects nd_ifinfo[] */ __private_extern__ lck_rw_t *nd_if_rwlock; #define ND_IFINFO(ifp) \ ((ifp)->if_index < nd_ifinfo_indexlim ? &nd_ifinfo[(ifp)->if_index] : NULL) /* * In a more readable form, we derive linkmtu based on: * * if (ND_IFINFO(ifp) == NULL || !ND_IFINFO(ifp)->initialized) * linkmtu = ifp->if_mtu; * else if (ND_IFINFO(ifp)->linkmtu && ND_IFINFO(ifp)->linkmtu < ifp->if_mtu) * linkmtu = ND_IFINFO(ifp)->linkmtu; * else if ((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < ifp->if_mtu)) * linkmtu = ND_IFINFO(ifp)->maxmtu; * else * linkmtu = ifp->if_mtu; */ #define IN6_LINKMTU(ifp) \ ((ND_IFINFO(ifp) == NULL || !ND_IFINFO(ifp)->initialized) ? \ (ifp)->if_mtu : ((ND_IFINFO(ifp)->linkmtu && \ ND_IFINFO(ifp)->linkmtu < (ifp)->if_mtu) ? ND_IFINFO(ifp)->linkmtu : \ ((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < (ifp)->if_mtu) ? \ ND_IFINFO(ifp)->maxmtu : (ifp)->if_mtu))) /* node constants */ #define MAX_REACHABLE_TIME 3600000 /* msec */ #define REACHABLE_TIME 30000 /* msec */ #define RETRANS_TIMER 1000 /* msec */ #define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */ #define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */ #define DEF_TEMP_VALID_LIFETIME 604800 /* 1 week */ #define DEF_TEMP_PREFERRED_LIFETIME 86400 /* 1 day */ #define TEMPADDR_REGEN_ADVANCE 5 /* sec */ #define MAX_TEMP_DESYNC_FACTOR 600 /* 10 min */ #define ND_COMPUTE_RTIME(x) \ (((MIN_RANDOM_FACTOR * (x >> 10)) + (random() & \ ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000) TAILQ_HEAD(nd_drhead, nd_defrouter); struct nd_defrouter { decl_lck_mtx_data(, nddr_lock); uint32_t nddr_refcount; uint32_t nddr_debug; TAILQ_ENTRY(nd_defrouter) dr_entry; struct in6_addr rtaddr; u_char flags; /* flags on RA message */ u_char stateflags; u_short rtlifetime; u_int32_t expire; struct ifnet *ifp; unsigned int genid; int err; void (*nddr_trace) /* callback fn for tracing refs */ (struct nd_defrouter *, int); }; #define NDDR_LOCK_ASSERT_HELD(_nddr) \ lck_mtx_assert(&(_nddr)->nddr_lock, LCK_MTX_ASSERT_OWNED) #define NDDR_LOCK_ASSERT_NOTHELD(_nddr) \ lck_mtx_assert(&(_nddr)->nddr_lock, LCK_MTX_ASSERT_NOTOWNED) #define NDDR_LOCK(_nddr) \ lck_mtx_lock(&(_nddr)->nddr_lock) #define NDDR_LOCK_SPIN(_nddr) \ lck_mtx_lock_spin(&(_nddr)->nddr_lock) #define NDDR_CONVERT_LOCK(_nddr) do { \ NDPR_LOCK_ASSERT_HELD(_nddr); \ lck_mtx_convert_spin(&(_nddr)->nddr_lock); \ } while (0) #define NDDR_UNLOCK(_nddr) \ lck_mtx_unlock(&(_nddr)->nddr_lock) #define NDDR_ADDREF(_nddr) \ nddr_addref(_nddr, 0) #define NDDR_ADDREF_LOCKED(_nddr) \ nddr_addref(_nddr, 1) #define NDDR_REMREF(_nddr) do { \ (void) nddr_remref(_nddr, 0); \ } while (0) #define NDDR_REMREF_LOCKED(_nddr) \ nddr_remref(_nddr, 1) /* define struct prproxy_sols_tree */ RB_HEAD(prproxy_sols_tree, nd6_prproxy_soltgt); struct nd_prefix { decl_lck_mtx_data(, ndpr_lock); u_int32_t ndpr_refcount; /* reference count */ u_int32_t ndpr_debug; /* see ifa_debug flags */ struct ifnet *ndpr_ifp; struct rtentry *ndpr_rt; LIST_ENTRY(nd_prefix) ndpr_entry; struct sockaddr_in6 ndpr_prefix; /* prefix */ struct in6_addr ndpr_mask; /* netmask derived from the prefix */ struct in6_addr ndpr_addr; /* address that is derived from the prefix */ u_int32_t ndpr_vltime; /* advertised valid lifetime */ u_int32_t ndpr_pltime; /* advertised preferred lifetime */ time_t ndpr_preferred; /* preferred time of the prefix */ time_t ndpr_expire; /* expiration time of the prefix */ time_t ndpr_lastupdate; /* reception time of last advertisement */ struct prf_ra ndpr_flags; u_int32_t ndpr_stateflags; /* actual state flags */ /* list of routers that advertise the prefix: */ LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs; u_char ndpr_plen; int ndpr_addrcnt; /* reference counter from addresses */ u_int32_t ndpr_allmulti_cnt; /* total all-multi reqs */ u_int32_t ndpr_prproxy_sols_cnt; /* total # of proxied NS */ struct prproxy_sols_tree ndpr_prproxy_sols; /* tree of proxied NS */ void (*ndpr_trace) /* callback fn for tracing refs */ (struct nd_prefix *, int); }; #define ndpr_next ndpr_entry.le_next #define ndpr_raf ndpr_flags #define ndpr_raf_onlink ndpr_flags.onlink #define ndpr_raf_auto ndpr_flags.autonomous #define ndpr_raf_router ndpr_flags.router /* * We keep expired prefix for certain amount of time, for validation purposes. * 1800s = MaxRtrAdvInterval */ #define NDPR_KEEP_EXPIRED (1800 * 2) #define NDPR_LOCK_ASSERT_HELD(_ndpr) \ lck_mtx_assert(&(_ndpr)->ndpr_lock, LCK_MTX_ASSERT_OWNED) #define NDPR_LOCK_ASSERT_NOTHELD(_ndpr) \ lck_mtx_assert(&(_ndpr)->ndpr_lock, LCK_MTX_ASSERT_NOTOWNED) #define NDPR_LOCK(_ndpr) \ lck_mtx_lock(&(_ndpr)->ndpr_lock) #define NDPR_LOCK_SPIN(_ndpr) \ lck_mtx_lock_spin(&(_ndpr)->ndpr_lock) #define NDPR_CONVERT_LOCK(_ndpr) do { \ NDPR_LOCK_ASSERT_HELD(_ndpr); \ lck_mtx_convert_spin(&(_ndpr)->ndpr_lock); \ } while (0) #define NDPR_UNLOCK(_ndpr) \ lck_mtx_unlock(&(_ndpr)->ndpr_lock) #define NDPR_ADDREF(_ndpr) \ ndpr_addref(_ndpr, 0) #define NDPR_ADDREF_LOCKED(_ndpr) \ ndpr_addref(_ndpr, 1) #define NDPR_REMREF(_ndpr) do { \ (void) ndpr_remref(_ndpr, 0); \ } while (0) #define NDPR_REMREF_LOCKED(_ndpr) \ ndpr_remref(_ndpr, 1) /* * Message format for use in obtaining information about prefixes * from inet6 sysctl function */ struct inet6_ndpr_msghdr { u_short inpm_msglen; /* to skip over non-understood messages */ u_char inpm_version; /* future binary compatibility */ u_char inpm_type; /* message type */ struct in6_addr inpm_prefix; u_int32_t prm_vltim; u_int32_t prm_pltime; u_int32_t prm_expire; u_int32_t prm_preferred; struct in6_prflags prm_flags; u_short prm_index; /* index for associated ifp */ u_char prm_plen; /* length of prefix in bits */ }; #define prm_raf_onlink prm_flags.prf_ra.onlink #define prm_raf_auto prm_flags.prf_ra.autonomous #define prm_statef_onlink prm_flags.prf_state.onlink #define prm_rrf_decrvalid prm_flags.prf_rr.decrvalid #define prm_rrf_decrprefd prm_flags.prf_rr.decrprefd #define ifpr2ndpr(ifpr) ((struct nd_prefix *)(ifpr)) #define ndpr2ifpr(ndpr) ((struct ifprefix *)(ndpr)) struct nd_pfxrouter { LIST_ENTRY(nd_pfxrouter) pfr_entry; #define pfr_next pfr_entry.le_next struct nd_defrouter *router; }; LIST_HEAD(nd_prhead, nd_prefix); struct nd_prefix_list { struct nd_prefix_list *next; struct nd_prefix pr; }; #endif /* XNU_KERNEL_PRIVATE */ #if defined(PRIVATE) /* ND6 kernel event subclass value */ #define KEV_ND6_SUBCLASS 7 /* ND6 kernel event action type */ #define KEV_ND6_RA 1 /* ND6 RA L2 source address length */ #define ND6_ROUTER_LL_SIZE 64 struct nd6_ra_prefix { struct sockaddr_in6 prefix; struct prf_ra raflags; u_int32_t prefixlen; u_int32_t origin; u_int64_t vltime; u_int64_t pltime; u_int64_t expire; u_int32_t flags; u_int32_t refcnt; u_int32_t if_index; u_int32_t pad; }; /* ND6 router advertisement valid bits */ #define KEV_ND6_DATA_VALID_MTU (0x1 << 0) #define KEV_ND6_DATA_VALID_PREFIX (0x1 << 1) struct kev_nd6_ra_data { u_int8_t lladdr[ND6_ROUTER_LL_SIZE]; u_int32_t lladdrlen; u_int32_t mtu; u_int32_t list_index; u_int32_t list_length; u_int32_t flags; struct nd6_ra_prefix prefix; u_int32_t pad; }; #endif /* PRIVATE */ #if defined(XNU_KERNEL_PRIVATE) /* nd6.c */ extern int nd6_prune; extern int nd6_delay; extern int nd6_umaxtries; extern int nd6_mmaxtries; extern int nd6_useloopback; extern int nd6_accept_6to4; extern int nd6_maxnudhint; extern int nd6_gctimer; extern struct llinfo_nd6 llinfo_nd6; extern struct nd_ifinfo *nd_ifinfo; extern struct nd_drhead nd_defrouter; extern struct nd_prhead nd_prefix; extern int nd6_debug; extern size_t nd_ifinfo_indexlim; extern int nd6_onlink_ns_rfc4861; extern int nd6_optimistic_dad; #define nd6log(x) do { if (nd6_debug >= 1) log x; } while (0) #define nd6log2(x) do { if (nd6_debug >= 2) log x; } while (0) #define ND6_OPTIMISTIC_DAD_LINKLOCAL (1 << 0) #define ND6_OPTIMISTIC_DAD_AUTOCONF (1 << 1) #define ND6_OPTIMISTIC_DAD_TEMPORARY (1 << 2) #define ND6_OPTIMISTIC_DAD_DYNAMIC (1 << 3) /* nd6_rtr.c */ extern int nd6_defifindex; extern int ip6_desync_factor; /* seconds */ /* ND6_INFINITE_LIFETIME does not apply to temporary addresses */ extern u_int32_t ip6_temp_preferred_lifetime; /* seconds */ extern u_int32_t ip6_temp_valid_lifetime; /* seconds */ extern int ip6_temp_regen_advance; /* seconds */ union nd_opts { struct nd_opt_hdr *nd_opt_array[8]; /* max = target address list */ struct { struct nd_opt_hdr *zero; struct nd_opt_hdr *src_lladdr; struct nd_opt_hdr *tgt_lladdr; struct nd_opt_prefix_info *pi_beg; /* multiple opts, start */ struct nd_opt_rd_hdr *rh; struct nd_opt_mtu *mtu; struct nd_opt_hdr *search; /* multiple opts */ struct nd_opt_hdr *last; /* multiple opts */ int done; struct nd_opt_prefix_info *pi_end;/* multiple opts, end */ } nd_opt_each; }; #define nd_opts_src_lladdr nd_opt_each.src_lladdr #define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr #define nd_opts_pi nd_opt_each.pi_beg #define nd_opts_pi_end nd_opt_each.pi_end #define nd_opts_rh nd_opt_each.rh #define nd_opts_mtu nd_opt_each.mtu #define nd_opts_search nd_opt_each.search #define nd_opts_last nd_opt_each.last #define nd_opts_done nd_opt_each.done /* XXX: need nd6_var.h?? */ /* nd6.c */ extern void nd6_init(void); extern int nd6_ifattach(struct ifnet *); extern int nd6_is_addr_neighbor(struct sockaddr_in6 *, struct ifnet *, int); extern void nd6_option_init(void *, int, union nd_opts *); extern struct nd_opt_hdr *nd6_option(union nd_opts *); extern int nd6_options(union nd_opts *); extern struct rtentry *nd6_lookup(struct in6_addr *, int, struct ifnet *, int); extern void nd6_setmtu(struct ifnet *); extern void nd6_timer(void *); extern void nd6_purge(struct ifnet *); extern void nd6_free(struct rtentry *); extern void nd6_nud_hint(struct rtentry *, struct in6_addr *, int); extern int nd6_resolve(struct ifnet *, struct rtentry *, struct mbuf *, struct sockaddr *, u_char *); extern void nd6_rtrequest(int, struct rtentry *, struct sockaddr *); extern int nd6_ioctl(u_long, caddr_t, struct ifnet *); extern void nd6_cache_lladdr(struct ifnet *, struct in6_addr *, char *, int, int, int); extern int nd6_output(struct ifnet *, struct ifnet *, struct mbuf *, struct sockaddr_in6 *, struct rtentry *, struct flowadv *); extern int nd6_storelladdr(struct ifnet *, struct rtentry *, struct mbuf *, struct sockaddr *, u_char *); extern int nd6_need_cache(struct ifnet *); extern void nd6_drain(void *); extern void nd6_post_msg(u_int32_t, struct nd_prefix_list *, u_int32_t, u_int32_t, char *, u_int32_t); extern int nd6_setifinfo(struct ifnet *, u_int32_t, u_int32_t); /* nd6_nbr.c */ extern void nd6_nbr_init(void); extern void nd6_na_input(struct mbuf *, int, int); extern void nd6_na_output(struct ifnet *, const struct in6_addr *, const struct in6_addr *, u_int32_t, int, struct sockaddr *); extern void nd6_ns_input(struct mbuf *, int, int); extern void nd6_ns_output(struct ifnet *, const struct in6_addr *, const struct in6_addr *, struct llinfo_nd6 *, int); extern caddr_t nd6_ifptomac(struct ifnet *); extern void nd6_dad_start(struct ifaddr *, int *); extern void nd6_dad_stop(struct ifaddr *); extern void nd6_dad_duplicated(struct ifaddr *, boolean_t); extern void nd6_llreach_alloc(struct rtentry *, struct ifnet *, void *, unsigned int, boolean_t); extern void nd6_llreach_set_reachable(struct ifnet *, void *, unsigned int); extern void nd6_llreach_use(struct llinfo_nd6 *); extern void nd6_alt_node_addr_decompose(struct ifnet *, struct sockaddr *, struct sockaddr_dl *, struct sockaddr_in6 *); extern void nd6_alt_node_present(struct ifnet *, struct sockaddr_in6 *, struct sockaddr_dl *, int32_t, int, int); extern void nd6_alt_node_absent(struct ifnet *, struct sockaddr_in6 *); /* nd6_rtr.c */ extern void nd6_rtr_init(void); extern void nd6_rs_input(struct mbuf *, int, int); extern void nd6_ra_input(struct mbuf *, int, int); extern void prelist_del(struct nd_prefix *); extern void defrouter_select(struct ifnet *); extern void defrouter_reset(void); extern int defrtrlist_ioctl(u_long, caddr_t); extern void defrtrlist_del(struct nd_defrouter *); extern int defrtrlist_add_static(struct nd_defrouter *); extern int defrtrlist_del_static(struct nd_defrouter *); extern void prelist_remove(struct nd_prefix *); extern int prelist_update(struct nd_prefix *, struct nd_defrouter *, struct mbuf *, int); extern int nd6_prelist_add(struct nd_prefix *, struct nd_defrouter *, struct nd_prefix **, boolean_t); extern int nd6_prefix_onlink(struct nd_prefix *); extern int nd6_prefix_onlink_scoped(struct nd_prefix *, unsigned int); extern int nd6_prefix_offlink(struct nd_prefix *); extern void pfxlist_onlink_check(void); extern struct nd_defrouter *defrouter_lookup(struct in6_addr *, struct ifnet *); extern struct nd_prefix *nd6_prefix_lookup(struct nd_prefix *); extern int in6_init_prefix_ltimes(struct nd_prefix *ndpr); extern void rt6_flush(struct in6_addr *, struct ifnet *); extern int nd6_setdefaultiface(int); extern int in6_tmpifadd(const struct in6_ifaddr *, int, int); extern void nddr_addref(struct nd_defrouter *, int); extern struct nd_defrouter *nddr_remref(struct nd_defrouter *, int); extern void ndpr_addref(struct nd_prefix *, int); extern struct nd_prefix *ndpr_remref(struct nd_prefix *, int); /* nd6_prproxy.c */ struct ip6_hdr; extern u_int32_t nd6_prproxy; extern void nd6_prproxy_init(void); extern int nd6_if_prproxy(struct ifnet *, boolean_t); extern void nd6_prproxy_prelist_update(struct nd_prefix *, struct nd_prefix *); extern boolean_t nd6_prproxy_ifaddr(struct in6_ifaddr *); extern boolean_t nd6_prproxy_isours(struct mbuf *, struct ip6_hdr *, struct route_in6 *, unsigned int); extern void nd6_prproxy_ns_output(struct ifnet *, struct in6_addr *, struct in6_addr *, struct llinfo_nd6 *); extern void nd6_prproxy_ns_input(struct ifnet *, struct in6_addr *, char *, int, struct in6_addr *, struct in6_addr *); extern void nd6_prproxy_na_input(struct ifnet *, struct in6_addr *, struct in6_addr *, struct in6_addr *, int); extern void nd6_prproxy_sols_reap(struct nd_prefix *); extern void nd6_prproxy_sols_prune(struct nd_prefix *, u_int32_t); #endif /* XNU_KERNEL_PRIVATE */ #ifdef KERNEL /*! @function nd6_lookup_ipv6 @discussion This function will check the routing table for a cached neighbor discovery entry or trigger an neighbor discovery query to resolve the IPv6 address to a link-layer address. nd entries are stored in the routing table. This function will lookup the IPv6 destination in the routing table. If the destination requires forwarding to a gateway, the route of the gateway will be looked up. The route entry is inspected to determine if the link layer destination address is known. If unknown, neighbor discovery will be used to resolve the entry. @param interface The interface the packet is being sent on. @param ip6_dest The IPv6 destination of the packet. @param ll_dest On output, the link-layer destination. @param ll_dest_len The length of the buffer for ll_dest. @param hint Any routing hint passed down from the protocol. @param packet The packet being transmitted. @result May return an error such as EHOSTDOWN or ENETUNREACH. If this function returns EJUSTRETURN, the packet has been queued and will be sent when the address is resolved. If any other value is returned, the caller is responsible for disposing of the packet. */ extern errno_t nd6_lookup_ipv6(ifnet_t interface, const struct sockaddr_in6 *ip6_dest, struct sockaddr_dl *ll_dest, size_t ll_dest_len, route_t hint, mbuf_t packet); #endif /* KERNEL */ #endif /* _NETINET6_ND6_H_ */