static void ping_recv(int s, const ip_addr_t *addr) { char buf[200]; socklen_t fromlen; int len; struct sockaddr_storage from; ip_addr_t ip_from; LWIP_UNUSED_ARG(addr); len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, &fromlen); #if LWIP_IPV4 if(!IP_IS_V6(addr)) { struct sockaddr_in *from4 = (struct sockaddr_in*)&from; inet_addr_to_ipaddr(ip_2_ip4(&ip_from), &from4->sin_addr); } #endif /* LWIP_IPV4 */ #if LWIP_IPV6 if(IP_IS_V6(addr)) { struct sockaddr_in6 *from6 = (struct sockaddr_in6*)&from; inet6_addr_to_ip6addr(ip_2_ip6(&ip_from), &from6->sin6_addr); } #endif /* LWIP_IPV6 */ printf("Received %d bytes from %s\n", len, ipaddr_ntoa(&ip_from)); }
void add_dns_addr(struct netif *lwip_netif) { const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif); if (ip_addr) { if (IP_IS_V6(ip_addr)) { const ip_addr_t *dns_ip_addr; bool dns_addr_exists = false; for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) { dns_ip_addr = dns_getserver(numdns); if (!ip_addr_isany(dns_ip_addr)) { dns_addr_exists = true; break; } } if (!dns_addr_exists) { /* 2001:4860:4860::8888 google */ ip_addr_t ipv6_dns_addr = IPADDR6_INIT( PP_HTONL(0x20014860UL), PP_HTONL(0x48600000UL), PP_HTONL(0x00000000UL), PP_HTONL(0x00008888UL)); dns_setserver(0, &ipv6_dns_addr); } } } }
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; }
/* Ping using the socket ip */ static err_t ping_send(int s, ip_addr_t *addr) { int err; struct icmp_echo_hdr *iecho; struct sockaddr_in to; size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE; LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff); LWIP_ASSERT("ping: expect IPv4 address", !IP_IS_V6(addr)); iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size); if (!iecho) { return ERR_MEM; } ping_prepare_echo(iecho, (u16_t)ping_size); to.sin_len = sizeof(to); to.sin_family = AF_INET; inet_addr_from_ipaddr(&to.sin_addr, ip_2_ip4(addr)); err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to)); mem_free(iecho); return (err ? ERR_OK : ERR_VAL); }
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 }
END_TEST START_TEST(test_ip6_lladdr) { u8_t zeros[128]; const u8_t test_mac_addr[6] = {0xb0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}; const u32_t expected_ip6_addr_1[4] = {PP_HTONL(0xfe800000), 0, PP_HTONL(0xb2a1a2ff), PP_HTONL(0xfea3a4a5)}; const u32_t expected_ip6_addr_2[4] = {PP_HTONL(0xfe800000), 0, PP_HTONL(0x0000b0a1), PP_HTONL(0xa2a3a4a5)}; LWIP_UNUSED_ARG(_i); memset(zeros, 0, sizeof(zeros)); fail_unless(test_netif6.hwaddr_len == 6); fail_unless(!memcmp(test_netif6.hwaddr, zeros, 6)); fail_unless(test_netif6.ip6_addr_state[0] == 0); fail_unless(!memcmp(netif_ip6_addr(&test_netif6, 0), zeros, sizeof(ip6_addr_t))); /* set specific mac addr */ memcpy(test_netif6.hwaddr, test_mac_addr, 6); /* create link-local addr based on mac (EUI-48) */ netif_create_ip6_linklocal_address(&test_netif6, 1); fail_unless(IP_IS_V6(&test_netif6.ip6_addr[0])); fail_unless(!memcmp(&netif_ip6_addr(&test_netif6, 0)->addr, expected_ip6_addr_1, 16)); #if LWIP_IPV6_SCOPES fail_unless(netif_ip6_addr(&test_netif6, 0)->zone == (test_netif6.num + 1)); #endif /* reset address */ memset(&test_netif6.ip6_addr[0], 0, sizeof(ip6_addr_t)); test_netif6.ip6_addr_state[0] = 0; /* create link-local addr based interface ID */ netif_create_ip6_linklocal_address(&test_netif6, 0); fail_unless(IP_IS_V6(&test_netif6.ip6_addr[0])); fail_unless(!memcmp(&netif_ip6_addr(&test_netif6, 0)->addr, expected_ip6_addr_2, 16)); #if LWIP_IPV6_SCOPES fail_unless(netif_ip6_addr(&test_netif6, 0)->zone == (test_netif6.num + 1)); #endif /* reset address */ memset(&test_netif6.ip6_addr[0], 0, sizeof(ip6_addr_t)); test_netif6.ip6_addr_state[0] = 0; /* reset mac address */ memset(&test_netif6.hwaddr, 0, sizeof(test_netif6.hwaddr)); }
/* LWIP network stack implementation */ static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version) { ip_addr_t lwip_addr; #if LWIP_IPV4 && LWIP_IPV6 u8_t addr_type; if (version == NSAPI_UNSPEC) { const ip_addr_t *ip_addr; ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); // Prefer IPv6 if (IP_IS_V6(ip_addr)) { // If IPv4 is available use it as backup if (mbed_lwip_get_ipv4_addr(&lwip_netif)) { addr_type = NETCONN_DNS_IPV6_IPV4; } else { addr_type = NETCONN_DNS_IPV6; } // Prefer IPv4 } else { // If IPv6 is available use it as backup if (mbed_lwip_get_ipv6_addr(&lwip_netif)) { addr_type = NETCONN_DNS_IPV4_IPV6; } else { addr_type = NETCONN_DNS_IPV4; } } } else if (version == NSAPI_IPv4) { addr_type = NETCONN_DNS_IPV4; } else if (version == NSAPI_IPv6) { addr_type = NETCONN_DNS_IPV6; } else { return NSAPI_ERROR_DNS_FAILURE; } err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type); #elif LWIP_IPV4 if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) { return NSAPI_ERROR_DNS_FAILURE; } err_t err = netconn_gethostbyname(host, &lwip_addr); #elif LWIP_IPV6 if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC) { return NSAPI_ERROR_DNS_FAILURE; } err_t err = netconn_gethostbyname(host, &lwip_addr); #endif if (err != ERR_OK) { return NSAPI_ERROR_DNS_FAILURE; } convert_lwip_addr_to_mbed(addr, &lwip_addr); return 0; }
static void ping_send(int s, const ip_addr_t *addr) { struct icmp_echo_hdr *iecho; struct sockaddr_storage to; if (!(iecho = (struct icmp_echo_hdr *)malloc(sizeof(struct icmp_echo_hdr)))) return; ICMPH_TYPE_SET(iecho,ICMP_ECHO); iecho->chksum = 0; iecho->seqno = htons(seq_num); iecho->chksum = inet_chksum(iecho, sizeof(*iecho)); #if LWIP_IPV4 if(!IP_IS_V6(addr)) { struct sockaddr_in *to4 = (struct sockaddr_in*)&to; to4->sin_len = sizeof(to); to4->sin_family = AF_INET; inet_addr_from_ipaddr(&to4->sin_addr, ip_2_ip4(addr)); } #endif /* LWIP_IPV4 */ #if LWIP_IPV6 if(IP_IS_V6(addr)) { struct sockaddr_in6 *to6 = (struct sockaddr_in6*)&to; to6->sin6_len = sizeof(to); to6->sin6_family = AF_INET6; inet6_addr_from_ip6addr(&to6->sin6_addr, ip_2_ip6(addr)); } #endif /* LWIP_IPV6 */ lwip_sendto(s, iecho, sizeof(*iecho), 0, (struct sockaddr*)&to, sizeof(to)); free(iecho); seq_num++; }
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 }
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; }
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; }
static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto) { // check if network is connected if (!lwip_connected) { return NSAPI_ERROR_NO_CONNECTION; } // allocate a socket struct lwip_socket *s = mbed_lwip_arena_alloc(); if (!s) { return NSAPI_ERROR_NO_SOCKET; } u8_t lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP; #if LWIP_IPV6 && LWIP_IPV4 const ip_addr_t *ip_addr; ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); if (IP_IS_V6(ip_addr)) { // Enable IPv6 (or dual-stack). LWIP dual-stack support is // currently incomplete as of 2.0.0rc2 - eg we will only be able // to do a UDP sendto to an address matching the type selected // here. Matching "get_ip_addr" and DNS logic, use v4 if // available. lwip_proto |= NETCONN_TYPE_IPV6; } #elif LWIP_IPV6 lwip_proto |= NETCONN_TYPE_IPV6; #endif s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback); if (!s->conn) { mbed_lwip_arena_dealloc(s); return NSAPI_ERROR_NO_SOCKET; } netconn_set_recvtimeout(s->conn, 1); *(struct lwip_socket **)handle = s; return 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 }
/** * 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; }
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; } }