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); } } } }
END_TEST static void test_sockets_init_loopback_addr(int domain, struct sockaddr_storage *addr_st, socklen_t *sz) { memset(addr_st, 0, sizeof(*addr_st)); switch(domain) { #if LWIP_IPV6 case AF_INET6: { struct sockaddr_in6 *addr = (struct sockaddr_in6*)addr_st; struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; addr->sin6_family = AF_INET6; addr->sin6_port = 0; /* use ephemeral port */ addr->sin6_addr = lo6; *sz = sizeof(*addr); } break; #endif /* LWIP_IPV6 */ #if LWIP_IPV4 case AF_INET: { struct sockaddr_in *addr = (struct sockaddr_in*)addr_st; addr->sin_family = AF_INET; addr->sin_port = 0; /* use ephemeral port */ addr->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); *sz = sizeof(*addr); } break; #endif /* LWIP_IPV4 */ default: *sz = 0; fail(); break; } }
void netif_init(void) { #if LWIP_HAVE_LOOPIF #if LWIP_IPV4 #define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; IP4_ADDR(&loop_gw, 127,0,0,1); IP4_ADDR(&loop_ipaddr, 127,0,0,1); IP4_ADDR(&loop_netmask, 255,0,0,0); #else /* LWIP_IPV4 */ #define LOOPIF_ADDRINIT #endif /* LWIP_IPV4 */ #if NO_SYS netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); #else /* NO_SYS */ netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); #endif /* NO_SYS */ #if LWIP_IPV6 IP_ADDR6(loop_netif.ip6_addr, 0, 0, 0, PP_HTONL(0x00000001UL)); loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; #endif /* LWIP_IPV6 */ netif_set_link_up(&loop_netif); netif_set_up(&loop_netif); #endif /* LWIP_HAVE_LOOPIF */ }
void netif_init(void) { #if LWIP_HAVE_LOOPIF ip_addr_t loop_ipaddr, loop_netmask, loop_gw; IP4_ADDR(&loop_gw, 127,0,0,1); IP4_ADDR(&loop_ipaddr, 127,0,0,1); IP4_ADDR(&loop_netmask, 255,0,0,0); #if NO_SYS netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input); #else /* NO_SYS */ netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input); #endif /* NO_SYS */ #if LWIP_IPV6 loop_netif.ip6_addr[0].addr[0] = 0; loop_netif.ip6_addr[0].addr[1] = 0; loop_netif.ip6_addr[0].addr[2] = 0; loop_netif.ip6_addr[0].addr[3] = PP_HTONL(0x00000001UL); loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; #endif /* LWIP_IPV6 */ netif_set_up(&loop_netif); #endif /* LWIP_HAVE_LOOPIF */ }
/* Build a timestamp option (12 bytes long) at the specified options pointer) * * @param pcb tcp_pcb * @param opts option pointer where to store the timestamp option */ static void tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) { /* Pad with two NOP options to make everything nicely aligned */ opts[0] = PP_HTONL(0x0101080A); opts[1] = htonl(sys_now()); opts[2] = htonl(pcb->ts_recent); }
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)); }
static void add_dns_addr_to_dns_list_index(const u8_t addr_type, const u8_t index) { #if LWIP_IPV6 if (addr_type == IPADDR_TYPE_V6) { /* 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(index, &ipv6_dns_addr); } #endif #if LWIP_IPV4 if (addr_type == IPADDR_TYPE_V4) { /* 8.8.8.8 google */ ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808); dns_setserver(index, &ipv4_dns_addr); } #endif }
/** 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 */ }
void netif_create_ip6_linklocal_address(struct netif * netif, u8_t from_mac_48bit) { u8_t i, addr_index; /* Link-local prefix. */ netif->ip6_addr[0].addr[0] = PP_HTONL(0xfe800000ul); 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. */ 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)); 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 { u8_t *id; /* Use hwaddr directly as interface ID. */ netif->ip6_addr[0].addr[2] = 0; netif->ip6_addr[0].addr[3] = 0; LWIP_ASSERT("bad netif->hwaddr_len", 0 < netif->hwaddr_len && netif->hwaddr_len <= 8); id = (uint8_t *)&netif->ip6_addr[0].addr[2]; id += 8 - netif->hwaddr_len; for (i = 0; i < netif->hwaddr_len; ++i) { id[i] = netif->hwaddr[i]; } } /* 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 */ }
/** * RTP send thread */ static void rtp_send_thread(void *arg) { int sock; struct sockaddr_in local; struct sockaddr_in to; u32_t rtp_stream_address; LWIP_UNUSED_ARG(arg); /* initialize RTP stream address */ rtp_stream_address = RTP_STREAM_ADDRESS; /* if we got a valid RTP stream address... */ if (rtp_stream_address != 0) { /* create new socket */ sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock >= 0) { /* prepare local address */ memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_port = PP_HTONS(INADDR_ANY); local.sin_addr.s_addr = PP_HTONL(INADDR_ANY); /* bind to local address */ if (bind(sock, (struct sockaddr *)&local, sizeof(local)) == 0) { /* prepare RTP stream address */ memset(&to, 0, sizeof(to)); to.sin_family = AF_INET; to.sin_port = PP_HTONS(RTP_STREAM_PORT); to.sin_addr.s_addr = rtp_stream_address; /* send RTP packets */ memset(rtp_send_packet, 0, sizeof(rtp_send_packet)); while (1) { rtp_send_packets( sock, &to); sys_msleep(RTP_SEND_DELAY); } } /* close the socket */ closesocket(sock); } } }
/** * RTP send packets */ static void rtp_send_packets( int sock, struct sockaddr_in* to) { struct rtp_hdr* rtphdr; u8_t* rtp_payload; int rtp_payload_size; size_t rtp_data_index; /* prepare RTP packet */ rtphdr = (struct rtp_hdr*)rtp_send_packet; rtphdr->version = RTP_VERSION; rtphdr->payloadtype = 0; rtphdr->ssrc = PP_HTONL(RTP_SSRC); rtphdr->timestamp = lwip_htonl(lwip_ntohl(rtphdr->timestamp) + RTP_TIMESTAMP_INCREMENT); /* send RTP stream packets */ rtp_data_index = 0; do { rtp_payload = rtp_send_packet+sizeof(struct rtp_hdr); rtp_payload_size = LWIP_MIN(RTP_PAYLOAD_SIZE, (sizeof(rtp_data) - rtp_data_index)); MEMCPY(rtp_payload, rtp_data + rtp_data_index, rtp_payload_size); /* set MARKER bit in RTP header on the last packet of an image */ rtphdr->payloadtype = RTP_PAYLOADTYPE | (((rtp_data_index + rtp_payload_size) >= sizeof(rtp_data)) ? RTP_MARKER_MASK : 0); /* send RTP stream packet */ if (sendto(sock, rtp_send_packet, sizeof(struct rtp_hdr) + rtp_payload_size, 0, (struct sockaddr *)to, sizeof(struct sockaddr)) >= 0) { rtphdr->seqNum = lwip_htons(lwip_ntohs(rtphdr->seqNum) + 1); rtp_data_index += rtp_payload_size; } else { LWIP_DEBUGF(RTP_DEBUG, ("rtp_sender: not sendto==%i\n", errno)); } }while (rtp_data_index < sizeof(rtp_data)); }
static void test_sockets_msgapi_cmsg(int domain) { int s, ret, enable; struct sockaddr_storage addr_storage; socklen_t addr_size; struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; struct in_pktinfo *pktinfo; u8_t rcv_buf[4]; u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF}; u8_t cmsg_buf[CMSG_SPACE(sizeof(struct in_pktinfo))]; test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size); s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM); fail_unless(s >= 0); ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size); fail_unless(ret == 0); /* Update addr with epehermal port */ ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size); fail_unless(ret == 0); enable = 1; ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable)); fail_unless(ret == 0); /* Receive full message, including control message */ iov.iov_base = rcv_buf; iov.iov_len = sizeof(rcv_buf); msg.msg_control = cmsg_buf; msg.msg_controllen = sizeof(cmsg_buf); msg.msg_flags = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; memset(rcv_buf, 0, sizeof(rcv_buf)); ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size); fail_unless(ret == sizeof(snd_buf)); tcpip_thread_poll_one(); ret = lwip_recvmsg(s, &msg, 0); fail_unless(ret == sizeof(rcv_buf)); fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf))); /* Verify message header */ cmsg = CMSG_FIRSTHDR(&msg); fail_unless(cmsg != NULL); fail_unless(cmsg->cmsg_len > 0); fail_unless(cmsg->cmsg_level == IPPROTO_IP); fail_unless(cmsg->cmsg_type == IP_PKTINFO); /* Verify message data */ pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg); /* We only have loopback interface enabled */ fail_unless(pktinfo->ipi_ifindex == 1); fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK)); /* Verify there are no additional messages */ cmsg = CMSG_NXTHDR(&msg, cmsg); fail_unless(cmsg == NULL); /* Send datagram again, testing truncation */ memset(rcv_buf, 0, sizeof(rcv_buf)); ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size); fail_unless(ret == sizeof(snd_buf)); tcpip_thread_poll_one(); msg.msg_controllen = 1; msg.msg_flags = 0; ret = lwip_recvmsg(s, &msg, 0); fail_unless(ret == sizeof(rcv_buf)); fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf))); /* Ensure truncation was returned */ fail_unless(msg.msg_flags & MSG_CTRUNC); /* Ensure no control messages were returned */ fail_unless(msg.msg_controllen == 0); ret = lwip_close(s); fail_unless(ret == 0); }
void VBoxNetLwipNAT::onLwipTcpIpInit(void* arg) { AssertPtrReturnVoid(arg); VBoxNetLwipNAT *pNat = static_cast<VBoxNetLwipNAT *>(arg); HRESULT hrc = com::Initialize(); Assert(!FAILED(hrc)); proxy_arp_hook = pxremap_proxy_arp; proxy_ip4_divert_hook = pxremap_ip4_divert; proxy_na_hook = pxremap_proxy_na; proxy_ip6_divert_hook = pxremap_ip6_divert; /* lwip thread */ RTNETADDRIPV4 network; RTNETADDRIPV4 address = g_pLwipNat->getIpv4Address(); RTNETADDRIPV4 netmask = g_pLwipNat->getIpv4Netmask(); network.u = address.u & netmask.u; ip_addr LwipIpAddr, LwipIpNetMask, LwipIpNetwork; memcpy(&LwipIpAddr, &address, sizeof(ip_addr)); memcpy(&LwipIpNetMask, &netmask, sizeof(ip_addr)); memcpy(&LwipIpNetwork, &network, sizeof(ip_addr)); netif *pNetif = netif_add(&g_pLwipNat->m_LwipNetIf /* Lwip Interface */, &LwipIpAddr /* IP address*/, &LwipIpNetMask /* Network mask */, &LwipIpAddr /* gateway address, @todo: is self IP acceptable? */, g_pLwipNat /* state */, VBoxNetLwipNAT::netifInit /* netif_init_fn */, tcpip_input /* netif_input_fn */); AssertPtrReturnVoid(pNetif); LogRel(("netif %c%c%d: mac %RTmac\n", pNetif->name[0], pNetif->name[1], pNetif->num, pNetif->hwaddr)); LogRel(("netif %c%c%d: inet %RTnaipv4 netmask %RTnaipv4\n", pNetif->name[0], pNetif->name[1], pNetif->num, pNetif->ip_addr, pNetif->netmask)); for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { if (!ip6_addr_isinvalid(netif_ip6_addr_state(pNetif, i))) { LogRel(("netif %c%c%d: inet6 %RTnaipv6\n", pNetif->name[0], pNetif->name[1], pNetif->num, netif_ip6_addr(pNetif, i))); } } netif_set_up(pNetif); netif_set_link_up(pNetif); if (pNat->m_ProxyOptions.ipv6_enabled) { /* * XXX: lwIP currently only ever calls mld6_joingroup() in * nd6_tmr() for fresh tentative addresses, which is a wrong place * to do it - but I'm not keen on fixing this properly for now * (with correct handling of interface up and down transitions, * etc). So stick it here as a kludge. */ for (int i = 0; i <= 1; ++i) { ip6_addr_t *paddr = netif_ip6_addr(pNetif, i); ip6_addr_t solicited_node_multicast_address; ip6_addr_set_solicitednode(&solicited_node_multicast_address, paddr->addr[3]); mld6_joingroup(paddr, &solicited_node_multicast_address); } /* * XXX: We must join the solicited-node multicast for the * addresses we do IPv6 NA-proxy for. We map IPv6 loopback to * proxy address + 1. We only need the low 24 bits, and those are * fixed. */ { ip6_addr_t solicited_node_multicast_address; ip6_addr_set_solicitednode(&solicited_node_multicast_address, /* last 24 bits of the address */ PP_HTONL(0x00000002)); mld6_netif_joingroup(pNetif, &solicited_node_multicast_address); } } proxy_init(&g_pLwipNat->m_LwipNetIf, &g_pLwipNat->m_ProxyOptions); natServiceProcessRegisteredPf(g_pLwipNat->m_vecPortForwardRule4); natServiceProcessRegisteredPf(g_pLwipNat->m_vecPortForwardRule6); }
static void dhcpd_thread_entry(void *parameter) { struct netif *netif = RT_NULL; int sock; int bytes_read; char *recv_data; rt_uint32_t addr_len; struct sockaddr_in server_addr, client_addr; struct dhcp_msg *msg; int optval = 1; /* get ethernet interface. */ netif = (struct netif*) parameter; RT_ASSERT(netif != RT_NULL); /* our DHCP server information */ DEBUG_PRINTF("DHCP server IP: %d.%d.%d.%d client IP: %d.%d.%d.%d-%d\n", DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1, DHCPD_SERVER_IPADDR2, DHCPD_SERVER_IPADDR3, DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1, DHCPD_SERVER_IPADDR2, DHCPD_CLIENT_IP_MIN, DHCPD_CLIENT_IP_MAX); /* allocate buffer for receive */ recv_data = rt_malloc(BUFSZ); if (recv_data == RT_NULL) { /* No memory */ DEBUG_PRINTF("Out of memory\n"); return; } /* create a socket with UDP */ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { DEBUG_PRINTF("create socket failed, errno = %d\n", errno); rt_free(recv_data); return; } /* set to receive broadcast packet */ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)); /* initialize server address */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(DHCP_SERVER_PORT); server_addr.sin_addr.s_addr = INADDR_ANY; rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* bind socket to the server address */ if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { /* bind failed. */ DEBUG_PRINTF("bind server address failed, errno=%d\n", errno); rt_free(recv_data); return; } addr_len = sizeof(struct sockaddr); DEBUG_PRINTF("DHCP server listen on port %d...\n", DHCP_SERVER_PORT); while (1) { bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0, (struct sockaddr *)&client_addr, &addr_len); if (bytes_read < DHCP_MSG_LEN) { DEBUG_PRINTF("packet too short, wait for next!\n"); continue; } msg = (struct dhcp_msg *)recv_data; /* check message type to make sure we can handle it */ if ((msg->op != DHCP_BOOTREQUEST) || (msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE))) { continue; } /* handler. */ { uint8_t *dhcp_opt; uint8_t option; uint8_t length; uint8_t message_type = 0; uint8_t finished = 0; uint32_t request_ip = 0; dhcp_opt = (uint8_t *)msg + DHCP_OPTIONS_OFS; while (finished == 0) { option = *dhcp_opt; length = *(dhcp_opt + 1); switch (option) { case DHCP_OPTION_REQUESTED_IP: request_ip = *(dhcp_opt + 2) << 24 | *(dhcp_opt + 3) << 16 | *(dhcp_opt + 4) << 8 | *(dhcp_opt + 5); break; case DHCP_OPTION_END: finished = 1; break; case DHCP_OPTION_MESSAGE_TYPE: message_type = *(dhcp_opt + 2); break; default: break; } /* switch(option) */ dhcp_opt += (2 + length); } /* reply. */ dhcp_opt = (uint8_t *)msg + DHCP_OPTIONS_OFS; /* check. */ if (request_ip) { uint32_t client_ip = DHCPD_SERVER_IPADDR0 << 24 | DHCPD_SERVER_IPADDR1 << 16 | DHCPD_SERVER_IPADDR2 << 8 | (next_client_ip); if (request_ip != client_ip) { *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE; *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE_LEN; *dhcp_opt++ = DHCP_NAK; *dhcp_opt++ = DHCP_OPTION_END; DEBUG_PRINTF("requested IP invalid, reply DHCP_NAK\n"); if (netif != RT_NULL) { int send_byte = (dhcp_opt - (uint8_t *)msg); _low_level_dhcp_send(netif, msg, send_byte); DEBUG_PRINTF("DHCP server send %d byte\n", send_byte); } next_client_ip++; if (next_client_ip > DHCPD_CLIENT_IP_MAX) next_client_ip = DHCPD_CLIENT_IP_MIN; continue; } } if (message_type == DHCP_DISCOVER) { DEBUG_PRINTF("request DHCP_DISCOVER\n"); DEBUG_PRINTF("reply DHCP_OFFER\n"); // DHCP_OPTION_MESSAGE_TYPE *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE; *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE_LEN; *dhcp_opt++ = DHCP_OFFER; // DHCP_OPTION_SERVER_ID *dhcp_opt++ = DHCP_OPTION_SERVER_ID; *dhcp_opt++ = 4; *dhcp_opt++ = DHCPD_SERVER_IPADDR0; *dhcp_opt++ = DHCPD_SERVER_IPADDR1; *dhcp_opt++ = DHCPD_SERVER_IPADDR2; *dhcp_opt++ = DHCPD_SERVER_IPADDR3; // DHCP_OPTION_LEASE_TIME *dhcp_opt++ = DHCP_OPTION_LEASE_TIME; *dhcp_opt++ = 4; *dhcp_opt++ = 0x00; *dhcp_opt++ = 0x01; *dhcp_opt++ = 0x51; *dhcp_opt++ = 0x80; } else if (message_type == DHCP_REQUEST) { DEBUG_PRINTF("request DHCP_REQUEST\n"); DEBUG_PRINTF("reply DHCP_ACK\n"); // DHCP_OPTION_MESSAGE_TYPE *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE; *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE_LEN; *dhcp_opt++ = DHCP_ACK; // DHCP_OPTION_SERVER_ID *dhcp_opt++ = DHCP_OPTION_SERVER_ID; *dhcp_opt++ = 4; *dhcp_opt++ = DHCPD_SERVER_IPADDR0; *dhcp_opt++ = DHCPD_SERVER_IPADDR1; *dhcp_opt++ = DHCPD_SERVER_IPADDR2; *dhcp_opt++ = DHCPD_SERVER_IPADDR3; // DHCP_OPTION_SUBNET_MASK *dhcp_opt++ = DHCP_OPTION_SUBNET_MASK; *dhcp_opt++ = 4; *dhcp_opt++ = 0xFF; *dhcp_opt++ = 0xFF; *dhcp_opt++ = 0xFF; *dhcp_opt++ = 0x00; #ifdef DHCPD_USING_ROUTER // DHCP_OPTION_ROUTER *dhcp_opt++ = DHCP_OPTION_ROUTER; *dhcp_opt++ = 4; *dhcp_opt++ = DHCPD_SERVER_IPADDR0; *dhcp_opt++ = DHCPD_SERVER_IPADDR1; *dhcp_opt++ = DHCPD_SERVER_IPADDR2; *dhcp_opt++ = 1; #endif // DHCP_OPTION_DNS_SERVER, use the default DNS server address in lwIP *dhcp_opt++ = DHCP_OPTION_DNS_SERVER; *dhcp_opt++ = 4; *dhcp_opt++ = 208; *dhcp_opt++ = 67; *dhcp_opt++ = 222; *dhcp_opt++ = 222; // DHCP_OPTION_LEASE_TIME *dhcp_opt++ = DHCP_OPTION_LEASE_TIME; *dhcp_opt++ = 4; *dhcp_opt++ = 0x00; *dhcp_opt++ = 0x01; *dhcp_opt++ = 0x51; *dhcp_opt++ = 0x80; } else { DEBUG_PRINTF("un handle message:%d\n", message_type); } // append DHCP_OPTION_END *dhcp_opt++ = DHCP_OPTION_END; /* send reply. */ if ((message_type == DHCP_DISCOVER) || (message_type == DHCP_REQUEST)) { msg->op = DHCP_BOOTREPLY; IP4_ADDR(&msg->yiaddr, DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1, DHCPD_SERVER_IPADDR2, next_client_ip); client_addr.sin_addr.s_addr = INADDR_BROADCAST; if (netif != RT_NULL) { int send_byte = (dhcp_opt - (uint8_t *)msg); _low_level_dhcp_send(netif, msg, send_byte); DEBUG_PRINTF("DHCP server send %d byte\n", send_byte); } } } /* handler. */ } }
END_TEST START_TEST(test_sockets_recv_after_rst) { int sl, sact; int spass = -1; int ret; struct sockaddr_in sa_listen; const u16_t port = 1234; int arg; const char txbuf[] = "something"; char rxbuf[16]; struct lwip_sock *sact_sock; int err; LWIP_UNUSED_ARG(_i); fail_unless(test_sockets_get_used_count() == 0); memset(&sa_listen, 0, sizeof(sa_listen)); sa_listen.sin_family = AF_INET; sa_listen.sin_port = PP_HTONS(port); sa_listen.sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); /* set up the listener */ sl = lwip_socket(AF_INET, SOCK_STREAM, 0); fail_unless(sl >= 0); fail_unless(test_sockets_get_used_count() == 0); ret = lwip_bind(sl, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); fail_unless(ret == 0); ret = lwip_listen(sl, 0); fail_unless(ret == 0); /* set up the client */ sact = lwip_socket(AF_INET, SOCK_STREAM, 0); fail_unless(sact >= 0); fail_unless(test_sockets_get_used_count() == 0); /* set the client to nonblocking to simplify this test */ arg = 1; ret = lwip_ioctl(sact, FIONBIO, &arg); fail_unless(ret == 0); /* connect */ do { ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); err = errno; fail_unless((ret == 0) || (ret == -1)); if (ret != 0) { if (err == EISCONN) { /* Although this is not valid, use EISCONN as an indicator for successful connection. This marks us as "connect phase is done". On error, we would either have a different errno code or "send" fails later... -> good enough for this test. */ ret = 0; } else { fail_unless(err == EINPROGRESS); if (err != EINPROGRESS) { goto cleanup; } /* we're in progress: little side check: test for EALREADY */ ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen)); err = errno; fail_unless(ret == -1); fail_unless(err == EALREADY); if ((ret != -1) || (err != EALREADY)) { goto cleanup; } } tcpip_thread_poll_one(); tcpip_thread_poll_one(); tcpip_thread_poll_one(); tcpip_thread_poll_one(); } } while (ret != 0); fail_unless(ret == 0); /* accept the server connection part */ spass = lwip_accept(sl, NULL, NULL); fail_unless(spass >= 0); /* write data from client */ ret = lwip_send(sact, txbuf, sizeof(txbuf), 0); fail_unless(ret == sizeof(txbuf)); tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* issue RST (This is a HACK, don't try this in your own app!) */ sact_sock = lwip_socket_dbg_get_socket(sact); fail_unless(sact_sock != NULL); if (sact_sock != NULL) { struct netconn *sact_conn = sact_sock->conn; fail_unless(sact_conn != NULL); if (sact_conn != NULL) { struct tcp_pcb *pcb = sact_conn->pcb.tcp; fail_unless(pcb != NULL); if (pcb != NULL) { tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port); } } } tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* expect to receive data first */ ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); fail_unless(ret > 0); tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* expect to receive RST indication */ ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); fail_unless(ret == -1); err = errno; fail_unless(err == ECONNRESET); tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* expect to receive ENOTCONN indication */ ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); fail_unless(ret == -1); err = errno; fail_unless(err == ENOTCONN); tcpip_thread_poll_one(); tcpip_thread_poll_one(); /* expect to receive ENOTCONN indication */ ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0); fail_unless(ret == -1); err = errno; fail_unless(err == ENOTCONN); tcpip_thread_poll_one(); tcpip_thread_poll_one(); cleanup: ret = lwip_close(sl); fail_unless(ret == 0); ret = lwip_close(sact); fail_unless(ret == 0); if (spass >= 0) { ret = lwip_close(spass); fail_unless(ret == 0); } }
/** * Send an SNTP request via sockets. * This is a very minimal implementation that does not fully conform * to the SNTPv4 RFC, especially regarding server load and error procesing. */ void sntp_request(void *arg) { int sock; struct sockaddr_in local; struct sockaddr_in to; int tolen; int size; int timeout; struct sntp_msg sntpmsg; ip_addr_t sntp_server_address; LWIP_UNUSED_ARG(arg); /* if we got a valid SNTP server address... */ if (ipaddr_aton(SNTP_SERVER_ADDRESS, &sntp_server_address)) { /* create new socket */ sock = lwip_socket(AF_INET, SOCK_DGRAM, 0); if (sock >= 0) { /* prepare local address */ memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_port = PP_HTONS(INADDR_ANY); local.sin_addr.s_addr = PP_HTONL(INADDR_ANY); /* bind to local address */ if (lwip_bind(sock, (struct sockaddr *)&local, sizeof(local)) == 0) { /* set recv timeout */ timeout = SNTP_RECV_TIMEOUT; lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); /* prepare SNTP request */ sntp_initialize_request(&sntpmsg); /* prepare SNTP server address */ memset(&to, 0, sizeof(to)); to.sin_family = AF_INET; to.sin_port = PP_HTONS(SNTP_PORT); inet_addr_from_ipaddr(&to.sin_addr, &sntp_server_address); /* send SNTP request to server */ if (lwip_sendto(sock, &sntpmsg, SNTP_MSG_LEN, 0, (struct sockaddr *)&to, sizeof(to)) >= 0) { /* receive SNTP server response */ tolen = sizeof(to); size = lwip_recvfrom(sock, &sntpmsg, SNTP_MSG_LEN, 0, (struct sockaddr *)&to, (socklen_t *)&tolen); /* if the response size is good */ if (size == SNTP_MSG_LEN) { /* if this is a SNTP response... */ if (((sntpmsg.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_SERVER) || ((sntpmsg.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_BROADCAST)) { /* do time processing */ sntp_process(sntpmsg.receive_timestamp); } else { LWIP_DEBUGF( SNTP_DEBUG_WARN, ("sntp_request: not response frame code\n")); } } } else { LWIP_DEBUGF( SNTP_DEBUG_WARN, ("sntp_request: not sendto==%i\n", errno)); } } /* close the socket */ closesocket(sock); } } }
/** Receive data on an iperf tcp session */ static err_t lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { u16_t tot_len; u32_t packet_idx; struct pbuf* q; lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); LWIP_UNUSED_ARG(tpcb); if (err != ERR_OK) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); return ERR_OK; } if (p == NULL) { /* connection closed -> test done */ if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { /* client requested transmission after end of test */ lwiperf_tx_start(conn); } lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER); return ERR_OK; } tot_len = p->tot_len; conn->poll_count = 0; if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) { /* wait for 24-byte header */ if (p->tot_len < sizeof(lwiperf_settings_t)) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); pbuf_free(p); return ERR_VAL; } if (!conn->have_settings_buf) { if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); pbuf_free(p); return ERR_VAL; } conn->have_settings_buf = 1; if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) { /* client requested parallel transmission test */ err_t err2 = lwiperf_tx_start(conn); if (err2 != ERR_OK) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR); pbuf_free(p); return err2; } } } else { if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); pbuf_free(p); return ERR_VAL; } } conn->bytes_transferred += sizeof(lwiperf_settings_t); if(conn->bytes_transferred <= 24) { conn->time_started = sys_now(); tcp_recved(tpcb, p->tot_len); pbuf_free(p); return ERR_OK; } conn->next_num = 4; /* 24 bytes received... */ err = pbuf_header(p, -24); LWIP_ASSERT("pbuf_header failed", err == ERR_OK); } packet_idx = 0; for (q = p; q != NULL; q = q->next) { #if LWIPERF_CHECK_RX_DATA const u8_t* payload = (const u8_t*)q->payload; u16_t i; for (i = 0; i < q->len; i++) { u8_t val = payload[i]; u8_t num = val - '0'; if (num == conn->next_num) { conn->next_num++; if (conn->next_num == 10) { conn->next_num = 0; } } else { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); pbuf_free(p); return ERR_VAL; } } packet_idx += i; #else packet_idx += q->len; #endif } LWIP_ASSERT("count mismatch", packet_idx == p->tot_len); conn->bytes_transferred += packet_idx; tcp_recved(tpcb, tot_len); pbuf_free(p); return ERR_OK; }
/** Try to send more data on an iperf tcp session */ static err_t lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn) { int send_more; err_t err; u16_t txlen; u16_t txlen_max; void* txptr; u8_t apiflags; LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0)); do { send_more = 0; if (conn->settings.amount & PP_HTONL(0x80000000)) { /* this session is time-limited */ u32_t now = sys_now(); u32_t diff_ms = now - conn->time_started; u32_t time = (u32_t)-(s32_t)htonl(conn->settings.amount); u32_t time_ms = time * 10; if (diff_ms >= time_ms) { /* time specified by the client is over -> close the connection */ lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); return ERR_OK; } } else { /* this session is byte-limited */ u32_t amount_bytes = htonl(conn->settings.amount); /* @todo: this can send up to 1*MSS more than requested... */ if (amount_bytes >= conn->bytes_transferred) { /* all requested bytes transferred -> close the connection */ lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); return ERR_OK; } } if (conn->bytes_transferred < 24) { /* transmit the settings a first time */ txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred]; txlen_max = (u16_t)(24 - conn->bytes_transferred); apiflags = TCP_WRITE_FLAG_COPY; } else if (conn->bytes_transferred < 48) { /* transmit the settings a second time */ txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24]; txlen_max = (u16_t)(48 - conn->bytes_transferred); apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE; send_more = 1; } else { /* transmit data */ /* @todo: every x bytes, transmit the settings again */ txptr = (void*)(size_t)&lwiperf_txbuf_const[conn->bytes_transferred % 10]; txlen_max = TCP_MSS; if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */ txlen_max = TCP_MSS - 24; } apiflags = 0; /* no copying needed */ send_more = 1; } txlen = txlen_max; do { err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags); if (err == ERR_MEM) { txlen /= 2; } } while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2))); if (err == ERR_OK) { conn->bytes_transferred += txlen; } else { send_more = 0; } } while(send_more); tcp_output(conn->conn_pcb); return ERR_OK; }
/** * Convert an u32_t from host- to network byte order. * * @param n u32_t in host byte order * @return n in network byte order */ u32_t lwip_htonl(u32_t n) { return (u32_t)PP_HTONL(n); }
#include "dhcp6.h" #include "proxy.h" #include <string.h> #include "lwip/opt.h" #include "lwip/mld6.h" #include "lwip/udp.h" static void dhcp6ds_recv(void *, struct udp_pcb *, struct pbuf *, ip6_addr_t *, u16_t); /* ff02::1:2 - "All_DHCP_Relay_Agents_and_Servers" link-scoped multicast */ static /* const */ ip6_addr_t all_dhcp_relays_and_servers = { { PP_HTONL(0xff020000UL), 0, 0, PP_HTONL(0x00010002UL) } }; /* ff05::1:3 - "All_DHCP_Servers" site-scoped multicast */ static /* const */ ip6_addr_t all_dhcp_servers = { { PP_HTONL(0xff050000UL), 0, 0, PP_HTONL(0x00010003UL) } }; static struct udp_pcb *dhcp6ds_pcb; /* prebuilt Server ID option */ #define DUID_LL_LEN (/* duid type */ 2 + /* hw type */ 2 + /* ether addr */ 6) static u8_t dhcp6ds_serverid[/* opt */ 2 + /* optlen */ 2 + DUID_LL_LEN]; /* prebuilt DNS Servers option */
/** * RTP recv thread */ static void rtp_recv_thread(void *arg) { int sock; struct sockaddr_in local; struct sockaddr_in from; int fromlen; struct ip_mreq ipmreq; struct rtp_hdr* rtphdr; u32_t rtp_stream_address; int timeout; size_t result; int recvrtppackets = 0; int lostrtppackets = 0; u16_t lastrtpseq = 0; LWIP_UNUSED_ARG(arg); /* initialize RTP stream address */ rtp_stream_address = RTP_STREAM_ADDRESS; /* if we got a valid RTP stream address... */ if (rtp_stream_address != 0) { /* create new socket */ sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock >= 0) { /* prepare local address */ memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_port = PP_HTONS(RTP_STREAM_PORT); local.sin_addr.s_addr = PP_HTONL(INADDR_ANY); /* bind to local address */ if (bind(sock, (struct sockaddr *)&local, sizeof(local)) == 0) { /* set recv timeout */ timeout = RTP_RECV_TIMEOUT; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); /* prepare multicast "ip_mreq" struct */ ipmreq.imr_multiaddr.s_addr = rtp_stream_address; ipmreq.imr_interface.s_addr = PP_HTONL(INADDR_ANY); /* join multicast group */ if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipmreq, sizeof(ipmreq)) == 0) { /* receive RTP packets */ while(1) { fromlen = sizeof(from); result = recvfrom(sock, rtp_recv_packet, sizeof(rtp_recv_packet), 0, (struct sockaddr *)&from, (socklen_t *)&fromlen); if (result >= sizeof(struct rtp_hdr)) { rtphdr = (struct rtp_hdr *)rtp_recv_packet; recvrtppackets++; if ((lastrtpseq == 0) || ((lastrtpseq + 1) == lwip_ntohs(rtphdr->seqNum))) { RTP_RECV_PROCESSING((rtp_recv_packet + sizeof(rtp_hdr)),(result-sizeof(rtp_hdr))); } else { lostrtppackets++; } lastrtpseq = lwip_ntohs(rtphdr->seqNum); if ((recvrtppackets % RTP_RECV_STATS) == 0) { LWIP_DEBUGF(RTP_DEBUG, ("rtp_recv_thread: recv %6i packet(s) / lost %4i packet(s) (%.4f%%)...\n", recvrtppackets, lostrtppackets, (lostrtppackets*100.0)/recvrtppackets)); } } else { LWIP_DEBUGF(RTP_DEBUG, ("rtp_recv_thread: recv timeout...\n")); } } /* leave multicast group */ setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &ipmreq, sizeof(ipmreq)); } } /* close the socket */ closesocket(sock); } } }
END_TEST static void test_sockets_allfunctions_basic_domain(int domain) { int s, s2, s3, ret; struct sockaddr_storage addr, addr2; socklen_t addrlen, addr2len; char buf[4]; /* listen socket */ s = lwip_socket(domain, SOCK_STREAM, 0); fail_unless(s >= 0); ret = lwip_listen(s, 0); fail_unless(ret == 0); addrlen = sizeof(addr); ret = lwip_getsockname(s, (struct sockaddr*)&addr, &addrlen); fail_unless(ret == 0); s2 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM); fail_unless(s2 >= 0); /* nonblocking connect s2 to s (but use loopback address) */ if (domain == AF_INET) { #if LWIP_IPV4 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; addr4->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK); #endif } else { #if LWIP_IPV6 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; addr6->sin6_addr = lo6; #endif } ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen); fail_unless(ret == -1); fail_unless(errno == EINPROGRESS); ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen); fail_unless(ret == -1); fail_unless(errno == EALREADY); while(tcpip_thread_poll_one()); s3 = lwip_accept(s, (struct sockaddr*)&addr2, &addr2len); fail_unless(s3 >= 0); ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen); fail_unless(ret == -1); fail_unless(errno == EISCONN); /* write from server to client */ ret = write(s3, "test", 4); fail_unless(ret == 4); ret = lwip_shutdown(s3, SHUT_WR); fail_unless(ret == 0); while(tcpip_thread_poll_one()); ret = lwip_recv(s2, buf, 3, MSG_PEEK); fail_unless(ret == 3); ret = lwip_recv(s2, buf, 3, MSG_PEEK); fail_unless(ret == 3); ret = lwip_read(s2, buf, 4); fail_unless(ret == 4); ret = lwip_read(s2, buf, 1); fail_unless(ret == 0); ret = lwip_read(s2, buf, 1); fail_unless(ret == -1); ret = lwip_write(s2, "foo", 3); fail_unless(ret == 3); ret = lwip_close(s2); fail_unless(ret == 0); while(tcpip_thread_poll_one()); /* read one byte more than available to check handling FIN */ ret = lwip_read(s3, buf, 4); fail_unless(ret == 3); ret = lwip_read(s3, buf, 1); fail_unless(ret == 0); ret = lwip_read(s3, buf, 1); fail_unless(ret == -1); while(tcpip_thread_poll_one()); ret = lwip_close(s); fail_unless(ret == 0); ret = lwip_close(s3); fail_unless(ret == 0); }