Shammer's Philosophy

My private adversaria

ioctl で NIC の様々な情報を取得

ioctl で NIC の情報を取得 - Shammerismでは IPv4 のみだったが、MTU や BroadCast アドレスなども取得する関数を作成してみた。

#include <arpa/inet.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>      
#include <stdlib.h>
#include <string.h> 
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>

int getifmtu(const char * device){
    int status, fd, value;
    struct ifreq ifreq;
    strcpy(ifreq.ifr_name, device);
    fd = socket(PF_INET, SOCK_DGRAM, 0);
    status = ioctl(fd, SIOCGIFMTU, &ifreq);
    if( status == -1 ){
	value = -1;
    }
    else{
	value = ifreq.ifr_mtu;
    }
    close(fd);
    return value;
}

struct sockaddr_in * getifbroadcastip(const char * device){
    struct sockaddr_in * value;
    struct sockaddr_in addr;
    struct ifreq ifreq;
    int status, fd;
    strcpy(ifreq.ifr_name, device);
    fd = socket(PF_INET, SOCK_DGRAM, 0);
    status = ioctl(fd, SIOCGIFBRDADDR, &ifreq);
    if( status == -1 ){
	value = NULL;
    }
    else {
	memcpy(&addr, &ifreq.ifr_broadaddr, sizeof(struct sockaddr_in));
	value = (struct sockaddr_in *)malloc(sizeof(&value));
	memcpy(value,&addr, sizeof(value));
    }
    close(fd);
    return value;
}

struct sockaddr_in * getifnetmask(const char * device){
    struct sockaddr_in * value;
    struct sockaddr_in addr;
    struct ifreq ifreq;
    int status, fd;
    strcpy(ifreq.ifr_name, device);
    fd = socket(PF_INET, SOCK_DGRAM, 0);
    status = ioctl(fd, SIOCGIFNETMASK, &ifreq);
    if( status == -1 ){
	value = NULL;
    }
    else {
	memcpy(&addr, &ifreq.ifr_netmask, sizeof(struct sockaddr_in));
	value = (struct sockaddr_in *)malloc(sizeof(&value));
	memcpy(value, &addr, sizeof(value));
    }
    close(fd);
    return value;
}

char * getifhwaddr(const char * device){
    char * value;
    struct ifreq ifreq;
    int status, fd;
    strcpy(ifreq.ifr_name, device);
    fd = socket(PF_INET, SOCK_DGRAM, 0);
    status = ioctl(fd, SIOCGIFHWADDR, &ifreq);
    if( status == -1 ){ value = NULL; }
    else {
	value = (char *)malloc(sizeof(ifreq.ifr_hwaddr.sa_data));
	memcpy(value, &ifreq.ifr_hwaddr.sa_data, sizeof(value));
    }
    close(fd);
    return value;
}

int main(int argc, char * args[]){
    printf("MTU is %d.\n", getifmtu(args[1]));
    struct sockaddr_in * broadcastip;
    broadcastip= getifbroadcastip(args[1]);
    printf("Broadcast Address is %s.\n", inet_ntoa(broadcastip->sin_addr));
    struct sockaddr_in * netmask;
    netmask = getifnetmask(args[1]);
    printf("Netmask is %s.\n", inet_ntoa(netmask->sin_addr));
    char * p;
    p = getifhwaddr(args[1]);
    printf("hwaddr=%02X:%02X:%02X:%02X:%02X:%02X\n",
	   *p, *(p + 1), *(p + 2), *(p + 3), *(p + 4), *(p + 5));
    return 0;
}

実行結果は以下。

$ ./a.out eth0
MTU is 1500.
Broadcast Address is 192.168.1.255.
Netmask is 255.255.255.0.
hwaddr=FFFFFF84:3A:4B:FFFFFFDC:02:FFFFFF80

なんか MAC アドレスが変な感じになってしまっているが、、、これはいいのだろうか。