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