1+ #include " ip_analyzer.hh"
2+ #include < bitset>
3+ #include < stdexcept>
4+ #include < sstream>
5+ #include < algorithm>
6+
7+ IPv4Address::IPv4Address (std::string_view address)
8+ {
9+ std::istringstream iss (address.data ());
10+ std::string octet;
11+ size_t i = 0 ;
12+ while (std::getline (iss, octet, ' .' ))
13+ {
14+ if (i >= 4 )
15+ throw std::invalid_argument (" Invalid IP address format: too many octets" );
16+ int value = std::stoi (octet);
17+ if (value < 0 || value > 255 )
18+ throw std::invalid_argument (" Invalid IP address octet value" );
19+ octets_[i++] = static_cast <uint8_t >(value);
20+ }
21+ if (i != 4 )
22+ throw std::invalid_argument (" Invalid IP address format: not enough octets" );
23+ }
24+
25+ IPv4Address::IPv4Address (uint32_t address)
26+ {
27+ octets_[0 ] = static_cast <uint8_t >((address >> 24 ) & 0xFF );
28+ octets_[1 ] = static_cast <uint8_t >((address >> 16 ) & 0xFF );
29+ octets_[2 ] = static_cast <uint8_t >((address >> 8 ) & 0xFF );
30+ octets_[3 ] = static_cast <uint8_t >(address & 0xFF );
31+ }
32+
33+ std::string IPv4Address::to_string () const
34+ {
35+ std::ostringstream oss;
36+ oss << static_cast <int >(octets_[0 ]) << ' .'
37+ << static_cast <int >(octets_[1 ]) << ' .'
38+ << static_cast <int >(octets_[2 ]) << ' .'
39+ << static_cast <int >(octets_[3 ]);
40+ return oss.str ();
41+ }
42+
43+ std::string IPv4Address::to_binary_string () const
44+ {
45+ std::ostringstream oss;
46+ for (auto octet : octets_)
47+ {
48+ oss << std::bitset<8 >(octet).to_string ();
49+ }
50+ return oss.str ();
51+ }
52+
53+ uint32_t IPv4Address::to_uint32 () const
54+ {
55+ return (octets_[0 ] << 24 ) | (octets_[1 ] << 16 ) | (octets_[2 ] << 8 ) | octets_[3 ];
56+ }
57+
58+ IPAnalyzer::IPAnalyzer (std::string_view ip_cidr) : ip_(ip_cidr.substr(0 , ip_cidr.find(' /' )))
59+ {
60+ auto slash_pos = ip_cidr.find (' /' );
61+ if (slash_pos == std::string_view::npos)
62+ throw std::invalid_argument (" Invalid IP/CIDR format" );
63+ cidr_ = static_cast <uint8_t >(std::stoi (std::string (ip_cidr.substr (slash_pos + 1 ))));
64+ if (cidr_ > 32 )
65+ throw std::invalid_argument (" Invalid CIDR value" );
66+ }
67+
68+ IPv4Address IPAnalyzer::get_ip () const { return ip_; }
69+
70+ IPv4Address IPAnalyzer::get_network () const
71+ {
72+ if (cidr_ == 0 )
73+ return IPv4Address (" 0.0.0.0" );
74+ uint32_t ip = ip_.to_uint32 ();
75+ uint32_t mask = (cidr_ == 32 ) ? 0xFFFFFFFF : ~(0xFFFFFFFF >> cidr_);
76+ return IPv4Address (ip & mask);
77+ }
78+
79+ IPv4Address IPAnalyzer::get_netmask () const
80+ {
81+ if (cidr_ == 32 )
82+ return IPv4Address (" 255.255.255.255" );
83+ uint32_t mask = (cidr_ == 0 ) ? 0 : (~0U << (32 - cidr_));
84+ return IPv4Address (mask);
85+ }
86+
87+ IPv4Address IPAnalyzer::get_broadcast () const
88+ {
89+ if (cidr_ == 32 )
90+ return ip_;
91+ if (cidr_ == 0 )
92+ return IPv4Address (" 255.255.255.255" );
93+ uint32_t ip_int = ip_.to_uint32 ();
94+ uint32_t mask = (~0U << (32 - cidr_));
95+ return IPv4Address (ip_int | ~mask);
96+ }
97+
98+ std::pair<IPv4Address, IPv4Address> IPAnalyzer::get_host_range () const
99+ {
100+ if (cidr_ == 32 )
101+ return {ip_, ip_};
102+ uint32_t network_int = get_network ().to_uint32 ();
103+ uint32_t broadcast_int = get_broadcast ().to_uint32 ();
104+ return {IPv4Address (network_int + 1 ), IPv4Address (broadcast_int - 1 )};
105+ }
106+
107+ uint32_t IPAnalyzer::get_num_hosts () const
108+ {
109+ if (cidr_ == 32 )
110+ return 1 ;
111+ if (cidr_ == 31 )
112+ return 2 ;
113+ if (cidr_ == 0 )
114+ return 0xFFFFFFFE ;
115+ return (1ULL << (32 - cidr_)) - 2 ;
116+ }
117+
118+ bool IPAnalyzer::is_private () const
119+ {
120+ uint32_t ip = ip_.to_uint32 ();
121+ return (ip >= 0x0A000000 && ip <= 0x0AFFFFFF ) ||
122+ (ip >= 0xAC100000 && ip <= 0xAC1FFFFF ) ||
123+ (ip >= 0xC0A80000 && ip <= 0xC0A8FFFF );
124+ }
125+
126+ uint8_t IPAnalyzer::get_cidr () const { return cidr_; }
0 commit comments