summaryrefslogtreecommitdiffstats
path: root/qemu/slirp/ip6.h
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/slirp/ip6.h')
-rw-r--r--qemu/slirp/ip6.h141
1 files changed, 141 insertions, 0 deletions
diff --git a/qemu/slirp/ip6.h b/qemu/slirp/ip6.h
new file mode 100644
index 000000000..8ddfa242c
--- /dev/null
+++ b/qemu/slirp/ip6.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
+ */
+
+#ifndef SLIRP_IP6_H_
+#define SLIRP_IP6_H_
+
+#include "net/eth.h"
+
+#define ALLNODES_MULTICAST { .s6_addr = \
+ { 0xff, 0x02, 0x00, 0x00,\
+ 0x00, 0x00, 0x00, 0x00,\
+ 0x00, 0x00, 0x00, 0x00,\
+ 0x00, 0x00, 0x00, 0x01 } }
+
+#define SOLICITED_NODE_PREFIX { .s6_addr = \
+ { 0xff, 0x02, 0x00, 0x00,\
+ 0x00, 0x00, 0x00, 0x00,\
+ 0x00, 0x00, 0x00, 0x01,\
+ 0xff, 0x00, 0x00, 0x00 } }
+
+#define LINKLOCAL_ADDR { .s6_addr = \
+ { 0xfe, 0x80, 0x00, 0x00,\
+ 0x00, 0x00, 0x00, 0x00,\
+ 0x00, 0x00, 0x00, 0x00,\
+ 0x00, 0x00, 0x00, 0x02 } }
+
+static inline bool in6_equal(const struct in6_addr *a, const struct in6_addr *b)
+{
+ return memcmp(a, b, sizeof(*a)) == 0;
+}
+
+static inline bool in6_equal_net(const struct in6_addr *a,
+ const struct in6_addr *b,
+ int prefix_len)
+{
+ if (memcmp(a, b, prefix_len / 8) != 0) {
+ return 0;
+ }
+
+ if (prefix_len % 8 == 0) {
+ return 1;
+ }
+
+ return a->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8))
+ == b->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8));
+}
+
+static inline bool in6_equal_mach(const struct in6_addr *a,
+ const struct in6_addr *b,
+ int prefix_len)
+{
+ if (memcmp(&(a->s6_addr[(prefix_len + 7) / 8]),
+ &(b->s6_addr[(prefix_len + 7) / 8]),
+ 16 - (prefix_len + 7) / 8) != 0) {
+ return 0;
+ }
+
+ if (prefix_len % 8 == 0) {
+ return 1;
+ }
+
+ return (a->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1))
+ == (b->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1));
+}
+
+
+#define in6_equal_router(a)\
+ ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len)\
+ && in6_equal_mach(a, &slirp->vhost_addr6, slirp->vprefix_len))\
+ || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
+ && in6_equal_mach(a, &slirp->vhost_addr6, 64)))
+
+#define in6_equal_dns(a)\
+ ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len)\
+ && in6_equal_mach(a, &slirp->vnameserver_addr6, slirp->vprefix_len))\
+ || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
+ && in6_equal_mach(a, &slirp->vnameserver_addr6, 64)))
+
+#define in6_equal_host(a)\
+ (in6_equal_router(a) || in6_equal_dns(a))
+
+#define in6_solicitednode_multicast(a)\
+ (in6_equal_net(a, &(struct in6_addr)SOLICITED_NODE_PREFIX, 104))
+
+/* Compute emulated host MAC address from its ipv6 address */
+static inline void in6_compute_ethaddr(struct in6_addr ip,
+ uint8_t eth[ETH_ALEN])
+{
+ eth[0] = 0x52;
+ eth[1] = 0x56;
+ memcpy(&eth[2], &ip.s6_addr[16 - (ETH_ALEN - 2)], ETH_ALEN - 2);
+}
+
+/*
+ * Definitions for internet protocol version 6.
+ * Per RFC 2460, December 1998.
+ */
+#define IP6VERSION 6
+#define IP6_HOP_LIMIT 255
+
+/*
+ * Structure of an internet header, naked of options.
+ */
+struct ip6 {
+#ifdef HOST_WORDS_BIGENDIAN
+ uint32_t
+ ip_v:4, /* version */
+ ip_tc_hi:4, /* traffic class */
+ ip_tc_lo:4,
+ ip_fl_hi:4, /* flow label */
+ ip_fl_lo:16;
+#else
+ uint32_t
+ ip_tc_hi:4,
+ ip_v:4,
+ ip_fl_hi:4,
+ ip_tc_lo:4,
+ ip_fl_lo:16;
+#endif
+ uint16_t ip_pl; /* payload length */
+ uint8_t ip_nh; /* next header */
+ uint8_t ip_hl; /* hop limit */
+ struct in6_addr ip_src, ip_dst; /* source and dest address */
+} QEMU_PACKED;
+
+/*
+ * IPv6 pseudo-header used by upper-layer protocols
+ */
+struct ip6_pseudohdr {
+ struct in6_addr ih_src; /* source internet address */
+ struct in6_addr ih_dst; /* destination internet address */
+ uint32_t ih_pl; /* upper-layer packet length */
+ uint16_t ih_zero_hi; /* zero */
+ uint8_t ih_zero_lo; /* zero */
+ uint8_t ih_nh; /* next header */
+} QEMU_PACKED;
+
+
+#endif