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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
int domain2name_len (const char * s, int l) { /* TODO make domain2name FAIL at empty label (..) */
int r = 1; /* ending terminator */ /* make functions FAIL at label.length > 63 */
int o = 0; /* label offset */ /* currently domain2name never fails */
for (int i = 0; i < l; i++) { /* NOTE when using BOTH _len, check that they are */
if (s[i] == '.') { /* NOT negative. d2n_len will fail in d future */
if (!o) /* double period or starting period, label is empty */
break;
o = 0;
continue;
}
if (!o) /* label has started */
r++;
r++;
o++;
}
return r;
}
int domain2name (char * n /* at least _len bytes */, const char * s, int l) { /* l is length of s */
char * c = n; /* where to write the label size when done with label */
char * w = n;
int o = 0; /* label offset */
for (int i = 0; i <= l /* yes, we go one more ... */; i++) {
if (i == l /* ... here */ || s[i] == '.') { /* end of label or end of last label */
if (!o) /* double period or starting period, label is empty */
break;
if (o <= 63) /* max length of label (six bits) */
*c = o;
o = 0;
continue;
}
if (!o++) /* label has started */
c = w++; /* to be filled with length */
if (o <= 63)
*w++ = s[i];
if (o == 64) /* if this label is too long, instead of writing it, we silently cap */
*c = 63; /* it at 63 bytes */
}
*w++ = '\0'; /* luckily this makes domain2name kind of safe for handling as a string (: */
return w-n; /* we return number of bytes written */
} /* no compression, it's 2022, net bandwidth is unlimited. n2d OFC does decompress ptrs acc2 std. */
int name2domain_len (const char * u /* >= 512 bytes */, const char * n /* name */) {
#define N2DO(x) ((x) & ~(1 << 7 & 1 << 6)) /* pointer offset */
int r = 0;
if (n < u+512 && *n == '\0') {
return 2;
}
while (n < u+512) {
if (*n & 1 << 7) {
if (!(*n & 1 << 6))
return -1; /* 10xx xxxx not implemented - reserved for future use */
n = u + N2DO(*n);
continue;
}
if (*n & 1 << 6)
return -2; /* 01xx xxxx not implemented - reserved for future use */
if (!*n)
return r+1;
r += *n+1;
n += *n+1;
}
return -3; /* malformed packet */
} /* returns number of bytes needed for buffer, passed as the first argument of name2domain(). */
const char * name2domain (char * d /* >= _len B */, const char * u /* >= 512 B */, const char * n) {
char * w = d; /* if d is NULL nothing is written and last byte of name is returned */
const char * r = NULL;
if (n < u+512 && *n == '\0') {
*w++ = '.';
*w++ = '\0';
return n;
}
while (n < u+512) {
if (*n & 1 << 7) {
if (!(*n & 1 << 6))
return NULL; /* 10xx xxxx N/I - reserved for future use as per RFC */
n = u + N2DO(*n);
r = n;
continue;
}
if (*n & 1 << 6)
return NULL; /* 01xx xxxx N/I - reserved for future use as per RFC */
if (!*n) { /* end of name */
if (w)
*w++ = '\0';
return r ? r : n;
}
const char * x = n+*n;
n++;
if (!(x < u+512))
return NULL; /* malformed packet */
while (n <= x)
if (w)
*w++ = *n++;
else
n++;
if (w)
*w++ = '.';
}
return NULL; /* malformed packet */
} /* Returns ptr to last byte of name - '\0' or dnsptr. Ret. NULL on fail (_len also returned < 0) */
int normalizedomain_len (const char * s, int l) {
int ž = domain2name_len(s, l);
if (ž < 0)
return -4;
char * b = alloca(ž);
if (domain2name(b, s, l) != ž)
return -5;
return name2domain_len(b, b);
}
int normalizedomain (char * d /* at least _len bytes */, const char * s, int l) {
int ž = domain2name_len(s, l);
if (ž < 0)
return -4;
char * b = alloca(ž);
if (domain2name(b, s, l) != ž)
return -5;
if (!name2domain(d, b, b))
return -6;
return 0;
}
|