Date: Sun, 16 Feb 2003 00:32:52 +0200 From: Giorgos Keramidas <keramida@ceid.upatras.gr> To: freebsd-current@freebsd.org Subject: UDP connect() behavior in 5.0-CURRENT Message-ID: <20030215223252.GA17712@gothmog.gr>
next in thread | raw e-mail | index | archive | help
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 <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <err.h> #include <errno.h> #include <stdio.h> #include <strings.h> #include <unistd.h> #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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030215223252.GA17712>