Ignore:
File:
1 edited

Legend:

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

    r02a09ed 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 void host2addr128_t_be(const addr128_t host, addr128_t be)
    75 {
    76 #ifdef __BE__
    77         memcpy(be, host, 16);
    78 #else
    79         be[0] = host[15];
    80         be[1] = host[14];
    81         be[2] = host[13];
    82         be[3] = host[12];
    83         be[4] = host[11];
    84         be[5] = host[10];
    85         be[6] = host[9];
    86         be[7] = host[8];
    87         be[8] = host[7];
    88         be[9] = host[6];
    89         be[10] = host[5];
    90         be[11] = host[4];
    91         be[12] = host[3];
    92         be[13] = host[2];
    93         be[14] = host[1];
    94         be[15] = host[0];
    95 #endif
    96 }
    97 
    98 void addr128_t_be2host(const addr128_t be, addr128_t host)
    99 {
    100 #ifdef __BE__
    101         memcpy(host, be, 16);
    102 #else
    103         host[0] = be[15];
    104         host[1] = be[14];
    105         host[2] = be[13];
    106         host[3] = be[12];
    107         host[4] = be[11];
    108         host[5] = be[10];
    109         host[6] = be[9];
    110         host[7] = be[8];
    111         host[8] = be[7];
    112         host[9] = be[6];
    113         host[10] = be[5];
    114         host[11] = be[4];
    115         host[12] = be[3];
    116         host[13] = be[2];
    117         host[14] = be[1];
    118         host[15] = be[0];
    119 #endif
    120 }
    121 
    122 void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
    123 {
    124         addr->family = AF_INET;
    125         addr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
    126             ((addr32_t) c << 8) | ((addr32_t) d);
    127 }
    128 
    129 void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d,
    130     uint8_t prefix)
    131 {
    132         naddr->family = AF_INET;
    133         naddr->addr = ((addr32_t) a << 24) | ((addr32_t) b << 16) |
    134             ((addr32_t) c << 8) | ((addr32_t) d);
    135         naddr->prefix = prefix;
    136 }
    137 
    138 void inet_addr6(inet_addr_t *addr, uint16_t a, uint16_t b, uint16_t c,
    139     uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h)
    140 {
    141         addr->family = AF_INET6;
    142         addr->addr6[0] = (a >> 8) & 0xff;
    143         addr->addr6[1] = a & 0xff;
    144         addr->addr6[2] = (b >> 8) & 0xff;
    145         addr->addr6[3] = b & 0xff;
    146         addr->addr6[4] = (c >> 8) & 0xff;
    147         addr->addr6[5] = c & 0xff;
    148         addr->addr6[6] = (d >> 8) & 0xff;
    149         addr->addr6[7] = d & 0xff;
    150         addr->addr6[8] = (e >> 8) & 0xff;
    151         addr->addr6[9] = e & 0xff;
    152         addr->addr6[10] = (f >> 8) & 0xff;
    153         addr->addr6[11] = f & 0xff;
    154         addr->addr6[12] = (g >> 8) & 0xff;
    155         addr->addr6[13] = g & 0xff;
    156         addr->addr6[14] = (h >> 8) & 0xff;
    157         addr->addr6[15] = h & 0xff;
    158 }
    159 
    160 void inet_naddr6(inet_naddr_t *naddr, uint16_t a, uint16_t b, uint16_t c,
    161     uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h, uint8_t prefix)
    162 {
    163         naddr->family = AF_INET6;
    164         naddr->addr6[0] = (a >> 8) & 0xff;
    165         naddr->addr6[1] = a & 0xff;
    166         naddr->addr6[2] = (b >> 8) & 0xff;
    167         naddr->addr6[3] = b & 0xff;
    168         naddr->addr6[4] = (c >> 8) & 0xff;
    169         naddr->addr6[5] = c & 0xff;
    170         naddr->addr6[6] = (d >> 8) & 0xff;
    171         naddr->addr6[7] = d & 0xff;
    172         naddr->addr6[8] = (e >> 8) & 0xff;
    173         naddr->addr6[9] = e & 0xff;
    174         naddr->addr6[10] = (f >> 8) & 0xff;
    175         naddr->addr6[11] = f & 0xff;
    176         naddr->addr6[12] = (g >> 8) & 0xff;
    177         naddr->addr6[13] = g & 0xff;
    178         naddr->addr6[14] = (h >> 8) & 0xff;
    179         naddr->addr6[15] = h & 0xff;
    180         naddr->prefix = prefix;
    181 }
    182 
    183 /** Parse network address family.
    184  *
    185  * @param text Network address in common notation.
    186  * @param af   Place to store network address family.
    187  *
    188  * @return EOK on success, EINVAL if input is not in valid format.
    189  *
    190  */
    191 int inet_addr_family(const char *text, uint16_t *af)
    192 {
    193         char *dot = str_chr(text, '.');
    194         if (dot != NULL) {
    195                 *af = AF_INET;
    196                 return EOK;
    197         }
    198        
    199         char *collon = str_chr(text, ':');
    200         if (collon != NULL) {
    201                 *af = AF_INET6;
    202                 return EOK;
    203         }
    204        
    205         return EINVAL;
    206 }
    207 
    208 void inet_naddr_addr(const inet_naddr_t *naddr, inet_addr_t *addr)
    209 {
    210         addr->family = naddr->family;
    211         memcpy(addr->addr6, naddr->addr6, 16);
    212 }
    213 
    214 void inet_addr_any(inet_addr_t *addr)
    215 {
    216         addr->family = AF_NONE;
    217         memset(addr->addr6, 0, 16);
    218 }
    219 
    220 void inet_naddr_any(inet_naddr_t *naddr)
    221 {
    222         naddr->family = AF_NONE;
    223         memset(naddr->addr6, 0, 16);
    224         naddr->prefix = 0;
    225 }
    226 
    227 int inet_addr_compare(const inet_addr_t *a, const inet_addr_t *b)
    228 {
    229         if (a->family != b->family)
    230                 return 0;
    231        
    232         switch (a->family) {
    233         case AF_INET:
    234                 return (a->addr == b->addr);
    235         case AF_INET6:
    236                 return memcmp(&a->addr6, &b->addr6, 16);
    237         default:
    238                 return 0;
    239         }
    240 }
    241 
    242 int inet_addr_is_any(const inet_addr_t *addr)
    243 {
    244         return ((addr->family == 0) ||
    245             (inet_addr_compare(addr, &inet_addr_any_addr)) ||
    246             (inet_addr_compare(addr, &inet_addr_any_addr6)));
    247 }
    248 
    249 int inet_naddr_compare_mask(const inet_naddr_t *naddr, const inet_addr_t *addr)
    250 {
    251         if (naddr->family != addr->family)
    252                 return 0;
    253        
    254         switch (naddr->family) {
    255         case AF_INET:
    256                 if (naddr->prefix > 32)
    257                         return 0;
    258                
    259                 addr32_t mask =
    260                     BIT_RANGE(addr32_t, 31, 31 - (naddr->prefix - 1));
    261                 return ((naddr->addr & mask) == (addr->addr & mask));
    262         case AF_INET6:
    263                 if (naddr->prefix > 128)
    264                         return 0;
    265                
    266                 size_t pos = 0;
    267                 for (size_t i = 0; i < 16; i++) {
    268                         /* Further bits do not matter */
    269                         if (naddr->prefix < pos)
    270                                 break;
    271                        
    272                         if (naddr->prefix - pos > 8) {
    273                                 /* Comparison without masking */
    274                                 if (naddr->addr6[i] != addr->addr6[i])
    275                                         return 0;
    276                         } else {
    277                                 /* Comparison with masking */
    278                                 uint8_t mask =
    279                                     BIT_RANGE(uint8_t, 8, 8 - (naddr->prefix - pos - 1));
    280                                 if ((naddr->addr6[i] & mask) != (addr->addr6[i] & mask))
    281                                         return 0;
    282                         }
    283                        
    284                         pos += 8;
    285                 }
    286                
    287                 return 1;
    288         default:
    289                 return 0;
    290         }
     78        naddr->bits = bits;
     79        return EOK;
    29180}
    29281
    29382/** Parse node address.
    29483 *
    295  * @param text Network address in common notation.
    296  * @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
    29786 *
    298  * @return EOK on success, EINVAL if input is not in valid format.
    299  *
     87 * @return      EOK on success, EINVAL if input is not in valid format
    30088 */
    30189int inet_addr_parse(const char *text, inet_addr_t *addr)
    30290{
    303         int rc = inet_addr_family(text, &addr->family);
    304         if (rc != EOK)
    305                 return rc;
    306        
    307         uint8_t buf[16];
    308         rc = inet_pton(addr->family, text, buf);
    309         if (rc != EOK)
    310                 return rc;
    311        
    312         switch (addr->family) {
    313         case AF_INET:
    314                 addr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
    315                     buf[3];
    316                 break;
    317         case AF_INET6:
    318                 memcpy(addr->addr6, buf, 16);
    319                 break;
    320         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')
    321104                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];
    322111        }
    323        
     112
    324113        return EOK;
    325114}
    326115
    327 /** Parse network address.
     116/** Format network address.
    328117 *
    329  * @param text  Network address in common notation.
    330  * @param naddr Place to store network address.
     118 * @param naddr Network address
     119 * @param bufp  Place to store pointer to formatted string (CIDR notation)
    331120 *
    332  * @return EOK on success, EINVAL if input is not in valid format.
    333  *
     121 * @return      EOK on success, ENOMEM if out of memory.
    334122 */
    335 int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
     123int inet_naddr_format(inet_naddr_t *naddr, char **bufp)
    336124{
    337         char *slash = str_chr(text, '/');
    338         if (slash == NULL)
    339                 return EINVAL;
    340        
    341         *slash = 0;
    342        
    343         int rc = inet_addr_family(text, &naddr->family);
    344         if (rc != EOK)
    345                 return rc;
    346        
    347         uint8_t buf[16];
    348         rc = inet_pton(naddr->family, text, buf);
    349         *slash = '/';
    350        
    351         if (rc != EOK)
    352                 return rc;
    353        
    354         slash++;
    355         uint8_t prefix;
    356        
    357         switch (naddr->family) {
    358         case AF_INET:
    359                 prefix = strtoul(slash, &slash, 10);
    360                 if (prefix > 32)
    361                         return EINVAL;
    362                
    363                 naddr->addr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) |
    364                     buf[3];
    365                 naddr->prefix = prefix;
    366                
    367                 break;
    368         case AF_INET6:
    369                 prefix = strtoul(slash, &slash, 10);
    370                 if (prefix > 128)
    371                         return EINVAL;
    372                
    373                 memcpy(naddr->addr6, buf, 16);
    374                 naddr->prefix = prefix;
    375                
    376                 break;
    377         default:
    378                 return ENOTSUP;
    379         }
    380        
     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
    381134        return EOK;
    382135}
     
    384137/** Format node address.
    385138 *
    386  * @param addr Node address.
    387  * @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)
    388141 *
    389  * @return EOK on success.
    390  * @return ENOMEM if out of memory.
    391  * @return ENOTSUP on unsupported address family.
    392  *
     142 * @return      EOK on success, ENOMEM if out of memory.
    393143 */
    394 int inet_addr_format(const inet_addr_t *addr, char **bufp)
     144int inet_addr_format(inet_addr_t *addr, char **bufp)
    395145{
    396         int rc = 0;
    397        
    398         switch (addr->family) {
    399         case AF_NONE:
    400                 rc = asprintf(bufp, "none");
    401                 break;
    402         case AF_INET:
    403                 rc = asprintf(bufp, "%u.%u.%u.%u", (addr->addr >> 24) & 0xff,
    404                     (addr->addr >> 16) & 0xff, (addr->addr >> 8) & 0xff,
    405                     addr->addr & 0xff);
    406                 break;
    407         case AF_INET6:
    408                 *bufp = (char *) malloc(INET6_ADDRSTRLEN);
    409                 if (*bufp == NULL)
    410                         return ENOMEM;
    411                
    412                 return inet_ntop(AF_INET6, addr->addr6, *bufp, INET6_ADDRSTRLEN);
    413         default:
    414                 return ENOTSUP;
    415         }
    416        
     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
    417152        if (rc < 0)
    418153                return ENOMEM;
    419        
     154
    420155        return EOK;
    421 }
    422 
    423 /** Format network address.
    424  *
    425  * @param naddr Network address.
    426  * @param bufp  Place to store pointer to formatted string.
    427  *
    428  * @return EOK on success.
    429  * @return ENOMEM if out of memory.
    430  * @return ENOTSUP on unsupported address family.
    431  *
    432  */
    433 int inet_naddr_format(const inet_naddr_t *naddr, char **bufp)
    434 {
    435         int rc = 0;
    436         char prefix[INET_PREFIXSTRSIZE];
    437        
    438         switch (naddr->family) {
    439         case AF_NONE:
    440                 rc = asprintf(bufp, "none");
    441                 break;
    442         case AF_INET:
    443                 rc = asprintf(bufp, "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8
    444                     "/%" PRIu8, (naddr->addr >> 24) & 0xff,
    445                     (naddr->addr >> 16) & 0xff, (naddr->addr >> 8) & 0xff,
    446                     naddr->addr & 0xff, naddr->prefix);
    447                 break;
    448         case AF_INET6:
    449                 *bufp = (char *) malloc(INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
    450                 if (*bufp == NULL)
    451                         return ENOMEM;
    452                
    453                 rc = inet_ntop(AF_INET6, naddr->addr6, *bufp,
    454                     INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE);
    455                 if (rc != EOK) {
    456                         free(*bufp);
    457                         return rc;
    458                 }
    459                
    460                 rc = snprintf(prefix, INET_PREFIXSTRSIZE, "/%" PRIu8,
    461                     naddr->prefix);
    462                 if (rc < 0) {
    463                         free(*bufp);
    464                         return ENOMEM;
    465                 }
    466                
    467                 str_append(*bufp, INET6_ADDRSTRLEN + INET_PREFIXSTRSIZE, prefix);
    468                
    469                 break;
    470         default:
    471                 return ENOTSUP;
    472         }
    473        
    474         if (rc < 0)
    475                 return ENOMEM;
    476        
    477         return EOK;
    478 }
    479 
    480 uint16_t inet_addr_get(const inet_addr_t *addr, addr32_t *v4, addr128_t *v6)
    481 {
    482         switch (addr->family) {
    483         case AF_INET:
    484                 if (v4 != NULL)
    485                         *v4 = addr->addr;
    486                
    487                 break;
    488         case AF_INET6:
    489                 if (v6 != NULL)
    490                         memcpy(*v6, addr->addr6, 16);
    491                
    492                 break;
    493         }
    494        
    495         return addr->family;
    496 }
    497 
    498 uint16_t inet_naddr_get(const inet_naddr_t *naddr, addr32_t *v4, addr128_t *v6,
    499     uint8_t *prefix)
    500 {
    501         switch (naddr->family) {
    502         case AF_INET:
    503                 if (v4 != NULL)
    504                         *v4 = naddr->addr;
    505                
    506                 if (prefix != NULL)
    507                         *prefix = naddr->prefix;
    508                
    509                 break;
    510         case AF_INET6:
    511                 if (v6 != NULL)
    512                         memcpy(*v6, naddr->addr6, 16);
    513                
    514                 if (prefix != NULL)
    515                         *prefix = naddr->prefix;
    516                
    517                 break;
    518         }
    519        
    520         return naddr->family;
    521 }
    522 
    523 void inet_addr_set(addr32_t v4, inet_addr_t *addr)
    524 {
    525         addr->family = AF_INET;
    526         addr->addr = v4;
    527 }
    528 
    529 void inet_naddr_set(addr32_t v4, uint8_t prefix, inet_naddr_t *naddr)
    530 {
    531         naddr->family = AF_INET;
    532         naddr->addr = v4;
    533         naddr->prefix = prefix;
    534 }
    535 
    536 void inet_sockaddr_in_addr(const sockaddr_in_t *sockaddr_in, inet_addr_t *addr)
    537 {
    538         addr->family = AF_INET;
    539         addr->addr = uint32_t_be2host(sockaddr_in->sin_addr.s_addr);
    540 }
    541 
    542 void inet_addr_set6(addr128_t v6, inet_addr_t *addr)
    543 {
    544         addr->family = AF_INET6;
    545         memcpy(addr->addr6, v6, 16);
    546 }
    547 
    548 void inet_naddr_set6(addr128_t v6, uint8_t prefix, inet_naddr_t *naddr)
    549 {
    550         naddr->family = AF_INET6;
    551         memcpy(naddr->addr6, v6, 16);
    552         naddr->prefix = prefix;
    553 }
    554 
    555 void inet_sockaddr_in6_addr(const sockaddr_in6_t *sockaddr_in6,
    556     inet_addr_t *addr)
    557 {
    558         addr->family = AF_INET6;
    559         addr128_t_be2host(sockaddr_in6->sin6_addr.s6_addr, addr->addr6);
    560 }
    561 
    562 uint16_t inet_addr_sockaddr_in(const inet_addr_t *addr,
    563     sockaddr_in_t *sockaddr_in, sockaddr_in6_t *sockaddr_in6)
    564 {
    565         switch (addr->family) {
    566         case AF_INET:
    567                 if (sockaddr_in != NULL) {
    568                         sockaddr_in->sin_family = AF_INET;
    569                         sockaddr_in->sin_addr.s_addr = host2uint32_t_be(addr->addr);
    570                 }
    571                
    572                 break;
    573         case AF_INET6:
    574                 if (sockaddr_in6 != NULL) {
    575                         sockaddr_in6->sin6_family = AF_INET6;
    576                         host2addr128_t_be(addr->addr6, sockaddr_in6->sin6_addr.s6_addr);
    577                 }
    578                
    579                 break;
    580         }
    581        
    582         return addr->family;
    583156}
    584157
Note: See TracChangeset for help on using the changeset viewer.