#include <ICMPv6.h>
Public Member Functions | |
| void | sendErrorMessage (IPv6Datagram *datagram, ICMPv6Type type, int code) |
| void | sendErrorMessage (cMessage *transportPacket, IPv6ControlInfo *ctrl, ICMPv6Type type, int code) |
Protected Member Functions | |
| void | sendToIP (ICMPv6Message *msg, const IPv6Address &dest) |
| void | sendToIP (ICMPv6Message *msg) |
| ICMPv6Message * | createDestUnreachableMsg (int code) |
| ICMPv6Message * | createPacketTooBigMsg (int mtu) |
| ICMPv6Message * | createTimeExceededMsg (int code) |
| 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 (cMessage *) |
| bool | validateDatagramPromptingError (IPv6Datagram *datagram) |
| virtual void | errorOut (ICMPv6Message *) |
|
|
00204 {
00205 ICMPv6DestUnreachableMsg *errorMsg
00206 = new ICMPv6DestUnreachableMsg("Dest Unreachable");
00207 errorMsg->setType(ICMPv6_DESTINATION_UNREACHABLE);
00208 errorMsg->setCode(code);
00209 return errorMsg;
00210 }
|
|
|
00213 {
00214 ICMPv6PacketTooBigMsg *errorMsg
00215 = new ICMPv6PacketTooBigMsg("Packet Too Big");
00216 errorMsg->setType(ICMPv6_PACKET_TOO_BIG);
00217 errorMsg->setCode(0);//Set to 0 by sender and ignored by receiver.
00218 errorMsg->setMTU(mtu);
00219 return errorMsg;
00220 }
|
|
|
|
|
|
00223 {
00224 ICMPv6TimeExceededMsg *errorMsg
00225 = new ICMPv6TimeExceededMsg("Time Exceeded");
00226 errorMsg->setType(ICMPv6_TIME_EXCEEDED);
00227 errorMsg->setCode(code);
00228 return errorMsg;
00229 }
|
|
|
00266 {
00267 send(icmpv6msg, "errorOut");
00268 }
|
|
|
Processing of messages that arrive in this module. Messages arrived here could be for ICMP ping requests or ICMPv6 messages that require processing. 00033 {
00034 // process arriving ICMP message
00035 if (msg->arrivalGate()->isName("fromIPv6"))
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->arrivalGate()->isName("pingIn"))
00044 {
00045 sendEchoRequest(msg);
00046 return;
00047 }
00048 }
|
|
|
Initialization 00028 {
00029 //...
00030 }
|
|
|
Forward the ping reply to the "pingOut" of this module. 00111 {
00112 IPv6ControlInfo *ctrl = check_and_cast<IPv6ControlInfo*>(reply->removeControlInfo());
00113 cMessage *payload = reply->decapsulate();
00114 payload->setControlInfo(ctrl);
00115 delete reply;
00116 send(payload, "pingOut");
00117 }
|
|
|
Respond to the machine that tried to ping us. 00088 {
00089 //Create an ICMPv6 Reply Message
00090 ICMPv6EchoReplyMsg *reply = new ICMPv6EchoReplyMsg("Echo Reply");
00091 reply->setName((std::string(request->name())+"-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->controlInfo());
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->destAddr());
00102 //set Msg's dest addr as the source addr of request msg.
00103 replyCtrl->setDestAddr(ctrl->srcAddr());
00104 reply->setControlInfo(replyCtrl);
00105
00106 delete request;
00107 sendToIP(reply);
00108 }
|
|
|
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 }
|
|
|
Ping a machine. The information needed to do this is in the cMessage parameter. TODO where in cMessage? document!!! 00120 {
00121 IPv6ControlInfo *ctrl = check_and_cast<IPv6ControlInfo*>(msg->removeControlInfo());
00122 ctrl->setProtocol(IP_PROT_IPv6_ICMP);
00123 ICMPv6EchoRequestMsg *request = new ICMPv6EchoRequestMsg(msg->name());
00124 request->setType(ICMPv6_ECHO_REQUEST);
00125 request->encapsulate(msg);
00126 request->setControlInfo(ctrl);
00127 sendToIP(request);
00128 }
|
|
||||||||||||||||||||
|
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. 00178 {
00179 Enter_Method("sendErrorMessage(transportPacket, ctrl, type=%d, code=%d)", type, code);
00180
00181 IPv6Datagram *datagram = ctrl->removeOrigDatagram();
00182 datagram->encapsulate(transportPacket);
00183 sendErrorMessage(datagram, type, code);
00184 }
|
|
||||||||||||||||
|
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:
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 // ICMP message length: the internet header plus the first 8 bytes of
00152 // the original datagram's data is returned to the sender
00153 //errorMessage->setByteLength(4 + origDatagram->headerLength() + 8); FIXME What is this for?
00154
00155 // if srcAddr is not filled in, we're still in the src node, so we just
00156 // process the ICMP message locally, right away
00157 if (origDatagram->srcAddress().isUnspecified())
00158 {
00159 // pretend it came from the IP layer
00160 IPv6ControlInfo *ctrlInfo = new IPv6ControlInfo();
00161 ctrlInfo->setSrcAddr(IPv6Address::LOOPBACK_ADDRESS); // FIXME maybe use configured loopback address
00162 ctrlInfo->setProtocol(IP_PROT_ICMP);
00163 errorMsg->setControlInfo(ctrlInfo);
00164
00165 // then process it locally
00166 handleMessage(errorMsg);
00167 }
00168 else
00169 {
00170 sendToIP(errorMsg, origDatagram->srcAddress());
00171 }
00172
00173 // debugging information
00174 //EV << "sending ICMP error: " << errorMsg->type() << " / " << errorMsg->code() << endl;
00175 }
|
|
|
00198 {
00199 // assumes IPControlInfo is already attached
00200 send(msg,"toIPv6");
00201 }
|
|
||||||||||||
|
00187 {
00188
00189 IPv6ControlInfo *ctrlInfo = new IPv6ControlInfo();
00190 ctrlInfo->setDestAddr(dest);
00191 ctrlInfo->setProtocol(IP_PROT_IPv6_ICMP);
00192 msg->setControlInfo(ctrlInfo);
00193
00194 send(msg,"toIPv6");
00195 }
|
|
|
Validate the received IPv6 datagram before responding with error message. 00242 {
00243 // don't send ICMP error messages for multicast messages
00244 if (origDatagram->destAddress().isMulticast())
00245 {
00246 EV << "won't send ICMP error messages for multicast message " << origDatagram << endl;
00247 delete origDatagram;
00248 return false;
00249 }
00250
00251 // do not reply with error message to error message
00252 if (origDatagram->transportProtocol() == IP_PROT_IPv6_ICMP)
00253 {
00254 ICMPv6Message *recICMPMsg = check_and_cast<ICMPv6Message *>(origDatagram->encapsulatedMsg());
00255 if (recICMPMsg->type()<128)
00256 {
00257 EV << "ICMP error received -- do not reply to it" << endl;
00258 delete origDatagram;
00259 return false;
00260 }
00261 }
00262 return true;
00263 }
|
1.4.1