lkml.org 
[lkml]   [2006]   [Feb]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Subject[IPv6 since 2.6.12] connect() without bind() can't time out.
From
Date
Hello.

I think timer check for TCP's "connect() without bind()" for IPv6
doesn't work when no local port is available.

I can run the following program for 2.4.30, 2.4.31, 2.4.32 and 2.6.11.
But I can't run it for 2.6.12 and later (including 2.6.16-rc2).

The stream socket enters to SYN_SENT state. But when there is no free
port in the range defined by /proc/sys/net/ipv4/ip_local_port_range,
the connect() call sleeps forever; even after some ports became free.

Other operations such as TCP's "bind() with port = 0",
UDP's "bind() with port = 0", UDP's "connect() without bind()",
UDP's "sendto() without bind()" return immediately
when no free port is available.

---- Start of code. -----
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

static void Test(unsigned short int port) {
int i = 0;
for (i = 0; ; i++) {
const int fd = socket(AF_INET6, SOCK_STREAM, 0);
struct sockaddr_in6 addr;
socklen_t size = sizeof(addr);
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_loopback;
addr.sin6_port = htons(port);
printf("i=%d\n", i); fflush(stdout);
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr))) break;
if (getsockname(fd, (struct sockaddr *) &addr, &size)) {
printf("getsockname() failed.\n"); break;
}
}
printf("IPv6/TCP connect port exhausted at %d\n", i); fflush(stdout);
}

int main(int argc, char *argv[]) {
FILE *fp = fopen("/proc/sys/net/ipv4/ip_local_port_range", "r");
int original_range[2], narrow_range[2] = { 32768, 32768 + 100 };
if (!fp || fscanf(fp, "%u %u", &original_range[0], &original_range[1]) != 2) {
fprintf(stderr, "Can't open /proc/sys/net/ipv4/ip_local_port_range .\n");
exit(1);
}
fclose(fp);
if ((fp = fopen("/proc/sys/net/ipv4/ip_local_port_range", "w")) == NULL) {
fprintf(stderr, "Can't open /proc/sys/net/ipv4/ip_local_port_range .\n");
exit(1);
}
fprintf(fp, "%d %d\n", narrow_range[0], narrow_range[1]);
fclose(fp);
{
struct sockaddr_in6 addr;
socklen_t size = sizeof(addr);
pid_t pid;
const int listener = socket(AF_INET6, SOCK_STREAM, 0);
unsigned short int port;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = htons(0);
bind(listener, (struct sockaddr *) &addr, sizeof(addr));
getsockname(listener, (struct sockaddr *) &addr, &size);
port = ntohs(addr.sin6_port);
listen(listener, 512);
if ((pid = fork()) == 0) {
while (1) {
size_t size = sizeof(addr);
const int fd = accept(listener, (struct sockaddr *) &addr, &size);
fprintf(stderr, "accept=%d\n", fd);
}
}
close(listener);
Test(port);
kill(pid, SIGHUP);
}
if ((fp = fopen("/proc/sys/net/ipv4/ip_local_port_range", "w")) == NULL) {
fprintf(stderr, "Can't open /proc/sys/net/ipv4/ip_local_port_range .\n");
exit(1);
}
fprintf(fp, "%d %d\n", original_range[0], original_range[1]);
fclose(fp);
printf("Done.\n");
return 0;
}
---- End of code. -----

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

\
 
 \ /
  Last update: 2006-02-10 12:48    [W:0.052 / U:0.612 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site