#ifndef _NETINET_IN_VAR_H_
#define _NETINET_IN_VAR_H_
struct in_aliasreq {
char ifra_name[IFNAMSIZ];
struct sockaddr_in ifra_addr;
struct sockaddr_in ifra_broadaddr;
#define ifra_dstaddr ifra_broadaddr
struct sockaddr_in ifra_mask;
int ifra_vhid;
};
#ifdef _KERNEL
#include <sys/queue.h>
#include <sys/fnv_hash.h>
#include <sys/tree.h>
struct igmp_ifsoftc;
struct in_multi;
struct lltable;
SLIST_HEAD(in_multi_head, in_multi);
struct in_ifinfo {
struct lltable *ii_llt;
struct igmp_ifsoftc *ii_igmp;
struct in_multi *ii_allhosts;
};
struct in_ifaddr {
struct ifaddr ia_ifa;
#define ia_ifp ia_ifa.ifa_ifp
#define ia_flags ia_ifa.ifa_flags
u_long ia_subnet;
u_long ia_subnetmask;
CK_LIST_ENTRY(in_ifaddr) ia_hash;
CK_STAILQ_ENTRY(in_ifaddr) ia_link;
struct sockaddr_in ia_addr;
struct sockaddr_in ia_dstaddr;
#define ia_broadaddr ia_dstaddr
struct sockaddr_in ia_sockmask;
struct callout ia_garp_timer;
int ia_garp_count;
};
#define IA_SIN(ia) (&(((struct in_ifaddr *)(ia))->ia_addr))
#define IA_DSTSIN(ia) (&(((struct in_ifaddr *)(ia))->ia_dstaddr))
#define IA_MASKSIN(ia) (&(((struct in_ifaddr *)(ia))->ia_sockmask))
#define IN_LNAOF(in, ifa) \
((ntohl((in).s_addr) & ~((struct in_ifaddr *)(ifa)->ia_subnetmask))
#ifdef _KERNEL
#define IN_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
((((d).s_addr ^ (a).s_addr) & (m).s_addr)) == 0 )
#endif
#define LLTABLE(ifp) ((struct in_ifinfo *)(ifp)->if_inet)->ii_llt
CK_STAILQ_HEAD(in_ifaddrhead, in_ifaddr);
CK_LIST_HEAD(in_ifaddrhashhead, in_ifaddr);
VNET_DECLARE(struct in_ifaddrhashhead *, in_ifaddrhashtbl);
VNET_DECLARE(struct in_ifaddrhead, in_ifaddrhead);
VNET_DECLARE(u_long, in_ifaddrhmask);
#define V_in_ifaddrhashtbl VNET(in_ifaddrhashtbl)
#define V_in_ifaddrhead VNET(in_ifaddrhead)
#define V_in_ifaddrhmask VNET(in_ifaddrhmask)
#define INADDR_NHASH_LOG2 9
#define INADDR_NHASH (1 << INADDR_NHASH_LOG2)
#define INADDR_HASHVAL(x) fnv_32_buf((&(x)), sizeof(x), FNV1_32_INIT)
#define INADDR_HASH(x) \
(&V_in_ifaddrhashtbl[INADDR_HASHVAL(x) & V_in_ifaddrhmask])
#define INADDR_TO_IFADDR(addr, ia) \
\
\
do { \
NET_EPOCH_ASSERT(); \
CK_LIST_FOREACH(ia, INADDR_HASH((addr).s_addr), ia_hash) \
if (IA_SIN(ia)->sin_addr.s_addr == (addr).s_addr) \
break; \
} while (0)
#define INADDR_TO_IFP(addr, ifp) \
\
\
{ \
struct in_ifaddr *ia; \
\
INADDR_TO_IFADDR(addr, ia); \
(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
}
struct router_info {
struct ifnet *rti_ifp;
int rti_type;
int rti_time;
SLIST_ENTRY(router_info) rti_list;
};
struct ip_msource {
RB_ENTRY(ip_msource) ims_link;
in_addr_t ims_haddr;
struct ims_st {
uint16_t ex;
uint16_t in;
} ims_st[2];
uint8_t ims_stp;
};
struct in_msource {
RB_ENTRY(ip_msource) ims_link;
in_addr_t ims_haddr;
uint8_t imsl_st[2];
};
RB_HEAD(ip_msource_tree, ip_msource);
static __inline int
ip_msource_cmp(const struct ip_msource *a, const struct ip_msource *b)
{
if (a->ims_haddr < b->ims_haddr)
return (-1);
if (a->ims_haddr == b->ims_haddr)
return (0);
return (1);
}
RB_PROTOTYPE(ip_msource_tree, ip_msource, ims_link, ip_msource_cmp);
struct in_mfilter {
struct ip_msource_tree imf_sources;
u_long imf_nsrc;
uint8_t imf_st[2];
struct in_multi *imf_inm;
STAILQ_ENTRY(in_mfilter) imf_entry;
};
STAILQ_HEAD(ip_mfilter_head, in_mfilter);
struct in_mfilter *ip_mfilter_alloc(int mflags, int st0, int st1);
void ip_mfilter_free(struct in_mfilter *);
static inline void
ip_mfilter_init(struct ip_mfilter_head *head)
{
STAILQ_INIT(head);
}
static inline struct in_mfilter *
ip_mfilter_first(const struct ip_mfilter_head *head)
{
return (STAILQ_FIRST(head));
}
static inline void
ip_mfilter_insert(struct ip_mfilter_head *head, struct in_mfilter *imf)
{
STAILQ_INSERT_TAIL(head, imf, imf_entry);
}
static inline void
ip_mfilter_remove(struct ip_mfilter_head *head, struct in_mfilter *imf)
{
STAILQ_REMOVE(head, imf, in_mfilter, imf_entry);
}
#define IP_MFILTER_FOREACH(imf, head) \
STAILQ_FOREACH(imf, head, imf_entry)
static inline size_t
ip_mfilter_count(struct ip_mfilter_head *head)
{
struct in_mfilter *imf;
size_t num = 0;
STAILQ_FOREACH(imf, head, imf_entry)
num++;
return (num);
}
struct in_multi {
LIST_ENTRY(in_multi) inm_link;
struct in_addr inm_addr;
struct ifnet *inm_ifp;
struct ifmultiaddr *inm_ifma;
u_int inm_timer;
u_int inm_state;
void *inm_rti;
u_int inm_refcount;
struct igmp_ifsoftc *inm_igi;
SLIST_ENTRY(in_multi) inm_nrele;
struct ip_msource_tree inm_srcs;
u_long inm_nsrc;
struct mbufq inm_scq;
struct timeval inm_lastgsrtv;
uint16_t inm_sctimer;
uint16_t inm_scrv;
struct inm_st {
uint16_t iss_fmode;
uint16_t iss_asm;
uint16_t iss_ex;
uint16_t iss_in;
uint16_t iss_rec;
} inm_st[2];
};
static __inline uint8_t
ims_get_mode(const struct in_multi *inm, const struct ip_msource *ims,
uint8_t t)
{
t = !!t;
if (inm->inm_st[t].iss_ex > 0 &&
inm->inm_st[t].iss_ex == ims->ims_st[t].ex)
return (MCAST_EXCLUDE);
else if (ims->ims_st[t].in > 0 && ims->ims_st[t].ex == 0)
return (MCAST_INCLUDE);
return (MCAST_UNDEFINED);
}
#ifdef SYSCTL_DECL
SYSCTL_DECL(_net_inet);
SYSCTL_DECL(_net_inet_ip);
SYSCTL_DECL(_net_inet_raw);
#endif
extern struct mtx in_multi_list_mtx;
extern struct sx in_multi_sx;
#define IN_MULTI_LIST_LOCK() mtx_lock(&in_multi_list_mtx)
#define IN_MULTI_LIST_UNLOCK() mtx_unlock(&in_multi_list_mtx)
#define IN_MULTI_LIST_LOCK_ASSERT() mtx_assert(&in_multi_list_mtx, MA_OWNED)
#define IN_MULTI_LIST_UNLOCK_ASSERT() mtx_assert(&in_multi_list_mtx, MA_NOTOWNED)
#define IN_MULTI_LOCK() sx_xlock(&in_multi_sx)
#define IN_MULTI_UNLOCK() sx_xunlock(&in_multi_sx)
#define IN_MULTI_LOCK_ASSERT() sx_assert(&in_multi_sx, SA_XLOCKED)
#define IN_MULTI_UNLOCK_ASSERT() sx_assert(&in_multi_sx, SA_XUNLOCKED)
void inm_disconnect(struct in_multi *inm);
static __inline struct in_multi *
inm_ifmultiaddr_get_inm(struct ifmultiaddr *ifma)
{
NET_EPOCH_ASSERT();
return ((ifma->ifma_addr->sa_family != AF_INET ||
(ifma->ifma_flags & IFMA_F_ENQUEUED) == 0) ? NULL :
ifma->ifma_protospec);
}
static __inline void
inm_acquire_locked(struct in_multi *inm)
{
IN_MULTI_LIST_LOCK_ASSERT();
++inm->inm_refcount;
}
static __inline void
inm_acquire(struct in_multi *inm)
{
IN_MULTI_LIST_LOCK();
inm_acquire_locked(inm);
IN_MULTI_LIST_UNLOCK();
}
static __inline void
inm_rele_locked(struct in_multi_head *inmh, struct in_multi *inm)
{
MPASS(inm->inm_refcount > 0);
IN_MULTI_LIST_LOCK_ASSERT();
if (--inm->inm_refcount == 0) {
MPASS(inmh != NULL);
inm_disconnect(inm);
inm->inm_ifma->ifma_protospec = NULL;
SLIST_INSERT_HEAD(inmh, inm, inm_nrele);
}
}
#define MCAST_PASS 0
#define MCAST_NOTGMEMBER 1
#define MCAST_NOTSMEMBER 2
#define MCAST_MUTED 3
struct rib_head;
struct ip_moptions;
struct ucred;
struct in_multi *inm_lookup_locked(struct ifnet *, const struct in_addr);
struct in_multi *inm_lookup(struct ifnet *, const struct in_addr);
int imo_multi_filter(const struct ip_moptions *, const struct ifnet *,
const struct sockaddr *, const struct sockaddr *);
void inm_commit(struct in_multi *);
void inm_clear_recorded(struct in_multi *);
void inm_print(const struct in_multi *);
int inm_record_source(struct in_multi *inm, const in_addr_t);
void inm_release_deferred(struct in_multi *);
void inm_release_list_deferred(struct in_multi_head *);
void inm_release_wait(void *);
int in_joingroup(struct ifnet *, const struct in_addr *,
struct in_mfilter *, struct in_multi **);
int in_joingroup_locked(struct ifnet *, const struct in_addr *,
struct in_mfilter *, struct in_multi **);
int in_leavegroup(struct in_multi *, struct in_mfilter *);
int in_leavegroup_locked(struct in_multi *,
struct in_mfilter *);
int in_mask2len(struct in_addr *);
int in_control(struct socket *, u_long, void *, struct ifnet *,
struct thread *);
int in_control_ioctl(u_long, void *, struct ifnet *,
struct ucred *);
int in_addprefix(struct in_ifaddr *);
int in_scrubprefix(struct in_ifaddr *, u_int);
void in_ifscrub_all(void);
void ip_input(struct mbuf *);
void ip_direct_input(struct mbuf *);
void in_ifadown(struct ifaddr *ifa, int);
struct mbuf *ip_tryforward(struct mbuf *);
struct rib_head *in_inithead(uint32_t fibnum);
void in_ifattach(void *, struct ifnet *);
#ifdef VIMAGE
void in_detachhead(struct rib_head *rh);
#endif
#endif
#include <netinet6/in6_var.h>
#endif