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 #include "ns3/assert.h"
26 #include "ns3/log.h"
27 #include "ns3/simulator.h"
28 #include "ns3/address-utils.h"
29 #include "dhcp-header.h"
30
31 namespace ns3 {
32
33 NS_LOG_COMPONENT_DEFINE ("DhcpHeader");
34 NS_OBJECT_ENSURE_REGISTERED (DhcpHeader);
35
DhcpHeader()36 DhcpHeader::DhcpHeader ()
37 {
38 m_hType = 1;
39 m_hLen = 6;
40 m_xid = 0;
41 m_secs = 0;
42 m_hops = 0;
43 m_flags = 0;
44 Ipv4Address addr = Ipv4Address ("0.0.0.0");
45 m_yiAddr = addr;
46 m_ciAddr = addr;
47 m_siAddr = addr;
48 m_giAddr = addr;
49 m_dhcps = addr;
50 m_req = addr;
51 m_route = addr;
52 m_len = 240;
53
54 uint32_t i;
55
56 for (i = 0; i < 64; i++)
57 {
58 m_sname[i] = 0;
59 }
60 for (i = 0; i < 128; i++)
61 {
62 m_file[i] = 0;
63 }
64 m_magic_cookie[0] = 99;
65 m_magic_cookie[1] = 130;
66 m_magic_cookie[2] = 83;
67 m_magic_cookie[3] = 99;
68 }
69
~DhcpHeader()70 DhcpHeader::~DhcpHeader ()
71 {
72 }
73
SetType(uint8_t type)74 void DhcpHeader::SetType (uint8_t type)
75 {
76 if (m_opt[OP_MSGTYPE] == false)
77 {
78 m_len += 3;
79 m_opt[OP_MSGTYPE] = true;
80 }
81 m_op = type;
82 m_bootp = (m_op == 0||m_op == 2) ? 1 : 2;
83 }
84
GetType(void) const85 uint8_t DhcpHeader::GetType (void) const
86 {
87 return m_op;
88 }
89
SetHWType(uint8_t htype,uint8_t hlen)90 void DhcpHeader::SetHWType (uint8_t htype, uint8_t hlen)
91 {
92 m_hType = htype;
93 m_hLen = hlen;
94 }
95
SetTran(uint32_t tran)96 void DhcpHeader::SetTran (uint32_t tran)
97 {
98 m_xid = tran;
99 }
100
GetTran(void) const101 uint32_t DhcpHeader::GetTran (void) const
102 {
103 return m_xid;
104 }
105
SetTime()106 void DhcpHeader::SetTime ()
107 {
108 m_secs = (uint16_t) Simulator::Now ().GetSeconds ();
109 }
110
SetChaddr(Address addr)111 void DhcpHeader::SetChaddr (Address addr)
112 {
113 std::memset (m_chaddr, 0, 16);
114 NS_ASSERT_MSG (addr.GetLength () <= 16, "Address length too big");
115 addr.CopyTo (m_chaddr);
116 }
117
SetChaddr(uint8_t * addr,uint8_t len)118 void DhcpHeader::SetChaddr (uint8_t* addr, uint8_t len)
119 {
120 std::memset (m_chaddr, 0, 16);
121 NS_ASSERT_MSG (len <= 16, "Address length too big");
122 std::memcpy (m_chaddr, addr, len);
123 }
124
GetChaddr()125 Address DhcpHeader::GetChaddr ()
126 {
127 Address addr;
128 addr.CopyFrom (m_chaddr, 16);
129 return addr;
130 }
131
SetYiaddr(Ipv4Address addr)132 void DhcpHeader::SetYiaddr (Ipv4Address addr)
133 {
134 m_yiAddr = addr;
135 }
136
GetYiaddr(void) const137 Ipv4Address DhcpHeader::GetYiaddr (void) const
138 {
139 return m_yiAddr;
140 }
141
SetDhcps(Ipv4Address addr)142 void DhcpHeader::SetDhcps (Ipv4Address addr)
143 {
144 if (m_opt[OP_SERVID] == false)
145 {
146 m_len += 6;
147 m_opt[OP_SERVID] = true;
148 }
149 m_dhcps = addr;
150 }
151
GetDhcps(void) const152 Ipv4Address DhcpHeader::GetDhcps (void) const
153 {
154 return m_dhcps;
155 }
156
SetReq(Ipv4Address addr)157 void DhcpHeader::SetReq (Ipv4Address addr)
158 {
159 if (m_opt[OP_ADDREQ] == false)
160 {
161 m_len += 6;
162 m_opt[OP_ADDREQ] = true;
163 }
164 m_req = addr;
165 }
166
GetReq(void) const167 Ipv4Address DhcpHeader::GetReq (void) const
168 {
169 return m_req;
170 }
171
SetMask(uint32_t addr)172 void DhcpHeader::SetMask (uint32_t addr)
173 {
174 if (m_opt[OP_MASK] == false)
175 {
176 m_len += 6;
177 m_opt[OP_MASK] = true;
178 }
179 m_mask = addr;
180 }
181
GetMask(void) const182 uint32_t DhcpHeader::GetMask (void) const
183 {
184 return m_mask;
185 }
186
SetRouter(Ipv4Address addr)187 void DhcpHeader::SetRouter (Ipv4Address addr)
188 {
189 if (m_opt[OP_ROUTE] == false)
190 {
191 m_len += 6;
192 m_opt[OP_ROUTE] = true;
193 }
194 m_route = addr;
195 }
196
GetRouter(void) const197 Ipv4Address DhcpHeader::GetRouter (void) const
198 {
199 return m_route;
200 }
201
SetLease(uint32_t time)202 void DhcpHeader::SetLease (uint32_t time)
203 {
204 if (m_opt[OP_LEASE] == false)
205 {
206 m_len += 6;
207 m_opt[OP_LEASE] = true;
208 }
209 m_lease = time;
210 }
211
GetLease(void) const212 uint32_t DhcpHeader::GetLease (void) const
213 {
214 return m_lease;
215 }
216
SetRenew(uint32_t time)217 void DhcpHeader::SetRenew (uint32_t time)
218 {
219 if (m_opt[OP_RENEW] == false)
220 {
221 m_len += 6;
222 m_opt[OP_RENEW] = true;
223 }
224 m_renew = time;
225 }
226
GetRenew(void) const227 uint32_t DhcpHeader::GetRenew (void) const
228 {
229 return m_renew;
230 }
231
SetRebind(uint32_t time)232 void DhcpHeader::SetRebind (uint32_t time)
233 {
234 if (m_opt[OP_REBIND] == false)
235 {
236 m_len += 6;
237 m_opt[OP_REBIND] = true;
238 }
239 m_rebind = time;
240 }
241
GetRebind(void) const242 uint32_t DhcpHeader::GetRebind (void) const
243 {
244 return m_rebind;
245 }
246
ResetOpt()247 void DhcpHeader::ResetOpt ()
248 {
249 m_len = 241;
250 int i;
251 for (i = 0; i < OP_END; i++)
252 {
253 m_opt[i] = false;
254 }
255 }
256
GetSerializedSize(void) const257 uint32_t DhcpHeader::GetSerializedSize (void) const
258 {
259 return m_len;
260 }
261
GetTypeId(void)262 TypeId DhcpHeader::GetTypeId (void)
263 {
264 static TypeId tid = TypeId ("ns3::DhcpHeader")
265 .SetParent<Header> ()
266 .SetGroupName ("Internet-Apps")
267 .AddConstructor<DhcpHeader> ()
268 ;
269 return tid;
270 }
271
GetInstanceTypeId(void) const272 TypeId DhcpHeader::GetInstanceTypeId (void) const
273 {
274 return GetTypeId ();
275 }
276
Print(std::ostream & os) const277 void DhcpHeader::Print (std::ostream &os) const
278 {
279 os << "(type=" << m_op << ")";
280 }
281
282 void
Serialize(Buffer::Iterator start) const283 DhcpHeader::Serialize (Buffer::Iterator start) const
284 {
285 Buffer::Iterator i = start;
286 i.WriteU8 (m_bootp);
287 i.WriteU8 (m_hType);
288 i.WriteU8 (m_hLen);
289 i.WriteU8 (m_hops);
290 i.WriteU32 (m_xid);
291 i.WriteHtonU16 (m_secs);
292 i.WriteU16 ( m_flags);
293 WriteTo (i, m_ciAddr);
294 WriteTo (i, m_yiAddr);
295 WriteTo (i, m_siAddr);
296 WriteTo (i, m_giAddr);
297 i.Write (m_chaddr, 16);
298 i.Write (m_sname,64);
299 i.Write (m_file,128);
300 i.Write (m_magic_cookie,4);
301 if (m_opt[OP_MASK])
302 {
303 i.WriteU8 (OP_MASK);
304 i.WriteU8 (4);
305 i.WriteHtonU32 (m_mask);
306 }
307 if (m_opt[OP_MSGTYPE])
308 {
309 i.WriteU8 (OP_MSGTYPE);
310 i.WriteU8 (1);
311 i.WriteU8 ((m_op + 1));
312 }
313 if (m_opt[OP_ADDREQ])
314 {
315 i.WriteU8 (OP_ADDREQ);
316 i.WriteU8 (4);
317 WriteTo (i, m_req);
318 }
319 if (m_opt[OP_SERVID])
320 {
321 i.WriteU8 (OP_SERVID);
322 i.WriteU8 (4);
323 WriteTo (i, m_dhcps);
324 }
325 if (m_opt[OP_ROUTE])
326 {
327 i.WriteU8 (OP_ROUTE);
328 i.WriteU8 (4);
329 WriteTo (i, m_route);
330 }
331 if (m_opt[OP_LEASE])
332 {
333 i.WriteU8 (OP_LEASE);
334 i.WriteU8 (4);
335 i.WriteHtonU32 (m_lease);
336 }
337 if (m_opt[OP_RENEW])
338 {
339 i.WriteU8 (OP_RENEW);
340 i.WriteU8 (4);
341 i.WriteHtonU32 (m_renew);
342 }
343 if (m_opt[OP_REBIND])
344 {
345 i.WriteU8 (OP_REBIND);
346 i.WriteU8 (4);
347 i.WriteHtonU32 (m_rebind);
348 }
349 i.WriteU8 (OP_END);
350 }
351
Deserialize(Buffer::Iterator start)352 uint32_t DhcpHeader::Deserialize (Buffer::Iterator start)
353 {
354 uint32_t len, clen = start.GetSize ();
355 if (clen < 240)
356 {
357 NS_LOG_WARN ("Malformed Packet");
358 return 0;
359 }
360 Buffer::Iterator i = start;
361 m_bootp = i.ReadU8 ();
362 m_hType = i.ReadU8 ();
363 m_hLen = i.ReadU8 ();
364 m_hops = i.ReadU8 ();
365 m_xid = i.ReadU32 ();
366 m_secs = i.ReadNtohU16 ();
367 m_flags = i.ReadU16 ();
368 ReadFrom (i, m_ciAddr);
369 ReadFrom (i, m_yiAddr);
370 ReadFrom (i, m_siAddr);
371 ReadFrom (i, m_giAddr);
372 i.Read (m_chaddr, 16);
373 i.Read (m_sname, 64);
374 i.Read (m_file, 128);
375 i.Read (m_magic_cookie, 4);
376 if ( m_magic_cookie[0] != 99 || m_magic_cookie[1] != 130 || m_magic_cookie[2] != 83 || m_magic_cookie[3] != 99)
377 {
378 NS_LOG_WARN ("Malformed Packet");
379 return 0;
380 }
381 len = 240;
382 uint8_t option;
383 bool loop = true;
384 do
385 {
386 if (len + 1 <= clen)
387 {
388 option = i.ReadU8 ();
389 len += 1;
390 }
391 else
392 {
393 NS_LOG_WARN ("Malformed Packet");
394 return 0;
395 }
396 switch (option)
397 {
398 case OP_MASK:
399 if (len + 5 < clen)
400 {
401 i.ReadU8 ();
402 m_mask = i.ReadNtohU32 ();
403 len += 5;
404 }
405 else
406 {
407 NS_LOG_WARN ("Malformed Packet");
408 return 0;
409 }
410 break;
411 case OP_ROUTE:
412 if (len + 5 < clen)
413 {
414 i.ReadU8 ();
415 ReadFrom (i, m_route);
416 len += 5;
417 }
418 else
419 {
420 NS_LOG_WARN ("Malformed Packet");
421 return 0;
422 }
423 break;
424 case OP_MSGTYPE:
425 if (len + 2 < clen)
426 {
427 i.ReadU8 ();
428 m_op = (i.ReadU8 () - 1);
429 len += 2;
430 }
431 else
432 {
433 NS_LOG_WARN ("Malformed Packet");
434 return 0;
435 }
436 break;
437 case OP_SERVID:
438 if (len + 5 < clen)
439 {
440 i.ReadU8 ();
441 ReadFrom (i, m_dhcps);
442 len += 5;
443 }
444 else
445 {
446 NS_LOG_WARN ("Malformed Packet");
447 return 0;
448 }
449 break;
450 case OP_ADDREQ:
451 if (len + 5 < clen)
452 {
453 i.ReadU8 ();
454 ReadFrom (i, m_req);
455 len += 5;
456 }
457 else
458 {
459 NS_LOG_WARN ("Malformed Packet");
460 return 0;
461 }
462 break;
463 case OP_LEASE:
464 if (len + 5 < clen)
465 {
466 i.ReadU8 ();
467 m_lease = i.ReadNtohU32 ();
468 len += 5;
469 }
470 else
471 {
472 NS_LOG_WARN ("Malformed Packet");
473 return 0;
474 }
475 break;
476 case OP_RENEW:
477 if (len + 5 < clen)
478 {
479 i.ReadU8 ();
480 m_renew = i.ReadNtohU32 ();
481 len += 5;
482 }
483 else
484 {
485 NS_LOG_WARN ("Malformed Packet");
486 return 0;
487 }
488 break;
489 case OP_REBIND:
490 if (len + 5 < clen)
491 {
492 i.ReadU8 ();
493 m_rebind = i.ReadNtohU32 ();
494 len += 5;
495 }
496 else
497 {
498 NS_LOG_WARN ("Malformed Packet");
499 return 0;
500 }
501 break;
502 case OP_END:
503 loop = false;
504 break;
505 default:
506 NS_LOG_WARN ("Malformed Packet");
507 return 0;
508 }
509 }
510 while (loop);
511
512 m_len = len;
513 return m_len;
514 }
515
516 } // namespace ns3
517