예제 #1
0
    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))
예제 #2
0
    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)
예제 #3
0
 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)
예제 #4
0
(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.