Beispiel #1
0
static bool mbed_lwip_is_local_addr(const ip_addr_t *ip_addr)
{
    struct netif *netif;

    for (netif = netif_list; netif != NULL; netif = netif->next) {
        if (!netif_is_up(netif)) {
            continue;
        }
#if LWIP_IPV6
        if (IP_IS_V6(ip_addr)) {
            for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
                if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
                    ip6_addr_cmp(netif_ip6_addr(netif, i), ip_2_ip6(ip_addr))) {
                    return true;
                }
            }
        }
#endif

#if LWIP_IPV4
        if (IP_IS_V4(ip_addr)) {
            if (!ip4_addr_isany(netif_ip4_addr(netif)) &&
                ip4_addr_cmp(netif_ip4_addr(netif), ip_2_ip4(ip_addr))) {
                return true;
            }
        }
#endif
    }
    return false;
}
Beispiel #2
0
const char *LWIP::get_ip_address()
{
    if (!default_interface) {
        return NULL;
    }

    const ip_addr_t *addr = get_ip_addr(true, &default_interface->netif);

    if (!addr) {
        return NULL;
    }
#if LWIP_IPV6
    if (IP_IS_V6(addr)) {
        return ip6addr_ntoa_r(ip_2_ip6(addr), ip_address, sizeof(ip_address));
    }
#endif
#if LWIP_IPV4
    if (IP_IS_V4(addr)) {
        return ip4addr_ntoa_r(ip_2_ip4(addr), ip_address, sizeof(ip_address));
    }
#endif
#if LWIP_IPV6 && LWIP_IPV4
    return NULL;
#endif
}
Beispiel #3
0
static int get_ip_addr_type(const ip_addr_t *ip_addr)
{
#if LWIP_IPV6
    if (IP_IS_V6(ip_addr)) {
        return IPADDR_TYPE_V6;
    }
#endif
#if LWIP_IPV4
    if (IP_IS_V4(ip_addr)) {
        return IPADDR_TYPE_V4;
    }
#endif
#if LWIP_IPV6 && LWIP_IPV4
    return IPADDR_TYPE_ANY;
#endif
}
Beispiel #4
0
char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen)
{
    const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
    if (!addr) {
        return NULL;
    }
#if LWIP_IPV6
    if (IP_IS_V6(addr)) {
        return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
    }
#endif
#if LWIP_IPV4
    if (IP_IS_V4(addr)) {
        return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
    }
#endif
    return NULL;
}
Beispiel #5
0
static bool convert_lwip_addr_to_mbed(nsapi_addr_t *out, const ip_addr_t *in)
{
#if LWIP_IPV6
    if (IP_IS_V6(in)) {
        out->version = NSAPI_IPv6;
        MEMCPY(out->bytes, ip_2_ip6(in), sizeof(ip6_addr_t));
        return true;
    }
#endif
#if LWIP_IPV4
    if (IP_IS_V4(in)) {
        out->version = NSAPI_IPv4;
        MEMCPY(out->bytes, ip_2_ip4(in), sizeof(ip4_addr_t));
        return true;
    }
#endif
    return false;
}
Beispiel #6
0
char *LWIP::Interface::get_ip_address(char *buf, nsapi_size_t buflen)
{
    const ip_addr_t *addr = LWIP::get_ip_addr(true, &netif);
    if (!addr) {
        return NULL;
    }
#if LWIP_IPV6
    if (IP_IS_V6(addr)) {
        return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
    }
#endif
#if LWIP_IPV4
    if (IP_IS_V4(addr)) {
        return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
    }
#endif
#if LWIP_IPV6 && LWIP_IPV4
    return NULL;
#endif
}
Beispiel #7
0
/**
 * Send the raw IP packet to the given address. Note that actually you cannot
 * modify the IP headers (this is inconsistent with the receive callback where
 * you actually get the IP headers), you can only specify the IP payload here.
 * It requires some more changes in lwIP. (there will be a raw_send() function
 * then.)
 *
 * @param pcb the raw pcb which to send
 * @param p the IP payload to send
 * @param ipaddr the destination address of the IP packet
 *
 */
err_t
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
{
  err_t err;
  struct netif *netif;
  const ip_addr_t *src_ip;
  struct pbuf *q; /* q will be sent down the stack */
  s16_t header_size;
  const ip_addr_t *dst_ip = ipaddr;

  if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
    return ERR_VAL;
  }

  LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));

  header_size = (
#if LWIP_IPV4 && LWIP_IPV6
    IP_IS_V6(ipaddr) ? IP6_HLEN : IP_HLEN);
#elif LWIP_IPV4
    IP_HLEN);
#else
    IP6_HLEN);
#endif

  /* not enough space to add an IP header to first pbuf in given p chain? */
  if (pbuf_header(p, header_size)) {
    /* allocate header in new pbuf */
    q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
    /* new header pbuf could not be allocated? */
    if (q == NULL) {
      LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
      return ERR_MEM;
    }
    if (p->tot_len != 0) {
      /* chain header q in front of given pbuf p */
      pbuf_chain(q, p);
    }
    /* { first pbuf q points to header pbuf } */
    LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
  } else {
    /* first pbuf q equals given pbuf */
    q = p;
    if (pbuf_header(q, -header_size)) {
      LWIP_ASSERT("Can't restore header we just removed!", 0);
      return ERR_MEM;
    }
  }

  netif = ip_route(&pcb->local_ip, dst_ip);
  if (netif == NULL) {
    LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
    ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip);
    /* free any temporary header pbuf allocated by pbuf_header() */
    if (q != p) {
      pbuf_free(q);
    }
    return ERR_RTE;
  }

#if IP_SOF_BROADCAST
  if (IP_IS_V4(ipaddr))
  {
    /* broadcast filter? */
    if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) {
      LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
      /* free any temporary header pbuf allocated by pbuf_header() */
      if (q != p) {
        pbuf_free(q);
      }
      return ERR_VAL;
    }
  }
#endif /* IP_SOF_BROADCAST */

  if (ip_addr_isany(&pcb->local_ip)) {
    /* use outgoing network interface IP address as source address */
    src_ip = ip_netif_get_local_ip(netif, dst_ip);
#if LWIP_IPV6
    if (src_ip == NULL) {
      if (q != p) {
        pbuf_free(q);
      }
      return ERR_RTE;
    }
#endif /* LWIP_IPV6 */
  } else {
    /* use RAW PCB local IP address as source address */
    src_ip = &pcb->local_ip;
  }

#if LWIP_IPV6
  /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542,
     compute the checksum and update the checksum in the payload. */
  if (IP_IS_V6(dst_ip) && pcb->chksum_reqd) {
    u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(dst_ip));
    LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2));
    SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t));
  }
#endif

  NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
  err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, pcb->protocol, netif);
  NETIF_SET_HWADDRHINT(netif, NULL);

  /* did we chain a header earlier? */
  if (q != p) {
    /* free the header */
    pbuf_free(q);
  }
  return err;
}
Beispiel #8
0
static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)
{
    struct lwip_socket *s = (struct lwip_socket *)handle;

    switch (optname) {
#if LWIP_TCP
        case NSAPI_KEEPALIVE:
            if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
                return NSAPI_ERROR_UNSUPPORTED;
            }

            s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE;
            return 0;

        case NSAPI_KEEPIDLE:
            if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
                return NSAPI_ERROR_UNSUPPORTED;
            }

            s->conn->pcb.tcp->keep_idle = *(int*)optval;
            return 0;

        case NSAPI_KEEPINTVL:
            if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
                return NSAPI_ERROR_UNSUPPORTED;
            }

            s->conn->pcb.tcp->keep_intvl = *(int*)optval;
            return 0;
#endif

        case NSAPI_REUSEADDR:
            if (optlen != sizeof(int)) {
                return NSAPI_ERROR_UNSUPPORTED;
            }

            if (*(int *)optval) {
                ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR);
            } else {
                ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR);
            }
            return 0;

        case NSAPI_ADD_MEMBERSHIP:
        case NSAPI_DROP_MEMBERSHIP: {
            if (optlen != sizeof(nsapi_ip_mreq_t)) {
                return NSAPI_ERROR_PARAMETER;
            }
            err_t igmp_err;
            const nsapi_ip_mreq_t *imr = optval;

            /* Check interface address type matches group, or is unspecified */
            if (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != imr->imr_multiaddr.version) {
                return NSAPI_ERROR_PARAMETER;
            }

            ip_addr_t if_addr;
            ip_addr_t multi_addr;

            /* Convert the group address */
            if (!convert_mbed_addr_to_lwip(&multi_addr, &imr->imr_multiaddr)) {
                return NSAPI_ERROR_PARAMETER;
            }

            /* Convert the interface address, or make sure it's the correct sort of "any" */
            if (imr->imr_interface.version != NSAPI_UNSPEC) {
                if (!convert_mbed_addr_to_lwip(&if_addr, &imr->imr_interface)) {
                    return NSAPI_ERROR_PARAMETER;
                }
            } else {
                ip_addr_set_any(IP_IS_V6(&if_addr), &if_addr);
            }

            igmp_err = ERR_USE; // Maps to NSAPI_ERROR_UNSUPPORTED
            int32_t member_pair_index = find_multicast_member(s, imr);

            if (optname == NSAPI_ADD_MEMBERSHIP) {
                if (!s->multicast_memberships) {
                    // First multicast join on this socket, allocate space for membership tracking
                    s->multicast_memberships = malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS);
                    if (!s->multicast_memberships) {
                        return NSAPI_ERROR_NO_MEMORY;
                    }
                } else if(s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) {
                    return NSAPI_ERROR_NO_MEMORY;
                }

                if (member_pair_index != -1) {
                    return NSAPI_ERROR_ADDRESS_IN_USE;
                }

                member_pair_index = next_free_multicast_member(s, 0);

                sys_prot_t prot = sys_arch_protect();

                #if LWIP_IPV4
                if (IP_IS_V4(&if_addr)) {
                    igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
                }
                #endif
                #if LWIP_IPV6
                if (IP_IS_V6(&if_addr)) {
                    igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
                }
                #endif

                sys_arch_unprotect(prot);

                if (igmp_err == ERR_OK) {
                    set_multicast_member_registry_bit(s, member_pair_index);
                    s->multicast_memberships[member_pair_index] = *imr;
                    s->multicast_memberships_count++;
                }
            } else {
                if (member_pair_index == -1) {
                    return NSAPI_ERROR_NO_ADDRESS;
                }

                clear_multicast_member_registry_bit(s, member_pair_index);
                s->multicast_memberships_count--;

                sys_prot_t prot = sys_arch_protect();

                #if LWIP_IPV4
                if (IP_IS_V4(&if_addr)) {
                    igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
                }
                #endif
                #if LWIP_IPV6
                if (IP_IS_V6(&if_addr)) {
                    igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
                }
                #endif

                sys_arch_unprotect(prot);
            }

            return mbed_lwip_err_remap(igmp_err);
         }

        default:
            return NSAPI_ERROR_UNSUPPORTED;
    }
}