Noros
Noros

Reputation: 105

local IP after gethostbyname()

How do I get the local IP address before using sendto() that is going to be used for the transmission to a remote host?

If I understand correctly, it should be known already after gethostbyname(remoteHostname) call.

I need this for including the local IP in the transmitted packet (127.0.0.1 wouldn't make sense). UDP is used.

Upvotes: 1

Views: 2684

Answers (3)

nos
nos

Reputation: 229284

You can call connect() on the socket first. UDP ofcourse is not connection oriented, but connect will just register the socket to only send to the given remote IP address, so you can e.g. just use send() instead of sendto()

However, this allows you to call getsockname() on the socket, and at least under Linux this will fetch the local address the socket uses. Here's an example, you can extract the info in the print_local_addr() here and use that info in your SNMP trap. (the bind() call is only needed if you want a fixed source port too)

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>


void diep(char *s)
{
  perror(s);
  exit(1);
}

void print_local_addr(int s)
{
    struct sockaddr_in my_addr;
    socklen_t len = sizeof my_addr;
    if(getsockname(s,(struct sockaddr*)&my_addr,&len) == -1)
      diep("getsockname");
    //print the local address of the socket that will be used when
    //sending datagrams to the "connected" peer.
    printf("local addr %s:%u\n",inet_ntoa(my_addr.sin_addr),ntohs(my_addr.sin_port));
}

int main(void)
{
  struct sockaddr_in si_me, si_other;
  int s;

  if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
    diep("socket");

  memset(&si_me, 0, sizeof(si_me));
  memset(&si_other, 0, sizeof(si_me));
  //bind to local port 4567
  si_me.sin_family = AF_INET;
  si_me.sin_port = htons(4567);
  si_me.sin_addr.s_addr = htonl(INADDR_ANY);

  //"connect" google's DNS server at 8.8.8.8 , port 4567
  si_other.sin_family = AF_INET;
  si_other.sin_port = htons(4567);
  si_other.sin_addr.s_addr = inet_addr("8.8.8.8");
  if(connect(s,(struct sockaddr*)&si_other,sizeof si_other) == -1)
    diep("connect");
  print_local_addr(s);
  close(s);
  return 0;
}

Upvotes: 1

Merlyn Morgan-Graham
Merlyn Morgan-Graham

Reputation: 59151

Info grabbed from: http://www.suite101.com/content/socket-programming-gethostbyname-a19557

As you said, localhost doesn't work. Instead, look up your hostname first, and pass that to gethostbyname.

char hostName[255];
gethostname(hostName, 255);

struct hostent* host_entry;
host_entry=gethostbyname(hostName);

char* localIP;
szLocalIP = inet_ntoa (*(struct in_addr*)*host_entry->h_addr_list);

Should this not be suitable, you can also do a DNS lookup, do a WMI query, or look it up in the registry.

Upvotes: 0

sarnold
sarnold

Reputation: 104090

Try calling getsockname(2) on a connected UDP socket; the stack would need to perform a fair amount of routing to connect the socket, sufficient to know which local address would be used once packets are sent or received.

Upvotes: 2

Related Questions