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