LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - mac8.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 84.0 % 263 221 6 21 15 2 93 20 106 25 93 16
Current Date: 2023-04-08 15:15:32 Functions: 86.4 % 22 19 3 18 1 3 17 2
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * mac8.c
       4                 :  *    PostgreSQL type definitions for 8 byte (EUI-64) MAC addresses.
       5                 :  *
       6                 :  * EUI-48 (6 byte) MAC addresses are accepted as input and are stored in
       7                 :  * EUI-64 format, with the 4th and 5th bytes set to FF and FE, respectively.
       8                 :  *
       9                 :  * Output is always in 8 byte (EUI-64) format.
      10                 :  *
      11                 :  * The following code is written with the assumption that the OUI field
      12                 :  * size is 24 bits.
      13                 :  *
      14                 :  * Portions Copyright (c) 1998-2023, PostgreSQL Global Development Group
      15                 :  *
      16                 :  * IDENTIFICATION
      17                 :  *        src/backend/utils/adt/mac8.c
      18                 :  *
      19                 :  *-------------------------------------------------------------------------
      20                 :  */
      21                 : 
      22                 : #include "postgres.h"
      23                 : 
      24                 : #include "common/hashfn.h"
      25                 : #include "libpq/pqformat.h"
      26                 : #include "utils/builtins.h"
      27                 : #include "utils/inet.h"
      28                 : 
      29                 : /*
      30                 :  *  Utility macros used for sorting and comparing:
      31                 :  */
      32                 : #define hibits(addr) \
      33                 :   ((unsigned long)(((addr)->a<<24) | ((addr)->b<<16) | ((addr)->c<<8) | ((addr)->d)))
      34                 : 
      35                 : #define lobits(addr) \
      36                 :   ((unsigned long)(((addr)->e<<24) | ((addr)->f<<16) | ((addr)->g<<8) | ((addr)->h)))
      37                 : 
      38                 : static unsigned char hex2_to_uchar(const unsigned char *ptr, bool *badhex);
      39                 : 
      40                 : static const signed char hexlookup[128] = {
      41                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      42                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      43                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      44                 :     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
      45                 :     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      46                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      47                 :     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      48                 :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      49                 : };
      50                 : 
      51                 : /*
      52                 :  * hex2_to_uchar - convert 2 hex digits to a byte (unsigned char)
      53                 :  *
      54                 :  * Sets *badhex to true if the end of the string is reached ('\0' found), or if
      55                 :  * either character is not a valid hex digit.
      56                 :  */
      57                 : static inline unsigned char
      58 GNC        8179 : hex2_to_uchar(const unsigned char *ptr, bool *badhex)
      59                 : {
      60                 :     unsigned char ret;
      61 ECB             :     signed char lookup;
      62 EUB             : 
      63                 :     /* Handle the first character */
      64 CBC        8179 :     if (*ptr > 127)
      65 LBC           0 :         goto invalid_input;
      66 ECB             : 
      67 GIC        8179 :     lookup = hexlookup[*ptr];
      68 CBC        8179 :     if (lookup < 0)
      69 GIC          12 :         goto invalid_input;
      70                 : 
      71 CBC        8167 :     ret = lookup << 4;
      72                 : 
      73 ECB             :     /* Move to the second character */
      74 GBC        8167 :     ptr++;
      75                 : 
      76 CBC        8167 :     if (*ptr > 127)
      77 LBC           0 :         goto invalid_input;
      78 ECB             : 
      79 GIC        8167 :     lookup = hexlookup[*ptr];
      80 CBC        8167 :     if (lookup < 0)
      81 GIC           9 :         goto invalid_input;
      82 ECB             : 
      83 GIC        8158 :     ret += lookup;
      84 ECB             : 
      85 CBC        8158 :     return ret;
      86 ECB             : 
      87 GIC          21 : invalid_input:
      88 GNC          21 :     *badhex = true;
      89 GIC          21 :     return 0;
      90 ECB             : }
      91                 : 
      92                 : /*
      93                 :  * MAC address (EUI-48 and EUI-64) reader. Accepts several common notations.
      94                 :  */
      95                 : Datum
      96 CBC        1211 : macaddr8_in(PG_FUNCTION_ARGS)
      97 ECB             : {
      98 CBC        1211 :     const unsigned char *str = (unsigned char *) PG_GETARG_CSTRING(0);
      99 GNC        1211 :     Node       *escontext = fcinfo->context;
     100 CBC        1211 :     const unsigned char *ptr = str;
     101 GNC        1211 :     bool        badhex = false;
     102 ECB             :     macaddr8   *result;
     103 CBC        1211 :     unsigned char a = 0,
     104            1211 :                 b = 0,
     105            1211 :                 c = 0,
     106            1211 :                 d = 0,
     107 GIC        1211 :                 e = 0,
     108            1211 :                 f = 0,
     109 CBC        1211 :                 g = 0,
     110            1211 :                 h = 0;
     111 GIC        1211 :     int         count = 0;
     112            1211 :     unsigned char spacer = '\0';
     113 ECB             : 
     114                 :     /* skip leading spaces */
     115 GIC        1259 :     while (*ptr && isspace(*ptr))
     116              48 :         ptr++;
     117                 : 
     118                 :     /* digits must always come in pairs */
     119            9351 :     while (*ptr && *(ptr + 1))
     120                 :     {
     121                 :         /*
     122 ECB             :          * Attempt to decode each byte, which must be 2 hex digits in a row.
     123                 :          * If either digit is not hex, hex2_to_uchar will throw ereport() for
     124                 :          * us.  Either 6 or 8 byte MAC addresses are supported.
     125                 :          */
     126                 : 
     127                 :         /* Attempt to collect a byte */
     128 CBC        8191 :         count++;
     129 ECB             : 
     130 CBC        8191 :         switch (count)
     131 ECB             :         {
     132 CBC        1211 :             case 1:
     133 GNC        1211 :                 a = hex2_to_uchar(ptr, &badhex);
     134 CBC        1211 :                 break;
     135            1205 :             case 2:
     136 GNC        1205 :                 b = hex2_to_uchar(ptr, &badhex);
     137 CBC        1205 :                 break;
     138            1193 :             case 3:
     139 GNC        1193 :                 c = hex2_to_uchar(ptr, &badhex);
     140 CBC        1193 :                 break;
     141            1193 :             case 4:
     142 GNC        1193 :                 d = hex2_to_uchar(ptr, &badhex);
     143 CBC        1193 :                 break;
     144            1187 :             case 5:
     145 GNC        1187 :                 e = hex2_to_uchar(ptr, &badhex);
     146 CBC        1187 :                 break;
     147            1187 :             case 6:
     148 GNC        1187 :                 f = hex2_to_uchar(ptr, &badhex);
     149 CBC        1187 :                 break;
     150             506 :             case 7:
     151 GNC         506 :                 g = hex2_to_uchar(ptr, &badhex);
     152 CBC         506 :                 break;
     153 GIC         497 :             case 8:
     154 GNC         497 :                 h = hex2_to_uchar(ptr, &badhex);
     155 CBC         497 :                 break;
     156              12 :             default:
     157                 :                 /* must be trailing garbage... */
     158 GNC          12 :                 goto fail;
     159 ECB             :         }
     160                 : 
     161 GNC        8179 :         if (badhex)
     162              21 :             goto fail;
     163                 : 
     164                 :         /* Move forward to where the next byte should be */
     165 CBC        8158 :         ptr += 2;
     166 ECB             : 
     167                 :         /* Check for a spacer, these are valid, anything else is not */
     168 GIC        8158 :         if (*ptr == ':' || *ptr == '-' || *ptr == '.')
     169 ECB             :         {
     170                 :             /* remember the spacer used, if it changes then it isn't valid */
     171 GIC        4466 :             if (spacer == '\0')
     172             857 :                 spacer = *ptr;
     173 ECB             : 
     174                 :             /* Have to use the same spacer throughout */
     175 GIC        3609 :             else if (spacer != *ptr)
     176 GNC          12 :                 goto fail;
     177                 : 
     178 ECB             :             /* move past the spacer */
     179 GIC        4454 :             ptr++;
     180                 :         }
     181 ECB             : 
     182                 :         /* allow trailing whitespace after if we have 6 or 8 bytes */
     183 GIC        8146 :         if (count == 6 || count == 8)
     184                 :         {
     185            1678 :             if (isspace(*ptr))
     186                 :             {
     187              72 :                 while (*++ptr && isspace(*ptr));
     188 ECB             : 
     189                 :                 /* If we found a space and then non-space, it's invalid */
     190 CBC          18 :                 if (*ptr)
     191 GNC           6 :                     goto fail;
     192 ECB             :             }
     193                 :         }
     194                 :     }
     195                 : 
     196                 :     /* Convert a 6 byte MAC address to macaddr8 */
     197 CBC        1160 :     if (count == 6)
     198                 :     {
     199             678 :         h = f;
     200             678 :         g = e;
     201             678 :         f = d;
     202 ECB             : 
     203 CBC         678 :         d = 0xFF;
     204             678 :         e = 0xFE;
     205 ECB             :     }
     206 CBC         482 :     else if (count != 8)
     207 GNC           6 :         goto fail;
     208 ECB             : 
     209 GIC        1154 :     result = (macaddr8 *) palloc0(sizeof(macaddr8));
     210                 : 
     211            1154 :     result->a = a;
     212            1154 :     result->b = b;
     213            1154 :     result->c = c;
     214            1154 :     result->d = d;
     215            1154 :     result->e = e;
     216            1154 :     result->f = f;
     217            1154 :     result->g = g;
     218 CBC        1154 :     result->h = h;
     219                 : 
     220            1154 :     PG_RETURN_MACADDR8_P(result);
     221                 : 
     222 GNC          57 : fail:
     223              57 :     ereturn(escontext, (Datum) 0,
     224                 :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     225                 :              errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8",
     226                 :                     str)));
     227                 : }
     228                 : 
     229 ECB             : /*
     230                 :  * MAC8 address (EUI-64) output function. Fixed format.
     231                 :  */
     232                 : Datum
     233 CBC         872 : macaddr8_out(PG_FUNCTION_ARGS)
     234                 : {
     235             872 :     macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
     236                 :     char       *result;
     237                 : 
     238 GIC         872 :     result = (char *) palloc(32);
     239                 : 
     240             872 :     snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
     241             872 :              addr->a, addr->b, addr->c, addr->d,
     242             872 :              addr->e, addr->f, addr->g, addr->h);
     243                 : 
     244 GBC         872 :     PG_RETURN_CSTRING(result);
     245                 : }
     246 EUB             : 
     247                 : /*
     248                 :  * macaddr8_recv - converts external binary format(EUI-48 and EUI-64) to macaddr8
     249                 :  *
     250                 :  * The external representation is just the eight bytes, MSB first.
     251                 :  */
     252                 : Datum
     253 UBC           0 : macaddr8_recv(PG_FUNCTION_ARGS)
     254                 : {
     255               0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     256                 :     macaddr8   *addr;
     257 EUB             : 
     258 UBC           0 :     addr = (macaddr8 *) palloc0(sizeof(macaddr8));
     259                 : 
     260 UIC           0 :     addr->a = pq_getmsgbyte(buf);
     261               0 :     addr->b = pq_getmsgbyte(buf);
     262 UBC           0 :     addr->c = pq_getmsgbyte(buf);
     263 EUB             : 
     264 UIC           0 :     if (buf->len == 6)
     265                 :     {
     266 UBC           0 :         addr->d = 0xFF;
     267               0 :         addr->e = 0xFE;
     268 EUB             :     }
     269                 :     else
     270                 :     {
     271 UIC           0 :         addr->d = pq_getmsgbyte(buf);
     272               0 :         addr->e = pq_getmsgbyte(buf);
     273                 :     }
     274                 : 
     275               0 :     addr->f = pq_getmsgbyte(buf);
     276               0 :     addr->g = pq_getmsgbyte(buf);
     277 UBC           0 :     addr->h = pq_getmsgbyte(buf);
     278                 : 
     279               0 :     PG_RETURN_MACADDR8_P(addr);
     280                 : }
     281                 : 
     282 EUB             : /*
     283                 :  * macaddr8_send - converts macaddr8(EUI-64) to binary format
     284                 :  */
     285                 : Datum
     286 UBC           0 : macaddr8_send(PG_FUNCTION_ARGS)
     287 EUB             : {
     288 UBC           0 :     macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
     289 EUB             :     StringInfoData buf;
     290                 : 
     291 UIC           0 :     pq_begintypsend(&buf);
     292 UBC           0 :     pq_sendbyte(&buf, addr->a);
     293 UIC           0 :     pq_sendbyte(&buf, addr->b);
     294               0 :     pq_sendbyte(&buf, addr->c);
     295               0 :     pq_sendbyte(&buf, addr->d);
     296               0 :     pq_sendbyte(&buf, addr->e);
     297               0 :     pq_sendbyte(&buf, addr->f);
     298               0 :     pq_sendbyte(&buf, addr->g);
     299               0 :     pq_sendbyte(&buf, addr->h);
     300 ECB             : 
     301 UIC           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     302 ECB             : }
     303                 : 
     304                 : 
     305                 : /*
     306                 :  * macaddr8_cmp_internal - comparison function for sorting:
     307                 :  */
     308                 : static int32
     309 CBC       89347 : macaddr8_cmp_internal(macaddr8 *a1, macaddr8 *a2)
     310                 : {
     311           89347 :     if (hibits(a1) < hibits(a2))
     312 GIC       49408 :         return -1;
     313           39939 :     else if (hibits(a1) > hibits(a2))
     314           35846 :         return 1;
     315 CBC        4093 :     else if (lobits(a1) < lobits(a2))
     316 GIC         111 :         return -1;
     317 CBC        3982 :     else if (lobits(a1) > lobits(a2))
     318              12 :         return 1;
     319                 :     else
     320            3970 :         return 0;
     321                 : }
     322                 : 
     323                 : Datum
     324 GIC        7253 : macaddr8_cmp(PG_FUNCTION_ARGS)
     325                 : {
     326            7253 :     macaddr8   *a1 = PG_GETARG_MACADDR8_P(0);
     327            7253 :     macaddr8   *a2 = PG_GETARG_MACADDR8_P(1);
     328 ECB             : 
     329 GIC        7253 :     PG_RETURN_INT32(macaddr8_cmp_internal(a1, a2));
     330 ECB             : }
     331                 : 
     332                 : /*
     333                 :  * Boolean comparison functions.
     334                 :  */
     335                 : 
     336                 : Datum
     337 CBC       56675 : macaddr8_lt(PG_FUNCTION_ARGS)
     338                 : {
     339           56675 :     macaddr8   *a1 = PG_GETARG_MACADDR8_P(0);
     340           56675 :     macaddr8   *a2 = PG_GETARG_MACADDR8_P(1);
     341                 : 
     342           56675 :     PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) < 0);
     343                 : }
     344                 : 
     345                 : Datum
     346            1846 : macaddr8_le(PG_FUNCTION_ARGS)
     347                 : {
     348            1846 :     macaddr8   *a1 = PG_GETARG_MACADDR8_P(0);
     349            1846 :     macaddr8   *a2 = PG_GETARG_MACADDR8_P(1);
     350                 : 
     351            1846 :     PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) <= 0);
     352                 : }
     353                 : 
     354                 : Datum
     355           19005 : macaddr8_eq(PG_FUNCTION_ARGS)
     356                 : {
     357           19005 :     macaddr8   *a1 = PG_GETARG_MACADDR8_P(0);
     358           19005 :     macaddr8   *a2 = PG_GETARG_MACADDR8_P(1);
     359                 : 
     360           19005 :     PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) == 0);
     361                 : }
     362                 : 
     363                 : Datum
     364            1497 : macaddr8_ge(PG_FUNCTION_ARGS)
     365                 : {
     366            1497 :     macaddr8   *a1 = PG_GETARG_MACADDR8_P(0);
     367            1497 :     macaddr8   *a2 = PG_GETARG_MACADDR8_P(1);
     368                 : 
     369            1497 :     PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) >= 0);
     370                 : }
     371                 : 
     372                 : Datum
     373            3065 : macaddr8_gt(PG_FUNCTION_ARGS)
     374                 : {
     375            3065 :     macaddr8   *a1 = PG_GETARG_MACADDR8_P(0);
     376            3065 :     macaddr8   *a2 = PG_GETARG_MACADDR8_P(1);
     377                 : 
     378            3065 :     PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) > 0);
     379                 : }
     380                 : 
     381                 : Datum
     382 GIC           6 : macaddr8_ne(PG_FUNCTION_ARGS)
     383                 : {
     384               6 :     macaddr8   *a1 = PG_GETARG_MACADDR8_P(0);
     385 CBC           6 :     macaddr8   *a2 = PG_GETARG_MACADDR8_P(1);
     386                 : 
     387               6 :     PG_RETURN_BOOL(macaddr8_cmp_internal(a1, a2) != 0);
     388                 : }
     389 ECB             : 
     390                 : /*
     391                 :  * Support function for hash indexes on macaddr8.
     392                 :  */
     393                 : Datum
     394 GIC          90 : hashmacaddr8(PG_FUNCTION_ARGS)
     395 ECB             : {
     396 GIC          90 :     macaddr8   *key = PG_GETARG_MACADDR8_P(0);
     397 ECB             : 
     398 CBC          90 :     return hash_any((unsigned char *) key, sizeof(macaddr8));
     399                 : }
     400                 : 
     401                 : Datum
     402 GIC          30 : hashmacaddr8extended(PG_FUNCTION_ARGS)
     403                 : {
     404              30 :     macaddr8   *key = PG_GETARG_MACADDR8_P(0);
     405 ECB             : 
     406 GIC          30 :     return hash_any_extended((unsigned char *) key, sizeof(macaddr8),
     407 CBC          30 :                              PG_GETARG_INT64(1));
     408                 : }
     409                 : 
     410 ECB             : /*
     411                 :  * Arithmetic functions: bitwise NOT, AND, OR.
     412                 :  */
     413                 : Datum
     414 CBC          60 : macaddr8_not(PG_FUNCTION_ARGS)
     415 ECB             : {
     416 CBC          60 :     macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
     417 ECB             :     macaddr8   *result;
     418                 : 
     419 GIC          60 :     result = (macaddr8 *) palloc0(sizeof(macaddr8));
     420 CBC          60 :     result->a = ~addr->a;
     421 GIC          60 :     result->b = ~addr->b;
     422              60 :     result->c = ~addr->c;
     423              60 :     result->d = ~addr->d;
     424 CBC          60 :     result->e = ~addr->e;
     425 GIC          60 :     result->f = ~addr->f;
     426 CBC          60 :     result->g = ~addr->g;
     427              60 :     result->h = ~addr->h;
     428                 : 
     429 GIC          60 :     PG_RETURN_MACADDR8_P(result);
     430 ECB             : }
     431                 : 
     432                 : Datum
     433 CBC          60 : macaddr8_and(PG_FUNCTION_ARGS)
     434 ECB             : {
     435 CBC          60 :     macaddr8   *addr1 = PG_GETARG_MACADDR8_P(0);
     436              60 :     macaddr8   *addr2 = PG_GETARG_MACADDR8_P(1);
     437 ECB             :     macaddr8   *result;
     438                 : 
     439 GIC          60 :     result = (macaddr8 *) palloc0(sizeof(macaddr8));
     440 CBC          60 :     result->a = addr1->a & addr2->a;
     441 GIC          60 :     result->b = addr1->b & addr2->b;
     442              60 :     result->c = addr1->c & addr2->c;
     443              60 :     result->d = addr1->d & addr2->d;
     444 CBC          60 :     result->e = addr1->e & addr2->e;
     445 GIC          60 :     result->f = addr1->f & addr2->f;
     446 CBC          60 :     result->g = addr1->g & addr2->g;
     447              60 :     result->h = addr1->h & addr2->h;
     448                 : 
     449 GIC          60 :     PG_RETURN_MACADDR8_P(result);
     450 ECB             : }
     451                 : 
     452                 : Datum
     453 CBC          60 : macaddr8_or(PG_FUNCTION_ARGS)
     454 ECB             : {
     455 CBC          60 :     macaddr8   *addr1 = PG_GETARG_MACADDR8_P(0);
     456              60 :     macaddr8   *addr2 = PG_GETARG_MACADDR8_P(1);
     457 ECB             :     macaddr8   *result;
     458                 : 
     459 GIC          60 :     result = (macaddr8 *) palloc0(sizeof(macaddr8));
     460 CBC          60 :     result->a = addr1->a | addr2->a;
     461 GIC          60 :     result->b = addr1->b | addr2->b;
     462              60 :     result->c = addr1->c | addr2->c;
     463              60 :     result->d = addr1->d | addr2->d;
     464              60 :     result->e = addr1->e | addr2->e;
     465              60 :     result->f = addr1->f | addr2->f;
     466              60 :     result->g = addr1->g | addr2->g;
     467 CBC          60 :     result->h = addr1->h | addr2->h;
     468                 : 
     469              60 :     PG_RETURN_MACADDR8_P(result);
     470                 : }
     471                 : 
     472 ECB             : /*
     473                 :  * Truncation function to allow comparing macaddr8 manufacturers.
     474                 :  */
     475                 : Datum
     476 CBC          60 : macaddr8_trunc(PG_FUNCTION_ARGS)
     477 ECB             : {
     478 CBC          60 :     macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
     479 ECB             :     macaddr8   *result;
     480                 : 
     481 CBC          60 :     result = (macaddr8 *) palloc0(sizeof(macaddr8));
     482                 : 
     483              60 :     result->a = addr->a;
     484 GIC          60 :     result->b = addr->b;
     485              60 :     result->c = addr->c;
     486              60 :     result->d = 0;
     487              60 :     result->e = 0;
     488              60 :     result->f = 0;
     489              60 :     result->g = 0;
     490 CBC          60 :     result->h = 0;
     491                 : 
     492              60 :     PG_RETURN_MACADDR8_P(result);
     493                 : }
     494                 : 
     495 ECB             : /*
     496                 :  * Set 7th bit for modified EUI-64 as used in IPv6.
     497                 :  */
     498                 : Datum
     499 CBC           3 : macaddr8_set7bit(PG_FUNCTION_ARGS)
     500 ECB             : {
     501 CBC           3 :     macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
     502 ECB             :     macaddr8   *result;
     503                 : 
     504 CBC           3 :     result = (macaddr8 *) palloc0(sizeof(macaddr8));
     505                 : 
     506               3 :     result->a = addr->a | 0x02;
     507 GIC           3 :     result->b = addr->b;
     508               3 :     result->c = addr->c;
     509               3 :     result->d = addr->d;
     510               3 :     result->e = addr->e;
     511               3 :     result->f = addr->f;
     512               3 :     result->g = addr->g;
     513               3 :     result->h = addr->h;
     514 EUB             : 
     515 GIC           3 :     PG_RETURN_MACADDR8_P(result);
     516 EUB             : }
     517                 : 
     518                 : /*----------------------------------------------------------
     519                 :  *  Conversion operators.
     520                 :  *---------------------------------------------------------*/
     521                 : 
     522                 : Datum
     523 UBC           0 : macaddrtomacaddr8(PG_FUNCTION_ARGS)
     524 EUB             : {
     525 UBC           0 :     macaddr    *addr6 = PG_GETARG_MACADDR_P(0);
     526 EUB             :     macaddr8   *result;
     527                 : 
     528 UBC           0 :     result = (macaddr8 *) palloc0(sizeof(macaddr8));
     529                 : 
     530 UIC           0 :     result->a = addr6->a;
     531 UBC           0 :     result->b = addr6->b;
     532 UIC           0 :     result->c = addr6->c;
     533               0 :     result->d = 0xFF;
     534               0 :     result->e = 0xFE;
     535 LBC           0 :     result->f = addr6->d;
     536 UIC           0 :     result->g = addr6->e;
     537 LBC           0 :     result->h = addr6->f;
     538                 : 
     539                 : 
     540               0 :     PG_RETURN_MACADDR8_P(result);
     541                 : }
     542 ECB             : 
     543 EUB             : Datum
     544 GIC          12 : macaddr8tomacaddr(PG_FUNCTION_ARGS)
     545                 : {
     546              12 :     macaddr8   *addr = PG_GETARG_MACADDR8_P(0);
     547                 :     macaddr    *result;
     548                 : 
     549              12 :     result = (macaddr *) palloc0(sizeof(macaddr));
     550                 : 
     551 CBC          12 :     if ((addr->d != 0xFF) || (addr->e != 0xFE))
     552 LBC           0 :         ereport(ERROR,
     553 ECB             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     554                 :                  errmsg("macaddr8 data out of range to convert to macaddr"),
     555                 :                  errhint("Only addresses that have FF and FE as values in the "
     556                 :                          "4th and 5th bytes from the left, for example "
     557                 :                          "xx:xx:xx:ff:fe:xx:xx:xx, are eligible to be converted "
     558                 :                          "from macaddr8 to macaddr.")));
     559                 : 
     560 GIC          12 :     result->a = addr->a;
     561              12 :     result->b = addr->b;
     562              12 :     result->c = addr->c;
     563              12 :     result->d = addr->f;
     564              12 :     result->e = addr->g;
     565              12 :     result->f = addr->h;
     566                 : 
     567              12 :     PG_RETURN_MACADDR_P(result);
     568                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a