#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
что сэкономит массу хлопот.