Skip to content

Commit a34503d

Browse files
committed
net: getaddrinfo: Parse numeric IPv4 addresses
If a valid numeric IP address is provided as argument, it should be resolved without contacting DNS server. Also, implement handling of AI_NUMERICHOST. Signed-off-by: Paul Sokolovsky <[email protected]>
1 parent 743eb53 commit a34503d

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

subsys/net/lib/sockets/getaddrinfo.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
/* libc headers */
88
#include <stdlib.h>
9+
#include <ctype.h>
910

1011
/* Zephyr headers */
1112
#include <logging/log.h>
@@ -19,6 +20,13 @@ LOG_MODULE_REGISTER(net_sock_addr, CONFIG_NET_SOCKETS_LOG_LEVEL);
1920

2021
#if defined(CONFIG_DNS_RESOLVER)
2122

23+
/* Helper macros which take into account the fact that ai_family as passed
24+
* into getaddrinfo() may take values AF_INET, AF_INET6, or AF_UNSPEC, where
25+
* AF_UNSPEC means resolve both AF_INET and AF_INET6.
26+
*/
27+
#define RESOLVE_IPV4(ai_family) (IS_ENABLED(CONFIG_NET_IPV4) && (ai_family) != AF_INET6)
28+
#define RESOLVE_IPV6(ai_family) (IS_ENABLED(CONFIG_NET_IPV6) && (ai_family) != AF_INET)
29+
2230
struct getaddrinfo_state {
2331
const struct zsock_addrinfo *hints;
2432
struct k_sem sem;
@@ -128,6 +136,7 @@ int z_impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,
128136
struct zsock_addrinfo *res)
129137
{
130138
int family = AF_UNSPEC;
139+
int ai_flags = 0;
131140
long int port = 0;
132141
int st1 = DNS_EAI_ADDRFAMILY, st2 = DNS_EAI_ADDRFAMILY;
133142
struct sockaddr *ai_addr;
@@ -136,6 +145,7 @@ int z_impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,
136145

137146
if (hints) {
138147
family = hints->ai_family;
148+
ai_flags = hints->ai_flags;
139149
}
140150

141151
if (service) {
@@ -155,6 +165,35 @@ int z_impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,
155165
return getaddrinfo_null_host(port, hints, res);
156166
}
157167

168+
#define SIN_ADDR(ptr) (((struct sockaddr_in *)(ptr))->sin_addr)
169+
170+
/* Check for IPv4 numeric address. Start with a quick heuristic check,
171+
* of first char of the address, then do long validating inet_pton()
172+
* call if needed.
173+
*/
174+
if (RESOLVE_IPV4(family)
175+
&& isdigit((int)*host)
176+
&& zsock_inet_pton(AF_INET, host,
177+
&SIN_ADDR(&res->_ai_addr)) == 1) {
178+
struct sockaddr_in *addr =
179+
(struct sockaddr_in *)&res->_ai_addr;
180+
181+
addr->sin_port = htons(port);
182+
addr->sin_family = AF_INET;
183+
INIT_ADDRINFO(res, addr);
184+
res->ai_family = AF_INET;
185+
res->ai_socktype = SOCK_STREAM;
186+
res->ai_protocol = IPPROTO_TCP;
187+
return 0;
188+
}
189+
190+
if (ai_flags & AI_NUMERICHOST) {
191+
/* Asked to resolve host as numeric, but it wasn't possible
192+
* to do that.
193+
*/
194+
return DNS_EAI_FAIL;
195+
}
196+
158197
ai_state.hints = hints;
159198
ai_state.idx = 0U;
160199
ai_state.port = htons(port);

0 commit comments

Comments
 (0)