def send(self, packet, ip, port, **kwargs): """ Performs final sanity-checking and address manipulation, then submits the packet for transmission. :param packet: The packet to be written. :type packet: :class:`DHCPPacket <dhcp_types.packet.DHCPPacket>` :param ip: The address to which the packet should be sent. :type ip: :class:`IPv4 <dhcp_types.IPv4>` :param int port: The port to which the packet should be sent. :param \*\*kwargs: Any technology-specific arguments. :return tuple(2): 0. The number of bytes written to the network. 1. The :class:`Address <dhcp.Address>` ultimately used. :except Exception: An error occurred during serialisation or transmission. """ (broadcast_changed, original_was_broadcast) = packet.setFlag(FLAGBIT_BROADCAST, _IP_BROADCAST == ip) #Perform any necessary packet-specific address-changes if not original_was_broadcast: #Unicast behaviour permitted; use the packet's IP override, if set ip = packet.response_ip or ip port = packet.response_port or port if packet.response_source_port is not None: kwargs['source_port'] = packet.response_source_port bytes_sent = self._send(packet, str(ip), port, **kwargs) if broadcast_changed: #Restore the broadcast bit, in case the packet needs to be used for something else packet.setFlag(FLAGBIT_BROADCAST, original_was_broadcast) try: sendip = IPv4(ip) except: sendip = "255.255.255.255" return (bytes_sent, Address(sendip, port))
def getData(self, timeout, packet_buffer): """ Runs `select()` over all relevant sockets, providing data if available. :param int timeout: The number of seconds to wait before returning. :param int packet_buffer: The size of the buffer to use for receiving packets. :return tuple(3): 0. :class:`Address <dhcp.Address>` or ``None``: None if the timeout was reached. 1. The received data as a ``str`` or ``None`` if the timeout was reached. 2. the port on which the packet was received; -1 on timeout or error. :except select.error: The `select()` operation did not complete gracefully. """ port = -1 active_sockets = select.select(self._listening_sockets, [], [], timeout)[0] if active_sockets: active_socket = active_sockets[0] if active_socket == self._proxy_socket: port = self._proxy_port else: port = self._server_port (data, source_address) = active_socket.recvfrom(packet_buffer) if data: return (Address(IPv4(source_address[0]), source_address[1]), data, port) return (None, None, port)
def getData(self, timeout, packet_buffer): """ Runs `select()` over all relevant sockets, providing data if available. :param int timeout: The number of seconds to wait before returning. :param int packet_buffer: The size of the buffer to use for receiving packets. :return tuple(3): 0. :class:`Address <dhcp.Address>` or ``None``: None if the timeout was reached. 1. The received data as a ``str`` or ``None`` if the timeout was reached. 2. A ``bool`` indicating whether the data was received via PXE. :except select.error: The `select()` operation did not complete gracefully. """ pxe = False active_sockets = select.select(self._listening_sockets, [], [], timeout)[0] if active_sockets: active_socket = active_sockets[0] pxe = active_socket == self._pxe_socket (data, source_address) = active_socket.recvfrom(packet_buffer) if data: return (Address(IPv4(source_address[0]), source_address[1]), data, pxe) return (None, None, False)
(C) Neil Tallim, 2014 <*****@*****.**> (C) Matthew Boedicker, 2011 <*****@*****.**> (C) Mathieu Ignacio, 2008 <*****@*****.**> """ import collections import platform import select import socket import threading from dhcp_types.ipv4 import IPv4 from dhcp_types.mac import MAC from dhcp_types.packet import (DHCPPacket, FLAGBIT_BROADCAST) #IP constants _IP_GLOB = IPv4('0.0.0.0') #: The internal "everything" address. _IP_BROADCAST = IPv4('255.255.255.255') #: The broadcast address. IP_UNSPECIFIED_FILTER = ( _IP_GLOB, _IP_BROADCAST, None ) #: A tuple of addresses that reflect non-unicast targets. _ETH_P_SNAP = 0x0005 """ Internal-only Ethernet-frame-grabbing for Linux. Nothing should be addressable to the special response socket, but better to avoid wasting memory. """ Address = collections.namedtuple("Address", ('ip', 'port')) """ An inet layer-3 address.