diff --git a/.hgtags b/.hgtags index e502ba1c0c1a2dad538e6b84f2506e1eaf763640..d37c81115b4a45e69996fc88eef2a502dcd64b20 100644 --- a/.hgtags +++ b/.hgtags @@ -484,3 +484,4 @@ e164cf76ae7dec36133ef9936c0d927a35d92691 v1.0.6.1 e452bf206aeb79768aa56cf8f781af1cce495532 v1.1.0 f88d999102206f461f9c602708ea6d1be5ecfe7a v1.1.1 b4343698bde097148d6fc9b28bea599cc6f41471 v1.2.0 +8a166f01bceeb9cd3ae5babab0b262362e97b5f6 v1.2.0.1 diff --git a/scapy.py b/scapy.py index 8be65eb243aa7572880122b0521176d59b190e26..22157bc8d66563d76fedca55b92c25bd0d0f63fe 100755 --- a/scapy.py +++ b/scapy.py @@ -23,7 +23,7 @@ from __future__ import generators import os -VERSION = "1.2.0" +VERSION = "1.2.0.1" DEFAULT_CONFIG_FILE = os.path.join(os.environ["HOME"], ".scapy_startup.py") @@ -6910,7 +6910,9 @@ class Dot11(Packet): def mysummary(self): return self.sprintf("802.11 %Dot11.type% %Dot11.subtype% %Dot11.addr2% > %Dot11.addr1%") def guess_payload_class(self, payload): - if self.FCfield & 0x40: + if self.type == 0x02 and (self.subtype >= 0x08 and self.subtype <=0xF and self.subtype != 0xD): + return Dot11QoS + elif self.FCfield & 0x40: return Dot11WEP else: return Packet.guess_payload_class(self, payload) @@ -6946,6 +6948,20 @@ class Dot11(Packet): self.payload=self.payload.payload +class Dot11QoS(Packet): + name = "802.11 QoS" + fields_desc = [ BitField("TID",None,4), + BitField("EOSP",None,1), + BitField("Ack Policy",None,2), + BitField("Reserved",None,1), + ByteField("TXOP",None) ] + def guess_payload_class(self, payload): + if isinstance(self.underlayer, Dot11): + if self.underlayer.FCfield & 0x40: + return Dot11WEP + return Packet.guess_payload_class(self, payload) + + capability_list = [ "res8", "res9", "short-slot", "res11", "res12", "DSSS-OFDM", "res14", "res15", "ESS", "IBSS", "CFP", "CFP-req", @@ -6972,7 +6988,7 @@ class Dot11Beacon(Packet): class Dot11Elt(Packet): name = "802.11 Information Element" fields_desc = [ ByteEnumField("ID", 0, {0:"SSID", 1:"Rates", 2: "FHset", 3:"DSset", 4:"CFset", 5:"TIM", 6:"IBSSset", 16:"challenge", - 42:"ERPinfo", 47:"ERPinfo", 48:"RSNinfo", 50:"ESRates",221:"vendor",68:"reserved"}), + 42:"ERPinfo", 46:"QoS Capability", 47:"ERPinfo", 48:"RSNinfo", 50:"ESRates",221:"vendor",68:"reserved"}), FieldLenField("len", None, "info", "B"), StrLenField("info", "", length_from=lambda x:x.len) ] def mysummary(self): @@ -8881,6 +8897,7 @@ bind_layers( GPRS, IP, ) bind_layers( PrismHeader, Dot11, ) bind_layers( RadioTap, Dot11, ) bind_layers( Dot11, LLC, type=2) +bind_layers( Dot11QoS, LLC, ) bind_layers( PPP, IP, proto=33) bind_layers( Ether, LLC, type=122) bind_layers( Ether, Dot1Q, type=33024) @@ -11712,12 +11729,13 @@ class Automaton: while 1: t = time.time()-t0 - if next_timeout is None: - remain = None - else: + if next_timeout is not None: if next_timeout <= t: self.run_condition(timeout_func, *state_output) next_timeout,timeout_func = expirations.next() + if next_timeout is None: + remain = None + else: remain = next_timeout-t r,_,_ = select([l],[],[],remain) @@ -11937,7 +11955,7 @@ class TFTP_WRQ_server(Automaton): @ATMT.state(initial=1) def BEGIN(self): self.blksize=512 - self.blk=0 + self.blk=1 self.filedata="" self.my_tid = self.sport or random.randint(10000,65500) bind_bottom_up(UDP, TFTP, dport=self.my_tid) @@ -11959,7 +11977,7 @@ class TFTP_WRQ_server(Automaton): self.last_packet = self.l3/TFTP_ACK(block=0) self.send(self.last_packet) else: - opt = [x for x in options.options if x.oname == "BLKSIZE"] + opt = [x for x in options.options if x.oname.upper() == "BLKSIZE"] if opt: self.blksize = int(opt[0].value) self.debug(2,"Negotiated new blksize at %i" % self.blksize) @@ -11968,8 +11986,13 @@ class TFTP_WRQ_server(Automaton): @ATMT.state() def WAIT_DATA(self): - self.blk += 1 + pass + @ATMT.timeout(WAIT_DATA, 1) + def resend_ack(self): + self.send(self.last_packet) + raise self.WAIT_DATA() + @ATMT.receive_condition(WAIT_DATA) def receive_data(self, pkt): if TFTP_DATA in pkt: @@ -11987,6 +12010,7 @@ class TFTP_WRQ_server(Automaton): self.filedata += data.load if len(data.load) < self.blksize: raise self.END() + self.blk += 1 raise self.WAIT_DATA() @ATMT.state(final=1) @@ -11996,10 +12020,14 @@ class TFTP_WRQ_server(Automaton): class TFTP_RRQ_server(Automaton): - def parse_args(self, store=None, joker=None, ip=None, sport=None, serve_one=False, **kargs): + def parse_args(self, store=None, joker=None, dir=None, ip=None, sport=None, serve_one=False, **kargs): Automaton.parse_args(self,**kargs) if store is None: store = {} + if dir is not None: + self.dir = os.path.join(os.path.abspath(dir),"") + else: + self.dir = None self.store = store self.joker = joker self.ip = ip @@ -12025,10 +12053,33 @@ class TFTP_RRQ_server(Automaton): @ATMT.state() def RECEIVED_RRQ(self, pkt): ip = pkt[IP] + options = pkt[TFTP_Options] self.l3 = IP(src=ip.dst, dst=ip.src)/UDP(sport=self.my_tid, dport=ip.sport)/TFTP() self.filename = pkt[TFTP_RRQ].filename self.blk=1 - self.data = self.store.get(self.filename, self.joker) + self.data = None + if self.filename in self.store: + self.data = self.store[self.filename] + elif self.dir is not None: + fn = os.path.abspath(os.path.join(self.dir, self.filename)) + if fn.startswith(self.dir): # Check we're still in the server's directory + try: + self.data=open(fn).read() + except IOError: + pass + if self.data is None: + self.data = self.joker + + if options: + opt = [x for x in options.options if x.oname.upper() == "BLKSIZE"] + if opt: + self.blksize = int(opt[0].value) + self.debug(2,"Negotiated new blksize at %i" % self.blksize) + self.last_packet = self.l3/TFTP_OACK()/TFTP_Options(options=opt) + self.send(self.last_packet) + + + @ATMT.condition(RECEIVED_RRQ) def file_in_store(self): @@ -12048,7 +12099,7 @@ class TFTP_RRQ_server(Automaton): def SEND_FILE(self): self.send(self.l3/TFTP_DATA(block=self.blk)/self.data[(self.blk-1)*self.blksize:self.blk*self.blksize]) - @ATMT.timeout(SEND_FILE, 113) + @ATMT.timeout(SEND_FILE, 3) def timeout_waiting_ack(self): raise self.SEND_FILE()