]> git.meshlink.io Git - catta/blob - src/address.c
c207fdc28445d2542d66af3546b2019524060c2d
[catta] / src / address.c
1 /***
2   This file is part of catta.
3
4   catta is free software; you can redistribute it and/or modify it
5   under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2.1 of the
7   License, or (at your option) any later version.
8
9   catta is distributed in the hope that it will be useful, but WITHOUT
10   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12   Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with catta; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17   USA.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <sys/types.h>
25 #include <netinet/in.h>
26 #include <sys/socket.h>
27 #include <arpa/inet.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <stdio.h>
31
32 #include <catta/address.h>
33 #include <catta/malloc.h>
34
35 static size_t address_get_size(const CattaAddress *a) {
36     assert(a);
37
38     if (a->proto == CATTA_PROTO_INET)
39         return 4;
40     else if (a->proto == CATTA_PROTO_INET6)
41         return 16;
42
43     return 0;
44 }
45
46 int catta_address_cmp(const CattaAddress *a, const CattaAddress *b) {
47     assert(a);
48     assert(b);
49
50     if (a->proto != b->proto)
51         return -1;
52
53     return memcmp(a->data.data, b->data.data, address_get_size(a));
54 }
55
56 char *catta_address_snprint(char *s, size_t length, const CattaAddress *a) {
57     assert(s);
58     assert(length);
59     assert(a);
60
61     if (!(inet_ntop(catta_proto_to_af(a->proto), a->data.data, s, length)))
62         return NULL;
63
64     return s;
65 }
66
67 char* catta_reverse_lookup_name(const CattaAddress *a, char *ret_s, size_t length) {
68     assert(ret_s);
69     assert(length > 0);
70     assert(a);
71
72     if (a->proto == CATTA_PROTO_INET) {
73         uint32_t n = ntohl(a->data.ipv4.address);
74         snprintf(
75             ret_s, length,
76             "%u.%u.%u.%u.in-addr.arpa",
77             n & 0xFF, (n >> 8) & 0xFF, (n >> 16) & 0xFF, n >> 24);
78     } else {
79         assert(a->proto == CATTA_PROTO_INET6);
80
81         snprintf(
82             ret_s, length,
83             "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa",
84             a->data.ipv6.address[15] & 0xF, a->data.ipv6.address[15] >> 4,
85             a->data.ipv6.address[14] & 0xF, a->data.ipv6.address[14] >> 4,
86             a->data.ipv6.address[13] & 0xF, a->data.ipv6.address[13] >> 4,
87             a->data.ipv6.address[12] & 0xF, a->data.ipv6.address[12] >> 4,
88             a->data.ipv6.address[11] & 0xF, a->data.ipv6.address[11] >> 4,
89             a->data.ipv6.address[10] & 0xF, a->data.ipv6.address[10] >> 4,
90             a->data.ipv6.address[ 9] & 0xF, a->data.ipv6.address[ 9] >> 4,
91             a->data.ipv6.address[ 8] & 0xF, a->data.ipv6.address[ 8] >> 4,
92             a->data.ipv6.address[ 7] & 0xF, a->data.ipv6.address[ 7] >> 4,
93             a->data.ipv6.address[ 6] & 0xF, a->data.ipv6.address[ 6] >> 4,
94             a->data.ipv6.address[ 5] & 0xF, a->data.ipv6.address[ 5] >> 4,
95             a->data.ipv6.address[ 4] & 0xF, a->data.ipv6.address[ 4] >> 4,
96             a->data.ipv6.address[ 3] & 0xF, a->data.ipv6.address[ 3] >> 4,
97             a->data.ipv6.address[ 2] & 0xF, a->data.ipv6.address[ 2] >> 4,
98             a->data.ipv6.address[ 1] & 0xF, a->data.ipv6.address[ 1] >> 4,
99             a->data.ipv6.address[ 0] & 0xF, a->data.ipv6.address[ 0] >> 4);
100     }
101
102     return ret_s;
103 }
104
105 CattaAddress *catta_address_parse(const char *s, CattaProtocol proto, CattaAddress *ret_addr) {
106     assert(ret_addr);
107     assert(s);
108
109     if (proto == CATTA_PROTO_UNSPEC) {
110         if (inet_pton(AF_INET, s, ret_addr->data.data) <= 0) {
111             if (inet_pton(AF_INET6, s, ret_addr->data.data) <= 0)
112                 return NULL;
113             else
114                 ret_addr->proto = CATTA_PROTO_INET6;
115         } else
116             ret_addr->proto = CATTA_PROTO_INET;
117     } else {
118         if (inet_pton(catta_proto_to_af(proto), s, ret_addr->data.data) <= 0)
119             return NULL;
120
121         ret_addr->proto = proto;
122     }
123
124     return ret_addr;
125 }
126
127 int catta_proto_to_af(CattaProtocol proto) {
128     if (proto == CATTA_PROTO_INET)
129         return AF_INET;
130     if (proto == CATTA_PROTO_INET6)
131         return AF_INET6;
132
133     assert(proto == CATTA_PROTO_UNSPEC);
134     return AF_UNSPEC;
135 }
136
137 CattaProtocol catta_af_to_proto(int af) {
138     if (af == AF_INET)
139         return CATTA_PROTO_INET;
140     if (af == AF_INET6)
141         return CATTA_PROTO_INET6;
142
143     assert(af == AF_UNSPEC);
144     return CATTA_PROTO_UNSPEC;
145 }
146
147 const char* catta_proto_to_string(CattaProtocol proto) {
148     if (proto == CATTA_PROTO_INET)
149         return "IPv4";
150     if (proto == CATTA_PROTO_INET6)
151         return "IPv6";
152
153     assert(proto == CATTA_PROTO_UNSPEC);
154     return "UNSPEC";
155 }