I/O 관련 하드웨어 제어 함수
header : #include <sys/ioctl.h>
int getsockopt(int sockfd, int request, …)
> setsockopt()함수 보다 더 낮은 레벨에서 소켓 디스크립터를 제어 가능한 함수
인자 설명
- int sockfd : 소켓 디스크립터
- int request : 요청할 정보
- … : 요청한 정보에 따라 달라진다.
∗ 함수 실행에 문제 생길 경우 0보다 작은 값을 반환한다.
ioctl()를 이용해 Ethernet과 관련된 정보를 요청
Ethernet과 관련된 정보가 필요하다면 ifreq 구조체를 사용하면 된다.
ifreq의 형식은 아래와 같다.
struct ifreq { # define IFHWADDRLEN 6 # define IFNAMSIZ IF_NAMESIZE union { char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ } ifr_ifrn; union { struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; struct sockaddr ifru_netmask; struct sockaddr ifru_hwaddr; short int ifru_flags; int ifru_ivalue; int ifru_mtu; struct ifmap ifru_map; char ifru_slave[IFNAMSIZ]; /* Just fits the size */ char ifru_newname[IFNAMSIZ]; __caddr_t ifru_data; } ifr_ifru; }; # define ifr_name ifr_ifrn.ifrn_name /* interface name */ # define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ # define ifr_addr ifr_ifru.ifru_addr /* address */ # define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ # define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ # define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ # define ifr_flags ifr_ifru.ifru_flags /* flags */ # define ifr_metric ifr_ifru.ifru_ivalue /* metric */ # define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ # define ifr_map ifr_ifru.ifru_map /* device map */ # define ifr_slave ifr_ifru.ifru_slave /* slave device */ # define ifr_data ifr_ifru.ifru_data /* for use by interface */ # define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ # define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ # define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */ # define ifr_newname ifr_ifru.ifru_newname /* New name */ # define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0) # define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0) # define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)
Ethernet 카드의 MAC 주소를 가져오는 예제
#include <stdio.h> #include <string.h> #include <sys/ioctl.h> #include <net/if.h> enum { ARGV_CMD, ARGV_INTERFACE }; int main(int argc, char * argv[]) { int sock; struct ifreq ifr; unsigned char *mac = NULL; if(argc != 2){ printf("%s [Interface name]\n", argv[ARGV_CMD]); return 1; } memset(&ifr, 0x00, sizeof(ifr)); strcpy(ifr.ifr_name, argv[ARGV_INTERFACE]); int fd=socket(AF_UNIX, SOCK_DGRAM, 0); if((sock=socket(AF_UNIX, SOCK_DGRAM, 0))<0){ perror("socket "); return 1; } if(ioctl(fd,SIOCGIFHWADDR,&ifr)<0){ perror("ioctl "); return 1; } mac = ifr.ifr_hwaddr.sa_data; printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", ifr.ifr_name, mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); close(sock); return 0; }
출력
ubun[email protected]:~$ ./Ex_13-09 eth0 eth0: 08:00:27:40:0c:3b
코드 리뷰
19 ~ 20 행 : ifreq 구조체 변수 'ifr'
을 초기화 하고 ifr의 멤버인 'ifr.ifr_name'
에 인터페이스 이름을 작성한다.
29 ~ 32 행 : ioctl()
함수를 이용하여 하드웨어 주소를 얻고 있다.