diff --git a/src/applications/generic/IPvXTrafGen.cc b/src/applications/generic/IPvXTrafGen.cc index 599711157f4..76b8c78923b 100644 --- a/src/applications/generic/IPvXTrafGen.cc +++ b/src/applications/generic/IPvXTrafGen.cc @@ -24,6 +24,8 @@ #include "IPvXAddressResolver.h" #include "IPv4ControlInfo.h" #include "IPv6ControlInfo.h" +#include "IPv6ExtensionHeaders.h" +#include "IPv4Datagram.h" Define_Module(IPvXTrafGen); @@ -187,6 +189,11 @@ void IPvXTrafGen::sendPacket() IPv4ControlInfo *controlInfo = new IPv4ControlInfo(); controlInfo->setDestAddr(destAddr.get4()); controlInfo->setProtocol(protocol); + if (par("routerAlert").boolValue() == true) + { + controlInfo->setOptions(IPOPTION_ROUTER_ALERT); + } + controlInfo->setOptions(148); payload->setControlInfo(controlInfo); gate = "ipOut"; } @@ -196,6 +203,14 @@ void IPvXTrafGen::sendPacket() IPv6ControlInfo *controlInfo = new IPv6ControlInfo(); controlInfo->setDestAddr(destAddr.get6()); controlInfo->setProtocol(protocol); + if (par("routerAlert").boolValue() == true) + { + // TODO how do we do this extension header handling elegantly? + IPv6HopByHopOptionsHeader *hdr = new IPv6HopByHopOptionsHeader(); + hdr->setOptionsArraySize(1); + hdr->setOptions(0, new IPv6OptionRouterAlert()); + controlInfo->addExtensionHeader(hdr); + } payload->setControlInfo(controlInfo); gate = "ipv6Out"; } diff --git a/src/applications/generic/IPvXTrafGen.ned b/src/applications/generic/IPvXTrafGen.ned index b4e2cea121b..7d92c8f65ba 100644 --- a/src/applications/generic/IPvXTrafGen.ned +++ b/src/applications/generic/IPvXTrafGen.ned @@ -41,6 +41,7 @@ simple IPvXTrafGen like IIPvXTrafficGenerator int protocol; // value for ~IPv4ControlInfo / ~IPv6ControlInfo protocol field volatile int packetLength @unit("B"); // packet length in bytes string destAddresses = default(""); // list of destination addresses, separated by spaces + bool routerAlert = default(false); // set the router alert header option @display("i=block/source"); @signal[sentPk](type=cPacket); @signal[rcvdPk](type=cPacket); diff --git a/src/networklayer/common/IRouterAlertHandler.h b/src/networklayer/common/IRouterAlertHandler.h new file mode 100644 index 00000000000..ef4a566ccc5 --- /dev/null +++ b/src/networklayer/common/IRouterAlertHandler.h @@ -0,0 +1,29 @@ +// +// Copyright (C) 2013 Markus Brueckner +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#ifndef IROUTERALERTHANDLER_H_ +#define IROUTERALERTHANDLER_H_ + +/** + * Base class for all router alert handlers. See the NED file for more + * information. + */ +class IRouterAlertHandler : public cSimpleModule +{ +}; + +#endif /* IROUTERALERTHANDLER_H_ */ diff --git a/src/networklayer/common/IRouterAlertHandler.ned b/src/networklayer/common/IRouterAlertHandler.ned new file mode 100644 index 00000000000..dc0142662a0 --- /dev/null +++ b/src/networklayer/common/IRouterAlertHandler.ned @@ -0,0 +1,35 @@ +// +// Copyright (C) 2013 Markus Brueckner +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +package inet.networklayer.common; + +// generic router alert handler interface +// This interface can be sub-classed by modules interested in intercepting +// IPv4 and IPv6 packets with the Router Alert option set. The interface +// offers two gates: one for receiving packets from the network layer (routerAlertIn) +// and one for re-injecting packets into the network layer (routerAlertReturn). +// Packets arriving at routerAlertIn are handed over to the module completely. +// If the packets are to be sent onwards along the normal routing path, they +// have to be re-injected via the routerAlertReturn gate. +moduleinterface IRouterAlertHandler +{ + parameters: + @display("i=block/control_s"); + gates: + input routerAlertIn @labels(IPv4Datagram,IPv6Datagram); + output routerAlertReturn @labels(IPv4Datagram,IPv6Datagram); +} \ No newline at end of file diff --git a/src/networklayer/contract/IPv4ControlInfo.msg b/src/networklayer/contract/IPv4ControlInfo.msg index 69c09fc12ea..a8b21f6240c 100644 --- a/src/networklayer/contract/IPv4ControlInfo.msg +++ b/src/networklayer/contract/IPv4ControlInfo.msg @@ -74,6 +74,7 @@ class IPv4ControlInfo abstract int explicitCongestionNotification; // maps to bits 6-7 of trafficClass short timeToLive; // maximum hop count bool dontFragment; // "don't fragment" bit + int options; // The "options" header field // The following fields are used in the DSR protocol; TODO revise IPv4Address nextHopAddr; // next hop address (DSR) diff --git a/src/networklayer/ipv4/IPv4.cc b/src/networklayer/ipv4/IPv4.cc index c9d9fa80bb9..aec3bb13121 100644 --- a/src/networklayer/ipv4/IPv4.cc +++ b/src/networklayer/ipv4/IPv4.cc @@ -177,6 +177,22 @@ void IPv4::handlePacketFromNetwork(IPv4Datagram *datagram, InterfaceEntry *fromI EV << "Received datagram `" << datagram->getName() << "' with dest=" << destAddr << "\n"; + // handle router alert option field -> This ist handled only on intermediate routers and not on the endpoints + // also the packet is not handled again if it returns from the router alert handler + if ((!datagram->getArrivalGate()->isName("routerAlertReturn")) && !(rt->isLocalAddress(destAddr)) && datagram->getOptionCode() == IPOPTION_ROUTER_ALERT) // FIXME If the option code handling is changed to support multiple options, we have to change this here too + { + // send the datagram to the router alert gate + cGate *rout = gate("routerAlertOut"); + if (rout != 0 && rout->isConnected()) { + send(datagram, rout); + // bail out of the handling. The packet has to be re-injected by the Option handler, when needed + return; // FIXME maybe implement without return? + } + else { + EV << "Router alert option set, but no handler connected. Ignoring.\n"; + } + } + if (fromIE->isLoopback()) { reassembleAndDeliver(datagram); @@ -805,7 +821,9 @@ IPv4Datagram *IPv4::encapsulate(cPacket *transportPacket, IPv4ControlInfo *contr datagram->setTimeToLive(ttl); datagram->setTransportProtocol(controlInfo->getProtocol()); - // setting IPv4 options is currently not supported + if (controlInfo->getOptions() != 0) { + datagram->setOptionCode(controlInfo->getOptions()); // FIXME will only work so long as only one option header is supported + } return datagram; } diff --git a/src/networklayer/ipv4/IPv4.ned b/src/networklayer/ipv4/IPv4.ned index 4b532568bce..8940f0fc7c1 100644 --- a/src/networklayer/ipv4/IPv4.ned +++ b/src/networklayer/ipv4/IPv4.ned @@ -77,7 +77,15 @@ package inet.networklayer.ipv4; // method which determines processing time for a packet, or (2) use a // different base class. // -// @see ~RoutingTable, ~IPv4ControlInfo, ~IPv4RoutingDecision, ~ARP +// Packet interception
+// +// Implementers interested in intercepting packets that pass through the IP layer +// can hook a ~IRouterAlertHandler-like module to the routerAlertOut gate. The +// IP module will then hand over all packets carrying the router alert option field +// to this module for detailled processing. In order to carry on with normal routing, +// packets must be returned using the routerAlertReturn gate. +// +// @see ~RoutingTable, ~IPv4ControlInfo, ~IPv4RoutingDecision, ~ARP, ~IRouterAlertHandler // // @author Andras Varga // @@ -96,4 +104,6 @@ simple IPv4 output transportOut[] @labels(IPv4ControlInfo/up,TCPSegment,UDPPacket); input queueIn[] @labels(IPv4Datagram); output queueOut @labels(IPv4Datagram); + output routerAlertOut @labels(IPv4Datagram); + input routerAlertReturn @labels(IPv4Datagram); } diff --git a/src/networklayer/ipv6/IPv6.cc b/src/networklayer/ipv6/IPv6.cc index 368d7de1a5a..825f23795bf 100644 --- a/src/networklayer/ipv6/IPv6.cc +++ b/src/networklayer/ipv6/IPv6.cc @@ -152,6 +152,32 @@ void IPv6::endService(cPacket *msg) // 2. The Ethernet or PPP frame is dropped by the link-layer if there is a transmission error. ASSERT(!datagram->hasBitError()); + if (!rt->isLocalAddress(datagram->getDestAddress())) + { + // handle router alert options, if set + cGate *rout = gate("routerAlertOut"); + // only check if we have a handler and this datagram wasn't returned from it already + if (rout && rout->isConnected() && !(datagram->arrivedOn("routerAlertReturn"))) + { + for (int i = datagram->getExtensionHeaderArraySize() - 1; i >= 0; --i) + { + // check whether the router alert extension header is set + IPv6ExtensionHeaderPtr extHdr = datagram->getExtensionHeader(i); + if (extHdr->getExtensionType() == IP_PROT_IPv6EXT_HOP) { + // check whether the router alert option is set + IPv6HopByHopOptionsHeader *optHdr = check_and_cast