네트워크 인터페이스에 관한 정보를 알고 싶다면 ioctl() 시스템콜을 사용할 수 있습니다.

 

전형적인 운영체제는 2계층으로 나뉩니다. User Space(사용자 모드)Kenel Space(커널 모드).

User Space에 상주하는 애플리케이션이 Kenel Space에 존재하는 자원을 사용하고자할 땐 시스템콜을 이용합니다.

참고로, System Call Function은 내부적으로 System Call Vector와 대응됩니다. 예를들면, exit()함수는 System Call Vector Number: 1번

write()함수는 System Call Vector Number: 4번.

전형적인 운영체제의 커널은 수 백개의 System Call Vector를 제공합니다.

ioctl() 시스템콜은 디바이스 드라이버(Device Driver)와 통신하기위한 함수입니다.

 

디바이스 드라이버(Device Driver)?

아래 2가지 사실을 생각해봅시다.

   1. 하드웨어 주변 장치는 커널 안에 직접적으로 주소지정을 할 수 있다.

   2. 응용 프로그램이 장치와 통신하길 원할 수 있다.( 하드웨어 장치의 기능을 사용하고 싶을 때 )

그런데 커널 개발자는 어떤 장치가 커널 안에 주소를 할당받을지, 그 장치에는 어떤 기능이 있는지 알 지 못합니다.( 미리 예측할 수 없는 문제 )

이러한 문제점 때문에 확장가능한 모듈식으로 커널을 유연하게 설계할 필요가 있었고, 그렇게해서 나온게 디바이스 드라이버입니다.

즉, 어떠한 장치가 연결될지 모르는 상황에서 디바이스 드라이버라는 하나의 중간 계층(?)을 둠으로써 문제를 해결할 수 있었습니다.

 

ioctl() 함수는 struct ifreq 구조체를 매개변수로 받아 정보를 해당 구조체에 저장합니다. 다음 예제는 자신의 MAC Address 정보를 가져옵니다.

#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
int main(int argc, char* argv[]) {
struct ifreq ifr;
u_char* macAddress;
u_char* interface = argv[1]; // argv[1]은 네트워크 인터페이스라 가정합니다. 예를 들어, ens33, eth0 eth1 ...
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, interface, IFNAMSIZ - 1); // ioctl의 대상으로 삼고자하는 인터페이스 이름을 ifr_name 멤버에 저장
ioctl(sock, SIOCGIFCONF, &ifr); // ioctl에 필요한 정보를 struct ifreq 구조체 데이터로 넘깁니다.
macAddress = (u_char*)ifr.ifr_hwaddr.sa_data; // ifr_hwaddr 멤버에 하드웨어 주소에 대한 정보가 담겨있습니다.
close(sock);
return 0;
}

 

다음은 struct 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)

댓글

댓글을 사용할 수 없습니다.