forked from rspamd/rbldnsd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dns_ptodn.c
62 lines (57 loc) · 1.68 KB
/
dns_ptodn.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* dns_ptodn() parses external textual dot-separated format
* into a domain name
*/
#include "dns.h"
#include <errno.h>
unsigned dns_ptodn(const char *name, unsigned char *dn, unsigned dnsiz) {
unsigned char *d; /* current position in dn (len byte first) */
unsigned char *label; /* start of last label */
unsigned char *m; /* max byte can be filled up */
unsigned l; /* length of current label */
unsigned c; /* next input character */
d = dn + 1;
label = d;
m = dn + (dnsiz > DNS_MAXDN ? DNS_MAXDN : dnsiz) - 1;
while((c = (unsigned char)*name++) != 0) {
if (c == '.') {
if ((l = d - label) != 0) { /* if there was a non-empty label */
if (l > DNS_MAXLABEL) {
errno = EMSGSIZE;
return 0;
}
label[-1] = (char)l; /* update len of last label */
label = ++d; /* start new label, label[-1] will be len of it */
}
continue;
}
if (c == '\\') { /* handle escapes */
if (!(c = (unsigned char)*name++))
break;
if (c >= '0' && c <= '9') { /* dec number: will be in c */
c -= '0';
if (*name >= '0' && *name <= '9') { /* 2digits */
c = (c * 10) + (*name++ - '0');
if (*name >= '0' && *name <= '9') { /* 3digits */
c = (c * 10) + (*name++ - '0');
if (c > 255) {
errno = EINVAL;
return 0;
}
}
}
}
}
if (d >= m) { /* too long? */
errno = EMSGSIZE;
return 0;
}
*d++ = (char)c; /* place next out byte */
}
if ((l = d - label) > DNS_MAXLABEL) {
errno = EMSGSIZE;
return 0;
}
if ((label[-1] = (char)l) != 0)
*d++ = 0;
return d - dn;
}