ifreq構造体によるMACアドレスの変更

arp_poisoningのソースを読み返しているときに、ifreq構造体を使ってMACアドレスを設定できることを思い出した。

なので、任意のMACアドレスに設定できるプログラムを作ることにした。

MACアドレスを設定するには、SIOCGIFFLAGSをioctlで指定する、取得するには、SIOCGIFLAGSを指定する。

その後、ifr.ifr_hwaddr.sa_data[i]を使い、設定や取得を行う。

確認動作環境:fedora15,13

 

 

ifreq構造体 

struct ifreq {
char ifr_name[IFNAMSIZ]; /* Interface name */
union {
struct sockaddr ifr_addr;
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_netmask;
struct sockaddr ifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmap ifr_map;
char ifr_slave[IFNAMSIZ];
char ifr_newname[IFNAMSIZ];
char *ifr_data;
};
};

struct ifconf {
int ifc_len; /* size of buffer */
union {
char *ifc_buf; /* buffer address */
struct ifreq *ifc_req; /* array of structures */
};
};

 

machanger.c

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_arp.h>
int main(int argc, char **argv)
{ // 引数チェック
if(argc != 3){
printf("machanger <interface> <address>\n");
return 0;
}
int fd; // ソケットディスクリプション
struct ifreq ifr; // MACアドレス構造体
char *tp;
int i,t,tmp;
char *device = argv[1];
char *str = argv[2];
i = 0;
// ソケットオープン
fd = socket(AF_INET, SOCK_DGRAM, 0); /* デバイスを変更 */
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
ifr.ifr_flags &= ~IFF_UP;

// 先頭MACアドレスのポインタ格納
tp = strtok(str,":");
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; // 指定されたMACアドレスを16進数変換する
while(tp != NULL){
for(t=0;t<2;t++){
switch (tp[t]){
case '0': if(t==1){tmp+=0x0;}else{tmp=0x0;}break;
case '1': if(t==1){tmp+=0x1;}else{tmp=0x1;}break;
case '2': if(t==1){tmp+=0x2;}else{tmp=0x2;}break;
case '3': if(t==1){tmp+=0x3;}else{tmp=0x3;}break;
case '4': if(t==1){tmp+=0x4;}else{tmp=0x4;}break;
case '5': if(t==1){tmp+=0x5;}else{tmp=0x5;}break;
case '6': if(t==1){tmp+=0x6;}else{tmp=0x6;}break;
case '7': if(t==1){tmp+=0x7;}else{tmp=0x7;}break;
case '8': if(t==1){tmp+=0x8;}else{tmp=0x8;}break;
case '9': if(t==1){tmp+=0x9;}else{tmp=0x9;}break;
case 'a': if(t==1){tmp+=0xa;}else{tmp=0xa;}break;
case 'b': if(t==1){tmp+=0xb;}else{tmp=0xb;}break;
case 'c': if(t==1){tmp+=0xc;}else{tmp=0xc;}break;
case 'd': if(t==1){tmp+=0xd;}else{tmp=0xd;}break;
case 'e': if(t==1){tmp+=0xe;}else{tmp=0xe;}break;
case 'f': if(t==1){tmp+=0xf;}else{tmp=0xf;}break;
} if(t==0){
tmp = tmp << 4;
}
}
// 1バイトMACアドレス格納
ifr.ifr_hwaddr.sa_data[i] = tmp;
tp = strtok(NULL,":");
i+=1;
}
if (ioctl(fd, SIOCSIFHWADDR, &ifr) != 0) {
perror("");
}
} close(fd);
return 0;
}

 

実行方法

# machanger eth0 aa:bb:cc:dd:ee:ff

 

RPMパッケージ

 

machanger-1.0-0.i386.rpm

 

ソース

 

machanger-1.0.tar.gz