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
20 #include <sys/types.h>
22 #include <minix/type.h>
23 #include <minix/sysutil.h>
24 #include <minix/syslib.h>
25 #include "inet_config.h"
30 struct eth_conf eth_conf
[IP_PORT_MAX
];
31 struct psip_conf psip_conf
[IP_PORT_MAX
];
32 struct ip_conf ip_conf
[IP_PORT_MAX
];
33 struct tcp_conf tcp_conf
[IP_PORT_MAX
];
34 struct udp_conf udp_conf
[IP_PORT_MAX
];
43 int ip_forward_directed_bcast
= 0; /* Default is off */
45 static u8_t iftype
[IP_PORT_MAX
]; /* Interface in use as? */
46 static int ifdefault
= -1; /* Default network interface. */
48 static void fatal(char *label
)
50 printf("init: %s: %s\n", label
, strerror(errno
));
54 static void check_rm(char *device
)
55 /* Check if a device is not among the living. */
57 if (unlink(device
) < 0) {
58 if (errno
== ENOENT
) return;
61 printf("rm %s\n", device
);
64 static void check_mknod(char *device
, mode_t mode
, int minor
)
65 /* Check if a device exists with the proper device number. */
70 dev
= makedev(major(ip_dev
), minor
);
72 if (stat(device
, &st
) < 0) {
73 if (errno
!= ENOENT
) fatal(device
);
75 if (S_ISCHR(st
.st_mode
) && st
.st_rdev
== dev
) return;
76 if (unlink(device
) < 0) fatal(device
);
79 if (mknod(device
, S_IFCHR
| mode
, dev
) < 0) fatal(device
);
80 printf("mknod %s c %d %d\n", device
, major(ip_dev
), minor
);
83 static void check_ln(char *old
, char *new)
84 /* Check if 'old' and 'new' are still properly linked. */
86 struct stat st_old
, st_new
;
88 if (stat(old
, &st_old
) < 0) fatal(old
);
89 if (stat(new, &st_new
) < 0) {
90 if (errno
!= ENOENT
) fatal(new);
92 if (st_new
.st_dev
== st_old
.st_dev
93 && st_new
.st_ino
== st_old
.st_ino
) {
96 if (unlink(new) < 0) fatal(new);
99 if (link(old
, new) < 0) fatal(new);
100 printf("ln %s %s\n", old
, new);
103 static void check_dev(int type
, int ifno
)
104 /* Check if the device group with interface number 'ifno' exists and has the
105 * proper device numbers. If 'type' is -1 then the device group must be
109 static struct devlist
{
114 { "/dev/eth", 0600, ETH_DEV_OFF
},
115 { "/dev/psip", 0600, PSIP_DEV_OFF
},
116 { "/dev/ip", 0600, IP_DEV_OFF
},
117 { "/dev/tcp", 0666, TCP_DEV_OFF
},
118 { "/dev/udp", 0666, UDP_DEV_OFF
},
122 char device
[sizeof("/dev/psip99")];
125 for (i
= 0; i
< sizeof(devlist
) / sizeof(devlist
[0]); i
++) {
127 strcpy(device
, dvp
->defname
);
128 dp
= device
+ strlen(device
);
129 if (ifno
>= 10) *dp
++ = '0' + (ifno
/ 10);
130 *dp
++ = '0' + (ifno
% 10);
134 || (i
== 0 && type
!= NETTYPE_ETH
)
135 || (i
== 1 && type
!= NETTYPE_PSIP
)
138 if (ifno
== ifdefault
) check_rm(dvp
->defname
);
140 check_mknod(device
, dvp
->mode
,
141 if2minor(ifno
, dvp
->minor_off
));
142 if (ifno
== ifdefault
) check_ln(device
, dvp
->defname
);
145 check_mknod(IPSTAT_DEV
, IPSTAT_MODE
, IPSTAT_MINOR
);
149 static char word
[16];
150 static unsigned char line
[256], *lineptr
;
151 static unsigned linenr
;
153 static void error(void)
155 printf("inet: error on line %u\n", linenr
);
159 static int nextline(void)
161 /* Read a line from the configuration file, to be used by subsequent
162 * token() calls. Skip empty lines, and lines where the first character
163 * after leading "whitespace" is '#'. The last line of the file need
164 * not be terminated by a newline. Return 1 if a line was read in
165 * successfully, and 0 on EOF or error.
167 unsigned char *lp
, c
;
174 while ((r
= read(cfg_fd
, &c
, 1)) == 1) {
184 if (skip
== -1 && c
> ' ')
187 if (skip
== 0 && lp
< (unsigned char *) line
+ sizeof(line
)-1)
192 return (r
== 1 || lp
!= line
);
195 static void token(int need
)
197 /* Read a word from the configuration line. Return a null string on
198 * EOL. Return a punctuation as a one character word. If 'need' is
199 * true then an actual word is expected at this point, so err out if
203 static unsigned char c
= '\n';
205 wp
= (unsigned char *) word
;
217 if (wp
< (unsigned char *) word
+ sizeof(word
)-1) *wp
++ = c
;
218 c
= (*lineptr
!= 0) ? *lineptr
++ : ' ';
219 if (word
[0] == ';' || word
[0] == '{' || word
[0] == '}') {
223 } while (c
> ' ' && c
!= ';' && c
!= '{' && c
!= '}');
227 static unsigned number(char *str
, unsigned max
)
229 /* Interpret a string as an unsigned decimal number, no bigger than
230 * 'max'. Return this number.
237 while ((d
= (*s
- '0')) < 10 && n
<= max
) {
241 if (*s
!= 0 || n
> max
) {
242 printf("inet: '%s' is not a number <= %u\n", str
, max
);
250 int i
, j
, ifno
= -1, type
= -1, port
= -1, enable
;
251 struct eth_conf
*ecp
;
252 struct psip_conf
*pcp
;
255 char buf
[sizeof(word
)];
257 { static int first
= 1;
258 if (!first
) ip_panic(( "read_conf: called a second time" ));
261 *(u8_t
*)0 = 0xcc; /* INT 3 */
266 /* Open the configuration file. */
267 if ((cfg_fd
= open(PATH_INET_CONF
, O_RDONLY
)) == -1)
268 fatal(PATH_INET_CONF
);
276 if (strncmp(word
, "eth", 3) == 0) {
277 ecp
->ec_ifno
= ifno
= number(word
+3, IP_PORT_MAX
-1);
281 if (strcmp(word
, "vlan") == 0) {
283 ecp
->ec_vlan
= number(word
, (1<<12)-1);
285 if (strncmp(word
, "eth", 3) != 0) {
287 "inet: VLAN eth%d can't be built on %s\n",
291 ecp
->ec_port
= number(word
+3, IP_PORT_MAX
-1);
293 /* The process label consists of the driver
294 * name, an underscore, and the instance
297 strncpy(buf
, word
, sizeof(buf
)-1);
298 buf
[sizeof(buf
)-1]= 0;
301 alloc(strlen(buf
)+1+strlen(word
)+1);
302 sprintf(ecp
->ec_label
, "%s_%s", buf
, word
);
307 } else if (strncmp(word
, "psip", 4) == 0) {
308 pcp
->pc_ifno
= ifno
= number(word
+4, IP_PORT_MAX
-1);
314 printf("inet: Unknown device '%s'\n", word
);
318 if (type
== -1 || ifno
== -1 || port
== -1) {
319 printf("inet: faulty configuration\n");
325 icp
->ic_devtype
= type
;
327 tcp_conf
[tcp_conf_nr
].tc_port
= ip_conf_nr
;
328 udp_conf
[udp_conf_nr
].uc_port
= ip_conf_nr
;
330 enable
= 7; /* 1 = IP, 2 = TCP, 4 = UDP */
333 if (word
[0] == '{') {
335 while (word
[0] != '}') {
336 if (strcmp(word
, "default") == 0) {
337 if (ifdefault
!= -1) {
339 "inet: ip%d and ip%d can't both be default\n",
346 if (strcmp(word
, "no") == 0) {
348 if (strcmp(word
, "ip") == 0) {
351 if (strcmp(word
, "tcp") == 0) {
354 if (strcmp(word
, "udp") == 0) {
358 "inet: Can't do 'no %s'\n",
364 printf("inet: Unknown option '%s'\n",
368 if (word
[0] == ';') token(0);
370 if (word
[0] != '}') error();
374 if (word
[0] != ';' && word
[0] != 0) error();
376 if (enable
& 1) icp
++, ip_conf_nr
++;
377 if (enable
& 2) tcp_conf_nr
++;
378 if (enable
& 4) udp_conf_nr
++;
381 if (ifdefault
== -1) {
382 printf("inet: No networks or no default network defined\n");
386 /* Translate VLAN network references to port numbers. */
387 for (i
= 0; i
< eth_conf_nr
; i
++) {
389 if (eth_is_vlan(ecp
)) {
390 for (j
= 0; j
< eth_conf_nr
; j
++) {
391 if (eth_conf
[j
].ec_ifno
== ecp
->ec_port
392 && !eth_is_vlan(ð_conf
[j
])
398 if (j
== eth_conf_nr
) {
400 "inet: VLAN eth%d can't be built on eth%d\n",
401 ecp
->ec_ifno
, ecp
->ec_port
);
407 /* Set umask 0 so we can creat mode 666 devices. */
410 /* See what the device number of /dev/ip is. That's what we
411 * used last time for the network devices, so we keep doing so.
413 if (stat("/dev/ip", &st
) < 0) fatal("/dev/ip");
416 for (i
= 0; i
< IP_PORT_MAX
; i
++) {
417 /* Create network devices. */
418 check_dev(iftype
[i
], i
);
422 void *alloc(size_t size
)
424 /* Allocate memory on the heap with sbrk(). */
430 * $PchId: inet_config.c,v 1.10 2003/08/21 09:26:02 philip Exp $