/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos72L src/bos/kernext/inet/in6_var.h 1.33.1.2 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* Restricted Materials of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 1997,2018 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ /* @(#)14 1.33.1.2 src/bos/kernext/inet/in6_var.h, sockinc, bos72L, l2018_11B8 2/28/18 09:37:59 */ /* $NetBSD: in_var.h,v 1.8 1994/06/29 06:38:13 cgd Exp $ */ /* * Copyright (c) 1985, 1986, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 _NETINET_IN6_VAR_H_ #define _NETINET_IN6_VAR_H_ #include #include #include /* Defect 786019 */ #ifndef CONST #define CONST const #endif extern struct domain inet6domain; extern CONST struct protosw inet6sw[]; /* We start with the hash chain infrastructure to manipulte * the interface address structure linked list as an array * of hashed entries */ struct in6ifaddr_hash { struct in6ifaddr_hash *next; struct in6ifaddr_hash *prev; }; #define ia6hashtoinifaddr(hp) \ (struct in6_ifaddr *)((char *)(hp) - offsetof(struct in6_ifaddr, ia_hash)) #define in6ifaddrtohash(ia) (&(ia->ia_hash)) #define IN6IFADDR_HASHSZ 59 #define IN6IFADDR_HASH(addr) ((addr) % IN6IFADDR_HASHSZ) struct in6ifaddr_hash_table { struct in6ifaddr_hash head; }; extern struct in6ifaddr_hash_table in6ifaddr_hash_table[IN6IFADDR_HASHSZ]; /* Hash table chain head lock */ #if defined(_KERNEL) extern DRW_lock *in6ifaddr_hashchn_lock[IN6IFADDR_HASHSZ]; #endif #define NET_CACHELINESIZE 128 /* * Including net_globals.h (where NET_CACHELINESIZE is defined) breaks nfs. * Hence we redefine NET_CACHELINESIZE here. These should be kept consistent. * This is also defined in route.h, in_var.h & in_pbc.h (because of build breaks * encountered when included through net_globals.h). */ /* * Interface address, IPv6 version. One of these structures * is allocated for each interface with an IPv6 address. * The ifaddr structure contains the protocol-independent part * of the structure and is assumed to be first. */ struct in6_ifaddr { struct ifaddr ia_ifa; /* protocol-independent info */ #define ia_ifp ia_ifa.ifa_ifp #define ia_flags ia_ifa.ifa_flags TAILQ_ENTRY(in6_ifaddr) ia_list; /* list of IPv6 addresses */ struct sockaddr_in6 ia_addr; /* space for interface name */ struct sockaddr_in6 ia_dstaddr; /* space for broadcast addr */ struct sockaddr_in6 ia_sockmask; /* space for general netmask */ struct in6ifaddr_hash ia_hash; /* hash links */ cid_t ia_kcid; /* kernel corral id */ caddr_t send_if_common; /* The SEND keys and necessary data */ u_short ia_type; /* type of address (i.e. temporary RFC3041) */ #define IAT_TEMP 0x1 /* temporary address RFC 3041 */ #define IAT_CGA 0x2 /* CGA address RFC 3972 */ u_short ia_state; /* autoconfiguration state of address */ #define IAS_PREFERRED 0 /* preferred address (default) */ #define IAS_DEPRECATED 1 /* deprecated address */ #define IAS_INVALID 2 /* invalid address */ u_short in6_flags; /* Address source flag */ #define IN6FLAG_OTHER 0x0001 /* Source of adr is unknown */ #define IN6FLAG_AUTOCONF6 0x0002 /* Source of addr is autoconf6 */ #define IN6FLAG_NDPDHOST 0x0004 /* Source of addr is ndpd-host */ #define IN6FLAG_IFCONFIG 0x0008 /* Source of addr is ifconfig */ }; struct in6_aliasreq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr_in6 ifra_addr; struct sockaddr_in6 ifra_dstaddr; struct sockaddr_in6 ifra_mask; }; #ifdef PHABRE1 struct in6_clustreq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr_in6 ifra_addr; struct sockaddr_in6 ifra_dstaddr; struct sockaddr_in6 ifra_mask; u_short ifra_flags; }; #endif /* PHABRE1 */ struct in6_aliasreq2 { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr_in6 ifra_addr; struct sockaddr_in6 ifra_dstaddr; struct sockaddr_in6 ifra_mask; union { u_short ifra_type; u_short ifra_state; u_short ifra_origin; /* Addr source flag */ } ifra_attr; #define ifra_type ifra_attr.ifra_type #define ifra_state ifra_attr.ifra_state #define ifra_origin ifra_attr.ifra_origin }; /* in the sin6_flowinfo field of ifra_addr for SIOCAIFADDR6 */ #define IN6_ADDR_TENTATIVE 0xffffffff struct in6_ifreq { char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr_in6 ifr_Addr; }; struct in6_ifreq2 { char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr_in6 ifr_Addr; union { u_short ifr_type; u_short ifr_state; } ifr_attr; #define ifr_type ifr_attr.ifr_type #define ifr_state ifr_attr.ifr_state }; struct in6_zonereq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ uint32_t ifrz_scope; #ifndef ADDR6_NUMSCOPES /* possibly already defined if in.h is included */ #define ADDR6_NUMSCOPES 16 /* number of IPv6 scopes */ #endif uint32_t ifrz_zone[ADDR6_NUMSCOPES]; }; /* * Structure for for SIOCSIFADDRORI6 ioctl */ struct ifaddrorigin6 { char ifro_name[IFNAMSIZ]; struct sockaddr_in6 ifro_addr; int ifro_origin; }; /* * Given a pointer to an in6_ifaddr (ifaddr), * return a pointer to the addr as a sockaddr_in6. */ #define IA_SIN6(ia) (&(((struct in6_ifaddr *)(ia))->ia_addr)) #define IA_DSTSIN6(ia) (&(((struct in6_ifaddr *)(ia))->ia_dstaddr)) /* NOTE: All future private IOCTL definitions should be defined in 'in_private.h'. */ #define SIOCSIFADDR6 (int)_IOW('i', 12, struct in6_ifreq) /* set ifnet address */ #define SIOCGIFADDR6 (int)_IOWR('i', 33, struct in6_ifreq) /* get ifnet address */ #define SIOCSIFDSTADDR6 (int)_IOW('i', 14, struct in6_ifreq)/* set p-p address */ #define SIOCGIFDSTADDR6 (int)_IOWR('i', 34, struct in6_ifreq)/* get p-p address */ #define SIOCSIFNETMASK6 (int)_IOW('i', 22, struct in6_ifreq) /* set net addr mask */ #define SIOCGIFNETMASK6 (int)_IOWR('i', 37, struct in6_ifreq)/* get net addr mask */ #define SIOCDIFADDR6 (int)_IOW('i', 25, struct in6_ifreq) /* delete IF addr */ #define SIOCAIFADDR6 (int)_IOW('i', 26, struct in6_aliasreq)/* add/chg IF alias */ #define SIOCFIFADDR6 (int)_IOW('i', 39, struct in6_ifreq) /* put IF addr in front */ #define SIOCVIFADDR6 (int)_IOW('i', 40, struct in6_aliasreq) /* does nothing */ #define SIOCGTUGADDR6 (int)_IOW('i', 41, struct in6_ifreq) /* get TUG real addr */ #define SIOCSTUGADDR6 (int)_IOW('i', 42, struct in6_ifreq) /* set TUG real addr */ #define SIOCADDANY6 (int)_IOW('i', 43, struct in6_ifreq) /* add an anycast */ #define SIOCDELANY6 (int)_IOW('i', 44, struct in6_ifreq) /* delete an anycast */ #define SIOCGIFSITE6 (int)_IOWR('i', 45, struct ifreq) /* get ifnet site */ #define SIOCSIFSITE6 (int)_IOW('i', 46, struct ifreq) /* set ifnet site */ #define SIOCGIFZONE6 (int)_IOWR('i', 47, struct in6_zonereq) /* get ifnet zone(s) */ #define SIOCSIFZONE6 (int)_IOW('i', 48, struct in6_zonereq) /* set ifnet zone */ /* address origin for snmp (IPv6) */ #define SIOCSIFADDRORI6 (int)_IOW('i',142,struct ifaddrorigin6) /* set address origin */ #define SIOCAIFADDR6T (int)_IOW('i', 50, struct in6_aliasreq2)/* add/chg IF alias and type */ #define SIOCGIFADDR6T (int)_IOWR('i', 51, struct in6_aliasreq2) /* get type of address */ #define SIOCSIFADDRSTATE6 (int)_IOW('i', 52, struct in6_aliasreq2)/* change address state */ #define SIOCGIFADDRSTATE6 (int)_IOWR('i', 53, struct in6_aliasreq2) /* get address state */ #define SIOCGSRCFILTER6 (int)_IOWR('i', 53, struct group_source_filter_req) /* get multicast source filter */ #define SIOCACLADDR6 (int)_IOW('i', 54, struct in6_aliasreq)/* add/chg IF alias */ #define SIOCDCLADDR6 (int)_IOW('i', 55, struct in6_ifreq) /* delete IF addr */ #define SIOCSIFADDRFLAG6 (int)_IOW('i', 56, struct in6_aliasreq2)/* set address source flag */ #define SIOCGIFADDRFLAG6 (int)_IOWR('i', 57, struct in6_aliasreq2)/* get address source flag */ #if defined(_KERNEL) #define IN6IFADDR_HASHCHNHEAD_LOCKINIT(index) \ do { \ NET_MALLOC(in6ifaddr_hashchn_lock[index], DRW_lock *, \ sizeof(DRW_lock), M_LOCKF, M_WAITOK); \ lock_alloc(in6ifaddr_hashchn_lock[index], \ LOCK_ALLOC_PIN, IN6IFADDR_LOCK_FAMILY, -1); \ drw_lock_init(in6ifaddr_hashchn_lock[index]); \ } while (0) #define IN6IFADDR_HASHCHNHEAD_LOCK_DECL() int _in6ifl_h, _in6ifrl_h #define IN6IFADDR_HASHCHNHEAD_WRITE_LOCK(index) \ do { \ _in6ifl_h = i_disable(PL_IMP); \ drw_lock_write(in6ifaddr_hashchn_lock[index]); \ } while (0) #define IN6IFADDR_HASHCHNHEAD_READ_LOCK(index) \ do { \ _in6ifrl_h = i_disable(PL_IMP); \ drw_lock_read(in6ifaddr_hashchn_lock[index]); \ } while (0) #define IN6IFADDR_HASHCHNHEAD_WRITE_UNLOCK(index) \ do { \ drw_lock_done(in6ifaddr_hashchn_lock[index]); \ i_enable(_in6ifl_h); \ } while (0) #define IN6IFADDR_HASHCHNHEAD_READ_UNLOCK(index) \ do { \ drw_lock_done(in6ifaddr_hashchn_lock[index]); \ i_enable(_in6ifrl_h); \ } while (0) extern simple_lock_data_t in6ifaddr_lock; #define IN6IFADDR_LOCKINIT() { \ lock_alloc(&in6ifaddr_lock, LOCK_ALLOC_PIN, IN6IFADDR_LOCK_FAMILY, -1);\ simple_lock_init(&in6ifaddr_lock); \ } #define IN6IFADDR_LOCK_DECL() int _in6ifl; #define IN6IFADDR_WRITE_LOCK() _in6ifl = disable_lock(PL_IMP, &in6ifaddr_lock) #define IN6IFADDR_READ_LOCK() _in6ifl = disable_lock(PL_IMP, &in6ifaddr_lock) #define IN6IFADDR_UNLOCK() unlock_enable(_in6ifl, &in6ifaddr_lock) extern simple_lock_data_t flow6_lock; #define FLOW6_LOCKINIT() { \ lock_alloc(&flow6_lock, LOCK_ALLOC_PIN, FLOW6_LOCK_FAMILY, -1);\ simple_lock_init(&flow6_lock); \ } #define FLOW6_LOCK_DECL() int _flow6l; #define FLOW6_WRITE_LOCK() _flow6l = disable_lock(PL_IMP, &flow6_lock) #define FLOW6_READ_LOCK() _flow6l = disable_lock(PL_IMP, &flow6_lock) #define FLOW6_LOCK() _flow6l = disable_lock(PL_IMP, &flow6_lock) #define FLOW6_UNLOCK() unlock_enable(_flow6l, &flow6_lock) #define IN6ANYADDR_HASHCHNHEAD_LOCKINIT(index) { \ lock_alloc(&(in6anycast_hashchn_lock[index]._l), LOCK_ALLOC_PIN, IN6ANYA_LOCK_FAMILY, -1); \ simple_lock_init(&(in6anycast_hashchn_lock[index]._l)); \ } #define IN6ANYADDR_HASHCHNHEAD_LOCK_DECL() int _in6anycast; #define IN6ANYADDR_HASHCHNHEAD_WRITE_LOCK(index) \ _in6anycast = disable_lock(PL_IMP, &(in6anycast_hashchn_lock[index]._l)) #define IN6ANYADDR_HASHCHNHEAD_READ_LOCK(index) \ _in6anycast = disable_lock(PL_IMP, &(in6anycast_hashchn_lock[index]._l)) #define IN6ANYADDR_HASHCHNHEAD_WRITE_UNLOCK(index) \ unlock_enable(_in6anycast, &(in6anycast_hashchn_lock[index]._l)) #define IN6ANYADDR_HASHCHNHEAD_READ_UNLOCK(index) \ unlock_enable(_in6anycast, &(in6anycast_hashchn_lock[index]._l)) extern simple_lock_data_t in6anyaddr_lock; #define IN6ANYADDR_LOCKINIT() { \ lock_alloc(&in6anyaddr_lock, LOCK_ALLOC_PIN, IN6ANYA_LOCK_FAMILY, -1);\ simple_lock_init(&in6anyaddr_lock); \ } #define IN6ANYADDR_LOCK_DECL() int _in6ifl; #define IN6ANYADDR_WRITE_LOCK() _in6ifl = disable_lock(PL_IMP, &in6anyaddr_lock) #define IN6ANYADDR_READ_LOCK() _in6ifl = disable_lock(PL_IMP, &in6anyaddr_lock) #define IN6ANYADDR_UNLOCK() unlock_enable(_in6ifl, &in6anyaddr_lock) TAILQ_HEAD(in6_ifaddrhead, in6_ifaddr); extern struct in6_ifaddrhead in6_ifaddr; extern LIST_HEAD(in6_anyhead, in6_anycast) in6_anyhead; #define SAME_ADDR6_MASK(a, b, m) \ ( (((a).s6_addr32[0] & (m).s6_addr32[0]) == \ ((b).s6_addr32[0] & (m).s6_addr32[0])) && \ (((a).s6_addr32[1] & (m).s6_addr32[1]) == \ ((b).s6_addr32[1] & (m).s6_addr32[1])) && \ (((a).s6_addr32[2] & (m).s6_addr32[2]) == \ ((b).s6_addr32[2] & (m).s6_addr32[2])) && \ (((a).s6_addr32[3] & (m).s6_addr32[3]) == \ ((b).s6_addr32[3] & (m).s6_addr32[3])) ) /* * Macro for finding the interface (ifnet structure) corresponding to one * of our IPv6 addresses. */ #define IN6ADDR_TO_IFP(addr, ifp) \ /* struct in6_addr addr; */ \ /* struct ifnet *ifp; */ \ { \ register struct in6_ifaddr *ia; \ struct in6ifaddr_hash *hp; \ struct in6ifaddr_hash_table *tablep; \ int index; \ IN6IFADDR_HASHCHNHEAD_LOCK_DECL(); \ ifp = NULL; \ \ index = IN6IFADDR_HASH((addr).s6_addr32[3]); \ IN6IFADDR_HASHCHNHEAD_READ_LOCK(index); \ tablep = &in6ifaddr_hash_table[index]; \ for (hp = tablep->head.next; hp != &(tablep->head); hp = hp->next) { \ ia = ia6hashtoinifaddr(hp); \ if (SAME_ADDR6(((ia->ia_ifp->if_flags & IFF_POINTOPOINT) ? \ IA_DSTSIN6(ia) : IA_SIN6(ia))->sin6_addr, addr)) { \ (ifp) = ia->ia_ifp; \ break; \ } \ } \ if (ifp == NULL) \ for (hp = tablep->head.next; hp != &(tablep->head); hp = hp->next) { \ ia = ia6hashtoinifaddr(hp); \ if (ia->ia_ifp->if_flags & IFF_POINTOPOINT && \ SAME_ADDR6(IA_SIN6(ia)->sin6_addr, addr)) { \ (ifp) = ia->ia_ifp; \ break; \ } \ } \ \ IN6IFADDR_HASHCHNHEAD_READ_UNLOCK(index); \ } /* * Macro for finding the IPv6 address structure (in6_ifaddr) corresponding * to a given interface (ifnet structure). */ #define IFP_TO_IA6(ifp, ia) \ /* struct ifnet *ifp; */ \ /* struct in6_ifaddr *ia; */ \ { \ struct in6ifaddr_hash *hp, *hphead; \ int index; \ IN6IFADDR_HASHCHNHEAD_LOCK_DECL(); \ \ for(index = 0; index < IN6IFADDR_HASHSZ; index++) { \ if (in6ifaddr_hash_table[index].head.next != \ &(in6ifaddr_hash_table[index].head)) { \ IN6IFADDR_HASHCHNHEAD_READ_LOCK(index); \ hphead = &(in6ifaddr_hash_table[index].head); \ hp = hphead->next; \ if ((hp != hphead) && hp) { \ for(; (hp != hphead) && hp; hp = hp->next) { \ (ia) = ia6hashtoinifaddr(hp); \ if ((ia)->ia_ifp == (ifp)) { \ IN6IFADDR_HASHCHNHEAD_READ_UNLOCK(index); \ break; \ } \ } /* hash chain for loop */ \ } \ if ((ia)->ia_ifp == (ifp)) \ break; \ IN6IFADDR_HASHCHNHEAD_READ_UNLOCK(index); \ } /* if test for inifaddrs in this chain */ \ } /* index for loop */ \ if (ia && (ia)->ia_ifp != (ifp)) \ ia = 0; \ } #define IN6ADDR_TO_IA(addr, ia) \ /* struct in6_addr addr; */ \ /* struct in6_ifaddr *ia; */ \ { \ IN6IFADDR_LOCK_DECL() \ \ IN6IFADDR_READ_LOCK(); \ for ((ia) = in6_ifaddr.tqh_first; (ia); (ia) = (ia)->ia_list.tqe_next) { \ if ((ia)->ia_sockmask.sin6_addr.u6_addr.u6_addr8[0] != 0 && \ SAME_ADDR6_MASK((ia)->ia_addr.sin6_addr, addr, \ (ia)->ia_sockmask.sin6_addr)) \ break; \ } \ IN6IFADDR_UNLOCK(); \ } #define IN6ADDR_TO_IA_IFP(addr, ia, ifp) \ /* struct in6_addr addr; */ \ /* struct in6_ifaddr *ia; */ \ /* struct ifnet *ifp; */ \ { \ IN6IFADDR_LOCK_DECL() \ \ IN6IFADDR_READ_LOCK(); \ for ((ia) = in6_ifaddr.tqh_first; (ia); (ia) = (ia)->ia_list.tqe_next) { \ if ((ia)->ia_sockmask.sin6_addr.u6_addr.u6_addr8[0] != 0 && \ SAME_ADDR6_MASK((ia)->ia_addr.sin6_addr, addr, \ (ia)->ia_sockmask.sin6_addr)) \ break; \ } \ if ((ifp) != (struct ifnet*)NULL) \ (ifp) = ((ia) == NULL) ? (struct ifnet*)NULL : (ia)->ia_ifp; \ IN6IFADDR_UNLOCK(); \ } #endif struct source6_info{ char si_mode; ushort num_src; ushort max_src; ushort refcount; struct in6_addr *si6_src; struct source6_info *si6_next; }; /* Filter list per multicast group */ struct filter6_list { char fl_mode; /* Filter mode */ ushort num_src; /* No. of source addresses in the list */ ushort max_src; /* Max source addresses that can fit */ struct in6_addr *fl6_src; /* Source list */ }; /* Include/Exclude addresses per group */ struct addr6_info { struct in6_addr addr6; /* Address list */ ushort count; /* Refcount/pending report count */ }; struct address6_list { ushort num_src; /* Number of sources in the list */ ushort max_src; /* Max source addresses that can fit */ struct addr6_info *al6_ai; }; /* * IPv6 multicast address structure. There is one of these for each IPv6 * multicast group to which this host belongs on a given network interface. * They are kept in a linked list, rooted in the interface's in6_ifaddr * structure. */ struct in6_multi { LIST_ENTRY(in6_multi) inm6_entry; /* list glue */ struct in6_addr inm6_addr; /* IPv6 multicast address */ struct ifnet *inm6_ifp; /* back pointer to ifnet */ ushort exc6_count; /* no. sockets in exclude mode */ ushort si6count; /* number of sockets having source info */ struct source6_info *inm6_ui; /* Source Address info */ u_int inm6_refcount; /* no. membership claims by sockets */ u_int inm6_timer; /* ICMPv6 membership report timer In MLDV2 , used to schedule State Change Reports */ u_int inm6_rtimer; /* Schedule Current State Reports for received multicast address queries for MLDv2 */ u_int inm6_state; /* state of the membership */ u_int32 inm6_sin6_scope_id; /* scope zone for this multicast addr. */ struct router6_info *inm6_rti; /* router info */ struct address6_list inm6_exc_list; /* list of excluded addresses */ struct address6_list inm6_inc_list; /* list of included addresses */ struct filter6_list inm6_fl; /* Consolidated source list */ char s6mode; /* State change mode */ ushort state6_count; /* State change report count */ struct address6_list inm6_allow; /* addresses to report in ALLOW */ struct address6_list inm6_block; /* addresses to report in BLOCK */ struct address6_list inm6_query_srcs; /* group and source specific query */ }; #define MULTI6_OTHERMEMBER 1 #define MULTI6_IREPORTEDLAST 2 #if defined(_KERNEL) /* * Structure used by macros below to remember position when stepping through * all of the in6_multi records. */ struct in6_multistep { struct ifnet *i6_if; struct ifnet *i6_lastif; struct in6_multi *i6_inm; }; /* * Macro for looking up the in6_multi record * for a given IPv6 multicast address on a given interface. * If no matching record is found, "inm" returns NULL. */ #define IN6_LOOKUP_MULTI(addr, ifp, inm) \ /* struct in6_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in6_multi *inm; */ \ { \ IF6MULTI_LOCK(ifp); \ for ((inm) = ifp->if_multiaddrs6.lh_first; \ (inm) != NULL && !SAME_ADDR6((inm)->inm6_addr, (addr)); \ (inm) = inm->inm6_entry.le_next) \ continue; \ IF6MULTI_UNLOCK(ifp); \ } #define IN6_LOOKUP_MULTI_NOLOCK(addr, ifp, inm) \ /* struct in6_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in6_multi *inm; */ \ { \ for ((inm) = ifp->if_multiaddrs6.lh_first; \ (inm) != NULL && !SAME_ADDR6((inm)->inm6_addr, (addr)); \ (inm) = inm->inm6_entry.le_next) \ continue; \ } #define UNLOCK_LAST_MULTI6(step) \ if((step).i6_lastif) IF6MULTI_UNLOCK_RECURSIVE((step).i6_lastif) /* * Macro for looking up the in_multi record for a given IP multicast address * on a given interface. If no matching record is found or if source is * blocked, "inm" returns NULL. */ #define IN6_LOOKUP_SOURCE_MULTI(saddr, addr, ifp, inm) \ /* struct in6_addr saddr; */ \ /* struct in6_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in6_multi *inm; */ \ { \ IFMULTI_LOCK(ifp); \ for ((inm) = ifp->if_multiaddrs6.lh_first; \ (inm) != NULL && !SAME_ADDR6((inm)->inm6_addr, (addr)); \ (inm) = inm->inm6_entry.le_next); \ if (inm != NULL) { \ IN6_LOOKUP_SOURCE_NOLOCK(inm,saddr); \ } \ IFMULTI_UNLOCK(ifp); \ } #define IN6_LOOKUP_SOURCE_NOLOCK(inm, saddr) \ /* struct in6_multi *inm; */ \ /* struct in6_addr saddr; */ \ { \ int index; \ struct filter6_list *fl = &(inm->inm6_fl); \ \ if (fl->fl_mode == INM_EXCLUDE) { \ for (index=0; indexnum_src; index++) \ if (SAME_ADDR6(fl->fl6_src[index], saddr)) { \ inm = NULL; \ break; \ } \ } else if (fl->fl_mode == INM_INCLUDE) { \ for (index=0; indexnum_src; index++) \ if (SAME_ADDR6(fl->fl6_src[index], saddr)) \ break; \ if (index == fl->num_src) \ inm = NULL; \ } \ } /* * Macro to step through all of the in6_multi records, one at a time. * The current position is remembered in "step", which the caller must * provide. IN6_FIRST_MULTI(), below, must be called to initialize "step" * and get the first record. Both macros return a NULL "inm" when there * are no remaining records. */ #define IN6_NEXT_MULTI(step, inm) \ /* struct in6_multistep step; */ \ /* struct in6_multi *inm; */ \ { \ if (((inm) = (step).i6_inm) != NULL) \ (step).i6_inm = (inm)->inm6_entry.le_next; \ else \ while ((step).i6_if != NULL) { \ UNLOCK_LAST_MULTI6(step); \ IF6MULTI_LOCK_RECURSIVE((step).i6_if); \ (inm) = (step).i6_if->if_multiaddrs6.lh_first; \ (step).i6_lastif = (step).i6_if; \ (step).i6_if = (step).i6_if->if_next; \ if ((inm) != NULL) { \ (step).i6_inm = (inm)->inm6_entry.le_next; \ break; \ } \ } \ } #define IN6_FIRST_MULTI(step, inm) \ /* struct in6_multistep step; */ \ /* struct in6_multi *inm; */ \ { \ (step).i6_if = ifnet; \ (step).i6_inm = NULL; \ (step).i6_lastif = NULL; \ IN6_NEXT_MULTI((step), (inm)); \ } /* * Macro to find the same sinfo structure for the given sourceaddr. * Currently just matches one sourceaddr due to performance issues. */ #define IN6_LOOKUP_SOURCE_RECORD_NOLOCK(inm6, sinfo6, mode, sourceaddr6) \ /* struct in6_multi *inm; */ \ /* struct source6_info *sinfo; */ \ /* int mode; */ \ /* struct in6_addr sourceaddr; */ \ { \ for((sinfo6) = (inm6)->inm6_ui; (sinfo6) != NULL; \ (sinfo6) = (sinfo6)->si6_next) { \ if ((sinfo6->num_src == 1) && \ (SAME_ADDR6(sinfo6->si6_src[0] , sourceaddr6)) && \ (sinfo6->si_mode == mode)) { \ break; \ } \ } \ } #define IN6ADDR_ALLOC(addrp, size, max6_src) \ /* struct in6_addr *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ NET_MALLOC(addrp, struct in6_addr *, (sizeof(struct in6_addr)) * size, \ M_IPMADDR, M_NOWAIT); \ if (addrp == NULL) \ return; \ bzero((caddr_t)addrp, sizeof(struct in6_addr)*size); \ max6_src = size; \ } #define IN6ADDR_ALLOC_RC(addrp, size, max6_src) \ /* struct in6_addr *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ NET_MALLOC(addrp, struct in6_addr *, (sizeof(struct in6_addr)) * size, \ M_IPMADDR, M_NOWAIT); \ if (addrp == NULL) \ return NULL; \ bzero((caddr_t)addrp, sizeof(struct in6_addr)*size); \ max6_src = size; \ } #define IN6ADDR_REALLOC(addrp, size, max_src) \ /* struct in6_addr *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ struct in6_addr *readdrp; \ NET_MALLOC(readdrp, struct in6_addr *, \ (sizeof(struct in6_addr))*(size+max_src), M_IPMADDR, M_NOWAIT); \ if (readdrp == NULL) \ return; \ bzero((caddr_t)readdrp, sizeof(struct in6_addr)*(size+max_src)); \ bcopy((caddr_t)addrp, (caddr_t)readdrp, \ sizeof(struct in6_addr)*max_src); \ max_src += size; \ NET_FREE(addrp, M_IPMADDR); \ addrp = readdrp; \ } #define IN6ADDR_REALLOC_RC(addrp, size, max_src) \ /* struct in6_addr *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ struct in6_addr *readdrp; \ NET_MALLOC(readdrp, struct in6_addr *, \ (sizeof(struct in6_addr))*(size+max_src), M_IPMADDR, M_NOWAIT); \ if (readdrp == NULL) \ return NULL; \ bzero((caddr_t)readdrp, sizeof(struct in6_addr)*(size+max_src)); \ bcopy((caddr_t)addrp, (caddr_t)readdrp, \ sizeof(struct in6_addr)*max_src); \ max_src += size; \ NET_FREE(addrp, M_IPMADDR); \ addrp = readdrp; \ } #define S6INFO_COPY_RC(sinfo6, sinfo6_new, inm6) \ /* struct source6_info *sinfo6 */ \ /* struct source6_info *sinfo6_new */ \ /* struct in6_multi *inm6 */ \ { \ NET_MALLOC(sinfo6_new, struct source6_info *, \ sizeof(*sinfo6_new), M_IPMADDR, M_NOWAIT); \ IN6ADDR_ALLOC_RC(sinfo6_new->si6_src, sinfo6->max_src, \ sinfo6_new->max_src); \ if ((sinfo6_new == NULL) || (sinfo6_new->si6_src == NULL)) \ return NULL; \ bcopy((caddr_t)sinfo6->si6_src, (caddr_t)sinfo6_new->si6_src, \ sizeof(struct in6_addr)*sinfo6->num_src); \ --sinfo6->refcount; \ sinfo6_new->si_mode = sinfo6->si_mode; \ sinfo6_new->num_src = sinfo6->num_src; \ sinfo6_new->refcount = 1; \ sinfo6_new->si6_next = inm6->inm6_ui; \ inm6->inm6_ui = sinfo6_new; \ } #define ADDR6INFO_ALLOC(addrp, size, max_src) \ /* struct addr6_info *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ NET_MALLOC(addrp, struct addr6_info *, \ (sizeof(struct addr6_info)) * size, M_IPMADDR, M_NOWAIT); \ if (addrp == NULL) \ return; \ bzero((caddr_t)addrp, sizeof(struct addr6_info)*size); \ max_src = size; \ } #define ADDR6INFO_ALLOC_RC(addrp, size, max_src) \ /* struct addr6_info *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ NET_MALLOC(addrp, struct addr6_info *, \ (sizeof(struct addr6_info)) * size, M_IPMADDR, M_NOWAIT); \ if (addrp == NULL) \ return NULL; \ bzero((caddr_t)addrp, sizeof(struct addr6_info)*size); \ max_src = size; \ } #define ADDR6INFO_REALLOC(addrp, size, max_src) \ /* struct addr6_info *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ struct addr6_info *readdrp; \ NET_MALLOC(readdrp, struct addr6_info *, \ (sizeof(struct addr6_info))*(size+max_src), \ M_IPMADDR, M_NOWAIT); \ if (readdrp == NULL) \ return; \ bzero((caddr_t)readdrp, sizeof(struct addr6_info)*(size+max_src)); \ bcopy((caddr_t)addrp, (caddr_t)readdrp, \ sizeof(struct addr6_info)*max_src); \ max_src += size; \ NET_FREE(addrp, M_IPMADDR); \ addrp = readdrp; \ } #define ADDR6INFO_REALLOC_RC(addrp, size, max_src) \ /* struct addr6_info *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ struct addr6_info *readdrp; \ NET_MALLOC(readdrp, struct addr6_info *, \ (sizeof(struct addr6_info))*(size+max_src), \ M_IPMADDR, M_NOWAIT); \ if (readdrp == NULL) \ return NULL; \ bzero((caddr_t)readdrp, sizeof(struct addr6_info)*(size+max_src)); \ bcopy((caddr_t)addrp, (caddr_t)readdrp, \ sizeof(struct addr6_info)*max_src); \ max_src += size; \ NET_FREE(addrp, M_IPMADDR); \ addrp = readdrp; \ } struct router6_info { struct ifnet *ifp; char type; /* type of router which is querier on this interface */ char robustness; short v1querier; /* # of slow timeouts since last v1 query */ short queriertime; /* Querier present interval */ short iftimer; /* Interface timer to respond to general queries */ struct router6_info *next; }; struct source6_info *in6_changemulti_nolock(struct in6_multi *, struct source6_info *, char, struct in6_addr, struct ifnet *); struct source6_info *in6_changemulti(struct in6_multi *, struct source6_info *, char, struct in6_addr); struct in6_multi *in6_addmulti_source(struct ifnet *, struct in6_multi *, struct source6_info **, char, struct in6_addr, struct in6_addr, struct inpcb *); struct in6_multi *in6_addmulti_sources(struct ifnet *, struct in6_multi *, struct source6_info **, char, struct sockaddr_storage *, int, struct sockaddr_storage *, struct inpcb *); struct source6_info *in6_changemulti_sources_nolock(struct in6_multi *, struct source6_info *, char, int, struct sockaddr_storage *, struct ifnet *); struct in6_multi *in6_addmulti_nolock(struct in6_addr*, struct ifnet *, int, struct inpcb *); void in6_change_filter(struct in6_multi *); void in6_del_addrlist(struct in6_multi *, struct source6_info *); void in6_change_addrlist(struct in6_multi *, struct in6_addr, int, int); void mergefl6(struct in6_multi *, struct filter6_list *, struct address6_list *, struct address6_list *); void merge6report(struct in6_multi *, struct address6_list *, struct address6_list *); int in6_delmulti_source(struct in6_multi *, struct source6_info *); void inm6_scrub(struct in6_multi *); #endif /* hash chain structure ot enocde the ipv6 anycast addresses * in a linked list as well as an array of hashed entries */ struct in6anycast_hash { struct in6anycast_hash *next; struct in6anycast_hash *prev; }; #define ia6hashtoanycast(hp) \ (struct in6_anycast *)((char *)(hp) - offsetof(struct in6_anycast, ia_hash)) #define in6anycasttohash(ia) (&(ia->ia_hash)) #define IN6ANYADDR_HASHSZ 29 #define IN6ANYADDR_HASH(addr) ((addr) % IN6ANYADDR_HASHSZ) struct in6anycast_hash_table { struct in6anycast_hash head; }; extern struct in6anycast_hash_table in6anycast_hash_table[IN6ANYADDR_HASHSZ]; struct aligned_in6anycast_lock { simple_lock_data_t _l; char dummy[NET_CACHELINESIZE - sizeof(simple_lock_data_t)]; }; /* Hash table chain head lock */ #if defined(_KERNEL) extern struct aligned_in6anycast_lock in6anycast_hashchn_lock[IN6ANYADDR_HASHSZ]; #endif /* * Anycast address structure. */ struct in6_anycast { #ifdef _KERNEL LIST_ENTRY(in6_anycast) ina6_list; /* list glue */ #endif struct in6_addr ina6_addr; /* IPv6 anycast address */ u_int ina6_refcount; /* reference count */ u_int ina6_flags; /* flags */ struct in6anycast_hash ia_hash; /* hash links */ }; #define IP6ANY_VALID 1 /* valid entry */ #define IP6ANY_ROUTER 2 /* router anycast */ #define IP6ANY_ALLWAYS 3 /* allways get it! */ #endif