botnet.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738
  1. /*
  2. * botnet.c -- handles:
  3. * keeping track of which bot's connected where in the chain
  4. * dumping a list of bots or a bot tree to a user
  5. * channel name associations on the party line
  6. * rejecting a bot
  7. * linking, unlinking, and relaying to another bot
  8. * pinging the bots periodically and checking leaf status
  9. *
  10. */
  11. #include "common.h"
  12. #include "botnet.h"
  13. #include "chanprog.h"
  14. #include "net.h"
  15. #include "users.h"
  16. #include "misc.h"
  17. #include "userrec.h"
  18. #include "main.h"
  19. #include "dccutil.h"
  20. #include "dcc.h"
  21. #include "botmsg.h"
  22. #include "tandem.h"
  23. #include "core_binds.h"
  24. #ifdef HUB
  25. # ifdef S_AUTOLOCK
  26. # include "src/mod/channels.mod/channels.h"
  27. # endif /* S_AUTOLOCK */
  28. #endif /* HUB */
  29. tand_t *tandbot = NULL; /* Keep track of tandem bots on the
  30. botnet */
  31. party_t *party = NULL; /* Keep track of people on the botnet */
  32. int tands = 0; /* Number of bots on the botnet */
  33. static int maxparty = 100; /* Maximum space for party line members
  34. currently */
  35. static int parties = 0; /* Number of people on the botnet */
  36. static int share_unlinks = 1; /* Allow remote unlinks of my
  37. sharebots? */
  38. void init_bots()
  39. {
  40. party = (party_t *) calloc(1, maxparty * sizeof(party_t));
  41. }
  42. tand_t *findbot(char *who)
  43. {
  44. tand_t *ptr = NULL;
  45. for (ptr = tandbot; ptr; ptr = ptr->next)
  46. if (!egg_strcasecmp(ptr->bot, who))
  47. return ptr;
  48. return NULL;
  49. }
  50. /* Add a tandem bot to our chain list
  51. */
  52. void addbot(char *who, char *from, char *next, char flag, int vernum)
  53. {
  54. tand_t **ptr = &tandbot, *ptr2 = NULL;
  55. while (*ptr) {
  56. if (!egg_strcasecmp((*ptr)->bot, who))
  57. putlog(LOG_BOTS, "*", "!!! Duplicate botnet bot entry!!");
  58. ptr = &((*ptr)->next);
  59. }
  60. ptr2 = calloc(1, sizeof(tand_t));
  61. strncpy(ptr2->bot, who, HANDLEN);
  62. ptr2->bot[HANDLEN] = 0;
  63. ptr2->share = flag;
  64. ptr2->ver = vernum;
  65. ptr2->next = *ptr;
  66. *ptr = ptr2;
  67. /* May be via itself */
  68. ptr2->via = findbot(from);
  69. if (!egg_strcasecmp(next, conf.bot->nick))
  70. ptr2->uplink = (tand_t *) 1;
  71. else
  72. ptr2->uplink = findbot(next);
  73. tands++;
  74. }
  75. #ifdef HUB
  76. #ifdef G_BACKUP
  77. void check_should_backup()
  78. {
  79. struct chanset_t *chan = NULL;
  80. for (chan = chanset; chan; chan = chan->next) {
  81. if (chan->channel.backup_time && (chan->channel.backup_time < now) && !channel_backup(chan)) {
  82. do_chanset(NULL, chan, STR("+backup"), DO_LOCAL | DO_NET);
  83. chan->channel.backup_time = 0;
  84. }
  85. }
  86. }
  87. #endif /* G_BACKUP */
  88. #endif /* HUB */
  89. void updatebot(int idx, char *who, char share, int vernum)
  90. {
  91. tand_t *ptr = findbot(who);
  92. if (ptr) {
  93. if (share)
  94. ptr->share = share;
  95. if (vernum)
  96. ptr->ver = vernum;
  97. botnet_send_update(idx, ptr);
  98. }
  99. }
  100. /* For backward 1.0 compatibility:
  101. * grab the (first) sock# for a user on another bot
  102. */
  103. int partysock(char *bot, char *nick)
  104. {
  105. int i;
  106. for (i = 0; i < parties; i++) {
  107. if ((!egg_strcasecmp(party[i].bot, bot)) &&
  108. (!egg_strcasecmp(party[i].nick, nick)))
  109. return party[i].sock;
  110. }
  111. return 0;
  112. }
  113. /* New botnet member
  114. */
  115. int addparty(char *bot, char *nick, int chan, char flag, int sock,
  116. char *from, int *idx)
  117. {
  118. int i;
  119. for (i = 0; i < parties; i++) {
  120. /* Just changing the channel of someone already on? */
  121. if (!egg_strcasecmp(party[i].bot, bot) &&
  122. (party[i].sock == sock)) {
  123. int oldchan = party[i].chan;
  124. party[i].chan = chan;
  125. party[i].timer = now;
  126. if (from[0]) {
  127. if (flag == ' ')
  128. flag = '-';
  129. party[i].flag = flag;
  130. if (party[i].from)
  131. free(party[i].from);
  132. party[i].from = strdup(from);
  133. }
  134. *idx = i;
  135. return oldchan;
  136. }
  137. }
  138. /* New member */
  139. if (parties == maxparty) {
  140. maxparty += 50;
  141. party = (party_t *) realloc((void *) party, maxparty * sizeof(party_t));
  142. }
  143. strncpy(party[parties].nick, nick, HANDLEN);
  144. party[parties].nick[HANDLEN] = 0;
  145. strncpy(party[parties].bot, bot, HANDLEN);
  146. party[parties].bot[HANDLEN] = 0;
  147. party[parties].chan = chan;
  148. party[parties].sock = sock;
  149. party[parties].status = 0;
  150. party[parties].away = 0;
  151. party[parties].timer = now; /* cope. */
  152. if (from[0]) {
  153. if (flag == ' ')
  154. flag = '-';
  155. party[parties].flag = flag;
  156. party[parties].from = strdup(from);
  157. } else {
  158. party[parties].flag = ' ';
  159. party[parties].from = strdup("(unknown)");
  160. }
  161. *idx = parties;
  162. parties++;
  163. return -1;
  164. }
  165. /* Alter status flags for remote party-line user.
  166. */
  167. void partystat(char *bot, int sock, int add, int rem)
  168. {
  169. int i;
  170. for (i = 0; i < parties; i++) {
  171. if ((!egg_strcasecmp(party[i].bot, bot)) &&
  172. (party[i].sock == sock)) {
  173. party[i].status |= add;
  174. party[i].status &= ~rem;
  175. }
  176. }
  177. }
  178. /* Other bot is sharing idle info.
  179. */
  180. void partysetidle(char *bot, int sock, int secs)
  181. {
  182. int i;
  183. for (i = 0; i < parties; i++) {
  184. if ((!egg_strcasecmp(party[i].bot, bot)) &&
  185. (party[i].sock == sock)) {
  186. party[i].timer = (now - (time_t) secs);
  187. }
  188. }
  189. }
  190. /* Return someone's chat channel.
  191. */
  192. int getparty(char *bot, int sock)
  193. {
  194. int i;
  195. for (i = 0; i < parties; i++) {
  196. if (!egg_strcasecmp(party[i].bot, bot) &&
  197. (party[i].sock == sock)) {
  198. return i;
  199. }
  200. }
  201. return -1;
  202. }
  203. /* Un-idle someone
  204. */
  205. int partyidle(char *bot, char *nick)
  206. {
  207. int i, ok = 0;
  208. for (i = 0; i < parties; i++) {
  209. if ((!egg_strcasecmp(party[i].bot, bot)) &&
  210. (!egg_strcasecmp(party[i].nick, nick))) {
  211. party[i].timer = now;
  212. ok = 1;
  213. }
  214. }
  215. return ok;
  216. }
  217. /* Change someone's nick
  218. */
  219. int partynick(char *bot, int sock, char *nick)
  220. {
  221. char work[HANDLEN + 1] = "";
  222. int i;
  223. for (i = 0; i < parties; i++) {
  224. if (!egg_strcasecmp(party[i].bot, bot) && (party[i].sock == sock)) {
  225. strcpy(work, party[i].nick);
  226. strncpy(party[i].nick, nick, HANDLEN);
  227. party[i].nick[HANDLEN] = 0;
  228. strcpy(nick, work);
  229. return i;
  230. }
  231. }
  232. return -1;
  233. }
  234. /* Set away message
  235. */
  236. void partyaway(char *bot, int sock, char *msg)
  237. {
  238. int i;
  239. for (i = 0; i < parties; i++) {
  240. if ((!egg_strcasecmp(party[i].bot, bot)) &&
  241. (party[i].sock == sock)) {
  242. if (party[i].away)
  243. free(party[i].away);
  244. if (msg[0]) {
  245. party[i].away = strdup(msg);
  246. } else
  247. party[i].away = 0;
  248. }
  249. }
  250. }
  251. /* Remove a tandem bot from the chain list
  252. */
  253. void rembot(char *who)
  254. {
  255. tand_t **ptr = &tandbot, *ptr2 = NULL;
  256. struct userrec *u = NULL;
  257. while (*ptr) {
  258. if (!egg_strcasecmp((*ptr)->bot, who))
  259. break;
  260. ptr = &((*ptr)->next);
  261. }
  262. if (!*ptr)
  263. /* May have just .unlink *'d */
  264. return;
  265. check_bind_disc(who);
  266. u = get_user_by_handle(userlist, who);
  267. if (u != NULL)
  268. touch_laston(u, "unlinked", now);
  269. ptr2 = *ptr;
  270. *ptr = ptr2->next;
  271. free(ptr2);
  272. tands--;
  273. dupwait_notify(who);
  274. }
  275. void remparty(char *bot, int sock)
  276. {
  277. int i;
  278. for (i = 0; i < parties; i++)
  279. if ((!egg_strcasecmp(party[i].bot, bot)) &&
  280. (party[i].sock == sock)) {
  281. parties--;
  282. if (party[i].from)
  283. free(party[i].from);
  284. if (party[i].away)
  285. free(party[i].away);
  286. if (i < parties) {
  287. strcpy(party[i].bot, party[parties].bot);
  288. strcpy(party[i].nick, party[parties].nick);
  289. party[i].chan = party[parties].chan;
  290. party[i].sock = party[parties].sock;
  291. party[i].flag = party[parties].flag;
  292. party[i].status = party[parties].status;
  293. party[i].timer = party[parties].timer;
  294. party[i].from = party[parties].from;
  295. party[i].away = party[parties].away;
  296. }
  297. }
  298. }
  299. /* Cancel every user that was on a certain bot
  300. */
  301. void rempartybot(char *bot)
  302. {
  303. int i;
  304. for (i = 0; i < parties; i++)
  305. if (!egg_strcasecmp(party[i].bot, bot)) {
  306. if (party[i].chan >= 0)
  307. check_bind_chpt(bot, party[i].nick, party[i].sock, party[i].chan);
  308. remparty(bot, party[i].sock);
  309. i--;
  310. }
  311. }
  312. /* Remove every bot linked 'via' bot <x>
  313. */
  314. void unvia(int idx, tand_t * who)
  315. {
  316. tand_t *bot = NULL, *bot2 = NULL;
  317. if (!who)
  318. return; /* Safety */
  319. rempartybot(who->bot);
  320. bot = tandbot;
  321. while (bot) {
  322. if (bot->uplink == who) {
  323. unvia(idx, bot);
  324. bot2 = bot->next;
  325. rembot(bot->bot);
  326. bot = bot2;
  327. } else
  328. bot = bot->next;
  329. }
  330. }
  331. void besthub(char *hub)
  332. {
  333. tand_t *ptr = tandbot;
  334. struct userrec *u = NULL, *besthub = NULL;
  335. char bestlval[20] = "", lval[20] = "";
  336. hub[0] = 0;
  337. strcpy(bestlval, "z");
  338. while (ptr) {
  339. u = get_user_by_handle(userlist, ptr->bot);
  340. if (u) {
  341. link_pref_val(u, lval);
  342. if (strcmp(lval, bestlval) < 0) {
  343. strcpy(bestlval, lval);
  344. besthub = u;
  345. }
  346. }
  347. ptr = ptr->next;
  348. }
  349. if (besthub)
  350. strcpy(hub, besthub->handle);
  351. return;
  352. }
  353. /* Return index into dcc list of the bot that connects us to bot <x>
  354. */
  355. int nextbot(char *who)
  356. {
  357. int j;
  358. tand_t *bot = findbot(who);
  359. if (!bot)
  360. return -1;
  361. for (j = 0; j < dcc_total; j++)
  362. if (bot->via && !egg_strcasecmp(bot->via->bot, dcc[j].nick) &&
  363. (dcc[j].type == &DCC_BOT))
  364. return j;
  365. return -1; /* We're not connected to 'via' */
  366. }
  367. /* Return name of the bot that is directly connected to bot X
  368. */
  369. char *lastbot(char *who)
  370. {
  371. tand_t *bot = findbot(who);
  372. if (!bot)
  373. return "*";
  374. else if (bot->uplink == (tand_t *) 1)
  375. return conf.bot->nick;
  376. else
  377. return bot->uplink->bot;
  378. }
  379. /* Modern version of 'whom' (use local data)
  380. */
  381. void answer_local_whom(int idx, int chan)
  382. {
  383. char format[81] = "", c = 0, idle[40] = "";
  384. int i, t, nicklen, botnicklen, total = 0;
  385. if (chan == (-1))
  386. dprintf(idx, "%s (+: %s, *: %s)\n", BOT_BOTNETUSERS, BOT_PARTYLINE,
  387. BOT_LOCALCHAN);
  388. else if (chan > 0) {
  389. dprintf(idx, "%s %s%d:\n", BOT_USERSONCHAN,
  390. (chan < GLOBAL_CHANS) ? "" : "*", chan % GLOBAL_CHANS);
  391. }
  392. /* Find longest nick and botnick */
  393. nicklen = botnicklen = 0;
  394. for (i = 0; i < dcc_total; i++)
  395. if (dcc[i].type == &DCC_CHAT) {
  396. if ((chan == (-1)) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
  397. t = strlen(dcc[i].nick); if(t > nicklen) nicklen = t;
  398. t = strlen(conf.bot->nick); if(t > botnicklen) botnicklen = t;
  399. }
  400. }
  401. for (i = 0; i < parties; i++) {
  402. if ((chan == (-1)) || ((chan >= 0) && (party[i].chan == chan))) {
  403. t = strlen(party[i].nick); if(t > nicklen) nicklen = t;
  404. t = strlen(party[i].bot); if(t > botnicklen) botnicklen = t;
  405. }
  406. }
  407. if(nicklen < 9) nicklen = 9;
  408. if(botnicklen < 9) botnicklen = 9;
  409. #ifdef HUB
  410. egg_snprintf(format, sizeof format, "%%-%us %%-%us %%s\n",
  411. nicklen, botnicklen);
  412. dprintf(idx, format, " Nick", " Bot", " Host");
  413. dprintf(idx, format, "----------", "---------", "--------------------");
  414. egg_snprintf(format, sizeof format, "%%c%%-%us %%c %%-%us %%s%%s\n",
  415. nicklen, botnicklen);
  416. #else /* !HUB */
  417. egg_snprintf(format, sizeof format, "%%-%us\n", nicklen);
  418. dprintf(idx, format, " Nick");
  419. dprintf(idx, format, "----------");
  420. egg_snprintf(format, sizeof format, "%%c%%-%us %%c %%s\n", nicklen);
  421. #endif /* HUB */
  422. for (i = 0; i < dcc_total; i++)
  423. if (dcc[i].type == &DCC_CHAT) {
  424. if ((chan == (-1)) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
  425. c = geticon(i);
  426. if (c == '-')
  427. c = ' ';
  428. if (now - dcc[i].timeval > 300) {
  429. unsigned long days, hrs, mins;
  430. days = (now - dcc[i].timeval) / 86400;
  431. hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
  432. mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
  433. if (days > 0)
  434. sprintf(idle, " [idle %lud%luh]", days, hrs);
  435. else if (hrs > 0)
  436. sprintf(idle, " [idle %luh%lum]", hrs, mins);
  437. else
  438. sprintf(idle, " [idle %lum]", mins);
  439. } else
  440. idle[0] = 0;
  441. total++;
  442. dprintf(idx, format, c, dcc[i].nick,
  443. (dcc[i].u.chat->channel == 0) && (chan == (-1)) ? '+' :
  444. (dcc[i].u.chat->channel > GLOBAL_CHANS) &&
  445. #ifdef HUB
  446. (chan == (-1)) ? '*' : ' ', conf.bot->nick, dcc[i].host, idle);
  447. #else /* !HUB */
  448. (chan == (-1)) ? '*' : ' ', idle);
  449. #endif /* HUB */
  450. if (dcc[i].u.chat->away != NULL)
  451. dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
  452. }
  453. }
  454. for (i = 0; i < parties; i++) {
  455. if ((chan == (-1)) || ((chan >= 0) && (party[i].chan == chan))) {
  456. c = party[i].flag;
  457. if (c == '-')
  458. c = ' ';
  459. if (party[i].timer == 0L)
  460. strcpy(idle, " [idle?]");
  461. else if (now - party[i].timer > 300) {
  462. unsigned long days, hrs, mins;
  463. days = (now - party[i].timer) / 86400;
  464. hrs = ((now - party[i].timer) - (days * 86400)) / 3600;
  465. mins = ((now - party[i].timer) - (hrs * 3600)) / 60;
  466. if (days > 0)
  467. sprintf(idle, " [idle %lud%luh]", days, hrs);
  468. else if (hrs > 0)
  469. sprintf(idle, " [idle %luh%lum]", hrs, mins);
  470. else
  471. sprintf(idle, " [idle %lum]", mins);
  472. } else
  473. idle[0] = 0;
  474. total++;
  475. dprintf(idx, format, c, party[i].nick,
  476. (party[i].chan == 0) && (chan == (-1)) ? '+' : ' ',
  477. #ifdef HUB
  478. party[i].bot, party[i].from, idle);
  479. #else /* !HUB */
  480. idle);
  481. #endif /* HUB */
  482. if (party[i].status & PLSTAT_AWAY)
  483. dprintf(idx, " %s: %s\n", MISC_AWAY,
  484. party[i].away ? party[i].away : "");
  485. }
  486. }
  487. dprintf(idx, "Total users: %d\n", total);
  488. }
  489. /* Show z a list of all bots connected
  490. */
  491. void tell_bots(int idx)
  492. {
  493. char s[512] = "";
  494. int i;
  495. tand_t *bot = NULL;
  496. if (!tands) {
  497. dprintf(idx, "No bots linked\n");
  498. return;
  499. }
  500. strcpy(s, conf.bot->nick);
  501. i = strlen(conf.bot->nick);
  502. for (bot = tandbot; bot; bot = bot->next) {
  503. if (i > (500 - HANDLEN)) {
  504. dprintf(idx, "Bots: %s\n", s);
  505. s[0] = 0;
  506. i = 0;
  507. }
  508. if (i) {
  509. s[i++] = ',';
  510. s[i++] = ' ';
  511. }
  512. strcpy(s + i, bot->bot);
  513. i += strlen(bot->bot);
  514. }
  515. if (s[0])
  516. dprintf(idx, "Bots: %s\n", s);
  517. dprintf(idx, "(Total up: %d)\n", tands + 1);
  518. }
  519. /* Show a simpleton bot tree
  520. */
  521. void tell_bottree(int idx, int showver)
  522. {
  523. char s[161] = "", work[1024] = "";
  524. tand_t *last[20] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  525. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  526. tand_t *this = NULL, *bot = NULL, *bot2 = NULL;
  527. int lev = 0, more = 1, mark[20], ok, cnt, i = 0, imark, tothops = 0;
  528. if (tands == 0) {
  529. dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
  530. return;
  531. }
  532. for (bot = tandbot; bot; bot = bot->next)
  533. if (!bot->uplink) {
  534. if (i) {
  535. s[i++] = ',';
  536. s[i++] = ' ';
  537. }
  538. strcpy(s + i, bot->bot);
  539. i += strlen(bot->bot);
  540. }
  541. if (s[0])
  542. dprintf(idx, "(%s %s)\n", BOT_NOTRACEINFO, s);
  543. if (showver)
  544. dprintf(idx, "%s (%lu)\n", conf.bot->nick, buildts);
  545. else
  546. dprintf(idx, "%s\n", conf.bot->nick);
  547. this = (tand_t *) 1;
  548. work[0] = 0;
  549. while (more) {
  550. if (lev == 20) {
  551. dprintf(idx, "\n%s\n", BOT_COMPLEXTREE);
  552. return;
  553. }
  554. cnt = 0;
  555. tothops += lev;
  556. for (bot = tandbot; bot; bot = bot->next)
  557. if (bot->uplink == this)
  558. cnt++;
  559. if (cnt) {
  560. imark = 0;
  561. for (i = 0; i < lev; i++) {
  562. if (mark[i])
  563. strcpy(work + imark, " | ");
  564. else
  565. strcpy(work + imark, " ");
  566. imark += 5;
  567. }
  568. if (cnt > 1)
  569. strcpy(work + imark, " |-");
  570. else
  571. strcpy(work + imark, " `-");
  572. s[0] = 0;
  573. bot = tandbot;
  574. while (!s[0]) {
  575. if (bot->uplink == this) {
  576. if (bot->ver) {
  577. i = sprintf(s, "%c%s", bot->share, bot->bot);
  578. if (showver)
  579. sprintf(s + i, " (%d.%d.%d.%d)",
  580. bot->ver / 1000000,
  581. bot->ver % 1000000 / 10000,
  582. bot->ver % 10000 / 100,
  583. bot->ver % 100);
  584. } else {
  585. sprintf(s, "-%s", bot->bot);
  586. }
  587. } else
  588. bot = bot->next;
  589. }
  590. dprintf(idx, "%s%s\n", work, s);
  591. if (cnt > 1)
  592. mark[lev] = 1;
  593. else
  594. mark[lev] = 0;
  595. work[0] = 0;
  596. last[lev] = this;
  597. this = bot;
  598. lev++;
  599. more = 1;
  600. } else {
  601. while (cnt == 0) {
  602. /* No subtrees from here */
  603. if (lev == 0) {
  604. dprintf(idx, "(( tree error ))\n");
  605. return;
  606. }
  607. ok = 0;
  608. for (bot = tandbot; bot; bot = bot->next) {
  609. if (bot->uplink == last[lev - 1]) {
  610. if (this == bot)
  611. ok = 1;
  612. else if (ok) {
  613. cnt++;
  614. if (cnt == 1) {
  615. bot2 = bot;
  616. if (bot->ver) {
  617. i = sprintf(s, "%c%s", bot->share, bot->bot);
  618. if (showver)
  619. sprintf(s + i, " (%d.%d.%d.%d)",
  620. bot->ver / 1000000,
  621. bot->ver % 1000000 / 10000,
  622. bot->ver % 10000 / 100,
  623. bot->ver % 100);
  624. } else {
  625. sprintf(s, "-%s", bot->bot);
  626. }
  627. }
  628. }
  629. }
  630. }
  631. if (cnt) {
  632. imark = 0;
  633. for (i = 1; i < lev; i++) {
  634. if (mark[i - 1])
  635. strcpy(work + imark, " | ");
  636. else
  637. strcpy(work + imark, " ");
  638. imark += 5;
  639. }
  640. more = 1;
  641. if (cnt > 1)
  642. dprintf(idx, "%s |-%s\n", work, s);
  643. else
  644. dprintf(idx, "%s `-%s\n", work, s);
  645. this = bot2;
  646. work[0] = 0;
  647. if (cnt > 1)
  648. mark[lev - 1] = 1;
  649. else
  650. mark[lev - 1] = 0;
  651. } else {
  652. /* This was the last child */
  653. lev--;
  654. if (lev == 0) {
  655. more = 0;
  656. cnt = 999;
  657. } else {
  658. more = 1;
  659. this = last[lev];
  660. }
  661. }
  662. }
  663. }
  664. }
  665. /* Hop information: (9d) */
  666. dprintf(idx, "Average hops: %3.1f, total bots: %d\n", ((float) tothops) / ((float) tands), tands + 1);
  667. }
  668. /* Dump list of links to a new bot
  669. */
  670. void dump_links(int z)
  671. {
  672. register int i, l;
  673. char x[1024] = "";
  674. tand_t *bot = NULL;
  675. for (bot = tandbot; bot; bot = bot->next) {
  676. char *p = NULL;
  677. if (bot->uplink == (tand_t *) 1)
  678. p = conf.bot->nick;
  679. else
  680. p = bot->uplink->bot;
  681. l = simple_sprintf(x, "n %s %s %c%D\n", bot->bot, p, bot->share, bot->ver);
  682. tputs(dcc[z].sock, x, l);
  683. }
  684. if (!(bot_flags(dcc[z].user) & BOT_ISOLATE)) {
  685. /* Dump party line members */
  686. for (i = 0; i < dcc_total; i++) {
  687. if (dcc[i].type == &DCC_CHAT) {
  688. if ((dcc[i].u.chat->channel >= 0) &&
  689. (dcc[i].u.chat->channel < GLOBAL_CHANS)) {
  690. l = simple_sprintf(x, "j !%s %s %D %c%D %s\n",
  691. conf.bot->nick, dcc[i].nick,
  692. dcc[i].u.chat->channel, geticon(i),
  693. dcc[i].sock, dcc[i].host);
  694. tputs(dcc[z].sock, x, l);
  695. l = simple_sprintf(x, "i %s %D %D %s\n", conf.bot->nick,
  696. dcc[i].sock, now - dcc[i].timeval,
  697. dcc[i].u.chat->away ? dcc[i].u.chat->away : "");
  698. tputs(dcc[z].sock, x, l);
  699. }
  700. }
  701. }
  702. for (i = 0; i < parties; i++) {
  703. l = simple_sprintf(x, "j %s %s %D %c%D %s\n",
  704. party[i].bot, party[i].nick,
  705. party[i].chan, party[i].flag,
  706. party[i].sock, party[i].from);
  707. tputs(dcc[z].sock, x, l);
  708. if ((party[i].status & PLSTAT_AWAY) || (party[i].timer != 0)) {
  709. l = simple_sprintf(x, "i %s %D %D %s\n", party[i].bot,
  710. party[i].sock, now - party[i].timer,
  711. party[i].away ? party[i].away : "");
  712. tputs(dcc[z].sock, x, l);
  713. }
  714. }
  715. }
  716. }
  717. int in_chain(char *who)
  718. {
  719. if (findbot(who))
  720. return 1;
  721. if (!egg_strcasecmp(who, conf.bot->nick))
  722. return 1;
  723. return 0;
  724. }
  725. int bots_in_subtree(tand_t *bot)
  726. {
  727. int nr = 1;
  728. tand_t *b = NULL;
  729. if (!bot)
  730. return 0;
  731. for (b = tandbot; b; b = b->next) {
  732. if (b->bot && (b->uplink == bot)) {
  733. nr += bots_in_subtree(b);
  734. }
  735. }
  736. return nr;
  737. }
  738. int users_in_subtree(tand_t *bot)
  739. {
  740. int i, nr;
  741. tand_t *b = NULL;
  742. nr = 0;
  743. if (!bot)
  744. return 0;
  745. for (i = 0; i < parties; i++)
  746. if (!egg_strcasecmp(party[i].bot, bot->bot))
  747. nr++;
  748. for (b = tandbot; b; b = b->next)
  749. if (b->bot && (b->uplink == bot))
  750. nr += users_in_subtree(b);
  751. return nr;
  752. }
  753. /* Break link with a tandembot
  754. */
  755. int botunlink(int idx, char *nick, char *reason)
  756. {
  757. register int i;
  758. int bots, users;
  759. tand_t *bot = NULL;
  760. if (nick[0] == '*')
  761. dprintf(idx, "%s\n", BOT_UNLINKALL);
  762. for (i = 0; i < dcc_total; i++) {
  763. if ((nick[0] == '*') || !egg_strcasecmp(dcc[i].nick, nick)) {
  764. if (dcc[i].type == &DCC_FORK_BOT) {
  765. if (idx >= 0)
  766. dprintf(idx, "%s: %s -> %s.\n", BOT_KILLLINKATTEMPT,
  767. dcc[i].nick, dcc[i].host);
  768. putlog(LOG_BOTS, "*", "%s: %s -> %s:%d",
  769. BOT_KILLLINKATTEMPT, dcc[i].nick,
  770. dcc[i].host, dcc[i].port);
  771. killsock(dcc[i].sock);
  772. lostdcc(i);
  773. if (nick[0] != '*')
  774. return 1;
  775. } else if (dcc[i].type == &DCC_BOT_NEW) {
  776. if (idx >= 0)
  777. dprintf(idx, "%s %s.\n", BOT_ENDLINKATTEMPT,
  778. dcc[i].nick);
  779. putlog(LOG_BOTS, "*", "%s %s @ %s:%d",
  780. "Stopped trying to link", dcc[i].nick,
  781. dcc[i].host, dcc[i].port);
  782. killsock(dcc[i].sock);
  783. lostdcc(i);
  784. if (nick[0] != '*')
  785. return 1;
  786. } else if (dcc[i].type == &DCC_BOT) {
  787. char s[1024] = "";
  788. if (idx >= 0)
  789. dprintf(idx, "%s %s.\n", BOT_BREAKLINK, dcc[i].nick);
  790. else if ((idx == -3) && (b_status(i) & STAT_SHARE) && !share_unlinks)
  791. return -1;
  792. bot = findbot(dcc[i].nick);
  793. bots = bots_in_subtree(bot);
  794. users = users_in_subtree(bot);
  795. if (reason && reason[0]) {
  796. simple_sprintf(s, "%s %s (%s) (lost %d bot%s and %d user%s)",
  797. BOT_UNLINKEDFROM, dcc[i].nick, reason, bots,
  798. (bots != 1) ? "s" : "", users, (users != 1) ?
  799. "s" : "");
  800. dprintf(i, "bye %s\n", reason);
  801. } else {
  802. simple_sprintf(s, "%s %s (lost %d bot%s and %d user%s)",
  803. BOT_UNLINKEDFROM, dcc[i].nick, bots, (bots != 1) ?
  804. "s" : "", users, (users != 1) ? "s" : "");
  805. dprintf(i, "bye No reason\n");
  806. }
  807. chatout("*** %s\n", s);
  808. botnet_send_unlinked(i, dcc[i].nick, s);
  809. killsock(dcc[i].sock);
  810. lostdcc(i);
  811. if (nick[0] != '*')
  812. return 1;
  813. }
  814. }
  815. }
  816. if (idx >= 0 && nick[0] != '*')
  817. dprintf(idx, "%s\n", BOT_NOTCONNECTED);
  818. if (nick[0] != '*') {
  819. bot = findbot(nick);
  820. if (bot) {
  821. /* The internal bot list is desynched from the dcc list
  822. sometimes. While we still search for the bug, provide
  823. an easy way to clear out those `ghost'-bots.
  824. Fabian (2000-08-02) */
  825. char *ghost = "BUG!!: Found bot `%s' in internal bot list, but it\n"
  826. " shouldn't have been there! Removing.\n"
  827. " This is a known bug we haven't fixed yet. If this\n"
  828. " bot is the newest eggdrop version available and you\n"
  829. " know a *reliable* way to reproduce the bug, please\n"
  830. " contact us - we need your help!\n";
  831. if (idx >= 0)
  832. dprintf(idx, ghost, nick);
  833. else
  834. putlog(LOG_MISC, "*", ghost, nick);
  835. rembot(bot->bot);
  836. return 1;
  837. }
  838. }
  839. if (nick[0] == '*') {
  840. dprintf(idx, "%s\n", BOT_WIPEBOTTABLE);
  841. while (tandbot)
  842. rembot(tandbot->bot);
  843. while (parties) {
  844. parties--;
  845. /* Assert? */
  846. if (party[i].chan >= 0)
  847. check_bind_chpt(party[i].bot, party[i].nick, party[i].sock,
  848. party[i].chan);
  849. }
  850. }
  851. return 0;
  852. }
  853. static void botlink_resolve_success(int);
  854. static void botlink_resolve_failure(int);
  855. /* Link to another bot
  856. */
  857. int botlink(char *linker, int idx, char *nick)
  858. {
  859. struct bot_addr *bi = NULL;
  860. struct userrec *u = NULL;
  861. register int i;
  862. u = get_user_by_handle(userlist, nick);
  863. if (!u || !(u->flags & USER_BOT)) {
  864. if (idx >= 0)
  865. dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
  866. } else if (!egg_strcasecmp(nick, conf.bot->nick)) {
  867. if (idx >= 0)
  868. dprintf(idx, "%s\n", BOT_CANTLINKMYSELF);
  869. } else if (in_chain(nick) && (idx != -3)) {
  870. if (idx >= 0)
  871. dprintf(idx, "%s\n", BOT_ALREADYLINKED);
  872. } else {
  873. for (i = 0; i < dcc_total; i++)
  874. if ((dcc[i].user == u) &&
  875. ((dcc[i].type == &DCC_FORK_BOT) ||
  876. (dcc[i].type == &DCC_BOT_NEW))) {
  877. if (idx >= 0)
  878. dprintf(idx, "%s\n", BOT_ALREADYLINKING);
  879. return 0;
  880. }
  881. /* Address to connect to is in 'info' */
  882. bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
  883. if (!bi || !strlen(bi->address) || !bi->telnet_port || (bi->telnet_port <= 0)) {
  884. if (idx >= 0) {
  885. dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
  886. dprintf(idx, "%s .chaddr %s %s\n",
  887. MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
  888. }
  889. } else if (dcc_total == max_dcc) {
  890. if (idx >= 0)
  891. dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
  892. } else {
  893. correct_handle(nick);
  894. if (idx > -2)
  895. putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
  896. bi->address, bi->telnet_port);
  897. i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
  898. dcc[i].timeval = now;
  899. dcc[i].port = bi->telnet_port;
  900. dcc[i].user = u;
  901. strcpy(dcc[i].nick, nick);
  902. strcpy(dcc[i].host, bi->address);
  903. dcc[i].u.dns->ibuf = idx;
  904. dcc[i].u.dns->cptr = calloc(1, strlen(linker) + 1);
  905. strcpy(dcc[i].u.dns->cptr, linker);
  906. dcc[i].u.dns->host = calloc(1, strlen(dcc[i].host) + 1);
  907. strcpy(dcc[i].u.dns->host, dcc[i].host);
  908. dcc[i].u.dns->dns_success = botlink_resolve_success;
  909. dcc[i].u.dns->dns_failure = botlink_resolve_failure;
  910. dcc[i].u.dns->dns_type = RES_IPBYHOST;
  911. dcc[i].u.dns->type = &DCC_FORK_BOT;
  912. #ifdef USE_IPV6
  913. botlink_resolve_success(i);
  914. #else
  915. dcc_dnsipbyhost(bi->address);
  916. #endif /* USE_IPV6 */
  917. return 1;
  918. }
  919. }
  920. return 0;
  921. }
  922. static void botlink_resolve_failure(int i)
  923. {
  924. free(dcc[i].u.dns->cptr);
  925. lostdcc(i);
  926. }
  927. static void botlink_resolve_success(int i)
  928. {
  929. int idx = dcc[i].u.dns->ibuf;
  930. char *linker = dcc[i].u.dns->cptr;
  931. dcc[i].addr = dcc[i].u.dns->ip;
  932. changeover_dcc(i, &DCC_FORK_BOT, sizeof(struct bot_info));
  933. dcc[i].timeval = now;
  934. strcpy(dcc[i].u.bot->linker, linker);
  935. strcpy(dcc[i].u.bot->version, "(primitive bot)");
  936. strcpy(dcc[i].u.bot->sysname, "*");
  937. dcc[i].u.bot->numver = idx;
  938. dcc[i].u.bot->port = dcc[i].port; /* Remember where i started */
  939. #ifdef USE_IPV6
  940. dcc[i].sock = getsock(SOCK_STRONGCONN, hostprotocol(dcc[i].host));
  941. #else
  942. dcc[i].sock = getsock(SOCK_STRONGCONN);
  943. #endif /* USE_IPV6 */
  944. free(linker);
  945. if (dcc[i].sock > 0)
  946. identd_open(); /* will be closed when an ident is replied. */
  947. if (dcc[i].sock < 0 ||
  948. #ifdef USE_IPV6
  949. open_telnet_raw(dcc[i].sock, dcc[i].host,
  950. #else
  951. open_telnet_raw(dcc[i].sock, iptostr(htonl(dcc[i].addr)),
  952. #endif /* USE_IPV6 */
  953. dcc[i].port) < 0)
  954. failed_link(i);
  955. else { /* let's attempt to initiate SSL before ANYTHING else... */
  956. #ifdef HAVE_SSL
  957. /* if (!ssl_link(dcc[i].sock, CONNECT_SSL)) {
  958. debug2("back from ssl_link(%d, %d) for botlink (failed)", dcc[i].sock, CONNECT_SSL);
  959. dcc[i].ssl = 0;
  960. putlog(LOG_BOTS, "*", "SSL link for '%s' failed", dcc[i].nick);
  961. } else */
  962. dcc[i].ssl = 1;
  963. #else
  964. dcc[i].ssl = 0;
  965. #endif /* HAVE_SSL */
  966. }
  967. }
  968. static void failed_tandem_relay(int idx)
  969. {
  970. int uidx = (-1), i;
  971. for (i = 0; i < dcc_total; i++)
  972. if ((dcc[i].type == &DCC_PRE_RELAY) &&
  973. (dcc[i].u.relay->sock == dcc[idx].sock))
  974. uidx = i;
  975. if (uidx < 0) {
  976. putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
  977. dcc[idx].sock, dcc[idx].u.relay->sock);
  978. killsock(dcc[idx].sock);
  979. lostdcc(idx);
  980. return;
  981. }
  982. if (dcc[idx].port >= dcc[idx].u.relay->port + 3) {
  983. struct chat_info *ci = dcc[uidx].u.relay->chat;
  984. dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
  985. dcc[uidx].status = dcc[uidx].u.relay->old_status;
  986. free(dcc[uidx].u.relay);
  987. dcc[uidx].u.chat = ci;
  988. dcc[uidx].type = &DCC_CHAT;
  989. killsock(dcc[idx].sock);
  990. lostdcc(idx);
  991. return;
  992. }
  993. killsock(dcc[idx].sock);
  994. #ifdef USE_IPV6
  995. dcc[idx].sock = getsock(SOCK_STRONGCONN, hostprotocol(dcc[idx].host));
  996. #else
  997. dcc[idx].sock = getsock(SOCK_STRONGCONN);
  998. #endif /* USE_IPV6 */
  999. dcc[uidx].u.relay->sock = dcc[idx].sock;
  1000. dcc[idx].port++;
  1001. dcc[idx].timeval = now;
  1002. if (dcc[idx].sock < 0 ||
  1003. #ifdef USE_IPV6
  1004. open_telnet_raw(dcc[idx].sock, dcc[idx].host,
  1005. #else
  1006. open_telnet_raw(dcc[idx].sock, dcc[idx].addr ?
  1007. iptostr(htonl(dcc[idx].addr)) :
  1008. dcc[idx].host,
  1009. #endif /* USE_IPV6 */
  1010. dcc[idx].port) < 0)
  1011. failed_tandem_relay(idx);
  1012. }
  1013. static void tandem_relay_resolve_failure(int);
  1014. static void tandem_relay_resolve_success(int);
  1015. /* Relay to another tandembot
  1016. */
  1017. void tandem_relay(int idx, char *nick, register int i)
  1018. {
  1019. struct userrec *u = NULL;
  1020. struct bot_addr *bi = NULL;
  1021. struct chat_info *ci = NULL;
  1022. u = get_user_by_handle(userlist, nick);
  1023. if (!u || !(u->flags & USER_BOT)) {
  1024. dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
  1025. return;
  1026. }
  1027. if (!egg_strcasecmp(nick, conf.bot->nick)) {
  1028. dprintf(idx, "%s\n", BOT_CANTRELAYMYSELF);
  1029. return;
  1030. }
  1031. /* Address to connect to is in 'info' */
  1032. bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
  1033. if (!bi || !strlen(bi->address) || !bi->relay_port || (bi->relay_port <= 0)) {
  1034. dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
  1035. dprintf(idx, "%s .chaddr %s %s\n",
  1036. MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
  1037. return;
  1038. }
  1039. i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
  1040. if (i < 0) {
  1041. dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
  1042. return;
  1043. }
  1044. #ifdef USE_IPV6
  1045. dcc[i].sock = getsock(SOCK_STRONGCONN | SOCK_VIRTUAL, hostprotocol(bi->address));
  1046. #else
  1047. dcc[i].sock = getsock(SOCK_STRONGCONN | SOCK_VIRTUAL);
  1048. #endif /* USE_IPV6 */
  1049. if (dcc[i].sock < 0) {
  1050. lostdcc(i);
  1051. dprintf(idx, "%s\n", MISC_NOFREESOCK);
  1052. return;
  1053. }
  1054. dcc[i].port = bi->relay_port;
  1055. dcc[i].addr = 0L;
  1056. strcpy(dcc[i].nick, nick);
  1057. dcc[i].user = u;
  1058. strcpy(dcc[i].host, bi->address);
  1059. #ifdef HUB
  1060. dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick, bi->address, bi->relay_port);
  1061. #endif /* HUB */
  1062. dprintf(idx, "%s\n", BOT_BYEINFO1);
  1063. dcc[idx].type = &DCC_PRE_RELAY;
  1064. ci = dcc[idx].u.chat;
  1065. dcc[idx].u.relay = calloc(1, sizeof(struct relay_info));
  1066. dcc[idx].u.relay->chat = ci;
  1067. dcc[idx].u.relay->old_status = dcc[idx].status;
  1068. dcc[idx].u.relay->sock = dcc[i].sock;
  1069. dcc[i].timeval = now;
  1070. dcc[i].u.dns->ibuf = dcc[idx].sock;
  1071. dcc[i].u.dns->host = calloc(1, strlen(bi->address) + 1);
  1072. strcpy(dcc[i].u.dns->host, bi->address);
  1073. dcc[i].u.dns->dns_success = tandem_relay_resolve_success;
  1074. dcc[i].u.dns->dns_failure = tandem_relay_resolve_failure;
  1075. dcc[i].u.dns->dns_type = RES_IPBYHOST;
  1076. dcc[i].u.dns->type = &DCC_FORK_RELAY;
  1077. #ifdef USE_IPV6
  1078. tandem_relay_resolve_success(i);
  1079. #else
  1080. dcc_dnsipbyhost(bi->address);
  1081. #endif /* USE_IPV6 */
  1082. }
  1083. static void tandem_relay_resolve_failure(int idx)
  1084. {
  1085. struct chat_info *ci = NULL;
  1086. register int uidx = (-1), i;
  1087. for (i = 0; i < dcc_total; i++)
  1088. if ((dcc[i].type == &DCC_PRE_RELAY) &&
  1089. (dcc[i].u.relay->sock == dcc[idx].sock)) {
  1090. uidx = i;
  1091. break;
  1092. }
  1093. if (uidx < 0) {
  1094. putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
  1095. dcc[idx].sock, dcc[idx].u.relay->sock);
  1096. killsock(dcc[idx].sock);
  1097. lostdcc(idx);
  1098. return;
  1099. }
  1100. ci = dcc[uidx].u.relay->chat;
  1101. dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
  1102. dcc[uidx].status = dcc[uidx].u.relay->old_status;
  1103. free(dcc[uidx].u.relay);
  1104. dcc[uidx].u.chat = ci;
  1105. dcc[uidx].type = &DCC_CHAT;
  1106. killsock(dcc[idx].sock);
  1107. lostdcc(idx);
  1108. }
  1109. static void tandem_relay_resolve_success(int i)
  1110. {
  1111. int sock = dcc[i].u.dns->ibuf;
  1112. dcc[i].addr = dcc[i].u.dns->ip;
  1113. changeover_dcc(i, &DCC_FORK_RELAY, sizeof(struct relay_info));
  1114. dcc[i].u.relay->chat = calloc(1, sizeof(struct chat_info));
  1115. dcc[i].u.relay->sock = sock;
  1116. dcc[i].u.relay->port = dcc[i].port;
  1117. dcc[i].u.relay->chat->away = NULL;
  1118. dcc[i].u.relay->chat->msgs_per_sec = 0;
  1119. dcc[i].u.relay->chat->con_flags = 0;
  1120. dcc[i].u.relay->chat->buffer = NULL;
  1121. dcc[i].u.relay->chat->max_line = 0;
  1122. dcc[i].u.relay->chat->line_count = 0;
  1123. dcc[i].u.relay->chat->current_lines = 0;
  1124. dcc[i].timeval = now;
  1125. #ifdef USE_IPV6
  1126. if (open_telnet_raw(dcc[i].sock, dcc[i].host,
  1127. #else
  1128. if (open_telnet_raw(dcc[i].sock, iptostr(htonl(dcc[i].addr)),
  1129. #endif /* USE_IPV6 */
  1130. dcc[i].port) < 0)
  1131. failed_tandem_relay(i);
  1132. }
  1133. /* Input from user before connect is ready
  1134. */
  1135. static void pre_relay(int idx, char *buf, register int i)
  1136. {
  1137. register int tidx = (-1);
  1138. for (i = 0; i < dcc_total; i++)
  1139. if ((dcc[i].type == &DCC_FORK_RELAY) &&
  1140. (dcc[i].u.relay->sock == dcc[idx].sock)) {
  1141. tidx = i;
  1142. break;
  1143. }
  1144. if (tidx < 0) {
  1145. /* Now try to find it among the DNSWAIT sockets instead. */
  1146. for (i = 0; i < dcc_total; i++)
  1147. if ((dcc[i].type == &DCC_DNSWAIT) &&
  1148. (dcc[i].sock == dcc[idx].u.relay->sock)) {
  1149. tidx = i;
  1150. break;
  1151. }
  1152. }
  1153. if (tidx < 0) {
  1154. putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
  1155. dcc[idx].sock, dcc[idx].u.relay->sock);
  1156. killsock(dcc[idx].sock);
  1157. lostdcc(idx);
  1158. return;
  1159. }
  1160. if (!egg_strcasecmp(buf, "*bye*")) {
  1161. /* Disconnect */
  1162. struct chat_info *ci = dcc[idx].u.relay->chat;
  1163. dprintf(idx, "%s %s.\n", BOT_ABORTRELAY1, dcc[tidx].nick);
  1164. dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, conf.bot->nick);
  1165. putlog(LOG_MISC, "*", "%s %s -> %s", BOT_ABORTRELAY3, dcc[idx].nick,
  1166. dcc[tidx].nick);
  1167. dcc[idx].status = dcc[idx].u.relay->old_status;
  1168. free(dcc[idx].u.relay);
  1169. dcc[idx].u.chat = ci;
  1170. dcc[idx].type = &DCC_CHAT;
  1171. killsock(dcc[tidx].sock);
  1172. lostdcc(tidx);
  1173. return;
  1174. }
  1175. }
  1176. /* User disconnected before her relay had finished connecting
  1177. */
  1178. static void failed_pre_relay(int idx)
  1179. {
  1180. register int tidx = (-1), i;
  1181. for (i = 0; i < dcc_total; i++)
  1182. if ((dcc[i].type == &DCC_FORK_RELAY) &&
  1183. (dcc[i].u.relay->sock == dcc[idx].sock)) {
  1184. tidx = i;
  1185. break;
  1186. }
  1187. if (tidx < 0) {
  1188. /* Now try to find it among the DNSWAIT sockets instead. */
  1189. for (i = 0; i < dcc_total; i++)
  1190. if ((dcc[i].type == &DCC_DNSWAIT) &&
  1191. (dcc[i].sock == dcc[idx].u.relay->sock)) {
  1192. tidx = i;
  1193. break;
  1194. }
  1195. }
  1196. if (tidx < 0) {
  1197. putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
  1198. dcc[idx].sock, dcc[idx].u.relay->sock);
  1199. killsock(dcc[idx].sock);
  1200. lostdcc(idx);
  1201. return;
  1202. }
  1203. putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
  1204. dcc[idx].host, dcc[idx].port);
  1205. putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPINGRELAY, dcc[tidx].nick);
  1206. if ((dcc[tidx].sock != STDOUT) || backgrd) {
  1207. if (idx > tidx) {
  1208. int t = tidx;
  1209. tidx = idx;
  1210. idx = t;
  1211. }
  1212. killsock(dcc[tidx].sock);
  1213. lostdcc(tidx);
  1214. } else {
  1215. fatal("Lost my terminal?!", 0);
  1216. }
  1217. killsock(dcc[idx].sock);
  1218. lostdcc(idx);
  1219. }
  1220. static void cont_tandem_relay(int idx, char *buf, register int i)
  1221. {
  1222. register int uidx = (-1);
  1223. struct relay_info *ri = NULL;
  1224. for (i = 0; i < dcc_total; i++)
  1225. if ((dcc[i].type == &DCC_PRE_RELAY) &&
  1226. (dcc[i].u.relay->sock == dcc[idx].sock))
  1227. uidx = i;
  1228. if (uidx < 0) {
  1229. putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
  1230. dcc[i].sock, dcc[i].u.relay->sock);
  1231. killsock(dcc[i].sock);
  1232. lostdcc(i);
  1233. return;
  1234. }
  1235. dcc[idx].type = &DCC_RELAY;
  1236. dcc[idx].u.relay->sock = dcc[uidx].sock;
  1237. dcc[uidx].u.relay->sock = dcc[idx].sock;
  1238. dprintf(uidx, "%s %s ...\n", BOT_RELAYSUCCESS, dcc[idx].nick);
  1239. dprintf(uidx, "%s\n\n", BOT_BYEINFO2);
  1240. putlog(LOG_MISC, "*", "%s %s -> %s", BOT_RELAYLINK,
  1241. dcc[uidx].nick, dcc[idx].nick);
  1242. ri = dcc[uidx].u.relay; /* YEAH */
  1243. dcc[uidx].type = &DCC_CHAT;
  1244. dcc[uidx].u.chat = ri->chat;
  1245. if (dcc[uidx].u.chat->channel >= 0) {
  1246. chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n",
  1247. dcc[uidx].nick, BOT_PARTYLEFT);
  1248. if (dcc[uidx].u.chat->channel < GLOBAL_CHANS)
  1249. botnet_send_part_idx(uidx, NULL);
  1250. check_bind_chpt(conf.bot->nick, dcc[uidx].nick, dcc[uidx].sock,
  1251. dcc[uidx].u.chat->channel);
  1252. }
  1253. check_bind_chof(dcc[uidx].nick, uidx);
  1254. dcc[uidx].type = &DCC_RELAYING;
  1255. dcc[uidx].u.relay = ri;
  1256. }
  1257. static void eof_dcc_relay(int idx)
  1258. {
  1259. register int j;
  1260. struct chat_info *ci = NULL;
  1261. for (j = 0; j < dcc_total; j++)
  1262. if (dcc[j].sock == dcc[idx].u.relay->sock)
  1263. break;
  1264. if (j == dcc_total) {
  1265. killsock(dcc[idx].sock);
  1266. lostdcc(idx);
  1267. return;
  1268. }
  1269. dcc[j].status = dcc[j].u.relay->old_status;
  1270. /* In case echo was off, turn it back on (send IAC WON'T ECHO): */
  1271. if (dcc[j].status & STAT_TELNET)
  1272. dprintf(j, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
  1273. putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_ENDRELAY1, dcc[j].nick,
  1274. dcc[idx].nick);
  1275. dprintf(j, "\n\n*** %s %s\n", BOT_ENDRELAY2, conf.bot->nick);
  1276. ci = dcc[j].u.relay->chat;
  1277. free(dcc[j].u.relay);
  1278. dcc[j].u.chat = ci;
  1279. dcc[j].type = &DCC_CHAT;
  1280. if (dcc[j].u.chat->channel >= 0) {
  1281. chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n",
  1282. dcc[j].nick, BOT_PARTYREJOINED);
  1283. if (dcc[j].u.chat->channel < GLOBAL_CHANS)
  1284. botnet_send_join_idx(j, -1);
  1285. }
  1286. check_bind_chon(dcc[j].nick, j);
  1287. check_bind_chjn(conf.bot->nick, dcc[j].nick, dcc[j].u.chat->channel,
  1288. geticon(j), dcc[j].sock, dcc[j].host);
  1289. killsock(dcc[idx].sock);
  1290. lostdcc(idx);
  1291. }
  1292. static void eof_dcc_relaying(int idx)
  1293. {
  1294. register int j, x = dcc[idx].u.relay->sock;
  1295. putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
  1296. dcc[idx].host, dcc[idx].port);
  1297. killsock(dcc[idx].sock);
  1298. lostdcc(idx);
  1299. for (j = 0; (dcc[j].sock != x) || (dcc[j].type == &DCC_FORK_RELAY); j++);
  1300. putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPEDRELAY, dcc[j].nick);
  1301. killsock(dcc[j].sock);
  1302. lostdcc(j); /* Drop connection to the bot */
  1303. }
  1304. static void dcc_relay(int idx, char *buf, int j)
  1305. {
  1306. unsigned char *p = (unsigned char *) buf;
  1307. int mark;
  1308. for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock ||
  1309. dcc[j].type != &DCC_RELAYING; j++);
  1310. /* If redirecting to a non-telnet user, swallow telnet codes and
  1311. escape sequences. */
  1312. if (!(dcc[j].status & STAT_TELNET)) {
  1313. while (*p != 0) {
  1314. while (*p != 255 && (*p != '\033' || *(p + 1) != '[') && *p != '\r' && *p)
  1315. p++; /* Search for IAC, escape sequences and CR. */
  1316. if (*p == 255) {
  1317. mark = 2;
  1318. if (!*(p + 1))
  1319. mark = 1; /* Bogus */
  1320. if ((*(p + 1) >= 251) || (*(p + 1) <= 254)) {
  1321. mark = 3;
  1322. if (!*(p + 2))
  1323. mark = 2; /* Bogus */
  1324. }
  1325. strcpy((char *) p, (char *) (p + mark));
  1326. } else if (*p == '\033') {
  1327. unsigned char *e;
  1328. /* Search for the end of the escape sequence. */
  1329. for (e = p + 2; *e != 'm' && *e; e++)
  1330. ;
  1331. strcpy((char *) p, (char *) (e + 1));
  1332. } else if (*p == '\r')
  1333. strcpy((char *) p, (char *) (p + 1));
  1334. }
  1335. if (!buf[0])
  1336. dprintf(-dcc[idx].u.relay->sock, " \n");
  1337. else
  1338. dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
  1339. return;
  1340. }
  1341. /* Telnet user */
  1342. if (!buf[0])
  1343. dprintf(-dcc[idx].u.relay->sock, " \r\n");
  1344. else
  1345. dprintf(-dcc[idx].u.relay->sock, "%s\r\n", buf);
  1346. }
  1347. static void dcc_relaying(int idx, char *buf, int j)
  1348. {
  1349. struct chat_info *ci = NULL;
  1350. if (egg_strcasecmp(buf, "*bye*")) {
  1351. dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
  1352. return;
  1353. }
  1354. for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
  1355. (dcc[j].type != &DCC_RELAY); j++);
  1356. dcc[idx].status = dcc[idx].u.relay->old_status;
  1357. /* In case echo was off, turn it back on (send IAC WON'T ECHO): */
  1358. if (dcc[idx].status & STAT_TELNET)
  1359. dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
  1360. dprintf(idx, "\n(%s %s.)\n", BOT_BREAKRELAY, dcc[j].nick);
  1361. dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, conf.bot->nick);
  1362. putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_RELAYBROKEN,
  1363. dcc[idx].nick, dcc[j].nick);
  1364. if (dcc[idx].u.relay->chat->channel >= 0) {
  1365. chanout_but(-1, dcc[idx].u.relay->chat->channel,
  1366. "*** %s joined the party line.\n", dcc[idx].nick);
  1367. if (dcc[idx].u.relay->chat->channel < GLOBAL_CHANS)
  1368. botnet_send_join_idx(idx, -1);
  1369. }
  1370. ci = dcc[idx].u.relay->chat;
  1371. free(dcc[idx].u.relay);
  1372. dcc[idx].u.chat = ci;
  1373. dcc[idx].type = &DCC_CHAT;
  1374. check_bind_chon(dcc[idx].nick, idx);
  1375. if (dcc[idx].u.chat->channel >= 0)
  1376. check_bind_chjn(conf.bot->nick, dcc[idx].nick, dcc[idx].u.chat->channel,
  1377. geticon(idx), dcc[idx].sock, dcc[idx].host);
  1378. killsock(dcc[j].sock);
  1379. lostdcc(j);
  1380. }
  1381. static void display_relay(int i, char *other)
  1382. {
  1383. sprintf(other, "rela -> sock %d", dcc[i].u.relay->sock);
  1384. }
  1385. static void display_relaying(int i, char *other)
  1386. {
  1387. sprintf(other, ">rly -> sock %d", dcc[i].u.relay->sock);
  1388. }
  1389. static void display_tandem_relay(int i, char *other)
  1390. {
  1391. strcpy(other, "other rela");
  1392. }
  1393. static void display_pre_relay(int i, char *other)
  1394. {
  1395. strcpy(other, "other >rly");
  1396. }
  1397. static void kill_relay(int idx, void *x)
  1398. {
  1399. register struct relay_info *p = (struct relay_info *) x;
  1400. if (p->chat)
  1401. DCC_CHAT.kill(idx, p->chat);
  1402. free(p);
  1403. }
  1404. struct dcc_table DCC_RELAY =
  1405. {
  1406. "RELAY",
  1407. 0, /* Flags */
  1408. eof_dcc_relay,
  1409. dcc_relay,
  1410. NULL,
  1411. NULL,
  1412. display_relay,
  1413. kill_relay,
  1414. NULL
  1415. };
  1416. static void out_relay(int idx, char *buf, void *x)
  1417. {
  1418. register struct relay_info *p = (struct relay_info *) x;
  1419. if (p && p->chat)
  1420. DCC_CHAT.output(idx, buf, p->chat);
  1421. else
  1422. tputs(dcc[idx].sock, buf, strlen(buf));
  1423. }
  1424. struct dcc_table DCC_RELAYING =
  1425. {
  1426. "RELAYING",
  1427. 0, /* Flags */
  1428. eof_dcc_relaying,
  1429. dcc_relaying,
  1430. NULL,
  1431. NULL,
  1432. display_relaying,
  1433. kill_relay,
  1434. out_relay
  1435. };
  1436. struct dcc_table DCC_FORK_RELAY =
  1437. {
  1438. "FORK_RELAY",
  1439. 0, /* Flags */
  1440. failed_tandem_relay,
  1441. cont_tandem_relay,
  1442. &connect_timeout,
  1443. failed_tandem_relay,
  1444. display_tandem_relay,
  1445. kill_relay,
  1446. NULL
  1447. };
  1448. struct dcc_table DCC_PRE_RELAY =
  1449. {
  1450. "PRE_RELAY",
  1451. 0, /* Flags */
  1452. failed_pre_relay,
  1453. pre_relay,
  1454. NULL,
  1455. NULL,
  1456. display_pre_relay,
  1457. kill_relay,
  1458. NULL
  1459. };
  1460. /* Once a minute, send 'ping' to each bot -- no exceptions
  1461. */
  1462. void check_botnet_pings()
  1463. {
  1464. int i;
  1465. int bots, users;
  1466. tand_t *bot = NULL;
  1467. for (i = 0; i < dcc_total; i++) {
  1468. if (dcc[i].type == &DCC_BOT)
  1469. if (dcc[i].status & STAT_PINGED) {
  1470. char s[1024] = "";
  1471. putlog(LOG_BOTS, "*", "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
  1472. bot = findbot(dcc[i].nick);
  1473. bots = bots_in_subtree(bot);
  1474. users = users_in_subtree(bot);
  1475. simple_sprintf(s, "%s: %s (lost %d bot%s and %d user%s)", BOT_PINGTIMEOUT,
  1476. dcc[i].nick, bots, (bots != 1) ? "s" : "",
  1477. users, (users != 1) ? "s" : "");
  1478. chatout("*** %s\n", s);
  1479. botnet_send_unlinked(i, dcc[i].nick, s);
  1480. killsock(dcc[i].sock);
  1481. lostdcc(i);
  1482. }
  1483. }
  1484. for (i = 0; i < dcc_total; i++) {
  1485. if (dcc[i].type == &DCC_BOT) {
  1486. botnet_send_ping(i);
  1487. dcc[i].status |= STAT_PINGED;
  1488. }
  1489. }
  1490. for (i = 0; i < dcc_total; i++) {
  1491. if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) {
  1492. tand_t *bot, *via = findbot(dcc[i].nick);
  1493. for (bot = tandbot; bot; bot = bot->next) {
  1494. if ((via == bot->via) && (bot != via)) {
  1495. /* Not leaflike behavior */
  1496. if (dcc[i].status & STAT_WARNED) {
  1497. char s[1024] = "";
  1498. putlog(LOG_BOTS, "*", "%s %s (%s).", BOT_DISCONNECTED,
  1499. dcc[i].nick, BOT_BOTNOTLEAFLIKE);
  1500. dprintf(i, "bye %s\n", BOT_BOTNOTLEAFLIKE);
  1501. bot = findbot(dcc[i].nick);
  1502. bots = bots_in_subtree(bot);
  1503. users = users_in_subtree(bot);
  1504. simple_sprintf(s, "%s %s (%s) (lost %d bot%s and %d user%s)",
  1505. BOT_DISCONNECTED, dcc[i].nick, BOT_BOTNOTLEAFLIKE,
  1506. bots, (bots != 1) ? "s" : "", users, (users != 1) ?
  1507. "s" : "");
  1508. chatout("*** %s\n", s);
  1509. botnet_send_unlinked(i, dcc[i].nick, s);
  1510. killsock(dcc[i].sock);
  1511. lostdcc(i);
  1512. } else {
  1513. putlog(LOG_MISC, "*", "I am lame, and am now rejecting %s", bot->bot);
  1514. botnet_send_reject(i, conf.bot->nick, NULL, bot->bot,
  1515. NULL, NULL);
  1516. dcc[i].status |= STAT_WARNED;
  1517. }
  1518. } else
  1519. dcc[i].status &= ~STAT_WARNED;
  1520. }
  1521. }
  1522. }
  1523. #ifdef HUB
  1524. #ifdef S_AUTOLOCK
  1525. check_should_lock();
  1526. #endif /* S_AUTOLOCK */
  1527. #ifdef G_BACKUP
  1528. check_should_backup();
  1529. #endif /* G_BACKUP */
  1530. #endif /* HUB */
  1531. }
  1532. void zapfbot(int idx)
  1533. {
  1534. char s[1024] = "";
  1535. int bots, users;
  1536. tand_t *bot = NULL;
  1537. bot = findbot(dcc[idx].nick);
  1538. bots = bots_in_subtree(bot);
  1539. users = users_in_subtree(bot);
  1540. simple_sprintf(s, "%s: %s (lost %d bot%s and %d user%s)", BOT_BOTDROPPED,
  1541. dcc[idx].nick, bots, (bots != 1) ? "s" : "", users,
  1542. (users != 1) ? "s" : "");
  1543. chatout("*** %s\n", s);
  1544. botnet_send_unlinked(idx, dcc[idx].nick, s);
  1545. killsock(dcc[idx].sock);
  1546. lostdcc(idx);
  1547. }
  1548. void restart_chons()
  1549. {
  1550. int i;
  1551. /* Dump party line members */
  1552. for (i = 0; i < dcc_total; i++) {
  1553. if (dcc[i].type == &DCC_CHAT) {
  1554. check_bind_chon(dcc[i].nick, i);
  1555. check_bind_chjn(conf.bot->nick, dcc[i].nick, dcc[i].u.chat->channel,
  1556. geticon(i), dcc[i].sock, dcc[i].host);
  1557. }
  1558. }
  1559. for (i = 0; i < parties; i++) {
  1560. check_bind_chjn(party[i].bot, party[i].nick, party[i].chan,
  1561. party[i].flag, party[i].sock, party[i].from);
  1562. }
  1563. }
  1564. static int get_role(char *bot)
  1565. {
  1566. int rl, i;
  1567. struct bot_addr *ba = NULL;
  1568. int r[5] = { 0, 0, 0, 0, 0 };
  1569. struct userrec *u = NULL, *u2 = NULL;
  1570. if (!(u2 = get_user_by_handle(userlist, bot)))
  1571. return 1;
  1572. for (u = userlist; u; u = u->next) {
  1573. if (u->flags & USER_BOT) {
  1574. if (strcmp(u->handle, bot)) {
  1575. ba = get_user(&USERENTRY_BOTADDR, u);
  1576. if ((nextbot(u->handle) >= 0) && (ba) && (ba->roleid > 0) && (ba->roleid < 5))
  1577. r[(ba->roleid - 1)]++;
  1578. }
  1579. }
  1580. }
  1581. rl = 0;
  1582. for (i = 1; i <= 4; i++)
  1583. if (r[i] < r[rl])
  1584. rl = i;
  1585. rl++;
  1586. ba = get_user(&USERENTRY_BOTADDR, u2);
  1587. if (ba)
  1588. ba->roleid = rl;
  1589. return rl;
  1590. }
  1591. void lower_bot_linked(int idx)
  1592. {
  1593. char tmp[6] = "";
  1594. egg_snprintf(tmp, sizeof tmp, "rl %d", get_role(dcc[idx].nick));
  1595. putbot(dcc[idx].nick, tmp);
  1596. }