1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include <cstdlib>
22 #include "ns3/log.h"
23 #include "ipv4-address.h"
24 #include "ns3/assert.h"
25 
26 namespace ns3 {
27 
28 NS_LOG_COMPONENT_DEFINE ("Ipv4Address");
29 
30 #define ASCII_DOT (0x2e)
31 #define ASCII_ZERO (0x30)
32 #define ASCII_SLASH (0x2f)
33 
34 /**
35  * \brief Converts a string representing an IP address into the address
36  * \param address the address string
37  * \returns the address
38  */
39 static uint32_t
AsciiToIpv4Host(char const * address)40 AsciiToIpv4Host (char const *address)
41 {
42   NS_LOG_FUNCTION (&address);
43   uint32_t host = 0;
44   uint8_t numberOfDots = 0;
45   char const *ptr = address;
46 
47   NS_ASSERT_MSG (*ptr != ASCII_DOT, "Error, can not build an IPv4 address from an invalid string: " << address);
48   while (true)
49     {
50       uint8_t byte = 0;
51       while (*ptr != ASCII_DOT && *ptr != 0)
52         {
53           byte *= 10;
54           byte += *ptr - ASCII_ZERO;
55           ptr++;
56         }
57       host <<= 8;
58       host |= byte;
59       if (*ptr == 0)
60         {
61           break;
62         }
63       ptr++;
64       NS_ASSERT_MSG (*ptr != ASCII_DOT, "Error, can not build an IPv4 address from an invalid string: " << address);
65       numberOfDots ++;
66     }
67   NS_ASSERT_MSG (*(ptr-1) != ASCII_DOT, "Error, can not build an IPv4 address from an invalid string: " << address);
68   NS_ASSERT_MSG (numberOfDots == 3, "Error, can not build an IPv4 address from an invalid string: " << address);
69 
70   return host;
71 }
72 
73 } // namespace ns3
74 
75 namespace ns3 {
76 
77 
Ipv4Mask()78 Ipv4Mask::Ipv4Mask ()
79   : m_mask (0x66666666)
80 {
81   NS_LOG_FUNCTION (this);
82 }
83 
Ipv4Mask(uint32_t mask)84 Ipv4Mask::Ipv4Mask (uint32_t mask)
85   : m_mask (mask)
86 {
87   NS_LOG_FUNCTION (this << mask);
88 }
89 
Ipv4Mask(char const * mask)90 Ipv4Mask::Ipv4Mask (char const *mask)
91 {
92   NS_LOG_FUNCTION (this << mask);
93   if (*mask == ASCII_SLASH)
94     {
95       uint32_t plen = static_cast<uint32_t> (std::atoi (++mask));
96       NS_ASSERT (plen <= 32);
97       if (plen > 0)
98         {
99           m_mask = 0xffffffff << (32 - plen);
100         }
101       else
102         {
103           m_mask = 0;
104         }
105     }
106   else
107     {
108       m_mask = AsciiToIpv4Host (mask);
109     }
110 }
111 
112 bool
IsMatch(Ipv4Address a,Ipv4Address b) const113 Ipv4Mask::IsMatch (Ipv4Address a, Ipv4Address b) const
114 {
115   NS_LOG_FUNCTION (this << a << b);
116   if ((a.Get () & m_mask) == (b.Get () & m_mask)) {
117       return true;
118     } else {
119       return false;
120     }
121 }
122 
123 uint32_t
Get(void) const124 Ipv4Mask::Get (void) const
125 {
126   NS_LOG_FUNCTION (this);
127   return m_mask;
128 }
129 void
Set(uint32_t mask)130 Ipv4Mask::Set (uint32_t mask)
131 {
132   NS_LOG_FUNCTION (this << mask);
133   m_mask = mask;
134 }
135 uint32_t
GetInverse(void) const136 Ipv4Mask::GetInverse (void) const
137 {
138   NS_LOG_FUNCTION (this);
139   return ~m_mask;
140 }
141 
142 void
Print(std::ostream & os) const143 Ipv4Mask::Print (std::ostream &os) const
144 {
145   NS_LOG_FUNCTION (this << &os);
146   os << ((m_mask >> 24) & 0xff) << "."
147      << ((m_mask >> 16) & 0xff) << "."
148      << ((m_mask >> 8) & 0xff) << "."
149      << ((m_mask >> 0) & 0xff);
150 }
151 
152 
153 Ipv4Mask
GetLoopback(void)154 Ipv4Mask::GetLoopback (void)
155 {
156   NS_LOG_FUNCTION_NOARGS ();
157   static Ipv4Mask loopback = Ipv4Mask ("255.0.0.0");
158   return loopback;
159 }
160 Ipv4Mask
GetZero(void)161 Ipv4Mask::GetZero (void)
162 {
163   NS_LOG_FUNCTION_NOARGS ();
164   static Ipv4Mask zero = Ipv4Mask ("0.0.0.0");
165   return zero;
166 }
167 Ipv4Mask
GetOnes(void)168 Ipv4Mask::GetOnes (void)
169 {
170   NS_LOG_FUNCTION_NOARGS ();
171   static Ipv4Mask ones = Ipv4Mask ("255.255.255.255");
172   return ones;
173 }
174 
175 uint16_t
GetPrefixLength(void) const176 Ipv4Mask::GetPrefixLength (void) const
177 {
178   NS_LOG_FUNCTION (this);
179   uint16_t tmp = 0;
180   uint32_t mask = m_mask;
181   while (mask != 0 )
182     {
183       mask = mask << 1;
184       tmp++;
185     }
186   return tmp;
187 }
188 
189 /**
190  *  Value of a not-yet-initialized IPv4 address, corresponding to 102.102.102.102.
191  *  This is totally arbitrary.
192  */
193 static constexpr uint32_t UNINITIALIZED = 0x66666666U;
194 
Ipv4Address()195 Ipv4Address::Ipv4Address ()
196   : m_address (UNINITIALIZED), m_initialized (false)
197 {
198   NS_LOG_FUNCTION (this);
199 }
Ipv4Address(uint32_t address)200 Ipv4Address::Ipv4Address (uint32_t address)
201 {
202   NS_LOG_FUNCTION (this << address);
203   m_address = address;
204   m_initialized = true;
205 }
Ipv4Address(char const * address)206 Ipv4Address::Ipv4Address (char const *address)
207 {
208   NS_LOG_FUNCTION (this << address);
209   m_address = AsciiToIpv4Host (address);
210   m_initialized = true;
211 }
212 
213 uint32_t
Get(void) const214 Ipv4Address::Get (void) const
215 {
216   NS_LOG_FUNCTION (this);
217   return m_address;
218 }
219 void
Set(uint32_t address)220 Ipv4Address::Set (uint32_t address)
221 {
222   NS_LOG_FUNCTION (this << address);
223   m_address = address;
224   m_initialized = true;
225 }
226 void
Set(char const * address)227 Ipv4Address::Set (char const *address)
228 {
229   NS_LOG_FUNCTION (this << address);
230   m_address = AsciiToIpv4Host (address);
231   m_initialized = true;
232 }
233 
234 Ipv4Address
CombineMask(Ipv4Mask const & mask) const235 Ipv4Address::CombineMask (Ipv4Mask const &mask) const
236 {
237   NS_LOG_FUNCTION (this << mask);
238   return Ipv4Address (Get () & mask.Get ());
239 }
240 
241 Ipv4Address
GetSubnetDirectedBroadcast(Ipv4Mask const & mask) const242 Ipv4Address::GetSubnetDirectedBroadcast (Ipv4Mask const &mask) const
243 {
244   NS_LOG_FUNCTION (this << mask);
245   if (mask == Ipv4Mask::GetOnes ())
246     {
247       NS_ASSERT_MSG (false, "Trying to get subnet-directed broadcast address with an all-ones netmask");
248     }
249   return Ipv4Address (Get () | mask.GetInverse ());
250 }
251 
252 bool
IsSubnetDirectedBroadcast(Ipv4Mask const & mask) const253 Ipv4Address::IsSubnetDirectedBroadcast (Ipv4Mask const &mask) const
254 {
255   NS_LOG_FUNCTION (this << mask);
256   if (mask == Ipv4Mask::GetOnes ())
257     {
258       // If the mask is 255.255.255.255, there is no subnet directed
259       // broadcast for this address.
260       return false;
261     }
262   return ( (Get () | mask.GetInverse ()) == Get () );
263 }
264 
265 bool
IsInitialized(void) const266 Ipv4Address::IsInitialized (void) const
267 {
268   NS_LOG_FUNCTION (this);
269   return (m_initialized);
270 }
271 
272 bool
IsAny(void) const273 Ipv4Address::IsAny (void) const
274 {
275   NS_LOG_FUNCTION (this);
276   return (m_address == 0x00000000U);
277 }
278 
279 bool
IsLocalhost(void) const280 Ipv4Address::IsLocalhost (void) const
281 {
282   NS_LOG_FUNCTION (this);
283   return (m_address == 0x7f000001U);
284 }
285 
286 bool
IsBroadcast(void) const287 Ipv4Address::IsBroadcast (void) const
288 {
289   NS_LOG_FUNCTION (this);
290   return (m_address == 0xffffffffU);
291 }
292 
293 bool
IsMulticast(void) const294 Ipv4Address::IsMulticast (void) const
295 {
296 //
297 // Multicast addresses are defined as ranging from 224.0.0.0 through
298 // 239.255.255.255 (which is E0000000 through EFFFFFFF in hex).
299 //
300   NS_LOG_FUNCTION (this);
301   return (m_address >= 0xe0000000 && m_address <= 0xefffffff);
302 }
303 
304 bool
IsLocalMulticast(void) const305 Ipv4Address::IsLocalMulticast (void) const
306 {
307   NS_LOG_FUNCTION (this);
308   // Link-Local multicast address is 224.0.0.0/24
309   return (m_address & 0xffffff00) == 0xe0000000;
310 }
311 
312 void
Serialize(uint8_t buf[4]) const313 Ipv4Address::Serialize (uint8_t buf[4]) const
314 {
315   NS_LOG_FUNCTION (this << &buf);
316   buf[0] = (m_address >> 24) & 0xff;
317   buf[1] = (m_address >> 16) & 0xff;
318   buf[2] = (m_address >> 8) & 0xff;
319   buf[3] = (m_address >> 0) & 0xff;
320 }
321 Ipv4Address
Deserialize(const uint8_t buf[4])322 Ipv4Address::Deserialize (const uint8_t buf[4])
323 {
324   NS_LOG_FUNCTION (&buf);
325   Ipv4Address ipv4;
326   ipv4.m_address = 0;
327   ipv4.m_address |= buf[0];
328   ipv4.m_address <<= 8;
329   ipv4.m_address |= buf[1];
330   ipv4.m_address <<= 8;
331   ipv4.m_address |= buf[2];
332   ipv4.m_address <<= 8;
333   ipv4.m_address |= buf[3];
334   ipv4.m_initialized = true;
335 
336   return ipv4;
337 }
338 
339 void
Print(std::ostream & os) const340 Ipv4Address::Print (std::ostream &os) const
341 {
342   NS_LOG_FUNCTION (this);
343   os << ((m_address >> 24) & 0xff) << "."
344      << ((m_address >> 16) & 0xff) << "."
345      << ((m_address >> 8) & 0xff) << "."
346      << ((m_address >> 0) & 0xff);
347 }
348 
349 bool
IsMatchingType(const Address & address)350 Ipv4Address::IsMatchingType (const Address &address)
351 {
352   NS_LOG_FUNCTION (&address);
353   return address.CheckCompatible (GetType (), 4);
354 }
operator Address() const355 Ipv4Address::operator Address () const
356 {
357   return ConvertTo ();
358 }
359 
360 Address
ConvertTo(void) const361 Ipv4Address::ConvertTo (void) const
362 {
363   NS_LOG_FUNCTION (this);
364   uint8_t buf[4];
365   Serialize (buf);
366   return Address (GetType (), buf, 4);
367 }
368 
369 Ipv4Address
ConvertFrom(const Address & address)370 Ipv4Address::ConvertFrom (const Address &address)
371 {
372   NS_LOG_FUNCTION (&address);
373   NS_ASSERT (address.CheckCompatible (GetType (), 4));
374   uint8_t buf[4];
375   address.CopyTo (buf);
376   return Deserialize (buf);
377 }
378 
379 uint8_t
GetType(void)380 Ipv4Address::GetType (void)
381 {
382   NS_LOG_FUNCTION_NOARGS ();
383   static uint8_t type = Address::Register ();
384   return type;
385 }
386 
387 Ipv4Address
GetZero(void)388 Ipv4Address::GetZero (void)
389 {
390   NS_LOG_FUNCTION_NOARGS ();
391   static Ipv4Address zero ("0.0.0.0");
392   return zero;
393 }
394 Ipv4Address
GetAny(void)395 Ipv4Address::GetAny (void)
396 {
397   NS_LOG_FUNCTION_NOARGS ();
398   static Ipv4Address any ("0.0.0.0");
399   return any;
400 }
401 Ipv4Address
GetBroadcast(void)402 Ipv4Address::GetBroadcast (void)
403 {
404   NS_LOG_FUNCTION_NOARGS ();
405   static Ipv4Address broadcast ("255.255.255.255");
406   return broadcast;
407 }
408 Ipv4Address
GetLoopback(void)409 Ipv4Address::GetLoopback (void)
410 {
411   NS_LOG_FUNCTION_NOARGS ();
412   Ipv4Address loopback ("127.0.0.1");
413   return loopback;
414 }
415 
operator ()(Ipv4Address const & x) const416 size_t Ipv4AddressHash::operator() (Ipv4Address const &x) const
417 {
418   return std::hash<uint32_t>()(x.Get ());
419 }
420 
operator <<(std::ostream & os,Ipv4Address const & address)421 std::ostream& operator<< (std::ostream& os, Ipv4Address const& address)
422 {
423   address.Print (os);
424   return os;
425 }
operator <<(std::ostream & os,Ipv4Mask const & mask)426 std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask)
427 {
428   mask.Print (os);
429   return os;
430 }
operator >>(std::istream & is,Ipv4Address & address)431 std::istream & operator >> (std::istream &is, Ipv4Address &address)
432 {
433   std::string str;
434   is >> str;
435   address = Ipv4Address (str.c_str ());
436   return is;
437 }
operator >>(std::istream & is,Ipv4Mask & mask)438 std::istream & operator >> (std::istream &is, Ipv4Mask &mask)
439 {
440   std::string str;
441   is >> str;
442   mask = Ipv4Mask (str.c_str ());
443   return is;
444 }
445 
446 ATTRIBUTE_HELPER_CPP (Ipv4Address);
447 ATTRIBUTE_HELPER_CPP (Ipv4Mask);
448 
449 } // namespace ns3
450