inet_config.c

Go to the documentation of this file.
00001 /*
00002 inet/inet_config.c
00003 
00004 Created:        Nov 11, 1992 by Philip Homburg
00005 
00006 Modified:       Apr 07, 2001 by Kees J. Bot
00007                 Read the configuration file and fill in the xx_conf[] arrays.
00008 
00009 Copyright 1995 Philip Homburg
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;       /* Default is off */
00041 
00042 static u8_t iftype[IP_PORT_MAX];        /* Interface in use as? */
00043 static int ifdefault= -1;               /* Default network interface. */
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 /* Check if a device is not among the living. */
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 /* Check if a device exists with the proper device number. */
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 /* Check if 'old' and 'new' are still properly linked. */
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 /* Check if the device group with interface number 'ifno' exists and has the
00102  * proper device numbers.  If 'type' is -1 then the device group must be
00103  * removed.
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         /* Read a word from the configuration file.  Return a null string on
00157          * EOF.  Return a punctiation as a one character word.  If 'need' is
00158          * true then an actual word is expected at this point, so err out if
00159          * not.
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         /* Interpret a string as an unsigned decimal number, no bigger than
00189          * 'max'.  Return this number.
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         /* Open the configuration file. */
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;      /* 1 = IP, 2 = TCP, 4 = UDP */
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         /* Translate VLAN network references to port numbers. */
00323         for (i= 0; i < eth_conf_nr; i++) {
00324                 ecp= &eth_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(&eth_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         /* Set umask 0 so we can creat mode 666 devices. */
00344         (void) umask(0);
00345 
00346         /* See what the device number of /dev/ip is.  That's what we
00347          * used last time for the network devices, so we keep doing so.
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                 /* Create network devices. */
00354                 check_dev(iftype[i], i);
00355         }
00356 }
00357 
00358 void *alloc(size_t size)
00359 {
00360         /* Allocate memory on the heap with sbrk(). */
00361 
00362         return sbrk((size + (sizeof(char *) - 1)) & ~(sizeof(char *) - 1));
00363 }
00364 
00365 /*
00366  * $PchId: inet_config.c,v 1.10 2003/08/21 09:26:02 philip Exp $
00367  */

Generated on Fri Apr 14 22:57:31 2006 for minix by  doxygen 1.4.6