From owner-freebsd-current Sat Feb 15 14:58: 8 2003 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 5CFAB37B401 for ; Sat, 15 Feb 2003 14:58:05 -0800 (PST) Received: from mailsrv.otenet.gr (mailsrv.otenet.gr [195.170.0.5]) by mx1.FreeBSD.org (Postfix) with ESMTP id E3DB743FBD for ; Sat, 15 Feb 2003 14:58:01 -0800 (PST) (envelope-from keramida@ceid.upatras.gr) Received: from gothmog.gr (patr530-a019.otenet.gr [212.205.215.19]) by mailsrv.otenet.gr (8.12.6/8.12.6) with ESMTP id h1FMvvSe016604 for ; Sun, 16 Feb 2003 00:57:59 +0200 (EET) Received: from gothmog.gr (gothmog [127.0.0.1]) by gothmog.gr (8.12.7/8.12.7) with ESMTP id h1FMvrBC001276 for ; Sun, 16 Feb 2003 00:57:53 +0200 (EET) (envelope-from keramida@ceid.upatras.gr) Received: (from giorgos@localhost) by gothmog.gr (8.12.7/8.12.7/Submit) id h1FMWq2t029123 for freebsd-current@freebsd.org; Sun, 16 Feb 2003 00:32:52 +0200 (EET) (envelope-from keramida@ceid.upatras.gr) Date: Sun, 16 Feb 2003 00:32:52 +0200 From: Giorgos Keramidas To: freebsd-current@freebsd.org Subject: UDP connect() behavior in 5.0-CURRENT Message-ID: <20030215223252.GA17712@gothmog.gr> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG The second volume of ``TCP/IP Illustrated'' by Stevens says that already connected UDP sockets return EISCONN on any following connect() attempts. Exercise 23.8 of the same book mentions that an interesting exception are connect() calls to address 0.0.0.0, which still return an EISCONN error, but also have the side-effect of leaving the socket disassociated from a UDP pcb, allowing subsequent connect() attempts to work. Trying to reproduce the EISCONN error by running the attached program, I couldn't. It seems that connect() returns ECONNREFUSED when it is run on already connected sockets. If you run the program as it is shown below, it works fine, connecting to localhost:53 and then exiting. If you undef the #if 0 ... #endif part, it should fail with EISCONN, but it fails with ECONNREFUSED instead :-( ===== conn.c ===== #include #include #include #include #include #include #include #include #include #define MY_PROTO "udp" int main(void) { struct sockaddr_in addr; struct protoent *pe; struct servent *se; int sd; /* * Create a UDP socket. */ pe = getprotobyname(MY_PROTO); if (pe == NULL) errx(1, "getprotobyname(%s): unknown protocol", MY_PROTO); if ((sd = socket(PF_INET, SOCK_DGRAM, pe->p_proto)) == -1) err(1, "socket"); /* * When the ifdef'ed part below is uncommented, the error of the * second connect() attempt is not EISCONN, but ECONNREFUSED, which * is wrong. */ #if 0 /* * First, connect to the UDP discard service of localhost and send at * least one packet to it. */ printf("-!- Connecting to localhost:discard/%s\n", MY_PROTO); fflush(stdout); se = getservbyname("discard", MY_PROTO); if (se == NULL) errx(1, "getservbyname[discard/%s]: unknown service", MY_PROTO); bzero((char *)&addr, sizeof(struct sockaddr_in)); addr.sin_family = PF_INET; addr.sin_addr.s_addr = htonl(0x7f000001); /* localhost */ addr.sin_port = htons(se->s_port); if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) err(1, "connect[%s/%s]", se->s_name, pe->p_name); printf("-!- Sending some stuff to localhost:%s/%s\n", se->s_name, pe->p_name); fflush(stdout); if (write(sd, (char *)&addr, sizeof(addr)) == -1) err(1, "write/%s", se->s_name); #endif /* * Now attempt to connect to localhost:domain (DNS). * This should fail on connect(). */ printf("-!- Connecting to localhost:domain/%s\n", pe->p_name); fflush(stdout); se = getservbyname("domain", MY_PROTO); if (se == NULL) errx(1, "getservbyname[domain/%s]: unknown service", pe->p_name); bzero((char *)&addr, sizeof(struct sockaddr_in)); addr.sin_family = PF_INET; addr.sin_addr.s_addr = htonl(0x7f000001); /* localhost */ addr.sin_port = htons(se->s_port); if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) err(1, "connect[%s/%s]: error %d:", se->s_name, pe->p_name, errno); close(sd); return (0); } ===== end of conn.c ===== To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message