diff options
Diffstat (limited to 'toxcore/network.c')
-rw-r--r-- | toxcore/network.c | 178 |
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 | |||
252 | int 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 | |||
289 | int 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 | */ | ||
407 | int 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 | }; | ||