From owner-freebsd-net@FreeBSD.ORG Wed Oct 22 19:31:52 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 A240516A4B3 for ; Wed, 22 Oct 2003 19:31:52 -0700 (PDT) Received: from mag.barnet.com.au (mag.barnet.com.au [218.185.88.3]) by mx1.FreeBSD.org (Postfix) with ESMTP id 6F20F43F3F for ; Wed, 22 Oct 2003 19:31:51 -0700 (PDT) (envelope-from edwin@mavetju.org) Received: from extmail.barnet.com.au (tim.direct.int.barnet.com.au [10.10.10.2]) by mag.barnet.com.au (Postfix) with ESMTP id 0824720E1 for ; Thu, 23 Oct 2003 12:31:49 +1000 (EST) X-Viruscan-Id: <3F973D9400010EB501A1AE6B@VIRUSCAN-127.0.0.1> Received: from extmail-auth.barnet.com.au (localhost [127.0.0.1]) by extmail.barnet.com.au (Postfix) with ESMTP id 983EA1F1E for ; Thu, 23 Oct 2003 12:31:48 +1000 (EST) Received: from k7.mavetju (p61-max1.syd.ihug.com.au [203.173.155.61]) by extmail-auth.barnet.com.au (Postfix) with ESMTP id 865531F1A for ; Thu, 23 Oct 2003 12:31:47 +1000 (EST) Received: by k7.mavetju (Postfix, from userid 1001) id 293FF6A7101; Thu, 23 Oct 2003 12:31:46 +1000 (EST) Date: Thu, 23 Oct 2003 12:31:46 +1000 From: Edwin Groothuis To: freebsd-net@freebsd.org Message-ID: <20031023023146.GA34131@k7.mavetju> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="gBBFr7Ir9EOA20Yy" Content-Disposition: inline User-Agent: Mutt/1.4.1i Subject: UDP connect: Can't assign requested address or "how to determine 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:31:52 -0000 --gBBFr7Ir9EOA20Yy Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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? Edwin attached code can be compiled with "gcc -Wall -g -o a a.c && ./a" -- Edwin Groothuis | Personal website: http://www.mavetju.org edwin@mavetju.org | Weblog: http://www.mavetju.org/weblog/weblog.php --gBBFr7Ir9EOA20Yy Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="a.c" #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; } 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; } --gBBFr7Ir9EOA20Yy--