* Copyright (c) 1986 Eric P. Allman
* Copyright (c) 1988 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
static char sccsid
[] = "@(#)domain.c 5.22 (Berkeley) 6/1/90 (with name server)";
static char sccsid
[] = "@(#)domain.c 5.22 (Berkeley) 6/1/90 (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((char *)&answer
, eom
, cp
, 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((char *)&answer
, eom
, cp
, 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
, T_ANY
, (char *)&answer
, sizeof(answer
));
n
= res_search(host
, C_IN
, T_CNAME
, (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((char *)&answer
, eom
, cp
, nbuf
,
(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((char *)&answer
, eom
, cp
, nbuf
,
(void)strncpy(host
, nbuf
, hbsize
); /* XXX */
if (++loopcnt
> 8) /* never be more than 1 */
#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 */