114 lines
2.8 KiB
C
114 lines
2.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <arpa/inet.h>
|
|
#include <errno.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "config.h"
|
|
#include "lib.h"
|
|
|
|
const char *program_invocation_name;
|
|
|
|
void error(int status, int errnum, const char *fmt, ...) {
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
fflush(stdout);
|
|
fprintf(stderr, "%s: ", program_invocation_name);
|
|
vfprintf(stderr, fmt, ap);
|
|
if (errnum) fprintf(stderr, ": %s", strerror(errnum));
|
|
fprintf(stderr, "\n");
|
|
if(status) exit(status);
|
|
va_end(ap);
|
|
}
|
|
|
|
void bits2ip4(bits b, mask_t m, char *s, int size) {
|
|
// convert bits to in4_addr
|
|
struct in4_addr ip;
|
|
for (int i = 0; i < 4; ++i) {
|
|
ip.s4_addr[i] = 0;
|
|
for (int j = 0; j < 8; ++j) {
|
|
ip.s4_addr[i] <<= 1;
|
|
int p = i*8 + j;
|
|
ip.s4_addr[i] |= (p >= m) ? 0 : b[p];
|
|
}
|
|
}
|
|
// get test representation of ip
|
|
char s_ip[INET_ADDRSTRLEN];
|
|
if (!inet_ntop(AF_INET, &ip, s_ip, INET_ADDRSTRLEN)) error(1, errno, "bits2ip4");
|
|
// print ip with mask to buffer
|
|
int res = snprintf(s, size, "%s/%d", s_ip, m);
|
|
// if printing to buffer has failed
|
|
if (res < 0 || res >= size) error(1, errno, "bits2ip4");
|
|
}
|
|
|
|
void bits2ip6(bits b, mask_t m, char *s, int size) {
|
|
// convert bits to in6_addr
|
|
struct in6_addr ip;
|
|
for (int i = 0; i < 16; ++i) {
|
|
ip.s6_addr[i] = 0;
|
|
for (int j = 0; j < 8; ++j) {
|
|
ip.s6_addr[i] <<= 1;
|
|
int p = i*8 + j;
|
|
ip.s6_addr[i] |= (p >= m) ? 0 : b[p];
|
|
}
|
|
}
|
|
// get test representation of ip
|
|
char s_ip[INET6_ADDRSTRLEN];
|
|
if (!inet_ntop(AF_INET6, &ip, s_ip, INET6_ADDRSTRLEN)) error(1, errno, "bits2ip6");
|
|
// print ip with mask to buffer
|
|
int res = snprintf(s, size, "%s/%d", s_ip, m);
|
|
// if printing to buffer has failed
|
|
if (res < 0 || res >= size) error(1, errno, "bits2ip6");
|
|
}
|
|
|
|
void ip42bits(char *s, bits b, mask_t *m) {
|
|
// split ip and mask
|
|
char *p = strchr(s, '/');
|
|
if (p) {
|
|
*p = 0;
|
|
++p;
|
|
unsigned long l = strtol(p, &p, 10);
|
|
if (*p || l > IP4LEN) error(1, errno, "ip42bits: bad mask");
|
|
*m = l;
|
|
} else {
|
|
*m = IP4LEN;
|
|
}
|
|
// convert ip to binary
|
|
struct in4_addr ip;
|
|
if (inet_pton(AF_INET, s, &ip) < 1) error(1, errno, "ip42bits");
|
|
// convert binary ip to bits
|
|
for (int i = 0; i < 4; ++i) {
|
|
for (int j = 0; j < 8; ++j) {
|
|
int p = i*8 + 8-1-j;
|
|
b[p] = (p > *m) ? 0 : (ip.s4_addr[i] & 1);
|
|
ip.s4_addr[i] >>= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ip62bits(char *s, bits b, mask_t *m) {
|
|
// split ip and mask
|
|
char *p = strchr(s, '/');
|
|
if (p) {
|
|
*p = 0;
|
|
++p;
|
|
unsigned long l = strtol(p, &p, 10);
|
|
if (*p || l > IP6LEN) error(1, errno, "ip62bits: bad mask");
|
|
*m = l;
|
|
} else {
|
|
*m = IP6LEN;
|
|
}
|
|
// convert ip to binary
|
|
struct in6_addr ip;
|
|
if (inet_pton(AF_INET6, s, &ip) < 1) error(1, errno, "ip62bits");
|
|
// convert binary ip to bits
|
|
for (int i = 0; i < 16; ++i) {
|
|
for (int j = 0; j < 8; ++j) {
|
|
int p = i*8 + 8-1-j;
|
|
b[p] = (p > *m) ? 0 : (ip.s6_addr[i] & 1);
|
|
ip.s6_addr[i] >>= 1;
|
|
}
|
|
}
|
|
}
|