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