INET Framework for OMNeT++/OMNEST
acl.cc
Go to the documentation of this file.
00001 /*
00002  *      acl.cc
00003  *
00004  *  Created  on: 24.2.2009
00005  *  Finished on:  7.5.2009
00006  *  Author: Tomas Suchomel, xsucho00
00007  */
00008 
00009 #include "acl.h"
00010 
00011 Define_Module(acl);
00012 
00013 using namespace std;
00014 
00015 /*
00016  * ipIsEqual(): IP IS EQUAL
00017  * Method that compares IP address from the packet header
00018  * to IP address presents in current ACL rule.
00019  * @param ip            - struct with IP address from ACL rule
00020  * @param packet        - struct with IP address from packet
00021  * @see filterPacket()
00022  * @return result of IP address comparison
00023  */
00024 bool acl::ipIsEqual(TIP* ip, TIP* packet)
00025 {
00026         ev << "ACL rule, ip  : " << ip->ipAddr.str() << endl;
00027         ev << "ACL rule, mask: " << ip->netmask.str() << endl;
00028         ev << "packet, ip    : " << packet->ipAddr.str() << endl;
00029         ev << "packet_masked : " << packet->ipAddr.doAnd(ip->netmask).str() << endl;
00030         if (ip->ipAddr != (packet->ipAddr.doAnd(ip->netmask)))
00031         {
00032                 ev << "IP DOESN'T MATCH" << endl;
00033                 return false;
00034         }
00035         ev << "IP MATCH OK" << endl;
00036         return true;
00037 }
00038 
00039 /*
00040  * portIsEqual(): PORT IS EQUAL
00041  * Method that compares port number(s) from the packet header
00042  * to port number(s) present in current ACL rule.
00043  * @param ip            - struct with ports from ACL rule
00044  * @param packet        - struct with ports from packet
00045  * @see filterPacket()
00046  * @return result of port comparison
00047  */
00048 bool acl::portIsEqual(TIP* ip, TIP* packet)
00049 {
00050         switch (ip->port_op) {
00051                 case PORT_EQ:
00052                         if (ip->portBeg == packet->portBeg)
00053                                 return true;
00054                         break;
00055                 case PORT_NEQ:
00056                         if (ip->portBeg != packet->portBeg)
00057                                 return true;
00058                         break;
00059                 case PORT_GT:
00060                         if (ip->portBeg < packet->portBeg)
00061                                 return true;
00062                         break;
00063                 case PORT_LT:
00064                         if (ip->portBeg > packet->portBeg)
00065                                 return true;
00066                         break;
00067                 case PORT_RNG:
00068                 case PORT_NDEF:
00069                         if ((ip->portBeg <= packet->portBeg) && (ip->portEnd >= packet->portBeg))
00070                                 return true;
00071                         break;
00072                 default:
00073                         cout << "BUG" << endl;
00074         }
00075         return false;
00076 }
00077 
00078 /*
00079  * andIpWithMask(): AND IP WITH MASK
00080  * Method that does AND operation between IP Address and network mask in current ACL rule.
00081  * @param rule  - struct with ACL rule
00082  * @return Negated wildcard mask [bits(O -> 1, 1 -> 0)].
00083  * @see loadConfigFromXML()
00084  */
00085 void acl::andIpWithMask(TRule* rule)
00086 {
00087         rule->source.ipAddr =   rule->source.ipAddr.doAnd(rule->source.netmask);
00088         rule->dest.ipAddr =     rule->dest.ipAddr.doAnd(rule->dest.netmask);
00089 }
00090 
00091 /*
00092  * negateWildcard(): NEGATE WILD CARD MASKs
00093  * Method that negates all the bits of given wildcard mask in ACL rule.
00094  * @param wc    - IPAddress structure with wildcard mask
00095  * @see loadConfigFromXML()
00096  */
00097 IPAddress acl::negateWildcard(IPAddress wc)
00098 {
00099         return (IPAddress(~(wc.getInt())));
00100 }
00101 
00102 /*
00103  * getAction(): GET ACTION
00104  * Method that gets "action" field from XML string and puts it
00105  * to current ACL rule.
00106  * @param action        - string with text from XML config file
00107  * @param rule          - struct with ACL rule
00108  * @see loadConfigFromXML()
00109  */
00110 void acl::getAction(std::string action, TRule* rule)
00111 {
00112         if (action == "deny")
00113                 rule->action = A_DENY;
00114         else if (action == "permit")
00115                 rule->action = A_PERMIT;
00116 }
00117 
00118 /*
00119  * getProtocol(): GET PROTOCOL
00120  * Method that gets protocol field from XML string and puts it
00121  * to current ACL rule. It can handle protocol typed as text
00122  * or as a number (according to RFC).
00123  * @param pom   - string with text/number from XML config file
00124  * @param rule  - struct with ACL rule
00125  * @see loadConfigFromXML()
00126  */
00127 void acl::getProtocol(std::string pom, TRule* rule)
00128 {
00129         if (pom == "ip" || pom == "4")
00130                 rule->protocol = PROT_IP;
00131         else if (pom == "tcp" || pom == "6")
00132                 rule->protocol = PROT_TCP;
00133         else if (pom == "udp" || pom == "17")
00134                 rule->protocol = PROT_UDP;
00135         else if (pom == "icmp" || pom == "1")
00136                 rule->protocol = PROT_ICMP;
00137         else if (pom == "igmp" || pom == "2")
00138                 rule->protocol = PROT_IGMP;
00139         else if (pom == "eigrp" || pom == "igrp" || pom == "88")
00140                 rule->protocol = PROT_EIGRP;
00141         else if (pom == "ospf" || pom == "89")
00142                 rule->protocol = PROT_OSPF;
00143 }
00144 
00145 /*
00146  * getPort(): GET PORT
00147  * Method that gets all port information fields from XML string.
00148  * It can handle ports typed as text or as a number (according to RFC).
00149  * @param pom   - string contains the port operator from XML file
00150  * @param p_beg - string contains the beginning port no. from XML file
00151  * @param p_end - string contains the ending port no. from XML file
00152  * @param ip    - struct with an IP Address in current ACL rule
00153  * @see loadConfigFromXML()
00154  */
00155 void acl::getPort(std::string pom, std::string p_beg, std::string p_end, TIP *ip)
00156 {
00157         int p1, p2;
00158         stringstream ss (stringstream::in | stringstream::out);
00159         /* if port is given as text string, it is converted to short int number */
00160         if (p_beg == "ftp-data") p1 = 20;
00161         if (p_beg == "ftp") p1 = 21;
00162         if (p_beg == "telnet") p1 = 23;
00163         if (p_beg == "smtp") p1 = 25;
00164         if (p_beg == "tftp") p1 = 69;
00165         if ((p_beg == "www") || (p_beg == "http") || (p_beg == "www-http")) p1 = 80;
00166         if ((p_beg == "pop3") || (p_beg == "pop")) p1 = 110;
00167         if (p_beg == "snmp") p1 = 161;
00168         if (p_beg == "irc") p1 = 194;
00169         if (p_beg == "ipx") p1 = 213;
00170         if (p_beg == "ldap") p1 = 389;
00171         if (p_beg == "https") p1 = 443;
00172 
00173         ss << p_beg;
00174         ss >> p1;
00175         ss << p_end;
00176         ss >> p2;
00177 
00178         /* resolution of port operators*/
00179         if (pom == "eq")                        // EQ
00180                 ip->port_op = PORT_EQ;
00181         else if (pom == "neq")          // NEQ
00182                 ip->port_op = PORT_NEQ;
00183         else if (pom == "gt")           // GT
00184                 ip->port_op = PORT_GT;
00185         else if (pom == "lt")           // LT
00186                 ip->port_op = PORT_LT;
00187         else if (pom == "range")        // RANGE
00188                 ip->port_op = PORT_RNG;
00189         else // if port operator is "" or not defined: NDEF
00190         {
00191                 ip->port_op = PORT_NDEF;
00192         }
00193         switch (ip->port_op) { // based on presence of current port operator
00194                 case PORT_EQ:
00195                 case PORT_NEQ:
00196                 case PORT_GT:
00197                 case PORT_LT: // if operator is any of following [eq, neq, gt, lt]: load only one port no. from portBeg
00198                         ip->portBeg = p1;
00199                         break;
00200                 case PORT_RNG: // if operator = RANGE, load two port number in the range of portBeg to portEnd
00201                         ip->portBeg = p1;
00202                         ip->portEnd = p2;
00203                         break;
00204                 case PORT_NDEF: // if any port operator is present, port range is full range of ports [0 - 65535]
00205                         ip->portBeg = 0;
00206                         ip->portEnd = 65535;
00207                         break;
00208         }
00209 }
00210 
00211 /*
00212  * loadConfigFromXML(): LOAD CONFIG FROM XML
00213  * Method that loads configuration from XML file to IP ACL structures.
00214  * Also binds list of ACL rules to interface and direction.
00215  * @param fileName      - configuration filename (XML)
00216  * @see initialize()
00217  * @return correct/incorrect load of ACL configuration on Router
00218  */
00219 bool acl::loadConfigFromXML(const char* fileName)
00220 {
00221         /* get access into Routing Table and Interface Table modules */
00222         IRoutingTable* rt = RoutingTableAccess().get();
00223         IInterfaceTable* ift = InterfaceTableAccess().get();
00224 
00225         /* resolution of configuration XML file according to specified filename */
00226         cXMLElement* document = ev.getXMLDocument(fileName);
00227         if (document == NULL)
00228         {       /* if no file with such name is provided, error is recognized */
00229                 error("Cannot read AS configuration from file %s", fileName);
00230                 return false;
00231         }
00232 
00233         /* try to find current router in XML on running instance of this ACL module */
00234         std::string routerXPath("Router[@id='");
00235         std::string routerId = rt->getRouterId().str();
00236         routerXPath += routerId;
00237         routerXPath += "']";
00238 
00239         cXMLElement* router = document->getElementByPath(routerXPath.c_str());
00240         if (router == NULL)
00241         {       /* current router configuration is completely missing in XML configuration - error */
00242                 error("No configuration for Router ID: %s", routerId.c_str());
00243                 this->aclEnabled = false;
00244                 return true;
00245         }
00246         cXMLElement* ACLs = router->getFirstChildWithTag("ACLs"); // find ACL configuration part
00247         if (ACLs == NULL)
00248         {       /* ACL configuration part is missing in XML configuration */
00249                 //cout << "ACL: ACL is NOT ENABLED on Router id = " << routerId.c_str() << endl;
00250                 this->aclEnabled = false; // ACL indicator is FALSE
00251                 return true;
00252         }
00253         cXMLElement* ACL = ACLs->getFirstChildWithTag("ACL");
00254         if (ACL == NULL)
00255         {
00256                 //cout << "ACL: ACL is NOT ENABLED on Router id = " << routerId.c_str() << endl;
00257                 this->aclEnabled = false;
00258                 return true;
00259         }
00260         else
00261         {
00262                 this->aclEnabled = true;
00263                 //cout << "ACL: Loading ACL entries for Router id = " << routerId.c_str() << "\n";
00264         }
00265         while (ACL != NULL)
00266         {
00267                 cXMLElement *entry = ACL->getFirstChildWithTag("entry");
00268                 TACL _acl;
00269 
00270                 while (entry != NULL)
00271                 {
00272                         cXMLElement *leaf = entry->getFirstChild();
00273                         TRule rule;
00274                         Stat stat;
00275                         stat.used = 0;
00276 
00277                         std::string src_port_op = "";
00278                         std::string src_port_beg = "";
00279                         std::string src_port_end = "";
00280                         std::string dst_port_op = "";
00281                         std::string dst_port_beg = "";
00282                         std::string dst_port_end = "";
00283 
00284                         /* processing current leaf under XML node <entry> */
00285                         while (leaf != NULL)
00286                         {
00287                                 const char* tagName = leaf->getTagName();
00288                                 const char* value = leaf->getNodeValue();
00289 
00290                                 if (strcmp(tagName, "action") == 0)
00291                                         getAction(value, &rule);
00292                                 else if (strcmp(tagName, "IP_src") == 0)
00293                                         rule.source.ipAddr.set(value);
00294                                 else if (strcmp(tagName, "WC_src") == 0)
00295                                         rule.source.netmask = negateWildcard(IPAddress(value));
00296                                 else if (strcmp(tagName, "protocol") == 0)
00297                                         getProtocol(value, &rule);
00298                                 else if (strcmp(tagName, "IP_dst") == 0)
00299                                         rule.dest.ipAddr.set(value);
00300                                 else if (strcmp(tagName, "WC_dst") == 0)
00301                                         rule.dest.netmask = negateWildcard(IPAddress(value));
00302                                 else if (strcmp(tagName, "port_op_src") == 0)
00303                                         src_port_op = value;
00304                                 else if (strcmp(tagName, "port_beg_src") == 0)
00305                                         src_port_beg = value;
00306                                 else if (strcmp(tagName, "port_end_src") == 0)
00307                                         src_port_end = value;
00308                                 else if (strcmp(tagName, "port_op_dst") == 0)
00309                                         dst_port_op = value;
00310                                 else if (strcmp(tagName, "port_beg_dst") == 0)
00311                                         dst_port_beg = value;
00312                                 else if (strcmp(tagName, "port_end_dst") == 0)
00313                                         dst_port_end = value;
00314                                 else if (strcmp(tagName, "orig") == 0)
00315                                         stat.text = value;
00316                                 leaf = leaf->getNextSibling();
00317                         }
00318 
00319                         /* AND (&) IP ADDRESS WITH NETWORK MASK IN CURRENT ACL RULE */
00320                         andIpWithMask(&rule);
00321                         /* PROCESS PORT INFORMATION FROM XML CONFIGURATION FILE */
00322                         getPort(src_port_op, src_port_beg, src_port_end, &rule.source);
00323                         getPort(dst_port_op, dst_port_beg, dst_port_end, &rule.dest);
00324 
00325                         /* generate statistics for processed rule */
00326                         stats.push_back(stat);
00327                         Stat* pStat = &this->stats.back();
00328                         rule.used = &(pStat->used);
00329 
00330                         _acl.push_back(rule); // processed rule is added at the end of ACL list
00331 
00332                         entry = entry->getNextSiblingWithTag("entry");
00333                 }
00334                 /* create default rule at the end of the ACL list - deny ip any any */
00335                 TRule rule;
00336                 Stat stat;
00337                 stat.used = 0;
00338                 rule.action = A_DENY;
00339                 rule.protocol = PROT_IP;
00340                 stat.text = "access-list deny ip any any";
00341                 rule.source.ipAddr.set("0.0.0.0");
00342                 rule.dest.ipAddr.set("0.0.0.0");
00343                 rule.source.netmask.set("0.0.0.0");
00344                 rule.dest.netmask.set("0.0.0.0");
00345                 getPort("", "", "", &rule.source);
00346                 getPort("", "", "", &rule.dest);
00347 
00348                 /* generate statistics for the default rule*/
00349                 stats.push_back(stat);
00350                 Stat* pStat = &this->stats.back();
00351                 rule.used = &(pStat->used);
00352 
00353                 _acl.push_back(rule); // implicit rule is finally added at the end of the list
00354 
00355                 this->acls.push_back(_acl); // current ACL list is added at the end of ACLs (list of lists)
00356 
00357                 cXMLElement *interfaces = ACL->getFirstChildWithTag("interfaces");
00358                 cXMLElement *interface  = interfaces->getFirstChildWithTag("interface");
00359 
00360                 /* processing interface information - binding ACL list to interface and direction */
00361                 while (interface != NULL)
00362                 {
00363                         InterfaceEntry *targetInt = ift->getInterfaceByName(interface->getNodeValue());
00364                         TInterface _if;
00365 
00366                         _if.gateIndex = targetInt->getNetworkLayerGateIndex();
00367                         if (interface->getAttribute("dir") == std::string("in"))
00368                                 _if.dir = true;
00369                         else
00370                                 _if.dir = false;
00371                         _if.rules = &this->acls.back();
00372 
00373                         this->interfaces.push_back(_if);
00374                         interface = interface->getNextSibling();
00375                 }
00376 
00377                 ACL = ACL->getNextSiblingWithTag("ACL");
00378         }
00379         return true;
00380 }
00381 
00382 /*
00383  * getRules(): GET RULES
00384  * Method that gets specific ACL list, which is about to be applied
00385  * on current in/outgoing packet.
00386  * @param gateIndex     - index of the arrival gate
00387  * @param dir           - direction of data communication
00388  * @see handleMessage()
00389  * @return ACL list corresponding to packet or NULL if it's not
00390  */
00391 TACL* acl::getRules(int gateIndex, bool dir)
00392 {
00393         for (std::list<TInterface>::iterator it = this->interfaces.begin(); it != this->interfaces.end(); it++)
00394         {
00395                 TInterface* _if = &(*it);
00396                 if (_if->gateIndex == gateIndex && _if->dir == dir)
00397                         return _if->rules;
00398         }
00399         return NULL;
00400 }
00401 
00402 /*
00403  * processPacket(): PROCESS PACKET
00404  * Method that is processing current packet, which is casted to IPDatagram.
00405  * It decapsulates packet and save the information such as source address,
00406  * destination address, transport protocol and transfer port numbers.
00407  * It also decides, whether the packet is about to be sent to upper/lower layer,
00408  * or is about to be dropped.
00409  * @param packet        - current IP packet casted to IPDatagram
00410  * @param acl           - list of ACL rules which fits current packet
00411  * @return Decision of action taken with current packet (permit/deny)
00412  */
00413 bool acl::processPacket(IPDatagram* packet, TACL* acl)
00414 {
00415         TIP source, dest;
00416         source.ipAddr = packet->getSrcAddress();
00417         dest.ipAddr = packet->getDestAddress();
00418         int protocol = packet->getTransportProtocol();
00419 
00420         ev << "Packet Source IP Address: " << source.ipAddr.str() << endl;
00421         ev << "Packet Dest.  IP Address: " << dest.ipAddr.str() << endl;
00422         ev << "Packet Protocol ID      : " << protocol << endl;
00423 
00424         UDPPacket *udppacket;
00425         TCPSegment *tcppacket;
00426 
00427         switch (protocol)
00428         {
00429                 case PROT_UDP: // if protocol is UDP, ports need to be checked
00430                         udppacket = dynamic_cast<UDPPacket *> (packet->decapsulate());
00431                         source.portBeg = udppacket->getSourcePort();
00432                         ev << "UDP packet, source port: " << source.portBeg << endl;
00433                         dest.portBeg = udppacket->getDestinationPort();
00434                         ev << "UDP packet, dest.  port: " << dest.portBeg << endl;
00435                         delete udppacket;
00436                         break;
00437                 case PROT_TCP: // if protocol is TCP, ports need to be checked
00438                         tcppacket = dynamic_cast<TCPSegment *> (packet->decapsulate());
00439                         source.portBeg = tcppacket->getSrcPort();
00440                         ev << "TCP packet, source port: " << source.portBeg << endl;
00441                         dest.portBeg = tcppacket->getDestPort();
00442                         ev << "TCP packet, dest.  port: " << dest.portBeg << endl;
00443                         delete tcppacket;
00444                         break;
00445                 default:
00446                         ev << "Protocol is other than TCP or UDP, ports don't need to be checked..." << endl;
00447                         break;
00448         }
00449         if (filterPacket(acl, source, dest, protocol))
00450         {
00451                 // rule is 'permit'
00452                 this->packetsPermitted++;
00453                 return true;
00454         }
00455         else
00456         {
00457             ev << "- ACL ACTION:  DENY, packet dropped   ---" << endl;
00458             this->packetsDropped++;
00459                 return false;
00460         }
00461 }
00462 
00463 /*
00464  * filterPacket(): FILTER PACKET
00465  * Method that compares information from the packet with whole
00466  * ACL list bound to current packet. Depending on this comparison,
00467  * indication of action is taken. (true = permit, false = deny).
00468  * @param acl           - list of ACL rules which fits current packet
00469  * @param source        - structure with source data from packet
00470  * @param dest          - structure with destination data from packet
00471  * @param protocol      - type of transport protocol of the packet
00472  * @return action taken with the current packet (permit/deny)
00473  * @see processPacket()
00474  */
00475 bool acl::filterPacket(TACL* acl, TIP source, TIP dest, int protocol)
00476 {
00477         for (TACL_it it = acl->begin(); it != acl->end(); it++)
00478         {
00479                 if (!(it->protocol == protocol || it->protocol == PROT_IP))
00480                   continue;
00481                 ev << "acl::filterPacket: PROTOCOL MATCH" << endl;
00482                 if (!ipIsEqual(&(it->source), &source))
00483                   continue;
00484                 ev << "acl::filterPacket: SOURCE IP MATCH" << endl;
00485                 if (it->protocol == PROT_UDP || it->protocol == PROT_TCP)
00486                 {
00487                   if (!portIsEqual(&(it->source), &source))
00488                           continue;
00489                   else
00490                           ev << "acl::filterPacket: SOURCE PORT MATCH" << endl;
00491                 }
00492                 if (!ipIsEqual(&(it->dest), &dest))
00493                   continue;
00494                 ev << "acl::filterPacket: DESTINATION IP MATCH" << endl;
00495                 if (it->protocol == PROT_UDP || it->protocol == PROT_TCP)
00496                 {
00497                   if (!portIsEqual(&(it->dest), &dest))
00498                           continue;
00499                   else
00500                           ev << "acl::filterPacket: DESTINATION PORT MATCH" << endl;
00501                 }
00502                 (*(it->used))++;
00503                 return it->action; // if match is found with current record of ACL, action is returned
00504         }
00505         cout << "BUG" << endl;
00506         return false; // if no match in whole ACL is found
00507 }
00508 
00509 /*
00510  * handleMessage(): HANDLE MESSAGE
00511  * Method that is processing current message arrived to gate.
00512  * It checks the index of the arrival gate, its name and index,
00513  * direction of communication according to which gate a packet came.
00514  * Some action is done with the message, it is being forwarded if no
00515  * ACL configuration is found for this router in XML file.
00516  * It also checks the type of packet. If it differs from IPDatagram,
00517  * it just forwards the message. Else it casts it to IPDatagram type.
00518  * @param msg           - original message arriving to gate
00519  */
00520 void acl::handleMessage(cMessage* msg)
00521 {
00522         cGate* gate = msg->getArrivalGate();
00523         string name = gate->getBaseName();
00524         int index = gate->getIndex();
00525         bool dir = true; // packet heading from networkLayer IN to interface (pres ACL); ifIn, ifOut (in == true)
00526         TACL* acl;
00527 
00528         if (name == "toNetworkLayerIn")
00529                 dir = false; // packet heading from interface OUT to networkLayer (pres ACL); toNetworkLayerIn, toNetworkLayerOut
00530                                          // (out == false)
00531         if (!(this->aclEnabled))
00532         { // if ACLs part is NOT listed in XML configuration file for current router
00533                 if (dir)
00534                 {       /* send packet to upper layer: from interface out to networkLayer */
00535                         this->send(msg, "toNetworkLayerOut", index);
00536                         ev << "ACL DISABLED, just directly send from interface out to networkLayer" << endl;
00537                 }
00538                 else
00539                 {       /* send packet to lower layer: from networkLayer out to interface */
00540                         this->send(msg, "ifOut", index);
00541                         ev << "ACL DISABLED, just directly send from networkLayer out to interface" << endl;
00542                 }
00543         }
00544         else  /* ACL configuration part is found on current router (however, ACL list still might be empty */
00545         {
00546                 acl = getRules(index, dir);  // get pointer to ACL list bound within current packet
00547 
00548                 cMessage *copy = msg->dup(); // duplicate the message due to instability during operations with an original message
00549 
00550                 cPacket *test = (cPacket*)(copy);
00551                 string typ = test->getClassName();
00552                 if (typ != "IPDatagram")
00553                 {       // if the message is not an IP packet, message is just forwarded
00554                         if (dir)
00555                         {
00556                                 ev << "Not an IP packet, sending directly from interface out to networkLayer" << endl;
00557                                 this->send (msg, "toNetworkLayerOut", index);
00558                         }
00559                         else
00560                         {
00561                                 ev << "Not an IP packet, sending directly from networkLayer out to interface..." << endl;
00562                                 this->send (msg, "ifOut", index);
00563                         }
00564                 }
00565                 else // if dynamic_cast is correctly done - message is IPDatagram (an IP packet)
00566                 {
00567                         this->numPackets++;
00568                         if (acl == NULL) // doesn't exist ACL for packet's interface and direction
00569                         {
00570                                 ev << "No ACL found for this router/interface." << endl;
00571                                 this->packetsAllowed++;
00572                                 if (dir)
00573                                 {       /* send packet to upper layer: from interface out to networkLayer */
00574                                         this->send(msg, "toNetworkLayerOut", index);
00575                                         ev << "+packet sent to upper layer without ACL action" << endl;
00576                                 }
00577                                 else
00578                                 {       /* send packet to lower layer: from networkLayer out to interface */
00579                                         this->send(msg, "ifOut", index);
00580                                         ev << "+packet sent to lower layer without ACL action" << endl;
00581                                 }
00582                         }
00583                         else // ACL is bound within packet's interface and direction, need to filter
00584                         {
00585                                 ev << "An ACL list bound correctly for this router/interface." << endl;
00586                                 IPDatagram *packet = dynamic_cast<IPDatagram*> (copy); // dynamic_cast is taken
00587                                 if (processPacket(packet, acl)) // action according to ACL is "permit"
00588                                 {
00589                                         if (dir)
00590                                         {       /* send packet to upper layer: from interface out to networkLayer */
00591                                             this->send(msg, "toNetworkLayerOut", index);
00592                                             ev << "+ACL ACTION:  PERMIT +++ from interface out to networkLayer" << endl;
00593                                         }
00594                                         else
00595                                         {       /* send packet to lower layer: from networkLayer out to interface */
00596                                                 this->send(msg, "ifOut", index);
00597                                             ev << "+ACL ACTION:  PERMIT +++ from networkLayer out to interface" << endl;
00598                                         }
00599                                 }
00600                                 else // action according to ACL is "deny"
00601                                 {
00602                                         delete msg;
00603                                 }
00604                         }
00605                 }
00606                 delete copy;
00607         }
00608 }
00609 
00610 /*
00611  * initialize(): INITIALIZE
00612  * An autonomous method that's been called whenever simulation is started.
00613  * It initializes the ACL filtering module for the simulation needs.
00614  * @param stage         - phase of simulation init
00615  */
00616 void acl::initialize(int stage)
00617 {
00618         switch (stage)
00619         {
00620                         case 0: // get access to notification board
00621                                 notificationBoard = NotificationBoardAccess().get();
00622                                 notificationBoard->subscribe(this, NF_INTERFACE_STATE_CHANGED);
00623                                 break;
00624                         case 4: // initialization of the ACL module
00625                                 const char *fileName = par("configFile"); // XML file name read from parameter
00626                                 if (loadConfigFromXML(fileName)) // success loading configuration data from XML file
00627                                 {
00628                                         //cout << "ACL: Configuration successfully loaded." << endl;
00629                                 }
00630                                 else // error loading configuration data from XML file
00631                                 {
00632                                         //cout << "ACL: Error loading configuration." << endl;
00633                                 }
00634                                 /* initialization of ACL action counters - usage in statistics */
00635                                 this->packetsAllowed = 0;
00636                                 this->packetsDropped = 0;
00637                                 this->packetsPermitted = 0;
00638                                 this->numPackets = 0;
00639 
00640                                 /* added class of statistics information onto Watch list */
00641                                 WATCH_LIST(stats);
00642         }
00643 }
00644 
00645 /*
00646  * finish(): FINISH
00647  * An autonomous method that's been called when simulation ends.
00648  * It displays all possible statistics from ACL module activities on console output.
00649  */
00650 void acl::finish()
00651 {
00652   /*
00653         cout << "IP datagrams received: " << this->numPackets << endl;
00654         cout << "IP packets permitted without ACL action: " << this->packetsAllowed  << endl;
00655         cout << "IP packets permitted by ACL action: " << this->packetsPermitted << endl;
00656         cout << "IP packets denied by an ACL action: " << this->packetsDropped << endl;
00657         for (std::list<Stat>::iterator it = this->stats.begin(); it != this->stats.end(); it++)
00658         {
00659                 cout << it->text << " (" << it->used << " matches)" << endl;
00660         }
00661         cout << "--------------------------------------------------------" << endl;
00662         */
00663 }