|
INET Framework for OMNeT++/OMNEST
|
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