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