1/*
2 * PostgreSQL type definitions for the INET and CIDR types.
3 *
4 * src/backend/utils/adt/network.c
5 *
6 * Jon Postel RIP 16 Oct 1998
7 */
8
9#include "postgres.h"
10
11#include <sys/socket.h>
12#include <netinet/in.h>
13#include <arpa/inet.h>
14
15#include "access/stratnum.h"
16#include "catalog/pg_opfamily.h"
17#include "catalog/pg_type.h"
18#include "common/ip.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/hashutils.h"
28#include "utils/inet.h"
29#include "utils/lsyscache.h"
30
31
32static int32 network_cmp_internal(inet *a1, inet *a2);
33static List *match_network_function(Node *leftop,
34 Node *rightop,
35 int indexarg,
36 Oid funcid,
37 Oid opfamily);
38static List *match_network_subset(Node *leftop,
39 Node *rightop,
40 bool is_eq,
41 Oid opfamily);
42static bool addressOK(unsigned char *a, int bits, int family);
43static inet *internal_inetpl(inet *ip, int64 addend);
44
45
46/*
47 * Common INET/CIDR input routine
48 */
49static inet *
50network_in(char *src, bool is_cidr)
51{
52 int bits;
53 inet *dst;
54
55 dst = (inet *) palloc0(sizeof(inet));
56
57 /*
58 * First, check to see if this is an IPv6 or IPv4 address. IPv6 addresses
59 * will have a : somewhere in them (several, in fact) so if there is one
60 * present, assume it's V6, otherwise assume it's V4.
61 */
62
63 if (strchr(src, ':') != NULL)
64 ip_family(dst) = PGSQL_AF_INET6;
65 else
66 ip_family(dst) = PGSQL_AF_INET;
67
68 bits = inet_net_pton(ip_family(dst), src, ip_addr(dst),
69 is_cidr ? ip_addrsize(dst) : -1);
70 if ((bits < 0) || (bits > ip_maxbits(dst)))
71 ereport(ERROR,
72 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
73 /* translator: first %s is inet or cidr */
74 errmsg("invalid input syntax for type %s: \"%s\"",
75 is_cidr ? "cidr" : "inet", src)));
76
77 /*
78 * Error check: CIDR values must not have any bits set beyond the masklen.
79 */
80 if (is_cidr)
81 {
82 if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
83 ereport(ERROR,
84 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
85 errmsg("invalid cidr value: \"%s\"", src),
86 errdetail("Value has bits set to right of mask.")));
87 }
88
89 ip_bits(dst) = bits;
90 SET_INET_VARSIZE(dst);
91
92 return dst;
93}
94
95Datum
96inet_in(PG_FUNCTION_ARGS)
97{
98 char *src = PG_GETARG_CSTRING(0);
99
100 PG_RETURN_INET_P(network_in(src, false));
101}
102
103Datum
104cidr_in(PG_FUNCTION_ARGS)
105{
106 char *src = PG_GETARG_CSTRING(0);
107
108 PG_RETURN_INET_P(network_in(src, true));
109}
110
111
112/*
113 * Common INET/CIDR output routine
114 */
115static char *
116network_out(inet *src, bool is_cidr)
117{
118 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
119 char *dst;
120 int len;
121
122 dst = inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
123 tmp, sizeof(tmp));
124 if (dst == NULL)
125 ereport(ERROR,
126 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
127 errmsg("could not format inet value: %m")));
128
129 /* For CIDR, add /n if not present */
130 if (is_cidr && strchr(tmp, '/') == NULL)
131 {
132 len = strlen(tmp);
133 snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
134 }
135
136 return pstrdup(tmp);
137}
138
139Datum
140inet_out(PG_FUNCTION_ARGS)
141{
142 inet *src = PG_GETARG_INET_PP(0);
143
144 PG_RETURN_CSTRING(network_out(src, false));
145}
146
147Datum
148cidr_out(PG_FUNCTION_ARGS)
149{
150 inet *src = PG_GETARG_INET_PP(0);
151
152 PG_RETURN_CSTRING(network_out(src, true));
153}
154
155
156/*
157 * network_recv - converts external binary format to inet
158 *
159 * The external representation is (one byte apiece for)
160 * family, bits, is_cidr, address length, address in network byte order.
161 *
162 * Presence of is_cidr is largely for historical reasons, though it might
163 * allow some code-sharing on the client side. We send it correctly on
164 * output, but ignore the value on input.
165 */
166static inet *
167network_recv(StringInfo buf, bool is_cidr)
168{
169 inet *addr;
170 char *addrptr;
171 int bits;
172 int nb,
173 i;
174
175 /* make sure any unused bits in a CIDR value are zeroed */
176 addr = (inet *) palloc0(sizeof(inet));
177
178 ip_family(addr) = pq_getmsgbyte(buf);
179 if (ip_family(addr) != PGSQL_AF_INET &&
180 ip_family(addr) != PGSQL_AF_INET6)
181 ereport(ERROR,
182 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
183 /* translator: %s is inet or cidr */
184 errmsg("invalid address family in external \"%s\" value",
185 is_cidr ? "cidr" : "inet")));
186 bits = pq_getmsgbyte(buf);
187 if (bits < 0 || bits > ip_maxbits(addr))
188 ereport(ERROR,
189 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
190 /* translator: %s is inet or cidr */
191 errmsg("invalid bits in external \"%s\" value",
192 is_cidr ? "cidr" : "inet")));
193 ip_bits(addr) = bits;
194 i = pq_getmsgbyte(buf); /* ignore is_cidr */
195 nb = pq_getmsgbyte(buf);
196 if (nb != ip_addrsize(addr))
197 ereport(ERROR,
198 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
199 /* translator: %s is inet or cidr */
200 errmsg("invalid length in external \"%s\" value",
201 is_cidr ? "cidr" : "inet")));
202
203 addrptr = (char *) ip_addr(addr);
204 for (i = 0; i < nb; i++)
205 addrptr[i] = pq_getmsgbyte(buf);
206
207 /*
208 * Error check: CIDR values must not have any bits set beyond the masklen.
209 */
210 if (is_cidr)
211 {
212 if (!addressOK(ip_addr(addr), bits, ip_family(addr)))
213 ereport(ERROR,
214 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
215 errmsg("invalid external \"cidr\" value"),
216 errdetail("Value has bits set to right of mask.")));
217 }
218
219 SET_INET_VARSIZE(addr);
220
221 return addr;
222}
223
224Datum
225inet_recv(PG_FUNCTION_ARGS)
226{
227 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
228
229 PG_RETURN_INET_P(network_recv(buf, false));
230}
231
232Datum
233cidr_recv(PG_FUNCTION_ARGS)
234{
235 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
236
237 PG_RETURN_INET_P(network_recv(buf, true));
238}
239
240
241/*
242 * network_send - converts inet to binary format
243 */
244static bytea *
245network_send(inet *addr, bool is_cidr)
246{
247 StringInfoData buf;
248 char *addrptr;
249 int nb,
250 i;
251
252 pq_begintypsend(&buf);
253 pq_sendbyte(&buf, ip_family(addr));
254 pq_sendbyte(&buf, ip_bits(addr));
255 pq_sendbyte(&buf, is_cidr);
256 nb = ip_addrsize(addr);
257 if (nb < 0)
258 nb = 0;
259 pq_sendbyte(&buf, nb);
260 addrptr = (char *) ip_addr(addr);
261 for (i = 0; i < nb; i++)
262 pq_sendbyte(&buf, addrptr[i]);
263 return pq_endtypsend(&buf);
264}
265
266Datum
267inet_send(PG_FUNCTION_ARGS)
268{
269 inet *addr = PG_GETARG_INET_PP(0);
270
271 PG_RETURN_BYTEA_P(network_send(addr, false));
272}
273
274Datum
275cidr_send(PG_FUNCTION_ARGS)
276{
277 inet *addr = PG_GETARG_INET_PP(0);
278
279 PG_RETURN_BYTEA_P(network_send(addr, true));
280}
281
282
283Datum
284inet_to_cidr(PG_FUNCTION_ARGS)
285{
286 inet *src = PG_GETARG_INET_PP(0);
287 int bits;
288
289 bits = ip_bits(src);
290
291 /* safety check */
292 if ((bits < 0) || (bits > ip_maxbits(src)))
293 elog(ERROR, "invalid inet bit length: %d", bits);
294
295 PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
296}
297
298Datum
299inet_set_masklen(PG_FUNCTION_ARGS)
300{
301 inet *src = PG_GETARG_INET_PP(0);
302 int bits = PG_GETARG_INT32(1);
303 inet *dst;
304
305 if (bits == -1)
306 bits = ip_maxbits(src);
307
308 if ((bits < 0) || (bits > ip_maxbits(src)))
309 ereport(ERROR,
310 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
311 errmsg("invalid mask length: %d", bits)));
312
313 /* clone the original data */
314 dst = (inet *) palloc(VARSIZE_ANY(src));
315 memcpy(dst, src, VARSIZE_ANY(src));
316
317 ip_bits(dst) = bits;
318
319 PG_RETURN_INET_P(dst);
320}
321
322Datum
323cidr_set_masklen(PG_FUNCTION_ARGS)
324{
325 inet *src = PG_GETARG_INET_PP(0);
326 int bits = PG_GETARG_INT32(1);
327
328 if (bits == -1)
329 bits = ip_maxbits(src);
330
331 if ((bits < 0) || (bits > ip_maxbits(src)))
332 ereport(ERROR,
333 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
334 errmsg("invalid mask length: %d", bits)));
335
336 PG_RETURN_INET_P(cidr_set_masklen_internal(src, bits));
337}
338
339/*
340 * Copy src and set mask length to 'bits' (which must be valid for the family)
341 */
342inet *
343cidr_set_masklen_internal(const inet *src, int bits)
344{
345 inet *dst = (inet *) palloc0(sizeof(inet));
346
347 ip_family(dst) = ip_family(src);
348 ip_bits(dst) = bits;
349
350 if (bits > 0)
351 {
352 Assert(bits <= ip_maxbits(dst));
353
354 /* Clone appropriate bytes of the address, leaving the rest 0 */
355 memcpy(ip_addr(dst), ip_addr(src), (bits + 7) / 8);
356
357 /* Clear any unwanted bits in the last partial byte */
358 if (bits % 8)
359 ip_addr(dst)[bits / 8] &= ~(0xFF >> (bits % 8));
360 }
361
362 /* Set varlena header correctly */
363 SET_INET_VARSIZE(dst);
364
365 return dst;
366}
367
368/*
369 * Basic comparison function for sorting and inet/cidr comparisons.
370 *
371 * Comparison is first on the common bits of the network part, then on
372 * the length of the network part, and then on the whole unmasked address.
373 * The effect is that the network part is the major sort key, and for
374 * equal network parts we sort on the host part. Note this is only sane
375 * for CIDR if address bits to the right of the mask are guaranteed zero;
376 * otherwise logically-equal CIDRs might compare different.
377 */
378
379static int32
380network_cmp_internal(inet *a1, inet *a2)
381{
382 if (ip_family(a1) == ip_family(a2))
383 {
384 int order;
385
386 order = bitncmp(ip_addr(a1), ip_addr(a2),
387 Min(ip_bits(a1), ip_bits(a2)));
388 if (order != 0)
389 return order;
390 order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
391 if (order != 0)
392 return order;
393 return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
394 }
395
396 return ip_family(a1) - ip_family(a2);
397}
398
399Datum
400network_cmp(PG_FUNCTION_ARGS)
401{
402 inet *a1 = PG_GETARG_INET_PP(0);
403 inet *a2 = PG_GETARG_INET_PP(1);
404
405 PG_RETURN_INT32(network_cmp_internal(a1, a2));
406}
407
408/*
409 * Boolean ordering tests.
410 */
411Datum
412network_lt(PG_FUNCTION_ARGS)
413{
414 inet *a1 = PG_GETARG_INET_PP(0);
415 inet *a2 = PG_GETARG_INET_PP(1);
416
417 PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
418}
419
420Datum
421network_le(PG_FUNCTION_ARGS)
422{
423 inet *a1 = PG_GETARG_INET_PP(0);
424 inet *a2 = PG_GETARG_INET_PP(1);
425
426 PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
427}
428
429Datum
430network_eq(PG_FUNCTION_ARGS)
431{
432 inet *a1 = PG_GETARG_INET_PP(0);
433 inet *a2 = PG_GETARG_INET_PP(1);
434
435 PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
436}
437
438Datum
439network_ge(PG_FUNCTION_ARGS)
440{
441 inet *a1 = PG_GETARG_INET_PP(0);
442 inet *a2 = PG_GETARG_INET_PP(1);
443
444 PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
445}
446
447Datum
448network_gt(PG_FUNCTION_ARGS)
449{
450 inet *a1 = PG_GETARG_INET_PP(0);
451 inet *a2 = PG_GETARG_INET_PP(1);
452
453 PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
454}
455
456Datum
457network_ne(PG_FUNCTION_ARGS)
458{
459 inet *a1 = PG_GETARG_INET_PP(0);
460 inet *a2 = PG_GETARG_INET_PP(1);
461
462 PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
463}
464
465/*
466 * MIN/MAX support functions.
467 */
468Datum
469network_smaller(PG_FUNCTION_ARGS)
470{
471 inet *a1 = PG_GETARG_INET_PP(0);
472 inet *a2 = PG_GETARG_INET_PP(1);
473
474 if (network_cmp_internal(a1, a2) < 0)
475 PG_RETURN_INET_P(a1);
476 else
477 PG_RETURN_INET_P(a2);
478}
479
480Datum
481network_larger(PG_FUNCTION_ARGS)
482{
483 inet *a1 = PG_GETARG_INET_PP(0);
484 inet *a2 = PG_GETARG_INET_PP(1);
485
486 if (network_cmp_internal(a1, a2) > 0)
487 PG_RETURN_INET_P(a1);
488 else
489 PG_RETURN_INET_P(a2);
490}
491
492/*
493 * Support function for hash indexes on inet/cidr.
494 */
495Datum
496hashinet(PG_FUNCTION_ARGS)
497{
498 inet *addr = PG_GETARG_INET_PP(0);
499 int addrsize = ip_addrsize(addr);
500
501 /* XXX this assumes there are no pad bytes in the data structure */
502 return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
503}
504
505Datum
506hashinetextended(PG_FUNCTION_ARGS)
507{
508 inet *addr = PG_GETARG_INET_PP(0);
509 int addrsize = ip_addrsize(addr);
510
511 return hash_any_extended((unsigned char *) VARDATA_ANY(addr), addrsize + 2,
512 PG_GETARG_INT64(1));
513}
514
515/*
516 * Boolean network-inclusion tests.
517 */
518Datum
519network_sub(PG_FUNCTION_ARGS)
520{
521 inet *a1 = PG_GETARG_INET_PP(0);
522 inet *a2 = PG_GETARG_INET_PP(1);
523
524 if (ip_family(a1) == ip_family(a2))
525 {
526 PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2) &&
527 bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
528 }
529
530 PG_RETURN_BOOL(false);
531}
532
533Datum
534network_subeq(PG_FUNCTION_ARGS)
535{
536 inet *a1 = PG_GETARG_INET_PP(0);
537 inet *a2 = PG_GETARG_INET_PP(1);
538
539 if (ip_family(a1) == ip_family(a2))
540 {
541 PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2) &&
542 bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
543 }
544
545 PG_RETURN_BOOL(false);
546}
547
548Datum
549network_sup(PG_FUNCTION_ARGS)
550{
551 inet *a1 = PG_GETARG_INET_PP(0);
552 inet *a2 = PG_GETARG_INET_PP(1);
553
554 if (ip_family(a1) == ip_family(a2))
555 {
556 PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2) &&
557 bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
558 }
559
560 PG_RETURN_BOOL(false);
561}
562
563Datum
564network_supeq(PG_FUNCTION_ARGS)
565{
566 inet *a1 = PG_GETARG_INET_PP(0);
567 inet *a2 = PG_GETARG_INET_PP(1);
568
569 if (ip_family(a1) == ip_family(a2))
570 {
571 PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2) &&
572 bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
573 }
574
575 PG_RETURN_BOOL(false);
576}
577
578Datum
579network_overlap(PG_FUNCTION_ARGS)
580{
581 inet *a1 = PG_GETARG_INET_PP(0);
582 inet *a2 = PG_GETARG_INET_PP(1);
583
584 if (ip_family(a1) == ip_family(a2))
585 {
586 PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
587 Min(ip_bits(a1), ip_bits(a2))) == 0);
588 }
589
590 PG_RETURN_BOOL(false);
591}
592
593/*
594 * Planner support function for network subset/superset operators
595 */
596Datum
597network_subset_support(PG_FUNCTION_ARGS)
598{
599 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
600 Node *ret = NULL;
601
602 if (IsA(rawreq, SupportRequestIndexCondition))
603 {
604 /* Try to convert operator/function call to index conditions */
605 SupportRequestIndexCondition *req = (SupportRequestIndexCondition *) rawreq;
606
607 if (is_opclause(req->node))
608 {
609 OpExpr *clause = (OpExpr *) req->node;
610
611 Assert(list_length(clause->args) == 2);
612 ret = (Node *)
613 match_network_function((Node *) linitial(clause->args),
614 (Node *) lsecond(clause->args),
615 req->indexarg,
616 req->funcid,
617 req->opfamily);
618 }
619 else if (is_funcclause(req->node)) /* be paranoid */
620 {
621 FuncExpr *clause = (FuncExpr *) req->node;
622
623 Assert(list_length(clause->args) == 2);
624 ret = (Node *)
625 match_network_function((Node *) linitial(clause->args),
626 (Node *) lsecond(clause->args),
627 req->indexarg,
628 req->funcid,
629 req->opfamily);
630 }
631 }
632
633 PG_RETURN_POINTER(ret);
634}
635
636/*
637 * match_network_function
638 * Try to generate an indexqual for a network subset/superset function.
639 *
640 * This layer is just concerned with identifying the function and swapping
641 * the arguments if necessary.
642 */
643static List *
644match_network_function(Node *leftop,
645 Node *rightop,
646 int indexarg,
647 Oid funcid,
648 Oid opfamily)
649{
650 switch (funcid)
651 {
652 case F_NETWORK_SUB:
653 /* indexkey must be on the left */
654 if (indexarg != 0)
655 return NIL;
656 return match_network_subset(leftop, rightop, false, opfamily);
657
658 case F_NETWORK_SUBEQ:
659 /* indexkey must be on the left */
660 if (indexarg != 0)
661 return NIL;
662 return match_network_subset(leftop, rightop, true, opfamily);
663
664 case F_NETWORK_SUP:
665 /* indexkey must be on the right */
666 if (indexarg != 1)
667 return NIL;
668 return match_network_subset(rightop, leftop, false, opfamily);
669
670 case F_NETWORK_SUPEQ:
671 /* indexkey must be on the right */
672 if (indexarg != 1)
673 return NIL;
674 return match_network_subset(rightop, leftop, true, opfamily);
675
676 default:
677
678 /*
679 * We'd only get here if somebody attached this support function
680 * to an unexpected function. Maybe we should complain, but for
681 * now, do nothing.
682 */
683 return NIL;
684 }
685}
686
687/*
688 * match_network_subset
689 * Try to generate an indexqual for a network subset function.
690 */
691static List *
692match_network_subset(Node *leftop,
693 Node *rightop,
694 bool is_eq,
695 Oid opfamily)
696{
697 List *result;
698 Datum rightopval;
699 Oid datatype = INETOID;
700 Oid opr1oid;
701 Oid opr2oid;
702 Datum opr1right;
703 Datum opr2right;
704 Expr *expr;
705
706 /*
707 * Can't do anything with a non-constant or NULL comparison value.
708 *
709 * Note that since we restrict ourselves to cases with a hard constant on
710 * the RHS, it's a-fortiori a pseudoconstant, and we don't need to worry
711 * about verifying that.
712 */
713 if (!IsA(rightop, Const) ||
714 ((Const *) rightop)->constisnull)
715 return NIL;
716 rightopval = ((Const *) rightop)->constvalue;
717
718 /*
719 * Must check that index's opfamily supports the operators we will want to
720 * apply.
721 *
722 * We insist on the opfamily being the specific one we expect, else we'd
723 * do the wrong thing if someone were to make a reverse-sort opfamily with
724 * the same operators.
725 */
726 if (opfamily != NETWORK_BTREE_FAM_OID)
727 return NIL;
728
729 /*
730 * create clause "key >= network_scan_first( rightopval )", or ">" if the
731 * operator disallows equality.
732 *
733 * Note: seeing that this function supports only fixed values for opfamily
734 * and datatype, we could just hard-wire the operator OIDs instead of
735 * looking them up. But for now it seems better to be general.
736 */
737 if (is_eq)
738 {
739 opr1oid = get_opfamily_member(opfamily, datatype, datatype,
740 BTGreaterEqualStrategyNumber);
741 if (opr1oid == InvalidOid)
742 elog(ERROR, "no >= operator for opfamily %u", opfamily);
743 }
744 else
745 {
746 opr1oid = get_opfamily_member(opfamily, datatype, datatype,
747 BTGreaterStrategyNumber);
748 if (opr1oid == InvalidOid)
749 elog(ERROR, "no > operator for opfamily %u", opfamily);
750 }
751
752 opr1right = network_scan_first(rightopval);
753
754 expr = make_opclause(opr1oid, BOOLOID, false,
755 (Expr *) leftop,
756 (Expr *) makeConst(datatype, -1,
757 InvalidOid, /* not collatable */
758 -1, opr1right,
759 false, false),
760 InvalidOid, InvalidOid);
761 result = list_make1(expr);
762
763 /* create clause "key <= network_scan_last( rightopval )" */
764
765 opr2oid = get_opfamily_member(opfamily, datatype, datatype,
766 BTLessEqualStrategyNumber);
767 if (opr2oid == InvalidOid)
768 elog(ERROR, "no <= operator for opfamily %u", opfamily);
769
770 opr2right = network_scan_last(rightopval);
771
772 expr = make_opclause(opr2oid, BOOLOID, false,
773 (Expr *) leftop,
774 (Expr *) makeConst(datatype, -1,
775 InvalidOid, /* not collatable */
776 -1, opr2right,
777 false, false),
778 InvalidOid, InvalidOid);
779 result = lappend(result, expr);
780
781 return result;
782}
783
784
785/*
786 * Extract data from a network datatype.
787 */
788Datum
789network_host(PG_FUNCTION_ARGS)
790{
791 inet *ip = PG_GETARG_INET_PP(0);
792 char *ptr;
793 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
794
795 /* force display of max bits, regardless of masklen... */
796 if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
797 tmp, sizeof(tmp)) == NULL)
798 ereport(ERROR,
799 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
800 errmsg("could not format inet value: %m")));
801
802 /* Suppress /n if present (shouldn't happen now) */
803 if ((ptr = strchr(tmp, '/')) != NULL)
804 *ptr = '\0';
805
806 PG_RETURN_TEXT_P(cstring_to_text(tmp));
807}
808
809/*
810 * network_show implements the inet and cidr casts to text. This is not
811 * quite the same behavior as network_out, hence we can't drop it in favor
812 * of CoerceViaIO.
813 */
814Datum
815network_show(PG_FUNCTION_ARGS)
816{
817 inet *ip = PG_GETARG_INET_PP(0);
818 int len;
819 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
820
821 if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
822 tmp, sizeof(tmp)) == NULL)
823 ereport(ERROR,
824 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
825 errmsg("could not format inet value: %m")));
826
827 /* Add /n if not present (which it won't be) */
828 if (strchr(tmp, '/') == NULL)
829 {
830 len = strlen(tmp);
831 snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
832 }
833
834 PG_RETURN_TEXT_P(cstring_to_text(tmp));
835}
836
837Datum
838inet_abbrev(PG_FUNCTION_ARGS)
839{
840 inet *ip = PG_GETARG_INET_PP(0);
841 char *dst;
842 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
843
844 dst = inet_net_ntop(ip_family(ip), ip_addr(ip),
845 ip_bits(ip), tmp, sizeof(tmp));
846
847 if (dst == NULL)
848 ereport(ERROR,
849 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
850 errmsg("could not format inet value: %m")));
851
852 PG_RETURN_TEXT_P(cstring_to_text(tmp));
853}
854
855Datum
856cidr_abbrev(PG_FUNCTION_ARGS)
857{
858 inet *ip = PG_GETARG_INET_PP(0);
859 char *dst;
860 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
861
862 dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip),
863 ip_bits(ip), tmp, sizeof(tmp));
864
865 if (dst == NULL)
866 ereport(ERROR,
867 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
868 errmsg("could not format cidr value: %m")));
869
870 PG_RETURN_TEXT_P(cstring_to_text(tmp));
871}
872
873Datum
874network_masklen(PG_FUNCTION_ARGS)
875{
876 inet *ip = PG_GETARG_INET_PP(0);
877
878 PG_RETURN_INT32(ip_bits(ip));
879}
880
881Datum
882network_family(PG_FUNCTION_ARGS)
883{
884 inet *ip = PG_GETARG_INET_PP(0);
885
886 switch (ip_family(ip))
887 {
888 case PGSQL_AF_INET:
889 PG_RETURN_INT32(4);
890 break;
891 case PGSQL_AF_INET6:
892 PG_RETURN_INT32(6);
893 break;
894 default:
895 PG_RETURN_INT32(0);
896 break;
897 }
898}
899
900Datum
901network_broadcast(PG_FUNCTION_ARGS)
902{
903 inet *ip = PG_GETARG_INET_PP(0);
904 inet *dst;
905 int byte;
906 int bits;
907 int maxbytes;
908 unsigned char mask;
909 unsigned char *a,
910 *b;
911
912 /* make sure any unused bits are zeroed */
913 dst = (inet *) palloc0(sizeof(inet));
914
915 maxbytes = ip_addrsize(ip);
916 bits = ip_bits(ip);
917 a = ip_addr(ip);
918 b = ip_addr(dst);
919
920 for (byte = 0; byte < maxbytes; byte++)
921 {
922 if (bits >= 8)
923 {
924 mask = 0x00;
925 bits -= 8;
926 }
927 else if (bits == 0)
928 mask = 0xff;
929 else
930 {
931 mask = 0xff >> bits;
932 bits = 0;
933 }
934
935 b[byte] = a[byte] | mask;
936 }
937
938 ip_family(dst) = ip_family(ip);
939 ip_bits(dst) = ip_bits(ip);
940 SET_INET_VARSIZE(dst);
941
942 PG_RETURN_INET_P(dst);
943}
944
945Datum
946network_network(PG_FUNCTION_ARGS)
947{
948 inet *ip = PG_GETARG_INET_PP(0);
949 inet *dst;
950 int byte;
951 int bits;
952 unsigned char mask;
953 unsigned char *a,
954 *b;
955
956 /* make sure any unused bits are zeroed */
957 dst = (inet *) palloc0(sizeof(inet));
958
959 bits = ip_bits(ip);
960 a = ip_addr(ip);
961 b = ip_addr(dst);
962
963 byte = 0;
964
965 while (bits)
966 {
967 if (bits >= 8)
968 {
969 mask = 0xff;
970 bits -= 8;
971 }
972 else
973 {
974 mask = 0xff << (8 - bits);
975 bits = 0;
976 }
977
978 b[byte] = a[byte] & mask;
979 byte++;
980 }
981
982 ip_family(dst) = ip_family(ip);
983 ip_bits(dst) = ip_bits(ip);
984 SET_INET_VARSIZE(dst);
985
986 PG_RETURN_INET_P(dst);
987}
988
989Datum
990network_netmask(PG_FUNCTION_ARGS)
991{
992 inet *ip = PG_GETARG_INET_PP(0);
993 inet *dst;
994 int byte;
995 int bits;
996 unsigned char mask;
997 unsigned char *b;
998
999 /* make sure any unused bits are zeroed */
1000 dst = (inet *) palloc0(sizeof(inet));
1001
1002 bits = ip_bits(ip);
1003 b = ip_addr(dst);
1004
1005 byte = 0;
1006
1007 while (bits)
1008 {
1009 if (bits >= 8)
1010 {
1011 mask = 0xff;
1012 bits -= 8;
1013 }
1014 else
1015 {
1016 mask = 0xff << (8 - bits);
1017 bits = 0;
1018 }
1019
1020 b[byte] = mask;
1021 byte++;
1022 }
1023
1024 ip_family(dst) = ip_family(ip);
1025 ip_bits(dst) = ip_maxbits(ip);
1026 SET_INET_VARSIZE(dst);
1027
1028 PG_RETURN_INET_P(dst);
1029}
1030
1031Datum
1032network_hostmask(PG_FUNCTION_ARGS)
1033{
1034 inet *ip = PG_GETARG_INET_PP(0);
1035 inet *dst;
1036 int byte;
1037 int bits;
1038 int maxbytes;
1039 unsigned char mask;
1040 unsigned char *b;
1041
1042 /* make sure any unused bits are zeroed */
1043 dst = (inet *) palloc0(sizeof(inet));
1044
1045 maxbytes = ip_addrsize(ip);
1046 bits = ip_maxbits(ip) - ip_bits(ip);
1047 b = ip_addr(dst);
1048
1049 byte = maxbytes - 1;
1050
1051 while (bits)
1052 {
1053 if (bits >= 8)
1054 {
1055 mask = 0xff;
1056 bits -= 8;
1057 }
1058 else
1059 {
1060 mask = 0xff >> (8 - bits);
1061 bits = 0;
1062 }
1063
1064 b[byte] = mask;
1065 byte--;
1066 }
1067
1068 ip_family(dst) = ip_family(ip);
1069 ip_bits(dst) = ip_maxbits(ip);
1070 SET_INET_VARSIZE(dst);
1071
1072 PG_RETURN_INET_P(dst);
1073}
1074
1075/*
1076 * Returns true if the addresses are from the same family, or false. Used to
1077 * check that we can create a network which contains both of the networks.
1078 */
1079Datum
1080inet_same_family(PG_FUNCTION_ARGS)
1081{
1082 inet *a1 = PG_GETARG_INET_PP(0);
1083 inet *a2 = PG_GETARG_INET_PP(1);
1084
1085 PG_RETURN_BOOL(ip_family(a1) == ip_family(a2));
1086}
1087
1088/*
1089 * Returns the smallest CIDR which contains both of the inputs.
1090 */
1091Datum
1092inet_merge(PG_FUNCTION_ARGS)
1093{
1094 inet *a1 = PG_GETARG_INET_PP(0),
1095 *a2 = PG_GETARG_INET_PP(1);
1096 int commonbits;
1097
1098 if (ip_family(a1) != ip_family(a2))
1099 ereport(ERROR,
1100 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1101 errmsg("cannot merge addresses from different families")));
1102
1103 commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
1104 Min(ip_bits(a1), ip_bits(a2)));
1105
1106 PG_RETURN_INET_P(cidr_set_masklen_internal(a1, commonbits));
1107}
1108
1109/*
1110 * Convert a value of a network datatype to an approximate scalar value.
1111 * This is used for estimating selectivities of inequality operators
1112 * involving network types.
1113 *
1114 * On failure (e.g., unsupported typid), set *failure to true;
1115 * otherwise, that variable is not changed.
1116 */
1117double
1118convert_network_to_scalar(Datum value, Oid typid, bool *failure)
1119{
1120 switch (typid)
1121 {
1122 case INETOID:
1123 case CIDROID:
1124 {
1125 inet *ip = DatumGetInetPP(value);
1126 int len;
1127 double res;
1128 int i;
1129
1130 /*
1131 * Note that we don't use the full address for IPv6.
1132 */
1133 if (ip_family(ip) == PGSQL_AF_INET)
1134 len = 4;
1135 else
1136 len = 5;
1137
1138 res = ip_family(ip);
1139 for (i = 0; i < len; i++)
1140 {
1141 res *= 256;
1142 res += ip_addr(ip)[i];
1143 }
1144 return res;
1145 }
1146 case MACADDROID:
1147 {
1148 macaddr *mac = DatumGetMacaddrP(value);
1149 double res;
1150
1151 res = (mac->a << 16) | (mac->b << 8) | (mac->c);
1152 res *= 256 * 256 * 256;
1153 res += (mac->d << 16) | (mac->e << 8) | (mac->f);
1154 return res;
1155 }
1156 case MACADDR8OID:
1157 {
1158 macaddr8 *mac = DatumGetMacaddr8P(value);
1159 double res;
1160
1161 res = (mac->a << 24) | (mac->b << 16) | (mac->c << 8) | (mac->d);
1162 res *= ((double) 256) * 256 * 256 * 256;
1163 res += (mac->e << 24) | (mac->f << 16) | (mac->g << 8) | (mac->h);
1164 return res;
1165 }
1166 }
1167
1168 *failure = true;
1169 return 0;
1170}
1171
1172/*
1173 * int
1174 * bitncmp(l, r, n)
1175 * compare bit masks l and r, for n bits.
1176 * return:
1177 * <0, >0, or 0 in the libc tradition.
1178 * note:
1179 * network byte order assumed. this means 192.5.5.240/28 has
1180 * 0x11110000 in its fourth octet.
1181 * author:
1182 * Paul Vixie (ISC), June 1996
1183 */
1184int
1185bitncmp(const unsigned char *l, const unsigned char *r, int n)
1186{
1187 unsigned int lb,
1188 rb;
1189 int x,
1190 b;
1191
1192 b = n / 8;
1193 x = memcmp(l, r, b);
1194 if (x || (n % 8) == 0)
1195 return x;
1196
1197 lb = l[b];
1198 rb = r[b];
1199 for (b = n % 8; b > 0; b--)
1200 {
1201 if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
1202 {
1203 if (IS_HIGHBIT_SET(lb))
1204 return 1;
1205 return -1;
1206 }
1207 lb <<= 1;
1208 rb <<= 1;
1209 }
1210 return 0;
1211}
1212
1213/*
1214 * bitncommon: compare bit masks l and r, for up to n bits.
1215 *
1216 * Returns the number of leading bits that match (0 to n).
1217 */
1218int
1219bitncommon(const unsigned char *l, const unsigned char *r, int n)
1220{
1221 int byte,
1222 nbits;
1223
1224 /* number of bits to examine in last byte */
1225 nbits = n % 8;
1226
1227 /* check whole bytes */
1228 for (byte = 0; byte < n / 8; byte++)
1229 {
1230 if (l[byte] != r[byte])
1231 {
1232 /* at least one bit in the last byte is not common */
1233 nbits = 7;
1234 break;
1235 }
1236 }
1237
1238 /* check bits in last partial byte */
1239 if (nbits != 0)
1240 {
1241 /* calculate diff of first non-matching bytes */
1242 unsigned int diff = l[byte] ^ r[byte];
1243
1244 /* compare the bits from the most to the least */
1245 while ((diff >> (8 - nbits)) != 0)
1246 nbits--;
1247 }
1248
1249 return (8 * byte) + nbits;
1250}
1251
1252
1253/*
1254 * Verify a CIDR address is OK (doesn't have bits set past the masklen)
1255 */
1256static bool
1257addressOK(unsigned char *a, int bits, int family)
1258{
1259 int byte;
1260 int nbits;
1261 int maxbits;
1262 int maxbytes;
1263 unsigned char mask;
1264
1265 if (family == PGSQL_AF_INET)
1266 {
1267 maxbits = 32;
1268 maxbytes = 4;
1269 }
1270 else
1271 {
1272 maxbits = 128;
1273 maxbytes = 16;
1274 }
1275 Assert(bits <= maxbits);
1276
1277 if (bits == maxbits)
1278 return true;
1279
1280 byte = bits / 8;
1281
1282 nbits = bits % 8;
1283 mask = 0xff;
1284 if (bits != 0)
1285 mask >>= nbits;
1286
1287 while (byte < maxbytes)
1288 {
1289 if ((a[byte] & mask) != 0)
1290 return false;
1291 mask = 0xff;
1292 byte++;
1293 }
1294
1295 return true;
1296}
1297
1298
1299/*
1300 * These functions are used by planner to generate indexscan limits
1301 * for clauses a << b and a <<= b
1302 */
1303
1304/* return the minimal value for an IP on a given network */
1305Datum
1306network_scan_first(Datum in)
1307{
1308 return DirectFunctionCall1(network_network, in);
1309}
1310
1311/*
1312 * return "last" IP on a given network. It's the broadcast address,
1313 * however, masklen has to be set to its max bits, since
1314 * 192.168.0.255/24 is considered less than 192.168.0.255/32
1315 *
1316 * inet_set_masklen() hacked to max out the masklength to 128 for IPv6
1317 * and 32 for IPv4 when given '-1' as argument.
1318 */
1319Datum
1320network_scan_last(Datum in)
1321{
1322 return DirectFunctionCall2(inet_set_masklen,
1323 DirectFunctionCall1(network_broadcast, in),
1324 Int32GetDatum(-1));
1325}
1326
1327
1328/*
1329 * IP address that the client is connecting from (NULL if Unix socket)
1330 */
1331Datum
1332inet_client_addr(PG_FUNCTION_ARGS)
1333{
1334 Port *port = MyProcPort;
1335 char remote_host[NI_MAXHOST];
1336 int ret;
1337
1338 if (port == NULL)
1339 PG_RETURN_NULL();
1340
1341 switch (port->raddr.addr.ss_family)
1342 {
1343 case AF_INET:
1344#ifdef HAVE_IPV6
1345 case AF_INET6:
1346#endif
1347 break;
1348 default:
1349 PG_RETURN_NULL();
1350 }
1351
1352 remote_host[0] = '\0';
1353
1354 ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
1355 remote_host, sizeof(remote_host),
1356 NULL, 0,
1357 NI_NUMERICHOST | NI_NUMERICSERV);
1358 if (ret != 0)
1359 PG_RETURN_NULL();
1360
1361 clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
1362
1363 PG_RETURN_INET_P(network_in(remote_host, false));
1364}
1365
1366
1367/*
1368 * port that the client is connecting from (NULL if Unix socket)
1369 */
1370Datum
1371inet_client_port(PG_FUNCTION_ARGS)
1372{
1373 Port *port = MyProcPort;
1374 char remote_port[NI_MAXSERV];
1375 int ret;
1376
1377 if (port == NULL)
1378 PG_RETURN_NULL();
1379
1380 switch (port->raddr.addr.ss_family)
1381 {
1382 case AF_INET:
1383#ifdef HAVE_IPV6
1384 case AF_INET6:
1385#endif
1386 break;
1387 default:
1388 PG_RETURN_NULL();
1389 }
1390
1391 remote_port[0] = '\0';
1392
1393 ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
1394 NULL, 0,
1395 remote_port, sizeof(remote_port),
1396 NI_NUMERICHOST | NI_NUMERICSERV);
1397 if (ret != 0)
1398 PG_RETURN_NULL();
1399
1400 PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
1401}
1402
1403
1404/*
1405 * IP address that the server accepted the connection on (NULL if Unix socket)
1406 */
1407Datum
1408inet_server_addr(PG_FUNCTION_ARGS)
1409{
1410 Port *port = MyProcPort;
1411 char local_host[NI_MAXHOST];
1412 int ret;
1413
1414 if (port == NULL)
1415 PG_RETURN_NULL();
1416
1417 switch (port->laddr.addr.ss_family)
1418 {
1419 case AF_INET:
1420#ifdef HAVE_IPV6
1421 case AF_INET6:
1422#endif
1423 break;
1424 default:
1425 PG_RETURN_NULL();
1426 }
1427
1428 local_host[0] = '\0';
1429
1430 ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
1431 local_host, sizeof(local_host),
1432 NULL, 0,
1433 NI_NUMERICHOST | NI_NUMERICSERV);
1434 if (ret != 0)
1435 PG_RETURN_NULL();
1436
1437 clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
1438
1439 PG_RETURN_INET_P(network_in(local_host, false));
1440}
1441
1442
1443/*
1444 * port that the server accepted the connection on (NULL if Unix socket)
1445 */
1446Datum
1447inet_server_port(PG_FUNCTION_ARGS)
1448{
1449 Port *port = MyProcPort;
1450 char local_port[NI_MAXSERV];
1451 int ret;
1452
1453 if (port == NULL)
1454 PG_RETURN_NULL();
1455
1456 switch (port->laddr.addr.ss_family)
1457 {
1458 case AF_INET:
1459#ifdef HAVE_IPV6
1460 case AF_INET6:
1461#endif
1462 break;
1463 default:
1464 PG_RETURN_NULL();
1465 }
1466
1467 local_port[0] = '\0';
1468
1469 ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
1470 NULL, 0,
1471 local_port, sizeof(local_port),
1472 NI_NUMERICHOST | NI_NUMERICSERV);
1473 if (ret != 0)
1474 PG_RETURN_NULL();
1475
1476 PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
1477}
1478
1479
1480Datum
1481inetnot(PG_FUNCTION_ARGS)
1482{
1483 inet *ip = PG_GETARG_INET_PP(0);
1484 inet *dst;
1485
1486 dst = (inet *) palloc0(sizeof(inet));
1487
1488 {
1489 int nb = ip_addrsize(ip);
1490 unsigned char *pip = ip_addr(ip);
1491 unsigned char *pdst = ip_addr(dst);
1492
1493 while (nb-- > 0)
1494 pdst[nb] = ~pip[nb];
1495 }
1496 ip_bits(dst) = ip_bits(ip);
1497
1498 ip_family(dst) = ip_family(ip);
1499 SET_INET_VARSIZE(dst);
1500
1501 PG_RETURN_INET_P(dst);
1502}
1503
1504
1505Datum
1506inetand(PG_FUNCTION_ARGS)
1507{
1508 inet *ip = PG_GETARG_INET_PP(0);
1509 inet *ip2 = PG_GETARG_INET_PP(1);
1510 inet *dst;
1511
1512 dst = (inet *) palloc0(sizeof(inet));
1513
1514 if (ip_family(ip) != ip_family(ip2))
1515 ereport(ERROR,
1516 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1517 errmsg("cannot AND inet values of different sizes")));
1518 else
1519 {
1520 int nb = ip_addrsize(ip);
1521 unsigned char *pip = ip_addr(ip);
1522 unsigned char *pip2 = ip_addr(ip2);
1523 unsigned char *pdst = ip_addr(dst);
1524
1525 while (nb-- > 0)
1526 pdst[nb] = pip[nb] & pip2[nb];
1527 }
1528 ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
1529
1530 ip_family(dst) = ip_family(ip);
1531 SET_INET_VARSIZE(dst);
1532
1533 PG_RETURN_INET_P(dst);
1534}
1535
1536
1537Datum
1538inetor(PG_FUNCTION_ARGS)
1539{
1540 inet *ip = PG_GETARG_INET_PP(0);
1541 inet *ip2 = PG_GETARG_INET_PP(1);
1542 inet *dst;
1543
1544 dst = (inet *) palloc0(sizeof(inet));
1545
1546 if (ip_family(ip) != ip_family(ip2))
1547 ereport(ERROR,
1548 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1549 errmsg("cannot OR inet values of different sizes")));
1550 else
1551 {
1552 int nb = ip_addrsize(ip);
1553 unsigned char *pip = ip_addr(ip);
1554 unsigned char *pip2 = ip_addr(ip2);
1555 unsigned char *pdst = ip_addr(dst);
1556
1557 while (nb-- > 0)
1558 pdst[nb] = pip[nb] | pip2[nb];
1559 }
1560 ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
1561
1562 ip_family(dst) = ip_family(ip);
1563 SET_INET_VARSIZE(dst);
1564
1565 PG_RETURN_INET_P(dst);
1566}
1567
1568
1569static inet *
1570internal_inetpl(inet *ip, int64 addend)
1571{
1572 inet *dst;
1573
1574 dst = (inet *) palloc0(sizeof(inet));
1575
1576 {
1577 int nb = ip_addrsize(ip);
1578 unsigned char *pip = ip_addr(ip);
1579 unsigned char *pdst = ip_addr(dst);
1580 int carry = 0;
1581
1582 while (nb-- > 0)
1583 {
1584 carry = pip[nb] + (int) (addend & 0xFF) + carry;
1585 pdst[nb] = (unsigned char) (carry & 0xFF);
1586 carry >>= 8;
1587
1588 /*
1589 * We have to be careful about right-shifting addend because
1590 * right-shift isn't portable for negative values, while simply
1591 * dividing by 256 doesn't work (the standard rounding is in the
1592 * wrong direction, besides which there may be machines out there
1593 * that round the wrong way). So, explicitly clear the low-order
1594 * byte to remove any doubt about the correct result of the
1595 * division, and then divide rather than shift.
1596 */
1597 addend &= ~((int64) 0xFF);
1598 addend /= 0x100;
1599 }
1600
1601 /*
1602 * At this point we should have addend and carry both zero if original
1603 * addend was >= 0, or addend -1 and carry 1 if original addend was <
1604 * 0. Anything else means overflow.
1605 */
1606 if (!((addend == 0 && carry == 0) ||
1607 (addend == -1 && carry == 1)))
1608 ereport(ERROR,
1609 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1610 errmsg("result is out of range")));
1611 }
1612
1613 ip_bits(dst) = ip_bits(ip);
1614 ip_family(dst) = ip_family(ip);
1615 SET_INET_VARSIZE(dst);
1616
1617 return dst;
1618}
1619
1620
1621Datum
1622inetpl(PG_FUNCTION_ARGS)
1623{
1624 inet *ip = PG_GETARG_INET_PP(0);
1625 int64 addend = PG_GETARG_INT64(1);
1626
1627 PG_RETURN_INET_P(internal_inetpl(ip, addend));
1628}
1629
1630
1631Datum
1632inetmi_int8(PG_FUNCTION_ARGS)
1633{
1634 inet *ip = PG_GETARG_INET_PP(0);
1635 int64 addend = PG_GETARG_INT64(1);
1636
1637 PG_RETURN_INET_P(internal_inetpl(ip, -addend));
1638}
1639
1640
1641Datum
1642inetmi(PG_FUNCTION_ARGS)
1643{
1644 inet *ip = PG_GETARG_INET_PP(0);
1645 inet *ip2 = PG_GETARG_INET_PP(1);
1646 int64 res = 0;
1647
1648 if (ip_family(ip) != ip_family(ip2))
1649 ereport(ERROR,
1650 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1651 errmsg("cannot subtract inet values of different sizes")));
1652 else
1653 {
1654 /*
1655 * We form the difference using the traditional complement, increment,
1656 * and add rule, with the increment part being handled by starting the
1657 * carry off at 1. If you don't think integer arithmetic is done in
1658 * two's complement, too bad.
1659 */
1660 int nb = ip_addrsize(ip);
1661 int byte = 0;
1662 unsigned char *pip = ip_addr(ip);
1663 unsigned char *pip2 = ip_addr(ip2);
1664 int carry = 1;
1665
1666 while (nb-- > 0)
1667 {
1668 int lobyte;
1669
1670 carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
1671 lobyte = carry & 0xFF;
1672 if (byte < sizeof(int64))
1673 {
1674 res |= ((int64) lobyte) << (byte * 8);
1675 }
1676 else
1677 {
1678 /*
1679 * Input wider than int64: check for overflow. All bytes to
1680 * the left of what will fit should be 0 or 0xFF, depending on
1681 * sign of the now-complete result.
1682 */
1683 if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
1684 ereport(ERROR,
1685 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1686 errmsg("result is out of range")));
1687 }
1688 carry >>= 8;
1689 byte++;
1690 }
1691
1692 /*
1693 * If input is narrower than int64, overflow is not possible, but we
1694 * have to do proper sign extension.
1695 */
1696 if (carry == 0 && byte < sizeof(int64))
1697 res |= ((uint64) (int64) -1) << (byte * 8);
1698 }
1699
1700 PG_RETURN_INT64(res);
1701}
1702
1703
1704/*
1705 * clean_ipv6_addr --- remove any '%zone' part from an IPv6 address string
1706 *
1707 * XXX This should go away someday!
1708 *
1709 * This is a kluge needed because we don't yet support zones in stored inet
1710 * values. Since the result of getnameinfo() might include a zone spec,
1711 * call this to remove it anywhere we want to feed getnameinfo's output to
1712 * network_in. Beats failing entirely.
1713 *
1714 * An alternative approach would be to let network_in ignore %-parts for
1715 * itself, but that would mean we'd silently drop zone specs in user input,
1716 * which seems not such a good idea.
1717 */
1718void
1719clean_ipv6_addr(int addr_family, char *addr)
1720{
1721#ifdef HAVE_IPV6
1722 if (addr_family == AF_INET6)
1723 {
1724 char *pct = strchr(addr, '%');
1725
1726 if (pct)
1727 *pct = '\0';
1728 }
1729#endif
1730}
1731