diff --git a/CHANGES b/CHANGES index c832af2..b3c3fc0 100644 --- a/CHANGES +++ b/CHANGES @@ -252,4 +252,8 @@ Alexey Khromov (zx@zxalexis.ru) + New option: emsi_send_tz - to send TZUTC EMSI-handshake part. 0.25.1 - + Added testing script for PSTN comms (tests folder). \ No newline at end of file + + Added testing script for PSTN comms (tests folder). + +0.25.2 + + Adopted for outgoing IPv6 communication + diff --git a/source/.version b/source/.version index af2dabf..166c9e2 100644 --- a/source/.version +++ b/source/.version @@ -1 +1 @@ -0.25.1 +0.25.2 diff --git a/source/bforce/io_tcpip.c b/source/bforce/io_tcpip.c index 36c5f55..e4f38f7 100644 --- a/source/bforce/io_tcpip.c +++ b/source/bforce/io_tcpip.c @@ -19,29 +19,50 @@ #define DEFAULT_PORT 60179 /* Birthday .. mother fucker :) */ +struct addrinfo *ai = NULL; + static RETSIGTYPE tcpip_interrupt(int sig) { tty_abort = TRUE; - log("terminating on signal %d", sig); + (void)log("terminating on signal %d", sig); } static RETSIGTYPE tcpip_brokenpipe(int sig) { tty_abort = TRUE; if( tty_online ) - log("connection closed"); + (void)log("connection closed"); else - log("terminating on signal %d", sig); + (void)log("terminating on signal %d", sig); } -static int tcpip_connect2(struct sockaddr_in server) +static int tcpip_connect2(struct addrinfo *ai) { - int fd; - - DEB((D_INFO, "tcpip_connect2: trying \"%s\" at port %d", - inet_ntoa(server.sin_addr), (int)ntohs(server.sin_port))); - - if( (fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) + int fd = -1; + char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; + + struct addrinfo *rai; + + for (rai = ai; rai != NULL; rai = rai->ai_next) + { + if (getnameinfo(rai->ai_addr, rai->ai_addrlen, hbuf, sizeof(hbuf), sbuf, + sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) + DEB((D_INFO, "tcpip_connect2: trying host=%s, serv=%s", hbuf, sbuf)); + + fd = socket (rai->ai_family, rai->ai_socktype, rai->ai_protocol); + + if ( fd == -1 ) + { + DEB((D_INFO, "tcpip_connect2: socket error")); + continue; + } + else break; + + hbuf[0]='\0'; + sbuf[0]='\0'; + } + DEB((D_INFO, "tcpip_connect2: socket success: %d", fd)); + if (fd < 0 ) { logerr("can't create socket"); return(1); @@ -84,9 +105,9 @@ static int tcpip_connect2(struct sockaddr_in server) clearerr(stdout); clearerr(stderr); - if( connect(0, (struct sockaddr*)&server, sizeof(server)) == -1 ) + if( connect(0, rai->ai_addr, rai->ai_addrlen) == -1 ) { - logerr("can't connect to %s", inet_ntoa(server.sin_addr)); + logerr("can't connect to %s", hbuf); close(0); close(1); close(2); @@ -99,8 +120,7 @@ static int tcpip_connect2(struct sockaddr_in server) return 1; } - log("TCP/IP connect to %s on port %d", - inet_ntoa(server.sin_addr), (int)ntohs(server.sin_port)); + (void)log("TCP/IP connect success to %s on service %s", hbuf, sbuf); return(0); } @@ -108,14 +128,23 @@ static int tcpip_connect2(struct sockaddr_in server) int tcpip_connect(const char *hostname, e_tcpmode tcpmode) { int rc = 0; - struct hostent *he = NULL; - struct servent *se = NULL; - struct sockaddr_in server; + //struct hostent *he = NULL; + //struct servent *se = NULL; + //struct sockaddr_in server; + //struct sockaddr_storage server; + + struct addrinfo *aisave = NULL; + struct addrinfo aihints; + int nameres = 0; + + char *host = xstrcpy(hostname); char *p = strrchr(host, ':'); const char *port = NULL; - - server.sin_family = AF_INET; + + + // AF_INET - only IPv4 + //server.sin_family = AF_INET; if( p ) { *p++ = '\0'; port = p; } @@ -125,16 +154,32 @@ int tcpip_connect(const char *hostname, e_tcpmode tcpmode) port = "telnet"; else /* Can not rely on /etc/services - it is not well-known port */ port = "60179"; - + + // Do not need it + /* if( ISDEC(port) ) server.sin_port = htons(atoi(port)); else if( (se = getservbyname(port, "tcp")) ) server.sin_port = se->s_port; else { log("invalid port or service name \"%s\"", port); rc = 1; } + */ + //if( rc == 0 ) + //{ + DEB((D_INFO, "tcpip_connect: port is %s", port)); + memset( &aihints, 0, sizeof( aihints) ); + aihints.ai_family = AF_UNSPEC; + //aihints.ai_socktype = SOCK_STREAM; + aihints.ai_protocol = IPPROTO_TCP; - if( rc == 0 ) + nameres = getaddrinfo ( host, port, &aihints, &ai ); + if ( nameres != 0 ) { + rc = 1; + log("Resolver error for host %s, port %s: \"%s\".", host, port, gai_strerror(nameres)); + } + // GetHostByName works with IPv4 only and *deprecated* + /* if( (he = gethostbyname(host)) ) { memcpy(&server.sin_addr, he->h_addr, he->h_length); @@ -159,12 +204,19 @@ int tcpip_connect(const char *hostname, e_tcpmode tcpmode) log("unknown error while resolving host \"%s\"", host); break; } - } - } + } */ + //} if( host ) { free(host); host = NULL; } + DEB((D_INFO, "tcpip_connect: resolver got result!")); + aisave = ai; + + if (rc == 0 ) + rc = tcpip_connect2(ai); + + freeaddrinfo( aisave ); - return rc ? rc : tcpip_connect2(server); + return rc; } int tcpip_init(void) diff --git a/tests/mktests.sh b/tests/mktests.sh index 5efe55b..5566609 100755 --- a/tests/mktests.sh +++ b/tests/mktests.sh @@ -28,6 +28,8 @@ function testcomm() { BFCFGA=${CURDIR}/etc/bforceA.conf BFCFGB=${CURDIR}/etc/bforceB.conf + # Works for Linux + BFCONFIG=${BFCFGA} BFCONFIG=${BFCFGA} ${BFBIN} -o 99:1/2 > ${CURDIR}/bforceAtoB < ${CURDIR}/bforceBtoA & # @@ -35,6 +37,9 @@ function testcomm() { BFCONFIG=${BFCFGB} BFCONFIG=${BFCFGB} ${BFBIN} -S"CONNECT 9600" auto < ${CURDIR}/bforceAtoB > ${CURDIR}/bforceBtoA + # For [Free]BSD it need to be replaced - pipes are bidirectional: + # ./ping <&1 | ./pong >&0 + rm ${CURDIR}/{bforceAtoB,bforceBtoA} ## WE MUST CHECK THAT INBOUND ARE FULL!!! ## @@ -88,6 +93,8 @@ else echo -n "--> Running Hydra test..." testcomm + # TODO: make binkd test over netcat possibly + fi