From 377cd6bb3cdbf4b23e7cf6b8ca5d0a9f21fb36bb Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Thu, 11 Oct 2007 03:56:09 -0400 Subject: [PATCH] Initial checkin of a DHCP server (untested) svn path=/trunk/dhcp/; revision=189 --- anemon-svn.tar.gz | Bin 0 -> 16326 bytes dhcpserver.py | 159 ++++++++ event_logger.py | 63 +++ pydhcplib/COPYING | 280 ++++++++++++++ pydhcplib/README | 20 + pydhcplib/examples/client_example.py | 51 +++ pydhcplib/examples/gen_packet_example.py | 16 + pydhcplib/examples/hwaddr_example.py | 32 ++ pydhcplib/examples/ipv4_example.py | 28 ++ pydhcplib/examples/server_example.py | 59 +++ pydhcplib/examples/strlist_example.py | 25 ++ pydhcplib/man/fr/man3/pydhcplib.3.gz | Bin 0 -> 488 bytes .../man/fr/man3/pydhcplib.DhcpBasicPacket.3.gz | Bin 0 -> 1489 bytes pydhcplib/man/fr/man3/pydhcplib.DhcpPacket.3.gz | Bin 0 -> 1230 bytes pydhcplib/man/fr/man3/pydhcplib.hwmac.3.gz | Bin 0 -> 1047 bytes pydhcplib/man/fr/man3/pydhcplib.ipv4.3.gz | Bin 0 -> 818 bytes pydhcplib/man/fr/man3/pydhcplib.strlist.3.gz | Bin 0 -> 1077 bytes pydhcplib/man/fr/man8/pydhcp.8.gz | Bin 0 -> 877 bytes pydhcplib/man/man3/pydhcplib.3.gz | Bin 0 -> 434 bytes pydhcplib/man/man3/pydhcplib.ipv4.3.gz | Bin 0 -> 713 bytes pydhcplib/man/man3/pydhcplib.strlist.3.gz | Bin 0 -> 959 bytes pydhcplib/man/man8/pydhcp.8.gz | Bin 0 -> 621 bytes pydhcplib/pydhcplib/__init__.py | 1 + pydhcplib/pydhcplib/dhcp_basic_packet.py | 188 +++++++++ pydhcplib/pydhcplib/dhcp_constants.py | 404 ++++++++++++++++++++ pydhcplib/pydhcplib/dhcp_network.py | 134 +++++++ pydhcplib/pydhcplib/dhcp_packet.py | 221 +++++++++++ pydhcplib/pydhcplib/type_hw_addr.py | 86 +++++ pydhcplib/pydhcplib/type_ipv4.py | 117 ++++++ pydhcplib/pydhcplib/type_strlist.py | 65 ++++ pydhcplib/scripts/pydhcp | 122 ++++++ pydhcplib/scripts/pydhcp.py | 67 ++++ pydhcplib/setup.py | 26 ++ 33 files changed, 2164 insertions(+) create mode 100644 anemon-svn.tar.gz create mode 100644 dhcpserver.py create mode 100644 event_logger.py create mode 100644 pydhcplib/COPYING create mode 100644 pydhcplib/README create mode 100755 pydhcplib/examples/client_example.py create mode 100755 pydhcplib/examples/gen_packet_example.py create mode 100644 pydhcplib/examples/hwaddr_example.py create mode 100755 pydhcplib/examples/ipv4_example.py create mode 100644 pydhcplib/examples/server_example.py create mode 100755 pydhcplib/examples/strlist_example.py create mode 100644 pydhcplib/man/fr/man3/pydhcplib.3.gz create mode 100644 pydhcplib/man/fr/man3/pydhcplib.DhcpBasicPacket.3.gz create mode 100644 pydhcplib/man/fr/man3/pydhcplib.DhcpPacket.3.gz create mode 100644 pydhcplib/man/fr/man3/pydhcplib.hwmac.3.gz create mode 100644 pydhcplib/man/fr/man3/pydhcplib.ipv4.3.gz create mode 100644 pydhcplib/man/fr/man3/pydhcplib.strlist.3.gz create mode 100644 pydhcplib/man/fr/man8/pydhcp.8.gz create mode 100644 pydhcplib/man/man3/pydhcplib.3.gz create mode 100644 pydhcplib/man/man3/pydhcplib.ipv4.3.gz create mode 100644 pydhcplib/man/man3/pydhcplib.strlist.3.gz create mode 100644 pydhcplib/man/man8/pydhcp.8.gz create mode 100644 pydhcplib/pydhcplib/__init__.py create mode 100644 pydhcplib/pydhcplib/dhcp_basic_packet.py create mode 100644 pydhcplib/pydhcplib/dhcp_constants.py create mode 100644 pydhcplib/pydhcplib/dhcp_network.py create mode 100644 pydhcplib/pydhcplib/dhcp_packet.py create mode 100644 pydhcplib/pydhcplib/type_hw_addr.py create mode 100644 pydhcplib/pydhcplib/type_ipv4.py create mode 100644 pydhcplib/pydhcplib/type_strlist.py create mode 100644 pydhcplib/scripts/pydhcp create mode 100644 pydhcplib/scripts/pydhcp.py create mode 100755 pydhcplib/setup.py diff --git a/anemon-svn.tar.gz b/anemon-svn.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..73466c88bfc6a32085a923c8a524ff86f419a423 GIT binary patch literal 16326 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 literal 0 HcmV?d00001 diff --git a/dhcpserver.py b/dhcpserver.py new file mode 100644 index 0000000..5c7721c --- /dev/null +++ b/dhcpserver.py @@ -0,0 +1,159 @@ +#!/usr/bin/python +import pydhcplib +from pydhcplib.dhcp_packet import * +from pydhcplib.type_hw_addr import hwmac +from pydhcplib.type_ipv4 import ipv4 + +from event_logger import Log + +import sipb_xen_database + +class DhcpBackend: + def __init__(self, database=None): + if database is not None: + sipb_xen_database.connect(database) + def findIP(self, mac): + value = sipb_xen_database.NIC.get_by(mac_addr=mac) + if value is None: + return None + ip = value.ip + if ip is None: #Deactivated? + return None + return ip + + def Discover(self, packet): + Log.Output(Log.debug,"dhcp_backend : Discover ") + chaddr = hwmac(packet.GetHardwareAddress()) + ip = self.findIP(str(chaddr)) + if ip is not None: + ip = ipv4(ip) + Log.Output(Log.debug,"dhcp_backend : Discover result = "+str(ip)) + packet_parameters = {} + + # FIXME: Other offer parameters go here + packet_parameters["yiaddr"] = ip.list() + + packet.SetMultipleOptions(packet_parameters) + return True + return False + + def Request(self, packet): + Log.Output(Log.debug, "dhcp_backend : Request") + + discover = self.Discover(packet) + + chaddr = hwmac(packet.GetHardwareAddress()) + request = packet.GetOption("request_ip_address") + yiaddr = packet.GetOption("yiaddr") + + if not discover: + Log.Output(Log.info,"Unknown MAC address: "+str(chaddr)) + return False + + if yiaddr!="0.0.0.0" and yiaddr == request : + Log.Output(Log.info,"Ack ip "+str(yiaddr)+" for "+str(chaddr)) + return True + else: + Log.Output(Log.info,"Requested ip "+str(request)+" not available for "+str(chaddr)) + return False + + def Decline(self, packet): + pass + def Release(self, packet): + pass + + +class DhcpServer(pydhcplib.dhcp_network.DhcpServer): + def __init__(self, backend, options = {'client_listenport':68,'server_listenport':67}): + pydhcplib.dhcp_network.DhcpServer.__init__(self,"0.0.0.0",options["client_listen_port"],options["server_listen_port"],) + self.backend = backend + Log.Output(Log.debug, "__init__ DhcpServer") + + def SendPacket(self, packet): + """Encode and send the packet.""" + + giaddr = packet.GetOption('giaddr') + + # in all case, if giaddr is set, send packet to relay_agent + # network address defines by giaddr + if giaddr!=[0,0,0,0] : + agent_ip = ".".join(map(str,giaddr)) + self.SendDhcpPacketTo(agent_ip,packet) + Log.Output(Log.debug, "SendPacket to agent : "+agent_ip) + + # FIXME: This shouldn't broadcast if it has an IP address to send + # it to instead. See RFC2131 part 4.1 for full details + else : + Log.Output(Log.debug, "No agent, broadcast packet.") + self.SendDhcpPacketTo("255.255.255.255",packet) + + + def HandleDhcpDiscover(self, packet): + """Build and send DHCPOFFER packet in response to DHCPDISCOVER + packet.""" + + logmsg = "Get DHCPDISCOVER packet from " + hwmac(packet.GetHardwareAddress()).str() + + Log.Output(Log.info, logmsg) + offer = DhcpPacket() + offer.CreateDhcpOfferPacketFrom(packet) + + if self.backend.Discover(offer) : + self.SendPacket(offer) + # FIXME : what if false ? + + + def HandleDhcpRequest(self, packet): + """Build and send DHCPACK or DHCPNACK packet in response to + DHCPREQUEST packet. 4 types of DHCPREQUEST exists.""" + + ip = packet.GetOption("request_ip_address") + sid = packet.GetOption("server_identifier") + ciaddr = packet.GetOption("ciaddr") + + if sid != [0,0,0,0] and ciaddr == [0,0,0,0] : + Log.Output(Log.info, "Get DHCPREQUEST_SELECTING_STATE packet") + + elif sid == [0,0,0,0] and ciaddr == [0,0,0,0] and ip : + Log.Output(Log.info, "Get DHCPREQUEST_INITREBOOT_STATE packet") + + elif sid == [0,0,0,0] and ciaddr != [0,0,0,0] and not ip : + Log.Output(Log.info,"Get DHCPREQUEST_INITREBOOT_STATE packet") + + else : Log.Output(Log.info,"Get DHCPREQUEST_UNKNOWN_STATE packet : not implemented") + + if self.backend.Request(packet) : packet.TransformToDhcpAckPacket() + else : packet.TransformToDhcpNackPacket() + + self.SendPacket(packet) + + + + # FIXME: These are not yet implemented. + def HandleDhcpDecline(self, packet): + Log.Output(Log.info, "Get DHCPDECLINE packet") + self.backend.Decline(packet) + + def HandleDhcpRelease(self, packet): + Log.Output(Log.info,"Get DHCPRELEASE packet") + self.backend.Release(packet) + + def HandleDhcpInform(self, packet): + Log.Output(Log.info, "Get DHCPINFORM packet") + + if self.backend.Request(packet) : + packet.TransformToDhcpAckPacket() + # FIXME : Remove lease_time from options + self.SendPacket(packet) + + # FIXME : what if false ? + +if '__main__' == __name__: + event_logger.init("stdout", event_logger.INFO, {}) + options = { "server_listen_port":67, + "client_listen_port":68, + "listen_address":"0.0.0.0"} + backend = DhcpBackend('postgres://sipb-xen@sipb-xen-dev/sipb_xen') + server = DhcpServer(backend, options) + + while True : server.GetNextDhcpPacket() diff --git a/event_logger.py b/event_logger.py new file mode 100644 index 0000000..fa59be0 --- /dev/null +++ b/event_logger.py @@ -0,0 +1,63 @@ +# Anemon Dhcp +# Copyright (C) 2005 Mathieu Ignacio -- mignacio@april.org +# +# 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. +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +import sys +from logging import * + + + +class EventLogger: + def __init__(self,logtype="stdout",loglevel=WARNING,option={}): + self.loglevel = loglevel + self.logtype = logtype + + self.info = INFO + self.debug = DEBUG + self.warn = WARN + self.error = ERROR + self.critical = CRITICAL + + + self.logger = getLogger('SipbXenDhcpServer') + + if logtype == "file" : + # into file logger + handler = FileHandler(option["log_file"]) + + elif logtype == "syslog" : + handler = SysLogHandler((option["log_host"],option["log_port"])) + + elif logtype == "http" : + handler = HTTPHandler(option["log_host"],option["log_url"],option["log_method"]) + + else : # logtype == "stdout" : + handler = StreamHandler() + + + + handler.setFormatter(Formatter('%(asctime)s %(levelname)s %(message)s')) + self.logger.addHandler(handler) + self.logger.setLevel(loglevel) + + def Output(self,level,infostring) : + self.logger.log(level,infostring) + +def init(logtype,level,path): + global Log + + Log = EventLogger(logtype,eval(level),path) + Log.Output(INFO,"EventLogger : Started.") diff --git a/pydhcplib/COPYING b/pydhcplib/COPYING new file mode 100644 index 0000000..4a4f44a --- /dev/null +++ b/pydhcplib/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + END OF TERMS AND CONDITIONS diff --git a/pydhcplib/README b/pydhcplib/README new file mode 100644 index 0000000..04eadbb --- /dev/null +++ b/pydhcplib/README @@ -0,0 +1,20 @@ +Pydhcplib is a python library to read/write and encode/decode dhcp +packet on network. + + + +Installation : +-------------- +On Debian Sarge, 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 diff --git a/pydhcplib/examples/client_example.py b/pydhcplib/examples/client_example.py new file mode 100755 index 0000000..c8f3887 --- /dev/null +++ b/pydhcplib/examples/client_example.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# +# pydhcplib +# Copyright (C) 2005,2006 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 2 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +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): + packet.PrintHeaders() + packet.PrintOptions() + + def HandleDhcpAck(self, packet): + packet.PrintHeaders() + packet.PrintOptions() + + def HandleDhcpNack(self, packet): + packet.PrintHeaders() + packet.PrintOptions() + + +client = Client(netopt) + +while True : + client.GetNextDhcpPacket() diff --git a/pydhcplib/examples/gen_packet_example.py b/pydhcplib/examples/gen_packet_example.py new file mode 100755 index 0000000..c6e7550 --- /dev/null +++ b/pydhcplib/examples/gen_packet_example.py @@ -0,0 +1,16 @@ +#!/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("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]) + +packet.PrintHeaders() +packet.PrintOptions() diff --git a/pydhcplib/examples/hwaddr_example.py b/pydhcplib/examples/hwaddr_example.py new file mode 100644 index 0000000..9c5de80 --- /dev/null +++ b/pydhcplib/examples/hwaddr_example.py @@ -0,0 +1,32 @@ +#!/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() diff --git a/pydhcplib/examples/ipv4_example.py b/pydhcplib/examples/ipv4_example.py new file mode 100755 index 0000000..2a74c67 --- /dev/null +++ b/pydhcplib/examples/ipv4_example.py @@ -0,0 +1,28 @@ +#!/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 + + + diff --git a/pydhcplib/examples/server_example.py b/pydhcplib/examples/server_example.py new file mode 100644 index 0000000..1a079ab --- /dev/null +++ b/pydhcplib/examples/server_example.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# pydhcplib +# Copyright (C) 2005 Mathieu Ignacio -- mignacio@april.org +# +# 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. +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +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): + packet.PrintHeaders() + packet.PrintOptions() + + def HandleDhcpRequest(self, packet): + packet.PrintHeaders() + packet.PrintOptions() + + def HandleDhcpDecline(self, packet): + packet.PrintHeaders() + packet.PrintOptions() + + def HandleDhcpRelease(self, packet): + packet.PrintHeaders() + packet.PrintOptions() + + def HandleDhcpInform(self, packet): + packet.PrintHeaders() + packet.PrintOptions() + + + +server = Server(netopt) + +while True : + server.GetNextDhcpPacket() diff --git a/pydhcplib/examples/strlist_example.py b/pydhcplib/examples/strlist_example.py new file mode 100755 index 0000000..9a597ad --- /dev/null +++ b/pydhcplib/examples/strlist_example.py @@ -0,0 +1,25 @@ +#!/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 + + + diff --git a/pydhcplib/man/fr/man3/pydhcplib.3.gz b/pydhcplib/man/fr/man3/pydhcplib.3.gz new file mode 100644 index 0000000000000000000000000000000000000000..28bbf2b0f482f22890b9f0cb65768be05e150399 GIT binary patch literal 488 zcmVDbDQC!aKa35TfEg(?m@>nR&b^!!;ZuMXC zIA6??WjqZ=Bz0cva1{lk|Gx0_6>5RtOieXI@Hn6Vb+$(-dd)maXWKZ*;?4T46pbCU z%!}JXGmC>9l&rPmHQsid-%%8@L=CcrvhB?h4Ji7jMr-=`#;Xu?Ymn9imK}d^{}Q31 zqDJ1CLn@`ey+L7}%u#H=Z?!u)yWrFqkF|Rym^Y{}ZDzYX5@IPXfeKfhcVTByMm0>E_>_I;cdv=?FlVj&|bNFVoD7wK4sTvPg1{pz|1&v zP5pq_($lBh9Cd@*5tq8B`A^q_M9ZD;c;(+rab$uJ0`F(bjZxv|r+ezMZIDZ)Ist)u z$uu0TRX-+^A)KxM?rFvNnMi$@^uwok?JoGj#9r!(S|)`deIj9=EjHU=w4(ONu!i^` eXu%|mE7n`T!|a(V&A7krX7mq)N1Byo0{{S2KKe5N literal 0 HcmV?d00001 diff --git a/pydhcplib/man/fr/man3/pydhcplib.DhcpBasicPacket.3.gz b/pydhcplib/man/fr/man3/pydhcplib.DhcpBasicPacket.3.gz new file mode 100644 index 0000000000000000000000000000000000000000..1d0037c91c7746a4ce10aba145f517bb5f82a546 GIT binary patch literal 1489 zcmV;?1ups@iwFP!000001BF-HZreBzeb-kIda;ews&?A#rUCXLvD4N-E{2^HTO>t5 zOLWYwM5?^F$=~*|>R0Rxshb^p7l>nt!x_$;IWru`Hy=q@Jg4iV$oMjz!1o!|Jekqt zD>ESpU&F`$%|1^)j%OFsvoMGkpmlY983qSc$^GwSoKdYANf}vE_)erSOi*En6{Miw zEbKz<*xOrtzPg?*ri(CGDVdYQmU&)CWysEQ5ENeg7nvmMuB1N*{0Wou#dtoQ-Au2q z!r+3E#QS&nB&H3?ntf$f=1dsMm5a$J$_>L6lJ<5YBIjA=1Li1)XKfTu3=w6*w00(_ z-7>){13Dr`S`9jy(0`;gnt;`n6p7(dXi{!uW=jxiiE1Tcfv+2;bjMi?#YYhb!R?lJ zE-dg(8*XfgCm(@WfvcLN99H2dcswCl4?O#27&?IN$ilf0lZ#r=4g3eB6;PoZLtpVH z7NK4fOR}bU(RjV$f@{*>NUq5I{g@n$UXKP~nAQfsD+tEBRUIrC3efp)mWmV(bPF4* zI9+DWOHs27%zm>ybVxIs)fQqhp#t66B~OIzK@_!{QF|njmIx^#cW_PxFKkw#V=k)v zR}TN{?8M}h3(dWRnYB#eVZqF`GlrHvG%uQ|4JMvigC+69L8fqzDid3jis1=WIMyRw zVTjn&8E{e7g2w5%V*KU#&Btq?eHcu2%ZUB}t8>l-z|Y8yvVamg4g2XMPsmuxubhQ0 zV#SP-c2godV2j@&7gmvHWLxw9K3-p{>EN^Q3)BEmDLQ8{(k zSVR6=KXPlD`42N}l1qv2Z&1BT^3t=_>dHUMML&}I*a z9lB5`hKyO|*wT_7s;XjRlOPml4#~9Vyd`wQk}bk@yn&o}tdS=5VmB9XMqA=tdTwLv zAwW!cTB;H>WS&=$`QCy>?0wYOI-vhSR|EYFKFL}-QU!}0G$M?o3yCkKgK&V$isc-( zQ1xhC``w?0h`5B>C;l_vhgskIe>aSd{)mo-!!H951enpdsfwwPT65%v3qNZ%?1zl) zY^kmIrineeD!p8$*xK6b3%?&6a z7riY|p|BmOy&C-&ZKvi_#iq8gAZ^Q?Z=^hV+pdpwESaI-!at2KEi0U4jKH{wBTD-4LLQ5#c?X?aOhYN}A!V z=7)nVOh{kjyR^%U`%7ZGZvzR(%$UZbDh*wSp)PppLY%Nph@CXf6q199wnTPJgiB>% zKs*#Ws;*$V84yP`Jfxiks!2-wG~x=L21?ca>aKIwkeX7D+N(3de$>5LssZx+@AJ#q z1zvXdtFxJskBYkP0!e3i0Txg0SMy+Zx^%2AUQCwNP#G^3+0`)51$zLfu$*d@>hfw)!**kMsK2{X!PZv5d+uLgPUW((%on{jOx#y(f=wxbDE}3 z?;Y%WdmMr0F>c3He!8B{$?5H4F|B`M^p6Ko2h;WUoF@I(TWc+m+I>t$vDGNe~(~JzaNxM9C#q8=C!li4?thw?y{+UATAei9JiXTpc#%x z*bbqt(sIKxSrkqoCZBMqUK>-Kyn5APp?zA>oM+ESkXOF)ip*le<67w=iEQto!)$*FrZ{;ZV>zn!GJ~=NDcr1CfwQ0 literal 0 HcmV?d00001 diff --git a/pydhcplib/man/fr/man3/pydhcplib.DhcpPacket.3.gz b/pydhcplib/man/fr/man3/pydhcplib.DhcpPacket.3.gz new file mode 100644 index 0000000000000000000000000000000000000000..3ecf004ab77346e83e807a0beba146ef6fa3f47e GIT binary patch literal 1230 zcmV;<1Tp&`iwFP!000001HD(cxMYellaU* zWuUc-9EYi3dC93=B5Lhy zE#gRlNC*f*)kA3$+Mt+eTd`QXBsp+7T?EVZu}%^e+eD|#)HW)aD*_H_f#p?wMR!wz zbyXn3gxLieV?-RlS6q)WjlmQhqcL;J0n0I#N&*QH{^GQzh7ts+_p=E-q1sQ4zd3T$Rz0DrYJn!;dOw#B%ja)u zWAoWr+PCd}U}GvkVRVAn@)K#go;yJ^@H^G2EuRX=qzI&X@Y{hMYVSl)rtMRH$FOMm zM{i#RN5?0@%iw6~`p2i^&YRAw&e7+cAev>k2cYH#>C@56m!10cXXmHR&o1%M?=9LL zpLEdk1kLM~I9Tr**I?FrJ$LXo!)Q#p*ON(9cl523cBgRyv!{&4t=DT~HvILWdOLA+ z>o0>1^9_yJGCKhMB-P`V8CUmPCdTw>=iHgyZ=9$S{`C67w%GEX)=e&^IrhXsu=2Eb zEecO8-Q9)-H3u&9+&Tp0MlwZaTIcT$4;wjKeobk{__N8WL)UZLhCexAw%MVsO>jiI s*VylmeXmdTj6q4F2SH;dNh@RS)2HtAGtCv_2CnV>2l`CaAhHbr08ayCGXMYp literal 0 HcmV?d00001 diff --git a/pydhcplib/man/fr/man3/pydhcplib.hwmac.3.gz b/pydhcplib/man/fr/man3/pydhcplib.hwmac.3.gz new file mode 100644 index 0000000000000000000000000000000000000000..a1c06e63114f9243d7a77b02e0d1c65be31f4401 GIT binary patch literal 1047 zcmV+y1nB!8iwFo64M9Wz18{j{Xk&0}X<{yDcWq%~E;9g?R$Fh{NECiv|BBOj0VJ5j z*wD%nE9JHuq+Adr)mEj7274Sv^{wMEN&anL`4@X;YzLc?Mny)9&*hu%T;>e)?h;7$ z60H3!5-YlXikVMLuflrG*qLY%yIBE0k#rJ4lW2uzq@AK_EfISt=EnZ7hqyq+E7; z7F|hb2y!Jw^4Ke}&o35d^XcqvdV52xD+YeVkOl11=DC6*DJheRs%A4S0ojeC#pDb6gJ>_=FCj)^E7@X`D%( z1SW0yHe-@0UdSAXNBV>k%pQ>Cfb`)!TDTlAXE|`(!sL!m6I^^Y}*?SJ;(7}*BgyU+jQ749aDQu zhhyrDsXL~l@t&#EM5VU992nT;z;&s?wJ?oXIl_*?1JbYDN{m`%H&u39H*D&LZJpE9 zIhX+v!YG)UWsq_hH?~12;GTGmVN7xf@J44g^L(}^WCeC57GDbK|#d(j) zuihUft*lf__q9}C?N8%AxT8LdKlZ`?h%flq_P2IzN4wgtm^TbO*YQ?3l*it&kCg@d z)TLM*w@A44_AV`tPOEM!yJbA8jYqX{d1OA{PUmoPzgSG`i?jQw*WVv^U8f}z*~Z-y z;n_F1C~aK8=lDBg{&%kS%(dbaZz=yx?G0B?sr-IGa~264QwJ1t_VlLioJ*V~sHoyT zz5f@-1kQ++o<3&o;Y1J#j(o literal 0 HcmV?d00001 diff --git a/pydhcplib/man/fr/man3/pydhcplib.ipv4.3.gz b/pydhcplib/man/fr/man3/pydhcplib.ipv4.3.gz new file mode 100644 index 0000000000000000000000000000000000000000..8b4f72d00aa23a2eb7c4e5db58e13542e1f2ebbf GIT binary patch literal 818 zcmV-21I_#&iwFql3_(Ny18{j{Xk&0}X<{yEaCS5+Fb z(nwUw1vNqtQ zMN%wW5v_X;I9>W@zv=zu)y4FBcD}wm8_8`U^Wp#q!JAhW8l8V zIHtpJ3TxD{P$Bd(KlA(XWI7+t9k$defUQUC;W>3Hf=Fot_RJWEetN1mn7h!heUFV6 z;maPW6tUSAi_nT}{L8`oVm6%K3@2lUU32gxr%Yj|GK>u*VOEusS5qm*abX}OLX4E@ zZ&-4n5qzrHXf6x}7@8OsJQlwa62`=fReCEfLVEg`yKaB&xa}_|Zp$T)tdx(Zf=FZN zr*sxD5(XazvgHms_pBju2y>z1vZ^0=z&D=VJ7OHkx)voF~WnHJL>y~w0 zDwByNY>Vo{-{emrLw?Gk#*Sn)Y!jS*e>W0Jy0*h$D5H`FvO`-ug+SS!$itYrwsFw<1d~v?|IMft8jP_$583-1~`U$J{E; zX>oZ6wPQ4|O8?xWxsZa!WshRUUk~aoQPbd&BHv2qx8G@|XrLB$#?$RW10+IP7+Ykz zq3upkcCFBG`tNI$DvDBo3wKIrSQ!(Y9v_#6EqPn=K*)`&^viMfy^3T)4r(G?Djje` w^Ir`3*)6TdnZrihtOO=7dhrl+*1bt00DQ1&;S4c literal 0 HcmV?d00001 diff --git a/pydhcplib/man/fr/man3/pydhcplib.strlist.3.gz b/pydhcplib/man/fr/man3/pydhcplib.strlist.3.gz new file mode 100644 index 0000000000000000000000000000000000000000..fbe73a6478e7fdf8900b82ea6f6829f6daf7a009 GIT binary patch literal 1077 zcmV-51j_p#iwFp*3_(Ny18{j{Xk&0}X<{yObaHHIb962<0F74LZsSG_eeQe(S1+*v zRq-XeZ3DPKZfFc7ju9t|E;fr`EREyAN;Aq_oTOjdx7L4AQX@HXE^PtpMvCMi4@o(> zI)$iw%9d%F%Xwm*$)$A>L_<8nZ~Eo<^k{lEK8#p0!?!0F=Mj5l0yjUxMEjNC9^6wY zKq@DU67VN%-i11;fU*uv=I*-b+J zZa#`r7aH;&8-!gLrQ*9(?-N4dISYW=EIf z>DBmR60tK5Y0j+`@H$h0hgTuX(&*A`C7HlD2k}T50bfW(`B?;+%Y_t_eJgp?Vb)ry zHD1xxN+^y}?a?8soK)ONjV?TxwZ+mVaHfsD_X6(y4q_-d-lH1~UBNQqFCT-oF|e3$>C4y$*Xls0$7U9;^sppXo|l=&VLyh+Nr)HU&w90`f|aHQU8H zlU!ms&`VXFreaMU7CeZW1-+mmOihNL=Z>9xwjo!VK}U@JkE+YgoKUo4UE2~QsvuU@>Wcr6tcA{K6vMAE2$v>F(gnsaw@w#Iq+GaAdR3EI z?S~zn8Hz>tL&k&**(aK@Tw&f{+q=dAZ_HW+*jhFxzn`2>&nW+!#o^TGJHv~jD$^sj zNWSUiTk**0IVqoD|7LN?-ds)%RrPYJ9~pblCVRc1NZN0SBmRdl?kQ@i2W|EJ!%OwB zz2koQDTe-FfTvy`PyIbQeIi*OcO7F`H>4`!J=ljRCiCE^k@q+9{f!;NCd zm|Q@e&(9^-Y&)9=E)c%2l7 z+{*M_?L;_)`TY&eQ7&<0-%woghj(?y!r)w?f`z;fuYbdl!Fid}Bvv~BheIkH>(=I_ z`qAWS8h#wd3|D!s%d#>^;Ioznmd=&?ySuGH@{bE%$owhM=59CqcPMjDe-oslZB~Ca v0+54i++UXwJLhgGg@^H-!jFxHP9ekH*MqBX90|?IU6=g>2o6Ke`3L|27%~fs literal 0 HcmV?d00001 diff --git a/pydhcplib/man/fr/man8/pydhcp.8.gz b/pydhcplib/man/fr/man8/pydhcp.8.gz new file mode 100644 index 0000000000000000000000000000000000000000..e2ce9e15eb83fd86354562ec1feb23c80b6aa115 GIT binary patch literal 877 zcmV-z1Csn7iwFq!_drAd18{j{Xk&0LH~@`RO>f&c5WVYH4193{)H)ZvIjOcW;3S5f zEOrs+KvUzGSczo$;i8NEu|2N#SL~3Z$V!`j0C7xHocG?$JdVn{E11~N^+DPROy1Im z|5ks#zq(v47Z;PF+|ZGm`E@lZ_#kX&5H*+>R0DYfH8ko;Bh(1ew5`xJa@_r9{^1n( zFu%N8+}=FG!|f_9HjjMjeYLq>Xb!~S7khGRVb=fc|XSL zS}Nf$;;b`{Ls1K=+IGf8PjJO$U;o@rhJqbcFZJ*T4Im#`*BwyjJ`6+`nJC4(&p)O4 zJ{~hSOe_XLeGhwgPKrv?0WG=F2+dURS{@Af1K$t=^^7p7hupwg?e|pwqPHbz|doj{0l3Uro!(wpp|_E)*;JM>>Z5$4Mr>8edTPSM+7z9$92$QP&Q=FXs6Re;q$Q+wWD`j&F+i zR8-QWank3Q?z>4q;?v7O_-c@(fv7xnMPdjz_*08Ug$~3KC0T*(m~tVoJ^>~=DbZPp zj_nRzabwzD9vh=RoF?aY`lw$C8m2T&k3h>&E*x5&^ChePm|w4!72Puay{RggFE_W( zZ-7Sa_`${f2RgKJW|wA5zRb2krOR>{Rq16x1*C$K*-1{_9kDUi^67VZ#AH|TU}Q;&5Bv-Yz=~7fj=gvrNPWCik(HbgcFhTTE(mWgl(`;9O4PB2syY(~)8=;fN z=Ud`~$a9Tf8uxcsx9dr9EdpJ*2#Y5zq%v^UDqcOz?;eG9sws_oIxqeQ<8qhSw+8?K DCk3r8 literal 0 HcmV?d00001 diff --git a/pydhcplib/man/man3/pydhcplib.3.gz b/pydhcplib/man/man3/pydhcplib.3.gz new file mode 100644 index 0000000000000000000000000000000000000000..9e503367089a7afe3f5052559ccab9032959d0c9 GIT binary patch literal 434 zcmV;j0ZslNiwFP!0000019ehOZ=)~}z4I$ZoKmSv4(*}Z8zE>DH6JLZYO8h+6FdQ{ zU?bZk%fDX(N!g8B35)0V=8eZQ4$=kqb<2yaF2&vl|IV%9OJ3)TC|NCMz85eTwF%d; z?|sI?`wwU&frA>gAn14?33Y1=B?r$uX3=h$q|5E*U#l>HXJZQ|Ev$7uaj}9`pb5E< z`E9TEfMljPfzrUKNBwyz}CML}_@Fq_={$BFuQe?=LqOJQusj;#;o z?w|Bcy9)1w85)s&t8Rt{f1yOBAo-PLho^6~Iq4&5C!B9Rd-}z$9!VoPb@M(_sp`t5 z34jqnVQu|$Ivvy5=Fb5uQMQ57`4kTBkyJ`|19PxKE0jDBDSS#7+nw*N(H4RlSmqKl cp+T_yHq#cUudQ5*B}D`0AFCp?f?J) literal 0 HcmV?d00001 diff --git a/pydhcplib/man/man3/pydhcplib.ipv4.3.gz b/pydhcplib/man/man3/pydhcplib.ipv4.3.gz new file mode 100644 index 0000000000000000000000000000000000000000..123dda4070b1d57a56d056cd6c0699ae48847cdc GIT binary patch literal 713 zcmV;)0yh00iwFP!000001Eo}LYvMo<{(So@rulLTxviRV^aKyIhO6L9Fcz+~rL1wI zOY_F=+SY%6vq`Lpr}W@Jah;iGW}atuhc0fx%66+wkVRriMfQ4Sf#u-0_;~lj+Z%5@ z8d!w-7&`4wT#M8J@c0cDyNpAaN*H;-Rx8Ps;tF25R3c5_ssQ`<)0yXwe2auKjp2|* zBlJc|-kW$R`CS55I3Fr-KQ50m7L!2rd?LGpqMv%rClR{x5jUM!D_-O;z0j0D_2#*wp zE+I&%(FDo$Rwl4wnjtJfIZZK~O^Q8dNLsUH#7q82*3kG2R-=j-G=BoY`IW-p|56F} zcYorIU6kT69JueyXkn(gmMqS1&@(TLG}}ST1`0ovN=>_c>LcgEWZ<;XtYfAI*26 zKz=EqsJn)GSsScg@3>NNbIyXHioU3#&$Z&5&Q`F5)4e#K_3}6RqK3{lp6fz??9cWq zvvJ+DD;H<;7PFw?)NJ`U>!xzC8Ea+r4)NDx!3)<%;l?pwN(5)UQ?B1q`EtT@6A4@c zCmeJ3cGfrK5?>iQNWpq=_X}T>&pB+g&bpVEm8Y_O4_Pdt9Zlu>GT)zZin~Q5c#QL% vRzA!A9WJQ3MJ5c_5Z}URov=Wp(1=BGdgw2n7!D*dshZ>u15OZV$_4-c%3)aQ literal 0 HcmV?d00001 diff --git a/pydhcplib/man/man3/pydhcplib.strlist.3.gz b/pydhcplib/man/man3/pydhcplib.strlist.3.gz new file mode 100644 index 0000000000000000000000000000000000000000..a6695eb482f5dde8cdfec36ec652fbe6fbe2a8de GIT binary patch literal 959 zcmV;w13>&AiwFP!000001D#cEZ{kJ}{@nc)bN*70T!**2YmsP00=gjO1qDv+>2iwJ z_870uZ{1zvxWE2py+8~ktyC#EFz?SiGh=Uk4Ng&qaZn_}_mq~2P}%`!NFV#R{4%?~ zTHY)!9pLl=bpnQ8%5 z22H>`GXZ%)37$pDH6}F-dp+A<3Mq6<1-+18Ieb zHk_prtYa$uJYFS|1aOO)E_p)r`bcmH0pYP# zP#mI<`w7Apr2(mqN6ECdKn%;Gv2Ar%ixge(OAS7Cu;Ma=AWsXfg>R~?ZF0&;JeLwf zkFkdMbIR=~1QN-Yy3FOKOsQlDs7J=XnPpQJ%gWTJGNFod>g|>%CBi1B@ownt{qg?2 z_rH^n;cjTAtE1m@%rN( z9ig^M`EQ>4F4}>$pyq!~ZVh39Z~KY8XF85A4;8aoAsb zF?K&0qlF94&xVoqTVjX*Lsi#KOFd|-|E^Be!}j6%?V}6*!GIpUK0W#)^Y~z7eL6sl zHBAGD_h1Z;Yus(1y}W;r_m35WgJN*37#hYQ|H&N+Zu}ImC+d< z$waXoorv}nlC<@jo6-MebC*xdjpC9k5xl9rvp4<~%~c|3VP8=^@aj$73?=OoDVRll z`S}wq%L)-_9{S18{j{Xk&0LH~@8&O^@O*42JLh6;@9mEj_RHR-hV?_!0$a zN5CPphDOsSRhkY$+8@8pN0$!6N|3sV^SqAjG}_G|tnYb|)ggpG>F<7<_vvi1S95uOWy14#QiGtI&7PN-)f;(Y^-7BW6nR!|SvfY8M%z0cIDO1KQ#*t~no~UyYfG%9(!SQFKApO;%~Ava z-k({2mgfqa=098fl>qP6Nhw!Mb_=$2FDjX1ubIqi1ioWUZrg?~U_niDL8e=UaO1kL zZAERxiJbJ8S%c#*EV zj{{vWw=mwnk 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 vlue 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] : + print "Error, bad option length (a): ", 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' + 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]} + + 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 + + print "Error, unknown option : ", name, value + 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): + options = [] + + + for each in self.options_data.keys() : + options.append(DhcpOptions[each]) + options.append(len(self.options_data[each])) + options += self.options_data[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)) + if ( debug ) : print "Packet length : ",len(self.packet_data) + + + # 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 + if ( debug ) : print "Debug : ", self.packet_data[iterator:-1] + + + while iterator < end_iterator : + if ( debug ) : + print "Debug Option : ", iterator , self.packet_data[iterator]," : ",DhcpOptionsList[self.packet_data[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 diff --git a/pydhcplib/pydhcplib/dhcp_constants.py b/pydhcplib/pydhcplib/dhcp_constants.py new file mode 100644 index 0000000..295aa78 --- /dev/null +++ b/pydhcplib/pydhcplib/dhcp_constants.py @@ -0,0 +1,404 @@ +# Anemon Dhcp +# Copyright (C) 2005 Mathieu Ignacio -- mignacio@april.org +# +# 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. +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + + +MagicCookie = [99,130,83,99] + + +# 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] + } +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_information':43, + 'nbns':44, + 'nbdd':45,'node_type':46, + 'netbios_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, + 'class_identifier':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_world_wide_web_server':72, + 'default_finger_server':73, + 'default_internet_relay_chat_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_information','nbns', + 'nbdd','node_type', + 'netbios_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', + 'class_identifier', + '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_world_wide_web_server', + 'default_finger_server', + 'default_internet_relay_chat_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:"ipv4", 55:"none", + 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:"Un"} diff --git a/pydhcplib/pydhcplib/dhcp_network.py b/pydhcplib/pydhcplib/dhcp_network.py new file mode 100644 index 0000000..5e95707 --- /dev/null +++ b/pydhcplib/pydhcplib/dhcp_network.py @@ -0,0 +1,134 @@ +# pydhcplib +# Copyright (C) 2005,2006 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 2 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, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +import sys +import socket +import dhcp_packet + + +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 + + def GetNextDhcpPacket(self): + data ="" + + while data == "" : + data = self.dhcp_socket.recv(1024) + if data != "" : + packet = dhcp_packet.DhcpPacket() + 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, To, packet): + return self.dhcp_socket.sendto(packet.EncodePacket(),(To,self.emit_port)) + + + # Server side Handle methods + def HandleDhcpDiscover(self, packet): + print "HandleDhcpRequest : method not implemented" + + def HandleDhcpRequest(self, packet): + print "HandleDhcpRequest : method not implemented" + + def HandleDhcpDecline(self, packet): + print "HandleDhcpDecline : method not implemented" + + def HandleDhcpRelease(self, packet): + print "HandleDhcpRelease : method not implemented" + + def HandleDhcpInform(self, packet): + print "HandleDhcpInform : method not implemented" + + + # client-side Handle methods + def HandleDhcpOffer(self, packet): + print "HandleDhcpOffer : method not implemented" + + def HandleDhcpAck(self, packet): + print "HandleDhcpAckhandling : method not implemented" + + def HandleDhcpNack(self, packet): + print "HandleDhcpNack : method not implemented" + + + # Handle unknown options or all options + def HandleDhcpUnknown(self, packet): + print "HandleDhcpUnknown : method not implemented" + + def HandleDhcpAll(self, packet): + pass + + +class DhcpServer(DhcpNetwork) : + def __init__(self, listen_address="0.0.0.0", client_listen_port=67,server_listen_port=68) : + + DhcpNetwork.__init__(self,listen_address,server_listen_port,client_listen_port) + + self.dhcp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.dhcp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1) + self.dhcp_socket.bind((self.listen_address, self.listen_port)) + + +class DhcpClient(DhcpNetwork) : + def __init__(self, listen_address="0.0.0.0",client_listen_port=67,server_listen_port=68) : + + DhcpNetwork.__init__(self,listen_address,client_listen_port,server_listen_port) + + self.dhcp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.dhcp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1) + self.dhcp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) + self.dhcp_socket.bind((self.listen_address, self.listen_port)) + +# Raw client permit to listen on network even if there is +# no interface set. Probably useful... :-) +class DhcpRawClient(DhcpNetwork) : + def __init__(self, interface="eth0", client_listen_port=67,server_listen_port=68) : + + DhcpNetwork.__init__(self,interface,client_listen_port,server_listen_port) + print interface + # 0x800 : ETH_P_IP, 0x003 : ETH_P_ALL + # See Linux/if_ether.h + self.dhcp_socket = socket.socket(socket.AF_PACKET, socket.SOCK_DGRAM,socket.ntohs(0x0800)) + + diff --git a/pydhcplib/pydhcplib/dhcp_packet.py b/pydhcplib/pydhcplib/dhcp_packet.py new file mode 100644 index 0000000..4f564f7 --- /dev/null +++ b/pydhcplib/pydhcplib/dhcp_packet.py @@ -0,0 +1,221 @@ +# Anemon Dhcp +# Copyright (C) 2005 Mathieu Ignacio -- mignacio@april.org +# +# 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. +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +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 +class DhcpPacket(DhcpBasicPacket): + + + # Useful function for debugging + def PrintHeaders(self): + print "# Header fields\n" + print "readable_dhcp_headers = {" + for opt in ['op','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] + if DhcpFieldsTypes[opt] == "int" : result = str(data[0]) + if DhcpFieldsTypes[opt] == "int2" : result = str(data[0]*256+data[0]) + if DhcpFieldsTypes[opt] == "int4" : result = str(ipv4(data).int()) + if DhcpFieldsTypes[opt] == "str" : result = strlist(data).str() + if DhcpFieldsTypes[opt] == "ipv4" : result = ipv4(data).str() + if DhcpFieldsTypes[opt] == "hwmac" : result = "".join(map(chr,data)) + + line = "\t'"+opt+"':"+str(data)+",\t# "+result + print line + print "\t'end':'true'}" + + # Useful function for debugging + def PrintOptions(self): + print "# Options fields" + print "readable_dhcp_options = {" + for opt in self.options_data.keys(): + data = self.options_data[opt] + result = "" + optnum = DhcpOptions[opt] + if DhcpOptionsTypes[optnum] == "char" : result = str(data[0]) + if DhcpOptionsTypes[optnum] == "16-bits" : result = str(data[0]*256+data[0]) + if DhcpOptionsTypes[optnum] == "32bits" : result = str(ipv4(data).int()) + if DhcpOptionsTypes[optnum] == "string" : result = strlist(data).str() + if DhcpOptionsTypes[optnum] == "ipv4" : result = ipv4(data).str() + if 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() + " - " + line = "\t'"+opt+"':"+str(data)+",\t# "+result + print line + print "\t'end':'true'}" + + + + # 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 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 + __str__=str + + # 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 + + + + diff --git a/pydhcplib/pydhcplib/type_ipv4.py b/pydhcplib/pydhcplib/type_ipv4.py new file mode 100644 index 0000000..f42dec0 --- /dev/null +++ b/pydhcplib/pydhcplib/type_ipv4.py @@ -0,0 +1,117 @@ +# Anemon Dhcp +# Copyright (C) 2005 Mathieu Ignacio -- mignacio@april.org +# +# 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. +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + + +# 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.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 + __str__=str + + # 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 + + + diff --git a/pydhcplib/pydhcplib/type_strlist.py b/pydhcplib/pydhcplib/type_strlist.py new file mode 100644 index 0000000..ca5f1c0 --- /dev/null +++ b/pydhcplib/pydhcplib/type_strlist.py @@ -0,0 +1,65 @@ +# Anemon Dhcp +# Copyright (C) 2005 Mathieu Ignacio -- mignacio@april.org +# +# 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. +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +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 + + + diff --git a/pydhcplib/scripts/pydhcp b/pydhcplib/scripts/pydhcp new file mode 100644 index 0000000..a0fec1b --- /dev/null +++ b/pydhcplib/scripts/pydhcp @@ -0,0 +1,122 @@ +#!/usr/bin/python + + +from pydhcplib import dhcp_constants +from pydhcplib import dhcp_packet +from pydhcplib import dhcp_network + +from pydhcplib import type_hw_addr +from pydhcplib import type_ipv4 +from pydhcplib import type_strlist + +import sys + +from optparse import OptionParser + + +parser = OptionParser() + +""" Action options """ +parser.add_option("-L", "--listen", action="store_true",dest="listen", help="",default=False) +parser.add_option("-E", "--emit", action="store_true",dest="emit", help="", default=False) +parser.add_option("-R", "--readable-conversion", action="store_true",dest="readable", help="", default=False) +parser.add_option("-B", "--binary-conversion", action="store_true",dest="binary", help="", default=False) +parser.add_option("-s", "--source-file", action="store",dest="source", help="", default=False, type="string") +parser.add_option("-d", "--destination-file", action="store",dest="destination", help="", default=False, type="string") +parser.add_option("-p", "--port", action="store",dest="port", help="", default="67", type="int") +parser.add_option("-a", "--address", action="store",dest="address", help="", default="0.0.0.0", type="string") +parser.add_option("-r", "--raw", action="store",dest="raw", help="", default=False,type="string") +parser.add_option("-n", "--number", action="store",dest="number", help="", default="0", type="int") + + + +(options, args) = parser.parse_args() + +print options + + + +def main() : + ActionSum = 0 + for Action in (options.listen,options.emit,options.readable,options.binary) : + if Action == True : ActionSum += 1 + if ActionSum > 1 : + print "Command line error : [-L -E -R -B] Only one of these actions can be taken." + sys.exit(0) + + if options.readable == True : r_conversion() + + if options.binary == True : b_conversion() + + if options.listen == True : + if options.raw == False: + listen_address(options.address,options.port,int(options.number)) + else : + print "Listen RAW : ",options.raw + listen_packet(options.raw,options.number) + + if options.emit == True : emit(options.address,options.port) + + +def listen_address(address,port,number) : + listener = dhcp_network.DhcpClient(address,port,port) + + if (number == 0 ) : + while True : + packet = listener.GetNextDhcpPacket() + packet.PrintHeaders() + packet.PrintOptions() + + else : + while number > 0 : + packet = listener.GetNextDhcpPacket() + packet.PrintHeaders() + packet.Print() + + number -= 1 + +def listen_packet(interface,number) : + listener = dhcp_network.DhcpRawClient(mysocket) + + if (number == 0 ) : + while True : + packet = dhcp_packet.DhcpPacket() + + packet.DecodePacket(listener.Receive(1024)) + packet.PrintHeaders() + packet.PrintOptions() + + else : + while number > 0 : + packet = dhcp_packet.DhcpPacket() + + packet.DecodePacket(listener.Receive(1024)) + packet.PrintHeaders() + packet.PrintOptions() + + number -= 1 + + +def emit(address,port) : + pass + +def r_conversion() : + rawdata = sys.stdin.read() + while ( len(rawdata)>0 ) : + readdata = dhcp_packet.DhcpPacket() + readdata.DecodePacket(rawdata) + readdata.PrintHeaders() + readdata.PrintOptions() + rawdata = sys.stdin.read() + +def b_conversion() : + """ + pythondata = sys.stdin.read() + while ( len(pythondata)>0 ) : + data = dhcp_packet.DhcpPacket() + data.DecodePacket(rawdata) + + pythondata = sys.stdin.read() + """ + +main() diff --git a/pydhcplib/scripts/pydhcp.py b/pydhcplib/scripts/pydhcp.py new file mode 100644 index 0000000..8cd8a47 --- /dev/null +++ b/pydhcplib/scripts/pydhcp.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + + +import dhcp_constants +import dhcp_packet +import dhcp_network + +import type_hw_addr +import type_ipv4 +import type_strlist + +import sys + +from optparse import OptionParser + + +parser = OptionParser() + +""" Action options """ +parser.add_option("-L", "--listen", action="store_true",dest="listen", help="",default="False") +parser.add_option("-E", "--emit", action="store_true",dest="emit", help="", default="False") +parser.add_option("-R", "--readable-conversion", action="store_true",dest="readable", help="", default="False") +parser.add_option("-B", "--binary-conversion", action="store_true",dest="binary", help="", default="False") + + +parser.add_option("-s", "--source-file", action="store",dest="source", help="", default="False", type="string") +parser.add_option("-d", "--destination-file", action="store",dest="destination", help="", default="False", type="string") + + + +(options, args) = parser.parse_args() + +print options + + + +def main() : + ActionSum = 0 + for Action in (options.listen,options.emit,options.readable,options.binary) : + if Action == True : ActionSum += 1 + if ActionSum > 1 : + print "Command line error : [-L -E -R -B] Only one of these actions can be taken." + sys.exit(0) + + if options.readable == True : r_conversion() + + + +def listen(port) : + pass + +def emit(address,port) : + pass + +def r_conversion() : + rawdata = rawdata = sys.stdin.read() + while ( len(rawdata)>0 ) : + readdata = dhcp_packet.DhcpPacket() + readdata.DecodePacket(rawdata) + readdata.PrintHeaders() + readdata.PrintOptions() + rawdata = rawdata = sys.stdin.read() + +def b_conversion() : + pass + +main() diff --git a/pydhcplib/setup.py b/pydhcplib/setup.py new file mode 100755 index 0000000..2c8b955 --- /dev/null +++ b/pydhcplib/setup.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +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'] +en8_manpages=['man/man8/pydhcp.8.gz'] + +setup(name='pydhcplib', + version="0.1", + license='GPL v2', + description='Dhcp client/server library', + author='Mathieu Ignacio', + author_email='tamtam@anemon.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) + ]) -- 1.7.9.5