From a8b923f0033cd1195d33d566c1d499080258b93b Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Wed, 21 Nov 2012 08:48:33 +0100 Subject: [PATCH] Bring back generation of src DGRAM socket name v2 Implementation of previously deleted automatic generation of path for temporary source Unix DATAGRAM socket. This feature is needed in case user didn't specified the path for source socket. Patch also brings back initial comment in ncat.xml and test into ncat-test.pl Several fixes in Nsock library. --- ncat/config.h.in | 3 +++ ncat/configure.ac | 9 +++++++ ncat/docs/ncat.xml | 7 ++++-- ncat/ncat_connect.c | 64 ++++++++++++++++++++++++++++++++++++----------- ncat/test/ncat-test.pl | 13 ++++++++++ nsock/src/nsock_connect.c | 27 ++++++++++---------- nsock/src/nsock_core.c | 3 ++- 7 files changed, 96 insertions(+), 30 deletions(-) diff --git a/ncat/config.h.in b/ncat/config.h.in index 3ef265e..2d29af8 100644 --- a/ncat/config.h.in +++ b/ncat/config.h.in @@ -151,3 +151,6 @@ /* Define to rpl_realloc if the replacement function should be used. */ #undef realloc + +/* Directory for temporary source Datagram UNIX sockets. */ +#undef TMP_UNIX_SOCK_DIR diff --git a/ncat/configure.ac b/ncat/configure.ac index 8ee523c..37617aa 100644 --- a/ncat/configure.ac +++ b/ncat/configure.ac @@ -196,6 +196,15 @@ AC_SUBST(PCAP_CLEAN) AC_SUBST(PCAP_DIST_CLEAN) AC_SUBST(PCAP_LIBS) +# Default path for temporary source Datagram UNIX sockets +AC_ARG_VAR([TMP_UNIX_SOCK_DIR], + [Set full path to directory where Ncat will generate temporary source sockets when using Datagram UNIX sockets (default: NOT set)]) +if test -n "$TMP_UNIX_SOCK_DIR"; then + AC_DEFINE_UNQUOTED([TMP_UNIX_SOCK_DIR], + ["$TMP_UNIX_SOCK_DIR"], + [Directory for temporary source Datagram UNIX sockets.]) +fi + # Needed on AIX. AC_CHECK_LIB(odm, odm_initialize) diff --git a/ncat/docs/ncat.xml b/ncat/docs/ncat.xml index fd8cd83..7ecb0d6 100644 --- a/ncat/docs/ncat.xml +++ b/ncat/docs/ncat.xml @@ -767,8 +767,11 @@ Both stream and datagram domain sockets are supported. Use on its own for stream sockets, or combine it with for datagram sockets. - Datagram sockets require the use of the - option to specify a source socket to connect from. + Datagram sockets require a source socket to connect from. By + default, a source socket with a random filename will be created as + needed, and deleted when the program ends. Use the + with a path to use a source socket with a + specific name. diff --git a/ncat/ncat_connect.c b/ncat/ncat_connect.c index 82cbf8d..3525461 100644 --- a/ncat/ncat_connect.c +++ b/ncat/ncat_connect.c @@ -481,6 +481,9 @@ int ncat_connect(void) { nsock_pool mypool; int rc; +#if HAVE_SYS_UN_H + int tmp_unixsock_created = 0; +#endif /* Unless explicitely asked not to do so, ncat uses the * fallback nsock engine to maximize compatibility between @@ -518,11 +521,27 @@ int ncat_connect(void) /* For DGRAM UNIX socket we have to use source socket */ if (o.af == AF_UNIX && o.udp) { - if (srcaddr.storage.ss_family != AF_UNIX) { - bye("A source socket filename (--source) is required when using\n" - "Unix domain sockets in --udp mode."); + if (srcaddr.storage.ss_family == AF_UNIX) { + nsi_set_localaddr(cs.sock_nsi, &srcaddr.storage, SUN_LEN((struct sockaddr_un *)&srcaddr.storage)); + } else { + char *tmp_name = NULL; + /* If no source socket was specified, we have to create temporary one. */ +#ifdef TMP_UNIX_SOCK_DIR + if ((tmp_name = tempnam(TMP_UNIX_SOCK_DIR, "ncat.")) == NULL) +#else + if ((tmp_name = tempnam(NULL, "ncat.")) == NULL) +#endif + bye("Failed to create name for temporary DGRAM source Unix domain socket (tempnam)."); + + srcaddr.un.sun_family = AF_UNIX; + strncpy(srcaddr.un.sun_path, tmp_name, sizeof(srcaddr.un.sun_path)); + free (tmp_name); + + nsi_set_localaddr(cs.sock_nsi, &srcaddr.storage, SUN_LEN((struct sockaddr_un *)&srcaddr.storage)); } - nsi_set_localaddr(cs.sock_nsi, &srcaddr.storage, SUN_LEN((struct sockaddr_un *)&srcaddr.storage)); + + if (o.verbose) + loguser("[%s] used as source DGRAM Unix domain socket.\n", srcaddr.un.sun_path); } else #endif @@ -544,7 +563,7 @@ int ncat_connect(void) #if HAVE_SYS_UN_H if (o.af == AF_UNIX) { if (o.udp) { - nsock_connect_unixsock_datagram(mypool, cs.sock_nsi, connect_handler, NULL, + nsock_connect_unixsock_datagram(mypool, cs.sock_nsi, connect_handler, (void*)&tmp_unixsock_created, &targetss.sockaddr, SUN_LEN((struct sockaddr_un *)&targetss.sockaddr)); } else { @@ -675,6 +694,15 @@ int ncat_connect(void) nsi_get_read_count(cs.sock_nsi), time); } +#if HAVE_SYS_UN_H + if (o.af == AF_UNIX && o.udp && tmp_unixsock_created) { + if (o.verbose) + loguser("Deleting source DGRAM Unix domain socket. [%s]\n", srcaddr.un.sun_path); + + unlink(srcaddr.un.sun_path); + } +#endif + nsp_delete(mypool); return rc == NSOCK_LOOP_ERROR ? 1 : 0; @@ -689,10 +717,12 @@ static void connect_handler(nsock_pool nsp, nsock_event evt, void *data) if (status == NSE_STATUS_ERROR) { loguser("%s.\n", socket_strerror(nse_errorcode(evt))); - exit(1); + nsock_loop_quit(nsp); + return; } else if (status == NSE_STATUS_TIMEOUT) { loguser("%s.\n", socket_strerror(ETIMEDOUT)); - exit(1); + nsock_loop_quit(nsp); + return; } else { assert(status == NSE_STATUS_SUCCESS); } @@ -770,10 +800,12 @@ static void read_stdin_handler(nsock_pool nsp, nsock_event evt, void *data) return; } else if (status == NSE_STATUS_ERROR) { loguser("%s.\n", socket_strerror(nse_errorcode(evt))); - exit(1); + nsock_loop_quit(nsp); + return; } else if (status == NSE_STATUS_TIMEOUT) { loguser("%s.\n", socket_strerror(ETIMEDOUT)); - exit(1); + nsock_loop_quit(nsp); + return; } else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) { return; } else { @@ -814,10 +846,12 @@ static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data) return; } else if (status == NSE_STATUS_ERROR) { loguser("%s.\n", socket_strerror(nse_errorcode(evt))); - exit(1); + nsock_loop_quit(nsp); + return; } else if (status == NSE_STATUS_TIMEOUT) { loguser("%s.\n", socket_strerror(ETIMEDOUT)); - exit(1); + nsock_loop_quit(nsp); + return; } else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) { return; } else { @@ -850,10 +884,12 @@ static void write_socket_handler(nsock_pool nsp, nsock_event evt, void *data) if (status == NSE_STATUS_ERROR) { loguser("%s.\n", socket_strerror(nse_errorcode(evt))); - exit(1); + nsock_loop_quit(nsp); + return; } else if (status == NSE_STATUS_TIMEOUT) { loguser("%s.\n", socket_strerror(ETIMEDOUT)); - exit(1); + nsock_loop_quit(nsp); + return; } else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) { return; } else { @@ -879,7 +915,7 @@ static void idle_timer_handler(nsock_pool nsp, nsock_event evt, void *data) loguser("Idle timeout expired (%d ms).\n", o.idletimeout); - exit(1); + nsock_loop_quit(nsp); } static void refresh_idle_timer(nsock_pool nsp) diff --git a/ncat/test/ncat-test.pl b/ncat/test/ncat-test.pl index 25f1e74..2697041 100755 --- a/ncat/test/ncat-test.pl +++ b/ncat/test/ncat-test.pl @@ -548,6 +548,19 @@ sub { kill_children; unlink($UNIXSOCK); +($s_pid, $s_out, $s_in) = ncat("-l", "-U", "--udp", $UNIXSOCK); +test "Server UNIX socket listen on $UNIXSOCK --udp (DGRAM)", +sub { + my $resp; + + unlink($UNIXSOCK); + my ($c_pid, $c_out, $c_in) = ncat("-U", "--udp", $UNIXSOCK); + syswrite($c_in, "abc\n"); + $resp = timeout_read($s_out); + $resp eq "abc\n" or die "Server got \"$resp\", not \"abc\\n\" from client"; +}; +kill_children; +unlink($UNIXSOCK); server_client_test "Connect success exit code", [], ["--send-only"], sub { diff --git a/nsock/src/nsock_connect.c b/nsock/src/nsock_connect.c index dfe0799..373b060 100644 --- a/nsock/src/nsock_connect.c +++ b/nsock/src/nsock_connect.c @@ -84,17 +84,16 @@ static int nsock_make_socket(mspool *ms, msiod *iod, int family, int type, int p setsockopt(iod->sd, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)); if (bind(iod->sd, (struct sockaddr *)&iod->local, (int) iod->locallen) == -1) { - if (ms->tracelevel > 0) { - const char *addrstr = NULL; #if HAVE_SYS_UN_H - if (iod->local.ss_family == AF_UNIX) - addrstr = get_unixsock_path(&iod->local); - else + if (iod->local.ss_family == AF_UNIX) { + nsock_trace(ms, "Bind to %s failed (IOD #%li)", + get_unixsock_path(&iod->local), iod->id); + return -1; + } #endif - addrstr = inet_ntop_ez(&iod->local, iod->locallen); - - nsock_trace(ms, "Bind to %s failed (IOD #%li)", addrstr, iod->id); - } + if (ms->tracelevel > 0) + nsock_trace(ms, "Bind to %s failed (IOD #%li)", + inet_ntop_ez(&iod->local, iod->locallen), iod->id); } } if (iod->ipoptslen && family == AF_INET) { @@ -151,13 +150,15 @@ void nsock_connect_internal(mspool *ms, msevent *nse, int type, int proto, struc nse->status = NSE_STATUS_ERROR; nse->errnum = socket_errno(); } else { +#if HAVE_SYS_UN_H + if (ss->ss_family == AF_UNIX) { + if (type == SOCK_DGRAM && nse->userdata) + *(int *)nse->userdata = 1; + } else +#endif if (ss->ss_family == AF_INET) { sin->sin_port = htons(port); -#if HAVE_SYS_UN_H - } else if (ss->ss_family == AF_INET6) { -#else } else { -#endif assert(ss->ss_family == AF_INET6); #if HAVE_IPV6 sin6->sin6_port = htons(port); diff --git a/nsock/src/nsock_core.c b/nsock/src/nsock_core.c index ff40d1b..39ab888 100644 --- a/nsock/src/nsock_core.c +++ b/nsock/src/nsock_core.c @@ -570,7 +570,8 @@ void handle_write_result(mspool *ms, msevent *nse, enum nse_status status) { } } - nse->iod->write_count+= res; + if (res >= 0) + nse->iod->write_count += res; } if (nse->event_done && nse->iod->sd != -1) { -- 1.7.11.7