diff --git a/src/3proxy.c b/src/3proxy.c index 3e4b10c..106e332 100644 --- a/src/3proxy.c +++ b/src/3proxy.c @@ -214,7 +214,7 @@ void dumpcounters(struct trafcount *tlin, int counterd){ if(cfp){ for(tl = tlin; cfp && tl; tl = tl->next){ if(tl->type >= conf.countertype) - fprintf(cfp, "%05d %020"PRIu64"%s%s\n", tl->number, tl->traf64, tl->comment?" #" : "", tl->comment? tl->comment : ""); + fprintf(cfp, "%05d %020"PRIu64"%s%s\n", tl->number, tl->v->traf64, tl->comment?" #" : "", tl->comment? tl->comment : ""); } fclose(cfp); } @@ -228,15 +228,15 @@ void dumpcounters(struct trafcount *tlin, int counterd){ if(lseek(counterd, sizeof(struct counter_header) + (tl->number - 1) * sizeof(struct counter_record), SEEK_SET) >= 0){ - crecord.traf64 = tl->traf64; - crecord.cleared = tl->cleared; - crecord.updated = tl->updated; + crecord.traf64 = tl->v->traf64; + crecord.cleared = tl->v->cleared; + crecord.updated = tl->v->updated; if(write(counterd, &crecord, sizeof(struct counter_record))){} } } - if(tl->type!=NEVER && timechanged(tl->cleared, curtime, tl->type)){ - tl->cleared = curtime; - tl->traf64 = 0; + if(tl->type!=NEVER && timechanged(tl->v->cleared, curtime, tl->type)){ + tl->v->cleared = curtime; + tl->v->traf64 = 0; } } } diff --git a/src/auth.c b/src/auth.c index 927e2ef..6de7e1e 100644 --- a/src/auth.c +++ b/src/auth.c @@ -47,12 +47,12 @@ int alwaysauth(struct clientparam * param){ countout = 1; if(tc->ace->action != COUNTALL) continue; } - if(tc->traflim64 <= tc->traf64) { + if(tc->traflim64 <= tc->v->traf64) { _3proxy_mutex_unlock(&tc_mutex); return 10; } param->trafcountfunc = conf.trafcountfunc; - param->maxtrafin64 = tc->traflim64 - tc->traf64; + param->maxtrafin64 = tc->traflim64 - tc->v->traf64; } } if(countout)for(tc = conf.trafcounter; tc; tc = tc->next) { @@ -62,12 +62,12 @@ int alwaysauth(struct clientparam * param){ if(tc->ace->action != COUNTOUT && tc->ace->action != COUNTALL) { continue; } - if(tc->traflim64 <= tc->traf64) { + if(tc->traflim64 <= tc->v->traf64) { _3proxy_mutex_unlock(&tc_mutex); return 10; } param->trafcountfunc = conf.trafcountfunc; - param->maxtrafout64 = tc->traflim64 - tc->traf64; + param->maxtrafout64 = tc->traflim64 - tc->v->traf64; } } _3proxy_mutex_unlock(&tc_mutex); diff --git a/src/conf.c b/src/conf.c index ddcd88a..be3bab6 100644 --- a/src/conf.c +++ b/src/conf.c @@ -47,6 +47,42 @@ int linenum = 0; struct counter_header cheader = {"3CF", (time_t)0}; struct counter_record crecord; +/* The values of the numbered counters, process-wide: a counter of a number + met for the first time takes its value from the counter file. Only the + thread reading the configuration adds to the list. */ +static struct trafcell { + struct trafcell *next; + unsigned number; + struct trafvalue v; +} *trafcells = NULL; + +struct trafvalue * trafvalue(unsigned number){ + struct trafcell *tc; + + for(tc = trafcells; tc; tc = tc->next) if(tc->number == number) return &tc->v; + if(!(tc = malloc(sizeof(*tc)))) return NULL; + memset(tc, 0, sizeof(*tc)); + tc->number = number; + if(conf.counterd >= 0) { + lseek(conf.counterd, + sizeof(struct counter_header) + (number - 1) * sizeof(struct counter_record), + SEEK_SET); + memset(&crecord, 0, sizeof(struct counter_record)); + if(read(conf.counterd, &crecord, sizeof(struct counter_record)) == sizeof(struct counter_record)){ + if(crecord.cleared < 0 || crecord.cleared >= MAX_COUNTER_TIME || crecord.updated < 0 || crecord.updated >= MAX_COUNTER_TIME){ + free(tc); + return NULL; + } + tc->v.traf64 = crecord.traf64; + tc->v.cleared = crecord.cleared; + tc->v.updated = crecord.updated; + } + } + tc->next = trafcells; + trafcells = tc; + return &tc->v; +} + int mainprepare(int argc, char** argv, void **service); int mainrun(void *service); void maindrop(void *service); @@ -1718,22 +1754,16 @@ static int h_ace(int argc, unsigned char **argv){ fprintf(stderr, "Wrong traffic limit specified, line %d\n", linenum); return(6); } - if(tl->number != 0 && conf.counterd >= 0) { - lseek(conf.counterd, - sizeof(struct counter_header) + (tl->number - 1) * sizeof(struct counter_record), - SEEK_SET); - memset(&crecord, 0, sizeof(struct counter_record)); - if(read(conf.counterd, &crecord, sizeof(struct counter_record)) == sizeof(struct counter_record)){ - tl->traf64 = crecord.traf64; - tl->cleared = crecord.cleared; - tl->updated = crecord.updated; - if(tl->cleared < 0 || tl->cleared >= MAX_COUNTER_TIME || tl->updated < 0 || tl->updated >= MAX_COUNTER_TIME){ - fprintf(stderr, "Invalid, incompatible or corrupted counter file.\n"); - return(6); - } - } + if(!tl->number) tl->v = &tl->own; + else if(!(tl->v = trafvalue(tl->number))){ + free(tl->comment); + free(tl); + freeacl(acl); + fprintf(stderr, "Invalid, incompatible or corrupted counter file.\n"); + return(6); } } + else tl->v = &tl->own; _3proxy_mutex_lock(&tc_mutex); if(!conf.trafcounter){ conf.trafcounter = tl; diff --git a/src/datatypes.c b/src/datatypes.c index 859bd33..84aa56e 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -471,7 +471,7 @@ static void * ef_trafcounter_type(struct node * node){ } static void * ef_trafcounter_traffic64(struct node * node){ - return &((struct trafcount *)node->value) -> traf64; + return &((struct trafcount *)node->value) -> v->traf64; } static void * ef_trafcounter_limit64(struct node * node){ return &((struct trafcount *)node->value) -> traflim64; @@ -493,11 +493,11 @@ static void * ef_client_bytesout64(struct node * node){ } static void * ef_trafcounter_cleared(struct node * node){ - return &((struct trafcount *)node->value) -> cleared; + return &((struct trafcount *)node->value) -> v->cleared; } static void * ef_trafcounter_updated(struct node * node){ - return &((struct trafcount *)node->value) -> updated; + return &((struct trafcount *)node->value) -> v->updated; } static void * ef_trafcounter_comment(struct node * node){ diff --git a/src/limiter.c b/src/limiter.c index be472da..3fe636a 100644 --- a/src/limiter.c +++ b/src/limiter.c @@ -184,8 +184,8 @@ void trafcountfunc(struct clientparam *param){ countout = 1; continue; } - tc->traf64 += param->statssrv64; - tc->updated = curtime; + tc->v->traf64 += param->statssrv64; + tc->v->updated = curtime; } } if(countout) for(tc = conf.trafcounter; tc; tc = tc->next) { @@ -194,8 +194,8 @@ void trafcountfunc(struct clientparam *param){ if(tc->ace->action != COUNTOUT && tc->ace->action != COUNTALL ) { continue; } - tc->traf64 += param->statscli64; - tc->updated = curtime; + tc->v->traf64 += param->statscli64; + tc->v->updated = curtime; } } diff --git a/src/plugins/LdapPlugin/ldapauth.c b/src/plugins/LdapPlugin/ldapauth.c index d5f57eb..0296b21 100644 --- a/src/plugins/LdapPlugin/ldapauth.c +++ b/src/plugins/LdapPlugin/ldapauth.c @@ -120,8 +120,8 @@ int savecounters(void *v) sprintf(tmpbuf,pat_file,ldap_dircount,tcd->ace->users->user); f=fopen(tmpbuf,"w+b"); fseek(f,0,SEEK_SET); - fprintf(f,"%"PRIu64" %lu %lu\n",tcd->traf64, - (unsigned long)tcd->cleared,(unsigned long)tcd->updated); + fprintf(f,"%"PRIu64" %lu %lu\n",tcd->v->traf64, + (unsigned long)tcd->v->cleared,(unsigned long)tcd->v->updated); fclose(f); free(tmpbuf); @@ -433,6 +433,7 @@ int h_trafgroup(int argc, unsigned char ** argv) newtrafcount =(*mypluginlink->mallocfunc)(sizeof (struct trafcount)); memset(newtrafcount, 0, sizeof(struct trafcount)); newtrafcount->ace = newace; + newtrafcount->v = &newtrafcount->own; newtrafcount->type=rtype; newtrafcount->traflim64 = traflimit; newtrafcount->comment=(*mypluginlink->strdupfunc)("ldapcounters"); @@ -450,9 +451,9 @@ int h_trafgroup(int argc, unsigned char ** argv) &rcounter.cleared, &rcounter.updated); - newtrafcount->traf64=rcounter.traf64; - newtrafcount->cleared=rcounter.cleared; - newtrafcount->updated=rcounter.updated; + newtrafcount->own.traf64=rcounter.traf64; + newtrafcount->own.cleared=rcounter.cleared; + newtrafcount->own.updated=rcounter.updated; fclose(f); } free(tmpbuf); diff --git a/src/proxy.h b/src/proxy.h index 47d0925..93bb893 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -291,6 +291,7 @@ int ipauth(struct clientparam * param); int doauth(struct clientparam * param); int strongauth(struct clientparam * param); void trafcountfunc(struct clientparam *param); +struct trafvalue * trafvalue(unsigned number); unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nbytesout); int handleredirect(struct clientparam * param, struct ace * acentry); diff --git a/src/structures.h b/src/structures.h index b84a9ce..6456533 100644 --- a/src/structures.h +++ b/src/structures.h @@ -471,17 +471,26 @@ struct schedule { }; +/* What a traffic counter has counted. A numbered counter's lives as long as + the process, shared by the counters of that number in every configuration + loaded, so that a reload neither loses it nor splits it; an unnumbered + counter keeps its own. */ +struct trafvalue { + uint64_t traf64; + time_t cleared; + time_t updated; +}; + struct trafcount { struct trafcount *next; struct ace *ace; unsigned number; ROTATION type; - uint64_t traf64; uint64_t traflim64; char * comment; int disabled; - time_t cleared; - time_t updated; + struct trafvalue *v; /* the shared value, or &own */ + struct trafvalue own; }; struct nserver { diff --git a/src/webadmin.c b/src/webadmin.c index 8683470..5d98119 100644 --- a/src/webadmin.c +++ b/src/webadmin.c @@ -458,16 +458,16 @@ int op_admin_counters(struct httpreq *r, const unsigned char *params) "