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