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