*BSD News Article 80899


Return to BSD News archive

Newsgroups: comp.unix.bsd.freebsd.misc,comp.unix.solaris
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!munnari.OZ.AU!metro!metro!news.nsw.CSIRO.AU!marka
From: marka@syd.dms.CSIRO.AU (Mark Andrews)
Subject: Re: named/Connection lags on Solaris..
X-Nntp-Posting-Host: pride.syd.dms.csiro.au
Message-ID: <845519879.509524@pride.syd.dms.CSIRO.AU>
Sender: news@news.nsw.CSIRO.AU
Organization: CSIRO Division of Mathematics and Statistics, Australia
References: <540rpq$rhj@netaxs.com>
Cache-Post-Path: pride.syd.dms.CSIRO.AU!unknown@drugs.syd.dms.csiro.au
Distribution: inet
Date: Thu, 17 Oct 1996 02:38:00 GMT
Lines: 149
Xref: euryale.cc.adfa.oz.au comp.unix.bsd.freebsd.misc:29399 comp.unix.solaris:86131

In article <540rpq$rhj@netaxs.com> heller@cdnow.com writes:
>
>  Strange topic to post here but its related... trust me..
>
>
>I've got a Solaris 2.5.1 box that is running as a secondary name server
>to a FreeBSD 2.1.5 box primary name server.
>
>  I'm experiencing connection lags to and from the solaris box to other
>machines.  The connection eventually will go through but will sit for
>a very long time before connecting.  It is also random ( or so ) and I 
>can't reproduce it other than when someone screams why they can't get to
>some machine.
>
>  You can telnet to some host and it will just sit there.. then go through.
>This lag can be a few seconds to over 30.  I am assuming that this is some
>kind of Solaris problem as it existed when it was the primary name server.

	This is related to a bug/feature in the SunOS (both 4 and 5)
	kernels and the workaround in the resolver library. It will only
	impact you if the first server queried takes a long time to
	resolve the message.

	1. the resolver uses "connected" UDP sockets to detect dead
	named processes on the DNS server. fast fall over.

	2. when it moves onto the second server it attempts to put this
	socket into an "unconnected" state. This is possible on BSD 4.3
	or later derived kernels but not on BSD 4.2 derived kernels or
	in the IP stack in SunOS 5. The workaround in the resolver is to
	open a new UDP socket.

	The ICMP unreachables are the result of the server finally
	getting an answer to the first query, or SERVFAIL, and
	responding to the now non-existent UDP port.

	The code below demonstates the problem using the UDP echo
	port. The third getpeername() should fail but doesn't.

	Mark

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

main()
{
	int fd;
	int size;
	int count;
	struct sockaddr_in none, remote, set, echo;
	char buf[100];
	
	alarm(10);

	if ((fd = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) {
		perror("socket");
	}
	none.sin_family = AF_INET;
	none.sin_port = 0;
	none.sin_addr.s_addr = 0;
	if (bind(fd,(struct sockaddr *)&none,sizeof(none)) < 0) {
		perror("bind");
	}
	/*
	 * UNCONNECTED
	 */
	/*
	 * getpeername should fail
	 */
	size = sizeof(remote);
	if (getpeername(fd,(struct sockaddr *)& remote, &size ) < 0) {
		perror("getpeername 1");
	} else {
		printf("getpeername 1: %s.%d\n", inet_ntoa(remote.sin_addr),
				ntohs(remote.sin_port));
	}

	echo.sin_family = AF_INET;
	echo.sin_port = htons(7); /* echo */
	echo.sin_addr.s_addr = inet_addr("127.0.0.1");

	if (sendto(fd, "Message 1", 9, 0,(struct sockaddr *) &echo, sizeof(echo)) < 0) {
		perror("sendto 1");
	}

	size = 0;
	if ((count = recvfrom(fd, buf, 100, 0, (struct sockaddr *)0, &size)) < 0) {
		perror("recvfrom 1");
	} else {
		printf("Got back %0.*s\n", count, buf);
	}

	/*
	 * CONNECT
	 */
	set.sin_family = AF_INET;
	set.sin_port = htons(53);
	set.sin_addr.s_addr = inet_addr("10.0.2.1");

	if (connect(fd,(struct sockaddr *)&set, sizeof(set)) < 0) {
		perror("connect 1");
	}
	size = sizeof(remote);
	if (getpeername(fd,(struct sockaddr *)& remote, &size ) < 0) {
		perror("getpeername 2");
	} else {
		printf("getpeername 2: %s.%d\n", inet_ntoa(remote.sin_addr),
				ntohs(remote.sin_port));
	}

	/*
	 * UNCONNECT
	 */
	set.sin_family = AF_INET;
	set.sin_port = htons(0);
	set.sin_addr.s_addr = htonl(0);

	if (connect(fd,(struct sockaddr *)&set, sizeof(set)) < 0) {
		perror("connect 2");
	}

	/*
	 * getpeername should fail.
	 */
	size = sizeof(remote);
	if (getpeername(fd,(struct sockaddr *)& remote, &size ) < 0) {
		perror("getpeername 3");
	} else {
		printf("getpeername 3: %s.%d\n", inet_ntoa(remote.sin_addr),
				ntohs(remote.sin_port));
	}

	echo.sin_family = AF_INET;
	echo.sin_port = htons(7);
	echo.sin_addr.s_addr = inet_addr("127.0.0.1");

	if (sendto(fd, "Message 2", 9, 0,(struct sockaddr *) &echo, sizeof(echo)) < 0) {
		perror("sendto 1:");
	}

	size = 0;
	if ((count = recvfrom(fd, buf, 100, 0, (struct sockaddr *)0, &size)) < 0) {
		perror("recvfrom 2");
	} else {
		printf("Got back %0.*s\n", count, buf);
	}
}