Ejemplo n.º 1
0
    def append_from_file(self, input_file_str):
        linelist = file_to_list(input_file_str)

        for line in linelist:
            result = [word.strip() for word in line.split(' ')]

            if len(result) != 3:
                self.__table['ERROR'] = self.addrflag('MALFORMED', 'ENTRY')
                
                msg = 'Input \'{}{}{}\' from file \'{}{}{}\' is malformed. Unable to add entry to table.\n'.format(K.color.bold.WHT, line, K.NRM, K.color.bold.WHT, input_file_str, K.NRM)

                log(logstat.ERR, funcname(), msg)
            else:
                if result[2] == DNS_table.flag.NS.value and self.__ts_hostname == '__NONE__':
                    self.__ts_hostname = result[0]

                    msg = 'ts_hostname assigned as \'{}{}{}\'.'.format(K.color.bold.WHT, result[0], K.NRM)

                    log(logstat.LOG, funcname(), msg)
                elif result[2] == DNS_table.flag.A.value:
                    self.__table[result[0]] = self.addrflag(result[1], result[2])

                    msg = '{}\'{} : ({}, {}){}\' added to table from file {}\'{}\'{}.'.format(K.color.bold.WHT, result[0], result[1], result[2], K.NRM, K.color.bold.WHT, input_file_str, K.NRM)

                    log(logstat.LOG, funcname(), msg)
        
        print('')       
Ejemplo n.º 2
0
def is_valid_hostname(hostname):
    """Uses gethostbyname to determine if hostname valid, or not

        Args:
            hostname: str
                desired hostname to verify
        Returns:
            str representing the IP address of the validated hostname;
            if hostname is invalid, returns None
        Raises:
            EnvironmentError if hostname is invalid (gethostbyname fails)
    """
    try:
        ipaddr = gethostbyname(hostname)
    except EnvironmentError:
        msg = 'Host by name \'{}{}{}\' is not available.\n'.format(K.color.bold.WHT, ls_hostname, K.NRM)
        log(logstat.ERR, funcname(), msg)

        return None
    
    msg = 'Verified hostname and IP address ({}{}{} : {}{}{})\n'.format(K.color.CYN, hostname, K.NRM, K.color.CYN, ipaddr, K.NRM)

    log(logstat.OK, funcname(), msg)

    return ipaddr
Ejemplo n.º 3
0
def main(argv):
    """Main function, where client function is called

        Args:
            Command line arguments (as per sys.argv)
                argv[1] - ts2_listen_port
                    desired port number for ts2 program
                argv[2] - input_file (OPTIONAL)
                    desired name of input file of entries for ts2 program
        Returns:
            Exit status, by default, 0 upon exit
        Raises:
            KeyboardInterrupt
                if user terminates program with (Ctrl + c) before completion
            SystemExit
                causes program to exit upon KeyboardInterrupt
    """
    (ts2_portno, input_file_str) = check_args(argv)
    print('')
    
    table = DNS_table()
    table.append_from_file(input_file_str)

    try:
        msg = 'Starting TS1 server. Hit (Ctrl + c) to quit.\n'
        log(logstat.LOG, funcname(), msg)

        start_ts2(ts2_portno, table)
    except KeyboardInterrupt, SystemExit:
        print('')
        msg = 'User terminated program before completion.\n'
        log(logstat.LOG, funcname(), msg)
Ejemplo n.º 4
0
def main(argv):
    """Main function, where client function is called

        Args:
            Command line arguments (as per sys.argv)
                argv[1] - ls_hostname
                    desired hostname for LS machine
                argv[2] - ls_listen_port
                    desired port number for LS machine
                argv[3] - input_file_name (OPTIONAL)
                    desired name of input file (queried hostnames)
                argv[4] - output_file_name (OPTIONAL)
                    desired name of output file (resolved host names)
        Returns:
            Exit status, by default, 0 upon exit
        Raises:
            KeyboardInterrupt
                if user terminates program with (Ctrl + c) before completion
            SystemExit
                causes program to exit upon KeyboardInterrupt
    """
    (ls_info, file_str) = check_args(argv)
    # ls_info[0] is LS's hostname
    # ls_info[1] is LS's port number

    # file_str[0] is the query input file string
    # file_str[1] is the query output file string
    print('')

    # read the input file into a list
    hostname_list = file_to_list(file_str[0])

    if len(hostname_list) > 0:
        resolved_list = []

        # if the hostname list has at least one element, proceed to LS server
        try:
            msg = 'Starting client routine. Hit (Ctrl + c) to quit.\n'
            log(logstat.LOG, funcname(), msg)

            resolved_list = query_ls(ls_info, hostname_list)
        except KeyboardInterrupt, SystemExit:
            print('')
            msg = 'User terminated program before completion.\n'
            log(logstat.LOG, funcname(), msg)

        if len(resolved_list) > 0:
            # if the resolved_list has at least one element, write to file
            write_to_file_from_list(file_str[1], resolved_list, 'w')
Ejemplo n.º 5
0
    def append_from_str(self, input_str):
        result = str_to_list(input_str, ' ')

        if len(result) != 3:
            self.__table['ERROR'] = self.addrflag('MALFORMED', 'ENTRY')
        else:
            if result[2] == DNS_table.flag.NS.value and self.__ts_hostname == '__NONE__':
                self.__ts_hostname = result[0]

                msg = 'ts_hostname assigned as \'{}{}{}\'.'.format(K.color.bold.WHT, result[0], K.NRM)

                log(logstat.LOG, funcname(), msg)
            elif result[2] == DNS_table.flag.A.value:
                self.__table[result[0]] = self.addrflag(result[1], result[2])
    
                msg = '{}\'{} : ({}, {}){}\' added to table from string {}\'{}\'{}.'.format(K.color.bold.WHT, result[0], result[1], result[2], K.NRM, K.color.bold.WHT, input_str, K.NRM)

                log(logstat.LOG, funcname(), msg)
Ejemplo n.º 6
0
    def has_hostname(self, query):
        found = False  
        q = query.lower()

        for key, value in self.__table.iteritems():
            if key.lower() == q:
                found = True

                msg = 'Found queried hostname \'{}{}{}\' with value \'{}({}, {}){}\' in table.'.format(K.color.bold.WHT, query, K.NRM, K.color.bold.WHT, value[0], value[1], K.NRM)

                log(logstat.OK, funcname(), msg)

                break

        if not found:
            msg = 'Unable to find hostname \'{}{}{}\' in table.'.format(K.color.bold.WHT, query, K.NRM)

            log(logstat.LOG, funcname(), msg)

        return found  
Ejemplo n.º 7
0
def main(argv):
    """Main function, where LS function is called

        Args:
            Command line arguments (as per sys.argv)
                argv[1] - ls_listen_port
                    desired port number for LS program
                argv[2] - ts1_hostname
                    hostname for desired TS1 server
                argv[3] - ts1_listen_port
                    port number for desired TS1 server, corresponds to ts1_hostname
                argv[4] - ts2_hostname
                    hostname for desired TS2 server
                argv[5] - ts2_listen_port
                    port number for desired TS2 server, corresponds to ts2_hostname
        Returns:
            Exit status, by default, 0 upon exit
        Raises:
            KeyboardInterrupt
                if user terminates program with (Ctrl + c) before completion
            SystemExit
                causes program to exit upon KeyboardInterrupt
    """

    (ls_portno, ts1_info, ts2_info) = check_args(argv)
    # ts1_info[0] is TS1's hostname
    # ts1_info[1] is TS1's port number
    # ts2_info[0] is TS2's hostname
    # ts2_info[1] is TS2's port number
    print('')

    try:
        msg = 'Starting LS server. Hit (Ctrl + c) to quit.\n'
        log(logstat.LOG, funcname(), msg)

        start_ls(ls_portno, ts1_info, ts2_info)
    except KeyboardInterrupt, SystemExit:
        print('')
        msg = 'User terminated program before completion.\n'
        log(logstat.LOG, funcname(), msg)
Ejemplo n.º 8
0
def udp_socket_open():
    """Opens a UDP (datagram) socket, with a call to setsockopt (so the hostname can be immediately reused after a disconnect)

        Args:
            (none)
        Returns:
            An open UDP (datagram) socket
        Raises:
            EnvironmentError if socket fails to open
    """
    sock = 0
    msg = ''

    try:
        sock = socket(AF_INET, SOCK_DGRAM)
    except EnvironmentError:
        msg = 'Socket open error.\n'
        log(logstat.ERR, funcname(), msg)

        exit()

    sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)

    msg = 'Opened new datagram socket.\n'
    log(logstat.OK, funcname(), msg)

    hostname = gethostname()
    ipaddr = gethostbyname(hostname)

    msg = 'Hostname is \'{}{}{}\'.'.format(K.color.bold.WHT, hostname, K.NRM)
    log(logstat.LOG, funcname(), msg)

    msg = 'IP address is \'{}{}{}\'.\n'.format(K.color.bold.WHT, ipaddr, K.NRM)
    log(logstat.LOG, funcname(), msg)

    return sock
Ejemplo n.º 9
0
def start_ls(ls_portno, ts1_info, ts2_info):
    """Starts the LS server routine by opening a socket so that it can receive client queries -- also opens a socket for the TS1 and TS2 servers respectively so that it can forward the client queries to the TS servers, and await any potential replies from them. Routine runs indefintely unless connection is severed or client quits with KeyboardInterrupt.

        Args:
            ls_portno: int
                desired port number for LS server
            ts1_info: tuple
                consists of (ts1_hostname, ts1_portno)
            ts2_info: tuple
                consists of (ts2_hostname, ts2_portno)
        Returns:
            (none)
        Raises:
            (none)
    """
    ts1_hostname = ts1_info[0]
    ts1_portno = ts1_info[1]

    ts2_hostname = ts2_info[0]
    ts2_portno = ts2_info[1]

    ls_binding = ('', ls_portno)

    ls_sock = udp_socket_open()
    ls_sock.bind(ls_binding)

    ts1_ipaddr = is_valid_hostname(ts1_hostname)
    ts1_binding = (ts1_hostname, ts1_portno)

    ts1_sock = udp_socket_open()
    ts1_sock.setblocking(False)

    ts2_ipaddr = is_valid_hostname(ts2_hostname)
    ts2_binding = (ts2_hostname, ts2_portno)

    ts2_sock = udp_socket_open()
    ts2_sock.setblocking(False)

    ts_sockets = [ts1_sock, ts2_sock]
    resolved_sockets = []

    query = ''

    data_in = ''
    data_out = ''

    msg_in = ''
    msg_out = ''

    msg_log = ''

    timeout_val = DEFAULT_TS_TIMEOUT_VALUE

    while True:
        # receive data from client, decode for logging
        (data_in, (client_ipaddr,
                   client_portno)) = ls_sock.recvfrom(BUFFER_SIZE)
        client_binding = (client_ipaddr, client_portno)
        query = data_in.decode('utf-8')

        # retrieve client hostname from client_ipaddr
        client_hostname = gethostbyaddr(client_ipaddr)[0]

        msg_log = logstr(client_hostname, client_ipaddr, query)
        log(logstat.IN, funcname(), msg_log)

        # send data to TS1
        ts1_sock.sendto(data_in, ts1_binding)

        msg_log = logstr(ts1_hostname, ts1_ipaddr, query)
        log(logstat.OUT, funcname(), msg_log)

        # send data to TS2
        ts2_sock.sendto(data_in, ts2_binding)

        msg_log = logstr(ts2_hostname, ts2_ipaddr, query)
        log(logstat.OUT, funcname(), msg_log)

        # use select with timeout_val to determine which socket to recv from
        resolved_sockets, _, _ = select(ts_sockets, [], [], timeout_val)

        if resolved_sockets:
            # if TS1 or TS2 received data, we proceed here
            for ts in resolved_sockets:
                hostname = ''
                ipaddr = ''

                # receive incoming data from TS socket
                # data received from TS socket will be sent to client
                data_in = ts.recv(BUFFER_SIZE)
                data_out = data_in

                # decode message for logging
                msg_in = data_in.decode('utf-8')
                msg_out = msg_in

                # log incoming data from TS socket
                if ts is ts1_sock:
                    hostname = ts1_hostname
                    ipaddr = ts1_ipaddr
                elif ts is ts2_sock:
                    hostname = ts2_hostname
                    ipaddr = ts2_ipaddr

                msg_log = logstr(hostname, ipaddr, msg_in)
                log(logstat.IN, funcname(), msg_log)
        else:
            # TS1 and TS2 did not receive data after timeout_val seconds, log it
            msg_log = '[Connection timeout]'
            log(logstat.LOG, funcname(), msg_log)

            # prepare 'HOST NOT FOUND' message for client
            msg_out = '{} - {}'.format(query,
                                       DNS_table.flag.HOST_NOT_FOUND.value)

            # encode prepared message, will send to client shortly
            data_out = msg_out.encode('utf-8')

        # send outgoing data to client
        ls_sock.sendto(data_out, client_binding)

        msg_log = logstr(client_hostname, client_ipaddr, msg_out)
        log(logstat.OUT, funcname(), msg_log)

        print('')
Ejemplo n.º 10
0
def start_ts2(ts2_portno, table):
    """Starts the TS2 server routine by opening a socket so that it can receive queries from LS. The query is used to run a look-up for a hostname mapping within table, and a reply is sent if the query is resolved.

        Args:
            ts2_portno: int
                desired port number for TS2 server
            table: DNS_table
                table containing (hostname : addrflag) mappings
        Returns:
            (none)
        Raises:
            (none)
    """
    ts2_binding = ('', ts2_portno)

    ts2_sock = udp_socket_open()
    ts2_hostname = gethostname()
    ts2_sock.bind(ts2_binding)

    query = ''

    data_in = ''
    data_out = ''

    msg_out = ''

    msg_log = ''

    while True:
        # receive data from LS, decode for logging
        data_in, (ls_ipaddr, ls_portno) = ts2_sock.recvfrom(BUFFER_SIZE)
        ls_binding = (ls_ipaddr, ls_portno)
        query = data_in.decode('utf-8')
    
        # retrieve ls_hostname from ls_ipaddr
        ls_hostname = gethostbyaddr(ls_ipaddr)[0]

        msg_log = logstr(ls_hostname, ls_ipaddr, query)
        log(logstat.IN, funcname(), msg_log)

        # search table for query
        if table.has_hostname(query):
            # if query is resolved, reply to LS
            
            # prepare outgoing data to LS
        
            # original specificaton, as per PDF
            msg_out = '{} {} {}'.format(query, table.ipaddr(query), table.flagtype(query))
        
            """
            # new specification, as mentioned by professor
            msg_out = '{} {} {} {}'.format(query, table.ipaddr(query), table.flagtype(query), ts2_hostname)
            """

            # send outgoing data to LS
            data_out = msg_out.encode('utf-8')
            ts2_sock.sendto(data_out, ls_binding)

            # log outgoing data to LS
            msg_log = logstr(ls_hostname, ls_ipaddr, msg_out)
            log(logstat.OUT, funcname(), msg_log)
        else:
            # if query is not resolved, notify user
            log(logstat.LOG, funcname(), 'No outgoing data will be sent for this query.')

        print('')
Ejemplo n.º 11
0
def query_ls(ls_info, hostname_list):
    """Starts the client routine by opening a socket so that it can communicate with the LS server, and send it the contents of hostname_list. Client will then receive replies from LS; each reply will be appended to a resolved_list and returned from this function.

        Args:
            ls_info: tuple
                consists of ls_hostname (LS hostname) and ls_portno (LS port number)
            hostname_list: list
                consists of hostnames (each a [str]) to query, which LS server will receive from client
        Returns:
            a [str] of replies from LS
        Raises:
            socket.timeout if no data is received from LS by timeout_val seconds.
    """
    ls_hostname = ls_info[0]
    ls_portno = ls_info[1]

    ls_ipaddr = is_valid_hostname(ls_hostname)
    ls_binding = (ls_hostname, ls_portno)

    timeout_val = DEFAULT_TS_TIMEOUT_VALUE * 2

    ls_sock = udp_socket_open()
    ls_sock.settimeout(timeout_val)

    resolved_list = []

    if ls_ipaddr:
        # if ls_hostname yields a valid ip address
        data_in = ''
        msg_in = ''

        msg_log = ''

        for query in hostname_list:
            # log query
            msg_log = 'Querying hostname \'{}{}{}\'...'.format(
                K.color.bold.WHT, query, K.NRM)
            log(logstat.LOG, funcname(), msg_log)

            # send encoded query to LS
            ls_sock.sendto(query.encode('utf-8'), ls_binding)

            msg_log = logstr(ls_hostname, ls_ipaddr, query)
            log(logstat.OUT, funcname(), msg_log)

            # upon the next recv call,
            # we are expecting the query results from LS

            # receive data from LS, decode it
            try:
                data_in = ls_sock.recv(BUFFER_SIZE)
            except timeout:
                # LS is given a maximum of 10 sec to respond --
                # since TS1 and TS2 have a max of 5 secs to respond,
                # RTT must be accounted for
                msg_log = '[Connection timeout]'
                log(logstat.LOG, funcname(), msg_log + '\n')

            msg_in = data_in.decode('utf-8')

            msg_log = logstr(ls_hostname, ls_ipaddr, msg_in)
            log(logstat.IN, funcname(), msg_log)

            # append query result to resolved_list
            resolved_list.append(msg_in)

            msg_log = 'Added \'{}{}{}\' to resolved_list.'.format(
                K.color.bold.WHT, msg_in, K.NRM)
            log(logstat.LOG, funcname(), msg_log)

            print('')

    return resolved_list
Ejemplo n.º 12
0
        resolved_list = []

        # if the hostname list has at least one element, proceed to LS server
        try:
            msg = 'Starting client routine. Hit (Ctrl + c) to quit.\n'
            log(logstat.LOG, funcname(), msg)

            resolved_list = query_ls(ls_info, hostname_list)
        except KeyboardInterrupt, SystemExit:
            print('')
            msg = 'User terminated program before completion.\n'
            log(logstat.LOG, funcname(), msg)

        if len(resolved_list) > 0:
            # if the resolved_list has at least one element, write to file
            write_to_file_from_list(file_str[1], resolved_list, 'w')
    else:
        # if the hostname list is empty, notify the user
        log(
            logstat.ERR, funcname(),
            'No data was read from \'{}{}{}\'.\n'.format(
                K.color.bold.WHT, file_str[0], K.NRM))

    print('')
    return EX_OK


if __name__ == '__main__':
    # Program execution begins here.
    retval = main(argv)