1 1.4 andvar /* $NetBSD: res_mkupdate.c,v 1.4 2025/02/17 22:58:34 andvar Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * Copyright (c) 1996-1999 by Internet Software Consortium. 6 1.1 christos * 7 1.1 christos * Permission to use, copy, modify, and distribute this software for any 8 1.1 christos * purpose with or without fee is hereby granted, provided that the above 9 1.1 christos * copyright notice and this permission notice appear in all copies. 10 1.1 christos * 11 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 1.1 christos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 1.1 christos */ 19 1.1 christos 20 1.1 christos /*! \file 21 1.1 christos * \brief 22 1.1 christos * Based on the Dynamic DNS reference implementation by Viraj Bais 23 1.1 christos * <viraj_bais (at) ccm.fm.intel.com> 24 1.1 christos */ 25 1.1 christos #include <sys/cdefs.h> 26 1.1 christos #if 0 27 1.1 christos static const char rcsid[] = "Id: res_mkupdate.c,v 1.10 2008/12/11 09:59:00 marka Exp "; 28 1.1 christos #else 29 1.4 andvar __RCSID("$NetBSD: res_mkupdate.c,v 1.4 2025/02/17 22:58:34 andvar Exp $"); 30 1.1 christos #endif 31 1.1 christos 32 1.1 christos #include "port_before.h" 33 1.1 christos 34 1.1 christos #include <sys/types.h> 35 1.1 christos #include <sys/param.h> 36 1.1 christos 37 1.1 christos #include <netinet/in.h> 38 1.1 christos #include <arpa/nameser.h> 39 1.1 christos #include <arpa/inet.h> 40 1.1 christos 41 1.1 christos #include <errno.h> 42 1.1 christos #include <limits.h> 43 1.1 christos #include <netdb.h> 44 1.1 christos #include <resolv.h> 45 1.1 christos #include <res_update.h> 46 1.1 christos #include <stdio.h> 47 1.1 christos #include <stdlib.h> 48 1.1 christos #include <string.h> 49 1.1 christos #include <unistd.h> 50 1.1 christos #include <ctype.h> 51 1.1 christos 52 1.1 christos #include "port_after.h" 53 1.1 christos 54 1.1 christos /* Options. Leave them on. */ 55 1.1 christos #define MAXPORT 1024 56 1.1 christos 57 1.1 christos static int getnum_str(u_char **, u_char *); 58 1.1 christos static int gethexnum_str(u_char **, u_char *); 59 1.1 christos static int getword_str(char *, size_t, u_char **, u_char *); 60 1.1 christos static int getstr_str(char *, size_t, u_char **, u_char *); 61 1.1 christos 62 1.1 christos #define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2); 63 1.1 christos 64 1.1 christos /* Forward. */ 65 1.1 christos 66 1.1 christos int res_protocolnumber(const char *); 67 1.1 christos int res_servicenumber(const char *); 68 1.1 christos 69 1.1 christos /*% 70 1.1 christos * Form update packets. 71 1.1 christos * Returns the size of the resulting packet if no error 72 1.1 christos * 73 1.1 christos * On error, 74 1.1 christos * returns 75 1.1 christos *\li -1 if error in reading a word/number in rdata 76 1.1 christos * portion for update packets 77 1.1 christos *\li -2 if length of buffer passed is insufficient 78 1.1 christos *\li -3 if zone section is not the first section in 79 1.1 christos * the linked list, or section order has a problem 80 1.1 christos *\li -4 on a number overflow 81 1.1 christos *\li -5 unknown operation or no records 82 1.1 christos */ 83 1.1 christos int 84 1.1 christos res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) { 85 1.1 christos ns_updrec *rrecp_start = rrecp_in; 86 1.1 christos HEADER *hp; 87 1.1 christos u_char *cp, *sp2, *startp, *endp; 88 1.1 christos int n, i, soanum, multiline; 89 1.1 christos ns_updrec *rrecp; 90 1.1 christos struct in_addr ina; 91 1.1 christos struct in6_addr in6a; 92 1.1 christos char buf2[MAXDNAME]; 93 1.1 christos u_char buf3[MAXDNAME]; 94 1.1 christos int section, numrrs = 0, counts[ns_s_max]; 95 1.1 christos u_int16_t rtype, rclass; 96 1.1 christos u_int32_t n1, rttl; 97 1.1 christos u_char *dnptrs[20], **dpp, **lastdnptr; 98 1.1 christos int siglen, keylen, certlen; 99 1.1 christos 100 1.1 christos /* 101 1.1 christos * Initialize header fields. 102 1.1 christos */ 103 1.1 christos if ((buf == NULL) || (buflen < HFIXEDSZ)) 104 1.1 christos return (-1); 105 1.1 christos memset(buf, 0, HFIXEDSZ); 106 1.1 christos hp = (void *)buf; 107 1.1 christos statp->id = res_nrandomid(statp); 108 1.1 christos hp->id = htons(statp->id); 109 1.1 christos hp->opcode = ns_o_update; 110 1.1 christos hp->rcode = NOERROR; 111 1.1 christos cp = buf + HFIXEDSZ; 112 1.1 christos buflen -= HFIXEDSZ; 113 1.1 christos dpp = dnptrs; 114 1.1 christos *dpp++ = buf; 115 1.1 christos *dpp++ = NULL; 116 1.1 christos lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; 117 1.1 christos 118 1.1 christos if (rrecp_start == NULL) 119 1.1 christos return (-5); 120 1.1 christos else if (rrecp_start->r_section != S_ZONE) 121 1.1 christos return (-3); 122 1.1 christos 123 1.1 christos memset(counts, 0, sizeof counts); 124 1.1 christos for (rrecp = rrecp_start; rrecp; rrecp = TAILQ_NEXT(rrecp, r_glink)) { 125 1.1 christos numrrs++; 126 1.1 christos section = rrecp->r_section; 127 1.1 christos if (section < 0 || section >= ns_s_max) 128 1.1 christos return (-1); 129 1.1 christos counts[section]++; 130 1.1 christos for (i = section + 1; i < ns_s_max; i++) 131 1.1 christos if (counts[i]) 132 1.1 christos return (-3); 133 1.1 christos rtype = rrecp->r_type; 134 1.1 christos rclass = rrecp->r_class; 135 1.1 christos rttl = rrecp->r_ttl; 136 1.1 christos /* overload class and type */ 137 1.1 christos if (section == S_PREREQ) { 138 1.1 christos rttl = 0; 139 1.1 christos switch (rrecp->r_opcode) { 140 1.1 christos case YXDOMAIN: 141 1.1 christos rclass = C_ANY; 142 1.1 christos rtype = T_ANY; 143 1.1 christos rrecp->r_size = 0; 144 1.1 christos break; 145 1.1 christos case NXDOMAIN: 146 1.1 christos rclass = C_NONE; 147 1.1 christos rtype = T_ANY; 148 1.1 christos rrecp->r_size = 0; 149 1.1 christos break; 150 1.1 christos case NXRRSET: 151 1.1 christos rclass = C_NONE; 152 1.1 christos rrecp->r_size = 0; 153 1.1 christos break; 154 1.1 christos case YXRRSET: 155 1.1 christos if (rrecp->r_size == 0) 156 1.1 christos rclass = C_ANY; 157 1.1 christos break; 158 1.1 christos default: 159 1.1 christos fprintf(stderr, 160 1.1 christos "res_mkupdate: incorrect opcode: %d\n", 161 1.1 christos rrecp->r_opcode); 162 1.1 christos fflush(stderr); 163 1.1 christos return (-1); 164 1.1 christos } 165 1.1 christos } else if (section == S_UPDATE) { 166 1.1 christos switch (rrecp->r_opcode) { 167 1.1 christos case DELETE: 168 1.1 christos rclass = rrecp->r_size == 0 ? C_ANY : C_NONE; 169 1.1 christos break; 170 1.1 christos case ADD: 171 1.1 christos break; 172 1.1 christos default: 173 1.1 christos fprintf(stderr, 174 1.1 christos "res_mkupdate: incorrect opcode: %d\n", 175 1.1 christos rrecp->r_opcode); 176 1.1 christos fflush(stderr); 177 1.1 christos return (-1); 178 1.1 christos } 179 1.1 christos } 180 1.1 christos 181 1.1 christos /* 182 1.1 christos * XXX appending default domain to owner name is omitted, 183 1.1 christos * fqdn must be provided 184 1.1 christos */ 185 1.1 christos if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs, 186 1.1 christos lastdnptr)) < 0) 187 1.1 christos return (-1); 188 1.1 christos cp += n; 189 1.1 christos ShrinkBuffer(n + 2*INT16SZ); 190 1.1 christos PUTSHORT(rtype, cp); 191 1.1 christos PUTSHORT(rclass, cp); 192 1.1 christos if (section == S_ZONE) { 193 1.1 christos if (numrrs != 1 || rrecp->r_type != T_SOA) 194 1.1 christos return (-3); 195 1.1 christos continue; 196 1.1 christos } 197 1.1 christos ShrinkBuffer(INT32SZ + INT16SZ); 198 1.1 christos PUTLONG(rttl, cp); 199 1.1 christos sp2 = cp; /*%< save pointer to length byte */ 200 1.1 christos cp += INT16SZ; 201 1.1 christos if (rrecp->r_size == 0) { 202 1.1 christos if (section == S_UPDATE && rclass != C_ANY) 203 1.1 christos return (-1); 204 1.1 christos else { 205 1.1 christos PUTSHORT(0, sp2); 206 1.1 christos continue; 207 1.1 christos } 208 1.1 christos } 209 1.1 christos startp = rrecp->r_data; 210 1.1 christos endp = startp + rrecp->r_size - 1; 211 1.1 christos /* XXX this should be done centrally. */ 212 1.1 christos switch (rrecp->r_type) { 213 1.1 christos case T_A: 214 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 215 1.1 christos return (-1); 216 1.1 christos if (!inet_aton(buf2, &ina)) 217 1.1 christos return (-1); 218 1.1 christos n1 = ntohl(ina.s_addr); 219 1.1 christos ShrinkBuffer(INT32SZ); 220 1.1 christos PUTLONG(n1, cp); 221 1.1 christos break; 222 1.1 christos case T_CNAME: 223 1.1 christos case T_MB: 224 1.1 christos case T_MG: 225 1.1 christos case T_MR: 226 1.1 christos case T_NS: 227 1.1 christos case T_PTR: 228 1.1 christos case ns_t_dname: 229 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 230 1.1 christos return (-1); 231 1.1 christos n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); 232 1.1 christos if (n < 0) 233 1.1 christos return (-1); 234 1.1 christos cp += n; 235 1.1 christos ShrinkBuffer(n); 236 1.1 christos break; 237 1.1 christos case T_MINFO: 238 1.1 christos case T_SOA: 239 1.1 christos case T_RP: 240 1.1 christos for (i = 0; i < 2; i++) { 241 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, 242 1.1 christos endp)) 243 1.1 christos return (-1); 244 1.1 christos n = dn_comp(buf2, cp, buflen, 245 1.1 christos dnptrs, lastdnptr); 246 1.1 christos if (n < 0) 247 1.1 christos return (-1); 248 1.1 christos cp += n; 249 1.1 christos ShrinkBuffer(n); 250 1.1 christos } 251 1.1 christos if (rrecp->r_type == T_SOA) { 252 1.1 christos ShrinkBuffer(5 * INT32SZ); 253 1.1 christos while (isspace(*startp) || !*startp) 254 1.1 christos startp++; 255 1.1 christos if (*startp == '(') { 256 1.1 christos multiline = 1; 257 1.1 christos startp++; 258 1.1 christos } else 259 1.1 christos multiline = 0; 260 1.1 christos /* serial, refresh, retry, expire, minimum */ 261 1.1 christos for (i = 0; i < 5; i++) { 262 1.1 christos soanum = getnum_str(&startp, endp); 263 1.1 christos if (soanum < 0) 264 1.1 christos return (-1); 265 1.1 christos PUTLONG(soanum, cp); 266 1.1 christos } 267 1.1 christos if (multiline) { 268 1.1 christos while (isspace(*startp) || !*startp) 269 1.1 christos startp++; 270 1.1 christos if (*startp != ')') 271 1.1 christos return (-1); 272 1.1 christos } 273 1.1 christos } 274 1.1 christos break; 275 1.1 christos case T_MX: 276 1.1 christos case T_AFSDB: 277 1.1 christos case T_RT: 278 1.1 christos n = getnum_str(&startp, endp); 279 1.1 christos if (n < 0) 280 1.1 christos return (-1); 281 1.1 christos ShrinkBuffer(INT16SZ); 282 1.1 christos PUTSHORT(n, cp); 283 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 284 1.1 christos return (-1); 285 1.1 christos n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); 286 1.1 christos if (n < 0) 287 1.1 christos return (-1); 288 1.1 christos cp += n; 289 1.1 christos ShrinkBuffer(n); 290 1.1 christos break; 291 1.1 christos case T_SRV: 292 1.1 christos n = getnum_str(&startp, endp); 293 1.1 christos if (n < 0) 294 1.1 christos return (-1); 295 1.1 christos ShrinkBuffer(INT16SZ); 296 1.1 christos PUTSHORT(n, cp); 297 1.1 christos 298 1.1 christos n = getnum_str(&startp, endp); 299 1.1 christos if (n < 0) 300 1.1 christos return (-1); 301 1.1 christos ShrinkBuffer(INT16SZ); 302 1.1 christos PUTSHORT(n, cp); 303 1.1 christos 304 1.1 christos n = getnum_str(&startp, endp); 305 1.1 christos if (n < 0) 306 1.1 christos return (-1); 307 1.1 christos ShrinkBuffer(INT16SZ); 308 1.1 christos PUTSHORT(n, cp); 309 1.1 christos 310 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 311 1.1 christos return (-1); 312 1.1 christos n = dn_comp(buf2, cp, buflen, NULL, NULL); 313 1.1 christos if (n < 0) 314 1.1 christos return (-1); 315 1.1 christos cp += n; 316 1.1 christos ShrinkBuffer(n); 317 1.1 christos break; 318 1.1 christos case T_PX: 319 1.1 christos n = getnum_str(&startp, endp); 320 1.1 christos if (n < 0) 321 1.1 christos return (-1); 322 1.1 christos PUTSHORT(n, cp); 323 1.1 christos ShrinkBuffer(INT16SZ); 324 1.1 christos for (i = 0; i < 2; i++) { 325 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, 326 1.1 christos endp)) 327 1.1 christos return (-1); 328 1.1 christos n = dn_comp(buf2, cp, buflen, dnptrs, 329 1.1 christos lastdnptr); 330 1.1 christos if (n < 0) 331 1.1 christos return (-1); 332 1.1 christos cp += n; 333 1.1 christos ShrinkBuffer(n); 334 1.1 christos } 335 1.1 christos break; 336 1.1 christos case T_WKS: { 337 1.1 christos char bm[MAXPORT/8]; 338 1.1 christos unsigned int maxbm = 0; 339 1.1 christos 340 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 341 1.1 christos return (-1); 342 1.1 christos if (!inet_aton(buf2, &ina)) 343 1.1 christos return (-1); 344 1.1 christos n1 = ntohl(ina.s_addr); 345 1.1 christos ShrinkBuffer(INT32SZ); 346 1.1 christos PUTLONG(n1, cp); 347 1.1 christos 348 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 349 1.1 christos return (-1); 350 1.1 christos if ((i = res_protocolnumber(buf2)) < 0) 351 1.1 christos return (-1); 352 1.1 christos ShrinkBuffer(1); 353 1.1 christos *cp++ = i & 0xff; 354 1.1 christos 355 1.1 christos for (i = 0; i < MAXPORT/8 ; i++) 356 1.1 christos bm[i] = 0; 357 1.1 christos 358 1.1 christos while (getword_str(buf2, sizeof buf2, &startp, endp)) { 359 1.1 christos if ((n = res_servicenumber(buf2)) <= 0) 360 1.1 christos return (-1); 361 1.1 christos 362 1.1 christos if (n < MAXPORT) { 363 1.1 christos bm[n/8] |= (0x80>>(n%8)); 364 1.1 christos if ((unsigned)n > maxbm) 365 1.1 christos maxbm = n; 366 1.1 christos } else 367 1.1 christos return (-1); 368 1.1 christos } 369 1.1 christos maxbm = maxbm/8 + 1; 370 1.1 christos ShrinkBuffer(maxbm); 371 1.1 christos memcpy(cp, bm, maxbm); 372 1.1 christos cp += maxbm; 373 1.1 christos break; 374 1.1 christos } 375 1.1 christos case T_HINFO: 376 1.1 christos for (i = 0; i < 2; i++) { 377 1.1 christos if ((n = getstr_str(buf2, sizeof buf2, 378 1.1 christos &startp, endp)) < 0) 379 1.1 christos return (-1); 380 1.1 christos if (n > 255) 381 1.1 christos return (-1); 382 1.1 christos ShrinkBuffer(n+1); 383 1.1 christos *cp++ = n; 384 1.1 christos memcpy(cp, buf2, n); 385 1.1 christos cp += n; 386 1.1 christos } 387 1.1 christos break; 388 1.1 christos case T_TXT: 389 1.1 christos for (;;) { 390 1.1 christos if ((n = getstr_str(buf2, sizeof buf2, 391 1.1 christos &startp, endp)) < 0) { 392 1.1 christos if (cp != (sp2 + INT16SZ)) 393 1.1 christos break; 394 1.1 christos return (-1); 395 1.1 christos } 396 1.1 christos if (n > 255) 397 1.1 christos return (-1); 398 1.1 christos ShrinkBuffer(n+1); 399 1.1 christos *cp++ = n; 400 1.1 christos memcpy(cp, buf2, n); 401 1.1 christos cp += n; 402 1.1 christos } 403 1.1 christos break; 404 1.1 christos case T_X25: 405 1.1 christos /* RFC1183 */ 406 1.1 christos if ((n = getstr_str(buf2, sizeof buf2, &startp, 407 1.1 christos endp)) < 0) 408 1.1 christos return (-1); 409 1.1 christos if (n > 255) 410 1.1 christos return (-1); 411 1.1 christos ShrinkBuffer(n+1); 412 1.1 christos *cp++ = n; 413 1.1 christos memcpy(cp, buf2, n); 414 1.1 christos cp += n; 415 1.1 christos break; 416 1.1 christos case T_ISDN: 417 1.1 christos /* RFC1183 */ 418 1.1 christos if ((n = getstr_str(buf2, sizeof buf2, &startp, 419 1.1 christos endp)) < 0) 420 1.1 christos return (-1); 421 1.1 christos if ((n > 255) || (n == 0)) 422 1.1 christos return (-1); 423 1.1 christos ShrinkBuffer(n+1); 424 1.1 christos *cp++ = n; 425 1.1 christos memcpy(cp, buf2, n); 426 1.1 christos cp += n; 427 1.1 christos if ((n = getstr_str(buf2, sizeof buf2, &startp, 428 1.1 christos endp)) < 0) 429 1.1 christos n = 0; 430 1.1 christos if (n > 255) 431 1.1 christos return (-1); 432 1.1 christos ShrinkBuffer(n+1); 433 1.1 christos *cp++ = n; 434 1.1 christos memcpy(cp, buf2, n); 435 1.1 christos cp += n; 436 1.1 christos break; 437 1.1 christos case T_NSAP: 438 1.1 christos if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, 439 1.1 christos (int)sizeof(buf2))) != 0) { 440 1.1 christos ShrinkBuffer(n); 441 1.1 christos memcpy(cp, buf2, n); 442 1.1 christos cp += n; 443 1.1 christos } else { 444 1.1 christos return (-1); 445 1.1 christos } 446 1.1 christos break; 447 1.1 christos case T_LOC: 448 1.1 christos if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) { 449 1.1 christos ShrinkBuffer(n); 450 1.1 christos memcpy(cp, buf2, n); 451 1.1 christos cp += n; 452 1.1 christos } else 453 1.1 christos return (-1); 454 1.1 christos break; 455 1.1 christos case ns_t_sig: 456 1.1 christos { 457 1.1 christos int sig_type, success, dateerror; 458 1.1 christos u_int32_t exptime, timesigned; 459 1.1 christos 460 1.1 christos /* type */ 461 1.1 christos if ((n = getword_str(buf2, sizeof buf2, 462 1.1 christos &startp, endp)) < 0) 463 1.1 christos return (-1); 464 1.1 christos sig_type = sym_ston(__p_type_syms, buf2, &success); 465 1.1 christos if (!success || sig_type == ns_t_any) 466 1.1 christos return (-1); 467 1.1 christos ShrinkBuffer(INT16SZ); 468 1.1 christos PUTSHORT(sig_type, cp); 469 1.1 christos /* alg */ 470 1.1 christos n = getnum_str(&startp, endp); 471 1.1 christos if (n < 0) 472 1.1 christos return (-1); 473 1.1 christos ShrinkBuffer(1); 474 1.1 christos *cp++ = n; 475 1.1 christos /* labels */ 476 1.1 christos n = getnum_str(&startp, endp); 477 1.1 christos if (n <= 0 || n > 255) 478 1.1 christos return (-1); 479 1.1 christos ShrinkBuffer(1); 480 1.1 christos *cp++ = n; 481 1.1 christos /* ottl & expire */ 482 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 483 1.1 christos return (-1); 484 1.1 christos exptime = ns_datetosecs(buf2, &dateerror); 485 1.1 christos if (!dateerror) { 486 1.1 christos ShrinkBuffer(INT32SZ); 487 1.1 christos PUTLONG(rttl, cp); 488 1.1 christos } 489 1.1 christos else { 490 1.1 christos char *ulendp; 491 1.1 christos u_int32_t ottl; 492 1.1 christos unsigned long ul; 493 1.1 christos 494 1.1 christos errno = 0; 495 1.1 christos ul = strtoul(buf2, &ulendp, 10); 496 1.1 christos if (ul > 0xffffffffU) 497 1.1 christos errno = ERANGE; 498 1.1 christos ottl = (u_int32_t)ul; 499 1.1 christos if (errno != 0 || 500 1.1 christos (ulendp != NULL && *ulendp != '\0')) 501 1.1 christos return (-1); 502 1.1 christos ShrinkBuffer(INT32SZ); 503 1.1 christos PUTLONG(ottl, cp); 504 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, 505 1.1 christos endp)) 506 1.1 christos return (-1); 507 1.1 christos exptime = ns_datetosecs(buf2, &dateerror); 508 1.1 christos if (dateerror) 509 1.1 christos return (-1); 510 1.1 christos } 511 1.1 christos /* expire */ 512 1.1 christos ShrinkBuffer(INT32SZ); 513 1.1 christos PUTLONG(exptime, cp); 514 1.1 christos /* timesigned */ 515 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 516 1.1 christos return (-1); 517 1.1 christos timesigned = ns_datetosecs(buf2, &dateerror); 518 1.1 christos if (!dateerror) { 519 1.1 christos ShrinkBuffer(INT32SZ); 520 1.1 christos PUTLONG(timesigned, cp); 521 1.1 christos } 522 1.1 christos else 523 1.1 christos return (-1); 524 1.1 christos /* footprint */ 525 1.1 christos n = getnum_str(&startp, endp); 526 1.1 christos if (n < 0) 527 1.1 christos return (-1); 528 1.1 christos ShrinkBuffer(INT16SZ); 529 1.1 christos PUTSHORT(n, cp); 530 1.1 christos /* signer name */ 531 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 532 1.1 christos return (-1); 533 1.1 christos n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); 534 1.1 christos if (n < 0) 535 1.1 christos return (-1); 536 1.1 christos cp += n; 537 1.1 christos ShrinkBuffer(n); 538 1.1 christos /* sig */ 539 1.1 christos if ((n = getword_str(buf2, sizeof buf2, 540 1.1 christos &startp, endp)) < 0) 541 1.1 christos return (-1); 542 1.1 christos siglen = b64_pton(buf2, buf3, sizeof(buf3)); 543 1.1 christos if (siglen < 0) 544 1.1 christos return (-1); 545 1.1 christos ShrinkBuffer(siglen); 546 1.1 christos memcpy(cp, buf3, siglen); 547 1.1 christos cp += siglen; 548 1.1 christos break; 549 1.1 christos } 550 1.1 christos case ns_t_key: 551 1.1 christos /* flags */ 552 1.1 christos n = gethexnum_str(&startp, endp); 553 1.1 christos if (n < 0) 554 1.1 christos return (-1); 555 1.1 christos ShrinkBuffer(INT16SZ); 556 1.1 christos PUTSHORT(n, cp); 557 1.1 christos /* proto */ 558 1.1 christos n = getnum_str(&startp, endp); 559 1.1 christos if (n < 0) 560 1.1 christos return (-1); 561 1.1 christos ShrinkBuffer(1); 562 1.1 christos *cp++ = n; 563 1.1 christos /* alg */ 564 1.1 christos n = getnum_str(&startp, endp); 565 1.1 christos if (n < 0) 566 1.1 christos return (-1); 567 1.1 christos ShrinkBuffer(1); 568 1.1 christos *cp++ = n; 569 1.1 christos /* key */ 570 1.1 christos if ((n = getword_str(buf2, sizeof buf2, 571 1.1 christos &startp, endp)) < 0) 572 1.1 christos return (-1); 573 1.1 christos keylen = b64_pton(buf2, buf3, sizeof(buf3)); 574 1.1 christos if (keylen < 0) 575 1.1 christos return (-1); 576 1.1 christos ShrinkBuffer(keylen); 577 1.1 christos memcpy(cp, buf3, keylen); 578 1.1 christos cp += keylen; 579 1.1 christos break; 580 1.1 christos case ns_t_nxt: 581 1.1 christos { 582 1.1 christos int success, nxt_type; 583 1.1 christos u_char data[32]; 584 1.1 christos int maxtype; 585 1.1 christos 586 1.1 christos /* next name */ 587 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 588 1.1 christos return (-1); 589 1.1 christos n = dn_comp(buf2, cp, buflen, NULL, NULL); 590 1.1 christos if (n < 0) 591 1.1 christos return (-1); 592 1.1 christos cp += n; 593 1.1 christos ShrinkBuffer(n); 594 1.1 christos maxtype = 0; 595 1.1 christos memset(data, 0, sizeof data); 596 1.1 christos for (;;) { 597 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, 598 1.1 christos endp)) 599 1.1 christos break; 600 1.1 christos nxt_type = sym_ston(__p_type_syms, buf2, 601 1.1 christos &success); 602 1.1 christos if (!success || !ns_t_rr_p(nxt_type)) 603 1.1 christos return (-1); 604 1.1 christos NS_NXT_BIT_SET(nxt_type, data); 605 1.1 christos if (nxt_type > maxtype) 606 1.1 christos maxtype = nxt_type; 607 1.1 christos } 608 1.1 christos n = maxtype/NS_NXT_BITS+1; 609 1.1 christos ShrinkBuffer(n); 610 1.1 christos memcpy(cp, data, n); 611 1.1 christos cp += n; 612 1.1 christos break; 613 1.1 christos } 614 1.1 christos case ns_t_cert: 615 1.1 christos /* type */ 616 1.1 christos n = getnum_str(&startp, endp); 617 1.1 christos if (n < 0) 618 1.1 christos return (-1); 619 1.1 christos ShrinkBuffer(INT16SZ); 620 1.1 christos PUTSHORT(n, cp); 621 1.1 christos /* key tag */ 622 1.1 christos n = getnum_str(&startp, endp); 623 1.1 christos if (n < 0) 624 1.1 christos return (-1); 625 1.1 christos ShrinkBuffer(INT16SZ); 626 1.1 christos PUTSHORT(n, cp); 627 1.1 christos /* alg */ 628 1.1 christos n = getnum_str(&startp, endp); 629 1.1 christos if (n < 0) 630 1.1 christos return (-1); 631 1.1 christos ShrinkBuffer(1); 632 1.1 christos *cp++ = n; 633 1.1 christos /* cert */ 634 1.1 christos if ((n = getword_str(buf2, sizeof buf2, 635 1.1 christos &startp, endp)) < 0) 636 1.1 christos return (-1); 637 1.1 christos certlen = b64_pton(buf2, buf3, sizeof(buf3)); 638 1.1 christos if (certlen < 0) 639 1.1 christos return (-1); 640 1.1 christos ShrinkBuffer(certlen); 641 1.1 christos memcpy(cp, buf3, certlen); 642 1.1 christos cp += certlen; 643 1.1 christos break; 644 1.1 christos case ns_t_aaaa: 645 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 646 1.1 christos return (-1); 647 1.1 christos if (inet_pton(AF_INET6, buf2, &in6a) <= 0) 648 1.1 christos return (-1); 649 1.1 christos ShrinkBuffer(NS_IN6ADDRSZ); 650 1.1 christos memcpy(cp, &in6a, NS_IN6ADDRSZ); 651 1.1 christos cp += NS_IN6ADDRSZ; 652 1.1 christos break; 653 1.1 christos case ns_t_naptr: 654 1.1 christos /* Order Preference Flags Service Replacement Regexp */ 655 1.1 christos /* Order */ 656 1.1 christos n = getnum_str(&startp, endp); 657 1.1 christos if (n < 0 || n > 65535) 658 1.1 christos return (-1); 659 1.1 christos ShrinkBuffer(INT16SZ); 660 1.1 christos PUTSHORT(n, cp); 661 1.1 christos /* Preference */ 662 1.1 christos n = getnum_str(&startp, endp); 663 1.1 christos if (n < 0 || n > 65535) 664 1.1 christos return (-1); 665 1.1 christos ShrinkBuffer(INT16SZ); 666 1.1 christos PUTSHORT(n, cp); 667 1.1 christos /* Flags */ 668 1.1 christos if ((n = getstr_str(buf2, sizeof buf2, 669 1.1 christos &startp, endp)) < 0) { 670 1.1 christos return (-1); 671 1.1 christos } 672 1.1 christos if (n > 255) 673 1.1 christos return (-1); 674 1.1 christos ShrinkBuffer(n+1); 675 1.1 christos *cp++ = n; 676 1.1 christos memcpy(cp, buf2, n); 677 1.1 christos cp += n; 678 1.1 christos /* Service Classes */ 679 1.1 christos if ((n = getstr_str(buf2, sizeof buf2, 680 1.1 christos &startp, endp)) < 0) { 681 1.1 christos return (-1); 682 1.1 christos } 683 1.1 christos if (n > 255) 684 1.1 christos return (-1); 685 1.1 christos ShrinkBuffer(n+1); 686 1.1 christos *cp++ = n; 687 1.1 christos memcpy(cp, buf2, n); 688 1.1 christos cp += n; 689 1.1 christos /* Pattern */ 690 1.1 christos if ((n = getstr_str(buf2, sizeof buf2, 691 1.1 christos &startp, endp)) < 0) { 692 1.1 christos return (-1); 693 1.1 christos } 694 1.1 christos if (n > 255) 695 1.1 christos return (-1); 696 1.1 christos ShrinkBuffer(n+1); 697 1.1 christos *cp++ = n; 698 1.1 christos memcpy(cp, buf2, n); 699 1.1 christos cp += n; 700 1.1 christos /* Replacement */ 701 1.1 christos if (!getword_str(buf2, sizeof buf2, &startp, endp)) 702 1.1 christos return (-1); 703 1.1 christos n = dn_comp(buf2, cp, buflen, NULL, NULL); 704 1.1 christos if (n < 0) 705 1.1 christos return (-1); 706 1.1 christos cp += n; 707 1.1 christos ShrinkBuffer(n); 708 1.1 christos break; 709 1.1 christos default: 710 1.1 christos return (-1); 711 1.1 christos } /*switch*/ 712 1.1 christos n = (u_int16_t)((cp - sp2) - INT16SZ); 713 1.1 christos PUTSHORT(n, sp2); 714 1.1 christos } /*for*/ 715 1.1 christos 716 1.1 christos hp->qdcount = htons(counts[0]); 717 1.1 christos hp->ancount = htons(counts[1]); 718 1.1 christos hp->nscount = htons(counts[2]); 719 1.1 christos hp->arcount = htons(counts[3]); 720 1.1 christos return (int)(cp - buf); 721 1.1 christos } 722 1.1 christos 723 1.1 christos /*% 724 1.1 christos * Get a whitespace delimited word from a string (not file) 725 1.1 christos * into buf. modify the start pointer to point after the 726 1.1 christos * word in the string. 727 1.1 christos */ 728 1.1 christos static int 729 1.1 christos getword_str(char *buf, size_t size, u_char **startpp, u_char *endp) { 730 1.1 christos char *cp; 731 1.1 christos int c; 732 1.1 christos 733 1.1 christos for (cp = buf; *startpp <= endp; ) { 734 1.1 christos c = **startpp; 735 1.1 christos if (isspace(c) || c == '\0') { 736 1.1 christos if (cp != buf) /*%< trailing whitespace */ 737 1.1 christos break; 738 1.1 christos else { /*%< leading whitespace */ 739 1.1 christos (*startpp)++; 740 1.1 christos continue; 741 1.1 christos } 742 1.1 christos } 743 1.1 christos (*startpp)++; 744 1.1 christos if (cp >= buf+size-1) 745 1.1 christos break; 746 1.1 christos *cp++ = (u_char)c; 747 1.1 christos } 748 1.1 christos *cp = '\0'; 749 1.1 christos return (cp != buf); 750 1.1 christos } 751 1.1 christos 752 1.1 christos /*% 753 1.3 andvar * get a whitespace delimited string from memory. Process quoted strings 754 1.1 christos * and \\DDD escapes. Return length or -1 on error. Returned string may 755 1.1 christos * contain nulls. 756 1.1 christos */ 757 1.1 christos static char digits[] = "0123456789"; 758 1.1 christos static int 759 1.1 christos getstr_str(char *buf, size_t size, u_char **startpp, u_char *endp) { 760 1.1 christos char *cp; 761 1.1 christos int c, c1 = 0; 762 1.1 christos int inquote = 0; 763 1.1 christos int seen_quote = 0; 764 1.1 christos int escape = 0; 765 1.1 christos int dig = 0; 766 1.1 christos 767 1.1 christos for (cp = buf; *startpp <= endp; ) { 768 1.1 christos if ((c = **startpp) == '\0') 769 1.1 christos break; 770 1.1 christos /* leading white space */ 771 1.1 christos if ((cp == buf) && !seen_quote && isspace(c)) { 772 1.1 christos (*startpp)++; 773 1.1 christos continue; 774 1.1 christos } 775 1.1 christos 776 1.1 christos switch (c) { 777 1.1 christos case '\\': 778 1.1 christos if (!escape) { 779 1.1 christos escape = 1; 780 1.1 christos dig = 0; 781 1.1 christos c1 = 0; 782 1.1 christos (*startpp)++; 783 1.1 christos continue; 784 1.1 christos } 785 1.1 christos goto do_escape; 786 1.1 christos case '"': 787 1.1 christos if (!escape) { 788 1.1 christos inquote = !inquote; 789 1.1 christos seen_quote = 1; 790 1.1 christos (*startpp)++; 791 1.1 christos continue; 792 1.1 christos } 793 1.1 christos /*FALLTHROUGH*/ 794 1.1 christos default: 795 1.1 christos do_escape: 796 1.1 christos if (escape) { 797 1.1 christos switch (c) { 798 1.1 christos case '0': 799 1.1 christos case '1': 800 1.1 christos case '2': 801 1.1 christos case '3': 802 1.1 christos case '4': 803 1.1 christos case '5': 804 1.1 christos case '6': 805 1.1 christos case '7': 806 1.1 christos case '8': 807 1.1 christos case '9': 808 1.1 christos c1 = c1 * 10 + 809 1.1 christos (int)(strchr(digits, c) - digits); 810 1.1 christos 811 1.1 christos if (++dig == 3) { 812 1.1 christos c = c1 &0xff; 813 1.1 christos break; 814 1.1 christos } 815 1.1 christos (*startpp)++; 816 1.1 christos continue; 817 1.1 christos } 818 1.1 christos escape = 0; 819 1.1 christos } else if (!inquote && isspace(c)) 820 1.1 christos goto done; 821 1.1 christos if (cp >= buf+size-1) 822 1.1 christos goto done; 823 1.1 christos *cp++ = (u_char)c; 824 1.1 christos (*startpp)++; 825 1.1 christos } 826 1.1 christos } 827 1.1 christos done: 828 1.1 christos *cp = '\0'; 829 1.1 christos return ((cp == buf)? (seen_quote? 0: -1): (int)(cp - buf)); 830 1.1 christos } 831 1.1 christos 832 1.1 christos /*% 833 1.1 christos * Get a whitespace delimited base 16 number from a string (not file) into buf 834 1.1 christos * update the start pointer to point after the number in the string. 835 1.1 christos */ 836 1.1 christos static int 837 1.1 christos gethexnum_str(u_char **startpp, u_char *endp) { 838 1.1 christos int c, n; 839 1.1 christos int seendigit = 0; 840 1.1 christos int m = 0; 841 1.1 christos 842 1.1 christos if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0) 843 1.1 christos return getnum_str(startpp, endp); 844 1.1 christos (*startpp)+=2; 845 1.1 christos for (n = 0; *startpp <= endp; ) { 846 1.1 christos c = **startpp; 847 1.1 christos if (isspace(c) || c == '\0') { 848 1.1 christos if (seendigit) /*%< trailing whitespace */ 849 1.1 christos break; 850 1.1 christos else { /*%< leading whitespace */ 851 1.1 christos (*startpp)++; 852 1.1 christos continue; 853 1.1 christos } 854 1.1 christos } 855 1.1 christos if (c == ';') { 856 1.1 christos while ((*startpp <= endp) && 857 1.1 christos ((c = **startpp) != '\n')) 858 1.1 christos (*startpp)++; 859 1.1 christos if (seendigit) 860 1.1 christos break; 861 1.1 christos continue; 862 1.1 christos } 863 1.1 christos if (!isxdigit(c)) { 864 1.1 christos if (c == ')' && seendigit) { 865 1.1 christos (*startpp)--; 866 1.1 christos break; 867 1.1 christos } 868 1.1 christos return (-1); 869 1.1 christos } 870 1.1 christos (*startpp)++; 871 1.1 christos if (isdigit(c)) 872 1.1 christos n = n * 16 + (c - '0'); 873 1.1 christos else 874 1.1 christos n = n * 16 + (tolower(c) - 'a' + 10); 875 1.1 christos seendigit = 1; 876 1.1 christos } 877 1.1 christos return (n + m); 878 1.1 christos } 879 1.1 christos 880 1.1 christos /*% 881 1.1 christos * Get a whitespace delimited base 10 number from a string (not file) into buf 882 1.1 christos * update the start pointer to point after the number in the string. 883 1.1 christos */ 884 1.1 christos static int 885 1.1 christos getnum_str(u_char **startpp, u_char *endp) { 886 1.1 christos int c, n; 887 1.1 christos int seendigit = 0; 888 1.1 christos int m = 0; 889 1.1 christos 890 1.1 christos for (n = 0; *startpp <= endp; ) { 891 1.1 christos c = **startpp; 892 1.1 christos if (isspace(c) || c == '\0') { 893 1.1 christos if (seendigit) /*%< trailing whitespace */ 894 1.1 christos break; 895 1.1 christos else { /*%< leading whitespace */ 896 1.1 christos (*startpp)++; 897 1.1 christos continue; 898 1.1 christos } 899 1.1 christos } 900 1.1 christos if (c == ';') { 901 1.1 christos while ((*startpp <= endp) && 902 1.1 christos ((c = **startpp) != '\n')) 903 1.1 christos (*startpp)++; 904 1.1 christos if (seendigit) 905 1.1 christos break; 906 1.1 christos continue; 907 1.1 christos } 908 1.1 christos if (!isdigit(c)) { 909 1.1 christos if (c == ')' && seendigit) { 910 1.1 christos (*startpp)--; 911 1.1 christos break; 912 1.1 christos } 913 1.1 christos return (-1); 914 1.1 christos } 915 1.1 christos (*startpp)++; 916 1.1 christos n = n * 10 + (c - '0'); 917 1.1 christos seendigit = 1; 918 1.1 christos } 919 1.1 christos return (n + m); 920 1.1 christos } 921 1.1 christos 922 1.1 christos /*% 923 1.1 christos * Allocate a resource record buffer & save rr info. 924 1.1 christos */ 925 1.1 christos ns_updrec * 926 1.1 christos res_mkupdrec(int section, const char *dname, 927 1.1 christos u_int class, u_int type, u_long ttl) { 928 1.1 christos ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec)); 929 1.1 christos 930 1.1 christos if (!rrecp || !(rrecp->r_dname = strdup(dname))) { 931 1.1 christos if (rrecp) 932 1.1 christos free(rrecp); 933 1.1 christos return (NULL); 934 1.1 christos } 935 1.1 christos rrecp->r_class = (ns_class)class; 936 1.1 christos rrecp->r_type = (ns_type)type; 937 1.1 christos rrecp->r_ttl = (u_int)ttl; 938 1.1 christos rrecp->r_section = (ns_sect)section; 939 1.1 christos return (rrecp); 940 1.1 christos } 941 1.1 christos 942 1.1 christos /*% 943 1.1 christos * Free a resource record buffer created by res_mkupdrec. 944 1.1 christos */ 945 1.1 christos void 946 1.1 christos res_freeupdrec(ns_updrec *rrecp) { 947 1.1 christos /* Note: freeing r_dp is the caller's responsibility. */ 948 1.1 christos if (rrecp->r_dname != NULL) 949 1.1 christos free(rrecp->r_dname); 950 1.1 christos free(rrecp); 951 1.1 christos } 952 1.1 christos 953 1.1 christos struct valuelist { 954 1.1 christos struct valuelist * next; 955 1.1 christos struct valuelist * prev; 956 1.1 christos char * name; 957 1.1 christos char * proto; 958 1.1 christos int port; 959 1.1 christos }; 960 1.1 christos static struct valuelist *servicelist, *protolist; 961 1.1 christos 962 1.1 christos static void 963 1.1 christos res_buildservicelist(void) { 964 1.1 christos struct servent *sp; 965 1.1 christos struct valuelist *slp; 966 1.1 christos 967 1.1 christos #ifdef MAYBE_HESIOD 968 1.1 christos setservent(0); 969 1.1 christos #else 970 1.1 christos setservent(1); 971 1.1 christos #endif 972 1.1 christos while ((sp = getservent()) != NULL) { 973 1.1 christos slp = (struct valuelist *)malloc(sizeof(struct valuelist)); 974 1.1 christos if (!slp) 975 1.1 christos break; 976 1.1 christos slp->name = strdup(sp->s_name); 977 1.1 christos slp->proto = strdup(sp->s_proto); 978 1.1 christos if ((slp->name == NULL) || (slp->proto == NULL)) { 979 1.1 christos if (slp->name) free(slp->name); 980 1.1 christos if (slp->proto) free(slp->proto); 981 1.1 christos free(slp); 982 1.1 christos break; 983 1.1 christos } 984 1.4 andvar slp->port = ntohs((u_int16_t)sp->s_port); /*%< host byte order */ 985 1.1 christos slp->next = servicelist; 986 1.1 christos slp->prev = NULL; 987 1.1 christos if (servicelist) 988 1.1 christos servicelist->prev = slp; 989 1.1 christos servicelist = slp; 990 1.1 christos } 991 1.1 christos endservent(); 992 1.1 christos } 993 1.1 christos 994 1.1 christos void 995 1.2 christos res_destroyservicelist(void) { 996 1.1 christos struct valuelist *slp, *slp_next; 997 1.1 christos 998 1.1 christos for (slp = servicelist; slp != NULL; slp = slp_next) { 999 1.1 christos slp_next = slp->next; 1000 1.1 christos free(slp->name); 1001 1.1 christos free(slp->proto); 1002 1.1 christos free(slp); 1003 1.1 christos } 1004 1.1 christos servicelist = (struct valuelist *)0; 1005 1.1 christos } 1006 1.1 christos 1007 1.1 christos void 1008 1.1 christos res_buildprotolist(void) { 1009 1.1 christos struct protoent *pp; 1010 1.1 christos struct valuelist *slp; 1011 1.1 christos 1012 1.1 christos #ifdef MAYBE_HESIOD 1013 1.1 christos setprotoent(0); 1014 1.1 christos #else 1015 1.1 christos setprotoent(1); 1016 1.1 christos #endif 1017 1.1 christos while ((pp = getprotoent()) != NULL) { 1018 1.1 christos slp = (struct valuelist *)malloc(sizeof(struct valuelist)); 1019 1.1 christos if (!slp) 1020 1.1 christos break; 1021 1.1 christos slp->name = strdup(pp->p_name); 1022 1.1 christos if (slp->name == NULL) { 1023 1.1 christos free(slp); 1024 1.1 christos break; 1025 1.1 christos } 1026 1.1 christos slp->port = pp->p_proto; /*%< host byte order */ 1027 1.1 christos slp->next = protolist; 1028 1.1 christos slp->prev = NULL; 1029 1.1 christos if (protolist) 1030 1.1 christos protolist->prev = slp; 1031 1.1 christos protolist = slp; 1032 1.1 christos } 1033 1.1 christos endprotoent(); 1034 1.1 christos } 1035 1.1 christos 1036 1.1 christos void 1037 1.1 christos res_destroyprotolist(void) { 1038 1.1 christos struct valuelist *plp, *plp_next; 1039 1.1 christos 1040 1.1 christos for (plp = protolist; plp != NULL; plp = plp_next) { 1041 1.1 christos plp_next = plp->next; 1042 1.1 christos free(plp->name); 1043 1.1 christos free(plp); 1044 1.1 christos } 1045 1.1 christos protolist = (struct valuelist *)0; 1046 1.1 christos } 1047 1.1 christos 1048 1.1 christos static int 1049 1.1 christos findservice(const char *s, struct valuelist **list) { 1050 1.1 christos struct valuelist *lp = *list; 1051 1.1 christos int n; 1052 1.1 christos 1053 1.1 christos for (; lp != NULL; lp = lp->next) 1054 1.1 christos if (strcasecmp(lp->name, s) == 0) { 1055 1.1 christos if (lp != *list) { 1056 1.1 christos lp->prev->next = lp->next; 1057 1.1 christos if (lp->next) 1058 1.1 christos lp->next->prev = lp->prev; 1059 1.1 christos (*list)->prev = lp; 1060 1.1 christos lp->next = *list; 1061 1.1 christos *list = lp; 1062 1.1 christos } 1063 1.1 christos return (lp->port); /*%< host byte order */ 1064 1.1 christos } 1065 1.1 christos if (sscanf(s, "%d", &n) != 1 || n <= 0) 1066 1.1 christos n = -1; 1067 1.1 christos return (n); 1068 1.1 christos } 1069 1.1 christos 1070 1.1 christos /*% 1071 1.1 christos * Convert service name or (ascii) number to int. 1072 1.1 christos */ 1073 1.1 christos int 1074 1.1 christos res_servicenumber(const char *p) { 1075 1.1 christos if (servicelist == (struct valuelist *)0) 1076 1.1 christos res_buildservicelist(); 1077 1.1 christos return (findservice(p, &servicelist)); 1078 1.1 christos } 1079 1.1 christos 1080 1.1 christos /*% 1081 1.1 christos * Convert protocol name or (ascii) number to int. 1082 1.1 christos */ 1083 1.1 christos int 1084 1.1 christos res_protocolnumber(const char *p) { 1085 1.1 christos if (protolist == (struct valuelist *)0) 1086 1.1 christos res_buildprotolist(); 1087 1.1 christos return (findservice(p, &protolist)); 1088 1.1 christos } 1089 1.1 christos 1090 1.1 christos static struct servent * 1091 1.1 christos cgetservbyport(u_int16_t port, const char *proto) { /*%< Host byte order. */ 1092 1.1 christos struct valuelist **list = &servicelist; 1093 1.1 christos struct valuelist *lp = *list; 1094 1.1 christos static struct servent serv; 1095 1.1 christos 1096 1.1 christos port = ntohs(port); 1097 1.1 christos for (; lp != NULL; lp = lp->next) { 1098 1.1 christos if (port != (u_int16_t)lp->port) /*%< Host byte order. */ 1099 1.1 christos continue; 1100 1.1 christos if (strcasecmp(lp->proto, proto) == 0) { 1101 1.1 christos if (lp != *list) { 1102 1.1 christos lp->prev->next = lp->next; 1103 1.1 christos if (lp->next) 1104 1.1 christos lp->next->prev = lp->prev; 1105 1.1 christos (*list)->prev = lp; 1106 1.1 christos lp->next = *list; 1107 1.1 christos *list = lp; 1108 1.1 christos } 1109 1.1 christos serv.s_name = lp->name; 1110 1.1 christos serv.s_port = htons((u_int16_t)lp->port); 1111 1.1 christos serv.s_proto = lp->proto; 1112 1.1 christos return (&serv); 1113 1.1 christos } 1114 1.1 christos } 1115 1.1 christos return (0); 1116 1.1 christos } 1117 1.1 christos 1118 1.1 christos static struct protoent * 1119 1.1 christos cgetprotobynumber(int proto) { /*%< Host byte order. */ 1120 1.1 christos struct valuelist **list = &protolist; 1121 1.1 christos struct valuelist *lp = *list; 1122 1.1 christos static struct protoent prot; 1123 1.1 christos 1124 1.1 christos for (; lp != NULL; lp = lp->next) 1125 1.1 christos if (lp->port == proto) { /*%< Host byte order. */ 1126 1.1 christos if (lp != *list) { 1127 1.1 christos lp->prev->next = lp->next; 1128 1.1 christos if (lp->next) 1129 1.1 christos lp->next->prev = lp->prev; 1130 1.1 christos (*list)->prev = lp; 1131 1.1 christos lp->next = *list; 1132 1.1 christos *list = lp; 1133 1.1 christos } 1134 1.1 christos prot.p_name = lp->name; 1135 1.1 christos prot.p_proto = lp->port; /*%< Host byte order. */ 1136 1.1 christos return (&prot); 1137 1.1 christos } 1138 1.1 christos return (0); 1139 1.1 christos } 1140 1.1 christos 1141 1.1 christos const char * 1142 1.1 christos res_protocolname(int num) { 1143 1.1 christos static char number[8]; 1144 1.1 christos struct protoent *pp; 1145 1.1 christos 1146 1.1 christos if (protolist == (struct valuelist *)0) 1147 1.1 christos res_buildprotolist(); 1148 1.1 christos pp = cgetprotobynumber(num); 1149 1.1 christos if (pp == 0) { 1150 1.1 christos (void) sprintf(number, "%d", num); 1151 1.1 christos return (number); 1152 1.1 christos } 1153 1.1 christos return (pp->p_name); 1154 1.1 christos } 1155 1.1 christos 1156 1.1 christos const char * 1157 1.1 christos res_servicename(u_int16_t port, const char *proto) { /*%< Host byte order. */ 1158 1.1 christos static char number[8]; 1159 1.1 christos struct servent *ss; 1160 1.1 christos 1161 1.1 christos if (servicelist == (struct valuelist *)0) 1162 1.1 christos res_buildservicelist(); 1163 1.1 christos ss = cgetservbyport(htons(port), proto); 1164 1.1 christos if (ss == 0) { 1165 1.1 christos (void) sprintf(number, "%d", port); 1166 1.1 christos return (number); 1167 1.1 christos } 1168 1.1 christos return (ss->s_name); 1169 1.1 christos } 1170