ICMPv6 Class Reference

#include <ICMPv6.h>

List of all members.


Detailed Description

ICMPv6 implementation.

Public Member Functions

virtual void sendErrorMessage (IPv6Datagram *datagram, ICMPv6Type type, int code)
virtual void sendErrorMessage (cPacket *transportPacket, IPv6ControlInfo *ctrl, ICMPv6Type type, int code)

Protected Member Functions

virtual void sendToIP (ICMPv6Message *msg, const IPv6Address &dest)
virtual void sendToIP (ICMPv6Message *msg)
virtual ICMPv6Message * createDestUnreachableMsg (int code)
virtual ICMPv6Message * createPacketTooBigMsg (int mtu)
virtual ICMPv6Message * createTimeExceededMsg (int code)
virtual ICMPv6Message * createParamProblemMsg (int code)
virtual void initialize ()
virtual void handleMessage (cMessage *msg)
virtual void processICMPv6Message (ICMPv6Message *)
virtual void processEchoRequest (ICMPv6EchoRequestMsg *)
virtual void processEchoReply (ICMPv6EchoReplyMsg *)
virtual void sendEchoRequest (cPacket *)
virtual bool validateDatagramPromptingError (IPv6Datagram *datagram)
virtual void errorOut (ICMPv6Message *)

Member Function Documentation

void ICMPv6::sendErrorMessage ( IPv6Datagram datagram,
ICMPv6Type  type,
int  code 
) [virtual]

This method can be called from other modules to send an ICMPv6 error packet. RFC 2463, Section 3: ICMPv6 Error Messages There are a total of 4 ICMPv6 error messages as described in the RFC. This method will construct and send error messages corresponding to the given type. Error Types:

  • Destination Unreachable Message - 1
  • Packet Too Big Message - 2
  • Time Exceeded Message - 3
  • Parameter Problem Message - 4 Code Types have different semantics for each error type. See RFC 2463.

Referenced by IPv6NeighbourDiscovery::dropQueuedPacketsAwaitingAR(), IPv6NeighbourDiscovery::processIPv6Datagram(), UDP::processUndeliverablePacket(), IPv6FragBuf::purgeStaleFragments(), and sendErrorMessage().

00131 {
00132     Enter_Method("sendErrorMessage(datagram, type=%d, code=%d)", type, code);
00133 
00134     // get ownership
00135     take(origDatagram);
00136 
00137     if (!validateDatagramPromptingError(origDatagram))
00138         return;
00139 
00140     ICMPv6Message *errorMsg;
00141 
00142     if (type == ICMPv6_DESTINATION_UNREACHABLE) errorMsg = createDestUnreachableMsg(code);
00143     //TODO: implement MTU support.
00144     else if (type == ICMPv6_PACKET_TOO_BIG) errorMsg = createPacketTooBigMsg(0);
00145     else if (type == ICMPv6_TIME_EXCEEDED) errorMsg = createTimeExceededMsg(code);
00146     else if (type == ICMPv6_PARAMETER_PROBLEM) errorMsg = createParamProblemMsg(code);
00147     else error("Unknown ICMPv6 error type\n");
00148 
00149     errorMsg->encapsulate(origDatagram);
00150 
00151     // debugging information
00152     EV << "sending ICMP error: (" << errorMsg->getClassName() << ")" << errorMsg->getName()
00153        << " type=" << type << " code=" << code << endl;
00154 
00155     // ICMP message length: the internet header plus the first 8 bytes of
00156     // the original datagram's data is returned to the sender
00157     //errorMessage->setByteLength(4 + origDatagram->getHeaderLength() + 8); FIXME What is this for?
00158 
00159     // if srcAddr is not filled in, we're still in the src node, so we just
00160     // process the ICMP message locally, right away
00161     if (origDatagram->getSrcAddress().isUnspecified())
00162     {
00163         // pretend it came from the IP layer
00164         IPv6ControlInfo *ctrlInfo = new IPv6ControlInfo();
00165         ctrlInfo->setSrcAddr(IPv6Address::LOOPBACK_ADDRESS); // FIXME maybe use configured loopback address
00166         ctrlInfo->setProtocol(IP_PROT_ICMP);
00167         errorMsg->setControlInfo(ctrlInfo);
00168 
00169         // then process it locally
00170         processICMPv6Message(errorMsg);
00171     }
00172     else
00173     {
00174         sendToIP(errorMsg, origDatagram->getSrcAddress());
00175     }
00176 }

void ICMPv6::sendErrorMessage ( cPacket *  transportPacket,
IPv6ControlInfo ctrl,
ICMPv6Type  type,
int  code 
) [virtual]

This method can be called from other modules to send an ICMP error packet in response to a received bogus packet from the transport layer (like UDP). The ICMP error packet needs to include (part of) the original IP datagram, so this function will wrap back the transport packet into the IP datagram based on its IPControlInfo.

00179 {
00180     Enter_Method("sendErrorMessage(transportPacket, ctrl, type=%d, code=%d)", type, code);
00181 
00182     IPv6Datagram *datagram = ctrl->removeOrigDatagram();
00183     datagram->encapsulate(transportPacket);
00184     sendErrorMessage(datagram, type, code);
00185 }

void ICMPv6::sendToIP ( ICMPv6Message *  msg,
const IPv6Address dest 
) [protected, virtual]

Referenced by processEchoRequest(), sendEchoRequest(), and sendErrorMessage().

00188 {
00189 
00190     IPv6ControlInfo *ctrlInfo = new IPv6ControlInfo();
00191     ctrlInfo->setDestAddr(dest);
00192     ctrlInfo->setProtocol(IP_PROT_IPv6_ICMP);
00193     msg->setControlInfo(ctrlInfo);
00194 
00195     send(msg,"ipv6Out");
00196 }

void ICMPv6::sendToIP ( ICMPv6Message *  msg  )  [protected, virtual]

00199 {
00200     // assumes IPControlInfo is already attached
00201     send(msg,"ipv6Out");
00202 }

ICMPv6Message * ICMPv6::createDestUnreachableMsg ( int  code  )  [protected, virtual]

Referenced by sendErrorMessage().

00205 {
00206     ICMPv6DestUnreachableMsg *errorMsg = new ICMPv6DestUnreachableMsg("Dest Unreachable");
00207     errorMsg->setType(ICMPv6_DESTINATION_UNREACHABLE);
00208     errorMsg->setCode(code);
00209     return errorMsg;
00210 }

ICMPv6Message * ICMPv6::createPacketTooBigMsg ( int  mtu  )  [protected, virtual]

Referenced by sendErrorMessage().

00213 {
00214     ICMPv6PacketTooBigMsg *errorMsg = new ICMPv6PacketTooBigMsg("Packet Too Big");
00215     errorMsg->setType(ICMPv6_PACKET_TOO_BIG);
00216     errorMsg->setCode(0);//Set to 0 by sender and ignored by receiver.
00217     errorMsg->setMTU(mtu);
00218     return errorMsg;
00219 }

ICMPv6Message * ICMPv6::createTimeExceededMsg ( int  code  )  [protected, virtual]

Referenced by sendErrorMessage().

00222 {
00223     ICMPv6TimeExceededMsg *errorMsg = new ICMPv6TimeExceededMsg("Time Exceeded");
00224     errorMsg->setType(ICMPv6_TIME_EXCEEDED);
00225     errorMsg->setCode(code);
00226     return errorMsg;
00227 }

ICMPv6Message * ICMPv6::createParamProblemMsg ( int  code  )  [protected, virtual]

Referenced by sendErrorMessage().

00230 {
00231     ICMPv6ParamProblemMsg *errorMsg = new ICMPv6ParamProblemMsg("Parameter Problem");
00232     errorMsg->setType(ICMPv6_PARAMETER_PROBLEM);
00233     errorMsg->setCode(code);
00234     //TODO: What Pointer? section 3.4
00235     return errorMsg;
00236 }

void ICMPv6::initialize (  )  [protected, virtual]

Initialization

00027 {
00028 }

void ICMPv6::handleMessage ( cMessage *  msg  )  [protected, virtual]

Processing of messages that arrive in this module. Messages arrived here could be for ICMP ping requests or ICMPv6 messages that require processing.

00031 {
00032     ASSERT(!msg->isSelfMessage()); // no timers in ICMPv6
00033 
00034     // process arriving ICMP message
00035     if (msg->getArrivalGate()->isName("ipv6In"))
00036     {
00037         EV << "Processing ICMPv6 message.\n";
00038         processICMPv6Message(check_and_cast<ICMPv6Message *>(msg));
00039         return;
00040     }
00041 
00042     // request from application
00043     if (msg->getArrivalGate()->isName("pingIn"))
00044     {
00045         sendEchoRequest(PK(msg));
00046         return;
00047     }
00048 }

void ICMPv6::processICMPv6Message ( ICMPv6Message *  icmpv6msg  )  [protected, virtual]

Referenced by handleMessage(), and sendErrorMessage().

00051 {
00052     ASSERT(dynamic_cast<ICMPv6Message *>(icmpv6msg));
00053     if (dynamic_cast<ICMPv6DestUnreachableMsg *>(icmpv6msg))
00054     {
00055         EV << "ICMPv6 Destination Unreachable Message Received." << endl;
00056         errorOut(icmpv6msg);
00057     }
00058     else if (dynamic_cast<ICMPv6PacketTooBigMsg *>(icmpv6msg))
00059     {
00060         EV << "ICMPv6 Packet Too Big Message Received." << endl;
00061         errorOut(icmpv6msg);
00062     }
00063     else if (dynamic_cast<ICMPv6TimeExceededMsg *>(icmpv6msg))
00064     {
00065         EV << "ICMPv6 Time Exceeded Message Received." << endl;
00066         errorOut(icmpv6msg);
00067     }
00068     else if (dynamic_cast<ICMPv6ParamProblemMsg *>(icmpv6msg))
00069     {
00070         EV << "ICMPv6 Parameter Problem Message Received." << endl;
00071         errorOut(icmpv6msg);
00072     }
00073     else if (dynamic_cast<ICMPv6EchoRequestMsg *>(icmpv6msg))
00074     {
00075         EV << "ICMPv6 Echo Request Message Received." << endl;
00076         processEchoRequest((ICMPv6EchoRequestMsg *)icmpv6msg);
00077     }
00078     else if (dynamic_cast<ICMPv6EchoReplyMsg *>(icmpv6msg))
00079     {
00080         EV << "ICMPv6 Echo Reply Message Received." << endl;
00081         processEchoReply((ICMPv6EchoReplyMsg *)icmpv6msg);
00082     }
00083     else
00084         error("Unknown message type received.\n");
00085 }

void ICMPv6::processEchoRequest ( ICMPv6EchoRequestMsg *  request  )  [protected, virtual]

Respond to the machine that tried to ping us.

Referenced by processICMPv6Message().

00088 {
00089     //Create an ICMPv6 Reply Message
00090     ICMPv6EchoReplyMsg *reply = new ICMPv6EchoReplyMsg("Echo Reply");
00091     reply->setName((std::string(request->getName())+"-reply").c_str());
00092     reply->setType(ICMPv6_ECHO_REPLY);
00093     reply->encapsulate(request->decapsulate());
00094 
00095     // TBD check what to do if dest was multicast etc?
00096     IPv6ControlInfo *ctrl
00097         = check_and_cast<IPv6ControlInfo *>(request->getControlInfo());
00098     IPv6ControlInfo *replyCtrl = new IPv6ControlInfo();
00099     replyCtrl->setProtocol(IP_PROT_IPv6_ICMP);
00100     //set Msg's source addr as the dest addr of request msg.
00101     replyCtrl->setSrcAddr(ctrl->getDestAddr());
00102     //set Msg's dest addr as the source addr of request msg.
00103     replyCtrl->setDestAddr(ctrl->getSrcAddr());
00104     reply->setControlInfo(replyCtrl);
00105 
00106     delete request;
00107     sendToIP(reply);
00108 }

void ICMPv6::processEchoReply ( ICMPv6EchoReplyMsg *  reply  )  [protected, virtual]

Forward the ping reply to the "pingOut" of this module.

Referenced by processICMPv6Message().

00111 {
00112     IPv6ControlInfo *ctrl = check_and_cast<IPv6ControlInfo*>(reply->removeControlInfo());
00113     cPacket *payload = reply->decapsulate();
00114     payload->setControlInfo(ctrl);
00115     delete reply;
00116     send(payload, "pingOut");
00117 }

void ICMPv6::sendEchoRequest ( cPacket *  msg  )  [protected, virtual]

Ping a machine. The information needed to do this is in the cMessage parameter. TODO where in cMessage? document!!!

Referenced by handleMessage().

00120 {
00121     IPv6ControlInfo *ctrl = check_and_cast<IPv6ControlInfo*>(msg->removeControlInfo());
00122     ctrl->setProtocol(IP_PROT_IPv6_ICMP);
00123     ICMPv6EchoRequestMsg *request = new ICMPv6EchoRequestMsg(msg->getName());
00124     request->setType(ICMPv6_ECHO_REQUEST);
00125     request->encapsulate(msg);
00126     request->setControlInfo(ctrl);
00127     sendToIP(request);
00128 }

bool ICMPv6::validateDatagramPromptingError ( IPv6Datagram datagram  )  [protected, virtual]

Validate the received IPv6 datagram before responding with error message.

Referenced by sendErrorMessage().

00239 {
00240     // don't send ICMP error messages for multicast messages
00241     if (origDatagram->getDestAddress().isMulticast())
00242     {
00243         EV << "won't send ICMP error messages for multicast message " << origDatagram << endl;
00244         delete origDatagram;
00245         return false;
00246     }
00247 
00248     // do not reply with error message to error message
00249     if (origDatagram->getTransportProtocol() == IP_PROT_IPv6_ICMP)
00250     {
00251         ICMPv6Message *recICMPMsg = check_and_cast<ICMPv6Message *>(origDatagram->getEncapsulatedMsg());
00252         if (recICMPMsg->getType()<128)
00253         {
00254             EV << "ICMP error received -- do not reply to it" << endl;
00255             delete origDatagram;
00256             return false;
00257         }
00258     }
00259     return true;
00260 }

void ICMPv6::errorOut ( ICMPv6Message *  icmpv6msg  )  [protected, virtual]

Referenced by processICMPv6Message().

00263 {
00264     send(icmpv6msg, "errorOut");
00265 }


The documentation for this class was generated from the following files:

Generated on Fri Mar 20 18:51:19 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5