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

1

Итак, у меня есть код Python, который создает интерфейс TAP для Linux, но он всегда имеет случайный MAC-адрес auto-. Чтобы упростить тестирование, я хотел бы вручную назначить интерфейс 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?

Спасибо!

  • 0
    Вы хотите сделать это в Python или в C?
  • 0
    В Python моей главной проблемой является построение структуры для передачи в ioctl.
Теги:

3 ответа

6
Лучший ответ

from: http://nullege.com/codes/show/src@p@[email protected]@[email protected]

def set_mac(self, newmac):
    ''' Set the device 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
    Хотел бы я знать об этом модуле раньше. Спасибо!
0

A 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 имеет то же (или строжайшее) требование выравнивания, что и другие члены союза. Если нет, вам может понадобиться отступы.

0

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню