]> git.meshlink.io Git - meshlink/blobdiff - src/subnet.c
Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1
[meshlink] / src / subnet.c
index 2c67dcc1c07115798f89c7963a4854a609c62f23..63d169fe2e4abac6ec263827b6e11b536b401be4 100644 (file)
@@ -135,7 +135,7 @@ int subnet_compare(const subnet_t *a, const subnet_t *b) {
        case SUBNET_IPV6:
                return subnet_compare_ipv6(a, b);
        default:
-               logger(LOG_ERR, "subnet_compare() was called with unknown subnet type %d, exitting!",
+               logger(DEBUG_ALWAYS, LOG_ERR, "subnet_compare() was called with unknown subnet type %d, exitting!",
                           a->type);
                exit(0);
        }
@@ -269,12 +269,84 @@ bool str2net(subnet_t *subnet, const char *subnetstr) {
                return true;
        }
 
+       // IPv6 short form
+       if(strstr(subnetstr, "::")) {
+               const char *p;
+               char *q;
+               int colons = 0;
+
+               // Count number of colons
+               for(p = subnetstr; *p; p++)
+                       if(*p == ':')
+                               colons++;
+
+               if(colons > 7)
+                       return false;
+
+               // Scan numbers before the double colon
+               p = subnetstr;
+               for(i = 0; i < colons; i++) {
+                       if(*p == ':')
+                               break;
+                       x[i] = strtoul(p, &q, 0x10);
+                       if(!q || p == q || *q != ':')
+                               return false;
+                       p = ++q;
+               }
+
+               p++;
+               colons -= i;
+               if(!i) {
+                       p++;
+                       colons--;
+               }
+
+               if(!*p || *p == '/' || *p == '#')
+                       colons--;
+
+               // Fill in the blanks
+               for(; i < 8 - colons; i++)
+                       x[i] = 0;
+
+               // Scan the remaining numbers
+               for(; i < 8; i++) {
+                       x[i] = strtoul(p, &q, 0x10);
+                       if(!q || p == q)
+                               return false;
+                       if(i == 7) {
+                               p = q;
+                               break;
+                       }
+                       if(*q != ':')
+                               return false;
+                       p = ++q;
+               }
+
+               l = 128;
+               if(*p == '/')
+                       sscanf(p, "/%d#%d", &l, &weight);
+               else if(*p == '#')
+                       sscanf(p, "#%d", &weight);
+
+               if(l < 0 || l > 128)
+                       return false;
+
+               subnet->type = SUBNET_IPV6;
+               subnet->net.ipv6.prefixlength = l;
+               subnet->weight = weight;
+
+               for(i = 0; i < 8; i++)
+                       subnet->net.ipv6.address.x[i] = htons(x[i]);
+
+               return true;
+       }
+
        return false;
 }
 
 bool net2str(char *netstr, int len, const subnet_t *subnet) {
        if(!netstr || !subnet) {
-               logger(LOG_ERR, "net2str() was called with netstr=%p, subnet=%p!", netstr, subnet);
+               logger(DEBUG_ALWAYS, LOG_ERR, "net2str() was called with netstr=%p, subnet=%p!", netstr, subnet);
                return false;
        }
 
@@ -315,7 +387,7 @@ bool net2str(char *netstr, int len, const subnet_t *subnet) {
                        break;
 
                default:
-                       logger(LOG_ERR,
+                       logger(DEBUG_ALWAYS, LOG_ERR,
                                   "net2str() was called with unknown subnet type %d, exiting!",
                                   subnet->type);
                        exit(0);