X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fnumnicks.c;h=66e432135d23db284df65b3e1c1b0a03518bd2c8;hb=a36ad5e29241b0c89379947b13887cb6930ef3e0;hp=781ff6f8a263513a9f591fb5ae32af66110b6174;hpb=9b1f5beca29ec78141f19a19d689f0f7cc3fe3ac;p=ircu2.10.12-pk.git diff --git a/ircd/numnicks.c b/ircd/numnicks.c index 781ff6f..66e4321 100644 --- a/ircd/numnicks.c +++ b/ircd/numnicks.c @@ -15,8 +15,10 @@ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id$ + */ +/** @file + * @brief Implementation of numeric nickname operations. + * @version $Id$ */ #include "config.h" @@ -24,6 +26,7 @@ #include "client.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_log.h" #include "ircd_string.h" #include "match.h" #include "s_bsd.h" @@ -31,28 +34,28 @@ #include "s_misc.h" #include "struct.h" -#include +/* #include -- Now using assert in ircd_log.h */ #include #include #include -/* - * Numeric nicks are new as of version ircu2.10.00beta1. +/** @page numnicks Numeric Nicks + * %Numeric nicks (numnicks) are new as of version ircu2.10.00beta1. * * The idea is as follows: * In most messages (for protocol 10+) the original nick will be - * replaced by a 3 character string: YXX - * Where 'Y' represents the server, and 'XX' the nick on that server. + * replaced by a 5 character string: YYXXX + * Where 'YY' represents the server, and 'XXX' the nick on that server. * - * 'YXX' should not interfer with the input parser, and therefore is + * 'YYXXX' should not interfere with the input parser, and therefore is * not allowed to contain spaces or a ':'. - * Also, 'Y' can't start with a '+' because of m_server(). + * Also, 'YY' can't start with a '+' because of m_server(). * * We keep the characters printable for debugging reasons too. * - * The 'XX' value can be larger then the maximum number of clients - * per server, we use a mask (struct Server::nn_mask) to get the real + * The 'XXX' value can be larger then the maximum number of clients + * per server, we use a mask (Server::nn_mask) to get the real * client numeric. The overhead is used to have some redundancy so * just-disconnected-client aren't confused with just-connected ones. */ @@ -60,33 +63,40 @@ /* These must be the same on ALL servers ! Do not change ! */ +/** Number of bits encoded in one numnick character. */ #define NUMNICKLOG 6 -#define NUMNICKMAXCHAR 'z' /* See convert2n[] */ -#define NUMNICKBASE 64 /* (2 << NUMNICKLOG) */ +/** Bitmask to select value of next numnick character. */ #define NUMNICKMASK 63 /* (NUMNICKBASE-1) */ +/** Number of servers representable in a numnick. */ #define NN_MAX_SERVER 4096 /* (NUMNICKBASE * NUMNICKBASE) */ +/** Number of clients representable in a numnick. */ #define NN_MAX_CLIENT 262144 /* NUMNICKBASE ^ 3 */ /* * The internal counter for the 'XX' of local clients */ +/** Maximum used server numnick, plus one. */ static unsigned int lastNNServer = 0; +/** Array of servers indexed by numnick. */ static struct Client* server_list[NN_MAX_SERVER]; /* *INDENT-OFF* */ -/* - * convert2y[] converts a numeric to the corresponding character. +/** + * Converts a numeric to the corresponding character. * The following characters are currently known to be forbidden: * - * '\0' : Because we use '\0' as end of line. + * '\\0' : Because we use '\\0' as end of line. + * + * ' ' : Because parse_*() uses this as parameter separator. * - * ' ' : Because parse_*() uses this as parameter seperator. * ':' : Because parse_server() uses this to detect if a prefix is a * numeric or a name. + * * '+' : Because m_nick() uses this to determine if parv[6] is a * umode or not. - * '&', '#', '+', '$', '@' and '%' : + * + * '&', '#', '$', '@' and '%' : * Because m_message() matches these characters to detect special cases. */ static const char convert2y[] = { @@ -96,11 +106,12 @@ static const char convert2y[] = { 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','[',']' }; +/** Converts a character to its (base64) numnick value. */ static const unsigned int convert2n[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 52,53,54,55,56,57,58,59,60,61, 0, 0, 0, 0, 0, 0, + 52,53,54,55,56,57,58,59,60,61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25,62, 0,63, 0, 0, 0,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, @@ -118,7 +129,10 @@ static const unsigned int convert2n[] = { /* *INDENT-ON* */ - +/** Convert a string to its value as a numnick. + * @param[in] s Numnick string to decode. + * @return %Numeric nickname value. + */ unsigned int base64toint(const char* s) { unsigned int i = convert2n[(unsigned char) *s++]; @@ -129,9 +143,14 @@ unsigned int base64toint(const char* s) return i; } +/** Encode a number as a numnick. + * @param[out] buf Output buffer. + * @param[in] v Value to encode. + * @param[in] count Number of numnick digits to write to \a buf. + */ const char* inttobase64(char* buf, unsigned int v, unsigned int count) { - buf[count] = '\0'; + buf[count] = '\0'; while (count > 0) { buf[--count] = convert2y[(v & NUMNICKMASK)]; v >>= NUMNICKLOG; @@ -139,6 +158,11 @@ const char* inttobase64(char* buf, unsigned int v, unsigned int count) return buf; } +/** Look up a server by numnick string. + * See @ref numnicks for more details. + * @param[in] numeric %Numeric nickname of server (may contain trailing junk). + * @return %Server with that numnick (or NULL). + */ static struct Client* FindXNServer(const char* numeric) { char buf[3]; @@ -149,6 +173,11 @@ static struct Client* FindXNServer(const char* numeric) return server_list[base64toint(buf)]; } +/** Look up a server by numnick string. + * See @ref numnicks for more details. + * @param[in] numeric %Numeric nickname of server. + * @return %Server with that numnick (or NULL). + */ struct Client* FindNServer(const char* numeric) { unsigned int len = strlen(numeric); @@ -165,6 +194,11 @@ struct Client* FindNServer(const char* numeric) return FindXNServer(numeric); } +/** Look up a user by numnick string. + * See @ref numnicks for more details. + * @param[in] yxx %Numeric nickname of user. + * @return %User with that numnick (or NULL). + */ struct Client* findNUser(const char* yxx) { struct Client* server = 0; @@ -183,6 +217,10 @@ struct Client* findNUser(const char* yxx) return 0; } +/** Remove a client from a server's user array. + * @param[in] server %Server that owns the user to remove. + * @param[in] yxx Numnick of client to remove. + */ void RemoveYXXClient(struct Client* server, const char* yxx) { assert(0 != server); @@ -194,6 +232,11 @@ void RemoveYXXClient(struct Client* server, const char* yxx) } } +/** Set a server's numeric nick. + * @param[in] cptr %Client that announced the server (ignored). + * @param[in,out] server %Server that is being assigned a numnick. + * @param[in] yxx %Numeric nickname for server. + */ void SetServerYXX(struct Client* cptr, struct Client* server, const char* yxx) { unsigned int index; @@ -220,10 +263,14 @@ void SetServerYXX(struct Client* cptr, struct Client* server, const char* yxx) (struct Client**) MyCalloc(cli_serv(server)->nn_mask + 1, sizeof(struct Client*)); } +/** Set a server's capacity. + * @param[in] c %Server whose capacity is being set. + * @param[in] capacity Maximum number of clients the server supports. + */ void SetYXXCapacity(struct Client* c, unsigned int capacity) { unsigned int max_clients = 16; - /* + /* * Calculate mask to be used for the maximum number of clients */ while (max_clients < capacity) @@ -238,13 +285,18 @@ void SetYXXCapacity(struct Client* c, unsigned int capacity) exit(-1); } --max_clients; - inttobase64(cli_serv(c)->nn_capacity, max_clients, 3); + inttobase64(cli_serv(c)->nn_capacity, max_clients, 3); cli_serv(c)->nn_mask = max_clients; /* Our Numeric Nick mask */ - cli_serv(c)->client_list = (struct Client**) MyCalloc(max_clients + 1, + cli_serv(c)->client_list = (struct Client**) MyCalloc(max_clients + 1, sizeof(struct Client*)); server_list[base64toint(cli_yxx(c))] = c; } +/** Set a server's numeric nick. + * See @ref numnicks for more details. + * @param[in] c %Server that is being assigned a numnick. + * @param[in] numeric Numnick value for server. + */ void SetYXXServerName(struct Client* c, unsigned int numeric) { assert(0 != c); @@ -256,6 +308,9 @@ void SetYXXServerName(struct Client* c, unsigned int numeric) server_list[numeric] = c; } +/** Unassign a server's numnick. + * @param[in] server %Server that should be removed from the numnick table. + */ void ClearServerYXX(const struct Client *server) { unsigned int index = base64toint(cli_yxx(server)); @@ -263,17 +318,17 @@ void ClearServerYXX(const struct Client *server) server_list[index] = 0; } -/* - * SetRemoteNumNick() - * - * Register numeric of new, remote, client. +/** Register numeric of new (remote) client. + * See @ref numnicks for more details. * Add it to the appropriate client_list. + * @param[in] acptr %User being registered. + * @param[in] yxx User's numnick. */ void SetRemoteNumNick(struct Client* acptr, const char *yxx) { struct Client** acptrp; struct Client* server = cli_user(acptr)->server; - + if (5 == strlen(yxx)) { strcpy(cli_yxx(acptr), yxx + 2); } @@ -282,7 +337,7 @@ void SetRemoteNumNick(struct Client* acptr, const char *yxx) (cli_yxx(acptr))[1] = *++yxx; (cli_yxx(acptr))[2] = 0; } - Debug((DEBUG_DEBUG, "SetRemoteNumNick: %s(%d)", cli_yxx(acptr), + Debug((DEBUG_DEBUG, "SetRemoteNumNick: %s(%d)", cli_yxx(acptr), base64toint(cli_yxx(acptr)) & cli_serv(server)->nn_mask)); acptrp = &(cli_serv(server))->client_list[base64toint(cli_yxx(acptr)) & cli_serv(server)->nn_mask]; @@ -297,11 +352,10 @@ void SetRemoteNumNick(struct Client* acptr, const char *yxx) } -/* - * SetLocalNumNick() - * - * Register numeric of new, local, client. Add it to our client_list. - * Muxtex needed if threaded +/** Register numeric of new (local) client. + * See @ref numnicks for more details. + * Assign a numnick and add it to our client_list. + * @param[in] cptr %User being registered. */ int SetLocalNumNick(struct Client *cptr) { @@ -328,10 +382,11 @@ int SetLocalNumNick(struct Client *cptr) return 1; } -/* - * markMatchexServer() - * Mark all servers whose name matches the given (compiled) mask - * and return their count, abusing FLAGS_MAP for this :) +/** Mark servers whose name matches the given (compiled) mask by + * setting their FLAG_MAP flag. + * @param[in] cmask Compiled mask for server names. + * @param[in] minlen Minimum match length for \a cmask. + * @return Number of servers marked. */ int markMatchexServer(const char *cmask, int minlen) { @@ -354,6 +409,10 @@ int markMatchexServer(const char *cmask, int minlen) return cnt; } +/** Find first server whose name matches the given mask. + * @param[in,out] mask %Server name mask (collapse()d in-place). + * @return Matching server with lowest numnick value (or NULL). + */ struct Client* find_match_server(char *mask) { struct Client *acptr; @@ -369,11 +428,30 @@ struct Client* find_match_server(char *mask) return 0; } -const char* iptobase64(char* buf, const struct irc_in_addr* addr, unsigned int count) +/** Encode an IP address in the base64 used by numnicks. + * For IPv4 addresses (including IPv4-mapped and IPv4-compatible IPv6 + * addresses), the 32-bit host address is encoded directly as six + * characters. + * + * For IPv6 addresses, each 16-bit address segment is encoded as three + * characters, but the longest run of zero segments is encoded using an + * underscore. + * @param[out] buf Output buffer to write to. + * @param[in] addr IP address to encode. + * @param[in] count Number of bytes writable to \a buf. + * @param[in] v6_ok If non-zero, peer understands base-64 encoded IPv6 addresses. + */ +const char* iptobase64(char* buf, const struct irc_in_addr* addr, unsigned int count, int v6_ok) { if (irc_in_addr_is_ipv4(addr)) { assert(count >= 6); - inttobase64(buf, (htons(addr->in6_16[6]) << 16) | htons(addr->in6_16[7]), 6); + inttobase64(buf, (ntohs(addr->in6_16[6]) << 16) | ntohs(addr->in6_16[7]), 6); + } else if (!v6_ok) { + assert(count >= 6); + if (addr->in6_16[0] == htons(0x2002)) + inttobase64(buf, (ntohs(addr->in6_16[1]) << 16) | ntohs(addr->in6_16[2]), 6); + else + strcpy(buf, "AAAAAA"); } else { unsigned int max_start, max_zeros, curr_zeros, zero, ii; char *output = buf; @@ -415,19 +493,27 @@ const char* iptobase64(char* buf, const struct irc_in_addr* addr, unsigned int c return buf; } +/** Decode an IP address from base64. + * @param[in] input Input buffer to decode. + * @param[out] addr IP address structure to populate. + */ void base64toip(const char* input, struct irc_in_addr* addr) { memset(addr, 0, sizeof(*addr)); if (strlen(input) == 6) { unsigned int in = base64toint(input); - addr->in6_16[6] = htons(in >> 16); - addr->in6_16[7] = htons(in & 65535); + /* An all-zero address should stay that way. */ + if (in) { + addr->in6_16[5] = htons(65535); + addr->in6_16[6] = htons(in >> 16); + addr->in6_16[7] = htons(in & 65535); + } } else { unsigned int pos = 0; do { if (*input == '_') { unsigned int left; - for (left = (strlen(input) - 1) / 3; left; left--) + for (left = (25 - strlen(input)) / 3 - pos; left; left--) addr->in6_16[pos++] = 0; input++; } else { @@ -435,7 +521,6 @@ void base64toip(const char* input, struct irc_in_addr* addr) accum = (accum << NUMNICKLOG) | convert2n[(unsigned char)*input++]; accum = (accum << NUMNICKLOG) | convert2n[(unsigned char)*input++]; addr->in6_16[pos++] = ntohs(accum); - input += 3; } } while (pos < 8); }