Services and their clients read their own configuration

A service keeps the configuration it was started with (srvparam.config)
and its threads and its clients' read it there: limits and counters
(alwaysauth, the limiter), RADIUS, dnspr's name servers, and the checks
for a reload in the accept loop and in sockmap(). The configuration is
still reloaded in place, so it is the current one for now; this is what
lets a reload build a new one while the old one still serves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Vladimir Dubrovin 2026-10-13 19:19:03 +03:00
parent 737bdc7d24
commit 7ec05ff372
7 changed files with 47 additions and 45 deletions

View File

@ -17,7 +17,7 @@ int alwaysauth(struct clientparam * param){
int countout = 0;
if(conf->connlimiter && !param->connlim && startconnlims(param)) return 10;
if(param->srv->config->connlimiter && !param->connlim && startconnlims(param)) return 10;
#ifdef WITH_HTTPSRV
/* The http server answers the request itself, so authorization must not
try to reach a destination that does not exist. A request it has handed
@ -27,15 +27,15 @@ int alwaysauth(struct clientparam * param){
res = doconnect(param);
#endif
if(!res){
if(conf->bandlimfunc && (conf->bandlimiter||conf->bandlimiterout)){
if(param->srv->config->bandlimfunc && (param->srv->config->bandlimiter||param->srv->config->bandlimiterout)){
_3proxy_mutex_lock(&bandlim_mutex);
initbandlims(param);
_3proxy_mutex_unlock(&bandlim_mutex);
}
if(conf->trafcountfunc && conf->trafcounter) {
if(param->srv->config->trafcountfunc && param->srv->config->trafcounter) {
_3proxy_mutex_lock(&tc_mutex);
for(tc = conf->trafcounter; tc; tc = tc->next) {
for(tc = param->srv->config->trafcounter; tc; tc = tc->next) {
if(tc->disabled) continue;
if(ACLmatches(tc->ace, param)){
if(tc->ace->action == NOCOUNTIN) {
@ -51,11 +51,11 @@ int alwaysauth(struct clientparam * param){
_3proxy_mutex_unlock(&tc_mutex);
return 10;
}
param->trafcountfunc = conf->trafcountfunc;
param->trafcountfunc = param->srv->config->trafcountfunc;
param->maxtrafin64 = tc->traflim64 - tc->v->traf64;
}
}
if(countout)for(tc = conf->trafcounter; tc; tc = tc->next) {
if(countout)for(tc = param->srv->config->trafcounter; tc; tc = tc->next) {
if(tc->disabled) continue;
if(ACLmatches(tc->ace, param)){
if(tc->ace->action == NOCOUNTOUT || tc->ace->action == NOCOUNTALL) break;
@ -66,7 +66,7 @@ int alwaysauth(struct clientparam * param){
_3proxy_mutex_unlock(&tc_mutex);
return 10;
}
param->trafcountfunc = conf->trafcountfunc;
param->trafcountfunc = param->srv->config->trafcountfunc;
param->maxtrafout64 = tc->traflim64 - tc->v->traf64;
}
}

View File

@ -306,7 +306,7 @@ int radsend(struct clientparam * param, int auth, int stop){
char buf[64];
if(!conf->nradservers) {
if(!param->srv->config->nradservers) {
return 4;
}
@ -371,12 +371,12 @@ int radsend(struct clientparam * param, int auth, int stop){
total_length += (2+len);
/* NAS-Identifier */
if(conf->stringtable){
if(param->srv->config->stringtable){
*ptr++ = PW_NAS_IDENTIFIER;
len = strlen((char *)conf->stringtable[SERVICES+param->service]);
len = strlen((char *)param->srv->config->stringtable[SERVICES+param->service]);
if(len > 253) len = 253;
*ptr++ = (2 + len);
memcpy(ptr, conf->stringtable[SERVICES+param->service], len);
memcpy(ptr, param->srv->config->stringtable[SERVICES+param->service], len);
ptr += len;
total_length+=(len+2);
}
@ -506,7 +506,7 @@ int radsend(struct clientparam * param, int auth, int stop){
memcpy(ptr, param->password, len);
rad_pwencode((char *)ptr,
&len,
conf->radiussecret,
param->srv->config->radiussecret,
(char *)packet.vector);
*(ptr-1) = len + 2;
ptr+=len;
@ -517,17 +517,17 @@ int radsend(struct clientparam * param, int auth, int stop){
packet.length = htons(total_length);
if(!auth){
len = strlen(conf->radiussecret);
memcpy(ptr,conf->radiussecret,len);
len = strlen(param->srv->config->radiussecret);
memcpy(ptr,param->srv->config->radiussecret,len);
md5_calc(packet.vector, (u_char *)&packet, total_length + len);
}
memcpy(vector, packet.vector, AUTH_VECTOR_LEN);
for (loop = 0; loop < conf->nradservers && loop < MAXRADIUS; loop++) {
for (loop = 0; loop < param->srv->config->nradservers && loop < MAXRADIUS; loop++) {
SOCKET remsock;
saremote = auth?conf->radiuslist[loop].authaddr : conf->radiuslist[loop].logaddr;
saremote = auth?param->srv->config->radiuslist[loop].authaddr : param->srv->config->radiuslist[loop].logaddr;
#ifdef NOIPV6
if(*SAFAMILY(&saremote)!= AF_INET) {
continue;
@ -548,9 +548,9 @@ int radsend(struct clientparam * param, int auth, int stop){
remsock = sockfd;
/*
}
else remsock = conf->radiuslist[loop].logsock;
else remsock = param->srv->config->radiuslist[loop].logsock;
*/
so._bind(so.state, remsock,(struct sockaddr *)&conf->radiuslist[loop].localaddr,SASIZE(&conf->radiuslist[loop].localaddr));
so._bind(so.state, remsock,(struct sockaddr *)&param->srv->config->radiuslist[loop].localaddr,SASIZE(&param->srv->config->radiuslist[loop].localaddr));
len = so._sendto(so.state, remsock, (char *)&packet, total_length, 0,
(struct sockaddr *)&saremote, sizeof(saremote));
if(len != ntohs(packet.length)){
@ -560,7 +560,7 @@ int radsend(struct clientparam * param, int auth, int stop){
memset(fds, 0, sizeof(fds));
fds[0].fd = remsock;
fds[0].events = POLLIN;
if(so._poll(so.state, fds, 1, conf->timeouts[SINGLEBYTE_L]*1000) <= 0) {
if(so._poll(so.state, fds, 1, param->srv->config->timeouts[SINGLEBYTE_L]*1000) <= 0) {
continue;
}
@ -582,7 +582,7 @@ int radsend(struct clientparam * param, int auth, int stop){
continue;
}
if (calc_replydigest((char *)&rpacket, (char *)packet.vector, conf->radiussecret,
if (calc_replydigest((char *)&rpacket, (char *)packet.vector, param->srv->config->radiussecret,
data_len) ){
continue;
}

View File

@ -145,17 +145,17 @@ void * dnsprchild(struct clientparam* param) {
}
else ip = 0;
}
if(!ip && conf->numservers){
if((param->remsock=param->srv->so._socket(param->sostate, SASOCK(&conf->nservers[0].addr), conf->nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, conf->nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {
if(!ip && param->srv->config->numservers){
if((param->remsock=param->srv->so._socket(param->sostate, SASOCK(&param->srv->config->nservers[0].addr), param->srv->config->nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, param->srv->config->nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {
RETURN(818);
}
memset(&param->sinsl, 0, sizeof(param->sinsl));
*SAFAMILY(&param->sinsl) = *SAFAMILY(&conf->nservers[0].addr);
*SAFAMILY(&param->sinsl) = *SAFAMILY(&param->srv->config->nservers[0].addr);
if(bindwithrange(param, param->remsock, &param->sinsl, param->extport)) {
RETURN(819);
}
param->sinsr = conf->nservers[0].addr;
if(conf->nservers[0].usetcp) {
param->sinsr = param->srv->config->nservers[0].addr;
if(param->srv->config->nservers[0].usetcp) {
if(connectwithpoll(param, param->remsock,(struct sockaddr *)&param->sinsr,SASIZE(&param->sinsr),param->srv->timeouts[CONNECT_TO])) RETURN(830);
buf-=2;
*(unsigned short*)buf = htons(i);
@ -180,7 +180,7 @@ void * dnsprchild(struct clientparam* param) {
}
param->statssrv64 += len;
param->nreads++;
if(conf->nservers[0].usetcp) {
if(param->srv->config->nservers[0].usetcp) {
unsigned short us;
us = ntohs(*(unsigned short *)buf);
if(us > 4096) RETURN(833);

View File

@ -16,7 +16,7 @@ int startconnlims (struct clientparam *param){
param->connlim = 1;
_3proxy_mutex_lock(&connlim_mutex);
for(ce = conf->connlimiter; ce; ce = ce->next) {
for(ce = param->srv->config->connlimiter; ce; ce = ce->next) {
if(ACLmatches(ce->ace, param)){
if(ce->ace->action == NOCONNLIM)break;
if(!ce->period){
@ -44,7 +44,7 @@ int startconnlims (struct clientparam *param){
}
if(ret) {
struct connlim * cee;
for(cee = conf->connlimiter; cee != ce; cee = cee->next) {
for(cee = param->srv->config->connlimiter; cee != ce; cee = cee->next) {
if(ACLmatches(cee->ace, param) && !cee->period && cee->rating) {
cee->rating--;
}
@ -59,7 +59,7 @@ void stopconnlims (struct clientparam *param){
struct connlim * ce;
_3proxy_mutex_lock(&connlim_mutex);
for(ce = conf->connlimiter; ce; ce = ce->next) {
for(ce = param->srv->config->connlimiter; ce; ce = ce->next) {
if(ACLmatches(ce->ace, param)){
if(ce->ace->action == NOCONNLIM)break;
if(!ce->period && ce->rating){
@ -78,28 +78,28 @@ void initbandlims (struct clientparam *param){
param->bandlimfunc = NULL;
param->bandlims[0] = NULL;
param->bandlimsout[0] = NULL;
if(!conf->bandlimfunc || (!conf->bandlimiter && !conf->bandlimiterout)) return;
for(i=0, be = conf->bandlimiter; be && i<MAXBANDLIMS; be = be->next) {
if(!param->srv->config->bandlimfunc || (!param->srv->config->bandlimiter && !param->srv->config->bandlimiterout)) return;
for(i=0, be = param->srv->config->bandlimiter; be && i<MAXBANDLIMS; be = be->next) {
if(ACLmatches(be->ace, param)){
if(be->ace->action == NOBANDLIM) {
break;
}
param->bandlims[i++] = be;
param->bandlimfunc = conf->bandlimfunc;
param->bandlimfunc = param->srv->config->bandlimfunc;
}
}
if(i<MAXBANDLIMS)param->bandlims[i] = NULL;
for(i=0, be = conf->bandlimiterout; be && i<MAXBANDLIMS; be = be->next) {
for(i=0, be = param->srv->config->bandlimiterout; be && i<MAXBANDLIMS; be = be->next) {
if(ACLmatches(be->ace, param)){
if(be->ace->action == NOBANDLIM) {
break;
}
param->bandlimsout[i++] = be;
param->bandlimfunc = conf->bandlimfunc;
param->bandlimfunc = param->srv->config->bandlimfunc;
}
}
if(i<MAXBANDLIMS)param->bandlimsout[i] = NULL;
param->bandlimver = conf->bandlimver;
param->bandlimver = param->srv->config->bandlimver;
}
unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nbytesout){
@ -125,9 +125,9 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb
if(!nbytesin && !nbytesout) return 0;
_3proxy_mutex_lock(&bandlim_mutex);
if(param->bandlimver != conf->bandlimver){
if(param->bandlimver != param->srv->config->bandlimver){
initbandlims(param);
param->bandlimver = conf->bandlimver;
param->bandlimver = param->srv->config->bandlimver;
}
for(i=0; nbytesin&& i<MAXBANDLIMS && param->bandlims[i]; i++){
if( !param->bandlims[i]->basetime ||
@ -172,7 +172,7 @@ void trafcountfunc(struct clientparam *param){
int countout = 0;
_3proxy_mutex_lock(&tc_mutex);
for(tc = conf->trafcounter; tc; tc = tc->next) {
for(tc = param->srv->config->trafcounter; tc; tc = tc->next) {
if(ACLmatches(tc->ace, param)){
if(tc->ace->action == NOCOUNTIN) {
@ -188,7 +188,7 @@ void trafcountfunc(struct clientparam *param){
tc->v->updated = curtime;
}
}
if(countout) for(tc = conf->trafcounter; tc; tc = tc->next) {
if(countout) for(tc = param->srv->config->trafcounter; tc; tc = tc->next) {
if(ACLmatches(tc->ace, param)){
if(tc->ace->action == NOCOUNTOUT || tc->ace->action == NOCOUNTALL) break;
if(tc->ace->action != COUNTOUT && tc->ace->action != COUNTALL ) {

View File

@ -1282,7 +1282,7 @@ static int srvrun(struct srvstart *s){
/* A connection is only taken with a slot of maxchild in hand, which
goes to its child; a slot not handed on is kept for the next one.
The wait is timed to notice a reload. */
while(!haveslot && conf->paused == srv->paused){
while(!haveslot && srv->config->paused == srv->paused){
if(!_3proxy_sem_timedlock(srv->childslots, 1000)){
haveslot = 1;
nfull = 0;
@ -1294,7 +1294,7 @@ static int srvrun(struct srvstart *s){
}
}
if (connectback) break;
if (conf->paused != srv->paused) break;
if (srv->config->paused != srv->paused) break;
error = srv->so._poll(srv->so.state, &srv->fds, 1, 1000);
if (error >= 1) break;
if (error == 0) continue;
@ -1304,7 +1304,7 @@ static int srvrun(struct srvstart *s){
break;
}
}
if((conf->paused != srv->paused) || (error < 0)) break;
if((srv->config->paused != srv->paused) || (error < 0)) break;
error = 0;
#if defined NOTCPMAIN
next = udpnext(s);
@ -1477,6 +1477,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
srv->maxchild = conf->maxchild;
srv->backlog = conf->backlog;
srv->stacksize = conf->stacksize;
srv->config = conf;
memcpy(srv->timeouts, conf->timeouts, sizeof(srv->timeouts));
srv->filtermaxsize = conf->filtermaxsize;
srv->parentretries = conf->parentretries;

View File

@ -252,10 +252,10 @@ log(logbuf);
(param->srv->logdumpcli && (param->statscli64 > param->srv->logdumpcli)))
dolog(param, NULL);
if(param->version < conf->version){
if(param->version < param->srv->config->version){
if(!param->srv->noforce && (res = (*param->srv->authfunc)(param)) && res != 2) {RETURN(res);}
param->paused = conf->paused;
param->version = conf->version;
param->paused = param->srv->config->paused;
param->version = param->srv->config->version;
}
if((param->maxtrafin64 && param->statssrv64 >= param->maxtrafin64) || (param->maxtrafout64 && param->statscli64 >= param->maxtrafout64)){

View File

@ -636,6 +636,7 @@ struct srvparam {
int nfilters, nreqfilters, nconnectfilters, nafterauthfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv;
int family;
int stacksize;
struct extparam *config; /* the configuration it was started with */
int timeouts[12]; /* conf.timeouts as they were when the service started */
int filtermaxsize, parentretries, maxseg; /* and these */
char delimchar;