Age Owner TLA Line data Source code
1 : /*
2 : * PostgreSQL type definitions for the INET and CIDR types.
3 : *
4 : * src/backend/utils/adt/network.c
5 : *
6 : * Jon Postel RIP 16 Oct 1998
7 : */
8 :
9 : #include "postgres.h"
10 :
11 : #include <sys/socket.h>
12 : #include <netinet/in.h>
13 : #include <arpa/inet.h>
14 :
15 : #include "access/stratnum.h"
16 : #include "catalog/pg_opfamily.h"
17 : #include "catalog/pg_type.h"
18 : #include "common/hashfn.h"
19 : #include "common/ip.h"
20 : #include "lib/hyperloglog.h"
21 : #include "libpq/libpq-be.h"
22 : #include "libpq/pqformat.h"
23 : #include "miscadmin.h"
24 : #include "nodes/makefuncs.h"
25 : #include "nodes/nodeFuncs.h"
26 : #include "nodes/supportnodes.h"
27 : #include "utils/builtins.h"
28 : #include "utils/fmgroids.h"
29 : #include "utils/guc.h"
30 : #include "utils/inet.h"
31 : #include "utils/lsyscache.h"
32 : #include "utils/sortsupport.h"
33 :
34 :
35 : /*
36 : * An IPv4 netmask size is a value in the range of 0 - 32, which is
37 : * represented with 6 bits in inet/cidr abbreviated keys where possible.
38 : *
39 : * An IPv4 inet/cidr abbreviated key can use up to 25 bits for subnet
40 : * component.
41 : */
42 : #define ABBREV_BITS_INET4_NETMASK_SIZE 6
43 : #define ABBREV_BITS_INET4_SUBNET 25
44 :
45 : /* sortsupport for inet/cidr */
46 : typedef struct
47 : {
48 : int64 input_count; /* number of non-null values seen */
49 : bool estimating; /* true if estimating cardinality */
50 :
51 : hyperLogLogState abbr_card; /* cardinality estimator */
52 : } network_sortsupport_state;
53 :
54 : static int32 network_cmp_internal(inet *a1, inet *a2);
55 : static int network_fast_cmp(Datum x, Datum y, SortSupport ssup);
56 : static bool network_abbrev_abort(int memtupcount, SortSupport ssup);
57 : static Datum network_abbrev_convert(Datum original, SortSupport ssup);
58 : static List *match_network_function(Node *leftop,
59 : Node *rightop,
60 : int indexarg,
61 : Oid funcid,
62 : Oid opfamily);
63 : static List *match_network_subset(Node *leftop,
64 : Node *rightop,
65 : bool is_eq,
66 : Oid opfamily);
67 : static bool addressOK(unsigned char *a, int bits, int family);
68 : static inet *internal_inetpl(inet *ip, int64 addend);
69 :
70 :
71 : /*
72 : * Common INET/CIDR input routine
73 : */
74 : static inet *
116 tgl 75 GNC 2348 : network_in(char *src, bool is_cidr, Node *escontext)
76 : {
77 : int bits;
78 : inet *dst;
79 :
5847 tgl 80 CBC 2348 : dst = (inet *) palloc0(sizeof(inet));
81 :
82 : /*
83 : * First, check to see if this is an IPv6 or IPv4 address. IPv6 addresses
84 : * will have a : somewhere in them (several, in fact) so if there is one
85 : * present, assume it's V6, otherwise assume it's V4.
86 : */
87 :
7191 88 2348 : if (strchr(src, ':') != NULL)
7229 bruce 89 448 : ip_family(dst) = PGSQL_AF_INET6;
90 : else
91 1900 : ip_family(dst) = PGSQL_AF_INET;
92 :
1330 tgl 93 3047 : bits = pg_inet_net_pton(ip_family(dst), src, ip_addr(dst),
94 699 : is_cidr ? ip_addrsize(dst) : -1);
7229 bruce 95 2348 : if ((bits < 0) || (bits > ip_maxbits(dst)))
116 tgl 96 GNC 15 : ereturn(escontext, NULL,
97 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
98 : /* translator: first %s is inet or cidr */
99 : errmsg("invalid input syntax for type %s: \"%s\"",
100 : is_cidr ? "cidr" : "inet", src)));
101 :
102 : /*
103 : * Error check: CIDR values must not have any bits set beyond the masklen.
104 : */
6285 bruce 105 CBC 2333 : if (is_cidr)
106 : {
7229 107 690 : if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
116 tgl 108 GNC 15 : ereturn(escontext, NULL,
109 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
110 : errmsg("invalid cidr value: \"%s\"", src),
111 : errdetail("Value has bits set to right of mask.")));
112 : }
113 :
8935 bruce 114 CBC 2318 : ip_bits(dst) = bits;
5847 tgl 115 2318 : SET_INET_VARSIZE(dst);
116 :
8935 bruce 117 2318 : return dst;
118 : }
119 :
120 : Datum
8284 tgl 121 1649 : inet_in(PG_FUNCTION_ARGS)
122 : {
123 1649 : char *src = PG_GETARG_CSTRING(0);
124 :
116 tgl 125 GNC 1649 : PG_RETURN_INET_P(network_in(src, false, fcinfo->context));
126 : }
127 :
128 : Datum
8284 tgl 129 CBC 699 : cidr_in(PG_FUNCTION_ARGS)
130 : {
131 699 : char *src = PG_GETARG_CSTRING(0);
132 :
116 tgl 133 GNC 699 : PG_RETURN_INET_P(network_in(src, true, fcinfo->context));
134 : }
135 :
136 :
137 : /*
138 : * Common INET/CIDR output routine
139 : */
140 : static char *
6282 tgl 141 CBC 7038 : network_out(inet *src, bool is_cidr)
142 : {
143 : char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
144 : char *dst;
145 : int len;
146 :
1330 147 7038 : dst = pg_inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
148 : tmp, sizeof(tmp));
7229 bruce 149 7038 : if (dst == NULL)
7196 tgl 150 UBC 0 : ereport(ERROR,
151 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
152 : errmsg("could not format inet value: %m")));
153 :
154 : /* For CIDR, add /n if not present */
6282 tgl 155 CBC 7038 : if (is_cidr && strchr(tmp, '/') == NULL)
156 : {
7229 bruce 157 539 : len = strlen(tmp);
158 539 : snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
159 : }
160 :
6282 tgl 161 7038 : return pstrdup(tmp);
162 : }
163 :
164 : Datum
165 4238 : inet_out(PG_FUNCTION_ARGS)
166 : {
4136 heikki.linnakangas 167 4238 : inet *src = PG_GETARG_INET_PP(0);
168 :
6282 tgl 169 4238 : PG_RETURN_CSTRING(network_out(src, false));
170 : }
171 :
172 : Datum
8284 173 2800 : cidr_out(PG_FUNCTION_ARGS)
174 : {
4136 heikki.linnakangas 175 2800 : inet *src = PG_GETARG_INET_PP(0);
176 :
6282 tgl 177 2800 : PG_RETURN_CSTRING(network_out(src, true));
178 : }
179 :
180 :
181 : /*
182 : * network_recv - converts external binary format to inet
183 : *
184 : * The external representation is (one byte apiece for)
185 : * family, bits, is_cidr, address length, address in network byte order.
186 : *
187 : * Presence of is_cidr is largely for historical reasons, though it might
188 : * allow some code-sharing on the client side. We send it correctly on
189 : * output, but ignore the value on input.
190 : */
191 : static inet *
6282 tgl 192 UBC 0 : network_recv(StringInfo buf, bool is_cidr)
193 : {
194 : inet *addr;
195 : char *addrptr;
196 : int bits;
197 : int nb,
198 : i;
199 :
200 : /* make sure any unused bits in a CIDR value are zeroed */
5847 201 0 : addr = (inet *) palloc0(sizeof(inet));
202 :
7271 203 0 : ip_family(addr) = pq_getmsgbyte(buf);
7191 204 0 : if (ip_family(addr) != PGSQL_AF_INET &&
205 0 : ip_family(addr) != PGSQL_AF_INET6)
7196 206 0 : ereport(ERROR,
207 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
208 : /* translator: %s is inet or cidr */
209 : errmsg("invalid address family in external \"%s\" value",
210 : is_cidr ? "cidr" : "inet")));
7271 211 0 : bits = pq_getmsgbyte(buf);
7229 bruce 212 0 : if (bits < 0 || bits > ip_maxbits(addr))
7196 tgl 213 0 : ereport(ERROR,
214 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
215 : /* translator: %s is inet or cidr */
216 : errmsg("invalid bits in external \"%s\" value",
217 : is_cidr ? "cidr" : "inet")));
7271 218 0 : ip_bits(addr) = bits;
6282 219 0 : i = pq_getmsgbyte(buf); /* ignore is_cidr */
7271 220 0 : nb = pq_getmsgbyte(buf);
221 0 : if (nb != ip_addrsize(addr))
7196 222 0 : ereport(ERROR,
223 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
224 : /* translator: %s is inet or cidr */
225 : errmsg("invalid length in external \"%s\" value",
226 : is_cidr ? "cidr" : "inet")));
227 :
7188 bruce 228 0 : addrptr = (char *) ip_addr(addr);
7271 tgl 229 0 : for (i = 0; i < nb; i++)
230 0 : addrptr[i] = pq_getmsgbyte(buf);
231 :
232 : /*
233 : * Error check: CIDR values must not have any bits set beyond the masklen.
234 : */
6282 235 0 : if (is_cidr)
236 : {
7229 bruce 237 0 : if (!addressOK(ip_addr(addr), bits, ip_family(addr)))
7196 tgl 238 0 : ereport(ERROR,
239 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
240 : errmsg("invalid external \"cidr\" value"),
241 : errdetail("Value has bits set to right of mask.")));
242 : }
243 :
5847 244 0 : SET_INET_VARSIZE(addr);
245 :
6282 246 0 : return addr;
247 : }
248 :
249 : Datum
250 0 : inet_recv(PG_FUNCTION_ARGS)
251 : {
252 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
253 :
254 0 : PG_RETURN_INET_P(network_recv(buf, false));
255 : }
256 :
257 : Datum
7271 258 0 : cidr_recv(PG_FUNCTION_ARGS)
259 : {
6282 260 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
261 :
262 0 : PG_RETURN_INET_P(network_recv(buf, true));
263 : }
264 :
265 :
266 : /*
267 : * network_send - converts inet to binary format
268 : */
269 : static bytea *
270 0 : network_send(inet *addr, bool is_cidr)
271 : {
272 : StringInfoData buf;
273 : char *addrptr;
274 : int nb,
275 : i;
276 :
7271 277 0 : pq_begintypsend(&buf);
278 0 : pq_sendbyte(&buf, ip_family(addr));
279 0 : pq_sendbyte(&buf, ip_bits(addr));
6282 280 0 : pq_sendbyte(&buf, is_cidr);
7271 281 0 : nb = ip_addrsize(addr);
282 0 : if (nb < 0)
283 0 : nb = 0;
284 0 : pq_sendbyte(&buf, nb);
7188 bruce 285 0 : addrptr = (char *) ip_addr(addr);
7271 tgl 286 0 : for (i = 0; i < nb; i++)
287 0 : pq_sendbyte(&buf, addrptr[i]);
6282 288 0 : return pq_endtypsend(&buf);
289 : }
290 :
291 : Datum
292 0 : inet_send(PG_FUNCTION_ARGS)
293 : {
4136 heikki.linnakangas 294 0 : inet *addr = PG_GETARG_INET_PP(0);
295 :
6282 tgl 296 0 : PG_RETURN_BYTEA_P(network_send(addr, false));
297 : }
298 :
299 : Datum
7271 300 0 : cidr_send(PG_FUNCTION_ARGS)
301 : {
4136 heikki.linnakangas 302 0 : inet *addr = PG_GETARG_INET_PP(0);
303 :
6282 tgl 304 0 : PG_RETURN_BYTEA_P(network_send(addr, true));
305 : }
306 :
307 :
308 : Datum
6282 tgl 309 CBC 1770 : inet_to_cidr(PG_FUNCTION_ARGS)
310 : {
4136 heikki.linnakangas 311 1770 : inet *src = PG_GETARG_INET_PP(0);
312 : int bits;
313 :
6282 tgl 314 1770 : bits = ip_bits(src);
315 :
316 : /* safety check */
317 1770 : if ((bits < 0) || (bits > ip_maxbits(src)))
6282 tgl 318 UBC 0 : elog(ERROR, "invalid inet bit length: %d", bits);
319 :
2420 tgl 320 CBC 1770 : PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
321 : }
322 :
323 : Datum
7970 bruce 324 75 : inet_set_masklen(PG_FUNCTION_ARGS)
325 : {
4136 heikki.linnakangas 326 75 : inet *src = PG_GETARG_INET_PP(0);
7836 bruce 327 75 : int bits = PG_GETARG_INT32(1);
328 : inet *dst;
329 :
7188 330 75 : if (bits == -1)
331 24 : bits = ip_maxbits(src);
332 :
7229 333 75 : if ((bits < 0) || (bits > ip_maxbits(src)))
7196 tgl 334 UBC 0 : ereport(ERROR,
335 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
336 : errmsg("invalid mask length: %d", bits)));
337 :
338 : /* clone the original data */
5847 tgl 339 CBC 75 : dst = (inet *) palloc(VARSIZE_ANY(src));
340 75 : memcpy(dst, src, VARSIZE_ANY(src));
341 :
7836 bruce 342 75 : ip_bits(dst) = bits;
343 :
7970 344 75 : PG_RETURN_INET_P(dst);
345 : }
346 :
347 : Datum
6282 tgl 348 UBC 0 : cidr_set_masklen(PG_FUNCTION_ARGS)
349 : {
4136 heikki.linnakangas 350 0 : inet *src = PG_GETARG_INET_PP(0);
6282 tgl 351 0 : int bits = PG_GETARG_INT32(1);
352 :
353 0 : if (bits == -1)
354 0 : bits = ip_maxbits(src);
355 :
356 0 : if ((bits < 0) || (bits > ip_maxbits(src)))
357 0 : ereport(ERROR,
358 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
359 : errmsg("invalid mask length: %d", bits)));
360 :
2420 361 0 : PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
362 : }
363 :
364 : /*
365 : * Copy src and set mask length to 'bits' (which must be valid for the family)
366 : */
367 : inet *
2420 tgl 368 CBC 1884 : cidr_set_masklen_internal(const inet *src, int bits)
369 : {
370 1884 : inet *dst = (inet *) palloc0(sizeof(inet));
371 :
372 1884 : ip_family(dst) = ip_family(src);
373 1884 : ip_bits(dst) = bits;
374 :
375 1884 : if (bits > 0)
376 : {
377 1884 : Assert(bits <= ip_maxbits(dst));
378 :
379 : /* Clone appropriate bytes of the address, leaving the rest 0 */
380 1884 : memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
381 :
382 : /* Clear any unwanted bits in the last partial byte */
383 1884 : if (bits % 8)
384 30 : ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
385 : }
386 :
387 : /* Set varlena header correctly */
388 1884 : SET_INET_VARSIZE(dst);
389 :
390 1884 : return dst;
391 : }
392 :
393 : /*
394 : * Basic comparison function for sorting and inet/cidr comparisons.
395 : *
396 : * Comparison is first on the common bits of the network part, then on
397 : * the length of the network part, and then on the whole unmasked address.
398 : * The effect is that the network part is the major sort key, and for
399 : * equal network parts we sort on the host part. Note this is only sane
400 : * for CIDR if address bits to the right of the mask are guaranteed zero;
401 : * otherwise logically-equal CIDRs might compare different.
402 : */
403 :
404 : static int32
8284 405 238810 : network_cmp_internal(inet *a1, inet *a2)
406 : {
7229 bruce 407 238810 : if (ip_family(a1) == ip_family(a2))
408 : {
409 : int order;
410 :
411 163042 : order = bitncmp(ip_addr(a1), ip_addr(a2),
7188 412 163042 : Min(ip_bits(a1), ip_bits(a2)));
8199 tgl 413 163042 : if (order != 0)
414 152703 : return order;
415 10339 : order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
8284 416 10339 : if (order != 0)
417 438 : return order;
7229 bruce 418 9901 : return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
419 : }
420 :
421 75768 : return ip_family(a1) - ip_family(a2);
422 : }
423 :
424 : Datum
8284 tgl 425 134 : network_cmp(PG_FUNCTION_ARGS)
426 : {
4136 heikki.linnakangas 427 134 : inet *a1 = PG_GETARG_INET_PP(0);
428 134 : inet *a2 = PG_GETARG_INET_PP(1);
429 :
8284 tgl 430 134 : PG_RETURN_INT32(network_cmp_internal(a1, a2));
431 : }
432 :
433 : /*
434 : * SortSupport strategy routine
435 : */
436 : Datum
1347 pg 437 153 : network_sortsupport(PG_FUNCTION_ARGS)
438 : {
439 153 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
440 :
441 153 : ssup->comparator = network_fast_cmp;
442 153 : ssup->ssup_extra = NULL;
443 :
444 153 : if (ssup->abbreviate)
445 : {
446 : network_sortsupport_state *uss;
447 : MemoryContext oldcontext;
448 :
449 80 : oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
450 :
451 80 : uss = palloc(sizeof(network_sortsupport_state));
452 80 : uss->input_count = 0;
453 80 : uss->estimating = true;
454 80 : initHyperLogLog(&uss->abbr_card, 10);
455 :
456 80 : ssup->ssup_extra = uss;
457 :
372 john.naylor 458 80 : ssup->comparator = ssup_datum_unsigned_cmp;
1347 pg 459 80 : ssup->abbrev_converter = network_abbrev_convert;
460 80 : ssup->abbrev_abort = network_abbrev_abort;
461 80 : ssup->abbrev_full_comparator = network_fast_cmp;
462 :
463 80 : MemoryContextSwitchTo(oldcontext);
464 : }
465 :
466 153 : PG_RETURN_VOID();
467 : }
468 :
469 : /*
470 : * SortSupport comparison func
471 : */
472 : static int
473 5978 : network_fast_cmp(Datum x, Datum y, SortSupport ssup)
474 : {
475 5978 : inet *arg1 = DatumGetInetPP(x);
476 5978 : inet *arg2 = DatumGetInetPP(y);
477 :
478 5978 : return network_cmp_internal(arg1, arg2);
479 : }
480 :
481 : /*
482 : * Callback for estimating effectiveness of abbreviated key optimization.
483 : *
484 : * We pay no attention to the cardinality of the non-abbreviated data, because
485 : * there is no equality fast-path within authoritative inet comparator.
486 : */
487 : static bool
488 21 : network_abbrev_abort(int memtupcount, SortSupport ssup)
489 : {
490 21 : network_sortsupport_state *uss = ssup->ssup_extra;
491 : double abbr_card;
492 :
493 21 : if (memtupcount < 10000 || uss->input_count < 10000 || !uss->estimating)
494 21 : return false;
495 :
1347 pg 496 UBC 0 : abbr_card = estimateHyperLogLog(&uss->abbr_card);
497 :
498 : /*
499 : * If we have >100k distinct values, then even if we were sorting many
500 : * billion rows we'd likely still break even, and the penalty of undoing
501 : * that many rows of abbrevs would probably not be worth it. At this point
502 : * we stop counting because we know that we're now fully committed.
503 : */
504 0 : if (abbr_card > 100000.0)
505 : {
506 : #ifdef TRACE_SORT
507 0 : if (trace_sort)
508 0 : elog(LOG,
509 : "network_abbrev: estimation ends at cardinality %f"
510 : " after " INT64_FORMAT " values (%d rows)",
511 : abbr_card, uss->input_count, memtupcount);
512 : #endif
513 0 : uss->estimating = false;
514 0 : return false;
515 : }
516 :
517 : /*
518 : * Target minimum cardinality is 1 per ~2k of non-null inputs. 0.5 row
519 : * fudge factor allows us to abort earlier on genuinely pathological data
520 : * where we've had exactly one abbreviated value in the first 2k
521 : * (non-null) rows.
522 : */
523 0 : if (abbr_card < uss->input_count / 2000.0 + 0.5)
524 : {
525 : #ifdef TRACE_SORT
526 0 : if (trace_sort)
527 0 : elog(LOG,
528 : "network_abbrev: aborting abbreviation at cardinality %f"
529 : " below threshold %f after " INT64_FORMAT " values (%d rows)",
530 : abbr_card, uss->input_count / 2000.0 + 0.5, uss->input_count,
531 : memtupcount);
532 : #endif
533 0 : return true;
534 : }
535 :
536 : #ifdef TRACE_SORT
537 0 : if (trace_sort)
538 0 : elog(LOG,
539 : "network_abbrev: cardinality %f after " INT64_FORMAT
540 : " values (%d rows)", abbr_card, uss->input_count, memtupcount);
541 : #endif
542 :
543 0 : return false;
544 : }
545 :
546 : /*
547 : * SortSupport conversion routine. Converts original inet/cidr representation
548 : * to abbreviated key representation that works with simple 3-way unsigned int
549 : * comparisons. The network_cmp_internal() rules for sorting inet/cidr datums
550 : * are followed by abbreviated comparisons by an encoding scheme that
551 : * conditions keys through careful use of padding.
552 : *
553 : * Some background: inet values have three major components (take for example
554 : * the address 1.2.3.4/24):
555 : *
556 : * * A network, or netmasked bits (1.2.3.0).
557 : * * A netmask size (/24).
558 : * * A subnet, or bits outside of the netmask (0.0.0.4).
559 : *
560 : * cidr values are the same except that with only the first two components --
561 : * all their subnet bits *must* be zero (1.2.3.0/24).
562 : *
563 : * IPv4 and IPv6 are identical in this makeup, with the difference being that
564 : * IPv4 addresses have a maximum of 32 bits compared to IPv6's 64 bits, so in
565 : * IPv6 each part may be larger.
566 : *
567 : * inet/cidr types compare using these sorting rules. If inequality is detected
568 : * at any step, comparison is finished. If any rule is a tie, the algorithm
569 : * drops through to the next to break it:
570 : *
571 : * 1. IPv4 always appears before IPv6.
572 : * 2. Network bits are compared.
573 : * 3. Netmask size is compared.
574 : * 4. All bits are compared (having made it here, we know that both
575 : * netmasked bits and netmask size are equal, so we're in effect only
576 : * comparing subnet bits).
577 : *
578 : * When generating abbreviated keys for SortSupport, we pack as much as we can
579 : * into a datum while ensuring that when comparing those keys as integers,
580 : * these rules will be respected. Exact contents depend on IP family and datum
581 : * size.
582 : *
583 : * IPv4
584 : * ----
585 : *
586 : * 4 byte datums:
587 : *
588 : * Start with 1 bit for the IP family (IPv4 or IPv6; this bit is present in
589 : * every case below) followed by all but 1 of the netmasked bits.
590 : *
591 : * +----------+---------------------+
592 : * | 1 bit IP | 31 bits network | (1 bit network
593 : * | family | (truncated) | omitted)
594 : * +----------+---------------------+
595 : *
596 : * 8 byte datums:
597 : *
598 : * We have space to store all netmasked bits, followed by the netmask size,
599 : * followed by 25 bits of the subnet (25 bits is usually more than enough in
600 : * practice). cidr datums always have all-zero subnet bits.
601 : *
602 : * +----------+-----------------------+--------------+--------------------+
603 : * | 1 bit IP | 32 bits network | 6 bits | 25 bits subnet |
604 : * | family | (full) | network size | (truncated) |
605 : * +----------+-----------------------+--------------+--------------------+
606 : *
607 : * IPv6
608 : * ----
609 : *
610 : * 4 byte datums:
611 : *
612 : * +----------+---------------------+
613 : * | 1 bit IP | 31 bits network | (up to 97 bits
614 : * | family | (truncated) | network omitted)
615 : * +----------+---------------------+
616 : *
617 : * 8 byte datums:
618 : *
619 : * +----------+---------------------------------+
620 : * | 1 bit IP | 63 bits network | (up to 65 bits
621 : * | family | (truncated) | network omitted)
622 : * +----------+---------------------------------+
623 : */
624 : static Datum
1347 pg 625 CBC 774 : network_abbrev_convert(Datum original, SortSupport ssup)
626 : {
627 774 : network_sortsupport_state *uss = ssup->ssup_extra;
628 774 : inet *authoritative = DatumGetInetPP(original);
629 : Datum res,
630 : ipaddr_datum,
631 : subnet_bitmask,
632 : network;
633 : int subnet_size;
634 :
635 774 : Assert(ip_family(authoritative) == PGSQL_AF_INET ||
636 : ip_family(authoritative) == PGSQL_AF_INET6);
637 :
638 : /*
639 : * Get an unsigned integer representation of the IP address by taking its
640 : * first 4 or 8 bytes. Always take all 4 bytes of an IPv4 address. Take
641 : * the first 8 bytes of an IPv6 address with an 8 byte datum and 4 bytes
642 : * otherwise.
643 : *
644 : * We're consuming an array of unsigned char, so byteswap on little endian
645 : * systems (an inet's ipaddr field stores the most significant byte
646 : * first).
647 : */
648 774 : if (ip_family(authoritative) == PGSQL_AF_INET)
649 : {
650 : uint32 ipaddr_datum32;
651 :
652 585 : memcpy(&ipaddr_datum32, ip_addr(authoritative), sizeof(uint32));
653 :
654 : /* Must byteswap on little-endian machines */
655 : #ifndef WORDS_BIGENDIAN
656 585 : ipaddr_datum = pg_bswap32(ipaddr_datum32);
657 : #else
658 : ipaddr_datum = ipaddr_datum32;
659 : #endif
660 :
661 : /* Initialize result without setting ipfamily bit */
662 585 : res = (Datum) 0;
663 : }
664 : else
665 : {
666 189 : memcpy(&ipaddr_datum, ip_addr(authoritative), sizeof(Datum));
667 :
668 : /* Must byteswap on little-endian machines */
669 189 : ipaddr_datum = DatumBigEndianToNative(ipaddr_datum);
670 :
671 : /* Initialize result with ipfamily (most significant) bit set */
672 189 : res = ((Datum) 1) << (SIZEOF_DATUM * BITS_PER_BYTE - 1);
673 : }
674 :
675 : /*
676 : * ipaddr_datum must be "split": high order bits go in "network" component
677 : * of abbreviated key (often with zeroed bits at the end due to masking),
678 : * while low order bits go in "subnet" component when there is space for
679 : * one. This is often accomplished by generating a temp datum subnet
680 : * bitmask, which we may reuse later when generating the subnet bits
681 : * themselves. (Note that subnet bits are only used with IPv4 datums on
682 : * platforms where datum is 8 bytes.)
683 : *
684 : * The number of bits in subnet is used to generate a datum subnet
685 : * bitmask. For example, with a /24 IPv4 datum there are 8 subnet bits
686 : * (since 32 - 24 is 8), so the final subnet bitmask is B'1111 1111'. We
687 : * need explicit handling for cases where the ipaddr bits cannot all fit
688 : * in a datum, though (otherwise we'd incorrectly mask the network
689 : * component with IPv6 values).
690 : */
691 774 : subnet_size = ip_maxbits(authoritative) - ip_bits(authoritative);
692 774 : Assert(subnet_size >= 0);
693 : /* subnet size must work with prefix ipaddr cases */
694 774 : subnet_size %= SIZEOF_DATUM * BITS_PER_BYTE;
695 774 : if (ip_bits(authoritative) == 0)
696 : {
697 : /* Fit as many ipaddr bits as possible into subnet */
698 84 : subnet_bitmask = ((Datum) 0) - 1;
699 84 : network = 0;
700 : }
701 690 : else if (ip_bits(authoritative) < SIZEOF_DATUM * BITS_PER_BYTE)
702 : {
703 : /* Split ipaddr bits between network and subnet */
704 585 : subnet_bitmask = (((Datum) 1) << subnet_size) - 1;
705 585 : network = ipaddr_datum & ~subnet_bitmask;
706 : }
707 : else
708 : {
709 : /* Fit as many ipaddr bits as possible into network */
710 105 : subnet_bitmask = 0;
711 105 : network = ipaddr_datum;
712 : }
713 :
714 : #if SIZEOF_DATUM == 8
715 774 : if (ip_family(authoritative) == PGSQL_AF_INET)
716 : {
717 : /*
718 : * IPv4 with 8 byte datums: keep all 32 netmasked bits, netmask size,
719 : * and most significant 25 subnet bits
720 : */
721 585 : Datum netmask_size = (Datum) ip_bits(authoritative);
722 : Datum subnet;
723 :
724 : /*
725 : * Shift left 31 bits: 6 bits netmask size + 25 subnet bits.
726 : *
727 : * We don't make any distinction between network bits that are zero
728 : * due to masking and "true"/non-masked zero bits. An abbreviated
729 : * comparison that is resolved by comparing a non-masked and non-zero
730 : * bit to a masked/zeroed bit is effectively resolved based on
731 : * ip_bits(), even though the comparison won't reach the netmask_size
732 : * bits.
733 : */
734 585 : network <<= (ABBREV_BITS_INET4_NETMASK_SIZE +
735 : ABBREV_BITS_INET4_SUBNET);
736 :
737 : /* Shift size to make room for subnet bits at the end */
738 585 : netmask_size <<= ABBREV_BITS_INET4_SUBNET;
739 :
740 : /* Extract subnet bits without shifting them */
741 585 : subnet = ipaddr_datum & subnet_bitmask;
742 :
743 : /*
744 : * If we have more than 25 subnet bits, we can't fit everything. Shift
745 : * subnet down to avoid clobbering bits that are only supposed to be
746 : * used for netmask_size.
747 : *
748 : * Discarding the least significant subnet bits like this is correct
749 : * because abbreviated comparisons that are resolved at the subnet
750 : * level must have had equal netmask_size/ip_bits() values in order to
751 : * get that far.
752 : */
753 585 : if (subnet_size > ABBREV_BITS_INET4_SUBNET)
754 72 : subnet >>= subnet_size - ABBREV_BITS_INET4_SUBNET;
755 :
756 : /*
757 : * Assemble the final abbreviated key without clobbering the ipfamily
758 : * bit that must remain a zero.
759 : */
760 585 : res |= network | netmask_size | subnet;
761 : }
762 : else
763 : #endif
764 : {
765 : /*
766 : * 4 byte datums, or IPv6 with 8 byte datums: Use as many of the
767 : * netmasked bits as will fit in final abbreviated key. Avoid
768 : * clobbering the ipfamily bit that was set earlier.
769 : */
770 189 : res |= network >> 1;
771 : }
772 :
773 774 : uss->input_count += 1;
774 :
775 : /* Hash abbreviated key */
776 774 : if (uss->estimating)
777 : {
778 : uint32 tmp;
779 :
780 : #if SIZEOF_DATUM == 8
781 774 : tmp = (uint32) res ^ (uint32) ((uint64) res >> 32);
782 : #else /* SIZEOF_DATUM != 8 */
783 : tmp = (uint32) res;
784 : #endif
785 :
786 774 : addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
787 : }
788 :
789 774 : return res;
790 : }
791 :
792 : /*
793 : * Boolean ordering tests.
794 : */
795 : Datum
8284 tgl 796 151433 : network_lt(PG_FUNCTION_ARGS)
797 : {
4136 heikki.linnakangas 798 151433 : inet *a1 = PG_GETARG_INET_PP(0);
799 151433 : inet *a2 = PG_GETARG_INET_PP(1);
800 :
8284 tgl 801 151433 : PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
802 : }
803 :
804 : Datum
805 9430 : network_le(PG_FUNCTION_ARGS)
806 : {
4136 heikki.linnakangas 807 9430 : inet *a1 = PG_GETARG_INET_PP(0);
808 9430 : inet *a2 = PG_GETARG_INET_PP(1);
809 :
8284 tgl 810 9430 : PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
811 : }
812 :
813 : Datum
814 50970 : network_eq(PG_FUNCTION_ARGS)
815 : {
4136 heikki.linnakangas 816 50970 : inet *a1 = PG_GETARG_INET_PP(0);
817 50970 : inet *a2 = PG_GETARG_INET_PP(1);
818 :
8284 tgl 819 50970 : PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
820 : }
821 :
822 : Datum
823 9586 : network_ge(PG_FUNCTION_ARGS)
824 : {
4136 heikki.linnakangas 825 9586 : inet *a1 = PG_GETARG_INET_PP(0);
826 9586 : inet *a2 = PG_GETARG_INET_PP(1);
827 :
8284 tgl 828 9586 : PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
829 : }
830 :
831 : Datum
832 11036 : network_gt(PG_FUNCTION_ARGS)
833 : {
4136 heikki.linnakangas 834 11036 : inet *a1 = PG_GETARG_INET_PP(0);
835 11036 : inet *a2 = PG_GETARG_INET_PP(1);
836 :
8284 tgl 837 11036 : PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
838 : }
839 :
840 : Datum
841 51 : network_ne(PG_FUNCTION_ARGS)
842 : {
4136 heikki.linnakangas 843 51 : inet *a1 = PG_GETARG_INET_PP(0);
844 51 : inet *a2 = PG_GETARG_INET_PP(1);
845 :
8284 tgl 846 51 : PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
847 : }
848 :
849 : /*
850 : * MIN/MAX support functions.
851 : */
852 : Datum
3146 853 96 : network_smaller(PG_FUNCTION_ARGS)
854 : {
855 96 : inet *a1 = PG_GETARG_INET_PP(0);
856 96 : inet *a2 = PG_GETARG_INET_PP(1);
857 :
858 96 : if (network_cmp_internal(a1, a2) < 0)
859 57 : PG_RETURN_INET_P(a1);
860 : else
861 39 : PG_RETURN_INET_P(a2);
862 : }
863 :
864 : Datum
865 96 : network_larger(PG_FUNCTION_ARGS)
866 : {
867 96 : inet *a1 = PG_GETARG_INET_PP(0);
868 96 : inet *a2 = PG_GETARG_INET_PP(1);
869 :
870 96 : if (network_cmp_internal(a1, a2) > 0)
871 78 : PG_RETURN_INET_P(a1);
872 : else
873 18 : PG_RETURN_INET_P(a2);
874 : }
875 :
876 : /*
877 : * Support function for hash indexes on inet/cidr.
878 : */
879 : Datum
6874 880 3036 : hashinet(PG_FUNCTION_ARGS)
881 : {
4136 heikki.linnakangas 882 3036 : inet *addr = PG_GETARG_INET_PP(0);
6874 tgl 883 3036 : int addrsize = ip_addrsize(addr);
884 :
885 : /* XXX this assumes there are no pad bytes in the data structure */
5847 886 3036 : return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
887 : }
888 :
889 : Datum
2047 rhaas 890 30 : hashinetextended(PG_FUNCTION_ARGS)
891 : {
892 30 : inet *addr = PG_GETARG_INET_PP(0);
893 30 : int addrsize = ip_addrsize(addr);
894 :
895 30 : return hash_any_extended((unsigned char *) VARDATA_ANY(addr), addrsize + 2,
896 30 : PG_GETARG_INT64(1));
897 : }
898 :
899 : /*
900 : * Boolean network-inclusion tests.
901 : */
902 : Datum
8284 tgl 903 3066 : network_sub(PG_FUNCTION_ARGS)
904 : {
4136 heikki.linnakangas 905 3066 : inet *a1 = PG_GETARG_INET_PP(0);
906 3066 : inet *a2 = PG_GETARG_INET_PP(1);
907 :
7229 bruce 908 3066 : if (ip_family(a1) == ip_family(a2))
909 : {
3382 tgl 910 2466 : PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2) &&
911 : bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
912 : }
913 :
7229 bruce 914 600 : PG_RETURN_BOOL(false);
915 : }
916 :
917 : Datum
8284 tgl 918 4953 : network_subeq(PG_FUNCTION_ARGS)
919 : {
4136 heikki.linnakangas 920 4953 : inet *a1 = PG_GETARG_INET_PP(0);
921 4953 : inet *a2 = PG_GETARG_INET_PP(1);
922 :
7229 bruce 923 4953 : if (ip_family(a1) == ip_family(a2))
924 : {
3382 tgl 925 3069 : PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2) &&
926 : bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
927 : }
928 :
7229 bruce 929 1884 : PG_RETURN_BOOL(false);
930 : }
931 :
932 : Datum
8284 tgl 933 3090 : network_sup(PG_FUNCTION_ARGS)
934 : {
4136 heikki.linnakangas 935 3090 : inet *a1 = PG_GETARG_INET_PP(0);
936 3090 : inet *a2 = PG_GETARG_INET_PP(1);
937 :
7229 bruce 938 3090 : if (ip_family(a1) == ip_family(a2))
939 : {
3382 tgl 940 2490 : PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2) &&
941 : bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
942 : }
943 :
7229 bruce 944 600 : PG_RETURN_BOOL(false);
945 : }
946 :
947 : Datum
8284 tgl 948 9294 : network_supeq(PG_FUNCTION_ARGS)
949 : {
4136 heikki.linnakangas 950 9294 : inet *a1 = PG_GETARG_INET_PP(0);
951 9294 : inet *a2 = PG_GETARG_INET_PP(1);
952 :
7229 bruce 953 9294 : if (ip_family(a1) == ip_family(a2))
954 : {
3382 tgl 955 5124 : PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2) &&
956 : bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
957 : }
958 :
7229 bruce 959 4170 : PG_RETURN_BOOL(false);
960 : }
961 :
962 : Datum
3288 tgl 963 10515 : network_overlap(PG_FUNCTION_ARGS)
964 : {
965 10515 : inet *a1 = PG_GETARG_INET_PP(0);
966 10515 : inet *a2 = PG_GETARG_INET_PP(1);
967 :
968 10515 : if (ip_family(a1) == ip_family(a2))
969 : {
970 6399 : PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
971 : Min(ip_bits(a1), ip_bits(a2))) == 0);
972 : }
973 :
974 4116 : PG_RETURN_BOOL(false);
975 : }
976 :
977 : /*
978 : * Planner support function for network subset/superset operators
979 : */
980 : Datum
1518 981 744 : network_subset_support(PG_FUNCTION_ARGS)
982 : {
983 744 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
984 744 : Node *ret = NULL;
985 :
986 744 : if (IsA(rawreq, SupportRequestIndexCondition))
987 : {
988 : /* Try to convert operator/function call to index conditions */
989 24 : SupportRequestIndexCondition *req = (SupportRequestIndexCondition *) rawreq;
990 :
991 24 : if (is_opclause(req->node))
992 : {
993 24 : OpExpr *clause = (OpExpr *) req->node;
994 :
995 24 : Assert(list_length(clause->args) == 2);
996 : ret = (Node *)
997 24 : match_network_function((Node *) linitial(clause->args),
998 24 : (Node *) lsecond(clause->args),
999 : req->indexarg,
1000 : req->funcid,
1001 : req->opfamily);
1002 : }
1518 tgl 1003 UBC 0 : else if (is_funcclause(req->node)) /* be paranoid */
1004 : {
1005 0 : FuncExpr *clause = (FuncExpr *) req->node;
1006 :
1007 0 : Assert(list_length(clause->args) == 2);
1008 : ret = (Node *)
1009 0 : match_network_function((Node *) linitial(clause->args),
1010 0 : (Node *) lsecond(clause->args),
1011 : req->indexarg,
1012 : req->funcid,
1013 : req->opfamily);
1014 : }
1015 : }
1016 :
1518 tgl 1017 CBC 744 : PG_RETURN_POINTER(ret);
1018 : }
1019 :
1020 : /*
1021 : * match_network_function
1022 : * Try to generate an indexqual for a network subset/superset function.
1023 : *
1024 : * This layer is just concerned with identifying the function and swapping
1025 : * the arguments if necessary.
1026 : */
1027 : static List *
1028 24 : match_network_function(Node *leftop,
1029 : Node *rightop,
1030 : int indexarg,
1031 : Oid funcid,
1032 : Oid opfamily)
1033 : {
1034 24 : switch (funcid)
1035 : {
1036 6 : case F_NETWORK_SUB:
1037 : /* indexkey must be on the left */
1038 6 : if (indexarg != 0)
1518 tgl 1039 UBC 0 : return NIL;
1518 tgl 1040 CBC 6 : return match_network_subset(leftop, rightop, false, opfamily);
1041 :
1042 6 : case F_NETWORK_SUBEQ:
1043 : /* indexkey must be on the left */
1044 6 : if (indexarg != 0)
1518 tgl 1045 UBC 0 : return NIL;
1518 tgl 1046 CBC 6 : return match_network_subset(leftop, rightop, true, opfamily);
1047 :
1048 6 : case F_NETWORK_SUP:
1049 : /* indexkey must be on the right */
1050 6 : if (indexarg != 1)
1518 tgl 1051 UBC 0 : return NIL;
1518 tgl 1052 CBC 6 : return match_network_subset(rightop, leftop, false, opfamily);
1053 :
1054 6 : case F_NETWORK_SUPEQ:
1055 : /* indexkey must be on the right */
1056 6 : if (indexarg != 1)
1518 tgl 1057 UBC 0 : return NIL;
1518 tgl 1058 CBC 6 : return match_network_subset(rightop, leftop, true, opfamily);
1059 :
1518 tgl 1060 UBC 0 : default:
1061 :
1062 : /*
1063 : * We'd only get here if somebody attached this support function
1064 : * to an unexpected function. Maybe we should complain, but for
1065 : * now, do nothing.
1066 : */
1067 0 : return NIL;
1068 : }
1069 : }
1070 :
1071 : /*
1072 : * match_network_subset
1073 : * Try to generate an indexqual for a network subset function.
1074 : */
1075 : static List *
1518 tgl 1076 CBC 24 : match_network_subset(Node *leftop,
1077 : Node *rightop,
1078 : bool is_eq,
1079 : Oid opfamily)
1080 : {
1081 : List *result;
1082 : Datum rightopval;
1083 24 : Oid datatype = INETOID;
1084 : Oid opr1oid;
1085 : Oid opr2oid;
1086 : Datum opr1right;
1087 : Datum opr2right;
1088 : Expr *expr;
1089 :
1090 : /*
1091 : * Can't do anything with a non-constant or NULL comparison value.
1092 : *
1093 : * Note that since we restrict ourselves to cases with a hard constant on
1094 : * the RHS, it's a-fortiori a pseudoconstant, and we don't need to worry
1095 : * about verifying that.
1096 : */
1097 24 : if (!IsA(rightop, Const) ||
1098 24 : ((Const *) rightop)->constisnull)
1518 tgl 1099 UBC 0 : return NIL;
1518 tgl 1100 CBC 24 : rightopval = ((Const *) rightop)->constvalue;
1101 :
1102 : /*
1103 : * Must check that index's opfamily supports the operators we will want to
1104 : * apply.
1105 : *
1106 : * We insist on the opfamily being the specific one we expect, else we'd
1107 : * do the wrong thing if someone were to make a reverse-sort opfamily with
1108 : * the same operators.
1109 : */
1110 24 : if (opfamily != NETWORK_BTREE_FAM_OID)
1518 tgl 1111 UBC 0 : return NIL;
1112 :
1113 : /*
1114 : * create clause "key >= network_scan_first( rightopval )", or ">" if the
1115 : * operator disallows equality.
1116 : *
1117 : * Note: seeing that this function supports only fixed values for opfamily
1118 : * and datatype, we could just hard-wire the operator OIDs instead of
1119 : * looking them up. But for now it seems better to be general.
1120 : */
1518 tgl 1121 CBC 24 : if (is_eq)
1122 : {
1123 12 : opr1oid = get_opfamily_member(opfamily, datatype, datatype,
1124 : BTGreaterEqualStrategyNumber);
1125 12 : if (opr1oid == InvalidOid)
1518 tgl 1126 UBC 0 : elog(ERROR, "no >= operator for opfamily %u", opfamily);
1127 : }
1128 : else
1129 : {
1518 tgl 1130 CBC 12 : opr1oid = get_opfamily_member(opfamily, datatype, datatype,
1131 : BTGreaterStrategyNumber);
1132 12 : if (opr1oid == InvalidOid)
1518 tgl 1133 UBC 0 : elog(ERROR, "no > operator for opfamily %u", opfamily);
1134 : }
1135 :
1518 tgl 1136 CBC 24 : opr1right = network_scan_first(rightopval);
1137 :
1138 24 : expr = make_opclause(opr1oid, BOOLOID, false,
1139 : (Expr *) leftop,
1140 24 : (Expr *) makeConst(datatype, -1,
1141 : InvalidOid, /* not collatable */
1142 : -1, opr1right,
1143 : false, false),
1144 : InvalidOid, InvalidOid);
1145 24 : result = list_make1(expr);
1146 :
1147 : /* create clause "key <= network_scan_last( rightopval )" */
1148 :
1149 24 : opr2oid = get_opfamily_member(opfamily, datatype, datatype,
1150 : BTLessEqualStrategyNumber);
1151 24 : if (opr2oid == InvalidOid)
1518 tgl 1152 UBC 0 : elog(ERROR, "no <= operator for opfamily %u", opfamily);
1153 :
1518 tgl 1154 CBC 24 : opr2right = network_scan_last(rightopval);
1155 :
1156 24 : expr = make_opclause(opr2oid, BOOLOID, false,
1157 : (Expr *) leftop,
1158 24 : (Expr *) makeConst(datatype, -1,
1159 : InvalidOid, /* not collatable */
1160 : -1, opr2right,
1161 : false, false),
1162 : InvalidOid, InvalidOid);
1163 24 : result = lappend(result, expr);
1164 :
1165 24 : return result;
1166 : }
1167 :
1168 :
1169 : /*
1170 : * Extract data from a network datatype.
1171 : */
1172 : Datum
8312 1173 51 : network_host(PG_FUNCTION_ARGS)
1174 : {
4136 heikki.linnakangas 1175 51 : inet *ip = PG_GETARG_INET_PP(0);
1176 : char *ptr;
1177 : char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
1178 :
1179 : /* force display of max bits, regardless of masklen... */
1330 tgl 1180 51 : if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
1181 : tmp, sizeof(tmp)) == NULL)
7196 tgl 1182 UBC 0 : ereport(ERROR,
1183 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1184 : errmsg("could not format inet value: %m")));
1185 :
1186 : /* Suppress /n if present (shouldn't happen now) */
8935 bruce 1187 CBC 51 : if ((ptr = strchr(tmp, '/')) != NULL)
8312 tgl 1188 UBC 0 : *ptr = '\0';
1189 :
5493 tgl 1190 CBC 51 : PG_RETURN_TEXT_P(cstring_to_text(tmp));
1191 : }
1192 :
1193 : /*
1194 : * network_show implements the inet and cidr casts to text. This is not
1195 : * quite the same behavior as network_out, hence we can't drop it in favor
1196 : * of CoerceViaIO.
1197 : */
1198 : Datum
8185 1199 106 : network_show(PG_FUNCTION_ARGS)
1200 : {
4136 heikki.linnakangas 1201 106 : inet *ip = PG_GETARG_INET_PP(0);
1202 : int len;
1203 : char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
1204 :
1330 tgl 1205 106 : if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
1206 : tmp, sizeof(tmp)) == NULL)
7196 tgl 1207 UBC 0 : ereport(ERROR,
1208 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1209 : errmsg("could not format inet value: %m")));
1210 :
1211 : /* Add /n if not present (which it won't be) */
7229 bruce 1212 CBC 106 : if (strchr(tmp, '/') == NULL)
1213 : {
1214 106 : len = strlen(tmp);
1215 106 : snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
1216 : }
1217 :
5493 tgl 1218 106 : PG_RETURN_TEXT_P(cstring_to_text(tmp));
1219 : }
1220 :
1221 : Datum
6282 tgl 1222 UBC 0 : inet_abbrev(PG_FUNCTION_ARGS)
1223 : {
4136 heikki.linnakangas 1224 0 : inet *ip = PG_GETARG_INET_PP(0);
1225 : char *dst;
1226 : char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
1227 :
1330 tgl 1228 0 : dst = pg_inet_net_ntop(ip_family(ip), ip_addr(ip),
1229 0 : ip_bits(ip), tmp, sizeof(tmp));
1230 :
7229 bruce 1231 0 : if (dst == NULL)
7196 tgl 1232 0 : ereport(ERROR,
1233 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1234 : errmsg("could not format inet value: %m")));
1235 :
5493 1236 0 : PG_RETURN_TEXT_P(cstring_to_text(tmp));
1237 : }
1238 :
1239 : Datum
6282 tgl 1240 CBC 51 : cidr_abbrev(PG_FUNCTION_ARGS)
1241 : {
4136 heikki.linnakangas 1242 51 : inet *ip = PG_GETARG_INET_PP(0);
1243 : char *dst;
1244 : char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
1245 :
1330 tgl 1246 51 : dst = pg_inet_cidr_ntop(ip_family(ip), ip_addr(ip),
1247 51 : ip_bits(ip), tmp, sizeof(tmp));
1248 :
6282 1249 51 : if (dst == NULL)
6282 tgl 1250 UBC 0 : ereport(ERROR,
1251 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
1252 : errmsg("could not format cidr value: %m")));
1253 :
5493 tgl 1254 CBC 51 : PG_RETURN_TEXT_P(cstring_to_text(tmp));
1255 : }
1256 :
1257 : Datum
8284 1258 177 : network_masklen(PG_FUNCTION_ARGS)
1259 : {
4136 heikki.linnakangas 1260 177 : inet *ip = PG_GETARG_INET_PP(0);
1261 :
8284 tgl 1262 177 : PG_RETURN_INT32(ip_bits(ip));
1263 : }
1264 :
1265 : Datum
7229 bruce 1266 51 : network_family(PG_FUNCTION_ARGS)
1267 : {
4136 heikki.linnakangas 1268 51 : inet *ip = PG_GETARG_INET_PP(0);
1269 :
7188 bruce 1270 51 : switch (ip_family(ip))
1271 : {
1272 42 : case PGSQL_AF_INET:
1273 42 : PG_RETURN_INT32(4);
1274 : break;
1275 9 : case PGSQL_AF_INET6:
1276 9 : PG_RETURN_INT32(6);
1277 : break;
7188 bruce 1278 UBC 0 : default:
1279 0 : PG_RETURN_INT32(0);
1280 : break;
1281 : }
1282 : }
1283 :
1284 : Datum
8312 tgl 1285 CBC 126 : network_broadcast(PG_FUNCTION_ARGS)
1286 : {
4136 heikki.linnakangas 1287 126 : inet *ip = PG_GETARG_INET_PP(0);
1288 : inet *dst;
1289 : int byte;
1290 : int bits;
1291 : int maxbytes;
1292 : unsigned char mask;
1293 : unsigned char *a,
1294 : *b;
1295 :
1296 : /* make sure any unused bits are zeroed */
5847 tgl 1297 126 : dst = (inet *) palloc0(sizeof(inet));
1298 :
2420 1299 126 : maxbytes = ip_addrsize(ip);
7229 bruce 1300 126 : bits = ip_bits(ip);
1301 126 : a = ip_addr(ip);
1302 126 : b = ip_addr(dst);
1303 :
4382 1304 846 : for (byte = 0; byte < maxbytes; byte++)
1305 : {
7188 1306 720 : if (bits >= 8)
1307 : {
7229 1308 495 : mask = 0x00;
1309 495 : bits -= 8;
1310 : }
7188 1311 225 : else if (bits == 0)
7229 1312 213 : mask = 0xff;
1313 : else
1314 : {
1315 12 : mask = 0xff >> bits;
1316 12 : bits = 0;
1317 : }
1318 :
4382 1319 720 : b[byte] = a[byte] | mask;
1320 : }
1321 :
8185 tgl 1322 126 : ip_family(dst) = ip_family(ip);
1323 126 : ip_bits(dst) = ip_bits(ip);
5847 1324 126 : SET_INET_VARSIZE(dst);
1325 :
8185 1326 126 : PG_RETURN_INET_P(dst);
1327 : }
1328 :
1329 : Datum
8312 1330 126 : network_network(PG_FUNCTION_ARGS)
1331 : {
4136 heikki.linnakangas 1332 126 : inet *ip = PG_GETARG_INET_PP(0);
1333 : inet *dst;
1334 : int byte;
1335 : int bits;
1336 : unsigned char mask;
1337 : unsigned char *a,
1338 : *b;
1339 :
1340 : /* make sure any unused bits are zeroed */
5847 tgl 1341 126 : dst = (inet *) palloc0(sizeof(inet));
1342 :
7229 bruce 1343 126 : bits = ip_bits(ip);
1344 126 : a = ip_addr(ip);
1345 126 : b = ip_addr(dst);
1346 :
1347 126 : byte = 0;
1348 :
7188 1349 633 : while (bits)
1350 : {
1351 507 : if (bits >= 8)
1352 : {
7229 1353 495 : mask = 0xff;
1354 495 : bits -= 8;
1355 : }
1356 : else
1357 : {
1358 12 : mask = 0xff << (8 - bits);
1359 12 : bits = 0;
1360 : }
1361 :
4382 1362 507 : b[byte] = a[byte] & mask;
1363 507 : byte++;
1364 : }
1365 :
8185 tgl 1366 126 : ip_family(dst) = ip_family(ip);
1367 126 : ip_bits(dst) = ip_bits(ip);
5847 1368 126 : SET_INET_VARSIZE(dst);
1369 :
8185 1370 126 : PG_RETURN_INET_P(dst);
1371 : }
1372 :
1373 : Datum
8312 tgl 1374 UBC 0 : network_netmask(PG_FUNCTION_ARGS)
1375 : {
4136 heikki.linnakangas 1376 0 : inet *ip = PG_GETARG_INET_PP(0);
1377 : inet *dst;
1378 : int byte;
1379 : int bits;
1380 : unsigned char mask;
1381 : unsigned char *b;
1382 :
1383 : /* make sure any unused bits are zeroed */
5847 tgl 1384 0 : dst = (inet *) palloc0(sizeof(inet));
1385 :
7229 bruce 1386 0 : bits = ip_bits(ip);
1387 0 : b = ip_addr(dst);
1388 :
1389 0 : byte = 0;
1390 :
7188 1391 0 : while (bits)
1392 : {
1393 0 : if (bits >= 8)
1394 : {
7229 1395 0 : mask = 0xff;
1396 0 : bits -= 8;
1397 : }
1398 : else
1399 : {
1400 0 : mask = 0xff << (8 - bits);
1401 0 : bits = 0;
1402 : }
1403 :
1404 0 : b[byte] = mask;
4382 1405 0 : byte++;
1406 : }
1407 :
8185 tgl 1408 0 : ip_family(dst) = ip_family(ip);
7069 1409 0 : ip_bits(dst) = ip_maxbits(ip);
5847 1410 0 : SET_INET_VARSIZE(dst);
1411 :
8185 1412 0 : PG_RETURN_INET_P(dst);
1413 : }
1414 :
1415 : Datum
7324 bruce 1416 0 : network_hostmask(PG_FUNCTION_ARGS)
1417 : {
4136 heikki.linnakangas 1418 0 : inet *ip = PG_GETARG_INET_PP(0);
1419 : inet *dst;
1420 : int byte;
1421 : int bits;
1422 : int maxbytes;
1423 : unsigned char mask;
1424 : unsigned char *b;
1425 :
1426 : /* make sure any unused bits are zeroed */
5847 tgl 1427 0 : dst = (inet *) palloc0(sizeof(inet));
1428 :
2420 1429 0 : maxbytes = ip_addrsize(ip);
7229 bruce 1430 0 : bits = ip_maxbits(ip) - ip_bits(ip);
1431 0 : b = ip_addr(dst);
1432 :
1433 0 : byte = maxbytes - 1;
1434 :
7188 1435 0 : while (bits)
1436 : {
1437 0 : if (bits >= 8)
1438 : {
7229 1439 0 : mask = 0xff;
1440 0 : bits -= 8;
1441 : }
1442 : else
1443 : {
1444 0 : mask = 0xff >> (8 - bits);
1445 0 : bits = 0;
1446 : }
1447 :
1448 0 : b[byte] = mask;
4382 1449 0 : byte--;
1450 : }
1451 :
7324 1452 0 : ip_family(dst) = ip_family(ip);
7069 tgl 1453 0 : ip_bits(dst) = ip_maxbits(ip);
5847 1454 0 : SET_INET_VARSIZE(dst);
1455 :
7324 bruce 1456 0 : PG_RETURN_INET_P(dst);
1457 : }
1458 :
1459 : /*
1460 : * Returns true if the addresses are from the same family, or false. Used to
1461 : * check that we can create a network which contains both of the networks.
1462 : */
1463 : Datum
2896 alvherre 1464 CBC 120 : inet_same_family(PG_FUNCTION_ARGS)
1465 : {
1466 120 : inet *a1 = PG_GETARG_INET_PP(0);
1467 120 : inet *a2 = PG_GETARG_INET_PP(1);
1468 :
1469 120 : PG_RETURN_BOOL(ip_family(a1) == ip_family(a2));
1470 : }
1471 :
1472 : /*
1473 : * Returns the smallest CIDR which contains both of the inputs.
1474 : */
1475 : Datum
1476 117 : inet_merge(PG_FUNCTION_ARGS)
1477 : {
1478 117 : inet *a1 = PG_GETARG_INET_PP(0),
2420 tgl 1479 117 : *a2 = PG_GETARG_INET_PP(1);
1480 : int commonbits;
1481 :
2896 alvherre 1482 117 : if (ip_family(a1) != ip_family(a2))
1483 3 : ereport(ERROR,
1484 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1485 : errmsg("cannot merge addresses from different families")));
1486 :
1487 114 : commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
1488 114 : Min(ip_bits(a1), ip_bits(a2)));
1489 :
2420 tgl 1490 114 : PG_RETURN_INET_P(cidr_set_masklen_internal(a1, commonbits));
1491 : }
1492 :
1493 : /*
1494 : * Convert a value of a network datatype to an approximate scalar value.
1495 : * This is used for estimating selectivities of inequality operators
1496 : * involving network types.
1497 : *
1498 : * On failure (e.g., unsupported typid), set *failure to true;
1499 : * otherwise, that variable is not changed.
1500 : */
1501 : double
1863 1502 5440 : convert_network_to_scalar(Datum value, Oid typid, bool *failure)
1503 : {
7974 1504 5440 : switch (typid)
1505 : {
1506 5440 : case INETOID:
1507 : case CIDROID:
1508 : {
4170 heikki.linnakangas 1509 5440 : inet *ip = DatumGetInetPP(value);
1510 : int len;
1511 : double res;
1512 : int i;
1513 :
1514 : /*
1515 : * Note that we don't use the full address for IPv6.
1516 : */
7229 bruce 1517 5440 : if (ip_family(ip) == PGSQL_AF_INET)
1518 5440 : len = 4;
1519 : else
7229 bruce 1520 UBC 0 : len = 5;
1521 :
7229 bruce 1522 CBC 5440 : res = ip_family(ip);
7188 1523 27200 : for (i = 0; i < len; i++)
1524 : {
7229 1525 21760 : res *= 256;
1526 21760 : res += ip_addr(ip)[i];
1527 : }
1528 5440 : return res;
1529 : }
7974 tgl 1530 UBC 0 : case MACADDROID:
1531 : {
7836 bruce 1532 0 : macaddr *mac = DatumGetMacaddrP(value);
1533 : double res;
1534 :
1535 0 : res = (mac->a << 16) | (mac->b << 8) | (mac->c);
1536 0 : res *= 256 * 256 * 256;
1537 0 : res += (mac->d << 16) | (mac->e << 8) | (mac->f);
1538 0 : return res;
1539 : }
2216 sfrost 1540 0 : case MACADDR8OID:
1541 : {
1542 0 : macaddr8 *mac = DatumGetMacaddr8P(value);
1543 : double res;
1544 :
1545 0 : res = (mac->a << 24) | (mac->b << 16) | (mac->c << 8) | (mac->d);
1546 0 : res *= ((double) 256) * 256 * 256 * 256;
1547 0 : res += (mac->e << 24) | (mac->f << 16) | (mac->g << 8) | (mac->h);
1548 0 : return res;
1549 : }
1550 : }
1551 :
1863 tgl 1552 0 : *failure = true;
7974 1553 0 : return 0;
1554 : }
1555 :
1556 : /*
1557 : * int
1558 : * bitncmp(l, r, n)
1559 : * compare bit masks l and r, for n bits.
1560 : * return:
1561 : * <0, >0, or 0 in the libc tradition.
1562 : * note:
1563 : * network byte order assumed. this means 192.5.5.240/28 has
1564 : * 0x11110000 in its fourth octet.
1565 : * author:
1566 : * Paul Vixie (ISC), June 1996
1567 : */
1568 : int
3288 tgl 1569 CBC 193223 : bitncmp(const unsigned char *l, const unsigned char *r, int n)
1570 : {
1571 : unsigned int lb,
1572 : rb;
1573 : int x,
1574 : b;
1575 :
7229 bruce 1576 193223 : b = n / 8;
1577 193223 : x = memcmp(l, r, b);
4931 heikki.linnakangas 1578 193223 : if (x || (n % 8) == 0)
6297 neilc 1579 193102 : return x;
1580 :
3288 tgl 1581 121 : lb = l[b];
1582 121 : rb = r[b];
7188 bruce 1583 215 : for (b = n % 8; b > 0; b--)
1584 : {
6314 1585 148 : if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
1586 : {
1587 54 : if (IS_HIGHBIT_SET(lb))
1588 30 : return 1;
1589 24 : return -1;
1590 : }
7229 1591 94 : lb <<= 1;
1592 94 : rb <<= 1;
1593 : }
6314 1594 67 : return 0;
1595 : }
1596 :
1597 : /*
1598 : * bitncommon: compare bit masks l and r, for up to n bits.
1599 : *
1600 : * Returns the number of leading bits that match (0 to n).
1601 : */
1602 : int
3288 tgl 1603 1660 : bitncommon(const unsigned char *l, const unsigned char *r, int n)
1604 : {
1605 : int byte,
1606 : nbits;
1607 :
1608 : /* number of bits to examine in last byte */
1609 1660 : nbits = n % 8;
1610 :
1611 : /* check whole bytes */
1612 2165 : for (byte = 0; byte < n / 8; byte++)
1613 : {
1614 533 : if (l[byte] != r[byte])
1615 : {
1616 : /* at least one bit in the last byte is not common */
1617 28 : nbits = 7;
1618 28 : break;
1619 : }
1620 : }
1621 :
1622 : /* check bits in last partial byte */
1623 1660 : if (nbits != 0)
1624 : {
1625 : /* calculate diff of first non-matching bytes */
1626 1282 : unsigned int diff = l[byte] ^ r[byte];
1627 :
1628 : /* compare the bits from the most to the least */
1629 1512 : while ((diff >> (8 - nbits)) != 0)
1630 230 : nbits--;
1631 : }
1632 :
1633 1660 : return (8 * byte) + nbits;
1634 : }
1635 :
1636 :
1637 : /*
1638 : * Verify a CIDR address is OK (doesn't have bits set past the masklen)
1639 : */
1640 : static bool
7229 bruce 1641 690 : addressOK(unsigned char *a, int bits, int family)
1642 : {
1643 : int byte;
1644 : int nbits;
1645 : int maxbits;
1646 : int maxbytes;
1647 : unsigned char mask;
1648 :
7188 1649 690 : if (family == PGSQL_AF_INET)
1650 : {
7229 1651 549 : maxbits = 32;
1652 549 : maxbytes = 4;
1653 : }
1654 : else
1655 : {
1656 141 : maxbits = 128;
1657 141 : maxbytes = 16;
1658 : }
7191 tgl 1659 690 : Assert(bits <= maxbits);
1660 :
7229 bruce 1661 690 : if (bits == maxbits)
7191 tgl 1662 301 : return true;
1663 :
6757 bruce 1664 389 : byte = bits / 8;
1665 :
7229 1666 389 : nbits = bits % 8;
1667 389 : mask = 0xff;
1668 389 : if (bits != 0)
1669 365 : mask >>= nbits;
1670 :
4382 1671 1501 : while (byte < maxbytes)
1672 : {
1673 1127 : if ((a[byte] & mask) != 0)
7191 tgl 1674 15 : return false;
7229 bruce 1675 1112 : mask = 0xff;
4382 1676 1112 : byte++;
1677 : }
1678 :
7191 tgl 1679 374 : return true;
1680 : }
1681 :
1682 :
1683 : /*
1684 : * These functions are used by planner to generate indexscan limits
1685 : * for clauses a << b and a <<= b
1686 : */
1687 :
1688 : /* return the minimal value for an IP on a given network */
1689 : Datum
7966 1690 24 : network_scan_first(Datum in)
1691 : {
1692 24 : return DirectFunctionCall1(network_network, in);
1693 : }
1694 :
1695 : /*
1696 : * return "last" IP on a given network. It's the broadcast address,
1697 : * however, masklen has to be set to its max bits, since
1698 : * 192.168.0.255/24 is considered less than 192.168.0.255/32
1699 : *
1700 : * inet_set_masklen() hacked to max out the masklength to 128 for IPv6
1701 : * and 32 for IPv4 when given '-1' as argument.
1702 : */
1703 : Datum
1704 24 : network_scan_last(Datum in)
1705 : {
1706 24 : return DirectFunctionCall2(inet_set_masklen,
1707 : DirectFunctionCall1(network_broadcast, in),
1708 : Int32GetDatum(-1));
1709 : }
1710 :
1711 :
1712 : /*
1713 : * IP address that the client is connecting from (NULL if Unix socket)
1714 : */
1715 : Datum
6874 tgl 1716 UBC 0 : inet_client_addr(PG_FUNCTION_ARGS)
1717 : {
6797 bruce 1718 0 : Port *port = MyProcPort;
1719 : char remote_host[NI_MAXHOST];
1720 : int ret;
1721 :
6874 tgl 1722 0 : if (port == NULL)
1723 0 : PG_RETURN_NULL();
1724 :
6797 bruce 1725 0 : switch (port->raddr.addr.ss_family)
1726 : {
1727 0 : case AF_INET:
6797 bruce 1728 EUB : case AF_INET6:
6797 bruce 1729 UBC 0 : break;
6797 bruce 1730 UIC 0 : default:
1731 0 : PG_RETURN_NULL();
6874 tgl 1732 EUB : }
1733 :
6874 tgl 1734 UBC 0 : remote_host[0] = '\0';
1735 :
6383 tgl 1736 UIC 0 : ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
1737 : remote_host, sizeof(remote_host),
6383 tgl 1738 EUB : NULL, 0,
1739 : NI_NUMERICHOST | NI_NUMERICSERV);
4261 peter_e 1740 UIC 0 : if (ret != 0)
6874 tgl 1741 UBC 0 : PG_RETURN_NULL();
1742 :
5806 1743 0 : clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
1744 :
116 tgl 1745 UNC 0 : PG_RETURN_INET_P(network_in(remote_host, false, NULL));
1746 : }
1747 :
1748 :
1749 : /*
1750 : * port that the client is connecting from (NULL if Unix socket)
6874 tgl 1751 EUB : */
1752 : Datum
6874 tgl 1753 UBC 0 : inet_client_port(PG_FUNCTION_ARGS)
1754 : {
6797 bruce 1755 UIC 0 : Port *port = MyProcPort;
1756 : char remote_port[NI_MAXSERV];
6797 bruce 1757 EUB : int ret;
6874 tgl 1758 :
6874 tgl 1759 UIC 0 : if (port == NULL)
6874 tgl 1760 UBC 0 : PG_RETURN_NULL();
1761 :
6797 bruce 1762 0 : switch (port->raddr.addr.ss_family)
1763 : {
1764 0 : case AF_INET:
6797 bruce 1765 EUB : case AF_INET6:
6797 bruce 1766 UIC 0 : break;
6797 bruce 1767 UBC 0 : default:
6797 bruce 1768 UIC 0 : PG_RETURN_NULL();
6874 tgl 1769 EUB : }
1770 :
6874 tgl 1771 UIC 0 : remote_port[0] = '\0';
1772 :
6383 tgl 1773 UBC 0 : ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
6383 tgl 1774 EUB : NULL, 0,
1775 : remote_port, sizeof(remote_port),
1776 : NI_NUMERICHOST | NI_NUMERICSERV);
4261 peter_e 1777 UIC 0 : if (ret != 0)
6874 tgl 1778 0 : PG_RETURN_NULL();
1779 :
1780 0 : PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
1781 : }
1782 :
1783 :
6874 tgl 1784 EUB : /*
1785 : * IP address that the server accepted the connection on (NULL if Unix socket)
1786 : */
1787 : Datum
6874 tgl 1788 UIC 0 : inet_server_addr(PG_FUNCTION_ARGS)
1789 : {
6797 bruce 1790 UBC 0 : Port *port = MyProcPort;
6797 bruce 1791 EUB : char local_host[NI_MAXHOST];
1792 : int ret;
6874 tgl 1793 :
6874 tgl 1794 UIC 0 : if (port == NULL)
6874 tgl 1795 UBC 0 : PG_RETURN_NULL();
1796 :
6797 bruce 1797 0 : switch (port->laddr.addr.ss_family)
6797 bruce 1798 EUB : {
6797 bruce 1799 UBC 0 : case AF_INET:
1800 : case AF_INET6:
6797 bruce 1801 UIC 0 : break;
6797 bruce 1802 UBC 0 : default:
6797 bruce 1803 UIC 0 : PG_RETURN_NULL();
1804 : }
1805 :
6874 tgl 1806 UBC 0 : local_host[0] = '\0';
6874 tgl 1807 EUB :
6383 tgl 1808 UIC 0 : ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
6383 tgl 1809 EUB : local_host, sizeof(local_host),
1810 : NULL, 0,
1811 : NI_NUMERICHOST | NI_NUMERICSERV);
4261 peter_e 1812 UIC 0 : if (ret != 0)
6874 tgl 1813 0 : PG_RETURN_NULL();
1814 :
5806 1815 0 : clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
1816 :
116 tgl 1817 UNC 0 : PG_RETURN_INET_P(network_in(local_host, false, NULL));
1818 : }
6874 tgl 1819 EUB :
1820 :
1821 : /*
1822 : * port that the server accepted the connection on (NULL if Unix socket)
1823 : */
1824 : Datum
6874 tgl 1825 UBC 0 : inet_server_port(PG_FUNCTION_ARGS)
6874 tgl 1826 EUB : {
6797 bruce 1827 UIC 0 : Port *port = MyProcPort;
6797 bruce 1828 EUB : char local_port[NI_MAXSERV];
1829 : int ret;
6874 tgl 1830 :
6874 tgl 1831 UIC 0 : if (port == NULL)
6874 tgl 1832 UBC 0 : PG_RETURN_NULL();
6874 tgl 1833 EUB :
6797 bruce 1834 UBC 0 : switch (port->laddr.addr.ss_family)
1835 : {
6797 bruce 1836 UIC 0 : case AF_INET:
1837 : case AF_INET6:
1838 0 : break;
1839 0 : default:
1840 0 : PG_RETURN_NULL();
6874 tgl 1841 EUB : }
1842 :
6874 tgl 1843 UIC 0 : local_port[0] = '\0';
6874 tgl 1844 EUB :
6383 tgl 1845 UIC 0 : ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
1846 : NULL, 0,
1847 : local_port, sizeof(local_port),
1848 : NI_NUMERICHOST | NI_NUMERICSERV);
4261 peter_e 1849 LBC 0 : if (ret != 0)
6874 tgl 1850 UIC 0 : PG_RETURN_NULL();
6874 tgl 1851 ECB :
6874 tgl 1852 UIC 0 : PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
1853 : }
6266 bruce 1854 ECB :
1855 :
1856 : Datum
6266 bruce 1857 CBC 51 : inetnot(PG_FUNCTION_ARGS)
6266 bruce 1858 ECB : {
4136 heikki.linnakangas 1859 CBC 51 : inet *ip = PG_GETARG_INET_PP(0);
1860 : inet *dst;
6266 bruce 1861 ECB :
5847 tgl 1862 CBC 51 : dst = (inet *) palloc0(sizeof(inet));
1863 :
6266 bruce 1864 ECB : {
6031 bruce 1865 GIC 51 : int nb = ip_addrsize(ip);
6031 bruce 1866 CBC 51 : unsigned char *pip = ip_addr(ip);
1867 51 : unsigned char *pdst = ip_addr(dst);
1868 :
24 andres 1869 363 : while (--nb >= 0)
6266 bruce 1870 GIC 312 : pdst[nb] = ~pip[nb];
1871 : }
1872 51 : ip_bits(dst) = ip_bits(ip);
1873 :
6266 bruce 1874 CBC 51 : ip_family(dst) = ip_family(ip);
5847 tgl 1875 GIC 51 : SET_INET_VARSIZE(dst);
6266 bruce 1876 ECB :
6266 bruce 1877 CBC 51 : PG_RETURN_INET_P(dst);
1878 : }
1879 :
6266 bruce 1880 ECB :
1881 : Datum
6266 bruce 1882 CBC 51 : inetand(PG_FUNCTION_ARGS)
6266 bruce 1883 EUB : {
4136 heikki.linnakangas 1884 GIC 51 : inet *ip = PG_GETARG_INET_PP(0);
1885 51 : inet *ip2 = PG_GETARG_INET_PP(1);
1886 : inet *dst;
1887 :
5847 tgl 1888 CBC 51 : dst = (inet *) palloc0(sizeof(inet));
6266 bruce 1889 ECB :
6266 bruce 1890 CBC 51 : if (ip_family(ip) != ip_family(ip2))
6266 bruce 1891 LBC 0 : ereport(ERROR,
1892 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6266 tgl 1893 ECB : errmsg("cannot AND inet values of different sizes")));
bruce 1894 : else
1895 : {
6031 bruce 1896 CBC 51 : int nb = ip_addrsize(ip);
6031 bruce 1897 GIC 51 : unsigned char *pip = ip_addr(ip);
6031 bruce 1898 CBC 51 : unsigned char *pip2 = ip_addr(ip2);
1899 51 : unsigned char *pdst = ip_addr(dst);
1900 :
24 andres 1901 363 : while (--nb >= 0)
6266 bruce 1902 GIC 312 : pdst[nb] = pip[nb] & pip2[nb];
1903 : }
1904 51 : ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
1905 :
6266 bruce 1906 CBC 51 : ip_family(dst) = ip_family(ip);
5847 tgl 1907 GIC 51 : SET_INET_VARSIZE(dst);
6266 bruce 1908 ECB :
6266 bruce 1909 CBC 51 : PG_RETURN_INET_P(dst);
1910 : }
1911 :
6266 bruce 1912 ECB :
1913 : Datum
6266 bruce 1914 CBC 51 : inetor(PG_FUNCTION_ARGS)
6266 bruce 1915 EUB : {
4136 heikki.linnakangas 1916 GIC 51 : inet *ip = PG_GETARG_INET_PP(0);
1917 51 : inet *ip2 = PG_GETARG_INET_PP(1);
1918 : inet *dst;
1919 :
5847 tgl 1920 CBC 51 : dst = (inet *) palloc0(sizeof(inet));
6266 bruce 1921 ECB :
6266 bruce 1922 CBC 51 : if (ip_family(ip) != ip_family(ip2))
6266 bruce 1923 LBC 0 : ereport(ERROR,
1924 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6266 tgl 1925 ECB : errmsg("cannot OR inet values of different sizes")));
bruce 1926 : else
1927 : {
6031 bruce 1928 CBC 51 : int nb = ip_addrsize(ip);
6031 bruce 1929 GIC 51 : unsigned char *pip = ip_addr(ip);
6031 bruce 1930 CBC 51 : unsigned char *pip2 = ip_addr(ip2);
1931 51 : unsigned char *pdst = ip_addr(dst);
1932 :
24 andres 1933 363 : while (--nb >= 0)
6266 bruce 1934 GIC 312 : pdst[nb] = pip[nb] | pip2[nb];
1935 : }
1936 51 : ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
1937 :
6266 bruce 1938 CBC 51 : ip_family(dst) = ip_family(ip);
5847 tgl 1939 GIC 51 : SET_INET_VARSIZE(dst);
1940 :
6266 bruce 1941 51 : PG_RETURN_INET_P(dst);
6266 bruce 1942 ECB : }
1943 :
1944 :
tgl 1945 : static inet *
6266 tgl 1946 CBC 2571 : internal_inetpl(inet *ip, int64 addend)
6266 bruce 1947 ECB : {
1948 : inet *dst;
1949 :
5847 tgl 1950 CBC 2571 : dst = (inet *) palloc0(sizeof(inet));
1951 :
6266 bruce 1952 ECB : {
6031 bruce 1953 CBC 2571 : int nb = ip_addrsize(ip);
1954 2571 : unsigned char *pip = ip_addr(ip);
6031 bruce 1955 GIC 2571 : unsigned char *pdst = ip_addr(dst);
1956 2571 : int carry = 0;
1957 :
24 andres 1958 18687 : while (--nb >= 0)
1959 : {
6266 tgl 1960 16116 : carry = pip[nb] + (int) (addend & 0xFF) + carry;
1961 16116 : pdst[nb] = (unsigned char) (carry & 0xFF);
1962 16116 : carry >>= 8;
1963 :
1964 : /*
6266 tgl 1965 ECB : * We have to be careful about right-shifting addend because
6031 bruce 1966 : * right-shift isn't portable for negative values, while simply
1967 : * dividing by 256 doesn't work (the standard rounding is in the
1968 : * wrong direction, besides which there may be machines out there
1969 : * that round the wrong way). So, explicitly clear the low-order
1970 : * byte to remove any doubt about the correct result of the
1971 : * division, and then divide rather than shift.
1972 : */
6266 tgl 1973 GIC 16116 : addend &= ~((int64) 0xFF);
6266 tgl 1974 CBC 16116 : addend /= 0x100;
6266 bruce 1975 ECB : }
6031 1976 :
1977 : /*
1978 : * At this point we should have addend and carry both zero if original
1979 : * addend was >= 0, or addend -1 and carry 1 if original addend was <
1980 : * 0. Anything else means overflow.
6266 tgl 1981 : */
6266 tgl 1982 CBC 2571 : if (!((addend == 0 && carry == 0) ||
1983 63 : (addend == -1 && carry == 1)))
6266 tgl 1984 GIC 6 : ereport(ERROR,
6266 tgl 1985 ECB : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1986 : errmsg("result is out of range")));
1987 : }
1988 :
5847 tgl 1989 GIC 2565 : ip_bits(dst) = ip_bits(ip);
6266 bruce 1990 CBC 2565 : ip_family(dst) = ip_family(ip);
5847 tgl 1991 GIC 2565 : SET_INET_VARSIZE(dst);
6266 bruce 1992 ECB :
6266 tgl 1993 CBC 2565 : return dst;
1994 : }
6266 bruce 1995 ECB :
1996 :
1997 : Datum
6266 bruce 1998 GIC 2505 : inetpl(PG_FUNCTION_ARGS)
1999 : {
4136 heikki.linnakangas 2000 CBC 2505 : inet *ip = PG_GETARG_INET_PP(0);
6031 bruce 2001 GIC 2505 : int64 addend = PG_GETARG_INT64(1);
6266 bruce 2002 ECB :
6266 tgl 2003 CBC 2505 : PG_RETURN_INET_P(internal_inetpl(ip, addend));
2004 : }
6266 bruce 2005 ECB :
2006 :
2007 : Datum
6266 bruce 2008 GIC 66 : inetmi_int8(PG_FUNCTION_ARGS)
2009 : {
4136 heikki.linnakangas 2010 CBC 66 : inet *ip = PG_GETARG_INET_PP(0);
6031 bruce 2011 GIC 66 : int64 addend = PG_GETARG_INT64(1);
6266 bruce 2012 ECB :
6266 tgl 2013 CBC 66 : PG_RETURN_INET_P(internal_inetpl(ip, -addend));
6266 bruce 2014 ECB : }
2015 :
2016 :
6266 bruce 2017 EUB : Datum
6266 bruce 2018 GIC 72 : inetmi(PG_FUNCTION_ARGS)
2019 : {
4136 heikki.linnakangas 2020 72 : inet *ip = PG_GETARG_INET_PP(0);
2021 72 : inet *ip2 = PG_GETARG_INET_PP(1);
6266 bruce 2022 72 : int64 res = 0;
2023 :
2024 72 : if (ip_family(ip) != ip_family(ip2))
6266 bruce 2025 UIC 0 : ereport(ERROR,
2026 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2027 : errmsg("cannot subtract inet values of different sizes")));
6266 bruce 2028 ECB : else
2029 : {
tgl 2030 : /*
6031 bruce 2031 : * We form the difference using the traditional complement, increment,
2032 : * and add rule, with the increment part being handled by starting the
2033 : * carry off at 1. If you don't think integer arithmetic is done in
2034 : * two's complement, too bad.
2035 : */
6031 bruce 2036 GIC 72 : int nb = ip_addrsize(ip);
4382 2037 72 : int byte = 0;
6031 bruce 2038 CBC 72 : unsigned char *pip = ip_addr(ip);
2039 72 : unsigned char *pip2 = ip_addr(ip2);
2040 72 : int carry = 1;
2041 :
24 andres 2042 636 : while (--nb >= 0)
2043 : {
2044 : int lobyte;
2045 :
6266 tgl 2046 GIC 570 : carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
2047 570 : lobyte = carry & 0xFF;
4382 bruce 2048 570 : if (byte < sizeof(int64))
2049 : {
2050 384 : res |= ((int64) lobyte) << (byte * 8);
6266 tgl 2051 ECB : }
2052 : else
2053 : {
2054 : /*
2055 : * Input wider than int64: check for overflow. All bytes to
6031 bruce 2056 : * the left of what will fit should be 0 or 0xFF, depending on
2057 : * sign of the now-complete result.
2058 : */
6266 tgl 2059 GIC 186 : if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
bruce 2060 6 : ereport(ERROR,
2061 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
2062 : errmsg("result is out of range")));
2063 : }
6266 tgl 2064 CBC 564 : carry >>= 8;
4382 bruce 2065 564 : byte++;
2066 : }
2067 :
6266 tgl 2068 ECB : /*
2069 : * If input is narrower than int64, overflow is not possible, but we
2070 : * have to do proper sign extension.
2071 : */
4382 bruce 2072 GIC 66 : if (carry == 0 && byte < sizeof(int64))
1757 tgl 2073 6 : res |= ((uint64) (int64) -1) << (byte * 8);
2074 : }
2075 :
6266 bruce 2076 66 : PG_RETURN_INT64(res);
2077 : }
2078 :
2079 :
2080 : /*
2081 : * clean_ipv6_addr --- remove any '%zone' part from an IPv6 address string
2082 : *
2083 : * XXX This should go away someday!
2084 : *
2085 : * This is a kluge needed because we don't yet support zones in stored inet
2086 : * values. Since the result of getnameinfo() might include a zone spec,
5806 tgl 2087 ECB : * call this to remove it anywhere we want to feed getnameinfo's output to
2088 : * network_in. Beats failing entirely.
2089 : *
2090 : * An alternative approach would be to let network_in ignore %-parts for
2091 : * itself, but that would mean we'd silently drop zone specs in user input,
2092 : * which seems not such a good idea.
2093 : */
5806 tgl 2094 EUB : void
5806 tgl 2095 GIC 39 : clean_ipv6_addr(int addr_family, char *addr)
5806 tgl 2096 ECB : {
5806 tgl 2097 GIC 39 : if (addr_family == AF_INET6)
2098 : {
5624 bruce 2099 12 : char *pct = strchr(addr, '%');
2100 :
5806 tgl 2101 12 : if (pct)
5806 tgl 2102 UIC 0 : *pct = '\0';
2103 : }
5806 tgl 2104 GIC 39 : }
|