]>
Commit | Line | Data |
---|---|---|
0d6ff71a GS |
1 | /* |
2 | * Copyright (c) 2013 | |
3 | * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. | |
4 | */ | |
5 | ||
2a6a4076 MA |
6 | #ifndef SLIRP_IP6_H |
7 | #define SLIRP_IP6_H | |
0d6ff71a | 8 | |
e429f296 | 9 | #include <glib.h> |
a9d8b3ec | 10 | #include <string.h> |
0d6ff71a GS |
11 | |
12 | #define ALLNODES_MULTICAST { .s6_addr = \ | |
13 | { 0xff, 0x02, 0x00, 0x00,\ | |
14 | 0x00, 0x00, 0x00, 0x00,\ | |
15 | 0x00, 0x00, 0x00, 0x00,\ | |
16 | 0x00, 0x00, 0x00, 0x01 } } | |
17 | ||
18 | #define SOLICITED_NODE_PREFIX { .s6_addr = \ | |
19 | { 0xff, 0x02, 0x00, 0x00,\ | |
20 | 0x00, 0x00, 0x00, 0x00,\ | |
21 | 0x00, 0x00, 0x00, 0x01,\ | |
22 | 0xff, 0x00, 0x00, 0x00 } } | |
23 | ||
24 | #define LINKLOCAL_ADDR { .s6_addr = \ | |
25 | { 0xfe, 0x80, 0x00, 0x00,\ | |
26 | 0x00, 0x00, 0x00, 0x00,\ | |
27 | 0x00, 0x00, 0x00, 0x00,\ | |
28 | 0x00, 0x00, 0x00, 0x02 } } | |
29 | ||
1d17654e ST |
30 | #define ZERO_ADDR { .s6_addr = \ |
31 | { 0x00, 0x00, 0x00, 0x00,\ | |
32 | 0x00, 0x00, 0x00, 0x00,\ | |
33 | 0x00, 0x00, 0x00, 0x00,\ | |
34 | 0x00, 0x00, 0x00, 0x00 } } | |
35 | ||
0d6ff71a GS |
36 | static inline bool in6_equal(const struct in6_addr *a, const struct in6_addr *b) |
37 | { | |
38 | return memcmp(a, b, sizeof(*a)) == 0; | |
39 | } | |
40 | ||
41 | static inline bool in6_equal_net(const struct in6_addr *a, | |
42 | const struct in6_addr *b, | |
43 | int prefix_len) | |
44 | { | |
45 | if (memcmp(a, b, prefix_len / 8) != 0) { | |
46 | return 0; | |
47 | } | |
48 | ||
49 | if (prefix_len % 8 == 0) { | |
50 | return 1; | |
51 | } | |
52 | ||
53 | return a->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8)) | |
54 | == b->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8)); | |
55 | } | |
56 | ||
57 | static inline bool in6_equal_mach(const struct in6_addr *a, | |
58 | const struct in6_addr *b, | |
59 | int prefix_len) | |
60 | { | |
e88718fc MAL |
61 | if (memcmp(&(a->s6_addr[DIV_ROUND_UP(prefix_len, 8)]), |
62 | &(b->s6_addr[DIV_ROUND_UP(prefix_len, 8)]), | |
63 | 16 - DIV_ROUND_UP(prefix_len, 8)) != 0) { | |
0d6ff71a GS |
64 | return 0; |
65 | } | |
66 | ||
67 | if (prefix_len % 8 == 0) { | |
68 | return 1; | |
69 | } | |
70 | ||
71 | return (a->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1)) | |
72 | == (b->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1)); | |
73 | } | |
74 | ||
75 | ||
76 | #define in6_equal_router(a)\ | |
77 | ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len)\ | |
78 | && in6_equal_mach(a, &slirp->vhost_addr6, slirp->vprefix_len))\ | |
79 | || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\ | |
80 | && in6_equal_mach(a, &slirp->vhost_addr6, 64))) | |
81 | ||
05061d85 GS |
82 | #define in6_equal_dns(a)\ |
83 | ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len)\ | |
84 | && in6_equal_mach(a, &slirp->vnameserver_addr6, slirp->vprefix_len))\ | |
85 | || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\ | |
86 | && in6_equal_mach(a, &slirp->vnameserver_addr6, 64))) | |
0d6ff71a GS |
87 | |
88 | #define in6_equal_host(a)\ | |
89 | (in6_equal_router(a) || in6_equal_dns(a)) | |
90 | ||
91 | #define in6_solicitednode_multicast(a)\ | |
92 | (in6_equal_net(a, &(struct in6_addr)SOLICITED_NODE_PREFIX, 104)) | |
93 | ||
1d17654e ST |
94 | #define in6_zero(a)\ |
95 | (in6_equal(a, &(struct in6_addr)ZERO_ADDR)) | |
96 | ||
0d6ff71a GS |
97 | /* Compute emulated host MAC address from its ipv6 address */ |
98 | static inline void in6_compute_ethaddr(struct in6_addr ip, | |
99 | uint8_t eth[ETH_ALEN]) | |
100 | { | |
101 | eth[0] = 0x52; | |
102 | eth[1] = 0x56; | |
103 | memcpy(ð[2], &ip.s6_addr[16 - (ETH_ALEN - 2)], ETH_ALEN - 2); | |
104 | } | |
105 | ||
106 | /* | |
107 | * Definitions for internet protocol version 6. | |
108 | * Per RFC 2460, December 1998. | |
109 | */ | |
110 | #define IP6VERSION 6 | |
111 | #define IP6_HOP_LIMIT 255 | |
112 | ||
113 | /* | |
114 | * Structure of an internet header, naked of options. | |
115 | */ | |
116 | struct ip6 { | |
e429f296 | 117 | #if G_BYTE_ORDER == G_BIG_ENDIAN |
0d6ff71a GS |
118 | uint32_t |
119 | ip_v:4, /* version */ | |
120 | ip_tc_hi:4, /* traffic class */ | |
121 | ip_tc_lo:4, | |
122 | ip_fl_hi:4, /* flow label */ | |
123 | ip_fl_lo:16; | |
124 | #else | |
125 | uint32_t | |
126 | ip_tc_hi:4, | |
127 | ip_v:4, | |
128 | ip_fl_hi:4, | |
129 | ip_tc_lo:4, | |
130 | ip_fl_lo:16; | |
131 | #endif | |
132 | uint16_t ip_pl; /* payload length */ | |
133 | uint8_t ip_nh; /* next header */ | |
134 | uint8_t ip_hl; /* hop limit */ | |
135 | struct in6_addr ip_src, ip_dst; /* source and dest address */ | |
c74e3ae9 | 136 | }; |
0d6ff71a GS |
137 | |
138 | /* | |
139 | * IPv6 pseudo-header used by upper-layer protocols | |
140 | */ | |
141 | struct ip6_pseudohdr { | |
142 | struct in6_addr ih_src; /* source internet address */ | |
143 | struct in6_addr ih_dst; /* destination internet address */ | |
144 | uint32_t ih_pl; /* upper-layer packet length */ | |
145 | uint16_t ih_zero_hi; /* zero */ | |
146 | uint8_t ih_zero_lo; /* zero */ | |
147 | uint8_t ih_nh; /* next header */ | |
c74e3ae9 | 148 | }; |
0d6ff71a | 149 | |
c74e3ae9 PM |
150 | /* |
151 | * We don't want to mark these ip6 structs as packed as they are naturally | |
152 | * correctly aligned; instead assert that there is no stray padding. | |
153 | * If we marked the struct as packed then we would be unable to take | |
154 | * the address of any of the fields in it. | |
155 | */ | |
85a0e43c ST |
156 | G_STATIC_ASSERT(sizeof(struct ip6) == 40); |
157 | G_STATIC_ASSERT(sizeof(struct ip6_pseudohdr) == 40); | |
0d6ff71a GS |
158 | |
159 | #endif |