add/re-enable at_wini debug output
[minix3.git] / servers / inet / inet_config.c
blob5c1b68caa82020c3a07550ffa6d4ac217f6f60bf
1 /*
2 inet/inet_config.c
4 Created: Nov 11, 1992 by Philip Homburg
6 Modified: Apr 07, 2001 by Kees J. Bot
7 Read the configuration file and fill in the xx_conf[] arrays.
9 Copyright 1995 Philip Homburg
12 #define _MINIX_SOURCE 1
13 #define _POSIX_SOURCE 1
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <minix/type.h>
23 #include <minix/sysutil.h>
24 #include <minix/syslib.h>
25 #include "inet_config.h"
27 struct eth_conf eth_conf[IP_PORT_MAX];
28 struct psip_conf psip_conf[IP_PORT_MAX];
29 struct ip_conf ip_conf[IP_PORT_MAX];
30 struct tcp_conf tcp_conf[IP_PORT_MAX];
31 struct udp_conf udp_conf[IP_PORT_MAX];
32 dev_t ip_dev;
34 int eth_conf_nr;
35 int psip_conf_nr;
36 int ip_conf_nr;
37 int tcp_conf_nr;
38 int udp_conf_nr;
40 int ip_forward_directed_bcast= 0; /* Default is off */
42 static u8_t iftype[IP_PORT_MAX]; /* Interface in use as? */
43 static int ifdefault= -1; /* Default network interface. */
45 static void fatal(char *label)
47 printf("init: %s: %s\n", label, strerror(errno));
48 exit(1);
51 static void check_rm(char *device)
52 /* Check if a device is not among the living. */
54 if (unlink(device) < 0) {
55 if (errno == ENOENT) return;
56 fatal(device);
58 printf("rm %s\n", device);
61 static void check_mknod(char *device, mode_t mode, int minor)
62 /* Check if a device exists with the proper device number. */
64 struct stat st;
65 dev_t dev;
67 dev= (ip_dev & 0xFF00) | minor;
69 if (stat(device, &st) < 0) {
70 if (errno != ENOENT) fatal(device);
71 } else {
72 if (S_ISCHR(st.st_mode) && st.st_rdev == dev) return;
73 if (unlink(device) < 0) fatal(device);
76 if (mknod(device, S_IFCHR | mode, dev) < 0) fatal(device);
77 printf("mknod %s c %d %d\n", device, (ip_dev >> 8), minor);
80 static void check_ln(char *old, char *new)
81 /* Check if 'old' and 'new' are still properly linked. */
83 struct stat st_old, st_new;
85 if (stat(old, &st_old) < 0) fatal(old);
86 if (stat(new, &st_new) < 0) {
87 if (errno != ENOENT) fatal(new);
88 } else {
89 if (st_new.st_dev == st_old.st_dev
90 && st_new.st_ino == st_old.st_ino) {
91 return;
93 if (unlink(new) < 0) fatal(new);
96 if (link(old, new) < 0) fatal(new);
97 printf("ln %s %s\n", old, new);
100 static void check_dev(int type, int ifno)
101 /* Check if the device group with interface number 'ifno' exists and has the
102 * proper device numbers. If 'type' is -1 then the device group must be
103 * removed.
106 static struct devlist {
107 char *defname;
108 mode_t mode;
109 u8_t minor_off;
110 } devlist[] = {
111 { "/dev/eth", 0600, ETH_DEV_OFF },
112 { "/dev/psip", 0600, PSIP_DEV_OFF },
113 { "/dev/ip", 0600, IP_DEV_OFF },
114 { "/dev/tcp", 0666, TCP_DEV_OFF },
115 { "/dev/udp", 0666, UDP_DEV_OFF },
117 struct devlist *dvp;
118 int i;
119 char device[sizeof("/dev/psip99")];
120 char *dp;
122 for (i= 0; i < sizeof(devlist) / sizeof(devlist[0]); i++) {
123 dvp= &devlist[i];
124 strcpy(device, dvp->defname);
125 dp= device + strlen(device);
126 if (ifno >= 10) *dp++ = '0' + (ifno / 10);
127 *dp++ = '0' + (ifno % 10);
128 *dp = 0;
130 if (type == 0
131 || (i == 0 && type != NETTYPE_ETH)
132 || (i == 1 && type != NETTYPE_PSIP)
134 check_rm(device);
135 if (ifno == ifdefault) check_rm(dvp->defname);
136 } else {
137 check_mknod(device, dvp->mode,
138 if2minor(ifno, dvp->minor_off));
139 if (ifno == ifdefault) check_ln(device, dvp->defname);
142 check_mknod(IPSTAT_DEV, IPSTAT_MODE, IPSTAT_MINOR);
145 static int cfg_fd;
146 static char word[16];
147 static unsigned line;
149 static void error(void)
151 printf("inet: error on line %u\n", line);
152 exit(1);
155 static void token(int need)
157 /* Read a word from the configuration file. Return a null string on
158 * EOF. Return a punctiation as a one character word. If 'need' is
159 * true then an actual word is expected at this point, so err out if
160 * not.
162 unsigned char *wp;
163 static unsigned char c= '\n';
165 wp= (unsigned char *) word;
166 *wp = 0;
168 while (c <= ' ') {
169 if (c == '\n') line++;
170 if (read(cfg_fd, &c, 1) != 1) {
171 if (need) error();
172 return;
176 do {
177 if (wp < (unsigned char *) word + sizeof(word)-1) *wp++ = c;
178 if (read(cfg_fd, &c, 1) != 1) c= ' ';
179 if (word[0] == ';' || word[0] == '{' || word[0] == '}') {
180 if (need) error();
181 break;
183 } while (c > ' ' && c != ';' && c != '{' && c != '}');
184 *wp = 0;
187 static unsigned number(char *str, unsigned max)
189 /* Interpret a string as an unsigned decimal number, no bigger than
190 * 'max'. Return this number.
192 char *s;
193 unsigned n, d;
195 s= str;
196 n= 0;
197 while ((d= (*s - '0')) < 10 && n <= max) {
198 n= n * 10 + d;
199 s++;
201 if (*s != 0 || n > max) {
202 printf("inet: '%s' is not a number <= %u\n", str, max);
203 error();
205 return n;
208 void read_conf(void)
210 int i, j, ifno, type, port, enable;
211 struct eth_conf *ecp;
212 struct psip_conf *pcp;
213 struct ip_conf *icp;
214 struct stat st;
216 /* Open the configuration file. */
217 if ((cfg_fd= open(PATH_INET_CONF, O_RDONLY)) == -1)
218 fatal(PATH_INET_CONF);
220 ecp= eth_conf;
221 pcp= psip_conf;
222 icp= ip_conf;
224 while (token(0), word[0] != 0) {
225 if (strncmp(word, "eth", 3) == 0) {
226 ecp->ec_ifno= ifno= number(word+3, IP_PORT_MAX-1);
227 type= NETTYPE_ETH;
228 port= eth_conf_nr;
229 token(1);
230 if (strcmp(word, "vlan") == 0) {
231 token(1);
232 ecp->ec_vlan= number(word, (1<<12)-1);
233 token(1);
234 if (strncmp(word, "eth", 3) != 0) {
235 printf(
236 "inet: VLAN eth%d can't be built on %s\n",
237 ifno, word);
238 exit(1);
240 ecp->ec_port= number(word+3, IP_PORT_MAX-1);
241 } else {
242 ecp->ec_task= alloc(strlen(word)+1);
243 strcpy(ecp->ec_task, word);
244 token(1);
245 ecp->ec_port= number(word, IP_PORT_MAX-1);
247 ecp++;
248 eth_conf_nr++;
249 } else
250 if (strncmp(word, "psip", 4) == 0) {
251 pcp->pc_ifno= ifno= number(word+4, IP_PORT_MAX-1);
252 type= NETTYPE_PSIP;
253 port= psip_conf_nr;
254 pcp++;
255 psip_conf_nr++;
256 } else {
257 printf("inet: Unknown device '%s'\n", word);
258 error();
260 iftype[ifno]= type;
261 icp->ic_ifno= ifno;
262 icp->ic_devtype= type;
263 icp->ic_port= port;
264 tcp_conf[tcp_conf_nr].tc_port= ip_conf_nr;
265 udp_conf[udp_conf_nr].uc_port= ip_conf_nr;
267 enable= 7; /* 1 = IP, 2 = TCP, 4 = UDP */
269 token(0);
270 if (word[0] == '{') {
271 token(0);
272 while (word[0] != '}') {
273 if (strcmp(word, "default") == 0) {
274 if (ifdefault != -1) {
275 printf(
276 "inet: ip%d and ip%d can't both be default\n",
277 ifdefault, ifno);
278 error();
280 ifdefault= ifno;
281 token(0);
282 } else
283 if (strcmp(word, "no") == 0) {
284 token(1);
285 if (strcmp(word, "ip") == 0) {
286 enable= 0;
287 } else
288 if (strcmp(word, "tcp") == 0) {
289 enable &= ~2;
290 } else
291 if (strcmp(word, "udp") == 0) {
292 enable &= ~4;
293 } else {
294 printf(
295 "inet: Can't do 'no %s'\n",
296 word);
297 exit(1);
299 token(0);
300 } else {
301 printf("inet: Unknown option '%s'\n",
302 word);
303 exit(1);
305 if (word[0] == ';') token(0);
306 else
307 if (word[0] != '}') error();
309 token(0);
311 if (word[0] != ';' && word[0] != 0) error();
313 if (enable & 1) icp++, ip_conf_nr++;
314 if (enable & 2) tcp_conf_nr++;
315 if (enable & 4) udp_conf_nr++;
318 if (ifdefault == -1) {
319 printf("inet: No networks or no default network defined\n");
320 exit(1);
323 /* Translate VLAN network references to port numbers. */
324 for (i= 0; i < eth_conf_nr; i++) {
325 ecp= &eth_conf[i];
326 if (eth_is_vlan(ecp)) {
327 for (j= 0; j < eth_conf_nr; j++) {
328 if (eth_conf[j].ec_ifno == ecp->ec_port
329 && !eth_is_vlan(&eth_conf[j])
331 ecp->ec_port= j;
332 break;
335 if (j == eth_conf_nr) {
336 printf(
337 "inet: VLAN eth%d can't be built on eth%d\n",
338 ecp->ec_ifno, ecp->ec_port);
339 exit(1);
344 /* Set umask 0 so we can creat mode 666 devices. */
345 (void) umask(0);
347 /* See what the device number of /dev/ip is. That's what we
348 * used last time for the network devices, so we keep doing so.
350 if (stat("/dev/ip", &st) < 0) fatal("/dev/ip");
351 ip_dev= st.st_rdev;
353 for (i= 0; i < IP_PORT_MAX; i++) {
354 /* Create network devices. */
355 check_dev(iftype[i], i);
359 void *alloc(size_t size)
361 /* Allocate memory on the heap with sbrk(). */
363 return malloc(size);
367 * $PchId: inet_config.c,v 1.10 2003/08/21 09:26:02 philip Exp $