2008년 9월 24일 수요일

linux 에서 특정 인터페이스 카드의 MAC 어드레스 읽어오기

갑자기 이런 코드가 필요해져서 짜봤다.
샘플수준의 코드



/*
eth0 인터페이스의 하드웨어 어드레스(mac) 을 찍어주는 코드

1. 인터페이스 이름은 eth0 라고 가정했다. 런타임에 알아내야 한다면
SIOCGIFCONF 등을 참고

2. 소켓하나가 필요. 다른 예제들을 보니 보통 DGRAM 으로
만드네.. STREAM 으로도 동작엔 문제가 없는듯 한데 DGRAM 이 쓰이는
이유가 뭘까

3. ifreq 구조체 만들어서 적절히 채우고

4. ioctl 콜

5. SIOCGIFHWADDR 를 요청했다면 결과는 ifreq 구조체의
ifr_hwaddr.sa_data 를 6 바이트 읽어내면 된다.
*/
#include <sys/socket.h>
#include <sys/types.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
const char* ifname = "eth0";

int s = socket(AF_INET, SOCK_DGRAM, 0);
if(s < 0) perror("socket fail"); /* TODO 에러처리 */

struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);

if(ioctl(s, SIOCGIFHWADDR, &ifr) < 0)
perror("ioctl fail"); /* TODO 에러처리 */

const unsigned char* mac = ifr.ifr_hwaddr.sa_data;
printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0],
mac[1],
mac[2],
mac[3],
mac[4],
mac[5]);

close(s);
}


음. 추가로 SIOCGIFADDR 로 ip 얻어오는 함수도 만들어봤다. ioctl 쪽은 정말 드럽다. sockaddr_in 때문에 헤더파일 몇개 추가해야 한다는것 잊지 말도록. man inet_ntoa 참고

int get_ip_address(char* ip, int iplen, const char* ifname)
{
int s;
struct ifreq ifr;
struct sockaddr_in* sin;

s = socket(AF_INET, SOCK_DGRAM, 0);
if(s<0) return -1;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);

if(ioctl(s, SIOCGIFADDR, &ifr) < 0)
{
close(s);
return -1;
}

sin = (struct sockaddr_in*)&ifr.ifr_addr;
strncpy(ip,
inet_ntoa(sin->sin_addr),
iplen);

close(s);
return 0;
}




댓글 1개:

김태정 on Voiceportal :

trackback from: [linux/java]top 결과값 받아오기
리눅스 상에서 top를 실행하면 일정한 주기로 refresh된다. top을 실행한 후에 이를 다른 프로그램으로 보내주거나 파일로 저장하기 위해서 옵션을 넣어주면 된다. 먼저 man top를 해보자. 중요하게 봐두어야 할 것은 다음 두 옵션이다. -b : Batch mode operation Starts top in ’Batch mode’, which could be useful for sending output from top to other pro..