diff options
Diffstat (limited to 'dpid')
-rw-r--r-- | dpid/Makefile.am | 24 | ||||
-rw-r--r-- | dpid/dpi.c | 4 | ||||
-rw-r--r-- | dpid/dpi.h | 17 | ||||
-rw-r--r-- | dpid/dpi_service.c | 114 | ||||
-rw-r--r-- | dpid/dpi_service.h | 20 | ||||
-rw-r--r-- | dpid/dpi_socket_dir.c | 3 | ||||
-rw-r--r-- | dpid/dpid.c | 547 | ||||
-rw-r--r-- | dpid/dpid.h | 46 | ||||
-rw-r--r-- | dpid/dpid_common.c | 32 | ||||
-rw-r--r-- | dpid/dpid_common.h | 9 | ||||
-rw-r--r-- | dpid/dpidc | 31 | ||||
-rw-r--r-- | dpid/dpidc.c | 121 | ||||
-rw-r--r-- | dpid/dpidrc.in | 6 | ||||
-rw-r--r-- | dpid/main.c | 118 | ||||
-rw-r--r-- | dpid/misc_new.c | 55 | ||||
-rw-r--r-- | dpid/misc_new.h | 3 |
16 files changed, 580 insertions, 570 deletions
diff --git a/dpid/Makefile.am b/dpid/Makefile.am index 938a6244..2b81a98a 100644 --- a/dpid/Makefile.am +++ b/dpid/Makefile.am @@ -1,31 +1,29 @@ AM_CPPFLAGS=-DDPIDRC_SYS='"$(sysconfdir)/dpidrc"' -bin_PROGRAMS = dpid +bin_PROGRAMS = dpid dpidc dpid_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a +dpidc_LDADD = ../dpip/libDpip.a ../dlib/libDlib.a -EXTRA_DIST = dpidc -bin_SCRIPTS = dpidc +EXTRA_DIST = dpidrc.in dpid_SOURCES = \ dpi.h \ - dpi_service.h \ dpi_socket_dir.h \ dpid.h \ dpid_common.h \ misc_new.h \ dpi.c \ - dpi_service.c \ dpi_socket_dir.c \ dpid.c \ dpid_common.c \ main.c \ misc_new.c -install-data-local : - $(mkinstalldirs) $(DESTDIR)$(sysconfdir) - echo dpi_dir=$(libdir)/dillo/dpi > $(DESTDIR)$(sysconfdir)/dpidrc - echo >> $(DESTDIR)$(sysconfdir)/dpidrc - echo "proto.file=file/file.dpi" >> $(DESTDIR)$(sysconfdir)/dpidrc - echo "proto.ftp=ftp/ftp.filter.dpi" >> $(DESTDIR)$(sysconfdir)/dpidrc - echo "proto.https=https/https.filter.dpi" >> $(DESTDIR)$(sysconfdir)/dpidrc - echo "proto.data=datauri/datauri.filter.dpi" >> $(DESTDIR)$(sysconfdir)/dpidrc +dpidc_SOURCES = dpidc.c + +sysconf_DATA = dpidrc +CLEANFILES = $(sysconf_DATA) + +dpidrc: $(srcdir)/dpidrc.in Makefile + sed -e 's|[@]libdir[@]|$(libdir)|' $(srcdir)/dpidrc.in > dpidrc + @@ -12,8 +12,7 @@ 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + along with this program. If not, see <http://www.gnu.org/licenses/>. */ /*! \file @@ -23,6 +22,7 @@ */ #include <errno.h> +#include <stdlib.h> /* for exit */ #include "dpid_common.h" #include "dpi.h" #include "misc_new.h" @@ -7,18 +7,8 @@ #ifndef DPI_H #define DPI_H -#include <config.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> - -/* Check the Unix98 goodie */ -#ifndef socklen_t - #define socklen_t uint32_t -#endif +#include <unistd.h> /* for socklen_t */ +#include <sys/socket.h> /* for socklen_t and AF_LOCAL */ /* Some systems may not have this one... */ #ifndef AF_LOCAL @@ -38,7 +28,8 @@ */ enum { UNKNOWN_CMD, - BYE_CMD, /* "DpiBye" */ + AUTH_CMD, /* authentication */ + BYE_CMD, /* "DpiBye" */ CHECK_SERVER_CMD, /* "check_server" */ REGISTER_ALL_CMD, /* "register_all" */ REGISTER_SERVICE_CMD /* "register_service" */ diff --git a/dpid/dpi_service.c b/dpid/dpi_service.c deleted file mode 100644 index 07cdad8e..00000000 --- a/dpid/dpi_service.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright (C) 2003 Ferdi Franceschini <ferdif@optusnet.com.au> - - 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*! \file - * \todo - * This module should be removed because its original functions - * have been removed or modified. - * Put these functions in dpid.c - */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include "dpid_common.h" -#include "dpid.h" -#include "../dpip/dpip.h" - -#ifdef TEST -#include "testdat.h" -#endif - -/* exported functions */ -char *get_dpi_dir(char *dpidrc); - - -/*! Get dpi directory path from dpidrc - * \Return - * dpi directory on success, NULL on failure - * \Important - * The dpi_dir definition in dpidrc must have no leading white space. - */ -char *get_dpi_dir(char *dpidrc) -{ - FILE *In; - int len; - char *rcline = NULL, *value = NULL, *p; - - if ((In = fopen(dpidrc, "r")) == NULL) { - ERRMSG("dpi_dir", "fopen", errno); - MSG_ERR(" - %s\n", dpidrc); - return (NULL); - } - - while ((rcline = dGetline(In)) != NULL) { - if (strncmp(rcline, "dpi_dir", 7) == 0) - break; - dFree(rcline); - } - fclose(In); - - if (!rcline) { - ERRMSG("dpi_dir", "Failed to find a dpi_dir entry in dpidrc", 0); - MSG_ERR("Put your dillo plugins path in %s\n", dpidrc); - MSG_ERR("eg. dpi_dir=/usr/local/lib/dillo/dpi "); - MSG_ERR("with no leading spaces.\n"); - value = NULL; - } else { - len = (int) strlen(rcline); - if (len && rcline[len - 1] == '\n') - rcline[len - 1] = 0; - - if ((p = strchr(rcline, '='))) { - while (*++p == ' '); - value = dStrdup(p); - } else { - ERRMSG("dpi_dir", "strchr", 0); - MSG_ERR(" - '=' not found in %s\n", rcline); - value = NULL; - } - } - - dFree(rcline); - return (value); -} - -/*! Send the list of available dpi IDs to a client - * \Return - * 1 on success, -1 on failure. - * -static int send_service_list(int sock, struct dp *dpi_attr_list, int srv_num) -{ - int i; - char *buf; - ssize_t wlen = 0; - - for (i = 0; i < srv_num && wlen != -1; i++) { - d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", - "send_data", dpi_attr_list[i].id); - wlen = write(sock, d_cmd, strlen(d_cmd)); - dFree(d_cmd); - } - if (wlen == -1) { - ERRMSG("send_service_list", "write", errno); - return (-1); - } - return (1); -} - */ diff --git a/dpid/dpi_service.h b/dpid/dpi_service.h deleted file mode 100644 index af7679b3..00000000 --- a/dpid/dpi_service.h +++ /dev/null @@ -1,20 +0,0 @@ -/*! \file - * \todo - * This module should be removed because its original functions - * have been removed or modified. - * Put these functions in dpid.c - */ - -#ifndef DPI_SERVICE_H -#define DPI_SERVICE_H - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include "dpid.h" - -char *get_dpi_dir(char *dpidrc); - -int send_service_list(int sock, struct dp *dpi_attr_list, int srv_num); - -#endif diff --git a/dpid/dpi_socket_dir.c b/dpid/dpi_socket_dir.c index 333ccf6a..09a24e2f 100644 --- a/dpid/dpi_socket_dir.c +++ b/dpid/dpi_socket_dir.c @@ -12,8 +12,7 @@ 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + along with this program. If not, see <http://www.gnu.org/licenses/>. */ /*! \file diff --git a/dpid/dpid.c b/dpid/dpid.c index 97e6414d..d8bfeb96 100644 --- a/dpid/dpid.c +++ b/dpid/dpid.c @@ -12,22 +12,26 @@ 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + along with this program. If not, see <http://www.gnu.org/licenses/>. */ /*! \file * Main functions to set-up dpi information and to initialise sockets */ #include <errno.h> +#include <stdlib.h> /* for exit */ +#include <fcntl.h> /* for F_SETFD, F_GETFD, FD_CLOEXEC */ + #include <sys/stat.h> #include <sys/wait.h> +#include <sys/socket.h> +#include <netinet/tcp.h> + #include <unistd.h> #include "dpid_common.h" #include "dpid.h" #include "dpi.h" #include "dpi_socket_dir.h" -#include "dpi_service.h" #include "misc_new.h" #include "../dpip/dpip.h" @@ -35,71 +39,18 @@ #define QUEUE 5 volatile sig_atomic_t caught_sigchld = 0; +char *SharedKey = NULL; -/*! Return the basename of a filename - */ -static char *get_basename(char *filename) -{ - char *p; - - if (filename && (p = strrchr(filename, '/'))) { - filename = p + 1; - } - return filename; -} - -/*! Close and remove the sockets in the - * given dpi attribute list +/*! Remove dpid_comm_keys file. + * This avoids that dillo instances connect to a stale port after dpid + * has exited (e.g. after a reboot). */ -void rm_dpi_sockets(struct dp *dpi_attr_list, int numdpis) +void cleanup() { - int i; - - for (i = 0; i < numdpis; i++) { - a_Misc_close_fd(dpi_attr_list[i].socket); - (void) unlink(dpi_attr_list[i].sockpath); - } -} - -/*! Close and remove inactive dpi sockets - * \Return - * Number of active dpis. - */ -int rm_inactive_dpi_sockets(struct dp *dpi_attr_list, int numdpis) -{ - int i, active = 0; - - for (i = 0; i < numdpis; i++) { - if (dpi_attr_list[i].pid == 1) { - a_Misc_close_fd(dpi_attr_list[i].socket); - (void) unlink(dpi_attr_list[i].sockpath); - } else - active++; - } - return (active); -} - -/*! Remove sockets - */ -void cleanup(char *socket_dir) -{ - DIR *dir; - struct dirent *dir_entry = NULL; - char *sockpath; - - dir = opendir(socket_dir); - if (dir == NULL) { - ERRMSG("cleanup", "opendir", errno); - return; - } - while ( (dir_entry = readdir(dir)) != NULL ) { - if (dir_entry->d_name[0] == '.') - continue; - sockpath = dStrconcat(socket_dir, "/", dir_entry->d_name, NULL); - unlink(sockpath); - dFree(sockpath); - } - closedir(dir); + char *fname; + fname = dStrconcat(dGethomedir(), "/", dotDILLO_DPID_COMM_KEYS, NULL); + unlink(fname); + dFree(fname); } /*! Free memory used to describe @@ -115,10 +66,6 @@ void free_dpi_attr(struct dp *dpi_attr) dFree(dpi_attr->path); dpi_attr->path = NULL; } - if (dpi_attr->sockpath != NULL) { - dFree(dpi_attr->sockpath); - dpi_attr->sockpath = NULL; - } } /*! Free memory used by the plugin list @@ -152,53 +99,46 @@ void free_services_list(Dlist *s_list) dList_free(s_list); } -/*! \todo - * Remove terminator and est_terminator unless we really want to clean up - * on abnormal exit. - */ -#if 0 /*! Signal handler for SIGINT, SIGQUIT, and SIGTERM. Calls cleanup */ -void terminator(int sig) +static void terminator(int sig) { - (void) signal(SIGCHLD, SIG_DFL); + (void) sig; /* suppress unused parameter warning */ cleanup(); - (void) signal(sig, SIG_DFL); - (void) raise(sig); _exit(0); } /*! Establish handler for termination signals * and register cleanup with atexit */ -void est_terminator(void) +void est_dpi_terminator() { struct sigaction act; sigset_t block; - (void) sigemptyset(&block); - (void) sigaddset(&block, SIGINT); - (void) sigaddset(&block, SIGQUIT); - (void) sigaddset(&block, SIGTERM); - (void) sigaddset(&block, SIGSEGV); + sigemptyset(&block); + sigaddset(&block, SIGHUP); + sigaddset(&block, SIGINT); + sigaddset(&block, SIGQUIT); + sigaddset(&block, SIGTERM); act.sa_handler = terminator; act.sa_mask = block; act.sa_flags = 0; - if (sigaction(SIGINT, &act, NULL) || + if (sigaction(SIGHUP, &act, NULL) || + sigaction(SIGINT, &act, NULL) || sigaction(SIGQUIT, &act, NULL) || - sigaction(SIGTERM, &act, NULL) || sigaction(SIGSEGV, &act, NULL)) { - ERRMSG("est_terminator", "sigaction", errno); + sigaction(SIGTERM, &act, NULL)) { + ERRMSG("est_dpi_terminator", "sigaction", errno); exit(1); } if (atexit(cleanup) != 0) { - ERRMSG("est_terminator", "atexit", 0); + ERRMSG("est_dpi_terminator", "atexit", 0); MSG_ERR("Hey! atexit failed, how did that happen?\n"); exit(1); } } -#endif /*! Identify a given file * Currently there is only one file type associated with dpis. @@ -216,6 +156,56 @@ enum file_type get_file_type(char *file_name) } } +/*! Get dpi directory path from dpidrc + * \Return + * dpi directory on success, NULL on failure + * \Important + * The dpi_dir definition in dpidrc must have no leading white space. + */ +char *get_dpi_dir(char *dpidrc) +{ + FILE *In; + int len; + char *rcline = NULL, *value = NULL, *p; + + if ((In = fopen(dpidrc, "r")) == NULL) { + ERRMSG("dpi_dir", "fopen", errno); + MSG_ERR(" - %s\n", dpidrc); + return (NULL); + } + + while ((rcline = dGetline(In)) != NULL) { + if (strncmp(rcline, "dpi_dir", 7) == 0) + break; + dFree(rcline); + } + fclose(In); + + if (!rcline) { + ERRMSG("dpi_dir", "Failed to find a dpi_dir entry in dpidrc", 0); + MSG_ERR("Put your dillo plugins path in %s\n", dpidrc); + MSG_ERR("e.g. dpi_dir=/usr/local/lib/dillo/dpi\n"); + MSG_ERR("with no leading spaces.\n"); + value = NULL; + } else { + len = (int) strlen(rcline); + if (len && rcline[len - 1] == '\n') + rcline[len - 1] = 0; + + if ((p = strchr(rcline, '='))) { + while (*++p == ' '); + value = dStrdup(p); + } else { + ERRMSG("dpi_dir", "strchr", 0); + MSG_ERR(" - '=' not found in %s\n", rcline); + value = NULL; + } + } + + dFree(rcline); + return (value); +} + /*! Scans a service directory in dpi_dir and fills dpi_attr * \Note * Caller must allocate memory for dpi_attr. @@ -231,7 +221,7 @@ int get_dpi_attr(char *dpi_dir, char *service, struct dp *dpi_attr) char *service_dir = NULL; struct stat statinfo; enum file_type ftype; - int retval = -1; + int ret = -1; DIR *dir_stream; struct dirent *dir_entry = NULL; @@ -255,13 +245,13 @@ int get_dpi_attr(char *dpi_dir, char *service, struct dp *dpi_attr) dpi_attr->path = dStrconcat(service_dir, "/", dir_entry->d_name, NULL); dpi_attr->id = dStrdup(service); - dpi_attr->sockpath = NULL; + dpi_attr->port = 0; dpi_attr->pid = 1; if (strstr(dpi_attr->path, ".filter") != NULL) dpi_attr->filter = 1; else dpi_attr->filter = 0; - retval = 0; + ret = 0; break; default: break; @@ -269,12 +259,12 @@ int get_dpi_attr(char *dpi_dir, char *service, struct dp *dpi_attr) } closedir(dir_stream); - if (retval != 0) + if (ret != 0) MSG_ERR("get_dpi_attr: No dpi plug-in in %s/%s\n", dpi_dir, service); } dFree(service_dir); - return retval; + return ret; } /*! Register a service @@ -289,7 +279,7 @@ int get_dpi_attr(char *dpi_dir, char *service, struct dp *dpi_attr) int register_service(struct dp *dpi_attr, char *service) { char *user_dpi_dir, *dpidrc, *user_service_dir, *dir = NULL; - int retval = -1; + int ret = -1; user_dpi_dir = dStrconcat(dGethomedir(), "/", dotDILLO_DPI, NULL); user_service_dir = @@ -313,12 +303,12 @@ int register_service(struct dp *dpi_attr, char *service) /* Check home dir for dpis */ if (access(user_service_dir, F_OK) == 0) { get_dpi_attr(user_dpi_dir, service, dpi_attr); - retval = 0; + ret = 0; } else { /* Check system wide dpis */ if ((dir = get_dpi_dir(dpidrc)) != NULL) { if (access(dir, F_OK) == 0) { get_dpi_attr(dir, service, dpi_attr); - retval = 0; + ret = 0; } else { ERRMSG("register_service", "get_dpi_attr failed", 0); } @@ -330,7 +320,7 @@ int register_service(struct dp *dpi_attr, char *service) dFree(user_service_dir); dFree(dpidrc); dFree(dir); - return (retval); + return ret; } /*! @@ -424,19 +414,18 @@ static int services_alpha_comp(const struct service *s1, return -strcmp(s1->name, s2->name); } -/*! Add services reading a dpidrc file - * each non empty or commented line has the form - * service = path_relative_to_dpidir - * \Return: - * \li Returns number of available services on success - * \li -1 on failure - */ +/*! Add services reading a dpidrc file + * each non empty or commented line has the form + * service = path_relative_to_dpidir + * \Return: + * \li Returns number of available services on success + * \li -1 on failure + */ int fill_services_list(struct dp *attlist, int numdpis, Dlist **services_list) { FILE *dpidrc_stream; - char *p, *line = NULL; - char *service, *path; - int i; + char *p, *line = NULL, *service, *path; + int i, st; struct service *s; char *user_dpidir = NULL, *sys_dpidir = NULL, *dpidrc = NULL; @@ -479,16 +468,18 @@ int fill_services_list(struct dp *attlist, int numdpis, Dlist **services_list) *services_list = dList_new(8); /* dpidrc parser loop */ - while ((line = dGetline(dpidrc_stream)) != NULL) { - - if (dParser_get_rc_pair(&line, &service, &path) == -1) { - if (line[0] && line[0] != '#' && (!service || !path)) { - MSG_ERR("Syntax error in %s: service=\"%s\" path=\"%s\"\n", - dpidrc, service, path); - } + for (;(line = dGetline(dpidrc_stream)) != NULL; dFree(line)) { + st = dParser_parse_rc_line(&line, &service, &path); + if (st < 0) { + MSG_ERR("dpid: Syntax error in %s: service=\"%s\" path=\"%s\"\n", + dpidrc, service, path); + continue; + } else if (st != 0) { continue; } + _MSG("dpid: service=%s, path=%s\n", service, path); + /* ignore dpi_dir silently */ if (strcmp(service, "dpi_dir") == 0) continue; @@ -507,9 +498,8 @@ int fill_services_list(struct dp *attlist, int numdpis, Dlist **services_list) /* if the dpi exist bind service and dpi */ if (i < numdpis) s->dp_index = i; - dFree(line); } - fclose(dpidrc_stream); + fclose(dpidrc_stream); dList_sort(*services_list, (dCompareFunc)services_alpha_comp); @@ -520,127 +510,142 @@ int fill_services_list(struct dp *attlist, int numdpis, Dlist **services_list) return (dList_length(*services_list)); } -/*! Initialise the service request socket - * \Return: - * \li Number of sockets (1 == success) - * \li -1 on failure +/* + * Return a socket file descriptor + * (useful to set socket options in a uniform way) */ -int init_srs_socket(char *sockdir) +static int make_socket_fd() { - int retval = -1; - struct sockaddr_un srs_sa; - size_t sun_path_len; - socklen_t addr_sz; + int ret, one = 1; - srs_name = dStrconcat(sockdir, "/", SRS_NAME, NULL); - FD_ZERO(&sock_set); - - /* Initialise srs, service request socket on startup */ - if ((srs = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) { - ERRMSG("init_srs_socket", "socket", errno); - return (retval); /* avoids nesting ifs too deeply */ + if ((ret = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + ERRMSG("make_socket_fd", "socket", errno); + } else { + /* avoid delays when sending small pieces of data */ + setsockopt(ret, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); } - /* Set srs to close on exec */ - fcntl(srs, F_SETFD, FD_CLOEXEC | fcntl(srs, F_GETFD)); - srs_sa.sun_family = AF_LOCAL; + /* set some buffering to increase the transfer's speed */ + //setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, + // &sock_buflen, (socklen_t)sizeof(sock_buflen)); + + return ret; +} - sun_path_len = sizeof(srs_sa.sun_path); - if (strlen(srs_name) > sun_path_len) { - ERRMSG("init_srs_socket", "srs_name is too long", 0); - MSG_ERR("\n - it should be <= %lu chars", (ulong_t)sun_path_len); - MSG_ERR("\n - srs_name = %s\n", srs_name); - return(retval); +/*! Bind a socket port on localhost. Try to be close to base_port. + * \Return + * \li listening socket file descriptor on success + * \li -1 on failure + */ +int bind_socket_fd(int base_port, int *p_port) +{ + int sock_fd, port; + struct sockaddr_in sin; + int ok = 0, last_port = base_port + 50; + + if ((sock_fd = make_socket_fd()) == -1) { + return (-1); /* avoids nested ifs */ } - strncpy(srs_sa.sun_path, srs_name, sun_path_len); - addr_sz = (socklen_t) D_SUN_LEN(&srs_sa); + /* Set the socket FD to close on exec */ + fcntl(sock_fd, F_SETFD, FD_CLOEXEC | fcntl(sock_fd, F_GETFD)); - if ((bind(srs, (struct sockaddr *) &srs_sa, addr_sz)) == -1) { - if (errno == EADDRINUSE) { - ERRMSG("init_srs_socket", "bind", errno); - MSG_ERR("srs_sa.sun_path = %s\n", srs_sa.sun_path); - dpi_errno = dpid_srs_addrinuse; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + /* Try to bind a port on localhost */ + for (port = base_port; port <= last_port; ++port) { + sin.sin_port = htons(port); + if ((bind(sock_fd, (struct sockaddr *)&sin, sizeof(sin))) == -1) { + if (errno == EADDRINUSE || errno == EADDRNOTAVAIL) + continue; + ERRMSG("bind_socket_fd", "bind", errno); + } else if (listen(sock_fd, QUEUE) == -1) { + ERRMSG("bind_socket_fd", "listen", errno); } else { - ERRMSG("init_srs_socket", "bind", errno); - MSG_ERR("srs_sa.sun_path = %s\n", srs_sa.sun_path); + *p_port = port; + ok = 1; + break; } - } else if (chmod(srs_sa.sun_path, S_IRUSR | S_IWUSR) == -1) { - ERRMSG("init_srs_socket", "chmod", errno); - MSG_ERR("srs_sa.sun_path = %s\n", srs_sa.sun_path); - } else if (listen(srs, QUEUE) == -1) { - ERRMSG("init_srs_socket", "listen", errno); + } + if (port > last_port) { + MSG_ERR("Hey! Can't find an available port from %d to %d\n", + base_port, last_port); + } + + return ok ? sock_fd : -1; +} + +/*! Save the current port and a shared secret in a file so dillo can find it. + * \Return: + * \li -1 on failure + */ +int save_comm_keys(int srs_port) +{ + int fd, ret = -1; + char *fname, port_str[32]; + + fname = dStrconcat(dGethomedir(), "/", dotDILLO_DPID_COMM_KEYS, NULL); + fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + dFree(fname); + if (fd == -1) { + MSG("save_comm_keys: open %s\n", dStrerror(errno)); } else { - retval = 1; + snprintf(port_str, 16, "%d %s\n", srs_port, SharedKey); + if (CKD_WRITE(fd, port_str) != -1 && CKD_CLOSE(fd) != -1) { + ret = 1; + } + } + + return ret; +} + +/*! Initialise the service request socket (IDS) + * \Return: + * \li Number of sockets (1 == success) + * \li -1 on failure + */ +int init_ids_srs_socket() +{ + int srs_port, ret = -1; + + FD_ZERO(&sock_set); + + if ((srs_fd = bind_socket_fd(DPID_BASE_PORT, &srs_port)) != -1) { + /* create the shared secret */ + SharedKey = a_Misc_mksecret(8); + /* save port number and SharedKey */ + if (save_comm_keys(srs_port) != -1) { + FD_SET(srs_fd, &sock_set); + ret = 1; + } } - FD_SET(srs, &sock_set); - return (retval); + return ret; } -/*! Initialise a single dpi socket +/*! Initialize a single dpi socket * \Return * \li 1 on success * \li -1 on failure */ -int init_dpi_socket(struct dp *dpi_attr, char *sockdir) +int init_dpi_socket(struct dp *dpi_attr) { - int caught_error = 0, s; - char *dpi_nm; /* pointer to basename in dpi_attr->path */ - struct sockaddr_un sa; - size_t sp_len; - socklen_t addr_sz; - size_t sock_buflen = 8192; - - sp_len = sizeof(sa.sun_path); - if ((s = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) { - ERRMSG("init_all_dpi_sockets", "socket", errno); - return (-1); /* avoids nested ifs */ - } - /* Set the socket FD to close on exec */ - fcntl(s, F_SETFD, FD_CLOEXEC | fcntl(s, F_GETFD)); + int s_fd, port, ret = -1; - /* set some buffering to increase the transfer's speed */ - setsockopt(s, SOL_SOCKET, SO_SNDBUF, - &sock_buflen, (socklen_t)sizeof(sock_buflen)); - - dpi_attr->socket = s; - dpi_attr->sa.sun_family = AF_LOCAL; - dpi_nm = get_basename(dpi_attr->path); - - dpi_attr->sockpath = dStrconcat(sockdir, "/", dpi_nm, "-XXXXXX", NULL); - a_Misc_mkfname(dpi_attr->sockpath); - if (strlen(dpi_attr->sockpath) > sp_len) { - ERRMSG("init_all_dpi_sockets", "socket path is too long", 0); - MSG_ERR("\n - it should be <= %lu chars", (ulong_t)sp_len); - MSG_ERR("\n - socket path = %s\n", dpi_attr->sockpath); - return(-1); - } - strncpy(dpi_attr->sa.sun_path, dpi_attr->sockpath, sp_len); - addr_sz = (socklen_t) D_SUN_LEN(&dpi_attr->sa); - - if ((bind(s, (struct sockaddr *) &dpi_attr->sa, addr_sz)) == -1) { - ERRMSG("init_all_dpi_sockets", "bind", errno); - MSG_ERR("%s\n", dpi_attr->sa.sun_path); - caught_error = 1; - } else if (chmod(dpi_attr->sa.sun_path, S_IRUSR | S_IWUSR) == -1) { - ERRMSG("init_all_dpi_sockets", "chmod", errno); - MSG_ERR("%s\n", dpi_attr->sa.sun_path); - caught_error = 1; - } else if (listen(s, QUEUE) == -1) { - ERRMSG("init_all_dpi_sockets", "listen", errno); - caught_error = 1; - } - - if (caught_error) { - return (-1); - } else { - FD_SET(s, &sock_set); - return (1); + if ((s_fd = bind_socket_fd(DPID_BASE_PORT, &port)) != -1) { + dpi_attr->sock_fd = s_fd; + dpi_attr->port = port; + FD_SET(s_fd, &sock_set); + ret = 1; } + + return ret; } /*! Setup sockets for the plugins and add them to - * to the set of sockets (sock_set) watched by select. + * the set of sockets (sock_set) watched by select. * \Return * \li Number of sockets on success * \li -1 on failure @@ -649,17 +654,13 @@ int init_dpi_socket(struct dp *dpi_attr, char *sockdir) * \Uses * numdpis, srs, srs_name */ -int init_all_dpi_sockets(struct dp *dpi_attr_list, char *sockdir) +int init_all_dpi_sockets(struct dp *dpi_attr_list) { int i; - struct sockaddr_un sa; - size_t sp_len; - - sp_len = sizeof(sa.sun_path); /* Initialise sockets for each dpi */ for (i = 0; i < numdpis; i++) { - if (init_dpi_socket(dpi_attr_list + i, sockdir) == -1) + if (init_dpi_socket(dpi_attr_list + i) == -1) return (-1); numsocks++; } @@ -688,7 +689,7 @@ void handle_sigchld(void) for (i = 0; i < numdpis; i++) { if (waitpid(dpi_attr_list[i].pid, &status, WNOHANG) > 0) { dpi_attr_list[i].pid = 1; - FD_SET(dpi_attr_list[i].socket, &sock_set); + FD_SET(dpi_attr_list[i].sock_fd, &sock_set); numsocks++; } } @@ -714,45 +715,62 @@ void est_dpi_sigchld(void) } } +/*! EINTR aware connect() call */ +int ckd_connect (int sock_fd, struct sockaddr *addr, socklen_t len) +{ + ssize_t ret; + + do { + ret = connect(sock_fd, addr, len); + } while (ret == -1 && errno == EINTR); + if (ret == -1) { + ERRMSG("dpid.c", "connect", errno); + } + return ret; +} + /*! Send DpiBye command to all active non-filter dpis */ void stop_active_dpis(struct dp *dpi_attr_list, int numdpis) { - static char *DpiBye_cmd = NULL; - int i, dpi_socket; - struct sockaddr_un dpi_addr; - struct sockaddr_un sa; - size_t sun_path_len, addr_len; + char *bye_cmd, *auth_cmd; + int i, sock_fd; + struct sockaddr_in sin; - if (!DpiBye_cmd) - DpiBye_cmd = a_Dpip_build_cmd("cmd=%s", "DpiBye"); + bye_cmd = a_Dpip_build_cmd("cmd=%s", "DpiBye"); + auth_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "auth", SharedKey); - sun_path_len = sizeof(sa.sun_path); - addr_len = sizeof(dpi_addr); - - dpi_addr.sun_family = AF_LOCAL; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); for (i = 0; i < numdpis; i++) { /* Skip inactive dpis and filters */ if (dpi_attr_list[i].pid == 1 || dpi_attr_list[i].filter) continue; - if ((dpi_socket = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) { + if ((sock_fd = make_socket_fd()) == -1) { ERRMSG("stop_active_dpis", "socket", errno); + continue; } - if (strlen(dpi_attr_list[i].sockpath) > sun_path_len) { - ERRMSG("stop_active_dpis", "socket path is too long", 0); - MSG_ERR("\n - it should be <= %lu chars",(ulong_t)sun_path_len); - MSG_ERR("\n - socket path = %s\n", dpi_attr_list[i].sockpath); - } - strncpy(dpi_addr.sun_path, dpi_attr_list[i].sockpath, sun_path_len); - if (connect(dpi_socket, (struct sockaddr *) &dpi_addr, addr_len) == -1) { + + sin.sin_port = htons(dpi_attr_list[i].port); + if (ckd_connect(sock_fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { ERRMSG("stop_active_dpis", "connect", errno); - MSG_ERR("%s\n", dpi_addr.sun_path); + MSG_ERR("%s\n", dpi_attr_list[i].path); + } else if (CKD_WRITE(sock_fd, auth_cmd) == -1) { + ERRMSG("stop_active_dpis", "write", errno); + } else if (CKD_WRITE(sock_fd, bye_cmd) == -1) { + ERRMSG("stop_active_dpis", "write", errno); } - (void) write(dpi_socket, DpiBye_cmd, strlen(DpiBye_cmd)); - a_Misc_close_fd(dpi_socket); + a_Misc_close_fd(sock_fd); } + + dFree(auth_cmd); + dFree(bye_cmd); + + /* Allow child dpis some time to read dpid_comm_keys before erasing it */ + sleep (1); } /*! Removes dpis in dpi_attr_list from the @@ -764,8 +782,8 @@ void ignore_dpi_sockets(struct dp *dpi_attr_list, int numdpis) int i; for (i = 0; i < numdpis; i++) { - FD_CLR(dpi_attr_list[i].socket, &sock_set); - a_Misc_close_fd(dpi_attr_list[i].socket); + FD_CLR(dpi_attr_list[i].sock_fd, &sock_set); + a_Misc_close_fd(dpi_attr_list[i].sock_fd); } } @@ -776,20 +794,19 @@ void ignore_dpi_sockets(struct dp *dpi_attr_list, int numdpis) * \Return * Number of available dpis */ -int register_all_cmd(char *sockdir) +int register_all_cmd() { stop_active_dpis(dpi_attr_list, numdpis); - rm_dpi_sockets(dpi_attr_list, numdpis); free_plugin_list(&dpi_attr_list, numdpis); free_services_list(services_list); services_list = NULL; numdpis = 0; numsocks = 1; /* the srs socket */ FD_ZERO(&sock_set); - FD_SET(srs, &sock_set); + FD_SET(srs_fd, &sock_set); numdpis = register_all(&dpi_attr_list); fill_services_list(dpi_attr_list, numdpis, &services_list); - numsocks = init_all_dpi_sockets(dpi_attr_list, sockdir); + numsocks = init_all_dpi_sockets(dpi_attr_list); return (numdpis); } @@ -798,16 +815,16 @@ int register_all_cmd(char *sockdir) * \Return * message on success, NULL on failure */ -char *get_message(int sock, char *dpi_tag) +char *get_message(int sock_fd, char *dpi_tag) { char *msg, *d_cmd; - msg = a_Dpip_get_attr(dpi_tag, strlen(dpi_tag), "msg"); + msg = a_Dpip_get_attr(dpi_tag, "msg"); if (msg == NULL) { ERRMSG("get_message", "failed to parse msg", 0); d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "DpiError", "Failed to parse request"); - (void) CKD_WRITE(sock, d_cmd); + (void) CKD_WRITE(sock_fd, d_cmd); dFree(d_cmd); } return (msg); @@ -832,40 +849,30 @@ int service_match(const struct service *A, const char *B) } /*! - * Send socket path that matches dpi_id to client + * Send socket port that matches dpi_id to client */ -void send_sockpath(int sock, char *dpi_tag, struct dp *dpi_attr_list) +void send_sockport(int sock_fd, char *dpi_tag, struct dp *dpi_attr_list) { int i; - char *dpi_id; - char *d_cmd; + char *dpi_id, *d_cmd, port_str[16]; struct service *serv; - dReturn_if_fail((dpi_id = get_message(sock, dpi_tag)) != NULL); + dReturn_if_fail((dpi_id = get_message(sock_fd, dpi_tag)) != NULL); serv = dList_find_custom(services_list,dpi_id,(dCompareFunc)service_match); if (serv == NULL || (i = serv->dp_index) == -1) for (i = 0; i < numdpis; i++) if (!strncmp(dpi_attr_list[i].id, dpi_id, - dpi_attr_list[i].id - strchr(dpi_attr_list[i].id, '.'))) + dpi_attr_list[i].id - strchr(dpi_attr_list[i].id, '.'))) break; if (i < numdpis) { /* found */ - if (access(dpi_attr_list[i].path, F_OK) == -1) { - ERRMSG("send_sockpath", "access", errno); - MSG_ERR(" - %s\n", dpi_attr_list[i].sockpath); - d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", - "DpiError", "Plugin currently unavailable"); - (void) CKD_WRITE(sock, d_cmd); - dFree(d_cmd); - } else { - d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", - "send_data", dpi_attr_list[i].sockpath); - (void) CKD_WRITE(sock, d_cmd); - dFree(d_cmd); - } + snprintf(port_str, 8, "%d", dpi_attr_list[i].port); + d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "send_data", port_str); + (void) CKD_WRITE(sock_fd, d_cmd); + dFree(d_cmd); } dFree(dpi_id); diff --git a/dpid/dpid.h b/dpid/dpid.h index 74686087..8ef67dd5 100644 --- a/dpid/dpid.h +++ b/dpid/dpid.h @@ -5,42 +5,38 @@ #ifndef DPID_H #define DPID_H -#include <assert.h> -#include <signal.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <stdlib.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <string.h> #include <sys/socket.h> -#include <sys/time.h> +#include <sys/select.h> /* for fd_set */ #include <sys/un.h> -#include <errno.h> +#include <signal.h> /* for sig_atomic_t */ +#include <netinet/in.h> /* for ntohl, IPPORT_USERRESERVED and stuff */ #include "d_size.h" +/* FreeBSD 6.4 doesn't have it */ +#ifndef IPPORT_USERRESERVED + #define IPPORT_USERRESERVED 5000 +#endif #define PATH_LEN 50 #define CMDLEN 20 #define MSGLEN 50 +#define DPID_BASE_PORT (IPPORT_USERRESERVED + 20) + /*! \TODO: Should read this from dillorc */ #define SRS_NAME "dpid.srs" char *srs_name; -/*! dpid service request socket */ -int srs; +/*! dpid's service request socket file descriptor */ +int srs_fd; /*! plugin state information */ struct dp { char *id; char *path; - char *sockpath; - int socket; - struct sockaddr_un sa; + int sock_fd; + int port; pid_t pid; int filter; }; @@ -72,9 +68,7 @@ extern volatile sig_atomic_t caught_sigchld; void rm_dpi_sockets(struct dp *dpi_attr_list, int numdpis); -int rm_inactive_dpi_sockets(struct dp *dpi_attr_list, int numdpis); - -void cleanup(char *socket_dir); +void cleanup(); void free_dpi_attr(struct dp *dpi_attr); @@ -92,11 +86,11 @@ int register_all(struct dp **attlist); int fill_services_list(struct dp *attlist, int numdpis, Dlist **services_list); -int init_srs_socket(char *sockdir); +int init_ids_srs_socket(); -int init_dpi_socket(struct dp *dpi_attr, char *sockdir); +int init_dpi_socket(struct dp *dpi_attr); -int init_all_dpi_sockets(struct dp *dpi_attr_list, char *sockdir); +int init_all_dpi_sockets(struct dp *dpi_attr_list); void dpi_sigchld(int sig); @@ -104,16 +98,18 @@ void handle_sigchld(void); void est_dpi_sigchld(void); +void est_dpi_terminator(void); + void stop_active_dpis(struct dp *dpi_attr_list, int numdpis); void ignore_dpi_sockets(struct dp *dpi_attr_list, int numdpis); -int register_all_cmd(char *sockdir); +int register_all_cmd(); char *get_message(int sock, char *dpi_tag); int service_match(const struct service *A, const char *B); -void send_sockpath(int sock, char * dpi_tag, struct dp *dpi_attr_list); +void send_sockport(int sock_fd, char * dpi_tag, struct dp *dpi_attr_list); #endif diff --git a/dpid/dpid_common.c b/dpid/dpid_common.c index a04d9c4f..a903db95 100644 --- a/dpid/dpid_common.c +++ b/dpid/dpid_common.c @@ -1,5 +1,16 @@ +/* + * File: dpid_common.c + * + * Copyright 2008 Jorge Arellano Cid <jcid@dillo.org> + * + * 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. + */ + +#include <errno.h> #include <stdio.h> -#include <string.h> #include <unistd.h> #include "dpid_common.h" @@ -41,3 +52,22 @@ ssize_t ckd_write(int fd, char *msg, char *file, int line) } return (ret); } + +/*! + * Provides an error checked close() call. + * Call this via the CKD_CLOSE macro + * \return close return value + */ +ssize_t ckd_close(int fd, char *file, int line) +{ + ssize_t ret; + + do { + ret = close(fd); + } while (ret == -1 && errno == EINTR); + if (ret == -1) { + MSG_ERR("%s:%d: close: %s\n", file, line, dStrerror(errno)); + } + return (ret); +} + diff --git a/dpid/dpid_common.h b/dpid/dpid_common.h index 4311a8a8..ed886e19 100644 --- a/dpid/dpid_common.h +++ b/dpid/dpid_common.h @@ -9,9 +9,6 @@ * the next patch */ -#include <stdio.h> -#include <errno.h> -#include <sys/types.h> #include <dirent.h> #include "../dlib/dlib.h" @@ -26,15 +23,18 @@ #define dotDILLO_DPI ".dillo/dpi" #define dotDILLO_DPIDRC ".dillo/dpidrc" +#define dotDILLO_DPID_COMM_KEYS ".dillo/dpid_comm_keys" + #define ERRMSG(CALLER, CALLED, ERR)\ errmsg(CALLER, CALLED, ERR, __FILE__, __LINE__) #define _ERRMSG(CALLER, CALLED, ERR) /*! - * Macro for calling the ckd_write function + * Macros for calling ckd_write and ckd_close functions */ #define CKD_WRITE(fd, msg) ckd_write(fd, msg, __FILE__, __LINE__) +#define CKD_CLOSE(fd) ckd_close(fd, __FILE__, __LINE__) /*! Error codes for dpid */ @@ -57,5 +57,6 @@ void errmsg(char *caller, char *called, int errornum, char *file, int line); int no_dotfiles(const struct dirent *filedat); ssize_t ckd_write(int fd, char *msg, char *file, int line); +ssize_t ckd_close(int fd, char *file, int line); #endif diff --git a/dpid/dpidc b/dpid/dpidc deleted file mode 100644 index 88b887cb..00000000 --- a/dpid/dpidc +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/perl -w -# Author: Ferdi Franceschini -# -# dpid control program -# Currently allows -# register: Tells dpid to register all available dpis -# stop: Stops dpid. - -use strict; -use IO::Socket::UNIX; - -# Get socket directory name -open(DSD, "<$ENV{HOME}/.dillo/dpi_socket_dir"); -my $dir = <DSD>; -close(DSD); - -my $socket = IO::Socket::UNIX->new(Peer => "$dir/dpid.srs", Type => SOCK_STREAM, Timeout => 1000 ) or die "new: $@"; - -$socket->autoflush(1); - -my %dpi_command = ( - "register" => "<dpi cmd='register_all' '>", - "stop" => "<dpi cmd='DpiBye' '>", - ); - -if ( exists($dpi_command{$ARGV[0]}) ) { - print $socket $dpi_command{$ARGV[0]}; -} else { - close($socket); - print "Usage: dpidc register|stop\n"; -} diff --git a/dpid/dpidc.c b/dpid/dpidc.c new file mode 100644 index 00000000..61a91275 --- /dev/null +++ b/dpid/dpidc.c @@ -0,0 +1,121 @@ +#include <stdio.h> +#include <stdlib.h> /* for exit */ +#include <string.h> /* for bzero */ +#include <unistd.h> /* for read and write */ +#include <ctype.h> /* for isxdigit */ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <errno.h> + +#include "../dpip/dpip.h" + +#define MSG_ERR(...) printf("** ERROR **: " __VA_ARGS__); + +char *CMD_REGISTER = "<cmd='register_all' '>"; +char *CMD_STOP = "<cmd='DpiBye' '>"; + +static char SharedKey[32]; + +static void print_usage(const char *prgname) +{ + fprintf(stderr,"Control program for the Dillo plugin daemon\n" + "Usage: %s {stop|register|chat}\n\n", prgname); +} + +static void error(char *msg) +{ + perror(msg); + exit(1); +} + +/* + * Read dpid's communication keys from its saved file. + * Return value: 1 on success, -1 on error. + */ +static int Dpi_read_comm_keys(int *port) +{ + FILE *In; + char *fname, *rcline = NULL, *tail; + int i, ret = -1; + + fname = dStrconcat(dGethomedir(), "/.dillo/dpid_comm_keys", NULL); + if ((In = fopen(fname, "r")) == NULL) { + MSG_ERR("[Dpi_read_comm_keys] %s\n", dStrerror(errno)); + } else if ((rcline = dGetline(In)) == NULL) { + MSG_ERR("[Dpi_read_comm_keys] empty file: %s\n", fname); + } else { + *port = strtol(rcline, &tail, 10); + for (i = 0; *tail && isxdigit(tail[i+1]); ++i) + SharedKey[i] = tail[i+1]; + SharedKey[i] = 0; + ret = 1; + } + dFree(rcline); + dFree(fname); + + return ret; +} + +int main(int argc, char *argv[]) +{ + int sockfd, portno, n; + struct sockaddr_in serv_addr; + char buffer[256]; + + if (argc != 2) { + print_usage(argv[0]); + exit(1); + } + + /* Read dpid's port number from saved file */ + if (Dpi_read_comm_keys(&portno) == -1) { + MSG_ERR("main: Can't read dpid's port number\n"); + exit(1); + } + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + error("ERROR opening socket"); + bzero((char *) &serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + serv_addr.sin_port = htons(portno); + if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + error("ERROR connecting"); + + snprintf(buffer, sizeof(buffer), "<cmd='auth' msg='%s' '>", SharedKey); + n = write(sockfd, buffer, strlen(buffer)); + if (n < 0) + error("ERROR writing to socket"); + + if (strcmp(argv[1], "stop") == 0) { + strcpy(buffer, CMD_STOP); + } else if (strcmp(argv[1], "register") == 0) { + strcpy(buffer, CMD_REGISTER); + } else if (strcmp(argv[1], "chat") == 0) { + printf("Please enter the message: "); + bzero(buffer,256); + if (fgets(buffer,255,stdin) == NULL) + MSG_ERR("dpidc: Can't read the message\n"); + } else { + MSG_ERR("main: Unknown operation '%s'\n", argv[1]); + print_usage(argv[0]); + exit(1); + } + + n = write(sockfd,buffer,strlen(buffer)); + if (n < 0) + error("ERROR writing to socket"); +/* + bzero(buffer,256); + n = read(sockfd,buffer,255); + if (n < 0) + error("ERROR reading from socket"); + printf("%s\n",buffer); +*/ + close(sockfd); + return 0; +} diff --git a/dpid/dpidrc.in b/dpid/dpidrc.in new file mode 100644 index 00000000..23374d96 --- /dev/null +++ b/dpid/dpidrc.in @@ -0,0 +1,6 @@ +dpi_dir=@libdir@/dillo/dpi + +proto.file=file/file.dpi +proto.ftp=ftp/ftp.filter.dpi +proto.https=https/https.filter.dpi +proto.data=datauri/datauri.filter.dpi diff --git a/dpid/main.c b/dpid/main.c index b47ca627..5f512245 100644 --- a/dpid/main.c +++ b/dpid/main.c @@ -12,16 +12,15 @@ 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <errno.h> -#include <unistd.h> -#include <limits.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <assert.h> +#include <errno.h> /* for ckd_write */ +#include <unistd.h> /* for ckd_write */ +#include <stdlib.h> /* for exit */ +#include <assert.h> /* for assert */ +#include <sys/stat.h> /* for umask */ + #include "dpid_common.h" #include "dpid.h" #include "dpi.h" @@ -46,7 +45,7 @@ static int start_filter_plugin(struct dp dpi_attr) csz = (socklen_t) sizeof(clnt_addr); - newsock = accept(dpi_attr.socket, (struct sockaddr *) &clnt_addr, &csz); + newsock = accept(dpi_attr.sock_fd, (struct sockaddr *) &clnt_addr, &csz); if (newsock == -1) ERRMSG("start_plugin", "accept", errno); @@ -69,7 +68,7 @@ static int start_filter_plugin(struct dp dpi_attr) } if (pid == 0) { /* Child, start plugin */ - if (execl(dpi_attr.path, dpi_attr.path, NULL) == -1) { + if (execl(dpi_attr.path, dpi_attr.path, (char*)NULL) == -1) { ERRMSG("start_plugin", "execl", errno); MSG_ERR("ERROR in child proc for %s\n", dpi_attr.path); exit(1); @@ -91,17 +90,17 @@ static int start_filter_plugin(struct dp dpi_attr) static void start_server_plugin(struct dp dpi_attr) { - if (dup2(dpi_attr.socket, STDIN_FILENO) == -1) { + if (dup2(dpi_attr.sock_fd, STDIN_FILENO) == -1) { ERRMSG("start_plugin", "dup2", errno); MSG_ERR("ERROR in child proc for %s\n", dpi_attr.path); exit(1); } - if (a_Misc_close_fd(dpi_attr.socket) == -1) { + if (a_Misc_close_fd(dpi_attr.sock_fd) == -1) { ERRMSG("start_plugin", "close", errno); MSG_ERR("ERROR in child proc for %s\n", dpi_attr.path); exit(1); } - if (execl(dpi_attr.path, dpi_attr.path, NULL) == -1) { + if (execl(dpi_attr.path, dpi_attr.path, (char*)NULL) == -1) { ERRMSG("start_plugin", "execl", errno); MSG_ERR("ERROR in child proc for %s\n", dpi_attr.path); exit(1); @@ -113,32 +112,15 @@ static void start_server_plugin(struct dp dpi_attr) * \Return * pointer to dynamically allocated request tag */ -static char *get_request(int sock) +static char *get_request(Dsh *sh) { - char *req, buf[10]; - size_t buflen; - size_t rqsz; - ssize_t rdln; - - req = NULL; - buf[0] = '\0'; - buflen = sizeof(buf) / sizeof(buf[0]); + char *dpip_tag; (void) sigprocmask(SIG_BLOCK, &mask_sigchld, NULL); - for (rqsz = 0; (rdln = read(sock, buf, buflen)) != 0; rqsz += rdln) { - if (rdln == -1) - break; - req = (char *) realloc(req, rqsz + rdln + 1); - if (rqsz == 0) - req[0] = '\0'; - strncat(req, buf, (size_t) rdln); - } + dpip_tag = a_Dpip_dsh_read_token(sh, 1); (void) sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL); - if (rdln == -1) { - ERRMSG("get_request", "read", errno); - } - return (req); + return dpip_tag; } /*! @@ -146,7 +128,7 @@ static char *get_request(int sock) * \Return * command code on success, -1 on failure */ -static int get_command(int sock, char *dpi_tag) +static int get_command(Dsh *sh, char *dpi_tag) { char *cmd, *d_cmd; int COMMAND; @@ -156,16 +138,18 @@ static int get_command(int sock, char *dpi_tag) return (-1); } - cmd = a_Dpip_get_attr(dpi_tag, strlen(dpi_tag), "cmd"); + cmd = a_Dpip_get_attr(dpi_tag, "cmd"); if (cmd == NULL) { ERRMSG("get_command", "a_Dpip_get_attr", 0); MSG_ERR(": dpid failed to parse cmd in %s\n", dpi_tag); d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "DpiError", "Failed to parse request"); - (void) CKD_WRITE(sock, d_cmd); + a_Dpip_dsh_write_str(sh, 1, d_cmd); dFree(d_cmd); COMMAND = -1; + } else if (strcmp("auth", cmd) == 0) { + COMMAND = AUTH_CMD; } else if (strcmp("DpiBye", cmd) == 0) { COMMAND = BYE_CMD; } else if (strcmp("check_server", cmd) == 0) { @@ -221,7 +205,6 @@ static int get_open_max(void) int main(void) { int i, n = 0, open_max; - char *dirname = NULL, *sockdir = NULL; int dpid_idle_timeout = 60 * 60; /* default, in seconds */ struct timeval select_timeout; sigset_t mask_none; @@ -251,6 +234,7 @@ int main(void) /* Get list of available dpis */ numdpis = register_all(&dpi_attr_list); +#if 0 /* Get name of socket directory */ dirname = a_Dpi_sockdir_file(); if ((sockdir = init_sockdir(dirname)) == NULL) { @@ -258,14 +242,16 @@ int main(void) MSG_ERR("Failed to create socket directory\n"); exit(1); } +#endif /* Init and get services list */ fill_services_list(dpi_attr_list, numdpis, &services_list); /* Remove any sockets that may have been leftover from a crash */ - cleanup(sockdir); + //cleanup(); + /* Initialise sockets */ - if ((numsocks = init_srs_socket(sockdir)) == -1) { + if ((numsocks = init_ids_srs_socket()) == -1) { switch (dpi_errno) { case dpid_srs_addrinuse: MSG_ERR("dpid refuses to start, possibly because:\n"); @@ -273,12 +259,13 @@ int main(void) MSG_ERR("\t2) A previous dpid didn't clean up on exit.\n"); exit(1); default: - ERRMSG("main", "init_srs_sockets failed", 0); + //ERRMSG("main", "init_srs_socket failed", 0); + ERRMSG("main", "init_ids_srs_socket failed", 0); exit(1); } } - numsocks = init_all_dpi_sockets(dpi_attr_list, sockdir); - //est_terminator(); /* Do we still want to clean up on an abnormal exit? */ + numsocks = init_all_dpi_sockets(dpi_attr_list); + est_dpi_terminator(); est_dpi_sigchld(); (void) sigemptyset(&mask_sigchld); @@ -309,7 +296,7 @@ int main(void) continue; stop_active_dpis(dpi_attr_list, numdpis); - cleanup(sockdir); + //cleanup(); exit(0); } } while (n == -1 && errno == EINTR); @@ -319,42 +306,51 @@ int main(void) exit(1); } /* If the service req socket is selected then service the req. */ - if (FD_ISSET(srs, &selected_set)) { - int sock; - socklen_t csz; - struct sockaddr_un clnt_addr; + if (FD_ISSET(srs_fd, &selected_set)) { + int sock_fd; + socklen_t sin_sz; + struct sockaddr_in sin; char *req = NULL; --n; assert(n >= 0); - csz = (socklen_t) sizeof(clnt_addr); - sock = accept(srs, (struct sockaddr *) &clnt_addr, &csz); - if (sock == -1) { + sin_sz = (socklen_t) sizeof(sin); + sock_fd = accept(srs_fd, (struct sockaddr *)&sin, &sin_sz); + if (sock_fd == -1) { ERRMSG("main", "accept", errno); MSG_ERR("accept on srs socket failed\n"); MSG_ERR("service pending connections, and continue\n"); } else { int command; + Dsh *sh; - req = get_request(sock); - command = get_command(sock, req); + sh = a_Dpip_dsh_new(sock_fd, sock_fd, 1024); +read_next: + req = get_request(sh); + command = get_command(sh, req); switch (command) { + case AUTH_CMD: + if (a_Dpip_check_auth(req) != -1) { + dFree(req); + goto read_next; + } + break; case BYE_CMD: stop_active_dpis(dpi_attr_list, numdpis); - cleanup(sockdir); + //cleanup(); exit(0); break; case CHECK_SERVER_CMD: - send_sockpath(sock, req, dpi_attr_list); + send_sockport(sock_fd, req, dpi_attr_list); break; case REGISTER_ALL_CMD: - register_all_cmd(sockdir); + register_all_cmd(); break; case UNKNOWN_CMD: { char *d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "DpiError", "Unknown command"); - (void) CKD_WRITE(sock, d_cmd); + (void) CKD_WRITE(sock_fd, d_cmd); dFree(d_cmd); ERRMSG("main", "Unknown command", 0); MSG_ERR(" for request: %s\n", req); @@ -366,14 +362,15 @@ int main(void) } if (req) free(req); - a_Misc_close_fd(sock); + a_Dpip_dsh_close(sh); + a_Dpip_dsh_free(sh); } } /* While there's a request on one of the plugin sockets * find the matching plugin and start it. */ for (i = 0; n > 0 && i < numdpis; i++) { - if (FD_ISSET(dpi_attr_list[i].socket, &selected_set)) { + if (FD_ISSET(dpi_attr_list[i].sock_fd, &selected_set)) { --n; assert(n >= 0); @@ -387,11 +384,12 @@ int main(void) * on its socket */ numsocks--; assert(numsocks >= 0); - FD_CLR(dpi_attr_list[i].socket, &sock_set); + FD_CLR(dpi_attr_list[i].sock_fd, &sock_set); if ((dpi_attr_list[i].pid = fork()) == -1) { ERRMSG("main", "fork", errno); /* exit(1); */ } else if (dpi_attr_list[i].pid == 0) { + /* child */ (void) sigprocmask(SIG_SETMASK, &mask_none, NULL); start_server_plugin(dpi_attr_list[i]); } diff --git a/dpid/misc_new.c b/dpid/misc_new.c index f85f43e4..7f963aed 100644 --- a/dpid/misc_new.c +++ b/dpid/misc_new.c @@ -1,17 +1,23 @@ -#include <stdio.h> -#include <time.h> -#include <stdlib.h> -#include <string.h> +/* + * File: misc_new.c + * + * Copyright 2008 Jorge Arellano Cid <jcid@dillo.org> + * + * 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. + */ + +#include <errno.h> /* errno, err-codes */ #include <unistd.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <errno.h> -#include <fcntl.h> -#include "d_size.h" -#include "misc_new.h" -#include "dpid_common.h" +#include <time.h> +#include <sys/stat.h> /* stat */ +#include <stdlib.h> /* rand, srand */ -#include "misc_new.h" /* for function prototypes */ +#include "../dlib/dlib.h" +#include "dpid_common.h" +#include "misc_new.h" /* for function prototypes */ /* @@ -159,7 +165,7 @@ char *a_Misc_mkfname(char *template) { char *tmp = template + strlen(template) - 6; int i; - unsigned int random; + uint_t random; struct stat stat_buf; if (tmp < template) @@ -185,3 +191,26 @@ char *a_Misc_mkfname(char *template) MSG_ERR("a_Misc_mkfname: another round for %s \n", template); } } + +/* + * Return a new, random hexadecimal string of 'nchar' characters. + */ +char *a_Misc_mksecret(int nchar) +{ + int i; + uint_t random; + char *secret = dNew(char, nchar + 1); + + srand((uint_t)(time(0) ^ getpid())); + random = (unsigned) rand(); + for (i = 0; i < nchar; ++i) { + int hexdigit = (random >> (i * 5)) & 0x0f; + + secret[i] = hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0'; + } + secret[i] = 0; + MSG("a_Misc_mksecret: %s\n", secret); + + return secret; +} + diff --git a/dpid/misc_new.h b/dpid/misc_new.h index e2bf6e9a..325451a1 100644 --- a/dpid/misc_new.h +++ b/dpid/misc_new.h @@ -1,13 +1,12 @@ #ifndef MISC_NEW_H #define MISC_NEW_H -#include "../dlib/dlib.h" - int a_Misc_close_fd(int fd); Dstr *a_Misc_rdtag(int socket); char *a_Misc_readtag(int sock); char *a_Misc_mkdtemp(char *template); char *a_Misc_mkfname(char *template); +char *a_Misc_mksecret(int nchar); #endif |