Thread: [srvx-commits] CVS: services/src uplink.c,1.8,1.9 tools.h,1.10,1.11 tools.c,1.90,1.91 timeq.c,1.10,1
Brought to you by:
entrope
Update of /cvsroot/srvx/services/src In directory usw-pr-cvs1:/tmp/cvs-serv32442/src Modified Files: uplink.c tools.h tools.c timeq.c sockcheck.h sockcheck.c recdb.c proto_ircu_p10.c proto_bahamut.c proto.h opserv.help opserv.c nickserv.help nickserv.h nickserv.c nickserv-not.help modules.c messages.h main.c helpfile.h helpfile.c hash.h hash.c global.c gline.h gline.c config.h.in compat.h compat.c common.h chanserv.help chanserv.h chanserv.c alias.h alias.c Makefile.am Log Message: merge more 1.0 branch changes onto trunk Index: uplink.c =================================================================== RCS file: /cvsroot/srvx/services/src/uplink.c,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -r1.8 -r1.9 *** uplink.c 2001/08/10 05:08:16 1.8 --- uplink.c 2001/08/19 03:06:09 1.9 *************** *** 2,5 **** --- 2,6 ---- #include <errno.h> #include <netdb.h> + #include <stdarg.h> #include <stdlib.h> #include <unistd.h> *************** *** 27,30 **** --- 28,32 ---- enum uplink_state state; int tries; + int max_tries; long flags; *************** *** 48,51 **** --- 50,54 ---- struct uplink_manager cManager; unsigned int lines_processed; + int max_cycles; static char replay_line[MAXLEN+80]; *************** *** 76,79 **** --- 79,84 ---- cManager.enabled += enabled; + str = database_get_data(rd->d.object, "max_tries", RECDB_QSTRING); + uplink->max_tries = str ? atoi(str) : 3; uplink->flags = enabled ? 0 : UPLINK_UNAVAILABLE; uplink->state = DISCONNECTED; *************** *** 129,132 **** --- 134,140 ---- oldUplinks = cManager.uplinks; + rd = conf_get_node("server/max_cycles"); + max_cycles = rd ? atoi(rd->d.qstring) : 30; + rd = conf_get_node("uplinks"); if (!rd || rd->type != RECDB_OBJECT) { *************** *** 185,190 **** cManager.cycles++; ! /* TODO: Make this limit of 30 cycles configurable. */ ! if (cManager.cycles > 30) { log(MAIN_LOG, LOG_ERROR, "Maximum uplink list cycles exceeded; giving up.\n"); exit(1); --- 193,197 ---- cManager.cycles++; ! if (cManager.cycles > max_cycles) { log(MAIN_LOG, LOG_ERROR, "Maximum uplink list cycles exceeded; giving up.\n"); exit(1); *************** *** 319,324 **** irc_introduce(uplink->password); } else { ! /* TODO: Make this limit of 3 tries per uplink configurable. */ ! if (uplink->tries > 3) { /* This is a bad uplink, move on. */ uplink->flags |= UPLINK_UNAVAILABLE; --- 326,330 ---- irc_introduce(uplink->password); } else { ! if (uplink->tries > uplink->max_tries) { /* This is a bad uplink, move on. */ uplink->flags |= UPLINK_UNAVAILABLE; Index: tools.h =================================================================== RCS file: /cvsroot/srvx/services/src/tools.h,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -r1.10 -r1.11 *** tools.h 2001/08/19 01:28:39 1.10 --- tools.h 2001/08/19 03:06:09 1.11 *************** *** 46,53 **** int mmatch(const char *glob, const char *newglob); int match_ircglob(const char *text, const char *glob); int is_ircmask(const unsigned char *text); int is_gline(const unsigned char *text); ! char* generate_hostmask(struct userNode *user, int strict, int wildnick); unsigned long ParseInterval(const unsigned char *interval); unsigned long ParseVolume(const unsigned char *volume); --- 46,62 ---- int mmatch(const char *glob, const char *newglob); int match_ircglob(const char *text, const char *glob); + int user_matches_glob(struct userNode *user, const char *glob, int include_nick); int is_ircmask(const unsigned char *text); int is_gline(const unsigned char *text); ! ! /* The "default" for generate_hostmask is to have all of these options off. */ ! #define GENMASK_STRICT 1 ! #define GENMASK_USENICK 2 ! #define GENMASK_OMITNICK 4 /* Hurray for Kevin! */ ! #define GENMASK_BYIP 8 ! #define GENMASK_SRVXMASK 16 ! char *generate_hostmask(struct userNode *user, int options); ! unsigned long ParseInterval(const unsigned char *interval); unsigned long ParseVolume(const unsigned char *volume); *************** *** 73,81 **** DECLARE_LIST(string_buffer, char); void string_buffer_append_string(struct string_buffer *buf, const char *tail); - int string_buffer_sprintf(struct string_buffer *buf, const char *format, va_list al); void string_buffer_replace(struct string_buffer *buf, unsigned int from, unsigned int len, const char *repl); int make_chanmode(struct chanNode *chan, char *out, int len); int make_usermode(struct userNode *user, char *out, int len); #endif /* ifdef _TOOLS_H_ */ --- 82,91 ---- DECLARE_LIST(string_buffer, char); void string_buffer_append_string(struct string_buffer *buf, const char *tail); void string_buffer_replace(struct string_buffer *buf, unsigned int from, unsigned int len, const char *repl); int make_chanmode(struct chanNode *chan, char *out, int len); int make_usermode(struct userNode *user, char *out, int len); + + char *intoa(unsigned long addr); #endif /* ifdef _TOOLS_H_ */ Index: tools.c =================================================================== RCS file: /cvsroot/srvx/services/src/tools.c,v retrieving revision 1.90 retrieving revision 1.91 diff -C2 -r1.90 -r1.91 *** tools.c 2001/08/19 01:28:39 1.90 --- tools.c 2001/08/19 03:06:09 1.91 *************** *** 44,49 **** --- 44,56 ---- #include <sys/socket.h> #endif + #ifdef HAVE_NETINET_IN_H + #include <netinet/in.h> + #endif + #ifdef HAVE_ARPA_INET_H + #include <arpa/inet.h> + #endif #include "hash.h" + #include "log.h" #include "policer.h" #include "recdb.h" *************** *** 86,91 **** static unsigned char channel_inverse_modes[256]; - static int - void mod_usermode(struct userNode *user, const char *mode_change) { --- 93,96 ---- *************** *** 133,137 **** make_usermode(struct userNode *user, char *out, int len) { ! } --- 138,142 ---- make_usermode(struct userNode *user, char *out, int len) { ! /* TODO */ } *************** *** 389,414 **** } - void - fix_glob(char *dest, const char *src) - { - unsigned int i, j, star_p, q_cnt; - i = j = 0; - while (1) { - star_p = q_cnt = 0; - do { - if (src[i] == '*') star_p = 1; - else if (src[i] == '?') q_cnt++; - else break; - i++; - } while (1); - while (q_cnt) { dest[j++] = '?'; q_cnt--; } - if (star_p) dest[j++] = '*'; - if (!(dest[j++] = src[i++])) break; - } - } - int ! inner_ircglob(const char *text, const char *glob) { while (1) { switch (*glob) { --- 394,401 ---- } int ! match_ircglob(const char *text, const char *glob) { + unsigned int star_p, q_cnt; while (1) { switch (*glob) { *************** *** 416,440 **** return !*text; case '*': ! /* if this is the last glob character, it will match any text */ ! if (!glob[1]) return 1; ! /* fix_glob guarantees that we'll never see *?, so we don't ! * need logic for that -- we know that the next character is ! * a normal character. So just look for the right character. ! */ ! for (; *text; text++) { ! if ((tolower(*text) == tolower(glob[1])) ! && (inner_ircglob(text, glob+1))) { ! return 1; } } ! return 0; ! case '?': ! if (!*text) return 0; ! text++; glob++; break; default: if (!*text) return 0; while (*text && *glob && *glob != '*' && *glob != '?') { ! if (tolower(*text) != tolower(*glob)) return 0; ! text++; glob++; } } --- 403,437 ---- return !*text; case '*': ! case '?': ! star_p = q_cnt = 0; ! do { ! if (*glob == '*') star_p = 1; ! else if (*glob == '?') q_cnt++; ! else break; ! glob++; ! } while (1); ! while (q_cnt) { if (!*text++) return 0; q_cnt--; } ! if (star_p) { ! /* if this is the last glob character, it will match any text */ ! if (!*glob) return 1; ! /* Thanks to the loop above, we know that the next ! * character is a normal character. So just look for ! * the right character. ! */ ! for (; *text; text++) { ! if ((tolower(*text) == tolower(*glob)) ! && match_ircglob(text+1, glob+1)) { ! return 1; ! } } + return 0; } ! /* if !star_p, fall through to normal character case, ! * first checking to see if ?s carried us to the end */ ! if (!*glob && !*text) return 1; default: if (!*text) return 0; while (*text && *glob && *glob != '*' && *glob != '?') { ! if (tolower(*text++) != tolower(*glob++)) return 0; } } *************** *** 443,470 **** int ! match_ircglob(const char *text, const char *glob) { ! char *newglob = alloca(strlen(glob)+1); ! fix_glob(newglob, glob); ! return inner_ircglob(text, newglob); ! } ! ! int ! glob_valid(const char *glob, unsigned int require) ! { ! unsigned int non_wildcard = 0; ! ! while (*glob++) { ! switch (*glob) { ! case '*': ! case '?': ! break; ! default: ! non_wildcard++; ! break; ! } } - - return non_wildcard > require; } --- 440,477 ---- int ! user_matches_glob(struct userNode *user, const char *orig_glob, int include_nick) { ! char *glob, *marker; ! /* Make a writable copy of the glob */ ! glob = alloca(strlen(orig_glob)+1); ! strcpy(glob, orig_glob); ! /* Check the nick, if it's present */ ! if (include_nick) { ! if (!(marker = strchr(glob, '!'))) { ! log(MAIN_LOG, LOG_ERROR, "match_glob_user(\"%s\", \"%s\", %d) called, and glob doesn't include a '!'\n", user->nick, orig_glob, include_nick); ! return 0; ! } ! *marker = 0; ! if (!match_ircglob(user->nick, glob)) return 0; ! glob = marker + 1; ! } ! /* Check the ident */ ! if (!(marker = strchr(glob, '@'))) { ! log(MAIN_LOG, LOG_ERROR, "match_glob_user(\"%s\", \"%s\", %d) called, and glob doesn't include an '@'\n", user->nick, orig_glob, include_nick); ! return 0; ! } ! *marker = 0; ! if (!match_ircglob(user->username, glob)) return 0; ! glob = marker + 1; ! /* Now check the host part */ ! if (isdigit(*glob) && !glob[strspn(glob, "0123456789./*?")]) { ! /* Looks like an IP-based mask */ ! unsigned char userip[20]; ! sprintf(userip, "%ld.%ld.%ld.%ld", (user->ip >> 24) & 255, (user->ip >> 16) & 255, (user->ip >> 8) & 255, user->ip & 255); ! return match_ircglob(userip, glob); ! } else { ! /* The host part of the mask isn't IP-based */ ! return match_ircglob(user->hostname, glob); } } *************** *** 512,563 **** } ! char* ! generate_hostmask(struct userNode *user, int strict, int wildnick) { ! char *mask = malloc(NICKLEN+USERLEN+HOSTLEN+3); ! int ofs = (user->username[0] == '~' && !strict) ? 1 : 0; ! const char *nickname = wildnick ? "*" : user->nick; ! const char *username = user->username + ofs; ! const char *hostname = user->hostname; ! ! if (strict) { ! sprintf(mask, "%s!%s@%s", nickname, username, hostname); } else { ! int i, cnt; ! ! if (strspn(hostname, "0123456789.") == strlen(hostname)) { ! /* It's an IP address, treat it as such */ ! char *lastdot = strrchr(hostname, '.'); ! if (lastdot) { ! int len = lastdot + 1 - hostname; ! char *temphost = alloca(len); ! memcpy(temphost, hostname, len-1); ! temphost[len-1] = 0; ! sprintf(mask, "%s!*%s@%s.*", nickname, username, temphost); ! } else { ! /* An all-numeric IP.. this shouldn't happen */ ! sprintf(mask, "%s!*%s@%s", nickname, username, hostname); } ! return mask; } /* This heuristic could be made smarter. Is it worth the effort? */ ! for (i=cnt=0; user->hostname[i]; i++) { ! if (user->hostname[i] == '.') cnt++; ! } if (cnt == 1) { ! /* only a two-level domain name */ ! sprintf(mask, "%s!*%s@%s", nickname, username, hostname); } else if (cnt == 2) { ! for (i=0; user->hostname[i] != '.'; i++) ; ! hostname = user->hostname+i+1; ! sprintf(mask, "%s!*%s@*.%s", nickname, username, hostname); } else { ! for (cnt=3, i--; cnt; i--) { ! if (user->hostname[i] == '.') cnt--; } ! hostname = user->hostname+i+2; ! sprintf(mask, "%s!*%s@*.%s", nickname, username, hostname); } } return mask; } --- 519,601 ---- } ! char * ! generate_hostmask(struct userNode *user, int options) { ! char *nickname, *username, *hostname; ! char *mask; ! int len, ii; ! ! /* figure out string parts */ ! if (options & GENMASK_OMITNICK) { ! nickname = NULL; ! } else if (options & GENMASK_USENICK) { ! nickname = user->nick; } else { ! nickname = "*"; ! } ! if (options & GENMASK_STRICT) { ! username = user->username; ! } else { ! username = alloca(strlen(user->username)+2); ! username[0] = '*'; ! strcpy(username+1, user->username + ((*user->username == '~')?1:0)); ! } ! hostname = user->hostname; ! if (options & GENMASK_STRICT) { ! /* leave hostname as is */ ! } else if ((options & GENMASK_BYIP) || !hostname[strspn(hostname, "0123456789.")]) { ! /* Should generate an IP-based hostmask. By popular acclaim, a /16 ! * hostmask is used by default. */ ! unsigned masked_ip, mask, masklen; ! masklen = 16; ! mask = ~0 << masklen; ! masked_ip = user->ip & mask; ! hostname = alloca(32); ! if (options & GENMASK_SRVXMASK) { ! sprintf(hostname, "%d.%d.%d.%d/%d", (masked_ip>>24)&0xFF, (masked_ip>>16)&0xFF, (masked_ip>>8)&0xFF, masked_ip&0xFF, masklen); ! } else { ! int ofs = 0; ! for (ii=0; ii<4; ii++) { ! if (masklen) { ! ofs += sprintf(hostname+ofs, "%d.", (masked_ip>>24)&0xFF); ! masklen -= 8; ! masked_ip <<= 8; ! } else { ! ofs += sprintf(hostname+ofs, "*."); ! } } ! /* Truncate the last . */ ! hostname[ofs-1] = 0; } + } else { + int cnt; /* This heuristic could be made smarter. Is it worth the effort? */ ! for (ii=cnt=0; hostname[ii]; ii++) { ! if (hostname[ii] == '.') cnt++; ! } if (cnt == 1) { ! /* only a two-level domain name; leave hostname */ } else if (cnt == 2) { ! for (ii=0; user->hostname[ii] != '.'; ii++) ; ! hostname = alloca(strlen(user->hostname+ii)+2); ! sprintf(hostname, "*%s", user->hostname+ii+1); } else { ! for (cnt=3, ii--; cnt; ii--) { ! if (user->hostname[ii] == '.') cnt--; } ! hostname = alloca(strlen(user->hostname+ii)+2); ! sprintf(hostname, "*%s", user->hostname+ii+1); } } + /* Emit hostmask */ + len = strlen(username) + strlen(hostname) + 2; + if (nickname) { + len += strlen(nickname) + 1; + mask = malloc(len); + sprintf(mask, "%s!%s@%s", nickname, username, hostname); + } else { + mask = malloc(len); + sprintf(mask, "%s@%s", username, hostname); + } return mask; } *************** *** 675,679 **** } if (pos != start+accum) return 0; ! } else if(*str == 0) { break; } else { --- 713,717 ---- } if (pos != start+accum) return 0; ! } else if (*str == 0) { break; } else { *************** *** 788,814 **** } - int ban_match_user(struct userNode *user, char *ban) - { - int match = 0; - char *hostmask = generate_hostmask(user, 1, 0); - match = match_ircglob(hostmask, ban); - free(hostmask); - - if(match) return 1; - - hostmask = alloca(16); - sprintf(hostmask, "%d.%d.%d.%d", (int)((user->ip >> 24) & 255), (int)((user->ip >> 16) & 255), (int)((user->ip >> 8) & 255), (int)(user->ip & 255)); - return match_ircglob(hostmask, ban); - } - - int ban_match_user_host(struct userNode *user, char *hostmask, char *ban) - { - if(match_ircglob(hostmask, ban)) return 1; - - hostmask = alloca(16); - sprintf(hostmask, "%d.%d.%d.%d", (int)((user->ip >> 24) & 255), (int)((user->ip >> 16) & 255), (int)((user->ip >> 8) & 255), (int)(user->ip & 255)); - return match_ircglob(hostmask, ban); - } - int set_policer_param(const char *param, void *data, void *extra) --- 826,829 ---- *************** *** 834,862 **** } - int - string_buffer_sprintf(struct string_buffer *buf, const char *format, va_list al) { - int ret; - /* Normally, I'd pass NULL as the first parameter to vsnprintf. - * But guess what? It makes FreeBSD's libc allocate a buffer that it - * never frees! Surprise! - * The kludge-around is to pass a non-NULL pointer instead. - */ - if ((ret = vsnprintf((char*)&ret, 0, format, al)) <= 0) { - /* non-C99 behavior */ - buf->size = strlen(format); - buf->list = malloc(buf->size); - while ((ret = vsnprintf(buf->list, buf->size, format, al)) == -1) { - buf->size <<= 1; - buf->list = realloc(buf->list, buf->size); - } - } else { - /* C99 is nice about how vsnprintf fails */ - buf->size = ret + 1; - buf->list = malloc(buf->size); - ret = vsnprintf(buf->list, buf->size, format, al); - } - return buf->used = ret; - } - void string_buffer_replace(struct string_buffer *buf, unsigned int from, unsigned int len, const char *repl) --- 849,852 ---- *************** *** 874,877 **** --- 864,874 ---- memmove(buf->list+from+repl_len, buf->list+from+len, strlen(buf->list+from+len)); strcpy(buf->list+from, repl); + } + + char *intoa(unsigned long addr) { + struct in_addr in; + + in.s_addr = addr; + return inet_ntoa(in); } Index: timeq.c =================================================================== RCS file: /cvsroot/srvx/services/src/timeq.c,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -r1.10 -r1.11 *** timeq.c 2001/06/11 22:54:07 1.10 --- timeq.c 2001/08/19 03:06:09 1.11 *************** *** 25,28 **** --- 25,62 ---- #include "common.h" + #if HAVE_PTHREAD_H && SOCKCHECK_USABLE /* we could have multiple threads setting glines */ + #include <pthread.h> + /* Sigh. Want recursive mutexes in standard! + * (The timeq mutex needs to be recursive since callers frequently do timeq_add from + * within timeq_run() callbacks.) */ + static pthread_mutex_t timeq_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_cond_t timeq_condvar = PTHREAD_COND_INITIALIZER; + static pthread_t timeq_locker; + static int timeq_mutex_count; + + static void + timeq_mutex_lock(void) { + pthread_mutex_lock(&timeq_mutex); + if ((timeq_mutex_count > 0) && (timeq_locker != pthread_self())) { + pthread_cond_wait(&timeq_condvar, &timeq_mutex); + } + timeq_locker = pthread_self(); + timeq_mutex_count++; + pthread_mutex_unlock(&timeq_mutex); + } + + static void + timeq_mutex_unlock(void) { + pthread_mutex_lock(&timeq_mutex); + timeq_mutex_count--; + if (!timeq_mutex_count) pthread_cond_signal(&timeq_condvar); + pthread_mutex_unlock(&timeq_mutex); + } + + #else + #define timeq_mutex_lock() /*noop*/ + #define timeq_mutex_unlock() /*noop*/ + #endif + #include "heap.h" #include "timeq.h" *************** *** 53,57 **** --- 87,93 ---- { time_t time; + timeq_mutex_lock(); heap_peek(timeq, &time, NULL); + timeq_mutex_unlock(); return time; } *************** *** 63,67 **** --- 99,105 ---- ent->func = func; ent->data = data; + timeq_mutex_lock(); heap_insert(timeq, when, ent); + timeq_mutex_unlock(); } *************** *** 73,77 **** }; ! int timeq_del_matching(time_t key, void *data, void *extra) { --- 111,115 ---- }; ! static int timeq_del_matching(time_t key, void *data, void *extra) { *************** *** 93,97 **** --- 131,137 ---- extra.data = data; extra.mask = mask; + timeq_mutex_lock(); heap_remove_pred(timeq, timeq_del_matching, &extra); + timeq_mutex_unlock(); } *************** *** 102,105 **** --- 142,146 ---- void *d; struct timeq_entry *ent; + timeq_mutex_lock(); while (1) { heap_peek(timeq, &k, &d); *************** *** 110,112 **** --- 151,154 ---- free(ent); } + timeq_mutex_unlock(); } Index: sockcheck.h =================================================================== RCS file: /cvsroot/srvx/services/src/sockcheck.h,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -r1.7 -r1.8 *** sockcheck.h 2001/03/30 21:20:10 1.7 --- sockcheck.h 2001/08/19 03:06:09 1.8 *************** *** 29,32 **** --- 29,33 ---- unsigned int pending_ip_count; unsigned int test_count; + unsigned int cached_ip_count; }; Index: sockcheck.c =================================================================== RCS file: /cvsroot/srvx/services/src/sockcheck.c,v retrieving revision 1.59 retrieving revision 1.60 diff -C2 -r1.59 -r1.60 *** sockcheck.c 2001/08/01 22:14:35 1.59 --- sockcheck.c 2001/08/19 03:06:09 1.60 *************** *** 57,68 **** #include "conf.h" #include "dict.h" #include "log.h" #include "recdb.h" - #include "tools.h" #include "sockcheck.h" static int disable_sockcheck; ! #if defined(HAVE_POLL) && defined(HAVE_PTHREAD) && !defined(__CYGWIN__) #if !defined(SOCKCHECK_DEBUG) --- 57,70 ---- #include "conf.h" #include "dict.h" + #include "gline.h" #include "log.h" #include "recdb.h" #include "sockcheck.h" + #include "tools.h" + #include "uplink.h" static int disable_sockcheck; ! #if SOCKCHECK_USABLE #if !defined(SOCKCHECK_DEBUG) *************** *** 91,94 **** --- 93,99 ---- } *sockcheck_cache_info; + DECLARE_LIST(sci_list, sockcheck_cache_info); + DEFINE_LIST(sci_list, sockcheck_cache_info); + /* And here's the list of hostnames that need to be started on. * This is primarily used by the worker thread, although the main *************** *** 129,132 **** --- 134,138 ---- unsigned short port; unsigned short timeout; + unsigned short reps; enum sockcheck_decision type; const char *template; *************** *** 146,149 **** --- 152,156 ---- sockcheck_cache_info addr; unsigned int test_index; + unsigned short test_rep; struct sockcheck_state *state; unsigned int send_size, send_used, send_pos; *************** *** 168,173 **** static unsigned int sockcheck_num_sockets; static struct pollfd *poll_list; ! static struct sockcheck_client *client_list; static struct timeval tv_now; static unsigned int proxies_detected, checked_ip_count; --- 175,181 ---- static unsigned int sockcheck_num_sockets; static struct pollfd *poll_list; ! static struct sockcheck_client **client_list; static struct timeval tv_now; + static time_t last_clean; static unsigned int proxies_detected, checked_ip_count; *************** *** 220,224 **** strcpy(target+2, sci->hostname); log(PC_LOG, LOG_INFO, "Issuing gline for client at IP %08lx hostname %s: %s\n", sci->addr, sci->hostname, sci->reason); ! irc_gline(target, 3600, sci->reason); } --- 228,232 ---- strcpy(target+2, sci->hostname); log(PC_LOG, LOG_INFO, "Issuing gline for client at IP %08lx hostname %s: %s\n", sci->addr, sci->hostname, sci->reason); ! gline_add("ProxyCheck", target, 3600, sci->reason, 1); } *************** *** 266,269 **** --- 274,285 ---- { int res; + sockcheck_cache_info sci; + + if ((sci = dict_find(checked_ip_dict, name, NULL))) { + if ((sci->decision == PENDING) || (sci->decision == CHECKING)) { + return -1; + } + } + if (pthread_mutex_lock(&checked_ip_mutex)) { /* lock failure; this usually means coding error */ *************** *** 348,353 **** /* TODO: consider allowing non-NULL p_expansion with non-zero p_exp_length, ! * to avoid the malloc() impact. if it's important for speed. ! */ static void expand_var(const struct sockcheck_client *client, unsigned char var, unsigned char **p_expansion, unsigned int *p_exp_length) --- 364,368 ---- /* TODO: consider allowing non-NULL p_expansion with non-zero p_exp_length, ! * to avoid the malloc() impact. If it's important for speed. */ static void expand_var(const struct sockcheck_client *client, unsigned char var, unsigned char **p_expansion, unsigned int *p_exp_length) *************** *** 364,369 **** /* expand variable */ switch (var) { case 'i': ! exp4 = htonl(client->addr->addr); exp_length = sizeof(exp4); expansion = (unsigned char*)&exp4; --- 379,388 ---- /* expand variable */ switch (var) { + case 'c': + expansion = client->addr->hostname; + exp_length = strlen(expansion); + break; case 'i': ! exp4 = client->addr->addr; exp_length = sizeof(exp4); expansion = (unsigned char*)&exp4; *************** *** 374,381 **** expansion = (unsigned char*)&exp2; break; - case 'u': - expansion = self->uplink->name; - exp_length = strlen(expansion); - break; default: expansion = ""; --- 393,396 ---- *************** *** 400,405 **** client->writing = 1; client->send_used = 0; - client->send_size = strlen(template) >> 1; - client->send = malloc(client->send_size); while (*template) { unsigned char *target; --- 415,418 ---- *************** *** 421,425 **** --- 434,440 ---- unsigned int exp_length; expand_var(client, template[1], &expansion, &exp_length); + #if SOCKCHECK_DEBUG log(PC_LOG, LOG_INFO, "Expanded var %c for client %s to \"%s\" (len %d, pos %d)\n", template[1], client->addr->hostname, expansion, exp_length, client->send_used); + #endif if (client->send_used+exp_length >= client->send_size) { do { *************** *** 447,456 **** client->read_pos = 0; client->read_used = 0; - client->read_timeout.tv_sec = tv_now.tv_sec + client->state->timeout / 1000; - client->read_timeout.tv_usec = tv_now.tv_usec + (client->state->timeout % 1000) * 1000; - if (client->read_timeout.tv_usec > 1000000) { - client->read_timeout.tv_sec++; - client->read_timeout.tv_usec -= 1000000; - } #if SOCKCHECK_DEBUG log(PC_LOG, LOG_INFO, "elaborated state: "); --- 462,465 ---- *************** *** 465,479 **** sockcheck_begin_test(unsigned int idx) { ! struct sockcheck_client *client = client_list+idx; struct pollfd *poller = poll_list+idx+1; struct sockaddr_in sin; int flags; client->state = client->tests->list[client->test_index]; if (!client->state) { ! client->test_index++; ! return; } ! poller->events = POLLIN|POLLOUT; poller->revents = 0; /* otherwise we get confused this poll iteration.. */ if ((poller->fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { --- 474,497 ---- sockcheck_begin_test(unsigned int idx) { ! struct sockcheck_client *client = client_list[idx]; struct pollfd *poller = poll_list+idx+1; struct sockaddr_in sin; int flags; + client->connected = 0; client->state = client->tests->list[client->test_index]; if (!client->state) { ! client->test_index++; ! return; } ! ! client->read_timeout.tv_sec = tv_now.tv_sec + client->state->timeout / 1000; ! client->read_timeout.tv_usec = tv_now.tv_usec + (client->state->timeout % 1000) * 1000; ! if (client->read_timeout.tv_usec > 1000000) { ! client->read_timeout.tv_sec++; ! client->read_timeout.tv_usec -= 1000000; ! } ! ! poller->events = POLLIN | POLLOUT; poller->revents = 0; /* otherwise we get confused this poll iteration.. */ if ((poller->fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { *************** *** 498,503 **** } } log(PC_LOG, LOG_INFO, "Starting proxy check on port %d (test %d) for client %s, fd %d\n", client->state->port, client->test_index, client->addr->hostname, poller->fd); ! client->connected = 0; return; --- 516,522 ---- } } + #if SOCKCHECK_DEBUG log(PC_LOG, LOG_INFO, "Starting proxy check on port %d (test %d) for client %s, fd %d\n", client->state->port, client->test_index, client->addr->hostname, poller->fd); ! #endif return; *************** *** 507,519 **** poller->fd = -2; client->state = NULL; - client->test_index++; return; } static int sockcheck_worker_queue_client(unsigned int idx) { sockcheck_cache_info sci; - struct sockcheck_client *client; const char *new_addr; --- 526,562 ---- poller->fd = -2; client->state = NULL; return; } + static struct sockcheck_client * + sockcheck_alloc_client(sockcheck_cache_info sci) + { + struct sockcheck_client *client = malloc(sizeof(*client)); + memset(client, 0, sizeof(*client)); + client->tests = tests; + client->tests->refs++; + client->addr = sci; + client->send_size = 32; + client->send = malloc(client->send_size); + client->read_size = sockcheck_conf.max_read; + client->read = malloc(client->read_size); + client->resp_state = malloc(max_responses * sizeof(client->resp_state[0])); + return client; + } + + static void + sockcheck_free_client(struct sockcheck_client *client) + { + sockcheck_list_unref(client->tests); + free(client->send); + free(client->read); + free(client->resp_state); + free(client); + } + static int sockcheck_worker_queue_client(unsigned int idx) { sockcheck_cache_info sci; const char *new_addr; *************** *** 521,525 **** if (idx == (unsigned)-1) idx = sockcheck_num_sockets; if (idx == sockcheck_conf.max_sockets) return 0; - client = client_list + idx; new_addr = pending_ip_list->list[0]; memmove(pending_ip_list->list, pending_ip_list->list+1, --- 564,567 ---- *************** *** 540,551 **** } if (!tests) return 0; ! log(PC_LOG, LOG_INFO, "Proxy-checking client at %08lx (%s) as client %d (now %d in progress)\n", sci->addr, sci->hostname, idx, sockcheck_num_sockets); ! client->tests = tests; ! client->tests->refs++; ! client->addr = sci; ! client->test_index = 0; ! client->state = NULL; ! client->send_size = 0; ! client->read_used = 0; sockcheck_begin_test(idx); return 1; --- 582,590 ---- } if (!tests) return 0; ! #if SOCKCHECK_DEBUG ! log(PC_LOG, LOG_INFO, "Proxy-checking client at %08x (%s) as client %d (now %d in progress)\n", sci->addr, sci->hostname, idx, sockcheck_num_sockets); ! #endif ! client_list[idx] = sockcheck_alloc_client(sci); ! client_list[idx]->test_rep = 0; sockcheck_begin_test(idx); return 1; *************** *** 555,559 **** sockcheck_decide(unsigned int idx, enum sockcheck_decision decision) { ! struct sockcheck_client *client = client_list+idx; checked_ip_count++; --- 594,599 ---- sockcheck_decide(unsigned int idx, enum sockcheck_decision decision) { ! struct sockcheck_client *client = client_list[idx]; ! unsigned int n; checked_ip_count++; *************** *** 563,581 **** if (decision == ACCEPT) { /* do nothing */ ! log(PC_LOG, LOG_INFO, "Proxy check passed for client at IP %08lx hostname %s\n", client->addr->addr, client->addr->hostname); } else if (decision == REJECT) { proxies_detected++; sockcheck_issue_gline(client->addr); ! log(PC_LOG, LOG_INFO, "Proxy check failed for client at IP %08lx hostname %s (%s)\n", client->addr->addr, client->addr->hostname, client->addr->reason); ! /* don't compare idx != 0 directly, because somebody else may have ! * reordered the tests already ! */ if (client->tests->list[client->test_index] != tests->list[0]) { struct sockcheck_list *new_tests = sockcheck_list_clone(tests); struct sockcheck_state *new_first = client->tests->list[client->test_index]; ! unsigned int n; ! for (n=client->test_index; n>0; n--) { ! new_tests->list[n] = new_tests->list[n-1]; ! } new_tests->list[0] = new_first; sockcheck_list_unref(tests); --- 603,622 ---- if (decision == ACCEPT) { /* do nothing */ ! #if SOCKCHECK_DEBUG ! log(PC_LOG, LOG_INFO, "Proxy check passed for client at IP %08x hostname %s\n", client->addr->addr, client->addr->hostname); ! #endif } else if (decision == REJECT) { proxies_detected++; sockcheck_issue_gline(client->addr); ! #if SOCKCHECK_DEBUG ! log(PC_LOG, LOG_INFO, "Proxy check failed for client at IP %08x hostname %s (%s)\n", client->addr->addr, client->addr->hostname, client->addr->reason); ! #endif ! /* Don't compare idx != 0 directly, because somebody else may have ! * reordered the tests already. */ if (client->tests->list[client->test_index] != tests->list[0]) { struct sockcheck_list *new_tests = sockcheck_list_clone(tests); struct sockcheck_state *new_first = client->tests->list[client->test_index]; ! for (n=0; (n<tests->used) && (tests->list[n] != new_first); n++) ; ! for (; n>0; n--) new_tests->list[n] = new_tests->list[n-1]; new_tests->list[0] = new_first; sockcheck_list_unref(tests); *************** *** 585,599 **** log(PC_LOG, LOG_ERROR, "BUG: sockcheck_decide(\"%s\", %d): unrecognized decision\n", client->addr->hostname, decision); } - sockcheck_list_unref(client->tests); - /* .. and clean up this instance. */ - if (client->send_size) { - #if SOCKCHECK_DEBUG - log(PC_LOG, LOG_INFO, "Freeing client send buffer: size %d used %d buffer %p\n", client->send_size, client->send_used, client->send); - #endif - client->send_size = 0; - client->send_used = 0; - free(client->send); - } - client->addr = NULL; } --- 626,629 ---- *************** *** 619,622 **** --- 649,653 ---- /* read what we can from the fd */ int res; + unsigned int n; res = read(fd, client->read + client->read_used, client->read_size - client->read_used); *************** *** 632,640 **** } /* See if what's been read matches any of the expected responses */ while (client->read_pos < client->read_used) { unsigned char curr, bleh; const unsigned char *resp_state; - unsigned int n; curr = client->read[client->read_pos++]; --- 663,681 ---- } + /* Handle responses that dont require reading */ + if (client->read_pos == client->read_used) { + for (n=0; n<(client->state->responses.used-1); n++) { + /* since we have nothing to read we will never enter the while() loop */ + if (client->resp_state[n] && !strlen(client->resp_state[n])) { + log(PC_LOG, LOG_ERROR, "Choosing response %d for client %s\n", n, client->addr->hostname); + return n; + } + } + } + /* See if what's been read matches any of the expected responses */ while (client->read_pos < client->read_used) { unsigned char curr, bleh; const unsigned char *resp_state; curr = client->read[client->read_pos++]; *************** *** 689,697 **** --- 730,742 ---- if (client->read_used >= client->read_size) { /* we got more data than we expected to get .. don't read any more */ + #if SOCKCHECK_DEBUG log(PC_LOG, LOG_INFO, "Buffer filled (unmatched) for client %s\n", client->addr->hostname); + #endif return client->state->responses.used - 1; } else if (TV_CMP(tv_now, >, client->read_timeout)) { /* read timed out, use default handler. */ + #if SOCKCHECK_DEBUG log(PC_LOG, LOG_INFO, "Read timeout expired for client %s\n", client->addr->hostname); + #endif return client->state->responses.used - 1; } else { *************** *** 705,712 **** sockcheck_advance(unsigned int idx) { ! struct sockcheck_client *client = client_list+idx; struct pollfd *poller = poll_list+idx+1; int next_state = -1; if (!client->connected) { if (poller->revents & POLLHUP) { --- 750,763 ---- sockcheck_advance(unsigned int idx) { ! struct sockcheck_client *client = client_list[idx]; struct pollfd *poller = poll_list+idx+1; int next_state = -1; + if (!client->state) { + /* If we got here with a NULL state, connect() to the client + * previously failed. Advance it to the next test. */ + goto next_test; + } + if (!client->connected) { if (poller->revents & POLLHUP) { *************** *** 715,724 **** close(poller->fd); log(PC_LOG, LOG_ERROR, "Client %s gave us a POLLHUP on fd %d\n", client->addr->hostname, poller->fd); ! if (++client->test_index == client->tests->used) { ! sockcheck_decide(idx, ACCEPT); ! return 1; ! } else { ! sockcheck_begin_test(idx); ! } } else if (poller->revents & (POLLOUT|POLLIN)) { int rc, arglen = sizeof(rc); --- 766,770 ---- close(poller->fd); log(PC_LOG, LOG_ERROR, "Client %s gave us a POLLHUP on fd %d\n", client->addr->hostname, poller->fd); ! goto next_test; } else if (poller->revents & (POLLOUT|POLLIN)) { int rc, arglen = sizeof(rc); *************** *** 729,733 **** --- 775,781 ---- case ECONNREFUSED: case ETIMEDOUT: + #if SOCKCHECK_DEBUG log(PC_LOG, LOG_INFO, "Client %s gave us errno %d (%s)\n", client->addr->hostname, rc, strerror(rc)); + #endif goto disconn; case 0: break; *************** *** 793,797 **** #endif client->state = ns; ! switch(ns->type) { case CHECKING: break; case REJECT: --- 841,845 ---- #endif client->state = ns; ! switch (ns->type) { case CHECKING: break; case REJECT: *************** *** 801,809 **** case ACCEPT: close(poller->fd); ! if (++client->test_index == client->tests->used) { sockcheck_decide(idx, ACCEPT); return 1; - } else { - sockcheck_begin_test(idx); } break; --- 849,861 ---- case ACCEPT: close(poller->fd); ! next_test: ! if (++client->test_rep < client->tests->list[client->test_index]->reps) { ! sockcheck_begin_test(idx); ! } else if (++client->test_index < client->tests->used) { ! client->test_rep = 0; ! sockcheck_begin_test(idx); ! } else { sockcheck_decide(idx, ACCEPT); return 1; } break; *************** *** 816,819 **** --- 868,891 ---- } + static int + find_old_entries(const char *hostname, void *data, void *extra) + { + sockcheck_cache_info sci = data; + struct sci_list *cleaned = extra; + + (void)hostname; + switch (sci->decision) { + case ACCEPT: + case REJECT: + /* Forget anything more than an hour old. */ + if (sci->last_touched < (tv_now.tv_sec - 3600)) sci_list_append(cleaned, sci); + break; + default: + /* Do nothing. */ + break; + } + return 0; + } + static void * sockcheck_worker(void *arg) *************** *** 821,825 **** --- 893,900 ---- int res, timeout, err_count=0; unsigned int n; + struct sci_list cleaned; + (void)arg; + sci_list_init(&cleaned); while (1) { timeout = sockcheck_num_sockets ? 1000 : -1; *************** *** 827,865 **** if (pending_ip_pipe[0] == -1) break; if (res >= 0) { err_count = 0; if (poll_list[0].revents) sockcheck_read_pending(); while (sockcheck_worker_queue_client(-1)) ; ! if (gettimeofday(&tv_now, NULL) < 0) { ! log(PC_LOG, LOG_ERROR, "BUG: sockcheck_worker(): gettimeofday() returned errno %d (%s)\n", errno, strerror(errno)); ! } for (n=0; n<sockcheck_num_sockets; n++) { ! struct sockcheck_client *orig_client; ! const unsigned char **resp_state_hack; ! unsigned char *read_hack; ! ! /* Do work. If we have work left to do, continue. */ ! if (sockcheck_advance(n) == 0) continue; ! /* Testing done. Decrement number of sockets in progress. */ sockcheck_num_sockets--; ! /* If we can replace the current client, continue. */ ! if (sockcheck_worker_queue_client(n)) continue; ! /* If we can't do more useful work, see if we should swap things down further. */ ! if (n == sockcheck_num_sockets) continue; ! /* no work to do, so swap something down */ #if SOCKCHECK_DEBUG ! log(PC_LOG, LOG_INFO, "sockcheck moving client %s (at %d) to fill hole at %d\n", client_list[sockcheck_num_sockets].addr->hostname, sockcheck_num_sockets, n); #endif ! poll_list[n+1] = poll_list[sockcheck_num_sockets+1]; ! /* Do nasty hacks since the resp_state and read pointers are ! * allocated on a per-slot basis, and shouldn't be put into ! * more than one slot. ! */ ! resp_state_hack = client_list[n].resp_state; ! read_hack = client_list[n].read; ! orig_client = client_list + sockcheck_num_sockets; ! client_list[n] = *orig_client; ! orig_client->read = read_hack; ! orig_client->resp_state = resp_state_hack; ! /* And when we are done swapping, rescan this one */ n--; } --- 902,936 ---- if (pending_ip_pipe[0] == -1) break; if (res >= 0) { + if (gettimeofday(&tv_now, NULL) < 0) { + log(PC_LOG, LOG_ERROR, "BUG: sockcheck_worker(): gettimeofday() returned errno %d (%s)\n", errno, strerror(errno)); + } + /* This isn't done with timeq because timeq is in the wrong thread :( */ + if (tv_now.tv_sec > (last_clean + 3600)) { + cleaned.used = 0; + dict_foreach(checked_ip_dict, find_old_entries, &cleaned); + for (n=0; n<cleaned.used; n++) { + dict_remove(checked_ip_dict, cleaned.list[n]->hostname); + } + } + /* Do we have any new requests or connetions? */ err_count = 0; if (poll_list[0].revents) sockcheck_read_pending(); while (sockcheck_worker_queue_client(-1)) ; ! /* Handle existing connections */ for (n=0; n<sockcheck_num_sockets; n++) { ! /* Do work. If the client's not done, continue. */ ! if (!sockcheck_advance(n)) continue; ! /* Testing done. Free client and decrement number of sockets in progress. */ sockcheck_num_sockets--; ! sockcheck_free_client(client_list[n]); ! /* Swap down the highest-numbered socket client, if necessary. */ ! if (n != sockcheck_num_sockets) { #if SOCKCHECK_DEBUG ! log(PC_LOG, LOG_INFO, "sockcheck moving client %s (at %d) to fill hole at %d\n", client_list[sockcheck_num_sockets]->addr->hostname, sockcheck_num_sockets, n); #endif ! poll_list[n+1] = poll_list[sockcheck_num_sockets+1]; ! client_list[n] = client_list[sockcheck_num_sockets]; ! } ! client_list[sockcheck_num_sockets] = 0; n--; } *************** *** 876,879 **** --- 947,951 ---- } } + sci_list_clean(&cleaned); return NULL; } *************** *** 938,976 **** dict_t object; struct sockcheck_state *new_test; ! unsigned int n, found; rd = data; new_test = malloc(sizeof(*new_test)); new_test->template = NULL; new_test->port = strtoul(key, &end, 0); new_test->timeout = 5000; new_test->type = CHECKING; response_list_init(&new_test->responses); ! if ((*end != ':') || !(object = GET_RECORD_OBJECT(rd))) { log(PC_LOG, LOG_ERROR, "Error: misformed sockcheck test `%s', skipping it\n", key); free(new_test); return 1; } - new_test->template = strdup(end+1); dict_foreach(object, sockcheck_create_response, new_test); ! /* if none of the responses have template "other", create a ! * default response that goes to accept. ! */ ! found = (unsigned)-1; for (n=0; n<new_test->responses.used; n++) { ! if (!strcmp(new_test->responses.list[n]->template, "other")) { ! found = n; ! } } ! if (found == (unsigned)-1) { rd = alloc_record_data_qstring("accept"); sockcheck_create_response("other", rd, new_test); free_record_data(rd); ! } else if (found != (new_test->responses.used - 1)) { struct sockcheck_response *tmp; /* switch the response for "other" to the end */ tmp = new_test->responses.list[new_test->responses.used - 1]; ! new_test->responses.list[new_test->responses.used - 1] = new_test->responses.list[found]; ! new_test->responses.list[found] = tmp; } --- 1010,1059 ---- dict_t object; struct sockcheck_state *new_test; ! unsigned int n; rd = data; new_test = malloc(sizeof(*new_test)); new_test->template = NULL; + new_test->reps = 1; new_test->port = strtoul(key, &end, 0); new_test->timeout = 5000; new_test->type = CHECKING; response_list_init(&new_test->responses); ! if (!(object = GET_RECORD_OBJECT(rd))) { log(PC_LOG, LOG_ERROR, "Error: misformed sockcheck test `%s', skipping it\n", key); + free(new_test); + return 1; + } + while (*end) { + switch (*end) { + case '*': new_test->reps = strtoul(end+1, &end, 0); break; + case ':': new_test->template = strdup(end+1); end += strlen(end); break; + default: + log(PC_LOG, LOG_ERROR, "Error: misformed sockcheck test `%s', skipping it\n", key); + free(new_test); + return 1; + } + } + if (!new_test->template) { + log(PC_LOG, LOG_ERROR, "Error: misformed sockcheck test `%s', skipping it\n", key); free(new_test); return 1; } dict_foreach(object, sockcheck_create_response, new_test); ! /* If none of the responses have template "other", create a ! * default response that goes to accept. */ for (n=0; n<new_test->responses.used; n++) { ! if (!strcmp(new_test->responses.list[n]->template, "other")) break; } ! if (n == new_test->responses.used) { rd = alloc_record_data_qstring("accept"); sockcheck_create_response("other", rd, new_test); free_record_data(rd); ! } else if (n != (new_test->responses.used - 1)) { struct sockcheck_response *tmp; /* switch the response for "other" to the end */ tmp = new_test->responses.list[new_test->responses.used - 1]; ! new_test->responses.list[new_test->responses.used - 1] = new_test->responses.list[n]; ! new_test->responses.list[n] = tmp; } *************** *** 1116,1119 **** --- 1199,1203 ---- dict_delete(checked_ip_dict); free(pending_ip_list); /* not free_string_list because it doesn't own them */ + free(deq_buff); if (tests) { for (n=0; n<tests->used; n++) { *************** *** 1133,1141 **** if (client_list) { for (n=0; n<sockcheck_conf.max_sockets; n++) { ! if (client_list[n].send_size) { ! free(client_list[n].send); ! } ! free(client_list[n].read); ! free(client_list[n].resp_state); } free(client_list); --- 1217,1223 ---- if (client_list) { for (n=0; n<sockcheck_conf.max_sockets; n++) { ! if (client_list[n]) { ! sockcheck_free_client(client_list[n]); ! } } free(client_list); *************** *** 1146,1150 **** _sockcheck_init(void) { - unsigned int n; int flags; --- 1228,1231 ---- *************** *** 1169,1180 **** sockcheck_read_tests(); if (disable_sockcheck) return; ! client_list = malloc(sockcheck_conf.max_sockets * sizeof(client_list[0])); ! for (n=0; n<sockcheck_conf.max_sockets; n++) { ! client_list[n].send_size = 32; ! client_list[n].send = malloc(client_list[n].send_size); ! client_list[n].read_size = sockcheck_conf.max_read; ! client_list[n].read = malloc(client_list[n].read_size); ! client_list[n].resp_state = malloc(max_responses * sizeof(client_list[n].resp_state[0])); ! } if (pthread_create(&sockcheck_thread, NULL, sockcheck_worker, NULL)) { log(PC_LOG, LOG_ERROR, "pthread_create(..., sockcheck_worker, ...) returned errno %d (%s)\n", errno, strerror(errno)); --- 1250,1255 ---- sockcheck_read_tests(); if (disable_sockcheck) return; ! client_list = calloc(sockcheck_conf.max_sockets, sizeof(client_list[0])); ! last_clean = now; if (pthread_create(&sockcheck_thread, NULL, sockcheck_worker, NULL)) { log(PC_LOG, LOG_ERROR, "pthread_create(..., sockcheck_worker, ...) returned errno %d (%s)\n", errno, strerror(errno)); *************** *** 1202,1205 **** --- 1277,1281 ---- stats->pending_ip_count = pending_ip_list->used; stats->test_count = tests ? tests->used : 0; + stats->cached_ip_count = dict_size(checked_ip_dict); } *************** *** 1221,1225 **** } ! #endif /* defined(HAVE_POLL) && defined(HAVE_PTHREAD) */ ! ! --- 1297,1299 ---- } ! #endif Index: recdb.c =================================================================== RCS file: /cvsroot/srvx/services/src/recdb.c,v retrieving revision 1.30 retrieving revision 1.31 diff -C2 -r1.30 -r1.31 *** recdb.c 2001/08/01 22:14:35 1.30 --- recdb.c 2001/08/19 03:06:09 1.31 *************** *** 38,49 **** --- 38,52 ---- #if HAVE_GETC_UNLOCKED + #undef fgetc #define fgetc(STR) getc_unlocked(STR) #endif #if HAVE_PUTC_UNLOCKED + #undef fputc #define fputc(CHR,STR) putc_unlocked(CHR,STR) #endif #if HAVE_FEOF_UNLOCKED + #undef feof #define feof(STR) feof_unlocked(STR) #endif Index: proto_ircu_p10.c =================================================================== RCS file: /cvsroot/srvx/services/src/proto_ircu_p10.c,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -r1.18 -r1.19 *** proto_ircu_p10.c 2001/08/19 01:28:39 1.18 --- proto_ircu_p10.c 2001/08/19 03:06:09 1.19 *************** *** 614,617 **** --- 614,623 ---- void + irc_stats(struct userNode *from, struct server *target, char type) + { + putsock("%s STATS %c :%s", from->numeric, type, target->numeric); + } + + void irc_part(struct userNode *who, struct chanNode *what, const char *reason) { *************** *** 1166,1171 **** return 1; } else { ! struct chanNode *cn = GetChannel(argv[2]); ! struct userNode *un = GetUserX(argv[0]); int next_arg=4, res=1, add=1, bit; const char *mchange; --- 1172,1177 ---- return 1; } else { ! struct chanNode *cn; ! struct userNode *un; int next_arg=4, res=1, add=1, bit; const char *mchange; *************** *** 1175,1178 **** --- 1181,1186 ---- unsigned int orig_limit; + cn = GetChannel(argv[2]); + un = GetUserX(argv[0]); if (!cn) { log(MAIN_LOG, LOG_ERROR, "Unable to find channel %s whose mode is changing\n", argv[2]); *************** *** 1303,1306 **** --- 1311,1321 ---- } + static CMD_FUNC(cmd_num_gline) + { + if (argc < 7) return 0; + gline_add(argv[0]+1, argv[4], atoi(argv[5])-now, argv[6], 0); + return 1; + } + static CMD_FUNC(cmd_quit) { *************** *** 1464,1470 **** if (argc != 4) return 0; pd.user = GetUserX(argv[0]); ! /* The gag flag is never applied to userNodes it does not belong on, ! so no worries. */ ! if(IsGagged(pd.user)) return 1; pd.is_notice = 0; pd.text = argv[3]; --- 1479,1483 ---- if (argc != 4) return 0; pd.user = GetUserX(argv[0]); ! if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user))) return 1; pd.is_notice = 0; pd.text = argv[3]; *************** *** 1478,1483 **** if (argc != 4) return 0; pd.user = GetUserX(argv[0]); pd.is_notice = 1; - if (IsGagged(pd.user) && !IsOper(pd.user)) return 1; pd.text = argv[3]; parse_foreach(argv[2], privmsg_chan_helper, NULL, privmsg_user_helper, NULL, &pd); --- 1491,1496 ---- if (argc != 4) return 0; pd.user = GetUserX(argv[0]); + if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user))) return 1; pd.is_notice = 1; pd.text = argv[3]; parse_foreach(argv[2], privmsg_chan_helper, NULL, privmsg_user_helper, NULL, &pd); *************** *** 1637,1640 **** --- 1650,1656 ---- dict_insert(irc_func_dict, "332", cmd_num_topic); dict_insert(irc_func_dict, "333", cmd_num_topic); + /* "stats g" responses */ + dict_insert(irc_func_dict, "247", cmd_num_gline); + dict_insert(irc_func_dict, "219", cmd_dummy); /* "End of /STATS report" */ /* other numeric responses we might get */ dict_insert(irc_func_dict, "401", cmd_dummy); /* target left network */ Index: proto_bahamut.c =================================================================== RCS file: /cvsroot/srvx/services/src/proto_bahamut.c,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -r1.8 -r1.9 *** proto_bahamut.c 2001/08/19 01:28:39 1.8 --- proto_bahamut.c 2001/08/19 03:06:09 1.9 *************** *** 253,257 **** } ! putsock("%s %s %d :%s", CMD_SQUIT, srv->name, 0, message); if (srv == self->uplink) { --- 253,257 ---- } ! putsock("%s %s %d :%s", CMD_SQUIT, self->name, 0, message); if (srv == self->uplink) { *************** *** 436,439 **** --- 436,445 ---- { putsock("%s", what); + } + + void + irc_stats(struct userNode *from, struct server *target, char type) + { + putsock(":%s STATS %c :%s", from->nick, type, target->name); } Index: proto.h =================================================================== RCS file: /cvsroot/srvx/services/src/proto.h,v retrieving revision 1.37 retrieving revision 1.38 diff -C2 -r1.37 -r1.38 *** proto.h 2001/08/19 01:28:39 1.37 --- proto.h 2001/08/19 03:06:09 1.38 *************** *** 68,82 **** #ifndef PROTO_MODENODE_MODES ! #define PROTO_MODENODE_MODES RFC1459_MODENODE_MODES #define PROTO_MODENODE_MODE_CHARS RFC1459_MODENODE_MODE_CHARS #endif #ifndef PROTO_CHANNEL_MODES ! #define PROTO_CHANNEL_MODES RFC1459_CHANNEL_MODES #define PROTO_CHANNEL_MODE_CHARS RFC1459_CHANNEL_MODE_CHARS #endif #ifndef PROTO_USER_MODES ! #define PROTO_USER_MODES RFC1459_USER_MODES #define PROTO_USER_MODE_CHARS RFC1459_USER_MODE_CHARS #endif --- 68,82 ---- #ifndef PROTO_MODENODE_MODES ! #define PROTO_MODENODE_MODES RFC1459_MODENODE_MODES #define PROTO_MODENODE_MODE_CHARS RFC1459_MODENODE_MODE_CHARS #endif #ifndef PROTO_CHANNEL_MODES ! #define PROTO_CHANNEL_MODES RFC1459_CHANNEL_MODES #define PROTO_CHANNEL_MODE_CHARS RFC1459_CHANNEL_MODE_CHARS #endif #ifndef PROTO_USER_MODES ! #define PROTO_USER_MODES RFC1459_USER_MODES #define PROTO_USER_MODE_CHARS RFC1459_USER_MODE_CHARS #endif *************** *** 118,121 **** --- 118,122 ---- void irc_kill(struct userNode *from, struct userNode *target, const char *message); void irc_raw(const char *what); + void irc_stats(struct userNode *from, struct server *target, char type); /********************/ *************** *** 128,132 **** void reg_mode_change_func(mode_change_func_t handler); ! int parse_line(unsigned char *); /**********************/ --- 129,133 ---- void reg_mode_change_func(mode_change_func_t handler); ! int parse_line(unsigned char *line); /**********************/ Index: opserv.help =================================================================== RCS file: /cvsroot/srvx/services/src/opserv.help,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -r1.28 -r1.29 *** opserv.help 2001/07/15 14:49:25 1.28 --- opserv.help 2001/08/19 03:06:09 1.29 *************** *** 3,7 **** "${index}"); "ACCESS" ("$bACCESS$b", ! "/msg $O ACCESS <handle>", "Displays the access level on $b$O$b for the specified handle.", "$uSee Also:$u none"); --- 3,7 ---- "${index}"); "ACCESS" ("$bACCESS$b", ! "/msg $O ACCESS [handle]", "Displays the access level on $b$O$b for the specified handle.", "$uSee Also:$u none"); *************** *** 12,16 **** "ALERT REACTION" ("$bALERT REACTION$b", "Valid alert actions (to be taken when an alert is hit) are:", ! " notice Send a notice to the $O alert channel", "$uSee Also:$u addalert, delalert"); "ADDBAD" ("$bADDBAD$b", --- 12,17 ---- "ALERT REACTION" ("$bALERT REACTION$b", "Valid alert actions (to be taken when an alert is hit) are:", ! "$bNOTICE$b: Send a notice to the $b$O$b alert channel", ! "$bGLINE$b: Gline the user that tripped the alert", "$uSee Also:$u addalert, delalert"); "ADDBAD" ("$bADDBAD$b", *************** *** 58,62 **** "$uSee Also:$u ban, unban"); "CLEARHOST" ("$bCLEARHOST$b", ! "/msg $O CLEARHOST <host>", "Removes any data for the given host in sockcheck's proxy test result cache.", "$uSee Also:$u hostscan"); --- 59,63 ---- "$uSee Also:$u ban, unban"); "CLEARHOST" ("$bCLEARHOST$b", ! "/msg $O CLEARHOST <host/nick>", "Removes any data for the given host in sockcheck's proxy test result cache.", "$uSee Also:$u hostscan"); *************** *** 145,150 **** "$bMASK$b user@host Specifies a mask to search for.", "$bLIMIT$b count Limits the number of matching glines.", ! "$bREASON$b mask Looks for glines with the given reason.", ! "$bISSUER$b mask Looks for glines issued by the given mask.", "$bAFTER$b interval Looks for glines that expire more than $binterval$b in the future."); "HELP" ("$bHELP$b", --- 146,151 ---- "$bMASK$b user@host Specifies a mask to search for.", "$bLIMIT$b count Limits the number of matching glines.", ! "$bREASON$b reason Looks for glines with the given reason.", ! "$bISSUER$b handle Looks for glines issued by the given handle.", "$bAFTER$b interval Looks for glines that expire more than $binterval$b in the future."); "HELP" ("$bHELP$b", *************** *** 152,156 **** "Displays help information for the specified topic or command. If no topic or command is specified, help returns basic $bhelp$b information for $b$O$b."); "HOSTSCAN" ("$bHOSTSCAN$b", ! "/msg $O HOSTSCAN <host>", "Adds the speicified host to the proxycheck queue. If the host is found to have a running proxy, then that host is GLINED for an hour.", "$uSee Also:$u trace"); --- 153,157 ---- "Displays help information for the specified topic or command. If no topic or command is specified, help returns basic $bhelp$b information for $b$O$b."); "HOSTSCAN" ("$bHOSTSCAN$b", ! "/msg $O HOSTSCAN <host/nick>", "Adds the speicified host to the proxycheck queue. If the host is found to have a running proxy, then that host is GLINED for an hour.", "$uSee Also:$u trace"); *************** *** 203,208 **** " $bGLOBAL$b: Displays $b$G$b log.", " $bPROXYCHECK$b: Displays proxycheck log.", ! "$bTEXT$b: Displays results that match the vaule of $btext$b.", ! "$bLIMIT$b: Limits results printed by $b$O$b to that of the vaule of $blimit$b."); "LO... [truncated message content] |