/* botnet.c -- handles: keeping track of which bot's connected where in the chain dumping a list of bots or a bot tree to a user channel name associations on the party line rejecting a bot linking, unlinking, and relaying to another bot pinging the bots periodically and checking leaf status dprintf'ized, 28nov95 */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include "eggdrop.h" #include "tandem.h" #include "proto.h" /* share user file with tandem bots? */ int share_users=0; /* the ever-confusing passive flag */ int passive=1; /* set to isolate this bot's chat line */ int isolate=0; /* keep track of tandem bots on the botnet */ tand_t *tandbot; /* maximum space for tandem bots currently */ int maxtands=50; /* keep track of people on the botnet */ party_t *party; /* maximum space for party line members currently */ int maxparty=50; /* number of bots on the botnet */ int tands=0; /* number of people on the botnet */ int parties=0; /* channel name-number associations */ assoc_t *assoc=NULL; extern char origbotname[]; extern int serv; extern int dcc_total; extern struct dcc_t dcc[]; extern char botname[]; extern char cx_file[]; extern int cx_line; int expmem_botnet() { assoc_t *a=assoc; int size=0; while (a!=NULL) { size+=sizeof(assoc_t); a=a->next; } size+=(maxtands*sizeof(tand_t)); size+=(maxparty*sizeof(party_t)); return size; } void init_bots() { /* grab space for 50 bots for now -- expand later as needed */ maxtands=50; tandbot=(tand_t *)nmalloc(maxtands*sizeof(tand_t)); maxparty=50; party=(party_t *)nmalloc(maxparty*sizeof(party_t)); } /* add a tandem bot to our chain list */ void addbot(who,from) char *who,*from; { context; if (tands==maxtands) { /* expand tandem bot space */ maxtands+=50; tandbot=(tand_t *)nrealloc((void *)tandbot,maxtands*sizeof(tand_t)); } strcpy(tandbot[tands].bot,who); strcpy(tandbot[tands].via,from); if (strcasecmp(who,from)==0) strcpy(tandbot[tands].next,origbotname); else tandbot[tands].next[0]=0; tands++; } /* get icon symbol for a user (depending on access level) */ /* (*)owner (+)master (@)op (-)other */ char geticon(idx) int idx; { int atr=get_attr_handle(dcc[idx].nick); if (atr&USER_OWNER) return '*'; if (atr&USER_MASTER) return '+'; if (atr&USER_OP) return '@'; return '-'; } /* new botnet member */ void addparty(bot,nick,chan,flag,from) char *bot,*nick; int chan; char flag,*from; { int i; context; for (i=0; i0) { s=get_assoc_name(chan); if (s==NULL) dprintf(idx,"Users on channel %d:\n",chan); else dprintf(idx,"Users on channel '%s' (%d):\n",s,chan); } dprintf(idx,"%-10s %-9s Host\n","Nick","Bot"); dprintf(idx,"---------- --------- ------------------------------\n"); for (i=0; i=0) && (dcc[i].u.chat->channel==chan))) { c=geticon(i); if (c=='-') c=' '; if (now-dcc[i].u.chat->timer > 300) { unsigned long days,hrs,mins; days=(now-dcc[i].u.chat->timer)/86400; hrs=((now-dcc[i].u.chat->timer) - (days*86400))/3600; mins=((now-dcc[i].u.chat->timer) - (hrs*3600))/60; if (days>0) sprintf(idle," [idle %lud%luh]",days,hrs); else if (hrs>0) sprintf(idle," [idle %luh%lum]",hrs,mins); else sprintf(idle," [idle %lum]",mins); } else idle[0]=0; dprintf(idx,"%c%-9s %c %-9s %s%s\n",c,dcc[i].nick, (dcc[i].u.chat->channel==0)&&(chan==(-1))?'+':' ', origbotname,dcc[i].host,idle); if (dcc[i].u.chat->away!=NULL) dprintf(idx," AWAY: %s\n",dcc[i].u.chat->away); } } if (isolate) dprintf(idx,"(This bot is isolated from the botnet.)\n"); else { for (i=0; i=0) && (party[i].chan==chan))) { c=party[i].flag; if (c=='-') c=' '; if (party[i].timer == 0L) strcpy(idle," [idle?]"); else if (now-party[i].timer > 300) { unsigned long days,hrs,mins; days=(now-party[i].timer)/86400; hrs=((now-party[i].timer) - (days*86400))/3600; mins=((now-party[i].timer) - (hrs*3600))/60; if (days>0) sprintf(idle," [idle %lud%luh]",days,hrs); else if (hrs>0) sprintf(idle," [idle %luh%lum]",hrs,mins); else sprintf(idle," [idle %lum]",mins); } else idle[0]=0; dprintf(idx,"%c%-9s %c %-9s %s%s\n",c,party[i].nick, (party[i].chan==0)&&(chan==(-1))?'+':' ',party[i].bot, party[i].from,idle); if (party[i].status&PLSTAT_AWAY) dprintf(idx," AWAY: %s\n",party[i].away); } } } } /* remove every bot linked 'via' bot */ void unvia(idx,who) int idx; char *who; { int i; context; rempartybot(who); for (i=0; i */ int nextbot(who) char *who; { int i,j; for (i=0; i500) { s[strlen(s)-2]=0; dprintf(idx,"Bots: %s\n",s); s[0]=0; } } if (s[0]) { s[strlen(s)-2]=0; dprintf(idx,"Bots: %s\n",s); } dprintf(idx,"(total: %d)\n",tands+1); } int get_tands() { return tands; } char *get_tandbot(i) int i; { return tandbot[i].bot; } /* show a simpleton bot tree */ void tell_bottree(idx) int idx; { int i; char s[161],last[20][10],this[10]; int lev=0,more,mark[20],ok,cnt; int tothops=0; context; strcpy(this,origbotname); more=1; if (tands==0) { dprintf(idx,"No bots linked.\n"); return; } s[0]=0; for (i=0; i1) dprintf(idx," |--"); else dprintf(idx," `--"); s[0]=0; i=0; while (!s[0]) { if (strcasecmp(tandbot[i].next,this)==0) strcpy(s,tandbot[i].bot); else i++; } dprintf(idx,"%s\n",s); if (cnt>1) mark[lev]=1; else mark[lev]=0; strcpy(last[lev],this); strcpy(this,s); lev++; more=1; } else { while (cnt==0) { /* no subtrees from here */ if (lev==0) { dprintf(idx,"(( tree error ))\n"); return; } ok=0; for (i=0; i1) dprintf(idx," |--%s\n",this); else dprintf(idx," `--%s\n",this); if (cnt>1) mark[lev-1]=1; else mark[lev-1]=0; } else { /* this was the last child */ lev--; if (lev==0) { more=0; cnt=999; } else { more=1; strcpy(this,last[lev]); } } } } } /* hop information: (9d) */ dprintf(idx,"Average hops: %3.1f, total bots: %d\n", ((float)tothops)/((float)tands),tands+1); } void kill_assoc(chan) int chan; { assoc_t *a=assoc,*last=NULL; while (a!=NULL) { if (a->channel==chan) { if (last!=NULL) last->next=a->next; else assoc=a->next; nfree(a); a=NULL; } else { last=a; a=a->next; } } } void kill_all_assoc() { assoc_t *a=assoc,*x; while (a!=NULL) { x=a; a=a->next; nfree(x); } assoc=NULL; } /* add a channel association */ void add_assoc(name,chan) char *name; int chan; { assoc_t *a=assoc,*b,*old=NULL; while (a!=NULL) { if ((name[0]!=0) && (strcasecmp(a->name,name)==0)) { kill_assoc(a->channel); add_assoc(name,chan); return; } if (a->channel==chan) { strncpy(a->name,name,20); a->name[20]=0; return; } a=a->next; } /* add in numerical order */ a=assoc; while (a!=NULL) { if (a->channel > chan) { b=(assoc_t *)nmalloc(sizeof(assoc_t)); b->next=a; b->channel=chan; strncpy(b->name,name,20); b->name[20]=0; if (old==NULL) assoc=b; else old->next=b; return; } old=a; a=a->next; } /* add at the end */ b=(assoc_t *)nmalloc(sizeof(assoc_t)); b->next=NULL; b->channel=chan; strncpy(b->name,name,20); b->name[20]=0; if (old==NULL) assoc=b; else old->next=b; } int get_assoc(name) char *name; { assoc_t *a=assoc; while (a!=NULL) { if (strcasecmp(a->name,name)==0) return a->channel; a=a->next; } return -1; } char *get_assoc_name(chan) int chan; { assoc_t *a=assoc; while (a!=NULL) { if (a->channel==chan) return a->name; a=a->next; } return NULL; } /* no. don't do this any more. */ void dump_assoc(idx) int idx; { assoc_t *a=assoc; if (a==NULL) { dprintf(idx,"No channel names.\n"); return; } dprintf(idx,"Chan Name\n"); while (a!=NULL) { if (a->name[0]) dprintf(idx,"%5d %s\n",a->channel,a->name); a=a->next; } return; } /* dump list of links to a new bot */ void dump_links(z) int z; { int i; /* assoc_t *a=assoc; */ for (i=0; ichannel,geticon(i),dcc[i].host); if (dcc[i].u.chat->away!=NULL) tprintf(z,"away %s %s %s\n",origbotname,dcc[i].nick, dcc[i].u.chat->away); tprintf(z,"idle %s %s %lu\n",origbotname,dcc[i].nick, time(NULL)-dcc[i].u.chat->timer); } } for (i=0; iname[0]) tprintf(z,"assoc %d %s\n",a->channel,a->name); a=a->next; } */ } int in_chain(who) char *who; { int i; for (i=0; istatus&STAT_SHARE) { if (dcc[idx].u.bot->status&STAT_GETTING) { j=0; for (i=0; itype==DCC_SEND)))) j=i; if (j!=0) { killsock(dcc[j].sock); dcc[j].sock=dcc[j].type; dcc[j].type=DCC_LOST; unlink(dcc[j].u.xfer->filename); } putlog(LOG_BOTS,"*","(Userlist download aborted.)"); } if (dcc[idx].u.bot->status&STAT_SENDING) { j=0; for (i=0; ifilename); } putlog(LOG_BOTS,"*","(Userlist transmit aborted.)"); } if ((!(dcc[idx].u.bot->status&STAT_GETTING)) && (!(dcc[idx].u.bot->status&STAT_SENDING))) new_tbuf(dcc[idx].nick); } context; } void reject_bot(who) char *who; { int i; i=nextbot(who); if (i<0) return; if (strcasecmp(dcc[i].nick,who)==0) { /* we're directly connected to the offending bot?! (shudder!) */ putlog(LOG_BOTS,"*","Rejecting bot %s",dcc[i].nick); chatout("*** Rejected bot %s\n",dcc[i].nick); tandout_but(i,"chat %s Rejected bot %s\n",origbotname,dcc[i].nick); tandout_but(i,"unlinked %s\n",dcc[i].nick); rembot(dcc[i].nick,dcc[i].nick); unvia(i,dcc[i].nick); cancel_user_xfer(i); tprintf(dcc[i].sock,"bye\n"); killsock(dcc[i].sock); lostdcc(i); } else { tprintf(dcc[i].sock,"reject %s %s\n",origbotname,who); } } /* disconnect all +a bots because we just got a hub */ void drop_alt_bots() { int atr,i; for (i=0; itype==DCC_BOT) { killsock(dcc[i].sock); dcc[i].sock=dcc[i].type; dcc[i].type=DCC_LOST; } } else if (dcc[i].type==DCC_BOT_NEW) { killsock(dcc[i].sock); dcc[i].sock=dcc[i].type; dcc[i].type=DCC_LOST; } } } } /* break link with a tandembot */ int botunlink(idx,nick) int idx; char *nick; { int i; context; if (nick[0]=='*') dprintf(idx,"Unlinking all bots ...\n"); for (i=0; itype==DCC_BOT)) { if (idx>=0) dprintf(idx,"Killed link attempt to %s.\n",dcc[i].nick); putlog(LOG_BOTS,"*","Killed attempt to link %s at %s:%d",dcc[i].nick, dcc[i].host,dcc[i].port); killsock(dcc[i].sock); dcc[i].sock=dcc[i].type; dcc[i].type=DCC_LOST; if (nick[0]!='*') return 1; } if (dcc[i].type==DCC_BOT_NEW) { if (idx>=0) dprintf(idx,"No longer trying to link to %s.\n", dcc[i].nick); putlog(LOG_BOTS,"*","Stopped trying to link %s at %s:%d",dcc[i].nick, dcc[i].host,dcc[i].port); killsock(dcc[i].sock); dcc[i].sock=dcc[i].type; dcc[i].type=DCC_LOST; if (nick[0]!='*') return 1; else i--; } if (dcc[i].type==DCC_BOT) { if (idx>=0) dprintf(idx,"Breaking link with %s.\n",dcc[i].nick); tprintf(dcc[i].sock,"bye\n"); chatout("*** Unlinked from: %s\n",dcc[i].nick); tandout_but(i,"chat %s Unlinked from: %s\n",origbotname,dcc[i].nick); tandout_but(i,"unlinked %s\n",dcc[i].nick); cancel_user_xfer(i); rembot(dcc[i].nick,dcc[i].nick); unvia(i,dcc[i].nick); killsock(dcc[i].sock); dcc[i].sock=dcc[i].type; dcc[i].type=DCC_LOST; if (nick[0]!='*') return 1; else i--; } } } if ((idx>=0) && (nick[0]!='*')) dprintf(idx,"Not connected to that bot.\n"); if (nick[0]=='*') { dprintf(idx,"Smooshing bot tables and assocs...\n"); tands=0; parties=0; kill_all_assoc(); } return 0; } /* link to another bot */ int botlink(linker,idx,nick) int idx; char *linker,*nick; { char s[121],*p; int port,i; context; if (!(get_attr_handle(nick) & USER_BOT)) { if (idx>=0) dprintf(idx,"%s is not a known bot.\n",nick); return 0; } if (strcasecmp(nick,origbotname)==0) { if (idx>=0) dprintf(idx,"Link to myself? Oh boy, Freud would have a field day.\n"); return 0; } if ((in_chain(nick)) && (idx>=0)) { dprintf(idx,"That bot is already connected up.\n"); return 0; } /* address to connect to is in 'info' */ get_handle_info(nick,s); if (!s[0]) { if (idx>=0) { dprintf(idx,"No telnet port stored for '%s'.\n",nick); dprintf(idx,"Use: .chaddr %s
:\n",nick); } return 0; } p=strchr(s,':'); if (p==NULL) port=2222; else { *p=0; p++; port=atoi(p); } if (dcc_total==MAXDCC) { if (idx>=0) dprintf(idx,"No more dcc entries left: dcc table is full.\n"); return 0; } context; correct_handle(nick); dcc_total++; i=dcc_total-1; dcc[i].port=port; dcc[i].addr=0L; strcpy(dcc[i].nick,nick); strcpy(dcc[i].host,s); dcc[i].type=DCC_BOT; set_tand(i); dcc[i].u.bot->status=0; dcc[i].u.bot->timer=time(NULL); strcpy(dcc[i].u.bot->linker,linker); strcpy(dcc[i].u.bot->version,"(primitive bot)"); if (idx!=(-1)) putlog(LOG_BOTS,"*","Linking to %s at %s ...",nick,s); set_fork(i); dcc[i].u.fork->x=idx; dcc[i].u.fork->start=time(NULL); /* tandout("trying %s %s\n",origbotname,dcc[i].nick); */ dcc[i].u.fork->port=dcc[i].port; /* remember where i started */ context; dcc[i].sock=getsock(SOCK_STRONGCONN); if (open_telnet_raw(dcc[i].sock,s,dcc[i].port) < 0) { failed_link(i); return 0; } return 1; } void failed_link(idx) int idx; { char s[81]; if (dcc[idx].port >= dcc[idx].u.fork->port+3) { if (dcc[idx].u.fork->u.bot->linker[0]) { sprintf(s,"Couldn't link to %s.",dcc[idx].nick); add_note(dcc[idx].u.fork->u.bot->linker,origbotname,s,-2,0); } if (dcc[idx].u.fork->x != (-1)) putlog(LOG_BOTS,"*","Failed link to %s.",dcc[idx].nick); /* tandout("*trying %s %s\n",origbotname,dcc[idx].nick); */ killsock(dcc[idx].sock); dcc[idx].sock=dcc[idx].type; dcc[idx].type=DCC_LOST; autolink_cycle(dcc[idx].nick); /* check for more auto-connections */ return; } /* try next port */ killsock(dcc[idx].sock); dcc[idx].sock=getsock(SOCK_STRONGCONN); dcc[idx].port++; dcc[idx].u.fork->start=time(NULL); if (open_telnet_raw(dcc[idx].sock,dcc[idx].host,dcc[idx].port) < 0) { failed_link(idx); } } void cont_link(idx) int idx; { int i; char s[81]; struct bot_info *ti; context; ti=dcc[idx].u.fork->u.bot; nfree(dcc[idx].u.fork); dcc[idx].u.bot=ti; if (get_attr_handle(dcc[idx].nick) & BOT_HUB) { drop_alt_bots(); /* just those currently in the process of linking */ if (in_chain(dcc[idx].nick)) { i=nextbot(dcc[idx].nick); if (i>0) { chatout("*** Unlinked %s (restructure)\n",dcc[i].nick); tandout_but(i,"chat %s Unlinked %s (restructure)\n",origbotname, dcc[i].nick); tandout_but(i,"unlinked %s\n",dcc[i].nick); rembot(dcc[i].nick,dcc[i].nick); unvia(i,dcc[i].nick); cancel_user_xfer(i); tprintf(dcc[i].sock,"bye\n"); killsock(dcc[i].sock); dcc[i].sock=dcc[i].type; dcc[i].type=DCC_LOST; } } } dcc[idx].type=DCC_BOT_NEW; get_pass_by_handle(dcc[idx].nick,s); if (strcasecmp(s,"-")==0) tprintf(dcc[idx].sock,"%s\n",origbotname); else tprintf(dcc[idx].sock,"%s\n%s\n",origbotname,s); context; return; } /* relay to another tandembot */ void tandem_relay(idx,nick) int idx; char *nick; { char s[121],*p; int port,i; struct chat_info *ci; context; if (!(get_attr_handle(nick) & USER_BOT)) { dprintf(idx,"%s is not a listed bot.\n",nick); return; } if (strcasecmp(nick,origbotname)==0) { dprintf(idx,"Relay to myself? What on EARTH would be the point?!\n"); return; } /* address to connect to is in 'info' */ get_handle_info(nick,s); if (!s[0]) { dprintf(idx,"No telnet port stored for '%s'.\n",nick); dprintf(idx,"Use: .chaddr %s
:\n",nick); return; } p=strchr(s,':'); if (p==NULL) port=2222; else { *p=0; p++; port=atoi(p); } if (dcc_total==MAXDCC) { dprintf(idx,"No more dcc table entries available.\n"); return; } dcc_total++; i=dcc_total-1; dcc[i].port=port; dcc[i].addr=0L; strcpy(dcc[i].nick,nick); strcpy(dcc[i].host,s); dcc[i].type=DCC_RELAY; set_new_relay(i); dcc[i].u.relay->chat->away=NULL; dcc[i].u.relay->chat->status=0; dcc[i].u.relay->chat->timer=time(NULL); dcc[i].u.relay->chat->msgs_per_sec=0; dcc[i].u.relay->chat->con_flags=0; dprintf(idx,"Connecting to %s at %s ...\n",nick,s); dprintf(idx,"(Type *BYE* on a line by itself to abort.)\n"); ci=dcc[idx].u.chat; set_relay(idx); dcc[idx].u.relay->chat=ci; dcc[idx].type=DCC_RELAYING; set_fork(idx); set_fork(i); context; dcc[i].u.fork->port=dcc[i].port; dcc[i].sock=getsock(SOCK_STRONGCONN); dcc[idx].u.fork->u.relay->sock=dcc[i].sock; dcc[i].u.fork->u.relay->sock=dcc[idx].sock; dcc[i].u.fork->start=time(NULL); if (open_telnet_raw(dcc[i].sock,s,dcc[i].port) < 0) failed_tandem_relay(i); } /* input from user before connect is ready */ void pre_relay(idx,buf) int idx; char *buf; { int tidx=(-1),i; context; for (i=0; itype==DCC_RELAY) && (dcc[i].u.fork->u.relay->sock==dcc[idx].sock)) tidx=i; if (tidx<0) { putlog(LOG_MISC,"*","Can't find user for relay! %d -> %d", dcc[i].sock,dcc[i].u.fork->u.relay->sock); return; } if (strcasecmp(buf,"*bye*")==0) { /* disconnect */ struct chat_info *ci=dcc[idx].u.fork->u.relay->chat; dprintf(idx,"Aborting relay attempt to %s.\n",dcc[tidx].nick); dprintf(idx,"You are now back on %s.\n\n",origbotname); putlog(LOG_MISC,"*","Relay aborted: %s -> %s",dcc[idx].nick, dcc[tidx].nick); nfree(dcc[idx].u.fork->u.relay); nfree(dcc[idx].u.fork); dcc[idx].u.chat=ci; dcc[idx].type=DCC_CHAT; if (dcc[idx].u.chat->channel >= 0) { chanout2(dcc[idx].u.chat->channel,"%s joined the party line.\n", dcc[idx].nick); tandout("join %s %s %d %c %s\n",origbotname,dcc[idx].nick, dcc[idx].u.chat->channel,geticon(idx),dcc[idx].host); } notes_read(dcc[idx].nick,"",-1,idx); killsock(dcc[tidx].sock); lostdcc(tidx); return; } context; } /* user disconnected before her relay had finished connecting */ void failed_pre_relay(idx) int idx; { int tidx=(-1),i; context; for (i=0; itype==DCC_RELAY) && (dcc[i].u.fork->u.relay->sock==dcc[idx].sock)) tidx=i; if (tidx<0) { putlog(LOG_MISC,"*","Can't find user for relay! %d -> %d", dcc[i].sock,dcc[i].u.fork->u.relay->sock); return; } killsock(dcc[idx].sock); killsock(dcc[tidx].sock); putlog(LOG_MISC,"*","Lost dcc connection to [%s]%s/%d",dcc[idx].nick, dcc[idx].host,dcc[idx].port); putlog(LOG_MISC,"*","(Dropping relay attempt to %s)",dcc[tidx].nick); check_tcl_chof(dcc[idx].nick,dcc[idx].sock); dcc[idx].sock=dcc[idx].type; dcc[idx].type=DCC_LOST; dcc[tidx].sock=dcc[tidx].type; dcc[tidx].type=DCC_LOST; } void failed_tandem_relay(idx) int idx; { int uidx=(-1),i; context; for (i=0; itype==DCC_RELAYING) && (dcc[i].u.fork->u.relay->sock==dcc[idx].sock)) uidx=i; if (uidx<0) { putlog(LOG_MISC,"*","Can't find user for relay! %d -> %d", dcc[idx].sock,dcc[idx].u.fork->u.relay->sock); return; } if (dcc[idx].port >= dcc[idx].u.fork->port+3) { struct chat_info *ci=dcc[uidx].u.fork->u.relay->chat; dprintf(uidx,"Could not link to %s.\n",dcc[idx].nick); nfree(dcc[uidx].u.fork->u.relay); nfree(dcc[uidx].u.fork); dcc[uidx].u.chat=ci; dcc[uidx].type=DCC_CHAT; killsock(dcc[idx].sock); lostdcc(idx); return; } killsock(dcc[idx].sock); dcc[idx].sock=getsock(SOCK_STRONGCONN); dcc[idx].port++; dcc[idx].u.fork->start=time(NULL); if (open_telnet_raw(dcc[idx].sock,dcc[idx].host,dcc[idx].port)<0) failed_tandem_relay(idx); } void cont_tandem_relay(idx) int idx; { int uidx=(-1),i; struct relay_info *ri; context; for (i=0; itype==DCC_RELAYING) && (dcc[i].u.fork->u.relay->sock==dcc[idx].sock)) uidx=i; if (uidx<0) { putlog(LOG_MISC,"*","Can't find user for relay! %d -> %d", dcc[i].sock,dcc[i].u.fork->u.relay->sock); return; } ri=dcc[idx].u.fork->u.relay; nfree(dcc[idx].u.fork); dcc[idx].u.relay=ri; ri=dcc[uidx].u.fork->u.relay; nfree(dcc[uidx].u.fork); dcc[uidx].u.relay=ri; dcc[uidx].type=DCC_RELAYING; dcc[idx].type=DCC_RELAY; dcc[idx].u.relay->sock=dcc[uidx].sock; dcc[uidx].u.relay->sock=dcc[idx].sock; dprintf(uidx,"Success!\n\n"); dprintf(uidx,"NOW CONNECTED TO RELAY BOT %s ...\n",dcc[idx].nick); dprintf(uidx,"(You can type *BYE* to prematurely close the connection.)\n\n"); putlog(LOG_MISC,"*","Relay link: %s -> %s",dcc[uidx].nick,dcc[idx].nick); if (dcc[uidx].u.relay->chat->channel>=0) { chanout2(dcc[uidx].u.relay->chat->channel,"%s left the party line.\n", dcc[uidx].nick); tandout("part %s %s\n",origbotname,dcc[uidx].nick); } } /* once a monute, send 'ping' to each bot -- no exceptions */ void check_botnet_pings() { int i,j; time_t now=time(NULL); context; for (i=0; istatus&STAT_PINGED) { putlog(LOG_BOTS,"*","Ping timeout: %s",dcc[i].nick); chatout("*** Ping timeout: %s\n",dcc[i].nick); tandout_but(i,"chat %s Ping timeout: %s\n",origbotname,dcc[i].nick); tandout_but(i,"unlinked %s\n",dcc[i].nick); rembot(dcc[i].nick,dcc[i].nick); unvia(i,dcc[i].nick); cancel_user_xfer(i); killsock(dcc[i].sock); lostdcc(i); } for (i=0; istatus|=STAT_PINGED; } for (i=0; istatus&STAT_OFFERED) if (now-dcc[i].u.bot->timer > 120) { tprintf(dcc[i].sock,"userfile?\n"); flush_tbuf(dcc[i].nick); /* ^ send it again in case they missed it */ } for (i=0; istatus&STAT_LEAF)) { for (j=0; jstatus&STAT_WARNED) { putlog(LOG_BOTS,"*","No longer tolerating %s acting like a hub.", dcc[i].nick); tprintf(dcc[i].sock,"bye\n"); chatout("*** Disconnected %s (unleaflike behavior)\n", dcc[i].nick); tandout_but(i,"chat %s Disconnected %s (unleaflike behavior)\n", origbotname,dcc[i].nick); tandout_but(i,"unlinked %s\n",dcc[i].nick); cancel_user_xfer(i); rembot(dcc[i].nick,dcc[i].nick); unvia(i,dcc[i].nick); killsock(dcc[i].sock); lostdcc(i); } else { tprintf(dcc[i].sock,"reject %s %s\n",origbotname,tandbot[j].bot); dcc[i].u.bot->status|=STAT_WARNED; } } else dcc[i].u.bot->status&=~STAT_WARNED; } } } void zapfbot(idx) int idx; { chatout("*** Dropped bot: %s\n",dcc[idx].nick); tandout_but(idx,"unlinked %s\n",dcc[idx].nick); tandout_but(idx,"chat %s Dropped bot: %s\n",origbotname,dcc[idx].nick); cancel_user_xfer(idx); rembot(dcc[idx].nick,dcc[idx].nick); unvia(idx,dcc[idx].nick); killsock(dcc[idx].sock); dcc[idx].sock=dcc[idx].type; dcc[idx].type=DCC_LOST; }