diff --git a/libretroshare/src/pqi/Makefile b/libretroshare/src/pqi/Makefile index 60cdbbbf7..e185bfbfc 100644 --- a/libretroshare/src/pqi/Makefile +++ b/libretroshare/src/pqi/Makefile @@ -29,19 +29,22 @@ RSOBJ = $(BASE_OBJ) $(LOOP_OBJ) \ $(UDP_OBJ) \ $(GRP_OBJ) -TESTOBJ = dht_test.o conn_test.o +TESTOBJ = net_test.o dht_test.o conn_test.o -TESTS = dht_test conn_test +TESTS = net_test dht_test conn_test all: librs tests -dht_test: dht_test.o librs +dht_test: dht_test.o $(CC) $(CFLAGS) -o dht_test dht_test.o $(LIBS) -conn_test: conn_test.o librs +conn_test: conn_test.o $(CC) $(CFLAGS) -o conn_test conn_test.o $(LIBS) +net_test: net_test.o + $(CC) $(CFLAGS) -o net_test net_test.o $(LIBS) + ############################################################### include $(RS_TOP_DIR)/scripts/rules.mk ############################################################### diff --git a/libretroshare/src/pqi/net_test.cc b/libretroshare/src/pqi/net_test.cc new file mode 100644 index 000000000..4634d6549 --- /dev/null +++ b/libretroshare/src/pqi/net_test.cc @@ -0,0 +1,264 @@ +/* + * libretroshare/src/pqi net_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * NETWORKING Test to check Big/Little Endian behaviour + * as well as socket behaviour + * + */ + +#include "util/rsnet.h" +#include "pqi/pqinetwork.h" +#include +#include + + +bool test_byte_manipulation(); +bool test_address_manipulation(); +bool test_address_listen(); + +int main(int argc, char **argv) +{ + + test_byte_manipulation(); + test_address_manipulation(); + test_address_listen(); + return 1; +} + + /* test 1: byte manipulation */ +bool test_byte_manipulation() +{ + uint64_t num1 = 0x0000000000000000ffULL; /* 255 */ + uint64_t num2 = 0x00000000000000ff00ULL; /* */ + + uint64_t n_num1 = htonll(num1); + uint64_t n_num2 = htonll(num2); + + uint64_t h_num1 = ntohll(n_num1); + uint64_t h_num2 = ntohll(n_num2); + + std::ostringstream out; + out << std::hex; + out << "num1: " << num1 << " netOrder: " << n_num1 << " hostOrder: " << h_num1 << std::endl; + out << "num2: " << num2 << " netOrder: " << n_num2 << " hostOrder: " << h_num2 << std::endl; + + std::cerr << out.str(); + + return true; +} + +const char * loopback_addrstr = "127.0.0.1"; +const char * localnet1_addrstr = "192.168.0.1"; +const char * localnet2_addrstr = "10.0.0.1"; +const char * localnet3_addrstr = "10.5.63.78"; +const char * localnet4_addrstr = "192.168.74.91"; + + /* test 2: address manipulation */ +bool test_address_manipulation() +{ + struct sockaddr_in loopback_addr; + struct sockaddr_in localnet1_addr; + struct sockaddr_in localnet2_addr; + struct sockaddr_in localnet3_addr; + struct sockaddr_in localnet4_addr; + + /* setup some addresses */ + inet_aton(loopback_addrstr, &(loopback_addr.sin_addr)); + inet_aton(localnet1_addrstr, &(localnet1_addr.sin_addr)); + inet_aton(localnet2_addrstr, &(localnet2_addr.sin_addr)); + inet_aton(localnet3_addrstr, &(localnet3_addr.sin_addr)); + inet_aton(localnet4_addrstr, &(localnet4_addr.sin_addr)); + + + std::cerr << "Loopback Addr" << inet_ntoa(loopback_addr.sin_addr); + std::cerr << std::endl; + + std::cerr << "Localnet1 Addr" << inet_ntoa(localnet1_addr.sin_addr); + std::cerr << std::endl; + std::cerr << "Localnet2 Addr" << inet_ntoa(localnet2_addr.sin_addr); + std::cerr << std::endl; + std::cerr << "Localnet3 Addr" << inet_ntoa(localnet3_addr.sin_addr); + std::cerr << std::endl; + std::cerr << "Localnet4 Addr" << inet_ntoa(localnet4_addr.sin_addr); + std::cerr << std::endl; + std::cerr << std::endl; + + std::cerr << "Test 1a - networks"; + std::cerr << std::endl; + + struct sockaddr_in addr_ans, addr1, addr2; + + inet_aton("127.0.0.0", &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = inet_netof(loopback_addr.sin_addr); + addr2.sin_addr.s_addr = inet_network(loopback_addrstr); + + std::cerr << "Loopback Net(expected): 127.0.0.0 ->" << inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + inet_aton("192.168.0.0", &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = inet_netof(localnet1_addr.sin_addr); + addr2.sin_addr.s_addr = inet_network(localnet1_addrstr); + + std::cerr << "Localnet1 Net(expected): 192.168.0.0 ->" << inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + inet_aton("10.0.0.0", &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = inet_netof(localnet2_addr.sin_addr); + addr2.sin_addr.s_addr = inet_network(localnet2_addrstr); + + std::cerr << "Localnet2 Net(expected): 10.0.0.0 ->" << inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + + inet_aton("10.0.0.0", &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = inet_netof(localnet3_addr.sin_addr); + addr2.sin_addr.s_addr = inet_network(localnet3_addrstr); + + std::cerr << "Localnet3 Net(expected): 10.0.0.0 ->" << inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + + inet_aton("192.168.0.0", &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = inet_netof(localnet4_addr.sin_addr); + addr2.sin_addr.s_addr = inet_network(localnet4_addrstr); + + std::cerr << "Localnet4 Net(expected): 192.168.0.0 -> " << inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + return true; +} + + + +#if 0 + +std::ostream &showSocketError(std::ostream &out); + +std::string socket_errorType(int err); +int sockaddr_cmp(struct sockaddr_in &addr1, struct sockaddr_in &addr2 ); +int inaddr_cmp(struct sockaddr_in addr1, struct sockaddr_in addr1 ); +int inaddr_cmp(struct sockaddr_in addr1, unsigned long); + +std::list getLocalInterfaces(); // returns all possible addrs. +bool isExternalNet(struct in_addr *addr); // if Valid & is not Private or Loopback. +bool isPrivateNet(struct in_addr *addr); // if inside 10.0.0.0 or + // other then firewalled. +bool isLoopbackNet(struct in_addr *addr); +bool sameNet(struct in_addr *addr, struct in_addr *addr2); +bool isValidNet(struct in_addr *addr); + + // checks (addr1 & 255.255.255.0) == (addr2 & 255.255.255.0) +bool isSameSubnet(struct in_addr *addr1, struct in_addr *addr2); + + +struct in_addr getPreferredInterface(); // returns best addr. + +in_addr_t pqi_inet_netof(struct in_addr addr); // our implementation. + +bool LookupDNSAddr(std::string name, struct sockaddr_in &addr); + +/* universal socket interface */ + +int unix_close(int sockfd); +int unix_socket(int domain, int type, int protocol); +int unix_fcntl_nonblock(int sockfd); +int unix_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); +int unix_getsockopt_error(int sockfd, int *err); + +#endif + + +bool test_bind_addr(struct sockaddr_in addr); + +bool test_address_listen() +{ + struct sockaddr_in addr1, addr2, addr3; + + sockaddr_clear(&addr1); + addr1.sin_family = AF_INET; + inet_aton(loopback_addrstr, &(addr1.sin_addr)); + addr1.sin_port = htons(12345); + + sockaddr_clear(&addr2); + addr2.sin_family = AF_INET; + addr2.sin_addr = getPreferredInterface(); // returns best addr. + addr2.sin_port = htons(13245); + + sockaddr_clear(&addr3); + addr3.sin_family = AF_INET; + addr3.sin_addr = getPreferredInterface(); // returns best addr. + addr3.sin_port = htons(23451); + + /* test bind to loopback, and preferred interfaces */ + test_bind_addr(addr1); + test_bind_addr(addr2); + test_bind_addr(addr3); + + return true; +} + +bool test_bind_addr(struct sockaddr_in addr) +{ + + int err; + + std::cerr << "test_bind_addr()"; + std::cerr << std::endl; + + std::cerr << "\tAddress Family: " << (int) addr.sin_family; + std::cerr << std::endl; + std::cerr << "\tAddress: " << inet_ntoa(addr.sin_addr); + std::cerr << std::endl; + std::cerr << "\tPort: " << ntohs(addr.sin_port); + std::cerr << std::endl; + + int sockfd = unix_socket(PF_INET, SOCK_STREAM, 0); + + if (0 != (err = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)))) + { + std::cerr << " Failed to Bind to Local Address!" << std::endl; + showSocketError(std::cerr); + + return false; + } + + std::cerr << " Successfully Bound Socket to Address" << std::endl; + unix_close(sockfd); + + return true; +} + + diff --git a/libretroshare/src/pqi/p3connmgr.cc b/libretroshare/src/pqi/p3connmgr.cc index 5188fa036..58effa341 100644 --- a/libretroshare/src/pqi/p3connmgr.cc +++ b/libretroshare/src/pqi/p3connmgr.cc @@ -66,22 +66,15 @@ p3ConnectMgr::p3ConnectMgr(p3AuthMgr *am) peerConnectAddress::peerConnectAddress() :type(0), ts(0) { - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = 0; - addr.sin_port = 0; + sockaddr_clear(&addr); } peerAddrInfo::peerAddrInfo() :found(false), type(0), ts(0) { - laddr.sin_family = AF_INET; - laddr.sin_addr.s_addr = 0; - laddr.sin_port = 0; - - raddr.sin_family = AF_INET; - raddr.sin_addr.s_addr = 0; - raddr.sin_port = 0; + sockaddr_clear(&laddr); + sockaddr_clear(&raddr); } peerConnectState::peerConnectState() @@ -94,17 +87,9 @@ peerConnectState::peerConnectState() //lc_timestamp(0), lr_timestamp(0), //nc_timestamp(0), nc_timeintvl(0) { - lastaddr.sin_family = AF_INET; - lastaddr.sin_addr.s_addr = 0; - lastaddr.sin_port = 0; - - localaddr.sin_family = AF_INET; - localaddr.sin_addr.s_addr = 0; - localaddr.sin_port = 0; - - serveraddr.sin_family = AF_INET; - serveraddr.sin_addr.s_addr = 0; - serveraddr.sin_port = 0; + sockaddr_clear(&lastaddr); + sockaddr_clear(&localaddr); + sockaddr_clear(&serveraddr); return; } @@ -1698,6 +1683,9 @@ bool p3ConnectMgr::getDHTEnabled() bool p3ConnectMgr::checkNetAddress() { + std::cerr << "p3ConnectMgr::checkNetAddress()"; + std::cerr << std::endl; + std::list addrs = getLocalInterfaces(); std::list::iterator it; @@ -1706,8 +1694,13 @@ bool p3ConnectMgr::checkNetAddress() bool found = false; for(it = addrs.begin(); (!found) && (it != addrs.end()); it++) { + std::cerr << "p3ConnectMgr::checkNetAddress() Local Interface: " << *it; + std::cerr << std::endl; + if ((*it) == inet_ntoa(ownState.localaddr.sin_addr)) { + std::cerr << "p3ConnectMgr::checkNetAddress() Matches Existing Address! FOUND = true"; + std::cerr << std::endl; found = true; } } @@ -1720,6 +1713,11 @@ bool p3ConnectMgr::checkNetAddress() if (!found) { ownState.localaddr.sin_addr = getPreferredInterface(); + + std::cerr << "p3ConnectMgr::checkNetAddress() Local Address Not Found: Using Preferred Interface: "; + std::cerr << inet_ntoa(ownState.localaddr.sin_addr); + std::cerr << std::endl; + } if ((isPrivateNet(&(ownState.localaddr.sin_addr))) || (isLoopbackNet(&(ownState.localaddr.sin_addr)))) @@ -1754,6 +1752,11 @@ bool p3ConnectMgr::checkNetAddress() ownState.localaddr.sin_family = AF_INET; ownState.serveraddr.sin_family = AF_INET; ownState.lastaddr.sin_family = AF_INET; + + std::cerr << "p3ConnectMgr::checkNetAddress() Final Local Address: "; + std::cerr << inet_ntoa(ownState.localaddr.sin_addr); + std::cerr << ":" << ntohs(ownState.localaddr.sin_port); + std::cerr << std::endl; return 1; } diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc index 9809a17c7..5afbb9518 100644 --- a/libretroshare/src/pqi/pqinetwork.cc +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -46,6 +46,11 @@ int errno; #endif +void sockaddr_clear(struct sockaddr_in *addr) +{ + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; +} /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ @@ -142,8 +147,15 @@ std::list getLocalInterfaces() exit(1); } + if (!ifptr) + { + pqioutput(PQL_ALERT, pqinetzone, + "getLocalInterfaces(): ERROR if_nameindex == NULL"); + } + // loop through the interfaces. - for(; *(char *)ifptr != 0; ifptr++) + //for(; *(char *)ifptr != 0; ifptr++) + for(; ifptr->if_index != 0; ifptr++) { //copy in the interface name to look up address of strncpy(ifreq.ifr_name, ifptr->if_name, IF_NAMESIZE); @@ -860,3 +872,4 @@ int WinToUnixError(int error) #endif /******************* WINDOWS SPECIFIC PART ******************/ + diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h index a86f6cd0e..be988bf1c 100644 --- a/libretroshare/src/pqi/pqinetwork.h +++ b/libretroshare/src/pqi/pqinetwork.h @@ -97,6 +97,8 @@ extern int errno; /* Define extern errno, to duplicate unix behaviour */ #include #include +void sockaddr_clear(struct sockaddr_in *addr1); + // Same def - different functions... std::ostream &showSocketError(std::ostream &out); @@ -137,13 +139,7 @@ int unix_getsockopt_error(int sockfd, int *err); int WinToUnixError(int error); #endif -/***** From http://www.codeproject.com/KB/cpp/endianness.aspx -#define ntohll(x) (((int64_t)(ntohl((int32_t)((x << 32) >> 32))) << 32) | - (uint32_t) ntohl(((int32_t)(x >> 32)))) -#define htonll(x) ntohll(x) - -*****/ #endif diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc index bdb6d3963..5bbeba119 100644 --- a/libretroshare/src/pqi/pqissl.cc +++ b/libretroshare/src/pqi/pqissl.cc @@ -106,9 +106,7 @@ pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3AuthMgr *am, p3ConnectM { /* set address to zero */ - remote_addr.sin_addr.s_addr = 0; - remote_addr.sin_port = 0; - remote_addr.sin_family = AF_INET; + sockaddr_clear(&remote_addr); { std::ostringstream out; diff --git a/libretroshare/src/serialiser/rsbaseserial.cc b/libretroshare/src/serialiser/rsbaseserial.cc index 084e4bd10..9e38af5ba 100644 --- a/libretroshare/src/serialiser/rsbaseserial.cc +++ b/libretroshare/src/serialiser/rsbaseserial.cc @@ -123,8 +123,7 @@ bool getRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t *out) uint64_t netorder_num; memcpy(&netorder_num, buf, sizeof(uint64_t)); - //(*out) = ntohll(netorder_num); - (*out) = netorder_num; + (*out) = ntohll(netorder_num); (*offset) += 8; return true; } @@ -140,8 +139,7 @@ bool setRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t in) void *buf = (void *) &(((uint8_t *) data)[*offset]); /* convert the data to the right format */ - //uint64_t netorder_num = htonll(in); - uint64_t netorder_num = in; + uint64_t netorder_num = htonll(in); /* pack it in */ memcpy(buf, &netorder_num, sizeof(uint64_t)); diff --git a/libretroshare/src/util/Makefile b/libretroshare/src/util/Makefile index fe4187ff2..d86d9f3a3 100644 --- a/libretroshare/src/util/Makefile +++ b/libretroshare/src/util/Makefile @@ -7,7 +7,7 @@ RS_TOP_DIR = .. include $(RS_TOP_DIR)/scripts/config.mk ############################################################### -RSOBJ = rsthreads.o rsdir.o rsprint.o +RSOBJ = rsthreads.o rsdir.o rsprint.o rsnet.o TESTOBJ = dirtest.o dir2test.o diff --git a/libretroshare/src/util/rsnet.cc b/libretroshare/src/util/rsnet.cc new file mode 100644 index 000000000..ce9398ab6 --- /dev/null +++ b/libretroshare/src/util/rsnet.cc @@ -0,0 +1,55 @@ +/* + * libretroshare/src/util: rsnet.cc + * + * Universal Networking Header for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "util/rsnet.h" + +uint64_t ntohll(uint64_t x) +{ +#ifdef BYTE_ORDER + #if BYTE_ORDER == BIG_ENDIAN + return x; + #elif BYTE_ORDER == LITTLE_ENDIAN + + uint32_t top = (uint32_t) (x >> 32); + uint32_t bot = (uint32_t) (0x00000000ffffffffULL & x); + + uint64_t rev = ((uint64_t) ntohl(top)) | (((uint64_t) ntohl(bot)) << 32); + + return rev; + #else + #error "ENDIAN determination Failed" + #endif +#else + #error "ENDIAN determination Failed (BYTE_ORDER not defined)" +#endif + +} + +uint64_t htonll(uint64_t x) +{ + return ntohll(x); +} + + diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index bbef70c60..b94727b13 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -51,4 +51,8 @@ typedef uint32_t in_addr_t; #endif /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +/* 64 bit conversions */ +uint64_t ntohll(uint64_t x); +uint64_t htonll(uint64_t x); + #endif /* RS_UNIVERSAL_NETWORK_HEADER */