#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 *) |
ICMPv6Message * ICMPv6::createDestUnreachableMsg | ( | int | code | ) | [protected] |
00206 { 00207 ICMPv6DestUnreachableMsg *errorMsg = new ICMPv6DestUnreachableMsg("Dest Unreachable"); 00208 errorMsg->setType(ICMPv6_DESTINATION_UNREACHABLE); 00209 errorMsg->setCode(code); 00210 return errorMsg; 00211 }
ICMPv6Message * ICMPv6::createPacketTooBigMsg | ( | int | mtu | ) | [protected] |
00214 { 00215 ICMPv6PacketTooBigMsg *errorMsg = 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 }
ICMPv6Message * ICMPv6::createParamProblemMsg | ( | int | code | ) | [protected] |
00231 { 00232 ICMPv6ParamProblemMsg *errorMsg = new ICMPv6ParamProblemMsg("Parameter Problem"); 00233 errorMsg->setType(ICMPv6_PARAMETER_PROBLEM); 00234 errorMsg->setCode(code); 00235 //TODO: What Pointer? section 3.4 00236 return errorMsg; 00237 }
ICMPv6Message * ICMPv6::createTimeExceededMsg | ( | int | code | ) | [protected] |
00223 { 00224 ICMPv6TimeExceededMsg *errorMsg = new ICMPv6TimeExceededMsg("Time Exceeded"); 00225 errorMsg->setType(ICMPv6_TIME_EXCEEDED); 00226 errorMsg->setCode(code); 00227 return errorMsg; 00228 }
void ICMPv6::errorOut | ( | ICMPv6Message * | ) | [protected, virtual] |
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.
00032 { 00033 ASSERT(!msg->isSelfMessage()); // no timers in ICMPv6 00034 00035 // process arriving ICMP message 00036 if (msg->arrivalGate()->isName("fromIPv6")) 00037 { 00038 EV << "Processing ICMPv6 message.\n"; 00039 processICMPv6Message(check_and_cast<ICMPv6Message *>(msg)); 00040 return; 00041 } 00042 00043 // request from application 00044 if (msg->arrivalGate()->isName("pingIn")) 00045 { 00046 sendEchoRequest(msg); 00047 return; 00048 } 00049 }
void ICMPv6::processEchoReply | ( | ICMPv6EchoReplyMsg * | ) | [protected, virtual] |
Forward the ping reply to the "pingOut" of this module.
00112 { 00113 IPv6ControlInfo *ctrl = check_and_cast<IPv6ControlInfo*>(reply->removeControlInfo()); 00114 cMessage *payload = reply->decapsulate(); 00115 payload->setControlInfo(ctrl); 00116 delete reply; 00117 send(payload, "pingOut"); 00118 }
void ICMPv6::processEchoRequest | ( | ICMPv6EchoRequestMsg * | ) | [protected, virtual] |
Respond to the machine that tried to ping us.
00089 { 00090 //Create an ICMPv6 Reply Message 00091 ICMPv6EchoReplyMsg *reply = new ICMPv6EchoReplyMsg("Echo Reply"); 00092 reply->setName((std::string(request->name())+"-reply").c_str()); 00093 reply->setType(ICMPv6_ECHO_REPLY); 00094 reply->encapsulate(request->decapsulate()); 00095 00096 // TBD check what to do if dest was multicast etc? 00097 IPv6ControlInfo *ctrl 00098 = check_and_cast<IPv6ControlInfo *>(request->controlInfo()); 00099 IPv6ControlInfo *replyCtrl = new IPv6ControlInfo(); 00100 replyCtrl->setProtocol(IP_PROT_IPv6_ICMP); 00101 //set Msg's source addr as the dest addr of request msg. 00102 replyCtrl->setSrcAddr(ctrl->destAddr()); 00103 //set Msg's dest addr as the source addr of request msg. 00104 replyCtrl->setDestAddr(ctrl->srcAddr()); 00105 reply->setControlInfo(replyCtrl); 00106 00107 delete request; 00108 sendToIP(reply); 00109 }
void ICMPv6::processICMPv6Message | ( | ICMPv6Message * | ) | [protected, virtual] |
00052 { 00053 ASSERT(dynamic_cast<ICMPv6Message *>(icmpv6msg)); 00054 if (dynamic_cast<ICMPv6DestUnreachableMsg *>(icmpv6msg)) 00055 { 00056 EV << "ICMPv6 Destination Unreachable Message Received." << endl; 00057 errorOut(icmpv6msg); 00058 } 00059 else if (dynamic_cast<ICMPv6PacketTooBigMsg *>(icmpv6msg)) 00060 { 00061 EV << "ICMPv6 Packet Too Big Message Received." << endl; 00062 errorOut(icmpv6msg); 00063 } 00064 else if (dynamic_cast<ICMPv6TimeExceededMsg *>(icmpv6msg)) 00065 { 00066 EV << "ICMPv6 Time Exceeded Message Received." << endl; 00067 errorOut(icmpv6msg); 00068 } 00069 else if (dynamic_cast<ICMPv6ParamProblemMsg *>(icmpv6msg)) 00070 { 00071 EV << "ICMPv6 Parameter Problem Message Received." << endl; 00072 errorOut(icmpv6msg); 00073 } 00074 else if (dynamic_cast<ICMPv6EchoRequestMsg *>(icmpv6msg)) 00075 { 00076 EV << "ICMPv6 Echo Request Message Received." << endl; 00077 processEchoRequest((ICMPv6EchoRequestMsg *)icmpv6msg); 00078 } 00079 else if (dynamic_cast<ICMPv6EchoReplyMsg *>(icmpv6msg)) 00080 { 00081 EV << "ICMPv6 Echo Reply Message Received." << endl; 00082 processEchoReply((ICMPv6EchoReplyMsg *)icmpv6msg); 00083 } 00084 else 00085 error("Unknown message type received.\n"); 00086 }
void ICMPv6::sendEchoRequest | ( | cMessage * | ) | [protected, virtual] |
Ping a machine. The information needed to do this is in the cMessage parameter. TODO where in cMessage? document!!!
00121 { 00122 IPv6ControlInfo *ctrl = check_and_cast<IPv6ControlInfo*>(msg->removeControlInfo()); 00123 ctrl->setProtocol(IP_PROT_IPv6_ICMP); 00124 ICMPv6EchoRequestMsg *request = new ICMPv6EchoRequestMsg(msg->name()); 00125 request->setType(ICMPv6_ECHO_REQUEST); 00126 request->encapsulate(msg); 00127 request->setControlInfo(ctrl); 00128 sendToIP(request); 00129 }
void ICMPv6::sendErrorMessage | ( | cMessage * | transportPacket, | |
IPv6ControlInfo * | ctrl, | |||
ICMPv6Type | type, | |||
int | code | |||
) |
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.
00180 { 00181 Enter_Method("sendErrorMessage(transportPacket, ctrl, type=%d, code=%d)", type, code); 00182 00183 IPv6Datagram *datagram = ctrl->removeOrigDatagram(); 00184 datagram->encapsulate(transportPacket); 00185 sendErrorMessage(datagram, type, code); 00186 }
void ICMPv6::sendErrorMessage | ( | IPv6Datagram * | datagram, | |
ICMPv6Type | type, | |||
int | code | |||
) |
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:
00132 { 00133 Enter_Method("sendErrorMessage(datagram, type=%d, code=%d)", type, code); 00134 00135 // get ownership 00136 take(origDatagram); 00137 00138 if (!validateDatagramPromptingError(origDatagram)) 00139 return; 00140 00141 ICMPv6Message *errorMsg; 00142 00143 if (type == ICMPv6_DESTINATION_UNREACHABLE) errorMsg = createDestUnreachableMsg(code); 00144 //TODO: implement MTU support. 00145 else if (type == ICMPv6_PACKET_TOO_BIG) errorMsg = createPacketTooBigMsg(0); 00146 else if (type == ICMPv6_TIME_EXCEEDED) errorMsg = createTimeExceededMsg(code); 00147 else if (type == ICMPv6_PARAMETER_PROBLEM) errorMsg = createParamProblemMsg(code); 00148 else error("Unknown ICMPv6 error type\n"); 00149 00150 errorMsg->encapsulate(origDatagram); 00151 00152 // debugging information 00153 EV << "sending ICMP error: (" << errorMsg->className() << ")" << errorMsg->name() 00154 << " type=" << type << " code=" << code << endl; 00155 00156 // ICMP message length: the internet header plus the first 8 bytes of 00157 // the original datagram's data is returned to the sender 00158 //errorMessage->setByteLength(4 + origDatagram->headerLength() + 8); FIXME What is this for? 00159 00160 // if srcAddr is not filled in, we're still in the src node, so we just 00161 // process the ICMP message locally, right away 00162 if (origDatagram->srcAddress().isUnspecified()) 00163 { 00164 // pretend it came from the IP layer 00165 IPv6ControlInfo *ctrlInfo = new IPv6ControlInfo(); 00166 ctrlInfo->setSrcAddr(IPv6Address::LOOPBACK_ADDRESS); // FIXME maybe use configured loopback address 00167 ctrlInfo->setProtocol(IP_PROT_ICMP); 00168 errorMsg->setControlInfo(ctrlInfo); 00169 00170 // then process it locally 00171 processICMPv6Message(errorMsg); 00172 } 00173 else 00174 { 00175 sendToIP(errorMsg, origDatagram->srcAddress()); 00176 } 00177 }
void ICMPv6::sendToIP | ( | ICMPv6Message * | msg | ) | [protected] |
void ICMPv6::sendToIP | ( | ICMPv6Message * | msg, | |
const IPv6Address & | dest | |||
) | [protected] |
00189 { 00190 00191 IPv6ControlInfo *ctrlInfo = new IPv6ControlInfo(); 00192 ctrlInfo->setDestAddr(dest); 00193 ctrlInfo->setProtocol(IP_PROT_IPv6_ICMP); 00194 msg->setControlInfo(ctrlInfo); 00195 00196 send(msg,"toIPv6"); 00197 }
bool ICMPv6::validateDatagramPromptingError | ( | IPv6Datagram * | datagram | ) | [protected] |
Validate the received IPv6 datagram before responding with error message.
00240 { 00241 // don't send ICMP error messages for multicast messages 00242 if (origDatagram->destAddress().isMulticast()) 00243 { 00244 EV << "won't send ICMP error messages for multicast message " << origDatagram << endl; 00245 delete origDatagram; 00246 return false; 00247 } 00248 00249 // do not reply with error message to error message 00250 if (origDatagram->transportProtocol() == IP_PROT_IPv6_ICMP) 00251 { 00252 ICMPv6Message *recICMPMsg = check_and_cast<ICMPv6Message *>(origDatagram->encapsulatedMsg()); 00253 if (recICMPMsg->type()<128) 00254 { 00255 EV << "ICMP error received -- do not reply to it" << endl; 00256 delete origDatagram; 00257 return false; 00258 } 00259 } 00260 return true; 00261 }