Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions pythonping/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import socket
import sys
from random import randint
from . import network, executor, payload_provider
Expand All @@ -21,7 +22,8 @@ def ping(target,
out=sys.stdout,
match=False,
source=None,
out_format='legacy'):
out_format='legacy',
device=None):
"""Pings a remote host and handles the responses

:param target: The remote hostname or IP address to ping
Expand Down Expand Up @@ -51,8 +53,12 @@ def ping(target,
8.8.8.8 with 1000 bytes and reply is truncated to only the first 74 of request payload with packet identifiers
the same in request and reply)
:type match: bool
:param repr_format: How to __repr__ the response. Allowed: legacy, None
:type repr_format: str
:param source: Source IP for ICMP packets
:type source: str
:param out_format: How to __repr__ the response. Allowed: legacy, None
:type out_format: str
:param device: Name of the network interface to use (to bind ICMP socket to).
:type device: str
:return: List with the result of each ping
:rtype: executor.ResponseList"""
provider = payload_provider.Repeat(b'', 0)
Expand All @@ -64,9 +70,11 @@ def ping(target,
if not payload:
payload = random_text(size)
provider = payload_provider.Repeat(payload, count)
options = ()
options = []
if df:
options = network.Socket.DONT_FRAGMENT
options.append(network.Socket.DONT_FRAGMENT)
if device:
options.append((socket.SOL_SOCKET, socket.SO_BINDTODEVICE, device.encode('utf-8') + b'\0'))

# Fix to allow for pythonping multithreaded usage;
# no need to protect this loop as no one will ever surpass 0xFFFF amount of threads
Expand Down
4 changes: 2 additions & 2 deletions pythonping/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ def __iter__(self):

class Communicator:
"""Instance actually communicating over the network, sending messages and handling responses"""
def __init__(self, target, payload_provider, timeout, interval, socket_options=(), seed_id=None,
def __init__(self, target, payload_provider, timeout, interval, socket_options=None, seed_id=None,
verbose=False, output=sys.stdout, source=None, repr_format=None):
"""Creates an instance that can handle communication with the target device

Expand All @@ -281,7 +281,7 @@ def __init__(self, target, payload_provider, timeout, interval, socket_options=(
:param interval: Interval to wait between pings, in seconds
:type interval: int
:param socket_options: Options to specify for the network.Socket
:type socket_options: tuple
:type socket_options: list[tuple[int, int, int | Buffer]
:param seed_id: The first ICMP packet ID to use
:type seed_id: Union[None, int]
:param verbose: Flag to enable verbose mode, defaults to False
Expand Down
7 changes: 4 additions & 3 deletions pythonping/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ class Socket:
PROTO_LOOKUP = {"icmp": socket.IPPROTO_ICMP, "tcp": socket.IPPROTO_TCP, "udp": socket.IPPROTO_UDP,
"ip": socket.IPPROTO_IP, "raw": socket.IPPROTO_RAW}

def __init__(self, destination, protocol, options=(), buffer_size=2048, source=None):
def __init__(self, destination, protocol, options=None, buffer_size=2048, source=None):
"""Creates a network socket to exchange messages

:param destination: Destination IP address
:type destination: str
:param protocol: Name of the protocol to use
:type protocol: str
:param options: Options to set on the socket
:type options: tuple
:type options: list[tuple[int, int, int | Buffer]
:param source: Source IP to use - implemented in future releases
:type source: Union[None, str]
:param buffer_size: Size in bytes of the listening buffer for incoming packets (replies)
Expand All @@ -31,7 +31,8 @@ def __init__(self, destination, protocol, options=(), buffer_size=2048, source=N
self.socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, self.protocol)
self.source = source
if options:
self.socket.setsockopt(*options)
for option in options:
self.socket.setsockopt(*option)

# Implementing a version of socket.getprotobyname for this library since built-in is not thread safe
# for python 3.5, 3.6, and 3.7:
Expand Down