code:
/*-
 * Copyright (c) 1982, 1986, 1989, 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.
 *
 *	From: @(#)if.h	8.1 (Berkeley) 6/10/93
 * $FreeBSD: release/9.0.0/sys/net/if_var.h 224151 2011-07-17 21:15:20Z bz $
 */

#ifndef	_NET_IF_VAR_H_
#define	_NET_IF_VAR_H_

/*
 * Structures defining a network interface, providing a packet
 * transport mechanism (ala level 0 of the PUP protocols).
 *
 * Each interface accepts output datagrams of a specified maximum
 * length, and provides higher level routines with input datagrams
 * received from its medium.
 *
 * Output occurs when the routine if_output is called, with three parameters:
 *	(*ifp->if_output)(ifp, m, dst, rt)
 * Here m is the mbuf chain to be sent and dst is the destination address.
 * The output routine encapsulates the supplied datagram if necessary,
 * and then transmits it on its medium.
 *
 * On input, each interface unwraps the data received by it, and either
 * places it on the input queue of an internetwork datagram routine
 * and posts the associated software interrupt, or passes the datagram to a raw
 * packet input routine.
 *
 * Routines exist for locating interfaces by their addresses
 * or for locating an interface on a certain network, as well as more general
 * routing and gateway routines maintaining information used to locate
 * interfaces.  These routines live in the files if.c and route.c
 */

#ifdef __STDC__
/*
 * Forward structure declarations for function prototypes [sic].
 */
struct	mbuf;
struct	thread;
struct	rtentry;
struct	rt_addrinfo;
struct	socket;
struct	ether_header;
struct	carp_if;
struct  ifvlantrunk;
struct	route;
struct	vnet;
#endif

#include <sys/queue.h>		/* get TAILQ macros */

#ifdef _KERNEL
#include <sys/mbuf.h>
#include <sys/eventhandler.h>
#include <sys/buf_ring.h>
#include <net/vnet.h>
#endif /* _KERNEL */
#include <sys/lock.h>		/* XXX */
#include <sys/mutex.h>		/* XXX */
#include <sys/rwlock.h>		/* XXX */
#include <sys/sx.h>		/* XXX */
#include <sys/event.h>		/* XXX */
#include <sys/_task.h>

#define	IF_DUNIT_NONE	-1

#include <altq/if_altq.h>

TAILQ_HEAD(ifnethead, ifnet);	/* we use TAILQs so that the order of */
TAILQ_HEAD(ifaddrhead, ifaddr);	/* instantiation is preserved in the list */
TAILQ_HEAD(ifprefixhead, ifprefix);
TAILQ_HEAD(ifmultihead, ifmultiaddr);
TAILQ_HEAD(ifgrouphead, ifg_group);

/*
 * Structure defining a queue for a network interface.
 */
struct	ifqueue {
	struct	mbuf *ifq_head;
	struct	mbuf *ifq_tail;
	int	ifq_len;
	int	ifq_maxlen;
	int	ifq_drops;
	struct	mtx ifq_mtx;
};

/*
 * Structure defining a network interface.
 *
 * (Would like to call this struct ``if'', but C isn't PL/1.)
 */

struct ifnet {
	void	*if_softc;		/* pointer to driver state */
	void	*if_l2com;		/* pointer to protocol bits */
	struct vnet *if_vnet;		/* pointer to network stack instance */
	TAILQ_ENTRY(ifnet) if_link; 	/* all struct ifnets are chained */
	char	if_xname[IFNAMSIZ];	/* external name (name + unit) */
	const char *if_dname;		/* driver name */
	int	if_dunit;		/* unit or IF_DUNIT_NONE */
	u_int	if_refcount;		/* reference count */
	struct	ifaddrhead if_addrhead;	/* linked list of addresses per if */
		/*
		 * if_addrhead is the list of all addresses associated to
		 * an interface.
		 * Some code in the kernel assumes that first element
		 * of the list has type AF_LINK, and contains sockaddr_dl
		 * addresses which store the link-level address and the name
		 * of the interface.
		 * However, access to the AF_LINK address through this
		 * field is deprecated. Use if_addr or ifaddr_byindex() instead.
		 */
	int	if_pcount;		/* number of promiscuous listeners */
	struct	carp_if *if_carp;	/* carp interface structure */
	struct	bpf_if *if_bpf;		/* packet filter structure */
	u_short	if_index;		/* numeric abbreviation for this if  */
	short	if_index_reserved;	/* spare space to grow if_index */
	struct  ifvlantrunk *if_vlantrunk; /* pointer to 802.1q data */
	int	if_flags;		/* up/down, broadcast, etc. */
	int	if_capabilities;	/* interface features & capabilities */
	int	if_capenable;		/* enabled features & capabilities */
	void	*if_linkmib;		/* link-type-specific MIB data */
	size_t	if_linkmiblen;		/* length of above data */
	struct	if_data if_data;
	struct	ifmultihead if_multiaddrs; /* multicast addresses configured */
	int	if_amcount;		/* number of all-multicast requests */
/* procedure handles */
	int	(*if_output)		/* output routine (enqueue) */
		(struct ifnet *, struct mbuf *, struct sockaddr *,
		     struct route *);
	void	(*if_input)		/* input routine (from h/w driver) */
		(struct ifnet *, struct mbuf *);
	void	(*if_start)		/* initiate output routine */
		(struct ifnet *);
	int	(*if_ioctl)		/* ioctl routine */
		(struct ifnet *, u_long, caddr_t);
	void	(*if_init)		/* Init routine */
		(void *);
	int	(*if_resolvemulti)	/* validate/resolve multicast */
		(struct ifnet *, struct sockaddr **, struct sockaddr *);
	void	(*if_qflush)		/* flush any queues */
		(struct ifnet *);
	int	(*if_transmit)		/* initiate output routine */
		(struct ifnet *, struct mbuf *);
	void	(*if_reassign)		/* reassign to vnet routine */
		(struct ifnet *, struct vnet *, char *);
	struct	vnet *if_home_vnet;	/* where this ifnet originates from */
	struct	ifaddr	*if_addr;	/* pointer to link-level address */
	void	*if_llsoftc;		/* link layer softc */
	int	if_drv_flags;		/* driver-managed status flags */
	struct  ifaltq if_snd;		/* output queue (includes altq) */
	const u_int8_t *if_broadcastaddr; /* linklevel broadcast bytestring */

	void	*if_bridge;		/* bridge glue */

	struct	label *if_label;	/* interface MAC label */

	/* these are only used by IPv6 */
	struct	ifprefixhead if_prefixhead; /* list of prefixes per if */
	void	*if_afdata[AF_MAX];
	int	if_afdata_initialized;
	struct	rwlock if_afdata_lock;
	struct	task if_linktask;	/* task for link change events */
	struct	mtx if_addr_mtx;	/* mutex to protect address lists */

	LIST_ENTRY(ifnet) if_clones;	/* interfaces of a cloner */
	TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
					/* protected by if_addr_mtx */
	void	*if_pf_kif;
	void	*if_lagg;		/* lagg glue */
	char	*if_description;	/* interface description */
	u_int	if_fib;			/* interface FIB */
	u_char	if_alloctype;		/* if_type at time of allocation */

	/*
	 * Spare fields are added so that we can modify sensitive data
	 * structures without changing the kernel binary interface, and must
	 * be used with care where binary compatibility is required.
	 */
	char	if_cspare[3];
	int	if_ispare[4];
	void	*if_pspare[8];		/* 1 netmap, 7 TDB */
};

typedef void if_init_f_t(void *);

/*
 * XXX These aliases are terribly dangerous because they could apply
 * to anything.
 */
#define	if_mtu		if_data.ifi_mtu
#define	if_type		if_data.ifi_type
#define if_physical	if_data.ifi_physical
#define	if_addrlen	if_data.ifi_addrlen
#define	if_hdrlen	if_data.ifi_hdrlen
#define	if_metric	if_data.ifi_metric
#define	if_link_state	if_data.ifi_link_state
#define	if_baudrate	if_data.ifi_baudrate
#define	if_hwassist	if_data.ifi_hwassist
#define	if_ipackets	if_data.ifi_ipackets
#define	if_ierrors	if_data.ifi_ierrors
#define	if_opackets	if_data.ifi_opackets
#define	if_oerrors	if_data.ifi_oerrors
#define	if_collisions	if_data.ifi_collisions
#define	if_ibytes	if_data.ifi_ibytes
#define	if_obytes	if_data.ifi_obytes
#define	if_imcasts	if_data.ifi_imcasts
#define	if_omcasts	if_data.ifi_omcasts
#define	if_iqdrops	if_data.ifi_iqdrops
#define	if_noproto	if_data.ifi_noproto
#define	if_lastchange	if_data.ifi_lastchange

/* for compatibility with other BSDs */
#define	if_addrlist	if_addrhead
#define	if_list		if_link
#define	if_name(ifp)	((ifp)->if_xname)

/*
 * Locks for address lists on the network interface.
 */
#define	IF_ADDR_LOCK_INIT(if)	mtx_init(&(if)->if_addr_mtx,		\
				    "if_addr_mtx", NULL, MTX_DEF)
#define	IF_ADDR_LOCK_DESTROY(if)	mtx_destroy(&(if)->if_addr_mtx)
#define	IF_ADDR_LOCK(if)	mtx_lock(&(if)->if_addr_mtx)
#define	IF_ADDR_UNLOCK(if)	mtx_unlock(&(if)->if_addr_mtx)
#define	IF_ADDR_LOCK_ASSERT(if)	mtx_assert(&(if)->if_addr_mtx, MA_OWNED)

/*
 * Function variations on locking macros intended to be used by loadable
 * kernel modules in order to divorce them from the internals of address list
 * locking.
 */
void	if_addr_rlock(struct ifnet *ifp);	/* if_addrhead */
void	if_addr_runlock(struct ifnet *ifp);	/* if_addrhead */
void	if_maddr_rlock(struct ifnet *ifp);	/* if_multiaddrs */
void	if_maddr_runlock(struct ifnet *ifp);	/* if_multiaddrs */

/*
 * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq)
 * are queues of messages stored on ifqueue structures
 * (defined above).  Entries are added to and deleted from these structures
 * by these macros, which should be called with ipl raised to splimp().
 */
#define IF_LOCK(ifq)		mtx_lock(&(ifq)->ifq_mtx)
#define IF_UNLOCK(ifq)		mtx_unlock(&(ifq)->ifq_mtx)
#define	IF_LOCK_ASSERT(ifq)	mtx_assert(&(ifq)->ifq_mtx, MA_OWNED)
#define	_IF_QFULL(ifq)		((ifq)->ifq_len >= (ifq)->ifq_maxlen)
#define	_IF_DROP(ifq)		((ifq)->ifq_drops++)
#define	_IF_QLEN(ifq)		((ifq)->ifq_len)

#define	_IF_ENQUEUE(ifq, m) do { 				\
	(m)->m_nextpkt = NULL;					\
	if ((ifq)->ifq_tail == NULL) 				\
		(ifq)->ifq_head = m; 				\
	else 							\
		(ifq)->ifq_tail->m_nextpkt = m; 		\
	(ifq)->ifq_tail = m; 					\
	(ifq)->ifq_len++; 					\
} while (0)

#define IF_ENQUEUE(ifq, m) do {					\
	IF_LOCK(ifq); 						\
	_IF_ENQUEUE(ifq, m); 					\
	IF_UNLOCK(ifq); 					\
} while (0)

#define	_IF_PREPEND(ifq, m) do {				\
	(m)->m_nextpkt = (ifq)->ifq_head; 			\
	if ((ifq)->ifq_tail == NULL) 				\
		(ifq)->ifq_tail = (m); 				\
	(ifq)->ifq_head = (m); 					\
	(ifq)->ifq_len++; 					\
} while (0)

#define IF_PREPEND(ifq, m) do {		 			\
	IF_LOCK(ifq); 						\
	_IF_PREPEND(ifq, m); 					\
	IF_UNLOCK(ifq); 					\
} while (0)

#define	_IF_DEQUEUE(ifq, m) do { 				\
	(m) = (ifq)->ifq_head; 					\
	if (m) { 						\
		if (((ifq)->ifq_head = (m)->m_nextpkt) == NULL)	\
			(ifq)->ifq_tail = NULL; 		\
		(m)->m_nextpkt = NULL; 				\
		(ifq)->ifq_len--; 				\
	} 							\
} while (0)

#define IF_DEQUEUE(ifq, m) do { 				\
	IF_LOCK(ifq); 						\
	_IF_DEQUEUE(ifq, m); 					\
	IF_UNLOCK(ifq); 					\
} while (0)

#define	_IF_POLL(ifq, m)	((m) = (ifq)->ifq_head)
#define	IF_POLL(ifq, m)		_IF_POLL(ifq, m)

#define _IF_DRAIN(ifq) do { 					\
	struct mbuf *m; 					\
	for (;;) { 						\
		_IF_DEQUEUE(ifq, m); 				\
		if (m == NULL) 					\
			break; 					\
		m_freem(m); 					\
	} 							\
} while (0)

#define IF_DRAIN(ifq) do {					\
	IF_LOCK(ifq);						\
	_IF_DRAIN(ifq);						\
	IF_UNLOCK(ifq);						\
} while(0)

#ifdef _KERNEL
/* interface link layer address change event */
typedef void (*iflladdr_event_handler_t)(void *, struct ifnet *);
EVENTHANDLER_DECLARE(iflladdr_event, iflladdr_event_handler_t);
/* interface address change event */
typedef void (*ifaddr_event_handler_t)(void *, struct ifnet *);
EVENTHANDLER_DECLARE(ifaddr_event, ifaddr_event_handler_t);
/* new interface arrival event */
typedef void (*ifnet_arrival_event_handler_t)(void *, struct ifnet *);
EVENTHANDLER_DECLARE(ifnet_arrival_event, ifnet_arrival_event_handler_t);
/* interface departure event */
typedef void (*ifnet_departure_event_handler_t)(void *, struct ifnet *);
EVENTHANDLER_DECLARE(ifnet_departure_event, ifnet_departure_event_handler_t);
/* Interface link state change event */
typedef void (*ifnet_link_event_handler_t)(void *, struct ifnet *, int);
EVENTHANDLER_DECLARE(ifnet_link_event, ifnet_link_event_handler_t);

/*
 * interface groups
 */
struct ifg_group {
	char				 ifg_group[IFNAMSIZ];
	u_int				 ifg_refcnt;
	void				*ifg_pf_kif;
	TAILQ_HEAD(, ifg_member)	 ifg_members;
	TAILQ_ENTRY(ifg_group)		 ifg_next;
};

struct ifg_member {
	TAILQ_ENTRY(ifg_member)	 ifgm_next;
	struct ifnet		*ifgm_ifp;
};

struct ifg_list {
	struct ifg_group	*ifgl_group;
	TAILQ_ENTRY(ifg_list)	 ifgl_next;
};

/* group attach event */
typedef void (*group_attach_event_handler_t)(void *, struct ifg_group *);
EVENTHANDLER_DECLARE(group_attach_event, group_attach_event_handler_t);
/* group detach event */
typedef void (*group_detach_event_handler_t)(void *, struct ifg_group *);
EVENTHANDLER_DECLARE(group_detach_event, group_detach_event_handler_t);
/* group change event */
typedef void (*group_change_event_handler_t)(void *, const char *);
EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t);

#define	IF_AFDATA_LOCK_INIT(ifp)	\
	rw_init(&(ifp)->if_afdata_lock, "if_afdata")

#define	IF_AFDATA_WLOCK(ifp)	rw_wlock(&(ifp)->if_afdata_lock)
#define	IF_AFDATA_RLOCK(ifp)	rw_rlock(&(ifp)->if_afdata_lock)
#define	IF_AFDATA_WUNLOCK(ifp)	rw_wunlock(&(ifp)->if_afdata_lock)
#define	IF_AFDATA_RUNLOCK(ifp)	rw_runlock(&(ifp)->if_afdata_lock)
#define	IF_AFDATA_LOCK(ifp)	IF_AFDATA_WLOCK(ifp)
#define	IF_AFDATA_UNLOCK(ifp)	IF_AFDATA_WUNLOCK(ifp)
#define	IF_AFDATA_TRYLOCK(ifp)	rw_try_wlock(&(ifp)->if_afdata_lock)
#define	IF_AFDATA_DESTROY(ifp)	rw_destroy(&(ifp)->if_afdata_lock)

#define	IF_AFDATA_LOCK_ASSERT(ifp)	rw_assert(&(ifp)->if_afdata_lock, RA_LOCKED)
#define	IF_AFDATA_UNLOCK_ASSERT(ifp)	rw_assert(&(ifp)->if_afdata_lock, RA_UNLOCKED)

int	if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp,
	    int adjust);
#define	IF_HANDOFF(ifq, m, ifp)			\
	if_handoff((struct ifqueue *)ifq, m, ifp, 0)
#define	IF_HANDOFF_ADJ(ifq, m, ifp, adj)	\
	if_handoff((struct ifqueue *)ifq, m, ifp, adj)

void	if_start(struct ifnet *);

#define	IFQ_ENQUEUE(ifq, m, err)					\
do {									\
	IF_LOCK(ifq);							\
	if (ALTQ_IS_ENABLED(ifq))					\
		ALTQ_ENQUEUE(ifq, m, NULL, err);			\
	else {								\
		if (_IF_QFULL(ifq)) {					\
			m_freem(m);					\
			(err) = ENOBUFS;				\
		} else {						\
			_IF_ENQUEUE(ifq, m);				\
			(err) = 0;					\
		}							\
	}								\
	if (err)							\
		(ifq)->ifq_drops++;					\
	IF_UNLOCK(ifq);							\
} while (0)

#define	IFQ_DEQUEUE_NOLOCK(ifq, m)					\
do {									\
	if (TBR_IS_ENABLED(ifq))					\
		(m) = tbr_dequeue_ptr(ifq, ALTDQ_REMOVE);		\
	else if (ALTQ_IS_ENABLED(ifq))					\
		ALTQ_DEQUEUE(ifq, m);					\
	else								\
		_IF_DEQUEUE(ifq, m);					\
} while (0)

#define	IFQ_DEQUEUE(ifq, m)						\
do {									\
	IF_LOCK(ifq);							\
	IFQ_DEQUEUE_NOLOCK(ifq, m);					\
	IF_UNLOCK(ifq);							\
} while (0)

#define	IFQ_POLL_NOLOCK(ifq, m)						\
do {									\
	if (TBR_IS_ENABLED(ifq))					\
		(m) = tbr_dequeue_ptr(ifq, ALTDQ_POLL);			\
	else if (ALTQ_IS_ENABLED(ifq))					\
		ALTQ_POLL(ifq, m);					\
	else								\
		_IF_POLL(ifq, m);					\
} while (0)

#define	IFQ_POLL(ifq, m)						\
do {									\
	IF_LOCK(ifq);							\
	IFQ_POLL_NOLOCK(ifq, m);					\
	IF_UNLOCK(ifq);							\
} while (0)

#define	IFQ_PURGE_NOLOCK(ifq)						\
do {									\
	if (ALTQ_IS_ENABLED(ifq)) {					\
		ALTQ_PURGE(ifq);					\
	} else								\
		_IF_DRAIN(ifq);						\
} while (0)

#define	IFQ_PURGE(ifq)							\
do {									\
	IF_LOCK(ifq);							\
	IFQ_PURGE_NOLOCK(ifq);						\
	IF_UNLOCK(ifq);							\
} while (0)

#define	IFQ_SET_READY(ifq)						\
	do { ((ifq)->altq_flags |= ALTQF_READY); } while (0)

#define	IFQ_LOCK(ifq)			IF_LOCK(ifq)
#define	IFQ_UNLOCK(ifq)			IF_UNLOCK(ifq)
#define	IFQ_LOCK_ASSERT(ifq)		IF_LOCK_ASSERT(ifq)
#define	IFQ_IS_EMPTY(ifq)		((ifq)->ifq_len == 0)
#define	IFQ_INC_LEN(ifq)		((ifq)->ifq_len++)
#define	IFQ_DEC_LEN(ifq)		(--(ifq)->ifq_len)
#define	IFQ_INC_DROPS(ifq)		((ifq)->ifq_drops++)
#define	IFQ_SET_MAXLEN(ifq, len)	((ifq)->ifq_maxlen = (len))

/*
 * The IFF_DRV_OACTIVE test should really occur in the device driver, not in
 * the handoff logic, as that flag is locked by the device driver.
 */
#define	IFQ_HANDOFF_ADJ(ifp, m, adj, err)				\
do {									\
	int len;							\
	short mflags;							\
									\
	len = (m)->m_pkthdr.len;					\
	mflags = (m)->m_flags;						\
	IFQ_ENQUEUE(&(ifp)->if_snd, m, err);				\
	if ((err) == 0) {						\
		(ifp)->if_obytes += len + (adj);			\
		if (mflags & M_MCAST)					\
			(ifp)->if_omcasts++;				\
		if (((ifp)->if_drv_flags & IFF_DRV_OACTIVE) == 0)	\
			if_start(ifp);					\
	}								\
} while (0)

#define	IFQ_HANDOFF(ifp, m, err)					\
	IFQ_HANDOFF_ADJ(ifp, m, 0, err)

#define	IFQ_DRV_DEQUEUE(ifq, m)						\
do {									\
	(m) = (ifq)->ifq_drv_head;					\
	if (m) {							\
		if (((ifq)->ifq_drv_head = (m)->m_nextpkt) == NULL)	\
			(ifq)->ifq_drv_tail = NULL;			\
		(m)->m_nextpkt = NULL;					\
		(ifq)->ifq_drv_len--;					\
	} else {							\
		IFQ_LOCK(ifq);						\
		IFQ_DEQUEUE_NOLOCK(ifq, m);				\
		while ((ifq)->ifq_drv_len < (ifq)->ifq_drv_maxlen) {	\
			struct mbuf *m0;				\
			IFQ_DEQUEUE_NOLOCK(ifq, m0);			\
			if (m0 == NULL)					\
				break;					\
			m0->m_nextpkt = NULL;				\
			if ((ifq)->ifq_drv_tail == NULL)		\
				(ifq)->ifq_drv_head = m0;		\
			else						\
				(ifq)->ifq_drv_tail->m_nextpkt = m0;	\
			(ifq)->ifq_drv_tail = m0;			\
			(ifq)->ifq_drv_len++;				\
		}							\
		IFQ_UNLOCK(ifq);					\
	}								\
} while (0)

#define	IFQ_DRV_PREPEND(ifq, m)						\
do {									\
	(m)->m_nextpkt = (ifq)->ifq_drv_head;				\
	if ((ifq)->ifq_drv_tail == NULL)				\
		(ifq)->ifq_drv_tail = (m);				\
	(ifq)->ifq_drv_head = (m);					\
	(ifq)->ifq_drv_len++;						\
} while (0)

#define	IFQ_DRV_IS_EMPTY(ifq)						\
	(((ifq)->ifq_drv_len == 0) && ((ifq)->ifq_len == 0))

#define	IFQ_DRV_PURGE(ifq)						\
do {									\
	struct mbuf *m, *n = (ifq)->ifq_drv_head;			\
	while((m = n) != NULL) {					\
		n = m->m_nextpkt;					\
		m_freem(m);						\
	}								\
	(ifq)->ifq_drv_head = (ifq)->ifq_drv_tail = NULL;		\
	(ifq)->ifq_drv_len = 0;						\
	IFQ_PURGE(ifq);							\
} while (0)

#ifdef _KERNEL
static __inline void
drbr_stats_update(struct ifnet *ifp, int len, int mflags)
{
#ifndef NO_SLOW_STATS
	ifp->if_obytes += len;
	if (mflags & M_MCAST)
		ifp->if_omcasts++;
#endif
}

static __inline int
drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
{
	int error = 0;
	int len = m->m_pkthdr.len;
	int mflags = m->m_flags;

#ifdef ALTQ
	if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
		IFQ_ENQUEUE(&ifp->if_snd, m, error);
		return (error);
	}
#endif
	if ((error = buf_ring_enqueue_bytes(br, m, len)) == ENOBUFS) {
		br->br_drops++;
		m_freem(m);
	} else
		drbr_stats_update(ifp, len, mflags);

	return (error);
}

static __inline void
drbr_flush(struct ifnet *ifp, struct buf_ring *br)
{
	struct mbuf *m;

#ifdef ALTQ
	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
		IFQ_PURGE(&ifp->if_snd);
#endif
	while ((m = buf_ring_dequeue_sc(br)) != NULL)
		m_freem(m);
}

static __inline void
drbr_free(struct buf_ring *br, struct malloc_type *type)
{

	drbr_flush(NULL, br);
	buf_ring_free(br, type);
}

static __inline struct mbuf *
drbr_dequeue(struct ifnet *ifp, struct buf_ring *br)
{
#ifdef ALTQ
	struct mbuf *m;

	if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
		IFQ_DEQUEUE(&ifp->if_snd, m);
		return (m);
	}
#endif
	return (buf_ring_dequeue_sc(br));
}

static __inline struct mbuf *
drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
    int (*func) (struct mbuf *, void *), void *arg)
{
	struct mbuf *m;
#ifdef ALTQ
	if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
		IFQ_LOCK(&ifp->if_snd);
		IFQ_POLL_NOLOCK(&ifp->if_snd, m);
		if (m != NULL && func(m, arg) == 0) {
			IFQ_UNLOCK(&ifp->if_snd);
			return (NULL);
		}
		IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m);
		IFQ_UNLOCK(&ifp->if_snd);
		return (m);
	}
#endif
	m = buf_ring_peek(br);
	if (m == NULL || func(m, arg) == 0)
		return (NULL);

	return (buf_ring_dequeue_sc(br));
}

static __inline int
drbr_empty(struct ifnet *ifp, struct buf_ring *br)
{
#ifdef ALTQ
	if (ALTQ_IS_ENABLED(&ifp->if_snd))
		return (IFQ_IS_EMPTY(&ifp->if_snd));
#endif
	return (buf_ring_empty(br));
}

static __inline int
drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
{
#ifdef ALTQ
	if (ALTQ_IS_ENABLED(&ifp->if_snd))
		return (1);
#endif
	return (!buf_ring_empty(br));
}

static __inline int
drbr_inuse(struct ifnet *ifp, struct buf_ring *br)
{
#ifdef ALTQ
	if (ALTQ_IS_ENABLED(&ifp->if_snd))
		return (ifp->if_snd.ifq_len);
#endif
	return (buf_ring_count(br));
}
#endif
/*
 * 72 was chosen below because it is the size of a TCP/IP
 * header (40) + the minimum mss (32).
 */
#define	IF_MINMTU	72
#define	IF_MAXMTU	65535

#endif /* _KERNEL */

/*
 * The ifaddr structure contains information about one address
 * of an interface.  They are maintained by the different address families,
 * are allocated and attached when an address is set, and are linked
 * together so all addresses for an interface can be located.
 *
 * NOTE: a 'struct ifaddr' is always at the beginning of a larger
 * chunk of malloc'ed memory, where we store the three addresses
 * (ifa_addr, ifa_dstaddr and ifa_netmask) referenced here.
 */
struct ifaddr {
	struct	sockaddr *ifa_addr;	/* address of interface */
	struct	sockaddr *ifa_dstaddr;	/* other end of p-to-p link */
#define	ifa_broadaddr	ifa_dstaddr	/* broadcast address interface */
	struct	sockaddr *ifa_netmask;	/* used to determine subnet */
	struct	if_data if_data;	/* not all members are meaningful */
	struct	ifnet *ifa_ifp;		/* back-pointer to interface */
	TAILQ_ENTRY(ifaddr) ifa_link;	/* queue macro glue */
	void	(*ifa_rtrequest)	/* check or clean routes (+ or -)'d */
		(int, struct rtentry *, struct rt_addrinfo *);
	u_short	ifa_flags;		/* mostly rt_flags for cloning */
	u_int	ifa_refcnt;		/* references to this structure */
	int	ifa_metric;		/* cost of going out this interface */
	int (*ifa_claim_addr)		/* check if an addr goes to this if */
		(struct ifaddr *, struct sockaddr *);
	struct mtx ifa_mtx;
};
#define	IFA_ROUTE	RTF_UP		/* route installed */
#define IFA_RTSELF	RTF_HOST	/* loopback route to self installed */

/* for compatibility with other BSDs */
#define	ifa_list	ifa_link

#ifdef _KERNEL
#define	IFA_LOCK(ifa)		mtx_lock(&(ifa)->ifa_mtx)
#define	IFA_UNLOCK(ifa)		mtx_unlock(&(ifa)->ifa_mtx)

void	ifa_free(struct ifaddr *ifa);
void	ifa_init(struct ifaddr *ifa);
void	ifa_ref(struct ifaddr *ifa);
#endif

/*
 * The prefix structure contains information about one prefix
 * of an interface.  They are maintained by the different address families,
 * are allocated and attached when a prefix or an address is set,
 * and are linked together so all prefixes for an interface can be located.
 */
struct ifprefix {
	struct	sockaddr *ifpr_prefix;	/* prefix of interface */
	struct	ifnet *ifpr_ifp;	/* back-pointer to interface */
	TAILQ_ENTRY(ifprefix) ifpr_list; /* queue macro glue */
	u_char	ifpr_plen;		/* prefix length in bits */
	u_char	ifpr_type;		/* protocol dependent prefix type */
};

/*
 * Multicast address structure.  This is analogous to the ifaddr
 * structure except that it keeps track of multicast addresses.
 */
struct ifmultiaddr {
	TAILQ_ENTRY(ifmultiaddr) ifma_link; /* queue macro glue */
	struct	sockaddr *ifma_addr; 	/* address this membership is for */
	struct	sockaddr *ifma_lladdr;	/* link-layer translation, if any */
	struct	ifnet *ifma_ifp;	/* back-pointer to interface */
	u_int	ifma_refcount;		/* reference count */
	void	*ifma_protospec;	/* protocol-specific state, if any */
	struct	ifmultiaddr *ifma_llifma; /* pointer to ifma for ifma_lladdr */
};

#ifdef _KERNEL

extern	struct rwlock ifnet_rwlock;
extern	struct sx ifnet_sxlock;

#define	IFNET_LOCK_INIT() do {						\
	rw_init_flags(&ifnet_rwlock, "ifnet_rw",  RW_RECURSE);		\
	sx_init_flags(&ifnet_sxlock, "ifnet_sx",  SX_RECURSE);		\
} while(0)

#define	IFNET_WLOCK() do {						\
	sx_xlock(&ifnet_sxlock);					\
	rw_wlock(&ifnet_rwlock);					\
} while (0)

#define	IFNET_WUNLOCK() do {						\
	rw_wunlock(&ifnet_rwlock);					\
	sx_xunlock(&ifnet_sxlock);					\
} while (0)

/*
 * To assert the ifnet lock, you must know not only whether it's for read or
 * write, but also whether it was acquired with sleep support or not.
 */
#define	IFNET_RLOCK_ASSERT()		sx_assert(&ifnet_sxlock, SA_SLOCKED)
#define	IFNET_RLOCK_NOSLEEP_ASSERT()	rw_assert(&ifnet_rwlock, RA_RLOCKED)
#define	IFNET_WLOCK_ASSERT() do {					\
	sx_assert(&ifnet_sxlock, SA_XLOCKED);				\
	rw_assert(&ifnet_rwlock, RA_WLOCKED);				\
} while (0)

#define	IFNET_RLOCK()		sx_slock(&ifnet_sxlock)
#define	IFNET_RLOCK_NOSLEEP()	rw_rlock(&ifnet_rwlock)
#define	IFNET_RUNLOCK()		sx_sunlock(&ifnet_sxlock)
#define	IFNET_RUNLOCK_NOSLEEP()	rw_runlock(&ifnet_rwlock)

/*
 * Look up an ifnet given its index; the _ref variant also acquires a
 * reference that must be freed using if_rele().  It is almost always a bug
 * to call ifnet_byindex() instead if ifnet_byindex_ref().
 */
struct ifnet	*ifnet_byindex(u_short idx);
struct ifnet	*ifnet_byindex_locked(u_short idx);
struct ifnet	*ifnet_byindex_ref(u_short idx);

/*
 * Given the index, ifaddr_byindex() returns the one and only
 * link-level ifaddr for the interface. You are not supposed to use
 * it to traverse the list of addresses associated to the interface.
 */
struct ifaddr	*ifaddr_byindex(u_short idx);

VNET_DECLARE(struct ifnethead, ifnet);
VNET_DECLARE(struct ifgrouphead, ifg_head);
VNET_DECLARE(int, if_index);
VNET_DECLARE(struct ifnet *, loif);	/* first loopback interface */
VNET_DECLARE(int, useloopback);

#define	V_ifnet		VNET(ifnet)
#define	V_ifg_head	VNET(ifg_head)
#define	V_if_index	VNET(if_index)
#define	V_loif		VNET(loif)
#define	V_useloopback	VNET(useloopback)

extern	int ifqmaxlen;

int	if_addgroup(struct ifnet *, const char *);
int	if_delgroup(struct ifnet *, const char *);
int	if_addmulti(struct ifnet *, struct sockaddr *, struct ifmultiaddr **);
int	if_allmulti(struct ifnet *, int);
struct	ifnet* if_alloc(u_char);
void	if_attach(struct ifnet *);
void	if_dead(struct ifnet *);
int	if_delmulti(struct ifnet *, struct sockaddr *);
void	if_delmulti_ifma(struct ifmultiaddr *);
void	if_detach(struct ifnet *);
void	if_vmove(struct ifnet *, struct vnet *);
void	if_purgeaddrs(struct ifnet *);
void	if_delallmulti(struct ifnet *);
void	if_down(struct ifnet *);
struct ifmultiaddr *
	if_findmulti(struct ifnet *, struct sockaddr *);
void	if_free(struct ifnet *);
void	if_free_type(struct ifnet *, u_char);
void	if_initname(struct ifnet *, const char *, int);
void	if_link_state_change(struct ifnet *, int);
int	if_printf(struct ifnet *, const char *, ...) __printflike(2, 3);
void	if_qflush(struct ifnet *);
void	if_ref(struct ifnet *);
void	if_rele(struct ifnet *);
int	if_setlladdr(struct ifnet *, const u_char *, int);
void	if_up(struct ifnet *);
int	ifioctl(struct socket *, u_long, caddr_t, struct thread *);
int	ifpromisc(struct ifnet *, int);
struct	ifnet *ifunit(const char *);
struct	ifnet *ifunit_ref(const char *);

void	ifq_init(struct ifaltq *, struct ifnet *ifp);
void	ifq_delete(struct ifaltq *);

int	ifa_add_loopback_route(struct ifaddr *, struct sockaddr *);
int	ifa_del_loopback_route(struct ifaddr *, struct sockaddr *);

struct	ifaddr *ifa_ifwithaddr(struct sockaddr *);
int		ifa_ifwithaddr_check(struct sockaddr *);
struct	ifaddr *ifa_ifwithbroadaddr(struct sockaddr *);
struct	ifaddr *ifa_ifwithdstaddr(struct sockaddr *);
struct	ifaddr *ifa_ifwithnet(struct sockaddr *, int);
struct	ifaddr *ifa_ifwithroute(int, struct sockaddr *, struct sockaddr *);
struct	ifaddr *ifa_ifwithroute_fib(int, struct sockaddr *, struct sockaddr *, u_int);

struct	ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *);

int	if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen);

typedef	void *if_com_alloc_t(u_char type, struct ifnet *ifp);
typedef	void if_com_free_t(void *com, u_char type);
void	if_register_com_alloc(u_char type, if_com_alloc_t *a, if_com_free_t *f);
void	if_deregister_com_alloc(u_char type);

#define IF_LLADDR(ifp)							\
    LLADDR((struct sockaddr_dl *)((ifp)->if_addr->ifa_addr))

#ifdef DEVICE_POLLING
enum poll_cmd {	POLL_ONLY, POLL_AND_CHECK_STATUS };

typedef	int poll_handler_t(struct ifnet *ifp, enum poll_cmd cmd, int count);
int    ether_poll_register(poll_handler_t *h, struct ifnet *ifp);
int    ether_poll_deregister(struct ifnet *ifp);
#endif /* DEVICE_POLLING */

#endif /* _KERNEL */

#endif /* !_NET_IF_VAR_H_ */


code:
/*-
 * Copyright 1998 Massachusetts Institute of Technology
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby
 * granted, provided that both the above copyright notice and this
 * permission notice appear in all copies, that both the above
 * copyright notice and this permission notice appear in all
 * supporting documentation, and that the name of M.I.T. not be used
 * in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.  M.I.T. makes
 * no representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied
 * warranty.
 *
 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
 * SHALL M.I.T. 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/net/if_vlan_var.h 219819 2011-03-21 09:40:01Z jeff $
 */

#ifndef _NET_IF_VLAN_VAR_H_
#define	_NET_IF_VLAN_VAR_H_	1

struct	ether_vlan_header {
	u_char	evl_dhost[ETHER_ADDR_LEN];
	u_char	evl_shost[ETHER_ADDR_LEN];
	u_int16_t evl_encap_proto;
	u_int16_t evl_tag;
	u_int16_t evl_proto;
};

#define	EVL_VLID_MASK		0x0FFF
#define	EVL_PRI_MASK		0xE000
#define	EVL_VLANOFTAG(tag)	((tag) & EVL_VLID_MASK)
#define	EVL_PRIOFTAG(tag)	(((tag) >> 13) & 7)
#define	EVL_CFIOFTAG(tag)	(((tag) >> 12) & 1)
#define	EVL_MAKETAG(vlid, pri, cfi)					\
	((((((pri) & 7) << 1) | ((cfi) & 1)) << 12) | ((vlid) & EVL_VLID_MASK))

/* Set the VLAN ID in an mbuf packet header non-destructively. */
#define EVL_APPLY_VLID(m, vlid)						\
	do {								\
		if ((m)->m_flags & M_VLANTAG) {				\
			(m)->m_pkthdr.ether_vtag &= EVL_VLID_MASK;	\
			(m)->m_pkthdr.ether_vtag |= (vlid);		\
		} else {						\
			(m)->m_pkthdr.ether_vtag = (vlid);		\
			(m)->m_flags |= M_VLANTAG;			\
		}							\
	} while (0)

/* Set the priority ID in an mbuf packet header non-destructively. */
#define EVL_APPLY_PRI(m, pri)						\
	do {								\
		if ((m)->m_flags & M_VLANTAG) {				\
			uint16_t __vlantag = (m)->m_pkthdr.ether_vtag;	\
			(m)->m_pkthdr.ether_vtag |= EVL_MAKETAG(	\
			    EVL_VLANOFTAG(__vlantag), (pri),		\
			    EVL_CFIOFTAG(__vlantag));			\
		} else {						\
			(m)->m_pkthdr.ether_vtag =			\
			    EVL_MAKETAG(0, (pri), 0);			\
			(m)->m_flags |= M_VLANTAG;			\
		}							\
	} while (0)

/* sysctl(3) tags, for compatibility purposes */
#define	VLANCTL_PROTO	1
#define	VLANCTL_MAX	2

/*
 * Configuration structure for SIOCSETVLAN and SIOCGETVLAN ioctls.
 */
struct	vlanreq {
	char	vlr_parent[IFNAMSIZ];
	u_short	vlr_tag;
};
#define	SIOCSETVLAN	SIOCSIFGENERIC
#define	SIOCGETVLAN	SIOCGIFGENERIC

#ifdef _KERNEL
/*
 * Drivers that are capable of adding and removing the VLAN header
 * in hardware indicate they support this by marking IFCAP_VLAN_HWTAGGING
 * in if_capabilities.  Drivers for hardware that is capable
 * of handling larger MTU's that may include a software-appended
 * VLAN header w/o lowering the normal MTU should mark IFCAP_VLAN_MTU
 * in if_capabilities; this notifies the VLAN code it can leave the
 * MTU on the vlan interface at the normal setting.
 */

/*
 * VLAN tags are stored in host byte order.  Byte swapping may be
 * necessary.
 *
 * Drivers that support hardware VLAN tag stripping fill in the
 * received VLAN tag (containing both vlan and priority information)
 * into the ether_vtag mbuf packet header field:
 *
 *	m->m_pkthdr.ether_vtag = vlan_id;	// ntohs()?
 *	m->m_flags |= M_VLANTAG;
 *
 * to mark the packet m with the specified VLAN tag.
 *
 * On output the driver should check the mbuf for the M_VLANTAG
 * flag to see if a VLAN tag is present and valid:
 *
 *	if (m->m_flags & M_VLANTAG) {
 *		... = m->m_pkthdr.ether_vtag;	// htons()?
 *		... pass tag to hardware ...
 *	}
 *
 * Note that a driver must indicate it supports hardware VLAN
 * stripping/insertion by marking IFCAP_VLAN_HWTAGGING in
 * if_capabilities.
 */

#define	VLAN_CAPABILITIES(_ifp) do {				\
	if ((_ifp)->if_vlantrunk != NULL) 			\
		(*vlan_trunk_cap_p)(_ifp);			\
} while (0)

#define	VLAN_TRUNKDEV(_ifp)					\
	(_ifp)->if_type == IFT_L2VLAN ? (*vlan_trunkdev_p)((_ifp)) : NULL
#define	VLAN_TAG(_ifp, _tag)					\
	(_ifp)->if_type == IFT_L2VLAN ? (*vlan_tag_p)((_ifp), (_tag)) : EINVAL
#define	VLAN_COOKIE(_ifp)					\
	(_ifp)->if_type == IFT_L2VLAN ? (*vlan_cookie_p)((_ifp)) : NULL
#define	VLAN_SETCOOKIE(_ifp, _cookie)				\
	(_ifp)->if_type == IFT_L2VLAN ?				\
	    (*vlan_setcookie_p)((_ifp), (_cookie)) : EINVAL
#define	VLAN_DEVAT(_ifp, _tag)					\
	(_ifp)->if_vlantrunk != NULL ? (*vlan_devat_p)((_ifp), (_tag)) : NULL

extern	void (*vlan_trunk_cap_p)(struct ifnet *);
extern	struct ifnet *(*vlan_trunkdev_p)(struct ifnet *);
extern	struct ifnet *(*vlan_devat_p)(struct ifnet *, uint16_t);
extern	int (*vlan_tag_p)(struct ifnet *, uint16_t *);
extern	int (*vlan_setcookie_p)(struct ifnet *, void *);
extern	void *(*vlan_cookie_p)(struct ifnet *);

#endif /* _KERNEL */

#endif /* _NET_IF_VLAN_VAR_H_ */

repo_name: veiledmerc/mira

license: mit


code:
/*-
 * Copyright (c) 1998, Larry Lile
 * All rights reserved.
 *
 * For latest sources and information on this driver, please
 * go to http://anarchy.stdio.com.
 *
 * Questions, comments or suggestions should be directed to
 * Larry Lile <lile@stdio.com>.
 *
 * 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 unmodified, 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.
 *
 * 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/net/iso88025.h 194581 2009-06-21 10:29:31Z rdivacky $
 *
 * Information gathered from tokenring@freebsd, /sys/net/ethernet.h and
 * the Mach token ring driver.
 */

/*
 * Fundamental constants relating to iso 802.5
 */

#ifndef _NET_ISO88025_H_
#define	_NET_ISO88025_H_

/*
 * General ISO 802.5 definitions
 */
#define	ISO88025_ADDR_LEN	6
#define	ISO88025_CF_LEN		2
#define	ISO88025_HDR_LEN	(ISO88025_CF_LEN + (ISO88025_ADDR_LEN * 2))
#define	RCF_LEN			2
#define	RIF_MAX_RD		14
#define	RIF_MAX_LEN		16

#define	TR_AC			0x10
#define	TR_LLC_FRAME		0x40

#define	TR_4MBPS		4000000
#define	TR_16MBPS		16000000
#define	TR_100MBPS		100000000

/*
 * Source routing
 */
#define	TR_RII			0x80
#define	TR_RCF_BCST_MASK	0xe000
#define	TR_RCF_LEN_MASK		0x1f00
#define	TR_RCF_DIR		0x0080
#define	TR_RCF_LF_MASK		0x0070

#define	TR_RCF_RIFLEN(x)	((ntohs(x) & TR_RCF_LEN_MASK) >> 8)

/*
 * Minimum and maximum packet payload lengths.
 */
#define	ISO88025_MIN_LEN	0
#define	ISO88025_MAX_LEN_4	4464
#define	ISO88025_MAX_LEN_16	17960
#define	ISO88025_MAX_LEN	ISO88025_MAX_LEN_16

/*
 * A macro to validate a length with
 */
#define	ISO88025_IS_VALID_LEN(foo)	\
	((foo) >= ISO88025_MIN_LEN && (foo) <= ISO88025_MAX_LEN)

/* Access Control field */
#define	AC_PRI_MASK		0xe0	/* Priority bits 		*/
#define	AC_TOKEN		0x10	/* Token bit: 0=Token, 1=Frame	*/
#define	AC_MONITOR		0x08	/* Monitor			*/
#define	AC_RESV_MASK		0x07	/* Reservation bits		*/

/* Frame Control field */
#define	FC_FT_MASK		0xc0	/* Frame Type			*/
#define	FC_FT_MAC		0x00	/* MAC frame			*/
#define	FC_FT_LLC		0x40	/* LLC frame			*/
#define	FC_ATTN_MASK		0x0f	/* Attention bits		*/
#define	FC_ATTN_EB		0x01	/* Express buffer		*/
#define	FC_ATTN_BE		0x02	/* Beacon			*/
#define	FC_ATTN_CT		0x03	/* Claim token			*/
#define	FC_ATTN_RP		0x04	/* Ring purge			*/
#define	FC_ATTN_AMP		0x05	/* Active monitor present	*/
#define	FC_ATTN_SMP		0x06	/* Standby monitor present	*/

/* Token Ring destination address */
#define	DA_IG			0x80	/* Individual/group address.	*/
					/* 0=Individual, 1=Group	*/
#define	DA_UL			0x40	/* Universal/local address.	*/
					/* 0=Universal, 1=Local		*/
/* Token Ring source address */
#define	SA_RII			0x80	/* Routing information indicator */
#define	SA_IG			0x40	/* Individual/group address	*/
					/* 0=Group, 1=Individual	*/

/*
 * ISO 802.5 physical header
 */
struct iso88025_header {
	u_int8_t	ac;				    /* access control field */
	u_int8_t	fc;				    /* frame control field */
	u_int8_t	iso88025_dhost[ISO88025_ADDR_LEN];  /* destination address */
	u_int8_t	iso88025_shost[ISO88025_ADDR_LEN];  /* source address */
	u_int16_t	rcf;				    /* route control field */
	u_int16_t	rd[RIF_MAX_RD];			    /* routing designators */
} __packed;

struct iso88025_rif {
	u_int16_t	rcf;				    /* route control field */
	u_int16_t	rd[RIF_MAX_RD];			    /* routing designators */
} __packed;

struct iso88025_sockaddr_data {
	u_char ether_dhost[ISO88025_ADDR_LEN];
	u_char ether_shost[ISO88025_ADDR_LEN];
	u_char ac;
	u_char fc;
};

struct iso88025_sockaddr_dl_data {
	u_short	 trld_rcf;
	u_short	*trld_route[RIF_MAX_LEN];
};

#define	ISO88025_MAX(a, b)	(((a)>(b))?(a):(b))
#define	SDL_ISO88025(s)		((struct iso88025_sockaddr_dl_data *)	\
				 ((s)->sdl_data + \
				  ISO88025_MAX((s)->sdl_nlen + (s)->sdl_alen + \
					       (s)->sdl_slen, 12)))

/*
 * Structure of a 48-bit iso 802.5 address.
 *  ( We could also add the 16 bit addresses as a union)
 */
struct	iso88025_addr {
	u_char octet[ISO88025_ADDR_LEN];
};

#define	ISO88025_MAX_MTU		18000
#define	ISO88025_DEFAULT_MTU		1500

#define	ISO88025_BPF_UNSUPPORTED	0
#define	ISO88025_BPF_SUPPORTED		1

void	iso88025_ifattach	(struct ifnet *, const u_int8_t *, int);
void	iso88025_ifdetach	(struct ifnet *, int);
int	iso88025_ioctl		(struct ifnet *, u_long, caddr_t );
int	iso88025_output		(struct ifnet *, struct mbuf *, struct sockaddr *,
    				 struct route *);
void	iso88025_input		(struct ifnet *, struct mbuf *);

#endif


code:
/*-
 * Copyright (c) 2007-2009 Robert N. M. Watson
 * Copyright (c) 2010-2011 Juniper Networks, Inc.
 * All rights reserved.
 *
 * This software was developed by Robert N. M. Watson under contract
 * to Juniper Networks, Inc.
 *
 * 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.
 *
 * 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/net/netisr.h 222249 2011-05-24 12:34:19Z rwatson $
 */

#ifndef _NET_NETISR_H_
#define _NET_NETISR_H_

/*
 * The netisr (network interrupt service routine) provides a deferred
 * execution evironment in which (generally inbound) network processing can
 * take place.  Protocols register handlers which will be executed directly,
 * or via deferred dispatch, depending on the circumstances.
 *
 * Historically, this was implemented by the BSD software ISR facility; it is
 * now implemented via a software ithread (SWI).
 */

/*
 * Protocol numbers, which are encoded in monitoring applications and kernel
 * modules.  Internally, these are used in bit shift operations so must have
 * a value 0 < proto < 32; we currently further limit at compile-time to 16
 * for array-sizing purposes.
 */
#define	NETISR_IP	1
#define	NETISR_IGMP	2		/* IGMPv3 output queue */
#define	NETISR_ROUTE	3		/* routing socket */
#define	NETISR_AARP	4		/* Appletalk ARP */
#define	NETISR_ATALK2	5		/* Appletalk phase 2 */
#define	NETISR_ATALK1	6		/* Appletalk phase 1 */
#define	NETISR_ARP	7		/* same as AF_LINK */
#define	NETISR_IPX	8		/* same as AF_IPX */
#define	NETISR_ETHER	9		/* ethernet input */
#define	NETISR_IPV6	10
#define	NETISR_NATM	11
#define	NETISR_EPAIR	12		/* if_epair(4) */

/*
 * Protocol ordering and affinity policy constants.  See the detailed
 * discussion of policies later in the file.
 */
#define	NETISR_POLICY_SOURCE	1	/* Maintain source ordering. */
#define	NETISR_POLICY_FLOW	2	/* Maintain flow ordering. */
#define	NETISR_POLICY_CPU	3	/* Protocol determines CPU placement. */

/*
 * Protocol dispatch policy constants; selects whether and when direct
 * dispatch is permitted.
 */
#define	NETISR_DISPATCH_DEFAULT		0	/* Use global default. */
#define	NETISR_DISPATCH_DEFERRED	1	/* Always defer dispatch. */
#define	NETISR_DISPATCH_HYBRID		2	/* Allow hybrid dispatch. */
#define	NETISR_DISPATCH_DIRECT		3	/* Always direct dispatch. */

/*
 * Monitoring data structures, exported by sysctl(2).
 *
 * Three sysctls are defined.  First, a per-protocol structure exported by
 * net.isr.proto.
 */
#define	NETISR_NAMEMAXLEN	32
struct sysctl_netisr_proto {
	u_int	snp_version;			/* Length of struct. */
	char	snp_name[NETISR_NAMEMAXLEN];	/* nh_name */
	u_int	snp_proto;			/* nh_proto */
	u_int	snp_qlimit;			/* nh_qlimit */
	u_int	snp_policy;			/* nh_policy */
	u_int	snp_flags;			/* Various flags. */
	u_int	snp_dispatch;			/* Dispatch policy. */
	u_int	_snp_ispare[6];
};

/*
 * Flags for sysctl_netisr_proto.snp_flags.
 */
#define	NETISR_SNP_FLAGS_M2FLOW		0x00000001	/* nh_m2flow */
#define	NETISR_SNP_FLAGS_M2CPUID	0x00000002	/* nh_m2cpuid */
#define	NETISR_SNP_FLAGS_DRAINEDCPU	0x00000004	/* nh_drainedcpu */

/*
 * Next, a structure per-workstream, with per-protocol data, exported as
 * net.isr.workstream.
 */
struct sysctl_netisr_workstream {
	u_int	snws_version;			/* Length of struct. */
	u_int	snws_flags;			/* Various flags. */
	u_int	snws_wsid;			/* Workstream ID. */
	u_int	snws_cpu;			/* nws_cpu */
	u_int	_snws_ispare[12];
};

/*
 * Flags for sysctl_netisr_workstream.snws_flags
 */
#define	NETISR_SNWS_FLAGS_INTR		0x00000001	/* nws_intr_event */

/*
 * Finally, a per-workstream-per-protocol structure, exported as
 * net.isr.work.
 */
struct sysctl_netisr_work {
	u_int	snw_version;			/* Length of struct. */
	u_int	snw_wsid;			/* Workstream ID. */
	u_int	snw_proto;			/* Protocol number. */
	u_int	snw_len;			/* nw_len */
	u_int	snw_watermark;			/* nw_watermark */
	u_int	_snw_ispare[3];

	uint64_t	snw_dispatched;		/* nw_dispatched */
	uint64_t	snw_hybrid_dispatched;	/* nw_hybrid_dispatched */
	uint64_t	snw_qdrops;		/* nw_qdrops */
	uint64_t	snw_queued;		/* nw_queued */
	uint64_t	snw_handled;		/* nw_handled */

	uint64_t	_snw_llspare[7];
};

#ifdef _KERNEL

/*-
 * Protocols express ordering constraints and affinity preferences by
 * implementing one or neither of nh_m2flow and nh_m2cpuid, which are used by
 * netisr to determine which per-CPU workstream to assign mbufs to.
 *
 * The following policies may be used by protocols:
 *
 * NETISR_POLICY_SOURCE - netisr should maintain source ordering without
 *                        advice from the protocol.  netisr will ignore any
 *                        flow IDs present on the mbuf for the purposes of
 *                        work placement.
 *
 * NETISR_POLICY_FLOW - netisr should maintain flow ordering as defined by
 *                      the mbuf header flow ID field.  If the protocol
 *                      implements nh_m2flow, then netisr will query the
 *                      protocol in the event that the mbuf doesn't have a
 *                      flow ID, falling back on source ordering.
 *
 * NETISR_POLICY_CPU - netisr will delegate all work placement decisions to
 *                     the protocol, querying nh_m2cpuid for each packet.
 *
 * Protocols might make decisions about work placement based on an existing
 * calculated flow ID on the mbuf, such as one provided in hardware, the
 * receive interface pointed to by the mbuf (if any), the optional source
 * identifier passed at some dispatch points, or even parse packet headers to
 * calculate a flow.  Both protocol handlers may return a new mbuf pointer
 * for the chain, or NULL if the packet proves invalid or m_pullup() fails.
 *
 * XXXRW: If we eventually support dynamic reconfiguration, there should be
 * protocol handlers to notify them of CPU configuration changes so that they
 * can rebalance work.
 */
struct mbuf;
typedef void		 netisr_handler_t(struct mbuf *m);
typedef struct mbuf	*netisr_m2cpuid_t(struct mbuf *m, uintptr_t source,
			 u_int *cpuid);
typedef	struct mbuf	*netisr_m2flow_t(struct mbuf *m, uintptr_t source);
typedef void		 netisr_drainedcpu_t(u_int cpuid);

#define	NETISR_CPUID_NONE	((u_int)-1)	/* No affinity returned. */

/*
 * Data structure describing a protocol handler.
 */
struct netisr_handler {
	const char	*nh_name;	/* Character string protocol name. */
	netisr_handler_t *nh_handler;	/* Protocol handler. */
	netisr_m2flow_t	*nh_m2flow;	/* Query flow for untagged packet. */
	netisr_m2cpuid_t *nh_m2cpuid;	/* Query CPU to process mbuf on. */
	netisr_drainedcpu_t *nh_drainedcpu; /* Callback when drained a queue. */
	u_int		 nh_proto;	/* Integer protocol ID. */
	u_int		 nh_qlimit;	/* Maximum per-CPU queue depth. */
	u_int		 nh_policy;	/* Work placement policy. */
	u_int		 nh_dispatch;	/* Dispatch policy. */
	u_int		 nh_ispare[4];	/* For future use. */
	void		*nh_pspare[4];	/* For future use. */
};

/*
 * Register, unregister, and other netisr handler management functions.
 */
void	netisr_clearqdrops(const struct netisr_handler *nhp);
void	netisr_getqdrops(const struct netisr_handler *nhp,
	    u_int64_t *qdropsp);
void	netisr_getqlimit(const struct netisr_handler *nhp, u_int *qlimitp);
void	netisr_register(const struct netisr_handler *nhp);
int	netisr_setqlimit(const struct netisr_handler *nhp, u_int qlimit);
void	netisr_unregister(const struct netisr_handler *nhp);

/*
 * Process a packet destined for a protocol, and attempt direct dispatch.
 * Supplemental source ordering information can be passed using the _src
 * variant.
 */
int	netisr_dispatch(u_int proto, struct mbuf *m);
int	netisr_dispatch_src(u_int proto, uintptr_t source, struct mbuf *m);
int	netisr_queue(u_int proto, struct mbuf *m);
int	netisr_queue_src(u_int proto, uintptr_t source, struct mbuf *m);

/*
 * Provide a default implementation of "map an ID to a CPU ID".
 */
u_int	netisr_default_flow2cpu(u_int flowid);

/*
 * Utility routines to return the number of CPUs participting in netisr, and
 * to return a mapping from a number to a CPU ID that can be used with the
 * scheduler.
 */
u_int	netisr_get_cpucount(void);
u_int	netisr_get_cpuid(u_int cpunumber);

/*
 * Interfaces between DEVICE_POLLING and netisr.
 */
void	netisr_sched_poll(void);
void	netisr_poll(void);
void	netisr_pollmore(void);

#endif /* !_KERNEL */
#endif /* !_NET_NETISR_H_ */


code:
/*-
 * Copyright (c) 2007-2009 Robert N. M. Watson
 * Copyright (c) 2010-2011 Juniper Networks, Inc.
 * All rights reserved.
 *
 * This software was developed by Robert N. M. Watson under contract
 * to Juniper Networks, Inc.
 *
 * 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.
 *
 * 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/net/netisr_internal.h 222249 2011-05-24 12:34:19Z rwatson $
 */

#ifndef _NET_NETISR_INTERNAL_H_
#define	_NET_NETISR_INTERNAL_H_

#ifndef _WANT_NETISR_INTERNAL
#error "no user-serviceable parts inside"
#endif

/*
 * These definitions are private to the netisr implementation, but provided
 * here for use by post-mortem crashdump analysis tools.  They should not be
 * used in any other context as they can and will change.  Public definitions
 * may be found in netisr.h.
 */

#ifndef _KERNEL
typedef void *netisr_handler_t;
typedef void *netisr_m2flow_t;
typedef void *netisr_m2cpuid_t;
typedef void *netisr_drainedcpu_t;
#endif

/*
 * Each protocol is described by a struct netisr_proto, which holds all
 * global per-protocol information.  This data structure is set up by
 * netisr_register(), and derived from the public struct netisr_handler.
 */
struct netisr_proto {
	const char	*np_name;	/* Character string protocol name. */
	netisr_handler_t *np_handler;	/* Protocol handler. */
	netisr_m2flow_t	*np_m2flow;	/* Query flow for untagged packet. */
	netisr_m2cpuid_t *np_m2cpuid;	/* Query CPU to process packet on. */
	netisr_drainedcpu_t *np_drainedcpu; /* Callback when drained a queue. */
	u_int		 np_qlimit;	/* Maximum per-CPU queue depth. */
	u_int		 np_policy;	/* Work placement policy. */
	u_int		 np_dispatch;	/* Work dispatch policy. */
};

#define	NETISR_MAXPROT	16		/* Compile-time limit. */

/*
 * Protocol-specific work for each workstream is described by struct
 * netisr_work.  Each work descriptor consists of an mbuf queue and
 * statistics.
 */
struct netisr_work {
	/*
	 * Packet queue, linked by m_nextpkt.
	 */
	struct mbuf	*nw_head;
	struct mbuf	*nw_tail;
	u_int		 nw_len;
	u_int		 nw_qlimit;
	u_int		 nw_watermark;

	/*
	 * Statistics -- written unlocked, but mostly from curcpu.
	 */
	u_int64_t	 nw_dispatched; /* Number of direct dispatches. */
	u_int64_t	 nw_hybrid_dispatched; /* "" hybrid dispatches. */
	u_int64_t	 nw_qdrops;	/* "" drops. */
	u_int64_t	 nw_queued;	/* "" enqueues. */
	u_int64_t	 nw_handled;	/* "" handled in worker. */
};

/*
 * Workstreams hold a queue of ordered work across each protocol, and are
 * described by netisr_workstream.  Each workstream is associated with a
 * worker thread, which in turn is pinned to a CPU.  Work associated with a
 * workstream can be processd in other threads during direct dispatch;
 * concurrent processing is prevented by the NWS_RUNNING flag, which
 * indicates that a thread is already processing the work queue.  It is
 * important to prevent a directly dispatched packet from "skipping ahead" of
 * work already in the workstream queue.
 */
struct netisr_workstream {
	struct intr_event *nws_intr_event;	/* Handler for stream. */
	void		*nws_swi_cookie;	/* swi(9) cookie for stream. */
	struct mtx	 nws_mtx;		/* Synchronize work. */
	u_int		 nws_cpu;		/* CPU pinning. */
	u_int		 nws_flags;		/* Wakeup flags. */
	u_int		 nws_pendingbits;	/* Scheduled protocols. */

	/*
	 * Each protocol has per-workstream data.
	 */
	struct netisr_work	nws_work[NETISR_MAXPROT];
} __aligned(CACHE_LINE_SIZE);

/*
 * Per-workstream flags.
 */
#define	NWS_RUNNING	0x00000001	/* Currently running in a thread. */
#define	NWS_DISPATCHING	0x00000002	/* Currently being direct-dispatched. */
#define	NWS_SCHEDULED	0x00000004	/* Signal issued. */

#endif /* !_NET_NETISR_INTERNAL_H_ */


code:
/*	$FreeBSD: release/9.0.0/sys/contrib/pf/net/pf_mtag.h 223637 2011-06-28 11:57:25Z bz $	*/
/*
 * Copyright (c) 2001 Daniel Hartmeier
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    - Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    - 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef _NET_PF_MTAG_H_
#define _NET_PF_MTAG_H_

#ifdef _KERNEL

#define	PF_TAG_GENERATED		0x01
#define	PF_TAG_FRAGCACHE		0x02
#define	PF_TAG_TRANSLATE_LOCALHOST	0x04
#define	PF_PACKET_LOOPED		0x08
#define	PF_FASTFWD_OURS_PRESENT		0x10

struct pf_mtag {
	void		*hdr;		/* saved hdr pos in mbuf, for ECN */
	void		*statekey;	/* pf stackside statekey */
	u_int32_t	 qid;		/* queue id */
	u_int		 rtableid;	/* alternate routing table id */
	u_int16_t	 tag;		/* tag id */
	u_int8_t	 flags;
	u_int8_t	 routed;
};

static __inline struct pf_mtag *pf_find_mtag(struct mbuf *);
static __inline struct pf_mtag *pf_get_mtag(struct mbuf *);

static __inline struct pf_mtag *
pf_find_mtag(struct mbuf *m)
{
	struct m_tag	*mtag;

	if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL)
		return (NULL);

	return ((struct pf_mtag *)(mtag + 1));
}

static __inline struct pf_mtag *
pf_get_mtag(struct mbuf *m)
{
	struct m_tag	*mtag;

	if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL) {
		mtag = m_tag_get(PACKET_TAG_PF, sizeof(struct pf_mtag),
		    M_NOWAIT);
		if (mtag == NULL)
			return (NULL);
		bzero(mtag + 1, sizeof(struct pf_mtag));
		m_tag_prepend(m, mtag);
	}

	return ((struct pf_mtag *)(mtag + 1));
}
#endif /* _KERNEL */
#endif /* _NET_PF_MTAG_H_ */


code:
/*	$FreeBSD: release/9.0.0/sys/net/pfil.h 210121 2010-07-15 14:41:06Z luigi $ */
/*	$NetBSD: pfil.h,v 1.22 2003/06/23 12:57:08 martin Exp $	*/

/*-
 * Copyright (c) 1996 Matthew R. Green
 * 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. 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 ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _NET_PFIL_H_
#define _NET_PFIL_H_

#include <sys/systm.h>
#include <sys/queue.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/lock.h>
#include <sys/rmlock.h>

struct mbuf;
struct ifnet;
struct inpcb;

/*
 * The packet filter hooks are designed for anything to call them to
 * possibly intercept the packet.
 */
struct packet_filter_hook {
        TAILQ_ENTRY(packet_filter_hook) pfil_link;
	int	(*pfil_func)(void *, struct mbuf **, struct ifnet *, int,
		    struct inpcb *);
	void	*pfil_arg;
};

#define PFIL_IN		0x00000001
#define PFIL_OUT	0x00000002
#define PFIL_WAITOK	0x00000004
#define PFIL_ALL	(PFIL_IN|PFIL_OUT)

typedef	TAILQ_HEAD(pfil_list, packet_filter_hook) pfil_list_t;

#define	PFIL_TYPE_AF		1	/* key is AF_* type */
#define	PFIL_TYPE_IFNET		2	/* key is ifnet pointer */

struct pfil_head {
	pfil_list_t	ph_in;
	pfil_list_t	ph_out;
	int		ph_type;
	int		ph_nhooks;
#if defined( __linux__ ) || defined( _WIN32 )
	rwlock_t	ph_mtx;
#else
	struct rmlock	ph_lock;
#endif
	union {
		u_long		phu_val;
		void		*phu_ptr;
	} ph_un;
#define	ph_af		ph_un.phu_val
#define	ph_ifnet	ph_un.phu_ptr
	LIST_ENTRY(pfil_head) ph_list;
};

int	pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *,
	    int, struct inpcb *), void *, int, struct pfil_head *);
int	pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *,
	    int, struct inpcb *), void *, int, struct pfil_head *);
int	pfil_run_hooks(struct pfil_head *, struct mbuf **, struct ifnet *,
	    int, struct inpcb *inp);

int	pfil_head_register(struct pfil_head *);
int	pfil_head_unregister(struct pfil_head *);

struct pfil_head *pfil_head_get(int, u_long);

#define	PFIL_HOOKED(p) ((p)->ph_nhooks > 0)
#define	PFIL_LOCK_INIT(p) \
    rm_init_flags(&(p)->ph_lock, "PFil hook read/write mutex", RM_RECURSE)
#define	PFIL_LOCK_DESTROY(p) rm_destroy(&(p)->ph_lock)
#define PFIL_RLOCK(p, t) rm_rlock(&(p)->ph_lock, (t))
#define PFIL_WLOCK(p) rm_wlock(&(p)->ph_lock)
#define PFIL_RUNLOCK(p, t) rm_runlock(&(p)->ph_lock, (t))
#define PFIL_WUNLOCK(p) rm_wunlock(&(p)->ph_lock)
#define PFIL_LIST_LOCK() mtx_lock(&pfil_global_lock)
#define PFIL_LIST_UNLOCK() mtx_unlock(&pfil_global_lock)

static __inline struct packet_filter_hook *
pfil_hook_get(int dir, struct pfil_head *ph)
{

	if (dir == PFIL_IN)
		return (TAILQ_FIRST(&ph->ph_in));
	else if (dir == PFIL_OUT)
		return (TAILQ_FIRST(&ph->ph_out));
	else
		return (NULL);
}

#endif /* _NET_PFIL_H_ */


code:
/*	$FreeBSD: release/9.0.0/sys/net/pfkeyv2.h 194062 2009-06-12 15:44:35Z vanhu $	*/
/*	$KAME: pfkeyv2.h,v 1.37 2003/09/06 05:15:43 itojun Exp $	*/

/*-
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the project nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * This file has been derived rfc 2367,
 * And added some flags of SADB_KEY_FLAGS_ as SADB_X_EXT_.
 *	sakane@ydc.co.jp
 */

#ifndef _NET_PFKEYV2_H_
#define _NET_PFKEYV2_H_

/*
This file defines structures and symbols for the PF_KEY Version 2
key management interface. It was written at the U.S. Naval Research
Laboratory. This file is in the public domain. The authors ask that
you leave this credit intact on any copies of this file.
*/
#ifndef __PFKEY_V2_H
#define __PFKEY_V2_H 1

#define PF_KEY_V2 2
#define PFKEYV2_REVISION        199806L

#define SADB_RESERVED    0
#define SADB_GETSPI      1
#define SADB_UPDATE      2
#define SADB_ADD         3
#define SADB_DELETE      4
#define SADB_GET         5
#define SADB_ACQUIRE     6
#define SADB_REGISTER    7
#define SADB_EXPIRE      8
#define SADB_FLUSH       9
#define SADB_DUMP        10
#define SADB_X_PROMISC   11
#define SADB_X_PCHANGE   12

#define SADB_X_SPDUPDATE  13
#define SADB_X_SPDADD     14
#define SADB_X_SPDDELETE  15	/* by policy index */
#define SADB_X_SPDGET     16
#define SADB_X_SPDACQUIRE 17
#define SADB_X_SPDDUMP    18
#define SADB_X_SPDFLUSH   19
#define SADB_X_SPDSETIDX  20
#define SADB_X_SPDEXPIRE  21
#define SADB_X_SPDDELETE2 22	/* by policy id */
#define SADB_MAX          22

struct sadb_msg {
  u_int8_t sadb_msg_version;
  u_int8_t sadb_msg_type;
  u_int8_t sadb_msg_errno;
  u_int8_t sadb_msg_satype;
  u_int16_t sadb_msg_len;
  u_int16_t sadb_msg_reserved;
  u_int32_t sadb_msg_seq;
  u_int32_t sadb_msg_pid;
};

struct sadb_ext {
  u_int16_t sadb_ext_len;
  u_int16_t sadb_ext_type;
};

struct sadb_sa {
  u_int16_t sadb_sa_len;
  u_int16_t sadb_sa_exttype;
  u_int32_t sadb_sa_spi;
  u_int8_t sadb_sa_replay;
  u_int8_t sadb_sa_state;
  u_int8_t sadb_sa_auth;
  u_int8_t sadb_sa_encrypt;
  u_int32_t sadb_sa_flags;
};

struct sadb_lifetime {
  u_int16_t sadb_lifetime_len;
  u_int16_t sadb_lifetime_exttype;
  u_int32_t sadb_lifetime_allocations;
  u_int64_t sadb_lifetime_bytes;
  u_int64_t sadb_lifetime_addtime;
  u_int64_t sadb_lifetime_usetime;
};

struct sadb_address {
  u_int16_t sadb_address_len;
  u_int16_t sadb_address_exttype;
  u_int8_t sadb_address_proto;
  u_int8_t sadb_address_prefixlen;
  u_int16_t sadb_address_reserved;
};

struct sadb_key {
  u_int16_t sadb_key_len;
  u_int16_t sadb_key_exttype;
  u_int16_t sadb_key_bits;
  u_int16_t sadb_key_reserved;
};

struct sadb_ident {
  u_int16_t sadb_ident_len;
  u_int16_t sadb_ident_exttype;
  u_int16_t sadb_ident_type;
  u_int16_t sadb_ident_reserved;
  u_int64_t sadb_ident_id;
};

struct sadb_sens {
  u_int16_t sadb_sens_len;
  u_int16_t sadb_sens_exttype;
  u_int32_t sadb_sens_dpd;
  u_int8_t sadb_sens_sens_level;
  u_int8_t sadb_sens_sens_len;
  u_int8_t sadb_sens_integ_level;
  u_int8_t sadb_sens_integ_len;
  u_int32_t sadb_sens_reserved;
};

struct sadb_prop {
  u_int16_t sadb_prop_len;
  u_int16_t sadb_prop_exttype;
  u_int8_t sadb_prop_replay;
  u_int8_t sadb_prop_reserved[3];
};

struct sadb_comb {
  u_int8_t sadb_comb_auth;
  u_int8_t sadb_comb_encrypt;
  u_int16_t sadb_comb_flags;
  u_int16_t sadb_comb_auth_minbits;
  u_int16_t sadb_comb_auth_maxbits;
  u_int16_t sadb_comb_encrypt_minbits;
  u_int16_t sadb_comb_encrypt_maxbits;
  u_int32_t sadb_comb_reserved;
  u_int32_t sadb_comb_soft_allocations;
  u_int32_t sadb_comb_hard_allocations;
  u_int64_t sadb_comb_soft_bytes;
  u_int64_t sadb_comb_hard_bytes;
  u_int64_t sadb_comb_soft_addtime;
  u_int64_t sadb_comb_hard_addtime;
  u_int64_t sadb_comb_soft_usetime;
  u_int64_t sadb_comb_hard_usetime;
};

struct sadb_supported {
  u_int16_t sadb_supported_len;
  u_int16_t sadb_supported_exttype;
  u_int32_t sadb_supported_reserved;
};

struct sadb_alg {
  u_int8_t sadb_alg_id;
  u_int8_t sadb_alg_ivlen;
  u_int16_t sadb_alg_minbits;
  u_int16_t sadb_alg_maxbits;
  u_int16_t sadb_alg_reserved;
};

struct sadb_spirange {
  u_int16_t sadb_spirange_len;
  u_int16_t sadb_spirange_exttype;
  u_int32_t sadb_spirange_min;
  u_int32_t sadb_spirange_max;
  u_int32_t sadb_spirange_reserved;
};

struct sadb_x_kmprivate {
  u_int16_t sadb_x_kmprivate_len;
  u_int16_t sadb_x_kmprivate_exttype;
  u_int32_t sadb_x_kmprivate_reserved;
};

/*
 * XXX Additional SA Extension.
 * mode: tunnel or transport
 * reqid: to make SA unique nevertheless the address pair of SA are same.
 *        Mainly it's for VPN.
 */
struct sadb_x_sa2 {
  u_int16_t sadb_x_sa2_len;
  u_int16_t sadb_x_sa2_exttype;
  u_int8_t sadb_x_sa2_mode;
  u_int8_t sadb_x_sa2_reserved1;
  u_int16_t sadb_x_sa2_reserved2;
  u_int32_t sadb_x_sa2_sequence;	/* lowermost 32bit of sequence number */
  u_int32_t sadb_x_sa2_reqid;
};

/* XXX Policy Extension */
/* sizeof(struct sadb_x_policy) == 16 */
struct sadb_x_policy {
  u_int16_t sadb_x_policy_len;
  u_int16_t sadb_x_policy_exttype;
  u_int16_t sadb_x_policy_type;		/* See policy type of ipsec.h */
  u_int8_t sadb_x_policy_dir;		/* direction, see ipsec.h */
  u_int8_t sadb_x_policy_reserved;
  u_int32_t sadb_x_policy_id;
  u_int32_t sadb_x_policy_reserved2;
};
/*
 * When policy_type == IPSEC, it is followed by some of
 * the ipsec policy request.
 * [total length of ipsec policy requests]
 *	= (sadb_x_policy_len * sizeof(uint64_t) - sizeof(struct sadb_x_policy))
 */

/* XXX IPsec Policy Request Extension */
/*
 * This structure is aligned 8 bytes.
 */
struct sadb_x_ipsecrequest {
  u_int16_t sadb_x_ipsecrequest_len;	/* structure length in 64 bits. */
  u_int16_t sadb_x_ipsecrequest_proto;	/* See ipsec.h */
  u_int8_t sadb_x_ipsecrequest_mode;	/* See IPSEC_MODE_XX in ipsec.h. */
  u_int8_t sadb_x_ipsecrequest_level;	/* See IPSEC_LEVEL_XX in ipsec.h */
  u_int16_t sadb_x_ipsecrequest_reqid;	/* See ipsec.h */

  /*
   * followed by source IP address of SA, and immediately followed by
   * destination IP address of SA.  These encoded into two of sockaddr
   * structure without any padding.  Must set each sa_len exactly.
   * Each of length of the sockaddr structure are not aligned to 64bits,
   * but sum of x_request and addresses is aligned to 64bits.
   */
};

/* NAT-Traversal type, see RFC 3948 (and drafts). */
/* sizeof(struct sadb_x_nat_t_type) == 8 */
struct sadb_x_nat_t_type {
  u_int16_t sadb_x_nat_t_type_len;
  u_int16_t sadb_x_nat_t_type_exttype;
  u_int8_t sadb_x_nat_t_type_type;
  u_int8_t sadb_x_nat_t_type_reserved[3];
};

/* NAT-Traversal source or destination port. */
/* sizeof(struct sadb_x_nat_t_port) == 8 */
struct sadb_x_nat_t_port {
  u_int16_t sadb_x_nat_t_port_len;
  u_int16_t sadb_x_nat_t_port_exttype;
  u_int16_t sadb_x_nat_t_port_port;
  u_int16_t sadb_x_nat_t_port_reserved;
};

/* ESP fragmentation size. */
/* sizeof(struct sadb_x_nat_t_frag) == 8 */
struct sadb_x_nat_t_frag {
  u_int16_t sadb_x_nat_t_frag_len;
  u_int16_t sadb_x_nat_t_frag_exttype;
  u_int16_t sadb_x_nat_t_frag_fraglen;
  u_int16_t sadb_x_nat_t_frag_reserved;
};

#define SADB_EXT_RESERVED             0
#define SADB_EXT_SA                   1
#define SADB_EXT_LIFETIME_CURRENT     2
#define SADB_EXT_LIFETIME_HARD        3
#define SADB_EXT_LIFETIME_SOFT        4
#define SADB_EXT_ADDRESS_SRC          5
#define SADB_EXT_ADDRESS_DST          6
#define SADB_EXT_ADDRESS_PROXY        7
#define SADB_EXT_KEY_AUTH             8
#define SADB_EXT_KEY_ENCRYPT          9
#define SADB_EXT_IDENTITY_SRC         10
#define SADB_EXT_IDENTITY_DST         11
#define SADB_EXT_SENSITIVITY          12
#define SADB_EXT_PROPOSAL             13
#define SADB_EXT_SUPPORTED_AUTH       14
#define SADB_EXT_SUPPORTED_ENCRYPT    15
#define SADB_EXT_SPIRANGE             16
#define SADB_X_EXT_KMPRIVATE          17
#define SADB_X_EXT_POLICY             18
#define SADB_X_EXT_SA2                19
#define SADB_X_EXT_NAT_T_TYPE         20
#define SADB_X_EXT_NAT_T_SPORT        21
#define SADB_X_EXT_NAT_T_DPORT        22
#define SADB_X_EXT_NAT_T_OA           23	/* Deprecated. */
#define SADB_X_EXT_NAT_T_OAI          23	/* Peer's NAT_OA for src of SA. */
#define SADB_X_EXT_NAT_T_OAR          24	/* Peer's NAT_OA for dst of SA. */
#define SADB_X_EXT_NAT_T_FRAG         25	/* Manual MTU override. */
#define SADB_EXT_MAX                  25

#define SADB_SATYPE_UNSPEC	0
#define SADB_SATYPE_AH		2
#define SADB_SATYPE_ESP		3
#define SADB_SATYPE_RSVP	5
#define SADB_SATYPE_OSPFV2	6
#define SADB_SATYPE_RIPV2	7
#define SADB_SATYPE_MIP		8
#define SADB_X_SATYPE_IPCOMP	9
/*#define SADB_X_SATYPE_POLICY	10	obsolete, do not reuse */
#define SADB_X_SATYPE_TCPSIGNATURE	11
#define SADB_SATYPE_MAX		12

#define SADB_SASTATE_LARVAL   0
#define SADB_SASTATE_MATURE   1
#define SADB_SASTATE_DYING    2
#define SADB_SASTATE_DEAD     3
#define SADB_SASTATE_MAX      3

#define SADB_SAFLAGS_PFS      1

/* RFC2367 numbers - meets RFC2407 */
#define SADB_AALG_NONE		0
#define SADB_AALG_MD5HMAC	2
#define SADB_AALG_SHA1HMAC	3
#define SADB_AALG_MAX		252
/* private allocations - based on RFC2407/IANA assignment */
#define SADB_X_AALG_SHA2_256	5
#define SADB_X_AALG_SHA2_384	6
#define SADB_X_AALG_SHA2_512	7
#define SADB_X_AALG_RIPEMD160HMAC	8
#define SADB_X_AALG_AES_XCBC_MAC	9	/* draft-ietf-ipsec-ciph-aes-xcbc-mac-04 */
/* private allocations should use 249-255 (RFC2407) */
#define SADB_X_AALG_MD5		249	/* Keyed MD5 */
#define SADB_X_AALG_SHA		250	/* Keyed SHA */
#define SADB_X_AALG_NULL	251	/* null authentication */
#define SADB_X_AALG_TCP_MD5	252	/* Keyed TCP-MD5 (RFC2385) */

/* RFC2367 numbers - meets RFC2407 */
#define SADB_EALG_NONE		0
#define SADB_EALG_DESCBC	2
#define SADB_EALG_3DESCBC	3
#define SADB_EALG_NULL		11
#define SADB_EALG_MAX		250
/* private allocations - based on RFC2407/IANA assignment */
#define SADB_X_EALG_CAST128CBC	6
#define SADB_X_EALG_BLOWFISHCBC	7
#define SADB_X_EALG_RIJNDAELCBC	12
#define SADB_X_EALG_AES		12
/* private allocations - based on RFC4312/IANA assignment */
#define SADB_X_EALG_CAMELLIACBC		22
/* private allocations should use 249-255 (RFC2407) */
#define SADB_X_EALG_SKIPJACK	249	/*250*/ /* for IPSEC */
#define SADB_X_EALG_AESCTR	250	/*249*/ /* draft-ietf-ipsec-ciph-aes-ctr-03 */

/* private allocations - based on RFC2407/IANA assignment */
#define SADB_X_CALG_NONE	0
#define SADB_X_CALG_OUI		1
#define SADB_X_CALG_DEFLATE	2
#define SADB_X_CALG_LZS		3
#define SADB_X_CALG_MAX		4

#define SADB_IDENTTYPE_RESERVED   0
#define SADB_IDENTTYPE_PREFIX     1
#define SADB_IDENTTYPE_FQDN       2
#define SADB_IDENTTYPE_USERFQDN   3
#define SADB_X_IDENTTYPE_ADDR     4
#define SADB_IDENTTYPE_MAX        4

/* `flags' in sadb_sa structure holds followings */
#define SADB_X_EXT_NONE		0x0000	/* i.e. new format. */
#define SADB_X_EXT_OLD		0x0001	/* old format. */

#define SADB_X_EXT_IV4B		0x0010	/* IV length of 4 bytes in use */
#define SADB_X_EXT_DERIV	0x0020	/* DES derived */
#define SADB_X_EXT_CYCSEQ	0x0040	/* allowing to cyclic sequence. */

	/* three of followings are exclusive flags each them */
#define SADB_X_EXT_PSEQ		0x0000	/* sequencial padding for ESP */
#define SADB_X_EXT_PRAND	0x0100	/* random padding for ESP */
#define SADB_X_EXT_PZERO	0x0200	/* zero padding for ESP */
#define SADB_X_EXT_PMASK	0x0300	/* mask for padding flag */

#if 1
#define SADB_X_EXT_RAWCPI	0x0080	/* use well known CPI (IPComp) */
#endif

#define SADB_KEY_FLAGS_MAX	0x0fff

/* SPI size for PF_KEYv2 */
#define PFKEY_SPI_SIZE	sizeof(u_int32_t)

/* Identifier for menber of lifetime structure */
#define SADB_X_LIFETIME_ALLOCATIONS	0
#define SADB_X_LIFETIME_BYTES		1
#define SADB_X_LIFETIME_ADDTIME		2
#define SADB_X_LIFETIME_USETIME		3

/* The rate for SOFT lifetime against HARD one. */
#define PFKEY_SOFT_LIFETIME_RATE	80

/* Utilities */
#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
#define	PFKEY_EXTLEN(msg) \
	PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len)
#define PFKEY_ADDR_PREFIX(ext) \
	(((struct sadb_address *)(ext))->sadb_address_prefixlen)
#define PFKEY_ADDR_PROTO(ext) \
	(((struct sadb_address *)(ext))->sadb_address_proto)
#define PFKEY_ADDR_SADDR(ext) \
	((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address)))

/* in 64bits */
#define	PFKEY_UNUNIT64(a)	((a) << 3)
#define	PFKEY_UNIT64(a)		((a) >> 3)

#endif /* __PFKEY_V2_H */

#endif /* _NET_PFKEYV2_H_ */