1
votes

Recently i'm interested in how to access and set network interfaces in linux using a low level aproach. So i found, searching on the net the ioctl callback and i learnt how to use it. I started writing down something but today i'm having problem to change the mac address of a interface.

The code that i'm using is:

int change_mac(int handler){
  srand(times(NULL));

  get_hwaddr(handler,&req);
  for(int i=0;i<6;i++){
    req.ifr_hwaddr.sa_data[i]=(char)rand();
  }
  char err=ioctl(sock,SIOCSIFHWADDR,&req);
  if(err<0){
    printf("Problem to change the mac address with a random one\n %i",err);
    exit(0);
  }
}

int get_hwaddr(int handler,struct ifreq* req_a){
  if(handler>=current){
    return -1;
  }
  strncpy(req_a->ifr_name,interfaces[handler],strlen(interfaces[handler]));

  if(ioctl(sock,SIOCGIFHWADDR,req_a)<0){
    return -2;
  }
}

To better understand my code the "interfaces" variable is a char** where i store the name of interfaces when i initializate a new interface, and in that function after store the name in that variable, i'm returning a int as handler.

Before changing the mac address, from the code i put the interface down.

Now when i call ioctl to change the mac address with the SIOCSIFHWADDR ioctl return -1.

Can anyone help me? Sorry for the english

1
Change MAC address? Is that not a hardware, read-only, identifier?Martin James
check errno for details on what the error actually is. That might help youe.dan
strerror (errno) return always "-1"P.Carlino
Do you have permissions to perform this operation? Is the interface down when you do it? Not all network adapters or kernel drivers support changing the MAC address, but some certainly doKevin Boone
Yes because i execute it using sudo. Talking about the state of the interface before calling change_mac i call if_down that is my own implementation that works because i test it using after call it ifconfigP.Carlino

1 Answers

2
votes

Have a look at netdevice(7) man page:

SIOCGIFHWADDR, SIOCSIFHWADDR

Get or set the hardware address of a device using ifr_hwaddr. The hardware address is specified in a struct sockaddr. sa_family contains the ARPHRD_* device type, sa_data the L2 hardware address starting from byte 0. Setting the hardware address is a privileged operation.

So, you need few things to change the MAC:

  1. ifr_name (must be nul terminated string)
  2. sa_family contains the ARPHRD_* device type (filled in get_hwaddr()?)
  3. sa_data the L2 hardware address starting from byte 0 (done)
  4. setting the hardware address is a privileged operation (sudo)

Since you confirmed in comments you run it with sudo on a host, please make sure your interface name is correct and nul terminated, i.e. change line:

strncpy(req_a->ifr_name,interfaces[handler],strlen(interfaces[handler]));

to line:

strncpy(req_a->ifr_name,interfaces[handler],strlen(interfaces[handler]) + 1);

Here is an example of the code to change a MAC: https://gist.github.com/mad4j/8864135