int tcp_response_recursive_process (Context *cont) { const char *fn = "tcp_response_recursive_process()"; syslog (LOG_DEBUG, "%s: start", fn); switch (recursive_process (cont)) { case 0: syslog (LOG_DEBUG, "%s: return, continue", fn); /* SUCCESS */ return 0; case 1: assemble_response (cont); if (cont->mesg_len < 0 || cont->mesg_len > MAX_STREAM) { syslog (LOG_WARNING, "response message too big"); return (response_abort (cont, 1)); } if (cont->tout) cont->tout->handler = NULL; if (context_timeout_register (cont, cont->timeout)) return (response_abort (cont, -1)); /* register output */ if (ev_tcp_out_register (cont->conn_sock, cont)) return (response_abort (cont, -1)); /* change the state */ cont->process = tcp_response_writing_process; cont->retry = tcp_response_writing_retry; cont->wp = NULL; syslog (LOG_DEBUG, "%s: return, finish", fn); /* SUCCESS */ return 0; default: return (response_abort (cont, -1)); } }
int udp_response_finish (Context *cont) { const char *fn = "udp_response_finish()"; int len; syslog (LOG_DEBUG, "%s: start", fn); /* * We trim the response down if it doesn't fit in a default UDP * data in a somewhat crude way. Could be smarter, like trim * A records from response for pure IPv6 queries and so. See, if * it is needed often. Maybe better to support EDNS0 option instead. * * RFC1035 says we should truncate the message to 512 bytes and set the * tr bit in the header, but it is really vague on when a response does * not fit. RFC2181 clarifies the use of the tr bit in section 9. * * Note that similar logic is still present in mesg_assemble() in * ne_mesg.c (may disappear if we add the logic to assemble_response() * instead). */ assemble_response (cont); if (cont->mesg_len < 0 || cont->mesg_len > MAX_PACKET) { /* put the message on a diet */ list_destroy (cont->ar_list, rrset_freev); cont->ar_list = NULL; syslog (LOG_DEBUG, "Overweight, dropping additional section"); assemble_response (cont); } if (cont->mesg_len < 0 || cont->mesg_len > MAX_PACKET) { /* * ok, water adn bread then then. shuold check * RFCs, it may be better to return error msg * instead of slimmed answer. */ list_destroy (cont->ns_list, rrset_freev); cont->ns_list = NULL; syslog (LOG_DEBUG, "Overweight, dropping authority section"); assemble_response (cont); } if (cont->mesg_len < 0 || cont->mesg_len > MAX_PACKET) { /* ok, nothing viable left, so die */ list_destroy (cont->an_list, rrset_freev); cont->an_list = NULL; assemble_response (cont); cont->mesg.hdr->tc = 1; syslog (LOG_WARNING, "Obese, answers too big for UDP"); } if (cont->mesg_len < 0 || cont->mesg_len > MAX_PACKET) { syslog (LOG_ERR, "Even error msg is too big for UDP"); return (response_abort (cont, 1)); } /* send the answer */ len = net_mesg_send (cont->netifaddr, cont->mesg.p, cont->mesg_len, cont->peer); if (len < cont->mesg_len) { syslog (LOG_NOTICE, "failed to send message."); return (response_abort (cont, -1)); } context_destroy (cont); return 0; }
int tcp_response_reading_process (Context *cont) { const char *fn = "tcp_response_reading_process()"; int len; syslog (LOG_DEBUG, "%s: start", fn); if (cont->tout) cont->tout->handler = NULL; if (context_timeout_register (cont, cont->timeout)) return(response_abort (cont, -1)); len = read (cont->conn_sock, cont->wp, cont->mesg_len - (cont->wp - cont->mesg.p)); if (len <= 0) return(response_abort (cont, -1)); cont->wp += len; if (cont->wp < (cont->mesg.p + cont->mesg_len)) { syslog (LOG_DEBUG, "%s: left %zd bytes -- continue.", fn, (cont->mesg.p + cont->mesg_len) - cont->wp); /* SUCCESS */ return 0; /* the processing continues ... */ } /* all data has been read now */ ev_tcp_conn_in_remove (cont->conn_sock); if (cont->mesg.hdr->opcode == OP_QUERY) { if (cont->tout) cont->tout->handler = NULL; /* * don't register input list, * child context takes input */ switch (request_start (cont, QUERY_TCP)) { case 0: /* * We forwarded the request without problems, * asycnhronously awaiting a response. * goto recursive_processing state * clear events, child will call me then */ if (cont->tout) cont->tout->handler = NULL; cont->process = tcp_response_recursive_process; cont->retry = tcp_response_recursive_retry; /* SUCCESS */ return 0; case 1: /* Something wrong with the query */ syslog (LOG_NOTICE, "%s: Request failed", fn); cont->mesg.hdr->rcode = RC_FMTERR; default: /* totd failed itself somehow */ syslog (LOG_NOTICE, "%s: Totd failed", fn); cont->mesg.hdr->rcode = RC_SERVERERR; } } else cont->mesg.hdr->rcode = RC_NIMP; /* * Not OP_QUERY or Request failed brings us here * * Go to writing state. Timeout already done in this function * Register new output event */ if (!ev_tcp_out_register (cont->conn_sock, cont)) { assemble_response (cont); /* state change */ cont->process = tcp_response_writing_process; cont->retry = tcp_response_writing_retry; cont->wp = NULL; syslog (LOG_DEBUG, "%s: end (writing:)", fn); /* SUCCESS */ return 0; } /* FAILURE */ return (response_abort (cont, -1)); }