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