]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - release/sysinstall/network.c
Defensive coding to prevent a potential segfault.
[FreeBSD/FreeBSD.git] / release / sysinstall / network.c
1 /*
2  * The new sysinstall program.
3  *
4  * This is probably the last attempt in the `sysinstall' line, the next
5  * generation being slated to essentially a complete rewrite.
6  *
7  * $FreeBSD$
8  *
9  * Copyright (c) 1995
10  *      Jordan Hubbard.  All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer,
17  *    verbatim and that no modifications are made prior to this
18  *    point in the file.
19  *
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  *
24  * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  */
37
38 /* These routines deal with getting things off of network media */
39
40 #include "sysinstall.h"
41 #include <signal.h>
42 #include <termios.h>
43 #include <sys/fcntl.h>
44 #include <sys/ioctl.h>
45 #include <sys/stat.h>
46
47 static Boolean  networkInitialized;
48 static pid_t    startPPP(Device *devp);
49
50 static pid_t    pppPID;
51
52 Boolean
53 mediaInitNetwork(Device *dev)
54 {
55     int i;
56     char *rp;
57     char *cp, ifconfig[255];
58
59     if (!RunningAsInit || networkInitialized)
60         return TRUE;
61
62     if (isDebug())
63         msgDebug("Init routine called for network device %s.\n", dev->name);
64
65     if (!file_readable("/etc/resolv.conf")) {
66         if (DITEM_STATUS(configResolv(NULL)) == DITEM_FAILURE) {
67             msgConfirm("Can't seem to write out /etc/resolv.conf.  Net cannot be used.");
68             return FALSE;
69         }
70     }
71
72     /* Old PPP process lying around? */
73     if (pppPID) {
74         msgNotify("Killing previous PPP process %d.", pppPID);
75         kill(pppPID, SIGTERM);
76         pppPID = 0;
77     }
78     if (!strncmp("ppp", dev->name, 3)) {        /* PPP? */
79         if (!(pppPID = startPPP(dev))) {
80             msgConfirm("Unable to start PPP!  This installation method cannot be used.");
81             return FALSE;
82         }
83         networkInitialized = TRUE;
84         return TRUE;
85     }
86     else if (!strncmp("sl", dev->name, 2)) {    /* SLIP? */
87         char *val;
88         char attach[256];
89
90         dialog_clear_norefresh();
91         /* Cheesy slip attach */
92         snprintf(attach, 256, "slattach -a -h -l -s 9600 %s", dev->devname);
93         val = msgGetInput(attach,
94                           "Warning:  SLIP is rather poorly supported in this revision\n"
95                           "of the installation due to the lack of a dialing utility.\n"
96                           "If you can use PPP for this instead then you're much better\n"
97                           "off doing so, otherwise SLIP works fairly well for *hardwired*\n"
98                           "links.  Please edit the following slattach command for\n"
99                           "correctness (default here is: VJ compression, Hardware flow-\n"
100                           "control, ignore carrier and 9600 baud data rate).  When you're\n"
101                           "ready, press [ENTER] to execute it.");
102         if (!val) {
103             msgConfirm("slattach command was empty.  Try again!");
104             return FALSE;
105         }
106         else
107             SAFE_STRCPY(attach, val);
108         /*
109          * Doing this with vsystem() is actually bogus since we should be storing the pid of slattach
110          * for later killing.  It's just too convenient to call vsystem(), however, rather than
111          * constructing a proper argument for exec() so we punt on doing slip right for now.
112          */
113         if (vsystem(attach)) {
114             msgConfirm("slattach returned a bad status!  Please verify that\n"
115                        "the command is correct and try this operation again.");
116             return FALSE;
117         }
118     }
119
120     snprintf(ifconfig, 255, "%s%s", VAR_IFCONFIG, dev->name);
121     cp = variable_get(ifconfig);
122     if (!cp) {
123         msgConfirm("The %s device is not configured.  You will need to do so\n"
124                    "in the Networking configuration menu before proceeding.", dev->name);
125         return FALSE;
126     }
127     else if (!strcmp(cp, "DHCP"))
128         goto bail;
129     msgNotify("ifconfig %s %s", dev->name, cp);
130     i = vsystem("ifconfig %s %s", dev->name, cp);
131     if (i) {
132         msgConfirm("Unable to configure the %s interface!\n"
133                    "This installation method cannot be used.", dev->name);
134         return FALSE;
135     }
136
137     rp = variable_get(VAR_GATEWAY);
138     if (!rp || *rp == '0') {
139         msgConfirm("No gateway has been set. You may be unable to access hosts\n"
140                    "not on your local network");
141     }
142     else {
143         msgNotify("Adding default route to %s.", rp);
144         vsystem("route -n add default %s", rp);
145     }
146 bail:
147     if (isDebug())
148         msgDebug("Network initialized successfully.\n");
149     networkInitialized = TRUE;
150     return TRUE;
151 }
152
153 void
154 mediaShutdownNetwork(Device *dev)
155 {
156     char *cp;
157
158     if (!RunningAsInit || !networkInitialized)
159         return;
160
161     msgDebug("Shutdown called for network device %s\n", dev->name);
162     /* Not a serial device? */
163     if (strncmp("sl", dev->name, 2) && strncmp("ppp", dev->name, 3)) {
164         int i;
165         char ifconfig[255];
166
167         snprintf(ifconfig, 255, "%s%s", VAR_IFCONFIG, dev->name);
168         cp = variable_get(ifconfig);
169         if (!cp)
170             return;
171         msgNotify("ifconfig %s down", dev->name);
172         i = vsystem("ifconfig %s down", dev->name);
173         if (i)
174             msgConfirm("Warning: Unable to down the %s interface properly", dev->name);
175         cp = variable_get(VAR_GATEWAY);
176         if (cp) {
177             msgNotify("Deleting default route.");
178             vsystem("route -n delete default");
179         }
180     }
181     else if (pppPID) {
182         msgNotify("Killing previous PPP process %d.", pppPID);
183         kill(pppPID, SIGTERM);
184         pppPID = 0;
185     }
186     networkInitialized = FALSE;
187 }
188
189 /* Start PPP on the 3rd screen */
190 static pid_t
191 startPPP(Device *devp)
192 {
193     int fd2, pulse;
194     FILE *fp;
195     char *val;
196     pid_t pid = 0;
197     char myaddr[16], provider[16], speed[16], authname[32], authkey[16];
198     char phone[16];
199
200     /* These are needed to make ppp work */
201     Mkdir("/var/log");
202     Mkdir("/var/run");
203     Mkdir("/var/spool/lock");
204     Mkdir("/etc/ppp");
205
206     dialog_clear_norefresh();
207     if (!variable_get(VAR_SERIAL_SPEED))
208         variable_set2(VAR_SERIAL_SPEED, "115200", 0);
209     /* Get any important user values */
210     val = variable_get_value(VAR_SERIAL_SPEED,
211                       "Enter the baud rate for your modem - this can be higher than the actual\n"
212                       "maximum data rate since most modems can talk at one speed to the\n"
213                       "computer and at another speed to the remote end.\n\n"
214                       "If you're not sure what to put here, just select the default.", 0);
215     SAFE_STRCPY(speed, (val && *val) ? val : "115200");
216
217     val = variable_get(VAR_GATEWAY);
218     SAFE_STRCPY(provider, (val && *val) ? val : "0");
219
220     dialog_clear_norefresh();
221     val = msgGetInput(provider, "Enter the IP address of your service provider or 0 if you\n"
222                       "don't know it and would prefer to negotiate it dynamically.");
223     SAFE_STRCPY(provider, (val && *val) ? val : "0");
224
225     if (devp->private && ((DevInfo *)devp->private)->ipaddr[0])
226         SAFE_STRCPY(myaddr, ((DevInfo *)devp->private)->ipaddr);
227     else
228         strcpy(myaddr, "0");
229
230     if (!Fake)
231         fp = fopen("/etc/ppp/ppp.linkup", "w");
232     else
233         fp = fopen("/dev/stderr", "w");
234     if (fp != NULL) {
235         fprintf(fp, "MYADDR:\n");
236         fprintf(fp, " delete ALL\n");
237         fprintf(fp, " add 0 0 HISADDR\n");
238         fchmod(fileno(fp), 0755);
239         fclose(fp);
240     }
241     if (!Fake)
242         fd2 = open("/etc/ppp/ppp.secret", O_CREAT);
243     else
244         fd2 = -1;
245     if (fd2 != -1) {
246         fchmod(fd2, 0700);
247         close(fd2);
248     }
249     if (!Fake)
250         fp = fopen("/etc/ppp/ppp.conf", "a");
251     else
252         fp = fopen("/dev/stderr", "w");
253     if (!fp) {
254         msgConfirm("Couldn't open /etc/ppp/ppp.conf file!  This isn't going to work");
255         return 0;
256     }
257     authname[0] = '\0';
258     pulse = 0;
259     dialog_clear_norefresh();
260     if (!dialog_yesno("", "Does your ISP support PAP or CHAP ppp logins?", -1, -1)) {
261         val = msgGetInput(NULL, "Enter the name you use to login to your provider.");
262         SAFE_STRCPY(authname, val);
263         dialog_clear_norefresh();
264         val = msgGetInput(NULL, "Enter the password you use to login to your provider.");
265         SAFE_STRCPY(authkey, val);
266         dialog_clear_norefresh();
267         val = msgGetInput(NULL, "Enter the your provider's login phone number.");
268         SAFE_STRCPY(phone, val);
269         dialog_clear_norefresh();
270         pulse = dialog_yesno("", "Does your telephone line support tone dialing?", -1, -1);
271     }
272     fprintf(fp, "\ninstall:\n");
273     fprintf(fp, " set speed %s\n", speed);
274     fprintf(fp, " set device %s\n", devp->devname);
275     fprintf(fp, " set ifaddr %s %s\n", myaddr, provider);
276     fprintf(fp, " set timeout 0\n");
277     fprintf(fp, " enable dns\n");
278     fprintf(fp, " set log local phase\n");
279     if(authname[0] != '\0'){
280         fprintf(fp, " set dial \"ABORT BUSY ABORT NO\\\\sCARRIER TIMEOUT 5 \\\"\\\" AT OK-AT-OK ATE1Q0 OK \\\\dATD%c\\\\T TIMEOUT 40 CONNECT\"\n", pulse ? 'P' : 'T');
281         fprintf(fp, " set login\n");
282         fprintf(fp, " set authname %s\n", authname);
283         fprintf(fp, " set authkey %s\n", authkey);
284         fprintf(fp, " set phone %s\n", phone);
285     }
286     if (fchmod(fileno(fp), 0600) != 0)
287         msgConfirm("Warning: Failed to fix permissions on /etc/ppp/ppp.conf !");
288     fclose(fp);
289
290     /* Make the ppp config persistent */
291     variable_set2(VAR_PPP_ENABLE, "YES", 0);
292     variable_set2(VAR_PPP_PROFILE, "install", 0);
293
294     if (!Fake && !file_readable("/dev/tun0") && mknod("/dev/tun0", 0600 | S_IFCHR, makedev(52, 0))) {
295         msgConfirm("Warning:  No /dev/tun0 device.  PPP will not work!");
296         return 0;
297     }
298
299     if (isDebug())
300         msgDebug("About to start PPP on device %s @ %s baud.  Provider = %s\n", devp->devname, speed, provider);
301
302     if (!Fake && !(pid = fork())) {
303         int i, fd;
304         struct termios foo;
305         extern int login_tty(int);
306
307         for (i = getdtablesize(); i >= 0; i--)
308             close(i);
309
310         /* We're going over to VTY2 */
311         fd = open("/dev/ttyv2", O_RDWR);
312         ioctl(0, TIOCSCTTY, &fd);
313         dup2(0, 1);
314         dup2(0, 2);
315         DebugFD = 2;
316         if (login_tty(fd) == -1)
317             msgDebug("ppp: Can't set the controlling terminal.\n");
318         signal(SIGTTOU, SIG_IGN);
319         if (tcgetattr(fd, &foo) != -1) {
320             foo.c_cc[VERASE] = '\010';
321             if (tcsetattr(fd, TCSANOW, &foo) == -1)
322                 msgDebug("ppp: Unable to set the erase character.\n");
323         }
324         else
325             msgDebug("ppp: Unable to get the terminal attributes!\n");
326         execlp("ppp", "ppp", "install", (char *)NULL);
327         msgDebug("PPP process failed to exec!\n");
328         exit(1);
329     }
330     else {
331         dialog_clear_norefresh();
332         msgConfirm("NOTICE: The PPP command is now started on VTY3 (type ALT-F3 to\n"
333            "interact with it, ALT-F1 to switch back here). If you are using\n"
334            "a PAP or CHAP login simply enter \"dial\", otherwise you'll need\n"
335            "to use the \"term\" command which starts a terminal emulator\n"
336            "which you can use to talk to your modem and dial the service\n"
337            "provider.  Once you're connected, come back to this screen and\n"
338            "press return.\n\n"
339            "DO NOT PRESS [ENTER] HERE UNTIL THE CONNECTION IS FULLY\n"
340            "ESTABLISHED!");
341     }
342     return pid;
343 }