Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ | |
2 /* | |
3 * Copyright (c) 2011 UPB | |
4 * Copyright (c) 2017 NITK Surathkal | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License version 2 as | |
8 * published by the Free Software Foundation; | |
9 * | |
10 * This program is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 * GNU General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU General Public License | |
16 * along with this program; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 * | |
19 * Author: Radu Lupu <rlupu@elcom.pub.ro> | |
20 * Ankit Deepak <adadeepak8@gmail.com> | |
21 * Deepti Rajagopal <deeptir96@gmail.com> | |
22 * | |
23 * | |
24 */ | |
25 | |
26 #include <stdlib.h> | |
27 #include <stdio.h> | |
28 #include <ns3/ipv4.h> | |
29 #include "ns3/log.h" | |
30 #include "ns3/double.h" | |
31 #include "ns3/ipv4-address.h" | |
32 #include "ns3/nstime.h" | |
33 #include "ns3/inet-socket-address.h" | |
34 #include "ns3/socket.h" | |
35 #include "ns3/simulator.h" | |
36 #include "ns3/socket-factory.h" | |
37 #include "ns3/packet.h" | |
38 #include "ns3/uinteger.h" | |
39 #include <ns3/ipv4-static-routing-helper.h> | |
40 #include "ns3/random-variable-stream.h" | |
41 #include "dhcp-client.h" | |
42 #include "dhcp-header.h" | |
43 #include "ns3/pointer.h" | |
44 #include "ns3/string.h" | |
45 #include "ns3/ipv4-routing-table-entry.h" | |
46 #include <list> | |
47 | |
48 namespace ns3 { | |
49 | |
50 NS_LOG_COMPONENT_DEFINE ("DhcpClient"); | |
51 NS_OBJECT_ENSURE_REGISTERED (DhcpClient); | |
52 | |
53 TypeId | |
54 DhcpClient::GetTypeId (void) | |
55 { | |
56 static TypeId tid = TypeId ("ns3::DhcpClient") | |
57 .SetParent<Application> () | |
58 .AddConstructor<DhcpClient> () | |
59 .SetGroupName ("Internet-Apps") | |
60 .AddAttribute ("NetDevice", "Index of netdevice of the node for DHCP", | |
61 UintegerValue (0), | |
62 MakeUintegerAccessor (&DhcpClient::device), | |
63 MakeUintegerChecker<uint32_t> ()) | |
64 .AddAttribute ("RTRS", "Time for retransmission of Discover message", | |
65 TimeValue (Seconds (5)), | |
66 MakeTimeAccessor (&DhcpClient::m_rtrs), | |
67 MakeTimeChecker ()) | |
68 .AddAttribute ("Collect", "Time for which offer collection starts", | |
69 TimeValue (Seconds (5)), | |
70 MakeTimeAccessor (&DhcpClient::m_collect), | |
71 MakeTimeChecker ()) | |
72 .AddAttribute ("ReRequest", "Time after which request will be resent to next server", | |
73 TimeValue (Seconds (10)), | |
74 MakeTimeAccessor (&DhcpClient::m_nextoffer), | |
75 MakeTimeChecker ()) | |
76 .AddAttribute ("Transactions", | |
77 "The possible value of transaction numbers ", | |
78 StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=1000000. 0]"), | |
79 MakePointerAccessor (&DhcpClient::m_ran), | |
80 MakePointerChecker<RandomVariableStream> ()) | |
81 .AddTraceSource ("NewLease", | |
82 "Get a NewLease", | |
83 MakeTraceSourceAccessor (&DhcpClient::m_newLease), | |
84 "ns3::Ipv4Address::TracedCallback") | |
85 .AddTraceSource ("Expiry", | |
86 "A lease expires", | |
87 MakeTraceSourceAccessor (&DhcpClient::m_expiry), | |
88 "ns3::Ipv4Address::TracedCallback"); | |
89 return tid; | |
90 } | |
91 | |
92 DhcpClient::DhcpClient () : m_server (Ipv4Address::GetAny ()) | |
93 { | |
94 NS_LOG_FUNCTION_NOARGS (); | |
95 m_socket = 0; | |
96 m_refreshEvent = EventId (); | |
97 m_requestEvent = EventId (); | |
98 m_discoverEvent = EventId (); | |
99 m_rebindEvent = EventId (); | |
100 m_nextOfferEvent = EventId (); | |
101 m_timeout = EventId (); | |
102 } | |
103 | |
104 DhcpClient::~DhcpClient () | |
105 { | |
106 NS_LOG_FUNCTION_NOARGS (); | |
107 } | |
108 | |
109 Ipv4Address DhcpClient::GetDhcpServer (void) | |
110 { | |
111 return m_server; | |
112 } | |
113 | |
114 void | |
115 DhcpClient::DoDispose (void) | |
116 { | |
117 NS_LOG_FUNCTION_NOARGS (); | |
118 Application::DoDispose (); | |
119 } | |
120 | |
121 int64_t | |
122 DhcpClient::AssignStreams (int64_t stream) | |
123 { | |
124 NS_LOG_FUNCTION (this << stream); | |
125 m_ran->SetStream (stream); | |
126 return 1; | |
127 } | |
128 | |
129 void | |
130 DhcpClient::StartApplication (void) | |
131 { | |
132 NS_LOG_FUNCTION_NOARGS (); | |
133 m_remoteAddress = Ipv4Address ("255.255.255.255"); | |
134 m_myAddress = Ipv4Address ("0.0.0.0"); | |
135 Ptr<Ipv4> ipv4 = GetNode ()->GetObject<Ipv4> (); | |
136 uint32_t ifIndex = ipv4->GetInterfaceForDevice (GetNode ()->GetDevice (device) ); | |
137 uint32_t i; | |
138 bool found = false; | |
139 for (i = 0; i < ipv4->GetNAddresses (ifIndex); i++) | |
140 { | |
141 if (ipv4->GetAddress (ifIndex,i).GetLocal () == m_myAddress) | |
142 { | |
143 found = true; | |
144 } | |
145 } | |
146 if (!found) | |
147 { | |
148 ipv4->AddAddress (ifIndex, Ipv4InterfaceAddress (Ipv4Address ("0.0.0.0"),I pv4Mask ("/0"))); | |
149 } | |
150 if (m_socket == 0) | |
151 { | |
152 TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); | |
153 m_socket = Socket::CreateSocket (GetNode (), tid); | |
154 InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 68); | |
155 m_socket->SetAllowBroadcast (true); | |
156 m_socket->Bind (local); | |
157 m_socket->BindToNetDevice (GetNode ()->GetDevice (device)); | |
158 } | |
159 m_socket->SetRecvCallback (MakeCallback (&DhcpClient::NetHandler, this)); | |
160 | |
161 GetNode ()->GetDevice (device)->AddLinkChangeCallback (MakeCallback (&DhcpClie nt::LinkStateHandler, this)); | |
162 Boot (); | |
163 | |
164 } | |
165 | |
166 void | |
167 DhcpClient::StopApplication () | |
168 { | |
169 NS_LOG_FUNCTION_NOARGS (); | |
170 Simulator::Remove (m_discoverEvent); | |
171 Simulator::Remove (m_requestEvent); | |
172 Simulator::Remove (m_rebindEvent); | |
173 Simulator::Remove (m_refreshEvent); | |
174 Simulator::Remove (m_timeout); | |
175 Ptr<Ipv4> ipv4 = GetNode ()->GetObject<Ipv4> (); | |
176 | |
177 int32_t ifIndex = ipv4->GetInterfaceForDevice (GetNode ()->GetDevice (device)) ; | |
178 for (uint32_t i = 0; i < ipv4->GetNAddresses (ifIndex); i++) | |
179 { | |
180 if (ipv4->GetAddress (ifIndex,i).GetLocal () == m_myAddress) | |
181 { | |
182 ipv4->RemoveAddress (ifIndex, i); | |
183 break; | |
184 } | |
185 } | |
186 | |
187 m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ()); | |
188 m_socket->Close (); | |
189 } | |
190 | |
191 void DhcpClient::LinkStateHandler (void) | |
192 { | |
193 if (GetNode ()->GetDevice (device)->IsLinkUp ()) | |
194 { | |
195 NS_LOG_INFO ("[node " << GetNode ()->GetId () << "] " << "LINK UP!!!! at " << Simulator::Now ().GetSeconds ()); | |
196 m_socket->SetRecvCallback (MakeCallback (&DhcpClient::NetHandler, this)); | |
197 Boot (); | |
198 } | |
199 else | |
200 { | |
201 NS_LOG_INFO ("[node " << GetNode ()->GetId () << "] " << "LINK DOWN!!!! a t " << Simulator::Now ().GetSeconds ()); //reinitialization | |
202 Simulator::Remove (m_refreshEvent); //stop refresh timer!!!! | |
203 m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ()); //st op receiving on this socket !!! | |
204 | |
205 Ptr<Ipv4> ipv4MN = GetNode ()->GetObject<Ipv4> (); | |
206 int32_t ifIndex = ipv4MN->GetInterfaceForDevice (GetNode ()->GetDevice (de vice)); | |
207 | |
208 for (uint32_t i = 0; i < ipv4MN->GetNAddresses (ifIndex); i++) | |
209 { | |
210 if (ipv4MN->GetAddress (ifIndex,i).GetLocal () == m_myAddress) | |
211 { | |
212 ipv4MN->RemoveAddress (ifIndex, i); | |
213 break; | |
214 } | |
215 } | |
216 | |
217 Ipv4StaticRoutingHelper ipv4RoutingHelper; | |
218 Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting (ipv4MN); | |
219 uint32_t i; | |
220 for (i = 0; i < staticRouting->GetNRoutes (); i++) | |
221 { | |
222 if (staticRouting->GetRoute (i).GetGateway () == m_gateway) | |
223 { | |
224 staticRouting->RemoveRoute (i); | |
225 break; | |
226 } | |
227 } | |
228 } | |
229 } | |
230 | |
231 void DhcpClient::NetHandler (Ptr<Socket> socket) | |
232 { | |
233 NS_LOG_FUNCTION (this << socket); | |
234 Address from; | |
235 Ptr<Packet> packet = m_socket->RecvFrom (from); | |
236 DhcpHeader header; | |
237 if (packet->RemoveHeader (header) == 0) | |
238 { | |
239 return; | |
240 } | |
241 if (header.GetChaddr () != GetNode ()->GetDevice (device)->GetAddress ()) | |
242 { | |
243 return; | |
244 } | |
245 if (m_state == WAIT_OFFER && header.GetType () == DhcpHeader::DHCPOFFER) | |
246 { | |
247 OfferHandler (header); | |
248 } | |
249 if (m_state == WAIT_ACK && header.GetType () == DhcpHeader::DHCPACK) | |
250 { | |
251 Simulator::Remove (m_nextOfferEvent); | |
252 AcceptAck (header,from); | |
253 } | |
254 if (m_state == WAIT_ACK && header.GetType () == DhcpHeader::DHCPNACK) | |
255 { | |
256 Simulator::Remove (m_nextOfferEvent); | |
257 Boot (); | |
258 } | |
259 } | |
260 | |
261 void DhcpClient::Boot (void) | |
Tommaso Pecorella
2017/01/13 00:43:32
This is embarrassing... because we never noticed b
adadeepak8
2017/01/16 07:47:59
Done.
| |
262 { | |
263 DhcpHeader header; | |
264 Ptr<Packet> packet; | |
265 packet = Create<Packet> (); | |
266 header.ResetOpt (); | |
267 m_tran = (uint32_t) (m_ran->GetValue ()); | |
268 header.SetTran (m_tran); | |
269 header.SetType (DhcpHeader::DHCPDISCOVER); | |
270 header.SetTime (); | |
271 header.SetChaddr (GetNode ()->GetDevice (device)->GetAddress ()); | |
272 packet->AddHeader (header); | |
273 | |
274 if ((m_socket->SendTo (packet, 0, InetSocketAddress (Ipv4Address ("255.255.255 .255"), DHCP_PEER_PORT))) >= 0) | |
275 { | |
276 NS_LOG_INFO ("[node " << GetNode ()->GetId () << "] Trace TX: DHCP DISCOVE R" ); | |
277 } | |
278 else | |
279 { | |
280 NS_LOG_INFO ("[node " << GetNode ()->GetId () << "] " << "Error while sen ding DHCP DISCOVER to " << m_remoteAddress); | |
281 } | |
282 m_state = WAIT_OFFER; | |
283 m_offered = false; | |
284 m_discoverEvent = Simulator::Schedule (m_rtrs, &DhcpClient::Boot, this); | |
285 } | |
286 | |
287 void DhcpClient::OfferHandler (DhcpHeader header) | |
288 { | |
289 m_offerList.push_back (header); | |
290 if (m_offered == false) | |
291 { | |
292 Simulator::Remove (m_discoverEvent); | |
293 m_offered = true; | |
294 Simulator::Schedule (m_collect, &DhcpClient::Select, this); | |
295 } | |
296 } | |
297 | |
298 void DhcpClient::Select (void) | |
299 { | |
300 if (m_offerList.empty ()) | |
301 { | |
302 Boot (); | |
303 } | |
304 DhcpHeader header = m_offerList.front (); | |
305 m_offerList.pop_front (); | |
306 m_lease = Time (Seconds (header.GetLease ())); | |
307 m_renew = Time (Seconds (header.GetRenew ())); | |
308 m_rebind = Time (Seconds (header.GetRebind ())); | |
309 m_offeredAddress = header.GetYiaddr (); | |
310 m_myMask = Ipv4Mask (header.GetMask ()); | |
311 m_server = header.GetDhcps (); | |
312 m_gateway = header.GetRouter (); | |
313 Request (); | |
314 } | |
315 | |
316 void DhcpClient::Request (void) | |
317 { | |
318 DhcpHeader header; | |
319 Ptr<Packet> packet; | |
320 if (m_state != REFRESH_LEASE) | |
321 { | |
322 packet = Create<Packet> (); | |
323 header.ResetOpt (); | |
324 header.SetType (DhcpHeader::DHCPREQ); | |
325 header.SetTime (); | |
326 header.SetTran (m_tran); | |
327 header.SetReq (m_offeredAddress); | |
328 header.SetChaddr (GetNode ()->GetDevice (device)->GetAddress ()); | |
329 packet->AddHeader (header); | |
330 m_socket->SendTo (packet, 0, InetSocketAddress (Ipv4Address ("255.255.255. 255"), DHCP_PEER_PORT)); | |
331 m_state = WAIT_ACK; | |
332 m_nextOfferEvent = Simulator::Schedule (m_nextoffer, &DhcpClient::Select, this); | |
333 } | |
334 else | |
335 { | |
336 uint32_t addr = m_myAddress.Get (); | |
337 packet = Create<Packet> ((uint8_t*)&addr, sizeof(addr)); | |
338 header.ResetOpt (); | |
339 m_tran = (uint32_t) (m_ran->GetValue ()); | |
340 header.SetTran (m_tran); | |
341 header.SetTime (); | |
342 header.SetType (DhcpHeader::DHCPREQ); | |
343 header.SetReq (m_myAddress); | |
344 m_offeredAddress = m_myAddress; | |
345 header.SetChaddr (GetNode ()->GetDevice (device)->GetAddress ()); | |
346 packet->AddHeader (header); | |
347 if ((m_socket->SendTo (packet, 0, InetSocketAddress (m_remoteAddress, DHCP _PEER_PORT))) >= 0) | |
348 { | |
349 NS_LOG_INFO ("[node " << GetNode ()->GetId () << "] " << "Trace TX: D HCP REQUEST"); | |
350 } | |
351 else | |
352 { | |
353 NS_LOG_INFO ("[node " << GetNode ()->GetId () << "] " << "Error while sending DHCP REQ to " << m_remoteAddress); | |
354 } | |
355 m_state = WAIT_ACK; | |
356 } | |
357 } | |
358 | |
359 void DhcpClient::AcceptAck (DhcpHeader header, Address from) | |
360 { | |
361 Simulator::Remove (m_rebindEvent); | |
362 Simulator::Remove (m_refreshEvent); | |
363 Simulator::Remove (m_timeout); | |
364 NS_LOG_INFO ("[node " << GetNode ()->GetId () << "] " << "Trace TX: DHCP ACK RECEIVED"); | |
365 Ptr<Ipv4> ipv4 = GetNode ()->GetObject<Ipv4> (); | |
366 int32_t ifIndex = ipv4->GetInterfaceForDevice (GetNode ()->GetDevice (device)) ; | |
367 | |
368 for (uint32_t i = 0; i < ipv4->GetNAddresses (ifIndex); i++) | |
369 { | |
370 if (ipv4->GetAddress (ifIndex,i).GetLocal () == m_myAddress) | |
371 { | |
372 ipv4->RemoveAddress (ifIndex, i); | |
373 break; | |
374 } | |
375 } | |
376 | |
377 ipv4->AddAddress (ifIndex, Ipv4InterfaceAddress ((Ipv4Address)m_offeredAddress , m_myMask)); | |
378 ipv4->SetUp (ifIndex); | |
379 | |
380 InetSocketAddress remote = InetSocketAddress (InetSocketAddress::ConvertFrom ( from).GetIpv4 (), DHCP_PEER_PORT); | |
381 m_socket->Connect (remote); | |
382 if (m_myAddress != m_offeredAddress) | |
383 { | |
384 m_newLease (m_offeredAddress); | |
385 if (m_myAddress != Ipv4Address("0.0.0.0")); | |
386 { | |
387 m_expiry (m_myAddress); | |
388 } | |
389 } | |
390 m_myAddress = m_offeredAddress; | |
391 Ipv4StaticRoutingHelper ipv4RoutingHelper; | |
392 Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting (ipv 4); | |
393 if (m_gateway == Ipv4Address ()) | |
394 { | |
395 m_gateway = InetSocketAddress::ConvertFrom (from).GetIpv4 (); | |
396 } | |
397 | |
398 staticRouting->SetDefaultRoute (m_gateway, ifIndex, 0); | |
399 | |
400 m_remoteAddress = InetSocketAddress::ConvertFrom (from).GetIpv4 (); | |
401 NS_LOG_INFO ("[node " << GetNode ()->GetId () << "] " << "Current DHCP Server is =" << m_remoteAddress); | |
402 | |
403 m_offerList.clear (); | |
404 m_refreshEvent = Simulator::Schedule (m_renew, &DhcpClient::Request, this); | |
405 m_rebindEvent = Simulator::Schedule (m_rebind, &DhcpClient::Request, this); | |
406 m_timeout = Simulator::Schedule (m_lease, &DhcpClient::Boot, this); | |
407 m_state = REFRESH_LEASE; | |
408 } | |
409 | |
410 } // Namespace ns3 | |
OLD | NEW |