diff --git a/include/types/server.h b/include/types/server.h index 5092eb7df..8a6f72f77 100644 --- a/include/types/server.h +++ b/include/types/server.h @@ -230,7 +230,8 @@ struct server { const struct netns_entry *netns; /* contains network namespace name or NULL. Network namespace comes from configuration */ /* warning, these structs are huge, keep them at the bottom */ - struct sockaddr_storage addr; /* the address to connect to */ + struct sockaddr_storage addr; /* the address to connect to, doesn't include the port */ + unsigned int svc_port; /* the port to connect to (for relevant families) */ struct xprt_ops *xprt; /* transport-layer operations */ unsigned down_time; /* total time the server was down */ time_t last_change; /* last time, when the state was changed */ diff --git a/src/backend.c b/src/backend.c index bf70ee18b..c9bc3ed8b 100644 --- a/src/backend.c +++ b/src/backend.c @@ -769,6 +769,7 @@ int assign_server_address(struct stream *s) return SRV_STATUS_INTERNAL; srv_conn->addr.to = objt_server(s->target)->addr; + set_host_port(&srv_conn->addr.to, objt_server(s->target)->svc_port); if (!is_addr(&srv_conn->addr.to) && cli_conn) { /* if the server has no address, we use the same address @@ -1345,7 +1346,8 @@ int tcp_persist_rdp_cookie(struct stream *s, struct channel *req, int an_bit) int ret; struct sample smp; struct server *srv = px->srv; - struct sockaddr_in addr; + uint16_t port; + uint32_t addr; char *p; DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n", @@ -1366,22 +1368,25 @@ int tcp_persist_rdp_cookie(struct stream *s, struct channel *req, int an_bit) if (ret == 0 || (smp.flags & SMP_F_MAY_CHANGE) || smp.data.u.str.len == 0) goto no_cookie; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - - /* Considering an rdp cookie detected using acl, str ended with and should return */ - addr.sin_addr.s_addr = strtoul(smp.data.u.str.str, &p, 10); + /* Considering an rdp cookie detected using acl, str ended with and should return. + * The cookie format is "." where "ip" is the integer corresponding to the + * server's IP address in network order, and "port" is the integer corresponding to the + * server's port in network order. Comments please Emeric. + */ + addr = strtoul(smp.data.u.str.str, &p, 10); if (*p != '.') goto no_cookie; p++; - addr.sin_port = (unsigned short)strtoul(p, &p, 10); + + port = ntohs(strtoul(p, &p, 10)); if (*p != '.') goto no_cookie; s->target = NULL; while (srv) { if (srv->addr.ss_family == AF_INET && - memcmp(&addr, &(srv->addr), sizeof(addr)) == 0) { + port == srv->svc_port && + addr == ((struct sockaddr_in *)&srv->addr)->sin_addr.s_addr) { if ((srv->state != SRV_ST_STOPPED) || (px->options & PR_O_PERSIST)) { /* we found the server and it is usable */ s->flags |= SF_DIRECT | SF_ASSIGNED; diff --git a/src/checks.c b/src/checks.c index 2075e3fb7..7d4242267 100644 --- a/src/checks.c +++ b/src/checks.c @@ -527,7 +527,10 @@ static int httpchk_build_status_header(struct server *s, char *buffer, int size) (s->state != SRV_ST_STOPPED) ? (s->check.fall) : (s->check.rise)); addr_to_str(&s->addr, addr, sizeof(addr)); - port_to_str(&s->addr, port, sizeof(port)); + if (s->addr.ss_family == AF_INET || s->addr.ss_family == AF_INET6) + snprintf(port, sizeof(port), "%u", s->svc_port); + else + *port = 0; hlen += snprintf(buffer + hlen, size - hlen, "; address=%s; port=%s; name=%s/%s; node=%s; weight=%d/%d; scur=%d/%d; qcur=%d", addr, port, s->proxy->id, s->id, @@ -1778,7 +1781,11 @@ static int prepare_external_check(struct check *check) addr_to_str(&s->addr, buf, sizeof(buf)); check->argv[3] = strdup(buf); - port_to_str(&s->addr, buf, sizeof(buf)); + + if (s->addr.ss_family == AF_INET || s->addr.ss_family == AF_INET6) + snprintf(buf, sizeof(buf), "%u", s->svc_port); + else + *buf = 0; check->argv[4] = strdup(buf); for (i = 0; i < 5; i++) { @@ -3437,7 +3444,8 @@ int srv_check_healthcheck_port(struct check *chk) */ if (srv->flags & SRV_F_MAPPORTS) return 0; - i = get_host_port(&srv->addr); /* by default */ + + i = srv->svc_port; /* by default */ if (i > 0) return i; diff --git a/src/server.c b/src/server.c index 1551f7208..8aaf21842 100644 --- a/src/server.c +++ b/src/server.c @@ -1062,6 +1062,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr skip_name_resolution: newsrv->addr = *sk; + newsrv->svc_port = get_host_port(sk); newsrv->xprt = newsrv->check.xprt = newsrv->agent.xprt = xprt_get(XPRT_RAW); if (!protocol_by_family(newsrv->addr.ss_family)) { @@ -2807,7 +2808,7 @@ const char *update_server_addr_port(struct server *s, const char *addr, const ch chunk_appendf(msg, ", "); /* collecting data currently setup */ - current_port = get_host_port(&s->addr); + current_port = s->svc_port; /* check if PORT change is required */ port_change_required = 0; @@ -2848,7 +2849,7 @@ const char *update_server_addr_port(struct server *s, const char *addr, const ch /* applying PORT changes if required and update response message */ if (port_change_required) { /* apply new port */ - set_host_port(&s->addr, new_port); + s->svc_port = new_port; /* prepare message */ chunk_appendf(msg, "port changed from '"); diff --git a/src/stats.c b/src/stats.c index b7d030351..6bb33e826 100644 --- a/src/stats.c +++ b/src/stats.c @@ -1445,11 +1445,11 @@ int stats_fill_sv_stats(struct proxy *px, struct server *sv, int flags, switch (addr_to_str(&sv->addr, str, sizeof(str))) { case AF_INET: stats[ST_F_ADDR] = mkf_str(FO_CONFIG|FS_SERVICE, chunk_newstr(out)); - chunk_appendf(out, "%s:%d", str, get_host_port(&sv->addr)); + chunk_appendf(out, "%s:%d", str, sv->svc_port); break; case AF_INET6: stats[ST_F_ADDR] = mkf_str(FO_CONFIG|FS_SERVICE, chunk_newstr(out)); - chunk_appendf(out, "[%s]:%d", str, get_host_port(&sv->addr)); + chunk_appendf(out, "[%s]:%d", str, sv->svc_port); break; case AF_UNIX: stats[ST_F_ADDR] = mkf_str(FO_CONFIG|FS_SERVICE, "unix");