/*
 *	Copyright (c) 1995, 1996, Sun Microsystems, Inc.
 *
 * This software is provided by Sun ``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 Sun Microsystems be liable for any direct, indirect,
 * incidental, special, exemplary, or consequential damages.
 *
 * This software is not a product, and is provided for evaluation purposes
 * only.
 *
 * This software may not be resold without the express permission of
 * Sun Microsystems.
 *
 * Feedback on this tool may be sent to packet-shell-owner@sunroof.eng.sun.com.
 *
 * Sparker cheats here, making his own file with a bunch of ad hoc IPv6
 */

#pragma ident	"@(#)ipv6.h	1.20	99/05/28 SMI"

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

/*
 * If we're on an IPv6 system, we don't need to define some of
 * these constants and structures...
 */

#ifndef AF_INET6
#define	AF_INET6	26
#endif

#ifndef INET6_ADDRSTRLEN
#define	INET6_ADDRSTRLEN	46	/* max len of IPv6 addr in ascii */
					/* standard colon-hex notation. */
#endif

/*
 * On IPv6 capable Solaris, an s6_addr define interferes with our private
 * IPv6 address structure definition.  Suppress it.
 */
#ifdef	s6_addr
#undef	s6_addr
#endif

struct ip6_addr {
	ulong_t  s6_addr[4];	/*	 IPv6 address	*/
};

/*
 * On IPv6 capable Solaris, the following two macros are already defined
 * assuming the in6_addr structure, so we need to undefine them before
 * defining our own.
 */
#ifdef IN6_ARE_ADDR_EQUAL
#undef IN6_ARE_ADDR_EQUAL
#endif
#define	IN6_ARE_ADDR_EQUAL(addr1, addr2) \
	(((addr1)->s6_addr[3] == (addr2)->s6_addr[3]) && \
	((addr1)->s6_addr[2] == (addr2)->s6_addr[2]) && \
	((addr1)->s6_addr[1] == (addr2)->s6_addr[1]) && \
	((addr1)->s6_addr[0] == (addr2)->s6_addr[0]))

#ifdef IN6_IS_ADDR_MULTICAST
#undef IN6_IS_ADDR_MULTICAST
#endif
#ifdef _BIG_ENDIAN
#define	IN6_IS_ADDR_MULTICAST(addr) \
	(((addr)->s6_addr[0] & 0xff000000) == 0xff000000)
#else
#define	IN6_IS_ADDR_MULTICAST(addr) \
	(((addr)->s6_addr[0] & 0x000000ff) == 0x000000ff)
#endif

#ifndef OPTACTION_FLAGS
#define	OPTACTION_FLAGS			0xc0
#endif
#ifndef OPTACTION_SKIP
#define	OPTACTION_SKIP			0x00
#endif
#ifndef OPTACTION_DROP
#define	OPTACTION_DROP			0x40
#endif
#ifndef OPTACTION_PPROBWMCAST
#define	OPTACTION_PPROBWMCAST		0x80
#endif
#ifndef OPTACTION_PPROB
#define	OPTACTION_PPROB			0xc0
#endif
#ifndef IPV6OPT_PAD1
#define	IPV6OPT_PAD1			0
#endif
#ifndef IPV6OPT_PADN
#define	IPV6OPT_PADN			1
#endif
#ifndef IPV6OPT_JUMBO
#define	IPV6OPT_JUMBO			194
#endif

#ifndef OPTACTION_DATACHNG
#define	OPTACTION_DATACHNG		0x20	/* 3rd highest order bit on */
#endif
#ifndef MAXOP
#define	MAXOP				4	/* 4 options */
#endif

/*
 * protocol numbers for extension headers.
 * If the advanced API is fully implemented, then these must be
 * defined in <netinet/in.h>
 */
#ifndef IPPROTO_HOPOPTS
#define	IPPROTO_HOPOPTS			0
#endif
#ifndef IPPROTO_ROUTING
#define	IPPROTO_ROUTING			43
#endif
#ifndef IPPROTO_FRAGMENT
#define	IPPROTO_FRAGMENT		44
#endif
#ifndef IPPROTO_DSTOPTS
#define	IPPROTO_DSTOPTS			60
#endif




struct ip6 {
	int			ip6_vflow;
	ushort_t		ip6_len;
	unsigned char		ip6_nextheader;
	unsigned char		ip6_hoplimit;
	struct ip6_addr		ip6_src;
	struct ip6_addr		ip6_dst;
};

struct pseudo_ip6 {
	struct ip6_addr		pseudo_ip6_src;
	struct ip6_addr		pseudo_ip6_dst;
	uint_t			pseudo_ip6_len;
	ushort_t		pseudo_ip6_zero1;
	uchar_t			pseudo_ip6_zero2;
	uchar_t			pseudo_ip6_p;
};

#define	IP6_FLOW_MASK		0x0fffffff
#define	IP6_VERSION_MASK	0xf0000000

struct fragopt6 {
	unsigned char		fragopt6_nexthdr;
	unsigned char		fragopt6_reserved;
	ushort_t		fragopt6_offset_and_flags;
	ulong_t			fragopt6_ident;
};

/* fragopt6_offset_and_flags field related constants (in network byte order) */
#ifdef _BIG_ENDIAN
#define	FRAGOPT6_OFF_MASK	0xfff8  /* mask out offset from _offlg */
#define	FRAGOPT6_RESERVED_MASK	0x0006  /* reserved bits in ip6f_offlg */
#define	FRAGOPT6_MORE_FRAG	0x0001  /* more-fragments flag */
#else
#define	FRAGOPT6_OFF_MASK	0xf8ff  /* mask out offset from _offlg */
#define	FRAGOPT6_RESERVED_MASK	0x0600  /* reserved bits in ip6f_offlg */
#define	FRAGOPT6_MORE_FRAG	0x0100  /* more-fragments flag */
#endif


struct opt6tlv {
	unsigned char		opt6tlv_type;
	unsigned char		opt6tlv_dlen;
	unsigned char		opt6tlv_data[4];
};
struct opt6 {
	unsigned char		opt6_nexthdr;
	unsigned char		opt6_hdrextlen;
};


struct routeopt6 {
	unsigned char		routeopt6_nexthdr;
	unsigned char		routeopt6_hdrextlen;
	unsigned char		routeopt6_routingtype;
	unsigned char		routeopt6_segmentsleft;
	unsigned int
				routeopt6_reserved : 8,
				routeopt6_bitflag : 24;
};
