Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Dec 2003 15:59:48 +0300
From:      Gleb Smirnoff <glebius@cell.sick.ru>
To:        freebsd-net@freebsd.org
Subject:   incorrect connect() behavior
Message-ID:  <20031211125948.GN37784@cell.sick.ru>

next in thread | raw e-mail | index | archive | help

--yrj/dFKFPuw6o+aM
Content-Type: text/plain; charset=koi8-r
Content-Disposition: inline

  Dear sirs,

as it is described in connect(2):

ERRORS
     The connect() call fails if:
     ...
     [ENETUNREACH]      The network is not reachable from this host.

     [EHOSTUNREACH]     The remote host is not reachable from this host.


However, this sample program (attached) shows that connect() does not
return -1 in case of absence of routing do destination.(One should run
test program after "route delete default")

Testing FreeBSD-STABLE showed that connect() will return 0, and following
getsockname() on same sockaddr will return 127.0.0.1 as source address.
What does this break?  ntpd(8) will not work after temporary route flapping,
or in case when ntpd(8) starts before time servers are reachable. Same
problem with ports/net/net-snmp, it freezes after route flapping. In latter
case I haven't looked into sources, but I suppose the problem is similar
to ntpd's.

Testing FreeBSD 5.1-RELEASE showed that connect() will return 0, and
following getsockname() on same sockaddr will return same address,
as would be returned in presence of default route. Haven't tested
on multihomed 5.x boxes.

-- 
Totus tuus, Glebius.
GLEBIUS-RIPN GLEB-RIPE

--yrj/dFKFPuw6o+aM
Content-Type: text/plain; charset=koi8-r
Content-Disposition: attachment; filename="no-route-test.c"

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

#define	SOMEHOST	"209.132.205.227"

int main() {
  int s, rtn;
  struct sockaddr_in saddr;
  int saddrlen = sizeof(saddr);
  

  saddr.sin_family = AF_INET;
  saddr.sin_addr.s_addr = inet_addr(SOMEHOST);
  saddr.sin_port = htons(2000);

  s = socket(AF_INET, SOCK_DGRAM, 0);
  if (s < 0) {
	printf("Error from socket()\n");
	return -1;
  }

  rtn = connect(s, (struct sockaddr *)&saddr, sizeof(saddr));
  if (rtn < 0) {
	printf("Error from connect(): %s\n", strerror(errno));
	return -1;
  }

  rtn = getsockname(s, (struct sockaddr *)&saddr, &saddrlen);
  if (rtn < 0) {
	printf("Error from getsockname()\n");
	return -1;
  }
  close(s);
  printf("Addr is %s\n", inet_ntoa(saddr.sin_addr));
}

--yrj/dFKFPuw6o+aM--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031211125948.GN37784>