]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/network.c
Remove unused #includes in *.c files.
[postgresql] / src / backend / utils / adt / network.c
1 /*
2  *      PostgreSQL type definitions for the INET type.  This
3  *      is for IP V4 CIDR notation, but prepared for V6: just
4  *      add the necessary bits where the comments indicate.
5  *
6  *      $Id: network.c,v 1.13 1999/07/15 22:40:00 momjian Exp $
7  *      Jon Postel RIP 16 Oct 1998
8  */
9
10 #include <sys/types.h>
11 #include <sys/socket.h>
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <errno.h>
16
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19
20 #include <postgres.h>
21 #include <utils/builtins.h>
22
23 static int      v4bitncmp(unsigned int a1, unsigned int a2, int bits);
24
25 /*
26  *      Access macros.  Add IPV6 support.
27  */
28
29 #define ip_addrsize(inetptr) \
30         (((inet_struct *)VARDATA(inetptr))->family == AF_INET ? 4 : -1)
31
32 #define ip_family(inetptr) \
33         (((inet_struct *)VARDATA(inetptr))->family)
34
35 #define ip_bits(inetptr) \
36         (((inet_struct *)VARDATA(inetptr))->bits)
37
38 #define ip_type(inetptr) \
39         (((inet_struct *)VARDATA(inetptr))->type)
40
41 #define ip_v4addr(inetptr) \
42         (((inet_struct *)VARDATA(inetptr))->addr.ipv4_addr)
43
44 /* Common input routine */
45 static inet *
46 network_in(char *src, int type)
47 {
48         int                     bits;
49         inet       *dst;
50
51         if (!src)
52                 return NULL;
53
54         dst = palloc(VARHDRSZ + sizeof(inet_struct));
55         if (dst == NULL)
56                 elog(ERROR, "unable to allocate memory in network_in()");
57
58         /* First, try for an IP V4 address: */
59         ip_family(dst) = AF_INET;
60         bits = inet_net_pton(ip_family(dst), src, &ip_v4addr(dst),
61                                                  type ? ip_addrsize(dst) : -1);
62         if ((bits < 0) || (bits > 32))
63                 /* Go for an IPV6 address here, before faulting out: */
64                 elog(ERROR, "could not parse \"%s\"", src);
65
66         VARSIZE(dst) = VARHDRSZ
67                 + ((char *) &ip_v4addr(dst) - (char *) VARDATA(dst))
68                 + ip_addrsize(dst);
69         ip_bits(dst) = bits;
70         ip_type(dst) = type;
71         return dst;
72 }
73
74 /* INET address reader.  */
75 inet *
76 inet_in(char *src)
77 {
78         return network_in(src, 0);
79 }
80
81 /* CIDR address reader.  */
82 inet *
83 cidr_in(char *src)
84 {
85         return network_in(src, 1);
86 }
87
88 /*
89  *      INET address output function.
90  */
91
92 char *
93 inet_out(inet *src)
94 {
95         char       *dst,
96                                 tmp[sizeof("255.255.255.255/32")];
97
98         if (ip_family(src) == AF_INET)
99         {
100                 /* It's an IP V4 address: */
101                 if (ip_type(src))
102                         dst = inet_cidr_ntop(AF_INET, &ip_v4addr(src), ip_bits(src),
103                                                                  tmp, sizeof(tmp));
104                 else
105                         dst = inet_net_ntop(AF_INET, &ip_v4addr(src), ip_bits(src),
106                                                                 tmp, sizeof(tmp));
107
108                 if (dst == NULL)
109                         elog(ERROR, "unable to print address (%s)", strerror(errno));
110         }
111         else
112                 /* Go for an IPV6 address here, before faulting out: */
113                 elog(ERROR, "unknown address family (%d)", ip_family(src));
114
115         dst = palloc(strlen(tmp) + 1);
116         if (dst == NULL)
117                 elog(ERROR, "unable to allocate memory in inet_out()");
118
119         strcpy(dst, tmp);
120         return dst;
121 }
122
123
124 /* just a stub */
125 char *
126 cidr_out(inet *src)
127 {
128         return inet_out(src);
129 }
130
131 /*
132  *      Boolean tests for magnitude.  Add V4/V6 testing!
133  */
134
135 bool
136 network_lt(inet *a1, inet *a2)
137 {
138         if (!PointerIsValid(a1) || !PointerIsValid(a2))
139                 return FALSE;
140         if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
141         {
142                 int                     order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
143
144                 return ((order < 0) || ((order == 0) && (ip_bits(a1) < ip_bits(a2))));
145         }
146         else
147         {
148                 /* Go for an IPV6 address here, before faulting out: */
149                 elog(ERROR, "cannot compare address families %d and %d",
150                          ip_family(a1), ip_family(a2));
151                 return FALSE;
152         }
153 }
154
155 bool
156 network_le(inet *a1, inet *a2)
157 {
158         if (!PointerIsValid(a1) || !PointerIsValid(a2))
159                 return FALSE;
160         return (network_lt(a1, a2) || network_eq(a1, a2));
161 }
162
163 bool
164 network_eq(inet *a1, inet *a2)
165 {
166         if (!PointerIsValid(a1) || !PointerIsValid(a2))
167                 return FALSE;
168         if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
169         {
170                 return ((ip_bits(a1) == ip_bits(a2))
171                  && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
172         }
173         else
174         {
175                 /* Go for an IPV6 address here, before faulting out: */
176                 elog(ERROR, "cannot compare address families %d and %d",
177                          ip_family(a1), ip_family(a2));
178                 return FALSE;
179         }
180 }
181
182 bool
183 network_ge(inet *a1, inet *a2)
184 {
185         if (!PointerIsValid(a1) || !PointerIsValid(a2))
186                 return FALSE;
187         return (network_gt(a1, a2) || network_eq(a1, a2));
188 }
189
190 bool
191 network_gt(inet *a1, inet *a2)
192 {
193         if (!PointerIsValid(a1) || !PointerIsValid(a2))
194                 return FALSE;
195         if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
196         {
197                 int                     order = v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2));
198
199                 return ((order > 0) || ((order == 0) && (ip_bits(a1) > ip_bits(a2))));
200         }
201         else
202         {
203                 /* Go for an IPV6 address here, before faulting out: */
204                 elog(ERROR, "cannot compare address families %d and %d",
205                          ip_family(a1), ip_family(a2));
206                 return FALSE;
207         }
208 }
209
210 bool
211 network_ne(inet *a1, inet *a2)
212 {
213         if (!PointerIsValid(a1) || !PointerIsValid(a2))
214                 return FALSE;
215         return (!network_eq(a1, a2));
216 }
217
218 bool
219 network_sub(inet *a1, inet *a2)
220 {
221         if (!PointerIsValid(a1) || !PointerIsValid(a2))
222                 return FALSE;
223
224         if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
225         {
226                 return ((ip_bits(a1) > ip_bits(a2))
227                  && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0));
228         }
229         else
230         {
231                 /* Go for an IPV6 address here, before faulting out: */
232                 elog(ERROR, "cannot compare address families %d and %d",
233                          ip_family(a1), ip_family(a2));
234                 return FALSE;
235         }
236 }
237
238 bool
239 network_subeq(inet *a1, inet *a2)
240 {
241         if (!PointerIsValid(a1) || !PointerIsValid(a2))
242                 return FALSE;
243
244         if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
245         {
246                 return ((ip_bits(a1) >= ip_bits(a2))
247                  && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a2)) == 0));
248         }
249         else
250         {
251                 /* Go for an IPV6 address here, before faulting out: */
252                 elog(ERROR, "cannot compare address families %d and %d",
253                          ip_family(a1), ip_family(a2));
254                 return FALSE;
255         }
256 }
257
258 bool
259 network_sup(inet *a1, inet *a2)
260 {
261         if (!PointerIsValid(a1) || !PointerIsValid(a2))
262                 return FALSE;
263
264         if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
265         {
266                 return ((ip_bits(a1) < ip_bits(a2))
267                  && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
268         }
269         else
270         {
271                 /* Go for an IPV6 address here, before faulting out: */
272                 elog(ERROR, "cannot compare address families %d and %d",
273                          ip_family(a1), ip_family(a2));
274                 return FALSE;
275         }
276 }
277
278 bool
279 network_supeq(inet *a1, inet *a2)
280 {
281         if (!PointerIsValid(a1) || !PointerIsValid(a2))
282                 return FALSE;
283
284         if ((ip_family(a1) == AF_INET) && (ip_family(a2) == AF_INET))
285         {
286                 return ((ip_bits(a1) <= ip_bits(a2))
287                  && (v4bitncmp(ip_v4addr(a1), ip_v4addr(a2), ip_bits(a1)) == 0));
288         }
289         else
290         {
291                 /* Go for an IPV6 address here, before faulting out: */
292                 elog(ERROR, "cannot compare address families %d and %d",
293                          ip_family(a1), ip_family(a2));
294                 return FALSE;
295         }
296 }
297
298 /*
299  *      Comparison function for sorting.  Add V4/V6 testing!
300  */
301
302 int4
303 network_cmp(inet *a1, inet *a2)
304 {
305         if (ntohl(ip_v4addr(a1)) < ntohl(ip_v4addr(a2)))
306                 return (-1);
307
308         if (ntohl(ip_v4addr(a1)) > ntohl(ip_v4addr(a2)))
309                 return (1);
310
311         if (ip_bits(a1) < ip_bits(a2))
312                 return (-1);
313
314         if (ip_bits(a1) > ip_bits(a2))
315                 return (1);
316
317         return 0;
318 }
319
320 text *
321 network_host(inet *ip)
322 {
323         text       *ret;
324         int                     len;
325         char       *ptr,
326                                 tmp[sizeof("255.255.255.255/32")];
327
328         if (!PointerIsValid(ip))
329                 return NULL;
330
331         if (ip_type(ip))
332                 elog(ERROR, "CIDR type has no host part");
333
334         if (ip_family(ip) == AF_INET)
335         {
336                 /* It's an IP V4 address: */
337                 if (inet_net_ntop(AF_INET, &ip_v4addr(ip), 32, tmp, sizeof(tmp)) == NULL)
338                         elog(ERROR, "unable to print host (%s)", strerror(errno));
339         }
340         else
341                 /* Go for an IPV6 address here, before faulting out: */
342                 elog(ERROR, "unknown address family (%d)", ip_family(ip));
343
344         if ((ptr = strchr(tmp, '/')) != NULL)
345                 *ptr = 0;
346         len = VARHDRSZ + strlen(tmp) + 1;
347         ret = palloc(len);
348         if (ret == NULL)
349                 elog(ERROR, "unable to allocate memory in network_host()");
350
351         VARSIZE(ret) = len;
352         strcpy(VARDATA(ret), tmp);
353         return (ret);
354 }
355
356 int4
357 network_masklen(inet *ip)
358 {
359         if (!PointerIsValid(ip))
360                 return 0;
361
362         return ip_bits(ip);
363 }
364
365 text *
366 network_broadcast(inet *ip)
367 {
368         text       *ret;
369         int                     len;
370         char       *ptr,
371                                 tmp[sizeof("255.255.255.255/32")];
372
373         if (!PointerIsValid(ip))
374                 return NULL;
375
376         if (ip_family(ip) == AF_INET)
377         {
378                 /* It's an IP V4 address: */
379                 int                     addr;
380                 unsigned long mask = 0xffffffff;
381
382                 if (ip_bits(ip) < 32)
383                         mask >>= ip_bits(ip);
384                 addr = htonl(ntohl(ip_v4addr(ip)) | mask);
385
386                 if (inet_net_ntop(AF_INET, &addr, 32, tmp, sizeof(tmp)) == NULL)
387                         elog(ERROR, "unable to print address (%s)", strerror(errno));
388
389         }
390         else
391                 /* Go for an IPV6 address here, before faulting out: */
392                 elog(ERROR, "unknown address family (%d)", ip_family(ip));
393
394         if ((ptr = strchr(tmp, '/')) != NULL)
395                 *ptr = 0;
396         len = VARHDRSZ + strlen(tmp) + 1;
397         ret = palloc(len);
398         if (ret == NULL)
399                 elog(ERROR, "unable to allocate memory in network_broadcast()");
400
401         VARSIZE(ret) = len;
402         strcpy(VARDATA(ret), tmp);
403         return (ret);
404 }
405
406 text *
407 network_network(inet *ip)
408 {
409         text       *ret;
410         int                     len;
411         char            tmp[sizeof("255.255.255.255/32")];
412
413         if (!PointerIsValid(ip))
414                 return NULL;
415
416         if (ip_family(ip) == AF_INET)
417         {
418                 /* It's an IP V4 address: */
419                 int                     addr = htonl(ntohl(ip_v4addr(ip)) & (0xffffffff << (32 - ip_bits(ip))));
420
421                 if (inet_cidr_ntop(AF_INET, &addr, ip_bits(ip), tmp, sizeof(tmp)) == NULL)
422                         elog(ERROR, "unable to print network (%s)", strerror(errno));
423
424         }
425         else
426                 /* Go for an IPV6 address here, before faulting out: */
427                 elog(ERROR, "unknown address family (%d)", ip_family(ip));
428
429         len = VARHDRSZ + strlen(tmp) + 1;
430         ret = palloc(len);
431         if (ret == NULL)
432                 elog(ERROR, "unable to allocate memory in network_network()");
433
434         VARSIZE(ret) = len;
435         strcpy(VARDATA(ret), tmp);
436         return (ret);
437 }
438
439 text *
440 network_netmask(inet *ip)
441 {
442         text       *ret;
443         int                     len;
444         char       *ptr,
445                                 tmp[sizeof("255.255.255.255/32")];
446
447         if (!PointerIsValid(ip))
448                 return NULL;
449
450         if (ip_family(ip) == AF_INET)
451         {
452                 /* It's an IP V4 address: */
453                 int                     addr = htonl((-1 << (32 - ip_bits(ip))) & 0xffffffff);
454
455                 if (inet_net_ntop(AF_INET, &addr, 32, tmp, sizeof(tmp)) == NULL)
456                         elog(ERROR, "unable to print netmask (%s)", strerror(errno));
457
458         }
459         else
460                 /* Go for an IPV6 address here, before faulting out: */
461                 elog(ERROR, "unknown address family (%d)", ip_family(ip));
462
463         if ((ptr = strchr(tmp, '/')) != NULL)
464                 *ptr = 0;
465         len = VARHDRSZ + strlen(tmp) + 1;
466         ret = palloc(len);
467         if (ret == NULL)
468                 elog(ERROR, "unable to allocate memory in network_netmask()");
469
470         VARSIZE(ret) = len;
471         strcpy(VARDATA(ret), tmp);
472         return (ret);
473 }
474
475 /*
476  *      Bitwise comparison for V4 addresses.  Add V6 implementation!
477  */
478
479 static int
480 v4bitncmp(unsigned int a1, unsigned int a2, int bits)
481 {
482         unsigned long mask = 0;
483         int                     i;
484
485         for (i = 0; i < bits; i++)
486                 mask = (mask >> 1) | 0x80000000;
487         a1 = ntohl(a1);
488         a2 = ntohl(a2);
489         if ((a1 & mask) < (a2 & mask))
490                 return (-1);
491         else if ((a1 & mask) > (a2 & mask))
492                 return (1);
493         return (0);
494 }