Go Back

0 /*

1 * ISC License

2 * Copyright (c) 2023 RMF <rawmonk@firemail.cc>

3 */

4 #include <stdio.h>

5 #include <string.h>

6 #include <stdlib.h>

7 #include <sys/socket.h>

8 #include <errno.h>

9 #include <netdb.h>

10 #include <arpa/inet.h>

11 #ifdef __FreeBSD__

12 #include <netinet/in.h>

13 #include "sandbox.h"

14 #define getaddrinfo sandbox_getaddrinfo

15 #endif

16 #include "macro.h"

17 #include "error.h"

18 #include "dns.h"

19

20 int dns_getip(const char *hostname, ip *out) {

21

22 struct addrinfo hints, *servinfo, *p;

23 struct sockaddr_in *ipv4 = NULL;

24 struct sockaddr_in6 *ipv6 = NULL;

25 int error;

26

27 memset(&hints, 0, sizeof(hints));

28 hints.ai_family = AF_INET;

29 hints.ai_socktype = SOCK_STREAM;

30

31 /* can block */

32 if ((error = getaddrinfo(hostname , NULL, &hints, &servinfo)))

33 return ERROR_GETADDRINFO | ((-error) << 16);

34

35 for (p = servinfo; p != NULL; p = p->ai_next) {

36 switch (p->ai_family) {

37 case AF_INET:

38 ipv4 = (struct sockaddr_in*)p->ai_addr;

39 p = NULL; /* prioritize IPv4 */

40 break;

41 case AF_INET6:

42 ipv6 = (struct sockaddr_in6*)p->ai_addr;

43 if (ipv4) p = NULL;

44 break;

45 }

46 if (!p) break;

47 }

48

49 error = 0;

50 if (ipv4) {

51 *out = malloc(sizeof(struct sockaddr_in));

52 if (!out) error = ERROR_MEMORY_FAILURE;

53 else memcpy(*out, ipv4, sizeof(struct sockaddr_in));

54 } else if (ipv6) {

55 *out = malloc(sizeof(struct sockaddr_in6));

56 if (!out) error = ERROR_MEMORY_FAILURE;

57 else memcpy(*out, ipv6, sizeof(struct sockaddr_in6));

58 } else error = ERROR_INVALID_ADDRESS;

59

60 freeaddrinfo(servinfo);

61 return error;

62 }

63