def buildMessage(msgtype, token, code, messageId, options=[], payload=[], securityContext=None, partialIV=None): assert msgtype in d.TYPE_ALL assert code in d.METHOD_ALL + d.COAP_RC_ALL message = [] TKL = 0 if token: # determine token length for tokenLen in range(1, 8 + 1): if token < (1 << (8 * tokenLen)): TKL = tokenLen break if not TKL: raise ValueError('token {0} too long'.format(token)) # header message += [d.COAP_VERSION << 6 | msgtype << 4 | TKL] message += [code] message += u.int2buf(messageId, 2) message += u.int2buf(token, TKL) # options options = sortOptions(options) if securityContext: # invoke oscoap to protect the message (outerOptions, newPayload) = oscoap.protectMessage(context=securityContext, version=d.COAP_VERSION, code=code, options=options, payload=payload, partialIV=partialIV) else: (outerOptions, newPayload) = (options, payload) # add encoded options message += encodeOptions(outerOptions) # add payload message += encodePayload(newPayload) return message
def _writePcapMessage(self,timestamp,srcIp,destIp,srcPort,destPort,payload): bytesToWrite = [] # IPv6 message bytesToWrite += [0x06<<4] # version + traffic_class[high] bytesToWrite += [0x00]*3 # traffic_class[low] + flow_label bytesToWrite += u.int2buf(8+len(payload),2) # payload length (incl. UDP header) bytesToWrite += [17] # next header (17==UDP) bytesToWrite += [64] # hop limit bytesToWrite += srcIp # source address bytesToWrite += destIp # destination addres # UDP header bytesToWrite += u.int2buf(srcPort,2) # source port bytesToWrite += u.int2buf(destPort,2) # destination port bytesToWrite += u.int2buf(len(payload),2) # length bytesToWrite += u.int2buf( u.calcUdpCheckSum( srcIp, destIp, srcPort, destPort, payload, ), 2 ) # checksum # payload bytesToWrite += payload # payload # format PCAP message header ts_sec = int(timestamp) ts_usec = int((timestamp-ts_sec)*1000000) pcapMsgHeader = struct.pack( 'IIII', ts_sec, # ts_sec ts_usec, # ts_usec len(bytesToWrite), # incl_len len(bytesToWrite), # orig_len ) # write to file stringToWrite = ''.join( [pcapMsgHeader]+[''.join([chr(b) for b in bytesToWrite])] ) self.pcapFile.write(stringToWrite) self.pcapFile.flush() log.debug('written {0} bytes'.format(len(stringToWrite)))
def _receiveFromCoAP(self, timestamp, sender, data): ''' Receive CoAP response and forward it to the mesh network. Appends UDP and IPv6 headers to the CoAP message and forwards it on the Eventbus towards the mesh. ''' self.coapClient.close() # UDP udplen = len(data) + 8 udp = u.int2buf(self.coapClient.udpPort,2) # src port udp += u.int2buf(sender[1],2) # dest port udp += [udplen >> 8, udplen & 0xff] # length udp += [0x00, 0x00] # checksum udp += data # destination address of the packet is CoAP client's IPv6 address (address of the mote) dstIpv6Address = u.ipv6AddrString2Bytes(self.coapClient.ipAddress) assert len(dstIpv6Address)==16 # source address of the packet is DAG root's IPV6 address # use the same prefix (link-local or global) as in the destination address srcIpv6Address = dstIpv6Address[:8] srcIpv6Address += self.dagRootEui64 assert len(srcIpv6Address)==16 # CRC See https://tools.ietf.org/html/rfc2460. udp[6:8] = openvisualizer.openvisualizer_utils.calculatePseudoHeaderCRC( src=srcIpv6Address, dst=dstIpv6Address, length=[0x00, 0x00] + udp[4:6], nh=[0x00, 0x00, 0x00, 17], # UDP as next header payload=data, ) # IPv6 ip = [6 << 4] # v6 + traffic class (upper nybble) ip += [0x00, 0x00, 0x00] # traffic class (lower nibble) + flow label ip += udp[4:6] # payload length ip += [17] # next header (protocol); UDP=17 ip += [64] # hop limit (pick a safe value) ip += srcIpv6Address # source ip += dstIpv6Address # destination ip += udp # announce network prefix self.dispatch( signal = 'v6ToMesh', data = ip )
def _writePcapMessage(self, timestamp, srcIp, destIp, srcPort, destPort, payload): bytesToWrite = [] # IPv6 message bytesToWrite += [0x06 << 4] # version + traffic_class[high] bytesToWrite += [0x00] * 3 # traffic_class[low] + flow_label bytesToWrite += u.int2buf(8 + len(payload), 2) # payload length (incl. UDP header) bytesToWrite += [17] # next header (17==UDP) bytesToWrite += [64] # hop limit bytesToWrite += srcIp # source address bytesToWrite += destIp # destination addres # UDP header bytesToWrite += u.int2buf(srcPort, 2) # source port bytesToWrite += u.int2buf(destPort, 2) # destination port bytesToWrite += u.int2buf(len(payload), 2) # length bytesToWrite += u.int2buf( u.calcUdpCheckSum( srcIp, destIp, srcPort, destPort, payload, ), 2) # checksum # payload bytesToWrite += payload # payload # format PCAP message header ts_sec = int(timestamp) ts_usec = int((timestamp - ts_sec) * 1000000) pcapMsgHeader = struct.pack( 'IIII', ts_sec, # ts_sec ts_usec, # ts_usec len(bytesToWrite), # incl_len len(bytesToWrite), # orig_len ) # write to file stringToWrite = ''.join([pcapMsgHeader] + [''.join([chr(b) for b in bytesToWrite])]) self.pcapFile.write(stringToWrite) self.pcapFile.flush() log.debug('written {0} bytes'.format(len(stringToWrite)))
def _receiveFromCoAP(self, timestamp, sender, data): ''' Receive CoAP response and forward it to the mesh network. Appends UDP and IPv6 headers to the CoAP message and forwards it on the Eventbus towards the mesh. ''' self.coapClient.close() # UDP udplen = len(data) + 8 udp = u.int2buf(sender[1], 2) # src port udp += u.int2buf(self.coapClient.udpPort, 2) # dest port udp += [udplen >> 8, udplen & 0xff] # length udp += [0x00, 0x00] # checksum udp += data # destination address of the packet is CoAP client's IPv6 address (address of the mote) dstIpv6Address = u.ipv6AddrString2Bytes(self.coapClient.ipAddress) assert len(dstIpv6Address) == 16 # source address of the packet is DAG root's IPV6 address # use the same prefix (link-local or global) as in the destination address srcIpv6Address = dstIpv6Address[:8] srcIpv6Address += self.dagRootEui64 assert len(srcIpv6Address) == 16 # CRC See https://tools.ietf.org/html/rfc2460. udp[6: 8] = openvisualizer.openvisualizer_utils.calculatePseudoHeaderCRC( src=srcIpv6Address, dst=dstIpv6Address, length=[0x00, 0x00] + udp[4:6], nh=[0x00, 0x00, 0x00, 17], # UDP as next header payload=udp, ) # IPv6 ip = [6 << 4] # v6 + traffic class (upper nybble) ip += [0x00, 0x00, 0x00] # traffic class (lower nibble) + flow label ip += udp[4:6] # payload length ip += [17] # next header (protocol); UDP=17 ip += [64] # hop limit (pick a safe value) ip += srcIpv6Address # source ip += dstIpv6Address # destination ip += udp # announce network prefix self.dispatch(signal='v6ToMesh', data=ip)
def getRequestSecurityParams(objectSecurityOption): if objectSecurityOption: context = objectSecurityOption.context newSequenceNumber = objectSecurityOption.context.getSequenceNumber() # convert sequence number to string that is the length of the IV newSequenceNumber = u.buf2str( u.int2buf(newSequenceNumber, context.aeadAlgorithm.ivLength)) return (context, newSequenceNumber) else: return (None, None)
def test_int2buf(logFixture, validint2buf): (val, len, output) = validint2buf log.debug('val: {0}'.format(val)) log.debug('len: {0}'.format(len)) log.debug('output: {0}'.format(output)) result = coapUtils.int2buf(val, len) log.debug('result: {0}'.format(result)) assert tuple(result) == output
def test_int2buf(logFixture, validint2buf): (val,len,output) = validint2buf log.debug('val: {0}'.format(val)) log.debug('len: {0}'.format(len)) log.debug('output: {0}'.format(output)) result = coapUtils.int2buf(val,len) log.debug('result: {0}'.format(result)) assert tuple(result)==output
def toBytes(self, lastOptionNum): payload = self.getPayloadBytes() delta = self.optionNumber - lastOptionNum # optionDelta and optionDeltaExt fields if delta <= 12: optionDelta = delta optionDeltaExt = u.int2buf(delta, 0) elif delta <= (0xff + 13): optionDelta = 13 optionDeltaExt = u.int2buf(delta - 13, 1) elif delta <= (0xffff + 269): optionDelta = 14 optionDeltaExt = u.int2buf(delta - 269, 2) else: raise ValueError('delta is too large: {0}'.format(delta)) # optionLength and optionLengthExt fields if len(payload) <= 12: optionLength = len(payload) optionLengthExt = u.int2buf(len(payload), 0) elif len(payload) <= (0xff + 13): optionLength = 13 optionLengthExt = u.int2buf(len(payload) - 13, 1) elif len(payload) <= (0xffff + 269): optionLength = 14 optionLengthExt = u.int2buf(len(payload) - 269, 2) else: raise ValueError('payload is too long, {0} bytes'.format( len(payload))) returnVal = [] returnVal += [optionDelta << 4 | optionLength] returnVal += optionDeltaExt returnVal += optionLengthExt returnVal += payload return returnVal