summaryrefslogtreecommitdiff
path: root/toxcore/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/network.c')
-rw-r--r--toxcore/network.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/toxcore/network.c b/toxcore/network.c
index 622a4b17..f504401e 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -234,3 +234,181 @@ void kill_networking(Networking_Core *net)
234 free(net); 234 free(net);
235 return; 235 return;
236} 236}
237
238/*
239 * addr_parse_ip
240 * directly parses the input into an IP structure
241 * tries IPv4 first, then IPv6
242 *
243 * input
244 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
245 *
246 * output
247 * IP: family and the value is set on success
248 *
249 * returns 1 on success, 0 on failure
250 */
251
252int addr_parse_ip(const char *address, IPAny *to)
253{
254 struct in_addr addr4;
255 if (1 == inet_pton(AF_INET, address, &addr4))
256 {
257 to->family = AF_INET;
258 to->ip4.in_addr = addr4;
259 return 1;
260 };
261
262 struct in6_addr addr6;
263 if (1 == inet_pton(AF_INET6, address, &addr6))
264 {
265 to->family = AF_INET6;
266 to->ip6 = addr6;
267 return 1;
268 };
269
270 return 0;
271};
272
273/*
274 * addr_resolve():
275 * uses getaddrinfo to resolve an address into an IP address
276 * uses the first IPv4/IPv6 addresses returned by getaddrinfo
277 *
278 * input
279 * address: a hostname (or something parseable to an IP address)
280 * ip: ip.family MUST be initialized, either set to a specific IP version
281 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
282 * IP versions are acceptable
283 *
284 * returns in ip a valid IPAny (v4/v6),
285 * prefers v6 if ip.family was AF_UNSPEC and both available
286 * returns 0 on failure
287 */
288
289int addr_resolve(const char *address, IPAny *ip)
290{
291 struct addrinfo *server = NULL;
292 struct addrinfo *walker = NULL;
293 struct addrinfo hints;
294 int rc;
295
296 memset(&hints, 0, sizeof(hints));
297 hints.ai_family = ip->family;
298 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
299
300#ifdef __WIN32__
301 WSADATA wsa_data;
302
303 /* CLEANUP: really not the best place to put this */
304 rc = WSAStartup(MAKEWORD(2, 2), &wsa_data);
305
306 if (rc != 0) {
307 return 0;
308 }
309
310#endif
311
312 rc = getaddrinfo(address, NULL, &hints, &server);
313 // Lookup failed.
314 if (rc != 0) {
315#ifdef __WIN32__
316 WSACleanup();
317#endif
318 return 0;
319 }
320
321 IP4 ip4;
322 memset(&ip4, 0, sizeof(ip4));
323 IP6 ip6;
324 memset(&ip6, 0, sizeof(ip6));
325
326 walker = server;
327 while (walker && (rc != 3))
328 {
329 if (ip->family != AF_UNSPEC)
330 {
331 if (walker->ai_family == ip->family) {
332 if (ip->family == AF_INET)
333 {
334 if (walker->ai_addrlen == sizeof(struct sockaddr_in))
335 {
336 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
337 ip->ip4.in_addr = addr->sin_addr;
338 rc = 3;
339 }
340 }
341 else if (ip->family == AF_INET6)
342 {
343 if (walker->ai_addrlen == sizeof(struct sockaddr_in6))
344 {
345 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
346 ip->ip6 = addr->sin6_addr;
347 rc = 3;
348 }
349 }
350 }
351 }
352 else
353 {
354 if (walker->ai_family == AF_INET)
355 {
356 if (walker->ai_addrlen == sizeof(struct sockaddr_in))
357 {
358 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
359 ip4.in_addr = addr->sin_addr;
360 rc |= 1;
361 }
362 }
363 else if (walker->ai_family == AF_INET6)
364 {
365 if (walker->ai_addrlen == sizeof(struct sockaddr_in6))
366 {
367 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
368 ip6 = addr->sin6_addr;
369 rc |= 2;
370 }
371 }
372 }
373
374 walker = walker->ai_next;
375 }
376
377 if (ip->family == AF_UNSPEC)
378 {
379 if (rc & 2)
380 {
381 ip->family = AF_INET6;
382 ip->ip6 = ip6;
383 } else if (rc & 1)
384 {
385 ip->family = AF_INET;
386 ip->ip4 = ip4;
387 }
388 else
389 rc = 0;
390 }
391
392
393 freeaddrinfo(server);
394#ifdef __WIN32__
395 WSACleanup();
396#endif
397 return rc;
398}
399
400/*
401 * addr_resolve_or_parse_ip
402 * resolves string into an IP address
403 *
404 * to->family MUST be set (AF_UNSPEC, AF_INET, AF_INET6)
405 * returns 1 on success, 0 on failure
406 */
407int addr_resolve_or_parse_ip(const char *address, IPAny *to)
408{
409 if (!addr_resolve(address, to))
410 if (!addr_parse_ip(address, to))
411 return 0;
412
413 return 1;
414};