def isDown(self, host, timeout=1.0): """ Check if the host passed as argument is down. This check takes approximately 10 sec. @param host: IPv4 or hostname @type host: string @param timeout: time to wait in second (default=1s) @type timeout: float @return: no response event @rtype: templatemessage """ if not ( isinstance(timeout, int) or isinstance(timeout, float) ) or isinstance(timeout,bool): raise TestAdapterLib.ValueException(TestAdapterLib.caller(), "timeout argument is not a float or integer (%s)" % type(timeout) ) tpl = templates.pinger(destination=host, more=templates.ping(), type=templates.icmp() ) self.logSentEvent( shortEvt = "ping", tplEvt = tpl ) pa = PingAgent(self, host, self.nbPing) pa.start() # synchronization pa.join() ret= pa.isup if ret: tpl = templates.pinger(destination=host, more=templates.alive(), type=templates.icmp() ) self.logRecvEvent( shortEvt = "alive", tplEvt = tpl ) else: tpl = templates.pinger(destination=host, more=templates.no_response(), type=templates.icmp() ) self.logRecvEvent( shortEvt = "no response", tplEvt = tpl ) expected = templates.pinger(destination=host, more=templates.no_response(), type=templates.icmp() ) evt = self.received( expected = expected, timeout = timeout ) return evt
def areDown(self, hosts, timeout=1.0): """ Check if all hosts passed as argument are down. This check takes approximately 10 sec. @param hosts: list of IPv4 or hostname @type hosts: list @param timeout: time to wait in second (default=1s) @type timeout: float @return: True if all hosts are down, False otherwise @rtype: boolean """ TestAdapterLib.check_timeout(caller=TestAdapterLib.caller(), timeout=timeout) th = [] # parallelize for i in xrange(len(hosts)): tpl = templates.pinger(destination=hosts[i], more=templates.ping(), type=templates.icmp()) self.logSentEvent(shortEvt="ping", tplEvt=tpl) pa = PingAgent(self, hosts[i], self.nbPing) pa.start() th.append(pa) # synchronize for pa in th: pa.join() # compute final result ret = True for pa in th: if pa.isup: tpl = templates.pinger(destination=pa.host, more=templates.alive(), type=templates.icmp()) self.logRecvEvent(shortEvt="alive", tplEvt=tpl) else: tpl = templates.pinger(destination=pa.host, more=templates.no_response(), type=templates.icmp()) self.logRecvEvent(shortEvt="no response", tplEvt=tpl) expected = templates.pinger(destination=pa.host, more=templates.no_response(), type=templates.icmp()) evt = self.received(expected=expected, timeout=timeout) if evt is None: ret = False return ret
def isUp(self, host, timeout=1.0): """ Check if the host passed as argument is up. This check takes approximately 10 sec. @param host: IPv4 or hostname @type host: string @param timeout: time to wait in second (default=1s) @type timeout: float @return: alive event @rtype: templatemessage """ TestAdapterLib.check_timeout(caller=TestAdapterLib.caller(), timeout=timeout) tpl = templates.pinger(destination=host, more=templates.ping(), type=templates.icmp()) self.logSentEvent(shortEvt="ping", tplEvt=tpl) pa = PingAgent(self, host, self.nbPing) pa.start() # synchronization pa.join() ret = pa.isup if not ret: tpl = templates.pinger(destination=host, more=templates.no_response(), type=templates.icmp()) self.logRecvEvent(shortEvt="no response", tplEvt=tpl) else: tpl = templates.pinger(destination=host, more=templates.alive(), type=templates.icmp()) self.logRecvEvent(shortEvt="alive", tplEvt=tpl) expected = templates.pinger(destination=host, more=templates.alive(), type=templates.icmp()) evt = self.received(expected=expected, timeout=timeout) return evt
def decode(self, icmp): """ """ ## Extract the fixed header = 4 octets ## between error and query messages icmp_len = 4 icmp_hdr = struct.unpack('!2BH', icmp[:icmp_len]) ## Extract ICMP Fields ## Type icmp_type = icmp_hdr[0] type_string = None if MESSAGES.has_key(int(icmp_type)): type_string = MESSAGES[int(icmp_type)].lower() summary = type_string.title() ## Code icmp_code = icmp_hdr[1] ## Checksum icmp_chksum = icmp_hdr[2] icmp_chksum_hex = "0x%0.4X" % icmp_chksum next_data = icmp[icmp_len:] # checksum is correct ? sum_computed = self.checksum.compute(data=icmp, checksum_offset=1) sum_status = 'incorrect, should be 0x%0.4X' % sum_computed if icmp_chksum == sum_computed: sum_status = 'correct' self.debug('ip checksum computed') ## Decode OK, create template icmp_tpl = templates.icmp(tp=str(icmp_type), tp_str=str(type_string), code=str(icmp_code), sum=str(icmp_chksum_hex), sum_int=str(icmp_chksum), sum_status=sum_status) ## add the raw data to the layer icmp_tpl.addRaw(icmp) ## encode query if int(icmp_type) in [ ECHO, ECHO_REPLY, INFORMATION, INFORMATION_REPLY, TIMESTAMP, TIMESTAMP_REPLY, MASK, MASK_REPLY ]: ## start with the common part # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Identifier | Sequence Number | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ query_len = 4 icmp_query = struct.unpack('!HH', next_data[:query_len]) ## Identifier: If code = 0, an identifier to aid in matching echos and replies, may be zero echo_id = icmp_query[0] tpl_id = TestTemplatesLib.TemplateLayer(name="0x%0.4X" % echo_id) tpl_id.addKey(name='integer', data=str(echo_id)) icmp_tpl.addKey('identifier', tpl_id) ## Sequence Number: If code = 0, a sequence number to aid in matching echos and replies, may be zero. echo_seq = icmp_query[1] tpl_seq = TestTemplatesLib.TemplateLayer(name="0x%0.4X" % echo_seq) tpl_seq.addKey(name='integer', data=str(echo_seq)) icmp_tpl.addKey('sequence-number', tpl_seq) ## Echo or Echo Reply Message if int(icmp_type) in [ECHO, ECHO_REPLY]: # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Data ... # +-+-+-+-+- echo_data = next_data[query_len:] tpl_data = TestTemplatesLib.TemplateLayer(name=echo_data) tpl_data.addKey(name='length', data=str(len(echo_data))) icmp_tpl.addKey('data', tpl_data) ## Timestamp or Timestamp Reply Message if int(icmp_type) in [TIMESTAMP, TIMESTAMP_REPLY]: # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Originate Timestamp | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Receive Timestamp | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Transmit Timestamp | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ timestamp_len = 12 icmp_timestamp = struct.unpack( '!3I', next_data[query_len:query_len + timestamp_len]) data_upper = next_data[query_len + timestamp_len:] orig = icmp_timestamp[0] tpl_orig = TestTemplatesLib.TemplateLayer(name=str(orig)) tpl_orig.addKey(name='time', data=self.timestamp2human(orig)) tpl_orig.addKey(name='hex', data="0x%0.6X" % orig) icmp_tpl.addKey('originate-timestamp', tpl_orig) rx = icmp_timestamp[1] tpl_rx = TestTemplatesLib.TemplateLayer(name=str(rx)) tpl_rx.addKey(name='time', data=self.timestamp2human(rx)) tpl_rx.addKey(name='hex', data="0x%0.6X" % rx) icmp_tpl.addKey('receive-timestamp', tpl_rx) tx = icmp_timestamp[2] tpl_tx = TestTemplatesLib.TemplateLayer(name=str(tx)) tpl_tx.addKey(name='time', data=self.timestamp2human(tx)) tpl_tx.addKey(name='hex', data="0x%0.6X" % tx) icmp_tpl.addKey('transmit-timestamp', tpl_tx) # add padding if exist if len(data_upper): icmp_tpl.addKey('padding', data_upper) icmp_tpl.addKey('padding-length', len(data_upper)) ## Address Mask Request or Address Mask Reply if int(icmp_type) in [MASK, MASK_REPLY]: # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Address Mask | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ mask_len = 4 icmp_mask = struct.unpack( '!4B', next_data[query_len:query_len + mask_len]) data_upper = next_data[query_len + mask_len:] ## Address Mask: A 32-bit mask mask = icmp_mask[0:5] mask_addr = '.'.join([str(d) for d in mask]) tpl_mask = TestTemplatesLib.TemplateLayer(name=str(mask_addr)) icmp_tpl.addKey('mask', tpl_mask) # add padding if exist if len(data_upper): icmp_tpl.addKey('padding', data_upper) icmp_tpl.addKey('padding-length', len(data_upper)) elif int(icmp_type) in [ REDIRECT, SOURCE_QUENCH, PARAMETER_PROBLEM, TIME_EXCEEDED, DESTINATION_UNREACHABLE ]: ## Redirect Message if int(icmp_type) == REDIRECT: # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Gateway Internet Address | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Internet Header + 64 bits of Original Data Datagram | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ icmp_redirect = struct.unpack('!4B', next_data[:4]) gw = icmp_redirect[0] gw_addr = '.'.join([str(d) for d in gw]) tpl_gw_addr = TestTemplatesLib.TemplateLayer(name=str(gw_addr)) icmp_tpl.addKey('gateway', tpl_gw_addr) redirect_data = next_data[4:] tpl_data = TestTemplatesLib.TemplateLayer(name=redirect_data) tpl_data.addKey(name='length', data=str(len(redirect_data))) icmp_tpl.addKey('data', tpl_data) if CODES_REDIRECT.has_key(icmp_code): code_tpl = icmp_tpl.get('code') code_tpl.addKey('string', CODES_REDIRECT[icmp_code].lower()) ## Source Quench Message if int(icmp_type) == SOURCE_QUENCH: # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | unused | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Internet Header + 64 bits of Original Data Datagram | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ icmp_quench = struct.unpack('!I', next_data[:4]) unused = icmp_quench[0] tpl_unused = TestTemplatesLib.TemplateLayer(name=str(unused)) icmp_tpl.addKey('unused', tpl_unused) quench_data = next_data[4:] tpl_data = TestTemplatesLib.TemplateLayer(name=quench_data) tpl_data.addKey(name='length', data=str(len(quench_data))) icmp_tpl.addKey('data', tpl_data) ## Parameter Problem Message if int(icmp_type) == PARAMETER_PROBLEM: # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Pointer | unused | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Internet Header + 64 bits of Original Data Datagram | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ icmp_param = struct.unpack('!I', next_data[:4]) pointer = (icmp_param[0] >> 24) tpl_pointer = TestTemplatesLib.TemplateLayer(name=str(pointer)) icmp_tpl.addKey('pointer', tpl_pointer) unused = (icmp_param[0] & 0xFFFFFF) tpl_unused = TestTemplatesLib.TemplateLayer(name=str(unused)) icmp_tpl.addKey('unused', tpl_unused) problem_data = next_data[4:] tpl_data = TestTemplatesLib.TemplateLayer(name=problem_data) tpl_data.addKey(name='length', data=str(len(problem_data))) icmp_tpl.addKey('data', tpl_data) ## Time Exceeded Message if int(icmp_type) == TIME_EXCEEDED: # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | unused | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Internet Header + 64 bits of Original Data Datagram | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ icmp_exceeded = struct.unpack('!I', next_data[:4]) unused = icmp_exceeded[0] tpl_unused = TestTemplatesLib.TemplateLayer(name=str(unused)) icmp_tpl.addKey('unused', tpl_unused) exceeded_data = next_data[4:] tpl_data = TestTemplatesLib.TemplateLayer(name=exceeded_data) tpl_data.addKey(name='length', data=str(len(exceeded_data))) icmp_tpl.addKey('data', tpl_data) if CODES_TIME_EXCEEDED.has_key(icmp_code): code_tpl = icmp_tpl.get('code') code_tpl.addKey('string', CODES_TIME_EXCEEDED[icmp_code].lower()) ## Destination Unreachable Message if int(icmp_type) == DESTINATION_UNREACHABLE: # 0 1 2 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | unused | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Internet Header + 64 bits of Original Data Datagram | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ icmp_unreach = struct.unpack('!I', next_data[:4]) unused = icmp_unreach[0] tpl_unused = TestTemplatesLib.TemplateLayer(name=str(unused)) icmp_tpl.addKey('unused', tpl_unused) unreach_data = next_data[4:] tpl_data = TestTemplatesLib.TemplateLayer(name=unreach_data) tpl_data.addKey(name='length', data=str(len(unreach_data))) icmp_tpl.addKey('data', tpl_data) if CODES_UNREACHABLE.has_key(icmp_code): code_tpl = icmp_tpl.get('code') code_tpl.addKey('string', CODES_UNREACHABLE[icmp_code].lower()) else: # set summary summary = 'Unknown icmp message' echo_data = next_data[icmp_len:] tpl_data = TestTemplatesLib.TemplateLayer(name=echo_data) tpl_data.addKey(name='length', data=str(len(echo_data))) icmp_tpl.addKey('data', tpl_data) return icmp_tpl, summary
def hasReceivedPacket(self, timeout=1.0, icmpCode=None, icmpType=None, icmpId=None, icmpSeq=None, icmpData=None, icmpTimeOrig=None, icmpTimeReceive=None, icmpTimeTransmit=None, icmpMask=None): """ Waits to receive data event until the end of the timeout @param timeout: time max to wait to receive event in second (default=1s) @type timeout: float @param icmpCode: icmp code @type icmpCode: none/string/operators @param icmpType: icmp type @type icmpType: none/string/operators @param icmpId: icmp identifier @type icmpId: none/string/operators @param icmpSeq: icmp sequence number @type icmpSeq: none/string/operators @param icmpData: icmp data @type icmpData: none/string/operators @param icmpTimeOrig: originate timestamp @type icmpTimeOrig: none/string/operators @param icmpTimeReceive: receive timestamp @type icmpTimeReceive: none/string/operators @param icmpTimeTransmit: transmit timestamp @type icmpTimeTransmit: none/string/operators @param icmpMask: icmp mask @type icmpMask: none/string/operators @return: an event matching with the template or None otherwise @rtype: templatemessage """ TestAdapterLib.check_timeout(caller=TestAdapterLib.caller(), timeout=timeout) expected = TestTemplatesLib.TemplateMessage() if self.cfg['agent-support']: layer_agent= TestTemplatesLib.TemplateLayer('AGENT') layer_agent.addKey(name='name', data=self.cfg['agent']['name'] ) layer_agent.addKey(name='type', data=self.cfg['agent']['type'] ) expected.addLayer( layer_agent ) # add layer ethernet layer_ether = AdapterEthernet.ethernet() expected.addLayer(layer=layer_ether) # add layer ip layer_ip = AdapterIP.ip() expected.addLayer(layer=layer_ip) # add layer icmp layer_icmp = templates.icmp(code=icmpCode, tp=icmpType, id=icmpId, seq_num=icmpSeq, data=icmpData, time_orig=icmpTimeOrig, time_rx=icmpTimeReceive, time_tx=icmpTimeTransmit, mask=icmpMask ) expected.addLayer(layer=layer_icmp) # try to match the template evt = self.received( expected = expected, timeout = timeout ) return evt
def sendPacket(self, destIp, type=8, code=0, checksum=None, identifier=None, sequenceNumber=None, data=None, destMac=None, timeOrig=None, timeReceive=None, timeTransmit=None, mask=None, gw=None, unused=None, pointer=None): """ Send ICMP packet. The destination MAC address is automatically resolved if not passed on argument. @param destIp: destination ip @type destIp: string @param type: icmp type (default=8) @type type: integer @param code: icmp code (default=0) @type code: integer @param checksum: icmp checksum @type checksum: none/string @param identifier: icmp identifier @type identifier: none/string @param sequenceNumber: icmp sequence number @type sequenceNumber: none/string @param data: icmp data @type data: none/string @param destMac: destination mac address @type destMac: none/string @param timeOrig: originate timestamp @type timeOrig: none/string @param timeReceive: receive timestamp @type timeReceive: none/string @param timeTransmit: transmit timestamp @type timeTransmit: none/string @param mask: netmask @type mask: none/string @param gw: gateway internet address @type gw: none/string @param unused: unused bytes @type unused: none/string @param pointer: pointer @type pointer: none/string """ try: icmp_tpl = templates.icmp(code=code, id=identifier, seq_num=sequenceNumber, sum=checksum, data=data, tp=type, time_orig=timeOrig, time_rx=timeReceive, time_tx=timeTransmit, mask=mask, gw_addr=gw, unused=unused, pointer=pointer) except Exception as e: raise Exception('Cannot prepare icmp template: %s' % str(e)) else: try: (pkt, summary) = self.icmpCodec.encode(icmp_tpl=icmp_tpl) except Exception as e: raise Exception("Cannot encode icmp: %s" % str(e)) else: # Send packet try: lower = self.ip.sendDatagram(dstMac=destMac, dstIp=destIp, data=pkt, protocol=AdapterIP.ICMP) except Exception as e: raise Exception("Unable to send datagram: %s" % str(e)) else: lower.addLayer( icmp_tpl ) icmp_tpl.addRaw(raw=pkt) self.logSentEvent( shortEvt = summary, tplEvt = lower )