~kobe24-lixiang/ubiquity-ubuntukylin/trunk

« back to all changes in this revision

Viewing changes to d-i/source/netcfg/write_interface.c

  • Committer: kobe
  • Date: 2014-08-22 06:37:21 UTC
  • Revision ID: xiangli@ubuntukylin.com-20140822063721-p145o500i2y7o48h
first version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Functions to write things into /etc/network/interfaces
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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
 
17
 */
 
18
 
 
19
#include "netcfg.h"
 
20
#include <errno.h>
 
21
#include <string.h>
 
22
#include <stdlib.h>
 
23
#include <sys/types.h>
 
24
#include <sys/stat.h>
 
25
#include <unistd.h>
 
26
#include <fcntl.h>
 
27
#include <debian-installer.h>
 
28
 
 
29
static int nc_wi_header(FILE *fd)
 
30
{
 
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");
 
33
        
 
34
        return 1;
 
35
}
 
36
 
 
37
static int nc_wi_loopback(const struct netcfg_interface *interface, FILE *fd)
 
38
{
 
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);
 
42
        
 
43
        return 1;
 
44
}
 
45
 
 
46
static int nc_wi_wireless_options(const struct netcfg_interface *interface, FILE *fd)
 
47
{
 
48
        /*
 
49
         * Write wireless-tools options
 
50
         */
 
51
        /* FIXME: Whether this is a wireless interface should be stored
 
52
         * with the interface
 
53
         */
 
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);
 
57
        } else {
 
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");
 
63
 
 
64
                if (interface->wepkey != NULL)
 
65
                        fprintf(fd, "\twireless-key1 %s\n", interface->wepkey);
 
66
        }
 
67
 
 
68
        return 1;
 
69
}
 
70
 
 
71
/* Write out a DHCP stanza for the given interface
 
72
 */
 
73
static int nc_wi_dhcp(const struct netcfg_interface *interface, FILE *fd)
 
74
{
 
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);
 
80
        }
 
81
 
 
82
        return 1;
 
83
}
 
84
 
 
85
/* Write out a SLAAC stanza for the given interface
 
86
 */
 
87
static int nc_wi_slaac(const struct netcfg_interface *interface, FILE *fd)
 
88
{
 
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);
 
94
        }
 
95
 
 
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");*/
 
100
 
 
101
        return 1;
 
102
}
 
103
 
 
104
/* Write out a static IPv4 config stanza for the given interface
 
105
 */
 
106
static int nc_wi_static_ipv4(const struct netcfg_interface *interface, FILE *fd)
 
107
{
 
108
        char network[INET_ADDRSTRLEN];
 
109
        char broadcast[INET_ADDRSTRLEN];
 
110
        char netmask[INET_ADDRSTRLEN];
 
111
 
 
112
        netcfg_network_address(interface, network);
 
113
        netcfg_broadcast_address(interface, broadcast);
 
114
        inet_mtop(AF_INET, interface->masklen, netmask, INET_ADDRSTRLEN);
 
115
 
 
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);
 
128
 
 
129
        return 1;
 
130
}
 
131
 
 
132
/* Write out a static IPv6 config stanza for the given interface
 
133
 */
 
134
static int nc_wi_static_ipv6(const struct netcfg_interface *interface, FILE *fd)
 
135
{
 
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);
 
143
 
 
144
        return 1;
 
145
}
 
146
 
 
147
/* The main function for writing things to INTERFACES_FILE (aka
 
148
 * /etc/network/interfaces).
 
149
 *
 
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. 
 
152
 * In practice...
 
153
 *
 
154
 * Takes the interface struct to write out.  If you pass NULL, the file gets
 
155
 * deleted and a helpful comment header gets written.
 
156
 *
 
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.
 
160
 */
 
161
int netcfg_write_interface(const struct netcfg_interface *interface)
 
162
{
 
163
        FILE *fd;
 
164
        int rv;
 
165
        struct stat stat_buf;
 
166
        
 
167
        if (!interface) {
 
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));
 
172
                        return 0;
 
173
                }
 
174
        }
 
175
        
 
176
        fd = file_open(INTERFACES_FILE ".tmp", "w");
 
177
        if (!fd) {
 
178
                di_warning("Failed to open %s.tmp: %s", INTERFACES_FILE, strerror(errno));
 
179
                return 0;
 
180
        }
 
181
 
 
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.
 
186
         */
 
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");
 
191
                return 0;
 
192
        }
 
193
        if (rv == 0) {
 
194
                char *tmpbuf = malloc(stat_buf.st_size + 1);
 
195
                int origfd;
 
196
                origfd = open(INTERFACES_FILE, O_RDONLY);
 
197
                if (origfd < 0) {
 
198
                        di_warning("Failed to open %s: %s", INTERFACES_FILE, strerror(errno));
 
199
                        fclose(fd);
 
200
                        unlink(INTERFACES_FILE ".tmp");
 
201
                        free(tmpbuf);
 
202
                        return 0;
 
203
                }
 
204
                rv = read(origfd, tmpbuf, stat_buf.st_size);
 
205
                if (rv < 0) {
 
206
                        di_warning("Failed to read %s: %s", INTERFACES_FILE, strerror(errno));
 
207
                        fclose(fd);
 
208
                        unlink(INTERFACES_FILE ".tmp");
 
209
                        free(tmpbuf);
 
210
                        close(origfd);
 
211
                        return 0;
 
212
                }
 
213
                if (rv != stat_buf.st_size) {
 
214
                        di_warning("Short read on %s", INTERFACES_FILE);
 
215
                        fclose(fd);
 
216
                        unlink(INTERFACES_FILE ".tmp");
 
217
                        free(tmpbuf);
 
218
                        close(origfd);
 
219
                        return 0;
 
220
                }
 
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);
 
224
                        fclose(fd);
 
225
                        unlink(INTERFACES_FILE ".tmp");
 
226
                        free(tmpbuf);
 
227
                        close(origfd);
 
228
                        return 0;
 
229
                }
 
230
                free(tmpbuf);
 
231
                close(origfd);
 
232
        }
 
233
                
 
234
        
 
235
        /* Thank $DEITY all that's out of the way... now we can write a
 
236
         * freaking interfaces file entry */
 
237
        rv = 1;
 
238
 
 
239
        if (!interface) {
 
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);
 
249
                }
 
250
                if (interface->slaac == 1) {
 
251
                        di_debug("Writing SLAAC stanza for %s", interface->name);
 
252
                        rv = nc_wi_slaac(interface, fd);
 
253
                }
 
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);
 
260
        }
 
261
        
 
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);
 
265
        }
 
266
 
 
267
        if (rv) {
 
268
                di_debug("Success!");
 
269
                rename(INTERFACES_FILE ".tmp", INTERFACES_FILE);
 
270
        }
 
271
 
 
272
        fclose(fd);
 
273
        unlink(INTERFACES_FILE ".tmp");
 
274
        return rv;
 
275
}