]>
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 | |
86 | DNSName::string_t segmentDNSNameRaw(const char* realinput) | |
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 | unsigned int inputlen=strlen(realinput); |
104 | ret.reserve(inputlen+1); | |
1f3151e8 | 105 | |
bae1b0a2 | 106 | const char *p = realinput, *pe = realinput + inputlen; |
3c115e0f | 107 | const char* eof = pe; |
108 | int cs; | |
109 | char val = 0; | |
bae1b0a2 | 110 | char labellen=0; |
111 | unsigned int lenpos=0; | |
3c115e0f | 112 | %%{ |
113 | action labelEnd { | |
d0a4a4bc RG |
114 | if (labellen < 0 || labellen > 63) { |
115 | throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': invalid label length "+std::to_string(labellen)); | |
116 | } | |
bae1b0a2 | 117 | ret[lenpos]=labellen; |
118 | labellen=0; | |
3c115e0f | 119 | } |
120 | action labelBegin { | |
bae1b0a2 | 121 | lenpos=ret.size(); |
122 | ret.append(1, (char)0); | |
123 | labellen=0; | |
3c115e0f | 124 | } |
125 | ||
126 | action reportEscaped { | |
127 | char c = *fpc; | |
bae1b0a2 | 128 | ret.append(1, c); |
129 | labellen++; | |
3c115e0f | 130 | } |
131 | action reportEscapedNumber { | |
132 | char c = *fpc; | |
133 | val *= 10; | |
134 | val += c-'0'; | |
3c115e0f | 135 | } |
136 | action doneEscapedNumber { | |
bae1b0a2 | 137 | ret.append(1, val); |
138 | labellen++; | |
3c115e0f | 139 | val=0; |
140 | } | |
141 | ||
142 | action reportPlain { | |
bae1b0a2 | 143 | ret.append(1, *(fpc)); |
144 | labellen++; | |
3c115e0f | 145 | } |
146 | ||
147 | escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber)); | |
564ec901 | 148 | plain = (extend-'\\'-'.') $ reportPlain; |
3c115e0f | 149 | labelElement = escaped | plain; |
150 | ||
bae1b0a2 | 151 | label = labelElement+ >labelBegin %labelEnd; |
152 | ||
153 | main:= label ('.' label )* '.'?; | |
154 | ||
155 | #main := labelElement((labelElement+ '.') >labelBegin %labelEnd)+; | |
156 | ||
157 | # label = (plain | escaped | escdecb)+ >label_init %label_fin; | |
158 | # dnsname := '.'? label ('.' label >label_sep)* '.'?; | |
3c115e0f | 159 | |
160 | # Initialize and execute. | |
161 | write init; | |
162 | write exec; | |
163 | }%% | |
164 | ||
bae1b0a2 | 165 | if ( cs < dnsnameraw_first_final ) { |
166 | throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': cs="+std::to_string(cs)); | |
3c115e0f | 167 | } |
bae1b0a2 | 168 | ret.append(1, (char)0); |
3c115e0f | 169 | return ret; |
170 | }; | |
171 | ||
172 | ||
bae1b0a2 | 173 | |
bac8f21b BH |
174 | #if 0 |
175 | int main() | |
176 | { | |
177 | //char blah[]="\"blah\" \"bleh\" \"bloeh\\\"bleh\" \"\\97enzo\""; | |
178 | 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\""; | |
179 | //char blah[]="\"abc \\097\\098 def\""; | |
180 | printf("Input: '%s'\n", blah); | |
181 | vector<string> res=dnstext(blah); | |
182 | cerr<<res.size()<<" segments"<<endl; | |
183 | cerr<<res[0]<<endl; | |
184 | } | |
185 | #endif |