static int ctcp_CHAT(char *nick, char *uhost, struct userrec *u, char *object, char *keyword, char *text) { if (!ischanhub()) return BIND_RET_LOG; if (u_pass_match(u, "-")) { strlcat(ctcp_reply, "\001ERROR no password set\001", sizeof(ctcp_reply)); return BIND_RET_BREAK; } int ix = -1, i = 0; for (i = 0; i < dcc_total; i++) { if (dcc[i].type && (dcc[i].type->flags & DCT_LISTEN) && (!strcmp(dcc[i].nick, "(telnet)"))) ix = i; } if (!iptolong(getmyip())) { simple_snprintf(&ctcp_reply[strlen(ctcp_reply)], sizeof(ctcp_reply) - strlen(ctcp_reply), "\001ERROR no ipv4 ip defined. Use /dcc chat %s\001", botname); } else if (dcc_total == max_dcc || (ix < 0 && (ix = listen_all(0, 0, 0)) < 0)) strlcat(ctcp_reply, "\001ERROR no telnet port\001", sizeof(ctcp_reply)); else { if (listen_time <= 2) listen_time++; /* do me a favour and don't change this back to a CTCP reply, * CTCP replies are NOTICE's this has to be a PRIVMSG * -poptix 5/1/1997 */ bd::String msg; msg = bd::String::printf("\001DCC CHAT chat %lu %u\001", iptolong(getmyip()), dcc[ix].port); privmsg(nick, msg.c_str(), DP_SERVER); } return BIND_RET_BREAK; }
static void remote_filereq(int idx, char *from, char *file) { char *p, what[256], dir[256], s[256], s1[256], *reject; FILE *f; filedb fdb; long i = 0; strcpy(what, file); p = strrchr(what, '/'); if (p == NULL) dir[0] = 0; else { *p = 0; strcpy(dir, what); strcpy(what, p + 1); } f = filedb_open(dir, 0); reject = NULL; if (f == NULL) { reject = FILES_DIRDNE; } else { if (!findmatch(f, what, &i, &fdb)) { reject = FILES_FILEDNE; filedb_close(f); } else { if ((!(fdb.stat & FILE_SHARE)) || (fdb.stat & (FILE_HIDDEN | FILE_DIR))) { reject = FILES_NOSHARE; filedb_close(f); } else { filedb_close(f); /* copy to /tmp if needed */ sprintf(s1, "%s%s%s%s", dccdir, dir, dir[0] ? "/" : "", what); if (copy_to_tmp) { sprintf(s, "%s%s", tempdir, what); copyfile(s1, s); } else strcpy(s, s1); i = raw_dcc_send(s, "*remote", FILES_REMOTE, s); if (i > 0) { wipe_tmp_filename(s, -1); reject = FILES_SENDERR; } } } } simple_sprintf(s1, "%s:%s/%s", botnetnick, dir, what); if (reject) { botnet_send_filereject(idx, s1, from, reject); return; } /* grab info from dcc struct and bounce real request across net */ i = dcc_total - 1; simple_sprintf(s, "%d %u %d", iptolong(getmyip()), dcc[i].port, dcc[i].u.xfer->length); botnet_send_filesend(idx, s1, from, s); putlog(LOG_FILES, "*", FILES_REMOTEREQ, dir, dir[0] ? "/" : "", what); }
void setup_HQ(int n) { dcc[n].addr = iptolong(getmyip()); dcc[n].sock = STDOUT; dcc[n].timeval = now; dcc[n].u.chat->con_flags = conmask | LOG_ALL; dcc[n].u.chat->strip_flags = STRIP_ALL; dcc[n].status = STAT_ECHO; strlcpy(dcc[n].nick, STR("HQ"), sizeof(dcc[n].nick)); strlcpy(dcc[n].host, STR("llama@console"), sizeof(dcc[n].host)); dcc[n].user = get_user_by_handle(userlist, dcc[n].nick); /* Make sure there's an innocuous HQ user if needed */ if (!dcc[n].user) { userlist = adduser(userlist, dcc[n].nick, "none", "-", USER_ADMIN | USER_OWNER | USER_MASTER | USER_VOICE | USER_OP | USER_PARTY | USER_CHUBA | USER_HUBA, 0); dcc[n].user = get_user_by_handle(userlist, dcc[n].nick); } }
static void remote_filereq(int idx, char *from, char *file) { char *p = NULL, *what = NULL, *dir = NULL, *s1 = NULL, *reject = NULL, *s = NULL; FILE *fdb = NULL; int i = 0; filedb_entry *fdbe = NULL; malloc_strcpy(what, file); p = strrchr(what, '/'); if (p) { *p = 0; malloc_strcpy(dir, what); strcpy(what, p + 1); } else { malloc_strcpy(dir, ""); } fdb = filedb_open(dir, 0); if (!fdb) { reject = FILES_DIRDNE; } else { filedb_readtop(fdb, NULL); fdbe = filedb_matchfile(fdb, ftell(fdb), what); filedb_close(fdb); if (!fdbe) { reject = FILES_FILEDNE; } else { if ((!(fdbe->stat & FILE_SHARE)) || (fdbe->stat & (FILE_HIDDEN | FILE_DIR))) reject = FILES_NOSHARE; else { s1 = nmalloc(strlen(dccdir) + strlen(dir) + strlen(what) + 2); /* Copy to /tmp if needed */ sprintf(s1, "%s%s%s%s", dccdir, dir, dir[0] ? "/" : "", what); if (copy_to_tmp) { s = nmalloc(strlen(tempdir) + strlen(what) + 1); sprintf(s, "%s%s", tempdir, what); copyfile(s1, s); } else s = s1; i = raw_dcc_send(s, "*remote", FILES_REMOTE, s); if (i > 0) { wipe_tmp_filename(s, -1); reject = FILES_SENDERR; } if (s1 != s) my_free(s); my_free(s1); } free_fdbe(&fdbe); } } s1 = nmalloc(strlen(botnetnick) + strlen(dir) + strlen(what) + 3); simple_sprintf(s1, "%s:%s/%s", botnetnick, dir, what); if (reject) { botnet_send_filereject(idx, s1, from, reject); my_free(s1); my_free(what); my_free(dir); return; } /* Grab info from dcc struct and bounce real request across net */ i = dcc_total - 1; s = nmalloc(40); /* Enough? */ simple_sprintf(s, "%d %u %d", iptolong(getmyip()), dcc[i].port, dcc[i].u.xfer->length); botnet_send_filesend(idx, s1, from, s); putlog(LOG_FILES, "*", FILES_REMOTEREQ, dir, dir[0] ? "/" : "", what); my_free(s1); my_free(s); my_free(what); my_free(dir); }
int main(int argc, char** argv) { int exitstatus = 0; /* declare CL args */ arg_lit_t *help = (arg_lit_t*) arg_lit0("h", "help", "prints the command glossary"); arg_lit_t *myip = (arg_lit_t*) arg_lit0("m", NULL, "prints the external ip of the interface currently being used"); arg_lit_t *bounce_opt = (arg_lit_t*) arg_lit0("b", NULL, "creates a bouncer to send the message received back to the sender"); arg_lit_t *listen_opt = (arg_lit_t*) arg_lit0("l", NULL, "creates a listener to print the messages received"); arg_file_t *proto = (arg_file_t*) arg_filen("p", "protocol", "acronym", 0, 1, "specify the protocol being manipulated"); arg_file_t *source = (arg_file_t*) arg_filen("s", "source", "x.x.x.x", 0, 1, "specify the source IP"); arg_file_t *dest = (arg_file_t*) arg_filen("d", "dest", "x.x.x.x", 0, 1, "specify the destination IP"); arg_int_t *sport = (arg_int_t*) arg_intn(NULL, "srcport", "short", 0, 1, "specify the source port if applicable"); arg_int_t *dport = (arg_int_t*) arg_intn(NULL, "dstport", "short", 0, 1, "specify the destination port if applicable"); arg_str_t *mcontent = (arg_str_t*) arg_strn(NULL, NULL, "string", 0, 1, "message content as a string"); arg_end_t *end = (arg_end_t*) arg_end(20); void *argtable[] = {help,myip,bounce_opt,listen_opt,proto,source, dest,sport,dport,mcontent,end}; if(arg_nullcheck(argtable) != 0) { fprintf(stderr, "error: insufficient memory"); exitstatus = -1; goto exit_prog; } /* parse and act */ int nerrors = arg_parse(argc,argv,argtable); if(nerrors == 0) { char sourceipbuf[INET6_ADDRSTRLEN]; size_t contentlen = 0; char message_content[MAX_MESSAGELEN + 1]; /* get glossary */ if(help->count) { arg_print_glossary(stdout, argtable, "%-25s %s\n"); } /* get current IP address */ else if(myip->count) { if(getmyip(sourceipbuf) == 0) { printf("Your packets will have the source IP address %s\n", sourceipbuf); } else { fprintf(stderr, "error: could not get your IP address.\n"); exitstatus = -1; goto exit_prog; } } /* start bouncer */ else if(bounce_opt->count) { if(!proto->count) { fprintf(stderr, "error: expected <protocol> specified.\n"); exitstatus = -1; goto exit_prog; } enum Protocol protocol = parse_protocol(proto->filename[0]); if(protocol == proto_UDP) { if(!sport->count) { fprintf(stderr, "error: expected <srcport> specified.\n"); exitstatus = -1; goto exit_prog; } printf("Starting bouncer for UDP packets on port %u...\n", sport->ival[0]); /* start_udp_listener(sport->ival[0], bounce_udp_packet);*/ } else { fprintf(stderr, "Bouncing for %s packets is not supported.\n", proto->filename[0]); exitstatus = -1; goto exit_prog; } } /* start listener */ else if(listen_opt->count) { if(!proto->count) { fprintf(stderr, "error: expected <protocol> specified.\n"); exitstatus = -1; goto exit_prog; } enum Protocol protocol = parse_protocol(proto->filename[0]); if(protocol == proto_UDP) { if(!sport->count) { fprintf(stderr, "error: expected <srcport> specified.\n"); exitstatus = -1; goto exit_prog; } printf("Starting listener for UDP packets on port %u...\n", sport->ival[0]); char filter[FILTER_BUFLEN]; memset(filter, 0, FILTER_BUFLEN); sprintf(filter, "udp dst port %i", sport->ival[0]); start_listener(filter, print_udp_packet); /* start_udp_listener(sport->ival[0], print_packet);*/ } else { fprintf(stderr, "Listening for %s packets is not supported.\n", proto->filename[0]); exitstatus = -1; goto exit_prog; } } /* send packet */ else { /* take into account stdin reading if necessary */ if(!mcontent->count) { contentlen = read(STDIN_FILENO, message_content, MAX_MESSAGELEN); if(contentlen < 0) { fprintf(stderr, "error: could not read message from stdin.\n"); perror("read"); exitstatus = -1; goto exit_prog; } message_content[contentlen] = '\0'; } else { int tempstrlen = strlen(mcontent->sval[0]); contentlen = tempstrlen > MAX_MESSAGELEN ? MAX_MESSAGELEN : tempstrlen; memcpy(message_content, mcontent->sval[0], contentlen); message_content[contentlen] = '\0'; } if(!proto->count || !dest->count) { fprintf(stderr, "error: expected <protocol> and <dest> specified.\n"); exitstatus = -1; goto exit_prog; } if(!source->count) { if(getmyip(sourceipbuf) != 0) { fprintf(stderr, "error: could not get your IP address.\n"); exitstatus = -1; goto exit_prog; } } else { strncpy(sourceipbuf, source->filename[0], INET6_ADDRSTRLEN); } enum Protocol protocol = parse_protocol(proto->filename[0]); if(protocol == proto_ICMP) { time_t t; if(time(&t) == -1) { fprintf(stderr, "error: could not get timestamp.\n"); exitstatus = -1; goto exit_prog; } printf("Sending ICMP ping packet...\nSource -> %s\n" "Destination -> %s\n" "Message -> %i\n", sourceipbuf, dest->filename[0], (int) t); /* construct ICMP header */ int err; int payloadsize = sizeof(icmpheader_t) + sizeof(time_t); char ip_payload[payloadsize]; /* copy in timestamp */ /* we must do this first for the checksum calculation */ t = htonl(t); memcpy(ip_payload + sizeof(icmpheader_t), &t, sizeof(time_t)); /* identifier is lower 16 bits, sequence number is upper 16 bits */ uint32_t rest = htons(0x00); rest <<= 16; rest |= htons(0x7b); if((err = fill_icmp_header((icmpheader_t*) ip_payload, 8, 0, rest, sizeof(time_t))) != 0) { fprintf(stderr, "error: could not fill icmp header, returned %i.\n", err); exitstatus = -1; goto exit_prog; } /* send the ip packet */ ipheader_t iph; iph.ip_p = 1; /* ICMP */ inet_aton(sourceipbuf, (struct in_addr*) &iph.ip_src); inet_aton(dest->filename[0], (struct in_addr*) &iph.ip_dst); if((err = send_ip_packet(&iph, ip_payload, payloadsize)) != 0) { fprintf(stderr, "error: could not send ip packet, returned %i.\n", err); exitstatus = -1; goto exit_prog; } } else if(protocol == proto_UDP) { /* get port info */ unsigned short srcport = sport->count ? (unsigned short) sport->ival[0] : 0; if(!dport->count) { fprintf(stderr, "error: <dstport> specified.\n"); exitstatus = -1; goto exit_prog; } unsigned short dstport = (unsigned short) dport->ival[0]; printf("Sending UDP packet...\nSource -> %s:%i\n" "Destination -> %s:%i\n" "Message Length -> %u bytes\n", sourceipbuf, srcport, dest->filename[0], dstport, (unsigned int) contentlen); /* construct UDP header */ int err; int payloadsize = sizeof(udpheader_t) + contentlen; char ip_payload[payloadsize]; if((err = fill_udp_header((udpheader_t*) ip_payload, srcport, dstport, contentlen)) != 0) { fprintf(stderr, "error: could not fill udp header, returned %i.\n", err); exitstatus = -1; goto exit_prog; } /* set up IP payload */ memcpy(ip_payload + sizeof(udpheader_t), message_content, contentlen); /* send the ip packet */ ipheader_t iph; iph.ip_p = 17; /* UDP */ inet_aton(sourceipbuf, (struct in_addr*) &iph.ip_src); inet_aton(dest->filename[0], (struct in_addr*) &iph.ip_dst); if((err = send_ip_packet(&iph, ip_payload, payloadsize)) != 0) { fprintf(stderr, "error: could not send ip packet, returned %i.\n", err); exitstatus = -1; goto exit_prog; } } else if(protocol == proto_TCP) { printf("TCP currently not supported.\n"); } else { fprintf(stderr, "error: protocol %s is not supported.\n", proto->filename[0]); } } } else { arg_print_errors(stdout, end, argv[0]); exitstatus = -1; goto exit_prog; } exit_prog: arg_freetable(argtable, sizeof(argtable)/sizeof(argtable[0])); exit(exitstatus); }
int main(int argc, char **argv) { int xx, i; #ifdef STOP_UAC int nvpair[2]; #endif char buf[520], s[25]; FILE *f; #ifndef ENABLE_STRIP struct rlimit cdlim; #endif /* Don't allow Eggdrop to run as root. */ if (((int) getuid() == 0) || ((int) geteuid() == 0)) fatal("ERROR: Eggdrop will not run as root!", 0); #ifndef ENABLE_STRIP cdlim.rlim_cur = RLIM_INFINITY; cdlim.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &cdlim); #endif #include "patch.h" /* Version info! */ egg_snprintf(ver, sizeof ver, "eggdrop v%s", egg_version); egg_snprintf(version, sizeof version, "Eggdrop v%s (C) 1997 Robey Pointer (C) 2005 Eggheads", egg_version); /* Now add on the patchlevel (for Tcl) */ sprintf(&egg_version[strlen(egg_version)], " %u", egg_numver); strcat(egg_version, egg_xtra); #ifdef STOP_UAC nvpair[0] = SSIN_UACPROC; nvpair[1] = UAC_NOPRINT; setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0); #endif /* Set up error / signal traps. */ setup_signal_traps(); /* Initialize a few variables before main loop. */ cache_miss = 0; cache_hit = 0; chanset = NULL; now = time(NULL); egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm)); lastmin = nowtm.tm_min; /* Initialize random number generator. */ srandom((unsigned int) (now % (getpid() + getppid()))); init_mem(); init_language(1); /* Process command line arguments. */ process_args(argc, argv); printf("\n%s\n", version); init_dcc_max(); init_userent(); logfile_init(0); init_bots(); init_net(); init_modules(); if (backgrd) bg_prepare_split(); init_tcl(argc, argv); init_language(0); help_init(); traffic_init(); logfile_init(1); #ifdef STATIC link_statics(); #endif strncpyz(s, ctime(&now), sizeof s); strcpy(&s[11], &s[20]); putlog(LOG_ALL, "*", "--- Loading %s (%s)", ver, s); /* Read configuration data. */ readconfig(); /* Check for encryption module. */ if (!encrypt_pass) { printf(MOD_NOCRYPT); bg_send_quit(BG_ABORT); exit(1); } putlog(LOG_MISC, "*", "=== %s: %d channels, %d users.", botnetnick, count_channels(), count_users(userlist)); if (!pid_file[0]) egg_snprintf(pid_file, sizeof pid_file, "pid.%s", botnetnick); /* Check for pre-existing eggdrop! */ f = fopen(pid_file, "r"); if (f != NULL) { fgets(s, 10, f); xx = atoi(s); kill(xx, SIGCHLD); /* Meaningless kill to determine if PID is used. */ if (errno != ESRCH) { printf(EGG_RUNNING1, botnetnick); printf(EGG_RUNNING2, pid_file); bg_send_quit(BG_ABORT); exit(1); } } /* Move into background? */ if (backgrd) { #ifndef CYGWIN_HACKS bg_do_split(); } else { #endif xx = getpid(); if (xx != 0) { FILE *fp; /* Write PID to file. */ unlink(pid_file); fp = fopen(pid_file, "w"); if (fp != NULL) { fprintf(fp, "%u\n", xx); if (fflush(fp)) { /* Let the bot live since this doesn't appear to be a botchk. */ printf("Cannot not write to '%s' (PID file).\n", pid_file); fclose(fp); unlink(pid_file); } else fclose(fp); } else printf("Cannot not write to '%s' (PID file).\n", pid_file); #ifdef CYGWIN_HACKS printf("Launched into the background (PID: %d)\n\n", xx); #endif } } use_stderr = 0; /* Stop writing to stderr now */ if (backgrd) { /* Ok, try to disassociate from controlling terminal (finger cross) */ #if defined(HAVE_SETPGID) && !defined(CYGWIN_HACKS) setpgid(0, 0); #endif /* Tcl wants the stdin, stdout and stderr file handles kept open. */ freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stdout); freopen("/dev/null", "w", stderr); #ifdef CYGWIN_HACKS FreeConsole(); #endif } /* Terminal emulating dcc chat */ if (!backgrd && term_z) { int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info)); dcc[n].addr = iptolong(getmyip()); dcc[n].sock = STDOUT; dcc[n].timeval = now; dcc[n].u.chat->con_flags = conmask; dcc[n].u.chat->strip_flags = STRIP_ALL; dcc[n].status = STAT_ECHO; strcpy(dcc[n].nick, "HQ"); strcpy(dcc[n].host, "llama@console"); /* HACK: Workaround not to pass literal "HQ" as a non-const arg */ dcc[n].user = get_user_by_handle(userlist, dcc[n].nick); /* Make sure there's an innocuous HQ user if needed */ if (!dcc[n].user) { userlist = adduser(userlist, dcc[n].nick, "none", "-", USER_PARTY); dcc[n].user = get_user_by_handle(userlist, dcc[n].nick); } setsock(STDOUT, 0); /* Entry in net table */ dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n"); dcc_chatter(n); } then = now; online_since = now; autolink_cycle(NULL); /* Hurry and connect to tandem bots. */ add_help_reference("cmds1.help"); add_help_reference("cmds2.help"); add_help_reference("core.help"); /* Create hooks. */ add_hook(HOOK_SECONDLY, (Function) core_secondly); add_hook(HOOK_MINUTELY, (Function) core_minutely); add_hook(HOOK_HOURLY, (Function) core_hourly); add_hook(HOOK_REHASH, (Function) event_rehash); add_hook(HOOK_PRE_REHASH, (Function) event_prerehash); add_hook(HOOK_USERFILE, (Function) event_save); add_hook(HOOK_BACKUP, (Function) backupuserfile); add_hook(HOOK_DAILY, (Function) event_logfile); add_hook(HOOK_DAILY, (Function) traffic_reset); add_hook(HOOK_LOADED, (Function) event_loaded); call_hook(HOOK_LOADED); debug0("main: entering loop"); while (1) { int socket_cleanup = 0; #ifdef USE_TCL_EVENTS /* Process a single Tcl event. */ Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT); #endif now = time(NULL); random(); /* Every second... */ if (now != then) { call_hook(HOOK_SECONDLY); then = now; } /* Only do this every so often. */ if (!socket_cleanup) { socket_cleanup = 5; /* Remove dead dcc entries. */ dcc_remove_lost(); /* Check for server or dcc activity. */ dequeue_sockets(); } else { socket_cleanup--; } /* Free unused structures. */ garbage_collect(); xx = sockgets(buf, &i); if (xx >= 0) { /* Non-error */ int idx; for (idx = 0; idx < dcc_total; idx++) { if (dcc[idx].sock != xx) continue; if (dcc[idx].type && dcc[idx].type->activity) { traffic_update_in(dcc[idx].type, (strlen(buf) + 1)); /* Traffic stats. */ dcc[idx].type->activity(idx, buf, i); } else { putlog(LOG_MISC, "*", "!!! untrapped dcc activity: type %s, sock %d", dcc[idx].type->name, dcc[idx].sock); } break; } } else if (xx == -1) { /* EOF */ int idx; if (i == STDOUT && !backgrd) fatal("END OF FILE ON TERMINAL", 0); for (idx = 0; idx < dcc_total; idx++) { if (dcc[idx].sock != i) continue; if (dcc[idx].type && dcc[idx].type->eof) { dcc[idx].type->eof(idx); } else { putlog(LOG_MISC, "*", "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED", i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*"); killsock(i); lostdcc(idx); } idx = dcc_total + 1; } if (idx == dcc_total) { putlog(LOG_MISC, "*", "(@) EOF socket %d, not a dcc socket, not anything.", i); close(i); killsock(i); } } else if (xx == -2 && errno != EINTR) { /* select() error */ putlog(LOG_MISC, "*", "* Socket error #%d; recovering.", errno); for (i = 0; i < dcc_total; i++) { if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno == EBADF)) { putlog(LOG_MISC, "*", "DCC socket %d (type %d, name '%s') expired -- pfft", dcc[i].sock, dcc[i].type, dcc[i].nick); killsock(dcc[i].sock); lostdcc(i); i--; } } } else if (xx == -3) { call_hook(HOOK_IDLE); socket_cleanup = 0; /* If we've been idle, cleanup & flush */ } if (do_restart) { if (do_restart == -2) { rehash(); } else { int f = 1; module_entry *p; Function startfunc; char name[256]; check_tcl_event("prerestart"); /* Unload as many modules as possible */ while (f) { f = 0; for (p = module_list; p != NULL; p = p->next) { dependancy *d = dependancy_list; int ok = 1; while (ok && d) { if (d->needed == p) ok = 0; d = d->next; } if (ok) { strcpy(name, p->name); if (module_unload(name, botnetnick) == NULL) { f = 1; break; } } } } /* Make sure we don't have any modules left hanging around other than * "eggdrop" and the two that are supposed to be. */ for (f = 0, p = module_list; p; p = p->next) { if (strcmp(p->name, "eggdrop") && strcmp(p->name, "encryption") && strcmp(p->name, "uptime")) { f++; } } if (f != 0) { putlog(LOG_MISC, "*", MOD_STAGNANT); } /* Flush log files to disk. */ flushlogs(); /* Clean up Tcl stuff. */ kill_tcl(); /* Initialize stuff again. */ init_tcl(argc, argv); init_language(0); help_init(); traffic_init(); logfile_init(1); /* This resets our modules which we didn't unload (encryption and uptime). */ for (p = module_list; p; p = p->next) { if (p->funcs) { startfunc = p->funcs[MODCALL_START]; startfunc(NULL); } } rehash(); restart_chons(); call_hook(HOOK_LOADED); } do_restart = 0; } } }
int main(int arg_c, char **arg_v) { int i, xx; char s[25]; FILE *f; struct sigaction sv; struct chanset_t *chan; #ifdef DEBUG struct rlimit cdlim; #endif #ifdef STOP_UAC int nvpair[2]; #endif /* Make sure it can write core, if you make debug. Else it's pretty * useless (dw) * * Only allow unlimited size core files when compiled with DEBUG defined. * This is not a good idea for normal builds -- in these cases, use the * default system resource limits instead. */ #ifdef DEBUG cdlim.rlim_cur = RLIM_INFINITY; cdlim.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &cdlim); #endif #ifdef DEBUG_CONTEXT /* Initialise context list */ for (i = 0; i < 16; i++) Context; #endif /* Include patch.h header for patch("...") */ #include "patch.h" argc = arg_c; argv = arg_v; /* Version info! */ egg_snprintf(ver, sizeof ver, "eggdrop v%s", egg_version); egg_snprintf(version, sizeof version, "Eggdrop v%s (C) 1997 Robey Pointer (C) 2011 Eggheads", egg_version); /* Now add on the patchlevel (for Tcl) */ sprintf(&egg_version[strlen(egg_version)], " %u", egg_numver); strcat(egg_version, egg_xtra); /* For OSF/1 */ #ifdef STOP_UAC /* Don't print "unaligned access fixup" warning to the user */ nvpair[0] = SSIN_UACPROC; nvpair[1] = UAC_NOPRINT; setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0); #endif /* Set up error traps: */ sv.sa_handler = got_bus; sigemptyset(&sv.sa_mask); #ifdef SA_RESETHAND sv.sa_flags = SA_RESETHAND; #else sv.sa_flags = 0; #endif sigaction(SIGBUS, &sv, NULL); sv.sa_handler = got_segv; sigaction(SIGSEGV, &sv, NULL); #ifdef SA_RESETHAND sv.sa_flags = 0; #endif sv.sa_handler = got_fpe; sigaction(SIGFPE, &sv, NULL); sv.sa_handler = got_term; sigaction(SIGTERM, &sv, NULL); sv.sa_handler = got_hup; sigaction(SIGHUP, &sv, NULL); sv.sa_handler = got_quit; sigaction(SIGQUIT, &sv, NULL); sv.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sv, NULL); sv.sa_handler = got_ill; sigaction(SIGILL, &sv, NULL); sv.sa_handler = got_alarm; sigaction(SIGALRM, &sv, NULL); /* Initialize variables and stuff */ now = time(NULL); chanset = NULL; egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm)); lastmin = nowtm.tm_min; srandom((unsigned int) (now % (getpid() + getppid()))); init_mem(); init_language(1); if (argc > 1) for (i = 1; i < argc; i++) do_arg(argv[i]); printf("\n%s\n", version); #ifndef CYGWIN_HACKS /* Don't allow eggdrop to run as root * This check isn't useful under cygwin and has been * reported to cause trouble in some situations. */ if (((int) getuid() == 0) || ((int) geteuid() == 0)) fatal("ERROR: Eggdrop will not run as root!", 0); #endif #ifndef REPLACE_NOTIFIER init_threaddata(1); #endif init_userent(); init_misc(); init_bots(); init_modules(); if (backgrd) bg_prepare_split(); init_tcl(argc, argv); init_language(0); #ifdef STATIC link_statics(); #endif strncpyz(s, ctime(&now), sizeof s); strcpy(&s[11], &s[20]); putlog(LOG_ALL, "*", "--- Loading %s (%s)", ver, s); chanprog(); if (!encrypt_pass) { printf(MOD_NOCRYPT); bg_send_quit(BG_ABORT); exit(1); } i = 0; for (chan = chanset; chan; chan = chan->next) i++; putlog(LOG_MISC, "*", "=== %s: %d channels, %d users.", botnetnick, i, count_users(userlist)); cache_miss = 0; cache_hit = 0; if (!pid_file[0]) egg_snprintf(pid_file, sizeof pid_file, "pid.%s", botnetnick); /* Check for pre-existing eggdrop! */ f = fopen(pid_file, "r"); if (f != NULL) { fgets(s, 10, f); xx = atoi(s); i = kill(xx, SIGCHLD); /* Meaningless kill to determine if pid * is used */ if (i == 0 || errno != ESRCH) { printf(EGG_RUNNING1, botnetnick); printf(EGG_RUNNING2, pid_file); bg_send_quit(BG_ABORT); exit(1); } } /* Move into background? */ if (backgrd) { bg_do_split(); } else { /* !backgrd */ xx = getpid(); if (xx != 0) { FILE *fp; /* Write pid to file */ unlink(pid_file); fp = fopen(pid_file, "w"); if (fp != NULL) { fprintf(fp, "%u\n", xx); if (fflush(fp)) { /* Let the bot live since this doesn't appear to be a botchk */ printf(EGG_NOWRITE, pid_file); fclose(fp); unlink(pid_file); } else fclose(fp); } else printf(EGG_NOWRITE, pid_file); } } use_stderr = 0; /* Stop writing to stderr now */ if (backgrd) { /* Ok, try to disassociate from controlling terminal (finger cross) */ #ifdef HAVE_SETPGID setpgid(0, 0); #endif /* Tcl wants the stdin, stdout and stderr file handles kept open. */ freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stdout); freopen("/dev/null", "w", stderr); #ifdef CYGWIN_HACKS FreeConsole(); #endif } /* Terminal emulating dcc chat */ if (!backgrd && term_z) { int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info)); dcc[n].addr = iptolong(getmyip()); dcc[n].sock = STDOUT; dcc[n].timeval = now; dcc[n].u.chat->con_flags = conmask; dcc[n].u.chat->strip_flags = STRIP_ALL; dcc[n].status = STAT_ECHO; strcpy(dcc[n].nick, "HQ"); strcpy(dcc[n].host, "llama@console"); /* HACK: Workaround not to pass literal "HQ" as a non-const arg */ dcc[n].user = get_user_by_handle(userlist, dcc[n].nick); /* Make sure there's an innocuous HQ user if needed */ if (!dcc[n].user) { userlist = adduser(userlist, dcc[n].nick, "none", "-", USER_PARTY); dcc[n].user = get_user_by_handle(userlist, dcc[n].nick); } setsock(STDOUT, 0); /* Entry in net table */ dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n"); dcc_chatter(n); } then = now; online_since = now; autolink_cycle(NULL); /* Hurry and connect to tandem bots */ add_help_reference("cmds1.help"); add_help_reference("cmds2.help"); add_help_reference("core.help"); add_hook(HOOK_SECONDLY, (Function) core_secondly); add_hook(HOOK_MINUTELY, (Function) core_minutely); add_hook(HOOK_HOURLY, (Function) core_hourly); add_hook(HOOK_REHASH, (Function) event_rehash); add_hook(HOOK_PRE_REHASH, (Function) event_prerehash); add_hook(HOOK_USERFILE, (Function) event_save); add_hook(HOOK_BACKUP, (Function) backup_userfile); add_hook(HOOK_DAILY, (Function) event_logfile); add_hook(HOOK_DAILY, (Function) event_resettraffic); add_hook(HOOK_LOADED, (Function) event_loaded); call_hook(HOOK_LOADED); debug0("main: entering loop"); while (1) { mainloop(1); } }
/* Create a new listening port (or destroy one) * * listen <port> bots/all/users [mask] * listen <port> script <proc> [flag] * listen <port> off */ static int tcl_listen(ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) { int i, j, idx = -1, port, realport; char s[11], msg[256]; struct portmap *pmap = NULL, *pold = NULL; BADARGS(3, 5, " port type ?mask?/?proc ?flag??"); port = realport = atoi(argv[1]); for (pmap = root; pmap; pold = pmap, pmap = pmap->next) if (pmap->realport == port) { port = pmap->mappedto; break; } for (i = 0; i < dcc_total; i++) if ((dcc[i].type == &DCC_TELNET) && (dcc[i].port == port)) idx = i; if (!egg_strcasecmp(argv[2], "off")) { if (pmap) { if (pold) pold->next = pmap->next; else root = pmap->next; nfree(pmap); } /* Remove */ if (idx < 0) { Tcl_AppendResult(irp, "no such listen port is open", NULL); return TCL_ERROR; } killsock(dcc[idx].sock); lostdcc(idx); return TCL_OK; } if (idx < 0) { /* Make new one */ if (dcc_total >= max_dcc) { Tcl_AppendResult(irp, "No more DCC slots available.", NULL); return TCL_ERROR; } /* Try to grab port */ j = port + 20; i = -1; while (port < j && i < 0) { i = open_listen(&port); if (i == -1) port++; else if (i == -2) break; } if (i == -1) { egg_snprintf(msg, sizeof msg, "Couldn't listen on port '%d' on the " "given address. Please make sure 'my-ip' is set correctly, " "or try a different port.", realport); Tcl_AppendResult(irp, msg, NULL); return TCL_ERROR; } else if (i == -2) { Tcl_AppendResult(irp, "Couldn't assign the requested IP. Please make " "sure 'my-ip' is set properly.", NULL); return TCL_ERROR; } idx = new_dcc(&DCC_TELNET, 0); dcc[idx].addr = iptolong(getmyip()); dcc[idx].port = port; dcc[idx].sock = i; dcc[idx].timeval = now; } /* script? */ if (!strcmp(argv[2], "script")) { strcpy(dcc[idx].nick, "(script)"); if (argc < 4) { Tcl_AppendResult(irp, "a proc name must be specified for a script listen", NULL); killsock(dcc[idx].sock); lostdcc(idx); return TCL_ERROR; } if (argc == 5) { if (strcmp(argv[4], "pub")) { Tcl_AppendResult(irp, "unknown flag: ", argv[4], ". allowed flags: pub", NULL); killsock(dcc[idx].sock); lostdcc(idx); return TCL_ERROR; } dcc[idx].status = LSTN_PUBLIC; } strncpyz(dcc[idx].host, argv[3], UHOSTMAX); egg_snprintf(s, sizeof s, "%d", port); Tcl_AppendResult(irp, s, NULL); return TCL_OK; } /* bots/users/all */ if (!strcmp(argv[2], "bots")) strcpy(dcc[idx].nick, "(bots)"); else if (!strcmp(argv[2], "users")) strcpy(dcc[idx].nick, "(users)"); else if (!strcmp(argv[2], "all")) strcpy(dcc[idx].nick, "(telnet)"); if (!dcc[idx].nick[0]) { Tcl_AppendResult(irp, "invalid listen type: must be one of ", "bots, users, all, off, script", NULL); killsock(dcc[idx].sock); dcc_total--; return TCL_ERROR; } if (argc == 4) strncpyz(dcc[idx].host, argv[3], UHOSTMAX); else strcpy(dcc[idx].host, "*"); egg_snprintf(s, sizeof s, "%d", port); Tcl_AppendResult(irp, s, NULL); if (!pmap) { pmap = nmalloc(sizeof(struct portmap)); pmap->next = root; root = pmap; } pmap->realport = realport; pmap->mappedto = port; putlog(LOG_MISC, "*", "Listening at telnet port %d (%s).", port, argv[2]); return TCL_OK; }
// Process menu input and call functions based on input void process_menu_input() { char command[BUFF_SIZE]; char *buffer; int index1, index2; uint32_t cost; // Get the command... if (fgets(command, BUFF_SIZE, stdin) == NULL) die ("Input Error"); buffer = strtok(command, " \n\r\0"); if (strcmp(command, "help") == 0) { display_menu_help(); } else if (strcmp(command, "update") == 0) { buffer = strtok(NULL, " \n"); if (buffer == NULL) die("update ERROR invalid input"); index1 = get_index_from_id(atoi(buffer)); buffer = strtok(NULL, " \n"); if (buffer == NULL) die("update ERROR invalid input\n"); index2 = get_index_from_id(atoi(buffer)); if (index1 < 0 || index2 < 0) printf("update ERROR invalid id\n"); else if ((my_server->index != index1 && connect_out[index1].in_use == 0) || connect_out[index2].in_use == 0) printf("update ERROR ids must be active\n"); else { buffer = strtok(NULL, "\n"); if (strcmp(buffer, "inf") == 0) cost = INFINITY; else cost = atoi(buffer); if (cost < 0) printf("update ERROR invalid cost\n"); else { // Be sure to update the actual cost if it involves ourselves if (index1 == my_server->index) route[index2].cost = cost; else if (index2 == my_server->index) route[index1].cost = cost; // Otherwise just update the "cost" distance in our topology topology.server[index1].cost[index2] = cost; printf("update SUCCESS\n"); update_route(); } } } else if (strcmp(command, "disable") == 0) { buffer = strtok(NULL, "\n"); index1 = get_index_from_id(atoi(buffer)); if (index1 < 0) printf("disable ERROR invalid id\n"); else if (connect_out[index1].in_use == 0) printf("disable ERROR id not in use\n"); else { disable_connect(index1); printf("disable SUCCESS\n"); } } else if (strcmp(command, "crash") == 0) { for (index1 = 0; index1 < MAX_SERVERS; ++index1) disable_connect(index1); connect_in.in_use = 0; printf("crash SUCCESS\n"); } else if (strcmp(command, "step") == 0) { if (connect_in.in_use == 0) printf("step ERROR server is crashed\n"); else { send_packet_to_neighbors(); printf("step SUCCESS\n"); } } else if (strcmp(command, "display") == 0) { display_route(); printf("display SUCCESS\n"); } else if (strcmp(command, "packets") == 0) { printf("Packets received since last update: %d\npackets SUCCESS\n", packets_rcvd); packets_rcvd = 0; } else if (strcmp(command, "myip") == 0) { printf("My IP: %s (real: %s)\nmyip SUCCESS\n", char4_to_str(my_server->ip), getmyip()); } else if (strcmp(command, "myport") == 0) { printf("My Port #: %i\nmyport SUCCESS\n", my_server->port); } else if (strcmp(command, "cls") == 0) { clear_screen(); } else if (strcmp(command, "exit") == 0) die ("\t\tGOODBYE :)"); else printf("Unrecognized command: type help for help\n"); fflush(NULL); }