How to assign IP address to interface in python?

2019-03-27 20:11发布

问题:

I have python script that set the IP4 address for my wireless and wired interfaces. So far, I use subprocess command like :

subprocess.call(["ip addr add local 192.168.1.2/24 broadcast 192.168.1.255 dev wlan0"])

How can I set the IP4 address of an interface using python libraries? and if there is any way to get an already existing IP configurations using python libraries ?

回答1:

Set an address via the older ioctl interface:

import socket, struct, fcntl

SIOCSIFADDR = 0x8916
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


def setIpAddr(iface, ip):
    bin_ip = socket.inet_aton(ip)
    ifreq = struct.pack('16sH2s4s8s', iface, socket.AF_INET, '\x00' * 2, bin_ip, '\x00' * 8)
    fcntl.ioctl(sock, SIOCSIFADDR, ifreq)


setIpAddr('em1', '192.168.0.1')

(setting the netmask is done with SIOCSIFNETMASK = 0x891C)

Ip addresses can be retrieved in the same way: Finding local IP addresses using Python's stdlib

I believe there is a python implementation of Netlink should you want to use that over ioctl



回答2:

With pyroute2.IPRoute:

from pyroute2 import IPRoute
ip = IPRoute()
index = ip.link_lookup(ifname='em1')[0]
ip.addr('add', index, address='192.168.0.1', mask=24)
ip.close()

With pyroute2.IPDB:

from pyroute2 import IPDB
ip = IPDB()
with ip.interfaces.em1 as em1:
    em1.add_ip('192.168.0.1/24')
ip.release()


回答3:

You have multiple options to do it from your python program.

One could use the ip tool like you showed. While this is not the best option at all this usualy does the job while being a little bit slow and arkward to program.

Another way would be to do the things ip does on your own by using the kernel netlink interface directly. I know that libnl has some experimental (?) python bindings. This may work but you will have to deal with a lot of low level stuff. I wouldn't recommend this way for simple "set and get" ips but it's the most "correct" and reliable way to do so.

The best way in my opinion (if you only want to set and get ips) would be to use the NetworkManagers dbus interface. While this is very limited and may have its own problems (it might behave not the way you would like it to) this is the most straight forward way if the NetworkManager is running anyway.

So, choose the libnl approach if you want to get your hands dirty, it's clearly superior but also way more work. You may also get away with the NetworkManager dbus interface, depending on your needs and general system setup. Otherwise you can just leave it that way.