Ejemplo n.º 1
0
void openudp_receive(OpenQueueEntry_t* msg) {
   uint8_t temp_8b;
      
   msg->owner                      = COMPONENT_OPENUDP;
   if (msg->l4_protocol_compressed==TRUE) {
      // get the UDP header encoding byte
      temp_8b = *((uint8_t*)(msg->payload));
      packetfunctions_tossHeader(msg,sizeof(temp_8b));
      switch (temp_8b & NHC_UDP_PORTS_MASK) {
         case NHC_UDP_PORTS_INLINE:
            // source port:         16 bits in-line
            // dest port:           16 bits in-line
            msg->l4_sourcePortORicmpv6Type  = msg->payload[0]*256+msg->payload[1];
            msg->l4_destination_port        = msg->payload[2]*256+msg->payload[3];
            packetfunctions_tossHeader(msg,2+2);
            break;
         case NHC_UDP_PORTS_16S_8D:
            // source port:         16 bits in-line
            // dest port:   0xf0  +  8 bits in-line
            msg->l4_sourcePortORicmpv6Type  = msg->payload[0]*256+msg->payload[1];
            msg->l4_destination_port        = 0xf000 +            msg->payload[2];
            packetfunctions_tossHeader(msg,2+1);
            break;
         case NHC_UDP_PORTS_8S_8D:
            // source port: 0xf0  +  8 bits in-line
            // dest port:   0xf0  +  8 bits in-line
            msg->l4_sourcePortORicmpv6Type  = 0xf000 +            msg->payload[0];
            msg->l4_destination_port        = 0xf000 +            msg->payload[1];
            packetfunctions_tossHeader(msg,1+1);
            break;
         case NHC_UDP_PORTS_4S_4D:
            // source port: 0xf0b +  4 bits in-line
            // dest port:   0xf0b +  4 bits in-line
            msg->l4_sourcePortORicmpv6Type  = 0xf0b0 + (msg->payload[0] >> 4) & 0x0f;
            msg->l4_destination_port        = 0xf0b0 + (msg->payload[0] >> 0) & 0x0f;
            packetfunctions_tossHeader(msg,1);
            break;
      }
   } else {
Ejemplo n.º 2
0
/**
\brief Send a packet using the routing table to find the next hop.

\param[in,out] msg             The packet to send.
\param[in]     ipv6_header     The packet's IPv6 header.
\param[in]     rpl_option      The hop-by-hop option to add in this packet.
\param[in]     flow_label      The flowlabel to add in the 6LoWPAN header.
\param[in]     fw_SendOrfw_Rcv The packet is originating from this mote
   (PCKTSEND), or forwarded (PCKTFORWARD).
*/
owerror_t forwarding_send_internal_RoutingTable(OpenMote* self, 
      OpenQueueEntry_t*      msg,
      ipv6_header_iht*       ipv6_outer_header,
      ipv6_header_iht*       ipv6_inner_header,
      rpl_option_ht*         rpl_option,
      uint32_t*              flow_label,
      uint8_t                fw_SendOrfw_Rcv
   ) {
   
   // retrieve the next hop from the routing table
 forwarding_getNextHop(self, &(msg->l3_destinationAdd),&(msg->l2_nextORpreviousHop));
   if (msg->l2_nextORpreviousHop.type==ADDR_NONE) {
 openserial_printError(self, 
         COMPONENT_FORWARDING,
         ERR_NO_NEXTHOP,
         (errorparameter_t)0,
         (errorparameter_t)0
      );
      return E_FAIL;
   }
   
   if (ipv6_outer_header->src.type != ADDR_NONE){
 packetfunctions_tossHeader(self, msg,ipv6_outer_header->header_length);
   }
   
   // send to next lower layer
   return iphc_sendFromForwarding(self, 
      msg,
      ipv6_outer_header,
      ipv6_inner_header,
      rpl_option,
      flow_label,
      NULL,  // no rh3
      0,
      fw_SendOrfw_Rcv
   );
}
Ejemplo n.º 3
0
/**
\brief Called when RPL message received.

\param[in] msg   Pointer to the received message.
*/
void icmpv6rpl_receive(OpenQueueEntry_t* msg) {
   uint8_t      icmpv6code;
   open_addr_t  myPrefix;
   
   // take ownership
   msg->owner      = COMPONENT_ICMPv6RPL;
   
   // retrieve ICMPv6 code
   icmpv6code      = (((ICMPv6_ht*)(msg->payload))->code);
   
   // toss ICMPv6 header
   packetfunctions_tossHeader(msg,sizeof(ICMPv6_ht));
   
   // handle message
   switch (icmpv6code) {
      
      case IANA_ICMPv6_RPL_DIO:
         if (idmanager_getIsBridge()==TRUE) {
            // stop here if I'm in bridge mode
            break; // break, don't return
         }
         
         // update neighbor table
         neighbors_indicateRxDIO(msg);
         
         // update DODAGID in DIO/DAO
         memcpy(
            &(icmpv6rpl_vars.dio.DODAGID[0]),
            &(((icmpv6rpl_dio_ht*)(msg->payload))->DODAGID[0]),
            sizeof(icmpv6rpl_vars.dio.DODAGID)
         );
         memcpy(
            &(icmpv6rpl_vars.dao.DODAGID[0]),
            &(((icmpv6rpl_dio_ht*)(msg->payload))->DODAGID[0]),
            sizeof(icmpv6rpl_vars.dao.DODAGID)
         );
         
         // remember I got a DODAGID
         icmpv6rpl_vars.DODAGIDFlagSet=1;
         
         // update my prefix
         myPrefix.type = ADDR_PREFIX;
         memcpy(
            myPrefix.prefix,
            &((icmpv6rpl_dio_ht*)(msg->payload))->DODAGID[0],
            sizeof(myPrefix.prefix)
         );
         idmanager_setMyID(&myPrefix);
         
         break;
      
      case IANA_ICMPv6_RPL_DAO:
         // this should never happen
         openserial_printCritical(COMPONENT_ICMPv6RPL,ERR_UNEXPECTED_DAO,
                               (errorparameter_t)0,
                               (errorparameter_t)0);
         break;
      
      default:
         // this should never happen
         openserial_printCritical(COMPONENT_ICMPv6RPL,ERR_MSG_UNKNOWN_TYPE,
                               (errorparameter_t)icmpv6code,
                               (errorparameter_t)0);
         break;
      
   }
   
   // free message
   openqueue_freePacketBuffer(msg);
}
Ejemplo n.º 4
0
/**
\brief Indicate a CoAP messages was received.

A "CoAP message" is simply a UDP datagram received on the CoAP UDP port.

This function will call the appropriate resource, and send back its answer. The
received packetbuffer is reused to contain the response (or error code).

\param[in] msg The received CoAP message.
*/
void opencoap_receive(OpenQueueEntry_t* msg) {
   uint16_t                  temp_l4_destination_port;
   uint8_t                   i;
   uint8_t                   index;
   coap_option_t             last_option;
   coap_resource_desc_t*     temp_desc;
   bool                      found;
   owerror_t                 outcome;
   // local variables passed to the handlers (with msg)
   coap_header_iht           coap_header;
   coap_option_iht           coap_options[MAX_COAP_OPTIONS];
   
   // take ownership over the received packet
   msg->owner                = COMPONENT_OPENCOAP;
   
   //=== step 1. parse the packet
   
   // parse the CoAP header and remove from packet
   index = 0;
   coap_header.Ver           = (msg->payload[index] & 0xc0) >> 6;
   coap_header.T             = (coap_type_t)((msg->payload[index] & 0x30) >> 4);
   coap_header.TKL           = (msg->payload[index] & 0x0f);
   index++;
   coap_header.Code          = (coap_code_t)(msg->payload[index]);
   index++;
   coap_header.messageID     = msg->payload[index]*256+msg->payload[index+1];
   index+=2;
   
   // reject unsupported header
   if (coap_header.Ver!=COAP_VERSION || coap_header.TKL>COAP_MAX_TKL) {
      openserial_printError(
         COMPONENT_OPENCOAP,ERR_WRONG_TRAN_PROTOCOL,
         (errorparameter_t)0,
         (errorparameter_t)coap_header.Ver
      );
      openqueue_freePacketBuffer(msg);
      return;
   }
   
   // record the token
   memcpy(&coap_header.token[0], &msg->payload[index], coap_header.TKL);
   index += coap_header.TKL;
   
   // initialize the coap_options
   for (i=0;i<MAX_COAP_OPTIONS;i++) {
      coap_options[i].type = COAP_OPTION_NONE;
   }
   
   // fill in the coap_options
   last_option = COAP_OPTION_NONE;
   for (i=0;i<MAX_COAP_OPTIONS;i++) {
      
      // detect when done parsing options
      if (msg->payload[index]==COAP_PAYLOAD_MARKER){
         // found the payload marker, done parsing options.
         index++; // skip marker and stop parsing options
         break;
      }
      
      // parse this option
      coap_options[i].type        = (coap_option_t)((uint8_t)last_option+(uint8_t)((msg->payload[index] & 0xf0) >> 4));
      last_option                 = coap_options[i].type;
      coap_options[i].length      = (msg->payload[index] & 0x0f);
      index++;
      coap_options[i].pValue      = &(msg->payload[index]);
      index                      += coap_options[i].length; //includes length as well
   }
   
   // remove the CoAP header+options
   packetfunctions_tossHeader(msg,index);
   
   //=== step 2. find the resource to handle the packet
   
   // find the resource this applies to
   found = FALSE;
   
   if (
         coap_header.Code>=COAP_CODE_REQ_GET &&
         coap_header.Code<=COAP_CODE_REQ_DELETE
      ) {
      // this is a request: target resource is indicated as COAP_OPTION_LOCATIONPATH option(s)
      // find the resource which matches
      
      // start with the first resource in the linked list
      temp_desc = opencoap_vars.resources;
      
      // iterate until matching resource found, or no match
      while (found==FALSE) {
         if (
               coap_options[0].type==COAP_OPTION_NUM_URIPATH    &&
               coap_options[1].type==COAP_OPTION_NUM_URIPATH    &&
               temp_desc->path0len>0                            &&
               temp_desc->path0val!=NULL                        &&
               temp_desc->path1len>0                            &&
               temp_desc->path1val!=NULL
            ) {
            // resource has a path of form path0/path1
               
            if (
                  coap_options[0].length==temp_desc->path0len                               &&
                  memcmp(coap_options[0].pValue,temp_desc->path0val,temp_desc->path0len)==0 &&
                  coap_options[1].length==temp_desc->path1len                               &&
                  memcmp(coap_options[1].pValue,temp_desc->path1val,temp_desc->path1len)==0
               ) {
               found = TRUE;
            };
         
         } else if (
               coap_options[0].type==COAP_OPTION_NUM_URIPATH    &&
               temp_desc->path0len>0                            &&
               temp_desc->path0val!=NULL
            ) {
            // resource has a path of form path0
               
            if (
                  coap_options[0].length==temp_desc->path0len                               &&
                  memcmp(coap_options[0].pValue,temp_desc->path0val,temp_desc->path0len)==0
               ) {
               found = TRUE;
            };
         };
         
         // iterate to next resource, if not found
         if (found==FALSE) {
            if (temp_desc->next!=NULL) {
               temp_desc = temp_desc->next;
            } else {
               break;
            }
         }
      }
   
   } else {
      // this is a response: target resource is indicated by message ID
      // find the resource which matches
      
      // start with the first resource in the linked list
      temp_desc = opencoap_vars.resources;
      
      // iterate until matching resource found, or no match
      while (found==FALSE) {
         
         if (coap_header.messageID==temp_desc->messageID) {
            found=TRUE;
            
            // call the resource's callback
            if (temp_desc->callbackRx!=NULL) {
               temp_desc->callbackRx(msg,&coap_header,&coap_options[0]);
            }
         }
         
         // iterate to next resource, if not found
         if (found==FALSE) {
            if (temp_desc->next!=NULL) {
               temp_desc = temp_desc->next;
            } else {
               break;
            }
         }
      };
      
      // free the received packet
      openqueue_freePacketBuffer(msg);
      
      // stop here: will will not respond to a response
      return;
   }
   
   //=== step 3. ask the resource to prepare response
   
   if (found==TRUE) {
      
      // call the resource's callback
      outcome = temp_desc->callbackRx(msg,&coap_header,&coap_options[0]);
   } else {
      // reset packet payload (DO NOT DELETE, we will reuse same buffer for response)
      msg->payload                     = &(msg->packet[127]);
      msg->length                      = 0;
      // set the CoAP header
      coap_header.TKL                  = 0;
      coap_header.Code                 = COAP_CODE_RESP_NOTFOUND;
   }
   
   if (outcome==E_FAIL) {
      // reset packet payload (DO NOT DELETE, we will reuse same buffer for response)
      msg->payload                     = &(msg->packet[127]);
      msg->length                      = 0;
      // set the CoAP header
      coap_header.TKL                  = 0;
      coap_header.Code                 = COAP_CODE_RESP_METHODNOTALLOWED;
   }
   
   //=== step 4. send that packet back
   
   // fill in packet metadata
   if (found==TRUE) {
      msg->creator                     = temp_desc->componentID;
   } else {
      msg->creator                     = COMPONENT_OPENCOAP;
   }
   msg->l4_protocol                    = IANA_UDP;
   temp_l4_destination_port            = msg->l4_destination_port;
   msg->l4_destination_port            = msg->l4_sourcePortORicmpv6Type;
   msg->l4_sourcePortORicmpv6Type      = temp_l4_destination_port;
   
   // set destination address as the current source
   msg->l3_destinationAdd.type         = ADDR_128B;
   memcpy(&msg->l3_destinationAdd.addr_128b[0],&msg->l3_sourceAdd.addr_128b[0],LENGTH_ADDR128b);
   
   // fill in CoAP header
   packetfunctions_reserveHeaderSize(msg,4+coap_header.TKL);
   msg->payload[0]                  = (COAP_VERSION    << 6) |
                                      (COAP_TYPE_ACK   << 4) |
                                      (coap_header.TKL << 0);
   msg->payload[1]                  = coap_header.Code;
   msg->payload[2]                  = coap_header.messageID/256;
   msg->payload[3]                  = coap_header.messageID%256;
   memcpy(&msg->payload[4], &coap_header.token[0], coap_header.TKL);
   
   if ((openudp_send(msg))==E_FAIL) {
      openqueue_freePacketBuffer(msg);
   }
}
Ejemplo n.º 5
0
void task_sixtopNotifReceive() {
   OpenQueueEntry_t* msg;
   uint16_t          lenIE;
   
   // get received packet from openqueue
   msg = openqueue_sixtopGetReceivedPacket();
   if (msg==NULL) {
      openserial_printCritical(
         COMPONENT_SIXTOP,
         ERR_NO_RECEIVED_PACKET,
         (errorparameter_t)0,
         (errorparameter_t)0
      );
      return;
   }
   
   // take ownership
   msg->owner = COMPONENT_SIXTOP;
   
   // process the header IEs
   lenIE=0;
   if(
         msg->l2_frameType==IEEE154_TYPE_DATA            &&
         msg->l2_IEListPresent==IEEE154_IELIST_YES       &&
         sixtop_processIEs(msg, &lenIE) == FALSE
      ) {
      // free the packet's RAM memory
      openqueue_freePacketBuffer(msg);
      //log error
      return;
   }
   
   // toss the header IEs
   packetfunctions_tossHeader(msg,lenIE);
   
   // update neighbor statistics
   neighbors_indicateRx(
      &(msg->l2_nextORpreviousHop),
      msg->l1_rssi,
      &msg->l2_asn,
      msg->l2_joinPriorityPresent,
      msg->l2_joinPriority
   );
   
   // reset it to avoid race conditions with this var.
   msg->l2_joinPriorityPresent = FALSE; 
   
   // send the packet up the stack, if it qualifies
   switch (msg->l2_frameType) {
      case IEEE154_TYPE_BEACON:
      case IEEE154_TYPE_DATA:
      case IEEE154_TYPE_CMD:
         if (msg->length>0) {
            // send to upper layer
            iphc_receive(msg);
         } else {
            // free up the RAM
            openqueue_freePacketBuffer(msg);
         }
         break;
      case IEEE154_TYPE_ACK:
      default:
         // free the packet's RAM memory
         openqueue_freePacketBuffer(msg);
         // log the error
         openserial_printError(
            COMPONENT_SIXTOP,
            ERR_MSG_UNKNOWN_TYPE,
            (errorparameter_t)msg->l2_frameType,
            (errorparameter_t)0
         );
         break;
   }
}
Ejemplo n.º 6
0
void opentcp_receive(OpenQueueEntry_t* msg) {
   OpenQueueEntry_t* tempPkt;
   bool shouldIlisten;
   msg->owner                     = COMPONENT_OPENTCP;
   msg->l4_protocol               = IANA_TCP;
   msg->l4_payload                = msg->payload;
   msg->l4_length                 = msg->length;
   msg->l4_sourcePortORicmpv6Type = packetfunctions_ntohs((uint8_t*)&(((tcp_ht*)msg->payload)->source_port));
   msg->l4_destination_port       = packetfunctions_ntohs((uint8_t*)&(((tcp_ht*)msg->payload)->destination_port));
   if ( 
         tcp_vars.state!=TCP_STATE_CLOSED &&
         (
          msg->l4_destination_port != tcp_vars.myPort  ||
          msg->l4_sourcePortORicmpv6Type      != tcp_vars.hisPort ||
          packetfunctions_sameAddress(&(msg->l3_destinationAdd),&tcp_vars.hisIPv6Address)==FALSE
         )
      ) {
      openqueue_freePacketBuffer(msg);
      return;
   }
   if (containsControlBits(msg,TCP_ACK_WHATEVER,TCP_RST_YES,TCP_SYN_WHATEVER,TCP_FIN_WHATEVER)) {
      //I receive RST[+*], I reset
      opentcp_reset();
      openqueue_freePacketBuffer(msg);
   }
   switch (tcp_vars.state) {
      case TCP_STATE_CLOSED:                                      //[receive] establishement
         switch(msg->l4_destination_port) {
            case WKP_TCP_HTTP:
               shouldIlisten = ohlone_shouldIlisten();
               break;
            case WKP_TCP_ECHO:
               shouldIlisten = tcpecho_shouldIlisten();
               break;
            case WKP_TCP_INJECT:
               shouldIlisten = tcpinject_shouldIlisten();
               break;   
            case WKP_TCP_DISCARD:
               shouldIlisten = tcpprint_shouldIlisten();
               break;
            default:
               openserial_printError(COMPONENT_OPENTCP,ERR_UNSUPPORTED_PORT_NUMBER,
                                     (errorparameter_t)msg->l4_sourcePortORicmpv6Type,
                                     (errorparameter_t)2);
               shouldIlisten = FALSE;
               break;
         }
         if ( containsControlBits(msg,TCP_ACK_NO,TCP_RST_NO,TCP_SYN_YES,TCP_FIN_NO) && shouldIlisten==TRUE ) {
                  tcp_vars.myPort = msg->l4_destination_port;
                  //I receive SYN, I send SYN+ACK
                  tcp_vars.hisNextSeqNum = (packetfunctions_ntohl((uint8_t*)&(((tcp_ht*)msg->payload)->sequence_number)))+1;
                  tcp_vars.hisPort       = msg->l4_sourcePortORicmpv6Type;
                  memcpy(&tcp_vars.hisIPv6Address,&(msg->l3_destinationAdd),sizeof(open_addr_t));
                  tempPkt       = openqueue_getFreePacketBuffer(COMPONENT_OPENTCP);
                  if (tempPkt==NULL) {
                     openserial_printError(COMPONENT_OPENTCP,ERR_NO_FREE_PACKET_BUFFER,
                                           (errorparameter_t)0,
                                           (errorparameter_t)0);
                     openqueue_freePacketBuffer(msg);
                     return;
                  }
                  tempPkt->creator       = COMPONENT_OPENTCP;
                  tempPkt->owner         = COMPONENT_OPENTCP;
                  memcpy(&(tempPkt->l3_destinationAdd),&tcp_vars.hisIPv6Address,sizeof(open_addr_t));
                  prependTCPHeader(tempPkt,
                        TCP_ACK_YES,
                        TCP_PSH_NO,
                        TCP_RST_NO,
                        TCP_SYN_YES,
                        TCP_FIN_NO);
                  tcp_vars.mySeqNum++;
                  tcp_change_state(TCP_STATE_ALMOST_SYN_RECEIVED);
                  forwarding_send(tempPkt);
               } else {
                  opentcp_reset();
                  openserial_printError(COMPONENT_OPENTCP,ERR_TCP_RESET,
                                        (errorparameter_t)tcp_vars.state,
                                        (errorparameter_t)0);
               }
         openqueue_freePacketBuffer(msg);
         break;

      case TCP_STATE_SYN_SENT:                                    //[receive] establishement
         if (containsControlBits(msg,TCP_ACK_YES,TCP_RST_NO,TCP_SYN_YES,TCP_FIN_NO)) {
            //I receive SYN+ACK, I send ACK
            tcp_vars.hisNextSeqNum = (packetfunctions_ntohl((uint8_t*)&(((tcp_ht*)msg->payload)->sequence_number)))+1;
            tempPkt = openqueue_getFreePacketBuffer(COMPONENT_OPENTCP);
            if (tempPkt==NULL) {
               openserial_printError(COMPONENT_OPENTCP,ERR_NO_FREE_PACKET_BUFFER,
                                     (errorparameter_t)0,
                                     (errorparameter_t)0);
               openqueue_freePacketBuffer(msg);
               return;
            }
            tempPkt->creator       = COMPONENT_OPENTCP;
            tempPkt->owner         = COMPONENT_OPENTCP;
            memcpy(&(tempPkt->l3_destinationAdd),&tcp_vars.hisIPv6Address,sizeof(open_addr_t));
            prependTCPHeader(tempPkt,
                  TCP_ACK_YES,
                  TCP_PSH_NO,
                  TCP_RST_NO,
                  TCP_SYN_NO,
                  TCP_FIN_NO);
            tcp_change_state(TCP_STATE_ALMOST_ESTABLISHED);
            forwarding_send(tempPkt);
         } else if (containsControlBits(msg,TCP_ACK_NO,TCP_RST_NO,TCP_SYN_YES,TCP_FIN_NO)) {
            //I receive SYN, I send SYN+ACK
            tcp_vars.hisNextSeqNum = (packetfunctions_ntohl((uint8_t*)&(((tcp_ht*)msg->payload)->sequence_number)))+1;
            tempPkt       = openqueue_getFreePacketBuffer(COMPONENT_OPENTCP);
            if (tempPkt==NULL) {
               openserial_printError(COMPONENT_OPENTCP,ERR_NO_FREE_PACKET_BUFFER,
                                     (errorparameter_t)0,
                                     (errorparameter_t)0);
               openqueue_freePacketBuffer(msg);
               return;
            }
            tempPkt->creator       = COMPONENT_OPENTCP;
            tempPkt->owner         = COMPONENT_OPENTCP;
            memcpy(&(tempPkt->l3_destinationAdd),&tcp_vars.hisIPv6Address,sizeof(open_addr_t));
            prependTCPHeader(tempPkt,
                  TCP_ACK_YES,
                  TCP_PSH_NO,
                  TCP_RST_NO,
                  TCP_SYN_YES,
                  TCP_FIN_NO);
            tcp_vars.mySeqNum++;
            tcp_change_state(TCP_STATE_ALMOST_SYN_RECEIVED);
            forwarding_send(tempPkt);
         } else {
            opentcp_reset();
            openserial_printError(COMPONENT_OPENTCP,ERR_TCP_RESET,
                                  (errorparameter_t)tcp_vars.state,
                                  (errorparameter_t)1);
         }
         openqueue_freePacketBuffer(msg);
         break;

      case TCP_STATE_SYN_RECEIVED:                                //[receive] establishement
         if (containsControlBits(msg,TCP_ACK_YES,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_NO)) {
            //I receive ACK, the virtual circuit is established
            tcp_change_state(TCP_STATE_ESTABLISHED);
         } else {
            opentcp_reset();
            openserial_printError(COMPONENT_OPENTCP,ERR_TCP_RESET,
                                  (errorparameter_t)tcp_vars.state,
                                  (errorparameter_t)2);
         }
         openqueue_freePacketBuffer(msg);
         break;

      case TCP_STATE_ESTABLISHED:                                 //[receive] data/teardown
         if (containsControlBits(msg,TCP_ACK_WHATEVER,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_YES)) {
            //I receive FIN[+ACK], I send ACK
            tcp_vars.hisNextSeqNum = (packetfunctions_ntohl((uint8_t*)&(((tcp_ht*)msg->payload)->sequence_number)))+msg->length-sizeof(tcp_ht)+1;
            tempPkt = openqueue_getFreePacketBuffer(COMPONENT_OPENTCP);
            if (tempPkt==NULL) {
               openserial_printError(COMPONENT_OPENTCP,ERR_NO_FREE_PACKET_BUFFER,
                                     (errorparameter_t)0,
                                     (errorparameter_t)0);
               openqueue_freePacketBuffer(msg);
               return;
            }
            tempPkt->creator       = COMPONENT_OPENTCP;
            tempPkt->owner         = COMPONENT_OPENTCP;
            memcpy(&(tempPkt->l3_destinationAdd),&tcp_vars.hisIPv6Address,sizeof(open_addr_t));
            prependTCPHeader(tempPkt,
                  TCP_ACK_YES,
                  TCP_PSH_NO,
                  TCP_RST_NO,
                  TCP_SYN_NO,
                  TCP_FIN_NO);
            forwarding_send(tempPkt);
            tcp_change_state(TCP_STATE_ALMOST_CLOSE_WAIT);
         } else if (containsControlBits(msg,TCP_ACK_WHATEVER,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_NO)) {
            //I receive data, I send ACK
            tcp_vars.hisNextSeqNum = (packetfunctions_ntohl((uint8_t*)&(((tcp_ht*)msg->payload)->sequence_number)))+msg->length-sizeof(tcp_ht);
            tempPkt = openqueue_getFreePacketBuffer(COMPONENT_OPENTCP);
            if (tempPkt==NULL) {
               openserial_printError(COMPONENT_OPENTCP,ERR_NO_FREE_PACKET_BUFFER,
                                     (errorparameter_t)0,
                                     (errorparameter_t)0);
               openqueue_freePacketBuffer(msg);
               return;
            }
            tempPkt->creator       = COMPONENT_OPENTCP;
            tempPkt->owner         = COMPONENT_OPENTCP;
            memcpy(&(tempPkt->l3_destinationAdd),&tcp_vars.hisIPv6Address,sizeof(open_addr_t));
            prependTCPHeader(tempPkt,
                  TCP_ACK_YES,
                  TCP_PSH_NO,
                  TCP_RST_NO,
                  TCP_SYN_NO,
                  TCP_FIN_NO);
            forwarding_send(tempPkt);
            packetfunctions_tossHeader(msg,sizeof(tcp_ht));
            tcp_vars.dataReceived = msg;
            tcp_change_state(TCP_STATE_ALMOST_DATA_RECEIVED);
         } else {
            opentcp_reset();
            openserial_printError(COMPONENT_OPENTCP,ERR_TCP_RESET,
                                  (errorparameter_t)tcp_vars.state,
                                  (errorparameter_t)3);
            openqueue_freePacketBuffer(msg);
         }
         break;

      case TCP_STATE_DATA_SENT:                                   //[receive] data
         if (containsControlBits(msg,TCP_ACK_YES,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_NO)) {
            //I receive ACK, data message sent
            switch(tcp_vars.myPort) {
               case WKP_TCP_HTTP:
                  ohlone_sendDone(tcp_vars.dataToSend,E_SUCCESS);
                  break;
               case WKP_TCP_ECHO:
                  tcpecho_sendDone(tcp_vars.dataToSend,E_SUCCESS);
                  break;
               case WKP_TCP_INJECT:
                  tcpinject_sendDone(tcp_vars.dataToSend,E_SUCCESS);
                  break;
               case WKP_TCP_DISCARD:
                  tcpprint_sendDone(tcp_vars.dataToSend,E_SUCCESS);
                  break;
               default:
                  openserial_printError(COMPONENT_OPENTCP,ERR_UNSUPPORTED_PORT_NUMBER,
                                        (errorparameter_t)tcp_vars.myPort,
                                        (errorparameter_t)3);
                  break;
            }
            tcp_vars.dataToSend = NULL;
            tcp_change_state(TCP_STATE_ESTABLISHED);
         } else if (containsControlBits(msg,TCP_ACK_WHATEVER,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_YES)) {
            //I receive FIN[+ACK], I send ACK
            switch(tcp_vars.myPort) {
               case WKP_TCP_HTTP:
                  ohlone_sendDone(tcp_vars.dataToSend,E_SUCCESS);
                  break;
               case WKP_TCP_ECHO:
                  tcpecho_sendDone(tcp_vars.dataToSend,E_SUCCESS);
                  break;
               case WKP_TCP_INJECT:
                  tcpinject_sendDone(tcp_vars.dataToSend,E_SUCCESS);
                  break;
               case WKP_TCP_DISCARD:
                  tcpprint_sendDone(tcp_vars.dataToSend,E_SUCCESS);
                  break;
               default:
                  openserial_printError(COMPONENT_OPENTCP,ERR_UNSUPPORTED_PORT_NUMBER,
                                        (errorparameter_t)tcp_vars.myPort,
                                        (errorparameter_t)4);
                  break;
            }
            tcp_vars.dataToSend = NULL;
            tcp_vars.hisNextSeqNum = (packetfunctions_ntohl((uint8_t*)&(((tcp_ht*)msg->payload)->sequence_number)))+msg->length-sizeof(tcp_ht)+1;
            tempPkt = openqueue_getFreePacketBuffer(COMPONENT_OPENTCP);
            if (tempPkt==NULL) {
               openserial_printError(COMPONENT_OPENTCP,ERR_NO_FREE_PACKET_BUFFER,
                                     (errorparameter_t)0,
                                     (errorparameter_t)0);
               openqueue_freePacketBuffer(msg);
               return;
            }
            tempPkt->creator       = COMPONENT_OPENTCP;
            tempPkt->owner         = COMPONENT_OPENTCP;
            memcpy(&(tempPkt->l3_destinationAdd),&tcp_vars.hisIPv6Address,sizeof(open_addr_t));
            prependTCPHeader(tempPkt,
                  TCP_ACK_YES,
                  TCP_PSH_NO,
                  TCP_RST_NO,
                  TCP_SYN_NO,
                  TCP_FIN_NO);
            forwarding_send(tempPkt);
            tcp_change_state(TCP_STATE_ALMOST_CLOSE_WAIT);
         } else {
            opentcp_reset();
            openserial_printError(COMPONENT_OPENTCP,ERR_TCP_RESET,
                                  (errorparameter_t)tcp_vars.state,
                                  (errorparameter_t)4);
         }
         openqueue_freePacketBuffer(msg);
         break;

      case TCP_STATE_FIN_WAIT_1:                                  //[receive] teardown
         if (containsControlBits(msg,TCP_ACK_NO,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_YES)) {
            //I receive FIN, I send ACK
            tcp_vars.hisNextSeqNum = (packetfunctions_ntohl((uint8_t*)&(((tcp_ht*)msg->payload)->sequence_number)))+1;
            tempPkt = openqueue_getFreePacketBuffer(COMPONENT_OPENTCP);
            if (tempPkt==NULL) {
               openserial_printError(COMPONENT_OPENTCP,ERR_NO_FREE_PACKET_BUFFER,
                                     (errorparameter_t)0,
                                     (errorparameter_t)0);
               openqueue_freePacketBuffer(msg);
               return;
            }
            tempPkt->creator       = COMPONENT_OPENTCP;
            tempPkt->owner         = COMPONENT_OPENTCP;
            memcpy(&(tempPkt->l3_destinationAdd),&tcp_vars.hisIPv6Address,sizeof(open_addr_t));
            prependTCPHeader(tempPkt,
                  TCP_ACK_YES,
                  TCP_PSH_NO,
                  TCP_RST_NO,
                  TCP_SYN_NO,
                  TCP_FIN_NO);
            forwarding_send(tempPkt);
            tcp_change_state(TCP_STATE_ALMOST_CLOSING);
         } else if (containsControlBits(msg,TCP_ACK_YES,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_YES)) {
            //I receive FIN+ACK, I send ACK
            tcp_vars.hisNextSeqNum = (packetfunctions_ntohl((uint8_t*)&(((tcp_ht*)msg->payload)->sequence_number)))+1;
            tempPkt = openqueue_getFreePacketBuffer(COMPONENT_OPENTCP);
            if (tempPkt==NULL) {
               openserial_printError(COMPONENT_OPENTCP,ERR_NO_FREE_PACKET_BUFFER,
                                     (errorparameter_t)0,
                                     (errorparameter_t)0);
               openqueue_freePacketBuffer(msg);
               return;
            }
            tempPkt->creator       = COMPONENT_OPENTCP;
            tempPkt->owner         = COMPONENT_OPENTCP;
            memcpy(&(tempPkt->l3_destinationAdd),&tcp_vars.hisIPv6Address,sizeof(open_addr_t));
            prependTCPHeader(tempPkt,
                  TCP_ACK_YES,
                  TCP_PSH_NO,
                  TCP_RST_NO,
                  TCP_SYN_NO,
                  TCP_FIN_NO);
            forwarding_send(tempPkt);
            tcp_change_state(TCP_STATE_ALMOST_TIME_WAIT);
         } else if  (containsControlBits(msg,TCP_ACK_YES,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_NO)) {
            //I receive ACK, I will receive FIN later
            tcp_change_state(TCP_STATE_FIN_WAIT_2);
         } else {
            opentcp_reset();
            openserial_printError(COMPONENT_OPENTCP,ERR_TCP_RESET,
                                  (errorparameter_t)tcp_vars.state,
                                  (errorparameter_t)5);
         }
         openqueue_freePacketBuffer(msg);
         break;

      case TCP_STATE_FIN_WAIT_2:                                  //[receive] teardown
         if (containsControlBits(msg,TCP_ACK_WHATEVER,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_YES)) {
            //I receive FIN[+ACK], I send ACK
            tcp_vars.hisNextSeqNum = (packetfunctions_ntohl((uint8_t*)&(((tcp_ht*)msg->payload)->sequence_number)))+1;
            tempPkt = openqueue_getFreePacketBuffer(COMPONENT_OPENTCP);
            if (tempPkt==NULL) {
               openserial_printError(COMPONENT_OPENTCP,ERR_NO_FREE_PACKET_BUFFER,
                                     (errorparameter_t)0,
                                     (errorparameter_t)0);
               openqueue_freePacketBuffer(msg);
               return;
            }
            tempPkt->creator       = COMPONENT_OPENTCP;
            tempPkt->owner         = COMPONENT_OPENTCP;
            memcpy(&(tempPkt->l3_destinationAdd),&tcp_vars.hisIPv6Address,sizeof(open_addr_t));
            prependTCPHeader(tempPkt,
                  TCP_ACK_YES,
                  TCP_PSH_NO,
                  TCP_RST_NO,
                  TCP_SYN_NO,
                  TCP_FIN_NO);
            forwarding_send(tempPkt);
            tcp_change_state(TCP_STATE_ALMOST_TIME_WAIT);
         }
         openqueue_freePacketBuffer(msg);
         break;

      case TCP_STATE_CLOSING:                                     //[receive] teardown
         if (containsControlBits(msg,TCP_ACK_YES,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_NO)) {
            //I receive ACK, I do nothing
            tcp_change_state(TCP_STATE_TIME_WAIT);
            //TODO implement waiting timer
            opentcp_reset();
         }
         openqueue_freePacketBuffer(msg);
         break;

      case TCP_STATE_LAST_ACK:                                    //[receive] teardown
         if (containsControlBits(msg,TCP_ACK_YES,TCP_RST_NO,TCP_SYN_NO,TCP_FIN_NO)) {
            //I receive ACK, I reset
            opentcp_reset();
         }
         openqueue_freePacketBuffer(msg);
         break;

      default:
         openserial_printError(COMPONENT_OPENTCP,ERR_WRONG_TCP_STATE,
                               (errorparameter_t)tcp_vars.state,
                               (errorparameter_t)4);
         break;
   }
}
Ejemplo n.º 7
0
error_t fowarding_send_internal_SourceRouting(OpenQueueEntry_t *msg, ipv6_header_iht ipv6_header) {
  // It has to be forwarded to dest. so, next hop should be extracted from the message.
  uint8_t local_CmprE;
  uint8_t local_CmprI,numAddr,hlen;
  uint8_t addressposition;
  uint8_t* runningPointer;
  uint8_t octetsAddressSize;
  ipv6_Source_Routing_Header_t * ipv6_Source_Routing_Header;
  
  open_addr_t* prefix=idmanager_getMyID(ADDR_PREFIX);
 
  ipv6_Source_Routing_Header=(ipv6_Source_Routing_Header_t*)(msg->payload);
  
  
  runningPointer=(msg->payload) + sizeof(ipv6_Source_Routing_Header_t);
  
  // getting local_CmprE and CmprI;
  local_CmprE=ipv6_Source_Routing_Header->CmprICmprE & 0xf;
  local_CmprI= ipv6_Source_Routing_Header->CmprICmprE & 0xf0;
  //local_CmprI>>4; // shifting it by 4.
  local_CmprI=local_CmprI>>4; // shifting it by 4.
  
//  foundFlag=0;

    //see processing header algorithm in RFC6554 page 9
    
    numAddr=(((ipv6_Source_Routing_Header->HdrExtLen*8)-ipv6_Source_Routing_Header->PadRes -(16-local_CmprE))/(16-local_CmprI))+1;
  
  if(ipv6_Source_Routing_Header->SegmentsLeft==0){
    //we are there!..
    //process the next header in the pkt.. i.e push stack up..
    msg->l4_protocol=ipv6_Source_Routing_Header->nextHeader;
    hlen=ipv6_Source_Routing_Header->HdrExtLen;
        
    //toss header
    packetfunctions_tossHeader(msg,sizeof(ipv6_Source_Routing_Header_t));
    
    //toss list of addresses.
    if(local_CmprE==0)
    {
      octetsAddressSize=2;
      //remove 
      packetfunctions_tossHeader(msg,octetsAddressSize*hlen);   
    }
    else if(local_CmprE==8)
    {
      octetsAddressSize=8;
      packetfunctions_tossHeader(msg,octetsAddressSize*hlen);
    }
    else if(local_CmprE==2)
    {
      octetsAddressSize=16;
      packetfunctions_tossHeader(msg,octetsAddressSize*hlen);
    }
    else
    {
      msg->l2_nextORpreviousHop.type = ADDR_NONE;
      //error!
      while(1);
    }
    
    switch(msg->l4_protocol) {
    case IANA_TCP:
      opentcp_receive(msg);
      break;
    case IANA_UDP:
      openudp_receive(msg);
      break;
    case IANA_ICMPv6:
      icmpv6_receive(msg);
      break;
    default:
      openserial_printError(COMPONENT_FORWARDING,ERR_WRONG_TRAN_PROTOCOL,
                            (errorparameter_t)msg->l4_protocol,
                            (errorparameter_t)1);
    }
    
    return E_SUCCESS;
  }else{    
    if(ipv6_Source_Routing_Header->SegmentsLeft>numAddr){
      //not good.. error.
      //send and ICMPv6 parameter problem, code 0, to the src address 
      //then discard the packet.
      //TODO
      while (1);
    }else{
      //still hops remaining 
      ipv6_Source_Routing_Header->SegmentsLeft--;
      //find the address in the vector.
      addressposition=numAddr-(ipv6_Source_Routing_Header->SegmentsLeft);
      
      if(local_CmprE==0)
      {
        msg->l2_nextORpreviousHop.type = ADDR_16B;
        msg->l3_destinationAdd.type = ADDR_16B;
        octetsAddressSize=2;
        memcpy(&(msg->l2_nextORpreviousHop.addr_16b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize);
        memcpy(&(msg->l3_destinationAdd.addr_16b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize);
      }
      else if(local_CmprE==8)
      {
        msg->l2_nextORpreviousHop.type = ADDR_64B;
        msg->l3_destinationAdd.type = ADDR_128B;
        octetsAddressSize=8;
        memcpy(&(msg->l2_nextORpreviousHop.addr_64b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize);
     
        memcpy(&(msg->l3_destinationAdd.addr_128b[0]),prefix->prefix,8);
        memcpy(&(msg->l3_destinationAdd.addr_128b[8]),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize);
      }
      else if(local_CmprE==2)
      {
        msg->l2_nextORpreviousHop.type = ADDR_128B;
        msg->l3_destinationAdd.type = ADDR_128B;
        
        octetsAddressSize=16;
        memcpy(&(msg->l2_nextORpreviousHop.addr_128b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize);
        memcpy(&(msg->l3_destinationAdd.addr_128b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize);
      }
      else
      {
        msg->l2_nextORpreviousHop.type = ADDR_NONE;
        //error!
        while(1);
      }
    }
  }
  
  if (msg->l2_nextORpreviousHop.type==ADDR_NONE) {
    openserial_printError(COMPONENT_FORWARDING,ERR_NO_NEXTHOP,
                          (errorparameter_t)0,
                          (errorparameter_t)0);
    return E_FAIL;
  }
  return iphc_sendFromForwarding(msg, ipv6_header,PCKTFORWARD);
}
Ejemplo n.º 8
0
/**
\brief Send a packet using the source rout to find the next hop.

\note This is always called for packets being forwarded.

How to process the routing header is detailed in
http://tools.ietf.org/html/rfc6554#page-9.

\param[in,out] msg             The packet to send.
\param[in]     ipv6_header     The packet's IPv6 header.
*/
owerror_t forwarding_send_internal_SourceRouting(OpenMote* self, 
    OpenQueueEntry_t* msg,
    ipv6_header_iht*  ipv6_outer_header,
    ipv6_header_iht*  ipv6_inner_header,
    rpl_option_ht*    rpl_option
    ) {
    uint8_t              temp_8b;
    uint8_t              type;
    uint8_t              next_type;
    uint8_t              size;
    uint8_t              next_size;
    uint8_t              hlen;
    open_addr_t          firstAddr;
    open_addr_t          nextAddr;
    open_addr_t          temp_prefix;
    open_addr_t          temp_addr64;
    
    uint8_t              rpi_length;
    uint8_t              flags;
    uint16_t             senderRank;
    
    uint8_t              RH3_copy[127];
    uint8_t              RH3_length;
    
    memset(&RH3_copy[0],0,127);
    RH3_length = 0;
    memcpy(&msg->l3_destinationAdd,&ipv6_inner_header->dest,sizeof(open_addr_t));
    memcpy(&msg->l3_sourceAdd,&ipv6_inner_header->src,sizeof(open_addr_t));
    
    // initial first Address by compression reference
    firstAddr.type = ADDR_128B;
    if (ipv6_outer_header->src.type != ADDR_NONE){
        if (rpl_option->rplInstanceID == 0){
 icmpv6rpl_getRPLDODAGid(self, &firstAddr.addr_128b[0]);
        }
    } else {
        memcpy(&firstAddr,&ipv6_inner_header->src,sizeof(open_addr_t));
    }
    
    hlen = 0;
    
    temp_8b = *((uint8_t*)(msg->payload)+hlen);
    type    = *((uint8_t*)(msg->payload)+hlen+1);
    
    hlen += 2;
    // get the first address
    switch(type){
    case RH3_6LOTH_TYPE_0:
        memcpy(&firstAddr.addr_128b[15],msg->payload+hlen,1);
        hlen += 1;
        break;
    case RH3_6LOTH_TYPE_1:
        memcpy(&firstAddr.addr_128b[14],msg->payload+hlen,2);
        hlen += 2;
        break;
    case RH3_6LOTH_TYPE_2:
        memcpy(&firstAddr.addr_128b[12],msg->payload+hlen,4);
        hlen += 4;
        break;
    case RH3_6LOTH_TYPE_3:
        memcpy(&firstAddr.addr_128b[8],msg->payload+hlen,8);
        hlen += 8;
        break;
    case RH3_6LOTH_TYPE_4:
        memcpy(&firstAddr.addr_128b[0],msg->payload+hlen,16);
        hlen += 16;
        break;
    }
    
 packetfunctions_ip128bToMac64b(self, &firstAddr,&temp_prefix,&temp_addr64);
    if (
 packetfunctions_sameAddress(self, &temp_prefix, idmanager_getMyID(self, ADDR_PREFIX)) &&
 packetfunctions_sameAddress(self, &temp_addr64, idmanager_getMyID(self, ADDR_64B))
    ){
        size = temp_8b & RH3_6LOTH_SIZE_MASK;
        if (size > 0){
            // there are at least 2 entries in the header, 
            // the router removes the first entry and decrements the Size (by 1) 
            size -= 1;
 packetfunctions_tossHeader(self, msg,hlen);
 packetfunctions_reserveHeaderSize(self, msg,2);
            msg->payload[0] = CRITICAL_6LORH | size;
            msg->payload[1] = type;
            // get next hop
            memcpy(&nextAddr,&firstAddr,sizeof(open_addr_t));
            switch(type){
            case RH3_6LOTH_TYPE_0:
                memcpy(&nextAddr.addr_128b[15],msg->payload+2,1);
                break;
            case RH3_6LOTH_TYPE_1:
                memcpy(&nextAddr.addr_128b[14],msg->payload+2,2);
                break;
            case RH3_6LOTH_TYPE_2:
                memcpy(&nextAddr.addr_128b[12],msg->payload+2,4);
                break;
            case RH3_6LOTH_TYPE_3:
                memcpy(&nextAddr.addr_128b[8],msg->payload+2,8);
                break;
            case RH3_6LOTH_TYPE_4:
                memcpy(&nextAddr.addr_128b[0],msg->payload+2,16);
                break;
            }
 packetfunctions_ip128bToMac64b(self, 
                &nextAddr,
                &temp_prefix,
                &msg->l2_nextORpreviousHop
            );
        } else {
            temp_8b   = *((uint8_t*)(msg->payload)+hlen);
            next_type = *((uint8_t*)(msg->payload)+hlen+1);
            if (
                (temp_8b & FORMAT_6LORH_MASK) == CRITICAL_6LORH &&
                next_type<=RH3_6LOTH_TYPE_4
            ) {
                // there is another RH3-6LoRH following, check the type
                if (next_type >= type){
 packetfunctions_tossHeader(self, msg,hlen);
                    // get next hop
                    memcpy(&nextAddr,&firstAddr,sizeof(open_addr_t));
                    switch(next_type){
                    case RH3_6LOTH_TYPE_0:
                        memcpy(&nextAddr.addr_128b[15],msg->payload+2,1);
                        break;
                    case RH3_6LOTH_TYPE_1:
                        memcpy(&nextAddr.addr_128b[14],msg->payload+2,2);
                        break;
                    case RH3_6LOTH_TYPE_2:
                        memcpy(&nextAddr.addr_128b[12],msg->payload+2,4);
                        break;
                    case RH3_6LOTH_TYPE_3:
                        memcpy(&nextAddr.addr_128b[8],msg->payload+2,8);
                        break;
                    case RH3_6LOTH_TYPE_4:
                        memcpy(&nextAddr.addr_128b[0],msg->payload+2,16);
                        break;
                    }
 packetfunctions_ip128bToMac64b(self, 
                        &nextAddr,
                        &temp_prefix,
                        &msg->l2_nextORpreviousHop
                    );
                } else {
                    hlen += 2;
                    switch(next_type){
                    case RH3_6LOTH_TYPE_0:
                        memcpy(&firstAddr.addr_128b[15],msg->payload+hlen,1);
                        hlen += 1;
                        break;
                    case RH3_6LOTH_TYPE_1:
                        memcpy(&firstAddr.addr_128b[14],msg->payload+hlen,2);
                        hlen += 2;
                        break;
                    case RH3_6LOTH_TYPE_2:
                        memcpy(&firstAddr.addr_128b[12],msg->payload+hlen,4);
                        hlen += 4;
                        break;
                    case RH3_6LOTH_TYPE_3:
                        memcpy(&firstAddr.addr_128b[8],msg->payload+hlen,8);
                        hlen += 8;
                        break;
                    }
                    next_size = temp_8b & RH3_6LOTH_SIZE_MASK;
 packetfunctions_tossHeader(self, msg,hlen);
                    if (next_size>0){
                        next_size -= 1;
 packetfunctions_reserveHeaderSize(self, msg,2);
                        msg->payload[0] = CRITICAL_6LORH | next_size;
                        msg->payload[1] = next_type;
                    }
                    // add first address
                    switch(type){
                    case RH3_6LOTH_TYPE_0:
 packetfunctions_reserveHeaderSize(self, msg,1);
                        msg->payload[0] = firstAddr.addr_128b[15];
                        break;
                    case RH3_6LOTH_TYPE_1:
 packetfunctions_reserveHeaderSize(self, msg,2);
                        memcpy(&msg->payload[0],&firstAddr.addr_128b[14],2);
                        break;
                    case RH3_6LOTH_TYPE_2:
 packetfunctions_reserveHeaderSize(self, msg,4);
                        memcpy(&msg->payload[0],&firstAddr.addr_128b[12],4);
                        break;
                    case RH3_6LOTH_TYPE_3:
 packetfunctions_reserveHeaderSize(self, msg,8);
                        memcpy(&msg->payload[0],&firstAddr.addr_128b[8],8);
                        break;
                    case RH3_6LOTH_TYPE_4:
 packetfunctions_reserveHeaderSize(self, msg,16);
                        memcpy(&msg->payload[0],&firstAddr.addr_128b[0],16);
                        break;
                    }
 packetfunctions_reserveHeaderSize(self, msg,2);
                    msg->payload[0] = CRITICAL_6LORH | 0;
                    msg->payload[1] = type;
 packetfunctions_ip128bToMac64b(self, 
                        &firstAddr,
                        &temp_prefix,
                        &msg->l2_nextORpreviousHop
                    );
                }
            } else {
                // there is no next RH3-6loRH, remove current one
 packetfunctions_tossHeader(self, msg,hlen);
 packetfunctions_ip128bToMac64b(self, 
                    &msg->l3_destinationAdd,
                    &temp_prefix,
                    &msg->l2_nextORpreviousHop
                );
            }
        }
    } else {
        // log error
 openserial_printError(self, 
            COMPONENT_IPHC,
            ERR_6LOWPAN_UNSUPPORTED,
            (errorparameter_t)16,
            (errorparameter_t)(temp_addr64.addr_64b[7])
        );
    }
    // copy RH3s before toss them
    if (
        ipv6_outer_header->src.type != ADDR_NONE &&
        ipv6_outer_header->hopByhop_option != NULL
    ){
        // check the length of RH3s
        RH3_length = ipv6_outer_header->hopByhop_option-msg->payload;
        memcpy(&RH3_copy[0],msg->payload,RH3_length);
 packetfunctions_tossHeader(self, msg,RH3_length);
        
        // retrieve hop-by-hop header (includes RPL option)
        rpi_length = iphc_retrieveIPv6HopByHopHeader(self, 
                          msg,
                          rpl_option
                     );
     
        // toss the headers
 packetfunctions_tossHeader(self, 
            msg,
            rpi_length
        );
      
        flags = rpl_option->flags;
        senderRank = rpl_option->senderRank;
        if ((flags & O_FLAG)!=O_FLAG){
            // wrong direction
            // log error
 openserial_printError(self, 
                COMPONENT_FORWARDING,
                ERR_WRONG_DIRECTION,
                (errorparameter_t)flags,
                (errorparameter_t)senderRank
            );
        }
        if (senderRank > neighbors_getMyDAGrank(self)){
            // loop detected
            // set flag
            rpl_option->flags |= R_FLAG;
            // log error
 openserial_printError(self, 
                COMPONENT_FORWARDING,
                ERR_LOOP_DETECTED,
                (errorparameter_t) senderRank,
                (errorparameter_t) neighbors_getMyDAGrank(self)
            );
        }
 forwarding_createRplOption(self, rpl_option, rpl_option->flags);
        // toss the IP in IP 6LoRH
 packetfunctions_tossHeader(self, msg, ipv6_outer_header->header_length);
    } else {
        RH3_length = 0;
    }
    
    // send to next lower layer
    return iphc_sendFromForwarding(self, 
        msg,
        ipv6_outer_header,
        ipv6_inner_header,
        rpl_option,
        &ipv6_outer_header->flow_label,
        &RH3_copy[0],
        RH3_length,
        PCKTFORWARD
    );
}
Ejemplo n.º 9
0
/**
\brief Indicates a packet was received.

\param[in,out] msg               The packet just sent.
\param[in]     ipv6_header       The information contained in the IPv6 header.
\param[in]     ipv6_hop_header   The hop-by-hop header present in the packet.
\param[in]     rpl_option        The hop-by-hop options present in the packet.
*/
void forwarding_receive(OpenMote* self, 
      OpenQueueEntry_t*      msg,
      ipv6_header_iht*       ipv6_outer_header,
      ipv6_header_iht*       ipv6_inner_header,
      rpl_option_ht*         rpl_option
    ) {
    uint8_t flags;
    uint16_t senderRank;
   
    // take ownership
    msg->owner                     = COMPONENT_FORWARDING;
   
    // determine L4 protocol
    // get information from ipv6_header
    msg->l4_protocol            = ipv6_inner_header->next_header;
    msg->l4_protocol_compressed = ipv6_inner_header->next_header_compressed;
   
    // populate packets metadata with L3 information
    memcpy(&(msg->l3_destinationAdd),&ipv6_inner_header->dest, sizeof(open_addr_t));
    memcpy(&(msg->l3_sourceAdd),     &ipv6_inner_header->src,  sizeof(open_addr_t));
   
    if (
        (
 idmanager_isMyAddress(self, &(msg->l3_destinationAdd))
            ||
 packetfunctions_isBroadcastMulticast(self, &(msg->l3_destinationAdd))
        )
        &&
        ipv6_outer_header->next_header!=IANA_IPv6ROUTE
    ) {
        if (ipv6_outer_header->src.type != ADDR_NONE){
 packetfunctions_tossHeader(self, msg,ipv6_outer_header->header_length);
        }
        // this packet is for me, no source routing header // toss iphc inner header
 packetfunctions_tossHeader(self, msg,ipv6_inner_header->header_length);
        // indicate received packet to upper layer
        switch(msg->l4_protocol) {
        case IANA_TCP:
 opentcp_receive(self, msg);
            break;
        case IANA_UDP:
 openudp_receive(self, msg);
            break;
        case IANA_ICMPv6:
 icmpv6_receive(self, msg);
            break;
        default:
            // log error
 openserial_printError(self, 
                COMPONENT_FORWARDING,ERR_WRONG_TRAN_PROTOCOL,
                (errorparameter_t)msg->l4_protocol,
                (errorparameter_t)1
            );
            
            // free packet
 openqueue_freePacketBuffer(self, msg);
        }
    } else {
        // this packet is not for me: relay
      
        // change the creator of the packet
        msg->creator = COMPONENT_FORWARDING;
      
        if (ipv6_outer_header->next_header!=IANA_IPv6ROUTE) {
            flags = rpl_option->flags;
            senderRank = rpl_option->senderRank;
            if ((flags & O_FLAG)!=0){
                // wrong direction
                // log error
 openserial_printError(self, 
                    COMPONENT_FORWARDING,
                    ERR_WRONG_DIRECTION,
                    (errorparameter_t)flags,
                    (errorparameter_t)senderRank
                );
            }
            if (senderRank < neighbors_getMyDAGrank(self)){
                // loop detected
                // set flag
                rpl_option->flags |= R_FLAG;
                // log error
 openserial_printError(self, 
                    COMPONENT_FORWARDING,
                    ERR_LOOP_DETECTED,
                    (errorparameter_t) senderRank,
                    (errorparameter_t) neighbors_getMyDAGrank(self)
                );
            }
 forwarding_createRplOption(self, rpl_option, rpl_option->flags);
            // resend as if from upper layer
            if (
 forwarding_send_internal_RoutingTable(self, 
                    msg,
                    ipv6_outer_header,
                    ipv6_inner_header,
                    rpl_option,
                    &(ipv6_outer_header->flow_label),
                    PCKTFORWARD 
                )==E_FAIL
            ) {
 openqueue_freePacketBuffer(self, msg);
            }
        } else {
            // source routing header present
            if (
 forwarding_send_internal_SourceRouting(self, 
                    msg,
                    ipv6_outer_header,
                    ipv6_inner_header,
                    rpl_option
                )==E_FAIL
            ) {
                // log error
 openserial_printError(self, 
                    COMPONENT_FORWARDING,
                    ERR_INVALID_FWDMODE,
                    (errorparameter_t)0,
                    (errorparameter_t)0
                );
            }
        }
    }
}