CnUnix

[알림판목록 I] [알림판목록 II] [글목록][이 전][다 음]
[ CnUnix ] in KIDS
글 쓴 이(By): terzeron (microkid)
날 짜 (Date): 2003년 9월 19일 금요일 오후 03시 15분 55초
제 목(Title): Re: 로컬 IP 알아내기?


system("ifconfig ...")가 가장 쉽죠. 

두번째는 시스템마다 다른 방법인데요... 
BSD에서는 sysctl로 읽어들이면 됩니다.
Linux에서는 socket열고 ioctl로 읽어야 합니다.

더 간단한 방법도 있을 법한데 그건 저도 잘 모르겠네요.

아래 코드는 BSD와 Linux에서 사용할 수 있는 코드입니다만
솔라리스에서는 동작할지 모르겠습니다.(FreeBSD와 Linux의
ifconfig를 참고해서 핵심만 뽑아낸 겁니다. 물론 실제 소스
코드를 보면 이 코드보다 훨씬 복잡합니다.)

#ifdef __FreeBSD__

int if_status(char *this_ha)
{
    int ret = -1;
    int addrcount;
    struct sockaddr_dl *sdl = NULL;
    int mib[6];
    char *buf = NULL, *lim =  NULL, *next = NULL;
    struct if_msghdr *ifm = NULL, *nextifm = NULL;
    struct ifa_msghdr *ifam = NULL;
    size_t needed;
    int flags;

    printf("# ether_status device=%s\n", device);
    if (device == NULL) {
        errx(1, "can't identify device name");
    }

    // construct sysctl command
    mib[0] = CTL_NET;
    mib[1] = PF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_INET;
    mib[4] = NET_RT_IFLIST;
    mib[5] = 0;

    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
        errx(1, "iflist-sysctl-estimate");
    } 
    if ((buf = malloc(needed)) == NULL) {
        errx(1, "malloc");
    }
    if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
        errx(1, "actual retrieval of interface table");
    }

    // find one device in many device
    lim = buf + needed;
    next = buf;
    while (next < lim) {
        ifm = (struct if_msghdr *) next;
        if (ifm->ifm_type == RTM_IFINFO) {
            sdl = (struct sockaddr_dl *) (ifm + 1);
            flags = ifm->ifm_flags;
        } else {
            errx(1, "out of sync parsing NET_RT_IFLIST");
        }
        next += ifm->ifm_msglen;
        ifam = NULL;
        addrcount = 0;
        while (next < lim) {
            nextifm = (struct if_msghdr *) next;
            if (nextifm->ifm_type != RTM_NEWADDR) {
                break;
            }
            if (ifam == NULL) {
                ifam = (struct ifa_msghdr *) nextifm;
            }
            addrcount++;
            next += nextifm->ifm_msglen;
        }
        // find one device with same name
        if ((strlen(device) != sdl->sdl_nlen) || 
            (strncmp(device, sdl->sdl_data, sdl->sdl_nlen) != 0)) {
            continue;
        }
        ret = 0;
        break;
    }
 
    free(buf);
    memcpy(this_ha, &sdl->sdl_data[3], ETHERADDRLEN);
    
    return ret;
}

#else // __FreeBSD__

int if_status(char *this_ha)
{
    int sockfd;
    struct ifreq ifr;
    int ret;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        errx(1, "can't open INET socket");
    }
    strncpy(ifr.ifr_name, device, IFNAMSIZ);
    ret = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
    hex2str(ifr.ifr_hwaddr.sa_data, this_ha);

    return ret;
}

#endif // __FreeBSD__


 ---
어떤 성취가, 어떤 조롱이, 또는 어떤 고뇌가 나를 기다리고 있을지 나는 모른다. 
나는 아무 것도 모른다. 그러나 나는 아직 과거의 경이로운 기적의 시대가 영원히 
과거의 것이 되어 버리지는 않았다는 사실을 굳게 믿고 있다.  - Stanislaw Lem -
[알림판목록 I] [알림판목록 II] [글 목록][이 전][다 음]
키 즈 는 열 린 사 람 들 의 모 임 입 니 다.