Ignore:
File:
1 edited

Legend:

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

    r3495654 rbb9b0c6  
    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 inet_addr_t inet_addr_any_addr = {
     55        .family = AF_INET,
     56        .addr = 0
     57};
     58
     59static 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};
     63
     64void addr48(const addr48_t src, addr48_t dst)
     65{
     66        memcpy(dst, src, 6);
     67}
     68
     69void addr128(const addr128_t src, addr128_t dst)
     70{
     71        memcpy(dst, src, 16);
     72}
     73
     74int addr128_compare(const addr128_t a, const addr128_t b)
     75{
     76        return memcmp(a, b, 16);
     77}
     78
     79void 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
     103void 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
     127void 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
     134void 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
     143void 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
     165void 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 */
     196int 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
     213void 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
     219void 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
     227void inet_addr_any(inet_addr_t *addr)
     228{
     229        addr->family = AF_NONE;
     230        memset(addr->addr6, 0, 16);
     231}
     232
     233void 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
     240int 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
     255int 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
     262int 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        }
     304}
     305
     306/** Parse node address.
     307 *
     308 * @param text Network address in common notation.
     309 * @param addr Place to store node address.
     310 *
     311 * @return EOK on success, EINVAL if input is not in valid format.
     312 *
     313 */
     314int inet_addr_parse(const char *text, inet_addr_t *addr)
     315{
     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:
     334                return EINVAL;
     335        }
     336       
     337        return EOK;
     338}
    38339
    39340/** Parse network address.
    40341 *
    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
     342 * @param text  Network address in common notation.
     343 * @param naddr Place to store network address.
     344 *
     345 * @return EOK on success, EINVAL if input is not in valid format.
     346 *
    45347 */
    46348int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
    47349{
    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 != '.')
     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)
    55374                        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)
     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)
    71384                        return EINVAL;
    72                 naddr->ipv4 = (naddr->ipv4 << 8) | a[i];
    73         }
    74 
    75         if (bits > 31)
    76                 return EINVAL;
    77 
    78         naddr->bits = bits;
     385               
     386                memcpy(naddr->addr6, buf, 16);
     387                naddr->prefix = prefix;
     388               
     389                break;
     390        default:
     391                return ENOTSUP;
     392        }
     393       
    79394        return EOK;
    80395}
    81396
    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 
     397/** Format node address.
     398 *
     399 * @param addr Node address.
     400 * @param bufp Place to store pointer to formatted string.
     401 *
     402 * @return EOK on success.
     403 * @return ENOMEM if out of memory.
     404 * @return ENOTSUP on unsupported address family.
     405 *
     406 */
     407int inet_addr_format(const inet_addr_t *addr, char **bufp)
     408{
     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       
    131430        if (rc < 0)
    132431                return ENOMEM;
    133 
     432       
    134433        return EOK;
    135434}
    136435
    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 
     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 */
     446int 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       
    152487        if (rc < 0)
    153488                return ENOMEM;
    154 
     489       
    155490        return EOK;
    156491}
    157492
     493uint16_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
     511uint16_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
     536void inet_addr_set(addr32_t v4, inet_addr_t *addr)
     537{
     538        addr->family = AF_INET;
     539        addr->addr = v4;
     540}
     541
     542void 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
     549void 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
     555void inet_addr_set6(addr128_t v6, inet_addr_t *addr)
     556{
     557        addr->family = AF_INET6;
     558        memcpy(addr->addr6, v6, 16);
     559}
     560
     561void 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
     568void 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
     575uint16_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;
     596}
     597
    158598/** @}
    159599 */
Note: See TracChangeset for help on using the changeset viewer.