]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnslabeltext.rl
Merge pull request #9134 from omoerbeek/secpoll-cleanup
[thirdparty/pdns.git] / pdns / dnslabeltext.rl
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <string>
6 #include "dnsname.hh"
7 #include "namespaces.hh"
8 #include "dnswriter.hh"
9
10 namespace {
11 void appendSplit(vector<string>& ret, string& segment, char c)
12 {
13 if(segment.size()>254) {
14 ret.push_back(segment);
15 segment.clear();
16 }
17 segment.append(1, c);
18 }
19
20 }
21
22 vector<string> segmentDNSText(const string& input )
23 {
24 // cerr<<"segmentDNSText("<<input<<")"<<endl;
25 %%{
26 machine dnstext;
27 write data;
28 alphtype unsigned char;
29 }%%
30 (void)dnstext_error; // silence warnings
31 (void)dnstext_en_main;
32 const char *p = input.c_str(), *pe = input.c_str() + input.length();
33 const char* eof = pe;
34 int cs;
35 char val = 0;
36
37 string segment;
38 vector<string> ret;
39
40 %%{
41 action segmentEnd {
42 ret.push_back(segment);
43 segment.clear();
44 }
45 action segmentBegin {
46 segment.clear();
47 }
48
49 action reportEscaped {
50 char c = *fpc;
51 appendSplit(ret, segment, c);
52 }
53 action reportEscapedNumber {
54 char c = *fpc;
55 val *= 10;
56 val += c-'0';
57
58 }
59 action doneEscapedNumber {
60 appendSplit(ret, segment, val);
61 val=0;
62 }
63
64 action reportPlain {
65 appendSplit(ret, segment, *(fpc));
66 }
67
68 escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber));
69 plain = ((extend-'\\'-'"')|'\n'|'\t') $ reportPlain;
70 txtElement = escaped | plain;
71
72 main := (('"' txtElement* '"' space?) >segmentBegin %segmentEnd)+;
73
74 # Initialize and execute.
75 write init;
76 write exec;
77 }%%
78
79 if ( cs < dnstext_first_final ) {
80 throw runtime_error("Unable to parse DNS TXT '"+input+"'");
81 }
82
83 return ret;
84 };
85
86
87 DNSName::string_t segmentDNSNameRaw(const char* realinput, size_t inputlen)
88 {
89 %%{
90 machine dnsnameraw;
91 write data;
92 alphtype unsigned char;
93 }%%
94 (void)dnsnameraw_error; // silence warnings
95 (void)dnsnameraw_en_main;
96
97 DNSName::string_t ret;
98
99 if(!*realinput || *realinput == '.') {
100 ret.append(1, (char)0);
101 return ret;
102 }
103
104 ret.reserve(inputlen+1);
105
106 const char *p = realinput, *pe = realinput + inputlen;
107 const char* eof = pe;
108 int cs;
109 char val = 0;
110 char labellen=0;
111 unsigned int lenpos=0;
112 %%{
113 action labelEnd {
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 }
117 ret[lenpos]=labellen;
118 labellen=0;
119 }
120 action labelBegin {
121 lenpos=ret.size();
122 ret.append(1, (char)0);
123 labellen=0;
124 }
125
126 action reportEscaped {
127 char c = *fpc;
128 ret.append(1, c);
129 labellen++;
130 }
131 action reportEscapedNumber {
132 char c = *fpc;
133 val *= 10;
134 val += c-'0';
135 }
136 action doneEscapedNumber {
137 ret.append(1, val);
138 labellen++;
139 val=0;
140 }
141
142 action reportPlain {
143 ret.append(1, *(fpc));
144 labellen++;
145 }
146
147 escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber));
148 plain = (extend-'\\'-'.') $ reportPlain;
149 labelElement = escaped | plain;
150
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)* '.'?;
159
160 # Initialize and execute.
161 write init;
162 write exec;
163 }%%
164
165 if ( cs < dnsnameraw_first_final ) {
166 throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': cs="+std::to_string(cs));
167 }
168 ret.append(1, (char)0);
169 return ret;
170 };
171
172
173
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