2 # Copyright (C) 2005 Mathieu Ignacio -- mignacio@april.org
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 from struct import unpack
20 from struct import pack
21 from dhcp_basic_packet import *
22 from dhcp_constants import *
23 from type_ipv4 import ipv4
24 from type_strlist import strlist
25 class DhcpPacket(DhcpBasicPacket):
28 # Useful function for debugging
29 def PrintHeaders(self):
30 print "# Header fields\n"
31 print "readable_dhcp_headers = {"
32 for opt in ['op','htype','hlen','hops','xid','secs','flags',
33 'ciaddr','yiaddr','siaddr','giaddr','chaddr','sname','file'] :
34 begin = DhcpFields[opt][0]
35 end = DhcpFields[opt][0]+DhcpFields[opt][1]
36 data = self.packet_data[begin:end]
37 if DhcpFieldsTypes[opt] == "int" : result = str(data[0])
38 if DhcpFieldsTypes[opt] == "int2" : result = str(data[0]*256+data[0])
39 if DhcpFieldsTypes[opt] == "int4" : result = str(ipv4(data).int())
40 if DhcpFieldsTypes[opt] == "str" : result = strlist(data).str()
41 if DhcpFieldsTypes[opt] == "ipv4" : result = ipv4(data).str()
42 if DhcpFieldsTypes[opt] == "hwmac" : result = "".join(map(chr,data))
44 line = "\t'"+opt+"':"+str(data)+",\t# "+result
46 print "\t'end':'true'}"
48 # Useful function for debugging
49 def PrintOptions(self):
50 print "# Options fields"
51 print "readable_dhcp_options = {"
52 for opt in self.options_data.keys():
53 data = self.options_data[opt]
55 optnum = DhcpOptions[opt]
56 if DhcpOptionsTypes[optnum] == "char" : result = str(data[0])
57 if DhcpOptionsTypes[optnum] == "16-bits" : result = str(data[0]*256+data[0])
58 if DhcpOptionsTypes[optnum] == "32bits" : result = str(ipv4(data).int())
59 if DhcpOptionsTypes[optnum] == "string" : result = strlist(data).str()
60 if DhcpOptionsTypes[optnum] == "ipv4" : result = ipv4(data).str()
61 if DhcpOptionsTypes[optnum] == "ipv4+" :
62 for i in range(0,len(data),4) :
63 if len(data[i:i+4]) == 4 :
64 result += ipv4(data[i:i+4]).str() + " - "
65 line = "\t'"+opt+"':"+str(data)+",\t# "+result
67 print "\t'end':'true'}"
71 # FIXME: This is called from IsDhcpSomethingPacket, but is this really
72 # needed? Or maybe this testing should be done in
73 # DhcpBasicPacket.DecodePacket().
76 def IsDhcpSomethingPacket(self,type):
77 if self.IsDhcpPacket() == False : return False
78 if self.IsOption("dhcp_message_type") == False : return False
79 if self.GetOption("dhcp_message_type") != type : return False
82 def IsDhcpDiscoverPacket(self):
83 return self.IsDhcpSomethingPacket([1])
85 def IsDhcpOfferPacket(self):
86 return self.IsDhcpSomethingPacket([2])
88 def IsDhcpRequestPacket(self):
89 return self.IsDhcpSomethingPacket([3])
91 def IsDhcpDeclinePacket(self):
92 return self.IsDhcpSomethingPacket([4])
94 def IsDhcpAckPacket(self):
95 return self.IsDhcpSomethingPacket([5])
97 def IsDhcpNackPacket(self):
98 return self.IsDhcpSomethingPacket([6])
100 def IsDhcpReleasePacket(self):
101 return self.IsDhcpSomethingPacket([7])
103 def IsDhcpInformPacket(self):
104 return self.IsDhcpSomethingPacket([8])
107 def GetMultipleOptions(self,options=()):
110 result[each] = self.GetOption(each)
113 def SetMultipleOptions(self,options={}):
114 for each in options.keys():
115 self.SetOption(each,options[each])
122 # Creating Response Packet
124 # Server-side functions
125 # From RFC 2132 page 28/29
126 def CreateDhcpOfferPacketFrom(self,src): # src = discover packet
127 self.SetOption("htype",src.GetOption("htype"))
128 self.SetOption("xid",src.GetOption("xid"))
129 self.SetOption("flags",src.GetOption("flags"))
130 self.SetOption("giaddr",src.GetOption("giaddr"))
131 self.SetOption("chaddr",src.GetOption("chaddr"))
132 self.SetOption("ip_address_lease_time",src.GetOption("ip_address_lease_time"))
133 self.TransformToDhcpOfferPacket()
135 def TransformToDhcpOfferPacket(self):
136 self.SetOption("dhcp_message_type",[2])
137 self.SetOption("op",[2])
138 self.SetOption("hlen",[6])
140 self.DeleteOption("secs")
141 self.DeleteOption("ciaddr")
142 self.DeleteOption("request_ip_address")
143 self.DeleteOption("parameter_request_list")
144 self.DeleteOption("client_identifier")
145 self.DeleteOption("maximum_message_size")
151 """ Dhcp ACK packet creation """
152 def CreateDhcpAckPacketFrom(self,src): # src = request or inform packet
153 self.SetOption("htype",src.GetOption("htype"))
154 self.SetOption("xid",src.GetOption("xid"))
155 self.SetOption("ciaddr",src.GetOption("ciaddr"))
156 self.SetOption("flags",src.GetOption("flags"))
157 self.SetOption("giaddr",src.GetOption("giaddr"))
158 self.SetOption("chaddr",src.GetOption("chaddr"))
159 self.SetOption("ip_address_lease_time_option",src.GetOption("ip_address_lease_time_option"))
160 self.TransformToDhcpAckPacket()
162 def TransformToDhcpAckPacket(self): # src = request or inform packet
163 self.SetOption("op",[2])
164 self.SetOption("hlen",[6])
165 self.SetOption("dhcp_message_type",[5])
167 self.DeleteOption("secs")
168 self.DeleteOption("request_ip_address")
169 self.DeleteOption("parameter_request_list")
170 self.DeleteOption("client_identifier")
171 self.DeleteOption("maximum_message_size")
174 """ Dhcp NACK packet creation """
175 def CreateDhcpNackPacketFrom(self,src): # src = request or inform packet
177 self.SetOption("htype",src.GetOption("htype"))
178 self.SetOption("xid",src.GetOption("xid"))
179 self.SetOption("flags",src.GetOption("flags"))
180 self.SetOption("giaddr",src.GetOption("giaddr"))
181 self.SetOption("chaddr",src.GetOption("chaddr"))
182 self.TransformToDhcpNackPacket()
184 def TransformToDhcpNackPacket(self):
185 self.SetOption("op",[2])
186 self.SetOption("hlen",[6])
187 self.DeleteOption("secs")
188 self.DeleteOption("ciaddr")
189 self.DeleteOption("yiaddr")
190 self.DeleteOption("siaddr")
191 self.DeleteOption("sname")
192 self.DeleteOption("file")
193 self.DeleteOption("request_ip_address")
194 self.DeleteOption("ip_address_lease_time_option")
195 self.DeleteOption("parameter_request_list")
196 self.DeleteOption("client_identifier")
197 self.DeleteOption("maximum_message_size")
198 self.SetOption("dhcp_message_type",[6])
206 """ GetClientIdentifier """
208 def GetClientIdentifier(self) :
209 if self.IsOption("client_identifier") :
210 return self.GetOption("client_identifier")
213 def GetGiaddr(self) :
214 return self.GetOption("giaddr")
216 def GetHardwareAddress(self) :
217 length = self.GetOption("hlen")[0]
218 full_hw = self.GetOption("chaddr")
219 if length!=[] and length<len(full_hw) : return full_hw[0:length]