X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fnet.c;h=2e06a39e30b11afd75e9073087da30fac980c20e;hb=aa755206da4bcce3261ecd5dbfa41570a0155c73;hp=a4324a4774fc4b537b6ea37c4d0eed98eaabc9ac;hpb=698191fd2f512f3618e2d60592fcd57cd750b965;p=meshlink diff --git a/src/net.c b/src/net.c index a4324a47..2e06a39e 100644 --- a/src/net.c +++ b/src/net.c @@ -17,31 +17,47 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net.c,v 1.35.4.67 2000/11/04 22:57:30 guus Exp $ + $Id: net.c,v 1.35.4.74 2000/11/15 22:07:36 zarq Exp $ */ #include "config.h" -#include #include #include -#include -#include #include #include #include #include #include #include -#include #include #include #include #include #include -#include -#include -#include +/* SunOS really wants sys/socket.h BEFORE net/if.h, + and FreeBSD wants these lines below the rest. */ +#include +#include +#include + +#ifdef HAVE_OPENSSL_RAND_H +# include +#else +# include +#endif + +#ifdef HAVE_OPENSSL_EVP_H +# include +#else +# include +#endif + +#ifdef HAVE_OPENSSL_ERR_H +# include +#else +# include +#endif #ifdef HAVE_TUNTAP #include LINUX_IF_TUN_H @@ -52,6 +68,7 @@ #include "conf.h" #include "connlist.h" +#include "list.h" #include "meta.h" #include "net.h" #include "netutl.h" @@ -74,56 +91,72 @@ int keylifetime = 0; int keyexpires = 0; char *unknown = NULL; -char *interface_name = NULL; /* Contains the name of the interface */ subnet_t mymac; -/* - Execute the given script. - This function doesn't really belong here. -*/ -int execute_script(const char* name) +list_t *child_pids; + +void _execute_script(const char *name) { + int error = 0; char *scriptname; - pid_t pid; char *s; + int fd; - if((pid = fork()) < 0) + if(netname) { - syslog(LOG_ERR, _("System call `%s' failed: %m"), - "fork"); - return -1; + asprintf(&s, "NETNAME=%s", netname); + putenv(s); /* Don't free s! see man 3 putenv */ } - - if(pid) +#ifdef HAVE_UNSETENV + else { - return 0; + unsetenv("NETNAME"); } +#endif - /* Child here */ + if(chdir(confbase) < 0) + /* This cannot fail since we already read config files from this + directory. - Guus */ + /* Yes this can fail, somebody could have removed this directory + when we didn't pay attention. - Ivo */ + { + if(chdir("/") < 0) + /* Now if THIS fails, something wicked is going on. - Ivo */ + syslog(LOG_ERR, _("Couldn't chdir to `/': %m")); + /* Continue anyway. */ + } + asprintf(&scriptname, "%s/%s", confbase, name); - asprintf(&s, "IFNAME=%s", interface_name); - putenv(s); - free(s); - if(netname) - { - asprintf(&s, "NETNAME=%s", netname); - putenv(s); - free(s); - } - else + /* Close all file descriptors */ + closelog(); + fcloseall(); + + /* Open standard input */ + if(open("/dev/null", O_RDONLY) < 0) { - unsetenv("NETNAME"); + syslog(LOG_ERR, _("Opening `/dev/null' failed: %m")); + error = 1; } - if(chdir(confbase) < 0) + if(!error) { - syslog(LOG_ERR, _("Couldn't chdir to `%s': %m"), - confbase); + /* Standard output directly goes to syslog */ + openlog(name, LOG_CONS | LOG_PID, LOG_DAEMON); + /* Standard error as well */ + if(dup2(1, 2) < 0) + { + syslog(LOG_ERR, _("System call `%s' failed: %m"), + "dup2"); + error = 1; + } } + if(error && debug_lvl > 1) + syslog(LOG_INFO, _("This means that any output the script generates will not be shown in syslog.")); + execl(scriptname, NULL); /* No return on success */ @@ -134,6 +167,61 @@ int execute_script(const char* name) exit(0); } +/* + Execute the given script. + This function doesn't really belong here. +*/ +int execute_script(const char *name) +{ + pid_t pid; + + if((pid = fork()) < 0) + { + syslog(LOG_ERR, _("System call `%s' failed: %m"), + "fork"); + return -1; + } + + if(pid) + { + list_append(child_pids, pid); + return 0; + } + + /* Child here */ + + _execute_script(name); +} + +int check_child(void *data) +{ + pid_t pid; + int status; + + pid = (pid_t) data; + pid = waitpid(pid, &status, WNOHANG); + if(WIFEXITED(status)) + { + if(WIFSIGNALED(status)) /* Child was killed by a signal */ + { + syslog(LOG_ERR, _("Child with PID %d was killed by signal %d (%s)"), + pid, WTERMSIG(status), strsignal(WTERMSIG(status))); + return -1; + } + if(WEXITSTATUS(status) != 0) + { + syslog(LOG_INFO, _("Child with PID %d exited with code %d"), + WEXITSTATUS(status)); + } + return -1; + } +} + +void check_children(void) +{ + list_forall_nodes(child_pids, check_child); +} + int xsend(conn_list_t *cl, vpn_packet_t *inpkt) { vpn_packet_t outpkt; @@ -463,18 +551,11 @@ cp strncpy(ifr.ifr_name, netname, IFNAMSIZ); cp if (!ioctl(tap_fd, TUNSETIFF, (void *) &ifr)) - { + { syslog(LOG_INFO, _("%s is a new style tun/tap device"), tapfname); taptype = TAP_TYPE_TUNTAP; } #endif - - /* Add name of network interface to environment (for scripts) */ - - ioctl(tap_fd, SIOCGIFNAME, (void *) &ifr); - interface_name = xmalloc(strlen(ifr.ifr_name)); - strcpy(interface_name, ifr.ifr_name); - cp return 0; } @@ -498,6 +579,7 @@ cp if(setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { + close(nfd); syslog(LOG_ERR, _("System call `%s' failed: %m"), "setsockopt"); return -1; @@ -505,6 +587,7 @@ cp if(setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one))) { + close(nfd); syslog(LOG_ERR, _("System call `%s' failed: %m"), "setsockopt"); return -1; @@ -513,6 +596,7 @@ cp flags = fcntl(nfd, F_GETFL); if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { + close(nfd); syslog(LOG_ERR, _("System call `%s' failed: %m"), "fcntl"); return -1; @@ -522,6 +606,7 @@ cp { if(setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, cfg->data.ptr, strlen(cfg->data.ptr))) { + close(nfd); syslog(LOG_ERR, _("Unable to bind listen socket to interface %s: %m"), cfg->data.ptr); return -1; } @@ -538,12 +623,14 @@ cp if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr))) { + close(nfd); syslog(LOG_ERR, _("Can't bind to port %hd/tcp: %m"), port); return -1; } if(listen(nfd, 3)) { + close(nfd); syslog(LOG_ERR, _("System call `%s' failed: %m"), "listen"); return -1; @@ -564,12 +651,14 @@ int setup_vpn_in_socket(int port) cp if((nfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + close(nfd); syslog(LOG_ERR, _("Creating socket failed: %m")); return -1; } if(setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { + close(nfd); syslog(LOG_ERR, _("System call `%s' failed: %m"), "setsockopt"); return -1; @@ -578,6 +667,7 @@ cp flags = fcntl(nfd, F_GETFL); if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { + close(nfd); syslog(LOG_ERR, _("System call `%s' failed: %m"), "fcntl"); return -1; @@ -590,6 +680,7 @@ cp if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr))) { + close(nfd); syslog(LOG_ERR, _("Can't bind to port %hd/udp: %m"), port); return -1; } @@ -628,6 +719,7 @@ cp if(connect(cl->meta_socket, (struct sockaddr *)&a, sizeof(a)) == -1) { + close(cl->meta_socket); syslog(LOG_ERR, _("%s port %hd: %m"), cl->hostname, cl->port); return -1; } @@ -635,6 +727,7 @@ cp flags = fcntl(cl->meta_socket, F_GETFL); if(fcntl(cl->meta_socket, F_SETFL, flags | O_NONBLOCK) < 0) { + close(cl->meta_socket); syslog(LOG_ERR, _("fcntl for %s port %d: %m"), cl->hostname, cl->port); return -1; @@ -838,6 +931,8 @@ cp myself->status.active = 1; syslog(LOG_NOTICE, _("Ready: listening on port %hd"), myself->port); + + child_pids = list_new(); cp return 0; } @@ -977,6 +1072,7 @@ cp if(setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { + close(nfd); syslog(LOG_ERR, _("System call `%s' failed: %m"), "setsockopt"); return -1; @@ -985,6 +1081,7 @@ cp flags = fcntl(nfd, F_GETFL); if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { + close(nfd); syslog(LOG_ERR, _("System call `%s' failed: %m"), "fcntl"); return -1; @@ -997,6 +1094,7 @@ cp if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr))) { + close(nfd); syslog(LOG_ERR, _("Can't bind to port %hd/udp: %m"), myself->port); return -1; } @@ -1007,6 +1105,7 @@ cp if(connect(nfd, (struct sockaddr *)&a, sizeof(a)) == -1) { + close(nfd); syslog(LOG_ERR, _("Connecting to %s port %d failed: %m"), cl->hostname, cl->port); return -1; @@ -1015,6 +1114,7 @@ cp flags = fcntl(nfd, F_GETFL); if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { + close(nfd); syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m %s (%s)"), __FILE__, __LINE__, nfd, cl->name, cl->hostname); return -1; @@ -1038,7 +1138,7 @@ conn_list_t *create_new_connection(int sfd) cp p = new_conn_list(); - if(getpeername(sfd, &ci, &len) < 0) + if(getpeername(sfd, (struct sockaddr *) &ci, (socklen_t *) &len) < 0) { syslog(LOG_ERR, _("System call `%s' failed: %m"), "getpeername"); @@ -1421,6 +1521,8 @@ cp if(FD_ISSET(tap_fd, &fset)) handle_tap_input(); } + + check_children(); } cp }