]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Merge pull request #1230 from SaberUK/insp20+ipcache
authorAttila Molnar <attilamolnar@hush.com>
Wed, 17 May 2017 21:41:32 +0000 (23:41 +0200)
committerGitHub <noreply@github.com>
Wed, 17 May 2017 21:41:32 +0000 (23:41 +0200)
[2.0] Invalidate the caches properly when User::SetClientIP is called.

17 files changed:
.travis.yml
configure
docs/conf/modules.conf.example
include/base.h
make/calcdep.pl
modulemanager
src/commands/cmd_who.cpp
src/modules/extra/m_ldapauth.cpp
src/modules/m_cgiirc.cpp
src/modules/m_cloaking.cpp
src/modules/m_dnsbl.cpp
src/modules/m_httpd_stats.cpp
src/modules/m_spanningtree/protocolinterface.cpp
src/socketengines/socketengine_epoll.cpp
src/users.cpp
tools/travis-ci.sh
win/CMakeLists.txt

index 6318025264161fb6087d974fd0b5b75a49a4587f..bb82add9b681014f029101c3e75a69201a3d26d2 100644 (file)
@@ -1,12 +1,13 @@
 compiler:
-  - "clang"
-  - "gcc"
-language: "cpp"
+  - clang
+  - gcc
+dist: trusty
+env:
+  - PURE_STATIC=1
+  -
+language: cpp
 notifications:
   email: false
-os:
-  - "linux"
-  - "osx"
 script:
-  - "sh ./tools/travis-ci.sh"
+  - sh ./tools/travis-ci.sh
 sudo: required
index e8c3deb0d168dd60cae77ca41a228c5bd3f1de00..b380b5700046cad908714e057d3370ae2cc080e4 100755 (executable)
--- a/configure
+++ b/configure
@@ -28,6 +28,7 @@
 
 BEGIN {
        require 5.8.0;
+       push @INC, '.';
 }
 
 use strict;
@@ -268,10 +269,9 @@ if (defined $opt_cc)
 {
        $config{CC} = $opt_cc;
 }
-our $exec = $config{CC} . " -dumpversion | cut -c 1";
-chomp($config{GCCVER}          = `$exec`);                             # Major GCC Version
-$exec = $config{CC} . " -dumpversion | cut -c 3";
-chomp($config{GCCMINOR}                = `$exec`);
+`$config{CC} -dumpversion` =~ /^(\d+)(?:\.(\d+))?/;
+$config{GCCVER} = defined $1 ? $1 : '';
+$config{GCCMINOR} = defined $2 ? $2 : '0';
 $config{MAXBUF}                        = "512";                                # Max buffer size
 
 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)(?:[a-z])?(?:\-[a-z][0-9])?/) {
@@ -347,10 +347,9 @@ print ($cache_loaded ? "found\n" : "not found\n");
 $config{SYSTEM} = lc $^O;
 print "Checking operating system version... $config{SYSTEM}\n";
 
-$exec = $config{CC} . " -dumpversion | cut -c 1";
-chomp($config{GCCVER}          = `$exec`);                             # Major GCC Version
-$exec = $config{CC} . " -dumpversion | cut -c 3";
-chomp($config{GCCMINOR}                = `$exec`);
+`$config{CC} -dumpversion` =~ /^(\d+)(?:\.(\d+))?/;
+$config{GCCVER} = defined $1 ? $1 : '';
+$config{GCCMINOR} = defined $2 ? $2 : '0';
 
 printf "Checking if stdint.h exists... ";
 $config{HAS_STDINT} = test_compile('stdint');
@@ -488,8 +487,9 @@ should NOT be used. You should probably specify a newer compiler.\n\n";
                        }
                        chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
                        if ($foo ne "") {
-                               chomp($config{GCCVER}       = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
-                               chomp($config{GCCMINOR}     = `$config{CC} -dumpversion | cut -c 3`);
+                               `$config{CC} -dumpversion` =~ /^(\d+)(?:\.(\d+))?/;
+                               $config{GCCVER} = defined $1 ? $1 : '';
+                               $config{GCCMINOR} = defined $2 ? $2 : '0';
                                print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
                                if ($config{GCCVER} < 3) {
                                        print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
@@ -839,8 +839,8 @@ sub writefiles {
                open(FILEHANDLE, ">include/inspircd_config.h.tmp");
                print FILEHANDLE <<EOF;
 /* Auto generated by configure, do not modify! */
-#ifndef __CONFIGURATION_AUTO__
-#define __CONFIGURATION_AUTO__
+#ifndef INSPIRCD_CONFIG_H
+#define INSPIRCD_CONFIG_H
 
 /* this is for windows support. */
 #define CoreExport /**/
@@ -876,6 +876,10 @@ print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
                }
                if ($config{OSNAME} !~ /DARWIN/i) {
                        print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
+               } else {
+                       print FILEHANDLE "#ifdef MAC_OS_X_VERSION_10_12\n";
+                       print FILEHANDLE "# define HAS_CLOCK_GETTIME\n";
+                       print FILEHANDLE "#endif\n";
                }
                my $use_hiperf = 0;
                if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
index 97d69da90477b77dac16bae68e3d2419d1bc0c5a..003b4d04ba5b7949600fc9abc224f9975ce4134d 100644 (file)
 
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 # Chanprotect module: Gives +q and +a channel modes.
+#
+# IMPORTANT: This module has been removed in the next major version of
+# InspIRCd. You should use m_customprefix instead.
 #<module name="m_chanprotect.so">
 
 <chanprotect
 # key3, key4; the values must be less than 0x80000000 and should be   #
 # picked at random. Prefix is mandatory, will default to network name #
 # if not specified, and will always have a "-" appended.              #
+#                                                                     #
+# IMPORTANT: The compat-host and compat-ip modes have been removed in #
+# the next major version of InspIRCd. You should ONLY use them if you #
+# need backwards compatibility with InspIRCd 1.2.                     #
 #
 #<cloak mode="half"
 #       key="secret"
 
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 # Halfop module: Provides the +h (halfops) channel status mode.
+#
+# IMPORTANT: This module has been removed in the next major version of
+# InspIRCd. You should use m_customprefix instead.
 #<module name="m_halfop.so">
 
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 #           binddn="cn=Manager,dc=brainbox,dc=cc"                     #
 #           bindauth="mysecretpass"                                   #
 #           verbose="yes"                                             #
-#           host="$uid.$ou.inspircd.org">                             #
+#           host="$uid.$ou.inspircd.org"                              #
+#           useusername="no">                                         #
 #                                                                     #
 # <ldapwhitelist cidr="10.42.0.0/16">                                 #
 #                                                                     #
 # The attribute value indicates the attribute which is used to locate #
 # a user account by name. On POSIX systems this is usually 'uid'.     #
 #                                                                     #
+# The useusername setting chooses whether the user's username or      #
+# nickname is used when locating a user account, if a username isn't  #
+# provided in PASS.                                                   #
+#                                                                     #
 # The server parameter indicates the LDAP server to connect to. The   #
 # ldap:// style scheme before the hostname proper is MANDATORY.       #
 #                                                                     #
 #
 #-#-#-#-#-#-#-#-#-# SECURELIST CONFIGURATION -#-#-#-#-#-#-#-#-#-#-#-#-#
 #                                                                     #
-# Securelist can be harmful to some IRC search engines such as        #
-# netsplit.de and searchirc.com. To prevent securelist blocking these #
-# sites from listing, define exception tags as shown below:           #
-#<securehost exception="*@*.searchirc.org">
+# Securelist can be harmful to some IRC search engines. To prevent    #
+# securelist blocking these sites from listing, define exception tags #
+# as shown below:                                                     #
 #<securehost exception="*@*.netsplit.de">
-#<securehost exception="*@echo940.server4you.de">
 #<securehost exception="*@*.ircdriven.com">
+#<securehost exception="*@*.irc-source.com">
 #                                                                     #
 # Define the following variable to change how long a user must wait   #
 # before issuing a LIST. If not defined, defaults to 60 seconds.      #
 # SSL channel mode module: Adds support for SSL-only channels via
 # channel mode +z and the 'z' extban which matches SSL client
 # certificate fingerprints.
-# Does not do anything useful without a working SSL module (see below).
+# Does not do anything useful without a working SSL module and the
+# m_sslinfo module (see below).
 #<module name="m_sslmodes.so">
 
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
index 0a4456f3a7fd398c2aea015b38dc88c76a5d5ded..19222a6f5d2ac4ac592ae84797c7044c31d7a1a1 100644 (file)
@@ -201,7 +201,7 @@ class CoreExport CoreException : public std::exception
         * Actually no, it does nothing. Never mind.
         * @throws Nothing!
         */
-       virtual ~CoreException() throw() {};
+       virtual ~CoreException() throw() {}
        /** Returns the reason for the exception.
         * The module should probably put something informative here as the user will see this upon failure.
         */
index 4a759a24a163692ca19682cad0abb44ecc7ff11c..49506dd3be8fe35c05251bad55f477c582880e9b 100755 (executable)
@@ -160,7 +160,7 @@ END
 obj/ld-extra.cmd: $core_src
        \@\$(SOURCEPATH)/make/unit-cc.pl gen-ld\$(VERBOSE) \$\@ \$^ \$>
 
-bin/inspircd: obj/ld-extra.cmd $core_mk
+bin/inspircd: $core_mk obj/ld-extra.cmd
        \@\$(SOURCEPATH)/make/unit-cc.pl static-ld\$(VERBOSE) \$\@ \$^ \$>
 
 inspircd: bin/inspircd
index af5bf113caa6f75b1d16b43bfbb5c8b74d193bb0..b107f2c1fad62032d1b07dd6fd60de7e8374859e 100755 (executable)
@@ -25,6 +25,7 @@ use warnings FATAL => qw(all);
 use make::configure;
 
 BEGIN {
+       push @INC, '.';
        unless (module_installed("LWP::Simple")) {
                die "Your system is missing the LWP::Simple Perl module!";
        }
index 90c26a974d4b8c3676fe5b23f673b6753b5f8acf..8438f8cdd0e07d222252eb96c76df49a0d5741f1 100644 (file)
@@ -58,13 +58,15 @@ class CommandWho : public Command
 };
 
 
-static Channel* get_first_visible_channel(User *u)
+static Channel* get_first_visible_channel(User *source, User *u)
 {
        UCListIter i = u->chans.begin();
        while (i != u->chans.end())
        {
                Channel* c = *i++;
-               if (!c->IsModeSet('s'))
+
+               /* XXX move the +I check into m_hidechans */
+               if (source == u || !(c->IsModeSet('s') || c->IsModeSet('p') || u->IsModeSet('I')) || c->HasUser(source))
                        return c;
        }
        return NULL;
@@ -189,7 +191,7 @@ bool CommandWho::CanView(Channel* chan, User* user)
 void CommandWho::SendWhoLine(User* user, const std::vector<std::string>& parms, const std::string &initial, Channel* ch, User* u, std::vector<std::string> &whoresults)
 {
        if (!ch)
-               ch = get_first_visible_channel(u);
+               ch = get_first_visible_channel(user, u);
 
        std::string wholine = initial + (ch ? ch->name : "*") + " " + u->ident + " " +
                (opt_showrealhost ? u->host : u->dhost) + " ";
index 6c765fb2ece23f9b0b586d4b964349024f965906..405bab082bef6df6522de1327408505ec533c9ef 100644 (file)
@@ -310,36 +310,25 @@ public:
                }
 
                RAIILDAPMessage msg;
-               std::string what = (attribute + "=" + (useusername ? user->ident : user->nick));
-               if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS)
+               std::string what;
+               std::string::size_type pos = user->password.find(':');
+               // If a username is provided in PASS, use it, othewrise user their nick or ident
+               if (pos != std::string::npos)
                {
-                       // Do a second search, based on password, if it contains a :
-                       // That is, PASS <user>:<password> will work.
-                       size_t pos = user->password.find(":");
-                       if (pos != std::string::npos)
-                       {
-                               // manpage says we must deallocate regardless of success or failure
-                               // since we're about to do another query (and reset msg), first
-                               // free the old one.
-                               msg.dealloc();
-
-                               std::string cutpassword = user->password.substr(0, pos);
-                               res = ldap_search_ext_s(conn, base.c_str(), searchscope, cutpassword.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg);
-
-                               if (res == LDAP_SUCCESS)
-                               {
-                                       // Trim the user: prefix, leaving just 'pass' for later password check
-                                       user->password = user->password.substr(pos + 1);
-                               }
-                       }
+                       what = (attribute + "=" + user->password.substr(0, pos));
 
-                       // It may have found based on user:pass check above.
-                       if (res != LDAP_SUCCESS)
-                       {
-                               if (verbose)
-                                       ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search failed: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res));
-                               return false;
-                       }
+                       // Trim the user: prefix, leaving just 'pass' for later password check
+                       user->password = user->password.substr(pos + 1);
+               }
+               else
+               {
+                       what = (attribute + "=" + (useusername ? user->ident : user->nick));
+               }
+               if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS)
+               {
+                       if (verbose)
+                               ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search failed: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res));
+                       return false;
                }
                if (ldap_count_entries(conn, msg) > 1)
                {
@@ -404,7 +393,7 @@ public:
                        std::string dnPart;
                        while (stream.GetToken(dnPart))
                        {
-                               std::string::size_type pos = dnPart.find('=');
+                               pos = dnPart.find('=');
                                if (pos == std::string::npos) // malformed
                                        continue;
 
index cce2e785531ad3c38b6fd3283fdeb173a8712aa0..09f6a4659d88e0d760a85d48166514ed825b68d8 100644 (file)
@@ -73,6 +73,7 @@ class CommandWebirc : public Command
                  realhost("cgiirc_realhost", Creator), realip("cgiirc_realip", Creator),
                  webirc_hostname("cgiirc_webirc_hostname", Creator), webirc_ip("cgiirc_webirc_ip", Creator)
                {
+                       allow_empty_last_param = false;
                        works_before_reg = true;
                        this->syntax = "password client hostname ip";
                }
@@ -81,6 +82,14 @@ class CommandWebirc : public Command
                        if(user->registered == REG_ALL)
                                return CMD_FAILURE;
 
+                       irc::sockets::sockaddrs ipaddr;
+                       if (!irc::sockets::aptosa(parameters[3], 0, ipaddr))
+                       {
+                               IS_LOCAL(user)->CommandFloodPenalty += 5000;
+                               ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s tried to use WEBIRC but gave an invalid IP address.", user->GetFullRealHost().c_str());
+                               return CMD_FAILURE;
+                       }
+
                        for(CGIHostlist::iterator iter = Hosts.begin(); iter != Hosts.end(); iter++)
                        {
                                if(InspIRCd::Match(user->host, iter->hostmask, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(user->GetIPString(), iter->hostmask, ascii_case_insensitive_map))
@@ -108,6 +117,7 @@ class CommandWebirc : public Command
                                }
                        }
 
+                       IS_LOCAL(user)->CommandFloodPenalty += 5000;
                        ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s tried to use WEBIRC, but didn't match any configured webirc blocks.", user->GetFullRealHost().c_str());
                        return CMD_FAILURE;
                }
index 105d688337d20d0afb767059815bf10ace8c5671..1bf99f919f8550e9aaf21f0e9aee983898376fcd 100644 (file)
@@ -493,11 +493,14 @@ class ModuleCloaking : public Module
        {
                std::string chost;
 
+               irc::sockets::sockaddrs hostip;
+               bool host_is_ip = irc::sockets::aptosa(host, ip.port(), hostip) && hostip == ip;
+
                switch (mode)
                {
                        case MODE_COMPAT_HOST:
                        {
-                               if (ipstr != host)
+                               if (!host_is_ip)
                                {
                                        std::string tail = LastTwoDomainParts(host);
 
@@ -520,7 +523,7 @@ class ModuleCloaking : public Module
                                break;
                        case MODE_HALF_CLOAK:
                        {
-                               if (ipstr != host)
+                               if (!host_is_ip)
                                        chost = prefix + SegmentCloak(host, 1, 6) + LastTwoDomainParts(host);
                                if (chost.empty() || chost.length() > 50)
                                        chost = SegmentIP(ip, false);
index d4101686a03c1daaba9115da2a8244e2898838d0..3dea080cee59dd99474510ae5fe5567f4eda3b44 100644 (file)
@@ -70,8 +70,8 @@ class DNSBLResolver : public Resolver
                        int i = countExt.get(them);
                        if (i)
                                countExt.set(them, i - 1);
-                       // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d
-                       if(result.length())
+                       // All replies should be in 127.0.0.0/8
+                       if (result.compare(0, 4, "127.") == 0)
                        {
                                unsigned int bitmask = 0, record = 0;
                                bool match = false;
@@ -82,6 +82,7 @@ class DNSBLResolver : public Resolver
                                switch (ConfEntry->type)
                                {
                                        case DNSBLConfEntry::A_BITMASK:
+                                               // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d
                                                bitmask = resultip.s_addr >> 24; /* Last octet (network byte order) */
                                                bitmask &= ConfEntry->bitmask;
                                                match = (bitmask != 0);
@@ -196,7 +197,11 @@ class DNSBLResolver : public Resolver
                                        ConfEntry->stats_misses++;
                        }
                        else
+                       {
+                               if (!result.empty())
+                                       ServerInstance->SNO->WriteGlobalSno('a', "DNSBL: %s returned address outside of acceptable subnet 127.0.0.0/8: %s", ConfEntry->domain.c_str(), result.c_str());
                                ConfEntry->stats_misses++;
+                       }
                }
        }
 
index 2fc7ca7dea33656e4c79dfcf5c7723176daf75f1..e17bf514f0835d494e57f60074bd5e30b009a55a 100644 (file)
@@ -213,7 +213,7 @@ class ModuleHttpStats : public Module
                                        data << "<server>";
                                        data << "<servername>" << b->servername << "</servername>";
                                        data << "<parentname>" << b->parentname << "</parentname>";
-                                       data << "<gecos>" << b->gecos << "</gecos>";
+                                       data << "<gecos>" << Sanitize(b->gecos) << "</gecos>";
                                        data << "<usercount>" << b->usercount << "</usercount>";
 // This is currently not implemented, so, commented out.
 //                                     data << "<opercount>" << b->opercount << "</opercount>";
index 3ab5dae9df0c9aa5b54fed4fc8c53e4f244bb10d..ca4147fea254807ad7006001bf98a3e357c76bb9 100644 (file)
@@ -137,9 +137,6 @@ void SpanningTreeProtocolInterface::PushToClient(User* target, const std::string
 
 void SpanningTreeProtocolInterface::SendChannel(Channel* target, char status, const std::string &text)
 {
-       std::string cname = target->name;
-       if (status)
-               cname = status + cname;
        TreeServerList list;
        CUList exempt_list;
        Utils->GetListOfServersForChannel(target,list,status,exempt_list);
@@ -154,12 +151,20 @@ void SpanningTreeProtocolInterface::SendChannel(Channel* target, char status, co
 
 void SpanningTreeProtocolInterface::SendChannelPrivmsg(Channel* target, char status, const std::string &text)
 {
-       SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" PRIVMSG "+target->name+" :"+text);
+       std::string cname = target->name;
+       if (status)
+               cname.insert(0, 1, status);
+
+       SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" PRIVMSG "+cname+" :"+text);
 }
 
 void SpanningTreeProtocolInterface::SendChannelNotice(Channel* target, char status, const std::string &text)
 {
-       SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" NOTICE "+target->name+" :"+text);
+       std::string cname = target->name;
+       if (status)
+               cname.insert(0, 1, status);
+
+       SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" NOTICE "+cname+" :"+text);
 }
 
 void SpanningTreeProtocolInterface::SendUserPrivmsg(User* target, const std::string &text)
index f2837777ad7ec7a3ac11e6116be84bc70ca9ca0e..d5f01734782e568d29fbf69457ed7224d1fb25bd 100644 (file)
@@ -25,7 +25,7 @@
 #include "exitcodes.h"
 #include "socketengine.h"
 #include <sys/epoll.h>
-#include <ulimit.h>
+#include <sys/resource.h>
 #include <iostream>
 #define EP_DELAY 5
 
@@ -55,10 +55,11 @@ public:
 EPollEngine::EPollEngine()
 {
        CurrentSetSize = 0;
-       int max = ulimit(4, 0);
-       if (max > 0)
+
+       struct rlimit limit;
+       if (!getrlimit(RLIMIT_NOFILE, &limit))
        {
-               MAX_DESCRIPTORS = max;
+               MAX_DESCRIPTORS = limit.rlim_cur;
        }
        else
        {
index 685ef9743c9024ce93d931c0d0c444496ef2b9bd..4dbb73a1f55ef7e4e5492784d1165d283c832c53 100644 (file)
@@ -1398,6 +1398,8 @@ void User::DoHostCycle(const std::string &quitline)
 
        FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions));
 
+       // Users shouldn't see themselves quitting when host cycling
+       exceptions.erase(this);
        for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
        {
                LocalUser* u = IS_LOCAL(i->first);
index 6dbc823008449e4581d91818804ff2d2027b68f4..42b07fa251a37003384dba0059896d76bee3a8aa 100755 (executable)
@@ -4,11 +4,6 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]
 then
        sudo apt-get update --assume-yes
        sudo apt-get install --assume-yes libgeoip-dev libgnutls-dev libldap2-dev libmysqlclient-dev libpcre3-dev libpq-dev libsqlite3-dev libssl-dev libtre-dev
-elif [ "$TRAVIS_OS_NAME" = "osx" ]
-then
-       brew update
-       brew install geoip gnutls mysql-connector-c openssl pcre postgresql sqlite3 tre
-       brew link sqlite3 --force
 else
        >&2 echo "'$TRAVIS_OS_NAME' is an unknown Travis CI environment!"
        exit 1
index 10653cf74a13692c75f618c444341c463096275a..7be08a3fcd43f2c18d4dea2f508347af1dd863ef 100644 (file)
@@ -85,6 +85,7 @@ file(MAKE_DIRECTORY ${LOG_PATH})
 install(DIRECTORY ${LOG_PATH} DESTINATION .)
 
 if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
+       set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION ".") # place runtime libraries next to InspIRCd binary
        include(InstallRequiredSystemLibraries)
 
        set(CPACK_PACKAGE_NAME "InspIRCd IRC Daemon")