Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 3 | from subprocess import call, Popen, PIPE |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 4 | import sys |
| 5 | import subprocess |
| 6 | import dbus |
| 7 | import string |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 8 | import socket |
| 9 | import re |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 10 | import os |
| 11 | import fcntl |
| 12 | import glib |
| 13 | import gobject |
| 14 | import dbus.service |
| 15 | import dbus.mainloop.glib |
| 16 | |
| 17 | DBUS_NAME = 'org.openbmc.NetworkManager' |
| 18 | OBJ_NAME = '/org/openbmc/NetworkManager/Interface' |
| 19 | |
| 20 | network_providers = { |
Adriana Kobylak | 88c733b | 2016-02-03 16:46:58 -0600 | [diff] [blame] | 21 | 'networkd' : { |
| 22 | 'bus_name' : 'org.freedesktop.network1', |
| 23 | 'ip_object_name' : '/org/freedesktop/network1/network/default', |
| 24 | 'hw_object_name' : '/org/freedesktop/network1/link/_31', |
Hariharasubramanian R | 3a224e7 | 2016-02-10 12:32:08 -0600 | [diff] [blame] | 25 | 'ip_if_name' : 'org.freedesktop.network1.Network', |
| 26 | 'hw_if_name' : 'org.freedesktop.network1.Link', |
Adriana Kobylak | 88c733b | 2016-02-03 16:46:58 -0600 | [diff] [blame] | 27 | 'method' : 'org.freedesktop.network1.Network.SetAddr' |
| 28 | }, |
| 29 | 'NetworkManager' : { |
| 30 | 'bus_name' : 'org.freedesktop.NetworkManager', |
| 31 | 'ip_object_name' : '/org/freedesktop/NetworkManager', |
| 32 | 'hw_object_name' : '/org/freedesktop/NetworkManager', |
Hariharasubramanian R | 3a224e7 | 2016-02-10 12:32:08 -0600 | [diff] [blame] | 33 | 'ip_if_name' : 'org.freedesktop.NetworkManager', |
| 34 | 'hw_if_name' : 'org.freedesktop.NetworkManager', |
Adriana Kobylak | 88c733b | 2016-02-03 16:46:58 -0600 | [diff] [blame] | 35 | 'method' : 'org.freedesktop.NetworkManager' # FIXME: |
| 36 | }, |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 37 | } |
| 38 | |
| 39 | def getPrefixLen(mask): |
Adriana Kobylak | 88c733b | 2016-02-03 16:46:58 -0600 | [diff] [blame] | 40 | prefixLen = sum([bin(int(x)).count('1') for x in mask.split('.')]) |
| 41 | return prefixLen |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 42 | |
| 43 | class IfAddr (): |
| 44 | def __init__ (self, family, scope, flags, prefixlen, addr, gw): |
| 45 | self.family = family |
| 46 | self.scope = scope |
| 47 | self.flags = flags |
| 48 | self.prefixlen = prefixlen |
| 49 | self.addr = addr |
| 50 | self.gw = gw |
| 51 | |
| 52 | class NetMan (dbus.service.Object): |
| 53 | def __init__(self, bus, name): |
| 54 | self.bus = bus |
| 55 | self.name = name |
| 56 | dbus.service.Object.__init__(self,bus,name) |
| 57 | |
| 58 | def setNetworkProvider(self, provider): |
| 59 | self.provider = provider |
| 60 | |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 61 | def _isvaliddev(self, device): |
| 62 | devices = os.listdir ("/sys/class/net") |
| 63 | if not device in devices : return False |
| 64 | else: return True |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 65 | |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 66 | def _ishwdev (self, device): |
| 67 | f = open ("/sys/class/net/"+device+"/type") |
| 68 | type = f.read() |
| 69 | return False if (int(type) == 772) else True |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 70 | |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 71 | def _isvalidmask (self, mask): |
| 72 | for x in mask.split('.'): |
| 73 | try: |
| 74 | y = int(x) |
| 75 | except: |
| 76 | return False |
| 77 | if y > 255: return False |
| 78 | return mask.count('.') == 3 |
| 79 | |
| 80 | def _isvalidmac(self, mac): |
| 81 | macre = '([a-fA-F0-9]{2}[:|\-]?){6}' |
| 82 | if re.compile(macre).search(mac) : return True |
| 83 | else: return False |
| 84 | |
| 85 | def _isvalidip(self, family, ipaddr): |
| 86 | if family == socket.AF_INET: |
| 87 | try: |
| 88 | socket.inet_pton(socket.AF_INET, ipaddr) |
| 89 | except AttributeError: # no inet_pton here, sorry |
| 90 | try: |
| 91 | socket.inet_aton(ipaddr) |
| 92 | except socket.error: |
| 93 | return False |
| 94 | return ipaddr.count('.') == 3 |
| 95 | except socket.error: # not a valid address |
| 96 | return False |
| 97 | |
| 98 | return True |
| 99 | |
| 100 | elif family == socket.AF_INET6: |
| 101 | try: |
| 102 | socket.inet_pton(socket.AF_INET6, ipaddr) |
| 103 | except socket.error: # not a valid address |
| 104 | return False |
| 105 | return True |
| 106 | |
| 107 | else: return False |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 108 | |
| 109 | def _getAddr (self, target, device): |
| 110 | netprov = network_providers [self.provider] |
| 111 | bus_name = netprov ['bus_name'] |
| 112 | |
| 113 | if (target == "ip"): |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 114 | ipaddr = "" |
| 115 | defgw = "" |
| 116 | prefixlen = "0" |
| 117 | |
| 118 | proc = subprocess.Popen(["ip", "addr", "show", "dev", device], stdout=PIPE) |
| 119 | procout = proc.communicate() |
| 120 | if procout: |
| 121 | ipout = procout[0].splitlines()[2].strip() |
| 122 | ipaddr,prefixlen = ipout.split ()[1].split("/") |
| 123 | |
| 124 | proc = subprocess.Popen(["ip", "route", "show", "dev", device, "default", "0.0.0.0/0"], stdout=PIPE) |
| 125 | procout = proc.communicate() |
| 126 | if procout[0]: |
| 127 | ipout = procout[0].splitlines()[0].strip() |
| 128 | defgw = ipout.split ()[2] |
| 129 | |
| 130 | return 2, int(prefixlen), ipaddr, defgw |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 131 | |
| 132 | if (target == "mac"): |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 133 | proc = subprocess.Popen(["ip", "link", "show", "dev", device], stdout=PIPE) |
| 134 | ipout = proc.communicate()[0].splitlines()[1].strip() |
| 135 | mac = ipout.split ()[1] |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 136 | return mac |
| 137 | |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 138 | @dbus.service.method(DBUS_NAME, "", "") |
| 139 | def test(self): |
| 140 | print("TEST") |
| 141 | |
Hariharasubramanian R | 3a224e7 | 2016-02-10 12:32:08 -0600 | [diff] [blame] | 142 | @dbus.service.method(DBUS_NAME, "s", "x") |
| 143 | def EnableDHCP (self, device): |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 144 | if not self._isvaliddev (device) : raise ValueError, "Invalid Device" |
| 145 | |
| 146 | confFile = "/etc/systemd/network/00-bmc-" + device + ".network" |
Hariharasubramanian R | 3a224e7 | 2016-02-10 12:32:08 -0600 | [diff] [blame] | 147 | |
| 148 | print("Making .network file...") |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 149 | try: |
| 150 | networkconf = open (confFile, "w+") |
| 151 | except IOError: |
| 152 | raise IOError, "Failed to open " + confFile |
| 153 | |
Hariharasubramanian R | 3a224e7 | 2016-02-10 12:32:08 -0600 | [diff] [blame] | 154 | networkconf.write ('[Match]'+ '\n') |
| 155 | networkconf.write ('Name=' + (device) + '\n') |
| 156 | networkconf.write ('[Network]' + '\n') |
| 157 | networkconf.write ('DHCP=yes') |
| 158 | networkconf.close () |
| 159 | |
| 160 | print("Restarting networkd service...") |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 161 | rc = call(["ip", "addr", "flush", device]) |
| 162 | rc = call(["systemctl", "restart", "systemd-networkd.service"]) |
| 163 | return rc |
Hariharasubramanian R | 3a224e7 | 2016-02-10 12:32:08 -0600 | [diff] [blame] | 164 | |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 165 | @dbus.service.method(DBUS_NAME, "ssss", "x") |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 166 | def SetAddress4 (self, device, ipaddr, netmask, gateway): |
| 167 | if not self._isvaliddev (device) : raise ValueError, "Invalid Device" |
| 168 | if not self._isvalidip (socket.AF_INET, ipaddr) : raise ValueError, "Malformed IP Address" |
| 169 | if not self._isvalidip (socket.AF_INET, gateway) : raise ValueError, "Malformed GW Address" |
| 170 | if not self._isvalidmask (netmask) : raise ValueError, "Invalid Mask" |
| 171 | |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 172 | prefixLen = getPrefixLen (netmask) |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 173 | if prefixLen == 0: raise ValueError, "Invalid Mask" |
| 174 | |
| 175 | confFile = "/etc/systemd/network/00-bmc-" + device + ".network" |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 176 | |
| 177 | print("Making .network file...") |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 178 | try: |
| 179 | networkconf = open (confFile, "w+") |
| 180 | except IOError: |
| 181 | raise IOError, "Failed to open " + confFile |
| 182 | |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 183 | networkconf.write ('[Match]'+ '\n') |
| 184 | networkconf.write ('Name=' + (device) + '\n') |
| 185 | networkconf.write ('[Network]' + '\n') |
| 186 | networkconf.write ('Address=' + ipaddr + '/' + str(prefixLen) + '\n') |
| 187 | networkconf.write ('Gateway=' + gateway + '\n') |
Chris Austen | b13a3cd | 2016-02-01 18:18:21 -0600 | [diff] [blame] | 188 | networkconf.close() |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 189 | |
| 190 | print("Restarting networkd service...") |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 191 | rc = call(["ip", "addr", "flush", device]) |
| 192 | rc = call(["systemctl", "restart", "systemd-networkd.service"]) |
| 193 | return rc |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 194 | |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 195 | #family, prefixlen, ip, defgw |
| 196 | @dbus.service.method(DBUS_NAME, "s", "iyss") |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 197 | def GetAddress4 (self, device): |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 198 | if not self._isvaliddev (device) : raise ValueError, "Invalid Device" |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 199 | return self._getAddr ("ip", device) |
| 200 | |
| 201 | @dbus.service.method(DBUS_NAME, "s", "s") |
| 202 | def GetHwAddress (self, device): |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 203 | if not self._isvaliddev (device) : raise ValueError, "Invalid Device" |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 204 | return self._getAddr ("mac", device) |
| 205 | |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 206 | @dbus.service.method(DBUS_NAME, "ss", "i") |
| 207 | def SetHwAddress (self, device, mac): |
| 208 | if not self._isvaliddev (device) : raise ValueError, "Invalid Device" |
| 209 | if not self._ishwdev (device) : raise ValueError, "Not a Hardware Device" |
| 210 | if not self._isvalidmac (mac) : raise ValueError, "Malformed MAC address" |
| 211 | |
Adriana Kobylak | 88c733b | 2016-02-03 16:46:58 -0600 | [diff] [blame] | 212 | rc = subprocess.call(["fw_setenv", "ethaddr", mac]) |
Hariharasubramanian R | 308cffc | 2016-03-03 09:35:16 -0600 | [diff] [blame] | 213 | |
| 214 | print("Restarting networkd service...") |
| 215 | rc = call(["ip", "link", "set", "dev", device, "down"]) |
| 216 | rc = call(["ip", "link", "set", "dev", device, "address", mac]) |
| 217 | rc = call(["ip", "link", "set", "dev", device, "up"]) |
| 218 | |
| 219 | rc = call(["systemctl", "restart", "systemd-networkd.service"]) |
Adriana Kobylak | 88c733b | 2016-02-03 16:46:58 -0600 | [diff] [blame] | 220 | return rc |
| 221 | |
Hariharasubramanian R | cd38797 | 2016-01-20 07:19:41 -0600 | [diff] [blame] | 222 | def main(): |
| 223 | dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) |
| 224 | bus = dbus.SystemBus() |
| 225 | name = dbus.service.BusName(DBUS_NAME, bus) |
| 226 | obj = NetMan (bus, OBJ_NAME) |
| 227 | obj.setNetworkProvider ("networkd") |
| 228 | mainloop = gobject.MainLoop() |
| 229 | print("Started") |
| 230 | mainloop.run() |
| 231 | |
| 232 | if __name__ == '__main__': |
Adriana Kobylak | e150bfd | 2016-02-01 21:47:34 -0600 | [diff] [blame] | 233 | sys.exit(main()) |