2
* Functions to write things into /etc/network/interfaces
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
#include <sys/types.h>
27
#include <debian-installer.h>
29
static int nc_wi_header(FILE *fd)
31
fprintf(fd, "# This file describes the network interfaces available on your system\n");
32
fprintf(fd, "# and how to activate them. For more information, see interfaces(5).\n");
37
static int nc_wi_loopback(const struct netcfg_interface *interface, FILE *fd)
39
fprintf(fd, "\n# The loopback network interface\n");
40
fprintf(fd, "auto %s\n", interface->name);
41
fprintf(fd, "iface %s inet loopback\n", interface->name);
46
static int nc_wi_wireless_options(const struct netcfg_interface *interface, FILE *fd)
49
* Write wireless-tools options
51
/* FIXME: Whether this is a wireless interface should be stored
54
if (interface->wpa_supplicant_status == WPA_QUEUED) {
55
fprintf(fd, "\twpa-ssid %s\n", interface->essid);
56
fprintf(fd, "\twpa-psk %s\n", interface->passphrase);
58
fprintf(fd, "\t# wireless-* options are implemented by the wireless-tools package\n");
59
fprintf(fd, "\twireless-mode %s\n",
60
(interface->mode == MANAGED) ? "managed" : "ad-hoc");
61
fprintf(fd, "\twireless-essid %s\n",
62
(interface->essid && *interface->essid) ? interface->essid : "any");
64
if (interface->wepkey != NULL)
65
fprintf(fd, "\twireless-key1 %s\n", interface->wepkey);
71
/* Write out a DHCP stanza for the given interface
73
static int nc_wi_dhcp(const struct netcfg_interface *interface, FILE *fd)
75
fprintf(fd, "\n# The primary network interface\n");
76
fprintf(fd, "auto %s\n", interface->name);
77
fprintf(fd, "iface %s inet dhcp\n", interface->name);
78
if (!empty_str(interface->dhcp_hostname)) {
79
fprintf(fd, "\thostname %s\n", interface->dhcp_hostname);
85
/* Write out a SLAAC stanza for the given interface
87
static int nc_wi_slaac(const struct netcfg_interface *interface, FILE *fd)
89
if (interface->dhcp == 0)
90
fprintf(fd, "\n# The primary network interface\n");
91
fprintf(fd, "# This is an autoconfigured IPv6 interface\n");
92
if (interface->dhcp == 0) {
93
fprintf(fd, "auto %s\n", interface->name);
96
fprintf(fd, "iface %s inet6 auto\n", interface->name);
97
/* fprintf(fd, "\t# Activate RFC 4941 privacy extensions for outgoing connections. The\n");
98
fprintf(fd, "\t# machine will still be reachable via its EUI-64 interface identifier.\n");
99
fprintf(fd, "\tprivext 2\n");*/
104
/* Write out a static IPv4 config stanza for the given interface
106
static int nc_wi_static_ipv4(const struct netcfg_interface *interface, FILE *fd)
108
char network[INET_ADDRSTRLEN];
109
char broadcast[INET_ADDRSTRLEN];
110
char netmask[INET_ADDRSTRLEN];
112
netcfg_network_address(interface, network);
113
netcfg_broadcast_address(interface, broadcast);
114
inet_mtop(AF_INET, interface->masklen, netmask, INET_ADDRSTRLEN);
116
fprintf(fd, "\n# The primary network interface\n");
117
fprintf(fd, "auto %s\n", interface->name);
118
fprintf(fd, "iface %s inet static\n", interface->name);
119
fprintf(fd, "\taddress %s\n", interface->ipaddress);
120
fprintf(fd, "\tnetmask %s\n", empty_str(interface->pointopoint) ? netmask : "255.255.255.255");
121
fprintf(fd, "\tnetwork %s\n", network);
122
fprintf(fd, "\tbroadcast %s\n", broadcast);
123
if (!empty_str(interface->gateway))
124
fprintf(fd, "\tgateway %s\n",
125
empty_str(interface->pointopoint) ? interface->gateway : interface->pointopoint);
126
if (!empty_str(interface->pointopoint))
127
fprintf(fd, "\tpointopoint %s\n", interface->pointopoint);
132
/* Write out a static IPv6 config stanza for the given interface
134
static int nc_wi_static_ipv6(const struct netcfg_interface *interface, FILE *fd)
136
fprintf(fd, "\n# The primary network interface\n");
137
fprintf(fd, "auto %s\n", interface->name);
138
fprintf(fd, "iface %s inet6 static\n", interface->name);
139
fprintf(fd, "\taddress %s\n", interface->ipaddress);
140
fprintf(fd, "\tnetmask %i\n", interface->masklen);
141
if (!empty_str(interface->gateway))
142
fprintf(fd, "\tgateway %s\n", interface->gateway);
147
/* The main function for writing things to INTERFACES_FILE (aka
148
* /etc/network/interfaces).
150
* In principle, this function is very simple: just examine the interface
151
* we've been passed, and call out to the relevant private helper function.
154
* Takes the interface struct to write out. If you pass NULL, the file gets
155
* deleted and a helpful comment header gets written.
157
* Returns a true/false boolean representing "did everything go OK"; if 0 is
158
* returned, the interfaces file will not have been modified, and errno will
159
* contain the details.
161
int netcfg_write_interface(const struct netcfg_interface *interface)
165
struct stat stat_buf;
168
di_debug("No interface given; clearing " INTERFACES_FILE);
169
rv = unlink(INTERFACES_FILE);
170
if (rv < 0 && errno != ENOENT) {
171
di_info("Error clearing %s: %s", INTERFACES_FILE, strerror(errno));
176
fd = file_open(INTERFACES_FILE ".tmp", "w");
178
di_warning("Failed to open %s.tmp: %s", INTERFACES_FILE, strerror(errno));
182
/* All of this code is to handle the apparently simple task of
183
* copying the existing interfaces file to the tmpfile (if it exists)
184
* so we can add our new stuff to it. Bloody longwinded way of doing
185
* it, I'm sure you'll agree.
187
rv = stat(INTERFACES_FILE, &stat_buf);
188
if (rv < 0 && errno != ENOENT) {
189
di_warning("Failed to stat %s: %s", INTERFACES_FILE, strerror(errno));
190
unlink(INTERFACES_FILE ".tmp");
194
char *tmpbuf = malloc(stat_buf.st_size + 1);
196
origfd = open(INTERFACES_FILE, O_RDONLY);
198
di_warning("Failed to open %s: %s", INTERFACES_FILE, strerror(errno));
200
unlink(INTERFACES_FILE ".tmp");
204
rv = read(origfd, tmpbuf, stat_buf.st_size);
206
di_warning("Failed to read %s: %s", INTERFACES_FILE, strerror(errno));
208
unlink(INTERFACES_FILE ".tmp");
213
if (rv != stat_buf.st_size) {
214
di_warning("Short read on %s", INTERFACES_FILE);
216
unlink(INTERFACES_FILE ".tmp");
221
rv = fwrite(tmpbuf, sizeof(char), stat_buf.st_size, fd);
222
if (rv != (int)stat_buf.st_size) {
223
di_warning("Short write on %s.tmp", INTERFACES_FILE);
225
unlink(INTERFACES_FILE ".tmp");
235
/* Thank $DEITY all that's out of the way... now we can write a
236
* freaking interfaces file entry */
240
di_debug("Writing informative header");
241
rv = nc_wi_header(fd);
242
} else if (interface->loopback == 1) {
243
di_debug("Writing loopback interface");
244
rv = nc_wi_loopback(interface, fd);
245
} else if (interface->dhcp == 1 || interface->slaac == 1) {
246
if (interface->dhcp == 1) {
247
di_debug("Writing DHCP stanza for %s", interface->name);
248
rv = nc_wi_dhcp(interface, fd);
250
if (interface->slaac == 1) {
251
di_debug("Writing SLAAC stanza for %s", interface->name);
252
rv = nc_wi_slaac(interface, fd);
254
} else if (interface->address_family == AF_INET) {
255
di_debug("Writing static IPv4 stanza for %s", interface->name);
256
rv = nc_wi_static_ipv4(interface, fd);
257
} else if (interface->address_family == AF_INET6) {
258
di_debug("Writing static IPv6 stanza for %s", interface->name);
259
rv = nc_wi_static_ipv6(interface, fd);
262
if (rv && interface && is_wireless_iface(interface->name)) {
263
di_debug("Writing wireless options for %s", interface->name);
264
rv = nc_wi_wireless_options(interface, fd);
268
di_debug("Success!");
269
rename(INTERFACES_FILE ".tmp", INTERFACES_FILE);
273
unlink(INTERFACES_FILE ".tmp");