]> git.meshlink.io Git - catta/blob - avahi-common/domain.c
hide some more files
[catta] / avahi-common / domain.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <limits.h>
31 #include <stdio.h>
32 #include <ctype.h>
33 #include <stdlib.h>
34 #include <assert.h>
35
36 #include "domain.h"
37 #include "malloc.h"
38
39 char *avahi_get_host_name(void) {
40 #ifdef HOST_NAME_MAX
41     char t[HOST_NAME_MAX];
42 #else
43     char t[256];
44 #endif
45     gethostname(t, sizeof(t));
46     t[sizeof(t)-1] = 0;
47     return avahi_normalize_name(t);
48 }
49
50 static char *unescape_uneeded(const char *src, char *ret_dest, size_t size) {
51     int escaped = 0;
52     
53     assert(src);
54     assert(ret_dest);
55     assert(size > 0);
56     
57     for (; *src; src++) {
58
59         if (!escaped && *src == '\\')
60             escaped = 1;
61         else if (escaped && (*src == '.' || *src == '\\')) {
62
63             if ((size -= 2) <= 1) break;
64             
65             *(ret_dest++) = '\\';
66             *(ret_dest++) = *src;
67             escaped = 0;
68         } else {
69             if (--size <= 1) break;
70
71             *(ret_dest++) = *src;
72             escaped = 0;
73         }
74
75     }
76
77     *ret_dest = 0;
78     
79     return ret_dest;
80 }
81
82 char *avahi_normalize_name(const char *s) {
83     char tmp[256];
84     size_t l;
85     
86     assert(s);
87
88     unescape_uneeded(s, tmp, sizeof(tmp));
89
90     l = strlen(tmp);
91
92     while (l > 0 && tmp[l-1] == '.')
93         tmp[--l] = 0;
94
95     return avahi_strdup(tmp);
96 }
97
98
99 /* Read the first label from string *name, unescape "\" and write it to dest */
100 char *avahi_unescape_label(const char **name, char *dest, size_t size) {
101     unsigned i = 0;
102     char *d;
103     
104     assert(dest);
105     assert(size > 0);
106     assert(name);
107
108     if (!**name)
109         return NULL;
110
111     d = dest;
112     
113     for (;;) {
114         if (i >= size)
115             return NULL;
116
117         if (**name == '.') {
118             (*name)++;
119             break;
120         }
121         
122         if (**name == 0)
123             break;
124         
125         if (**name == '\\') {
126             (*name) ++;
127             
128             if (**name == 0)
129                 break;
130         }
131         
132         *(d++) = *((*name) ++);
133         i++;
134     }
135
136     assert(i < size);
137
138     *d = 0;
139
140     return dest;
141 }
142
143 /* Escape "\" and ".", append \0 */
144 char *avahi_escape_label(const uint8_t* src, size_t src_length, char **ret_name, size_t *ret_size) {
145     char *r;
146
147     assert(src);
148     assert(ret_name);
149     assert(*ret_name);
150     assert(ret_size);
151     assert(*ret_size > 0);
152
153     r = *ret_name;
154
155     while (src_length > 0) {
156         if (*src == '.' || *src == '\\') {
157             if (*ret_size < 3)
158                 return NULL;
159             
160             *((*ret_name) ++) = '\\';
161             (*ret_size) --;
162         }
163
164         if (*ret_size < 2)
165             return NULL;
166         
167         *((*ret_name)++) = *src;
168         (*ret_size) --;
169
170         src_length --;
171         src++;
172     }
173
174     **ret_name = 0;
175
176     return r;
177 }
178
179 int avahi_domain_equal(const char *a, const char *b) {
180     assert(a);
181     assert(b);
182
183     if (a == b)
184         return 1;
185     
186     for (;;) {
187         char ca[65], cb[65], *pa, *pb;
188
189         pa = avahi_unescape_label(&a, ca, sizeof(ca));
190         pb = avahi_unescape_label(&b, cb, sizeof(cb));
191
192         if (!pa && !pb)
193             return 1;
194         else if ((pa && !pb) || (!pa && pb))
195             return 0;
196
197         if (strcasecmp(pa, pb))
198             return 0;
199     }
200
201     return 1;
202 }
203
204 int avahi_binary_domain_cmp(const char *a, const char *b) {
205     assert(a);
206     assert(b);
207
208     if (a == b)
209         return 0;
210
211     for (;;) {
212         char ca[65], cb[65], *pa, *pb;
213         int r;
214
215         pa = avahi_unescape_label(&a, ca, sizeof(ca));
216         pb = avahi_unescape_label(&b, cb, sizeof(cb));
217
218         if (!pa && !pb)
219             return 0;
220         else if (pa && !pb)
221             return 1;
222         else if (!pa && pb)
223             return -1;
224         
225         if ((r = strcmp(pa, pb)))
226             return r;
227     }
228 }
229
230 int avahi_is_valid_service_type(const char *t) {
231     const char *p;
232     assert(t);
233
234     if (strlen(t) < 5)
235         return 0;
236     
237     if (*t != '_')
238         return 0;
239
240     if (!(p = strchr(t, '.')))
241         return 0;
242
243     if (p - t > 63 || p - t < 2)
244         return 0;
245
246     if (*(++p) != '_')
247         return 0;
248
249     if (strchr(p, '.'))
250         return 0;
251
252     if (strlen(p) > 63 || strlen(p) < 2)
253         return 0;
254     
255     return 1;
256 }
257
258 int avahi_is_valid_domain_name(const char *t) {
259     const char *p, *dp;
260     int dot = 0;
261         
262     assert(t);
263
264     if (*t == 0)
265         return 0;
266
267     /* Domains may not start with a dot */
268     if (*t == '.')
269         return 0;
270
271     dp = t; 
272
273     for (p = t; *p; p++) {
274
275         if (*p == '.') {
276             if (dot) /* Two subsequent dots */
277                 return 0;
278
279             if (p - dp > 63)
280                 return 0;
281
282             dot = 1;
283             dp = p + 1;
284         } else
285             dot = 0;
286
287     }
288
289     if (p - dp > 63)
290         return 0;
291
292     /* A trailing dot IS allowed */
293     
294     return 1;
295 }
296
297 int avahi_is_valid_service_name(const char *t) {
298     assert(t);
299
300     if (*t == 0)
301         return 0;
302
303     if (strlen(t) > 63)
304         return 0;
305
306     return 1;
307 }
308
309 int avahi_is_valid_host_name(const char *t) {
310     assert(t);
311
312     if (*t == 0)
313         return 0;
314
315     if (strlen(t) > 63)
316         return 0;
317
318     if (strchr(t, '.'))
319         return 0;
320
321     return 1;
322 }
323
324 unsigned avahi_domain_hash(const char *s) {
325     unsigned hash = 0;
326     
327     for (;;) {
328         char c[65], *p;
329
330         if (!avahi_unescape_label(&s, c, sizeof(c)))
331             return hash;
332
333         if (!c[0])
334             continue;
335
336         for (p = c; *p; p++)
337             hash = 31 * hash + tolower(*p);
338     }
339 }