1/* $NetBSD$ */ 2 3/* 4 * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 2000, 2001 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20/* Id: lwres_grbn.c,v 1.10 2007/06/19 23:47:22 tbox Exp */ 21 22/*! \file lwres_grbn.c 23 24 */ 25 26#include <config.h> 27 28#include <assert.h> 29#include <stdlib.h> 30#include <string.h> 31 32#include <lwres/lwbuffer.h> 33#include <lwres/lwpacket.h> 34#include <lwres/lwres.h> 35#include <lwres/result.h> 36 37#include "context_p.h" 38#include "assert_p.h" 39 40/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ 41lwres_result_t 42lwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req, 43 lwres_lwpacket_t *pkt, lwres_buffer_t *b) 44{ 45 unsigned char *buf; 46 size_t buflen; 47 int ret; 48 size_t payload_length; 49 lwres_uint16_t datalen; 50 51 REQUIRE(ctx != NULL); 52 REQUIRE(req != NULL); 53 REQUIRE(req->name != NULL); 54 REQUIRE(pkt != NULL); 55 REQUIRE(b != NULL); 56 57 datalen = strlen(req->name); 58 59 payload_length = 4 + 2 + 2 + 2 + req->namelen + 1; 60 61 buflen = LWRES_LWPACKET_LENGTH + payload_length; 62 buf = CTXMALLOC(buflen); 63 if (buf == NULL) 64 return (LWRES_R_NOMEMORY); 65 66 lwres_buffer_init(b, buf, buflen); 67 68 pkt->length = buflen; 69 pkt->version = LWRES_LWPACKETVERSION_0; 70 pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE; 71 pkt->opcode = LWRES_OPCODE_GETRDATABYNAME; 72 pkt->result = 0; 73 pkt->authtype = 0; 74 pkt->authlength = 0; 75 76 ret = lwres_lwpacket_renderheader(b, pkt); 77 if (ret != LWRES_R_SUCCESS) { 78 lwres_buffer_invalidate(b); 79 CTXFREE(buf, buflen); 80 return (ret); 81 } 82 83 INSIST(SPACE_OK(b, payload_length)); 84 85 /* 86 * Flags. 87 */ 88 lwres_buffer_putuint32(b, req->flags); 89 90 /* 91 * Class. 92 */ 93 lwres_buffer_putuint16(b, req->rdclass); 94 95 /* 96 * Type. 97 */ 98 lwres_buffer_putuint16(b, req->rdtype); 99 100 /* 101 * Put the length and the data. We know this will fit because we 102 * just checked for it. 103 */ 104 lwres_buffer_putuint16(b, datalen); 105 lwres_buffer_putmem(b, (unsigned char *)req->name, datalen); 106 lwres_buffer_putuint8(b, 0); /* trailing NUL */ 107 108 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); 109 110 return (LWRES_R_SUCCESS); 111} 112 113/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ 114lwres_result_t 115lwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req, 116 lwres_lwpacket_t *pkt, lwres_buffer_t *b) 117{ 118 unsigned char *buf; 119 size_t buflen; 120 int ret; 121 size_t payload_length; 122 lwres_uint16_t datalen; 123 int x; 124 125 REQUIRE(ctx != NULL); 126 REQUIRE(req != NULL); 127 REQUIRE(pkt != NULL); 128 REQUIRE(b != NULL); 129 130 /* flags, class, type, ttl, nrdatas, nsigs */ 131 payload_length = 4 + 2 + 2 + 4 + 2 + 2; 132 /* real name encoding */ 133 payload_length += 2 + req->realnamelen + 1; 134 /* each rr */ 135 for (x = 0; x < req->nrdatas; x++) 136 payload_length += 2 + req->rdatalen[x]; 137 for (x = 0; x < req->nsigs; x++) 138 payload_length += 2 + req->siglen[x]; 139 140 buflen = LWRES_LWPACKET_LENGTH + payload_length; 141 buf = CTXMALLOC(buflen); 142 if (buf == NULL) 143 return (LWRES_R_NOMEMORY); 144 lwres_buffer_init(b, buf, buflen); 145 146 pkt->length = buflen; 147 pkt->version = LWRES_LWPACKETVERSION_0; 148 pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE; 149 pkt->opcode = LWRES_OPCODE_GETRDATABYNAME; 150 pkt->authtype = 0; 151 pkt->authlength = 0; 152 153 ret = lwres_lwpacket_renderheader(b, pkt); 154 if (ret != LWRES_R_SUCCESS) { 155 lwres_buffer_invalidate(b); 156 CTXFREE(buf, buflen); 157 return (ret); 158 } 159 160 /* 161 * Check space needed here. 162 */ 163 INSIST(SPACE_OK(b, payload_length)); 164 165 /* Flags. */ 166 lwres_buffer_putuint32(b, req->flags); 167 168 /* encode class, type, ttl, and nrdatas */ 169 lwres_buffer_putuint16(b, req->rdclass); 170 lwres_buffer_putuint16(b, req->rdtype); 171 lwres_buffer_putuint32(b, req->ttl); 172 lwres_buffer_putuint16(b, req->nrdatas); 173 lwres_buffer_putuint16(b, req->nsigs); 174 175 /* encode the real name */ 176 datalen = req->realnamelen; 177 lwres_buffer_putuint16(b, datalen); 178 lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen); 179 lwres_buffer_putuint8(b, 0); 180 181 /* encode the rdatas */ 182 for (x = 0; x < req->nrdatas; x++) { 183 datalen = req->rdatalen[x]; 184 lwres_buffer_putuint16(b, datalen); 185 lwres_buffer_putmem(b, req->rdatas[x], datalen); 186 } 187 188 /* encode the signatures */ 189 for (x = 0; x < req->nsigs; x++) { 190 datalen = req->siglen[x]; 191 lwres_buffer_putuint16(b, datalen); 192 lwres_buffer_putmem(b, req->sigs[x], datalen); 193 } 194 195 INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); 196 INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length); 197 198 return (LWRES_R_SUCCESS); 199} 200 201/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ 202lwres_result_t 203lwres_grbnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b, 204 lwres_lwpacket_t *pkt, lwres_grbnrequest_t **structp) 205{ 206 int ret; 207 char *name; 208 lwres_grbnrequest_t *grbn; 209 lwres_uint32_t flags; 210 lwres_uint16_t rdclass, rdtype; 211 lwres_uint16_t namelen; 212 213 REQUIRE(ctx != NULL); 214 REQUIRE(pkt != NULL); 215 REQUIRE(b != NULL); 216 REQUIRE(structp != NULL && *structp == NULL); 217 218 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0) 219 return (LWRES_R_FAILURE); 220 221 if (!SPACE_REMAINING(b, 4 + 2 + 2)) 222 return (LWRES_R_UNEXPECTEDEND); 223 224 /* 225 * Pull off the flags, class, and type. 226 */ 227 flags = lwres_buffer_getuint32(b); 228 rdclass = lwres_buffer_getuint16(b); 229 rdtype = lwres_buffer_getuint16(b); 230 231 /* 232 * Pull off the name itself 233 */ 234 ret = lwres_string_parse(b, &name, &namelen); 235 if (ret != LWRES_R_SUCCESS) 236 return (ret); 237 238 if (LWRES_BUFFER_REMAINING(b) != 0) 239 return (LWRES_R_TRAILINGDATA); 240 241 grbn = CTXMALLOC(sizeof(lwres_grbnrequest_t)); 242 if (grbn == NULL) 243 return (LWRES_R_NOMEMORY); 244 245 grbn->flags = flags; 246 grbn->rdclass = rdclass; 247 grbn->rdtype = rdtype; 248 grbn->name = name; 249 grbn->namelen = namelen; 250 251 *structp = grbn; 252 return (LWRES_R_SUCCESS); 253} 254 255/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ 256lwres_result_t 257lwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, 258 lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp) 259{ 260 lwres_result_t ret; 261 unsigned int x; 262 lwres_uint32_t flags; 263 lwres_uint16_t rdclass, rdtype; 264 lwres_uint32_t ttl; 265 lwres_uint16_t nrdatas, nsigs; 266 lwres_grbnresponse_t *grbn; 267 268 REQUIRE(ctx != NULL); 269 REQUIRE(pkt != NULL); 270 REQUIRE(b != NULL); 271 REQUIRE(structp != NULL && *structp == NULL); 272 273 grbn = NULL; 274 275 if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0) 276 return (LWRES_R_FAILURE); 277 278 /* 279 * Pull off the flags, class, type, ttl, nrdatas, and nsigs 280 */ 281 if (!SPACE_REMAINING(b, 4 + 2 + 2 + 4 + 2 + 2)) 282 return (LWRES_R_UNEXPECTEDEND); 283 flags = lwres_buffer_getuint32(b); 284 rdclass = lwres_buffer_getuint16(b); 285 rdtype = lwres_buffer_getuint16(b); 286 ttl = lwres_buffer_getuint32(b); 287 nrdatas = lwres_buffer_getuint16(b); 288 nsigs = lwres_buffer_getuint16(b); 289 290 /* 291 * Pull off the name itself 292 */ 293 294 grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t)); 295 if (grbn == NULL) 296 return (LWRES_R_NOMEMORY); 297 grbn->rdatas = NULL; 298 grbn->rdatalen = NULL; 299 grbn->sigs = NULL; 300 grbn->siglen = NULL; 301 grbn->base = NULL; 302 303 grbn->flags = flags; 304 grbn->rdclass = rdclass; 305 grbn->rdtype = rdtype; 306 grbn->ttl = ttl; 307 grbn->nrdatas = nrdatas; 308 grbn->nsigs = nsigs; 309 310 if (nrdatas > 0) { 311 grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas); 312 if (grbn->rdatas == NULL) { 313 ret = LWRES_R_NOMEMORY; 314 goto out; 315 } 316 317 grbn->rdatalen = CTXMALLOC(sizeof(lwres_uint16_t) * nrdatas); 318 if (grbn->rdatalen == NULL) { 319 ret = LWRES_R_NOMEMORY; 320 goto out; 321 } 322 } 323 324 if (nsigs > 0) { 325 grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs); 326 if (grbn->sigs == NULL) { 327 ret = LWRES_R_NOMEMORY; 328 goto out; 329 } 330 331 grbn->siglen = CTXMALLOC(sizeof(lwres_uint16_t) * nsigs); 332 if (grbn->siglen == NULL) { 333 ret = LWRES_R_NOMEMORY; 334 goto out; 335 } 336 } 337 338 /* 339 * Now, pull off the real name. 340 */ 341 ret = lwres_string_parse(b, &grbn->realname, &grbn->realnamelen); 342 if (ret != LWRES_R_SUCCESS) 343 goto out; 344 345 /* 346 * Parse off the rdatas. 347 */ 348 for (x = 0; x < grbn->nrdatas; x++) { 349 ret = lwres_data_parse(b, &grbn->rdatas[x], 350 &grbn->rdatalen[x]); 351 if (ret != LWRES_R_SUCCESS) 352 goto out; 353 } 354 355 /* 356 * Parse off the signatures. 357 */ 358 for (x = 0; x < grbn->nsigs; x++) { 359 ret = lwres_data_parse(b, &grbn->sigs[x], &grbn->siglen[x]); 360 if (ret != LWRES_R_SUCCESS) 361 goto out; 362 } 363 364 if (LWRES_BUFFER_REMAINING(b) != 0) { 365 ret = LWRES_R_TRAILINGDATA; 366 goto out; 367 } 368 369 *structp = grbn; 370 return (LWRES_R_SUCCESS); 371 372 out: 373 if (grbn != NULL) { 374 if (grbn->rdatas != NULL) 375 CTXFREE(grbn->rdatas, sizeof(char *) * nrdatas); 376 if (grbn->rdatalen != NULL) 377 CTXFREE(grbn->rdatalen, 378 sizeof(lwres_uint16_t) * nrdatas); 379 if (grbn->sigs != NULL) 380 CTXFREE(grbn->sigs, sizeof(char *) * nsigs); 381 if (grbn->siglen != NULL) 382 CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * nsigs); 383 CTXFREE(grbn, sizeof(lwres_grbnresponse_t)); 384 } 385 386 return (ret); 387} 388 389/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ 390void 391lwres_grbnrequest_free(lwres_context_t *ctx, lwres_grbnrequest_t **structp) 392{ 393 lwres_grbnrequest_t *grbn; 394 395 REQUIRE(ctx != NULL); 396 REQUIRE(structp != NULL && *structp != NULL); 397 398 grbn = *structp; 399 *structp = NULL; 400 401 CTXFREE(grbn, sizeof(lwres_grbnrequest_t)); 402} 403 404/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ 405void 406lwres_grbnresponse_free(lwres_context_t *ctx, lwres_grbnresponse_t **structp) 407{ 408 lwres_grbnresponse_t *grbn; 409 410 REQUIRE(ctx != NULL); 411 REQUIRE(structp != NULL && *structp != NULL); 412 413 grbn = *structp; 414 *structp = NULL; 415 416 if (grbn->nrdatas > 0) { 417 CTXFREE(grbn->rdatas, sizeof(char *) * grbn->nrdatas); 418 CTXFREE(grbn->rdatalen, 419 sizeof(lwres_uint16_t) * grbn->nrdatas); 420 } 421 if (grbn->nsigs > 0) { 422 CTXFREE(grbn->sigs, sizeof(char *) * grbn->nsigs); 423 CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * grbn->nsigs); 424 } 425 if (grbn->base != NULL) 426 CTXFREE(grbn->base, grbn->baselen); 427 CTXFREE(grbn, sizeof(lwres_grbnresponse_t)); 428} 429