Date: Thu, 2 Sep 2004 06:07:48 GMT From: Dmitry Dvoinikov <dmitry@targeted.org> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/71274: Frequent bind()/connect()'s assign same local ports to different sockets Message-ID: <200409020607.i8267mld064901@www.freebsd.org> Resent-Message-ID: <200409020610.i826AKup007296@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 71274 >Category: kern >Synopsis: Frequent bind()/connect()'s assign same local ports to different sockets >Confidential: no >Severity: serious >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Sep 02 06:10:20 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Dmitry Dvoinikov >Release: 4.10-RELEASE >Organization: - >Environment: FreeBSD 4.10-RELEASE FreeBSD 4.10-RELEASE #0: Tue May 25 22:47:12 GMT 2004 root@perseus.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 >Description: 1. A program keeps looping forever creating TCP sockets and connecting them to some TCP server in a connect/send/recv/close fashion (sample uses HTTP server at localhost). 2. Each outgoing socket is assigned a local port number, either explicitly (with bind to zero port before connect) or implicitly (within connect). 3. After this program runs for a while, it happens that another port number assigned has just been used a few connects ago (and that used socket is probably not free, but is still alive in TIME_WAIT or some other near-terminal state). Therefore this second connect gets a port number which is not free, and therefore connect fails returning "Connection refused". 4. This is not a resource exhaustion problem, as netstat output shows only around a thousand sockets. 5. This is not a congestion problem, because the looping program is single-threaded and can't produce more than one connection at a time. >How-To-Repeat: Compile an run this program, having http server at localhost:80 (I used thttpd for it's lightweightness, but even http doesn't really matter of course, it's just any TCP server). Examine program's output for the following pattern: bound to 2664 bound to 1267 <<<<< REPEATS bound to 4646 bound to 3060 bound to 1374 bound to 4986 bound to 1267 <<<<< REPEATS connect failed: Connection refused ------------------------------------------------ base64 encoded sample: ------------------------------------------------ begin-base64 644 test.c I2luY2x1ZGUgPHN5cy90eXBlcy5oPgojaW5jbHVkZSA8c3lzL3NvY2tldC5oPgojaW5jbHVkZSA8 c3RkaW8uaD4KI2luY2x1ZGUgPHVuaXN0ZC5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRl IDxuZXRpbmV0L2luLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPGVycm5vLmg+CiNp bmNsdWRlIDxzeXMvcGFyYW0uaD4KCmNoYXIqIFJFUVVFU1QgPSAiR0VUIC8gSFRUUC8xLjBcclxu XHJcbiI7CgppbnQgbWFpbigpCnsKCiAgICAgICAgaW50IHMsIHVudXNlZDsKICAgICAgICBzdHJ1 Y3Qgc29ja2FkZHJfaW4gYTsKICAgICAgICBjaGFyIGJ1ZlsxMDI0XTsKCiAgICAgICAgbWVtc2V0 KCZhLCAwLCBzaXplb2Yoc3RydWN0IHNvY2thZGRyX2luKSk7CiAgICAgICAgYS5zaW5fbGVuID0g c2l6ZW9mKHN0cnVjdCBzb2NrYWRkcl9pbik7CiAgICAgICAgYS5zaW5fZmFtaWx5ID0gQUZfSU5F VDsKICAgICAgICBhLnNpbl9hZGRyLnNfYWRkciA9IGh0b25sKDB4N2YwMDAwMDEpOwoKICAgICAg ICB3aGlsZSAoMSkKICAgICAgICB7CgogICAgICAgICAgICAgICAgcyA9IHNvY2tldChQRl9JTkVU LCBTT0NLX1NUUkVBTSwgMCk7CgkJaWYgKHMgPT0gLTEpCgkJewoJCQlmcHJpbnRmKHN0ZG91dCwg InNvY2tldCBmYWlsZWQ6ICVzXG4iLCBzdHJlcnJvcihlcnJubykpOwoJCQljb250aW51ZTsKCQl9 CgogICAgICAgICAgICAgICAgYS5zaW5fcG9ydCA9IDA7CiAgICAgICAgICAgICAgICBpZiAoYmlu ZChzLCAoc3RydWN0IHNvY2thZGRyKikmYSwgc2l6ZW9mKHN0cnVjdCBzb2NrYWRkcl9pbikpID09 IC0xKQoJCXsKCQkJY2xvc2Uocyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZwcmludGYoc3Rk b3V0LCAiYmluZCBmYWlsZWQ6ICVzXG4iLCBzdHJlcnJvcihlcnJubykpOyAKICAgICAgICAgICAg ICAgICAgICAgICAgY29udGludWU7CgkJfQoKICAgICAgICAgICAgICAgIHVudXNlZCA9IHNpemVv ZihzdHJ1Y3Qgc29ja2FkZHJfaW4pOwogICAgICAgICAgICAgICAgaWYgKGdldHNvY2tuYW1lKHMs IChzdHJ1Y3Qgc29ja2FkZHIqKSZhLCAmdW51c2VkKSA9PSAtMSkKCQl7CiAgICAgICAgICAgICAg ICAgICAgICAgIGNsb3NlKHMpOwogICAgICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKHN0ZG91 dCwgImdldHNvY2tuYW1lIGZhaWxlZDogJXNcbiIsIHN0cmVycm9yKGVycm5vKSk7ICAgICAgICAg ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsgCgkJfQoKICAgICAg ICAgICAgICAgIGZwcmludGYoc3Rkb3V0LCAiYm91bmQgdG8gJWRcbiIsICh1bnNpZ25lZCBsb25n KW50b2hzKGEuc2luX3BvcnQpKTsKCiAgICAgICAgICAgICAgICBhLnNpbl9wb3J0ID0gaHRvbnMo ODApOwogICAgICAgICAgICAgICAgaWYgKGNvbm5lY3QocywgKHN0cnVjdCBzb2NrYWRkciopJmEs IHNpemVvZihzdHJ1Y3Qgc29ja2FkZHJfaW4pKSA9PSAtMSkKICAgICAgICAgICAgICAgIHsKICAg ICAgICAgICAgICAgICAgICAgICAgY2xvc2Uocyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZw cmludGYoc3Rkb3V0LCAiY29ubmVjdCBmYWlsZWQ6ICVzXG4iLCBzdHJlcnJvcihlcnJubykpOwog ICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgIH0KCiAgICAg ICAgICAgICAgICBzZW5kKHMsIFJFUVVFU1QsIHN0cmxlbihSRVFVRVNUKSwgMCk7CiAgICAgICAg ICAgICAgICB3aGlsZSAocmVjdihzLCBidWYsIHNpemVvZihidWYpLCAwKSA+IDApIHsgfQogICAg ICAgICAgICAgICAgY2xvc2Uocyk7CgogICAgICAgIH0KCn0KCg== ==== ------------------------------------------------ plain (broken ?) sample: ------------------------------------------------ #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <netinet/in.h> #include <string.h> #include <errno.h> #include <sys/param.h> char* REQUEST = "GET / HTTP/1.0\r\n\r\n"; int main() { int s, unused; struct sockaddr_in a; char buf[1024]; memset(&a, 0, sizeof(struct sockaddr_in)); a.sin_len = sizeof(struct sockaddr_in); a.sin_family = AF_INET; a.sin_addr.s_addr = htonl(0x7f000001); while (1) { s = socket(PF_INET, SOCK_STREAM, 0); if (s == -1) { fprintf(stdout, "socket failed: %s\n", strerror(errno)); continue; } a.sin_port = 0; if (bind(s, (struct sockaddr*)&a, sizeof(struct sockaddr_in)) == -1) { close(s); fprintf(stdout, "bind failed: %s\n", strerror(errno)); continue; } unused = sizeof(struct sockaddr_in); if (getsockname(s, (struct sockaddr*)&a, &unused) == -1) { close(s); fprintf(stdout, "getsockname failed: %s\n", strerror(errno)); continue; } fprintf(stdout, "bound to %d\n", (unsigned long)ntohs(a.sin_port)); a.sin_port = htons(80); if (connect(s, (struct sockaddr*)&a, sizeof(struct sockaddr_in)) == -1) { close(s); fprintf(stdout, "connect failed: %s\n", strerror(errno)); continue; } send(s, REQUEST, strlen(REQUEST), 0); while (recv(s, buf, sizeof(buf), 0) > 0) { } close(s); } } ------------------------------------------------ >Fix: >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200409020607.i8267mld064901>