[Network Basic] ioctl()함수와 ifreq구조체

I/O 관련 하드웨어 제어 함수

header : #include <sys/ioctl.h>
int getsockopt(int sockfd, int request, …)
         > setsockopt()함수 보다 더 낮은 레벨에서 소켓 디스크립터를 제어 가능한 함수

인자 설명

  1. int sockfd : 소켓 디스크립터
  2. int request : 요청할 정보
  3. … : 요청한 정보에 따라 달라진다.

∗ 함수 실행에 문제 생길 경우 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;
}

출력

ubuntu@ubuntu-VirtualBox:~$ ./Ex_13-09 eth0
eth0: 08:00:27:40:0c:3b

코드 리뷰

19 ~ 20 행 : ifreq 구조체 변수 'ifr'을 초기화 하고 ifr의 멤버인 'ifr.ifr_name'에 인터페이스 이름을 작성한다.
29 ~ 32 행 : ioctl()함수를 이용하여 하드웨어 주소를 얻고 있다.

글의 문제가 있다면 댓글을 달아 주세요.

This site uses Akismet to reduce spam. Learn how your comment data is processed.