Linux RedHat 6.x bug: IPv4/UDP bind() allocates same port number by default

Nicolas DE METZ-NOBLAT (nmn@pspc7811.cern.ch)
Fri, 12 Nov 1999 20:08:22 +0100


[1.] IPv4/UDP bind() allocates same port number by default.

[2.] Full description of the problem/report:

When dynamically binding a new UDP socket to a port, the bind()
system usually returns the same value, and this confuses remote
UDP servers for a few minutes timeouts.

The reason is that the next eligible value used is the last
allocated value (if freed) and not the next one.

Urgency: HIGH because may affect portability and interoperbility
of applications using UDP protocol.

May need to be applied to older kernel versions.

[3.] Keywords: networking, ip, udp, bind :

[4.] Kernel version (from /proc/version):
Linux version 2.2.12-20 (root@porky.devel.redhat.com)
(gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release))
#1 Mon Sep 27 10:40:35 EDT 1999

But apparently still present in kernel 2.3.27 looking at the source
even if routine name changed in file linux/net/ipv4/udp.c

[5.] No OOPS message

[6.] Example:

------------------ begin example.c ------------------------

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

struct sockaddr_in sin_from;
struct sockaddr_in sin_read;

void test_socket(void)
{
int s;
int p;
int l;

if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
exit(2);
}

memset((char*)&sin_from, '\0', sizeof(sin_from));
sin_from.sin_family = AF_INET;
sin_from.sin_addr.s_addr = htonl(INADDR_ANY);
sin_from.sin_port = 0;
if (bind(s, (struct sockaddr *)&sin_from, sizeof(sin_from)) < 0) {
perror("bind");
exit(2);
}

l = sizeof(sin_read);
if (getsockname(s, &sin_read, &l) < 0) {
perror("getsockname");
exit(2);
}

p = ntohs(sin_read.sin_port);
printf("Allocated port number = %d\n", p);

close(s);
return;
}
main(int argc, char **argv)
{

test_socket();
test_socket();
}
------------------ end example.c ------------------------

Output on Linux RedHat 6.1:
Allocated port number = 1116
Allocated port number = 1116

Output on Solaris 2.6:
Allocated port number = 44798
Allocated port number = 44799

Output on AIX 4.2.1:
Allocated port number = 1151
Allocated port number = 1152

Output on LynxOS 2.5.1 (BSD 4.4 networking):
Allocated port number = 3002
Allocated port number = 3003

Only Linux reports twice the same value and this explains other
problems when using UDP protocol, like confused remote servers:
I have some programs that run once without any problem, but if
restarted without waiting for at least 2 minutes, the remote
server just refuse the connection, because the port number and
all other informations are identical to the previous connection.

[7.] Environment
This is just RedHat 6.1 standard distribution
(+ AFS 3.5 patch 2 from Transarc, but this is not relevant).

[7.1.] Software (add the output of the ver_linux script here)

-- Versions installed: (if some fields are empty or look
-- unusual then possibly you have very old versions)
Linux pspc7811 2.2.12-20 #1 Mon Sep 27 10:40:35 EDT 1999 i686 unknown
Kernel modules 2.1.121
Gnu C egcs-2.91.66
Binutils 2.9.1.0.24
Linux C Library 2.1.2
Dynamic linker ldd (GNU libc) 2.1.2
Procps 2.0.4
Mount 2.9u
Net-tools 1.53
Console-tools 1999.03.02
Sh-utils 2.0
Sh-utils Parker.
Sh-utils
Sh-utils Inc.
Sh-utils NO
Sh-utils PURPOSE.
Modules Loaded nfs lockd sunrpc autofs libafs-2.2.10 eepro100
nls_iso8859-1 nls_cp437 vfat fat opl3 sb uart401
sound soundlow soundcore

[7.2.] Processor information (from /proc/cpuinfo):

processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 5
model name : Pentium II (Deschutes)
stepping : 2
cpu MHz : 300.688613
cache size : 512 KB
fdiv_bug : no
hlt_bug : no
sep_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 2
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 sep mtrr pge mca cmov
pat pse36 mmx osfxsr
bogomips : 299.83

[7.3.] Module information (from /proc/modules):

nfs 29656 2 (autoclean)
lockd 30984 0 (autoclean) [nfs]
sunrpc 52516 1 (autoclean) [nfs lockd]
autofs 8964 3 (autoclean)
libafs-2.2.10 353060 1
eepro100 12112 1 (autoclean)
nls_iso8859-1 2020 1 (autoclean)
nls_cp437 3548 1 (autoclean)
vfat 9180 1 (autoclean)
fat 30464 1 (autoclean) [vfat]
opl3 11208 0 (unused)
sb 33620 0
uart401 5968 0 [sb]
sound 57240 0 [opl3 sb uart401]
soundlow 300 0 [sound]
soundcore 2372 6 [sb sound]

[7.4.] SCSI information (from /proc/scsi/scsi)

none

[X.] Other notes, patches, fixes, workarounds:

For kernel 2.2.12 in file /usr/src/linux/net/ipv4/udp.c, after line
171, in routine udp_v4_get_port(), a line
udp_port_rover++;
should be added once assigned a new value.

For kernel 2.3.27, this applies after line 173.

For kernel 2.2.5, the change is in routine udp_good_socknum()
after line 225, add the line:
start++;

Nicolas

--
Nicolas de METZ-NOBLAT   Phone: +41 22 76 72023 (direct)
CERN - PS division              +41 79 201 3070
CH-1211 Geneva 23        Fax:   +41 22 76 79145
Switzerland              mailto:Nicolas.de.Metz-Noblat@cern.ch

- 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/