1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup dnspacket DNS Messages
36  *  @ingroup dnscore
37  *  @brief
38  *
39  * @{
40  */
41 /*------------------------------------------------------------------------------
42  *
43  * USE INCLUDES */
44 #include "dnscore/dnscore-config.h"
45 
46 #include <unistd.h>
47 #include <stddef.h>
48 #include <fcntl.h>
49 
50 #include "dnscore/message.h"
51 #include "dnscore/logger.h"
52 #include "dnscore/dnscore.h"
53 #include "dnscore/format.h"
54 #include "dnscore/fingerprint.h"
55 #include "dnscore/packet_reader.h"
56 #include "dnscore/packet_writer.h"
57 #include "dnscore/tsig.h"
58 #include "dnscore/fdtools.h"
59 #include "dnscore/tcp_io_stream.h"
60 #include "dnscore/counter_output_stream.h"
61 #include "dnscore/network.h"
62 
63 #include "dnscore/thread_pool.h"
64 
65 #if HAS_CTRL
66 #include "dnscore/ctrl-rfc.h"
67 #endif
68 
69 /*------------------------------------------------------------------------------
70  * GLOBAL VARIABLES */
71 
72 extern logger_handle *g_system_logger;
73 #define MODULE_MSG_HANDLE g_system_logger
74 
75 
76 
77 #define		SA_LOOP                 3
78 #define		SA_PRINT                4
79 
80 /*------------------------------------------------------------------------------
81  * FUNCTIONS */
82 
83 u16 edns0_maxsize = EDNS0_MAX_LENGTH;
84 
85 double g_message_data_minimum_troughput_default = 0;
86 
message_set_minimum_troughput_default(double rate)87 void message_set_minimum_troughput_default(double rate)
88 {
89     if(rate >= 0)
90     {
91         g_message_data_minimum_troughput_default = rate;
92     }
93 }
94 
message_edns0_setmaxsize(u16 maxsize)95 void message_edns0_setmaxsize(u16 maxsize)
96 {
97     edns0_maxsize = maxsize;
98 }
99 
message_edns0_getmaxsize()100 u16 message_edns0_getmaxsize()
101 {
102     return edns0_maxsize;
103 }
104 
105 // Handles OPT and TSIG
106 
message_process_adjust_buffer_size(message_data * mesg,u16 edns0_size)107 static inline void message_process_adjust_buffer_size(message_data *mesg, u16 edns0_size)
108 {
109     u32 mesg_buffer_size = message_get_buffer_size_max(mesg);
110     u32 query_buffer_size = edns0_size;
111     if(mesg_buffer_size > query_buffer_size)
112     {
113         mesg_buffer_size = query_buffer_size;
114         if(mesg_buffer_size < EDNS0_MIN_LENGTH)
115         {
116             mesg_buffer_size = EDNS0_MIN_LENGTH;
117         }
118     }
119     message_set_buffer_size(mesg, mesg_buffer_size);
120 }
121 
122 static ya_result
message_process_additionals(message_data * mesg,u8 * s,u16 ar_count)123 message_process_additionals(message_data *mesg, u8* s, u16 ar_count)
124 {
125     (void)s;
126     /*
127      * @note: I've moved this in the main function (the one calling this one)
128      */
129 
130     //yassert(ar_count != 0 && ar_count == message_get_additional_count(mesg));
131 
132     u8 *buffer = mesg->_buffer;
133     ya_result  ret;
134 
135     ar_count = ntohs(MESSAGE_AR(buffer));
136 
137     /*
138      * rfc2845
139      *
140      * If there is a TSIG then
141      * _ It must be put aside, safely
142      * _ It must be removed from the query
143      * _ It must be processed
144      *
145      * rfc2671
146      *
147      * Handle OPT
148      *
149      */
150 
151     /*
152      * Read DNS name (decompression on)
153      * Read type (TSIG = 250)
154      * Read class (ANY)
155      * Read TTL (0)
156      * Read RDLEN
157      *
158      */
159 
160     u32 query_end = message_get_size(mesg);
161 
162     packet_unpack_reader_data purd;
163     purd.packet = buffer;
164     purd.packet_size = query_end;
165 
166     if(mesg->_ar_start == NULL)
167     {
168         u32 ar_index = ntohs(MESSAGE_AN(buffer)) + ntohs(MESSAGE_NS(buffer));
169 
170         purd.offset = DNS_HEADER_LENGTH;        // header
171         packet_reader_skip_fqdn(&purd);         // checked below
172         if(FAIL(packet_reader_skip(&purd, 4)))  // type class
173         {
174             message_set_status(mesg, FP_ERROR_READING_QUERY);
175             return UNPROCESSABLE_MESSAGE;
176         }
177 
178         while(ar_index > 0) /* Skip all until AR records */
179         {
180             /*
181              * It should be in this kind of processing that we read the EDNS0 flag
182              */
183 
184             if(FAIL(ret = packet_reader_skip_record(&purd)))
185             {
186                 message_set_status(mesg, FP_ERROR_READING_QUERY);
187                 return UNPROCESSABLE_MESSAGE;
188             }
189 
190             ar_index--;
191         }
192 
193         query_end = purd.offset; // ready to remove all additionals in one fell swoop
194 
195         mesg->_ar_start = &mesg->_buffer[purd.offset];
196     }
197     else
198     {
199         purd.offset = message_get_additional_section_ptr(mesg) - mesg->_buffer;
200     }
201 
202     /* We are now at the start of the ar */
203 
204     struct type_class_ttl_rdlen tctr;
205     u8 tsigname[MAX_DOMAIN_LENGTH];
206 #if DNSCORE_HAS_TSIG_SUPPORT
207     u32 record_offset;
208 #endif
209 
210     while(ar_count-- > 0)
211     {
212 #if DNSCORE_HAS_TSIG_SUPPORT
213         record_offset = purd.offset;
214 #endif
215 
216         if(FAIL(packet_reader_read_fqdn(&purd, tsigname, sizeof(tsigname))))
217         {
218             /* oops */
219 
220             message_set_status(mesg, FP_ERROR_READING_QUERY);
221 
222             return UNPROCESSABLE_MESSAGE;
223         }
224 
225         if(packet_reader_read(&purd, &tctr, 10) == 10 ) // exact
226         {
227             /*
228              * EDNS (0)
229              */
230 
231             if(tctr.qtype == TYPE_OPT)
232             {
233                 /**
234                  * Handle EDNS
235                  */
236 
237                 if((tctr.ttl & NU32(0x00ff0000)) == 0) /* ensure version is 0 */
238                 {
239                     u32 rdlen = ntohs(tctr.rdlen);
240 
241 #if DNSCORE_HAS_NSID_SUPPORT
242                     if(rdlen != 0)
243                     {
244                         u32 next = purd.offset + rdlen;
245                         for(s32 remain = (s32)rdlen; remain >= 4; remain -= 4)
246                         {
247                             u32 opt_type_size;
248 
249                             if(ISOK(packet_reader_read_u32(&purd, &opt_type_size))) // read the option-code and the option-length in one operation
250                             {
251                                 if(opt_type_size == NU32(0x00030000)) // check if it's NSID
252                                 {
253                                     // nsid
254                                     mesg->_nsid = TRUE;
255                                     break;
256                                 }
257 
258                                 u32 opt_type_len = ntohl(opt_type_size) & 0xffff;
259 
260                                 if(FAIL(packet_reader_skip(&purd, opt_type_len)))   // skip the data
261                                 {
262                                     return UNPROCESSABLE_MESSAGE;
263                                 }
264 
265                                 remain -= opt_type_len;
266                             }
267                             else
268                             {
269                                 break;
270                             }
271                         }
272 
273                         if(FAIL(packet_reader_skip(&purd, next - purd.offset)))
274                         {
275                             return UNPROCESSABLE_MESSAGE;
276                         }
277                     }
278 #else
279                     if(FAIL(packet_reader_skip(&purd, rdlen)))
280                     {
281                         return UNPROCESSABLE_MESSAGE;
282                     }
283 #endif
284                     if(tsigname[0] == '\0')
285                     {
286                         message_process_adjust_buffer_size(mesg, ntohs(tctr.qclass));
287 
288                         mesg->_edns = TRUE;
289                         mesg->_rcode_ext = tctr.ttl;
290 #if DEBUG
291                         log_debug("EDNS: udp-size=%d rcode-ext=%08x desc=%04x", message_get_size(mesg), tctr.ttl, rdlen);
292 #endif
293                         continue;
294                     }
295 #if DEBUG
296                     log_debug("OPT record is not processable (broken)");
297 #endif
298                     return UNPROCESSABLE_MESSAGE;
299                 }
300                 else
301                 {
302                     message_set_status(mesg, FP_EDNS_BAD_VERSION);
303                     message_process_adjust_buffer_size(mesg, ntohs(tctr.qclass));
304 
305                     mesg->_edns = TRUE;
306                     mesg->_rcode_ext = 0;
307 #if DEBUG
308                    log_debug("OPT record is not processable (not supported)");
309 #endif
310                    return MAKE_DNSMSG_ERROR(FP_EDNS_BAD_VERSION);
311                 }
312             }
313 #if DNSCORE_HAS_TSIG_SUPPORT
314             /*
315              * TSIG
316              */
317 
318             else if(tctr.qtype == TYPE_TSIG)
319             {
320                 if(ar_count == 0)
321                 {
322                     /*
323                      * It looks like a TSIG ...
324                      */
325 
326                     ya_result return_code;
327 
328                     if(message_isquery(mesg))
329                     {
330                         if(FAIL(return_code = tsig_process_query(mesg, &purd, record_offset, tsigname, &tctr)))
331                         {
332 #if DEBUG
333                             // this should be reported above
334                             log_notice("%r query error from %{sockaddr}", return_code, message_get_sender_sa(mesg));
335 #endif
336                             return return_code;
337                         }
338                     }
339                     else
340                     {
341                         tsig_item *key = tsig_get(tsigname);
342 
343                         if(key != NULL)
344                         {
345                             if(FAIL(return_code = tsig_process(mesg, &purd, record_offset, key, &tctr)))
346                             {
347 #if DEBUG
348                                 // this should be reported above
349                                 log_notice("%r answer error from %{sockaddr}", return_code, message_get_sender_sa(mesg));
350 #endif
351                                 return return_code;
352                             }
353                         }
354                         else
355                         {
356                             log_notice("answer error from %{sockaddr}: TSIG when none expected", message_get_sender_sa(mesg));
357 
358                             message_set_status(mesg, FP_TSIG_UNEXPECTED);
359 
360                             return MAKE_DNSMSG_ERROR(FP_TSIG_UNEXPECTED);
361                         }
362                     }
363 
364                     break;  /* we know there is no need to loop anymore */
365                 }
366                 else
367                 {
368                     /*
369                      * Error: TSIG is not the last AR record
370                      */
371 
372 #if DEBUG
373                     log_debug("TSIG record is not the last AR");
374 #endif
375 
376                     message_set_status(mesg, FP_TSIG_IS_NOT_LAST);
377 
378                     return UNPROCESSABLE_MESSAGE;
379                 }
380             }
381 #endif
382             else
383             {
384                 /* Unhandled AR TYPE */
385 
386                 log_debug("unhandled AR type %{dnstype}", &tctr.qtype);
387 
388                 message_set_status(mesg, FP_UNEXPECTED_RR_IN_QUERY);
389 
390                 return UNPROCESSABLE_MESSAGE;
391             }
392         }
393     } /* While there are AR to process */
394 
395     message_set_additional_count_ne(mesg, 0);
396     message_set_size(mesg, query_end);
397 
398     return SUCCESS;
399 }
400 
401 /**
402  * Handles the OPT and TSIG records of an answer.
403  *
404  * @param mesg
405  * @param ar_count
406  * @return
407  */
408 
409 static ya_result
message_process_answer_additionals(message_data * mesg,u16 ar_count)410 message_process_answer_additionals(message_data *mesg, u16 ar_count /* network order */ )
411 {
412     /*
413      * @note: I've moved this in the main function (the one calling this one)
414      */
415 
416     yassert(ar_count != 0 && ar_count == message_get_additional_count_ne(mesg));
417 
418     u8 *buffer = message_get_buffer(mesg);
419 
420     ar_count = ntohs(ar_count);
421 
422     /*
423      * rfc2845
424      *
425      * If there is a TSIG then
426      * _ It must be put aside, safely
427      * _ It must be removed from the query
428      * _ It must be processed
429      *
430      * rfc2671
431      *
432      * Handle OPT
433      *
434      */
435 
436     /*
437      * Read DNS name (decompression on)
438      * Read type (TSIG = 250)
439      * Read class (ANY)
440      * Read TTL (0)
441      * Read RDLEN
442      *
443      */
444 
445     u32 message_size = message_get_size(mesg);
446 
447     packet_unpack_reader_data purd;
448     purd.packet = buffer;
449     purd.packet_size = message_size;
450     u16 ar_sub = 0;
451 
452     if(mesg->_ar_start == NULL)
453     {
454         u32 ar_index = ntohs(MESSAGE_AN(buffer)) + ntohs(MESSAGE_NS(buffer));
455 
456         purd.offset = DNS_HEADER_LENGTH;    // header
457         packet_reader_skip_fqdn(&purd);     // checked below
458         if(FAIL(packet_reader_skip_bytes(&purd, 4))) // type class
459         {
460             return UNPROCESSABLE_MESSAGE;
461         }
462 
463         while(ar_index > 0) /* Skip all until AR records */
464         {
465             /*
466              * It should be in this kind of processing that we read the EDNS0 flag
467              */
468 
469             if(FAIL(packet_reader_skip_record(&purd)))
470             {
471                 return UNPROCESSABLE_MESSAGE;
472             }
473 
474             ar_index--;
475         }
476 
477         message_size = purd.offset;
478 
479         mesg->_ar_start = &mesg->_buffer[purd.offset];
480     }
481     else
482     {
483         purd.offset = message_get_additional_section_ptr(mesg) - mesg->_buffer; // size up to additional sections
484     }
485 
486     /* We are now at the start of the ar */
487 
488     struct type_class_ttl_rdlen tctr;
489     u8 tsigname[MAX_DOMAIN_LENGTH];
490 
491 #if DNSCORE_HAS_TSIG_SUPPORT
492     u32 record_offset;
493 #endif
494 
495     while(ar_count-- > 0)
496     {
497 #if DNSCORE_HAS_TSIG_SUPPORT
498         record_offset = purd.offset;
499 #endif
500         if(FAIL(packet_reader_read_fqdn(&purd, tsigname, sizeof(tsigname))))
501         {
502             /* oops */
503 
504             message_set_status(mesg, FP_ERROR_READING_QUERY);
505 
506             return UNPROCESSABLE_MESSAGE;
507         }
508 
509         if(packet_reader_read(&purd, &tctr, 10) == 10 ) // exact
510         {
511             /*
512              * EDNS (0)
513              */
514 
515             if(tctr.qtype == TYPE_OPT)
516             {
517                 /**
518                  * Handle EDNS
519                  */
520 
521                 if((tctr.ttl & NU32(0x00ff0000)) == 0) /* ensure version is 0 */
522                 {
523                     if(tsigname[0] == '\0')
524                     {
525                         ++ar_sub;
526 
527                         mesg->_edns = TRUE;
528                         mesg->_rcode_ext = tctr.ttl;
529 
530                         log_debug("EDNS: udp-size=%d rcode-ext=%08x desc=%04x", message_get_buffer_size(mesg), tctr.ttl, ntohs(tctr.rdlen));
531                         continue;
532                     }
533                 }
534                 else
535                 {
536                    mesg->_edns = TRUE;
537                    mesg->_rcode_ext = tctr.ttl;
538                 }
539 
540                 log_debug("OPT record is not processable (broken or not supported)");
541 
542                 return UNPROCESSABLE_MESSAGE;
543             }
544 #if DNSCORE_HAS_TSIG_SUPPORT
545 
546             /*
547              * TSIG
548              */
549 
550             else if(tctr.qtype == TYPE_TSIG)
551             {
552                 if(ar_count == 0)
553                 {
554                     /*
555                      * It looks like a TSIG ...
556                      */
557 
558                     ya_result return_code;
559 
560                     if(message_isquery(mesg))
561                     {
562                         if(FAIL(return_code = tsig_process_query(mesg, &purd, record_offset, tsigname, &tctr)))
563                         {
564                             log_err("%r query error from %{sockaddr}", return_code, message_get_sender_sa(mesg));
565                             return UNPROCESSABLE_MESSAGE;
566                         }
567                     }
568                     else // not a query (an answer)
569                     {
570                         if(message_has_tsig(mesg))
571                         {
572                             if(dnsname_equals(tsigname, message_tsig_get_name(mesg)))
573                             {
574                                 if(FAIL(return_code = tsig_process_answer(mesg, &purd, record_offset, &tctr)))
575                                 {
576                                     log_err("%r answer error from %{sockaddr}", return_code, message_get_sender_sa(mesg));
577                                     return UNPROCESSABLE_MESSAGE;
578                                 }
579                             }
580                             else
581                             {
582                                 log_err("TSIG name mismatch from %{sockaddr}", message_get_sender_sa(mesg));
583 
584                                 return UNPROCESSABLE_MESSAGE;
585                             }
586                         }
587                         else // no tsig
588                         {
589                             log_err("answer error from %{sockaddr}: TSIG when none expected", message_get_sender_sa(mesg));
590 
591                             message_set_status(mesg, FP_TSIG_UNEXPECTED);
592 
593                             return UNPROCESSABLE_MESSAGE;
594                         }
595                     }
596 
597                     break;  /* we know there is no need to loop anymore */
598                 }
599                 else
600                 {
601                     /*
602                      * Error: TSIG is not the last AR record
603                      */
604 
605                     log_debug("TSIG record is not the last AR");
606 
607                     message_set_status(mesg, FP_TSIG_IS_NOT_LAST);
608 
609                     return UNPROCESSABLE_MESSAGE;
610                 }
611             }
612 #endif
613             else
614             {
615                 /* Unhandled AR TYPE */
616 #if DEBUG
617                 log_debug("skipping AR type %{dnstype}", &tctr.qtype);
618 #endif
619                 purd.offset += ntohs(tctr.rdlen);
620 
621                 message_size = purd.offset;
622             }
623         }
624     } /* While there are AR to process */
625 
626     //message_sub_additional_count(mesg, 1);
627 
628     message_set_additional_count_ne(mesg, 0);
629     message_set_size(mesg, message_size);
630 
631     return SUCCESS;
632 }
633 
634 /** \brief Processing DNS packet
635  *
636  *  @param mesg
637  *
638  *  @retval OK
639  *  @return status of message is written in message_get_status(mesg)
640  */
641 
642 /* Defines a mask and the expected result for the 4 first 16 bits of the header */
643 #ifdef WORDS_BIGENDIAN
644 #define MESSAGE_HEADER_MASK     (( (u64) 0 )                        |  \
645         ( ((u64) ( QR_BITS | AA_BITS | RA_BITS | TC_BITS )) << 40 ) |  \
646         ( ((u64) ( RA_BITS | RCODE_BITS )) << 32 )                  |  \
647         ( ((u64) 1LL) << 16 ))
648 
649 #define MESSAGE_HEADER_RESULT   ( ((u64) 1LL) << 16 )
650 
651 /* Bind gives "RA" here (seems irrelevant, nonsense, but we need to accept it) */
652 
653 #define NOTIFY_MESSAGE_HEADER_MASK     (( (u64) 0LL )             |  \
654         ( ((u64) ( TC_BITS )) << 40 )                             |  \
655         ( ((u64) 1LL) << 16 ))
656 
657 #define NOTIFY_MESSAGE_HEADER_RESULT   ( ((u64) 1LL) << 16 )
658 
659 #else
660 
661 #define MESSAGE_HEADER_MASK     (( (u64) 0LL )                      |  \
662         ( ((u64) ( QR_BITS | AA_BITS | RA_BITS | TC_BITS )) << 16 ) |  \
663         ( ((u64) ( RA_BITS | RCODE_BITS )) << 24 )                  |  \
664         ( ((u64) 1LL) << 40 ))
665 
666 #define MESSAGE_HEADER_RESULT   ( ((u64) 1LL) << 40 )
667 
668 /* Bind gives "RA" here (seems irrelevant, nonsense, but we need to accept it) */
669 
670 #define NOTIFY_MESSAGE_HEADER_MASK     (( (u64) 0LL )             |  \
671         ( ((u64) ( TC_BITS )) << 16 )                             |  \
672         ( ((u64) 1LL) << 40 ))
673 
674 #define NOTIFY_MESSAGE_HEADER_RESULT   ( ((u64) 1LL) << 40 )
675 
676 #endif
677 
678 /* EDF: this takes about 150 cycles [144;152] with peaks at 152 */
679 
680 /**
681  * Canonises the query:
682  * _ copies the query fqdn lowercase
683  * _ copies the query type and class for easy access
684  *
685  * (should be renamed to message_query_canonise or something of that effect)
686  *
687  * @param mesg
688  * @return a pointer to the answer section (or more accurately, just after the class of the (first) query
689  */
690 
691 static inline u8*
message_process_copy_fqdn(message_data * mesg)692 message_process_copy_fqdn(message_data *mesg)
693 {
694     u8 *src = message_get_query_section_ptr(mesg);
695     u8 *dst = &mesg->_canonised_fqdn[0];
696 
697     u8 *base = dst;
698     u32 len;
699 
700     for(;;)
701     {
702         len = *src++;
703         *dst++ = len;
704 
705         if(len == 0)
706         {
707             break;
708         }
709 
710         if( (len & 0xC0) == 0 )
711         {
712             const u8 * const limit = dst + len;
713 
714             if(limit - base < MAX_DOMAIN_LENGTH)
715             {
716                 do
717                 {
718                     *dst++ = LOCASE(*src++); /* Works with the dns character set */
719                 }
720                 while(dst < limit);
721             }
722             else
723             {
724                 message_set_status(mesg, FP_NAME_TOO_LARGE);
725 
726                 DERROR_MSG("FP_NAME_TOO_LARGE");
727 
728                 return NULL;
729             }
730         }
731         else
732         {
733             message_set_status(mesg, ((len & 0xC0)==0xC0)?FP_QNAME_COMPRESSED:FP_NAME_FORMAT_ERROR);
734 
735             return NULL;
736         }
737     }
738 
739     /* Get qtype & qclass */
740 
741     mesg->_query_type  = GET_U16_AT(src[0]); /** @note : NATIVETYPE  */
742     mesg->_query_class = GET_U16_AT(src[2]); /** @note : NATIVECLASS */
743 
744     // the next section starts at &src[4]
745 
746     return &src[4];
747 }
748 
749 ya_result
message_process_query(message_data * mesg)750 message_process_query(message_data *mesg)
751 {
752     u8 *buffer = message_get_buffer(mesg);
753 
754     /** CHECK DNS HEADER */
755     /** Drop dns packet if query is answer or does not have correct header length */
756 
757     /*
758      * +5 <=> 1 qd record ar least
759      */
760 
761     u64 *h64 = (u64*)buffer;
762     u64 m64 = MESSAGE_HEADER_MASK;
763     u64 r64 = MESSAGE_HEADER_RESULT;
764 
765     if((message_get_size(mesg) < DNS_HEADER_LENGTH + 5) ||
766             ((  *h64 & m64) != r64 ) )
767     {
768         /** Return if QDCOUNT is not 1
769          *
770          *  @note Previous test was actually testing if QDCOUNT was > 1
771          *        I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT
772          */
773 
774         if(MESSAGE_QR(buffer))
775         {
776             message_set_status(mesg, FP_QR_BIT_SET);
777             return INVALID_MESSAGE;
778         }
779 
780         MESSAGE_FLAGS_AND(buffer, OPCODE_BITS|RD_BITS, 0);
781 
782         if(NETWORK_ONE_16 != MESSAGE_QD(buffer))
783         {
784             if(0 == MESSAGE_QD(buffer))
785             {
786                 DERROR_MSG("FP_QDCOUNT_IS_0");
787                 message_set_status(mesg, FP_QDCOUNT_IS_0);
788                 return INVALID_MESSAGE; /* will be dropped */
789             }
790             else
791             {
792                 DERROR_MSG("FP_QDCOUNT_BIG_1");
793                 message_set_status(mesg, FP_QDCOUNT_BIG_1);
794             }
795         }
796         else if(MESSAGE_NS(buffer) != 0)
797         {
798             message_set_status(mesg, FP_NSCOUNT_NOT_0);
799         }
800         else
801         {
802             message_set_status(mesg, FP_PACKET_DROPPED);
803         }
804 
805         return UNPROCESSABLE_MESSAGE;
806     }
807 
808     /**
809      * @note Past this point, a message could be processable.
810      *       It's the right place to reset the message's defaults.
811      *
812      */
813 
814     message_reset_buffer_size(mesg);
815     mesg->_ar_start = NULL;
816 #if DNSCORE_HAS_TSIG_SUPPORT
817     mesg->_tsig.tsig  = NULL;
818 #endif
819     mesg->_rcode_ext  = 0;
820     mesg->_edns       = FALSE;
821 #if DNSCORE_HAS_NSID_SUPPORT
822     mesg->_nsid       = FALSE;
823 #endif
824 
825     u8 *s = message_process_copy_fqdn(mesg);
826 
827     if(s == NULL)
828     {
829         message_set_status(mesg, FP_NAME_FORMAT_ERROR);
830         return UNPROCESSABLE_MESSAGE;
831     }
832 
833     /*
834      * Handle the OPT and TSIG records
835      */
836 
837     {
838         ya_result return_code;
839         u32 nsar_count;
840 
841         if((nsar_count = MESSAGE_NSAR(buffer)) != 0)
842         {
843             if(FAIL(return_code = message_process_additionals(mesg, s, nsar_count)))
844             {
845                 //message_set_size(mesg, s - buffer);
846 
847                 return return_code;
848             }
849         }
850 
851         if(message_get_query_type(mesg) != TYPE_IXFR)
852         {
853             message_set_size(mesg, s - buffer);
854         }
855     }
856 
857     /* cut the trash here */
858 
859 
860     /* At this point the TSIG has been computed and removed */
861     /* Clear zome bits */
862     message_apply_mask(mesg, ~(QR_BITS|TC_BITS|AA_BITS), ~(Z_BITS|AD_BITS|CD_BITS|RA_BITS|RCODE_BITS));
863     //MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS|RCODE_BITS);
864 
865     message_set_status(mesg, FP_MESG_OK);
866 
867     return SUCCESS;
868 }
869 
870 int
message_process(message_data * mesg)871 message_process(message_data *mesg)
872 {
873     u8 *buffer = message_get_buffer(mesg);
874 
875     switch(MESSAGE_OP(buffer))
876     {
877         case OPCODE_QUERY:
878         {
879             /** CHECK DNS HEADER */
880             /** Drop dns packet if query is answer or does not have correct header length */
881 
882             /*
883              * +5 <=> 1 qd record ar least
884              */
885 
886             u64 *h64 = (u64*)buffer;
887             u64 m64 = MESSAGE_HEADER_MASK;
888             u64 r64 = MESSAGE_HEADER_RESULT;
889 
890             if(     (message_get_size(mesg) < DNS_HEADER_LENGTH + 5) ||
891                     ((  *h64 & m64) != r64 ) )
892             {
893                 /** Return if QDCOUNT is not 1
894                  *
895                  *  @note Previous test was actually testing if QDCOUNT was > 1
896                  *        I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT
897                  */
898 
899                 if(MESSAGE_QR(buffer))
900                 {
901                     message_set_status(mesg, FP_QR_BIT_SET);
902                     return INVALID_MESSAGE;
903                 }
904 
905                 MESSAGE_FLAGS_AND(buffer, OPCODE_BITS|RD_BITS, 0);
906 
907                 if(NETWORK_ONE_16 != MESSAGE_QD(buffer))
908                 {
909                     if(0 == MESSAGE_QD(buffer))
910                     {
911                         DERROR_MSG("FP_QDCOUNT_IS_0");
912 
913                         message_set_status(mesg, FP_QDCOUNT_IS_0);
914 
915                         return INVALID_MESSAGE; /* will be dropped */
916                     }
917                     else
918                     {
919                         message_set_status(mesg, FP_QDCOUNT_BIG_1);
920 
921                         DERROR_MSG("FP_QDCOUNT_BIG_1");
922                     }
923                 }
924                 else if( MESSAGE_NS(buffer) != 0)
925                 {
926                     message_set_status(mesg, FP_NSCOUNT_NOT_0);
927                 }
928                 else
929                 {
930                     message_set_status(mesg, FP_PACKET_DROPPED);
931                 }
932 
933                 return UNPROCESSABLE_MESSAGE;
934             }
935 
936 
937 
938             /**
939              * @note Past this point, a message could be processable.
940              *       It's the right place to reset the message's defaults.
941              *
942              */
943 
944             message_reset_buffer_size(mesg);
945             mesg->_ar_start   = NULL;
946 #if DNSCORE_HAS_TSIG_SUPPORT
947             mesg->_tsig.tsig  = NULL;
948 #endif
949             mesg->_rcode_ext  = 0;
950             mesg->_edns       = FALSE;
951 #if DNSCORE_HAS_NSID_SUPPORT
952             mesg->_nsid       = FALSE;
953 #endif
954             u8 *s = message_process_copy_fqdn(mesg);
955 
956             if(s == NULL)
957             {
958                 message_set_status(mesg, FP_NAME_FORMAT_ERROR);
959                 return UNPROCESSABLE_MESSAGE;
960             }
961 
962 
963 
964             /*
965              * Handle the OPT and TSIG records
966              */
967 
968             {
969                 ya_result return_code;
970                 u32 nsar_count;
971 
972                 if((nsar_count = MESSAGE_NSAR(buffer)) != 0)
973                 {
974                     if(FAIL(return_code = message_process_additionals(mesg, s, nsar_count)))
975                     {
976                         message_set_size(mesg, s - buffer);
977 
978                         return return_code;
979                     }
980                 }
981 
982                 if(message_get_query_type(mesg) != TYPE_IXFR)
983                 {
984                     message_set_size(mesg, s - buffer);
985                 }
986             }
987 
988             /* At this point the TSIG has been computed and removed */
989             /* Clear zome bits */
990             message_apply_mask(mesg, ~(QR_BITS|TC_BITS|AA_BITS), ~(Z_BITS|RA_BITS|AD_BITS|CD_BITS|RCODE_BITS));
991 
992             message_set_status(mesg, FP_MESG_OK);
993 
994             return OK;
995         }
996         case OPCODE_NOTIFY:
997         {
998             MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS);
999 
1000 
1001             /*    ------------------------------------------------------------    */
1002 
1003             /** CHECK DNS HEADER */
1004             /** Drop dns packet if query is answer or does not have correct header length */
1005 
1006             /*
1007              * +5 <=> 1 qd record ar least
1008              */
1009 
1010             u64 *h64 = (u64*)buffer;
1011             u64 m64 = NOTIFY_MESSAGE_HEADER_MASK;
1012             u64 r64 = NOTIFY_MESSAGE_HEADER_RESULT;
1013             /* ... A400 0001 ... */
1014             if(     (message_get_size(mesg) < DNS_HEADER_LENGTH + 5) ||
1015                     ((  *h64 & m64) != r64 ) )
1016             {
1017                 /** Return if QDCOUNT is not 1
1018                  *
1019                  *  @note Previous test was actually testing if QDCOUNT was > 1
1020                  *        I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT
1021                  */
1022                 MESSAGE_FLAGS_AND(buffer, OPCODE_BITS, 0);
1023 
1024 
1025                 if(NETWORK_ONE_16 != MESSAGE_QD(buffer))
1026                 {
1027                     if(0 == MESSAGE_QD(buffer))
1028                     {
1029                         DERROR_MSG("FP_QDCOUNT_IS_0");
1030                         message_set_status(mesg, FP_QDCOUNT_IS_0);
1031                         return INVALID_MESSAGE;
1032                     }
1033                     else
1034                     {
1035                         message_set_status(mesg, FP_QDCOUNT_BIG_1);
1036 
1037                         DERROR_MSG("FP_QDCOUNT_BIG_1");
1038                     }
1039                 }
1040                 else
1041                 {
1042                     message_set_status(mesg, FP_PACKET_DROPPED);
1043                 }
1044 
1045                 return UNPROCESSABLE_MESSAGE;
1046             }
1047 
1048 
1049 
1050             u8 *s = message_process_copy_fqdn(mesg);
1051 
1052             if(s == NULL)
1053             {
1054                 message_set_status(mesg, FP_NAME_FORMAT_ERROR);
1055                 return UNPROCESSABLE_MESSAGE;
1056             }
1057 
1058 
1059 
1060             /**
1061              * @note Past this point, a message could be processable.
1062              *       It's the right place to reset the message's defaults.
1063              *
1064              */
1065 
1066             message_reset_buffer_size(mesg);
1067             mesg->_ar_start  = NULL;
1068 #if DNSCORE_HAS_TSIG_SUPPORT
1069             mesg->_tsig.tsig  = NULL;
1070 #endif
1071             mesg->_rcode_ext  = 0;
1072             mesg->_edns       = FALSE;
1073 #if DNSCORE_HAS_NSID_SUPPORT
1074             mesg->_nsid       = FALSE;
1075 #endif
1076             /*
1077              * If there is a TSIG, it is here ...
1078              */
1079 
1080 #if DNSCORE_HAS_TSIG_SUPPORT
1081             {
1082                 ya_result return_code;
1083                 u16 ar_count;
1084 
1085                 if((ar_count = MESSAGE_AR(buffer)) != 0)
1086                 {
1087                     if(FAIL(return_code = message_process_additionals(mesg, s, ar_count)))
1088                     {
1089                         return return_code;
1090                     }
1091                 }
1092             }
1093 #endif
1094             /* At this point the TSIG has been computed and removed */
1095 
1096             message_set_status(mesg, FP_MESG_OK);
1097 
1098             return OK;
1099         }
1100         case OPCODE_UPDATE:
1101         {
1102             MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS|RCODE_BITS);
1103 
1104 
1105             /*    ------------------------------------------------------------    */
1106 
1107             /** CHECK DNS HEADER */
1108             /** Drop dns packet if query is answer or does not have correct header length */
1109 
1110             /*
1111              * +5 <=> 1 qd record ar least
1112              */
1113 
1114             u64 *h64 = (u64*)buffer;
1115             u64 m64 = MESSAGE_HEADER_MASK;
1116             u64 r64 = MESSAGE_HEADER_RESULT;
1117 
1118             if(     (message_get_size(mesg) < DNS_HEADER_LENGTH + 5) ||
1119                     ((  *h64 & m64) != r64 ) )
1120             {
1121                 /** Return if QDCOUNT is not 1
1122                  *
1123                  *  @note Previous test was actually testing if QDCOUNT was > 1
1124                  *        I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT
1125                  */
1126 
1127                 if(MESSAGE_QR(buffer))
1128                 {
1129                     message_set_status(mesg, FP_QR_BIT_SET);
1130                     return INVALID_MESSAGE;
1131                 }
1132 
1133                 MESSAGE_FLAGS_AND(buffer, OPCODE_BITS, 0);
1134 
1135                 if(NETWORK_ONE_16 != MESSAGE_QD(buffer))
1136                 {
1137                     if(0 == MESSAGE_QD(buffer))
1138                     {
1139                         DERROR_MSG("FP_QDCOUNT_IS_0");
1140                         message_set_status(mesg, FP_QDCOUNT_IS_0);
1141                         return INVALID_MESSAGE;
1142                     }
1143                     else
1144                     {
1145                         DERROR_MSG("FP_QDCOUNT_BIG_1");
1146                         message_set_status(mesg, FP_QDCOUNT_BIG_1);
1147                     }
1148 
1149                     return UNPROCESSABLE_MESSAGE;
1150                 }
1151 
1152                 message_set_status(mesg, FP_PACKET_DROPPED);
1153 
1154                 return UNPROCESSABLE_MESSAGE;
1155             }
1156 
1157 
1158 
1159             u8 *s = message_process_copy_fqdn(mesg);
1160 
1161             if(s == NULL)
1162             {
1163                 message_set_status(mesg, FP_NAME_FORMAT_ERROR);
1164                 return UNPROCESSABLE_MESSAGE;
1165             }
1166 
1167 
1168 
1169             /**
1170              * @note Past this point, a message could be processable.
1171              *       It's the right place to reset the message's defaults.
1172              *
1173              */
1174 
1175             message_reset_buffer_size(mesg);
1176             mesg->_ar_start = NULL;
1177 #if DNSCORE_HAS_TSIG_SUPPORT
1178             mesg->_tsig.tsig  = NULL;
1179 #endif
1180             mesg->_rcode_ext  = 0;
1181             mesg->_edns       = FALSE;
1182 #if DNSCORE_HAS_NSID_SUPPORT
1183             mesg->_nsid       = FALSE;
1184 #endif
1185             /*
1186              * If there is a TSIG, it is here ...
1187              */
1188 
1189 #if DNSCORE_HAS_TSIG_SUPPORT
1190             {
1191                 ya_result return_code;
1192                 u16 ar_count;
1193 
1194                 if((ar_count = MESSAGE_AR(buffer)) != 0)
1195                 {
1196                     if(FAIL(return_code = message_process_additionals(mesg, s, ar_count)))
1197                     {
1198                         return return_code;
1199                     }
1200                 }
1201             }
1202 #endif
1203 
1204             /* At this point the TSIG has been computed and removed */
1205 
1206             message_apply_mask(mesg, ~(QR_BITS|TC_BITS|AA_BITS), ~(RA_BITS|RCODE_BITS));
1207 
1208             message_set_status(mesg, FP_MESG_OK);
1209 
1210             return OK;
1211         }
1212 #if HAS_CTRL
1213         case OPCODE_CTRL:
1214         {
1215             MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS|RCODE_BITS);
1216 
1217             /*
1218                rdtsc_init(&mpb);
1219              */
1220             /*    ------------------------------------------------------------    */
1221 
1222             /** CHECK DNS HEADER */
1223             /** Drop dns packet if query is answer or does not have correct header length */
1224 
1225             /*
1226              * +5 <=> 1 qd record ar least
1227              */
1228 
1229             u64 *h64 = (u64*)buffer;
1230             u64 m64 = MESSAGE_HEADER_MASK;
1231             u64 r64 = MESSAGE_HEADER_RESULT;
1232 
1233             if(     (message_get_size(mesg) < DNS_HEADER_LENGTH + 5) ||
1234                     ((  *h64 & m64) != r64 ) )
1235             {
1236                 /** Return if QDCOUNT is not 1
1237                  *
1238                  *  @note Previous test was actually testing if QDCOUNT was > 1
1239                  *        I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT
1240                  */
1241 
1242                 if(MESSAGE_QR(buffer))
1243                 {
1244                     message_set_status(mesg, FP_QR_BIT_SET);
1245                     return INVALID_MESSAGE;
1246                 }
1247 
1248                 MESSAGE_FLAGS_AND(buffer, OPCODE_BITS, 0);
1249 
1250                 if(NETWORK_ONE_16 != MESSAGE_QD(buffer))
1251                 {
1252                     if(0 == MESSAGE_QD(buffer))
1253                     {
1254                         DERROR_MSG("FP_QDCOUNT_IS_0");
1255                         message_set_status(mesg, FP_QDCOUNT_IS_0);
1256                         return INVALID_MESSAGE;
1257                     }
1258                     else
1259                     {
1260                         DERROR_MSG("FP_QDCOUNT_BIG_1");
1261                         message_set_status(mesg, FP_QDCOUNT_BIG_1);
1262                     }
1263 
1264                     return UNPROCESSABLE_MESSAGE;
1265                 }
1266 
1267                 message_set_status(mesg, FP_PACKET_DROPPED);
1268 
1269                 return UNPROCESSABLE_MESSAGE;
1270             }
1271 
1272 
1273 
1274             u8 *s = message_process_copy_fqdn(mesg);
1275 
1276             if(s == NULL)
1277             {
1278                 message_set_status(mesg, FP_NAME_FORMAT_ERROR);
1279                 return UNPROCESSABLE_MESSAGE;
1280             }
1281 
1282 
1283 
1284             /**
1285              * @note Past this point, a message could be processable.
1286              *       It's the right place to reset the message's defaults.
1287              *
1288              */
1289 
1290             message_reset_buffer_size(mesg);
1291             mesg->_ar_start = NULL;
1292 #if DNSCORE_HAS_TSIG_SUPPORT
1293             message_tsig_clear_key(mesg);
1294 #endif
1295             mesg->_rcode_ext  = 0;
1296             mesg->_edns       = FALSE;
1297 #if DNSCORE_HAS_NSID_SUPPORT
1298             mesg->_nsid       = FALSE;
1299 #endif
1300             /*
1301              * If there is a TSIG, it is here ...
1302              */
1303 
1304 #if DNSCORE_HAS_TSIG_SUPPORT
1305             {
1306                 ya_result return_code;
1307                 u16 ar_count;
1308 
1309                 if((ar_count = MESSAGE_AR(buffer)) != 0)
1310                 {
1311                     if(FAIL(return_code = message_process_additionals(mesg, s, ar_count)))
1312                     {
1313                         return return_code;
1314                     }
1315                 }
1316             }
1317 #endif
1318 
1319             /* At this point the TSIG has been computed and removed */
1320 
1321             message_apply_mask(mesg, ~(QR_BITS|TC_BITS|AA_BITS), ~(RA_BITS|RCODE_BITS));
1322 
1323             message_set_status(mesg, FP_MESG_OK);
1324 
1325             return OK;
1326         }
1327 #endif // HAS_CTRL
1328         default:
1329         {
1330             u8 hf = MESSAGE_HIFLAGS(buffer);
1331             if((hf & QR_BITS) == 0)
1332             {
1333                 MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS|RCODE_BITS);
1334                 MESSAGE_FLAGS_AND(buffer, OPCODE_BITS, 0);
1335 
1336                 message_reset_buffer_size(mesg);
1337                 mesg->_ar_start = NULL;
1338 #if DNSCORE_HAS_TSIG_SUPPORT
1339                 mesg->_tsig.tsig  = NULL;
1340 #endif
1341                 mesg->_rcode_ext  = 0;
1342                 mesg->_edns       = FALSE;
1343 #if DNSCORE_HAS_NSID_SUPPORT
1344                 mesg->_nsid       = FALSE;
1345 #endif
1346                 message_set_status(mesg, FP_NOT_SUPP_OPC);
1347                 message_set_size(mesg, DNS_HEADER_LENGTH);
1348                 SET_U32_AT(mesg->_buffer[4],0);    /* aligned to 32 bits, so two 32 bits instead of one 64 */
1349                 SET_U32_AT(mesg->_buffer[8],0);
1350 
1351                 /* reserved for future use */
1352 
1353                 return UNPROCESSABLE_MESSAGE;
1354             }
1355             else
1356             {
1357                 message_set_status(mesg, FP_PACKET_DROPPED);
1358 
1359                 return INVALID_MESSAGE;
1360             }
1361         }
1362     }
1363 }
1364 
1365 int
message_process_lenient(message_data * mesg)1366 message_process_lenient(message_data *mesg)
1367 {
1368     if(message_get_size(mesg) < DNS_HEADER_LENGTH)
1369     {
1370         return UNPROCESSABLE_MESSAGE;
1371     }
1372     /*
1373     if(message_istruncated(mesg))
1374     {
1375         return MESSAGE_TRUNCATED;
1376     }
1377     */
1378     u8 *s = message_process_copy_fqdn(mesg);
1379 
1380     if(s == NULL)
1381     {
1382         return UNPROCESSABLE_MESSAGE;
1383     }
1384 
1385     /**
1386      * @note Past this point, a message could be processable.
1387      *       It's the right place to reset the message's defaults.
1388      *
1389      */
1390 
1391     message_reset_buffer_size(mesg);
1392     mesg->_ar_start = NULL;
1393     mesg->_rcode_ext  = 0;
1394     mesg->_edns       = FALSE;
1395 #if DNSCORE_HAS_NSID_SUPPORT
1396     mesg->_nsid       = FALSE;
1397 #endif
1398 
1399     /*
1400      * Handle the OPT and TSIG records
1401      */
1402 
1403     {
1404         ya_result return_code;
1405         u16 ar_count_ne;
1406 
1407         if((ar_count_ne = message_get_additional_count_ne(mesg)) != 0)
1408         {
1409             if(FAIL(return_code = message_process_answer_additionals(mesg, ar_count_ne)))
1410             {
1411                 return return_code;
1412             }
1413         }
1414 #if DNSCORE_HAS_TSIG_SUPPORT
1415         else
1416         {
1417             mesg->_tsig.tsig  = NULL;
1418 
1419             /* cut the trash here */
1420             /*message_set_size(mesg, s - buffer);(*/
1421         }
1422 #endif
1423     }
1424 
1425 
1426 
1427     /* At this point the TSIG has been computed and removed */
1428 
1429     //message_set_status(mesg, FP_MESG_OK);
1430     message_set_status(mesg, (mesg->_buffer[3] & 0xf));
1431 
1432     return SUCCESS;
1433 }
1434 
1435 static ya_result
message_answer_verify_additionals(message_data * mesg,packet_unpack_reader_data * purd,int ar_count)1436 message_answer_verify_additionals(message_data *mesg, packet_unpack_reader_data *purd, int ar_count)
1437 {
1438     /* We are now at the start of the ar */
1439 
1440     struct type_class_ttl_rdlen *tctr;
1441 #if DNSCORE_HAS_TSIG_SUPPORT
1442     u32 record_offset;
1443     u8 fqdn[MAX_DOMAIN_LENGTH];
1444 #endif
1445 
1446     while(ar_count-- > 0)
1447     {
1448 #if DNSCORE_HAS_TSIG_SUPPORT
1449         record_offset = purd->offset;
1450 #endif
1451 
1452         if(FAIL(packet_reader_read_fqdn(purd, fqdn, sizeof(fqdn))))
1453         {
1454             /* oops */
1455 
1456             message_set_status(mesg, FP_ERROR_READING_QUERY);
1457 
1458             return UNPROCESSABLE_MESSAGE;
1459         }
1460 
1461         if(packet_reader_available(purd) < 10)
1462         {
1463             message_set_status(mesg, FP_ERROR_READING_QUERY);
1464 
1465             return UNPROCESSABLE_MESSAGE;
1466         }
1467 
1468         tctr = (struct type_class_ttl_rdlen*)packet_reader_get_next_u8_ptr_const(purd);
1469 
1470         purd->offset += 10;
1471 
1472         switch(tctr->qtype)
1473         {
1474             /*
1475              * EDNS (0)
1476              */
1477 
1478             case TYPE_OPT:
1479             {
1480                 /**
1481                  * Handle EDNS
1482                  */
1483 
1484                 message_sub_additional_count(mesg, 1);
1485 
1486                 if((tctr->ttl & NU32(0x00ff0000)) == 0) /* ensure version is 0 */
1487                 {
1488                     if(fqdn[0] == '\0')
1489                     {
1490                         message_set_buffer_size(mesg, edns0_maxsize); /* our own limit, taken from the config file */
1491                         mesg->_edns = TRUE;
1492                         mesg->_rcode_ext = tctr->ttl;
1493 
1494                         log_debug("EDNS: udp-size=%d rcode-ext=%08x desc=%04x", message_get_size(mesg), tctr->ttl, ntohs(tctr->rdlen));
1495                         continue;
1496                     }
1497                 }
1498                 else
1499                 {
1500                    message_set_status(mesg, FP_EDNS_BAD_VERSION);
1501                    message_set_buffer_size(mesg, edns0_maxsize);
1502                    mesg->_edns = TRUE;
1503                    mesg->_rcode_ext = 0;
1504 
1505                    break;
1506                 }
1507 
1508                 log_debug("OPT record is not processable (broken or not supported)");
1509 
1510                 return UNPROCESSABLE_MESSAGE;
1511             }
1512 #if DNSCORE_HAS_TSIG_SUPPORT
1513 
1514             /*
1515              * TSIG
1516              */
1517 
1518             case TYPE_TSIG:
1519             {
1520                 if(ar_count == 0)
1521                 {
1522                     /*
1523                      * It looks like a TSIG ...
1524                      */
1525 
1526                     ya_result return_code;
1527 
1528                     if(message_has_tsig(mesg))
1529                     {
1530                         if(dnsname_equals(fqdn, message_tsig_get_name(mesg)))
1531                         {
1532                             if(FAIL(return_code = tsig_process_answer(mesg, purd, record_offset, tctr)))
1533                             {
1534                                 log_err("%r answer error from %{sockaddr}", return_code, message_get_sender_sa(mesg));
1535 
1536                                 return return_code;
1537                             }
1538                         }
1539                         else
1540                         {
1541                             log_err("TSIG name mismatch from %{sockaddr}", message_get_sender_sa(mesg));
1542 
1543                             return UNPROCESSABLE_MESSAGE;
1544                         }
1545                     }
1546                     else // no tsig
1547                     {
1548                         log_err("answer error from %{sockaddr}: TSIG when none expected", message_get_sender_sa(mesg));
1549 
1550                         message_set_status(mesg, FP_TSIG_UNEXPECTED);
1551 
1552                         return UNPROCESSABLE_MESSAGE;
1553                     }
1554 
1555                     return SUCCESS;  /* we know there is no need to loop anymore */
1556                 }
1557                 else
1558                 {
1559                     /*
1560                      * Error: TSIG is not the last AR record
1561                      */
1562 
1563                     log_debug("TSIG record is not the last AR");
1564 
1565                     message_set_status(mesg, FP_TSIG_IS_NOT_LAST);
1566 
1567                     return UNPROCESSABLE_MESSAGE;
1568                 }
1569             }
1570 #endif
1571             default:
1572             {
1573                 /* Unhandled AR TYPE */
1574 #if DEBUG
1575                 log_debug("skipping AR type %{dnstype}", &tctr->qtype);
1576 #endif
1577                 purd->offset += ntohs(tctr->rdlen);
1578                 break;
1579             }
1580         }
1581     } /* While there are AR to process */
1582 
1583     return SUCCESS;
1584 }
1585 
1586 int
message_answer_verify(message_data * mesg)1587 message_answer_verify(message_data *mesg)
1588 {
1589     if(message_get_size(mesg) < DNS_HEADER_LENGTH)
1590     {
1591         return UNPROCESSABLE_MESSAGE;
1592     }
1593 
1594     u8 *after_query_section;
1595 
1596     if(message_get_query_count_ne(mesg) != 0)
1597     {
1598         after_query_section = message_process_copy_fqdn(mesg); // canonises the query fqdn and fetches its type and class
1599 
1600         if(after_query_section == NULL)
1601         {
1602             return UNPROCESSABLE_MESSAGE;
1603         }
1604     }
1605     else
1606     {
1607         if(mesg->_tcp_serial == 0) // needed at the beginning of the stream
1608         {
1609             return UNPROCESSABLE_MESSAGE;
1610         }
1611 
1612         after_query_section = message_get_query_section_ptr(mesg); // as there is no query section
1613     }
1614 
1615     /**
1616      * @note Past this point, a message could be processable.
1617      *       It's the right place to reset the message's defaults.
1618      *
1619      */
1620 
1621     u16 ar_count_ne;
1622 
1623     if((ar_count_ne = message_get_additional_count_ne(mesg)) != 0)
1624     {
1625         // find the additional section
1626 
1627         packet_unpack_reader_data purd;
1628         purd.packet = message_get_buffer_const(mesg);
1629         purd.packet_size = message_get_size(mesg);
1630         purd.offset = after_query_section - purd.packet;
1631 
1632         // skip all records before the additional section
1633 
1634         for(int ar_index = message_get_answer_count(mesg) + message_get_authority_count(mesg); ar_index > 0; --ar_index)
1635         {
1636             if(FAIL(packet_reader_skip_record(&purd)))
1637             {
1638                 return UNPROCESSABLE_MESSAGE;
1639             }
1640         }
1641 
1642         mesg->_ar_start = &mesg->_buffer[purd.offset];
1643 
1644         // ar_start is ready
1645 
1646         message_answer_verify_additionals(mesg, &purd,  ntohs(ar_count_ne));
1647     }
1648     else
1649     {
1650         mesg->_ar_start = NULL;
1651         mesg->_rcode_ext  = 0;
1652         mesg->_edns       = FALSE;
1653 #if DNSCORE_HAS_NSID_SUPPORT
1654         mesg->_nsid       = FALSE;
1655 #endif
1656     }
1657 
1658     message_set_status(mesg, FP_MESG_OK);
1659 
1660     return OK;
1661 }
1662 
1663 
1664 void
message_transform_to_error(message_data * mesg)1665 message_transform_to_error(message_data *mesg)
1666 {
1667     if(!mesg->_edns)
1668     {
1669         message_set_answer(mesg);
1670         message_or_rcode(mesg, message_get_status(mesg));
1671 
1672         if(message_get_status(mesg) == RCODE_FORMERR)
1673         {
1674             SET_U32_AT(mesg->_buffer[4],0);    /* aligned to 32 bits, so two 32 bits instead of one 64 */
1675             SET_U32_AT(mesg->_buffer[8],0);
1676 
1677             message_set_size(mesg, DNS_HEADER_LENGTH);
1678         }
1679         else
1680         {
1681         }
1682     }
1683     else
1684     {
1685         /* 00 0029 0200 EE 00 00000000 */
1686 
1687         if(message_get_status(mesg) == RCODE_FORMERR)
1688         {
1689             SET_U32_AT(mesg->_buffer[4],0);    /* aligned to 32 bits, so two 32 bits instead of one 64 */
1690             SET_U32_AT(mesg->_buffer[8],0);
1691 
1692             message_set_size(mesg, DNS_HEADER_LENGTH);
1693         }
1694         else
1695         {
1696             message_set_size(mesg, message_get_additional_section_ptr(mesg) - mesg->_buffer);
1697         }
1698 
1699         message_set_answer(mesg);
1700         message_set_rcode(mesg, message_get_status(mesg) & 15);
1701 
1702         /* #AR = 1 */
1703         mesg->_buffer[DNS_HEADER_LENGTH - 1] = 1;    /* AR count was 0, now it is 1 */
1704 
1705         /* append opt *//* */
1706         u8 *buffer = message_get_buffer_limit(mesg);
1707         buffer[ 0] = 0;
1708         buffer[ 1] = 0;
1709         buffer[ 2] = 0x29;
1710         buffer[ 3] = edns0_maxsize>>8;
1711         buffer[ 4] = edns0_maxsize;
1712         buffer[ 5] = message_get_status(mesg) >> 4; // status is updated here
1713         buffer[ 6] = mesg->_rcode_ext >> 16;
1714         buffer[ 7] = mesg->_rcode_ext >> 8;
1715         buffer[ 8] = mesg->_rcode_ext;
1716 
1717 #if DNSCORE_HAS_NSID_SUPPORT
1718         if(!message_has_nsid(mesg))
1719         {
1720             buffer[ 9] = 0;
1721             buffer[10] = 0;
1722 
1723             buffer += EDNS0_RECORD_SIZE;
1724         }
1725         else
1726         {
1727             buffer += EDNS0_RECORD_SIZE - 2;
1728             memcpy(buffer, edns0_rdatasize_nsid_option_wire, edns0_rdatasize_nsid_option_wire_size);
1729             buffer += edns0_rdatasize_nsid_option_wire_size;
1730         }
1731 #else
1732         buffer[ 9] = 0;
1733         buffer[10] = 0;
1734 
1735         buffer += EDNS0_RECORD_SIZE;
1736 #endif
1737         message_set_size(mesg, buffer - mesg->_buffer);
1738     }
1739 }
1740 
1741 void
message_transform_to_signed_error(message_data * mesg)1742 message_transform_to_signed_error(message_data *mesg)
1743 {
1744     message_transform_to_error(mesg);
1745 
1746     if(message_has_tsig(mesg))
1747     {
1748         tsig_sign_answer(mesg);
1749     }
1750 }
1751 
1752 void
message_make_query(message_data * mesg,u16 id,const u8 * qname,u16 qtype,u16 qclass)1753 message_make_query(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass)
1754 {
1755 #ifdef WORDS_BIGENDIAN
1756     SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL);
1757     SET_U32_AT(mesg->_buffer[8], 0);
1758 #else
1759     SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL);
1760     SET_U32_AT(mesg->_buffer[8], 0);
1761 #endif
1762     message_set_id(mesg, id);
1763 
1764     dnsname_canonize(qname, mesg->_canonised_fqdn);
1765 
1766     ya_result qname_len      = dnsname_len(qname);
1767     u8 *tc                   = message_get_query_section_ptr(mesg);
1768     memcpy(tc, qname, qname_len);
1769     tc                      += qname_len;
1770     SET_U16_AT(tc[0], qtype);
1771     tc                      += 2;
1772     SET_U16_AT(tc[0], qclass);
1773     tc                      += 2;
1774 #if DNSCORE_HAS_TSIG_SUPPORT
1775     mesg->_tsig.tsig         = NULL;
1776 #endif
1777 
1778     mesg->_ar_start = tc;
1779     message_reset_buffer_size(mesg);
1780     message_set_size(mesg, tc - message_get_buffer_const(mesg));
1781     message_set_status(mesg, FP_MESG_OK);
1782     mesg->_rcode_ext        = 0;
1783 }
1784 
1785 void
message_make_query_ex(message_data * mesg,u16 id,const u8 * qname,u16 qtype,u16 qclass,u16 flags)1786 message_make_query_ex(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass, u16 flags)
1787 {
1788 #ifdef WORDS_BIGENDIAN
1789     SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL);
1790     SET_U32_AT(mesg->_buffer[8], 0);
1791 #else
1792     SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL);
1793     SET_U32_AT(mesg->_buffer[8], 0);
1794 #endif
1795     message_set_id(mesg, id);
1796 
1797     dnsname_canonize(qname, mesg->_canonised_fqdn);
1798 
1799     ya_result qname_len      = dnsname_len(qname);
1800     u8 *tc                   = message_get_query_section_ptr(mesg);
1801     memcpy(tc, qname, qname_len);
1802     tc += qname_len;
1803     SET_U16_AT(tc[0], qtype);
1804     tc += 2;
1805     SET_U16_AT(tc[0], qclass);
1806     tc += 2;
1807 
1808     mesg->_ar_start = tc;
1809     message_set_size(mesg, tc - message_get_buffer_const(mesg));
1810     mesg->_rcode_ext = 0;
1811 
1812     message_set_status(mesg, FP_MESG_OK);
1813 #if DNSCORE_HAS_TSIG_SUPPORT
1814     message_tsig_clear_key(mesg);
1815 #endif
1816 
1817     if(mesg->_edns || (flags != 0))
1818     {
1819         message_set_additional_count_ne(mesg, NETWORK_ONE_16);
1820 
1821         mesg->_rcode_ext |= MESSAGE_EDNS0_DNSSEC;
1822 
1823         u8 *buffer = message_get_buffer_limit(mesg);
1824         buffer[ 0] = 0;
1825         buffer[ 1] = 0;                     // TYPE
1826         buffer[ 2] = 0x29;                  //
1827         buffer[ 3] = edns0_maxsize >> 8;    // CLASS = SIZE
1828         buffer[ 4] = edns0_maxsize;         //
1829         buffer[ 5] = message_get_status(mesg) >> 4;   // extended RCODE & FLAGS
1830         buffer[ 6] = mesg->_rcode_ext >> 16;
1831         buffer[ 7] = mesg->_rcode_ext >> 8;
1832         buffer[ 8] = mesg->_rcode_ext;
1833         buffer[ 9] = 0;                     // RDATA descriptor
1834         buffer[10] = 0;
1835 
1836         message_increase_size(mesg, 11);
1837     }
1838 }
1839 
1840 void
message_make_query_ex_with_edns0(message_data * mesg,u16 id,const u8 * qname,u16 qtype,u16 qclass,u32 edns0_ttl)1841 message_make_query_ex_with_edns0(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass, u32 edns0_ttl)
1842 {
1843 #ifdef WORDS_BIGENDIAN
1844     SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL);
1845     SET_U32_AT(mesg->_buffer[8], 0);
1846 #else
1847     SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL);
1848     SET_U32_AT(mesg->_buffer[8], 0);
1849 #endif
1850     message_set_id(mesg, id);
1851 
1852     dnsname_canonize(qname, mesg->_canonised_fqdn);
1853 
1854     ya_result qname_len      = dnsname_len(qname);
1855     u8 *tc                   = message_get_query_section_ptr(mesg);
1856     memcpy(tc, qname, qname_len);
1857     tc += qname_len;
1858     SET_U16_AT(tc[0], qtype);
1859     tc += 2;
1860     SET_U16_AT(tc[0], qclass);
1861     tc += 2;
1862 
1863     mesg->_ar_start = tc;
1864     message_set_size(mesg, tc - message_get_buffer_const(mesg));
1865     mesg->_rcode_ext = edns0_ttl;
1866 
1867     message_set_status(mesg, FP_MESG_OK);
1868 #if DNSCORE_HAS_TSIG_SUPPORT
1869     message_tsig_clear_key(mesg);
1870 #endif
1871 
1872     message_set_additional_count_ne(mesg, NETWORK_ONE_16);
1873     // mesg->_rcode_ext |= MESSAGE_EDNS0_DNSSEC;
1874 
1875     u8 *buffer = message_get_buffer_limit(mesg);
1876     buffer[ 0] = 0;
1877     buffer[ 1] = 0;                     // TYPE
1878     buffer[ 2] = 0x29;                  //
1879     buffer[ 3] = edns0_maxsize >> 8;    // CLASS = SIZE
1880     buffer[ 4] = edns0_maxsize;         //
1881     buffer[ 5] = message_get_status(mesg) >> 4;   // extended RCODE & FLAGS
1882     buffer[ 6] = edns0_ttl >> 16;
1883     buffer[ 7] = edns0_ttl >> 8;
1884     buffer[ 8] = edns0_ttl;
1885     buffer[ 9] = 0;                     // RDATA descriptor
1886     buffer[10] = 0;
1887 
1888     message_increase_size(mesg, 11);
1889 }
1890 
message_make_message(message_data * mesg,u16 id,const u8 * qname,u16 qtype,u16 qclass,packet_writer * uninitialised_packet_writer)1891 void message_make_message(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass, packet_writer *uninitialised_packet_writer)
1892 {
1893     assert(uninitialised_packet_writer != NULL);
1894     assert(packet_writer_get_offset(uninitialised_packet_writer) <= message_get_buffer_size_max(mesg));
1895 
1896 #ifdef WORDS_BIGENDIAN
1897     SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL);
1898     SET_U32_AT(mesg->_buffer[8], 0);
1899 #else
1900     SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL);
1901     SET_U32_AT(mesg->_buffer[8], 0);
1902 #endif
1903     message_set_id(mesg, id);
1904 
1905     dnsname_canonize(qname, mesg->_canonised_fqdn);
1906 
1907     packet_writer_create(uninitialised_packet_writer, message_get_buffer(mesg), DNSPACKET_MAX_LENGTH);
1908 
1909     packet_writer_add_fqdn(uninitialised_packet_writer, qname);
1910     packet_writer_add_u16(uninitialised_packet_writer, qtype);
1911     packet_writer_add_u16(uninitialised_packet_writer, qclass);
1912 #if DNSCORE_HAS_TSIG_SUPPORT
1913     message_tsig_clear_key(mesg);
1914 #endif
1915 
1916     message_set_size(mesg, packet_writer_get_offset(uninitialised_packet_writer));
1917     mesg->_ar_start = message_get_buffer_limit(mesg);
1918 
1919     message_reset_buffer_size(mesg);
1920 
1921     message_set_status(mesg, FP_MESG_OK);
1922 }
1923 
1924 void
message_make_notify(message_data * mesg,u16 id,const u8 * qname,u16 qtype,u16 qclass)1925 message_make_notify(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass)
1926 {
1927 #ifdef WORDS_BIGENDIAN
1928     SET_U64_AT(mesg->_buffer[0], 0x0000240000010000LL); // notify + AA
1929     SET_U32_AT(mesg->_buffer[8], 0);
1930 #else
1931     SET_U64_AT(mesg->_buffer[0], 0x0000010000240000LL); // notify + AA
1932     SET_U32_AT(mesg->_buffer[8], 0);
1933 #endif
1934     message_set_id(mesg, id);
1935 
1936     dnsname_canonize(qname, mesg->_canonised_fqdn);
1937 
1938     ya_result qname_len = dnsname_len(qname);
1939     u8 *tc = message_get_query_section_ptr(mesg);
1940     memcpy(tc, qname, qname_len);
1941     tc += qname_len;
1942     SET_U16_AT(tc[0], qtype);
1943     tc += 2;
1944     SET_U16_AT(tc[0], qclass);
1945     tc += 2;
1946 #if DNSCORE_HAS_TSIG_SUPPORT
1947     message_tsig_clear_key(mesg);
1948 #endif
1949 
1950     message_set_size(mesg, tc - message_get_buffer_const(mesg));
1951     mesg->_ar_start = tc;
1952     message_set_status(mesg, FP_MESG_OK);
1953 }
1954 
1955 void
message_make_ixfr_query(message_data * mesg,u16 id,const u8 * qname,u32 soa_ttl,u16 soa_rdata_size,const u8 * soa_rdata)1956 message_make_ixfr_query(message_data *mesg, u16 id, const u8 *qname, u32 soa_ttl, u16 soa_rdata_size, const u8 *soa_rdata)
1957 {
1958     packet_writer pw;
1959 
1960 #ifdef WORDS_BIGENDIAN
1961     SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL);
1962     SET_U32_AT(mesg->_buffer[8], 0x00010000);
1963 #else
1964     SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL);
1965     SET_U32_AT(mesg->_buffer[8], 0x00000100);
1966 #endif
1967 
1968     message_set_id(mesg, id);
1969 
1970     dnsname_canonize(qname, mesg->_canonised_fqdn);
1971 
1972     packet_writer_create(&pw, message_get_buffer(mesg), message_get_buffer_size_max(mesg));
1973 
1974     packet_writer_add_fqdn(&pw, qname);
1975     packet_writer_add_u16(&pw, TYPE_IXFR);
1976     packet_writer_add_u16(&pw, CLASS_IN);
1977 
1978     packet_writer_add_fqdn(&pw, qname);
1979     packet_writer_add_u16(&pw, TYPE_SOA);
1980     packet_writer_add_u16(&pw, CLASS_IN);
1981     packet_writer_add_u32(&pw, htonl(soa_ttl));
1982     packet_writer_add_rdata(&pw, TYPE_SOA, soa_rdata, soa_rdata_size);
1983 
1984 #if DNSCORE_HAS_TSIG_SUPPORT
1985     message_tsig_clear_key(mesg);
1986 #endif
1987     mesg->_ar_start = &mesg->_buffer[packet_writer_get_offset(&pw)];
1988     message_reset_buffer_size(mesg);
1989     message_set_size(mesg, packet_writer_get_offset(&pw));
1990     message_set_status(mesg, FP_MESG_OK);
1991 }
1992 
1993 #if DNSCORE_HAS_TSIG_SUPPORT
1994 
1995 ya_result
message_sign_answer_by_name(message_data * mesg,const u8 * tsig_name)1996 message_sign_answer_by_name(message_data *mesg, const u8 *tsig_name)
1997 {
1998     const tsig_item *key = tsig_get(tsig_name);
1999 
2000     return message_sign_answer(mesg, key);
2001 }
2002 
2003 ya_result
message_sign_query_by_name(message_data * mesg,const u8 * tsig_name)2004 message_sign_query_by_name(message_data *mesg, const u8 *tsig_name)
2005 {
2006     const tsig_item *key = tsig_get(tsig_name);
2007 
2008     return message_sign_query(mesg, key);
2009 }
2010 
2011 ya_result
message_sign_query_by_name_with_epoch_and_fudge(message_data * mesg,const u8 * tsig_name,s64 epoch,u16 fudge)2012 message_sign_query_by_name_with_epoch_and_fudge(message_data *mesg, const u8 *tsig_name, s64 epoch, u16 fudge)
2013 {
2014     const tsig_item *key = tsig_get(tsig_name);
2015 
2016     return message_sign_query_with_epoch_and_fudge(mesg, key, epoch, fudge);
2017 }
2018 
2019 ya_result
message_sign_answer(message_data * mesg,const tsig_item * key)2020 message_sign_answer(message_data *mesg, const tsig_item *key)
2021 {
2022     if(key != NULL)
2023     {
2024         ZEROMEMORY(&mesg->_tsig, sizeof(message_tsig));
2025 
2026         mesg->_tsig.tsig = key;
2027         mesg->_tsig.mac_size = mesg->_tsig.tsig->mac_size;
2028 
2029         u64 now = time(NULL);
2030         mesg->_tsig.timehi = htons((u16)(now >> 32));
2031         mesg->_tsig.timelo = htonl((u32)now);
2032 
2033         mesg->_tsig.fudge  = htons(300);    /* 5m */
2034 
2035         mesg->_tsig.mac_algorithm = key->mac_algorithm;
2036 
2037         mesg->_tsig.original_id = message_get_id(mesg);
2038 
2039         ya_result ret = tsig_sign_answer(mesg);
2040         return ret;
2041     }
2042 
2043     return TSIG_BADKEY;
2044 }
2045 
2046 ya_result
message_sign_query(message_data * mesg,const tsig_item * key)2047 message_sign_query(message_data *mesg, const tsig_item *key)
2048 {
2049     if(key != NULL)
2050     {
2051         ZEROMEMORY(&mesg->_tsig, sizeof(message_tsig));
2052 
2053         mesg->_tsig.tsig = key;
2054         mesg->_tsig.mac_size = mesg->_tsig.tsig->mac_size;
2055 
2056         u64 now = time(NULL);
2057         mesg->_tsig.timehi = htons((u16)(now >> 32));
2058         mesg->_tsig.timelo = htonl((u32)now);
2059 
2060         mesg->_tsig.fudge  = htons(300);    /* 5m */
2061 
2062         mesg->_tsig.mac_algorithm = key->mac_algorithm;
2063 
2064         mesg->_tsig.original_id = message_get_id(mesg);
2065 
2066         // mesg->tsig.error = 0;     zeromem
2067         // mesg->tsig.other_len = 0; zeromem
2068 
2069         return tsig_sign_query(mesg);
2070     }
2071 
2072     return TSIG_BADKEY;
2073 }
2074 
2075 ya_result
message_sign_query_with_epoch_and_fudge(message_data * mesg,const tsig_item * key,s64 epoch,u16 fudge)2076 message_sign_query_with_epoch_and_fudge(message_data *mesg, const tsig_item *key, s64 epoch, u16 fudge)
2077 {
2078     if(key != NULL)
2079     {
2080         ZEROMEMORY(&mesg->_tsig, sizeof(message_tsig));
2081 
2082         mesg->_tsig.tsig = key;
2083         mesg->_tsig.mac_size = mesg->_tsig.tsig->mac_size;
2084 
2085         mesg->_tsig.timehi = htons((u16)(epoch >> 32));
2086         mesg->_tsig.timelo = htonl((u32)epoch);
2087 
2088         mesg->_tsig.fudge  = htons(fudge);    /* 5m */
2089 
2090         mesg->_tsig.mac_algorithm = key->mac_algorithm;
2091 
2092         mesg->_tsig.original_id = message_get_id(mesg);
2093 
2094         // mesg->tsig.error = 0;     zeromem
2095         // mesg->tsig.other_len = 0; zeromem
2096 
2097         return tsig_sign_query(mesg);
2098     }
2099 
2100     return TSIG_BADKEY;
2101 }
2102 
2103 
2104 #endif
2105 
2106 void
message_make_error(message_data * mesg,u16 error_code)2107 message_make_error(message_data *mesg, u16 error_code)
2108 {
2109     MESSAGE_FLAGS_OR(mesg->_buffer, QR_BITS, error_code);
2110 #ifdef WORDS_BIGENDIAN
2111     SET_U32_AT(mesg->_buffer[4], 0x00010000);
2112     SET_U32_AT(mesg->_buffer[8], 0x00000000);
2113 #else
2114     SET_U32_AT(mesg->_buffer[4], 0x00000100);
2115     SET_U32_AT(mesg->_buffer[8], 0x00000000);
2116 #endif
2117 
2118     message_reset_buffer_size(mesg);
2119     // + 4 is for TYPE + CLASS
2120     message_set_size(mesg, DNS_HEADER_LENGTH + 4 + dnsname_len(message_get_query_section_ptr(mesg)));
2121     mesg->_ar_start = message_get_buffer_limit(mesg);
2122     message_set_status(mesg, (finger_print)error_code);
2123 }
2124 
2125 void
message_make_signed_error(message_data * mesg,u16 error_code)2126 message_make_signed_error(message_data *mesg, u16 error_code)
2127 {
2128     message_make_error(mesg, error_code);
2129 
2130     if(message_has_tsig(mesg))
2131     {
2132         tsig_sign_answer(mesg);
2133     }
2134 }
2135 
2136 ya_result
message_make_error_and_reply_tcp(message_data * mesg,u16 error_code,int tcpfd)2137 message_make_error_and_reply_tcp(message_data *mesg, u16 error_code, int tcpfd)
2138 {
2139     ya_result ret;
2140 
2141     message_make_signed_error(mesg, error_code);
2142 
2143     if(ISOK(ret = message_send_tcp(mesg, tcpfd)))
2144     {
2145         //
2146     }
2147     else
2148     {
2149         tcp_set_abortive_close(tcpfd);
2150     }
2151 
2152     return ret;
2153 }
2154 
2155 ssize_t
message_make_error_and_reply_tcp_with_default_minimum_throughput(message_data * mesg,u16 error_code,int tcpfd)2156 message_make_error_and_reply_tcp_with_default_minimum_throughput(message_data *mesg, u16 error_code, int tcpfd)
2157 {
2158     ssize_t ret;
2159     message_make_signed_error(mesg, error_code);
2160 
2161     ret = message_update_length_send_tcp_with_default_minimum_throughput(mesg, tcpfd);
2162 
2163     return ret;
2164 }
2165 
2166 /**
2167  * Creates an answer with an OPT error code
2168  */
2169 
2170 void
message_make_error_ext(message_data * mesg,u32 error_code)2171 message_make_error_ext(message_data *mesg, u32 error_code)
2172 {
2173     MESSAGE_FLAGS_OR(mesg->_buffer, QR_BITS, error_code & 0x0f);
2174 #ifdef WORDS_BIGENDIAN
2175     SET_U32_AT(mesg->_buffer[4], 0x00010000);
2176     SET_U32_AT(mesg->_buffer[8], 0x00000000);
2177 #else
2178     SET_U32_AT(mesg->_buffer[4], 0x00000100);
2179     SET_U32_AT(mesg->_buffer[8], 0x00000000);
2180 #endif
2181 
2182     message_reset_buffer_size(mesg);
2183     // + 4 is for TYPE + CLASS
2184     size_t query_section_size = DNS_HEADER_LENGTH + 4 + dnsname_len(message_get_query_section_ptr(mesg));
2185     mesg->_ar_start = &mesg->_buffer[query_section_size];
2186 
2187     // the upper 8 bits of the error code are to be put in OPT
2188 
2189     u8 *edns0 = mesg->_ar_start;
2190     edns0[0] = 0;
2191     SET_U16_AT(edns0[1], TYPE_OPT);
2192     SET_U16_AT(edns0[3], htons(message_edns0_getmaxsize()));
2193     SET_U32_AT(edns0[5], (((error_code & 0xff0) << 24) | (message_get_rcode_ext(mesg) & 0x00ffffff)));
2194     SET_U16_AT(edns0[9], 0);
2195     message_set_size(mesg, query_section_size + 11);
2196     message_set_status(mesg, (finger_print)error_code);
2197 }
2198 
2199 ya_result
message_query_tcp(message_data * mesg,const host_address * server)2200 message_query_tcp(message_data *mesg, const host_address *server)
2201 {
2202     /* connect the server */
2203 
2204     ya_result return_value;
2205 
2206     if(ISOK(return_value = message_set_sender_from_host_address(mesg, server)))
2207     {
2208         int sockfd;
2209 
2210         if((sockfd = socket(message_get_sender_sa(mesg)->sa_family, SOCK_STREAM, 0)) >=0)
2211         {
2212             fd_setcloseonexec(sockfd);
2213 
2214             socklen_t sa_len = return_value;
2215 
2216             if(connect(sockfd, message_get_sender_sa(mesg), sa_len) == 0)
2217             {
2218 #if DEBUG
2219                 log_debug("sending %d+2 bytes to %{sockaddr} (tcp)", message_get_size(mesg), message_get_sender(mesg));
2220                 log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT);
2221 #endif
2222                 if(message_send_tcp(mesg, sockfd) == (ssize_t)message_get_size(mesg) + 2)
2223                 {
2224                     u16 tcp_len;
2225 
2226                     shutdown(sockfd, SHUT_WR);
2227 
2228                     if(readfully(sockfd, &tcp_len, 2) == 2)
2229                     {
2230                         tcp_len = ntohs(tcp_len);
2231 
2232                         if(readfully(sockfd, message_get_buffer(mesg), tcp_len) == tcp_len)
2233                         {
2234                             /*
2235                              * test the answser
2236                              * test the TSIG if any
2237                              */
2238 
2239                             message_set_size(mesg, tcp_len);
2240 #if DEBUG
2241                             log_debug("received %d bytes from %{sockaddr} (tcp)", message_get_size(mesg), message_get_sender(mesg));
2242                             log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT);
2243 #endif
2244                             return_value = message_process_lenient(mesg);
2245                         }
2246                     }
2247                 }
2248             }
2249             else
2250             {
2251                 // Linux quirk ...
2252 
2253                 if(errno != EINPROGRESS)
2254                 {
2255                     return_value = ERRNO_ERROR;
2256                 }
2257                 else
2258                 {
2259                     return_value = MAKE_ERRNO_ERROR(ETIMEDOUT);
2260                 }
2261             }
2262 
2263             shutdown(sockfd, SHUT_RDWR);
2264 
2265             tcp_set_abortive_close(sockfd);
2266 
2267             close_ex(sockfd);
2268         }
2269         else
2270         {
2271             return_value = ERRNO_ERROR;
2272         }
2273     }
2274 
2275     return return_value;
2276 }
2277 
2278 ya_result
message_query_tcp_ex(message_data * mesg,const host_address * bindto,const host_address * server,message_data * answer)2279 message_query_tcp_ex(message_data *mesg, const host_address *bindto, const host_address *server, message_data *answer)
2280 {
2281     /* connect the server */
2282 
2283     ya_result ret;
2284     socklen_t sa_len;
2285     socketaddress sa;
2286 
2287     if((mesg == NULL) || (server == NULL) || (answer == NULL))
2288     {
2289         return UNEXPECTED_NULL_ARGUMENT_ERROR;
2290     }
2291 
2292     if(bindto != NULL)
2293     {
2294         ret = host_address2sockaddr(bindto, &sa);
2295         if(FAIL(ret))
2296         {
2297             return ret;
2298         }
2299 
2300         sa_len = (socklen_t)ret;
2301     }
2302 
2303     if(ISOK(ret = message_set_sender_from_host_address(mesg, server)))
2304     {
2305         int sockfd;
2306 
2307         if((sockfd = socket(message_get_sender_sa(mesg)->sa_family, SOCK_STREAM, 0)) >=0)
2308         {
2309             fd_setcloseonexec(sockfd);
2310 
2311             if(bindto != NULL)
2312             {
2313                 int on = 1;
2314                 if(FAIL(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on))))
2315                 {
2316                     ret = ERRNO_ERROR;
2317                     close(sockfd);
2318                     return ret;
2319                 }
2320 
2321                 if(FAIL(setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (void *) &on, sizeof(on))))
2322                 {
2323                     ret = ERRNO_ERROR;
2324                     close(sockfd);
2325                     return ret;
2326                 }
2327 
2328                 if(bind(sockfd, &sa.sa, sa_len) < 0)
2329                 {
2330                     ret = ERRNO_ERROR;
2331                     close_ex(sockfd);
2332                     return ret;
2333                 }
2334             }
2335 
2336             if(connect(sockfd, message_get_sender_sa(mesg), message_get_sender_size(mesg)) == 0)
2337             {
2338 #if DEBUG
2339                 log_debug("sending %d bytes to %{sockaddr} (tcp)", message_get_size(mesg), message_get_sender(mesg));
2340                 log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT);
2341 #endif
2342                 if(message_send_tcp(mesg, sockfd) == (ssize_t)message_get_size(mesg) + 2)
2343                 {
2344                     u16 tcp_len;
2345 
2346                     shutdown(sockfd, SHUT_WR);
2347 
2348                     if(readfully(sockfd, &tcp_len, 2) == 2)
2349                     {
2350                         tcp_len = ntohs(tcp_len);
2351 
2352                         if(readfully(sockfd, message_get_buffer(answer), tcp_len) == tcp_len)
2353                         {
2354                             /*
2355                              * test the answser
2356                              * test the TSIG if any
2357                              */
2358 
2359                             message_set_size(answer, tcp_len);
2360 #if DNSCORE_HAS_TSIG_SUPPORT
2361                             message_tsig_copy_from(answer, mesg);
2362 #endif
2363                             message_copy_sender_from(answer, mesg);
2364 #if DEBUG
2365                             log_debug("received %d bytes from %{sockaddr} (tcp)", message_get_size(answer), message_get_sender_sa(answer));
2366                             log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(answer), message_get_size(answer), 16, OSPRINT_DUMP_HEXTEXT);
2367 #endif
2368                             ret = message_process_lenient(answer);
2369                         }
2370                     }
2371                 }
2372             }
2373             else
2374             {
2375                 // Linux quirk ...
2376 
2377                 if(errno != EINPROGRESS)
2378                 {
2379                     ret = ERRNO_ERROR;
2380                 }
2381                 else
2382                 {
2383                     ret = MAKE_ERRNO_ERROR(ETIMEDOUT);
2384                 }
2385             }
2386 
2387             shutdown(sockfd, SHUT_RDWR);
2388 
2389             tcp_set_abortive_close(sockfd);
2390 
2391             close_ex(sockfd);
2392         }
2393         else
2394         {
2395             ret = ERRNO_ERROR;
2396         }
2397     }
2398 
2399     return ret;
2400 }
2401 
2402 ya_result
message_query_tcp_with_timeout(message_data * mesg,const host_address * address,u8 to_sec)2403 message_query_tcp_with_timeout(message_data *mesg, const host_address *address, u8 to_sec)
2404 {
2405     ya_result ret;
2406 
2407     if((mesg == NULL) || (address == NULL))
2408     {
2409         return UNEXPECTED_NULL_ARGUMENT_ERROR;
2410     }
2411 
2412     input_stream is;
2413     output_stream os;
2414 
2415     if(ISOK(ret = tcp_input_output_stream_connect_host_address(address, &is, &os, to_sec)))
2416     {
2417         int sockfd = fd_input_stream_get_filedescriptor(&is);
2418 
2419         tcp_set_sendtimeout(sockfd, to_sec, 0);
2420         tcp_set_recvtimeout(sockfd, to_sec, 0);
2421 
2422         if(ISOK(ret = message_write_tcp(mesg, &os)))
2423         {
2424             output_stream_flush(&os);
2425 
2426             shutdown(sockfd, SHUT_WR);
2427 
2428             u16 id = message_get_id(mesg);
2429 #if DEBUG
2430             message_debug_trash_buffer(mesg);
2431 #endif
2432             u16 len;
2433 #if DEBUG
2434             len = ~0;
2435 #endif
2436             if(ISOK(ret = input_stream_read_nu16(&is, &len)))
2437             {
2438                 if (ISOK(ret =  input_stream_read_fully(&is, message_get_buffer(mesg), len)))
2439                 {
2440                     message_set_size(mesg, ret);
2441 
2442                     if(message_get_id(mesg) != id)
2443                     {
2444                         ret = MESSAGE_HAS_WRONG_ID;
2445                     }
2446                     else if(!message_isanswer(mesg))
2447                     {
2448                         ret = MESSAGE_IS_NOT_AN_ANSWER;
2449                     }
2450                     else if(message_get_rcode(mesg) != RCODE_NOERROR)
2451                     {
2452                         ret = MAKE_DNSMSG_ERROR(message_get_rcode(mesg));
2453                     }
2454                 }
2455                 else
2456                 {
2457                     message_set_size(mesg, 0);
2458                 }
2459             }
2460         }
2461 
2462         shutdown(sockfd, SHUT_RDWR);
2463 
2464         tcp_set_abortive_close(sockfd);
2465 
2466         output_stream_close(&os);
2467         output_stream_close(&is);
2468     }
2469 
2470     return ret;
2471 }
2472 
2473 ya_result
message_query_tcp_with_timeout_ex(message_data * mesg,const host_address * server,message_data * answer,u8 to_sec)2474 message_query_tcp_with_timeout_ex(message_data *mesg, const host_address *server, message_data *answer, u8 to_sec)
2475 {
2476     /* connect the server */
2477 
2478     ya_result return_value;
2479 
2480     if(ISOK(return_value = message_set_sender_from_host_address(mesg, server)))
2481     {
2482         int sockfd;
2483 
2484         if((sockfd = socket(message_get_sender_sa(mesg)->sa_family, SOCK_STREAM, 0)) >=0)
2485         {
2486             fd_setcloseonexec(sockfd);
2487 
2488             socklen_t sa_len = return_value;
2489 
2490             if(connect(sockfd, message_get_sender_sa(mesg), sa_len) == 0)
2491             {
2492 #if 1 // DEBUG
2493                 log_debug("sending %d bytes to %{sockaddr} (tcp)", message_get_size(mesg), message_get_sender(mesg));
2494                 log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT);
2495 #endif
2496                 tcp_set_sendtimeout(sockfd, to_sec, 0);
2497                 tcp_set_recvtimeout(sockfd, to_sec, 0);
2498 
2499                 ssize_t n = message_send_tcp(mesg, sockfd);
2500 
2501                 if(n == (ssize_t)message_get_size(mesg) + 2)
2502                 {
2503                     u16 tcp_len;
2504 
2505                     shutdown(sockfd, SHUT_WR);
2506 
2507                     n = readfully(sockfd, &tcp_len, 2);
2508 
2509                     if(n == 2)
2510                     {
2511                         tcp_len = ntohs(tcp_len);
2512 
2513                         n = readfully(sockfd, message_get_buffer(answer), tcp_len);
2514 
2515                         if(n == tcp_len)
2516                         {
2517                             /*
2518                              * test the answser
2519                              * test the TSIG if any
2520                              */
2521 
2522                             message_set_size(answer, tcp_len);
2523 #if DNSCORE_HAS_TSIG_SUPPORT
2524                             message_tsig_copy_from(answer, mesg);
2525 #endif
2526                             message_copy_sender_from(answer, mesg);
2527 #if DEBUG
2528                             log_debug("received %d bytes from %{sockaddr} (tcp)", message_get_size(answer), message_get_sender_sa(answer));
2529                             log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(answer), message_get_size(answer), 16, OSPRINT_DUMP_HEXTEXT);
2530 #endif
2531                             return_value = message_process_lenient(answer);
2532                         }
2533                         else
2534                         {
2535                             return_value = UNEXPECTED_EOF;
2536                         }
2537                     }
2538                     else
2539                     {
2540                         return_value = UNEXPECTED_EOF;
2541                     }
2542                 }
2543                 else
2544                 {
2545                     return_value = UNABLE_TO_COMPLETE_FULL_WRITE;
2546                 }
2547             }
2548             else
2549             {
2550                 // Linux quirk ...
2551 
2552                 if(errno != EINPROGRESS)
2553                 {
2554                     return_value = ERRNO_ERROR;
2555                 }
2556                 else
2557                 {
2558                     return_value = MAKE_ERRNO_ERROR(ETIMEDOUT);
2559                 }
2560             }
2561 
2562             shutdown(sockfd, SHUT_RDWR);
2563 
2564             tcp_set_abortive_close(sockfd);
2565 
2566             close_ex(sockfd);
2567         }
2568         else
2569         {
2570             return_value = ERRNO_ERROR;
2571         }
2572     }
2573 
2574     return return_value;
2575 }
2576 
2577 ya_result
message_query_udp(message_data * mesg,const host_address * server)2578 message_query_udp(message_data *mesg, const host_address *server)
2579 {
2580     ya_result                                         return_code = SUCCESS;
2581 
2582     int                                                   seconds = 0;
2583     int                                                  useconds = 500000;
2584 
2585     yassert(mesg != NULL);
2586     yassert(server != NULL);
2587 
2588     return_code = message_query_udp_with_timeout(mesg, server, seconds, useconds);
2589 
2590     return return_code;
2591 }
2592 
2593 ya_result
message_query_udp_with_timeout_and_retries(message_data * mesg,const host_address * server,int seconds,int useconds,u8 retries,u8 flags)2594 message_query_udp_with_timeout_and_retries(message_data *mesg, const host_address *server, int seconds, int useconds, u8 retries, u8 flags)
2595 {
2596     ya_result return_value = SUCCESS;
2597     random_ctx rndctx = thread_pool_get_random_ctx();
2598     u16 id;
2599 
2600     for(u8 countdown = retries; countdown > 0; )
2601     {
2602         if (flags & MESSAGE_QUERY_UDP_FLAG_RESET_ID)
2603         {
2604             id = (u16)random_next(rndctx);
2605             message_set_id(mesg, id);
2606         }
2607         else
2608         {
2609             id = message_get_id(mesg);
2610         }
2611 
2612         if(ISOK(return_value = message_query_udp_with_timeout(mesg, server, seconds, useconds)))
2613         {
2614             if(message_get_id(mesg) != id)
2615             {
2616                 return_value = MESSAGE_HAS_WRONG_ID;
2617             }
2618             else if(!message_isanswer(mesg))
2619             {
2620                 return_value = MESSAGE_IS_NOT_AN_ANSWER;
2621             }
2622             else if(message_get_rcode(mesg) != RCODE_NOERROR)
2623             {
2624                 return_value = MAKE_DNSMSG_ERROR(message_get_rcode(mesg));
2625             }
2626 
2627             break;
2628         }
2629 
2630         if(return_value == MAKE_ERRNO_ERROR(EINTR))
2631         {
2632             continue;
2633         }
2634 
2635         if(return_value != MAKE_ERRNO_ERROR(EAGAIN) || countdown <= 0)
2636         {
2637             /*
2638              * Do not retry for any other kind of error
2639              */
2640 
2641             break;
2642         }
2643 
2644         countdown--;
2645 
2646         usleep_ex(10000);  /* 10 ms */
2647 
2648         /*
2649         if (flags & CHANGE_NAME_SERVER)
2650         {
2651         }
2652         */
2653     }
2654 
2655     return return_value;
2656 }
2657 
2658 ya_result
message_query_udp_with_timeout(message_data * mesg,const host_address * server,int seconds,int useconds)2659 message_query_udp_with_timeout(message_data *mesg, const host_address *server, int seconds, int useconds)
2660 {
2661     yassert(mesg != NULL);
2662     yassert(server != NULL);
2663 
2664     /* connect the server */
2665 
2666     ya_result ret;
2667 
2668     u16 id;
2669     bool has_fqdn = FALSE;
2670     u8 fqdn[MAX_DOMAIN_LENGTH + 1];
2671 
2672     if(ISOK(ret = message_set_sender_from_host_address(mesg, server)))
2673     {
2674         int sockfd;
2675 
2676         if((sockfd = socket(message_get_sender_sa(mesg)->sa_family, SOCK_DGRAM, 0)) >=0)
2677         {
2678             fd_setcloseonexec(sockfd);
2679 
2680             tcp_set_recvtimeout(sockfd, seconds, useconds); /* half a second for UDP is a lot ... */
2681 
2682             int send_size = message_get_size(mesg);
2683 
2684             ssize_t n;
2685 
2686             if((n = message_send_udp(mesg, sockfd)) == send_size)
2687             {
2688                 id = message_get_id(mesg);
2689 
2690                 if(message_get_query_count_ne(mesg) != 0)
2691                 {
2692                     has_fqdn = TRUE;
2693                     dnsname_copy(fqdn, message_get_buffer_const(mesg) + 12);
2694                 }
2695 
2696                 message_data_with_buffer recv_mesg_buff;
2697                 message_data *recv_mesg = message_data_with_buffer_init(&recv_mesg_buff);
2698 
2699                 //recv_mesg._tsig.hmac = mesg->_tsig.hmac;
2700 
2701                 s64 time_limit = seconds;
2702                 time_limit *= ONE_SECOND_US;
2703                 time_limit += useconds;
2704                 time_limit += timeus();
2705 
2706                 ret = SUCCESS;
2707 
2708                 while((n = message_recv_udp(recv_mesg, sockfd)) >= 0)
2709                 {
2710 #if DEBUG
2711                     log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(recv_mesg), n, 16, OSPRINT_DUMP_HEXTEXT);
2712 #endif
2713                     // check the id is right
2714 
2715                     if(message_get_id(recv_mesg) == id)
2716                     {
2717                         // check that the sender is the one we spoke to
2718 
2719                         if(sockaddr_equals(message_get_sender_sa(mesg), message_get_sender_sa(recv_mesg)))
2720                         {
2721                             message_tsig_copy_from(recv_mesg, mesg);
2722 
2723                             if(ISOK(ret  = message_process_lenient(recv_mesg)))
2724                             {
2725                                 // check the domain is right
2726 
2727                                 if(!has_fqdn || dnsname_equals(fqdn, message_get_canonised_fqdn(recv_mesg)))
2728                                 {
2729                                     // everything checks up
2730 
2731                                     message_copy_sender_from(mesg, recv_mesg);
2732                                     mesg->_ar_start = &mesg->_buffer[recv_mesg->_ar_start - recv_mesg->_buffer];
2733                                     mesg->_iovec.iov_len = recv_mesg->_iovec.iov_len;
2734                                     mesg->_rcode_ext = recv_mesg->_rcode_ext;
2735                                     mesg->_status = recv_mesg->_status;
2736 
2737                                     if(mesg->_buffer_size < mesg->_iovec.iov_len)
2738                                     {
2739                                         mesg->_buffer_size = mesg->_iovec.iov_len;
2740                                     }
2741 
2742                                     mesg->_query_type = recv_mesg->_query_type;
2743                                     mesg->_query_class = recv_mesg->_query_class;
2744                                     mesg->_edns = recv_mesg->_edns;
2745                                     mesg->_nsid = recv_mesg->_nsid;
2746 
2747                                     if((mesg->_control_buffer_size = recv_mesg->_control_buffer_size) > 0)
2748                                     {
2749                                         memcpy(mesg->_msghdr_control_buffer, recv_mesg->_msghdr_control_buffer, recv_mesg->_control_buffer_size);
2750                                     }
2751 
2752                                     dnsname_copy(mesg->_canonised_fqdn, recv_mesg->_canonised_fqdn);
2753 
2754                                     memcpy(mesg->_buffer, recv_mesg->_buffer, recv_mesg->_iovec.iov_len);
2755 
2756                                     break;
2757                                 }
2758                                 else
2759                                 {
2760                                     ret = MESSAGE_UNEXPECTED_ANSWER_DOMAIN;
2761                                 }
2762                             }
2763 
2764                             // ret is set to an error
2765                         }
2766                         else
2767                         {
2768                             ret = INVALID_MESSAGE;
2769                         }
2770                     }
2771                     else
2772                     {
2773                         ret = MESSAGE_HAS_WRONG_ID;
2774                     }
2775 
2776                     s64 time_now = timeus();
2777 
2778                     if(time_now >= time_limit)
2779                     {
2780                         ret = MAKE_ERRNO_ERROR(EAGAIN);
2781                         break;
2782                     }
2783 
2784                     s64 time_remaining = time_limit - time_now;
2785 
2786                     tcp_set_recvtimeout(sockfd, time_remaining / 1000000ULL, time_remaining % 1000000ULL); /* half a second for UDP is a lot ... */
2787                 }
2788 
2789                 message_finalize(recv_mesg);
2790 
2791                 //recv_mesg._tsig.hmac = NULL;
2792 
2793                 if((n < 0) && ISOK(ret))
2794                 {
2795                     ret = ERRNO_ERROR;
2796                 }
2797 
2798                 /* timeout */
2799             }
2800             else
2801             {
2802                 ret = (n < 0)?n:ERROR;
2803             }
2804 
2805             close_ex(sockfd);
2806         }
2807         else
2808         {
2809             ret = ERRNO_ERROR;
2810         }
2811     }
2812 
2813     return ret;
2814 }
2815 
2816 ya_result
message_query(message_data * mesg,const host_address * server)2817 message_query(message_data *mesg, const host_address *server)
2818 {
2819     ya_result ret;
2820     size_t size;
2821     u8 header_copy[12];
2822 
2823     // keep a copy of the state, in case there is truncation
2824 
2825     size = message_get_size(mesg);
2826     memcpy(header_copy, mesg->_buffer, sizeof(header_copy));
2827 
2828     if(ISOK(ret = message_query_udp_with_timeout_and_retries(mesg, server, 1, 0, 3, 0)))
2829     {
2830         if(message_istruncated(mesg))
2831         {
2832             message_set_size(mesg, size);
2833             memcpy(mesg->_buffer, header_copy, sizeof(header_copy));
2834 
2835             ret = message_query_tcp_with_timeout(mesg, server, 3);
2836         }
2837     }
2838 
2839     return ret;
2840 }
2841 
2842 ya_result
message_ixfr_query_get_serial(const message_data * mesg,u32 * serial)2843 message_ixfr_query_get_serial(const message_data *mesg, u32 *serial)
2844 {
2845     packet_unpack_reader_data purd;
2846     ya_result return_value;
2847 
2848     u8 domain_fqdn[MAX_DOMAIN_LENGTH];
2849     u8 soa_fqdn[MAX_DOMAIN_LENGTH];
2850 
2851     packet_reader_init_from_message(&purd, mesg);
2852 
2853     /* Keep only the query */
2854 
2855     if(ISOK(return_value = packet_reader_read_fqdn(&purd, domain_fqdn, sizeof(domain_fqdn))))
2856     {
2857         purd.offset += 4;
2858 
2859         /* Get the queried serial */
2860 
2861         if(ISOK(return_value = packet_reader_read_fqdn(&purd, soa_fqdn, sizeof(soa_fqdn))))
2862         {
2863             if(dnsname_equals(domain_fqdn, soa_fqdn))
2864             {
2865                 u16 soa_type;
2866                 u16 soa_class;
2867                 u32 soa_ttl;
2868                 u16 soa_rdata_size;
2869                 u32 soa_serial;
2870 
2871                 if(ISOK(return_value = packet_reader_read_u16(&purd, &soa_type)))
2872                 {
2873                     if(soa_type == TYPE_SOA)
2874                     {
2875                         if(packet_reader_available(&purd) > 2 + 4 + 2)
2876                         {
2877                             packet_reader_read_u16_unchecked(&purd, &soa_class);        // checked
2878                             packet_reader_read_u32_unchecked(&purd, &soa_ttl);          // checked
2879                             packet_reader_read_u16_unchecked(&purd, &soa_rdata_size);   // checked
2880 
2881                             if(ISOK(return_value = packet_reader_skip_fqdn(&purd)))
2882                             {
2883                                 if(ISOK(return_value = packet_reader_skip_fqdn(&purd)))
2884                                 {
2885                                     if(ISOK(return_value = packet_reader_read_u32(&purd, &soa_serial)))
2886                                     {
2887                                         *serial=ntohl(soa_serial);
2888                                     }
2889                                 }
2890                             }
2891                         }
2892                         else
2893                         {
2894                             return_value = MAKE_DNSMSG_ERROR(RCODE_FORMERR);
2895                         }
2896                     }
2897                     else
2898                     {
2899                         return_value = MAKE_DNSMSG_ERROR(RCODE_FORMERR);
2900                     }
2901                 }
2902             }
2903             else
2904             {
2905                 return_value = MAKE_DNSMSG_ERROR(RCODE_FORMERR);
2906             }
2907         }
2908     }
2909 
2910     return return_value;
2911 }
2912 
2913 ya_result
message_query_serial(const u8 * origin,const host_address * server,u32 * serial_out)2914 message_query_serial(const u8 *origin, const host_address *server, u32 *serial_out)
2915 {
2916     yassert(origin != NULL);
2917     yassert(server != NULL);
2918     yassert(serial_out != NULL);
2919 
2920     /* do an SOA query */
2921 
2922     ya_result ret;
2923 
2924     random_ctx rndctx = thread_pool_get_random_ctx();
2925     message_data_with_buffer soa_query_mesg_buff;
2926     message_data *soa_query_mesg = message_data_with_buffer_init(&soa_query_mesg_buff);
2927 
2928     for(u16 countdown = 5; countdown > 0; )
2929     {
2930         u16 id = (u16)random_next(rndctx);
2931 
2932         message_make_query(soa_query_mesg, id, origin, TYPE_SOA, CLASS_IN);
2933 
2934         if(ISOK(ret = message_query_udp(soa_query_mesg, server)))
2935         {
2936             const u8 *buffer = message_get_buffer_const(soa_query_mesg);
2937 
2938             if(MESSAGE_QR(buffer))
2939             {
2940                 if(MESSAGE_ID(buffer) == id)
2941                 {
2942                     if(MESSAGE_RCODE(buffer) == RCODE_NOERROR)
2943                     {
2944                         if((MESSAGE_QD(buffer) == NETWORK_ONE_16) && ((MESSAGE_AN(buffer) == NETWORK_ONE_16) || (MESSAGE_NS(buffer) == NETWORK_ONE_16)))
2945                         {
2946                             packet_unpack_reader_data pr;
2947                             packet_reader_init_from_message_at(&pr, soa_query_mesg, DNS_HEADER_LENGTH); // scan-build false positive: if message_query_udp returns no-error, then soa_query_mesg.received is set
2948                             packet_reader_skip_fqdn(&pr);   // checked below
2949                             packet_reader_skip(&pr, 4); // checked below
2950 
2951                             if(!packet_reader_eof(&pr))
2952                             {
2953                                 u8 tmp[MAX_DOMAIN_LENGTH];
2954 
2955                                 /* read and expect an SOA */
2956 
2957                                 if(ISOK(packet_reader_read_fqdn(&pr, tmp, sizeof(tmp))))
2958                                 {
2959                                     if(dnsname_equals(tmp, origin))
2960                                     {
2961                                         struct type_class_ttl_rdlen tctr;
2962 
2963                                         if(packet_reader_read(&pr, &tctr, 10) == 10) // exact
2964                                         {
2965                                             if((tctr.qtype == TYPE_SOA) && (tctr.qclass == CLASS_IN))
2966                                             {
2967                                                 if(ISOK(ret = packet_reader_skip_fqdn(&pr)))
2968                                                 {
2969                                                     if(ISOK(ret = packet_reader_skip_fqdn(&pr)))
2970                                                     {
2971                                                         if(packet_reader_read(&pr, tmp, 4) == 4) // exact
2972                                                         {
2973                                                             *serial_out = ntohl(GET_U32_AT(tmp[0]));
2974 
2975                                                             return SUCCESS;
2976                                                         }
2977                                                     }
2978                                                 }
2979                                             }
2980                                             else
2981                                             {
2982                                                 ret = MESSAGE_UNEXPECTED_ANSWER_TYPE_CLASS;
2983                                             }
2984                                         }
2985                                         else
2986                                         {
2987                                             ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR);
2988                                         }
2989                                     }
2990                                     else
2991                                     {
2992                                         ret = MESSAGE_UNEXPECTED_ANSWER_DOMAIN;
2993                                     }
2994                                 }
2995                                 else
2996                                 {
2997                                     ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR);
2998                                 }
2999                             }
3000                             else
3001                             {
3002                                 ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR);
3003                             }
3004                         }
3005                         else
3006                         {
3007                             ret = INVALID_MESSAGE;
3008                         }
3009                     }
3010                     else
3011                     {
3012                         ret = MAKE_DNSMSG_ERROR(message_get_rcode(soa_query_mesg));
3013                     }
3014                 }
3015                 else
3016                 {
3017                     ret = MESSAGE_HAS_WRONG_ID;
3018                 }
3019             }
3020             else
3021             {
3022                 ret = MESSAGE_IS_NOT_AN_ANSWER;
3023             }
3024 
3025             break;
3026         }
3027 
3028         if(ret == MAKE_ERRNO_ERROR(EINTR))
3029         {
3030             continue;
3031         }
3032 
3033         if(ret != MAKE_ERRNO_ERROR(EAGAIN) || countdown <= 0)
3034         {
3035             /*
3036              * Do not retry for any other kind of error
3037              */
3038 
3039             break;
3040         }
3041 
3042         countdown--;
3043 
3044         usleep_ex(10000);  /* 10 ms */
3045     }
3046 
3047     return ret; // fake positive, ret has been initialised
3048 }
3049 
3050 #if MESSAGE_PAYLOAD_IS_POINTER
3051 
message_init_ex(message_data * mesg,u32 mesg_size,void * buffer,size_t buffer_size)3052 void message_init_ex(message_data* mesg, u32 mesg_size, void *buffer, size_t buffer_size)
3053 {
3054     ZEROMEMORY(mesg, offsetof(message_data, _msghdr_control_buffer)); // includes the tsig structure
3055     mesg->_msghdr.msg_name = &mesg->_sender;
3056     mesg->_msghdr.msg_namelen = sizeof(mesg->_sender);
3057     mesg->_msghdr.msg_iov = &mesg->_iovec;
3058     mesg->_msghdr.msg_iovlen = 1;
3059 #ifndef WIN32
3060     mesg->_msghdr.msg_control = NULL;
3061     mesg->_msghdr.msg_controllen = 0;
3062 #else
3063     mesg->_msghdr.msg_control.buf = NULL;
3064     mesg->_msghdr.msg_control.len = 0;
3065 #endif
3066     mesg->_msghdr.msg_flags = 0;
3067     //mesg->_msghdr.msg_control = mesg->_msghdr_control_buffer;
3068     //mesg->_msghdr.msg_controllen = sizeof(mesg->_msghdr_control_buffer);
3069 #if MESSAGE_PAYLOAD_IS_POINTER
3070     //
3071 #else
3072     mesg->_iovec.iov_base = mesg->_buffer;
3073 #endif
3074     mesg->_iovec.iov_len = buffer_size;
3075 
3076 #if MESSAGE_PAYLOAD_IS_POINTER
3077     mesg->_message_data_size = mesg_size;
3078 #endif
3079 
3080     mesg->_control_buffer_size = sizeof(mesg->_msghdr_control_buffer);
3081     mesg->_buffer_size = buffer_size;
3082     mesg->_buffer_size_limit = buffer_size;
3083     mesg->_tsig.hmac = NULL;
3084 
3085 #if MESSAGE_PAYLOAD_IS_POINTER
3086     mesg->_buffer = (u8*)buffer;
3087 
3088     mesg->_iovec.iov_base = mesg->_buffer;
3089 #if DEBUG
3090     memset(buffer,0x5a, buffer_size);
3091 #endif
3092 #else
3093 #if DEBUG
3094     memset(&mesg->_buffer,0x5a, mesg->_buffer_size_limit);
3095 #endif
3096 #endif
3097 }
3098 
3099 #else // MESSAGE_PAYLOAD_IS_POINTER
3100 
message_init(message_data * mesg)3101 void message_init(message_data* mesg)
3102 {
3103     ZEROMEMORY(mesg, offsetof(message_data, _msghdr_control_buffer));
3104     mesg->_msghdr.msg_name = &mesg->_sender;
3105     mesg->_msghdr.msg_namelen = sizeof(mesg->_sender);
3106     mesg->_msghdr.msg_iov = &mesg->_iovec;
3107     mesg->_msghdr.msg_iovlen = 1;
3108     mesg->_msghdr.msg_control = NULL;
3109     mesg->_msghdr.msg_controllen = 0;
3110     mesg->_msghdr.msg_flags = 0;
3111     //mesg->_msghdr.msg_control = mesg->_msghdr_control_buffer;
3112     //mesg->_msghdr.msg_controllen = sizeof(mesg->_msghdr_control_buffer);
3113     mesg->_iovec.iov_base = mesg->_buffer;
3114     mesg->_iovec.iov_len = NETWORK_BUFFER_SIZE;
3115     mesg->_control_buffer_size = sizeof(mesg->_msghdr_control_buffer);
3116     mesg->_buffer_size = NETWORK_BUFFER_SIZE;
3117     mesg->_buffer_size_limit = NETWORK_BUFFER_SIZE;
3118     mesg->_tsig.hmac = NULL;
3119 #if DEBUG
3120     memset(&mesg->_buffer,0x5a, mesg->_buffer_size_limit);
3121 #endif
3122 }
3123 
3124 #endif
3125 
3126 /**
3127  * If pointer is NULL, the structure and buffer will be allocated together
3128  * Note that in the current implementation, 8 bytes are reserved for TCP
3129  */
3130 
3131 message_data*
message_new_instance_ex(void * ptr,u32 message_size)3132 message_new_instance_ex(void *ptr, u32 message_size)        // should be size of edns0 or 64K for TCP
3133 {
3134     message_data *mesg;
3135     if(ptr == NULL)
3136     {
3137         u8 *tmp;
3138         size_t message_data_size = ((sizeof(message_data) + 7) & ~7) + message_size;
3139         MALLOC_OBJECT_ARRAY_OR_DIE(tmp, u8, message_data_size, MESGDATA_TAG);
3140         ptr = &tmp[(sizeof(message_data) + 7) & ~7];
3141         mesg = (message_data*)tmp;
3142         message_init_ex(mesg, message_data_size, ptr, message_size);
3143     }
3144     else
3145     {
3146         MALLOC_OBJECT_OR_DIE(mesg, message_data, MESGDATA_TAG); // legit
3147         message_init_ex(mesg, sizeof(message_data), ptr, message_size);
3148     }
3149     return mesg;
3150 }
3151 
3152 message_data*
message_new_instance()3153 message_new_instance()
3154 {
3155     message_data *mesg;
3156     mesg = message_new_instance_ex(NULL, 65536);
3157     return mesg;
3158 }
3159 
message_finalize(message_data * mesg)3160 void message_finalize(message_data *mesg)
3161 {
3162     if(mesg->_tsig.hmac != NULL)
3163     {
3164         hmac_free(mesg->_tsig.hmac);
3165         mesg->_tsig.hmac = NULL;
3166     }
3167     if(mesg->_tsig.other != NULL)
3168     {
3169        free(mesg->_tsig.other);
3170     }
3171 }
3172 
message_free(message_data * mesg)3173 void message_free(message_data *mesg)
3174 {
3175     if(mesg != NULL)
3176     {
3177         message_finalize(mesg);
3178         free(mesg); // legit
3179     }
3180 }
3181 
3182 /*
3183  * Does not clone the pool.
3184  */
3185 
3186 message_data*
message_dup(const message_data * mesg)3187 message_dup(const message_data *mesg)
3188 {
3189     size_t message_size = message_get_size(mesg);
3190     if(message_size > mesg->_buffer_size_limit)
3191     {
3192         return NULL;
3193     }
3194 
3195     message_data *clone = message_new_instance_ex(NULL, mesg->_buffer_size_limit + 8);
3196     if(message_get_additional_section_ptr_const(mesg) != NULL)
3197     {
3198         message_set_additional_section_ptr(clone,
3199                 &clone->_buffer[
3200                 message_get_additional_section_ptr_const(mesg) - message_get_buffer_const(mesg)
3201                 ]);
3202     }
3203 
3204     memcpy(&clone->_rcode_ext, &mesg->_rcode_ext,
3205             offsetof(message_data, _msghdr_control_buffer)
3206             );
3207 
3208     message_copy_sender_from(clone, mesg);
3209 #ifndef WIN32
3210     memcpy(clone->_msghdr_control_buffer, mesg->_msghdr_control_buffer, mesg->_msghdr.msg_controllen);
3211 #else
3212     memcpy(clone->_msghdr_control_buffer, mesg->_msghdr_control_buffer, mesg->_msghdr.msg_control.len);
3213 #endif
3214 
3215     dnsname_copy(clone->_canonised_fqdn, message_get_canonised_fqdn(mesg));
3216 #if !MESSAGE_PAYLOAD_IS_POINTER
3217     SET_U16_AT(clone->_buffer_tcp_len[0], GET_U16_AT(mesg->_buffer_tcp_len[0]));
3218 #endif
3219     memcpy(message_get_buffer(clone), message_get_buffer_const(mesg), message_size);
3220     message_set_size(clone, message_size);
3221 
3222     return clone;
3223 }
3224 
message_log(logger_handle * logger,int level,const message_data * mesg)3225 void message_log(logger_handle *logger, int level, const message_data *mesg)
3226 {
3227     ya_result ret;
3228     int index = 0;
3229     rdata_desc rrdesc = {0, 0, NULL};
3230     struct type_class_ttl_rdlen *tctrp;
3231     u8 rr[32768];
3232 
3233     logger_handle_msg(logger,level, "to: %{sockaddr}", message_get_sender_sa(mesg));
3234     logger_handle_msg(logger,level, "id: %i ", message_get_id(mesg));
3235     logger_handle_msg(logger,level, "flags: %02x %02x opcode: %s rcode: %s", message_get_flags_hi(mesg), message_get_flags_lo(mesg), dns_message_opcode_get_name(message_get_opcode(mesg) >> OPCODE_SHIFT), dns_message_rcode_get_name(message_get_rcode(mesg)));
3236     logger_handle_msg(logger,level, "qr: %i, an: %i, ns: %i, ar: %i",
3237             message_get_query_count(mesg), message_get_answer_count(mesg),
3238             message_get_authority_count(mesg), message_get_additional_count(mesg));
3239     packet_unpack_reader_data  pr;
3240     packet_reader_init_from_message(&pr, mesg);
3241 
3242     /* fqdn + type + class */
3243     for(u16 qc = message_get_query_count(mesg); qc > 0; --qc)
3244     {
3245         if(FAIL(ret = packet_reader_read_zone_record(&pr, rr, sizeof(rr))))
3246         {
3247             logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret);
3248             return;
3249         }
3250 
3251         u16 *type_class = (u16*)&rr[dnsname_len(rr)];
3252 
3253         logger_handle_msg(logger,level, "Q%3i: %{dnsname} %{dnstype} %{dnsclass}", index++, rr, &type_class[0], &type_class[1]);
3254     }
3255 
3256     if((message_get_opcode(mesg) == OPCODE_QUERY) || (message_get_opcode(mesg) == OPCODE_NOTIFY))
3257     {
3258         for(int section = 1; section <= 3; ++section)
3259         {
3260             index = 0;
3261 
3262             for(u16 sc = message_get_section_count(mesg, section); sc > 0; --sc)
3263             {
3264                 if(FAIL(ret = packet_reader_read_record(&pr, rr, sizeof(rr))))
3265                 {
3266                     logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret);
3267                     return;
3268                 }
3269 
3270                 tctrp = (struct type_class_ttl_rdlen *)&rr[dnsname_len(rr)];
3271                 rrdesc.type = tctrp->qtype;
3272                 rrdesc.len = ntohs(tctrp->rdlen);
3273                 rrdesc.rdata = &((u8*)tctrp)[10];
3274 
3275                 logger_handle_msg(logger, level, "%c%3i: %{dnsname} %i %{typerdatadesc}", "QANa"[section], index++, rr, ntohl(tctrp->ttl), &rrdesc);
3276             }
3277         }
3278     }
3279     else if(message_get_opcode(mesg) == OPCODE_UPDATE)
3280     {
3281         for(int section = 1; section <= 3; ++section)
3282         {
3283             index = 0;
3284 
3285             for(u16 sc = message_get_section_count(mesg, section); sc > 0; --sc)
3286             {
3287                 u8 *rdata_buffer;
3288                 s32 rttl;
3289                 u16 rtype;
3290                 u16 rclass;
3291                 u16 rdata_buffer_size;
3292                 u16 rdata_size;
3293 
3294                 if(FAIL(ret = packet_reader_read_fqdn(&pr, rr, sizeof(rr))))
3295                 {
3296                     return;
3297                 }
3298 
3299                 rdata_buffer = &rr[ret];
3300                 rdata_buffer_size = sizeof(rr) - ret;
3301 
3302                 if(FAIL(ret = packet_reader_read_u16(&pr, &rtype)))
3303                 {
3304                     logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret);
3305                     return;
3306                 }
3307 
3308                 if(FAIL(ret = packet_reader_read_u16(&pr, &rclass)))
3309                 {
3310                     logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret);
3311                     return;;
3312                 }
3313 
3314                 if(FAIL(ret = packet_reader_read_u32(&pr, (u32*)&rttl)))
3315                 {
3316                     logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret);
3317                     return;;
3318                 }
3319 
3320                 rttl = ntohl(rttl);
3321 
3322                 if(FAIL(ret = packet_reader_read_u16(&pr, &rdata_size)))
3323                 {
3324                     logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret);
3325                     return;;
3326                 }
3327 
3328                 rdata_size = ntohs(rdata_size);
3329 
3330                 if(rclass != TYPE_ANY)
3331                 {
3332                     if(FAIL(ret = packet_reader_read_rdata(&pr, rtype, rdata_size, rdata_buffer, rdata_buffer_size))) // fixed buffer
3333                     {
3334                         logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret);
3335                         return;
3336                     }
3337 
3338                     rrdesc.type = rtype;
3339                     rrdesc.len = rdata_size;
3340                     rrdesc.rdata = rdata_buffer;
3341 
3342                     logger_handle_msg(logger, level, "%c%3i: %{dnsname} %i %{dnsclass} %{typerdatadesc}", "QANa"[section], index++, rr, rttl, &rclass, &rrdesc);
3343                 }
3344                 else
3345                 {
3346                     logger_handle_msg(logger, level, "%c%3i: %{dnsname} %i %{dnsclass} %{dnstype}", "QANa"[section], index++, rr, rttl, &rclass, &rtype);
3347                 }
3348             }
3349         }
3350     }
3351 }
3352 
3353 ya_result
message_get_ixfr_query_serial(message_data * mesg,u32 * serialp)3354 message_get_ixfr_query_serial(message_data *mesg, u32 *serialp)
3355 {
3356     packet_unpack_reader_data purd;
3357     ya_result ret;
3358     u16 qtype;
3359 
3360     packet_reader_init_from_message(&purd, mesg);
3361 
3362     if(FAIL(ret = packet_reader_skip_fqdn(&purd)))
3363     {
3364         return ret;
3365     }
3366 
3367     if(FAIL(ret = packet_reader_read_u16(&purd, &qtype)))
3368     {
3369         return ret;
3370     }
3371 
3372     if(qtype != TYPE_IXFR)
3373     {
3374         return ERROR; // not an IXFR
3375     }
3376 
3377     if(FAIL(ret = packet_reader_skip(&purd, 2)))
3378     {
3379         return ret;
3380     }
3381 
3382     message_set_size(mesg, purd.offset);
3383 
3384     /* Get the queried serial */
3385 
3386     if(FAIL(ret = packet_reader_skip_fqdn(&purd)))
3387     {
3388         return ret;
3389     }
3390 
3391     if(FAIL(ret = packet_reader_skip(&purd, 10)))
3392     {
3393         return ret;
3394     }
3395 
3396     if(FAIL(ret = packet_reader_skip_fqdn(&purd)))
3397     {
3398         return ret;
3399     }
3400 
3401     if(FAIL(ret = packet_reader_skip_fqdn(&purd)))
3402     {
3403         return ret;
3404     }
3405 
3406     if(serialp != NULL)
3407     {
3408         if(FAIL(ret = packet_reader_read_u32(&purd, serialp)))
3409         {
3410             return ret;
3411         }
3412 
3413         *serialp = ntohl(*serialp);
3414     }
3415 
3416     return SUCCESS;
3417 }
3418 
3419 #if DNSCORE_HAS_TSIG_SUPPORT
3420 ya_result
message_terminate_then_write(message_data * mesg,output_stream * tcpos,tsig_tcp_message_position pos)3421 message_terminate_then_write(message_data *mesg, output_stream *tcpos, tsig_tcp_message_position pos)
3422 #else
3423 ya_result
3424 message_terminate_then_write(message_data *mesg, output_stream *tcpos, int unused)
3425 #endif
3426 {
3427     ya_result ret;
3428 
3429 #if !DNSCORE_HAS_TSIG_SUPPORT
3430 #pragma message("TSIG SUPPORT HAS BEEN DISABLED")
3431     (void)unused;
3432 #endif
3433 
3434     if(message_is_edns0(mesg)) // Dig does a TCP query with EDNS0
3435     {
3436         /* 00 00 29 SS SS rr vv 80 00 00 00 */
3437 
3438         u8 *buffer = message_get_buffer_limit(mesg);
3439         buffer[ 0] = 0;
3440         buffer[ 1] = 0;
3441         buffer[ 2] = 0x29;
3442         buffer[ 3] = edns0_maxsize >> 8;
3443         buffer[ 4] = edns0_maxsize;
3444         buffer[ 5] = message_get_status(mesg) >> 4;
3445         buffer[ 6] = mesg->_rcode_ext >> 16;
3446         buffer[ 7] = mesg->_rcode_ext >> 8;
3447         buffer[ 8] = mesg->_rcode_ext;
3448         buffer[ 9] = 0;
3449         buffer[10] = 0;
3450 
3451         message_increase_size(mesg, 11);
3452 
3453         message_set_additional_count_ne(mesg, NU16(1));
3454     }
3455     else
3456     {
3457         message_set_additional_count_ne(mesg, 0);
3458     }
3459 
3460 #if DNSCORE_HAS_TSIG_SUPPORT
3461     if(message_has_tsig(mesg))
3462     {
3463         if(FAIL(ret = tsig_sign_tcp_message(mesg, pos)))
3464         {
3465             return ret;
3466         }
3467     }
3468 #endif
3469 
3470     ret = message_write_tcp(mesg, tcpos);
3471 
3472     return ret;
3473 }
3474 
3475 /**
3476  * Maps records in a message to easily access them afterward.
3477  *
3478  * @param map the message map to initialise
3479  * @param mesg the message to map
3480  * @param tight do two passes to use the least amount of memory possible
3481  *
3482  * @return an error code
3483  */
3484 
3485 ya_result
message_map_init(message_map * map,const message_data * mesg)3486 message_map_init(message_map *map, const message_data *mesg)
3487 {
3488     map->mesg = mesg;
3489 
3490     packet_unpack_reader_data purd;
3491 
3492     packet_reader_init_from_message(&purd, mesg);
3493 
3494     ya_result ret;
3495 
3496     u16 qc = message_get_query_count(mesg);
3497     u16 an = message_get_answer_count(mesg);
3498     u16 ns = message_get_authority_count(mesg);
3499     u16 ar = message_get_additional_count(mesg);
3500 
3501     int total = qc;
3502     total += an;
3503     total += ns;
3504     total += ar;
3505 
3506     ptr_vector_init_ex(&map->records, total);
3507 
3508     int i;
3509 
3510     for(i = 0; i < qc; ++i)
3511     {
3512         ptr_vector_append(&map->records, (void*)packet_reader_get_next_u8_ptr_const(&purd));
3513         packet_reader_skip_fqdn(&purd); // checked below
3514         if(FAIL(ret = packet_reader_skip(&purd, 4)))
3515         {
3516             message_map_finalize(map);
3517             return ret;
3518         }
3519     }
3520 
3521     for(; i < total; ++i)
3522     {
3523         ptr_vector_append(&map->records, (void*)packet_reader_get_next_u8_ptr_const(&purd));
3524 
3525         if(FAIL(ret = packet_reader_skip_record(&purd)))
3526         {
3527             message_map_finalize(map);
3528             return ret;
3529         }
3530     }
3531 
3532     ret = ptr_vector_size(&map->records);
3533 
3534     map->section_base[0] = 0;
3535     map->section_base[1] = message_get_section_count(map->mesg, 0) + map->section_base[0];
3536     map->section_base[2] = message_get_section_count(map->mesg, 1) + map->section_base[1];
3537     map->section_base[3] = message_get_section_count(map->mesg, 2) + map->section_base[2];
3538 
3539     return ret;
3540 }
3541 
3542 /**
3543  * Gets the fqdn of the record at index
3544  *
3545  * @param map
3546  * @param index
3547  * @param fqdn
3548  * @param fqdn_size
3549  *
3550  * @return an error code
3551  */
3552 
3553 ya_result
message_map_get_fqdn(const message_map * map,int index,u8 * fqdn,int fqdn_size)3554 message_map_get_fqdn(const message_map *map, int index, u8 *fqdn, int fqdn_size)
3555 {
3556     if((index >= 0) && (index <= ptr_vector_last_index(&map->records)))
3557     {
3558         if(dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg),
3559                 ptr_vector_get(&map->records, index), fqdn, fqdn_size) != NULL)
3560         {
3561             return SUCCESS;
3562         }
3563     }
3564 
3565     return ERROR;
3566 }
3567 
3568 /**
3569  * Gets the type class ttl rdata_size of the record at index
3570  *
3571  * @param map
3572  * @param index
3573  * @param tctr
3574  *
3575  * @return an error code
3576  */
3577 
3578 
3579 ya_result
message_map_get_tctr(const message_map * map,int index,struct type_class_ttl_rdlen * tctr)3580 message_map_get_tctr(const message_map *map, int index, struct type_class_ttl_rdlen *tctr)
3581 {
3582     if((index >= 0) && (index <= ptr_vector_last_index(&map->records)))
3583     {
3584         const u8 *p;
3585         if((p = dnsname_skip_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg),
3586                 ptr_vector_get(&map->records, index))) != NULL)
3587         {
3588             if(index >= map->section_base[1])
3589             {
3590                 if(message_get_buffer_limit_const(map->mesg) - p >= 10)
3591                 {
3592                     memcpy(tctr, p, 10);
3593 
3594                     return SUCCESS;
3595                 }
3596             }
3597             else
3598             {
3599                 if(message_get_buffer_limit_const(map->mesg) - p >= 4)
3600                 {
3601                     memcpy(tctr, p, 4);
3602                     tctr->ttl = 0;
3603                     tctr->rdlen = 0;
3604 
3605                     return SUCCESS;
3606                 }
3607             }
3608         }
3609     }
3610 
3611     return ERROR;
3612 }
3613 
3614 /**
3615  * Gets the rdata of the record at index
3616  *
3617  * @param map
3618  * @param index
3619  * @param rdata
3620  * @param rdata_size
3621  *
3622  * @return the rdata size or an error code
3623  */
3624 
3625 ya_result
message_map_get_rdata(const message_map * map,int index,u8 * rdata,int rdata_size)3626 message_map_get_rdata(const message_map *map, int index, u8 *rdata, int rdata_size)
3627 {
3628     if((index >= (int)map->section_base[1]) && (index <= ptr_vector_last_index(&map->records)))
3629     {
3630         const u8 *p;
3631         if((p = dnsname_skip_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg),
3632                 ptr_vector_get(&map->records, index))) != NULL)
3633         {
3634             if(message_get_buffer_limit_const(map->mesg) - p >= 10)
3635             {
3636                 const u8 *rdata_base = rdata;
3637                 size_t d;
3638 
3639                 u16 rtype = GET_U16_AT_P(p);
3640                 p += 8;
3641                 u16 n = ntohs(GET_U16_AT_P(p));
3642                 p += 2;
3643 
3644                 if(message_get_buffer_limit_const(map->mesg) - p >= n)
3645                 {
3646                     switch(rtype)
3647                     {
3648                         /******************************************************************************
3649                          * The types that requires special handling (dname compression)
3650                          ******************************************************************************/
3651 
3652                         case TYPE_MX:
3653                         case TYPE_AFSDB:
3654                         {
3655                             if(rdata_size < 3) // minimal expected size
3656                             {
3657                                 return INVALID_RECORD;
3658                             }
3659 
3660                             SET_U16_AT_P(rdata, GET_U16_AT_P(p));
3661                             rdata += 2;
3662                             rdata_size -= 2;
3663                             p += 2;
3664                         }
3665 
3666                         FALLTHROUGH // fall through
3667 
3668                         case TYPE_NS:
3669                         case TYPE_CNAME:
3670                         case TYPE_DNAME:
3671                         case TYPE_PTR:
3672                         case TYPE_MB:
3673                         case TYPE_MD:
3674                         case TYPE_MF:
3675                         case TYPE_MG:
3676                         case TYPE_MR:
3677                         {
3678                             if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg),
3679                                 p, rdata, rdata_size)) != NULL)
3680                             {
3681                                 return p - rdata_base;
3682                             }
3683 
3684                             return INVALID_RECORD;
3685                         }
3686                         case TYPE_SOA:
3687                         {
3688                             if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg),
3689                                 p, rdata, rdata_size)) != NULL)
3690                             {
3691                                 d = dnsname_len(rdata);
3692                                 rdata += d;
3693                                 rdata_size -= d;
3694 
3695                                 if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg),
3696                                     p, rdata, rdata_size)) != NULL)
3697                                 {
3698                                     d = dnsname_len(rdata);
3699 
3700                                     rdata += d;
3701                                     rdata_size -= d;
3702 
3703                                     if(rdata_size >= 20)
3704                                     {
3705                                         memcpy(rdata, p, 20);
3706                                         return &rdata[20] - rdata_base;
3707                                     }
3708                                 }
3709                             }
3710 
3711                             return INVALID_RECORD;
3712                         }
3713                         case TYPE_RRSIG:    /* not supposed to be compressed */
3714                         {
3715                             if(rdata_size > RRSIG_RDATA_HEADER_LEN)
3716                             {
3717                                 const u8 *p_base = p;
3718                                 memcpy(rdata, p, RRSIG_RDATA_HEADER_LEN);
3719                                 rdata += RRSIG_RDATA_HEADER_LEN;
3720                                 rdata_size -= RRSIG_RDATA_HEADER_LEN;
3721                                 p += RRSIG_RDATA_HEADER_LEN;
3722 
3723                                 if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg),
3724                                     p, rdata, rdata_size)) != NULL)
3725                                 {
3726                                     d = dnsname_len(rdata);
3727                                     rdata += d;
3728                                     //rdata_size -= d;
3729                                     d = p - p_base;
3730                                     memcpy(rdata, p, d);
3731 
3732                                     return &rdata[d] - rdata_base;
3733                                 }
3734                             }
3735 
3736                             return INVALID_RECORD;
3737                         }
3738                         case TYPE_NSEC: /* not supposed to be compressed */
3739                         {
3740                             const u8 *p_base = p;
3741                             if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg),
3742                                 p, rdata, rdata_size)) != NULL)
3743                             {
3744                                 d = dnsname_len(rdata);
3745                                 rdata += d;
3746                                 //rdata_size -= d;
3747                                 d = p - p_base;
3748                                 memcpy(rdata, p, d);
3749 
3750                                 return &rdata[d] - rdata_base;
3751                             }
3752 
3753                             return INVALID_RECORD;
3754                         }
3755 
3756                         default:
3757                         {
3758                             if(rdata_size >= n)
3759                             {
3760                                 memcpy(rdata, p, n);
3761                                 return n;
3762                             }
3763 
3764                             return INVALID_RECORD;
3765                         }
3766                     } // switch type
3767                 }
3768             }
3769         }
3770     }
3771 
3772     return ERROR;
3773 }
3774 
3775 /**
3776  * Gets the type of the record at index
3777  *
3778  * @param map
3779  * @param index
3780  *
3781  * @return the record type or an error code
3782  */
3783 
3784 ya_result
message_map_get_type(const message_map * map,int index)3785 message_map_get_type(const message_map *map, int index)
3786 {
3787     if((index >= 0) && (index <= ptr_vector_last_index(&map->records)))
3788     {
3789         const u8 *p;
3790         if((p = dnsname_skip_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg),
3791                 ptr_vector_get(&map->records, index))) != NULL)
3792         {
3793             if(message_get_buffer_limit_const(map->mesg) - p >= 2)
3794             {
3795                 u16 rtype = GET_U16_AT_P(p);
3796 
3797                 return rtype;
3798             }
3799         }
3800     }
3801 
3802     return ERROR;
3803 }
3804 
3805 /**
3806  *
3807  * @param map
3808  *
3809  * @return the number of records mapped
3810  */
3811 
3812 int
message_map_record_count(const message_map * map)3813 message_map_record_count(const message_map *map)
3814 {
3815     int size = ptr_vector_size(&map->records);
3816     return size;
3817 }
3818 
3819 /**
3820  * Returns the index of the next record with the given type
3821  * from, and including, a given index.
3822  *
3823  * @param map
3824  * @param index
3825  * @param type
3826  * @return
3827  */
3828 
3829 int
message_map_get_next_record_from(const message_map * map,int index,u16 type)3830 message_map_get_next_record_from(const message_map *map, int index, u16 type)
3831 {
3832     ya_result ret;
3833 
3834     for(;;)
3835     {
3836         ret = message_map_get_type(map, index);
3837 
3838         if(ret == type)
3839         {
3840             return index;
3841         }
3842 
3843         if(FAIL(ret))
3844         {
3845             return ret;
3846         }
3847 
3848         ++index;
3849     }
3850 }
3851 
3852 /**
3853  * Returns the index of the next record with the given type
3854  * from, and including, a given index in a given section (0 to 3).
3855  *
3856  * @param map
3857  * @param index
3858  * @param type
3859  * @return
3860  */
3861 
3862 int
message_map_get_next_record_from_section(const message_map * map,int section,int index,u16 type)3863 message_map_get_next_record_from_section(const message_map *map, int section, int index, u16 type)
3864 {
3865     if(index < 0)
3866     {
3867         return INVALID_ARGUMENT_ERROR;
3868     }
3869 
3870     u16 sc = message_get_section_count(map->mesg, section);
3871 
3872     if(index >= sc)
3873     {
3874         return INVALID_ARGUMENT_ERROR;
3875     }
3876 
3877     ya_result ret;
3878 
3879     do
3880     {
3881         ret = message_map_get_type(map, map->section_base[section] + index);
3882 
3883         if(ret == type)
3884         {
3885             return index;
3886         }
3887 
3888         if(FAIL(ret))
3889         {
3890             return ret;
3891         }
3892 
3893         ++index;
3894     }
3895     while(index < sc);
3896 
3897     return ERROR;
3898 }
3899 
3900 /**
3901  * Releases the memory used by the map
3902  *
3903  * @param map
3904  */
3905 
3906 void
message_map_finalize(message_map * map)3907 message_map_finalize(message_map *map)
3908 {
3909     ptr_vector_destroy(&map->records);
3910 }
3911 
3912 static int
message_map_reorder_remap_type(int t,int ct)3913 message_map_reorder_remap_type(int t, int ct)
3914 {
3915     int r;
3916     switch(t)
3917     {
3918         case TYPE_SOA:
3919             r = 0 << 1;
3920             break;
3921         case TYPE_NSEC:
3922             r = 0x7ffe << 1;
3923             break;
3924         case TYPE_NSEC3:
3925             r = 0x7fff << 1;
3926             break;
3927         case TYPE_RRSIG:
3928             r = message_map_reorder_remap_type(ct, 0) + 1;
3929             break;
3930         default:
3931             r = (ntohs(t) + 0x1000) << 1;
3932             break;
3933     }
3934     return r;
3935 }
3936 
3937 static int
message_map_reorder_comparator(const void * rra,const void * rrb,void * ctx)3938 message_map_reorder_comparator(const void *rra, const void *rrb, void *ctx)
3939 {
3940     const u8 *pa = (const u8*)rra;
3941     const u8 *pb = (const u8*)rrb;
3942     message_map *map = (message_map *)ctx;
3943     struct type_class_ttl_rdlen tctra;
3944     struct type_class_ttl_rdlen tctrb;
3945     u16 ctypea;
3946     u16 ctypeb;
3947     u8 fqdna[256];
3948     u8 fqdnb[256];
3949 
3950     if(rra == rrb)
3951     {
3952         return 0;
3953     }
3954 
3955     pa = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), rra, fqdna, sizeof(fqdna));
3956     memcpy(&tctra, pa, 10);
3957     pa += 10;
3958     if(tctra.qtype == TYPE_RRSIG)
3959     {
3960         ctypea = GET_U16_AT_P(pa);
3961     }
3962     else
3963     {
3964         ctypea = 0;
3965     }
3966 
3967     pa += 10;
3968 
3969     pb = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), rrb, fqdnb, sizeof(fqdnb));
3970     memcpy(&tctrb, pb, 10);
3971     pb += 10;
3972     if(tctrb.qtype == TYPE_RRSIG)
3973     {
3974         ctypeb = GET_U16_AT_P(pb);
3975     }
3976     else
3977     {
3978         ctypeb = 0;
3979     }
3980 
3981     tctra.rdlen = ntohs(tctra.rdlen);
3982     tctrb.rdlen = ntohs(tctrb.rdlen);
3983     int rdata_size_d = tctra.rdlen;
3984     int rdata_size_min = MIN(tctra.rdlen, tctrb.rdlen);
3985     rdata_size_d -= tctrb.rdlen;
3986     int d;
3987 
3988     bool n3a = (tctra.qtype == TYPE_NSEC3) || (ctypea == TYPE_NSEC3);
3989     bool n3b = (tctrb.qtype == TYPE_NSEC3) || (ctypeb == TYPE_NSEC3);
3990 
3991     if(n3a)
3992     {
3993         if(n3b)
3994         {
3995             // both are NSEC3 related: normal sort
3996         }
3997         else
3998         {
3999             // the NSEC3 one is after the normal one
4000             return 1;
4001         }
4002     }
4003     else // the first one is not NSEC3 related
4004     {
4005         if(n3b)
4006         {
4007             // the second one is: it comes after the normal one
4008             return -1;
4009         }
4010         else
4011         {
4012             // none are NSEC3 related: normal sort
4013         }
4014     }
4015 
4016     d = dnsname_compare(fqdna, fqdnb);
4017 
4018     if(d == 0)
4019     {
4020         // let's avoid lot's of if-then-else
4021 
4022         int ta = message_map_reorder_remap_type(tctra.qtype, ctypea);
4023         int tb = message_map_reorder_remap_type(tctrb.qtype, ctypeb);
4024 
4025         d = ta - tb;
4026 
4027         if(d == 0)
4028         {
4029             d = memcmp(pa, pb, rdata_size_min);
4030 
4031             if(d == 0)
4032             {
4033                 d = rdata_size_d;
4034             }
4035         }
4036     }
4037 
4038     return d;
4039 }
4040 
4041 /**
4042  * Sorts records by section so that:
4043  * _ SOA is first,
4044  * _ NSEC is last,
4045  * _ NSEC3 labels are at the end,
4046  * _ RRSIG follows its RRSET
4047  *
4048  * @param map
4049  */
4050 
4051 void
message_map_reorder(message_map * map)4052 message_map_reorder(message_map *map)
4053 {
4054     // apply message_map_reorder_comparator to sections 1, 2 and 3.
4055     ptr_vector fakev;
4056     for(int section = 1; section < 4; ++section)
4057     {
4058         int sc = message_get_section_count(map->mesg, section);
4059         if(sc > 1)
4060         {
4061             fakev.data = &map->records.data[map->section_base[section]];
4062             fakev.offset = sc - 1;
4063             fakev.size = fakev.offset + 1;
4064             ptr_vector_qsort_r(&fakev, message_map_reorder_comparator, map);
4065         }
4066     }
4067 }
4068 
4069 void
message_map_print(const message_map * map,output_stream * os)4070 message_map_print(const message_map *map, output_stream *os)
4071 {
4072     osformat(os, ";; opcode: %s, status: %s, id: %i, flags:",
4073             dns_message_opcode_get_name(message_get_opcode(map->mesg) >> OPCODE_SHIFT),
4074             dns_message_rcode_get_name(message_get_rcode(map->mesg)),
4075             ntohs(message_get_id(map->mesg)));
4076 
4077     u8 h = message_get_flags_hi(map->mesg);
4078     if(h & QR_BITS) output_stream_write(os, "qr ", 3);
4079     if(h & AA_BITS) output_stream_write(os, "aa ", 3);
4080     if(h & TC_BITS) output_stream_write(os, "tc ", 3);
4081     if(h & RD_BITS) output_stream_write(os, "rd ", 3);
4082 
4083     u8 l = message_get_flags_hi(map->mesg);
4084 
4085     if(l & RA_BITS) output_stream_write(os, "ra ", 3);
4086     if(l & AD_BITS) output_stream_write(os, "ad ", 3);
4087     if(l & CD_BITS) output_stream_write(os, "cd ", 3);
4088 
4089     osformatln(os, "\n;; SECTION: [%i ,%i, %i, %i]",
4090             message_get_section_count(map->mesg, 0),
4091             message_get_section_count(map->mesg, 1),
4092             message_get_section_count(map->mesg, 2),
4093             message_get_section_count(map->mesg, 3));
4094 
4095     struct type_class_ttl_rdlen tctr;
4096     u8 tmp[1024];
4097 
4098     int i = 0;
4099 
4100     for(int section = 0; section < 4; ++section)
4101     {
4102         osformatln(os, ";; SECTION %i:", section);
4103 
4104         for(int n = message_get_section_count(map->mesg, section); n > 0; --n)
4105         {
4106             message_map_get_fqdn(map, i, tmp, sizeof(tmp));
4107             if(ISOK(message_map_get_tctr(map, i, &tctr)))
4108             {
4109                 osformat(os, "%{dnsname} %9i %{dnsclass} %{dnstype} ", tmp, ntohl(tctr.ttl), &tctr.qclass, &tctr.qtype);
4110 
4111                 if(section > 0)
4112                 {
4113                     int rdata_size = message_map_get_rdata(map, i, tmp, sizeof(tmp));
4114 
4115                     rdata_desc rd = {tctr.qtype, rdata_size, tmp};
4116                     osformat(os, "%{rdatadesc}", &rd);
4117                 }
4118                 osprintln(os, "");
4119 
4120                 ++i;
4121             }
4122             else
4123             {
4124                 osformatln(os, "%{dnsname} READ FAILURE\n", tmp);
4125                 break;
4126             }
4127         }
4128 
4129         osprintln(os, "");
4130     }
4131 }
4132 
message_send_udp_debug(const message_data * mesg,int sockfd)4133 s32 message_send_udp_debug(const message_data *mesg, int sockfd)
4134 {
4135     log_info("message_send_udp(%p, %i) through %{sockaddr}", mesg, sockfd, mesg->_msghdr.msg_name);
4136 
4137     s32 n;
4138 
4139     while((n = sendmsg(sockfd, &mesg->_msghdr, 0)) < 0)
4140     {
4141         int err = errno;
4142 
4143         if(err != EINTR)
4144         {
4145             return MAKE_ERRNO_ERROR(err);
4146         }
4147     }
4148 
4149     return n;
4150 }
4151 
message_send_tcp(const message_data * mesg,int sockfd)4152 ssize_t message_send_tcp(const message_data *mesg, int sockfd)
4153 {
4154     ssize_t ret;
4155     struct msghdr tcp_msghdr;
4156     struct iovec tcp_data[2];
4157     u16 tcp_len = message_get_size_u16(mesg);
4158     u16 tcp_native_len = htons(tcp_len);
4159 
4160     tcp_data[0].iov_base = &tcp_native_len;
4161     tcp_data[0].iov_len = 2;
4162     tcp_data[1].iov_base = mesg->_buffer;
4163     tcp_data[1].iov_len = tcp_len;
4164     tcp_msghdr.msg_name = mesg->_msghdr.msg_name;
4165     tcp_msghdr.msg_namelen = mesg->_msghdr.msg_namelen;
4166     tcp_msghdr.msg_iov = &tcp_data[0];
4167     tcp_msghdr.msg_iovlen = 2;
4168     tcp_msghdr.msg_control = mesg->_msghdr.msg_control;
4169     tcp_msghdr.msg_controllen = mesg->_msghdr.msg_controllen;
4170     tcp_msghdr.msg_flags = 0;
4171 
4172     s32 remain = tcp_len + 2;
4173 
4174 #if DEBUG
4175     s32 again = 0;
4176 #endif
4177 
4178     for(;;)
4179     {
4180         ret = sendmsg(sockfd, &tcp_msghdr, 0);
4181 
4182         if(ret < 0)
4183         {
4184             int err = ERRNO_ERROR;
4185             if(err == MAKE_ERRNO_ERROR(EINTR))
4186             {
4187                 continue;
4188             }
4189 
4190             if(err == MAKE_ERRNO_ERROR(EAGAIN))
4191             {
4192 #if DEBUG
4193                 ++again;
4194 #endif
4195                 usleep(100);
4196                 continue;
4197             }
4198 
4199             ret = err;
4200 
4201             break;
4202         }
4203 
4204         remain -= ret;
4205 
4206         if(remain == 0)
4207         {
4208             break;
4209         }
4210 
4211         while(tcp_msghdr.msg_iovlen > 0)
4212         {
4213             if((size_t)ret < tcp_msghdr.msg_iov[0].iov_len)
4214             {
4215                 u8* p = (u8*)tcp_msghdr.msg_iov[0].iov_base;
4216                 p += ret;
4217                 tcp_msghdr.msg_iov[0].iov_base = p;
4218                 tcp_msghdr.msg_iov[0].iov_len -= (size_t)ret;
4219                 break;
4220             }
4221             else
4222             {
4223                 ret -= (size_t)tcp_msghdr.msg_iov[0].iov_len;
4224 
4225                 ++tcp_msghdr.msg_iov;
4226                 --tcp_msghdr.msg_iovlen;
4227 
4228                 if(ret == 0)
4229                 {
4230                     break;
4231                 }
4232             }
4233         }
4234     }
4235 
4236 #if DEBUG
4237     if(again > 0)
4238     {
4239         log_debug("message_send_tcp: again=%i", again);
4240     }
4241 #endif
4242 
4243     return ret;
4244 }
4245 
4246 /** @} */
4247