Index | Thread | Search

From:
Kapetanakis Giannis <bilias@edu.physics.uoc.gr>
Subject:
Re: relayd disable/enable all hosts with same name
To:
Alexandr Nedvedicky <sashan@fastmail.net>
Cc:
tech@openbsd.org
Date:
Fri, 24 May 2024 10:07:51 +0300

Download raw body.

Thread
On 24/05/2024 09:13, Alexandr Nedvedicky wrote:
> Hello,
>
> I'm not using a relayd so I can't tell exactly. The relayctl(8) says:
>
>     host disable [name | id]
>              Disable a host.  Treat it as though it were always down.
>
>     host enable [name | id]
>              Enable the host.  Start checking its health again.
>
> so the whole issue feels like a kind of bug. See further below for comments on
> change itself. Note I'm not very familiar with relayctl code.
>
>
> +
> +		/* Disable hosts with same name on all tables */
> +		if (host_byname)
> +			TAILQ_FOREACH(t, env->sc_tables, entry)
> +				TAILQ_FOREACH(h, &t->hosts, entry)
> +					if (strcmp(h->conf.name, host->conf.name) == 0 &&
> +					    h->conf.id != host->conf.id && !h->conf.parentid)
> +						disable_host(c, id, h);
> 			^^^^
> 			I'm not sure if it is right place for TAILQ_FOREACH()
> 			over all tables here. The thing is the loop does call
> 			disable_host() recursively. So each level of
> 			recursion is going to walk over the same set of
> 			all tables relayd keeps.
>
> 			also lines exceed 80 characters.
>
> </snip>
>
> thanks and
> regards
> sashan

Look at host_findbyname() which is called early on disable_host()

I took the code from there. It does the same thing.

host_findbyname(struct relayd *env, const char *name)
{         
   struct table   *table;
   struct host *host;

   TAILQ_FOREACH(table, env->sc_tables, entry)
      TAILQ_FOREACH(host, &table->hosts, entry)
         if (strcmp(host->conf.name, name) == 0)
            return (host);
   return (NULL);
}

but returns uppon first entry found. So only the first host found is disabled/enabled and the rest (same host) are left intact.

So if you have for example table <webhosts> { www1, www2 }

redirect http { listen on $ext_ip port 80 forward to <webhosts> } redirect https { listen on $ext_if port 443 forward to <webhosts> } redirect service1 { listen on $ext_if port 8080 forward to <webhosts> } etc.. you get my point, many services on same servers and issue relayctl host disable www1 www1 will be only removed from http@relayd/http table which is the first and will be left enabled on rest of services. So the only functional way of putting www1 on maintenance is to manually issue disable on all host ids. Intentionally I didn't touch enable/disable by id. Maybe someone wants to only disable a specific host/port and not all services on host. But by name should do it on all names found. G