2012-04-16 2 views
0

모든 machin 네트워크 주소를 검색하는 매우 유용한 기능 호출 getifaddrs이 있습니다. 문제는이 기능이없는 오래된 glibc 버전을 사용하고 있다는 것입니다. 대체물이 있습니까? 내가 찾고 있었고 getipnodebyname을 찾았지만 주소가/etc/hosts 파일에 매핑되지 않은 경우에는 유용하지 않습니다.이전 glibc 버전의 getifaddrs와 유사

+0

사용중인 glibc 버전 –

+0

구현이 glibc (오픈 소스)에 있다고 생각하면 구현을 취하여 코드에 통합 할 수 있습니다 (이 접근법과 라이센스 호환 가능) . glibc 2.3이 2002 년에 릴리스되었습니다.' – Petesh

답변

2

이전 답변에 추가하려면 다음은 SIOCGIFCONF -approach의 예입니다. 당신은 이런 식으로해야합니다 :

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

int fd; 

int get_iface_list(struct ifconf *ifconf) 
{ 
    int rval; 
    if((rval = ioctl(fd, SIOCGIFCONF , (char*) ifconf )) < 0) 
     perror("ioctl(SIOGIFCONF)"); 

    return rval; 
} 

int main() 
{ 
    static struct ifreq ifreqs[100]; 
    static struct ifconf ifc; 
    char *ptr; 

    fd = socket(AF_INET, SOCK_DGRAM, 0); 
    if (fd < 0) 
     return 1; 

    ifc.ifc_buf = (char*) (ifreqs); 
    ifc.ifc_len = sizeof(ifreqs); 

    if(get_iface_list(&ifc) < 0) return -1; 

    /* Go through the list of interfaces */ 
    for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len;) 
    { 
     struct ifreq *ifr = (struct ifreq*)ptr; 
     int len = (sizeof(struct sockaddr) > ifr->ifr_addr.sa_len) ? 
       sizeof(struct sockaddr) : ifr->ifr_addr.sa_len; 

     ptr += sizeof(ifr->ifr_name) + len; 

      /* Do what you need with the ifr-structure. 
      * ifr->ifr_addr contains either sockaddr_dl, 
      * sockaddr_in or sockaddr_in6 depending on 
      * what addresses and L2 protocols the interface 
      * has associated in it. 
      */ 
    } 

    close(fd); 
    return 0; 
} 

물론 몇 가지 있습니다. 유닉스 네트워크 프로그래밍 Chapter 17.6에 따르면 ioctl(fd, SIOCGIFCONF, array)은 인자가 가리키는 배열이 너무 작 으면 일부 플랫폼에서 에러를 반환하지 않을 수도 있습니다. 그런 다음 데이터가 연결됩니다. 이 문제를 해결할 수있는 유일한 방법은 배열의 크기를 늘리는 동시에 동일한 결과 길이를 두 번 얻을 때까지 루프에서 ioctl()을 호출하는 것입니다. 물론 이것이 2012 년 이후로 더 이상 관련성이없는 것은 확실하지 않습니다.

크기 ifreqs 배열은이 경우에 완전히 추측입니다. 배열에는 인터페이스와 연결된 모든 L2 및 L3 주소에 대해 하나의 struct ifreq이 포함됩니다. 예를 들어 IPv6 주소가 있다고 가정하면 lo 인터페이스의 경우 이더넷, IPv4 및 IPv6의 세 가지 항목을 얻을 수 있습니다. 그러므로 충분한 공간을 확보하거나 kludge를 적용하십시오.

브로드 캐스트 주소 및 기타 추가 정보를 얻으려면 추가 ioctl() 통화가 필요합니다. 모든 가능한 옵션은 OS가 제공하는 것에 달려 있습니다.

자세한 내용은 W. Richard Stevens의 Unix Network Programming을 읽는 것이 좋습니다. 이 주제에 관한 가장 포괄적 인 책입니다.

+0

고마워요! 그게 내가 필요한거야. – gumik

2

에 해당하는 작업을 수행하는 전통적인 방법은 ioctlSIOCGIFCONF 작동을이었다. 모든 소켓을 조작에 사용할 수 있습니다. 하나의 함수 호출만큼 쉬운 것은 아닙니다.

+1

인터페이스리스트를 얻기 위해'SIOCGIFCONF'를 호출 한 후, 각각에 대해'SIOCGIFFLAGS' ioctl을 호출하여 그것이 작동하는지 확인합니다; 만약 그렇다면 실제로 주소를 가져 오기 위해'SIOCGIFADDR' ioctl을 호출한다. – caf