1 /***
2 This file is part of avahi.
3
4 avahi 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 avahi 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 avahi; 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 "address.h"
33 #include "avahi-malloc.h"
34
address_get_size(const AvahiAddress * a)35 static size_t address_get_size(const AvahiAddress *a) {
36 assert(a);
37
38 if (a->proto == AVAHI_PROTO_INET)
39 return 4;
40 else if (a->proto == AVAHI_PROTO_INET6)
41 return 16;
42
43 return 0;
44 }
45
avahi_address_cmp(const AvahiAddress * a,const AvahiAddress * b)46 int avahi_address_cmp(const AvahiAddress *a, const AvahiAddress *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
avahi_address_snprint(char * s,size_t length,const AvahiAddress * a)56 char *avahi_address_snprint(char *s, size_t length, const AvahiAddress *a) {
57 assert(s);
58 assert(length);
59 assert(a);
60
61 if (!(inet_ntop(avahi_proto_to_af(a->proto), a->data.data, s, length)))
62 return NULL;
63
64 return s;
65 }
66
avahi_reverse_lookup_name(const AvahiAddress * a,char * ret_s,size_t length)67 char* avahi_reverse_lookup_name(const AvahiAddress *a, char *ret_s, size_t length) {
68 assert(ret_s);
69 assert(length > 0);
70 assert(a);
71
72 if (a->proto == AVAHI_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 == AVAHI_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
avahi_address_parse(const char * s,AvahiProtocol proto,AvahiAddress * ret_addr)105 AvahiAddress *avahi_address_parse(const char *s, AvahiProtocol proto, AvahiAddress *ret_addr) {
106 assert(ret_addr);
107 assert(s);
108
109 if (proto == AVAHI_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 = AVAHI_PROTO_INET6;
115 } else
116 ret_addr->proto = AVAHI_PROTO_INET;
117 } else {
118 if (inet_pton(avahi_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
avahi_proto_to_af(AvahiProtocol proto)127 int avahi_proto_to_af(AvahiProtocol proto) {
128 if (proto == AVAHI_PROTO_INET)
129 return AF_INET;
130 if (proto == AVAHI_PROTO_INET6)
131 return AF_INET6;
132
133 assert(proto == AVAHI_PROTO_UNSPEC);
134 return AF_UNSPEC;
135 }
136
avahi_af_to_proto(int af)137 AvahiProtocol avahi_af_to_proto(int af) {
138 if (af == AF_INET)
139 return AVAHI_PROTO_INET;
140 if (af == AF_INET6)
141 return AVAHI_PROTO_INET6;
142
143 assert(af == AF_UNSPEC);
144 return AVAHI_PROTO_UNSPEC;
145 }
146
avahi_proto_to_string(AvahiProtocol proto)147 const char* avahi_proto_to_string(AvahiProtocol proto) {
148 if (proto == AVAHI_PROTO_INET)
149 return "IPv4";
150 if (proto == AVAHI_PROTO_INET6)
151 return "IPv6";
152
153 assert(proto == AVAHI_PROTO_UNSPEC);
154 return "UNSPEC";
155 }
156