2010-02-13 11 views
8

Ich bin neu auf iPhone-Entwicklung, und ich möchte Wake-on-LAN in meine Anwendung integrieren, ohne meine Benutzer zu komprimieren, um die MAC-Adresse des Computers einzugeben, wenn die IP bereits bekannt ist. Ich googelte für einige Stunden, nahm den Quellcode eines ARP-Tools, aber ich weiß nicht, wie das auf dem iPhone zu verwalten.Wie kann ich die ARP-Tabelle auf dem iPhone abfragen?

Antwort

19

Da niemand meine Frage beantwortet hat ... hier ist die Antwort;)

#include <sys/param.h> 
#include <sys/file.h> 
#include <sys/socket.h> 
#include <sys/sysctl.h> 

#include <net/if.h> 
#include <net/if_dl.h> 
#include "if_types.h" 
#include "route.h" 
#include "if_ether.h" 
#include <netinet/in.h> 


#include <arpa/inet.h> 

#include <err.h> 
#include <errno.h> 
#include <netdb.h> 

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

    -(NSString*) ip2mac: (char*) ip 
    { 



     int expire_time, flags, export_only, doing_proxy, found_entry; 



     NSString *mAddr = nil; 
     u_long addr = inet_addr(ip); 
     int mib[6]; 
     size_t needed; 
     char *host, *lim, *buf, *next; 
     struct rt_msghdr *rtm; 
     struct sockaddr_inarp *sin; 
     struct sockaddr_dl *sdl; 
     extern int h_errno; 
     struct hostent *hp; 

     mib[0] = CTL_NET; 
     mib[1] = PF_ROUTE; 
     mib[2] = 0; 
     mib[3] = AF_INET; 
     mib[4] = NET_RT_FLAGS; 
     mib[5] = RTF_LLINFO; 
     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 
      err(1, "route-sysctl-estimate"); 
     if ((buf = malloc(needed)) == NULL) 
      err(1, "malloc"); 
     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 
      err(1, "actual retrieval of routing table"); 


     lim = buf + needed; 
     for (next = buf; next < lim; next += rtm->rtm_msglen) { 
      rtm = (struct rt_msghdr *)next; 
      sin = (struct sockaddr_inarp *)(rtm + 1); 
      sdl = (struct sockaddr_dl *)(sin + 1); 
      if (addr) { 
       if (addr != sin->sin_addr.s_addr) 
        continue; 
       found_entry = 1; 
      } 
      if (nflag == 0) 
       hp = gethostbyaddr((caddr_t)&(sin->sin_addr), 
            sizeof sin->sin_addr, AF_INET); 
      else 
       hp = 0; 
      if (hp) 
       host = hp->h_name; 
      else { 
       host = "?"; 
       if (h_errno == TRY_AGAIN) 
        nflag = 1; 
      } 



      if (sdl->sdl_alen) { 

       u_char *cp = LLADDR(sdl); 

       mAddr = [NSString stringWithFormat:@"%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]]; 


      // ether_print((u_char *)LLADDR(sdl)); 
      } 
      else 

       mAddr = nil; 



     } 


     if (found_entry == 0) { 
      return nil; 
     } else { 
      return mAddr; 
     } 




    } 

aus Äpfeln arp.c arbeiten iphone

Kopieren Sie die folgenden:

- "if_types.h" 
- "route.h" 
- "if_ether.h" 

Header von Mac enthält in Ihrem Projektordner und Klassen hinzufügen

+0

Danke für den Tipp. Ich habe nur den Header "route.h" kopiert, da die anderen in den SDKs enthalten sind (3.2+). –

+1

hi, @ anthony iam bekomme nflag undeclared identifier error, was brauche ich um dies zu integrieren? – Bonnie

+1

nur oben in Datei hinzufügen static int nflag; –

7

Ich vereinfachte die co de und behoben ein Speicherleck.

Auf meinem Computer fanden die Header-Dateien in/usr/include/netinet und/usr/include/net.

- (NSString*)ip2mac:(in_addr_t)addr 
{ 
    NSString *ret = nil; 

    size_t needed; 
    char *buf, *next; 

    struct rt_msghdr *rtm; 
    struct sockaddr_inarp *sin; 
    struct sockaddr_dl *sdl; 

    int mib[6]; 

    mib[0] = CTL_NET; 
    mib[1] = PF_ROUTE; 
    mib[2] = 0; 
    mib[3] = AF_INET; 
    mib[4] = NET_RT_FLAGS; 
    mib[5] = RTF_LLINFO; 

    if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), NULL, &needed, NULL, 0) < 0) 
     err(1, "route-sysctl-estimate"); 

    if ((buf = (char*)malloc(needed)) == NULL) 
     err(1, "malloc"); 

    if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), buf, &needed, NULL, 0) < 0) 
     err(1, "retrieval of routing table"); 

    for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { 

     rtm = (struct rt_msghdr *)next; 
     sin = (struct sockaddr_inarp *)(rtm + 1); 
     sdl = (struct sockaddr_dl *)(sin + 1); 

     if (addr != sin->sin_addr.s_addr || sdl->sdl_alen < 6) 
      continue; 

     u_char *cp = (u_char*)LLADDR(sdl); 

     ret = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", 
       cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]]; 

     break; 
    } 

    free(buf); 

    return ret; 
} 
+0

Können Sie bitte einen einfachen Demo-Code dafür bereitstellen? Bcz kann ich nicht benutzen. Danke –

2

Ich bin nicht sicher, dass die sysctl Funktion Teil der öffentlichen API ist. Ich habe die Methode offensichtlich verwendet und meine App wurde für "nicht-öffentliche" API-Nutzung abgelehnt. Ich glaube aber auch nicht, dass es anders als die oben gezeigten Methoden möglich ist.

+0

Hallo new299, wenn ich dies für eine legale und öffentliche App verwende, wird es vom App Store abgelehnt? – FujiRoyale

+0

Es war für mich, das war vor einer Weile. Könnte einen Versuch wert sein. – new299

+1

Ich weiß, dass dies ein Thema ist, aber haben Sie möglicherweise eine Anweisung, nach Geräten im Netzwerk zu suchen, die programmatisch von den Apple-Behörden akzeptiert werden? Ich habe SO [hier] gefragt (http://stackoverflow.com/questions/26534050/nsnetservicebrowser-to-find-any-device-on-network) – FujiRoyale