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