Esempio n. 1
0
 def checkipcconnectivity(self, ipaddress):
     """ Check IP connectovity with ipaddress
         returns True if connectivity with 'ipaddress' is ok
         returns False if connectivity with 'ipaddress' is impossible
     """
     os = OSshell(self.logname)
     # /bin/ping will retun 0 if there is ICMP echo response
     # will return 1 if there is NO ICMP echo response
     command_shell = ["/bin/ping", "-c2 -w1", ipaddress]
     status, result, errors = os.runoscommand(command_shell)
     # in Python 0 is False, but it's OK for ping
     # in Python 1 is True, but it's NOK for ping
     # so let's change the rule...
     return not result.returncode
Esempio n. 2
0
 def checkcurrentwlan(self, wlaninfo):
     """
     Check if the current, active connection to WLAN is equal to the requested by wlaninfo
     :param wlaninfo: WLAN parameters to check
     :return: [status, message]
     """
     # Attach to LOCAL SYSLOG
     logger = self.logger
     # Instantiate an OSshell object for calling the Operating System
     os = OSshell(self.logname)
     # Let's get current wlan
     command_shell = [
         "nmcli", "connection", "show", "--active", wlaninfo["ssid"]
     ]
     status, output, errors = os.runoscommand(command_shell)
     if status > 1:
         #Problem calling the Operating System
         return [
             2,
             "Problem scanning, could NOT receive information from active SSIDs..."
         ]
     else:
         p1 = output.stdout.decode("utf-8").strip()
         # Check if current ssid match with wlaninfo
         if wlaninfo["ssid"] in p1:
             # The ACTIVE ssid IS the one in wlaninfo
             # get detailed information about the current wlan
             associatedwlan = self.getAssociationInfo()
             """
             Esto tiene mucha miga...
             """
         else:
             # The ACTIVE ssid is NOT the one in wlaninfo
             logger.info(
                 "Current SSID is not equal to needed SSID <" +
                 str(wlaninfo["ssid"]) +
                 ">. Will have to disconnect and connect to the right one.")
             return [
                 3, "Current SSID is not equal to needed SSID <" +
                 str(wlaninfo["ssid"]) +
                 ">. Will have to disconnect and connect to the right one."
             ]
Esempio n. 3
0
class Wireless:
    """
        This module wraps the wireless interfaces in a system.
        Modify sudoers so the user of this script is part of sudoers AND
        NO PASSWORD IS REQUESTED:
        $ sudo visudo
        -> Add AT THE END OF THE FILE:
        <user>  ALL=(root) NOPASSWD: /sbin/iw, /usr/bin/nmcli, /usr/bin/lshw
        
        Example:
        bartolo     ALL=(root) NOPASSWD: /sbin/iw, /usr/bin/nmcli, /usr/bin/lshw
    """
    def __init__(self, logname="log"):
        """
            Initializate wireless
        """
        self.logname = logname + ".Wireless"
        self.logger = logging.getLogger(self.logname)
        self.logger.info("Logging initialization of Wireless. Done.")
        self.os = OSshell()
        self.wirelessinfo = self.getSystemWLANInfo()

    def getSystemWLANInfo(self):
        """
            Let's get all possible current information.
            Information is retrieved using:
            - Linux files
            - lshw
            - nmcli
            - iw
            Returns a list of dict/json object with RELEVANT information
            Each entry is a Wireless Interface, most probably will be just one
        """
        # Attach to LOCAL SYSLOG
        logger = self.logger

        wlaninfo = []

        # Let's get Hardware and Drivers information about wireless system
        # with the output of lshw
        command_shell = ["sudo", "/usr/bin/lshw", "-C", "network"]
        status, p1, errors = self.os.runoscommand(command_shell)

        if p1.returncode:
            # Pretty strange something was wrong with the call to lshw
            # so we can't get information... most probably is a Linux issue
            lshw_ok = False
        else:

            p2 = p1.stdout.decode("utf-8").strip().split("*-network")
            del p2[0]
            hw_wlan_interfaces = []
            for interface in p2:
                if "Wireless" in interface:
                    # This is a Wireless Interface
                    wlan_int = {}
                    for line in interface.strip().replace(": ",
                                                          ":").splitlines():
                        wlan_int[line.partition(":")
                                 [0].strip()] = line.partition(":")[2].strip()
                    hw_wlan_interfaces.append(wlan_int.copy())
        """
            hw_wlan_interfaces:
            [
                {
                    "description": "Wireless interface",
                    "product": "Wireless 8260",
                    "vendor": "Intel Corporation",
                    "physical id": "0",
                    "bus info": "pci@0000:01:00.0",
                    "logical name": "wlp1s0",
                    "version": "3a",
                    "serial": "a0:c5:89:33:20:66",
                    "width": "64 bits",
                    "clock": "33MHz",
                    "capabilities": "pm msi pciexpress bus_master cap_list ethernet physical wireless",
                    "configuration": "broadcast=yes driver=iwlwifi driverversion=4.13.0-25-generic firmware=31.560484.0 ip=192.168.1.4 latency=0 link=yes multicast=yes wireless=IEEE 802.11",
                    "resources": "irq:283 memory:df100000-df101fff"
                }
            ]
        """
        wlaninfo = hw_wlan_interfaces.copy()
        for wlan_interface in wlaninfo:
            wlan_interface["phy"] = "phy" + wlan_interface["physical id"]
            try:
                del wlan_interface['bus info']
            except KeyError:
                # missing key
                print(sys.exc_info())
            try:
                del wlan_interface['version']
            except KeyError:
                # missing key
                print(sys.exc_info())
            try:
                del wlan_interface['capabilities']
            except KeyError:
                # missing key
                print(sys.exc_info())
            try:
                del wlan_interface['resources']
            except KeyError:
                # missing key
                print(sys.exc_info())

        # Let' get current information about the wireless phys
        for wlan_interface in wlaninfo:

            command_shell = [
                "sudo", "/sbin/iw", "phy", wlan_interface["phy"], "info"
            ]

            status, p1, errors = self.os.runoscommand(command_shell)

            p2 = p1.stdout.decode("utf-8").strip()

            wlan_interface["Bands"] = p2.count("Band ")
            phy_info = p2

        # Let's get current regulatory domain
        for wlan_interface in wlaninfo:

            command_shell = ["sudo", "/sbin/iw", "reg", "get"]
            status, p1, errors = self.os.runoscommand(command_shell)

            p2 = p1.stdout.decode("utf-8").strip()

            control = False
            for line in p2.splitlines():

                if line.strip().startswith("phy#" +
                                           wlan_interface["physical id"]):
                    control = True

                if control:
                    if line.strip().startswith("country"):
                        wlan_interface["Country"] = line.strip().split(
                            "country ")[1].split(": ")[0]
                        wlan_interface["DFS"] = line.strip().split(
                            "country ")[1].split(": ")[1]

        self.wirelessinfo = wlaninfo.copy()

        return self.wirelessinfo

    def getAssociationInfo(self):
        """
            Return information about the association status
        """
        # Attach to LOCAL SYSLOG
        logger = self.logger

        # Let's get current association status
        for wlan_interface in self.wirelessinfo:

            command_shell = [
                "sudo", "/sbin/iw", "dev", wlan_interface["logical name"],
                "link"
            ]
            status, p1, errors = self.os.runoscommand(command_shell)

            p2 = p1.stdout.decode("utf-8").strip()

            if p2.startswith("Not"):
                # Not connected to WLAN
                wlan_interface["connected"] = False
            else:
                # Connected to WLAN
                wlan_interface["connected"] = True
                wlan_interface["connection"] = {}

                for line in p2.splitlines():
                    if line.lstrip('\t').startswith("Connected"):
                        wlan_interface["connection"]["bssid"] = line.split()[2]
                    elif line.lstrip('\t').startswith("SSID"):
                        wlan_interface["connection"]["SSID"] = line.split()[1]
                    elif line.lstrip('\t').startswith("signal"):
                        wlan_interface["connection"]["signal"] = line.split(
                        )[1]
                    elif line.lstrip('\t').startswith("tx"):
                        wlan_interface["connection"][
                            "tx_bitrate"] = line.split()[2]
                        try:
                            wlan_interface["connection"]["MCS"] = line.split(
                            )[5]
                        except:
                            wlan_interface["connection"]["MCS"] = "undefined"
                    elif line.lstrip('\t').startswith("dtim"):
                        wlan_interface["connection"]["dtim"] = line.split()[2]
                    elif line.lstrip('\t').startswith("beacon"):
                        wlan_interface["connection"]["beacon"] = line.split(
                        )[2]

                command_shell = [
                    "sudo", "/sbin/iw", "dev", wlan_interface["logical name"],
                    "info"
                ]
                status, p1, errors = self.os.runoscommand(command_shell)

                p2 = p1.stdout.decode("utf-8").strip()

                for line in p2.splitlines():
                    if line.strip().startswith("channel"):
                        wlan_interface["connection"]["channel"] = line.split(
                        )[1].strip()
                        wlan_interface["connection"]["width"] = line.split(
                        )[5].strip()
                        wlan_interface["connection"]["Freq"] = line.split(
                        )[2].strip("(")
                        wlan_interface["connection"][
                            "CenterFreq"] = line.split()[8].strip()
                        if wlan_interface["connection"]["Freq"].startswith(
                                "2"):
                            wlan_interface["connection"]["Band"] = "2G"
                        elif wlan_interface["connection"]["Freq"].startswith(
                                "5"):
                            wlan_interface["connection"]["Band"] = "5G"
                    elif line.lstrip('\t').startswith("txpower"):
                        wlan_interface["connection"]["txpower"] = line.split(
                        )[1].strip()

                command_shell = [
                    "ip", "a", "show", wlan_interface["logical name"]
                ]
                status, p1, errors = self.os.runoscommand(command_shell)

                p2 = p1.stdout.decode("utf-8").strip()

                for line in p2.splitlines():
                    if line.strip().startswith("inet "):
                        wlan_interface["connection"]["ipaddress"] = line.split(
                        )[1].split("/")[0]
                        wlan_interface["connection"]["mask"] = line.split(
                        )[1].split("/")[1]
                    elif line.strip().startswith("inet6 "):
                        wlan_interface["connection"]["ipv6"] = line.split(
                        )[1].split("/")[0]
                        wlan_interface["connection"]["mask6"] = line.split(
                        )[1].split("/")[1]

                command_shell = ["ip", "route", "list"]
                status, p1, errors = self.os.runoscommand(command_shell)

                p2 = p1.stdout.decode("utf-8").strip()

                for line in p2.splitlines():
                    if line.strip().startswith("default "):
                        wlan_interface["connection"]["gateway"] = line.split(
                        )[2]

        return self.wirelessinfo

    def checkSSIDnmcli(self, wlaninfo):
        """
            Check if all values from <wlaninfo> are setup in nmcli configured connections
            -> ssid
            -> band
            -> bssid
            -> auth_method
            -> eap
            -> phase2-auth
            
            return [status, True/False, message, [error number], [error message] ]
            
            status: 
                 1  -> Found, all OK
                 2  -> SSID present, wrong BAND
                 3  -> SSID present, wrong BSSID
                 4  -> SSID present, auth_method wrong
                 5  -> SSID present, eap wrong
                 6  -> SSID present, phase2-auth wrong
                 7  -> OPEN auth_method, connect from scratch
                 8  -> SSID not found
                 20 -> error calling operating system
        """

        # Attach to LOCAL SYSLOG
        logger = self.logger

        logger.info("Searching " + wlaninfo["ssid"] +
                    " in the list of nmcli connections...")
        command_shell = ["nmcli", "connection", "show", wlaninfo["ssid"]]
        status, p1, errors = self.os.runoscommand(command_shell)

        if status == 20:
            return [20, False, errors[0], errors[1], errors[2]]

        if p1.returncode:
            # ssid is not listed in the nmcli configured connections
            logger.info("SSID <" + wlaninfo["ssid"] +
                        "> NOT found in the list of nmcli connections.")
            return [
                8, False, "SSID <" + wlaninfo["ssid"] +
                "> NOT found in the list of nmcli connections."
            ]

        logger.info("SSID <" + wlaninfo["ssid"] +
                    "> found in the list of nmcli connections.")
        # ssid is IN the list, let's check other parameters
        p2 = p1.stdout.decode("utf-8").strip()

        # if auth_method is "open", return with error, forcing to connect from scratch
        if wlaninfo["auth_method"] == "open":
            return [
                7, False,
                "Authentication method is OPEN, so connect from scratch."
            ]

        # Let's adapt some formats and variables
        band = wlaninfo["band"]
        if wlaninfo["band"] == "auto": band = "--"
        bssid = wlaninfo["bssid"]
        if wlaninfo["bssid"] == "auto": bssid = "--"

        test = {
            "band": False,
            "bssid": False,
            "auth_method": False,
            "eap": False,
            "phase2-auth": False
        }

        extract = {
            "band": "",
            "bssid": "",
            "auth_method": "",
            "eap": "",
            "phase2-auth": "",
            "phase2-autheap": ""
        }

        for line in p2.splitlines():

            if line.startswith("802-11-wireless.band"):
                extract["band"] = line.split(":")[1].strip()
                continue
            if line.startswith("802-11-wireless.bssid"):
                extract["bssid"] = line.split(":")[1].strip()
                continue
            if line.startswith("802-11-wireless-security.key-mgmt"):
                extract["auth_method"] = line.split(":")[1].strip()
                continue
            if line.startswith("802-1x.eap"):
                extract["eap"] = line.split(":")[1].strip()
                continue
            if line.startswith("802-1x.eap"):
                extract["eap"] = line.split(":")[1].strip()
                continue
            if line.startswith("802-1x.phase2-autheap"):
                extract["phase2-autheap"] = line.split(":")[1].strip()
                continue
            if line.startswith("802-1x.phase2-auth"):
                extract["phase2-auth"] = line.split(":")[1].strip()
                continue

        # check band
        if extract["band"] == band:
            # band is OK
            logger.info("Configured RIGHT band <" + wlaninfo["band"] +
                        "> in nmcli connection.")
            test["band"] = True
        else:
            # band NO OK
            logger.info("Configured band <" + wlaninfo["band"] +
                        "> in nmcli connection is WRONG.")
            status = 2
            msg = "Band is wrong"

        # check bssid
        if extract["bssid"] == bssid:
            # bssid is OK
            logger.info("Configured RIGHT bssid <" + wlaninfo["bssid"] +
                        "> in nmcli connection.")
            test["bssid"] = True
        else:
            # bssid NO OK
            logger.info("Configured bssid <" + wlaninfo["bssid"] +
                        "> in nmcli connection is WRONG.")
            status = 3
            msg = "bssid is wrong"

        # check auth_method, supported psk and 802.1x
        if extract["auth_method"] == wlaninfo["auth_method"]:
            # auth_method is OK
            logger.info("Configured RIGHT auth_method <" +
                        wlaninfo["auth_method"] + "> in nmcli connection.")
            test["auth_method"] = True

            if wlaninfo["auth_method"] == "wpa-psk":
                # auth_method is PSK... nothing else to do
                test["eap"] = True
                test["phase2-auth"] = True

            else:
                # auth_method is 802.1x, have to check EAP and EAP-PHASE2-AUTHENTICATION
                if extract["eap"] == wlaninfo["eap"]:
                    logger.info("Configured RIGHT EAP <" + wlaninfo["eap"] +
                                "> in nmcli connection.")
                    test["eap"] = True

                    # Check EAP-PHASE2-AUTHENTICATION, peap and ttls supported
                    if wlaninfo["eap"] == "ttls":
                        # EAP is TTLS
                        # supported phase2 is mschapv2, it's stored in attribute 802-1x.phase2-autheap for ttls
                        if extract["phase2-autheap"] == wlaninfo[
                                "phase2-auth"]:
                            # phase2 is right
                            logger.info(
                                "Configured RIGHT EAP Phase2 Authentication <"
                                + wlaninfo["phase2-auth"] +
                                "> in nmcli connection.")
                            test["phase2-auth"] = True
                        else:
                            # phase2 is wrong
                            logger.info(
                                "Configured EAP Phase2 Authentication <" +
                                wlaninfo["phase2-auth"] +
                                "> in nmcli connection is WRONG.")
                            status = 6
                            msg = "EAP Phase2 Authentication is wrong"
                    else:
                        # EAP is PEAP
                        # supported phase2 is mschapv2, it's stored in attribute 802-1x.phase2-auth for peap
                        if extract["phase2-auth"] == wlaninfo["phase2-auth"]:
                            # phase2 is right
                            logger.info(
                                "Configured RIGHT EAP Phase2 Authentication <"
                                + wlaninfo["phase2-auth"] +
                                "> in nmcli connection.")
                            test["phase2-auth"] = True
                        else:
                            # phase2 is wrong
                            logger.info(
                                "Configured EAP Phase2 Authentication <" +
                                wlaninfo["phase2-auth"] +
                                "> in nmcli connection is WRONG.")
                            status = 6
                            msg = "EAP Phase2 Authentication is wrong"

                else:
                    logger.info("Configured EAP <" + wlaninfo["eap"] +
                                "> in nmcli connection is WRONG.")
                    status = 5
                    msg = "EAP is wrong (not TTLS/PEAP)"
        else:
            # auth_method is NO OK
            logger.info("Configured auth_method <" + wlaninfo["auth_method"] +
                        "> in nmcli connection is WRONG.")
            status = 4
            msg = "Authentication method is wrong (not Open/PSK/802.1X)"

        # Let's define an OK Dict, in order to compare with the results
        test_ok = {
            "band": True,
            "bssid": True,
            "auth_method": True,
            "eap": True,
            "phase2-auth": True
        }

        if test == test_ok:
            # PERFECT, connection in nmcli is ok.
            logger.info(
                "The nmcli connection is OK, all connection options are set up according to the requierement !!!"
            )
            return [1, True, "Connection in nmcli is ok."]
        else:
            # One or more parameters are wrong
            logger.info(
                "The nmcli connection is NO OK, one or more connection options are NOT properly configured..."
            )
            return [status, False, msg]

    def scanWLAN(self):
        return

    def addConnectionnmcli(self, wlaninfo):
        """
            Let's configure or modify a connection in nmcli

            wlaninfo = {
                "ssid":"Temp",
                "status":"enable",
                "band":"auto",
                "bssid":"auto",
                "auth_method":"wpa-psk",
                "eap":"",
                "psk":"password-psk",
                "ipconfig":"dhcp",
                "ipaddress":"",
                "netmask":"",
                "gateway":"",
                "dns1":"",
                "dns2":""
            }

            nmcli connection add 
                type wifi 
                con-name "Rivendel" 
                ifname wlp1s0 
                ssid "Rivendel" 
                802-11-wireless.band [a , bg]
                802-11-wireless.bssid 18:64:72:EA:F0:F2
                wifi-sec.key-mgmt wpa-eap 
                802-1x.eap peap 
                802-1x.identity "jorge" 
                802-1x.password "password" 
                802-1x.phase2-auth mschapv2 
                ipv4.method auto

            return [status, msg, errors]
                status:
                    1  -> OK, connection successfully added
                    2  -> NO OK, connection could not be added to nmcli
                    20 -> error calling operating system
            
        """
        import ipaddress

        # Attach to LOCAL SYSLOG
        logger = self.logger

        logger.info("Adding or modifying a connection in nmcli...")

        # Let's delete the connection, just in case
        command_shell = ["nmcli", "connection", "delete", wlaninfo["ssid"]]
        status, output, errors = self.os.runoscommand(command_shell)

        if status == 20:
            # OS error calling nmcli
            logger.info("Error deleting existing connection in nmcli...")

        # Let's add the connection with the options in wlaninfo
        command_shell = ["nmcli", "connection", "add"]
        command_shell += ["type", "wifi"]
        command_shell += ["con-name", wlaninfo["ssid"]]

        # what interface to use, in case several interfaces
        if len(self.wirelessinfo) > 1:
            # Have several WLAN interfaces in the sensor
            logger.info("Several WLAN interfaces, choosing the right one...")
            if wlaninfo["band"] == "a":
                # 5GHz band, have to select a 5GHz capable interface
                logger.info("Interface must support 5GHz band... searching...")
                interface_ok = False
                for wlaninterface in self.wirelessinfo:
                    if wlaninterface["Bands"] == 2:
                        # This interface is 5GHz capable
                        logger.info("Found interface capable of 5GHz: <" +
                                    str(wlaninterface["logical name"]) + ">.")
                        command_shell += [
                            "ifname", wlaninterface["logical name"]
                        ]
                        interface_ok = True
                        break
                if not interface_ok:
                    # It's not possible to run the TEST in 5GHz...
                    # none of the available interfaces can support 5GHz
                    # Let's use the first one available
                    logger.info(
                        "None of the available WLAN interfaces support 5GHz, connection will default to <auto>"
                    )
                    logger.info("Interface to use <" +
                                str(self.wirelessinfo[0]["logical name"]) +
                                ">.")
                    command_shell += [
                        "ifname", self.wirelessinfo[0]["logical name"]
                    ]

            else:  # wlaninfo["band"] == "auto" or "bg"
                # Choose any (the first for instance) as Band doesn't matter
                logger.info(
                    "Band is auto or bg, interface capabilities are not important, choosing the first available WLAN interface."
                )
                logger.info("Interface to use <" +
                            str(self.wirelessinfo[0]["logical name"]) + ">.")
                command_shell += [
                    "ifname", self.wirelessinfo[0]["logical name"]
                ]

        else:
            # Just one WLAN interface
            logger.info("Only one interface in the SENSOR, using it.")
            logger.info("Interface to use <" +
                        str(self.wirelessinfo[0]["logical name"]) + ">.")
            command_shell += ["ifname", self.wirelessinfo[0]["logical name"]]

        # SSID
        command_shell += ["ssid", wlaninfo["ssid"]]

        # BAND
        if wlaninfo["band"] == "auto":
            logger.info("Setting BAND to auto...")
            # No need to add a band, let the OS and AP negotiate
        else:  # Assign the band
            logger.info("Setting BAND to <" + str(wlaninfo["band"]) + ">...")
            command_shell += ["802-11-wireless.band", wlaninfo["band"]]

        # BSSID or Virtul-AP or VAP
        if wlaninfo["bssid"] == "auto":
            logger.info("Setting BSSID to auto...")
            # No need to add a BSSID, OS and AP will negotiate
        else:  # Assign the bssid
            logger.info("Setting BSSID to <" + str(wlaninfo["bssid"]) + ">...")
            command_shell += ["802-11-wireless.bssid", wlaninfo["bssid"]]

        # Authentication
        if wlaninfo["auth_method"] == "open":
            logger.info("Setting authentication to OPEN...")
            # No need to add anything else
        elif wlaninfo["auth_method"] == "wpa-psk":
            # Pre-Shared Key with AES
            logger.info(
                "Setting authentication to PreShared Key and AES (WPA2-PSK)..."
            )
            command_shell += [
                "802-11-wireless-security.key-mgmt", wlaninfo["auth_method"]
            ]
            command_shell += ["802-11-wireless-security.psk", wlaninfo["psk"]]
        else:
            # 802.1X Authentication - wpa-eap
            logger.info("Setting authentication to 802.1X...")
            command_shell += [
                "802-11-wireless-security.key-mgmt", wlaninfo["auth_method"]
            ]
            if wlaninfo["eap"] == "peap":
                # EAP is PEAP
                logger.info("Setting EAP method to <" + str(wlaninfo["eap"]) +
                            ">...")
                command_shell += ["802-1x.eap", wlaninfo["eap"]]
                logger.info("Setting USERNAME and PASSWORD for PEAP...")
                command_shell += ["802-1x.identity", wlaninfo["username"]]
                command_shell += ["802-1x.password", wlaninfo["password"]]
                logger.info("Setting Phase2 to <" +
                            str(wlaninfo["phase2-auth"]) + ">...")
                command_shell += [
                    "802-1x.phase2-auth", wlaninfo["phase2-auth"]
                ]
            else:
                # EAP is TTLS
                logger.info("Setting EAP method to <" + str(wlaninfo["eap"]) +
                            ">...")
                command_shell += ["802-1x.eap", wlaninfo["eap"]]
                logger.info("Setting USERNAME and PASSWORD for PEAP...")
                command_shell += ["802-1x.identity", wlaninfo["username"]]
                command_shell += ["802-1x.password", wlaninfo["password"]]
                logger.info("Setting Phase2 to <" +
                            str(wlaninfo["phase2-auth"]) + ">...")
                command_shell += [
                    "802-1x.phase2-autheap", wlaninfo["phase2-auth"]
                ]

        # IPv4 Configuration
        if wlaninfo["ipconfig"] == "dhcp":
            # auto configuration
            logger.info("Setting IPv4 configuration to <" +
                        str(wlaninfo["ipconfig"]) + ">...")
            command_shell += ["ipv4.method", "auto"]
        else:
            # manual configuration
            logger.info("Setting IPv4 configuration to <" +
                        str(wlaninfo["ipconfig"]) + ">...")
            command_shell += ["ipv4.method", "manual"]
            # IPv4 address
            ip_interface = ipaddress.IPv4Interface(wlaninfo["ipaddress"] +
                                                   "/" + wlaninfo["netmask"])
            logger.info("Setting IPv4 address to <" + str(ip_interface) +
                        ">...")
            command_shell += ["ipv4.addresses", str(ip_interface)]
            # IPv4 gateway
            gateway = ipaddress.IPv4Address(wlaninfo["gateway"])
            logger.info("Setting IPv4 Gateway to <" +
                        str(wlaninfo["gateway"]) + ">...")
            if not gateway in ip_interface.network:
                logger.warning(
                    "Gateway IPv4 address is not in the network range... Setting gateway in any case."
                )
            command_shell += ["ipv4.gateway", str(gateway)]
            # IPv4 DNS
            if wlaninfo["dns2"] == "":
                # Only one DNS server
                dns = wlaninfo["dns1"]
            else:
                # Two DNS servers
                dns = wlaninfo["dns1"] + "," + wlaninfo["dns2"]
            logger.info("Setting IPv4 DNS to <" + str(dns) + ">...")
            command_shell += ["ipv4.dns", dns]

        # Command to call nmcli is complete
        logger.info("nmcli command before calling runOSCommand <" +
                    str(command_shell) + ">.")
        logger.info(
            "Calling Operating System to add connection to nmcli connections list..."
        )
        status, output, errors = self.os.runoscommand(command_shell)

        if status > 1:
            # Something went wrong calling the Operating System
            logger.warning("ERROR calling nmcli to add <" +
                           str(wlaninfo["ssid"]) +
                           "> to the list of nmcli connections...")
            logger.warning(str(output))
            logger.warning(str(errors[0]))
            logger.warning(str(errors[1]))
            logger.warning(str(errors[2]))
            return [20, output, errors]
        else:
            # Call to OS was right, let's see the result of calling nmcli
            if output.returncode == 0:
                # New connection successfully added to the list of nmcli connections
                logger.info("SUCCESS - connection <" + str(wlaninfo["ssid"]) +
                            "> added to the list of nmcli connections.")
                return [1, output, errors]
            else:
                # Some problem with the call to nmcli
                logger.info("<" + str(wlaninfo["ssid"]) +
                            "> added to the list of nmcli connections.")
                logger.info(str(output))
                return [2, output, errors]

    def checkSSIDair(self, wlaninfo, force_scan=False):
        """
            Check if the ssid in wlaninfo is present in the "air"
            Will use default information from kernel, from last scans
            If force_scan=True, try to rescan
            
            nmcli device wifi rescan
            nmcli -f signal,ssid,bssid,chan,in-use device wifi
            
        """
        import subprocess
        import sys

        # Attach to LOCAL SYSLOG
        logger = self.logger

        # Depending on force_scan will force rescan
        if force_scan:
            # Force to scan
            command_shell = ["nmcli", "device", "wifi", "rescan"]
            status, output, errors = self.os.runoscommand(command_shell)
#            if status > 1:
#                # Problem with the Operating System
#                # using information stored in the kernel from last scans
#            else:
#                # Call OK to Operating System
#                if output.returncode == 1:
#                    # Too frequent scans

# Calling scan results
        command_shell = [
            "nmcli", "-f", "ssid,bssid,signal,chan,in-use", "device", "wifi"
        ]
        status, output, errors = self.os.runoscommand(command_shell)
        if status > 1:
            #Problem calling the Operating System
            return [
                2,
                "Problem scanning, could NOT receive information from active SSIDs..."
            ]
        else:
            p2 = output.stdout.decode("utf-8").strip()
            if wlaninfo["ssid"] in p2:
                return [
                    1, "SSID <" + wlaninfo["ssid"] +
                    "> is in the list of visible SSIDs."
                ]

    def checkcurrentwlan(self, wlaninfo):
        """
        Check if the current, active connection to WLAN is equal to the requested by wlaninfo
        :param wlaninfo: WLAN parameters to check
        :return: [status, message]
        """
        # Attach to LOCAL SYSLOG
        logger = self.logger
        # Instantiate an OSshell object for calling the Operating System
        os = OSshell(self.logname)
        # Let's get current wlan
        command_shell = [
            "nmcli", "connection", "show", "--active", wlaninfo["ssid"]
        ]
        status, output, errors = os.runoscommand(command_shell)
        if status > 1:
            #Problem calling the Operating System
            return [
                2,
                "Problem scanning, could NOT receive information from active SSIDs..."
            ]
        else:
            p1 = output.stdout.decode("utf-8").strip()
            # Check if current ssid match with wlaninfo
            if wlaninfo["ssid"] in p1:
                # The ACTIVE ssid IS the one in wlaninfo
                # get detailed information about the current wlan
                associatedwlan = self.getAssociationInfo()
                """
                Esto tiene mucha miga...
                """
            else:
                # The ACTIVE ssid is NOT the one in wlaninfo
                logger.info(
                    "Current SSID is not equal to needed SSID <" +
                    str(wlaninfo["ssid"]) +
                    ">. Will have to disconnect and connect to the right one.")
                return [
                    3, "Current SSID is not equal to needed SSID <" +
                    str(wlaninfo["ssid"]) +
                    ">. Will have to disconnect and connect to the right one."
                ]

    def connectWLAN(self, wlaninfo):
        """
            Connects with indicated wlan network, using wlaninfo:
            
            wlaninfo = {
                "ssid":"Temp",
                "status":"enable",
                "band":"auto",
                "vap":"auto",
                "auth_method":"wpa-psk",
                "eap":"",
                "psk":"password-psk",
                "ipconfig":"dhcp",
                "ipaddress":"",
                "netmask":"",
                "gateway":"",
                "dns1":"",
                "dns2":""
            }
        """
        import subprocess
        import sys

        # Attach to LOCAL SYSLOG
        logger = self.logger

        # Check if wlaninfo is ENABLED... otherwise return
        if wlaninfo["status"] == "disable":
            # WLAN network disabled, no connection to make
            logger.info(
                "WLAN <" + str(wlaninfo["ssid"]) +
                ">, administrative disable. No connection will be made.")
            return [
                6, "WLAN <" + str(wlaninfo["ssid"]) +
                ">, administrative disable. No connection will be made."
            ]

        # Let's check if all configured paramenters for the ssid
        # are already in the list of nmcli connections
        logger.info("Check if " + wlaninfo["ssid"] +
                    " is in the nmcli already configured connections...")
        if self.checkSSIDnmcli(wlaninfo)[0] > 1:
            # Not in the list or some parameter is wrong
            logger.info("Let's configure the connection in nmcli...")
            if self.addConnectionnmcli(wlaninfo)[0] > 1:
                # Could NOT add the connection to nmcli... have to return with no results
                return [2, "Could NOT create a connection in nmcli."]

        # WLAN network in wlaninfo is already available in the list of nmcli connections
        # logger.info("WLAN network <" + str(wlaninfo["ssid"]) + "> available in the list of nmcli connections...")

        # Check that the WLAN network is present in the air
        logger.info("Checking that <" + str(wlaninfo["ssid"]) +
                    "> is seen in the air...")
        if self.checkSSIDair(wlaninfo, True)[0] > 1:
            # SSID not found in the list of visible SSIDs
            logger.warning("SSID <" + str(wlaninfo["ssid"]) +
                           ">, NOT RF visible... CAN'T CONNECT")
            return [
                3, "SSID <" + wlaninfo["ssid"] +
                ">, NOT visible in the last scanned... CAN'T CONNECT"
            ]
        logger.info("SSID <" + str(wlaninfo["ssid"]) +
                    "> is RF visible... can connect.")

        #Check if the current connection is right
        logger.info(
            "Checking if current connection is ok, so can be used without modification..."
        )

        # Connect
        logger.info("Connecting with the SSID <" + str(wlaninfo["ssid"]) +
                    ">...")
        command_shell = ["nmcli", "connection", "up", wlaninfo["ssid"]]
        status, output, errors = self.os.runoscommand(command_shell)

        if status > 1:
            # ERROR calling Operating System
            logger.info(
                "ERROR calling the Operating System for connecting to the right SSID."
            )
            return [
                4,
                "ERROR in the Operating System call when changing to the SSID."
            ]
        else:
            if output.returncode == 0:
                # SUCCESS!!! Connected to SSID
                logger.info("SUCCESS!!! Successfully connected to SSID <" +
                            str(wlaninfo["ssid"]) + ">.")
                return [1, output.stdout.decode("utf-8").strip()]
            else:
                # Problem in nmcli
                logger.info("Problem in nmcli connecting to SSID <" +
                            str(wlaninfo["ssid"]) + ">.")
                return [5, output.stdout.decode("utf-8").strip()]

    def pprint(self):
        import json
        return print(json.dumps(self.wirelessinfo, indent=2))
Esempio n. 4
0
    def runudptest(self, testinfo):
        """
            Let's run the UDP tests with the servers from testinfo
            Using iperf3 for jitter and packet loss
            {
                "test":"packetLoss",
                "testid":3,
                "status":"enable",
                "test_server_ip":"192.168.1.5",
                "test_server_port":"5201",
                "test_server_name":"Packet-loss Server",
                "test_server_udp_bandwidth":"10M",
                "test_server_udp_time": "10",
                "test_server_udp_interval": "10"
            }
        """
        import time
        import json

        # Attach to LOCAL SYSLOG
        logger = self.logger
        logger.info("Starting Packet Loss and Jitter test with <" +
                    str(testinfo["test_server_name"]) + "> server [" +
                    str(testinfo["test_server_ip"]) + ":" +
                    str(testinfo["test_server_port"]) + "]")
        # Instantiate an OSshell for calling the OS
        os = OSshell(self.logname)
        # Let's PING the TEST SERVERS, for ARP and DNS resolution and cache
        logger.info(
            "Will now ping test server for caching MAC and DNS... (avoiding false results)"
        )
        if not self.checkipcconnectivity(testinfo["test_server_ip"]):
            # Server NOT reachable... skip this test
            logger.error(
                "ERROR: Test Server: <" + str(testinfo["test_server_ip"]) +
                "> is NOT IP reachable... Will skip this Packet Loss and Jitter Test."
            )
            return [2, "Test Server not IP reachable..."]
        else:
            # Ping success, now it must be in ARP table
            logger.info("Test Server: <" + str(testinfo["test_server_ip"]) +
                        "> is now in ARP/DNS cache.")
            logger.info("Running the Packet Loss and Jitter test...")
            # Call iperf3
            command_shell = [
                "/usr/bin/iperf3", "--client", testinfo["test_server_ip"],
                "--udp", "--interval", testinfo["test_server_udp_interval"],
                "--time", testinfo["test_server_udp_time"], "--bandwidth",
                testinfo["test_server_udp_bandwidth"], "--json"
            ]
            status, result, errors = os.runoscommand(command_shell)
            # Get timestamp when test finished
            timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
            # Check test result
            if result.returncode:
                # Server down, unreachable
                logger.error(
                    "ERROR: UDP (Packet Loss and Jitter) Test FAILURE with Test Server <"
                    + testinfo["test_server_ip"] +
                    ">. Not reachable for testing...")
                logger.debug("ERROR: " + result.stdout.decode("utf-8"))
                logger.debug("ERROR: " + str(errors))
                return [
                    3,
                    "Iperf3 service was NOT ready in Server when running the test..."
                ]
            else:
                # UDP Test SUCCESS !!!!
                logger.info("SUCCESS!!! UDP Test with server <" +
                            testinfo["test_server_ip"] +
                            "> successfully done.")
                # Adapt the output, so only contains relevant information
                # and add Timestamp
                output = {}
                j1 = json.loads(result.stdout.decode("utf-8"))
                output = j1["end"]["streams"][0]["udp"]
                output["timestamp"] = timestamp
                output["testid"] = testinfo["testid"]
                output["status"] = "ok"
                """
                output =    {
                            "timestamp": "Thu, 28 Dec 2017 16:16:52 GMT",
                            "testid":3,
                            "status": "ok"
                            "socket": 4,
                            "start": 0,
                            "end": 10.000331,
                            "seconds": 10.000331,
                            "bytes": 12386304,
                            "bits_per_second": 9908715.059617,
                            "jitter_ms": 0.171,
                            "lost_packets": 2,
                            "packets": 1512,
                            "lost_percent": 0.132275,
                            "out_of_order": 0
                        }
                """
                logger.info("UDP (Packet Loss and Jitter) measurements: <" +
                            str(output) + ">")
                return [1, output]
Esempio n. 5
0
    def rundelaytest(self, testinfo):
        """
            Let's run the delay test with the information in testinfo
            Using ping for round-trip time delay
            {
                "test":"delay",
                "testid":2,
                "status":"enable",
                "test_server_ip":"192.168.1.5",
                "test_server_name":"Delay Test Server",
                "test_server_delay_packets_to_send":"50"
            }
        """
        import time
        import json

        # Attach to LOCAL SYSLOG
        logger = self.logger
        logger.info("Starting DELAY test with <" +
                    str(testinfo["test_server_name"]) + "> server [" +
                    str(testinfo["test_server_ip"]) + "]")
        # Instantiate an OSshell for calling the OS
        os = OSshell(self.logname)

        # Let's PING the TEST SERVERS, for ARP and DNS resolution and cache
        logger.info(
            "Will now ping test server for caching MAC and DNS... (avoiding false results)"
        )
        if not self.checkipcconnectivity(testinfo["test_server_ip"]):
            # Server NOT reachable... skip this test
            logger.error("ERROR: Test Server: <" +
                         str(testinfo["test_server_ip"]) +
                         "> is NOT IP reachable... Will skip this DELAY Test.")
            return [2, "Test Server not IP reachable..."]
        else:
            # Ping success, now it must be in ARP table
            logger.info("Test Server: <" + str(testinfo["test_server_ip"]) +
                        "> is now in ARP/DNS cache.")
            logger.info("Running the DELAY test...")
            """
            # Now let's run the delay test...
            # using regular ping tool
            # For better accuracy, a NTP timestamped TCP flow, avoiding IP fragmentation, is preferred... 
            # but for now let's use ping
            # ping -A -q -c 20 <IPADDRESS>
                # -A        -> wait for echo response and send new packet, instead of default 1 second between packets
                # -q        -> run in quiet mode, reporting the statistics at the end
                # -c 20    -> send 20 echo request
            # Adding the results to the output:
            """
            command_shell = [
                "/bin/ping", "-A", "-q", "-c",
                testinfo["test_server_delay_packets_to_send"],
                testinfo["test_server_ip"]
            ]
            status, result, errors = os.runoscommand(command_shell)
            # Get timestamp when test finished
            timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
            # Check test result
            if result.returncode:
                # Server down, unreachable
                logger.error("ERROR: DELAY Test FAILURE with Test Server <" +
                             testinfo["test_server_ip"] +
                             ">. Not reachable for testing...")
                logger.debug("ERROR: " + result.stdout.decode("utf-8"))
                logger.debug("ERROR: " + str(errors))
                return [
                    3, "DELAY server was NOT ready when running the test..."
                ]
            else:
                # Delay test SUCCESS !!
                logger.info("SUCCESS!!! DELAY Test with server <" +
                            testinfo["test_server_ip"] +
                            "> successfully done.")
                # Adapt the output, so only contains relevant information
                # and add Timestamp
                """
                    Content of ping output  - p1.stdout.decode("utf-8")
                    [0]PING 192.168.1.54 (192.168.1.54) 56(84) bytes of data.
                    [1]
                    [2]--- 192.168.1.54 ping statistics ---
                    [3]20 packets transmitted, 20 received, 0% packet loss, time 3812ms
                    [4]rtt min/avg/max/mdev = 2.804/42.068/202.262/47.512 ms, pipe 2, ipg/ewma 200.652/32.505 ms
                """
                output = {}
                p2 = result.stdout.decode("utf-8").splitlines()
                output["timestamp"] = timestamp
                output["testid"] = testinfo["testid"]
                output["status"] = "ok"
                output["d_packets_sent"] = p2[3].split()[0]
                output["d_packets_received"] = p2[3].split()[3]
                output["d_packet_loss"] = str(
                    int(p2[3].split()[0]) - int(p2[3].split()[3]))
                output["d_packet_loss_percent"] = float(
                    p2[3].split()[5].strip("%"))
                output["d_time"] = p2[3].split()[9].strip("ms")
                output["d_rtt_min_ms"] = float(p2[4].split()[3].split("/")[0])
                output["d_rtt_avg_ms"] = float(p2[4].split()[3].split("/")[1])
                output["d_rtt_max_ms"] = float(p2[4].split()[3].split("/")[2])
                output["d_rtt_mdev_ms"] = float(p2[4].split()[3].split("/")[3])
                output["d_ipg_ms"] = float(p2[4].split()[len(p2[4].split()) -
                                                         2].split("/")[0])
                output["d_ewma_ms"] = float(p2[4].split()[len(p2[4].split()) -
                                                          2].split("/")[1])
                """
                output = {
                            "timestamp": "Thu, 28 Dec 2017 16:16:52 GMT",
                            "testid":2,
                            "status": "ok",
                            "d_packets_sent": "20",
                            "d_packets_received": "20",
                            "d_packet_loss": "0",
                            "d_packet_loss_percent": "0",
                            "d_time": "3812",
                            "d_rtt_min_ms": "2.804",
                            "d_rtt_avg_ms": "42.068",
                            "d_rtt_max_ms": "202.262",
                            "d_rtt_mdev_ms": "47.512",
                            "d_ipg_ms": "200.652",
                            "d_ewma_ms": "32.505"
                        }
                """
                logger.info("Delay measurements: <" + str(output) + ">")
                return [1, output]
Esempio n. 6
0
    def runbandwidthtest(self, testinfo):
        """
            Let's run the iperf3 Bandwidth tests with the info in testinfo
            {
                "test":"bandwidth",
                "testid":1
                "status":"enable",
                "test_server_ip":"192.168.1.5",
                "test_server_port":"5201",
                "test_server_name":"Local - iperf3 Local"
            }
            return [status, result]
                status:
                1 -> OK
                2 -> Test server NOT IP reachable
                3 -> Iperf3 service not ready in the server when running the test
                result:
                {
                    "timestamp": "2017-12-28 18:43:17",
                    "testid": 1,
                    "socket": 4,
                    "start": 0,
                    "end": 10.000525,
                    "seconds": 10.000525,
                    "bytes": 444473728,
                    "bits_per_second": 355560315.564814,
                    "retransmits": 0,
                    "max_snd_cwnd": 3075552,
                    "max_rtt": 14185,
                    "min_rtt": 5595,
                    "mean_rtt": 9152
                }
        """
        import time
        import json

        # Attach to LOCAL SYSLOG
        logger = self.logger
        logger.info("Starting BANDWIDTH test with <" +
                    str(testinfo["test_server_name"]) + "> server [" +
                    str(testinfo["test_server_ip"]) + ":" +
                    str(testinfo["test_server_port"]) + "]")
        # Instantiate an OSshell for calling the OS
        os = OSshell(self.logname)
        # Let's PING the TEST SERVERS, for ARP and DNS resolution and cache
        logger.info(
            "Will now ping test server for caching MAC and DNS... (avoiding false results)"
        )
        if not self.checkipcconnectivity(testinfo["test_server_ip"]):
            # Server NOT reachable... skip this test
            logger.error(
                "ERROR: Test Server: <" + str(testinfo["test_server_ip"]) +
                "> is NOT IP reachable... Will skip this TCP Bandwidth Test.")
            return [2, "Test Server not IP reachable..."]
        else:
            # Ping success, now it must be in ARP table
            logger.info("Test Server: <" + str(testinfo["test_server_ip"]) +
                        "> is now in ARP/DNS cache.")
            logger.info("Running the TCP Bandwidth test...")
            # Call iperf3
            command_shell = [
                "/usr/bin/iperf3", "--client", testinfo["test_server_ip"]
            ]
            command_shell += ["--port", testinfo["test_server_port"], "--json"]
            status, result, errors = os.runoscommand(command_shell)
            # Get timestamp when test finished
            timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
            # Check test result
            if result.returncode:
                # Server down, unreachable
                logger.error("ERROR: TCP Test FAILURE with Test Server <" +
                             testinfo["test_server_ip"] +
                             ">. Not reachable for testing...")
                logger.debug("ERROR: " + result.stdout.decode("utf-8"))
                logger.debug("ERROR: " + str(errors))
                return [
                    3,
                    "Iperf3 service was NOT ready in Server when running the test..."
                ]
            else:
                # TCP Test SUCCESS !!!!
                logger.info("SUCCESS!!! TCP Test with server <" +
                            testinfo["test_server_ip"] +
                            "> successfully done.")
                # Adapt the output, so only contains relevant information
                # and add Timestamp
                j1 = json.loads(result.stdout.decode("utf-8"))
                output = j1["end"]["streams"][0]["sender"]
                output["timestamp"] = timestamp
                output["testid"] = testinfo["testid"]
                output["status"] = "ok"
                """
                    output = {
                                "timestamp": "2017-12-28 18:43:17",
                                "testid":1,
                                "status": "ok",
                                "socket": 4,
                                "start": 0,
                                "end": 10.000525,
                                "seconds": 10.000525,
                                "bytes": 444473728,
                                "bits_per_second": 355560315.564814,
                                "retransmits": 0,
                                "max_snd_cwnd": 3075552,
                                "max_rtt": 14185,
                                "min_rtt": 5595,
                                "mean_rtt": 9152
                            }
                """
                logger.info("TCP measurements: <" + str(output) + ">")
                return [1, output]