You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

186 lines
5.2 KiB

  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. 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. }
  18. }
  19. vector<string> segmentDNSText(const string& input )
  20. {
  21. // cerr<<"segmentDNSText("<<input<<")"<<endl;
  22. %%{
  23. machine dnstext;
  24. write data;
  25. alphtype unsigned char;
  26. }%%
  27. (void)dnstext_error; // silence warnings
  28. (void)dnstext_en_main;
  29. const char *p = input.c_str(), *pe = input.c_str() + input.length();
  30. const char* eof = pe;
  31. int cs;
  32. char val = 0;
  33. string segment;
  34. vector<string> ret;
  35. %%{
  36. action segmentEnd {
  37. ret.push_back(segment);
  38. segment.clear();
  39. }
  40. action segmentBegin {
  41. segment.clear();
  42. }
  43. action reportEscaped {
  44. char c = *fpc;
  45. appendSplit(ret, segment, c);
  46. }
  47. action reportEscapedNumber {
  48. char c = *fpc;
  49. val *= 10;
  50. val += c-'0';
  51. }
  52. action doneEscapedNumber {
  53. appendSplit(ret, segment, val);
  54. val=0;
  55. }
  56. action reportPlain {
  57. appendSplit(ret, segment, *(fpc));
  58. }
  59. escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber));
  60. plain = ((extend-'\\'-'"')|'\n'|'\t') $ reportPlain;
  61. txtElement = escaped | plain;
  62. main := (('"' txtElement* '"' space?) >segmentBegin %segmentEnd)+;
  63. # Initialize and execute.
  64. write init;
  65. write exec;
  66. }%%
  67. if ( cs < dnstext_first_final ) {
  68. throw runtime_error("Unable to parse DNS TXT '"+input+"'");
  69. }
  70. return ret;
  71. };
  72. DNSName::string_t segmentDNSNameRaw(const char* realinput, size_t inputlen)
  73. {
  74. %%{
  75. machine dnsnameraw;
  76. write data;
  77. alphtype unsigned char;
  78. }%%
  79. (void)dnsnameraw_error; // silence warnings
  80. (void)dnsnameraw_en_main;
  81. DNSName::string_t ret;
  82. if(!*realinput || *realinput == '.') {
  83. ret.append(1, (char)0);
  84. return ret;
  85. }
  86. ret.reserve(inputlen+1);
  87. const char *p = realinput, *pe = realinput + inputlen;
  88. const char* eof = pe;
  89. int cs;
  90. char val = 0;
  91. char labellen=0;
  92. unsigned int lenpos=0;
  93. %%{
  94. action labelEnd {
  95. if (labellen < 0 || labellen > 63) {
  96. throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': invalid label length "+std::to_string(labellen));
  97. }
  98. ret[lenpos]=labellen;
  99. labellen=0;
  100. }
  101. action labelBegin {
  102. lenpos=ret.size();
  103. ret.append(1, (char)0);
  104. labellen=0;
  105. }
  106. action reportEscaped {
  107. char c = *fpc;
  108. ret.append(1, c);
  109. labellen++;
  110. }
  111. action reportEscapedNumber {
  112. char c = *fpc;
  113. val *= 10;
  114. val += c-'0';
  115. }
  116. action doneEscapedNumber {
  117. ret.append(1, val);
  118. labellen++;
  119. val=0;
  120. }
  121. action reportPlain {
  122. ret.append(1, *(fpc));
  123. labellen++;
  124. }
  125. escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber));
  126. plain = (extend-'\\'-'.') $ reportPlain;
  127. labelElement = escaped | plain;
  128. label = labelElement+ >labelBegin %labelEnd;
  129. main:= label ('.' label )* '.'?;
  130. #main := labelElement((labelElement+ '.') >labelBegin %labelEnd)+;
  131. # label = (plain | escaped | escdecb)+ >label_init %label_fin;
  132. # dnsname := '.'? label ('.' label >label_sep)* '.'?;
  133. # Initialize and execute.
  134. write init;
  135. write exec;
  136. }%%
  137. if ( cs < dnsnameraw_first_final ) {
  138. throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': cs="+std::to_string(cs));
  139. }
  140. ret.append(1, (char)0);
  141. return ret;
  142. };
  143. #if 0
  144. int main()
  145. {
  146. //char blah[]="\"blah\" \"bleh\" \"bloeh\\\"bleh\" \"\\97enzo\"";
  147. 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\"";
  148. //char blah[]="\"abc \\097\\098 def\"";
  149. printf("Input: '%s'\n", blah);
  150. vector<string> res=dnstext(blah);
  151. cerr<<res.size()<<" segments"<<endl;
  152. cerr<<res[0]<<endl;
  153. }
  154. #endif