From 54942477d5d0066b7d37650420e2d7f834dd1d9e Mon Sep 17 00:00:00 2001 From: Mathieu Trudel-Lapierre Date: Fri, 26 May 2017 15:29:16 -0400 Subject: 1.142ubuntu2 (patches unapplied) Imported using git-ubuntu import. --- base-installer.d/40netcfg | 4 +- debian/changelog | 8 ++ debian/netcfg-common.templates | 6 + debian/netcfg.dirs | 1 + dhcp.c | 2 +- netcfg-common.c | 4 +- netcfg.h | 3 +- static.c | 2 +- write_interface.c | 290 +++++++++++++++++++++++++++++++++-------- 9 files changed, 262 insertions(+), 58 deletions(-) diff --git a/base-installer.d/40netcfg b/base-installer.d/40netcfg index 0bbffd5..6ce418a 100755 --- a/base-installer.d/40netcfg +++ b/base-installer.d/40netcfg @@ -1,11 +1,11 @@ #!/bin/sh -e # Copy all relevant networking-related files to /target. -if [ ! -f /etc/network/interfaces ]; then +if [ ! -f /etc/network/interfaces ] && [ ! -f /etc/netplan/*.yaml ]; then netcfg write_loopback fi -for file in /etc/network/interfaces /etc/networks /etc/hostname /etc/hosts; do +for file in /etc/network/interfaces /etc/networks /etc/hostname /etc/hosts /etc/netplan/*.yaml; do if [ -f "$file" ]; then mkdir /target/$(dirname $file) -p cp $file /target/$file diff --git a/debian/netcfg-common.templates b/debian/netcfg-common.templates index 0ca1ec7..6e42847 100644 --- a/debian/netcfg-common.templates +++ b/debian/netcfg-common.templates @@ -415,3 +415,9 @@ _Choices: ${essid_list} Enter ESSID manually _Description: Wireless network: Select the wireless network to use during the installation process. +Template: netcfg/do_not_use_netplan +Type: boolean +Default: false +Description: for internal use; can be preseeded + Set to false to fallback to ifupdown. + diff --git a/debian/netcfg.dirs b/debian/netcfg.dirs index dad6088..d548c6e 100644 --- a/debian/netcfg.dirs +++ b/debian/netcfg.dirs @@ -1,5 +1,6 @@ bin etc/network +etc/netplan usr/lib/base-installer.d usr/lib/post-base-installer.d lib/netcfg diff --git a/dhcp.c b/dhcp.c index b72a805..8824580 100644 --- a/dhcp.c +++ b/dhcp.c @@ -611,7 +611,7 @@ int netcfg_activate_dhcp (struct debconfclient *client, struct netcfg_interface di_debug("Network config complete"); netcfg_write_common("", hostname, domain); netcfg_write_loopback(); - netcfg_write_interface(interface); + netcfg_write_interface(client, interface); netcfg_write_resolv(domain, interface); #if !defined(__FreeBSD_kernel__) kill_dhcp_client(); diff --git a/netcfg-common.c b/netcfg-common.c index dafbf1a..d747450 100644 --- a/netcfg-common.c +++ b/netcfg-common.c @@ -1133,8 +1133,8 @@ void netcfg_write_loopback (void) lo.name = LO_IF; lo.loopback = 1; - netcfg_write_interface(NULL); - netcfg_write_interface(&lo); + netcfg_write_interface(NULL, NULL); + netcfg_write_interface(NULL, &lo); } /* diff --git a/netcfg.h b/netcfg.h index 19fe710..ae3f34c 100644 --- a/netcfg.h +++ b/netcfg.h @@ -2,6 +2,7 @@ #define _NETCFG_H_ #define INTERFACES_FILE "/etc/network/interfaces" +#define NETPLAN_YAML "/etc/netplan/01-netcfg.yaml" #define HOSTS_FILE "/etc/hosts" #define HOSTNAME_FILE "/etc/hostname" #define NETWORKS_FILE "/etc/networks" @@ -267,7 +268,7 @@ extern int nc_v6_interface_configured(const struct netcfg_interface *interface, extern int nc_v6_get_config_flags(struct debconfclient *client, struct netcfg_interface *interface); /* write_interfaces.c */ -extern int netcfg_write_interface(const struct netcfg_interface *interface); +extern int netcfg_write_interface(struct debconfclient *client, const struct netcfg_interface *interface); /* rdnssd.c */ extern int start_rdnssd(struct debconfclient *client); diff --git a/static.c b/static.c index e375dd4..b73b785 100644 --- a/static.c +++ b/static.c @@ -680,7 +680,7 @@ int netcfg_get_static(struct debconfclient *client, struct netcfg_interface *ifa } netcfg_write_common(iface->ipaddress, hostname, domain); netcfg_write_loopback(); - netcfg_write_interface(iface); + netcfg_write_interface(client, iface); netcfg_write_resolvconf_options(domain, iface); netcfg_write_resolv(domain, iface); } diff --git a/write_interface.c b/write_interface.c index 012ffb7..14d36e1 100644 --- a/write_interface.c +++ b/write_interface.c @@ -24,8 +24,20 @@ #include #include #include +#include #include +static int nc_wi_netplan_header(FILE *fd) +{ + fprintf(fd, "# This file describes the network interfaces available on your system\n"); + fprintf(fd, "# For more information, see netplan(5).\n"); + fprintf(fd, "network:\n"); + fprintf(fd, " version: 2\n"); + fprintf(fd, " renderer: networkd\n"); + + return 1; +} + static int nc_wi_header(FILE *fd) { fprintf(fd, "# This file describes the network interfaces available on your system\n"); @@ -57,6 +69,19 @@ static int nc_wi_vlan(const struct netcfg_interface *interface, FILE *fd) return rv; } +static int nc_wi_netplan_vlan(const struct netcfg_interface *interface, FILE *fd) +{ + int rv; + rv = 1; + + fprintf(fd, " vlans:\n"); + fprintf(fd, " %s:\n", interface->name); + fprintf(fd, " link: %s\n", interface->parentif); + fprintf(fd, " id: %d\n", interface->vlanid); + + return rv; +} + static int nc_wi_wireless_options(const struct netcfg_interface *interface, FILE *fd) { @@ -83,6 +108,29 @@ static int nc_wi_wireless_options(const struct netcfg_interface *interface, FILE return 1; } +static int nc_wi_netplan_wireless_aps(const struct netcfg_interface *interface, FILE *fd) +{ + fprintf(fd, " access-points:\n"); + + if (interface->essid && *interface->essid) { + fprintf(fd, " %s:\n", interface->essid); + } else { + fprintf(fd, " any:\n"); + } + + if (interface->wpa_supplicant_status == WPA_QUEUED) { + fprintf(fd, " password: %s\n", interface->passphrase); + } else { + fprintf(fd, " mode: %s\n", + (interface->mode == MANAGED) ? "infrastructure" : "adhoc"); + + if (interface->wepkey != NULL) + fprintf(fd, " password: %s\n", interface->wepkey); + } + + return 1; +} + /* Write out a DHCP stanza for the given interface */ static int nc_wi_dhcp(const struct netcfg_interface *interface, FILE *fd) @@ -134,6 +182,17 @@ static int nc_wi_static_ipv4(const struct netcfg_interface *interface, FILE *fd) return 1; } +static int nc_wi_netplan_static_ipv4(const struct netcfg_interface *interface, FILE *fd) +{ + fprintf(fd, " addresses: [ %s/%i ]\n", interface->ipaddress, + empty_str(interface->pointopoint) ? interface->masklen : 32); + if (!empty_str(interface->gateway)) + fprintf(fd, " gateway4: %s\n", + empty_str(interface->pointopoint) ? interface->gateway : interface->pointopoint); + + return 1; +} + /* Write out a static IPv6 config stanza for the given interface */ static int nc_wi_static_ipv6(const struct netcfg_interface *interface, FILE *fd) @@ -148,6 +207,131 @@ static int nc_wi_static_ipv6(const struct netcfg_interface *interface, FILE *fd) return 1; } +static int nc_wi_netplan_static_ipv6(const struct netcfg_interface *interface, FILE *fd) +{ + fprintf(fd, " addresses: [ %s/%i ]\n", interface->ipaddress, interface->masklen); + if (!empty_str(interface->gateway)) + fprintf(fd, " gateway6: %s\n", interface->gateway); + + return 1; +} + +static int nc_wi_write_eni(const struct netcfg_interface *interface, FILE *fd) +{ + int rv; + + rv = 1; + + di_debug("Using /etc/network/interfaces for network config"); + + if (!interface) { + di_debug("Writing informative header"); + rv = nc_wi_header(fd); + } else if (interface->loopback == 1) { + di_debug("Writing loopback interface"); + rv = nc_wi_loopback(interface, fd); + } else if (interface->dhcp == 1 || interface->slaac == 1) { + if (interface->dhcp == 1) { + di_debug("Writing DHCP stanza for %s", interface->name); + rv = nc_wi_dhcp(interface, fd); + } + if (interface->slaac == 1) { + di_debug("Writing SLAAC stanza for %s", interface->name); + rv = nc_wi_slaac(interface, fd); + } + } else if (interface->address_family == AF_INET) { + di_debug("Writing static IPv4 stanza for %s", interface->name); + rv = nc_wi_static_ipv4(interface, fd); + } else if (interface->address_family == AF_INET6) { + di_debug("Writing static IPv6 stanza for %s", interface->name); + rv = nc_wi_static_ipv6(interface, fd); + } + if (rv && interface && interface->parentif) { + di_debug("Writing VLAN: %s", interface->name); + rv = nc_wi_vlan(interface, fd); + } + if (rv && interface && is_wireless_iface(interface->name)) { + di_debug("Writing wireless options for %s", interface->name); + rv = nc_wi_wireless_options(interface, fd); + } + + return rv; +} + +static int nc_wi_write_netplan_yaml(const struct netcfg_interface *interface, FILE *fd, off_t size) +{ + int rv; + + rv = 1; + + di_warning("Using netplan for network config"); + + if (size <= 0) + rv = nc_wi_netplan_header(fd); + + /* No interface given, just clear the file */ + if (!interface) + return rv; + + /* With netplan, let loopback alone */ + if (interface->loopback == 1) + return rv; + + if (is_wireless_iface(interface->name)) { + fprintf(fd, " wifis:\n"); + } else { + fprintf(fd, " ethernets:\n"); + } + + /* Take care of handling VLANs correctly */ + fprintf(fd, " %s:\n", interface->parentif ? interface->parentif : interface->name); + + if (rv && interface && interface->parentif) { + /* Make sure our parent doesn't get an IP */ + fprintf(fd, " dhcp4: no\n"); + fprintf(fd, " dhcp6: no\n"); + + di_debug("Writing VLAN: %s", interface->name); + rv = nc_wi_netplan_vlan(interface, fd); + } + + if (interface->dhcp == 1 || interface->slaac == 1) { + if (interface->dhcp == 1) { + di_debug("Writing DHCP stanza for %s", interface->name); + fprintf(fd, " dhcp4: yes\n"); + } + if (interface->slaac == 1) { + di_debug("Writing SLAAC stanza for %s", interface->name); + fprintf(fd, " dhcp6: yes\n"); + } + + } + + /* Write all other static addresses */ + if (interface->address_family == AF_INET) { + di_debug("Writing static IPv4 stanza for %s", interface->name); + rv = nc_wi_netplan_static_ipv4(interface, fd); + } else if (interface->address_family == AF_INET) { + di_debug("Writing static IPv6 stanza for %s", interface->name); + rv = nc_wi_netplan_static_ipv6(interface, fd); + } + + if (rv && interface && is_wireless_iface(interface->name)) { + di_debug("Writing wireless options for %s", interface->name); + rv = nc_wi_netplan_wireless_aps(interface, fd); + } + + return rv; +} + +void unlink_config_tmp_file(int use_netplan) +{ + if (use_netplan) + unlink(NETPLAN_YAML ".tmp"); + else + unlink(INTERFACES_FILE ".tmp"); +} + /* The main function for writing things to INTERFACES_FILE (aka * /etc/network/interfaces). * @@ -162,24 +346,48 @@ static int nc_wi_static_ipv6(const struct netcfg_interface *interface, FILE *fd) * returned, the interfaces file will not have been modified, and errno will * contain the details. */ -int netcfg_write_interface(const struct netcfg_interface *interface) +int netcfg_write_interface(struct debconfclient *client, const struct netcfg_interface *interface) { FILE *fd; int rv; struct stat stat_buf; - + int use_netplan; + char *config_file_path; + + use_netplan = 1; + + if (client) { + debconf_get(client,"netcfg/do_not_use_netplan"); + } + + /* If this undocumented debconf key is set to true, skip netplan + * and fallback to /e/n/i as before. + */ + if (!client || !strcmp(client->value, "false")) { + config_file_path = NETPLAN_YAML; + } else { + use_netplan = 0; + config_file_path = INTERFACES_FILE; + } + + di_warning("Using %s", config_file_path); + if (!interface) { - di_debug("No interface given; clearing " INTERFACES_FILE); - rv = unlink(INTERFACES_FILE); + di_debug("No interface given; clearing %s", config_file_path); + rv = unlink(config_file_path); if (rv < 0 && errno != ENOENT) { - di_info("Error clearing %s: %s", INTERFACES_FILE, strerror(errno)); + di_info("Error clearing %s: %s", config_file_path, strerror(errno)); return 0; } } - fd = file_open(INTERFACES_FILE ".tmp", "w"); + if (use_netplan) + fd = file_open(NETPLAN_YAML ".tmp", "w"); + else + fd = file_open(INTERFACES_FILE ".tmp", "w"); + if (!fd) { - di_warning("Failed to open %s.tmp: %s", INTERFACES_FILE, strerror(errno)); + di_warning("Failed to open %s.tmp: %s", config_file_path, strerror(errno)); return 0; } @@ -188,45 +396,45 @@ int netcfg_write_interface(const struct netcfg_interface *interface) * so we can add our new stuff to it. Bloody longwinded way of doing * it, I'm sure you'll agree. */ - rv = stat(INTERFACES_FILE, &stat_buf); + rv = stat(config_file_path, &stat_buf); if (rv < 0 && errno != ENOENT) { - di_warning("Failed to stat %s: %s", INTERFACES_FILE, strerror(errno)); - unlink(INTERFACES_FILE ".tmp"); + di_warning("Failed to stat %s: %s", config_file_path, strerror(errno)); + unlink_config_tmp_file(use_netplan); return 0; } if (rv == 0) { char *tmpbuf = malloc(stat_buf.st_size + 1); int origfd; - origfd = open(INTERFACES_FILE, O_RDONLY); + origfd = open(config_file_path, O_RDONLY); if (origfd < 0) { - di_warning("Failed to open %s: %s", INTERFACES_FILE, strerror(errno)); + di_warning("Failed to open %s: %s", config_file_path, strerror(errno)); fclose(fd); - unlink(INTERFACES_FILE ".tmp"); + unlink_config_tmp_file(use_netplan); free(tmpbuf); return 0; } rv = read(origfd, tmpbuf, stat_buf.st_size); if (rv < 0) { - di_warning("Failed to read %s: %s", INTERFACES_FILE, strerror(errno)); + di_warning("Failed to read %s: %s", config_file_path, strerror(errno)); fclose(fd); - unlink(INTERFACES_FILE ".tmp"); + unlink_config_tmp_file(use_netplan); free(tmpbuf); close(origfd); return 0; } if (rv != stat_buf.st_size) { - di_warning("Short read on %s", INTERFACES_FILE); + di_warning("Short read on %s", config_file_path); fclose(fd); - unlink(INTERFACES_FILE ".tmp"); + unlink_config_tmp_file(use_netplan); free(tmpbuf); close(origfd); return 0; } rv = fwrite(tmpbuf, sizeof(char), stat_buf.st_size, fd); if (rv != (int)stat_buf.st_size) { - di_warning("Short write on %s.tmp", INTERFACES_FILE); + di_warning("Short write on %s.tmp", config_file_path); fclose(fd); - unlink(INTERFACES_FILE ".tmp"); + unlink_config_tmp_file(use_netplan); free(tmpbuf); close(origfd); return 0; @@ -240,43 +448,23 @@ int netcfg_write_interface(const struct netcfg_interface *interface) * freaking interfaces file entry */ rv = 1; - if (!interface) { - di_debug("Writing informative header"); - rv = nc_wi_header(fd); - } else if (interface->loopback == 1) { - di_debug("Writing loopback interface"); - rv = nc_wi_loopback(interface, fd); - } else if (interface->dhcp == 1 || interface->slaac == 1) { - if (interface->dhcp == 1) { - di_debug("Writing DHCP stanza for %s", interface->name); - rv = nc_wi_dhcp(interface, fd); - } - if (interface->slaac == 1) { - di_debug("Writing SLAAC stanza for %s", interface->name); - rv = nc_wi_slaac(interface, fd); - } - } else if (interface->address_family == AF_INET) { - di_debug("Writing static IPv4 stanza for %s", interface->name); - rv = nc_wi_static_ipv4(interface, fd); - } else if (interface->address_family == AF_INET6) { - di_debug("Writing static IPv6 stanza for %s", interface->name); - rv = nc_wi_static_ipv6(interface, fd); - } - if (rv && interface && interface->parentif) { - di_debug("Writing VLAN: %s", interface->name); - rv = nc_wi_vlan(interface, fd); - } - if (rv && interface && is_wireless_iface(interface->name)) { - di_debug("Writing wireless options for %s", interface->name); - rv = nc_wi_wireless_options(interface, fd); + if (use_netplan) { + rv = nc_wi_write_netplan_yaml(interface, fd, stat_buf.st_size); + } else { + rv = nc_wi_write_eni(interface, fd); } - if (rv) { + if (rv) di_debug("Success!"); + + if (use_netplan) + rename(NETPLAN_YAML ".tmp", NETPLAN_YAML); + else rename(INTERFACES_FILE ".tmp", INTERFACES_FILE); - } fclose(fd); - unlink(INTERFACES_FILE ".tmp"); + + unlink_config_tmp_file(use_netplan); + return rv; } -- cgit v1.1