pydhcplib-0.6.2/0000755000175000017500000000000011366364415011632 5ustar matmatpydhcplib-0.6.2/setup.py0000755000175000017500000000213611366364415013351 0ustar matmat#!/usr/bin/env python2.5 from distutils.core import setup fr8_manpages=['man/fr/man8/pydhcp.8.gz'] fr3_manpages=['man/fr/man3/pydhcplib.3.gz', 'man/fr/man3/pydhcplib.DhcpBasicPacket.3.gz', 'man/fr/man3/pydhcplib.DhcpPacket.3.gz', 'man/fr/man3/pydhcplib.hwmac.3.gz', 'man/fr/man3/pydhcplib.ipv4.3.gz', 'man/fr/man3/pydhcplib.strlist.3.gz'] en3_manpages=['man/man3/pydhcplib.strlist.3.gz', 'man/man3/pydhcplib.3.gz', 'man/man3/pydhcplib.ipv4.3.gz'] en8_manpages=['man/man8/pydhcp.8.gz'] setup(name='pydhcplib', version="0.6.2", license='GPL v3', description='Dhcp client/server library', author='Mathieu Ignacio', author_email='mignacio@april.org', url='http://pydhcplib.tuxfamily.org/', packages=['pydhcplib'], scripts=['scripts/pydhcp'], data_files=[("share/man/man8",en8_manpages), # ("share/man/fr/man8",fr8_manpages), ("share/man/fr/man3",fr3_manpages), ("share/man/man3",en3_manpages) ]) pydhcplib-0.6.2/docs/0000755000175000017500000000000011366364415012562 5ustar matmatpydhcplib-0.6.2/docs/dhcp_options_supported.txt0000644000175000017500000005662011366364415020132 0ustar matmatAll DHCP options described in RFC 2131 should be supported. To set an option in a dhcp packet you first create a dhcp packet : from dhcp_packet import DhcpPacket mypacket = DhcpPacket() Then you set an option like this : mypacket.SetOption('option_name',option_data) MUST be a list of integer between 0 and 255. Data types ========== * Single IP : 4 octets list (ex : [191.121.212.11]) * Multiple IP : MUST be a multiple of 4 octets list (4 octets at least) * 32-bits : integer of 4 octets. * String : a list of octet interpreted as ascii characters with a minimal size of 1. RFC 1497 Vendor Extensions ========================== * subnet_mask RFC code : 1 Type : Single IP The subnet mask option specifies the client's subnet mask as per RFC 950. * time_offset RFC code : 2 Type : 32-bits The time offset field specifies the offset of the client's subnet in seconds from Coordinated Universal Time (UTC). The offset is expressed as a two's complement 32-bit integer. A positive offset indicates a location east of the zero meridian and a negative offset indicates a location west of the zero meridian. * router_option (code 3) RFC code : 3 Type : Multiple IP The router option specifies a list of IP addresses for routers on the client's subnet. Routers SHOULD be listed in order of preference. * time_server RFC code : 4 Type : Multiple IP The time server option specifies a list of RFC 868 time servers available to the client. Servers SHOULD be listed in order of preference. * name_server RFC code : 5 Type : Multiple IP The name server option specifies a list of IEN 116 name servers available to the client. Servers SHOULD be listed in order of preference. * domain_name_server RFC code : 6 Type : Mutltiple IP The domain name server option specifies a list of Domain Name System (STD 13, RFC 1035) name servers available to the client. Servers SHOULD be listed in order of preference. * log_server RFC code : 7 Type : Multiple IP The log server option specifies a list of MIT-LCS UDP log servers available to the client. Servers SHOULD be listed in order of preference. * cookie_server RFC code : 8 Type : Multiple IP The cookie server option specifies a list of RFC 865 cookie servers available to the client. Servers SHOULD be listed in order of preference. * lpr_server RFC code : 9 Type : Multiple IP The LPR server option specifies a list of RFC 1179 line printer servers available to the client. Servers SHOULD be listed in order of preference. * impress_server RFC code : 10 Type : Multiple IP The Impress server option specifies a list of Imagen Impress servers available to the client. Servers SHOULD be listed in order of preference. * resource_location_ server Code : 11 Type : Multiple IP This option specifies a list of RFC 887 Resource Location servers available to the client. Servers SHOULD be listed in order of preference. * host_name RFC code : 12 Type : String This option specifies the name of the client. The name may or may not be qualified with the local domain name. See RFC 1035 for character set restrictions. * boot_file_size RFC code : 13 Type : 16-bits (unsigned integer) This option specifies the length in 512-octet blocks of the default boot image for the client. * merit_dump_file RFC code : 14 Type : String This option specifies the path-name of a file to which the client's core image should be dumped in the event the client crashes. The path is formatted as a character string consisting of characters from the NVT ASCII character set. * domain_name RFC code : 15 Type : String This option specifies the domain name that client should use when resolving hostnames via the Domain Name System. * swap_server RFC code : 16 Type : Single IP This specifies the IP address of the client's swap server. * root_path RFC code : 17 Type : String This option specifies the path-name that contains the client's root disk. The path is formatted as a character string consisting of characters from the NVT ASCII character set. * extensions_path RFC code : 18 Type : String A string to specify a file, retrievable via TFTP, which contains information which can be interpreted in the same way as the 64-octet vendor-extension field within the BOOTP response, with the following exceptions: - the length of the file is unconstrained; - all references to Tag 18 (i.e., instances of the BOOTP Extensions Path field) within the file are ignored. IP Layer Parameters per Host ============================ This section details the options that affect the operation of the IP layer on a per-host basis. * ip_forwarding RFC code : 19 Type : Bool This option specifies whether the client should configure its IP layer for packet forwarding. A value of 0 means disable IP forwarding, and a value of 1 means enable IP forwarding. * nonlocal_source_routing RFC code : 20 Type : Bool This option specifies whether the client should configure its IP layer to allow forwarding of datagrams with non-local source routes. A value of 0 means disallow forwarding of such datagrams, and a value of 1 means allow forwarding. * policy_filter RFC code : 21 Type : Special - Multiple IP/Mask This option specifies policy filters for non-local source routing. The filters consist of a list of IP addresses and masks which specify destination/mask pairs with which to filter incoming source routes. Any source routed datagram whose next-hop address does not match one of the filters should be discarded by the client. The minimum length of this option is 8, and the length MUST be a multiple of 8. * maximum_datagram_reassembly_size RFC code : 22 Type : 16-bits This option specifies the maximum size datagram that the client should be prepared to reassemble. The size is specified as a 16-bit unsigned integer. The minimum value legal value is 576. * default_ip_time-to-live RFC code : 23 Type : 8-bits unsigned int This option specifies the default time-to-live that the client should use on outgoing datagrams. The TTL is specified as an octet with a value between 1 and 255. * path_mtu_aging_timeout RFC code : 24 Type : 32-bits unsigned int This option specifies the timeout (in seconds) to use when aging Path MTU values discovered by the mechanism defined in RFC 1191 [12]. The timeout is specified as a 32-bit unsigned integer. * path_mtu_plateau_table RFC code : 25 Type : 16-bits unsigned integer list This option specifies a table of MTU sizes to use when performing Path MTU Discovery as defined in RFC 1191. The table is formatted as a list of 16-bit unsigned integers, ordered from smallest to largest. The minimum MTU value cannot be smaller than 68. IP Layer Parameters per Interface ================================= This section details the options that affect the operation of the IP layer on a per-interface basis. It is expected that a client can issue multiple requests, one per interface, in order to configure interfaces with their specific parameters. * Interface MTU Option RFC code : 26 Type : 16-bit unsigned integer This option specifies the MTU to use on this interface. The minimum legal value for the MTU is 68. * all_subnets_are_local RFC code : 27 Type : Bool This option specifies whether or not the client may assume that all subnets of the IP network to which the client is connected use the same MTU as the subnet of that network to which the client is directly connected. A value of 1 indicates that all subnets share the same MTU. A value of 0 means that the client should assume that some subnets of the directly connected network may have smaller MTUs. * broadcast_address RFC code : 28 Type : Single IP This option specifies the broadcast address in use on the client's subnet. * perform_mask_discovery RFC code : 29 Type : Bool This option specifies whether or not the client should perform subnet mask discovery using ICMP. A value of 0 indicates that the client should not perform mask discovery. A value of 1 means that the client should perform mask discovery. * mask_supplier RFC code : 30 Type : Bool This option specifies whether or not the client should respond to subnet mask requests using ICMP. A value of 0 indicates that the client should not respond. A value of 1 means that the client should respond. * perform_router_discovery RFC code : 31 Type : Bool This option specifies whether or not the client should solicit routers using the Router Discovery mechanism defined in RFC 1256. A value of 0 indicates that the client should not perform router discovery. A value of 1 means that the client should perform router discovery. * router_solicitation_address RFC code : 32 Type : Single IP This option specifies the address to which the client should transmit router solicitation requests. * static_route RFC code : 33 Type : Special - Multiple of 2 IP. This option specifies a list of static routes that the client should install in its routing cache. If multiple routes to the same destination are specified, they are listed in descending order of priority. The routes consist of a list of IP address pairs. The first address is the destination address, and the second address is the router for the destination. The default route (0.0.0.0) is an illegal destination for a static route. Link Layer Parameters per Interface =================================== This section lists the options that affect the operation of the data link layer on a per-interface basis. * trailer_encapsulation RFC code : 34 Type : Bool This option specifies whether or not the client should negotiate the use of trailers (RFC 893) when using the ARP protocol. A value of 0 indicates that the client should not attempt to use trailers. A value of 1 means that the client should attempt to use trailers. * arp_cache_timeout RFC code : 35 Type : 32-bits unsigned int This option specifies the timeout in seconds for ARP cache entries. The time is specified as a 32-bit unsigned integer. * ethernet_encapsulation RFC code : 36 Type : Bool This option specifies whether or not the client should use Ethernet Version 2 (RFC 894) or IEEE 802.3 (RFC 1042) encapsulation if the interface is an Ethernet. A value of 0 indicates that the client should use RFC 894 encapsulation. A value of 1 means that the client should use RFC 1042 encapsulation. TCP Parameters ============== This section lists the options that affect the operation of the TCP layer on a per-interface basis. * tcp_default_ttl RFC code : 37 Type : 8-bits unsigned integer This option specifies the default TTL that the client should use when sending TCP segments. The minimum value is 1. * tcp_keepalive_interval RFC code : 38 Type : 32-bits unsigned integer This option specifies the interval (in seconds) that the client TCP should wait before sending a keepalive message on a TCP connection. A value of zero indicates that the client should not generate keepalive messages on connections unless specifically requested by an application. * tcp_keepalive_garbage RFC code : 39 Type : Bool This option specifies the whether or not the client should send TCP keepalive messages with a octet of garbage for compatibility with older implementations. A value of 0 indicates that a garbage octet should not be sent. A value of 1 indicates that a garbage octet should be sent. Application and Service Parameters ================================== This section details some miscellaneous options used to configure miscellaneous applications and services. * nis_domain RFC code : 40 Type : String This option specifies the name of the client's NIS [17] domain. The domain is formatted as a character string consisting of characters from the NVT ASCII character set. * nis_servers RFC code : 41 Type : Multiple IP This option specifies a list of IP addresses indicating NIS servers available to the client. Servers SHOULD be listed in order of preference. * ntp_servers RFC code : 42 Type : Multiple IP This option specifies a list of IP addresses indicating NTP servers available to the client. Servers SHOULD be listed in order of preference. * vendor_specific_information RFC code : 43 Type : Special - n-octet This option is used by clients and servers to exchange vendor-specific information. The information is an opaque object of N octets, presumably interpreted by vendor-specific code on the clients and servers. The definition of this information is vendor specific. The vendor is indicated in the vendor class identifier option. Servers not equipped to interpret the vendor-specific information sent by a client MUST ignore it (although it may be reported). Clients which do not receive desired vendor-specific information SHOULD make an attempt to operate without it, although they may do so (and announce they are doing so) in a degraded mode. If a vendor potentially encodes more than one item of information in this option, then the vendor SHOULD encode the option using "Encapsulated vendor-specific options" as described below: The Encapsulated vendor-specific options field SHOULD be encoded as a sequence of code/length/value fields of identical syntax to the DHCP options field with the following exceptions: * There SHOULD NOT be a "magic cookie" field in the encapsulated vendor-specific extensions field. * Codes other than 0 or 255 MAY be redefined by the vendor within the encapsulated vendor-specific extensions field, but SHOULD conform to the tag-length-value syntax defined in section 2. * Code 255 (END), if present, signifies the end of the encapsulated vendor extensions, not the end of the vendor extensions field. If no code 255 is present, then the end of the enclosing vendor-specific information field is taken as the end of the encapsulated vendor-specific extensions field. * nbns RFC code : 44 Type : Multiple IP The NetBIOS name server (NBNS) option specifies a list of RFC 1001/1002 NBNS name servers listed in order of preference. * nbdd RFC code : 45 Type : Multiple IP The NetBIOS datagram distribution server (NBDD) option specifies a list of RFC 1001/1002 NBDD servers listed in order of preference. * nb_node_type RFC code : 46 Type : special - one octet The NetBIOS node type option allows NetBIOS over TCP/IP clients which are configurable to be configured as described in RFC 1001/1002. The value is specified as a single octet which identifies the client type as follows: Value Node Type ----- --------- 0x1 B-node 0x2 P-node 0x4 M-node 0x8 H-node In the above chart, the notation '0x' indicates a number in base-16 (hexadecimal). * nb_scope RFC code :47 Type : Special - String The NetBIOS scope option specifies the NetBIOS over TCP/IP scope parameter for the client as specified in RFC 1001/1002. * x_window_system_font_server RFC code : 48 Type : Multiple IP This option specifies a list of X Window System [21] Font servers available to the client. Servers SHOULD be listed in order of preference. The code for this option is 48. The minimum length of this option is 4 octets, and the length MUST be a multiple of 4. * x_window_system_display_manager RFC code : 49 Type : Multiple IP This option specifies a list of IP addresses of systems that are running the X Window System Display Manager and are available to the client. Addresses SHOULD be listed in order of preference. * nis+_domain RFC code : 64 Type : String This option specifies the name of the client's NIS+ [17] domain. The domain is formatted as a character string consisting of characters from the NVT ASCII character set. * nis+_servers RFC code : 65 Type : Multiple IP This option specifies a list of IP addresses indicating NIS+ servers available to the client. Servers SHOULD be listed in order of preference. * mobile_ip_home_agent RFC code : 68 Type : Special - Multiple IP This option specifies a list of IP addresses indicating mobile IP home agents available to the client. Agents SHOULD be listed in order of preference. Its minimum length is 0 (indicating no home agents are available). * smtp_server RFC code : 69 Type : Multiple IP The SMTP server option specifies a list of SMTP servers available to the client. Servers SHOULD be listed in order of preference. * pop3_server RFC code : 70 Type : Multiple IP The POP3 server option specifies a list of POP3 available to the client. Servers SHOULD be listed in order of preference. * nntp_server RFC code : 71 Type : Multiple IP The NNTP server option specifies a list of NNTP available to the client. Servers SHOULD be listed in order of preference. * default_www_server RFC code : 72 Type : Multiple IP The WWW server option specifies a list of WWW available to the client. Servers SHOULD be listed in order of preference. * default_finger_server RFC code : 73 Type : Multiple IP The Finger server option specifies a list of Finger available to the client. Servers SHOULD be listed in order of preference. * default_irc_server RFC code : 74 Type : Multiple IP The IRC server option specifies a list of IRC available to the client. Servers SHOULD be listed in order of preference. * streettalk_server RFC code : 75 Type : Multiple IP The StreetTalk server option specifies a list of StreetTalk servers available to the client. Servers SHOULD be listed in order of preference. * streettalk_directory_assistance_server RFC code : 76 Type : Multiple IP The StreetTalk Directory Assistance (STDA) server option specifies a list of STDA servers available to the client. Servers SHOULD be listed in order of preference. 9. DHCP Extensions ================== This section details the options that are specific to DHCP. * requested_ip_address RFC code : 50 Type : Single IP This option is used in a client request (DHCPDISCOVER) to allow the client to request that a particular IP address be assigned. * ip_address_lease_time RFC code : 51 Type : 32-bits unsigned integer This option is used in a client request (DHCPDISCOVER or DHCPREQUEST) to allow the client to request a lease time for the IP address. In a server reply (DHCPOFFER), a DHCP server uses this option to specify the lease time it is willing to offer. The time is in units of seconds. * option_overload RFC code : 52 Type : 8-bit Warning : Do not use. This option will be automagically managed by the pydhcplib. This option is used to indicate that the DHCP 'sname' or 'file' fields are being overloaded by using them to carry DHCP options. A DHCP server inserts this option if the returned parameters will exceed the usual space allotted for options. If this option is present, the client interprets the specified additional fields after it concludes interpretation of the standard option fields. Legal values for this option are: Value Meaning ----- -------- 1 the 'file' field is used to hold options 2 the 'sname' field is used to hold options 3 both fields are used to hold options * tftp_server_name RFC code : 66 Type : String This option is used to identify a TFTP server when the 'sname' field in the DHCP header has been used for DHCP options. * bootfile_name RFC code : 67 Type : String This option is used to identify a bootfile when the 'file' field in the DHCP header has been used for DHCP options. * dhcp_message_type RFC code : 53 Type : Special - 8-bits This option is used to convey the type of the DHCP message. Legal values for this option are: Value Message Type ----- ------------ 1 DHCPDISCOVER 2 DHCPOFFER 3 DHCPREQUEST 4 DHCPDECLINE 5 DHCPACK 6 DHCPNAK 7 DHCPRELEASE 8 DHCPINFORM * server_identifier RFC code : 54 Type : Single IP This option is used in DHCPOFFER and DHCPREQUEST messages, and may optionally be included in the DHCPACK and DHCPNAK messages. DHCP servers include this option in the DHCPOFFER in order to allow the client to distinguish between lease offers. DHCP clients use the contents of the 'server identifier' field as the destination address for any DHCP messages unicast to the DHCP server. DHCP clients also indicate which of several lease offers is being accepted by including this option in a DHCPREQUEST message. The identifier is the IP address of the selected server. * Parameter Request List RFC code : 55 Type : Special - N octets This option is used by a DHCP client to request values for specified configuration parameters. The list of requested parameters is specified as n octets, where each octet is a valid DHCP option code as defined in this document. The client MAY list the options in order of preference. The DHCP server is not required to return the options in the requested order, but MUST try to insert the requested options in the order requested by the client. * message RFC code : 56 Type : String This option is used by a DHCP server to provide an error message to a DHCP client in a DHCPNAK message in the event of a failure. A client may use this option in a DHCPDECLINE message to indicate the why the client declined the offered parameters. The message consists of N octets of NVT ASCII text, which the client may display on an available output device. * maximum_dhcp_message_size RFC code : 57 Type : 16-bits unsigned integer This option specifies the maximum length DHCP message that it is willing to accept. The length is specified as an unsigned 16-bit integer. A client may use the maximum DHCP message size option in DHCPDISCOVER or DHCPREQUEST messages, but should not use the option in DHCPDECLINE messages. The minimum legal value is 576 octets. * renewal_time_value RFC code : 58 Type : 32-bits unsigned integer This option specifies the time interval from address assignment until the client transitions to the RENEWING state. The value is in units of seconds, and is specified as a 32-bit unsigned integer. * rebinding_time_value RFC code : 59 Type : 32-bits unsigned integer This option specifies the time interval from address assignment until the client transitions to the REBINDING state. * vendor_class_identifier RFC code : 60 Type : String This option is used by DHCP clients to optionally identify the vendor type and configuration of a DHCP client. The information is a string of n octets, interpreted by servers. Vendors may choose to define specific vendor class identifiers to convey particular configuration or other identification information about a client. For example, the identifier may encode the client's hardware configuration. Servers not equipped to interpret the class-specific information sent by a client MUST ignore it (although it may be reported). Servers that respond SHOULD only use option 43 to return the vendor-specific information to the client. * client_identifier RFC code : 61 Type : Special This option is used by DHCP clients to specify their unique identifier. DHCP servers use this value to index their database of address bindings. This value is expected to be unique for all clients in an administrative domain. Identifiers SHOULD be treated as opaque objects by DHCP servers. The client identifier MAY consist of type-value pairs similar to the 'htype'/'chaddr' fields. For instance, it MAY consist of a hardware type and hardware address. In this case the type field SHOULD be one of the ARP hardware types defined in STD2. A hardware type of 0 (zero) should be used when the value field contains an identifier other than a hardware address (e.g. a fully qualified domain name). For correct identification of clients, each client's client-identifier MUST be unique among the client-identifiers used on the subnet to which the client is attached. Vendors and system administrators are responsible for choosing client-identifiers that meet this requirement for uniqueness. pydhcplib-0.6.2/pydhcplib/0000755000175000017500000000000011366364415013610 5ustar matmatpydhcplib-0.6.2/pydhcplib/type_hw_addr.py0000644000175000017500000000147111366364415016636 0ustar matmat# pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Temporarily needed for backward compatibilities. from pydhcplib.type_hwmac import * pydhcplib-0.6.2/pydhcplib/dhcp_network.py0000644000175000017500000002006611366364415016655 0ustar matmat# pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import sys import socket import select import dhcp_packet import IN class DhcpNetwork: def __init__(self, listen_address="0.0.0.0", listen_port=67, emit_port=68): self.listen_port = int(listen_port) self.emit_port = int(emit_port) self.listen_address = listen_address self.so_reuseaddr = False self.so_broadcast = True self.dhcp_socket = None # Networking stuff def CreateSocket(self) : try : self.dhcp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) except socket.error, msg : sys.stderr.write('pydhcplib.DhcpNetwork socket creation error : '+str(msg)) try : if self.so_broadcast : self.dhcp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1) except socket.error, msg : sys.stderr.write('pydhcplib.DhcpNetwork socket error in setsockopt SO_BROADCAST : '+str(msg)) try : if self.so_reuseaddr : self.dhcp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) except socket.error, msg : sys.stderr.write('pydhcplib.DhcpNetwork socket error in setsockopt SO_REUSEADDR : '+str(msg)) def EnableReuseaddr(self) : self.so_reuseaddr = True def DisableReuseaddr(self) : self.so_reuseaddr = False def EnableBroadcast(self) : self.so_broadcast = True def DisableBroadcast(self) : self.so_broadcast = False def BindToDevice(self) : try : self.dhcp_socket.setsockopt(socket.SOL_SOCKET,IN.SO_BINDTODEVICE,self.listen_address+'\0') except socket.error, msg : sys.stderr.write ('pydhcplib.DhcpNetwork.BindToDevice error in setsockopt SO_BINDTODEVICE : '+str(msg)) try : self.dhcp_socket.bind(('', self.listen_port)) except socket.error, msg : sys.stderr.write( 'pydhcplib.DhcpNetwork.BindToDevice error : '+str(msg)) def BindToAddress(self) : try : self.dhcp_socket.bind((self.listen_address, self.listen_port)) except socket.error,msg : sys.stderr.write( 'pydhcplib.DhcpNetwork.BindToAddress error : '+str(msg)) def GetNextDhcpPacket(self,timeout=60): data ="" while data == "" : data_input,data_output,data_except = select.select([self.dhcp_socket],[],[],timeout) if( data_input != [] ) : (data,source_address) = self.dhcp_socket.recvfrom(2048) else : return None if data != "" : packet = dhcp_packet.DhcpPacket() packet.source_address = source_address packet.DecodePacket(data) self.HandleDhcpAll(packet) if packet.IsDhcpDiscoverPacket(): self.HandleDhcpDiscover(packet) elif packet.IsDhcpRequestPacket(): self.HandleDhcpRequest(packet) elif packet.IsDhcpDeclinePacket(): self.HandleDhcpDecline(packet) elif packet.IsDhcpReleasePacket(): self.HandleDhcpRelease(packet) elif packet.IsDhcpInformPacket(): self.HandleDhcpInform(packet) elif packet.IsDhcpOfferPacket(): self.HandleDhcpOffer(packet) elif packet.IsDhcpAckPacket(): self.HandleDhcpAck(packet) elif packet.IsDhcpNackPacket(): self.HandleDhcpNack(packet) else: self.HandleDhcpUnknown(packet) return packet def SendDhcpPacketTo(self, packet, _ip,_port): return self.dhcp_socket.sendto(packet.EncodePacket(),(_ip,_port)) # Server side Handle methods def HandleDhcpDiscover(self, packet): pass def HandleDhcpRequest(self, packet): pass def HandleDhcpDecline(self, packet): pass def HandleDhcpRelease(self, packet): pass def HandleDhcpInform(self, packet): pass # client-side Handle methods def HandleDhcpOffer(self, packet): pass def HandleDhcpAck(self, packet): pass def HandleDhcpNack(self, packet): pass # Handle unknown options or all options def HandleDhcpUnknown(self, packet): pass def HandleDhcpAll(self, packet): pass class DhcpServer(DhcpNetwork) : def __init__(self, listen_address="0.0.0.0", client_listen_port=68,server_listen_port=67) : DhcpNetwork.__init__(self,listen_address,server_listen_port,client_listen_port) self.EnableBroadcast() self.DisableReuseaddr() self.CreateSocket() self.BindToAddress() class DhcpClient(DhcpNetwork) : def __init__(self, listen_address="0.0.0.0", client_listen_port=68,server_listen_port=67) : DhcpNetwork.__init__(self,listen_address,client_listen_port,server_listen_port) self.EnableBroadcast() self.EnableReuseaddr() self.CreateSocket() class DhcpClientOld(DhcpNetwork) : def __init__(self, listen_address="0.0.0.0",client_listen_port=68,server_listen_port=67) : DhcpNetwork.__init__(self,listen_address,client_listen_port,server_listen_port) try : self.dhcp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) except socket.error, msg : sys.stderr.write( 'pydhcplib.DhcpClient socket creation error : '+str(msg)) try : self.dhcp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1) self.dhcp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) except socket.error, msg : sys.stderr.write( 'pydhcplib.DhcpClient socket error in setsockopt SO_BROADCAST or SO_REUSEADDR : '+str(msg)) def BindToDevice(self) : try : self.dhcp_socket.setsockopt(socket.SOL_SOCKET,IN.SO_BINDTODEVICE,self.listen_address+'\0') except socket.error, msg : sys.stderr.write( 'pydhcplib.DhcpClient socket error in setsockopt SO_BINDTODEVICE : '+str(msg)) try : self.dhcp_socket.bind(('', self.listen_port)) except socket.error, msg : sys.stderr.write( 'pydhcplib.DhcpClient bind error : '+str(msg)) def BindToAddress(self) : try : self.dhcp_socket.bind((self.listen_address, self.listen_port)) except socket.error,msg : sys.stderr.write( 'pydhcplib.DhcpClient bind error : '+str(msg)) class DhcpServerOld(DhcpNetwork) : def __init__(self, listen_address="0.0.0.0", client_listen_port=68,server_listen_port=67) : DhcpNetwork.__init__(self,listen_address,server_listen_port,client_listen_port) try : self.dhcp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) except socket.error, msg : sys.stderr.write( 'pydhcplib.DhcpServer socket creation error : '+str(msg)) try: self.dhcp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1) except socket.error, msg : sys.stderr.write( 'pydhcplib.DhcpServer socket error in setsockopt SO_BROADCAST : '+str(msg)) try : self.dhcp_socket.bind((self.listen_address, self.listen_port)) except socket.error, msg : sys.stderr.write( 'pydhcplib.DhcpServer bind error : '+str(msg)) pydhcplib-0.6.2/pydhcplib/type_hwmac.py0000644000175000017500000000537511366364415016334 0ustar matmat# pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from binascii import unhexlify,hexlify # Check and convert hardware/nic/mac address type class hwmac: def __init__(self,value="00:00:00:00:00:00") : self._hw_numlist = [] self._hw_string = "" hw_type = type(value) if hw_type == str : value = value.strip() self._hw_string = value self._StringToNumlist(value) self._CheckNumList() elif hw_type == list : self._hw_numlist = value self._CheckNumList() self._NumlistToString() else : raise TypeError , 'hwmac init : Valid types are str and list' # Check if _hw_numlist is valid and raise error if not. def _CheckNumList(self) : if len(self._hw_numlist) != 6 : raise ValueError , "hwmac : wrong list length." for part in self._hw_numlist : if type (part) != int : raise TypeError , "hwmac : each element of list must be int" if part < 0 or part > 255 : raise ValueError , "hwmac : need numbers between 0 and 255." return True def _StringToNumlist(self,value): self._hw_string = self._hw_string.replace("-",":").replace(".",":") self._hw_string = self._hw_string.lower() for twochar in self._hw_string.split(":"): self._hw_numlist.append(ord(unhexlify(twochar))) # Convert NumList type ip to String type ip def _NumlistToString(self) : self._hw_string = ":".join(map(hexlify,map(chr,self._hw_numlist))) # Convert String type ip to NumList type ip # return ip string def str(self) : return self._hw_string # return ip list (useful for DhcpPacket class) def list(self) : return self._hw_numlist def __hash__(self) : return self._hw_string.__hash__() def __repr__(self) : return self._hw_string def __cmp__(self,other) : if self._hw_string == other : return 0 return 1 def __nonzero__(self) : if self._hw_string != "00:00:00:00:00:00" : return 1 return 0 pydhcplib-0.6.2/pydhcplib/dhcp_file_io.py0000644000175000017500000000434211366364415016571 0ustar matmat# pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import sys import dhcp_packet import IN class DhcpFileIO() : def __init__(self) : self.binary = False self.filedesc = False def EnableBinaryTransport(self) : self.binary = True def DisableBinaryTransport(self) : self.binary = False def SendDhcpPacketTo(self,packet,forgetthisparameter1=None,forgetthisparameter2=None) : if self.filedesc and self.binary : self.filedesc.write(packet.EncodePacket()) elif self.filedesc and not self.binary : self.filedesc.write(packet.str()) def GetNextDhcpPacket(self) : if self.filedesc and self.binary : packet = dhcp_packet.DhcpPacket() data = self.filedesc.read(4096) packet.DecodePacket(data) return packet elif self.filedesc and not self.binary : packet = dhcp_packet.DhcpPacket() for line in self.filedesc : packet.AddLine(line) return packet class DhcpStdIn(DhcpFileIO) : def __init__(self) : self.EnableBinaryTransport() self.filedesc = sys.stdin class DhcpStdOut(DhcpFileIO) : def __init__(self) : self.EnableBinaryTransport() self.filedesc = sys.stdout class DhcpFileOut(DhcpFileIO) : def __init__(self,filename) : self.filedesc = file(filename, 'w') self.EnableBinaryTransport() class DhcpFileIn(DhcpFileIO) : def __init__(self,filename) : self.filedesc = file(filename, 'r') self.EnableBinaryTransport() pydhcplib-0.6.2/pydhcplib/interface.py0000644000175000017500000001424611366364415016131 0ustar matmat#!/usr/bin/python # -*- coding: utf-8 -*- # # Copyright (C) 2005, TUBITAK/UEKAE # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. Please read the COPYING file. # import os import array import fcntl import struct import socket class interface: """ ioctl stuff """ IFNAMSIZ = 16 # interface name size # From SIOCGIFADDR = 0x8915 # get PA address SIOCGIFBRDADDR = 0x8919 # get broadcast PA address SIOCGIFCONF = 0x8912 # get iface list SIOCGIFFLAGS = 0x8913 # get flags SIOCGIFMTU = 0x8921 # get MTU size SIOCGIFNETMASK = 0x891b # get network PA mask SIOCSIFADDR = 0x8916 # set PA address SIOCSIFBRDADDR = 0x891a # set broadcast PA address SIOCSIFFLAGS = 0x8914 # set flags SIOCSIFMTU = 0x8922 # set MTU size SIOCSIFNETMASK = 0x891c # set network PA mask # From IFF_UP = 0x1 # Interface is up. IFF_BROADCAST = 0x2 # Broadcast address valid. IFF_DEBUG = 0x4 # Turn on debugging. IFF_LOOPBACK = 0x8 # Is a loopback net. IFF_POINTOPOINT = 0x10 # Interface is point-to-point link. IFF_NOTRAILERS = 0x20 # Avoid use of trailers. IFF_RUNNING = 0x40 # Resources allocated. IFF_NOARP = 0x80 # No address resolution protocol. IFF_PROMISC = 0x100 # Receive all packets. IFF_ALLMULTI = 0x200 # Receive all multicast packets. IFF_MASTER = 0x400 # Master of a load balancer. IFF_SLAVE = 0x800 # Slave of a load balancer. IFF_MULTICAST = 0x1000 # Supports multicast. IFF_PORTSEL = 0x2000 # Can set media type. IFF_AUTOMEDIA = 0x4000 # Auto media select active. def __init__(self): # create a socket to communicate with system self.sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) def _ioctl(self, func, args): return fcntl.ioctl(self.sockfd.fileno(), func, args) def _call(self, ifname, func, ip = None): if ip is None: data = (ifname + '\0'*32)[:32] else: ifreq = (ifname + '\0' * self.IFNAMSIZ)[:self.IFNAMSIZ] data = struct.pack("16si4s10x", ifreq, socket.AF_INET, socket.inet_aton(ip)) try: result = self._ioctl(func, data) except IOError: return None return result def getInterfaceList(self): """ Get all interface names in a list """ # get interface list buffer = array.array('c', '\0' * 1024) ifconf = struct.pack("iP", buffer.buffer_info()[1], buffer.buffer_info()[0]) result = self._ioctl(self.SIOCGIFCONF, ifconf) # loop over interface names iflist = [] size, ptr = struct.unpack("iP", result) for idx in range(0, size, 32): ifconf = buffer.tostring()[idx:idx+32] name, dummy = struct.unpack("16s16s", ifconf) name, dummy = name.split('\0', 1) iflist.append(name) return iflist def getAddr(self, ifname): """ Get the inet addr for an interface """ result = self._call(ifname, self.SIOCGIFADDR) return socket.inet_ntoa(result[20:24]) def getNetmask(self, ifname): """ Get the netmask for an interface """ result = self._call(ifname, self.SIOCGIFNETMASK) return socket.inet_ntoa(result[20:24]) def getBroadcast(self, ifname): """ Get the broadcast addr for an interface """ result = self._call(ifname, self.SIOCGIFBRDADDR) return socket.inet_ntoa(result[20:24]) def getStatus(self, ifname): """ Check whether interface is UP """ result = self._call(ifname, self.SIOCGIFFLAGS) flags, = struct.unpack('H', result[16:18]) return (flags & self.IFF_UP) != 0 def getMTU(self, ifname): """ Get the MTU size of an interface """ data = self._call(ifname, self.SIOCGIFMTU) mtu = struct.unpack("16si12x", data)[1] return mtu def setAddr(self, ifname, ip): """ Set the inet addr for an interface """ result = self._call(ifname, self.SIOCSIFADDR, ip) if result and socket.inet_ntoa(result[20:24]) is ip: return True else: return None def setNetmask(self, ifname, ip): """ Set the netmask for an interface """ result = self._call(ifname, self.SIOCSIFNETMASK, ip) if result and socket.inet_ntoa(result[20:24]) is ip: return True else: return None def setBroadcast(self, ifname, ip): """ Set the broadcast addr for an interface """ result = self._call(ifname, self.SIOCSIFBRDADDR, ip) if socket.inet_ntoa(result[20:24]) is ip: return True else: return None def setStatusDown(self, ifname): """ Set interface status (UP/DOWN) """ ifreq = (ifname + '\0' * self.IFNAMSIZ)[:self.IFNAMSIZ] result = self._call(ifname, self.SIOCGIFFLAGS) flags, = struct.unpack('H', result[16:18]) flags &= ~self.IFF_UP data = struct.pack("16sh", ifreq, flags) result = self._ioctl(self.SIOCSIFFLAGS, data) return result def setStatusUp(self, ifname): """ Set interface status (UP/DOWN) """ ifreq = (ifname + '\0' * self.IFNAMSIZ)[:self.IFNAMSIZ] flags = self.IFF_UP flags |= self.IFF_RUNNING flags |= self.IFF_BROADCAST flags |= self.IFF_MULTICAST flags &= ~self.IFF_NOARP flags &= ~self.IFF_PROMISC data = struct.pack("16sh", ifreq, flags) result = self._ioctl(self.SIOCSIFFLAGS, data) return result def setMTU(self, ifname, mtu): """ Set the MTU size of an interface """ ifreq = (ifname + '\0' * self.IFNAMSIZ)[:self.IFNAMSIZ] data = struct.pack("16si", ifreq, mtu) result = self._ioctl(self.SIOCSIFMTU, data) if struct.unpack("16si", result)[1] is mtu: return True else: return None pydhcplib-0.6.2/pydhcplib/type_strlist.py0000644000175000017500000000343511366364415016734 0ustar matmat# pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . class strlist : def __init__(self,data="") : str_type = type(data) self._str = "" self._list = [] if str_type == str : self._str = data for each in range(len(self._str)) : self._list.append(ord(self._str[each])) elif str_type == list : self._list = data self._str = "".join(map(chr,self._list)) else : raise TypeError , 'strlist init : Valid types are str and list of int' # return string def str(self) : return self._str # return list (useful for DhcpPacket class) def list(self) : return self._list # return int # FIXME def int(self) : return 0 """ Useful function for native python operations """ def __hash__(self) : return self._str.__hash__() def __repr__(self) : return self._str def __nonzero__(self) : if self._str != "" : return 1 return 0 def __cmp__(self,other) : if self._str == other : return 0 return 1 pydhcplib-0.6.2/pydhcplib/__init__.py0000644000175000017500000000002411366364415015715 0ustar matmat__version__ = '0.2' pydhcplib-0.6.2/pydhcplib/dhcp_basic_packet.py0000644000175000017500000001562011366364415017574 0ustar matmat# pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import operator from struct import unpack from struct import pack from dhcp_constants import * import sys # DhcpPacket : base class to encode/decode dhcp packets. class DhcpBasicPacket: def __init__(self): self.packet_data = [0]*240 self.options_data = {} self.packet_data[236:240] = MagicCookie self.source_address = False def IsDhcpPacket(self): if self.packet_data[236:240] != MagicCookie : return False return True # Check if variable is a list with int between 0 and 255 def CheckType(self,variable): if type(variable) == list : for each in variable : if (type(each) != int) or (each < 0) or (each > 255) : return False return True else : return False def DeleteOption(self,name): # if name is a standard dhcp field # Set field to 0 if DhcpFields.has_key(name) : begin = DhcpFields[name][0] end = DhcpFields[name][0]+DhcpFields[name][1] self.packet_data[begin:end] = [0]*DhcpFields[name][1] return True # if name is a dhcp option # delete option from self.option_data elif self.options_data.has_key(name) : # forget how to remove a key... try delete self.options_data.__delitem__(name) return True return False def GetOption(self,name): if DhcpFields.has_key(name) : option_info = DhcpFields[name] return self.packet_data[option_info[0]:option_info[0]+option_info[1]] elif self.options_data.has_key(name) : return self.options_data[name] return [] def SetOption(self,name,value): # Basic value checking : # has value list a correct length # if name is a standard dhcp field if DhcpFields.has_key(name) : if len(value) != DhcpFields[name][1] : sys.stderr.write( "pydhcplib.dhcp_basic_packet.setoption error, bad option length : "+name) return False begin = DhcpFields[name][0] end = DhcpFields[name][0]+DhcpFields[name][1] self.packet_data[begin:end] = value return True # if name is a dhcp option elif DhcpOptions.has_key(name) : # fields_specs : {'option_code':fixed_length,minimum_length,multiple} # if fixed_length == 0 : minimum_length and multiple apply # else : forget minimum_length and multiple # multiple : length MUST be a multiple of 'multiple' # FIXME : this definition should'nt be in dhcp_constants ? fields_specs = { "ipv4":[4,0,1], "ipv4+":[0,4,4], "string":[0,0,1], "bool":[1,0,1], "char":[1,0,1], "16-bits":[2,0,1], "32-bits":[4,0,1], "identifier":[0,2,1], "RFC3397":[0,4,1],"none":[0,0,1],"char+":[0,1,1] } specs = fields_specs[DhcpOptionsTypes[DhcpOptions[name]]] length = len(value) if (specs[0]!=0 and specs==length) or (specs[1]<=length and length%specs[2]==0): self.options_data[name] = value return True else : return False sys.stderr.write( "pydhcplib.dhcp_basic_packet.setoption error : unknown option "+name) return False def IsOption(self,name): if self.options_data.has_key(name) : return True elif DhcpFields.has_key(name) : return True else : return False # Encode Packet and return it def EncodePacket(self): # MUST set options in order to respect the RFC (see router option) order = {} for each in self.options_data.keys() : order[DhcpOptions[each]] = [] order[DhcpOptions[each]].append(DhcpOptions[each]) order[DhcpOptions[each]].append(len(self.options_data[each])) order[DhcpOptions[each]] += self.options_data[each] options = [] for each in sorted(order.keys()) : options += (order[each]) packet = self.packet_data[:240] + options packet.append(255) # add end option pack_fmt = str(len(packet))+"c" packet = map(chr,packet) return pack(pack_fmt,*packet) # Insert packet in the object def DecodePacket(self,data,debug=False): self.packet_data = [] self.options_data = {} if (not data) : return False # we transform all data to int list unpack_fmt = str(len(data)) + "c" for i in unpack(unpack_fmt,data): self.packet_data.append(ord(i)) # Some servers or clients don't place magic cookie immediately # after headers and begin options fields only after magic. # These 4 lines search magic cookie and begin iterator after. iterator = 236 end_iterator = len(self.packet_data) while ( self.packet_data[iterator:iterator+4] != MagicCookie and iterator < end_iterator) : iterator += 1 iterator += 4 # parse extended options while iterator < end_iterator : if self.packet_data[iterator] == 0 : # pad option opt_first = iterator+1 iterator += 1 elif self.packet_data[iterator] == 255 : self.packet_data = self.packet_data[:240] # base packet length without magic cookie return elif DhcpOptionsTypes.has_key(self.packet_data[iterator]) and self.packet_data[iterator]!= 255: opt_len = self.packet_data[iterator+1] opt_first = iterator+1 self.options_data[DhcpOptionsList[self.packet_data[iterator]]] = self.packet_data[opt_first+1:opt_len+opt_first+1] iterator += self.packet_data[opt_first] + 2 else : opt_first = iterator+1 iterator += self.packet_data[opt_first] + 2 # cut packet_data to remove options self.packet_data = self.packet_data[:240] # base packet length with magic cookie pydhcplib-0.6.2/pydhcplib/dhcp_constants.py0000644000175000017500000004677311366364415017215 0ustar matmat# pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . MagicCookie = [99,130,83,99] PyDhcpLibVersion = '0.6' # DhcpBaseOptions = '{fieldname':[location,length]} DhcpFields = {'op':[0,1], 'htype':[1,1], 'hlen':[2,1], 'hops':[3,1], 'xid':[4,4], 'secs':[8,2], 'flags':[10,2], 'ciaddr':[12,4], 'yiaddr':[16,4], 'siaddr':[20,4], 'giaddr':[24,4], 'chaddr':[28,16], 'sname':[44,64], 'file':[108,128] } DhcpFieldsName = { 'op' : { '0': 'ERROR_UNDEF', '1' : 'BOOTREQUEST' , '2' : 'BOOTREPLY'}, 'dhcp_message_type' : { '0': 'ERROR_UNDEF', '1': 'DHCP_DISCOVER', '2': 'DHCP_OFFER', '3' : 'DHCP_REQUEST','4':'DHCP_DECLINE', '5': 'DHCP_ACK', '6': 'DHCP_NACK', '7': 'DHCP_RELEASE', '8' : 'DHCP_INFORM' } } DhcpNames = { 'ERROR_UNDEF':0 , 'BOOTREQUEST':1 , 'BOOTREPLY':2 , 'DHCP_DISCOVER':1 , 'DHCP_OFFER':2 , 'DHCP_REQUEST':3 , 'DHCP_DECLINE':4 , 'DHCP_ACK':5 , 'DHCP_NACK':6 , 'DHCP_RELEASE':7 , 'DHCP_INFORM':8 } DhcpFieldsTypes = {'op':"int", 'htype':"int", 'hlen':"int", 'hops':"int", 'xid':"int4", 'secs':"int2", 'flags':"int2", 'ciaddr':"ipv4", 'yiaddr':"ipv4", 'siaddr':"ipv4", 'giaddr':"ipv4", 'chaddr':"hwmac", 'sname':"str", 'file':"str" } # DhcpOptions = 'option_name':option_code DhcpOptions = {'pad':0, # Vendor Extension 'subnet_mask':1,'time_offset':2, 'router':3,'time_server':4,'name_server':5, 'domain_name_server':6,'log_server':7, 'cookie_server':8,'lpr_server':9, 'impress_server':10,'resource_location_server':11, 'host_name':12,'boot_file':13,'merit_dump_file':14, 'domain_name':15,'swap_server':16,'root_path':17,'extensions_path':18, # IP layer parameters per host 'ip_forwarding':19,'nonlocal_source_rooting':20, 'policy_filter':21,'maximum_datagram_reassembly_size':22, 'default_ip_time-to-live':23,'path_mtu_aging_timeout':24, 'path_mtu_table':25, # IP layer parameters per interface 'interface_mtu':26,'all_subnets_are_local':27, 'broadcast_address':28,'perform_mask_discovery':29, 'mask_supplier':30,'perform_router_discovery':31, 'routeur_solicitation_address':32,'static_route':33, # link layer parameters per interface 'trailer_encapsulation':34,'arp_cache_timeout':35, 'ethernet_encapsulation':36, # TCP parameters 'tcp_default_ttl':37,'tcp_keepalive_interval':38, 'tcp_keepalive_garbage':39, # Applications and service parameters 'nis_domain':40, 'nis_servers':41, 'ntp_servers':42, 'vendor_specific':43, 'nbns':44, 'nbdd':45,'nb_node_type':46, 'nb_scope':47,'x_window_system_font_server':48, 'x_window_system_display_manager':49, # DHCP extensions 'request_ip_address':50, 'ip_address_lease_time':51, 'overload':52, 'dhcp_message_type':53, 'server_identifier':54, 'parameter_request_list':55, 'message':56, 'maximum_dhcp_message_size':57, 'renewal_time_value':58, 'rebinding_time_value':59, 'vendor_class':60, 'client_identifier':61, # Add from RFC 2132 'netware_ip_domain_name':62, 'netware_ip_sub_options':63, 'nis+_domain':64, 'nis+_servers':65, 'tftp_server_name':66, 'bootfile_name':67, 'mobile_ip_home_agent':68, 'smtp_servers':69, 'pop_servers':70, 'nntp_servers':71, 'default_www_server':72, 'default_finger_server':73, 'default_irc_server':74, 'streettalk_server':75, 'streettalk_directory_assistance_server':76, 'user_class':77, 'directory_agent':78, 'service_scope':79, 'rapid_commit':80, 'client_fqdn':81, 'relay_agent':82, 'internet_storage_name_service':83, '84':84, 'nds_server':85, 'nds_tree_name':86, 'nds_context':87, '88':88, '89':89, 'authentication':90, 'client_last_transaction_time':91, 'associated_ip':92, 'client_system':93, 'client_ndi':94, 'ldap':95, 'unassigned':96, 'uuid_guid':97, 'open_group_user_auth':98, 'unassigned':99, 'unassigned':100, 'unassigned':101, 'unassigned':102, 'unassigned':103, 'unassigned':104, 'unassigned':105, 'unassigned':106, 'unassigned':107, 'unassigned':108, 'unassigned':109, 'unassigned':110, 'unassigned':111, 'netinfo_address':112, 'netinfo_tag':113, 'url':114, 'unassigned':115, 'auto_config':116, 'name_service_search':117, 'subnet_selection':118, 'domain_search':119, 'sip_servers':120, 'classless_static_route':121, 'cablelabs_client_configuration':122, 'geoconf':123, 'vendor_class':124, 'vendor_specific':125, '126':126,'127':127,'128':128,'129':129, '130':130,'131':131,'132':132,'133':133, '134':134,'135':135,'136':136,'137':137, '138':138,'139':139,'140':140,'141':141, '142':142,'143':143,'144':144,'145':145, '146':146,'147':147,'148':148,'149':149, '150':150,'151':151,'152':152,'153':153, '154':154,'155':155,'156':156,'157':157, '158':158,'159':159,'160':160,'161':161, '162':162,'163':163,'164':164,'165':165, '166':166,'167':167,'168':168,'169':169, '170':170,'171':171,'172':172,'173':173, '174':174,'175':175,'176':176,'177':177, '178':178,'179':179,'180':180,'181':181, '182':182,'183':183,'184':184,'185':185, '186':186,'187':187,'188':188,'189':189, '190':190,'191':191,'192':192,'193':193, '194':194,'195':195,'196':196,'197':197, '198':198,'199':199,'200':200,'201':201, '202':202,'203':203,'204':204,'205':205, '206':206,'207':207,'208':208,'209':209, '210':210,'211':211,'212':212,'213':213, '214':214,'215':215,'216':216,'217':217, '218':218,'219':219,'220':220,'221':221, '222':222,'223':223,'224':224,'225':225, '226':226,'227':227,'228':228,'229':229, '230':230,'231':231,'232':232,'233':233, '234':234,'235':235,'236':236,'237':237, '238':238,'239':239,'240':240,'241':241, '242':242,'243':243,'244':244,'245':245, '246':246,'247':247,'248':248,'249':249, '250':250,'251':251,'252':252,'253':253, '254':254,'end':255 } # DhcpOptionsList : reverse of DhcpOptions DhcpOptionsList = ['pad', # Vendor Extension 'subnet_mask','time_offset', 'router','time_server','name_server', 'domain_name_server','log_server', 'cookie_server','lpr_server', 'impress_server','resource_location_server', 'host_name','boot_file','merit_dump_file', 'domain_name','swap_server','root_path','extensions_path', # IP layer parameters per host 'ip_forwarding','nonlocal_source_rooting', 'policy_filter','maximum_datagram_reassembly_size', 'default_ip_time-to-live','path_mtu_aging_timeout', 'path_mtu_table', # IP layer parameters per interface 'interface_mtu','all_subnets_are_local', 'broadcast_address','perform_mask_discovery', 'mask_supplier','perform_router_discovery', 'routeur_solicitation_address','static_route', # link layer parameters per interface 'trailer_encapsulation','arp_cache_timeout', 'ethernet_encapsulation', # TCP parameters 'tcp_default_ttl','tcp_keepalive_interval', 'tcp_keepalive_garbage', # Applications and service parameters 'nis_domain', 'nis_servers', 'ntp_servers', 'vendor_specific','nbns', 'nbdd','nd_node_type', 'nb_scope','x_window_system_font_server', 'x_window_system_display_manager', # DHCP extensions 'request_ip_address', 'ip_address_lease_time', 'overload', 'dhcp_message_type', 'server_identifier', 'parameter_request_list', 'message', 'maximum_dhcp_message_size', 'renewal_time_value', 'rebinding_time_value', 'vendor_class', 'client_identifier', # adds from RFC 2132,2242 'netware_ip_domain_name', 'netware_ip_sub_options', 'nis+_domain', 'nis+_servers', 'tftp_server_name', 'bootfile_name', 'mobile_ip_home_agent', 'smtp_servers', 'pop_servers', 'nntp_servers', 'default_www_server', 'default_finger_server', 'default_irc_server', 'streettalk_server', 'streettalk_directory_assistance_server', 'user_class','directory_agent','service_scope', # 80 'rapid_commit','client_fqdn','relay_agent', 'internet_storage_name_service', '84', 'nds_server','nds_tree_name','nds_context', '88','89', #90 'authentication', 'client_last_transaction_time','associated_ip', #RFC 4388 'client_system', 'client_ndi', #RFC 3679 'ldap','unassigned','uuid_guid', #RFC 3679 'open_group_user_auth', #RFC 2485 # 99->115 RFC3679 'unassigned','unassigned','unassigned', 'unassigned','unassigned','unassigned', 'unassigned','unassigned','unassigned', 'unassigned','unassigned','unassigned', 'unassigned','netinfo_address','netinfo_tag', 'url','unassigned', #116 'auto_config','name_service_search','subnet_selection', 'domain_search','sip_servers','classless_static_route', 'cablelabs_client_configuration','geoconf', #124 'vendor_class', 'vendor_specific', '126','127','128','129', '130','131','132','133','134','135','136','137','138','139', '140','141','142','143','144','145','146','147','148','149', '150','151','152','153','154','155','156','157','158','159', '160','161','162','163','164','165','166','167','168','169', '170','171','172','173','174','175','176','177','178','179', '180','181','182','183','184','185','186','187','188','189', '190','191','192','193','194','195','196','197','198','199', '200','201','202','203','204','205','206','207','208','209', '210','211','212','213','214','215','216','217','218','219', '220','221','222','223','224','225','226','227','228','229', '230','231','232','233','234','235','236','237','238','239', '240','241','242','243','244','245','246','247','248','249', '250','251','252','253','254', 'end' ] # See http://www.iana.org/assignments/bootp-dhcp-parameters # FIXME : verify all ipv4+ options, somes are 32 bits... DhcpOptionsTypes = {0:"none", 1:"ipv4", 2:"ipv4", 3:"ipv4+", 4:"ipv4+", 5:"ipv4+", 6:"ipv4+", 7:"ipv4+", 8:"ipv4+", 9:"ipv4+", 10:"ipv4+", 11:"ipv4+", 12:"string", 13:"16-bits", 14:"string", 15:"string", 16:"ipv4", 17:"string", 18:"string", 19:"bool", 20:"bool", 21:"ipv4+", 22:"16-bits", 23:"char", 24:"ipv4", 25:"16-bits", 26:"16-bits", 27:"bool", 28:"ipv4", 29:"bool", 30:"bool", 31:"bool", 32:"ipv4", 33:"ipv4+", 34:"bool", 35:"32-bits", 36:"bool", 37:"char", 38:"32-bits", 39:"bool", 40:"string", 41:"ipv4+", 42:"ipv4+", 43:"string", 44:"ipv4+", 45:"ipv4+", 46:"char", 47:"string", 48:"ipv4+", 49:"ipv4+", 50:"ipv4", 51:"32-bits", 52:"char", 53:"char", 54:"32-bits", 55:"char+", 56:"string", 57:"16-bits", 58:"32-bits", 59:"32-bits", 60:"string", 61:"identifier", 62:"string", 63:"RFC2242", 64:"string", 65:"ipv4+", 66:"string", 67:"string", 68:"ipv4", 69:"ipv4+", 70:"ipv4+", 71:"ipv4+", 72:"ipv4+", 73:"ipv4+", 74:"ipv4+", 75:"ipv4+", 76:"ipv4+", 77:"RFC3004", 78:"RFC2610", 79:"RFC2610", 80:"null", 81:"string", 82:"RFC3046", 83:"RFC4174", 84:"Unassigned", 85:"ipv4+", 86:"RFC2241", 87:"RFC2241", 88:"Unassigned", 89:"Unassigned", 90:"RFC3118", 91:"RFC4388", 92:"ipv4+", 93:"Unassigned", 94:"Unassigned", 95:"Unassigned", 96:"Unassigned", 97:"Unassigned", 98:"string", 99:"Unassigned", 100:"Unassigned", 101:"Unassigned", 102:"Unassigned", 103:"Unassigned", 104:"Unassigned", 105:"Unassigned", 106:"Unassigned", 107:"Unassigned", 108:"Unassigned", 109:"Unassigned", 110:"Unassigned", 111:"Unassigned", 112:"Unassigned", 113:"Unassigned", 114:"Unassigned", 115:"Unassigned", 116:"char", 117:"RFC2937", 118:"ipv4", 119:"RFC3397", 120:"RFC3361", #TODO 121:"Unassigned", 122:"Unassigned", 123:"Unassigned", 124:"Unassigned", 125:"Unassigned", 126:"Unassigned", 127:"Unassigned", 128:"Unassigned", 129:"Unassigned", 130:"Unassigned", 131:"Unassigned", 132:"Unassigned", 133:"Unassigned", 134:"Unassigned", 135:"Unassigned", 136:"Unassigned", 137:"Unassigned", 138:"Unassigned", 139:"Unassigned", 140:"Unassigned", 141:"Unassigned", 142:"Unassigned", 143:"Unassigned", 144:"Unassigned", 145:"Unassigned", 146:"Unassigned", 147:"Unassigned", 148:"Unassigned", 149:"Unassigned", 150:"Unassigned", 151:"Unassigned", 152:"Unassigned", 153:"Unassigned", 154:"Unassigned", 155:"Unassigned", 156:"Unassigned", 157:"Unassigned", 158:"Unassigned", 159:"Unassigned", 160:"Unassigned", 161:"Unassigned", 162:"Unassigned", 163:"Unassigned", 164:"Unassigned", 165:"Unassigned", 166:"Unassigned", 167:"Unassigned", 168:"Unassigned", 169:"Unassigned", 170:"Unassigned", 171:"Unassigned", 172:"Unassigned", 173:"Unassigned", 174:"Unassigned", 175:"Unassigned", 176:"Unassigned", 177:"Unassigned", 178:"Unassigned", 179:"Unassigned", 180:"Unassigned", 181:"Unassigned", 182:"Unassigned", 183:"Unassigned", 184:"Unassigned", 185:"Unassigned", 186:"Unassigned", 187:"Unassigned", 188:"Unassigned", 189:"Unassigned", 190:"Unassigned", 191:"Unassigned", 192:"Unassigned", 193:"Unassigned", 194:"Unassigned", 195:"Unassigned", 196:"Unassigned", 197:"Unassigned", 198:"Unassigned", 199:"Unassigned", 200:"Unassigned", 201:"Unassigned", 202:"Unassigned", 203:"Unassigned", 204:"Unassigned", 205:"Unassigned", 206:"Unassigned", 207:"Unassigned", 208:"Unassigned", 209:"Unassigned", 210:"Unassigned", 211:"Unassigned", 212:"Unassigned", 213:"Unassigned", 214:"Unassigned", 215:"Unassigned", 216:"Unassigned", 217:"Unassigned", 218:"Unassigned", 219:"Unassigned", 220:"Unassigned", 221:"Unassigned", 222:"Unassigned", 223:"Unassigned", 224:"Unassigned", 225:"Unassigned", 226:"Unassigned", 227:"Unassigned", 228:"Unassigned", 229:"Unassigned", 230:"Unassigned", 231:"Unassigned", 232:"Unassigned", 233:"Unassigned", 234:"Unassigned", 235:"Unassigned", 236:"Unassigned", 237:"Unassigned", 238:"Unassigned", 239:"Unassigned", 240:"Unassigned", 241:"Unassigned", 242:"Unassigned", 243:"Unassigned", 244:"Unassigned", 245:"Unassigned"} pydhcplib-0.6.2/pydhcplib/dhcp_packet.py0000644000175000017500000003106311366364415016432 0ustar matmat# pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import operator from struct import unpack from struct import pack from dhcp_basic_packet import * from dhcp_constants import * from type_ipv4 import ipv4 from type_strlist import strlist from type_hwmac import hwmac import sys class DhcpPacket(DhcpBasicPacket): def str(self): # Process headers : printable_data = "# Header fields\n" op = self.packet_data[DhcpFields['op'][0]:DhcpFields['op'][0]+DhcpFields['op'][1]] printable_data += "op : " + DhcpFieldsName['op'][str(op[0])] + "\n" for opt in ['htype','hlen','hops','xid','secs','flags', 'ciaddr','yiaddr','siaddr','giaddr','chaddr','sname','file'] : begin = DhcpFields[opt][0] end = DhcpFields[opt][0]+DhcpFields[opt][1] data = self.packet_data[begin:end] result = '' if DhcpFieldsTypes[opt] == "int" : result = str(data[0]) elif DhcpFieldsTypes[opt] == "int2" : result = str(data[0]*256+data[1]) elif DhcpFieldsTypes[opt] == "int4" : result = str(ipv4(data).int()) elif DhcpFieldsTypes[opt] == "str" : for each in data : if each != 0 : result += chr(each) else : break elif DhcpFieldsTypes[opt] == "ipv4" : result = ipv4(data).str() elif DhcpFieldsTypes[opt] == "hwmac" : result = [] hexsym = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'] for iterator in range(6) : result += [str(hexsym[data[iterator]/16]+hexsym[data[iterator]%16])] result = ':'.join(result) printable_data += opt+" : "+result + "\n" # Process options : printable_data += "# Options fields\n" for opt in self.options_data.keys(): data = self.options_data[opt] result = "" optnum = DhcpOptions[opt] if opt=='dhcp_message_type' : result = DhcpFieldsName['dhcp_message_type'][str(data[0])] elif DhcpOptionsTypes[optnum] == "char" : result = str(data[0]) elif DhcpOptionsTypes[optnum] == "16-bits" : result = str(data[0]*256+data[0]) elif DhcpOptionsTypes[optnum] == "32-bits" : result = str(ipv4(data).int()) elif DhcpOptionsTypes[optnum] == "string" : for each in data : if each != 0 : result += chr(each) else : break elif DhcpOptionsTypes[optnum] == "ipv4" : result = ipv4(data).str() elif DhcpOptionsTypes[optnum] == "ipv4+" : for i in range(0,len(data),4) : if len(data[i:i+4]) == 4 : result += ipv4(data[i:i+4]).str() + " - " elif DhcpOptionsTypes[optnum] == "char+" : if optnum == 55 : # parameter_request_list result = ','.join([DhcpOptionsList[each] for each in data]) else : result += str(data) printable_data += opt + " : " + result + "\n" return printable_data def AddLine(self,_string) : (parameter,junk,value) = _string.partition(':') parameter = parameter.strip() # If value begin with a whitespace, remove it, leave others if len(value)>0 and value[0] == ' ' : value = value[1:] value = self._OptionsToBinary(parameter,value) if value : self.SetOption(parameter,value) def _OptionsToBinary(self,parameter,value) : # Transform textual data into dhcp binary data p = parameter.strip() # 1- Search for header informations or specific parameter if p == 'op' or p == 'htype' : value = value.strip() if value.isdigit() : return [int(value)] try : value = DhcpNames[value.strip()] return [value] except KeyError : return [0] elif p == 'hlen' or p == 'hops' : try : value = int(value) return [value] except ValueError : return [0] elif p == 'secs' or p == 'flags' : try : value = ipv4(int(value)).list() except ValueError : value = [0,0,0,0] return value[2:] elif p == 'xid' : try : value = ipv4(int(value)).list() except ValueError : value = [0,0,0,0] return value elif p == 'ciaddr' or p == 'yiaddr' or p == 'siaddr' or p == 'giaddr' : try : ip = ipv4(value).list() except ValueError : ip = [0,0,0,0] return ip elif p == 'chaddr' : try: value = hwmac(value).list()+[0]*10 except ValueError,TypeError : value = [0]*16 return value elif p == 'sname' : return elif p == 'file' : return elif p == 'parameter_request_list' : value = value.strip().split(',') tmp = [] for each in value: if DhcpOptions.has_key(each) : tmp.append(DhcpOptions[each]) return tmp elif p=='dhcp_message_type' : try : return [DhcpNames[value]] except KeyError: return # 2- Search for options try : option_type = DhcpOptionsTypes[DhcpOptions[parameter]] except KeyError : return False if option_type == "ipv4" : # this is a single ip address try : binary_value = map(int,value.split(".")) except ValueError : return False elif option_type == "ipv4+" : # this is multiple ip address iplist = value.split(",") opt = [] for single in iplist : opt += (ipv4(single).list()) binary_value = opt elif option_type == "32-bits" : # This is probably a number... try : digit = int(value) binary_value = [digit>>24&0xFF,(digit>>16)&0xFF,(digit>>8)&0xFF,digit&0xFF] except ValueError : return False elif option_type == "16-bits" : try : digit = int(value) binary_value = [(digit>>8)&0xFF,digit&0xFF] except ValueError : return False elif option_type == "char" : try : digit = int(value) binary_value = [digit&0xFF] except ValueError : return False elif option_type == "bool" : if value=="False" or value=="false" or value==0 : binary_value = [0] else : binary_value = [1] elif option_type == "string" : binary_value = strlist(value).list() else : binary_value = strlist(value).list() return binary_value # FIXME: This is called from IsDhcpSomethingPacket, but is this really # needed? Or maybe this testing should be done in # DhcpBasicPacket.DecodePacket(). # Test Packet Type def IsDhcpSomethingPacket(self,type): if self.IsDhcpPacket() == False : return False if self.IsOption("dhcp_message_type") == False : return False if self.GetOption("dhcp_message_type") != type : return False return True def IsDhcpDiscoverPacket(self): return self.IsDhcpSomethingPacket([1]) def IsDhcpOfferPacket(self): return self.IsDhcpSomethingPacket([2]) def IsDhcpRequestPacket(self): return self.IsDhcpSomethingPacket([3]) def IsDhcpDeclinePacket(self): return self.IsDhcpSomethingPacket([4]) def IsDhcpAckPacket(self): return self.IsDhcpSomethingPacket([5]) def IsDhcpNackPacket(self): return self.IsDhcpSomethingPacket([6]) def IsDhcpReleasePacket(self): return self.IsDhcpSomethingPacket([7]) def IsDhcpInformPacket(self): return self.IsDhcpSomethingPacket([8]) def GetMultipleOptions(self,options=()): result = {} for each in options: result[each] = self.GetOption(each) return result def SetMultipleOptions(self,options={}): for each in options.keys(): self.SetOption(each,options[each]) # Creating Response Packet # Server-side functions # From RFC 2132 page 28/29 def CreateDhcpOfferPacketFrom(self,src): # src = discover packet self.SetOption("htype",src.GetOption("htype")) self.SetOption("xid",src.GetOption("xid")) self.SetOption("flags",src.GetOption("flags")) self.SetOption("giaddr",src.GetOption("giaddr")) self.SetOption("chaddr",src.GetOption("chaddr")) self.SetOption("ip_address_lease_time",src.GetOption("ip_address_lease_time")) self.TransformToDhcpOfferPacket() def TransformToDhcpOfferPacket(self): self.SetOption("dhcp_message_type",[2]) self.SetOption("op",[2]) self.SetOption("hlen",[6]) self.DeleteOption("secs") self.DeleteOption("ciaddr") self.DeleteOption("request_ip_address") self.DeleteOption("parameter_request_list") self.DeleteOption("client_identifier") self.DeleteOption("maximum_message_size") """ Dhcp ACK packet creation """ def CreateDhcpAckPacketFrom(self,src): # src = request or inform packet self.SetOption("htype",src.GetOption("htype")) self.SetOption("xid",src.GetOption("xid")) self.SetOption("ciaddr",src.GetOption("ciaddr")) self.SetOption("flags",src.GetOption("flags")) self.SetOption("giaddr",src.GetOption("giaddr")) self.SetOption("chaddr",src.GetOption("chaddr")) self.SetOption("ip_address_lease_time_option",src.GetOption("ip_address_lease_time_option")) self.TransformToDhcpAckPacket() def TransformToDhcpAckPacket(self): # src = request or inform packet self.SetOption("op",[2]) self.SetOption("hlen",[6]) self.SetOption("dhcp_message_type",[5]) self.DeleteOption("secs") self.DeleteOption("request_ip_address") self.DeleteOption("parameter_request_list") self.DeleteOption("client_identifier") self.DeleteOption("maximum_message_size") """ Dhcp NACK packet creation """ def CreateDhcpNackPacketFrom(self,src): # src = request or inform packet self.SetOption("htype",src.GetOption("htype")) self.SetOption("xid",src.GetOption("xid")) self.SetOption("flags",src.GetOption("flags")) self.SetOption("giaddr",src.GetOption("giaddr")) self.SetOption("chaddr",src.GetOption("chaddr")) self.TransformToDhcpNackPacket() def TransformToDhcpNackPacket(self): self.SetOption("op",[2]) self.SetOption("hlen",[6]) self.DeleteOption("secs") self.DeleteOption("ciaddr") self.DeleteOption("yiaddr") self.DeleteOption("siaddr") self.DeleteOption("sname") self.DeleteOption("file") self.DeleteOption("request_ip_address") self.DeleteOption("ip_address_lease_time_option") self.DeleteOption("parameter_request_list") self.DeleteOption("client_identifier") self.DeleteOption("maximum_message_size") self.SetOption("dhcp_message_type",[6]) """ GetClientIdentifier """ def GetClientIdentifier(self) : if self.IsOption("client_identifier") : return self.GetOption("client_identifier") return [] def GetGiaddr(self) : return self.GetOption("giaddr") def GetHardwareAddress(self) : length = self.GetOption("hlen")[0] full_hw = self.GetOption("chaddr") if length!=[] and length. # Check and convert ipv4 address type class ipv4: def __init__(self,value="0.0.0.0") : ip_type = type(value) if ip_type == str : if not self.CheckString(value) : raise ValueError, "ipv4 string argument is not an valid ip " self._ip_string = value self._StringToNumlist() self._StringToLong() self._NumlistToString() elif ip_type == list : if not self.CheckNumList(value) : raise ValueError, "ipv4 list argument is not an valid ip " self._ip_numlist = value self._NumlistToString() self._StringToLong() elif ip_type == int or ip_type == long: self._ip_long = value self._LongToNumlist() self._NumlistToString() elif ip_type == bool : self._ip_long = 0 self._LongToNumlist() self._NumlistToString() else : raise TypeError , 'ipv4 init : Valid types are str, list, int or long' # Convert Long type ip to numlist ip def _LongToNumlist(self) : self._ip_numlist = [self._ip_long >> 24 & 0xFF] self._ip_numlist.append(self._ip_long >> 16 & 0xFF) self._ip_numlist.append(self._ip_long >> 8 & 0xFF) self._ip_numlist.append(self._ip_long & 0xFF) if not self.CheckNumList(self._ip_numlist) : raise ValueError, "ipv4 list argument is not an valid ip " # Convert String type ip to Long type ip def _StringToLong(self) : ip_numlist = map(int,self._ip_string.split('.')) self._ip_long = ip_numlist[3] + ip_numlist[2]*256 + ip_numlist[1]*256*256 + ip_numlist[0]*256*256*256 if not self.CheckNumList(self._ip_numlist) : raise ValueError, "ipv4 list argument is not an valid ip " # Convert NumList type ip to String type ip def _NumlistToString(self) : self._ip_string = ".".join(map(str,self._ip_numlist)) if not self.CheckNumList(self._ip_numlist) : raise ValueError, "ipv4 list argument is not an valid ip " # Convert String type ip to NumList type ip def _StringToNumlist(self) : self._ip_numlist = map(int,self._ip_string.split('.')) if not self.CheckNumList(self._ip_numlist) : raise ValueError, "ipv4 list argument is not an valid ip " """ Public methods """ # Check if _ip_numlist is valid and raise error if not. # self._ip_numlist def CheckNumList(self,value) : if len(value) != 4 : return False for part in value : if part < 0 or part > 255 : return False return True # Check if _ip_numlist is valid and raise error if not. def CheckString(self,value) : tmp = value.strip().split('.') if len(tmp) != 4 : return False for each in tmp : if not each.isdigit() : return False return True # return ip string def str(self) : return self._ip_string # return ip list (useful for DhcpPacket class) def list(self) : return self._ip_numlist # return Long ip type (useful for SQL ip address backend) def int(self) : return self._ip_long """ Useful function for native python operations """ def __hash__(self) : return self._ip_long.__hash__() def __repr__(self) : return self._ip_string def __cmp__(self,other) : return cmp(self._ip_long, other._ip_long); def __nonzero__(self) : if self._ip_long != 0 : return 1 return 0 pydhcplib-0.6.2/examples/0000755000175000017500000000000011366364415013450 5ustar matmatpydhcplib-0.6.2/examples/client_example.py0000755000175000017500000000321211366364415017014 0ustar matmat#!/usr/bin/python # # pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from pydhcplib.dhcp_packet import * from pydhcplib.dhcp_network import * netopt = {'client_listen_port':68, 'server_listen_port':67, 'listen_address':"0.0.0.0"} class Client(DhcpClient): def __init__(self, options): DhcpClient.__init__(self,options["listen_address"], options["client_listen_port"], options["server_listen_port"]) def HandleDhcpOffer(self, packet): print packet.str() def HandleDhcpAck(self, packet): print packet.str() def HandleDhcpNack(self, packet): print packet.str() client = Client(netopt) # Use BindToAddress if you want to emit/listen to an internet address (like 192.168.1.1) # or BindToDevice if you want to emit/listen to a network device (like eth0) client.BindToAddress() while True : client.GetNextDhcpPacket() print client.str() pydhcplib-0.6.2/examples/server_example.py0000755000175000017500000000307211366364415017050 0ustar matmat#!/usr/bin/python # # pydhcplib # Copyright (C) 2008 Mathieu Ignacio -- mignacio@april.org # # This file is part of pydhcplib. # Pydhcplib is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from pydhcplib.dhcp_packet import * from pydhcplib.dhcp_network import * netopt = {'client_listen_port':"68", 'server_listen_port':"67", 'listen_address':"0.0.0.0"} class Server(DhcpServer): def __init__(self, options): DhcpServer.__init__(self,options["listen_address"], options["client_listen_port"], options["server_listen_port"]) def HandleDhcpDiscover(self, packet): print packet.str() def HandleDhcpRequest(self, packet): print packet.str() def HandleDhcpDecline(self, packet): print packet.str() def HandleDhcpRelease(self, packet): print packet.str() def HandleDhcpInform(self, packet): print packet.str() server = Server(netopt) while True : server.GetNextDhcpPacket() pydhcplib-0.6.2/examples/strlist_example.py0000755000175000017500000000072411366364415017247 0ustar matmat#!/usr/bin/python from pydhcplib.type_strlist import strlist word = strlist() print "a0 : ",word word1 = strlist("azerty") print "a1 : ",word1 word2 = strlist("qwerty") print "a2 : ",word2 word3 = strlist([97, 122, 101, 114, 116, 121]) print "a3 : ",word3 if word1 == word2 : print "test 1 : ",word1, "==",word2 else : print "test 1 : " ,word1, "!=",word2 if word1 == word3 : print "test 2 : ", word1, "==",word3 else : print "test 2 : ", word1, "!=",word3 pydhcplib-0.6.2/examples/ipv4_example.py0000755000175000017500000000077011366364415016426 0ustar matmat#!/usr/bin/python from pydhcplib.type_ipv4 import ipv4 address = ipv4() print "a0 : ",address address1 = ipv4("192.168.0.1") print "a1 : ",address1 address2 = ipv4("10.0.0.1") print "a2 : ",address2 address3 = ipv4([192,168,0,1]) print "a3 : ",address3 if address1 == address2 : print "test 1 : ",address1, "==",address2 else : print "test 1 : " ,address1, "!=",address2 if address1 == address3 : print "test 2 : ", address1, "==",address3 else : print "test 2 : ", address1, "!=",address3 pydhcplib-0.6.2/examples/gen_packet_example.py0000755000175000017500000000066711366364415017651 0ustar matmat#!/usr/bin/python from pydhcplib.dhcp_packet import DhcpPacket from pydhcplib.type_strlist import strlist from pydhcplib.type_ipv4 import ipv4 packet = DhcpPacket() packet.SetOption("op",[1]) packet.SetOption("domain_name",strlist("anemon.org").list()) packet.SetOption("router",ipv4("192.168.0.1").list()+[6,4,2,1]) packet.SetOption("time_server",[100,100,100,7,6,4,2,1]) packet.SetOption("yiaddr",[192,168,0,18]) print packet.str() pydhcplib-0.6.2/examples/hwaddr_example.py0000755000175000017500000000127311366364415017014 0ustar matmat#!/usr/bin/python from pydhcplib.type_hw_addr import hwmac address = hwmac() print "a0 : ",address address1 = hwmac("ff:11:22:33:44:55") print "a1 : ",address1 address2 = hwmac("f6.16.26.36.46.56") print "a2 : ",address2 address3 = hwmac("ff.11-22:33-44.55") print "a3 : ",address3 if address1 == address2 : print "test 1 : ",address1, "==",address2 else : print "test 1 : " ,address1, "!=",address2 if address1 == address3 : print "test 2 : ", address1, "==",address3 else : print "test 2 : ", address1, "!=",address3 address4 = hwmac([186, 45, 67, 176, 6, 11]) address5 = hwmac("ba:2d:43:b0:06:0c") print "b0 : ", address4,address4.list() print "b1 : ", address5,address5.list() pydhcplib-0.6.2/TODO0000644000175000017500000000125711366364415012327 0ustar matmat* Options should be available in list or directly in string form * Server_identifier is not correctly set for selecting state * Write test scripts * Better exception handling * Docs * Package for various systems * Add directory type for dhcp_file_io (multiple file IO support) * Change interface to linux_interface and search for *BSD management * Add a packet.SetTextOption for textual data handling * Handle Maximum DHCP Message Size (option 57) * Handle Overload (option 52) OK * Use recvfrom instead of recv to store source IP of the received packet. OK * Do simple SetParameter in dhcp_packet class to read human readable data (look at anemon server code) OK * Finish import class pydhcplib-0.6.2/README0000644000175000017500000000104511366364415012512 0ustar matmatPydhcplib is a python library to read/write and encode/decode dhcp packet on network. Installation : -------------- On Debian, simply run "./setup.py install". Python modules will be installed in /usr/lib/python2.X/site-packages/pydhcplib/. If you want to install it on a different location, use the --prefix on the setup.py command line like this : ./setup.py install --prefix=/rootpath/to/your/location/ How to use pydhcplib : ---------------------- Look in the examples directory to learn how to use the modules. man pydhcp man pydhcplib pydhcplib-0.6.2/COPYING0000644000175000017500000010451311366364415012671 0ustar matmat GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . pydhcplib-0.6.2/man/0000755000175000017500000000000011366364415012405 5ustar matmatpydhcplib-0.6.2/man/man8/0000755000175000017500000000000011366364415013250 5ustar matmatpydhcplib-0.6.2/man/man8/pydhcp.8.gz0000644000175000017500000000227211366364415015252 0ustar matmatNIpydhcp.8uV[o6 ~ Hfzd8@zm&V{Pl9jK,7 ?R/:_DǏ1'e ͏ou5ppW. Rȥ`{w|4-yZͧf_OW|k?/=o= '6#x H+<ƒ'/‚V=h22*x*3rɾFʴ)ZU0 W瑰ϣWa*~Πe`"<1|r G \z2)RQ%Fo{B(ˠؾVh`UpG Y%&:NKv u ATꬫY&s1mؚGgƑ/^ .WC9KrNUL$V@]aBijDU )&KDBe XUS0 eeTX! A0G]'dA{t`ԸA._/ؘ'_EE*$K|iٺp;@`:=$CQV@t nP >u, ힺAbukIrCB]:K^Ĩsz TdRIyMJ{9a\;T%`Ej@Kn۞1><<؄zfR`y"oI^WUhˁJ”?2ҋ`=ۋ΂KR@()_˄Aq ܈aWF~#4 {D`O/b9 ݙ/:B12 Ӛ&Z_ܷ0ы8"wi>,p"pr& ;Ckj3 7j#s!rT .\Z|`S )ߗ%%&)⧲<&%:םXn̈́o]ܜ(hkxviE .)nЖF'jnu;_ěuc ҿ;..۰bi?݀xm 3f~In<:z6C9n?LRXL=n~,!kQbx"5 m?gΣfV pydhcplib-0.6.2/man/man3/0000755000175000017500000000000011366364415013243 5ustar matmatpydhcplib-0.6.2/man/man3/pydhcplib.3.gz0000644000175000017500000000067211366364415015731 0ustar matmatcIpydhcplib.3uRM0+FҖ7BPm>P̪]=8x۲MR} $g+u'Bt !|k*6EDGmbh%By@ sg~,𫱃!缏nVp rA|,@Ph8O .ʼEypL' #1g_j-5G Z64.R_u76% { כ-^JLX+40Dӟ)kxCu)SBL?H |?u)yA f {Pݧz~(spydhcplib-0.6.2/man/man3/pydhcplib.ipv4.3.gz0000644000175000017500000000131111366364415016601 0ustar matmatTmk@|+r rK0qKI@qgfgv.nvMEbIEzexo<X:O\ CJyV+ɕ ^T"Mә|2E#9O%,̙hp5JEbLo#o1M-p" :9P(W[W9d`9F~M[1T 3m1<#;=`"-ZLl:7iR&]) jQdC*>FBa#liI.!HV&b!,A9M1M=gHZeKH V4R w]1ha,o3/4A1dwnqam͕1zLӢ>2+ kA,.{Wj}S9U4@w@~)zY^Rqs΂ϵVӽ877B+qݴ+gl8rkec G1`JgSRrs \'sv7_:Hzp _9lκ}Y,M2ߟqE$xV>.E& h@ЈEqz/$2Nhpydhcplib-0.6.2/man/man3/pydhcplib.strlist.3.gz0000644000175000017500000000167711366364415017442 0ustar matmatUmoFsR\khE Nro]㸿f@ $T)80<3co} NQqP$PgH2Z,.nz;wؙ<Lx.V2b֨yJlȫ/wbH鋳g=C "-r!R0a :]D_k?hF÷M7a!HRpL( ܘf%Un5nWr͡r݃?c̀ )CjUM<3yA E5&5 {=_ )tLcThs"fR MR6&A9F #x ) .$< C)c*<^%p.yBHpUP Gɴ@ ˢmuW]K >u2 O omrH<Cs(ɗLdGƿeSԧ2s'%&nnhKPGw s;__Vvzʹ6=#`d}:@5M` kmbpCD;@kheqLx ~~gy 4{k^ 9LoVS׮DesO̍+7U"ha_QnWapAIӆd;2+s& d I{[,só6'2aZ;n`#M?MRp)4)2%D5S,⣈n; 7ēAUMRp<~ Y eDyȭ: #OX'BbFI. pTI)E9`f1|},Ξ3!k[i'F/= c!GK8ڍN&[Өo!5#.dt>WfbGh c-rV`1hh](CƬrliIUUI3dsf:@Njl~d%F҅ė^8er[zNCD\B3¬FDׁhTTH9rÅ5vCƶV|]^.Slmq@7n:Ws%]^!eWx^󐈩~ʋP^SbSX6 NG#MYw]E|阪@|"6ͳRTlk!}sN}h`I/u7bDxfr\fx`."@13JCa 'b'3`--BYKnQ igj>Ru5ԣꌰuoj~l:u8;ܹ5|rHΆSu|bIaHg>l-igJ3Ipydhcplib-0.6.2/man/fr/man3/pydhcplib.ipv4.3.gz0000644000175000017500000000146211366364415017217 0ustar matmatfDpydhcplib.ipv4.3Un@}~/DnHT5H"HFI-V]{k ̜7WDER,\{8]gzx0wNaU{x c'`6B c8p kԱP!2?d:*G9u+Hi~z7а}Њlb6 'c]s$La2 $aVWS)qa %BoXr|h. <ċUz+.Bzn/'n%Hct0L5 l5{OJ n&DAJ,n+x1XDUhāL#?Kdl_\bcM4 `Ҭ7 BMAR)*,H&c`" T-tC541!%.2A p`4=.ϧZhnk oܾN3gOSL.ĥ^h;U֦t Roto)8:vYծ:e]u]*%lO!C~ʡƎd5l~7J`(Ct{˪t˿ d8|X,IYjkz"K/*%=f*iqyc4Jܣeb_.Q"JihvB$BZ[dNPvpk*R wJhX-y[@ȍqdBj"\*pC_ -ǙFܬ&0| 'n8]5Spydhcplib-0.6.2/man/fr/man3/pydhcplib.strlist.3.gz0000644000175000017500000000206511366364415020041 0ustar matmatfDpydhcplib.strlist.3VnF }|W/U%m@nh $'.6`,J3\_۷QR#9r.mF!I9:|ʖiybɥuDCX2÷'{e7?DS)@*''lޅR{ NB9 rlGN8@/lDG¹Za8<΋<,D(!VXr[;u[2Y^Qu½x]D8 Q.qdP\wu\Ñy$V;C*j~ Wy˲2HೖΕA ^)n7w(sOmV6k_;n)N!׃o ]Cpydhcplib-0.6.2/man/fr/man3/pydhcplib.DhcpPacket.3.gz0000644000175000017500000000230111366364415020334 0ustar matmat(eIpydhcplib.DhcpPacket.3VmoH_򗀎:I[J'.!Q6jﺻk~fw1ԊHx Ɨ/^iRd!uH}Ï~^vWљ#tz͋ܽ!*d>Y9SIIAhe5 G&Rd+( !5YI X@#ۂU 5u7ap5N=p4u!} ;WQ?ᵓ{b;pto:R PoqxG #>2.E+3͊ wq(8a1FmLjyc3,1BN3$ FDUݢBE#fP~<4&Zfg4R"WI <5SLl4S1fjM<{1&7L8 fX kDV"< &acϑ|hSKʕiU{ /Uy79H]钸FK!*Š͸$EQ8q; u01I.VjDhn-؆"J 4HD$t!yjR  hYw^VSmmmuglu hj~Hg_i2[p--(~9~0l=\Ht0S{Lcꌩ;Du0X9ŽүJZe7Uv[7lm9. AW i{2߈Go;CC &a2F8Lyʯ&TKT_O>>?/vmGڮ7 NprXL닳w]%7(m\;cw̵o)M WO~@s SsK%>Έ>fD Jl7;;\"", default=False) parser.add_option("-i", "--input", action="store",dest="input", help="\";;\"", default=False) (options, args) = parser.parse_args() def print_error(_msg) : return sys.stderr.write(_msg+"\n") def main() : listener = False emitter = False port_destination = False ip_destination = False if options.version == True : print "PyDhcpLib version : ",dhcp_constants.PyDhcpLibVersion sys.exit(0) # process input command line if options.input != False : options.input = process_inline_options(options.input) listener = process_input(options.input,options.count) else : print_error ("Warning : no input option defined. Default is *stdin* with option *binary*.") listener = dhcp_file_io.DhcpStdIn() # process output command line if options.output != False : options.output = process_inline_options(options.output) emitter = process_output(options.output,options.count) ip_destination = options.output[2] port_destination = options.output[3] else : print_error ("Warning : no output option defined. Default is *stdout* with option *binary*.") emitter = dhcp_file_io.DhcpStdOut() # Last check before processing if ( not emitter ) : return False if ( not listener ) : return False # Go ! Process dhcp packet count = options.count if not options.input or options.input[0] == 'file' or options.input[0] == 'stdin' : count = 1 if not options.output or options.output[0] == 'file' or options.output[0] == 'stdout' : count = 1 gap = 0 if count != 0 : gap = 1 else : count = 1 while count > 0 : packet = listener.GetNextDhcpPacket() emitter.SendDhcpPacketTo(packet,ip_destination,port_destination) count -= gap return True def process_input(_input,_count) : if not _input : print_error( "process_input_error" ) return false option_up = False option_binary = False listener = False file_in = False if not _count : _count = 0 for option in _input[1] : if (option == 'binary') : option_binary = True if (option == 'up') : option_up = True _type = _input[0] _location = _input[2] _port = _input[3] if (_type == 'device') : if not option_binary : print_error ("Warning : option *readable* has no effect for types *device* and *address*") if option_up : print_error ("Setting interface "+_location+" up.)") check_device(_location,options.no_up) listener = dhcp_network.DhcpClient(_location,_port,_port) listener.BindToDevice() return listener elif (_type == 'address') : if option_up : print_error ("Warning : option *up* has effect only for type *device* ") if not option_binary : print_error ("Warning : option *readable* has no effect for types *device* and *address*") listener = dhcp_network.DhcpClient(_location,_port,_port) listener.BindToAddress() return listener elif (_type == 'file') : if option_up : print_error ("Warning : option *up* has effect only for type *device* ") if option_binary and _count !=1 : print_error ("Warning : option *count* is always 1 for type *file*") listener = dhcp_file_io.DhcpFileIn(_location) if not option_binary : listener.DisableBinaryTransport() return listener elif(_type == 'stdin') : if option_up : print_error ("Warning : option *up* has effect only for type *device* ") listener = dhcp_file_io.DhcpStdIn() listener.DisableBinaryTransport() return listener def process_output(_output,_count) : if not _output : print_error( "process_output_error" ) return false option_up = False option_binary = False listener = False file_in = False if not _count : _count = 0 for option in _output[1] : if (option == 'binary') : option_binary = True if (option == 'up') : option_up = True _type = _output[0] _location = _output[2] _port = _output[3] if (_type == 'device') : print_error('Warning : type *device* not available for output. Send data to stdout with option *binary*') emitter = dhcp_file_io.DhcpStdOut() emitter.EnableBinaryTransport() return emitter elif (_type == 'address') : if option_up : print_error ("Warning : option *up* has effect only for type *device* ") if not option_binary : print_error ("Warning : option *readable* has no effect for types *device* and *address*") emitter = dhcp_network.DhcpNetwork(_location,_port,_port) return emitter elif (_type == 'file') : if option_up : print_error ("Warning : option *up* has effect only for type *device* ") if option_binary and _count !=1 : print_error ("Warning : option *count* is always 1 for type *file*") emitter = dhcp_file_io.DhcpFileOut(_location) if not option_binary : emitter.DisableBinaryTransport() else : emitter.EnableBinaryTransport() return emitter elif(_type == 'stdout') : if option_up : print_error ("Warning : option *up* has effect only for type *device* ") emitter = dhcp_file_io.DhcpStdOut() emitter.DisableBinaryTransport() return emitter def check_device(device_name,_up) : device = interface.interface() # Set UP interface if no_up option not present if _up : device.setStatusUp(device_name) # test if interface exists all_devices = device.getInterfaceList() valid = 0 for each in all_devices : if each == device_name : valid += 1 if valid == 0 : print_error( "Warning : no configured device - "+device_name+" - found." ) def process_inline_options(definition) : type_list = ['device','address','file','stdin','stdout'] options_list = ['readable','binary','up','noup'] input_split = definition.split(';') # Test the number of field in device definition if (len(input_split) > 3) : print_error( "Error : too many fields in device definition" ) return False elif (len(input_split) < 3) : print_error( "Error : not enough fields in device description" ) return False # Get and test _type_ field input_type = input_split[0] try: type_list.index(input_type) except ValueError: print_error( "Error : unknown type <"+input_type+"> (device, address, file, input, or output)") return False # Get an test options field input_options = input_split[1].split('|') if (len(input_options[0]) == 0) : input_options = [] mutual_up = 0 readable_up = 0 for each in input_options : try: options_list.index(each) except ValueError: print_error( "Error : unknown option <"+each+"> (readable, binary, up, or noup)") return False if each == 'up' : mutual_up += 1 if each == 'noup' : mutual_up += 1 if each == 'readable' : readable_up += 1 if each == 'binary' : readable_up += 1 if ( mutual_up > 1) : print_error( "Error : and are mutualy exclusive.") return False if ( readable_up > 1) : print_error( "Error : and are mutualy exclusive." ) return False # Get name and port if input_type=='device' or input_type=='address' : try : input_name = input_split[2] input_tmp = input_name.split(':') input_name = input_tmp[0] input_port = input_tmp[1] except : if input_type=='device' : print_error( "Error : wrong name field. Example : eth0:68" ) if input_type=='address' : print_error( "Error : wrong name field. Example : 192.168.8.5:68" ) return False elif input_type=='file' : input_name = input_split[2] input_port = '' else : input_name = '' input_port = '' return [input_type,input_options,input_name,input_port] try : if main() : sys.exit(0) sys.exit(1) except KeyboardInterrupt : print_error("Exiting pydhcp"); sys.exit(1)