Changeset 32785


Ignore:
Timestamp:
2012-07-20T15:43:10+02:00 (6 years ago)
Author:
jow
Message:

[package] owipcalc: add new operations "next", "prev", "6to4" and "pop", implement a stack for intermediate results

Location:
trunk/package/owipcalc
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/owipcalc/Makefile

    r32782 r32785  
    88 
    99PKG_NAME:=owipcalc 
    10 PKG_RELEASE:=2 
     10PKG_RELEASE:=3 
    1111 
    1212include $(INCLUDE_DIR)/package.mk 
  • trunk/package/owipcalc/src/owipcalc.c

    r32782 r32785  
    3737        union { 
    3838                char v4[sizeof("255.255.255.255/255.255.255.255 ")]; 
    39                 char v6[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF/128 ")]; 
     39                char v6[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128 ")]; 
    4040        } buf; 
     41        struct cidr *next; 
    4142}; 
    4243 
     
    5859static bool printed = false; 
    5960 
     61static struct cidr *stack = NULL; 
     62 
     63#define qprintf(...) \ 
     64        do { \ 
     65                if (!quiet) printf(__VA_ARGS__); \ 
     66                printed = true; \ 
     67        } while(0) 
     68 
     69static void cidr_push(struct cidr *a) 
     70{ 
     71        if (a) 
     72        { 
     73                a->next = stack; 
     74                stack = a; 
     75        } 
     76} 
     77 
     78static bool cidr_pop(struct cidr *a) 
     79{ 
     80        struct cidr *old = stack; 
     81 
     82        if (old) 
     83        { 
     84                stack = stack->next; 
     85                free(old); 
     86 
     87                return true; 
     88        } 
     89 
     90        return false; 
     91} 
     92 
     93static struct cidr * cidr_clone(struct cidr *a) 
     94{ 
     95        struct cidr *b = malloc(sizeof(*b)); 
     96 
     97        if (!b) 
     98        { 
     99                fprintf(stderr, "out of memory\n"); 
     100                exit(255); 
     101        } 
     102 
     103        memcpy(b, a, sizeof(*b)); 
     104        cidr_push(b); 
     105 
     106        return b; 
     107} 
     108 
    60109 
    61110static struct cidr * cidr_parse4(const char *s) 
     
    116165        uint32_t y = ntohl(b->addr.v4.s_addr); 
    117166 
    118         if ((a->family != AF_INET) || (b->family != AF_INET)) 
     167        struct cidr *n = cidr_clone(a); 
     168 
     169        if ((n->family != AF_INET) || (b->family != AF_INET)) 
    119170                return false; 
    120171 
     
    125176        } 
    126177 
    127         a->addr.v4.s_addr = htonl(x + y); 
     178        n->addr.v4.s_addr = htonl(x + y); 
    128179        return true; 
    129180} 
     
    134185        uint32_t y = ntohl(b->addr.v4.s_addr); 
    135186 
    136         if ((a->family != AF_INET) || (b->family != AF_INET)) 
     187        struct cidr *n = cidr_clone(a); 
     188 
     189        if ((n->family != AF_INET) || (b->family != AF_INET)) 
    137190                return false; 
    138191 
     
    143196        } 
    144197 
    145         a->addr.v4.s_addr = htonl(x - y); 
     198        n->addr.v4.s_addr = htonl(x - y); 
    146199        return true; 
    147200} 
     
    149202static bool cidr_network4(struct cidr *a) 
    150203{ 
    151         a->addr.v4.s_addr &= htonl(~((1 << (32 - a->prefix)) - 1)); 
    152         a->prefix = 32; 
     204        struct cidr *n = cidr_clone(a); 
     205 
     206        n->addr.v4.s_addr &= htonl(~((1 << (32 - n->prefix)) - 1)); 
     207        n->prefix = 32; 
     208 
    153209        return true; 
    154210} 
     
    156212static bool cidr_broadcast4(struct cidr *a) 
    157213{ 
    158         a->addr.v4.s_addr |= htonl(((1 << (32 - a->prefix)) - 1)); 
    159         a->prefix = 32; 
     214        struct cidr *n = cidr_clone(a); 
     215 
     216        n->addr.v4.s_addr |= htonl(((1 << (32 - n->prefix)) - 1)); 
     217        n->prefix = 32; 
     218 
    160219        return true; 
    161220} 
     
    166225        uint32_t net2 = b->addr.v4.s_addr & htonl(~((1 << (32 - a->prefix)) - 1)); 
    167226 
    168         printed = true; 
    169  
    170227        if ((b->prefix >= a->prefix) && (net1 == net2)) 
    171228        { 
    172                 if (!quiet) printf("1\n"); 
     229                qprintf("1\n"); 
    173230                return true; 
    174231        } 
    175232        else 
    176233        { 
    177                 if (!quiet) printf("0\n"); 
     234                qprintf("0\n"); 
    178235                return false; 
    179236        } 
     
    182239static bool cidr_netmask4(struct cidr *a) 
    183240{ 
    184         struct in_addr mask; 
    185         char buf[sizeof("255.255.255.255 ")]; 
    186  
    187         mask.s_addr = htonl(~((1 << (32 - a->prefix)) - 1)); 
    188  
    189         if (!quiet) 
    190                 printf("%s\n", inet_ntop(AF_INET, &mask, buf, sizeof(buf))); 
    191  
    192         printed = true; 
     241        struct cidr *n = cidr_clone(a); 
     242 
     243        n->addr.v4.s_addr = htonl(~((1 << (32 - n->prefix)) - 1)); 
     244        n->prefix = 32; 
    193245 
    194246        return true; 
     
    198250{ 
    199251        uint32_t x = ntohl(a->addr.v4.s_addr); 
    200  
    201         printed = true; 
    202252 
    203253        if (((x >= 0x0A000000) && (x <= 0x0AFFFFFF)) || 
     
    205255            ((x >= 0xC0A80000) && (x <= 0xC0A8FFFF))) 
    206256        { 
    207                 if (!quiet) printf("1\n"); 
     257                qprintf("1\n"); 
    208258                return true; 
    209259        } 
    210260        else 
    211261        { 
    212                 if (!quiet) printf("0\n"); 
     262                qprintf("0\n"); 
    213263                return false; 
    214264        } 
     
    219269        uint32_t x = ntohl(a->addr.v4.s_addr); 
    220270 
    221         printed = true; 
    222  
    223271        if ((x >= 0xA9FE0000) && (x <= 0xA9FEFFFF)) 
    224272        { 
    225                 if (!quiet) printf("1\n"); 
     273                qprintf("1\n"); 
    226274                return true; 
    227275        } 
    228276        else 
    229277        { 
    230                 if (!quiet) printf("0\n"); 
    231                 return false; 
    232         } 
     278                qprintf("0\n"); 
     279                return false; 
     280        } 
     281} 
     282 
     283static bool cidr_prev4(struct cidr *a, struct cidr *b) 
     284{ 
     285        struct cidr *n = cidr_clone(a); 
     286 
     287        n->prefix = b->prefix; 
     288        n->addr.v4.s_addr -= htonl(1 << (32 - b->prefix)); 
     289 
     290        return true; 
     291} 
     292 
     293static bool cidr_next4(struct cidr *a, struct cidr *b) 
     294{ 
     295        struct cidr *n = cidr_clone(a); 
     296 
     297        n->prefix = b->prefix; 
     298        n->addr.v4.s_addr += htonl(1 << (32 - b->prefix)); 
     299 
     300        return true; 
     301} 
     302 
     303static bool cidr_6to4(struct cidr *a) 
     304{ 
     305        struct cidr *n = cidr_clone(a); 
     306        uint32_t x = a->addr.v4.s_addr; 
     307 
     308        memset(&n->addr.v6.s6_addr, 0, sizeof(n->addr.v6.s6_addr)); 
     309 
     310        n->family = AF_INET6; 
     311        n->prefix = 48; 
     312 
     313        n->addr.v6.s6_addr[0] = 0x20; 
     314        n->addr.v6.s6_addr[1] = 0x02; 
     315        n->addr.v6.s6_addr[2] = (x >> 24); 
     316        n->addr.v6.s6_addr[3] = (x >> 16) & 0xFF; 
     317        n->addr.v6.s6_addr[4] = (x >>  8) & 0xFF; 
     318        n->addr.v6.s6_addr[5] = x & 0xFF; 
     319 
     320        return true; 
    233321} 
    234322 
     
    237325        char *p; 
    238326 
    239         if (a->family != AF_INET) 
     327        if (!a || (a->family != AF_INET)) 
    240328                return false; 
    241329 
     
    243331                return false; 
    244332 
    245         if (!quiet) 
    246                 printf("%s", p); 
    247  
    248         if (!quiet && (a->prefix < 32)) 
    249                 printf("/%u", a->prefix); 
    250  
    251         if (!quiet) 
    252                 printf("\n"); 
    253  
    254         printed = true; 
     333        if (printed) 
     334                qprintf(" "); 
     335 
     336        qprintf("%s", p); 
     337 
     338        if (a->prefix < 32) 
     339                qprintf("/%u", a->prefix); 
     340 
     341        cidr_pop(a); 
    255342 
    256343        return true; 
     
    266353                goto err; 
    267354 
    268         snprintf(addr->buf.v6, sizeof(addr->buf.v6), "%s", s); 
     355        snprintf(addr->buf.v4, sizeof(addr->buf.v6), "%s", s); 
    269356 
    270357        addr->family = AF_INET6; 
    271358 
    272         if ((p = strchr(addr->buf.v6, '/')) != NULL) 
     359        if ((p = strchr(addr->buf.v4, '/')) != NULL) 
    273360        { 
    274361                *p++ = 0; 
     
    284371        } 
    285372 
    286         if (p == addr->buf.v6+1) 
     373        if (p == addr->buf.v4+1) 
    287374                memset(&addr->addr.v6, 0, sizeof(addr->addr.v6)); 
    288         else if (inet_pton(AF_INET6, addr->buf.v6, &addr->addr.v6) != 1) 
     375        else if (inet_pton(AF_INET6, addr->buf.v4, &addr->addr.v6) != 1) 
    289376                goto err; 
    290377 
     
    302389        uint8_t idx = 15, carry = 0, overflow = 0; 
    303390 
    304         struct in6_addr *x = &a->addr.v6; 
     391        struct cidr *n = cidr_clone(a); 
     392        struct in6_addr *x = &n->addr.v6; 
    305393        struct in6_addr *y = &b->addr.v6; 
    306394 
     
    328416        uint8_t idx = 15, carry = 0, underflow = 0; 
    329417 
    330         struct in6_addr *x = &a->addr.v6; 
     418        struct cidr *n = cidr_clone(a); 
     419        struct in6_addr *x = &n->addr.v6; 
    331420        struct in6_addr *y = &b->addr.v6; 
    332421 
    333         if ((a->family != AF_INET6) || (b->family != AF_INET6)) 
     422        if ((n->family != AF_INET6) || (b->family != AF_INET6)) 
    334423                return false; 
    335424 
     
    350439} 
    351440 
     441static bool cidr_prev6(struct cidr *a, struct cidr *b) 
     442{ 
     443        uint8_t idx, carry = 1, underflow = 0; 
     444        struct cidr *n = cidr_clone(a); 
     445        struct in6_addr *x = &n->addr.v6; 
     446 
     447        if (b->prefix == 0) 
     448        { 
     449                fprintf(stderr, "underflow during 'prev'\n"); 
     450                return false; 
     451        } 
     452 
     453        idx = (b->prefix - 1) / 8; 
     454 
     455        do { 
     456                underflow = !!((x->s6_addr[idx] - carry) < 0); 
     457                x->s6_addr[idx] -= carry; 
     458                carry = underflow; 
     459        } 
     460        while (idx-- > 0); 
     461 
     462        if (carry) 
     463        { 
     464                fprintf(stderr, "underflow during 'prev'\n"); 
     465                return false; 
     466        } 
     467 
     468        n->prefix = b->prefix; 
     469 
     470        return true; 
     471} 
     472 
     473static bool cidr_next6(struct cidr *a, struct cidr *b) 
     474{ 
     475        uint8_t idx, carry = 1, overflow = 0; 
     476        struct cidr *n = cidr_clone(a); 
     477        struct in6_addr *x = &n->addr.v6; 
     478 
     479        if (b->prefix == 0) 
     480        { 
     481                fprintf(stderr, "overflow during 'next'\n"); 
     482                return false; 
     483        } 
     484 
     485        idx = (b->prefix - 1) / 8; 
     486 
     487        do { 
     488                overflow = !!((x->s6_addr[idx] + carry) >= 256); 
     489                x->s6_addr[idx] += carry; 
     490                carry = overflow; 
     491        } 
     492        while (idx-- > 0); 
     493 
     494        if (carry) 
     495        { 
     496                fprintf(stderr, "overflow during 'next'\n"); 
     497                return false; 
     498        } 
     499 
     500        n->prefix = b->prefix; 
     501 
     502        return true; 
     503} 
     504 
    352505static bool cidr_network6(struct cidr *a) 
    353506{ 
    354507        uint8_t i; 
    355  
    356         for (i = 0; i < (128 - a->prefix) / 8; i++) 
    357                 a->addr.v6.s6_addr[15-i] = 0; 
    358  
    359         if ((128 - a->prefix) % 8) 
    360                 a->addr.v6.s6_addr[15-i] &= ~((1 << ((128 - a->prefix) % 8)) - 1); 
     508        struct cidr *n = cidr_clone(a); 
     509 
     510        for (i = 0; i < (128 - n->prefix) / 8; i++) 
     511                n->addr.v6.s6_addr[15-i] = 0; 
     512 
     513        if ((128 - n->prefix) % 8) 
     514                n->addr.v6.s6_addr[15-i] &= ~((1 << ((128 - n->prefix) % 8)) - 1); 
    361515 
    362516        return true; 
     
    365519static bool cidr_contains6(struct cidr *a, struct cidr *b) 
    366520{ 
    367         struct in6_addr *x = &a->addr.v6; 
     521        struct cidr *n = cidr_clone(a); 
     522        struct in6_addr *x = &n->addr.v6; 
    368523        struct in6_addr *y = &b->addr.v6; 
    369  
    370         uint8_t i = (128 - a->prefix) / 8; 
    371         uint8_t m = ~((1 << ((128 - a->prefix) % 8)) - 1); 
     524        uint8_t i = (128 - n->prefix) / 8; 
     525        uint8_t m = ~((1 << ((128 - n->prefix) % 8)) - 1); 
    372526        uint8_t net1 = x->s6_addr[15-i] & m; 
    373527        uint8_t net2 = y->s6_addr[15-i] & m; 
    374528 
    375         printed = true; 
    376  
    377         if ((b->prefix >= a->prefix) && (net1 == net2) && 
     529        if ((b->prefix >= n->prefix) && (net1 == net2) && 
    378530            ((i == 15) || !memcmp(&x->s6_addr, &y->s6_addr, 15-i))) 
    379531        { 
    380                 if (!quiet) printf("1\n"); 
     532                qprintf("1\n"); 
    381533                return true; 
    382534        } 
    383535        else 
    384536        { 
    385                 if (!quiet) printf("0\n"); 
     537                qprintf("0\n"); 
    386538                return false; 
    387539        } 
     
    390542static bool cidr_linklocal6(struct cidr *a) 
    391543{ 
    392         printed = true; 
    393  
    394544        if ((a->addr.v6.s6_addr[0] == 0xFE) && 
    395545            (a->addr.v6.s6_addr[1] >= 0x80) && 
    396546            (a->addr.v6.s6_addr[1] <= 0xBF)) 
    397547        { 
    398                 if (!quiet) printf("1\n"); 
     548                qprintf("1\n"); 
    399549                return true; 
    400550        } 
    401551        else 
    402552        { 
    403                 if (!quiet) printf("0\n"); 
     553                qprintf("0\n"); 
    404554                return false; 
    405555        } 
     
    408558static bool cidr_ula6(struct cidr *a) 
    409559{ 
    410         printed = true; 
    411  
    412560        if ((a->addr.v6.s6_addr[0] >= 0xFC) && 
    413561            (a->addr.v6.s6_addr[0] <= 0xFD)) 
    414562        { 
    415                 if (!quiet) printf("1\n"); 
     563                qprintf("1\n"); 
    416564                return true; 
    417565        } 
    418566        else 
    419567        { 
    420                 if (!quiet) printf("0\n"); 
     568                qprintf("0\n"); 
    421569                return false; 
    422570        } 
     
    427575        char *p; 
    428576 
    429         if (a->family != AF_INET6) 
     577        if (!a || (a->family != AF_INET6)) 
    430578                return NULL; 
    431579 
     
    433581                return false; 
    434582 
    435         if (!quiet) 
    436                 printf("%s", p); 
    437  
    438         if (!quiet && (a->prefix < 128)) 
    439                 printf("/%u", a->prefix); 
    440  
    441         if (!quiet) 
    442                 printf("\n"); 
    443  
    444         printed = true; 
     583        if (printed) 
     584                qprintf(" "); 
     585 
     586        qprintf("%s", p); 
     587 
     588        if (a->prefix < 128) 
     589                qprintf("/%u", a->prefix); 
     590 
     591        cidr_pop(a); 
    445592 
    446593        return true; 
     
    466613                { 
    467614                        a->family = AF_INET; 
    468                         a->prefix = 32; 
     615                        a->prefix = sum; 
    469616                        a->addr.v4.s_addr = htonl(sum); 
    470617                } 
     
    472619                { 
    473620                        a->family = AF_INET6; 
    474                         a->prefix = 128; 
     621                        a->prefix = sum; 
    475622 
    476623                        for (i = 0; i <= 15; i++) 
     
    506653static bool cidr_howmany(struct cidr *a, struct cidr *b) 
    507654{ 
    508         if (!quiet) 
    509         { 
    510                 if (b->prefix < a->prefix) 
    511                         printf("0\n"); 
    512                 else 
    513                         printf("%u\n", 1 << (b->prefix - a->prefix)); 
    514         } 
    515  
    516         printed = true; 
     655        if (b->prefix < a->prefix) 
     656                qprintf("0\n"); 
     657        else 
     658                qprintf("%u\n", 1 << (b->prefix - a->prefix)); 
    517659 
    518660        return true; 
     
    543685          .f6.a2 = cidr_sub6 }, 
    544686 
     687        { .name = "next", 
     688          .desc = "Advance base address to next prefix of given size", 
     689          .f4.a2 = cidr_next4, 
     690          .f6.a2 = cidr_next6 }, 
     691 
     692        { .name = "prev", 
     693          .desc = "Lower base address to previous prefix of give size", 
     694          .f4.a2 = cidr_prev4, 
     695          .f6.a2 = cidr_prev6 }, 
     696 
    545697        { .name = "network", 
    546698          .desc = "Turn base address into network address", 
     
    558710 
    559711        { .name = "netmask", 
    560           .desc = "Print netmask of base address, does not change base address", 
     712          .desc = "Calculate netmask of base address", 
    561713          .f4.a1 = cidr_netmask4 }, 
    562714 
     715        { .name = "6to4", 
     716          .desc = "Calculate 6to4 prefix of given ipv4-address", 
     717          .f4.a1 = cidr_6to4 }, 
     718 
    563719        { .name = "howmany", 
    564           .desc = "Print amount of righ-hand prefixes that fit into base address, " 
    565                   "does not change base address", 
     720          .desc = "Print amount of righ-hand prefixes that fit into base address", 
    566721          .f4.a2 = cidr_howmany, 
    567722          .f6.a2 = cidr_howmany }, 
    568723 
    569724        { .name = "contains", 
    570           .desc = "Print '1' if argument fits into base address or '0' " 
    571                   "if not, does not change base address", 
     725          .desc = "Print '1' if argument fits into base address or '0' if not", 
    572726          .f4.a2 = cidr_contains4, 
    573727          .f6.a2 = cidr_contains6 }, 
     
    575729        { .name = "private", 
    576730          .desc = "Print '1' if base address is in RFC1918 private space or '0' " 
    577                   "if not, does not change base address", 
     731                  "if not", 
    578732          .f4.a1 = cidr_private4 }, 
    579733 
    580734        { .name = "linklocal", 
    581735          .desc = "Print '1' if base address is in 169.254.0.0/16 or FE80::/10 " 
    582                   "link local space or '0' if not, does not change base address", 
     736                  "link local space or '0' if not", 
    583737          .f4.a1 = cidr_linklocal4, 
    584738          .f6.a1 = cidr_linklocal6 }, 
     
    586740        { .name = "ula", 
    587741          .desc = "Print '1' if base address is in FC00::/7 unique local address " 
    588                   "(ULA) space or '0' if not, does not change base address", 
     742                  "(ULA) space or '0' if not", 
    589743          .f6.a1 = cidr_ula6 }, 
    590744 
    591745        { .name = "quiet", 
    592746          .desc = "Suppress output, useful for test operation where the result can " 
    593                   "be inferred from the exit code, does not change base address", 
     747                  "be inferred from the exit code", 
    594748          .f4.a1 = cidr_quiet, 
    595749          .f6.a1 = cidr_quiet }, 
    596750 
     751        { .name = "pop", 
     752          .desc = "Pop intermediate result from stack", 
     753          .f4.a1 = cidr_pop, 
     754          .f6.a1 = cidr_pop }, 
     755 
    597756        { .name = "print", 
    598           .desc = "Print intermediate result, invoked implicitely at the end of " 
    599                   "calculation if no intermediate prints happened", 
     757          .desc = "Print intermediate result and pop it from stack, invoked " 
     758                  "implicitely at the end of calculation if no intermediate prints " 
     759                  "happened", 
    600760          .f4.a1 = cidr_print4, 
    601761          .f6.a1 = cidr_print6 }, 
     
    652812} 
    653813 
    654 static bool runop(struct cidr *a, char ***arg, int *status) 
     814static bool runop(char ***arg, int *status) 
    655815{ 
    656816        int i; 
    657817        char *arg1 = **arg; 
    658818        char *arg2 = *(*arg+1); 
     819        struct cidr *a = stack; 
    659820        struct cidr *b = NULL; 
    660821 
     
    746907                usage(argv[0]); 
    747908 
    748         while (runop(a, &arg, &status)); 
     909        cidr_push(a); 
     910 
     911        while (runop(&arg, &status)); 
    749912 
    750913        if (*arg) 
     
    756919        if (!printed && (status < 2)) 
    757920        { 
    758                 if (a->family == AF_INET) 
    759                         cidr_print4(a); 
     921                if (stack->family == AF_INET) 
     922                        cidr_print4(stack); 
    760923                else 
    761                         cidr_print6(a); 
    762         } 
     924                        cidr_print6(stack); 
     925        } 
     926 
     927        qprintf("\n"); 
    763928 
    764929        exit(status); 
Note: See TracChangeset for help on using the changeset viewer.