Skip to content
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

Draft: Change .local domain heuristic #84

Merged
merged 2 commits into from
Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/nss.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ enum nss_status _nss_mdns_gethostbyname_impl(const char* name, int af,
userdata_t* u, int* errnop,
int* h_errnop) {

int name_allowed;
FILE* mdns_allow_file = NULL;
use_name_result_t result;

#ifdef NSS_IPV4_ONLY
if (af == AF_UNSPEC) {
Expand Down Expand Up @@ -118,13 +118,14 @@ enum nss_status _nss_mdns_gethostbyname_impl(const char* name, int af,
#ifndef MDNS_MINIMAL
mdns_allow_file = fopen(MDNS_ALLOW_FILE, "r");
#endif
name_allowed = verify_name_allowed_with_soa(name, mdns_allow_file);
result = verify_name_allowed_with_soa(name, mdns_allow_file,
TEST_LOCAL_SOA_AUTO);
#ifndef MDNS_MINIMAL
if (mdns_allow_file)
fclose(mdns_allow_file);
#endif

if (!name_allowed) {
if (result == USE_NAME_RESULT_SKIP) {
*errnop = EINVAL;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
Expand All @@ -137,6 +138,11 @@ enum nss_status _nss_mdns_gethostbyname_impl(const char* name, int af,
case AVAHI_RESOLVE_RESULT_HOST_NOT_FOUND:
*errnop = ETIMEDOUT;
*h_errnop = HOST_NOT_FOUND;
if (result == USE_NAME_RESULT_OPTIONAL) {
/* continue to dns plugin if DNS .local zone is detected. */
*h_errnop = TRY_AGAIN;
return NSS_STATUS_UNAVAIL;
}
return NSS_STATUS_NOTFOUND;

case AVAHI_RESOLVE_RESULT_UNAVAIL:
Expand Down
18 changes: 13 additions & 5 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,24 @@ int ends_with(const char* name, const char* suffix) {
return strcasecmp(name + ln - ls, suffix) == 0;
}

int verify_name_allowed_with_soa(const char* name, FILE* mdns_allow_file) {
use_name_result_t verify_name_allowed_with_soa(const char* name,
FILE* mdns_allow_file,
test_local_soa_t test) {
switch (verify_name_allowed(name, mdns_allow_file)) {
case VERIFY_NAME_RESULT_NOT_ALLOWED:
return 0;
return USE_NAME_RESULT_SKIP;
case VERIFY_NAME_RESULT_ALLOWED:
return 1;
return USE_NAME_RESULT_AUTHORITATIVE;
case VERIFY_NAME_RESULT_ALLOWED_IF_NO_LOCAL_SOA:
return !local_soa();
if (test == TEST_LOCAL_SOA_YES ||
(test == TEST_LOCAL_SOA_AUTO && local_soa()) )
/* Make multicast resolution not authoritative for .local zone.
* Allow continuing to unicast resolution after multicast had not worked. */
return USE_NAME_RESULT_OPTIONAL;
else
return USE_NAME_RESULT_AUTHORITATIVE;
default:
return 0;
return USE_NAME_RESULT_SKIP;
}
}

Expand Down
16 changes: 15 additions & 1 deletion src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@ char* buffer_strdup(buffer_t* buf, const char* str);
int set_cloexec(int fd);
int ends_with(const char* name, const char* suffix);

typedef enum {
USE_NAME_RESULT_SKIP,
USE_NAME_RESULT_AUTHORITATIVE,
USE_NAME_RESULT_OPTIONAL,
} use_name_result_t;

typedef enum {
TEST_LOCAL_SOA_NO,
TEST_LOCAL_SOA_YES,
TEST_LOCAL_SOA_AUTO,
} test_local_soa_t;

// Returns true if we should try to resolve the name with mDNS.
//
// If mdns_allow_file is NULL, then this implements the "local" SOA
Expand All @@ -71,7 +83,9 @@ int ends_with(const char* name, const char* suffix);
//
// The two heuristics described above are disabled if mdns_allow_file
// is not NULL.
int verify_name_allowed_with_soa(const char* name, FILE* mdns_allow_file);
use_name_result_t verify_name_allowed_with_soa(const char* name,
FILE* mdns_allow_file,
test_local_soa_t test);

typedef enum {
VERIFY_NAME_RESULT_NOT_ALLOWED,
Expand Down
18 changes: 18 additions & 0 deletions tests/check_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,24 @@ START_TEST(test_verify_name_allowed_minimal) {
VERIFY_NAME_RESULT_NOT_ALLOWED);
ck_assert_int_eq(verify_name_allowed(".", NULL),
VERIFY_NAME_RESULT_NOT_ALLOWED);

ck_assert_int_eq(verify_name_allowed_with_soa(".", NULL, TEST_LOCAL_SOA_YES),
USE_NAME_RESULT_SKIP);
ck_assert_int_eq(verify_name_allowed_with_soa(".", NULL, TEST_LOCAL_SOA_NO),
USE_NAME_RESULT_SKIP);
ck_assert_int_eq(verify_name_allowed_with_soa(".", NULL, TEST_LOCAL_SOA_AUTO),
USE_NAME_RESULT_SKIP);
ck_assert_int_eq(verify_name_allowed_with_soa("example3.sub.local",
NULL, TEST_LOCAL_SOA_YES), USE_NAME_RESULT_SKIP);
ck_assert_int_eq(verify_name_allowed_with_soa("example4.sub.local",
NULL, TEST_LOCAL_SOA_NO), USE_NAME_RESULT_SKIP);
ck_assert_int_eq(verify_name_allowed_with_soa("example4.sub.local",
NULL, TEST_LOCAL_SOA_AUTO), USE_NAME_RESULT_SKIP);
ck_assert_int_eq(verify_name_allowed_with_soa("example1.local",
NULL, TEST_LOCAL_SOA_YES), USE_NAME_RESULT_OPTIONAL);
ck_assert_int_eq(verify_name_allowed_with_soa("example2.local",
NULL, TEST_LOCAL_SOA_NO), USE_NAME_RESULT_AUTHORITATIVE);
/* TEST_LOCAL_SOA_AUTO would test actual DNS on host, skip that. */
}
END_TEST

Expand Down