leres@helios.ee.lbl.gov (Craig Leres) (03/10/89)
This afternoon, I noticed a lot of nameserver traffic on my ethernet. A host was making an request, getting an answer, and then asking the same question again. Over and over. After a little investigation, I think I understand the problem and can offer a solution. Let's say someone wants to send mail to a host that has a MX record but no A record. (For example, DEC is setup so that any mx query in the domain dec.com returns decwrl.dec.com.) Unfortunately, he try this from a Sun that is running a non-mx sendmail. Here's where things go wrong. Sendmail does a gethostbyname() which turns into a yp request. Ypserv (which is running with -i) forks and the child makes an A record request of the nameserver. The nameserver comes back with the status NO_ADDRESS (an alias for NO_DATA) which means that there are valid records for the name (i.e. the MX record) but that the requested record does not exist. The ypserv child exists and after some short timeout, the parent ypserv forks off another to repeat the process. To demonstrate the bug, try something similar to: % ypmatch fnord.dec.com hosts.byname This should hang for a long time (perhaps forever) while ypserv (repeatedly) puts the DNS (Domain Name System) through its paces. It seems obvious that if ypserv gets NO_ADDRESS, it should just return the error and not retry. Appended is a context diff to the 3.5 version of usr.etc/ypserv/ypserv_proc.c (your line numbers may vary) which implements this fix. I'm not sure how this problem relates to 4.0. Craig ------ RCS file: RCS/ypserv_proc.c,v retrieving revision 1.3 diff -c -r1.3 ypserv_proc.c *** /tmp/,RCSt1a01990 Fri Mar 3 04:05:34 1989 --- ypserv_proc.c Fri Mar 3 04:06:01 1989 *************** *** 172,178 **** if (h == NULL) { extern int h_errno; ! if (h_errno == TRY_AGAIN || h_errno == NO_ADDRESS) exit(0); *statusp = YP_NOKEY; return(CHILD_PROC); } --- 172,181 ---- if (h == NULL) { extern int h_errno; ! /* Bail if there's a chance we'll get the info next time */ ! if (h_errno == TRY_AGAIN) ! exit(0); ! *statusp = YP_NOKEY; return(CHILD_PROC); }