return (be32toh(a->s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
}
+bool in4_addr_is_non_local(const struct in_addr *a) {
+ /* Whether the address is not null and not localhost.
+ *
+ * As such, it is suitable to configure as DNS/NTP server from DHCP. */
+ return !in4_addr_is_null(a) &&
+ !in4_addr_is_localhost(a);
+}
+
int in_addr_is_localhost(int family, const union in_addr_union *u) {
assert(u);
bool in4_addr_is_localhost(const struct in_addr *a);
int in_addr_is_localhost(int family, const union in_addr_union *u);
+bool in4_addr_is_non_local(const struct in_addr *a);
+
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
return 0;
}
-void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
- unsigned i;
+size_t serialize_in_addrs(FILE *f,
+ const struct in_addr *addresses,
+ size_t size,
+ bool with_leading_space,
+ bool (*predicate)(const struct in_addr *addr)) {
+ size_t count;
+ size_t i;
assert(f);
assert(addresses);
- assert(size);
- for (i = 0; i < size; i++)
- fprintf(f, "%s%s", inet_ntoa(addresses[i]),
- (i < (size - 1)) ? " ": "");
+ count = 0;
+
+ for (i = 0; i < size; i++) {
+ if (predicate && !predicate(&addresses[i]))
+ continue;
+ if (with_leading_space)
+ fputc(' ', f);
+ else
+ with_leading_space = true;
+ fputs(inet_ntoa(addresses[i]), f);
+ count++;
+ }
+
+ return count;
}
int deserialize_in_addrs(struct in_addr **ret, const char *string) {
int net_get_unique_predictable_data(sd_device *device, uint64_t *result);
const char *net_get_name(sd_device *device);
-void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size);
+size_t serialize_in_addrs(FILE *f,
+ const struct in_addr *addresses,
+ size_t size,
+ bool with_leading_space,
+ bool (*predicate)(const struct in_addr *addr));
int deserialize_in_addrs(struct in_addr **addresses, const char *string);
void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
size_t size);
return 0;
}
-static void filter_bogus_addresses(struct in_addr *addresses, size_t *n) {
- size_t i, j;
-
- /* Silently filter DNS/NTP servers supplied to us that do not make outside of the local scope. */
-
- for (i = 0, j = 0; i < *n; i ++) {
-
- if (in4_addr_is_null(addresses+i) ||
- in4_addr_is_localhost(addresses+i))
- continue;
-
- addresses[j++] = addresses[i];
- }
-
- *n = j;
-}
-
-static int lease_parse_in_addrs(const uint8_t *option, size_t len, bool filter_bogus, struct in_addr **ret, size_t *n_ret) {
+static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
assert(option);
assert(ret);
assert(n_ret);
if (!addresses)
return -ENOMEM;
- if (filter_bogus)
- filter_bogus_addresses(addresses, &n_addresses);
-
free(*ret);
*ret = addresses;
*n_ret = n_addresses;
break;
case SD_DHCP_OPTION_ROUTER:
- r = lease_parse_in_addrs(option, len, false, &lease->router, &lease->router_size);
+ r = lease_parse_in_addrs(option, len, &lease->router, &lease->router_size);
if (r < 0)
log_debug_errno(r, "Failed to parse router addresses, ignoring: %m");
break;
case SD_DHCP_OPTION_DOMAIN_NAME_SERVER:
- r = lease_parse_in_addrs(option, len, true, &lease->dns, &lease->dns_size);
+ r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);
if (r < 0)
log_debug_errno(r, "Failed to parse DNS server, ignoring: %m");
break;
case SD_DHCP_OPTION_NTP_SERVER:
- r = lease_parse_in_addrs(option, len, true, &lease->ntp, &lease->ntp_size);
+ r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);
if (r < 0)
log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
break;
r = sd_dhcp_lease_get_router(lease, &addresses);
if (r > 0) {
fputs("ROUTER=", f);
- serialize_in_addrs(f, addresses, r);
+ serialize_in_addrs(f, addresses, r, false, NULL);
fputc('\n', f);
}
r = sd_dhcp_lease_get_dns(lease, &addresses);
if (r > 0) {
fputs("DNS=", f);
- serialize_in_addrs(f, addresses, r);
+ serialize_in_addrs(f, addresses, r, false, NULL);
fputc('\n', f);
}
r = sd_dhcp_lease_get_ntp(lease, &addresses);
if (r > 0) {
fputs("NTP=", f);
- serialize_in_addrs(f, addresses, r);
+ serialize_in_addrs(f, addresses, r, false, NULL);
fputc('\n', f);
}
if (link->network->dhcp_use_dns && link->dhcp_lease) {
const struct in_addr *da = NULL;
- int n;
+ int j, n;
n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
if (n > 0) {
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
return log_oom();
- memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
- n_addresses += n;
+ for (j = 0; j < n; j++)
+ if (in4_addr_is_non_local(&da[j]))
+ addresses[n_addresses++] = da[j];
}
}
if (link->network->dhcp_use_ntp && link->dhcp_lease) {
const struct in_addr *da = NULL;
- int n;
+ int j, n;
n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
if (n > 0) {
if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
return log_oom();
- memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
- n_addresses += n;
+ for (j = 0; j < n; j++)
+ if (in4_addr_is_non_local(&da[j]))
+ addresses[n_addresses++] = da[j];
}
}
const struct in_addr *addresses;
r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
- if (r > 0) {
- if (space)
- fputc(' ', f);
- serialize_in_addrs(f, addresses, r);
- space = true;
- }
+ if (r > 0)
+ if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0)
+ space = true;
}
if (link->network->dhcp_use_dns && dhcp6_lease) {
const struct in_addr *addresses;
r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
- if (r > 0) {
- if (space)
- fputc(' ', f);
- serialize_in_addrs(f, addresses, r);
- space = true;
- }
+ if (r > 0)
+ if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0)
+ space = true;
}
if (link->network->dhcp_use_ntp && dhcp6_lease) {
r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
if (r >= 0) {
fputs("DHCP4_ADDRESS=", f);
- serialize_in_addrs(f, &address, 1);
+ serialize_in_addrs(f, &address, 1, false, NULL);
fputc('\n', f);
}
r = sd_ipv4ll_get_address(link->ipv4ll, &address);
if (r >= 0) {
fputs("IPV4LL_ADDRESS=", f);
- serialize_in_addrs(f, &address, 1);
+ serialize_in_addrs(f, &address, 1, false, NULL);
fputc('\n', f);
}
}
return r;
}
-static int ordered_set_put_in4_addrv(OrderedSet *s, const struct in_addr *addresses, unsigned n) {
+static int ordered_set_put_in4_addrv(OrderedSet *s,
+ const struct in_addr *addresses,
+ size_t n,
+ bool (*predicate)(const struct in_addr *addr)) {
int r, c = 0;
- unsigned i;
+ size_t i;
assert(s);
assert(n == 0 || addresses);
for (i = 0; i < n; i++) {
+ if (predicate && !predicate(&addresses[i]))
+ continue;
r = ordered_set_put_in4_addr(s, addresses+i);
if (r < 0)
return r;
r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
if (r > 0) {
- r = ordered_set_put_in4_addrv(dns, addresses, r);
+ r = ordered_set_put_in4_addrv(dns, addresses, r, in4_addr_is_non_local);
if (r < 0)
return r;
} else if (r < 0 && r != -ENODATA)
r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
if (r > 0) {
- r = ordered_set_put_in4_addrv(ntp, addresses, r);
+ r = ordered_set_put_in4_addrv(ntp, addresses, r, in4_addr_is_non_local);
if (r < 0)
return r;
} else if (r < 0 && r != -ENODATA)