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