Home | History | Annotate | Line # | Download | only in generic
      1 /*
      2  * eui.h -- EUI-48 and EUI-64 (RFC7043) parser
      3  *
      4  * Copyright (c) 2023, NLnet Labs. All rights reserved.
      5  *
      6  * SPDX-License-Identifier: BSD-3-Clause
      7  *
      8  */
      9 #ifndef EUI_H
     10 #define EUI_H
     11 
     12 nonnull((1,2))
     13 static really_inline bool
     14 eui_base16_dec_loop_generic_32_inner(const uint8_t *s, uint8_t *o, bool last)
     15 {
     16   const uint32_t val1 = base16_table_dec_32bit_d0[s[0]]
     17                       | base16_table_dec_32bit_d1[s[1]];
     18   const uint32_t val2 = base16_table_dec_32bit_d0[s[3]]
     19                       | base16_table_dec_32bit_d1[s[4]];
     20 
     21   if (val1 > 0xff || val2 > 0xff || s[2] != '-' || (!last && s[5] != '-'))
     22     return false;
     23 
     24   o[0] = (uint8_t)val1;
     25   o[1] = (uint8_t)val2;
     26 
     27   return true;
     28 }
     29 
     30 // RFC7043 section 3.2, require xx-xx-xx-xx-xx-xx
     31 nonnull_all
     32 static really_inline int32_t parse_eui48(
     33   parser_t *parser,
     34   const type_info_t *type,
     35   const rdata_info_t *field,
     36   rdata_t *rdata,
     37   const token_t *token)
     38 {
     39   const uint8_t *input = (const uint8_t *)token->data;
     40   if (token->length == 17 &&
     41       eui_base16_dec_loop_generic_32_inner(input, rdata->octets, false) &&
     42       eui_base16_dec_loop_generic_32_inner(input+6, rdata->octets+2, false) &&
     43       eui_base16_dec_loop_generic_32_inner(input+12, rdata->octets+4, true))
     44     return (void)(rdata->octets += 6), 0;
     45   SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
     46 }
     47 
     48 // RFC7043 section 4.2, require xx-xx-xx-xx-xx-xx-xx-xx
     49 nonnull_all
     50 static really_inline int32_t parse_eui64(
     51   parser_t *parser,
     52   const type_info_t *type,
     53   const rdata_info_t *field,
     54   rdata_t *rdata,
     55   const token_t *token)
     56 {
     57   const uint8_t *input = (const uint8_t *)token->data;
     58   if (token->length == 23 &&
     59       eui_base16_dec_loop_generic_32_inner(input, rdata->octets, false) &&
     60       eui_base16_dec_loop_generic_32_inner(input+6, rdata->octets+2, false) &&
     61       eui_base16_dec_loop_generic_32_inner(input+12, rdata->octets+4, false) &&
     62       eui_base16_dec_loop_generic_32_inner(input+18, rdata->octets+6, true))
     63     return (void)(rdata->octets += 8), 0;
     64   SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
     65 }
     66 
     67 #endif // EUI_H
     68