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
00020
00021 #include <omnetpp.h>
00022 #include <string.h>
00023
00024 #include "IPDatagram.h"
00025 #include "IPControlInfo.h"
00026 #include "ICMP.h"
00027
00028 Define_Module(ICMP);
00029
00030
00031 void ICMP::handleMessage(cMessage *msg)
00032 {
00033 cGate *arrivalGate = msg->getArrivalGate();
00034
00035
00036 if (!strcmp(arrivalGate->getName(), "localIn"))
00037 {
00038 processICMPMessage(check_and_cast<ICMPMessage *>(msg));
00039 return;
00040 }
00041
00042
00043 if (!strcmp(arrivalGate->getName(), "pingIn"))
00044 {
00045 sendEchoRequest(PK(msg));
00046 return;
00047 }
00048 }
00049
00050
00051 void ICMP::sendErrorMessage(IPDatagram *origDatagram, ICMPType type, ICMPCode code)
00052 {
00053 Enter_Method("sendErrorMessage(datagram, type=%d, code=%d)", type, code);
00054
00055
00056 take(origDatagram);
00057
00058
00059 if (origDatagram->getDestAddress().isMulticast())
00060 {
00061 EV << "won't send ICMP error messages for multicast message " << origDatagram << endl;
00062 delete origDatagram;
00063 return;
00064 }
00065
00066
00067 if (origDatagram->getTransportProtocol() == IP_PROT_ICMP)
00068 {
00069 ICMPMessage *recICMPMsg = check_and_cast<ICMPMessage *>(origDatagram->getEncapsulatedMsg());
00070 if (recICMPMsg->getType()<128)
00071 {
00072 EV << "ICMP error received -- do not reply to it" << endl;
00073 delete origDatagram;
00074 return;
00075 }
00076 }
00077
00078
00079 char msgname[32];
00080 static long ctr;
00081 sprintf(msgname, "ICMP-error-#%ld-type%d-code%d", ++ctr, type, code);
00082
00083
00084 EV << "sending ICMP error " << msgname << endl;
00085
00086
00087 ICMPMessage *errorMessage = new ICMPMessage(msgname);
00088 errorMessage->setType(type);
00089 errorMessage->setCode(code);
00090 errorMessage->encapsulate(origDatagram);
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 int dataLength = origDatagram->getByteLength() - origDatagram->getHeaderLength();
00101 int truncatedDataLength = dataLength <= 8 ? dataLength : 8;
00102 errorMessage->setByteLength(8 + origDatagram->getHeaderLength() + truncatedDataLength);
00103
00104
00105
00106 if (origDatagram->getSrcAddress().isUnspecified())
00107 {
00108
00109 IPControlInfo *controlInfo = new IPControlInfo();
00110 controlInfo->setSrcAddr(IPAddress::LOOPBACK_ADDRESS);
00111 controlInfo->setProtocol(IP_PROT_ICMP);
00112 errorMessage->setControlInfo(controlInfo);
00113
00114
00115 processICMPMessage(errorMessage);
00116 }
00117 else
00118 {
00119 sendToIP(errorMessage, origDatagram->getSrcAddress());
00120 }
00121 }
00122
00123 void ICMP::sendErrorMessage(cPacket *transportPacket, IPControlInfo *ctrl, ICMPType type, ICMPCode code)
00124 {
00125 Enter_Method("sendErrorMessage(transportPacket, ctrl, type=%d, code=%d)", type, code);
00126
00127 IPDatagram *datagram = ctrl->removeOrigDatagram();
00128 take(transportPacket);
00129 take(datagram);
00130 datagram->encapsulate(transportPacket);
00131 sendErrorMessage(datagram, type, code);
00132 }
00133
00134 void ICMP::processICMPMessage(ICMPMessage *icmpmsg)
00135 {
00136 switch (icmpmsg->getType())
00137 {
00138 case ICMP_DESTINATION_UNREACHABLE:
00139 errorOut(icmpmsg);
00140 break;
00141 case ICMP_REDIRECT:
00142 errorOut(icmpmsg);
00143 break;
00144 case ICMP_TIME_EXCEEDED:
00145 errorOut(icmpmsg);
00146 break;
00147 case ICMP_PARAMETER_PROBLEM:
00148 errorOut(icmpmsg);
00149 break;
00150 case ICMP_ECHO_REQUEST:
00151 processEchoRequest(icmpmsg);
00152 break;
00153 case ICMP_ECHO_REPLY:
00154 processEchoReply(icmpmsg);
00155 break;
00156 case ICMP_TIMESTAMP_REQUEST:
00157 processEchoRequest(icmpmsg);
00158 break;
00159 case ICMP_TIMESTAMP_REPLY:
00160 processEchoReply(icmpmsg);
00161 break;
00162 default:
00163 opp_error("Unknown ICMP type %d", icmpmsg->getType());
00164 }
00165 }
00166
00167 void ICMP::errorOut(ICMPMessage *icmpmsg)
00168 {
00169 send(icmpmsg, "errorOut");
00170 }
00171
00172 void ICMP::processEchoRequest(ICMPMessage *request)
00173 {
00174
00175 ICMPMessage *reply = request;
00176 reply->setName((std::string(request->getName())+"-reply").c_str());
00177 reply->setType(ICMP_ECHO_REPLY);
00178
00179
00180
00181 IPControlInfo *ctrl = check_and_cast<IPControlInfo *>(reply->getControlInfo());
00182 IPAddress src = ctrl->getSrcAddr();
00183 IPAddress dest = ctrl->getDestAddr();
00184 ctrl->setSrcAddr(dest);
00185 ctrl->setDestAddr(src);
00186
00187 sendToIP(reply);
00188 }
00189
00190 void ICMP::processEchoReply(ICMPMessage *reply)
00191 {
00192 IPControlInfo *ctrl = check_and_cast<IPControlInfo*>(reply->removeControlInfo());
00193 cPacket *payload = reply->decapsulate();
00194 payload->setControlInfo(ctrl);
00195 delete reply;
00196 send(payload, "pingOut");
00197 }
00198
00199 void ICMP::sendEchoRequest(cPacket *msg)
00200 {
00201 IPControlInfo *ctrl = check_and_cast<IPControlInfo*>(msg->removeControlInfo());
00202 ctrl->setProtocol(IP_PROT_ICMP);
00203 ICMPMessage *request = new ICMPMessage(msg->getName());
00204 request->setType(ICMP_ECHO_REQUEST);
00205 request->encapsulate(msg);
00206 request->setControlInfo(ctrl);
00207 sendToIP(request);
00208 }
00209
00210 void ICMP::sendToIP(ICMPMessage *msg, const IPAddress& dest)
00211 {
00212 IPControlInfo *controlInfo = new IPControlInfo();
00213 controlInfo->setDestAddr(dest);
00214 controlInfo->setProtocol(IP_PROT_ICMP);
00215 msg->setControlInfo(controlInfo);
00216
00217 send(msg, "sendOut");
00218 }
00219
00220 void ICMP::sendToIP(ICMPMessage *msg)
00221 {
00222
00223 send(msg, "sendOut");
00224 }
00225