Ignore:
File:
1 edited

Legend:

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

    r3495654 r83781a22  
    3434
    3535#include <errno.h>
     36#include <unistd.h>
     37#include <net/socket_codes.h>
    3638#include <inet/addr.h>
     39#include <net/inet.h>
    3740#include <stdio.h>
     41#include <malloc.h>
     42#include <bitops.h>
     43
     44#define INET_PREFIXSTRSIZE  5
     45
     46#if !(defined(__BE__) ^ defined(__LE__))
     47        #error The architecture must be either big-endian or little-endian.
     48#endif
     49
     50const addr48_t addr48_broadcast = {
     51        0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     52};
     53
     54static const addr48_t inet_addr48_solicited_node = {
     55        0x33, 0x33, 0xff, 0, 0, 0
     56};
     57
     58static const inet_addr_t inet_addr_any_addr = {
     59        .family = AF_INET,
     60        .addr = 0
     61};
     62
     63static 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};
     67
     68void addr48(const addr48_t src, addr48_t dst)
     69{
     70        memcpy(dst, src, 6);
     71}
     72
     73void addr128(const addr128_t src, addr128_t dst)
     74{
     75        memcpy(dst, src, 16);
     76}
     77
     78int addr48_compare(const addr48_t a, const addr48_t b)
     79{
     80        return memcmp(a, b, 6);
     81}
     82
     83int 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 */
     94void 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
     100void 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
     124void 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
     148void 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
     155void 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
     164void 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
     186void 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 */
     217int 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
     234void 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
     240void 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
     248void inet_addr_any(inet_addr_t *addr)
     249{
     250        addr->family = AF_NONE;
     251        memset(addr->addr6, 0, 16);
     252}
     253
     254void 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
     261int 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
     276int 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
     283int 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
     298int 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        }
     340}
     341
     342/** Parse node address.
     343 *
     344 * @param text Network address in common notation.
     345 * @param addr Place to store node address.
     346 *
     347 * @return EOK on success, EINVAL if input is not in valid format.
     348 *
     349 */
     350int inet_addr_parse(const char *text, inet_addr_t *addr)
     351{
     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:
     370                return EINVAL;
     371        }
     372       
     373        return EOK;
     374}
    38375
    39376/** Parse network address.
    40377 *
    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
     378 * @param text  Network address in common notation.
     379 * @param naddr Place to store network address.
     380 *
     381 * @return EOK on success, EINVAL if input is not in valid format.
     382 *
    45383 */
    46384int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
    47385{
    48         unsigned long a[4], bits;
    49         char *cp = (char *)text;
    50         int i;
    51 
    52         for (i = 0; i < 3; i++) {
    53                 a[i] = strtoul(cp, &cp, 10);
    54                 if (*cp != '.')
     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)
    55410                        return EINVAL;
    56                 ++cp;
    57         }
    58 
    59         a[3] = strtoul(cp, &cp, 10);
    60         if (*cp != '/')
    61                 return EINVAL;
    62         ++cp;
    63 
    64         bits = strtoul(cp, &cp, 10);
    65         if (*cp != '\0')
    66                 return EINVAL;
    67 
    68         naddr->ipv4 = 0;
    69         for (i = 0; i < 4; i++) {
    70                 if (a[i] > 255)
     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)
    71420                        return EINVAL;
    72                 naddr->ipv4 = (naddr->ipv4 << 8) | a[i];
    73         }
    74 
    75         if (bits > 31)
    76                 return EINVAL;
    77 
    78         naddr->bits = bits;
     421               
     422                memcpy(naddr->addr6, buf, 16);
     423                naddr->prefix = prefix;
     424               
     425                break;
     426        default:
     427                return ENOTSUP;
     428        }
     429       
    79430        return EOK;
    80431}
    81432
    82 /** Parse node address.
    83  *
    84  * @param text  Network address in dot notation (a.b.c.d)
    85  * @param addr  Place to store node address
    86  *
    87  * @return      EOK on success, EINVAL if input is not in valid format
    88  */
    89 int inet_addr_parse(const char *text, inet_addr_t *addr)
    90 {
    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')
    104                 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];
    111         }
    112 
    113         return EOK;
    114 }
    115 
    116 /** Format network address.
    117  *
    118  * @param naddr Network address
    119  * @param bufp  Place to store pointer to formatted string (CIDR notation)
    120  *
    121  * @return      EOK on success, ENOMEM if out of memory.
    122  */
    123 int inet_naddr_format(inet_naddr_t *naddr, char **bufp)
    124 {
    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 
     433/** Format node address.
     434 *
     435 * @param addr Node address.
     436 * @param bufp Place to store pointer to formatted string.
     437 *
     438 * @return EOK on success.
     439 * @return ENOMEM if out of memory.
     440 * @return ENOTSUP on unsupported address family.
     441 *
     442 */
     443int inet_addr_format(const inet_addr_t *addr, char **bufp)
     444{
     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       
    131466        if (rc < 0)
    132467                return ENOMEM;
    133 
     468       
    134469        return EOK;
    135470}
    136471
    137 /** Format node address.
    138  *
    139  * @param addr  Node address
    140  * @param bufp  Place to store pointer to formatted string (dot notation)
    141  *
    142  * @return      EOK on success, ENOMEM if out of memory.
    143  */
    144 int inet_addr_format(inet_addr_t *addr, char **bufp)
    145 {
    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 
     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 */
     482int 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       
    152523        if (rc < 0)
    153524                return ENOMEM;
    154 
     525       
    155526        return EOK;
    156527}
    157528
     529uint16_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
     547uint16_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
     572void inet_addr_set(addr32_t v4, inet_addr_t *addr)
     573{
     574        addr->family = AF_INET;
     575        addr->addr = v4;
     576}
     577
     578void 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
     585void 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
     591void inet_addr_set6(addr128_t v6, inet_addr_t *addr)
     592{
     593        addr->family = AF_INET6;
     594        memcpy(addr->addr6, v6, 16);
     595}
     596
     597void 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
     604void 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
     611uint16_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;
     632}
     633
    158634/** @}
    159635 */
Note: See TracChangeset for help on using the changeset viewer.