From owner-freebsd-net@FreeBSD.ORG Wed Oct 22 19:52:10 2003 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1ADB016A4B3 for ; Wed, 22 Oct 2003 19:52:10 -0700 (PDT) Received: from smtp.netli.com (ip2-pal-focal.netli.com [66.243.52.2]) by mx1.FreeBSD.org (Postfix) with ESMTP id 12F7B43F93 for ; Wed, 22 Oct 2003 19:52:09 -0700 (PDT) (envelope-from vlm@netli.com) Received: (qmail 18679 invoked by uid 84); 23 Oct 2003 02:52:08 -0000 Received: from vlm@netli.com by l3-1 with qmail-scanner-0.96 (uvscan: v4.1.40/v4121. . Clean. Processed in 0.160765 secs); 23 Oct 2003 02:52:08 -0000 Received: from unknown (HELO netli.com) (172.17.1.12) by mx01-pal-lan.netli.lan with SMTP; 23 Oct 2003 02:52:08 -0000 Message-ID: <3F974296.9040304@netli.com> Date: Wed, 22 Oct 2003 19:53:10 -0700 From: Lev Walkin Organization: Netli, Inc. User-Agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.5) Gecko/20031019 X-Accept-Language: ru, en-us, en MIME-Version: 1.0 To: Edwin Groothuis References: <20031023023146.GA34131@k7.mavetju> In-Reply-To: <20031023023146.GA34131@k7.mavetju> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit cc: freebsd-net@freebsd.org Subject: Re: UDP connect: Can't assign requested address or "how todetermine the outgoing IP address?" X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Oct 2003 02:52:10 -0000 Edwin Groothuis wrote: > Hello, > > I got a nice piece of code (see attachment) which could be used to > determine the outgoing IP address for an UDP socket. It works without > problem under Linux, but it fails on FreeBSD (-current and -stable) > during the call to connect() with the error: "Can't assign requested > address". The code looks like the udpcli09.c example in Richard > Stevens 'Unix Network Programming' book, which states it doesn't > work on SVR4 derived kernels. > > So, the question is, how can I determine the outgoing IP address > for a socket? Everything's fine apart from one thing: connect() does not like to connect to places with destination port equal to zero. > attached code can be compiled with "gcc -Wall -g -o a a.c && ./a" > > > > ------------------------------------------------------------------------ > > #include > #include > #include > #include > #include > #include > #include > #include > #include > > int guess_local_address(char *address_to_reach,char **loc); > > int main(void) { > char *loc; > > guess_local_address("218.185.88.1",&loc);printf("%s\n",loc); > guess_local_address("192.168.1.3",&loc);printf("%s\n",loc); > guess_local_address("127.0.0.1",&loc);printf("%s\n",loc); > return 0; > } > > int guess_local_address(char *address_to_reach,char **loc){ > int s,err; > struct addrinfo hints; > struct addrinfo *res=NULL; > struct sockaddr addr; > int sock; > > *loc=NULL; > > printf("Trying %s: ",address_to_reach); > > memset(&hints,0,sizeof(hints)); > hints.ai_family=PF_UNSPEC; > hints.ai_socktype=SOCK_DGRAM; > hints.ai_flags=AI_NUMERICHOST|AI_CANONNAME; > > err=getaddrinfo(address_to_reach,NULL,&hints,&res); > if (err<0){ > printf("getaddrinfo: %s\n",gai_strerror(err)); > return -1; > } > if (res==NULL){ > printf("getaddrinfo reported nothing !"); > return -1; > } > sock=socket(res->ai_family,SOCK_DGRAM,0); > if (err<0){ > printf("Error in socket: %s\n",strerror(errno)); > return -1; > } > { > struct sockaddr_in servaddr; > memset(&servaddr,sizeof(servaddr),0); > servaddr.sin_family=AF_INET; > servaddr.sin_addr.s_addr=htonl(INADDR_ANY); > servaddr.sin_port=htons(0); > err=bind(sock,(struct sockaddr *)&servaddr,sizeof(servaddr)); > if (err<0){ > printf("Error in bind: %s\n",strerror(errno)); > return -1; > } > } > s=1; > err=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&s,sizeof(int)); > if (err<0){ > printf("Error in setsockopt: %s\n",strerror(errno)); > return -1; > } /* * This will do. Note that it assumes AF_INET. */ ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(80); > err=connect(sock,res->ai_addr,res->ai_addrlen); > if (err<0) { > printf("Error in connect: %s\n",strerror(errno)); > return -1; > } > freeaddrinfo(res); > res=NULL; > s=sizeof(addr); > err=getsockname(sock,(struct sockaddr*)&addr,&s); > if (err<0) { > printf("Error in getsockname: %s\n",strerror(errno)); > return -1; > } > *loc=malloc(30); > err=getnameinfo(&addr,s,*loc,30,NULL,0,NI_NUMERICHOST); > if (err<0){ > printf("getnameinfo error:%s",strerror(errno)); > return -1; > } > close(sock); > return 0; > } > -- Lev Walkin vlm@netli.com