Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/inet/addr.c

    rbb9b0c6 r3495654  
    3434
    3535#include <errno.h>
    36 #include <unistd.h>
    37 #include <net/socket_codes.h>
    3836#include <inet/addr.h>
    39 #include <net/inet.h>
    4037#include <stdio.h>
    41 #include <malloc.h>
    42 #include <bitops.h>
    4338
    44 #define INET_PREFIXSTRSIZE  5
     39/** Parse network address.
     40 *
     41 * @param text  Network address in CIDR notation (a.b.c.d/w)
     42 * @param naddr Place to store network address
     43 *
     44 * @return      EOK on success, EINVAL if input is not in valid format
     45 */
     46int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
     47{
     48        unsigned long a[4], bits;
     49        char *cp = (char *)text;
     50        int i;
    4551
    46 #if !(defined(__BE__) ^ defined(__LE__))
    47         #error The architecture must be either big-endian or little-endian.
    48 #endif
     52        for (i = 0; i < 3; i++) {
     53                a[i] = strtoul(cp, &cp, 10);
     54                if (*cp != '.')
     55                        return EINVAL;
     56                ++cp;
     57        }
    4958
    50 const addr48_t addr48_broadcast = {
    51         0xff, 0xff, 0xff, 0xff, 0xff, 0xff
    52 };
     59        a[3] = strtoul(cp, &cp, 10);
     60        if (*cp != '/')
     61                return EINVAL;
     62        ++cp;
    5363
    54 static const inet_addr_t inet_addr_any_addr = {
    55         .family = AF_INET,
    56         .addr = 0
    57 };
     64        bits = strtoul(cp, &cp, 10);
     65        if (*cp != '\0')
     66                return EINVAL;
    5867
    59 static const inet_addr_t inet_addr_any_addr6 = {
    60         .family = AF_INET6,
    61         .addr6 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    62 };
     68        naddr->ipv4 = 0;
     69        for (i = 0; i < 4; i++) {
     70                if (a[i] > 255)
     71                        return EINVAL;
     72                naddr->ipv4 = (naddr->ipv4 << 8) | a[i];
     73        }
    6374
    64 void addr48(const addr48_t src, addr48_t dst)
    65 {
    66         memcpy(dst, src, 6);
    67 }
     75        if (bits > 31)
     76                return EINVAL;
    6877
    69 void addr128(const addr128_t src, addr128_t dst)
    70 {
    71         memcpy(dst, src, 16);
    72 }
    73 
    74 int addr128_compare(const addr128_t a, const addr128_t b)
    75 {
    76         return memcmp(a, b, 16);
    77 }
    78 
    79 void host2addr128_t_be(const addr128_t host, addr128_t be)
    80 {
    81 #ifdef __BE__
    82         memcpy(be, host, 16);
    83 #else
    84         be[0] = host[15];
    85         be[1] = host[14];
    86         be[2] = host[13];
    87         be[3] = host[12];
    88         be[4] = host[11];
    89         be[5] = host[10];
    90         be[6] = host[9];
    91         be[7] = host[8];
    92         be[8] = host[7];
    93         be[9] = host[6];
    94         be[10] = host[5];
    95         be[11] = host[4];
    96         be[12] = host[3];
    97         be[13] = host[2];
    98         be[14] = host[1];
    99         be[15] = host[0];
    100 #endif
    101 }
    102 
    103 void addr128_t_be2host(const addr128_t be, addr128_t host)
    104 {
    105 #ifdef __BE__
    106         memcpy(host, be, 16);
    107 #else
    108         host[0] = be[15];
    109         host[1] = be[14];
    110         host[2] = be[13];
    111         host[3] = be[12];
    112         host[4] = be[11];
    113         host[5] = be[10];
    114         host[6] = be[9];
    115         host[7] = be[8];
    116         host[8] = be[7];
    117         host[9] = be[6];
    118         host[10] = be[5];
    119         host[11] = be[4];
    120         host[12] = be[3];
    121         host[13] = be[2];
    122         host[14] = be[1];
    123         host[15] = be[0];
    124 #endif
    125 }
    126 
    127 void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
    128 {
    129         addr->family = AF_INET;
    130         addr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
    131             ((addr32_t) c << 8) | ((addr32_t) d);
    132 }
    133 
    134 void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d,
    135     uint8_t prefix)
    136 {
    137         naddr->family = AF_INET;
    138         naddr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
    139             ((addr32_t) c << 8) | ((addr32_t) d);
    140         naddr->prefix = prefix;
    141 }
    142 
    143 void inet_addr6(inet_addr_t *addr, uint16_t a, uint16_t b, uint16_t c,
    144     uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h)
    145 {
    146         addr->family = AF_INET6;
    147         addr->addr6[0] = (a >> 8) & 0xff;
    148         addr->addr6[1] = a & 0xff;
    149         addr->addr6[2] = (b >> 8) & 0xff;
    150         addr->addr6[3] = b & 0xff;
    151         addr->addr6[4] = (c >> 8) & 0xff;
    152         addr->addr6[5] = c & 0xff;
    153         addr->addr6[6] = (d >> 8) & 0xff;
    154         addr->addr6[7] = d & 0xff;
    155         addr->addr6[8] = (e >> 8) & 0xff;
    156         addr->addr6[9] = e & 0xff;
    157         addr->addr6[10] = (f >> 8) & 0xff;
    158         addr->addr6[11] = f & 0xff;
    159         addr->addr6[12] = (g >> 8) & 0xff;
    160         addr->addr6[13] = g & 0xff;
    161         addr->addr6[14] = (h >> 8) & 0xff;
    162         addr->addr6[15] = h & 0xff;
    163 }
    164 
    165 void inet_naddr6(inet_naddr_t *naddr, uint16_t a, uint16_t b, uint16_t c,
    166     uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h, uint8_t prefix)
    167 {
    168         naddr->family = AF_INET6;
    169         naddr->addr6[0] = (a >> 8) & 0xff;
    170         naddr->addr6[1] = a & 0xff;
    171         naddr->addr6[2] = (b >> 8) & 0xff;
    172         naddr->addr6[3] = b & 0xff;
    173         naddr->addr6[4] = (c >> 8) & 0xff;
    174         naddr->addr6[5] = c & 0xff;
    175         naddr->addr6[6] = (d >> 8) & 0xff;
    176         naddr->addr6[7] = d & 0xff;
    177         naddr->addr6[8] = (e >> 8) & 0xff;
    178         naddr->addr6[9] = e & 0xff;
    179         naddr->addr6[10] = (f >> 8) & 0xff;
    180         naddr->addr6[11] = f & 0xff;
    181         naddr->addr6[12] = (g >> 8) & 0xff;
    182         naddr->addr6[13] = g & 0xff;
    183         naddr->addr6[14] = (h >> 8) & 0xff;
    184         naddr->addr6[15] = h & 0xff;
    185         naddr->prefix = prefix;
    186 }
    187 
    188 /** Parse network address family.
    189  *
    190  * @param text Network address in common notation.
    191  * @param af   Place to store network address family.
    192  *
    193  * @return EOK on success, EINVAL if input is not in valid format.
    194  *
    195  */
    196 int inet_addr_family(const char *text, uint16_t *af)
    197 {
    198         char *dot = str_chr(text, '.');
    199         if (dot != NULL) {
    200                 *af = AF_INET;
    201                 return EOK;
    202         }
    203        
    204         char *collon = str_chr(text, ':');
    205         if (collon != NULL) {
    206                 *af = AF_INET6;
    207                 return EOK;
    208         }
    209        
    210         return EINVAL;
    211 }
    212 
    213 void inet_naddr_addr(const inet_naddr_t *naddr, inet_addr_t *addr)
    214 {
    215         addr->family = naddr->family;
    216         memcpy(addr->addr6, naddr->addr6, 16);
    217 }
    218 
    219 void inet_addr_naddr(const inet_addr_t *addr, uint8_t prefix,
    220     inet_naddr_t *naddr)
    221 {
    222         naddr->family = addr->family;
    223         memcpy(naddr->addr6, addr->addr6, 16);
    224         naddr->prefix = prefix;
    225 }
    226 
    227 void inet_addr_any(inet_addr_t *addr)
    228 {
    229         addr->family = AF_NONE;
    230         memset(addr->addr6, 0, 16);
    231 }
    232 
    233 void inet_naddr_any(inet_naddr_t *naddr)
    234 {
    235         naddr->family = AF_NONE;
    236         memset(naddr->addr6, 0, 16);
    237         naddr->prefix = 0;
    238 }
    239 
    240 int inet_addr_compare(const inet_addr_t *a, const inet_addr_t *b)
    241 {
    242         if (a->family != b->family)
    243                 return 0;
    244        
    245         switch (a->family) {
    246         case AF_INET:
    247                 return (a->addr == b->addr);
    248         case AF_INET6:
    249                 return addr128_compare(a->addr6, b->addr6);
    250         default:
    251                 return 0;
    252         }
    253 }
    254 
    255 int inet_addr_is_any(const inet_addr_t *addr)
    256 {
    257         return ((addr->family == 0) ||
    258             (inet_addr_compare(addr, &inet_addr_any_addr)) ||
    259             (inet_addr_compare(addr, &inet_addr_any_addr6)));
    260 }
    261 
    262 int inet_naddr_compare_mask(const inet_naddr_t *naddr, const inet_addr_t *addr)
    263 {
    264         if (naddr->family != addr->family)
    265                 return 0;
    266        
    267         switch (naddr->family) {
    268         case AF_INET:
    269                 if (naddr->prefix > 32)
    270                         return 0;
    271                
    272                 addr32_t mask =
    273                     BIT_RANGE(addr32_t, 31, 31 - (naddr->prefix - 1));
    274                 return ((naddr->addr & mask) == (addr->addr & mask));
    275         case AF_INET6:
    276                 if (naddr->prefix > 128)
    277                         return 0;
    278                
    279                 size_t pos = 0;
    280                 for (size_t i = 0; i < 16; i++) {
    281                         /* Further bits do not matter */
    282                         if (naddr->prefix < pos)
    283                                 break;
    284                        
    285                         if (naddr->prefix - pos > 8) {
    286                                 /* Comparison without masking */
    287                                 if (naddr->addr6[i] != addr->addr6[i])
    288                                         return 0;
    289                         } else {
    290                                 /* Comparison with masking */
    291                                 uint8_t mask =
    292                                     BIT_RANGE(uint8_t, 8, 8 - (naddr->prefix - pos - 1));
    293                                 if ((naddr->addr6[i] & mask) != (addr->addr6[i] & mask))
    294                                         return 0;
    295                         }
    296                        
    297                         pos += 8;
    298                 }
    299                
    300                 return 1;
    301         default:
    302                 return 0;
    303         }
     78        naddr->bits = bits;
     79        return EOK;
    30480}
    30581
    30682/** Parse node address.
    30783 *
    308  * @param text Network address in common notation.
    309  * @param addr Place to store node address.
     84 * @param text  Network address in dot notation (a.b.c.d)
     85 * @param addr  Place to store node address
    31086 *
    311  * @return EOK on success, EINVAL if input is not in valid format.
    312  *
     87 * @return      EOK on success, EINVAL if input is not in valid format
    31388 */
    31489int inet_addr_parse(const char *text, inet_addr_t *addr)
    31590{
    316         int rc = inet_addr_family(text, &addr->family);
    317         if (rc != EOK)
    318                 return rc;
    319        
    320         uint8_t buf[16];
    321         rc = inet_pton(addr->family, text, buf);
    322         if (rc != EOK)
    323                 return rc;
    324        
    325         switch (addr->family) {
    326         case AF_INET:
    327                 addr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
    328                     buf[3];
    329                 break;
    330         case AF_INET6:
    331                 memcpy(addr->addr6, buf, 16);
    332                 break;
    333         default:
     91        unsigned long a[4];
     92        char *cp = (char *)text;
     93        int i;
     94
     95        for (i = 0; i < 3; i++) {
     96                a[i] = strtoul(cp, &cp, 10);
     97                if (*cp != '.')
     98                        return EINVAL;
     99                ++cp;
     100        }
     101
     102        a[3] = strtoul(cp, &cp, 10);
     103        if (*cp != '\0')
    334104                return EINVAL;
     105
     106        addr->ipv4 = 0;
     107        for (i = 0; i < 4; i++) {
     108                if (a[i] > 255)
     109                        return EINVAL;
     110                addr->ipv4 = (addr->ipv4 << 8) | a[i];
    335111        }
    336        
     112
    337113        return EOK;
    338114}
    339115
    340 /** Parse network address.
     116/** Format network address.
    341117 *
    342  * @param text  Network address in common notation.
    343  * @param naddr Place to store network address.
     118 * @param naddr Network address
     119 * @param bufp  Place to store pointer to formatted string (CIDR notation)
    344120 *
    345  * @return EOK on success, EINVAL if input is not in valid format.
    346  *
     121 * @return      EOK on success, ENOMEM if out of memory.
    347122 */
    348 int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
     123int inet_naddr_format(inet_naddr_t *naddr, char **bufp)
    349124{
    350         char *slash = str_chr(text, '/');
    351         if (slash == NULL)
    352                 return EINVAL;
    353        
    354         *slash = 0;
    355        
    356         int rc = inet_addr_family(text, &naddr->family);
    357         if (rc != EOK)
    358                 return rc;
    359        
    360         uint8_t buf[16];
    361         rc = inet_pton(naddr->family, text, buf);
    362         *slash = '/';
    363        
    364         if (rc != EOK)
    365                 return rc;
    366        
    367         slash++;
    368         uint8_t prefix;
    369        
    370         switch (naddr->family) {
    371         case AF_INET:
    372                 prefix = strtoul(slash, &slash, 10);
    373                 if (prefix > 32)
    374                         return EINVAL;
    375                
    376                 naddr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
    377                     buf[3];
    378                 naddr->prefix = prefix;
    379                
    380                 break;
    381         case AF_INET6:
    382                 prefix = strtoul(slash, &slash, 10);
    383                 if (prefix > 128)
    384                         return EINVAL;
    385                
    386                 memcpy(naddr->addr6, buf, 16);
    387                 naddr->prefix = prefix;
    388                
    389                 break;
    390         default:
    391                 return ENOTSUP;
    392         }
    393        
     125        int rc;
     126
     127        rc = asprintf(bufp, "%d.%d.%d.%d/%d", naddr->ipv4 >> 24,
     128            (naddr->ipv4 >> 16) & 0xff, (naddr->ipv4 >> 8) & 0xff,
     129            naddr->ipv4 & 0xff, naddr->bits);
     130
     131        if (rc < 0)
     132                return ENOMEM;
     133
    394134        return EOK;
    395135}
     
    397137/** Format node address.
    398138 *
    399  * @param addr Node address.
    400  * @param bufp Place to store pointer to formatted string.
     139 * @param addr  Node address
     140 * @param bufp  Place to store pointer to formatted string (dot notation)
    401141 *
    402  * @return EOK on success.
    403  * @return ENOMEM if out of memory.
    404  * @return ENOTSUP on unsupported address family.
    405  *
     142 * @return      EOK on success, ENOMEM if out of memory.
    406143 */
    407 int inet_addr_format(const inet_addr_t *addr, char **bufp)
     144int inet_addr_format(inet_addr_t *addr, char **bufp)
    408145{
    409         int rc = 0;
    410        
    411         switch (addr->family) {
    412         case AF_NONE:
    413                 rc = asprintf(bufp, "none");
    414                 break;
    415         case AF_INET:
    416                 rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff,
    417                     (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff,
    418                     addr->addr & 0xff);
    419                 break;
    420         case AF_INET6:
    421                 *bufp = (char *) malloc(INET6_ADDRSTRLEN);
    422                 if (*bufp == NULL)
    423                         return ENOMEM;
    424                
    425                 return inet_ntop(AF_INET6, addr->addr6, *bufp, INET6_ADDRSTRLEN);
    426         default:
    427                 return ENOTSUP;
    428         }
    429        
     146        int rc;
     147
     148        rc = asprintf(bufp, "%d.%d.%d.%d", addr->ipv4 >> 24,
     149            (addr->ipv4 >> 16) & 0xff, (addr->ipv4 >> 8) & 0xff,
     150            addr->ipv4 & 0xff);
     151
    430152        if (rc < 0)
    431153                return ENOMEM;
    432        
     154
    433155        return EOK;
    434 }
    435 
    436 /** Format network address.
    437  *
    438  * @param naddr Network address.
    439  * @param bufp  Place to store pointer to formatted string.
    440  *
    441  * @return EOK on success.
    442  * @return ENOMEM if out of memory.
    443  * @return ENOTSUP on unsupported address family.
    444  *
    445  */
    446 int inet_naddr_format(const inet_naddr_t *naddr, char **bufp)
    447 {
    448         int rc = 0;
    449         char prefix[INET_PREFIXSTRSIZE];
    450        
    451         switch (naddr->family) {
    452         case AF_NONE:
    453                 rc = asprintf(bufp, "none");
    454                 break;
    455         case AF_INET:
    456                 rc = asprintf(bufp, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8
    457                     "/%" PRIu8, (naddr->addr >> 24) & 0xff,
    458                     (naddr->addr >> 16) & 0xff, (naddr->addr >> 8) & 0xff,
    459                     naddr->addr & 0xff, naddr->prefix);
    460                 break;
    461         case AF_INET6:
    462                 *bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
    463                 if (*bufp == NULL)
    464                         return ENOMEM;
    465                
    466                 rc = inet_ntop(AF_INET6, naddr->addr6, *bufp,
    467                     INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
    468                 if (rc != EOK) {
    469                         free(*bufp);
    470                         return rc;
    471                 }
    472                
    473                 rc = snprintf(prefix, INET_PREFIXSTRSIZE, "/%" PRIu8,
    474                     naddr->prefix);
    475                 if (rc < 0) {
    476                         free(*bufp);
    477                         return ENOMEM;
    478                 }
    479                
    480                 str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix);
    481                
    482                 break;
    483         default:
    484                 return ENOTSUP;
    485         }
    486        
    487         if (rc < 0)
    488                 return ENOMEM;
    489        
    490         return EOK;
    491 }
    492 
    493 uint16_t inet_addr_get(const inet_addr_t *addr, addr32_t *v4, addr128_t *v6)
    494 {
    495         switch (addr->family) {
    496         case AF_INET:
    497                 if (v4 != NULL)
    498                         *v4 = addr->addr;
    499                
    500                 break;
    501         case AF_INET6:
    502                 if (v6 != NULL)
    503                         memcpy(*v6, addr->addr6, 16);
    504                
    505                 break;
    506         }
    507        
    508         return addr->family;
    509 }
    510 
    511 uint16_t inet_naddr_get(const inet_naddr_t *naddr, addr32_t *v4, addr128_t *v6,
    512     uint8_t *prefix)
    513 {
    514         switch (naddr->family) {
    515         case AF_INET:
    516                 if (v4 != NULL)
    517                         *v4 = naddr->addr;
    518                
    519                 if (prefix != NULL)
    520                         *prefix = naddr->prefix;
    521                
    522                 break;
    523         case AF_INET6:
    524                 if (v6 != NULL)
    525                         memcpy(*v6, naddr->addr6, 16);
    526                
    527                 if (prefix != NULL)
    528                         *prefix = naddr->prefix;
    529                
    530                 break;
    531         }
    532        
    533         return naddr->family;
    534 }
    535 
    536 void inet_addr_set(addr32_t v4, inet_addr_t *addr)
    537 {
    538         addr->family = AF_INET;
    539         addr->addr = v4;
    540 }
    541 
    542 void inet_naddr_set(addr32_t v4, uint8_t prefix, inet_naddr_t *naddr)
    543 {
    544         naddr->family = AF_INET;
    545         naddr->addr = v4;
    546         naddr->prefix = prefix;
    547 }
    548 
    549 void inet_sockaddr_in_addr(const sockaddr_in_t *sockaddr_in, inet_addr_t *addr)
    550 {
    551         addr->family = AF_INET;
    552         addr->addr = uint32_t_be2host(sockaddr_in->sin_addr.s_addr);
    553 }
    554 
    555 void inet_addr_set6(addr128_t v6, inet_addr_t *addr)
    556 {
    557         addr->family = AF_INET6;
    558         memcpy(addr->addr6, v6, 16);
    559 }
    560 
    561 void inet_naddr_set6(addr128_t v6, uint8_t prefix, inet_naddr_t *naddr)
    562 {
    563         naddr->family = AF_INET6;
    564         memcpy(naddr->addr6, v6, 16);
    565         naddr->prefix = prefix;
    566 }
    567 
    568 void inet_sockaddr_in6_addr(const sockaddr_in6_t *sockaddr_in6,
    569     inet_addr_t *addr)
    570 {
    571         addr->family = AF_INET6;
    572         addr128_t_be2host(sockaddr_in6->sin6_addr.s6_addr, addr->addr6);
    573 }
    574 
    575 uint16_t inet_addr_sockaddr_in(const inet_addr_t *addr,
    576     sockaddr_in_t *sockaddr_in, sockaddr_in6_t *sockaddr_in6)
    577 {
    578         switch (addr->family) {
    579         case AF_INET:
    580                 if (sockaddr_in != NULL) {
    581                         sockaddr_in->sin_family = AF_INET;
    582                         sockaddr_in->sin_addr.s_addr = host2uint32_t_be(addr->addr);
    583                 }
    584                
    585                 break;
    586         case AF_INET6:
    587                 if (sockaddr_in6 != NULL) {
    588                         sockaddr_in6->sin6_family = AF_INET6;
    589                         host2addr128_t_be(addr->addr6, sockaddr_in6->sin6_addr.s6_addr);
    590                 }
    591                
    592                 break;
    593         }
    594        
    595         return addr->family;
    596156}
    597157
Note: See TracChangeset for help on using the changeset viewer.