[bug?] udp send to loopback and accept() dropping non-blocking status

Lucian B Landry (blandry@abby.arlut.utexas.edu)
Wed, 6 Oct 1999 12:51:39 -0500


Howdy, first time poster so please don't flame me too hard....

While porting to linux I've run across .. err .. 'anomalies' in some of the
socket behavior.

1) When I try to send udp packets to the loopback address, every third(!?)
port returns an "connection refused" error.

2) The latest man page I could find for accept() (23 oct 98) states

"The accept function extracts the first connection request on the queue
of pending connections, creates a new socket *with the same properties of s*,
and allocates a new file descriptor for the socket"

... however even if the listen socket has been set to non-blocking, the socket
returned by accept() blocks. (yes the workaround is obvious)

I apologize in advance if these are known problems, glibc bugs, or expected
behavior; I've searched many places for info regarding this and have so far
seen only mention of some 'accept() bug' on blackdown's (java/linux) homepage.
These programs run as expected on Solaris 5.6 and SCO 5.0.4. I would
appreciate any pointers to a more appropriate forum or an explanation of what
I'm doing wrong. Of course I would like (non)confirmations as well..

These programs were tested under rh 6.0 (running 2.2.12 and the stock
2.2.5) and debian (running 2.0.36). I tried 2.3.19 briefly, w/ same results
for 1); 2) gave me EINVAL for accept() on the receive side and the connection
was never established. Perhaps I screwed up my configuration somehow.

Responders please cc: me.

Thanks for your time
Buck

/* udps.c -- demonstrate supposed udp over loopback 'bug' */

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

#define MYPORTLOW 10000
#define MYPORTHIGH 10015

int main(void)
{
int sd, i, res;
char msg[20] = "hi there!\n";
struct sockaddr_in addr;

if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
perror("socket");

memset((void *) &addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

for (i = MYPORTLOW; i< MYPORTHIGH; i++)
{
fprintf(stderr, "sending to %d\n", i);
addr.sin_port = ntohs(i);
if ((res = sendto(sd, msg, strlen(msg) + 1, /* send \0 */
0, (struct sockaddr *) &addr,
sizeof(struct sockaddr_in))) < 0)
{
fprintf(stderr, "(res was %d) ", res);
perror("sendto");
}
}
return 0;
}

/* tcpr.c -- demonstrate supposed tcp accept() 'bug' */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

#define MYPORT 10012

int main(void)
{
int sd, newsock, res;
char msg[20] = "ackackack";
struct sockaddr_in addr, src_addr;
int src_addr_size;

if ((sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
perror("socket");

memset((void *) &addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = ntohs(MYPORT);

/* set to nonblock */
if ((res = fcntl (sd, F_SETFL, O_NONBLOCK)) < 0)
perror("fcntl");

/* bind */
if ((res = bind(sd, (struct sockaddr *) &addr,
sizeof(struct sockaddr_in))) < 0)
perror("bind");

/* listen */
if ((res = listen(sd, 5) < 0))
perror("listen");

/* accept */
while ((newsock = accept(sd, (struct sockaddr *) &src_addr,
&src_addr_size)) < 0)
{
if (errno == EWOULDBLOCK)
{
fprintf(stderr, "no connex accepted.\n");
sleep(1);
}
else
perror("accept");
}

#if 0
if ((res = fcntl (newsock, F_SETFL, O_NONBLOCK)) < 0)
perror("fcntl");
#endif

/* ok we opened a connection. Listen for a message. */
while ((res = recv(newsock, msg, 20, 0)) < 0)
{
if (errno == EWOULDBLOCK)
{
fprintf(stderr, "no message available.\n");
sleep(1);
}
else
perror("recv");
}
printf("message received: %s", msg);

return 0;
}

/* tcps.c -- run this once you have tcpr fired up to make a connex */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

#define MYPORT 10012

int main(void)
{
int sd, res;
char msg[20] = "hi there!";
struct sockaddr_in addr;

if ((sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
perror("socket");

memset((void *) &addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = ntohs(MYPORT);

/* connect */
if ((res = connect(sd, (struct sockaddr *) &addr,
sizeof(struct sockaddr_in))) < 0)
perror("connect");

sleep(10);

/* send message. */
if ((res = send(sd, msg, strlen(msg) + 1, 0)) < 0) /* send \0 */
perror("sendto");

return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/