server.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576
  1. #ifdef LEAF
  2. /*
  3. * server.c -- part of server.mod
  4. * basic irc server support
  5. *
  6. */
  7. #include "src/common.h"
  8. #include "src/cfg.h"
  9. #include "src/botmsg.h"
  10. #include "src/rfc1459.h"
  11. #include "src/settings.h"
  12. #include "src/tclhash.h"
  13. #include "src/users.h"
  14. #include "src/userrec.h"
  15. #include "src/main.h"
  16. #include "src/misc.h"
  17. #include "src/chanprog.h"
  18. #include "src/hooks.h"
  19. #include "src/net.h"
  20. #include "src/auth.h"
  21. #include "src/dns.h"
  22. #include "src/egg_timer.h"
  23. #include "src/mod/channels.mod/channels.h"
  24. #include "server.h"
  25. extern struct cfg_entry CFG_OPTIMESLACK;
  26. int checked_hostmask; /* Used in request_op()/check_hostmask() cleared on connect */
  27. int ctcp_mode;
  28. int serv; /* sock # of server currently */
  29. int servidx; /* idx of server */
  30. char newserver[121] = ""; /* new server? */
  31. int newserverport; /* new server port? */
  32. char newserverpass[121] = ""; /* new server password? */
  33. static time_t trying_server; /* trying to connect to a server right now? */
  34. static int curserv; /* current position in server list: */
  35. int flud_thr; /* msg flood threshold */
  36. int flud_time; /* msg flood time */
  37. int flud_ctcp_thr; /* ctcp flood threshold */
  38. int flud_ctcp_time; /* ctcp flood time */
  39. char botuserhost[121] = ""; /* bot's user@host (refreshed whenever the
  40. bot joins a channel) */
  41. /* may not be correct user@host BUT it's
  42. how the server sees it */
  43. static int keepnick; /* keep trying to regain my intended
  44. nickname? */
  45. static int nick_juped = 0; /* True if origbotname is juped(RPL437) (dw) */
  46. static int check_stoned; /* Check for a stoned server? */
  47. static int serverror_quit; /* Disconnect from server if ERROR
  48. messages received? */
  49. int quiet_reject; /* Quietly reject dcc chat or sends from
  50. users without access? */
  51. static int waiting_for_awake; /* set when i unidle myself, cleared when
  52. i get the response */
  53. time_t server_online; /* server connection time */
  54. static time_t server_cycle_wait; /* seconds to wait before
  55. re-beginning the server list */
  56. char botrealname[121] = ""; /* realname of bot */
  57. static int server_timeout; /* server timeout for connecting */
  58. static int never_give_up; /* never give up when connecting to servers? */
  59. static int strict_servernames; /* don't update server list */
  60. static struct server_list *serverlist = NULL; /* old-style queue, still used by
  61. server list */
  62. int cycle_time; /* cycle time till next server connect */
  63. int default_port; /* default IRC port */
  64. static char oldnick[NICKLEN] = ""; /* previous nickname *before* rehash */
  65. int trigger_on_ignore; /* trigger bindings if user is ignored ? */
  66. int answer_ctcp; /* answer how many stacked ctcp's ? */
  67. static int lowercase_ctcp; /* answer lowercase CTCP's (non-standard) */
  68. static int check_mode_r; /* check for IRCNET +r modes */
  69. static int net_type;
  70. static int resolvserv; /* in the process of resolving a server host */
  71. static int double_mode; /* allow a msgs to be twice in a queue? */
  72. static int double_server;
  73. static int double_help;
  74. static int double_warned;
  75. static int lastpingtime; /* IRCNet LAGmeter support -- drummer */
  76. static char stackablecmds[511] = "";
  77. static char stackable2cmds[511] = "";
  78. static time_t last_time;
  79. static int use_penalties;
  80. static int use_fastdeq;
  81. int nick_len; /* Maximal nick length allowed on the network. */
  82. static int kick_method;
  83. static int optimize_kicks;
  84. static void empty_msgq(void);
  85. static void next_server(int *, char *, unsigned int *, char *);
  86. static void disconnect_server(int, int);
  87. static int calc_penalty(char *);
  88. static int fast_deq(int);
  89. static char *splitnicks(char **);
  90. static void check_queues(char *, char *);
  91. static void parse_q(struct msgq_head *, char *, char *);
  92. static void purge_kicks(struct msgq_head *);
  93. static int deq_kick(int);
  94. static void msgq_clear(struct msgq_head *qh);
  95. static int stack_limit;
  96. /* New bind tables. */
  97. static bind_table_t *BT_raw = NULL, *BT_msg = NULL;
  98. bind_table_t *BT_ctcr = NULL, *BT_ctcp = NULL;
  99. #ifdef S_AUTHCMDS
  100. bind_table_t *BT_msgc = NULL;
  101. #endif /* S_AUTHCMDS */
  102. #include "servmsg.c"
  103. #define MAXPENALTY 10
  104. /* Number of seconds to wait between transmitting queued lines to the server
  105. * lower this value at your own risk. ircd is known to start flood control
  106. * at 512 bytes/2 seconds.
  107. */
  108. #define msgrate 2
  109. /* Maximum messages to store in each queue. */
  110. static int maxqmsg;
  111. static struct msgq_head mq, hq, modeq;
  112. static int burst;
  113. #include "cmdsserv.c"
  114. /*
  115. * Bot server queues
  116. */
  117. /* Called periodically to shove out another queued item.
  118. *
  119. * 'mode' queue gets priority now.
  120. *
  121. * Most servers will allow 'busts' of upto 5 msgs, so let's put something
  122. * in to support flushing modeq a little faster if possible.
  123. * Will send upto 4 msgs from modeq, and then send 1 msg every time
  124. * it will *not* send anything from hq until the 'burst' value drops
  125. * down to 0 again (allowing a sudden mq flood to sneak through).
  126. */
  127. static void deq_msg()
  128. {
  129. struct msgq *q = NULL;
  130. int ok = 0;
  131. /* now < last_time tested 'cause clock adjustments could mess it up */
  132. if ((now - last_time) >= msgrate || now < (last_time - 90)) {
  133. last_time = now;
  134. if (burst > 0)
  135. burst--;
  136. ok = 1;
  137. }
  138. if (serv < 0)
  139. return;
  140. /* Send upto 4 msgs to server if the *critical queue* has anything in it */
  141. if (modeq.head) {
  142. while (modeq.head && (burst < 4) && ((last_time - now) < MAXPENALTY)) {
  143. if (deq_kick(DP_MODE)) {
  144. burst++;
  145. continue;
  146. }
  147. if (!modeq.head)
  148. break;
  149. if (fast_deq(DP_MODE)) {
  150. burst++;
  151. continue;
  152. }
  153. tputs(serv, modeq.head->msg, modeq.head->len);
  154. if (debug_output) {
  155. modeq.head->msg[strlen(modeq.head->msg) - 1] = 0; /* delete the "\n" */
  156. putlog(LOG_SRVOUT, "@", "[m->] %s", modeq.head->msg);
  157. }
  158. modeq.tot--;
  159. last_time += calc_penalty(modeq.head->msg);
  160. q = modeq.head->next;
  161. free(modeq.head->msg);
  162. free(modeq.head);
  163. modeq.head = q;
  164. burst++;
  165. }
  166. if (!modeq.head)
  167. modeq.last = 0;
  168. return;
  169. }
  170. /* Send something from the normal msg q even if we're slightly bursting */
  171. if (burst > 1)
  172. return;
  173. if (mq.head) {
  174. burst++;
  175. if (deq_kick(DP_SERVER))
  176. return;
  177. if (fast_deq(DP_SERVER))
  178. return;
  179. tputs(serv, mq.head->msg, mq.head->len);
  180. if (debug_output) {
  181. mq.head->msg[strlen(mq.head->msg) - 1] = 0; /* delete the "\n" */
  182. putlog(LOG_SRVOUT, "@", "[s->] %s", mq.head->msg);
  183. }
  184. mq.tot--;
  185. last_time += calc_penalty(mq.head->msg);
  186. q = mq.head->next;
  187. free(mq.head->msg);
  188. free(mq.head);
  189. mq.head = q;
  190. if (!mq.head)
  191. mq.last = NULL;
  192. return;
  193. }
  194. /* Never send anything from the help queue unless everything else is
  195. * finished.
  196. */
  197. if (!hq.head || burst || !ok)
  198. return;
  199. if (deq_kick(DP_HELP))
  200. return;
  201. if (fast_deq(DP_HELP))
  202. return;
  203. tputs(serv, hq.head->msg, hq.head->len);
  204. if (debug_output) {
  205. hq.head->msg[strlen(hq.head->msg) - 1] = 0; /* delete the "\n" */
  206. putlog(LOG_SRVOUT, "*", "[h->] %s", hq.head->msg);
  207. }
  208. hq.tot--;
  209. last_time += calc_penalty(hq.head->msg);
  210. q = hq.head->next;
  211. free(hq.head->msg);
  212. free(hq.head);
  213. hq.head = q;
  214. if (!hq.head)
  215. hq.last = NULL;
  216. }
  217. static int calc_penalty(char * msg)
  218. {
  219. char *cmd = NULL, *par1 = NULL, *par2 = NULL, *par3 = NULL;
  220. register int penalty, i, ii;
  221. if (!use_penalties &&
  222. net_type != NETT_UNDERNET && net_type != NETT_HYBRID_EFNET)
  223. return 0;
  224. if (msg[strlen(msg) - 1] == '\n')
  225. msg[strlen(msg) - 1] = '\0';
  226. cmd = newsplit(&msg);
  227. if (msg)
  228. i = strlen(msg);
  229. else
  230. i = strlen(cmd);
  231. last_time -= 2; /* undo eggdrop standard flood prot */
  232. if (net_type == NETT_UNDERNET || net_type == NETT_HYBRID_EFNET) {
  233. last_time += (2 + i / 120);
  234. return 0;
  235. }
  236. penalty = (1 + i / 100);
  237. if (!egg_strcasecmp(cmd, "KICK")) {
  238. par1 = newsplit(&msg); /* channel */
  239. par2 = newsplit(&msg); /* victim(s) */
  240. par3 = splitnicks(&par2);
  241. penalty++;
  242. while (strlen(par3) > 0) {
  243. par3 = splitnicks(&par2);
  244. penalty++;
  245. }
  246. ii = penalty;
  247. par3 = splitnicks(&par1);
  248. while (strlen(par1) > 0) {
  249. par3 = splitnicks(&par1);
  250. penalty += ii;
  251. }
  252. } else if (!egg_strcasecmp(cmd, "MODE")) {
  253. i = 0;
  254. par1 = newsplit(&msg); /* channel */
  255. par2 = newsplit(&msg); /* mode(s) */
  256. if (!strlen(par2))
  257. i++;
  258. while (strlen(par2) > 0) {
  259. if (strchr("ntimps", par2[0]))
  260. i += 3;
  261. else if (!strchr("+-", par2[0]))
  262. i += 1;
  263. par2++;
  264. }
  265. while (strlen(msg) > 0) {
  266. newsplit(&msg);
  267. i += 2;
  268. }
  269. ii = 0;
  270. while (strlen(par1) > 0) {
  271. splitnicks(&par1);
  272. ii++;
  273. }
  274. penalty += (ii * i);
  275. } else if (!egg_strcasecmp(cmd, "TOPIC")) {
  276. penalty++;
  277. par1 = newsplit(&msg); /* channel */
  278. par2 = newsplit(&msg); /* topic */
  279. if (strlen(par2) > 0) { /* topic manipulation => 2 penalty points */
  280. penalty += 2;
  281. par3 = splitnicks(&par1);
  282. while (strlen(par1) > 0) {
  283. par3 = splitnicks(&par1);
  284. penalty += 2;
  285. }
  286. }
  287. } else if (!egg_strcasecmp(cmd, "PRIVMSG") ||
  288. !egg_strcasecmp(cmd, "NOTICE")) {
  289. par1 = newsplit(&msg); /* channel(s)/nick(s) */
  290. /* Add one sec penalty for each recipient */
  291. while (strlen(par1) > 0) {
  292. splitnicks(&par1);
  293. penalty++;
  294. }
  295. } else if (!egg_strcasecmp(cmd, "WHO")) {
  296. par1 = newsplit(&msg); /* masks */
  297. par2 = par1;
  298. while (strlen(par1) > 0) {
  299. par2 = splitnicks(&par1);
  300. if (strlen(par2) > 4) /* long WHO-masks receive less penalty */
  301. penalty += 3;
  302. else
  303. penalty += 5;
  304. }
  305. } else if (!egg_strcasecmp(cmd, "AWAY")) {
  306. if (strlen(msg) > 0)
  307. penalty += 2;
  308. else
  309. penalty += 1;
  310. } else if (!egg_strcasecmp(cmd, "INVITE")) {
  311. /* Successful invite receives 2 or 3 penalty points. Let's go
  312. * with the maximum.
  313. */
  314. penalty += 3;
  315. } else if (!egg_strcasecmp(cmd, "JOIN")) {
  316. penalty += 2;
  317. } else if (!egg_strcasecmp(cmd, "PART")) {
  318. penalty += 4;
  319. } else if (!egg_strcasecmp(cmd, "VERSION")) {
  320. penalty += 2;
  321. } else if (!egg_strcasecmp(cmd, "TIME")) {
  322. penalty += 2;
  323. } else if (!egg_strcasecmp(cmd, "TRACE")) {
  324. penalty += 2;
  325. } else if (!egg_strcasecmp(cmd, "NICK")) {
  326. penalty += 3;
  327. } else if (!egg_strcasecmp(cmd, "ISON")) {
  328. penalty += 1;
  329. } else if (!egg_strcasecmp(cmd, "WHOIS")) {
  330. penalty += 2;
  331. } else if (!egg_strcasecmp(cmd, "DNS")) {
  332. penalty += 2;
  333. } else
  334. penalty++; /* just add standard-penalty */
  335. /* Shouldn't happen, but you never know... */
  336. if (penalty > 99)
  337. penalty = 99;
  338. if (penalty < 2) {
  339. putlog(LOG_SRVOUT, "*", "Penalty < 2sec, that's impossible!");
  340. penalty = 2;
  341. }
  342. if (debug_output && penalty != 0)
  343. putlog(LOG_SRVOUT, "*", "Adding penalty: %i", penalty);
  344. return penalty;
  345. }
  346. char *splitnicks(char **rest)
  347. {
  348. register char *o = NULL, *r = NULL;
  349. if (!rest)
  350. return *rest = "";
  351. o = *rest;
  352. while (*o == ' ')
  353. o++;
  354. r = o;
  355. while (*o && *o != ',')
  356. o++;
  357. if (*o)
  358. *o++ = 0;
  359. *rest = o;
  360. return r;
  361. }
  362. static int fast_deq(int which)
  363. {
  364. struct msgq_head *h = NULL;
  365. struct msgq *m = NULL, *nm = NULL;
  366. char msgstr[511] = "", nextmsgstr[511] = "", tosend[511] = "", victims[511] = "", stackable[511] = "",
  367. *msg = NULL, *nextmsg = NULL, *cmd = NULL, *nextcmd = NULL, *to = NULL, *nextto = NULL, *stckbl = NULL;
  368. int len, doit = 0, found = 0, cmd_count = 0, stack_method = 1;
  369. if (!use_fastdeq)
  370. return 0;
  371. switch (which) {
  372. case DP_MODE:
  373. h = &modeq;
  374. break;
  375. case DP_SERVER:
  376. h = &mq;
  377. break;
  378. case DP_HELP:
  379. h = &hq;
  380. break;
  381. default:
  382. return 0;
  383. }
  384. m = h->head;
  385. strncpyz(msgstr, m->msg, sizeof msgstr);
  386. msg = msgstr;
  387. cmd = newsplit(&msg);
  388. if (use_fastdeq > 1) {
  389. strncpyz(stackable, stackablecmds, sizeof stackable);
  390. stckbl = stackable;
  391. while (strlen(stckbl) > 0)
  392. if (!egg_strcasecmp(newsplit(&stckbl), cmd)) {
  393. found = 1;
  394. break;
  395. }
  396. /* If use_fastdeq is 2, only commands in the list should be stacked. */
  397. if (use_fastdeq == 2 && !found)
  398. return 0;
  399. /* If use_fastdeq is 3, only commands that are _not_ in the list
  400. * should be stacked.
  401. */
  402. if (use_fastdeq == 3 && found)
  403. return 0;
  404. /* we check for the stacking method (default=1) */
  405. strncpyz(stackable, stackable2cmds, sizeof stackable);
  406. stckbl = stackable;
  407. while (strlen(stckbl) > 0)
  408. if (!egg_strcasecmp(newsplit(&stckbl), cmd)) {
  409. stack_method = 2;
  410. break;
  411. }
  412. }
  413. to = newsplit(&msg);
  414. len = strlen(to);
  415. if (to[len - 1] == '\n')
  416. to[len -1] = 0;
  417. simple_sprintf(victims, "%s", to);
  418. while (m) {
  419. nm = m->next;
  420. if (!nm)
  421. break;
  422. strncpyz(nextmsgstr, nm->msg, sizeof nextmsgstr);
  423. nextmsg = nextmsgstr;
  424. nextcmd = newsplit(&nextmsg);
  425. nextto = newsplit(&nextmsg);
  426. len = strlen(nextto);
  427. if (nextto[len - 1] == '\n')
  428. nextto[len - 1] = 0;
  429. if ( strcmp(to, nextto) /* we don't stack to the same recipients */
  430. && !strcmp(cmd, nextcmd) && !strcmp(msg, nextmsg)
  431. && ((strlen(cmd) + strlen(victims) + strlen(nextto)
  432. + strlen(msg) + 2) < 510)
  433. && (!stack_limit || cmd_count < stack_limit - 1)) {
  434. cmd_count++;
  435. if (stack_method == 1)
  436. simple_sprintf(victims, "%s,%s", victims, nextto);
  437. else
  438. simple_sprintf(victims, "%s %s", victims, nextto);
  439. doit = 1;
  440. m->next = nm->next;
  441. if (!nm->next)
  442. h->last = m;
  443. free(nm->msg);
  444. free(nm);
  445. h->tot--;
  446. } else
  447. m = m->next;
  448. }
  449. if (doit) {
  450. simple_sprintf(tosend, "%s %s %s", cmd, victims, msg);
  451. len = strlen(tosend);
  452. tosend[len - 1] = '\n';
  453. tputs(serv, tosend, len);
  454. m = h->head->next;
  455. free(h->head->msg);
  456. free(h->head);
  457. h->head = m;
  458. if (!h->head)
  459. h->last = 0;
  460. h->tot--;
  461. if (debug_output) {
  462. tosend[len - 1] = 0;
  463. switch (which) {
  464. case DP_MODE:
  465. putlog(LOG_SRVOUT, "*", "[m=>] %s", tosend);
  466. break;
  467. case DP_SERVER:
  468. putlog(LOG_SRVOUT, "*", "[s=>] %s", tosend);
  469. break;
  470. case DP_HELP:
  471. putlog(LOG_SRVOUT, "*", "[h=>] %s", tosend);
  472. break;
  473. }
  474. }
  475. last_time += calc_penalty(tosend);
  476. return 1;
  477. }
  478. return 0;
  479. }
  480. static void check_queues(char *old_nick, char *newnick)
  481. {
  482. if (optimize_kicks == 2) {
  483. if (modeq.head)
  484. parse_q(&modeq, old_nick, newnick);
  485. if (mq.head)
  486. parse_q(&mq, old_nick, newnick);
  487. if (hq.head)
  488. parse_q(&hq, old_nick, newnick);
  489. }
  490. }
  491. static void parse_q(struct msgq_head *q, char *old_nick, char *newnick)
  492. {
  493. struct msgq *m = NULL, *lm = NULL; char buf[511] = "", *msg = NULL, *nicks = NULL,
  494. *nick = NULL, *chan = NULL, newnicks[511] = "", newmsg[511] = "";
  495. int changed;
  496. for (m = q->head; m;) {
  497. changed = 0;
  498. if (optimize_kicks == 2 && !egg_strncasecmp(m->msg, "KICK ", 5)) {
  499. newnicks[0] = 0;
  500. strncpyz(buf, m->msg, sizeof buf);
  501. if (buf[0] && (buf[strlen(buf)-1] == '\n'))
  502. buf[strlen(buf)-1] = '\0';
  503. msg = buf;
  504. newsplit(&msg);
  505. chan = newsplit(&msg);
  506. nicks = newsplit(&msg);
  507. while (strlen(nicks) > 0) {
  508. nick = splitnicks(&nicks);
  509. if (!egg_strcasecmp(nick, old_nick) &&
  510. ((9 + strlen(chan) + strlen(newnicks) + strlen(newnick) +
  511. strlen(nicks) + strlen(msg)) < 510)) {
  512. if (newnick)
  513. egg_snprintf(newnicks, sizeof newnicks, "%s,%s", newnicks, newnick);
  514. changed = 1;
  515. } else
  516. egg_snprintf(newnicks, sizeof newnicks, ",%s", nick);
  517. }
  518. egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s\n", chan,
  519. newnicks + 1, msg);
  520. }
  521. if (changed) {
  522. if (newnicks[0] == 0) {
  523. if (!lm)
  524. q->head = m->next;
  525. else
  526. lm->next = m->next;
  527. free(m->msg);
  528. free(m);
  529. m = lm;
  530. q->tot--;
  531. if (!q->head)
  532. q->last = 0;
  533. } else {
  534. free(m->msg);
  535. m->len = strlen(newmsg);
  536. m->msg = strdup(newmsg);
  537. }
  538. }
  539. lm = m;
  540. if (m)
  541. m = m->next;
  542. else
  543. m = q->head;
  544. }
  545. }
  546. static void purge_kicks(struct msgq_head *q)
  547. {
  548. struct msgq *m, *lm = NULL;
  549. char buf[511] = "", *reason = NULL, *nicks = NULL, *nick = NULL, *chan = NULL,
  550. newnicks[511] = "", newmsg[511] = "", chans[511] = "", *chns, *ch;
  551. int changed, found;
  552. struct chanset_t *cs = NULL;
  553. for (m = q->head; m;) {
  554. if (!egg_strncasecmp(m->msg, "KICK", 4)) {
  555. newnicks[0] = 0;
  556. changed = 0;
  557. strncpyz(buf, m->msg, sizeof buf);
  558. if (buf[0] && (buf[strlen(buf)-1] == '\n'))
  559. buf[strlen(buf)-1] = '\0';
  560. reason = buf;
  561. newsplit(&reason);
  562. chan = newsplit(&reason);
  563. nicks = newsplit(&reason);
  564. while (strlen(nicks) > 0) {
  565. found = 0;
  566. nick = splitnicks(&nicks);
  567. strncpyz(chans, chan, sizeof chans);
  568. chns = chans;
  569. while (strlen(chns) > 0) {
  570. ch = newsplit(&chns);
  571. cs = findchan(ch);
  572. if (!cs)
  573. continue;
  574. if (ismember(cs, nick))
  575. found = 1;
  576. }
  577. if (found)
  578. egg_snprintf(newnicks, sizeof newnicks, "%s,%s", newnicks, nick);
  579. else {
  580. putlog(LOG_SRVOUT, "*", "%s isn't on any target channel, removing "
  581. "kick...", nick);
  582. changed = 1;
  583. }
  584. }
  585. if (changed) {
  586. if (newnicks[0] == 0) {
  587. if (!lm)
  588. q->head = m->next;
  589. else
  590. lm->next = m->next;
  591. free(m->msg);
  592. free(m);
  593. m = lm;
  594. q->tot--;
  595. if (!q->head)
  596. q->last = 0;
  597. } else {
  598. free(m->msg);
  599. egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s\n", chan,
  600. newnicks + 1, reason);
  601. m->len = strlen(newmsg);
  602. m->msg = strdup(newmsg);
  603. }
  604. }
  605. }
  606. lm = m;
  607. if (m)
  608. m = m->next;
  609. else
  610. m = q->head;
  611. }
  612. }
  613. static int deq_kick(int which)
  614. {
  615. struct msgq_head *h = NULL;
  616. struct msgq *msg = NULL, *m = NULL, *lm = NULL;
  617. char buf[511] = "", buf2[511] = "", *reason2 = NULL, *nicks = NULL, *chan = NULL,
  618. *chan2 = NULL, *reason = NULL, *nick = NULL, newnicks[511] = "", newnicks2[511] = "",
  619. newmsg[511] = "";
  620. int changed = 0, nr = 0;
  621. if (!optimize_kicks)
  622. return 0;
  623. newnicks[0] = 0;
  624. switch (which) {
  625. case DP_MODE:
  626. h = &modeq;
  627. break;
  628. case DP_SERVER:
  629. h = &mq;
  630. break;
  631. case DP_HELP:
  632. h = &hq;
  633. break;
  634. default:
  635. return 0;
  636. }
  637. if (egg_strncasecmp(h->head->msg, "KICK", 4))
  638. return 0;
  639. if (optimize_kicks == 2) {
  640. purge_kicks(h);
  641. if (!h->head)
  642. return 1;
  643. }
  644. if (egg_strncasecmp(h->head->msg, "KICK", 4))
  645. return 0;
  646. msg = h->head;
  647. strncpyz(buf, msg->msg, sizeof buf);
  648. reason = buf;
  649. newsplit(&reason);
  650. chan = newsplit(&reason);
  651. nicks = newsplit(&reason);
  652. while (strlen(nicks) > 0) {
  653. egg_snprintf(newnicks, sizeof newnicks, "%s,%s", newnicks,
  654. newsplit(&nicks));
  655. nr++;
  656. }
  657. for (m = msg->next, lm = NULL; m && (nr < kick_method);) {
  658. if (!egg_strncasecmp(m->msg, "KICK", 4)) {
  659. changed = 0;
  660. newnicks2[0] = 0;
  661. strncpyz(buf2, m->msg, sizeof buf2);
  662. if (buf2[0] && (buf2[strlen(buf2)-1] == '\n'))
  663. buf2[strlen(buf2)-1] = '\0';
  664. reason2 = buf2;
  665. newsplit(&reason2);
  666. chan2 = newsplit(&reason2);
  667. nicks = newsplit(&reason2);
  668. if (!egg_strcasecmp(chan, chan2) && !egg_strcasecmp(reason, reason2)) {
  669. while (strlen(nicks) > 0) {
  670. nick = splitnicks(&nicks);
  671. if ((nr < kick_method) &&
  672. ((9 + strlen(chan) + strlen(newnicks) + strlen(nick) +
  673. strlen(reason)) < 510)) {
  674. egg_snprintf(newnicks, sizeof newnicks, "%s,%s", newnicks, nick);
  675. nr++;
  676. changed = 1;
  677. } else
  678. egg_snprintf(newnicks2, sizeof newnicks2, "%s,%s", newnicks2, nick);
  679. }
  680. }
  681. if (changed) {
  682. if (newnicks2[0] == 0) {
  683. if (!lm)
  684. h->head->next = m->next;
  685. else
  686. lm->next = m->next;
  687. free(m->msg);
  688. free(m);
  689. m = lm;
  690. h->tot--;
  691. if (!h->head)
  692. h->last = 0;
  693. } else {
  694. free(m->msg);
  695. egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s\n", chan2,
  696. newnicks2 + 1, reason);
  697. m->len = strlen(newmsg);
  698. m->msg = strdup(newmsg);
  699. }
  700. }
  701. }
  702. lm = m;
  703. if (m)
  704. m = m->next;
  705. else
  706. m = h->head->next;
  707. }
  708. egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s\n", chan, newnicks + 1, reason);
  709. tputs(serv, newmsg, strlen(newmsg));
  710. if (debug_output) {
  711. newmsg[strlen(newmsg) - 1] = 0;
  712. switch (which) {
  713. case DP_MODE:
  714. putlog(LOG_SRVOUT, "@", "[m->] %s", newmsg);
  715. break;
  716. case DP_SERVER:
  717. putlog(LOG_SRVOUT, "@", "[s->] %s", newmsg);
  718. break;
  719. case DP_HELP:
  720. putlog(LOG_SRVOUT, "@", "[h->] %s", newmsg);
  721. break;
  722. }
  723. debug3("Changed: %d, kick-method: %d, nr: %d", changed, kick_method, nr);
  724. }
  725. h->tot--;
  726. last_time += calc_penalty(newmsg);
  727. m = h->head->next;
  728. free(h->head->msg);
  729. free(h->head);
  730. h->head = m;
  731. if (!h->head)
  732. h->last = 0;
  733. return 1;
  734. }
  735. /* Clean out the msg queues (like when changing servers).
  736. */
  737. static void empty_msgq()
  738. {
  739. msgq_clear(&modeq);
  740. msgq_clear(&mq);
  741. msgq_clear(&hq);
  742. burst = 0;
  743. }
  744. /* Use when sending msgs... will spread them out so there's no flooding.
  745. */
  746. void queue_server(int which, char *buf, int len)
  747. {
  748. struct msgq_head *h = NULL, tempq;
  749. struct msgq *q = NULL, *tq = NULL, *tqq = NULL;
  750. int doublemsg = 0, qnext = 0;
  751. /* Don't even BOTHER if there's no server online. */
  752. if (serv < 0)
  753. return;
  754. /* No queue for PING and PONG - drummer */
  755. if (!egg_strncasecmp(buf, "PING", 4) || !egg_strncasecmp(buf, "PONG", 4)) {
  756. if (buf[1] == 'I' || buf[1] == 'i')
  757. lastpingtime = now; /* lagmeter */
  758. tputs(serv, buf, len);
  759. if (debug_output) {
  760. if (buf[len - 1] == '\n')
  761. buf[len - 1] = 0;
  762. putlog(LOG_SRVOUT, "@", "[m->] %s", buf);
  763. }
  764. return;
  765. }
  766. switch (which) {
  767. case DP_MODE_NEXT:
  768. qnext = 1;
  769. /* Fallthrough */
  770. case DP_MODE:
  771. h = &modeq;
  772. tempq = modeq;
  773. if (double_mode)
  774. doublemsg = 1;
  775. break;
  776. case DP_SERVER_NEXT:
  777. qnext = 1;
  778. /* Fallthrough */
  779. case DP_SERVER:
  780. h = &mq;
  781. tempq = mq;
  782. if (double_server)
  783. doublemsg = 1;
  784. break;
  785. case DP_HELP_NEXT:
  786. qnext = 1;
  787. /* Fallthrough */
  788. case DP_HELP:
  789. h = &hq;
  790. tempq = hq;
  791. if (double_help)
  792. doublemsg = 1;
  793. break;
  794. default:
  795. putlog(LOG_MISC, "*", "!!! queuing unknown type to server!!");
  796. return;
  797. }
  798. if (h->tot < maxqmsg) {
  799. /* Don't queue msg if it's already queued? */
  800. if (!doublemsg)
  801. for (tq = tempq.head; tq; tq = tqq) {
  802. tqq = tq->next;
  803. if (!egg_strcasecmp(tq->msg, buf)) {
  804. if (!double_warned) {
  805. if (buf[len - 1] == '\n')
  806. buf[len - 1] = 0;
  807. debug1("msg already queued. skipping: %s", buf);
  808. double_warned = 1;
  809. }
  810. return;
  811. }
  812. }
  813. q = malloc(sizeof(struct msgq));
  814. if (qnext)
  815. q->next = h->head;
  816. else
  817. q->next = NULL;
  818. if (h->head) {
  819. if (!qnext)
  820. h->last->next = q;
  821. } else
  822. h->head = q;
  823. if (qnext)
  824. h->head = q;
  825. h->last = q;
  826. q->len = len;
  827. q->msg = calloc(1, len + 1);
  828. strncpyz(q->msg, buf, len + 1);
  829. h->tot++;
  830. h->warned = 0;
  831. double_warned = 0;
  832. } else {
  833. if (!h->warned) {
  834. switch (which) {
  835. case DP_MODE_NEXT:
  836. /* Fallthrough */
  837. case DP_MODE:
  838. putlog(LOG_MISC, "*", "!!! OVER MAXIMUM MODE QUEUE");
  839. break;
  840. case DP_SERVER_NEXT:
  841. /* Fallthrough */
  842. case DP_SERVER:
  843. putlog(LOG_MISC, "*", "!!! OVER MAXIMUM SERVER QUEUE");
  844. break;
  845. case DP_HELP_NEXT:
  846. /* Fallthrough */
  847. case DP_HELP:
  848. putlog(LOG_MISC, "*", "!!! OVER MAXIMUM HELP QUEUE");
  849. break;
  850. }
  851. }
  852. h->warned = 1;
  853. }
  854. if (debug_output && !h->warned) {
  855. if (buf[len - 1] == '\n')
  856. buf[len - 1] = 0;
  857. switch (which) {
  858. case DP_MODE:
  859. putlog(LOG_SRVOUT, "@", "[!m] %s", buf);
  860. break;
  861. case DP_SERVER:
  862. putlog(LOG_SRVOUT, "@", "[!s] %s", buf);
  863. break;
  864. case DP_HELP:
  865. putlog(LOG_SRVOUT, "@", "[!h] %s", buf);
  866. break;
  867. case DP_MODE_NEXT:
  868. putlog(LOG_SRVOUT, "@", "[!!m] %s", buf);
  869. break;
  870. case DP_SERVER_NEXT:
  871. putlog(LOG_SRVOUT, "@", "[!!s] %s", buf);
  872. break;
  873. case DP_HELP_NEXT:
  874. putlog(LOG_SRVOUT, "@", "[!!h] %s", buf);
  875. break;
  876. }
  877. }
  878. if (which == DP_MODE || which == DP_MODE_NEXT)
  879. deq_msg(); /* DP_MODE needs to be sent ASAP, flush if
  880. possible. */
  881. }
  882. /* Add a new server to the server_list.
  883. */
  884. static void add_server(char *ss)
  885. {
  886. struct server_list *x = NULL, *z = NULL;
  887. #ifdef USE_IPV6
  888. char *r = NULL;
  889. #endif /* USE_IPV6 */
  890. char *p = NULL, *q = NULL;
  891. for (z = serverlist; z && z->next; z = z->next);
  892. while (ss) {
  893. p = strchr(ss, ',');
  894. if (p)
  895. *p++ = 0;
  896. x = calloc(1, sizeof(struct server_list));
  897. x->next = 0;
  898. x->realname = 0;
  899. x->port = 0;
  900. if (z)
  901. z->next = x;
  902. else
  903. serverlist = x;
  904. z = x;
  905. q = strchr(ss, ':');
  906. if (!q) {
  907. x->port = default_port;
  908. x->pass = 0;
  909. x->name = strdup(ss);
  910. } else {
  911. #ifdef USE_IPV6
  912. if (ss[0] == '[') {
  913. *ss++;
  914. q = strchr(ss, ']');
  915. *q++ = 0; /* intentional */
  916. r = strchr(q, ':');
  917. if (!r)
  918. x->port = default_port;
  919. }
  920. #endif /* USE_IPV6 */
  921. *q++ = 0;
  922. x->name = calloc(1, q - ss);
  923. strcpy(x->name, ss);
  924. ss = q;
  925. q = strchr(ss, ':');
  926. if (!q) {
  927. x->pass = 0;
  928. } else {
  929. *q++ = 0;
  930. x->pass = strdup(q);
  931. }
  932. #ifdef USE_IPV6
  933. if (!x->port) {
  934. x->port = atoi(ss);
  935. }
  936. #else
  937. x->port = atoi(ss);
  938. #endif /* USE_IPV6 */
  939. }
  940. ss = p;
  941. }
  942. }
  943. /* Clear out the given server_list.
  944. */
  945. static void clearq(struct server_list *xx)
  946. {
  947. struct server_list *x = NULL;
  948. while (xx) {
  949. x = xx->next;
  950. if (xx->name)
  951. free(xx->name);
  952. if (xx->pass)
  953. free(xx->pass);
  954. if (xx->realname)
  955. free(xx->realname);
  956. free(xx);
  957. xx = x;
  958. }
  959. }
  960. void servers_describe(struct cfg_entry * entry, int idx) {
  961. }
  962. void servers6_describe(struct cfg_entry * entry, int idx) {
  963. }
  964. void servers_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  965. #ifdef LEAF
  966. char *slist = NULL, *p = NULL;
  967. if (conf.bot->host6 || conf.bot->ip6) /* we want to use the servers6 entry. */
  968. return;
  969. slist = (char *) (entry->ldata ? entry->ldata : (entry->gdata ? entry->gdata : ""));
  970. if (serverlist) {
  971. clearq(serverlist);
  972. serverlist = NULL;
  973. }
  974. #ifdef S_RANDSERVERS
  975. shuffle(slist, ",");
  976. #endif /* S_RANDSERVERS */
  977. p = strdup(slist);
  978. add_server(p);
  979. free(p);
  980. #endif /* LEAF */
  981. }
  982. void servers6_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  983. #ifdef LEAF
  984. char *slist = NULL, *p = NULL;
  985. if (!conf.bot->host6 && !conf.bot->ip6) /* we probably want to use the normal server list.. */
  986. return;
  987. slist = (char *) (entry->ldata ? entry->ldata : (entry->gdata ? entry->gdata : ""));
  988. if (serverlist) {
  989. clearq(serverlist);
  990. serverlist = NULL;
  991. }
  992. #ifdef S_RANDSERVERS
  993. shuffle(slist, ",");
  994. #endif /* S_RANDSERVERS */
  995. p = strdup(slist);
  996. add_server(p);
  997. free(p);
  998. #endif /* LEAF */
  999. }
  1000. void nick_describe(struct cfg_entry * entry, int idx) {
  1001. }
  1002. void nick_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  1003. #ifdef LEAF
  1004. char *p = NULL;
  1005. if (entry->ldata)
  1006. p = entry->ldata;
  1007. else if (entry->gdata)
  1008. p = entry->gdata;
  1009. else
  1010. p = NULL;
  1011. if (p && p[0])
  1012. strncpyz(origbotname, p, NICKLEN + 1);
  1013. else
  1014. strncpyz(origbotname, conf.bot->nick, NICKLEN + 1);
  1015. if (server_online)
  1016. dprintf(DP_SERVER, "NICK %s\n", origbotname);
  1017. #endif /* LEAF */
  1018. }
  1019. void realname_describe(struct cfg_entry * entry, int idx) {
  1020. }
  1021. void realname_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  1022. #ifdef LEAF
  1023. if (entry->ldata) {
  1024. strncpyz(botrealname, (char *) entry->ldata, 121);
  1025. } else if (entry->gdata) {
  1026. strncpyz(botrealname, (char *) entry->gdata, 121);
  1027. }
  1028. #endif /* LEAF */
  1029. }
  1030. struct cfg_entry CFG_SERVERS = {
  1031. "servers", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  1032. servers_changed, servers_changed, servers_describe
  1033. };
  1034. struct cfg_entry CFG_SERVERS6 = {
  1035. "servers6", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  1036. servers6_changed, servers6_changed, servers6_describe
  1037. };
  1038. struct cfg_entry CFG_NICK = {
  1039. "nick", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  1040. nick_changed, nick_changed, nick_describe
  1041. };
  1042. struct cfg_entry CFG_REALNAME = {
  1043. "realname", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  1044. realname_changed, realname_changed, realname_describe
  1045. };
  1046. /* Set botserver to the next available server.
  1047. *
  1048. * -> if (*ptr == -1) then jump to that particular server
  1049. */
  1050. static void next_server(int *ptr, char *servname, unsigned int *port, char *pass)
  1051. {
  1052. struct server_list *x = serverlist;
  1053. int i = 0;
  1054. if (x == NULL)
  1055. return;
  1056. /* -1 --> Go to specified server */
  1057. if (*ptr == (-1)) {
  1058. for (; x; x = x->next) {
  1059. if (x->port == *port) {
  1060. if (!egg_strcasecmp(x->name, servname)) {
  1061. *ptr = i;
  1062. return;
  1063. } else if (x->realname && !egg_strcasecmp(x->realname, servname)) {
  1064. *ptr = i;
  1065. strncpyz(servname, x->realname, sizeof servname);
  1066. return;
  1067. }
  1068. }
  1069. i++;
  1070. }
  1071. /* Gotta add it: */
  1072. x = calloc(1, sizeof(struct server_list));
  1073. x->next = 0;
  1074. x->realname = 0;
  1075. x->name = strdup(servname);
  1076. x->port = *port ? *port : default_port;
  1077. if (pass && pass[0]) {
  1078. x->pass = strdup(pass);
  1079. } else
  1080. x->pass = NULL;
  1081. list_append((struct list_type **) (&serverlist), (struct list_type *) x);
  1082. *ptr = i;
  1083. return;
  1084. }
  1085. /* Find where i am and boogie */
  1086. i = (*ptr);
  1087. while (i > 0 && x != NULL) {
  1088. x = x->next;
  1089. i--;
  1090. }
  1091. if (x != NULL) {
  1092. x = x->next;
  1093. (*ptr)++;
  1094. } /* Go to next server */
  1095. if (x == NULL) {
  1096. x = serverlist;
  1097. *ptr = 0;
  1098. } /* Start over at the beginning */
  1099. strcpy(servname, x->name);
  1100. *port = x->port ? x->port : default_port;
  1101. if (x->pass)
  1102. strcpy(pass, x->pass);
  1103. else
  1104. pass[0] = 0;
  1105. }
  1106. static void do_nettype(void)
  1107. {
  1108. switch (net_type) {
  1109. case NETT_EFNET:
  1110. check_mode_r = 0;
  1111. nick_len = 9;
  1112. break;
  1113. case NETT_IRCNET:
  1114. check_mode_r = 1;
  1115. use_penalties = 1;
  1116. use_fastdeq = 3;
  1117. nick_len = 9;
  1118. simple_sprintf(stackablecmds, "INVITE AWAY VERSION NICK");
  1119. kick_method = 4;
  1120. break;
  1121. case NETT_UNDERNET:
  1122. check_mode_r = 0;
  1123. use_fastdeq = 2;
  1124. nick_len = 9;
  1125. simple_sprintf(stackablecmds, "PRIVMSG NOTICE TOPIC PART WHOIS USERHOST USERIP ISON");
  1126. simple_sprintf(stackable2cmds, "USERHOST USERIP ISON");
  1127. break;
  1128. case NETT_DALNET:
  1129. check_mode_r = 0;
  1130. use_fastdeq = 2;
  1131. nick_len = 32;
  1132. simple_sprintf(stackablecmds, "PRIVMSG NOTICE PART WHOIS WHOWAS USERHOST ISON WATCH DCCALLOW");
  1133. simple_sprintf(stackable2cmds, "USERHOST ISON WATCH");
  1134. break;
  1135. case NETT_HYBRID_EFNET:
  1136. check_mode_r = 0;
  1137. nick_len = 9;
  1138. break;
  1139. }
  1140. }
  1141. /*
  1142. * CTCP DCC CHAT functions
  1143. */
  1144. static void dcc_chat_hostresolved(int);
  1145. /* This only handles CHAT requests, otherwise it's handled in filesys.
  1146. */
  1147. static int ctcp_DCC_CHAT(char *nick, char *from, struct userrec *u, char *object, char *keyword, char *text)
  1148. {
  1149. char *action = NULL, *param = NULL, *ip = NULL, *prt = NULL;
  1150. int i, ok;
  1151. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  1152. if (!ischanhub())
  1153. return BIND_RET_LOG;
  1154. action = newsplit(&text);
  1155. param = newsplit(&text);
  1156. ip = newsplit(&text);
  1157. prt = newsplit(&text);
  1158. if (egg_strcasecmp(action, "CHAT") || egg_strcasecmp(object, botname) || !u)
  1159. return BIND_RET_LOG;
  1160. get_user_flagrec(u, &fr, 0);
  1161. ok = 1;
  1162. if (ischanhub() && !glob_chuba(fr))
  1163. ok = 0;
  1164. if (dcc_total == max_dcc) {
  1165. if (!quiet_reject)
  1166. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, DCC_TOOMANYDCCS1);
  1167. putlog(LOG_MISC, "*", DCC_TOOMANYDCCS2, "CHAT", param, nick, from);
  1168. } else if (!ok) {
  1169. if (!quiet_reject)
  1170. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, DCC_REFUSED2);
  1171. putlog(LOG_MISC, "*", "%s: %s!%s", ischanhub() ? DCC_REFUSED : DCC_REFUSEDNC, nick, from);
  1172. } else if (u_pass_match(u, "-")) {
  1173. if (!quiet_reject)
  1174. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, DCC_REFUSED3);
  1175. putlog(LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED4, nick, from);
  1176. } else if (atoi(prt) < 1024 || atoi(prt) > 65535) {
  1177. /* Invalid port */
  1178. if (!quiet_reject)
  1179. dprintf(DP_HELP, "NOTICE %s :%s (invalid port)\n", nick, DCC_CONNECTFAILED1);
  1180. putlog(LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED3, nick, from);
  1181. } else {
  1182. if (!sanitycheck_dcc(nick, from, ip, prt))
  1183. return BIND_RET_BREAK;
  1184. i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
  1185. if (i < 0) {
  1186. putlog(LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", dcc[i].nick, ip);
  1187. return BIND_RET_BREAK;
  1188. }
  1189. #ifdef USE_IPV6
  1190. if (hostprotocol(ip) == AF_INET6 && sockprotocol(dcc[i].sock) == AF_INET6) {
  1191. debug1("ipv6 addr: %s",ip);
  1192. strcpy(dcc[i].addr6,ip);
  1193. debug1("ipv6 addr: %s",dcc[i].addr6);
  1194. } else
  1195. #endif /* USE_IPV6 */
  1196. dcc[i].addr = my_atoul(ip);
  1197. dcc[i].port = atoi(prt);
  1198. dcc[i].sock = -1;
  1199. strcpy(dcc[i].nick, u->handle);
  1200. strcpy(dcc[i].host, from);
  1201. dcc[i].timeval = now;
  1202. dcc[i].user = u;
  1203. #ifdef USE_IPV6
  1204. if (sockprotocol(dcc[i].sock) != AF_INET6) {
  1205. #endif /* USE_IPV6 */
  1206. /* remove me? */
  1207. dcc[i].addr = my_atoul(ip);
  1208. dcc[i].u.dns->ip = dcc[i].addr;
  1209. dcc[i].u.dns->dns_type = RES_HOSTBYIP;
  1210. dcc[i].u.dns->dns_success = dcc_chat_hostresolved;
  1211. dcc[i].u.dns->dns_failure = dcc_chat_hostresolved;
  1212. dcc[i].u.dns->type = &DCC_CHAT_PASS;
  1213. dcc_dnshostbyip(dcc[i].addr);
  1214. #ifdef USE_IPV6
  1215. } else
  1216. dcc_chat_hostresolved(i); /* Don't try to look it up */
  1217. #endif /* USE_IPV6 */
  1218. }
  1219. return BIND_RET_BREAK;
  1220. }
  1221. static void dcc_chat_hostresolved(int i)
  1222. {
  1223. char buf[512] = "", ip[512] = "";
  1224. int ok;
  1225. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  1226. egg_snprintf(buf, sizeof buf, "%d", dcc[i].port);
  1227. #ifndef USE_IPV6
  1228. if (!hostsanitycheck_dcc(dcc[i].nick, dcc[i].host, dcc[i].addr, dcc[i].u.dns->host, buf)) {
  1229. lostdcc(i);
  1230. return;
  1231. }
  1232. #else
  1233. if (sockprotocol(dcc[i].sock) == AF_INET6) {
  1234. strcpy(ip,dcc[i].addr6); /* safe, addr6 is 121 */
  1235. debug0("afinet6, af_type, strcpy");
  1236. } else
  1237. #endif /* !USE_IPV6 */
  1238. egg_snprintf(ip, sizeof ip, "%lu", iptolong(htonl(dcc[i].addr)));
  1239. #ifdef USE_IPV6
  1240. if (sockprotocol(dcc[i].sock) == AF_INET6) {
  1241. # ifdef IPV6_DEBUG
  1242. debug2("af_inet6 %s / %s", dcc[i].addr6, ip);
  1243. # endif /* IPV6_DEBUG */
  1244. dcc[i].sock = getsock(0, AF_INET6);
  1245. } else {
  1246. # ifdef IPV6_DEBUG
  1247. debug0("af_inet");
  1248. # endif /* IPV6_DEBUG */
  1249. dcc[i].sock = getsock(0, AF_INET);
  1250. }
  1251. #else
  1252. dcc[i].sock = getsock(0);
  1253. # ifdef IPV6_DEBUG
  1254. debug2("sock: %d %s", dcc[i].sock, ip);
  1255. # endif /* IPV6_DEBUG */
  1256. #endif /* USE_IPV6 */
  1257. if (dcc[i].sock < 0 || open_telnet_dcc(dcc[i].sock, ip, buf) < 0) {
  1258. neterror(buf);
  1259. if (!quiet_reject)
  1260. dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", dcc[i].nick, DCC_CONNECTFAILED1, buf);
  1261. putlog(LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED2, dcc[i].nick, dcc[i].host);
  1262. putlog(LOG_MISC, "*", " (%s)", buf);
  1263. killsock(dcc[i].sock);
  1264. lostdcc(i);
  1265. } else {
  1266. #ifdef HAVE_SSL
  1267. ssl_link(dcc[i].sock, CONNECT_SSL);
  1268. #endif /* HAVE_SSL */
  1269. changeover_dcc(i, &DCC_CHAT_PASS, sizeof(struct chat_info));
  1270. dcc[i].status = STAT_ECHO;
  1271. get_user_flagrec(dcc[i].user, &fr, 0);
  1272. ok = 1;
  1273. if (ischanhub() && !glob_chuba(fr))
  1274. ok = 0;
  1275. if (ok)
  1276. dcc[i].status |= STAT_PARTY;
  1277. strcpy(dcc[i].u.chat->con_chan, (chanset) ? chanset->dname : "*");
  1278. dcc[i].timeval = now;
  1279. /* Ok, we're satisfied with them now: attempt the connect */
  1280. putlog(LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", dcc[i].nick, dcc[i].host);
  1281. dprintf(i, "%s", rand_dccresp());
  1282. }
  1283. return;
  1284. }
  1285. /*
  1286. * Server timer functions
  1287. */
  1288. static void server_secondly()
  1289. {
  1290. if (cycle_time)
  1291. cycle_time--;
  1292. deq_msg();
  1293. if (!resolvserv && serv < 0 && !trying_server)
  1294. connect_server();
  1295. }
  1296. static void server_5minutely()
  1297. {
  1298. if (check_stoned && server_online) {
  1299. if (waiting_for_awake) {
  1300. /* Uh oh! Never got pong from last time, five minutes ago!
  1301. * Server is probably stoned.
  1302. */
  1303. disconnect_server(servidx, DO_LOST);
  1304. putlog(LOG_SERV, "*", IRC_SERVERSTONED);
  1305. } else if (!trying_server) {
  1306. /* Check for server being stoned. */
  1307. dprintf(DP_MODE, "PING :%li\n", now);
  1308. waiting_for_awake = 1;
  1309. }
  1310. }
  1311. }
  1312. static void server_prerehash()
  1313. {
  1314. strcpy(oldnick, botname);
  1315. }
  1316. static void server_postrehash()
  1317. {
  1318. strncpyz(botname, origbotname, NICKLEN);
  1319. if (oldnick[0] && !rfc_casecmp(oldnick, botname)) {
  1320. /* Change botname back, don't be premature. */
  1321. strcpy(botname, oldnick);
  1322. dprintf(DP_SERVER, "NICK %s\n", origbotname);
  1323. }
  1324. /* Change botname back incase we were using altnick previous to rehash. */
  1325. else if (oldnick[0])
  1326. strcpy(botname, oldnick);
  1327. }
  1328. static void server_die()
  1329. {
  1330. cycle_time = 100;
  1331. if (server_online) {
  1332. dprintf(-serv, "QUIT :%s\n", quit_msg[0] ? quit_msg : "");
  1333. sleep(3); /* Give the server time to understand */
  1334. }
  1335. nuke_server(NULL);
  1336. }
  1337. /* A report on the module status.
  1338. */
  1339. void server_report(int idx, int details)
  1340. {
  1341. char s1[64] = "", s[128] = "";
  1342. if (server_online) {
  1343. dprintf(idx, " Online as: %s%s%s (%s)\n", botname,
  1344. botuserhost[0] ? "!" : "", botuserhost[0] ? botuserhost : "",
  1345. botrealname);
  1346. if (nick_juped)
  1347. dprintf(idx, " NICK IS JUPED: %s %s\n", origbotname,
  1348. keepnick ? "(trying)" : "");
  1349. nick_juped = 0; /* WHY?? -- drummer */
  1350. daysdur(now, server_online, s1);
  1351. egg_snprintf(s, sizeof s, "(connected %s)", s1);
  1352. if (server_lag && !waiting_for_awake) {
  1353. if (server_lag == (-1))
  1354. egg_snprintf(s1, sizeof s1, " (bad pong replies)");
  1355. else
  1356. egg_snprintf(s1, sizeof s1, " (lag: %ds)", server_lag);
  1357. strcat(s, s1);
  1358. }
  1359. }
  1360. if ((trying_server || server_online) && (servidx != (-1))) {
  1361. dprintf(idx, " Server %s:%d %s\n", dcc[servidx].host, dcc[servidx].port,
  1362. trying_server ? "(trying)" : s);
  1363. } else
  1364. dprintf(idx, " %s\n", IRC_NOSERVER);
  1365. if (modeq.tot)
  1366. dprintf(idx, " %s %d%%, %d msgs\n", IRC_MODEQUEUE,
  1367. (int) ((float) (modeq.tot * 100.0) / (float) maxqmsg),
  1368. (int) modeq.tot);
  1369. if (mq.tot)
  1370. dprintf(idx, " %s %d%%, %d msgs\n", IRC_SERVERQUEUE,
  1371. (int) ((float) (mq.tot * 100.0) / (float) maxqmsg), (int) mq.tot);
  1372. if (hq.tot)
  1373. dprintf(idx, " %s %d%%, %d msgs\n", IRC_HELPQUEUE,
  1374. (int) ((float) (hq.tot * 100.0) / (float) maxqmsg), (int) hq.tot);
  1375. if (details) {
  1376. dprintf(idx, " Flood is: %d msg/%ds, %d ctcp/%ds\n",
  1377. flud_thr, flud_time, flud_ctcp_thr, flud_ctcp_time);
  1378. }
  1379. }
  1380. static void msgq_clear(struct msgq_head *qh)
  1381. {
  1382. register struct msgq *q = NULL, *qq = NULL;
  1383. for (q = qh->head; q; q = qq) {
  1384. qq = q->next;
  1385. free(q->msg);
  1386. free(q);
  1387. }
  1388. qh->head = qh->last = NULL;
  1389. qh->tot = qh->warned = 0;
  1390. }
  1391. static cmd_t my_ctcps[] =
  1392. {
  1393. {"DCC", "", ctcp_DCC_CHAT, "server:DCC"},
  1394. {NULL, NULL, NULL, NULL}
  1395. };
  1396. void server_init()
  1397. {
  1398. /*
  1399. * Init of all the variables *must* be done in _start rather than
  1400. * globally.
  1401. */
  1402. serv = -1;
  1403. servidx = -1;
  1404. botname[0] = 0;
  1405. trying_server = 0;
  1406. server_lag = 0;
  1407. curserv = 0;
  1408. flud_thr = 5;
  1409. flud_time = 60;
  1410. flud_ctcp_thr = 3;
  1411. flud_ctcp_time = 60;
  1412. botuserhost[0] = 0;
  1413. keepnick = 1;
  1414. check_stoned = 1;
  1415. serverror_quit = 1;
  1416. quiet_reject = 1;
  1417. waiting_for_awake = 0;
  1418. server_online = 0;
  1419. server_cycle_wait = 15;
  1420. strcpy(botrealname, "A deranged product of evil coders");
  1421. server_timeout = 15;
  1422. never_give_up = 1;
  1423. strict_servernames = 1;
  1424. serverlist = NULL;
  1425. cycle_time = 0;
  1426. default_port = 6667;
  1427. oldnick[0] = 0;
  1428. trigger_on_ignore = 0;
  1429. answer_ctcp = 1;
  1430. lowercase_ctcp = 0;
  1431. check_mode_r = 0;
  1432. maxqmsg = 300;
  1433. burst = 0;
  1434. net_type = NETT_EFNET;
  1435. double_mode = 0;
  1436. double_server = 0;
  1437. double_help = 0;
  1438. use_penalties = 0;
  1439. use_fastdeq = 0;
  1440. stackablecmds[0] = 0;
  1441. strcpy(stackable2cmds, "USERHOST ISON");
  1442. resolvserv = 0;
  1443. lastpingtime = 0;
  1444. last_time = 0;
  1445. nick_len = 9;
  1446. kick_method = 1;
  1447. optimize_kicks = 0;
  1448. stack_limit = 4;
  1449. #ifdef S_AUTHCMDS
  1450. BT_msgc = bind_table_add("msgc", 5, "ssUss", 0, BIND_USE_ATTR);
  1451. #endif /* S_AUTHCMDS */
  1452. BT_msg = bind_table_add("msg", 4, "ssUs", 0, BIND_USE_ATTR);
  1453. BT_raw = bind_table_add("raw", 2, "ss", MATCH_MASK, BIND_STACKABLE);
  1454. BT_ctcr = bind_table_add("ctcr", 6, "ssUsss", MATCH_MASK, BIND_USE_ATTR | BIND_STACKABLE);
  1455. BT_ctcp = bind_table_add("ctcp", 6, "ssUsss", MATCH_MASK, BIND_USE_ATTR | BIND_STACKABLE);
  1456. add_builtins("raw", my_raw_binds);
  1457. add_builtins("dcc", C_dcc_serv);
  1458. add_builtins("ctcp", my_ctcps);
  1459. timer_create_secs(1, "server_secondly", (Function) server_secondly);
  1460. timer_create_secs(10, "server_10secondly", (Function) server_10secondly);
  1461. timer_create_secs(300, "server_5minutely", (Function) server_5minutely);
  1462. timer_create_secs(60, "minutely_checks", (Function) minutely_checks);
  1463. add_hook(HOOK_PRE_REHASH, (Function) server_prerehash);
  1464. add_hook(HOOK_REHASH, (Function) server_postrehash);
  1465. add_hook(HOOK_DIE, (Function) server_die);
  1466. mq.head = hq.head = modeq.head = NULL;
  1467. mq.last = hq.last = modeq.last = NULL;
  1468. mq.tot = hq.tot = modeq.tot = 0;
  1469. mq.warned = hq.warned = modeq.warned = 0;
  1470. double_warned = 0;
  1471. newserver[0] = 0;
  1472. newserverport = 0;
  1473. curserv = 999;
  1474. checked_hostmask = 0;
  1475. do_nettype();
  1476. add_cfg(&CFG_NICK);
  1477. add_cfg(&CFG_SERVERS);
  1478. add_cfg(&CFG_SERVERS6);
  1479. add_cfg(&CFG_REALNAME);
  1480. cfg_noshare = 1;
  1481. set_cfg_str(NULL, STR("realname"), "A deranged product of evil coders.");
  1482. cfg_noshare = 0;
  1483. }
  1484. #endif /* LEAF */