RoutingTableParser.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2000 Institut fuer Telematik, Universitaet Karlsruhe
00003 // Copyright (C) 2004 Andras Varga
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 
00020 //  Cleanup and rewrite: Andras Varga, 2004
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <ctype.h>
00026 
00027 #include "RoutingTableParser.h"
00028 #include "IPv4InterfaceData.h"
00029 
00030 //
00031 // Constants
00032 //
00033 const int MAX_FILESIZE = 10000; // TBD lift hardcoded limit
00034 const int MAX_ENTRY_STRING_SIZE = 500;
00035 
00036 //
00037 // Tokens that mark the route file.
00038 //
00039 const char  *IFCONFIG_START_TOKEN = "ifconfig:",
00040             *IFCONFIG_END_TOKEN = "ifconfigend.",
00041             *ROUTE_START_TOKEN = "route:",
00042             *ROUTE_END_TOKEN = "routeend.";
00043 
00044 RoutingTableParser::RoutingTableParser(IInterfaceTable *i, IRoutingTable *r)
00045 {
00046     ift = i;
00047     rt = r;
00048 }
00049 
00050 
00051 int RoutingTableParser::streq(const char *str1, const char *str2)
00052 {
00053     return (strncmp(str1, str2, strlen(str2)) == 0);
00054 }
00055 
00056 
00057 int RoutingTableParser::strcpyword(char *dest, const char *src)
00058 {
00059     int i;
00060     for (i = 0; !isspace(dest[i] = src[i]); i++) ;
00061     dest[i] = '\0';
00062     return i;
00063 }
00064 
00065 
00066 void RoutingTableParser::skipBlanks(char *str, int &charptr)
00067 {
00068     for (;isspace(str[charptr]); charptr++) ;
00069 }
00070 
00071 
00072 int RoutingTableParser::readRoutingTableFromFile(const char *filename)
00073 {
00074     FILE *fp;
00075     int charpointer;
00076     char *file = new char[MAX_FILESIZE];
00077     char *ifconfigFile = NULL;
00078     char *routeFile = NULL;
00079 
00080     fp = fopen(filename, "r");
00081     if (fp == NULL)
00082         opp_error("Error opening routing table file `%s'", filename);
00083 
00084     // read the whole into the file[] char-array
00085     for (charpointer = 0;
00086          (file[charpointer] = getc(fp)) != EOF;
00087          charpointer++) ;
00088 
00089     charpointer++;
00090     for (; charpointer < MAX_FILESIZE; charpointer++)
00091         file[charpointer] = '\0';
00092     //    file[++charpointer] = '\0';
00093 
00094     fclose(fp);
00095 
00096 
00097     // copy file into specialized, filtered char arrays
00098     for (charpointer = 0;
00099          (charpointer < MAX_FILESIZE) && (file[charpointer] != EOF);
00100          charpointer++) {
00101         // check for tokens at beginning of file or line
00102         if (charpointer == 0 || file[charpointer - 1] == '\n') {
00103             // copy into ifconfig filtered chararray
00104             if (streq(file + charpointer, IFCONFIG_START_TOKEN)) {
00105                 ifconfigFile = createFilteredFile(file,
00106                                                   charpointer,
00107                                                   IFCONFIG_END_TOKEN);
00108                 //PRINTF("Filtered File 1 created:\n%s\n", ifconfigFile);
00109             }
00110 
00111             // copy into route filtered chararray
00112             if (streq(file + charpointer, ROUTE_START_TOKEN)) {
00113                 routeFile = createFilteredFile(file,
00114                                                charpointer,
00115                                                ROUTE_END_TOKEN);
00116                 //PRINTF("Filtered File 2 created:\n%s\n", routeFile);
00117             }
00118         }
00119     }
00120 
00121     delete file;
00122 
00123     // parse filtered files
00124     if (ifconfigFile)
00125         parseInterfaces(ifconfigFile);
00126     if (routeFile)
00127         parseRouting(routeFile);
00128 
00129     delete ifconfigFile;
00130     delete routeFile;
00131 
00132     return 0;
00133 
00134 }
00135 
00136 char *RoutingTableParser::createFilteredFile(char *file, int &charpointer, const char *endtoken)
00137 {
00138     int i = 0;
00139     char *filterFile = new char[MAX_FILESIZE];
00140     filterFile[0] = '\0';
00141 
00142     while(true) {
00143         // skip blank lines and comments
00144         while ( !isalnum(file[charpointer]) && !isspace(file[charpointer]) ) {
00145             while (file[charpointer++] != '\n') ;
00146         }
00147 
00148         // check for endtoken:
00149         if (streq(file + charpointer, endtoken)) {
00150             filterFile[i] = '\0';
00151             break;
00152         }
00153 
00154         // copy whole line to filterFile
00155         while ((filterFile[i++] = file[charpointer++]) != '\n') ;
00156     }
00157 
00158     return filterFile;
00159 }
00160 
00161 
00162 void RoutingTableParser::parseInterfaces(char *ifconfigFile)
00163 {
00164     char buf[MAX_ENTRY_STRING_SIZE];
00165     int charpointer = 0;
00166     InterfaceEntry *ie;
00167 
00168     // parsing of entries in interface definition
00169     while(ifconfigFile[charpointer] != '\0')
00170     {
00171         // name entry
00172         if (streq(ifconfigFile + charpointer, "name:")) {
00173             // find existing interface with this name
00174             char *name = parseEntry(ifconfigFile, "name:", charpointer,buf);
00175             ie = ift->getInterfaceByName(name);
00176             if (!ie)
00177                 opp_error("Error in routing file: interface name `%s' not registered by any L2 module", name);
00178             continue;
00179         }
00180 
00181         // encap entry
00182         if (streq(ifconfigFile + charpointer, "encap:")) {
00183             // ignore encap
00184             parseEntry(ifconfigFile, "encap:", charpointer, buf);
00185             continue;
00186         }
00187 
00188         // HWaddr entry
00189         if (streq(ifconfigFile + charpointer, "HWaddr:")) {
00190             // ignore hwAddr
00191             parseEntry(ifconfigFile, "HWaddr:", charpointer, buf);
00192             continue;
00193         }
00194 
00195         // inet_addr entry
00196         if (streq(ifconfigFile + charpointer, "inet_addr:")) {
00197             ie->ipv4Data()->setIPAddress(IPAddress(parseEntry(ifconfigFile, "inet_addr:", charpointer,buf)));
00198             continue;
00199         }
00200 
00201         // Broadcast address entry
00202         if (streq(ifconfigFile + charpointer, "Bcast:")) {
00203             // ignore Bcast
00204             parseEntry(ifconfigFile, "Bcast:", charpointer, buf);
00205             continue;
00206         }
00207 
00208         // Mask entry
00209         if (streq(ifconfigFile + charpointer, "Mask:")) {
00210             ie->ipv4Data()->setNetmask(IPAddress(parseEntry(ifconfigFile, "Mask:", charpointer,buf)));
00211             continue;
00212         }
00213 
00214         // Multicast groups entry
00215         if (streq(ifconfigFile + charpointer, "Groups:")) {
00216             char *grStr = parseEntry(ifconfigFile, "Groups:", charpointer, buf);
00217             parseMulticastGroups(grStr, ie);
00218             continue;
00219         }
00220 
00221         // MTU entry
00222         if (streq(ifconfigFile + charpointer, "MTU:")) {
00223             ie->setMtu(atoi(parseEntry(ifconfigFile, "MTU:", charpointer,buf)));
00224             continue;
00225         }
00226 
00227         // Metric entry
00228         if (streq(ifconfigFile + charpointer, "Metric:")) {
00229             ie->ipv4Data()->setMetric(atoi(parseEntry(ifconfigFile, "Metric:", charpointer,buf)));
00230             continue;
00231         }
00232 
00233         // BROADCAST Flag
00234         if (streq(ifconfigFile + charpointer, "BROADCAST")) {
00235             ie->setBroadcast(true);
00236             charpointer += strlen("BROADCAST");
00237             skipBlanks(ifconfigFile, charpointer);
00238             continue;
00239         }
00240 
00241         // MULTICAST Flag
00242         if (streq(ifconfigFile + charpointer, "MULTICAST")) {
00243             ie->setMulticast(true);
00244             charpointer += strlen("MULTICAST");
00245             skipBlanks(ifconfigFile, charpointer);
00246             continue;
00247         }
00248 
00249         // POINTTOPOINT Flag
00250         if (streq(ifconfigFile + charpointer, "POINTTOPOINT")) {
00251             ie->setPointToPoint(true);
00252             charpointer += strlen("POINTTOPOINT");
00253             skipBlanks(ifconfigFile, charpointer);
00254             continue;
00255         }
00256 
00257         // no entry discovered: move charpointer on
00258         charpointer++;
00259     }
00260 }
00261 
00262 
00263 char *RoutingTableParser::parseEntry(char *ifconfigFile, const char *tokenStr,
00264                                      int& charpointer, char *destStr)
00265 {
00266     int temp = 0;
00267 
00268     charpointer += strlen(tokenStr);
00269     skipBlanks(ifconfigFile, charpointer);
00270     temp = strcpyword(destStr, ifconfigFile + charpointer);
00271     charpointer += temp;
00272 
00273     skipBlanks(ifconfigFile, charpointer);
00274 
00275     return destStr;
00276 }
00277 
00278 
00279 void RoutingTableParser::parseMulticastGroups(char *groupStr, InterfaceEntry *itf)
00280 {
00281     IPv4InterfaceData::IPAddressVector mcg = itf->ipv4Data()->getMulticastGroups();
00282 
00283     // add "224.0.0.1" automatically
00284     mcg.push_back(IPAddress::ALL_HOSTS_MCAST);
00285 
00286     // add 224.0.0.2" only if Router (IP forwarding enabled)
00287     if (rt->isIPForwardingEnabled())
00288         mcg.push_back(IPAddress::ALL_ROUTERS_MCAST);
00289 
00290     // Parse string (IP addresses separated by colons)
00291     cStringTokenizer tokenizer(groupStr,":");
00292     const char *token;
00293     while ((token = tokenizer.nextToken())!=NULL)
00294         mcg.push_back(IPAddress(token));
00295 
00296     itf->ipv4Data()->setMulticastGroups(mcg);
00297 }
00298 
00299 void RoutingTableParser::parseRouting(char *routeFile)
00300 {
00301     char *str = new char[MAX_ENTRY_STRING_SIZE];
00302 
00303     int pos = strlen(ROUTE_START_TOKEN);
00304     skipBlanks(routeFile, pos);
00305     while (routeFile[pos] != '\0')
00306     {
00307         // 1st entry: Host
00308         pos += strcpyword(str, routeFile + pos);
00309         skipBlanks(routeFile, pos);
00310         IPRoute *e = new IPRoute();
00311         if (strcmp(str, "default:"))
00312         {
00313             // if entry is not the default entry
00314             if (!IPAddress::isWellFormed(str))
00315                 opp_error("Syntax error in routing file: `%s' on 1st column should be `default:' or a valid IP address", str);
00316             e->setHost(IPAddress(str));
00317         }
00318 
00319         // 2nd entry: Gateway
00320         pos += strcpyword(str, routeFile + pos);
00321         skipBlanks(routeFile, pos);
00322         if (!strcmp(str, "*") || !strcmp(str, "0.0.0.0"))
00323         {
00324             e->setGateway(IPAddress::UNSPECIFIED_ADDRESS);
00325         }
00326         else
00327         {
00328             if (!IPAddress::isWellFormed(str))
00329                 opp_error("Syntax error in routing file: `%s' on 2nd column should be `*' or a valid IP address", str);
00330             e->setGateway(IPAddress(str));
00331         }
00332 
00333         // 3rd entry: Netmask
00334         pos += strcpyword(str, routeFile + pos);
00335         skipBlanks(routeFile, pos);
00336         if (!IPAddress::isWellFormed(str))
00337             opp_error("Syntax error in routing file: `%s' on 3rd column should be a valid IP address", str);
00338         e->setNetmask(IPAddress(str));
00339 
00340         // 4th entry: flags
00341         pos += strcpyword(str, routeFile + pos);
00342         skipBlanks(routeFile, pos);
00343         // parse flag-String to set flags
00344         for (int i = 0; str[i]; i++)
00345         {
00346             if (str[i] == 'H') {
00347                 e->setType(IPRoute::DIRECT);
00348             } else if (str[i] == 'G') {
00349                 e->setType(IPRoute::REMOTE);
00350             } else {
00351                 opp_error("Syntax error in routing file: 4th column should be `G' or `H' not `%s'", str);
00352             }
00353         }
00354 
00355         // 5th entry: metric
00356         pos += strcpyword(str, routeFile + pos);
00357         skipBlanks(routeFile, pos);
00358         int metric = atoi(str);
00359         if (metric==0 && str[0]!='0')
00360             opp_error("Syntax error in routing file: 5th column should be numeric not `%s'", str);
00361         e->setMetric(metric);
00362 
00363         // 6th entry: interface
00364         opp_string interfaceName;
00365         interfaceName.reserve(MAX_ENTRY_STRING_SIZE);
00366         pos += strcpyword(interfaceName.buffer(), routeFile + pos);
00367         skipBlanks(routeFile, pos);
00368         InterfaceEntry *ie = ift->getInterfaceByName(interfaceName.c_str());
00369         if (!ie)
00370             opp_error("Syntax error in routing file: 6th column: `%s' is not an existing interface", interfaceName.c_str());
00371         e->setInterface(ie);
00372 
00373         // add entry
00374         rt->addRoute(e);
00375     }
00376 }
00377