anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
ratbox.cpp (12727B)
1 /* Ratbox IRCD functions 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "module.h" 13 14 static Anope::string UplinkSID; 15 16 static ServiceReference<IRCDProto> hybrid("IRCDProto", "hybrid"); 17 18 class RatboxProto : public IRCDProto 19 { 20 BotInfo *FindIntroduced() 21 { 22 BotInfo *bi = Config->GetClient("OperServ"); 23 24 if (bi && bi->introduced) 25 return bi; 26 27 for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) 28 if (it->second->introduced) 29 return it->second; 30 31 return NULL; 32 } 33 34 public: 35 RatboxProto(Module *creator) : IRCDProto(creator, "Ratbox 3.0+") 36 { 37 DefaultPseudoclientModes = "+oiS"; 38 CanSNLine = true; 39 CanSQLine = true; 40 CanSQLineChannel = true; 41 CanSZLine = true; 42 RequiresID = true; 43 MaxModes = 4; 44 } 45 46 void SendSVSKillInternal(const MessageSource &source, User *targ, const Anope::string &reason) anope_override { hybrid->SendSVSKillInternal(source, targ, reason); } 47 void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalNotice(bi, dest, msg); } 48 void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalPrivmsg(bi, dest, msg); } 49 void SendSGLine(User *u, const XLine *x) anope_override { hybrid->SendSGLine(u, x); } 50 void SendSGLineDel(const XLine *x) anope_override { hybrid->SendSGLineDel(x); } 51 void SendAkill(User *u, XLine *x) anope_override { hybrid->SendAkill(u, x); } 52 void SendAkillDel(const XLine *x) anope_override { hybrid->SendAkillDel(x); } 53 void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { hybrid->SendJoin(user, c, status); } 54 void SendServer(const Server *server) anope_override { hybrid->SendServer(server); } 55 void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override { hybrid->SendModeInternal(source, u, buf); } 56 void SendChannel(Channel *c) anope_override { hybrid->SendChannel(c); } 57 bool IsIdentValid(const Anope::string &ident) anope_override { return hybrid->IsIdentValid(ident); } 58 59 void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override 60 { 61 UplinkSocket::Message(source) << "OPERWALL :" << buf; 62 } 63 64 void SendSQLine(User *, const XLine *x) anope_override 65 { 66 /* Calculate the time left before this would expire, capping it at 2 days */ 67 time_t timeleft = x->expires - Anope::CurTime; 68 69 if (timeleft > 172800 || !x->expires) 70 timeleft = 172800; 71 72 UplinkSocket::Message(FindIntroduced()) << "ENCAP * RESV " << timeleft << " " << x->mask << " 0 :" << x->GetReason(); 73 } 74 75 void SendSQLineDel(const XLine *x) anope_override 76 { 77 UplinkSocket::Message(Config->GetClient("OperServ")) << "ENCAP * UNRESV " << x->mask; 78 } 79 80 void SendConnect() anope_override 81 { 82 UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " TS 6 :" << Me->GetSID(); 83 /* 84 QS - Can handle quit storm removal 85 EX - Can do channel +e exemptions 86 CHW - Can do channel wall @# 87 IE - Can do invite exceptions 88 GLN - Can do GLINE message 89 KNOCK - supports KNOCK 90 TB - supports topic burst 91 ENCAP - supports ENCAP 92 */ 93 UplinkSocket::Message() << "CAPAB :QS EX CHW IE GLN TB ENCAP"; 94 /* Make myself known to myself in the serverlist */ 95 SendServer(Me); 96 /* 97 * SVINFO 98 * parv[0] = sender prefix 99 * parv[1] = TS_CURRENT for the server 100 * parv[2] = TS_MIN for the server 101 * parv[3] = server is standalone or connected to non-TS only 102 * parv[4] = server's idea of UTC time 103 */ 104 UplinkSocket::Message() << "SVINFO 6 3 0 :" << Anope::CurTime; 105 } 106 107 void SendClientIntroduction(User *u) anope_override 108 { 109 Anope::string modes = "+" + u->GetModes(); 110 UplinkSocket::Message(Me) << "UID " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " " << u->host << " 0 " << u->GetUID() << " :" << u->realname; 111 } 112 113 void SendLogin(User *u, NickAlias *na) anope_override 114 { 115 if (na->nc->HasExt("UNCONFIRMED")) 116 return; 117 118 UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID() << " " << na->nc->display; 119 } 120 121 void SendLogout(User *u) anope_override 122 { 123 UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID(); 124 } 125 126 void SendTopic(const MessageSource &source, Channel *c) anope_override 127 { 128 BotInfo *bi = source.GetBot(); 129 bool needjoin = c->FindUser(bi) == NULL; 130 131 if (needjoin) 132 { 133 ChannelStatus status; 134 135 status.AddMode('o'); 136 bi->Join(c, &status); 137 } 138 139 IRCDProto::SendTopic(source, c); 140 141 if (needjoin) 142 bi->Part(c); 143 } 144 }; 145 146 struct IRCDMessageEncap : IRCDMessage 147 { 148 IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 3) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } 149 150 // Debug: Received: :00BAAAAAB ENCAP * LOGIN Adam 151 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 152 { 153 if (params[1] == "LOGIN" || params[1] == "SU") 154 { 155 User *u = source.GetUser(); 156 157 NickCore *nc = NickCore::Find(params[2]); 158 if (!nc) 159 return; 160 u->Login(nc); 161 162 /* Sometimes a user connects, we send them the usual "this nickname is registered" mess (if 163 * their server isn't syncing) and then we receive this.. so tell them about it. 164 */ 165 if (u->server->IsSynced()) 166 u->SendMessage(Config->GetClient("NickServ"), _("You have been logged in as \002%s\002."), nc->display.c_str()); 167 } 168 } 169 }; 170 171 struct IRCDMessageJoin : Message::Join 172 { 173 IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { } 174 175 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 176 { 177 if (params.size() == 1 && params[0] == "0") 178 return Message::Join::Run(source, params); 179 180 if (params.size() < 2) 181 return; 182 183 std::vector<Anope::string> p = params; 184 p.erase(p.begin()); 185 186 return Message::Join::Run(source, p); 187 } 188 }; 189 190 struct IRCDMessagePass : IRCDMessage 191 { 192 IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 193 194 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 195 { 196 UplinkSID = params[3]; 197 } 198 }; 199 200 struct IRCDMessageServer : IRCDMessage 201 { 202 IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 203 204 // SERVER hades.arpa 1 :ircd-ratbox test server 205 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 206 { 207 // Servers other then our immediate uplink are introduced via SID 208 if (params[1] != "1") 209 return; 210 new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], 1, params[2], UplinkSID); 211 IRCD->SendPing(Me->GetName(), params[0]); 212 } 213 }; 214 215 struct IRCDMessageTBurst : IRCDMessage 216 { 217 IRCDMessageTBurst(Module *creator) : IRCDMessage(creator, "TB", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 218 219 /* 220 * params[0] = channel 221 * params[1] = ts 222 * params[2] = topic OR who set the topic 223 * params[3] = topic if params[2] isn't the topic 224 */ 225 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 226 { 227 time_t topic_time = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime; 228 Channel *c = Channel::Find(params[0]); 229 230 if (!c) 231 return; 232 233 const Anope::string &setter = params.size() == 4 ? params[2] : "", 234 topic = params.size() == 4 ? params[3] : params[2]; 235 236 c->ChangeTopicInternal(NULL, setter, topic, topic_time); 237 } 238 }; 239 240 struct IRCDMessageUID : IRCDMessage 241 { 242 IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 9) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 243 244 // :42X UID Adam 1 1348535644 +aow Adam 192.168.0.5 192.168.0.5 42XAAAAAB :Adam 245 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 246 { 247 /* Source is always the server */ 248 User::OnIntroduce(params[0], params[4], params[5], "", params[6], source.GetServer(), params[8], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[3], params[7], NULL); 249 } 250 }; 251 252 class ProtoRatbox : public Module 253 { 254 Module *m_hybrid; 255 256 RatboxProto ircd_proto; 257 258 /* Core message handlers */ 259 Message::Away message_away; 260 Message::Capab message_capab; 261 Message::Error message_error; 262 Message::Invite message_invite; 263 Message::Kick message_kick; 264 Message::Kill message_kill; 265 Message::Mode message_mode; 266 Message::MOTD message_motd; 267 Message::Notice message_notice; 268 Message::Part message_part; 269 Message::Ping message_ping; 270 Message::Privmsg message_privmsg; 271 Message::Quit message_quit; 272 Message::SQuit message_squit; 273 Message::Stats message_stats; 274 Message::Time message_time; 275 Message::Topic message_topic; 276 Message::Version message_version; 277 Message::Whois message_whois; 278 279 /* Hybrid message handlers */ 280 ServiceAlias message_bmask, message_nick, message_pong, message_sid, 281 message_sjoin, message_tmode; 282 283 /* Our message handlers */ 284 IRCDMessageEncap message_encap; 285 IRCDMessageJoin message_join; 286 IRCDMessagePass message_pass; 287 IRCDMessageServer message_server; 288 IRCDMessageTBurst message_tburst; 289 IRCDMessageUID message_uid; 290 291 void AddModes() 292 { 293 /* user modes */ 294 ModeManager::AddUserMode(new UserModeOperOnly("ADMIN", 'a')); 295 ModeManager::AddUserMode(new UserModeOperOnly("BOT", 'b')); 296 // c/C = con 297 // d = debug? 298 ModeManager::AddUserMode(new UserMode("DEAF", 'D')); 299 // f = full? 300 ModeManager::AddUserMode(new UserMode("CALLERID", 'g')); 301 ModeManager::AddUserMode(new UserMode("INVIS", 'i')); 302 // k = skill? 303 ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l')); 304 // n = nchange 305 ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o')); 306 // r = rej 307 ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's')); 308 ModeManager::AddUserMode(new UserModeNoone("PROTECTED", 'S')); 309 // u = unauth? 310 ModeManager::AddUserMode(new UserMode("WALLOPS", 'w')); 311 // x = external? 312 // y = spy? 313 ModeManager::AddUserMode(new UserModeOperOnly("OPERWALLS", 'z')); 314 // Z = spy? 315 316 /* b/e/I */ 317 ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b')); 318 ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e')); 319 ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I')); 320 321 /* v/h/o/a/q */ 322 ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', 0)); 323 ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', 1)); 324 325 /* l/k */ 326 ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true)); 327 ModeManager::AddChannelMode(new ChannelModeKey('k')); 328 329 /* channel modes */ 330 ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i')); 331 ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm')); 332 ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n')); 333 ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p')); 334 ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'r')); 335 ModeManager::AddChannelMode(new ChannelMode("SECRET", 's')); 336 ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't')); 337 ModeManager::AddChannelMode(new ChannelMode("SSL", 'S')); 338 } 339 340 public: 341 ProtoRatbox(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR), 342 ircd_proto(this), 343 message_away(this), message_capab(this), message_error(this), message_invite(this), message_kick(this), 344 message_kill(this), message_mode(this), message_motd(this), message_notice(this), message_part(this), 345 message_ping(this), message_privmsg(this), message_quit(this), message_squit(this), message_stats(this), 346 message_time(this), message_topic(this), message_version(this), message_whois(this), 347 348 message_bmask("IRCDMessage", "ratbox/bmask", "hybrid/bmask"), message_nick("IRCDMessage", "ratbox/nick", "hybrid/nick"), 349 message_pong("IRCDMessage", "ratbox/pong", "hybrid/pong"), message_sid("IRCDMessage", "ratbox/sid", "hybrid/sid"), 350 message_sjoin("IRCDMessage", "ratbox/sjoin", "hybrid/sjoin"), message_tmode("IRCDMessage", "ratbox/tmode", "hybrid/tmode"), 351 352 message_encap(this), message_join(this), message_pass(this), message_server(this), message_tburst(this), message_uid(this) 353 { 354 355 if (ModuleManager::LoadModule("hybrid", User::Find(creator)) != MOD_ERR_OK) 356 throw ModuleException("Unable to load hybrid"); 357 m_hybrid = ModuleManager::FindModule("hybrid"); 358 if (!m_hybrid) 359 throw ModuleException("Unable to find hybrid"); 360 if (!hybrid) 361 throw ModuleException("No protocol interface for hybrid"); 362 363 this->AddModes(); 364 } 365 366 ~ProtoRatbox() 367 { 368 m_hybrid = ModuleManager::FindModule("hybrid"); 369 ModuleManager::UnloadModule(m_hybrid, NULL); 370 } 371 }; 372 373 MODULE_INIT(ProtoRatbox)