diff options
Diffstat (limited to 'host.c')
-rw-r--r-- | host.c | 95 |
1 files changed, 95 insertions, 0 deletions
@@ -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; +} |