]>
Commit | Line | Data |
---|---|---|
bac8f21b BH |
1 | #include <stdlib.h> |
2 | #include <string.h> | |
3 | #include <stdio.h> | |
4 | #include <unistd.h> | |
5 | #include <string> | |
bae1b0a2 | 6 | #include "dnsname.hh" |
bac8f21b BH |
7 | #include "namespaces.hh" |
8 | ||
bac8f21b BH |
9 | namespace { |
10 | void appendSplit(vector<string>& ret, string& segment, char c) | |
11 | { | |
12 | if(segment.size()>254) { | |
13 | ret.push_back(segment); | |
14 | segment.clear(); | |
15 | } | |
16 | segment.append(1, c); | |
17 | } | |
3c115e0f | 18 | |
bac8f21b BH |
19 | } |
20 | ||
21 | vector<string> segmentDNSText(const string& input ) | |
22 | { | |
fc634e87 | 23 | // cerr<<"segmentDNSText("<<input<<")"<<endl; |
2fa33bce BH |
24 | %%{ |
25 | machine dnstext; | |
26 | write data; | |
916a0fda | 27 | alphtype unsigned char; |
2fa33bce | 28 | }%% |
f8499e52 BH |
29 | (void)dnstext_error; // silence warnings |
30 | (void)dnstext_en_main; | |
bac8f21b BH |
31 | const char *p = input.c_str(), *pe = input.c_str() + input.length(); |
32 | const char* eof = pe; | |
33 | int cs; | |
34 | char val = 0; | |
35 | ||
36 | string segment; | |
37 | vector<string> ret; | |
38 | ||
39 | %%{ | |
40 | action segmentEnd { | |
41 | ret.push_back(segment); | |
42 | segment.clear(); | |
43 | } | |
44 | action segmentBegin { | |
45 | segment.clear(); | |
46 | } | |
47 | ||
48 | action reportEscaped { | |
49 | char c = *fpc; | |
50 | appendSplit(ret, segment, c); | |
51 | } | |
52 | action reportEscapedNumber { | |
53 | char c = *fpc; | |
54 | val *= 10; | |
55 | val += c-'0'; | |
56 | ||
57 | } | |
58 | action doneEscapedNumber { | |
59 | appendSplit(ret, segment, val); | |
60 | val=0; | |
61 | } | |
62 | ||
63 | action reportPlain { | |
64 | appendSplit(ret, segment, *(fpc)); | |
65 | } | |
66 | ||
35261869 | 67 | escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber)); |
973efd35 | 68 | plain = ((extend-'\\'-'"')|'\n'|'\t') $ reportPlain; |
2fa33bce BH |
69 | txtElement = escaped | plain; |
70 | ||
71 | main := (('"' txtElement* '"' space?) >segmentBegin %segmentEnd)+; | |
bac8f21b BH |
72 | |
73 | # Initialize and execute. | |
74 | write init; | |
75 | write exec; | |
76 | }%% | |
77 | ||
78 | if ( cs < dnstext_first_final ) { | |
79 | throw runtime_error("Unable to parse DNS TXT '"+input+"'"); | |
80 | } | |
81 | ||
82 | return ret; | |
83 | }; | |
2fa33bce | 84 | |
bae1b0a2 | 85 | |
beb9fad5 | 86 | DNSName::string_t segmentDNSNameRaw(const char* realinput, size_t inputlen) |
3c115e0f | 87 | { |
88 | %%{ | |
bae1b0a2 | 89 | machine dnsnameraw; |
3c115e0f | 90 | write data; |
91 | alphtype unsigned char; | |
92 | }%% | |
bae1b0a2 | 93 | (void)dnsnameraw_error; // silence warnings |
94 | (void)dnsnameraw_en_main; | |
1f3151e8 | 95 | |
bae1b0a2 | 96 | DNSName::string_t ret; |
1f3151e8 | 97 | |
bae1b0a2 | 98 | if(!*realinput || *realinput == '.') { |
99 | ret.append(1, (char)0); | |
100 | return ret; | |
101 | } | |
1f3151e8 | 102 | |
bae1b0a2 | 103 | ret.reserve(inputlen+1); |
1f3151e8 | 104 | |
bae1b0a2 | 105 | const char *p = realinput, *pe = realinput + inputlen; |
3c115e0f | 106 | const char* eof = pe; |
107 | int cs; | |
108 | char val = 0; | |
bae1b0a2 | 109 | char labellen=0; |
110 | unsigned int lenpos=0; | |
3c115e0f | 111 | %%{ |
112 | action labelEnd { | |
d0a4a4bc RG |
113 | if (labellen < 0 || labellen > 63) { |
114 | throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': invalid label length "+std::to_string(labellen)); | |
115 | } | |
bae1b0a2 | 116 | ret[lenpos]=labellen; |
117 | labellen=0; | |
3c115e0f | 118 | } |
119 | action labelBegin { | |
bae1b0a2 | 120 | lenpos=ret.size(); |
121 | ret.append(1, (char)0); | |
122 | labellen=0; | |
3c115e0f | 123 | } |
124 | ||
125 | action reportEscaped { | |
126 | char c = *fpc; | |
bae1b0a2 | 127 | ret.append(1, c); |
128 | labellen++; | |
3c115e0f | 129 | } |
130 | action reportEscapedNumber { | |
131 | char c = *fpc; | |
132 | val *= 10; | |
133 | val += c-'0'; | |
3c115e0f | 134 | } |
135 | action doneEscapedNumber { | |
bae1b0a2 | 136 | ret.append(1, val); |
137 | labellen++; | |
3c115e0f | 138 | val=0; |
139 | } | |
140 | ||
141 | action reportPlain { | |
bae1b0a2 | 142 | ret.append(1, *(fpc)); |
143 | labellen++; | |
3c115e0f | 144 | } |
145 | ||
146 | escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber)); | |
564ec901 | 147 | plain = (extend-'\\'-'.') $ reportPlain; |
3c115e0f | 148 | labelElement = escaped | plain; |
149 | ||
bae1b0a2 | 150 | label = labelElement+ >labelBegin %labelEnd; |
151 | ||
152 | main:= label ('.' label )* '.'?; | |
153 | ||
154 | #main := labelElement((labelElement+ '.') >labelBegin %labelEnd)+; | |
155 | ||
156 | # label = (plain | escaped | escdecb)+ >label_init %label_fin; | |
157 | # dnsname := '.'? label ('.' label >label_sep)* '.'?; | |
3c115e0f | 158 | |
159 | # Initialize and execute. | |
160 | write init; | |
161 | write exec; | |
162 | }%% | |
163 | ||
bae1b0a2 | 164 | if ( cs < dnsnameraw_first_final ) { |
165 | throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': cs="+std::to_string(cs)); | |
3c115e0f | 166 | } |
bae1b0a2 | 167 | ret.append(1, (char)0); |
3c115e0f | 168 | return ret; |
169 | }; | |
170 | ||
171 | ||
bae1b0a2 | 172 | |
bac8f21b BH |
173 | #if 0 |
174 | int main() | |
175 | { | |
176 | //char blah[]="\"blah\" \"bleh\" \"bloeh\\\"bleh\" \"\\97enzo\""; | |
177 | char blah[]="\"v=spf1 ip4:67.106.74.128/25 ip4:63.138.42.224/28 ip4:65.204.46.224/27 \\013\\010ip4:66.104.217.176/28 \\013\\010ip4:209.48.147.0/27 ~all\""; | |
178 | //char blah[]="\"abc \\097\\098 def\""; | |
179 | printf("Input: '%s'\n", blah); | |
180 | vector<string> res=dnstext(blah); | |
181 | cerr<<res.size()<<" segments"<<endl; | |
182 | cerr<<res[0]<<endl; | |
183 | } | |
184 | #endif |