Re: UDP connect: Can't assign requested address or "how todetermine the outgoing IP address?"

From: Lev Walkin (vlm_at_netli.com)
Date: 10/23/03

  • Next message: Edwin Groothuis: "Re: UDP connect: Can't assign requested address or "how to determine the outgoing IP address?""
    Date: Wed, 22 Oct 2003 19:53:10 -0700
    To: Edwin Groothuis <edwin@mavetju.org>
    
    

    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 <sys/types.h>
    > #include <sys/socket.h>
    > #include <netinet/in.h>
    > #include <errno.h>
    > #include <netdb.h>
    > #include <string.h>
    > #include <stdio.h>
    > #include <unistd.h>
    > #include <stdlib.h>
    >
    > 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
    _______________________________________________
    freebsd-net@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-net
    To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org"
    

  • Next message: Edwin Groothuis: "Re: UDP connect: Can't assign requested address or "how to determine the outgoing IP address?""