diff --git a/src/netconfig.c b/src/netconfig.c index 694611ac..1857449f 100644 --- a/src/netconfig.c +++ b/src/netconfig.c @@ -222,6 +222,65 @@ static int netconfig_set_dns(struct netconfig *netconfig) return 0; } +static void append_domain(char **domains, unsigned int *n_domains, + size_t max, char *domain) +{ + unsigned int i; + + if (*n_domains == max) + return; + + for (i = 0; i < *n_domains; i++) + if (!strcmp(domains[i], domain)) + return; + + domains[*n_domains] = domain; + *n_domains += 1; +} + +static int netconfig_set_domains(struct netconfig *netconfig) +{ + char *domains[31]; + unsigned int n_domains = 0; + char *v4_domain = NULL; + char **v6_domains = NULL; + char **p; + + memset(domains, 0, sizeof(domains)); + + /* Allow to override the DHCP domain name with setting entry. */ + v4_domain = l_settings_get_string(netconfig->active_settings, + "IPv4", "DomainName"); + if (!v4_domain && netconfig->rtm_protocol == RTPROT_DHCP) { + const struct l_dhcp_lease *lease = + l_dhcp_client_get_lease(netconfig->dhcp_client); + + if (lease) + v4_domain = l_dhcp_lease_get_domain_name(lease); + } + + append_domain(domains, &n_domains, + L_ARRAY_SIZE(domains) - 1, v4_domain); + + if (netconfig->rtm_v6_protocol == RTPROT_DHCP) { + const struct l_dhcp6_lease *lease = + l_dhcp6_client_get_lease(netconfig->dhcp6_client); + + if (lease) + v6_domains = l_dhcp6_lease_get_domains(lease); + } + + for (p = v6_domains; p && *p; p++) + append_domain(domains, &n_domains, + L_ARRAY_SIZE(domains) - 1, *p); + + resolve_set_domains(netconfig->resolve, domains); + l_strv_free(v6_domains); + l_free(v4_domain); + + return 0; +} + static struct netconfig_ifaddr *netconfig_ipv4_get_ifaddr( struct netconfig *netconfig, uint8_t proto) @@ -333,28 +392,6 @@ static char *netconfig_ipv4_get_gateway(struct netconfig *netconfig) return NULL; } -static char *netconfig_ipv4_get_domain_name(struct netconfig *netconfig, - uint8_t proto) -{ - const struct l_dhcp_lease *lease; - char *domain_name; - - domain_name = l_settings_get_string(netconfig->active_settings, - "IPv4", "DomainName"); - if (domain_name) - /* Allow to override the DHCP domain name with setting entry. */ - return domain_name; - - if (proto != RTPROT_DHCP) - return NULL; - - lease = l_dhcp_client_get_lease(netconfig->dhcp_client); - if (!lease) - return NULL; - - return l_dhcp_lease_get_domain_name(lease); -} - static struct netconfig_ifaddr *netconfig_ipv6_get_ifaddr( struct netconfig *netconfig, uint8_t proto) @@ -775,7 +812,6 @@ static void netconfig_ipv4_ifaddr_add_cmd_cb(int error, uint16_t type, { struct netconfig *netconfig = user_data; struct netconfig_ifaddr *ifaddr; - char *domain_name; if (error && error != -EEXIST) { l_error("netconfig: Failed to add IP address. " @@ -798,14 +834,7 @@ static void netconfig_ipv4_ifaddr_add_cmd_cb(int error, uint16_t type, } netconfig_set_dns(netconfig); - - domain_name = netconfig_ipv4_get_domain_name(netconfig, - netconfig->rtm_protocol); - if (!domain_name) - goto done; - - resolve_add_domain_name(netconfig->resolve, domain_name); - l_free(domain_name); + netconfig_set_domains(netconfig); done: netconfig_ifaddr_destroy(ifaddr); diff --git a/src/resolve.c b/src/resolve.c index 8e36caad..1d211937 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -39,8 +39,7 @@ struct resolve_ops { void (*set_dns)(struct resolve *resolve, char **dns_list); - void (*add_domain_name)(struct resolve *resolve, - const char *domain_name); + void (*set_domains)(struct resolve *resolve, char **domain_list); void (*revert)(struct resolve *resolve); void (*destroy)(struct resolve *resolve); }; @@ -68,15 +67,15 @@ void resolve_set_dns(struct resolve *resolve, char **dns_list) resolve->ops->set_dns(resolve, dns_list); } -void resolve_add_domain_name(struct resolve *resolve, const char *domain_name) +void resolve_set_domains(struct resolve *resolve, char **domain_list) { - if (!domain_name) + if (!domain_list) return; - if (!resolve->ops->add_domain_name) + if (!resolve->ops->set_domains) return; - resolve->ops->add_domain_name(resolve, domain_name); + resolve->ops->set_domains(resolve, domain_list); } void resolve_revert(struct resolve *resolve) @@ -210,7 +209,7 @@ static void resolve_systemd_set_dns(struct resolve *resolve, char **dns_list) NULL, NULL); } -static void systemd_link_add_domains_reply(struct l_dbus_message *message, +static void systemd_set_link_domains_reply(struct l_dbus_message *message, void *user_data) { const char *name; @@ -225,10 +224,12 @@ static void systemd_link_add_domains_reply(struct l_dbus_message *message, name, text); } -static void resolve_systemd_add_domain_name(struct resolve *resolve, - const char *domain_name) +static void resolve_systemd_set_domains(struct resolve *resolve, + char **domain_list) { struct l_dbus_message *message; + struct l_dbus_message_builder *builder; + bool f = false; l_debug("ifindex: %u", resolve->ifindex); @@ -244,11 +245,29 @@ static void resolve_systemd_add_domain_name(struct resolve *resolve, if (!message) return; - l_dbus_message_set_arguments(message, "ia(sb)", resolve->ifindex, - 1, domain_name, false); + builder = l_dbus_message_builder_new(message); + if (!builder) { + l_dbus_message_unref(message); + return; + } + + l_dbus_message_builder_append_basic(builder, 'i', &resolve->ifindex); + l_dbus_message_builder_enter_array(builder, "(sb)"); + + for (; *domain_list; domain_list++) { + l_dbus_message_builder_enter_struct(builder, "sb"); + l_dbus_message_builder_append_basic(builder, 's', *domain_list); + l_dbus_message_builder_append_basic(builder, 'b', &f); + l_dbus_message_builder_leave_struct(builder); + } + + l_dbus_message_builder_leave_array(builder); + + l_dbus_message_builder_finalize(builder); + l_dbus_message_builder_destroy(builder); l_dbus_send_with_reply(dbus_get_bus(), message, - systemd_link_add_domains_reply, NULL, NULL); + systemd_set_link_domains_reply, NULL, NULL); } static void resolve_systemd_revert(struct resolve *resolve) @@ -282,7 +301,7 @@ static void resolve_systemd_destroy(struct resolve *resolve) static const struct resolve_ops systemd_ops = { .set_dns = resolve_systemd_set_dns, - .add_domain_name = resolve_systemd_add_domain_name, + .set_domains = resolve_systemd_set_domains, .revert = resolve_systemd_revert, .destroy = resolve_systemd_destroy, }; @@ -398,19 +417,25 @@ static void resolve_resolvconf_set_dns(struct resolve *resolve, char **dns_list) rc->have_dns = true; } -static void resolve_resolvconf_add_domain_name(struct resolve *resolve, - const char *domain_name) +static void resolve_resolvconf_set_domains(struct resolve *resolve, + char **domain_list) { struct resolvconf *rc = l_container_of(resolve, struct resolvconf, super); - L_AUTO_FREE_VAR(char *, domain_str) = NULL; + struct l_string *content; + L_AUTO_FREE_VAR(char *, str) = NULL; if (L_WARN_ON(!resolvconf_path)) return; - domain_str = l_strdup_printf("search %s\n", domain_name); + content = l_string_new(0); - if (resolvconf_invoke(rc->ifname, "domain", domain_str)) + for (; *domain_list; domain_list++) + l_string_append_printf(content, "search %s\n", *domain_list); + + str = l_string_unwrap(content); + + if (resolvconf_invoke(rc->ifname, "domain", str)) rc->have_domain = true; } @@ -440,7 +465,7 @@ static void resolve_resolvconf_destroy(struct resolve *resolve) static struct resolve_ops resolvconf_ops = { .set_dns = resolve_resolvconf_set_dns, - .add_domain_name = resolve_resolvconf_add_domain_name, + .set_domains = resolve_resolvconf_set_domains, .revert = resolve_resolvconf_revert, .destroy = resolve_resolvconf_destroy, }; diff --git a/src/resolve.h b/src/resolve.h index 84beb15b..64ed15f3 100644 --- a/src/resolve.h +++ b/src/resolve.h @@ -22,6 +22,6 @@ struct resolve *resolve_new(uint32_t ifindex); void resolve_set_dns(struct resolve *resolve, char **dns_list); -void resolve_add_domain_name(struct resolve *resolve, const char *domain_name); +void resolve_set_domains(struct resolve *resolve, char **domain_list); void resolve_revert(struct resolve *resolve); void resolve_free(struct resolve *resolve);