| [ 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 - |