diff --git a/ext/lwip/src/core/ipv6/ip6.c b/ext/lwip/src/core/ipv6/ip6.c index 1ebde1c..3f604df 100644 --- a/ext/lwip/src/core/ipv6/ip6.c +++ b/ext/lwip/src/core/ipv6/ip6.c @@ -500,15 +500,11 @@ ip6_input(struct pbuf *p, struct netif *inp) if (netif_is_up(netif)) { /* unicast to this interface address? address configured? */ for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - ip_addr_debug_print(1, netif_ip6_addr(inp, i)); - - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { - if(ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { - /* exit outer loop */ - goto netif_found; - } + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { + /* exit outer loop */ + goto netif_found; } - } } if (ip6_addr_islinklocal(ip6_current_dest_addr())) { @@ -527,7 +523,6 @@ ip6_input(struct pbuf *p, struct netif *inp) } } while (netif != NULL); netif_found: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); } @@ -545,7 +540,6 @@ netif_found: /* packet not for us? */ if (netif == NULL) { - ip6_debug_print(p); /* packet not for us, route or discard */ LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); #if LWIP_IPV6_FORWARD @@ -716,6 +710,7 @@ options_done: pbuf_header_force(p, ip_data.current_ip_header_tot_len); /* send to upper layers */ + LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); ip6_debug_print(p); LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); @@ -890,6 +885,7 @@ ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { /* Packet to self, enqueue it for loopback */ + LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); return netif_loop_output(netif, p); } } @@ -902,6 +898,7 @@ ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, } #endif /* LWIP_IPV6_FRAG */ + LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); return netif->output_ip6(netif, p, dest); } diff --git a/make-liblwip200.mk b/make-liblwip.mk similarity index 98% rename from make-liblwip200.mk rename to make-liblwip.mk index 91b1175..b66d2bc 100644 --- a/make-liblwip200.mk +++ b/make-liblwip.mk @@ -123,7 +123,7 @@ all: $(LWIPLIB) .PHONY: all clean: - rm -f *.o $(LWIPLIB) *.s .depend* *.core core + rm -f *.o $(LWIPLIB4) $(LWIPLIB6) *.s .depend* *.core core depend dep: .depend diff --git a/make-liblwip141.mk b/make-liblwip141.mk deleted file mode 100644 index 033280b..0000000 --- a/make-liblwip141.mk +++ /dev/null @@ -1,112 +0,0 @@ -# -# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# 3. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -# OF SUCH DAMAGE. -# -# This file is part of the lwIP TCP/IP stack. -# -# Author: Adam Dunkels -# - -CONTRIBDIR=ext/contrib -LWIPARCH=$(CONTRIBDIR)/ports/unix - -#Set this to where you have the lwip core module checked out from CVS -#default assumes it's a dir named lwip at the same level as the contrib module -LWIPDIR=ext/lwip/src - - -CCDEP=gcc -CC=gcc -CFLAGS=-O3 -g -Wall -DIPv4 -fPIC - -# Debug output for lwIP -ifeq ($(SDK_LWIP_DEBUG),1) - CFLAGS+=-DLWIP_DEBUG -endif - -CFLAGS:=$(CFLAGS) \ - -I$(LWIPDIR)/include -I$(LWIPARCH)/include -I$(LWIPDIR)/include/ipv4 \ - -I$(LWIPDIR) -I. - - -# COREFILES, CORE4FILES: The minimum set of files needed for lwIP. -COREFILES=$(LWIPDIR)/core/mem.c $(LWIPDIR)/core/memp.c $(LWIPDIR)/core/netif.c \ - $(LWIPDIR)/core/pbuf.c $(LWIPDIR)/core/raw.c $(LWIPDIR)/core/stats.c \ - $(LWIPDIR)/core/sys.c $(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_in.c \ - $(LWIPDIR)/core/tcp_out.c $(LWIPDIR)/core/udp.c \ - $(LWIPDIR)/core/init.c $(LWIPDIR)/core/timers.c $(LWIPDIR)/core/def.c - -CORE4FILES=$(wildcard $(LWIPDIR)/core/ipv4/*.c) $(LWIPDIR)/core/ipv4/inet.c \ - $(LWIPDIR)/core/ipv4/inet_chksum.c - -# SNMPFILES: Extra SNMPv1 agent -SNMPFILES=$(LWIPDIR)/core/snmp/asn1_dec.c $(LWIPDIR)/core/snmp/asn1_enc.c \ - $(LWIPDIR)/core/snmp/mib2.c $(LWIPDIR)/core/snmp/mib_structs.c \ - $(LWIPDIR)/core/snmp/msg_in.c $(LWIPDIR)/core/snmp/msg_out.c - -# APIFILES: The files which implement the sequential and socket APIs. -APIFILES=$(LWIPDIR)/api/api_lib.c $(LWIPDIR)/api/api_msg.c $(LWIPDIR)/api/tcpip.c \ - $(LWIPDIR)/api/err.c $(LWIPDIR)/api/sockets.c $(LWIPDIR)/api/netbuf.c $(LWIPDIR)/api/netdb.c - -# NETIFFILES: Files implementing various generic network interface functions.' -NETIFFILES=$(LWIPDIR)/netif/etharp.c $(LWIPDIR)/netif/slipif.c - -# NETIFFILES: Add PPP netif -NETIFFILES+=$(LWIPDIR)/netif/ppp/auth.c $(LWIPDIR)/netif/ppp/chap.c \ - $(LWIPDIR)/netif/ppp/chpms.c $(LWIPDIR)/netif/ppp/fsm.c \ - $(LWIPDIR)/netif/ppp/ipcp.c $(LWIPDIR)/netif/ppp/lcp.c \ - $(LWIPDIR)/netif/ppp/magic.c $(LWIPDIR)/netif/ppp/md5.c \ - $(LWIPDIR)/netif/ppp/pap.c $(LWIPDIR)/netif/ppp/ppp.c \ - $(LWIPDIR)/netif/ppp/randm.c $(LWIPDIR)/netif/ppp/vj.c - -# ARCHFILES: Architecture specific files. -ARCHFILES=$(wildcard $(LWIPARCH)/*.c $(LWIPARCH)tapif.c $(LWIPARCH)/netif/list.c $(LWIPARCH)/netif/tcpdump.c) - -# LWIPFILES: All the above. -LWIPFILES=$(COREFILES) $(CORE4FILES) $(SNMPFILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES) -LWIPFILESW=$(wildcard $(LWIPFILES)) -LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o)) - -LWIPLIB=liblwip.so - -%.o: - $(CC) $(CFLAGS) -c $(<:.o=.c) - -all: $(LWIPLIB) -.PHONY: all - -clean: - rm -f *.o $(LWIPLIB) *.s .depend* *.core core - -depend dep: .depend - -include .depend - -$(LWIPLIB): $(LWIPOBJS) - mkdir -p build - $(CC) -g -nostartfiles -shared -o build/$@ $^ - -.depend: $(LWIPFILES) - $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend diff --git a/make-linux.mk b/make-linux.mk index e0df437..5d01280 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -24,9 +24,7 @@ ONE_CLI = $(BUILD)/$(ONE_CLI_NAME) ONE_IDTOOL = $(BUILD)/$(ONE_IDTOOL_NAME) LWIP_LIB = $(BUILD)/$(LWIP_LIB_NAME) # -LWIP_2_DIR = ext/lwip -LWIP_1_DIR = ext/lwip141 -LWIP_BASE_DIR = ext/lwip +LWIP_DIR = ext/lwip # Automagically pick clang or gcc, with preference for clang # This is only done if we have not overridden these with an environment or CLI variable @@ -80,24 +78,16 @@ INCLUDES+= -Iext \ -I../$(ZT1)/node \ -I../$(ZT1)/service \ -I. \ - -Isrc + -Isrc \ + -I$(LWIP_DIR)/src/include \ + -I$(LWIP_DIR)/src/include/ipv4 \ + -I$(LWIP_DIR)/src/include/ipv6 # lwIP ifeq ($(SDK_LWIP_DEBUG),1) LWIP_FLAGS+=SDK_LWIP_DEBUG=1 endif -ifeq ($(LWIP_VERSION_2),1) - CXXFLAGS+=-DLWIP_VERSION_2 - INCLUDES+=-I$(LWIP_2_DIR)/src/include - INCLUDES+=-I$(LWIP_2_DIR)/src/include/ipv4 - INCLUDES+=-I$(LWIP_2_DIR)/src/include/ipv6 -else - INCLUDES+=-I$(LWIP_1_DIR)/src/include - INCLUDES+=-I$(LWIP_1_DIR)/src/include/ipv4 - INCLUDES+=-I$(LWIP_1_DIR)/src/include/ipv6 -endif - # Debug output for the SDK # Specific levels can be controlled in src/SDK_Debug.h @@ -122,17 +112,7 @@ remove_only_intermediates: # --- EXTERNAL LIBRARIES --- lwip: -ifeq ($(LWIP_VERSION_2),1) - #mv ext/lwip200 ext/lwip - -make -f make-liblwip200.mk $(LWIP_FLAGS) - #mv ext/lwip ext/lwip200 -else - mv ext/lwip141 ext/lwip - -make -f make-liblwip141.mk $(LWIP_FLAGS) - mv ext/lwip ext/lwip141 -endif - - + -make -f make-liblwip.mk $(LWIP_FLAGS) # --------- LINUX ---------- @@ -252,14 +232,6 @@ test_suite: tests lwip linux_service_and_intercept # ----- ADMINISTRATIVE ----- -#restore_lwip_dirs: -# if [ -d "$LWIP_2_DIR" && ! -d "$LWIP_1_DIR" ]; then -# -mv $LWIP_BASE_DIR $LWIP_1_DIR -# fi -# if [ -d "$LWIP_1_DIR" && ! -d "$LWIP_2_DIR" ]; then -# -mv $LWIP_BASE_DIR $LWIP_2_DIR -# fi - clean_android: # android JNI lib project -test -s /usr/bin/javac || { echo "Javac not found"; exit 1; } diff --git a/src/SDK_EthernetTap.cpp b/src/SDK_EthernetTap.cpp index dac97bd..ab98ffa 100644 --- a/src/SDK_EthernetTap.cpp +++ b/src/SDK_EthernetTap.cpp @@ -36,41 +36,33 @@ #include #include "SDK_EthernetTap.hpp" +#include "SDK_Utils.hpp" +#include "SDK.h" +#include "SDK_Debug.h" +#include "SDK_LWIPStack.hpp" #include "Utils.hpp" #include "OSUtils.hpp" #include "Constants.hpp" #include "Phy.hpp" -#include "SDK_LWIPStack.hpp" - // LWIP #include "lwip/priv/tcp_priv.h" - - -//#include "lwip/etharp.h" #include "lwip/nd6.h" - #include "lwip/api.h" #include "lwip/ip.h" - -//#include "lwip/tcp_impl.h" - - #include "lwip/ip_addr.h" #include "lwip/tcp.h" #include "lwip/init.h" #include "lwip/mem.h" #include "lwip/pbuf.h" -//#include "lwip/ip_addr.h" #include "lwip/netif.h" #include "lwip/udp.h" #include "lwip/tcp.h" -#include "SDK.h" -#include "SDK_Debug.h" - #include "Mutex.hpp" - +//#include "lwip/etharp.h" +//#include "lwip/ip_addr.h" +//#include "lwip/tcp_impl.h" //#if !defined(__IOS__) && !defined(__ANDROID__) && !defined(__UNITY_3D__) && !defined(__XCODE__) // const ip_addr_t ip_addr_any = { IPADDR_ANY }; @@ -109,23 +101,11 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) struct eth_hdr *ethhdr; ethhdr = (struct eth_hdr *)buf; - ZeroTier::MAC src_mac; ZeroTier::MAC dest_mac; src_mac.setTo(ethhdr->src.addr, 6); dest_mac.setTo(ethhdr->dest.addr, 6); - DEBUG_ERROR("netif = %p", netif); - DEBUG_ERROR("tap = %p", tap); - DEBUG_ERROR("tap->_handler = %p", tap->_handler); - DEBUG_ERROR("tap->_arg = %p", tap->_arg); - DEBUG_ERROR("ethhdr = %p", ethhdr); - DEBUG_ERROR("tap->_nwid = %p", tap->_nwid); - //DEBUG_ERROR("src_mac = %p", (void*)src_mac); - //DEBUG_ERROR("dest_mac = %p", (void*)dest_mac); - DEBUG_ERROR("ethhdr->type = %p", ethhdr->type); - DEBUG_ERROR("buf = %p", buf); - tap->_handler(tap->_arg,tap->_nwid,src_mac,dest_mac, Utils::ntoh((uint16_t)ethhdr->type),0,buf + sizeof(struct eth_hdr),totalLength - sizeof(struct eth_hdr)); return ERR_OK; @@ -191,12 +171,6 @@ bool NetconEthernetTap::enabled() const return _enabled; } -#define IP6_ADDR2(ipaddr, a,b,c,d,e,f,g,h) do { (ipaddr)->addr[0] = Utils::hton((u32_t)((a & 0xffff) << 16) | (b & 0xffff)); \ - (ipaddr)->addr[1] = Utils::hton(((c & 0xffff) << 16) | (d & 0xffff)); \ - (ipaddr)->addr[2] = Utils::hton(((e & 0xffff) << 16) | (f & 0xffff)); \ - (ipaddr)->addr[3] = Utils::hton(((g & 0xffff) << 16) | (h & 0xffff)); } while(0) - - bool NetconEthernetTap::addIp(const InetAddress &ip) { DEBUG_INFO("local_addr=%s", ip.toString().c_str()); @@ -209,7 +183,7 @@ bool NetconEthernetTap::addIp(const InetAddress &ip) if (ip.isV4()) { DEBUG_INFO("IPV4"); // Set IP - static ip_addr_t ipaddr, netmask, gw; + static ip4_addr_t ipaddr, netmask, gw; IP4_ADDR(&gw,127,0,0,1); ipaddr.addr = *((u32_t *)ip.rawIpData()); netmask.addr = *((u32_t *)ip.netmask().rawIpData()); @@ -235,23 +209,24 @@ bool NetconEthernetTap::addIp(const InetAddress &ip) DEBUG_INFO("IPV6"); static ip6_addr_t addr6; IP6_ADDR2(&addr6, 0xfd56, 0x5799, 0xd8f6, 0x1238, 0x8c99, 0x93b4, 0x9d8e, 0x24f6); - ip6_addr_copy(ip_2_ip6(interface6.ip6_addr[1]), addr6); - // interface.flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; + interface6.mtu = _mtu; interface6.name[0] = 't'; interface6.name[1] = 'p'; interface6.hwaddr_len = 6; interface6.linkoutput = low_level_output; - interface6.ip6_autoconfig_enabled = 1; + _mac.copyTo(interface6.hwaddr, interface6.hwaddr_len); lwipstack->__netif_create_ip6_linklocal_address(&interface6, 1); lwipstack->__netif_add(&interface6, NULL, tapif_init, lwipstack->_ethernet_input); - netif_ip6_addr_set_state(&interface6, 1, IP6_ADDR_TENTATIVE); lwipstack->__netif_set_default(&interface6); - interface6.output_ip6 = lwipstack->_ethip6_output; lwipstack->__netif_set_up(&interface6); + + netif_ip6_addr_set_state(&interface6, 1, IP6_ADDR_TENTATIVE); ip6_addr_copy(ip_2_ip6(interface6.ip6_addr[1]), addr6); + + interface6.output_ip6 = lwipstack->_ethip6_output; interface6.state = this; interface6.flags = NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; } @@ -284,78 +259,35 @@ void NetconEthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType struct pbuf *p,*q; if (!_enabled) return; - - //#if defined(LWIP_IPV6) - DEBUG_EXTRA("IPV6"); - DEBUG_EXTRA("sizeof(struct eth_hdr) = %d", sizeof(struct eth_hdr)); - struct eth_hdr ethhdr; - from.copyTo(ethhdr.src.addr, 6); - to.copyTo(ethhdr.dest.addr, 6); - - ethhdr.type = Utils::hton((uint16_t)etherType); - p = lwipstack->__pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_POOL); - - if (p != NULL) { - const char *dataptr = reinterpret_cast(data); - // First pbuf gets ethernet header at start - q = p; - if (q->len < sizeof(ethhdr)) { - DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header"); - return; - } - int v = 6; - memcpy(ðhdr, &v, 1); - 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; - } - } - else { - DEBUG_ERROR("dropped packet: no pbufs available"); + DEBUG_EXTRA("IPV6"); + struct eth_hdr ethhdr; + from.copyTo(ethhdr.src.addr, 6); + to.copyTo(ethhdr.dest.addr, 6); + ethhdr.type = Utils::hton((uint16_t)etherType); + + p = lwipstack->__pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_POOL); + if (p != NULL) { + const char *dataptr = reinterpret_cast(data); + // First pbuf gets ethernet header at start + q = p; + if (q->len < sizeof(ethhdr)) { + DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header"); return; } + memcpy(q->payload,ðhdr,sizeof(ethhdr)); + memcpy((char*)q->payload + sizeof(ethhdr),dataptr,q->len - sizeof(ethhdr)); + dataptr += q->len - sizeof(ethhdr); - // IPV4 - /* - #elif defined(LWIP_IPV4) - DEBUG_EXTRA("IPV4"); - struct eth_hdr ethhdr; - from.copyTo(ethhdr.src.addr, 6); - to.copyTo(ethhdr.dest.addr, 6); - ethhdr.type = Utils::hton((uint16_t)etherType); - - // We allocate a pbuf chain of pbufs from the pool. - p = lwipstack->__pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_POOL); - - if (p != NULL) { - const char *dataptr = reinterpret_cast(data); - // First pbuf gets ethernet header at start - q = p; - if (q->len < sizeof(ethhdr)) { - DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header"); - return; - } - 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; - } - } - else { - DEBUG_ERROR("dropped packet: no pbufs available"); - return; + // Remaining pbufs (if any) get rest of data + while ((q = q->next)) { + memcpy(q->payload,dataptr,q->len); + dataptr += q->len; } - #endif - */ + } + else { + DEBUG_ERROR("dropped packet: no pbufs available"); + return; + } { if(interface6.input(p, &interface6) != ERR_OK) { DEBUG_ERROR("error while RX of packet (netif->input)"); diff --git a/src/SDK_Utils.hpp b/src/SDK_Utils.hpp new file mode 100644 index 0000000..6fc6020 --- /dev/null +++ b/src/SDK_Utils.hpp @@ -0,0 +1,33 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + + +#define IP6_ADDR2(ipaddr, a,b,c,d,e,f,g,h) do { (ipaddr)->addr[0] = Utils::hton((u32_t)((a & 0xffff) << 16) | (b & 0xffff)); \ + (ipaddr)->addr[1] = Utils::hton(((c & 0xffff) << 16) | (d & 0xffff)); \ + (ipaddr)->addr[2] = Utils::hton(((e & 0xffff) << 16) | (f & 0xffff)); \ + (ipaddr)->addr[3] = Utils::hton(((g & 0xffff) << 16) | (h & 0xffff)); } while(0) +