Many changes: add option 2; fix FIN_WAIT_2 problem; fix some mail
[unix-history] / usr / src / usr.sbin / sendmail / src / domain.c
CommitLineData
8c0f18d2 1/*
dc45ba8c 2 * Copyright (c) 1986 Eric P. Allman
fa8514f8
KB
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
1acb1197 5 *
417f7a11 6 * %sccs.include.redist.c%
1acb1197 7 */
8c0f18d2 8
97543758 9#include "sendmail.h"
a29056d8 10
8c0f18d2 11#ifndef lint
a29056d8 12#ifdef NAMED_BIND
35f1f39e 13static char sccsid[] = "@(#)domain.c 8.4 (Berkeley) %G% (with name server)";
a29056d8 14#else
35f1f39e 15static char sccsid[] = "@(#)domain.c 8.4 (Berkeley) %G% (without name server)";
a29056d8 16#endif
1acb1197
KB
17#endif /* not lint */
18
a29056d8
EA
19#ifdef NAMED_BIND
20
a29056d8 21#include <errno.h>
bece62ab
KB
22#include <arpa/nameser.h>
23#include <resolv.h>
24#include <netdb.h>
8c0f18d2 25
7e70d3c8
EA
26typedef union
27{
28 HEADER qb1;
29 char qb2[PACKETSZ];
8c0f18d2
JB
30} querybuf;
31
96091294 32static char MXHostBuf[MAXMXHOSTS*PACKETSZ];
8c0f18d2 33
322eceee
EA
34#ifndef MAXDNSRCH
35#define MAXDNSRCH 6 /* number of possible domains to search */
36#endif
37
49a282c6
EA
38#ifndef MAX
39#define MAX(a, b) ((a) > (b) ? (a) : (b))
40#endif
41
35f1f39e
EA
42#ifndef NO_DATA
43# define NO_DATA NO_ADDRESS
44#endif
45
85fe919d
EA
46/* don't use sizeof because sizeof(long) is different on 64-bit machines */
47#define SHORTSIZE 2 /* size of a short (really, must be 2) */
48#define LONGSIZE 4 /* size of a long (really, must be 4) */
fa8514f8
KB
49
50#define MAXCNAMEDEPTH 10 /* maximum depth of CNAME recursion */
85fe919d
EA
51\f/*
52** GETMXRR -- get MX resource records for a domain
53**
54** Parameters:
55** host -- the name of the host to MX.
56** mxhosts -- a pointer to a return buffer of MX records.
c3577cd6
EA
57** droplocalhost -- If TRUE, all MX records less preferred
58** than the local host (as determined by $=w) will
59** be discarded.
85fe919d
EA
60** rcode -- a pointer to an EX_ status code.
61**
62** Returns:
63** The number of MX records found.
64** -1 if there is an internal failure.
65** If no MX records are found, mxhosts[0] is set to host
66** and 1 is returned.
67*/
68
c3577cd6 69getmxrr(host, mxhosts, droplocalhost, rcode)
96091294
EA
70 char *host;
71 char **mxhosts;
c3577cd6 72 bool droplocalhost;
bece62ab 73 int *rcode;
8c0f18d2 74{
bece62ab
KB
75 extern int h_errno;
76 register u_char *eom, *cp;
035aca77
EA
77 register int i, j, n;
78 int nmx = 0;
bece62ab 79 register char *bp;
8c0f18d2 80 HEADER *hp;
bece62ab 81 querybuf answer;
e1b35328 82 int ancount, qdcount, buflen;
035aca77 83 bool seenlocal = FALSE;
6120c83f
EA
84 u_short pref, localpref, type;
85 char *fallbackMX = FallBackMX;
86 static bool firsttime = TRUE;
c3577cd6 87 STAB *st;
6120c83f 88 u_short prefer[MAXMXHOSTS];
7e70d3c8 89 int weight[MAXMXHOSTS];
035aca77 90 extern bool getcanonname();
8c0f18d2 91
6120c83f
EA
92 if (fallbackMX != NULL)
93 {
94 if (firsttime && res_query(FallBackMX, C_IN, T_A,
95 (char *) &answer, sizeof answer) < 0)
96 {
97 /* this entry is bogus */
98 fallbackMX = FallBackMX = NULL;
99 }
c3577cd6
EA
100 else if (droplocalhost &&
101 (st = stab(fallbackMX, ST_CLASS, ST_FIND)) != NULL &&
102 bitnset('w', st->s_class))
6120c83f
EA
103 {
104 /* don't use fallback for this pass */
105 fallbackMX = NULL;
106 }
107 firsttime = FALSE;
108 }
109
19c9e482 110 errno = 0;
bece62ab 111 n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer));
a29056d8
EA
112 if (n < 0)
113 {
bece62ab 114 if (tTd(8, 1))
5ee1c83d
EA
115 printf("getmxrr: res_search(%s) failed (errno=%d, h_errno=%d)\n",
116 (host == NULL) ? "<NULL>" : host, errno, h_errno);
a29056d8
EA
117 switch (h_errno)
118 {
119 case NO_DATA:
120 case NO_RECOVERY:
121 /* no MX data on this host */
bece62ab 122 goto punt;
a29056d8
EA
123
124 case HOST_NOT_FOUND:
125 /* the host just doesn't exist */
bece62ab
KB
126 *rcode = EX_NOHOST;
127 break;
a29056d8
EA
128
129 case TRY_AGAIN:
130 /* couldn't connect to the name server */
131 if (!UseNameServer && errno == ECONNREFUSED)
132 goto punt;
133
134 /* it might come up later; better queue it up */
bece62ab
KB
135 *rcode = EX_TEMPFAIL;
136 break;
8c0f18d2 137 }
a29056d8
EA
138
139 /* irreconcilable differences */
140 return (-1);
8c0f18d2 141 }
bece62ab
KB
142
143 /* find first satisfactory answer */
144 hp = (HEADER *)&answer;
145 cp = (u_char *)&answer + sizeof(HEADER);
146 eom = (u_char *)&answer + n;
147 for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
ba5c6ea8 148 if ((n = dn_skipname(cp, eom)) < 0)
bece62ab 149 goto punt;
96091294
EA
150 buflen = sizeof(MXHostBuf) - 1;
151 bp = MXHostBuf;
bece62ab 152 ancount = ntohs(hp->ancount);
a2798604 153 while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS - 1)
3251a23d 154 {
0df908a9
KB
155 if ((n = dn_expand((u_char *)&answer,
156 eom, cp, (u_char *)bp, buflen)) < 0)
8c0f18d2
JB
157 break;
158 cp += n;
bece62ab 159 GETSHORT(type, cp);
85fe919d 160 cp += SHORTSIZE + LONGSIZE;
bece62ab 161 GETSHORT(n, cp);
3251a23d
EA
162 if (type != T_MX)
163 {
322eceee 164 if (tTd(8, 8) || _res.options & RES_DEBUG)
8c0f18d2 165 printf("unexpected answer type %d, size %d\n",
bece62ab 166 type, n);
8c0f18d2
JB
167 cp += n;
168 continue;
169 }
bece62ab 170 GETSHORT(pref, cp);
3251a23d
EA
171 if ((n = dn_expand((u_char *)&answer, eom, cp,
172 (u_char *)bp, buflen)) < 0)
8c0f18d2 173 break;
3fff2c44 174 cp += n;
c3577cd6
EA
175 if (droplocalhost &&
176 (st = stab(bp, ST_CLASS, ST_FIND)) != NULL &&
177 bitnset('w', st->s_class))
3251a23d 178 {
e1b35328 179 if (!seenlocal || pref < localpref)
bece62ab 180 localpref = pref;
e1b35328 181 seenlocal = TRUE;
3fff2c44
JB
182 continue;
183 }
7e70d3c8 184 weight[nmx] = mxrand(bp);
8c0f18d2
JB
185 prefer[nmx] = pref;
186 mxhosts[nmx++] = bp;
3251a23d 187 n = strlen(bp);
bece62ab 188 bp += n;
3251a23d
EA
189 if (bp[-1] != '.')
190 {
191 *bp++ = '.';
192 n++;
193 }
194 *bp++ = '\0';
195 buflen -= n + 1;
8c0f18d2 196 }
035aca77
EA
197
198 /* sort the records */
199 for (i = 0; i < nmx; i++)
7e70d3c8 200 {
035aca77 201 for (j = i + 1; j < nmx; j++)
1d014a65 202 {
035aca77
EA
203 if (prefer[i] > prefer[j] ||
204 (prefer[i] == prefer[j] && weight[i] > weight[j]))
205 {
206 register int temp;
207 register char *temp1;
208
209 temp = prefer[i];
210 prefer[i] = prefer[j];
211 prefer[j] = temp;
212 temp1 = mxhosts[i];
213 mxhosts[i] = mxhosts[j];
214 mxhosts[j] = temp1;
215 temp = weight[i];
216 weight[i] = weight[j];
217 weight[j] = temp;
218 }
219 }
220 if (seenlocal && prefer[i] >= localpref)
221 {
222 /* truncate higher preference part of list */
223 nmx = i;
1d014a65 224 }
3fff2c44 225 }
035aca77
EA
226
227 if (nmx == 0)
7e70d3c8 228 {
035aca77
EA
229punt:
230 if (seenlocal &&
231 (!TryNullMXList || gethostbyname(host) == NULL))
7e70d3c8 232 {
035aca77
EA
233 /*
234 ** If we have deleted all MX entries, this is
235 ** an error -- we should NEVER send to a host that
236 ** has an MX, and this should have been caught
237 ** earlier in the config file.
238 **
239 ** Some sites prefer to go ahead and try the
240 ** A record anyway; that case is handled by
241 ** setting TryNullMXList. I believe this is a
242 ** bad idea, but it's up to you....
243 */
244
245 *rcode = EX_CONFIG;
246 return -1;
247 }
248 mxhosts[0] = strcpy(MXHostBuf, host);
249 if (getcanonname(MXHostBuf, sizeof MXHostBuf - 1, FALSE))
250 {
251 bp = &MXHostBuf[strlen(MXHostBuf)];
252 if (bp[-1] != '.')
7e70d3c8 253 {
035aca77
EA
254 *bp++ = '.';
255 *bp = '\0';
3fff2c44 256 }
3fff2c44 257 }
035aca77 258 nmx = 1;
8c0f18d2 259 }
a2798604
EA
260
261 /* if we have a default lowest preference, include that */
c2f90f5a
EA
262 if (fallbackMX != NULL && !seenlocal)
263 mxhosts[nmx++] = fallbackMX;
a2798604 264
7e70d3c8
EA
265 return (nmx);
266}
267\f/*
268** MXRAND -- create a randomizer for equal MX preferences
269**
270** If two MX hosts have equal preferences we want to randomize
271** the selection. But in order for signatures to be the same,
272** we need to randomize the same way each time. This function
273** computes a pseudo-random hash function from the host name.
274**
275** Parameters:
276** host -- the name of the host.
277**
278** Returns:
279** A random but repeatable value based on the host name.
280**
281** Side Effects:
282** none.
283*/
284
285mxrand(host)
286 register char *host;
287{
288 int hfunc;
289 static unsigned int seed;
290
291 if (seed == 0)
292 {
293 seed = (int) curtime() & 0xffff;
294 if (seed == 0)
295 seed++;
296 }
297
298 if (tTd(17, 9))
299 printf("mxrand(%s)", host);
300
301 hfunc = seed;
302 while (*host != '\0')
303 {
304 int c = *host++;
305
306 if (isascii(c) && isupper(c))
307 c = tolower(c);
308 hfunc = ((hfunc << 1) + c) % 2003;
309 }
310
311 hfunc &= 0xff;
312
313 if (tTd(17, 9))
314 printf(" = %d\n", hfunc);
315 return hfunc;
8c0f18d2 316}
07b49560
EA
317\f/*
318** GETCANONNAME -- get the canonical name for named host
319**
322eceee
EA
320** This algorithm tries to be smart about wildcard MX records.
321** This is hard to do because DNS doesn't tell is if we matched
322** against a wildcard or a specific MX.
323**
324** We always prefer A & CNAME records, since these are presumed
325** to be specific.
326**
327** If we match an MX in one pass and lose it in the next, we use
328** the old one. For example, consider an MX matching *.FOO.BAR.COM.
329** A hostname bletch.foo.bar.com will match against this MX, but
330** will stop matching when we try bletch.bar.com -- so we know
331** that bletch.foo.bar.com must have been right. This fails if
332** there was also an MX record matching *.BAR.COM, but there are
333** some things that just can't be fixed.
334**
07b49560
EA
335** Parameters:
336** host -- a buffer containing the name of the host.
337** This is a value-result parameter.
338** hbsize -- the size of the host buffer.
035aca77 339** trymx -- if set, try MX records as well as A and CNAME.
07b49560
EA
340**
341** Returns:
342** TRUE -- if the host matched.
343** FALSE -- otherwise.
07b49560 344*/
94ce122d 345
bbfde42f 346bool
035aca77 347getcanonname(host, hbsize, trymx)
b22f87a1
JB
348 char *host;
349 int hbsize;
035aca77 350 bool trymx;
b22f87a1 351{
fa3cad61 352 extern int h_errno;
94ce122d
EA
353 register u_char *eom, *ap;
354 register char *cp;
bece62ab 355 register int n;
b22f87a1 356 HEADER *hp;
bece62ab 357 querybuf answer;
a3934270 358 int ancount, qdcount;
94ce122d 359 int ret;
94ce122d 360 char **domain;
94ce122d 361 int type;
322eceee
EA
362 char **dp;
363 char *mxmatch;
364 bool amatch;
57c2a3b9 365 bool gotmx;
c63cdab6 366 int qtype;
fa8514f8 367 int loopcnt;
49a282c6 368 char nbuf[MAX(PACKETSZ, MAXDNAME*2+2)];
421d5c80 369 char *searchlist[MAXDNSRCH+2];
94ce122d
EA
370
371 if (tTd(8, 2))
372 printf("getcanonname(%s)\n", host);
373
374 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
375 return (FALSE);
b22f87a1 376
19c9e482 377 /*
322eceee
EA
378 ** Initialize domain search list. If there is at least one
379 ** dot in the name, search the unmodified name first so we
380 ** find "vse.CS" in Czechoslovakia instead of in the local
381 ** domain (e.g., vse.CS.Berkeley.EDU).
382 **
383 ** Older versions of the resolver could create this
384 ** list by tearing apart the host name.
d51c0d9a
EA
385 */
386
fa8514f8 387 loopcnt = 0;
b104ca4a
EA
388cnameloop:
389 for (cp = host, n = 0; *cp; cp++)
390 if (*cp == '.')
391 n++;
392
322eceee
EA
393 dp = searchlist;
394 if (n > 0)
395 *dp++ = "";
57c2a3b9 396 if (n >= 0 && *--cp != '.' && bitset(RES_DNSRCH, _res.options))
d51c0d9a 397 {
322eceee
EA
398 for (domain = _res.dnsrch; *domain != NULL; )
399 *dp++ = *domain++;
d51c0d9a 400 }
57c2a3b9
EA
401 else if (n == 0 && bitset(RES_DEFNAMES, _res.options))
402 {
403 *dp++ = _res.defdname;
404 }
322eceee 405 *dp = NULL;
d51c0d9a
EA
406
407 /*
322eceee 408 ** Now run through the search list for the name in question.
d51c0d9a
EA
409 */
410
322eceee 411 mxmatch = NULL;
c63cdab6 412 qtype = T_ANY;
322eceee 413
c63cdab6 414 for (dp = searchlist; *dp != NULL; )
94ce122d 415 {
57c2a3b9
EA
416 if (qtype == T_ANY)
417 gotmx = FALSE;
322eceee 418 if (tTd(8, 5))
ab54800d
EA
419 printf("getcanonname: trying %s.%s (%s)\n", host, *dp,
420 qtype == T_ANY ? "ANY" : qtype == T_A ? "A" :
421 qtype == T_MX ? "MX" : "???");
c63cdab6 422 ret = res_querydomain(host, *dp, C_IN, qtype,
49a282c6 423 &answer, sizeof(answer));
322eceee 424 if (ret <= 0)
94ce122d 425 {
1d136a1f 426 if (tTd(8, 7))
1c7897ef
EA
427 printf("\tNO: errno=%d, h_errno=%d\n",
428 errno, h_errno);
94ce122d 429
1c7897ef 430 if (errno == ECONNREFUSED || h_errno == TRY_AGAIN)
d51c0d9a 431 {
322eceee 432 /* the name server seems to be down */
94ce122d 433 h_errno = TRY_AGAIN;
4ae3ff58 434 return FALSE;
94ce122d 435 }
322eceee 436
2c8a024c 437 if (h_errno != HOST_NOT_FOUND)
c63cdab6 438 {
2c8a024c
EA
439 /* might have another type of interest */
440 if (qtype == T_ANY)
441 {
442 qtype = T_A;
443 continue;
444 }
035aca77 445 else if (qtype == T_A && !gotmx && trymx)
2c8a024c
EA
446 {
447 qtype = T_MX;
448 continue;
449 }
c63cdab6
EA
450 }
451
322eceee 452 if (mxmatch != NULL)
94ce122d 453 {
322eceee 454 /* we matched before -- use that one */
94ce122d
EA
455 break;
456 }
2c8a024c
EA
457
458 /* otherwise, try the next name */
459 dp++;
460 qtype = T_ANY;
322eceee 461 continue;
94ce122d 462 }
1d136a1f 463 else if (tTd(8, 7))
322eceee
EA
464 printf("\tYES\n");
465
4ae3ff58 466 /*
322eceee
EA
467 ** This might be a bogus match. Search for A or
468 ** CNAME records. If we don't have a matching
469 ** wild card MX record, we will accept MX as well.
4ae3ff58
EA
470 */
471
322eceee
EA
472 hp = (HEADER *) &answer;
473 ap = (u_char *) &answer + sizeof(HEADER);
474 eom = (u_char *) &answer + ret;
475
476 /* skip question part of response -- we know what we asked */
477 for (qdcount = ntohs(hp->qdcount); qdcount--; ap += ret + QFIXEDSZ)
94ce122d 478 {
322eceee
EA
479 if ((ret = dn_skipname(ap, eom)) < 0)
480 {
481 if (tTd(8, 20))
482 printf("qdcount failure (%d)\n",
483 ntohs(hp->qdcount));
484 return FALSE; /* ???XXX??? */
485 }
94ce122d 486 }
bece62ab 487
322eceee
EA
488 amatch = FALSE;
489 for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom; ap += n)
94ce122d 490 {
322eceee
EA
491 n = dn_expand((u_char *) &answer, eom, ap,
492 (u_char *) nbuf, sizeof nbuf);
493 if (n < 0)
494 break;
495 ap += n;
496 GETSHORT(type, ap);
85fe919d 497 ap += SHORTSIZE + LONGSIZE;
322eceee
EA
498 GETSHORT(n, ap);
499 switch (type)
500 {
501 case T_MX:
57c2a3b9 502 gotmx = TRUE;
322eceee
EA
503 if (**dp != '\0')
504 {
505 /* got a match -- save that info */
506 if (mxmatch == NULL)
507 mxmatch = *dp;
508 continue;
509 }
510
511 /* exact MX matches are as good as an A match */
512 /* fall through */
513
514 case T_A:
515 /* good show */
516 amatch = TRUE;
517
518 /* continue in case a CNAME also exists */
519 continue;
520
521 case T_CNAME:
fa8514f8
KB
522 if (loopcnt++ > MAXCNAMEDEPTH)
523 {
524 syserr("DNS failure: CNAME loop for %s",
525 host);
526 continue;
527 }
528
322eceee
EA
529 /* value points at name */
530 if ((ret = dn_expand((u_char *)&answer,
531 eom, ap, (u_char *)nbuf, sizeof(nbuf))) < 0)
532 break;
533 (void)strncpy(host, nbuf, hbsize); /* XXX */
534 host[hbsize - 1] = '\0';
f1770f93
EA
535
536 /*
537 ** RFC 1034 section 3.6 specifies that CNAME
538 ** should point at the canonical name -- but
539 ** urges software to try again anyway.
540 */
541
542 goto cnameloop;
322eceee
EA
543
544 default:
545 /* not a record of interest */
546 continue;
547 }
94ce122d 548 }
bece62ab 549
322eceee
EA
550 if (amatch)
551 {
552 /* got an A record and no CNAME */
553 mxmatch = *dp;
b22f87a1 554 break;
b22f87a1 555 }
c63cdab6
EA
556
557 /*
558 ** If this was a T_ANY query, we may have the info but
559 ** need an explicit query. Try T_A, then T_MX.
560 */
561
562 if (qtype == T_ANY)
563 qtype = T_A;
035aca77 564 else if (qtype == T_A && !gotmx && trymx)
c63cdab6
EA
565 qtype = T_MX;
566 else
567 {
568 /* really nothing in this domain; try the next */
569 qtype = T_ANY;
570 dp++;
571 }
b22f87a1 572 }
322eceee
EA
573
574 if (mxmatch == NULL)
575 return FALSE;
576
577 /* create matching name and return */
578 (void) sprintf(nbuf, "%.*s%s%.*s", MAXDNAME, host,
579 *mxmatch == '\0' ? "" : ".",
580 MAXDNAME, mxmatch);
581 strncpy(host, nbuf, hbsize);
582 host[hbsize - 1] = '\0';
583 return TRUE;
b22f87a1 584}
3e13e52f
EA
585\f/*
586** MAILB_LOOKUP -- do DNS mailbox lookup
587*/
588
589#ifdef DNS_MAILB
590
591mailb_lookup(addr)
592 char *addr;
593{
594 /*
595 ** Convert addr to DNS form (user.host).
596 */
597
598 /* figure out how much space it needs */
599 atp = strchr(addr, '@');
600 if (atp == NULL)
601 atp = &addr(strlen(addr));
602 i = strlen(addr);
603 for (p = addr; (p = strchr(p, '.')) != NULL; p++)
604 {
605 if (p > atp)
606 break;
607 i++;
608 }
609 if (i < sizeof abuf)
610 bufp = abuf;
611 else
612 bufp = xalloc(i + 1);
613
614 lhsmode = TRUE;
615 for (p = addr, q = bufp; (c = *p++) != '\0'; )
616 {
617 if (c == '.' && lhsmode)
618 *q++ = '\\';
619 if (c == '@')
620 lhsmode = FALSE;
621 *q++ = c;
622 }
623 *q = '\0';
624
625 /*
626 ** Now do a MAILB lookup.
627 */
628
629retry:
630 if (res_query(bufp, C_IN, T_MAILB, (char *) &answer, sizeof answer < 0)
631 {
632 /* no match -- just continue as usual */
633 return FALSE;
634 }
635
636 /* find first satisfactory answer */
637 hp = (HEADER *)&answer;
638 ap = (u_char *)&answer + sizeof(HEADER);
639 eom = (u_char *)&answer + n;
640 for (qdcount = ntohs(hp->qdcount); qdcount--; ap += n + QFIXEDSZ)
641 if ((n = dn_skipname(ap, eom)) < 0)
642 return FALSE;
643 for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom; ap += n)
644 {
645 n = dn_expand((u_char *)&answer, eom, ap, (u_char *)bp, buflen);
646 if (n < 0)
647 break;
648 ap += n;
649 GETSHORT(type, ap);
650 ap += SHORTSIZE + LONGSIZE;
651 GETSHORT(n, ap);
652 switch (type)
653 {
654 case T_MR:
655 /* rename: try again */
656 i = dn_expand((u_char *) &answer, eom, ap,
657 (u_char) abuf, sizeof abuf);
658 if (i < 0)
659 break;
660 if (bufp != abuf)
661 {
662 free(bufp);
663 bufp = abuf;
664 }
665 goto retry;
666
667 case T_MB:
668 i = dn_expand((u_char *) &answer, eom, ap,
669 (u_char) hbuf, sizeof hbuf);
670 if (i < 0)
671 break;
672
673 /* hbuf now has the host to deliver to */
674 break;
675
676 case T_MG:
677 i = dn_expand((u_char *) &answer, eom, ap,
678 (u_char) gbuf, sizeof gbuf);
679 if (i < 0)
680 break;
681 AliasLevel++;
682 naddrs += sendtolist(ubuf, a, sendq, e);
683 AliasLevel--;
684 break;
685
686 case T_MINFO:
687 /* bleach */
688 XXX;
689 }
690
691
692
693 if (type != T_MX)
694 {
695 if (tTd(8, 8) || _res.options & RES_DEBUG)
696 printf("unexpected answer type %d, size %d\n",
697 type, n);
698 cp += n;
699 continue;
700 }
701 GETSHORT(pref, cp);
702 if ((n = dn_expand((u_char *)&answer, eom, cp,
703 (u_char *)bp, buflen)) < 0)
704 break;
705 cp += n;
706
707
708#endif /* DNS_MAILB */
a29056d8 709
da1f33f9
PL
710#else /* not NAMED_BIND */
711
712#include <netdb.h>
713
bbfde42f 714bool
035aca77 715getcanonname(host, hbsize, trymx)
da1f33f9
PL
716 char *host;
717 int hbsize;
035aca77 718 bool trymx;
da1f33f9
PL
719{
720 struct hostent *hp;
721
722 hp = gethostbyname(host);
723 if (hp == NULL)
bbfde42f 724 return (FALSE);
da1f33f9
PL
725
726 if (strlen(hp->h_name) >= hbsize)
bbfde42f 727 return (FALSE);
da1f33f9
PL
728
729 (void) strcpy(host, hp->h_name);
bbfde42f 730 return (TRUE);
da1f33f9
PL
731}
732
733#endif /* not NAMED_BIND */