Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <omnetpp.h>
00020 #include "ICMPv6.h"
00021
00022
00023 Define_Module(ICMPv6);
00024
00025
00026 void ICMPv6::initialize()
00027 {
00028 }
00029
00030 void ICMPv6::handleMessage(cMessage *msg)
00031 {
00032 ASSERT(!msg->isSelfMessage());
00033
00034
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
00043 if (msg->getArrivalGate()->isName("pingIn"))
00044 {
00045 sendEchoRequest(PK(msg));
00046 return;
00047 }
00048 }
00049
00050 void ICMPv6::processICMPv6Message(ICMPv6Message *icmpv6msg)
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 }
00086
00087 void ICMPv6::processEchoRequest(ICMPv6EchoRequestMsg *request)
00088 {
00089
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
00096 IPv6ControlInfo *ctrl
00097 = check_and_cast<IPv6ControlInfo *>(request->getControlInfo());
00098 IPv6ControlInfo *replyCtrl = new IPv6ControlInfo();
00099 replyCtrl->setProtocol(IP_PROT_IPv6_ICMP);
00100
00101 replyCtrl->setSrcAddr(ctrl->getDestAddr());
00102
00103 replyCtrl->setDestAddr(ctrl->getSrcAddr());
00104 reply->setControlInfo(replyCtrl);
00105
00106 delete request;
00107 sendToIP(reply);
00108 }
00109
00110 void ICMPv6::processEchoReply(ICMPv6EchoReplyMsg *reply)
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 }
00118
00119 void ICMPv6::sendEchoRequest(cPacket *msg)
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 }
00129
00130 void ICMPv6::sendErrorMessage(IPv6Datagram *origDatagram, ICMPv6Type type, int code)
00131 {
00132 Enter_Method("sendErrorMessage(datagram, type=%d, code=%d)", type, code);
00133
00134
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
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
00152 EV << "sending ICMP error: (" << errorMsg->getClassName() << ")" << errorMsg->getName()
00153 << " type=" << type << " code=" << code << endl;
00154
00155
00156
00157
00158
00159
00160
00161 if (origDatagram->getSrcAddress().isUnspecified())
00162 {
00163
00164 IPv6ControlInfo *ctrlInfo = new IPv6ControlInfo();
00165 ctrlInfo->setSrcAddr(IPv6Address::LOOPBACK_ADDRESS);
00166 ctrlInfo->setProtocol(IP_PROT_ICMP);
00167 errorMsg->setControlInfo(ctrlInfo);
00168
00169
00170 processICMPv6Message(errorMsg);
00171 }
00172 else
00173 {
00174 sendToIP(errorMsg, origDatagram->getSrcAddress());
00175 }
00176 }
00177
00178 void ICMPv6::sendErrorMessage(cPacket *transportPacket, IPv6ControlInfo *ctrl, ICMPv6Type type, int code)
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 }
00186
00187 void ICMPv6::sendToIP(ICMPv6Message *msg, const IPv6Address& dest)
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 }
00197
00198 void ICMPv6::sendToIP(ICMPv6Message *msg)
00199 {
00200
00201 send(msg,"ipv6Out");
00202 }
00203
00204 ICMPv6Message *ICMPv6::createDestUnreachableMsg(int code)
00205 {
00206 ICMPv6DestUnreachableMsg *errorMsg = new ICMPv6DestUnreachableMsg("Dest Unreachable");
00207 errorMsg->setType(ICMPv6_DESTINATION_UNREACHABLE);
00208 errorMsg->setCode(code);
00209 return errorMsg;
00210 }
00211
00212 ICMPv6Message *ICMPv6::createPacketTooBigMsg(int mtu)
00213 {
00214 ICMPv6PacketTooBigMsg *errorMsg = new ICMPv6PacketTooBigMsg("Packet Too Big");
00215 errorMsg->setType(ICMPv6_PACKET_TOO_BIG);
00216 errorMsg->setCode(0);
00217 errorMsg->setMTU(mtu);
00218 return errorMsg;
00219 }
00220
00221 ICMPv6Message *ICMPv6::createTimeExceededMsg(int code)
00222 {
00223 ICMPv6TimeExceededMsg *errorMsg = new ICMPv6TimeExceededMsg("Time Exceeded");
00224 errorMsg->setType(ICMPv6_TIME_EXCEEDED);
00225 errorMsg->setCode(code);
00226 return errorMsg;
00227 }
00228
00229 ICMPv6Message *ICMPv6::createParamProblemMsg(int code)
00230 {
00231 ICMPv6ParamProblemMsg *errorMsg = new ICMPv6ParamProblemMsg("Parameter Problem");
00232 errorMsg->setType(ICMPv6_PARAMETER_PROBLEM);
00233 errorMsg->setCode(code);
00234
00235 return errorMsg;
00236 }
00237
00238 bool ICMPv6::validateDatagramPromptingError(IPv6Datagram *origDatagram)
00239 {
00240
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
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 }
00261
00262 void ICMPv6::errorOut(ICMPv6Message *icmpv6msg)
00263 {
00264 send(icmpv6msg, "errorOut");
00265 }