From 739c89a9c6872a19d6c9ebd72ae1b6d82e4803e7 Mon Sep 17 00:00:00 2001 From: Evan Broder Date: Sun, 30 Mar 2008 16:56:54 -0400 Subject: [PATCH] Splitting pydhcplib off into its own package Hold onto your hats, folks - this could get messy svn path=/trunk/packages/sipb-xen-python-pydhcplib/; revision=361 --- COPYING | 280 +++++++++++++++++++ README | 20 ++ debian/changelog | 6 + debian/compat | 1 + debian/control | 12 + debian/control.in | 12 + debian/copyright | 31 +++ debian/docs | 1 + debian/pycompat | 1 + debian/pyversions | 1 + debian/rules | 7 + examples/client_example.py | 51 ++++ examples/gen_packet_example.py | 16 ++ examples/hwaddr_example.py | 32 +++ examples/ipv4_example.py | 28 ++ examples/server_example.py | 59 ++++ examples/strlist_example.py | 25 ++ man/fr/man3/pydhcplib.3.gz | Bin 0 -> 488 bytes man/fr/man3/pydhcplib.DhcpBasicPacket.3.gz | Bin 0 -> 1489 bytes man/fr/man3/pydhcplib.DhcpPacket.3.gz | Bin 0 -> 1230 bytes man/fr/man3/pydhcplib.hwmac.3.gz | Bin 0 -> 1047 bytes man/fr/man3/pydhcplib.ipv4.3.gz | Bin 0 -> 818 bytes man/fr/man3/pydhcplib.strlist.3.gz | Bin 0 -> 1077 bytes man/fr/man8/pydhcp.8.gz | Bin 0 -> 877 bytes man/man3/pydhcplib.3.gz | Bin 0 -> 434 bytes man/man3/pydhcplib.ipv4.3.gz | Bin 0 -> 713 bytes man/man3/pydhcplib.strlist.3.gz | Bin 0 -> 959 bytes man/man8/pydhcp.8.gz | Bin 0 -> 621 bytes pydhcplib/__init__.py | 1 + pydhcplib/dhcp_basic_packet.py | 188 +++++++++++++ pydhcplib/dhcp_constants.py | 404 ++++++++++++++++++++++++++++ pydhcplib/dhcp_network.py | 134 +++++++++ pydhcplib/dhcp_packet.py | 221 +++++++++++++++ pydhcplib/type_hw_addr.py | 85 ++++++ pydhcplib/type_ipv4.py | 116 ++++++++ pydhcplib/type_strlist.py | 65 +++++ scripts/pydhcp | 122 +++++++++ scripts/pydhcp.py | 67 +++++ setup.py | 26 ++ 39 files changed, 2012 insertions(+) create mode 100644 COPYING create mode 100644 README create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/control.in create mode 100644 debian/copyright create mode 100644 debian/docs create mode 100644 debian/pycompat create mode 100644 debian/pyversions create mode 100755 debian/rules create mode 100755 examples/client_example.py create mode 100755 examples/gen_packet_example.py create mode 100644 examples/hwaddr_example.py create mode 100755 examples/ipv4_example.py create mode 100644 examples/server_example.py create mode 100755 examples/strlist_example.py create mode 100644 man/fr/man3/pydhcplib.3.gz create mode 100644 man/fr/man3/pydhcplib.DhcpBasicPacket.3.gz create mode 100644 man/fr/man3/pydhcplib.DhcpPacket.3.gz create mode 100644 man/fr/man3/pydhcplib.hwmac.3.gz create mode 100644 man/fr/man3/pydhcplib.ipv4.3.gz create mode 100644 man/fr/man3/pydhcplib.strlist.3.gz create mode 100644 man/fr/man8/pydhcp.8.gz create mode 100644 man/man3/pydhcplib.3.gz create mode 100644 man/man3/pydhcplib.ipv4.3.gz create mode 100644 man/man3/pydhcplib.strlist.3.gz create mode 100644 man/man8/pydhcp.8.gz create mode 100644 pydhcplib/__init__.py create mode 100644 pydhcplib/dhcp_basic_packet.py create mode 100644 pydhcplib/dhcp_constants.py create mode 100644 pydhcplib/dhcp_network.py create mode 100644 pydhcplib/dhcp_packet.py create mode 100644 pydhcplib/type_hw_addr.py create mode 100644 pydhcplib/type_ipv4.py create mode 100644 pydhcplib/type_strlist.py create mode 100644 scripts/pydhcp create mode 100644 scripts/pydhcp.py create mode 100755 setup.py diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..4a4f44a --- /dev/null +++ b/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/README b/README new file mode 100644 index 0000000..04eadbb --- /dev/null +++ b/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/debian/changelog b/debian/changelog new file mode 100644 index 0000000..cb5c741 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +sipb-xen-python-pydhcplib (0.3.2-1) unstable; urgency=low + + * Initial release. + + -- SIPB Xen Project Sun, 30 Mar 2008 16:03:05 -0400 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..68300c1 --- /dev/null +++ b/debian/control @@ -0,0 +1,12 @@ +Source: sipb-xen-python-pydhcplib +Section: python +Priority: extra +Maintainer: SIPB Xen Project +Build-Depends: cdbs (>= 0.4.23-1.1), debhelper (>= 5), debhelper (>= 5.0.37.2), cdbs (>= 0.4.43), python-all-dev (>= 2.3.5-11), python-support (>= 0.3.2) +Standards-Version: 3.7.2 + +Package: sipb-xen-python-pydhcplib +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends} +Provides: ${python:Provides} +Description: A pure Python library for handling DHCP packets and requests diff --git a/debian/control.in b/debian/control.in new file mode 100644 index 0000000..95e4ea7 --- /dev/null +++ b/debian/control.in @@ -0,0 +1,12 @@ +Source: sipb-xen-python-pydhcplib +Section: python +Priority: extra +Maintainer: SIPB Xen Project +Build-Depends: @cdbs@ +Standards-Version: 3.7.2 + +Package: sipb-xen-python-pydhcplib +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends} +Provides: ${python:Provides} +Description: A pure Python library for handling DHCP packets and requests diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..244defe --- /dev/null +++ b/debian/copyright @@ -0,0 +1,31 @@ +This package was debianized by for the SIPB Xen Project +on Sun, 30 Mar 2008 16:40:21 -0400. + +It was downloaded from http://pydhcplib.tuxfamily.org/download/ + +Upstream Author(s): + + Mathieu Ignacio + +Copyright: + + Copyright (C) 2005 Mathieu Ignacio -- mignacio@april.org + +License: + + 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 package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +README diff --git a/debian/pycompat b/debian/pycompat new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/debian/pycompat @@ -0,0 +1 @@ +2 diff --git a/debian/pyversions b/debian/pyversions new file mode 100644 index 0000000..0087e9e --- /dev/null +++ b/debian/pyversions @@ -0,0 +1 @@ +2.4- \ No newline at end of file diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..79ab8a3 --- /dev/null +++ b/debian/rules @@ -0,0 +1,7 @@ +#!/usr/bin/make -f + +DEB_AUTO_UPDATE_DEBIAN_CONTROL=1 +DEB_PYTHON_SYSTEM=pysupport + +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/class/python-distutils.mk diff --git a/examples/client_example.py b/examples/client_example.py new file mode 100755 index 0000000..c8f3887 --- /dev/null +++ b/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/examples/gen_packet_example.py b/examples/gen_packet_example.py new file mode 100755 index 0000000..c6e7550 --- /dev/null +++ b/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/examples/hwaddr_example.py b/examples/hwaddr_example.py new file mode 100644 index 0000000..9c5de80 --- /dev/null +++ b/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/examples/ipv4_example.py b/examples/ipv4_example.py new file mode 100755 index 0000000..2a74c67 --- /dev/null +++ b/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/examples/server_example.py b/examples/server_example.py new file mode 100644 index 0000000..1a079ab --- /dev/null +++ b/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/examples/strlist_example.py b/examples/strlist_example.py new file mode 100755 index 0000000..9a597ad --- /dev/null +++ b/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/man/fr/man3/pydhcplib.3.gz b/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/man/fr/man3/pydhcplib.DhcpBasicPacket.3.gz b/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/man/fr/man3/pydhcplib.DhcpPacket.3.gz b/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/man/fr/man3/pydhcplib.hwmac.3.gz b/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/man/fr/man3/pydhcplib.ipv4.3.gz b/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/man/fr/man3/pydhcplib.strlist.3.gz b/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/man/fr/man8/pydhcp.8.gz b/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/man/man3/pydhcplib.3.gz b/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/man/man3/pydhcplib.ipv4.3.gz b/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/man/man3/pydhcplib.strlist.3.gz b/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/dhcp_constants.py b/pydhcplib/dhcp_constants.py new file mode 100644 index 0000000..295aa78 --- /dev/null +++ b/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/dhcp_network.py b/pydhcplib/dhcp_network.py new file mode 100644 index 0000000..5e95707 --- /dev/null +++ b/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/dhcp_packet.py b/pydhcplib/dhcp_packet.py new file mode 100644 index 0000000..4f564f7 --- /dev/null +++ b/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 + + # 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/type_ipv4.py b/pydhcplib/type_ipv4.py new file mode 100644 index 0000000..c6177a4 --- /dev/null +++ b/pydhcplib/type_ipv4.py @@ -0,0 +1,116 @@ +# 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 + + # 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/type_strlist.py b/pydhcplib/type_strlist.py new file mode 100644 index 0000000..ca5f1c0 --- /dev/null +++ b/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/scripts/pydhcp b/scripts/pydhcp new file mode 100644 index 0000000..a0fec1b --- /dev/null +++ b/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/scripts/pydhcp.py b/scripts/pydhcp.py new file mode 100644 index 0000000..8cd8a47 --- /dev/null +++ b/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/setup.py b/setup.py new file mode 100755 index 0000000..2dc7e23 --- /dev/null +++ b/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.3.2", + 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