2 * PostgreSQL type definitions for MAC addresses.
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
);