Page 1 of 1

C: get local ip address

Posted: Tue Jun 14, 2005 3:52 pm
by Einherjar
έχω ένα socket που έχει γίνει bind στο ANY_ADDR. Αυτό το socket το χρησιμοποιώ για ανταλλαγή UTP μηνυμάτων. Αυτό που θέλω είναι να πάρω την τοπική IP address. Την πραγματική IP από την οποία στέλνω και όχι την 0.0.0.0. Όπως φαίνεται από τον τίτλο μιλάω για C (λειτουργικό σύστημα linux).

Ευχαριστώ εκ των πρωτέρων

Posted: Tue Jun 14, 2005 4:24 pm
by mikem4600
Για ένα project εγώ έκανα DNS lookup τον τοπικό υπολογιστή, και μου επέστρεφε (χωρίς φυσικά να ρωτήσει DNS server) όλες τις τοπικες διευθύνσεις (ο υπολογιστής που δούλευα είχε αρκετές), ή 127.0.0.1 αν τις είχα κάνει όλες disabled.

Posted: Tue Jun 14, 2005 4:37 pm
by AmmarkoV
Καλή ερώτηση..
Και εγώ αν και έχω ασχοληθεί με sockets (σε μηχάνημα Windows) δεν το έχω κάνει ποτέ..

Υπάρχει μια function getsockname , παίζει αυτό να κάνει..

Παραθέτω..

The Windows Sockets getsockname function gets the local name for a socket.
int getsockname ( SOCKET s, struct sockaddr FAR * name, int FAR * namelen);
Parameters
s A descriptor identifying a bound socket.

name Receives the address (name) of the socket.

namelen The size of the name buffer.

Return Value
If no error occurs, getsockname returns zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code may be retrieved by calling WSAGetLastError.

Error Codes
WSANOTINITIALISED A successful WSAStartup must occur before using this function.
WSAENETDOWN The Windows Sockets implementation has detected that the network subsystem has failed.
WSAEFAULT The namelen argument is not large enough.
WSAEINPROGRESS A blocking Windows Sockets operation is in progress.
WSAENOTSOCK The descriptor is not a socket.
WSAEINVAL The socket has not been bound to an address with bind.
Remarks

The getsockname function retrieves the current name for the specified socket descriptor in name. It is used on a bound or connected socket specified by the s parameter. The local association is returned. This call is especially useful when a connect call has been made without doing a bind first; this call provides the only means by which you can determine the local association set by the system.
On return, the namelen argument contains the actual size of the name returned in bytes.

If a socket was bound to INADDR_ANY, indicating that any of the host's IP addresses should be used for the socket, getsockname will not necessarily return information about the host IP address, unless the socket has been connected with connect or accept. A Windows Sockets application must not assume that the IP address will be changed from INADDR_ANY unless the socket is connected. This is because for a multi-homed host, the IP address that will be used for the socket is unknown unless the socket is connected.

Posted: Tue Jun 14, 2005 4:50 pm
by Einherjar
η getsockname μου επιστρέφει 0.0.0.0
mikem με ενδιαφέρει η μια που χρησιμοποιείται, όχι όλες οι δυνατές

Posted: Tue Jun 14, 2005 5:58 pm
by AmmarkoV
If a socket was bound to INADDR_ANY, indicating that any of the host's IP addresses should be used for the socket, getsockname will not necessarily return information about the host IP address, unless the socket has been connected with connect or accept. A Windows Sockets application must not assume that the IP address will be changed from INADDR_ANY unless the socket is connected. This is because for a multi-homed host, the IP address that will be used for the socket is unknown unless the socket is connected.
Έχεις κάνει connect ή accept όταν ζητάς την IP σου?

Posted: Tue Jun 14, 2005 8:42 pm
by HdkiLLeR
Έχω κώδικα που το κάνει αυτό στο παραθέτω και πάρε αυτό που θέλεις...

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <net/if.h>

#include <sys/ioctl.h>
#include <net/if_arp.h>
#include <arpa/inet.h>

#define inaddrr(x) (*(struct in_addr *) &ifr->x[sizeof sa.sin_port])
#define IFRSIZE   ((int)(size * sizeof (struct ifreq)))

int main(void)
{
  unsigned char      *u;
  int                sockfd, size  = 1;
  struct ifreq       *ifr;
  struct ifconf      ifc;
  struct sockaddr_in sa;

  if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
   fprintf(stderr, "Cannot open socket.\n");
    exit(EXIT_FAILURE);
  }

  ifc.ifc_len = IFRSIZE;
  ifc.ifc_req = NULL;

  do {
    ++size;
    /* realloc buffer size until no overflow occurs  */
    if (NULL == (ifc.ifc_req = realloc(ifc.ifc_req, IFRSIZE))) {
      fprintf(stderr, "Out of memory.\n");
      exit(EXIT_FAILURE);
    }
    ifc.ifc_len = IFRSIZE;
    if (ioctl(sockfd, SIOCGIFCONF, &ifc)) {
      perror("ioctl SIOCFIFCONF");
      exit(EXIT_FAILURE);
    }
  } while  (IFRSIZE <= ifc.ifc_len);

  ifr = ifc.ifc_req;
  for (;(char *) ifr < (char *) ifc.ifc_req + ifc.ifc_len; ++ifr) {

    if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data) {
      continue;  /* duplicate, skip it */
    }

    if (ioctl(sockfd, SIOCGIFFLAGS, ifr)) {
      continue;  /* failed to get flags, skip it */
    }

    printf("Interface:  %s\n", ifr->ifr_name);
    printf("IP Address: %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data)));

    if (0 == ioctl(sockfd, SIOCGIFHWADDR, ifr)) {

      /* Select which  hardware types to process.
       *
       *    See list in system include file included from
       *    /usr/include/net/if_arp.h  (For example, on
       *    Linux see file /usr/include/linux/if_arp.h to
       *    get the list.)
       */
      switch (ifr->ifr_hwaddr.sa_family) {
      default:
 printf("\n");
 continue;
      case  ARPHRD_NETROM:  case  ARPHRD_ETHER:  case  ARPHRD_PPP:
      case  ARPHRD_EETHER:  case  ARPHRD_IEEE802: break;
      }

      u = (unsigned char *) &ifr->ifr_addr.sa_data;

      if (u[0] + u[1] + u[2] + u[3] + u[4] + u[5]) {
        printf("HW Address: %2.2x.%2.2x.%2.2x.%2.2x.%2.2x.%2.2x\n",
      u[0], u[1], u[2], u[3], u[4], u[5]);
      }
    }

    if (0 == ioctl(sockfd, SIOCGIFNETMASK, ifr) &&
 strcmp("255.255.255.255", inet_ntoa(inaddrr(ifr_addr.sa_data)))) {
      printf("Netmask:    %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data)));
    }

    if (ifr->ifr_flags & IFF_BROADCAST) {
      if (0 == ioctl(sockfd, SIOCGIFBRDADDR, ifr) &&
   strcmp("0.0.0.0", inet_ntoa(inaddrr(ifr_addr.sa_data)))) {
        printf("Broadcast:  %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data)));
      }
    }

    if (0 == ioctl(sockfd, SIOCGIFMTU, ifr)) {
      printf("MTU:        %u\n",  ifr->ifr_mtu);
    }

    if (0 == ioctl(sockfd, SIOCGIFMETRIC, ifr)) {
      printf("Metric:     %u\n",  ifr->ifr_metric);
    } printf("\n");
  }

  close(sockfd);
  return EXIT_SUCCESS;
}
απλά τώρα βαριέμαι να σου κάνω print μόνο τις γραμμές που θέλεις.
Με το ioctl δούλεψε.

Posted: Wed Jun 15, 2005 1:02 am
by Einherjar
το έχω δοκιμάσει αυτό που λες και μου επέστρεψε την 0.0.0.0
Είχα και εγώ την ελπίδα ότι θα παίξει. κάτι άλλο μήπως?

Posted: Wed Jun 15, 2005 1:02 pm
by HdkiLLeR
Εμένα μου επιστρέφει την ip κανονικά πάντως.

Posted: Wed Jun 15, 2005 3:11 pm
by Einherjar
και πάλι όμως,έστω ότι ισχύει αυτό που λες. δεν θα σου επιστρέφει μια λίστα μέ όλες τις ip διευθύνσεις που έχει? πως μπορώ να ξέρω ποια από αυτές είναι αυτή που χρησιμοποιείται για τη συγκεκριμένη επικοινωνία?

Re: C: get local ip address

Posted: Wed Jun 15, 2005 8:23 pm
by HdkiLLeR
Einherjar wrote:έχω ένα socket που έχει γίνει bind στο ANY_ADDR.
Βασικά επειδή τώρα το πρόσεξα εδώ εννοείς INADDR_ANY έτσι;

Posted: Wed Jun 15, 2005 8:30 pm
by Einherjar
ναι αυτό εννούσα

Posted: Wed Jun 15, 2005 8:39 pm
by HdkiLLeR
Tώρα που ξαναδιάβασα το post:

1)Το παραπάνω μου παίζει κανονικά(όντως δεν σου κάνει όμως)
2)Η getsockname() είναι function call οπότε το OS θα σου επιστρέψει την ip, η οποία είναι η ίδια με αυτήν που αρχικοποίησες το socket(όλα αυτά τα κρατάει σε μια δομή). Εάν στην αρχή είχες δώσει INADDR_ANY = 0.0.0.0 τότε το ίδιο θα πάρεις με την getsock...

Posted: Wed Jun 15, 2005 8:46 pm
by Einherjar
ναι αυτό είναι το πρόβλημα. ο server κάνει bind στο 0.0.0.0 για να ακούει σε όλα τα interfaces που έχει. όμως χρειάζεται την πραγματική ip μέσω της οποίας επικοινωνεί με τον client ώστε να κωδικοποιήσει τα πακέτα που στέλνει. με το 0.0.0.0 ομως έχω πρόβλημα

Posted: Thu Jun 16, 2005 12:56 am
by AmmarkoV
Sorry που το ξαναγράφω αλλά
If a socket was bound to INADDR_ANY, indicating that any of the host's IP addresses should be used for the socket, getsockname will not necessarily return information about the host IP address, unless the socket has been connected with connect or accept. A Windows Sockets application must not assume that the IP address will be changed from INADDR_ANY unless the socket is connected. This is because for a multi-homed host, the IP address that will be used for the socket is unknown unless the socket is connected
Εγώ καταλαβαίνω οτι αν έχει γίνει η σύνδεση τότε η getsockname θα επιστρέφει σωστά.. (Βέβαια δεν το έχω δοκιμάσει..)
Δεν μπορεί πάντως,κάποιος τρόπος θα υπάρχει..

Posted: Thu Jun 16, 2005 12:58 am
by Einherjar
όπως είπα παραπάνω χρησιμοποιώ UTP και ως εκ τούτου δεν κάνω ούτε connect ούτε accept.

Posted: Thu Jun 16, 2005 2:08 am
by AmmarkoV
όπως είπα παραπάνω χρησιμοποιώ UTP και ως εκ τούτου δεν κάνω ούτε connect ούτε accept.
UDP μάλλον εννοείς,όχι UTP..
Δεν ξέρω , UDP δεν έχω χρησιμοποιήσει ποτέ , it surpasses my existing programming skills.. :)
Θα σου έλεγα να το κάνεις με standard TCP αλλά θα έχεις τους λόγους σου..
Ελπίζω να βρείς μια άκρη..
(Αν βρείς πες και σε εμάς.. ;) )

Posted: Thu Jun 16, 2005 2:29 am
by Einherjar
ναι αυτό :-D
αυτό που μάλλον θα κάνω είναι να ζητάω από την άλλη πλευρά να μου πει την ip μου. μπακάλικη μεν, λύση δε.
αν μέχρι τότε έχουμε κάτι καλύτερο, pls let me know!

Posted: Thu Jun 16, 2005 1:07 pm
by HdkiLLeR
AmmarkoV wrote:Sorry που το ξαναγράφω αλλά
If a socket was bound to INADDR_ANY, indicating that any of the host's IP addresses should be used for the socket, getsockname will not necessarily return information about the host IP address, unless the socket has been connected with connect or accept. A Windows Sockets application must not assume that the IP address will be changed from INADDR_ANY unless the socket is connected. This is because for a multi-homed host, the IP address that will be used for the socket is unknown unless the socket is connected
Εγώ καταλαβαίνω οτι αν έχει γίνει η σύνδεση τότε η getsockname θα επιστρέφει σωστά.. (Βέβαια δεν το έχω δοκιμάσει..)
Δεν μπορεί πάντως,κάποιος τρόπος θα υπάρχει..
Σίγουρα υπάρχει τρόπος αλλά το παραπάνω που αναφέρεις είναι για TCP only.

ΥΓ: Νεκ, άλλη μπακαλιά είναι να το περνάει ο user σαν όρισμα στην κλήση του προγράμματος και να μην ακούς στο INADDR_ANY.

Posted: Thu Jun 16, 2005 2:32 pm
by AmmarkoV
Einherjar wrote:αυτό που μάλλον θα κάνω είναι να ζητάω από την άλλη πλευρά να μου πει την ip μου. μπακάλικη μεν, λύση δε.
αν μέχρι τότε έχουμε κάτι καλύτερο, pls let me know!
Το σκεφτόμουν και εγώ (τα μεγάλα μυαλά.. :-D ) αλλά αν ο άλλος ξέρει το προτόκολλο που χρησιμοποιείς και σου στείλει ψεύτικη διευθυνση,λέμε τώρα έτσι.. ;) ,θα σου το ανατινάξει το πρόγραμμα..
Δεν είναι hack-proof έτσι..
Ωστόσο για πειραματισμό μια χαρά λύση είναι..!
HdkiLLeR wrote:ΥΓ: Νεκ, άλλη μπακαλιά είναι να το περνάει ο user σαν όρισμα στην κλήση του προγράμματος και να μην ακούς στο INADDR_ANY.
Σωστός..
Ή να τρέχεις 2,3 threads του προγράμματος ανάλογα με τα δίκτυα που είσαι και το καθένα να ακούει για μια συγκεκριμένη IP..
Γμτ με πόρωσες , θα πιάσω sockets πάλι να φτιάξω τπτ.. :razz:

Posted: Thu Jun 16, 2005 2:39 pm
by Einherjar
για το πρώτο δεν υπάρχει πρόβλημα. το πακέτο είναι κρυπτογραφημένο και ας πούμε ότι η ip του αποστολέα είναι ένας παράγοντας κρυπτογράφησης.
όσο για το δεύτερο δεν παίζει. απλά δε παίζει για το συγκεκριμένο θέμα.
τεσπα.... thanx a lot για τη βοήθειά σας!

Posted: Thu Jun 16, 2005 8:23 pm
by HdkiLLeR
AmmarkoV wrote: Το σκεφτόμουν και εγώ (τα μεγάλα μυαλά.. :-D ) αλλά αν ο άλλος ξέρει το προτόκολλο που χρησιμοποιείς και σου στείλει ψεύτικη διευθυνση,λέμε τώρα έτσι.. ;) ,θα σου το ανατινάξει το πρόγραμμα..
Οι περισσότεροι(για να μην πώ όλοι) routers πλέον δεν rouτάρουν packetes με spoofed ip οπότε κατά 90% δεν θα καταφάρεις κάτι με αυτό...

ΥΓ: Πάνε οι παλιές καλές στιγμές που έκανες ωραία πραγματάκια με IP Spoofing + TCP Seq attacks :) :) :)