1
2 #line 1 "dnslabeltext.rl"
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <string>
8 #include "dnsname.hh"
9 #include "namespaces.hh"
10 #include "dnswriter.hh"
11 #include "misc.hh"
12
13 namespace {
appendSplit(vector<string> & ret,string & segment,char c)14 void appendSplit(vector<string>& ret, string& segment, char c)
15 {
16 if(segment.size()>254) {
17 ret.push_back(segment);
18 segment.clear();
19 }
20 segment.append(1, c);
21 }
22
23 }
24
segmentDNSText(const string & input)25 vector<string> segmentDNSText(const string& input )
26 {
27 // cerr<<"segmentDNSText("<<input<<")"<<endl;
28
29 #line 30 "dnslabeltext.cc"
30 static const char _dnstext_actions[] = {
31 0, 1, 0, 1, 1, 1, 2, 1,
32 3, 1, 4, 1, 5, 2, 0, 1,
33 2, 4, 5
34 };
35
36 static const char _dnstext_key_offsets[] = {
37 0, 0, 1, 3, 5, 7, 9, 11,
38 15
39 };
40
41 static const unsigned char _dnstext_trans_keys[] = {
42 34u, 34u, 92u, 48u, 57u, 48u, 57u, 48u,
43 57u, 34u, 92u, 32u, 34u, 9u, 13u, 34u,
44 0
45 };
46
47 static const char _dnstext_single_lengths[] = {
48 0, 1, 2, 0, 0, 0, 2, 2,
49 1
50 };
51
52 static const char _dnstext_range_lengths[] = {
53 0, 0, 0, 1, 1, 1, 0, 1,
54 0
55 };
56
57 static const char _dnstext_index_offsets[] = {
58 0, 0, 2, 5, 7, 9, 11, 14,
59 18
60 };
61
62 static const char _dnstext_trans_targs[] = {
63 2, 0, 7, 3, 2, 4, 2, 5,
64 0, 6, 0, 7, 3, 2, 8, 2,
65 8, 0, 2, 0, 0
66 };
67
68 static const char _dnstext_trans_actions[] = {
69 3, 0, 0, 0, 11, 7, 5, 7,
70 0, 7, 0, 9, 9, 16, 0, 13,
71 0, 0, 13, 0, 0
72 };
73
74 static const char _dnstext_eof_actions[] = {
75 0, 0, 0, 0, 0, 0, 0, 1,
76 1
77 };
78
79 static const int dnstext_start = 1;
80 static const int dnstext_first_final = 7;
81 static const int dnstext_error = 0;
82
83 static const int dnstext_en_main = 1;
84
85
86 #line 30 "dnslabeltext.rl"
87
88 (void)dnstext_error; // silence warnings
89 (void)dnstext_en_main;
90 const char *p = input.c_str(), *pe = input.c_str() + input.length();
91 const char* eof = pe;
92 int cs;
93 char val = 0;
94
95 string segment;
96 vector<string> ret;
97
98
99 #line 100 "dnslabeltext.cc"
100 {
101 cs = dnstext_start;
102 }
103
104 #line 105 "dnslabeltext.cc"
105 {
106 int _klen;
107 unsigned int _trans;
108 const char *_acts;
109 unsigned int _nacts;
110 const unsigned char *_keys;
111
112 if ( p == pe )
113 goto _test_eof;
114 if ( cs == 0 )
115 goto _out;
116 _resume:
117 _keys = _dnstext_trans_keys + _dnstext_key_offsets[cs];
118 _trans = _dnstext_index_offsets[cs];
119
120 _klen = _dnstext_single_lengths[cs];
121 if ( _klen > 0 ) {
122 const unsigned char *_lower = _keys;
123 const unsigned char *_mid;
124 const unsigned char *_upper = _keys + _klen - 1;
125 while (1) {
126 if ( _upper < _lower )
127 break;
128
129 _mid = _lower + ((_upper-_lower) >> 1);
130 if ( (*p) < *_mid )
131 _upper = _mid - 1;
132 else if ( (*p) > *_mid )
133 _lower = _mid + 1;
134 else {
135 _trans += (unsigned int)(_mid - _keys);
136 goto _match;
137 }
138 }
139 _keys += _klen;
140 _trans += _klen;
141 }
142
143 _klen = _dnstext_range_lengths[cs];
144 if ( _klen > 0 ) {
145 const unsigned char *_lower = _keys;
146 const unsigned char *_mid;
147 const unsigned char *_upper = _keys + (_klen<<1) - 2;
148 while (1) {
149 if ( _upper < _lower )
150 break;
151
152 _mid = _lower + (((_upper-_lower) >> 1) & ~1);
153 if ( (*p) < _mid[0] )
154 _upper = _mid - 2;
155 else if ( (*p) > _mid[1] )
156 _lower = _mid + 2;
157 else {
158 _trans += (unsigned int)((_mid - _keys)>>1);
159 goto _match;
160 }
161 }
162 _trans += _klen;
163 }
164
165 _match:
166 cs = _dnstext_trans_targs[_trans];
167
168 if ( _dnstext_trans_actions[_trans] == 0 )
169 goto _again;
170
171 _acts = _dnstext_actions + _dnstext_trans_actions[_trans];
172 _nacts = (unsigned int) *_acts++;
173 while ( _nacts-- > 0 )
174 {
175 switch ( *_acts++ )
176 {
177 case 0:
178 #line 42 "dnslabeltext.rl"
179 {
180 ret.push_back(segment);
181 segment.clear();
182 }
183 break;
184 case 1:
185 #line 46 "dnslabeltext.rl"
186 {
187 segment.clear();
188 }
189 break;
190 case 2:
191 #line 50 "dnslabeltext.rl"
192 {
193 char c = *p;
194 appendSplit(ret, segment, c);
195 }
196 break;
197 case 3:
198 #line 54 "dnslabeltext.rl"
199 {
200 char c = *p;
201 val *= 10;
202 val += c-'0';
203
204 }
205 break;
206 case 4:
207 #line 60 "dnslabeltext.rl"
208 {
209 appendSplit(ret, segment, val);
210 val=0;
211 }
212 break;
213 case 5:
214 #line 65 "dnslabeltext.rl"
215 {
216 appendSplit(ret, segment, *(p));
217 }
218 break;
219 #line 220 "dnslabeltext.cc"
220 }
221 }
222
223 _again:
224 if ( cs == 0 )
225 goto _out;
226 if ( ++p != pe )
227 goto _resume;
228 _test_eof: {}
229 if ( p == eof )
230 {
231 const char *__acts = _dnstext_actions + _dnstext_eof_actions[cs];
232 unsigned int __nacts = (unsigned int) *__acts++;
233 while ( __nacts-- > 0 ) {
234 switch ( *__acts++ ) {
235 case 0:
236 #line 42 "dnslabeltext.rl"
237 {
238 ret.push_back(segment);
239 segment.clear();
240 }
241 break;
242 #line 243 "dnslabeltext.cc"
243 }
244 }
245 }
246
247 _out: {}
248 }
249
250 #line 78 "dnslabeltext.rl"
251
252
253 if ( cs < dnstext_first_final ) {
254 throw runtime_error("Unable to parse DNS TXT '"+input+"'");
255 }
256
257 return ret;
258 };
259
260
segmentDNSNameRaw(const char * realinput,size_t inputlen)261 DNSName::string_t segmentDNSNameRaw(const char* realinput, size_t inputlen)
262 {
263
264 #line 265 "dnslabeltext.cc"
265 static const char _dnsnameraw_actions[] = {
266 0, 1, 0, 1, 1, 1, 2, 1,
267 3, 1, 4, 1, 5, 2, 1, 5,
268 2, 4, 0, 2, 4, 5
269 };
270
271 static const char _dnsnameraw_key_offsets[] = {
272 0, 0, 2, 4, 6, 8, 10, 12
273 };
274
275 static const unsigned char _dnsnameraw_trans_keys[] = {
276 46u, 92u, 48u, 57u, 48u, 57u, 48u, 57u,
277 46u, 92u, 46u, 92u, 46u, 92u, 0
278 };
279
280 static const char _dnsnameraw_single_lengths[] = {
281 0, 2, 0, 0, 0, 2, 2, 2
282 };
283
284 static const char _dnsnameraw_range_lengths[] = {
285 0, 0, 1, 1, 1, 0, 0, 0
286 };
287
288 static const char _dnsnameraw_index_offsets[] = {
289 0, 0, 3, 5, 7, 9, 12, 15
290 };
291
292 static const char _dnsnameraw_trans_targs[] = {
293 0, 2, 5, 3, 5, 4, 0, 7,
294 0, 6, 2, 5, 0, 2, 5, 6,
295 2, 5, 0
296 };
297
298 static const char _dnsnameraw_trans_actions[] = {
299 0, 3, 13, 7, 5, 7, 0, 7,
300 0, 1, 0, 11, 0, 3, 13, 16,
301 9, 19, 0
302 };
303
304 static const char _dnsnameraw_eof_actions[] = {
305 0, 0, 0, 0, 0, 1, 0, 16
306 };
307
308 static const int dnsnameraw_start = 1;
309 static const int dnsnameraw_first_final = 5;
310 static const int dnsnameraw_error = 0;
311
312 static const int dnsnameraw_en_main = 1;
313
314
315 #line 94 "dnslabeltext.rl"
316
317 (void)dnsnameraw_error; // silence warnings
318 (void)dnsnameraw_en_main;
319
320 DNSName::string_t ret;
321
322 if(!*realinput || *realinput == '.') {
323 ret.append(1, (char)0);
324 return ret;
325 }
326
327 ret.reserve(inputlen+1);
328
329 const char *p = realinput, *pe = realinput + inputlen;
330 const char* eof = pe;
331 int cs;
332 char val = 0;
333 char labellen=0;
334 unsigned int lenpos=0;
335
336 #line 337 "dnslabeltext.cc"
337 {
338 cs = dnsnameraw_start;
339 }
340
341 #line 342 "dnslabeltext.cc"
342 {
343 int _klen;
344 unsigned int _trans;
345 const char *_acts;
346 unsigned int _nacts;
347 const unsigned char *_keys;
348
349 if ( p == pe )
350 goto _test_eof;
351 if ( cs == 0 )
352 goto _out;
353 _resume:
354 _keys = _dnsnameraw_trans_keys + _dnsnameraw_key_offsets[cs];
355 _trans = _dnsnameraw_index_offsets[cs];
356
357 _klen = _dnsnameraw_single_lengths[cs];
358 if ( _klen > 0 ) {
359 const unsigned char *_lower = _keys;
360 const unsigned char *_mid;
361 const unsigned char *_upper = _keys + _klen - 1;
362 while (1) {
363 if ( _upper < _lower )
364 break;
365
366 _mid = _lower + ((_upper-_lower) >> 1);
367 if ( (*p) < *_mid )
368 _upper = _mid - 1;
369 else if ( (*p) > *_mid )
370 _lower = _mid + 1;
371 else {
372 _trans += (unsigned int)(_mid - _keys);
373 goto _match;
374 }
375 }
376 _keys += _klen;
377 _trans += _klen;
378 }
379
380 _klen = _dnsnameraw_range_lengths[cs];
381 if ( _klen > 0 ) {
382 const unsigned char *_lower = _keys;
383 const unsigned char *_mid;
384 const unsigned char *_upper = _keys + (_klen<<1) - 2;
385 while (1) {
386 if ( _upper < _lower )
387 break;
388
389 _mid = _lower + (((_upper-_lower) >> 1) & ~1);
390 if ( (*p) < _mid[0] )
391 _upper = _mid - 2;
392 else if ( (*p) > _mid[1] )
393 _lower = _mid + 2;
394 else {
395 _trans += (unsigned int)((_mid - _keys)>>1);
396 goto _match;
397 }
398 }
399 _trans += _klen;
400 }
401
402 _match:
403 cs = _dnsnameraw_trans_targs[_trans];
404
405 if ( _dnsnameraw_trans_actions[_trans] == 0 )
406 goto _again;
407
408 _acts = _dnsnameraw_actions + _dnsnameraw_trans_actions[_trans];
409 _nacts = (unsigned int) *_acts++;
410 while ( _nacts-- > 0 )
411 {
412 switch ( *_acts++ )
413 {
414 case 0:
415 #line 114 "dnslabeltext.rl"
416 {
417 if (labellen < 0 || labellen > 63) {
418 throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': invalid label length "+std::to_string(labellen));
419 }
420 ret[lenpos]=labellen;
421 labellen=0;
422 }
423 break;
424 case 1:
425 #line 121 "dnslabeltext.rl"
426 {
427 lenpos=ret.size();
428 ret.append(1, (char)0);
429 labellen=0;
430 }
431 break;
432 case 2:
433 #line 127 "dnslabeltext.rl"
434 {
435 char c = *p;
436 ret.append(1, c);
437 labellen++;
438 }
439 break;
440 case 3:
441 #line 132 "dnslabeltext.rl"
442 {
443 char c = *p;
444 val *= 10;
445 val += c-'0';
446 }
447 break;
448 case 4:
449 #line 137 "dnslabeltext.rl"
450 {
451 ret.append(1, val);
452 labellen++;
453 val=0;
454 }
455 break;
456 case 5:
457 #line 143 "dnslabeltext.rl"
458 {
459 ret.append(1, *(p));
460 labellen++;
461 }
462 break;
463 #line 464 "dnslabeltext.cc"
464 }
465 }
466
467 _again:
468 if ( cs == 0 )
469 goto _out;
470 if ( ++p != pe )
471 goto _resume;
472 _test_eof: {}
473 if ( p == eof )
474 {
475 const char *__acts = _dnsnameraw_actions + _dnsnameraw_eof_actions[cs];
476 unsigned int __nacts = (unsigned int) *__acts++;
477 while ( __nacts-- > 0 ) {
478 switch ( *__acts++ ) {
479 case 0:
480 #line 114 "dnslabeltext.rl"
481 {
482 if (labellen < 0 || labellen > 63) {
483 throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': invalid label length "+std::to_string(labellen));
484 }
485 ret[lenpos]=labellen;
486 labellen=0;
487 }
488 break;
489 case 4:
490 #line 137 "dnslabeltext.rl"
491 {
492 ret.append(1, val);
493 labellen++;
494 val=0;
495 }
496 break;
497 #line 498 "dnslabeltext.cc"
498 }
499 }
500 }
501
502 _out: {}
503 }
504
505 #line 164 "dnslabeltext.rl"
506
507
508 if ( cs < dnsnameraw_first_final ) {
509 throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': cs="+std::to_string(cs));
510 }
511 ret.append(1, (char)0);
512 return ret;
513 };
514
515 // Reads an RFC 1035 character string from 'in', puts the resulting bytes in 'out'.
516 // Returns the amount of bytes read from 'in'
parseRFC1035CharString(const std::string & in,std::string & val)517 size_t parseRFC1035CharString(const std::string &in, std::string &val) {
518
519 val.clear();
520 val.reserve(in.size());
521 const char *p = in.c_str();
522 const char *pe = p + in.size();
523 int cs = 0;
524 uint8_t escaped_octet = 0;
525 // Keeps track of how many chars we read from the source string
526 size_t counter=0;
527
528 /* This parses an RFC 1035 char-string.
529 * It was created from the ABNF in draft-ietf-dnsop-svcb-https-02 with
530 * https://github.com/zinid/abnfc and modified to put all the characters in the
531 * right place.
532 */
533
534 #line 535 "dnslabeltext.cc"
535 static const char _dns_text_to_string_actions[] = {
536 0, 1, 0, 1, 2, 1, 3, 2,
537 0, 1
538 };
539
540 static const char _dns_text_to_string_key_offsets[] = {
541 0, 0, 8, 15, 17, 19, 22, 24,
542 33, 41, 43, 45, 48, 50, 58
543 };
544
545 static const char _dns_text_to_string_trans_keys[] = {
546 34, 92, 33, 39, 42, 58, 60, 126,
547 50, 33, 47, 48, 49, 58, 126, 48,
548 57, 48, 57, 53, 48, 52, 48, 53,
549 9, 34, 92, 32, 39, 42, 58, 60,
550 126, 9, 50, 32, 47, 48, 49, 58,
551 126, 48, 57, 48, 57, 53, 48, 52,
552 48, 53, 33, 92, 35, 39, 42, 58,
553 60, 126, 0
554 };
555
556 static const char _dns_text_to_string_single_lengths[] = {
557 0, 2, 1, 0, 0, 1, 0, 3,
558 2, 0, 0, 1, 0, 2, 0
559 };
560
561 static const char _dns_text_to_string_range_lengths[] = {
562 0, 3, 3, 1, 1, 1, 1, 3,
563 3, 1, 1, 1, 1, 3, 0
564 };
565
566 static const char _dns_text_to_string_index_offsets[] = {
567 0, 0, 6, 11, 13, 15, 18, 20,
568 27, 33, 35, 37, 40, 42, 48
569 };
570
571 static const char _dns_text_to_string_indicies[] = {
572 2, 3, 0, 0, 0, 1, 5, 0,
573 4, 0, 1, 6, 1, 7, 1, 8,
574 6, 1, 7, 1, 9, 10, 11, 9,
575 9, 9, 1, 9, 13, 9, 12, 9,
576 1, 14, 1, 15, 1, 16, 14, 1,
577 15, 1, 0, 3, 0, 0, 0, 1,
578 1, 0
579 };
580
581 static const char _dns_text_to_string_trans_targs[] = {
582 13, 0, 7, 2, 3, 5, 4, 13,
583 6, 7, 14, 8, 9, 11, 10, 7,
584 12
585 };
586
587 static const char _dns_text_to_string_trans_actions[] = {
588 3, 0, 5, 5, 1, 1, 1, 7,
589 1, 3, 5, 5, 1, 1, 1, 7,
590 1
591 };
592
593 static const int dns_text_to_string_start = 1;
594 static const int dns_text_to_string_first_final = 13;
595 static const int dns_text_to_string_error = 0;
596
597 static const int dns_text_to_string_en_main = 1;
598
599
600 #line 601 "dnslabeltext.cc"
601 {
602 cs = dns_text_to_string_start;
603 }
604
605 #line 232 "dnslabeltext.rl"
606
607
608 // silence warnings
609 (void) dns_text_to_string_first_final;
610 (void) dns_text_to_string_error;
611 (void) dns_text_to_string_en_main;
612
613 #line 614 "dnslabeltext.cc"
614 {
615 int _klen;
616 unsigned int _trans;
617 const char *_acts;
618 unsigned int _nacts;
619 const char *_keys;
620
621 if ( p == pe )
622 goto _test_eof;
623 if ( cs == 0 )
624 goto _out;
625 _resume:
626 _keys = _dns_text_to_string_trans_keys + _dns_text_to_string_key_offsets[cs];
627 _trans = _dns_text_to_string_index_offsets[cs];
628
629 _klen = _dns_text_to_string_single_lengths[cs];
630 if ( _klen > 0 ) {
631 const char *_lower = _keys;
632 const char *_mid;
633 const char *_upper = _keys + _klen - 1;
634 while (1) {
635 if ( _upper < _lower )
636 break;
637
638 _mid = _lower + ((_upper-_lower) >> 1);
639 if ( (*p) < *_mid )
640 _upper = _mid - 1;
641 else if ( (*p) > *_mid )
642 _lower = _mid + 1;
643 else {
644 _trans += (unsigned int)(_mid - _keys);
645 goto _match;
646 }
647 }
648 _keys += _klen;
649 _trans += _klen;
650 }
651
652 _klen = _dns_text_to_string_range_lengths[cs];
653 if ( _klen > 0 ) {
654 const char *_lower = _keys;
655 const char *_mid;
656 const char *_upper = _keys + (_klen<<1) - 2;
657 while (1) {
658 if ( _upper < _lower )
659 break;
660
661 _mid = _lower + (((_upper-_lower) >> 1) & ~1);
662 if ( (*p) < _mid[0] )
663 _upper = _mid - 2;
664 else if ( (*p) > _mid[1] )
665 _lower = _mid + 2;
666 else {
667 _trans += (unsigned int)((_mid - _keys)>>1);
668 goto _match;
669 }
670 }
671 _trans += _klen;
672 }
673
674 _match:
675 _trans = _dns_text_to_string_indicies[_trans];
676 cs = _dns_text_to_string_trans_targs[_trans];
677
678 if ( _dns_text_to_string_trans_actions[_trans] == 0 )
679 goto _again;
680
681 _acts = _dns_text_to_string_actions + _dns_text_to_string_trans_actions[_trans];
682 _nacts = (unsigned int) *_acts++;
683 while ( _nacts-- > 0 )
684 {
685 switch ( *_acts++ )
686 {
687 case 0:
688 #line 194 "dnslabeltext.rl"
689 {
690 escaped_octet *= 10;
691 escaped_octet += (*p)-'0';
692 counter++;
693 }
694 break;
695 case 1:
696 #line 200 "dnslabeltext.rl"
697 {
698 val += escaped_octet;
699 escaped_octet = 0;
700 }
701 break;
702 case 2:
703 #line 205 "dnslabeltext.rl"
704 {
705 val += (*p);
706 counter++;
707 }
708 break;
709 case 3:
710 #line 210 "dnslabeltext.rl"
711 {
712 counter++;
713 }
714 break;
715 #line 716 "dnslabeltext.cc"
716 }
717 }
718
719 _again:
720 if ( cs == 0 )
721 goto _out;
722 if ( ++p != pe )
723 goto _resume;
724 _test_eof: {}
725 _out: {}
726 }
727
728 #line 239 "dnslabeltext.rl"
729
730 return counter;
731 }
732
parseSVCBValueListFromParsedRFC1035CharString(const std::string & in,std::vector<std::string> & val)733 size_t parseSVCBValueListFromParsedRFC1035CharString(const std::string &in, std::vector<std::string> &val) {
734 val.clear();
735 const char *p = in.c_str();
736 const char *pe = p + in.size();
737 int cs = 0;
738 const char* eof = pe;
739 // Keeps track of how many chars we read from the source string
740 size_t counter=0;
741
742 // Here we store the parsed value until we hit a comma or are done
743 std::string tmp;
744
745
746 #line 747 "dnslabeltext.cc"
747 static const char _dns_text_to_value_list_actions[] = {
748 0, 1, 0, 1, 2, 1, 3, 2,
749 2, 3, 2, 3, 1
750 };
751
752 static const char _dns_text_to_value_list_key_offsets[] = {
753 0, 0, 2, 4, 6
754 };
755
756 static const unsigned char _dns_text_to_value_list_trans_keys[] = {
757 44u, 92u, 44u, 92u, 44u, 92u, 44u, 92u,
758 0
759 };
760
761 static const char _dns_text_to_value_list_single_lengths[] = {
762 0, 2, 2, 2, 2
763 };
764
765 static const char _dns_text_to_value_list_range_lengths[] = {
766 0, 0, 0, 0, 0
767 };
768
769 static const char _dns_text_to_value_list_index_offsets[] = {
770 0, 0, 3, 6, 9
771 };
772
773 static const char _dns_text_to_value_list_indicies[] = {
774 1, 2, 0, 3, 3, 1, 1, 2,
775 0, 4, 2, 0, 0
776 };
777
778 static const char _dns_text_to_value_list_trans_targs[] = {
779 4, 0, 2, 4, 1
780 };
781
782 static const char _dns_text_to_value_list_trans_actions[] = {
783 1, 0, 5, 10, 7
784 };
785
786 static const char _dns_text_to_value_list_eof_actions[] = {
787 0, 0, 0, 0, 3
788 };
789
790 static const int dns_text_to_value_list_start = 3;
791 static const int dns_text_to_value_list_first_final = 3;
792 static const int dns_text_to_value_list_error = 0;
793
794 static const int dns_text_to_value_list_en_main = 3;
795
796
797 #line 798 "dnslabeltext.cc"
798 {
799 cs = dns_text_to_value_list_start;
800 }
801
802 #line 288 "dnslabeltext.rl"
803
804
805 // silence warnings
806 (void) dns_text_to_value_list_first_final;
807 (void) dns_text_to_value_list_error;
808 (void) dns_text_to_value_list_en_main;
809
810 #line 811 "dnslabeltext.cc"
811 {
812 int _klen;
813 unsigned int _trans;
814 const char *_acts;
815 unsigned int _nacts;
816 const unsigned char *_keys;
817
818 if ( p == pe )
819 goto _test_eof;
820 if ( cs == 0 )
821 goto _out;
822 _resume:
823 _keys = _dns_text_to_value_list_trans_keys + _dns_text_to_value_list_key_offsets[cs];
824 _trans = _dns_text_to_value_list_index_offsets[cs];
825
826 _klen = _dns_text_to_value_list_single_lengths[cs];
827 if ( _klen > 0 ) {
828 const unsigned char *_lower = _keys;
829 const unsigned char *_mid;
830 const unsigned char *_upper = _keys + _klen - 1;
831 while (1) {
832 if ( _upper < _lower )
833 break;
834
835 _mid = _lower + ((_upper-_lower) >> 1);
836 if ( (*p) < *_mid )
837 _upper = _mid - 1;
838 else if ( (*p) > *_mid )
839 _lower = _mid + 1;
840 else {
841 _trans += (unsigned int)(_mid - _keys);
842 goto _match;
843 }
844 }
845 _keys += _klen;
846 _trans += _klen;
847 }
848
849 _klen = _dns_text_to_value_list_range_lengths[cs];
850 if ( _klen > 0 ) {
851 const unsigned char *_lower = _keys;
852 const unsigned char *_mid;
853 const unsigned char *_upper = _keys + (_klen<<1) - 2;
854 while (1) {
855 if ( _upper < _lower )
856 break;
857
858 _mid = _lower + (((_upper-_lower) >> 1) & ~1);
859 if ( (*p) < _mid[0] )
860 _upper = _mid - 2;
861 else if ( (*p) > _mid[1] )
862 _lower = _mid + 2;
863 else {
864 _trans += (unsigned int)((_mid - _keys)>>1);
865 goto _match;
866 }
867 }
868 _trans += _klen;
869 }
870
871 _match:
872 _trans = _dns_text_to_value_list_indicies[_trans];
873 cs = _dns_text_to_value_list_trans_targs[_trans];
874
875 if ( _dns_text_to_value_list_trans_actions[_trans] == 0 )
876 goto _again;
877
878 _acts = _dns_text_to_value_list_actions + _dns_text_to_value_list_trans_actions[_trans];
879 _nacts = (unsigned int) *_acts++;
880 while ( _nacts-- > 0 )
881 {
882 switch ( *_acts++ )
883 {
884 case 0:
885 #line 259 "dnslabeltext.rl"
886 {
887 tmp += (*p);
888 counter++;
889 }
890 break;
891 case 1:
892 #line 264 "dnslabeltext.rl"
893 {
894 tmp += (*p);
895 }
896 break;
897 case 2:
898 #line 268 "dnslabeltext.rl"
899 {
900 val.push_back(tmp);
901 tmp.clear();
902 counter++;
903 }
904 break;
905 case 3:
906 #line 274 "dnslabeltext.rl"
907 {
908 counter++;
909 }
910 break;
911 #line 912 "dnslabeltext.cc"
912 }
913 }
914
915 _again:
916 if ( cs == 0 )
917 goto _out;
918 if ( ++p != pe )
919 goto _resume;
920 _test_eof: {}
921 if ( p == eof )
922 {
923 const char *__acts = _dns_text_to_value_list_actions + _dns_text_to_value_list_eof_actions[cs];
924 unsigned int __nacts = (unsigned int) *__acts++;
925 while ( __nacts-- > 0 ) {
926 switch ( *__acts++ ) {
927 case 2:
928 #line 268 "dnslabeltext.rl"
929 {
930 val.push_back(tmp);
931 tmp.clear();
932 counter++;
933 }
934 break;
935 #line 936 "dnslabeltext.cc"
936 }
937 }
938 }
939
940 _out: {}
941 }
942
943 #line 295 "dnslabeltext.rl"
944
945 if ( cs < dns_text_to_value_list_first_final ) {
946 throw runtime_error("Unable to parse DNS SVCB value list '"+in+"'");
947 }
948
949 return counter;
950 }
951
952
953 #if 0
954 int main()
955 {
956 //char blah[]="\"blah\" \"bleh\" \"bloeh\\\"bleh\" \"\\97enzo\"";
957 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\"";
958 //char blah[]="\"abc \\097\\098 def\"";
959 printf("Input: '%s'\n", blah);
960 vector<string> res=dnstext(blah);
961 cerr<<res.size()<<" segments"<<endl;
962 cerr<<res[0]<<endl;
963 }
964 #endif
965