/*
 * from inet.h,v 1.31.2.5 1995/01/13 19:18:51 jch Exp
 */

/*
 * ------------------------------------------------------------------------
 * 
 * Copyright (c) 1996, 1997 The Regents of the University of Michigan
 * All Rights Reserved
 *  
 * Royalty-free licenses to redistribute GateD Release
 * 3 in whole or in part may be obtained by writing to:
 * 
 * 	Merit GateDaemon Project
 * 	4251 Plymouth Road, Suite C
 * 	Ann Arbor, MI 48105
 *  
 * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE
 * UNIVERSITY OF MICHIGAN AND MERIT DO NOT WARRANT THAT THE
 * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR
 * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. The Regents of the
 * University of Michigan and Merit shall not be liable for
 * any special, indirect, incidental or consequential damages with respect
 * to any claim by Licensee or any third party arising from use of the
 * software. GateDaemon was originated and developed through release 3.0
 * by Cornell University and its collaborators.
 * 
 * Please forward bug fixes, enhancements and questions to the
 * gated mailing list: gated-people@gated.merit.edu.
 * 
 * ------------------------------------------------------------------------
 * 
 * Copyright (c) 1990,1991,1992,1993,1994,1995 by Cornell University.
 *     All rights reserved.
 * 
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 * 
 * GateD is based on Kirton's EGP, UC Berkeley's routing
 * daemon	 (routed), and DCN's HELLO routing Protocol.
 * Development of GateD has been supported in part by the
 * National Science Foundation.
 * 
 * ------------------------------------------------------------------------
 * 
 * Portions of this software may fall under the following
 * copyrights:
 * 
 * Copyright (c) 1988 Regents of the University of California.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms are
 * permitted provided that the above copyright notice and
 * this paragraph are duplicated in all such forms and that
 * any documentation, advertising materials, and other
 * materials related to such distribution and use
 * acknowledge that the software was developed by the
 * University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote
 * products derived from this software without specific
 * prior written permission.  THIS SOFTWARE IS PROVIDED
 * ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */


/* REALLY ugly Solaris hack */
#ifdef	SUNOS5_0
#include	<netinet/in.h>
/* Unaligned IPv6 header */
typedef struct ipv6h_s {
	u_char  ipv6h_vers_and_flow[4]; /* vers # in hi 4 bits, rest flow */
	u_char  ipv6h_length[2];
	u_char  ipv6h_nexthdr;
	u_char  ipv6h_hoplimit;
	u_char  ipv6h_src[16];
	u_char  ipv6h_dst[16];
} ipv6h_t;
#endif	/* SUNOS5_0 */

/* kernel depended macros */
#define LESS_ADDR6(a, b) \
	(((a).s6_addr[8] < (b).s6_addr[8]) || \
	 (((a).s6_addr[8] == (b).s6_addr[8]) && \
	  (((a).s6_addr[9] < (b).s6_addr[9]) || \
	   (((a).s6_addr[9] == (b).s6_addr[9]) && \
	    (((a).s6_addr[10] < (b).s6_addr[10]) || \
	     (((a).s6_addr[10] == (b).s6_addr[10]) && \
	      (((a).s6_addr[11] < (b).s6_addr[11]) || \
	       (((a).s6_addr[11] == (b).s6_addr[11]) && \
	        (((a).s6_addr[12] < (b).s6_addr[12]) || \
	         (((a).s6_addr[12] == (b).s6_addr[12]) && \
	          (((a).s6_addr[13] < (b).s6_addr[13]) || \
	           (((a).s6_addr[13] == (b).s6_addr[13]) && \
	            (((a).s6_addr[14] < (b).s6_addr[14]) || \
	             (((a).s6_addr[14] == (b).s6_addr[14]) && \
	              ((a).s6_addr[15] < (b).s6_addr[15])))))))))))))))

#ifdef INRIA
#endif /* INRIA */
#ifdef SHIN
#define s6_addr s6_addr8
#define ipv6_mreq ip6_mreq
#define ipv6mr_multiaddr imr6_multiaddr
#define ipv6mr_interface imr6_interface
#define IS_ANYADDR6(a) (((a).s6_addr32[0] == 0) \
			&& ((a).s6_addr32[1] == 0) \
			&& ((a).s6_addr32[2] == 0) \
			&& ((a).s6_addr32[3] == 0))
#define SAME_ADDR6(a, b) (((a).s6_addr32[0] == (b).s6_addr32[0]) \
			  && ((a).s6_addr32[1] == (b).s6_addr32[1]) \
			  && ((a).s6_addr32[2] == (b).s6_addr32[2]) \
			  && ((a).s6_addr32[3] == (b).s6_addr32[3]))
#endif /* SHIN */
#ifdef HYDRANGEA
#define ipv6mr_multiaddr	im6r_multiaddr
#define	ipv6mr_interface	im6r_interface
#define IS_ANYADDR6(a) (((a).s6_addr32[0] == 0) \
			&& ((a).s6_addr32[1] == 0) \
			&& ((a).s6_addr32[2] == 0) \
			&& ((a).s6_addr32[3] == 0))
#define SAME_ADDR6(a, b) (((a).s6_addr32[0] == (b).s6_addr32[0]) \
			  && ((a).s6_addr32[1] == (b).s6_addr32[1]) \
			  && ((a).s6_addr32[2] == (b).s6_addr32[2]) \
			  && ((a).s6_addr32[3] == (b).s6_addr32[3]))
#endif /* HYDRANGEA */

#ifdef	SUNOS5_0
#define IS_ANYADDR6(a) (((a).s6_addr[0] == 0) \
			&& ((a).s6_addr[1] == 0) \
			&& ((a).s6_addr[2] == 0) \
			&& ((a).s6_addr[3] == 0))
#define SAME_ADDR6(a, b) (((a).s6_addr[0] == (b).s6_addr[0]) \
			  && ((a).s6_addr[1] == (b).s6_addr[1]) \
			  && ((a).s6_addr[2] == (b).s6_addr[2]) \
			  && ((a).s6_addr[3] == (b).s6_addr[3]))
#endif	/* SUNOS5_0 */

/* macros to select IPv6 address given pointer to a struct sockaddr */

/* clear and init a sockaddr_un for Inet use */
#define	sock2in6(x)	((x)->in6.gin6_addr)
#define	sock2port6(x)	((x)->in6.gin6_port)
#define	sock2flow6(x)	((x)->in6.gin6_flowinfo)
#define	sockclear_in6(x)	\
			bzero((void_t)(x), sizeof ((x)->in6)); \
			socktype(x) = AF_INET6; \
    			socksize(x) = sizeof ((x)->in6);
#define	sockaddrcmp_in6(a, b)	(SAME_ADDR6(sock2in6(a), sock2in6(b)))
#define	sockaddrless_in6(a, b)	(LESS_ADDR6(sock2in6(a), sock2in6(b)))
#define	sockcmp_in6(a, b)	(sock2port6(a) == sock2port6(b) && sockaddrcmp_in6(a, b))

#define	sockaddrmask_in6(addr, mask)	\
		((int *)&sock2in6(addr))[0] &= ((int *)&sock2in6(mask))[0]; \
		((int *)&sock2in6(addr))[1] &= ((int *)&sock2in6(mask))[1]; \
		((int *)&sock2in6(addr))[2] &= ((int *)&sock2in6(mask))[2]; \
		((int *)&sock2in6(addr))[3] &= ((int *)&sock2in6(mask))[3];

#define	sockmask_in6(addr, mask)	\
				sock2port6(addr) &= sock2port6(mask); \
				sockaddrmask_in6(addr, mask)

#define	inet6_addrcmp_mask(a, b, m)	\
		((!((((int *)&a)[0] ^ ((int *)&b)[0]) & ((int *)&m)[0])) && \
		 (!((((int *)&a)[1] ^ ((int *)&b)[1]) & ((int *)&m)[1])) && \
		 (!((((int *)&a)[2] ^ ((int *)&b)[2]) & ((int *)&m)[2])) && \
		 (!((((int *)&a)[3] ^ ((int *)&b)[3]) & ((int *)&m)[3])))

#define	SOCKADDR_IN6_LEN	sizeof (inet6_addr_default->in6)

/* additional definitions to netinet/in.h */

#ifndef IPPROTO_OSPF
#define IPPROTO_OSPF 89
#endif	/* IPPROTO_OSPF */

extern int inet6_ipforwarding;		/* IPv6 forwarding engine enabled */

extern const bits inet6_proto_bits[];	/* Protocol types */

/* Common addresses */
extern sockaddr_un *inet6_addr_default;
extern sockaddr_un *inet6_addr_loopback;
extern sockaddr_un *inet6_addr_any;
extern sockaddr_un *inet6_addr_reject;
extern sockaddr_un *inet6_addr_blackhole;
extern sockaddr_un *inet6_addr_allnodes;
extern sockaddr_un *inet6_addr_allrouters;

#define	inet6_mask_default	inet6_masks[INET6_MASK_DEFAULT]
#define	inet6_mask_host		inet6_masks[INET6_MASK_HOST]

extern	sockaddr_un *inet6_masks[];		/* Table of all possible *contiguous* masks */
extern	byte inet6_mask_list[SOCKADDR_IN6_LEN * (sizeof (struct in6_addr) * NBBY + 1)];	/* The actual masks */

#define	INET6_LIMIT_MASKLEN	0, 128

#define	INET6_LIMIT_TTL		1, 255

#define INET6_SCOPE_NONE	0
#define INET6_SCOPE_V4COMPAT	1
#define INET6_SCOPE_GLOBAL	2
#define INET6_SCOPE_LINKLOCAL	3
#define INET6_SCOPE_SITELOCAL	4
#define INET6_SCOPE_MULTICAST	5

/* Masks */
#define	INET6_MASK_DEFAULT	0		/* 0:0:0:0:0:0:0:0 */
#define	INET6_MASK_HOST		128		/* ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff */
#define	INET6_NODE_NOMASK	0
#define	INET6_MASK_INVALID	129		/* Oops! */

/* Locate an inet mask given it's prefix length */
#define        inet6_mask_prefix(pfx)   ((pfx < 0 || pfx > 128) ? (sockaddr_un *) 0 : inet6_masks[pfx])

/* Calculate the prefix length given a mask */
#define        inet6_prefix_mask(mask) \
	(((byte *) (mask) >= inet6_mask_list && (byte *) (mask) < inet6_mask_list + sizeof inet6_mask_list) \
	? (((byte *) (mask) - inet6_mask_list) / SOCKADDR_IN6_LEN) \
	: (u_int) -1)

extern struct in6_addr inaddr6_hostmask;
extern struct in6_addr inaddr6_empty;

#ifdef	IPV6_MULTICAST
extern task *inet6_task;
#endif	/* IPV6_MULTICAST */

PROTOTYPE(inet6_mask_locate,
	  extern sockaddr_un *,
	  (sockaddr_un *));
PROTOTYPE(inet6_ifwithnet,
	  extern if_addr *,
	  (sockaddr_un *));
PROTOTYPE(inet6_family_init,
	  extern void,
	  (void));
PROTOTYPE(inet6_var_init,
	  extern void,
	  (void));
PROTOTYPE(inet6_init,
	  extern void,
	  (void));
PROTOTYPE(inet6_allrouters_join,
	  extern void,
	  (if_addr *));
PROTOTYPE(inet6_allrouters_drop,
	  extern void,
	  (if_addr *));
#ifdef V6L1
PROTOTYPE(inet6_scope_of,
	  extern byte,
	  (sockaddr_un *));
#endif
