botnet.c 46 KB

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