-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sys/posix: add module posix_netdb #16853
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also added the option to use posix sockets for the existing
sock_dns
module. Without using posix sockets I had extremely poor success rates for address resolution (approximately 1 out of 20).
NACK. 1. We rather should find the reason, why sock_udp
performs so poorly compared to POSIX sockets (which below use sock_udp
, so this fact seems weird to me). 2. sock_dns
using POSIX sockets turns everything on its head, now we have a sock
module using POSIX sockets using a sock
module. Conceptually alone this sounds very dirty.
I have to correct myself. Either I did not remember correctly (has been some months now) or it is due to the rebase, but without using posix sockets it is not working at all. I traced it back to the function |
Ok, so the problem is with lwIP's |
Still a dirty hack that should not go into |
Speaking of, I really think you should rebase this PR ;-). |
I'll have a look into it |
This was just so one could test this with a working wolfmqtt application ;) I would rather find out why this is happening, but if I can't find out the reason in reasonable time and if you say it is a viable option I might resort to implement a |
Again, I think the more viable option in the latter case would be, I think to put the functionality directly into |
a972bb8
to
96aeab2
Compare
My comments were addressed. Sorry for the long blocking.
965fd34
to
8efa4d4
Compare
Murdock results❌ FAILED af92ba3 tests/posix_netdb: add test Build failures (1)
ArtifactsThis only reflects a subset of all builds from https://ci-prod.riot-os.org. Please refer to https://ci.riot-os.org for a complete build for now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the description needs an update, but what's LWIP specific about this?
8efa4d4
to
81e3f63
Compare
81e3f63
to
af92ba3
Compare
CI is unhappy |
Seems like the esp32 platform, in contrast to the other platforms, defines its own |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean by providing errno.h
in RIOT - it's already provided by libc
/** | ||
* @brief The name could not be resolved at this time. Future attempts may succeed. | ||
*/ | ||
#define EAI_AGAIN 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#define EAI_AGAIN 1 | |
#ifndef EAI_AGAIN | |
#define EAI_AGAIN 1 | |
#endif |
would be the simplest solution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could lead to overlapping or diverging number spaces, when the libc/IDE provides defines differ from the defines here. Rather, it should just be avoided to include external headers (as we did already e.g. for defines in net/inet.h
).
If this source is correct, then libc defines |
For some weird reason the three error codes @gschorcht Can we get rid of these error codes for the esp32? |
af92ba3
to
3d3fc4e
Compare
3d3fc4e
to
7cec42c
Compare
* @retval EAI_AGAIN Recoverable error, try again later | ||
* @retval EAI_BADFLAGS Invalid value in flag parameters (hints->ai_flags) | ||
* @retval EAI_FAIL Non-recoverable error | ||
* @retval EAI_FAMILY Unsupported address family | ||
* @retval EAI_MEMORY No memory available to receive data or to allocate result object | ||
* @retval EAI_NONAME Name does not resolve | ||
* @retval EAI_SERVICE Service does not resolve |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
POSIX spec just says a non-zero return value indicates failure
, but the errno
should be set. The implementation should reflect the specified behavior.
*/ | ||
#define INADDR_ANY ((in_addr_t)0x00000000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This constant is specified for this header. Please do not remove it.
/* invalid name length */ | ||
return EAI_FAIL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and in other instances of early return
/* invalid name length */ | |
return EAI_FAIL; | |
/* invalid name length */ | |
errno = EAI_FAIL | |
return EAI_FAIL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe even use an error goto?
At the very end of your function put
error:
return errno;
And then, whenever there is an error (such in this case) use
/* invalid name length */ | |
return EAI_FAIL; | |
/* invalid name length */ | |
errno = EAI_FAIL; | |
goto error; |
uint8_t addr_buf[16] = { 0 }; | ||
int res = dns_query(nodename, addr_buf, hints->ai_family); | ||
switch (res) { | ||
case -ETIMEDOUT: | ||
/* fall-through */ | ||
case -EAGAIN: | ||
return EAI_AGAIN; | ||
|
||
case -ENOMEM: | ||
return EAI_MEMORY; | ||
|
||
case INADDRSZ: | ||
addr.type = AF_INET; | ||
memcpy(&addr.ipv4, addr_buf, INADDRSZ); | ||
break; | ||
|
||
case IN6ADDRSZ: | ||
addr.type = AF_INET6; | ||
memcpy(&addr.ipv6, addr_buf, IN6ADDRSZ); | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use addr
directly?
Make ipvx_addr_t
the following:
typedef struct ipvx_addr {
sa_family_t type;
union {
struct in_addr ipv4;
struct in6_addr ipv6;
uint8_t u8[16];
};
} ipvx_addr_t;
Then just do
uint8_t addr_buf[16] = { 0 }; | |
int res = dns_query(nodename, addr_buf, hints->ai_family); | |
switch (res) { | |
case -ETIMEDOUT: | |
/* fall-through */ | |
case -EAGAIN: | |
return EAI_AGAIN; | |
case -ENOMEM: | |
return EAI_MEMORY; | |
case INADDRSZ: | |
addr.type = AF_INET; | |
memcpy(&addr.ipv4, addr_buf, INADDRSZ); | |
break; | |
case IN6ADDRSZ: | |
addr.type = AF_INET6; | |
memcpy(&addr.ipv6, addr_buf, IN6ADDRSZ); | |
break; | |
int res = dns_query(nodename, addr->u8, hints->ai_family); | |
switch (res) { | |
case -ETIMEDOUT: | |
/* fall-through */ | |
case -EAGAIN: | |
return EAI_AGAIN; | |
case -ENOMEM: | |
return EAI_MEMORY; | |
case INADDRSZ: | |
addr.type = AF_INET; | |
break; | |
case IN6ADDRSZ: | |
addr.type = AF_INET6; | |
break; |
And safe both a little ROM and RAM
if (addr.type == AF_INET) { | ||
ai->ai_family = AF_INET; | ||
|
||
struct sockaddr_in *sa4 = (struct sockaddr_in*) sas; | ||
sa4->sin_addr = addr.ipv4; | ||
sa4->sin_family = AF_INET; | ||
sa4->sin_port = htons(port); | ||
} | ||
else if (addr.type == AF_INET6) { | ||
ai->ai_family = AF_INET6; | ||
|
||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*) sas; | ||
sa6->sin6_addr = addr.ipv6; | ||
sa6->sin6_family = AF_INET6; | ||
sa6->sin6_port = htons(port); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (addr.type == AF_INET) { | |
ai->ai_family = AF_INET; | |
struct sockaddr_in *sa4 = (struct sockaddr_in*) sas; | |
sa4->sin_addr = addr.ipv4; | |
sa4->sin_family = AF_INET; | |
sa4->sin_port = htons(port); | |
} | |
else if (addr.type == AF_INET6) { | |
ai->ai_family = AF_INET6; | |
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*) sas; | |
sa6->sin6_addr = addr.ipv6; | |
sa6->sin6_family = AF_INET6; | |
sa6->sin6_port = htons(port); | |
} | |
ai->ai_family = addr.type; | |
struct sockaddr_in6 *sa = (struct sockaddr_in6*) sas; | |
sa->sin6_addr = addr.ipv6; | |
sa->sin6_family = addr.type; | |
sa->sin6_port = htons(port); |
Should suffice.
return EAI_MEMORY; | ||
} | ||
|
||
memcpy(ai->ai_canonname, nodename, name_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Use strncpy()
instead? You are copying a string here after all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or strscpy()
USEMODULE += sock_udp | ||
USEMODULE += gnrc_ipv6 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need the whole stack if you mock DNS anyway?
TEST_ASSERT_EQUAL_INT(AF_INET, result->ai_family); | ||
TEST_ASSERT_NOT_NULL(inet_ntop(AF_INET, &((struct sockaddr_in*)(result->ai_addr))->sin_addr, | ||
addr4_str, sizeof(addr4_str))); | ||
TEST_ASSERT_EQUAL_INT(0, strcmp(addr4_str, test_ipv4)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and in other instances where you used TEST_ASSERT_EQUAL_INT(0, strcmp(...))
TEST_ASSERT_EQUAL_INT(0, strcmp(addr4_str, test_ipv4)); | |
TEST_ASSERT_EQUAL_STRING(addr4_str, test_ipv4); |
TEST_ASSERT_NOT_NULL(inet_ntop(AF_INET6, &((struct sockaddr_in6*)(result->ai_addr))->sin6_addr, | ||
addr6_str, sizeof(addr6_str))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use a temporary variable here for sockaddr_in6 for better readability?
|
||
switch (result->ai_family) { | ||
case AF_INET: | ||
memcpy(&addr_ipv4, &((struct sockaddr_in*)(result->ai_addr))->sin_addr.s_addr, sizeof(ipv4_addr_t)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dito (also: in its current state the line is longer than 100 chars)
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
include ../Makefile.tests_common | ||
|
||
USEMODULE += embunit | ||
|
||
# make sure we have an implementation of sock_types.h | ||
USEMODULE += sock_udp | ||
USEMODULE += gnrc_ipv6 | ||
|
||
USEMODULE += ipv4_addr | ||
USEMODULE += ipv6_addr | ||
|
||
# use mock data for the test | ||
USEMODULE += sock_dns_mock | ||
|
||
USEMODULE += posix_netdb | ||
|
||
include $(RIOTBASE)/Makefile.include |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make -C tests/posix_netdb/ all-valgrind term-valgrind
yields
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
--105511-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x9b
==105511== Invalid read of size 4
==105511== at 0x804BC0C: ??? (in /home/mlenders/Repositories/RIOT-OS/RIOT/tests/posix_netdb/bin/native/tests_posix_netdb.elf)
==105511== Address 0x806c790 is in the brk data segment 0x8079000-0x8078fff
==105511==
{ "threads": [{ "name": "main", "stack_size": 12288, "stack_used": 2444}]}
Sadly no line number but somewhere is an out of bounds read error to one of the malloc
'd memory areas in this test (or the netdb code).
Contribution description
This PR adds a new posix module which provides netdb functions like
gethostbyname
orgetaddrinfo
. It does not come with its own implementation.Testing procedure
You can test this PR e.g. in conjunction with everything else in #15969.
Issues/PRs references
Missing posix feature, see #7801.
This PR is split out from the chunky #15969.
Dependencies: