pgpool2.git / summary / log / commit / refs

commit    fd0efceae011c8d2c2f7c2b26dc0a738f055972e
Author:   Tatsuo Ishii <ishii@sraoss.co.jp>
Date:     Wed Feb 23 03:29:44 2022 +0000

    Implement comma separated multiple listen addresses.
    
    Pgpool-II only allowed to set single hostname, IP or '*' to the
    listen_addresses parameter. Now we can set multiple listen addresses
    to the parameter as PostgreSQL already does.  Note that the
    documentations for listen_addresses are shamelessly stolen from
    PostgreSQL.
    
    Discussion: https://www.pgpool.net/pipermail/pgpool-hackers/2022-February/004131.html


doc.ja/src/sgml/connection-settings.sgml | 41 ++++++++++----- doc/src/sgml/connection-settings.sgml | 27 +++++++--- src/config/pool_config_variables.c | 24 +++++---- src/include/pool_config.h | 3 +- src/main/pgpool_main.c | 89 +++++++++++++++++++++++--------- src/utils/pool_process_reporting.c | 10 +++- 6 files changed, 138 insertions(+), 56 deletions(-) diff --git a/doc.ja/src/sgml/connection-settings.sgml b/doc.ja/src/sgml/connection-settings.sgml index 068d64bf5..64e8c4b50 100644 --- a/doc.ja/src/sgml/connection-settings.sgml +++ b/doc.ja/src/sgml/connection-settings.sgml @@ -26,18 +26,35 @@ <listitem> <para> <!-- - Specifies the hostname or IP address, on which <productname>Pgpool-II</> - will accept TCP/IP connections. <literal>'*'</literal> - accepts all incoming connections. <literal>''</literal> - disables TCP/IP connections. Default - is <literal>'localhost'</literal>. Connections via UNIX - domain socket are always accepted. - --> - <productname>Pgpool-II</>がTCP/IP接続を受け付けるホスト名またはIPアドレスを指定します。 - <literal>*</literal>を指定すると入ってくる全ての接続を受け付けます。 - <literal>''</literal>を指定するとTCP/IP接続を受け付けません。 - デフォルト値は<literal>'localhost'</literal>です。 - UNIXドメインソケット経由の接続は常に受け付けます。 + Specifies the TCP/IP address(es) on which the server is + to listen for connections from client applications. + The value takes the form of a comma-separated list of host names + and/or numeric IP addresses. The special entry <literal>*</literal> + corresponds to all available IP interfaces. The entry + <literal>0.0.0.0</literal> allows listening for all IPv4 addresses and + <literal>::</literal> allows listening for all IPv6 addresses. + If the list is empty, the server does not listen on any IP interface + at all, in which case only Unix-domain sockets can be used to connect + to it. + The default value + is <systemitem class="systemname">localhost</systemitem>, which + allows only local TCP/IP <quote>loopback</quote> connections to + be made. While client authentication + (<xref linkend="auth-pool-hba-conf">) allows fine-grained + control over who can access the + server, <varname>listen_addresses</varname> controls which + interfaces accept connection attempts, which can help prevent + repeated malicious connection requests on insecure network + interfaces. This parameter can only be set at server start. + --> + クライアントアプリケーションからの接続をサーバが監視する TCP/IP アドレスを指定します。 + この値は、ホスト名をコンマで区切ったリスト、そして/もしくは、数値によるIPアドレスです。 + <literal>*</literal>という特別なエントリは利用可能な全てのIPインタフェースに対応します。 + エントリ<literal>0.0.0.0</literal>は全てのIPv4アドレスの監視を、そしてエントリ<literal>::</literal>は全てのIPv6アドレスの監視を許容します。 + リストが空の場合、サーバはいかなるIPインタフェースも全く監視しないで、Unixドメインソケットのみを使用して接続が行われます。 + デフォルトの値は<systemitem class="systemname">localhost</systemitem>で、ローカルなTCP/IP <quote>loopback</quote>接続のみ許可します。 + クライアント認証(<xref linkend="auth-pool-hba-conf">)は誰がサーバにアクセス可能かをきめ細かく制御するのに対し、<varname>listen_addresses</varname>はどのインタフェースが接続を試みるかを制御します。 + これにより、安全でないネットワークインタフェース上において繰り返して行われる悪意のある接続要求の防止に役立ちます。 </para> <para> <!-- diff --git a/doc/src/sgml/connection-settings.sgml b/doc/src/sgml/connection-settings.sgml index a87fe9a14..0521e56e1 100644 --- a/doc/src/sgml/connection-settings.sgml +++ b/doc/src/sgml/connection-settings.sgml @@ -16,13 +16,26 @@ </term> <listitem> <para> - Specifies the hostname or IP address, on - which <productname>Pgpool-II</productname> will accept - TCP/IP connections. <literal>'*'</literal> accepts all - incoming connections. <literal>''</literal> disables - TCP/IP connections. Default - is <literal>'localhost'</literal>. Connections via UNIX - domain socket are always accepted. + Specifies the TCP/IP address(es) on which the server is + to listen for connections from client applications. + The value takes the form of a comma-separated list of host names + and/or numeric IP addresses. The special entry <literal>*</literal> + corresponds to all available IP interfaces. The entry + <literal>0.0.0.0</literal> allows listening for all IPv4 addresses and + <literal>::</literal> allows listening for all IPv6 addresses. + If the list is empty, the server does not listen on any IP interface + at all, in which case only Unix-domain sockets can be used to connect + to it. + The default value + is <systemitem class="systemname">localhost</systemitem>, which + allows only local TCP/IP <quote>loopback</quote> connections to + be made. While client authentication + (<xref linkend="auth-pool-hba-conf">) allows fine-grained + control over who can access the + server, <varname>listen_addresses</varname> controls which + interfaces accept connection attempts, which can help prevent + repeated malicious connection requests on insecure network + interfaces. This parameter can only be set at server start. </para> <para> This parameter can only be set at server start. diff --git a/src/config/pool_config_variables.c b/src/config/pool_config_variables.c index 976203f9e..18ad30c3e 100644 --- a/src/config/pool_config_variables.c +++ b/src/config/pool_config_variables.c @@ -49,6 +49,7 @@ #endif #define default_reset_query_list "ABORT;DISCARD ALL" +#define default_listen_addresses_list "localhost" #define default_read_only_function_list "" #define default_write_function_list "" @@ -811,16 +812,6 @@ static struct config_string ConfigureNamesString[] = MakeDMLAdaptiveObjectRelationList, NULL }, - { - {"listen_addresses", CFGCXT_INIT, CONNECTION_CONFIG, - "hostname or IP address on which pgpool will listen on.", - CONFIG_VAR_TYPE_STRING, false, 0 - }, - &g_pool_config.listen_addresses, - "localhost", - NULL, NULL, NULL, NULL - }, - { {"pcp_listen_addresses", CFGCXT_INIT, CONNECTION_CONFIG, "hostname(s) or IP address(es) on which pcp will listen on.", @@ -1334,6 +1325,19 @@ static struct config_string_list ConfigureNamesStringList[] = NULL, NULL, NULL /* assign, check, show funcs */ }, + { + {"listen_addresses", CFGCXT_INIT, CONNECTION_CONFIG, + "hostname or IP address on which pgpool will listen on.", + CONFIG_VAR_TYPE_STRING_LIST, false, 0 + }, + &g_pool_config.listen_addresses, + &g_pool_config.num_listen_addresses, + (const char *) default_listen_addresses_list, + ",", + false, + NULL, NULL, NULL + }, + { {"read_only_function_list", CFGCXT_RELOAD, CONNECTION_POOL_CONFIG, "list of functions that does not writes to database.", diff --git a/src/include/pool_config.h b/src/include/pool_config.h index 26424b00d..dada252a0 100644 --- a/src/include/pool_config.h +++ b/src/include/pool_config.h @@ -203,7 +203,7 @@ typedef struct typedef struct { ClusteringModes backend_clustering_mode; /* Backend clustering mode */ - char *listen_addresses; /* hostnames/IP addresses to listen on */ + char **listen_addresses; /* hostnames/IP addresses to listen on */ int port; /* port # to bind */ char *pcp_listen_addresses; /* PCP listen address to listen on */ int pcp_port; /* PCP port # to bind */ @@ -391,6 +391,7 @@ typedef struct /* followings till syslog, does not exist in the configuration file */ int num_reset_queries; /* number of queries in reset_query_list */ + int num_listen_addresses; /* number of entries in listen_addresses */ int num_read_only_function_list; /* number of functions in * read_only_function_list */ int num_write_function_list; /* number of functions in diff --git a/src/main/pgpool_main.c b/src/main/pgpool_main.c index 036bd8b3a..55189e398 100644 --- a/src/main/pgpool_main.c +++ b/src/main/pgpool_main.c @@ -148,6 +148,7 @@ static pid_t worker_fork_a_child(ProcessType type, void (*func) (), void *params static int create_unix_domain_socket(struct sockaddr_un un_addr_tmp); static int create_inet_domain_socket(const char *hostname, const int port); static int *create_inet_domain_sockets(const char *hostname, const int port); +static int *create_inet_domain_sockets_by_list(char **listen_addresses, int n_listen_addresses, int port, int *n_sockets); static void failover(void); static bool check_all_backend_down(void); static void reaper(void); @@ -269,6 +270,8 @@ volatile SI_ManageInfo *si_manage_info; int PgpoolMain(bool discard_status, bool clear_memcache_oidmaps) { + int num_fds = 0; + int *inet_fds; int i; sigjmp_buf local_sigjmp_buf; @@ -397,43 +400,26 @@ PgpoolMain(bool discard_status, bool clear_memcache_oidmaps) } /* create unix domain socket */ - fds = malloc(sizeof(int) * 2); + fds = malloc(sizeof(int) * (num_fds + 2)); if (fds == NULL) ereport(FATAL, (errmsg("failed to allocate memory in startup process"))); fds[0] = create_unix_domain_socket(un_addr); - fds[1] = -1; on_proc_exit(FileUnlink, (Datum) un_addr.sun_path); /* create inet domain socket if any */ - if (pool_config->listen_addresses[0]) - { - int *inet_fds, - *walk; - int n = 1; - - inet_fds = create_inet_domain_sockets(pool_config->listen_addresses, pool_config->port); - - for (walk = inet_fds; *walk != -1; walk++) - n++; - - fds = realloc(fds, sizeof(int) * (n + 1)); - if (fds == NULL) - ereport(FATAL, - (errmsg("failed to allocate memory in startup process"))); + inet_fds = create_inet_domain_sockets_by_list(pool_config->listen_addresses, pool_config->num_listen_addresses, + pool_config->port, &num_fds); - n = 1; - for (walk = inet_fds; *walk != -1; walk++) - { - fds[n] = inet_fds[n - 1]; - n++; - } - fds[n] = -1; + /* copy inet domain sockets if any */ + if (num_fds > 0) + { + memcpy(&fds[1], inet_fds, sizeof(int) * num_fds); + fds[num_fds + 1] = -1; free(inet_fds); } - /* * We need to block signal here. Otherwise child might send some signals, * for example SIGUSR1(fail over). Children will inherit signal blocking @@ -4628,3 +4614,56 @@ exec_notice_pcp_child(FAILOVER_CONTEXT *failover_context) * Subroutines for failover() end * ------------------------------------------------------------------------- */ + + +/* + * Create INET domain sockets by specified listen address list + * "listen_addresses", which is an array of string. The number of elements is + * "n_listen_addresses". "port" is the port number. A socket array is returned. + * The number of elements in the socket array is "n_sockets". + */ +static int * +create_inet_domain_sockets_by_list(char **listen_addresses, int n_listen_addresses, int port, int *n_sockets) +{ + int *sockets = NULL; + int i; + + *n_sockets = 0; + + if (listen_addresses == NULL || listen_addresses[0] == NULL) + return NULL; + + for (i = 0; i < n_listen_addresses; i++) + { + int *inet_fds, + *walk; + int n = 0; /* number of fds returned from create_inet_domain_sockets(). */ + + ereport(LOG, + (errmsg("listen address[%d]: %s", i, listen_addresses[i]))); + + inet_fds = create_inet_domain_sockets(listen_addresses[i], port); + + for (walk = inet_fds; *walk != -1; walk++) + n++; + + sockets = realloc(sockets, sizeof(int) * (n + 1 + *n_sockets)); + if (sockets == NULL) + ereport(FATAL, + (errmsg("failed to allocate memory in startup process"))); + + n = 0; + for (walk = inet_fds; *walk != -1; walk++) + { + ereport(DEBUG5, + (errmsg("set inet socket: %d to sockets[%d]", inet_fds[n], *n_sockets))); + + sockets[*n_sockets] = inet_fds[n++]; + (*n_sockets)++; + } + sockets[*n_sockets] = -1; + free(inet_fds); + } + + return sockets; +} diff --git a/src/utils/pool_process_reporting.c b/src/utils/pool_process_reporting.c index f05df0432..825e4847a 100644 --- a/src/utils/pool_process_reporting.c +++ b/src/utils/pool_process_reporting.c @@ -191,7 +191,15 @@ get_config(int *nrows) /* - pgpool Connection Settings - */ StrNCpy(status[i].name, "listen_addresses", POOLCONFIG_MAXNAMELEN); - snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->listen_addresses); + *(status[i].value) = '\0'; + for (j = 0; j < pool_config->num_listen_addresses; j++) + { + len = POOLCONFIG_MAXVALLEN - strlen(status[i].value); + strncat(status[i].value, pool_config->listen_addresses[j], len); + len = POOLCONFIG_MAXVALLEN - strlen(status[i].value); + if (j != pool_config->num_listen_addresses - 1) + strncat(status[i].value, ",", len); + } StrNCpy(status[i].desc, "host name(s) or IP address(es) to listen on", POOLCONFIG_MAXDESCLEN); i++; [parent: 26a0679f6dc7]