diff options
Diffstat (limited to 'src/libcharon/plugins/lookip')
-rw-r--r-- | src/libcharon/plugins/lookip/Makefile.am | 12 | ||||
-rw-r--r-- | src/libcharon/plugins/lookip/Makefile.in | 83 | ||||
-rw-r--r-- | src/libcharon/plugins/lookip/lookip.c | 89 | ||||
-rw-r--r-- | src/libcharon/plugins/lookip/lookip_listener.c | 21 | ||||
-rw-r--r-- | src/libcharon/plugins/lookip/lookip_listener.h | 7 | ||||
-rw-r--r-- | src/libcharon/plugins/lookip/lookip_msg.h | 6 | ||||
-rw-r--r-- | src/libcharon/plugins/lookip/lookip_plugin.c | 39 | ||||
-rw-r--r-- | src/libcharon/plugins/lookip/lookip_socket.c | 429 |
8 files changed, 392 insertions, 294 deletions
diff --git a/src/libcharon/plugins/lookip/Makefile.am b/src/libcharon/plugins/lookip/Makefile.am index 450995c9c..6d71c8c13 100644 --- a/src/libcharon/plugins/lookip/Makefile.am +++ b/src/libcharon/plugins/lookip/Makefile.am @@ -1,10 +1,12 @@ - -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon - -AM_CFLAGS = -rdynamic \ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" +AM_CFLAGS = \ + -rdynamic + if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-lookip.la else diff --git a/src/libcharon/plugins/lookip/Makefile.in b/src/libcharon/plugins/lookip/Makefile.in index 24eb31feb..630ec4a1c 100644 --- a/src/libcharon/plugins/lookip/Makefile.in +++ b/src/libcharon/plugins/lookip/Makefile.in @@ -64,7 +64,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/macros/with.m4 \ $(top_srcdir)/m4/macros/enable-disable.m4 \ $(top_srcdir)/m4/macros/add-plugin.m4 \ - $(top_srcdir)/configure.in + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -105,9 +105,13 @@ am_libstrongswan_lookip_la_OBJECTS = lookip_plugin.lo \ lookip_listener.lo lookip_socket.lo libstrongswan_lookip_la_OBJECTS = \ $(am_libstrongswan_lookip_la_OBJECTS) -libstrongswan_lookip_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libstrongswan_lookip_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +libstrongswan_lookip_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_lookip_la_LDFLAGS) \ + $(LDFLAGS) -o $@ @MONOLITHIC_FALSE@am_libstrongswan_lookip_la_rpath = -rpath \ @MONOLITHIC_FALSE@ $(plugindir) @MONOLITHIC_TRUE@am_libstrongswan_lookip_la_rpath = @@ -121,13 +125,26 @@ am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libstrongswan_lookip_la_SOURCES) $(lookip_SOURCES) DIST_SOURCES = $(libstrongswan_lookip_la_SOURCES) $(lookip_SOURCES) am__can_run_installinfo = \ @@ -141,6 +158,7 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -153,6 +171,8 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -168,6 +188,7 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +GENHTML = @GENHTML@ GPERF = @GPERF@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ @@ -176,6 +197,7 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ @@ -222,6 +244,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCKLIB = @SOCKLIB@ STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ @@ -250,6 +273,7 @@ charon_natt_port = @charon_natt_port@ charon_plugins = @charon_plugins@ charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -327,12 +351,15 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon - -AM_CFLAGS = -rdynamic \ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ -DIPSEC_PIDDIR=\"${piddir}\" +AM_CFLAGS = \ + -rdynamic + @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-lookip.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-lookip.la libstrongswan_lookip_la_SOURCES = lookip_plugin.h lookip_plugin.c \ @@ -417,7 +444,7 @@ clean-pluginLTLIBRARIES: rm -f "$${dir}/so_locations"; \ done libstrongswan-lookip.la: $(libstrongswan_lookip_la_OBJECTS) $(libstrongswan_lookip_la_DEPENDENCIES) $(EXTRA_libstrongswan_lookip_la_DEPENDENCIES) - $(libstrongswan_lookip_la_LINK) $(am_libstrongswan_lookip_la_rpath) $(libstrongswan_lookip_la_OBJECTS) $(libstrongswan_lookip_la_LIBADD) $(LIBS) + $(AM_V_CCLD)$(libstrongswan_lookip_la_LINK) $(am_libstrongswan_lookip_la_rpath) $(libstrongswan_lookip_la_OBJECTS) $(libstrongswan_lookip_la_LIBADD) $(LIBS) install-ipsecPROGRAMS: $(ipsec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \ @@ -466,7 +493,7 @@ clean-ipsecPROGRAMS: rm -f $$list lookip$(EXEEXT): $(lookip_OBJECTS) $(lookip_DEPENDENCIES) $(EXTRA_lookip_DEPENDENCIES) @rm -f lookip$(EXEEXT) - $(LINK) $(lookip_OBJECTS) $(lookip_LDADD) $(LIBS) + $(AM_V_CCLD)$(LINK) $(lookip_OBJECTS) $(lookip_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -480,25 +507,25 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lookip_socket.Plo@am__quote@ .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo diff --git a/src/libcharon/plugins/lookip/lookip.c b/src/libcharon/plugins/lookip/lookip.c index 9887a3a92..d473c7022 100644 --- a/src/libcharon/plugins/lookip/lookip.c +++ b/src/libcharon/plugins/lookip/lookip.c @@ -20,51 +20,112 @@ #include <unistd.h> #include <stddef.h> #include <stdio.h> +#include <stdlib.h> #include <errno.h> #include <getopt.h> +#include <arpa/inet.h> /** * Connect to the daemon, return FD */ static int make_connection() { - struct sockaddr_un addr; - int fd; + union { + struct sockaddr_un un; + struct sockaddr_in in; + struct sockaddr sa; + } addr; + int fd, len; - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, LOOKIP_SOCKET); + if (getenv("TCP_PORT")) + { + addr.in.sin_family = AF_INET; + addr.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.in.sin_port = htons(atoi(getenv("TCP_PORT"))); + len = sizeof(addr.in); + } + else + { + addr.un.sun_family = AF_UNIX; + strcpy(addr.un.sun_path, LOOKIP_SOCKET); - fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + len = offsetof(struct sockaddr_un, sun_path) + strlen(addr.un.sun_path); + } + fd = socket(addr.sa.sa_family, SOCK_STREAM, 0); if (fd < 0) { fprintf(stderr, "opening socket failed: %s\n", strerror(errno)); return -1; } - if (connect(fd, (struct sockaddr *)&addr, - offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path)) < 0) + if (connect(fd, &addr.sa, len) < 0) { - fprintf(stderr, "connecting to %s failed: %s\n", - LOOKIP_SOCKET, strerror(errno)); + fprintf(stderr, "connecting failed: %s\n", strerror(errno)); close(fd); return -1; } return fd; } +static int read_all(int fd, void *buf, size_t len, int flags) +{ + ssize_t ret, done = 0; + + while (done < len) + { + ret = recv(fd, buf, len - done, flags); + if (ret == -1 && errno == EINTR) + { /* interrupted, try again */ + continue; + } + if (ret == 0) + { + return 0; + } + if (ret < 0) + { + return -1; + } + done += ret; + buf += ret; + } + return len; +} + +static int write_all(int fd, void *buf, size_t len) +{ + ssize_t ret, done = 0; + + while (done < len) + { + ret = write(fd, buf, len - done); + if (ret == -1 && errno == EINTR) + { /* interrupted, try again */ + continue; + } + if (ret < 0) + { + return -1; + } + done += ret; + buf += ret; + } + return len; +} + /** * Send a request message */ static int send_request(int fd, int type, char *vip) { lookip_request_t req = { - .type = type, + .type = htonl(type), }; if (vip) { snprintf(req.vip, sizeof(req.vip), "%s", vip); } - if (send(fd, &req, sizeof(req), 0) != sizeof(req)) + if (write_all(fd, &req, sizeof(req)) != sizeof(req)) { fprintf(stderr, "writing to socket failed: %s\n", strerror(errno)); return 2; @@ -83,7 +144,7 @@ static int receive(int fd, int block, int loop) do { - res = recv(fd, &resp, sizeof(resp), block ? 0 : MSG_DONTWAIT); + res = read_all(fd, &resp, sizeof(resp), block ? 0 : MSG_DONTWAIT); if (res == 0) { /* closed by server */ return 0; @@ -97,7 +158,7 @@ static int receive(int fd, int block, int loop) fprintf(stderr, "reading from socket failed: %s\n", strerror(errno)); return 1; } - switch (resp.type) + switch (ntohl(resp.type)) { case LOOKIP_ENTRY: label = "lookup:"; @@ -120,7 +181,7 @@ static int receive(int fd, int block, int loop) resp.id[sizeof(resp.id) - 1] = '\0'; resp.name[sizeof(resp.name) - 1] = '\0'; - snprintf(name, sizeof(name), "%s[%u]", resp.name, resp.unique_id); + snprintf(name, sizeof(name), "%s[%u]", resp.name, ntohl(resp.unique_id)); printf("%-12s %16s %16s %20s %s\n", label, resp.vip, resp.ip, name, resp.id); } diff --git a/src/libcharon/plugins/lookip/lookip_listener.c b/src/libcharon/plugins/lookip/lookip_listener.c index caf336a2e..d5eab1f6c 100644 --- a/src/libcharon/plugins/lookip/lookip_listener.c +++ b/src/libcharon/plugins/lookip/lookip_listener.c @@ -290,6 +290,26 @@ METHOD(lookip_listener_t, add_listener, void, this->lock->unlock(this->lock); } +METHOD(lookip_listener_t, remove_listener, void, + private_lookip_listener_t *this, void *user) +{ + listener_entry_t *listener; + enumerator_t *enumerator; + + this->lock->write_lock(this->lock); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &listener)) + { + if (listener->user == user) + { + this->listeners->remove_at(this->listeners, enumerator); + free(listener); + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); +} + METHOD(lookip_listener_t, destroy, void, private_lookip_listener_t *this) { @@ -315,6 +335,7 @@ lookip_listener_t *lookip_listener_create() }, .lookup = _lookup, .add_listener = _add_listener, + .remove_listener = _remove_listener, .destroy = _destroy, }, .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), diff --git a/src/libcharon/plugins/lookip/lookip_listener.h b/src/libcharon/plugins/lookip/lookip_listener.h index 56f74ed48..f6612b324 100644 --- a/src/libcharon/plugins/lookip/lookip_listener.h +++ b/src/libcharon/plugins/lookip/lookip_listener.h @@ -75,6 +75,13 @@ struct lookip_listener_t { lookip_callback_t cb, void *user); /** + * Unregister a listener by the user data. + * + * @param user user data, as passed during add_listener() + */ + void (*remove_listener)(lookip_listener_t *this, void *user); + + /** * Destroy a lookip_listener_t. */ void (*destroy)(lookip_listener_t *this); diff --git a/src/libcharon/plugins/lookip/lookip_msg.h b/src/libcharon/plugins/lookip/lookip_msg.h index d5789c29f..83b765ece 100644 --- a/src/libcharon/plugins/lookip/lookip_msg.h +++ b/src/libcharon/plugins/lookip/lookip_msg.h @@ -69,7 +69,7 @@ struct lookip_request_t { int type; /** null terminated string representation of virtual IP */ char vip[40]; -}; +} __attribute__((packed)); /** * Response message sent to client. @@ -86,11 +86,11 @@ struct lookip_response_t { /** null terminated string representation of outer IP */ char ip[40]; /** null terminated peer identity */ - char id[128]; + char id[256]; /** null terminated connection name */ char name[40]; /** unique connection id */ unsigned int unique_id; -}; +} __attribute__((packed)); #endif /** LOOKIP_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/lookip/lookip_plugin.c b/src/libcharon/plugins/lookip/lookip_plugin.c index 360864849..a6c32d65d 100644 --- a/src/libcharon/plugins/lookip/lookip_plugin.c +++ b/src/libcharon/plugins/lookip/lookip_plugin.c @@ -49,11 +49,38 @@ METHOD(plugin_t, get_name, char*, return "lookip"; } +/** + * Register listener + */ +static bool plugin_cb(private_lookip_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_lookip_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "lookip"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_lookip_plugin_t *this) { - this->socket->destroy(this->socket); - charon->bus->remove_listener(charon->bus, &this->listener->listener); + DESTROY_IF(this->socket); this->listener->destroy(this->listener); free(this); } @@ -69,15 +96,19 @@ plugin_t *lookip_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .listener = lookip_listener_create(), ); - charon->bus->add_listener(charon->bus, &this->listener->listener); this->socket = lookip_socket_create(this->listener); + if (!this->socket) + { + destroy(this); + return NULL; + } return &this->public.plugin; } diff --git a/src/libcharon/plugins/lookip/lookip_socket.c b/src/libcharon/plugins/lookip/lookip_socket.c index f2a469e92..d25573bf4 100644 --- a/src/libcharon/plugins/lookip/lookip_socket.c +++ b/src/libcharon/plugins/lookip/lookip_socket.c @@ -48,17 +48,12 @@ struct private_lookip_socket_t { lookip_listener_t *listener; /** - * lookip unix socket file descriptor + * stream service accepting connections */ - int socket; + stream_service_t *service; /** - * List of registered listeners, as entry_t - */ - linked_list_t *registered; - - /** - * List of connected clients, as uintptr_t FD + * List of connected clients, as entry_t */ linked_list_t *connected; @@ -69,88 +64,80 @@ struct private_lookip_socket_t { }; /** - * Open lookip unix socket - */ -static bool open_socket(private_lookip_socket_t *this) -{ - struct sockaddr_un addr; - mode_t old; - - addr.sun_family = AF_UNIX; - strcpy(addr.sun_path, LOOKIP_SOCKET); - - this->socket = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (this->socket == -1) - { - DBG1(DBG_CFG, "creating lookip socket failed"); - return FALSE; - } - unlink(addr.sun_path); - old = umask(~(S_IRWXU | S_IRWXG)); - if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) - { - DBG1(DBG_CFG, "binding lookip socket failed: %s", strerror(errno)); - close(this->socket); - return FALSE; - } - umask(old); - if (chown(addr.sun_path, charon->caps->get_uid(charon->caps), - charon->caps->get_gid(charon->caps)) != 0) - { - DBG1(DBG_CFG, "changing lookip socket permissions failed: %s", - strerror(errno)); - } - if (listen(this->socket, 10) < 0) - { - DBG1(DBG_CFG, "listening on lookip socket failed: %s", strerror(errno)); - close(this->socket); - unlink(addr.sun_path); - return FALSE; - } - return TRUE; -} - -/** - * Listener callback entry + * List entry for a connected stream */ typedef struct { - /* FD to write to */ - int fd; - /* message type to send */ - int type; - /* back pointer to socket, only for subscriptions */ + /* stream to write to */ + stream_t *stream; + /* registered for up events? */ + bool up; + /* registered for down events? */ + bool down; + /** backref to this for unregistration */ private_lookip_socket_t *this; } entry_t; /** - * Destroy entry + * Clean up a connection entry */ -static void entry_destroy(entry_t *this) +static void entry_destroy(entry_t *entry) { - close(this->fd); - free(this); + entry->stream->destroy(entry->stream); + free(entry); +} + +/** + * Disconnect a stream, remove connection entry + */ +static void disconnect(private_lookip_socket_t *this, stream_t *stream) +{ + enumerator_t *enumerator; + entry_t *entry; + + this->mutex->lock(this->mutex); + enumerator = this->connected->create_enumerator(this->connected); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->stream == stream) + { + this->connected->remove_at(this->connected, enumerator); + if (entry->up || entry->down) + { + this->listener->remove_listener(this->listener, entry); + } + entry_destroy(entry); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); } /** - * Callback function for listener + * Callback function for listener up/down events */ -static bool listener_cb(entry_t *entry, bool up, host_t *vip, - host_t *other, identification_t *id, - char *name, u_int unique_id) +static bool event_cb(entry_t *entry, bool up, host_t *vip, host_t *other, + identification_t *id, char *name, u_int unique_id) { lookip_response_t resp = { - .type = entry->type, - .unique_id = unique_id, + .unique_id = htonl(unique_id), }; - /* filter events */ - if (up && entry->type == LOOKIP_NOTIFY_DOWN) + if (up) { - return TRUE; + if (!entry->up) + { + return TRUE; + } + resp.type = htonl(LOOKIP_NOTIFY_UP); } - if (!up && entry->type == LOOKIP_NOTIFY_UP) + else { - return TRUE; + if (!entry->down) + { + return TRUE; + } + resp.type = htonl(LOOKIP_NOTIFY_DOWN); } snprintf(resp.vip, sizeof(resp.vip), "%H", vip); @@ -158,37 +145,66 @@ static bool listener_cb(entry_t *entry, bool up, host_t *vip, snprintf(resp.id, sizeof(resp.id), "%Y", id); snprintf(resp.name, sizeof(resp.name), "%s", name); - switch (send(entry->fd, &resp, sizeof(resp), 0)) + if (entry->stream->write_all(entry->stream, &resp, sizeof(resp))) { - case sizeof(resp): - return TRUE; - case 0: + return TRUE; + } + switch (errno) + { + case ECONNRESET: + case EPIPE: /* client disconnected, adios */ break; default: - DBG1(DBG_CFG, "sending lookip response failed: %s", strerror(errno)); + DBG1(DBG_CFG, "sending lookip event failed: %s", strerror(errno)); break; } - if (entry->this) - { /* unregister listener */ - entry->this->mutex->lock(entry->this->mutex); - entry->this->registered->remove(entry->this->registered, entry, NULL); - entry->this->mutex->unlock(entry->this->mutex); + /* don't unregister, as we return FALSE */ + entry->up = entry->down = FALSE; + disconnect(entry->this, entry->stream); + return FALSE; +} + +/** + * Callback function for queries + */ +static bool query_cb(stream_t *stream, bool up, host_t *vip, host_t *other, + identification_t *id, char *name, u_int unique_id) +{ + lookip_response_t resp = { + .type = htonl(LOOKIP_ENTRY), + .unique_id = htonl(unique_id), + }; - entry_destroy(entry); + snprintf(resp.vip, sizeof(resp.vip), "%H", vip); + snprintf(resp.ip, sizeof(resp.ip), "%H", other); + snprintf(resp.id, sizeof(resp.id), "%Y", id); + snprintf(resp.name, sizeof(resp.name), "%s", name); + + if (stream->write_all(stream, &resp, sizeof(resp))) + { + return TRUE; + } + switch (errno) + { + case ECONNRESET: + case EPIPE: + /* client disconnected, adios */ + break; + default: + DBG1(DBG_CFG, "sending lookip response failed: %s", strerror(errno)); + break; } return FALSE; } /** - * Perform a entry lookup + * Perform a lookup */ -static void query(private_lookip_socket_t *this, int fd, lookip_request_t *req) +static void query(private_lookip_socket_t *this, stream_t *stream, + lookip_request_t *req) { - entry_t entry = { - .fd = fd, - .type = LOOKIP_ENTRY, - }; + host_t *vip = NULL; int matches = 0; @@ -199,17 +215,17 @@ static void query(private_lookip_socket_t *this, int fd, lookip_request_t *req) if (vip) { matches = this->listener->lookup(this->listener, vip, - (void*)listener_cb, &entry); + (void*)query_cb, stream); vip->destroy(vip); } if (matches == 0) { lookip_response_t resp = { - .type = LOOKIP_NOT_FOUND, + .type = htonl(LOOKIP_NOT_FOUND), }; snprintf(resp.vip, sizeof(resp.vip), "%s", req->vip); - if (send(fd, &resp, sizeof(resp), 0) < 0) + if (!stream->write_all(stream, &resp, sizeof(resp))) { DBG1(DBG_CFG, "sending lookip not-found failed: %s", strerror(errno)); @@ -219,214 +235,143 @@ static void query(private_lookip_socket_t *this, int fd, lookip_request_t *req) else { /* dump */ this->listener->lookup(this->listener, NULL, - (void*)listener_cb, &entry); + (void*)query_cb, stream); } } /** * Subscribe to virtual IP events */ -static void subscribe(private_lookip_socket_t *this, int fd, int type) -{ - entry_t *entry; - - INIT(entry, - .fd = fd, - .type = type, - .this = this, - ); - - this->mutex->lock(this->mutex); - this->registered->insert_last(this->registered, entry); - this->mutex->unlock(this->mutex); - - this->listener->add_listener(this->listener, (void*)listener_cb, entry); -} - -/** - * Check if a client is subscribed for notifications - */ -static bool subscribed(private_lookip_socket_t *this, int fd) +static void subscribe(private_lookip_socket_t *this, stream_t *stream, bool up) { enumerator_t *enumerator; - bool subscribed = FALSE; entry_t *entry; this->mutex->lock(this->mutex); - enumerator = this->registered->create_enumerator(this->registered); + enumerator = this->connected->create_enumerator(this->connected); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->fd == fd) + if (entry->stream == stream) { - subscribed = TRUE; - break; + if (!entry->up && !entry->down) + { /* newly registered */ + this->listener->add_listener(this->listener, + (void*)event_cb, entry); + } + if (up) + { + entry->up = TRUE; + } + else + { + entry->down = TRUE; + } } } enumerator->destroy(enumerator); this->mutex->unlock(this->mutex); - - return subscribed; } /** - * Create a fd_set from all bound sockets - */ -static int build_fds(private_lookip_socket_t *this, fd_set *fds) -{ - enumerator_t *enumerator; - uintptr_t fd; - int maxfd; - - FD_ZERO(fds); - FD_SET(this->socket, fds); - maxfd = this->socket; - - this->mutex->lock(this->mutex); - enumerator = this->connected->create_enumerator(this->connected); - while (enumerator->enumerate(enumerator, &fd)) - { - FD_SET(fd, fds); - maxfd = max(maxfd, fd); - } - enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); - - return maxfd + 1; -} - -/** - * Find the socket select()ed + * Check if a client is subscribed for notifications */ -static int scan_fds(private_lookip_socket_t *this, fd_set *fds) +static bool subscribed(private_lookip_socket_t *this, stream_t *stream) { enumerator_t *enumerator; - uintptr_t fd; - int selected = -1; + bool subscribed = FALSE; + entry_t *entry; this->mutex->lock(this->mutex); enumerator = this->connected->create_enumerator(this->connected); - while (enumerator->enumerate(enumerator, &fd)) + while (enumerator->enumerate(enumerator, &entry)) { - if (FD_ISSET(fd, fds)) + if (entry->stream == stream) { - selected = fd; + subscribed = entry->up || entry->down; break; } } enumerator->destroy(enumerator); this->mutex->unlock(this->mutex); - return selected; + return subscribed; } /** - * Dispatch from a socket, return TRUE to end communication + * Dispatch from a socket, on-read callback */ -static bool dispatch(private_lookip_socket_t *this, int fd) +static bool on_read(private_lookip_socket_t *this, stream_t *stream) { lookip_request_t req; - int len; - len = recv(fd, &req, sizeof(req), 0); - if (len != sizeof(req)) + if (stream->read_all(stream, &req, sizeof(req))) { - if (len != 0) + switch (ntohl(req.type)) + { + case LOOKIP_LOOKUP: + query(this, stream, &req); + return TRUE; + case LOOKIP_DUMP: + query(this, stream, NULL); + return TRUE; + case LOOKIP_REGISTER_UP: + subscribe(this, stream, TRUE); + return TRUE; + case LOOKIP_REGISTER_DOWN: + subscribe(this, stream, FALSE); + return TRUE; + case LOOKIP_END: + break; + default: + DBG1(DBG_CFG, "received unknown lookip command"); + break; + } + } + else + { + if (errno != ECONNRESET) { DBG1(DBG_CFG, "receiving lookip request failed: %s", strerror(errno)); } - return TRUE; + disconnect(this, stream); + return FALSE; } - switch (req.type) + if (subscribed(this, stream)) { - case LOOKIP_LOOKUP: - query(this, fd, &req); - return FALSE; - case LOOKIP_DUMP: - query(this, fd, NULL); - return FALSE; - case LOOKIP_REGISTER_UP: - subscribe(this, fd, LOOKIP_NOTIFY_UP); - return FALSE; - case LOOKIP_REGISTER_DOWN: - subscribe(this, fd, LOOKIP_NOTIFY_DOWN); - return FALSE; - case LOOKIP_END: - return TRUE; - default: - DBG1(DBG_CFG, "received unknown lookip command"); - return TRUE; + return TRUE; } + disconnect(this, stream); + return FALSE; } /** * Accept client connections, dispatch */ -static job_requeue_t receive(private_lookip_socket_t *this) +static bool on_accept(private_lookip_socket_t *this, stream_t *stream) { - struct sockaddr_un addr; - int fd, maxfd, len; - bool oldstate; - fd_set fds; + entry_t *entry; - while (TRUE) - { - maxfd = build_fds(this, &fds); - oldstate = thread_cancelability(TRUE); - if (select(maxfd, &fds, NULL, NULL, NULL) <= 0) - { - thread_cancelability(oldstate); - DBG1(DBG_CFG, "selecting lookip sockets failed: %s", - strerror(errno)); - break; - } - thread_cancelability(oldstate); + INIT(entry, + .stream = stream, + .this = this, + ); - if (FD_ISSET(this->socket, &fds)) - { /* new connection, accept() */ - len = sizeof(addr); - fd = accept(this->socket, (struct sockaddr*)&addr, &len); - if (fd != -1) - { - this->mutex->lock(this->mutex); - this->connected->insert_last(this->connected, - (void*)(uintptr_t)fd); - this->mutex->unlock(this->mutex); - } - else - { - DBG1(DBG_CFG, "accepting lookip connection failed: %s", - strerror(errno)); - } - continue; - } + this->mutex->lock(this->mutex); + this->connected->insert_last(this->connected, entry); + this->mutex->unlock(this->mutex); - fd = scan_fds(this, &fds); - if (fd == -1) - { - continue; - } - if (dispatch(this, fd)) - { - this->mutex->lock(this->mutex); - this->connected->remove(this->connected, (void*)(uintptr_t)fd, NULL); - this->mutex->unlock(this->mutex); - if (!subscribed(this, fd)) - { - close(fd); - } - } - } - return JOB_REQUEUE_FAIR; + stream->on_read(stream, (void*)on_read, this); + + return TRUE; } METHOD(lookip_socket_t, destroy, void, private_lookip_socket_t *this) { - this->registered->destroy_function(this->registered, (void*)entry_destroy); - this->connected->destroy(this->connected); + DESTROY_IF(this->service); + this->connected->destroy_function(this->connected, (void*)entry_destroy); this->mutex->destroy(this->mutex); - close(this->socket); free(this); } @@ -436,26 +381,30 @@ METHOD(lookip_socket_t, destroy, void, lookip_socket_t *lookip_socket_create(lookip_listener_t *listener) { private_lookip_socket_t *this; + char *uri; INIT(this, .public = { .destroy = _destroy, }, .listener = listener, - .registered = linked_list_create(), .connected = linked_list_create(), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); - if (!open_socket(this)) + uri = lib->settings->get_str(lib->settings, + "%s.plugins.lookip.socket", "unix://" LOOKIP_SOCKET, + charon->name); + this->service = lib->streams->create_service(lib->streams, uri, 10); + if (!this->service) { - free(this); + DBG1(DBG_CFG, "creating lookip socket failed"); + destroy(this); return NULL; } - lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this, - NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); + this->service->on_accept(this->service, (stream_service_cb_t)on_accept, + this, JOB_PRIO_CRITICAL, 1); return &this->public; } |