PostgreSQL Source Code git master
Loading...
Searching...
No Matches
mac.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * mac.c
4 * PostgreSQL type definitions for 6 byte, EUI-48, MAC addresses.
5 *
6 * Portions Copyright (c) 1998-2026, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * src/backend/utils/adt/mac.c
10 *
11 *-------------------------------------------------------------------------
12 */
13
14#include "postgres.h"
15
16#include "common/hashfn.h"
17#include "libpq/pqformat.h"
18#include "port/pg_bswap.h"
19#include "utils/fmgrprotos.h"
20#include "utils/inet.h"
21#include "utils/sortsupport.h"
22
23
24/*
25 * Utility macros used for sorting and comparing:
26 */
27
28#define hibits(addr) \
29 ((unsigned long)(((addr)->a<<16)|((addr)->b<<8)|((addr)->c)))
30
31#define lobits(addr) \
32 ((unsigned long)(((addr)->d<<16)|((addr)->e<<8)|((addr)->f)))
33
35static int macaddr_fast_cmp(Datum x, Datum y, SortSupport ssup);
36static bool macaddr_abbrev_abort(int memtupcount, SortSupport ssup);
37static Datum macaddr_abbrev_convert(Datum original, SortSupport ssup);
38
39/*
40 * MAC address reader. Accepts several common notations.
41 */
42
45{
46 char *str = PG_GETARG_CSTRING(0);
47 Node *escontext = fcinfo->context;
49 int a,
50 b,
51 c,
52 d,
53 e,
54 f;
55 char junk[2];
56 int count;
57
58 /* %1s matches iff there is trailing non-whitespace garbage */
59
60 count = sscanf(str, "%x:%x:%x:%x:%x:%x%1s",
61 &a, &b, &c, &d, &e, &f, junk);
62 if (count != 6)
63 count = sscanf(str, "%x-%x-%x-%x-%x-%x%1s",
64 &a, &b, &c, &d, &e, &f, junk);
65 if (count != 6)
66 count = sscanf(str, "%2x%2x%2x:%2x%2x%2x%1s",
67 &a, &b, &c, &d, &e, &f, junk);
68 if (count != 6)
69 count = sscanf(str, "%2x%2x%2x-%2x%2x%2x%1s",
70 &a, &b, &c, &d, &e, &f, junk);
71 if (count != 6)
72 count = sscanf(str, "%2x%2x.%2x%2x.%2x%2x%1s",
73 &a, &b, &c, &d, &e, &f, junk);
74 if (count != 6)
75 count = sscanf(str, "%2x%2x-%2x%2x-%2x%2x%1s",
76 &a, &b, &c, &d, &e, &f, junk);
77 if (count != 6)
78 count = sscanf(str, "%2x%2x%2x%2x%2x%2x%1s",
79 &a, &b, &c, &d, &e, &f, junk);
80 if (count != 6)
81 ereturn(escontext, (Datum) 0,
83 errmsg("invalid input syntax for type %s: \"%s\"", "macaddr",
84 str)));
85
86 if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
87 (c < 0) || (c > 255) || (d < 0) || (d > 255) ||
88 (e < 0) || (e > 255) || (f < 0) || (f > 255))
89 ereturn(escontext, (Datum) 0,
91 errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
92
94
95 result->a = a;
96 result->b = b;
97 result->c = c;
98 result->d = d;
99 result->e = e;
100 result->f = f;
101
103}
104
105/*
106 * MAC address output function. Fixed format.
107 */
108
109Datum
111{
112 macaddr *addr = PG_GETARG_MACADDR_P(0);
113 char *result;
114
115 result = (char *) palloc(32);
116
117 snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x",
118 addr->a, addr->b, addr->c, addr->d, addr->e, addr->f);
119
121}
122
123/*
124 * macaddr_recv - converts external binary format to macaddr
125 *
126 * The external representation is just the six bytes, MSB first.
127 */
128Datum
130{
132 macaddr *addr;
133
134 addr = palloc_object(macaddr);
135
136 addr->a = pq_getmsgbyte(buf);
137 addr->b = pq_getmsgbyte(buf);
138 addr->c = pq_getmsgbyte(buf);
139 addr->d = pq_getmsgbyte(buf);
140 addr->e = pq_getmsgbyte(buf);
141 addr->f = pq_getmsgbyte(buf);
142
144}
145
146/*
147 * macaddr_send - converts macaddr to binary format
148 */
149Datum
151{
152 macaddr *addr = PG_GETARG_MACADDR_P(0);
154
156 pq_sendbyte(&buf, addr->a);
157 pq_sendbyte(&buf, addr->b);
158 pq_sendbyte(&buf, addr->c);
159 pq_sendbyte(&buf, addr->d);
160 pq_sendbyte(&buf, addr->e);
161 pq_sendbyte(&buf, addr->f);
163}
164
165
166/*
167 * Comparison function for sorting:
168 */
169
170static int
172{
173 if (hibits(a1) < hibits(a2))
174 return -1;
175 else if (hibits(a1) > hibits(a2))
176 return 1;
177 else if (lobits(a1) < lobits(a2))
178 return -1;
179 else if (lobits(a1) > lobits(a2))
180 return 1;
181 else
182 return 0;
183}
184
185Datum
193
194/*
195 * Boolean comparisons.
196 */
197
198Datum
206
207Datum
215
216Datum
224
225Datum
233
234Datum
242
243Datum
251
252/*
253 * Support function for hash indexes on macaddr.
254 */
255Datum
257{
259
260 return hash_any((unsigned char *) key, sizeof(macaddr));
261}
262
263Datum
265{
267
268 return hash_any_extended((unsigned char *) key, sizeof(macaddr),
269 PG_GETARG_INT64(1));
270}
271
272/*
273 * Arithmetic functions: bitwise NOT, AND, OR.
274 */
275Datum
277{
278 macaddr *addr = PG_GETARG_MACADDR_P(0);
280
282 result->a = ~addr->a;
283 result->b = ~addr->b;
284 result->c = ~addr->c;
285 result->d = ~addr->d;
286 result->e = ~addr->e;
287 result->f = ~addr->f;
289}
290
291Datum
293{
297
299 result->a = addr1->a & addr2->a;
300 result->b = addr1->b & addr2->b;
301 result->c = addr1->c & addr2->c;
302 result->d = addr1->d & addr2->d;
303 result->e = addr1->e & addr2->e;
304 result->f = addr1->f & addr2->f;
306}
307
308Datum
310{
314
316 result->a = addr1->a | addr2->a;
317 result->b = addr1->b | addr2->b;
318 result->c = addr1->c | addr2->c;
319 result->d = addr1->d | addr2->d;
320 result->e = addr1->e | addr2->e;
321 result->f = addr1->f | addr2->f;
323}
324
325/*
326 * Truncation function to allow comparing mac manufacturers.
327 * From suggestion by Alex Pilosov <alex@pilosoft.com>
328 */
329Datum
331{
332 macaddr *addr = PG_GETARG_MACADDR_P(0);
334
336
337 result->a = addr->a;
338 result->b = addr->b;
339 result->c = addr->c;
340 result->d = 0;
341 result->e = 0;
342 result->f = 0;
343
345}
346
347/*
348 * SortSupport strategy function. Populates a SortSupport struct with the
349 * information necessary to use comparison by abbreviated keys.
350 */
351Datum
369
370/*
371 * SortSupport "traditional" comparison function. Pulls two MAC addresses from
372 * the heap and runs a standard comparison on them.
373 */
374static int
382
383/*
384 * Abbreviation is never aborted for macaddr because the 6-byte MAC address
385 * fits entirely within a 64-bit Datum, making the abbreviated key
386 * authoritative.
387 */
388static bool
389macaddr_abbrev_abort(int memtupcount, SortSupport ssup)
390{
391 return false;
392}
393
394/*
395 * SortSupport conversion routine. Converts original macaddr representation
396 * to abbreviated key representation.
397 *
398 * Packs the bytes of a 6-byte MAC address into a Datum and treats it as an
399 * unsigned integer for purposes of comparison. There will be two zeroed bytes
400 * of padding. The integer is converted to native endianness to facilitate
401 * easy comparison.
402 */
403static Datum
405{
407 Datum res;
408
409 /*
410 * Zero out the 8-byte Datum and copy in the 6 bytes of the MAC address.
411 * There will be two bytes of zero padding on the end of the least
412 * significant bits.
413 */
414 StaticAssertDecl(sizeof(res) >= sizeof(macaddr),
415 "Datum is too small for macaddr");
416 memset(&res, 0, sizeof(res));
417 memcpy(&res, authoritative, sizeof(macaddr));
418
419 /*
420 * Byteswap on little-endian machines.
421 *
422 * This is needed so that ssup_datum_unsigned_cmp() (an unsigned integer
423 * 3-way comparator) works correctly on all platforms. Without this, the
424 * comparator would have to call memcmp() with a pair of pointers to the
425 * first byte of each abbreviated key, which is slower.
426 */
427 res = DatumBigEndianToNative(res);
428
429 return res;
430}
#define StaticAssertDecl(condition, errmessage)
Definition c.h:1008
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereturn(context, dummy_value,...)
Definition elog.h:280
struct SortSupportData * SortSupport
Definition execnodes.h:61
#define palloc_object(type)
Definition fe_memutils.h:74
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define PG_RETURN_BYTEA_P(x)
Definition fmgr.h:373
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_RETURN_CSTRING(x)
Definition fmgr.h:364
#define PG_GETARG_CSTRING(n)
Definition fmgr.h:278
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
#define PG_RETURN_INT32(x)
Definition fmgr.h:355
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition hashfn.h:37
static Datum hash_any(const unsigned char *k, int keylen)
Definition hashfn.h:31
const char * str
static const FormData_pg_attribute a1
Definition heap.c:144
static const FormData_pg_attribute a2
Definition heap.c:157
int y
Definition isn.c:76
int b
Definition isn.c:74
int x
Definition isn.c:75
int a
Definition isn.c:73
Datum macaddr_lt(PG_FUNCTION_ARGS)
Definition mac.c:199
#define hibits(addr)
Definition mac.c:28
Datum macaddr_cmp(PG_FUNCTION_ARGS)
Definition mac.c:186
static int macaddr_cmp_internal(macaddr *a1, macaddr *a2)
Definition mac.c:171
Datum hashmacaddrextended(PG_FUNCTION_ARGS)
Definition mac.c:264
Datum hashmacaddr(PG_FUNCTION_ARGS)
Definition mac.c:256
static Datum macaddr_abbrev_convert(Datum original, SortSupport ssup)
Definition mac.c:404
Datum macaddr_or(PG_FUNCTION_ARGS)
Definition mac.c:309
Datum macaddr_recv(PG_FUNCTION_ARGS)
Definition mac.c:129
Datum macaddr_ne(PG_FUNCTION_ARGS)
Definition mac.c:244
Datum macaddr_trunc(PG_FUNCTION_ARGS)
Definition mac.c:330
Datum macaddr_eq(PG_FUNCTION_ARGS)
Definition mac.c:217
Datum macaddr_in(PG_FUNCTION_ARGS)
Definition mac.c:44
Datum macaddr_not(PG_FUNCTION_ARGS)
Definition mac.c:276
static bool macaddr_abbrev_abort(int memtupcount, SortSupport ssup)
Definition mac.c:389
Datum macaddr_and(PG_FUNCTION_ARGS)
Definition mac.c:292
Datum macaddr_send(PG_FUNCTION_ARGS)
Definition mac.c:150
Datum macaddr_sortsupport(PG_FUNCTION_ARGS)
Definition mac.c:352
#define lobits(addr)
Definition mac.c:31
Datum macaddr_ge(PG_FUNCTION_ARGS)
Definition mac.c:226
static int macaddr_fast_cmp(Datum x, Datum y, SortSupport ssup)
Definition mac.c:375
Datum macaddr_le(PG_FUNCTION_ARGS)
Definition mac.c:208
Datum macaddr_out(PG_FUNCTION_ARGS)
Definition mac.c:110
Datum macaddr_gt(PG_FUNCTION_ARGS)
Definition mac.c:235
void * palloc(Size size)
Definition mcxt.c:1387
static char * errmsg
#define DatumBigEndianToNative(x)
Definition pg_bswap.h:145
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:260
uint64_t Datum
Definition postgres.h:70
void pq_begintypsend(StringInfo buf)
Definition pqformat.c:325
int pq_getmsgbyte(StringInfo msg)
Definition pqformat.c:398
bytea * pq_endtypsend(StringInfo buf)
Definition pqformat.c:345
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition pqformat.h:160
char * c
e
static int fb(int x)
struct StringInfoData * StringInfo
Definition string.h:15
Definition nodes.h:135
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Datum(* abbrev_converter)(Datum original, SortSupport ssup)
int(* abbrev_full_comparator)(Datum x, Datum y, SortSupport ssup)
bool(* abbrev_abort)(int memtupcount, SortSupport ssup)
Definition inet.h:95
unsigned char e
Definition inet.h:100
unsigned char b
Definition inet.h:97
unsigned char f
Definition inet.h:101
unsigned char c
Definition inet.h:98
unsigned char a
Definition inet.h:96
unsigned char d
Definition inet.h:99
int ssup_datum_unsigned_cmp(Datum x, Datum y, SortSupport ssup)
Definition tuplesort.c:3447
#define PG_GETARG_MACADDR_P(n)
Definition inet.h:158
#define PG_RETURN_MACADDR_P(x)
Definition inet.h:159
static macaddr * DatumGetMacaddrP(Datum X)
Definition inet.h:147