00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <isc/mem.h>
00025 #include <isc/task.h>
00026 #include <isc/util.h>
00027
00028 #include <dns/events.h>
00029 #include <dns/result.h>
00030 #include <dns/tcpmsg.h>
00031
00032 #ifdef TCPMSG_DEBUG
00033 #include <stdio.h>
00034 #define XDEBUG(x) printf x
00035 #else
00036 #define XDEBUG(x)
00037 #endif
00038
00039 #define TCPMSG_MAGIC ISC_MAGIC('T', 'C', 'P', 'm')
00040 #define VALID_TCPMSG(foo) ISC_MAGIC_VALID(foo, TCPMSG_MAGIC)
00041
00042 static void recv_length(isc_task_t *, isc_event_t *);
00043 static void recv_message(isc_task_t *, isc_event_t *);
00044
00045
00046 static void
00047 recv_length(isc_task_t *task, isc_event_t *ev_in) {
00048 isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
00049 isc_event_t *dev;
00050 dns_tcpmsg_t *tcpmsg = ev_in->ev_arg;
00051 isc_region_t region;
00052 isc_result_t result;
00053
00054 INSIST(VALID_TCPMSG(tcpmsg));
00055
00056 dev = &tcpmsg->event;
00057 tcpmsg->address = ev->address;
00058
00059 if (ev->result != ISC_R_SUCCESS) {
00060 tcpmsg->result = ev->result;
00061 goto send_and_free;
00062 }
00063
00064
00065
00066
00067 tcpmsg->size = ntohs(tcpmsg->size);
00068 if (tcpmsg->size == 0) {
00069 tcpmsg->result = ISC_R_UNEXPECTEDEND;
00070 goto send_and_free;
00071 }
00072 if (tcpmsg->size > tcpmsg->maxsize) {
00073 tcpmsg->result = ISC_R_RANGE;
00074 goto send_and_free;
00075 }
00076
00077 region.base = isc_mem_get(tcpmsg->mctx, tcpmsg->size);
00078 region.length = tcpmsg->size;
00079 if (region.base == NULL) {
00080 tcpmsg->result = ISC_R_NOMEMORY;
00081 goto send_and_free;
00082 }
00083 XDEBUG(("Allocated %d bytes\n", tcpmsg->size));
00084
00085 isc_buffer_init(&tcpmsg->buffer, region.base, region.length);
00086 result = isc_socket_recv(tcpmsg->sock, ®ion, 0,
00087 task, recv_message, tcpmsg);
00088 if (result != ISC_R_SUCCESS) {
00089 tcpmsg->result = result;
00090 goto send_and_free;
00091 }
00092
00093 isc_event_free(&ev_in);
00094 return;
00095
00096 send_and_free:
00097 isc_task_send(tcpmsg->task, &dev);
00098 tcpmsg->task = NULL;
00099 isc_event_free(&ev_in);
00100 return;
00101 }
00102
00103 static void
00104 recv_message(isc_task_t *task, isc_event_t *ev_in) {
00105 isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
00106 isc_event_t *dev;
00107 dns_tcpmsg_t *tcpmsg = ev_in->ev_arg;
00108
00109 (void)task;
00110
00111 INSIST(VALID_TCPMSG(tcpmsg));
00112
00113 dev = &tcpmsg->event;
00114 tcpmsg->address = ev->address;
00115
00116 if (ev->result != ISC_R_SUCCESS) {
00117 tcpmsg->result = ev->result;
00118 goto send_and_free;
00119 }
00120
00121 tcpmsg->result = ISC_R_SUCCESS;
00122 isc_buffer_add(&tcpmsg->buffer, ev->n);
00123
00124 XDEBUG(("Received %d bytes (of %d)\n", ev->n, tcpmsg->size));
00125
00126 send_and_free:
00127 isc_task_send(tcpmsg->task, &dev);
00128 tcpmsg->task = NULL;
00129 isc_event_free(&ev_in);
00130 }
00131
00132 void
00133 dns_tcpmsg_init(isc_mem_t *mctx, isc_socket_t *sock, dns_tcpmsg_t *tcpmsg) {
00134 REQUIRE(mctx != NULL);
00135 REQUIRE(sock != NULL);
00136 REQUIRE(tcpmsg != NULL);
00137
00138 tcpmsg->magic = TCPMSG_MAGIC;
00139 tcpmsg->size = 0;
00140 tcpmsg->buffer.base = NULL;
00141 tcpmsg->buffer.length = 0;
00142 tcpmsg->maxsize = 65535;
00143 tcpmsg->mctx = mctx;
00144 tcpmsg->sock = sock;
00145 tcpmsg->task = NULL;
00146 tcpmsg->result = ISC_R_UNEXPECTED;
00147
00148
00149
00150 }
00151
00152
00153 void
00154 dns_tcpmsg_setmaxsize(dns_tcpmsg_t *tcpmsg, unsigned int maxsize) {
00155 REQUIRE(VALID_TCPMSG(tcpmsg));
00156 REQUIRE(maxsize < 65536);
00157
00158 tcpmsg->maxsize = maxsize;
00159 }
00160
00161
00162 isc_result_t
00163 dns_tcpmsg_readmessage(dns_tcpmsg_t *tcpmsg,
00164 isc_task_t *task, isc_taskaction_t action, void *arg)
00165 {
00166 isc_result_t result;
00167 isc_region_t region;
00168
00169 REQUIRE(VALID_TCPMSG(tcpmsg));
00170 REQUIRE(task != NULL);
00171 REQUIRE(tcpmsg->task == NULL);
00172
00173 if (tcpmsg->buffer.base != NULL) {
00174 isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base,
00175 tcpmsg->buffer.length);
00176 tcpmsg->buffer.base = NULL;
00177 tcpmsg->buffer.length = 0;
00178 }
00179
00180 tcpmsg->task = task;
00181 tcpmsg->action = action;
00182 tcpmsg->arg = arg;
00183 tcpmsg->result = ISC_R_UNEXPECTED;
00184
00185 ISC_EVENT_INIT(&tcpmsg->event, sizeof(isc_event_t), 0, 0,
00186 DNS_EVENT_TCPMSG, action, arg, tcpmsg,
00187 NULL, NULL);
00188
00189 region.base = (unsigned char *)&tcpmsg->size;
00190 region.length = 2;
00191 result = isc_socket_recv(tcpmsg->sock, ®ion, 0,
00192 tcpmsg->task, recv_length, tcpmsg);
00193
00194 if (result != ISC_R_SUCCESS)
00195 tcpmsg->task = NULL;
00196
00197 return (result);
00198 }
00199
00200 void
00201 dns_tcpmsg_cancelread(dns_tcpmsg_t *tcpmsg) {
00202 REQUIRE(VALID_TCPMSG(tcpmsg));
00203
00204 isc_socket_cancel(tcpmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
00205 }
00206
00207 void
00208 dns_tcpmsg_keepbuffer(dns_tcpmsg_t *tcpmsg, isc_buffer_t *buffer) {
00209 REQUIRE(VALID_TCPMSG(tcpmsg));
00210 REQUIRE(buffer != NULL);
00211
00212 *buffer = tcpmsg->buffer;
00213 tcpmsg->buffer.base = NULL;
00214 tcpmsg->buffer.length = 0;
00215 }
00216
00217 #if 0
00218 void
00219 dns_tcpmsg_freebuffer(dns_tcpmsg_t *tcpmsg) {
00220 REQUIRE(VALID_TCPMSG(tcpmsg));
00221
00222 if (tcpmsg->buffer.base == NULL)
00223 return;
00224
00225 isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base, tcpmsg->buffer.length);
00226 tcpmsg->buffer.base = NULL;
00227 tcpmsg->buffer.length = 0;
00228 }
00229 #endif
00230
00231 void
00232 dns_tcpmsg_invalidate(dns_tcpmsg_t *tcpmsg) {
00233 REQUIRE(VALID_TCPMSG(tcpmsg));
00234
00235 tcpmsg->magic = 0;
00236
00237 if (tcpmsg->buffer.base != NULL) {
00238 isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base,
00239 tcpmsg->buffer.length);
00240 tcpmsg->buffer.base = NULL;
00241 tcpmsg->buffer.length = 0;
00242 }
00243 }