2016-03-15 10:31:19 +01:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013
|
|
|
|
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
|
|
|
|
*/
|
|
|
|
|
2016-06-29 13:47:03 +02:00
|
|
|
#ifndef SLIRP_IP6_H
|
|
|
|
#define SLIRP_IP6_H
|
2016-03-15 10:31:19 +01:00
|
|
|
|
|
|
|
#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 } }
|
|
|
|
|
2016-03-20 15:09:09 +01:00
|
|
|
#define ZERO_ADDR { .s6_addr = \
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00,\
|
|
|
|
0x00, 0x00, 0x00, 0x00,\
|
|
|
|
0x00, 0x00, 0x00, 0x00,\
|
|
|
|
0x00, 0x00, 0x00, 0x00 } }
|
|
|
|
|
2016-03-15 10:31:19 +01:00
|
|
|
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)
|
|
|
|
{
|
2017-06-22 14:41:45 +02:00
|
|
|
if (memcmp(&(a->s6_addr[DIV_ROUND_UP(prefix_len, 8)]),
|
|
|
|
&(b->s6_addr[DIV_ROUND_UP(prefix_len, 8)]),
|
|
|
|
16 - DIV_ROUND_UP(prefix_len, 8)) != 0) {
|
2016-03-15 10:31:19 +01:00
|
|
|
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)))
|
|
|
|
|
2016-03-15 10:31:22 +01:00
|
|
|
#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)))
|
2016-03-15 10:31:19 +01:00
|
|
|
|
|
|
|
#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))
|
|
|
|
|
2016-03-20 15:09:09 +01:00
|
|
|
#define in6_zero(a)\
|
|
|
|
(in6_equal(a, &(struct in6_addr)ZERO_ADDR))
|
|
|
|
|
2016-03-15 10:31:19 +01:00
|
|
|
/* 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(ð[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
|