1 /* vim: set expandtab ts=4 sw=4: */
2 /*
3  * You may redistribute this program and/or modify it under the terms of
4  * the GNU General Public License as published by the Free Software Foundation,
5  * either version 3 of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
14  */
15 #include "util/events/libuv/UvWrapper.h"
16 #include "benc/String.h"
17 #include "memory/Allocator.h"
18 #include "util/platform/Sockaddr.h"
19 #include "util/CString.h"
20 #include "util/Bits.h"
21 #include "util/Hex.h"
22 #include "util/Hash.h"
23 #include "util/Base10.h"
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stddef.h>
28 #include <stdint.h>
29 
30 struct Sockaddr_pvt
31 {
32     struct Sockaddr pub;
33     struct sockaddr_storage ss;
34 };
35 
36 struct Sockaddr_in_pvt
37 {
38     struct Sockaddr pub;
39     struct sockaddr_in si;
40 };
41 struct Sockaddr_in6_pvt
42 {
43     struct Sockaddr pub;
44     struct sockaddr_in6 si;
45 };
46 
47 const struct Sockaddr* const Sockaddr_LOOPBACK_be =
48     (const struct Sockaddr*) &((const struct Sockaddr_in_pvt) {
49         .pub = { .addrLen = sizeof(struct Sockaddr_in_pvt) },
50         .si = {
51             .sin_family = AF_INET,
52             .sin_addr = { .s_addr = 0x7f000001 }
53         }
54     });
55 const struct Sockaddr* const Sockaddr_LOOPBACK_le =
56     (const struct Sockaddr*) &((const struct Sockaddr_in_pvt) {
57         .pub = { .addrLen = sizeof(struct Sockaddr_in_pvt) },
58         .si = {
59             .sin_family = AF_INET,
60             .sin_addr = { .s_addr = 0x0100007f }
61         }
62     });
63 const struct Sockaddr* const Sockaddr_LOOPBACK6 =
64     (const struct Sockaddr*) &((const struct Sockaddr_in6_pvt) {
65         .pub = { .addrLen = sizeof(struct Sockaddr_in6_pvt) },
66         .si = {
67             .sin6_family = AF_INET6,
68             .sin6_addr = { .s6_addr = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}
69         }
70     });
71 
Sockaddr_fromNative(const void * ss,int addrLen,struct Allocator * alloc)72 struct Sockaddr* Sockaddr_fromNative(const void* ss, int addrLen, struct Allocator* alloc)
73 {
74     struct Sockaddr_pvt* out = Allocator_calloc(alloc, addrLen + Sockaddr_OVERHEAD, 1);
75     Bits_memcpy(&out->ss, ss, addrLen);
76     out->pub.addrLen = addrLen + Sockaddr_OVERHEAD;
77     Sockaddr_normalizeNative(&out->ss);
78     return &out->pub;
79 }
80 
Sockaddr_getPrefix(struct Sockaddr * addr)81 int Sockaddr_getPrefix(struct Sockaddr* addr)
82 {
83     if (addr->flags & Sockaddr_flags_PREFIX) {
84         return addr->prefix;
85     }
86     int af = Sockaddr_getFamily(addr);
87     if (af == Sockaddr_AF_INET) {
88         return 32;
89     } else if (af == Sockaddr_AF_INET6) {
90         return 128;
91     } else {
92         return -1;
93     }
94 }
95 
Sockaddr_parse(const char * input,struct Sockaddr_storage * out)96 int Sockaddr_parse(const char* input, struct Sockaddr_storage* out)
97 {
98     struct Sockaddr_storage unusedOut;
99     if (!out) {
100         out = &unusedOut;
101     }
102     uint8_t buff[64] = {0};
103     if (CString_strlen(input) > 63) {
104         return -1;
105     }
106     CString_safeStrncpy(buff, input, 63);
107 
108     int64_t port = 0;
109     char* lastColon = CString_strrchr(buff, ':');
110     char* firstColon = CString_strchr(buff, ':');
111     char* bracket = CString_strchr(buff, ']');
112     if (!lastColon) {
113         // ipv4, no port
114     } else if (lastColon != firstColon && (!bracket || lastColon < bracket)) {
115         // ipv6, no port
116     } else {
117         if (bracket && lastColon != &bracket[1]) { return -1; }
118         if (Base10_fromString(&lastColon[1], &port)) { return -1; }
119         if (port > 65535) { return -1; }
120         *lastColon = '\0';
121     }
122     if (bracket) {
123         *bracket = '\0';
124         if (buff[0] != '[') { return -1; }
125     } else if (buff[0] == '[') { return -1; }
126 
127     int64_t prefix = -1;
128     char* slash = CString_strchr(buff, '/');
129     if (slash) {
130         *slash = '\0';
131         if (!slash[1]) { return -1; }
132         if (Base10_fromString(&slash[1], &prefix)) { return -1; }
133     }
134 
135     Bits_memset(out, 0, sizeof(struct Sockaddr_storage));
136     if (lastColon != firstColon) {
137         // ipv6
138         struct sockaddr_in6* in6 = (struct sockaddr_in6*) Sockaddr_asNative(&out->addr);
139         if (uv_inet_pton(AF_INET6, (char*) ((buff[0] == '[') ? &buff[1] : buff), &in6->sin6_addr)) {
140             return -1;
141         }
142         out->addr.addrLen = sizeof(struct sockaddr_in6) + Sockaddr_OVERHEAD;
143         in6->sin6_port = Endian_hostToBigEndian16(port);
144         in6->sin6_family = AF_INET6;
145     } else {
146         struct sockaddr_in* in = ((struct sockaddr_in*) Sockaddr_asNative(&out->addr));
147         if (uv_inet_pton(AF_INET, (char*) buff, &in->sin_addr)) {
148             return -1;
149         }
150         out->addr.addrLen = sizeof(struct sockaddr_in) + Sockaddr_OVERHEAD;
151         in->sin_port = Endian_hostToBigEndian16(port);
152         in->sin_family = AF_INET;
153     }
154     if (prefix != -1) {
155         if (prefix < 0 || prefix > 128) { return -1; }
156         if (Sockaddr_getFamily(&out->addr) == Sockaddr_AF_INET && prefix > 32) { return -1; }
157         out->addr.prefix = prefix;
158         out->addr.flags |= Sockaddr_flags_PREFIX;
159     }
160     return 0;
161 }
162 
Sockaddr_clone(const struct Sockaddr * addr,struct Allocator * alloc)163 struct Sockaddr* Sockaddr_clone(const struct Sockaddr* addr, struct Allocator* alloc)
164 {
165     struct Sockaddr* out = Allocator_malloc(alloc, addr->addrLen);
166     Bits_memcpy(out, addr, addr->addrLen);
167     return out;
168 }
169 
Sockaddr_print(struct Sockaddr * sockaddr,struct Allocator * alloc)170 char* Sockaddr_print(struct Sockaddr* sockaddr, struct Allocator* alloc)
171 {
172     if (sockaddr->addrLen < (2 + Sockaddr_OVERHEAD)
173         || sockaddr->addrLen > Sockaddr_MAXSIZE + Sockaddr_OVERHEAD) {
174         return "invalid";
175     }
176 
177     struct Sockaddr_pvt* addr = (struct Sockaddr_pvt*) sockaddr;
178 
179     void* inAddr;
180     uint16_t port;
181     switch (addr->ss.ss_family) {
182         case AF_INET:
183             inAddr = &((struct sockaddr_in*) &addr->ss)->sin_addr;
184             port = Endian_bigEndianToHost16(((struct sockaddr_in*)&addr->ss)->sin_port);
185             break;
186         case AF_INET6:
187             inAddr = &((struct sockaddr_in6*) &addr->ss)->sin6_addr;
188             port = Endian_bigEndianToHost16(((struct sockaddr_in6*)&addr->ss)->sin6_port);
189             break;
190         default: {
191             uint8_t buff[Sockaddr_MAXSIZE * 2 + 1] = {0};
192             Hex_encode(buff, sizeof(buff), (uint8_t*)&addr->ss,
193                 sockaddr->addrLen - Sockaddr_OVERHEAD);
194             String* out = String_printf(alloc, "unknown (%s)", buff);
195             return out->bytes;
196         }
197     };
198 
199     #define BUFF_SZ 64
200     char printedAddr[BUFF_SZ] = {0};
201     int ret = uv_inet_ntop(addr->ss.ss_family, inAddr, printedAddr, BUFF_SZ - 1);
202     if (ret != 0) {
203         return "invalid";
204     }
205 
206     char printedPrefix[16] = {0};
207     if (addr->pub.flags & Sockaddr_flags_PREFIX) {
208         snprintf(printedPrefix, 15, "/%u", addr->pub.prefix);
209     }
210 
211     char printedPort[16] = {0};
212     if (port) {
213         snprintf(printedPort, 15, ":%u", port);
214     }
215 
216     char finalAddr[128] = {0};
217     const char* format = (port && addr->ss.ss_family == AF_INET6) ? "[%s%s]%s" : "%s%s%s";
218     snprintf(finalAddr, 127, format, printedAddr, printedPrefix, printedPort);
219 
220     int totalLength = CString_strlen(finalAddr) + 1;
221     char* out = Allocator_calloc(alloc, totalLength, 1);
222     Bits_memcpy(out, finalAddr, totalLength);
223     return out;
224 }
225 
getPortPtr(struct Sockaddr * sockaddr)226 static uint16_t* getPortPtr(struct Sockaddr* sockaddr)
227 {
228     if (sockaddr->addrLen < (2 + Sockaddr_OVERHEAD)) {
229         return NULL;
230     }
231     struct Sockaddr_pvt* sa = (struct Sockaddr_pvt*) sockaddr;
232     switch (sa->ss.ss_family) {
233         case AF_INET: return &((struct sockaddr_in*)&sa->ss)->sin_port;
234         case AF_INET6: return &((struct sockaddr_in6*)&sa->ss)->sin6_port;
235     }
236     return NULL;
237 }
238 
Sockaddr_getPort(struct Sockaddr * sockaddr)239 int Sockaddr_getPort(struct Sockaddr* sockaddr)
240 {
241     uint16_t* pp = getPortPtr(sockaddr);
242     return (pp) ? Endian_bigEndianToHost16(*pp) : -1;
243 }
244 
Sockaddr_setPort(struct Sockaddr * sockaddr,uint16_t port)245 int Sockaddr_setPort(struct Sockaddr* sockaddr, uint16_t port)
246 {
247     uint16_t* pp = getPortPtr(sockaddr);
248     if (pp) {
249         *pp = Endian_hostToBigEndian16(port);
250         return 0;
251     }
252     return -1;
253 }
254 
Sockaddr_getAddress(struct Sockaddr * sockaddr,void * addrPtr)255 int Sockaddr_getAddress(struct Sockaddr* sockaddr, void* addrPtr)
256 {
257     if (sockaddr->addrLen < (2 + Sockaddr_OVERHEAD)) {
258         return -1;
259     }
260     struct Sockaddr_pvt* sa = (struct Sockaddr_pvt*) sockaddr;
261     if (addrPtr) {
262         void** ap = (void**) addrPtr;
263         switch (sa->ss.ss_family) {
264             case AF_INET: *ap = &((struct sockaddr_in*)&sa->ss)->sin_addr; break;
265             case AF_INET6: *ap = &((struct sockaddr_in6*)&sa->ss)->sin6_addr; break;
266         }
267     }
268     switch (sa->ss.ss_family) {
269         case AF_INET: return 4;
270         case AF_INET6: return 16;
271     }
272     return -1;
273 }
274 
275 const int Sockaddr_AF_INET = AF_INET;
276 const int Sockaddr_AF_INET6 = AF_INET6;
Sockaddr_getFamily(struct Sockaddr * sockaddr)277 int Sockaddr_getFamily(struct Sockaddr* sockaddr)
278 {
279     if (sockaddr->addrLen < (2 + Sockaddr_OVERHEAD)) {
280         return -1;
281     }
282     struct Sockaddr_pvt* sa = (struct Sockaddr_pvt*) sockaddr;
283     return sa->ss.ss_family;
284 }
285 
Sockaddr_fromBytes(const uint8_t * bytes,int addrFamily,struct Allocator * alloc)286 struct Sockaddr* Sockaddr_fromBytes(const uint8_t* bytes, int addrFamily, struct Allocator* alloc)
287 {
288     struct sockaddr_storage ss;
289     Bits_memset(&ss, 0, sizeof(struct sockaddr_storage));
290     int addrLen;
291     switch (addrFamily) {
292         case AF_INET: {
293             ss.ss_family = AF_INET;
294             Bits_memcpy(&((struct sockaddr_in*)&ss)->sin_addr, bytes, 4);
295             addrLen = sizeof(struct sockaddr_in);
296             break;
297         }
298         case AF_INET6: {
299             ss.ss_family = AF_INET6;
300             Bits_memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr, bytes, 16);
301             addrLen = sizeof(struct sockaddr_in6);
302             break;
303         }
304         default: Assert_failure("unrecognized address type [%d]", addrFamily);
305     }
306 
307     struct Sockaddr_pvt* out = Allocator_calloc(alloc, addrLen + Sockaddr_OVERHEAD, 1);
308     Bits_memcpy(&out->ss, &ss, addrLen);
309     out->pub.addrLen = addrLen + Sockaddr_OVERHEAD;
310     return &out->pub;
311 }
312 
Sockaddr_normalizeNative(void * nativeSockaddr)313 void Sockaddr_normalizeNative(void* nativeSockaddr)
314 {
315 #if defined(freebsd) || defined(openbsd) || defined(netbsd) || defined(darwin)
316     ((struct sockaddr*)nativeSockaddr)->sa_len = 0;
317 #endif
318 }
319 
Sockaddr_hash(const struct Sockaddr * addr)320 uint32_t Sockaddr_hash(const struct Sockaddr* addr)
321 {
322     return Hash_compute((uint8_t*)addr, addr->addrLen);
323 }
324 
Sockaddr_compare(const struct Sockaddr * a,const struct Sockaddr * b)325 int Sockaddr_compare(const struct Sockaddr* a, const struct Sockaddr* b)
326 {
327     return Bits_memcmp(a, b, a->addrLen);
328 }
329 
Sockaddr_addrHandle(const struct Sockaddr * addr)330 uint32_t Sockaddr_addrHandle(const struct Sockaddr* addr)
331 {
332     if (addr->addrLen != sizeof(struct Sockaddr) || addr->type != Sockaddr_HANDLE) {
333         return Sockaddr_addrHandle_INVALID;
334     }
335     uint32_t handle;
336     Bits_memcpy(&handle, &((uint8_t*)addr)[4], 4);
337     return handle;
338 }
339 
Sockaddr_addrFromHandle(struct Sockaddr * addr,uint32_t handle)340 void Sockaddr_addrFromHandle(struct Sockaddr* addr, uint32_t handle)
341 {
342     Assert_true(handle != Sockaddr_addrHandle_INVALID);
343     Bits_memset(addr, 0, sizeof(struct Sockaddr));
344     addr->type = Sockaddr_HANDLE;
345     addr->addrLen = sizeof(struct Sockaddr);
346     Bits_memcpy(&((uint8_t*)addr)[4], &handle, 4);
347 }