#include <ICMPv6.h>
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 *) |
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:
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] |
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::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] |