/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos72Q src/bos/kernext/inet/in_var.h 1.29.5.3 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 1988,2019 */ /* 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 */ /* @(#)50 1.29.5.3 src/bos/kernext/inet/in_var.h, sockinc, bos72Q, q2019_13A4 2/6/19 00:43:31 */ /* * COMPONENT_NAME: SYSXINET * * FUNCTIONS: IA_SIN * IFP_TO_IA * INADDR_TO_IFP * INIFADDR_LOCKINIT * INIFADDR_READ_LOCK * INIFADDR_UNLOCK * INIFADDR_WRITE_LOCK * IN_FIRST_MULTI * IN_LOOKUP_MULTI * IN_LOOKUP_MULTI_NOLOCK * IN_NEXT_MULTI * UNLOCK_LAST_MULTI * * * ORIGINS: 26,27,85,89,127,196 * * * (C) COPYRIGHT International Business Machines Corp. 1988,1997 * All Rights Reserved * Licensed Materials - Property of IBM * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* * * (c) Copyright 1991, OPEN SOFTWARE FOUNDATION, INC. * ALL RIGHTS RESERVED * */ /* * OSF/1 1.2 */ /* * Copyright (c) 1985, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Base: in_var.h 7.4 (Berkeley) 4/22/89 * Merged: in_var.h 7.6 (Berkeley) 6/28/90 */ #ifndef _IN_VAR_H_ #define _IN_VAR_H_ #include #include #ifdef __cplusplus extern "C" { #endif /* We start with the hash chain infrastructure to manipulte * the interface address structure linked list as an array * of hashed entries */ struct inifaddr_hash { struct inifaddr_hash *next; struct inifaddr_hash *prev; }; #define iahashtoinifaddr(hp) \ (struct in_ifaddr *)((char *)(hp) - offsetof(struct in_ifaddr, ia_hash)) #define inifaddrtohash(ia) (&(ia->ia_hash)) #define INIFADDR_HASHSZ 29 #define INIFADDR_HASH(addr) ((addr) % INIFADDR_HASHSZ) struct inifaddr_hash_table { struct inifaddr_hash head; }; extern struct inifaddr_hash_table inifaddr_hash_table[INIFADDR_HASHSZ]; /* Hash table chain head lock */ #if defined(_KERNEL) extern struct rw_lock *inifaddr_hashchn_lock[INIFADDR_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_pbc.h (because of build breaks * encountered when included through net_globals.h). */ /* * Interface address, Internet version. One of these structures * is allocated for each interface with an Internet address. * The ifaddr structure contains the protocol-independent part * of the structure and is assumed to be first. */ struct in_ifaddr { struct ifaddr ia_ifa; /* protocol-independent info */ #define ia_ifp ia_ifa.ifa_ifp #define ia_flags ia_ifa.ifa_flags /* ia_{,sub}net{,mask} in host order */ u_long ia_net; /* network number of interface */ u_long ia_netmask; /* mask of net part */ u_long ia_subnet; /* subnet number, including net */ u_long ia_subnetmask; /* mask of subnet part */ struct in_addr ia_netbroadcast; /* to recognize net broadcasts */ struct in_ifaddr *ia_next; /* next in list of internet addresses */ struct sockaddr_in ia_addr; /* reserve space for interface name */ struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ #define ia_broadaddr ia_dstaddr struct sockaddr_in ia_sockmask; /* reserve space for general netmask */ struct inifaddr_hash ia_hash; /* hash links */ cid_t ia_kcid; /* kernel corral id */ int_rule_t * if_rule; /* MLS interface rule */ }; struct in_aliasreq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr_in ifra_addr; struct sockaddr_in ifra_broadaddr; #define ifra_dstaddr ifra_broadaddr struct sockaddr_in ifra_mask; }; #ifdef PHABRE1 struct in_clustreq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr_in ifra_addr; struct sockaddr_in ifra_broadaddr; #define ifra_dstaddr ifra_broadaddr struct sockaddr_in ifra_mask; u_short ifra_flags; }; #endif /* PHABRE1 */ /* * Given a pointer to an in_ifaddr (ifaddr), * return a pointer to the addr as a sockaddr_in. */ #define IA_SIN(ia) (&(((struct in_ifaddr *)(ia))->ia_addr)) #ifdef _KERNEL #define INIFADDR_HASHCHNHEAD_LOCKINIT(index) \ RW_LOCKINIT(inifaddr_hashchn_lock[index], 2*NET_CACHELINESIZE, M_LOCKF, M_WAITOK, LOCK_ALLOC_PIN, \ INIFADDR_LOCK_FAMILY, -1); #define INIFADDR_HASHCHNHEAD_LOCK_DECL() int _inifl_h, _inifrl_h; #define INIFADDR_HASHCHNHEAD_WRITE_LOCK(index) RW_WRITE_LOCK(inifaddr_hashchn_lock[index], _inifl_h, PL_IMP) #define INIFADDR_HASHCHNHEAD_WRITE_UNLOCK(index) RW_WRITE_UNLOCK(inifaddr_hashchn_lock[index], _inifl_h) #define INIFADDR_HASHCHNHEAD_READ_LOCK(index) \ RW_READ_LOCK(inifaddr_hashchn_lock[index], _inifl_h, PL_IMP, _inifrl_h) #define INIFADDR_HASHCHNHEAD_READ_UNLOCK(index) RW_READ_UNLOCK(inifaddr_hashchn_lock[index], _inifrl_h) #endif #ifdef _KERNEL extern DRW_lock *inifaddr_lock; #define INIFADDR_LOCKINIT() \ do { \ NET_MALLOC(inifaddr_lock, DRW_lock *, sizeof(DRW_lock), \ M_LOCKF, M_WAITOK); \ lock_alloc(inifaddr_lock, LOCK_ALLOC_PIN, INIFADDR_LOCK_FAMILY, -1); \ drw_lock_init(inifaddr_lock); \ } while (0) #define INIFADDR_LOCK_DECL() int _inifl, _inifrl; #define INIFADDR_WRITE_LOCK() \ do { \ _inifl = i_disable(PL_IMP); \ drw_lock_write(inifaddr_lock); \ } while (0) #define INIFADDR_WRITE_UNLOCK() \ do { \ drw_lock_done(inifaddr_lock); \ i_enable(_inifl); \ } while (0) #define INIFADDR_READ_LOCK() \ do { \ _inifrl = i_disable(PL_IMP); \ drw_lock_read(inifaddr_lock); \ } while (0) #define INIFADDR_READ_UNLOCK() \ do { \ drw_lock_done(inifaddr_lock); \ i_enable(_inifrl); \ } while (0) /*---------------------------------- * Define 629937 * * Convert an INIFADDR_WRITE_LOCK to a READ lock, and * then restore it to a WRITE lock. You must restore the * lock back -- not simple call READ_UNLOCK, or you risk * an incorrect priority. */ #define INIFADDR_WRITE_TO_READ_LOCK() \ drw_lock_write_to_read(inifaddr_lock) #define INIFADDR_READ_TO_WRITE_LOCK(_ret_val) \ (_ret_val) = drw_lock_read_to_write(inifaddr_lock) #define INIFADDR_WRITE_LOCK_NO_DISABLE() \ drw_lock_write(inifaddr_lock) extern struct domain inetdomain; extern CONST struct protosw inetsw[]; extern long inetprintfs; extern long ipforwarding; extern CONST struct sockaddr_in in_zeroaddr; extern CONST struct sockaddr_in6 in6_zeroaddr; extern struct in_ifaddr *in_ifaddr; extern struct ifqueue ipintrq[NETMAXCPU]; /* ip packet input queue */ #endif #ifdef IP_MULTICAST /* * Internet multicast address structure. There is one of these for each IP * multicast group to which this host belongs on a given network interface. * They are kept in a linked list, rooted at the interface (struct ifnet) * structure. */ #define INM_INIT_SOURCE 16 /* No. of source addresses per socket per group */ #define INM_INIT_ADDR_LIST 64 /* No. of blocked/included addresses per group */ #define INM_INIT_FLT_LIST 128 /* No. of addresses in filter list per group */ #define SRC_ADD 1 /* Option for adding to the address list */ #define SRC_DEL 0 /* Option for deleting from the address list */ #define INM_INCLUDE 1 /* Should be same value as MODE_IS_INCLUDE in igmp.h */ #define INM_EXCLUDE 2 /* Should be same value as MODE_IS_EXCLUDE in igmp.h */ struct source_info { char si_mode; /* filter mode */ ushort num_src; /* No. of source addresses in list */ ushort max_src; /* Max source addresses that can fit */ ushort refcount; struct in_addr *si_src; /* Source list */ struct source_info *si_next; }; /* Filter list per multicast group */ struct filter_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 in_addr *fl_src; /* Source list */ }; /* Include/Exclude addresses per group */ struct addr_info { struct in_addr addr; /* Address list */ ushort count; /* Refcount/pending report count */ }; struct address_list { ushort num_src; /* Number of sources in the list */ ushort max_src; /* Max source addresses that can fit */ struct addr_info *al_ai; }; struct in_multi { struct in_addr inm_addr; /* IP multicast address */ struct ifnet *inm_ifp; /* back pointer to ifnet */ u_int inm_refcount; /* no. membership claims by sockets */ ushort exc_count; /* no. sockets in exclude mode */ ushort sicount; /* no. sockets having source info */ u_int inm_state; /* state of the membership */ /* For IGMPv3, inm_timer is used for retransmission of reports from 'change * of interface state'. inm_timer2 will be used for scheduling reports on * reception of a group specific query */ u_int inm_timer; /* IGMP membership report timer */ u_int inm_timer2; /* IGMPv3 membership report timer */ struct in_multi *inm_next; /* ptr to next multicast address */ struct router_info *inm_rti; /* router info */ struct source_info *inm_ui; /* Source Address info */ struct address_list inm_exc_list; /* list of excluded addresses */ struct address_list inm_inc_list; /* list of included addresses */ struct filter_list inm_fl; /* Consolidated source list */ char smode; /* State change mode */ ushort state_count; /* State change report count */ struct address_list inm_allow; /* addresses to report in ALLOW */ struct address_list inm_block; /* addresses to report in BLOCK */ struct address_list inm_query_srcs; /* group and source specific query */ cid_t im_kcid; /* kcid of the WPAR using this mcast addr */ }; #define ADDRINFO_ALLOC(addrp, size, max_src) \ /* struct address_list *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ NET_MALLOC(addrp, struct addr_info *, \ (sizeof(struct addr_info)) * size, M_IPMADDR, M_NOWAIT); \ if (addrp == NULL) \ return; \ bzero((caddr_t)addrp, sizeof(struct addr_info)*size); \ max_src = size; \ } #define ADDRINFO_REALLOC(addrp, size, max_src) \ /* struct address_list *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ struct addr_info *readdrp; \ NET_MALLOC(readdrp, struct addr_info *, \ (sizeof(struct addr_info))*(size+max_src), \ M_IPMADDR, M_NOWAIT); \ if (readdrp == NULL) \ return; \ bzero((caddr_t)readdrp, sizeof(struct addr_info)*(size+max_src)); \ bcopy((caddr_t)addrp, (caddr_t)readdrp, \ sizeof(struct addr_info)*max_src); \ max_src += size; \ NET_FREE(addrp, M_IPMADDR); \ addrp = readdrp; \ } #define ADDRINFO_REALLOC_RC(addrp, size, max_src) \ /* struct address_list *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ struct addr_info *readdrp; \ NET_MALLOC(readdrp, struct addr_info *, \ (sizeof(struct addr_info))*(size+max_src), \ M_IPMADDR, M_NOWAIT); \ if (readdrp == NULL) \ return NULL; \ bzero((caddr_t)readdrp, sizeof(struct addr_info)*(size+max_src)); \ bcopy((caddr_t)addrp, (caddr_t)readdrp, \ sizeof(struct addr_info)*max_src); \ max_src += size; \ NET_FREE(addrp, M_IPMADDR); \ addrp = readdrp; \ } #define INADDR_ALLOC(addrp, size, max_src) \ /* struct in_addr *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ NET_MALLOC(addrp, struct in_addr *, (sizeof(struct in_addr)) * size, \ M_IPMADDR, M_NOWAIT); \ if (addrp == NULL) \ return; \ bzero((caddr_t)addrp, sizeof(struct in_addr)*size); \ max_src = size; \ } #define INADDR_ALLOC_RC(addrp, size, max_src) \ /* struct in_addr *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ NET_MALLOC(addrp, struct in_addr *, (sizeof(struct in_addr)) * size, \ M_IPMADDR, M_NOWAIT); \ if (addrp == NULL) \ return NULL; \ bzero((caddr_t)addrp, sizeof(struct in_addr)*size); \ max_src = size; \ } #define INADDR_REALLOC(addrp, size, max_src) \ /* struct in_addr *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ struct in_addr *readdrp; \ NET_MALLOC(readdrp, struct in_addr *, \ (sizeof(struct in_addr))*(size+max_src), M_IPMADDR, M_NOWAIT); \ if (readdrp == NULL) \ return; \ bzero((caddr_t)readdrp, sizeof(struct in_addr)*(size+max_src)); \ bcopy((caddr_t)addrp, (caddr_t)readdrp, \ sizeof(struct in_addr)*max_src); \ max_src += size; \ NET_FREE(addrp, M_IPMADDR); \ addrp = readdrp; \ } #define INADDR_REALLOC_RC(addrp, size, max_src) \ /* struct in_addr *addrp; */ \ /* ushort size; */ \ /* ushort max_src; */ \ { \ struct in_addr *readdrp; \ NET_MALLOC(readdrp, struct in_addr *, \ (sizeof(struct in_addr))*(size+max_src), M_IPMADDR, M_NOWAIT); \ if (readdrp == NULL) \ return NULL; \ bzero((caddr_t)readdrp, sizeof(struct in_addr)*(size+max_src)); \ bcopy((caddr_t)addrp, (caddr_t)readdrp, \ sizeof(struct in_addr)*max_src); \ max_src += size; \ NET_FREE(addrp, M_IPMADDR); \ addrp = readdrp; \ } #ifdef _KERNEL /* * Macro for finding the interface (ifnet structure) corresponding to one * of our IP addresses. */ #define INADDR_TO_IFP(addr, ifp) \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ { \ register struct in_ifaddr *ia; \ struct inifaddr_hash *hp; \ struct inifaddr_hash_table *tablep; \ int index; \ INIFADDR_HASHCHNHEAD_LOCK_DECL() \ ifp = NULL; \ \ index = INIFADDR_HASH((addr).s_addr); \ INIFADDR_HASHCHNHEAD_READ_LOCK(index); \ \ tablep = &inifaddr_hash_table[index]; \ for (hp = tablep->head.next; hp != &(tablep->head); hp = hp->next) { \ ia = iahashtoinifaddr(hp); \ if (IA_SIN(ia)->sin_addr.s_addr == (addr).s_addr){ \ (ifp) = ia->ia_ifp; \ break; \ } \ } \ \ INIFADDR_HASHCHNHEAD_READ_UNLOCK(index); \ \ } /* * Macro for finding the internet address structure (in_ifaddr) corresponding * to a given interface (ifnet structure). */ #define IFP_TO_IA(ifp, ia) \ /* struct ifnet *ifp; */ \ /* struct in_ifaddr *ia; */ \ { \ struct inifaddr_hash *hp, *hphead; \ int index; \ INIFADDR_HASHCHNHEAD_LOCK_DECL() \ \ ia = NULL; \ for(index = 0; index < INIFADDR_HASHSZ; index++) { \ if (inifaddr_hash_table[index].head.next != \ &(inifaddr_hash_table[index].head)) { \ INIFADDR_HASHCHNHEAD_READ_LOCK(index); \ hphead = &(inifaddr_hash_table[index].head); \ hp = hphead->next; \ if ((hp != hphead) && hp) { \ for(; hp != hphead; hp = hp->next) { \ (ia) = iahashtoinifaddr(hp); \ if ((ia)->ia_ifp == (ifp)) { \ INIFADDR_HASHCHNHEAD_READ_UNLOCK(index); \ break; \ } \ } /* hash chain for loop */ \ } \ if ((ia) && (ia)->ia_ifp == (ifp)) \ break; \ INIFADDR_HASHCHNHEAD_READ_UNLOCK(index); \ } /* if test for inifaddrs in this chain */ \ } /* index for loop */ \ if ((ia) && (ia)->ia_ifp != (ifp)) \ ia = 0; \ } /* * This information should be part of the ifnet structure but we don't wish * to change that - as it might break a number of things */ struct router_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 v2querier; /* # of slow timeouts since last v2 query */ short queriertime; /* Querier present interval */ short iftimer; /* Interface timer to respond to general queries */ struct router_info *next; }; /* * Structure used by macros below to remember position when stepping through * all of the in_multi records. */ struct in_multistep { struct ifnet *i_if; struct ifnet *i_lastif; struct in_multi *i_inm; }; /* * Macro for looking up the in_multi record for a given IP multicast address * on a given interface. If no matching record is found, "inm" returns NULL. */ #define IN_LOOKUP_MULTI(addr, ifp, inm, kcid) \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in_multi *inm; */ \ /* cid_t kcid; */ \ { \ IFMULTI_LOCK(ifp); \ for ((inm) = ifp->if_multiaddrs; \ ((inm) != NULL && !(((inm)->inm_addr.s_addr == (addr).s_addr) \ && ((inm)->im_kcid == kcid))); \ (inm) = inm->inm_next); \ IFMULTI_UNLOCK(ifp); \ } #define IN_LOOKUP_MULTI_NOLOCK(addr, ifp, inm, kcid) \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in_multi *inm; */ \ /* cid_t kcid; */ \ { \ for ((inm) = ifp->if_multiaddrs; \ ((inm) != NULL && !(((inm)->inm_addr.s_addr == (addr).s_addr) \ && ((inm)->im_kcid == kcid))); \ (inm) = inm->inm_next); \ } /* * Macro for looking up the in_multi record for a given IP multicast address * and kcid on a given interface. If no matching record is found, * "inm" returns NULL. We are searching for the same mulitcast address with * different kcid. This indicates there is another listener on same box * from different WPAR / Global WPAR is listening for this address. */ #define IN_LOOKUP_MULTI_WPAR(addr, ifp, inm, kcid) \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in_multi *inm; */ \ /* cid_t kcid; */ \ { \ IFMULTI_LOCK(ifp); \ for ((inm) = ifp->if_multiaddrs; \ (inm) != NULL && !(((inm)->inm_addr.s_addr == (addr).s_addr) \ && ((inm)->im_kcid != kcid)); \ (inm) = inm->inm_next); \ IFMULTI_UNLOCK(ifp); \ } #define IN_LOOKUP_MULTI_WPAR_NOLOCK(addr, ifp, inm, kcid) \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in_multi *inm; */ \ /* cid_t kcid; */ \ { \ for ((inm) = ifp->if_multiaddrs; \ (inm) != NULL && !(((inm)->inm_addr.s_addr == (addr).s_addr) \ && ((inm)->im_kcid != kcid)); \ (inm) = inm->inm_next); \ } /* * 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 IN_LOOKUP_SOURCE_MULTI(saddr, addr, ifp, inm) \ /* struct in_addr saddr; */ \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in_multi *inm; */ \ { \ IFMULTI_LOCK(ifp); \ for ((inm) = ifp->if_multiaddrs; \ (inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \ (inm) = inm->inm_next); \ if (inm != NULL) { \ IN_LOOKUP_SOURCE_NOLOCK(inm,saddr); \ } \ IFMULTI_UNLOCK(ifp); \ } #define IN_LOOKUP_SOURCE_NOLOCK(inm, saddr) \ /* struct in_multi *inm; */ \ /* struct in_addr saddr; */ \ { \ int index; \ struct filter_list *fl = &(inm->inm_fl); \ \ if (fl->fl_mode == INM_EXCLUDE) { \ for (index=0; indexnum_src; index++) \ if (fl->fl_src[index].s_addr == saddr.s_addr) { \ inm = NULL; \ break; \ } \ } else if (fl->fl_mode == INM_INCLUDE) { \ for (index=0; indexnum_src; index++) \ if (fl->fl_src[index].s_addr == saddr.s_addr) \ break; \ if (index == fl->num_src) \ inm = NULL; \ } \ } /* * Macro to find the same sinfo structure for the given sourceaddr. * Currently just matches one sourceaddr due to performance issues. */ #define IN_LOOKUP_SOURCE_RECORD_NOLOCK(inm, sinfo, mode, sourceaddr) \ /* struct in_multi *inm; */ \ /* struct source_info *sinfo; */ \ /* int mode; */ \ /* struct in_addr sourceaddr; */ \ { \ for((sinfo) = (inm)->inm_ui; (sinfo) != NULL; \ (sinfo) = (sinfo)->si_next) { \ if ((sinfo->num_src == 1) && \ (sinfo->si_src[0].s_addr == sourceaddr.s_addr) && \ (sinfo->si_mode == mode)) { \ break; \ } \ } \ } #define SINFO_COPY_RC(sinfo, sinfo_new, inm) \ /* struct source_info *sinfo */ \ /* struct source_info *sinfo_new */ \ /* struct in_multi *inm */ \ { \ NET_MALLOC(sinfo_new, struct source_info *, \ sizeof(*sinfo_new), M_IPMADDR, M_NOWAIT); \ if (sinfo_new == NULL) \ return NULL; \ INADDR_ALLOC_RC(sinfo_new->si_src, sinfo->max_src, \ sinfo_new->max_src); \ if (sinfo_new->si_src == NULL) { \ NET_FREE(sinfo_new, M_IPMADDR); \ return NULL; \ } \ bcopy((caddr_t)sinfo->si_src, (caddr_t)sinfo_new->si_src, \ sizeof(struct in_addr)*sinfo->num_src); \ --sinfo->refcount; \ sinfo_new->si_mode = sinfo->si_mode; \ sinfo_new->num_src = sinfo->num_src; \ sinfo_new->refcount = 1; \ sinfo_new->si_next = inm->inm_ui; \ inm->inm_ui = sinfo_new; \ } #define UNLOCK_LAST_MULTI(step) \ if((step).i_lastif) IFMULTI_UNLOCK_RECURSIVE((step).i_lastif) /* * Macro to step through all of the in_multi records, one at a time. * The current position is remembered in "step", which the caller must * provide. IN_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 IN_NEXT_MULTI(step, inm) \ /* struct in_multistep step; */ \ /* struct in_multi *inm; */ \ { \ if (((inm) = (step).i_inm) != NULL) { \ (step).i_inm = (inm)->inm_next; \ } \ else while ((step).i_if != NULL) { \ UNLOCK_LAST_MULTI(step); \ IFMULTI_LOCK_RECURSIVE((step).i_if); \ (inm) = (step).i_if->if_multiaddrs; \ (step).i_lastif = (step).i_if; \ (step).i_if = (step).i_if->if_next; \ if ((inm) != NULL) { \ (step).i_inm = (inm)->inm_next; \ break; \ } \ } \ } #define IN_FIRST_MULTI(step, inm) \ /* struct in_multistep step; */ \ /* struct in_multi *inm; */ \ { \ (step).i_if = ifnet; \ (step).i_inm = NULL; \ (step).i_lastif = NULL; \ IN_NEXT_MULTI((step), (inm)); \ } struct in_multi *in_addmulti(struct in_addr , struct ifnet *, cid_t kcid, int *ret, struct inpcb *parent_inpcb); struct in_multi *in_addmulti_nolock(struct in_addr , struct ifnet *, cid_t kcid, int *ret, struct inpcb *parent_inpcb); int in_delmulti_source(struct in_multi *, struct source_info *, struct inpcb *parent_inpcb); int in_delmulti(struct in_multi *, struct inpcb *); struct source_info *in_changemulti_nolock(struct in_multi *, struct source_info *, char, struct in_addr, struct ifnet *); struct source_info *in_changemulti(struct in_multi *, struct source_info *, char, struct in_addr); struct in_multi *in_addmulti_source(struct ifnet *, struct in_multi *, struct source_info **, char, struct in_addr, struct in_addr, cid_t kcid, struct inpcb *); struct in_multi *in_addmulti_sources(struct ifnet *, struct in_multi *, struct source_info **, char, struct in_addr, int, struct in_addr *, cid_t kcid, struct inpcb *); struct source_info *in_changemulti_sources_nolock( struct in_multi *, struct source_info *, char, int, struct in_addr *, struct ifnet *); void inm_init(struct in_multi *, struct in_addr , struct ifnet *); void inm_scrub(struct in_multi *); void in_change_filter(struct in_multi *); void in_del_addrlist(struct in_multi *, struct source_info *); void in_change_addrlist(struct in_multi *, struct in_addr , int, int); void mergefl(struct in_multi *, struct filter_list *, struct address_list *, struct address_list *); void mergereport(struct in_multi *, struct address_list *, struct address_list *); #endif /* _KERNEL */ #endif /* IP_MULTICAST */ #define INADDR_HASHSZ 229 #define INADDR_HASH2(addr) ((addr) % INADDR_HASHSZ) struct in_addr_hash { struct in_addr_hash *iah_nxt; struct in_addr iah_ia; struct ifnet *iah_ifp; int iah_flags; unsigned short iah_cid; struct wpar_per_ifnet *wp_ifnet; }; extern struct in_addr_hash *in_addr_hash_table[INADDR_HASHSZ]; extern simple_lock_data_t in_addr_hash_lock[NET_CACHELINESIZE / sizeof(simple_lock_data_t)]; /* flags for in_addr_hash */ #define IAH_VALID 0x1 #define IAH_BROADCAST 0x2 #define INADDR_HASH_LOCK_DECL() int _iahl; #define INADDR_HASH_LOCK_INIT() { \ lock_alloc(in_addr_hash_lock, \ LOCK_ALLOC_PIN, INADDR_HASH_LOCK_FAMILY, -1); \ simple_lock_init(in_addr_hash_lock); \ } #define INADDR_HASH_READ_LOCK() #define INADDR_HASH_WRITE_LOCK() _iahl = disable_lock(PL_IMP, \ in_addr_hash_lock) #define INADDR_HASH_READ_UNLOCK() #define INADDR_HASH_WRITE_UNLOCK() unlock_enable(_iahl, \ in_addr_hash_lock) #ifdef __cplusplus } #endif #endif /* _IN_VAR_H_ */