~ubuntu-branches/ubuntu/precise/postgresql-9.1/precise-security

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/mac.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      PostgreSQL type definitions for MAC addresses.
 
3
 *
 
4
 *      src/backend/utils/adt/mac.c
 
5
 */
 
6
 
 
7
#include "postgres.h"
 
8
 
 
9
#include "access/hash.h"
 
10
#include "libpq/pqformat.h"
 
11
#include "utils/builtins.h"
 
12
#include "utils/inet.h"
 
13
 
 
14
 
 
15
/*
 
16
 *      Utility macros used for sorting and comparing:
 
17
 */
 
18
 
 
19
#define hibits(addr) \
 
20
  ((unsigned long)(((addr)->a<<16)|((addr)->b<<8)|((addr)->c)))
 
21
 
 
22
#define lobits(addr) \
 
23
  ((unsigned long)(((addr)->d<<16)|((addr)->e<<8)|((addr)->f)))
 
24
 
 
25
/*
 
26
 *      MAC address reader.  Accepts several common notations.
 
27
 */
 
28
 
 
29
Datum
 
30
macaddr_in(PG_FUNCTION_ARGS)
 
31
{
 
32
        char       *str = PG_GETARG_CSTRING(0);
 
33
        macaddr    *result;
 
34
        int                     a,
 
35
                                b,
 
36
                                c,
 
37
                                d,
 
38
                                e,
 
39
                                f;
 
40
        char            junk[2];
 
41
        int                     count;
 
42
 
 
43
        /* %1s matches iff there is trailing non-whitespace garbage */
 
44
 
 
45
        count = sscanf(str, "%x:%x:%x:%x:%x:%x%1s",
 
46
                                   &a, &b, &c, &d, &e, &f, junk);
 
47
        if (count != 6)
 
48
                count = sscanf(str, "%x-%x-%x-%x-%x-%x%1s",
 
49
                                           &a, &b, &c, &d, &e, &f, junk);
 
50
        if (count != 6)
 
51
                count = sscanf(str, "%2x%2x%2x:%2x%2x%2x%1s",
 
52
                                           &a, &b, &c, &d, &e, &f, junk);
 
53
        if (count != 6)
 
54
                count = sscanf(str, "%2x%2x%2x-%2x%2x%2x%1s",
 
55
                                           &a, &b, &c, &d, &e, &f, junk);
 
56
        if (count != 6)
 
57
                count = sscanf(str, "%2x%2x.%2x%2x.%2x%2x%1s",
 
58
                                           &a, &b, &c, &d, &e, &f, junk);
 
59
        if (count != 6)
 
60
                count = sscanf(str, "%2x%2x%2x%2x%2x%2x%1s",
 
61
                                           &a, &b, &c, &d, &e, &f, junk);
 
62
        if (count != 6)
 
63
                ereport(ERROR,
 
64
                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 
65
                          errmsg("invalid input syntax for type macaddr: \"%s\"", str)));
 
66
 
 
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))
 
70
                ereport(ERROR,
 
71
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 
72
                   errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
 
73
 
 
74
        result = (macaddr *) palloc(sizeof(macaddr));
 
75
 
 
76
        result->a = a;
 
77
        result->b = b;
 
78
        result->c = c;
 
79
        result->d = d;
 
80
        result->e = e;
 
81
        result->f = f;
 
82
 
 
83
        PG_RETURN_MACADDR_P(result);
 
84
}
 
85
 
 
86
/*
 
87
 *      MAC address output function.  Fixed format.
 
88
 */
 
89
 
 
90
Datum
 
91
macaddr_out(PG_FUNCTION_ARGS)
 
92
{
 
93
        macaddr    *addr = PG_GETARG_MACADDR_P(0);
 
94
        char       *result;
 
95
 
 
96
        result = (char *) palloc(32);
 
97
 
 
98
        snprintf(result, 32, "%02x:%02x:%02x:%02x:%02x:%02x",
 
99
                         addr->a, addr->b, addr->c, addr->d, addr->e, addr->f);
 
100
 
 
101
        PG_RETURN_CSTRING(result);
 
102
}
 
103
 
 
104
/*
 
105
 *              macaddr_recv                    - converts external binary format to macaddr
 
106
 *
 
107
 * The external representation is just the six bytes, MSB first.
 
108
 */
 
109
Datum
 
110
macaddr_recv(PG_FUNCTION_ARGS)
 
111
{
 
112
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
 
113
        macaddr    *addr;
 
114
 
 
115
        addr = (macaddr *) palloc(sizeof(macaddr));
 
116
 
 
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);
 
123
 
 
124
        PG_RETURN_MACADDR_P(addr);
 
125
}
 
126
 
 
127
/*
 
128
 *              macaddr_send                    - converts macaddr to binary format
 
129
 */
 
130
Datum
 
131
macaddr_send(PG_FUNCTION_ARGS)
 
132
{
 
133
        macaddr    *addr = PG_GETARG_MACADDR_P(0);
 
134
        StringInfoData buf;
 
135
 
 
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));
 
144
}
 
145
 
 
146
 
 
147
/*
 
148
 *      Comparison function for sorting:
 
149
 */
 
150
 
 
151
static int32
 
152
macaddr_cmp_internal(macaddr *a1, macaddr *a2)
 
153
{
 
154
        if (hibits(a1) < hibits(a2))
 
155
                return -1;
 
156
        else if (hibits(a1) > hibits(a2))
 
157
                return 1;
 
158
        else if (lobits(a1) < lobits(a2))
 
159
                return -1;
 
160
        else if (lobits(a1) > lobits(a2))
 
161
                return 1;
 
162
        else
 
163
                return 0;
 
164
}
 
165
 
 
166
Datum
 
167
macaddr_cmp(PG_FUNCTION_ARGS)
 
168
{
 
169
        macaddr    *a1 = PG_GETARG_MACADDR_P(0);
 
170
        macaddr    *a2 = PG_GETARG_MACADDR_P(1);
 
171
 
 
172
        PG_RETURN_INT32(macaddr_cmp_internal(a1, a2));
 
173
}
 
174
 
 
175
/*
 
176
 *      Boolean comparisons.
 
177
 */
 
178
 
 
179
Datum
 
180
macaddr_lt(PG_FUNCTION_ARGS)
 
181
{
 
182
        macaddr    *a1 = PG_GETARG_MACADDR_P(0);
 
183
        macaddr    *a2 = PG_GETARG_MACADDR_P(1);
 
184
 
 
185
        PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) < 0);
 
186
}
 
187
 
 
188
Datum
 
189
macaddr_le(PG_FUNCTION_ARGS)
 
190
{
 
191
        macaddr    *a1 = PG_GETARG_MACADDR_P(0);
 
192
        macaddr    *a2 = PG_GETARG_MACADDR_P(1);
 
193
 
 
194
        PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) <= 0);
 
195
}
 
196
 
 
197
Datum
 
198
macaddr_eq(PG_FUNCTION_ARGS)
 
199
{
 
200
        macaddr    *a1 = PG_GETARG_MACADDR_P(0);
 
201
        macaddr    *a2 = PG_GETARG_MACADDR_P(1);
 
202
 
 
203
        PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) == 0);
 
204
}
 
205
 
 
206
Datum
 
207
macaddr_ge(PG_FUNCTION_ARGS)
 
208
{
 
209
        macaddr    *a1 = PG_GETARG_MACADDR_P(0);
 
210
        macaddr    *a2 = PG_GETARG_MACADDR_P(1);
 
211
 
 
212
        PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) >= 0);
 
213
}
 
214
 
 
215
Datum
 
216
macaddr_gt(PG_FUNCTION_ARGS)
 
217
{
 
218
        macaddr    *a1 = PG_GETARG_MACADDR_P(0);
 
219
        macaddr    *a2 = PG_GETARG_MACADDR_P(1);
 
220
 
 
221
        PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) > 0);
 
222
}
 
223
 
 
224
Datum
 
225
macaddr_ne(PG_FUNCTION_ARGS)
 
226
{
 
227
        macaddr    *a1 = PG_GETARG_MACADDR_P(0);
 
228
        macaddr    *a2 = PG_GETARG_MACADDR_P(1);
 
229
 
 
230
        PG_RETURN_BOOL(macaddr_cmp_internal(a1, a2) != 0);
 
231
}
 
232
 
 
233
/*
 
234
 * Support function for hash indexes on macaddr.
 
235
 */
 
236
Datum
 
237
hashmacaddr(PG_FUNCTION_ARGS)
 
238
{
 
239
        macaddr    *key = PG_GETARG_MACADDR_P(0);
 
240
 
 
241
        return hash_any((unsigned char *) key, sizeof(macaddr));
 
242
}
 
243
 
 
244
/*
 
245
 *      Truncation function to allow comparing mac manufacturers.
 
246
 *      From suggestion by Alex Pilosov <alex@pilosoft.com>
 
247
 */
 
248
Datum
 
249
macaddr_trunc(PG_FUNCTION_ARGS)
 
250
{
 
251
        macaddr    *addr = PG_GETARG_MACADDR_P(0);
 
252
        macaddr    *result;
 
253
 
 
254
        result = (macaddr *) palloc(sizeof(macaddr));
 
255
 
 
256
        result->a = addr->a;
 
257
        result->b = addr->b;
 
258
        result->c = addr->c;
 
259
        result->d = 0;
 
260
        result->e = 0;
 
261
        result->f = 0;
 
262
 
 
263
        PG_RETURN_MACADDR_P(result);
 
264
}