servmsg.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493
  1. /*
  2. * servmsg.c -- part of server.mod
  3. *
  4. */
  5. #include <netinet/tcp.h>
  6. char cursrvname[120] = "";
  7. char curnetwork[120] = "";
  8. static time_t last_ctcp = (time_t) 0L;
  9. static int count_ctcp = 0;
  10. static char altnick_char = 0;
  11. static unsigned int rolls = 0;
  12. #define ALTCHARS "-_\\`^[]"
  13. #define ROLL_RIGHT
  14. #undef ROLL_LEFT
  15. static int gotfake433(char *from)
  16. {
  17. size_t len = strlen(botname);
  18. int use_chr = 1;
  19. /* First run? */
  20. if (altnick_char == 0 && !rolls) {
  21. altnick_char = ALTCHARS[0];
  22. /* the nick is already as long as it can be. */
  23. if (len == (unsigned) nick_len) {
  24. /* make the last char the current altnick_char */
  25. botname[len - 1] = altnick_char;
  26. } else {
  27. /* tack it on to the end */
  28. botname[len] = altnick_char;
  29. botname[len + 1] = 0;
  30. }
  31. } else {
  32. char *p = NULL;
  33. if ((p = strchr(ALTCHARS, altnick_char)))
  34. p++;
  35. /* if we haven't been rolling, use the ALTCHARS
  36. */
  37. if (!rolls && p && *p) {
  38. altnick_char = *p;
  39. /* if we've already rolled, just keep rolling until we've rolled completely
  40. * after that, just generate random chars
  41. */
  42. } else if (rolls < len) {
  43. /* fun BX style rolling, WEEEE */
  44. char tmp = 0;
  45. size_t i = 0;
  46. altnick_char = 0;
  47. use_chr = 0;
  48. if (rolls == 0) {
  49. strcpy(botname, origbotname);
  50. len = strlen(botname);
  51. }
  52. #ifdef ROLL_RIGHT
  53. tmp = botname[len - 1];
  54. #endif /* ROLL_RIGHT */
  55. #ifdef ROLL_LEFT
  56. tmp = botname[0];
  57. #endif /* ROLL_LEFT */
  58. if (strchr(BADHANDCHARS, tmp))
  59. tmp = '_';
  60. rolls++;
  61. #ifdef ROLL_RIGHT
  62. for (i = (len - 1); i > 0; i--)
  63. botname[i] = botname[i - 1];
  64. botname[0] = tmp;
  65. #endif /* ROLL_RIGHT */
  66. #ifdef ROLL_LEFT
  67. for (i = 0; i < (len - 1); i++)
  68. botname[i] = botname[i + 1];
  69. botname[len - 1] = tmp;
  70. #endif /* ROLL_LEFT */
  71. botname[len] = 0;
  72. } else {
  73. /* we've tried ALTCHARS, and rolled the nick, just use random chars now */
  74. altnick_char = 'a' + randint(26);
  75. }
  76. if (use_chr && altnick_char) {
  77. botname[len - 1] = altnick_char;
  78. botname[len] = 0;
  79. }
  80. }
  81. putlog(LOG_SERV, "*", "NICK IN USE: Trying '%s'", botname);
  82. dprintf(DP_SERVER, "NICK %s\n", botname);
  83. return 0;
  84. }
  85. /* Check for tcl-bound msg command, return 1 if found
  86. *
  87. * msg: proc-name <nick> <user@host> <handle> <args...>
  88. */
  89. static void check_bind_msg(const char *cmd, char *nick, char *uhost, struct userrec *u, char *args)
  90. {
  91. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0 };
  92. int x;
  93. get_user_flagrec(u, &fr, NULL);
  94. x = check_bind(BT_msg, cmd, &fr, nick, uhost, u, args);
  95. if (x & BIND_RET_LOG)
  96. putlog(LOG_CMDS, "*", "(%s!%s) !%s! %s %s", nick, uhost, u ? u->handle : "*" , cmd, args);
  97. else if (x == 0)
  98. putlog(LOG_MSGS, "*", "[%s!%s] %s %s", nick, uhost, cmd, args);
  99. }
  100. /* Return 1 if processed.
  101. */
  102. static int check_bind_raw(char *from, char *code, char *msg)
  103. {
  104. char *p1 = NULL, *p2 = NULL, *myfrom = NULL, *mymsg = NULL;
  105. int ret = 0;
  106. myfrom = p1 = strdup(from);
  107. mymsg = p2 = strdup(msg);
  108. ret = check_bind(BT_raw, code, NULL, myfrom, mymsg);
  109. free(p1);
  110. free(p2);
  111. return ret;
  112. }
  113. int check_bind_ctcpr(char *nick, char *uhost, struct userrec *u,
  114. char *dest, char *keyword, char *args,
  115. bind_table_t *table)
  116. {
  117. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0 };
  118. get_user_flagrec(u, &fr, NULL);
  119. return check_bind(table, keyword, &fr, nick, uhost, u, dest, keyword, args);
  120. }
  121. bool match_my_nick(char *nick)
  122. {
  123. return (!rfc_casecmp(nick, botname));
  124. }
  125. void rehash_server(const char *servname, const char *nick)
  126. {
  127. server_online = now;
  128. altnick_char = 0;
  129. strlcpy(cursrvname, servname, sizeof(cursrvname));
  130. if (nick && nick[0]) {
  131. strlcpy(botname, nick, NICKLEN);
  132. dprintf(DP_SERVER, "WHOIS %s\n", botname); /* get user@host */
  133. dprintf(DP_SERVER, "USERHOST %s\n", botname); /* get user@ip */
  134. dprintf(DP_SERVER, "MODE %s +iws\n", botname);
  135. }
  136. }
  137. void
  138. join_chans()
  139. {
  140. for (register struct chanset_t *chan = chanset; chan; chan = chan->next) {
  141. chan->status &= ~(CHAN_ACTIVE | CHAN_PEND | CHAN_JOINING);
  142. if (shouldjoin(chan)) {
  143. dprintf(DP_SERVER, "JOIN %s %s\n", (chan->name[0]) ? chan->name : chan->dname,
  144. chan->channel.key[0] ? chan->channel.key : chan->key_prot);
  145. chan->status |= CHAN_JOINING;
  146. }
  147. }
  148. }
  149. /* 001: welcome to IRC (use it to fix the server name)
  150. */
  151. static int got001(char *from, char *msg)
  152. {
  153. fixcolon(msg);
  154. rehash_server(from, msg);
  155. /* Ok...param #1 of 001 = what server thinks my nick is */
  156. join_chans();
  157. #ifdef no
  158. if (egg_strcasecmp(from, dcc[servidx].host)) {
  159. struct server_list *x = serverlist;
  160. if (x == NULL)
  161. return 0; /* Uh, no server list */
  162. putlog(LOG_MISC, "*", "(%s claims to be %s; updating server list)", dcc[servidx].host, from);
  163. for (int i = curserv; i > 0 && x != NULL; i--)
  164. x = x->next;
  165. if (x == NULL) {
  166. putlog(LOG_MISC, "*", "Invalid server list!");
  167. return 0;
  168. }
  169. }
  170. #endif
  171. return 0;
  172. }
  173. /* <server> 005 <to> <option> <option> <... option> :are supported by this server */
  174. static int
  175. got005(char *from, char *msg)
  176. {
  177. char *tmp = NULL, *p, *p2;
  178. newsplit(&msg); /* nick */
  179. while ((tmp = newsplit(&msg))[0]) {
  180. p = NULL;
  181. if ((p = strchr(tmp, '=')))
  182. *p++ = 0;
  183. if (!egg_strcasecmp(tmp, ":are"))
  184. break;
  185. else if (!egg_strcasecmp(tmp, "MODES")) {
  186. modesperline = atoi(p);
  187. if (modesperline > MODES_PER_LINE_MAX)
  188. modesperline = MODES_PER_LINE_MAX;
  189. } else if (!egg_strcasecmp(tmp, "NICKLEN"))
  190. nick_len = atoi(p);
  191. else if (!egg_strcasecmp(tmp, "NETWORK"))
  192. strlcpy(curnetwork, p, 120);
  193. else if (!egg_strcasecmp(tmp, "PENALTY"))
  194. use_penalties = 1;
  195. else if (!egg_strcasecmp(tmp, "WHOX"))
  196. use_354 = 1;
  197. else if (!egg_strcasecmp(tmp, "EXCEPTS"))
  198. use_exempts = 1;
  199. else if (!egg_strcasecmp(tmp, "INVEX"))
  200. use_invites = 1;
  201. else if (!egg_strcasecmp(tmp, "MAXBANS")) {
  202. max_bans = atoi(p);
  203. max_modes = max_bans;
  204. max_exempts = max_bans;
  205. max_invites = max_bans;
  206. }
  207. else if (!egg_strcasecmp(tmp, "MAXLIST")) {
  208. p2 = NULL;
  209. if ((p2 = strchr(p, ':'))) {
  210. *p2++ = 0;
  211. max_modes = atoi(p2);
  212. if (strchr(p, 'e'))
  213. max_exempts = max_modes;
  214. if (strchr(p, 'b'))
  215. max_bans = max_modes;
  216. if (strchr(p, 'I'))
  217. max_invites = max_modes;
  218. }
  219. }
  220. else if (!egg_strcasecmp(tmp, "CASEMAPPING")) {
  221. /* we are default set to rfc1459, so only switch if NOT rfc1459 */
  222. if (egg_strcasecmp(p, "rfc1459")) {
  223. rfc_casecmp = egg_strcasecmp;
  224. rfc_toupper = toupper;
  225. }
  226. }
  227. }
  228. return 0;
  229. }
  230. /* Got 442: not on channel
  231. */
  232. static int got442(char *from, char *msg)
  233. {
  234. char *chname = NULL;
  235. struct chanset_t *chan = NULL;
  236. int i;
  237. struct server_list *x = NULL;
  238. for (x = serverlist, i = 0; x; x = x->next, i++)
  239. if (i == curserv) {
  240. if (egg_strcasecmp(from, x->name))
  241. return 0;
  242. break;
  243. }
  244. newsplit(&msg);
  245. chname = newsplit(&msg);
  246. chan = findchan(chname);
  247. if (chan)
  248. if (shouldjoin(chan) && !channel_joining(chan)) {
  249. putlog(LOG_MISC, chname, "Server says I'm not on channel: %s", chname);
  250. clear_channel(chan, 1);
  251. chan->status &= ~CHAN_ACTIVE;
  252. chan->status |= CHAN_JOINING;
  253. dprintf(DP_MODE, "JOIN %s %s\n", chan->name,
  254. chan->channel.key[0] ? chan->channel.key : chan->key_prot);
  255. }
  256. return 0;
  257. }
  258. /* Close the current server connection.
  259. */
  260. void nuke_server(const char *reason)
  261. {
  262. if (serv >= 0 && servidx >= 0) {
  263. if (reason)
  264. dprintf(DP_DUMP, "QUIT :%s\n", reason);
  265. sleep(1);
  266. disconnect_server(servidx, DO_LOST);
  267. }
  268. }
  269. char ctcp_reply[1024] = "";
  270. static int lastmsgs[FLOOD_GLOBAL_MAX];
  271. static char lastmsghost[FLOOD_GLOBAL_MAX][128];
  272. static time_t lastmsgtime[FLOOD_GLOBAL_MAX];
  273. /* Do on NICK, PRIVMSG, NOTICE and JOIN.
  274. */
  275. static bool detect_flood(char *floodnick, char *floodhost, char *from, int which)
  276. {
  277. struct userrec *u = get_user_by_host(from);
  278. int atr = u ? u->flags : 0;
  279. if ((u && u->bot) || (atr & USER_NOFLOOD))
  280. return 0;
  281. char *p = NULL, ftype[10] = "", h[1024] = "";
  282. int thr = 0;
  283. time_t lapse = 0;
  284. /* Determine how many are necessary to make a flood */
  285. switch (which) {
  286. case FLOOD_PRIVMSG:
  287. case FLOOD_NOTICE:
  288. thr = flud_thr;
  289. lapse = flud_time;
  290. strcpy(ftype, "msg");
  291. break;
  292. case FLOOD_CTCP:
  293. thr = flud_ctcp_thr;
  294. lapse = flud_ctcp_time;
  295. strcpy(ftype, "ctcp");
  296. break;
  297. }
  298. if ((thr == 0) || (lapse == 0))
  299. return 0; /* No flood protection */
  300. /* Okay, make sure i'm not flood-checking myself */
  301. if (match_my_nick(floodnick))
  302. return 0;
  303. if (!egg_strcasecmp(floodhost, botuserhost))
  304. return 0; /* My user@host (?) */
  305. p = strchr(floodhost, '@');
  306. if (p) {
  307. p++;
  308. if (egg_strcasecmp(lastmsghost[which], p)) { /* New */
  309. strcpy(lastmsghost[which], p);
  310. lastmsgtime[which] = now;
  311. lastmsgs[which] = 0;
  312. return 0;
  313. }
  314. } else
  315. return 0; /* Uh... whatever. */
  316. if (lastmsgtime[which] < now - lapse) {
  317. /* Flood timer expired, reset it */
  318. lastmsgtime[which] = now;
  319. lastmsgs[which] = 0;
  320. return 0;
  321. }
  322. lastmsgs[which]++;
  323. if (lastmsgs[which] >= thr) { /* FLOOD */
  324. /* Reset counters */
  325. lastmsgs[which] = 0;
  326. lastmsgtime[which] = 0;
  327. lastmsghost[which][0] = 0;
  328. u = get_user_by_host(from);
  329. /* Private msg */
  330. simple_sprintf(h, "*!*@%s", p);
  331. putlog(LOG_MISC, "*", "Flood from @%s! Placing on ignore!", p);
  332. addignore(h, conf.bot->nick, (which == FLOOD_CTCP) ? "CTCP flood" : "MSG/NOTICE flood", now + (60 * ignore_time));
  333. return 1;
  334. }
  335. return 0;
  336. }
  337. /* Check for more than 8 control characters in a line.
  338. * This could indicate: beep flood CTCP avalanche.
  339. */
  340. bool detect_avalanche(char *msg)
  341. {
  342. int count = 0;
  343. for (unsigned char *p = (unsigned char *) msg; (*p) && (count < 8); p++)
  344. if ((*p == 7) || (*p == 1))
  345. count++;
  346. if (count >= 8)
  347. return 1;
  348. else
  349. return 0;
  350. }
  351. /* Got a private message.
  352. */
  353. static int gotmsg(char *from, char *msg)
  354. {
  355. if (msg[0] && ((strchr(CHANMETA, *msg) != NULL) ||
  356. (*msg == '@'))) /* Notice to a channel, not handled here */
  357. return 0;
  358. char *to = NULL, buf[UHOSTLEN] = "", *nick = NULL, ctcpbuf[512] = "", *uhost = buf,
  359. *ctcp = NULL, *p = NULL, *p1 = NULL, *code = NULL;
  360. struct userrec *u = NULL;
  361. int ctcp_count = 0;
  362. bool ignoring = match_ignore(from);
  363. to = newsplit(&msg);
  364. fixcolon(msg);
  365. /* Only check if flood-ctcp is active */
  366. strcpy(uhost, from);
  367. nick = splitnick(&uhost);
  368. if (flud_ctcp_thr && detect_avalanche(msg)) {
  369. if (!ignoring) {
  370. putlog(LOG_MODES, "*", "Avalanche from %s - ignoring", from);
  371. p = strchr(uhost, '@');
  372. if (p != NULL)
  373. p++;
  374. else
  375. p = uhost;
  376. simple_sprintf(ctcpbuf, "*!*@%s", p);
  377. addignore(ctcpbuf, conf.bot->nick, "ctcp avalanche", now + (60 * ignore_time));
  378. ignoring++;
  379. }
  380. }
  381. /* Check for CTCP: */
  382. ctcp_reply[0] = 0;
  383. p = strchr(msg, 1);
  384. while ((p != NULL) && (*p)) {
  385. p++;
  386. p1 = p;
  387. while ((*p != 1) && (*p != 0))
  388. p++;
  389. if (*p == 1) {
  390. *p = 0;
  391. ctcp = strcpy(ctcpbuf, p1);
  392. strcpy(p1 - 1, p + 1);
  393. if (!ignoring)
  394. ignoring = detect_flood(nick, uhost, from, strncmp(ctcp, "ACTION ", 7) ? FLOOD_CTCP : FLOOD_PRIVMSG);
  395. /* Respond to the first answer_ctcp */
  396. p = strchr(msg, 1);
  397. if (ctcp_count < answer_ctcp) {
  398. ctcp_count++;
  399. if (ctcp[0] != ' ') {
  400. code = newsplit(&ctcp);
  401. if ((to[0] == '$') || strchr(to, '.')) {
  402. if (!ignoring) {
  403. /* Don't interpret */
  404. putlog(LOG_PUBLIC, to, "CTCP %s: %s from %s (%s) to %s", code, ctcp, nick, uhost, to);
  405. }
  406. } else {
  407. u = get_user_by_host(from);
  408. if (!ignoring || trigger_on_ignore) {
  409. if (check_bind_ctcp(nick, uhost, u, to, code, ctcp) == BIND_RET_LOG && !ignoring) {
  410. if (!strcmp(code, "DCC")) {
  411. /* If it gets this far unhandled, it means that
  412. * the user is totally unknown.
  413. */
  414. code = newsplit(&ctcp);
  415. if (!strcmp(code, "CHAT")) {
  416. if (!quiet_reject) {
  417. if (u)
  418. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, "I'm not accepting call at the moment.");
  419. else
  420. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, DCC_NOSTRANGERS);
  421. }
  422. if (!ischanhub())
  423. putlog(LOG_MISC, "*", "%s: %s", DCC_REFUSEDNC, from);
  424. else
  425. putlog(LOG_MISC, "*", "%s: %s", DCC_REFUSED, from);
  426. } else {
  427. putlog(LOG_MISC, "*", "Refused DCC %s: %s", code, from);
  428. }
  429. } else if (!strcmp(code, "CHAT")) {
  430. if (!quiet_reject) {
  431. if (u)
  432. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, "I'm not accepting call at the moment.");
  433. else
  434. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, DCC_NOSTRANGERS);
  435. }
  436. if (!ischanhub())
  437. putlog(LOG_MISC, "*", "%s: %s", DCC_REFUSEDNC, from);
  438. else
  439. putlog(LOG_MISC, "*", "%s: %s", DCC_REFUSED, from);
  440. }
  441. }
  442. if (!strcmp(code, "ACTION")) {
  443. putlog(LOG_MSGS, "*", "Action to %s: %s %s", to, nick, ctcp);
  444. } else {
  445. putlog(LOG_MSGS, "*", "CTCP %s: %s from %s (%s)", code, ctcp, nick, uhost);
  446. } /* I love a good close cascade ;) */
  447. }
  448. }
  449. }
  450. }
  451. }
  452. }
  453. /* Send out possible ctcp responses */
  454. if (ctcp_reply[0]) {
  455. if (ctcp_mode != 2) {
  456. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
  457. } else {
  458. if (now - last_ctcp > flud_ctcp_time) {
  459. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
  460. count_ctcp = 1;
  461. } else if (count_ctcp < flud_ctcp_thr) {
  462. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
  463. count_ctcp++;
  464. }
  465. last_ctcp = now;
  466. }
  467. }
  468. if (msg[0]) {
  469. if ((to[0] == '$') || (strchr(to, '.') != NULL)) {
  470. /* Msg from oper */
  471. ignoring = detect_flood(nick, uhost, from, FLOOD_PRIVMSG);
  472. if (!ignoring) {
  473. /* Do not interpret as command */
  474. putlog(LOG_MSGS | LOG_SERV, "*", "[%s!%s to %s] %s",nick, uhost, to, msg);
  475. }
  476. } else {
  477. char *my_code = NULL;
  478. Auth *auth = Auth::Find(uhost);
  479. if (!auth)
  480. ignoring = detect_flood(nick, uhost, from, FLOOD_PRIVMSG);
  481. my_code = newsplit(&msg);
  482. rmspace(msg);
  483. /* is it a cmd? */
  484. if (my_code && my_code[0] && my_code[1] && auth && auth->Authed() && my_code[0] == cmdprefix) {
  485. my_code++; //eliminate the cmdprefix
  486. auth->atime = now;
  487. if (!check_bind_authc(my_code, auth, NULL, msg))
  488. putlog(LOG_MSGS, "*", "[%s] %c%s %s", from, cmdprefix, my_code, msg);
  489. } else if (!ignoring && (my_code[0] != cmdprefix || !my_code[1] || !auth || !auth->Authed())) {
  490. struct userrec *my_u = get_user_by_host(from);
  491. bool doit = 1;
  492. if (!egg_strcasecmp(my_code, "op") || !egg_strcasecmp(my_code, "pass") || !egg_strcasecmp(my_code, "invite")
  493. || !egg_strcasecmp(my_code, "ident")
  494. || !egg_strcasecmp(my_code, msgop) || !egg_strcasecmp(my_code, msgpass)
  495. || !egg_strcasecmp(my_code, msginvite) || !egg_strcasecmp(my_code, msgident)) {
  496. const char *buf2 = NULL;
  497. doit = 0;
  498. if (!egg_strcasecmp(my_code, msgop))
  499. buf2 = "op";
  500. else if (!egg_strcasecmp(my_code, msgpass))
  501. buf2 = "pass";
  502. else if (!egg_strcasecmp(my_code, msginvite))
  503. buf2 = "invite";
  504. else if (!egg_strcasecmp(my_code, msgident))
  505. buf2 = "ident";
  506. if (buf2)
  507. check_bind_msg(buf2, nick, uhost, my_u, msg);
  508. else
  509. putlog(LOG_MSGS, "*", "(%s!%s) attempted to use invalid msg cmd '%s'", nick, uhost, my_code);
  510. }
  511. if (doit)
  512. check_bind_msg(my_code, nick, uhost, my_u, msg);
  513. }
  514. }
  515. }
  516. return 0;
  517. }
  518. /* Got a private notice.
  519. */
  520. static int gotnotice(char *from, char *msg)
  521. {
  522. if (msg[0] && ((strchr(CHANMETA, *msg) != NULL) ||
  523. (*msg == '@'))) /* Notice to a channel, not handled here */
  524. return 0;
  525. char *to = NULL, *nick = NULL, ctcpbuf[512] = "", *p = NULL, *p1 = NULL, buf[512] = "",
  526. *uhost = buf, *ctcp = NULL, *ctcpmsg = NULL, *ptr = NULL;
  527. struct userrec *u = NULL;
  528. bool ignoring = match_ignore(from);
  529. to = newsplit(&msg);
  530. fixcolon(msg);
  531. strcpy(uhost, from);
  532. nick = splitnick(&uhost);
  533. if (flud_ctcp_thr && detect_avalanche(msg)) {
  534. /* Discard -- kick user if it was to the channel */
  535. if (!ignoring)
  536. putlog(LOG_MODES, "*", "Avalanche from %s", from);
  537. return 0;
  538. }
  539. /* Check for CTCP: */
  540. ctcpmsg = ptr = strdup(msg);
  541. p = strchr(ctcpmsg, 1);
  542. while ((p != NULL) && (*p)) {
  543. p++;
  544. p1 = p;
  545. while ((*p != 1) && (*p != 0))
  546. p++;
  547. if (*p == 1) {
  548. *p = 0;
  549. ctcp = strcpy(ctcpbuf, p1);
  550. strcpy(p1 - 1, p + 1);
  551. if (!ignoring)
  552. ignoring = detect_flood(nick, uhost, from, FLOOD_CTCP);
  553. p = strchr(ctcpmsg, 1);
  554. if (ctcp[0] != ' ') {
  555. char *code = newsplit(&ctcp);
  556. if ((to[0] == '$') || strchr(to, '.')) {
  557. if (!ignoring)
  558. putlog(LOG_PUBLIC, "*",
  559. "CTCP reply %s: %s from %s (%s) to %s", code, ctcp, nick, uhost, to);
  560. } else {
  561. u = get_user_by_host(from);
  562. if (!ignoring || trigger_on_ignore) {
  563. check_bind_ctcr(nick, uhost, u, to, code, ctcp);
  564. if (!ignoring)
  565. /* Who cares? */
  566. putlog(LOG_MSGS, "*", "CTCP reply %s: %s from %s (%s) to %s", code, ctcp, nick, uhost, to);
  567. }
  568. }
  569. }
  570. }
  571. }
  572. free(ptr);
  573. if (msg[0]) {
  574. if (((to[0] == '$') || strchr(to, '.')) && !ignoring) {
  575. ignoring = detect_flood(nick, uhost, from, FLOOD_NOTICE);
  576. putlog(LOG_MSGS | LOG_SERV, "*", "-%s (%s) to %s- %s", nick, uhost, to, msg);
  577. } else {
  578. /* Server notice? */
  579. if ((nick[0] == 0) || (uhost[0] == 0)) {
  580. if (!server_online &&
  581. (!strcmp(msg, "*** You are exempt from flood limits.") ||
  582. !strcmp(msg, "*** You are exempt from user limits. congrats.")))
  583. floodless = 1;
  584. /* Hidden `250' connection count message from server */
  585. if (strncmp(msg, "Highest connection count:", 25))
  586. putlog(LOG_SERV, "*", "-NOTICE- %s", msg);
  587. } else {
  588. ignoring = detect_flood(nick, uhost, from, FLOOD_NOTICE);
  589. u = get_user_by_host(from);
  590. if (!ignoring)
  591. putlog(LOG_MSGS, "*", "-%s (%s)- %s", nick, uhost, msg);
  592. }
  593. }
  594. }
  595. return 0;
  596. }
  597. /* WALLOPS: oper's nuisance
  598. */
  599. static int gotwall(char *from, char *msg)
  600. {
  601. fixcolon(msg);
  602. putlog(LOG_WALL, "*", "!%s! %s", from, msg);
  603. return 0;
  604. }
  605. static void server_10secondly()
  606. {
  607. if (server_online && keepnick) {
  608. /* NOTE: now that botname can but upto NICKLEN bytes long,
  609. * check that it's not just a truncation of the full nick.
  610. */
  611. if (strncmp(botname, origbotname, strlen(botname))) {
  612. /* See if my nickname is in use and if if my nick is right. */
  613. dprintf(DP_SERVER, "ISON :%s %s\n", botname, origbotname);
  614. }
  615. }
  616. }
  617. /* Called once a minute... but if we're the only one on the
  618. * channel, we only wanna send out "lusers" once every 5 mins.
  619. */
  620. static void minutely_checks()
  621. {
  622. /* Only check if we have already successfully logged in. */
  623. if (server_online) {
  624. static int count = 4;
  625. bool ok = 0;
  626. for (register struct chanset_t *chan = chanset; chan; chan = chan->next) {
  627. if (channel_active(chan) && chan->channel.members == 1) {
  628. ok = 1;
  629. break;
  630. }
  631. }
  632. if (!ok)
  633. return;
  634. count++;
  635. if (count >= 5) {
  636. dprintf(DP_SERVER, "LUSERS\n");
  637. count = 0;
  638. }
  639. }
  640. }
  641. /* Pong from server.
  642. */
  643. static int gotpong(char *from, char *msg)
  644. {
  645. newsplit(&msg);
  646. fixcolon(msg); /* Scrap server name */
  647. server_lag = now - my_atoul(msg);
  648. if (server_lag > 99999) {
  649. /* IRCnet lagmeter support by drummer */
  650. server_lag = now - lastpingtime;
  651. }
  652. return 0;
  653. }
  654. /* This is a reply on ISON :<current> <orig> [<alt>]
  655. */
  656. static void got303(char *from, char *msg)
  657. {
  658. if (!keepnick || !strncmp(botname, origbotname, strlen(botname)))
  659. return;
  660. char *tmp = NULL;
  661. newsplit(&msg);
  662. fixcolon(msg);
  663. tmp = newsplit(&msg);
  664. if (tmp[0] && !rfc_casecmp(botname, tmp)) {
  665. bool ison_orig = 0;
  666. while ((tmp = newsplit(&msg))[0]) { /* no, it's NOT == */
  667. if (!rfc_casecmp(tmp, origbotname))
  668. ison_orig = 1;
  669. }
  670. if (!ison_orig) {
  671. if (!nick_juped)
  672. putlog(LOG_MISC, "*", "Switching back to nick %s", origbotname);
  673. dprintf(DP_SERVER, "NICK %s\n", origbotname);
  674. }
  675. }
  676. }
  677. /* 432 : Bad nickname
  678. */
  679. static int got432(char *from, char *msg)
  680. {
  681. char *erroneus = NULL;
  682. newsplit(&msg);
  683. erroneus = newsplit(&msg);
  684. if (server_online)
  685. putlog(LOG_MISC, "*", "NICK IS INVALID: %s (keeping '%s').", erroneus,
  686. botname);
  687. else {
  688. putlog(LOG_MISC, "*", "Server says my nickname is invalid.");
  689. if (!keepnick) {
  690. makepass(erroneus);
  691. erroneus[NICKMAX] = 0;
  692. dprintf(DP_MODE, "NICK %s\n", erroneus);
  693. }
  694. return 0;
  695. }
  696. return 0;
  697. }
  698. /* 433 : Nickname in use
  699. * Change nicks till we're acceptable or we give up
  700. */
  701. static int got433(char *from, char *msg)
  702. {
  703. /* We are online and have a nickname, we'll keep it */
  704. if (server_online) {
  705. char *tmp = NULL;
  706. newsplit(&msg);
  707. tmp = newsplit(&msg);
  708. putlog(LOG_MISC, "*", "NICK IN USE: %s (keeping '%s').", tmp, botname);
  709. nick_juped = 0;
  710. return 0;
  711. }
  712. gotfake433(from);
  713. return 0;
  714. }
  715. /* 437 : Channel/Nickname juped (IRCnet)
  716. */
  717. static int got437(char *from, char *msg)
  718. {
  719. char *s = NULL;
  720. struct chanset_t *chan = NULL;
  721. newsplit(&msg);
  722. s = newsplit(&msg);
  723. if (s[0] && (strchr(CHANMETA, s[0]) != NULL)) {
  724. chan = findchan(s);
  725. if (chan) {
  726. if (chan->status & CHAN_ACTIVE) {
  727. putlog(LOG_MISC, "*", IRC_CANTCHANGENICK, s);
  728. } else {
  729. if (!channel_juped(chan)) {
  730. putlog(LOG_MISC, "*", "Channel %s is juped. :(", s);
  731. chan->status |= CHAN_JUPED;
  732. }
  733. }
  734. }
  735. } else if (server_online) {
  736. if (!nick_juped)
  737. putlog(LOG_MISC, "*", "NICK IS JUPED: %s (keeping '%s').", s, botname);
  738. if (!rfc_casecmp(s, origbotname))
  739. nick_juped = 1;
  740. } else {
  741. putlog(LOG_MISC, "*", "%s: %s", "Nickname has been juped", s);
  742. gotfake433(from);
  743. }
  744. return 0;
  745. }
  746. /* 438 : Nick change too fast
  747. */
  748. static int got438(char *from, char *msg)
  749. {
  750. newsplit(&msg);
  751. newsplit(&msg);
  752. fixcolon(msg);
  753. putlog(LOG_MISC, "*", "%s", msg);
  754. return 0;
  755. }
  756. static int got451(char *from, char *msg)
  757. {
  758. /* Usually if we get this then we really messed up somewhere
  759. * or this is a non-standard server, so we log it and kill the socket
  760. * hoping the next server will work :) -poptix
  761. */
  762. /* Um, this does occur on a lagged anti-spoof server connection if the
  763. * (minutely) sending of joins occurs before the bot does its ping reply.
  764. * Probably should do something about it some time - beldin
  765. */
  766. putlog(LOG_MISC, "*", "%s says I'm not registered, trying next one.", from);
  767. nuke_server("The server says we are not registered yet..");
  768. return 0;
  769. }
  770. /* Got error notice
  771. */
  772. static int goterror(char *from, char *msg)
  773. {
  774. if (msg[0] == ':')
  775. msg++;
  776. putlog(LOG_SERV, "*", "-ERROR from server- %s", msg);
  777. putlog(LOG_SERV, "*", "Disconnecting from server.");
  778. nuke_server("Bah, stupid error messages.");
  779. return 1;
  780. }
  781. /* Got nick change.
  782. */
  783. static int gotnick(char *from, char *msg)
  784. {
  785. char *nick = NULL, *buf = NULL, *buf_ptr = NULL;
  786. struct userrec *u = NULL;
  787. buf = buf_ptr = strdup(from);
  788. u = get_user_by_host(buf);
  789. nick = splitnick(&buf);
  790. fixcolon(msg);
  791. if (match_my_nick(nick)) {
  792. /* Regained nick! */
  793. strlcpy(botname, msg, NICKLEN);
  794. altnick_char = 0;
  795. if (!strcmp(msg, origbotname)) {
  796. putlog(LOG_SERV | LOG_MISC, "*", "Regained nickname '%s'.", msg);
  797. nick_juped = 0;
  798. } else if (keepnick && strcmp(nick, msg)) {
  799. putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg);
  800. if (!rfc_casecmp(nick, origbotname)) {
  801. putlog(LOG_MISC, "*", "Switching back to nick %s", origbotname);
  802. dprintf(DP_SERVER, "NICK %s\n", origbotname);
  803. }
  804. } else
  805. putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg);
  806. } else if ((keepnick) && (rfc_casecmp(nick, msg))) {
  807. /* Only do the below if there was actual nick change, case doesn't count */
  808. if (!rfc_casecmp(nick, origbotname)) {
  809. putlog(LOG_MISC, "*", "Switching back to nick %s", origbotname);
  810. dprintf(DP_SERVER, "NICK %s\n", origbotname);
  811. }
  812. }
  813. free(buf_ptr);
  814. return 0;
  815. }
  816. static int gotmode(char *from, char *msg)
  817. {
  818. char *ch = NULL, *buf = NULL, *buf_ptr = NULL;
  819. buf_ptr = buf = strdup(msg);
  820. ch = newsplit(&buf);
  821. /* Usermode changes? */
  822. if (strchr(CHANMETA, ch[0]) == NULL) {
  823. if (match_my_nick(ch) && check_mode_r) {
  824. /* umode +r? - D0H dalnet uses it to mean something different */
  825. fixcolon(buf);
  826. if ((buf[0] == '+') && strchr(buf, 'r')) {
  827. putlog(LOG_MISC | LOG_JOIN, "*", "%s has me i-lined (jumping)", dcc[servidx].host);
  828. nuke_server("i-lines suck");
  829. }
  830. }
  831. }
  832. free(buf_ptr);
  833. return 0;
  834. }
  835. static void disconnect_server(int idx, int dolost)
  836. {
  837. if ((serv != dcc[idx].sock) && serv >= 0)
  838. killsock(serv);
  839. if (dcc[idx].sock >= 0)
  840. killsock(dcc[idx].sock);
  841. dcc[idx].sock = -1;
  842. serv = -1;
  843. servidx = -1;
  844. server_online = 0;
  845. floodless = 0;
  846. botuserhost[0] = 0;
  847. botuserip[0] = 0;
  848. if (dolost) {
  849. Auth::DeleteAll();
  850. trying_server = 0;
  851. lostdcc(idx);
  852. }
  853. }
  854. static void eof_server(int idx)
  855. {
  856. putlog(LOG_SERV, "*", "Disconnected from %s", dcc[idx].host);
  857. disconnect_server(idx, DO_LOST);
  858. }
  859. static void display_server(int idx, char *buf)
  860. {
  861. simple_sprintf(buf, "%s (lag: %d)", trying_server ? "conn" : "serv", server_lag);
  862. }
  863. static void connect_server(void);
  864. static void kill_server(int idx, void *x)
  865. {
  866. disconnect_server(idx, NO_LOST); /* eof_server will lostdcc() it. */
  867. for (struct chanset_t *chan = chanset; chan; chan = chan->next)
  868. clear_channel(chan, 1);
  869. /* A new server connection will be automatically initiated in
  870. about 2 seconds. */
  871. }
  872. static void timeout_server(int idx)
  873. {
  874. putlog(LOG_SERV, "*", "Timeout: connect to %s", dcc[idx].host);
  875. disconnect_server(idx, DO_LOST);
  876. }
  877. static void server_activity(int, char *, int);
  878. struct dcc_table SERVER_SOCKET =
  879. {
  880. "SERVER",
  881. 0,
  882. eof_server,
  883. server_activity,
  884. NULL,
  885. timeout_server,
  886. display_server,
  887. kill_server,
  888. NULL,
  889. NULL
  890. };
  891. static void server_activity(int idx, char *msg, int len)
  892. {
  893. char *from = NULL, *code = NULL;
  894. if (trying_server) {
  895. strcpy(dcc[idx].nick, "(server)");
  896. putlog(LOG_SERV, "*", "Connected to %s", dcc[idx].host);
  897. trying_server = 0;
  898. /*
  899. servidx = idx;
  900. serv = dcc[idx].sosck;
  901. */
  902. SERVER_SOCKET.timeout_val = 0;
  903. }
  904. waiting_for_awake = 0;
  905. if (msg[0] == ':') {
  906. msg++;
  907. from = newsplit(&msg);
  908. } else
  909. from = "";
  910. code = newsplit(&msg);
  911. if (use_console_r) {
  912. if (!strcmp(code, "PRIVMSG") || !strcmp(code, "NOTICE")) {
  913. if (!match_ignore(from))
  914. putlog(LOG_RAW, "@", "[@] %s %s %s", from, code, msg);
  915. } else
  916. putlog(LOG_RAW, "@", "[@] %s %s %s", from, code, msg);
  917. }
  918. /* This has GOT to go into the raw binding table, * merely because this
  919. * is less effecient.
  920. */
  921. check_bind_raw(from, code, msg);
  922. }
  923. static int gotping(char *from, char *msg)
  924. {
  925. fixcolon(msg);
  926. dprintf(DP_MODE, "PONG :%s\n", msg);
  927. return 0;
  928. }
  929. static int gotkick(char *from, char *msg)
  930. {
  931. if (!match_my_nick(from))
  932. /* Not my kick, I don't need to bother about it. */
  933. return 0;
  934. if (use_penalties) {
  935. last_time += 2;
  936. if (debug_output)
  937. putlog(LOG_SRVOUT, "*", "adding 2secs penalty (successful kick)");
  938. }
  939. return 0;
  940. }
  941. /* Another sec penalty if bot did a whois on another server.
  942. */
  943. static int got318_369(char *, char *, int);
  944. static int whoispenalty(char *from, char *msg)
  945. {
  946. struct server_list *x = serverlist;
  947. if (x && use_penalties) {
  948. int i = 0, ii = 0;
  949. for (; x; x = x->next) {
  950. if (i == curserv) {
  951. if (strcmp(x->name, from))
  952. ii = 1;
  953. }
  954. i++;
  955. }
  956. if (ii) {
  957. last_time += 1;
  958. if (debug_output)
  959. putlog(LOG_SRVOUT, "*", "adding 1sec penalty (remote whois)");
  960. }
  961. }
  962. got318_369(from, msg, 0);
  963. return 0;
  964. }
  965. static void irc_whois(char *, const char *, ...) __attribute__((format(printf, 2, 3)));
  966. static void
  967. irc_whois(char *nick, const char *format, ...)
  968. {
  969. char va_out[2001] = "";
  970. va_list va;
  971. va_start(va, format);
  972. egg_vsnprintf(va_out, sizeof(va_out) - 1, format, va);
  973. va_end(va);
  974. for (int idx = 0; idx < dcc_total; idx++)
  975. if (dcc[idx].type && dcc[idx].whois[0] && !rfc_casecmp(nick, dcc[idx].whois))
  976. dprintf(idx, "%s\n", va_out);
  977. }
  978. static void check_hostmask()
  979. {
  980. char s[UHOSTLEN + 2] = "";
  981. simple_sprintf(s, "*!%s", botuserhost); /* just add actual user@ident, regardless of ~ */
  982. /* dont add the host if it conflicts with another in the userlist */
  983. struct userrec *u = NULL;
  984. struct list_type *q = NULL;
  985. for (u = userlist; u; u = u->next) {
  986. q = (struct list_type *) get_user(&USERENTRY_HOSTS, u);
  987. for (; q; q = q->next) {
  988. if (wild_match(s, q->extra) || wild_match(q->extra, s)) {
  989. if (u != conf.bot->u) {
  990. putlog(LOG_WARN, "*", "My automatic hostmask '%s' would conflict with user: '%s'. (Not adding)", s, u->handle);
  991. sdprintf("I am %s, they are: %s, (%X vs %X)", conf.bot->u->handle, u->handle, conf.bot->u, u);
  992. } else
  993. sdprintf("Already have hostmask '%s' added for myself", s);
  994. return;
  995. }
  996. }
  997. }
  998. addhost_by_handle(conf.bot->nick, s);
  999. putlog(LOG_GETIN, "*", "Updated my hostmask: %s", s);
  1000. }
  1001. /* 311 $me nick username address * :realname */
  1002. static int got311(char *from, char *msg)
  1003. {
  1004. char *nick = NULL, *username = NULL, *address = NULL, uhost[UHOSTLEN + 1];
  1005. struct userrec *u = NULL;
  1006. newsplit(&msg);
  1007. nick = newsplit(&msg);
  1008. username = newsplit(&msg);
  1009. address = newsplit(&msg);
  1010. newsplit(&msg);
  1011. fixcolon(msg);
  1012. if (match_my_nick(nick)) {
  1013. simple_snprintf(botuserhost, sizeof botuserhost, "%s@%s", username, address);
  1014. check_hostmask();
  1015. }
  1016. irc_whois(nick, "$b%s$b [%s@%s]", nick, username, address);
  1017. simple_snprintf(uhost, sizeof uhost, "%s!%s@%s", nick, username, address);
  1018. if ((u = get_user_by_host(uhost)))
  1019. irc_whois(nick, " username : $u%s$u", u->handle);
  1020. irc_whois(nick, " ircname : %s", msg);
  1021. return 0;
  1022. }
  1023. /* 319 $me nick :channels */
  1024. static int got319(char *from, char *msg)
  1025. {
  1026. char *nick = NULL;
  1027. newsplit(&msg);
  1028. nick = newsplit(&msg);
  1029. fixcolon(msg);
  1030. irc_whois(nick, " channels : %s", msg);
  1031. return 0;
  1032. }
  1033. /* 312 $me nick server :text */
  1034. static int got312(char *from, char *msg)
  1035. {
  1036. char *nick = NULL, *server = NULL;
  1037. newsplit(&msg);
  1038. nick = newsplit(&msg);
  1039. server = newsplit(&msg);
  1040. fixcolon(msg);
  1041. irc_whois(nick, " server : %s [%s]", server, msg);
  1042. return 0;
  1043. }
  1044. /* 301 $me nick :away msg */
  1045. static int got301(char *from, char *msg)
  1046. {
  1047. char *nick = NULL;
  1048. newsplit(&msg);
  1049. nick = newsplit(&msg);
  1050. fixcolon(msg);
  1051. irc_whois(nick, " away : %s", msg);
  1052. return 0;
  1053. }
  1054. /* 313 $me nick :server text */
  1055. static int got313(char *from, char *msg)
  1056. {
  1057. char *nick = NULL;
  1058. newsplit(&msg);
  1059. nick = newsplit(&msg);
  1060. fixcolon(msg);
  1061. irc_whois(nick, " : $b%s$b", msg);
  1062. return 0;
  1063. }
  1064. /* 317 $me nick idle signon :idle-eng signon-eng */
  1065. static int got317(char *from, char *msg)
  1066. {
  1067. char *nick = NULL, date[50] = "";
  1068. time_t idle, signon;
  1069. int mydays, myhours, mymins, mysecs;
  1070. newsplit(&msg);
  1071. nick = newsplit(&msg);
  1072. idle = atol(newsplit(&msg));
  1073. signon = atol(newsplit(&msg));
  1074. fixcolon(msg);
  1075. egg_strftime(date, sizeof date, "%c %Z", gmtime(&signon));
  1076. mydays = idle / 86400;
  1077. idle = idle % 86400;
  1078. myhours = idle / 3600;
  1079. idle = idle % 3600;
  1080. mymins = idle / 60;
  1081. idle = idle % 60;
  1082. mysecs = idle;
  1083. irc_whois(nick, " idle : %d days %d hours %d mins %d secs [signon: %s]", mydays, myhours, mymins, mysecs, date);
  1084. return 0;
  1085. }
  1086. static int got369(char *from, char *msg)
  1087. {
  1088. return got318_369(from, msg, 1);
  1089. }
  1090. /* 318/319 $me nick :End of /? */
  1091. static int got318_369(char *from, char *msg, int whowas)
  1092. {
  1093. char *nick = NULL;
  1094. newsplit(&msg);
  1095. nick = newsplit(&msg);
  1096. fixcolon(msg);
  1097. irc_whois(nick, "%s", msg);
  1098. for (int idx = 0; idx < dcc_total; idx++) {
  1099. if (dcc[idx].type && dcc[idx].whois[0] && !rfc_casecmp(dcc[idx].whois, nick) &&
  1100. ((!whowas && !dcc[idx].whowas) || (whowas && dcc[idx].whowas))) {
  1101. dcc[idx].whois[0] = 0;
  1102. dcc[idx].whowas = 0;
  1103. }
  1104. }
  1105. return 0;
  1106. }
  1107. /* 401 $me nick :text */
  1108. static int got401(char *from, char *msg)
  1109. {
  1110. char *nick = NULL;
  1111. newsplit(&msg);
  1112. nick = newsplit(&msg);
  1113. fixcolon(msg);
  1114. irc_whois(nick, "%s", msg);
  1115. for (int idx = 0; idx < dcc_total; idx++)
  1116. if (dcc[idx].type && dcc[idx].whois[0] && !rfc_casecmp(dcc[idx].whois, nick))
  1117. dcc[idx].whowas = 1;
  1118. dprintf(DP_SERVER, "WHOWAS %s %s\n", nick, from);
  1119. return 0;
  1120. }
  1121. /* 406 $me nick :text */
  1122. static int got406(char *from, char *msg)
  1123. {
  1124. char *nick = NULL;
  1125. newsplit(&msg);
  1126. nick = newsplit(&msg);
  1127. fixcolon(msg);
  1128. irc_whois(nick, "%s", msg);
  1129. return 0;
  1130. }
  1131. /* 718 $me nick user@host :msg
  1132. * for receiving a msg while +g
  1133. */
  1134. static int got718(char *from, char *msg)
  1135. {
  1136. char *nick = NULL, *uhost = NULL;
  1137. newsplit(&msg);
  1138. nick = newsplit(&msg);
  1139. uhost = newsplit(&msg);
  1140. fixcolon(msg);
  1141. putlog(LOG_WALL, "*", "(+g) !%s!%s! %s", nick, uhost, msg);
  1142. return 0;
  1143. }
  1144. static cmd_t my_raw_binds[] =
  1145. {
  1146. {"PRIVMSG", "", (Function) gotmsg, NULL, LEAF},
  1147. {"NOTICE", "", (Function) gotnotice, NULL, LEAF},
  1148. {"MODE", "", (Function) gotmode, NULL, LEAF},
  1149. {"PING", "", (Function) gotping, NULL, LEAF},
  1150. {"PONG", "", (Function) gotpong, NULL, LEAF},
  1151. {"WALLOPS", "", (Function) gotwall, NULL, LEAF},
  1152. {"001", "", (Function) got001, NULL, LEAF},
  1153. {"005", "", (Function) got005, NULL, LEAF},
  1154. {"303", "", (Function) got303, NULL, LEAF},
  1155. {"432", "", (Function) got432, NULL, LEAF},
  1156. {"433", "", (Function) got433, NULL, LEAF},
  1157. {"437", "", (Function) got437, NULL, LEAF},
  1158. {"438", "", (Function) got438, NULL, LEAF},
  1159. {"451", "", (Function) got451, NULL, LEAF},
  1160. {"442", "", (Function) got442, NULL, LEAF},
  1161. {"NICK", "", (Function) gotnick, NULL, LEAF},
  1162. {"ERROR", "", (Function) goterror, NULL, LEAF},
  1163. /* ircu2.10.10 has a bug when a client is throttled ERROR is sent wrong */
  1164. {"ERROR:", "", (Function) goterror, NULL, LEAF},
  1165. {"KICK", "", (Function) gotkick, NULL, LEAF},
  1166. /* WHOIS RAWS */
  1167. {"311", "", (Function) got311, NULL, LEAF}, /* ident host * :realname */
  1168. {"314", "", (Function) got311, NULL, LEAF}, /* "" -WHOWAS */
  1169. {"319", "", (Function) got319, NULL, LEAF}, /* :#channels */
  1170. {"312", "", (Function) got312, NULL, LEAF}, /* server :gecos */
  1171. {"301", "", (Function) got301, NULL, LEAF}, /* :away msg */
  1172. {"313", "", (Function) got313, NULL, LEAF}, /* :ircop */
  1173. {"317", "", (Function) got317, NULL, LEAF}, /* idle, signon :idle-eng, signon-eng */
  1174. {"401", "", (Function) got401, NULL, LEAF},
  1175. {"406", "", (Function) got406, NULL, LEAF},
  1176. {"318", "", (Function) whoispenalty, NULL, LEAF}, /* :End of /WHOIS */
  1177. {"369", "", (Function) got369, NULL, LEAF}, /* :End of /WHOWAS */
  1178. {"718", "", (Function) got718, NULL, LEAF},
  1179. {NULL, NULL, NULL, NULL, 0}
  1180. };
  1181. static void server_dns_callback(int, void *, const char *, char **);
  1182. /* Hook up to a server
  1183. */
  1184. static void connect_server(void)
  1185. {
  1186. char pass[121] = "", botserver[UHOSTLEN] = "";
  1187. int newidx;
  1188. port_t botserverport = 0;
  1189. waiting_for_awake = 0;
  1190. /* trying_server = now; */
  1191. empty_msgq();
  1192. if (newserverport) { /* cmd_jump was used; connect specified server */
  1193. curserv = -1; /* Reset server list */
  1194. strcpy(botserver, newserver);
  1195. botserverport = newserverport;
  1196. strcpy(pass, newserverpass);
  1197. newserver[0] = newserverport = newserverpass[0] = 0;
  1198. }
  1199. if (!cycle_time) {
  1200. struct chanset_t *chan = NULL;
  1201. struct server_list *x = serverlist;
  1202. if (!x)
  1203. return;
  1204. trying_server = now;
  1205. newidx = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
  1206. if (newidx < 0) {
  1207. putlog(LOG_SERV, "*", "NO MORE DCC CONNECTIONS -- Can't create server connection.");
  1208. trying_server = 0;
  1209. return;
  1210. }
  1211. next_server(&curserv, botserver, &botserverport, pass);
  1212. putlog(LOG_SERV, "*", "Trying server %s:%d", botserver, botserverport);
  1213. dcc[newidx].port = botserverport;
  1214. strcpy(dcc[newidx].nick, "(server)");
  1215. strlcpy(dcc[newidx].host, botserver, UHOSTLEN);
  1216. botuserhost[0] = 0;
  1217. nick_juped = 0;
  1218. for (chan = chanset; chan; chan = chan->next)
  1219. chan->status &= ~CHAN_JUPED;
  1220. dcc[newidx].timeval = now;
  1221. dcc[newidx].sock = -1;
  1222. dcc[newidx].u.dns->cbuf = strdup(pass);
  1223. cycle_time = 15; /* wait 15 seconds before attempting next server connect */
  1224. /* I'm resolving... don't start another server connect request */
  1225. resolvserv = 1;
  1226. /* Resolve the hostname. */
  1227. int dns_id = egg_dns_lookup(botserver, 20, server_dns_callback, (void *) newidx);
  1228. if (dns_id >= 0)
  1229. dcc[newidx].dns_id = dns_id;
  1230. /* wait for async reply */
  1231. }
  1232. }
  1233. static void server_dns_callback(int id, void *client_data, const char *host, char **ips)
  1234. {
  1235. int idx = (int) client_data;
  1236. resolvserv = 0;
  1237. if (!valid_dns_id(idx, id))
  1238. return;
  1239. if (!ips) {
  1240. putlog(LOG_SERV, "*", "Failed connect to %s (DNS lookup failed)", host);
  1241. trying_server = 0;
  1242. lostdcc(idx);
  1243. return;
  1244. }
  1245. addr_t addr;
  1246. char *ip = NULL;
  1247. /* FIXME: this is a temporary hack to stop bots from connecting over ipv4 when they should be on ipv6
  1248. * eventually will handle this in open_telnet(ips);
  1249. */
  1250. if (conf.bot->net.v6) {
  1251. int i = 0;
  1252. for (i = 0; ips[i]; i++) {
  1253. if (is_dotted_ip(ips[i]) == AF_INET6) {
  1254. ip = ips[i];
  1255. break;
  1256. }
  1257. }
  1258. if (!ip) {
  1259. putlog(LOG_SERV, "*", "Failed connect to %s (Could not DNS as IPV6)", host);
  1260. trying_server = 0;
  1261. lostdcc(idx);
  1262. return;
  1263. }
  1264. } else
  1265. ip = ips[0];
  1266. get_addr(ip, &addr);
  1267. if (addr.family == AF_INET)
  1268. dcc[idx].addr = htonl(addr.u.addr.s_addr);
  1269. strcpy(serverpass, (char *) dcc[idx].u.dns->cbuf);
  1270. changeover_dcc(idx, &SERVER_SOCKET, 0);
  1271. identd_open();
  1272. serv = open_telnet(ip, dcc[idx].port, 0);
  1273. if (serv < 0) {
  1274. putlog(LOG_SERV, "*", "Failed connect to %s (%s)", dcc[idx].host, strerror(errno));
  1275. trying_server = 0;
  1276. lostdcc(idx);
  1277. } else {
  1278. int i = 1;
  1279. /* set these now so if we fail disconnect_server() can cleanup right. */
  1280. dcc[idx].sock = serv;
  1281. servidx = idx;
  1282. sdprintf("Connecting to '%s' (serv: %d, servidx: %d)", dcc[idx].host, serv, servidx);
  1283. setsockopt(serv, 6, TCP_NODELAY, &i, sizeof(int));
  1284. /* Queue standard login */
  1285. dcc[idx].timeval = now;
  1286. SERVER_SOCKET.timeout_val = &server_timeout;
  1287. /* Another server may have truncated it, so use the original */
  1288. strcpy(botname, origbotname);
  1289. /* Start alternate nicks from the beginning */
  1290. altnick_char = 0;
  1291. if (serverpass[0])
  1292. dprintf(DP_MODE, "PASS %s\n", serverpass);
  1293. dprintf(DP_MODE, "NICK %s\n", botname);
  1294. dprintf(DP_MODE, "USER %s localhost %s :%s\n", botuser, dcc[idx].host, botrealname);
  1295. /* Wait for async result now */
  1296. }
  1297. }