summaryrefslogtreecommitdiffstats
path: root/host.c
diff options
context:
space:
mode:
Diffstat (limited to 'host.c')
-rw-r--r--host.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/host.c b/host.c
new file mode 100644
index 0000000..b6e68dd
--- /dev/null
+++ b/host.c
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <netdb.h>
+struct in_net {
+ struct in_addr addr;
+ struct in_addr mask;
+};
+/* not needed begin */
+#define POPCNT(y) int popcnt##x (uint##y##_t x) { \
+ int c = 0; \
+ for (int i = 0; i < y; i++) \
+ if (1 << i & x) \
+ c++; \
+ return c; \
+}
+POPCNT(32)
+unsigned int power2[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648 }; /* ah yes, libmath */
+/* not needed end */
+struct in_addr host (struct in_net n, int h /* consecutive number of the host in the network */) {
+ n.addr.s_addr = ntohl(n.addr.s_addr & n.mask.s_addr);
+ n.mask.s_addr = ntohl(n.mask.s_addr);
+ int c = 1;
+ int s = 0;
+ for (int i = 0; i < 32; i++)
+ if (1 << i & ~n.mask.s_addr) {
+ if (1 << s++ & h)
+ n.addr.s_addr |= 1 << i;
+ c = c * 2;
+ }
+ if (h >= c)
+ n.addr.s_addr = 0;
+ n.addr.s_addr = htonl(n.addr.s_addr);
+ return n.addr;
+}
+int resolve (const char * d, uint32_t * r) {
+ struct addrinfo hints = {
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_DGRAM,
+ .ai_flags = 0,
+ .ai_protocol = 0,
+ .ai_canonname = NULL,
+ .ai_addr = NULL,
+ .ai_next = NULL
+ };
+ struct addrinfo * result;
+ int ret = getaddrinfo(d, NULL, &hints, &result);
+ *r = ((struct sockaddr_in *) result->ai_addr)->sin_addr.s_addr; /* ah yes, C */
+ freeaddrinfo(result);
+ return ret;
+}
+struct in_net str2net (char * s) { /* blocking, resolving */
+ struct in_net r = {
+ .mask = {
+ .s_addr = 0
+ },
+ .addr = {
+ .s_addr = 0
+ }
+ };
+ char * m = strchr(s, '/');
+ char o = '\0';
+ int e;
+ if (m) {
+ o = *m;
+ *m++ = '\0';
+ } else
+ m = "32";
+ fprintf(stderr, "str2net: resolving %s ... ", s);
+ if ((e = resolve(s, &r.addr.s_addr))) {
+ fprintf(stderr, "failed: %s\n", gai_strerror(e));
+ goto r;
+ }
+ fprintf(stderr, " %s mask %s ...", inet_ntoa(r.addr), m);
+ char * p;
+ int x = strtoll(m, &p, 10);
+ r.mask.s_addr = 0;
+ for (int j = 0; j < x && j < 32; j++)
+ r.mask.s_addr = r.mask.s_addr >> 1 | 1 << 31;
+ r.mask.s_addr = htonl(r.mask.s_addr);
+ if (*p)
+ if ((e = resolve(m, &r.mask.s_addr))) {
+ fprintf(stderr, "no: %s\n", gai_strerror(e));
+ goto r;
+ }
+ fprintf(stderr, " %s\n", inet_ntoa(r.mask));
+r:
+ if (o)
+ *--m = o;
+ return r;
+}