From: Guus Sliepen Date: Tue, 27 Jul 2021 12:46:17 +0000 (+0200) Subject: Use inet_pton() to parse Subnets. X-Git-Url: https://tinc-vpn.org/git/browse?a=commitdiff_plain;h=f7f7d8b15e12471c95bbd291195e83c5126a0631;p=tinc Use inet_pton() to parse Subnets. Nowadays all operating systems tinc runs on should support IPv6, so we can rely on inet_pton() and inet_ntop() to convert IPv4 and IPv6 addresses. Use this instead of our own parsing code. --- diff --git a/src/subnet.c b/src/subnet.c index 154fd804..da69810c 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -205,7 +205,7 @@ void subnet_del(node_t *n, subnet_t *subnet) { /* Ascii representation of subnets */ bool str2net(subnet_t *subnet, const char *subnetstr) { - char str[1024]; + char str[64]; strncpy(str, subnetstr, sizeof(str)); str[sizeof(str) - 1] = 0; int consumed; @@ -270,7 +270,7 @@ bool str2net(subnet_t *subnet, const char *subnetstr) { return true; } - if(sscanf(str, "%hu.%hu.%hu.%hu%n", &x[0], &x[1], &x[2], &x[3], &consumed) >= 4 && !str[consumed]) { + if(inet_pton(AF_INET, str, &subnet->net.ipv4.address)) { if(prefixlength == -1) { prefixlength = 32; } @@ -283,71 +283,10 @@ bool str2net(subnet_t *subnet, const char *subnetstr) { subnet->net.ipv4.prefixlength = prefixlength; subnet->weight = weight; - for(int i = 0; i < 4; i++) { - if(x[i] > 255) { - return false; - } - - subnet->net.ipv4.address.x[i] = x[i]; - } - return true; } - /* IPv6 */ - - char *last_colon = strrchr(str, ':'); - - if(last_colon && sscanf(last_colon, ":%hu.%hu.%hu.%hu%n", &x[0], &x[1], &x[2], &x[3], &consumed) >= 4 && !last_colon[consumed]) { - /* Dotted quad suffix notation, convert to standard IPv6 notation */ - for(int i = 0; i < 4; i++) - if(x[i] > 255) { - return false; - } - - snprintf(last_colon, sizeof(str) - (last_colon - str), ":%02x%02x:%02x%02x", x[0], x[1], x[2], x[3]); - } - - char *double_colon = strstr(str, "::"); - - if(double_colon) { - /* Figure out how many zero groups we need to expand */ - int zero_group_count = 8; - - for(const char *cur = str; *cur; cur++) - if(*cur != ':') { - zero_group_count--; - - while(cur[1] && cur[1] != ':') { - cur++; - } - } - - if(zero_group_count < 1) { - return false; - } - - /* Split the double colon in the middle to make room for zero groups */ - double_colon++; - memmove(double_colon + (zero_group_count * 2 - 1), double_colon, strlen(double_colon) + 1); - - /* Write zero groups in the resulting gap, overwriting the second colon */ - for(int i = 0; i < zero_group_count; i++) { - memcpy(&double_colon[i * 2], "0:", 2); - } - - /* Remove any leading or trailing colons */ - if(str[0] == ':') { - memmove(&str[0], &str[1], strlen(&str[1]) + 1); - } - - if(str[strlen(str) - 1] == ':') { - str[strlen(str) - 1] = 0; - } - } - - if(sscanf(str, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx%n", - &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], &consumed) >= 8 && !str[consumed]) { + if(inet_pton(AF_INET6, str, &subnet->net.ipv6.address)) { if(prefixlength == -1) { prefixlength = 128; } @@ -360,10 +299,6 @@ bool str2net(subnet_t *subnet, const char *subnetstr) { subnet->net.ipv6.prefixlength = prefixlength; subnet->weight = weight; - for(int i = 0; i < 8; i++) { - subnet->net.ipv6.address.x[i] = htons(x[i]); - } - return true; } @@ -376,47 +311,58 @@ bool net2str(char *netstr, int len, const subnet_t *subnet) { return false; } + int result; + int prefixlength = -1; + switch(subnet->type) { case SUBNET_MAC: - snprintf(netstr, len, "%x:%x:%x:%x:%x:%x#%d", + snprintf(netstr, len, "%02x:%02x:%02x:%02x:%02x:%02x", subnet->net.mac.address.x[0], subnet->net.mac.address.x[1], subnet->net.mac.address.x[2], subnet->net.mac.address.x[3], subnet->net.mac.address.x[4], - subnet->net.mac.address.x[5], - subnet->weight); + subnet->net.mac.address.x[5]); break; case SUBNET_IPV4: - snprintf(netstr, len, "%u.%u.%u.%u/%d#%d", - subnet->net.ipv4.address.x[0], - subnet->net.ipv4.address.x[1], - subnet->net.ipv4.address.x[2], - subnet->net.ipv4.address.x[3], - subnet->net.ipv4.prefixlength, - subnet->weight); + inet_ntop(AF_INET, &subnet->net.ipv4.address, netstr, len); + prefixlength = subnet->net.ipv4.prefixlength; + + if(prefixlength == 32) { + prefixlength = -1; + } + break; - case SUBNET_IPV6: - snprintf(netstr, len, "%x:%x:%x:%x:%x:%x:%x:%x/%d#%d", - ntohs(subnet->net.ipv6.address.x[0]), - ntohs(subnet->net.ipv6.address.x[1]), - ntohs(subnet->net.ipv6.address.x[2]), - ntohs(subnet->net.ipv6.address.x[3]), - ntohs(subnet->net.ipv6.address.x[4]), - ntohs(subnet->net.ipv6.address.x[5]), - ntohs(subnet->net.ipv6.address.x[6]), - ntohs(subnet->net.ipv6.address.x[7]), - subnet->net.ipv6.prefixlength, - subnet->weight); + case SUBNET_IPV6: { + inet_ntop(AF_INET6, &subnet->net.ipv6.address, netstr, len); + prefixlength = subnet->net.ipv6.prefixlength; + + if(prefixlength == 128) { + prefixlength = -1; + } + break; + } default: - logger(LOG_ERR, - "net2str() was called with unknown subnet type %d, exiting!", - subnet->type); - exit(0); + logger(LOG_ERR, "net2str() was called with unknown subnet type %d, exiting!", subnet->type); + exit(1); + } + + size_t used = strlen(netstr); + netstr += used; + len -= used; + + if(prefixlength >= 0) { + result = snprintf(netstr, len, "/%d", prefixlength); + netstr += result; + len -= result; + } + + if(subnet->weight != 10) { + snprintf(netstr, len, "#%d", subnet->weight); } return true;