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 [EMAIL PROTECTED] with "unsubscribe freebsd-current" in the body of the message