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