tcpip.c revision 8561
1/*
2 * $Id: tcpip.c,v 1.1 1995/05/16 02:53:28 jkh Exp $
3 *
4 * Copyright (c) 1995
5 *      Gary J Palmer. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer,
12 *    verbatim and that no modifications are made prior to this
13 *    point in the file.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed by Gary J Palmer
20 *      for the FreeBSD Project.
21 * 4. The name of Gary J Palmer or the FreeBSD Project may not be used to
22 *    endorse or promote products derived from this software without specific
23 *    prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY GARY J PALMER ``AS IS'' AND ANY EXPRESS
26 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL GARY J PALMER BE LIABLE FOR ANY
29 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 */
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <unistd.h>
42#include <sys/param.h>
43#include <string.h>
44#include <dialog.h>
45#include "ui_objects.h"
46#include "dir.h"
47#include "dialog.priv.h"
48#include "colors.h"
49#include "rc.h"
50#include "sysinstall.h"
51
52static char		hostname[256], domainname[256],
53			gateway[32], nameserver[32], iface[8];
54static int		okbutton, cancelbutton;
55static char		ipaddr[32], netmask[32], extras[256];
56
57#define TCP_DIALOG_Y		0
58#define TCP_DIALOG_X		8
59#define TCP_DIALOG_WIDTH	COLS - 16
60#define TCP_DIALOG_HEIGHT	LINES - 2
61
62typedef struct _interface {
63    char ipaddr[32];
64    char netmask[32];
65    char extras[256];
66    Device *dev;
67} Interface;
68
69/* The names and details of the available interfaces, for the list */
70Interface 	if_list[INTERFACE_MAX];
71char		*iface_names[INTERFACE_MAX];
72
73typedef struct _layout {
74    int		y;
75    int		x;
76    int		len;
77    int		maxlen;
78    char	*prompt;
79    char	*help;
80    void	*var;
81    int		type;
82    void	*obj;
83} Layout;
84
85static Layout layout[] = {
86{ 1, 2, 25, 255,
87      "Host name:", "The name of your machine on a network, e.g. foo.bar.com",
88      hostname, STRINGOBJ, NULL },
89{ 1, 35, 20, 255,
90      "Domain name:",
91      "The name of the domain that your machine is in, e.g. bar.com",
92      domainname, STRINGOBJ, NULL },
93{ 5, 2, 18, 15,
94      "Gateway:",
95      "IP address of host forwarding packets to non-local hosts or nets",
96      gateway, STRINGOBJ, NULL },
97{ 5, 35, 18, 15,
98      "Name server:", "IP address of your local DNS server",
99      nameserver, STRINGOBJ, NULL },
100{ 9, 2, 9, 6,
101      "Interface:", "One of potentially several network interfaces",
102      iface, LISTOBJ, NULL },
103{ 10, 18, 18, 15,
104      "IP Address:",
105      "The IP address to be used for your host - use 127.0.0.1 for loopback",
106      ipaddr, STRINGOBJ, NULL },
107{ 10, 37, 18, 15,
108      "Netmask:",
109      "The netmask for your network, e.g. 0xffffff00 for a class C network",
110      netmask, STRINGOBJ, NULL },
111{ 14, 18, 37, 255,
112      "Extra options to ifconfig:",
113      "Any options to ifconfig you'd like to specify manually",
114      extras, STRINGOBJ, NULL },
115{ 19, 10, 0, 0,
116      "OK", "Select this if you are happy with these settings",
117      &okbutton, BUTTONOBJ, NULL },
118{ 19, 30, 0, 0,
119      "CANCEL", "Select this if you wish to cancel this screen",
120      &cancelbutton, BUTTONOBJ, NULL },
121{ NULL },
122};
123
124#define _validByte(b) ((b) > 0 && (b) < 255)
125
126static void
127feepout(char *msg)
128{
129    beep();
130    dialog_notify(msg);
131}
132
133static int
134verifyIP(char *ip)
135{
136    int a, b, c, d;
137
138    if (ip && sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
139	_validByte(a) && _validByte(b) && _validByte(c) &&
140	_validByte(d))
141	return 1;
142    else
143	return 0;
144}
145
146static int
147verifySettings(void)
148{
149    if (!hostname[0])
150	feepout("Must specify a host name of some sort!");
151    else if (!verifyIP(ipaddr))
152	feepout("Invalid or missing value for IP address");
153    else if (gateway[0] && !verifyIP(gateway))
154	feepout("Invalid gateway IP address specified");
155    else if (nameserver[0] && !verifyIP(nameserver))
156	feepout("Invalid name server IP address specified");
157    else if (netmask[0] < '0' || netmask[0] > '9')
158	feepout("Invalid or missing netmask");
159    else
160	return 1;
161    return 0;
162}
163
164/* This is it - how to get TCP setup values */
165int
166tcpOpenDialog(char *str)
167{
168    WINDOW              *ds_win;
169    ComposeObj          *obj = NULL;
170    ComposeObj		*first, *last;
171    int                 n=0, quit=FALSE, cancel=FALSE, ret,
172    			max, n_iface;
173    char                *tmp;
174    Device		**devs;
175    char		old_iface[8];
176
177    ds_win = newwin(LINES, COLS, 0, 0);
178    if (ds_win == 0)
179	msgFatal("Cannot open TCP/IP dialog window!!");
180
181    devs = deviceFind(NULL, DEVICE_TYPE_NETWORK);
182    if (!devs) {
183	msgConfirm("Couldn't find any potential network devices!");
184	return 0;
185    }
186
187    while (devs[n] != NULL) {
188	iface_names[n] = (devs[n])->name;
189	++n;
190    }
191    n_iface = --n;
192
193    draw_box(ds_win, TCP_DIALOG_Y, TCP_DIALOG_X,
194	     TCP_DIALOG_HEIGHT, TCP_DIALOG_WIDTH,
195	     dialog_attr, border_attr);
196    wattrset(ds_win, dialog_attr);
197    mvwaddstr(ds_win, TCP_DIALOG_Y, TCP_DIALOG_X + 20,
198	      " Network Configuration ");
199    draw_box(ds_win, TCP_DIALOG_Y + 9, TCP_DIALOG_X + 16,
200	     TCP_DIALOG_HEIGHT - 13, TCP_DIALOG_WIDTH - 21,
201	     dialog_attr, border_attr);
202    wattrset(ds_win, dialog_attr);
203    mvwaddstr(ds_win, TCP_DIALOG_Y + 9, TCP_DIALOG_X + 24,
204	      " Per Interface Configuration ");
205
206
207    strcpy(ipaddr, if_list[0].ipaddr);
208    strcpy(netmask, if_list[0].netmask);
209    strcpy(extras, if_list[0].extras);
210
211    tmp = getenv(VAR_HOSTNAME);
212    if (tmp)
213	strcpy(hostname, tmp);
214    else
215	bzero(hostname, sizeof(hostname));
216    tmp = getenv(VAR_DOMAINNAME);
217    if (tmp)
218	strcpy(domainname, tmp);
219    else
220	bzero(domainname, sizeof(domainname));
221    tmp = getenv(VAR_GATEWAY);
222    if (tmp)
223	strcpy(gateway, tmp);
224    else
225	bzero(gateway, sizeof(gateway));
226    tmp = getenv(VAR_NAMESERVER);
227    if (tmp)
228	strcpy(nameserver, tmp);
229    else
230	bzero(nameserver, sizeof(nameserver));
231
232    n = 0;
233#define lt layout[n]
234    while (lt.help != NULL) {
235	switch (lt.type) {
236	case STRINGOBJ:
237	    lt.obj = NewStringObj(ds_win, lt.prompt, lt.var,
238				  lt.y + TCP_DIALOG_Y, lt.x + TCP_DIALOG_X,
239				  lt.len, lt.maxlen);
240	    break;
241
242	case BUTTONOBJ:
243	    lt.obj = NewButtonObj(ds_win, lt.prompt, lt.var,
244				  lt.y + TCP_DIALOG_Y, lt.x + TCP_DIALOG_X);
245	    break;
246
247	case LISTOBJ:
248	    lt.obj = NewListObj(ds_win, lt.prompt, (char **) iface_names,
249				lt.var, lt.y + TCP_DIALOG_Y,
250				lt.x + TCP_DIALOG_X, lt.len, 12, n_iface);
251	    break;
252	default:
253	    msgFatal("Don't support this object yet!");
254	}
255	AddObj(&obj, lt.type, (void *) lt.obj);
256	n++;
257    }
258    max = n - 1;
259
260    last = obj;
261    while (last->next)
262	last = last->next;
263
264    /* find the first object in the list */
265    first = obj;
266    while (first->prev)
267	first = first->prev;
268
269    n = 0;
270    cancelbutton = okbutton = 0;
271    strcpy(iface, iface_names[0]);
272    strcpy(old_iface, iface);
273
274    while (!quit) {
275	char help_line[80];
276	int i, len = strlen(lt.help);
277
278	for (i = 0; i < 79; i++)
279	    help_line[i] = (i < len) ? lt.help[i] : ' ';
280	help_line[i] = '\0';
281	use_helpline(help_line);
282	display_helpline(ds_win, LINES - 1, COLS - 1);
283
284	ret = PollObj(&obj);
285
286	switch (ret) {
287	case SEL_ESC:
288	    quit = TRUE, cancel=TRUE;
289	    break;
290
291	case KEY_UP:
292	    if (obj->prev !=NULL ) {
293		obj = obj->prev;
294		--n;
295	    } else {
296		obj = last;
297		n = max;
298	    }
299	    break;
300
301	case KEY_DOWN:
302	    if (n == 7) {
303		n = 4;
304		obj = (((first->next)->next)->next)->next;
305	    } else if (obj->next != NULL) {
306		obj = obj->next;
307		++n;
308	    } else {
309		obj = first;
310		n = 0;
311	    }
312	    break;
313
314	case SEL_TAB:
315	    if (n == 7) {
316		n = 4;
317		obj = (((first->next)->next)->next)->next;
318	    } else if (obj->next != NULL) {
319		++n;
320	    } else {
321		n = 0;
322	    }
323	    if (n == 5) {
324		n = 8;
325		obj = ((obj->next)->next)->next;
326	    }
327	    break;
328
329	case SEL_BUTTON:
330 	    if (cancelbutton) {
331		cancel = TRUE, quit = TRUE;
332	    } else {
333		if (verifySettings())
334		    quit = TRUE;
335	    }
336	    break;
337
338	case SEL_CR:
339	    if (strcmp(old_iface, iface)) {
340		/* First, find the old value */
341		n_iface = 0;
342		while (strcmp(old_iface, iface_names[n_iface]) &&
343		       (iface_names[n_iface] != NULL))
344		    ++n_iface;
345
346		if (iface_names[n_iface] == NULL)
347		    msgFatal("Erk - run off the end of the list of interfaces!");
348		strcpy(if_list[n_iface].ipaddr, ipaddr);
349		strcpy(if_list[n_iface].netmask, netmask);
350		strcpy(if_list[n_iface].extras, extras);
351
352		/* Now go find the new location */
353		n_iface = 0;
354		while (strcmp(iface, iface_names[n_iface]) &&
355		       (iface_names[n_iface] != NULL))
356		    ++n_iface;
357		if (iface_names[n_iface] == NULL)
358		    msgFatal("Erk - run off the end of the list of interfaces!");
359		strcpy(ipaddr, if_list[n_iface].ipaddr);
360		strcpy(netmask, if_list[n_iface].netmask);
361		strcpy(extras, if_list[n_iface].extras);
362
363		RefreshStringObj(layout[5].obj);
364		RefreshStringObj(layout[6].obj);
365		RefreshStringObj(layout[7].obj);
366
367		strcpy(old_iface, iface);
368	    }
369
370	    if (n == 7) {
371		n = 4;
372		obj = (((first->next)->next)->next)->next;
373	    } else if (n < max)
374		++n;
375	    else
376		n = 0;
377	    break;
378
379	case SEL_BACKTAB:
380	    if (n)
381		--n;
382	    else
383		n = max;
384	    break;
385
386	default:
387	    beep();
388	}
389
390	if (n == 1) {
391	    if ((tmp = index(hostname, '.')) != NULL) {
392		strncpy(domainname, tmp + 1, strlen(tmp + 1));
393		domainname[strlen(tmp+1)] = '\0';
394		RefreshStringObj(layout[1].obj);
395	    }
396	}
397    }
398
399    dialog_clear();
400    refresh();
401
402    if (!cancel) {
403	variable_set2(VAR_HOSTNAME, hostname);
404	variable_set2(VAR_DOMAINNAME, domainname);
405	if (gateway[0])
406	    variable_set2(VAR_GATEWAY, gateway);
407	if (nameserver[0])
408	    variable_set2(VAR_NAMESERVER, nameserver);
409	return 1;
410    }
411
412    return 0;
413}
414