#include <ctype.h>
#include <net/if.h>
-#include "networkd.h"
-#include "networkd-netdev.h"
-#include "networkd-link.h"
-#include "network-internal.h"
#include "path-util.h"
#include "conf-files.h"
#include "conf-parser.h"
#include "util.h"
+#include "networkd.h"
+#include "networkd-netdev.h"
+#include "networkd-link.h"
+#include "network-internal.h"
static int network_load_one(Manager *manager, const char *filename) {
_cleanup_network_free_ Network *network = NULL;
LIST_HEAD_INIT(network->static_addresses);
LIST_HEAD_INIT(network->static_routes);
+ LIST_HEAD_INIT(network->static_fdb_entries);
network->stacked_netdevs = hashmap_new(&string_hash_ops);
if (!network->stacked_netdevs)
if (!network->routes_by_section)
return log_oom();
+ network->fdb_entries_by_section = hashmap_new(NULL);
+ if (!network->fdb_entries_by_section)
+ return log_oom();
+
network->filename = strdup(filename);
if (!network->filename)
return log_oom();
- network->dhcp = DHCP_SUPPORT_NONE;
+ network->dhcp = ADDRESS_FAMILY_NO;
network->dhcp_ntp = true;
network->dhcp_dns = true;
network->dhcp_hostname = true;
network->llmnr = LLMNR_SUPPORT_YES;
r = config_parse(NULL, filename, file,
- "Match\0Network\0Address\0Route\0DHCP\0DHCPv4\0",
+ "Match\0"
+ "Link\0"
+ "Network\0"
+ "Address\0"
+ "Route\0"
+ "DHCP\0"
+ "DHCPv4\0"
+ "Bridge\0"
+ "BridgeFDB\0",
config_item_perf_lookup, network_network_gperf_lookup,
false, false, true, network);
if (r < 0)
return r;
+ /* IPMasquerade=yes implies IPForward=yes */
+ if (network->ip_masquerade)
+ network->ip_forward |= ADDRESS_FAMILY_IPV4;
+
LIST_PREPEND(networks, manager->networks, network);
LIST_FOREACH(routes, route, network->static_routes) {
network_free(network);
r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
- if (r < 0) {
- log_error("Failed to enumerate network files: %s", strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to enumerate network files: %m");
STRV_FOREACH_BACKWARDS(f, files) {
r = network_load_one(manager, *f);
NetDev *netdev;
Route *route;
Address *address;
+ FdbEntry *fdb_entry;
Iterator i;
if (!network)
free(network->description);
free(network->dhcp_vendor_class_identifier);
+ free(network->mac);
+
strv_free(network->ntp);
strv_free(network->dns);
strv_free(network->domains);
while ((address = network->static_addresses))
address_free(address);
+ while ((fdb_entry = network->static_fdb_entries))
+ fdb_entry_free(fdb_entry);
+
hashmap_free(network->addresses_by_section);
hashmap_free(network->routes_by_section);
+ hashmap_free(network->fdb_entries_by_section);
if (network->manager && network->manager->networks)
LIST_REMOVE(networks, network->manager->networks, network);
udev_device_get_property_value(device, "ID_NET_DRIVER"),
udev_device_get_devtype(device),
ifname)) {
- log_debug("%-*s: found matching network '%s'", IFNAMSIZ, ifname,
- network->filename);
+ if (network->match_name) {
+ const char *attr;
+ uint8_t name_assign_type = NET_NAME_UNKNOWN;
+
+ attr = udev_device_get_sysattr_value(device, "name_assign_type");
+ if (attr)
+ (void)safe_atou8(attr, &name_assign_type);
+
+ if (name_assign_type == NET_NAME_ENUM)
+ log_warning("%-*s: found matching network '%s', based on potentially unpredictable ifname",
+ IFNAMSIZ, ifname, network->filename);
+ else
+ log_debug("%-*s: found matching network '%s'", IFNAMSIZ, ifname, network->filename);
+ } else
+ log_debug("%-*s: found matching network '%s'", IFNAMSIZ, ifname, network->filename);
+
*ret = network;
return 0;
}
break;
case NETDEV_KIND_VLAN:
case NETDEV_KIND_MACVLAN:
+ case NETDEV_KIND_IPVLAN:
case NETDEV_KIND_VXLAN:
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
if (r < 0) {
if (netdev->kind != NETDEV_KIND_IPIP &&
netdev->kind != NETDEV_KIND_SIT &&
netdev->kind != NETDEV_KIND_GRE &&
- netdev->kind != NETDEV_KIND_VTI) {
+ netdev->kind != NETDEV_KIND_GRETAP &&
+ netdev->kind != NETDEV_KIND_IP6GRE &&
+ netdev->kind != NETDEV_KIND_IP6GRETAP &&
+ netdev->kind != NETDEV_KIND_VTI &&
+ netdev->kind != NETDEV_KIND_IP6TNL
+ ) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"NetDev is not a tunnel, ignoring assignment: %s", rvalue);
return 0;
return 0;
}
-static const char* const dhcp_support_table[_DHCP_SUPPORT_MAX] = {
- [DHCP_SUPPORT_NONE] = "none",
- [DHCP_SUPPORT_BOTH] = "both",
- [DHCP_SUPPORT_V4] = "v4",
- [DHCP_SUPPORT_V6] = "v6",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(dhcp_support, DHCPSupport);
-
int config_parse_dhcp(
const char* unit,
const char *filename,
void *data,
void *userdata) {
- DHCPSupport *dhcp = data;
- int k;
+ AddressFamilyBoolean *dhcp = data, s;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- /* Our enum shall be a superset of booleans, hence first try
- * to parse as boolean, and then as enum */
-
- k = parse_boolean(rvalue);
- if (k > 0)
- *dhcp = DHCP_SUPPORT_BOTH;
- else if (k == 0)
- *dhcp = DHCP_SUPPORT_NONE;
- else {
- DHCPSupport s;
-
- s = dhcp_support_from_string(rvalue);
- if (s < 0){
- log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse DHCP option, ignoring: %s", rvalue);
+ /* Note that this is mostly like
+ * config_parse_address_family_boolean(), except that it
+ * understands some old names for the enum values */
+
+ s = address_family_boolean_from_string(rvalue);
+ if (s < 0) {
+
+ /* Previously, we had a slightly different enum here,
+ * support its values for compatbility. */
+
+ if (streq(rvalue, "none"))
+ s = ADDRESS_FAMILY_NO;
+ else if (streq(rvalue, "v4"))
+ s = ADDRESS_FAMILY_IPV4;
+ else if (streq(rvalue, "v6"))
+ s = ADDRESS_FAMILY_IPV6;
+ else if (streq(rvalue, "both"))
+ s = ADDRESS_FAMILY_YES;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse DHCP option, ignoring: %s", rvalue);
return 0;
}
-
- *dhcp = s;
}
+ *dhcp = s;
return 0;
}