diff --git a/ext/lwip/src/include/arch/cc.h b/ext/lwip/src/include/arch/cc.h index 462124d..ac270da 100644 --- a/ext/lwip/src/include/arch/cc.h +++ b/ext/lwip/src/include/arch/cc.h @@ -80,7 +80,8 @@ typedef unsigned long mem_ptr_t; #include #include /* Plaform specific diagnostic output */ -#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) +//#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) +#define LWIP_PLATFORM_DIAG(x) printf(x); #define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \ x, __LINE__, __FILE__); fflush(NULL); abort();} while(0) diff --git a/ext/lwip/src/include/lwip/debug.h b/ext/lwip/src/include/lwip/debug.h index dd7afa8..747c69c 100644 --- a/ext/lwip/src/include/lwip/debug.h +++ b/ext/lwip/src/include/lwip/debug.h @@ -102,7 +102,8 @@ /** print debug message only if debug message type is enabled... * AND is of correct type AND is at least LWIP_DBG_LEVEL */ -#define LWIP_DEBUGF(debug, message) LWIP_PLATFORM_DIAG(message); +#include "Debug.hpp" // use libzt's more descriptive debug printers +#define LWIP_DEBUGF(debug, message) DEBUG_LWIP message; #else /* LWIP_DEBUG */ #define LWIP_DEBUGF(debug, message) diff --git a/include/Debug.hpp b/include/Debug.hpp index ce7e68c..fe66773 100644 --- a/include/Debug.hpp +++ b/include/Debug.hpp @@ -65,18 +65,6 @@ #define ZT_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) // short -/* -#ifdef __linux__ - #define ZT_THREAD_ID 0 // (long)getpid() -#elif __FreeBSD__ - #define ZT_THREAD_ID 0 // (long)getpid() -#elif __APPLE__ - #define ZT_THREAD_ID 0 // (long)syscall(SYS_thread_selfid) -#endif -*/ - -// #define ZT_THREAD_ID 0 - #if defined(__JNI_LIB__) #include #endif @@ -85,6 +73,9 @@ #define ZT_LOG_TAG "ZTSDK" #endif +#define DEBUG_LWIP(fmt, args...) fprintf(stderr, ZT_CYN "LWIP : %17s:%5d:%25s: " fmt \ + ZT_RESET, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) + #if ZT_DEBUG_LEVEL >= ZT_MSG_TEST #define DEBUG_TEST(fmt, args...) fprintf(stderr, ZT_CYN "TEST : %17s:%5d:%25s: " fmt \ "\n" ZT_RESET, ZT_FILENAME, __LINE__, __FUNCTION__, ##args) diff --git a/include/lwipopts.h b/include/lwipopts.h index c720a52..0686477 100644 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -54,13 +54,68 @@ #define LWIP_IPV6 0 #endif -#define LWIP_TCP 1 -#define IP6_DEBUG 1 -#define LWIP_DEBUG 1 -#define IP_DEBUG LWIP_DBG_ON -#define LWIP_ETHERNET 1 +// --- DEBUG --- -#define LWIP_DBG_TYPES_ON LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_FRESH +/* flag for LWIP_DEBUGF indicating a tracing message + * (to follow program flow) + */ +#define LWIP_DBG_TRACE 0x40U +/* flag for LWIP_DEBUGF indicating a state debug message + * (to follow module states) + */ +#define LWIP_DBG_STATE 0x20U +/* flag for LWIP_DEBUGF indicating newly added code, + * not thoroughly tested yet + */ +#define LWIP_DBG_FRESH 0x10U +/* flag for LWIP_DEBUGF to halt after printing + * this debug message + */ +#define LWIP_DBG_HALT 0x08U + +#define LWIP_DEBUG 0 + +//#define LWIP_DBG_TYPES_ON LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_FRESH + +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON + +#define ETHARP_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_OFF +#define IGMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TIMERS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF +#define AUTOIP_DEBUG LWIP_DBG_OFF +#define DNS_DEBUG LWIP_DBG_OFF +#define IP6_DEBUG LWIP_DBG_OFF + +#define LWIP_UDP 1 +#define LWIP_TCP 1 +#define LWIP_ETHERNET 1 #define LWIP_CHKSUM_ALGORITHM 2 diff --git a/make-liblwip.mk b/make-liblwip.mk index 3fb662b..9e73c1b 100644 --- a/make-liblwip.mk +++ b/make-liblwip.mk @@ -104,10 +104,12 @@ LWIPFILES=$(COREFILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES) ifeq ($(LIBZT_IPV4),1) LWIPFILES+=$(CORE4FILES) CFLAGS+=-DLIBZT_IPV4=1 -DLWIP_IPV4 -DLWIP_IPV6=0 -DIPv4 + #-DLWIP_DEBUG=1 endif ifeq ($(LIBZT_IPV6),1) LWIPFILES+=$(CORE6FILES) CFLAGS+=-DLIBZT_IPV6=1 -DLWIP_IPV6 -DLWIP_IPV4=0 -DIPv6 + # -DLWIP_DEBUG=1 endif LWIPFILESW=$(wildcard $(LWIPFILES)) diff --git a/src/VirtualTap.cpp b/src/VirtualTap.cpp index 6db45c3..dd8b48c 100644 --- a/src/VirtualTap.cpp +++ b/src/VirtualTap.cpp @@ -542,9 +542,10 @@ namespace ZeroTier { } #endif #if defined(STACK_LWIP) - if(lwipstack) + if(lwipstack) { err = lwipstack->lwip_Connect(vs, addr, addrlen); // implicit err = lwipstack->lwip_Write(vs, (void*)buf, len); + } #endif return err; } diff --git a/src/VirtualTap.hpp b/src/VirtualTap.hpp index 315a1f1..37b82f6 100644 --- a/src/VirtualTap.hpp +++ b/src/VirtualTap.hpp @@ -210,12 +210,10 @@ namespace ZeroTier { int pico_frame_rxbuf_tot = 0; Mutex _pico_frame_rxbuf_m; #endif - #if defined(STACK_LWIP) netif lwipdev; netif lwipdev6; #endif - std::vector> routes; void *zt1ServiceRef = NULL; diff --git a/src/libzt.cpp b/src/libzt.cpp index 8d2204e..4f1c77e 100644 --- a/src/libzt.cpp +++ b/src/libzt.cpp @@ -499,6 +499,7 @@ Linux: */ int zts_connect(ZT_CONNECT_SIG) { + DEBUG_INFO("fd=%d"); int err = errno = 0; if(fd < 0 || fd >= ZT_MAX_SOCKETS) { errno = EBADF; @@ -979,6 +980,7 @@ Linux: */ int zts_getpeername(ZT_GETPEERNAME_SIG) { + DEBUG_INFO("fd=%d"); int err = errno = 0; if(fd < 0 || fd >= ZT_MAX_SOCKETS) { errno = EBADF; @@ -1048,6 +1050,7 @@ Linux / Darwin: int zts_close(ZT_CLOSE_SIG) { + //DEBUG_EXTRA("fd=%d", fd); int err = errno = 0; if(fd < 0 || fd >= ZT_MAX_SOCKETS) { errno = EBADF; @@ -1206,7 +1209,7 @@ Linux: ssize_t zts_sendto(ZT_SENDTO_SIG) { - //DEBUG_TRANS("fd=%d", fd); + DEBUG_TRANS("fd=%d", fd); int err = errno = 0; if(fd < 0 || fd >= ZT_MAX_SOCKETS) { errno = EBADF; @@ -1552,7 +1555,7 @@ ssize_t zts_recv(ZT_RECV_SIG) ssize_t zts_recvfrom(ZT_RECVFROM_SIG) { - //DEBUG_TRANS("fd=%d", fd); + DEBUG_TRANS("fd=%d", fd); int32_t r = 0; errno = 0; if(fd < 0 || fd >= ZT_MAX_SOCKETS) { diff --git a/src/lwIP.cpp b/src/lwIP.cpp index 89f694c..2e02fab 100644 --- a/src/lwIP.cpp +++ b/src/lwIP.cpp @@ -45,7 +45,6 @@ void nd6_tmr(void); err_t tapif_init(struct netif *netif) { - DEBUG_INFO(); return ERR_OK; } @@ -95,7 +94,8 @@ namespace ZeroTier { void lwIP::lwip_init_interface(VirtualTap *tap, const InetAddress &ip) { - DEBUG_INFO(); + /* NOTE: It is a known issue that when assigned more than one IP address via + Central, this interface will be unable to transmit (including ARP). */ Mutex::Lock _l(tap->_ips_m); if (std::find(tap->_ips.begin(),tap->_ips.end(),ip) == tap->_ips.end()) { @@ -104,7 +104,6 @@ namespace ZeroTier char ipbuf[INET6_ADDRSTRLEN], nmbuf[INET6_ADDRSTRLEN]; #if defined(LIBZT_IPV4) if (ip.isV4()) { - // Set IP static ip_addr_t ipaddr, netmask, gw; IP4_ADDR(&gw,127,0,0,1); ipaddr.addr = *((u32_t *)ip.rawIpData()); @@ -112,16 +111,18 @@ namespace ZeroTier netif_add(&(tap->lwipdev),&ipaddr, &netmask, &gw, NULL, tapif_init, ethernet_input); tap->lwipdev.state = tap; tap->lwipdev.output = etharp_output; - tap->_mac.copyTo(tap->lwipdev.hwaddr, 6); tap->lwipdev.mtu = tap->_mtu; tap->lwipdev.name[0] = 'l'; tap->lwipdev.name[1] = '4'; tap->lwipdev.linkoutput = lwip_eth_tx; tap->lwipdev.hwaddr_len = 6; + tap->_mac.copyTo(tap->lwipdev.hwaddr, tap->lwipdev.hwaddr_len); tap->lwipdev.flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; netif_set_default(&(tap->lwipdev)); netif_set_up(&(tap->lwipdev)); - DEBUG_INFO("addr=%s, netmask=%s", ip.toString(ipbuf), ip.netmask().toString(nmbuf)); + char macbuf[ZT_MAC_ADDRSTRLEN]; + mac2str(macbuf, ZT_MAC_ADDRSTRLEN, tap->lwipdev.hwaddr); + DEBUG_INFO("mac=%s, addr=%s, nm=%s", macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf)); } #endif #if defined(LIBZT_IPV6) @@ -133,20 +134,38 @@ namespace ZeroTier tap->lwipdev6.mtu = tap->_mtu; tap->lwipdev6.name[0] = 'l'; tap->lwipdev6.name[1] = '6'; + + // hwaddr tap->lwipdev6.hwaddr_len = 6; - tap->lwipdev6.linkoutput = lwip_eth_tx; - tap->lwipdev6.ip6_autoconfig_enabled = 1; tap->_mac.copyTo(tap->lwipdev6.hwaddr, tap->lwipdev6.hwaddr_len); - netif_create_ip6_linklocal_address(&(tap->lwipdev6), 1); - netif_add(&(tap->lwipdev6), NULL, tapif_init, ethernet_input); - netif_set_default(&(tap->lwipdev6)); - netif_set_up(&(tap->lwipdev6)); - netif_ip6_addr_set_state(&(tap->lwipdev6), 1, IP6_ADDR_TENTATIVE); - ip6_addr_copy(ip_2_ip6(tap->lwipdev6.ip6_addr[1]), addr6); + + // I/O + tap->lwipdev6.linkoutput = lwip_eth_tx; tap->lwipdev6.output_ip6 = ethip6_output; + netif_add(&(tap->lwipdev6), NULL, tapif_init, ethernet_input); + + //struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx + //netif_add_ip6_address(); + + // linklocal + tap->lwipdev6.ip6_autoconfig_enabled = 1; + netif_create_ip6_linklocal_address(&(tap->lwipdev6), 1); + netif_ip6_addr_set_state(&(tap->lwipdev6), 0, IP6_ADDR_TENTATIVE); + + // manually config addresses + ip6_addr_copy(ip_2_ip6(tap->lwipdev6.ip6_addr[1]), addr6); + netif_ip6_addr_set_state(&(tap->lwipdev6), 1, IP6_ADDR_TENTATIVE); + + netif_set_default(&(tap->lwipdev6)); + netif_set_up(&(tap->lwipdev6)); + + // state and flags tap->lwipdev6.state = tap; tap->lwipdev6.flags = NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; - DEBUG_INFO("addr=%s, netmask=%s", ip.toString(ipbuf), ip.netmask().toString(nmbuf)); + + char macbuf[ZT_MAC_ADDRSTRLEN]; + mac2str(macbuf, ZT_MAC_ADDRSTRLEN, tap->lwipdev6.hwaddr); + DEBUG_INFO("mac=%s, addr=%s", macbuf, ip.toString(ipbuf)); } #endif } @@ -206,8 +225,9 @@ namespace ZeroTier void lwIP::lwip_eth_rx(VirtualTap *tap, const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len) { struct pbuf *p,*q; - if (!tap->_enabled) + if (!tap->_enabled){ return; + } struct eth_hdr ethhdr; from.copyTo(ethhdr.src.addr, 6); to.copyTo(ethhdr.dest.addr, 6); @@ -225,39 +245,36 @@ namespace ZeroTier memcpy(q->payload,ðhdr,sizeof(ethhdr)); memcpy((char*)q->payload + sizeof(ethhdr),dataptr,q->len - sizeof(ethhdr)); dataptr += q->len - sizeof(ethhdr); - // Remaining pbufs (if any) get rest of data while ((q = q->next)) { memcpy(q->payload,dataptr,q->len); dataptr += q->len; } } - if(ZT_DEBUG_LEVEL >= ZT_MSG_TRANSFER) { char flagbuf[32]; memset(&flagbuf, 0, 32); char macBuf[ZT_MAC_ADDRSTRLEN], nodeBuf[ZT_ID_LEN]; mac2str(macBuf, ZT_MAC_ADDRSTRLEN, ethhdr.dest.addr); ZeroTier::MAC mac; - mac.setTo(ethhdr.dest.addr, 6); + mac.setTo(ethhdr.src.addr, 6); mac.toAddress(tap->_nwid).toString(nodeBuf); DEBUG_TRANS("len=%5d dst=%s [%s RX --> %s] proto=0x%04x %s %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), ZeroTier::Utils::ntoh(ethhdr.type), beautify_eth_proto_nums(ZeroTier::Utils::ntoh(ethhdr.type)), flagbuf); } - else { DEBUG_ERROR("dropped packet: no pbufs available"); return; } { -#if defined(LIBZT_IPV6) - if(tap->lwipdev6.input(p, &(tap->lwipdev6)) != ERR_OK) { - DEBUG_ERROR("error while feeding frame into stack lwipdev6"); - } -#endif #if defined(LIBZT_IPV4) if(tap->lwipdev.input(p, &(tap->lwipdev)) != ERR_OK) { - DEBUG_ERROR("error while feeding frame into stack lwipdev"); + DEBUG_ERROR("error while feeding frame into stack interface (ipv4)"); + } +#endif +#if defined(LIBZT_IPV6) + if(tap->lwipdev6.input(p, &(tap->lwipdev6)) != ERR_OK) { + DEBUG_ERROR("error while feeding frame into stack interface (ipv6)"); } #endif } @@ -265,7 +282,7 @@ namespace ZeroTier int lwIP::lwip_Socket(void **pcb, int socket_family, int socket_type, int protocol) { - DEBUG_INFO(); + //DEBUG_INFO(); if(!can_provision_new_socket()) { DEBUG_ERROR("unable to create new socket due to limitation of network stack"); return -1; @@ -285,7 +302,7 @@ namespace ZeroTier int lwIP::lwip_Connect(VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) { - DEBUG_INFO(); + //DEBUG_INFO(); ip_addr_t ba; char addrstr[INET6_ADDRSTRLEN]; int port = 0, err = 0; @@ -303,7 +320,6 @@ namespace ZeroTier struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr; in6_to_ip6((ip6_addr *)&ba, in6); if(addr->sa_family == AF_INET6) { - struct sockaddr_in6 *vsaddr6 = (struct sockaddr_in6 *)addr; inet_ntop(AF_INET6, &(in6->sin6_addr), addrstr, INET6_ADDRSTRLEN); DEBUG_EXTRA("connecting to %s : %d", addrstr, lwip_ntohs(in6->sin6_port)); } @@ -376,9 +392,10 @@ namespace ZeroTier int lwIP::lwip_Bind(VirtualTap *tap, VirtualSocket *vs, const struct sockaddr *addr, socklen_t addrlen) { - DEBUG_INFO(); + //DEBUG_EXTRA("vs=%p", vs); ip_addr_t ba; char addrstr[INET6_ADDRSTRLEN]; + memset(addrstr, 0, INET6_ADDRSTRLEN); int port = 0, err = 0; #if defined(LIBZT_IPV4) @@ -391,10 +408,9 @@ namespace ZeroTier port = lwip_ntohs(in4->sin_port); #endif #if defined(LIBZT_IPV6) - struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&addr; + struct sockaddr_in6 *in6 = (struct sockaddr_in6*)addr; in6_to_ip6((ip6_addr *)&ba, in6); if(addr->sa_family == AF_INET6) { - struct sockaddr_in6 *vsaddr6 = (struct sockaddr_in6 *)addr; inet_ntop(AF_INET6, &(in6->sin6_addr), addrstr, INET6_ADDRSTRLEN); DEBUG_EXTRA("binding to %s : %d", addrstr, lwip_ntohs(in6->sin6_port)); } @@ -407,7 +423,7 @@ namespace ZeroTier } else { // set the recv callback - udp_recv((struct udp_pcb*)vs->pcb, lwip_cb_udp_recved, new VirtualBindingPair(tap, vs)); + udp_recv((struct udp_pcb*)vs->pcb, lwip_cb_udp_recved, vs); err = ERR_OK; errno = ERR_OK; // success } @@ -464,7 +480,6 @@ namespace ZeroTier } // Retreive first of queued VirtualSockets from parent VirtualSocket VirtualSocket *new_vs = NULL; - Mutex::Lock _l(vs->tap->_tcpconns_m); if(vs->_AcceptedConnections.size()) { new_vs = vs->_AcceptedConnections.front(); vs->_AcceptedConnections.pop(); @@ -515,7 +530,7 @@ namespace ZeroTier int lwIP::lwip_Write(VirtualSocket *vs, void *data, ssize_t len) { - DEBUG_EXTRA("vs=%p, len=%d", (void*)&vs, len); + DEBUG_EXTRA("vs=%p, len=%d", vs, len); int err = 0; if(!vs) { DEBUG_ERROR("no virtual socket"); @@ -523,16 +538,16 @@ namespace ZeroTier } if(vs->socket_type == SOCK_DGRAM) { - DEBUG_ERROR("socket_type==SOCK_DGRAM"); + //DEBUG_ERROR("socket_type==SOCK_DGRAM"); // TODO: Packet re-assembly hasn't yet been tested with lwIP so UDP packets are limited to MTU-sized chunks - int udp_trans_len = std::min((ssize_t)vs->TXbuf->count(), (ssize_t)ZT_MAX_MTU); - DEBUG_EXTRA("allocating pbuf chain of size=%d for UDP packet, txsz=%d", udp_trans_len, vs->TXbuf->count()); + int udp_trans_len = std::min(len, (ssize_t)ZT_MAX_MTU); + //DEBUG_EXTRA("allocating pbuf chain of size=%d for UDP packet", udp_trans_len); struct pbuf * pb = pbuf_alloc(PBUF_TRANSPORT, udp_trans_len, PBUF_POOL); if(!pb){ DEBUG_ERROR("unable to allocate new pbuf of size=%d", vs->TXbuf->count()); return -1; } - memcpy(pb->payload, vs->TXbuf->get_buf(), udp_trans_len); + memcpy(pb->payload, data, udp_trans_len); int err = udp_send((struct udp_pcb*)vs->pcb, pb); if(err == ERR_MEM) { @@ -541,11 +556,11 @@ namespace ZeroTier DEBUG_ERROR("could not find route to destinations address"); } else if(err != ERR_OK) { DEBUG_ERROR("error sending packet - %d", err); - } else { - vs->TXbuf->consume(udp_trans_len); // success - } + } pbuf_free(pb); - return ERR_OK; + if(err == ERR_OK) { + return udp_trans_len; + } } if(vs->socket_type == SOCK_STREAM) { @@ -594,15 +609,14 @@ namespace ZeroTier int lwIP::lwip_Close(VirtualSocket *vs) { - DEBUG_INFO(); - + //DEBUG_INFO(); if(vs->socket_type == SOCK_DGRAM) { udp_remove((struct udp_pcb*)vs->pcb); } // FIXME: check if already closed? vs->TCP_pcb->state != CLOSED if(vs->pcb) { //DEBUG_EXTRA("vs=%p, sock=%p, PCB->state = %d", - // (void*)&conn, (void*)&sock, vs->TCP_pcb->state); + // conn, sock, vs->TCP_pcb->state); if(((struct tcp_pcb*)vs->pcb)->state == SYN_SENT /*|| vs->TCP_pcb->state == CLOSE_WAIT*/) { DEBUG_EXTRA("ignoring close request. invalid PCB state for this operation. sock=%p", vs->sock); return -1; @@ -634,26 +648,25 @@ namespace ZeroTier int tot = 0; if(!vs) { - DEBUG_ERROR("no VirtualSocket"); + DEBUG_ERROR("no virtual socket"); return ERR_OK; // FIXME: Determine if this is correct behaviour expected by the stack } - //Mutex::Lock _l(vs->tap->_tcpconns_m); - //Mutex::Lock _l2(vs->_rx_m); - vs->tap->_tcpconns_m.lock(); - vs->_rx_m.lock(); - struct pbuf* q = p; if(p == NULL) { + /* if(((struct tcp_pcb*)vs->pcb)->state == CLOSE_WAIT) { // FIXME: Implement? } + */ DEBUG_INFO("p == NULL"); return ERR_ABRT; } - // Cycle through pbufs and write them to the RX buffer - // The RX buffer will be emptied via phyOnUnixWritable() + vs->tap->_tcpconns_m.lock(); + vs->_rx_m.lock(); + + // cycle through pbufs and write them to the RX buffer while(p != NULL) { if(p->len <= 0) break; @@ -662,6 +675,7 @@ namespace ZeroTier if(avail < len) { DEBUG_ERROR("not enough room (%d bytes) on RX buffer", avail); } + // get it on the buffer, fast! memcpy(vs->RXbuf->get_buf(), p->payload, len); vs->RXbuf->produce(len); p = p->next; @@ -669,13 +683,24 @@ namespace ZeroTier } DEBUG_INFO("tot=%d", tot); + if(tot) { + int w, write_attempt_sz = vs->RXbuf->count() < ZT_MAX_MTU ? vs->RXbuf->count() : ZT_MAX_MTU; + if((w = write(vs->sdk_fd, vs->RXbuf->get_buf(), write_attempt_sz)) < 0) { + perror("write"); + DEBUG_ERROR("write(fd=%d)=%d, errno=%d", vs->sdk_fd, w, errno); + } + if(w > 0) { + DEBUG_INFO("write_attempt_sz=%d, w=%d", write_attempt_sz, w); + vs->RXbuf->consume(w); + } + + //vs->tap->_phy.setNotifyWritable(vs->sock, true); + //vs->tap->phyOnUnixWritable(vs->sock, NULL, true); // to app + } + vs->tap->_tcpconns_m.unlock(); vs->_rx_m.unlock(); - if(tot) { - vs->tap->_phy.setNotifyWritable(vs->sock, true); - //vs->tap->phyOnUnixWritable(vs->sock, NULL, true); // to app - } pbuf_free(q); return ERR_OK; } @@ -683,15 +708,24 @@ namespace ZeroTier err_t lwIP::lwip_cb_accept(void *arg, struct tcp_pcb *newPCB, err_t err) { VirtualSocket *vs = (VirtualSocket*)arg; - DEBUG_INFO("vs=%p", vs); - //Mutex::Lock _l(vs->tap->_tcpconns_m); + struct sockaddr_storage ss; +#if defined(LIBZT_IPV4) + struct sockaddr_in *in4 = (struct sockaddr_in *)&ss; + in4->sin_addr.s_addr = newPCB->remote_ip.addr; + in4->sin_port = newPCB->remote_port; +#endif +#if defined(LIBZT_IPV6) + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&ss; + // TODO: check this + memcpy(&(in6->sin6_addr.s6_addr), &(newPCB->remote_ip), sizeof(int32_t)*4); + in6->sin6_port = newPCB->remote_port; +#endif VirtualSocket *new_vs = new VirtualSocket(); new_vs->socket_type = SOCK_STREAM; new_vs->pcb = newPCB; new_vs->tap = vs->tap; new_vs->sock = vs->tap->_phy.wrapSocket(new_vs->sdk_fd, new_vs); - //memcpy(new_vs->tap->_phy.getuptr(new_vs->sock), new_vs, sizeof(vs)); - DEBUG_INFO("new_vs=%p", new_vs); + memcpy(&(new_vs->peer_addr), &ss, sizeof(new_vs->peer_addr)); // add new VirtualSocket object to parent VirtualSocket so that we can find it via lwip_Accept() vs->_AcceptedConnections.push(new_vs); // set callbacks @@ -700,20 +734,74 @@ namespace ZeroTier tcp_err(newPCB, lwip_cb_err); tcp_sent(newPCB, lwip_cb_sent); tcp_poll(newPCB, lwip_cb_poll, 1); - // let lwIP know that it can queue additional incoming VirtualSockets + // let lwIP know that it can queue additional incoming PCBs tcp_accepted((struct tcp_pcb*)vs->pcb); return 0; } + // copy processed datagram to app socket void lwIP::lwip_cb_udp_recved(void * arg, struct udp_pcb * upcb, struct pbuf * p, const ip_addr_t * addr, u16_t port) { - DEBUG_INFO(); - // to be implemented + DEBUG_EXTRA("arg(vs)=%p, pcb=%p, port=%d)", arg, upcb, port); + VirtualSocket *vs = (VirtualSocket *)arg; + if(!vs) { + DEBUG_ERROR("invalid virtual socket"); + return; + } + if(!p) { + DEBUG_ERROR("!p"); + return; + } + struct pbuf* q = p; + struct sockaddr_storage ss; + + #if defined(LIBZT_IPV4) + struct sockaddr_in *in4 = (struct sockaddr_in *)&ss; + in4->sin_addr.s_addr = addr->addr; + in4->sin_port = port; + #endif + #if defined(LIBZT_IPV6) + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&ss; + memcpy(&(in6->sin6_addr.s6_addr), &(addr->addr), sizeof(int32_t)*4); + in6->sin6_port = port; + #endif + + char udp_payload_buf[ZT_SOCKET_MSG_BUF_SZ]; + char *msg_ptr = udp_payload_buf; + + int tot_len = 0; + while(p != NULL) + { + if(p->len <= 0) { + break; + } + memcpy(msg_ptr, p->payload, p->len); + msg_ptr += p->len; + tot_len += p->len; + p = p->next; + } + if(tot_len) { + int w = 0; + //DEBUG_INFO("tot_len=%d", tot_len); + char udp_msg_buf[ZT_SOCKET_MSG_BUF_SZ]; // [sz : addr : payload] + int32_t len = sizeof(struct sockaddr_storage) + tot_len; + int32_t msg_tot_len = sizeof(int32_t) + len; + memcpy(udp_msg_buf, &len, sizeof(int32_t)); // len: sockaddr+payload + memcpy(udp_msg_buf + sizeof(int32_t), &ss, sizeof(struct sockaddr_storage)); // sockaddr + memcpy(udp_msg_buf + sizeof(int32_t) + sizeof(struct sockaddr_storage), &udp_payload_buf, tot_len); // payload + if((w = write(vs->sdk_fd, udp_msg_buf, msg_tot_len)) < 0) { + perror("write"); + DEBUG_ERROR("write(fd=%d)=%d, errno=%d", vs->sdk_fd, w, errno); + } + //vs->tap->phyOnUnixWritable(vs->sock, NULL, true); + //vs->tap->_phy.setNotifyWritable(vs->sock, true); + } + pbuf_free(q); } err_t lwIP::lwip_cb_sent(void* arg, struct tcp_pcb *PCB, u16_t len) { - DEBUG_EXTRA("pcb=%p", (void*)&PCB); + DEBUG_EXTRA("pcb=%p", PCB); VirtualSocket *vs = (VirtualSocket *)arg; Mutex::Lock _l(vs->tap->_tcpconns_m); if(vs && len) { @@ -728,12 +816,18 @@ namespace ZeroTier err_t lwIP::lwip_cb_connected(void *arg, struct tcp_pcb *PCB, err_t err) { - DEBUG_ATTN("pcb=%p", (void*)&PCB); + DEBUG_ATTN("pcb=%p", PCB); VirtualSocket *vs = (VirtualSocket *)arg; - if(vs) - return ERR_OK; - return -1; - // FIXME: check stack for expected return values + if(!vs) { + DEBUG_ERROR("invalid virtual socket"); + return -1; + } + // add to unhandled connection set for zts_connect to pick up on + vs->tap->_tcpconns_m.lock(); + vs->state = ZT_SOCK_STATE_UNHANDLED_CONNECTED; + vs->tap->_VirtualSockets.push_back(vs); + vs->tap->_tcpconns_m.unlock(); + return ERR_OK; } err_t lwIP::lwip_cb_poll(void* arg, struct tcp_pcb *PCB) @@ -752,7 +846,7 @@ namespace ZeroTier Mutex::Lock _l(vs->tap->_tcpconns_m); int fd = vs->tap->_phy.getDescriptor(vs->sock); DEBUG_ERROR("vs=%p, pcb=%p, fd=%d, err=%d", vs, vs->pcb, fd, err); - DEBUG_ERROR("closing VirtualSocket"); + DEBUG_ERROR("closing virtual socket"); vs->tap->Close(vs); switch(err) { diff --git a/src/lwIP.hpp b/src/lwIP.hpp index 830bc49..c0992f8 100644 --- a/src/lwIP.hpp +++ b/src/lwIP.hpp @@ -103,6 +103,8 @@ struct netif; #define LWIP_NETIF_SET_UP_SIG struct netif *netif #define LWIP_NETIF_POLL_SIG struct netif *netif +#define NETIF_SET_STATUS_CALLBACK struct netif *netif, netif_status_callback_fn status_callback + #if defined(LIBZT_IPV4) extern "C" err_t etharp_output(LWIP_ETHARP_OUTPUT_SIG); @@ -159,6 +161,8 @@ extern "C" u16_t lwip_ntohs(LWIP_NTOHS_SIG); extern "C" void tcp_input(LWIP_TCP_INPUT_SIG); extern "C" err_t ip_input(LWIP_IP_INPUT_SIG); +//extern "C" void netif_set_status_callback(NETIF_SET_STATUS_CALLBACK); + namespace ZeroTier { @@ -237,6 +241,7 @@ namespace ZeroTier { // --- Callbacks from network stack --- + //static void netif_status_callback(struct netif *nif); /* * Callback for handling received UDP packets (already processed by network stack) diff --git a/test/selftest.cpp b/test/selftest.cpp index 1589a8d..b56705d 100644 --- a/test/selftest.cpp +++ b/test/selftest.cpp @@ -2335,13 +2335,13 @@ udp-ip6-server | | OK | | OK // set start time here since we aren't waiting for libzt to come online in NATIVETEST mode #if defined(__NATIVETEST__) long int selftest_start_time = get_now_ts(); - subtest_expected_duration = 10; // initial value, wait for other instance to come online + subtest_expected_duration = 0; // initial value, wait for other instance to come online #endif #if defined(LIBZT_IPV4) // UDP 4 client/server - + /* ipv = 4; subtest_start_time_offset += subtest_expected_duration; subtest_expected_duration = 30; @@ -2413,7 +2413,7 @@ udp-ip6-server | | OK | | OK } RECORD_RESULTS(passed, details, &results); port++; - +*/ // TCP 4 client/server ipv = 4;