1# Copyright (c) 2003-2016 CORE Security Technologies
2#
3# This software is provided under under a slightly modified version
4# of the Apache Software License. See the accompanying LICENSE file
5# for more information.
6#
7# Description:
8#  IEEE 802.11 Network packet codecs.
9#
10# Author:
11#  Gustavo Moreira
12
13import struct
14import string
15from binascii import crc32
16
17from ImpactPacket import ProtocolPacket
18from Dot11Crypto import RC4
19
20frequency = {
21    2412: 1,    2417: 2,    2422: 3,    2427: 4,    2432: 5,    2437: 6,    2442: 7,    2447: 8,    2452: 9,
22    2457: 10,   2462: 11,   2467: 12,   2472: 13,   2484: 14,   5170: 34,   5180: 36,   5190: 38,   5200: 40,
23    5210: 42,   5220: 44,   5230: 46,   5240: 48,   5260: 52,   5280: 56,   5300: 60,   5320: 64,   5500: 100,
24    5510: 102,  5520: 104,  5530: 106,  5540: 108,  5550: 110,  5560: 112,  5570: 114,  5580: 116,  5590: 118,
25    5600: 120,  5610: 122,  5620: 124,  5630: 126,  5640: 128,  5650: 130,  5660: 132,  5670: 134,  5680: 136,
26    5690: 138,  5700: 140,  5745: 149,  5765: 153,  5785: 157,  5805: 161,  5825: 165,  5855: 170,  5860: 172,
27    5865: 173,  5870: 174,  5875: 175,  5880: 176,  5885: 177,  5890: 178,  5895: 179,  5900: 180,  5905: 181,
28    5910: 182,  5915: 183,  5920: 184,
29}
30
31
32class Dot11ManagementCapabilities():
33    #
34    # Capability Information
35    #   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
36    # +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
37    # | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
38    # +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
39    #   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
40    #   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |---+-- Reserved
41    #   |   |   |   |   |   |   |   |   |   |   |   |   |   |
42    #   |   |   |   |   |   |   |   |   |   |   |   |   |   |---------- DSSS-OFDM
43    #   |   |   |   |   |   |   |   |   |   |   |   |   |
44    #   |   |   |   |   |   |   |   |   |   |   |   |---+-------------- Reserved
45    #   |   |   |   |   |   |   |   |   |   |   |
46    #   |   |   |   |   |   |   |   |   |   |   |---------------------- Short slot time
47    #   |   |   |   |   |   |   |   |   |   |
48    #   |   |   |   |   |   |   |   |   |---+-------------------------- Reserved
49    #   |   |   |   |   |   |   |   |
50    #   |   |   |   |   |   |   |   |---------------------------------- Channel agility (802.11b)
51    #   |   |   |   |   |   |   |
52    #   |   |   |   |   |   |   |-------------------------------------- PBCC (802.11b)
53    #   |   |   |   |   |   |
54    #   |   |   |   |   |   |------------------------------------------ Short preamble (802.11b)
55    #   |   |   |   |   |
56    #   |   |   |   |   |---------------------------------------------- Privacy
57    #   |   |   |   |
58    #   |   |   |   |-------------------------------------------------- CF-Poll request
59    #   |   |   |
60    #   |   |   |------------------------------------------------------ CF-Pollable
61    #   |   |
62    #   |   |---------------------------------------------------------- IBSS
63    #   |
64    #   |-------------------------------------------------------------- ESS
65    #
66    CAPABILITY_RESERVED_1      = int("1000000000000000", 2)
67    CAPABILITY_RESERVED_2      = int("0100000000000000", 2)
68    CAPABILITY_DSSS_OFDM       = int("0010000000000000", 2)
69    CAPABILITY_RESERVED_3      = int("0001000000000000", 2)
70    CAPABILITY_RESERVED_4      = int("0000100000000000", 2)
71    CAPABILITY_SHORT_SLOT_TIME = int("0000010000000000", 2)
72    CAPABILITY_RESERVED_5      = int("0000001000000000", 2)
73    CAPABILITY_RESERVED_6      = int("0000000100000000", 2)
74    CAPABILITY_CH_AGILITY      = int("0000000010000000", 2)
75    CAPABILITY_PBCC            = int("0000000001000000", 2)
76    CAPABILITY_SHORT_PREAMBLE  = int("0000000000100000", 2)
77    CAPABILITY_PRIVACY         = int("0000000000010000", 2)
78    CAPABILITY_CF_POLL_REQ     = int("0000000000001000", 2)
79    CAPABILITY_CF_POLLABLE     = int("0000000000000100", 2)
80    CAPABILITY_IBSS            = int("0000000000000010", 2)
81    CAPABILITY_ESS             = int("0000000000000001", 2)
82
83class Dot11Types():
84    # Management Types/SubTypes
85    DOT11_TYPE_MANAGEMENT                           = int("00",2)
86    DOT11_SUBTYPE_MANAGEMENT_ASSOCIATION_REQUEST    = int("0000",2)
87    DOT11_SUBTYPE_MANAGEMENT_ASSOCIATION_RESPONSE   = int("0001",2)
88    DOT11_SUBTYPE_MANAGEMENT_REASSOCIATION_REQUEST  = int("0010",2)
89    DOT11_SUBTYPE_MANAGEMENT_REASSOCIATION_RESPONSE = int("0011",2)
90    DOT11_SUBTYPE_MANAGEMENT_PROBE_REQUEST          = int("0100",2)
91    DOT11_SUBTYPE_MANAGEMENT_PROBE_RESPONSE         = int("0101",2)
92    DOT11_SUBTYPE_MANAGEMENT_RESERVED1              = int("0110",2)
93    DOT11_SUBTYPE_MANAGEMENT_RESERVED2              = int("0111",2)
94    DOT11_SUBTYPE_MANAGEMENT_BEACON                 = int("1000",2)
95    DOT11_SUBTYPE_MANAGEMENT_ATIM                   = int("1001",2)
96    DOT11_SUBTYPE_MANAGEMENT_DISASSOCIATION         = int("1010",2)
97    DOT11_SUBTYPE_MANAGEMENT_AUTHENTICATION         = int("1011",2)
98    DOT11_SUBTYPE_MANAGEMENT_DEAUTHENTICATION       = int("1100",2)
99    DOT11_SUBTYPE_MANAGEMENT_ACTION                 = int("1101",2)
100    DOT11_SUBTYPE_MANAGEMENT_RESERVED3              = int("1110",2)
101    DOT11_SUBTYPE_MANAGEMENT_RESERVED4              = int("1111",2)
102
103    DOT11_TYPE_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST = \
104        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_ASSOCIATION_REQUEST<<2
105    DOT11_TYPE_MANAGEMENT_SUBTYPE_ASSOCIATION_RESPONSE = \
106        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_ASSOCIATION_RESPONSE<<2
107    DOT11_TYPE_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST = \
108        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_REASSOCIATION_REQUEST<<2
109    DOT11_TYPE_MANAGEMENT_SUBTYPE_REASSOCIATION_RESPONSE = \
110        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_REASSOCIATION_RESPONSE<<2
111    DOT11_TYPE_MANAGEMENT_SUBTYPE_PROBE_REQUEST = \
112        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_PROBE_REQUEST<<2
113    DOT11_TYPE_MANAGEMENT_SUBTYPE_PROBE_RESPONSE = \
114        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_PROBE_RESPONSE<<2
115    DOT11_TYPE_MANAGEMENT_SUBTYPE_RESERVED1 = \
116        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_RESERVED1<<2
117    DOT11_TYPE_MANAGEMENT_SUBTYPE_RESERVED2 = \
118        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_RESERVED2<<2
119    DOT11_TYPE_MANAGEMENT_SUBTYPE_BEACON = \
120        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_BEACON<<2
121    DOT11_TYPE_MANAGEMENT_SUBTYPE_ATIM = \
122        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_ATIM<<2
123    DOT11_TYPE_MANAGEMENT_SUBTYPE_DISASSOCIATION = \
124        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_DISASSOCIATION<<2
125    DOT11_TYPE_MANAGEMENT_SUBTYPE_AUTHENTICATION = \
126        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_AUTHENTICATION<<2
127    DOT11_TYPE_MANAGEMENT_SUBTYPE_DEAUTHENTICATION = \
128        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_DEAUTHENTICATION<<2
129    DOT11_TYPE_MANAGEMENT_SUBTYPE_ACTION = \
130        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_ACTION<<2
131    DOT11_TYPE_MANAGEMENT_SUBTYPE_RESERVED3 = \
132        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_RESERVED3<<2
133    DOT11_TYPE_MANAGEMENT_SUBTYPE_RESERVED4 = \
134        DOT11_TYPE_MANAGEMENT|DOT11_SUBTYPE_MANAGEMENT_RESERVED4<<2
135
136    # Control Types/SubTypes
137    DOT11_TYPE_CONTROL                              = int("01",2)
138    DOT11_SUBTYPE_CONTROL_RESERVED1                 = int("0000",2)
139    DOT11_SUBTYPE_CONTROL_RESERVED2                 = int("0001",2)
140    DOT11_SUBTYPE_CONTROL_RESERVED3                 = int("0010",2)
141    DOT11_SUBTYPE_CONTROL_RESERVED4                 = int("0011",2)
142    DOT11_SUBTYPE_CONTROL_RESERVED5                 = int("0100",2)
143    DOT11_SUBTYPE_CONTROL_RESERVED6                 = int("0101",2)
144    DOT11_SUBTYPE_CONTROL_RESERVED7                 = int("0110",2)
145    DOT11_SUBTYPE_CONTROL_RESERVED8                 = int("0111",2)
146    DOT11_SUBTYPE_CONTROL_BLOCK_ACK_REQUEST         = int("1000",2)
147    DOT11_SUBTYPE_CONTROL_BLOCK_ACK                 = int("1001",2)
148    DOT11_SUBTYPE_CONTROL_POWERSAVE_POLL            = int("1010",2)
149    DOT11_SUBTYPE_CONTROL_REQUEST_TO_SEND           = int("1011",2)
150    DOT11_SUBTYPE_CONTROL_CLEAR_TO_SEND             = int("1100",2)
151    DOT11_SUBTYPE_CONTROL_ACKNOWLEDGMENT            = int("1101",2)
152    DOT11_SUBTYPE_CONTROL_CF_END                    = int("1110",2)
153    DOT11_SUBTYPE_CONTROL_CF_END_CF_ACK             = int("1111",2)
154
155    DOT11_TYPE_CONTROL_SUBTYPE_RESERVED1 = \
156        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_RESERVED1<<2
157    DOT11_TYPE_CONTROL_SUBTYPE_RESERVED2 = \
158        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_RESERVED2<<2
159    DOT11_TYPE_CONTROL_SUBTYPE_RESERVED3 = \
160        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_RESERVED3<<2
161    DOT11_TYPE_CONTROL_SUBTYPE_RESERVED4 = \
162        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_RESERVED4<<2
163    DOT11_TYPE_CONTROL_SUBTYPE_RESERVED5 = \
164        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_RESERVED5<<2
165    DOT11_TYPE_CONTROL_SUBTYPE_RESERVED6 = \
166        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_RESERVED6<<2
167    DOT11_TYPE_CONTROL_SUBTYPE_RESERVED7 = \
168        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_RESERVED7<<2
169    DOT11_TYPE_CONTROL_SUBTYPE_BLOCK_ACK_REQUEST = \
170        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_BLOCK_ACK_REQUEST<<2
171    DOT11_TYPE_CONTROL_SUBTYPE_BLOCK_ACK = \
172        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_BLOCK_ACK<<2
173    DOT11_TYPE_CONTROL_SUBTYPE_POWERSAVE_POLL = \
174        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_POWERSAVE_POLL<<2
175    DOT11_TYPE_CONTROL_SUBTYPE_REQUEST_TO_SEND = \
176        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_REQUEST_TO_SEND<<2
177    DOT11_TYPE_CONTROL_SUBTYPE_CLEAR_TO_SEND = \
178        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_CLEAR_TO_SEND<<2
179    DOT11_TYPE_CONTROL_SUBTYPE_ACKNOWLEDGMENT = \
180        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_ACKNOWLEDGMENT<<2
181    DOT11_TYPE_CONTROL_SUBTYPE_CF_END = \
182        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_CF_END<<2
183    DOT11_TYPE_CONTROL_SUBTYPE_CF_END_CF_ACK = \
184        DOT11_TYPE_CONTROL|DOT11_SUBTYPE_CONTROL_CF_END_CF_ACK<<2
185
186    # Data Types/SubTypes
187    DOT11_TYPE_DATA                                = int("10",2)
188    DOT11_SUBTYPE_DATA                             = int("0000",2)
189    DOT11_SUBTYPE_DATA_CF_ACK                      = int("0001",2)
190    DOT11_SUBTYPE_DATA_CF_POLL                     = int("0010",2)
191    DOT11_SUBTYPE_DATA_CF_ACK_CF_POLL              = int("0011",2)
192    DOT11_SUBTYPE_DATA_NULL_NO_DATA                = int("0100",2)
193    DOT11_SUBTYPE_DATA_CF_ACK_NO_DATA              = int("0101",2)
194    DOT11_SUBTYPE_DATA_CF_POLL_NO_DATA             = int("0110",2)
195    DOT11_SUBTYPE_DATA_CF_ACK_CF_POLL_NO_DATA      = int("0111",2)
196    DOT11_SUBTYPE_DATA_QOS_DATA                    = int("1000",2)
197    DOT11_SUBTYPE_DATA_QOS_DATA_CF_ACK             = int("1001",2)
198    DOT11_SUBTYPE_DATA_QOS_DATA_CF_POLL            = int("1010",2)
199    DOT11_SUBTYPE_DATA_QOS_DATA_CF_ACK_CF_POLL     = int("1011",2)
200    DOT11_SUBTYPE_DATA_QOS_NULL_NO_DATA            = int("1100",2)
201    DOT11_SUBTYPE_DATA_RESERVED1                   = int("1101",2)
202    DOT11_SUBTYPE_DATA_QOS_CF_POLL_NO_DATA         = int("1110",2)
203    DOT11_SUBTYPE_DATA_QOS_CF_ACK_CF_POLL_NO_DATA  = int("1111",2)
204
205    DOT11_TYPE_DATA_SUBTYPE_DATA = \
206        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA<<2
207    DOT11_TYPE_DATA_SUBTYPE_CF_ACK = \
208        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_CF_ACK<<2
209    DOT11_TYPE_DATA_SUBTYPE_CF_POLL = \
210        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_CF_POLL<<2
211    DOT11_TYPE_DATA_SUBTYPE_CF_ACK_CF_POLL = \
212        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_CF_ACK_CF_POLL<<2
213    DOT11_TYPE_DATA_SUBTYPE_NULL_NO_DATA = \
214        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_NULL_NO_DATA<<2
215    DOT11_TYPE_DATA_SUBTYPE_CF_ACK_NO_DATA = \
216        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_CF_POLL_NO_DATA<<2
217    DOT11_TYPE_DATA_SUBTYPE_CF_ACK_CF_POLL_NO_DATA = \
218        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_CF_ACK_CF_POLL_NO_DATA<<2
219    DOT11_TYPE_DATA_SUBTYPE_QOS_DATA = \
220        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_QOS_DATA<<2
221    DOT11_TYPE_DATA_SUBTYPE_QOS_DATA_CF_ACK = \
222        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_QOS_DATA_CF_ACK<<2
223    DOT11_TYPE_DATA_SUBTYPE_QOS_DATA_CF_POLL = \
224        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_QOS_DATA_CF_POLL<<2
225    DOT11_TYPE_DATA_SUBTYPE_QOS_DATA_CF_ACK_CF_POLL = \
226        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_QOS_DATA_CF_ACK_CF_POLL<<2
227    DOT11_TYPE_DATA_SUBTYPE_QOS_NULL_NO_DATA = \
228        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_QOS_NULL_NO_DATA<<2
229    DOT11_TYPE_DATA_SUBTYPE_RESERVED1 = \
230        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_RESERVED1<<2
231    DOT11_TYPE_DATA_SUBTYPE_QOS_CF_POLL_NO_DATA = \
232        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_QOS_CF_POLL_NO_DATA<<2
233    DOT11_TYPE_DATA_SUBTYPE_QOS_CF_ACK_CF_POLL_NO_DATA = \
234        DOT11_TYPE_DATA|DOT11_SUBTYPE_DATA_QOS_CF_ACK_CF_POLL_NO_DATA<<2
235
236    # Reserved Types/SubTypes
237    DOT11_TYPE_RESERVED = int("11",2)
238    DOT11_SUBTYPE_RESERVED_RESERVED1               = int("0000",2)
239    DOT11_SUBTYPE_RESERVED_RESERVED2               = int("0001",2)
240    DOT11_SUBTYPE_RESERVED_RESERVED3               = int("0010",2)
241    DOT11_SUBTYPE_RESERVED_RESERVED4               = int("0011",2)
242    DOT11_SUBTYPE_RESERVED_RESERVED5               = int("0100",2)
243    DOT11_SUBTYPE_RESERVED_RESERVED6               = int("0101",2)
244    DOT11_SUBTYPE_RESERVED_RESERVED7               = int("0110",2)
245    DOT11_SUBTYPE_RESERVED_RESERVED8               = int("0111",2)
246    DOT11_SUBTYPE_RESERVED_RESERVED9               = int("1000",2)
247    DOT11_SUBTYPE_RESERVED_RESERVED10              = int("1001",2)
248    DOT11_SUBTYPE_RESERVED_RESERVED11              = int("1010",2)
249    DOT11_SUBTYPE_RESERVED_RESERVED12              = int("1011",2)
250    DOT11_SUBTYPE_RESERVED_RESERVED13              = int("1100",2)
251    DOT11_SUBTYPE_RESERVED_RESERVED14              = int("1101",2)
252    DOT11_SUBTYPE_RESERVED_RESERVED15              = int("1110",2)
253    DOT11_SUBTYPE_RESERVED_RESERVED16              = int("1111",2)
254
255    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED1 = \
256        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED1<<2
257    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED2 = \
258        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED2<<2
259    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED3 = \
260        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED3<<2
261    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED4 = \
262        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED4<<2
263    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED5 = \
264        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED5<<2
265    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED6 = \
266        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED6<<2
267    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED7 = \
268        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED7<<2
269    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED8 = \
270        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED8<<2
271    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED9 = \
272        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED9<<2
273    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED10 = \
274        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED10<<2
275    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED11 = \
276        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED11<<2
277    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED12 = \
278        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED12<<2
279    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED13 = \
280        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED13<<2
281    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED14 = \
282        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED14<<2
283    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED15 = \
284        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED15<<2
285    DOT11_TYPE_RESERVED_SUBTYPE_RESERVED16 = \
286        DOT11_TYPE_RESERVED|DOT11_SUBTYPE_RESERVED_RESERVED16<<2
287
288class Dot11(ProtocolPacket):
289    def __init__(self, aBuffer = None, FCS_at_end = True):
290        header_size = 2
291        self.__FCS_at_end=not not FCS_at_end # Is Boolean
292        if self.__FCS_at_end:
293            tail_size = 4
294        else:
295            tail_size = 0
296
297        ProtocolPacket.__init__(self, header_size,tail_size)
298        if(aBuffer):
299            self.load_packet(aBuffer)
300
301    def get_order(self):
302        "Return 802.11 frame 'Order' field"
303        b = self.header.get_byte(1)
304        return ((b >> 7) & 0x01)
305
306    def set_order(self, value):
307        "Set 802.11 frame 'Order' field"
308        # clear the bits
309        mask = (~0x80) & 0xFF
310        masked = self.header.get_byte(1) & mask
311        # set the bits
312        nb = masked | ((value & 0x01) << 7)
313        self.header.set_byte(1, nb)
314
315    def get_protectedFrame(self):
316        "Return 802.11 frame 'Protected' field"
317        b = self.header.get_byte(1)
318        return ((b >> 6) & 0x01)
319
320    def set_protectedFrame(self, value):
321        "Set 802.11 frame 'Protected Frame' field"
322        # clear the bits
323        mask = (~0x40) & 0xFF
324        masked = self.header.get_byte(1) & mask
325        # set the bits
326        nb = masked | ((value & 0x01) << 6)
327        self.header.set_byte(1, nb)
328
329    def get_moreData(self):
330        "Return 802.11 frame 'More Data' field"
331        b = self.header.get_byte(1)
332        return ((b >> 5) & 0x01)
333
334    def set_moreData(self, value):
335        "Set 802.11 frame 'More Data' field"
336        # clear the bits
337        mask = (~0x20) & 0xFF
338        masked = self.header.get_byte(1) & mask
339        # set the bits
340        nb = masked | ((value & 0x01) << 5)
341        self.header.set_byte(1, nb)
342
343    def get_powerManagement(self):
344        "Return 802.11 frame 'Power Management' field"
345        b = self.header.get_byte(1)
346        return ((b >> 4) & 0x01)
347
348    def set_powerManagement(self, value):
349        "Set 802.11 frame 'Power Management' field"
350        # clear the bits
351        mask = (~0x10) & 0xFF
352        masked = self.header.get_byte(1) & mask
353        # set the bits
354        nb = masked | ((value & 0x01) << 4)
355        self.header.set_byte(1, nb)
356
357    def get_retry(self):
358        "Return 802.11 frame 'Retry' field"
359        b = self.header.get_byte(1)
360        return ((b >> 3) & 0x01)
361
362    def set_retry(self, value):
363        "Set 802.11 frame 'Retry' field"
364        # clear the bits
365        mask = (~0x08) & 0xFF
366        masked = self.header.get_byte(1) & mask
367        # set the bits
368        nb = masked | ((value & 0x01) << 3)
369        self.header.set_byte(1, nb)
370
371    def get_moreFrag(self):
372        "Return 802.11 frame 'More Fragments' field"
373        b = self.header.get_byte(1)
374        return ((b >> 2) & 0x01)
375
376    def set_moreFrag(self, value):
377        "Set 802.11 frame 'More Fragments' field"
378        # clear the bits
379        mask = (~0x04) & 0xFF
380        masked = self.header.get_byte(1) & mask
381        # set the bits
382        nb = masked | ((value & 0x01) << 2)
383        self.header.set_byte(1, nb)
384
385    def get_fromDS(self):
386        "Return 802.11 frame 'from DS' field"
387        b = self.header.get_byte(1)
388        return ((b >> 1) & 0x01)
389
390    def set_fromDS(self, value):
391        "Set 802.11 frame 'from DS' field"
392        # clear the bits
393        mask = (~0x02) & 0xFF
394        masked = self.header.get_byte(1) & mask
395        # set the bits
396        nb = masked | ((value & 0x01) << 1)
397        self.header.set_byte(1, nb)
398
399    def get_toDS(self):
400        "Return 802.11 frame 'to DS' field"
401        b = self.header.get_byte(1)
402        return (b & 0x01)
403
404    def set_toDS(self, value):
405        "Set 802.11 frame 'to DS' field"
406        # clear the bits
407        mask = (~0x01) & 0xFF
408        masked = self.header.get_byte(1) & mask
409        # set the bits
410        nb = masked | (value & 0x01)
411        self.header.set_byte(1, nb)
412
413    def get_subtype(self):
414        "Return 802.11 frame 'subtype' field"
415        b = self.header.get_byte(0)
416        return ((b >> 4) & 0x0F)
417
418    def set_subtype(self, value):
419        "Set 802.11 frame 'subtype' field"
420        # clear the bits
421        mask = (~0xF0)&0xFF
422        masked = self.header.get_byte(0) & mask
423        # set the bits
424        nb = masked | ((value << 4) & 0xF0)
425        self.header.set_byte(0, nb)
426
427    def get_type(self):
428        "Return 802.11 frame 'type' field"
429        b = self.header.get_byte(0)
430        return ((b >> 2) & 0x03)
431
432    def set_type(self, value):
433        "Set 802.11 frame 'type' field"
434        # clear the bits
435        mask = (~0x0C)&0xFF
436        masked = self.header.get_byte(0) & mask
437        # set the bits
438        nb = masked | ((value << 2) & 0x0C)
439        self.header.set_byte(0, nb)
440
441    def get_type_n_subtype(self):
442        "Return 802.11 frame 'Type and Subtype' field"
443        b = self.header.get_byte(0)
444        return ((b >> 2) & 0x3F)
445
446    def set_type_n_subtype(self, value):
447        "Set 802.11 frame 'Type and Subtype' field"
448        # clear the bits
449        mask = (~0xFC)&0xFF
450        masked = self.header.get_byte(0) & mask
451        # set the bits
452        nb = masked | ((value << 2) & 0xFC)
453        self.header.set_byte(0, nb)
454
455    def get_version(self):
456        "Return 802.11 frame control 'Protocol version' field"
457        b = self.header.get_byte(0)
458        return (b & 0x03)
459
460    def set_version(self, value):
461        "Set the 802.11 frame control 'Protocol version' field"
462        # clear the bits
463        mask = (~0x03)&0xFF
464        masked = self.header.get_byte(0) & mask
465        # set the bits
466        nb = masked | (value & 0x03)
467        self.header.set_byte(0, nb)
468
469    def compute_checksum(self,bytes):
470        crcle=crc32(bytes)&0xffffffffL
471        # ggrr this crc32 is in little endian, convert it to big endian
472        crc=struct.pack('<L', crcle)
473         # Convert to long
474        (crc_long,) = struct.unpack('!L', crc)
475        return crc_long
476
477    def is_QoS_frame(self):
478        "Return 'True' if is an QoS data frame type"
479
480        b = self.header.get_byte(0)
481        return (b & 0x80) and True
482
483    def is_no_framebody_frame(self):
484        "Return 'True' if it frame contain no Frame Body"
485
486        b = self.header.get_byte(0)
487        return (b & 0x40) and True
488
489    def is_cf_poll_frame(self):
490        "Return 'True' if it frame is a CF_POLL frame"
491
492        b = self.header.get_byte(0)
493        return (b & 0x20) and True
494
495    def is_cf_ack_frame(self):
496        "Return 'True' if it frame is a CF_ACK frame"
497
498        b = self.header.get_byte(0)
499        return (b & 0x10) and True
500
501    def get_fcs(self):
502        "Return 802.11 'FCS' field"
503
504        if not self.__FCS_at_end:
505            return None
506
507        b = self.tail.get_long(-4, ">")
508        return b
509
510    def set_fcs(self, value = None):
511        "Set the 802.11 CTS control frame 'FCS' field. If value is None, is auto_checksum"
512
513        if not self.__FCS_at_end:
514            return
515
516        # calculate the FCS
517        if value is None:
518            payload = self.get_body_as_string()
519            crc32=self.compute_checksum(payload)
520            value=crc32
521
522        # set the bits
523        nb = value & 0xFFFFFFFF
524        self.tail.set_long(-4, nb)
525
526class Dot11ControlFrameCTS(ProtocolPacket):
527    "802.11 Clear-To-Send Control Frame"
528
529    def __init__(self, aBuffer = None):
530        header_size = 8
531        tail_size = 0
532
533        ProtocolPacket.__init__(self, header_size, tail_size)
534        if(aBuffer):
535            self.load_packet(aBuffer)
536
537    def get_duration(self):
538        "Return 802.11 CTS control frame 'Duration' field"
539        b = self.header.get_word(0, "<")
540        return b
541
542    def set_duration(self, value):
543        "Set the 802.11 CTS control frame 'Duration' field"
544        # set the bits
545        nb = value & 0xFFFF
546        self.header.set_word(0, nb, "<")
547
548    def get_ra(self):
549        "Return 802.11 CTS control frame 48 bit 'Receiver Address' field as a 6 bytes array"
550        return self.header.get_bytes()[2:8]
551
552    def set_ra(self, value):
553        "Set 802.11 CTS control frame 48 bit 'Receiver Address' field as a 6 bytes array"
554        for i in range(0, 6):
555            self.header.set_byte(2+i, value[i])
556
557class Dot11ControlFrameACK(ProtocolPacket):
558    "802.11 Acknowledgement Control Frame"
559
560    def __init__(self, aBuffer = None):
561        header_size = 8
562        tail_size = 0
563
564        ProtocolPacket.__init__(self, header_size, tail_size)
565        if(aBuffer):
566            self.load_packet(aBuffer)
567
568    def get_duration(self):
569        "Return 802.11 ACK control frame 'Duration' field"
570        b = self.header.get_word(0, "<")
571        return b
572
573    def set_duration(self, value):
574        "Set the 802.11 ACK control frame 'Duration' field"
575        # set the bits
576        nb = value & 0xFFFF
577        self.header.set_word(0, nb, "<")
578
579    def get_ra(self):
580        "Return 802.11 ACK control frame 48 bit 'Receiver Address' field as a 6 bytes array"
581        return self.header.get_bytes()[2:8]
582
583    def set_ra(self, value):
584        "Set 802.11 ACK control frame 48 bit 'Receiver Address' field as a 6 bytes array"
585        for i in range(0, 6):
586            self.header.set_byte(2+i, value[i])
587
588class Dot11ControlFrameRTS(ProtocolPacket):
589    "802.11 Request-To-Send Control Frame"
590
591    def __init__(self, aBuffer = None):
592        header_size = 14
593        tail_size = 0
594
595        ProtocolPacket.__init__(self, header_size, tail_size)
596        if(aBuffer):
597            self.load_packet(aBuffer)
598
599    def get_duration(self):
600        "Return 802.11 RTS control frame 'Duration' field"
601        b = self.header.get_word(0, "<")
602        return b
603
604    def set_duration(self, value):
605        "Set the 802.11 RTS control frame 'Duration' field"
606        # set the bits
607        nb = value & 0xFFFF
608        self.header.set_word(0, nb, "<")
609
610    def get_ra(self):
611        "Return 802.11 RTS control frame 48 bit 'Receiver Address' field as a 6 bytes array"
612        return self.header.get_bytes()[2:8]
613
614    def set_ra(self, value):
615        "Set 802.11 RTS control frame 48 bit 'Receiver Address' field as a 6 bytes array"
616        for i in range(0, 6):
617            self.header.set_byte(2+i, value[i])
618
619    def get_ta(self):
620        "Return 802.11 RTS control frame 48 bit 'Transmitter Address' field as a 6 bytes array"
621        return self.header.get_bytes()[8:14]
622
623    def set_ta(self, value):
624        "Set 802.11 RTS control frame 48 bit 'Transmitter Address' field as a 6 bytes array"
625        for i in range(0, 6):
626            self.header.set_byte(8+i, value[i])
627
628class Dot11ControlFramePSPoll(ProtocolPacket):
629    "802.11 Power-Save Poll Control Frame"
630
631    def __init__(self, aBuffer = None):
632        header_size = 14
633        tail_size = 0
634
635        ProtocolPacket.__init__(self, header_size, tail_size)
636        if(aBuffer):
637            self.load_packet(aBuffer)
638
639    def get_aid(self):
640        "Return 802.11 PSPoll control frame 'AID' field"
641        # the spec says "The AID value always has its two MSBs each set to 1."
642        # TODO: Should we do check/modify it? Wireshark shows the only MSB to 0
643        b = self.header.get_word(0, "<")
644        return b
645
646    def set_aid(self, value):
647        "Set the 802.11 PSPoll control frame 'AID' field"
648        # set the bits
649        nb = value & 0xFFFF
650        # the spec says "The AID value always has its two MSBs each set to 1."
651        # TODO: Should we do check/modify it? Wireshark shows the only MSB to 0
652        self.header.set_word(0, nb, "<")
653
654    def get_bssid(self):
655        "Return 802.11 PSPoll control frame 48 bit 'BSS ID' field as a 6 bytes array"
656        return self.header.get_bytes()[2:8]
657
658    def set_bssid(self, value):
659        "Set 802.11 PSPoll control frame 48 bit 'BSS ID' field as a 6 bytes array"
660        for i in range(0, 6):
661            self.header.set_byte(2+i, value[i])
662
663    def get_ta(self):
664        "Return 802.11 PSPoll control frame 48 bit 'Transmitter Address' field as a 6 bytes array"
665        return self.header.get_bytes()[8:14]
666
667    def set_ta(self, value):
668        "Set 802.11 PSPoll control frame 48 bit 'Transmitter Address' field as a 6 bytes array"
669        for i in range(0, 6):
670            self.header.set_byte(8+i, value[i])
671
672class Dot11ControlFrameCFEnd(ProtocolPacket):
673    "802.11 'Contention Free End' Control Frame"
674
675    def __init__(self, aBuffer = None):
676        header_size = 14
677        tail_size = 0
678
679        ProtocolPacket.__init__(self, header_size, tail_size)
680        if(aBuffer):
681            self.load_packet(aBuffer)
682
683    def get_duration(self):
684        "Return 802.11 CF-End control frame 'Duration' field"
685        b = self.header.get_word(0, "<")
686        return b
687
688    def set_duration(self, value):
689        "Set the 802.11 CF-End control frame 'Duration' field"
690        # set the bits
691        nb = value & 0xFFFF
692        self.header.set_word(0, nb, "<")
693
694    def get_ra(self):
695        "Return 802.11 CF-End control frame 48 bit 'Receiver Address' field as a 6 bytes array"
696        return self.header.get_bytes()[2:8]
697
698    def set_ra(self, value):
699        "Set 802.11 CF-End control frame 48 bit 'Receiver Address' field as a 6 bytes array"
700        for i in range(0, 6):
701            self.header.set_byte(2+i, value[i])
702
703    def get_bssid(self):
704        "Return 802.11 CF-End control frame 48 bit 'BSS ID' field as a 6 bytes array"
705        return self.header.get_bytes()[8:14]
706
707    def set_bssid(self, value):
708        "Set 802.11 CF-End control frame 48 bit 'BSS ID' field as a 6 bytes array"
709        for i in range(0, 6):
710            self.header.set_byte(8+i, value[i])
711
712class Dot11ControlFrameCFEndCFACK(ProtocolPacket):
713    '802.11 \'CF-End + CF-ACK\' Control Frame'
714
715    def __init__(self, aBuffer = None):
716        header_size = 14
717        tail_size = 0
718
719        ProtocolPacket.__init__(self, header_size, tail_size)
720        if(aBuffer):
721            self.load_packet(aBuffer)
722
723    def get_duration(self):
724        'Return 802.11 \'CF-End+CF-ACK\' control frame \'Duration\' field'
725        b = self.header.get_word(0, "<")
726        return b
727
728    def set_duration(self, value):
729        'Set the 802.11 \'CF-End+CF-ACK\' control frame \'Duration\' field'
730        # set the bits
731        nb = value & 0xFFFF
732        self.header.set_word(0, nb, "<")
733
734    def get_ra(self):
735        'Return 802.11 \'CF-End+CF-ACK\' control frame 48 bit \'Receiver Address\' field as a 6 bytes array'
736        return self.header.get_bytes()[2:8]
737
738    def set_ra(self, value):
739        'Set 802.11 \'CF-End+CF-ACK\' control frame 48 bit \'Receiver Address\' field as a 6 bytes array'
740        for i in range(0, 6):
741            self.header.set_byte(2+i, value[i])
742
743    def get_bssid(self):
744        'Return 802.11 \'CF-End+CF-ACK\' control frame 48 bit \'BSS ID\' field as a 6 bytes array'
745        return self.header.get_bytes()[8:16]
746
747    def set_bssid(self, value):
748        'Set 802.11 \'CF-End+CF-ACK\' control frame 48 bit \'BSS ID\' field as a 6 bytes array'
749        for i in range(0, 6):
750            self.header.set_byte(8+i, value[i])
751
752class Dot11DataFrame(ProtocolPacket):
753    '802.11 Data Frame'
754
755    def __init__(self, aBuffer = None):
756        header_size = 22
757        tail_size = 0
758
759        ProtocolPacket.__init__(self, header_size, tail_size)
760        if(aBuffer):
761            self.load_packet(aBuffer)
762
763    def get_duration(self):
764        'Return 802.11 \'Data\' data frame \'Duration\' field'
765        b = self.header.get_word(0, "<")
766        return b
767
768    def set_duration(self, value):
769        'Set the 802.11 \'Data\' data frame \'Duration\' field'
770        # set the bits
771        nb = value & 0xFFFF
772        self.header.set_word(0, nb, "<")
773
774    def get_address1(self):
775        'Return 802.11 \'Data\' data frame 48 bit \'Address1\' field as a 6 bytes array'
776        return self.header.get_bytes()[2:8]
777
778    def set_address1(self, value):
779        'Set 802.11 \'Data\' data frame 48 bit \'Address1\' field as a 6 bytes array'
780        for i in range(0, 6):
781            self.header.set_byte(2+i, value[i])
782
783    def get_address2(self):
784        'Return 802.11 \'Data\' data frame 48 bit \'Address2\' field as a 6 bytes array'
785        return self.header.get_bytes()[8:14]
786
787    def set_address2(self, value):
788        'Set 802.11 \'Data\' data frame 48 bit \'Address2\' field as a 6 bytes array'
789        for i in range(0, 6):
790            self.header.set_byte(8+i, value[i])
791
792    def get_address3(self):
793        'Return 802.11 \'Data\' data frame 48 bit \'Address3\' field as a 6 bytes array'
794        return self.header.get_bytes()[14: 20]
795
796    def set_address3(self, value):
797        'Set 802.11 \'Data\' data frame 48 bit \'Address3\' field as a 6 bytes array'
798        for i in range(0, 6):
799            self.header.set_byte(14+i, value[i])
800
801    def get_sequence_control(self):
802        'Return 802.11 \'Data\' data frame \'Sequence Control\' field'
803        b = self.header.get_word(20, "<")
804        return b
805
806    def set_sequence_control(self, value):
807        'Set the 802.11 \'Data\' data frame \'Sequence Control\' field'
808        # set the bits
809        nb = value & 0xFFFF
810        self.header.set_word(20, nb, "<")
811
812    def get_fragment_number(self):
813        'Return 802.11 \'Data\' data frame \'Fragment Number\' subfield'
814
815        b = self.header.get_word(20, "<")
816        return (b&0x000F)
817
818    def set_fragment_number(self, value):
819        'Set the 802.11 \'Data\' data frame \'Fragment Number\' subfield'
820        # clear the bits
821        mask = (~0x000F) & 0xFFFF
822        masked = self.header.get_word(20, "<") & mask
823        # set the bits
824        nb = masked | (value & 0x000F)
825        self.header.set_word(20, nb, "<")
826
827    def get_sequence_number(self):
828        'Return 802.11 \'Data\' data frame \'Sequence Number\' subfield'
829
830        b = self.header.get_word(20, "<")
831        return ((b>>4) & 0xFFF)
832
833    def set_sequence_number(self, value):
834        'Set the 802.11 \'Data\' data frame \'Sequence Number\' subfield'
835        # clear the bits
836        mask = (~0xFFF0) & 0xFFFF
837        masked = self.header.get_word(20, "<") & mask
838        # set the bits
839        nb = masked | ((value & 0x0FFF ) << 4 )
840        self.header.set_word(20, nb, "<")
841
842    def get_frame_body(self):
843        'Return 802.11 \'Data\' data frame \'Frame Body\' field'
844
845        return self.get_body_as_string()
846
847    def set_frame_body(self, data):
848        'Set 802.11 \'Data\' data frame \'Frame Body\' field'
849
850        self.load_body(data)
851
852class Dot11DataQoSFrame(Dot11DataFrame):
853    '802.11 Data QoS Frame'
854
855    def __init__(self, aBuffer = None):
856        header_size = 24
857        tail_size = 0
858
859        ProtocolPacket.__init__(self, header_size, tail_size)
860        if(aBuffer):
861            self.load_packet(aBuffer)
862
863    def get_QoS(self):
864        'Return 802.11 \'Data\' data frame \'QoS\' field'
865        b = self.header.get_word(22, "<")
866        return b
867
868    def set_QoS(self, value):
869        'Set the 802.11 \'Data\' data frame \'QoS\' field'
870        # set the bits
871        nb = value & 0xFFFF
872        self.header.set_word(22, nb, "<")
873
874class Dot11DataAddr4Frame(Dot11DataFrame):
875    '802.11 Data With ToDS From DS Flags (With Addr 4) Frame'
876
877    def __init__(self, aBuffer = None):
878        header_size = 28
879        tail_size = 0
880
881        ProtocolPacket.__init__(self, header_size, tail_size)
882        if(aBuffer):
883            self.load_packet(aBuffer)
884
885    def get_address4(self):
886        'Return 802.11 \'Data\' data frame 48 bit \'Address4\' field as a 6 bytes array'
887        return self.header.get_bytes()[22:28]
888
889    def set_address4(self, value):
890        'Set 802.11 \'Data\' data frame 48 bit \'Address4\' field as a 6 bytes array'
891        for i in range(0, 6):
892            self.header.set_byte(22+i, value[i])
893
894class Dot11DataAddr4QoSFrame(Dot11DataAddr4Frame):
895    '802.11 Data With ToDS From DS Flags (With Addr 4) and QoS Frame'
896
897    def __init__(self, aBuffer = None):
898        header_size = 30
899        tail_size = 0
900
901        ProtocolPacket.__init__(self, header_size, tail_size)
902        if(aBuffer):
903            self.load_packet(aBuffer)
904
905    def get_QoS(self):
906        'Return 802.11 \'Data\' data frame \'QoS\' field'
907        b = self.header.get_word(28, "<")
908        return b
909
910    def set_QoS(self, value):
911        'Set the 802.11 \'Data\' data frame \'QoS\' field'
912        # set the bits
913        nb = value & 0xFFFF
914        self.header.set_word(28, nb, "<")
915
916class SAPTypes():
917    NULL            = 0x00
918    LLC_SLMGMT      = 0x02
919    SNA_PATHCTRL    = 0x04
920    IP              = 0x06
921    SNA1            = 0x08
922    SNA2            = 0x0C
923    PROWAY_NM_INIT  = 0x0E
924    NETWARE1        = 0x10
925    OSINL1          = 0x14
926    TI              = 0x18
927    OSINL2          = 0x20
928    OSINL3          = 0x34
929    SNA3            = 0x40
930    BPDU            = 0x42
931    RS511           = 0x4E
932    OSINL4          = 0x54
933    X25             = 0x7E
934    XNS             = 0x80
935    BACNET          = 0x82
936    NESTAR          = 0x86
937    PROWAY_ASLM     = 0x8E
938    ARP             = 0x98
939    SNAP            = 0xAA
940    HPJD            = 0xB4
941    VINES1          = 0xBA
942    VINES2          = 0xBC
943    NETWARE2        = 0xE0
944    NETBIOS         = 0xF0
945    IBMNM           = 0xF4
946    HPEXT           = 0xF8
947    UB              = 0xFA
948    RPL             = 0xFC
949    OSINL5          = 0xFE
950    GLOBAL          = 0xFF
951
952class LLC(ProtocolPacket):
953    '802.2 Logical Link Control (LLC) Frame'
954
955    DLC_UNNUMBERED_FRAMES = 0x03
956
957    def __init__(self, aBuffer = None):
958        header_size = 3
959        tail_size = 0
960
961        ProtocolPacket.__init__(self, header_size, tail_size)
962        if(aBuffer):
963            self.load_packet(aBuffer)
964
965    def get_DSAP(self):
966        "Get the Destination Service Access Point (SAP) from LLC frame"
967        return self.header.get_byte(0)
968
969    def set_DSAP(self, value):
970        "Set the Destination Service Access Point (SAP) of LLC frame"
971        self.header.set_byte(0, value)
972
973    def get_SSAP(self):
974        "Get the Source Service Access Point (SAP) from LLC frame"
975        return self.header.get_byte(1)
976
977    def set_SSAP(self, value):
978        "Set the Source Service Access Point (SAP) of LLC frame"
979        self.header.set_byte(1, value)
980
981    def get_control(self):
982        "Get the Control field from LLC frame"
983        return self.header.get_byte(2)
984
985    def set_control(self, value):
986        "Set the Control field of LLC frame"
987        self.header.set_byte(2, value)
988
989class SNAP(ProtocolPacket):
990    '802.2 SubNetwork Access Protocol (SNAP) Frame'
991
992    def __init__(self, aBuffer = None):
993        header_size = 5
994        tail_size = 0
995
996        ProtocolPacket.__init__(self, header_size, tail_size)
997        if(aBuffer):
998            self.load_packet(aBuffer)
999
1000    def get_OUI(self):
1001        "Get the three-octet Organizationally Unique Identifier (OUI) SNAP frame"
1002        b=self.header.get_bytes()[0:3].tostring()
1003        #unpack requires a string argument of length 4 and b is 3 bytes long
1004        (oui,)=struct.unpack('!L', '\x00'+b)
1005        return oui
1006
1007    def set_OUI(self, value):
1008        "Set the three-octet Organizationally Unique Identifier (OUI) SNAP frame"
1009        # clear the bits
1010        mask = ((~0xFFFFFF00) & 0xFF)
1011        masked = self.header.get_long(0, ">") & mask
1012        # set the bits
1013        nb = masked | ((value & 0x00FFFFFF) << 8)
1014        self.header.set_long(0, nb)
1015
1016    def get_protoID(self):
1017        "Get the two-octet Protocol Identifier (PID) SNAP field"
1018        return self.header.get_word(3, ">")
1019
1020    def set_protoID(self, value):
1021        "Set the two-octet Protocol Identifier (PID) SNAP field"
1022        self.header.set_word(3, value, ">")
1023
1024class Dot11WEP(ProtocolPacket):
1025    '802.11 WEP'
1026
1027    def __init__(self, aBuffer = None):
1028        header_size = 4
1029        tail_size = 0
1030
1031        ProtocolPacket.__init__(self, header_size, tail_size)
1032        if(aBuffer):
1033            self.load_packet(aBuffer)
1034
1035    def is_WEP(self):
1036        'Return True if it\'s a WEP'
1037        # We already know that it's private.
1038        # Now we must differentiate between WEP and WPA/WPA2
1039        # WPA/WPA2 have the ExtIV (Bit 5) enaled and WEP disabled
1040        b = self.header.get_byte(3)
1041        return not (b & 0x20)
1042
1043    def get_iv(self):
1044        'Return the \'WEP IV\' field'
1045        b=self.header.get_bytes()[0:3].tostring()
1046        #unpack requires a string argument of length 4 and b is 3 bytes long
1047        (iv,)=struct.unpack('!L', '\x00'+b)
1048        return iv
1049
1050    def set_iv(self, value):
1051        'Set the \'WEP IV\' field.'
1052        # clear the bits
1053        mask = ((~0xFFFFFF00) & 0xFF)
1054        masked = self.header.get_long(0, ">") & mask
1055        # set the bits
1056        nb = masked | ((value & 0x00FFFFFF) << 8)
1057        self.header.set_long(0, nb)
1058
1059    def get_keyid(self):
1060        'Return the \'WEP KEY ID\' field'
1061        b = self.header.get_byte(3)
1062        return ((b>>6) & 0x03)
1063
1064    def set_keyid(self, value):
1065        'Set the \'WEP KEY ID\' field'
1066        # clear the bits
1067        mask = (~0xC0) & 0xFF
1068        masked = self.header.get_byte(3) & mask
1069        # set the bits
1070        nb = masked | ((value & 0x03) << 6)
1071        self.header.set_byte(3, nb)
1072
1073    def get_decrypted_data(self, key_string):
1074        'Return \'WEP Data\' field decrypted'
1075
1076        # Needs to be at least 8 bytes of payload
1077        if len(self.body_string)<8:
1078            return self.body_string
1079
1080        # initialize the first bytes of the key from the IV
1081        # and copy rest of the WEP key (the secret part)
1082
1083        # Convert IV to 3 bytes long string
1084        iv=struct.pack('>L',self.get_iv())[-3:]
1085        key=iv+key_string
1086        rc4=RC4(key)
1087        decrypted_data=rc4.decrypt(self.body_string)
1088
1089        return decrypted_data
1090
1091    def get_encrypted_data(self, key_string):
1092        # RC4 is symmetric
1093        return self.get_decrypted_data(key_string)
1094
1095    def encrypt_frame(self, key_string):
1096        enc = self.get_encrypted_data(key_string)
1097        self.load_body(enc)
1098
1099class Dot11WEPData(ProtocolPacket):
1100    '802.11 WEP Data Part'
1101
1102    def __init__(self, aBuffer = None):
1103        header_size = 0
1104        tail_size = 4
1105
1106        ProtocolPacket.__init__(self, header_size, tail_size)
1107        if(aBuffer):
1108            self.load_packet(aBuffer)
1109
1110    def get_icv(self):
1111        "Return 'WEP ICV' field"
1112
1113        b = self.tail.get_long(-4, ">")
1114        return b
1115
1116    def set_icv(self, value = None):
1117        "Set 'WEP ICV' field"
1118
1119        # Compute the WEP ICV
1120        if value is None:
1121            value=self.get_computed_icv()
1122
1123        # set the bits
1124        nb = value & 0xFFFFFFFF
1125        self.tail.set_long(-4, nb)
1126
1127    def get_computed_icv(self):
1128        crcle=crc32(self.body_string)&0xffffffffL
1129        # This crc32 is in little endian, convert it to big endian
1130        crc=struct.pack('<L', crcle)
1131         # Convert to long
1132        (crc_long,) = struct.unpack('!L', crc)
1133        return crc_long
1134
1135    def check_icv(self):
1136        computed_icv=self.get_computed_icv()
1137        current_icv=self.get_icv()
1138        if computed_icv==current_icv:
1139            return True
1140        else:
1141            return False
1142
1143class Dot11WPA(ProtocolPacket):
1144    '802.11 WPA'
1145
1146    def __init__(self, aBuffer = None):
1147        header_size = 8
1148        tail_size = 0
1149
1150        ProtocolPacket.__init__(self, header_size, tail_size)
1151        if(aBuffer):
1152            self.load_packet(aBuffer)
1153
1154    def is_WPA(self):
1155        'Return True if it\'s a WPA'
1156        # Now we must differentiate between WPA and WPA2
1157        # In WPA WEPSeed is set to (TSC1 | 0x20) & 0x7f.
1158        b = self.get_WEPSeed() == ((self.get_TSC1() | 0x20 ) & 0x7f)
1159        return (b and self.get_extIV())
1160
1161    def get_keyid(self):
1162        'Return the \'WPA KEY ID\' field'
1163        b = self.header.get_byte(3)
1164        return ((b>>6) & 0x03)
1165
1166    def set_keyid(self, value):
1167        'Set the \'WPA KEY ID\' field'
1168        # clear the bits
1169        mask = (~0xC0) & 0xFF
1170        masked = self.header.get_byte(3) & mask
1171        # set the bits
1172        nb = masked | ((value & 0x03) << 6)
1173        self.header.set_byte(3, nb)
1174
1175    def get_decrypted_data(self):
1176        'Return \'WPA Data\' field decrypted'
1177        # TODO: Replace it with the decoded string
1178        return self.body_string
1179
1180    def get_TSC1(self):
1181        'Return the \'WPA TSC1\' field'
1182        b = self.header.get_byte(0)
1183        return (b & 0xFF)
1184
1185    def set_TSC1(self, value):
1186        'Set the \'WPA TSC1\' field'
1187        # set the bits
1188        nb = (value & 0xFF)
1189        self.header.set_byte(0, nb)
1190
1191    def get_WEPSeed(self):
1192        'Return the \'WPA WEPSeed\' field'
1193        b = self.header.get_byte(1)
1194        return (b & 0xFF)
1195
1196    def set_WEPSeed(self, value):
1197        'Set the \'WPA WEPSeed\' field'
1198        # set the bits
1199        nb = (value & 0xFF)
1200        self.header.set_byte(1, nb)
1201
1202    def get_TSC0(self):
1203        'Return the \'WPA TSC0\' field'
1204        b = self.header.get_byte(2)
1205        return (b & 0xFF)
1206
1207    def set_TSC0(self, value):
1208        'Set the \'WPA TSC0\' field'
1209        # set the bits
1210        nb = (value & 0xFF)
1211        self.header.set_byte(2, nb)
1212
1213    def get_extIV(self):
1214        'Return the \'WPA extID\' field'
1215        b = self.header.get_byte(3)
1216        return ((b>>5) & 0x1)
1217
1218    def set_extIV(self, value):
1219        'Set the \'WPA extID\' field'
1220        # clear the bits
1221        mask = (~0x20) & 0xFF
1222        masked = self.header.get_byte(3) & mask
1223        # set the bits
1224        nb = masked | ((value & 0x01) << 5)
1225        self.header.set_byte(3, nb)
1226
1227    def get_TSC2(self):
1228        'Return the \'WPA TSC2\' field'
1229        b = self.header.get_byte(4)
1230        return (b & 0xFF)
1231
1232    def set_TSC2(self, value):
1233        'Set the \'WPA TSC2\' field'
1234        # set the bits
1235        nb = (value & 0xFF)
1236        self.header.set_byte(4, nb)
1237
1238    def get_TSC3(self):
1239        'Return the \'WPA TSC3\' field'
1240        b = self.header.get_byte(5)
1241        return (b & 0xFF)
1242
1243    def set_TSC3(self, value):
1244        'Set the \'WPA TSC3\' field'
1245        # set the bits
1246        nb = (value & 0xFF)
1247        self.header.set_byte(5, nb)
1248
1249    def get_TSC4(self):
1250        'Return the \'WPA TSC4\' field'
1251        b = self.header.get_byte(6)
1252        return (b & 0xFF)
1253
1254    def set_TSC4(self, value):
1255        'Set the \'WPA TSC4\' field'
1256        # set the bits
1257        nb = (value & 0xFF)
1258        self.header.set_byte(6, nb)
1259
1260    def get_TSC5(self):
1261        'Return the \'WPA TSC5\' field'
1262        b = self.header.get_byte(7)
1263        return (b & 0xFF)
1264
1265    def set_TSC5(self, value):
1266        'Set the \'WPA TSC5\' field'
1267        # set the bits
1268        nb = (value & 0xFF)
1269        self.header.set_byte(7, nb)
1270
1271class Dot11WPAData(ProtocolPacket):
1272    '802.11 WPA Data Part'
1273
1274    def __init__(self, aBuffer = None):
1275        header_size = 0
1276        tail_size = 12
1277
1278        ProtocolPacket.__init__(self, header_size, tail_size)
1279        if(aBuffer):
1280            self.load_packet(aBuffer)
1281
1282    def get_icv(self):
1283        "Return 'WPA ICV' field"
1284
1285        b = self.tail.get_long(-4, ">")
1286        return b
1287
1288    def set_icv(self, value = None):
1289        "Set 'WPA ICV' field"
1290
1291        # calculate the FCS
1292        if value is None:
1293            value=self.compute_checksum(self.body_string)
1294
1295        # set the bits
1296        nb = value & 0xFFFFFFFF
1297        self.tail.set_long(-4, nb)
1298
1299    def get_MIC(self):
1300        'Return the \'WPA2Data MIC\' field'
1301        return self.get_tail_as_string()[:8]
1302
1303    def set_MIC(self, value):
1304        'Set the \'WPA2Data MIC\' field'
1305        #Padding to 8 bytes with 0x00's
1306        value.ljust(8,'\x00')
1307        #Stripping to 8 bytes
1308        value=value[:8]
1309        icv=self.tail.get_buffer_as_string()[-4:]
1310        self.tail.set_bytes_from_string(value+icv)
1311
1312class Dot11WPA2(ProtocolPacket):
1313    '802.11 WPA2'
1314
1315    def __init__(self, aBuffer = None):
1316        header_size = 8
1317        tail_size = 0
1318
1319        ProtocolPacket.__init__(self, header_size, tail_size)
1320        if(aBuffer):
1321            self.load_packet(aBuffer)
1322
1323    def is_WPA2(self):
1324        'Return True if it\'s a WPA2'
1325        # Now we must differentiate between WPA and WPA2
1326        # In WPA WEPSeed is set to (TSC1 | 0x20) & 0x7f.
1327        # In WPA2 WEPSeed=PN1 and TSC1=PN0
1328        b = self.get_PN1() == ((self.get_PN0() | 0x20 ) & 0x7f)
1329        return (not b and self.get_extIV())
1330
1331    def get_extIV(self):
1332        'Return the \'WPA2 extID\' field'
1333        b = self.header.get_byte(3)
1334        return ((b>>5) & 0x1)
1335
1336    def set_extIV(self, value):
1337        'Set the \'WPA2 extID\' field'
1338        # clear the bits
1339        mask = (~0x20) & 0xFF
1340        masked = self.header.get_byte(3) & mask
1341        # set the bits
1342        nb = masked | ((value & 0x01) << 5)
1343        self.header.set_byte(3, nb)
1344
1345    def get_keyid(self):
1346        'Return the \'WPA2 KEY ID\' field'
1347        b = self.header.get_byte(3)
1348        return ((b>>6) & 0x03)
1349
1350    def set_keyid(self, value):
1351        'Set the \'WPA2 KEY ID\' field'
1352        # clear the bits
1353        mask = (~0xC0) & 0xFF
1354        masked = self.header.get_byte(3) & mask
1355        # set the bits
1356        nb = masked | ((value & 0x03) << 6)
1357        self.header.set_byte(3, nb)
1358
1359    def get_decrypted_data(self):
1360        'Return \'WPA2 Data\' field decrypted'
1361        # TODO: Replace it with the decoded string
1362        return self.body_string
1363
1364    def get_PN0(self):
1365        'Return the \'WPA2 PN0\' field'
1366        b = self.header.get_byte(0)
1367        return (b & 0xFF)
1368
1369    def set_PN0(self, value):
1370        'Set the \'WPA2 PN0\' field'
1371        # set the bits
1372        nb = (value & 0xFF)
1373        self.header.set_byte(0, nb)
1374
1375    def get_PN1(self):
1376        'Return the \'WPA2 PN1\' field'
1377        b = self.header.get_byte(1)
1378        return (b & 0xFF)
1379
1380    def set_PN1(self, value):
1381        'Set the \'WPA2 PN1\' field'
1382        # set the bits
1383        nb = (value & 0xFF)
1384        self.header.set_byte(1, nb)
1385
1386    def get_PN2(self):
1387        'Return the \'WPA2 PN2\' field'
1388        b = self.header.get_byte(4)
1389        return (b & 0xFF)
1390
1391    def set_PN2(self, value):
1392        'Set the \'WPA2 PN2\' field'
1393        # set the bits
1394        nb = (value & 0xFF)
1395        self.header.set_byte(4, nb)
1396
1397    def get_PN3(self):
1398        'Return the \'WPA2 PN3\' field'
1399        b = self.header.get_byte(5)
1400        return (b & 0xFF)
1401
1402    def set_PN3(self, value):
1403        'Set the \'WPA2 PN3\' field'
1404        # set the bits
1405        nb = (value & 0xFF)
1406        self.header.set_byte(5, nb)
1407
1408    def get_PN4(self):
1409        'Return the \'WPA2 PN4\' field'
1410        b = self.header.get_byte(6)
1411        return (b & 0xFF)
1412
1413    def set_PN4(self, value):
1414        'Set the \'WPA2 PN4\' field'
1415        # set the bits
1416        nb = (value & 0xFF)
1417        self.header.set_byte(6, nb)
1418
1419    def get_PN5(self):
1420        'Return the \'WPA2 PN5\' field'
1421        b = self.header.get_byte(7)
1422        return (b & 0xFF)
1423
1424    def set_PN5(self, value):
1425        'Set the \'WPA2 PN5\' field'
1426        # set the bits
1427        nb = (value & 0xFF)
1428        self.header.set_byte(7, nb)
1429
1430class Dot11WPA2Data(ProtocolPacket):
1431    '802.11 WPA2 Data Part'
1432
1433    def __init__(self, aBuffer = None):
1434        header_size = 0
1435        tail_size = 8
1436
1437        ProtocolPacket.__init__(self, header_size, tail_size)
1438        if(aBuffer):
1439            self.load_packet(aBuffer)
1440
1441    def get_MIC(self):
1442        'Return the \'WPA2Data MIC\' field'
1443        return self.get_tail_as_string()
1444
1445    def set_MIC(self, value):
1446        'Set the \'WPA2Data MIC\' field'
1447        #Padding to 8 bytes with 0x00's
1448        value.ljust(8,'\x00')
1449        #Stripping to 8 bytes
1450        value=value[:8]
1451        self.tail.set_bytes_from_string(value)
1452
1453class RadioTap(ProtocolPacket):
1454    __HEADER_BASE_SIZE = 8  # minimal header size
1455    _PRESENT_FLAGS_SIZE = 4
1456    _BASE_PRESENT_FLAGS_OFFSET = 4
1457
1458    class __RadioTapField(object):
1459        ALIGNMENT = 1
1460
1461        def __str__( self ):
1462            return str( self.__class__.__name__ )
1463
1464    class RTF_TSFT(__RadioTapField):
1465        BIT_NUMBER = 0
1466        STRUCTURE = "<Q"
1467        ALIGNMENT = 8
1468
1469    class RTF_FLAGS(__RadioTapField):
1470        BIT_NUMBER = 1
1471        STRUCTURE = "<B"
1472
1473        # From http://www.radiotap.org/defined-fields/Flags
1474        PROPERTY_CFP            = 0x01 #sent/received during CFP
1475        PROPERTY_SHORTPREAMBLE  = 0x02 #sent/received with short preamble
1476        PROPERTY_WEP            = 0x04 #sent/received with WEP encryption
1477        PROPERTY_FRAGMENTATION  = 0x08 #sent/received with fragmentation
1478        PROPERTY_FCS_AT_END     = 0x10 #frame includes FCS
1479        PROPERTY_PAYLOAD_PADDING= 0x20 #frame has padding between 802.11 header and payload (to 32-bit boundary)
1480        PROPERTY_BAD_FCS        = 0x40 #does not pass FCS check
1481        PROPERTY_SHORT_GI       = 0x80 #frame used short guard interval (HT). Unspecified but used:
1482
1483    class RTF_RATE(__RadioTapField):
1484        BIT_NUMBER = 2
1485        STRUCTURE = "<B"
1486
1487    class RTF_CHANNEL(__RadioTapField):
1488        BIT_NUMBER = 3
1489        STRUCTURE = "<HH"
1490        ALIGNMENT = 2
1491
1492    class RTF_FHSS(__RadioTapField):
1493        BIT_NUMBER = 4
1494        STRUCTURE = "<BB"
1495
1496    class RTF_DBM_ANTSIGNAL(__RadioTapField):
1497        BIT_NUMBER = 5
1498        STRUCTURE = "<B"
1499
1500    class RTF_DBM_ANTNOISE(__RadioTapField):
1501        BIT_NUMBER = 6
1502        STRUCTURE = "<B"
1503
1504    class RTF_LOCK_QUALITY(__RadioTapField):
1505        BIT_NUMBER = 7
1506        STRUCTURE = "<H"
1507        ALIGNMENT = 2
1508
1509    class RTF_TX_ATTENUATION(__RadioTapField):
1510        BIT_NUMBER = 8
1511        STRUCTURE = "<H"
1512        ALIGNMENT = 2
1513
1514    class RTF_DB_TX_ATTENUATION(__RadioTapField):
1515        BIT_NUMBER = 9
1516        STRUCTURE = "<H"
1517        ALIGNMENT = 2
1518
1519    class RTF_DBM_TX_POWER(__RadioTapField):
1520        BIT_NUMBER = 10
1521        STRUCTURE = "<b"
1522        ALIGNMENT = 2
1523
1524    class RTF_ANTENNA(__RadioTapField):
1525        BIT_NUMBER = 11
1526        STRUCTURE = "<B"
1527
1528    class RTF_DB_ANTSIGNAL(__RadioTapField):
1529        BIT_NUMBER = 12
1530        STRUCTURE = "<B"
1531
1532    class RTF_DB_ANTNOISE(__RadioTapField):
1533        BIT_NUMBER = 13
1534        STRUCTURE = "<B"
1535
1536##    # official assignment, clashes with RTF_FCS_IN_HEADER
1537##    class RTF_RX_FLAGS(__RadioTapField):
1538##        BIT_NUMBER = 14
1539##        STRUCTURE = "<H"
1540##        ALIGNMENT = 2
1541
1542    # clashes with RTF_RX_FLAGS
1543    class RTF_FCS_IN_HEADER(__RadioTapField):
1544        BIT_NUMBER = 14
1545        STRUCTURE = "<L"
1546        ALIGNMENT = 4
1547
1548    # clashes with HARDWARE_QUEUE
1549    class RTF_TX_FLAGS(__RadioTapField):
1550        BIT_NUMBER = 15
1551        STRUCTURE = "<H"
1552        ALIGNMENT = 2
1553
1554##    # clashes with TX_FLAGS
1555##    class RTF_HARDWARE_QUEUE(__RadioTapField):
1556##        BIT_NUMBER = 15
1557##        STRUCTURE = "<B"
1558##        ALIGNMENT = 1
1559
1560    # clashes with RSSI
1561    class RTF_RTS_RETRIES(__RadioTapField):
1562        BIT_NUMBER = 16
1563        STRUCTURE = "<B"
1564
1565##    # clashes with RTS_RETRIES
1566##    class RTF_RSSI(__RadioTapField):
1567##        BIT_NUMBER = 16
1568##        STRUCTURE = "<H"
1569##        ALIGNMENT = 1
1570
1571    class RTF_DATA_RETRIES(__RadioTapField):
1572        BIT_NUMBER = 17
1573        STRUCTURE = "<B"
1574
1575    class RTF_XCHANNEL(__RadioTapField):
1576        BIT_NUMBER = 18
1577        STRUCTURE = "<LHBB"
1578        ALIGNMENT = 4
1579
1580    class RTF_EXT(__RadioTapField):
1581        BIT_NUMBER = 31
1582        STRUCTURE = []
1583
1584    # Sort the list so the 'for' statement walk the list in the right order
1585    radiotap_fields = __RadioTapField.__subclasses__()
1586    radiotap_fields.sort(lambda x, y: cmp(x.BIT_NUMBER,y.BIT_NUMBER))
1587
1588    def __init__(self, aBuffer = None):
1589        header_size = self.__HEADER_BASE_SIZE
1590        tail_size = 0
1591
1592        if aBuffer:
1593            length = struct.unpack('<H', aBuffer[2:4])[0]
1594            header_size=length
1595
1596            ProtocolPacket.__init__(self, header_size, tail_size)
1597            self.load_packet(aBuffer)
1598        else:
1599            ProtocolPacket.__init__(self, header_size, tail_size)
1600            self.set_version(0)
1601            self.__set_present(0x00000000)
1602
1603    def get_header_length(self):
1604        'Return the RadioTap header \'length\' field'
1605        self.__update_header_length()
1606        return self.header.get_word(2, "<")
1607
1608    def get_version(self):
1609        'Return the \'version\' field'
1610        b = self.header.get_byte(0)
1611        return b
1612
1613    def set_version(self, value):
1614        'Set the \'version\' field'
1615        nb = (value & 0xFF)
1616        self.header.set_byte(0, nb)
1617
1618        nb = (value & 0xFF)
1619
1620    def get_present(self, offset=_BASE_PRESENT_FLAGS_OFFSET):
1621        "Return RadioTap present bitmap field"
1622        present = self.header.get_long(offset, "<")
1623        return present
1624
1625    def __set_present(self, value):
1626        "Set RadioTap present field bit"
1627        self.header.set_long(4, value)
1628
1629    def get_present_bit(self, field, offset=4):
1630        'Get a \'present\' field bit'
1631        present=self.get_present(offset)
1632        return not not (2**field.BIT_NUMBER & present)
1633
1634    def __set_present_bit(self, field):
1635        'Set a \'present\' field bit'
1636        npresent=2**field.BIT_NUMBER | self.get_present()
1637        self.header.set_long(4, npresent,'<')
1638
1639    def __unset_present_bit(self, field):
1640        'Unset a \'present\' field bit'
1641        npresent=~(2**field.BIT_NUMBER) & self.get_present()
1642        self.header.set_long(4, npresent,'<')
1643
1644    def __align(self, val, align):
1645        return ( (((val) + ((align) - 1)) & ~((align) - 1)) - val )
1646
1647    def __get_field_position(self, field):
1648
1649        offset = RadioTap._BASE_PRESENT_FLAGS_OFFSET
1650        extra_present_flags_count = 0
1651        while self.get_present_bit(RadioTap.RTF_EXT, offset):
1652            offset += RadioTap._PRESENT_FLAGS_SIZE
1653            extra_present_flags_count += 1
1654
1655        field_position = self.__HEADER_BASE_SIZE + (RadioTap._BASE_PRESENT_FLAGS_OFFSET * extra_present_flags_count)
1656
1657        for f in self.radiotap_fields:
1658            field_position += self.__align(field_position, f.ALIGNMENT)
1659            if f == field:
1660                return field_position
1661
1662            if self.get_present_bit(f):
1663                total_length = struct.calcsize(f.STRUCTURE)
1664                field_position += total_length
1665
1666        return None
1667
1668    def unset_field( self, field):
1669        is_present=self.get_present_bit(field)
1670        if is_present is False:
1671            return False
1672
1673        byte_pos=self.__get_field_position(field)
1674        if not byte_pos:
1675            return False
1676
1677        self.__unset_present_bit(field)
1678
1679        header=self.get_header_as_string()
1680        total_length = struct.calcsize(field.STRUCTURE)
1681        header=header[:byte_pos]+header[byte_pos+total_length:]
1682
1683        self.load_header(header)
1684
1685    def __get_field_values( self, field ):
1686        is_present=self.get_present_bit(field)
1687        if is_present is False:
1688            return None
1689
1690        byte_pos=self.__get_field_position(field)
1691        header=self.get_header_as_string()
1692        total_length=struct.calcsize(field.STRUCTURE)
1693        v=header[ byte_pos:byte_pos+total_length ]
1694
1695        field_values = struct.unpack(field.STRUCTURE, v)
1696
1697        return field_values
1698
1699    def __set_field_values( self, field, values ):
1700        if not hasattr(values,'__iter__'):
1701            raise Exception("arg 'values' is not iterable")
1702
1703        # It's for to known the qty of argument of a structure
1704        num_fields=len(field.STRUCTURE.translate(string.maketrans("",""), '=@!<>'))
1705
1706        if len(values)!=num_fields:
1707            raise Exception("Field %s has exactly %d items"%(str(field),struct.calcsize(field.STRUCTURE)))
1708
1709        is_present=self.get_present_bit(field)
1710        if is_present is False:
1711            self.__set_present_bit(field)
1712
1713        byte_pos=self.__get_field_position(field)
1714        header=self.get_header_as_string()
1715        total_length=struct.calcsize(field.STRUCTURE)
1716        v=header[ byte_pos:byte_pos+total_length ]
1717
1718        new_str = struct.pack(field.STRUCTURE, *values)
1719
1720        if is_present is True:
1721            header=header[:byte_pos]+new_str+header[byte_pos+total_length:]
1722        else:
1723            header=header[:byte_pos]+new_str+header[byte_pos:]
1724        self.load_header(header)
1725
1726
1727    def set_tsft( self, nvalue ):
1728        "Set the Value in microseconds of the MAC's 64-bit 802.11 "\
1729        "Time Synchronization Function timer when the first bit of "\
1730        "the MPDU arrived at the MAC"
1731        self.__set_field_values(RadioTap.RTF_TSFT, [nvalue])
1732
1733    def get_tsft( self ):
1734        "Get the Value in microseconds of the MAC's 64-bit 802.11 "\
1735        "Time Synchronization Function timer when the first bit of "\
1736        "the MPDU arrived at the MAC"
1737
1738        values=self.__get_field_values(RadioTap.RTF_TSFT)
1739        if not values:
1740            return None
1741        return values[0]
1742
1743    def set_flags( self, nvalue ):
1744        "Set the properties of transmitted and received frames."
1745        self.__set_field_values(self.RTF_FLAGS, [nvalue])
1746
1747    def get_flags( self ):
1748        "Get the properties of transmitted and received frames."
1749        values=self.__get_field_values(self.RTF_FLAGS)
1750        if not values:
1751            return None
1752        return values[0]
1753
1754    def set_rate( self, nvalue ):
1755        "Set the TX/RX data rate in 500 Kbps units"
1756
1757        self.__set_field_values(self.RTF_RATE, [nvalue])
1758
1759    def get_rate( self ):
1760        "Get the TX/RX data rate in 500 Kbps units"
1761
1762        values=self.__get_field_values(self.RTF_RATE)
1763        if not values:
1764            return None
1765        return values[0]
1766
1767    def set_channel( self, freq, flags ):
1768        "Set the channel Tx/Rx frequency in MHz and the channel flags"
1769
1770        self.__set_field_values(self.RTF_CHANNEL, [freq, flags])
1771
1772    def get_channel( self ):
1773        "Get the TX/RX data rate in 500 Kbps units"
1774
1775        values=self.__get_field_values(self.RTF_CHANNEL)
1776
1777        return values
1778
1779    def set_FHSS( self, hop_set, hop_pattern ):
1780        "Set the hop set and pattern for frequency-hopping radios"
1781
1782        self.__set_field_values(self.RTF_FHSS, [hop_set, hop_pattern])
1783
1784    def get_FHSS( self ):
1785        "Get the hop set and pattern for frequency-hopping radios"
1786
1787        values=self.__get_field_values(self.RTF_FHSS)
1788
1789        return values
1790
1791    def set_dBm_ant_signal( self, signal ):
1792        "Set the RF signal power at the antenna, decibel difference from an "\
1793        "arbitrary, fixed reference."
1794
1795        self.__set_field_values(self.RTF_DBM_ANTSIGNAL, [signal])
1796
1797    def get_dBm_ant_signal( self ):
1798        "Get the RF signal power at the antenna, decibel difference from an "\
1799        "arbitrary, fixed reference."
1800
1801        values=self.__get_field_values(self.RTF_DBM_ANTSIGNAL)
1802        if not values:
1803            return None
1804        return values[0]
1805
1806    def set_dBm_ant_noise( self, signal ):
1807        "Set the RF noise power at the antenna, decibel difference from an "\
1808        "arbitrary, fixed reference."
1809
1810        self.__set_field_values(self.RTF_DBM_ANTNOISE, [signal])
1811
1812    def get_dBm_ant_noise( self ):
1813        "Get the RF noise power at the antenna, decibel difference from an "\
1814        "arbitrary, fixed reference."
1815
1816        values=self.__get_field_values(self.RTF_DBM_ANTNOISE)
1817        if not values:
1818            return None
1819        return values[0]
1820
1821    def set_lock_quality( self, quality ):
1822        "Set the quality of Barker code lock. "\
1823        "Called 'Signal Quality' in datasheets. "
1824
1825        self.__set_field_values(self.RTF_LOCK_QUALITY, [quality])
1826
1827    def get_lock_quality( self ):
1828        "Get the quality of Barker code lock. "\
1829        "Called 'Signal Quality' in datasheets. "
1830
1831        values=self.__get_field_values(self.RTF_LOCK_QUALITY)
1832        if not values:
1833            return None
1834        return values[0]
1835
1836    def set_tx_attenuation( self, power ):
1837        "Set the transmit power expressed as unitless distance from max power "\
1838        "set at factory calibration. 0 is max power."
1839
1840        self.__set_field_values(self.RTF_TX_ATTENUATION, [power])
1841
1842    def get_tx_attenuation( self ):
1843        "Set the transmit power expressed as unitless distance from max power "\
1844        "set at factory calibration. 0 is max power."
1845
1846        values=self.__get_field_values(self.RTF_TX_ATTENUATION)
1847        if not values:
1848            return None
1849        return values[0]
1850
1851    def set_dB_tx_attenuation( self, power ):
1852        "Set the transmit power expressed as decibel distance from max power "\
1853        "set at factory calibration. 0 is max power. "
1854
1855        self.__set_field_values(self.RTF_DB_TX_ATTENUATION, [power])
1856
1857    def get_dB_tx_attenuation( self ):
1858        "Set the transmit power expressed as decibel distance from max power "\
1859        "set at factory calibration. 0 is max power. "
1860
1861        values=self.__get_field_values(self.RTF_DB_TX_ATTENUATION)
1862        if not values:
1863            return None
1864        return values[0]
1865
1866    def set_dBm_tx_power( self, power ):
1867        "Set the transmit power expressed as dBm (decibels from a 1 milliwatt"\
1868        " reference). This is the absolute power level measured at the "\
1869        "antenna port."
1870
1871        self.__set_field_values(self.RTF_DBM_TX_POWER, [power])
1872
1873    def get_dBm_tx_power( self ):
1874        "Get the transmit power expressed as dBm (decibels from a 1 milliwatt"\
1875        " reference). This is the absolute power level measured at the "\
1876        "antenna port."
1877
1878        values=self.__get_field_values(self.RTF_DBM_TX_POWER)
1879        if not values:
1880            return None
1881        return values[0]
1882
1883    def set_antenna( self, antenna_index ):
1884        "Set Rx/Tx antenna index for this packet. "\
1885        "The first antenna is antenna 0. "\
1886
1887        self.__set_field_values(self.RTF_ANTENNA, [antenna_index])
1888
1889    def get_antenna( self ):
1890        "Set Rx/Tx antenna index for this packet. "\
1891        "The first antenna is antenna 0. "\
1892
1893        values=self.__get_field_values(self.RTF_ANTENNA)
1894        if not values:
1895            return None
1896        return values[0]
1897
1898    def set_dB_ant_signal( self, signal ):
1899        "Set the RF signal power at the antenna, decibel difference from an "\
1900        "arbitrary, fixed reference."
1901
1902        self.__set_field_values(self.RTF_DB_ANTSIGNAL, [signal])
1903
1904    def get_dB_ant_signal( self ):
1905        "Get the RF signal power at the antenna, decibel difference from an "\
1906        "arbitrary, fixed reference."
1907
1908        values=self.__get_field_values(self.RTF_DB_ANTSIGNAL)
1909        if not values:
1910            return None
1911        return values[0]
1912
1913    def set_dB_ant_noise( self, signal ):
1914        "Set the RF noise power at the antenna, decibel difference from an "\
1915        "arbitrary, fixed reference."
1916
1917        self.__set_field_values(self.RTF_DB_ANTNOISE, [signal])
1918
1919    def get_dB_ant_noise( self ):
1920        "Get the RF noise power at the antenna, decibel difference from an "\
1921        "arbitrary, fixed reference."
1922
1923        values=self.__get_field_values(self.RTF_DB_ANTNOISE)
1924        if not values:
1925            return None
1926        return values[0]
1927
1928##    def set_rx_flags( self, flags ):
1929##        "Set the properties of received frames."
1930##
1931##        self.__set_field_values(self.RTF_RX_FLAGS, [flags])
1932##
1933##    def get_rx_flags( self ):
1934##        "Get the properties of received frames."
1935##
1936##        values=self.__get_field_values(self.RTF_RX_FLAGS)
1937##        if not values:
1938##            return None
1939##        return values[0]
1940
1941    def set_FCS_in_header( self, fcs ):
1942        "Set the Field containing the FCS of the frame (instead of it being "\
1943        "appended to the frame as it would appear on the air.) "
1944
1945        self.__set_field_values(self.RTF_FCS_IN_HEADER, [fcs])
1946
1947    def get_FCS_in_header( self ):
1948        "Get the Field containing the FCS of the frame (instead of it being "\
1949        "appended to the frame as it would appear on the air.) "
1950
1951        values=self.__get_field_values(self.RTF_FCS_IN_HEADER)
1952        if not values:
1953            return None
1954        return values[0]
1955
1956##    def set_RSSI( self, rssi, max_rssi ):
1957##        "Set the received signal strength and the maximum for the hardware."
1958##
1959##        self.__set_field_values(self.RTF_RSSI, [rssi, max_rssi])
1960##
1961##    def get_RSSI( self ):
1962##        "Get the received signal strength and the maximum for the hardware."
1963##
1964##        values=self.__get_field_values(self.RTF_RSSI)
1965##
1966##        return values
1967
1968    def set_RTS_retries( self, retries):
1969        "Set the number of RTS retries a transmitted frame used."
1970
1971        self.__set_field_values(self.RTF_RTS_RETRIES, [retries])
1972
1973    def get_RTS_retries( self ):
1974        "Get the number of RTS retries a transmitted frame used."
1975
1976        values=self.__get_field_values(self.RTF_RTS_RETRIES)
1977        if not values:
1978            return None
1979        return values[0]
1980
1981    def set_tx_flags( self, flags ):
1982        "Set the properties of transmitted frames."
1983
1984        self.__set_field_values(self.RTF_TX_FLAGS, [flags])
1985
1986    def get_tx_flags( self ):
1987        "Get the properties of transmitted frames."
1988
1989        values=self.__get_field_values(self.RTF_TX_FLAGS)
1990        if not values:
1991            return None
1992        return values[0]
1993
1994    def set_xchannel( self, flags, freq, channel, maxpower ):
1995        "Set extended channel information: flags, freq, channel and maxpower"
1996
1997        self.__set_field_values(self.RTF_XCHANNEL, [flags, freq, channel, maxpower] )
1998
1999    def get_xchannel( self ):
2000        "Get extended channel information: flags, freq, channel and maxpower"
2001
2002        values=self.__get_field_values(field=self.RTF_XCHANNEL)
2003
2004        return values
2005
2006    def set_data_retries( self, retries ):
2007        "Set the number of data retries a transmitted frame used."
2008
2009        self.__set_field_values(self.RTF_DATA_RETRIES, [retries])
2010
2011    def get_data_retries( self ):
2012        "Get the number of data retries a transmitted frame used."
2013
2014        values=self.__get_field_values(self.RTF_DATA_RETRIES)
2015        if not values:
2016            return None
2017        return values[0]
2018
2019    def set_hardware_queue( self, queue ):
2020        "Set the hardware queue to send the frame on."
2021
2022        self.__set_field_values(self.RTF_HARDWARE_QUEUE, [queue])
2023
2024##    def get_hardware_queue( self ):
2025##        "Get the hardware queue to send the frame on."
2026##
2027##        values=self.__get_field_values(self.RTF_HARDWARE_QUEUE)
2028##        if not values:
2029##            return None
2030##        return values[0]
2031
2032    def __update_header_length(self):
2033        'Update the RadioTap header length field with the real size'
2034        self.header.set_word(2, self.get_header_size(), "<")
2035
2036    def get_packet(self):
2037        self.__update_header_length()
2038        return ProtocolPacket.get_packet(self)
2039
2040class Dot11ManagementFrame(ProtocolPacket):
2041    '802.11 Management Frame'
2042
2043    def __init__(self, aBuffer = None):
2044        header_size = 22
2045        tail_size = 0
2046
2047        ProtocolPacket.__init__(self, header_size, tail_size)
2048        if(aBuffer):
2049            self.load_packet(aBuffer)
2050
2051    def __init__(self, aBuffer = None):
2052        header_size = 22
2053        tail_size = 0
2054
2055        ProtocolPacket.__init__(self, header_size, tail_size)
2056        if(aBuffer):
2057            self.load_packet(aBuffer)
2058
2059    def get_duration(self):
2060        'Return 802.11 Management frame \'Duration\' field'
2061        b = self.header.get_word(0, "<")
2062        return b
2063
2064    def set_duration(self, value):
2065        'Set the 802.11 Management frame \'Duration\' field'
2066        # set the bits
2067        nb = value & 0xFFFF
2068        self.header.set_word(0, nb, "<")
2069
2070    def get_destination_address(self):
2071        'Return 802.11 Management frame \'Destination Address\' field as a 6 bytes array'
2072        return self.header.get_bytes()[2:8]
2073
2074    def set_destination_address(self, value):
2075        'Set 802.11 Management frame \'Destination Address\' field as a 6 bytes array'
2076        for i in range(0, 6):
2077            self.header.set_byte(2+i, value[i])
2078
2079    def get_source_address(self):
2080        'Return 802.11 Management frame \'Source Address\' field as a 6 bytes array'
2081        return self.header.get_bytes()[8:14]
2082
2083    def set_source_address(self, value):
2084        'Set 802.11 Management frame \'Source Address\' field as a 6 bytes array'
2085        for i in range(0, 6):
2086            self.header.set_byte(8+i, value[i])
2087
2088    def get_bssid(self):
2089        'Return 802.11 Management frame \'BSSID\' field as a 6 bytes array'
2090        return self.header.get_bytes()[14: 20]
2091
2092    def set_bssid(self, value):
2093        'Set 802.11 Management frame \'BSSID\' field as a 6 bytes array'
2094        for i in range(0, 6):
2095            self.header.set_byte(14+i, value[i])
2096
2097    def get_sequence_control(self):
2098        'Return 802.11 Management frame \'Sequence Control\' field'
2099        b = self.header.get_word(20, "<")
2100        return b
2101
2102    def set_sequence_control(self, value):
2103        'Set the 802.11 Management frame \'Sequence Control\' field'
2104        # set the bits
2105        nb = value & 0xFFFF
2106        self.header.set_word(20, nb, "<")
2107
2108    def get_fragment_number(self):
2109        'Return 802.11 Management frame \'Fragment Number\' subfield'
2110
2111        b = self.get_sequence_control()
2112        return (b&0x000F)
2113
2114    def set_fragment_number(self, value):
2115        'Set the 802.11 Management frame \'Fragment Number\' subfield'
2116        # clear the bits
2117        mask = (~0x000F) & 0xFFFF
2118        masked = self.header.get_word(20, "<") & mask
2119        # set the bits
2120        nb = masked | (value & 0x000F)
2121        self.header.set_word(20, nb, "<")
2122
2123    def get_sequence_number(self):
2124        'Return 802.11 Management frame \'Sequence Number\' subfield'
2125
2126        b = self.get_sequence_control()
2127        return ((b>>4) & 0xFFF)
2128
2129    def set_sequence_number(self, value):
2130        'Set the 802.11 Management frame \'Sequence Number\' subfield'
2131        # clear the bits
2132        mask = (~0xFFF0) & 0xFFFF
2133        masked = self.header.get_word(20, "<") & mask
2134        # set the bits
2135        nb = masked | ((value & 0x0FFF ) << 4 )
2136        self.header.set_word(20, nb, "<")
2137
2138    def get_frame_body(self):
2139        'Return 802.11 Management frame \'Frame Body\' field'
2140
2141        return self.get_body_as_string()
2142
2143    def set_frame_body(self, data):
2144        'Set 802.11 Management frame \'Frame Body\' field'
2145
2146        self.load_body(data)
2147
2148class DOT11_MANAGEMENT_ELEMENTS():
2149    SSID                    =  0
2150    SUPPORTED_RATES         =  1
2151    FH_PARAMETER_SET        =  2
2152    DS_PARAMETER_SET        =  3
2153    CF_PARAMETER_SET        =  4
2154    TIM                     =  5
2155    IBSS_PARAMETER_SET      =  6
2156    COUNTRY                 =  7
2157    HOPPING_PARAMETER       =  8
2158    HOPPING_TABLE           =  9
2159    REQUEST                 = 10
2160    BSS_LOAD                = 11
2161    EDCA_PARAMETER_SET      = 12
2162    TSPEC                   = 13
2163    TCLAS                   = 14
2164    SCHEDULE                = 15
2165    CHALLENGE_TEXT          = 16
2166    # RESERVED                17-31
2167    POWER_CONSTRAINT        = 32
2168    POWER_CAPABILITY        = 33
2169    TPC_REQUEST             = 34
2170    TPC_REPORT              = 35
2171    SUPPORTED_CHANNELS      = 36
2172    CHANNEL_SWITCH_ANN      = 37
2173    MEASURE_REQ             = 38
2174    MEASURE_REP             = 39
2175    QUIET                   = 40
2176    IBSS_DFS                = 41
2177    ERP_INFO                = 42
2178    TS_DELAY                = 43
2179    TCLAS_PROCESSING        = 44
2180    #RESERVED                 45  # See: IEEE 802.11n
2181    QOS_CAPABILITY          = 46
2182    #RESERVED                 47  # See: IEEE 802.11g
2183    RSN                     = 48
2184    #RESERVED                 49
2185    EXT_SUPPORTED_RATES     = 50
2186    #RESERVED                 51-126
2187    EXTENDED_CAPABILITIES   = 127
2188    #RESERVED                 128-220
2189    VENDOR_SPECIFIC         = 221
2190    #RESERVED                 222-255
2191
2192class Dot11ManagementHelper(ProtocolPacket):
2193
2194    def __init__(self, header_size, tail_size, aBuffer = None):
2195        self.__HEADER_BASE_SIZE=header_size
2196
2197        if aBuffer:
2198            elements_length=self.__calculate_elements_length(aBuffer[self.__HEADER_BASE_SIZE:])
2199            header_size+=elements_length
2200
2201            ProtocolPacket.__init__(self, header_size, tail_size)
2202            self.load_packet(aBuffer)
2203        else:
2204            ProtocolPacket.__init__(self, header_size, tail_size)
2205
2206    def _find_element(self, elements, element_id ):
2207        remaining=len(elements)
2208
2209        offset=0
2210        while remaining > 0:
2211            (id,length)=struct.unpack("!BB",elements[offset:offset+2])
2212            if element_id is None:
2213                pass # through the whole list returning the length
2214            elif id==element_id:
2215                yield (0,offset,length+2)    # ==
2216            length+=2 #id+length
2217            offset+=length
2218            if length>remaining:
2219                # Error!!
2220                length = remaining;
2221            remaining-=length
2222        # < Not found
2223        yield (-1, offset, None)
2224
2225    def __calculate_elements_length(self, elements):
2226        gen_tp=self._find_element(elements, None )
2227        (match,offset,length)=gen_tp.next()
2228        if match != -1:
2229            # element_id is None, then __find_tagged_parameter must return -1
2230            raise Exception("Internal Error %s"%match)
2231        return offset
2232
2233    def _get_elements_generator(self, element_id):
2234        elements=self.get_header_as_string()[self.__HEADER_BASE_SIZE:]
2235        gen_tp=self._find_element(elements, element_id )
2236        while True:
2237            (match,offset,length)=gen_tp.next()
2238            if match != 0:
2239                return
2240            value_offset=offset+2
2241            value_end=offset+length
2242            value=elements[value_offset:value_end]
2243            yield value
2244
2245    def _get_element(self, element_id):
2246        gen_get_element=self._get_elements_generator(element_id)
2247        try:
2248            s=gen_get_element.next()
2249
2250            if s is None:
2251                raise Exception("gen_get_element salio con None in _get_element!!!")
2252
2253            return s
2254        except StopIteration:
2255            pass
2256
2257        return None
2258
2259    def delete_element(self, element_id, multiple = False):
2260        header=self.get_header_as_string()
2261        elements=header[self.__HEADER_BASE_SIZE:]
2262        gen_tp=self._find_element(elements, element_id )
2263        found=False
2264        while True:
2265            (match,offset,length)=gen_tp.next()
2266            if match != 0:
2267                break
2268            start=self.__HEADER_BASE_SIZE+offset
2269            header=header[:start]+header[start+length:]
2270            found=True
2271            if multiple is False:
2272                break
2273
2274        if not found:
2275            return  False
2276
2277        self.load_header(header)
2278        return True
2279
2280    def _set_element(self, element_id, value, replace = True):
2281        parameter=struct.pack('BB%ds'%len(value),element_id,len(value),value)
2282
2283        header=self.get_header_as_string()
2284        elements=header[self.__HEADER_BASE_SIZE:]
2285        gen_tp=self._find_element(elements, element_id )
2286        found=False
2287        while True:
2288            (match,offset,length)=gen_tp.next()
2289            start=self.__HEADER_BASE_SIZE+offset
2290            if match == 0 and replace:
2291                # Replace
2292                header=header[:start]+parameter+header[start+length:]
2293                found=True
2294                break
2295            elif match > 0:
2296                # Add
2297                header=header[:start]+parameter+header[start:]
2298                found=True
2299                break
2300            else:
2301                break
2302        if not found:
2303            # Append (found<0 Not found)
2304            header=header+parameter
2305        self.load_header(header)
2306
2307class Dot11ManagementBeacon(Dot11ManagementHelper):
2308    '802.11 Management Beacon Frame'
2309
2310    __HEADER_BASE_SIZE = 12 # minimal header size
2311
2312    def __init__(self, aBuffer = None):
2313        header_size = self.__HEADER_BASE_SIZE
2314        tail_size = 0
2315        Dot11ManagementHelper.__init__(self, header_size, tail_size, aBuffer)
2316
2317    def get_timestamp(self):
2318        'Return the 802.11 Management Beacon frame \'Timestamp\' field'
2319        b = self.header.get_long_long(0, "<")
2320        return b
2321
2322    def set_timestamp(self, value):
2323        'Set the 802.11 Management Beacon frame \'Timestamp\' field'
2324        # set the bits
2325        nb = value & 0xFFFFFFFFFFFFFFFF
2326        self.header.set_long_long(0, nb, "<")
2327
2328    def get_beacon_interval(self):
2329        'Return the 802.11 Management Beacon frame \'Beacon Interval\' field' \
2330        'To convert it to seconds =>  secs = Beacon_Interval*1024/1000000'
2331
2332        b = self.header.get_word(8, "<")
2333        return b
2334
2335    def set_beacon_interval(self, value):
2336        'Set the 802.11 Management Beacon frame \'Beacon Interval\' field'
2337        # set the bits
2338        nb = value & 0xFFFF
2339        self.header.set_word(8, nb, "<")
2340
2341    def get_capabilities(self):
2342        'Return the 802.11 Management Beacon frame \'Capability information\' field. '
2343
2344        b = self.header.get_word(10, "<")
2345        return b
2346
2347    def set_capabilities(self, value):
2348        'Set the 802.11 Management Beacon frame \'Capability Information\' field'
2349        # set the bits
2350        nb = value & 0xFFFF
2351        self.header.set_word(10, nb, "<")
2352
2353    def get_ssid(self):
2354        "Get the 802.11 Management SSID element. "\
2355        "The SSID element indicates the identity of an ESS or IBSS."
2356        return self._get_element(DOT11_MANAGEMENT_ELEMENTS.SSID)
2357
2358    def set_ssid(self, ssid):
2359        self._set_element(DOT11_MANAGEMENT_ELEMENTS.SSID,ssid)
2360
2361    def get_supported_rates(self, human_readable=False):
2362        "Get the 802.11 Management Supported Rates element. "\
2363        "Specifies up to eight rates, then an Extended Supported Rate element "\
2364        "shall be generated to specify the remaining supported rates."\
2365        "If human_readable is True, the rates are returned in Mbit/sec"
2366        s=self._get_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES)
2367        if s is None:
2368            return None
2369
2370        rates=struct.unpack('%dB'%len(s),s)
2371        if not human_readable:
2372            return rates
2373
2374        rates_Mbs=tuple(map(lambda x: (x&0x7F)*0.5,rates))
2375        return rates_Mbs
2376
2377    def set_supported_rates(self, rates):
2378        "Set the 802.11 Management Supported Rates element. "\
2379        "Specifies a tuple or list with up to eight rates, then an "\
2380        "Extended Supported Rate element shall be generated to specify "\
2381        "the remaining supported rates."
2382        qty_rates=len(rates)
2383        if qty_rates>8:
2384            raise Exception("requires up to eight rates")
2385        rates_string=struct.pack('B'*qty_rates,*rates)
2386        self._set_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES,rates_string)
2387
2388    def get_ds_parameter_set(self):
2389        "Get the 802.11 Management DS Parameter set element. "\
2390        "Contains information to allow channel number identification for "\
2391        "STAs using a DSSS PHY."
2392        s=self._get_element(DOT11_MANAGEMENT_ELEMENTS.DS_PARAMETER_SET)
2393        if s is None:
2394            return None
2395
2396        (ch,)=struct.unpack('B',s)
2397
2398        return ch
2399
2400    def set_ds_parameter_set(self, channel):
2401        "Set the 802.11 Management DS Parameter set element. "\
2402        "Contains information to allow channel number identification for "\
2403        "STAs using a DSSS PHY."
2404        channel_string=struct.pack('B',channel)
2405        self._set_element(DOT11_MANAGEMENT_ELEMENTS.DS_PARAMETER_SET,channel_string)
2406
2407    def get_rsn(self):
2408        "Get the 802.11 Management Robust Security Network element."
2409        s = self._get_element(DOT11_MANAGEMENT_ELEMENTS.RSN)
2410        if s is None:
2411            return None
2412        return s
2413
2414    def set_rsn(self, data):
2415        "Set the 802.11 Management Robust Security Network element."
2416        self._set_element(DOT11_MANAGEMENT_ELEMENTS.RSN, data)
2417
2418    def get_erp(self):
2419        "Get the 802.11 Management ERP (extended rate PHY) Information element."
2420        s = self._get_element(DOT11_MANAGEMENT_ELEMENTS.ERP_INFO)
2421        if s is None:
2422            return None
2423
2424        (erp,) = struct.unpack('B',s)
2425
2426        return erp
2427
2428    def set_erp(self, erp):
2429        "Set the 802.11 Management ERP (extended rate PHY) Inforamation "\
2430        "element."
2431        erp_string = struct.pack('B',erp)
2432        self._set_element(DOT11_MANAGEMENT_ELEMENTS.ERP_INFO, erp_string)
2433
2434    def get_country(self):
2435        "Get the 802.11 Management Country element." \
2436        "Returns a tuple containing Country code, first channel number, "\
2437        "number of channels and maximum transmit power level"
2438        s = self._get_element(DOT11_MANAGEMENT_ELEMENTS.COUNTRY)
2439        if s is None:
2440            return None
2441
2442        code, first, num, max = struct.unpack('3sBBB',s)
2443        code = code.strip(' ')
2444        return code, first, num, max
2445
2446    def set_country(self, code, first_channel, number_of_channels, max_power):
2447        "Set the 802.11 Management Country element."
2448        if len(code) > 3:
2449            raise Exception("Country code must be up to 3 bytes long")
2450
2451        #Padding the country code
2452        code += ' ' * (3-len(code))
2453
2454        country_string = struct.pack('3sBBB', code, first_channel,
2455                number_of_channels, max_power)
2456        self._set_element(DOT11_MANAGEMENT_ELEMENTS.COUNTRY, country_string)
2457
2458    def get_vendor_specific(self):
2459        "Get the 802.11 Management Vendor Specific elements "\
2460        "as a list of tuples."
2461        "The Vendor Specific information element is used to carry "\
2462        "information not defined in the standard within a single "\
2463        "defined format"
2464
2465        vs=[]
2466        gen_get_element=self._get_elements_generator(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC)
2467        try:
2468            while 1:
2469                s=gen_get_element.next()
2470
2471                if s is None:
2472                    raise Exception("gen_get_element salio con None!!!")
2473
2474                # OUI is 3 bytes
2475                oui=s[:3]
2476                data=s[3:]
2477                vs.append((oui,data))
2478        except StopIteration:
2479            pass
2480
2481        return vs
2482
2483    def add_vendor_specific(self, oui, data):
2484        "Set the 802.11 Management Vendor Specific element. "\
2485        "The Vendor Specific information element is used to carry "\
2486        "information not defined in the standard within a single "\
2487        "defined format"
2488
2489        # 3 is the OUI length
2490        max_data_len=255-3
2491        data_len=len(data)
2492
2493        if data_len>max_data_len:
2494            raise Exception("data allow up to %d bytes long" % max_data)
2495        if len(oui) > 3:
2496            raise Exception("oui is three bytes long")
2497
2498        self._set_element(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC,oui+data, replace=False)
2499
2500class Dot11ManagementProbeRequest(Dot11ManagementHelper):
2501    '802.11 Management Probe Request Frame'
2502
2503    def __init__(self, aBuffer = None):
2504        header_size = 0
2505        tail_size = 0
2506        Dot11ManagementHelper.__init__(self, header_size, tail_size, aBuffer)
2507
2508    def get_ssid(self):
2509        "Get the 802.11 Management SSID element. "\
2510        "The SSID element indicates the identity of an ESS or IBSS."
2511        return self._get_element(DOT11_MANAGEMENT_ELEMENTS.SSID)
2512
2513    def set_ssid(self, ssid):
2514        self._set_element(DOT11_MANAGEMENT_ELEMENTS.SSID,ssid)
2515
2516    def get_supported_rates(self, human_readable=False):
2517        "Get the 802.11 Management Supported Rates element. "\
2518        "Specifies up to eight rates, then an Extended Supported Rate element "\
2519        "shall be generated to specify the remaining supported rates."\
2520        "If human_readable is True, the rates are returned in Mbit/sec"
2521        s=self._get_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES)
2522        if s is None:
2523            return None
2524
2525        rates=struct.unpack('%dB'%len(s),s)
2526        if not human_readable:
2527            return rates
2528
2529        rates_Mbs=tuple(map(lambda x: (x&0x7F)*0.5,rates))
2530        return rates_Mbs
2531
2532    def set_supported_rates(self, rates):
2533        "Set the 802.11 Management Supported Rates element. "\
2534        "Specifies a tuple or list with up to eight rates, then an "\
2535        "Extended Supported Rate element shall be generated to specify "\
2536        "the remaining supported rates."
2537        qty_rates=len(rates)
2538        if qty_rates>8:
2539            raise Exception("requires up to eight rates")
2540        rates_string=struct.pack('B'*qty_rates,*rates)
2541        self._set_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES,rates_string)
2542
2543class Dot11ManagementProbeResponse(Dot11ManagementBeacon):
2544    '802.11 Management Probe Response Frame'
2545
2546    def __init__(self, aBuffer = None):
2547        Dot11ManagementBeacon.__init__(self, aBuffer)
2548
2549class DOT11_REASON_CODES():
2550    # RESERVED                                         = 0
2551    UNSPECIFIED_REASON                                 = 1
2552    PREV_AUTH_NO_LONGER_VALID                          = 2
2553    DEAUTH_STA_IS_LEAVING                              = 3
2554    DISASS_DUE_TO_INACTIVITY                           = 4
2555    DISASS_AP_UNABLE_HANDLE_ALL_STA                    = 5
2556    C2_FRAME_FROM_NONAUTHENTICATED_STA                 = 6
2557    C3_FRAME_FROM_NONASSOCIATED_STA                    = 7
2558    DISSASS_STA_IS_LEAVING                             = 8
2559    STA_REQ_NOT_AUTH_STA                               = 9
2560    DISASS_POWER_CAP_IE_UNNACCEPTABLE                  = 10
2561    DISASS_SUP_CH_IE_UNNACCEPTABLE                     = 11
2562    # RESERVED                                         = 12
2563    INVALID_IE                                         = 13
2564    MIC_FAILURE                                        = 14
2565    FOUR_WAY_HANDSHAKE_TIMEOUT                         = 15
2566    GROUP_KEY_HANDSHAKE_TIMEOUT                        = 16
2567    IE_FOUR_WAY_HANDSHAKE_DIFFERENT                    = 17
2568    INVALID_GROUP_CIPHER                               = 18
2569    INVALID_PAIRWISE_CIPHER                            = 19
2570    INVALID_AKMP                                       = 20
2571    UNSUPPORTED_RSN_IE_VERSION                         = 21
2572    INVALID_RSN_IE_CAP                                 = 22
2573    X_AUTH_FAILED                                      = 23
2574    CIPHER_SUITE_REJECTED_SECURITY_POLICY              = 24
2575    # RESERVED                                         = 25 - 31
2576    DISASS_QOS_RELATED_REASON                          = 32
2577    DISASS_QOS_UNSUFFICIENT_BANDWIDTH                  = 33
2578    DISASS_EXCESSIVE_FRAMES_WITHOUT_ACK                = 34
2579    DISASS_STA_TX_OUTSIDE_TXOPS                        = 35
2580    REQ_STA_LEAVING                                    = 36
2581    REQ_STA_NOT_WANT_MECHANISM                         = 37
2582    REQ_STA_RECV_FRAMES_WHICH_SETUP_REQ                = 38
2583    REQ_STA_DUE_TIMEOUT                                = 39
2584    STA_NOT_SUPPORT_CIPHER_SUITE                       = 45
2585    # RESERVED                                         = 46 - 65 535
2586
2587class Dot11ManagementDeauthentication(ProtocolPacket):
2588    '802.11 Management Deauthentication Frame'
2589
2590    def __init__(self, aBuffer = None):
2591        header_size = 2
2592        tail_size = 0
2593        if aBuffer:
2594            ProtocolPacket.__init__(self, header_size, tail_size)
2595            self.load_packet(aBuffer)
2596        else:
2597            ProtocolPacket.__init__(self, header_size, tail_size)
2598
2599    def get_reason_code(self):
2600        "Get the 802.11 Management Deauthentication or Disassociation Code."
2601        return self.header.get_word(0, "<")
2602
2603    def set_reason_code(self, rc):
2604        self.header.set_word(0, rc, "<")
2605
2606class DOT11_AUTH_ALGORITHMS():
2607    OPEN       = 0
2608    SHARED_KEY = 1
2609
2610class DOT11_AUTH_STATUS_CODES():
2611    SUCCESSFUL                                         = 0
2612    UNSPECIFIED_FAILURE                                = 1
2613    # RESERVED                                         = 2 - 9
2614    CAP_REQ_UNSUPPORTED                                = 10
2615    REASS_DENIED_CANNOT_CONFIRM_ASS_EXISTS             = 11
2616    ASS_DENIED_REASON_OUTSIDE_SCOPE_STANDARD           = 12
2617    STA_NOT_SUPPORT_AUTH_ALGORITHM                     = 13
2618    AUTH_SEQ_OUT_OF_EXPECTED                           = 14
2619    AUTH_REJECTED_CHALLENGE_FAILURE                    = 15
2620    AUTH_REJECTED_TIMEOUT                              = 16
2621    ASS_DENIED_AP_UNABLE_HANDLE_MORE_STA               = 17
2622    ASS_DENIED_STA_NOT_SUPPORTING_DATA_RATES           = 18
2623    ASS_DENIED_STA_NOT_SUPPORTING_SHORT_PREAMBLE       = 19
2624    ASS_DENIED_STA_NOT_SUPPORTING_PBCC_MODULATION      = 20
2625    ASS_DENIED_STA_NOT_SUPPORTING_CHANNEL_AGILITY      = 21
2626    ASS_REQUEST_REJECTED_SPACTRUM_MGT_CAP              = 22
2627    ASS_REQUEST_REJECTED_POWER_CAP_IE_UNNACCEPTABLE    = 23
2628    ASS_REQUEST_REJECTED_SUP_CH_IE_UNNACCEPTABLE       = 24
2629    ASS_DENIED_STA_NOT_SUPPORTING_SHORT_SLOT_TIME      = 25
2630    ASS_DENIED_STA_NOT_SUPPORTING_DSSS_OFDM            = 26
2631    # RESERVED                                         = 27 - 31
2632    UNSPECIFIED_QOS                                    = 32
2633    ASS_DENIED_QOS_UNSUFFICIENT_BANDWIDTH              = 33
2634    ASS_DENIED_EXCESSIVE_FRAME_LOST                    = 34
2635    ASS_DENIED_STA_NOT_SUPPORT_QOS                     = 35
2636    # RESERVED                                         = 36
2637    REQ_HAS_BEEN_DECLINED                              = 37
2638    REQ_NOT_SUCCESSFUL_PARAM_INVALID_VALUE             = 38
2639    TSPEC                                              = 39
2640    INVALID_IE                                         = 40
2641    INVALID_GROUP_CIPHER                               = 41
2642    INVALID_PAIRWISE_CIPHER                            = 42
2643    INVALID_AKMP                                       = 43
2644    UNSUPPORTED_RSN_IE_VERSION                         = 44
2645    INVALID_RSN_IE_CAP                                 = 45
2646    CIPHER_SUITE_REJECTED_SECURITY_POLICY              = 46
2647    TS_NOT_CREATED                                     = 47
2648    DIRECT_LINK_NOT_ALLOWED_BSS_POLICY                 = 48
2649    DST_STA_NOT_PRESENT_IN_BSS                         = 49
2650    DST_STA_NOT_QOS_STA                                = 50
2651    ASS_DENIED_LISTEN_INTERVAL_TOO_LARGE               = 51
2652    # RESERVED                                         = 52 - 65 535
2653
2654class Dot11ManagementAuthentication(Dot11ManagementHelper):
2655    '802.11 Management Authentication Frame'
2656
2657    __HEADER_BASE_SIZE = 6 # minimal header size
2658
2659    def __init__(self, aBuffer = None):
2660        header_size = self.__HEADER_BASE_SIZE
2661        tail_size = 0
2662        Dot11ManagementHelper.__init__(self, header_size, tail_size, aBuffer)
2663
2664    def get_authentication_algorithm(self):
2665        "Get the 802.11 Management Authentication Algorithm."
2666        return self.header.get_word(0, "<")
2667
2668    def set_authentication_algorithm(self, algorithm):
2669        "Set the 802.11 Management Authentication Algorithm."
2670        self.header.set_word(0, algorithm, "<")
2671
2672    def get_authentication_sequence(self):
2673        "Get the 802.11 Management Authentication Sequence."
2674        return self.header.get_word(2, "<")
2675
2676    def set_authentication_sequence(self, seq):
2677        "Set the 802.11 Management Authentication Sequence."
2678        self.header.set_word(2, seq, "<")
2679
2680    def get_authentication_status(self):
2681        "Get the 802.11 Management Authentication Status."
2682        return self.header.get_word(4, "<")
2683
2684    def set_authentication_status(self, status):
2685        "Set the 802.11 Management Authentication Status."
2686        self.header.set_word(4, status, "<")
2687
2688    def get_challenge_text(self):
2689        return self._get_element(DOT11_MANAGEMENT_ELEMENTS.CHALLENGE_TEXT)
2690
2691    def set_challenge_text(self, challenge):
2692        self._set_element(DOT11_MANAGEMENT_ELEMENTS.CHALLENGE_TEXT, challenge)
2693
2694    def get_vendor_specific(self):
2695        "Get the 802.11 Management Vendor Specific elements "\
2696        "as a list of tuples."
2697        "The Vendor Specific information element is used to carry "\
2698        "information not defined in the standard within a single "\
2699        "defined format"
2700
2701        vs=[]
2702        gen_get_element=self._get_elements_generator(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC)
2703        try:
2704            while 1:
2705                s=gen_get_element.next()
2706
2707                if s is None:
2708                    raise Exception("gen_get_element salio con None!!!")
2709
2710                # OUI is 3 bytes
2711                oui=s[:3]
2712                data=s[3:]
2713                vs.append((oui,data))
2714        except StopIteration:
2715            pass
2716
2717        return vs
2718
2719    def add_vendor_specific(self, oui, data):
2720        "Set the 802.11 Management Vendor Specific element. "\
2721        "The Vendor Specific information element is used to carry "\
2722        "information not defined in the standard within a single "\
2723        "defined format"
2724
2725        # 3 is the OUI length
2726        max_data_len=255-3
2727        data_len=len(data)
2728
2729        if data_len>max_data_len:
2730            raise Exception("data allow up to %d bytes long" % max_data)
2731        if len(oui) > 3:
2732            raise Exception("oui is three bytes long")
2733
2734        self._set_element(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC,oui+data, replace=False)
2735
2736class Dot11ManagementDisassociation(Dot11ManagementDeauthentication):
2737    '802.11 Management Disassociation Frame'
2738
2739    def __init__(self, aBuffer = None):
2740        Dot11ManagementDeauthentication.__init__(self, aBuffer)
2741
2742class Dot11ManagementAssociationRequest(Dot11ManagementHelper):
2743    '802.11 Management Association Request Frame'
2744
2745    __HEADER_BASE_SIZE = 4 # minimal header size
2746
2747    def __init__(self, aBuffer = None):
2748        header_size = self.__HEADER_BASE_SIZE
2749        tail_size = 0
2750        Dot11ManagementHelper.__init__(self, header_size, tail_size, aBuffer)
2751
2752    def get_capabilities(self):
2753        'Return the 802.11 Management Association Request Frame \'Capability information\' field. '
2754        b = self.header.get_word(0, "<")
2755        return b
2756
2757    def set_capabilities(self, value):
2758        'Set the 802.11 Management Association Request Frame \'Capability Information\' field'
2759        # set the bits
2760        nb = value & 0xFFFF
2761        self.header.set_word(0, nb, "<")
2762
2763    def get_listen_interval(self):
2764        'Return the 802.11 Management Association Request Frame \'Listen Interval\' field. '
2765        b = self.header.get_word(2, "<")
2766        return b
2767
2768    def set_listen_interval(self, value):
2769        'Set the 802.11 Management Association Request Frame \'Listen Interval\' field'
2770        self.header.set_word(2, value, "<")
2771
2772    def get_ssid(self):
2773        "Get the 802.11 Management SSID element. "\
2774        "The SSID element indicates the identity of an ESS or IBSS."
2775        return self._get_element(DOT11_MANAGEMENT_ELEMENTS.SSID)
2776
2777    def set_ssid(self, ssid):
2778        self._set_element(DOT11_MANAGEMENT_ELEMENTS.SSID,ssid)
2779
2780    def get_supported_rates(self, human_readable=False):
2781        "Get the 802.11 Management Supported Rates element. "\
2782        "Specifies up to eight rates, then an Extended Supported Rate element "\
2783        "shall be generated to specify the remaining supported rates."\
2784        "If human_readable is True, the rates are returned in Mbit/sec"
2785        s=self._get_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES)
2786        if s is None:
2787            return None
2788
2789        rates=struct.unpack('%dB'%len(s),s)
2790        if not human_readable:
2791            return rates
2792
2793        rates_Mbs=tuple(map(lambda x: (x&0x7F)*0.5,rates))
2794        return rates_Mbs
2795
2796    def set_supported_rates(self, rates):
2797        "Set the 802.11 Management Supported Rates element. "\
2798        "Specifies a tuple or list with up to eight rates, then an "\
2799        "Extended Supported Rate element shall be generated to specify "\
2800        "the remaining supported rates."
2801        qty_rates=len(rates)
2802        if qty_rates>8:
2803            raise Exception("requires up to eight rates")
2804        rates_string=struct.pack('B'*qty_rates,*rates)
2805        self._set_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES,rates_string)
2806
2807    def get_rsn(self):
2808        "Get the 802.11 Management Robust Security Network element."
2809        s = self._get_element(DOT11_MANAGEMENT_ELEMENTS.RSN)
2810        if s is None:
2811            return None
2812        return s
2813
2814    def set_rsn(self, data):
2815        "Set the 802.11 Management Robust Security Network element."
2816        self._set_element(DOT11_MANAGEMENT_ELEMENTS.RSN, data)
2817
2818    def get_vendor_specific(self):
2819        "Get the 802.11 Management Vendor Specific elements "\
2820        "as a list of tuples."
2821        "The Vendor Specific information element is used to carry "\
2822        "information not defined in the standard within a single "\
2823        "defined format"
2824
2825        vs=[]
2826        gen_get_element=self._get_elements_generator(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC)
2827        try:
2828            while 1:
2829                s=gen_get_element.next()
2830
2831                if s is None:
2832                    raise Exception("gen_get_element salio con None!!!")
2833
2834                # OUI is 3 bytes
2835                oui=s[:3]
2836                data=s[3:]
2837                vs.append((oui,data))
2838        except StopIteration:
2839            pass
2840
2841        return vs
2842
2843    def add_vendor_specific(self, oui, data):
2844        "Set the 802.11 Management Vendor Specific element. "\
2845        "The Vendor Specific information element is used to carry "\
2846        "information not defined in the standard within a single "\
2847        "defined format"
2848
2849        # 3 is the OUI length
2850        max_data_len=255-3
2851        data_len=len(data)
2852
2853        if data_len>max_data_len:
2854            raise Exception("data allow up to %d bytes long" % max_data)
2855        if len(oui) > 3:
2856            raise Exception("oui is three bytes long")
2857
2858        self._set_element(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC,oui+data, replace=False)
2859
2860class Dot11ManagementAssociationResponse(Dot11ManagementHelper):
2861    '802.11 Management Association Response Frame'
2862
2863    __HEADER_BASE_SIZE = 6 # minimal header size
2864
2865    def __init__(self, aBuffer = None):
2866        header_size = self.__HEADER_BASE_SIZE
2867        tail_size = 0
2868        Dot11ManagementHelper.__init__(self, header_size, tail_size, aBuffer)
2869
2870    def get_capabilities(self):
2871        'Return the 802.11 Management Association Response Frame \'Capability information\' field. '
2872        b = self.header.get_word(0, "<")
2873        return b
2874
2875    def set_capabilities(self, value):
2876        'Set the 802.11 Management Association Response Frame \'Capability Information\' field'
2877        # set the bits
2878        nb = value & 0xFFFF
2879        self.header.set_word(0, nb, "<")
2880
2881    def get_status_code(self):
2882        'Return the 802.11 Management Association Response Frame \'Status Code\' field. '
2883        b = self.header.get_word(2, "<")
2884        return b
2885
2886    def set_status_code(self, value):
2887        'Set the 802.11 Management Association Response Frame \'Status Code\' field'
2888        self.header.set_word(2, value, "<")
2889
2890    def get_association_id(self):
2891        'Return the 802.11 Management Association Response Frame \'Association Id\' field. '
2892        b = self.header.get_word(4, "<")
2893        return b
2894
2895    def set_association_id(self, value):
2896        'Set the 802.11 Management Association Response Frame \'Association Id\' field'
2897        self.header.set_word(4, value, "<")
2898
2899    def get_supported_rates(self, human_readable=False):
2900        "Get the 802.11 Management Supported Rates element. "\
2901        "Specifies up to eight rates, then an Extended Supported Rate element "\
2902        "shall be generated to specify the remaining supported rates."\
2903        "If human_readable is True, the rates are returned in Mbit/sec"
2904        s=self._get_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES)
2905        if s is None:
2906            return None
2907
2908        rates=struct.unpack('%dB'%len(s),s)
2909        if not human_readable:
2910            return rates
2911
2912        rates_Mbs=tuple(map(lambda x: (x&0x7F)*0.5,rates))
2913        return rates_Mbs
2914
2915    def set_supported_rates(self, rates):
2916        "Set the 802.11 Management Supported Rates element. "\
2917        "Specifies a tuple or list with up to eight rates, then an "\
2918        "Extended Supported Rate element shall be generated to specify "\
2919        "the remaining supported rates."
2920        qty_rates=len(rates)
2921        if qty_rates>8:
2922            raise Exception("requires up to eight rates")
2923        rates_string=struct.pack('B'*qty_rates,*rates)
2924        self._set_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES,rates_string)
2925
2926    def get_vendor_specific(self):
2927        "Get the 802.11 Management Vendor Specific elements "\
2928        "as a list of tuples."
2929        "The Vendor Specific information element is used to carry "\
2930        "information not defined in the standard within a single "\
2931        "defined format"
2932
2933        vs=[]
2934        gen_get_element=self._get_elements_generator(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC)
2935        try:
2936            while 1:
2937                s=gen_get_element.next()
2938
2939                if s is None:
2940                    raise Exception("gen_get_element salio con None!!!")
2941
2942                # OUI is 3 bytes
2943                oui=s[:3]
2944                data=s[3:]
2945                vs.append((oui,data))
2946        except StopIteration:
2947            pass
2948
2949        return vs
2950
2951    def add_vendor_specific(self, oui, data):
2952        "Set the 802.11 Management Vendor Specific element. "\
2953        "The Vendor Specific information element is used to carry "\
2954        "information not defined in the standard within a single "\
2955        "defined format"
2956
2957        # 3 is the OUI length
2958        max_data_len=255-3
2959        data_len=len(data)
2960        if data_len>max_data_len:
2961            raise Exception("data allow up to %d bytes long" % max_data)
2962        if len(oui) > 3:
2963            raise Exception("oui is three bytes long")
2964
2965        self._set_element(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC,oui+data, replace=False)
2966
2967class Dot11ManagementReassociationRequest(Dot11ManagementHelper):
2968    '802.11 Management Reassociation Request Frame'
2969
2970    __HEADER_BASE_SIZE = 10 # minimal header size
2971
2972    def __init__(self, aBuffer = None):
2973        header_size = self.__HEADER_BASE_SIZE
2974        tail_size = 0
2975        Dot11ManagementHelper.__init__(self, header_size, tail_size, aBuffer)
2976
2977    def get_capabilities(self):
2978        'Return the 802.11 Management Reassociation Request Frame \'Capability information\' field. '
2979        b = self.header.get_word(0, "<")
2980        return b
2981
2982    def set_capabilities(self, value):
2983        'Set the 802.11 Management Reassociation Request Frame \'Capability Information\' field'
2984        # set the bits
2985        nb = value & 0xFFFF
2986        self.header.set_word(0, nb, "<")
2987
2988    def get_listen_interval(self):
2989        'Return the 802.11 Management Reassociation Request Frame \'Listen Interval\' field. '
2990        b = self.header.get_word(2, "<")
2991        return b
2992
2993    def set_listen_interval(self, value):
2994        'Set the 802.11 Management Reassociation Request Frame \'Listen Interval\' field'
2995        self.header.set_word(2, value, "<")
2996
2997    def get_current_ap(self):
2998        'Return the 802.11 Management Reassociation Request Frame \'Current AP\' field.'
2999        return self.header.get_bytes()[4:10]
3000
3001    def set_current_ap(self, value):
3002        'Set the 802.11 Management Reassociation Request Frame \'Current AP\' field'
3003        for i in range(0, 6):
3004            self.header.set_byte(4+i, value[i])
3005
3006    def get_ssid(self):
3007        "Get the 802.11 Management SSID element. "\
3008        "The SSID element indicates the identity of an ESS or IBSS."
3009        return self._get_element(DOT11_MANAGEMENT_ELEMENTS.SSID)
3010
3011    def set_ssid(self, ssid):
3012        self._set_element(DOT11_MANAGEMENT_ELEMENTS.SSID,ssid)
3013
3014    def get_supported_rates(self, human_readable=False):
3015        "Get the 802.11 Management Supported Rates element. "\
3016        "Specifies up to eight rates, then an Extended Supported Rate element "\
3017        "shall be generated to specify the remaining supported rates."\
3018        "If human_readable is True, the rates are returned in Mbit/sec"
3019        s=self._get_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES)
3020        if s is None:
3021            return None
3022
3023        rates=struct.unpack('%dB'%len(s),s)
3024        if not human_readable:
3025            return rates
3026
3027        rates_Mbs=tuple(map(lambda x: (x&0x7F)*0.5,rates))
3028        return rates_Mbs
3029
3030    def set_supported_rates(self, rates):
3031        "Set the 802.11 Management Supported Rates element. "\
3032        "Specifies a tuple or list with up to eight rates, then an "\
3033        "Extended Supported Rate element shall be generated to specify "\
3034        "the remaining supported rates."
3035        qty_rates=len(rates)
3036        if qty_rates>8:
3037            raise Exception("requires up to eight rates")
3038        rates_string=struct.pack('B'*qty_rates,*rates)
3039        self._set_element(DOT11_MANAGEMENT_ELEMENTS.SUPPORTED_RATES,rates_string)
3040
3041    def get_rsn(self):
3042        "Get the 802.11 Management Robust Security Network element."
3043        s = self._get_element(DOT11_MANAGEMENT_ELEMENTS.RSN)
3044        if s is None:
3045            return None
3046        return s
3047
3048    def set_rsn(self, data):
3049        "Set the 802.11 Management Robust Security Network element."
3050        self._set_element(DOT11_MANAGEMENT_ELEMENTS.RSN, data)
3051
3052    def get_vendor_specific(self):
3053        "Get the 802.11 Management Vendor Specific elements "\
3054        "as a list of tuples."
3055        "The Vendor Specific information element is used to carry "\
3056        "information not defined in the standard within a single "\
3057        "defined format"
3058
3059        vs=[]
3060        gen_get_element=self._get_elements_generator(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC)
3061        try:
3062            while 1:
3063                s=gen_get_element.next()
3064
3065                if s is None:
3066                    raise Exception("gen_get_element salio con None!!!")
3067
3068                # OUI is 3 bytes
3069                oui=s[:3]
3070                data=s[3:]
3071                vs.append((oui,data))
3072        except StopIteration:
3073            pass
3074
3075        return vs
3076
3077    def add_vendor_specific(self, oui, data):
3078        "Set the 802.11 Management Vendor Specific element. "\
3079        "The Vendor Specific information element is used to carry "\
3080        "information not defined in the standard within a single "\
3081        "defined format"
3082
3083        # 3 is the OUI length
3084        max_data_len=255-3
3085        data_len=len(data)
3086
3087        if data_len>max_data_len:
3088            raise Exception("data allow up to %d bytes long" % max_data)
3089        if len(oui) > 3:
3090            raise Exception("oui is three bytes long")
3091
3092        self._set_element(DOT11_MANAGEMENT_ELEMENTS.VENDOR_SPECIFIC,oui+data, replace=False)
3093
3094class Dot11ManagementReassociationResponse(Dot11ManagementAssociationResponse):
3095    '802.11 Management Reassociation Response Frame'
3096
3097    def __init__(self, aBuffer = None):
3098        Dot11ManagementAssociationResponse.__init__(self, aBuffer)
3099