--- /dev/null
+/*
+ * "Copyright (c) 2008 The Regents of the University of California.
+ * All rights reserved."
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ */
+#ifndef _IP_H_
+#define _IP_H_
+
+/*
+ * define message structures for internet communication
+ *
+ */
+
+#ifdef PC
+#include <linux/if_tun.h>
+#include <netinet/in.h>
+#endif
+
+#include "6lowpan.h"
+#include "blip-platform.h"
+
+enum {
+ /*
+ * The time, in binary milliseconds, after which we stop waiting for
+ * fragments and report a failed receive. We
+ */
+ FRAG_EXPIRE_TIME = 4096,
+};
+
+
+#ifndef PC
+// update to use netinet/in definition of an IPv6 address; this is a
+// lot more elegent.
+struct in6_addr
+ {
+ union
+ {
+ uint8_t u6_addr8[16];
+ uint16_t u6_addr16[8];
+ uint32_t u6_addr32[4];
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+ };
+
+struct sockaddr_in6 {
+ uint16_t sin6_port;
+ struct in6_addr sin6_addr;
+};
+#endif
+
+/*
+ * Definition for internet protocol version 6.
+ * RFC 2460
+ */
+struct ip6_hdr {
+ uint8_t vlfc[4];
+ uint16_t plen; /* payload length */
+ uint8_t nxt_hdr; /* next header */
+ uint8_t hlim; /* hop limit */
+ struct in6_addr ip6_src; /* source address */
+ struct in6_addr ip6_dst; /* destination address */
+} __attribute__((packed));
+
+#define IPV6_VERSION 0x6
+#define IPV6_VERSION_MASK 0xf0
+
+
+/*
+ * Extension Headers
+ */
+
+struct ip6_ext {
+ uint8_t nxt_hdr;
+ uint8_t len;
+ uint8_t data[0];
+};
+
+struct tlv_hdr {
+ uint8_t type;
+ uint8_t len;
+};
+/*
+ * IP protocol numbers
+ */
+enum {
+ IANA_ICMP = 58,
+ IANA_UDP = 17,
+ IANA_TCP = 6,
+
+ // IPV6 defined extention header types. All other next header
+ // values are supposed to be transport protocols, with TLVs used
+ IPV6_HOP = 0,
+ IPV6_DEST = 60,
+ IPV6_ROUTING = 43,
+ IPV6_FRAG = 44,
+ IPV6_AUTH = 51,
+ IPV6_SEC = 50,
+ IPV6_MOBILITY = 135,
+ IPV6_NONEXT = 59,
+};
+#define EXTENSION_HEADER(X) ((X) == IPV6_HOP || (X) == IPV6_ROUTING || (X) == IPV6_DEST)
+#define COMPRESSIBLE_TRANSPORT(X) ((X) == IANA_UDP)
+
+/*
+ * nonstandard source routing header fields
+ */
+enum {
+ IP6ROUTE_TYPE_SOURCE = 0,
+ IP6ROUTE_TYPE_INVAL = 1,
+ IP6ROUTE_FLAG_CONTROLLER = 0x8,
+ IP6ROUTE_FLAG_MASK = IP6ROUTE_FLAG_CONTROLLER,
+
+ IP_EXT_SOURCE_DISPATCH = 0x40,
+ IP_EXT_SOURCE_MASK = 0xc0,
+
+ // dispatch values
+ IP_EXT_SOURCE_CONTROLLER = 0x40,
+
+ // dispatch values for route installation if this flag is set, the
+ // source_header must be immediately followed by a
+ // source_install_opt struct.
+ IP_EXT_SOURCE_INSTALL = 0x10,
+ IP_EXT_SOURCE_INSTALL_MASK= 0x10,
+
+ // indicates weather the forward and reverse paths should be
+ // installed. Are these needed? the only case when we don't want
+ // to install the reverse path is when the destination is a
+ // multicast?
+ IP_EXT_SOURCE_INST_SRC = 0x20,
+ IP_EXT_SOURCE_INST_DST = 0x40,
+
+ // a topology TLV inside a destination option
+ TLV_TYPE_TOPOLOGY = 0x0a,
+ // a route install message, inside a hop-by-hop or destination
+ // option message.
+ TLV_TYPE_INSTALL = 0x0b,
+ TLV_TYPE_FLOW = 0x0c,
+ TLV_TYPE_MCASTSEQ = 0x0d,
+};
+
+struct ip6_route {
+ uint8_t nxt_hdr;
+ uint8_t len;
+ uint8_t type;
+ uint8_t segs_remain;
+ uint16_t hops[0];
+};
+#define ROUTE_NENTRIES(SH) (((SH)->len - (sizeof(struct ip6_route))) / (sizeof(uint16_t)))
+
+
+/*
+ * icmp
+ */
+struct icmp6_hdr {
+ uint8_t type; /* type field */
+ uint8_t code; /* code field */
+ uint16_t cksum; /* checksum field */
+};
+
+enum {
+ ICMP_TYPE_ECHO_DEST_UNREACH = 1,
+ ICMP_TYPE_ECHO_PKT_TOO_BIG = 2,
+ ICMP_TYPE_ECHO_TIME_EXCEEDED = 3,
+ ICMP_TYPE_ECHO_PARAM_PROBLEM = 4,
+ ICMP_TYPE_ECHO_REQUEST = 128,
+ ICMP_TYPE_ECHO_REPLY = 129,
+ ICMP_TYPE_ROUTER_SOL = 133,
+ ICMP_TYPE_ROUTER_ADV = 134,
+ ICMP_TYPE_NEIGHBOR_SOL = 135,
+ ICMP_TYPE_NEIGHBOR_ADV = 136,
+ ICMP_NEIGHBOR_HOPLIMIT = 255,
+
+ ICMP_CODE_HOPLIMIT_EXCEEDED = 0,
+ ICMP_CODE_ASSEMBLY_EXCEEDED = 1,
+};
+
+/*
+ * UDP protocol header.
+ */
+struct udp_hdr {
+ uint16_t srcport; /* source port */
+ uint16_t dstport; /* destination port */
+ uint16_t len; /* udp length */
+ uint16_t chksum; /* udp checksum */
+};
+
+/*
+ * TCP transport headers and flags
+ */
+enum {
+ TCP_FLAG_FIN = 0x1,
+ TCP_FLAG_SYN = 0x2,
+ TCP_FLAG_RST = 0x4,
+ TCP_FLAG_PSH = 0x8,
+ TCP_FLAG_ACK = 0x10,
+ TCP_FLAG_URG = 0x20,
+ TCP_FLAG_ECE = 0x40,
+ TCP_FLAG_CWR = 0x80,
+};
+
+struct tcp_hdr {
+ uint16_t srcport;
+ uint16_t dstport;
+ uint32_t seqno;
+ uint32_t ackno;
+ uint8_t offset;
+ uint8_t flags;
+ uint16_t window;
+ uint16_t chksum;
+ uint16_t urgent;
+};
+
+/*
+ * IP metadata and routing structures
+ */
+struct ip_metadata {
+ ieee154_saddr_t sender;
+ uint8_t lqi;
+ uint8_t padding[1];
+};
+
+struct flow_match {
+ cmpr_ip6_addr_t src;
+ cmpr_ip6_addr_t dest; // Need to make this more extensible at some point
+};
+
+struct rinstall_header {
+ struct flow_match match;
+ uint8_t flags;
+ uint8_t path_len;
+ cmpr_ip6_addr_t path[0];
+};
+
+enum {
+ // is this a hop-by-hop or source install command
+ HYDRO_INSTALL_METHOD_MASK = 0x03,
+ HYDRO_METHOD_HOP = 0x01,
+ HYDRO_METHOD_SOURCE = 0x02,
+
+ // should we also apply the action to the reverse path?
+ HYDRO_INSTALL_REVERSE = 0x04,
+
+ // is this an uninstallation?
+ HYDRO_INSTALL_UNINSTALL_MASK = 0x08,
+
+};
+
+enum {
+ T_INVAL_NEIGH = 0xef,
+ T_SET_NEIGH = 0xee,
+};
+
+
+/*
+ * These are data structures to hold IP messages. We used a linked
+ * list of headers so that we can easily add extra headers with no
+ * copy; similar to the linux iovec's or BSD mbuf structs.
+ * Every split_ip_msg contains a full IPv6 header (40 bytes), but it
+ * is placed at the end of the struct so that we can read() a message
+ * straight into one of these structs, and then just set up the header
+ * chain.
+ *
+ * Due to the way fragmentation is currently implemented, the total
+ * length of the data referenced from this chain must not be longer
+ * then what can fit into a single fragment. This is a limitation of
+ * the current fragmentation code, but is perfectly usable in most
+ * cases.
+ */
+struct generic_header {
+#ifdef PC
+ int payload_malloced:1;
+#endif
+ uint8_t len;
+ union {
+ // this could be an eumeration of all the valid headers we can have here.
+ struct ip6_ext *ext;
+ struct ip6_route *sh;
+ struct udp_hdr *udp;
+ uint8_t *data;
+ } hdr;
+ struct generic_header *next;
+};
+
+enum {
+ IP_NOHEADERS = 1 << 0,
+ IP_MCAST = 1 << 1,
+ IP_NOADDRESS = 1 << 2,
+};
+
+struct split_ip_msg {
+ struct generic_header *headers;
+ uint16_t data_len;
+ uint8_t *data;
+#ifdef PC
+ uint16_t foo;
+ uint16_t flow_id;
+ uint16_t prev_hop;
+ struct ip_metadata metadata;
+ // this must be last so we can read() straight into the end of the buffer.
+ struct tun_pi pi;
+#endif
+ struct ip6_hdr hdr;
+ uint8_t next[0];
+};
+
+#ifndef NO_LIB6LOWPAN_ASCII
+/*
+ * parse a string representation of an IPv6 address
+ */
+void inet_pton6(char *addr, struct in6_addr *dest);
+int inet_ntop6(struct in6_addr *addr, char *buf, int cnt);
+#endif
+
+#endif