NeoMutt  2022-04-29-323-g5fcc6c
Teaching an old dog new tricks
DOXYGEN
getdomain.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <assert.h>
31#include <netdb.h>
32#include <string.h>
33#include <sys/socket.h>
34#include <time.h>
35#include <unistd.h>
36#include "mutt/lib.h"
37#include "lib.h" // IWYU pragma: keep
38
39#ifdef HAVE_GETADDRINFO_A
49static struct addrinfo *mutt_getaddrinfo_a(const char *node, const struct addrinfo *hints)
50{
51 assert(node);
52 assert(hints);
53 struct addrinfo *result = NULL;
54
55 /* Allow 0.1 seconds to get the FQDN (fully-qualified domain name).
56 * If it takes longer, the system is mis-configured and the network is not
57 * working properly, so... */
58 struct timespec timeout = { 0, 100000000 };
59 struct gaicb req = { 0 };
60 req.ar_name = node;
61 req.ar_request = hints;
62 struct gaicb *reqs[1] = { &req };
63 if (getaddrinfo_a(GAI_NOWAIT, reqs, 1, NULL) == 0)
64 {
65 gai_suspend((const struct gaicb *const *) reqs, 1, &timeout);
66 const int status = gai_error(reqs[0]);
67 if (status == 0)
68 {
69 result = reqs[0]->ar_result;
70 }
71 else if (status == EAI_INPROGRESS)
72 {
73 mutt_debug(LL_DEBUG1, "timeout\n");
74 /* request is not finished, cancel it to free it safely */
75 if (gai_cancel(reqs[0]) == EAI_NOTCANCELED)
76 {
77 // try once more for half-a-second, then bail out
78 timeout.tv_nsec = 50000000;
79 gai_suspend((const struct gaicb *const *) reqs, 1, &timeout);
80 }
81 }
82 else
83 {
84 mutt_debug(LL_DEBUG1, "fail: (%d) %s\n", status, gai_strerror(status));
85 }
86 }
87 return result;
88}
89
90#elif defined(HAVE_GETADDRINFO)
100static struct addrinfo *mutt_getaddrinfo(const char *node, const struct addrinfo *hints)
101{
102 assert(node);
103 assert(hints);
104 struct addrinfo *result = NULL;
105 mutt_debug(LL_DEBUG3, "before getaddrinfo\n");
106 int rc = getaddrinfo(node, NULL, hints, &result);
107 mutt_debug(LL_DEBUG3, "after getaddrinfo\n");
108
109 if (rc != 0)
110 result = NULL;
111
112 return result;
113}
114#endif
115
122int getdnsdomainname(struct Buffer *result)
123{
124 assert(result);
125 int rc = -1;
126
127#if defined(HAVE_GETADDRINFO) || defined(HAVE_GETADDRINFO_A)
128 char node[256] = { 0 };
129 if (gethostname(node, sizeof(node)) != 0)
130 return rc;
131
132 struct addrinfo *lookup_result = NULL;
133 struct addrinfo hints;
134
135 mutt_buffer_reset(result);
136 memset(&hints, 0, sizeof(struct addrinfo));
137 hints.ai_flags = AI_CANONNAME;
138 hints.ai_family = AF_UNSPEC;
139
140#ifdef HAVE_GETADDRINFO_A
141 lookup_result = mutt_getaddrinfo_a(node, &hints);
142#else
143 lookup_result = mutt_getaddrinfo(node, &hints);
144#endif
145
146 if (lookup_result && lookup_result->ai_canonname)
147 {
148 const char *hostname = strchr(lookup_result->ai_canonname, '.');
149 if (hostname && hostname[1] != '\0')
150 {
151 mutt_buffer_strcpy(result, ++hostname);
152 rc = 0;
153 }
154 }
155
156 if (lookup_result)
157 freeaddrinfo(lookup_result);
158#endif
159
160 return rc;
161}
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:327
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
int getdnsdomainname(struct Buffer *result)
Lookup the host's name using DNS.
Definition: getdomain.c:122
static struct addrinfo * mutt_getaddrinfo(const char *node, const struct addrinfo *hints)
Lookup the host's name using getaddrinfo()
Definition: getdomain.c:100
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
Convenience wrapper for the library headers.
Key value store.
String manipulation buffer.
Definition: buffer.h:34
Time value with nanosecond precision.
Definition: file.h:50
long tv_nsec
Number of nanosecond, on top.
Definition: file.h:52