diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/basic/ether-addr-util.c | 69 | ||||
| -rw-r--r-- | src/basic/ether-addr-util.h | 2 | 
2 files changed, 71 insertions, 0 deletions
| diff --git a/src/basic/ether-addr-util.c b/src/basic/ether-addr-util.c index a4d8d656da..5697e8d132 100644 --- a/src/basic/ether-addr-util.c +++ b/src/basic/ether-addr-util.c @@ -23,6 +23,7 @@  #include "ether-addr-util.h"  #include "macro.h" +#include "string-util.h"  char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {          assert(addr); @@ -54,3 +55,71 @@ bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {                  a->ether_addr_octet[4] == b->ether_addr_octet[4] &&                  a->ether_addr_octet[5] == b->ether_addr_octet[5];  } + +int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset) { +        size_t pos = 0, n, field; +        char sep = '\0'; +        const char *hex = HEXDIGITS, *hexoff; +        size_t x; +        bool touched; + +#define parse_fields(v)                                         \ +        for (field = 0; field < ELEMENTSOF(v); field++) {       \ +                touched = false;                                \ +                for (n = 0; n < (2 * sizeof(v[0])); n++) {      \ +                        if (s[pos] == '\0')                     \ +                                break;                          \ +                        hexoff = strchr(hex, s[pos]);           \ +                        if (hexoff == NULL)                     \ +                                break;                          \ +                        assert(hexoff >= hex);                  \ +                        x = hexoff - hex;                       \ +                        if (x >= 16)                            \ +                                x -= 6; /* A-F */               \ +                        assert(x < 16);                         \ +                        touched = true;                         \ +                        v[field] <<= 4;                         \ +                        v[field] += x;                          \ +                        pos++;                                  \ +                }                                               \ +                if (!touched)                                   \ +                        return -EINVAL;                         \ +                if (field < (ELEMENTSOF(v)-1)) {                \ +                        if (s[pos] != sep)                      \ +                                return -EINVAL;                 \ +                        else                                    \ +                                pos++;                          \ +                }                                               \ +        } + +        assert(s); +        assert(ret); + +        sep = s[strspn(s, hex)]; +        if (sep == '\n') +                return -EINVAL; +        if (strchr(":.-", sep) == NULL) +                return -EINVAL; + +        if (sep == '.') { +                uint16_t shorts[3] = { 0 }; + +                parse_fields(shorts); + +                for (n = 0; n < ELEMENTSOF(shorts); n++) { +                        ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8); +                        ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff); +                } +        } else { +                struct ether_addr out = { .ether_addr_octet = { 0 } }; + +                parse_fields(out.ether_addr_octet); + +                for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++) +                        ret->ether_addr_octet[n] = out.ether_addr_octet[n]; +        } + +        if (offset) +                *offset = pos; +        return 0; +} diff --git a/src/basic/ether-addr-util.h b/src/basic/ether-addr-util.h index 074363793e..74e125a95f 100644 --- a/src/basic/ether-addr-util.h +++ b/src/basic/ether-addr-util.h @@ -35,3 +35,5 @@ bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b);  static inline bool ether_addr_is_null(const struct ether_addr *addr) {          return ether_addr_equal(addr, ÐER_ADDR_NULL);  } + +int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset); | 
