]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/network.c
Cosmetic code cleanup: fix a bunch of places that used "return (expr);"
[postgresql] / src / backend / utils / adt / network.c
1 /*
2  *      PostgreSQL type definitions for the INET and CIDR types.
3  *
4  *      $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.58 2006/01/11 08:43:12 neilc Exp $
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 Datum text_network(text *src, int type);
26 static int32 network_cmp_internal(inet *a1, inet *a2);
27 static int      bitncmp(void *l, void *r, int n);
28 static bool addressOK(unsigned char *a, int bits, int family);
29 static int      ip_addrsize(inet *inetptr);
30
31 /*
32  *      Access macros.
33  */
34
35 #define ip_family(inetptr) \
36         (((inet_struct *)VARDATA(inetptr))->family)
37
38 #define ip_bits(inetptr) \
39         (((inet_struct *)VARDATA(inetptr))->bits)
40
41 #define ip_type(inetptr) \
42         (((inet_struct *)VARDATA(inetptr))->type)
43
44 #define ip_addr(inetptr) \
45         (((inet_struct *)VARDATA(inetptr))->ipaddr)
46
47 #define ip_maxbits(inetptr) \
48         (ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)
49
50 /*
51  * Return the number of bytes of storage needed for this data type.
52  */
53 static int
54 ip_addrsize(inet *inetptr)
55 {
56         switch (ip_family(inetptr))
57         {
58                 case PGSQL_AF_INET:
59                         return 4;
60                 case PGSQL_AF_INET6:
61                         return 16;
62                 default:
63                         return 0;
64         }
65 }
66
67 /* Common input routine */
68 static inet *
69 network_in(char *src, int type)
70 {
71         int                     bits;
72         inet       *dst;
73
74         dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
75
76         /*
77          * First, check to see if this is an IPv6 or IPv4 address.      IPv6 addresses
78          * will have a : somewhere in them (several, in fact) so if there is one
79          * present, assume it's V6, otherwise assume it's V4.
80          */
81
82         if (strchr(src, ':') != NULL)
83                 ip_family(dst) = PGSQL_AF_INET6;
84         else
85                 ip_family(dst) = PGSQL_AF_INET;
86
87         bits = inet_net_pton(ip_family(dst), src, ip_addr(dst),
88                                                  type ? ip_addrsize(dst) : -1);
89         if ((bits < 0) || (bits > ip_maxbits(dst)))
90                 ereport(ERROR,
91                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
92                 /* translator: first %s is inet or cidr */
93                                  errmsg("invalid input syntax for type %s: \"%s\"",
94                                                 type ? "cidr" : "inet", src)));
95
96         /*
97          * Error check: CIDR values must not have any bits set beyond the masklen.
98          */
99         if (type)
100         {
101                 if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
102                         ereport(ERROR,
103                                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
104                                          errmsg("invalid cidr value: \"%s\"", src),
105                                          errdetail("Value has bits set to right of mask.")));
106         }
107
108         VARATT_SIZEP(dst) = VARHDRSZ
109                 + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
110                 + ip_addrsize(dst);
111         ip_bits(dst) = bits;
112         ip_type(dst) = type;
113
114         return dst;
115 }
116
117 /* INET address reader.  */
118 Datum
119 inet_in(PG_FUNCTION_ARGS)
120 {
121         char       *src = PG_GETARG_CSTRING(0);
122
123         PG_RETURN_INET_P(network_in(src, 0));
124 }
125
126 /* CIDR address reader.  */
127 Datum
128 cidr_in(PG_FUNCTION_ARGS)
129 {
130         char       *src = PG_GETARG_CSTRING(0);
131
132         PG_RETURN_INET_P(network_in(src, 1));
133 }
134
135
136 /*
137  *      INET address output function.
138  */
139 Datum
140 inet_out(PG_FUNCTION_ARGS)
141 {
142         inet       *src = PG_GETARG_INET_P(0);
143         char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
144         char       *dst;
145         int                     len;
146
147         dst = inet_net_ntop(ip_family(src), ip_addr(src), ip_bits(src),
148                                                 tmp, sizeof(tmp));
149         if (dst == NULL)
150                 ereport(ERROR,
151                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
152                                  errmsg("could not format inet value: %m")));
153
154         /* For CIDR, add /n if not present */
155         if (ip_type(src) && strchr(tmp, '/') == NULL)
156         {
157                 len = strlen(tmp);
158                 snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(src));
159         }
160
161         PG_RETURN_CSTRING(pstrdup(tmp));
162 }
163
164
165 /* share code with INET case */
166 Datum
167 cidr_out(PG_FUNCTION_ARGS)
168 {
169         return inet_out(fcinfo);
170 }
171
172
173 /*
174  *              inet_recv                       - converts external binary format to inet
175  *
176  * The external representation is (one byte apiece for)
177  * family, bits, type, address length, address in network byte order.
178  */
179 Datum
180 inet_recv(PG_FUNCTION_ARGS)
181 {
182         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
183         inet       *addr;
184         char       *addrptr;
185         int                     bits;
186         int                     nb,
187                                 i;
188
189         /* make sure any unused bits in a CIDR value are zeroed */
190         addr = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
191
192         ip_family(addr) = pq_getmsgbyte(buf);
193         if (ip_family(addr) != PGSQL_AF_INET &&
194                 ip_family(addr) != PGSQL_AF_INET6)
195                 ereport(ERROR,
196                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
197                            errmsg("invalid address family in external \"inet\" value")));
198         bits = pq_getmsgbyte(buf);
199         if (bits < 0 || bits > ip_maxbits(addr))
200                 ereport(ERROR,
201                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
202                                  errmsg("invalid bits in external \"inet\" value")));
203         ip_bits(addr) = bits;
204         ip_type(addr) = pq_getmsgbyte(buf);
205         if (ip_type(addr) != 0 && ip_type(addr) != 1)
206                 ereport(ERROR,
207                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
208                                  errmsg("invalid type in external \"inet\" value")));
209         nb = pq_getmsgbyte(buf);
210         if (nb != ip_addrsize(addr))
211                 ereport(ERROR,
212                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
213                                  errmsg("invalid length in external \"inet\" value")));
214         VARATT_SIZEP(addr) = VARHDRSZ
215                 + ((char *) ip_addr(addr) - (char *) VARDATA(addr))
216                 + ip_addrsize(addr);
217
218         addrptr = (char *) ip_addr(addr);
219         for (i = 0; i < nb; i++)
220                 addrptr[i] = pq_getmsgbyte(buf);
221
222         /*
223          * Error check: CIDR values must not have any bits set beyond the masklen.
224          */
225         if (ip_type(addr))
226         {
227                 if (!addressOK(ip_addr(addr), bits, ip_family(addr)))
228                         ereport(ERROR,
229                                         (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
230                                          errmsg("invalid external \"cidr\" value"),
231                                          errdetail("Value has bits set to right of mask.")));
232         }
233
234         PG_RETURN_INET_P(addr);
235 }
236
237 /* share code with INET case */
238 Datum
239 cidr_recv(PG_FUNCTION_ARGS)
240 {
241         return inet_recv(fcinfo);
242 }
243
244 /*
245  *              inet_send                       - converts inet to binary format
246  */
247 Datum
248 inet_send(PG_FUNCTION_ARGS)
249 {
250         inet       *addr = PG_GETARG_INET_P(0);
251         StringInfoData buf;
252         char       *addrptr;
253         int                     nb,
254                                 i;
255
256         pq_begintypsend(&buf);
257         pq_sendbyte(&buf, ip_family(addr));
258         pq_sendbyte(&buf, ip_bits(addr));
259         pq_sendbyte(&buf, ip_type(addr));
260         nb = ip_addrsize(addr);
261         if (nb < 0)
262                 nb = 0;
263         pq_sendbyte(&buf, nb);
264         addrptr = (char *) ip_addr(addr);
265         for (i = 0; i < nb; i++)
266                 pq_sendbyte(&buf, addrptr[i]);
267         PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
268 }
269
270 /* share code with INET case */
271 Datum
272 cidr_send(PG_FUNCTION_ARGS)
273 {
274         return inet_send(fcinfo);
275 }
276
277
278 static Datum
279 text_network(text *src, int type)
280 {
281         int                     len = VARSIZE(src) - VARHDRSZ;
282
283         char       *str = palloc(len + 1);
284
285         memcpy(str, VARDATA(src), len);
286         *(str + len) = '\0';
287
288         PG_RETURN_INET_P(network_in(str, type));
289 }
290
291
292 Datum
293 text_cidr(PG_FUNCTION_ARGS)
294 {
295         return text_network(PG_GETARG_TEXT_P(0), 1);
296 }
297
298 Datum
299 text_inet(PG_FUNCTION_ARGS)
300 {
301         return text_network(PG_GETARG_TEXT_P(0), 0);
302 }
303
304 Datum
305 inet_set_masklen(PG_FUNCTION_ARGS)
306 {
307         inet       *src = PG_GETARG_INET_P(0);
308         int                     bits = PG_GETARG_INT32(1);
309         inet       *dst;
310
311         if (bits == -1)
312                 bits = ip_maxbits(src);
313
314         if ((bits < 0) || (bits > ip_maxbits(src)))
315                 ereport(ERROR,
316                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
317                                  errmsg("invalid mask length: %d", bits)));
318
319         /* clone the original data */
320         dst = (inet *) palloc(VARSIZE(src));
321         memcpy(dst, src, VARSIZE(src));
322
323         ip_bits(dst) = bits;
324
325         PG_RETURN_INET_P(dst);
326 }
327
328 /*
329  *      Basic comparison function for sorting and inet/cidr comparisons.
330  *
331  * Comparison is first on the common bits of the network part, then on
332  * the length of the network part, and then on the whole unmasked address.
333  * The effect is that the network part is the major sort key, and for
334  * equal network parts we sort on the host part.  Note this is only sane
335  * for CIDR if address bits to the right of the mask are guaranteed zero;
336  * otherwise logically-equal CIDRs might compare different.
337  */
338
339 static int32
340 network_cmp_internal(inet *a1, inet *a2)
341 {
342         if (ip_family(a1) == ip_family(a2))
343         {
344                 int                     order;
345
346                 order = bitncmp(ip_addr(a1), ip_addr(a2),
347                                                 Min(ip_bits(a1), ip_bits(a2)));
348                 if (order != 0)
349                         return order;
350                 order = ((int) ip_bits(a1)) - ((int) ip_bits(a2));
351                 if (order != 0)
352                         return order;
353                 return bitncmp(ip_addr(a1), ip_addr(a2), ip_maxbits(a1));
354         }
355
356         return ip_family(a1) - ip_family(a2);
357 }
358
359 Datum
360 network_cmp(PG_FUNCTION_ARGS)
361 {
362         inet       *a1 = PG_GETARG_INET_P(0);
363         inet       *a2 = PG_GETARG_INET_P(1);
364
365         PG_RETURN_INT32(network_cmp_internal(a1, a2));
366 }
367
368 /*
369  *      Boolean ordering tests.
370  */
371 Datum
372 network_lt(PG_FUNCTION_ARGS)
373 {
374         inet       *a1 = PG_GETARG_INET_P(0);
375         inet       *a2 = PG_GETARG_INET_P(1);
376
377         PG_RETURN_BOOL(network_cmp_internal(a1, a2) < 0);
378 }
379
380 Datum
381 network_le(PG_FUNCTION_ARGS)
382 {
383         inet       *a1 = PG_GETARG_INET_P(0);
384         inet       *a2 = PG_GETARG_INET_P(1);
385
386         PG_RETURN_BOOL(network_cmp_internal(a1, a2) <= 0);
387 }
388
389 Datum
390 network_eq(PG_FUNCTION_ARGS)
391 {
392         inet       *a1 = PG_GETARG_INET_P(0);
393         inet       *a2 = PG_GETARG_INET_P(1);
394
395         PG_RETURN_BOOL(network_cmp_internal(a1, a2) == 0);
396 }
397
398 Datum
399 network_ge(PG_FUNCTION_ARGS)
400 {
401         inet       *a1 = PG_GETARG_INET_P(0);
402         inet       *a2 = PG_GETARG_INET_P(1);
403
404         PG_RETURN_BOOL(network_cmp_internal(a1, a2) >= 0);
405 }
406
407 Datum
408 network_gt(PG_FUNCTION_ARGS)
409 {
410         inet       *a1 = PG_GETARG_INET_P(0);
411         inet       *a2 = PG_GETARG_INET_P(1);
412
413         PG_RETURN_BOOL(network_cmp_internal(a1, a2) > 0);
414 }
415
416 Datum
417 network_ne(PG_FUNCTION_ARGS)
418 {
419         inet       *a1 = PG_GETARG_INET_P(0);
420         inet       *a2 = PG_GETARG_INET_P(1);
421
422         PG_RETURN_BOOL(network_cmp_internal(a1, a2) != 0);
423 }
424
425 /*
426  * Support function for hash indexes on inet/cidr.
427  *
428  * Since network_cmp considers only ip_family, ip_bits, and ip_addr,
429  * only these fields may be used in the hash; in particular don't use type.
430  */
431 Datum
432 hashinet(PG_FUNCTION_ARGS)
433 {
434         inet       *addr = PG_GETARG_INET_P(0);
435         int                     addrsize = ip_addrsize(addr);
436         unsigned char key[sizeof(inet_struct)];
437
438         Assert(addrsize + 2 <= sizeof(key));
439         key[0] = ip_family(addr);
440         key[1] = ip_bits(addr);
441         memcpy(key + 2, ip_addr(addr), addrsize);
442
443         return hash_any(key, addrsize + 2);
444 }
445
446 /*
447  *      Boolean network-inclusion tests.
448  */
449 Datum
450 network_sub(PG_FUNCTION_ARGS)
451 {
452         inet       *a1 = PG_GETARG_INET_P(0);
453         inet       *a2 = PG_GETARG_INET_P(1);
454
455         if (ip_family(a1) == ip_family(a2))
456         {
457                 PG_RETURN_BOOL(ip_bits(a1) > ip_bits(a2)
458                                          && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
459         }
460
461         PG_RETURN_BOOL(false);
462 }
463
464 Datum
465 network_subeq(PG_FUNCTION_ARGS)
466 {
467         inet       *a1 = PG_GETARG_INET_P(0);
468         inet       *a2 = PG_GETARG_INET_P(1);
469
470         if (ip_family(a1) == ip_family(a2))
471         {
472                 PG_RETURN_BOOL(ip_bits(a1) >= ip_bits(a2)
473                                          && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a2)) == 0);
474         }
475
476         PG_RETURN_BOOL(false);
477 }
478
479 Datum
480 network_sup(PG_FUNCTION_ARGS)
481 {
482         inet       *a1 = PG_GETARG_INET_P(0);
483         inet       *a2 = PG_GETARG_INET_P(1);
484
485         if (ip_family(a1) == ip_family(a2))
486         {
487                 PG_RETURN_BOOL(ip_bits(a1) < ip_bits(a2)
488                                          && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
489         }
490
491         PG_RETURN_BOOL(false);
492 }
493
494 Datum
495 network_supeq(PG_FUNCTION_ARGS)
496 {
497         inet       *a1 = PG_GETARG_INET_P(0);
498         inet       *a2 = PG_GETARG_INET_P(1);
499
500         if (ip_family(a1) == ip_family(a2))
501         {
502                 PG_RETURN_BOOL(ip_bits(a1) <= ip_bits(a2)
503                                          && bitncmp(ip_addr(a1), ip_addr(a2), ip_bits(a1)) == 0);
504         }
505
506         PG_RETURN_BOOL(false);
507 }
508
509 /*
510  * Extract data from a network datatype.
511  */
512 Datum
513 network_host(PG_FUNCTION_ARGS)
514 {
515         inet       *ip = PG_GETARG_INET_P(0);
516         text       *ret;
517         int                     len;
518         char       *ptr;
519         char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
520
521         /* force display of max bits, regardless of masklen... */
522         if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
523                                           tmp, sizeof(tmp)) == NULL)
524                 ereport(ERROR,
525                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
526                                  errmsg("could not format inet value: %m")));
527
528         /* Suppress /n if present (shouldn't happen now) */
529         if ((ptr = strchr(tmp, '/')) != NULL)
530                 *ptr = '\0';
531
532         /* Return string as a text datum */
533         len = strlen(tmp);
534         ret = (text *) palloc(len + VARHDRSZ);
535         VARATT_SIZEP(ret) = len + VARHDRSZ;
536         memcpy(VARDATA(ret), tmp, len);
537         PG_RETURN_TEXT_P(ret);
538 }
539
540 Datum
541 network_show(PG_FUNCTION_ARGS)
542 {
543         inet       *ip = PG_GETARG_INET_P(0);
544         text       *ret;
545         int                     len;
546         char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
547
548         if (inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip),
549                                           tmp, sizeof(tmp)) == NULL)
550                 ereport(ERROR,
551                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
552                                  errmsg("could not format inet value: %m")));
553
554         /* Add /n if not present (which it won't be) */
555         if (strchr(tmp, '/') == NULL)
556         {
557                 len = strlen(tmp);
558                 snprintf(tmp + len, sizeof(tmp) - len, "/%u", ip_bits(ip));
559         }
560
561         /* Return string as a text datum */
562         len = strlen(tmp);
563         ret = (text *) palloc(len + VARHDRSZ);
564         VARATT_SIZEP(ret) = len + VARHDRSZ;
565         memcpy(VARDATA(ret), tmp, len);
566         PG_RETURN_TEXT_P(ret);
567 }
568
569 Datum
570 network_abbrev(PG_FUNCTION_ARGS)
571 {
572         inet       *ip = PG_GETARG_INET_P(0);
573         text       *ret;
574         char       *dst;
575         int                     len;
576         char            tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
577
578         if (ip_type(ip))
579                 dst = inet_cidr_ntop(ip_family(ip), ip_addr(ip),
580                                                          ip_bits(ip), tmp, sizeof(tmp));
581         else
582                 dst = inet_net_ntop(ip_family(ip), ip_addr(ip),
583                                                         ip_bits(ip), tmp, sizeof(tmp));
584
585         if (dst == NULL)
586                 ereport(ERROR,
587                                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
588                                  errmsg("could not format inet value: %m")));
589
590         /* Return string as a text datum */
591         len = strlen(tmp);
592         ret = (text *) palloc(len + VARHDRSZ);
593         VARATT_SIZEP(ret) = len + VARHDRSZ;
594         memcpy(VARDATA(ret), tmp, len);
595         PG_RETURN_TEXT_P(ret);
596 }
597
598 Datum
599 network_masklen(PG_FUNCTION_ARGS)
600 {
601         inet       *ip = PG_GETARG_INET_P(0);
602
603         PG_RETURN_INT32(ip_bits(ip));
604 }
605
606 Datum
607 network_family(PG_FUNCTION_ARGS)
608 {
609         inet       *ip = PG_GETARG_INET_P(0);
610
611         switch (ip_family(ip))
612         {
613                 case PGSQL_AF_INET:
614                         PG_RETURN_INT32(4);
615                         break;
616                 case PGSQL_AF_INET6:
617                         PG_RETURN_INT32(6);
618                         break;
619                 default:
620                         PG_RETURN_INT32(0);
621                         break;
622         }
623 }
624
625 Datum
626 network_broadcast(PG_FUNCTION_ARGS)
627 {
628         inet       *ip = PG_GETARG_INET_P(0);
629         inet       *dst;
630         int                     byte;
631         int                     bits;
632         int                     maxbytes;
633         unsigned char mask;
634         unsigned char *a,
635                            *b;
636
637         /* make sure any unused bits are zeroed */
638         dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
639
640         if (ip_family(ip) == PGSQL_AF_INET)
641                 maxbytes = 4;
642         else
643                 maxbytes = 16;
644
645         bits = ip_bits(ip);
646         a = ip_addr(ip);
647         b = ip_addr(dst);
648
649         for (byte = 0; byte < maxbytes; byte++)
650         {
651                 if (bits >= 8)
652                 {
653                         mask = 0x00;
654                         bits -= 8;
655                 }
656                 else if (bits == 0)
657                         mask = 0xff;
658                 else
659                 {
660                         mask = 0xff >> bits;
661                         bits = 0;
662                 }
663
664                 b[byte] = a[byte] | mask;
665         }
666
667         ip_family(dst) = ip_family(ip);
668         ip_bits(dst) = ip_bits(ip);
669         ip_type(dst) = 0;
670         VARATT_SIZEP(dst) = VARHDRSZ
671                 + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
672                 + ip_addrsize(dst);
673
674         PG_RETURN_INET_P(dst);
675 }
676
677 Datum
678 network_network(PG_FUNCTION_ARGS)
679 {
680         inet       *ip = PG_GETARG_INET_P(0);
681         inet       *dst;
682         int                     byte;
683         int                     bits;
684         unsigned char mask;
685         unsigned char *a,
686                            *b;
687
688         /* make sure any unused bits are zeroed */
689         dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
690
691         bits = ip_bits(ip);
692         a = ip_addr(ip);
693         b = ip_addr(dst);
694
695         byte = 0;
696         while (bits)
697         {
698                 if (bits >= 8)
699                 {
700                         mask = 0xff;
701                         bits -= 8;
702                 }
703                 else
704                 {
705                         mask = 0xff << (8 - bits);
706                         bits = 0;
707                 }
708
709                 b[byte] = a[byte] & mask;
710                 byte++;
711         }
712
713         ip_family(dst) = ip_family(ip);
714         ip_bits(dst) = ip_bits(ip);
715         ip_type(dst) = 1;
716         VARATT_SIZEP(dst) = VARHDRSZ
717                 + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
718                 + ip_addrsize(dst);
719
720         PG_RETURN_INET_P(dst);
721 }
722
723 Datum
724 network_netmask(PG_FUNCTION_ARGS)
725 {
726         inet       *ip = PG_GETARG_INET_P(0);
727         inet       *dst;
728         int                     byte;
729         int                     bits;
730         unsigned char mask;
731         unsigned char *b;
732
733         /* make sure any unused bits are zeroed */
734         dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
735
736         bits = ip_bits(ip);
737         b = ip_addr(dst);
738
739         byte = 0;
740         while (bits)
741         {
742                 if (bits >= 8)
743                 {
744                         mask = 0xff;
745                         bits -= 8;
746                 }
747                 else
748                 {
749                         mask = 0xff << (8 - bits);
750                         bits = 0;
751                 }
752
753                 b[byte] = mask;
754                 byte++;
755         }
756
757         ip_family(dst) = ip_family(ip);
758         ip_bits(dst) = ip_maxbits(ip);
759         ip_type(dst) = 0;
760         VARATT_SIZEP(dst) = VARHDRSZ
761                 + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
762                 + ip_addrsize(dst);
763
764         PG_RETURN_INET_P(dst);
765 }
766
767 Datum
768 network_hostmask(PG_FUNCTION_ARGS)
769 {
770         inet       *ip = PG_GETARG_INET_P(0);
771         inet       *dst;
772         int                     byte;
773         int                     bits;
774         int                     maxbytes;
775         unsigned char mask;
776         unsigned char *b;
777
778         /* make sure any unused bits are zeroed */
779         dst = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
780
781         if (ip_family(ip) == PGSQL_AF_INET)
782                 maxbytes = 4;
783         else
784                 maxbytes = 16;
785
786         bits = ip_maxbits(ip) - ip_bits(ip);
787         b = ip_addr(dst);
788
789         byte = maxbytes - 1;
790         while (bits)
791         {
792                 if (bits >= 8)
793                 {
794                         mask = 0xff;
795                         bits -= 8;
796                 }
797                 else
798                 {
799                         mask = 0xff >> (8 - bits);
800                         bits = 0;
801                 }
802
803                 b[byte] = mask;
804                 byte--;
805         }
806
807         ip_family(dst) = ip_family(ip);
808         ip_bits(dst) = ip_maxbits(ip);
809         ip_type(dst) = 0;
810         VARATT_SIZEP(dst) = VARHDRSZ
811                 + ((char *) ip_addr(dst) - (char *) VARDATA(dst))
812                 + ip_addrsize(dst);
813
814         PG_RETURN_INET_P(dst);
815 }
816
817 /*
818  * Convert a value of a network datatype to an approximate scalar value.
819  * This is used for estimating selectivities of inequality operators
820  * involving network types.
821  *
822  * Currently, inet/cidr values are simply converted to the IPv4 address;
823  * this will need more thought when IPv6 is supported too.      MAC addresses
824  * are converted to their numeric equivalent as well (OK since we have a
825  * double to play in).
826  */
827 double
828 convert_network_to_scalar(Datum value, Oid typid)
829 {
830         switch (typid)
831         {
832                 case INETOID:
833                 case CIDROID:
834                         {
835                                 inet       *ip = DatumGetInetP(value);
836                                 int                     len;
837                                 double          res;
838                                 int                     i;
839
840                                 /*
841                                  * Note that we don't use the full address here.
842                                  */
843                                 if (ip_family(ip) == PGSQL_AF_INET)
844                                         len = 4;
845                                 else
846                                         len = 5;
847
848                                 res = ip_family(ip);
849                                 for (i = 0; i < len; i++)
850                                 {
851                                         res *= 256;
852                                         res += ip_addr(ip)[i];
853                                 }
854                                 return res;
855
856                                 break;
857                         }
858                 case MACADDROID:
859                         {
860                                 macaddr    *mac = DatumGetMacaddrP(value);
861                                 double          res;
862
863                                 res = (mac->a << 16) | (mac->b << 8) | (mac->c);
864                                 res *= 256 * 256 * 256;
865                                 res += (mac->d << 16) | (mac->e << 8) | (mac->f);
866                                 return res;
867                         }
868         }
869
870         /*
871          * Can't get here unless someone tries to use scalarltsel/scalargtsel on
872          * an operator with one network and one non-network operand.
873          */
874         elog(ERROR, "unsupported type: %u", typid);
875         return 0;
876 }
877
878 /*
879  * int
880  * bitncmp(l, r, n)
881  *              compare bit masks l and r, for n bits.
882  * return:
883  *              -1, 1, or 0 in the libc tradition.
884  * note:
885  *              network byte order assumed.  this means 192.5.5.240/28 has
886  *              0x11110000 in its fourth octet.
887  * author:
888  *              Paul Vixie (ISC), June 1996
889  */
890 static int
891 bitncmp(void *l, void *r, int n)
892 {
893         u_int           lb,
894                                 rb;
895         int                     x,
896                                 b;
897
898         b = n / 8;
899         x = memcmp(l, r, b);
900         if (x)
901                 return x;
902
903         lb = ((const u_char *) l)[b];
904         rb = ((const u_char *) r)[b];
905         for (b = n % 8; b > 0; b--)
906         {
907                 if (IS_HIGHBIT_SET(lb) != IS_HIGHBIT_SET(rb))
908                 {
909                         if (IS_HIGHBIT_SET(lb))
910                                 return 1;
911                         return -1;
912                 }
913                 lb <<= 1;
914                 rb <<= 1;
915         }
916         return 0;
917 }
918
919 static bool
920 addressOK(unsigned char *a, int bits, int family)
921 {
922         int                     byte;
923         int                     nbits;
924         int                     maxbits;
925         int                     maxbytes;
926         unsigned char mask;
927
928         if (family == PGSQL_AF_INET)
929         {
930                 maxbits = 32;
931                 maxbytes = 4;
932         }
933         else
934         {
935                 maxbits = 128;
936                 maxbytes = 16;
937         }
938         Assert(bits <= maxbits);
939
940         if (bits == maxbits)
941                 return true;
942
943         byte = bits / 8;
944         nbits = bits % 8;
945         mask = 0xff;
946         if (bits != 0)
947                 mask >>= nbits;
948
949         while (byte < maxbytes)
950         {
951                 if ((a[byte] & mask) != 0)
952                         return false;
953                 mask = 0xff;
954                 byte++;
955         }
956
957         return true;
958 }
959
960
961 /*
962  * These functions are used by planner to generate indexscan limits
963  * for clauses a << b and a <<= b
964  */
965
966 /* return the minimal value for an IP on a given network */
967 Datum
968 network_scan_first(Datum in)
969 {
970         return DirectFunctionCall1(network_network, in);
971 }
972
973 /*
974  * return "last" IP on a given network. It's the broadcast address,
975  * however, masklen has to be set to its max btis, since
976  * 192.168.0.255/24 is considered less than 192.168.0.255/32
977  *
978  * inet_set_masklen() hacked to max out the masklength to 128 for IPv6
979  * and 32 for IPv4 when given '-1' as argument.
980  */
981 Datum
982 network_scan_last(Datum in)
983 {
984         return DirectFunctionCall2(inet_set_masklen,
985                                                            DirectFunctionCall1(network_broadcast, in),
986                                                            Int32GetDatum(-1));
987 }
988
989
990 /*
991  * IP address that the client is connecting from (NULL if Unix socket)
992  */
993 Datum
994 inet_client_addr(PG_FUNCTION_ARGS)
995 {
996         Port       *port = MyProcPort;
997         char            remote_host[NI_MAXHOST];
998         int                     ret;
999
1000         if (port == NULL)
1001                 PG_RETURN_NULL();
1002
1003         switch (port->raddr.addr.ss_family)
1004         {
1005                 case AF_INET:
1006 #ifdef HAVE_IPV6
1007                 case AF_INET6:
1008 #endif
1009                         break;
1010                 default:
1011                         PG_RETURN_NULL();
1012         }
1013
1014         remote_host[0] = '\0';
1015
1016         ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
1017                                                          remote_host, sizeof(remote_host),
1018                                                          NULL, 0,
1019                                                          NI_NUMERICHOST | NI_NUMERICSERV);
1020         if (ret)
1021                 PG_RETURN_NULL();
1022
1023         PG_RETURN_INET_P(network_in(remote_host, 0));
1024 }
1025
1026
1027 /*
1028  * port that the client is connecting from (NULL if Unix socket)
1029  */
1030 Datum
1031 inet_client_port(PG_FUNCTION_ARGS)
1032 {
1033         Port       *port = MyProcPort;
1034         char            remote_port[NI_MAXSERV];
1035         int                     ret;
1036
1037         if (port == NULL)
1038                 PG_RETURN_NULL();
1039
1040         switch (port->raddr.addr.ss_family)
1041         {
1042                 case AF_INET:
1043 #ifdef HAVE_IPV6
1044                 case AF_INET6:
1045 #endif
1046                         break;
1047                 default:
1048                         PG_RETURN_NULL();
1049         }
1050
1051         remote_port[0] = '\0';
1052
1053         ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
1054                                                          NULL, 0,
1055                                                          remote_port, sizeof(remote_port),
1056                                                          NI_NUMERICHOST | NI_NUMERICSERV);
1057         if (ret)
1058                 PG_RETURN_NULL();
1059
1060         PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
1061 }
1062
1063
1064 /*
1065  * IP address that the server accepted the connection on (NULL if Unix socket)
1066  */
1067 Datum
1068 inet_server_addr(PG_FUNCTION_ARGS)
1069 {
1070         Port       *port = MyProcPort;
1071         char            local_host[NI_MAXHOST];
1072         int                     ret;
1073
1074         if (port == NULL)
1075                 PG_RETURN_NULL();
1076
1077         switch (port->laddr.addr.ss_family)
1078         {
1079                 case AF_INET:
1080 #ifdef HAVE_IPV6
1081                 case AF_INET6:
1082 #endif
1083                         break;
1084                 default:
1085                         PG_RETURN_NULL();
1086         }
1087
1088         local_host[0] = '\0';
1089
1090         ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
1091                                                          local_host, sizeof(local_host),
1092                                                          NULL, 0,
1093                                                          NI_NUMERICHOST | NI_NUMERICSERV);
1094         if (ret)
1095                 PG_RETURN_NULL();
1096
1097         PG_RETURN_INET_P(network_in(local_host, 0));
1098 }
1099
1100
1101 /*
1102  * port that the server accepted the connection on (NULL if Unix socket)
1103  */
1104 Datum
1105 inet_server_port(PG_FUNCTION_ARGS)
1106 {
1107         Port       *port = MyProcPort;
1108         char            local_port[NI_MAXSERV];
1109         int                     ret;
1110
1111         if (port == NULL)
1112                 PG_RETURN_NULL();
1113
1114         switch (port->laddr.addr.ss_family)
1115         {
1116                 case AF_INET:
1117 #ifdef HAVE_IPV6
1118                 case AF_INET6:
1119 #endif
1120                         break;
1121                 default:
1122                         PG_RETURN_NULL();
1123         }
1124
1125         local_port[0] = '\0';
1126
1127         ret = pg_getnameinfo_all(&port->laddr.addr, port->laddr.salen,
1128                                                          NULL, 0,
1129                                                          local_port, sizeof(local_port),
1130                                                          NI_NUMERICHOST | NI_NUMERICSERV);
1131         if (ret)
1132                 PG_RETURN_NULL();
1133
1134         PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(local_port)));
1135 }