|
INET Framework for OMNeT++/OMNEST
|
#include <acl.h>
Protected Member Functions | |
| virtual void | handleMessage (cMessage *msg) |
| virtual void | initialize (int stage) |
| virtual void | finish () |
| virtual void | receiveChangeNotification (int category, const cPolymorphic *details) |
| virtual int | numInitStages () const |
Protected Attributes | |
| NotificationBoard * | notificationBoard |
Private Member Functions | |
| bool | loadConfigFromXML (const char *filename) |
| bool | processPacket (IPDatagram *packet, TACL *acl) |
| TACL * | getRules (int gateIndex, bool dir) |
| bool | filterPacket (TACL *acl, TIP source, TIP dest, int protocol) |
| bool | ipIsEqual (TIP *ip, TIP *packet) |
| bool | portIsEqual (TIP *ip, TIP *packet) |
| void | getAction (std::string action, TRule *rule) |
| void | getProtocol (std::string pom, TRule *rule) |
| void | getPort (std::string pom, std::string p_beg, std::string p_end, TIP *ip) |
| void | andIpWithMask (TRule *rule) |
| IPAddress | negateWildcard (IPAddress wc) |
Private Attributes | |
| std::list< TACL > | acls |
| std::list< TInterface > | interfaces |
| std::list< Stat > | stats |
| bool | aclEnabled |
| int | numPackets |
| int | packetsDropped |
| int | packetsPermitted |
| int | packetsAllowed |
| void acl::andIpWithMask | ( | TRule * | rule | ) | [private] |
| bool acl::filterPacket | ( | TACL * | acl, |
| TIP | source, | ||
| TIP | dest, | ||
| int | protocol | ||
| ) | [private] |
Definition at line 475 of file acl.cc.
{
for (TACL_it it = acl->begin(); it != acl->end(); it++)
{
if (!(it->protocol == protocol || it->protocol == PROT_IP))
continue;
ev << "acl::filterPacket: PROTOCOL MATCH" << endl;
if (!ipIsEqual(&(it->source), &source))
continue;
ev << "acl::filterPacket: SOURCE IP MATCH" << endl;
if (it->protocol == PROT_UDP || it->protocol == PROT_TCP)
{
if (!portIsEqual(&(it->source), &source))
continue;
else
ev << "acl::filterPacket: SOURCE PORT MATCH" << endl;
}
if (!ipIsEqual(&(it->dest), &dest))
continue;
ev << "acl::filterPacket: DESTINATION IP MATCH" << endl;
if (it->protocol == PROT_UDP || it->protocol == PROT_TCP)
{
if (!portIsEqual(&(it->dest), &dest))
continue;
else
ev << "acl::filterPacket: DESTINATION PORT MATCH" << endl;
}
(*(it->used))++;
return it->action; // if match is found with current record of ACL, action is returned
}
cout << "BUG" << endl;
return false; // if no match in whole ACL is found
}
| void acl::finish | ( | ) | [protected, virtual] |
Definition at line 650 of file acl.cc.
{
/*
cout << "IP datagrams received: " << this->numPackets << endl;
cout << "IP packets permitted without ACL action: " << this->packetsAllowed << endl;
cout << "IP packets permitted by ACL action: " << this->packetsPermitted << endl;
cout << "IP packets denied by an ACL action: " << this->packetsDropped << endl;
for (std::list<Stat>::iterator it = this->stats.begin(); it != this->stats.end(); it++)
{
cout << it->text << " (" << it->used << " matches)" << endl;
}
cout << "--------------------------------------------------------" << endl;
*/
}
| void acl::getAction | ( | std::string | action, |
| TRule * | rule | ||
| ) | [private] |
| void acl::getPort | ( | std::string | pom, |
| std::string | p_beg, | ||
| std::string | p_end, | ||
| TIP * | ip | ||
| ) | [private] |
Definition at line 155 of file acl.cc.
{
int p1, p2;
stringstream ss (stringstream::in | stringstream::out);
/* if port is given as text string, it is converted to short int number */
if (p_beg == "ftp-data") p1 = 20;
if (p_beg == "ftp") p1 = 21;
if (p_beg == "telnet") p1 = 23;
if (p_beg == "smtp") p1 = 25;
if (p_beg == "tftp") p1 = 69;
if ((p_beg == "www") || (p_beg == "http") || (p_beg == "www-http")) p1 = 80;
if ((p_beg == "pop3") || (p_beg == "pop")) p1 = 110;
if (p_beg == "snmp") p1 = 161;
if (p_beg == "irc") p1 = 194;
if (p_beg == "ipx") p1 = 213;
if (p_beg == "ldap") p1 = 389;
if (p_beg == "https") p1 = 443;
ss << p_beg;
ss >> p1;
ss << p_end;
ss >> p2;
/* resolution of port operators*/
if (pom == "eq") // EQ
ip->port_op = PORT_EQ;
else if (pom == "neq") // NEQ
ip->port_op = PORT_NEQ;
else if (pom == "gt") // GT
ip->port_op = PORT_GT;
else if (pom == "lt") // LT
ip->port_op = PORT_LT;
else if (pom == "range") // RANGE
ip->port_op = PORT_RNG;
else // if port operator is "" or not defined: NDEF
{
ip->port_op = PORT_NDEF;
}
switch (ip->port_op) { // based on presence of current port operator
case PORT_EQ:
case PORT_NEQ:
case PORT_GT:
case PORT_LT: // if operator is any of following [eq, neq, gt, lt]: load only one port no. from portBeg
ip->portBeg = p1;
break;
case PORT_RNG: // if operator = RANGE, load two port number in the range of portBeg to portEnd
ip->portBeg = p1;
ip->portEnd = p2;
break;
case PORT_NDEF: // if any port operator is present, port range is full range of ports [0 - 65535]
ip->portBeg = 0;
ip->portEnd = 65535;
break;
}
}
| void acl::getProtocol | ( | std::string | pom, |
| TRule * | rule | ||
| ) | [private] |
Definition at line 127 of file acl.cc.
{
if (pom == "ip" || pom == "4")
rule->protocol = PROT_IP;
else if (pom == "tcp" || pom == "6")
rule->protocol = PROT_TCP;
else if (pom == "udp" || pom == "17")
rule->protocol = PROT_UDP;
else if (pom == "icmp" || pom == "1")
rule->protocol = PROT_ICMP;
else if (pom == "igmp" || pom == "2")
rule->protocol = PROT_IGMP;
else if (pom == "eigrp" || pom == "igrp" || pom == "88")
rule->protocol = PROT_EIGRP;
else if (pom == "ospf" || pom == "89")
rule->protocol = PROT_OSPF;
}
| TACL * acl::getRules | ( | int | gateIndex, |
| bool | dir | ||
| ) | [private] |
Definition at line 391 of file acl.cc.
{
for (std::list<TInterface>::iterator it = this->interfaces.begin(); it != this->interfaces.end(); it++)
{
TInterface* _if = &(*it);
if (_if->gateIndex == gateIndex && _if->dir == dir)
return _if->rules;
}
return NULL;
}
| void acl::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
Definition at line 520 of file acl.cc.
{
cGate* gate = msg->getArrivalGate();
string name = gate->getBaseName();
int index = gate->getIndex();
bool dir = true; // packet heading from networkLayer IN to interface (pres ACL); ifIn, ifOut (in == true)
TACL* acl;
if (name == "toNetworkLayerIn")
dir = false; // packet heading from interface OUT to networkLayer (pres ACL); toNetworkLayerIn, toNetworkLayerOut
// (out == false)
if (!(this->aclEnabled))
{ // if ACLs part is NOT listed in XML configuration file for current router
if (dir)
{ /* send packet to upper layer: from interface out to networkLayer */
this->send(msg, "toNetworkLayerOut", index);
ev << "ACL DISABLED, just directly send from interface out to networkLayer" << endl;
}
else
{ /* send packet to lower layer: from networkLayer out to interface */
this->send(msg, "ifOut", index);
ev << "ACL DISABLED, just directly send from networkLayer out to interface" << endl;
}
}
else /* ACL configuration part is found on current router (however, ACL list still might be empty */
{
acl = getRules(index, dir); // get pointer to ACL list bound within current packet
cMessage *copy = msg->dup(); // duplicate the message due to instability during operations with an original message
cPacket *test = (cPacket*)(copy);
string typ = test->getClassName();
if (typ != "IPDatagram")
{ // if the message is not an IP packet, message is just forwarded
if (dir)
{
ev << "Not an IP packet, sending directly from interface out to networkLayer" << endl;
this->send (msg, "toNetworkLayerOut", index);
}
else
{
ev << "Not an IP packet, sending directly from networkLayer out to interface..." << endl;
this->send (msg, "ifOut", index);
}
}
else // if dynamic_cast is correctly done - message is IPDatagram (an IP packet)
{
this->numPackets++;
if (acl == NULL) // doesn't exist ACL for packet's interface and direction
{
ev << "No ACL found for this router/interface." << endl;
this->packetsAllowed++;
if (dir)
{ /* send packet to upper layer: from interface out to networkLayer */
this->send(msg, "toNetworkLayerOut", index);
ev << "+packet sent to upper layer without ACL action" << endl;
}
else
{ /* send packet to lower layer: from networkLayer out to interface */
this->send(msg, "ifOut", index);
ev << "+packet sent to lower layer without ACL action" << endl;
}
}
else // ACL is bound within packet's interface and direction, need to filter
{
ev << "An ACL list bound correctly for this router/interface." << endl;
IPDatagram *packet = dynamic_cast<IPDatagram*> (copy); // dynamic_cast is taken
if (processPacket(packet, acl)) // action according to ACL is "permit"
{
if (dir)
{ /* send packet to upper layer: from interface out to networkLayer */
this->send(msg, "toNetworkLayerOut", index);
ev << "+ACL ACTION: PERMIT +++ from interface out to networkLayer" << endl;
}
else
{ /* send packet to lower layer: from networkLayer out to interface */
this->send(msg, "ifOut", index);
ev << "+ACL ACTION: PERMIT +++ from networkLayer out to interface" << endl;
}
}
else // action according to ACL is "deny"
{
delete msg;
}
}
}
delete copy;
}
}
| void acl::initialize | ( | int | stage | ) | [protected, virtual] |
Definition at line 616 of file acl.cc.
{
switch (stage)
{
case 0: // get access to notification board
notificationBoard = NotificationBoardAccess().get();
notificationBoard->subscribe(this, NF_INTERFACE_STATE_CHANGED);
break;
case 4: // initialization of the ACL module
const char *fileName = par("configFile"); // XML file name read from parameter
if (loadConfigFromXML(fileName)) // success loading configuration data from XML file
{
//cout << "ACL: Configuration successfully loaded." << endl;
}
else // error loading configuration data from XML file
{
//cout << "ACL: Error loading configuration." << endl;
}
/* initialization of ACL action counters - usage in statistics */
this->packetsAllowed = 0;
this->packetsDropped = 0;
this->packetsPermitted = 0;
this->numPackets = 0;
/* added class of statistics information onto Watch list */
WATCH_LIST(stats);
}
}
| bool acl::ipIsEqual | ( | TIP * | ip, |
| TIP * | packet | ||
| ) | [private] |
Definition at line 24 of file acl.cc.
{
ev << "ACL rule, ip : " << ip->ipAddr.str() << endl;
ev << "ACL rule, mask: " << ip->netmask.str() << endl;
ev << "packet, ip : " << packet->ipAddr.str() << endl;
ev << "packet_masked : " << packet->ipAddr.doAnd(ip->netmask).str() << endl;
if (ip->ipAddr != (packet->ipAddr.doAnd(ip->netmask)))
{
ev << "IP DOESN'T MATCH" << endl;
return false;
}
ev << "IP MATCH OK" << endl;
return true;
}
| bool acl::loadConfigFromXML | ( | const char * | filename | ) | [private] |
Definition at line 219 of file acl.cc.
{
/* get access into Routing Table and Interface Table modules */
IRoutingTable* rt = RoutingTableAccess().get();
IInterfaceTable* ift = InterfaceTableAccess().get();
/* resolution of configuration XML file according to specified filename */
cXMLElement* document = ev.getXMLDocument(fileName);
if (document == NULL)
{ /* if no file with such name is provided, error is recognized */
error("Cannot read AS configuration from file %s", fileName);
return false;
}
/* try to find current router in XML on running instance of this ACL module */
std::string routerXPath("Router[@id='");
std::string routerId = rt->getRouterId().str();
routerXPath += routerId;
routerXPath += "']";
cXMLElement* router = document->getElementByPath(routerXPath.c_str());
if (router == NULL)
{ /* current router configuration is completely missing in XML configuration - error */
error("No configuration for Router ID: %s", routerId.c_str());
this->aclEnabled = false;
return true;
}
cXMLElement* ACLs = router->getFirstChildWithTag("ACLs"); // find ACL configuration part
if (ACLs == NULL)
{ /* ACL configuration part is missing in XML configuration */
//cout << "ACL: ACL is NOT ENABLED on Router id = " << routerId.c_str() << endl;
this->aclEnabled = false; // ACL indicator is FALSE
return true;
}
cXMLElement* ACL = ACLs->getFirstChildWithTag("ACL");
if (ACL == NULL)
{
//cout << "ACL: ACL is NOT ENABLED on Router id = " << routerId.c_str() << endl;
this->aclEnabled = false;
return true;
}
else
{
this->aclEnabled = true;
//cout << "ACL: Loading ACL entries for Router id = " << routerId.c_str() << "\n";
}
while (ACL != NULL)
{
cXMLElement *entry = ACL->getFirstChildWithTag("entry");
TACL _acl;
while (entry != NULL)
{
cXMLElement *leaf = entry->getFirstChild();
TRule rule;
Stat stat;
stat.used = 0;
std::string src_port_op = "";
std::string src_port_beg = "";
std::string src_port_end = "";
std::string dst_port_op = "";
std::string dst_port_beg = "";
std::string dst_port_end = "";
/* processing current leaf under XML node <entry> */
while (leaf != NULL)
{
const char* tagName = leaf->getTagName();
const char* value = leaf->getNodeValue();
if (strcmp(tagName, "action") == 0)
getAction(value, &rule);
else if (strcmp(tagName, "IP_src") == 0)
rule.source.ipAddr.set(value);
else if (strcmp(tagName, "WC_src") == 0)
rule.source.netmask = negateWildcard(IPAddress(value));
else if (strcmp(tagName, "protocol") == 0)
getProtocol(value, &rule);
else if (strcmp(tagName, "IP_dst") == 0)
rule.dest.ipAddr.set(value);
else if (strcmp(tagName, "WC_dst") == 0)
rule.dest.netmask = negateWildcard(IPAddress(value));
else if (strcmp(tagName, "port_op_src") == 0)
src_port_op = value;
else if (strcmp(tagName, "port_beg_src") == 0)
src_port_beg = value;
else if (strcmp(tagName, "port_end_src") == 0)
src_port_end = value;
else if (strcmp(tagName, "port_op_dst") == 0)
dst_port_op = value;
else if (strcmp(tagName, "port_beg_dst") == 0)
dst_port_beg = value;
else if (strcmp(tagName, "port_end_dst") == 0)
dst_port_end = value;
else if (strcmp(tagName, "orig") == 0)
stat.text = value;
leaf = leaf->getNextSibling();
}
/* AND (&) IP ADDRESS WITH NETWORK MASK IN CURRENT ACL RULE */
andIpWithMask(&rule);
/* PROCESS PORT INFORMATION FROM XML CONFIGURATION FILE */
getPort(src_port_op, src_port_beg, src_port_end, &rule.source);
getPort(dst_port_op, dst_port_beg, dst_port_end, &rule.dest);
/* generate statistics for processed rule */
stats.push_back(stat);
Stat* pStat = &this->stats.back();
rule.used = &(pStat->used);
_acl.push_back(rule); // processed rule is added at the end of ACL list
entry = entry->getNextSiblingWithTag("entry");
}
/* create default rule at the end of the ACL list - deny ip any any */
TRule rule;
Stat stat;
stat.used = 0;
rule.action = A_DENY;
rule.protocol = PROT_IP;
stat.text = "access-list deny ip any any";
rule.source.ipAddr.set("0.0.0.0");
rule.dest.ipAddr.set("0.0.0.0");
rule.source.netmask.set("0.0.0.0");
rule.dest.netmask.set("0.0.0.0");
getPort("", "", "", &rule.source);
getPort("", "", "", &rule.dest);
/* generate statistics for the default rule*/
stats.push_back(stat);
Stat* pStat = &this->stats.back();
rule.used = &(pStat->used);
_acl.push_back(rule); // implicit rule is finally added at the end of the list
this->acls.push_back(_acl); // current ACL list is added at the end of ACLs (list of lists)
cXMLElement *interfaces = ACL->getFirstChildWithTag("interfaces");
cXMLElement *interface = interfaces->getFirstChildWithTag("interface");
/* processing interface information - binding ACL list to interface and direction */
while (interface != NULL)
{
InterfaceEntry *targetInt = ift->getInterfaceByName(interface->getNodeValue());
TInterface _if;
_if.gateIndex = targetInt->getNetworkLayerGateIndex();
if (interface->getAttribute("dir") == std::string("in"))
_if.dir = true;
else
_if.dir = false;
_if.rules = &this->acls.back();
this->interfaces.push_back(_if);
interface = interface->getNextSibling();
}
ACL = ACL->getNextSiblingWithTag("ACL");
}
return true;
}
| IPAddress acl::negateWildcard | ( | IPAddress | wc | ) | [private] |
| virtual int acl::numInitStages | ( | ) | const [inline, protected, virtual] |
| bool acl::portIsEqual | ( | TIP * | ip, |
| TIP * | packet | ||
| ) | [private] |
Definition at line 48 of file acl.cc.
{
switch (ip->port_op) {
case PORT_EQ:
if (ip->portBeg == packet->portBeg)
return true;
break;
case PORT_NEQ:
if (ip->portBeg != packet->portBeg)
return true;
break;
case PORT_GT:
if (ip->portBeg < packet->portBeg)
return true;
break;
case PORT_LT:
if (ip->portBeg > packet->portBeg)
return true;
break;
case PORT_RNG:
case PORT_NDEF:
if ((ip->portBeg <= packet->portBeg) && (ip->portEnd >= packet->portBeg))
return true;
break;
default:
cout << "BUG" << endl;
}
return false;
}
| bool acl::processPacket | ( | IPDatagram * | packet, |
| TACL * | acl | ||
| ) | [private] |
Definition at line 413 of file acl.cc.
{
TIP source, dest;
source.ipAddr = packet->getSrcAddress();
dest.ipAddr = packet->getDestAddress();
int protocol = packet->getTransportProtocol();
ev << "Packet Source IP Address: " << source.ipAddr.str() << endl;
ev << "Packet Dest. IP Address: " << dest.ipAddr.str() << endl;
ev << "Packet Protocol ID : " << protocol << endl;
UDPPacket *udppacket;
TCPSegment *tcppacket;
switch (protocol)
{
case PROT_UDP: // if protocol is UDP, ports need to be checked
udppacket = dynamic_cast<UDPPacket *> (packet->decapsulate());
source.portBeg = udppacket->getSourcePort();
ev << "UDP packet, source port: " << source.portBeg << endl;
dest.portBeg = udppacket->getDestinationPort();
ev << "UDP packet, dest. port: " << dest.portBeg << endl;
delete udppacket;
break;
case PROT_TCP: // if protocol is TCP, ports need to be checked
tcppacket = dynamic_cast<TCPSegment *> (packet->decapsulate());
source.portBeg = tcppacket->getSrcPort();
ev << "TCP packet, source port: " << source.portBeg << endl;
dest.portBeg = tcppacket->getDestPort();
ev << "TCP packet, dest. port: " << dest.portBeg << endl;
delete tcppacket;
break;
default:
ev << "Protocol is other than TCP or UDP, ports don't need to be checked..." << endl;
break;
}
if (filterPacket(acl, source, dest, protocol))
{
// rule is 'permit'
this->packetsPermitted++;
return true;
}
else
{
ev << "- ACL ACTION: DENY, packet dropped ---" << endl;
this->packetsDropped++;
return false;
}
}
| virtual void acl::receiveChangeNotification | ( | int | category, |
| const cPolymorphic * | details | ||
| ) | [inline, protected, virtual] |
Called by the NotificationBoard whenever a change of a category occurs to which this client has subscribed.
Implements INotifiable.
Definition at line 119 of file acl.h.
{}
bool acl::aclEnabled [private] |
std::list<TInterface> acl::interfaces [private] |
NotificationBoard* acl::notificationBoard [protected] |
int acl::numPackets [private] |
int acl::packetsAllowed [private] |
int acl::packetsDropped [private] |
int acl::packetsPermitted [private] |
std::list<Stat> acl::stats [private] |