res_mkupdate.c revision 1.2 1 1.2 christos /* $NetBSD: res_mkupdate.c,v 1.2 2012/11/19 13:45:00 christos 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.2 christos __RCSID("$NetBSD: res_mkupdate.c,v 1.2 2012/11/19 13:45:00 christos 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.1 christos * get a white spae 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.1 christos slp->port = ntohs((u_int16_t)sp->s_port); /*%< host byt 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