Ignore:
File:
1 edited

Legend:

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

    r83781a22 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 addr48_t inet_addr48_solicited_node = {
    55         0x33, 0x33, 0xff, 0, 0, 0
    56 };
     64        bits = strtoul(cp, &cp, 10);
     65        if (*cp != '\0')
     66                return EINVAL;
    5767
    58 static const inet_addr_t inet_addr_any_addr = {
    59         .family = AF_INET,
    60         .addr = 0
    61 };
     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        }
    6274
    63 static const inet_addr_t inet_addr_any_addr6 = {
    64         .family = AF_INET6,
    65         .addr6 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    66 };
     75        if (bits > 31)
     76                return EINVAL;
    6777
    68 void addr48(const addr48_t src, addr48_t dst)
    69 {
    70         memcpy(dst, src, 6);
    71 }
    72 
    73 void addr128(const addr128_t src, addr128_t dst)
    74 {
    75         memcpy(dst, src, 16);
    76 }
    77 
    78 int addr48_compare(const addr48_t a, const addr48_t b)
    79 {
    80         return memcmp(a, b, 6);
    81 }
    82 
    83 int addr128_compare(const addr128_t a, const addr128_t b)
    84 {
    85         return memcmp(a, b, 16);
    86 }
    87 
    88 /** Compute solicited node MAC multicast address from target IPv6 address
    89  *
    90  * @param ip  Target IPv6 address
    91  * @param mac Solicited MAC address to be assigned
    92  *
    93  */
    94 void addr48_solicited_node(const addr128_t ip, addr48_t mac)
    95 {
    96         memcpy(mac, inet_addr48_solicited_node, 3);
    97         memcpy(mac + 3, ip + 13, 3);
    98 }
    99 
    100 void host2addr128_t_be(const addr128_t host, addr128_t be)
    101 {
    102 #ifdef __BE__
    103         memcpy(be, host, 16);
    104 #else
    105         be[0] = host[15];
    106         be[1] = host[14];
    107         be[2] = host[13];
    108         be[3] = host[12];
    109         be[4] = host[11];
    110         be[5] = host[10];
    111         be[6] = host[9];
    112         be[7] = host[8];
    113         be[8] = host[7];
    114         be[9] = host[6];
    115         be[10] = host[5];
    116         be[11] = host[4];
    117         be[12] = host[3];
    118         be[13] = host[2];
    119         be[14] = host[1];
    120         be[15] = host[0];
    121 #endif
    122 }
    123 
    124 void addr128_t_be2host(const addr128_t be, addr128_t host)
    125 {
    126 #ifdef __BE__
    127         memcpy(host, be, 16);
    128 #else
    129         host[0] = be[15];
    130         host[1] = be[14];
    131         host[2] = be[13];
    132         host[3] = be[12];
    133         host[4] = be[11];
    134         host[5] = be[10];
    135         host[6] = be[9];
    136         host[7] = be[8];
    137         host[8] = be[7];
    138         host[9] = be[6];
    139         host[10] = be[5];
    140         host[11] = be[4];
    141         host[12] = be[3];
    142         host[13] = be[2];
    143         host[14] = be[1];
    144         host[15] = be[0];
    145 #endif
    146 }
    147 
    148 void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
    149 {
    150         addr->family = AF_INET;
    151         addr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
    152             ((addr32_t) c << 8) | ((addr32_t) d);
    153 }
    154 
    155 void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d,
    156     uint8_t prefix)
    157 {
    158         naddr->family = AF_INET;
    159         naddr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
    160             ((addr32_t) c << 8) | ((addr32_t) d);
    161         naddr->prefix = prefix;
    162 }
    163 
    164 void inet_addr6(inet_addr_t *addr, uint16_t a, uint16_t b, uint16_t c,
    165     uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h)
    166 {
    167         addr->family = AF_INET6;
    168         addr->addr6[0] = (a >> 8) & 0xff;
    169         addr->addr6[1] = a & 0xff;
    170         addr->addr6[2] = (b >> 8) & 0xff;
    171         addr->addr6[3] = b & 0xff;
    172         addr->addr6[4] = (c >> 8) & 0xff;
    173         addr->addr6[5] = c & 0xff;
    174         addr->addr6[6] = (d >> 8) & 0xff;
    175         addr->addr6[7] = d & 0xff;
    176         addr->addr6[8] = (e >> 8) & 0xff;
    177         addr->addr6[9] = e & 0xff;
    178         addr->addr6[10] = (f >> 8) & 0xff;
    179         addr->addr6[11] = f & 0xff;
    180         addr->addr6[12] = (g >> 8) & 0xff;
    181         addr->addr6[13] = g & 0xff;
    182         addr->addr6[14] = (h >> 8) & 0xff;
    183         addr->addr6[15] = h & 0xff;
    184 }
    185 
    186 void inet_naddr6(inet_naddr_t *naddr, uint16_t a, uint16_t b, uint16_t c,
    187     uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h, uint8_t prefix)
    188 {
    189         naddr->family = AF_INET6;
    190         naddr->addr6[0] = (a >> 8) & 0xff;
    191         naddr->addr6[1] = a & 0xff;
    192         naddr->addr6[2] = (b >> 8) & 0xff;
    193         naddr->addr6[3] = b & 0xff;
    194         naddr->addr6[4] = (c >> 8) & 0xff;
    195         naddr->addr6[5] = c & 0xff;
    196         naddr->addr6[6] = (d >> 8) & 0xff;
    197         naddr->addr6[7] = d & 0xff;
    198         naddr->addr6[8] = (e >> 8) & 0xff;
    199         naddr->addr6[9] = e & 0xff;
    200         naddr->addr6[10] = (f >> 8) & 0xff;
    201         naddr->addr6[11] = f & 0xff;
    202         naddr->addr6[12] = (g >> 8) & 0xff;
    203         naddr->addr6[13] = g & 0xff;
    204         naddr->addr6[14] = (h >> 8) & 0xff;
    205         naddr->addr6[15] = h & 0xff;
    206         naddr->prefix = prefix;
    207 }
    208 
    209 /** Parse network address family.
    210  *
    211  * @param text Network address in common notation.
    212  * @param af   Place to store network address family.
    213  *
    214  * @return EOK on success, EINVAL if input is not in valid format.
    215  *
    216  */
    217 int inet_addr_family(const char *text, uint16_t *af)
    218 {
    219         char *dot = str_chr(text, '.');
    220         if (dot != NULL) {
    221                 *af = AF_INET;
    222                 return EOK;
    223         }
    224        
    225         char *collon = str_chr(text, ':');
    226         if (collon != NULL) {
    227                 *af = AF_INET6;
    228                 return EOK;
    229         }
    230        
    231         return EINVAL;
    232 }
    233 
    234 void inet_naddr_addr(const inet_naddr_t *naddr, inet_addr_t *addr)
    235 {
    236         addr->family = naddr->family;
    237         memcpy(addr->addr6, naddr->addr6, 16);
    238 }
    239 
    240 void inet_addr_naddr(const inet_addr_t *addr, uint8_t prefix,
    241     inet_naddr_t *naddr)
    242 {
    243         naddr->family = addr->family;
    244         memcpy(naddr->addr6, addr->addr6, 16);
    245         naddr->prefix = prefix;
    246 }
    247 
    248 void inet_addr_any(inet_addr_t *addr)
    249 {
    250         addr->family = AF_NONE;
    251         memset(addr->addr6, 0, 16);
    252 }
    253 
    254 void inet_naddr_any(inet_naddr_t *naddr)
    255 {
    256         naddr->family = AF_NONE;
    257         memset(naddr->addr6, 0, 16);
    258         naddr->prefix = 0;
    259 }
    260 
    261 int inet_addr_compare(const inet_addr_t *a, const inet_addr_t *b)
    262 {
    263         if (a->family != b->family)
    264                 return 0;
    265        
    266         switch (a->family) {
    267         case AF_INET:
    268                 return (a->addr == b->addr);
    269         case AF_INET6:
    270                 return addr128_compare(a->addr6, b->addr6);
    271         default:
    272                 return 0;
    273         }
    274 }
    275 
    276 int inet_addr_is_any(const inet_addr_t *addr)
    277 {
    278         return ((addr->family == 0) ||
    279             (inet_addr_compare(addr, &inet_addr_any_addr)) ||
    280             (inet_addr_compare(addr, &inet_addr_any_addr6)));
    281 }
    282 
    283 int inet_naddr_compare(const inet_naddr_t *naddr, const inet_addr_t *addr)
    284 {
    285         if (naddr->family != addr->family)
    286                 return 0;
    287        
    288         switch (naddr->family) {
    289         case AF_INET:
    290                 return (naddr->addr == addr->addr);
    291         case AF_INET6:
    292                 return addr128_compare(naddr->addr6, addr->addr6);
    293         default:
    294                 return 0;
    295         }
    296 }
    297 
    298 int inet_naddr_compare_mask(const inet_naddr_t *naddr, const inet_addr_t *addr)
    299 {
    300         if (naddr->family != addr->family)
    301                 return 0;
    302        
    303         switch (naddr->family) {
    304         case AF_INET:
    305                 if (naddr->prefix > 32)
    306                         return 0;
    307                
    308                 addr32_t mask =
    309                     BIT_RANGE(addr32_t, 31, 31 - (naddr->prefix - 1));
    310                 return ((naddr->addr & mask) == (addr->addr & mask));
    311         case AF_INET6:
    312                 if (naddr->prefix > 128)
    313                         return 0;
    314                
    315                 size_t pos = 0;
    316                 for (size_t i = 0; i < 16; i++) {
    317                         /* Further bits do not matter */
    318                         if (naddr->prefix < pos)
    319                                 break;
    320                        
    321                         if (naddr->prefix - pos > 8) {
    322                                 /* Comparison without masking */
    323                                 if (naddr->addr6[i] != addr->addr6[i])
    324                                         return 0;
    325                         } else {
    326                                 /* Comparison with masking */
    327                                 uint8_t mask =
    328                                     BIT_RANGE(uint8_t, 8, 8 - (naddr->prefix - pos - 1));
    329                                 if ((naddr->addr6[i] & mask) != (addr->addr6[i] & mask))
    330                                         return 0;
    331                         }
    332                        
    333                         pos += 8;
    334                 }
    335                
    336                 return 1;
    337         default:
    338                 return 0;
    339         }
     78        naddr->bits = bits;
     79        return EOK;
    34080}
    34181
    34282/** Parse node address.
    34383 *
    344  * @param text Network address in common notation.
    345  * @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
    34686 *
    347  * @return EOK on success, EINVAL if input is not in valid format.
    348  *
     87 * @return      EOK on success, EINVAL if input is not in valid format
    34988 */
    35089int inet_addr_parse(const char *text, inet_addr_t *addr)
    35190{
    352         int rc = inet_addr_family(text, &addr->family);
    353         if (rc != EOK)
    354                 return rc;
    355        
    356         uint8_t buf[16];
    357         rc = inet_pton(addr->family, text, buf);
    358         if (rc != EOK)
    359                 return rc;
    360        
    361         switch (addr->family) {
    362         case AF_INET:
    363                 addr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
    364                     buf[3];
    365                 break;
    366         case AF_INET6:
    367                 memcpy(addr->addr6, buf, 16);
    368                 break;
    369         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')
    370104                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];
    371111        }
    372        
     112
    373113        return EOK;
    374114}
    375115
    376 /** Parse network address.
     116/** Format network address.
    377117 *
    378  * @param text  Network address in common notation.
    379  * @param naddr Place to store network address.
     118 * @param naddr Network address
     119 * @param bufp  Place to store pointer to formatted string (CIDR notation)
    380120 *
    381  * @return EOK on success, EINVAL if input is not in valid format.
    382  *
     121 * @return      EOK on success, ENOMEM if out of memory.
    383122 */
    384 int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
     123int inet_naddr_format(inet_naddr_t *naddr, char **bufp)
    385124{
    386         char *slash = str_chr(text, '/');
    387         if (slash == NULL)
    388                 return EINVAL;
    389        
    390         *slash = 0;
    391        
    392         int rc = inet_addr_family(text, &naddr->family);
    393         if (rc != EOK)
    394                 return rc;
    395        
    396         uint8_t buf[16];
    397         rc = inet_pton(naddr->family, text, buf);
    398         *slash = '/';
    399        
    400         if (rc != EOK)
    401                 return rc;
    402        
    403         slash++;
    404         uint8_t prefix;
    405        
    406         switch (naddr->family) {
    407         case AF_INET:
    408                 prefix = strtoul(slash, &slash, 10);
    409                 if (prefix > 32)
    410                         return EINVAL;
    411                
    412                 naddr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
    413                     buf[3];
    414                 naddr->prefix = prefix;
    415                
    416                 break;
    417         case AF_INET6:
    418                 prefix = strtoul(slash, &slash, 10);
    419                 if (prefix > 128)
    420                         return EINVAL;
    421                
    422                 memcpy(naddr->addr6, buf, 16);
    423                 naddr->prefix = prefix;
    424                
    425                 break;
    426         default:
    427                 return ENOTSUP;
    428         }
    429        
     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
    430134        return EOK;
    431135}
     
    433137/** Format node address.
    434138 *
    435  * @param addr Node address.
    436  * @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)
    437141 *
    438  * @return EOK on success.
    439  * @return ENOMEM if out of memory.
    440  * @return ENOTSUP on unsupported address family.
    441  *
     142 * @return      EOK on success, ENOMEM if out of memory.
    442143 */
    443 int inet_addr_format(const inet_addr_t *addr, char **bufp)
     144int inet_addr_format(inet_addr_t *addr, char **bufp)
    444145{
    445         int rc = 0;
    446        
    447         switch (addr->family) {
    448         case AF_NONE:
    449                 rc = asprintf(bufp, "none");
    450                 break;
    451         case AF_INET:
    452                 rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff,
    453                     (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff,
    454                     addr->addr & 0xff);
    455                 break;
    456         case AF_INET6:
    457                 *bufp = (char *) malloc(INET6_ADDRSTRLEN);
    458                 if (*bufp == NULL)
    459                         return ENOMEM;
    460                
    461                 return inet_ntop(AF_INET6, addr->addr6, *bufp, INET6_ADDRSTRLEN);
    462         default:
    463                 return ENOTSUP;
    464         }
    465        
     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
    466152        if (rc < 0)
    467153                return ENOMEM;
    468        
     154
    469155        return EOK;
    470 }
    471 
    472 /** Format network address.
    473  *
    474  * @param naddr Network address.
    475  * @param bufp  Place to store pointer to formatted string.
    476  *
    477  * @return EOK on success.
    478  * @return ENOMEM if out of memory.
    479  * @return ENOTSUP on unsupported address family.
    480  *
    481  */
    482 int inet_naddr_format(const inet_naddr_t *naddr, char **bufp)
    483 {
    484         int rc = 0;
    485         char prefix[INET_PREFIXSTRSIZE];
    486        
    487         switch (naddr->family) {
    488         case AF_NONE:
    489                 rc = asprintf(bufp, "none");
    490                 break;
    491         case AF_INET:
    492                 rc = asprintf(bufp, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8
    493                     "/%" PRIu8, (naddr->addr >> 24) & 0xff,
    494                     (naddr->addr >> 16) & 0xff, (naddr->addr >> 8) & 0xff,
    495                     naddr->addr & 0xff, naddr->prefix);
    496                 break;
    497         case AF_INET6:
    498                 *bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
    499                 if (*bufp == NULL)
    500                         return ENOMEM;
    501                
    502                 rc = inet_ntop(AF_INET6, naddr->addr6, *bufp,
    503                     INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
    504                 if (rc != EOK) {
    505                         free(*bufp);
    506                         return rc;
    507                 }
    508                
    509                 rc = snprintf(prefix, INET_PREFIXSTRSIZE, "/%" PRIu8,
    510                     naddr->prefix);
    511                 if (rc < 0) {
    512                         free(*bufp);
    513                         return ENOMEM;
    514                 }
    515                
    516                 str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix);
    517                
    518                 break;
    519         default:
    520                 return ENOTSUP;
    521         }
    522        
    523         if (rc < 0)
    524                 return ENOMEM;
    525        
    526         return EOK;
    527 }
    528 
    529 uint16_t inet_addr_get(const inet_addr_t *addr, addr32_t *v4, addr128_t *v6)
    530 {
    531         switch (addr->family) {
    532         case AF_INET:
    533                 if (v4 != NULL)
    534                         *v4 = addr->addr;
    535                
    536                 break;
    537         case AF_INET6:
    538                 if (v6 != NULL)
    539                         memcpy(*v6, addr->addr6, 16);
    540                
    541                 break;
    542         }
    543        
    544         return addr->family;
    545 }
    546 
    547 uint16_t inet_naddr_get(const inet_naddr_t *naddr, addr32_t *v4, addr128_t *v6,
    548     uint8_t *prefix)
    549 {
    550         switch (naddr->family) {
    551         case AF_INET:
    552                 if (v4 != NULL)
    553                         *v4 = naddr->addr;
    554                
    555                 if (prefix != NULL)
    556                         *prefix = naddr->prefix;
    557                
    558                 break;
    559         case AF_INET6:
    560                 if (v6 != NULL)
    561                         memcpy(*v6, naddr->addr6, 16);
    562                
    563                 if (prefix != NULL)
    564                         *prefix = naddr->prefix;
    565                
    566                 break;
    567         }
    568        
    569         return naddr->family;
    570 }
    571 
    572 void inet_addr_set(addr32_t v4, inet_addr_t *addr)
    573 {
    574         addr->family = AF_INET;
    575         addr->addr = v4;
    576 }
    577 
    578 void inet_naddr_set(addr32_t v4, uint8_t prefix, inet_naddr_t *naddr)
    579 {
    580         naddr->family = AF_INET;
    581         naddr->addr = v4;
    582         naddr->prefix = prefix;
    583 }
    584 
    585 void inet_sockaddr_in_addr(const sockaddr_in_t *sockaddr_in, inet_addr_t *addr)
    586 {
    587         addr->family = AF_INET;
    588         addr->addr = uint32_t_be2host(sockaddr_in->sin_addr.s_addr);
    589 }
    590 
    591 void inet_addr_set6(addr128_t v6, inet_addr_t *addr)
    592 {
    593         addr->family = AF_INET6;
    594         memcpy(addr->addr6, v6, 16);
    595 }
    596 
    597 void inet_naddr_set6(addr128_t v6, uint8_t prefix, inet_naddr_t *naddr)
    598 {
    599         naddr->family = AF_INET6;
    600         memcpy(naddr->addr6, v6, 16);
    601         naddr->prefix = prefix;
    602 }
    603 
    604 void inet_sockaddr_in6_addr(const sockaddr_in6_t *sockaddr_in6,
    605     inet_addr_t *addr)
    606 {
    607         addr->family = AF_INET6;
    608         addr128_t_be2host(sockaddr_in6->sin6_addr.s6_addr, addr->addr6);
    609 }
    610 
    611 uint16_t inet_addr_sockaddr_in(const inet_addr_t *addr,
    612     sockaddr_in_t *sockaddr_in, sockaddr_in6_t *sockaddr_in6)
    613 {
    614         switch (addr->family) {
    615         case AF_INET:
    616                 if (sockaddr_in != NULL) {
    617                         sockaddr_in->sin_family = AF_INET;
    618                         sockaddr_in->sin_addr.s_addr = host2uint32_t_be(addr->addr);
    619                 }
    620                
    621                 break;
    622         case AF_INET6:
    623                 if (sockaddr_in6 != NULL) {
    624                         sockaddr_in6->sin6_family = AF_INET6;
    625                         host2addr128_t_be(addr->addr6, sockaddr_in6->sin6_addr.s6_addr);
    626                 }
    627                
    628                 break;
    629         }
    630        
    631         return addr->family;
    632156}
    633157
Note: See TracChangeset for help on using the changeset viewer.