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 "libpq/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 inet *dst;
272 int bits;
273 int byte;
274 int nbits;
275 int maxbytes;
276
277 bits = ip_bits(src);
278
279 /* safety check */
280 if ((bits < 0) || (bits > ip_maxbits(src)))
281 elog(ERROR, "invalid inet bit length: %d", bits);
282
283 /* clone the original data */
284 dst = (inet *) palloc(VARSIZE_ANY(src));
285 memcpy(dst, src, VARSIZE_ANY(src));
286
287 /* zero out any bits to the right of the netmask */
288 byte = bits / 8;
289
290 nbits = bits % 8;
291 /* clear the first byte, this might be a partial byte */
292 if (nbits != 0)
293 {
294 ip_addr(dst)[byte] &= ~(0xFF >> nbits);
295 byte++;
296 }
297 /* clear remaining bytes */
298 maxbytes = ip_addrsize(dst);
299 while (byte < maxbytes)
300 {
301 ip_addr(dst)[byte] = 0;
302 byte++;
303 }
304
305 PG_RETURN_INET_P(dst);
306 }
307
308 Datum
inet_set_masklen(PG_FUNCTION_ARGS)309 inet_set_masklen(PG_FUNCTION_ARGS)
310 {
311 inet *src = PG_GETARG_INET_PP(0);
312 int bits = PG_GETARG_INT32(1);
313 inet *dst;
314
315 if (bits == -1)
316 bits = ip_maxbits(src);
317
318 if ((bits < 0) || (bits > ip_maxbits(src)))
319 ereport(ERROR,
320 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
321 errmsg("invalid mask length: %d", bits)));
322
323 /* clone the original data */
324 dst = (inet *) palloc(VARSIZE_ANY(src));
325 memcpy(dst, src, VARSIZE_ANY(src));
326
327 ip_bits(dst) = bits;
328
329 PG_RETURN_INET_P(dst);
330 }
331
332 Datum
cidr_set_masklen(PG_FUNCTION_ARGS)333 cidr_set_masklen(PG_FUNCTION_ARGS)
334 {
335 inet *src = PG_GETARG_INET_PP(0);
336 int bits = PG_GETARG_INT32(1);
337 inet *dst;
338 int byte;
339 int nbits;
340 int maxbytes;
341
342 if (bits == -1)
343 bits = ip_maxbits(src);
344
345 if ((bits < 0) || (bits > ip_maxbits(src)))
346 ereport(ERROR,
347 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
348 errmsg("invalid mask length: %d", bits)));
349
350 /* clone the original data */
351 dst = (inet *) palloc(VARSIZE_ANY(src));
352 memcpy(dst, src, VARSIZE_ANY(src));
353
354 ip_bits(dst) = bits;
355
356 /* zero out any bits to the right of the new netmask */
357 byte = bits / 8;
358
359 nbits = bits % 8;
360 /* clear the first byte, this might be a partial byte */
361 if (nbits != 0)
362 {
363 ip_addr(dst)[byte] &= ~(0xFF >> nbits);
364 byte++;
365 }
366 /* clear remaining bytes */
367 maxbytes = ip_addrsize(dst);
368 while (byte < maxbytes)
369 {
370 ip_addr(dst)[byte] = 0;
371 byte++;
372 }
373
374 PG_RETURN_INET_P(dst);
375 }
376
377 /*
378 * Basic comparison function for sorting and inet/cidr comparisons.
379 *
380 * Comparison is first on the common bits of the network part, then on
381 * the length of the network part, and then on the whole unmasked address.
382 * The effect is that the network part is the major sort key, and for
383 * equal network parts we sort on the host part. Note this is only sane
384 * for CIDR if address bits to the right of the mask are guaranteed zero;
385 * otherwise logically-equal CIDRs might compare different.
386 */
387
388 static int32
network_cmp_internal(inet * a1,inet * a2)389 network_cmp_internal(inet *a1, inet *a2)
390 {
391 if (ip_family(a1) == ip_family(a2))
392 {
393 int order;
394
395 order = bitncmp(ip_addr(a1), ip_addr(a2),
396 Min(ip_bits(a1), ip_bits(a2)));
397 if (order != 0)
398 return order;
399 order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
400 if (order != 0)
401 return order;
402 return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
403 }
404
405 return ip_family(a1) - ip_family(a2);
406 }
407
408 Datum
network_cmp(PG_FUNCTION_ARGS)409 network_cmp(PG_FUNCTION_ARGS)
410 {
411 inet *a1 = PG_GETARG_INET_PP(0);
412 inet *a2 = PG_GETARG_INET_PP(1);
413
414 PG_RETURN_INT32(network_cmp_internal(a1, a2));
415 }
416
417 /*
418 * Boolean ordering tests.
419 */
420 Datum
network_lt(PG_FUNCTION_ARGS)421 network_lt(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
429 Datum
network_le(PG_FUNCTION_ARGS)430 network_le(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
438 Datum
network_eq(PG_FUNCTION_ARGS)439 network_eq(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
447 Datum
network_ge(PG_FUNCTION_ARGS)448 network_ge(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
456 Datum
network_gt(PG_FUNCTION_ARGS)457 network_gt(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 Datum
network_ne(PG_FUNCTION_ARGS)466 network_ne(PG_FUNCTION_ARGS)
467 {
468 inet *a1 = PG_GETARG_INET_PP(0);
469 inet *a2 = PG_GETARG_INET_PP(1);
470
471 PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
472 }
473
474 /*
475 * MIN/MAX support functions.
476 */
477 Datum
network_smaller(PG_FUNCTION_ARGS)478 network_smaller(PG_FUNCTION_ARGS)
479 {
480 inet *a1 = PG_GETARG_INET_PP(0);
481 inet *a2 = PG_GETARG_INET_PP(1);
482
483 if (network_cmp_internal(a1, a2) < 0)
484 PG_RETURN_INET_P(a1);
485 else
486 PG_RETURN_INET_P(a2);
487 }
488
489 Datum
network_larger(PG_FUNCTION_ARGS)490 network_larger(PG_FUNCTION_ARGS)
491 {
492 inet *a1 = PG_GETARG_INET_PP(0);
493 inet *a2 = PG_GETARG_INET_PP(1);
494
495 if (network_cmp_internal(a1, a2) > 0)
496 PG_RETURN_INET_P(a1);
497 else
498 PG_RETURN_INET_P(a2);
499 }
500
501 /*
502 * Support function for hash indexes on inet/cidr.
503 */
504 Datum
hashinet(PG_FUNCTION_ARGS)505 hashinet(PG_FUNCTION_ARGS)
506 {
507 inet *addr = PG_GETARG_INET_PP(0);
508 int addrsize = ip_addrsize(addr);
509
510 /* XXX this assumes there are no pad bytes in the data structure */
511 return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
512 }
513
514 /*
515 * Boolean network-inclusion tests.
516 */
517 Datum
network_sub(PG_FUNCTION_ARGS)518 network_sub(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_subeq(PG_FUNCTION_ARGS)533 network_subeq(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(a2)) == 0);
542 }
543
544 PG_RETURN_BOOL(false);
545 }
546
547 Datum
network_sup(PG_FUNCTION_ARGS)548 network_sup(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_supeq(PG_FUNCTION_ARGS)563 network_supeq(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(ip_bits(a1) <= ip_bits(a2) &&
571 bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
572 }
573
574 PG_RETURN_BOOL(false);
575 }
576
577 Datum
network_overlap(PG_FUNCTION_ARGS)578 network_overlap(PG_FUNCTION_ARGS)
579 {
580 inet *a1 = PG_GETARG_INET_PP(0);
581 inet *a2 = PG_GETARG_INET_PP(1);
582
583 if (ip_family(a1) == ip_family(a2))
584 {
585 PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
586 Min(ip_bits(a1), ip_bits(a2))) == 0);
587 }
588
589 PG_RETURN_BOOL(false);
590 }
591
592 /*
593 * Extract data from a network datatype.
594 */
595 Datum
network_host(PG_FUNCTION_ARGS)596 network_host(PG_FUNCTION_ARGS)
597 {
598 inet *ip = PG_GETARG_INET_PP(0);
599 char *ptr;
600 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
601
602 /* force display of max bits, regardless of masklen... */
603 if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
604 tmp, sizeof(tmp)) == NULL)
605 ereport(ERROR,
606 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
607 errmsg("could not format inet value: %m")));
608
609 /* Suppress /n if present (shouldn't happen now) */
610 if ((ptr = strchr(tmp, '/')) != NULL)
611 *ptr = '\0';
612
613 PG_RETURN_TEXT_P(cstring_to_text(tmp));
614 }
615
616 /*
617 * network_show implements the inet and cidr casts to text. This is not
618 * quite the same behavior as network_out, hence we can't drop it in favor
619 * of CoerceViaIO.
620 */
621 Datum
network_show(PG_FUNCTION_ARGS)622 network_show(PG_FUNCTION_ARGS)
623 {
624 inet *ip = PG_GETARG_INET_PP(0);
625 int len;
626 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
627
628 if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
629 tmp, sizeof(tmp)) == NULL)
630 ereport(ERROR,
631 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
632 errmsg("could not format inet value: %m")));
633
634 /* Add /n if not present (which it won't be) */
635 if (strchr(tmp, '/') == NULL)
636 {
637 len = strlen(tmp);
638 snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
639 }
640
641 PG_RETURN_TEXT_P(cstring_to_text(tmp));
642 }
643
644 Datum
inet_abbrev(PG_FUNCTION_ARGS)645 inet_abbrev(PG_FUNCTION_ARGS)
646 {
647 inet *ip = PG_GETARG_INET_PP(0);
648 char *dst;
649 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
650
651 dst = inet_net_ntop(ip_family(ip), ip_addr(ip),
652 ip_bits(ip), tmp, sizeof(tmp));
653
654 if (dst == NULL)
655 ereport(ERROR,
656 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
657 errmsg("could not format inet value: %m")));
658
659 PG_RETURN_TEXT_P(cstring_to_text(tmp));
660 }
661
662 Datum
cidr_abbrev(PG_FUNCTION_ARGS)663 cidr_abbrev(PG_FUNCTION_ARGS)
664 {
665 inet *ip = PG_GETARG_INET_PP(0);
666 char *dst;
667 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
668
669 dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip),
670 ip_bits(ip), tmp, sizeof(tmp));
671
672 if (dst == NULL)
673 ereport(ERROR,
674 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
675 errmsg("could not format cidr value: %m")));
676
677 PG_RETURN_TEXT_P(cstring_to_text(tmp));
678 }
679
680 Datum
network_masklen(PG_FUNCTION_ARGS)681 network_masklen(PG_FUNCTION_ARGS)
682 {
683 inet *ip = PG_GETARG_INET_PP(0);
684
685 PG_RETURN_INT32(ip_bits(ip));
686 }
687
688 Datum
network_family(PG_FUNCTION_ARGS)689 network_family(PG_FUNCTION_ARGS)
690 {
691 inet *ip = PG_GETARG_INET_PP(0);
692
693 switch (ip_family(ip))
694 {
695 case PGSQL_AF_INET:
696 PG_RETURN_INT32(4);
697 break;
698 case PGSQL_AF_INET6:
699 PG_RETURN_INT32(6);
700 break;
701 default:
702 PG_RETURN_INT32(0);
703 break;
704 }
705 }
706
707 Datum
network_broadcast(PG_FUNCTION_ARGS)708 network_broadcast(PG_FUNCTION_ARGS)
709 {
710 inet *ip = PG_GETARG_INET_PP(0);
711 inet *dst;
712 int byte;
713 int bits;
714 int maxbytes;
715 unsigned char mask;
716 unsigned char *a,
717 *b;
718
719 /* make sure any unused bits are zeroed */
720 dst = (inet *) palloc0(sizeof(inet));
721
722 if (ip_family(ip) == PGSQL_AF_INET)
723 maxbytes = 4;
724 else
725 maxbytes = 16;
726
727 bits = ip_bits(ip);
728 a = ip_addr(ip);
729 b = ip_addr(dst);
730
731 for (byte = 0; byte < maxbytes; byte++)
732 {
733 if (bits >= 8)
734 {
735 mask = 0x00;
736 bits -= 8;
737 }
738 else if (bits == 0)
739 mask = 0xff;
740 else
741 {
742 mask = 0xff >> bits;
743 bits = 0;
744 }
745
746 b[byte] = a[byte] | mask;
747 }
748
749 ip_family(dst) = ip_family(ip);
750 ip_bits(dst) = ip_bits(ip);
751 SET_INET_VARSIZE(dst);
752
753 PG_RETURN_INET_P(dst);
754 }
755
756 Datum
network_network(PG_FUNCTION_ARGS)757 network_network(PG_FUNCTION_ARGS)
758 {
759 inet *ip = PG_GETARG_INET_PP(0);
760 inet *dst;
761 int byte;
762 int bits;
763 unsigned char mask;
764 unsigned char *a,
765 *b;
766
767 /* make sure any unused bits are zeroed */
768 dst = (inet *) palloc0(sizeof(inet));
769
770 bits = ip_bits(ip);
771 a = ip_addr(ip);
772 b = ip_addr(dst);
773
774 byte = 0;
775
776 while (bits)
777 {
778 if (bits >= 8)
779 {
780 mask = 0xff;
781 bits -= 8;
782 }
783 else
784 {
785 mask = 0xff << (8 - bits);
786 bits = 0;
787 }
788
789 b[byte] = a[byte] & mask;
790 byte++;
791 }
792
793 ip_family(dst) = ip_family(ip);
794 ip_bits(dst) = ip_bits(ip);
795 SET_INET_VARSIZE(dst);
796
797 PG_RETURN_INET_P(dst);
798 }
799
800 Datum
network_netmask(PG_FUNCTION_ARGS)801 network_netmask(PG_FUNCTION_ARGS)
802 {
803 inet *ip = PG_GETARG_INET_PP(0);
804 inet *dst;
805 int byte;
806 int bits;
807 unsigned char mask;
808 unsigned char *b;
809
810 /* make sure any unused bits are zeroed */
811 dst = (inet *) palloc0(sizeof(inet));
812
813 bits = ip_bits(ip);
814 b = ip_addr(dst);
815
816 byte = 0;
817
818 while (bits)
819 {
820 if (bits >= 8)
821 {
822 mask = 0xff;
823 bits -= 8;
824 }
825 else
826 {
827 mask = 0xff << (8 - bits);
828 bits = 0;
829 }
830
831 b[byte] = mask;
832 byte++;
833 }
834
835 ip_family(dst) = ip_family(ip);
836 ip_bits(dst) = ip_maxbits(ip);
837 SET_INET_VARSIZE(dst);
838
839 PG_RETURN_INET_P(dst);
840 }
841
842 Datum
network_hostmask(PG_FUNCTION_ARGS)843 network_hostmask(PG_FUNCTION_ARGS)
844 {
845 inet *ip = PG_GETARG_INET_PP(0);
846 inet *dst;
847 int byte;
848 int bits;
849 int maxbytes;
850 unsigned char mask;
851 unsigned char *b;
852
853 /* make sure any unused bits are zeroed */
854 dst = (inet *) palloc0(sizeof(inet));
855
856 if (ip_family(ip) == PGSQL_AF_INET)
857 maxbytes = 4;
858 else
859 maxbytes = 16;
860
861 bits = ip_maxbits(ip) - ip_bits(ip);
862 b = ip_addr(dst);
863
864 byte = maxbytes - 1;
865
866 while (bits)
867 {
868 if (bits >= 8)
869 {
870 mask = 0xff;
871 bits -= 8;
872 }
873 else
874 {
875 mask = 0xff >> (8 - bits);
876 bits = 0;
877 }
878
879 b[byte] = mask;
880 byte--;
881 }
882
883 ip_family(dst) = ip_family(ip);
884 ip_bits(dst) = ip_maxbits(ip);
885 SET_INET_VARSIZE(dst);
886
887 PG_RETURN_INET_P(dst);
888 }
889
890 /*
891 * Returns true if the addresses are from the same family, or false. Used to
892 * check that we can create a network which contains both of the networks.
893 */
894 Datum
inet_same_family(PG_FUNCTION_ARGS)895 inet_same_family(PG_FUNCTION_ARGS)
896 {
897 inet *a1 = PG_GETARG_INET_PP(0);
898 inet *a2 = PG_GETARG_INET_PP(1);
899
900 PG_RETURN_BOOL(ip_family(a1) == ip_family(a2));
901 }
902
903 /*
904 * Returns the smallest CIDR which contains both of the inputs.
905 */
906 Datum
inet_merge(PG_FUNCTION_ARGS)907 inet_merge(PG_FUNCTION_ARGS)
908 {
909 inet *a1 = PG_GETARG_INET_PP(0),
910 *a2 = PG_GETARG_INET_PP(1),
911 *result;
912 int commonbits;
913
914 if (ip_family(a1) != ip_family(a2))
915 ereport(ERROR,
916 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
917 errmsg("cannot merge addresses from different families")));
918
919 commonbits = bitncommon(ip_addr(a1), ip_addr(a2),
920 Min(ip_bits(a1), ip_bits(a2)));
921
922 /* Make sure any unused bits are zeroed. */
923 result = (inet *) palloc0(sizeof(inet));
924
925 ip_family(result) = ip_family(a1);
926 ip_bits(result) = commonbits;
927
928 /* Clone appropriate bytes of the address. */
929 if (commonbits > 0)
930 memcpy(ip_addr(result), ip_addr(a1), (commonbits + 7) / 8);
931
932 /* Clean any unwanted bits in the last partial byte. */
933 if (commonbits % 8 != 0)
934 ip_addr(result)[commonbits / 8] &= ~(0xFF >> (commonbits % 8));
935
936 /* Set varlena header correctly. */
937 SET_INET_VARSIZE(result);
938
939 PG_RETURN_INET_P(result);
940 }
941
942 /*
943 * Convert a value of a network datatype to an approximate scalar value.
944 * This is used for estimating selectivities of inequality operators
945 * involving network types.
946 *
947 * On failure (e.g., unsupported typid), set *failure to true;
948 * otherwise, that variable is not changed.
949 */
950 double
convert_network_to_scalar(Datum value,Oid typid,bool * failure)951 convert_network_to_scalar(Datum value, Oid typid, bool *failure)
952 {
953 switch (typid)
954 {
955 case INETOID:
956 case CIDROID:
957 {
958 inet *ip = DatumGetInetPP(value);
959 int len;
960 double res;
961 int i;
962
963 /*
964 * Note that we don't use the full address for IPv6.
965 */
966 if (ip_family(ip) == PGSQL_AF_INET)
967 len = 4;
968 else
969 len = 5;
970
971 res = ip_family(ip);
972 for (i = 0; i < len; i++)
973 {
974 res *= 256;
975 res += ip_addr(ip)[i];
976 }
977 return res;
978 }
979 case MACADDROID:
980 {
981 macaddr *mac = DatumGetMacaddrP(value);
982 double res;
983
984 res = (mac->a << 16) | (mac->b << 8) | (mac->c);
985 res *= 256 * 256 * 256;
986 res += (mac->d << 16) | (mac->e << 8) | (mac->f);
987 return res;
988 }
989 }
990
991 *failure = true;
992 return 0;
993 }
994
995 /*
996 * int
997 * bitncmp(l, r, n)
998 * compare bit masks l and r, for n bits.
999 * return:
1000 * <0, >0, or 0 in the libc tradition.
1001 * note:
1002 * network byte order assumed. this means 192.5.5.240/28 has
1003 * 0x11110000 in its fourth octet.
1004 * author:
1005 * Paul Vixie (ISC), June 1996
1006 */
1007 int
bitncmp(const unsigned char * l,const unsigned char * r,int n)1008 bitncmp(const unsigned char *l, const unsigned char *r, int n)
1009 {
1010 unsigned int lb,
1011 rb;
1012 int x,
1013 b;
1014
1015 b = n / 8;
1016 x = memcmp(l, r, b);
1017 if (x || (n % 8) == 0)
1018 return x;
1019
1020 lb = l[b];
1021 rb = r[b];
1022 for (b = n % 8; b > 0; b--)
1023 {
1024 if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
1025 {
1026 if (IS_HIGHBIT_SET(lb))
1027 return 1;
1028 return -1;
1029 }
1030 lb <<= 1;
1031 rb <<= 1;
1032 }
1033 return 0;
1034 }
1035
1036 /*
1037 * bitncommon: compare bit masks l and r, for up to n bits.
1038 *
1039 * Returns the number of leading bits that match (0 to n).
1040 */
1041 int
bitncommon(const unsigned char * l,const unsigned char * r,int n)1042 bitncommon(const unsigned char *l, const unsigned char *r, int n)
1043 {
1044 int byte,
1045 nbits;
1046
1047 /* number of bits to examine in last byte */
1048 nbits = n % 8;
1049
1050 /* check whole bytes */
1051 for (byte = 0; byte < n / 8; byte++)
1052 {
1053 if (l[byte] != r[byte])
1054 {
1055 /* at least one bit in the last byte is not common */
1056 nbits = 7;
1057 break;
1058 }
1059 }
1060
1061 /* check bits in last partial byte */
1062 if (nbits != 0)
1063 {
1064 /* calculate diff of first non-matching bytes */
1065 unsigned int diff = l[byte] ^ r[byte];
1066
1067 /* compare the bits from the most to the least */
1068 while ((diff >> (8 - nbits)) != 0)
1069 nbits--;
1070 }
1071
1072 return (8 * byte) + nbits;
1073 }
1074
1075
1076 /*
1077 * Verify a CIDR address is OK (doesn't have bits set past the masklen)
1078 */
1079 static bool
addressOK(unsigned char * a,int bits,int family)1080 addressOK(unsigned char *a, int bits, int family)
1081 {
1082 int byte;
1083 int nbits;
1084 int maxbits;
1085 int maxbytes;
1086 unsigned char mask;
1087
1088 if (family == PGSQL_AF_INET)
1089 {
1090 maxbits = 32;
1091 maxbytes = 4;
1092 }
1093 else
1094 {
1095 maxbits = 128;
1096 maxbytes = 16;
1097 }
1098 Assert(bits <= maxbits);
1099
1100 if (bits == maxbits)
1101 return true;
1102
1103 byte = bits / 8;
1104
1105 nbits = bits % 8;
1106 mask = 0xff;
1107 if (bits != 0)
1108 mask >>= nbits;
1109
1110 while (byte < maxbytes)
1111 {
1112 if ((a[byte] & mask) != 0)
1113 return false;
1114 mask = 0xff;
1115 byte++;
1116 }
1117
1118 return true;
1119 }
1120
1121
1122 /*
1123 * These functions are used by planner to generate indexscan limits
1124 * for clauses a << b and a <<= b
1125 */
1126
1127 /* return the minimal value for an IP on a given network */
1128 Datum
network_scan_first(Datum in)1129 network_scan_first(Datum in)
1130 {
1131 return DirectFunctionCall1(network_network, in);
1132 }
1133
1134 /*
1135 * return "last" IP on a given network. It's the broadcast address,
1136 * however, masklen has to be set to its max btis, since
1137 * 192.168.0.255/24 is considered less than 192.168.0.255/32
1138 *
1139 * inet_set_masklen() hacked to max out the masklength to 128 for IPv6
1140 * and 32 for IPv4 when given '-1' as argument.
1141 */
1142 Datum
network_scan_last(Datum in)1143 network_scan_last(Datum in)
1144 {
1145 return DirectFunctionCall2(inet_set_masklen,
1146 DirectFunctionCall1(network_broadcast, in),
1147 Int32GetDatum(-1));
1148 }
1149
1150
1151 /*
1152 * IP address that the client is connecting from (NULL if Unix socket)
1153 */
1154 Datum
inet_client_addr(PG_FUNCTION_ARGS)1155 inet_client_addr(PG_FUNCTION_ARGS)
1156 {
1157 Port *port = MyProcPort;
1158 char remote_host[NI_MAXHOST];
1159 int ret;
1160
1161 if (port == NULL)
1162 PG_RETURN_NULL();
1163
1164 switch (port->raddr.addr.ss_family)
1165 {
1166 case AF_INET:
1167 #ifdef HAVE_IPV6
1168 case AF_INET6:
1169 #endif
1170 break;
1171 default:
1172 PG_RETURN_NULL();
1173 }
1174
1175 remote_host[0] = '\0';
1176
1177 ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
1178 remote_host, sizeof(remote_host),
1179 NULL, 0,
1180 NI_NUMERICHOST | NI_NUMERICSERV);
1181 if (ret != 0)
1182 PG_RETURN_NULL();
1183
1184 clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
1185
1186 PG_RETURN_INET_P(network_in(remote_host, false));
1187 }
1188
1189
1190 /*
1191 * port that the client is connecting from (NULL if Unix socket)
1192 */
1193 Datum
inet_client_port(PG_FUNCTION_ARGS)1194 inet_client_port(PG_FUNCTION_ARGS)
1195 {
1196 Port *port = MyProcPort;
1197 char remote_port[NI_MAXSERV];
1198 int ret;
1199
1200 if (port == NULL)
1201 PG_RETURN_NULL();
1202
1203 switch (port->raddr.addr.ss_family)
1204 {
1205 case AF_INET:
1206 #ifdef HAVE_IPV6
1207 case AF_INET6:
1208 #endif
1209 break;
1210 default:
1211 PG_RETURN_NULL();
1212 }
1213
1214 remote_port[0] = '\0';
1215
1216 ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
1217 NULL, 0,
1218 remote_port, sizeof(remote_port),
1219 NI_NUMERICHOST | NI_NUMERICSERV);
1220 if (ret != 0)
1221 PG_RETURN_NULL();
1222
1223 PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
1224 }
1225
1226
1227 /*
1228 * IP address that the server accepted the connection on (NULL if Unix socket)
1229 */
1230 Datum
inet_server_addr(PG_FUNCTION_ARGS)1231 inet_server_addr(PG_FUNCTION_ARGS)
1232 {
1233 Port *port = MyProcPort;
1234 char local_host[NI_MAXHOST];
1235 int ret;
1236
1237 if (port == NULL)
1238 PG_RETURN_NULL();
1239
1240 switch (port->laddr.addr.ss_family)
1241 {
1242 case AF_INET:
1243 #ifdef HAVE_IPV6
1244 case AF_INET6:
1245 #endif
1246 break;
1247 default:
1248 PG_RETURN_NULL();
1249 }
1250
1251 local_host[0] = '\0';
1252
1253 ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
1254 local_host, sizeof(local_host),
1255 NULL, 0,
1256 NI_NUMERICHOST | NI_NUMERICSERV);
1257 if (ret != 0)
1258 PG_RETURN_NULL();
1259
1260 clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
1261
1262 PG_RETURN_INET_P(network_in(local_host, false));
1263 }
1264
1265
1266 /*
1267 * port that the server accepted the connection on (NULL if Unix socket)
1268 */
1269 Datum
inet_server_port(PG_FUNCTION_ARGS)1270 inet_server_port(PG_FUNCTION_ARGS)
1271 {
1272 Port *port = MyProcPort;
1273 char local_port[NI_MAXSERV];
1274 int ret;
1275
1276 if (port == NULL)
1277 PG_RETURN_NULL();
1278
1279 switch (port->laddr.addr.ss_family)
1280 {
1281 case AF_INET:
1282 #ifdef HAVE_IPV6
1283 case AF_INET6:
1284 #endif
1285 break;
1286 default:
1287 PG_RETURN_NULL();
1288 }
1289
1290 local_port[0] = '\0';
1291
1292 ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
1293 NULL, 0,
1294 local_port, sizeof(local_port),
1295 NI_NUMERICHOST | NI_NUMERICSERV);
1296 if (ret != 0)
1297 PG_RETURN_NULL();
1298
1299 PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
1300 }
1301
1302
1303 Datum
inetnot(PG_FUNCTION_ARGS)1304 inetnot(PG_FUNCTION_ARGS)
1305 {
1306 inet *ip = PG_GETARG_INET_PP(0);
1307 inet *dst;
1308
1309 dst = (inet *) palloc0(sizeof(inet));
1310
1311 {
1312 int nb = ip_addrsize(ip);
1313 unsigned char *pip = ip_addr(ip);
1314 unsigned char *pdst = ip_addr(dst);
1315
1316 while (nb-- > 0)
1317 pdst[nb] = ~pip[nb];
1318 }
1319 ip_bits(dst) = ip_bits(ip);
1320
1321 ip_family(dst) = ip_family(ip);
1322 SET_INET_VARSIZE(dst);
1323
1324 PG_RETURN_INET_P(dst);
1325 }
1326
1327
1328 Datum
inetand(PG_FUNCTION_ARGS)1329 inetand(PG_FUNCTION_ARGS)
1330 {
1331 inet *ip = PG_GETARG_INET_PP(0);
1332 inet *ip2 = PG_GETARG_INET_PP(1);
1333 inet *dst;
1334
1335 dst = (inet *) palloc0(sizeof(inet));
1336
1337 if (ip_family(ip) != ip_family(ip2))
1338 ereport(ERROR,
1339 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1340 errmsg("cannot AND inet values of different sizes")));
1341 else
1342 {
1343 int nb = ip_addrsize(ip);
1344 unsigned char *pip = ip_addr(ip);
1345 unsigned char *pip2 = ip_addr(ip2);
1346 unsigned char *pdst = ip_addr(dst);
1347
1348 while (nb-- > 0)
1349 pdst[nb] = pip[nb] & pip2[nb];
1350 }
1351 ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
1352
1353 ip_family(dst) = ip_family(ip);
1354 SET_INET_VARSIZE(dst);
1355
1356 PG_RETURN_INET_P(dst);
1357 }
1358
1359
1360 Datum
inetor(PG_FUNCTION_ARGS)1361 inetor(PG_FUNCTION_ARGS)
1362 {
1363 inet *ip = PG_GETARG_INET_PP(0);
1364 inet *ip2 = PG_GETARG_INET_PP(1);
1365 inet *dst;
1366
1367 dst = (inet *) palloc0(sizeof(inet));
1368
1369 if (ip_family(ip) != ip_family(ip2))
1370 ereport(ERROR,
1371 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1372 errmsg("cannot OR inet values of different sizes")));
1373 else
1374 {
1375 int nb = ip_addrsize(ip);
1376 unsigned char *pip = ip_addr(ip);
1377 unsigned char *pip2 = ip_addr(ip2);
1378 unsigned char *pdst = ip_addr(dst);
1379
1380 while (nb-- > 0)
1381 pdst[nb] = pip[nb] | pip2[nb];
1382 }
1383 ip_bits(dst) = Max(ip_bits(ip), ip_bits(ip2));
1384
1385 ip_family(dst) = ip_family(ip);
1386 SET_INET_VARSIZE(dst);
1387
1388 PG_RETURN_INET_P(dst);
1389 }
1390
1391
1392 static inet *
internal_inetpl(inet * ip,int64 addend)1393 internal_inetpl(inet *ip, int64 addend)
1394 {
1395 inet *dst;
1396
1397 dst = (inet *) palloc0(sizeof(inet));
1398
1399 {
1400 int nb = ip_addrsize(ip);
1401 unsigned char *pip = ip_addr(ip);
1402 unsigned char *pdst = ip_addr(dst);
1403 int carry = 0;
1404
1405 while (nb-- > 0)
1406 {
1407 carry = pip[nb] + (int) (addend & 0xFF) + carry;
1408 pdst[nb] = (unsigned char) (carry & 0xFF);
1409 carry >>= 8;
1410
1411 /*
1412 * We have to be careful about right-shifting addend because
1413 * right-shift isn't portable for negative values, while simply
1414 * dividing by 256 doesn't work (the standard rounding is in the
1415 * wrong direction, besides which there may be machines out there
1416 * that round the wrong way). So, explicitly clear the low-order
1417 * byte to remove any doubt about the correct result of the
1418 * division, and then divide rather than shift.
1419 */
1420 addend &= ~((int64) 0xFF);
1421 addend /= 0x100;
1422 }
1423
1424 /*
1425 * At this point we should have addend and carry both zero if original
1426 * addend was >= 0, or addend -1 and carry 1 if original addend was <
1427 * 0. Anything else means overflow.
1428 */
1429 if (!((addend == 0 && carry == 0) ||
1430 (addend == -1 && carry == 1)))
1431 ereport(ERROR,
1432 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1433 errmsg("result is out of range")));
1434 }
1435
1436 ip_bits(dst) = ip_bits(ip);
1437 ip_family(dst) = ip_family(ip);
1438 SET_INET_VARSIZE(dst);
1439
1440 return dst;
1441 }
1442
1443
1444 Datum
inetpl(PG_FUNCTION_ARGS)1445 inetpl(PG_FUNCTION_ARGS)
1446 {
1447 inet *ip = PG_GETARG_INET_PP(0);
1448 int64 addend = PG_GETARG_INT64(1);
1449
1450 PG_RETURN_INET_P(internal_inetpl(ip, addend));
1451 }
1452
1453
1454 Datum
inetmi_int8(PG_FUNCTION_ARGS)1455 inetmi_int8(PG_FUNCTION_ARGS)
1456 {
1457 inet *ip = PG_GETARG_INET_PP(0);
1458 int64 addend = PG_GETARG_INT64(1);
1459
1460 PG_RETURN_INET_P(internal_inetpl(ip, -addend));
1461 }
1462
1463
1464 Datum
inetmi(PG_FUNCTION_ARGS)1465 inetmi(PG_FUNCTION_ARGS)
1466 {
1467 inet *ip = PG_GETARG_INET_PP(0);
1468 inet *ip2 = PG_GETARG_INET_PP(1);
1469 int64 res = 0;
1470
1471 if (ip_family(ip) != ip_family(ip2))
1472 ereport(ERROR,
1473 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1474 errmsg("cannot subtract inet values of different sizes")));
1475 else
1476 {
1477 /*
1478 * We form the difference using the traditional complement, increment,
1479 * and add rule, with the increment part being handled by starting the
1480 * carry off at 1. If you don't think integer arithmetic is done in
1481 * two's complement, too bad.
1482 */
1483 int nb = ip_addrsize(ip);
1484 int byte = 0;
1485 unsigned char *pip = ip_addr(ip);
1486 unsigned char *pip2 = ip_addr(ip2);
1487 int carry = 1;
1488
1489 while (nb-- > 0)
1490 {
1491 int lobyte;
1492
1493 carry = pip[nb] + (~pip2[nb] & 0xFF) + carry;
1494 lobyte = carry & 0xFF;
1495 if (byte < sizeof(int64))
1496 {
1497 res |= ((int64) lobyte) << (byte * 8);
1498 }
1499 else
1500 {
1501 /*
1502 * Input wider than int64: check for overflow. All bytes to
1503 * the left of what will fit should be 0 or 0xFF, depending on
1504 * sign of the now-complete result.
1505 */
1506 if ((res < 0) ? (lobyte != 0xFF) : (lobyte != 0))
1507 ereport(ERROR,
1508 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1509 errmsg("result is out of range")));
1510 }
1511 carry >>= 8;
1512 byte++;
1513 }
1514
1515 /*
1516 * If input is narrower than int64, overflow is not possible, but we
1517 * have to do proper sign extension.
1518 */
1519 if (carry == 0 && byte < sizeof(int64))
1520 res |= ((int64) -1) << (byte * 8);
1521 }
1522
1523 PG_RETURN_INT64(res);
1524 }
1525
1526
1527 /*
1528 * clean_ipv6_addr --- remove any '%zone' part from an IPv6 address string
1529 *
1530 * XXX This should go away someday!
1531 *
1532 * This is a kluge needed because we don't yet support zones in stored inet
1533 * values. Since the result of getnameinfo() might include a zone spec,
1534 * call this to remove it anywhere we want to feed getnameinfo's output to
1535 * network_in. Beats failing entirely.
1536 *
1537 * An alternative approach would be to let network_in ignore %-parts for
1538 * itself, but that would mean we'd silently drop zone specs in user input,
1539 * which seems not such a good idea.
1540 */
1541 void
clean_ipv6_addr(int addr_family,char * addr)1542 clean_ipv6_addr(int addr_family, char *addr)
1543 {
1544 #ifdef HAVE_IPV6
1545 if (addr_family == AF_INET6)
1546 {
1547 char *pct = strchr(addr, '%');
1548
1549 if (pct)
1550 *pct = '\0';
1551 }
1552 #endif
1553 }
1554