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