INET Framework for OMNeT++/OMNEST
inet::ICMP Class Reference

ICMP module. More...

#include <ICMP.h>

Inheritance diagram for inet::ICMP:

Public Member Functions

virtual void sendErrorMessage (IPv4Datagram *datagram, int inputInterfaceId, ICMPType type, ICMPCode code)
 This method can be called from other modules to send an ICMP error packet in response to a received bogus packet. More...
 
virtual void sendErrorMessage (cPacket *transportPacket, IPv4ControlInfo *ctrl, ICMPType type, ICMPCode 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). More...
 

Protected Types

typedef std::map< long, int > PingMap
 

Protected Member Functions

virtual void processICMPMessage (ICMPMessage *)
 
virtual void errorOut (ICMPMessage *)
 
virtual void processEchoRequest (ICMPMessage *)
 
virtual void processEchoReply (ICMPMessage *)
 
virtual void sendEchoRequest (PingPayload *)
 
virtual void sendToIP (ICMPMessage *, const IPv4Address &dest)
 
virtual void sendToIP (ICMPMessage *msg)
 
virtual bool possiblyLocalBroadcast (const IPv4Address &addr, int interfaceId)
 
virtual int numInitStages () const override
 
virtual void initialize (int stage) override
 
virtual void handleMessage (cMessage *msg) override
 

Protected Attributes

PingMap pingMap
 

Detailed Description

ICMP module.

Member Typedef Documentation

typedef std::map<long, int> inet::ICMP::PingMap
protected

Member Function Documentation

void inet::ICMP::errorOut ( ICMPMessage icmpmsg)
protectedvirtual

Referenced by processICMPMessage().

227 {
228  send(icmpmsg, "errorOut");
229 }
void inet::ICMP::handleMessage ( cMessage *  msg)
overrideprotectedvirtual
48 {
49  cGate *arrivalGate = msg->getArrivalGate();
50 
51  // process arriving ICMP message
52  if (!strcmp(arrivalGate->getName(), "localIn")) {
53  EV_INFO << "Received " << msg << " from network protocol.\n";
54  processICMPMessage(check_and_cast<ICMPMessage *>(msg));
55  return;
56  }
57 
58  // request from application
59  if (!strcmp(arrivalGate->getName(), "pingIn")) {
60  EV_INFO << "Received " << msg << " from upper layer.\n";
61  sendEchoRequest(check_and_cast<PingPayload *>(msg));
62  return;
63  }
64 }
virtual void sendEchoRequest(PingPayload *)
Definition: ICMP.cc:270
virtual void processICMPMessage(ICMPMessage *)
Definition: ICMP.cc:186
void inet::ICMP::initialize ( int  stage)
overrideprotectedvirtual
38 {
39  cSimpleModule::initialize(stage);
40 
41  if (stage == INITSTAGE_NETWORK_LAYER_2) {
42  IPSocket socket(gate("sendOut"));
43  socket.registerProtocol(IP_PROT_ICMP);
44  }
45 }
Definition: IPProtocolId_m.h:77
Initialization of network-layer protocols, stage 2.
Definition: InitStages.h:78
virtual int inet::ICMP::numInitStages ( ) const
inlineoverrideprotectedvirtual
77 { return NUM_INIT_STAGES; }
The number of initialization stages.
Definition: InitStages.h:116
bool inet::ICMP::possiblyLocalBroadcast ( const IPv4Address addr,
int  interfaceId 
)
protectedvirtual

Referenced by sendErrorMessage().

160 {
161  if ((addr.getInt() & 1) == 0)
162  return false;
163 
164  IIPv4RoutingTable *rt = getModuleFromPar<IIPv4RoutingTable>(par("routingTableModule"), this);
165  if (rt->isLocalBroadcastAddress(addr))
166  return true;
167 
168  // if the input interface is unconfigured, we won't recognize network-directed broadcasts because we don't what network we are on
169  IInterfaceTable *ift = getModuleFromPar<IInterfaceTable>(par("interfaceTableModule"), this);
170  if (interfaceId != -1) {
171  InterfaceEntry *ie = ift->getInterfaceById(interfaceId);
172  bool interfaceUnconfigured = (ie->ipv4Data() == nullptr) || ie->ipv4Data()->getIPAddress().isUnspecified();
173  return interfaceUnconfigured;
174  }
175  else {
176  // if all interfaces are configured, we are OK
177  bool allInterfacesConfigured = true;
178  for (int i = 0; i < (int)ift->getNumInterfaces(); i++)
179  if ((ift->getInterface(i)->ipv4Data() == nullptr) || ift->getInterface(i)->ipv4Data()->getIPAddress().isUnspecified())
180  allInterfacesConfigured = false;
181 
182  return !allInterfacesConfigured;
183  }
184 }
void inet::ICMP::processEchoReply ( ICMPMessage reply)
protectedvirtual

Referenced by processICMPMessage().

253 {
254  IPv4ControlInfo *ctrl = check_and_cast<IPv4ControlInfo *>(reply->removeControlInfo());
255  PingPayload *payload = check_and_cast<PingPayload *>(reply->decapsulate());
256  payload->setControlInfo(ctrl);
257  delete reply;
258  long originatorId = payload->getOriginatorId();
259  auto i = pingMap.find(originatorId);
260  if (i != pingMap.end()) {
261  EV_INFO << "Sending " << payload << " to upper layer.\n";
262  send(payload, "pingOut", i->second);
263  }
264  else {
265  EV_WARN << "Received ECHO REPLY has an unknown originator ID: " << originatorId << ", packet dropped." << endl;
266  delete payload;
267  }
268 }
PingMap pingMap
Definition: ICMP.h:44
void inet::ICMP::processEchoRequest ( ICMPMessage request)
protectedvirtual

Referenced by processICMPMessage().

232 {
233  // turn request into a reply
234  ICMPMessage *reply = request;
235  reply->setName((std::string(request->getName()) + "-reply").c_str());
236  reply->setType(ICMP_ECHO_REPLY);
237 
238  // swap src and dest
239  // TBD check what to do if dest was multicast etc?
240  IPv4ControlInfo *ctrl = check_and_cast<IPv4ControlInfo *>(reply->getControlInfo());
241  IPv4Address src = ctrl->getSrcAddr();
242  IPv4Address dest = ctrl->getDestAddr();
243  // A. Ariza Modification 5/1/2011 clean the interface id, this forces the use of routing table in the IPv4 layer
244  ctrl->setInterfaceId(-1);
245  ctrl->setSrcAddr(dest);
246  ctrl->setDestAddr(src);
247  ctrl->setTimeToLive(0); // if the TTL is set to 0 here, IP resets it to the default TTL
248 
249  sendToIP(reply);
250 }
virtual void sendToIP(ICMPMessage *, const IPv4Address &dest)
Definition: ICMP.cc:286
Definition: ICMPMessage_m.h:74
void inet::ICMP::processICMPMessage ( ICMPMessage icmpmsg)
protectedvirtual

Referenced by handleMessage(), and sendErrorMessage().

187 {
188  switch (icmpmsg->getType()) {
190  errorOut(icmpmsg);
191  break;
192 
193  case ICMP_REDIRECT:
194  errorOut(icmpmsg);
195  break;
196 
197  case ICMP_TIME_EXCEEDED:
198  errorOut(icmpmsg);
199  break;
200 
202  errorOut(icmpmsg);
203  break;
204 
205  case ICMP_ECHO_REQUEST:
206  processEchoRequest(icmpmsg);
207  break;
208 
209  case ICMP_ECHO_REPLY:
210  processEchoReply(icmpmsg);
211  break;
212 
214  processEchoRequest(icmpmsg);
215  break;
216 
218  processEchoReply(icmpmsg);
219  break;
220 
221  default:
222  throw cRuntimeError("Unknown ICMP type %d", icmpmsg->getType());
223  }
224 }
Definition: ICMPMessage_m.h:75
virtual void processEchoReply(ICMPMessage *)
Definition: ICMP.cc:252
Definition: ICMPMessage_m.h:69
Definition: ICMPMessage_m.h:66
Definition: ICMPMessage_m.h:74
virtual void errorOut(ICMPMessage *)
Definition: ICMP.cc:226
Definition: ICMPMessage_m.h:72
virtual void processEchoRequest(ICMPMessage *)
Definition: ICMP.cc:231
Definition: ICMPMessage_m.h:73
Definition: ICMPMessage_m.h:68
Definition: ICMPMessage_m.h:76
void inet::ICMP::sendEchoRequest ( PingPayload msg)
protectedvirtual

Referenced by handleMessage().

271 {
272  cGate *arrivalGate = msg->getArrivalGate();
273  int i = arrivalGate->getIndex();
274  pingMap[msg->getOriginatorId()] = i;
275 
276  IPv4ControlInfo *ctrl = check_and_cast<IPv4ControlInfo *>(msg->removeControlInfo());
277  ctrl->setProtocol(IP_PROT_ICMP);
278  ICMPMessage *request = new ICMPMessage(msg->getName());
279  request->setByteLength(4);
280  request->setType(ICMP_ECHO_REQUEST);
281  request->encapsulate(msg);
282  request->setControlInfo(ctrl);
283  sendToIP(request);
284 }
virtual void sendToIP(ICMPMessage *, const IPv4Address &dest)
Definition: ICMP.cc:286
Definition: ICMPMessage_m.h:69
Definition: IPProtocolId_m.h:77
PingMap pingMap
Definition: ICMP.h:44
void inet::ICMP::sendErrorMessage ( IPv4Datagram datagram,
int  inputInterfaceId,
ICMPType  type,
ICMPCode  code 
)
virtual

This method can be called from other modules to send an ICMP error packet in response to a received bogus packet.

It will not send ICMP error in response to broadcast or multicast packets – in that case it will simply delete the packet. Kludge: if inputInterfaceId cannot be determined, pass in -1.

Referenced by inet::IPv4FragBuf::purgeStaleFragments(), and sendErrorMessage().

67 {
68  Enter_Method("sendErrorMessage(datagram, type=%d, code=%d)", type, code);
69 
70  // get ownership
71  take(origDatagram);
72 
73  IPv4Address origSrcAddr = origDatagram->getSrcAddress();
74  IPv4Address origDestAddr = origDatagram->getDestAddress();
75 
76  // don't send ICMP error messages in response to broadcast or multicast messages
77  if (origDestAddr.isMulticast() || origDestAddr.isLimitedBroadcastAddress() || possiblyLocalBroadcast(origDestAddr, inputInterfaceId)) {
78  EV_DETAIL << "won't send ICMP error messages for broadcast/multicast message " << origDatagram << endl;
79  delete origDatagram;
80  return;
81  }
82 
83  // don't send ICMP error messages response to unspecified, broadcast or multicast addresses
84  if ((inputInterfaceId != -1 && origSrcAddr.isUnspecified())
85  || origSrcAddr.isMulticast()
86  || origSrcAddr.isLimitedBroadcastAddress()
87  || possiblyLocalBroadcast(origSrcAddr, inputInterfaceId)) {
88  EV_DETAIL << "won't send ICMP error messages to broadcast/multicast address, message " << origDatagram << endl;
89  delete origDatagram;
90  return;
91  }
92 
93  // do not reply with error message to error message
94  if (origDatagram->getTransportProtocol() == IP_PROT_ICMP) {
95  ICMPMessage *recICMPMsg = check_and_cast<ICMPMessage *>(origDatagram->getEncapsulatedPacket());
96  if (!isIcmpInfoType(recICMPMsg->getType())) {
97  EV_DETAIL << "ICMP error received -- do not reply to it" << endl;
98  delete origDatagram;
99  return;
100  }
101  }
102 
103  // assemble a message name
104  char msgname[80];
105  static long ctr;
106  sprintf(msgname, "ICMP-error-#%ld-type%d-code%d", ++ctr, type, code);
107 
108  // debugging information
109  EV_DETAIL << "sending ICMP error " << msgname << endl;
110 
111  // create and send ICMP packet
112  ICMPMessage *errorMessage = new ICMPMessage(msgname);
113  errorMessage->setType(type);
114  errorMessage->setCode(code);
115  errorMessage->encapsulate(origDatagram);
116 
117  // ICMP message length: the internet header plus the first 8 bytes of
118  // the original datagram's data is returned to the sender.
119  //
120  // NOTE: since we just overwrite the errorMessage length without actually
121  // truncating origDatagram, one can get "packet length became negative"
122  // error when decapsulating the origDatagram on the receiver side.
123  // A workaround is to avoid decapsulation, or to manually set the
124  // errorMessage length to be larger than the encapsulated message.
125  int dataLength = origDatagram->getByteLength() - origDatagram->getHeaderLength();
126  int truncatedDataLength = dataLength <= 8 ? dataLength : 8;
127  errorMessage->setByteLength(8 + origDatagram->getHeaderLength() + truncatedDataLength);
128 
129  // if srcAddr is not filled in, we're still in the src node, so we just
130  // process the ICMP message locally, right away
131  if (origSrcAddr.isUnspecified()) {
132  // pretend it came from the IPv4 layer
133  IPv4ControlInfo *controlInfo = new IPv4ControlInfo();
134  controlInfo->setSrcAddr(IPv4Address::LOOPBACK_ADDRESS); // FIXME maybe use configured loopback address
135  controlInfo->setProtocol(IP_PROT_ICMP);
136  errorMessage->setControlInfo(controlInfo);
137 
138  // then process it locally
139  processICMPMessage(errorMessage);
140  }
141  else {
142  sendToIP(errorMessage, origDatagram->getSrcAddress());
143  }
144 }
virtual void sendToIP(ICMPMessage *, const IPv4Address &dest)
Definition: ICMP.cc:286
bool isIcmpInfoType(int type)
Definition: ICMPMessage_m.h:189
Definition: IPProtocolId_m.h:77
static const IPv4Address LOOPBACK_ADDRESS
127.0.0.1
Definition: IPv4Address.h:103
virtual bool possiblyLocalBroadcast(const IPv4Address &addr, int interfaceId)
Definition: ICMP.cc:159
virtual void processICMPMessage(ICMPMessage *)
Definition: ICMP.cc:186
void inet::ICMP::sendErrorMessage ( cPacket *  transportPacket,
IPv4ControlInfo ctrl,
ICMPType  type,
ICMPCode  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).

It will not send ICMP error in response to broadcast or multicast packets – in that case it will simply delete the packet. The ICMP error packet needs to include (part of) the original IPv4 datagram, so this function will wrap back the transport packet into the IPv4 datagram based on its IPv4ControlInfo.

147 {
148  Enter_Method("sendErrorMessage(transportPacket, ctrl, type=%d, code=%d)", type, code);
149 
150  IPv4Datagram *datagram = ctrl->removeOrigDatagram();
151  int inputInterfaceId = ctrl->getInterfaceId();
152  delete ctrl;
153  take(transportPacket);
154  take(datagram);
155  datagram->encapsulate(transportPacket);
156  sendErrorMessage(datagram, inputInterfaceId, type, code);
157 }
virtual void sendErrorMessage(IPv4Datagram *datagram, int inputInterfaceId, ICMPType type, ICMPCode code)
This method can be called from other modules to send an ICMP error packet in response to a received b...
Definition: ICMP.cc:66
void inet::ICMP::sendToIP ( ICMPMessage msg,
const IPv4Address dest 
)
protectedvirtual

Referenced by processEchoRequest(), sendEchoRequest(), and sendErrorMessage().

287 {
288  IPv4ControlInfo *controlInfo = new IPv4ControlInfo();
289  controlInfo->setDestAddr(dest);
290  controlInfo->setProtocol(IP_PROT_ICMP);
291  msg->setControlInfo(controlInfo);
292  sendToIP(msg);
293 }
virtual void sendToIP(ICMPMessage *, const IPv4Address &dest)
Definition: ICMP.cc:286
Definition: IPProtocolId_m.h:77
void inet::ICMP::sendToIP ( ICMPMessage msg)
protectedvirtual
296 {
297  // assumes IPv4ControlInfo is already attached
298  EV_INFO << "Sending " << msg << " to lower layer.\n";
299  send(msg, "sendOut");
300 }

Member Data Documentation

PingMap inet::ICMP::pingMap
protected

The documentation for this class was generated from the following files: