#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 }
|