From owner-freebsd-current@FreeBSD.ORG Mon Jun 7 19:02:43 2004 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 640FF16A4CE for ; Mon, 7 Jun 2004 19:02:43 +0000 (GMT) Received: from relay.macomnet.ru (relay.macomnet.ru [195.128.64.10]) by mx1.FreeBSD.org (Postfix) with ESMTP id 6961343D31 for ; Mon, 7 Jun 2004 19:02:42 +0000 (GMT) (envelope-from maxim@macomnet.ru) Received: from mp3 (d0snjwf1@mp3files.int.ru [195.128.64.20]) by relay.macomnet.ru (8.12.10/8.12.10) with ESMTP id i57J2eu515856000; Mon, 7 Jun 2004 23:02:40 +0400 (MSD) Date: Mon, 7 Jun 2004 23:02:40 +0400 (MSD) From: Maxim Konovalov To: Gleb Smirnoff In-Reply-To: <20040530100739.GA58477@cell.sick.ru> Message-ID: <20040607224538.L2382@mp3files.int.ru> References: <20040530100739.GA58477@cell.sick.ru> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII cc: freebsd-current@freebsd.org Subject: Re: incorrect connect() behavior X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Jun 2004 19:02:43 -0000 [ Change CC: in hope to reach a wide audience. ] On Sun, 30 May 2004, 14:07+0400, Gleb Smirnoff wrote: > Dear networkers, > > there is a problem in connect() syscall, which can be reproduced > on a box running without default route. > > According to POSIX, connect() must return if ENETUNREACH, if a route to > destination was not found. > > http://www.opengroup.org/onlinepubs/000095399/functions/connect.html > > In case of SOCK_STREAM it works this way. But in case of Yep, the absence of the route is discovered in ip_output() and EHOSTUNREACH returned. > SOCK_DGRAM connect() does not return error. And it picks up first > available local IP address for local side of socket. In some cases > this address may appear to be 127.0.0.1. Later, when a route to > destination shows up, datagrams will fail to send, since 127.0.0.1 > can not appear on wire. > > Affected installations are: > - BGP routers without default route > - localnet routers running some IGP > > Affected applications are: > > - ntpd. ntpd starts before routing daemon have established all > adjacencies, connect() binds to 127.0.0.1. Later when routing show > up, ntpd fails to send dgrams to server. > - net-snmpd. It is difficult to reproduce, but after some route > flapping snmpd hangs, and does not respond to requests. This can > be workarounded with a static route to source of queries. > - ng_ksocket. If node is of type inet/dgram/udp and a connect > message is sent to it, it does not return an error. Later it fails > to send packets withEPERM. > > Here is attached a test case for this problem no-route-test.c. To > test, one needs to delete default route, compile no-route-test and > run it. If connect() picks up non-localhost address, then you are > lucky :), some of your interfaces was ifconfiged before lo0. To > reproduce problem with 100 % guarantee, one needs to have lo0 first > one in list ${network_interfaces} var in /etc/rc.conf. Then you > should add default route, and look into what is typed by > no-route-test, which was started before this route was added. Someone can use udpcliserv/udpcli09.c from UNPv1 as well. > I have written two patches to deal with this problem. The first one > clings to POSIX behavior - it returns ENETUNREACH. I have tested > ntpd with it - it works well. But there is no guarantee that > anything else would be broken. The second patch is a POLA-patch, it > makes connect() to take first non-localhost address for local side > of socket. Code was obtained directly from NetBSD. This patch is > considered not to break anything. Both patches are attached. I prefer the former: return ENETUNREACH as soon as we detect we do not have a route to the net. Btw, Solaris 8 and Linux 2.4.x work this way. Discuss the issue with NetBSD people is a good idea too. %%% Index: in_pcb.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.147 diff -u -r1.147 in_pcb.c --- in_pcb.c 20 May 2004 06:35:02 -0000 1.147 +++ in_pcb.c 29 May 2004 21:12:40 -0000 @@ -612,9 +612,7 @@ if (ia == 0) ia = ifatoia(ifa_ifwithnet(sintosa(&sa))); if (ia == 0) - ia = TAILQ_FIRST(&in_ifaddrhead); - if (ia == 0) - return (EADDRNOTAVAIL); + return (ENETUNREACH); } /* * If the destination address is multicast and an outgoing %%% Any comments? -- Maxim Konovalov