* Copyright (c) 1986 Eric P. Allman
* Copyright (c) 1988 Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)domain.c 5.24 (Berkeley) %G% (with name server)";
static char sccsid
[] = "@(#)domain.c 5.24 (Berkeley) %G% (without name server)";
#include <arpa/nameser.h>
static char hostbuf
[MAXMXHOSTS
*PACKETSZ
];
getmxrr(host
, mxhosts
, localhost
, rcode
)
char *host
, **mxhosts
, *localhost
;
register u_char
*eom
, *cp
;
register int i
, j
, n
, nmx
;
int ancount
, qdcount
, buflen
, seenlocal
;
u_short pref
, localpref
, type
, prefer
[MAXMXHOSTS
];
n
= res_search(host
, C_IN
, T_MX
, (char *)&answer
, sizeof(answer
));
printf("getmxrr: res_search failed (errno=%d, h_errno=%d)\n",
/* no MX data on this host */
/* the host just doesn't exist */
/* couldn't connect to the name server */
if (!UseNameServer
&& errno
== ECONNREFUSED
)
/* it might come up later; better queue it up */
/* irreconcilable differences */
/* find first satisfactory answer */
cp
= (u_char
*)&answer
+ sizeof(HEADER
);
eom
= (u_char
*)&answer
+ n
;
for (qdcount
= ntohs(hp
->qdcount
); qdcount
--; cp
+= n
+ QFIXEDSZ
)
if ((n
= __dn_skipname(cp
, eom
)) < 0)
buflen
= sizeof(hostbuf
);
ancount
= ntohs(hp
->ancount
);
while (--ancount
>= 0 && cp
< eom
&& nmx
< MAXMXHOSTS
) {
if ((n
= dn_expand((u_char
*)&answer
,
eom
, cp
, (u_char
*)bp
, buflen
)) < 0)
cp
+= sizeof(u_short
) + sizeof(u_long
);
if (tTd(8, 1) || _res
.options
& RES_DEBUG
)
printf("unexpected answer type %d, size %d\n",
if ((n
= dn_expand((u_char
*)&answer
,
eom
, cp
, (u_char
*)bp
, buflen
)) < 0)
if (!strcasecmp(bp
, localhost
)) {
if (seenlocal
== 0 || pref
< localpref
)
punt
: mxhosts
[0] = strcpy(hostbuf
, host
);
for (i
= 0; i
< nmx
; i
++) {
for (j
= i
+ 1; j
< nmx
; j
++) {
if (prefer
[i
] > prefer
[j
] ||
(prefer
[i
] == prefer
[j
] && rand() % 1 == 0)) {
if (seenlocal
&& prefer
[i
] >= localpref
) {
* truncate higher pref part of list; if we're
* the best choice left, we should have realized
* awhile ago that this was a local delivery.
getcanonname(host
, hbsize
)
register u_char
*eom
, *cp
;
int first
, ancount
, qdcount
, loopcnt
;
* Use query type of ANY if possible (NO_WILDCARD_MX), which will
* find types CNAME, A, and MX, and will cause all existing records
* to be cached by our local server. If there is (might be) a
* wildcard MX record in the local domain or its parents that are
* searched, we can't use ANY; it would cause fully-qualified names
* to match as names in a local domain.
n
= res_search(host
, C_IN
, WildcardMX
? T_CNAME
: T_ANY
,
(char *)&answer
, sizeof(answer
));
printf("getcanonname: res_search failed (errno=%d, h_errno=%d)\n",
/* find first satisfactory answer */
ancount
= ntohs(hp
->ancount
);
/* we don't care about errors here, only if we got an answer */
printf("rcode = %d, ancount=%d\n", hp
->rcode
, ancount
);
cp
= (u_char
*)&answer
+ sizeof(HEADER
);
eom
= (u_char
*)&answer
+ n
;
for (qdcount
= ntohs(hp
->qdcount
); qdcount
--; cp
+= n
+ QFIXEDSZ
)
if ((n
= __dn_skipname(cp
, eom
)) < 0)
* just in case someone puts a CNAME record after another record,
* check all records for CNAME; otherwise, just take the first
for (first
= 1; --ancount
>= 0 && cp
< eom
; cp
+= n
) {
if ((n
= dn_expand((u_char
*)&answer
,
eom
, cp
, (u_char
*)nbuf
, sizeof(nbuf
))) < 0)
(void)strncpy(host
, nbuf
, hbsize
);
cp
+= sizeof(u_short
) + sizeof(u_long
);
* assume that only one cname will be found. More
* than one is undefined. Copy so that if dn_expand
* fails, `host' is still okay.
if ((n
= dn_expand((u_char
*)&answer
,
eom
, cp
, (u_char
*)nbuf
, sizeof(nbuf
))) < 0)
(void)strncpy(host
, nbuf
, hbsize
); /* XXX */
if (++loopcnt
> 8) /* never be more than 1 */
* Skip over a compressed domain name. Return the size or -1.
__dn_skipname(comp_dn
, eom
)
const u_char
*comp_dn
, *eom
;
while (cp
< eom
&& (n
= *cp
++)) {
switch (n
& INDIR_MASK
) {
case 0: /* normal case, n == len */
default: /* illegal type */
case INDIR_MASK
: /* indirection */
#else /* not NAMED_BIND */
getcanonname(host
, hbsize
)
hp
= gethostbyname(host
);
if (strlen(hp
->h_name
) >= hbsize
)
(void) strcpy(host
, hp
->h_name
);
#endif /* not NAMED_BIND */