예제 #1
0
/**
 * Send a MLD message (report or done).
 *
 * An IPv6 hop-by-hop options header with a router alert option
 * is prepended.
 *
 * @param group the group to report or quit
 * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done)
 */
static void
mld6_send(struct mld_group *group, u8_t type)
{
  struct mld_header * mld_hdr;
  struct pbuf * p;
  ip6_addr_t * src_addr;

  /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */
  p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM);
  if ((p == NULL) || (p->len < (sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr)))) {
    /* We couldn't allocate a suitable pbuf. drop it. */
    if (p != NULL) {
      pbuf_free(p);
    }
    MLD6_STATS_INC(mld6.memerr);
    return;
  }

  /* Move to make room for Hop-by-hop options header. */
  if (pbuf_header(p, -IP6_HBH_HLEN)) {
    pbuf_free(p);
    MLD6_STATS_INC(mld6.lenerr);
    return;
  }

  /* Select our source address. */
  if (!ip6_addr_isvalid(netif_ip6_addr_state(group->netif, 0))) {
    /* This is a special case, when we are performing duplicate address detection.
     * We must join the multicast group, but we don't have a valid address yet. */
    src_addr = IP6_ADDR_ANY;
  } else {
    /* Use link-local address as source address. */
    src_addr = netif_ip6_addr(group->netif, 0);
  }

  /* MLD message header pointer. */
  mld_hdr = (struct mld_header *)p->payload;

  /* Set fields. */
  mld_hdr->type = type;
  mld_hdr->code = 0;
  mld_hdr->chksum = 0;
  mld_hdr->max_resp_delay = 0;
  mld_hdr->reserved = 0;
  ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address));

#if CHECKSUM_GEN_ICMP6
  mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len,
    src_addr, &(group->group_address));
#endif /* CHECKSUM_GEN_ICMP6 */

  /* Add hop-by-hop headers options: router alert with MLD value. */
  ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD);

  /* Send the packet out. */
  MLD6_STATS_INC(mld6.xmit);
  ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address),
      MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, group->netif);
  pbuf_free(p);
}
예제 #2
0
/**
 * Mapping from local network to loopback for outbound connections.
 *
 * Copy "src" to "dst" with ip6_addr_set(dst, src), but if "src" is a
 * local network address that maps host's loopback address, copy IPv6
 * loopback address to "dst".
 */
int
pxremap_outbound_ip6(ip6_addr_t *dst, ip6_addr_t *src)
{
    struct netif *netif;
    int i;

    LWIP_ASSERT1(dst != NULL);
    LWIP_ASSERT1(src != NULL);

    for (netif = netif_list; netif != NULL; netif = netif->next) {
        if (!netif_is_up(netif) /* || this is not a proxy netif */) {
            continue;
        }

        for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
            if (ip6_addr_ispreferred(netif_ip6_addr_state(netif, i))
                && ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)))
            {
                ip6_addr_t *ifaddr = netif_ip6_addr(netif, i);
                if (memcmp(src, ifaddr, sizeof(ip6_addr_t) - 1) == 0
                    && ((IP6_ADDR_BLOCK8(src) & 0xff)
                        == (IP6_ADDR_BLOCK8(ifaddr) & 0xff) + 1))
                {
                    ip6_addr_set_loopback(dst);
                    return PXREMAP_MAPPED;
                }
            }
        }
    }

    /* not remapped, just copy src */
    ip6_addr_set(dst, src);
    return PXREMAP_ASIS;
}
예제 #3
0
파일: ip6.c 프로젝트: ORCOS/ORCOS
err_t ip6_output_if(struct pbuf *p, struct ip6_addr *src, struct ip6_addr *dest, u8_t ttl, u8_t proto, struct netif *netif) {
    struct ip6_hdr *iphdr;

    PERF_START;

    LWIP_DEBUGF(IP_DEBUG, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len));
    if (pbuf_header(p, IP6_HLEN)) {
        LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));IP_STATS_INC(ip.err);

        return ERR_BUF;
    }
    LWIP_DEBUGF(IP_DEBUG, ("len %"U16_F" tot_len %"U16_F"\n", p->len, p->tot_len));

    iphdr = p->payload;

    if (dest != IP_HDRINCL) {
        LWIP_DEBUGF(IP_DEBUG, ("!IP_HDRLINCL\n"));
        iphdr->hoplim = ttl;
        iphdr->nexthdr = proto;
        iphdr->len = htons(p->tot_len - IP6_HLEN);
        ip6_addr_set(&(iphdr->dest), dest);

        iphdr->v = 6;

        if (ip6_addr_isany(src)) {
            ip6_addr_set(&(iphdr->src), &(netif->ip6_addr));
        } else {
            ip6_addr_set(&(iphdr->src), src);
        }
    } else {
        dest = &(iphdr->dest);
    }

    IP_STATS_INC(ip.xmit);

    LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %"U16_F")\n", netif->name[0], netif->name[1], p->tot_len));
#if IP_DEBUG
    ip6_debug_print(p);
#endif /* IP_DEBUG */

    PERF_STOP("ip_output_if");
    if (netif->ip6_output != 0) {
        return (netif->ip6_output(netif, p, dest));
    } else {
        return (ERR_RTE);
    }
}
예제 #4
0
/**
 * Mapping from loopback to local network for inbound (port-forwarded)
 * connections.
 *
 * Copy "src" to "dst" with ip6_addr_set(dst, src), but if "src" is a
 * host's loopback address, copy local network address that maps it to
 * "dst".
 */
int
pxremap_inbound_ip6(ip6_addr_t *dst, ip6_addr_t *src)
{
    ip6_addr_t loopback;
    struct netif *netif;
    int i;

    ip6_addr_set_loopback(&loopback);
    if (!ip6_addr_cmp(src, &loopback)) {
        ip6_addr_set(dst, src);
        return PXREMAP_ASIS;
    }

#if 0  /* ?TODO: with multiple interfaces we need to consider fwspec::dst */
    netif = ip6_route_fwd(target);
    if (netif == NULL) {
        return PXREMAP_FAILED;
    }
#else
    netif = netif_list;
    LWIP_ASSERT1(netif != NULL);
    LWIP_ASSERT1(netif->next == NULL);
#endif

    for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) {
        ip6_addr_t *ifaddr = netif_ip6_addr(netif, i);
        if (ip6_addr_ispreferred(netif_ip6_addr_state(netif, i))
            && ip6_addr_isuniquelocal(ifaddr))
        {
            ip6_addr_set(dst, ifaddr);
            ++((u8_t *)&dst->addr[3])[3];
            return PXREMAP_MAPPED;
        }
    }

    return PXREMAP_FAILED;
}
예제 #5
0
파일: netif.c 프로젝트: EagleSmith/ESP31B
/** Create a link-local IPv6 address on a netif (stored in slot 0)
 *
 * @param netif the netif to create the address on
 * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion)
 *                       if == 0, use hwaddr directly as interface ID
 */
void
netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
{
  u8_t i, addr_index;

  /* Link-local prefix. */
  ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul);
  ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0;

  /* Generate interface ID. */
  if (from_mac_48bit) {
    /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
    ip_2_ip6(&netif->ip6_addr[0])->addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
        ((u32_t)(netif->hwaddr[1]) << 16) |
        ((u32_t)(netif->hwaddr[2]) << 8) |
        (0xff));
    ip_2_ip6(&netif->ip6_addr[0])->addr[3] = htonl((0xfeul << 24) |
        ((u32_t)(netif->hwaddr[3]) << 16) |
        ((u32_t)(netif->hwaddr[4]) << 8) |
        (netif->hwaddr[5]));
  } else {
    /* Use hwaddr directly as interface ID. */
    ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0;
    ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0;

    addr_index = 3;
    for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) {
      if (i == 4) {
        addr_index--;
      }
      ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03));
    }
  }
  
#ifdef LWIP_ESP8266
    ip6_addr_set( ip_2_ip6(&netif->link_local_addr), ip_2_ip6(&netif->ip6_addr[0]) );
#endif

  /* Set address state. */
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
  /* Will perform duplicate address detection (DAD). */
  netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE;
#else
  /* Consider address valid. */
  netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED;
#endif /* LWIP_IPV6_AUTOCONFIG */
}
예제 #6
0
/**
 * create a new group
 *
 * @param ifp the network interface for which to create
 * @param addr the new group ipv6
 * @return a struct mld_group*,
 *         NULL on memory error.
 */
static struct mld_group *
mld6_new_group(struct netif *ifp, ip6_addr_t *addr)
{
  struct mld_group *group;

  group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP);
  if (group != NULL) {
    group->netif              = ifp;
    ip6_addr_set(&(group->group_address), addr);
    group->timer              = 0; /* Not running */
    group->group_state        = MLD6_GROUP_IDLE_MEMBER;
    group->last_reporter_flag = 0;
    group->use                = 0;
    group->next               = mld_group_list;

    mld_group_list = group;
  }

  return group;
}