def nl_socket_alloc(pid=None, grps=0, seq=None, rx=None, tx=None, timeout=None) -> NLSocket: """ create a netlink socket :param pid: port id :param grps: multicast groups mask :param seq: initial seq. # :param rx: rx buffer size :param tx: tx buffer size :param timeout: time to block on socket :returns: a NLSocket NOTE: per man socket, the kernel will double the specified rx/tx buffer size and the min. size is 128 """ # set & validate paramaters pid = pid or getpid() + int(time()) # allow multiple sockets on this host if pid < 1: raise EnvironmentError(errno.EINVAL, "Invalid port id") seq = seq or int(time()) if seq < 1: raise EnvironmentError(errno.EINVAL, "Invalid sequence number") rx = rx or BUFSZ if rx < 128 or rx > _maxbufsz_(): raise pyric.error(errno.EINVAL, "Invalid rx size") tx = tx or BUFSZ if tx < 128 or tx > _maxbufsz_(): raise pyric.error(errno.EINVAL, "Invalid tx size") # create the socket and return it try: s = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, nlh.NETLINK_GENERIC) s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, tx) s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, rx) s.settimeout(timeout) s.bind((pid, grps)) except socket.error as e: raise EnvironmentError(e.errno, e.strerror) return NLSocket({ "sock": s, "tx": tx, "rx": rx, "pid": pid, "grpm": grps, "seq": seq })
def rfkill_block(idx): """ blocks the device at index :param idx: rkill index """ if not os.path.exists(os.path.join(spath,"rfkill{0}".format(idx))): raise pyric.error(errno.ENODEV,"No device at {0}".format(idx)) with open(dpath, 'wb') as fout: try: rfke = rfkh.rfkill_event(idx,rfkh.RFKILL_TYPE_ALL,rfkh.RFKILL_OP_CHANGE,1,0) fout.write(rfke) except struct.error as e: raise pyric.error(pyric.EUNDEF,"Error packing rfkill event {0}".format(e)) except IOError as e: raise pyric.error(e.errno,e.message)
def load(opath: str = None) -> Dict[str, str]: """ parse oui.txt file :param opath: path of oui text file :returns: oui dict {oui:manuf} for each oui in path or empty dict """ fin = None ouis = {} if not opath: opath = OUIPATH try: fin = open(opath) for line in fin.readlines()[1:]: o, m = line.strip().split("\t") ouis[o.lower()] = m[0:100] fin.close() except IndexError: pass except IOError as e: raise pyric.error(e.errno, e.strerror) finally: if fin and not fin.closed: fin.close() return ouis
def test_start_interface_not_compatible_none(self, pyw): """ Tests start method when interface is not supported """ pyw.side_effect = pyric.error(93, "Device does not support nl80211") self.network_manager.start()
def hard_blocked(idx): """ determines hard block state of device :param idx: rkill index :returns: True if device at idx is hard blocked, False otherwise """ if not os.path.exists(os.path.join(spath,"rfkill{0}".format(idx))): raise pyric.error(errno.ENODEV,"No device at {0}".format(idx)) fin = None try: fin = open(os.path.join(spath,"rfkill{0}".format(idx),'hard'),'r') return int(fin.read().strip()) == 1 except IOError: raise pyric.error(errno.ENODEV,"No device at {0}".format(idx)) except ValueError: raise pyric.error(pyric.EUNDEF,"Unexpected error") finally: if fin: fin.close()
def hard_blocked(idx): """ determines hard block state of device :param idx: rkill index :returns: True if device at idx is hard blocked, False otherwise """ if not os.path.exists(os.path.join(spath, "rfkill{0}".format(idx))): raise pyric.error(errno.ENODEV, "No device at {0}".format(idx)) fin = None try: fin = open(os.path.join(spath, "rfkill{0}".format(idx), 'hard'), 'r') return int(fin.read().strip()) == 1 except IOError: raise pyric.error(errno.ENODEV, "No device at {0}".format(idx)) except ValueError: raise pyric.error(pyric.EUNDEF, "Unexpected error") finally: if fin: fin.close()
def test_start_interface_no_such_device_none(self, pyw): """ Tests start method when there is no such interface """ pyw.side_effect = pyric.error(19, "No such device") # just checking to make sure error is not raised self.assertIsNone(self.network_manager.start())
def rfkill_block(idx): """ blocks the device at index :param idx: rkill index """ if not os.path.exists(os.path.join(spath,"rfkill{0}".format(idx))): raise pyric.error(errno.ENODEV,"No device at {0}".format(idx)) fout = None try: rfke = rfkh.rfkill_event(idx,rfkh.RFKILL_TYPE_ALL,rfkh.RFKILL_OP_CHANGE,1,0) if _PY3_: rfke = rfke.decode('ascii') fout = open(dpath, 'w') fout.write(rfke) except struct.error as e: raise pyric.error(pyric.EUNDEF,"Error packing rfkill event {0}".format(e)) except IOError as e: raise pyric.error(e.errno,e.message) finally: if fout: fout.close()
def rfkill_unblock(idx): """ unblocks the device at index :param idx: rkill index """ if not os.path.exists(os.path.join(spath, "rfkill{0}".format(idx))): raise pyric.error(errno.ENODEV, "No device at {0}".format(idx)) fout = None try: rfke = rfkh.rfkill_event(idx, rfkh.RFKILL_TYPE_ALL, rfkh.RFKILL_OP_CHANGE, 0, 0) fout = open(dpath, 'w') fout.write(rfke) except struct.error as e: raise pyric.error(pyric.EUNDEF, "Error packing rfkill event {0}".format(e)) except IOError as e: raise pyric.error(e.errno, e.message) finally: if fout: fout.close()
def rfkill_unblockby(rtype): """ unblocks the device of type :param rtype: rfkill type one of {'all'|'wlan'|'bluetooth'|'uwb'|'wimax' |'wwan'|'gps'|'fm'|'nfc'} """ if rtype not in rfkh.RFKILL_TYPES: raise pyric.error(errno.EINVAL,"Type {0} is not valid".format(rtype)) rfks = rfkill_list() for name in rfks: if rfks[name]['type'] == rtype: rfkill_unblock(rfks[name]['idx'])
def nla_putat(msg, i, v, a, d): """ puts (overwrites) attribute at index i in msg's attr list :param msg: GENLMsg :param i: index to put attribute :param v: attribute value :param a: attribute type :param d: attribute datatype """ if d > nlh.NLA_TYPE_MAX: raise pyric.error(errno.ERANGE, "Invalid datatype") msg["attrs"][i] = (a, v, d)
def search(tkn): """ searches for and returns any commands,attributes with tkn :param tkn: :returns: a list of commands,attributes with tkn in them """ tkn = tkn.upper() if len(tkn) < 3: raise pyric.error(pyric.EUNDEF, "{0} is to ambiguous".format(tkn)) found = [cmd for cmd in commands if tkn in cmd] found += [attr for attr in attributes if tkn in attr] return found
def rfkill_unblockby(rtype): """ unblocks the device of type :param rtype: rfkill type one of {'all'|'wlan'|'bluetooth'|'uwb'|'wimax' |'wwan'|'gps'|'fm'|'nfc'} """ if rtype not in rfkh.RFKILL_TYPES: raise pyric.error(errno.EINVAL, "Type {0} is not valid".format(rtype)) rfks = rfkill_list() for name in rfks: if rfks[name]["type"] == rtype: rfkill_unblock(rfks[name]["idx"])
def search(tkn): """ searches for and returns any commands,attributes with tkn :param tkn: :returns: a list of commands,attributes with tkn in them """ tkn = tkn.upper() if len(tkn) < 3: raise pyric.error(pyric.EUNDEF,"{0} is to ambiguous".format(tkn)) found = [cmd for cmd in commands if tkn in cmd] found += [attr for attr in attributes if tkn in attr] return found
def test_start_interface_unidentified_error_error(self, pyw): """ Tests start method when an unidentified error has happened while getting the card """ pyw.side_effect = pyric.error(2220, "This is a fake error") with self.assertRaises(pyric.error) as error: self.network_manager.start() the_exception = error.exception self.assertEqual(the_exception[0], 2220, "The error was not caught.")
def gettype(idx): """ returns the type of the device :param idx: rfkill index :returns: the type of the device """ fin = None try: fin = open(os.path.join(spath, "rfkill{0}".format(idx), 'type'), 'r') return fin.read().strip() except IOError: raise pyric.error(errno.ENODEV, "No device at {0}".format(idx)) finally: if fin: fin.close()
def gettype(idx): """ returns the type of the device :param idx: rfkill index :returns: the type of the device """ fin = None try: fin = open(os.path.join(spath,"rfkill{0}".format(idx),'type'),'r') return fin.read().strip() except IOError: raise pyric.error(errno.ENODEV,"No device at {0}".format(idx)) finally: if fin: fin.close()
def getname(idx): """ returns the phyical name of the device :param idx: rfkill index :returns: the name of the device """ fin = None try: fin = open(os.path.join(spath, "rfkill{0}".format(idx), "name"), "r") return fin.read().strip() except IOError: raise pyric.error(errno.EINVAL, "No device at {0}".format(idx)) finally: if fin: fin.close()
def test_set_interface_mac_invalid_mac_error(self, pyw): """ Test set_interface_mac with an invalid MAC address to raise an error """ pyw.macset.side_effect = pyric.error(22, "Invalid mac address") interface_name = "wlan0" interface_object = "Card Object" mac_address = "1" adapter = interfaces.NetworkAdapter(interface_name, interface_object, self.mac_address) self.network_manager._name_to_object[interface_name] = adapter self.network_manager._active.add(interface_name) with self.assertRaises(interfaces.InvalidMacAddressError): self.network_manager.set_interface_mac(interface_name, mac_address)
def test_set_interface_unexpected_error(self, pyw): """ Test set_interface_mac when an unexpected error occurs """ pyw.macset.side_effect = pyric.error(5534, "Unexpected error") interface_name = "wlan0" interface_object = "Card Object" mac_address = "11:22:33:44:55:66" adapter = interfaces.NetworkAdapter(interface_name, interface_object, self.mac_address) self.network_manager._name_to_object[interface_name] = adapter self.network_manager._active.add(interface_name) with self.assertRaises(pyric.error) as error: self.network_manager.set_interface_mac(interface_name, mac_address) self.assertEqual(error.exception[0], 5534, "Unexpected error")
def test_add_virtual_interface_first_run_error_second_run_success( self, mock_pyric): """ Test add_virtual_interface when the interface name already exist This case should return pyric.error for the first time """ card = mock.Mock() exceptions = iter([pyric.error(22, "interface name exists")]) def side_effect(*args): try: raise next(exceptions) except StopIteration: return mock_pyric.down.return_value = None mock_pyric.devadd.side_effect = side_effect expected = 'wlan2' actual = self.network_manager.add_virtual_interface(card) self.assertEqual(actual, expected)
def nl_sendmsg(sock, msg, override=False): """ sends msg to kernel :param sock: netlink socket :param msg: nlmsg stream :param override: if True will keep the message's pid and seq. This can be used for testing """ try: # change the msg's pid & seq to that of the sockets prior to sending & # set the ack flag - I can't figure how to tell in recv if an ack was # requested or not so I force an ACK here if not override: msg.pid = sock.pid msg.seq = sock.seq msg.flags = msg.flags | nlh.NLM_F_ACK sent = sock.send(msg.tostream()) if sent != msg.len: raise EnvironmentError(errno.EBADMSG, "Message sent incomplete") except socket.error as e: raise EnvironmentError(errno.ECOMM, e) except AttributeError: raise pyric.error(errno.ENOTSOCK, "Invalid netlink socket")
def load(opath=None): """ parse oui.txt file :param opath: path of oui text file :returns: oui dict {oui:manuf} for each oui in path or empty dict """ fin = None ouis = {} if not opath: opath = OUIPATH try: fin = open(opath) for line in fin.readlines()[1:]: o,m = line.strip().split('\t') ouis[o.lower()] = m[0:100] fin.close() except IndexError: pass except IOError as e: raise pyric.error(e.errno,e.strerror) finally: if fin and not fin.closed: fin.close() return ouis
fpath = os.path.dirname(os.path.realpath(__file__)) # read in the files here cmdpath = os.path.join(fpath, "commands.help") commands = None # cmd -> desc,attributes used dict cmdlookup = None # reverse lookup for command constants cin = None try: # first three lines are comments, 4th line is empty cin = open(cmdpath, "r") for _ in range(4): _in = cin.readline() commands = json.loads(cin.readline()) cmdlookup = json.loads(cin.readline()) except: raise pyric.error(pyric.EUNDEF, "Failed to process commands.help") finally: if cin: cin.close() attrpath = os.path.join(fpath, "attributes.help") attributes = None # attr -> desc, commands used by, datatype attrlookup = None # reverse lookup for attribute constants ain = None try: # first three lines are comments, 3th line is empty ain = open(attrpath, "r") for _ in range(4): _in = ain.readline() attributes = json.loads(ain.readline()) attrlookup = json.loads(ain.readline())
# where are we? fpath = os.path.dirname(os.path.realpath(__file__)) # read in the files here cmdpath = os.path.join(fpath,'commands.help') commands = None # cmd -> desc,attributes used dict cmdlookup = None # reverse lookup for command constants cin = None try: # first three lines are comments, 4th line is empty cin = open(cmdpath,'r') for _ in range(4): _in = cin.readline() commands = json.loads(cin.readline()) cmdlookup = json.loads(cin.readline()) except: raise pyric.error(pyric.EUNDEF,"Failed to process commands.help") finally: if cin: cin.close() attrpath = os.path.join(fpath,'attributes.help') attributes = None # attr -> desc, commands used by, datatype attrlookup = None # reverse lookup for attribute constants ain = None try: # first three lines are comments, 3th line is empty ain = open(attrpath,'r') for _ in range(4): _in = ain.readline() attributes = json.loads(ain.readline()) attrlookup = json.loads(ain.readline()) except: raise pyric.error(pyric.EUNDEF, "Failed to process attributes.help")