#ifdef HAVE_NETINET_IP6MH_H
#include_next <netinet/ip6mh.h>
#endif

#ifndef _NETINET_IP6MH_H
#define _NETINET_IP6MH_H 1

#include <inttypes.h>
#include <netinet/in.h>

struct ip6_mh {
	uint8_t		ip6mh_proto;	/* NO_NXTHDR by default */
	uint8_t		ip6mh_hdrlen;	/* Header Len in unit of 8 Octets
				   excluding the first 8 Octets */
	uint8_t		ip6mh_type;	/* Type of Mobility Header */
	uint8_t		ip6mh_reserved;	/* Reserved */
	uint16_t	ip6mh_cksum;	/* Mobility Header Checksum */
	/* Followed by type specific messages */
} __attribute__ ((packed));

struct ip6_mh_binding_request {
	struct ip6_mh	ip6mhbr_hdr;
	uint16_t	ip6mhbr_reserved;
	/* Followed by optional Mobility Options */
} __attribute__ ((packed));

struct ip6_mh_home_test_init {
	struct ip6_mh	ip6mhhti_hdr;
	uint16_t	ip6mhhti_reserved;
	uint32_t	ip6mhhti_cookie[2];	/* 64 bit Cookie by MN */
	/* Followed by optional Mobility Options */
} __attribute__ ((packed));

struct ip6_mh_careof_test_init {
	struct ip6_mh	ip6mhcti_hdr;
	uint16_t	ip6mhcti_reserved;
	uint32_t	ip6mhcti_cookie[2];	/* 64 bit Cookie by MN */
	/* Followed by optional Mobility Options */
} __attribute__ ((packed));

struct ip6_mh_home_test {
	struct ip6_mh	ip6mhht_hdr;
	uint16_t	ip6mhht_nonce_index;
	uint32_t	ip6mhht_cookie[2];	/* Cookie from HOTI msg */
	uint32_t	ip6mhht_keygen[2];	/* 64 Bit Key by CN */
	/* Followed by optional Mobility Options */
} __attribute__ ((packed));

struct ip6_mh_careof_test {
	struct ip6_mh	ip6mhct_hdr;
	uint16_t	ip6mhct_nonce_index;
	uint32_t	ip6mhct_cookie[2];	/* Cookie from COTI message */
	uint32_t	ip6mhct_keygen[2];	/* 64bit key by CN */
	/* Followed by optional Mobility Options */
} __attribute__ ((packed));

struct ip6_mh_binding_update {
	struct ip6_mh	ip6mhbu_hdr;
	uint16_t	ip6mhbu_seqno;		/* Sequence Number */
	uint16_t	ip6mhbu_flags;
	uint16_t	ip6mhbu_lifetime;	/* Time in unit of 4 sec */
	/* Followed by optional Mobility Options */
} __attribute__ ((packed));

/* ip6mhbu_flags */
#if BYTE_ORDER == BIG_ENDIAN
#define IP6_MH_BU_ACK		0x8000	/* Request a binding ack */
#define IP6_MH_BU_HOME		0x4000	/* Home Registration */
#define IP6_MH_BU_LLOCAL	0x2000	/* Link-local compatibility */
#define IP6_MH_BU_KEYM		0x1000	/* Key management mobility */
#define IP6_MH_BU_MAP		0x0800	/* HMIPv6 MAP Registration */
#define IP6_MH_BU_MR		0x0400	/* NEMO MR Registration */
#else				/* BYTE_ORDER == LITTLE_ENDIAN */
#define IP6_MH_BU_ACK		0x0080	/* Request a binding ack */
#define IP6_MH_BU_HOME		0x0040	/* Home Registration */
#define IP6_MH_BU_LLOCAL	0x0020	/* Link-local compatibility */
#define IP6_MH_BU_KEYM		0x0010	/* Key management mobility */
#define IP6_MH_BU_MAP		0x0008	/* HMIPv6 MAP Registration */
#define IP6_MH_BU_MR		0x0004	/* NEMO MR Registration */
#endif

struct ip6_mh_binding_ack {
	struct ip6_mh	ip6mhba_hdr;
	uint8_t 	ip6mhba_status;	/* Status code */
	uint8_t		ip6mhba_flags;
	uint16_t	ip6mhba_seqno;
	uint16_t	ip6mhba_lifetime;
	/* Followed by optional Mobility Options */
} __attribute__ ((packed));

/* ip6mhba_flags */
#define IP6_MH_BA_KEYM		0x80	/* Key management mobility */
#define IP6_MH_BA_MR		0x40	/* NEMO MR registration */

struct ip6_mh_binding_error {
	struct ip6_mh	ip6mhbe_hdr;
	uint8_t 	ip6mhbe_status;	/* Error Status */
	uint8_t		ip6mhbe_reserved;
	struct in6_addr	ip6mhbe_homeaddr;
	/* Followed by optional Mobility Options */
} __attribute__ ((packed));

/*
 * Mobility Option TLV data structure
 */
struct ip6_mh_opt {
	uint8_t		ip6mhopt_type;	/* Option Type */
	uint8_t		ip6mhopt_len;	/* Option Length */
	/* Followed by variable length Option Data in bytes */
} __attribute__ ((packed));

/*
 * Mobility Option Data Structures 
 */
struct ip6_mh_opt_refresh_advice {
	uint8_t		ip6mora_type;
	uint8_t		ip6mora_len;
	uint16_t	ip6mora_interval;	/* Refresh interval in 4 sec */
} __attribute__ ((packed));

struct ip6_mh_opt_altcoa {
	uint8_t		ip6moa_type;
	uint8_t		ip6moa_len;
	struct in6_addr	ip6moa_addr;		/* Alternate Care-of Address */
} __attribute__ ((packed));

struct ip6_mh_opt_nonce_index {
	uint8_t		ip6moni_type;
	uint8_t		ip6moni_len;
	uint16_t	ip6moni_home_nonce;
	uint16_t	ip6moni_coa_nonce;
} __attribute__ ((packed));

struct ip6_mh_opt_auth_data {
	uint8_t		ip6moad_type;
	uint8_t 	ip6moad_len;
	uint8_t 	ip6moad_data[12];	/* 96 bit Authenticator */
} __attribute__ ((packed));

struct ip6_mh_opt_mob_net_prefix {
	uint8_t 	ip6mnp_type;
	uint8_t 	ip6mnp_len;
	uint8_t 	ip6mnp_reserved;
	uint8_t 	ip6mnp_prefix_len;
	struct in6_addr ip6mnp_prefix;
} __attribute__ ((packed));

/*
 *     Mobility Header Message Types
 */
#define IP6_MH_TYPE_BRR		0	/* Binding Refresh Request */
#define IP6_MH_TYPE_HOTI	1	/* HOTI Message */
#define IP6_MH_TYPE_COTI	2	/* COTI Message */
#define IP6_MH_TYPE_HOT		3	/* HOT Message */
#define IP6_MH_TYPE_COT		4	/* COT Message */
#define IP6_MH_TYPE_BU		5	/* Binding Update */
#define IP6_MH_TYPE_BACK	6	/* Binding ACK */
#define IP6_MH_TYPE_BERROR	7	/* Binding Error */

/*
 *     Mobility Header Message Option Types
 */
#define IP6_MHOPT_PAD1		0x00	/* PAD1 */
#define IP6_MHOPT_PADN		0x01	/* PADN */
#define IP6_MHOPT_BREFRESH	0x02	/* Binding Refresh */
#define IP6_MHOPT_ALTCOA	0x03	/* Alternate COA */
#define IP6_MHOPT_NONCEID	0x04	/* Nonce Index */
#define IP6_MHOPT_BAUTH		0x05	/* Binding Auth Data */
#define IP6_MHOPT_MOB_NET_PRFX	0x06	/* Mobile Network Prefix */

/*
 *    Status values accompanied with Mobility Binding Acknowledgement
 */
#define IP6_MH_BAS_ACCEPTED		0	/* BU accepted */
#define IP6_MH_BAS_PRFX_DISCOV		1	/* Accepted, but prefix discovery
						   required */
#define IP6_MH_BAS_UNSPECIFIED		128	/* Reason unspecified */
#define IP6_MH_BAS_PROHIBIT		129	/* Administratively prohibited */
#define IP6_MH_BAS_INSUFFICIENT		130	/* Insufficient resources */
#define IP6_MH_BAS_HA_NOT_SUPPORTED	131	/* HA registration not supported */
#define IP6_MH_BAS_NOT_HOME_SUBNET	132	/* Not Home subnet */
#define IP6_MH_BAS_NOT_HA		133	/* Not HA for this mobile node */
#define IP6_MH_BAS_DAD_FAILED		134	/* DAD failed */
#define IP6_MH_BAS_SEQNO_BAD		135	/* Sequence number out of range */
#define IP6_MH_BAS_HOME_NI_EXPIRED	136	/* Expired Home nonce index */
#define IP6_MH_BAS_COA_NI_EXPIRED	137	/* Expired Care-of nonce index */
#define IP6_MH_BAS_NI_EXPIRED		138	/* Expired Nonce Indices */
#define IP6_MH_BAS_REG_NOT_ALLOWED	139	/* Registration type change 
						   disallowed */
#define IP6_MH_BAS_MR_OP_NOT_PERMITTED	140	/* MR Operation not permitted */
#define IP6_MH_BAS_INVAL_PRFX		141	/* Invalid Prefix */
#define IP6_MH_BAS_NOT_AUTH_FOR_PRFX	142	/* Not Authorized for Prefix */
#define IP6_MH_BAS_FWDING_FAILED	143	/* Forwarding Setup failed */
/*
 *    Status values for the Binding Error mobility messages
 */
#define IP6_MH_BES_UNKNOWN_HAO	1	/* Unknown binding for HOA */
#define IP6_MH_BES_UNKNOWN_MH	2	/* Unknown MH Type */

#endif	/* netinet/ip6mh.h */
