From 71a8c7c49e912f4c6117b62bdf24cbe21916c2ae Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 21 Dec 2016 22:04:54 +0100 Subject: [PATCH] MINOR: listener: move the transport layer pointer to the bind_conf A mistake was made when the socket layer was cut into proto and transport, the transport was attached to the listener while all listeners in a single "bind" line always have exactly the same transport. It doesn't seem obvious but this is the reason why there are so many #ifdefs USE_OPENSSL in cfgparse : a lot of operations have to be open-coded because cfgparse only manipulates bind_conf and we don't have the information of the transport layer here. Very little code makes use of the transport layer, mainly session setup and log. These places can afford an extra pointer indirection (the listener points to the bind_conf). This change is thus very small, it saves a little bit of memory (8B per listener) and makes the code more flexible. --- include/proto/listener.h | 4 +++- include/types/listener.h | 2 +- src/cfgparse.c | 5 ++--- src/cli.c | 2 +- src/log.c | 6 +++--- src/session.c | 4 ++-- src/ssl_sock.c | 6 +----- 7 files changed, 13 insertions(+), 16 deletions(-) diff --git a/include/proto/listener.h b/include/proto/listener.h index 75bae86d9..f67ca5eff 100644 --- a/include/proto/listener.h +++ b/include/proto/listener.h @@ -123,7 +123,8 @@ void bind_dump_kws(char **out); * If is not NULL, it is duplicated into ->arg to store useful config * information for error reporting. */ -static inline struct bind_conf *bind_conf_alloc(struct list *lh, const char *file, int line, const char *arg) +static inline struct bind_conf *bind_conf_alloc(struct list *lh, const char *file, + int line, const char *arg, struct xprt_ops *xprt) { struct bind_conf *bind_conf = (void *)calloc(1, sizeof(struct bind_conf)); @@ -137,6 +138,7 @@ static inline struct bind_conf *bind_conf_alloc(struct list *lh, const char *fil bind_conf->ux.uid = -1; bind_conf->ux.gid = -1; bind_conf->ux.mode = 0; + bind_conf->xprt = xprt; LIST_INIT(&bind_conf->listeners); return bind_conf; diff --git a/include/types/listener.h b/include/types/listener.h index d06e4e7c8..b203c6cd7 100644 --- a/include/types/listener.h +++ b/include/types/listener.h @@ -142,6 +142,7 @@ struct bind_conf { X509 *ca_sign_cert; /* CA certificate referenced by ca_file */ EVP_PKEY *ca_sign_pkey; /* CA private key referenced by ca_key */ #endif + struct xprt_ops *xprt; /* transport-layer operations for all listeners */ int is_ssl; /* SSL is required for these listeners */ int generate_certs; /* 1 if generate-certificates option is set, else 0 */ unsigned long bind_proc; /* bitmask of processes allowed to use these listeners */ @@ -173,7 +174,6 @@ struct listener { int options; /* socket options : LI_O_* */ struct fe_counters *counters; /* statistics counters */ struct protocol *proto; /* protocol this listener belongs to */ - struct xprt_ops *xprt; /* transport-layer operations for this socket */ int nbconn; /* current number of connections on this listener */ int maxconn; /* maximum connections allowed on this listener */ unsigned int backlog; /* if set, listen backlog */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 1c9b430c5..3fe3cc6b4 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -302,7 +302,6 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, l->fd = fd; memcpy(&l->addr, &ss, sizeof(ss)); - l->xprt = &raw_sock; l->state = LI_INIT; if (ss.ss_family == AF_INET) { @@ -2033,7 +2032,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum; peers_setup_frontend(curpeers->peers_fe); - bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]); + bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2], &raw_sock); if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { if (errmsg && *errmsg) { @@ -2882,7 +2881,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) goto out; } - bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]); + bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1], &raw_sock); /* use default settings for unix sockets */ bind_conf->ux.uid = global.unix_bind.ux.uid; diff --git a/src/cli.c b/src/cli.c index e6e9b45a8..86fb2eaa2 100644 --- a/src/cli.c +++ b/src/cli.c @@ -215,7 +215,7 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx } } - bind_conf = bind_conf_alloc(&global.stats_fe->conf.bind, file, line, args[2]); + bind_conf = bind_conf_alloc(&global.stats_fe->conf.bind, file, line, args[2], &raw_sock); bind_conf->level = ACCESS_LVL_OPER; /* default access level */ if (!str2listener(args[2], global.stats_fe, bind_conf, file, line, err)) { diff --git a/src/log.c b/src/log.c index 3a6f781d9..27d53f7eb 100644 --- a/src/log.c +++ b/src/log.c @@ -1630,7 +1630,7 @@ int build_logline(struct stream *s, char *dst, size_t maxsize, struct list *list goto out; tmplog += iret; #ifdef USE_OPENSSL - if (sess->listener->xprt == &ssl_sock) + if (sess->listener->bind_conf->xprt == &ssl_sock) LOGCHAR('~'); #endif if (tmp->options & LOG_OPT_QUOTE) @@ -1642,7 +1642,7 @@ int build_logline(struct stream *s, char *dst, size_t maxsize, struct list *list src = NULL; conn = objt_conn(sess->origin); if (conn) { - if (sess->listener->xprt == &ssl_sock) + if (sess->listener->bind_conf->xprt == &ssl_sock) src = ssl_sock_get_cipher_name(conn); } ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp); @@ -1656,7 +1656,7 @@ int build_logline(struct stream *s, char *dst, size_t maxsize, struct list *list src = NULL; conn = objt_conn(sess->origin); if (conn) { - if (sess->listener->xprt == &ssl_sock) + if (sess->listener->bind_conf->xprt == &ssl_sock) src = ssl_sock_get_proto_version(conn); } ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp); diff --git a/src/session.c b/src/session.c index 35177cf20..d96240095 100644 --- a/src/session.c +++ b/src/session.c @@ -127,7 +127,7 @@ int session_accept_fd(struct listener *l, int cfd, struct sockaddr_storage *addr if (unlikely((cli_conn = conn_new()) == NULL)) goto out_close; - conn_prepare(cli_conn, l->proto, l->xprt); + conn_prepare(cli_conn, l->proto, l->bind_conf->xprt); cli_conn->t.sock.fd = cfd; cli_conn->addr.from = *addr; @@ -292,7 +292,7 @@ int session_accept_fd(struct listener *l, int cfd, struct sockaddr_storage *addr conn_xprt_close(cli_conn); conn_free(cli_conn); out_close: - if (ret < 0 && l->xprt == &raw_sock && p->mode == PR_MODE_HTTP) { + if (ret < 0 && l->bind_conf->xprt == &raw_sock && p->mode == PR_MODE_HTTP) { /* critical error, no more memory, try to emit a 500 response */ struct chunk *err_msg = &p->errmsg[HTTP_ERR_500]; if (!err_msg->str) diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 6739fbc9f..617c00297 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -5491,17 +5491,13 @@ static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bi /* parse the "ssl" bind keyword */ static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) { - struct listener *l; - + conf->xprt = &ssl_sock; conf->is_ssl = 1; if (global.listen_default_ciphers && !conf->ciphers) conf->ciphers = strdup(global.listen_default_ciphers); conf->ssl_options |= global.listen_default_ssloptions; - list_for_each_entry(l, &conf->listeners, by_bind) - l->xprt = &ssl_sock; - return 0; }