Example #1
0
def verbose_ping(address, count=4, interval=1, timeout=2, id=PID):
    # A payload of 56 bytes is used by default. You can modify it using
    # the 'payload_size' parameter of your ICMP request.
    print(f'PING {address}: 56 data bytes\n')

    # We detect the socket to use from the specified IP address
    if is_ipv6_address(address):
        sock = ICMPv6Socket()
    else:
        sock = ICMPv4Socket()

    for sequence in range(count):
        # We create an ICMP request
        request = ICMPRequest(
            destination=address,
            id=id,
            sequence=sequence)

        try:
            # We send the request
            sock.send(request)

            # We are awaiting receipt of an ICMP reply
            reply = sock.receive(request, timeout)

            # We received a reply
            # We display some information
            print(f'  {reply.bytes_received} bytes from '
                  f'{reply.source}: ', end='')

            # We throw an exception if it is an ICMP error message
            reply.raise_for_status()

            # We calculate the round-trip time and we display it
            round_trip_time = (reply.time - request.time) * 1000

            print(f'icmp_seq={sequence} '
                  f'time={round(round_trip_time, 3)} ms')

            # We wait before continuing
            if sequence < count - 1:
                sleep(interval)

        except TimeoutExceeded:
            # The timeout has been reached
            print(f'  Request timeout for icmp_seq {sequence}')

        except ICMPError as err:
            # An ICMP error message has been received
            print(err)

        except ICMPLibError:
            # All other errors
            print('  An error has occurred.')

    print('\nCompleted.')
Example #2
0
def broadcast_ping(address, count=4, timeout=1, id=PID):
    # ICMPRequest uses a payload of 56 bytes by default
    # You can modify it using the payload_size parameter
    print(f'PING {address}: 56 data bytes')

    # Broadcast is only possible in IPv4
    socket = ICMPv4Socket()

    # We allow the socket to send broadcast packets
    socket.broadcast = True

    for sequence in range(count):
        # We create an ICMP request
        request = ICMPRequest(destination=address,
                              id=id,
                              sequence=sequence,
                              timeout=timeout)

        print()

        try:
            # We send the request
            socket.send(request)

            while 'we receive replies':
                # We are awaiting receipt of an ICMP reply
                # If there is no more responses, the TimeoutExceeded
                # exception is thrown and the loop is stopped
                reply = socket.receive()

                # We calculate the round-trip time of the reply
                round_trip_time = (reply.time - request.time) * 1000

                # We display some information
                print(f'  {reply.bytes_received} bytes from '
                      f'{reply.source}: icmp_seq={sequence} '
                      f'time={round(round_trip_time, 3)} ms')

        except TimeoutExceeded:
            # The timeout has been reached
            # We use this exception to break the while loop
            pass

        except ICMPLibError:
            # All other errors
            print('An error has occurred.')
Example #3
0
def check_connection(address, timeout=2, request_id=PID):
    sock = ICMPv4Socket()
    request = ICMPRequest(destination=address, id=request_id, sequence=1)

    try:
        sock.send(request)
        reply = sock.receive(request, timeout)
        reply.raise_for_status()

    except TimeoutExceeded as err:
        print(err)

    except DestinationUnreachable as err:
        print(err)

    except TimeExceeded as err:
        print(err)

    except ICMPLibError as err:
        print(err)
Example #4
0
def verbose_traceroute(address, count=2, interval=0.05, timeout=2,
        id=PID, max_hops=30):
    # We perform a DNS resolution of the address passed in parameters.
    # If the address is already an IP address, no lookup is done. The
    # same address is returned.
    ip_address = resolve(address)

    # A payload of 56 bytes is used by default. You can modify it using
    # the 'payload_size' parameter of your ICMP request.
    print(f'Traceroute to {address} ({ip_address}): '
          f'56 data bytes, {max_hops} hops max\n')

    # We detect the socket to use from the specified IP address
    if is_ipv6_address(ip_address):
        sock = ICMPv6Socket()

    else:
        sock = ICMPv4Socket()

    ttl = 1
    host_reached = False

    while not host_reached and ttl <= max_hops:
        for sequence in range(count):
            # We create an ICMP request
            request = ICMPRequest(
                destination=ip_address,
                id=id,
                sequence=sequence,
                ttl=ttl)

            try:
                # We send the request
                sock.send(request)

                # We are awaiting receipt of an ICMP reply
                reply = sock.receive(request, timeout)

                # We received a reply
                # We display some information
                source_name = getfqdn(reply.source)

                print(f'  {ttl:<2}    {reply.source:15}    '
                      f'{source_name:40}    ', end='')

                # We throw an exception if it is an ICMP error message
                reply.raise_for_status()

                # We reached the destination host
                # We calculate the round-trip time and we display it
                round_trip_time = (reply.time - request.time) * 1000
                print(round(round_trip_time, 2), 'ms')

                # We can stop the search
                host_reached = True
                break

            except TimeExceeded as err:
                # An ICMP Time Exceeded message has been received
                # The message was probably generated by an intermediate
                # gateway
                reply = err.reply

                # We calculate the round-trip time and we display it
                round_trip_time = (reply.time - request.time) * 1000
                print(round(round_trip_time, 2), 'ms')

                sleep(interval)
                break

            except TimeoutExceeded:
                # The timeout has been reached and no host or gateway
                # has responded after multiple attempts
                if sequence >= count - 1:
                    print(f'  {ttl:<2}    * * *')

            except ICMPLibError:
                # Other errors are ignored
                pass

        ttl += 1

    print('\nCompleted.')
Example #5
0
def do_traceroute(
    table: Table,
    address: str,
    count: int = 2,
    interval: float = 0.05,
    timeout: int = 3,
    id: int = PID,
    first_hop: int = 1,
    max_hops: int = 32,
    source: Optional[str] = None,
    fast: bool = False,
    **kwargs,
) -> List[Hop]:
    """
    :param table: rich 动态表格

    参数的含义与: `icmplib.traceroute` 保持一致
    """
    address = resolve(address)

    address = address[0] if isinstance(address, list) else address

    sock = ICMPv6Socket(source) if is_ipv6_address(address) else ICMPv4Socket(source)

    ttl = first_hop
    host_reached = False
    hops = []

    while not host_reached and ttl <= max_hops:
        hop_address = None
        packets_sent = 0

        rtts: List[float] = []

        for sequence in range(count):
            request = ICMPRequest(
                destination=address, id=id, sequence=sequence, ttl=ttl, **kwargs
            )

            reply: Optional[ICMPReply] = None
            try:
                sock.send(request)
                packets_sent += 1

                reply = sock.receive(request, timeout)
                reply.raise_for_status()
                host_reached = True

            except TimeExceeded:
                sleep(interval)

            except ICMPLibError:
                continue

            assert reply is not None

            hop_address = reply.source

            round_trip_time = (reply.time - request.time) * 1000

            rtts.append(round_trip_time)

            if fast:
                break

        if len(rtts) > 0:

            hop = Hop(
                address=hop_address, packets_sent=packets_sent, distance=ttl, rtts=rtts
            )

            hops.append(hop)
            ip_info = get_ip_info(hop.address)
            if ip_info is None:
                position = ""
                isp = ""
            else:
                position = f"{ip_info.country} {ip_info.regionName} {ip_info.city}"
                isp = f"{ip_info.isp}"
            table.add_row(
                f"{hop.address}",  # 地址
                position,  # 位置
                isp,  # ISP
                f"{min(hop.rtts):.2f}",  # min
                f"{mean(hop.rtts):.2f}",  # avg
                f"{max(hop.rtts):.2f}",  # max
            )
        else:
            table.add_row("*", "*", "*", "*", "*", "*")

        ttl += 1

    sock.close()

    return hops
Example #6
0
def do_one_ping(
    host,
    progress: Progress,
    cc: Optional[str] = None,
    seq_offset=0,
    count=8,
    interval=0.1,
    timeout=2,
    id=PID,
    source=None,
    **kwargs,
) -> PingResult:
    """
    :raises NameLookupError: If you pass a hostname or FQDN in
        parameters and it does not exist or cannot be resolved.
    :raises SocketPermissionError: If the privileges are insufficient
        to create the socket.
    :raises SocketAddressError: If the source address cannot be
        assigned to the socket.
    :raises ICMPSocketError: If another error occurs. See the
        `ICMPv4Socket` or `ICMPv6Socket` class for details.
    """

    address = resolve(host)
    if isinstance(address, list):
        address = address[0]

    log = logging.getLogger("rich")

    task_id = progress.add_task(host, total=count)

    # on linux `privileged` must be True
    if is_ipv6_address(address):
        sock = ICMPv6Socket(address=source, privileged=True)
    else:
        sock = ICMPv4Socket(address=source, privileged=True)

    times = []

    for sequence in range(count):
        progress.update(task_id, advance=1)

        request = ICMPRequest(
            destination=address, id=id, sequence=sequence + seq_offset, **kwargs
        )

        try:
            sock.send(request)

            reply = sock.receive(request, timeout)
            reply.raise_for_status()

            round_trip_time = (reply.time - request.time) * 1000
            times.append(round_trip_time)

            if sequence < count - 1:
                sleep(interval)

        except ICMPLibError as e:
            log.error(f"接收 {host} Ping 返回信息失败: {e}")

    progress.remove_task(task_id=task_id)

    sock.close()

    log.info(f"{host} Ping 检测已经完成")

    return PingResult(host=host, cc=cc, count=count, times=times)
def do_traceroute_v2(
    host: str,
    count: int = 2,
    interval: float = 0.05,
    timeout: int = 3,
    id: int = PID,
    first_hop: int = 1,
    max_hops: int = 32,
    source: Optional[str] = None,
    fast: bool = False,
    **kwargs,
) -> TraceResult:
    """
    :param table: rich 动态表格

    参数的含义与: `icmplib.traceroute` 保持一致
    """

    address = resolve(host)
    if isinstance(address, list):
        address = address[0]

    if is_ipv6_address(address):
        sock = ICMPv6Socket(source)
    else:
        sock = ICMPv4Socket(source)

    ttl = first_hop
    host_reached = False
    hops: List[TraceHop] = []

    while not host_reached and ttl <= max_hops:
        hop_address = None
        packets_sent = 0
        packets_received = 0

        times: List[float] = []

        for sequence in range(count):
            request = ICMPRequest(destination=address,
                                  id=id,
                                  sequence=sequence,
                                  ttl=ttl,
                                  **kwargs)

            reply: Optional[ICMPReply] = None
            try:
                sock.send(request)
                packets_sent += 1

                reply = sock.receive(request, timeout)
                reply.raise_for_status()
                host_reached = True

            except TimeExceeded:
                sleep(interval)

            except ICMPLibError:
                continue

            assert reply is not None

            hop_address = reply.source
            packets_received += 1

            round_trip_time = (reply.time - request.time) * 1000

            times.append(round_trip_time)

            if fast:
                break

        if packets_received:
            ip_info = get_ip_info(hop_address)

            info = ip_info.dict() if ip_info is not None else dict()

            hop = TraceHop(ip=hop_address,
                           distance=ttl,
                           count=count,
                           times=times,
                           info=info)

            hops.append(hop)

        ttl += 1

    sock.close()

    return TraceResult(results=hops, host=host)
def tracingAlg(address, count=2, interval=0.05, timeout=2, id=PID, #hadi
        hop1=1, max_hops=17, source=None, fast=False, **kwargs):
    address = resolve(address)

    socket = ICMPv4Socket(source)#ICMPv4Socket is a custom socket class
                                #creates a socket(socket.socket(family=socket.AF_INET,type=type,proto=socket.IPPROTO_ICMP))
                               #it sets for that socket a TTL and checks if broadcast support is enabled on the socket

    ttl = hop1
    dest_reached = False #true when we reach final destination
    hopsList = []#empty list

    while not dest_reached and ttl <= max_hops:
        hop_address = None # adress that the hop reached
        sentPackets = 0 #number of packets sent to final host
        recievedPackets = 0 #number of packets recieved by either current or final host

        #initializing round trip times
        #min_rtt = float('inf')#minimum round trip time
        avRTT = 0.0#average round trip time
        #max_rtt = 0.0#maximum round trip time

        for sequence in range(count):#for loop to keep varying packets sent
            req = ICMPRequest( #ICMP echo request
                                    #payload size initialized to 56
                                    #ttl initialized to 64
                destination=address,
                id=id, #id of the request(to match reply with request)
                sequence=sequence,
                ttl=ttl,#initialized in ICMPRequest to 64
                **kwargs)#traffic class

            try:
                socket.send(req)#sending request to host
                                  #raises errors such as socketunavailable and SocketBroadcastError
                sentPackets += 1

                reply = socket.receive(req, timeout)#listening for the reply of current or final hosts
                                                      #takes arguement timeout to set a timer in case socket doesn't recieve confirmation
                reply.raise_for_status()# function to make an exception if reply is not an icmp echo reply
                dest_reached = True

            except TimeExceeded:#icmplib error
                sleep(interval)#wait a given number of seconds

            except ICMPLibError:#Exception class for the icmplib package.
                continue

            hopAddress = reply.source# ip adress of the current or final host
            recievedPackets += 1 #increment packets recieved

            round_trip_time = (reply.time - req.time) * 1000# rtt in milliseconds
            avRTT += round_trip_time
            #min_rtt = min(round_trip_time, min_rtt)
            #max_rtt = max(round_trip_time, max_rtt)

            if fast:
                break

        if recievedPackets:
            avRTT = avRTT/recievedPackets #average rtt

            currentHop = Hops_Properties(#hop class created to store the properties bellow for every hop
                address=hopAddress,
                avRTT=avRTT,
                packets_sent=sentPackets,
                packets_received=recievedPackets,
                distance=ttl)

            hopsList.append(currentHop)#adding current hop to the list of hops
######################################################
        elif recievedPackets==False:
            currentHop = Hops_Properties(#hop class created to store the properties bellow for every hop
                address='Not Responding :/',
                avRTT=avRTT,
                packets_sent=sentPackets,
                packets_received=recievedPackets,
                distance=ttl)

            hopsList.append(currentHop)#adding current hop to the list of hops
########################################################
        ttl += 1#adding hop to reach the next destination

    socket.close()#closing socket

    return hopsList