Skip to content

Commit a702fa0

Browse files
committed
First commit
0 parents  commit a702fa0

8 files changed

Lines changed: 523 additions & 0 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.vscode/
2+
build/

CMakeLists.txt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
cmake_minimum_required(VERSION 3.22)
2+
project(ip-analyzer VERSION 1.0.0 LANGUAGES CXX)
3+
4+
set(CMAKE_CXX_STANDARD 26)
5+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6+
set(CMAKE_CXX_EXTENSIONS OFF)
7+
8+
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CPM.cmake")
9+
message(STATUS "Downloading CPM.cmake")
10+
file(DOWNLOAD
11+
"https://github.com/cpm-cmake/CPM.cmake/releases/download/v0.40.2/CPM.cmake"
12+
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/CPM.cmake"
13+
EXPECTED_HASH SHA256=c8cdc32c03816538ce22781ed72964dc864b2a34a310d3b7104812a5ca2d835d
14+
TLS_VERIFY ON)
15+
endif()
16+
17+
include(cmake/CPM.cmake)
18+
CPMAddPackage("gh:catchorg/Catch2@3.3.2")
19+
20+
CPMAddPackage(
21+
NAME fmt
22+
GITHUB_REPOSITORY fmtlib/fmt
23+
GIT_TAG 9.1.0
24+
)
25+
26+
add_executable(ip-analyzer src/main.cc src/ip_analyzer.cc)
27+
target_include_directories(ip-analyzer PRIVATE src)
28+
target_link_libraries(ip-analyzer PRIVATE fmt::fmt)
29+
30+
if(CMAKE_BUILD_TYPE STREQUAL "Release")
31+
target_compile_options(ip-analyzer PRIVATE -O3 -march=native -mtune=native)
32+
endif()
33+
34+
enable_testing()
35+
add_executable(ip_analyzer_tests tests/ip_analyzer_tests.cc src/ip_analyzer.cc)
36+
target_link_libraries(ip_analyzer_tests PRIVATE Catch2::Catch2WithMain fmt::fmt)
37+
target_include_directories(ip_analyzer_tests PRIVATE src)
38+
39+
include(CTest)
40+
41+
list(APPEND CMAKE_MODULE_PATH ${Catch2_SOURCE_DIR}/extras)
42+
include(Catch)
43+
catch_discover_tests(ip_analyzer_tests)

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Volker Schwaberow <volker@schwaberow.de>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# IP Analyzer
2+
3+
IP Analyzer is a command-line tool that provides detailed information about IP addresses and their associated network properties. It offers a user-friendly interface with a visually appealing Commodore Amiga Copper-style output.
4+
5+
## Features
6+
7+
- Analyze IP addresses with CIDR notation
8+
- Display IP address details in both decimal and binary formats
9+
- Show network address, netmask, and broadcast address
10+
- Calculate usable IP range and number of hosts
11+
- Determine if the IP address is private
12+
- Present results in a colorful, easy-to-read format
13+
14+
## Prerequisites
15+
16+
To build and run this project, you need:
17+
18+
- C++17 compatible compiler (e.g., GCC 7+, Clang 5+, or MSVC 2017+)
19+
- CMake 3.10 or higher
20+
- fmt library (will be automatically downloaded if not found)
21+
22+
## Building the Project
23+
24+
1. Clone the repository:
25+
26+
```bash
27+
git clone https://github.com/yourusername/ip-analyzer.git
28+
```
29+
30+
2. Build using CMake:
31+
32+
```bash
33+
cmake -S . -B ./build
34+
cmake --build build --config Release
35+
```
36+
37+
3. Run the executable:
38+
39+
```bash
40+
./build/ip-analyzer
41+
```
42+
43+
4. You can also run the tests:
44+
45+
```bash
46+
./build/ip_analyzer_tests
47+
```
48+
49+
## Usage
50+
51+
To analyze an IP address, run the program and enter the IP address with CIDR notation:
52+
53+
```bash
54+
./build/ip-analyzer
55+
Enter an IP address with CIDR notation: 192.168.178.0/24
56+
```
57+
58+
The program will display detailed information about the IP address.
59+
60+
## License
61+
62+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
63+
64+
## Pull Requests
65+
66+
If you find a bug or want to contribute to the project, feel free to submit a pull request.

src/ip_analyzer.cc

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
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_; }

src/ip_analyzer.hh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#pragma once
2+
3+
#include <array>
4+
#include <cstdint>
5+
#include <string>
6+
#include <string_view>
7+
8+
class IPv4Address
9+
{
10+
public:
11+
explicit IPv4Address(std::string_view address);
12+
explicit IPv4Address(uint32_t address); // Add this constructor
13+
[[nodiscard]] std::string to_string() const;
14+
[[nodiscard]] std::string to_binary_string() const;
15+
[[nodiscard]] uint32_t to_uint32() const;
16+
17+
private:
18+
std::array<uint8_t, 4> octets_;
19+
};
20+
21+
class IPAnalyzer
22+
{
23+
public:
24+
explicit IPAnalyzer(std::string_view ip_cidr);
25+
26+
[[nodiscard]] IPv4Address get_ip() const;
27+
[[nodiscard]] IPv4Address get_network() const;
28+
[[nodiscard]] IPv4Address get_netmask() const;
29+
[[nodiscard]] IPv4Address get_broadcast() const;
30+
[[nodiscard]] std::pair<IPv4Address, IPv4Address> get_host_range() const;
31+
[[nodiscard]] uint32_t get_num_hosts() const;
32+
[[nodiscard]] bool is_private() const;
33+
[[nodiscard]] uint8_t get_cidr() const;
34+
35+
private:
36+
IPv4Address ip_;
37+
uint8_t cidr_;
38+
};

0 commit comments

Comments
 (0)