BSD 4_4_Lite1 release
[unix-history] / usr / src / contrib / bind-4.9.2 / named / db_glue.c
CommitLineData
ad787160
C
1#if !defined(lint) && !defined(SABER)
2static char sccsid[] = "@(#)db_glue.c 4.4 (Berkeley) 6/1/90";
ed554bc5 3static char rcsid[] = "$Id: db_glue.c,v 4.9.1.5 1993/11/03 12:26:04 vixie Exp $";
ad787160
C
4#endif /* not lint */
5
6/*
7 * ++Copyright++ 1986, 1988
8 * -
ed554bc5
C
9 * Copyright (c) 1986, 1988
10 * The Regents of the University of California. All rights reserved.
ad787160
C
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 * -
40 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
41 *
42 * Permission to use, copy, modify, and distribute this software for any
43 * purpose with or without fee is hereby granted, provided that the above
44 * copyright notice and this permission notice appear in all copies, and that
45 * the name of Digital Equipment Corporation not be used in advertising or
46 * publicity pertaining to distribution of the document or software without
47 * specific, written prior permission.
48 *
49 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
50 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
51 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
52 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
53 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
54 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
55 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56 * SOFTWARE.
57 * -
58 * --Copyright--
59 */
60
61#include <sys/types.h>
62#include <sys/uio.h>
63#include <sys/param.h>
ad787160
C
64#include <sys/stat.h>
65#include <netinet/in.h>
66#include <arpa/nameser.h>
67#include <stdio.h>
68#include <syslog.h>
69#include <ctype.h>
70#include <netdb.h>
71#include <errno.h>
ed554bc5
C
72
73#include "named.h"
ad787160
C
74
75struct valuelist {
76 struct valuelist *next, *prev;
77 char *name;
78 char *proto;
ed554bc5 79 int port;
ad787160
C
80} *servicelist, *protolist;
81
82void
83buildservicelist()
84{
85 struct servent *sp;
86 struct valuelist *slp;
87
88 setservent(1);
89 while (sp = getservent()) {
90 slp = (struct valuelist *)malloc(sizeof(struct valuelist));
91 slp->name = savestr(sp->s_name);
92 slp->proto = savestr(sp->s_proto);
ed554bc5 93 slp->port = ntohs((u_int16_t)sp->s_port);
ad787160
C
94 slp->next = servicelist;
95 slp->prev = NULL;
96 if (servicelist)
97 servicelist->prev = slp;
98 servicelist = slp;
99 }
100 endservent();
101}
102
103void
104buildprotolist()
105{
106 struct protoent *pp;
107 struct valuelist *slp;
108
109 setprotoent(1);
110 while (pp = getprotoent()) {
111 slp = (struct valuelist *)malloc(sizeof(struct valuelist));
112 slp->name = savestr(pp->p_name);
113 slp->port = pp->p_proto;
114 slp->next = protolist;
115 slp->prev = NULL;
116 if (protolist)
117 protolist->prev = slp;
118 protolist = slp;
119 }
120 endprotoent();
121}
122
ed554bc5 123static int
ad787160
C
124findservice(s, list)
125 register char *s;
126 register struct valuelist **list;
127{
128 register struct valuelist *lp = *list;
129 int n;
130
131 for (; lp != NULL; lp = lp->next)
132 if (strcasecmp(lp->name, s) == 0) {
133 if (lp != *list) {
134 lp->prev->next = lp->next;
135 if (lp->next)
136 lp->next->prev = lp->prev;
137 (*list)->prev = lp;
138 lp->next = *list;
139 *list = lp;
140 }
141 return(lp->port);
142 }
143 if (sscanf(s, "%d", &n) != 1 || n <= 0)
144 n = -1;
145 return(n);
146}
147
ed554bc5
C
148/*
149 * Convert service name or (ascii) number to int.
150 */
151int
152servicenumber(p)
153 char *p;
154{
155 return (findservice(p, &servicelist));
156}
157
158/*
159 * Convert protocol name or (ascii) number to int.
160 */
161int
162protocolnumber(p)
163 char *p;
164{
165 return (findservice(p, &protolist));
166}
167
168#if defined(__STDC__) || defined(__GNUC__)
169static struct servent *
170cgetservbyport(u_int16_t port,
171 char *proto)
172#else
173static struct servent *
ad787160 174cgetservbyport(port, proto)
ed554bc5 175 u_int16_t port;
ad787160 176 char *proto;
ed554bc5 177#endif
ad787160
C
178{
179 register struct valuelist **list = &servicelist;
180 register struct valuelist *lp = *list;
181 static struct servent serv;
182
183 port = htons(port);
184 for (; lp != NULL; lp = lp->next) {
ed554bc5 185 if (port != (u_int16_t)lp->port)
ad787160
C
186 continue;
187 if (strcasecmp(lp->proto, proto) == 0) {
188 if (lp != *list) {
189 lp->prev->next = lp->next;
190 if (lp->next)
191 lp->next->prev = lp->prev;
192 (*list)->prev = lp;
193 lp->next = *list;
194 *list = lp;
195 }
196 serv.s_name = lp->name;
ed554bc5 197 serv.s_port = htons((u_int16_t)lp->port);
ad787160
C
198 serv.s_proto = lp->proto;
199 return(&serv);
200 }
201 }
202 return(0);
203}
204
ed554bc5 205static struct protoent *
ad787160
C
206cgetprotobynumber(proto)
207 register int proto;
208{
ad787160
C
209 register struct valuelist **list = &protolist;
210 register struct valuelist *lp = *list;
211 static struct protoent prot;
212
213 for (; lp != NULL; lp = lp->next)
214 if (lp->port == proto) {
215 if (lp != *list) {
216 lp->prev->next = lp->next;
217 if (lp->next)
218 lp->next->prev = lp->prev;
219 (*list)->prev = lp;
220 lp->next = *list;
221 *list = lp;
222 }
223 prot.p_name = lp->name;
224 prot.p_proto = lp->port;
225 return(&prot);
226 }
227 return(0);
228}
229
230char *
231protocolname(num)
232 int num;
233{
234 static char number[8];
235 struct protoent *pp;
236
237 pp = cgetprotobynumber(num);
238 if(pp == 0) {
239 (void) sprintf(number, "%d", num);
240 return(number);
241 }
242 return(pp->p_name);
243}
244
ed554bc5
C
245#if defined(__STDC__) || defined(__GNUC__)
246char *
247servicename(u_int16_t port, char *proto)
248#else
ad787160
C
249char *
250servicename(port, proto)
ed554bc5 251 u_int16_t port;
ad787160 252 char *proto;
ed554bc5 253#endif
ad787160
C
254{
255 static char number[8];
256 struct servent *ss;
257
258 ss = cgetservbyport(htons(port), proto);
ed554bc5 259 if (ss == 0) {
ad787160
C
260 (void) sprintf(number, "%d", port);
261 return(number);
262 }
263 return(ss->s_name);
264}
265
ed554bc5
C
266#ifdef CRED
267db_getclev(origin)
268char *origin;
269{
270 int lev = 0;
271 dprintf(1, (ddt, "db_getclev of \"%s\"",origin));
272 while (origin && (origin = strchr(origin,'.'))) {
273 origin++;
274 lev++;
275 }
276 dprintf(1, (ddt, " = %d\n",lev));
277 return lev;
278}
279#endif
280
ad787160
C
281void
282gettime(ttp)
283struct timeval *ttp;
284{
285 if (gettimeofday(ttp, (struct timezone *)0) < 0)
286 syslog(LOG_ERR, "gettimeofday failed: %m");
287 return;
288}
289
290#if !defined(BSD)
291int
292getdtablesize()
293{
ed554bc5 294#if defined(USE_POSIX)
ad787160
C
295 int j;
296
297 if ((j = (int) sysconf(_SC_OPEN_MAX)) < 0)
ed554bc5
C
298 return FD_SETSIZE;
299 return j;
ad787160 300#else
ed554bc5 301 return FD_SETSIZE;
ad787160
C
302#endif /* POSIX */
303}
304#endif /* BSD */
305
306int
307my_close(fd)
308 int fd;
309{
310 int s = close(fd);
311
312 if (s < 0) {
313 syslog(LOG_ERR, "close(%d) failed: %m", fd);
ed554bc5
C
314 dprintf(3, (ddt, "close(%d) failed: %s\n",
315 fd, strerror(errno)));
ad787160 316 } else {
ed554bc5 317 dprintf(3, (ddt, "close(%d) succeeded\n", fd));
ad787160
C
318 }
319 return s;
320}
321
ed554bc5
C
322#ifdef GEN_AXFR
323/*
324 * Map class names to number
325 */
326struct map {
327 char *token;
328 int val;
329};
330
331static struct map map_class[] = {
332 "in", C_IN,
333 "chaos", C_CHAOS,
334 "hs", C_HS,
335 NULL, 0,
336};
337
338int
339get_class(class)
340 char *class;
341{
342 struct map *mp;
343
344 if (isdigit(*class))
345 return (atoi(class));
346 for (mp = map_class; mp->token != NULL; mp++)
347 if (strcasecmp(class, mp->token) == 0)
348 return (mp->val);
349 return (C_IN);
350}
351#endif
352
ad787160
C
353int
354my_fclose(fp)
355 FILE *fp;
356{
357 int fd = fileno(fp),
358 s = fclose(fp);
359
360 if (s < 0) {
361 syslog(LOG_ERR, "fclose(%d) failed: %m", fd);
ed554bc5
C
362 dprintf(3, (ddt, "fclose(%d) failed: %s\n",
363 fd, strerror(errno)));
ad787160 364 } else {
ed554bc5 365 dprintf(3, (ddt, "fclose(%d) succeeded\n", fd));
ad787160
C
366 }
367 return s;
368}
369
370/*
371 * Make a copy of a string and return a pointer to it.
372 */
373char *
374savestr(str)
375 char *str;
376{
377 char *cp;
378
379 cp = malloc(strlen(str) + 1);
380 if (cp == NULL) {
381 syslog(LOG_ERR, "savestr: %m");
382 exit(1);
383 }
384 (void) strcpy(cp, str);
ed554bc5 385 return cp;
ad787160
C
386}
387
388int
389writemsg(rfd, msg, msglen)
390 int rfd;
391 u_char *msg;
392 int msglen;
393{
394 struct iovec iov[2];
ed554bc5 395 u_int16_t len = htons((u_int16_t)msglen);
ad787160
C
396
397 iov[0].iov_base = (caddr_t)&len;
398 iov[0].iov_len = sizeof(len);
399 iov[1].iov_base = (caddr_t)msg;
400 iov[1].iov_len = msglen;
401 if (writev(rfd, iov, 2) != sizeof(len) + msglen) {
ed554bc5 402 dprintf(1, (ddt, "write failed %d\n", errno));
ad787160
C
403 return (-1);
404 }
405 return (0);
406}
ed554bc5
C
407
408/* rm_datum(dp, np, pdp)
409 * remove datum 'dp' from name 'np'. pdp is previous data pointer.
410 * return value:
411 * "next" field from removed datum, suitable for relinking
412 */
413struct databuf *
414rm_datum(dp, np, pdp)
415 register struct databuf *dp;
416 register struct namebuf *np;
417 register struct databuf *pdp;
418{
419 register struct databuf *ndp = dp->d_next;
420
421 dprintf(3, (ddt, "rm_datum(%x, %x, %x) -> %x\n",
422 dp, np->n_data, pdp, ndp));
423#if INVQ
424 rminv(dp);
425#endif
426 if (pdp == NULL)
427 np->n_data = ndp;
428 else
429 pdp->d_next = ndp;
430#ifdef DATUMREFCNT
431 if (--(dp->d_rcnt)) {
432 switch(dp->d_type) {
433 case T_NS:
434 dprintf(1, (ddt, "rm_datum: %s rcnt = %d\n",
435 dp->d_data, dp->d_rcnt));
436 break;
437 case T_A:
438 dprintf(1, (ddt, "rm_datum: %08.8X rcnt = %d\n",
439 *(int32_t*)(dp->d_data), dp->d_rcnt));
440 break;
441 default:
442 dprintf(1, (ddt, "rm_datum: rcnt = %d\n", dp->d_rcnt));
443 }
444 } else
445#endif
446 free((char *)dp);
447 return ndp;
448}
449
450/* rm_name(np, he, pnp)
451 * remove name 'np' from parent 'pp'. pnp is previous name pointer.
452 * return value:
453 * "next" field from removed name, suitable for relinking
454 */
455struct namebuf *
456rm_name(np, pp, pnp)
457 struct namebuf *np, **pp, *pnp;
458{
459 struct namebuf *nnp = np->n_next;
460 char *msg;
461
462 /* verify */
463 if ( (np->n_data && (msg = "data"))
464 || (np->n_hash && (msg = "hash"))
465 ) {
466 fprintf(ddt,
467 "rm_name(%x(%s)): non-nil %s pointer\n",
468 np, np->n_dname?np->n_dname:"Nil", msg);
469 syslog(LOG_ERR,
470 "rm_name(%x(%s)): non-nil %s pointer\n",
471 np, np->n_dname?np->n_dname:"Nil", msg);
472 abort();
473 }
474
475 /* unlink */
476 if (pnp) {
477 pnp->n_next = nnp;
478 } else {
479 *pp = nnp;
480 }
481
482 /* deallocate */
483 free(np->n_dname);
484 free((char*) np);
485
486 /* done */
487 return nnp;
488}
489
490/*
491 * Get the domain name of 'np' and put in 'buf'. Bounds checking is done.
492 */
493void
494getname(np, buf, buflen)
495 struct namebuf *np;
496 char *buf;
497 int buflen;
498{
499 register char *cp;
500 register int i;
501
502 cp = buf;
503 while (np != NULL) {
504 if ((i = strlen(np->n_dname))+1 >= buflen) {
505 *cp = '\0';
506 syslog(LOG_ERR, "domain name too long: %s...\n", buf);
507 strcpy(buf, "Name_Too_Long");
508 return;
509 }
510 if (cp != buf)
511 *cp++ = '.';
512 (void) strcpy(cp, np->n_dname);
513 cp += i;
514 buflen -= (i+1);
515 np = np->n_parent;
516 }
517 *cp = '\0';
518}
519
520#if INVQ
521/*
522 * Add data 'dp' to inverse query tables for name 'np'.
523 */
524void
525addinv(np, dp)
526 struct namebuf *np;
527 struct databuf *dp;
528{
529 register struct invbuf *ip;
530 register int hval, i;
531
532 switch (dp->d_type) {
533 case T_A:
534 case T_UID:
535 case T_GID:
536 break;
537
538 default:
539 return;
540 }
541
542 hval = dhash(dp->d_data, dp->d_size);
543 for (ip = invtab[hval]; ip != NULL; ip = ip->i_next)
544 for (i = 0; i < INVBLKSZ; i++)
545 if (ip->i_dname[i] == NULL) {
546 ip->i_dname[i] = np;
547 return;
548 }
549 ip = saveinv();
550 ip->i_next = invtab[hval];
551 invtab[hval] = ip;
552 ip->i_dname[0] = np;
553}
554
555/*
556 * Remove data 'odp' from inverse query table.
557 */
558void
559rminv(odp)
560 struct databuf *odp;
561{
562 register struct invbuf *ip;
563 register struct databuf *dp;
564 struct namebuf *np;
565 register int i;
566
567 for (ip = invtab[dhash(odp->d_data, odp->d_size)]; ip != NULL;
568 ip = ip->i_next) {
569 for (i = 0; i < INVBLKSZ; i++) {
570 if ((np = ip->i_dname[i]) == NULL)
571 break;
572 for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
573 if (dp != odp)
574 continue;
575 while (i < INVBLKSZ-1) {
576 ip->i_dname[i] = ip->i_dname[i+1];
577 i++;
578 }
579 ip->i_dname[i] = NULL;
580 return;
581 }
582 }
583 }
584}
585
586/*
587 * Allocate an inverse query buffer.
588 */
589struct invbuf *
590saveinv()
591{
592 register struct invbuf *ip;
593
594 ip = (struct invbuf *) malloc(sizeof(struct invbuf));
595 if (ip == NULL) {
596 syslog(LOG_ERR, "saveinv: %m");
597 exit(1);
598 }
599 ip->i_next = NULL;
600 bzero((char *)ip->i_dname, sizeof(ip->i_dname));
601 return (ip);
602}
603#endif /*INVQ*/
604
605/*
606 * Compute hash value from data.
607 */
608int
609dhash(dp, dlen)
610 u_char *dp;
611 int dlen;
612{
613 register u_char *cp;
614 register unsigned hval;
615 register int n;
616
617 n = dlen;
618 if (n > 8)
619 n = 8;
620 hval = 0;
621 for (cp = dp; --n >= 0; ) {
622 hval <<= 1;
623 hval += *cp++;
624 }
625 return (hval % INVHASHSZ);
626}