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