12632SN/A/*
22632SN/A * ip6.h
32632SN/A *
42632SN/A * Internet Protocol, Version 6 (RFC 2460).
52632SN/A *
62632SN/A * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
72632SN/A *
82632SN/A * $Id: ip6.h,v 1.6 2004/02/23 10:01:15 dugsong Exp $
92632SN/A */
102632SN/A
112632SN/A#ifndef DNET_IP6_H
122632SN/A#define DNET_IP6_H
132632SN/A
142632SN/A#define IP6_ADDR_LEN	16
152632SN/A#define IP6_ADDR_BITS	128
162632SN/A
172632SN/A#define IP6_HDR_LEN	40		/* IPv6 header length */
182632SN/A#define IP6_LEN_MIN	IP6_HDR_LEN
192632SN/A#define IP6_LEN_MAX	65535		/* non-jumbo payload */
202632SN/A
212632SN/A#define IP6_MTU_MIN	1280		/* minimum MTU (1024 + 256) */
222632SN/A
232632SN/Atypedef struct ip6_addr {
242632SN/A        uint8_t         data[IP6_ADDR_LEN];
252632SN/A} ip6_addr_t;
262632SN/A
272632SN/A#ifndef __GNUC__
282632SN/A# define __attribute__(x)
292632SN/A# pragma pack(1)
302632SN/A#endif
312632SN/A
322632SN/A/*
332632SN/A * IPv6 header
342632SN/A */
352632SN/Astruct ip6_hdr {
362632SN/A        union {
372632SN/A                struct ip6_hdr_ctl {
382632SN/A                        uint32_t	ip6_un1_flow; /* 20 bits of flow ID */
392632SN/A                        uint16_t	ip6_un1_plen; /* payload length */
402632SN/A                        uint8_t		ip6_un1_nxt;  /* next header */
412632SN/A                        uint8_t		ip6_un1_hlim; /* hop limit */
422632SN/A                } ip6_un1;
432632SN/A                uint8_t	ip6_un2_vfc;	/* 4 bits version, top 4 bits class */
442632SN/A        } ip6_ctlun;
452632SN/A        ip6_addr_t	ip6_src;
462632SN/A        ip6_addr_t	ip6_dst;
472632SN/A} __attribute__((__packed__));
482632SN/A
492632SN/A#define ip6_vfc		ip6_ctlun.ip6_un2_vfc
502632SN/A#define ip6_flow	ip6_ctlun.ip6_un1.ip6_un1_flow
512632SN/A#define ip6_plen	ip6_ctlun.ip6_un1.ip6_un1_plen
522632SN/A#define ip6_nxt		ip6_ctlun.ip6_un1.ip6_un1_nxt	/* IP_PROTO_* */
532632SN/A#define ip6_hlim	ip6_ctlun.ip6_un1.ip6_un1_hlim
542632SN/A
552632SN/A#define IP6_VERSION		0x60
562632SN/A#define IP6_VERSION_MASK	0xf0		/* ip6_vfc version */
572632SN/A
582632SN/A#if DNET_BYTESEX == DNET_BIG_ENDIAN
592632SN/A#define IP6_FLOWINFO_MASK	0x0fffffff	/* ip6_flow info (28 bits) */
602632SN/A#define IP6_FLOWLABEL_MASK	0x000fffff	/* ip6_flow label (20 bits) */
612632SN/A#elif DNET_BYTESEX == DNET_LIL_ENDIAN
622632SN/A#define IP6_FLOWINFO_MASK	0xffffff0f	/* ip6_flow info (28 bits) */
632632SN/A#define IP6_FLOWLABEL_MASK	0xffff0f00	/* ip6_flow label (20 bits) */
642632SN/A#endif
652632SN/A
662632SN/A/*
672632SN/A * Hop limit (ip6_hlim)
682632SN/A */
692632SN/A#define IP6_HLIM_DEFAULT	64
702632SN/A#define IP6_HLIM_MAX		255
712632SN/A
722632SN/A/*
732632SN/A * Preferred extension header order from RFC 2460, 4.1:
742632SN/A *
752632SN/A * IP_PROTO_IPV6, IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS, IP_PROTO_ROUTING,
762632SN/A * IP_PROTO_FRAGMENT, IP_PROTO_AH, IP_PROTO_ESP, IP_PROTO_DSTOPTS, IP_PROTO_*
772632SN/A */
782632SN/A
792632SN/A/*
802632SN/A * Routing header data (IP_PROTO_ROUTING)
812632SN/A */
822632SN/Astruct ip6_ext_data_routing {
832632SN/A        uint8_t  type;			/* routing type */
842632SN/A        uint8_t  segleft;		/* segments left */
852632SN/A        /* followed by routing type specific data */
862632SN/A} __attribute__((__packed__));
872632SN/A
882632SN/Astruct ip6_ext_data_routing0 {
892632SN/A        uint8_t  type;			/* always zero */
902632SN/A        uint8_t  segleft;		/* segments left */
912632SN/A        uint8_t  reserved;		/* reserved field */
922632SN/A        uint8_t  slmap[3];		/* strict/loose bit map */
932632SN/A        ip6_addr_t  addr[1];		/* up to 23 addresses */
942632SN/A} __attribute__((__packed__));
952632SN/A
962632SN/A/*
972632SN/A * Fragment header data (IP_PROTO_FRAGMENT)
982632SN/A */
992632SN/Astruct ip6_ext_data_fragment {
1002632SN/A        uint16_t  offlg;		/* offset, reserved, and flag */
1012632SN/A        uint32_t  ident;		/* identification */
1022632SN/A} __attribute__((__packed__));
1032632SN/A
1042632SN/A/*
1052632SN/A * Fragmentation offset, reserved, and flags (offlg)
1062632SN/A */
1072632SN/A#if DNET_BYTESEX == DNET_BIG_ENDIAN
1082632SN/A#define IP6_OFF_MASK		0xfff8	/* mask out offset from offlg */
1092632SN/A#define IP6_RESERVED_MASK	0x0006	/* reserved bits in offlg */
1102632SN/A#define IP6_MORE_FRAG		0x0001	/* more-fragments flag */
1112632SN/A#elif DNET_BYTESEX == DNET_LIL_ENDIAN
1122632SN/A#define IP6_OFF_MASK		0xf8ff	/* mask out offset from offlg */
1132632SN/A#define IP6_RESERVED_MASK	0x0600	/* reserved bits in offlg */
1142632SN/A#define IP6_MORE_FRAG		0x0100	/* more-fragments flag */
1152632SN/A#endif
1162632SN/A
1172632SN/A/*
1182632SN/A * Option types, for IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS headers
1192632SN/A */
1202632SN/A#define IP6_OPT_PAD1		0x00	/* 00 0 00000 */
1212632SN/A#define IP6_OPT_PADN		0x01	/* 00 0 00001 */
1222632SN/A#define IP6_OPT_JUMBO		0xC2	/* 11 0 00010 = 194 */
1232632SN/A#define IP6_OPT_JUMBO_LEN	6
1242632SN/A#define IP6_OPT_RTALERT		0x05	/* 00 0 00101 */
1252632SN/A#define IP6_OPT_RTALERT_LEN	4
1262632SN/A#define IP6_OPT_RTALERT_MLD	0	/* Datagram contains an MLD message */
1272632SN/A#define IP6_OPT_RTALERT_RSVP	1	/* Datagram contains an RSVP message */
1282632SN/A#define IP6_OPT_RTALERT_ACTNET	2 	/* contains an Active Networks msg */
1292632SN/A#define IP6_OPT_LEN_MIN		2
1302632SN/A
1312632SN/A#define IP6_OPT_TYPE(o)		((o) & 0xC0)	/* high 2 bits of opt_type */
1322632SN/A#define IP6_OPT_TYPE_SKIP	0x00	/* continue processing on failure */
1332632SN/A#define IP6_OPT_TYPE_DISCARD	0x40	/* discard packet on failure */
1342632SN/A#define IP6_OPT_TYPE_FORCEICMP	0x80	/* discard and send ICMP on failure */
1352632SN/A#define IP6_OPT_TYPE_ICMP	0xC0	/* ...only if non-multicast dst */
1362632SN/A
1372632SN/A#define IP6_OPT_MUTABLE		0x20	/* option data may change en route */
1382632SN/A
1392632SN/A/*
1402632SN/A * Extension header (chained via {ip6,ext}_nxt, following IPv6 header)
1412632SN/A */
1422632SN/Astruct ip6_ext_hdr {
1432632SN/A        uint8_t  ext_nxt;	/* next header */
1442632SN/A        uint8_t  ext_len;	/* following length in units of 8 octets */
1452632SN/A        union {
1462632SN/A                struct ip6_ext_data_routing	routing;
1472632SN/A                struct ip6_ext_data_fragment	fragment;
1482632SN/A        } ext_data;
1492632SN/A} __attribute__((__packed__));
1502632SN/A
1512632SN/A#ifndef __GNUC__
1522632SN/A# pragma pack()
1532632SN/A#endif
1542632SN/A
1552632SN/A/*
1562632SN/A * Reserved addresses
1572632SN/A */
1582632SN/A#define IP6_ADDR_UNSPEC	\
1592632SN/A        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
1602632SN/A#define IP6_ADDR_LOOPBACK \
1612632SN/A        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
1622632SN/A
1632632SN/A#define ip6_pack_hdr(hdr, fc, fl, plen, nxt, hlim, src, dst) do {	\
1642632SN/A        struct ip6_hdr *ip6 = (struct ip6_hdr *)(hdr);			\
1652632SN/A        ip6->ip6_flow = htonl(((uint32_t)(fc) << 28) &			\
1662632SN/A            (IP6_FLOWLABEL_MASK | (fl)));				\
1672632SN/A        ip6->ip6_vfc = (IP6_VERSION | ((fc) >> 4));			\
1682632SN/A        ip6->ip6_plen = htons((plen));					\
1692632SN/A        ip6->ip6_nxt = (nxt); ip6->ip6_hlim = (hlim);			\
1702632SN/A        memmove(&ip6->ip6_src, &(src), IP6_ADDR_LEN);			\
1712632SN/A        memmove(&ip6->ip6_dst, &(dst), IP6_ADDR_LEN);			\
1722632SN/A} while (0);
1732632SN/A
1742632SN/A__BEGIN_DECLS
1752632SN/Achar	*ip6_ntop(const ip6_addr_t *ip6, char *dst, size_t size);
1762632SN/Aint	 ip6_pton(const char *src, ip6_addr_t *dst);
1772632SN/Achar	*ip6_ntoa(const ip6_addr_t *ip6);
1782632SN/A#define	 ip6_aton ip6_pton
1792632SN/A
1802632SN/Avoid	 ip6_checksum(void *buf, size_t len);
1812632SN/A__END_DECLS
1822632SN/A
1832632SN/A#endif /* DNET_IP6_H */
184