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