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