/** 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, (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 if ((addr->in6_16[0] == htons(0x2001)) && (addr->in6_16[1] == 0)) inttobase64(buf, (ntohs(addr->in6_16[6] ^ 0xFFFF) << 16) | ntohs(addr->in6_16[7] ^ 0xFFFF), 6); else strcpy(buf, "AAAAAA"); } else { unsigned int max_start, max_zeros, curr_zeros, zero, ii; char *output = buf; assert(count >= 25); /* Can start by printing out the leading non-zero parts. */ for (ii = 0; (addr->in6_16[ii]) && (ii < 8); ++ii) { inttobase64(output, ntohs(addr->in6_16[ii]), 3); output += 3; } /* Find the longest run of zeros. */ for (max_start = zero = ii, max_zeros = curr_zeros = 0; ii < 8; ++ii) { if (!addr->in6_16[ii]) curr_zeros++; else if (curr_zeros > max_zeros) { max_start = ii - curr_zeros; max_zeros = curr_zeros; curr_zeros = 0; } } if (curr_zeros > max_zeros) { max_start = ii - curr_zeros; max_zeros = curr_zeros; curr_zeros = 0; } /* Print the rest of the address */ for (ii = zero; ii < 8; ) { if ((ii == max_start) && max_zeros) { *output++ = '_'; ii += max_zeros; } else { inttobase64(output, ntohs(addr->in6_16[ii]), 3); output += 3; ii++; } } *output = '\0'; } return buf; }
/** 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); assert(numeric < NN_MAX_SERVER); inttobase64(cli_yxx(c), numeric, 2); if (numeric >= lastNNServer) lastNNServer = numeric + 1; server_list[numeric] = c; }
void asuka_cmd_connect(void) { if (!BadPtr(Numeric)) { inttobase64(p10id, atoi(Numeric), 2); me_server = do_server(NULL, ServerName, (char *) "0", ServerDesc, p10id); asuka_cmd_pass(RemotePassword); asuka_cmd_server(ServerName, 1, ServerDesc); } else { alog(LOG_NORMAL, "Numeric is required for P10 ircds"); exit(1); } }
/** 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) { static unsigned int last_nn = 0; struct Client** client_list = cli_serv(&me)->client_list; unsigned int mask = cli_serv(&me)->nn_mask; unsigned int count = 0; assert(cli_user(cptr)->server == &me); while (client_list[last_nn & mask]) { if (++count == NN_MAX_CLIENT) { assert(count < NN_MAX_CLIENT); return 0; } if (++last_nn == NN_MAX_CLIENT) last_nn = 0; } client_list[last_nn & mask] = cptr; /* Reserve the numeric ! */ inttobase64(cli_yxx(cptr), last_nn, 3); if (++last_nn == NN_MAX_CLIENT) last_nn = 0; return 1; }
/** 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) max_clients <<= 1; /* * Sanity checks */ if (max_clients > NN_MAX_CLIENT) { fprintf(stderr, "MAXCLIENTS (or MAXCONNECTIONS) is (at least) %d " "too large ! Please decrease this value.\n", max_clients - NN_MAX_CLIENT); exit(-1); } --max_clients; 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, sizeof(struct Client*)); server_list[base64toint(cli_yxx(c))] = c; }
bool CProtocol::Initialize ( const CSocket& socket, const CConfig& config ) { m_socket = socket; m_config = config; // Inicializamos la autenticación CString szHost; if ( ! m_config.GetValue ( szHost, "bots", "host" ) ) return false; CString szNumeric; if ( ! m_config.GetValue ( szNumeric, "bots", "numeric" ) ) return false; CString szPass; if ( ! m_config.GetValue ( szPass, "server", "password" ) ) return false; CString szDesc; if ( ! m_config.GetValue ( szDesc, "bots", "description" ) ) return false; CString szFlags; if ( ! m_config.GetValue ( szFlags, "bots", "flags" ) ) return false; if ( ! m_config.GetValue ( m_szHiddenAddress, "bots", "hiddenAddress" ) ) return false; if ( ! m_config.GetValue ( m_szHiddenDesc, "bots", "hiddenDesc" ) ) return false; // Generamos el numérico char szYXX [ 4 ]; memset ( szYXX, 0, sizeof ( szYXX ) ); unsigned long ulNumeric = atol ( szNumeric ); if ( ulNumeric > 4095 ) inttobase64 ( szYXX, ulNumeric, 2 ); else inttobase64 ( szYXX, ulNumeric, 1 ); // Limpiamos los flags if ( *szFlags == '+' ) szFlags = szFlags.substr ( 1 ); // Creamos nuestra estructura de servidor m_me.Create ( 0, szYXX, szHost, szDesc, szFlags ); // Negociamos la conexión unsigned long ulMaxusers; if ( ulNumeric > 63 ) ulMaxusers = 262143; else ulMaxusers = 4095; Send ( CMessagePASS ( szPass ) ); Send ( CMessageSERVER ( szHost, 1, time ( 0 ), "J10", szYXX, ulMaxusers, szFlags, szDesc ) ); // Enviamos la versión de base de datos Send ( CMessageDB ( "*", 0, 0, 0, "", "", 2 ), &m_me ); // Solicitamos las tablas for ( unsigned char ucTable = 'a'; ucTable <= 'z'; ++ucTable ) Send ( CMessageDB ( "*", 'J', 0, ucTable, "", "", 0 ), &m_me ); for ( unsigned char ucTable = 'A'; ucTable <= 'Z'; ++ucTable ) Send ( CMessageDB ( "*", 'J', 0, ucTable, "", "", 0 ), &m_me ); // Registramos eventos InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageEND_OF_BURST(), PROTOCOL_CALLBACK ( &CProtocol::evtEndOfBurst, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessagePING(), PROTOCOL_CALLBACK ( &CProtocol::evtPing, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageSERVER(), PROTOCOL_CALLBACK ( &CProtocol::evtServer, this ) ); InternalAddHandler ( HANDLER_AFTER_CALLBACKS, CMessageSQUIT(), PROTOCOL_CALLBACK ( &CProtocol::evtSquit, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageNICK(), PROTOCOL_CALLBACK ( &CProtocol::evtNick, this ) ); InternalAddHandler ( HANDLER_AFTER_CALLBACKS, CMessageQUIT(), PROTOCOL_CALLBACK ( &CProtocol::evtQuit, this ) ); InternalAddHandler ( HANDLER_AFTER_CALLBACKS, CMessageKILL(), PROTOCOL_CALLBACK ( &CProtocol::evtKill, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageMODE(), PROTOCOL_CALLBACK ( &CProtocol::evtMode, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageBMODE(), PROTOCOL_CALLBACK ( &CProtocol::evtBmode, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageBURST(), PROTOCOL_CALLBACK ( &CProtocol::evtBurst, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageTBURST(), PROTOCOL_CALLBACK ( &CProtocol::evtTburst, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageTOPIC(), PROTOCOL_CALLBACK ( &CProtocol::evtTopic, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageCREATE(), PROTOCOL_CALLBACK ( &CProtocol::evtCreate, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageJOIN(), PROTOCOL_CALLBACK ( &CProtocol::evtJoin, this ) ); InternalAddHandler ( HANDLER_AFTER_CALLBACKS, CMessagePART(), PROTOCOL_CALLBACK ( &CProtocol::evtPart, this ) ); InternalAddHandler ( HANDLER_AFTER_CALLBACKS, CMessageKICK(), PROTOCOL_CALLBACK ( &CProtocol::evtKick, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageDB(), PROTOCOL_CALLBACK ( &CProtocol::evtDB, this ) ); InternalAddHandler ( HANDLER_IN_CALLBACKS, CMessageRAW(), PROTOCOL_CALLBACK ( &CProtocol::evtRaw, this ) ); InternalAddHandler ( HANDLER_BEFORE_CALLBACKS, CMessageAWAY(), PROTOCOL_CALLBACK ( &CProtocol::evtAway, this ) ); InternalAddHandler ( HANDLER_AFTER_CALLBACKS, CMessageWHOIS(), PROTOCOL_CALLBACK ( &CProtocol::evtWhois, this ) ); // Inicializamos los servicios CService::RegisterServices ( m_config ); // Finalizamos el negociado Send ( CMessageEND_OF_BURST (), &m_me ); return true; }