LCOV - code coverage report
Current view: top level - basic - ether-addr-util.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 41 41 100.0 %
Date: 2019-08-22 15:41:25 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <net/ethernet.h>
       5             : #include <stdio.h>
       6             : #include <sys/types.h>
       7             : 
       8             : #include "ether-addr-util.h"
       9             : #include "macro.h"
      10             : #include "string-util.h"
      11             : 
      12           4 : char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
      13           4 :         assert(addr);
      14           4 :         assert(buffer);
      15             : 
      16             :         /* Like ether_ntoa() but uses %02x instead of %x to print
      17             :          * ethernet addresses, which makes them look less funny. Also,
      18             :          * doesn't use a static buffer. */
      19             : 
      20          24 :         sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
      21           4 :                 addr->ether_addr_octet[0],
      22           4 :                 addr->ether_addr_octet[1],
      23           4 :                 addr->ether_addr_octet[2],
      24           4 :                 addr->ether_addr_octet[3],
      25           4 :                 addr->ether_addr_octet[4],
      26           4 :                 addr->ether_addr_octet[5]);
      27             : 
      28           4 :         return buffer;
      29             : }
      30             : 
      31          75 : int ether_addr_compare(const struct ether_addr *a, const struct ether_addr *b) {
      32          75 :         return memcmp(a, b, ETH_ALEN);
      33             : }
      34             : 
      35          54 : static void ether_addr_hash_func(const struct ether_addr *p, struct siphash *state) {
      36          54 :         siphash24_compress(p, sizeof(struct ether_addr), state);
      37          54 : }
      38             : 
      39             : DEFINE_HASH_OPS(ether_addr_hash_ops, struct ether_addr, ether_addr_hash_func, ether_addr_compare);
      40             : 
      41          67 : int ether_addr_from_string(const char *s, struct ether_addr *ret) {
      42          67 :         size_t pos = 0, n, field;
      43          67 :         char sep = '\0';
      44          67 :         const char *hex = HEXDIGITS, *hexoff;
      45             :         size_t x;
      46             :         bool touched;
      47             : 
      48             : #define parse_fields(v)                                         \
      49             :         for (field = 0; field < ELEMENTSOF(v); field++) {       \
      50             :                 touched = false;                                \
      51             :                 for (n = 0; n < (2 * sizeof(v[0])); n++) {      \
      52             :                         if (s[pos] == '\0')                     \
      53             :                                 break;                          \
      54             :                         hexoff = strchr(hex, s[pos]);           \
      55             :                         if (!hexoff)                            \
      56             :                                 break;                          \
      57             :                         assert(hexoff >= hex);                  \
      58             :                         x = hexoff - hex;                       \
      59             :                         if (x >= 16)                            \
      60             :                                 x -= 6; /* A-F */               \
      61             :                         assert(x < 16);                         \
      62             :                         touched = true;                         \
      63             :                         v[field] <<= 4;                         \
      64             :                         v[field] += x;                          \
      65             :                         pos++;                                  \
      66             :                 }                                               \
      67             :                 if (!touched)                                   \
      68             :                         return -EINVAL;                         \
      69             :                 if (field < (ELEMENTSOF(v)-1)) {                \
      70             :                         if (s[pos] != sep)                      \
      71             :                                 return -EINVAL;                 \
      72             :                         else                                    \
      73             :                                 pos++;                          \
      74             :                 }                                               \
      75             :         }
      76             : 
      77          67 :         assert(s);
      78          67 :         assert(ret);
      79             : 
      80          67 :         s += strspn(s, WHITESPACE);
      81          67 :         sep = s[strspn(s, hex)];
      82             : 
      83          67 :         if (sep == '.') {
      84          14 :                 uint16_t shorts[3] = { 0 };
      85             : 
      86         176 :                 parse_fields(shorts);
      87             : 
      88          10 :                 if (s[pos] != '\0')
      89           2 :                         return -EINVAL;
      90             : 
      91          32 :                 for (n = 0; n < ELEMENTSOF(shorts); n++) {
      92          24 :                         ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8);
      93          24 :                         ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff);
      94             :                 }
      95             : 
      96          53 :         } else if (IN_SET(sep, ':', '-')) {
      97          45 :                 struct ether_addr out = ETHER_ADDR_NULL;
      98             : 
      99         762 :                 parse_fields(out.ether_addr_octet);
     100             : 
     101          35 :                 if (s[pos] != '\0')
     102           9 :                         return -EINVAL;
     103             : 
     104         182 :                 for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++)
     105         156 :                         ret->ether_addr_octet[n] = out.ether_addr_octet[n];
     106             : 
     107             :         } else
     108           8 :                 return -EINVAL;
     109             : 
     110          34 :         return 0;
     111             : }

Generated by: LCOV version 1.14