-
-
Notifications
You must be signed in to change notification settings - Fork 645
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
Add getservbyname and getservbyport #204
Conversation
getservbyname and getservbyport have implementation similar to that of gethostbyname and gethostbyaddr. However, there is no struct ServicesTxt like struct HostsTxt. For every call of getservbyname/getservbyport the lookup of /etc/services is done by opening the file and parsing each line one-by-one. This is slow, but the implementation is simple, and the file parsing is similar to ParseHostsTxt.
@jart would you prefer a |
when gethostbyname is provided an IP address in the form of a string, it is supposed to write the address to h_name; the function instead was writing an empty string. getaddrinfo does the correct thing by calling inet_pton and returning on success, and the mistake is in gethostbyname. The fix is to strlen(result->ai_canonname): If the inet_pton call in getaddrinfo is successful, ai_canonname will point to valid memory (non-NULL) but the string will be empty. in this case, the name (which is an IP address string) will now correctly be copied to h_name of the hostent structure.
using statically allocated values instead. also, the canonname check in gethostbyname doesn't need strlen, just checking the first character to be nonzero should be enough.
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.
Thanks for sending this! Looks good to merge.
I noticed there's no unit tests for this change. Here's how that could have worked:
#include "libc/testlib/testlib.h"
char testlib_enable_tmp_setup_teardown;
void SetUp(void) {
int fd;
const char *s = "\
# hello\n\
finger 79/tcp\n\
http 80/tcp www # WorldWideWeb HTTP\n";
ASSERT_NE(-1, (fd = creat("hosts", 0755)));
ASSERT_NE(-1, write(fd, s, strlen(s)));
ASSERT_NE(-1, close(fd));
}
TEST(ftruncate, test) {
ASSERT_EQ(80, LookupServicesByName("http", ptr, "hosts"));
}
This is fine for now. We can revise it to have a global singleton as soon as it presents performance issues.
Our malloc() is very fast but this does look like a case where it's not needed. If RFC6335 says it's 15 characters then it must be 15 characters. I'm fine enforcing that limit and having a I would support your decision if you chose to make the buffer larger. It doesn't change the fact that the number is officially still 15. It's more of a Postel's Maxim kind of thing in being generous towards nonconformity. But in that case I'd argue that unlimited malloc is much better than defining another arbitrary but somewhat higher limit. |
@jart I have
Thanks for providing an outline for the testing.
My preference for a static buffer for
Currently I'm just using |
* use calloc instead malloc for s_aliases * use strcasecmp instead of strcmp * look through aliases when comparing for LookupServicesByName * provide buffer for name in LookupServicesByName also * provide a filepath param in LookupServicesBy* for testing * use static buffers and DNS_NAME_MAX for s_name
getservbyname
andgetservbyport
have implementation similar to that ofgethostbyname
andgethostbyaddr
.output matches glibc, except that the aliases for a service (ie
struct servent.s_aliases
) are not filled.There is no
struct ServicesTxt
likestruct HostsTxt
. For every call ofgetservbyname
/getservbyport
the lookup of/etc/services
is done by opening the file and parsing each line one-by-one to compare. This is slow, but the implementation is simple; the file loading is similar toGetHostsTxt
and the file parsing is similar toParseHostsTxt
.The remaining functions are stubs in the
musl
source code, so I left them unimplemented here as well.