2
* PostgreSQL type definitions for MAC addresses.
4
* src/backend/utils/adt/mac.c
9
#include "access/hash.h"
10
#include "libpq/pqformat.h"
11
#include "utils/builtins.h"
12
#include "utils/inet.h"
16
* Utility macros used for sorting and comparing:
19
#define hibits(addr) \
20
((unsigned long)(((addr)->a<<16)|((addr)->b<<8)|((addr)->c)))
22
#define lobits(addr) \
23
((unsigned long)(((addr)->d<<16)|((addr)->e<<8)|((addr)->f)))
26
* MAC address reader. Accepts several common notations.
30
macaddr_in(PG_FUNCTION_ARGS)
32
char *str = PG_GETARG_CSTRING(0);
43
/* %1s matches iff there is trailing non-whitespace garbage */
45
count = sscanf(str, "%x:%x:%x:%x:%x:%x%1s",
46
&a, &b, &c, &d, &e, &f, junk);
48
count = sscanf(str, "%x-%x-%x-%x-%x-%x%1s",
49
&a, &b, &c, &d, &e, &f, junk);
51
count = sscanf(str, "%2x%2x%2x:%2x%2x%2x%1s",
52
&a, &b, &c, &d, &e, &f, junk);
54
count = sscanf(str, "%2x%2x%2x-%2x%2x%2x%1s",
55
&a, &b, &c, &d, &e, &f, junk);
57
count = sscanf(str, "%2x%2x.%2x%2x.%2x%2x%1s",
58
&a, &b, &c, &d, &e, &f, junk);
60
count = sscanf(str, "%2x%2x%2x%2x%2x%2x%1s",
61
&a, &b, &c, &d, &e, &f, junk);
64
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
65
errmsg("invalid input syntax for type macaddr: \"%s\"", str)));
67
if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
68
(c < 0) || (c > 255) || (d < 0) || (d > 255) ||
69
(e < 0) || (e > 255) || (f < 0) || (f > 255))
71
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
72
errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
74
result = (macaddr *) palloc(sizeof(macaddr));
83
PG_RETURN_MACADDR_P(result);
87
* MAC address output function. Fixed format.
91
macaddr_out(PG_FUNCTION_ARGS)
93
macaddr *addr = PG_GETARG_MACADDR_P(0);
96
result = (char *) palloc(32);
98
snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x",
99
addr->a, addr->b, addr->c, addr->d, addr->e, addr->f);
101
PG_RETURN_CSTRING(result);
105
* macaddr_recv - converts external binary format to macaddr
107
* The external representation is just the six bytes, MSB first.
110
macaddr_recv(PG_FUNCTION_ARGS)
112
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
115
addr = (macaddr *) palloc(sizeof(macaddr));
117
addr->a = pq_getmsgbyte(buf);
118
addr->b = pq_getmsgbyte(buf);
119
addr->c = pq_getmsgbyte(buf);
120
addr->d = pq_getmsgbyte(buf);
121
addr->e = pq_getmsgbyte(buf);
122
addr->f = pq_getmsgbyte(buf);
124
PG_RETURN_MACADDR_P(addr);
128
* macaddr_send - converts macaddr to binary format
131
macaddr_send(PG_FUNCTION_ARGS)
133
macaddr *addr = PG_GETARG_MACADDR_P(0);
136
pq_begintypsend(&buf);
137
pq_sendbyte(&buf, addr->a);
138
pq_sendbyte(&buf, addr->b);
139
pq_sendbyte(&buf, addr->c);
140
pq_sendbyte(&buf, addr->d);
141
pq_sendbyte(&buf, addr->e);
142
pq_sendbyte(&buf, addr->f);
143
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
148
* Comparison function for sorting:
152
macaddr_cmp_internal(macaddr *a1, macaddr *a2)
154
if (hibits(a1) < hibits(a2))
156
else if (hibits(a1) > hibits(a2))
158
else if (lobits(a1) < lobits(a2))
160
else if (lobits(a1) > lobits(a2))
167
macaddr_cmp(PG_FUNCTION_ARGS)
169
macaddr *a1 = PG_GETARG_MACADDR_P(0);
170
macaddr *a2 = PG_GETARG_MACADDR_P(1);
172
PG_RETURN_INT32(macaddr_cmp_internal(a1, a2));
176
* Boolean comparisons.
180
macaddr_lt(PG_FUNCTION_ARGS)
182
macaddr *a1 = PG_GETARG_MACADDR_P(0);
183
macaddr *a2 = PG_GETARG_MACADDR_P(1);
185
PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) < 0);
189
macaddr_le(PG_FUNCTION_ARGS)
191
macaddr *a1 = PG_GETARG_MACADDR_P(0);
192
macaddr *a2 = PG_GETARG_MACADDR_P(1);
194
PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) <= 0);
198
macaddr_eq(PG_FUNCTION_ARGS)
200
macaddr *a1 = PG_GETARG_MACADDR_P(0);
201
macaddr *a2 = PG_GETARG_MACADDR_P(1);
203
PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) == 0);
207
macaddr_ge(PG_FUNCTION_ARGS)
209
macaddr *a1 = PG_GETARG_MACADDR_P(0);
210
macaddr *a2 = PG_GETARG_MACADDR_P(1);
212
PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) >= 0);
216
macaddr_gt(PG_FUNCTION_ARGS)
218
macaddr *a1 = PG_GETARG_MACADDR_P(0);
219
macaddr *a2 = PG_GETARG_MACADDR_P(1);
221
PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) > 0);
225
macaddr_ne(PG_FUNCTION_ARGS)
227
macaddr *a1 = PG_GETARG_MACADDR_P(0);
228
macaddr *a2 = PG_GETARG_MACADDR_P(1);
230
PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) != 0);
234
* Support function for hash indexes on macaddr.
237
hashmacaddr(PG_FUNCTION_ARGS)
239
macaddr *key = PG_GETARG_MACADDR_P(0);
241
return hash_any((unsigned char *) key, sizeof(macaddr));
245
* Truncation function to allow comparing mac manufacturers.
246
* From suggestion by Alex Pilosov <alex@pilosoft.com>
249
macaddr_trunc(PG_FUNCTION_ARGS)
251
macaddr *addr = PG_GETARG_MACADDR_P(0);
254
result = (macaddr *) palloc(sizeof(macaddr));
263
PG_RETURN_MACADDR_P(result);