2 * PostgreSQL type definitions for MAC addresses.
4 * $Header: /cvsroot/pgsql/src/backend/utils/adt/mac.c,v 1.26 2002/09/04 20:31:28 momjian Exp $
9 #include "access/hash.h"
10 #include "utils/builtins.h"
11 #include "utils/inet.h"
14 * Utility macros used for sorting and comparing:
17 #define hibits(addr) \
18 ((unsigned long)(((addr)->a<<16)|((addr)->b<<8)|((addr)->c)))
20 #define lobits(addr) \
21 ((unsigned long)(((addr)->d<<16)|((addr)->e<<8)|((addr)->f)))
24 * MAC address reader. Accepts several common notations.
28 macaddr_in(PG_FUNCTION_ARGS)
30 char *str = PG_GETARG_CSTRING(0);
40 count = sscanf(str, "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f);
42 count = sscanf(str, "%x-%x-%x-%x-%x-%x", &a, &b, &c, &d, &e, &f);
44 count = sscanf(str, "%2x%2x%2x:%2x%2x%2x", &a, &b, &c, &d, &e, &f);
46 count = sscanf(str, "%2x%2x%2x-%2x%2x%2x", &a, &b, &c, &d, &e, &f);
48 count = sscanf(str, "%2x%2x.%2x%2x.%2x%2x", &a, &b, &c, &d, &e, &f);
50 count = sscanf(str, "%2x%2x%2x%2x%2x%2x", &a, &b, &c, &d, &e, &f);
52 elog(ERROR, "macaddr_in: error in parsing \"%s\"", str);
54 if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
55 (c < 0) || (c > 255) || (d < 0) || (d > 255) ||
56 (e < 0) || (e > 255) || (f < 0) || (f > 255))
57 elog(ERROR, "macaddr_in: illegal address \"%s\"", str);
59 result = (macaddr *) palloc(sizeof(macaddr));
68 PG_RETURN_MACADDR_P(result);
72 * MAC address output function. Fixed format.
76 macaddr_out(PG_FUNCTION_ARGS)
78 macaddr *addr = PG_GETARG_MACADDR_P(0);
81 result = (char *) palloc(32);
83 snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x",
84 addr->a, addr->b, addr->c, addr->d, addr->e, addr->f);
86 PG_RETURN_CSTRING(result);
90 * Convert macaddr to text data type.
94 macaddr_text(PG_FUNCTION_ARGS)
96 /* Input is a macaddr, but may as well leave it in Datum form */
97 Datum addr = PG_GETARG_DATUM(0);
102 str = DatumGetCString(DirectFunctionCall1(macaddr_out, addr));
104 len = (strlen(str) + VARHDRSZ);
106 result = palloc(len);
108 VARATT_SIZEP(result) = len;
109 memmove(VARDATA(result), str, (len - VARHDRSZ));
113 PG_RETURN_TEXT_P(result);
117 * Convert text to macaddr data type.
121 text_macaddr(PG_FUNCTION_ARGS)
123 text *addr = PG_GETARG_TEXT_P(0);
128 len = (VARSIZE(addr) - VARHDRSZ);
130 elog(ERROR, "Text is too long to convert to MAC address");
132 memcpy(str, VARDATA(addr), len);
135 result = DirectFunctionCall1(macaddr_in, CStringGetDatum(str));
141 * Comparison function for sorting:
145 macaddr_cmp_internal(macaddr *a1, macaddr *a2)
147 if (hibits(a1) < hibits(a2))
149 else if (hibits(a1) > hibits(a2))
151 else if (lobits(a1) < lobits(a2))
153 else if (lobits(a1) > lobits(a2))
160 macaddr_cmp(PG_FUNCTION_ARGS)
162 macaddr *a1 = PG_GETARG_MACADDR_P(0);
163 macaddr *a2 = PG_GETARG_MACADDR_P(1);
165 PG_RETURN_INT32(macaddr_cmp_internal(a1, a2));
169 * Boolean comparisons.
173 macaddr_lt(PG_FUNCTION_ARGS)
175 macaddr *a1 = PG_GETARG_MACADDR_P(0);
176 macaddr *a2 = PG_GETARG_MACADDR_P(1);
178 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) < 0);
182 macaddr_le(PG_FUNCTION_ARGS)
184 macaddr *a1 = PG_GETARG_MACADDR_P(0);
185 macaddr *a2 = PG_GETARG_MACADDR_P(1);
187 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) <= 0);
191 macaddr_eq(PG_FUNCTION_ARGS)
193 macaddr *a1 = PG_GETARG_MACADDR_P(0);
194 macaddr *a2 = PG_GETARG_MACADDR_P(1);
196 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) == 0);
200 macaddr_ge(PG_FUNCTION_ARGS)
202 macaddr *a1 = PG_GETARG_MACADDR_P(0);
203 macaddr *a2 = PG_GETARG_MACADDR_P(1);
205 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) >= 0);
209 macaddr_gt(PG_FUNCTION_ARGS)
211 macaddr *a1 = PG_GETARG_MACADDR_P(0);
212 macaddr *a2 = PG_GETARG_MACADDR_P(1);
214 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) > 0);
218 macaddr_ne(PG_FUNCTION_ARGS)
220 macaddr *a1 = PG_GETARG_MACADDR_P(0);
221 macaddr *a2 = PG_GETARG_MACADDR_P(1);
223 PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) != 0);
227 * Support function for hash indexes on macaddr.
230 hashmacaddr(PG_FUNCTION_ARGS)
232 macaddr *key = PG_GETARG_MACADDR_P(0);
234 return hash_any((unsigned char *) key, sizeof(macaddr));
238 * Truncation function to allow comparing mac manufacturers.
239 * From suggestion by Alex Pilosov <alex@pilosoft.com>
242 macaddr_trunc(PG_FUNCTION_ARGS)
244 macaddr *addr = PG_GETARG_MACADDR_P(0);
247 result = (macaddr *) palloc(sizeof(macaddr));
256 PG_RETURN_MACADDR_P(result);