--- /dev/null
+#!/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()
--- /dev/null
+# 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.")
--- /dev/null
+ 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.
+\f
+ 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.)
+\f
+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.
+\f
+ 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.
+\f
+ 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
--- /dev/null
+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
--- /dev/null
+#!/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()
--- /dev/null
+#!/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()
--- /dev/null
+#!/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()
--- /dev/null
+#!/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
+
+
+
--- /dev/null
+#!/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()
--- /dev/null
+#!/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
+
+
+
--- /dev/null
+__version__ = '0.2'
--- /dev/null
+# 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_constants import *
+
+# DhcpPacket : base class to encode/decode dhcp packets.
+
+
+class DhcpBasicPacket:
+ def __init__(self):
+ self.packet_data = [0]*240
+ self.options_data = {}
+ self.packet_data[236:240] = MagicCookie
+
+ def IsDhcpPacket(self):
+ if self.packet_data[236:240] != MagicCookie : return False
+ return True
+
+ # Check if variable is a list with int between 0 and 255
+ def CheckType(self,variable):
+ if type(variable) == list :
+ for each in variable :
+ if (type(each) != int) or (each < 0) or (each > 255) :
+ return False
+ return True
+ else : return False
+
+
+ def DeleteOption(self,name):
+ # if name is a standard dhcp field
+ # Set field to 0
+ if DhcpFields.has_key(name) :
+ begin = DhcpFields[name][0]
+ end = DhcpFields[name][0]+DhcpFields[name][1]
+ self.packet_data[begin:end] = [0]*DhcpFields[name][1]
+ return True
+
+ # if name is a dhcp option
+ # delete option from self.option_data
+ elif self.options_data.has_key(name) :
+ # forget how to remove a key... try delete
+ self.options_data.__delitem__(name)
+ return True
+
+ return False
+
+ def GetOption(self,name):
+ if DhcpFields.has_key(name) :
+ option_info = DhcpFields[name]
+ return self.packet_data[option_info[0]:option_info[0]+option_info[1]]
+
+ elif self.options_data.has_key(name) :
+ return self.options_data[name]
+
+ return []
+
+
+ def SetOption(self,name,value):
+
+ # Basic 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
--- /dev/null
+# 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"}
--- /dev/null
+# 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))
+
+
--- /dev/null
+# 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<len(full_hw) : return full_hw[0:length]
+ return full_hw
+
--- /dev/null
+# 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
+
+
+from binascii import unhexlify,hexlify
+
+# Check and convert hardware/nic/mac address type
+class hwmac:
+ def __init__(self,value="00:00:00:00:00:00") :
+ self._hw_numlist = []
+ self._hw_string = ""
+ hw_type = type(value)
+ if hw_type == str :
+ self._hw_string = value
+ self._StringToNumlist(value)
+ self._CheckNumList()
+ elif hw_type == list :
+ self._hw_numlist = value
+ self._CheckNumList()
+ self._NumlistToString()
+ else : raise TypeError , 'hwmac init : Valid types are tr and list'
+
+
+
+ # Check if _hw_numlist is valid and raise error if not.
+ def _CheckNumList(self) :
+ if len(self._hw_numlist) != 6 : raise ValueError , "hwmac : wrong list length."
+ for part in self._hw_numlist :
+ if type (part) != int : raise TypeError , "hwmac : each element of list must be int"
+ if part < 0 or part > 255 : raise ValueError , "hwmac : need numbers between 0 and 255."
+ return True
+
+
+ def _StringToNumlist(self,value):
+ self._hw_string = self._hw_string.replace("-",":").replace(".",":")
+ self._hw_string = self._hw_string.lower()
+
+
+ for twochar in self._hw_string.split(":"):
+ self._hw_numlist.append(ord(unhexlify(twochar)))
+
+ # Convert NumList type ip to String type ip
+ def _NumlistToString(self) :
+ self._hw_string = ":".join(map(hexlify,map(chr,self._hw_numlist)))
+
+ # Convert String type ip to NumList type ip
+ # return ip string
+ def str(self) :
+ return self._hw_string
+ __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
+
+
+
+
--- /dev/null
+# 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
+
+
+
--- /dev/null
+# 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
+
+
+
--- /dev/null
+#!/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()
--- /dev/null
+#!/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()
--- /dev/null
+#!/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)
+ ])