Package killerbee :: Module zigbeedecode
[hide private]
[frames] | no frames]

Source Code for Module killerbee.zigbeedecode

  1  import struct 
  2   
  3  #  ZigBee NWK FCF fields 
  4  ZBEE_NWK_FCF_FRAME_TYPE     = 0x0003 #: ZigBee NWK Frame Control Frame Type 
  5  ZBEE_NWK_FCF_VERSION        = 0x003C #: ZigBee NWK Frame Control Version 
  6  ZBEE_NWK_FCF_DISCOVER_ROUTE = 0x00C0 #: ZigBee NWK Frame Control Route Topology Discovery Flag 
  7  ZBEE_NWK_FCF_MULTICAST      = 0x0100 #: ZigBee NWK Frame Control Multicast Flag, ZigBee 2006 and Later 
  8  ZBEE_NWK_FCF_SECURITY       = 0x0200 #: ZigBee NWK Frame Control Security Bit 
  9  ZBEE_NWK_FCF_SOURCE_ROUTE   = 0x0400 #: ZigBee NWK Frame Control Source Route Bit, ZigBee 2006 and Later 
 10  ZBEE_NWK_FCF_EXT_DEST       = 0x0800 #: ZigBee NWK Frame Control Extended Destination Addressing, ZigBee 2006 and Later 
 11  ZBEE_NWK_FCF_EXT_SOURCE     = 0x1000 #: ZigBee NWK Frame Control Extended Source Addressing, ZigBee 2006 and Later 
 12   
 13  #  ZigBee NWK FCF Frame Types 
 14  ZBEE_NWK_FCF_DATA           = 0x0000 #: ZigBee NWK Frame Control Field Frame Type: Data 
 15  ZBEE_NWK_FCF_CMD            = 0x0001 #: ZigBee NWK Frame Control Field Frame Type: Command 
 16   
 17  # ZigBee APS FCF Fields 
 18  ZBEE_APS_FCF_FRAME_TYPE     = 0x03 #: ZigBee APS Frame Control Frame Type 
 19  ZBEE_APS_FCF_DELIVERY_MODE  = 0x0c #: ZigBee APS Frame Control Delivery Mode 
 20  ZBEE_APS_FCF_INDIRECT_MODE  = 0x10 #: ZigBee APS Frame Control Indirect Delivery Mode Flag, ZigBee 2004 and earlier. 
 21  ZBEE_APS_FCF_ACK_MODE       = 0x10 #: ZigBee APS Frame Control ACK Mode, ZigBee 2007 and later. 
 22  ZBEE_APS_FCF_SECURITY       = 0x20 #: ZigBee APS Frame Control Security Bit 
 23  ZBEE_APS_FCF_ACK_REQ        = 0x40 #: ZigBee APS Frame Control ACK Required Bit 
 24  ZBEE_APS_FCF_EXT_HEADER     = 0x80 #: ZigBee APS Frame Control Extended Header Bit 
 25   
 26  ZBEE_APS_FCF_DATA           = 0x00 #: ZigBee APS Frame Control Field Frame Type: Data 
 27  ZBEE_APS_FCF_CMD            = 0x01 #: ZigBee APS Frame Control Field Frame Type: Command 
 28  ZBEE_APS_FCF_ACK            = 0x02 #: ZigBee APS Frame Control Field Frame Type: ACK 
 29   
 30  ZBEE_APS_FCF_UNICAST        = 0x00 #: ZigBee APS Frame Control Field Delivery Mode: Unicast Delivery 
 31  ZBEE_APS_FCF_INDIRECT       = 0x01 #: ZigBee APS Frame Control Field Delivery Mode: Indirect Delivery 
 32  ZBEE_APS_FCF_BCAST          = 0x02 #: ZigBee APS Frame Control Field Delivery Mode: Broadcast Delivery 
 33  ZBEE_APS_FCF_GROUP          = 0x03 #: ZigBee APS Frame Control Field Delivery Mode: Group Delivery, ZigBee 2006 and later.  
 34   
 35   
36 -class ZigBeeNWKPacketParser:
37 - def __init__(self):
38 ''' 39 Instantiates the ZigBeeNWKPacketParser class. 40 ''' 41 42 return
43
44 - def pktchop(self, packet):
45 ''' 46 Chops up the specified packet contents into a list of fields. Does 47 not attempt to re-order the field values for parsing. ''.join(X) will 48 reassemble original packet string. Fields which may or may not be 49 present (such as the destination address) are empty if they are not 50 present, keeping the list elements consistent, as follows: 51 Frame Control | DA | SA | Radius | Seq # | Dst IEEE Address | Src IEEE Address | MCast Ctrl | Src Route Subframe | Payload 52 53 An exception is raised if the packet contents are too short to 54 decode. 55 56 @type packet: String 57 @param packet: Packet contents. 58 @rtype: list 59 @return: Chopped contents of the ZigBee NWK packet into list elements. 60 ''' 61 if len(packet) < 8: 62 raise Exception("Packet too small, %d bytes." % len(packet)) 63 64 # Frame control field 65 fc = struct.unpack("<H",packet[0:2])[0] 66 67 # FC | DA | SA | Radius | Seq # 68 pktchop = [packet[0:2], packet[2:4], packet[4:6], packet[6], packet[7]] 69 offset = 8 70 71 # Check if the DA bit is set in the frame control field 72 if (fc & ZBEE_NWK_FCF_EXT_DEST) != 0: 73 pktchop.append(packet[offset:offset+8]) 74 offset+=8 75 else: 76 pktchop.append("") 77 78 # Check if the SA bit is set in the frame control field 79 if (fc &fc & ZBEE_NWK_FCF_EXT_SOURCE) != 0: 80 pktchop.append(packet[offset:offset+8]) 81 offset+=8 82 else: 83 pktchop.append("") 84 85 # Check if the Multicast Control bit is set in the frame control field 86 if (fc & ZBEE_NWK_FCF_MULTICAST) != 0: 87 pktchop.append(packet[offset]) 88 offset+=1 89 else: 90 pktchop.append("") 91 92 # Check if the Source Route bit is set in the frame control field 93 if (fc & ZBEE_NWK_FCF_SOURCE_ROUTE) != 0: 94 # Source Route Subfield has a format Count | Index | List 95 # where Count and Index are 1-byte each, and list is a list of 96 # addresses for source routing count*2 long. 97 relaycount = packet[offset] 98 relayindex = packet[offset+1] 99 relaylist = packet[offset+2:(relaycount*2)] 100 sourceroutesubframe = packet[relaycount + relayindex + relaylist] 101 pktchop.append(sourceroutesubframe) 102 offset+=len(sourceroutesubframe) 103 else: 104 pktchop.append("") 105 106 # Append remaining payload 107 pktchop.append(packet[offset:]) 108 109 return pktchop
110
111 - def hdrlen(self, packet):
112 ''' 113 Returns the length of the ZigBee NWK header. 114 @type packet: String 115 @param packet: Packet contents to evaluate for header length. 116 @rtype: Int 117 @return: Length of the ZigBEE NWK header. 118 ''' 119 # Frame control field 120 fc = struct.unpack("<H",packet[0:2])[0] 121 plen = 8 122 123 # Check if the DA bit is set in the frame control field 124 if (fc & ZBEE_NWK_FCF_EXT_DEST) != 0: 125 plen+=8 126 127 # Check if the SA bit is set in the frame control field 128 if (fc & ZBEE_NWK_FCF_EXT_SOURCE) != 0: 129 plen+=8 130 131 # Check if the Source Route bit is set in the frame control field 132 if (fc & ZBEE_NWK_FCF_SOURCE_ROUTE) != 0: 133 # relay list based on relay count * 2 134 plen+= (ord(packet[plen])*2) 135 # relay count and relay index fields 136 plen+=2 137 138 return plen
139
140 - def payloadlen(self, packet):
141 ''' 142 Returns the length of the NWK payload. 143 @type packet: String 144 @param packet: Packet contents to evaluate for header length. 145 @rtype: Int 146 @return: Length of the NWK payload. 147 ''' 148 return len(packet) - self.hdrlen(packet)
149 150 151
152 -class ZigBeeAPSPacketParser:
153 - def __init__(self):
154 ''' 155 Instantiates the ZigBeeAPSPacketParser class. 156 ''' 157 158 return
159
160 - def pktchop(self, packet):
161 ''' 162 Chops up the specified packet contents into a list of fields. Does 163 not attempt to re-order the field values for parsing. ''.join(X) will 164 reassemble original packet string. Fields which may or may not be 165 present (such as the destination endpoint) are empty if they are not 166 present, keeping the list elements consistent, as follows: 167 Frame Control | Dst Endpoint | Group Address | Cluster Identifier | Profile Identifier | Source Endpoint | APS Counter | Payload 168 169 An exception is raised if the packet contents are too short to 170 decode. 171 172 @type packet: String 173 @param packet: Packet contents. 174 @rtype: list 175 @return: Chopped contents of the ZigBee APS packet into list elements. 176 ''' 177 if len(packet) < 3: 178 raise Exception("Packet too small, %d bytes." % len(packet)) 179 180 # Frame control field 181 fc = packet[0] 182 pktchop = [fc,] 183 offset = 1 184 185 # Identify the APS frame type 186 apsftype = ord(fc) & ZBEE_APS_FCF_FRAME_TYPE 187 apsdeliverymode = (ord(fc) & ZBEE_APS_FCF_DELIVERY_MODE >> 2) 188 189 if apsftype == ZBEE_APS_FCF_DATA: 190 # APS Data frames are FC | Dst Endpoint | Group Address | Cluster ID | Src Endpoint | APS Counter 191 192 # Get Delivery Mode value 193 if apsdeliverymode == 0: # Normal Unicast Delivery 194 pktchop.append(packet[offset]) # Dst Endpoint 195 pktchop.append("") # Group Address (not present in this mode) 196 pktchop.append(packet[offset+1:offset+3]) # Cluster ID 197 pktchop.append(packet[offset+3:offset+5]) # Profile ID 198 pktchop.append(packet[offset+5]) # Source Endpoint 199 offset += 6 200 elif apsdeliverymode == 1: # Indirect Delivery 201 pktchop.append("") # Dst Endpoint (not present) 202 pktchop.append("") # Group Address (not present) 203 pktchop.append(packet[offset:offset+2]) # Cluster ID 204 pktchop.append(packet[offset+2:offset+4]) # Profile ID 205 pktchop.append(packet[offset+4]) # Source Endpoint 206 offset += 5 207 elif apsdeliverymode == 2: # Broadcast Delivery 208 pktchop.append(packet[offset]) # Dst Endpoint 209 pktchop.append("") # Group Address (not present) 210 pktchop.append(packet[offset+1:offset+3]) # Cluster ID 211 pktchop.append(packet[offset+3:offset+5]) # Profile ID 212 pktchop.append(packet[offset+5]) # Source Endpoint 213 offset += 6 214 else: # Group Delivery 215 pktchop.append("") # Dst Endpoint 216 pktchop.append(packet[offset:offset+2]) # Group Address (not present) 217 pktchop.append(packet[offset+2:offset+4]) # Cluster ID 218 pktchop.append(packet[offset+4:offset+6]) # Profile ID 219 pktchop.append(packet[offset+6]) # Source Endpoint 220 offset += 7 221 222 elif apsftype == ZBEE_APS_FCF_CMD: 223 # APS Command frames are FC | Group Address | APS Counter 224 pktchop.append("") # Dst Endpoint (not present) 225 226 # Get Delivery Mode value 227 if apsdeliverymode == 2: # Group Delivery 228 pktchop.append(packet[offset:offset+2]) # Group Address 229 offset += 2 230 else: 231 pktchop.append("") # Group Address (not present) 232 233 pktchop.append("") # Cluster ID (not present) 234 pktchop.append("") # Source Endpoint (not present) 235 236 elif apsftype == ZBEE_APS_FCF_ACK: 237 if apsdeliverymode == 0: # Normal Unicast Delivery 238 pktchop.append(packet[offset]) # Dst Endpoint 239 pktchop.append("") # Group Address (not present in this mode) 240 pktchop.append(packet[offset+1:offset+3]) # Cluster ID 241 pktchop.append(packet[offset+3:offset+5]) # Profile ID 242 pktchop.append(packet[offset+5]) # Source Endpoint 243 offset += 6 244 elif apsdeliverymode == 1: # Indirect Delivery 245 pktchop.append(packet[offset]) # Dst Endpoint 246 pktchop.append("") # Group Address (not present) 247 pktchop.append(packet[offset+1:offset+3]) # Cluster ID 248 pktchop.append(packet[offset+3:offset+5]) # Profile ID 249 pktchop.append(packet[offset+5]) # Source Endpoint 250 offset += 6 251 elif apsdeliverymode == 2: # Broadcast Delivery 252 pktchop.append(packet[offset]) # Dst Endpoint 253 pktchop.append("") # Group Address (not present) 254 pktchop.append(packet[offset+1:offset+3]) # Cluster ID 255 pktchop.append(packet[offset+3:offset+5]) # Profile ID 256 pktchop.append(packet[offset+5]) # Source Endpoint 257 offset += 6 258 else: # Group Delivery 259 pktchop.append(packet[offset]) # Dst Endpoint 260 pktchop.append(packet[offset:offset+3]) # Group Address (not present) 261 pktchop.append(packet[offset+3:offset+5]) # Cluster ID 262 pktchop.append(packet[offset+5:offset+7]) # Profile ID 263 pktchop.append(packet[offset+7]) # Source Endpoint 264 offset += 8 265 266 # APS Counter 267 pktchop.append(packet[offset]) 268 offset+= 1 269 270 # Payload 271 pktchop.append(packet[offset:]) 272 return pktchop
273
274 - def hdrlen(self, packet):
275 ''' 276 Returns the length of the ZigBee NWK header. 277 @type packet: String 278 @param packet: Packet contents to evaluate for header length. 279 @rtype: Int 280 @return: Length of the ZigBEE NWK header. 281 ''' 282 # Frame control field 283 fc = packet[0] 284 pktchop = [fc,] 285 plen = 1 286 287 # Identify the APS frame type 288 apsftype = ord(fc) & ZBEE_APS_FCF_FRAME_TYPE 289 apsdeliverymode = (ord(fc) & ZBEE_APS_FCF_DELIVERY_MODE >> 2) 290 291 if apsftype == ZBEE_APS_FCF_DATA: 292 if apsdeliverymode == 0 or apsdeliverymode == 2: 293 plen += 6 294 elif apsdeliverymode == 1: 295 plen += 5 296 else: 297 plen += 7 298 299 elif apsftype == ZBEE_APS_FCF_CMD: 300 if apsdeliverymode == 2: 301 plen += 2 302 303 elif apsftype == ZBEE_APS_FCF_ACK: 304 if apsdeliverymode == 3: 305 plen += 8 306 else: 307 plen += 6 308 309 plen += 1 # APS Counter 310 311 return plen
312
313 - def payloadlen(self, packet):
314 ''' 315 Returns the length of the APS payload. 316 @type packet: String 317 @param packet: Packet contents to evaluate for header length. 318 @rtype: Int 319 @return: Length of the APS payload. 320 ''' 321 return len(packet) - self.hdrlen(packet)
322