]> git.meshlink.io Git - catta/blob - avahi-common/domain.c
Split avahi-common/util.h into
[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 unsigned avahi_strhash(const char *p) {
231     unsigned hash = 0;
232
233     for (; *p; p++)
234         hash = 31 * hash + *p;
235
236     return hash;
237 }
238
239 unsigned avahi_domain_hash(const char *s) {
240     unsigned hash = 0;
241     
242     for (;;) {
243         char c[65];
244
245         if (!avahi_unescape_label(&s, c, sizeof(c)))
246             return hash;
247
248         if (!c[0])
249             continue;
250         
251         hash += avahi_strhash(avahi_strdown(c));
252     }
253 }
254
255 int avahi_valid_service_type(const char *t) {
256     const char *p;
257     assert(t);
258
259     if (strlen(t) < 5)
260         return 0;
261     
262     if (*t != '_')
263         return 0;
264
265     if (!(p = strchr(t, '.')))
266         return 0;
267
268     if (p - t > 63 || p - t < 2)
269         return 0;
270
271     if (*(++p) != '_')
272         return 0;
273
274     if (strchr(p, '.'))
275         return 0;
276
277     if (strlen(p) > 63 || strlen(p) < 2)
278         return 0;
279     
280     return 1;
281 }
282
283 int avahi_valid_domain_name(const char *t) {
284     const char *p, *dp;
285     int dot = 0;
286         
287     assert(t);
288
289     if (*t == 0)
290         return 0;
291
292     /* Domains may not start with a dot */
293     if (*t == '.')
294         return 0;
295
296     dp = t; 
297
298     for (p = t; *p; p++) {
299
300         if (*p == '.') {
301             if (dot) /* Two subsequent dots */
302                 return 0;
303
304             if (p - dp > 63)
305                 return 0;
306
307             dot = 1;
308             dp = p + 1;
309         } else
310             dot = 0;
311
312     }
313
314     if (p - dp > 63)
315         return 0;
316
317     /* A trailing dot IS allowed */
318     
319     return 1;
320 }
321
322 int avahi_valid_service_name(const char *t) {
323     assert(t);
324
325     if (*t == 0)
326         return 0;
327
328     if (strlen(t) > 63)
329         return 0;
330
331     return 1;
332 }
333
334 int avahi_valid_host_name(const char *t) {
335     assert(t);
336
337     if (*t == 0)
338         return 0;
339
340     if (strlen(t) > 63)
341         return 0;
342
343     if (strchr(t, '.'))
344         return 0;
345
346     return 1;
347 }
348
349 char *avahi_strdown(char *s) {
350     char *c;
351     
352     assert(s);
353
354     for (c = s; *c; c++)
355         *c = (char) tolower(*c);
356
357     return s;
358 }
359
360 char *avahi_strup(char *s) {
361     char *c;
362     assert(s);
363
364     for (c = s; *c; c++)
365         *c = (char) toupper(*c);
366
367     return s;
368 }
369