diff options
author | pankunull <panku_null@proton.me> | 2025-09-05 23:27:18 +0200 |
---|---|---|
committer | pankunull <panku_null@proton.me> | 2025-09-05 23:27:18 +0200 |
commit | 1acd14aa77268bd75afd465496bba57d6b1e5436 (patch) | |
tree | 85638a9405aab8fb67e267d699559b5582956493 /src |
Initial commit
Diffstat (limited to 'src')
-rw-r--r-- | src/iptool.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/iptool.c b/src/iptool.c new file mode 100644 index 0000000..e940c52 --- /dev/null +++ b/src/iptool.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * subnet_calc.c - Simple IP subnet calculator + * + * Takes an IPv4 address and a prefix length, then calculates: + * - IP class + * - Network address + * - Broadcast address + * - Total hosts + * - Usable hosts + * - Usable IP range + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +static uint32_t ip_to_u32(const char *ip_str) +{ + int o1, o2, o3, o4; + + if (sscanf(ip_str, "%d.%d.%d.%d", &o1, &o2, &o3, &o4) != 4) { + fprintf(stderr, "Invalid IP format: %s\n", ip_str); + exit(1); + } + + if (o1 < 0 || o1 > 255 || o2 < 0 || o2 > 255 || + o3 < 0 || o3 > 255 || o4 < 0 || o4 > 255) { + fprintf(stderr, "IP octet out of range: %s\n", ip_str); + exit(1); + } + + return (o1 << 24) | (o2 << 16) | (o3 << 8) | o4; +} + +static uint32_t netmask_from_prefix(int prefix) +{ + return prefix ? 0xFFFFFFFFU << (32 - prefix) : 0; +} + +static uint32_t network_addr(uint32_t ip, uint32_t netmask) +{ + return ip & netmask; +} + +static uint32_t broadcast_addr(uint32_t ip, uint32_t netmask) +{ + return (ip & netmask) | ~netmask; +} + +static uint32_t total_hosts(int prefix) +{ + return 1U << (32 - prefix); +} + +static uint32_t usable_hosts(int prefix) +{ + uint32_t th = total_hosts(prefix); + + return (th <= 2) ? 0 : th - 2; +} + +static char ip_class(uint32_t ip) +{ + uint8_t first_octet = ip >> 24; + + if (first_octet <= 127) + return 'A'; + if (first_octet <= 191) + return 'B'; + if (first_octet <= 223) + return 'C'; + if (first_octet <= 239) + return 'D'; + return 'E'; +} + +static void print_ip(uint32_t ip) +{ + printf("%u.%u.%u.%u", + (ip >> 24) & 0xFF, + (ip >> 16) & 0xFF, + (ip >> 8) & 0xFF, + ip & 0xFF); +} + +int main(int argc, char *argv[]) +{ + uint32_t ip, netmask, network, broadcast; + int prefix; + uint32_t total, usable; + + if (argc < 3) { + fprintf(stderr, "Usage: %s <ip> <prefix>\n", argv[0]); + return 1; + } + + ip = ip_to_u32(argv[1]); + prefix = atoi(argv[2]); + + if (prefix < 0 || prefix > 32) { + fprintf(stderr, "Prefix must be 0-32\n"); + return 1; + } + + netmask = netmask_from_prefix(prefix); + network = network_addr(ip, netmask); + broadcast = broadcast_addr(ip, netmask); + total = total_hosts(prefix); + usable = usable_hosts(prefix); + + printf("IP Class: %c\n", ip_class(ip)); + printf("Network: "); print_ip(network); printf("\n"); + printf("Broadcast: "); print_ip(broadcast); printf("\n"); + printf("Total hosts: %u\n", total); + printf("Usable hosts: %u\n", usable); + + if (usable > 0) { + printf("Usable IP range: "); + print_ip(network + 1); + printf(" - "); + print_ip(broadcast - 1); + printf("\n"); + } else { + printf("No usable IPs in this subnet\n"); + } + + return 0; +} + |