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

Implements a DHCP client. More...

#include <DHCPClient.h>

Inheritance diagram for inet::DHCPClient:
inet::ILifecycle

Public Member Functions

 DHCPClient ()
 
virtual ~DHCPClient ()
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Types

enum  TimerType {
  WAIT_OFFER, WAIT_ACK, T1, T2,
  LEASE_TIMEOUT, START_DHCP
}
 
enum  ClientState {
  IDLE, INIT, INIT_REBOOT, REBOOTING,
  SELECTING, REQUESTING, BOUND, RENEWING,
  REBINDING
}
 

Protected Member Functions

virtual int numInitStages () const override
 
virtual void initialize (int stage) override
 
virtual void finish () override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void scheduleTimerTO (TimerType type)
 
virtual void scheduleTimerT1 ()
 
virtual void scheduleTimerT2 ()
 
const char * getAndCheckMessageTypeName (DHCPMessageType type)
 
virtual void refreshDisplay () const override
 
virtual void openSocket ()
 
virtual void handleDHCPMessage (DHCPMessage *msg)
 
virtual void handleTimer (cMessage *msg)
 
virtual void receiveSignal (cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override
 
virtual void sendToUDP (cPacket *msg, int srcPort, const L3Address &destAddr, int destPort)
 
virtual void sendDiscover ()
 
virtual void sendRequest ()
 
virtual void sendDecline (IPv4Address declinedIp)
 
virtual void recordLease (DHCPMessage *dhcpACK)
 
virtual void recordOffer (DHCPMessage *dhcpOffer)
 
virtual void bindLease ()
 
virtual void unbindLease ()
 
virtual void initClient ()
 
virtual void initRebootedClient ()
 
virtual void handleDHCPACK (DHCPMessage *msg)
 
virtual InterfaceEntrychooseInterface ()
 
virtual void startApp ()
 
virtual void stopApp ()
 
virtual bool handleOperationStage (LifecycleOperation *operation, int stage, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 

Static Protected Member Functions

static const char * getStateName (ClientState state)
 

Protected Attributes

int serverPort = -1
 
int clientPort = -1
 
UDPSocket socket
 
simtime_t startTime
 
MACAddress macAddress
 
cModule * host = nullptr
 
InterfaceEntryie = nullptr
 
IIPv4RoutingTableirt = nullptr
 
cMessage * timerT1 = nullptr
 
cMessage * timerT2 = nullptr
 
cMessage * timerTo = nullptr
 
cMessage * leaseTimer = nullptr
 
cMessage * startTimer = nullptr
 
bool isOperational = false
 
ClientState clientState = INIT
 
unsigned int xid = 0
 
DHCPLeaselease = nullptr
 
IPv4Routeroute = nullptr
 
int numSent = 0
 
int numReceived = 0
 
int responseTimeout = 0
 

Detailed Description

Implements a DHCP client.

See NED file for more details.

Member Enumeration Documentation

Enumerator
IDLE 
INIT 
INIT_REBOOT 
REBOOTING 
SELECTING 
REQUESTING 
BOUND 
RENEWING 
REBINDING 
46  {
48  };
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Enumerator
WAIT_OFFER 
WAIT_ACK 
T1 
T2 
LEASE_TIMEOUT 
START_DHCP 
41  {
43  };
Definition: DHCPClient.h:42
Definition: DHCPClient.h:42
Definition: DHCPClient.h:42
Definition: DHCPClient.h:42
Definition: DHCPClient.h:42
Definition: DHCPClient.h:42

Constructor & Destructor Documentation

inet::DHCPClient::DHCPClient ( )
inline
184 {}
inet::DHCPClient::~DHCPClient ( )
virtual
32 {
33  cancelAndDelete(timerT1);
34  cancelAndDelete(timerTo);
35  cancelAndDelete(timerT2);
36  cancelAndDelete(leaseTimer);
37  cancelAndDelete(startTimer);
38  delete lease;
39 }
cMessage * timerTo
Definition: DHCPClient.h:63
cMessage * timerT2
Definition: DHCPClient.h:62
DHCPLease * lease
Definition: DHCPClient.h:69
cMessage * leaseTimer
Definition: DHCPClient.h:64
cMessage * startTimer
Definition: DHCPClient.h:65
cMessage * timerT1
Definition: DHCPClient.h:61

Member Function Documentation

void inet::DHCPClient::bindLease ( )
protectedvirtual

Referenced by handleDHCPACK().

316 {
319 
320  std::string banner = "Got IP " + lease->ip.str();
321  host->bubble(banner.c_str());
322 
323  /*
324  The client SHOULD perform a final check on the parameters (ping, ARP).
325  If the client detects that the address is already in use:
326  EV_INFO << "The offered IP " << lease->ip << " is not available." << endl;
327  sendDecline(lease->ip);
328  initClient();
329  */
330 
331  EV_INFO << "The requested IP " << lease->ip << "/" << lease->subnetMask << " is available. Assigning it to "
332  << host->getFullName() << "." << endl;
333 
334  IPv4Route *iroute = nullptr;
335  for (int i = 0; i < irt->getNumRoutes(); i++) {
336  IPv4Route *e = irt->getRoute(i);
337  if (routeMatches(e, IPv4Address(), IPv4Address(), lease->gateway, 0, ie->getName())) {
338  iroute = e;
339  break;
340  }
341  }
342  if (iroute == nullptr) {
343  // create gateway route
344  route = new IPv4Route();
345  route->setDestination(IPv4Address());
346  route->setNetmask(IPv4Address());
350  irt->addRoute(route);
351  }
352 
353  // update the routing table
354  cancelEvent(leaseTimer);
355  scheduleAt(simTime() + lease->leaseTime, leaseTimer);
356 }
IPv4InterfaceData * ipv4Data() const
Definition: InterfaceEntry.h:221
std::string str(bool printUnspec=true) const
Returns the string representation of the address (e.g.
Definition: IPv4Address.cc:109
virtual IPv4Route * getRoute(int k) const override=0
Returns the kth route.
virtual int getNumRoutes() const =0
Returns the total number of unicast routes.
simtime_t leaseTime
Definition: DHCPLease.h:43
virtual void setSourceType(SourceType _source) override
Definition: IPv4Route.h:100
IPv4Address gateway
Definition: DHCPLease.h:37
virtual void setInterface(InterfaceEntry *_interfacePtr) override
Definition: IPv4Route.h:99
virtual void setGateway(IPv4Address _gateway)
Definition: IPv4Route.h:98
IPv4Route * route
Definition: DHCPClient.h:70
virtual void setIPAddress(IPv4Address a)
Definition: IPv4InterfaceData.h:195
DHCPLease * lease
Definition: DHCPClient.h:69
cMessage * leaseTimer
Definition: DHCPClient.h:64
virtual void addRoute(IPv4Route *entry)=0
Adds a route to the routing table.
const value< double, units::C > e(1.602176487e-19)
virtual void setNetmask(IPv4Address m)
Definition: IPv4InterfaceData.h:196
InterfaceEntry * ie
Definition: DHCPClient.h:57
IPv4Address ip
Definition: DHCPLease.h:35
virtual void setDestination(IPv4Address _dest)
Definition: IPv4Route.h:96
IPv4Address subnetMask
Definition: DHCPLease.h:38
manually added static route
Definition: IRoute.h:40
IIPv4RoutingTable * irt
Definition: DHCPClient.h:58
cModule * host
Definition: DHCPClient.h:56
virtual void setNetmask(IPv4Address _netmask)
Definition: IPv4Route.h:97
InterfaceEntry * inet::DHCPClient::chooseInterface ( )
protectedvirtual

Referenced by initialize(), and startApp().

92 {
93  IInterfaceTable *ift = getModuleFromPar<IInterfaceTable>(par("interfaceTableModule"), this);
94  const char *interfaceName = par("interface");
95  InterfaceEntry *ie = nullptr;
96 
97  if (strlen(interfaceName) > 0) {
98  ie = ift->getInterfaceByName(interfaceName);
99  if (ie == nullptr)
100  throw cRuntimeError("Interface \"%s\" does not exist", interfaceName);
101  }
102  else {
103  // there should be exactly one non-loopback interface that we want to configure
104  for (int i = 0; i < ift->getNumInterfaces(); i++) {
105  InterfaceEntry *current = ift->getInterface(i);
106  if (!current->isLoopback()) {
107  if (ie)
108  throw cRuntimeError("Multiple non-loopback interfaces found, please select explicitly which one you want to configure via DHCP");
109  ie = current;
110  }
111  }
112  if (!ie)
113  throw cRuntimeError("No non-loopback interface found to be configured via DHCP");
114  }
115 
116  if (!ie->ipv4Data()->getIPAddress().isUnspecified())
117  throw cRuntimeError("Refusing to start DHCP on interface \"%s\" that already has an IP address", ie->getName());
118  return ie;
119 }
InterfaceEntry * ie
Definition: DHCPClient.h:57
void inet::DHCPClient::finish ( )
overrideprotectedvirtual
122 {
123  cancelEvent(timerT1);
124  cancelEvent(timerTo);
125  cancelEvent(timerT2);
126  cancelEvent(leaseTimer);
127  cancelEvent(startTimer);
128 }
cMessage * timerTo
Definition: DHCPClient.h:63
cMessage * timerT2
Definition: DHCPClient.h:62
cMessage * leaseTimer
Definition: DHCPClient.h:64
cMessage * startTimer
Definition: DHCPClient.h:65
cMessage * timerT1
Definition: DHCPClient.h:61
const char * inet::DHCPClient::getAndCheckMessageTypeName ( DHCPMessageType  type)
protected

Referenced by handleDHCPMessage().

170 {
171  switch (type) {
172 #define CASE(X) case X: \
173  return #X;
175  CASE(DHCPOFFER);
176  CASE(DHCPREQUEST);
177  CASE(DHCPDECLINE);
178  CASE(DHCPACK);
179  CASE(DHCPNAK);
180  CASE(DHCPRELEASE);
181  CASE(DHCPINFORM);
182 
183  default:
184  throw cRuntimeError("Unknown or invalid DHCP message type %d", type);
185 #undef CASE
186  }
187 }
Definition: DHCPMessage_m.h:72
Definition: DHCPMessage_m.h:76
Definition: DHCPMessage_m.h:79
Definition: DHCPMessage_m.h:77
Definition: DHCPMessage_m.h:75
Definition: DHCPMessage_m.h:74
Definition: DHCPMessage_m.h:78
#define CASE(X)
Definition: DHCPMessage_m.h:73
const char * inet::DHCPClient::getStateName ( ClientState  state)
staticprotected

Referenced by refreshDisplay().

150 {
151  switch (state) {
152 #define CASE(X) case X: \
153  return #X;
154  CASE(INIT);
155  CASE(INIT_REBOOT);
156  CASE(REBOOTING);
157  CASE(SELECTING);
158  CASE(REQUESTING);
159  CASE(BOUND);
160  CASE(RENEWING);
161  CASE(REBINDING);
162 
163  default:
164  return "???";
165 #undef CASE
166  }
167 }
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
#define CASE(X)
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
void inet::DHCPClient::handleDHCPACK ( DHCPMessage msg)
protectedvirtual

Referenced by handleDHCPMessage().

631 {
632  recordLease(msg);
633  cancelEvent(timerTo);
634  scheduleTimerT1();
635  scheduleTimerT2();
636  bindLease();
637 }
cMessage * timerTo
Definition: DHCPClient.h:63
virtual void scheduleTimerT1()
Definition: DHCPClient.cc:647
virtual void scheduleTimerT2()
Definition: DHCPClient.cc:654
virtual void recordLease(DHCPMessage *dhcpACK)
Definition: DHCPClient.cc:290
virtual void bindLease()
Definition: DHCPClient.cc:315
void inet::DHCPClient::handleDHCPMessage ( DHCPMessage msg)
protectedvirtual

Referenced by handleMessage().

394 {
395  ASSERT(isOperational && ie != nullptr);
396 
397  if (msg->getOp() != BOOTREPLY) {
398  EV_WARN << "Client received a non-BOOTREPLY message, dropping." << endl;
399  return;
400  }
401 
402  if (msg->getXid() != xid) {
403  EV_WARN << "Message transaction ID is not valid, dropping." << endl;
404  return;
405  }
406 
407  DHCPMessageType messageType = (DHCPMessageType)msg->getOptions().getMessageType();
408  switch (clientState) {
409  case INIT:
410  EV_WARN << getAndCheckMessageTypeName(messageType) << " message arrived in INIT state. In this state, client does not wait for any message at all, dropping." << endl;
411  break;
412 
413  case SELECTING:
414  if (messageType == DHCPOFFER) {
415  EV_INFO << "DHCPOFFER message arrived in SELECTING state with IP address: " << msg->getYiaddr() << "." << endl;
418  recordOffer(msg);
419  sendRequest(); // we accept the first offer
420  }
421  else
422  EV_WARN << "Client is in SELECTING and the arriving packet is not a DHCPOFFER, dropping." << endl;
423  break;
424 
425  case REQUESTING:
426  if (messageType == DHCPOFFER) {
427  EV_WARN << "We don't accept DHCPOFFERs in REQUESTING state, dropping." << endl; // remains in REQUESTING
428  }
429  else if (messageType == DHCPACK) {
430  EV_INFO << "DHCPACK message arrived in REQUESTING state. The requested IP address is available in the server's pool of addresses." << endl;
431  handleDHCPACK(msg);
432  clientState = BOUND;
433  }
434  else if (messageType == DHCPNAK) {
435  EV_INFO << "DHCPNAK message arrived in REQUESTING state. Restarting the configuration process." << endl;
436  initClient();
437  }
438  else {
439  EV_WARN << getAndCheckMessageTypeName(messageType) << " message arrived in REQUESTING state. In this state, client does not expect messages of this type, dropping." << endl;
440  }
441  break;
442 
443  case BOUND:
444  EV_DETAIL << "We are in BOUND, discard all DHCP messages." << endl; // remain in BOUND
445  break;
446 
447  case RENEWING:
448  if (messageType == DHCPACK) {
449  handleDHCPACK(msg);
450  EV_INFO << "DHCPACK message arrived in RENEWING state. The renewing process was successful." << endl;
451  clientState = BOUND;
452  }
453  else if (messageType == DHCPNAK) {
454  EV_INFO << "DHPCNAK message arrived in RENEWING state. The renewing process was unsuccessful. Restarting the DHCP configuration process." << endl;
455  unbindLease();
456  initClient();
457  }
458  else {
459  EV_WARN << getAndCheckMessageTypeName(messageType) << " message arrived in RENEWING state. In this state, client does not expect messages of this type, dropping." << endl;
460  }
461  break;
462 
463  case REBINDING:
464  if (messageType == DHCPNAK) {
465  EV_INFO << "DHPCNAK message arrived in REBINDING state. The rebinding process was unsuccessful. Restarting the DHCP configuration process." << endl;
466  unbindLease();
467  initClient();
468  }
469  else if (messageType == DHCPACK) {
470  handleDHCPACK(msg);
471  EV_INFO << "DHCPACK message arrived in REBINDING state. The rebinding process was successful." << endl;
472  clientState = BOUND;
473  }
474  else {
475  EV_WARN << getAndCheckMessageTypeName(messageType) << " message arrived in REBINDING state. In this state, client does not expect messages of this type, dropping." << endl;
476  }
477  break;
478 
479  case REBOOTING:
480  if (messageType == DHCPACK) {
481  handleDHCPACK(msg);
482  EV_INFO << "DHCPACK message arrived in REBOOTING state. Initialization with known IP address was successful." << endl;
483  clientState = BOUND;
484  }
485  else if (messageType == DHCPNAK) {
486  EV_INFO << "DHCPNAK message arrived in REBOOTING. Initialization with known IP address was unsuccessful." << endl;
487  unbindLease();
488  initClient();
489  }
490  else {
491  EV_WARN << getAndCheckMessageTypeName(messageType) << " message arrived in REBOOTING state. In this state, client does not expect messages of this type, dropping." << endl;
492  }
493  break;
494 
495  default:
496  throw cRuntimeError("Unknown or invalid client state %d", clientState);
497  }
498 }
Definition: DHCPClient.h:42
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
unsigned int xid
Definition: DHCPClient.h:68
virtual void handleDHCPACK(DHCPMessage *msg)
Definition: DHCPClient.cc:630
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
Definition: DHCPMessage_m.h:76
Definition: DHCPMessage_m.h:51
Definition: DHCPMessage_m.h:77
virtual void sendRequest()
Definition: DHCPClient.cc:520
virtual void recordOffer(DHCPMessage *dhcpOffer)
Definition: DHCPClient.cc:270
virtual void initClient()
Definition: DHCPClient.cc:372
InterfaceEntry * ie
Definition: DHCPClient.h:57
Definition: DHCPClient.h:47
Definition: DHCPMessage_m.h:73
ClientState clientState
Definition: DHCPClient.h:67
virtual void unbindLease()
Definition: DHCPClient.cc:358
DHCPMessageType
Enum generated from inet/applications/dhcp/DHCPMessage.msg:37 by nedtool.
Definition: DHCPMessage_m.h:71
bool isOperational
Definition: DHCPClient.h:66
virtual void scheduleTimerTO(TimerType type)
Definition: DHCPClient.cc:639
const char * getAndCheckMessageTypeName(DHCPMessageType type)
Definition: DHCPClient.cc:169
void inet::DHCPClient::handleMessage ( cMessage *  msg)
overrideprotectedvirtual
195 {
196  if (!isOperational) {
197  EV_ERROR << "Message '" << msg << "' arrived when module status is down, dropping." << endl;
198  delete msg;
199  return;
200  }
201  if (msg->isSelfMessage()) {
202  handleTimer(msg);
203  }
204  else if (msg->arrivedOn("udpIn")) {
205  DHCPMessage *dhcpPacket = dynamic_cast<DHCPMessage *>(msg);
206  if (!dhcpPacket)
207  throw cRuntimeError(dhcpPacket, "Unexpected packet received (not a DHCPMessage)");
208 
209  handleDHCPMessage(dhcpPacket);
210  delete msg;
211  }
212  else
213  throw cRuntimeError("Unknown incoming gate: '%s'", msg->getArrivalGate()->getFullName());
214 }
virtual void handleDHCPMessage(DHCPMessage *msg)
Definition: DHCPClient.cc:393
virtual void handleTimer(cMessage *msg)
Definition: DHCPClient.cc:216
bool isOperational
Definition: DHCPClient.h:66
bool inet::DHCPClient::handleOperationStage ( LifecycleOperation operation,
int  stage,
IDoneCallback doneCallback 
)
overrideprotectedvirtual

Perform one stage of a lifecycle operation.

Processing may be done entirely within this method, or may be a longer process that involves nonzero simulation time or several events, and is triggered by this method call.

Return value: true = "done"; false = "not yet done, will invoke doneCallback when done"

Implements inet::ILifecycle.

698 {
699  Enter_Method_Silent();
700  if (dynamic_cast<NodeStartOperation *>(operation)) {
702  startApp();
703  isOperational = true;
704  }
705  }
706  else if (dynamic_cast<NodeShutdownOperation *>(operation)) {
708  stopApp();
709  isOperational = false;
710  ie = nullptr;
711  }
712  }
713  else if (dynamic_cast<NodeCrashOperation *>(operation)) {
715  stopApp();
716  isOperational = false;
717  ie = nullptr;
718  }
719  }
720  else
721  throw cRuntimeError("Unsupported lifecycle operation '%s'", operation->getClassName());
722  return true;
723 }
virtual void stopApp()
Definition: DHCPClient.cc:684
Stage
Definition: NodeOperations.h:71
Stage
Definition: NodeOperations.h:126
virtual void startApp()
Definition: DHCPClient.cc:677
InterfaceEntry * ie
Definition: DHCPClient.h:57
Stage
Definition: NodeOperations.h:46
Definition: NodeOperations.h:127
bool isOperational
Definition: DHCPClient.h:66
void inet::DHCPClient::handleTimer ( cMessage *  msg)
protectedvirtual

Referenced by handleMessage().

217 {
218  int category = msg->getKind();
219 
220  if (category == START_DHCP) {
221  openSocket();
222  if (lease) {
225  }
226  else { // we have no lease from the previous DHCP process
227  clientState = INIT;
228  initClient();
229  }
230  }
231  else if (category == WAIT_OFFER) {
232  EV_DETAIL << "No DHCP offer received within timeout. Restarting. " << endl;
233  initClient();
234  }
235  else if (category == WAIT_ACK) {
236  EV_DETAIL << "No DHCP ACK received within timeout. Restarting." << endl;
237  initClient();
238  }
239  else if (category == T1) {
240  EV_DETAIL << "T1 expired. Starting RENEWING state." << endl;
243  sendRequest();
244  }
245  else if (category == T2 && clientState == RENEWING) {
246  EV_DETAIL << "T2 expired. Starting REBINDING state." << endl;
248  cancelEvent(timerT1);
249  cancelEvent(timerT2);
250  cancelEvent(timerTo);
251  cancelEvent(leaseTimer);
252 
253  sendRequest();
255  }
256  else if (category == T2) {
257  // T1 < T2 always holds by definition and when T1 expires client will move to RENEWING
258  throw cRuntimeError("T2 occurred in wrong state. (T1 must be earlier than T2.)");
259  }
260  else if (category == LEASE_TIMEOUT) {
261  EV_INFO << "Lease has expired. Starting DHCP process in INIT state." << endl;
262  unbindLease();
263  clientState = INIT;
264  initClient();
265  }
266  else
267  throw cRuntimeError("Unknown self message '%s'", msg->getName());
268 }
Definition: DHCPClient.h:42
cMessage * timerTo
Definition: DHCPClient.h:63
Definition: DHCPClient.h:47
cMessage * timerT2
Definition: DHCPClient.h:62
Definition: DHCPClient.h:42
Definition: DHCPClient.h:47
Definition: DHCPClient.h:42
Definition: DHCPClient.h:47
DHCPLease * lease
Definition: DHCPClient.h:69
cMessage * leaseTimer
Definition: DHCPClient.h:64
virtual void initRebootedClient()
Definition: DHCPClient.cc:386
virtual void sendRequest()
Definition: DHCPClient.cc:520
virtual void initClient()
Definition: DHCPClient.cc:372
Definition: DHCPClient.h:42
Definition: DHCPClient.h:47
virtual void openSocket()
Definition: DHCPClient.cc:669
Definition: DHCPClient.h:42
Definition: DHCPClient.h:42
ClientState clientState
Definition: DHCPClient.h:67
virtual void unbindLease()
Definition: DHCPClient.cc:358
cMessage * timerT1
Definition: DHCPClient.h:61
virtual void scheduleTimerTO(TimerType type)
Definition: DHCPClient.cc:639
void inet::DHCPClient::initClient ( )
protectedvirtual

Referenced by handleDHCPMessage(), handleTimer(), and receiveSignal().

373 {
374  EV_INFO << "Starting DHCP configuration process." << endl;
375 
376  cancelEvent(timerT1);
377  cancelEvent(timerT2);
378  cancelEvent(timerTo);
379  cancelEvent(leaseTimer);
380 
381  sendDiscover();
384 }
cMessage * timerTo
Definition: DHCPClient.h:63
cMessage * timerT2
Definition: DHCPClient.h:62
virtual void sendDiscover()
Definition: DHCPClient.cc:577
cMessage * leaseTimer
Definition: DHCPClient.h:64
Definition: DHCPClient.h:47
Definition: DHCPClient.h:42
ClientState clientState
Definition: DHCPClient.h:67
cMessage * timerT1
Definition: DHCPClient.h:61
virtual void scheduleTimerTO(TimerType type)
Definition: DHCPClient.cc:639
void inet::DHCPClient::initialize ( int  stage)
overrideprotectedvirtual
42 {
43  if (stage == INITSTAGE_LOCAL) {
44  timerT1 = new cMessage("T1 Timer", T1);
45  timerT2 = new cMessage("T2 Timer", T2);
46  timerTo = new cMessage("DHCP Timeout");
47  leaseTimer = new cMessage("Lease Timeout", LEASE_TIMEOUT);
48  startTimer = new cMessage("Starting DHCP", START_DHCP);
49  startTime = par("startTime");
50  }
51  else if (stage == INITSTAGE_APPLICATION_LAYER) {
52  NodeStatus *nodeStatus = dynamic_cast<NodeStatus *>(findContainingNode(this)->getSubmodule("status"));
53  isOperational = (!nodeStatus) || nodeStatus->getState() == NodeStatus::UP;
54 
55  numSent = 0;
56  numReceived = 0;
57  xid = 0;
58  responseTimeout = 60; // response timeout in seconds RFC 2131, 4.4.3
59 
60  WATCH(numSent);
61  WATCH(numReceived);
62  WATCH(clientState);
63  WATCH(xid);
64 
65  // DHCP UDP ports
66  clientPort = 68; // client
67  serverPort = 67; // server
68 
69  // get the hostname
70  host = getContainingNode(this);
71 
72  // for a wireless interface subscribe the association event to start the DHCP protocol
73  host->subscribe(NF_L2_ASSOCIATED, this);
74  host->subscribe(NF_INTERFACE_DELETED, this);
75 
76  // get the routing table to update and subscribe it to the blackboard
77  irt = getModuleFromPar<IIPv4RoutingTable>(par("routingTableModule"), this);
78  // set client to idle state
79  clientState = IDLE;
80  // get the interface to configure
81 
82  if (isOperational) {
83  ie = chooseInterface();
84  // grab the interface MAC address
86  startApp();
87  }
88  }
89 }
cMessage * timerTo
Definition: DHCPClient.h:63
cMessage * timerT2
Definition: DHCPClient.h:62
simtime_t startTime
Definition: DHCPClient.h:54
virtual InterfaceEntry * chooseInterface()
Definition: DHCPClient.cc:91
Definition: DHCPClient.h:47
int responseTimeout
Definition: DHCPClient.h:75
Definition: DHCPClient.h:42
unsigned int xid
Definition: DHCPClient.h:68
Definition: DHCPClient.h:42
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:56
Local initializations.
Definition: InitStages.h:35
cMessage * leaseTimer
Definition: DHCPClient.h:64
virtual void startApp()
Definition: DHCPClient.cc:677
cModule * getContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:65
InterfaceEntry * ie
Definition: DHCPClient.h:57
int clientPort
Definition: DHCPClient.h:52
MACAddress macAddress
Definition: DHCPClient.h:55
int numSent
Definition: DHCPClient.h:73
cMessage * startTimer
Definition: DHCPClient.h:65
const MACAddress & getMacAddress() const
Definition: InterfaceEntry.h:197
simsignal_t NF_L2_ASSOCIATED
Definition: NotifierConsts.cc:36
int serverPort
Definition: DHCPClient.h:51
simsignal_t NF_INTERFACE_DELETED
Definition: NotifierConsts.cc:49
IIPv4RoutingTable * irt
Definition: DHCPClient.h:58
Definition: DHCPClient.h:42
Definition: DHCPClient.h:42
int numReceived
Definition: DHCPClient.h:74
ClientState clientState
Definition: DHCPClient.h:67
cMessage * timerT1
Definition: DHCPClient.h:61
bool isOperational
Definition: DHCPClient.h:66
cModule * host
Definition: DHCPClient.h:56
Initialization of applications.
Definition: InitStages.h:106
Definition: NodeStatus.h:40
void inet::DHCPClient::initRebootedClient ( )
protectedvirtual

Referenced by handleTimer().

387 {
388  sendRequest();
391 }
Definition: DHCPClient.h:42
Definition: DHCPClient.h:47
virtual void sendRequest()
Definition: DHCPClient.cc:520
ClientState clientState
Definition: DHCPClient.h:67
virtual void scheduleTimerTO(TimerType type)
Definition: DHCPClient.cc:639
virtual int inet::DHCPClient::numInitStages ( ) const
inlineoverrideprotectedvirtual
78 { return NUM_INIT_STAGES; }
The number of initialization stages.
Definition: InitStages.h:116
void inet::DHCPClient::openSocket ( )
protectedvirtual

Referenced by handleTimer().

670 {
671  socket.setOutputGate(gate("udpOut"));
673  socket.setBroadcast(true);
674  EV_INFO << "DHCP server bound to port " << serverPort << "." << endl;
675 }
UDPSocket socket
Definition: DHCPClient.h:53
void setOutputGate(cGate *toUdp)
Sets the gate on which to send to UDP.
Definition: UDPSocket.h:110
void setBroadcast(bool broadcast)
Set the Broadcast option on the UDP socket.
Definition: UDPSocket.cc:121
int clientPort
Definition: DHCPClient.h:52
int serverPort
Definition: DHCPClient.h:51
void bind(int localPort)
Bind the socket to a local port number.
Definition: UDPSocket.cc:53
void inet::DHCPClient::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprotectedvirtual
501 {
502  Enter_Method_Silent();
503  printNotificationBanner(signalID, obj);
504 
505  // host associated. link is up. change the state to init.
506  if (signalID == NF_L2_ASSOCIATED) {
507  InterfaceEntry *associatedIE = check_and_cast_nullable<InterfaceEntry *>(obj);
508  if (associatedIE && ie == associatedIE) {
509  EV_INFO << "Interface associated, starting DHCP." << endl;
510  unbindLease();
511  initClient();
512  }
513  }
514  else if (signalID == NF_INTERFACE_DELETED) {
515  if (isOperational)
516  throw cRuntimeError("Reacting to interface deletions is not implemented in this module");
517  }
518 }
virtual void initClient()
Definition: DHCPClient.cc:372
InterfaceEntry * ie
Definition: DHCPClient.h:57
void printNotificationBanner(simsignal_t signalID, const cObject *obj)
Utility function.
Definition: NotifierConsts.cc:109
simsignal_t NF_L2_ASSOCIATED
Definition: NotifierConsts.cc:36
simsignal_t NF_INTERFACE_DELETED
Definition: NotifierConsts.cc:49
virtual void unbindLease()
Definition: DHCPClient.cc:358
bool isOperational
Definition: DHCPClient.h:66
void inet::DHCPClient::recordLease ( DHCPMessage dhcpACK)
protectedvirtual

Referenced by handleDHCPACK().

291 {
292  if (!dhcpACK->getYiaddr().isUnspecified()) {
293  IPv4Address ip = dhcpACK->getYiaddr();
294  EV_DETAIL << "DHCPACK arrived with " << "IP: " << ip << endl;
295 
296  lease->subnetMask = dhcpACK->getOptions().getSubnetMask();
297 
298  if (dhcpACK->getOptions().getRouterArraySize() > 0)
299  lease->gateway = dhcpACK->getOptions().getRouter(0);
300  if (dhcpACK->getOptions().getDnsArraySize() > 0)
301  lease->dns = dhcpACK->getOptions().getDns(0);
302  if (dhcpACK->getOptions().getNtpArraySize() > 0)
303  lease->ntp = dhcpACK->getOptions().getNtp(0);
304 
305  lease->leaseTime = dhcpACK->getOptions().getLeaseTime();
306  lease->renewalTime = dhcpACK->getOptions().getRenewalTime();
307  lease->rebindTime = dhcpACK->getOptions().getRebindingTime();
308 
309  // std::cout << lease->leaseTime << " " << lease->renewalTime << " " << lease->rebindTime << endl;
310  }
311  else
312  EV_ERROR << "DHCPACK arrived, but no IP address confirmed." << endl;
313 }
simtime_t renewalTime
Definition: DHCPLease.h:44
IPv4Address ntp
Definition: DHCPLease.h:40
simtime_t leaseTime
Definition: DHCPLease.h:43
IPv4Address gateway
Definition: DHCPLease.h:37
simtime_t rebindTime
Definition: DHCPLease.h:45
DHCPLease * lease
Definition: DHCPClient.h:69
IPv4Address dns
Definition: DHCPLease.h:39
IPv4Address subnetMask
Definition: DHCPLease.h:38
void inet::DHCPClient::recordOffer ( DHCPMessage dhcpOffer)
protectedvirtual

Referenced by handleDHCPMessage().

271 {
272  if (!dhcpOffer->getYiaddr().isUnspecified()) {
273  IPv4Address ip = dhcpOffer->getYiaddr();
274 
275  //Byte serverIdB = dhcpOffer->getOptions().get(SERVER_ID);
276  IPv4Address serverId = dhcpOffer->getOptions().getServerIdentifier();
277 
278  // minimal information to configure the interface
279  // create the lease to request
280  delete lease;
281  lease = new DHCPLease();
282  lease->ip = ip;
283  lease->mac = macAddress;
284  lease->serverId = serverId;
285  }
286  else
287  EV_WARN << "DHCPOFFER arrived, but no IP address has been offered. Discarding it and remaining in SELECTING." << endl;
288 }
DHCPLease * lease
Definition: DHCPClient.h:69
IPv4Address serverId
Definition: DHCPLease.h:41
IPv4Address ip
Definition: DHCPLease.h:35
MACAddress macAddress
Definition: DHCPClient.h:55
MACAddress mac
Definition: DHCPLease.h:36
void inet::DHCPClient::refreshDisplay ( ) const
overrideprotectedvirtual
190 {
191  getDisplayString().setTagArg("t", 0, getStateName(clientState));
192 }
static const char * getStateName(ClientState state)
Definition: DHCPClient.cc:149
ClientState clientState
Definition: DHCPClient.h:67
void inet::DHCPClient::scheduleTimerT1 ( )
protectedvirtual

Referenced by handleDHCPACK().

648 {
649  // cancel the previous T1
650  cancelEvent(timerT1);
651  scheduleAt(simTime() + (lease->renewalTime), timerT1); // RFC 2131 4.4.5
652 }
simtime_t renewalTime
Definition: DHCPLease.h:44
DHCPLease * lease
Definition: DHCPClient.h:69
cMessage * timerT1
Definition: DHCPClient.h:61
void inet::DHCPClient::scheduleTimerT2 ( )
protectedvirtual

Referenced by handleDHCPACK().

655 {
656  // cancel the previous T2
657  cancelEvent(timerT2);
658  scheduleAt(simTime() + (lease->rebindTime), timerT2); // RFC 2131 4.4.5
659 }
cMessage * timerT2
Definition: DHCPClient.h:62
simtime_t rebindTime
Definition: DHCPLease.h:45
DHCPLease * lease
Definition: DHCPClient.h:69
void inet::DHCPClient::scheduleTimerTO ( TimerType  type)
protectedvirtual

Referenced by handleDHCPMessage(), handleTimer(), initClient(), and initRebootedClient().

640 {
641  // cancel the previous timeout
642  cancelEvent(timerTo);
643  timerTo->setKind(type);
644  scheduleAt(simTime() + responseTimeout, timerTo);
645 }
cMessage * timerTo
Definition: DHCPClient.h:63
int responseTimeout
Definition: DHCPClient.h:75
void inet::DHCPClient::sendDecline ( IPv4Address  declinedIp)
protectedvirtual
610 {
611  xid = intuniform(0, RAND_MAX);
612  DHCPMessage *decline = new DHCPMessage("DHCPDECLINE");
613  decline->setOp(BOOTREQUEST);
614  decline->setByteLength(280); // DHCPDECLINE packet size
615  decline->setHtype(1); // ethernet
616  decline->setHlen(6); // hardware Address length (6 octets)
617  decline->setHops(0);
618  decline->setXid(xid); // transaction id
619  decline->setSecs(0); // 0 seconds from transaction started
620  decline->setBroadcast(false); // unicast
621  decline->setChaddr(macAddress); // my MAC address
622  decline->setSname(""); // no server name given
623  decline->setFile(""); // no file given
624  decline->getOptions().setMessageType(DHCPDECLINE);
625  decline->getOptions().setRequestedIp(declinedIp);
626  EV_INFO << "Sending DHCPDECLINE." << endl;
628 }
unsigned int xid
Definition: DHCPClient.h:68
Definition: DHCPMessage_m.h:75
Definition: DHCPMessage_m.h:50
virtual void sendToUDP(cPacket *msg, int srcPort, const L3Address &destAddr, int destPort)
Definition: DHCPClient.cc:661
int clientPort
Definition: DHCPClient.h:52
MACAddress macAddress
Definition: DHCPClient.h:55
int serverPort
Definition: DHCPClient.h:51
static const IPv4Address ALLONES_ADDRESS
255.255.255.255
Definition: IPv4Address.h:105
void inet::DHCPClient::sendDiscover ( )
protectedvirtual

Referenced by initClient().

578 {
579  // setting the xid
580  xid = intuniform(0, RAND_MAX);
581  //std::cout << xid << endl;
582  DHCPMessage *discover = new DHCPMessage("DHCPDISCOVER");
583  discover->setOp(BOOTREQUEST);
584  discover->setByteLength(280); // DHCP Discover packet size;
585  discover->setHtype(1); // ethernet
586  discover->setHlen(6); // hardware Address lenght (6 octets)
587  discover->setHops(0);
588  discover->setXid(xid); // transaction id
589  discover->setSecs(0); // 0 seconds from transaction started
590  discover->setBroadcast(false); // unicast
591  discover->setChaddr(macAddress); // my mac address
592  discover->setSname(""); // no server name given
593  discover->setFile(""); // no file given
594  discover->getOptions().setMessageType(DHCPDISCOVER);
595  discover->getOptions().setClientIdentifier(macAddress);
596  discover->getOptions().setRequestedIp(IPv4Address());
597 
598  // set the parameters to request
599  discover->getOptions().setParameterRequestListArraySize(4);
600  discover->getOptions().setParameterRequestList(0, SUBNET_MASK);
601  discover->getOptions().setParameterRequestList(1, ROUTER);
602  discover->getOptions().setParameterRequestList(2, DNS);
603  discover->getOptions().setParameterRequestList(3, NTP_SRV);
604 
605  EV_INFO << "Sending DHCPDISCOVER." << endl;
607 }
Definition: DHCPMessage_m.h:72
unsigned int xid
Definition: DHCPClient.h:68
Definition: DHCPMessage_m.h:113
Definition: DHCPMessage_m.h:110
Definition: DHCPMessage_m.h:111
Definition: DHCPMessage_m.h:112
Definition: DHCPMessage_m.h:50
virtual void sendToUDP(cPacket *msg, int srcPort, const L3Address &destAddr, int destPort)
Definition: DHCPClient.cc:661
int clientPort
Definition: DHCPClient.h:52
MACAddress macAddress
Definition: DHCPClient.h:55
int serverPort
Definition: DHCPClient.h:51
static const IPv4Address ALLONES_ADDRESS
255.255.255.255
Definition: IPv4Address.h:105
void inet::DHCPClient::sendRequest ( )
protectedvirtual

Referenced by handleDHCPMessage(), handleTimer(), and initRebootedClient().

521 {
522  // setting the xid
523  xid = intuniform(0, RAND_MAX); // generating a new xid for each transmission
524 
525  DHCPMessage *request = new DHCPMessage("DHCPREQUEST");
526  request->setOp(BOOTREQUEST);
527  request->setByteLength(280); // DHCP request packet size
528  request->setHtype(1); // ethernet
529  request->setHlen(6); // hardware Address length (6 octets)
530  request->setHops(0);
531  request->setXid(xid); // transaction id
532  request->setSecs(0); // 0 seconds from transaction started
533  request->setBroadcast(false); // unicast
534  request->setYiaddr(IPv4Address()); // no 'your IP' addr
535  request->setGiaddr(IPv4Address()); // no DHCP Gateway Agents
536  request->setChaddr(macAddress); // my mac address;
537  request->setSname(""); // no server name given
538  request->setFile(""); // no file given
539  request->getOptions().setMessageType(DHCPREQUEST);
540  request->getOptions().setClientIdentifier(macAddress);
541 
542  // set the parameters to request
543  request->getOptions().setParameterRequestListArraySize(4);
544  request->getOptions().setParameterRequestList(0, SUBNET_MASK);
545  request->getOptions().setParameterRequestList(1, ROUTER);
546  request->getOptions().setParameterRequestList(2, DNS);
547  request->getOptions().setParameterRequestList(3, NTP_SRV);
548 
549  // RFC 4.3.6 Table 4
550  if (clientState == INIT_REBOOT) {
551  request->getOptions().setRequestedIp(lease->ip);
552  request->setCiaddr(IPv4Address()); // zero
553  EV_INFO << "Sending DHCPREQUEST asking for IP " << lease->ip << " via broadcast." << endl;
555  }
556  else if (clientState == REQUESTING) {
557  request->getOptions().setServerIdentifier(lease->serverId);
558  request->getOptions().setRequestedIp(lease->ip);
559  request->setCiaddr(IPv4Address()); // zero
560  EV_INFO << "Sending DHCPREQUEST asking for IP " << lease->ip << " via broadcast." << endl;
562  }
563  else if (clientState == RENEWING) {
564  request->setCiaddr(lease->ip); // the client IP
565  EV_INFO << "Sending DHCPREQUEST extending lease for IP " << lease->ip << " via unicast to " << lease->serverId << "." << endl;
567  }
568  else if (clientState == REBINDING) {
569  request->setCiaddr(lease->ip); // the client IP
570  EV_INFO << "Sending DHCPREQUEST renewing the IP " << lease->ip << " via broadcast." << endl;
572  }
573  else
574  throw cRuntimeError("Invalid state");
575 }
Definition: DHCPClient.h:47
unsigned int xid
Definition: DHCPClient.h:68
Definition: DHCPMessage_m.h:113
Definition: DHCPMessage_m.h:110
Definition: DHCPClient.h:47
Definition: DHCPClient.h:47
DHCPLease * lease
Definition: DHCPClient.h:69
Definition: DHCPMessage_m.h:111
IPv4Address serverId
Definition: DHCPLease.h:41
Definition: DHCPMessage_m.h:112
Definition: DHCPMessage_m.h:74
Definition: DHCPMessage_m.h:50
IPv4Address ip
Definition: DHCPLease.h:35
virtual void sendToUDP(cPacket *msg, int srcPort, const L3Address &destAddr, int destPort)
Definition: DHCPClient.cc:661
int clientPort
Definition: DHCPClient.h:52
MACAddress macAddress
Definition: DHCPClient.h:55
Definition: DHCPClient.h:47
int serverPort
Definition: DHCPClient.h:51
static const IPv4Address ALLONES_ADDRESS
255.255.255.255
Definition: IPv4Address.h:105
ClientState clientState
Definition: DHCPClient.h:67
void inet::DHCPClient::sendToUDP ( cPacket *  msg,
int  srcPort,
const L3Address destAddr,
int  destPort 
)
protectedvirtual

Referenced by sendDecline(), sendDiscover(), and sendRequest().

662 {
663  EV_INFO << "Sending packet " << msg << endl;
664  UDPSocket::SendOptions options;
665  options.outInterfaceId = ie->getInterfaceId();
666  socket.sendTo(msg, destAddr, destPort, &options);
667 }
int getInterfaceId() const
Definition: InterfaceEntry.h:185
void sendTo(cPacket *msg, L3Address destAddr, int destPort, const SendOptions *options=nullptr)
Sends a data packet to the given address and port.
Definition: UDPSocket.cc:88
UDPSocket socket
Definition: DHCPClient.h:53
InterfaceEntry * ie
Definition: DHCPClient.h:57
void inet::DHCPClient::startApp ( )
protectedvirtual

Referenced by handleOperationStage(), and initialize().

678 {
679  simtime_t start = std::max(startTime, simTime());
680  ie = chooseInterface();
681  scheduleAt(start, startTimer);
682 }
simtime_t startTime
Definition: DHCPClient.h:54
virtual InterfaceEntry * chooseInterface()
Definition: DHCPClient.cc:91
double max(double a, double b)
Returns the greater of the given parameters.
Definition: INETMath.h:161
InterfaceEntry * ie
Definition: DHCPClient.h:57
cMessage * startTimer
Definition: DHCPClient.h:65
void inet::DHCPClient::stopApp ( )
protectedvirtual

Referenced by handleOperationStage().

685 {
686  cancelEvent(timerT1);
687  cancelEvent(timerT2);
688  cancelEvent(timerTo);
689  cancelEvent(leaseTimer);
690  cancelEvent(startTimer);
691 
692  // TODO: Client should send DHCPRELEASE to the server. However, the correct operation
693  // of DHCP does not depend on the transmission of DHCPRELEASE messages.
694  // TODO: socket.close();
695 }
cMessage * timerTo
Definition: DHCPClient.h:63
cMessage * timerT2
Definition: DHCPClient.h:62
cMessage * leaseTimer
Definition: DHCPClient.h:64
cMessage * startTimer
Definition: DHCPClient.h:65
cMessage * timerT1
Definition: DHCPClient.h:61
void inet::DHCPClient::unbindLease ( )
protectedvirtual

Referenced by handleDHCPMessage(), handleTimer(), and receiveSignal().

359 {
360  EV_INFO << "Unbinding lease on " << ie->getName() << "." << endl;
361 
362  cancelEvent(timerT1);
363  cancelEvent(timerT2);
364  cancelEvent(timerTo);
365  cancelEvent(leaseTimer);
366 
368  ie->ipv4Data()->setIPAddress(IPv4Address());
370 }
IPv4InterfaceData * ipv4Data() const
Definition: InterfaceEntry.h:221
cMessage * timerTo
Definition: DHCPClient.h:63
cMessage * timerT2
Definition: DHCPClient.h:62
virtual bool deleteRoute(IPv4Route *entry)=0
Deletes the given route from the routing table.
IPv4Route * route
Definition: DHCPClient.h:70
virtual void setIPAddress(IPv4Address a)
Definition: IPv4InterfaceData.h:195
cMessage * leaseTimer
Definition: DHCPClient.h:64
virtual void setNetmask(IPv4Address m)
Definition: IPv4InterfaceData.h:196
InterfaceEntry * ie
Definition: DHCPClient.h:57
static const IPv4Address ALLONES_ADDRESS
255.255.255.255
Definition: IPv4Address.h:105
IIPv4RoutingTable * irt
Definition: DHCPClient.h:58
cMessage * timerT1
Definition: DHCPClient.h:61

Member Data Documentation

int inet::DHCPClient::clientPort = -1
protected
cModule* inet::DHCPClient::host = nullptr
protected

Referenced by bindLease(), and initialize().

IIPv4RoutingTable* inet::DHCPClient::irt = nullptr
protected

Referenced by bindLease(), initialize(), and unbindLease().

bool inet::DHCPClient::isOperational = false
protected
DHCPLease* inet::DHCPClient::lease = nullptr
protected
cMessage* inet::DHCPClient::leaseTimer = nullptr
protected
MACAddress inet::DHCPClient::macAddress
protected
int inet::DHCPClient::numReceived = 0
protected

Referenced by initialize().

int inet::DHCPClient::numSent = 0
protected

Referenced by initialize().

int inet::DHCPClient::responseTimeout = 0
protected

Referenced by initialize(), and scheduleTimerTO().

IPv4Route* inet::DHCPClient::route = nullptr
protected

Referenced by bindLease(), and unbindLease().

int inet::DHCPClient::serverPort = -1
protected
UDPSocket inet::DHCPClient::socket
protected

Referenced by openSocket(), and sendToUDP().

simtime_t inet::DHCPClient::startTime
protected

Referenced by initialize(), and startApp().

cMessage* inet::DHCPClient::startTimer = nullptr
protected
cMessage* inet::DHCPClient::timerT1 = nullptr
protected
cMessage* inet::DHCPClient::timerT2 = nullptr
protected
cMessage* inet::DHCPClient::timerTo = nullptr
protected
unsigned int inet::DHCPClient::xid = 0
protected

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