Как вызвать SIOCSIFHWADDR ioctl для изменения MAC-адреса в Python?

#python #c #linux

#python #c #linux

Вопрос:

Итак, у меня есть код на Python, который создает интерфейс Linux TAP, но он всегда выдает случайный, автоматически сгенерированный MAC-адрес. Для упрощения тестирования я хотел бы вручную назначить интерфейсу MAC-адрес после его инициализации. Я знаю, что могу сделать это с помощью SIOCSIFHWADDR ioctl и struct ifreq , но у меня возникло несколько вопросов о реализации.

Вот структура C:

 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;
};
  

Теперь я думаю, что мне нужно только заполнить hwaddr поле, но поскольку это объединение, я не уверен, как создать структуру в Python.

Каков наилучший способ вызвать SIOCSIFHWADDR ioctl с struct ifreq , чтобы изменить MAC-адрес интерфейса в Python?

Спасибо!

Комментарии:

1. Вы хотите сделать это на Python или на C?

2. В Python моя основная проблема заключается в создании структуры для передачи в ioctl.

Ответ №1:

от:http://nullege.com/codes/show/src@p@y@pynetlinux-1.0@pynetlinux@ifconfig.py

 def set_mac(self, newmac):
    ''' Set the device's mac address. Device must be down for this to
        succeed. '''
    macbytes = [int(i, 16) for i in newmac.split(':')]
    ifreq = struct.pack('16sH6B8x', self.name, AF_UNIX, *macbytes)
    fcntl.ioctl(sockfd, SIOCSIFHWADDR, ifreq)
  

Я использовал множество сетевых методов из этого модуля; очень полезно!

Комментарии:

1. Хотел бы я знать об этом модуле раньше. Спасибо!

Ответ №2:

union Просто означает, что существует несколько способов думать о содержимом. Вас интересует только один, этот:

 struct ifreq_set_hwaddr
{
# define IFHWADDRLEN    6
# define IFNAMSIZ       IF_NAMESIZE
    char ifrn_name[IFNAMSIZ];       /* Interface name, e.g. "en0".  */
    struct sockaddr ifru_hwaddr;
};
  

Обратите внимание, что я предположил, что struct sockaddr имеет то же (или самое строгое) требование к выравниванию, что и другие члены объединения. Если нет, вам может понадобиться некоторое дополнение.

Ответ №3:

Вы создаете / sbin / ip в качестве подпроцесса, например

 /sbin/ip link set dev dummy0 address 02:23:45:67:89:ab
  

что сэкономит массу хлопот.