00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #define _MINIX_SOURCE 1
00013 #define _POSIX_SOURCE 1
00014
00015 #include <stdlib.h>
00016 #include <unistd.h>
00017 #include <fcntl.h>
00018 #include <string.h>
00019 #include <errno.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #include <minix/type.h>
00023 #include <minix/sysutil.h>
00024 #include <minix/syslib.h>
00025 #include "inet_config.h"
00026
00027 struct eth_conf eth_conf[IP_PORT_MAX];
00028 struct psip_conf psip_conf[IP_PORT_MAX];
00029 struct ip_conf ip_conf[IP_PORT_MAX];
00030 struct tcp_conf tcp_conf[IP_PORT_MAX];
00031 struct udp_conf udp_conf[IP_PORT_MAX];
00032 dev_t ip_dev;
00033
00034 int eth_conf_nr;
00035 int psip_conf_nr;
00036 int ip_conf_nr;
00037 int tcp_conf_nr;
00038 int udp_conf_nr;
00039
00040 int ip_forward_directed_bcast= 0;
00041
00042 static u8_t iftype[IP_PORT_MAX];
00043 static int ifdefault= -1;
00044
00045 static void fatal(char *label)
00046 {
00047 printf("init: %s: %s\n", label, strerror(errno));
00048 exit(1);
00049 }
00050
00051 static void check_rm(char *device)
00052
00053 {
00054 if (unlink(device) < 0) {
00055 if (errno == ENOENT) return;
00056 fatal(device);
00057 }
00058 printf("rm %s\n", device);
00059 }
00060
00061 static void check_mknod(char *device, mode_t mode, int minor)
00062
00063 {
00064 struct stat st;
00065 dev_t dev;
00066
00067 dev= (ip_dev & 0xFF00) | minor;
00068
00069 if (stat(device, &st) < 0) {
00070 if (errno != ENOENT) fatal(device);
00071 } else {
00072 if (S_ISCHR(st.st_mode) && st.st_rdev == dev) return;
00073 if (unlink(device) < 0) fatal(device);
00074 }
00075
00076 if (mknod(device, S_IFCHR | mode, dev) < 0) fatal(device);
00077 printf("mknod %s c %d %d\n", device, (ip_dev >> 8), minor);
00078 }
00079
00080 static void check_ln(char *old, char *new)
00081
00082 {
00083 struct stat st_old, st_new;
00084
00085 if (stat(old, &st_old) < 0) fatal(old);
00086 if (stat(new, &st_new) < 0) {
00087 if (errno != ENOENT) fatal(new);
00088 } else {
00089 if (st_new.st_dev == st_old.st_dev
00090 && st_new.st_ino == st_old.st_ino) {
00091 return;
00092 }
00093 if (unlink(new) < 0) fatal(new);
00094 }
00095
00096 if (link(old, new) < 0) fatal(new);
00097 printf("ln %s %s\n", old, new);
00098 }
00099
00100 static void check_dev(int type, int ifno)
00101
00102
00103
00104
00105 {
00106 static struct devlist {
00107 char *defname;
00108 mode_t mode;
00109 u8_t minor_off;
00110 } devlist[] = {
00111 { "/dev/eth", 0600, ETH_DEV_OFF },
00112 { "/dev/psip", 0600, PSIP_DEV_OFF },
00113 { "/dev/ip", 0600, IP_DEV_OFF },
00114 { "/dev/tcp", 0666, TCP_DEV_OFF },
00115 { "/dev/udp", 0666, UDP_DEV_OFF },
00116 };
00117 struct devlist *dvp;
00118 int i;
00119 char device[sizeof("/dev/psip99")];
00120 char *dp;
00121
00122 for (i= 0; i < sizeof(devlist) / sizeof(devlist[0]); i++) {
00123 dvp= &devlist[i];
00124 strcpy(device, dvp->defname);
00125 dp= device + strlen(device);
00126 if (ifno >= 10) *dp++ = '0' + (ifno / 10);
00127 *dp++ = '0' + (ifno % 10);
00128 *dp = 0;
00129
00130 if (type == 0
00131 || (i == 0 && type != NETTYPE_ETH)
00132 || (i == 1 && type != NETTYPE_PSIP)
00133 ) {
00134 check_rm(device);
00135 if (ifno == ifdefault) check_rm(dvp->defname);
00136 } else {
00137 check_mknod(device, dvp->mode,
00138 if2minor(ifno, dvp->minor_off));
00139 if (ifno == ifdefault) check_ln(device, dvp->defname);
00140 }
00141 }
00142 }
00143
00144 static int cfg_fd;
00145 static char word[16];
00146 static unsigned line;
00147
00148 static void error(void)
00149 {
00150 printf("inet: error on line %u\n", line);
00151 exit(1);
00152 }
00153
00154 static void token(int need)
00155 {
00156
00157
00158
00159
00160
00161 unsigned char *wp;
00162 static unsigned char c= '\n';
00163
00164 wp= (unsigned char *) word;
00165 *wp = 0;
00166
00167 while (c <= ' ') {
00168 if (c == '\n') line++;
00169 if (read(cfg_fd, &c, 1) != 1) {
00170 if (need) error();
00171 return;
00172 }
00173 }
00174
00175 do {
00176 if (wp < (unsigned char *) word + sizeof(word)-1) *wp++ = c;
00177 if (read(cfg_fd, &c, 1) != 1) c= ' ';
00178 if (word[0] == ';' || word[0] == '{' || word[0] == '}') {
00179 if (need) error();
00180 break;
00181 }
00182 } while (c > ' ' && c != ';' && c != '{' && c != '}');
00183 *wp = 0;
00184 }
00185
00186 static unsigned number(char *str, unsigned max)
00187 {
00188
00189
00190
00191 char *s;
00192 unsigned n, d;
00193
00194 s= str;
00195 n= 0;
00196 while ((d= (*s - '0')) < 10 && n <= max) {
00197 n= n * 10 + d;
00198 s++;
00199 }
00200 if (*s != 0 || n > max) {
00201 printf("inet: '%s' is not a number <= %u\n", str, max);
00202 error();
00203 }
00204 return n;
00205 }
00206
00207 void read_conf(void)
00208 {
00209 int i, j, ifno, type, port, enable;
00210 struct eth_conf *ecp;
00211 struct psip_conf *pcp;
00212 struct ip_conf *icp;
00213 struct stat st;
00214
00215
00216 if ((cfg_fd= open(PATH_INET_CONF, O_RDONLY)) == -1)
00217 fatal(PATH_INET_CONF);
00218
00219 ecp= eth_conf;
00220 pcp= psip_conf;
00221 icp= ip_conf;
00222
00223 while (token(0), word[0] != 0) {
00224 if (strncmp(word, "eth", 3) == 0) {
00225 ecp->ec_ifno= ifno= number(word+3, IP_PORT_MAX-1);
00226 type= NETTYPE_ETH;
00227 port= eth_conf_nr;
00228 token(1);
00229 if (strcmp(word, "vlan") == 0) {
00230 token(1);
00231 ecp->ec_vlan= number(word, (1<<12)-1);
00232 token(1);
00233 if (strncmp(word, "eth", 3) != 0) {
00234 printf(
00235 "inet: VLAN eth%d can't be built on %s\n",
00236 ifno, word);
00237 exit(1);
00238 }
00239 ecp->ec_port= number(word+3, IP_PORT_MAX-1);
00240 } else {
00241 ecp->ec_task= alloc(strlen(word)+1);
00242 strcpy(ecp->ec_task, word);
00243 token(1);
00244 ecp->ec_port= number(word, IP_PORT_MAX-1);
00245 }
00246 ecp++;
00247 eth_conf_nr++;
00248 } else
00249 if (strncmp(word, "psip", 4) == 0) {
00250 pcp->pc_ifno= ifno= number(word+4, IP_PORT_MAX-1);
00251 type= NETTYPE_PSIP;
00252 port= psip_conf_nr;
00253 pcp++;
00254 psip_conf_nr++;
00255 } else {
00256 printf("inet: Unknown device '%s'\n", word);
00257 error();
00258 }
00259 iftype[ifno]= type;
00260 icp->ic_ifno= ifno;
00261 icp->ic_devtype= type;
00262 icp->ic_port= port;
00263 tcp_conf[tcp_conf_nr].tc_port= ip_conf_nr;
00264 udp_conf[udp_conf_nr].uc_port= ip_conf_nr;
00265
00266 enable= 7;
00267
00268 token(0);
00269 if (word[0] == '{') {
00270 token(0);
00271 while (word[0] != '}') {
00272 if (strcmp(word, "default") == 0) {
00273 if (ifdefault != -1) {
00274 printf(
00275 "inet: ip%d and ip%d can't both be default\n",
00276 ifdefault, ifno);
00277 error();
00278 }
00279 ifdefault= ifno;
00280 token(0);
00281 } else
00282 if (strcmp(word, "no") == 0) {
00283 token(1);
00284 if (strcmp(word, "ip") == 0) {
00285 enable= 0;
00286 } else
00287 if (strcmp(word, "tcp") == 0) {
00288 enable &= ~2;
00289 } else
00290 if (strcmp(word, "udp") == 0) {
00291 enable &= ~4;
00292 } else {
00293 printf(
00294 "inet: Can't do 'no %s'\n",
00295 word);
00296 exit(1);
00297 }
00298 token(0);
00299 } else {
00300 printf("inet: Unknown option '%s'\n",
00301 word);
00302 exit(1);
00303 }
00304 if (word[0] == ';') token(0);
00305 else
00306 if (word[0] != '}') error();
00307 }
00308 token(0);
00309 }
00310 if (word[0] != ';' && word[0] != 0) error();
00311
00312 if (enable & 1) icp++, ip_conf_nr++;
00313 if (enable & 2) tcp_conf_nr++;
00314 if (enable & 4) udp_conf_nr++;
00315 }
00316
00317 if (ifdefault == -1) {
00318 printf("inet: No networks or no default network defined\n");
00319 exit(1);
00320 }
00321
00322
00323 for (i= 0; i < eth_conf_nr; i++) {
00324 ecp= ð_conf[i];
00325 if (eth_is_vlan(ecp)) {
00326 for (j= 0; j < eth_conf_nr; j++) {
00327 if (eth_conf[j].ec_ifno == ecp->ec_port
00328 && !eth_is_vlan(ð_conf[j])
00329 ) {
00330 ecp->ec_port= j;
00331 break;
00332 }
00333 }
00334 if (j == eth_conf_nr) {
00335 printf(
00336 "inet: VLAN eth%d can't be built on eth%d\n",
00337 ecp->ec_ifno, ecp->ec_port);
00338 exit(1);
00339 }
00340 }
00341 }
00342
00343
00344 (void) umask(0);
00345
00346
00347
00348
00349 if (stat("/dev/ip", &st) < 0) fatal("/dev/ip");
00350 ip_dev= st.st_rdev;
00351
00352 for (i= 0; i < IP_PORT_MAX; i++) {
00353
00354 check_dev(iftype[i], i);
00355 }
00356 }
00357
00358 void *alloc(size_t size)
00359 {
00360
00361
00362 return sbrk((size + (sizeof(char *) - 1)) & ~(sizeof(char *) - 1));
00363 }
00364
00365
00366
00367