1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#include "calc.h"
#include <time.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
int print_usage() {
printf("Invalid arguments:\n\tcalc <network/cidr> <ips per subnet>\n");
return 1;
}
uint32_t calc_netmask(unsigned int cidr) {
return UINT32_MAX << (32 - cidr);
}
uint32_t segments_to_ip(unsigned int segments[4]) {
return (segments[0] << 3*8) | (segments[1] << 2*8) | (segments[2] << 1*8) | (segments[3]);
}
uint32_t subnetmask_for_netspace(unsigned int desired_netspace) {
uint32_t start = UINT32_MAX;
// +1 because 2s complement
while (~start +1 < desired_netspace + 2) {
start = start << 1;
}
return start;
}
int main(int argc, char** argv) {
struct timespec start;
clock_gettime(CLOCK_MONOTONIC, &start);
unsigned int segments[4] = {0};
unsigned int cidr = 0;
unsigned int min_ips_per_subnet = 0;
// parse args
if (argc < 3) {
return print_usage();
}
if (sscanf(argv[1], "%u.%u.%u.%u/%u", &segments[0], &segments[1], &segments[2], &segments[3], &cidr) != 5) return print_usage();
if (sscanf(argv[2], "%u", &min_ips_per_subnet) != 1) return print_usage();
CalcRequest req = {
.network = segments_to_ip(segments), // fixed later
.netmask = calc_netmask(cidr),
.subnet_mask = subnetmask_for_netspace(min_ips_per_subnet),
.count = 0, // later
};
// User can provide any ip address, this converts it to the network address
req.network = req.network & req.netmask;
// +1 because 2s complement
const unsigned int ips_per_subnet = ~req.subnet_mask + 1;
req.count = (~req.netmask+1) / (ips_per_subnet);
FILE *out = fopen("file.json", "w");
if (out == NULL) {
perror("Failed to open output file:");
return errno;
}
fprintf(out, "[\n"); // file start
uint32_t offset = 0;
int i = 0;
while (i<req.count) {
const uint32_t network = req.network + offset;
const uint32_t first = network + 1;
const uint32_t broadcast = first + ips_per_subnet - 2;
const uint32_t last = broadcast - 1;
offset += ips_per_subnet;
if (i+1 == req.count) {
fprintf(out,
"\t{\n\t\t\"Reseau\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Premiere\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Derniere\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Broadcast\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Nbr\": \"%hu\"\n\t}\n",
UINT_TO_SEGMENTS(network),
UINT_TO_SEGMENTS(first),
UINT_TO_SEGMENTS(last),
UINT_TO_SEGMENTS(broadcast),
ips_per_subnet - 2
);
break;
}
fprintf(out,
"\t{\n\t\t\"Reseau\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Premiere\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Derniere\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Broadcast\": \"%hu.%hu.%hu.%hu\",\n\t\t\"Nbr\": \"%hu\"\n\t},\n",
UINT_TO_SEGMENTS(network),
UINT_TO_SEGMENTS(first),
UINT_TO_SEGMENTS(last),
UINT_TO_SEGMENTS(broadcast),
ips_per_subnet - 2
);
i++;
}
fprintf(out, "]"); // file end
fflush(out);
fclose(out);
struct timespec end;
clock_gettime(CLOCK_MONOTONIC, &end);
printf("Time elapsed: %llu ms\n", (unsigned long long)((end.tv_sec - start.tv_sec) * 1e3 + (end.tv_nsec - start.tv_nsec) / 1e6));
return 0;
}
|