/* Send connection request to proxy */ static int proxy_connect(int sock, char *host, int port, int proxy) { unsigned char x[10]; struct hostent *hp; char s[256]; int i; /* socks proxy */ if (proxy == PROXY_SOCKS) { /* numeric IP? */ if (host[strlen(host) - 1] >= '0' && host[strlen(host) - 1] <= '9') { IP ip = ((IP) inet_addr(host)); egg_memcpy(x, &ip, 4); } else { /* no, must be host.domain */ if (!sigsetjmp(alarmret, 1)) { alarm(resolve_timeout); hp = gethostbyname(host); alarm(0); } else hp = NULL; if (hp == NULL) { killsock(sock); return -2; } egg_memcpy(x, hp->h_addr, hp->h_length); } for (i = 0; i < threaddata()->MAXSOCKS; i++) if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock) socklist[i].flags |= SOCK_PROXYWAIT; /* drummer */ egg_snprintf(s, sizeof s, "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256, (port % 256), x[0], x[1], x[2], x[3], botuser); tputs(sock, s, strlen(botuser) + 9); /* drummer */ } else if (proxy == PROXY_SUN) {
static int make_header(char *buf, int id) { _dns_header.question_count = htons(1); // _dns_header.id = htons(id); _dns_header.id = id; egg_memcpy(buf, &_dns_header, HEAD_SIZE); return(HEAD_SIZE); }
char * strdup(const char *entry) { size_t len = strlen(entry); char *target = (char *) my_calloc(1, len + 1); if (target == NULL) return NULL; target[len] = 0; return (char *) egg_memcpy(target, entry, len); }
/* Walk through every dcc entry and look for waiting DNS requests * of RES_IPBYHOST for our hostname. */ static void dns_dccipbyhost(sockname_t *ip, char *hostn, int ok, void *other) { int idx; for (idx = 0; idx < dcc_total; idx++) { if ((dcc[idx].type == &DCC_DNSWAIT) && (dcc[idx].u.dns->dns_type == RES_IPBYHOST) && !egg_strcasecmp(dcc[idx].u.dns->host, hostn)) { if (ok) { if (dcc[idx].u.dns->ip) egg_memcpy(dcc[idx].u.dns->ip, ip, sizeof(sockname_t)); else egg_memcpy(&dcc[idx].sockname, ip, sizeof(sockname_t)); dcc[idx].u.dns->dns_success(idx); } else dcc[idx].u.dns->dns_failure(idx); } } }
char * strldup(const char *entry, size_t maxlen) { size_t slen = strlen(entry); size_t len = slen < maxlen ? slen : maxlen; char *target = (char *) my_calloc(1, len + 1); if (target == NULL) return NULL; target[len] = 0; return (char *) egg_memcpy(target, entry, len); }
static int reverse_ip(const char *host, char *reverse) { char *period; int offset, len; period = strchr(host, '.'); if (!period) { len = strlen(host); egg_memcpy(reverse, host, len); return(len); } else { len = period - host; offset = reverse_ip(host+len+1, reverse); reverse[offset++] = '.'; egg_memcpy(reverse+offset, host, len); reverse[offset+len] = 0; return(offset+len); } }
static int read_thing(char *buf, char *ip) { int skip, len; skip = strspn(buf, separators); buf += skip; len = strcspn(buf, separators); egg_memcpy(ip, buf, len); ip[len] = 0; return(skip + len); }
/* Remove entry from dcc list. Think twice before using this function, * because it invalidates any variables that point to a specific dcc * entry! * * Note: The entry will be deconstructed if it was not deconstructed * already. This case should normally not occur. */ void removedcc(int n) { if (dcc[n].type && dcc[n].type->kill) dcc[n].type->kill(n, dcc[n].u.other); else if (dcc[n].u.other) nfree(dcc[n].u.other); dcc_total--; if (n < dcc_total) egg_memcpy(&dcc[n], &dcc[dcc_total], sizeof(struct dcc_t)); else egg_bzero(&dcc[n], sizeof(struct dcc_t)); /* drummer */ }
static void cache_del(int id) { answer_free(&cache[id].answer); free(cache[id].query); cache[id].expiretime = 0; ncache--; if (id < ncache) egg_memcpy(&cache[id], &cache[ncache], sizeof(dns_cache_t)); else egg_bzero(&cache[id], sizeof(dns_cache_t)); cache = (dns_cache_t *) my_realloc(cache, (ncache+1)*sizeof(*cache)); }
void str_redup(char **str, const char *newstr) { size_t len; if (!newstr) { if (*str) free(*str); *str = NULL; return; } len = strlen(newstr) + 1; *str = (char *) my_realloc(*str, len); egg_memcpy(*str, newstr, len); }
static int cut_host(const char *host, char *query) { char *period, *orig; int len; orig = query; while ((period = strchr(host, '.'))) { len = period - host; if (len > 63) return(-1); *query++ = len; egg_memcpy(query, host, len); query += len; host = period+1; } len = strlen(host); if (len) { *query++ = len; egg_memcpy(query, host, len); query += len; } *query++ = 0; return(query-orig); }
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) 2010 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)); #ifdef TLS ssl_init(); #endif 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)); getvhost(&dcc[n].sockname, AF_INET); 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); } }
/* Called once a second. * * Note: Try to not put any Context lines in here (guppy 21Mar2000). */ static void core_secondly() { static int cnt = 0; int miltime; do_check_timers(&utimer); /* Secondly timers */ cnt++; if (cnt >= 10) { /* Every 10 seconds */ cnt = 0; check_expired_dcc(); if (con_chan && !backgrd) { dprintf(DP_STDOUT, "\033[2J\033[1;1H"); tell_verbose_status(DP_STDOUT); do_module_report(DP_STDOUT, 0, "server"); do_module_report(DP_STDOUT, 0, "channels"); tell_mem_status_dcc(DP_STDOUT); } } egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm)); if (nowtm.tm_min != lastmin) { int i = 0; /* Once a minute */ lastmin = (lastmin + 1) % 60; call_hook(HOOK_MINUTELY); check_expired_ignores(); autolink_cycle(NULL); /* Attempt autolinks */ /* In case for some reason more than 1 min has passed: */ while (nowtm.tm_min != lastmin) { /* Timer drift, dammit */ debug2("timer: drift (lastmin=%d, now=%d)", lastmin, nowtm.tm_min); i++; lastmin = (lastmin + 1) % 60; call_hook(HOOK_MINUTELY); } if (i > 1) putlog(LOG_MISC, "*", "(!) timer drift -- spun %d minutes", i); miltime = (nowtm.tm_hour * 100) + (nowtm.tm_min); if (((int) (nowtm.tm_min / 5) * 5) == (nowtm.tm_min)) { /* 5 min */ call_hook(HOOK_5MINUTELY); check_botnet_pings(); if (!quick_logs) { flushlogs(); check_logsize(); } if (!miltime) { /* At midnight */ char s[25]; int j; strncpyz(s, ctime(&now), sizeof s); if (quiet_save < 3) putlog(LOG_ALL, "*", "--- %.11s%s", s, s + 20); call_hook(HOOK_BACKUP); for (j = 0; j < max_logs; j++) { if (logs[j].filename != NULL && logs[j].f != NULL) { fclose(logs[j].f); logs[j].f = NULL; } } } } if (nowtm.tm_min == notify_users_at) call_hook(HOOK_HOURLY); /* These no longer need checking since they are all check vs minutely * settings and we only get this far on the minute. */ if (miltime == switch_logfiles_at) { call_hook(HOOK_DAILY); if (!keep_all_logs) { if (quiet_save < 3) putlog(LOG_MISC, "*", MISC_LOGSWITCH); for (i = 0; i < max_logs; i++) if (logs[i].filename) { char s[1024]; if (logs[i].f) { fclose(logs[i].f); logs[i].f = NULL; } egg_snprintf(s, sizeof s, "%s.yesterday", logs[i].filename); unlink(s); movefile(logs[i].filename, s); } } } } }
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; } } }
/* Called once a second. */ static void core_secondly() { static int cnt = 0; int miltime; check_timers(&utimer); /* Secondly timers */ cnt++; if (cnt >= 10) { /* Every 10 seconds */ cnt = 0; check_expired_dcc(); if (con_chan && !backgrd) { dprintf(DP_STDOUT, "\033[2J\033[1;1H"); tell_verbose_status(DP_STDOUT); do_module_report(DP_STDOUT, 0, "server"); do_module_report(DP_STDOUT, 0, "channels"); tell_mem_status(DP_STDOUT); } } egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm)); if (nowtm.tm_min != lastmin) { int i = 0; /* Once a minute */ lastmin = (lastmin + 1) % 60; call_hook(HOOK_MINUTELY); check_expired_ignores(); autolink_cycle(NULL); /* Attempt autolinks. */ /* In case for some reason more than 1 min has passed: */ while (nowtm.tm_min != lastmin) { /* Timer drift, dammit */ debug2("timer: drift (lastmin=%d, now=%d)", lastmin, nowtm.tm_min); i++; lastmin = (lastmin + 1) % 60; call_hook(HOOK_MINUTELY); } if (i > 1) putlog(LOG_MISC, "*", "(!) timer drift -- spun %d minutes", i); miltime = (nowtm.tm_hour * 100) + nowtm.tm_min; if (((int) (nowtm.tm_min / 5) * 5) == nowtm.tm_min) { /* 5-minutely. */ call_hook(HOOK_5MINUTELY); check_botnet_pings(); flush_and_check_logs(LOGS_FIVEMINUTELY); /* Is it midnight? */ if (miltime == MILTIME_MIDNIGHT) { char s[25]; strncpyz(s, ctime(&now), sizeof s); putlog(LOG_ALL, "*", "--- %.11s%s", s, s + 20); call_hook(HOOK_BACKUP); close_logs_at_midnight(); } } if (nowtm.tm_min == notify_users_at) call_hook(HOOK_HOURLY); if (miltime == switch_logfiles_at) { call_hook(HOOK_DAILY); switch_logs(); } } }
static int parse_reply(char *response, size_t nbytes) { dns_header_t header; dns_query_t *q = NULL, *prev = NULL; dns_rr_t reply; char result[512] = ""; short rr; int r = -1; unsigned const char *eop = (unsigned char *) response + nbytes; unsigned char *ptr = (unsigned char *) response; egg_memcpy(&header, ptr, HEAD_SIZE); ptr += HEAD_SIZE; /* header.id is already in our order, echoed by the server */ header.flags = ntohs(header.flags); header.question_count = ntohs(header.question_count); header.answer_count = ntohs(header.answer_count); header.ar_count = ntohs(header.ar_count); header.ns_count = ntohs(header.ns_count); // print_header(header); /* Find our copy of the query before proceeding. */ for (q = query_head; q; q = q->next) { if (q->id == header.id) break; prev = q; } if (!q) return 0; // /* destroy our async timeout */ // timer_destroy(q->timer_id); /* Pass over the questions. */ for (rr = 0; rr < header.question_count; rr++) { ptr += skip_name(ptr); ptr += 4; } /* End of questions. */ // for (rr = 0; rr < header.answer_count + header.ar_count + header.ns_count; rr++) { q->answers += header.answer_count; for (rr = 0; rr < header.answer_count; rr++) { result[0] = 0; /* Read in the answer. */ ptr += skip_name(ptr); egg_memcpy(&reply, ptr, RR_SIZE); ptr += RR_SIZE; reply.type = ntohs(reply.type); reply.dclass = ntohs(reply.dclass); reply.rdlength = ntohs(reply.rdlength); reply.ttl = ntohl(reply.ttl); /* Save the lowest ttl */ if (reply.ttl && ((!q->answer.ttl) || (q->answer.ttl > reply.ttl))) q->answer.ttl = reply.ttl; // print_reply(reply); switch (reply.type) { case DNS_A: egg_inet_ntop(AF_INET, ptr, result, 512); answer_add(&q->answer, result); break; case DNS_AAAA: #ifdef USE_IPV6 egg_inet_ntop(AF_INET6, ptr, result, 512); answer_add(&q->answer, result); #endif /* USE_IPV6 */ break; case DNS_PTR: r = my_dn_expand((const unsigned char *) response, eop, ptr, result, sizeof(result)); if (r != -1 && result[0]) answer_add(&q->answer, result); break; default: sdprintf("Unhandled DNS reply type: %d", reply.type); break; } ptr += reply.rdlength; if ((size_t) (ptr - (unsigned char*) response) > nbytes) { sdprintf("MALFORMED/TRUNCATED DNS PACKET detected (need TCP)."); q->remaining = 0; break; } } /* Don't continue if we haven't gotten all expected replies. */ if (--q->remaining > 0) return 0; if (q->answer.len == 0) { sdprintf("Failed to get any answers for query"); if (prev) prev->next = q->next; else query_head = q->next; q->callback(q->id, q->client_data, q->query, NULL); free(q->query); if (q->ip) free(q->ip); free(q); return 1; /* get a new server */ } /* Ok, we have, so now issue the callback with the answers. */ if (prev) prev->next = q->next; else query_head = q->next; cache_add(q->query, &q->answer); q->callback(q->id, q->client_data, q->query, q->answer.list); answer_free(&q->answer); free(q->query); if (q->ip) free(q->ip); free(q); return(0); }