mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +03:00
networkd: add support for Uplink Failure Detection
Introduce BindCarrier= to indicate the set of links that determine if the current link should be brought UP or DOWN. [tomegun: add a bit to commit message]
This commit is contained in:
parent
2bdbf32183
commit
0d4ad91dd4
@ -279,6 +279,17 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>BindCarrier=</varname></term>
|
||||
<listitem>
|
||||
<para>A port or a list of ports. When set, controls the
|
||||
behaviour of the current interface. When all ports in the list
|
||||
are in an operational down state, the current interface is brought
|
||||
down. When at least one port has carrier, the current interface
|
||||
is brought up.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Address=</varname></term>
|
||||
<listitem>
|
||||
|
@ -261,6 +261,14 @@ _public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
|
||||
return network_get_link_strv("DOMAINS", ifindex, ret);
|
||||
}
|
||||
|
||||
_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) {
|
||||
return network_get_link_strv("CARRIER_BOUND_TO", ifindex, ret);
|
||||
}
|
||||
|
||||
_public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
|
||||
return network_get_link_strv("CARRIER_BOUND_BY", ifindex, ret);
|
||||
}
|
||||
|
||||
_public_ int sd_network_link_get_wildcard_domain(int ifindex) {
|
||||
int r;
|
||||
_cleanup_free_ char *p = NULL, *s = NULL;
|
||||
|
@ -508,6 +508,8 @@ static int link_status_one(
|
||||
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
|
||||
const char *on_color_operational, *off_color_operational,
|
||||
*on_color_setup, *off_color_setup;
|
||||
_cleanup_strv_free_ char **carrier_bound_to = NULL;
|
||||
_cleanup_strv_free_ char **carrier_bound_by = NULL;
|
||||
struct ether_addr e;
|
||||
unsigned iftype;
|
||||
int r, ifindex;
|
||||
@ -606,12 +608,15 @@ static int link_status_one(
|
||||
|
||||
sd_network_link_get_network_file(ifindex, &network);
|
||||
|
||||
sd_network_link_get_carrier_bound_to(ifindex, &carrier_bound_to);
|
||||
sd_network_link_get_carrier_bound_by(ifindex, &carrier_bound_by);
|
||||
|
||||
printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, name);
|
||||
|
||||
printf(" Link File: %s\n"
|
||||
"Network File: %s\n"
|
||||
" Type: %s\n"
|
||||
" State: %s%s%s (%s%s%s)\n",
|
||||
printf(" Link File: %s\n"
|
||||
" Network File: %s\n"
|
||||
" Type: %s\n"
|
||||
" State: %s%s%s (%s%s%s)\n",
|
||||
strna(link),
|
||||
strna(network),
|
||||
strna(t),
|
||||
@ -619,13 +624,13 @@ static int link_status_one(
|
||||
on_color_setup, strna(setup_state), off_color_setup);
|
||||
|
||||
if (path)
|
||||
printf(" Path: %s\n", path);
|
||||
printf(" Path: %s\n", path);
|
||||
if (driver)
|
||||
printf(" Driver: %s\n", driver);
|
||||
printf(" Driver: %s\n", driver);
|
||||
if (vendor)
|
||||
printf(" Vendor: %s\n", vendor);
|
||||
printf(" Vendor: %s\n", vendor);
|
||||
if (model)
|
||||
printf(" Model: %s\n", model);
|
||||
printf(" Model: %s\n", model);
|
||||
|
||||
if (have_mac) {
|
||||
_cleanup_free_ char *description = NULL;
|
||||
@ -634,23 +639,29 @@ static int link_status_one(
|
||||
ieee_oui(hwdb, &e, &description);
|
||||
|
||||
if (description)
|
||||
printf(" HW Address: %s (%s)\n", ether_addr_to_string(&e, ea), description);
|
||||
printf(" HW Address: %s (%s)\n", ether_addr_to_string(&e, ea), description);
|
||||
else
|
||||
printf(" HW Address: %s\n", ether_addr_to_string(&e, ea));
|
||||
printf(" HW Address: %s\n", ether_addr_to_string(&e, ea));
|
||||
}
|
||||
|
||||
if (mtu > 0)
|
||||
printf(" MTU: %u\n", mtu);
|
||||
printf(" MTU: %u\n", mtu);
|
||||
|
||||
dump_addresses(rtnl, " Address: ", ifindex);
|
||||
dump_gateways(rtnl, hwdb, " Gateway: ", ifindex);
|
||||
dump_addresses(rtnl, " Address: ", ifindex);
|
||||
dump_gateways(rtnl, hwdb, " Gateway: ", ifindex);
|
||||
|
||||
if (!strv_isempty(dns))
|
||||
dump_list(" DNS: ", dns);
|
||||
dump_list(" DNS: ", dns);
|
||||
if (!strv_isempty(domains))
|
||||
dump_list(" Domain: ", domains);
|
||||
dump_list(" Domain: ", domains);
|
||||
if (!strv_isempty(ntp))
|
||||
dump_list(" NTP: ", ntp);
|
||||
dump_list(" NTP: ", ntp);
|
||||
|
||||
if (!strv_isempty(carrier_bound_to))
|
||||
dump_list("Carrier Bound To: ", carrier_bound_to);
|
||||
|
||||
if (!strv_isempty(carrier_bound_by))
|
||||
dump_list("Carrier Bound By: ", carrier_bound_by);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -272,6 +272,8 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
|
||||
|
||||
static void link_free(Link *link) {
|
||||
Address *address;
|
||||
Iterator i;
|
||||
Link *carrier;
|
||||
|
||||
if (!link)
|
||||
return;
|
||||
@ -309,6 +311,14 @@ static void link_free(Link *link) {
|
||||
|
||||
udev_device_unref(link->udev_device);
|
||||
|
||||
HASHMAP_FOREACH (carrier, link->bound_to_links, i)
|
||||
hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex));
|
||||
hashmap_free(link->bound_to_links);
|
||||
|
||||
HASHMAP_FOREACH (carrier, link->bound_by_links, i)
|
||||
hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
|
||||
hashmap_free(link->bound_by_links);
|
||||
|
||||
free(link);
|
||||
}
|
||||
|
||||
@ -355,19 +365,6 @@ static void link_set_state(Link *link, LinkState state) {
|
||||
return;
|
||||
}
|
||||
|
||||
void link_drop(Link *link) {
|
||||
if (!link || link->state == LINK_STATE_LINGER)
|
||||
return;
|
||||
|
||||
link_set_state(link, LINK_STATE_LINGER);
|
||||
|
||||
log_link_debug(link, "link removed");
|
||||
|
||||
link_unref(link);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void link_enter_unmanaged(Link *link) {
|
||||
assert(link);
|
||||
|
||||
@ -1148,13 +1145,319 @@ static int link_up(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_down_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
|
||||
_cleanup_link_unref_ Link *link = userdata;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_rtnl_message_get_errno(m);
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, -r, "%-*s: could not bring down interface: %m", IFNAMSIZ, link->ifname);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_down(Link *link) {
|
||||
_cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
|
||||
log_link_debug(link, "bringing link down");
|
||||
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
|
||||
RTM_SETLINK, link->ifindex);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not allocate RTM_SETLINK message");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
|
||||
if (r < 0) {
|
||||
log_link_error(link, "Could not set link flags: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_call_async(link->manager->rtnl, req, link_down_handler, link,
|
||||
0, NULL);
|
||||
if (r < 0) {
|
||||
log_link_error(link,
|
||||
"Could not send rtnetlink message: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
link_ref(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_handle_bound_to_list(Link *link) {
|
||||
Link *l;
|
||||
Iterator i;
|
||||
int r;
|
||||
bool required_up = false;
|
||||
bool link_is_up = false;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (hashmap_isempty(link->bound_to_links))
|
||||
return 0;
|
||||
|
||||
if (link->flags & IFF_UP)
|
||||
link_is_up = true;
|
||||
|
||||
HASHMAP_FOREACH (l, link->bound_to_links, i)
|
||||
if (link_has_carrier(l)) {
|
||||
required_up = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!required_up && link_is_up) {
|
||||
r = link_down(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (required_up && !link_is_up) {
|
||||
r = link_up(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_handle_bound_by_list(Link *link) {
|
||||
Iterator i;
|
||||
Link *l;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (hashmap_isempty(link->bound_by_links))
|
||||
return 0;
|
||||
|
||||
HASHMAP_FOREACH (l, link->bound_by_links, i) {
|
||||
r = link_handle_bound_to_list(l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(carrier);
|
||||
|
||||
if (link == carrier)
|
||||
return 0;
|
||||
|
||||
if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex)))
|
||||
return 0;
|
||||
|
||||
r = hashmap_ensure_allocated(h, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_new_bound_by_list(Link *link) {
|
||||
Manager *m;
|
||||
Link *carrier;
|
||||
Iterator i;
|
||||
int r;
|
||||
bool list_updated = false;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
m = link->manager;
|
||||
|
||||
HASHMAP_FOREACH (carrier, m->links, i) {
|
||||
if (!carrier->network)
|
||||
continue;
|
||||
|
||||
if (strv_isempty(carrier->network->bind_carrier))
|
||||
continue;
|
||||
|
||||
if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) {
|
||||
r = link_put_carrier(link, carrier, &link->bound_by_links);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
list_updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (list_updated)
|
||||
link_save(link);
|
||||
|
||||
HASHMAP_FOREACH (carrier, link->bound_by_links, i) {
|
||||
r = link_put_carrier(carrier, link, &carrier->bound_to_links);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_save(carrier);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_new_bound_to_list(Link *link) {
|
||||
Manager *m;
|
||||
Link *carrier;
|
||||
Iterator i;
|
||||
int r;
|
||||
bool list_updated = false;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
if (!link->network)
|
||||
return 0;
|
||||
|
||||
if (strv_isempty(link->network->bind_carrier))
|
||||
return 0;
|
||||
|
||||
m = link->manager;
|
||||
|
||||
HASHMAP_FOREACH (carrier, m->links, i) {
|
||||
if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) {
|
||||
r = link_put_carrier(link, carrier, &link->bound_to_links);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
list_updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (list_updated)
|
||||
link_save(link);
|
||||
|
||||
HASHMAP_FOREACH (carrier, link->bound_to_links, i) {
|
||||
r = link_put_carrier(carrier, link, &carrier->bound_by_links);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_save(carrier);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_new_carrier_maps(Link *link) {
|
||||
int r;
|
||||
|
||||
r = link_new_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_handle_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_new_bound_to_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_handle_bound_to_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void link_free_bound_to_list(Link *link) {
|
||||
Link *bound_to;
|
||||
Iterator i;
|
||||
|
||||
HASHMAP_FOREACH (bound_to, link->bound_to_links, i) {
|
||||
hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex));
|
||||
|
||||
if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex)))
|
||||
link_save(bound_to);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void link_free_bound_by_list(Link *link) {
|
||||
Link *bound_by;
|
||||
Iterator i;
|
||||
|
||||
HASHMAP_FOREACH (bound_by, link->bound_by_links, i) {
|
||||
hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex));
|
||||
|
||||
if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) {
|
||||
link_save(bound_by);
|
||||
link_handle_bound_to_list(bound_by);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void link_free_carrier_maps(Link *link) {
|
||||
bool list_updated = false;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!hashmap_isempty(link->bound_to_links)) {
|
||||
link_free_bound_to_list(link);
|
||||
list_updated = true;
|
||||
}
|
||||
|
||||
if (!hashmap_isempty(link->bound_by_links)) {
|
||||
link_free_bound_by_list(link);
|
||||
list_updated = true;
|
||||
}
|
||||
|
||||
if (list_updated)
|
||||
link_save(link);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void link_drop(Link *link) {
|
||||
if (!link || link->state == LINK_STATE_LINGER)
|
||||
return;
|
||||
|
||||
link_set_state(link, LINK_STATE_LINGER);
|
||||
|
||||
link_free_carrier_maps(link);
|
||||
|
||||
log_link_debug(link, "link removed");
|
||||
|
||||
link_unref(link);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int link_joined(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
|
||||
if (!(link->flags & IFF_UP)) {
|
||||
if (!hashmap_isempty(link->bound_to_links)) {
|
||||
r = link_handle_bound_to_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (!(link->flags & IFF_UP)) {
|
||||
r = link_up(link);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
@ -1429,6 +1732,14 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
|
||||
|
||||
log_link_debug(link, "link state is up-to-date");
|
||||
|
||||
r = link_new_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_handle_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = network_get(link->manager, link->udev_device, link->ifname,
|
||||
&link->mac, &network);
|
||||
if (r == -ENOENT) {
|
||||
@ -1452,6 +1763,10 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_new_bound_to_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_configure(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1729,6 +2044,10 @@ static int link_carrier_gained(Link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
r = link_handle_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1743,6 +2062,10 @@ static int link_carrier_lost(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = link_handle_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1782,16 +2105,26 @@ int link_update(Link *link, sd_rtnl_message *m) {
|
||||
link_ref(link);
|
||||
log_link_info(link, "link readded");
|
||||
link_set_state(link, LINK_STATE_ENSLAVING);
|
||||
|
||||
r = link_new_carrier_maps(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
|
||||
if (r >= 0 && !streq(ifname, link->ifname)) {
|
||||
log_link_info(link, "renamed to %s", ifname);
|
||||
|
||||
link_free_carrier_maps(link);
|
||||
|
||||
free(link->ifname);
|
||||
link->ifname = strdup(ifname);
|
||||
if (!link->ifname)
|
||||
return -ENOMEM;
|
||||
|
||||
r = link_new_carrier_maps(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
|
||||
@ -2060,6 +2393,39 @@ int link_save(Link *link) {
|
||||
llmnr_support_to_string(link->network->llmnr));
|
||||
}
|
||||
|
||||
if (!hashmap_isempty(link->bound_to_links)) {
|
||||
Link *carrier;
|
||||
Iterator i;
|
||||
bool space = false;
|
||||
|
||||
fputs("CARRIER_BOUND_TO=", f);
|
||||
HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(carrier->ifname, f);
|
||||
space = true;
|
||||
}
|
||||
|
||||
fputs("\n", f);
|
||||
}
|
||||
|
||||
if (!hashmap_isempty(link->bound_by_links)) {
|
||||
Link *carrier;
|
||||
Iterator i;
|
||||
bool space = false;
|
||||
|
||||
fputs("CARRIER_BOUND_BY=", f);
|
||||
space = false;
|
||||
HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(carrier->ifname, f);
|
||||
space = true;
|
||||
}
|
||||
|
||||
fputs("\n", f);
|
||||
}
|
||||
|
||||
if (link->dhcp_lease) {
|
||||
assert(link->network);
|
||||
|
||||
|
@ -85,6 +85,9 @@ struct Link {
|
||||
|
||||
sd_lldp *lldp;
|
||||
char *lldp_file;
|
||||
|
||||
Hashmap *bound_by_links;
|
||||
Hashmap *bound_to_links;
|
||||
};
|
||||
|
||||
Link *link_unref(Link *link);
|
||||
|
@ -48,6 +48,7 @@ Network.LLMNR, config_parse_llmnr, 0,
|
||||
Network.NTP, config_parse_strv, 0, offsetof(Network, ntp)
|
||||
Network.IPForward, config_parse_address_family_boolean,0, offsetof(Network, ip_forward)
|
||||
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
|
||||
Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier)
|
||||
Address.Address, config_parse_address, 0, 0
|
||||
Address.Peer, config_parse_address, 0, 0
|
||||
Address.Broadcast, config_parse_broadcast, 0, 0
|
||||
|
@ -208,6 +208,7 @@ void network_free(Network *network) {
|
||||
strv_free(network->ntp);
|
||||
strv_free(network->dns);
|
||||
strv_free(network->domains);
|
||||
strv_free(network->bind_carrier);
|
||||
|
||||
netdev_unref(network->bridge);
|
||||
|
||||
|
@ -151,7 +151,7 @@ struct Network {
|
||||
Hashmap *fdb_entries_by_section;
|
||||
|
||||
bool wildcard_domain;
|
||||
char **domains, **dns, **ntp;
|
||||
char **domains, **dns, **ntp, **bind_carrier;
|
||||
|
||||
LLMNRSupport llmnr;
|
||||
|
||||
|
@ -116,6 +116,12 @@ int sd_network_link_get_lldp(int ifindex, char **lldp);
|
||||
/* Get the DNS domain names for a given link. */
|
||||
int sd_network_link_get_domains(int ifindex, char ***domains);
|
||||
|
||||
/* Get the CARRIERS to which current link is bound to. */
|
||||
int sd_network_link_get_carrier_bound_to(int ifindex, char ***carriers);
|
||||
|
||||
/* Get the CARRIERS that are bound to current link. */
|
||||
int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers);
|
||||
|
||||
/* Returns whether or not domains that don't match any link should be resolved
|
||||
* on this link. 1 for yes, 0 for no and negative value for error */
|
||||
int sd_network_link_get_wildcard_domain(int ifindex);
|
||||
|
Loading…
Reference in New Issue
Block a user