示例#1
0
/**
 * Join a group on a network interface.
 *
 * @param srcaddr ipv6 address of the network interface which should
 *                join a new group. If IP6_ADDR_ANY, join on all netifs
 * @param groupaddr the ipv6 address of the group to join
 * @return ERR_OK if group was joined on the netif(s), an err_t otherwise
 */
err_t
mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr)
{
  err_t              err = ERR_VAL; /* no matching interface */
  struct mld_group  *group;
  struct netif      *netif;
  u8_t               match;
  u8_t               i;

  /* loop through netif's */
  netif = netif_list;
  while (netif != NULL) {
    /* Should we join this interface ? */
    match = 0;
    if (ip6_addr_isany(srcaddr)) {
      match = 1;
    }
    else {
      for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
        if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) &&
            ip6_addr_cmp(srcaddr, netif_ip6_addr(netif, i))) {
          match = 1;
          break;
        }
      }
    }
    if (match) {
      /* find group or create a new one if not found */
      group = mld6_lookfor_group(netif, groupaddr);

      if (group == NULL) {
        /* Joining a new group. Create a new group entry. */
        group = mld6_new_group(netif, groupaddr);
        if (group == NULL) {
          return ERR_MEM;
        }

        /* Activate this address on the MAC layer. */
        if (netif->mld_mac_filter != NULL) {
          netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER);
        }

        /* Report our membership. */
        MLD6_STATS_INC(mld6.tx_report);
        mld6_send(group, ICMP6_TYPE_MLR);
        mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS);
      }

      /* Increment group use */
      group->use++;
      err = ERR_OK;
    }

    /* proceed to next network interface */
    netif = netif->next;
  }

  return err;
}
示例#2
0
/**
 * Report MLD memberships for this interface
 *
 * @param netif network interface on which report MLD memberships
 */
void
mld6_report_groups(struct netif *netif)
{
  struct mld_group *group = mld_group_list;

  while (group != NULL) {
    if (group->netif == netif) {
      mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR);
    }
    group = group->next;
  }
}
示例#3
0
/**
 * Process an input MLD message. Called by icmp6_input.
 *
 * @param p the mld packet, p->payload pointing to the icmpv6 header
 * @param inp the netif on which this packet was received
 */
void
mld6_input(struct pbuf *p, struct netif *inp)
{
  struct mld_header * mld_hdr;
  struct mld_group* group;

  MLD6_STATS_INC(mld6.recv);

  /* Check that mld header fits in packet. */
  if (p->len < sizeof(struct mld_header)) {
    // TODO debug message
    pbuf_free(p);
    MLD6_STATS_INC(mld6.lenerr);
    MLD6_STATS_INC(mld6.drop);
    return;
  }

  mld_hdr = (struct mld_header *)p->payload;

  switch (mld_hdr->type) {
  case ICMP6_TYPE_MLQ: /* Multicast listener query. */
  {
    /* Is it a general query? */
    if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) &&
        ip6_addr_isany(&(mld_hdr->multicast_address))) {
      MLD6_STATS_INC(mld6.rx_general);
      /* Report all groups, except all nodes group, and if-local groups. */
      group = mld_group_list;
      while (group != NULL) {
        if ((group->netif == inp) &&
            (!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) &&
            (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) {
          mld6_delayed_report(group, mld_hdr->max_resp_delay);
        }
        group = group->next;
      }
    }
    else {
      /* Have we joined this group?
       * We use IP6 destination address to have a memory aligned copy.
       * mld_hdr->multicast_address should be the same. */
      MLD6_STATS_INC(mld6.rx_group);
      group = mld6_lookfor_group(inp, ip6_current_dest_addr());
      if (group != NULL) {
        /* Schedule a report. */
        mld6_delayed_report(group, mld_hdr->max_resp_delay);
      }
    }
    break; /* ICMP6_TYPE_MLQ */
  }
  case ICMP6_TYPE_MLR: /* Multicast listener report. */
  {
    /* Have we joined this group?
     * We use IP6 destination address to have a memory aligned copy.
     * mld_hdr->multicast_address should be the same. */
    MLD6_STATS_INC(mld6.rx_report);
    group = mld6_lookfor_group(inp, ip6_current_dest_addr());
    if (group != NULL) {
      /* If we are waiting to report, cancel it. */
      if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) {
        group->timer = 0; /* stopped */
        group->group_state = MLD6_GROUP_IDLE_MEMBER;
        group->last_reporter_flag = 0;
      }
    }
    break; /* ICMP6_TYPE_MLR */
  }
  case ICMP6_TYPE_MLD: /* Multicast listener done. */
  {
    /* Do nothing, router will query us. */
    break; /* ICMP6_TYPE_MLD */
  }
  default:
    MLD6_STATS_INC(mld6.proterr);
    MLD6_STATS_INC(mld6.drop);
    break;
  }

  pbuf_free(p);
}