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