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