[linux C] IP van lokale NIC opvragen

Pagina: 1
Acties:

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 15:06

voodooless

Sound is no voodoo!

Topicstarter
Zoals de titel als zegt wil ik het IP adres van mijn lokale NIC opvragen...

Ik heb zelf al het volgende geprobeerd:

C:
1
2
3
4
5
6
7
8
9
    char hostname[255];
    struct hostent *phost;
    if (gethostname (hostname, sizeof (hostname)) == -1) {
      sprintf (hostname, "unknown");
    }
    printf("hostname: %s",hostname);
    phost = gethostbyname( hostname );
    info->ip =  inet_addr(&phost->h_addr);
    info->port = portnumber;


Helaas klopt dan de hostname wel, maar het IP-address wat ik krijg slaat nergens op (255.255.255.255 i.p.v 10.0.1.11 :X ).

Nu heb ik al zitten zoeken naar andere manieren, naar heb helaas niets zinnigs gevonden. Zoeken naar "C" (plus rest) in google is niet echt efficient, en de man pages waren ook niet echt behulpzaam.

Mij lijkt het misschien handiger om dit probleem vanuit de netwerkinterfaces aan te pakken i.p.v via hostname, maar hoe je die opvraagt kan ik ook nergens vinden..

Wie kan mij dus verderhelpen... Ik ben meer een java guru, en C is al weer lang geleden voor mij (en voor het laatsts in embeded, zonder ook maar een enkele api ;) ). Helemaal voorkauwen hoeft ook niet, goede hints zijn ook prima :)

[ Voor 4% gewijzigd door voodooless op 04-06-2004 00:43 ]

Do diamonds shine on the dark side of the moon :?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:19
Adressen van interfaces enumeraten kan ik onder FreeBSD met getifaddrs(); geen idee of dat onder Linux ook kan.

Wat je concrete probleem betreft: die h_addr is een pointer naar een in_addr structure, niet een adres in stringvorm of zoiets. Geen wonder dat je garbage in je IP adres krijg. Als regel 8 aanpast, werkt het waarschijnlijk wel:
C:
8
memcpy(&info->ip, phost->h_addr, sizeof(info->ip));

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 15:06

voodooless

Sound is no voodoo!

Topicstarter
Ah, thanks Soultaker :) , dat werkt idd wat beter. Echter geeft ie localhost (127.0.0.1) terug, en niet 10.0.1.11 :(

Ik ga gtifaddrs() eens proberen :) , de functie is in ieder geval wel aanwezig in linux, maar weinig voorbeelden te vinden.

[ Voor 23% gewijzigd door voodooless op 04-06-2004 00:57 ]

Do diamonds shine on the dark side of the moon :?


Verwijderd

Dit werkt bij kernel 1..2.13 en 2.0
Of dit ook werkt op 2.4 & 2.6 .........

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    char *host, **names, **adrs;
    struct hostent, *hostinfo;

    if (argc ==  1) {
         char myname[256];
         gethostname(myname, 256);
         host = myname;
    }
    else host = argv[1];

    hosinfo = gethostbyname(host);
    if (!hostinfo) {
         fprintf(stderr, "geen info voor host: %s\n",host);
         exit(1);
    }

    printf("resultaten voor host %s:\n",host);
    printf("naam: %s\n", hostinfo -> h_name);
    printf("Aliassen:");
    names = hostinfo -> h_aliasses;

    while (*names) {
        printf(" %s", *names);
        names++;
    }
    printf("\n");

    // gebruikt host IP ?

    if (hostinfo -> h_addrtype != AF_INET) {
         fprintf(stderr, "niet een IP host!\n");
         exit(1);
    }

    addrs = hostinfo -> h_addr_list;
 
    while (*addrs) {
        printf(" %s", inet_ntoa(*(struct in_addr *)*addrs));
        addrs++;
    }
    printf("\n");
    exit(0);
}

[ Voor 21% gewijzigd door curry684 op 04-06-2004 02:10 . Reden: [code]-tags voor leesbaarheid... ]


  • CyBeR
  • Registratie: September 2001
  • Niet online

CyBeR

💩

als info->ip een char* is, probeer dan inet_ntoa() eens ;)

All my posts are provided as-is. They come with NO WARRANTY at all.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:19
Je krijgt een heel rijtje hosts, als je niet de h_addr (pseudo-)member maar de h_addr_list member gebruikt. Daar zal je echte IP ook wel bij zitten (ik krijg m'n externe IP ook als eerste) maar het blijft natuurlijk lastig programmatisch kiezen welk adres je moet hebben (alleen 127.0.0.1 is redelijk veiliger te herkennen als niet-extern adres).
CyBeR schreef op 04 juni 2004 @ 00:58:
als info->ip een char* is, probeer dan inet_ntoa() eens ;)
Dat werkt wel, maar niet zomaar als char*, want inet_ntoa() verwacht een struct in_addr als argument.

[ Voor 28% gewijzigd door Soultaker op 04-06-2004 01:00 ]


  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 15:06

voodooless

Sound is no voodoo!

Topicstarter
Dit vind ook alleen het localhost ip. Maar thanks anyway :)

die info->ip is unsigned int (hmm, die is 64 bits bij mij... misschien kan daar ook wat fout gaan)...

[ Voor 25% gewijzigd door voodooless op 04-06-2004 01:06 ]

Do diamonds shine on the dark side of the moon :?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:19
Weet je zeker dat die 64 bits is?? Ik dacht dat met tenminste de AMD x86-64 architectuur met GCC (long) ints gewoon 32 bits zijn (en long long ints dus pas 64 bits, net als op de x86).

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 15:06

voodooless

Sound is no voodoo!

Topicstarter
Soultaker schreef op 04 juni 2004 @ 01:08:
Weet je zeker dat die 64 bits is?? Ik dacht dat met tenminste de AMD x86-64 architectuur met GCC (long) ints gewoon 32 bits zijn (en long long ints dus pas 64 bits, net als op de x86).
int is idd 32 bits. Een long (en ook long long) zijn 64 bits op amd64. in dit geval dus niets aan de hand.

Nog niet echt verder met getifaddrs() :(

[ Voor 13% gewijzigd door voodooless op 04-06-2004 01:24 ]

Do diamonds shine on the dark side of the moon :?


  • CyBeR
  • Registratie: September 2001
  • Niet online

CyBeR

💩

Soultaker schreef op 04 juni 2004 @ 00:59:

[...]

Dat werkt wel, maar niet zomaar als char*, want inet_ntoa() verwacht een struct in_addr als argument.
Yeah, maar info->ip is waar het heen gaat. En inet_ntoa() returned een pointer to char ;)

All my posts are provided as-is. They come with NO WARRANTY at all.


Verwijderd

Mja, dit is redelijk slecht gedocumenteerd in linux dus hints over ioctls en if_nameindex helpen je ook niet verder denk ik:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int sock= ::socket(PF_INET, SOCK_DGRAM, 0);
    if(sock < 0) {
        ::perror("socket");
        return 1;
    }
    struct if_nameindex* ifs= ::if_nameindex();
    if(!ifs) {
        ::perror("if_nameindex");
        ::close(sock);
        return 1;
    }
    for(int i= 0; ifs[i].if_index; ++i) {
        ::ifreq req;
        ::strncpy(req.ifr_name, ifs[i].if_name, IFNAMSIZ - 1);
        req.ifr_name[IFNAMSIZ - 1]= '\0';
        if(::ioctl(sock, SIOCGIFADDR, &req) == -1) {
            ::perror("ioctl");
            ::if_freenameindex(ifs);
            ::close(sock);
            return 1;
        }
        ::printf("%-*s %s\n", IFNAMSIZ, ifs[i].if_name, ::inet_ntoa(
            reinterpret_cast< ::sockaddr_in* >(&req.ifr_addr)->sin_addr));
    }
    ::if_freenameindex(ifs);
    ::close(sock);
    return 0;
}

[ Voor 19% gewijzigd door Verwijderd op 04-06-2004 11:37 ]


Verwijderd

[b][message=20900280,noline]deepspace schreef
...
Mij lijkt het misschien handiger om dit probleem vanuit de netwerkinterfaces aan te pakken i.p.v via hostname, maar hoe je die opvraagt kan ik ook nergens vinden..
....
Kijk eens op www.ntop.org en download ntop-3.0.tgz
En bestudeer iface.c

Verwijderd

Verwijderd schreef op 04 juni 2004 @ 02:58:
Kijk eens op www.ntop.org en download ntop-3.0.tgz
En bestudeer iface.c
Ik postte net al een stukje code dat (vergelijkbaar met ifconfig) alle actieve interfaces met bijbehorende adressen uitprint, dus verder zoekwerk voor studie lijkt me onnodig :)

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:19
Wat jammer dat dat zo ingewikkeld is onder Linux...

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 15:06

voodooless

Sound is no voodoo!

Topicstarter
Thanks jongens, ik kom er zo wel uit denk ik :D

Do diamonds shine on the dark side of the moon :?


  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 15:06

voodooless

Sound is no voodoo!

Topicstarter
Verwijderd schreef op 04 juni 2004 @ 03:18:
[...]


Ik postte net al een stukje code dat (vergelijkbaar met ifconfig) alle actieve interfaces met bijbehorende adressen uitprint, dus verder zoekwerk voor studie lijkt me onnodig :)
Zo voorbarig moet je nooit zijn... Ik krijg op twee machines een linker error op je code (misschien wat vergeten :?). bovendien zoek ik echt naar een stukje C-code, en niet C++ hacking ;)

Dat stukje uit ntop is wel heel erg uigebreid. Ik wil gewoon heel simpel mijn IP krijgen ;).

Do diamonds shine on the dark side of the moon :?


Verwijderd

deepspace schreef op 04 juni 2004 @ 13:08:
Zo voorbarig moet je nooit zijn... Ik krijg op twee machines een linker error op je code (misschien wat vergeten :?). bovendien zoek ik echt naar een stukje C-code, en niet C++ hacking ;)

Dat stukje uit ntop is wel heel erg uigebreid. Ik wil gewoon heel simpel mijn IP krijgen ;).
De code werkt als je hem met g++ compileert, ik had deze source nog liggen en had geen zin om 3 uur 's nachts te gaan zitten editen :)

Als je alle "::" weghaalt, de variabelen bovenaan declareert, struct voor de structures zet en de reinterpret_cast door een c-style cast vervangt moet het werken.

edit:
Bij deze een C-versie
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void)
{
    struct if_nameindex *ifs;
    int i;
    int sock= socket(PF_INET, SOCK_DGRAM, 0);
    if(sock < 0) {
        perror("socket");
        return 1;
    }
    ifs= if_nameindex();
    if(!ifs) {
        perror("if_nameindex");
        close(sock);
        return 1;
    }
    for(i= 0; ifs[i].if_index; ++i) {
        struct ifreq req;
        strncpy(req.ifr_name, ifs[i].if_name, IFNAMSIZ - 1);
        req.ifr_name[IFNAMSIZ - 1]= '\0';
        if(ioctl(sock, SIOCGIFADDR, &req) == -1) {
            perror("ioctl");
            if_freenameindex(ifs);
            close(sock);
            return 1;
        }
        printf("%-*s %s\n", IFNAMSIZ, ifs[i].if_name, inet_ntoa(
            ((struct sockaddr_in*)&req.ifr_addr)->sin_addr));
    }
    if_freenameindex(ifs);
    close(sock);
    return 0;
}


edit 2:
Je kunt deze code niet compilen met de -ansi optie omdat de compiler dan alle niet-ansi functies (zoals if_nameindex()) deactiveert.

[ Voor 73% gewijzigd door Verwijderd op 04-06-2004 15:16 ]

Pagina: 1