"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/dns/tcpmsg.c" (4 Sep 2020, 5458 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tcpmsg.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 
   14 #include <inttypes.h>
   15 
   16 #include <isc/mem.h>
   17 #include <isc/print.h>
   18 #include <isc/task.h>
   19 #include <isc/util.h>
   20 
   21 #include <dns/events.h>
   22 #include <dns/result.h>
   23 #include <dns/tcpmsg.h>
   24 
   25 #ifdef TCPMSG_DEBUG
   26 #include <stdio.h> /* Required for printf. */
   27 #define XDEBUG(x) printf x
   28 #else /* ifdef TCPMSG_DEBUG */
   29 #define XDEBUG(x)
   30 #endif /* ifdef TCPMSG_DEBUG */
   31 
   32 #define TCPMSG_MAGIC      ISC_MAGIC('T', 'C', 'P', 'm')
   33 #define VALID_TCPMSG(foo) ISC_MAGIC_VALID(foo, TCPMSG_MAGIC)
   34 
   35 static void
   36 recv_length(isc_task_t *, isc_event_t *);
   37 static void
   38 recv_message(isc_task_t *, isc_event_t *);
   39 
   40 static void
   41 recv_length(isc_task_t *task, isc_event_t *ev_in) {
   42     isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
   43     isc_event_t *dev;
   44     dns_tcpmsg_t *tcpmsg = ev_in->ev_arg;
   45     isc_region_t region;
   46     isc_result_t result;
   47 
   48     INSIST(VALID_TCPMSG(tcpmsg));
   49 
   50     dev = &tcpmsg->event;
   51     tcpmsg->address = ev->address;
   52 
   53     if (ev->result != ISC_R_SUCCESS) {
   54         tcpmsg->result = ev->result;
   55         goto send_and_free;
   56     }
   57 
   58     /*
   59      * Success.
   60      */
   61     tcpmsg->size = ntohs(tcpmsg->size);
   62     if (tcpmsg->size == 0) {
   63         tcpmsg->result = ISC_R_UNEXPECTEDEND;
   64         goto send_and_free;
   65     }
   66     if (tcpmsg->size > tcpmsg->maxsize) {
   67         tcpmsg->result = ISC_R_RANGE;
   68         goto send_and_free;
   69     }
   70 
   71     region.base = isc_mem_get(tcpmsg->mctx, tcpmsg->size);
   72     region.length = tcpmsg->size;
   73     if (region.base == NULL) {
   74         tcpmsg->result = ISC_R_NOMEMORY;
   75         goto send_and_free;
   76     }
   77     XDEBUG(("Allocated %d bytes\n", tcpmsg->size));
   78 
   79     isc_buffer_init(&tcpmsg->buffer, region.base, region.length);
   80     result = isc_socket_recv(tcpmsg->sock, &region, 0, task, recv_message,
   81                  tcpmsg);
   82     if (result != ISC_R_SUCCESS) {
   83         tcpmsg->result = result;
   84         goto send_and_free;
   85     }
   86 
   87     isc_event_free(&ev_in);
   88     return;
   89 
   90 send_and_free:
   91     isc_task_send(tcpmsg->task, &dev);
   92     tcpmsg->task = NULL;
   93     isc_event_free(&ev_in);
   94     return;
   95 }
   96 
   97 static void
   98 recv_message(isc_task_t *task, isc_event_t *ev_in) {
   99     isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
  100     isc_event_t *dev;
  101     dns_tcpmsg_t *tcpmsg = ev_in->ev_arg;
  102 
  103     (void)task;
  104 
  105     INSIST(VALID_TCPMSG(tcpmsg));
  106 
  107     dev = &tcpmsg->event;
  108     tcpmsg->address = ev->address;
  109 
  110     if (ev->result != ISC_R_SUCCESS) {
  111         tcpmsg->result = ev->result;
  112         goto send_and_free;
  113     }
  114 
  115     tcpmsg->result = ISC_R_SUCCESS;
  116     isc_buffer_add(&tcpmsg->buffer, ev->n);
  117 
  118     XDEBUG(("Received %u bytes (of %d)\n", ev->n, tcpmsg->size));
  119 
  120 send_and_free:
  121     isc_task_send(tcpmsg->task, &dev);
  122     tcpmsg->task = NULL;
  123     isc_event_free(&ev_in);
  124 }
  125 
  126 void
  127 dns_tcpmsg_init(isc_mem_t *mctx, isc_socket_t *sock, dns_tcpmsg_t *tcpmsg) {
  128     REQUIRE(mctx != NULL);
  129     REQUIRE(sock != NULL);
  130     REQUIRE(tcpmsg != NULL);
  131 
  132     tcpmsg->magic = TCPMSG_MAGIC;
  133     tcpmsg->size = 0;
  134     tcpmsg->buffer.base = NULL;
  135     tcpmsg->buffer.length = 0;
  136     tcpmsg->maxsize = 65535; /* Largest message possible. */
  137     tcpmsg->mctx = mctx;
  138     tcpmsg->sock = sock;
  139     tcpmsg->task = NULL;           /* None yet. */
  140     tcpmsg->result = ISC_R_UNEXPECTED; /* None yet. */
  141 
  142     /* Should probably initialize the event here, but it can wait. */
  143 }
  144 
  145 void
  146 dns_tcpmsg_setmaxsize(dns_tcpmsg_t *tcpmsg, unsigned int maxsize) {
  147     REQUIRE(VALID_TCPMSG(tcpmsg));
  148     REQUIRE(maxsize < 65536);
  149 
  150     tcpmsg->maxsize = maxsize;
  151 }
  152 
  153 isc_result_t
  154 dns_tcpmsg_readmessage(dns_tcpmsg_t *tcpmsg, isc_task_t *task,
  155                isc_taskaction_t action, void *arg) {
  156     isc_result_t result;
  157     isc_region_t region;
  158 
  159     REQUIRE(VALID_TCPMSG(tcpmsg));
  160     REQUIRE(task != NULL);
  161     REQUIRE(tcpmsg->task == NULL); /* not currently in use */
  162 
  163     if (tcpmsg->buffer.base != NULL) {
  164         isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base,
  165                 tcpmsg->buffer.length);
  166         tcpmsg->buffer.base = NULL;
  167         tcpmsg->buffer.length = 0;
  168     }
  169 
  170     tcpmsg->task = task;
  171     tcpmsg->action = action;
  172     tcpmsg->arg = arg;
  173     tcpmsg->result = ISC_R_UNEXPECTED; /* unknown right now */
  174 
  175     ISC_EVENT_INIT(&tcpmsg->event, sizeof(isc_event_t), 0, 0,
  176                DNS_EVENT_TCPMSG, action, arg, tcpmsg, NULL, NULL);
  177 
  178     region.base = (unsigned char *)&tcpmsg->size;
  179     region.length = 2; /* uint16_t */
  180     result = isc_socket_recv(tcpmsg->sock, &region, 0, tcpmsg->task,
  181                  recv_length, tcpmsg);
  182 
  183     if (result != ISC_R_SUCCESS) {
  184         tcpmsg->task = NULL;
  185     }
  186 
  187     return (result);
  188 }
  189 
  190 void
  191 dns_tcpmsg_cancelread(dns_tcpmsg_t *tcpmsg) {
  192     REQUIRE(VALID_TCPMSG(tcpmsg));
  193 
  194     isc_socket_cancel(tcpmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
  195 }
  196 
  197 void
  198 dns_tcpmsg_keepbuffer(dns_tcpmsg_t *tcpmsg, isc_buffer_t *buffer) {
  199     REQUIRE(VALID_TCPMSG(tcpmsg));
  200     REQUIRE(buffer != NULL);
  201 
  202     *buffer = tcpmsg->buffer;
  203     tcpmsg->buffer.base = NULL;
  204     tcpmsg->buffer.length = 0;
  205 }
  206 
  207 #if 0
  208 void
  209 dns_tcpmsg_freebuffer(dns_tcpmsg_t *tcpmsg) {
  210     REQUIRE(VALID_TCPMSG(tcpmsg));
  211 
  212     if (tcpmsg->buffer.base == NULL) {
  213         return;
  214     }
  215 
  216     isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base, tcpmsg->buffer.length);
  217     tcpmsg->buffer.base = NULL;
  218     tcpmsg->buffer.length = 0;
  219 }
  220 #endif /* if 0 */
  221 
  222 void
  223 dns_tcpmsg_invalidate(dns_tcpmsg_t *tcpmsg) {
  224     REQUIRE(VALID_TCPMSG(tcpmsg));
  225 
  226     tcpmsg->magic = 0;
  227 
  228     if (tcpmsg->buffer.base != NULL) {
  229         isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base,
  230                 tcpmsg->buffer.length);
  231         tcpmsg->buffer.base = NULL;
  232         tcpmsg->buffer.length = 0;
  233     }
  234 }