mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #17240 from yuwata/network-cleanup
network: several cleanups and fix IPv4DAD and IP Masqurade
This commit is contained in:
@@ -862,11 +862,12 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) {
|
||||
int r;
|
||||
int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short type, int family, union in_addr_union *data) {
|
||||
void *attr_data;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(IN_SET(family, AF_INET, AF_INET6), -EINVAL);
|
||||
|
||||
r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR);
|
||||
if (r < 0)
|
||||
@@ -875,35 +876,35 @@ int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type,
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if ((size_t) r < sizeof(struct in_addr))
|
||||
else if ((size_t) r < FAMILY_ADDRESS_SIZE(family))
|
||||
return -EIO;
|
||||
|
||||
if (data)
|
||||
memcpy(data, attr_data, sizeof(struct in_addr));
|
||||
memcpy(data, attr_data, FAMILY_ADDRESS_SIZE(family));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) {
|
||||
int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) {
|
||||
union in_addr_union u;
|
||||
int r;
|
||||
void *attr_data;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
r = netlink_message_read_in_addr_union(m, type, AF_INET, &u);
|
||||
if (r >= 0 && data)
|
||||
*data = u.in;
|
||||
|
||||
r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = netlink_message_read_internal(m, type, &attr_data, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else if ((size_t) r < sizeof(struct in6_addr))
|
||||
return -EIO;
|
||||
int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) {
|
||||
union in_addr_union u;
|
||||
int r;
|
||||
|
||||
if (data)
|
||||
memcpy(data, attr_data, sizeof(struct in6_addr));
|
||||
r = netlink_message_read_in_addr_union(m, type, AF_INET6, &u);
|
||||
if (r >= 0 && data)
|
||||
*data = u.in6;
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) {
|
||||
|
||||
@@ -77,18 +77,20 @@ int rtnl_log_create_error(int r);
|
||||
userdata, 0, __func__); \
|
||||
})
|
||||
|
||||
#define netlink_add_match(nl, ret_slot, metch, callback, destroy_callback, userdata) \
|
||||
#define netlink_add_match(nl, ret_slot, match, callback, destroy_callback, userdata, description) \
|
||||
({ \
|
||||
int (*_callback_)(sd_netlink *, sd_netlink_message *, typeof(userdata)) = callback; \
|
||||
void (*_destroy_)(typeof(userdata)) = destroy_callback; \
|
||||
sd_netlink_add_match(nl, ret_slot, match, \
|
||||
(sd_netlink_message_handler_t) _callback_, \
|
||||
(sd_netlink_destroy_t) _destroy_, \
|
||||
userdata, __func__); \
|
||||
userdata, description); \
|
||||
})
|
||||
|
||||
int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data);
|
||||
int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data);
|
||||
|
||||
int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short type, int family, union in_addr_union *data);
|
||||
|
||||
void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length);
|
||||
int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void *data, size_t data_length);
|
||||
|
||||
@@ -111,6 +111,8 @@ sources = files('''
|
||||
networkd-speed-meter.h
|
||||
networkd-sriov.c
|
||||
networkd-sriov.h
|
||||
networkd-sysctl.c
|
||||
networkd-sysctl.h
|
||||
networkd-util.c
|
||||
networkd-util.h
|
||||
networkd-wifi.c
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "memory-util.h"
|
||||
#include "netlink-util.h"
|
||||
#include "network-internal.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "path-util.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_macsec.h>
|
||||
|
||||
#include "ether-addr-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "netdev.h"
|
||||
#include "networkd-util.h"
|
||||
|
||||
@@ -4,31 +4,28 @@
|
||||
#include <linux/if_addrlabel.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "conf-parser.h"
|
||||
#include "networkd-address-label.h"
|
||||
#include "netlink-util.h"
|
||||
#include "networkd-address-label.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-network.h"
|
||||
#include "parse-util.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
void address_label_free(AddressLabel *label) {
|
||||
AddressLabel *address_label_free(AddressLabel *label) {
|
||||
if (!label)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
if (label->network) {
|
||||
LIST_REMOVE(labels, label->network->address_labels, label);
|
||||
assert(label->network->n_address_labels > 0);
|
||||
label->network->n_address_labels--;
|
||||
|
||||
if (label->section) {
|
||||
hashmap_remove(label->network->address_labels_by_section, label->section);
|
||||
network_config_section_free(label->section);
|
||||
}
|
||||
assert(label->section);
|
||||
hashmap_remove(label->network->address_labels_by_section, label->section);
|
||||
}
|
||||
|
||||
free(label);
|
||||
network_config_section_free(label->section);
|
||||
return mfree(label);
|
||||
}
|
||||
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free);
|
||||
|
||||
static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
|
||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
||||
_cleanup_(address_label_freep) AddressLabel *label = NULL;
|
||||
@@ -36,19 +33,17 @@ static int address_label_new_static(Network *network, const char *filename, unsi
|
||||
|
||||
assert(network);
|
||||
assert(ret);
|
||||
assert(!!filename == (section_line > 0));
|
||||
assert(filename);
|
||||
assert(section_line > 0);
|
||||
|
||||
if (filename) {
|
||||
r = network_config_section_new(filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = network_config_section_new(filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
label = hashmap_get(network->address_labels_by_section, n);
|
||||
if (label) {
|
||||
*ret = TAKE_PTR(label);
|
||||
|
||||
return 0;
|
||||
}
|
||||
label = hashmap_get(network->address_labels_by_section, n);
|
||||
if (label) {
|
||||
*ret = TAKE_PTR(label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
label = new(AddressLabel, 1);
|
||||
@@ -57,25 +52,18 @@ static int address_label_new_static(Network *network, const char *filename, unsi
|
||||
|
||||
*label = (AddressLabel) {
|
||||
.network = network,
|
||||
.section = TAKE_PTR(n),
|
||||
};
|
||||
|
||||
LIST_APPEND(labels, network->address_labels, label);
|
||||
network->n_address_labels++;
|
||||
r = hashmap_ensure_allocated(&network->address_labels_by_section, &network_config_hash_ops);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (filename) {
|
||||
label->section = TAKE_PTR(n);
|
||||
|
||||
r = hashmap_ensure_allocated(&network->address_labels_by_section, &network_config_hash_ops);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_put(network->address_labels_by_section, label->section, label);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = hashmap_put(network->address_labels_by_section, label->section, label);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(label);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -107,12 +95,7 @@ static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
|
||||
return 1;
|
||||
}
|
||||
|
||||
int address_label_configure(
|
||||
AddressLabel *label,
|
||||
Link *link,
|
||||
link_netlink_message_handler_t callback,
|
||||
bool update) {
|
||||
|
||||
static int address_label_configure(AddressLabel *label, Link *link) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
@@ -140,7 +123,7 @@ int address_label_configure(
|
||||
return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m");
|
||||
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req,
|
||||
callback ?: address_label_handler,
|
||||
address_label_handler,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
||||
@@ -150,6 +133,34 @@ int address_label_configure(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_set_address_labels(Link *link) {
|
||||
AddressLabel *label;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
|
||||
HASHMAP_FOREACH(label, link->network->address_labels_by_section) {
|
||||
r = address_label_configure(label, link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not set address label: %m");
|
||||
|
||||
link->address_label_messages++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void network_drop_invalid_address_labels(Network *network) {
|
||||
AddressLabel *label;
|
||||
|
||||
assert(network);
|
||||
|
||||
HASHMAP_FOREACH(label, network->address_labels_by_section)
|
||||
if (section_is_invalid(label->section))
|
||||
address_label_free(label);
|
||||
}
|
||||
|
||||
int config_parse_address_label_prefix(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
|
||||
@@ -2,38 +2,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "in-addr-util.h"
|
||||
|
||||
typedef struct AddressLabel AddressLabel;
|
||||
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-util.h"
|
||||
|
||||
typedef struct Network Network;
|
||||
typedef struct Link Link;
|
||||
typedef struct NetworkConfigSection NetworkConfigSection;
|
||||
|
||||
struct AddressLabel {
|
||||
typedef struct AddressLabel {
|
||||
Network *network;
|
||||
NetworkConfigSection *section;
|
||||
|
||||
unsigned char prefixlen;
|
||||
uint32_t label;
|
||||
|
||||
union in_addr_union in_addr;
|
||||
} AddressLabel;
|
||||
|
||||
LIST_FIELDS(AddressLabel, labels);
|
||||
};
|
||||
AddressLabel *address_label_free(AddressLabel *label);
|
||||
|
||||
void address_label_free(AddressLabel *label);
|
||||
void network_drop_invalid_address_labels(Network *network);
|
||||
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free);
|
||||
|
||||
int address_label_configure(AddressLabel *address, Link *link, link_netlink_message_handler_t callback, bool update);
|
||||
int link_set_address_labels(Link *link);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_address_label);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "networkd-address-pool.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
@@ -10,15 +11,14 @@
|
||||
|
||||
static int address_pool_new(
|
||||
Manager *m,
|
||||
AddressPool **ret,
|
||||
int family,
|
||||
const union in_addr_union *u,
|
||||
unsigned prefixlen) {
|
||||
|
||||
AddressPool *p;
|
||||
_cleanup_free_ AddressPool *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(ret);
|
||||
assert(u);
|
||||
|
||||
p = new(AddressPool, 1);
|
||||
@@ -32,15 +32,16 @@ static int address_pool_new(
|
||||
.in_addr = *u,
|
||||
};
|
||||
|
||||
LIST_PREPEND(address_pools, m->address_pools, p);
|
||||
r = ordered_set_ensure_put(&m->address_pools, NULL, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = p;
|
||||
TAKE_PTR(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int address_pool_new_from_string(
|
||||
static int address_pool_new_from_string(
|
||||
Manager *m,
|
||||
AddressPool **ret,
|
||||
int family,
|
||||
const char *p,
|
||||
unsigned prefixlen) {
|
||||
@@ -49,25 +50,38 @@ int address_pool_new_from_string(
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(ret);
|
||||
assert(p);
|
||||
|
||||
r = in_addr_from_string(family, p, &u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return address_pool_new(m, ret, family, &u, prefixlen);
|
||||
return address_pool_new(m, family, &u, prefixlen);
|
||||
}
|
||||
|
||||
void address_pool_free(AddressPool *p) {
|
||||
int address_pool_setup_default(Manager *m) {
|
||||
int r;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
assert(m);
|
||||
|
||||
if (p->manager)
|
||||
LIST_REMOVE(address_pools, p->manager->address_pools, p);
|
||||
/* Add in the well-known private address ranges. */
|
||||
r = address_pool_new_from_string(m, AF_INET6, "fd00::", 8);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
free(p);
|
||||
r = address_pool_new_from_string(m, AF_INET, "192.168.0.0", 16);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = address_pool_new_from_string(m, AF_INET, "172.16.0.0", 12);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = address_pool_new_from_string(m, AF_INET, "10.0.0.0", 8);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool address_pool_prefix_is_taken(
|
||||
@@ -94,7 +108,7 @@ static bool address_pool_prefix_is_taken(
|
||||
}
|
||||
|
||||
/* Don't clash with addresses already pulled from the pool, but not assigned yet */
|
||||
LIST_FOREACH(addresses, a, l->pool_addresses) {
|
||||
SET_FOREACH(a, l->pool_addresses) {
|
||||
if (a->family != p->family)
|
||||
continue;
|
||||
|
||||
@@ -107,7 +121,7 @@ static bool address_pool_prefix_is_taken(
|
||||
ORDERED_HASHMAP_FOREACH(n, p->manager->networks) {
|
||||
Address *a;
|
||||
|
||||
LIST_FOREACH(addresses, a, n->static_addresses) {
|
||||
ORDERED_HASHMAP_FOREACH(a, n->addresses_by_section) {
|
||||
if (a->family != p->family)
|
||||
continue;
|
||||
|
||||
@@ -119,7 +133,7 @@ static bool address_pool_prefix_is_taken(
|
||||
return false;
|
||||
}
|
||||
|
||||
int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) {
|
||||
static int address_pool_acquire_one(AddressPool *p, int family, unsigned prefixlen, union in_addr_union *found) {
|
||||
union in_addr_union u;
|
||||
unsigned i;
|
||||
int r;
|
||||
@@ -128,6 +142,9 @@ int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union
|
||||
assert(prefixlen > 0);
|
||||
assert(found);
|
||||
|
||||
if (p->family != family)
|
||||
return 0;
|
||||
|
||||
if (p->prefixlen >= prefixlen)
|
||||
return 0;
|
||||
|
||||
@@ -153,3 +170,21 @@ int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) {
|
||||
AddressPool *p;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(prefixlen > 0);
|
||||
assert(found);
|
||||
|
||||
ORDERED_SET_FOREACH(p, m->address_pools) {
|
||||
r = address_pool_acquire_one(p, family, prefixlen, found);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
typedef struct AddressPool AddressPool;
|
||||
|
||||
#include "in-addr-util.h"
|
||||
#include "list.h"
|
||||
|
||||
typedef struct Manager Manager;
|
||||
|
||||
struct AddressPool {
|
||||
typedef struct AddressPool {
|
||||
Manager *manager;
|
||||
|
||||
int family;
|
||||
unsigned prefixlen;
|
||||
|
||||
union in_addr_union in_addr;
|
||||
} AddressPool;
|
||||
|
||||
LIST_FIELDS(AddressPool, address_pools);
|
||||
};
|
||||
|
||||
int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen);
|
||||
void address_pool_free(AddressPool *p);
|
||||
|
||||
int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found);
|
||||
int address_pool_setup_default(Manager *m);
|
||||
int address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,26 +3,22 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "in-addr-util.h"
|
||||
|
||||
typedef struct Address Address;
|
||||
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-util.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sd-ipv4acd.h"
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-util.h"
|
||||
|
||||
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
|
||||
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Network Network;
|
||||
typedef struct Link Link;
|
||||
typedef struct NetworkConfigSection NetworkConfigSection;
|
||||
typedef int (*address_ready_callback_t)(Address *address);
|
||||
|
||||
struct Address {
|
||||
typedef struct Address {
|
||||
Network *network;
|
||||
NetworkConfigSection *section;
|
||||
|
||||
@@ -42,39 +38,40 @@ struct Address {
|
||||
|
||||
bool scope_set:1;
|
||||
bool ip_masquerade_done:1;
|
||||
bool manage_temporary_address:1;
|
||||
bool home_address:1;
|
||||
bool prefix_route:1;
|
||||
bool autojoin:1;
|
||||
AddressFamily duplicate_address_detection;
|
||||
|
||||
/* Called when address become ready */
|
||||
address_ready_callback_t callback;
|
||||
|
||||
sd_ipv4acd *acd;
|
||||
|
||||
LIST_FIELDS(Address, addresses);
|
||||
};
|
||||
} Address;
|
||||
|
||||
int address_new(Address **ret);
|
||||
void address_free(Address *address);
|
||||
int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
|
||||
int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
|
||||
Address *address_free(Address *address);
|
||||
int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
|
||||
bool address_exists(Link *link, int family, const union in_addr_union *in_addr);
|
||||
int address_update(Address *address, unsigned char flags, unsigned char scope, const struct ifa_cacheinfo *cinfo);
|
||||
int address_drop(Address *address);
|
||||
int address_configure(Address *address, Link *link, link_netlink_message_handler_t callback, bool update, Address **ret);
|
||||
int address_remove(Address *address, Link *link, link_netlink_message_handler_t callback);
|
||||
bool address_equal(Address *a1, Address *a2);
|
||||
bool address_is_ready(const Address *a);
|
||||
int address_section_verify(Address *a);
|
||||
int configure_ipv4_duplicate_address_detection(Link *link, Address *address);
|
||||
|
||||
int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret);
|
||||
|
||||
DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
|
||||
|
||||
int link_set_addresses(Link *link);
|
||||
int link_drop_addresses(Link *link);
|
||||
int link_drop_foreign_addresses(Link *link);
|
||||
int link_serialize_addresses(Link *link, FILE *f);
|
||||
int link_deserialize_addresses(Link *link, const char *addresses);
|
||||
|
||||
int ipv4_dad_stop(Link *link);
|
||||
int ipv4_dad_update_mac(Link *link);
|
||||
|
||||
int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m);
|
||||
|
||||
void network_drop_invalid_addresses(Network *network);
|
||||
|
||||
void address_hash_func(const Address *a, struct siphash *state);
|
||||
int address_compare_func(const Address *a1, const Address *a2);
|
||||
extern const struct hash_ops address_hash_ops;
|
||||
|
||||
@@ -146,26 +146,26 @@ static int set_brvlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *lin
|
||||
return 1;
|
||||
}
|
||||
|
||||
int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap) {
|
||||
int link_set_bridge_vlan(Link *link) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
sd_netlink *rtnl;
|
||||
uint16_t flags;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(br_vid_bitmap);
|
||||
assert(br_untagged_bitmap);
|
||||
assert(link->network);
|
||||
|
||||
/* pvid might not be in br_vid_bitmap yet */
|
||||
if (pvid)
|
||||
set_bit(pvid, br_vid_bitmap);
|
||||
if (!link->network->use_br_vlan)
|
||||
return 0;
|
||||
|
||||
rtnl = link->manager->rtnl;
|
||||
if (!link->network->bridge && !streq_ptr(link->kind, "bridge"))
|
||||
return 0;
|
||||
|
||||
/* pvid might not be in br_vid_bitmap yet */
|
||||
if (link->network->pvid)
|
||||
set_bit(link->network->pvid, link->network->br_vid_bitmap);
|
||||
|
||||
/* create new RTM message */
|
||||
r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
|
||||
|
||||
@@ -179,14 +179,14 @@ int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32
|
||||
|
||||
/* master needs flag self */
|
||||
if (!link->network->bridge) {
|
||||
flags = BRIDGE_FLAGS_SELF;
|
||||
r = sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(uint16_t));
|
||||
uint16_t flags = BRIDGE_FLAGS_SELF;
|
||||
r = sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(flags));
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not open IFLA_BRIDGE_FLAGS: %m");
|
||||
}
|
||||
|
||||
/* add vlan info */
|
||||
r = append_vlan_info_data(link, req, pvid, br_vid_bitmap, br_untagged_bitmap);
|
||||
r = append_vlan_info_data(link, req, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append VLANs: %m");
|
||||
|
||||
@@ -195,7 +195,7 @@ int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32
|
||||
return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
|
||||
|
||||
/* send message to the kernel */
|
||||
r = netlink_call_async(rtnl, NULL, req, set_brvlan_handler,
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req, set_brvlan_handler,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
Copyright © 2016 BISDN GmbH. All rights reserved.
|
||||
***/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "conf-parser.h"
|
||||
|
||||
#define BRIDGE_VLAN_BITMAP_MAX 4096
|
||||
@@ -14,7 +12,7 @@
|
||||
|
||||
typedef struct Link Link;
|
||||
|
||||
int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap);
|
||||
int link_set_bridge_vlan(Link *link);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_pvid);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_vlan);
|
||||
|
||||
@@ -1,15 +1,231 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_arp.h>
|
||||
|
||||
#include "dhcp-internal.h"
|
||||
#include "dhcp6-internal.h"
|
||||
#include "escape.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "networkd-dhcp-common.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-network.h"
|
||||
#include "parse-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-table.h"
|
||||
#include "strv.h"
|
||||
|
||||
bool link_dhcp_enabled(Link *link, int family) {
|
||||
assert(link);
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
|
||||
if (family == AF_INET6 && !socket_ipv6_is_supported())
|
||||
return false;
|
||||
|
||||
if (link->flags & IFF_LOOPBACK)
|
||||
return false;
|
||||
|
||||
if (!link->network)
|
||||
return false;
|
||||
|
||||
if (link->network->bond)
|
||||
return false;
|
||||
|
||||
if (link->iftype == ARPHRD_CAN)
|
||||
return false;
|
||||
|
||||
return link->network->dhcp & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6);
|
||||
}
|
||||
|
||||
DUID* link_get_duid(Link *link) {
|
||||
if (link->network->duid.type != _DUID_TYPE_INVALID)
|
||||
return &link->network->duid;
|
||||
else
|
||||
return &link->manager->duid;
|
||||
}
|
||||
|
||||
static int duid_set_uuid(DUID *duid, sd_id128_t uuid) {
|
||||
assert(duid);
|
||||
|
||||
if (duid->raw_data_len > 0)
|
||||
return 0;
|
||||
|
||||
if (duid->type != DUID_TYPE_UUID)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(&duid->raw_data, &uuid, sizeof(sd_id128_t));
|
||||
duid->raw_data_len = sizeof(sd_id128_t);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
Manager *manager = userdata;
|
||||
const sd_bus_error *e;
|
||||
const void *a;
|
||||
size_t sz;
|
||||
DUID *duid;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(manager);
|
||||
|
||||
e = sd_bus_message_get_error(m);
|
||||
if (e) {
|
||||
log_error_errno(sd_bus_error_get_errno(e),
|
||||
"Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s",
|
||||
e->message);
|
||||
goto configure;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read_array(m, 'y', &a, &sz);
|
||||
if (r < 0)
|
||||
goto configure;
|
||||
|
||||
if (sz != sizeof(sd_id128_t)) {
|
||||
log_error("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID.");
|
||||
goto configure;
|
||||
}
|
||||
|
||||
memcpy(&manager->product_uuid, a, sz);
|
||||
while ((duid = set_steal_first(manager->duids_requesting_uuid)))
|
||||
(void) duid_set_uuid(duid, manager->product_uuid);
|
||||
|
||||
manager->duids_requesting_uuid = set_free(manager->duids_requesting_uuid);
|
||||
|
||||
configure:
|
||||
while ((link = set_steal_first(manager->links_requesting_uuid))) {
|
||||
link_unref(link);
|
||||
|
||||
r = link_configure(link);
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
}
|
||||
|
||||
manager->links_requesting_uuid = set_free(manager->links_requesting_uuid);
|
||||
|
||||
/* To avoid calling GetProductUUID() bus method so frequently, set the flag below
|
||||
* even if the method fails. */
|
||||
manager->has_product_uuid = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int manager_request_product_uuid(Manager *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->has_product_uuid)
|
||||
return 0;
|
||||
|
||||
log_debug("Requesting product UUID");
|
||||
|
||||
if (link) {
|
||||
DUID *duid;
|
||||
|
||||
assert_se(duid = link_get_duid(link));
|
||||
|
||||
r = set_ensure_put(&m->links_requesting_uuid, NULL, link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
if (r > 0)
|
||||
link_ref(link);
|
||||
|
||||
r = set_ensure_put(&m->duids_requesting_uuid, NULL, duid);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
|
||||
log_debug("Not connected to system bus, requesting product UUID later.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_bus_call_method_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.hostname1",
|
||||
"/org/freedesktop/hostname1",
|
||||
"org.freedesktop.hostname1",
|
||||
"GetProductUUID",
|
||||
get_product_uuid_handler,
|
||||
m,
|
||||
"b",
|
||||
false);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to get product UUID: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool link_requires_uuid(Link *link) {
|
||||
const DUID *duid;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->network);
|
||||
|
||||
duid = link_get_duid(link);
|
||||
if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0)
|
||||
return false;
|
||||
|
||||
if (link_dhcp4_enabled(link) && IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY))
|
||||
return true;
|
||||
|
||||
if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int link_configure_duid(Link *link) {
|
||||
Manager *m;
|
||||
DUID *duid;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->network);
|
||||
|
||||
m = link->manager;
|
||||
duid = link_get_duid(link);
|
||||
|
||||
if (!link_requires_uuid(link))
|
||||
return 1;
|
||||
|
||||
if (m->has_product_uuid) {
|
||||
(void) duid_set_uuid(duid, m->product_uuid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!m->links_requesting_uuid) {
|
||||
r = manager_request_product_uuid(m, link);
|
||||
if (r < 0) {
|
||||
if (r == -ENOMEM)
|
||||
return r;
|
||||
|
||||
log_link_warning_errno(link, r,
|
||||
"Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
r = set_put(m->links_requesting_uuid, link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
if (r > 0)
|
||||
link_ref(link);
|
||||
|
||||
r = set_put(m->duids_requesting_uuid, duid);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#define DHCP_ROUTE_METRIC 1024
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Manager Manager;
|
||||
|
||||
typedef enum DHCPUseDomains {
|
||||
DHCP_USE_DOMAINS_NO,
|
||||
DHCP_USE_DOMAINS_YES,
|
||||
@@ -35,6 +38,18 @@ typedef struct DUID {
|
||||
usec_t llt_time;
|
||||
} DUID;
|
||||
|
||||
bool link_dhcp_enabled(Link *link, int family);
|
||||
static inline bool link_dhcp4_enabled(Link *link) {
|
||||
return link_dhcp_enabled(link, AF_INET);
|
||||
}
|
||||
static inline bool link_dhcp6_enabled(Link *link) {
|
||||
return link_dhcp_enabled(link, AF_INET6);
|
||||
}
|
||||
|
||||
DUID* link_get_duid(Link *link);
|
||||
int link_configure_duid(Link *link);
|
||||
int manager_request_product_uuid(Manager *m, Link *link);
|
||||
|
||||
const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
|
||||
DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
|
||||
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include "sd-dhcp-server.h"
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-dhcp-server.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
@@ -14,6 +19,24 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
static bool link_dhcp4_server_enabled(Link *link) {
|
||||
assert(link);
|
||||
|
||||
if (link->flags & IFF_LOOPBACK)
|
||||
return false;
|
||||
|
||||
if (!link->network)
|
||||
return false;
|
||||
|
||||
if (link->network->bond)
|
||||
return false;
|
||||
|
||||
if (link->iftype == ARPHRD_CAN)
|
||||
return false;
|
||||
|
||||
return link->network->dhcp_server;
|
||||
}
|
||||
|
||||
static Address* link_find_dhcp_server_address(Link *link) {
|
||||
Address *address;
|
||||
|
||||
@@ -21,13 +44,13 @@ static Address* link_find_dhcp_server_address(Link *link) {
|
||||
assert(link->network);
|
||||
|
||||
/* The first statically configured address if there is any */
|
||||
LIST_FOREACH(addresses, address, link->network->static_addresses)
|
||||
ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section)
|
||||
if (address->family == AF_INET &&
|
||||
!in_addr_is_null(address->family, &address->in_addr))
|
||||
return address;
|
||||
|
||||
/* If that didn't work, find a suitable address we got from the pool */
|
||||
LIST_FOREACH(addresses, address, link->pool_addresses)
|
||||
SET_FOREACH(address, link->pool_addresses)
|
||||
if (address->family == AF_INET)
|
||||
return address;
|
||||
|
||||
@@ -230,6 +253,24 @@ int dhcp4_server_configure(Link *link) {
|
||||
Address *address;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!link_dhcp4_server_enabled(link))
|
||||
return 0;
|
||||
|
||||
if (!(link->flags & IFF_UP))
|
||||
return 0;
|
||||
|
||||
if (!link->dhcp_server) {
|
||||
r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_dhcp_server_attach_event(link->dhcp_server, link->manager->event, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
address = link_find_dhcp_server_address(link);
|
||||
if (!address)
|
||||
return log_link_error_errno(link, SYNTHETIC_ERRNO(EBUSY),
|
||||
@@ -341,6 +382,8 @@ int dhcp4_server_configure(Link *link) {
|
||||
r = sd_dhcp_server_start(link->dhcp_server);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m");
|
||||
|
||||
log_link_debug(link, "Offering DHCPv4 leases");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "hostname-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "network-internal.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-dhcp4.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
@@ -384,7 +385,7 @@ static int link_set_dhcp_routes(Link *link) {
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set router: %m");
|
||||
|
||||
LIST_FOREACH(routes, rt, link->network->static_routes) {
|
||||
HASHMAP_FOREACH(rt, link->network->routes_by_section) {
|
||||
if (!rt->gateway_from_dhcp)
|
||||
continue;
|
||||
|
||||
@@ -622,7 +623,7 @@ static int configure_dhcpv4_duplicate_address_detection(Link *link) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_ipv4acd_attach_event(link->network->dhcp_acd, NULL, 0);
|
||||
r = sd_ipv4acd_attach_event(link->network->dhcp_acd, link->manager->event, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -698,7 +699,7 @@ static int dhcp4_address_ready_callback(Address *address) {
|
||||
return r;
|
||||
|
||||
/* Reconfigure static routes as kernel may remove some routes when lease expires. */
|
||||
r = link_request_set_routes(link);
|
||||
r = link_set_routes(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -755,9 +756,9 @@ static int dhcp4_update_address(Link *link, bool announce) {
|
||||
link_set_state(link, LINK_STATE_CONFIGURING);
|
||||
link->dhcp4_configured = false;
|
||||
|
||||
/* address_handler calls link_request_set_routes() and link_request_set_nexthop(). Before they
|
||||
* are called, the related flags must be cleared. Otherwise, the link becomes configured state
|
||||
* before routes are configured. */
|
||||
/* address_handler calls link_set_routes() and link_set_nexthop(). Before they are called, the
|
||||
* related flags must be cleared. Otherwise, the link becomes configured state before routes
|
||||
* are configured. */
|
||||
link->static_routes_configured = false;
|
||||
link->static_nexthops_configured = false;
|
||||
|
||||
@@ -814,7 +815,7 @@ static int dhcp4_update_address(Link *link, bool announce) {
|
||||
addr->cinfo.ifa_valid = lifetime;
|
||||
addr->prefixlen = prefixlen;
|
||||
addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
|
||||
addr->prefix_route = link_prefixroute(link);
|
||||
SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link));
|
||||
|
||||
/* allow reusing an existing address and simply update its lifetime
|
||||
* in case it already exists */
|
||||
@@ -1156,12 +1157,10 @@ static bool promote_secondaries_enabled(const char *ifname) {
|
||||
* the primary one expires it relies on the kernel to promote the
|
||||
* secondary IP. See also https://github.com/systemd/systemd/issues/7163
|
||||
*/
|
||||
int dhcp4_set_promote_secondaries(Link *link) {
|
||||
static int dhcp4_set_promote_secondaries(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
|
||||
|
||||
/* check if the kernel has promote_secondaries enabled for our
|
||||
* interface. If it is not globally enabled or enabled for the
|
||||
@@ -1181,7 +1180,7 @@ int dhcp4_set_promote_secondaries(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp4_set_client_identifier(Link *link) {
|
||||
static int dhcp4_set_client_identifier(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
@@ -1240,6 +1239,25 @@ int dhcp4_set_client_identifier(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp4_init(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (link->dhcp_client)
|
||||
return 0;
|
||||
|
||||
r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_dhcp_client_attach_event(link->dhcp_client, link->manager->event, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp4_configure(Link *link) {
|
||||
sd_dhcp_option *send_option;
|
||||
void *request_options;
|
||||
@@ -1247,19 +1265,17 @@ int dhcp4_configure(Link *link) {
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
|
||||
|
||||
if (!link->dhcp_client) {
|
||||
r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to create DHCP4 client: %m");
|
||||
if (!link_dhcp4_enabled(link))
|
||||
return 0;
|
||||
|
||||
r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to attach event: %m");
|
||||
}
|
||||
r = dhcp4_set_promote_secondaries(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp4_init(link);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to initialize DHCP4 client: %m");
|
||||
|
||||
r = sd_dhcp_client_set_mac(link->dhcp_client,
|
||||
(const uint8_t *) &link->mac,
|
||||
@@ -1419,6 +1435,49 @@ int dhcp4_configure(Link *link) {
|
||||
return dhcp4_set_client_identifier(link);
|
||||
}
|
||||
|
||||
int dhcp4_update_mac(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!link->dhcp_client)
|
||||
return 0;
|
||||
|
||||
r = sd_dhcp_client_set_mac(link->dhcp_client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp4_set_client_identifier(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_deserialize_dhcp4(Link *link, const char *dhcp4_address) {
|
||||
union in_addr_union address;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (isempty(dhcp4_address))
|
||||
return 0;
|
||||
|
||||
r = in_addr_from_string(AF_INET, dhcp4_address, &address);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to parse DHCPv4 address: %s", dhcp4_address);
|
||||
|
||||
r = dhcp4_init(link);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to initialize DHCPv4 client: %m");
|
||||
|
||||
r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to set initial DHCPv4 address %s: %m", dhcp4_address);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_max_attempts(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
||||
@@ -18,8 +18,9 @@ typedef enum DHCPClientIdentifier {
|
||||
} DHCPClientIdentifier;
|
||||
|
||||
int dhcp4_configure(Link *link);
|
||||
int dhcp4_set_client_identifier(Link *link);
|
||||
int dhcp4_set_promote_secondaries(Link *link);
|
||||
int dhcp4_update_mac(Link *link);
|
||||
|
||||
int link_deserialize_dhcp4(Link *link, const char *dhcp4_address);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_acl_ip_address);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "hostname-util.h"
|
||||
#include "missing_network.h"
|
||||
#include "network-internal.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-dhcp6.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
@@ -24,6 +25,15 @@
|
||||
#include "radv-internal.h"
|
||||
#include "web-util.h"
|
||||
|
||||
bool link_dhcp6_pd_is_enabled(Link *link) {
|
||||
assert(link);
|
||||
|
||||
if (!link->network)
|
||||
return false;
|
||||
|
||||
return link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_DHCP6;
|
||||
}
|
||||
|
||||
static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
|
||||
uint32_t lifetime_preferred, lifetime_valid;
|
||||
union in_addr_union pd_prefix;
|
||||
@@ -180,6 +190,9 @@ int dhcp6_pd_remove(Link *link) {
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
|
||||
if (!link_dhcp6_pd_is_enabled(link))
|
||||
return 0;
|
||||
|
||||
link->dhcp6_pd_address_configured = false;
|
||||
link->dhcp6_pd_route_configured = false;
|
||||
|
||||
@@ -342,7 +355,7 @@ static int dhcp6_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = link_request_set_routes(link);
|
||||
r = link_set_routes(link);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return 1;
|
||||
@@ -425,13 +438,6 @@ static int dhcp6_pd_assign_prefix(Link *link, const union in_addr_union *prefix,
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool link_dhcp6_pd_is_enabled(Link *link) {
|
||||
if (!link->network)
|
||||
return false;
|
||||
|
||||
return link->network->router_prefix_delegation & RADV_PREFIX_DELEGATION_DHCP6;
|
||||
}
|
||||
|
||||
static bool link_has_preferred_subnet_id(Link *link) {
|
||||
if (!link->network)
|
||||
return false;
|
||||
@@ -607,9 +613,9 @@ static int dhcp6_pd_finalize(Link *link) {
|
||||
link->dhcp6_pd_address_configured = true;
|
||||
} else {
|
||||
log_link_debug(link, "Setting DHCPv6 PD addresses");
|
||||
/* address_handler calls link_request_set_routes() and link_request_set_nexthop().
|
||||
* Before they are called, the related flags must be cleared. Otherwise, the link
|
||||
* becomes configured state before routes are configured. */
|
||||
/* address_handler calls link_set_routes() and link_set_nexthop(). Before they are
|
||||
* called, the related flags must be cleared. Otherwise, the link becomes configured
|
||||
* state before routes are configured. */
|
||||
link->static_routes_configured = false;
|
||||
link->static_nexthops_configured = false;
|
||||
}
|
||||
@@ -643,9 +649,6 @@ static void dhcp6_pd_prefix_lost(Link *dhcp6_link) {
|
||||
if (link == dhcp6_link)
|
||||
continue;
|
||||
|
||||
if (!link_dhcp6_pd_is_enabled(link))
|
||||
continue;
|
||||
|
||||
r = dhcp6_pd_remove(link);
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
@@ -952,7 +955,7 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = link_request_set_routes(link);
|
||||
r = link_set_routes(link);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return 1;
|
||||
@@ -1075,9 +1078,9 @@ static int dhcp6_lease_ip_acquired(sd_dhcp6_client *client, Link *link) {
|
||||
link->dhcp6_address_configured = true;
|
||||
else {
|
||||
log_link_debug(link, "Setting DHCPv6 addresses");
|
||||
/* address_handler calls link_request_set_routes() and link_request_set_nexthop().
|
||||
* Before they are called, the related flags must be cleared. Otherwise, the link
|
||||
* becomes configured state before routes are configured. */
|
||||
/* address_handler calls link_set_routes() and link_set_nexthop(). Before they are
|
||||
* called, the related flags must be cleared. Otherwise, the link becomes configured
|
||||
* state before routes are configured. */
|
||||
link->static_routes_configured = false;
|
||||
link->static_nexthops_configured = false;
|
||||
}
|
||||
@@ -1343,40 +1346,22 @@ static bool dhcp6_enable_prefix_delegation(Link *dhcp6_link) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int dhcp6_configure(Link *link) {
|
||||
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
|
||||
sd_dhcp6_option *vendor_option;
|
||||
sd_dhcp6_option *send_option;
|
||||
void *request_options;
|
||||
static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) {
|
||||
const DUID *duid;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
assert(client);
|
||||
|
||||
if (link->dhcp6_client)
|
||||
return 0;
|
||||
|
||||
r = sd_dhcp6_client_new(&client);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
r = sd_dhcp6_client_set_mac(client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to create DHCP6 client: %m");
|
||||
|
||||
r = sd_dhcp6_client_attach_event(client, NULL, 0);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to attach event: %m");
|
||||
|
||||
r = sd_dhcp6_client_set_mac(client,
|
||||
(const uint8_t *) &link->mac,
|
||||
sizeof (link->mac), ARPHRD_ETHER);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set MAC address: %m");
|
||||
return r;
|
||||
|
||||
if (link->network->iaid_set) {
|
||||
r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set IAID: %m");
|
||||
return r;
|
||||
}
|
||||
|
||||
duid = link_get_duid(link);
|
||||
@@ -1388,7 +1373,40 @@ int dhcp6_configure(Link *link) {
|
||||
duid->raw_data_len > 0 ? duid->raw_data : NULL,
|
||||
duid->raw_data_len);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set DUID: %m");
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp6_configure(Link *link) {
|
||||
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
|
||||
sd_dhcp6_option *vendor_option;
|
||||
sd_dhcp6_option *send_option;
|
||||
void *request_options;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
|
||||
if (!link_dhcp6_enabled(link) && !link_ipv6_accept_ra_enabled(link))
|
||||
return 0;
|
||||
|
||||
if (link->dhcp6_client)
|
||||
return 0;
|
||||
|
||||
r = sd_dhcp6_client_new(&client);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to create DHCP6 client: %m");
|
||||
|
||||
r = sd_dhcp6_client_attach_event(client, link->manager->event, 0);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to attach event: %m");
|
||||
|
||||
r = dhcp6_set_identifier(link, client);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set identifier: %m");
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp6_client_send_options) {
|
||||
r = sd_dhcp6_client_add_option(client, send_option);
|
||||
@@ -1471,6 +1489,57 @@ int dhcp6_configure(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp6_update_mac(Link *link) {
|
||||
bool restart;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!link->dhcp6_client)
|
||||
return 0;
|
||||
|
||||
restart = sd_dhcp6_client_is_running(link->dhcp6_client) > 0;
|
||||
|
||||
if (restart) {
|
||||
r = sd_dhcp6_client_stop(link->dhcp6_client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dhcp6_set_identifier(link, link->dhcp6_client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (restart) {
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not restart DHCPv6 client: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_serialize_dhcp6_client(Link *link, FILE *f) {
|
||||
_cleanup_free_ char *duid = NULL;
|
||||
uint32_t iaid;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!link->dhcp6_client)
|
||||
return 0;
|
||||
|
||||
r = sd_dhcp6_client_get_iaid(link->dhcp6_client, &iaid);
|
||||
if (r >= 0)
|
||||
fprintf(f, "DHCP6_CLIENT_IAID=0x%x\n", iaid);
|
||||
|
||||
r = sd_dhcp6_client_duid_as_string(link->dhcp6_client, &duid);
|
||||
if (r >= 0)
|
||||
fprintf(f, "DHCP6_CLIENT_DUID=%s\n", duid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp6_pd_hint(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
|
||||
@@ -29,9 +29,12 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6DelegatedPrefix*, dhcp6_pd_free);
|
||||
bool link_dhcp6_pd_is_enabled(Link *link);
|
||||
int dhcp6_pd_remove(Link *link);
|
||||
int dhcp6_configure(Link *link);
|
||||
int dhcp6_update_mac(Link *link);
|
||||
int dhcp6_request_address(Link *link, int ir);
|
||||
int dhcp6_request_prefix_delegation(Link *link);
|
||||
|
||||
int link_serialize_dhcp6_client(Link *link, FILE *f);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_client_start_mode);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user