code:
/*-
 * 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.
 *
 *	$KAME: in6_var.h,v 1.56 2001/03/29 05:34:31 itojun 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.
 * 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.
 *
 *	@(#)in_var.h	8.1 (Berkeley) 6/10/93
 * $FreeBSD: release/9.0.0/sys/netinet6/in6_var.h 207369 2010-04-29 11:52:42Z bz $
 */

#ifndef _NETINET6_IN6_VAR_H_
#define _NETINET6_IN6_VAR_H_

#include <sys/tree.h>

#ifdef _KERNEL
#include <sys/libkern.h>
#endif

/*
 * 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.
 */

/*
 * pltime/vltime are just for future reference (required to implements 2
 * hour rule for hosts).  they should never be modified by nd6_timeout or
 * anywhere else.
 *	userland -> kernel: accept pltime/vltime
 *	kernel -> userland: throw up everything
 *	in kernel: modify preferred/expire only
 */
struct in6_addrlifetime {
	time_t ia6t_expire;	/* valid lifetime expiration time */
	time_t ia6t_preferred;	/* preferred lifetime expiration time */
	u_int32_t ia6t_vltime;	/* valid lifetime */
	u_int32_t ia6t_pltime;	/* prefix lifetime */
};

struct nd_ifinfo;
struct scope6_id;
struct lltable;
struct mld_ifinfo;

struct in6_ifextra {
	struct in6_ifstat *in6_ifstat;
	struct icmp6_ifstat *icmp6_ifstat;
	struct nd_ifinfo *nd_ifinfo;
	struct scope6_id *scope6_id;
	struct lltable *lltable;
	struct mld_ifinfo *mld_ifinfo;
};

#define	LLTABLE6(ifp)	(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)

struct	in6_ifaddr {
	struct	ifaddr ia_ifa;		/* protocol-independent info */
#define	ia_ifp		ia_ifa.ifa_ifp
#define ia_flags	ia_ifa.ifa_flags
	struct	sockaddr_in6 ia_addr;	/* interface address */
	struct	sockaddr_in6 ia_net;	/* network number of interface */
	struct	sockaddr_in6 ia_dstaddr; /* space for destination addr */
	struct	sockaddr_in6 ia_prefixmask; /* prefix mask */
	u_int32_t ia_plen;		/* prefix length */
	TAILQ_ENTRY(in6_ifaddr)	ia_link;	/* list of IPv6 addresses */
	int	ia6_flags;

	struct in6_addrlifetime ia6_lifetime;
	time_t	ia6_createtime; /* the creation time of this address, which is
				 * currently used for temporary addresses only.
				 */
	time_t	ia6_updatetime;

	/* back pointer to the ND prefix (for autoconfigured addresses only) */
	struct nd_prefix *ia6_ndpr;

	/* multicast addresses joined from the kernel */
	LIST_HEAD(, in6_multi_mship) ia6_memberships;
};

/* List of in6_ifaddr's. */
TAILQ_HEAD(in6_ifaddrhead, in6_ifaddr);

/* control structure to manage address selection policy */
struct in6_addrpolicy {
	struct sockaddr_in6 addr; /* prefix address */
	struct sockaddr_in6 addrmask; /* prefix mask */
	int preced;		/* precedence */
	int label;		/* matching label */
	u_quad_t use;		/* statistics */
};

/*
 * IPv6 interface statistics, as defined in RFC2465 Ipv6IfStatsEntry (p12).
 */
struct in6_ifstat {
	u_quad_t ifs6_in_receive;	/* # of total input datagram */
	u_quad_t ifs6_in_hdrerr;	/* # of datagrams with invalid hdr */
	u_quad_t ifs6_in_toobig;	/* # of datagrams exceeded MTU */
	u_quad_t ifs6_in_noroute;	/* # of datagrams with no route */
	u_quad_t ifs6_in_addrerr;	/* # of datagrams with invalid dst */
	u_quad_t ifs6_in_protounknown;	/* # of datagrams with unknown proto */
					/* NOTE: increment on final dst if */
	u_quad_t ifs6_in_truncated;	/* # of truncated datagrams */
	u_quad_t ifs6_in_discard;	/* # of discarded datagrams */
					/* NOTE: fragment timeout is not here */
	u_quad_t ifs6_in_deliver;	/* # of datagrams delivered to ULP */
					/* NOTE: increment on final dst if */
	u_quad_t ifs6_out_forward;	/* # of datagrams forwarded */
					/* NOTE: increment on outgoing if */
	u_quad_t ifs6_out_request;	/* # of outgoing datagrams from ULP */
					/* NOTE: does not include forwrads */
	u_quad_t ifs6_out_discard;	/* # of discarded datagrams */
	u_quad_t ifs6_out_fragok;	/* # of datagrams fragmented */
	u_quad_t ifs6_out_fragfail;	/* # of datagrams failed on fragment */
	u_quad_t ifs6_out_fragcreat;	/* # of fragment datagrams */
					/* NOTE: this is # after fragment */
	u_quad_t ifs6_reass_reqd;	/* # of incoming fragmented packets */
					/* NOTE: increment on final dst if */
	u_quad_t ifs6_reass_ok;		/* # of reassembled packets */
					/* NOTE: this is # after reass */
					/* NOTE: increment on final dst if */
	u_quad_t ifs6_reass_fail;	/* # of reass failures */
					/* NOTE: may not be packet count */
					/* NOTE: increment on final dst if */
	u_quad_t ifs6_in_mcast;		/* # of inbound multicast datagrams */
	u_quad_t ifs6_out_mcast;	/* # of outbound multicast datagrams */
};

/*
 * ICMPv6 interface statistics, as defined in RFC2466 Ipv6IfIcmpEntry.
 * XXX: I'm not sure if this file is the right place for this structure...
 */
struct icmp6_ifstat {
	/*
	 * Input statistics
	 */
	/* ipv6IfIcmpInMsgs, total # of input messages */
	u_quad_t ifs6_in_msg;
	/* ipv6IfIcmpInErrors, # of input error messages */
	u_quad_t ifs6_in_error;
	/* ipv6IfIcmpInDestUnreachs, # of input dest unreach errors */
	u_quad_t ifs6_in_dstunreach;
	/* ipv6IfIcmpInAdminProhibs, # of input administratively prohibited errs */
	u_quad_t ifs6_in_adminprohib;
	/* ipv6IfIcmpInTimeExcds, # of input time exceeded errors */
	u_quad_t ifs6_in_timeexceed;
	/* ipv6IfIcmpInParmProblems, # of input parameter problem errors */
	u_quad_t ifs6_in_paramprob;
	/* ipv6IfIcmpInPktTooBigs, # of input packet too big errors */
	u_quad_t ifs6_in_pkttoobig;
	/* ipv6IfIcmpInEchos, # of input echo requests */
	u_quad_t ifs6_in_echo;
	/* ipv6IfIcmpInEchoReplies, # of input echo replies */
	u_quad_t ifs6_in_echoreply;
	/* ipv6IfIcmpInRouterSolicits, # of input router solicitations */
	u_quad_t ifs6_in_routersolicit;
	/* ipv6IfIcmpInRouterAdvertisements, # of input router advertisements */
	u_quad_t ifs6_in_routeradvert;
	/* ipv6IfIcmpInNeighborSolicits, # of input neighbor solicitations */
	u_quad_t ifs6_in_neighborsolicit;
	/* ipv6IfIcmpInNeighborAdvertisements, # of input neighbor advertisements */
	u_quad_t ifs6_in_neighboradvert;
	/* ipv6IfIcmpInRedirects, # of input redirects */
	u_quad_t ifs6_in_redirect;
	/* ipv6IfIcmpInGroupMembQueries, # of input MLD queries */
	u_quad_t ifs6_in_mldquery;
	/* ipv6IfIcmpInGroupMembResponses, # of input MLD reports */
	u_quad_t ifs6_in_mldreport;
	/* ipv6IfIcmpInGroupMembReductions, # of input MLD done */
	u_quad_t ifs6_in_mlddone;

	/*
	 * Output statistics. We should solve unresolved routing problem...
	 */
	/* ipv6IfIcmpOutMsgs, total # of output messages */
	u_quad_t ifs6_out_msg;
	/* ipv6IfIcmpOutErrors, # of output error messages */
	u_quad_t ifs6_out_error;
	/* ipv6IfIcmpOutDestUnreachs, # of output dest unreach errors */
	u_quad_t ifs6_out_dstunreach;
	/* ipv6IfIcmpOutAdminProhibs, # of output administratively prohibited errs */
	u_quad_t ifs6_out_adminprohib;
	/* ipv6IfIcmpOutTimeExcds, # of output time exceeded errors */
	u_quad_t ifs6_out_timeexceed;
	/* ipv6IfIcmpOutParmProblems, # of output parameter problem errors */
	u_quad_t ifs6_out_paramprob;
	/* ipv6IfIcmpOutPktTooBigs, # of output packet too big errors */
	u_quad_t ifs6_out_pkttoobig;
	/* ipv6IfIcmpOutEchos, # of output echo requests */
	u_quad_t ifs6_out_echo;
	/* ipv6IfIcmpOutEchoReplies, # of output echo replies */
	u_quad_t ifs6_out_echoreply;
	/* ipv6IfIcmpOutRouterSolicits, # of output router solicitations */
	u_quad_t ifs6_out_routersolicit;
	/* ipv6IfIcmpOutRouterAdvertisements, # of output router advertisements */
	u_quad_t ifs6_out_routeradvert;
	/* ipv6IfIcmpOutNeighborSolicits, # of output neighbor solicitations */
	u_quad_t ifs6_out_neighborsolicit;
	/* ipv6IfIcmpOutNeighborAdvertisements, # of output neighbor advertisements */
	u_quad_t ifs6_out_neighboradvert;
	/* ipv6IfIcmpOutRedirects, # of output redirects */
	u_quad_t ifs6_out_redirect;
	/* ipv6IfIcmpOutGroupMembQueries, # of output MLD queries */
	u_quad_t ifs6_out_mldquery;
	/* ipv6IfIcmpOutGroupMembResponses, # of output MLD reports */
	u_quad_t ifs6_out_mldreport;
	/* ipv6IfIcmpOutGroupMembReductions, # of output MLD done */
	u_quad_t ifs6_out_mlddone;
};

struct	in6_ifreq {
	char	ifr_name[IFNAMSIZ];
	union {
		struct	sockaddr_in6 ifru_addr;
		struct	sockaddr_in6 ifru_dstaddr;
		int	ifru_flags;
		int	ifru_flags6;
		int	ifru_metric;
		caddr_t	ifru_data;
		struct in6_addrlifetime ifru_lifetime;
		struct in6_ifstat ifru_stat;
		struct icmp6_ifstat ifru_icmp6stat;
		u_int32_t ifru_scope_id[16];
	} ifr_ifru;
};

struct	in6_aliasreq {
	char	ifra_name[IFNAMSIZ];
	struct	sockaddr_in6 ifra_addr;
	struct	sockaddr_in6 ifra_dstaddr;
	struct	sockaddr_in6 ifra_prefixmask;
	int	ifra_flags;
	struct in6_addrlifetime ifra_lifetime;
};

/* prefix type macro */
#define IN6_PREFIX_ND	1
#define IN6_PREFIX_RR	2

/*
 * prefix related flags passed between kernel(NDP related part) and
 * user land command(ifconfig) and daemon(rtadvd).
 */
struct in6_prflags {
	struct prf_ra {
		u_char onlink : 1;
		u_char autonomous : 1;
		u_char reserved : 6;
	} prf_ra;
	u_char prf_reserved1;
	u_short prf_reserved2;
	/* want to put this on 4byte offset */
	struct prf_rr {
		u_char decrvalid : 1;
		u_char decrprefd : 1;
		u_char reserved : 6;
	} prf_rr;
	u_char prf_reserved3;
	u_short prf_reserved4;
};

struct  in6_prefixreq {
	char	ipr_name[IFNAMSIZ];
	u_char	ipr_origin;
	u_char	ipr_plen;
	u_int32_t ipr_vltime;
	u_int32_t ipr_pltime;
	struct in6_prflags ipr_flags;
	struct	sockaddr_in6 ipr_prefix;
};

#define PR_ORIG_RA	0
#define PR_ORIG_RR	1
#define PR_ORIG_STATIC	2
#define PR_ORIG_KERNEL	3

#define ipr_raf_onlink		ipr_flags.prf_ra.onlink
#define ipr_raf_auto		ipr_flags.prf_ra.autonomous

#define ipr_statef_onlink	ipr_flags.prf_state.onlink

#define ipr_rrf_decrvalid	ipr_flags.prf_rr.decrvalid
#define ipr_rrf_decrprefd	ipr_flags.prf_rr.decrprefd

struct	in6_rrenumreq {
	char	irr_name[IFNAMSIZ];
	u_char	irr_origin;
	u_char	irr_m_len;	/* match len for matchprefix */
	u_char	irr_m_minlen;	/* minlen for matching prefix */
	u_char	irr_m_maxlen;	/* maxlen for matching prefix */
	u_char	irr_u_uselen;	/* uselen for adding prefix */
	u_char	irr_u_keeplen;	/* keeplen from matching prefix */
	struct irr_raflagmask {
		u_char onlink : 1;
		u_char autonomous : 1;
		u_char reserved : 6;
	} irr_raflagmask;
	u_int32_t irr_vltime;
	u_int32_t irr_pltime;
	struct in6_prflags irr_flags;
	struct	sockaddr_in6 irr_matchprefix;
	struct	sockaddr_in6 irr_useprefix;
};

#define irr_raf_mask_onlink	irr_raflagmask.onlink
#define irr_raf_mask_auto	irr_raflagmask.autonomous
#define irr_raf_mask_reserved	irr_raflagmask.reserved

#define irr_raf_onlink		irr_flags.prf_ra.onlink
#define irr_raf_auto		irr_flags.prf_ra.autonomous

#define irr_statef_onlink	irr_flags.prf_state.onlink

#define irr_rrf			irr_flags.prf_rr
#define irr_rrf_decrvalid	irr_flags.prf_rr.decrvalid
#define irr_rrf_decrprefd	irr_flags.prf_rr.decrprefd

/*
 * Given a pointer to an in6_ifaddr (ifaddr),
 * return a pointer to the addr as a sockaddr_in6
 */
#define IA6_IN6(ia)	(&((ia)->ia_addr.sin6_addr))
#define IA6_DSTIN6(ia)	(&((ia)->ia_dstaddr.sin6_addr))
#define IA6_MASKIN6(ia)	(&((ia)->ia_prefixmask.sin6_addr))
#define IA6_SIN6(ia)	(&((ia)->ia_addr))
#define IA6_DSTSIN6(ia)	(&((ia)->ia_dstaddr))
#define IFA_IN6(x)	(&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr)
#define IFA_DSTIN6(x)	(&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->sin6_addr)

#define IFPR_IN6(x)	(&((struct sockaddr_in6 *)((x)->ifpr_prefix))->sin6_addr)

#ifdef _KERNEL
#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m)	(	\
	(((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \
	(((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \
	(((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \
	(((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 )
#endif

#define SIOCSIFADDR_IN6		 _IOW('i', 12, struct in6_ifreq)
#define SIOCGIFADDR_IN6		_IOWR('i', 33, struct in6_ifreq)

#ifdef _KERNEL
/*
 * SIOCSxxx ioctls should be unused (see comments in in6.c), but
 * we do not shift numbers for binary compatibility.
 */
#define SIOCSIFDSTADDR_IN6	 _IOW('i', 14, struct in6_ifreq)
#define SIOCSIFNETMASK_IN6	 _IOW('i', 22, struct in6_ifreq)
#endif

#define SIOCGIFDSTADDR_IN6	_IOWR('i', 34, struct in6_ifreq)
#define SIOCGIFNETMASK_IN6	_IOWR('i', 37, struct in6_ifreq)

#define SIOCDIFADDR_IN6		 _IOW('i', 25, struct in6_ifreq)
#define SIOCAIFADDR_IN6		 _IOW('i', 26, struct in6_aliasreq)

#define SIOCSIFPHYADDR_IN6       _IOW('i', 70, struct in6_aliasreq)
#define	SIOCGIFPSRCADDR_IN6	_IOWR('i', 71, struct in6_ifreq)
#define	SIOCGIFPDSTADDR_IN6	_IOWR('i', 72, struct in6_ifreq)

#define SIOCGIFAFLAG_IN6	_IOWR('i', 73, struct in6_ifreq)

#define SIOCGDRLST_IN6		_IOWR('i', 74, struct in6_drlist)
#ifdef _KERNEL
/* XXX: SIOCGPRLST_IN6 is exposed in KAME but in6_oprlist is not. */
#define SIOCGPRLST_IN6		_IOWR('i', 75, struct in6_oprlist)
#endif
#ifdef _KERNEL
#define OSIOCGIFINFO_IN6	_IOWR('i', 76, struct in6_ondireq)
#endif
#define SIOCGIFINFO_IN6		_IOWR('i', 108, struct in6_ndireq)
#define SIOCSIFINFO_IN6		_IOWR('i', 109, struct in6_ndireq)
#define SIOCSNDFLUSH_IN6	_IOWR('i', 77, struct in6_ifreq)
#define SIOCGNBRINFO_IN6	_IOWR('i', 78, struct in6_nbrinfo)
#define SIOCSPFXFLUSH_IN6	_IOWR('i', 79, struct in6_ifreq)
#define SIOCSRTRFLUSH_IN6	_IOWR('i', 80, struct in6_ifreq)

#define SIOCGIFALIFETIME_IN6	_IOWR('i', 81, struct in6_ifreq)
#define SIOCSIFALIFETIME_IN6	_IOWR('i', 82, struct in6_ifreq)
#define SIOCGIFSTAT_IN6		_IOWR('i', 83, struct in6_ifreq)
#define SIOCGIFSTAT_ICMP6	_IOWR('i', 84, struct in6_ifreq)

#define SIOCSDEFIFACE_IN6	_IOWR('i', 85, struct in6_ndifreq)
#define SIOCGDEFIFACE_IN6	_IOWR('i', 86, struct in6_ndifreq)

#define SIOCSIFINFO_FLAGS	_IOWR('i', 87, struct in6_ndireq) /* XXX */

#define SIOCSSCOPE6		_IOW('i', 88, struct in6_ifreq)
#define SIOCGSCOPE6		_IOWR('i', 89, struct in6_ifreq)
#define SIOCGSCOPE6DEF		_IOWR('i', 90, struct in6_ifreq)

#define SIOCSIFPREFIX_IN6	_IOW('i', 100, struct in6_prefixreq) /* set */
#define SIOCGIFPREFIX_IN6	_IOWR('i', 101, struct in6_prefixreq) /* get */
#define SIOCDIFPREFIX_IN6	_IOW('i', 102, struct in6_prefixreq) /* del */
#define SIOCAIFPREFIX_IN6	_IOW('i', 103, struct in6_rrenumreq) /* add */
#define SIOCCIFPREFIX_IN6	_IOW('i', 104, \
				     struct in6_rrenumreq) /* change */
#define SIOCSGIFPREFIX_IN6	_IOW('i', 105, \
				     struct in6_rrenumreq) /* set global */

#define SIOCGETSGCNT_IN6	_IOWR('u', 106, \
				      struct sioc_sg_req6) /* get s,g pkt cnt */
#define SIOCGETMIFCNT_IN6	_IOWR('u', 107, \
				      struct sioc_mif_req6) /* get pkt cnt per if */

#define SIOCAADDRCTL_POLICY	_IOW('u', 108, struct in6_addrpolicy)
#define SIOCDADDRCTL_POLICY	_IOW('u', 109, struct in6_addrpolicy)

#define IN6_IFF_ANYCAST		0x01	/* anycast address */
#define IN6_IFF_TENTATIVE	0x02	/* tentative address */
#define IN6_IFF_DUPLICATED	0x04	/* DAD detected duplicate */
#define IN6_IFF_DETACHED	0x08	/* may be detached from the link */
#define IN6_IFF_DEPRECATED	0x10	/* deprecated address */
#define IN6_IFF_NODAD		0x20	/* don't perform DAD on this address
					 * (used only at first SIOC* call)
					 */
#define IN6_IFF_AUTOCONF	0x40	/* autoconfigurable address. */
#define IN6_IFF_TEMPORARY	0x80	/* temporary (anonymous) address. */
#define IN6_IFF_NOPFX		0x8000	/* skip kernel prefix management.
					 * XXX: this should be temporary.
					 */

/* do not input/output */
#define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)

#ifdef _KERNEL
#define IN6_ARE_SCOPE_CMP(a,b) ((a)-(b))
#define IN6_ARE_SCOPE_EQUAL(a,b) ((a)==(b))
#endif

#ifdef _KERNEL
VNET_DECLARE(struct in6_ifaddrhead, in6_ifaddrhead);
#define	V_in6_ifaddrhead		VNET(in6_ifaddrhead)

extern struct rwlock in6_ifaddr_lock;
#define	IN6_IFADDR_LOCK_ASSERT(	)	rw_assert(&in6_ifaddr_lock, RA_LOCKED)
#define	IN6_IFADDR_RLOCK()		rw_rlock(&in6_ifaddr_lock)
#define	IN6_IFADDR_RLOCK_ASSERT()	rw_assert(&in6_ifaddr_lock, RA_RLOCKED)
#define	IN6_IFADDR_RUNLOCK()		rw_runlock(&in6_ifaddr_lock)
#define	IN6_IFADDR_WLOCK()		rw_wlock(&in6_ifaddr_lock)
#define	IN6_IFADDR_WLOCK_ASSERT()	rw_assert(&in6_ifaddr_lock, RA_WLOCKED)
#define	IN6_IFADDR_WUNLOCK()		rw_wunlock(&in6_ifaddr_lock)

VNET_DECLARE(struct icmp6stat, icmp6stat);
#define	V_icmp6stat			VNET(icmp6stat)
#define in6_ifstat_inc(ifp, tag) \
do {								\
	if (ifp)						\
		((struct in6_ifextra *)((ifp)->if_afdata[AF_INET6]))->in6_ifstat->tag++; \
} while (/*CONSTCOND*/ 0)

extern struct in6_addr zeroin6_addr;
extern u_char inet6ctlerrmap[];
VNET_DECLARE(unsigned long, in6_maxmtu);
#define	V_in6_maxmtu			VNET(in6_maxmtu)
#endif /* _KERNEL */

/*
 * IPv6 multicast MLD-layer source entry.
 */
struct ip6_msource {
	RB_ENTRY(ip6_msource)	im6s_link;	/* RB tree links */
	struct in6_addr		im6s_addr;
	struct im6s_st {
		uint16_t	ex;		/* # of exclusive members */
		uint16_t	in;		/* # of inclusive members */
	}			im6s_st[2];	/* state at t0, t1 */
	uint8_t			im6s_stp;	/* pending query */
};
RB_HEAD(ip6_msource_tree, ip6_msource);

/*
 * IPv6 multicast PCB-layer source entry.
 *
 * NOTE: overlapping use of struct ip6_msource fields at start.
 */
struct in6_msource {
	RB_ENTRY(ip6_msource)	im6s_link;	/* Common field */
	struct in6_addr		im6s_addr;	/* Common field */
	uint8_t			im6sl_st[2];	/* state before/at commit */
};

#ifdef _KERNEL
/*
 * IPv6 source tree comparison function.
 *
 * An ordered predicate is necessary; bcmp() is not documented to return
 * an indication of order, memcmp() is, and is an ISO C99 requirement.
 */
static __inline int
ip6_msource_cmp(const struct ip6_msource *a, const struct ip6_msource *b)
{

	return (memcmp(&a->im6s_addr, &b->im6s_addr, sizeof(struct in6_addr)));
}
RB_PROTOTYPE(ip6_msource_tree, ip6_msource, im6s_link, ip6_msource_cmp);
#endif /* _KERNEL */

/*
 * IPv6 multicast PCB-layer group filter descriptor.
 */
struct in6_mfilter {
	struct ip6_msource_tree	im6f_sources; /* source list for (S,G) */
	u_long			im6f_nsrc;    /* # of source entries */
	uint8_t			im6f_st[2];   /* state before/at commit */
};

/*
 * Legacy KAME IPv6 multicast membership descriptor.
 */
struct in6_multi_mship {
	struct	in6_multi *i6mm_maddr;
	LIST_ENTRY(in6_multi_mship) i6mm_chain;
};

/*
 * IPv6 group descriptor.
 *
 * For every entry on an ifnet's if_multiaddrs list which represents
 * an IP multicast group, there is one of these structures.
 *
 * If any source filters are present, then a node will exist in the RB-tree
 * to permit fast lookup by source whenever an operation takes place.
 * This permits pre-order traversal when we issue reports.
 * Source filter trees are kept separately from the socket layer to
 * greatly simplify locking.
 *
 * When MLDv2 is active, in6m_timer is the response to group query timer.
 * The state-change timer in6m_sctimer is separate; whenever state changes
 * for the group the state change record is generated and transmitted,
 * and kept if retransmissions are necessary.
 *
 * FUTURE: in6m_link is now only used when groups are being purged
 * on a detaching ifnet. It could be demoted to a SLIST_ENTRY, but
 * because it is at the very start of the struct, we can't do this
 * w/o breaking the ABI for ifmcstat.
 */
struct in6_multi {
	LIST_ENTRY(in6_multi) in6m_entry; /* list glue */
	struct	in6_addr in6m_addr;	/* IPv6 multicast address */
	struct	ifnet *in6m_ifp;	/* back pointer to ifnet */
	struct	ifmultiaddr *in6m_ifma;	/* back pointer to ifmultiaddr */
	u_int	in6m_refcount;		/* reference count */
	u_int	in6m_state;		/* state of the membership */
	u_int	in6m_timer;		/* MLD6 listener report timer */

	/* New fields for MLDv2 follow. */
	struct mld_ifinfo	*in6m_mli;	/* MLD info */
	SLIST_ENTRY(in6_multi)	 in6m_nrele;	/* to-be-released by MLD */
	struct ip6_msource_tree	 in6m_srcs;	/* tree of sources */
	u_long			 in6m_nsrc;	/* # of tree entries */

	struct ifqueue		 in6m_scq;	/* queue of pending
						 * state-change packets */
	struct timeval		 in6m_lastgsrtv;	/* last G-S-R query */
	uint16_t		 in6m_sctimer;	/* state-change timer */
	uint16_t		 in6m_scrv;	/* state-change rexmit count */

	/*
	 * SSM state counters which track state at T0 (the time the last
	 * state-change report's RV timer went to zero) and T1
	 * (time of pending report, i.e. now).
	 * Used for computing MLDv2 state-change reports. Several refcounts
	 * are maintained here to optimize for common use-cases.
	 */
	struct in6m_st {
		uint16_t	iss_fmode;	/* MLD filter mode */
		uint16_t	iss_asm;	/* # of ASM listeners */
		uint16_t	iss_ex;		/* # of exclusive members */
		uint16_t	iss_in;		/* # of inclusive members */
		uint16_t	iss_rec;	/* # of recorded sources */
	}			in6m_st[2];	/* state at t0, t1 */
};

/*
 * Helper function to derive the filter mode on a source entry
 * from its internal counters. Predicates are:
 *  A source is only excluded if all listeners exclude it.
 *  A source is only included if no listeners exclude it,
 *  and at least one listener includes it.
 * May be used by ifmcstat(8).
 */
static __inline uint8_t
im6s_get_mode(const struct in6_multi *inm, const struct ip6_msource *ims,
    uint8_t t)
{

	t = !!t;
	if (inm->in6m_st[t].iss_ex > 0 &&
	    inm->in6m_st[t].iss_ex == ims->im6s_st[t].ex)
		return (MCAST_EXCLUDE);
	else if (ims->im6s_st[t].in > 0 && ims->im6s_st[t].ex == 0)
		return (MCAST_INCLUDE);
	return (MCAST_UNDEFINED);
}

#ifdef _KERNEL

/*
 * Lock macros for IPv6 layer multicast address lists.  IPv6 lock goes
 * before link layer multicast locks in the lock order.  In most cases,
 * consumers of IN_*_MULTI() macros should acquire the locks before
 * calling them; users of the in_{add,del}multi() functions should not.
 */
extern struct mtx in6_multi_mtx;
#define	IN6_MULTI_LOCK()		mtx_lock(&in6_multi_mtx)
#define	IN6_MULTI_UNLOCK()		mtx_unlock(&in6_multi_mtx)
#define	IN6_MULTI_LOCK_ASSERT()		mtx_assert(&in6_multi_mtx, MA_OWNED)
#define	IN6_MULTI_UNLOCK_ASSERT()	mtx_assert(&in6_multi_mtx, MA_NOTOWNED)

/*
 * Look up an in6_multi record for an IPv6 multicast address
 * on the interface ifp.
 * If no record found, return NULL.
 *
 * SMPng: The IN6_MULTI_LOCK and IF_ADDR_LOCK on ifp must be held.
 */
static __inline struct in6_multi *
in6m_lookup_locked(struct ifnet *ifp, const struct in6_addr *mcaddr)
{
	struct ifmultiaddr *ifma;
	struct in6_multi *inm;

	IN6_MULTI_LOCK_ASSERT();
	IF_ADDR_LOCK_ASSERT(ifp);

	inm = NULL;
	TAILQ_FOREACH(ifma, &((ifp)->if_multiaddrs), ifma_link) {
		if (ifma->ifma_addr->sa_family == AF_INET6) {
			inm = (struct in6_multi *)ifma->ifma_protospec;
			if (IN6_ARE_ADDR_EQUAL(&inm->in6m_addr, mcaddr))
				break;
			inm = NULL;
		}
	}
	return (inm);
}

/*
 * Wrapper for in6m_lookup_locked().
 *
 * SMPng: Assumes that neithr the IN6_MULTI_LOCK() or IF_ADDR_LOCK() are held.
 */
static __inline struct in6_multi *
in6m_lookup(struct ifnet *ifp, const struct in6_addr *mcaddr)
{
	struct in6_multi *inm;

	IN6_MULTI_LOCK();
	IF_ADDR_LOCK(ifp);
	inm = in6m_lookup_locked(ifp, mcaddr);
	IF_ADDR_UNLOCK(ifp);
	IN6_MULTI_UNLOCK();

	return (inm);
}

/* Acquire an in6_multi record. */
static __inline void
in6m_acquire_locked(struct in6_multi *inm)
{

	IN6_MULTI_LOCK_ASSERT();
	++inm->in6m_refcount;
}

struct ip6_moptions;
struct sockopt;

/* Multicast KPIs. */
int	im6o_mc_filter(const struct ip6_moptions *, const struct ifnet *,
	    const struct sockaddr *, const struct sockaddr *);
int	in6_mc_join(struct ifnet *, const struct in6_addr *,
	    struct in6_mfilter *, struct in6_multi **, int);
int	in6_mc_join_locked(struct ifnet *, const struct in6_addr *,
	    struct in6_mfilter *, struct in6_multi **, int);
int	in6_mc_leave(struct in6_multi *, struct in6_mfilter *);
int	in6_mc_leave_locked(struct in6_multi *, struct in6_mfilter *);
void	in6m_clear_recorded(struct in6_multi *);
void	in6m_commit(struct in6_multi *);
void	in6m_print(const struct in6_multi *);
int	in6m_record_source(struct in6_multi *, const struct in6_addr *);
void	in6m_release_locked(struct in6_multi *);
void	ip6_freemoptions(struct ip6_moptions *);
int	ip6_getmoptions(struct inpcb *, struct sockopt *);
int	ip6_setmoptions(struct inpcb *, struct sockopt *);

/* Legacy KAME multicast KPIs. */
struct in6_multi_mship *
	in6_joingroup(struct ifnet *, struct in6_addr *, int *, int);
int	in6_leavegroup(struct in6_multi_mship *);

/* flags to in6_update_ifa */
#define IN6_IFAUPDATE_DADDELAY	0x1 /* first time to configure an address */

int	in6_mask2len __P((struct in6_addr *, u_char *));
int	in6_control __P((struct socket *, u_long, caddr_t, struct ifnet *,
	struct thread *));
int	in6_update_ifa __P((struct ifnet *, struct in6_aliasreq *,
	struct in6_ifaddr *, int));
void	in6_purgeaddr __P((struct ifaddr *));
int	in6if_do_dad __P((struct ifnet *));
void	in6_purgeif __P((struct ifnet *));
void	in6_savemkludge __P((struct in6_ifaddr *));
void	*in6_domifattach __P((struct ifnet *));
void	in6_domifdetach __P((struct ifnet *, void *));
void	in6_setmaxmtu   __P((void));
int	in6_if2idlen   __P((struct ifnet *));
struct in6_ifaddr *in6ifa_ifpforlinklocal __P((struct ifnet *, int));
struct in6_ifaddr *in6ifa_ifpwithaddr __P((struct ifnet *, struct in6_addr *));
char	*ip6_sprintf __P((char *, const struct in6_addr *));
int	in6_addr2zoneid __P((struct ifnet *, struct in6_addr *, u_int32_t *));
int	in6_matchlen __P((struct in6_addr *, struct in6_addr *));
int	in6_are_prefix_equal __P((struct in6_addr *, struct in6_addr *, int));
void	in6_prefixlen2mask __P((struct in6_addr *, int));
int	in6_prefix_ioctl __P((struct socket *, u_long, caddr_t,
	struct ifnet *));
int	in6_prefix_add_ifid __P((int, struct in6_ifaddr *));
void	in6_prefix_remove_ifid __P((int, struct in6_ifaddr *));
void	in6_purgeprefix __P((struct ifnet *));
void	in6_ifremloop(struct ifaddr *);
void	in6_ifaddloop(struct ifaddr *);

int	in6_is_addr_deprecated __P((struct sockaddr_in6 *));
struct inpcb;
int in6_src_ioctl __P((u_long, caddr_t));
#endif /* _KERNEL */

#endif /* _NETINET6_IN6_VAR_H_ */


code:
/*	$FreeBSD: release/9.0.0/sys/netinet6/ip6.h 62587 2000-07-04 16:35:15Z itojun $	*/
/*	$KAME: ip6.h,v 1.7 2000/03/25 07:23:36 sumikawa Exp $	*/

#error "netinet6/ip6.h is obsolete.  use netinet/ip6.h"

repo_name: veiledmerc/mira

license: mit


code:
/*-
 * Copyright (C) 1999 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.
 *
 *	$KAME: ip_ecn.h,v 1.5 2000/03/27 04:58:38 sumikawa Exp $
 * $FreeBSD: release/9.0.0/sys/netinet6/ip6_ecn.h 174510 2007-12-10 16:03:40Z obrien $
 */

/*
 * ECN consideration on tunnel ingress/egress operation.
 * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
 */

#ifdef _KERNEL
extern void ip6_ecn_ingress(int, u_int32_t *, const u_int32_t *);
extern int ip6_ecn_egress(int, const u_int32_t *, u_int32_t *);
#endif


code:
/*-
 * Copyright (c) 1982, 1986, 1988, 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.
 * 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.
 *
 * $FreeBSD: release/9.0.0/sys/netinet6/ip6_ipsec.h 177166 2008-03-14 11:44:30Z bz $
 */

#ifndef _NETINET_IP6_IPSEC_H_
#define _NETINET_IP6_IPSEC_H_

int	ip6_ipsec_filtertunnel(struct mbuf *);
int	ip6_ipsec_fwd(struct mbuf *);
int	ip6_ipsec_input(struct mbuf *, int);
int	ip6_ipsec_output(struct mbuf **, struct inpcb *, int *, int *,
	    struct ifnet **, struct secpolicy **sp);
#if 0
int	ip6_ipsec_mtu(struct mbuf *);
#endif
#endif


code:
/*-
 * Copyright (C) 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.
 *
 *	$KAME: ip6_mroute.h,v 1.19 2001/06/14 06:12:55 suz Exp $
 * $FreeBSD: release/9.0.0/sys/netinet6/ip6_mroute.h 194581 2009-06-21 10:29:31Z rdivacky $
 */

/*	BSDI ip_mroute.h,v 2.5 1996/10/11 16:01:48 pjd Exp	*/

/*
 * Definitions for IP multicast forwarding.
 *
 * Written by David Waitzman, BBN Labs, August 1988.
 * Modified by Steve Deering, Stanford, February 1989.
 * Modified by Ajit Thyagarajan, PARC, August 1993.
 * Modified by Ajit Thyagarajan, PARC, August 1994.
 * Modified by Ahmed Helmy, USC, September 1996.
 *
 * MROUTING Revision: 1.2
 */

#ifndef _NETINET6_IP6_MROUTE_H_
#define _NETINET6_IP6_MROUTE_H_

/*
 * Multicast Routing set/getsockopt commands.
 */
#ifdef _KERNEL
#define MRT6_OINIT		100	/* initialize forwarder (omrt6msg) */
#endif
#define MRT6_DONE		101	/* shut down forwarder */
#define MRT6_ADD_MIF		102	/* add multicast interface */
#define MRT6_DEL_MIF		103	/* delete multicast interface */
#define MRT6_ADD_MFC		104	/* insert forwarding cache entry */
#define MRT6_DEL_MFC		105	/* delete forwarding cache entry */
#define MRT6_PIM                107     /* enable pim code */
#define MRT6_INIT		108	/* initialize forwarder (mrt6msg) */

#if BSD >= 199103
#define GET_TIME(t)	microtime(&t)
#elif defined(sun)
#define GET_TIME(t)	uniqtime(&t)
#else
#define GET_TIME(t)	((t) = time)
#endif

/*
 * Types and macros for handling bitmaps with one bit per multicast interface.
 */
typedef u_short mifi_t;		/* type of a mif index */
#define MAXMIFS		64

#ifndef	IF_SETSIZE
#define	IF_SETSIZE	256
#endif

typedef	u_int32_t	if_mask;
#define	NIFBITS	(sizeof(if_mask) * NBBY)	/* bits per mask */

#ifndef howmany
#define	howmany(x, y)	(((x) + ((y) - 1)) / (y))
#endif

typedef	struct if_set {
	if_mask	ifs_bits[howmany(IF_SETSIZE, NIFBITS)];
} if_set;

#define	IF_SET(n, p)	((p)->ifs_bits[(n)/NIFBITS] |= (1 << ((n) % NIFBITS)))
#define	IF_CLR(n, p)	((p)->ifs_bits[(n)/NIFBITS] &= ~(1 << ((n) % NIFBITS)))
#define	IF_ISSET(n, p)	((p)->ifs_bits[(n)/NIFBITS] & (1 << ((n) % NIFBITS)))
#define	IF_COPY(f, t)	bcopy(f, t, sizeof(*(f)))
#define	IF_ZERO(p)	bzero(p, sizeof(*(p)))

/*
 * Argument structure for MRT6_ADD_IF.
 */
struct mif6ctl {
	mifi_t	    mif6c_mifi;		/* the index of the mif to be added  */
	u_char	    mif6c_flags;	/* MIFF_ flags defined below         */
	u_short	    mif6c_pifi;		/* the index of the physical IF */
};

#define	MIFF_REGISTER	0x1	/* mif represents a register end-point */

/*
 * Argument structure for MRT6_ADD_MFC and MRT6_DEL_MFC
 */
struct mf6cctl {
	struct sockaddr_in6 mf6cc_origin;	/* IPv6 origin of mcasts */
	struct sockaddr_in6 mf6cc_mcastgrp; /* multicast group associated */
	mifi_t		mf6cc_parent;	/* incoming ifindex */
	struct if_set	mf6cc_ifset;	/* set of forwarding ifs */
};

/*
 * The kernel's multicast routing statistics.
 */
struct mrt6stat {
	u_quad_t mrt6s_mfc_lookups;	/* # forw. cache hash table hits   */
	u_quad_t mrt6s_mfc_misses;	/* # forw. cache hash table misses */
	u_quad_t mrt6s_upcalls;		/* # calls to multicast routing daemon */
	u_quad_t mrt6s_no_route;	/* no route for packet's origin    */
	u_quad_t mrt6s_bad_tunnel;	/* malformed tunnel options        */
	u_quad_t mrt6s_cant_tunnel;	/* no room for tunnel options      */
	u_quad_t mrt6s_wrong_if;	/* arrived on wrong interface	   */
	u_quad_t mrt6s_upq_ovflw;	/* upcall Q overflow		   */
	u_quad_t mrt6s_cache_cleanups;	/* # entries with no upcalls	   */
	u_quad_t mrt6s_drop_sel;	/* pkts dropped selectively        */
	u_quad_t mrt6s_q_overflow;	/* pkts dropped - Q overflow       */
	u_quad_t mrt6s_pkt2large;	/* pkts dropped - size > BKT SIZE  */
	u_quad_t mrt6s_upq_sockfull;	/* upcalls dropped - socket full   */
};

#ifdef MRT6_OINIT
/*
 * Struct used to communicate from kernel to multicast router
 * note the convenient similarity to an IPv6 header.
 * XXX old version, superseded by mrt6msg.
 */
struct omrt6msg {
	u_long	    unused1;
	u_char	    im6_msgtype;		/* what type of message	    */
#if 0
#define MRT6MSG_NOCACHE	1
#define MRT6MSG_WRONGMIF	2
#define MRT6MSG_WHOLEPKT	3		/* used for user level encap*/
#endif
	u_char	    im6_mbz;			/* must be zero		    */
	u_char	    im6_mif;			/* mif rec'd on		    */
	u_char	    unused2;
	struct in6_addr  im6_src, im6_dst;
};
#endif

/*
 * Structure used to communicate from kernel to multicast router.
 * We'll overlay the structure onto an MLD header (not an IPv6 header
 * like igmpmsg{} used for IPv4 implementation). This is because this
 * structure will be passed via an IPv6 raw socket, on which an application
 * will only receive the payload i.e. the data after the IPv6 header and all
 * the extension headers. (see Section 3 of RFC3542)
 */
struct mrt6msg {
#define MRT6MSG_NOCACHE		1
#define MRT6MSG_WRONGMIF	2
#define MRT6MSG_WHOLEPKT	3		/* used for user level encap*/
	u_char	    im6_mbz;			/* must be zero		    */
	u_char	    im6_msgtype;		/* what type of message	    */
	u_int16_t   im6_mif;			/* mif rec'd on		    */
	u_int32_t   im6_pad;			/* padding for 64bit arch   */
	struct in6_addr  im6_src, im6_dst;
};

/*
 * Argument structure used by multicast routing daemon to get src-grp
 * packet counts
 */
struct sioc_sg_req6 {
	struct sockaddr_in6 src;
	struct sockaddr_in6 grp;
	u_quad_t pktcnt;
	u_quad_t bytecnt;
	u_quad_t wrong_if;
};

/*
 * Argument structure used by mrouted to get mif pkt counts
 */
struct sioc_mif_req6 {
	mifi_t mifi;		/* mif number				*/
	u_quad_t icount;	/* Input packet count on mif		*/
	u_quad_t ocount;	/* Output packet count on mif		*/
	u_quad_t ibytes;	/* Input byte count on mif		*/
	u_quad_t obytes;	/* Output byte count on mif		*/
};

#if defined(_KERNEL) || defined(KERNEL)
/*
 * The kernel's multicast-interface structure.
 */
struct mif6 {
        u_char		m6_flags;	/* MIFF_ flags defined above         */
	u_int		m6_rate_limit;	/* max rate			     */
	struct in6_addr	m6_lcl_addr;	/* local interface address           */
	struct ifnet    *m6_ifp;	/* pointer to interface              */
	u_quad_t	m6_pkt_in;	/* # pkts in on interface            */
	u_quad_t	m6_pkt_out;	/* # pkts out on interface           */
	u_quad_t	m6_bytes_in;	/* # bytes in on interface	     */
	u_quad_t	m6_bytes_out;	/* # bytes out on interface	     */
	struct route_in6 m6_route;	/* cached route */
#ifdef notyet
	u_int		m6_rsvp_on;	/* RSVP listening on this vif */
	struct socket   *m6_rsvpd;	/* RSVP daemon socket */
#endif
};

/*
 * The kernel's multicast forwarding cache entry structure
 */
struct mf6c {
	struct sockaddr_in6  mf6c_origin;	/* IPv6 origin of mcasts     */
	struct sockaddr_in6  mf6c_mcastgrp;	/* multicast group associated*/
	mifi_t		 mf6c_parent;		/* incoming IF               */
	struct if_set	 mf6c_ifset;		/* set of outgoing IFs */

	u_quad_t	mf6c_pkt_cnt;		/* pkt count for src-grp     */
	u_quad_t	mf6c_byte_cnt;		/* byte count for src-grp    */
	u_quad_t	mf6c_wrong_if;		/* wrong if for src-grp	     */
	int		mf6c_expire;		/* time to clean entry up    */
	struct timeval  mf6c_last_assert;	/* last time I sent an assert*/
	struct rtdetq  *mf6c_stall;		/* pkts waiting for route */
	struct mf6c    *mf6c_next;		/* hash table linkage */
};

#define MF6C_INCOMPLETE_PARENT ((mifi_t)-1)

/*
 * Argument structure used for pkt info. while upcall is made
 */
#ifndef _NETINET_IP_MROUTE_H_
struct rtdetq {		/* XXX: rtdetq is also defined in ip_mroute.h */
    struct mbuf		*m;		/* A copy of the packet		    */
    struct ifnet	*ifp;		/* Interface pkt came in on	    */
#ifdef UPCALL_TIMING
    struct timeval	t;		/* Timestamp */
#endif /* UPCALL_TIMING */
    struct rtdetq	*next;
};
#endif /* _NETINET_IP_MROUTE_H_ */

#define MF6CTBLSIZ	256
#if (MF6CTBLSIZ & (MF6CTBLSIZ - 1)) == 0	  /* from sys:route.h */
#define MF6CHASHMOD(h)	((h) & (MF6CTBLSIZ - 1))
#else
#define MF6CHASHMOD(h)	((h) % MF6CTBLSIZ)
#endif

#define MAX_UPQ6	4		/* max. no of pkts in upcall Q */

extern int	(*ip6_mrouter_set)(struct socket *so, struct sockopt *sopt);
extern int	(*ip6_mrouter_get)(struct socket *so, struct sockopt *sopt);
extern int	(*ip6_mrouter_done)(void);
extern int	(*mrt6_ioctl)(u_long, caddr_t);
#endif /* _KERNEL */

#endif /* !_NETINET6_IP6_MROUTE_H_ */


code:
/*-
 * 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.
 *
 *	$KAME: ip6_var.h,v 1.62 2001/05/03 14:51:48 itojun Exp $
 */

/*-
 * Copyright (c) 1982, 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.
 * 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.
 *
 *	@(#)ip_var.h	8.1 (Berkeley) 6/10/93
 * $FreeBSD: release/9.0.0/sys/netinet6/ip6_var.h 225521 2011-09-13 00:06:11Z hrs $
 */

#ifndef _NETINET6_IP6_VAR_H_
#define _NETINET6_IP6_VAR_H_

/*
 * IP6 reassembly queue structure.  Each fragment
 * being reassembled is attached to one of these structures.
 */
struct	ip6q {
	struct ip6asfrag *ip6q_down;
	struct ip6asfrag *ip6q_up;
	u_int32_t	ip6q_ident;
	u_int8_t	ip6q_nxt;
	u_int8_t	ip6q_ecn;
	u_int8_t	ip6q_ttl;
	struct in6_addr ip6q_src, ip6q_dst;
	struct ip6q	*ip6q_next;
	struct ip6q	*ip6q_prev;
	int		ip6q_unfrglen;	/* len of unfragmentable part */
#ifdef notyet
	u_char		*ip6q_nxtp;
#endif
	int		ip6q_nfrag;	/* # of fragments */
	struct label	*ip6q_label;
};

struct	ip6asfrag {
	struct ip6asfrag *ip6af_down;
	struct ip6asfrag *ip6af_up;
	struct mbuf	*ip6af_m;
	int		ip6af_offset;	/* offset in ip6af_m to next header */
	int		ip6af_frglen;	/* fragmentable part length */
	int		ip6af_off;	/* fragment offset */
	u_int16_t	ip6af_mff;	/* more fragment bit in frag off */
};

#define IP6_REASS_MBUF(ip6af) (*(struct mbuf **)&((ip6af)->ip6af_m))

/*
 * Structure attached to inpcb.in6p_moptions and
 * passed to ip6_output when IPv6 multicast options are in use.
 * This structure is lazy-allocated.
 */
struct ip6_moptions {
	struct	ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */
	u_char	im6o_multicast_hlim;	/* hoplimit for outgoing multicasts */
	u_char	im6o_multicast_loop;	/* 1 >= hear sends if a member */
	u_short	im6o_num_memberships;	/* no. memberships this socket */
	u_short	im6o_max_memberships;	/* max memberships this socket */
	struct	in6_multi **im6o_membership;	/* group memberships */
	struct	in6_mfilter *im6o_mfilters;	/* source filters */
};

/*
 * Control options for outgoing packets
 */

/* Routing header related info */
struct	ip6po_rhinfo {
	struct	ip6_rthdr *ip6po_rhi_rthdr; /* Routing header */
	struct	route_in6 ip6po_rhi_route; /* Route to the 1st hop */
};
#define ip6po_rthdr	ip6po_rhinfo.ip6po_rhi_rthdr
#define ip6po_route	ip6po_rhinfo.ip6po_rhi_route

/* Nexthop related info */
struct	ip6po_nhinfo {
	struct	sockaddr *ip6po_nhi_nexthop;
	struct	route_in6 ip6po_nhi_route; /* Route to the nexthop */
};
#define ip6po_nexthop	ip6po_nhinfo.ip6po_nhi_nexthop
#define ip6po_nextroute	ip6po_nhinfo.ip6po_nhi_route

struct	ip6_pktopts {
	struct	mbuf *ip6po_m;	/* Pointer to mbuf storing the data */
	int	ip6po_hlim;	/* Hoplimit for outgoing packets */

	/* Outgoing IF/address information */
	struct	in6_pktinfo *ip6po_pktinfo;

	/* Next-hop address information */
	struct	ip6po_nhinfo ip6po_nhinfo;

	struct	ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */

	/* Destination options header (before a routing header) */
	struct	ip6_dest *ip6po_dest1;

	/* Routing header related info. */
	struct	ip6po_rhinfo ip6po_rhinfo;

	/* Destination options header (after a routing header) */
	struct	ip6_dest *ip6po_dest2;

	int	ip6po_tclass;	/* traffic class */

	int	ip6po_minmtu;  /* fragment vs PMTU discovery policy */
#define IP6PO_MINMTU_MCASTONLY	-1 /* default; send at min MTU for multicast*/
#define IP6PO_MINMTU_DISABLE	 0 /* always perform pmtu disc */
#define IP6PO_MINMTU_ALL	 1 /* always send at min MTU */

	int	ip6po_prefer_tempaddr;  /* whether temporary addresses are
					   preferred as source address */
#define IP6PO_TEMPADDR_SYSTEM	-1 /* follow the system default */
#define IP6PO_TEMPADDR_NOTPREFER 0 /* not prefer temporary address */
#define IP6PO_TEMPADDR_PREFER	 1 /* prefer temporary address */

	int ip6po_flags;
#if 0	/* parameters in this block is obsolete. do not reuse the values. */
#define IP6PO_REACHCONF	0x01	/* upper-layer reachability confirmation. */
#define IP6PO_MINMTU	0x02	/* use minimum MTU (IPV6_USE_MIN_MTU) */
#endif
#define IP6PO_DONTFRAG	0x04	/* disable fragmentation (IPV6_DONTFRAG) */
#define IP6PO_USECOA	0x08	/* use care of address */
};

/*
 * Control options for incoming packets
 */

struct	ip6stat {
	u_quad_t ip6s_total;		/* total packets received */
	u_quad_t ip6s_tooshort;		/* packet too short */
	u_quad_t ip6s_toosmall;		/* not enough data */
	u_quad_t ip6s_fragments;	/* fragments received */
	u_quad_t ip6s_fragdropped;	/* frags dropped(dups, out of space) */
	u_quad_t ip6s_fragtimeout;	/* fragments timed out */
	u_quad_t ip6s_fragoverflow;	/* fragments that exceeded limit */
	u_quad_t ip6s_forward;		/* packets forwarded */
	u_quad_t ip6s_cantforward;	/* packets rcvd for unreachable dest */
	u_quad_t ip6s_redirectsent;	/* packets forwarded on same net */
	u_quad_t ip6s_delivered;	/* datagrams delivered to upper level*/
	u_quad_t ip6s_localout;		/* total ip packets generated here */
	u_quad_t ip6s_odropped;		/* lost packets due to nobufs, etc. */
	u_quad_t ip6s_reassembled;	/* total packets reassembled ok */
	u_quad_t ip6s_fragmented;	/* datagrams successfully fragmented */
	u_quad_t ip6s_ofragments;	/* output fragments created */
	u_quad_t ip6s_cantfrag;		/* don't fragment flag was set, etc. */
	u_quad_t ip6s_badoptions;	/* error in option processing */
	u_quad_t ip6s_noroute;		/* packets discarded due to no route */
	u_quad_t ip6s_badvers;		/* ip6 version != 6 */
	u_quad_t ip6s_rawout;		/* total raw ip packets generated */
	u_quad_t ip6s_badscope;		/* scope error */
	u_quad_t ip6s_notmember;	/* don't join this multicast group */
	u_quad_t ip6s_nxthist[256];	/* next header history */
	u_quad_t ip6s_m1;		/* one mbuf */
	u_quad_t ip6s_m2m[32];		/* two or more mbuf */
	u_quad_t ip6s_mext1;		/* one ext mbuf */
	u_quad_t ip6s_mext2m;		/* two or more ext mbuf */
	u_quad_t ip6s_exthdrtoolong;	/* ext hdr are not contiguous */
	u_quad_t ip6s_nogif;		/* no match gif found */
	u_quad_t ip6s_toomanyhdr;	/* discarded due to too many headers */

	/*
	 * statistics for improvement of the source address selection
	 * algorithm:
	 * XXX: hardcoded 16 = # of ip6 multicast scope types + 1
	 */
	/* number of times that address selection fails */
	u_quad_t ip6s_sources_none;
	/* number of times that an address on the outgoing I/F is chosen */
	u_quad_t ip6s_sources_sameif[16];
	/* number of times that an address on a non-outgoing I/F is chosen */
	u_quad_t ip6s_sources_otherif[16];
	/*
	 * number of times that an address that has the same scope
	 * from the destination is chosen.
	 */
	u_quad_t ip6s_sources_samescope[16];
	/*
	 * number of times that an address that has a different scope
	 * from the destination is chosen.
	 */
	u_quad_t ip6s_sources_otherscope[16];
	/* number of times that a deprecated address is chosen */
	u_quad_t ip6s_sources_deprecated[16];

	/* number of times that each rule of source selection is applied. */
	u_quad_t ip6s_sources_rule[16];
};

#ifdef _KERNEL
#define	IP6STAT_ADD(name, val)	V_ip6stat.name += (val)
#define	IP6STAT_SUB(name, val)	V_ip6stat.name -= (val)
#define	IP6STAT_INC(name)	IP6STAT_ADD(name, 1)
#define	IP6STAT_DEC(name)	IP6STAT_SUB(name, 1)
#endif

#ifdef _KERNEL
/*
 * IPv6 onion peeling state.
 * it will be initialized when we come into ip6_input().
 * XXX do not make it a kitchen sink!
 */
struct ip6aux {
	u_int32_t ip6a_flags;
#define IP6A_SWAP	0x01		/* swapped home/care-of on packet */
#define IP6A_HASEEN	0x02		/* HA was present */
#define IP6A_BRUID	0x04		/* BR Unique Identifier was present */
#define IP6A_RTALERTSEEN 0x08		/* rtalert present */

	/* ip6.ip6_src */
	struct in6_addr ip6a_careof;	/* care-of address of the peer */
	struct in6_addr ip6a_home;	/* home address of the peer */
	u_int16_t	ip6a_bruid;	/* BR unique identifier */

	/* ip6.ip6_dst */
	struct in6_ifaddr *ip6a_dstia6;	/* my ifaddr that matches ip6_dst */

	/* rtalert */
	u_int16_t ip6a_rtalert;		/* rtalert option value */

	/*
	 * decapsulation history will be here.
	 * with IPsec it may not be accurate.
	 */
};
#endif

#ifdef _KERNEL
/* flags passed to ip6_output as last parameter */
#define	IPV6_UNSPECSRC		0x01	/* allow :: as the source address */
#define	IPV6_FORWARDING		0x02	/* most of IPv6 header exists */
#define	IPV6_MINMTU		0x04	/* use minimum MTU (IPV6_USE_MIN_MTU) */

#ifdef __NO_STRICT_ALIGNMENT
#define IP6_HDR_ALIGNED_P(ip)	1
#else
#define IP6_HDR_ALIGNED_P(ip)	((((intptr_t) (ip)) & 3) == 0)
#endif

VNET_DECLARE(struct ip6stat, ip6stat);	/* statistics */
VNET_DECLARE(int, ip6_defhlim);		/* default hop limit */
VNET_DECLARE(int, ip6_defmcasthlim);	/* default multicast hop limit */
VNET_DECLARE(int, ip6_forwarding);	/* act as router? */
VNET_DECLARE(int, ip6_use_deprecated);	/* allow deprecated addr as source */
VNET_DECLARE(int, ip6_rr_prune);	/* router renumbering prefix
					 * walk list every 5 sec.    */
VNET_DECLARE(int, ip6_mcast_pmtu);	/* enable pMTU discovery for multicast? */
VNET_DECLARE(int, ip6_v6only);
#define	V_ip6stat			VNET(ip6stat)
#define	V_ip6_defhlim			VNET(ip6_defhlim)
#define	V_ip6_defmcasthlim		VNET(ip6_defmcasthlim)
#define	V_ip6_forwarding		VNET(ip6_forwarding)
#define	V_ip6_use_deprecated		VNET(ip6_use_deprecated)
#define	V_ip6_rr_prune			VNET(ip6_rr_prune)
#define	V_ip6_mcast_pmtu		VNET(ip6_mcast_pmtu)
#define	V_ip6_v6only			VNET(ip6_v6only)

VNET_DECLARE(struct socket *, ip6_mrouter);	/* multicast routing daemon */
VNET_DECLARE(int, ip6_sendredirects);	/* send IP redirects when forwarding? */
VNET_DECLARE(int, ip6_maxfragpackets);	/* Maximum packets in reassembly
					 * queue */
VNET_DECLARE(int, ip6_maxfrags);	/* Maximum fragments in reassembly
					 * queue */
VNET_DECLARE(int, ip6_accept_rtadv);	/* Acts as a host not a router */
VNET_DECLARE(int, ip6_no_radr);		/* No defroute from RA */
VNET_DECLARE(int, ip6_norbit_raif);	/* Disable R-bit in NA on RA
					 * receiving IF. */
VNET_DECLARE(int, ip6_rfc6204w3);	/* Accept defroute from RA even when
					   forwarding enabled */
VNET_DECLARE(int, ip6_keepfaith);	/* Firewall Aided Internet Translator */
VNET_DECLARE(int, ip6_log_interval);
VNET_DECLARE(time_t, ip6_log_time);
VNET_DECLARE(int, ip6_hdrnestlimit);	/* upper limit of # of extension
					 * headers */
VNET_DECLARE(int, ip6_dad_count);	/* DupAddrDetectionTransmits */
#define	V_ip6_mrouter			VNET(ip6_mrouter)
#define	V_ip6_sendredirects		VNET(ip6_sendredirects)
#define	V_ip6_maxfragpackets		VNET(ip6_maxfragpackets)
#define	V_ip6_maxfrags			VNET(ip6_maxfrags)
#define	V_ip6_accept_rtadv		VNET(ip6_accept_rtadv)
#define	V_ip6_no_radr			VNET(ip6_no_radr)
#define	V_ip6_norbit_raif		VNET(ip6_norbit_raif)
#define	V_ip6_rfc6204w3			VNET(ip6_rfc6204w3)
#define	V_ip6_keepfaith			VNET(ip6_keepfaith)
#define	V_ip6_log_interval		VNET(ip6_log_interval)
#define	V_ip6_log_time			VNET(ip6_log_time)
#define	V_ip6_hdrnestlimit		VNET(ip6_hdrnestlimit)
#define	V_ip6_dad_count			VNET(ip6_dad_count)

VNET_DECLARE(int, ip6_auto_flowlabel);
VNET_DECLARE(int, ip6_auto_linklocal);
#define	V_ip6_auto_flowlabel		VNET(ip6_auto_flowlabel)
#define	V_ip6_auto_linklocal		VNET(ip6_auto_linklocal)

VNET_DECLARE(int, ip6_use_tempaddr);	/* Whether to use temporary addresses */
VNET_DECLARE(int, ip6_prefer_tempaddr);	/* Whether to prefer temporary
					 * addresses in the source address
					 * selection */
#define	V_ip6_use_tempaddr		VNET(ip6_use_tempaddr)
#define	V_ip6_prefer_tempaddr		VNET(ip6_prefer_tempaddr)

VNET_DECLARE(int, ip6_use_defzone);	/* Whether to use the default scope
					 * zone when unspecified */
#define	V_ip6_use_defzone		VNET(ip6_use_defzone)

VNET_DECLARE (struct pfil_head, inet6_pfil_hook);	/* packet filter hooks */
#define	V_inet6_pfil_hook	VNET(inet6_pfil_hook)
#ifdef IPSTEALTH
VNET_DECLARE(int, ip6stealth);
#define	V_ip6stealth			VNET(ip6stealth)
#endif

extern struct	pr_usrreqs rip6_usrreqs;
struct sockopt;

struct inpcb;

int	icmp6_ctloutput __P((struct socket *, struct sockopt *sopt));

struct in6_ifaddr;
void	ip6_init __P((void));
#ifdef VIMAGE
void	ip6_destroy __P((void));
#endif
int	ip6proto_register(short);
int	ip6proto_unregister(short);

void	ip6_input __P((struct mbuf *));
struct in6_ifaddr *ip6_getdstifaddr __P((struct mbuf *));
void	ip6_freepcbopts __P((struct ip6_pktopts *));

int	ip6_unknown_opt __P((u_int8_t *, struct mbuf *, int));
char *	ip6_get_prevhdr __P((struct mbuf *, int));
int	ip6_nexthdr __P((struct mbuf *, int, int, int *));
int	ip6_lasthdr __P((struct mbuf *, int, int, int *));

struct ip6aux *ip6_addaux __P((struct mbuf *));
struct ip6aux *ip6_findaux __P((struct mbuf *));
void	ip6_delaux __P((struct mbuf *));

extern int	(*ip6_mforward)(struct ip6_hdr *, struct ifnet *,
    struct mbuf *);

int	ip6_process_hopopts __P((struct mbuf *, u_int8_t *, int, u_int32_t *,
				 u_int32_t *));
struct mbuf	**ip6_savecontrol_v4(struct inpcb *, struct mbuf *,
	    struct mbuf **, int *);
void	ip6_savecontrol __P((struct inpcb *, struct mbuf *, struct mbuf **));
void	ip6_notify_pmtu __P((struct inpcb *, struct sockaddr_in6 *,
			     u_int32_t *));
int	ip6_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));

void	ip6_forward __P((struct mbuf *, int));

void	ip6_mloopback __P((struct ifnet *, struct mbuf *, struct sockaddr_in6 *));
int	ip6_output __P((struct mbuf *, struct ip6_pktopts *,
			struct route_in6 *,
			int,
			struct ip6_moptions *, struct ifnet **,
			struct inpcb *));
int	ip6_ctloutput __P((struct socket *, struct sockopt *));
int	ip6_raw_ctloutput __P((struct socket *, struct sockopt *));
void	ip6_initpktopts __P((struct ip6_pktopts *));
int	ip6_setpktopts __P((struct mbuf *, struct ip6_pktopts *,
	struct ip6_pktopts *, struct ucred *, int));
void	ip6_clearpktopts __P((struct ip6_pktopts *, int));
struct ip6_pktopts *ip6_copypktopts __P((struct ip6_pktopts *, int));
int	ip6_optlen __P((struct inpcb *));

int	route6_input __P((struct mbuf **, int *, int));

void	frag6_init __P((void));
int	frag6_input __P((struct mbuf **, int *, int));
void	frag6_slowtimo __P((void));
void	frag6_drain __P((void));

void	rip6_init __P((void));
int	rip6_input __P((struct mbuf **, int *, int));
void	rip6_ctlinput __P((int, struct sockaddr *, void *));
int	rip6_ctloutput __P((struct socket *, struct sockopt *));
int	rip6_output __P((struct mbuf *, ...));
int	rip6_usrreq __P((struct socket *,
	    int, struct mbuf *, struct mbuf *, struct mbuf *, struct thread *));

int	dest6_input __P((struct mbuf **, int *, int));
int	none_input __P((struct mbuf **, int *, int));

int	in6_selectsrc(struct sockaddr_in6 *, struct ip6_pktopts *,
	struct inpcb *inp, struct route_in6 *, struct ucred *cred,
	struct ifnet **, struct in6_addr *);
int in6_selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
	struct ip6_moptions *, struct route_in6 *, struct ifnet **,
	struct rtentry **));
u_int32_t ip6_randomid __P((void));
u_int32_t ip6_randomflowlabel __P((void));
#endif /* _KERNEL */

#endif /* !_NETINET6_IP6_VAR_H_ */


code:
/*-
 * 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.
 *
 *	$KAME: ip6protosw.h,v 1.25 2001/09/26 06:13:03 keiichi Exp $
 */

/*-
 * Copyright (c) 1982, 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.
 * 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.
 *
 *	@(#)protosw.h	8.1 (Berkeley) 6/2/93
 *	BSDI protosw.h,v 2.3 1996/10/11 16:02:40 pjd Exp
 * $FreeBSD: release/9.0.0/sys/netinet6/ip6protosw.h 193731 2009-06-08 17:15:40Z zec $
 */

#ifndef _NETINET6_IP6PROTOSW_H_
#define _NETINET6_IP6PROTOSW_H_

/*
 * Protocol switch table for IPv6.
 * All other definitions should refer to sys/protosw.h
 */

struct mbuf;
struct sockaddr;
struct socket;
struct domain;
struct thread;
struct ip6_hdr;
struct icmp6_hdr;
struct in6_addr;
struct pr_usrreqs;

/*
 * argument type for the last arg of pr_ctlinput().
 * should be consulted only with AF_INET6 family.
 *
 * IPv6 ICMP IPv6 [exthdrs] finalhdr payload
 * ^    ^    ^              ^
 * |    |    ip6c_ip6       ip6c_off
 * |    ip6c_icmp6
 * ip6c_m
 *
 * ip6c_finaldst usually points to ip6c_ip6->ip6_dst.  if the original
 * (internal) packet carries a routing header, it may point the final
 * dstination address in the routing header.
 *
 * ip6c_src: ip6c_ip6->ip6_src + scope info + flowlabel in ip6c_ip6
 *	(beware of flowlabel, if you try to compare it against others)
 * ip6c_dst: ip6c_finaldst + scope info
 */
struct ip6ctlparam {
	struct mbuf *ip6c_m;		/* start of mbuf chain */
	struct icmp6_hdr *ip6c_icmp6;	/* icmp6 header of target packet */
	struct ip6_hdr *ip6c_ip6;	/* ip6 header of target packet */
	int ip6c_off;			/* offset of the target proto header */
	struct sockaddr_in6 *ip6c_src;	/* srcaddr w/ additional info */
	struct sockaddr_in6 *ip6c_dst;	/* (final) dstaddr w/ additional info */
	struct in6_addr *ip6c_finaldst;	/* final destination address */
	void *ip6c_cmdarg;		/* control command dependent data */
	u_int8_t ip6c_nxt;		/* final next header field */
};

struct ip6protosw {
	short	pr_type;		/* socket type used for */
	struct	domain *pr_domain;	/* domain protocol a member of */
	short	pr_protocol;		/* protocol number */
	short	pr_flags;		/* see below */

/* protocol-protocol hooks */
	int	(*pr_input)		/* input to protocol (from below) */
			__P((struct mbuf **, int *, int));
	int	(*pr_output)		/* output to protocol (from above) */
			__P((struct mbuf *, ...));
	void	(*pr_ctlinput)		/* control input (from below) */
			__P((int, struct sockaddr *, void *));
	int	(*pr_ctloutput)		/* control output (from above) */
			__P((struct socket *, struct sockopt *));

/* utility hooks */
	void	(*pr_init)		/* initialization hook */
			__P((void));
	void	(*pr_destroy)		/* cleanup hook */
			__P((void));

	void	(*pr_fasttimo)		/* fast timeout (200ms) */
			__P((void));
	void	(*pr_slowtimo)		/* slow timeout (500ms) */
			__P((void));
	void	(*pr_drain)		/* flush any excess space possible */
			__P((void));
	struct	pr_usrreqs *pr_usrreqs;	/* supersedes pr_usrreq() */
};

#ifdef _KERNEL
extern struct ip6protosw inet6sw[];
#endif

#endif /* !_NETINET6_IP6PROTOSW_H_ */


code:
/*-
 * Copyright (c) 2009 Bruce Simpson.
 *
 * 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. The name of the author may not be used to endorse or promote
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
 *
 * $FreeBSD: release/9.0.0/sys/netinet6/mld6.h 191666 2009-04-29 11:31:23Z bms $
 */

#ifndef _NETINET6_MLD6_H_
#define _NETINET6_MLD6_H_

/*
 * Multicast Listener Discovery (MLD) definitions.
 */

/* Minimum length of any MLD protocol message. */
#define MLD_MINLEN	sizeof(struct icmp6_hdr)

/*
 * MLD v2 query format.
 * See <netinet/icmp6.h> for struct mld_hdr
 * (MLDv1 query and host report format).
 */
struct mldv2_query {
	struct icmp6_hdr	mld_icmp6_hdr;	/* ICMPv6 header */
	struct in6_addr		mld_addr;	/* address being queried */
	uint8_t		mld_misc;	/* reserved/suppress/robustness   */
	uint8_t		mld_qqi;	/* querier's query interval       */
	uint16_t	mld_numsrc;	/* number of sources              */
	/* followed by 1..numsrc source addresses */
} __packed;
#define MLD_V2_QUERY_MINLEN		sizeof(struct mldv2_query)
#define MLD_MRC_EXP(x)			((ntohs((x)) >> 12) & 0x0007)
#define MLD_MRC_MANT(x)			(ntohs((x)) & 0x0fff)
#define MLD_QQIC_EXP(x)			(((x) >> 4) & 0x07)
#define MLD_QQIC_MANT(x)		((x) & 0x0f)
#define MLD_QRESV(x)			(((x) >> 4) & 0x0f)
#define MLD_SFLAG(x)			(((x) >> 3) & 0x01)
#define MLD_QRV(x)			((x) & 0x07)

/*
 * MLDv2 host membership report header.
 * mld_type: MLDV2_LISTENER_REPORT
 */
struct mldv2_report {
	struct icmp6_hdr	mld_icmp6_hdr;
	/* followed by 1..numgrps records */
} __packed;
/* overlaid on struct icmp6_hdr. */
#define mld_numrecs	mld_icmp6_hdr.icmp6_data16[1]

struct mldv2_record {
	uint8_t			mr_type;	/* record type */
	uint8_t			mr_datalen;	/* length of auxiliary data */
	uint16_t		mr_numsrc;	/* number of sources */
	struct in6_addr		mr_addr;	/* address being reported */
	/* followed by 1..numsrc source addresses */
} __packed;
#define MLD_V2_REPORT_MAXRECS		65535

/*
 * MLDv2 report modes.
 */
#define MLD_DO_NOTHING			0	/* don't send a record */
#define MLD_MODE_IS_INCLUDE		1	/* MODE_IN */
#define MLD_MODE_IS_EXCLUDE		2	/* MODE_EX */
#define MLD_CHANGE_TO_INCLUDE_MODE	3	/* TO_IN */
#define MLD_CHANGE_TO_EXCLUDE_MODE	4	/* TO_EX */
#define MLD_ALLOW_NEW_SOURCES		5	/* ALLOW_NEW */
#define MLD_BLOCK_OLD_SOURCES		6	/* BLOCK_OLD */

/*
 * MLDv2 query types.
 */
#define MLD_V2_GENERAL_QUERY		1
#define MLD_V2_GROUP_QUERY		2
#define MLD_V2_GROUP_SOURCE_QUERY	3

/*
 * Maximum report interval for MLDv1 host membership reports.
 */
#define MLD_V1_MAX_RI			10

/*
 * MLD_TIMER_SCALE denotes that the MLD code field specifies
 * time in milliseconds.
 */
#define MLD_TIMER_SCALE			1000

#endif /* _NETINET6_MLD6_H_ */


code:
/*-
 * Copyright (c) 2009 Bruce Simpson.
 *
 * 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. The name of the author may not be used to endorse or promote
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
 *
 * $FreeBSD: release/9.0.0/sys/netinet6/mld6_var.h 200871 2009-12-22 20:40:22Z bms $
 */
#ifndef _NETINET6_MLD6_VAR_H_
#define _NETINET6_MLD6_VAR_H_

/*
 * Multicast Listener Discovery (MLD)
 * implementation-specific definitions.
 */

#ifdef _KERNEL

/*
 * Per-link MLD state.
 */
struct mld_ifinfo {
	LIST_ENTRY(mld_ifinfo) mli_link;
	struct ifnet *mli_ifp;	/* interface this instance belongs to */
	uint32_t mli_version;	/* MLDv1 Host Compatibility Mode */
	uint32_t mli_v1_timer;	/* MLDv1 Querier Present timer (s) */
	uint32_t mli_v2_timer;	/* MLDv2 General Query (interface) timer (s)*/
	uint32_t mli_flags;	/* MLD per-interface flags */
	uint32_t mli_rv;	/* MLDv2 Robustness Variable */
	uint32_t mli_qi;	/* MLDv2 Query Interval (s) */
	uint32_t mli_qri;	/* MLDv2 Query Response Interval (s) */
	uint32_t mli_uri;	/* MLDv2 Unsolicited Report Interval (s) */
	SLIST_HEAD(,in6_multi)	mli_relinmhead; /* released groups */
	struct ifqueue	 mli_gq;	/* queue of general query responses */
};
#define MLIF_SILENT	0x00000001	/* Do not use MLD on this ifp */
#define MLIF_USEALLOW	0x00000002	/* Use ALLOW/BLOCK for joins/leaves */

#define MLD_RANDOM_DELAY(X)		(arc4random() % (X) + 1)
#define MLD_MAX_STATE_CHANGES		24 /* Max pending changes per group */

/*
 * MLD per-group states.
 */
#define MLD_NOT_MEMBER			0 /* Can garbage collect group */
#define MLD_SILENT_MEMBER		1 /* Do not perform MLD for group */
#define MLD_REPORTING_MEMBER		2 /* MLDv1 we are reporter */
#define MLD_IDLE_MEMBER			3 /* MLDv1 we reported last */
#define MLD_LAZY_MEMBER			4 /* MLDv1 other member reporting */
#define MLD_SLEEPING_MEMBER		5 /* MLDv1 start query response */
#define MLD_AWAKENING_MEMBER		6 /* MLDv1 group timer will start */
#define MLD_G_QUERY_PENDING_MEMBER	7 /* MLDv2 group query pending */
#define MLD_SG_QUERY_PENDING_MEMBER	8 /* MLDv2 source query pending */
#define MLD_LEAVING_MEMBER		9 /* MLDv2 dying gasp (pending last */
					  /* retransmission of INCLUDE {}) */

/*
 * MLD version tag.
 */
#define MLD_VERSION_NONE		0 /* Invalid */
#define MLD_VERSION_1			1
#define MLD_VERSION_2			2 /* Default */

/*
 * MLDv2 protocol control variables.
 */
#define MLD_RV_INIT		2	/* Robustness Variable */
#define MLD_RV_MIN		1
#define MLD_RV_MAX		7

#define MLD_QI_INIT		125	/* Query Interval (s) */
#define MLD_QI_MIN		1
#define MLD_QI_MAX		255

#define MLD_QRI_INIT		10	/* Query Response Interval (s) */
#define MLD_QRI_MIN		1
#define MLD_QRI_MAX		255

#define MLD_URI_INIT		3	/* Unsolicited Report Interval (s) */
#define MLD_URI_MIN		0
#define MLD_URI_MAX		10

#define MLD_MAX_GS_SOURCES		256 /* # of sources in rx GS query */
#define MLD_MAX_G_GS_PACKETS		8 /* # of packets to answer G/GS */
#define MLD_MAX_STATE_CHANGE_PACKETS	8 /* # of packets per state change */
#define MLD_MAX_RESPONSE_PACKETS	16 /* # of packets for general query */
#define MLD_MAX_RESPONSE_BURST		4 /* # of responses to send at once */
#define MLD_RESPONSE_BURST_INTERVAL	(PR_FASTHZ / 2)	/* 500ms */

/*
 * MLD-specific mbuf flags.
 */
#define M_MLDV1		M_PROTO1	/* Packet is MLDv1 */
#define M_GROUPREC	M_PROTO3	/* mbuf chain is a group record */

/*
 * Leading space for MLDv2 reports inside MTU.
 *
 * NOTE: This differs from IGMPv3 significantly. KAME IPv6 requires
 * that a fully formed mbuf chain *without* the Router Alert option
 * is passed to ip6_output(), however we must account for it in the
 * MTU if we need to split an MLDv2 report into several packets.
 *
 * We now put the MLDv2 report header in the initial mbuf containing
 * the IPv6 header.
 */
#define	MLD_MTUSPACE	(sizeof(struct ip6_hdr) + sizeof(struct mld_raopt) + \
			 sizeof(struct icmp6_hdr))

/*
 * Subsystem lock macros.
 * The MLD lock is only taken with MLD. Currently it is system-wide.
 * VIMAGE: The lock could be pushed to per-VIMAGE granularity in future.
 */
#define	MLD_LOCK_INIT()	mtx_init(&mld_mtx, "mld_mtx", NULL, MTX_DEF)
#define	MLD_LOCK_DESTROY()	mtx_destroy(&mld_mtx)
#define	MLD_LOCK()		mtx_lock(&mld_mtx)
#define	MLD_LOCK_ASSERT()	mtx_assert(&mld_mtx, MA_OWNED)
#define	MLD_UNLOCK()		mtx_unlock(&mld_mtx)
#define	MLD_UNLOCK_ASSERT()	mtx_assert(&mld_mtx, MA_NOTOWNED)

/*
 * Per-link MLD context.
 */
#define MLD_IFINFO(ifp) \
	(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->mld_ifinfo)

int	mld_change_state(struct in6_multi *, const int);
struct mld_ifinfo *
	mld_domifattach(struct ifnet *);
void	mld_domifdetach(struct ifnet *);
void	mld_fasttimo(void);
void	mld_ifdetach(struct ifnet *);
int	mld_input(struct mbuf *, int, int);
void	mld_slowtimo(void);

#ifdef SYSCTL_DECL
SYSCTL_DECL(_net_inet6_mld);
#endif

#endif /* _KERNEL */

#endif /* _NETINET6_MLD6_VAR_H_ */


code:
/*-
 * 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.
 *
 *	$KAME: nd6.h,v 1.76 2001/12/18 02:10:31 itojun Exp $
 * $FreeBSD: release/9.0.0/sys/netinet6/nd6.h 222728 2011-06-06 02:14:23Z hrs $
 */

#ifndef _NETINET6_ND6_H_
#define _NETINET6_ND6_H_

/* see net/route.h, or net/if_inarp.h */
#ifndef RTF_ANNOUNCE
#define RTF_ANNOUNCE	RTF_PROTO2
#endif

#include <sys/queue.h>
#include <sys/callout.h>

struct llentry;

#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

#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
#define ND6_LLINFO_PERMANENT(n) (((n)->la_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE))

struct nd_ifinfo {
	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 initialized; /* Flag to see the entry is initialized */
	/* the following 3 members are for privacy extension for addrconf */
	u_int8_t randomseed0[8]; /* upper 64 bits of MD5 digest */
	u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */
	u_int8_t randomid[8];	/* current random ID */
};

#define ND6_IFF_PERFORMNUD	0x1
#define ND6_IFF_ACCEPT_RTADV	0x2
#define ND6_IFF_PREFER_SOURCE	0x4 /* XXX: 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
#define ND6_IFF_AUTO_LINKLOCAL	0x20
#define	ND6_IFF_NO_RADR		0x40

#define	ND6_CREATE		LLE_CREATE
#define	ND6_EXCLUSIVE		LLE_EXCLUSIVE

#ifdef _KERNEL
#define ND_IFINFO(ifp) \
	(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo)
#define IN6_LINKMTU(ifp) \
	((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))
#endif

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 */
};

#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];
};

struct	in6_defrouter {
	struct	sockaddr_in6 rtaddr;
	u_char	flags;
	u_short	rtlifetime;
	u_long	expire;
	u_short if_index;
};

#ifdef _KERNEL
struct	in6_oprlist {
	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];
};
#endif

struct	in6_prlist {
	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;
		time_t expire;
		u_short if_index;
		u_short advrtrs; /* number of advertisement routers */
		struct	in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */
	} prefix[PRLSTSIZ];
};

struct in6_prefix {
	struct	sockaddr_in6 prefix;
	struct prf_ra raflags;
	u_char	prefixlen;
	u_char	origin;
	u_int32_t vltime;
	u_int32_t pltime;
	time_t expire;
	u_int32_t flags;
	int refcnt;
	u_short if_index;
	u_short advrtrs; /* number of advertisement routers */
	/* struct sockaddr_in6 advrtr[] */
};

#ifdef _KERNEL
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;
};
#endif

struct	in6_ndireq {
	char ifname[IFNAMSIZ];
	struct nd_ifinfo ndi;
};

struct	in6_ndifreq {
	char ifname[IFNAMSIZ];
	u_long ifindex;
};

/* Prefix status */
#define NDPRF_ONLINK		0x1
#define NDPRF_DETACHED		0x2

/* 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

#ifdef _KERNEL
/* 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)) + (arc4random() & \
		((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000)

TAILQ_HEAD(nd_drhead, nd_defrouter);
struct	nd_defrouter {
	TAILQ_ENTRY(nd_defrouter) dr_entry;
	struct	in6_addr rtaddr;
	u_char	flags;		/* flags on RA message */
	u_short	rtlifetime;
	u_long	expire;
	struct  ifnet *ifp;
	int	installed;	/* is installed into kernel routing table */
};

struct nd_prefixctl {
	struct ifnet *ndpr_ifp;

	/* prefix */
	struct sockaddr_in6 ndpr_prefix;
	u_char	ndpr_plen;

	u_int32_t ndpr_vltime;	/* advertised valid lifetime */
	u_int32_t ndpr_pltime;	/* advertised preferred lifetime */

	struct prf_ra ndpr_flags;
};

struct nd_prefix {
	struct ifnet *ndpr_ifp;
	LIST_ENTRY(nd_prefix) ndpr_entry;
	struct sockaddr_in6 ndpr_prefix;	/* prefix */
	struct in6_addr ndpr_mask; /* netmask derived from the prefix */

	u_int32_t ndpr_vltime;	/* advertised valid lifetime */
	u_int32_t ndpr_pltime;	/* advertised preferred lifetime */

	time_t ndpr_expire;	/* expiration time of the prefix */
	time_t ndpr_preferred;	/* preferred 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_refcnt;	/* reference couter from addresses */
};

#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

/*
 * 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_long	prm_vltim;
	u_long	prm_pltime;
	u_long	prm_expire;
	u_long	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

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);

/* nd6.c */
VNET_DECLARE(int, nd6_prune);
VNET_DECLARE(int, nd6_delay);
VNET_DECLARE(int, nd6_umaxtries);
VNET_DECLARE(int, nd6_mmaxtries);
VNET_DECLARE(int, nd6_useloopback);
VNET_DECLARE(int, nd6_maxnudhint);
VNET_DECLARE(int, nd6_gctimer);
VNET_DECLARE(struct nd_drhead, nd_defrouter);
VNET_DECLARE(struct nd_prhead, nd_prefix);
VNET_DECLARE(int, nd6_debug);
VNET_DECLARE(int, nd6_onlink_ns_rfc4861);
#define	V_nd6_prune			VNET(nd6_prune)
#define	V_nd6_delay			VNET(nd6_delay)
#define	V_nd6_umaxtries			VNET(nd6_umaxtries)
#define	V_nd6_mmaxtries			VNET(nd6_mmaxtries)
#define	V_nd6_useloopback		VNET(nd6_useloopback)
#define	V_nd6_maxnudhint		VNET(nd6_maxnudhint)
#define	V_nd6_gctimer			VNET(nd6_gctimer)
#define	V_nd_defrouter			VNET(nd_defrouter)
#define	V_nd_prefix			VNET(nd_prefix)
#define	V_nd6_debug			VNET(nd6_debug)
#define	V_nd6_onlink_ns_rfc4861		VNET(nd6_onlink_ns_rfc4861)

#define nd6log(x)	do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0)

VNET_DECLARE(struct callout, nd6_timer_ch);
#define	V_nd6_timer_ch			VNET(nd6_timer_ch)

/* nd6_rtr.c */
VNET_DECLARE(int, nd6_defifindex);
VNET_DECLARE(int, ip6_desync_factor);	/* seconds */
VNET_DECLARE(u_int32_t, ip6_temp_preferred_lifetime); /* seconds */
VNET_DECLARE(u_int32_t, ip6_temp_valid_lifetime); /* seconds */
VNET_DECLARE(int, ip6_temp_regen_advance); /* seconds */
#define	V_nd6_defifindex		VNET(nd6_defifindex)
#define	V_ip6_desync_factor		VNET(ip6_desync_factor)
#define	V_ip6_temp_preferred_lifetime	VNET(ip6_temp_preferred_lifetime)
#define	V_ip6_temp_valid_lifetime	VNET(ip6_temp_valid_lifetime)
#define	V_ip6_temp_regen_advance	VNET(ip6_temp_regen_advance)

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 */
void nd6_init __P((void));
#ifdef VIMAGE
void nd6_destroy __P((void));
#endif
struct nd_ifinfo *nd6_ifattach __P((struct ifnet *));
void nd6_ifdetach __P((struct nd_ifinfo *));
int nd6_is_addr_neighbor __P((struct sockaddr_in6 *, struct ifnet *));
void nd6_option_init __P((void *, int, union nd_opts *));
struct nd_opt_hdr *nd6_option __P((union nd_opts *));
int nd6_options __P((union nd_opts *));
struct	llentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
void nd6_setmtu __P((struct ifnet *));
void nd6_llinfo_settimer __P((struct llentry *, long));
void nd6_llinfo_settimer_locked __P((struct llentry *, long));
void nd6_timer __P((void *));
void nd6_purge __P((struct ifnet *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
int nd6_resolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
	struct sockaddr *, u_char *));
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
struct llentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
	char *, int, int, int));
int nd6_output __P((struct ifnet *, struct ifnet *, struct mbuf *,
	struct sockaddr_in6 *, struct rtentry *));
int nd6_output_lle __P((struct ifnet *, struct ifnet *, struct mbuf *,
	struct sockaddr_in6 *, struct rtentry *, struct llentry *,
	struct mbuf **));
int nd6_output_flush __P((struct ifnet *, struct ifnet *, struct mbuf *,
	struct sockaddr_in6 *, struct route *));
int nd6_need_cache __P((struct ifnet *));
int nd6_storelladdr __P((struct ifnet *, struct mbuf *,
	struct sockaddr *, u_char *, struct llentry **));

/* nd6_nbr.c */
void nd6_na_input __P((struct mbuf *, int, int));
void nd6_na_output __P((struct ifnet *, const struct in6_addr *,
	const struct in6_addr *, u_long, int, struct sockaddr *));
void nd6_ns_input __P((struct mbuf *, int, int));
void nd6_ns_output __P((struct ifnet *, const struct in6_addr *,
	const struct in6_addr *, struct llentry *, int));
caddr_t nd6_ifptomac __P((struct ifnet *));
void nd6_dad_start __P((struct ifaddr *, int));
void nd6_dad_stop __P((struct ifaddr *));
void nd6_dad_duplicated __P((struct ifaddr *));

/* nd6_rtr.c */
void nd6_rs_input __P((struct mbuf *, int, int));
void nd6_ra_input __P((struct mbuf *, int, int));
void prelist_del __P((struct nd_prefix *));
void defrouter_addreq __P((struct nd_defrouter *));
void defrouter_reset __P((void));
void defrouter_select __P((void));
void defrtrlist_del __P((struct nd_defrouter *));
void prelist_remove __P((struct nd_prefix *));
int nd6_prelist_add __P((struct nd_prefixctl *, struct nd_defrouter *,
	struct nd_prefix **));
int nd6_prefix_onlink __P((struct nd_prefix *));
int nd6_prefix_offlink __P((struct nd_prefix *));
void pfxlist_onlink_check __P((void));
struct nd_defrouter *defrouter_lookup __P((struct in6_addr *, struct ifnet *));
struct nd_prefix *nd6_prefix_lookup __P((struct nd_prefixctl *));
void rt6_flush __P((struct in6_addr *, struct ifnet *));
int nd6_setdefaultiface __P((int));
int in6_tmpifadd __P((const struct in6_ifaddr *, int, int));

#endif /* _KERNEL */

#endif /* _NETINET6_ND6_H_ */


code:
/*-
 * Copyright (C) 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.
 *
 *	$KAME: pim6.h,v 1.3 2000/03/25 07:23:58 sumikawa Exp $
 * $FreeBSD: release/9.0.0/sys/netinet6/pim6.h 174510 2007-12-10 16:03:40Z obrien $
 */
/*
 * Protocol Independent Multicast (PIM) definitions
 *
 * Written by Ahmed Helmy, SGI, July 1996
 *
 * MULTICAST
 */

/*
 * PIM packet header
 */
#define PIM_VERSION	2
struct pim {
#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
	u_char	pim_type:4, /* the PIM message type, currently they are:
			     * Hello, Register, Register-Stop, Join/Prune,
			     * Bootstrap, Assert, Graft (PIM-DM only),
			     * Graft-Ack (PIM-DM only), C-RP-Adv
			     */
		pim_ver:4;  /* PIM version number; 2 for PIMv2 */
#else
	u_char	pim_ver:4,	/* PIM version */
		pim_type:4;	/* PIM type    */
#endif
	u_char  pim_rsv;	/* Reserved */
	u_short	pim_cksum;	/* IP style check sum */
};

#define PIM_MINLEN	8		/* The header min. length is 8    */
#define PIM6_REG_MINLEN	(PIM_MINLEN+40)	/* Register message + inner IP6 header */

/*
 * Message types
 */
#define PIM_REGISTER	1	/* PIM Register type is 1 */

/* second bit in reg_head is the null bit */
#define PIM_NULL_REGISTER 0x40000000


code:
/*-
 * Copyright (C) 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.
 *
 *	$KAME: pim6_var.h,v 1.8 2000/06/06 08:07:43 jinmei Exp $
 * $FreeBSD: release/9.0.0/sys/netinet6/pim6_var.h 174510 2007-12-10 16:03:40Z obrien $
 */

/*
 * Protocol Independent Multicast (PIM),
 * implementation-specific definitions.
 *
 * Written by George Edmond Eddy (Rusty), ISI, February 1998
 * Modified by Pavlin Ivanov Radoslavov, USC/ISI, May 1998
 */

#ifndef _NETINET6_PIM6_VAR_H_
#define _NETINET6_PIM6_VAR_H_

struct pim6stat {
	u_quad_t pim6s_rcv_total;	/* total PIM messages received	*/
	u_quad_t pim6s_rcv_tooshort;	/* received with too few bytes	*/
	u_quad_t pim6s_rcv_badsum;	/* received with bad checksum	*/
	u_quad_t pim6s_rcv_badversion;	/* received bad PIM version	*/
	u_quad_t pim6s_rcv_registers;	/* received registers		*/
	u_quad_t pim6s_rcv_badregisters; /* received invalid registers	*/
	u_quad_t pim6s_snd_registers;	/* sent registers		*/
};

#if (defined(KERNEL)) || (defined(_KERNEL))
int pim6_input __P((struct mbuf **, int*, int));
#endif /* KERNEL */

/*
 * Names for PIM sysctl objects
 */
#define PIM6CTL_STATS		1	/* statistics (read-only) */
#define PIM6CTL_MAXID		2

#define PIM6CTL_NAMES { \
	{ 0, 0 }, \
	{ 0, 0 }, \
}
#endif /* _NETINET6_PIM6_VAR_H_ */