/*% Release the memory in resolver context ctx that was allocated to the lwres_gabnresponse_t. */ void lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp) { lwres_gabnresponse_t *gabn; lwres_addr_t *addr; REQUIRE(ctx != NULL); REQUIRE(structp != NULL && *structp != NULL); gabn = *structp; *structp = NULL; if (gabn->naliases > 0) { CTXFREE(gabn->aliases, sizeof(char *) * gabn->naliases); CTXFREE(gabn->aliaslen, sizeof(lwres_uint16_t) * gabn->naliases); } addr = LWRES_LIST_HEAD(gabn->addrs); while (addr != NULL) { LWRES_LIST_UNLINK(gabn->addrs, addr, link); CTXFREE(addr, sizeof(lwres_addr_t)); addr = LWRES_LIST_HEAD(gabn->addrs); } if (gabn->base != NULL) CTXFREE(gabn->base, gabn->baselen); CTXFREE(gabn, sizeof(lwres_gabnresponse_t)); }
static lwres_result_t lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp) { int idx, delim; char word[LWRES_CONFMAXLINELEN]; lwres_conf_t *confdata; confdata = &ctx->confdata; if (confdata->domainname != NULL) { /* * Search and domain are mutually exclusive. */ CTXFREE(confdata->domainname, strlen(confdata->domainname) + 1); confdata->domainname = NULL; } /* * Remove any previous search definitions. */ for (idx = 0; idx < LWRES_CONFMAXSEARCH; idx++) { if (confdata->search[idx] != NULL) { CTXFREE(confdata->search[idx], strlen(confdata->search[idx])+1); confdata->search[idx] = NULL; } } confdata->searchnxt = 0; delim = getword(fp, word, sizeof(word)); if (strlen(word) == 0U) return (LWRES_R_FAILURE); /* Nothing else on line. */ idx = 0; while (strlen(word) > 0U) { if (confdata->searchnxt == LWRES_CONFMAXSEARCH) goto ignore; /* Too many domains. */ confdata->search[idx] = lwres_strdup(ctx, word); if (confdata->search[idx] == NULL) return (LWRES_R_FAILURE); idx++; confdata->searchnxt++; ignore: if (delim == EOF || delim == '\n') break; else delim = getword(fp, word, sizeof(word)); } return (LWRES_R_SUCCESS); }
/*% Frees len bytes of space starting at location mem. */ void lwres_context_freemem(lwres_context_t *ctx, void *mem, size_t len) { REQUIRE(mem != NULL); REQUIRE(len != 0U); CTXFREE(mem, len); }
/*% Uses resolver context ctx to convert getnamebyaddr request structure req to canonical format. */ lwres_result_t lwres_gnbarequest_render (lwres_context_t * ctx, lwres_gnbarequest_t * req, lwres_lwpacket_t * pkt, lwres_buffer_t * b) { unsigned char *buf; size_t buflen; int ret; size_t payload_length; REQUIRE (ctx != NULL); REQUIRE (req != NULL); REQUIRE (req->addr.family != 0); REQUIRE (req->addr.length != 0); REQUIRE (pkt != NULL); REQUIRE (b != NULL); payload_length = 4 + 4 + 2 + +req->addr.length; buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC (buflen); if (buf == NULL) return (LWRES_R_NOMEMORY); lwres_buffer_init (b, buf, buflen); pkt->length = buflen; pkt->version = LWRES_LWPACKETVERSION_0; pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE; pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR; pkt->result = 0; pkt->authtype = 0; pkt->authlength = 0; ret = lwres_lwpacket_renderheader (b, pkt); if (ret != LWRES_R_SUCCESS) { lwres_buffer_invalidate (b); CTXFREE (buf, buflen); return (ret); } INSIST (SPACE_OK (b, payload_length)); /* * Put the length and the data. We know this will fit because we * just checked for it. */ lwres_buffer_putuint32 (b, req->flags); lwres_buffer_putuint32 (b, req->addr.family); lwres_buffer_putuint16 (b, req->addr.length); lwres_buffer_putmem (b, (unsigned char *) req->addr.address, req->addr.length); INSIST (LWRES_BUFFER_AVAILABLECOUNT (b) == 0); return (LWRES_R_SUCCESS); }
/*% Release the memory in resolver context ctx that was allocated to the lwres_gnbaresponse_t. */ void lwres_gnbaresponse_free (lwres_context_t * ctx, lwres_gnbaresponse_t ** structp) { lwres_gnbaresponse_t *gnba; REQUIRE (ctx != NULL); REQUIRE (structp != NULL && *structp != NULL); gnba = *structp; *structp = NULL; if (gnba->naliases > 0) { CTXFREE (gnba->aliases, sizeof (char *) * gnba->naliases); CTXFREE (gnba->aliaslen, sizeof (lwres_uint16_t) * gnba->naliases); } if (gnba->base != NULL) CTXFREE (gnba->base, gnba->baselen); CTXFREE (gnba, sizeof (lwres_gnbaresponse_t)); }
/*% Frees up all the internal memory used by the config data structure, returning it to the lwres_context_t. */ void lwres_conf_clear(lwres_context_t *ctx) { int i; lwres_conf_t *confdata; REQUIRE(ctx != NULL); confdata = &ctx->confdata; for (i = 0; i < confdata->nsnext; i++) { lwres_resetaddr(&confdata->nameservers[i]); confdata->nameserverports[i] = 0; } if (confdata->domainname != NULL) { CTXFREE(confdata->domainname, strlen(confdata->domainname) + 1); confdata->domainname = NULL; } for (i = 0; i < confdata->searchnxt; i++) { if (confdata->search[i] != NULL) { CTXFREE(confdata->search[i], strlen(confdata->search[i]) + 1); confdata->search[i] = NULL; } } for (i = 0; i < LWRES_CONFMAXSORTLIST; i++) { lwres_resetaddr(&confdata->sortlist[i].addr); lwres_resetaddr(&confdata->sortlist[i].mask); } confdata->nsnext = 0; confdata->lwnext = 0; confdata->domainname = NULL; confdata->searchnxt = 0; confdata->sortlistnxt = 0; confdata->resdebug = 0; confdata->ndots = 1; confdata->no_tld_query = 0; }
static IWorkUnit * updateWorkunit(ICodeContext * ctx) { // following bit of a kludge, as // 1) eclagent keeps WU locked, and // 2) rtti not available in generated .so's to convert to IAgentContext IAgentContext * actx = dynamic_cast<IAgentContext *>(ctx); if (actx == NULL) { // fall back to pure ICodeContext // the following works for thor only char * platform = ctx->getPlatform(); if (strcmp(platform,"thor")==0) { CTXFREE(parentCtx, platform); Owned<IWorkUnitFactory> factory = getWorkUnitFactory(); StringAttr wuid; wuid.setown(ctx->getWuid()); return factory->updateWorkUnit(wuid); } CTXFREE(parentCtx, platform); return NULL; } return actx->updateWorkUnit(); }
/*% Release the memory in resolver context ctx that was allocated to the lwres_gnbarequest_t. */ void lwres_gnbarequest_free (lwres_context_t * ctx, lwres_gnbarequest_t ** structp) { lwres_gnbarequest_t *gnba; REQUIRE (ctx != NULL); REQUIRE (structp != NULL && *structp != NULL); gnba = *structp; *structp = NULL; CTXFREE (gnba, sizeof (lwres_gnbarequest_t)); }
static lwres_result_t lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp) { char word[LWRES_CONFMAXLINELEN]; int res, i; lwres_conf_t *confdata; confdata = &ctx->confdata; res = getword(fp, word, sizeof(word)); if (strlen(word) == 0U) return (LWRES_R_FAILURE); /* Nothing else on line. */ else if (res == ' ' || res == '\t') res = eatwhite(fp); if (res != EOF && res != '\n') return (LWRES_R_FAILURE); /* Extra junk on line. */ if (confdata->domainname != NULL) CTXFREE(confdata->domainname, strlen(confdata->domainname) + 1); /* */ /* * Search and domain are mutually exclusive. */ for (i = 0; i < LWRES_CONFMAXSEARCH; i++) { if (confdata->search[i] != NULL) { CTXFREE(confdata->search[i], strlen(confdata->search[i])+1); confdata->search[i] = NULL; } } confdata->searchnxt = 0; confdata->domainname = lwres_strdup(ctx, word); if (confdata->domainname == NULL) return (LWRES_R_FAILURE); return (LWRES_R_SUCCESS); }
/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ void lwres_grbnrequest_free(lwres_context_t *ctx, lwres_grbnrequest_t **structp) { lwres_grbnrequest_t *grbn; REQUIRE(ctx != NULL); REQUIRE(structp != NULL && *structp != NULL); grbn = *structp; *structp = NULL; CTXFREE(grbn, sizeof(lwres_grbnrequest_t)); }
/*% Release the memory in resolver context ctx. */ void lwres_nooprequest_free(lwres_context_t *ctx, lwres_nooprequest_t **structp) { lwres_nooprequest_t *noop; REQUIRE(ctx != NULL); REQUIRE(structp != NULL && *structp != NULL); noop = *structp; *structp = NULL; CTXFREE(noop, sizeof(lwres_nooprequest_t)); }
lwres_result_t lwres_noopresponse_render(lwres_context_t *ctx, lwres_noopresponse_t *req, lwres_lwpacket_t *pkt, lwres_buffer_t *b) { unsigned char *buf; size_t buflen; int ret; size_t payload_length; REQUIRE(ctx != NULL); REQUIRE(req != NULL); REQUIRE(pkt != NULL); REQUIRE(b != NULL); payload_length = sizeof(lwres_uint16_t) + req->datalength; buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC(buflen); if (buf == NULL) return (LWRES_R_NOMEMORY); lwres_buffer_init(b, buf, (unsigned int)buflen); pkt->length = (lwres_uint32_t)buflen; pkt->version = LWRES_LWPACKETVERSION_0; pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE; pkt->opcode = LWRES_OPCODE_NOOP; pkt->authtype = 0; pkt->authlength = 0; ret = lwres_lwpacket_renderheader(b, pkt); if (ret != LWRES_R_SUCCESS) { lwres_buffer_invalidate(b); CTXFREE(buf, buflen); return (ret); } INSIST(SPACE_OK(b, payload_length)); /* * Put the length and the data. We know this will fit because we * just checked for it. */ lwres_buffer_putuint16(b, req->datalength); lwres_buffer_putmem(b, req->data, req->datalength); INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); return (LWRES_R_SUCCESS); }
/*% Offers the same semantics as lwres_nooprequest_parse() except it yields a lwres_noopresponse_t structure. */ lwres_result_t lwres_noopresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, lwres_lwpacket_t *pkt, lwres_noopresponse_t **structp) { int ret; lwres_noopresponse_t *req; REQUIRE(ctx != NULL); REQUIRE(b != NULL); REQUIRE(pkt != NULL); REQUIRE(structp != NULL && *structp == NULL); if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0) return (LWRES_R_FAILURE); req = CTXMALLOC(sizeof(lwres_noopresponse_t)); if (req == NULL) return (LWRES_R_NOMEMORY); if (!SPACE_REMAINING(b, sizeof(lwres_uint16_t))) { ret = LWRES_R_UNEXPECTEDEND; goto out; } req->datalength = lwres_buffer_getuint16(b); if (!SPACE_REMAINING(b, req->datalength)) { ret = LWRES_R_UNEXPECTEDEND; goto out; } req->data = b->base + b->current; lwres_buffer_forward(b, req->datalength); if (LWRES_BUFFER_REMAINING(b) != 0) { ret = LWRES_R_TRAILINGDATA; goto out; } /* success! */ *structp = req; return (LWRES_R_SUCCESS); /* Error return */ out: CTXFREE(req, sizeof(lwres_noopresponse_t)); return (ret); }
/*% Destroys a #lwres_context_t, closing its socket. contextp is a pointer to a pointer to the context that is to be destroyed. The pointer will be set to NULL when the context has been destroyed. */ void lwres_context_destroy(lwres_context_t **contextp) { lwres_context_t *ctx; REQUIRE(contextp != NULL && *contextp != NULL); ctx = *contextp; *contextp = NULL; if (ctx->sock != -1) { #ifdef WIN32 DestroySockets(); #endif (void)close(ctx->sock); ctx->sock = -1; } CTXFREE(ctx, sizeof(lwres_context_t)); }
/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ void lwres_grbnresponse_free(lwres_context_t *ctx, lwres_grbnresponse_t **structp) { lwres_grbnresponse_t *grbn; REQUIRE(ctx != NULL); REQUIRE(structp != NULL && *structp != NULL); grbn = *structp; *structp = NULL; if (grbn->nrdatas > 0) { CTXFREE(grbn->rdatas, sizeof(char *) * grbn->nrdatas); CTXFREE(grbn->rdatalen, sizeof(lwres_uint16_t) * grbn->nrdatas); } if (grbn->nsigs > 0) { CTXFREE(grbn->sigs, sizeof(char *) * grbn->nsigs); CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * grbn->nsigs); } if (grbn->base != NULL) CTXFREE(grbn->base, grbn->baselen); CTXFREE(grbn, sizeof(lwres_grbnresponse_t)); }
int lwres_getrrsetbyname_read(struct lwres_async_state **plas, lwres_context_t *ctx, struct rrsetinfo **res) { lwres_result_t lwresult; lwres_grbnresponse_t *response = NULL; char *buffer; struct rrsetinfo *rrset = NULL; int recvlen; int ret, result; unsigned int i; lwres_buffer_t b_in; struct lwres_async_state *las; struct lwres_async_state **las_prev; lwres_lwpacket_t pkt; buffer = NULL; buffer = CTXMALLOC(LWRES_RECVLENGTH); if (buffer == NULL) { return ERRSET_NOMEMORY; } ret = LWRES_R_SUCCESS; lwresult = lwres_context_recv(ctx, buffer, LWRES_RECVLENGTH, &recvlen); if (lwresult == LWRES_R_RETRY) { ret = LWRES_R_RETRY; goto out; } if (ret != LWRES_R_SUCCESS) goto out; lwres_buffer_init(&b_in, buffer, recvlen); b_in.used = recvlen; /* * Parse the packet header. */ ret = lwres_lwpacket_parseheader(&b_in, &pkt); if (ret != LWRES_R_SUCCESS) goto out; /* * find an appropriate waiting las entry. This is a linear search. * we can do MUCH better, since we control the serial number! * do that later. */ las_prev = &ctx->pending; las = ctx->pending; while(las && las->serial != pkt.serial) { las_prev=&las->next; las=las->next; } if(las == NULL) { /* no matching serial number! */ return(LWRES_R_RETRY); } /* okay, remove it from the receive queue */ *las_prev = las->next; las->next = NULL; las->inqueue = 0; *plas = las; /* * Free what we've transmitted, long ago. */ CTXFREE(las->b_out.base, las->b_out.length); las->b_out.base = NULL; las->b_out.length = 0; if (pkt.result != LWRES_R_SUCCESS) { ret = pkt.result; goto out; } /* * Parse the response. */ ret = lwres_grbnresponse_parse(ctx, &b_in, &pkt, &response); if (ret != LWRES_R_SUCCESS) { out: if (buffer != NULL) CTXFREE(buffer, LWRES_RECVLENGTH); if (response != NULL) lwres_grbnresponse_free(ctx, &response); result = lwresult_to_result(ret); goto fail; } response->base = buffer; response->baselen = LWRES_RECVLENGTH; buffer = NULL; /* don't free this below */ lwresult = LWRES_R_SUCCESS; rrset = sane_malloc(sizeof(struct rrsetinfo)); if (rrset == NULL) { result = ERRSET_NOMEMORY; goto fail; } rrset->rri_name = NULL; rrset->rri_rdclass = response->rdclass; rrset->rri_rdtype = response->rdtype; rrset->rri_ttl = response->ttl; rrset->rri_flags = 0; rrset->rri_nrdatas = 0; rrset->rri_rdatas = NULL; rrset->rri_nsigs = 0; rrset->rri_sigs = NULL; rrset->rri_name = sane_malloc(response->realnamelen + 1); if (rrset->rri_name == NULL) { result = ERRSET_NOMEMORY; goto fail; } strncpy(rrset->rri_name, response->realname, response->realnamelen); rrset->rri_name[response->realnamelen] = 0; if ((response->flags & LWRDATA_VALIDATED) != 0) rrset->rri_flags |= RRSET_VALIDATED; rrset->rri_nrdatas = response->nrdatas; rrset->rri_rdatas = sane_calloc(rrset->rri_nrdatas, sizeof(struct rdatainfo)); if (rrset->rri_rdatas == NULL) { result = ERRSET_NOMEMORY; goto fail; } for (i = 0; i < rrset->rri_nrdatas; i++) { rrset->rri_rdatas[i].rdi_length = response->rdatalen[i]; rrset->rri_rdatas[i].rdi_data = sane_malloc(rrset->rri_rdatas[i].rdi_length); if (rrset->rri_rdatas[i].rdi_data == NULL) { result = ERRSET_NOMEMORY; goto fail; } memcpy(rrset->rri_rdatas[i].rdi_data, response->rdatas[i], rrset->rri_rdatas[i].rdi_length); } rrset->rri_nsigs = response->nsigs; rrset->rri_sigs = sane_calloc(rrset->rri_nsigs, sizeof(struct rdatainfo)); if (rrset->rri_sigs == NULL) { result = ERRSET_NOMEMORY; goto fail; } for (i = 0; i < rrset->rri_nsigs; i++) { rrset->rri_sigs[i].rdi_length = response->siglen[i]; rrset->rri_sigs[i].rdi_data = sane_malloc(rrset->rri_sigs[i].rdi_length); if (rrset->rri_sigs[i].rdi_data == NULL) { result = ERRSET_NOMEMORY; goto fail; } memcpy(rrset->rri_sigs[i].rdi_data, response->sigs[i], rrset->rri_sigs[i].rdi_length); } lwres_grbnresponse_free(ctx, &response); *res = rrset; return (ERRSET_SUCCESS); fail: if (rrset != NULL) lwres_freerrset(rrset); if (response != NULL) lwres_grbnresponse_free(ctx, &response); return (result); }
/*% converts a getaddrbyname response structure lwres_gabnresponse_t to the lightweight resolver's canonical format. */ lwres_result_t lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req, lwres_lwpacket_t *pkt, lwres_buffer_t *b) { unsigned char *buf; size_t buflen; int ret; size_t payload_length; lwres_uint16_t datalen; lwres_addr_t *addr; int x; REQUIRE(ctx != NULL); REQUIRE(req != NULL); REQUIRE(pkt != NULL); REQUIRE(b != NULL); /* naliases, naddrs */ payload_length = 4 + 2 + 2; /* real name encoding */ payload_length += 2 + req->realnamelen + 1; /* each alias */ for (x = 0; x < req->naliases; x++) payload_length += 2 + req->aliaslen[x] + 1; /* each address */ x = 0; addr = LWRES_LIST_HEAD(req->addrs); while (addr != NULL) { payload_length += 4 + 2; payload_length += addr->length; addr = LWRES_LIST_NEXT(addr, link); x++; } INSIST(x == req->naddrs); buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC(buflen); if (buf == NULL) return (LWRES_R_NOMEMORY); lwres_buffer_init(b, buf, (unsigned int)buflen); pkt->length = (lwres_uint32_t)buflen; pkt->version = LWRES_LWPACKETVERSION_0; pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE; pkt->opcode = LWRES_OPCODE_GETADDRSBYNAME; pkt->authtype = 0; pkt->authlength = 0; ret = lwres_lwpacket_renderheader(b, pkt); if (ret != LWRES_R_SUCCESS) { lwres_buffer_invalidate(b); CTXFREE(buf, buflen); return (ret); } /* * Check space needed here. */ INSIST(SPACE_OK(b, payload_length)); /* Flags. */ lwres_buffer_putuint32(b, req->flags); /* encode naliases and naddrs */ lwres_buffer_putuint16(b, req->naliases); lwres_buffer_putuint16(b, req->naddrs); /* encode the real name */ datalen = req->realnamelen; lwres_buffer_putuint16(b, datalen); lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen); lwres_buffer_putuint8(b, 0); /* encode the aliases */ for (x = 0; x < req->naliases; x++) { datalen = req->aliaslen[x]; lwres_buffer_putuint16(b, datalen); lwres_buffer_putmem(b, (unsigned char *)req->aliases[x], datalen); lwres_buffer_putuint8(b, 0); } /* encode the addresses */ addr = LWRES_LIST_HEAD(req->addrs); while (addr != NULL) { lwres_buffer_putuint32(b, addr->family); lwres_buffer_putuint16(b, addr->length); lwres_buffer_putmem(b, addr->address, addr->length); addr = LWRES_LIST_NEXT(addr, link); } INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length); return (LWRES_R_SUCCESS); }
lwres_result_t lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, lwres_lwpacket_t *pkt, lwres_gabnresponse_t **structp) { lwres_result_t ret; unsigned int x; lwres_uint32_t flags; lwres_uint16_t naliases; lwres_uint16_t naddrs; lwres_gabnresponse_t *gabn; lwres_addrlist_t addrlist; lwres_addr_t *addr; REQUIRE(ctx != NULL); REQUIRE(pkt != NULL); REQUIRE(b != NULL); REQUIRE(structp != NULL && *structp == NULL); gabn = NULL; if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0) return (LWRES_R_FAILURE); /* * Pull off the name itself */ if (!SPACE_REMAINING(b, 4 + 2 + 2)) return (LWRES_R_UNEXPECTEDEND); flags = lwres_buffer_getuint32(b); naliases = lwres_buffer_getuint16(b); naddrs = lwres_buffer_getuint16(b); gabn = CTXMALLOC(sizeof(lwres_gabnresponse_t)); if (gabn == NULL) return (LWRES_R_NOMEMORY); gabn->aliases = NULL; gabn->aliaslen = NULL; LWRES_LIST_INIT(gabn->addrs); gabn->base = NULL; gabn->flags = flags; gabn->naliases = naliases; gabn->naddrs = naddrs; LWRES_LIST_INIT(addrlist); if (naliases > 0) { gabn->aliases = CTXMALLOC(sizeof(char *) * naliases); if (gabn->aliases == NULL) { ret = LWRES_R_NOMEMORY; goto out; } gabn->aliaslen = CTXMALLOC(sizeof(lwres_uint16_t) * naliases); if (gabn->aliaslen == NULL) { ret = LWRES_R_NOMEMORY; goto out; } } for (x = 0; x < naddrs; x++) { addr = CTXMALLOC(sizeof(lwres_addr_t)); if (addr == NULL) { ret = LWRES_R_NOMEMORY; goto out; } LWRES_LINK_INIT(addr, link); LWRES_LIST_APPEND(addrlist, addr, link); } /* * Now, pull off the real name. */ ret = lwres_string_parse(b, &gabn->realname, &gabn->realnamelen); if (ret != LWRES_R_SUCCESS) goto out; /* * Parse off the aliases. */ for (x = 0; x < gabn->naliases; x++) { ret = lwres_string_parse(b, &gabn->aliases[x], &gabn->aliaslen[x]); if (ret != LWRES_R_SUCCESS) goto out; } /* * Pull off the addresses. We already strung the linked list * up above. */ addr = LWRES_LIST_HEAD(addrlist); for (x = 0; x < gabn->naddrs; x++) { INSIST(addr != NULL); ret = lwres_addr_parse(b, addr); if (ret != LWRES_R_SUCCESS) goto out; addr = LWRES_LIST_NEXT(addr, link); } if (LWRES_BUFFER_REMAINING(b) != 0) { ret = LWRES_R_TRAILINGDATA; goto out; } gabn->addrs = addrlist; *structp = gabn; return (LWRES_R_SUCCESS); out: if (gabn != NULL) { if (gabn->aliases != NULL) CTXFREE(gabn->aliases, sizeof(char *) * naliases); if (gabn->aliaslen != NULL) CTXFREE(gabn->aliaslen, sizeof(lwres_uint16_t) * naliases); addr = LWRES_LIST_HEAD(addrlist); while (addr != NULL) { LWRES_LIST_UNLINK(addrlist, addr, link); CTXFREE(addr, sizeof(lwres_addr_t)); addr = LWRES_LIST_HEAD(addrlist); } CTXFREE(gabn, sizeof(lwres_gabnresponse_t)); } return (ret); }
lwres_result_t lwres_gnbaresponse_parse (lwres_context_t * ctx, lwres_buffer_t * b, lwres_lwpacket_t * pkt, lwres_gnbaresponse_t ** structp) { int ret; unsigned int x; lwres_uint32_t flags; lwres_uint16_t naliases; lwres_gnbaresponse_t *gnba; REQUIRE (ctx != NULL); REQUIRE (pkt != NULL); REQUIRE (b != NULL); REQUIRE (structp != NULL && *structp == NULL); gnba = NULL; if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0) return (LWRES_R_FAILURE); /* * Pull off flags & naliases */ if (!SPACE_REMAINING (b, 4 + 2)) return (LWRES_R_UNEXPECTEDEND); flags = lwres_buffer_getuint32 (b); naliases = lwres_buffer_getuint16 (b); gnba = CTXMALLOC (sizeof (lwres_gnbaresponse_t)); if (gnba == NULL) return (LWRES_R_NOMEMORY); gnba->base = NULL; gnba->aliases = NULL; gnba->aliaslen = NULL; gnba->flags = flags; gnba->naliases = naliases; if (naliases > 0) { gnba->aliases = CTXMALLOC (sizeof (char *) * naliases); if (gnba->aliases == NULL) { ret = LWRES_R_NOMEMORY; goto out; } gnba->aliaslen = CTXMALLOC (sizeof (lwres_uint16_t) * naliases); if (gnba->aliaslen == NULL) { ret = LWRES_R_NOMEMORY; goto out; } } /* * Now, pull off the real name. */ ret = lwres_string_parse (b, &gnba->realname, &gnba->realnamelen); if (ret != LWRES_R_SUCCESS) goto out; /* * Parse off the aliases. */ for (x = 0; x < gnba->naliases; x++) { ret = lwres_string_parse (b, &gnba->aliases[x], &gnba->aliaslen[x]); if (ret != LWRES_R_SUCCESS) goto out; } if (LWRES_BUFFER_REMAINING (b) != 0) { ret = LWRES_R_TRAILINGDATA; goto out; } *structp = gnba; return (LWRES_R_SUCCESS); out: if (gnba != NULL) { if (gnba->aliases != NULL) CTXFREE (gnba->aliases, sizeof (char *) * naliases); if (gnba->aliaslen != NULL) CTXFREE (gnba->aliaslen, sizeof (lwres_uint16_t) * naliases); CTXFREE (gnba, sizeof (lwres_gnbaresponse_t)); } return (ret); }
/*% Converts a getnamebyaddr response structure lwres_gnbaresponse_t to the lightweight resolver's canonical format. */ lwres_result_t lwres_gnbaresponse_render (lwres_context_t * ctx, lwres_gnbaresponse_t * req, lwres_lwpacket_t * pkt, lwres_buffer_t * b) { unsigned char *buf; size_t buflen; int ret; size_t payload_length; lwres_uint16_t datalen; int x; REQUIRE (ctx != NULL); REQUIRE (req != NULL); REQUIRE (pkt != NULL); REQUIRE (b != NULL); /* * Calculate packet size. */ payload_length = 4; /* flags */ payload_length += 2; /* naliases */ payload_length += 2 + req->realnamelen + 1; /* real name encoding */ for (x = 0; x < req->naliases; x++) /* each alias */ payload_length += 2 + req->aliaslen[x] + 1; buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC (buflen); if (buf == NULL) return (LWRES_R_NOMEMORY); lwres_buffer_init (b, buf, buflen); pkt->length = buflen; pkt->version = LWRES_LWPACKETVERSION_0; pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE; pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR; pkt->authtype = 0; pkt->authlength = 0; ret = lwres_lwpacket_renderheader (b, pkt); if (ret != LWRES_R_SUCCESS) { lwres_buffer_invalidate (b); CTXFREE (buf, buflen); return (ret); } INSIST (SPACE_OK (b, payload_length)); lwres_buffer_putuint32 (b, req->flags); /* encode naliases */ lwres_buffer_putuint16 (b, req->naliases); /* encode the real name */ datalen = req->realnamelen; lwres_buffer_putuint16 (b, datalen); lwres_buffer_putmem (b, (unsigned char *) req->realname, datalen); lwres_buffer_putuint8 (b, 0); /* encode the aliases */ for (x = 0; x < req->naliases; x++) { datalen = req->aliaslen[x]; lwres_buffer_putuint16 (b, datalen); lwres_buffer_putmem (b, (unsigned char *) req->aliases[x], datalen); lwres_buffer_putuint8 (b, 0); } INSIST (LWRES_BUFFER_AVAILABLECOUNT (b) == 0); return (LWRES_R_SUCCESS); }
/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ lwres_result_t lwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req, lwres_lwpacket_t *pkt, lwres_buffer_t *b) { unsigned char *buf; size_t buflen; int ret; size_t payload_length; lwres_uint16_t datalen; REQUIRE(ctx != NULL); REQUIRE(req != NULL); REQUIRE(req->name != NULL); REQUIRE(pkt != NULL); REQUIRE(b != NULL); datalen = strlen(req->name); payload_length = 4 + 2 + 2 + 2 + req->namelen + 1; buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC(buflen); if (buf == NULL) return (LWRES_R_NOMEMORY); lwres_buffer_init(b, buf, buflen); pkt->length = buflen; pkt->version = LWRES_LWPACKETVERSION_0; pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE; pkt->opcode = LWRES_OPCODE_GETRDATABYNAME; pkt->result = 0; pkt->authtype = 0; pkt->authlength = 0; ret = lwres_lwpacket_renderheader(b, pkt); if (ret != LWRES_R_SUCCESS) { lwres_buffer_invalidate(b); CTXFREE(buf, buflen); return (ret); } INSIST(SPACE_OK(b, payload_length)); /* * Flags. */ lwres_buffer_putuint32(b, req->flags); /* * Class. */ lwres_buffer_putuint16(b, req->rdclass); /* * Type. */ lwres_buffer_putuint16(b, req->rdtype); /* * Put the length and the data. We know this will fit because we * just checked for it. */ lwres_buffer_putuint16(b, datalen); lwres_buffer_putmem(b, (unsigned char *)req->name, datalen); lwres_buffer_putuint8(b, 0); /* trailing NUL */ INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); return (LWRES_R_SUCCESS); }
/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ lwres_result_t lwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b, lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp) { lwres_result_t ret; unsigned int x; lwres_uint32_t flags; lwres_uint16_t rdclass, rdtype; lwres_uint32_t ttl; lwres_uint16_t nrdatas, nsigs; lwres_grbnresponse_t *grbn; REQUIRE(ctx != NULL); REQUIRE(pkt != NULL); REQUIRE(b != NULL); REQUIRE(structp != NULL && *structp == NULL); grbn = NULL; if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0) return (LWRES_R_FAILURE); /* * Pull off the flags, class, type, ttl, nrdatas, and nsigs */ if (!SPACE_REMAINING(b, 4 + 2 + 2 + 4 + 2 + 2)) return (LWRES_R_UNEXPECTEDEND); flags = lwres_buffer_getuint32(b); rdclass = lwres_buffer_getuint16(b); rdtype = lwres_buffer_getuint16(b); ttl = lwres_buffer_getuint32(b); nrdatas = lwres_buffer_getuint16(b); nsigs = lwres_buffer_getuint16(b); /* * Pull off the name itself */ grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t)); if (grbn == NULL) return (LWRES_R_NOMEMORY); grbn->rdatas = NULL; grbn->rdatalen = NULL; grbn->sigs = NULL; grbn->siglen = NULL; grbn->base = NULL; grbn->flags = flags; grbn->rdclass = rdclass; grbn->rdtype = rdtype; grbn->ttl = ttl; grbn->nrdatas = nrdatas; grbn->nsigs = nsigs; if (nrdatas > 0) { grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas); if (grbn->rdatas == NULL) { ret = LWRES_R_NOMEMORY; goto out; } grbn->rdatalen = CTXMALLOC(sizeof(lwres_uint16_t) * nrdatas); if (grbn->rdatalen == NULL) { ret = LWRES_R_NOMEMORY; goto out; } } if (nsigs > 0) { grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs); if (grbn->sigs == NULL) { ret = LWRES_R_NOMEMORY; goto out; } grbn->siglen = CTXMALLOC(sizeof(lwres_uint16_t) * nsigs); if (grbn->siglen == NULL) { ret = LWRES_R_NOMEMORY; goto out; } } /* * Now, pull off the real name. */ ret = lwres_string_parse(b, &grbn->realname, &grbn->realnamelen); if (ret != LWRES_R_SUCCESS) goto out; /* * Parse off the rdatas. */ for (x = 0; x < grbn->nrdatas; x++) { ret = lwres_data_parse(b, &grbn->rdatas[x], &grbn->rdatalen[x]); if (ret != LWRES_R_SUCCESS) goto out; } /* * Parse off the signatures. */ for (x = 0; x < grbn->nsigs; x++) { ret = lwres_data_parse(b, &grbn->sigs[x], &grbn->siglen[x]); if (ret != LWRES_R_SUCCESS) goto out; } if (LWRES_BUFFER_REMAINING(b) != 0) { ret = LWRES_R_TRAILINGDATA; goto out; } *structp = grbn; return (LWRES_R_SUCCESS); out: if (grbn != NULL) { if (grbn->rdatas != NULL) CTXFREE(grbn->rdatas, sizeof(char *) * nrdatas); if (grbn->rdatalen != NULL) CTXFREE(grbn->rdatalen, sizeof(lwres_uint16_t) * nrdatas); if (grbn->sigs != NULL) CTXFREE(grbn->sigs, sizeof(char *) * nsigs); if (grbn->siglen != NULL) CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * nsigs); CTXFREE(grbn, sizeof(lwres_grbnresponse_t)); } return (ret); }
/*% Get rdata by name. */ lwres_result_t lwres_getrdatabyname(lwres_context_t *ctx, const char *name, lwres_uint16_t rdclass, lwres_uint16_t rdtype, lwres_uint32_t flags, lwres_grbnresponse_t **structp) { int ret; int recvlen; lwres_buffer_t b_in, b_out; lwres_lwpacket_t pkt; lwres_uint32_t serial; char *buffer; lwres_grbnrequest_t request; lwres_grbnresponse_t *response; char target_name[1024]; unsigned int target_length; REQUIRE(ctx != NULL); REQUIRE(name != NULL); REQUIRE(structp != NULL && *structp == NULL); b_in.base = NULL; b_out.base = NULL; response = NULL; buffer = NULL; serial = lwres_context_nextserial(ctx); buffer = CTXMALLOC(LWRES_RECVLENGTH); if (buffer == NULL) { ret = LWRES_R_NOMEMORY; goto out; } target_length = strlen(name); if (target_length >= sizeof(target_name)) return (LWRES_R_FAILURE); strcpy(target_name, name); /* strcpy is safe */ /* * Set up our request and render it to a buffer. */ request.rdclass = rdclass; request.rdtype = rdtype; request.flags = flags; request.name = target_name; request.namelen = target_length; pkt.pktflags = 0; pkt.serial = serial; pkt.result = 0; pkt.recvlength = LWRES_RECVLENGTH; again: ret = lwres_grbnrequest_render(ctx, &request, &pkt, &b_out); if (ret != LWRES_R_SUCCESS) goto out; ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer, LWRES_RECVLENGTH, &recvlen); if (ret != LWRES_R_SUCCESS) goto out; lwres_buffer_init(&b_in, buffer, recvlen); b_in.used = recvlen; /* * Parse the packet header. */ ret = lwres_lwpacket_parseheader(&b_in, &pkt); if (ret != LWRES_R_SUCCESS) goto out; /* * Sanity check. */ if (pkt.serial != serial) goto again; if (pkt.opcode != LWRES_OPCODE_GETRDATABYNAME) goto again; /* * Free what we've transmitted */ CTXFREE(b_out.base, b_out.length); b_out.base = NULL; b_out.length = 0; if (pkt.result != LWRES_R_SUCCESS) { ret = pkt.result; goto out; } /* * Parse the response. */ ret = lwres_grbnresponse_parse(ctx, &b_in, &pkt, &response); if (ret != LWRES_R_SUCCESS) goto out; response->base = buffer; response->baselen = LWRES_RECVLENGTH; buffer = NULL; /* don't free this below */ *structp = response; return (LWRES_R_SUCCESS); out: if (b_out.base != NULL) CTXFREE(b_out.base, b_out.length); if (buffer != NULL) CTXFREE(buffer, LWRES_RECVLENGTH); if (response != NULL) lwres_grbnresponse_free(ctx, &response); return (ret); }
/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */ lwres_result_t lwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req, lwres_lwpacket_t *pkt, lwres_buffer_t *b) { unsigned char *buf; size_t buflen; int ret; size_t payload_length; lwres_uint16_t datalen; int x; REQUIRE(ctx != NULL); REQUIRE(req != NULL); REQUIRE(pkt != NULL); REQUIRE(b != NULL); /* flags, class, type, ttl, nrdatas, nsigs */ payload_length = 4 + 2 + 2 + 4 + 2 + 2; /* real name encoding */ payload_length += 2 + req->realnamelen + 1; /* each rr */ for (x = 0; x < req->nrdatas; x++) payload_length += 2 + req->rdatalen[x]; for (x = 0; x < req->nsigs; x++) payload_length += 2 + req->siglen[x]; buflen = LWRES_LWPACKET_LENGTH + payload_length; buf = CTXMALLOC(buflen); if (buf == NULL) return (LWRES_R_NOMEMORY); lwres_buffer_init(b, buf, buflen); pkt->length = buflen; pkt->version = LWRES_LWPACKETVERSION_0; pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE; pkt->opcode = LWRES_OPCODE_GETRDATABYNAME; pkt->authtype = 0; pkt->authlength = 0; ret = lwres_lwpacket_renderheader(b, pkt); if (ret != LWRES_R_SUCCESS) { lwres_buffer_invalidate(b); CTXFREE(buf, buflen); return (ret); } /* * Check space needed here. */ INSIST(SPACE_OK(b, payload_length)); /* Flags. */ lwres_buffer_putuint32(b, req->flags); /* encode class, type, ttl, and nrdatas */ lwres_buffer_putuint16(b, req->rdclass); lwres_buffer_putuint16(b, req->rdtype); lwres_buffer_putuint32(b, req->ttl); lwres_buffer_putuint16(b, req->nrdatas); lwres_buffer_putuint16(b, req->nsigs); /* encode the real name */ datalen = req->realnamelen; lwres_buffer_putuint16(b, datalen); lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen); lwres_buffer_putuint8(b, 0); /* encode the rdatas */ for (x = 0; x < req->nrdatas; x++) { datalen = req->rdatalen[x]; lwres_buffer_putuint16(b, datalen); lwres_buffer_putmem(b, req->rdatas[x], datalen); } /* encode the signatures */ for (x = 0; x < req->nsigs; x++) { datalen = req->siglen[x]; lwres_buffer_putuint16(b, datalen); lwres_buffer_putmem(b, req->sigs[x], datalen); } INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0); INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length); return (LWRES_R_SUCCESS); }
/*% Used to perform reverse lookups. */ lwres_result_t lwres_getnamebyaddr(lwres_context_t *ctx, lwres_uint32_t addrtype, lwres_uint16_t addrlen, const unsigned char *addr, lwres_gnbaresponse_t **structp) { lwres_gnbarequest_t request; lwres_gnbaresponse_t *response; int ret; int recvlen; lwres_buffer_t b_in, b_out; lwres_lwpacket_t pkt; lwres_uint32_t serial; char *buffer; REQUIRE(ctx != NULL); REQUIRE(addrtype != 0); REQUIRE(addrlen != 0); REQUIRE(addr != NULL); REQUIRE(structp != NULL && *structp == NULL); b_in.base = NULL; b_out.base = NULL; response = NULL; buffer = NULL; serial = lwres_context_nextserial(ctx); buffer = CTXMALLOC(LWRES_RECVLENGTH); if (buffer == NULL) { ret = LWRES_R_NOMEMORY; goto out; } /* * Set up our request and render it to a buffer. */ request.flags = 0; request.addr.family = addrtype; request.addr.length = addrlen; memmove(request.addr.address, addr, addrlen); pkt.pktflags = 0; pkt.serial = serial; pkt.result = 0; pkt.recvlength = LWRES_RECVLENGTH; again: ret = lwres_gnbarequest_render(ctx, &request, &pkt, &b_out); if (ret != LWRES_R_SUCCESS) goto out; ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer, LWRES_RECVLENGTH, &recvlen); if (ret != LWRES_R_SUCCESS) goto out; lwres_buffer_init(&b_in, buffer, recvlen); b_in.used = recvlen; /* * Parse the packet header. */ ret = lwres_lwpacket_parseheader(&b_in, &pkt); if (ret != LWRES_R_SUCCESS) goto out; /* * Sanity check. */ if (pkt.serial != serial) goto again; if (pkt.opcode != LWRES_OPCODE_GETNAMEBYADDR) goto again; /* * Free what we've transmitted */ CTXFREE(b_out.base, b_out.length); b_out.base = NULL; b_out.length = 0; if (pkt.result != LWRES_R_SUCCESS) { ret = pkt.result; goto out; } /* * Parse the response. */ ret = lwres_gnbaresponse_parse(ctx, &b_in, &pkt, &response); if (ret != LWRES_R_SUCCESS) goto out; response->base = buffer; response->baselen = LWRES_RECVLENGTH; buffer = NULL; /* don't free this below */ *structp = response; return (LWRES_R_SUCCESS); out: if (b_out.base != NULL) CTXFREE(b_out.base, b_out.length); if (buffer != NULL) CTXFREE(buffer, LWRES_RECVLENGTH); if (response != NULL) lwres_gnbaresponse_free(ctx, &response); return (ret); }