/** \brief Prepare and a send a RPL DAO. */ void sendDAO() { OpenQueueEntry_t* msg; // pointer to DAO messages uint8_t nbrIdx; // running neighbor index uint8_t numTransitParents,numTargetParents; // the number of parents indicated in transit option open_addr_t address; open_addr_t* prefix; if (ieee154e_isSynch()==FALSE) { // I'm not sync'ed // delete packets genereted by this module (DIO and DAO) from openqueue openqueue_removeAllCreatedBy(COMPONENT_ICMPv6RPL); // I'm not busy sending a DIO/DAO icmpv6rpl_vars.busySending = FALSE; // stop here return; } // dont' send a DAO if you're in bridge mode if (idmanager_getIsBridge()==TRUE) { return; } // dont' send a DAO if you did not acquire a DAGrank if (neighbors_getMyDAGrank()==DEFAULTDAGRANK) { return; } // dont' send a DAO if you're still busy sending the previous one if (icmpv6rpl_vars.busySending==TRUE) { return; } // if you get here, you start construct DAO // reserve a free packet buffer for DAO msg = openqueue_getFreePacketBuffer(COMPONENT_ICMPv6RPL); if (msg==NULL) { openserial_printError(COMPONENT_ICMPv6RPL,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); return; } // take ownership msg->creator = COMPONENT_ICMPv6RPL; msg->owner = COMPONENT_ICMPv6RPL; // set transport information msg->l4_protocol = IANA_ICMPv6; msg->l4_sourcePortORicmpv6Type = IANA_ICMPv6_RPL; // set DAO destination msg->l3_destinationAdd.type=ADDR_128B; memcpy(msg->l3_destinationAdd.addr_128b,icmpv6rpl_vars.dio.DODAGID,sizeof(icmpv6rpl_vars.dio.DODAGID)); //===== fill in packet //NOTE: limit to preferrred parent only the number of DAO transit addresses to send //=== transit option -- from RFC 6550, page 55 - 1 transit information header per parent is required. //getting only preferred parent as transit numTransitParents=0; neighbors_getPreferredParentEui64(&address); packetfunctions_writeAddress(msg,&address,OW_BIG_ENDIAN); prefix=idmanager_getMyID(ADDR_PREFIX); packetfunctions_writeAddress(msg,prefix,OW_BIG_ENDIAN); // update transit info fields // from rfc6550 p.55 -- Variable, depending on whether or not the DODAG ParentAddress subfield is present. // poipoi xv: it is not very clear if this includes all fields in the header. or as target info 2 bytes are removed. // using the same pattern as in target information. icmpv6rpl_vars.dao_transit.optionLength = LENGTH_ADDR128b + sizeof(icmpv6rpl_dao_transit_ht)-2; icmpv6rpl_vars.dao_transit.PathControl=0; //todo. this is to set the preference of this parent. icmpv6rpl_vars.dao_transit.type=OPTION_TRANSIT_INFORMATION_TYPE; // write transit info in packet packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dao_transit_ht)); memcpy( ((icmpv6rpl_dao_transit_ht*)(msg->payload)), &(icmpv6rpl_vars.dao_transit), sizeof(icmpv6rpl_dao_transit_ht) ); numTransitParents++; //target information is required. RFC 6550 page 55. /* One or more Transit Information options MUST be preceded by one or more RPL Target options. */ numTargetParents = 0; for (nbrIdx=0;nbrIdx<MAXNUMNEIGHBORS;nbrIdx++) { if ((neighbors_isNeighborWithHigherDAGrank(nbrIdx))==TRUE) { // this neighbor is of higher DAGrank as I am. so it is my child // write it's address in DAO RFC6550 page 80 check point 1. neighbors_getNeighbor(&address,ADDR_64B,nbrIdx); packetfunctions_writeAddress(msg,&address,OW_BIG_ENDIAN); prefix=idmanager_getMyID(ADDR_PREFIX); packetfunctions_writeAddress(msg,prefix,OW_BIG_ENDIAN); // update target info fields // from rfc6550 p.55 -- Variable, length of the option in octets excluding the Type and Length fields. // poipoi xv: assuming that type and length fields refer to the 2 first bytes of the header icmpv6rpl_vars.dao_target.optionLength = LENGTH_ADDR128b +sizeof(icmpv6rpl_dao_target_ht) - 2; //no header type and length icmpv6rpl_vars.dao_target.type = OPTION_TARGET_INFORMATION_TYPE; icmpv6rpl_vars.dao_target.flags = 0; //must be 0 icmpv6rpl_vars.dao_target.prefixLength = 128; //128 leading bits -- full address. // write transit info in packet packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dao_target_ht)); memcpy( ((icmpv6rpl_dao_target_ht*)(msg->payload)), &(icmpv6rpl_vars.dao_target), sizeof(icmpv6rpl_dao_target_ht) ); // remember I found it numTargetParents++; } //limit to MAX_TARGET_PARENTS the number of DAO target addresses to send //section 8.2.1 pag 67 RFC6550 -- using a subset // poipoi TODO base selection on ETX rather than first X. if (numTargetParents>=MAX_TARGET_PARENTS) break; } // stop here if no parents found if (numTransitParents==0) { openqueue_freePacketBuffer(msg); return; } icmpv6rpl_vars.dao_transit.PathSequence++; //increment path sequence. // if you get here, you will send a DAO //=== DAO header packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dao_ht)); memcpy( ((icmpv6rpl_dao_ht*)(msg->payload)), &(icmpv6rpl_vars.dao), sizeof(icmpv6rpl_dao_ht) ); //=== ICMPv6 header packetfunctions_reserveHeaderSize(msg,sizeof(ICMPv6_ht)); ((ICMPv6_ht*)(msg->payload))->type = msg->l4_sourcePortORicmpv6Type; ((ICMPv6_ht*)(msg->payload))->code = IANA_ICMPv6_RPL_DAO; packetfunctions_calculateChecksum(msg,(uint8_t*)&(((ICMPv6_ht*)(msg->payload))->checksum)); //call last //===== send if (icmpv6_send(msg)==E_SUCCESS) { icmpv6rpl_vars.busySending = TRUE; } else { openqueue_freePacketBuffer(msg); } }
void ieee802154_prependHeader(OpenQueueEntry_t* msg, uint8_t frameType, bool securityEnabled, uint8_t sequenceNumber, open_addr_t* nextHop) { uint8_t temp_8b; //previousHop address (always 64-bit) packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_64B),LITTLE_ENDIAN); // poipoi: using 16-bit source address //packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_16B),LITTLE_ENDIAN); //nextHop address if (packetfunctions_isBroadcastMulticast(nextHop)) { //broadcast address is always 16-bit packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = 0xFF; packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = 0xFF; } else { // poipoi: using 16-bit destination address // packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); // *((uint8_t*)(msg->payload)) = nextHop->addr_64b[6]; // packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); // *((uint8_t*)(msg->payload)) = nextHop->addr_64b[7]; // switch (nextHop->type) { case ADDR_16B: case ADDR_64B: packetfunctions_writeAddress(msg,nextHop,LITTLE_ENDIAN); break; default: openserial_printError(COMPONENT_IEEE802154,ERR_WRONG_ADDR_TYPE, (errorparameter_t)nextHop->type, (errorparameter_t)1); } } //destpan packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_PANID),LITTLE_ENDIAN); //dsn packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = sequenceNumber; //fcf (2nd byte) temp_8b = 0; // poipoi: 16-bit source/dest addresses // temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE; //temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_SRC_ADDR_MODE; if (packetfunctions_isBroadcastMulticast(nextHop)) { temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE; } else { switch (nextHop->type) { case ADDR_16B: temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE; break; case ADDR_64B: temp_8b |= IEEE154_ADDR_EXT << IEEE154_FCF_DEST_ADDR_MODE; break; } } temp_8b |= IEEE154_ADDR_EXT << IEEE154_FCF_SRC_ADDR_MODE; packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = temp_8b; //fcf (1st byte) temp_8b = 0; temp_8b |= frameType << IEEE154_FCF_FRAME_TYPE; temp_8b |= securityEnabled << IEEE154_FCF_SECURITY_ENABLED; temp_8b |= IEEE154_PENDING_NO_FRAMEPENDING << IEEE154_FCF_FRAME_PENDING; if (frameType==IEEE154_TYPE_ACK || packetfunctions_isBroadcastMulticast(nextHop)) { temp_8b |= IEEE154_ACK_NO_ACK_REQ << IEEE154_FCF_ACK_REQ; } else { temp_8b |= IEEE154_ACK_YES_ACK_REQ << IEEE154_FCF_ACK_REQ; } temp_8b |= IEEE154_PANID_COMPRESSED << IEEE154_FCF_INTRAPAN; packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = temp_8b; }
/** \brief Prepend the IEEE802.15.4 MAC header to a (to be transmitted) packet. Note that we are writing the field from the end of the header to the beginning. \param[in,out] msg The message to append the header to. \param[in] frameType Type of IEEE802.15.4 frame. \param[in] ielistpresent Is the IE list present¿ \param[in] frameVersion IEEE802.15.4 frame version. \param[in] securityEnabled Is security enabled on this frame? \param[in] sequenceNumber Sequence number of this frame. \param[in] nextHop Address of the next hop */ void ieee802154_prependHeader(OpenQueueEntry_t* msg, uint8_t frameType, uint8_t ielistpresent, uint8_t frameVersion, bool securityEnabled, uint8_t sequenceNumber, open_addr_t* nextHop) { uint8_t temp_8b; //General IEs here (those that are carried in all packets) -- None by now. // previousHop address (always 64-bit) packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_64B),OW_LITTLE_ENDIAN); // nextHop address if (packetfunctions_isBroadcastMulticast(nextHop)) { //broadcast address is always 16-bit packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = 0xFF; packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = 0xFF; } else { switch (nextHop->type) { case ADDR_16B: case ADDR_64B: packetfunctions_writeAddress(msg,nextHop,OW_LITTLE_ENDIAN); break; default: openserial_printCritical(COMPONENT_IEEE802154,ERR_WRONG_ADDR_TYPE, (errorparameter_t)nextHop->type, (errorparameter_t)1); } } // destpan packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_PANID),OW_LITTLE_ENDIAN); //dsn packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = sequenceNumber; //fcf (2nd byte) packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); temp_8b = 0; if (packetfunctions_isBroadcastMulticast(nextHop)) { temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE; } else { switch (nextHop->type) { case ADDR_16B: temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE; break; case ADDR_64B: temp_8b |= IEEE154_ADDR_EXT << IEEE154_FCF_DEST_ADDR_MODE; break; // no need for a default, since it would have been caught above. } } temp_8b |= IEEE154_ADDR_EXT << IEEE154_FCF_SRC_ADDR_MODE; //poipoi xv IE list present temp_8b |= ielistpresent << IEEE154_FCF_IELIST_PRESENT; temp_8b |= frameVersion << IEEE154_FCF_FRAME_VERSION; *((uint8_t*)(msg->payload)) = temp_8b; //fcf (1st byte) packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); temp_8b = 0; temp_8b |= frameType << IEEE154_FCF_FRAME_TYPE; temp_8b |= securityEnabled << IEEE154_FCF_SECURITY_ENABLED; temp_8b |= IEEE154_PENDING_NO_FRAMEPENDING << IEEE154_FCF_FRAME_PENDING; if (frameType==IEEE154_TYPE_ACK || packetfunctions_isBroadcastMulticast(nextHop)) { temp_8b |= IEEE154_ACK_NO_ACK_REQ << IEEE154_FCF_ACK_REQ; } else { temp_8b |= IEEE154_ACK_YES_ACK_REQ << IEEE154_FCF_ACK_REQ; } temp_8b |= IEEE154_PANID_COMPRESSED << IEEE154_FCF_INTRAPAN; *((uint8_t*)(msg->payload)) = temp_8b; }
void security_outgoingFrame(OpenQueueEntry_t* msg, uint8_t securityLevel, uint8_t keyIdMode, open_addr_t* keySource, uint8_t keyIndex){ uint8_t auxlen; uint8_t temp8b; uint8_t match; m_keyDescriptor* keypoint; if(m_macFrameCounter == (0xffffffffffffffff)){ return; } //max length of MAC frames authLengthChecking(securityLevel); // length of auth msg->l2_authenticationLength = authlen; //auxLengthChecking(keyIdMode, auxlen); //length of Key ID field //for us, keyIdMode = 3 and so Auxlen = 9 auxlen = 9; if((msg->length+auxlen+authlen+2) >= 130 ){ //2 bytes of CRC, 130 MaxPHYPacketSize return; } //check if SecurityLevel is not zero //in my impl. secLevel may not be zero if i'm here. /*if(securityLevel == ASH_SLF_TYPE_NOSEC){ return; }*/ open_addr_t* nextHop; nextHop = &msg->l2_nextORpreviousHop; //search for a key match = keyDescriptorLookup(keyIdMode, keySource, keyIndex, nextHop, //idmanager_getMyID(ADDR_PANID), msg->l2_frameType); keypoint = &MacKeyTable.KeyDescriptorElement[match]; //start setting the Auxiliary Security Header temp8b = keyIndex; //key index field packetfunctions_reserveHeaderSize(msg, sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = temp8b; //Key Identifier Mode /*if(keyIdMode != 0){ switch(keyIdMode){ case(ASH_KIMF_TYPE_MACDEF): break; case(ASH_KIMF_TYPE_4OCTKEY): packetfunctions_writeAddress(msg, idmanager_getMyID(ADDR_16B) ,OW_LITTLE_ENDIAN);//da rivedere break; case(ASH_KIMF_TYPE_8OCTKEY): packetfunctions_writeAddress(msg,keySource,OW_LITTLE_ENDIAN); break; } }*/ //in our impl. keyIdMode = 3 packetfunctions_writeAddress(msg,keySource,OW_LITTLE_ENDIAN); //Frame Counter uint32_t temp; uint8_t i; temp = m_macFrameCounter; for(i=0;i<3;i++){ packetfunctions_reserveHeaderSize(msg, sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = temp; temp = temp >>8; } packetfunctions_reserveHeaderSize(msg, sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = temp; //security control field packetfunctions_reserveHeaderSize(msg, sizeof(uint8_t)); temp8b = 0; temp8b |= securityLevel << ASH_SCF_SECURITY_LEVEL;//3b temp8b |= keyIdMode << ASH_SCF_KEY_IDENTIFIER_MODE;//2b temp8b |= 0 << 3;//3b reserved *((uint8_t*)(msg->payload)) = temp8b; //cryptographic block for(i=0; i<8; i++){ nonce[i] = keySource->addr_64b[i]; } temp = m_macFrameCounter; nonce[8] = temp; nonce[9] = temp << 8; nonce[10] = temp <<16; nonce[11] = temp <<24; nonce[12] = securityLevel; // CRYPTO TEST // asn_t init; // // if(msg->l2_frameType == IEEE154_TYPE_DATA){ // // uint8_t start[5]; // // ieee154e_getAsn(start); // // init.bytes0and1 = start[0]+256*start[1]; // init.bytes2and3 = start[2]+256*start[3]; // init.byte4 = start[4]; // } //CCMstar(msg,keypoint->key); // if(msg->l2_frameType == IEEE154_TYPE_DATA){ // uint16_t diff; // diff = ieee154e_asnDiff(&init); // // openserial_printError(COMPONENT_RES,ERR_OK, // (errorparameter_t)diff, // (errorparameter_t)501); // } //h increment the Frame Counter and save. m_macFrameCounter++; }