From 686f91919431ddcb99f69baff005d0916a502ffa Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Sat, 23 Jan 2021 13:54:41 +0100 Subject: [PATCH] owipcalc: separate in client and lib Separate owipcalc in client and lib part. Owipcalc brings a lot of nice functionality with it, e.g. parsing and calculating prefixes. Signed-off-by: Nick Hainke --- net/owipcalc/Makefile | 31 ++- net/owipcalc/src/main.c | 279 ++++++++++++++++++++++++++ net/owipcalc/src/owipcalc.c | 381 ++++-------------------------------- net/owipcalc/src/owipcalc.h | 82 ++++++++ 4 files changed, 425 insertions(+), 348 deletions(-) create mode 100644 net/owipcalc/src/main.c create mode 100644 net/owipcalc/src/owipcalc.h diff --git a/net/owipcalc/Makefile b/net/owipcalc/Makefile index c7857f5c8..2865b1c7c 100644 --- a/net/owipcalc/Makefile +++ b/net/owipcalc/Makefile @@ -12,12 +12,12 @@ PKG_LICENSE:=Apache-2.0 include $(INCLUDE_DIR)/package.mk - define Package/owipcalc SECTION:=utils CATEGORY:=Utilities TITLE:=Simple IPv4/IPv6 address calculator MAINTAINER:=Jo-Philipp Wich + DEPENDS:=+libowipcalc endef define Package/owipcalc/description @@ -27,18 +27,45 @@ define Package/owipcalc/description for dhcp pools. endef +define Package/libowipcalc + SECTION:=libs + CATEGORY:=Libraries + TITLE:=Owipcalc Library +endef + +define Package/libowipcalc/description + The owipcalc library supports a number of calculations and tests to work + with ip-address ranges, this is useful for programms that e.g. need to + partition ipv6-prefixes into small subnets or to calculate address ranges + for dhcp pools. +endef + define Build/Configure endef define Build/Compile $(TARGET_CC) $(TARGET_CFLAGS) \ - -o $(PKG_BUILD_DIR)/owipcalc $(PKG_BUILD_DIR)/owipcalc.c + -shared -fPIC -o $(PKG_BUILD_DIR)/libowipcalc.so $(PKG_BUILD_DIR)/owipcalc.c + $(TARGET_CC) $(TARGET_CFLAGS) \ + -o $(PKG_BUILD_DIR)/owipcalc $(PKG_BUILD_DIR)/main.c -L$(PKG_BUILD_DIR)/ -lowipcalc endef +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/ + $(CP) $(PKG_BUILD_DIR)/owipcalc.h $(1)/usr/include/ + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/libowipcalc.so $(1)/usr/lib/libowipcalc.so +endef define Package/owipcalc/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/owipcalc $(1)/usr/bin/owipcalc endef +define Package/libowipcalc/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/libowipcalc.so $(1)/usr/lib/libowipcalc.so +endef + +$(eval $(call BuildPackage,libowipcalc)) $(eval $(call BuildPackage,owipcalc)) diff --git a/net/owipcalc/src/main.c b/net/owipcalc/src/main.c new file mode 100644 index 000000000..c47ba3fcf --- /dev/null +++ b/net/owipcalc/src/main.c @@ -0,0 +1,279 @@ +#include +#include +#include + +#include + +#include "owipcalc.h" + +struct op { + const char *name; + const char *desc; + struct { + bool (*a1)(struct cidr *a); + bool (*a2)(struct cidr *a, struct cidr *b); + } f4; + struct { + bool (*a1)(struct cidr *a); + bool (*a2)(struct cidr *a, struct cidr *b); + } f6; +}; + +struct op ops[] = { + { .name = "add", + .desc = "Add argument to base address", + .f4.a2 = cidr_add4, + .f6.a2 = cidr_add6 }, + + { .name = "sub", + .desc = "Substract argument from base address", + .f4.a2 = cidr_sub4, + .f6.a2 = cidr_sub6 }, + + { .name = "next", + .desc = "Advance base address to next prefix of given size", + .f4.a2 = cidr_next4, + .f6.a2 = cidr_next6 }, + + { .name = "prev", + .desc = "Lower base address to previous prefix of give size", + .f4.a2 = cidr_prev4, + .f6.a2 = cidr_prev6 }, + + { .name = "network", + .desc = "Turn base address into network address", + .f4.a1 = cidr_network4, + .f6.a1 = cidr_network6 }, + + { .name = "broadcast", + .desc = "Turn base address into broadcast address", + .f4.a1 = cidr_broadcast4 }, + + { .name = "prefix", + .desc = "Set the prefix of base address to argument", + .f4.a2 = cidr_prefix, + .f6.a2 = cidr_prefix }, + + { .name = "netmask", + .desc = "Calculate netmask of base address", + .f4.a1 = cidr_netmask4 }, + + { .name = "6to4", + .desc = "Calculate 6to4 prefix of given ipv4-address", + .f4.a1 = cidr_6to4 }, + + { .name = "howmany", + .desc = "Print amount of righ-hand prefixes that fit into base address", + .f4.a2 = cidr_howmany, + .f6.a2 = cidr_howmany }, + + { .name = "contains", + .desc = "Print '1' if argument fits into base address or '0' if not", + .f4.a2 = cidr_contains4, + .f6.a2 = cidr_contains6 }, + + { .name = "private", + .desc = "Print '1' if base address is in RFC1918 private space or '0' " + "if not", + .f4.a1 = cidr_private4 }, + + { .name = "linklocal", + .desc = "Print '1' if base address is in 169.254.0.0/16 or FE80::/10 " + "link local space or '0' if not", + .f4.a1 = cidr_linklocal4, + .f6.a1 = cidr_linklocal6 }, + + { .name = "ula", + .desc = "Print '1' if base address is in FC00::/7 unique local address " + "(ULA) space or '0' if not", + .f6.a1 = cidr_ula6 }, + + { .name = "quiet", + .desc = "Suppress output, useful for test operation where the result can " + "be inferred from the exit code", + .f4.a1 = cidr_quiet, + .f6.a1 = cidr_quiet }, + + { .name = "pop", + .desc = "Pop intermediate result from stack", + .f4.a1 = cidr_pop, + .f6.a1 = cidr_pop }, + + { .name = "print", + .desc = "Print intermediate result and pop it from stack, invoked " + "implicitely at the end of calculation if no intermediate prints " + "happened", + .f4.a1 = cidr_print4, + .f6.a1 = cidr_print6 }, +}; + +static void usage(const char *prog) +{ + int i; + + fprintf(stderr, + "\n" + "Usage:\n\n" + " %s {base address} operation [argument] " + "[operation [argument] ...]\n\n" + "Operations:\n\n", + prog); + + for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++) + { + if (ops[i].f4.a2 || ops[i].f6.a2) + { + fprintf(stderr, " %s %s\n", + ops[i].name, + (ops[i].f4.a2 && ops[i].f6.a2) ? "{ipv4/ipv6/amount}" : + (ops[i].f6.a2 ? "{ipv6/amount}" : "{ipv4/amount}")); + } + else + { + fprintf(stderr, " %s\n", ops[i].name); + } + + fprintf(stderr, " %s.\n", ops[i].desc); + + if ((ops[i].f4.a1 && ops[i].f6.a1) || (ops[i].f4.a2 && ops[i].f6.a2)) + fprintf(stderr, " Applicable to ipv4- and ipv6-addresses.\n\n"); + else if (ops[i].f6.a2 || ops[i].f6.a1) + fprintf(stderr, " Only applicable to ipv6-addresses.\n\n"); + else + fprintf(stderr, " Only applicable to ipv4-addresses.\n\n"); + } + + fprintf(stderr, + "Examples:\n\n" + " Calculate a DHCP range:\n\n" + " $ %s 192.168.1.1/255.255.255.0 network add 100 print add 150 print\n" + " 192.168.1.100\n" + " 192.168.1.250\n\n" + " Count number of prefixes:\n\n" + " $ %s 2001:0DB8:FDEF::/48 howmany ::/64\n" + " 65536\n\n", + prog, prog); + + exit(1); +} + +static bool runop(char ***arg, int *status) +{ + int i; + char *arg1 = **arg; + char *arg2 = *(*arg+1); + struct cidr *a = stack; + struct cidr *b = NULL; + + if (!arg1) + return false; + + for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++) + { + if (!strcmp(ops[i].name, arg1)) + { + if (ops[i].f4.a2 || ops[i].f6.a2) + { + if (!arg2) + { + fprintf(stderr, "'%s' requires an argument\n", + ops[i].name); + + *status = 2; + return false; + } + + b = cidr_parse(ops[i].name, arg2, a->family); + + if (!b) + { + fprintf(stderr, "invalid address argument for '%s'\n", + ops[i].name); + + *status = 3; + return false; + } + + *arg += 2; + + if (((a->family == AF_INET) && !ops[i].f4.a2) || + ((a->family == AF_INET6) && !ops[i].f6.a2)) + { + fprintf(stderr, "'%s' not supported for %s addresses\n", + ops[i].name, + (a->family == AF_INET) ? "ipv4" : "ipv6"); + + *status = 5; + return false; + } + + *status = !((a->family == AF_INET) ? ops[i].f4.a2(a, b) + : ops[i].f6.a2(a, b)); + + return true; + } + else + { + *arg += 1; + + if (((a->family == AF_INET) && !ops[i].f4.a1) || + ((a->family == AF_INET6) && !ops[i].f6.a1)) + { + fprintf(stderr, "'%s' not supported for %s addresses\n", + ops[i].name, + (a->family == AF_INET) ? "ipv4" : "ipv6"); + + *status = 5; + return false; + } + + *status = !((a->family == AF_INET) ? ops[i].f4.a1(a) + : ops[i].f6.a1(a)); + + return true; + } + } + } + + return false; +} + +int main(int argc, char **argv) +{ + int status = 0; + char **arg = argv+2; + struct cidr *a; + + // enable printing + quiet = false; + + if (argc < 3) + usage(argv[0]); + + a = strchr(argv[1], ':') ? cidr_parse6(argv[1]) : cidr_parse4(argv[1]); + + if (!a) + usage(argv[0]); + + cidr_push(a); + + while (runop(&arg, &status)); + + if (*arg) + { + fprintf(stderr, "unknown operation '%s'\n", *arg); + exit(6); + } + + if (!printed && (status < 2)) + { + if (stack->family == AF_INET) + cidr_print4(stack); + else + cidr_print6(stack); + } + + qprintf("\n"); + + exit(status); +} diff --git a/net/owipcalc/src/owipcalc.c b/net/owipcalc/src/owipcalc.c index fa656948b..e69654715 100644 --- a/net/owipcalc/src/owipcalc.c +++ b/net/owipcalc/src/owipcalc.c @@ -1,72 +1,18 @@ -/* - * owipcalc - OpenWrt IP Calculator - * - * Copyright (C) 2012 Jo-Philipp Wich - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include #include -#include #include - #include #include #include +#include "owipcalc.h" + +bool quiet = true; +bool printed = false; + +struct cidr *stack = NULL; -struct cidr { - uint8_t family; - uint32_t prefix; - union { - struct in_addr v4; - struct in6_addr v6; - } addr; - union { - char v4[sizeof("255.255.255.255/255.255.255.255 ")]; - char v6[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128 ")]; - } buf; - struct cidr *next; -}; - -struct op { - const char *name; - const char *desc; - struct { - bool (*a1)(struct cidr *a); - bool (*a2)(struct cidr *a, struct cidr *b); - } f4; - struct { - bool (*a1)(struct cidr *a); - bool (*a2)(struct cidr *a, struct cidr *b); - } f6; -}; - - -static bool quiet = false; -static bool printed = false; - -static struct cidr *stack = NULL; - -#define qprintf(...) \ - do { \ - if (!quiet) printf(__VA_ARGS__); \ - printed = true; \ - } while(0) - -static void cidr_push(struct cidr *a) +void cidr_push(struct cidr *a) { if (a) { @@ -75,7 +21,7 @@ static void cidr_push(struct cidr *a) } } -static bool cidr_pop(struct cidr *a) +bool cidr_pop(struct cidr *a) { struct cidr *old = stack; @@ -107,7 +53,7 @@ static struct cidr * cidr_clone(struct cidr *a) } -static struct cidr * cidr_parse4(const char *s) +struct cidr * cidr_parse4(const char *s) { char *p = NULL, *r; struct in_addr mask; @@ -159,7 +105,7 @@ err: return NULL; } -static bool cidr_add4(struct cidr *a, struct cidr *b) +bool cidr_add4(struct cidr *a, struct cidr *b) { uint32_t x = ntohl(a->addr.v4.s_addr); uint32_t y = ntohl(b->addr.v4.s_addr); @@ -179,7 +125,7 @@ static bool cidr_add4(struct cidr *a, struct cidr *b) return true; } -static bool cidr_sub4(struct cidr *a, struct cidr *b) +bool cidr_sub4(struct cidr *a, struct cidr *b) { uint32_t x = ntohl(a->addr.v4.s_addr); uint32_t y = ntohl(b->addr.v4.s_addr); @@ -199,7 +145,7 @@ static bool cidr_sub4(struct cidr *a, struct cidr *b) return true; } -static bool cidr_network4(struct cidr *a) +bool cidr_network4(struct cidr *a) { struct cidr *n = cidr_clone(a); @@ -209,7 +155,7 @@ static bool cidr_network4(struct cidr *a) return true; } -static bool cidr_broadcast4(struct cidr *a) +bool cidr_broadcast4(struct cidr *a) { struct cidr *n = cidr_clone(a); @@ -219,7 +165,7 @@ static bool cidr_broadcast4(struct cidr *a) return true; } -static bool cidr_contains4(struct cidr *a, struct cidr *b) +bool cidr_contains4(struct cidr *a, struct cidr *b) { uint32_t net1 = a->addr.v4.s_addr & htonl(~((1 << (32 - a->prefix)) - 1)); uint32_t net2 = b->addr.v4.s_addr & htonl(~((1 << (32 - a->prefix)) - 1)); @@ -239,7 +185,7 @@ static bool cidr_contains4(struct cidr *a, struct cidr *b) } } -static bool cidr_netmask4(struct cidr *a) +bool cidr_netmask4(struct cidr *a) { struct cidr *n = cidr_clone(a); @@ -249,7 +195,7 @@ static bool cidr_netmask4(struct cidr *a) return true; } -static bool cidr_private4(struct cidr *a) +bool cidr_private4(struct cidr *a) { uint32_t x = ntohl(a->addr.v4.s_addr); @@ -270,7 +216,7 @@ static bool cidr_private4(struct cidr *a) } } -static bool cidr_linklocal4(struct cidr *a) +bool cidr_linklocal4(struct cidr *a) { uint32_t x = ntohl(a->addr.v4.s_addr); @@ -289,7 +235,7 @@ static bool cidr_linklocal4(struct cidr *a) } } -static bool cidr_prev4(struct cidr *a, struct cidr *b) +bool cidr_prev4(struct cidr *a, struct cidr *b) { struct cidr *n = cidr_clone(a); @@ -299,7 +245,7 @@ static bool cidr_prev4(struct cidr *a, struct cidr *b) return true; } -static bool cidr_next4(struct cidr *a, struct cidr *b) +bool cidr_next4(struct cidr *a, struct cidr *b) { struct cidr *n = cidr_clone(a); @@ -309,7 +255,7 @@ static bool cidr_next4(struct cidr *a, struct cidr *b) return true; } -static bool cidr_6to4(struct cidr *a) +bool cidr_6to4(struct cidr *a) { struct cidr *n = cidr_clone(a); uint32_t x = a->addr.v4.s_addr; @@ -329,7 +275,7 @@ static bool cidr_6to4(struct cidr *a) return true; } -static bool cidr_print4(struct cidr *a) +bool cidr_print4(struct cidr *a) { char *p; @@ -353,7 +299,7 @@ static bool cidr_print4(struct cidr *a) } -static struct cidr * cidr_parse6(const char *s) +struct cidr * cidr_parse6(const char *s) { char *p = NULL, *r; struct cidr *addr = malloc(sizeof(struct cidr)); @@ -393,7 +339,7 @@ err: return NULL; } -static bool cidr_add6(struct cidr *a, struct cidr *b) +bool cidr_add6(struct cidr *a, struct cidr *b) { uint8_t idx = 15, carry = 0, overflow = 0; @@ -420,7 +366,7 @@ static bool cidr_add6(struct cidr *a, struct cidr *b) return true; } -static bool cidr_sub6(struct cidr *a, struct cidr *b) +bool cidr_sub6(struct cidr *a, struct cidr *b) { uint8_t idx = 15, carry = 0, underflow = 0; @@ -447,7 +393,7 @@ static bool cidr_sub6(struct cidr *a, struct cidr *b) return true; } -static bool cidr_prev6(struct cidr *a, struct cidr *b) +bool cidr_prev6(struct cidr *a, struct cidr *b) { uint8_t idx, carry = 1, underflow = 0; struct cidr *n = cidr_clone(a); @@ -479,7 +425,7 @@ static bool cidr_prev6(struct cidr *a, struct cidr *b) return true; } -static bool cidr_next6(struct cidr *a, struct cidr *b) +bool cidr_next6(struct cidr *a, struct cidr *b) { uint8_t idx, carry = 1, overflow = 0; struct cidr *n = cidr_clone(a); @@ -511,7 +457,7 @@ static bool cidr_next6(struct cidr *a, struct cidr *b) return true; } -static bool cidr_network6(struct cidr *a) +bool cidr_network6(struct cidr *a) { uint8_t i; struct cidr *n = cidr_clone(a); @@ -525,7 +471,7 @@ static bool cidr_network6(struct cidr *a) return true; } -static bool cidr_contains6(struct cidr *a, struct cidr *b) +bool cidr_contains6(struct cidr *a, struct cidr *b) { struct in6_addr *x = &a->addr.v6; struct in6_addr *y = &b->addr.v6; @@ -551,7 +497,7 @@ static bool cidr_contains6(struct cidr *a, struct cidr *b) } } -static bool cidr_linklocal6(struct cidr *a) +bool cidr_linklocal6(struct cidr *a) { if (printed) qprintf(" "); @@ -570,7 +516,7 @@ static bool cidr_linklocal6(struct cidr *a) } } -static bool cidr_ula6(struct cidr *a) +bool cidr_ula6(struct cidr *a) { if (printed) qprintf(" "); @@ -588,7 +534,7 @@ static bool cidr_ula6(struct cidr *a) } } -static bool cidr_print6(struct cidr *a) +bool cidr_print6(struct cidr *a) { char *p; @@ -612,7 +558,7 @@ static bool cidr_print6(struct cidr *a) } -static struct cidr * cidr_parse(const char *op, const char *s, int af_hint) +struct cidr * cidr_parse(const char *op, const char *s, int af_hint) { char *r; struct cidr *a; @@ -668,7 +614,7 @@ static struct cidr * cidr_parse(const char *op, const char *s, int af_hint) return a; } -static bool cidr_howmany(struct cidr *a, struct cidr *b) +bool cidr_howmany(struct cidr *a, struct cidr *b) { if (printed) qprintf(" "); @@ -681,271 +627,14 @@ static bool cidr_howmany(struct cidr *a, struct cidr *b) return true; } -static bool cidr_prefix(struct cidr *a, struct cidr *b) +bool cidr_prefix(struct cidr *a, struct cidr *b) { a->prefix = b->prefix; return true; } -static bool cidr_quiet(struct cidr *a) +bool cidr_quiet(struct cidr *a) { quiet = true; return true; } - - -struct op ops[] = { - { .name = "add", - .desc = "Add argument to base address", - .f4.a2 = cidr_add4, - .f6.a2 = cidr_add6 }, - - { .name = "sub", - .desc = "Substract argument from base address", - .f4.a2 = cidr_sub4, - .f6.a2 = cidr_sub6 }, - - { .name = "next", - .desc = "Advance base address to next prefix of given size", - .f4.a2 = cidr_next4, - .f6.a2 = cidr_next6 }, - - { .name = "prev", - .desc = "Lower base address to previous prefix of give size", - .f4.a2 = cidr_prev4, - .f6.a2 = cidr_prev6 }, - - { .name = "network", - .desc = "Turn base address into network address", - .f4.a1 = cidr_network4, - .f6.a1 = cidr_network6 }, - - { .name = "broadcast", - .desc = "Turn base address into broadcast address", - .f4.a1 = cidr_broadcast4 }, - - { .name = "prefix", - .desc = "Set the prefix of base address to argument", - .f4.a2 = cidr_prefix, - .f6.a2 = cidr_prefix }, - - { .name = "netmask", - .desc = "Calculate netmask of base address", - .f4.a1 = cidr_netmask4 }, - - { .name = "6to4", - .desc = "Calculate 6to4 prefix of given ipv4-address", - .f4.a1 = cidr_6to4 }, - - { .name = "howmany", - .desc = "Print amount of righ-hand prefixes that fit into base address", - .f4.a2 = cidr_howmany, - .f6.a2 = cidr_howmany }, - - { .name = "contains", - .desc = "Print '1' if argument fits into base address or '0' if not", - .f4.a2 = cidr_contains4, - .f6.a2 = cidr_contains6 }, - - { .name = "private", - .desc = "Print '1' if base address is in RFC1918 private space or '0' " - "if not", - .f4.a1 = cidr_private4 }, - - { .name = "linklocal", - .desc = "Print '1' if base address is in 169.254.0.0/16 or FE80::/10 " - "link local space or '0' if not", - .f4.a1 = cidr_linklocal4, - .f6.a1 = cidr_linklocal6 }, - - { .name = "ula", - .desc = "Print '1' if base address is in FC00::/7 unique local address " - "(ULA) space or '0' if not", - .f6.a1 = cidr_ula6 }, - - { .name = "quiet", - .desc = "Suppress output, useful for test operation where the result can " - "be inferred from the exit code", - .f4.a1 = cidr_quiet, - .f6.a1 = cidr_quiet }, - - { .name = "pop", - .desc = "Pop intermediate result from stack", - .f4.a1 = cidr_pop, - .f6.a1 = cidr_pop }, - - { .name = "print", - .desc = "Print intermediate result and pop it from stack, invoked " - "implicitely at the end of calculation if no intermediate prints " - "happened", - .f4.a1 = cidr_print4, - .f6.a1 = cidr_print6 }, -}; - -static void usage(const char *prog) -{ - int i; - - fprintf(stderr, - "\n" - "Usage:\n\n" - " %s {base address} operation [argument] " - "[operation [argument] ...]\n\n" - "Operations:\n\n", - prog); - - for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++) - { - if (ops[i].f4.a2 || ops[i].f6.a2) - { - fprintf(stderr, " %s %s\n", - ops[i].name, - (ops[i].f4.a2 && ops[i].f6.a2) ? "{ipv4/ipv6/amount}" : - (ops[i].f6.a2 ? "{ipv6/amount}" : "{ipv4/amount}")); - } - else - { - fprintf(stderr, " %s\n", ops[i].name); - } - - fprintf(stderr, " %s.\n", ops[i].desc); - - if ((ops[i].f4.a1 && ops[i].f6.a1) || (ops[i].f4.a2 && ops[i].f6.a2)) - fprintf(stderr, " Applicable to ipv4- and ipv6-addresses.\n\n"); - else if (ops[i].f6.a2 || ops[i].f6.a1) - fprintf(stderr, " Only applicable to ipv6-addresses.\n\n"); - else - fprintf(stderr, " Only applicable to ipv4-addresses.\n\n"); - } - - fprintf(stderr, - "Examples:\n\n" - " Calculate a DHCP range:\n\n" - " $ %s 192.168.1.1/255.255.255.0 network add 100 print add 150 print\n" - " 192.168.1.100\n" - " 192.168.1.250\n\n" - " Count number of prefixes:\n\n" - " $ %s 2001:0DB8:FDEF::/48 howmany ::/64\n" - " 65536\n\n", - prog, prog); - - exit(1); -} - -static bool runop(char ***arg, int *status) -{ - int i; - char *arg1 = **arg; - char *arg2 = *(*arg+1); - struct cidr *a = stack; - struct cidr *b = NULL; - - if (!arg1) - return false; - - for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++) - { - if (!strcmp(ops[i].name, arg1)) - { - if (ops[i].f4.a2 || ops[i].f6.a2) - { - if (!arg2) - { - fprintf(stderr, "'%s' requires an argument\n", - ops[i].name); - - *status = 2; - return false; - } - - b = cidr_parse(ops[i].name, arg2, a->family); - - if (!b) - { - fprintf(stderr, "invalid address argument for '%s'\n", - ops[i].name); - - *status = 3; - return false; - } - - *arg += 2; - - if (((a->family == AF_INET) && !ops[i].f4.a2) || - ((a->family == AF_INET6) && !ops[i].f6.a2)) - { - fprintf(stderr, "'%s' not supported for %s addresses\n", - ops[i].name, - (a->family == AF_INET) ? "ipv4" : "ipv6"); - - *status = 5; - return false; - } - - *status = !((a->family == AF_INET) ? ops[i].f4.a2(a, b) - : ops[i].f6.a2(a, b)); - - return true; - } - else - { - *arg += 1; - - if (((a->family == AF_INET) && !ops[i].f4.a1) || - ((a->family == AF_INET6) && !ops[i].f6.a1)) - { - fprintf(stderr, "'%s' not supported for %s addresses\n", - ops[i].name, - (a->family == AF_INET) ? "ipv4" : "ipv6"); - - *status = 5; - return false; - } - - *status = !((a->family == AF_INET) ? ops[i].f4.a1(a) - : ops[i].f6.a1(a)); - - return true; - } - } - } - - return false; -} - -int main(int argc, char **argv) -{ - int status = 0; - char **arg = argv+2; - struct cidr *a; - - if (argc < 3) - usage(argv[0]); - - a = strchr(argv[1], ':') ? cidr_parse6(argv[1]) : cidr_parse4(argv[1]); - - if (!a) - usage(argv[0]); - - cidr_push(a); - - while (runop(&arg, &status)); - - if (*arg) - { - fprintf(stderr, "unknown operation '%s'\n", *arg); - exit(6); - } - - if (!printed && (status < 2)) - { - if (stack->family == AF_INET) - cidr_print4(stack); - else - cidr_print6(stack); - } - - qprintf("\n"); - - exit(status); -} diff --git a/net/owipcalc/src/owipcalc.h b/net/owipcalc/src/owipcalc.h new file mode 100644 index 000000000..8257ca1cb --- /dev/null +++ b/net/owipcalc/src/owipcalc.h @@ -0,0 +1,82 @@ +/* + * owipcalc - OpenWrt IP Calculator + * + * Copyright (C) 2012 Jo-Philipp Wich + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __OWIPCALC_H__ +#define __OWIPCALC_H__ + +#include +#include +#include + +#include + +#define qprintf(...) \ + do { \ + if (!quiet) printf(__VA_ARGS__); \ + printed = true; \ + } while(0) + +struct cidr { + uint8_t family; + uint32_t prefix; + union { + struct in_addr v4; + struct in6_addr v6; + } addr; + union { + char v4[sizeof("255.255.255.255/255.255.255.255 ")]; + char v6[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128 ")]; + } buf; + struct cidr *next; +}; + +void cidr_push(struct cidr *a); +bool cidr_pop(struct cidr *a); + +struct cidr * cidr_parse4(const char *s); +bool cidr_add4(struct cidr *a, struct cidr *b); +bool cidr_sub4(struct cidr *a, struct cidr *b); +bool cidr_network4(struct cidr *a); +bool cidr_broadcast4(struct cidr *a); +bool cidr_contains4(struct cidr *a, struct cidr *b); +bool cidr_netmask4(struct cidr *a); +bool cidr_private4(struct cidr *a); +bool cidr_linklocal4(struct cidr *a); +bool cidr_prev4(struct cidr *a, struct cidr *b); +bool cidr_next4(struct cidr *a, struct cidr *b); +bool cidr_6to4(struct cidr *a); +bool cidr_print4(struct cidr *a); +struct cidr * cidr_parse6(const char *s); +bool cidr_add6(struct cidr *a, struct cidr *b); +bool cidr_sub6(struct cidr *a, struct cidr *b); +bool cidr_prev6(struct cidr *a, struct cidr *b); +bool cidr_next6(struct cidr *a, struct cidr *b); +bool cidr_network6(struct cidr *a); +bool cidr_contains6(struct cidr *a, struct cidr *b); +bool cidr_linklocal6(struct cidr *a); +bool cidr_ula6(struct cidr *a); +bool cidr_print6(struct cidr *a); +struct cidr * cidr_parse(const char *op, const char *s, int af_hint); +bool cidr_howmany(struct cidr *a, struct cidr *b); +bool cidr_prefix(struct cidr *a, struct cidr *b); +bool cidr_quiet(struct cidr *a); + +extern struct cidr *stack; +extern bool quiet; +extern bool printed; + +#endif