void mldProcessListenerReport(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const ChunkedBuffer *buffer, size_t offset, uint8_t hopLimit) { uint_t i; size_t length; MldMessage *message; Ipv6FilterEntry *entry; //Retrieve the length of the MLD message length = chunkedBufferGetLength(buffer) - offset; //The message must be at least 24 octets long if(length < sizeof(MldMessage)) return; //Point to the beginning of the MLD message message = chunkedBufferAt(buffer, offset); //Sanity check if(!message) return; //Debug message TRACE_INFO("MLD message received (%" PRIuSIZE " bytes)...\r\n", length); //Dump message contents for debugging purpose mldDumpMessage(message); //Make sure the source address of the message is a valid link-local address if(!ipv6IsLinkLocalUnicastAddr(&pseudoHeader->srcAddr)) return; //Check the Hop Limit field if(hopLimit != MLD_HOP_LIMIT) return; //Acquire exclusive access to the IPv6 filter table osMutexAcquire(interface->ipv6FilterMutex); //Loop through filter table entries for(i = 0; i < interface->ipv6FilterSize; i++) { //Point to the current entry entry = &interface->ipv6Filter[i]; //Report messages are ignored for multicast addresses //in the Non-Listener or Idle Listener state if(entry->state == MLD_STATE_DELAYING_LISTENER) { //The Multicast Listener Report message matches the current entry? if(ipv6CompAddr(&message->multicastAddr, &entry->addr)) { //Clear flag entry->flag = FALSE; //Switch to the Idle Listener state entry->state = MLD_STATE_IDLE_LISTENER; } } } //Release exclusive access to the IPv6 filter table osMutexRelease(interface->ipv6FilterMutex); }
void ndpProcessRouterAdv(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const ChunkedBuffer *buffer, size_t offset, uint8_t hopLimit) { size_t length; NdpRouterAdvMessage *message; //Retrieve the length of the message length = chunkedBufferGetLength(buffer) - offset; //Check the length of the Router Advertisement message if(length < sizeof(NdpRouterAdvMessage)) return; //Point to the beginning of the message message = chunkedBufferAt(buffer, offset); //Sanity check if(!message) return; //Debug message TRACE_INFO("Router Advertisement message received (%" PRIuSIZE " bytes)...\r\n", length); //Dump message contents for debugging purpose ndpDumpRouterAdvMessage(message); //Routers must use their link-local address as the source for the //Router Advertisement so that hosts can uniquely identify routers if(!ipv6IsLinkLocalUnicastAddr(&pseudoHeader->srcAddr)) return; //The IPv6 Hop Limit field must have a value of 255 to ensure //that the packet has not been forwarded by a router if(hopLimit != NDP_HOP_LIMIT) return; //ICMPv6 Code must be 0. An advertisement that passes the validity //checks is called a valid advertisement if(message->code) return; #if (SLAAC_SUPPORT == ENABLED) //Stateless Address Autoconfiguration is currently used? if(interface->slaacContext != NULL) { //Process the valid advertisement slaacProcessRouterAdv(interface->slaacContext, &pseudoHeader->srcAddr, message, length); } #endif }
void mldProcessListenerQuery(NetInterface *interface, Ipv6PseudoHeader *pseudoHeader, const ChunkedBuffer *buffer, size_t offset, uint8_t hopLimit) { uint_t i; size_t length; systime_t time; systime_t maxRespDelay; MldMessage *message; Ipv6FilterEntry *entry; //Retrieve the length of the MLD message length = chunkedBufferGetLength(buffer) - offset; //The message must be at least 24 octets long if(length < sizeof(MldMessage)) return; //Point to the beginning of the MLD message message = chunkedBufferAt(buffer, offset); //Sanity check if(!message) return; //Debug message TRACE_INFO("MLD message received (%" PRIuSIZE " bytes)...\r\n", length); //Dump message contents for debugging purpose mldDumpMessage(message); //Make sure the source address of the message is a valid link-local address if(!ipv6IsLinkLocalUnicastAddr(&pseudoHeader->srcAddr)) return; //Check the Hop Limit field if(hopLimit != MLD_HOP_LIMIT) return; //Get current time time = osGetTickCount(); //The Max Resp Delay field specifies the maximum time allowed //before sending a responding report maxRespDelay = message->maxRespDelay * 10; //Acquire exclusive access to the IPv6 filter table osMutexAcquire(interface->ipv6FilterMutex); //Loop through filter table entries for(i = 0; i < interface->ipv6FilterSize; i++) { //Point to the current entry entry = &interface->ipv6Filter[i]; //The link-scope all-nodes address (FF02::1) is handled as a special //case. The host starts in Idle Listener state for that address on //every interface and never transitions to another state if(ipv6CompAddr(&entry->addr, &IPV6_LINK_LOCAL_ALL_NODES_ADDR)) continue; //A General Query is used to learn which multicast addresses have listeners //on an attached link. A Multicast-Address-Specific Query is used to learn //if a particular multicast address has any listeners on an attached link if(ipv6CompAddr(&message->multicastAddr, &IPV6_UNSPECIFIED_ADDR) || ipv6CompAddr(&message->multicastAddr, &entry->addr)) { //Delaying Listener state? if(entry->state == MLD_STATE_DELAYING_LISTENER) { //The timer has not yet expired? if(timeCompare(time, entry->timer) < 0) { //If a timer for the address is already running, it is reset to //the new random value only if the requested Max Response Delay //is less than the remaining value of the running timer if(maxRespDelay < (entry->timer - time)) { //Restart delay timer entry->timer = time + mldRand(maxRespDelay); } } } //Idle Listener state? else if(entry->state == MLD_STATE_IDLE_LISTENER) { //Switch to the Delaying Listener state entry->state = MLD_STATE_DELAYING_LISTENER; //Delay the response by a random amount of time entry->timer = time + mldRand(maxRespDelay); } } } //Release exclusive access to the IPv6 filter table osMutexRelease(interface->ipv6FilterMutex); }