1 import struct
2
3
4 ZBEE_NWK_FCF_FRAME_TYPE = 0x0003
5 ZBEE_NWK_FCF_VERSION = 0x003C
6 ZBEE_NWK_FCF_DISCOVER_ROUTE = 0x00C0
7 ZBEE_NWK_FCF_MULTICAST = 0x0100
8 ZBEE_NWK_FCF_SECURITY = 0x0200
9 ZBEE_NWK_FCF_SOURCE_ROUTE = 0x0400
10 ZBEE_NWK_FCF_EXT_DEST = 0x0800
11 ZBEE_NWK_FCF_EXT_SOURCE = 0x1000
12
13
14 ZBEE_NWK_FCF_DATA = 0x0000
15 ZBEE_NWK_FCF_CMD = 0x0001
16
17
18 ZBEE_APS_FCF_FRAME_TYPE = 0x03
19 ZBEE_APS_FCF_DELIVERY_MODE = 0x0c
20 ZBEE_APS_FCF_INDIRECT_MODE = 0x10
21 ZBEE_APS_FCF_ACK_MODE = 0x10
22 ZBEE_APS_FCF_SECURITY = 0x20
23 ZBEE_APS_FCF_ACK_REQ = 0x40
24 ZBEE_APS_FCF_EXT_HEADER = 0x80
25
26 ZBEE_APS_FCF_DATA = 0x00
27 ZBEE_APS_FCF_CMD = 0x01
28 ZBEE_APS_FCF_ACK = 0x02
29
30 ZBEE_APS_FCF_UNICAST = 0x00
31 ZBEE_APS_FCF_INDIRECT = 0x01
32 ZBEE_APS_FCF_BCAST = 0x02
33 ZBEE_APS_FCF_GROUP = 0x03
34
35
38 '''
39 Instantiates the ZigBeeNWKPacketParser class.
40 '''
41
42 return
43
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
65 fc = struct.unpack("<H",packet[0:2])[0]
66
67
68 pktchop = [packet[0:2], packet[2:4], packet[4:6], packet[6], packet[7]]
69 offset = 8
70
71
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
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
86 if (fc & ZBEE_NWK_FCF_MULTICAST) != 0:
87 pktchop.append(packet[offset])
88 offset+=1
89 else:
90 pktchop.append("")
91
92
93 if (fc & ZBEE_NWK_FCF_SOURCE_ROUTE) != 0:
94
95
96
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
107 pktchop.append(packet[offset:])
108
109 return pktchop
110
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
120 fc = struct.unpack("<H",packet[0:2])[0]
121 plen = 8
122
123
124 if (fc & ZBEE_NWK_FCF_EXT_DEST) != 0:
125 plen+=8
126
127
128 if (fc & ZBEE_NWK_FCF_EXT_SOURCE) != 0:
129 plen+=8
130
131
132 if (fc & ZBEE_NWK_FCF_SOURCE_ROUTE) != 0:
133
134 plen+= (ord(packet[plen])*2)
135
136 plen+=2
137
138 return plen
139
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
154 '''
155 Instantiates the ZigBeeAPSPacketParser class.
156 '''
157
158 return
159
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
181 fc = packet[0]
182 pktchop = [fc,]
183 offset = 1
184
185
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
191
192
193 if apsdeliverymode == 0:
194 pktchop.append(packet[offset])
195 pktchop.append("")
196 pktchop.append(packet[offset+1:offset+3])
197 pktchop.append(packet[offset+3:offset+5])
198 pktchop.append(packet[offset+5])
199 offset += 6
200 elif apsdeliverymode == 1:
201 pktchop.append("")
202 pktchop.append("")
203 pktchop.append(packet[offset:offset+2])
204 pktchop.append(packet[offset+2:offset+4])
205 pktchop.append(packet[offset+4])
206 offset += 5
207 elif apsdeliverymode == 2:
208 pktchop.append(packet[offset])
209 pktchop.append("")
210 pktchop.append(packet[offset+1:offset+3])
211 pktchop.append(packet[offset+3:offset+5])
212 pktchop.append(packet[offset+5])
213 offset += 6
214 else:
215 pktchop.append("")
216 pktchop.append(packet[offset:offset+2])
217 pktchop.append(packet[offset+2:offset+4])
218 pktchop.append(packet[offset+4:offset+6])
219 pktchop.append(packet[offset+6])
220 offset += 7
221
222 elif apsftype == ZBEE_APS_FCF_CMD:
223
224 pktchop.append("")
225
226
227 if apsdeliverymode == 2:
228 pktchop.append(packet[offset:offset+2])
229 offset += 2
230 else:
231 pktchop.append("")
232
233 pktchop.append("")
234 pktchop.append("")
235
236 elif apsftype == ZBEE_APS_FCF_ACK:
237 if apsdeliverymode == 0:
238 pktchop.append(packet[offset])
239 pktchop.append("")
240 pktchop.append(packet[offset+1:offset+3])
241 pktchop.append(packet[offset+3:offset+5])
242 pktchop.append(packet[offset+5])
243 offset += 6
244 elif apsdeliverymode == 1:
245 pktchop.append(packet[offset])
246 pktchop.append("")
247 pktchop.append(packet[offset+1:offset+3])
248 pktchop.append(packet[offset+3:offset+5])
249 pktchop.append(packet[offset+5])
250 offset += 6
251 elif apsdeliverymode == 2:
252 pktchop.append(packet[offset])
253 pktchop.append("")
254 pktchop.append(packet[offset+1:offset+3])
255 pktchop.append(packet[offset+3:offset+5])
256 pktchop.append(packet[offset+5])
257 offset += 6
258 else:
259 pktchop.append(packet[offset])
260 pktchop.append(packet[offset:offset+3])
261 pktchop.append(packet[offset+3:offset+5])
262 pktchop.append(packet[offset+5:offset+7])
263 pktchop.append(packet[offset+7])
264 offset += 8
265
266
267 pktchop.append(packet[offset])
268 offset+= 1
269
270
271 pktchop.append(packet[offset:])
272 return pktchop
273
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
283 fc = packet[0]
284 pktchop = [fc,]
285 plen = 1
286
287
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
310
311 return plen
312
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