Basic and global functions

Global settings and error handling

Set of global and useful classes and functions used within the module.

Exceptions:BOF-specific exceptions raised by the module.
Logging:Functions to enable or disable logging for the module.
String manipulation:
 Functions to make basic changes on strings.
exception bof.base.BOFError

Bases: Exception

Base class for all BOF exceptions.

Warning

Should not be used directly, please raise or catch subclasses instead.

exception bof.base.BOFLibraryError

Bases: bof.base.BOFError

Library, files and import-related exceptions.

Raise when the library cannot find what it needs to work correctly (such as an external module or a file).

exception bof.base.BOFNetworkError

Bases: bof.base.BOFError

Network-related exceptions.

Raise when the network connection fails or is interrupted.

exception bof.base.BOFProgrammingError

Bases: bof.base.BOFError

Script and module programming-related errors.

Raise when a function or an argument is not used as expected.

Note

As a module user, this exception is the most frequent one.

bof.base.disable_logging() → None

Turn off logging features,

bof.base.enable_logging(filename: str = '', error_only: bool = False) → None

Turn on logging features to store BOF-autogenerated and user events. Relies on Python’s logging module.

Parameters:
  • filename – Optional name of the file in which events will be saved. Default is bof.log.
  • error_only – All types of events are logged (info, warning, error) are saved unless this parameter is set to True.
bof.base.log(message: str, level: str = 'INFO') → bool

Logs an event (message) to a file, if BOF logging is enabled. Requires previous call to bof.`enable_logging()`. A message is recorded along with event-related information:

  • date and time
  • level (can be changed with parameter level)
  • event location in the code (file name, line number)
Parameters:
  • message – Event definition.
  • level – Type of event to record: ERROR, WARNING, DEBUG. INFO` (default). Levels from Python’s logging are used.
Returns:

Current state of logging (enabled/True, disabled/False).

bof.base.to_property(value: str) → str

Lower a string and replace all non alnum characters with _

Basic network protocol implementation

Network protocol global classes and abstract implementations.

Provides classes for asynchronous network connection management on different transport protocols, to be used by higher-level protocol implementation classes. Relies on module asyncio.

UDP:Implementation of asynchronous UDP communication and packet crafting.
TCP:Implementation of asynchronous TCP communication and packet crafting.

Both classes rely on internal class _Transport, which should not be instantiated.

Network connection and exchange example with raw UDP:

from bof import UDP
udp = UDP()
udp.connect("192.168.1.1", 3671)
udp.send(b"Hi!")
udp.disconnect()

Usage is the same with raw TCP.

Warning

Direct initialization of TCP/UDP object is not recommended. The user should use BOF network classes inherited from TCP/UDP (e.g. KNXnet for the KNX protocol).

bof.network.IS_IP(ip: str)

Check that ip is a valid IPv4 address.

class bof.network.TCP

Bases: bof.network._Transport

TCP protocol endpoint.

This is the parent class to higher-lever network protocol implementation. It can be instantiated as is, however this is not the expected behavior. Uses protected _TCP classes implementing asyncio TCP handler.

Warning

Should not be instantiated directly.

connect(ip: str, port: int) → object

Initialize asynchronous connection using TCP on ip:port.

Parameters:
  • ip – IPv4 address as a string with format A.B.C.D.
  • port – Port number as an integer.
Returns:

The instance of the TCP class created,

Raises:

BOFNetworkError – if connection fails.

Example:

tcp = bof.TCP().connect("127.0.0.1", 4840)
send(data: bytes, address: tuple = None) → int

Send data to address over TCP.

Parameters:
  • data – Raw byte array or string to send.
  • address – Address to send data to, with format tuple (ipv4_address, port). If address is not specified, uses the address given to connect.
Returns:

The number of bytes sent, as an integer.

Example:

tcp.send("test_send")
tcp.send(b'')
class bof.network.UDP

Bases: bof.network._Transport

UDP protocol endpoint, inheriting from Transport base class.

This is the parent class to higher-lever network protocol implementation. It can be instantiated as is, however this is not the expected behavior. Uses protected _UDP classes implementing asyncio UDP handler.

Warning

Should not be instantiated directly.

static broadcast(data: bytes, address: tuple, timeout: float = 1.0) → list

Broadcasts a request and waits for responses from devices (UDP).

Parameters:
  • data – Raw byte array or string to send.
  • address – Remote network address with format tuple (ip, port).
  • timeout – Time out value in seconds, as a float (default is 1.0s).
Returns:

A list of tuples with format (response, (ip, port)).

Raises:

BOFNetworkError – If multicast parameters are invalid.

Example:

devices = UDP.broadcast(b'...', ('192.168.1.255', 3671))
connect(ip: str, port: int) → object

Initialize asynchronous connection using UDP on ip:port.

Parameters:
  • ip – IPv4 address as a string with format A.B.C.D.
  • port – Port number as an integer.
Returns:

The instance of the UDP class created,

Raises:

BOFNetworkError – if connection fails.

Example:

udp = bof.UDP().connect("127.0.0.1", 13671)
static multicast(data: bytes, address: tuple, timeout: float = 1.0) → list

Sends a multicast request to specified ip address and port (UDP).

Expects devices subscribed to the address to respond and return responses as a list of frames with their source. Opens its own socket.

Parameters:
  • data – Raw byte array or string to send.
  • address – Remote network address with format tuple (ip, port).
  • timeout – Time out value in seconds, as a float (default is 1.0s).
Returns:

A list of tuples with format (response, (ip, port)).

Raises:

BOFNetworkError – If multicast parameters are invalid.

Example:

devices = UDP.multicast(b'...', ('224.0.23.12', 3671))
send(data: bytes, address: tuple = None) → int

Send data to address over UDP.

Parameters:
  • data – Raw byte array or string to send.
  • address – Address to send data to, with format tuple (ipv4_address, port). If address is not specified, uses the address given to connect.
Returns:

The number of bytes sent, as an integer.

Example:

udp.send("test_send")
udp.send(b'')

BOFPacket base class

Interfaces with a packet as a Scapy object, with specific features.

A BOFPacket is a sort of wrapper around a Scapy Packet object, and implements specific features or changes relative to Scapy’s behavior when interacting with this packet.

The Scapy Packet is used as a basis for BOF to manipulate frames with its own syntax. You don’t need to know how to use Scapy to use BOF. However, you can still perform “Scapy stuff” on the packet by directly accessing BOFPacket.scapy_pkt attribute.

Note

BOFPacket DOES NOT inherit from Scapy packet, because we don’t need a “specialized” class, but a “translation” from BOF usage to Scapy objects.

Example (keep in mind that BOFPacket should not be instantiated directly :)):

pkt = BOFPacket(scapy_pkt=ScapyBasicOtterPacket1())
print(pkt.scapy_pkt.basic_otter_1_1, pkt.basic_otter_1_1) # Same output
pkt.basic_otter_1_1 = "192.168.1.2" # Not the expected type, BOF converts it
pkt.show2()
class bof.packet.BOFPacket(_pkt: bytes = None, scapy_pkt: scapy.packet.Packet = None, **kwargs)

Bases: object

Base class for BOF network packet handling, to inherit in subclasses.

This class should not be instantiated directly but protocol-specific Packet classes in BOF shall inherit it. It acts as a wrapper around Scapy-based packets in the specified protocol, either relaying, replacing or modifying Scapy default behaviors on Packets and Fields.

Parameters:
  • _pkt – Raw Packet bytes used to build a packet (mostly done at reception, but you can manually create a packet from bytes)
  • scapy_pkt – Actual Scapy Packet object, used by BOF for protocol implementation-related stuff. Can be referred to directly to do “Scapy stuff” inside BOF.
  • kwargs – Field values to set when instantiating the class. Format is field_name=value, .... If two fields have the same name, it sets the first one.

Example:

class OtterPacket(BOFPacket)
append(other: object, autobind: bool = False, packet=None, value=None) → None

Adds either a BOFPacket, Scapy Packet or Field to current packet.

Parameters:
  • other – BOFPacket or Scapy Packet or field to append as payload.
  • autobind – Whether or not unspecified binding found in Scapy implementation are automatically added.
  • packet – Packet at to append other to.
  • value – Value to set to a newly-created field.
Raises:

BOFProgrammingError – if type is not supported.

fields

Returns the list of field objects in a BOFPacket.

Can be used to retrieve the list of fields as a name list with:

[x.name for x in pkt.fields]
get(*args) → object

Get a field either from its name, partial or absolute path.

Partial indicates part of the absolute path, in other words where the search for the field should start from.

Parameters:args – Can take from one to many arguments. The last argument must be the field you look for. Previous “path” arguments must be in the right order (even if the path is not complete).
Raises:BOFProgrammingError – If field not found or not supported.
length

Returns the length of the packet (number of bytes).

scapy_pkt
type

Get information about the packet’s type (protocol-dependent).

Should be overriden in subclasses to match a protocol’s different types of packets. For instance, BOF’s packet for the KNX protocol (KNXPacket) returns the type of packet as a name, relying on its identifier fields. If identifier is 0x0203, pkt.type indicates that the packet is a DESCRIPTION REQUEST.

update(value: object, *args) → None

Set value to a field either from its name, partial or absolute path.

Partial indicates part of the absolute path, in other words where the search for the field should start from.

Parameters:
  • value – The value to set to the field. If the type does not match, the type of field will be changed.
  • args – Can take from one to many arguments. The last argument must be the field you look for. Previous “path” arguments must be in the right order (even if the path is not complete).
Raises:

BOFProgrammingError – If field not found or not supported.