| [361] | 1 | # Anemon Dhcp | 
|---|
 | 2 | # Copyright (C) 2005 Mathieu Ignacio -- mignacio@april.org | 
|---|
 | 3 | # | 
|---|
 | 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. | 
|---|
 | 8 | # | 
|---|
 | 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. | 
|---|
 | 13 | # | 
|---|
 | 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 | 
|---|
 | 17 |  | 
|---|
 | 18 | import operator | 
|---|
 | 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): | 
|---|
 | 26 |  | 
|---|
 | 27 |  | 
|---|
 | 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)) | 
|---|
 | 43 |  | 
|---|
 | 44 |             line = "\t'"+opt+"':"+str(data)+",\t# "+result | 
|---|
 | 45 |             print line | 
|---|
 | 46 |         print "\t'end':'true'}" | 
|---|
 | 47 |  | 
|---|
 | 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] | 
|---|
 | 54 |             result = "" | 
|---|
 | 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 | 
|---|
 | 66 |             print line | 
|---|
 | 67 |         print "\t'end':'true'}" | 
|---|
 | 68 |          | 
|---|
 | 69 |  | 
|---|
 | 70 |              | 
|---|
 | 71 |     # FIXME: This is called from IsDhcpSomethingPacket, but is this really | 
|---|
 | 72 |     # needed?  Or maybe this testing should be done in | 
|---|
 | 73 |     # DhcpBasicPacket.DecodePacket(). | 
|---|
 | 74 |  | 
|---|
 | 75 |     # Test Packet Type | 
|---|
 | 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 | 
|---|
 | 80 |         return True | 
|---|
 | 81 |      | 
|---|
 | 82 |     def IsDhcpDiscoverPacket(self): | 
|---|
 | 83 |         return self.IsDhcpSomethingPacket([1]) | 
|---|
 | 84 |  | 
|---|
 | 85 |     def IsDhcpOfferPacket(self): | 
|---|
 | 86 |         return self.IsDhcpSomethingPacket([2]) | 
|---|
 | 87 |  | 
|---|
 | 88 |     def IsDhcpRequestPacket(self): | 
|---|
 | 89 |         return self.IsDhcpSomethingPacket([3]) | 
|---|
 | 90 |  | 
|---|
 | 91 |     def IsDhcpDeclinePacket(self): | 
|---|
 | 92 |         return self.IsDhcpSomethingPacket([4]) | 
|---|
 | 93 |  | 
|---|
 | 94 |     def IsDhcpAckPacket(self): | 
|---|
 | 95 |         return self.IsDhcpSomethingPacket([5]) | 
|---|
 | 96 |  | 
|---|
 | 97 |     def IsDhcpNackPacket(self): | 
|---|
 | 98 |         return self.IsDhcpSomethingPacket([6]) | 
|---|
 | 99 |  | 
|---|
 | 100 |     def IsDhcpReleasePacket(self): | 
|---|
 | 101 |         return self.IsDhcpSomethingPacket([7]) | 
|---|
 | 102 |  | 
|---|
 | 103 |     def IsDhcpInformPacket(self): | 
|---|
 | 104 |         return self.IsDhcpSomethingPacket([8]) | 
|---|
 | 105 |  | 
|---|
 | 106 |  | 
|---|
 | 107 |     def GetMultipleOptions(self,options=()): | 
|---|
 | 108 |         result = {} | 
|---|
 | 109 |         for each in options: | 
|---|
 | 110 |             result[each] = self.GetOption(each) | 
|---|
 | 111 |         return result | 
|---|
 | 112 |  | 
|---|
 | 113 |     def SetMultipleOptions(self,options={}): | 
|---|
 | 114 |         for each in options.keys(): | 
|---|
 | 115 |             self.SetOption(each,options[each]) | 
|---|
 | 116 |  | 
|---|
 | 117 |  | 
|---|
 | 118 |  | 
|---|
 | 119 |  | 
|---|
 | 120 |  | 
|---|
 | 121 |  | 
|---|
 | 122 |     # Creating Response Packet | 
|---|
 | 123 |  | 
|---|
 | 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() | 
|---|
 | 134 |  | 
|---|
 | 135 |     def TransformToDhcpOfferPacket(self): | 
|---|
 | 136 |         self.SetOption("dhcp_message_type",[2]) | 
|---|
 | 137 |         self.SetOption("op",[2]) | 
|---|
 | 138 |         self.SetOption("hlen",[6])  | 
|---|
 | 139 |  | 
|---|
 | 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") | 
|---|
 | 146 |  | 
|---|
 | 147 |  | 
|---|
 | 148 |  | 
|---|
 | 149 |  | 
|---|
 | 150 |  | 
|---|
 | 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() | 
|---|
 | 161 |  | 
|---|
 | 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]) | 
|---|
 | 166 |  | 
|---|
 | 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") | 
|---|
 | 172 |  | 
|---|
 | 173 |  | 
|---|
 | 174 |     """ Dhcp NACK packet creation """ | 
|---|
 | 175 |     def CreateDhcpNackPacketFrom(self,src): # src = request or inform packet | 
|---|
 | 176 |          | 
|---|
 | 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() | 
|---|
 | 183 |  | 
|---|
 | 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]) | 
|---|
 | 199 |  | 
|---|
 | 200 |  | 
|---|
 | 201 |  | 
|---|
 | 202 |  | 
|---|
 | 203 |  | 
|---|
 | 204 |  | 
|---|
 | 205 |  | 
|---|
 | 206 |     """ GetClientIdentifier """ | 
|---|
 | 207 |  | 
|---|
 | 208 |     def GetClientIdentifier(self) : | 
|---|
 | 209 |         if self.IsOption("client_identifier") : | 
|---|
 | 210 |             return self.GetOption("client_identifier") | 
|---|
 | 211 |         return [] | 
|---|
 | 212 |  | 
|---|
 | 213 |     def GetGiaddr(self) : | 
|---|
 | 214 |         return self.GetOption("giaddr") | 
|---|
 | 215 |  | 
|---|
 | 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] | 
|---|
 | 220 |         return full_hw | 
|---|
 | 221 |  | 
|---|