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