diff options
Diffstat (limited to 'plugins/netutils.c')
| -rw-r--r-- | plugins/netutils.c | 232 |
1 files changed, 120 insertions, 112 deletions
diff --git a/plugins/netutils.c b/plugins/netutils.c index e2916c65..f9933ebd 100644 --- a/plugins/netutils.c +++ b/plugins/netutils.c | |||
| @@ -30,18 +30,15 @@ | |||
| 30 | #include "common.h" | 30 | #include "common.h" |
| 31 | #include "output.h" | 31 | #include "output.h" |
| 32 | #include "states.h" | 32 | #include "states.h" |
| 33 | #include <sys/types.h> | ||
| 33 | #include "netutils.h" | 34 | #include "netutils.h" |
| 34 | 35 | ||
| 35 | unsigned int socket_timeout = DEFAULT_SOCKET_TIMEOUT; | 36 | unsigned int socket_timeout = DEFAULT_SOCKET_TIMEOUT; |
| 36 | unsigned int socket_timeout_state = STATE_CRITICAL; | 37 | mp_state_enum socket_timeout_state = STATE_CRITICAL; |
| 37 | 38 | mp_state_enum econn_refuse_state = STATE_CRITICAL; | |
| 38 | int econn_refuse_state = STATE_CRITICAL; | ||
| 39 | bool was_refused = false; | 39 | bool was_refused = false; |
| 40 | #if USE_IPV6 | 40 | |
| 41 | int address_family = AF_UNSPEC; | 41 | int address_family = AF_UNSPEC; |
| 42 | #else | ||
| 43 | int address_family = AF_INET; | ||
| 44 | #endif | ||
| 45 | 42 | ||
| 46 | /* handles socket timeouts */ | 43 | /* handles socket timeouts */ |
| 47 | void socket_timeout_alarm_handler(int sig) { | 44 | void socket_timeout_alarm_handler(int sig) { |
| @@ -63,38 +60,40 @@ void socket_timeout_alarm_handler(int sig) { | |||
| 63 | /* connects to a host on a specified tcp port, sends a string, and gets a | 60 | /* connects to a host on a specified tcp port, sends a string, and gets a |
| 64 | response. loops on select-recv until timeout or eof to get all of a | 61 | response. loops on select-recv until timeout or eof to get all of a |
| 65 | multi-packet answer */ | 62 | multi-packet answer */ |
| 66 | int process_tcp_request2(const char *server_address, int server_port, const char *send_buffer, char *recv_buffer, int recv_size) { | 63 | mp_state_enum process_tcp_request2(const char *server_address, const int server_port, |
| 64 | const char *send_buffer, char *recv_buffer, | ||
| 65 | const int recv_size) { | ||
| 67 | 66 | ||
| 68 | int result; | 67 | int socket; |
| 69 | int send_result; | ||
| 70 | int recv_result; | ||
| 71 | int sd; | ||
| 72 | struct timeval tv; | ||
| 73 | fd_set readfds; | ||
| 74 | int recv_length = 0; | ||
| 75 | 68 | ||
| 76 | result = np_net_connect(server_address, server_port, &sd, IPPROTO_TCP); | 69 | mp_state_enum connect_result = |
| 77 | if (result != STATE_OK) { | 70 | np_net_connect(server_address, server_port, &socket, IPPROTO_TCP); |
| 71 | if (connect_result != STATE_OK) { | ||
| 78 | return STATE_CRITICAL; | 72 | return STATE_CRITICAL; |
| 79 | } | 73 | } |
| 80 | 74 | ||
| 81 | send_result = send(sd, send_buffer, strlen(send_buffer), 0); | 75 | mp_state_enum result; |
| 76 | ssize_t send_result = send(socket, send_buffer, strlen(send_buffer), 0); | ||
| 82 | if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) { | 77 | if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) { |
| 83 | // printf("%s\n", _("Send failed")); | 78 | // printf("%s\n", _("Send failed")); |
| 84 | result = STATE_WARNING; | 79 | result = STATE_WARNING; |
| 85 | } | 80 | } |
| 86 | 81 | ||
| 87 | while (1) { | 82 | fd_set readfds; |
| 83 | ssize_t recv_length = 0; | ||
| 84 | while (true) { | ||
| 88 | /* wait up to the number of seconds for socket timeout | 85 | /* wait up to the number of seconds for socket timeout |
| 89 | minus one for data from the host */ | 86 | minus one for data from the host */ |
| 90 | tv.tv_sec = socket_timeout - 1; | 87 | struct timeval timeout = { |
| 91 | tv.tv_usec = 0; | 88 | .tv_sec = socket_timeout - 1, |
| 89 | .tv_usec = 0, | ||
| 90 | }; | ||
| 92 | FD_ZERO(&readfds); | 91 | FD_ZERO(&readfds); |
| 93 | FD_SET(sd, &readfds); | 92 | FD_SET(socket, &readfds); |
| 94 | select(sd + 1, &readfds, NULL, NULL, &tv); | 93 | select(socket + 1, &readfds, NULL, NULL, &timeout); |
| 95 | 94 | ||
| 96 | /* make sure some data has arrived */ | 95 | /* make sure some data has arrived */ |
| 97 | if (!FD_ISSET(sd, &readfds)) { /* it hasn't */ | 96 | if (!FD_ISSET(socket, &readfds)) { /* it hasn't */ |
| 98 | if (!recv_length) { | 97 | if (!recv_length) { |
| 99 | strcpy(recv_buffer, ""); | 98 | strcpy(recv_buffer, ""); |
| 100 | // printf("%s\n", _("No data was received from host!")); | 99 | // printf("%s\n", _("No data was received from host!")); |
| @@ -103,70 +102,69 @@ int process_tcp_request2(const char *server_address, int server_port, const char | |||
| 103 | recv_buffer[recv_length] = 0; | 102 | recv_buffer[recv_length] = 0; |
| 104 | } | 103 | } |
| 105 | break; | 104 | break; |
| 106 | } else { /* it has */ | 105 | } /* it has */ |
| 107 | recv_result = recv(sd, recv_buffer + recv_length, (size_t)recv_size - recv_length - 1, 0); | 106 | |
| 108 | if (recv_result == -1) { | 107 | ssize_t recv_result = |
| 109 | /* recv failed, bail out */ | 108 | recv(socket, recv_buffer + recv_length, (size_t)(recv_size - recv_length - 1), 0); |
| 110 | strcpy(recv_buffer + recv_length, ""); | 109 | if (recv_result == -1) { |
| 111 | result = STATE_WARNING; | 110 | /* recv failed, bail out */ |
| 112 | break; | 111 | strcpy(recv_buffer + recv_length, ""); |
| 113 | } else if (recv_result == 0) { | 112 | result = STATE_WARNING; |
| 114 | /* end of file ? */ | 113 | break; |
| 115 | recv_buffer[recv_length] = 0; | 114 | } |
| 116 | break; | 115 | |
| 117 | } else { /* we got data! */ | 116 | if (recv_result == 0) { |
| 118 | recv_length += recv_result; | 117 | /* end of file ? */ |
| 119 | if (recv_length >= recv_size - 1) { | 118 | recv_buffer[recv_length] = 0; |
| 120 | /* buffer full, we're done */ | 119 | break; |
| 121 | recv_buffer[recv_size - 1] = 0; | 120 | } |
| 122 | break; | 121 | |
| 123 | } | 122 | /* we got data! */ |
| 124 | } | 123 | recv_length += recv_result; |
| 124 | if (recv_length >= recv_size - 1) { | ||
| 125 | /* buffer full, we're done */ | ||
| 126 | recv_buffer[recv_size - 1] = 0; | ||
| 127 | break; | ||
| 125 | } | 128 | } |
| 126 | /* end if(!FD_ISSET(sd,&readfds)) */ | 129 | /* end if(!FD_ISSET(sd,&readfds)) */ |
| 127 | } | 130 | } |
| 128 | /* end while(1) */ | ||
| 129 | 131 | ||
| 130 | close(sd); | 132 | close(socket); |
| 131 | return result; | 133 | return result; |
| 132 | } | 134 | } |
| 133 | 135 | ||
| 134 | /* connects to a host on a specified port, sends a string, and gets a | 136 | /* connects to a host on a specified port, sends a string, and gets a |
| 135 | response */ | 137 | response */ |
| 136 | int process_request(const char *server_address, int server_port, int proto, const char *send_buffer, char *recv_buffer, int recv_size) { | 138 | mp_state_enum process_request(const char *server_address, const int server_port, const int proto, |
| 137 | int result; | 139 | const char *send_buffer, char *recv_buffer, const int recv_size) { |
| 138 | int sd; | ||
| 139 | 140 | ||
| 140 | result = STATE_OK; | 141 | mp_state_enum result = STATE_OK; |
| 141 | 142 | int socket; | |
| 142 | result = np_net_connect(server_address, server_port, &sd, proto); | 143 | result = np_net_connect(server_address, server_port, &socket, proto); |
| 143 | if (result != STATE_OK) { | 144 | if (result != STATE_OK) { |
| 144 | return STATE_CRITICAL; | 145 | return STATE_CRITICAL; |
| 145 | } | 146 | } |
| 146 | 147 | ||
| 147 | result = send_request(sd, proto, send_buffer, recv_buffer, recv_size); | 148 | result = send_request(socket, proto, send_buffer, recv_buffer, recv_size); |
| 148 | 149 | ||
| 149 | close(sd); | 150 | close(socket); |
| 150 | 151 | ||
| 151 | return result; | 152 | return result; |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | /* opens a tcp or udp connection to a remote host or local socket */ | 155 | /* opens a tcp or udp connection to a remote host or local socket */ |
| 155 | int np_net_connect(const char *host_name, int port, int *sd, int proto) { | 156 | mp_state_enum np_net_connect(const char *host_name, int port, int *socketDescriptor, |
| 157 | const int proto) { | ||
| 156 | /* send back STATE_UNKOWN if there's an error | 158 | /* send back STATE_UNKOWN if there's an error |
| 157 | send back STATE_OK if we connect | 159 | send back STATE_OK if we connect |
| 158 | send back STATE_CRITICAL if we can't connect. | 160 | send back STATE_CRITICAL if we can't connect. |
| 159 | Let upstream figure out what to send to the user. */ | 161 | Let upstream figure out what to send to the user. */ |
| 160 | struct addrinfo hints; | 162 | bool is_socket = (host_name[0] == '/'); |
| 161 | struct addrinfo *r, *res; | 163 | int socktype = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM; |
| 162 | struct sockaddr_un su; | ||
| 163 | char port_str[6], host[MAX_HOST_ADDRESS_LENGTH]; | ||
| 164 | size_t len; | ||
| 165 | int socktype, result; | ||
| 166 | short is_socket = (host_name[0] == '/'); | ||
| 167 | |||
| 168 | socktype = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM; | ||
| 169 | 164 | ||
| 165 | struct addrinfo hints = {}; | ||
| 166 | struct addrinfo *res = NULL; | ||
| 167 | int result; | ||
| 170 | /* as long as it doesn't start with a '/', it's assumed a host or ip */ | 168 | /* as long as it doesn't start with a '/', it's assumed a host or ip */ |
| 171 | if (!is_socket) { | 169 | if (!is_socket) { |
| 172 | memset(&hints, 0, sizeof(hints)); | 170 | memset(&hints, 0, sizeof(hints)); |
| @@ -174,38 +172,46 @@ int np_net_connect(const char *host_name, int port, int *sd, int proto) { | |||
| 174 | hints.ai_protocol = proto; | 172 | hints.ai_protocol = proto; |
| 175 | hints.ai_socktype = socktype; | 173 | hints.ai_socktype = socktype; |
| 176 | 174 | ||
| 177 | len = strlen(host_name); | 175 | size_t len = strlen(host_name); |
| 178 | /* check for an [IPv6] address (and strip the brackets) */ | 176 | /* check for an [IPv6] address (and strip the brackets) */ |
| 179 | if (len >= 2 && host_name[0] == '[' && host_name[len - 1] == ']') { | 177 | if (len >= 2 && host_name[0] == '[' && host_name[len - 1] == ']') { |
| 180 | host_name++; | 178 | host_name++; |
| 181 | len -= 2; | 179 | len -= 2; |
| 182 | } | 180 | } |
| 181 | |||
| 182 | char host[MAX_HOST_ADDRESS_LENGTH]; | ||
| 183 | |||
| 183 | if (len >= sizeof(host)) { | 184 | if (len >= sizeof(host)) { |
| 184 | return STATE_UNKNOWN; | 185 | return STATE_UNKNOWN; |
| 185 | } | 186 | } |
| 187 | |||
| 186 | memcpy(host, host_name, len); | 188 | memcpy(host, host_name, len); |
| 187 | host[len] = '\0'; | 189 | host[len] = '\0'; |
| 190 | |||
| 191 | char port_str[6]; | ||
| 188 | snprintf(port_str, sizeof(port_str), "%d", port); | 192 | snprintf(port_str, sizeof(port_str), "%d", port); |
| 189 | result = getaddrinfo(host, port_str, &hints, &res); | 193 | int getaddrinfo_err = getaddrinfo(host, port_str, &hints, &res); |
| 190 | 194 | ||
| 191 | if (result != 0) { | 195 | if (getaddrinfo_err != 0) { |
| 192 | // printf("%s\n", gai_strerror(result)); | 196 | // printf("%s\n", gai_strerror(result)); |
| 193 | return STATE_UNKNOWN; | 197 | return STATE_UNKNOWN; |
| 194 | } | 198 | } |
| 195 | 199 | ||
| 196 | r = res; | 200 | struct addrinfo *addressPointer = res; |
| 197 | while (r) { | 201 | while (addressPointer) { |
| 198 | /* attempt to create a socket */ | 202 | /* attempt to create a socket */ |
| 199 | *sd = socket(r->ai_family, socktype, r->ai_protocol); | 203 | *socketDescriptor = |
| 204 | socket(addressPointer->ai_family, socktype, addressPointer->ai_protocol); | ||
| 200 | 205 | ||
| 201 | if (*sd < 0) { | 206 | if (*socketDescriptor < 0) { |
| 202 | // printf("%s\n", _("Socket creation failed")); | 207 | // printf("%s\n", _("Socket creation failed")); |
| 203 | freeaddrinfo(r); | 208 | freeaddrinfo(addressPointer); |
| 204 | return STATE_UNKNOWN; | 209 | return STATE_UNKNOWN; |
| 205 | } | 210 | } |
| 206 | 211 | ||
| 207 | /* attempt to open a connection */ | 212 | /* attempt to open a connection */ |
| 208 | result = connect(*sd, r->ai_addr, r->ai_addrlen); | 213 | result = |
| 214 | connect(*socketDescriptor, addressPointer->ai_addr, addressPointer->ai_addrlen); | ||
| 209 | 215 | ||
| 210 | if (result == 0) { | 216 | if (result == 0) { |
| 211 | was_refused = false; | 217 | was_refused = false; |
| @@ -220,24 +226,28 @@ int np_net_connect(const char *host_name, int port, int *sd, int proto) { | |||
| 220 | } | 226 | } |
| 221 | } | 227 | } |
| 222 | 228 | ||
| 223 | close(*sd); | 229 | close(*socketDescriptor); |
| 224 | r = r->ai_next; | 230 | addressPointer = addressPointer->ai_next; |
| 225 | } | 231 | } |
| 232 | |||
| 226 | freeaddrinfo(res); | 233 | freeaddrinfo(res); |
| 227 | } | 234 | |
| 228 | /* else the hostname is interpreted as a path to a unix socket */ | 235 | } else { |
| 229 | else { | 236 | /* else the hostname is interpreted as a path to a unix socket */ |
| 230 | if (strlen(host_name) >= UNIX_PATH_MAX) { | 237 | if (strlen(host_name) >= UNIX_PATH_MAX) { |
| 231 | die(STATE_UNKNOWN, _("Supplied path too long unix domain socket")); | 238 | die(STATE_UNKNOWN, _("Supplied path too long unix domain socket")); |
| 232 | } | 239 | } |
| 233 | memset(&su, 0, sizeof(su)); | 240 | |
| 241 | struct sockaddr_un su = {}; | ||
| 234 | su.sun_family = AF_UNIX; | 242 | su.sun_family = AF_UNIX; |
| 235 | strncpy(su.sun_path, host_name, UNIX_PATH_MAX); | 243 | strncpy(su.sun_path, host_name, UNIX_PATH_MAX); |
| 236 | *sd = socket(PF_UNIX, SOCK_STREAM, 0); | 244 | *socketDescriptor = socket(PF_UNIX, SOCK_STREAM, 0); |
| 237 | if (*sd < 0) { | 245 | |
| 246 | if (*socketDescriptor < 0) { | ||
| 238 | die(STATE_UNKNOWN, _("Socket creation failed")); | 247 | die(STATE_UNKNOWN, _("Socket creation failed")); |
| 239 | } | 248 | } |
| 240 | result = connect(*sd, (struct sockaddr *)&su, sizeof(su)); | 249 | |
| 250 | result = connect(*socketDescriptor, (struct sockaddr *)&su, sizeof(su)); | ||
| 241 | if (result < 0 && errno == ECONNREFUSED) { | 251 | if (result < 0 && errno == ECONNREFUSED) { |
| 242 | was_refused = true; | 252 | was_refused = true; |
| 243 | } | 253 | } |
| @@ -245,7 +255,9 @@ int np_net_connect(const char *host_name, int port, int *sd, int proto) { | |||
| 245 | 255 | ||
| 246 | if (result == 0) { | 256 | if (result == 0) { |
| 247 | return STATE_OK; | 257 | return STATE_OK; |
| 248 | } else if (was_refused) { | 258 | } |
| 259 | |||
| 260 | if (was_refused) { | ||
| 249 | switch (econn_refuse_state) { /* a user-defined expected outcome */ | 261 | switch (econn_refuse_state) { /* a user-defined expected outcome */ |
| 250 | case STATE_OK: | 262 | case STATE_OK: |
| 251 | case STATE_WARNING: /* user wants WARN or OK on refusal, or... */ | 263 | case STATE_WARNING: /* user wants WARN or OK on refusal, or... */ |
| @@ -253,7 +265,8 @@ int np_net_connect(const char *host_name, int port, int *sd, int proto) { | |||
| 253 | if (is_socket) { | 265 | if (is_socket) { |
| 254 | // printf("connect to file socket %s: %s\n", host_name, strerror(errno)); | 266 | // printf("connect to file socket %s: %s\n", host_name, strerror(errno)); |
| 255 | } else { | 267 | } else { |
| 256 | // printf("connect to address %s and port %d: %s\n", host_name, port, strerror(errno)); | 268 | // printf("connect to address %s and port %d: %s\n", host_name, port, |
| 269 | // strerror(errno)); | ||
| 257 | } | 270 | } |
| 258 | return STATE_CRITICAL; | 271 | return STATE_CRITICAL; |
| 259 | break; | 272 | break; |
| @@ -271,14 +284,11 @@ int np_net_connect(const char *host_name, int port, int *sd, int proto) { | |||
| 271 | } | 284 | } |
| 272 | } | 285 | } |
| 273 | 286 | ||
| 274 | int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer, int recv_size) { | 287 | mp_state_enum send_request(const int socket, const int proto, const char *send_buffer, |
| 275 | int result = STATE_OK; | 288 | char *recv_buffer, const int recv_size) { |
| 276 | int send_result; | 289 | mp_state_enum result = STATE_OK; |
| 277 | int recv_result; | ||
| 278 | struct timeval tv; | ||
| 279 | fd_set readfds; | ||
| 280 | 290 | ||
| 281 | send_result = send(sd, send_buffer, strlen(send_buffer), 0); | 291 | ssize_t send_result = send(socket, send_buffer, strlen(send_buffer), 0); |
| 282 | if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) { | 292 | if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) { |
| 283 | // printf("%s\n", _("Send failed")); | 293 | // printf("%s\n", _("Send failed")); |
| 284 | result = STATE_WARNING; | 294 | result = STATE_WARNING; |
| @@ -286,21 +296,22 @@ int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer, | |||
| 286 | 296 | ||
| 287 | /* wait up to the number of seconds for socket timeout minus one | 297 | /* wait up to the number of seconds for socket timeout minus one |
| 288 | for data from the host */ | 298 | for data from the host */ |
| 289 | tv.tv_sec = socket_timeout - 1; | 299 | struct timeval timestamp = { |
| 290 | tv.tv_usec = 0; | 300 | .tv_sec = socket_timeout - 1, |
| 301 | .tv_usec = 0, | ||
| 302 | }; | ||
| 303 | fd_set readfds; | ||
| 291 | FD_ZERO(&readfds); | 304 | FD_ZERO(&readfds); |
| 292 | FD_SET(sd, &readfds); | 305 | FD_SET(socket, &readfds); |
| 293 | select(sd + 1, &readfds, NULL, NULL, &tv); | 306 | select(socket + 1, &readfds, NULL, NULL, ×tamp); |
| 294 | 307 | ||
| 295 | /* make sure some data has arrived */ | 308 | /* make sure some data has arrived */ |
| 296 | if (!FD_ISSET(sd, &readfds)) { | 309 | if (!FD_ISSET(socket, &readfds)) { |
| 297 | strcpy(recv_buffer, ""); | 310 | strcpy(recv_buffer, ""); |
| 298 | // printf("%s\n", _("No data was received from host!")); | 311 | // printf("%s\n", _("No data was received from host!")); |
| 299 | result = STATE_WARNING; | 312 | result = STATE_WARNING; |
| 300 | } | 313 | } else { |
| 301 | 314 | ssize_t recv_result = recv(socket, recv_buffer, (size_t)(recv_size - 1), 0); | |
| 302 | else { | ||
| 303 | recv_result = recv(sd, recv_buffer, (size_t)recv_size - 1, 0); | ||
| 304 | if (recv_result == -1) { | 315 | if (recv_result == -1) { |
| 305 | strcpy(recv_buffer, ""); | 316 | strcpy(recv_buffer, ""); |
| 306 | if (proto != IPPROTO_TCP) { | 317 | if (proto != IPPROTO_TCP) { |
| @@ -314,6 +325,7 @@ int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer, | |||
| 314 | /* die returned string */ | 325 | /* die returned string */ |
| 315 | recv_buffer[recv_size - 1] = 0; | 326 | recv_buffer[recv_size - 1] = 0; |
| 316 | } | 327 | } |
| 328 | |||
| 317 | return result; | 329 | return result; |
| 318 | } | 330 | } |
| 319 | 331 | ||
| @@ -332,30 +344,24 @@ void host_or_die(const char *str) { | |||
| 332 | } | 344 | } |
| 333 | 345 | ||
| 334 | bool is_addr(const char *address) { | 346 | bool is_addr(const char *address) { |
| 335 | #ifdef USE_IPV6 | ||
| 336 | if (address_family == AF_INET && is_inet_addr(address)) { | 347 | if (address_family == AF_INET && is_inet_addr(address)) { |
| 337 | return true; | 348 | return true; |
| 338 | } else if (address_family == AF_INET6 && is_inet6_addr(address)) { | ||
| 339 | return true; | ||
| 340 | } | 349 | } |
| 341 | #else | 350 | |
| 342 | if (is_inet_addr(address)) { | 351 | if (address_family == AF_INET6 && is_inet6_addr(address)) { |
| 343 | return (true); | 352 | return true; |
| 344 | } | 353 | } |
| 345 | #endif | ||
| 346 | 354 | ||
| 347 | return (false); | 355 | return false; |
| 348 | } | 356 | } |
| 349 | 357 | ||
| 350 | int dns_lookup(const char *in, struct sockaddr_storage *ss, int family) { | 358 | bool dns_lookup(const char *node_string, struct sockaddr_storage *ss, const int family) { |
| 351 | struct addrinfo hints; | 359 | struct addrinfo hints; |
| 352 | struct addrinfo *res; | ||
| 353 | int retval; | ||
| 354 | |||
| 355 | memset(&hints, 0, sizeof(struct addrinfo)); | 360 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 356 | hints.ai_family = family; | 361 | hints.ai_family = family; |
| 357 | 362 | ||
| 358 | retval = getaddrinfo(in, NULL, &hints, &res); | 363 | struct addrinfo *res; |
| 364 | int retval = getaddrinfo(node_string, NULL, &hints, &res); | ||
| 359 | if (retval != 0) { | 365 | if (retval != 0) { |
| 360 | return false; | 366 | return false; |
| 361 | } | 367 | } |
| @@ -363,6 +369,8 @@ int dns_lookup(const char *in, struct sockaddr_storage *ss, int family) { | |||
| 363 | if (ss != NULL) { | 369 | if (ss != NULL) { |
| 364 | memcpy(ss, res->ai_addr, res->ai_addrlen); | 370 | memcpy(ss, res->ai_addr, res->ai_addrlen); |
| 365 | } | 371 | } |
| 372 | |||
| 366 | freeaddrinfo(res); | 373 | freeaddrinfo(res); |
| 374 | |||
| 367 | return true; | 375 | return true; |
| 368 | } | 376 | } |
