1135446Strhodes/* 2262706Serwin * Copyright (C) 2004, 2007, 2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1999-2002 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18234010Sdougb/* $Id$ */ 19135446Strhodes 20135446Strhodes/* Reviewed: Fri Mar 17 15:01:49 PST 2000 by explorer */ 21135446Strhodes 22135446Strhodes#ifndef RDATA_IN_1_WKS_11_C 23135446Strhodes#define RDATA_IN_1_WKS_11_C 24135446Strhodes 25135446Strhodes#include <limits.h> 26135446Strhodes#include <stdlib.h> 27135446Strhodes 28135446Strhodes#include <isc/net.h> 29135446Strhodes#include <isc/netdb.h> 30234010Sdougb#include <isc/once.h> 31135446Strhodes 32135446Strhodes#define RRTYPE_WKS_ATTRIBUTES (0) 33135446Strhodes 34234010Sdougbstatic isc_mutex_t wks_lock; 35234010Sdougb 36234010Sdougbstatic void init_lock(void) { 37234010Sdougb RUNTIME_CHECK(isc_mutex_init(&wks_lock) == ISC_R_SUCCESS); 38234010Sdougb} 39234010Sdougb 40234010Sdougbstatic isc_boolean_t 41234010Sdougbmygetprotobyname(const char *name, long *proto) { 42234010Sdougb struct protoent *pe; 43234010Sdougb 44234010Sdougb LOCK(&wks_lock); 45234010Sdougb pe = getprotobyname(name); 46234010Sdougb if (pe != NULL) 47234010Sdougb *proto = pe->p_proto; 48234010Sdougb UNLOCK(&wks_lock); 49234010Sdougb return (ISC_TF(pe != NULL)); 50234010Sdougb} 51234010Sdougb 52234010Sdougbstatic isc_boolean_t 53234010Sdougbmygetservbyname(const char *name, const char *proto, long *port) { 54234010Sdougb struct servent *se; 55234010Sdougb 56234010Sdougb LOCK(&wks_lock); 57234010Sdougb se = getservbyname(name, proto); 58234010Sdougb if (se != NULL) 59234010Sdougb *port = ntohs(se->s_port); 60234010Sdougb UNLOCK(&wks_lock); 61234010Sdougb return (ISC_TF(se != NULL)); 62234010Sdougb} 63234010Sdougb 64135446Strhodesstatic inline isc_result_t 65135446Strhodesfromtext_in_wks(ARGS_FROMTEXT) { 66234010Sdougb static isc_once_t once = ISC_ONCE_INIT; 67135446Strhodes isc_token_t token; 68135446Strhodes isc_region_t region; 69135446Strhodes struct in_addr addr; 70135446Strhodes char *e; 71135446Strhodes long proto; 72135446Strhodes unsigned char bm[8*1024]; /* 64k bits */ 73135446Strhodes long port; 74135446Strhodes long maxport = -1; 75135446Strhodes const char *ps = NULL; 76135446Strhodes unsigned int n; 77135446Strhodes char service[32]; 78135446Strhodes int i; 79135446Strhodes 80135446Strhodes REQUIRE(type == 11); 81135446Strhodes REQUIRE(rdclass == 1); 82135446Strhodes 83135446Strhodes UNUSED(type); 84135446Strhodes UNUSED(origin); 85135446Strhodes UNUSED(options); 86135446Strhodes UNUSED(rdclass); 87135446Strhodes 88234010Sdougb RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); 89234010Sdougb 90135446Strhodes /* 91135446Strhodes * IPv4 dotted quad. 92135446Strhodes */ 93135446Strhodes RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 94135446Strhodes ISC_FALSE)); 95135446Strhodes 96135446Strhodes isc_buffer_availableregion(target, ®ion); 97135446Strhodes if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1) 98135446Strhodes RETTOK(DNS_R_BADDOTTEDQUAD); 99135446Strhodes if (region.length < 4) 100135446Strhodes return (ISC_R_NOSPACE); 101262706Serwin memmove(region.base, &addr, 4); 102135446Strhodes isc_buffer_add(target, 4); 103135446Strhodes 104135446Strhodes /* 105135446Strhodes * Protocol. 106135446Strhodes */ 107135446Strhodes RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 108135446Strhodes ISC_FALSE)); 109135446Strhodes 110135446Strhodes proto = strtol(DNS_AS_STR(token), &e, 10); 111135446Strhodes if (*e == 0) 112135446Strhodes ; 113234010Sdougb else if (!mygetprotobyname(DNS_AS_STR(token), &proto)) 114135446Strhodes RETTOK(DNS_R_UNKNOWNPROTO); 115234010Sdougb 116135446Strhodes if (proto < 0 || proto > 0xff) 117135446Strhodes RETTOK(ISC_R_RANGE); 118135446Strhodes 119135446Strhodes if (proto == IPPROTO_TCP) 120135446Strhodes ps = "tcp"; 121135446Strhodes else if (proto == IPPROTO_UDP) 122135446Strhodes ps = "udp"; 123135446Strhodes 124135446Strhodes RETERR(uint8_tobuffer(proto, target)); 125135446Strhodes 126135446Strhodes memset(bm, 0, sizeof(bm)); 127135446Strhodes do { 128135446Strhodes RETERR(isc_lex_getmastertoken(lexer, &token, 129135446Strhodes isc_tokentype_string, ISC_TRUE)); 130135446Strhodes if (token.type != isc_tokentype_string) 131135446Strhodes break; 132135446Strhodes 133135446Strhodes /* 134135446Strhodes * Lowercase the service string as some getservbyname() are 135135446Strhodes * case sensitive and the database is usually in lowercase. 136135446Strhodes */ 137135446Strhodes strncpy(service, DNS_AS_STR(token), sizeof(service)); 138135446Strhodes service[sizeof(service)-1] = '\0'; 139135446Strhodes for (i = strlen(service) - 1; i >= 0; i--) 140135446Strhodes if (isupper(service[i]&0xff)) 141143731Sdougb service[i] = tolower(service[i]&0xff); 142135446Strhodes 143135446Strhodes port = strtol(DNS_AS_STR(token), &e, 10); 144135446Strhodes if (*e == 0) 145135446Strhodes ; 146234010Sdougb else if (!mygetservbyname(service, ps, &port) && 147234010Sdougb !mygetservbyname(DNS_AS_STR(token), ps, &port)) 148135446Strhodes RETTOK(DNS_R_UNKNOWNSERVICE); 149135446Strhodes if (port < 0 || port > 0xffff) 150135446Strhodes RETTOK(ISC_R_RANGE); 151135446Strhodes if (port > maxport) 152135446Strhodes maxport = port; 153135446Strhodes bm[port / 8] |= (0x80 >> (port % 8)); 154135446Strhodes } while (1); 155135446Strhodes 156135446Strhodes /* 157135446Strhodes * Let upper layer handle eol/eof. 158135446Strhodes */ 159135446Strhodes isc_lex_ungettoken(lexer, &token); 160135446Strhodes 161135446Strhodes n = (maxport + 8) / 8; 162135446Strhodes return (mem_tobuffer(target, bm, n)); 163135446Strhodes} 164135446Strhodes 165135446Strhodesstatic inline isc_result_t 166135446Strhodestotext_in_wks(ARGS_TOTEXT) { 167135446Strhodes isc_region_t sr; 168135446Strhodes unsigned short proto; 169135446Strhodes char buf[sizeof("65535")]; 170135446Strhodes unsigned int i, j; 171135446Strhodes 172135446Strhodes UNUSED(tctx); 173135446Strhodes 174135446Strhodes REQUIRE(rdata->type == 11); 175135446Strhodes REQUIRE(rdata->rdclass == 1); 176135446Strhodes REQUIRE(rdata->length >= 5); 177135446Strhodes 178135446Strhodes dns_rdata_toregion(rdata, &sr); 179135446Strhodes RETERR(inet_totext(AF_INET, &sr, target)); 180135446Strhodes isc_region_consume(&sr, 4); 181135446Strhodes 182135446Strhodes proto = uint8_fromregion(&sr); 183135446Strhodes sprintf(buf, "%u", proto); 184135446Strhodes RETERR(str_totext(" ", target)); 185135446Strhodes RETERR(str_totext(buf, target)); 186135446Strhodes isc_region_consume(&sr, 1); 187135446Strhodes 188193149Sdougb INSIST(sr.length <= 8*1024); 189135446Strhodes for (i = 0; i < sr.length; i++) { 190135446Strhodes if (sr.base[i] != 0) 191135446Strhodes for (j = 0; j < 8; j++) 192135446Strhodes if ((sr.base[i] & (0x80 >> j)) != 0) { 193135446Strhodes sprintf(buf, "%u", i * 8 + j); 194135446Strhodes RETERR(str_totext(" ", target)); 195135446Strhodes RETERR(str_totext(buf, target)); 196135446Strhodes } 197135446Strhodes } 198135446Strhodes 199135446Strhodes return (ISC_R_SUCCESS); 200135446Strhodes} 201135446Strhodes 202135446Strhodesstatic inline isc_result_t 203135446Strhodesfromwire_in_wks(ARGS_FROMWIRE) { 204135446Strhodes isc_region_t sr; 205135446Strhodes isc_region_t tr; 206135446Strhodes 207135446Strhodes REQUIRE(type == 11); 208135446Strhodes REQUIRE(rdclass == 1); 209135446Strhodes 210135446Strhodes UNUSED(type); 211135446Strhodes UNUSED(dctx); 212135446Strhodes UNUSED(options); 213135446Strhodes UNUSED(rdclass); 214135446Strhodes 215135446Strhodes isc_buffer_activeregion(source, &sr); 216135446Strhodes isc_buffer_availableregion(target, &tr); 217135446Strhodes 218135446Strhodes if (sr.length < 5) 219135446Strhodes return (ISC_R_UNEXPECTEDEND); 220135446Strhodes if (sr.length > 8 * 1024 + 5) 221135446Strhodes return (DNS_R_EXTRADATA); 222135446Strhodes if (tr.length < sr.length) 223135446Strhodes return (ISC_R_NOSPACE); 224135446Strhodes 225262706Serwin memmove(tr.base, sr.base, sr.length); 226135446Strhodes isc_buffer_add(target, sr.length); 227135446Strhodes isc_buffer_forward(source, sr.length); 228135446Strhodes 229135446Strhodes return (ISC_R_SUCCESS); 230135446Strhodes} 231135446Strhodes 232135446Strhodesstatic inline isc_result_t 233135446Strhodestowire_in_wks(ARGS_TOWIRE) { 234135446Strhodes isc_region_t sr; 235135446Strhodes 236135446Strhodes UNUSED(cctx); 237135446Strhodes 238135446Strhodes REQUIRE(rdata->type == 11); 239135446Strhodes REQUIRE(rdata->rdclass == 1); 240135446Strhodes REQUIRE(rdata->length != 0); 241135446Strhodes 242135446Strhodes dns_rdata_toregion(rdata, &sr); 243135446Strhodes return (mem_tobuffer(target, sr.base, sr.length)); 244135446Strhodes} 245135446Strhodes 246135446Strhodesstatic inline int 247135446Strhodescompare_in_wks(ARGS_COMPARE) { 248135446Strhodes isc_region_t r1; 249135446Strhodes isc_region_t r2; 250135446Strhodes 251135446Strhodes REQUIRE(rdata1->type == rdata2->type); 252135446Strhodes REQUIRE(rdata1->rdclass == rdata2->rdclass); 253135446Strhodes REQUIRE(rdata1->type == 11); 254135446Strhodes REQUIRE(rdata1->rdclass == 1); 255135446Strhodes REQUIRE(rdata1->length != 0); 256135446Strhodes REQUIRE(rdata2->length != 0); 257135446Strhodes 258135446Strhodes dns_rdata_toregion(rdata1, &r1); 259135446Strhodes dns_rdata_toregion(rdata2, &r2); 260135446Strhodes return (isc_region_compare(&r1, &r2)); 261135446Strhodes} 262135446Strhodes 263135446Strhodesstatic inline isc_result_t 264135446Strhodesfromstruct_in_wks(ARGS_FROMSTRUCT) { 265135446Strhodes dns_rdata_in_wks_t *wks = source; 266135446Strhodes isc_uint32_t a; 267135446Strhodes 268135446Strhodes REQUIRE(type == 11); 269135446Strhodes REQUIRE(rdclass == 1); 270135446Strhodes REQUIRE(source != NULL); 271135446Strhodes REQUIRE(wks->common.rdtype == type); 272135446Strhodes REQUIRE(wks->common.rdclass == rdclass); 273193149Sdougb REQUIRE((wks->map != NULL && wks->map_len <= 8*1024) || 274193149Sdougb wks->map_len == 0); 275135446Strhodes 276135446Strhodes UNUSED(type); 277135446Strhodes UNUSED(rdclass); 278135446Strhodes 279135446Strhodes a = ntohl(wks->in_addr.s_addr); 280135446Strhodes RETERR(uint32_tobuffer(a, target)); 281262706Serwin RETERR(uint8_tobuffer(wks->protocol, target)); 282135446Strhodes return (mem_tobuffer(target, wks->map, wks->map_len)); 283135446Strhodes} 284135446Strhodes 285135446Strhodesstatic inline isc_result_t 286135446Strhodestostruct_in_wks(ARGS_TOSTRUCT) { 287135446Strhodes dns_rdata_in_wks_t *wks = target; 288135446Strhodes isc_uint32_t n; 289135446Strhodes isc_region_t region; 290135446Strhodes 291135446Strhodes REQUIRE(rdata->type == 11); 292135446Strhodes REQUIRE(rdata->rdclass == 1); 293135446Strhodes REQUIRE(rdata->length != 0); 294135446Strhodes 295135446Strhodes wks->common.rdclass = rdata->rdclass; 296135446Strhodes wks->common.rdtype = rdata->type; 297135446Strhodes ISC_LINK_INIT(&wks->common, link); 298135446Strhodes 299135446Strhodes dns_rdata_toregion(rdata, ®ion); 300135446Strhodes n = uint32_fromregion(®ion); 301135446Strhodes wks->in_addr.s_addr = htonl(n); 302135446Strhodes isc_region_consume(®ion, 4); 303262706Serwin wks->protocol = uint8_fromregion(®ion); 304262706Serwin isc_region_consume(®ion, 1); 305135446Strhodes wks->map_len = region.length; 306135446Strhodes wks->map = mem_maybedup(mctx, region.base, region.length); 307135446Strhodes if (wks->map == NULL) 308135446Strhodes return (ISC_R_NOMEMORY); 309135446Strhodes wks->mctx = mctx; 310135446Strhodes return (ISC_R_SUCCESS); 311135446Strhodes} 312135446Strhodes 313135446Strhodesstatic inline void 314135446Strhodesfreestruct_in_wks(ARGS_FREESTRUCT) { 315135446Strhodes dns_rdata_in_wks_t *wks = source; 316135446Strhodes 317135446Strhodes REQUIRE(source != NULL); 318135446Strhodes REQUIRE(wks->common.rdtype == 11); 319135446Strhodes REQUIRE(wks->common.rdclass == 1); 320135446Strhodes 321135446Strhodes if (wks->mctx == NULL) 322135446Strhodes return; 323135446Strhodes 324135446Strhodes if (wks->map != NULL) 325135446Strhodes isc_mem_free(wks->mctx, wks->map); 326135446Strhodes wks->mctx = NULL; 327135446Strhodes} 328135446Strhodes 329135446Strhodesstatic inline isc_result_t 330135446Strhodesadditionaldata_in_wks(ARGS_ADDLDATA) { 331135446Strhodes UNUSED(rdata); 332135446Strhodes UNUSED(add); 333135446Strhodes UNUSED(arg); 334135446Strhodes 335135446Strhodes REQUIRE(rdata->type == 11); 336135446Strhodes REQUIRE(rdata->rdclass == 1); 337135446Strhodes 338135446Strhodes return (ISC_R_SUCCESS); 339135446Strhodes} 340135446Strhodes 341135446Strhodesstatic inline isc_result_t 342135446Strhodesdigest_in_wks(ARGS_DIGEST) { 343135446Strhodes isc_region_t r; 344135446Strhodes 345135446Strhodes REQUIRE(rdata->type == 11); 346135446Strhodes REQUIRE(rdata->rdclass == 1); 347135446Strhodes 348135446Strhodes dns_rdata_toregion(rdata, &r); 349135446Strhodes 350135446Strhodes return ((digest)(arg, &r)); 351135446Strhodes} 352135446Strhodes 353135446Strhodesstatic inline isc_boolean_t 354135446Strhodescheckowner_in_wks(ARGS_CHECKOWNER) { 355135446Strhodes 356135446Strhodes REQUIRE(type == 11); 357135446Strhodes REQUIRE(rdclass == 1); 358135446Strhodes 359135446Strhodes UNUSED(type); 360135446Strhodes UNUSED(rdclass); 361135446Strhodes 362135446Strhodes return (dns_name_ishostname(name, wildcard)); 363135446Strhodes} 364135446Strhodes 365135446Strhodesstatic inline isc_boolean_t 366135446Strhodeschecknames_in_wks(ARGS_CHECKNAMES) { 367135446Strhodes 368135446Strhodes REQUIRE(rdata->type == 11); 369135446Strhodes REQUIRE(rdata->rdclass == 1); 370135446Strhodes 371135446Strhodes UNUSED(rdata); 372135446Strhodes UNUSED(owner); 373135446Strhodes UNUSED(bad); 374135446Strhodes 375135446Strhodes return (ISC_TRUE); 376135446Strhodes} 377135446Strhodes 378224092Sdougbstatic inline int 379224092Sdougbcasecompare_in_wks(ARGS_COMPARE) { 380224092Sdougb return (compare_in_wks(rdata1, rdata2)); 381224092Sdougb} 382224092Sdougb 383135446Strhodes#endif /* RDATA_IN_1_WKS_11_C */ 384