On Sun, 4 Jun 2006 23:58:19 -0700
[EMAIL PROTECTED] wrote:

> http://bugzilla.kernel.org/show_bug.cgi?id=6646
> 
>            Summary: UDP socket doesn't return to bound state after
>                     association is dissolved by connect(..AF_UNSPEC)
>     Kernel Version: 2.6.12
>             Status: NEW
>           Severity: high
>              Owner: [EMAIL PROTECTED]
>          Submitter: [EMAIL PROTECTED]
> 
> 
> Most recent kernel where this bug did not occur:
> Distribution:
> Hardware Environment:
> Software Environment:
> Problem Description:
> When disconnect a UDP socket, Linux kernel set local port to zero if the port
> number comes from a implicit bind. Linux connect(2) man page reads:
> "Generally, connection-based protocol sockets may successfully *connect* only
> once; connectionless protocol sockets may use *connect* multiple times to 
> change
> their association. Connectionless sockets may dissolve the association by
> connecting to an address with the /sa_family/ member of *sockaddr* set to
> *AF_UNSPEC*."
> But dissolve the association should not impact the local binding, while
> currently it does. In contrast, Unix variants like Solaris don't alter local
> binding when disconnecting a UDP socket. 
> 
> Steps to reproduce:
> Compile attached c file, and run it. You'll see local port number changed 
> after
> a UDP socket disconnected.
> 
> #include <errno.h>
> #include <string.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <net/if.h>
> #include <netdb.h>
> #include <arpa/inet.h>
> #include <stdio.h>
> #include <stdlib.h>
> 
> #define SERV_PORT 12345
> 
> void print_local_addr(int s);
> 
> int main(int argc, char** argv)
> {
>     int sockfd;
>     struct sockaddr_in servaddr, cliaddr;
> 
>     if (argc != 2) {
>         printf("Usage: disconnect_udp <ipaddress>");
>         exit(0);
>     }
>     
>     // creat a UDP socket which binds to a local address
>     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
>     bzero(&cliaddr, sizeof(cliaddr));
>     cliaddr.sin_family = AF_INET;
>     if (inet_pton(AF_INET, argv[1], &cliaddr.sin_addr) != 1) {
>         perror("inet_pton failed");
>     }
>     bind(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
>     
>     // connect this UDP socket
>     bzero(&servaddr, sizeof(servaddr));
>     servaddr.sin_family = AF_INET;
>     servaddr.sin_port = htons(SERV_PORT);
>     if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) != 1) {
>         perror("inet_pton failed");
>     }
>     if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) 
> {
>         perror("connect failed");
>     }
>     print_local_addr(sockfd);
>     
>     // disconnect it
>     servaddr.sin_family = AF_UNSPEC;
>     if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) 
> {
>         perror("connect failed");
>     }
>     print_local_addr(sockfd);
>     
>     close(sockfd);
> }
> 
> void print_local_addr(int s)
> {
>     struct sockaddr_in localaddr;
>     socklen_t len = 0;
>     char temp[INET_ADDRSTRLEN];
>     
>     len = sizeof(localaddr);
>     if (getsockname(s, (struct sockaddr *)&localaddr, &len) != 0) {
>         perror("getsockname failed");
>     }
>     
>     inet_ntop(AF_INET, &localaddr.sin_addr, temp, INET_ADDRSTRLEN);
>     printf("Local binding: address=%s, port=%d\n",
>            temp, ntohs(localaddr.sin_port));
> }
> 
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug, or are watching someone who is.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to