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