diff --git a/include/haproxy/dns-t.h b/include/haproxy/dns-t.h index 245169bc5..255ad33e9 100644 --- a/include/haproxy/dns-t.h +++ b/include/haproxy/dns-t.h @@ -154,8 +154,9 @@ struct dns_nameserver { /* mixed dns and resolver counters, we will have to split them */ struct dns_counters { - char *id; - char *pid; + char *id; /* nameserver id */ + char *pid; /* parent resolver id */ + unsigned int ns_puid; /* nameserver numerical id (ns->puid) */ long long sent; /* - queries sent */ long long snd_error; /* - sending errors */ union { diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index 0108372c9..555eace61 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -612,6 +612,49 @@ struct server_inetaddr { } port; }; +/* struct to store informations about server's addr / port updater in + * INET context + */ +enum server_inetaddr_updater_by { + SERVER_INETADDR_UPDATER_BY_NONE = 0, + SERVER_INETADDR_UPDATER_BY_CLI, + SERVER_INETADDR_UPDATER_BY_LUA, + SERVER_INETADDR_UPDATER_BY_DNS_AR, + SERVER_INETADDR_UPDATER_BY_DNS_CACHE, + SERVER_INETADDR_UPDATER_BY_DNS_RESOLVER, + /* changes here must be reflected in SERVER_INETADDR_UPDATER_* + * helper macros and in server_inetaddr_updater_by_to_str() func + */ +}; +struct server_inetaddr_updater { + enum server_inetaddr_updater_by by; // by identifier (unique) + union { + struct { + unsigned int ns_id; // nameserver id responsible for the update + } dns_resolver; // SERVER_INETADDR_UPDATER_DNS_RESOLVER specific infos + }; // per updater's additional ctx +}; +#define SERVER_INETADDR_UPDATER_NONE \ + (struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_NONE } + +#define SERVER_INETADDR_UPDATER_CLI \ + (struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_CLI } + +#define SERVER_INETADDR_UPDATER_LUA \ + (struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_LUA } + +#define SERVER_INETADDR_UPDATER_DNS_AR \ + (struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_DNS_AR } + +#define SERVER_INETADDR_UPDATER_DNS_CACHE \ + (struct server_inetaddr_updater){ .by = SERVER_INETADDR_UPDATER_BY_DNS_CACHE } + +#define SERVER_INETADDR_UPDATER_DNS_RESOLVER(_ns_id) \ + (struct server_inetaddr_updater){ \ + .by = SERVER_INETADDR_UPDATER_BY_DNS_RESOLVER, \ + .dns_resolver.ns_id = _ns_id, \ + } + /* data provided to EVENT_HDL_SUB_SERVER_INETADDR handlers through * event_hdl facility * diff --git a/include/haproxy/server.h b/include/haproxy/server.h index fe78e2b72..229899153 100644 --- a/include/haproxy/server.h +++ b/include/haproxy/server.h @@ -47,12 +47,13 @@ int srv_lastsession(const struct server *s); int srv_getinter(const struct check *check); void srv_settings_cpy(struct server *srv, const struct server *src, int srv_tmpl); int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, const struct proxy *defproxy, int parse_flags); -int srv_update_addr(struct server *s, void *ip, int ip_sin_family, const char *updater); +int srv_update_addr(struct server *s, void *ip, int ip_sin_family, struct server_inetaddr_updater updater); int server_parse_sni_expr(struct server *newsrv, struct proxy *px, char **err); -int server_set_inetaddr(struct server *s, const struct server_inetaddr *inetaddr, const char *updater, struct buffer *msg); -int server_set_inetaddr_warn(struct server *s, const struct server_inetaddr *inetaddr, const char *updater); +int server_set_inetaddr(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater, struct buffer *msg); +int server_set_inetaddr_warn(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater); void server_get_inetaddr(struct server *s, struct server_inetaddr *inetaddr); -const char *srv_update_addr_port(struct server *s, const char *addr, const char *port, char *updater); +const char *srv_update_addr_port(struct server *s, const char *addr, const char *port, struct server_inetaddr_updater updater); +const char *server_inetaddr_updater_by_to_str(enum server_inetaddr_updater_by by); const char *srv_update_check_addr_port(struct server *s, const char *addr, const char *port); const char *srv_update_agent_addr_port(struct server *s, const char *addr, const char *port); struct server *server_find_by_id(struct proxy *bk, int id); diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index d8dcdfd1e..a13e0f5f4 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -1513,7 +1513,7 @@ int hlua_server_set_addr(lua_State *L) port = NULL; HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); - err = srv_update_addr_port(srv, addr, port, "Lua script"); + err = srv_update_addr_port(srv, addr, port, SERVER_INETADDR_UPDATER_LUA); HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock); if (!err) lua_pushnil(L); diff --git a/src/resolvers.c b/src/resolvers.c index 762b818a0..8f219f192 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -847,10 +847,10 @@ srv_found: switch (item->ar_item->type) { case DNS_RTYPE_A: - srv_update_addr(srv, &item->ar_item->data.in4.sin_addr, AF_INET, "DNS additional record"); + srv_update_addr(srv, &item->ar_item->data.in4.sin_addr, AF_INET, SERVER_INETADDR_UPDATER_DNS_AR); break; case DNS_RTYPE_AAAA: - srv_update_addr(srv, &item->ar_item->data.in6.sin6_addr, AF_INET6, "DNS additional record"); + srv_update_addr(srv, &item->ar_item->data.in6.sin6_addr, AF_INET6, SERVER_INETADDR_UPDATER_DNS_AR); break; } @@ -2811,6 +2811,7 @@ int resolv_allocate_counters(struct list *stat_modules) if (strcmp(mod->name, "resolvers") == 0) { ns->counters = (struct dns_counters *)ns->extra_counters->data + mod->counters_off[COUNTERS_RSLV]; ns->counters->id = ns->id; + ns->counters->ns_puid = ns->puid; ns->counters->pid = resolvers->id; } } diff --git a/src/server.c b/src/server.c index 1c8854af3..e9df3f416 100644 --- a/src/server.c +++ b/src/server.c @@ -3719,6 +3719,66 @@ void server_get_inetaddr(struct server *s, struct server_inetaddr *inetaddr) inetaddr->port.map = mapports; } +/* get human readable name for server_inetaddr_updater .by struct member + */ +const char *server_inetaddr_updater_by_to_str(enum server_inetaddr_updater_by by) +{ + switch (by) { + case SERVER_INETADDR_UPDATER_BY_CLI: + return "stats socket command"; + case SERVER_INETADDR_UPDATER_BY_LUA: + return "Lua script"; + case SERVER_INETADDR_UPDATER_BY_DNS_AR: + return "DNS additional record"; + case SERVER_INETADDR_UPDATER_BY_DNS_CACHE: + return "DNS cache"; + case SERVER_INETADDR_UPDATER_BY_DNS_RESOLVER: + return "DNS resolver"; + default: + /* unknown, don't mention updater */ + break; + } + return NULL; +} + +/* append inetaddr updater info to chunk + */ +static void _srv_append_inetaddr_updater_info(struct buffer *out, + struct server *s, + struct server_inetaddr_updater updater) +{ + switch (updater.by) { + case SERVER_INETADDR_UPDATER_BY_DNS_RESOLVER: + /* we need to report the resolver/nameserver id which is + * responsible for the update + */ + { + struct resolvers *r = s->resolvers; + struct dns_nameserver *ns; + + /* we already know that the update comes from the + * resolver section linked to the server, but we + * need to find out which nameserver handled the dns + * query + */ + BUG_ON(!r); + ns = find_nameserver_by_resolvers_and_id(r, updater.dns_resolver.ns_id); + BUG_ON(!ns); + chunk_appendf(out, " by '%s/%s'", r->id, ns->id); + } + break; + default: + { + const char *by_name; + + by_name = server_inetaddr_updater_by_to_str(updater.by); + if (by_name) + chunk_appendf(out, " by '%s'", by_name); + } + break; + } +} + /* server_set_inetaddr() helper */ static void _addr_to_str(int family, const void *addr, char *addr_str, size_t len) { @@ -3784,7 +3844,7 @@ static int _inetaddr_addr_cmp(const struct server_inetaddr *inetaddr, const stru */ int server_set_inetaddr(struct server *s, const struct server_inetaddr *inetaddr, - const char *updater, struct buffer *msg) + struct server_inetaddr_updater updater, struct buffer *msg) { union { struct event_hdl_cb_data_server_inetaddr addr; @@ -3893,8 +3953,8 @@ int server_set_inetaddr(struct server *s, ret = 1; } - if (ret && msg && updater) - chunk_appendf(msg, " by '%s'", updater); + if (ret && msg && updater.by != SERVER_INETADDR_UPDATER_BY_NONE) + _srv_append_inetaddr_updater_info(msg, s, updater); return ret; } @@ -3906,7 +3966,7 @@ int server_set_inetaddr(struct server *s, */ int server_set_inetaddr_warn(struct server *s, const struct server_inetaddr *inetaddr, - const char *updater) + struct server_inetaddr_updater updater) { struct buffer *msg = get_trash_chunk(); int ret; @@ -3935,7 +3995,7 @@ int server_set_inetaddr_warn(struct server *s, * * Must be called with the server lock held. */ -int srv_update_addr(struct server *s, void *ip, int ip_sin_family, const char *updater) +int srv_update_addr(struct server *s, void *ip, int ip_sin_family, struct server_inetaddr_updater updater) { struct server_inetaddr inetaddr; @@ -4061,8 +4121,8 @@ out: /* * This function update a server's addr and port only for AF_INET and AF_INET6 families. * - * Caller can pass its name through to get it integrated in the response message - * returned by the function. + * Caller can pass its info through to get it integrated in the response + * message returned by the function. * * The function first does the following, in that order: * - checks that don't switch from/to a family other than AF_INET and AF_INET6 @@ -4071,7 +4131,8 @@ out: * * Must be called with the server lock held. */ -const char *srv_update_addr_port(struct server *s, const char *addr, const char *port, char *updater) +const char *srv_update_addr_port(struct server *s, const char *addr, const char *port, + struct server_inetaddr_updater updater) { struct sockaddr_storage sa; struct server_inetaddr inetaddr; @@ -4300,7 +4361,6 @@ int snr_resolution_cb(struct resolv_requester *requester, struct dns_counters *c void *serverip, *firstip; short server_sin_family, firstip_sin_family; int ret; - struct buffer *chk = get_trash_chunk(); int has_no_ip = 0; s = objt_server(requester->owner); @@ -4375,11 +4435,11 @@ int snr_resolution_cb(struct resolv_requester *requester, struct dns_counters *c if (counters) { counters->app.resolver.update++; /* save the first ip we found */ - chunk_printf(chk, "%s/%s", counters->pid, counters->id); + srv_update_addr(s, firstip, firstip_sin_family, + SERVER_INETADDR_UPDATER_DNS_RESOLVER(counters->ns_puid)); } else - chunk_printf(chk, "DNS cache"); - srv_update_addr(s, firstip, firstip_sin_family, (char *) chk->area); + srv_update_addr(s, firstip, firstip_sin_family, SERVER_INETADDR_UPDATER_DNS_CACHE); update_status: if (!snr_update_srv_status(s, has_no_ip) && has_no_ip) @@ -5005,7 +5065,7 @@ static int cli_parse_set_server(char **args, char *payload, struct appctx *appct port = args[6]; } HA_SPIN_LOCK(SERVER_LOCK, &sv->lock); - warning = srv_update_addr_port(sv, addr, port, "stats socket command"); + warning = srv_update_addr_port(sv, addr, port, SERVER_INETADDR_UPDATER_CLI); if (warning) cli_msg(appctx, LOG_WARNING, warning); srv_clr_admin_flag(sv, SRV_ADMF_RMAINT);