Exemple #1
0
error_t statelessAddrConfig(NetInterface *interface)
{
   error_t error;
   Eui64 interfaceId;
   Ipv6Addr linkLocalAddr;
   Ipv6Addr solicitedNodeAddr;

   //Generate the 64-bit interface identifier
   macAddrToEui64(&interface->macAddr, &interfaceId);

   //A link-local address is formed by combining the well-known
   //link-local prefix fe80::0 with the interface identifier
   linkLocalAddr.w[0] = htons(0xFE80);
   linkLocalAddr.w[1] = htons(0x0000);
   linkLocalAddr.w[2] = htons(0x0000);
   linkLocalAddr.w[3] = htons(0x0000);
   linkLocalAddr.w[4] = interfaceId.w[0];
   linkLocalAddr.w[5] = interfaceId.w[1];
   linkLocalAddr.w[6] = interfaceId.w[2];
   linkLocalAddr.w[7] = interfaceId.w[3];

   //Form the Solicited-Node address
   ipv6ComputeSolicitedNodeAddr(&linkLocalAddr, &solicitedNodeAddr);
   //Join the Solicited-Node multicast group for the tentative address
   ipv6JoinMulticastGroup(interface, &solicitedNodeAddr);

   //Ensure that the address is not already in use on the local network
   error = slaacDetectDuplicateAddr(&linkLocalAddr);
   //If a duplicate address is discovered during the procedure,
   //the address cannot be assigned to the interface
   if(error)
   {
      ipv6LeaveMulticastGroup(interface, &solicitedNodeAddr);
      return error;
   }

   //Assign the link-local address to the local IPv6 address
   interface->ipv6Config.linkLocalAddr = linkLocalAddr;

   //The node next attempts to contact a local router for more
   //information on continuing the configuration

   //The global address is formed by appending the interface
   //identifier to a prefix of appropriate length

   //Successful configuration
   return NO_ERROR;
}
Exemple #2
0
void slaacProcessRouterAdv(SlaacContext *context,
   const Ipv6Addr *srcAddr, NdpRouterAdvMessage *message, size_t length)
{
   uint_t i;
   uint_t n;
   NdpPrefixInfoOption *prefixInfoOption;
   NdpRdnssOption *rdnssOption;
   Eui64 interfaceId;
   Ipv6Addr globalAddr;

   //Check current state
   if(context->state != SLAAC_STATE_ROUTER_SOLICIT)
      return;

   //Save router address
   ipv6SetRouter(context->interface, srcAddr);

   //Calculate the length of the Options field
   length -= sizeof(NdpRouterAdvMessage);

   //Search for the Prefix Information option
   prefixInfoOption = ndpGetOption(message->options, length, NDP_OPT_PREFIX_INFORMATION);

   //Prefix Information option not found?
   if(prefixInfoOption == NULL || prefixInfoOption->length != 4)
      return;

   //If the Autonomous flag is not set, silently ignore the Prefix
   //Information option
   if(!prefixInfoOption->a)
      return;

   //If the prefix is the link-local prefix, silently ignore the
   //Prefix Information option
   if(ipv6CompPrefix(&prefixInfoOption->prefix, &IPV6_LINK_LOCAL_ADDR_PREFIX, 64))
      return;

   //If the preferred lifetime is greater than the valid lifetime,
   //silently ignore the Prefix Information option
   if(prefixInfoOption->preferredLifetime > prefixInfoOption->validLifetime)
      return;

   //If the sum of the prefix length and interface identifier length does
   //not equal 128 bits, the Prefix Information option must be ignored
   if(prefixInfoOption->prefixLength != 64)
      return;

   //Save IPv6 prefix
   ipv6SetPrefix(context->interface, &prefixInfoOption->prefix,
      prefixInfoOption->prefixLength);

   //Generate the 64-bit interface identifier
   macAddrToEui64(&context->interface->macAddr, &interfaceId);

   //Form an address by combining the advertised prefix
   //with the interface identifier
   globalAddr.w[0] = prefixInfoOption->prefix.w[0];
   globalAddr.w[1] = prefixInfoOption->prefix.w[1];
   globalAddr.w[2] = prefixInfoOption->prefix.w[2];
   globalAddr.w[3] = prefixInfoOption->prefix.w[3];
   globalAddr.w[4] = interfaceId.w[0];
   globalAddr.w[5] = interfaceId.w[1];
   globalAddr.w[6] = interfaceId.w[2];
   globalAddr.w[7] = interfaceId.w[3];

   //Use the global address as a tentative address
   ipv6SetGlobalAddr(context->interface, &globalAddr, IPV6_ADDR_STATE_TENTATIVE);

   //Use the DNS servers provided by the router?
   if(!context->manualDnsConfig)
   {
      //Search for the Recursive DNS Server (RDNSS) option
      rdnssOption = ndpGetOption(message->options, length, NDP_OPT_RECURSIVE_DNS_SERVER);

      //RDNSS option found?
      if(rdnssOption != NULL && rdnssOption->length >= 1)
      {
         //Retrieve the number of addresses
         n = (rdnssOption->length - 1) / 2;

         //Save DNS servers
         for(i = 0; i < n; i++)
            ipv6SetDnsServer(context->interface, i, &rdnssOption->address[i]);
      }
   }

   //Set time stamp
   context->timestamp = osGetSystemTime();
   //Reset timeout value
   context->timeout = 0;
   //Reset retransmission counter
   context->retransmitCount = 0;

   //Verify the uniqueness of the global address
   context->state = SLAAC_STATE_GLOBAL_ADDR_DAD;
}
Exemple #3
0
void slaacTick(SlaacContext *context)
{
   systime_t time;

   //Get current time
   time = osGetSystemTime();

   //Enter critical section
   osAcquireMutex(&context->mutex);

   //Check current state
   if(context->state == SLAAC_STATE_INIT)
   {
      //Check link state
      if(context->running && context->interface->linkState)
      {
         Eui64 interfaceId;
         Ipv6Addr linkLocalAddr;

         //Generate the 64-bit interface identifier
         macAddrToEui64(&context->interface->macAddr, &interfaceId);

         //A link-local address is formed by combining the well-known
         //link-local prefix fe80::0 with the interface identifier
         linkLocalAddr.w[0] = htons(0xFE80);
         linkLocalAddr.w[1] = htons(0x0000);
         linkLocalAddr.w[2] = htons(0x0000);
         linkLocalAddr.w[3] = htons(0x0000);
         linkLocalAddr.w[4] = interfaceId.w[0];
         linkLocalAddr.w[5] = interfaceId.w[1];
         linkLocalAddr.w[6] = interfaceId.w[2];
         linkLocalAddr.w[7] = interfaceId.w[3];

         //Use the link-local address as a tentative address
         ipv6SetLinkLocalAddr(context->interface,
            &linkLocalAddr, IPV6_ADDR_STATE_TENTATIVE);

         //Set time stamp
         context->timestamp = time;
         //Reset timeout value
         context->timeout = 0;
         //Reset retransmission counter
         context->retransmitCount = 0;

         //Verify the uniqueness of the link-local address
         context->state = SLAAC_STATE_LINK_LOCAL_ADDR_DAD;
      }
   }
   else if(context->state == SLAAC_STATE_LINK_LOCAL_ADDR_DAD)
   {
      //Check current time
      if((time - context->timestamp) >= context->timeout)
      {
         //Duplicate Address Detection failed?
         if(context->interface->ipv6Config.linkLocalAddrDup)
         {
            //A tentative address that is determined to be a duplicate
            //must not be assigned to an interface
            ipv6SetLinkLocalAddr(context->interface,
               &IPV6_UNSPECIFIED_ADDR, IPV6_ADDR_STATE_INVALID);

            //Address autoconfiguration failed
            context->state = SLAAC_STATE_ERROR;

            //Dump current IPv6 configuration for debugging purpose
            slaacDumpConfig(context);
         }
#if (NDP_DUP_ADDR_DETECT_TRANSMITS > 0)
         //Duplicate Address Detection is on-going?
         else if(context->retransmitCount < NDP_DUP_ADDR_DETECT_TRANSMITS)
         {
            //Send Neighbor Solicitation message
            ndpSendNeighborSol(context->interface, &context->interface->ipv6Config.linkLocalAddr);

            //Save the time at which the message was sent
            context->timestamp = time;
            //Set timeout value
            context->timeout = NDP_RETRANS_TIMER;
            //Increment retransmission counter
            context->retransmitCount++;
         }
#endif
         //Duplicate Address Detection is complete?
         else
         {
            //The use of the link-local address is now unrestricted
            context->interface->ipv6Config.linkLocalAddrState = IPV6_ADDR_STATE_PREFERRED;

            //Set time stamp
            context->timestamp = time;
            //Delay before transmitting the first Router Solicitation message
            context->timeout = tcpIpStackGetRandRange(0, NDP_MAX_RTR_SOLICITATION_DELAY);
            //Reset retransmission counter
            context->retransmitCount = 0;

            //To obtain an advertisement quickly, a host sends out Router Solicitations
            context->state = SLAAC_STATE_ROUTER_SOLICIT;
         }
      }
   }
   else if(context->state == SLAAC_STATE_ROUTER_SOLICIT)
   {
      //Check current time
      if((time - context->timestamp) >= context->timeout)
      {
         //Check retransmission counter
         if(context->retransmitCount < NDP_MAX_RTR_SOLICITATIONS)
         {
            //Send Router Solicitation message
            ndpSendRouterSol(context->interface);

            //Save the time at which the message was sent
            context->timestamp = time;
            //Set timeout value
            context->timeout = NDP_RTR_SOLICITATION_INTERVAL;
            //Increment retransmission counter
            context->retransmitCount++;
         }
         else
         {
            //A link has no routers if no Router Advertisements are received
            //after having sent a small number of Router Solicitations
            context->state = SLAAC_STATE_ERROR;

            //Dump current IPv6 configuration for debugging purpose
            slaacDumpConfig(context);
         }
      }
   }
   else if(context->state == SLAAC_STATE_GLOBAL_ADDR_DAD)
   {
      //Check current time
      if((time - context->timestamp) >= context->timeout)
      {
         //Duplicate Address Detection failed?
         if(context->interface->ipv6Config.globalAddrDup)
         {
            //A tentative address that is determined to be a duplicate
            //must not be assigned to an interface
            ipv6SetGlobalAddr(context->interface,
               &IPV6_UNSPECIFIED_ADDR, IPV6_ADDR_STATE_INVALID);

            //Address autoconfiguration failed
            context->state = SLAAC_STATE_ERROR;

            //Dump current IPv6 configuration for debugging purpose
            slaacDumpConfig(context);
         }
#if (NDP_DUP_ADDR_DETECT_TRANSMITS > 0)
         //Duplicate Address Detection is on-going?
         else if(context->retransmitCount < NDP_DUP_ADDR_DETECT_TRANSMITS)
         {
            //Send Neighbor Solicitation message
            ndpSendNeighborSol(context->interface, &context->interface->ipv6Config.globalAddr);

            //Save the time at which the message was sent
            context->timestamp = time;
            //Set timeout value
            context->timeout = NDP_RETRANS_TIMER;
            //Increment retransmission counter
            context->retransmitCount++;
         }
#endif
         //Duplicate Address Detection is complete?
         else
         {
            //The use of the global address is now unrestricted
            context->interface->ipv6Config.globalAddrState = IPV6_ADDR_STATE_PREFERRED;
            //Successful address autoconfiguration
            context->state = SLAAC_STATE_CONFIGURED;

            //Dump current IPv6 configuration for debugging purpose
            slaacDumpConfig(context);
         }
      }
   }

   //Leave critical section
   osReleaseMutex(&context->mutex);
}
Exemple #4
0
error_t wilc1000Init(NetInterface *interface)
{
   int8_t status;
   tstrWifiInitParam param;

   //STA or AP mode?
   if(interface->nicDriver == &wilc1000StaDriver)
   {
      //Debug message
      TRACE_INFO("Initializing WILC1000 (STA mode)...\r\n");
   }
   else
   {
      //Debug message
      TRACE_INFO("Initializing WILC1000 (AP mode)...\r\n");
   }

   //Start of exception handling block
   do
   {
      //Initialization sequence is performed once at startup
      if(wilc1000StaInterface == NULL && wilc1000ApInterface == NULL)
      {
         //Low-level initialization
         status = nm_bsp_init();

         //Check status code
         if(status != M2M_SUCCESS)
            break;

         //Set default parameters
         memset(&param, 0, sizeof(param));

         //Register callback functions
         param.pfAppWifiCb = wilc1000AppWifiEvent;
         param.pfAppMonCb = NULL;
         param.strEthInitParam.pfAppWifiCb = NULL;
         param.strEthInitParam.pfAppEthCb = wilc1000AppEthEvent;

         //Set receive buffer
         param.strEthInitParam.au8ethRcvBuf = rxBuffer;
         param.strEthInitParam.u16ethRcvBufSize = WILC1000_RX_BUFFER_SIZE - ETH_CRC_SIZE;

         //Initialize WILC1000 controller
         status = m2m_wifi_init(&param);

         //Check status code
         if(status != M2M_SUCCESS)
            break;

         //Optionally set the station MAC address
         if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
         {
            //Use the factory preprogrammed station address
            status = m2m_wifi_get_mac_address(interface->macAddr.b);

            //Check status code
            if(status != M2M_SUCCESS)
               break;

            //Generate the 64-bit interface identifier
            macAddrToEui64(&interface->macAddr, &interface->eui64);
         }
         else
         {
            //Override the factory preprogrammed address
            status = m2m_wifi_set_mac_address(interface->macAddr.b);

            //Check status code
            if(status != M2M_SUCCESS)
               break;
         }
      }
      else
      {
         //Initialization was already done
         status = M2M_SUCCESS;
      }

      //STA or AP mode?
      if(interface->nicDriver == &wilc1000StaDriver)
      {
         //Save underlying network interface (STA mode)
         wilc1000StaInterface = interface;

         if(wilc1000ApInterface != NULL)
         {
            wilc1000StaInterface->macAddr = wilc1000ApInterface->macAddr;
            wilc1000StaInterface->eui64 = wilc1000ApInterface->eui64;
         }
      }
      else
      {
         //Save underlying network interface (AP mode)
         wilc1000ApInterface = interface;

         if(wilc1000StaInterface != NULL)
         {
            wilc1000ApInterface->macAddr = wilc1000StaInterface->macAddr;
            wilc1000ApInterface->eui64 = wilc1000StaInterface->eui64;
         }
      }

      //End of exception handling block
   } while(0);

   //WILC1000 is now ready to send
   osSetEvent(&interface->nicTxEvent);

   //Return status code
   if(status == M2M_SUCCESS)
      return NO_ERROR;
   else
      return ERROR_FAILURE;
}