]> arthur.barton.de Git - ngircd.git/commitdiff
Merge pull request #2 from briancollins/master
authorAlexander Barton <alex@barton.de>
Tue, 11 Sep 2012 18:29:14 +0000 (11:29 -0700)
committerAlexander Barton <alex@barton.de>
Tue, 11 Sep 2012 18:29:14 +0000 (11:29 -0700)
Fix IRC_Send_NAMES not sending correct prefix for certain clients.

21 files changed:
README
contrib/Debian/control
contrib/Makefile.am
contrib/ngircd.spec
doc/Modes.txt
src/ngircd/channel.c
src/ngircd/client.c
src/ngircd/conf.c
src/ngircd/conf.h
src/ngircd/conn-ssl.c
src/ngircd/conn.c
src/ngircd/conn.h
src/ngircd/defines.h
src/ngircd/io.c
src/ngircd/irc-cap.c
src/ngircd/irc-info.c
src/ngircd/irc-mode.c
src/ngircd/messages.h
src/ngircd/ngircd.c
src/ngircd/sighandlers.c
src/tool/tool.c

diff --git a/README b/README
index 2e19d831deac91663730963afba874b0f52dd736..11d140d6464b7fb780fa79d9f7c3fa96b2197306 100644 (file)
--- a/README
+++ b/README
 I. Introduction
 ~~~~~~~~~~~~~~~
 
-ngIRCd is an Open Source server for the Internet Relay Chat (IRC), which
-is developed and published under the terms of the GNU General Public
-Licence, see the file COPYING for details. ngIRCd means "next generation
-IRC daemon" (which is a little bit exaggerated, "lightweight Internet Relay
-Chat server" would be better), it's written from scratch and not deduced
-from the "grandfather of IRC daemons", the daemon of the IRCNet.
+ngIRCd is a free, portable and lightweight Internet Relay Chat server for
+small or private networks, developed under the GNU General Public License
+(GPL; please see the file COPYING for details). It is simple to configure,
+can cope with dynamic IP addresses, and supports IPv6 as well as SSL. It is
+written from scratch and not based on the original IRCd.
+
+The name ngIRCd means next generation IRC daemon, which is a little bit
+exaggerated: lightweight Internet Relay Chat server most probably would be a
+better name :-)
 
 Please see the INSTALL document for installation and upgrade information!
 
index 0ac6d22a47446749ef69b78b37686d23a779ea64..d6cf418c15202f1227eb337fe6df94237ae49758 100644 (file)
@@ -18,11 +18,11 @@ Architecture: any
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Provides: ircd
 Description: lightweight Internet Relay Chat server
- This package provides ngIRCd, a lightweight Internet Relay Chat
- server for small or private networks. It is simple to configure, can
- cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
- is written from scratch, not based on the original IRCd and quite
portable.
+ This package provides ngIRCd, a portable and lightweight Internet Relay
+ Chat server for small or private networks, developed under the GNU
+ General Public License (GPL). It is simple to configure, can cope with
+ dynamic IP addresses, and supports IPv6 as well as SSL. It is written
from scratch and not based on the original IRCd.
  .
  This package contains the "standard distribution", including support for
  syslog logging and compressed server-links using zlib. Please have a look
@@ -35,11 +35,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends}
 Provides: ircd
 Conflicts: ngircd, ngircd-dbg
 Description: lightweight Internet Relay Chat server
- This package provides ngIRCd, a lightweight Internet Relay Chat
- server for small or private networks. It is simple to configure, can
- cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
- is written from scratch, not based on the original IRCd and quite
portable.
+ This package provides ngIRCd, a portable and lightweight Internet Relay
+ Chat server for small or private networks, developed under the GNU
+ General Public License (GPL). It is simple to configure, can cope with
+ dynamic IP addresses, and supports IPv6 as well as SSL. It is written
from scratch and not based on the original IRCd.
  .
  In addition to the features of the "standard package", this package
  includes support for TCP wrappers, IDENT requests, the IPv6 protocol and
@@ -51,11 +51,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends}
 Provides: ircd
 Conflicts: ngircd, ngircd-full
 Description: lightweight Internet Relay Chat server
- This package provides ngIRCd, a lightweight Internet Relay Chat
- server for small or private networks. It is simple to configure, can
- cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
- is written from scratch, not based on the original IRCd and quite
portable.
+ This package provides ngIRCd, a portable and lightweight Internet Relay
+ Chat server for small or private networks, developed under the GNU
+ General Public License (GPL). It is simple to configure, can cope with
+ dynamic IP addresses, and supports IPv6 as well as SSL. It is written
from scratch and not based on the original IRCd.
  .
  In addition to the features of the "standard package", this package
  includes support for TCP wrappers, IDENT requests, the IPv6 protocol and
index 73611fd441a2d9f77a2d4d1337a6a3c4ca68d089..99ab68446a4bfb15ede491f7a372492b1d4ad652 100644 (file)
@@ -16,7 +16,7 @@ EXTRA_DIST = README \
        ngircd-bsd.sh \
        ngIRCd-Logo.gif \
        ngircd-redhat.init \
-       ngircd.service
+       ngircd.service \
        ngircd.spec \
        platformtest.sh \
        systrace.policy
index 2041aa08b0e84cf57d0c69543070c4103e7e97c1..aeb10f2aa7604f54b0c1cfce6dd765d647eb2e18 100644 (file)
@@ -15,11 +15,11 @@ BuildRoot:    %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires:  zlib-devel, openssl-devel
 
 %description
-This package provides ngIRCd, a lightweight Internet Relay Chat
-server for small or private networks. It is simple to configure, can
-cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
-is written from scratch, not based on the original IRCd and quite
-portable.
+This package provides ngIRCd, a portable and lightweight Internet Relay
+Chat server for small or private networks, developed under the GNU
+General Public License (GPL). It is simple to configure, can cope with
+dynamic IP addresses, and supports IPv6 as well as SSL. It is written
+from scratch and not based on the original IRCd.
 
 Advantages:
  - well arranged (lean) configuration file
index e47e2707244f9d30894c6b108357918468fa92af..c2c533f2a67e1784561869cfee1ac49c5bf0fd90 100644 (file)
@@ -2,7 +2,7 @@
                      ngIRCd - Next Generation IRC Server
                            http://ngircd.barton.de/
 
-               (c)2001-2011 Alexander Barton and Contributors.
+               (c)2001-2012 Alexander Barton and Contributors.
                ngIRCd is free software and published under the
                    terms of the GNU General Public License.
 
@@ -22,6 +22,7 @@ channels he is using at the moment.
   mode since   description
 
   a    0.3.0   User is away.
+  B    20      User is flagged as a "bot".
   c    17      IRC operator wants to receive connect/disconnect NOTICEs.
   C    19      Only users that share a channel are allowed to send messages.
   i    0.0.1   User is "invisible".
@@ -49,6 +50,7 @@ users to lists (e.g. "invite list", "ban list"), others have parameters
   k    0.6.0   Channel has a "key" (a password).
   l    0.6.0   Channel has a user limit.
   m    0.3.0   Channel is moderated, only "voiced" users can send messages.
+  M    20      Only registered users (and IRC Ops) can send messages.
   n    0.3.0   Channel doesn't allow messages of users not being members.
   O    18      Only IRC operators are allowed to join this channel.
   P    0.5.0   Channel is "persistent".
index ff470246fec79e09d67ab764c6bca583138e2a00..f0a9525d348a5d992596f453fd9ba709cbd47c9a 100644 (file)
@@ -66,16 +66,8 @@ static void Set_KeyFile PARAMS((CHANNEL *Chan, const char *KeyFile));
 GLOBAL void
 Channel_Init( void )
 {
-       CHANNEL *sc;
-
        My_Channels = NULL;
        My_Cl2Chan = NULL;
-
-       sc = Channel_Create("&SERVER");
-       if (sc) {
-               Channel_SetModes(sc, "mnPt");
-               Channel_SetTopic(sc, Client_ThisServer(), "Server Messages");
-       }
 } /* Channel_Init */
 
 
@@ -103,11 +95,12 @@ Channel_GetListInvites(CHANNEL *c)
 }
 
 
+/**
+ * Generate predefined persistent channels and &SERVER
+ */
 GLOBAL void
 Channel_InitPredefined( void )
 {
-       /* Generate predefined persistent channels */
-
        CHANNEL *new_chan;
        const struct Conf_Channel *conf_chan;
        const char *c;
@@ -160,6 +153,18 @@ Channel_InitPredefined( void )
        }
        if (channel_count)
                array_free(&Conf_Channels);
+
+       /* Make sure the local &SERVER channel exists */
+       if (!Channel_Search("&SERVER")) {
+               new_chan = Channel_Create("&SERVER");
+               if (new_chan) {
+                       Channel_SetModes(new_chan, "mnPt");
+                       Channel_SetTopic(new_chan, Client_ThisServer(),
+                                        "Server Messages");
+               } else
+                       Log(LOG_ERR, "Failed to create \"&SERVER\" channel!");
+       } else
+               LogDebug("Required channel \"&SERVER\" already exists, ok.");
 } /* Channel_InitPredefined */
 
 
@@ -832,6 +837,10 @@ Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
        if (strchr(Channel_Modes(Chan), 'n') && !is_member)
                return false;
 
+       if (strchr(Channel_Modes(Chan), 'M') && !Client_HasMode(From, 'R')
+           && !Client_HasMode(From, 'o'))
+               return false;
+
        if (is_op || has_voice)
                return true;
 
index 0d2d4147345046b87f7f3c6e46fd018749f4da36..4728c7a4672ac802d944dc599d23031f75e50d60 100644 (file)
@@ -687,18 +687,35 @@ Client_Hostname(CLIENT *Client)
 
 /**
  * Get potentially cloaked hostname of a client.
+ *
  * If the client has not enabled cloaking, the real hostname is used.
+ * Please note that this function uses a global static buffer, so you can't
+ * nest invocations without overwriting earlier results!
+ *
  * @param Client Pointer to client structure
  * @return Pointer to client hostname
  */
 GLOBAL char *
 Client_HostnameCloaked(CLIENT *Client)
 {
+       static char Cloak_Buffer[CLIENT_HOST_LEN];
+
        assert(Client != NULL);
-       if (Client_HasMode(Client, 'x'))
-               return Client_ID(Client->introducer);
-       else
+
+       if (!Client_HasMode(Client, 'x'))
                return Client_Hostname(Client);
+
+       /* Do simple mapping to the server ID? */
+       if (!*Conf_CloakHostModeX)
+               return Client_ID(Client->introducer);
+
+       strlcpy(Cloak_Buffer, Client->host, CLIENT_HOST_LEN);
+       strlcat(Cloak_Buffer, Conf_CloakHostSalt, CLIENT_HOST_LEN);
+
+       snprintf(Cloak_Buffer, CLIENT_HOST_LEN, Conf_CloakHostModeX,
+                Hash(Cloak_Buffer));
+
+       return Cloak_Buffer;
 } /* Client_HostnameCloaked */
 
 
@@ -792,10 +809,12 @@ Client_Mask( CLIENT *Client )
 
 /**
  * Return ID of a client with cloaked hostname: "client!user@server-name"
+ *
  * This client ID is used for IRC prefixes, for example.
  * Please note that this function uses a global static buffer, so you can't
  * nest invocations without overwriting earlier results!
  * If the client has not enabled cloaking, the real hostname is used.
+ *
  * @param Client Pointer to client structure
  * @return Pointer to global buffer containing the client ID
  */
@@ -803,7 +822,6 @@ GLOBAL char *
 Client_MaskCloaked(CLIENT *Client)
 {
        static char Mask_Buffer[GETID_LEN];
-       char Cloak_Buffer[GETID_LEN];
 
        assert (Client != NULL);
 
@@ -811,16 +829,8 @@ Client_MaskCloaked(CLIENT *Client)
        if (!Client_HasMode(Client, 'x'))
                return Client_Mask(Client);
 
-       if(*Conf_CloakHostModeX) {
-               strlcpy(Cloak_Buffer, Client->host, GETID_LEN);
-               strlcat(Cloak_Buffer, Conf_CloakHostSalt, GETID_LEN);
-               snprintf(Cloak_Buffer, GETID_LEN, Conf_CloakHostModeX, Hash(Cloak_Buffer));
-       } else {
-               strncpy(Cloak_Buffer, Client_ID(Client->introducer), GETID_LEN);
-       }
-
-       snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s",
-               Client->id, Client->user, Cloak_Buffer);
+       snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user,
+                Client_HostnameCloaked(Client));
 
        return Mask_Buffer;
 } /* Client_MaskCloaked */
index 3966dc908a1afff2bf5a95901c8cff6427b91524..627e6d3fbf22557d695478ffe2a507b5fafe2a4d 100644 (file)
@@ -346,7 +346,7 @@ Conf_Test( void )
 
        puts("[LIMITS]");
        printf("  ConnectRetry = %d\n", Conf_ConnectRetry);
-       printf("  MaxConnections = %ld\n", Conf_MaxConnections);
+       printf("  MaxConnections = %d\n", Conf_MaxConnections);
        printf("  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP);
        printf("  MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
        printf("  MaxNickLength = %u\n", Conf_MaxNickLength - 1);
@@ -1432,7 +1432,7 @@ Handle_LIMITS(int Line, char *Var, char *Arg)
                return;
        }
        if (strcasecmp(Var, "MaxConnections") == 0) {
-               Conf_MaxConnections = atol(Arg);
+               Conf_MaxConnections = atoi(Arg);
                if (!Conf_MaxConnections && strcmp(Arg, "0"))
                        Config_Error_NaN(Line, Var);
                return;
@@ -1911,6 +1911,13 @@ Validate_Config(bool Configtest, bool Rehash)
        bool config_valid = true;
        char *ptr;
 
+       /* Emit a warning when the config file is not a full path name */
+       if (NGIRCd_ConfFile[0] && NGIRCd_ConfFile[0] != '/') {
+               Config_Error(LOG_WARNING,
+                       "Not specifying a full path name to \"%s\" can cause problems when rehashing the server!",
+                       NGIRCd_ConfFile);
+       }
+
        /* Validate configured server name, see RFC 2812 section 2.3.1 */
        ptr = Conf_ServerName;
        do {
index 8e66c07c3c671f3ecf119fc50f6fc313cdaa5307..7a4e38aa05b56a626a4aed84055a0e7d28fc081a 100644 (file)
@@ -206,7 +206,7 @@ GLOBAL bool Conf_ConnectIPv6;
 GLOBAL bool Conf_ConnectIPv4;
 
 /** Maximum number of simultaneous connections to this server */
-GLOBAL long Conf_MaxConnections;
+GLOBAL int Conf_MaxConnections;
 
 /** Maximum number of channels a user can join */
 GLOBAL int Conf_MaxJoins;
index 5d44b30f07708e46d0221c4ba227f20f1bc7d853..8f7b70afccb0e310793013e0f53ee5f38522a614 100644 (file)
@@ -625,6 +625,8 @@ ConnectAccept( CONNECTION *c, bool connect)
 #endif /* _GNUTLS */
        Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
        ConnSSL_LogCertInfo(c);
+
+       Conn_StartLogin(CONNECTION2ID(c));
        return 1;
 }
 
index e57aa2423a3eea2bbdacea0500fe9e3452ddb0bf..6091ebe26a34a8096d2d62cf48e06b06c5dd321d 100644 (file)
@@ -88,7 +88,7 @@
 
 static bool Handle_Write PARAMS(( CONN_ID Idx ));
 static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
-static int New_Connection PARAMS(( int Sock ));
+static int New_Connection PARAMS(( int Sock, bool IsSSL ));
 static CONN_ID Socket2Index PARAMS(( int Sock ));
 static void Read_Request PARAMS(( CONN_ID Idx ));
 static unsigned int Handle_Buffer PARAMS(( CONN_ID Idx ));
@@ -134,7 +134,7 @@ static void
 cb_listen(int sock, short irrelevant)
 {
        (void) irrelevant;
-       (void) New_Connection(sock);
+       (void) New_Connection(sock, false);
 }
 
 
@@ -152,7 +152,7 @@ cb_listen_ssl(int sock, short irrelevant)
        int fd;
 
        (void) irrelevant;
-       fd = New_Connection(sock);
+       fd = New_Connection(sock, true);
        if (fd < 0)
                return;
        io_event_setcb(My_Connections[fd].sock, cb_clientserver_ssl);
@@ -1362,17 +1362,18 @@ Count_Connections(ng_ipaddr_t *a)
  * Initialize new client connection on a listening socket.
  *
  * @param Sock Listening socket descriptor.
+ * @param IsSSL        true if this socket expects SSL-encrypted data.
  * @returns    Accepted socket descriptor or -1 on error.
  */
 static int
-New_Connection(int Sock)
+New_Connection(int Sock, UNUSED bool IsSSL)
 {
 #ifdef TCPWRAP
        struct request_info req;
 #endif
        ng_ipaddr_t new_addr;
        char ip_str[NG_INET_ADDRSTRLEN];
-       int new_sock, new_sock_len, identsock;
+       int new_sock, new_sock_len;
        CLIENT *c;
        long cnt;
 
@@ -1492,30 +1493,56 @@ New_Connection(int Sock)
        Log(LOG_INFO, "Accepted connection %d from %s:%d on socket %d.",
            new_sock, My_Connections[new_sock].host,
            ng_ipaddr_getport(&new_addr), Sock);
+       Account_Connection();
+
+#ifdef SSL_SUPPORT
+       /* Delay connection initalization until SSL handshake is finished */
+       if (!IsSSL)
+#endif
+               Conn_StartLogin(new_sock);
+
+       return new_sock;
+} /* New_Connection */
+
+
+/**
+ * Finish connection initialization, start resolver subprocess.
+ *
+ * @param Idx Connection index.
+ */
+GLOBAL void
+Conn_StartLogin(CONN_ID Idx)
+{
+       int ident_sock = -1;
+
+       assert(Idx >= 0);
+
+       /* Nothing to do if DNS (and resolver subprocess) is disabled */
+       if (!Conf_DNS)
+               return;
 
-       identsock = new_sock;
 #ifdef IDENTAUTH
-       if (!Conf_Ident)
-               identsock = -1;
+       /* Should we make an IDENT request? */
+       if (Conf_Ident)
+               ident_sock = My_Connections[Idx].sock;
 #endif
-       if (Conf_DNS) {
-               if (Conf_NoticeAuth) {
+
+       if (Conf_NoticeAuth) {
+               /* Send "NOTICE AUTH" messages to the client */
 #ifdef IDENTAUTH
-                       if (Conf_Ident)
-                               (void)Conn_WriteStr(new_sock,
-                                       "NOTICE AUTH :*** Looking up your hostname and checking ident");
-                       else
+               if (Conf_Ident)
+                       (void)Conn_WriteStr(Idx,
+                               "NOTICE AUTH :*** Looking up your hostname and checking ident");
+               else
 #endif
-                               (void)Conn_WriteStr(new_sock,
-                                       "NOTICE AUTH :*** Looking up your hostname");
-               }
-               Resolve_Addr(&My_Connections[new_sock].proc_stat, &new_addr,
-                            identsock, cb_Read_Resolver_Result);
+                       (void)Conn_WriteStr(Idx,
+                               "NOTICE AUTH :*** Looking up your hostname");
+               (void)Handle_Write(Idx);
        }
 
-       Account_Connection();
-       return new_sock;
-} /* New_Connection */
+       Resolve_Addr(&My_Connections[Idx].proc_stat, &My_Connections[Idx].addr,
+                    ident_sock, cb_Read_Resolver_Result);
+}
 
 
 /**
@@ -2257,7 +2284,8 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
                Client_SetHostname(c, readbuf);
                if (Conf_NoticeAuth)
                        (void)Conn_WriteStr(i,
-                                       "NOTICE AUTH :*** Found your hostname");
+                                       "NOTICE AUTH :*** Found your hostname: %s",
+                                       My_Connections[i].host);
 #ifdef IDENTAUTH
                ++identptr;
                if (*identptr) {
@@ -2282,8 +2310,10 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
                        }
                        if (Conf_NoticeAuth) {
                                (void)Conn_WriteStr(i,
-                                       "NOTICE AUTH :*** Got %sident response",
-                                       *ptr ? "invalid " : "");
+                                       "NOTICE AUTH :*** Got %sident response%s%s",
+                                       *ptr ? "invalid " : "",
+                                       *ptr ? "" : ": ",
+                                       *ptr ? "" : identptr);
                        }
                } else {
                        Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
@@ -2292,6 +2322,10 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
                                        "NOTICE AUTH :*** No ident response");
                }
 #endif
+
+               if (Conf_NoticeAuth)
+                       (void)Handle_Write(i);
+
                Class_HandleServerBans(c);
        }
 #ifdef DEBUG
index 7dcc8d9d590619c143276d93b003c0c565d3a4e4..e42a2ae6a7ac1c1466ade3a8124650a489e61715 100644 (file)
@@ -42,7 +42,7 @@
 #define CONN_SSL_WANT_READ     128     /* SSL/TLS library needs to read protocol data */
 #define CONN_SSL_FLAGS_ALL     (CONN_SSL_CONNECT|CONN_SSL|CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ)
 #endif
-typedef long CONN_ID;
+typedef int CONN_ID;
 
 #include "client.h"
 #include "proc.h"
@@ -101,6 +101,8 @@ GLOBAL CONNECTION *My_Connections;
 GLOBAL CONN_ID Pool_Size;
 GLOBAL long WCounter;
 
+#define CONNECTION2ID(x) (long)(x - My_Connections)
+
 #endif /* CONN_MODULE */
 
 
@@ -112,6 +114,8 @@ GLOBAL void Conn_CloseAllSockets PARAMS((int ExceptOf));
 GLOBAL unsigned int Conn_InitListeners PARAMS(( void ));
 GLOBAL void Conn_ExitListeners PARAMS(( void ));
 
+GLOBAL void Conn_StartLogin PARAMS((CONN_ID Idx));
+
 GLOBAL void Conn_Handler PARAMS(( void ));
 
 GLOBAL bool Conn_WriteStr PARAMS(( CONN_ID Idx, const char *Format, ... ));
@@ -126,6 +130,7 @@ GLOBAL void Conn_SyncServerStruct PARAMS(( void ));
 GLOBAL CONN_ID Conn_GetFromProc PARAMS((int fd));
 GLOBAL CLIENT* Conn_GetClient PARAMS((CONN_ID i));
 GLOBAL PROC_STAT* Conn_GetProcStat PARAMS((CONN_ID i));
+
 #ifdef SSL_SUPPORT
 GLOBAL bool Conn_GetCipherInfo PARAMS((CONN_ID Idx, char *buf, size_t len));
 GLOBAL bool Conn_UsesSSL PARAMS((CONN_ID Idx));
index cd0a1666ae58a7696c27f7c5aeac40fcfeea565b..82837599aadbb6485f0f044b447739d7b5f922fa 100644 (file)
 #endif
 
 /** Supported user modes. */
-#define USERMODES "acCiorRswx"
+#define USERMODES "aBcCiorRswx"
 
 /** Supported channel modes. */
-#define CHANMODES "beiIklmnoOPrRstvz"
+#define CHANMODES "beiIklmMnoOPrRstvz"
 
 /** Away message for users connected to linked servers. */
 #define DEFAULT_AWAY_MSG "Away"
index 9ffdfd6b8320e4ab12439e3273e92d99ceceb8a1..cce6ef536557e7376bf93a1a8df9f912218ae0e4 100644 (file)
@@ -86,6 +86,20 @@ static int io_masterfd;
 
 static int io_dispatch_kqueue(struct timeval *tv);
 static bool io_event_change_kqueue(int, short, const int action);
+
+#ifndef EV_SET
+/* Taken from /usr/include/sys/event.h of FreeBSD 8.1 and required by all
+ * platforms that have kqueue but lack EV_SET() -- for example FreeBSD 4. */
+#define EV_SET(kevp, a, b, c, d, e, f) do {    \
+       struct kevent *__kevp__ = (kevp);       \
+       __kevp__->ident = (a);                  \
+       __kevp__->filter = (b);                 \
+       __kevp__->flags = (c);                  \
+       __kevp__->fflags = (d);                 \
+       __kevp__->data = (e);                   \
+       __kevp__->udata = (f);                  \
+} while(0)
+#endif
 #endif
 
 #ifdef IO_USE_POLL
index 2ea4c9af135f6a9309be449924946bd6ca6ae879..af34c38c18403370f16f223eac257e429bc6fb3d 100644 (file)
@@ -275,8 +275,8 @@ Parse_CAP(int Capabilities, char *Args)
  * @param Capabilities Capability flags (bitmask).
  * @return Pointer to textual representation.
  */
-char
-*Get_CAP_String(int Capabilities)
+char *
+Get_CAP_String(int Capabilities)
 {
        static char txt[COMMAND_LEN];
 
index 89d2deef1fc2b647cf3fbfee543329d85e4fada8..fc04773ae14ef307d1ac5adb0b53f2a18a64dd03 100644 (file)
@@ -848,6 +848,8 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
        assert( Client != NULL );
        assert( Chan != NULL );
 
+       IRC_SetPenalty(Client, 1);
+
        is_member = Channel_IsMemberOf(Chan, Client);
 
        /* Secret channel? */
@@ -866,9 +868,6 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
 
                is_visible = strchr(client_modes, 'i') == NULL;
                if (is_member || is_visible) {
-                       if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
-                               break;
-
                        strcpy(flags, who_flags_status(client_modes));
                        if (is_ircop)
                                strlcat(flags, "*", sizeof(flags));
@@ -883,6 +882,11 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
                        count++;
                }
        }
+
+       /* If there are a lot of clients, augment penalty a bit */
+       if (count > MAX_RPL_WHO)
+               IRC_SetPenalty(Client, 1);
+
        return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
                                  Channel_Name(Chan));
 }
@@ -911,6 +915,7 @@ IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps)
        if (Mask)
                ngt_LowerStr(Mask);
 
+       IRC_SetPenalty(Client, 3);
        for (c = Client_First(); c != NULL; c = Client_Next(c)) {
                if (Client_Type(c) != CLIENT_USER)
                        continue;
@@ -1014,13 +1019,11 @@ IRC_WHO(CLIENT *Client, REQUEST *Req)
                chan = Channel_Search(Req->argv[0]);
                if (chan) {
                        /* Members of a channel have been requested */
-                       IRC_SetPenalty(Client, 1);
                        return IRC_WHO_Channel(Client, chan, only_ops);
                }
                if (strcmp(Req->argv[0], "0") != 0) {
                        /* A mask has been given. But please note this RFC
                         * stupidity: "0" is same as no arguments ... */
-                       IRC_SetPenalty(Client, 3);
                        return IRC_WHO_Mask(Client, Req->argv[0], only_ops);
                }
        }
@@ -1111,6 +1114,12 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
                                Client_ID(from), Client_ID(c)))
                return DISCONNECTED;
 
+       /* IRC-Bot? */
+       if (Client_HasMode(c, 'B') &&
+           !IRC_WriteStrClient(from, RPL_WHOISBOT_MSG,
+                               Client_ID(from), Client_ID(c)))
+               return DISCONNECTED;
+
        /* Connected using SSL? */
        if (Conn_UsesSSL(Client_Conn(c)) &&
            !IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from),
@@ -1477,7 +1486,15 @@ Show_MOTD_Sendline(CLIENT *Client, const char *msg)
 static bool
 Show_MOTD_End(CLIENT *Client)
 {
-       return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ));
+       if (!IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, Client_ID(Client)))
+               return DISCONNECTED;
+
+       if (*Conf_CloakHost)
+               return IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG,
+                                         Client_ID(Client),
+                                         Client_Hostname(Client));
+
+       return CONNECTED;
 }
 
 #ifdef SSL_SUPPORT
index fa35cdd0f29d7742d92c169f6ce992a56eaa1ca5..71557201d8d938f4a5ff65416f50eb487f78333d 100644 (file)
@@ -138,6 +138,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
 {
        char the_modes[COMMAND_LEN], x[2], *mode_ptr;
        bool ok, set;
+       bool send_RPL_HOSTHIDDEN_MSG = false;
        int mode_arg;
        size_t len;
 
@@ -229,6 +230,14 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                        ERR_NOPRIVILEGES_MSG,
                                                        Client_ID(Origin));
                        break;
+               case 'B': /* Bot */
+                       if (Client_HasMode(Client, 'r'))
+                               ok = IRC_WriteStrClient(Origin,
+                                                       ERR_RESTRICTED_MSG,
+                                                       Client_ID(Origin));
+                       else
+                               x[0] = 'B';
+                       break;
                case 'c': /* Receive connect notices
                           * (only settable by IRC operators!) */
                        if (!set || Client_Type(Client) == CLIENT_SERVER
@@ -256,6 +265,14 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                        ERR_RESTRICTED_MSG,
                                                        Client_ID(Origin));
                        break;
+               case 'R': /* Registered (not [un]settable by clients) */
+                       if (Client_Type(Client) == CLIENT_SERVER)
+                               x[0] = 'R';
+                       else
+                               ok = IRC_WriteStrClient(Origin,
+                                                       ERR_NICKREGISTER_MSG,
+                                                       Client_ID(Origin));
+                       break;
                case 'x': /* Cloak hostname */
                        if (Client_HasMode(Client, 'r'))
                                ok = IRC_WriteStrClient(Origin,
@@ -263,6 +280,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                        Client_ID(Origin));
                        else
                                x[0] = 'x';
+                               send_RPL_HOSTHIDDEN_MSG = true;
                        break;
                default:
                        if (Client_Type(Client) != CLIENT_SERVER) {
@@ -332,6 +350,10 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
                                                  "MODE %s :%s",
                                                  Client_ID(Target),
                                                  the_modes);
+                       if (send_RPL_HOSTHIDDEN_MSG)
+                               IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG,
+                                                  Client_ID(Client),
+                                                  Client_HostnameCloaked(Client));
                }
                LogDebug("%s \"%s\": Mode change, now \"%s\".",
                         Client_TypeText(Target), Client_Mask(Target),
@@ -500,6 +522,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                switch (*mode_ptr) {
                /* --- Channel modes --- */
                case 'i': /* Invite only */
+               case 'M': /* Only identified nicks can write */
                case 'm': /* Moderated */
                case 'n': /* Only members can write */
                case 'R': /* Registered users only */
index d2e04dbf3454186b60def620a0847fe5b51cc9f5..4f3a397b2647eabc6fd6ed21f9aa31d776df69e9 100644 (file)
@@ -21,7 +21,7 @@
 #define RPL_YOURHOST_MSG               "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)"
 #define RPL_CREATED_MSG                        "003 %s :This server has been started %s"
 #define RPL_MYINFO_MSG                 "004 %s %s ngircd-%s %s %s"
-#define RPL_ISUPPORT1_MSG              "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=beI,k,l,imnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
+#define RPL_ISUPPORT1_MSG              "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
 #define RPL_ISUPPORT2_MSG              "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d EXCEPTS=e INVEX=I PENALTY :are supported on this server"
 
 #define RPL_TRACELINK_MSG              "200 %s Link %s-%s %s %s V%s %ld %d %d"
@@ -72,6 +72,7 @@
 #define RPL_NOTOPIC_MSG                        "331 %s %s :No topic is set"
 #define RPL_TOPIC_MSG                  "332 %s %s :%s"
 #define RPL_TOPICSETBY_MSG             "333 %s %s %s %u"
+#define RPL_WHOISBOT_MSG               "335 %s %s :is a IRC Bot"
 #define RPL_INVITING_MSG               "341 %s %s %s%s"
 #define RPL_INVITELIST_MSG             "346 %s %s %s"
 #define RPL_ENDOFINVITELIST_MSG                "347 %s %s :End of channel invite list"
@@ -95,6 +96,7 @@
 #define RPL_YOUREOPER_MSG              "381 %s :You are now an IRC Operator"
 #define RPL_YOURESERVICE_MSG           "383 %s :You are service %s"
 #define RPL_TIME_MSG                   "391 %s %s :%s"
+#define RPL_HOSTHIDDEN_MSG             "396 %s %s :is your displayed hostname now"
 
 #define ERR_NOSUCHNICK_MSG             "401 %s %s :No such nick or channel name"
 #define ERR_NOSUCHSERVER_MSG           "402 %s %s :No such server"
 #define ERR_CHANOPRIVSNEEDED_MSG       "482 %s %s :You are not channel operator"
 #define ERR_CANTKILLSERVER_MSG         "483 %s :You can't kill a server!"
 #define ERR_RESTRICTED_MSG             "484 %s :Your connection is restricted"
+#define ERR_NICKREGISTER_MSG           "484 %s :Cannot modify user mode (+R) -- Use IRC services"
 #define ERR_NOOPERHOST_MSG             "491 %s :Not configured for your host"
 #define ERR_NOTONSAMECHANNEL_MSG       "493 %s :You must share a common channel with %s"
 
index 8a93bcb00839a796b262b890d12b373d662ccf56..e24cefa86d63402c61dc6d81c7adba8e4c4e0d7d 100644 (file)
@@ -330,6 +330,7 @@ main(int argc, const char *argv[])
                Channel_Exit();
                Class_Exit();
                Log_Exit();
+               Signals_Exit();
        }
        Pidfile_Delete();
 
index efb41bcd8465147ff68fff0f70afcac1452cdba9..a219105f4b5aff571e045f22d58f0f5fc4d17162 100644 (file)
@@ -334,6 +334,7 @@ Signals_Exit(void)
 #endif
        close(signalpipe[1]);
        close(signalpipe[0]);
+       signalpipe[0] = signalpipe[1] = 0;
 }
 
 /* -eof- */
index df10918893348a4a1ef4205938e00db49eddb6b7..eb6c131e428462e81d3aad67075c721b429edd00 100644 (file)
@@ -135,24 +135,20 @@ ngt_TrimLastChr( char *String, const char Chr)
  * Fill a String with random chars
  */
 GLOBAL char *
-ngt_RandomStr( char *String, const size_t len)
+ngt_RandomStr(char *String, const size_t len)
 {
-       assert(String != NULL);
+       static const char chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!\"#$&'()*+,-./:;<=>?@[\\]^_`";
+       struct timeval t;
+       size_t i;
 
-       static const char chars[] = 
-               "0123456789ABCDEFGHIJKLMNO"
-               "PQRSTUVWXYZabcdefghijklmn"
-               "opqrstuvwxyz!\"#$&'()*+,-"
-               "./:;<=>?@[\\]^_`";
+       assert(String != NULL);
 
-       struct timeval t;
        gettimeofday(&t, NULL);
        srand((unsigned)(t.tv_usec * t.tv_sec));
 
-       for (size_t i = 0; i < len; ++i) {
+       for (i = 0; i < len; ++i) {
                String[i] = chars[rand() % (sizeof(chars) - 1)];
        }
-
        String[len] = '\0';
 
        return String;