PostgreSQL Source Code  git master
fe-connect.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <netdb.h>
#include <time.h>
#include <unistd.h>
#include "common/ip.h"
#include "common/link-canary.h"
#include "common/scram-common.h"
#include "common/string.h"
#include "fe-auth.h"
#include "libpq-fe.h"
#include "libpq-int.h"
#include "mb/pg_wchar.h"
#include "pg_config_paths.h"
#include "port/pg_bswap.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <pthread.h>
Include dependency graph for fe-connect.c:

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

#define PGPASSFILE   ".pgpass"
 
#define ERRCODE_APPNAME_UNKNOWN   "42704"
 
#define ERRCODE_INVALID_PASSWORD   "28P01"
 
#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"
 
#define DefaultHost   "localhost"
 
#define DefaultOption   ""
 
#define DefaultChannelBinding   "disable"
 
#define DefaultTargetSessionAttrs   "any"
 
#define DefaultLoadBalanceHosts   "disable"
 
#define DefaultSSLMode   "disable"
 
#define DefaultSSLCertMode   "disable"
 
#define DefaultGSSMode   "disable"
 
#define MAX_ERRLEN   30000
 

Typedefs

typedef struct _internalPQconninfoOption internalPQconninfoOption
 

Functions

static bool connectOptions1 (PGconn *conn, const char *conninfo)
 
static PGPing internal_ping (PGconn *conn)
 
static void pqFreeCommandQueue (PGcmdQueueEntry *queue)
 
static bool fillPGconn (PGconn *conn, PQconninfoOption *connOptions)
 
static void freePGconn (PGconn *conn)
 
static void release_conn_addrinfo (PGconn *conn)
 
static int store_conn_addrinfo (PGconn *conn, struct addrinfo *addrlist)
 
static void sendTerminateConn (PGconn *conn)
 
static PQconninfoOptionconninfo_init (PQExpBuffer errorMessage)
 
static PQconninfoOptionparse_connection_string (const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
 
static int uri_prefix_length (const char *connstr)
 
static bool recognized_connection_string (const char *connstr)
 
static PQconninfoOptionconninfo_parse (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
 
static PQconninfoOptionconninfo_array_parse (const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)
 
static bool conninfo_add_defaults (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static PQconninfoOptionconninfo_uri_parse (const char *uri, PQExpBuffer errorMessage, bool use_defaults)
 
static bool conninfo_uri_parse_options (PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
 
static bool conninfo_uri_parse_params (char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
 
static char * conninfo_uri_decode (const char *str, PQExpBuffer errorMessage)
 
static bool get_hexdigit (char digit, int *value)
 
static const char * conninfo_getval (PQconninfoOption *connOptions, const char *keyword)
 
static PQconninfoOptionconninfo_storeval (PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
 
static PQconninfoOptionconninfo_find (PQconninfoOption *connOptions, const char *keyword)
 
static void defaultNoticeReceiver (void *arg, const PGresult *res)
 
static void defaultNoticeProcessor (void *arg, const char *message)
 
static int parseServiceInfo (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static int parseServiceFile (const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
 
static char * pwdfMatchesString (char *buf, const char *token)
 
static char * passwordFromFile (const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
 
static void pgpassfileWarning (PGconn *conn)
 
static void default_threadlock (int acquire)
 
static bool sslVerifyProtocolVersion (const char *version)
 
static bool sslVerifyProtocolRange (const char *min, const char *max)
 
void pqDropConnection (PGconn *conn, bool flushInput)
 
static void pqDropServerData (PGconn *conn)
 
PGconnPQconnectdbParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGPing PQpingParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectdb (const char *conninfo)
 
PGPing PQping (const char *conninfo)
 
PGconnPQconnectStartParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectStart (const char *conninfo)
 
bool pqCopyPGconn (PGconn *srcConn, PGconn *dstConn)
 
static int count_comma_separated_elems (const char *input)
 
static char * parse_comma_separated_list (char **startptr, bool *more)
 
static void libpq_prng_init (PGconn *conn)
 
bool pqConnectOptions2 (PGconn *conn)
 
PQconninfoOptionPQconndefaults (void)
 
PGconnPQsetdbLogin (const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
 
static int connectNoDelay (PGconn *conn)
 
static void getHostaddr (PGconn *conn, char *host_addr, int host_addr_len)
 
static void emitHostIdentityInfo (PGconn *conn, const char *host_addr)
 
static void connectFailureMessage (PGconn *conn, int errorno)
 
static int useKeepalives (PGconn *conn)
 
static int setKeepalivesIdle (PGconn *conn)
 
static int setKeepalivesInterval (PGconn *conn)
 
static int setKeepalivesCount (PGconn *conn)
 
static int setTCPUserTimeout (PGconn *conn)
 
int pqConnectDBStart (PGconn *conn)
 
int pqConnectDBComplete (PGconn *conn)
 
PostgresPollingStatusType PQconnectPoll (PGconn *conn)
 
PGconnpqMakeEmptyPGconn (void)
 
void pqReleaseConnHosts (PGconn *conn)
 
void pqClosePGconn (PGconn *conn)
 
void PQfinish (PGconn *conn)
 
void PQreset (PGconn *conn)
 
int PQresetStart (PGconn *conn)
 
PostgresPollingStatusType PQresetPoll (PGconn *conn)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
PQconninfoOptionPQconninfoParse (const char *conninfo, char **errmsg)
 
PQconninfoOptionPQconninfo (PGconn *conn)
 
void PQconninfoFree (PQconninfoOption *connOptions)
 
char * PQdb (const PGconn *conn)
 
char * PQuser (const PGconn *conn)
 
char * PQpass (const PGconn *conn)
 
char * PQhost (const PGconn *conn)
 
char * PQhostaddr (const PGconn *conn)
 
char * PQport (const PGconn *conn)
 
char * PQtty (const PGconn *conn)
 
char * PQoptions (const PGconn *conn)
 
ConnStatusType PQstatus (const PGconn *conn)
 
PGTransactionStatusType PQtransactionStatus (const PGconn *conn)
 
const char * PQparameterStatus (const PGconn *conn, const char *paramName)
 
int PQprotocolVersion (const PGconn *conn)
 
int PQserverVersion (const PGconn *conn)
 
char * PQerrorMessage (const PGconn *conn)
 
int PQsocket (const PGconn *conn)
 
int PQbackendPID (const PGconn *conn)
 
PGpipelineStatus PQpipelineStatus (const PGconn *conn)
 
int PQconnectionNeedsPassword (const PGconn *conn)
 
int PQconnectionUsedPassword (const PGconn *conn)
 
int PQconnectionUsedGSSAPI (const PGconn *conn)
 
int PQclientEncoding (const PGconn *conn)
 
int PQsetClientEncoding (PGconn *conn, const char *encoding)
 
PGVerbosity PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity)
 
PGContextVisibility PQsetErrorContextVisibility (PGconn *conn, PGContextVisibility show_context)
 
PQnoticeReceiver PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg)
 
PQnoticeProcessor PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
bool pqParseIntParam (const char *value, int *result, PGconn *conn, const char *context)
 
pgthreadlock_t PQregisterThreadLock (pgthreadlock_t newhandler)
 

Variables

static const internalPQconninfoOption PQconninfoOptions []
 
static const PQEnvironmentOption EnvironmentOptions []
 
static const char uri_designator [] = "postgresql://"
 
static const char short_uri_designator [] = "postgres://"
 
pgthreadlock_t pg_g_threadlock = default_threadlock
 

Macro Definition Documentation

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

Definition at line 121 of file fe-connect.c.

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

Definition at line 136 of file fe-connect.c.

◆ DefaultHost

#define DefaultHost   "localhost"

Definition at line 116 of file fe-connect.c.

◆ DefaultLoadBalanceHosts

#define DefaultLoadBalanceHosts   "disable"

Definition at line 124 of file fe-connect.c.

◆ DefaultOption

#define DefaultOption   ""

Definition at line 117 of file fe-connect.c.

◆ DefaultSSLCertMode

#define DefaultSSLCertMode   "disable"

Definition at line 130 of file fe-connect.c.

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

Definition at line 129 of file fe-connect.c.

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

Definition at line 123 of file fe-connect.c.

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

Definition at line 86 of file fe-connect.c.

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

Definition at line 91 of file fe-connect.c.

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

Definition at line 89 of file fe-connect.c.

◆ MAX_ERRLEN

#define MAX_ERRLEN   30000

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

Definition at line 75 of file fe-connect.c.

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

Definition at line 2087 of file fe-connect.c.

2088 {
2089  char sebuf[PG_STRERROR_R_BUFLEN];
2090 
2092  "%s\n",
2093  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2094 
2095  if (conn->raddr.addr.ss_family == AF_UNIX)
2096  libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2097  else
2098  libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2099 }
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1325
#define SOCK_STRERROR
Definition: libpq-int.h:921
#define PG_STRERROR_R_BUFLEN
Definition: port.h:256
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
PGconn * conn
Definition: streamutil.c:55
struct sockaddr_storage addr
Definition: pqcomm.h:32
PQExpBufferData errorMessage
Definition: libpq-int.h:621
SockAddr raddr
Definition: libpq-int.h:466

References SockAddr::addr, appendPQExpBuffer(), conn, pg_conn::errorMessage, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, pg_conn::raddr, and SOCK_STRERROR.

Referenced by PQconnectPoll().

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

Definition at line 1972 of file fe-connect.c.

1973 {
1974 #ifdef TCP_NODELAY
1975  int on = 1;
1976 
1977  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1978  (char *) &on,
1979  sizeof(on)) < 0)
1980  {
1981  char sebuf[PG_STRERROR_R_BUFLEN];
1982 
1983  libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
1984  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1985  return 0;
1986  }
1987 #endif
1988 
1989  return 1;
1990 }
#define SOCK_ERRNO
Definition: libpq-int.h:920
pgsocket sock
Definition: libpq-int.h:463

References conn, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

◆ connectOptions1()

static bool connectOptions1 ( PGconn conn,
const char *  conninfo 
)
static

Definition at line 986 of file fe-connect.c.

987 {
988  PQconninfoOption *connOptions;
989 
990  /*
991  * Parse the conninfo string
992  */
993  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
994  if (connOptions == NULL)
995  {
997  /* errorMessage is already set */
998  return false;
999  }
1000 
1001  /*
1002  * Move option values into conn structure
1003  */
1004  if (!fillPGconn(conn, connOptions))
1005  {
1007  PQconninfoFree(connOptions);
1008  return false;
1009  }
1010 
1011  /*
1012  * Free the option info - all is in conn now
1013  */
1014  PQconninfoFree(connOptions);
1015 
1016  return true;
1017 }
static PQconninfoOption * parse_connection_string(const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5590
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6781
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:907
@ CONNECTION_BAD
Definition: libpq-fe.h:61
ConnStatusType status
Definition: libpq-int.h:429

References conn, CONNECTION_BAD, pg_conn::errorMessage, fillPGconn(), parse_connection_string(), PQconninfoFree(), and pg_conn::status.

Referenced by PQconnectStart(), and PQsetdbLogin().

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

Definition at line 5978 of file fe-connect.c.

5979 {
5981  PQconninfoOption *sslmode_default = NULL,
5982  *sslrootcert = NULL;
5983  char *tmp;
5984 
5985  /*
5986  * If there's a service spec, use it to obtain any not-explicitly-given
5987  * parameters. Ignore error if no error message buffer is passed because
5988  * there is no way to pass back the failure message.
5989  */
5990  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
5991  return false;
5992 
5993  /*
5994  * Get the fallback resources for parameters not specified in the conninfo
5995  * string nor the service.
5996  */
5997  for (option = options; option->keyword != NULL; option++)
5998  {
5999  if (strcmp(option->keyword, "sslrootcert") == 0)
6000  sslrootcert = option; /* save for later */
6001 
6002  if (option->val != NULL)
6003  continue; /* Value was in conninfo or service */
6004 
6005  /*
6006  * Try to get the environment variable fallback
6007  */
6008  if (option->envvar != NULL)
6009  {
6010  if ((tmp = getenv(option->envvar)) != NULL)
6011  {
6012  option->val = strdup(tmp);
6013  if (!option->val)
6014  {
6015  if (errorMessage)
6016  libpq_append_error(errorMessage, "out of memory");
6017  return false;
6018  }
6019  continue;
6020  }
6021  }
6022 
6023  /*
6024  * Interpret the deprecated PGREQUIRESSL environment variable. Per
6025  * tradition, translate values starting with "1" to sslmode=require,
6026  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
6027  * PGSSLMODE takes precedence; the opposite was true before v9.3.
6028  */
6029  if (strcmp(option->keyword, "sslmode") == 0)
6030  {
6031  const char *requiresslenv = getenv("PGREQUIRESSL");
6032 
6033  if (requiresslenv != NULL && requiresslenv[0] == '1')
6034  {
6035  option->val = strdup("require");
6036  if (!option->val)
6037  {
6038  if (errorMessage)
6039  libpq_append_error(errorMessage, "out of memory");
6040  return false;
6041  }
6042  continue;
6043  }
6044 
6045  /*
6046  * sslmode is not specified. Let it be filled in with the compiled
6047  * default for now, but if sslrootcert=system, we'll override the
6048  * default later before returning.
6049  */
6050  sslmode_default = option;
6051  }
6052 
6053  /*
6054  * No environment variable specified or the variable isn't set - try
6055  * compiled-in default
6056  */
6057  if (option->compiled != NULL)
6058  {
6059  option->val = strdup(option->compiled);
6060  if (!option->val)
6061  {
6062  if (errorMessage)
6063  libpq_append_error(errorMessage, "out of memory");
6064  return false;
6065  }
6066  continue;
6067  }
6068 
6069  /*
6070  * Special handling for "user" option. Note that if pg_fe_getauthname
6071  * fails, we just leave the value as NULL; there's no need for this to
6072  * be an error condition if the caller provides a user name. The only
6073  * reason we do this now at all is so that callers of PQconndefaults
6074  * will see a correct default (barring error, of course).
6075  */
6076  if (strcmp(option->keyword, "user") == 0)
6077  {
6078  option->val = pg_fe_getauthname(NULL);
6079  continue;
6080  }
6081  }
6082 
6083  /*
6084  * Special handling for sslrootcert=system with no sslmode explicitly
6085  * defined. In this case we want to strengthen the default sslmode to
6086  * verify-full.
6087  */
6088  if (sslmode_default && sslrootcert)
6089  {
6090  if (sslrootcert->val && strcmp(sslrootcert->val, "system") == 0)
6091  {
6092  free(sslmode_default->val);
6093 
6094  sslmode_default->val = strdup("verify-full");
6095  if (!sslmode_default->val)
6096  {
6097  if (errorMessage)
6098  libpq_append_error(errorMessage, "out of memory");
6099  return false;
6100  }
6101  }
6102  }
6103 
6104  return true;
6105 }
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1213
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5283
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
Definition: fe-misc.c:1296
#define free(a)
Definition: header.h:65
int val
Definition: getopt_long.h:21

References free, libpq_append_error(), parseServiceInfo(), pg_fe_getauthname(), option::val, and _PQconninfoOption::val.

Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), and PQconndefaults().

◆ conninfo_array_parse()

static PQconninfoOption * conninfo_array_parse ( const char *const *  keywords,
const char *const *  values,
PQExpBuffer  errorMessage,
bool  use_defaults,
int  expand_dbname 
)
static

Definition at line 5820 of file fe-connect.c.

5823 {
5825  PQconninfoOption *dbname_options = NULL;
5827  int i = 0;
5828 
5829  /*
5830  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
5831  * actually a recognized connection string.
5832  */
5833  while (expand_dbname && keywords[i])
5834  {
5835  const char *pname = keywords[i];
5836  const char *pvalue = values[i];
5837 
5838  /* first find "dbname" if any */
5839  if (strcmp(pname, "dbname") == 0 && pvalue)
5840  {
5841  /*
5842  * If value is a connection string, parse it, but do not use
5843  * defaults here -- those get picked up later. We only want to
5844  * override for those parameters actually passed.
5845  */
5846  if (recognized_connection_string(pvalue))
5847  {
5848  dbname_options = parse_connection_string(pvalue, errorMessage, false);
5849  if (dbname_options == NULL)
5850  return NULL;
5851  }
5852  break;
5853  }
5854  ++i;
5855  }
5856 
5857  /* Make a working copy of PQconninfoOptions */
5858  options = conninfo_init(errorMessage);
5859  if (options == NULL)
5860  {
5861  PQconninfoFree(dbname_options);
5862  return NULL;
5863  }
5864 
5865  /* Parse the keywords/values arrays */
5866  i = 0;
5867  while (keywords[i])
5868  {
5869  const char *pname = keywords[i];
5870  const char *pvalue = values[i];
5871 
5872  if (pvalue != NULL && pvalue[0] != '\0')
5873  {
5874  /* Search for the param record */
5875  for (option = options; option->keyword != NULL; option++)
5876  {
5877  if (strcmp(option->keyword, pname) == 0)
5878  break;
5879  }
5880 
5881  /* Check for invalid connection option */
5882  if (option->keyword == NULL)
5883  {
5884  libpq_append_error(errorMessage, "invalid connection option \"%s\"", pname);
5886  PQconninfoFree(dbname_options);
5887  return NULL;
5888  }
5889 
5890  /*
5891  * If we are on the first dbname parameter, and we have a parsed
5892  * connection string, copy those parameters across, overriding any
5893  * existing previous settings.
5894  */
5895  if (strcmp(pname, "dbname") == 0 && dbname_options)
5896  {
5897  PQconninfoOption *str_option;
5898 
5899  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
5900  {
5901  if (str_option->val != NULL)
5902  {
5903  int k;
5904 
5905  for (k = 0; options[k].keyword; k++)
5906  {
5907  if (strcmp(options[k].keyword, str_option->keyword) == 0)
5908  {
5909  free(options[k].val);
5910  options[k].val = strdup(str_option->val);
5911  if (!options[k].val)
5912  {
5913  libpq_append_error(errorMessage, "out of memory");
5915  PQconninfoFree(dbname_options);
5916  return NULL;
5917  }
5918  break;
5919  }
5920  }
5921  }
5922  }
5923 
5924  /*
5925  * Forget the parsed connection string, so that any subsequent
5926  * dbname parameters will not be expanded.
5927  */
5928  PQconninfoFree(dbname_options);
5929  dbname_options = NULL;
5930  }
5931  else
5932  {
5933  /*
5934  * Store the value, overriding previous settings
5935  */
5936  free(option->val);
5937  option->val = strdup(pvalue);
5938  if (!option->val)
5939  {
5940  libpq_append_error(errorMessage, "out of memory");
5942  PQconninfoFree(dbname_options);
5943  return NULL;
5944  }
5945  }
5946  }
5947  ++i;
5948  }
5949  PQconninfoFree(dbname_options);
5950 
5951  /*
5952  * Add in defaults if the caller wants that.
5953  */
5954  if (use_defaults)
5955  {
5956  if (!conninfo_add_defaults(options, errorMessage))
5957  {
5959  return NULL;
5960  }
5961  }
5962 
5963  return options;
5964 }
static Datum values[MAXATTR]
Definition: bootstrap.c:152
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5551
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5978
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5633
long val
Definition: informix.c:670
int i
Definition: isn.c:73
static char ** options

References conninfo_add_defaults(), conninfo_init(), free, i, _PQconninfoOption::keyword, libpq_append_error(), options, parse_connection_string(), PQconninfoFree(), recognized_connection_string(), option::val, val, _PQconninfoOption::val, and values.

Referenced by PQconnectStartParams().

◆ conninfo_find()

static PQconninfoOption * conninfo_find ( PQconninfoOption connOptions,
const char *  keyword 
)
static

Definition at line 6719 of file fe-connect.c.

6720 {
6722 
6723  for (option = connOptions; option->keyword != NULL; option++)
6724  {
6725  if (strcmp(option->keyword, keyword) == 0)
6726  return option;
6727  }
6728 
6729  return NULL;
6730 }

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

static const char * conninfo_getval ( PQconninfoOption connOptions,
const char *  keyword 
)
static

Definition at line 6629 of file fe-connect.c.

6631 {
6633 
6634  option = conninfo_find(connOptions, keyword);
6635 
6636  return option ? option->val : NULL;
6637 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6719

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

Definition at line 5551 of file fe-connect.c.

5552 {
5554  PQconninfoOption *opt_dest;
5555  const internalPQconninfoOption *cur_opt;
5556 
5557  /*
5558  * Get enough memory for all options in PQconninfoOptions, even if some
5559  * end up being filtered out.
5560  */
5562  if (options == NULL)
5563  {
5564  libpq_append_error(errorMessage, "out of memory");
5565  return NULL;
5566  }
5567  opt_dest = options;
5568 
5569  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5570  {
5571  /* Only copy the public part of the struct, not the full internal */
5572  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5573  opt_dest++;
5574  }
5575  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5576 
5577  return options;
5578 }
#define MemSet(start, val, len)
Definition: c.h:1007
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:189
#define malloc(a)
Definition: header.h:50

References _internalPQconninfoOption::keyword, libpq_append_error(), malloc, MemSet, options, and PQconninfoOptions.

Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), PQconndefaults(), and PQconninfo().

◆ conninfo_parse()

static PQconninfoOption * conninfo_parse ( const char *  conninfo,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

Definition at line 5644 of file fe-connect.c.

5646 {
5647  char *pname;
5648  char *pval;
5649  char *buf;
5650  char *cp;
5651  char *cp2;
5653 
5654  /* Make a working copy of PQconninfoOptions */
5655  options = conninfo_init(errorMessage);
5656  if (options == NULL)
5657  return NULL;
5658 
5659  /* Need a modifiable copy of the input string */
5660  if ((buf = strdup(conninfo)) == NULL)
5661  {
5662  libpq_append_error(errorMessage, "out of memory");
5664  return NULL;
5665  }
5666  cp = buf;
5667 
5668  while (*cp)
5669  {
5670  /* Skip blanks before the parameter name */
5671  if (isspace((unsigned char) *cp))
5672  {
5673  cp++;
5674  continue;
5675  }
5676 
5677  /* Get the parameter name */
5678  pname = cp;
5679  while (*cp)
5680  {
5681  if (*cp == '=')
5682  break;
5683  if (isspace((unsigned char) *cp))
5684  {
5685  *cp++ = '\0';
5686  while (*cp)
5687  {
5688  if (!isspace((unsigned char) *cp))
5689  break;
5690  cp++;
5691  }
5692  break;
5693  }
5694  cp++;
5695  }
5696 
5697  /* Check that there is a following '=' */
5698  if (*cp != '=')
5699  {
5700  libpq_append_error(errorMessage,
5701  "missing \"=\" after \"%s\" in connection info string",
5702  pname);
5704  free(buf);
5705  return NULL;
5706  }
5707  *cp++ = '\0';
5708 
5709  /* Skip blanks after the '=' */
5710  while (*cp)
5711  {
5712  if (!isspace((unsigned char) *cp))
5713  break;
5714  cp++;
5715  }
5716 
5717  /* Get the parameter value */
5718  pval = cp;
5719 
5720  if (*cp != '\'')
5721  {
5722  cp2 = pval;
5723  while (*cp)
5724  {
5725  if (isspace((unsigned char) *cp))
5726  {
5727  *cp++ = '\0';
5728  break;
5729  }
5730  if (*cp == '\\')
5731  {
5732  cp++;
5733  if (*cp != '\0')
5734  *cp2++ = *cp++;
5735  }
5736  else
5737  *cp2++ = *cp++;
5738  }
5739  *cp2 = '\0';
5740  }
5741  else
5742  {
5743  cp2 = pval;
5744  cp++;
5745  for (;;)
5746  {
5747  if (*cp == '\0')
5748  {
5749  libpq_append_error(errorMessage, "unterminated quoted string in connection info string");
5751  free(buf);
5752  return NULL;
5753  }
5754  if (*cp == '\\')
5755  {
5756  cp++;
5757  if (*cp != '\0')
5758  *cp2++ = *cp++;
5759  continue;
5760  }
5761  if (*cp == '\'')
5762  {
5763  *cp2 = '\0';
5764  cp++;
5765  break;
5766  }
5767  *cp2++ = *cp++;
5768  }
5769  }
5770 
5771  /*
5772  * Now that we have the name and the value, store the record.
5773  */
5774  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
5775  {
5777  free(buf);
5778  return NULL;
5779  }
5780  }
5781 
5782  /* Done with the modifiable input string */
5783  free(buf);
5784 
5785  /*
5786  * Add in defaults if the caller wants that.
5787  */
5788  if (use_defaults)
5789  {
5790  if (!conninfo_add_defaults(options, errorMessage))
5791  {
5793  return NULL;
5794  }
5795  }
5796 
5797  return options;
5798 }
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6655
static char * buf
Definition: pg_test_fsync.c:73

References buf, conninfo_add_defaults(), conninfo_init(), conninfo_storeval(), free, libpq_append_error(), options, and PQconninfoFree().

Referenced by parse_connection_string().

◆ conninfo_storeval()

static PQconninfoOption * conninfo_storeval ( PQconninfoOption connOptions,
const char *  keyword,
const char *  value,
PQExpBuffer  errorMessage,
bool  ignoreMissing,
bool  uri_decode 
)
static

Definition at line 6655 of file fe-connect.c.

6659 {
6661  char *value_copy;
6662 
6663  /*
6664  * For backwards compatibility, requiressl=1 gets translated to
6665  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6666  * (which is the default for sslmode).
6667  */
6668  if (strcmp(keyword, "requiressl") == 0)
6669  {
6670  keyword = "sslmode";
6671  if (value[0] == '1')
6672  value = "require";
6673  else
6674  value = "prefer";
6675  }
6676 
6677  option = conninfo_find(connOptions, keyword);
6678  if (option == NULL)
6679  {
6680  if (!ignoreMissing)
6681  libpq_append_error(errorMessage,
6682  "invalid connection option \"%s\"",
6683  keyword);
6684  return NULL;
6685  }
6686 
6687  if (uri_decode)
6688  {
6689  value_copy = conninfo_uri_decode(value, errorMessage);
6690  if (value_copy == NULL)
6691  /* conninfo_uri_decode already set an error message */
6692  return NULL;
6693  }
6694  else
6695  {
6696  value_copy = strdup(value);
6697  if (value_copy == NULL)
6698  {
6699  libpq_append_error(errorMessage, "out of memory");
6700  return NULL;
6701  }
6702  }
6703 
6704  free(option->val);
6705  option->val = value_copy;
6706 
6707  return option;
6708 }
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6540
static struct @154 value

References conninfo_find(), conninfo_uri_decode(), free, libpq_append_error(), option::val, and value.

Referenced by conninfo_parse(), conninfo_uri_parse_options(), conninfo_uri_parse_params(), and PQconninfo().

◆ conninfo_uri_decode()

static char * conninfo_uri_decode ( const char *  str,
PQExpBuffer  errorMessage 
)
static

Definition at line 6540 of file fe-connect.c.

6541 {
6542  char *buf;
6543  char *p;
6544  const char *q = str;
6545 
6546  buf = malloc(strlen(str) + 1);
6547  if (buf == NULL)
6548  {
6549  libpq_append_error(errorMessage, "out of memory");
6550  return NULL;
6551  }
6552  p = buf;
6553 
6554  for (;;)
6555  {
6556  if (*q != '%')
6557  {
6558  /* copy and check for NUL terminator */
6559  if (!(*(p++) = *(q++)))
6560  break;
6561  }
6562  else
6563  {
6564  int hi;
6565  int lo;
6566  int c;
6567 
6568  ++q; /* skip the percent sign itself */
6569 
6570  /*
6571  * Possible EOL will be caught by the first call to
6572  * get_hexdigit(), so we never dereference an invalid q pointer.
6573  */
6574  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6575  {
6576  libpq_append_error(errorMessage,
6577  "invalid percent-encoded token: \"%s\"",
6578  str);
6579  free(buf);
6580  return NULL;
6581  }
6582 
6583  c = (hi << 4) | lo;
6584  if (c == 0)
6585  {
6586  libpq_append_error(errorMessage,
6587  "forbidden value %%00 in percent-encoded value: \"%s\"",
6588  str);
6589  free(buf);
6590  return NULL;
6591  }
6592  *(p++) = c;
6593  }
6594  }
6595 
6596  return buf;
6597 }
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6608
char * c

References buf, free, get_hexdigit(), libpq_append_error(), malloc, and generate_unaccent_rules::str.

Referenced by conninfo_storeval(), and conninfo_uri_parse_params().

◆ conninfo_uri_parse()

static PQconninfoOption * conninfo_uri_parse ( const char *  uri,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

Definition at line 6113 of file fe-connect.c.

6115 {
6117 
6118  /* Make a working copy of PQconninfoOptions */
6119  options = conninfo_init(errorMessage);
6120  if (options == NULL)
6121  return NULL;
6122 
6123  if (!conninfo_uri_parse_options(options, uri, errorMessage))
6124  {
6126  return NULL;
6127  }
6128 
6129  /*
6130  * Add in defaults if the caller wants that.
6131  */
6132  if (use_defaults)
6133  {
6134  if (!conninfo_add_defaults(options, errorMessage))
6135  {
6137  return NULL;
6138  }
6139  }
6140 
6141  return options;
6142 }
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:6166

References conninfo_add_defaults(), conninfo_init(), conninfo_uri_parse_options(), options, and PQconninfoFree().

Referenced by parse_connection_string().

◆ conninfo_uri_parse_options()

static bool conninfo_uri_parse_options ( PQconninfoOption options,
const char *  uri,
PQExpBuffer  errorMessage 
)
static

Definition at line 6166 of file fe-connect.c.

6168 {
6169  int prefix_len;
6170  char *p;
6171  char *buf = NULL;
6172  char *start;
6173  char prevchar = '\0';
6174  char *user = NULL;
6175  char *host = NULL;
6176  bool retval = false;
6177  PQExpBufferData hostbuf;
6178  PQExpBufferData portbuf;
6179 
6180  initPQExpBuffer(&hostbuf);
6181  initPQExpBuffer(&portbuf);
6182  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6183  {
6184  libpq_append_error(errorMessage, "out of memory");
6185  goto cleanup;
6186  }
6187 
6188  /* need a modifiable copy of the input URI */
6189  buf = strdup(uri);
6190  if (buf == NULL)
6191  {
6192  libpq_append_error(errorMessage, "out of memory");
6193  goto cleanup;
6194  }
6195  start = buf;
6196 
6197  /* Skip the URI prefix */
6198  prefix_len = uri_prefix_length(uri);
6199  if (prefix_len == 0)
6200  {
6201  /* Should never happen */
6202  libpq_append_error(errorMessage,
6203  "invalid URI propagated to internal parser routine: \"%s\"",
6204  uri);
6205  goto cleanup;
6206  }
6207  start += prefix_len;
6208  p = start;
6209 
6210  /* Look ahead for possible user credentials designator */
6211  while (*p && *p != '@' && *p != '/')
6212  ++p;
6213  if (*p == '@')
6214  {
6215  /*
6216  * Found username/password designator, so URI should be of the form
6217  * "scheme://user[:password]@[netloc]".
6218  */
6219  user = start;
6220 
6221  p = user;
6222  while (*p != ':' && *p != '@')
6223  ++p;
6224 
6225  /* Save last char and cut off at end of user name */
6226  prevchar = *p;
6227  *p = '\0';
6228 
6229  if (*user &&
6230  !conninfo_storeval(options, "user", user,
6231  errorMessage, false, true))
6232  goto cleanup;
6233 
6234  if (prevchar == ':')
6235  {
6236  const char *password = p + 1;
6237 
6238  while (*p != '@')
6239  ++p;
6240  *p = '\0';
6241 
6242  if (*password &&
6243  !conninfo_storeval(options, "password", password,
6244  errorMessage, false, true))
6245  goto cleanup;
6246  }
6247 
6248  /* Advance past end of parsed user name or password token */
6249  ++p;
6250  }
6251  else
6252  {
6253  /*
6254  * No username/password designator found. Reset to start of URI.
6255  */
6256  p = start;
6257  }
6258 
6259  /*
6260  * There may be multiple netloc[:port] pairs, each separated from the next
6261  * by a comma. When we initially enter this loop, "p" has been
6262  * incremented past optional URI credential information at this point and
6263  * now points at the "netloc" part of the URI. On subsequent loop
6264  * iterations, "p" has been incremented past the comma separator and now
6265  * points at the start of the next "netloc".
6266  */
6267  for (;;)
6268  {
6269  /*
6270  * Look for IPv6 address.
6271  */
6272  if (*p == '[')
6273  {
6274  host = ++p;
6275  while (*p && *p != ']')
6276  ++p;
6277  if (!*p)
6278  {
6279  libpq_append_error(errorMessage,
6280  "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"",
6281  uri);
6282  goto cleanup;
6283  }
6284  if (p == host)
6285  {
6286  libpq_append_error(errorMessage,
6287  "IPv6 host address may not be empty in URI: \"%s\"",
6288  uri);
6289  goto cleanup;
6290  }
6291 
6292  /* Cut off the bracket and advance */
6293  *(p++) = '\0';
6294 
6295  /*
6296  * The address may be followed by a port specifier or a slash or a
6297  * query or a separator comma.
6298  */
6299  if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6300  {
6301  libpq_append_error(errorMessage,
6302  "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"",
6303  *p, (int) (p - buf + 1), uri);
6304  goto cleanup;
6305  }
6306  }
6307  else
6308  {
6309  /* not an IPv6 address: DNS-named or IPv4 netloc */
6310  host = p;
6311 
6312  /*
6313  * Look for port specifier (colon) or end of host specifier
6314  * (slash) or query (question mark) or host separator (comma).
6315  */
6316  while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6317  ++p;
6318  }
6319 
6320  /* Save the hostname terminator before we null it */
6321  prevchar = *p;
6322  *p = '\0';
6323 
6324  appendPQExpBufferStr(&hostbuf, host);
6325 
6326  if (prevchar == ':')
6327  {
6328  const char *port = ++p; /* advance past host terminator */
6329 
6330  while (*p && *p != '/' && *p != '?' && *p != ',')
6331  ++p;
6332 
6333  prevchar = *p;
6334  *p = '\0';
6335 
6336  appendPQExpBufferStr(&portbuf, port);
6337  }
6338 
6339  if (prevchar != ',')
6340  break;
6341  ++p; /* advance past comma separator */
6342  appendPQExpBufferChar(&hostbuf, ',');
6343  appendPQExpBufferChar(&portbuf, ',');
6344  }
6345 
6346  /* Save final values for host and port. */
6347  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6348  goto cleanup;
6349  if (hostbuf.data[0] &&
6350  !conninfo_storeval(options, "host", hostbuf.data,
6351  errorMessage, false, true))
6352  goto cleanup;
6353  if (portbuf.data[0] &&
6354  !conninfo_storeval(options, "port", portbuf.data,
6355  errorMessage, false, true))
6356  goto cleanup;
6357 
6358  if (prevchar && prevchar != '?')
6359  {
6360  const char *dbname = ++p; /* advance past host terminator */
6361 
6362  /* Look for query parameters */
6363  while (*p && *p != '?')
6364  ++p;
6365 
6366  prevchar = *p;
6367  *p = '\0';
6368 
6369  /*
6370  * Avoid setting dbname to an empty string, as it forces the default
6371  * value (username) and ignores $PGDATABASE, as opposed to not setting
6372  * it at all.
6373  */
6374  if (*dbname &&
6375  !conninfo_storeval(options, "dbname", dbname,
6376  errorMessage, false, true))
6377  goto cleanup;
6378  }
6379 
6380  if (prevchar)
6381  {
6382  ++p; /* advance past terminator */
6383 
6384  if (!conninfo_uri_parse_params(p, options, errorMessage))
6385  goto cleanup;
6386  }
6387 
6388  /* everything parsed okay */
6389  retval = true;
6390 
6391 cleanup:
6392  termPQExpBuffer(&hostbuf);
6393  termPQExpBuffer(&portbuf);
6394  free(buf);
6395  return retval;
6396 }
static void cleanup(void)
Definition: bootstrap.c:682
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5610
static bool conninfo_uri_parse_params(char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
Definition: fe-connect.c:6407
static char * user
Definition: pg_regress.c:120
static int port
Definition: pg_regress.c:116
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static char * password
Definition: streamutil.c:54
char * dbname
Definition: streamutil.c:52

References appendPQExpBufferChar(), appendPQExpBufferStr(), buf, cleanup(), conninfo_storeval(), conninfo_uri_parse_params(), PQExpBufferData::data, dbname, free, initPQExpBuffer(), libpq_append_error(), password, port, PQExpBufferDataBroken, termPQExpBuffer(), uri_prefix_length(), and user.

Referenced by conninfo_uri_parse().

◆ conninfo_uri_parse_params()

static bool conninfo_uri_parse_params ( char *  params,
PQconninfoOption connOptions,
PQExpBuffer  errorMessage 
)
static

Definition at line 6407 of file fe-connect.c.

6410 {
6411  while (*params)
6412  {
6413  char *keyword = params;
6414  char *value = NULL;
6415  char *p = params;
6416  bool malloced = false;
6417  int oldmsglen;
6418 
6419  /*
6420  * Scan the params string for '=' and '&', marking the end of keyword
6421  * and value respectively.
6422  */
6423  for (;;)
6424  {
6425  if (*p == '=')
6426  {
6427  /* Was there '=' already? */
6428  if (value != NULL)
6429  {
6430  libpq_append_error(errorMessage,
6431  "extra key/value separator \"=\" in URI query parameter: \"%s\"",
6432  keyword);
6433  return false;
6434  }
6435  /* Cut off keyword, advance to value */
6436  *p++ = '\0';
6437  value = p;
6438  }
6439  else if (*p == '&' || *p == '\0')
6440  {
6441  /*
6442  * If not at the end, cut off value and advance; leave p
6443  * pointing to start of the next parameter, if any.
6444  */
6445  if (*p != '\0')
6446  *p++ = '\0';
6447  /* Was there '=' at all? */
6448  if (value == NULL)
6449  {
6450  libpq_append_error(errorMessage,
6451  "missing key/value separator \"=\" in URI query parameter: \"%s\"",
6452  keyword);
6453  return false;
6454  }
6455  /* Got keyword and value, go process them. */
6456  break;
6457  }
6458  else
6459  ++p; /* Advance over all other bytes. */
6460  }
6461 
6462  keyword = conninfo_uri_decode(keyword, errorMessage);
6463  if (keyword == NULL)
6464  {
6465  /* conninfo_uri_decode already set an error message */
6466  return false;
6467  }
6468  value = conninfo_uri_decode(value, errorMessage);
6469  if (value == NULL)
6470  {
6471  /* conninfo_uri_decode already set an error message */
6472  free(keyword);
6473  return false;
6474  }
6475  malloced = true;
6476 
6477  /*
6478  * Special keyword handling for improved JDBC compatibility.
6479  */
6480  if (strcmp(keyword, "ssl") == 0 &&
6481  strcmp(value, "true") == 0)
6482  {
6483  free(keyword);
6484  free(value);
6485  malloced = false;
6486 
6487  keyword = "sslmode";
6488  value = "require";
6489  }
6490 
6491  /*
6492  * Store the value if the corresponding option exists; ignore
6493  * otherwise. At this point both keyword and value are not
6494  * URI-encoded.
6495  */
6496  oldmsglen = errorMessage->len;
6497  if (!conninfo_storeval(connOptions, keyword, value,
6498  errorMessage, true, false))
6499  {
6500  /* Insert generic message if conninfo_storeval didn't give one. */
6501  if (errorMessage->len == oldmsglen)
6502  libpq_append_error(errorMessage,
6503  "invalid URI query parameter: \"%s\"",
6504  keyword);
6505  /* And fail. */
6506  if (malloced)
6507  {
6508  free(keyword);
6509  free(value);
6510  }
6511  return false;
6512  }
6513 
6514  if (malloced)
6515  {
6516  free(keyword);
6517  free(value);
6518  }
6519 
6520  /* Proceed to next key=value pair, if any */
6521  params = p;
6522  }
6523 
6524  return true;
6525 }

References conninfo_storeval(), conninfo_uri_decode(), free, PQExpBufferData::len, libpq_append_error(), and value.

Referenced by conninfo_uri_parse_options().

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

Definition at line 1023 of file fe-connect.c.

1024 {
1025  int n;
1026 
1027  n = 1;
1028  for (; *input != '\0'; input++)
1029  {
1030  if (*input == ',')
1031  n++;
1032  }
1033 
1034  return n;
1035 }
FILE * input

References input.

Referenced by pqConnectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

Definition at line 7534 of file fe-connect.c.

7535 {
7536  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7537 
7538  if (acquire)
7539  {
7540  if (pthread_mutex_lock(&singlethread_lock))
7541  Assert(false);
7542  }
7543  else
7544  {
7545  if (pthread_mutex_unlock(&singlethread_lock))
7546  Assert(false);
7547  }
7548 }
Assert(fmt[strlen(fmt) - 1] !='\n')
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:60
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:42
#define PTHREAD_MUTEX_INITIALIZER
Definition: pthread-win32.h:16

References Assert(), PTHREAD_MUTEX_INITIALIZER, pthread_mutex_lock(), and pthread_mutex_unlock().

Referenced by PQregisterThreadLock().

◆ defaultNoticeProcessor()

static void defaultNoticeProcessor ( void *  arg,
const char *  message 
)
static

Definition at line 7165 of file fe-connect.c.

7166 {
7167  (void) arg; /* not used */
7168  /* Note: we expect the supplied string to end with a newline already. */
7169  fprintf(stderr, "%s", message);
7170 }
void * arg
#define fprintf
Definition: port.h:242

References arg, and fprintf.

Referenced by pqMakeEmptyPGconn().

◆ defaultNoticeReceiver()

static void defaultNoticeReceiver ( void *  arg,
const PGresult res 
)
static

Definition at line 7150 of file fe-connect.c.

7151 {
7152  (void) arg; /* not used */
7153  if (res->noticeHooks.noticeProc != NULL)
7156 }
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:3387
void * noticeProcArg
Definition: libpq-int.h:158
PQnoticeProcessor noticeProc
Definition: libpq-int.h:157
PGNoticeHooks noticeHooks
Definition: libpq-int.h:189

References arg, pg_result::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeProcArg, PQresultErrorMessage(), and res.

Referenced by pqMakeEmptyPGconn().

◆ emitHostIdentityInfo()

static void emitHostIdentityInfo ( PGconn conn,
const char *  host_addr 
)
static

Definition at line 2031 of file fe-connect.c.

2032 {
2033  if (conn->raddr.addr.ss_family == AF_UNIX)
2034  {
2035  char service[NI_MAXHOST];
2036 
2038  NULL, 0,
2039  service, sizeof(service),
2040  NI_NUMERICSERV);
2042  libpq_gettext("connection to server on socket \"%s\" failed: "),
2043  service);
2044  }
2045  else
2046  {
2047  const char *displayed_host;
2048  const char *displayed_port;
2049 
2050  /* To which host and port were we actually connecting? */
2052  displayed_host = conn->connhost[conn->whichhost].hostaddr;
2053  else
2054  displayed_host = conn->connhost[conn->whichhost].host;
2055  displayed_port = conn->connhost[conn->whichhost].port;
2056  if (displayed_port == NULL || displayed_port[0] == '\0')
2057  displayed_port = DEF_PGPORT_STR;
2058 
2059  /*
2060  * If the user did not supply an IP address using 'hostaddr', and
2061  * 'host' was missing or does not match our lookup, display the
2062  * looked-up IP address.
2063  */
2065  host_addr[0] &&
2066  strcmp(displayed_host, host_addr) != 0)
2068  libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
2069  displayed_host, host_addr,
2070  displayed_port);
2071  else
2073  libpq_gettext("connection to server at \"%s\", port %s failed: "),
2074  displayed_host,
2075  displayed_port);
2076  }
2077 }
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:114
#define libpq_gettext(x)
Definition: libpq-int.h:899
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:310
socklen_t salen
Definition: pqcomm.h:33
char * host
Definition: libpq-int.h:346
char * port
Definition: libpq-int.h:348
char * hostaddr
Definition: libpq-int.h:347
pg_conn_host_type type
Definition: libpq-int.h:345
int whichhost
Definition: libpq-int.h:445
pg_conn_host * connhost
Definition: libpq-int.h:446

References SockAddr::addr, appendPQExpBuffer(), CHT_HOST_ADDRESS, conn, pg_conn::connhost, pg_conn::errorMessage, pg_conn_host::host, pg_conn_host::hostaddr, libpq_gettext, pg_getnameinfo_all(), pg_conn_host::port, pg_conn::raddr, SockAddr::salen, pg_conn_host::type, and pg_conn::whichhost.

Referenced by PQconnectPoll().

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

Definition at line 907 of file fe-connect.c.

908 {
910 
911  for (option = PQconninfoOptions; option->keyword; option++)
912  {
913  if (option->connofs >= 0)
914  {
915  const char *tmp = conninfo_getval(connOptions, option->keyword);
916 
917  if (tmp)
918  {
919  char **connmember = (char **) ((char *) conn + option->connofs);
920 
921  free(*connmember);
922  *connmember = strdup(tmp);
923  if (*connmember == NULL)
924  {
925  libpq_append_conn_error(conn, "out of memory");
926  return false;
927  }
928  }
929  }
930  }
931 
932  return true;
933 }
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6629

References conn, conninfo_getval(), free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by connectOptions1(), and PQconnectStartParams().

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

Definition at line 4426 of file fe-connect.c.

4427 {
4428  /* let any event procs clean up their state data */
4429  for (int i = 0; i < conn->nEvents; i++)
4430  {
4431  PGEventConnDestroy evt;
4432 
4433  evt.conn = conn;
4434  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
4435  conn->events[i].passThrough);
4436  free(conn->events[i].name);
4437  }
4438 
4441 
4443  free(conn->events);
4444  free(conn->pghost);
4445  free(conn->pghostaddr);
4446  free(conn->pgport);
4449  free(conn->pgoptions);
4450  free(conn->appname);
4451  free(conn->fbappname);
4452  free(conn->dbName);
4453  free(conn->replication);
4454  free(conn->pguser);
4455  if (conn->pgpass)
4456  {
4457  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4458  free(conn->pgpass);
4459  }
4460  free(conn->pgpassfile);
4462  free(conn->keepalives);
4466  free(conn->sslmode);
4467  free(conn->sslcert);
4468  free(conn->sslkey);
4469  if (conn->sslpassword)
4470  {
4472  free(conn->sslpassword);
4473  }
4474  free(conn->sslcertmode);
4475  free(conn->sslrootcert);
4476  free(conn->sslcrl);
4477  free(conn->sslcrldir);
4479  free(conn->sslsni);
4480  free(conn->requirepeer);
4484  free(conn->gssencmode);
4485  free(conn->krbsrvname);
4486  free(conn->gsslib);
4488  free(conn->connip);
4489  /* Note that conn->Pfdebug is not ours to close or free */
4491  free(conn->inBuffer);
4492  free(conn->outBuffer);
4493  free(conn->rowBuf);
4498 
4499  free(conn);
4500 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4575
void pqReleaseConnHosts(PGconn *conn)
Definition: fe-connect.c:4507
@ PGEVT_CONNDESTROY
Definition: libpq-events.h:31
void explicit_bzero(void *buf, size_t len)
void * passThrough
Definition: libpq-int.h:165
char * name
Definition: libpq-int.h:164
PGEventProc proc
Definition: libpq-int.h:163
char * replication
Definition: libpq-int.h:378
char * write_err_msg
Definition: libpq-int.h:475
char * sslrootcert
Definition: libpq-int.h:396
PGdataValue * rowBuf
Definition: libpq-int.h:529
char * sslcompression
Definition: libpq-int.h:391
char * require_auth
Definition: libpq-int.h:409
char * inBuffer
Definition: libpq-int.h:512
char * channel_binding
Definition: libpq-int.h:382
char * sslcrldir
Definition: libpq-int.h:398
char * gssdelegation
Definition: libpq-int.h:405
char * pgoptions
Definition: libpq-int.h:374
char * sslcrl
Definition: libpq-int.h:397
char * pghost
Definition: libpq-int.h:361
char * ssl_max_protocol_version
Definition: libpq-int.h:407
char * pgpass
Definition: libpq-int.h:380
char * dbName
Definition: libpq-int.h:377
char * fbappname
Definition: libpq-int.h:376
char * sslcert
Definition: libpq-int.h:393
char * sslcertmode
Definition: libpq-int.h:395
char * target_session_attrs
Definition: libpq-int.h:408
char * sslpassword
Definition: libpq-int.h:394
PQExpBufferData workBuffer
Definition: libpq-int.h:625
char * keepalives_idle
Definition: libpq-int.h:385
char * connip
Definition: libpq-int.h:447
char * load_balance_hosts
Definition: libpq-int.h:410
char * pguser
Definition: libpq-int.h:379
char * keepalives
Definition: libpq-int.h:384
char * client_encoding_initial
Definition: libpq-int.h:373
char * keepalives_interval
Definition: libpq-int.h:386
char * appname
Definition: libpq-int.h:375
char * sslmode
Definition: libpq-int.h:390
char * pgtcp_user_timeout
Definition: libpq-int.h:372
char * ssl_min_protocol_version
Definition: libpq-int.h:406
char * gssencmode
Definition: libpq-int.h:401
int nEvents
Definition: libpq-int.h:425
char * pghostaddr
Definition: libpq-int.h:365
char * sslkey
Definition: libpq-int.h:392
char * pgpassfile
Definition: libpq-int.h:381
char * connect_timeout
Definition: libpq-int.h:371
char * krbsrvname
Definition: libpq-int.h:402
char * gsslib
Definition: libpq-int.h:403
char * pgport
Definition: libpq-int.h:369
char * keepalives_count
Definition: libpq-int.h:388
char * requirepeer
Definition: libpq-int.h:400
char * sslsni
Definition: libpq-int.h:399
PGEvent * events
Definition: libpq-int.h:424
char * outBuffer
Definition: libpq-int.h:519

References pg_conn::appname, pg_conn::channel_binding, pg_conn::client_encoding_initial, conn, PGEventConnDestroy::conn, pg_conn::connect_timeout, pg_conn::connip, pg_conn::dbName, pg_conn::errorMessage, pg_conn::events, explicit_bzero(), pg_conn::fbappname, free, pg_conn::gssdelegation, pg_conn::gssencmode, pg_conn::gsslib, i, pg_conn::inBuffer, pg_conn::keepalives, pg_conn::keepalives_count, pg_conn::keepalives_idle, pg_conn::keepalives_interval, pg_conn::krbsrvname, pg_conn::load_balance_hosts, PGEvent::name, pg_conn::nEvents, pg_conn::outBuffer, PGEvent::passThrough, PGEVT_CONNDESTROY, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgoptions, pg_conn::pgpass, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pgtcp_user_timeout, pg_conn::pguser, pqReleaseConnHosts(), PGEvent::proc, release_conn_addrinfo(), pg_conn::replication, pg_conn::require_auth, pg_conn::requirepeer, pg_conn::rowBuf, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, pg_conn::sslcert, pg_conn::sslcertmode, pg_conn::sslcompression, pg_conn::sslcrl, pg_conn::sslcrldir, pg_conn::sslkey, pg_conn::sslmode, pg_conn::sslpassword, pg_conn::sslrootcert, pg_conn::sslsni, pg_conn::target_session_attrs, termPQExpBuffer(), pg_conn::workBuffer, and pg_conn::write_err_msg.

Referenced by PQfinish(), and pqMakeEmptyPGconn().

◆ get_hexdigit()

static bool get_hexdigit ( char  digit,
int *  value 
)
static

Definition at line 6608 of file fe-connect.c.

6609 {
6610  if ('0' <= digit && digit <= '9')
6611  *value = digit - '0';
6612  else if ('A' <= digit && digit <= 'F')
6613  *value = digit - 'A' + 10;
6614  else if ('a' <= digit && digit <= 'f')
6615  *value = digit - 'a' + 10;
6616  else
6617  return false;
6618 
6619  return true;
6620 }

References value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

static void getHostaddr ( PGconn conn,
char *  host_addr,
int  host_addr_len 
)
static

Definition at line 1998 of file fe-connect.c.

1999 {
2000  struct sockaddr_storage *addr = &conn->raddr.addr;
2001 
2002  if (addr->ss_family == AF_INET)
2003  {
2004  if (pg_inet_net_ntop(AF_INET,
2005  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
2006  32,
2007  host_addr, host_addr_len) == NULL)
2008  host_addr[0] = '\0';
2009  }
2010  else if (addr->ss_family == AF_INET6)
2011  {
2012  if (pg_inet_net_ntop(AF_INET6,
2013  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
2014  128,
2015  host_addr, host_addr_len) == NULL)
2016  host_addr[0] = '\0';
2017  }
2018  else
2019  host_addr[0] = '\0';
2020 }
char * pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
Definition: inet_net_ntop.c:77

References SockAddr::addr, conn, pg_inet_net_ntop(), and pg_conn::raddr.

Referenced by PQconnectPoll().

◆ internal_ping()

static PGPing internal_ping ( PGconn conn)
static

Definition at line 4263 of file fe-connect.c.

4264 {
4265  /* Say "no attempt" if we never got to PQconnectPoll */
4266  if (!conn || !conn->options_valid)
4267  return PQPING_NO_ATTEMPT;
4268 
4269  /* Attempt to complete the connection */
4270  if (conn->status != CONNECTION_BAD)
4271  (void) pqConnectDBComplete(conn);
4272 
4273  /* Definitely OK if we succeeded */
4274  if (conn->status != CONNECTION_BAD)
4275  return PQPING_OK;
4276 
4277  /*
4278  * Here begins the interesting part of "ping": determine the cause of the
4279  * failure in sufficient detail to decide what to return. We do not want
4280  * to report that the server is not up just because we didn't have a valid
4281  * password, for example. In fact, any sort of authentication request
4282  * implies the server is up. (We need this check since the libpq side of
4283  * things might have pulled the plug on the connection before getting an
4284  * error as such from the postmaster.)
4285  */
4286  if (conn->auth_req_received)
4287  return PQPING_OK;
4288 
4289  /*
4290  * If we failed to get any ERROR response from the postmaster, report
4291  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
4292  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
4293  * out of support. Another corner case where the server could return a
4294  * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
4295  * isn't totally unreasonable for that anyway. We expect that every other
4296  * failure case in a modern server will produce a report with a SQLSTATE.
4297  *
4298  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
4299  * client-side errors, we should either not store those into
4300  * last_sqlstate, or add an extra flag so we can tell client-side errors
4301  * apart from server-side ones.
4302  */
4303  if (strlen(conn->last_sqlstate) != 5)
4304  return PQPING_NO_RESPONSE;
4305 
4306  /*
4307  * Report PQPING_REJECT if server says it's not accepting connections.
4308  */
4309  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
4310  return PQPING_REJECT;
4311 
4312  /*
4313  * Any other SQLSTATE can be taken to indicate that the server is up.
4314  * Presumably it didn't like our username, password, or database name; or
4315  * perhaps it had some transient failure, but that should not be taken as
4316  * meaning "it's down".
4317  */
4318  return PQPING_OK;
4319 }
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:91
int pqConnectDBComplete(PGconn *conn)
Definition: fe-connect.c:2408
@ PQPING_OK
Definition: libpq-fe.h:150
@ PQPING_REJECT
Definition: libpq-fe.h:151
@ PQPING_NO_RESPONSE
Definition: libpq-fe.h:152
@ PQPING_NO_ATTEMPT
Definition: libpq-fe.h:153
bool auth_req_received
Definition: libpq-int.h:469
char last_sqlstate[6]
Definition: libpq-int.h:432
bool options_valid
Definition: libpq-int.h:433

References pg_conn::auth_req_received, conn, CONNECTION_BAD, ERRCODE_CANNOT_CONNECT_NOW, pg_conn::last_sqlstate, pg_conn::options_valid, pqConnectDBComplete(), PQPING_NO_ATTEMPT, PQPING_NO_RESPONSE, PQPING_OK, PQPING_REJECT, and pg_conn::status.

Referenced by PQping(), and PQpingParams().

◆ libpq_prng_init()

static void libpq_prng_init ( PGconn conn)
static

Definition at line 1082 of file fe-connect.c.

1083 {
1084  uint64 rseed;
1085  struct timeval tval = {0};
1086 
1088  return;
1089 
1090  gettimeofday(&tval, NULL);
1091 
1092  rseed = ((uintptr_t) conn) ^
1093  ((uint64) getpid()) ^
1094  ((uint64) tval.tv_usec) ^
1095  ((uint64) tval.tv_sec);
1096 
1097  pg_prng_seed(&conn->prng_state, rseed);
1098 }
void pg_prng_seed(pg_prng_state *state, uint64 seed)
Definition: pg_prng.c:89
#define pg_prng_strong_seed(state)
Definition: pg_prng.h:46
pg_prng_state prng_state
Definition: libpq-int.h:508
int gettimeofday(struct timeval *tp, void *tzp)

References conn, gettimeofday(), pg_prng_seed(), pg_prng_strong_seed, and pg_conn::prng_state.

Referenced by pqConnectOptions2().

◆ parse_comma_separated_list()

static char* parse_comma_separated_list ( char **  startptr,
bool more 
)
static

Definition at line 1047 of file fe-connect.c.

1048 {
1049  char *p;
1050  char *s = *startptr;
1051  char *e;
1052  int len;
1053 
1054  /*
1055  * Search for the end of the current element; a comma or end-of-string
1056  * acts as a terminator.
1057  */
1058  e = s;
1059  while (*e != '\0' && *e != ',')
1060  ++e;
1061  *more = (*e == ',');
1062 
1063  len = e - s;
1064  p = (char *) malloc(sizeof(char) * (len + 1));
1065  if (p)
1066  {
1067  memcpy(p, s, len);
1068  p[len] = '\0';
1069  }
1070  *startptr = e + 1;
1071 
1072  return p;
1073 }
const void size_t len
e
Definition: preproc-init.c:82

References len, and malloc.

Referenced by pqConnectOptions2().

◆ parse_connection_string()

static PQconninfoOption * parse_connection_string ( const char *  connstr,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

Definition at line 5590 of file fe-connect.c.

5592 {
5593  /* Parse as URI if connection string matches URI prefix */
5594  if (uri_prefix_length(connstr) != 0)
5595  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5596 
5597  /* Parse as default otherwise */
5598  return conninfo_parse(connstr, errorMessage, use_defaults);
5599 }
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6113
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5644
static char * connstr
Definition: pg_dumpall.c:90

References conninfo_parse(), conninfo_uri_parse(), connstr, and uri_prefix_length().

Referenced by connectOptions1(), conninfo_array_parse(), and PQconninfoParse().

◆ parseServiceFile()

static int parseServiceFile ( const char *  serviceFile,
const char *  service,
PQconninfoOption options,
PQExpBuffer  errorMessage,
bool group_found 
)
static

Definition at line 5351 of file fe-connect.c.

5356 {
5357  int result = 0,
5358  linenr = 0,
5359  i;
5360  FILE *f;
5361  char *line;
5362  char buf[1024];
5363 
5364  *group_found = false;
5365 
5366  f = fopen(serviceFile, "r");
5367  if (f == NULL)
5368  {
5369  libpq_append_error(errorMessage, "service file \"%s\" not found", serviceFile);
5370  return 1;
5371  }
5372 
5373  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5374  {
5375  int len;
5376 
5377  linenr++;
5378 
5379  if (strlen(line) >= sizeof(buf) - 1)
5380  {
5381  libpq_append_error(errorMessage,
5382  "line %d too long in service file \"%s\"",
5383  linenr,
5384  serviceFile);
5385  result = 2;
5386  goto exit;
5387  }
5388 
5389  /* ignore whitespace at end of line, especially the newline */
5390  len = strlen(line);
5391  while (len > 0 && isspace((unsigned char) line[len - 1]))
5392  line[--len] = '\0';
5393 
5394  /* ignore leading whitespace too */
5395  while (*line && isspace((unsigned char) line[0]))
5396  line++;
5397 
5398  /* ignore comments and empty lines */
5399  if (line[0] == '\0' || line[0] == '#')
5400  continue;
5401 
5402  /* Check for right groupname */
5403  if (line[0] == '[')
5404  {
5405  if (*group_found)
5406  {
5407  /* end of desired group reached; return success */
5408  goto exit;
5409  }
5410 
5411  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5412  line[strlen(service) + 1] == ']')
5413  *group_found = true;
5414  else
5415  *group_found = false;
5416  }
5417  else
5418  {
5419  if (*group_found)
5420  {
5421  /*
5422  * Finally, we are in the right group and can parse the line
5423  */
5424  char *key,
5425  *val;
5426  bool found_keyword;
5427 
5428 #ifdef USE_LDAP
5429  if (strncmp(line, "ldap", 4) == 0)
5430  {
5431  int rc = ldapServiceLookup(line, options, errorMessage);
5432 
5433  /* if rc = 2, go on reading for fallback */
5434  switch (rc)
5435  {
5436  case 0:
5437  goto exit;
5438  case 1:
5439  case 3:
5440  result = 3;
5441  goto exit;
5442  case 2:
5443  continue;
5444  }
5445  }
5446 #endif
5447 
5448  key = line;
5449  val = strchr(line, '=');
5450  if (val == NULL)
5451  {
5452  libpq_append_error(errorMessage,
5453  "syntax error in service file \"%s\", line %d",
5454  serviceFile,
5455  linenr);
5456  result = 3;
5457  goto exit;
5458  }
5459  *val++ = '\0';
5460 
5461  if (strcmp(key, "service") == 0)
5462  {
5463  libpq_append_error(errorMessage,
5464  "nested service specifications not supported in service file \"%s\", line %d",
5465  serviceFile,
5466  linenr);
5467  result = 3;
5468  goto exit;
5469  }
5470 
5471  /*
5472  * Set the parameter --- but don't override any previous
5473  * explicit setting.
5474  */
5475  found_keyword = false;
5476  for (i = 0; options[i].keyword; i++)
5477  {
5478  if (strcmp(options[i].keyword, key) == 0)
5479  {
5480  if (options[i].val == NULL)
5481  options[i].val = strdup(val);
5482  if (!options[i].val)
5483  {
5484  libpq_append_error(errorMessage, "out of memory");
5485  result = 3;
5486  goto exit;
5487  }
5488  found_keyword = true;
5489  break;
5490  }
5491  }
5492 
5493  if (!found_keyword)
5494  {
5495  libpq_append_error(errorMessage,
5496  "syntax error in service file \"%s\", line %d",
5497  serviceFile,
5498  linenr);
5499  result = 3;
5500  goto exit;
5501  }
5502  }
5503  }
5504  }
5505 
5506 exit:
5507  fclose(f);
5508 
5509  return result;
5510 }
exit(1)

References buf, exit(), i, sort-test::key, len, libpq_append_error(), and val.

Referenced by parseServiceInfo().

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

Definition at line 5283 of file fe-connect.c.

5284 {
5285  const char *service = conninfo_getval(options, "service");
5286  char serviceFile[MAXPGPATH];
5287  char *env;
5288  bool group_found = false;
5289  int status;
5290  struct stat stat_buf;
5291 
5292  /*
5293  * We have to special-case the environment variable PGSERVICE here, since
5294  * this is and should be called before inserting environment defaults for
5295  * other connection options.
5296  */
5297  if (service == NULL)
5298  service = getenv("PGSERVICE");
5299 
5300  /* If no service name given, nothing to do */
5301  if (service == NULL)
5302  return 0;
5303 
5304  /*
5305  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5306  * exists).
5307  */
5308  if ((env = getenv("PGSERVICEFILE")) != NULL)
5309  strlcpy(serviceFile, env, sizeof(serviceFile));
5310  else
5311  {
5312  char homedir[MAXPGPATH];
5313 
5314  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5315  goto next_file;
5316  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5317  if (stat(serviceFile, &stat_buf) != 0)
5318  goto next_file;
5319  }
5320 
5321  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5322  if (group_found || status != 0)
5323  return status;
5324 
5325 next_file:
5326 
5327  /*
5328  * This could be used by any application so we can't use the binary
5329  * location to find our config files.
5330  */
5331  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5332  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5333  if (stat(serviceFile, &stat_buf) != 0)
5334  goto last_file;
5335 
5336  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5337  if (status != 0)
5338  return status;
5339 
5340 last_file:
5341  if (!group_found)
5342  {
5343  libpq_append_error(errorMessage, "definition of service \"%s\" not found", service);
5344  return 3;
5345  }
5346 
5347  return 0;
5348 }
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:5351
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7456
#define MAXPGPATH
#define snprintf
Definition: port.h:238
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define stat
Definition: win32_port.h:284

References conninfo_getval(), libpq_append_error(), MAXPGPATH, parseServiceFile(), pqGetHomeDirectory(), snprintf, stat, and strlcpy().

Referenced by conninfo_add_defaults().

◆ passwordFromFile()

static char * passwordFromFile ( const char *  hostname,
const char *  port,
const char *  dbname,
const char *  username,
const char *  pgpassfile 
)
static

Definition at line 7214 of file fe-connect.c.

7216 {
7217  FILE *fp;
7218  struct stat stat_buf;
7220 
7221  if (dbname == NULL || dbname[0] == '\0')
7222  return NULL;
7223 
7224  if (username == NULL || username[0] == '\0')
7225  return NULL;
7226 
7227  /* 'localhost' matches pghost of '' or the default socket directory */
7228  if (hostname == NULL || hostname[0] == '\0')
7230  else if (is_unixsock_path(hostname))
7231 
7232  /*
7233  * We should probably use canonicalize_path(), but then we have to
7234  * bring path.c into libpq, and it doesn't seem worth it.
7235  */
7236  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
7238 
7239  if (port == NULL || port[0] == '\0')
7240  port = DEF_PGPORT_STR;
7241 
7242  /* If password file cannot be opened, ignore it. */
7243  if (stat(pgpassfile, &stat_buf) != 0)
7244  return NULL;
7245 
7246 #ifndef WIN32
7247  if (!S_ISREG(stat_buf.st_mode))
7248  {
7249  fprintf(stderr,
7250  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
7251  pgpassfile);
7252  return NULL;
7253  }
7254 
7255  /* If password file is insecure, alert the user and ignore it. */
7256  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
7257  {
7258  fprintf(stderr,
7259  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
7260  pgpassfile);
7261  return NULL;
7262  }
7263 #else
7264 
7265  /*
7266  * On Win32, the directory is protected, so we don't have to check the
7267  * file.
7268  */
7269 #endif
7270 
7271  fp = fopen(pgpassfile, "r");
7272  if (fp == NULL)
7273  return NULL;
7274 
7275  /* Use an expansible buffer to accommodate any reasonable line length */
7276  initPQExpBuffer(&buf);
7277 
7278  while (!feof(fp) && !ferror(fp))
7279  {
7280  /* Make sure there's a reasonable amount of room in the buffer */
7281  if (!enlargePQExpBuffer(&buf, 128))
7282  break;
7283 
7284  /* Read some data, appending it to what we already have */
7285  if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
7286  break;
7287  buf.len += strlen(buf.data + buf.len);
7288 
7289  /* If we don't yet have a whole line, loop around to read more */
7290  if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
7291  continue;
7292 
7293  /* ignore comments */
7294  if (buf.data[0] != '#')
7295  {
7296  char *t = buf.data;
7297  int len;
7298 
7299  /* strip trailing newline and carriage return */
7300  len = pg_strip_crlf(t);
7301 
7302  if (len > 0 &&
7303  (t = pwdfMatchesString(t, hostname)) != NULL &&
7304  (t = pwdfMatchesString(t, port)) != NULL &&
7305  (t = pwdfMatchesString(t, dbname)) != NULL &&
7306  (t = pwdfMatchesString(t, username)) != NULL)
7307  {
7308  /* Found a match. */
7309  char *ret,
7310  *p1,
7311  *p2;
7312 
7313  ret = strdup(t);
7314 
7315  fclose(fp);
7316  explicit_bzero(buf.data, buf.maxlen);
7317  termPQExpBuffer(&buf);
7318 
7319  if (!ret)
7320  {
7321  /* Out of memory. XXX: an error message would be nice. */
7322  return NULL;
7323  }
7324 
7325  /* De-escape password. */
7326  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
7327  {
7328  if (*p1 == '\\' && p1[1] != '\0')
7329  ++p1;
7330  *p2 = *p1;
7331  }
7332  *p2 = '\0';
7333 
7334  return ret;
7335  }
7336  }
7337 
7338  /* No match, reset buffer to prepare for next line. */
7339  buf.len = 0;
7340  }
7341 
7342  fclose(fp);
7343  explicit_bzero(buf.data, buf.maxlen);
7344  termPQExpBuffer(&buf);
7345  return NULL;
7346 }
#define DefaultHost
Definition: fe-connect.c:116
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:7177
#define DEFAULT_PGSOCKET_DIR
static char * hostname
Definition: pg_regress.c:115
const char * username
Definition: pgbench.c:296
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:67
int enlargePQExpBuffer(PQExpBuffer str, size_t needed)
Definition: pqexpbuffer.c:172
int pg_strip_crlf(char *str)
Definition: string.c:155
#define S_IRWXG
Definition: win32_port.h:310
#define S_IRWXO
Definition: win32_port.h:322
#define S_ISREG(m)
Definition: win32_port.h:328

References buf, dbname, DEFAULT_PGSOCKET_DIR, DefaultHost, enlargePQExpBuffer(), explicit_bzero(), fprintf, hostname, initPQExpBuffer(), is_unixsock_path(), len, libpq_gettext, p2, pg_strip_crlf(), port, pwdfMatchesString(), S_IRWXG, S_IRWXO, S_ISREG, stat::st_mode, stat, termPQExpBuffer(), and username.

Referenced by pqConnectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

Definition at line 7354 of file fe-connect.c.

7355 {
7356  /* If it was 'invalid authorization', add pgpassfile mention */
7357  /* only works with >= 9.0 servers */
7358  if (conn->password_needed &&
7359  conn->connhost[conn->whichhost].password != NULL &&
7360  conn->result)
7361  {
7362  const char *sqlstate = PQresultErrorField(conn->result,
7364 
7365  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7366  libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
7367  conn->pgpassfile);
7368  }
7369 }
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:89
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3426
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:56
char * password
Definition: libpq-int.h:349
PGresult * result
Definition: libpq-int.h:541
bool password_needed
Definition: libpq-int.h:470

References conn, pg_conn::connhost, ERRCODE_INVALID_PASSWORD, libpq_append_conn_error(), pg_conn_host::password, pg_conn::password_needed, PG_DIAG_SQLSTATE, pg_conn::pgpassfile, PQresultErrorField(), pg_conn::result, and pg_conn::whichhost.

Referenced by PQconnectPoll().

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

Definition at line 6982 of file fe-connect.c.

6983 {
6984  if (!conn || conn->status != CONNECTION_OK)
6985  return 0;
6986  return conn->be_pid;
6987 }
@ CONNECTION_OK
Definition: libpq-fe.h:60
int be_pid
Definition: libpq-int.h:498

References pg_conn::be_pid, conn, CONNECTION_OK, and pg_conn::status.

Referenced by get_prompt(), libpqrcv_get_backend_pid(), main(), send_cancellable_query_impl(), and StartLogStreamer().

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ pqClosePGconn()

void pqClosePGconn ( PGconn conn)

Definition at line 4623 of file fe-connect.c.

4624 {
4625  /*
4626  * If possible, send Terminate message to close the connection politely.
4627  */
4629 
4630  /*
4631  * Must reset the blocking status so a possible reconnect will work.
4632  *
4633  * Don't call PQsetnonblocking() because it will fail if it's unable to
4634  * flush the connection.
4635  */
4636  conn->nonblocking = false;
4637 
4638  /*
4639  * Close the connection, reset all transient state, flush I/O buffers.
4640  * Note that this includes clearing conn's error state; we're no longer
4641  * interested in any failures associated with the old connection, and we
4642  * want a clean slate for any new connection attempt.
4643  */
4644  pqDropConnection(conn, true);
4645  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4649  pqClearAsyncResult(conn); /* deallocate result */
4651 
4652  /*
4653  * Release addrinfo, but since cancel requests never change their addrinfo
4654  * we don't do that. Otherwise we would have to rebuild it during a
4655  * PQcancelReset.
4656  */
4657  if (!conn->cancelRequest)
4659 
4660  /* Reset all state obtained from server, too */
4662 }
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:460
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4589
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:573
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:777
@ PQTRANS_IDLE
Definition: libpq-fe.h:121
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:161
@ PGASYNC_IDLE
Definition: libpq-int.h:221
#define pqClearConnErrorState(conn)
Definition: libpq-int.h:872
PGTransactionStatusType xactStatus
Definition: libpq-int.h:431
bool cancelRequest
Definition: libpq-int.h:412
bool nonblocking
Definition: libpq-int.h:434
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:430
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:436

References pg_conn::asyncStatus, pg_conn::cancelRequest, conn, CONNECTION_BAD, pg_conn::nonblocking, PGASYNC_IDLE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqClearAsyncResult(), pqClearConnErrorState, pqDropConnection(), pqDropServerData(), PQTRANS_IDLE, release_conn_addrinfo(), sendTerminateConn(), pg_conn::status, and pg_conn::xactStatus.

Referenced by PQcancelReset(), PQfinish(), PQreset(), and PQresetStart().

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

Definition at line 1819 of file fe-connect.c.

1820 {
1821  PQExpBufferData errorBuf;
1822  PQconninfoOption *connOptions;
1823 
1824  /* We don't actually report any errors here, but callees want a buffer */
1825  initPQExpBuffer(&errorBuf);
1826  if (PQExpBufferDataBroken(errorBuf))
1827  return NULL; /* out of memory already :-( */
1828 
1829  connOptions = conninfo_init(&errorBuf);
1830  if (connOptions != NULL)
1831  {
1832  /* pass NULL errorBuf to ignore errors */
1833  if (!conninfo_add_defaults(connOptions, NULL))
1834  {
1835  PQconninfoFree(connOptions);
1836  connOptions = NULL;
1837  }
1838  }
1839 
1840  termPQExpBuffer(&errorBuf);
1841  return connOptions;
1842 }

References conninfo_add_defaults(), conninfo_init(), initPQExpBuffer(), PQconninfoFree(), PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by check_pghost_envvar(), dblink_fdw_validator(), do_connect(), get_connect_string(), GetDbnameFromConnectionOptions(), InitPgFdwOptions(), and main().

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

Definition at line 733 of file fe-connect.c.

734 {
735  PGconn *conn = PQconnectStart(conninfo);
736 
737  if (conn && conn->status != CONNECTION_BAD)
738  (void) pqConnectDBComplete(conn);
739 
740  return conn;
741 }
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:861

References conn, CONNECTION_BAD, pqConnectDBComplete(), PQconnectStart(), and pg_conn::status.

Referenced by connect_database(), get_db_conn(), and main().

◆ pqConnectDBComplete()

int pqConnectDBComplete ( PGconn conn)

Definition at line 2408 of file fe-connect.c.

2409 {
2411  time_t finish_time = ((time_t) -1);
2412  int timeout = 0;
2413  int last_whichhost = -2; /* certainly different from whichhost */
2414  int last_whichaddr = -2; /* certainly different from whichaddr */
2415 
2416  if (conn == NULL || conn->status == CONNECTION_BAD)
2417  return 0;
2418 
2419  /*
2420  * Set up a time limit, if connect_timeout isn't zero.
2421  */
2422  if (conn->connect_timeout != NULL)
2423  {
2424  if (!pqParseIntParam(conn->connect_timeout, &timeout, conn,
2425  "connect_timeout"))
2426  {
2427  /* mark the connection as bad to report the parsing failure */
2429  return 0;
2430  }
2431 
2432  if (timeout > 0)
2433  {
2434  /*
2435  * Rounding could cause connection to fail unexpectedly quickly;
2436  * to prevent possibly waiting hardly-at-all, insist on at least
2437  * two seconds.
2438  */
2439  if (timeout < 2)
2440  timeout = 2;
2441  }
2442  else /* negative means 0 */
2443  timeout = 0;
2444  }
2445 
2446  for (;;)
2447  {
2448  int ret = 0;
2449 
2450  /*
2451  * (Re)start the connect_timeout timer if it's active and we are
2452  * considering a different host than we were last time through. If
2453  * we've already succeeded, though, needn't recalculate.
2454  */
2455  if (flag != PGRES_POLLING_OK &&
2456  timeout > 0 &&
2457  (conn->whichhost != last_whichhost ||
2458  conn->whichaddr != last_whichaddr))
2459  {
2460  finish_time = time(NULL) + timeout;
2461  last_whichhost = conn->whichhost;
2462  last_whichaddr = conn->whichaddr;
2463  }
2464 
2465  /*
2466  * Wait, if necessary. Note that the initial state (just after
2467  * PQconnectStart) is to wait for the socket to select for writing.
2468  */
2469  switch (flag)
2470  {
2471  case PGRES_POLLING_OK:
2472  return 1; /* success! */
2473 
2474  case PGRES_POLLING_READING:
2475  ret = pqWaitTimed(1, 0, conn, finish_time);
2476  if (ret == -1)
2477  {
2478  /* hard failure, eg select() problem, aborts everything */
2480  return 0;
2481  }
2482  break;
2483 
2484  case PGRES_POLLING_WRITING:
2485  ret = pqWaitTimed(0, 1, conn, finish_time);
2486  if (ret == -1)
2487  {
2488  /* hard failure, eg select() problem, aborts everything */
2490  return 0;
2491  }
2492  break;
2493 
2494  default:
2495  /* Just in case we failed to set it in PQconnectPoll */
2497  return 0;
2498  }
2499 
2500  if (ret == 1) /* connect_timeout elapsed */
2501  {
2502  /*
2503  * Give up on current server/address, try the next one.
2504  */
2505  conn->try_next_addr = true;
2507  }
2508 
2509  /*
2510  * Now try to advance the state machine.
2511  */
2512  if (conn->cancelRequest)
2514  else
2515  flag = PQconnectPoll(conn);
2516  }
2517 }
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
Definition: fe-cancel.c:207
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2547
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:7483
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:992
@ CONNECTION_NEEDED
Definition: libpq-fe.h:76
PostgresPollingStatusType
Definition: libpq-fe.h:88
@ PGRES_POLLING_OK
Definition: libpq-fe.h:92
@ PGRES_POLLING_READING
Definition: libpq-fe.h:90
@ PGRES_POLLING_WRITING
Definition: libpq-fe.h:91
int whichaddr
Definition: libpq-int.h:492
bool try_next_addr
Definition: libpq-int.h:489
char * flag(int b)
Definition: test-ctype.c:33

References pg_conn::cancelRequest, conn, pg_conn::connect_timeout, CONNECTION_BAD, CONNECTION_NEEDED, flag(), PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQcancelPoll(), PQconnectPoll(), pqParseIntParam(), pqWaitTimed(), pg_conn::status, pg_conn::try_next_addr, pg_conn::whichaddr, and pg_conn::whichhost.

Referenced by internal_ping(), PQcancelBlocking(), PQconnectdb(), PQconnectdbParams(), PQreset(), and PQsetdbLogin().

◆ PQconnectdbParams()

PGconn* PQconnectdbParams ( const char *const *  keywords,
const char *const *  values,
int  expand_dbname 
)

Definition at line 678 of file fe-connect.c.

681 {
682  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
683 
684  if (conn && conn->status != CONNECTION_BAD)
685  (void) pqConnectDBComplete(conn);
686 
687  return conn;
688 }
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:780

References conn, CONNECTION_BAD, pqConnectDBComplete(), PQconnectStartParams(), pg_conn::status, and values.

Referenced by ConnectDatabase(), connectDatabase(), copy_connection(), do_connect(), doConnect(), ECPGconnect(), GetConnection(), main(), sql_conn(), and vacuumlo().

◆ pqConnectDBStart()

int pqConnectDBStart ( PGconn conn)

Definition at line 2330 of file fe-connect.c.

2331 {
2332  if (!conn)
2333  return 0;
2334 
2335  if (!conn->options_valid)
2336  goto connect_errReturn;
2337 
2338  /*
2339  * Check for bad linking to backend-internal versions of src/common
2340  * functions (see comments in link-canary.c for the reason we need this).
2341  * Nobody but developers should see this message, so we don't bother
2342  * translating it.
2343  */
2345  {
2347  "libpq is incorrectly linked to backend functions\n");
2348  goto connect_errReturn;
2349  }
2350 
2351  /* Ensure our buffers are empty */
2352  conn->inStart = conn->inCursor = conn->inEnd = 0;
2353  conn->outCount = 0;
2354 
2355  /*
2356  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2357  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2358  * anything else looks at it.)
2359  *
2360  * Cancel requests are special though, they should only try one host and
2361  * address, and these fields have already been set up in PQcancelCreate,
2362  * so leave these fields alone for cancel requests.
2363  */
2364  if (!conn->cancelRequest)
2365  {
2366  conn->whichhost = -1;
2367  conn->try_next_host = true;
2368  conn->try_next_addr = false;
2369  }
2370 
2372 
2373  /* Also reset the target_server_type state if needed */
2376 
2377  /*
2378  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2379  * so that it can easily be re-executed if needed again during the
2380  * asynchronous startup process. However, we must run it once here,
2381  * because callers expect a success return from this routine to mean that
2382  * we are in PGRES_POLLING_WRITING connection state.
2383  */
2385  return 1;
2386 
2387 connect_errReturn:
2388 
2389  /*
2390  * If we managed to open a socket, close it immediately rather than
2391  * waiting till PQfinish. (The application cannot have gotten the socket
2392  * from PQsocket yet, so this doesn't risk breaking anything.)
2393  */
2394  pqDropConnection(conn, true);
2396  return 0;
2397 }
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition: libpq-int.h:243
@ SERVER_TYPE_PREFER_STANDBY
Definition: libpq-int.h:242
bool try_next_host
Definition: libpq-int.h:490
int inCursor
Definition: libpq-int.h:515
int inEnd
Definition: libpq-int.h:516
int inStart
Definition: libpq-int.h:514
PGTargetServerType target_server_type
Definition: libpq-int.h:486
int outCount
Definition: libpq-int.h:521

References appendPQExpBufferStr(), pg_conn::cancelRequest, conn, CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::options_valid, pg_conn::outCount, pg_link_canary_is_frontend(), PGRES_POLLING_WRITING, PQconnectPoll(), pqDropConnection(), SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PREFER_STANDBY_PASS2, pg_conn::status, pg_conn::target_server_type, pg_conn::try_next_addr, pg_conn::try_next_host, and pg_conn::whichhost.

Referenced by PQcancelStart(), PQconnectStart(), PQconnectStartParams(), PQreset(), PQresetStart(), and PQsetdbLogin().

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

Definition at line 6999 of file fe-connect.c.

7000 {
7001  char *password;
7002 
7003  if (!conn)
7004  return false;
7005  password = PQpass(conn);
7006  if (conn->password_needed &&
7007  (password == NULL || password[0] == '\0'))
7008  return true;
7009  else
7010  return false;
7011 }
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6810

References conn, password, pg_conn::password_needed, and PQpass().

Referenced by ConnectDatabase(), connectDatabase(), do_connect(), doConnect(), GetConnection(), main(), sql_conn(), and vacuumlo().

◆ PQconnectionUsedGSSAPI()

int PQconnectionUsedGSSAPI ( const PGconn conn)

Definition at line 7025 of file fe-connect.c.

7026 {
7027  if (!conn)
7028  return false;
7029  if (conn->gssapi_used)
7030  return true;
7031  else
7032  return false;
7033 }
bool gssapi_used
Definition: libpq-int.h:471

References conn, and pg_conn::gssapi_used.

Referenced by dblink_security_check(), and pgfdw_security_check().

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

Definition at line 7014 of file fe-connect.c.

7015 {
7016  if (!conn)
7017  return false;
7018  if (conn->password_needed)
7019  return true;
7020  else
7021  return false;
7022 }

References conn, and pg_conn::password_needed.

Referenced by ConnectDatabase(), dblink_security_check(), libpqrcv_connect(), and pgfdw_security_check().

◆ pqConnectOptions2()

bool pqConnectOptions2 ( PGconn conn)

Definition at line 1109 of file fe-connect.c.

1110 {
1111  int i;
1112 
1113  /*
1114  * Allocate memory for details about each host to which we might possibly
1115  * try to connect. For that, count the number of elements in the hostaddr
1116  * or host options. If neither is given, assume one host.
1117  */
1118  conn->whichhost = 0;
1119  if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1121  else if (conn->pghost && conn->pghost[0] != '\0')
1123  else
1124  conn->nconnhost = 1;
1125  conn->connhost = (pg_conn_host *)
1126  calloc(conn->nconnhost, sizeof(pg_conn_host));
1127  if (conn->connhost == NULL)
1128  goto oom_error;
1129 
1130  /*
1131  * We now have one pg_conn_host structure per possible host. Fill in the
1132  * host and hostaddr fields for each, by splitting the parameter strings.
1133  */
1134  if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1135  {
1136  char *s = conn->pghostaddr;
1137  bool more = true;
1138 
1139  for (i = 0; i < conn->nconnhost && more; i++)
1140  {
1142  if (conn->connhost[i].hostaddr == NULL)
1143  goto oom_error;
1144  }
1145 
1146  /*
1147  * If hostaddr was given, the array was allocated according to the
1148  * number of elements in the hostaddr list, so it really should be the
1149  * right size.
1150  */
1151  Assert(!more);
1152  Assert(i == conn->nconnhost);
1153  }
1154 
1155  if (conn->pghost != NULL && conn->pghost[0] != '\0')
1156  {
1157  char *s = conn->pghost;
1158  bool more = true;
1159 
1160  for (i = 0; i < conn->nconnhost && more; i++)
1161  {
1163  if (conn->connhost[i].host == NULL)
1164  goto oom_error;
1165  }
1166 
1167  /* Check for wrong number of host items. */
1168  if (more || i != conn->nconnhost)
1169  {
1171  libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
1173  return false;
1174  }
1175  }
1176 
1177  /*
1178  * Now, for each host slot, identify the type of address spec, and fill in
1179  * the default address if nothing was given.
1180  */
1181  for (i = 0; i < conn->nconnhost; i++)
1182  {
1183  pg_conn_host *ch = &conn->connhost[i];
1184 
1185  if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1186  ch->type = CHT_HOST_ADDRESS;
1187  else if (ch->host != NULL && ch->host[0] != '\0')
1188  {
1189  ch->type = CHT_HOST_NAME;
1190  if (is_unixsock_path(ch->host))
1191  ch->type = CHT_UNIX_SOCKET;
1192  }
1193  else
1194  {
1195  free(ch->host);
1196 
1197  /*
1198  * This bit selects the default host location. If you change
1199  * this, see also pg_regress.
1200  */
1201  if (DEFAULT_PGSOCKET_DIR[0])
1202  {
1203  ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1204  ch->type = CHT_UNIX_SOCKET;
1205  }
1206  else
1207  {
1208  ch->host = strdup(DefaultHost);
1209  ch->type = CHT_HOST_NAME;
1210  }
1211  if (ch->host == NULL)
1212  goto oom_error;
1213  }
1214  }
1215 
1216  /*
1217  * Next, work out the port number corresponding to each host name.
1218  *
1219  * Note: unlike the above for host names, this could leave the port fields
1220  * as null or empty strings. We will substitute DEF_PGPORT whenever we
1221  * read such a port field.
1222  */
1223  if (conn->pgport != NULL && conn->pgport[0] != '\0')
1224  {
1225  char *s = conn->pgport;
1226  bool more = true;
1227 
1228  for (i = 0; i < conn->nconnhost && more; i++)
1229  {
1231  if (conn->connhost[i].port == NULL)
1232  goto oom_error;
1233  }
1234 
1235  /*
1236  * If exactly one port was given, use it for every host. Otherwise,
1237  * there must be exactly as many ports as there were hosts.
1238  */
1239  if (i == 1 && !more)
1240  {
1241  for (i = 1; i < conn->nconnhost; i++)
1242  {
1243  conn->connhost[i].port = strdup(conn->connhost[0].port);
1244  if (conn->connhost[i].port == NULL)
1245  goto oom_error;
1246  }
1247  }
1248  else if (more || i != conn->nconnhost)
1249  {
1251  libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
1253  return false;
1254  }
1255  }
1256 
1257  /*
1258  * If user name was not given, fetch it. (Most likely, the fetch will
1259  * fail, since the only way we get here is if pg_fe_getauthname() failed
1260  * during conninfo_add_defaults(). But now we want an error message.)
1261  */
1262  if (conn->pguser == NULL || conn->pguser[0] == '\0')
1263  {
1264  free(conn->pguser);
1266  if (!conn->pguser)
1267  {
1269  return false;
1270  }
1271  }
1272 
1273  /*
1274  * If database name was not given, default it to equal user name
1275  */
1276  if (conn->dbName == NULL || conn->dbName[0] == '\0')
1277  {
1278  free(conn->dbName);
1279  conn->dbName = strdup(conn->pguser);
1280  if (!conn->dbName)
1281  goto oom_error;
1282  }
1283 
1284  /*
1285  * If password was not given, try to look it up in password file. Note
1286  * that the result might be different for each host/port pair.
1287  */
1288  if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1289  {
1290  /* If password file wasn't specified, use ~/PGPASSFILE */
1291  if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1292  {
1293  char homedir[MAXPGPATH];
1294 
1295  if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1296  {
1297  free(conn->pgpassfile);
1299  if (!conn->pgpassfile)
1300  goto oom_error;
1301  snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1302  homedir, PGPASSFILE);
1303  }
1304  }
1305 
1306  if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1307  {
1308  for (i = 0; i < conn->nconnhost; i++)
1309  {
1310  /*
1311  * Try to get a password for this host from file. We use host
1312  * for the hostname search key if given, else hostaddr (at
1313  * least one of them is guaranteed nonempty by now).
1314  */
1315  const char *pwhost = conn->connhost[i].host;
1316 
1317  if (pwhost == NULL || pwhost[0] == '\0')
1318  pwhost = conn->connhost[i].hostaddr;
1319 
1320  conn->connhost[i].password =
1321  passwordFromFile(pwhost,
1322  conn->connhost[i].port,
1323  conn->dbName,
1324  conn->pguser,
1325  conn->pgpassfile);
1326  }
1327  }
1328  }
1329 
1330  /*
1331  * parse and validate require_auth option
1332  */
1333  if (conn->require_auth && conn->require_auth[0])
1334  {
1335  char *s = conn->require_auth;
1336  bool first,
1337  more;
1338  bool negated = false;
1339 
1340  /*
1341  * By default, start from an empty set of allowed options and add to
1342  * it.
1343  */
1344  conn->auth_required = true;
1346 
1347  for (first = true, more = true; more; first = false)
1348  {
1349  char *method,
1350  *part;
1351  uint32 bits;
1352 
1353  part = parse_comma_separated_list(&s, &more);
1354  if (part == NULL)
1355  goto oom_error;
1356 
1357  /*
1358  * Check for negation, e.g. '!password'. If one element is
1359  * negated, they all have to be.
1360  */
1361  method = part;
1362  if (*method == '!')
1363  {
1364  if (first)
1365  {
1366  /*
1367  * Switch to a permissive set of allowed options, and
1368  * subtract from it.
1369  */
1370  conn->auth_required = false;
1371  conn->allowed_auth_methods = -1;
1372  }
1373  else if (!negated)
1374  {
1376  libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
1377  method);
1378 
1379  free(part);
1380  return false;
1381  }
1382 
1383  negated = true;
1384  method++;
1385  }
1386  else if (negated)
1387  {
1389  libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
1390  method);
1391 
1392  free(part);
1393  return false;
1394  }
1395 
1396  if (strcmp(method, "password") == 0)
1397  {
1398  bits = (1 << AUTH_REQ_PASSWORD);
1399  }
1400  else if (strcmp(method, "md5") == 0)
1401  {
1402  bits = (1 << AUTH_REQ_MD5);
1403  }
1404  else if (strcmp(method, "gss") == 0)
1405  {
1406  bits = (1 << AUTH_REQ_GSS);
1407  bits |= (1 << AUTH_REQ_GSS_CONT);
1408  }
1409  else if (strcmp(method, "sspi") == 0)
1410  {
1411  bits = (1 << AUTH_REQ_SSPI);
1412  bits |= (1 << AUTH_REQ_GSS_CONT);
1413  }
1414  else if (strcmp(method, "scram-sha-256") == 0)
1415  {
1416  /* This currently assumes that SCRAM is the only SASL method. */
1417  bits = (1 << AUTH_REQ_SASL);
1418  bits |= (1 << AUTH_REQ_SASL_CONT);
1419  bits |= (1 << AUTH_REQ_SASL_FIN);
1420  }
1421  else if (strcmp(method, "none") == 0)
1422  {
1423  /*
1424  * Special case: let the user explicitly allow (or disallow)
1425  * connections where the server does not send an explicit
1426  * authentication challenge, such as "trust" and "cert" auth.
1427  */
1428  if (negated) /* "!none" */
1429  {
1430  if (conn->auth_required)
1431  goto duplicate;
1432 
1433  conn->auth_required = true;
1434  }
1435  else /* "none" */
1436  {
1437  if (!conn->auth_required)
1438  goto duplicate;
1439 
1440  conn->auth_required = false;
1441  }
1442 
1443  free(part);
1444  continue; /* avoid the bitmask manipulation below */
1445  }
1446  else
1447  {
1449  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1450  "require_auth", method);
1451 
1452  free(part);
1453  return false;
1454  }
1455 
1456  /* Update the bitmask. */
1457  if (negated)
1458  {
1459  if ((conn->allowed_auth_methods & bits) == 0)
1460  goto duplicate;
1461 
1462  conn->allowed_auth_methods &= ~bits;
1463  }
1464  else
1465  {
1466  if ((conn->allowed_auth_methods & bits) == bits)
1467  goto duplicate;
1468 
1469  conn->allowed_auth_methods |= bits;
1470  }
1471 
1472  free(part);
1473  continue;
1474 
1475  duplicate:
1476 
1477  /*
1478  * A duplicated method probably indicates a typo in a setting
1479  * where typos are extremely risky.
1480  */
1482  libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
1483  part);
1484 
1485  free(part);
1486  return false;
1487  }
1488  }
1489 
1490  /*
1491  * validate channel_binding option
1492  */
1493  if (conn->channel_binding)
1494  {
1495  if (strcmp(conn->channel_binding, "disable") != 0
1496  && strcmp(conn->channel_binding, "prefer") != 0
1497  && strcmp(conn->channel_binding, "require") != 0)
1498  {
1500  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1501  "channel_binding", conn->channel_binding);
1502  return false;
1503  }
1504  }
1505  else
1506  {
1508  if (!conn->channel_binding)
1509  goto oom_error;
1510  }
1511 
1512 #ifndef USE_SSL
1513 
1514  /*
1515  * sslrootcert=system is not supported. Since setting this changes the
1516  * default sslmode, check this _before_ we validate sslmode, to avoid
1517  * confusing the user with errors for an option they may not have set.
1518  */
1519  if (conn->sslrootcert
1520  && strcmp(conn->sslrootcert, "system") == 0)
1521  {
1523  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1524  "sslrootcert", conn->sslrootcert);
1525  return false;
1526  }
1527 #endif
1528 
1529  /*
1530  * validate sslmode option
1531  */
1532  if (conn->sslmode)
1533  {
1534  if (strcmp(conn->sslmode, "disable") != 0
1535  && strcmp(conn->sslmode, "allow") != 0
1536  && strcmp(conn->sslmode, "prefer") != 0
1537  && strcmp(conn->sslmode, "require") != 0
1538  && strcmp(conn->sslmode, "verify-ca") != 0
1539  && strcmp(conn->sslmode, "verify-full") != 0)
1540  {
1542  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1543  "sslmode", conn->sslmode);
1544  return false;
1545  }
1546 
1547 #ifndef USE_SSL
1548  switch (conn->sslmode[0])
1549  {
1550  case 'a': /* "allow" */
1551  case 'p': /* "prefer" */
1552 
1553  /*
1554  * warn user that an SSL connection will never be negotiated
1555  * since SSL was not compiled in?
1556  */
1557  break;
1558 
1559  case 'r': /* "require" */
1560  case 'v': /* "verify-ca" or "verify-full" */
1562  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1563  "sslmode", conn->sslmode);
1564  return false;
1565  }
1566 #endif
1567  }
1568  else
1569  {
1570  conn->sslmode = strdup(DefaultSSLMode);
1571  if (!conn->sslmode)
1572  goto oom_error;
1573  }
1574 
1575 #ifdef USE_SSL
1576 
1577  /*
1578  * If sslrootcert=system, make sure our chosen sslmode is compatible.
1579  */
1580  if (conn->sslrootcert
1581  && strcmp(conn->sslrootcert, "system") == 0
1582  && strcmp(conn->sslmode, "verify-full") != 0)
1583  {
1585  libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
1586  conn->sslmode);
1587  return false;
1588  }
1589 #endif
1590 
1591  /*
1592  * Validate TLS protocol versions for ssl_min_protocol_version and
1593  * ssl_max_protocol_version.
1594  */
1596  {
1598  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1599  "ssl_min_protocol_version",
1601  return false;
1602  }
1604  {
1606  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1607  "ssl_max_protocol_version",
1609  return false;
1610  }
1611 
1612  /*
1613  * Check if the range of SSL protocols defined is correct. This is done
1614  * at this early step because this is independent of the SSL
1615  * implementation used, and this avoids unnecessary cycles with an
1616  * already-built SSL context when the connection is being established, as
1617  * it would be doomed anyway.
1618  */
1621  {
1623  libpq_append_conn_error(conn, "invalid SSL protocol version range");
1624  return false;
1625  }
1626 
1627  /*
1628  * validate sslcertmode option
1629  */
1630  if (conn->sslcertmode)
1631  {
1632  if (strcmp(conn->sslcertmode, "disable") != 0 &&
1633  strcmp(conn->sslcertmode, "allow") != 0 &&
1634  strcmp(conn->sslcertmode, "require") != 0)
1635  {
1637  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1638  "sslcertmode", conn->sslcertmode);
1639  return false;
1640  }
1641 #ifndef USE_SSL
1642  if (strcmp(conn->sslcertmode, "require") == 0)
1643  {
1645  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1646  "sslcertmode", conn->sslcertmode);
1647  return false;
1648  }
1649 #endif
1650 #ifndef HAVE_SSL_CTX_SET_CERT_CB
1651 
1652  /*
1653  * Without a certificate callback, the current implementation can't
1654  * figure out if a certificate was actually requested, so "require" is
1655  * useless.
1656  */
1657  if (strcmp(conn->sslcertmode, "require") == 0)
1658  {
1660  libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
1661  "sslcertmode", conn->sslcertmode);
1662  return false;
1663  }
1664 #endif
1665  }
1666  else
1667  {
1668  conn->sslcertmode = strdup(DefaultSSLCertMode);
1669  if (!conn->sslcertmode)
1670  goto oom_error;
1671  }
1672 
1673  /*
1674  * validate gssencmode option
1675  */
1676  if (conn->gssencmode)
1677  {
1678  if (strcmp(conn->gssencmode, "disable") != 0 &&
1679  strcmp(conn->gssencmode, "prefer") != 0 &&
1680  strcmp(conn->gssencmode, "require") != 0)
1681  {
1683  libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1684  return false;
1685  }
1686 #ifndef ENABLE_GSS
1687  if (strcmp(conn->gssencmode, "require") == 0)
1688  {
1690  libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
1691  conn->gssencmode);
1692  return false;
1693  }
1694 #endif
1695  }
1696  else
1697  {
1698  conn->gssencmode = strdup(DefaultGSSMode);
1699  if (!conn->gssencmode)
1700  goto oom_error;
1701  }
1702 
1703  /*
1704  * validate target_session_attrs option, and set target_server_type
1705  */
1707  {
1708  if (strcmp(conn->target_session_attrs, "any") == 0)
1710  else if (strcmp(conn->target_session_attrs, "read-write") == 0)
1712  else if (strcmp(conn->target_session_attrs, "read-only") == 0)
1714  else if (strcmp(conn->target_session_attrs, "primary") == 0)
1716  else if (strcmp(conn->target_session_attrs, "standby") == 0)
1718  else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
1720  else
1721  {
1723  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1724  "target_session_attrs",
1726  return false;
1727  }
1728  }
1729  else
1731 
1732  /*
1733  * validate load_balance_hosts option, and set load_balance_type
1734  */
1735  if (conn->load_balance_hosts)
1736  {
1737  if (strcmp(conn->load_balance_hosts, "disable") == 0)
1739  else if (strcmp(conn->load_balance_hosts, "random") == 0)
1741  else
1742  {
1744  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1745  "load_balance_hosts",
1747  return false;
1748  }
1749  }
1750  else
1752 
1754  {
1756 
1757  /*
1758  * This is the "inside-out" variant of the Fisher-Yates shuffle
1759  * algorithm. Notionally, we append each new value to the array and
1760  * then swap it with a randomly-chosen array element (possibly
1761  * including itself, else we fail to generate permutations with the
1762  * last integer last). The swap step can be optimized by combining it
1763  * with the insertion.
1764  */
1765  for (i = 1; i < conn->nconnhost; i++)
1766  {
1767  int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
1768  pg_conn_host temp = conn->connhost[j];
1769 
1770  conn->connhost[j] = conn->connhost[i];
1771  conn->connhost[i] = temp;
1772  }
1773  }
1774 
1775  /*
1776  * Resolve special "auto" client_encoding from the locale
1777  */
1779  strcmp(conn->client_encoding_initial, "auto") == 0)
1780  {
1784  goto oom_error;
1785  }
1786 
1787  /*
1788  * Only if we get this far is it appropriate to try to connect. (We need a
1789  * state flag, rather than just the boolean result of this function, in
1790  * case someone tries to PQreset() the PGconn.)
1791  */
1792  conn->options_valid = true;
1793 
1794  return true;
1795 
1796 oom_error:
1798  libpq_append_conn_error(conn, "out of memory");
1799  return false;
1800 }
unsigned int uint32
Definition: c.h:493
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:7214
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7403
static void libpq_prng_init(PGconn *conn)
Definition: fe-connect.c:1082
#define DefaultSSLMode
Definition: fe-connect.c:129
#define DefaultGSSMode
Definition: fe-connect.c:136
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:1023
#define DefaultChannelBinding
Definition: fe-connect.c:121
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:7377
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:1047
#define PGPASSFILE
Definition: fe-connect.c:75
#define DefaultSSLCertMode
Definition: fe-connect.c:130
#define calloc(a, b)
Definition: header.h:55
int j
Definition: isn.c:74
@ LOAD_BALANCE_DISABLE
Definition: libpq-int.h:249
@ LOAD_BALANCE_RANDOM
Definition: libpq-int.h:250
@ CHT_UNIX_SOCKET
Definition: libpq-int.h:311
@ CHT_HOST_NAME
Definition: libpq-int.h:309
@ SERVER_TYPE_STANDBY
Definition: libpq-int.h:241
@ SERVER_TYPE_PRIMARY
Definition: libpq-int.h:240
@ SERVER_TYPE_ANY
Definition: libpq-int.h:237
@ SERVER_TYPE_READ_WRITE
Definition: libpq-int.h:238
@ SERVER_TYPE_READ_ONLY
Definition: libpq-int.h:239
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:144
#define pg_encoding_to_char
Definition: pg_wchar.h:630
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:428
#define AUTH_REQ_SSPI
Definition: protocol.h:79
#define AUTH_REQ_SASL_CONT
Definition: protocol.h:81
#define AUTH_REQ_GSS
Definition: protocol.h:77
#define AUTH_REQ_MD5
Definition: protocol.h:75
#define AUTH_REQ_PASSWORD
Definition: protocol.h:73
#define AUTH_REQ_GSS_CONT
Definition: protocol.h:78
#define AUTH_REQ_SASL
Definition: protocol.h:80
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:82
int nconnhost
Definition: libpq-int.h:444
uint32 allowed_auth_methods
Definition: libpq-int.h:479
bool auth_required
Definition: libpq-int.h:477
PGLoadBalanceType load_balance_type
Definition: libpq-int.h:487

References pg_conn::allowed_auth_methods, Assert(), AUTH_REQ_GSS, AUTH_REQ_GSS_CONT, AUTH_REQ_MD5, AUTH_REQ_PASSWORD, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, AUTH_REQ_SSPI, pg_conn::auth_required, calloc, pg_conn::channel_binding, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, pg_conn::client_encoding_initial, conn, CONNECTION_BAD, pg_conn::connhost, count_comma_separated_elems(), pg_conn::dbName, DEFAULT_PGSOCKET_DIR, DefaultChannelBinding, DefaultGSSMode, DefaultHost, DefaultSSLCertMode, DefaultSSLMode, pg_conn::errorMessage, free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, is_unixsock_path(), j, libpq_append_conn_error(), libpq_prng_init(), LOAD_BALANCE_DISABLE, pg_conn::load_balance_hosts, LOAD_BALANCE_RANDOM, pg_conn::load_balance_type, malloc, MAXPGPATH, pg_conn::nconnhost, pg_conn::options_valid, parse_comma_separated_list(), pg_conn_host::password, passwordFromFile(), pg_encoding_to_char, pg_fe_getauthname(), pg_get_encoding_from_locale(), pg_prng_uint64_range(), pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgpass, PGPASSFILE, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pguser, pg_conn_host::port, pqGetHomeDirectory(), pg_conn::prng_state, pg_conn::require_auth, SERVER_TYPE_ANY, SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PRIMARY, SERVER_TYPE_READ_ONLY, SERVER_TYPE_READ_WRITE, SERVER_TYPE_STANDBY, snprintf, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, pg_conn::sslcertmode, pg_conn::sslmode, pg_conn::sslrootcert, sslVerifyProtocolRange(), sslVerifyProtocolVersion(), pg_conn::status, pg_conn::target_server_type, pg_conn::target_session_attrs, pg_conn_host::type, and pg_conn::whichhost.

Referenced by PQcancelCreate(), PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

Definition at line 2547 of file fe-connect.c.

2548 {
2549  bool reset_connection_state_machine = false;
2550  bool need_new_connection = false;
2551  PGresult *res;
2552  char sebuf[PG_STRERROR_R_BUFLEN];
2553  int optval;
2554 
2555  if (conn == NULL)
2556  return PGRES_POLLING_FAILED;
2557 
2558  /* Get the new data */
2559  switch (conn->status)
2560  {
2561  /*
2562  * We really shouldn't have been polled in these two cases, but we
2563  * can handle it.
2564  */
2565  case CONNECTION_BAD:
2566  return PGRES_POLLING_FAILED;
2567  case CONNECTION_OK:
2568  return PGRES_POLLING_OK;
2569 
2570  /* These are reading states */
2572  case CONNECTION_AUTH_OK:
2574  case CONNECTION_CONSUME:
2576  {
2577  /* Load waiting data */
2578  int n = pqReadData(conn);
2579 
2580  if (n < 0)
2581  goto error_return;
2582  if (n == 0)
2583  return PGRES_POLLING_READING;
2584 
2585  break;
2586  }
2587 
2588  /* These are writing states, so we just proceed. */
2589  case CONNECTION_STARTED:
2590  case CONNECTION_MADE:
2591  break;
2592 
2593  /* Special cases: proceed without waiting. */
2595  case CONNECTION_NEEDED:
2598  break;
2599 
2600  default:
2601  libpq_append_conn_error(conn, "invalid connection state, probably indicative of memory corruption");
2602  goto error_return;
2603  }
2604 
2605 
2606 keep_going: /* We will come back to here until there is
2607  * nothing left to do. */
2608 
2609  /* Time to advance to next address, or next host if no more addresses? */
2610  if (conn->try_next_addr)
2611  {
2612  if (conn->whichaddr < conn->naddr)
2613  {
2614  conn->whichaddr++;
2615  reset_connection_state_machine = true;
2616  }
2617  else
2618  conn->try_next_host = true;
2619  conn->try_next_addr = false;
2620  }
2621 
2622  /* Time to advance to next connhost[] entry? */
2623  if (conn->try_next_host)
2624  {
2625  pg_conn_host *ch;
2626  struct addrinfo hint;
2627  struct addrinfo *addrlist;
2628  int thisport;
2629  int ret;
2630  char portstr[MAXPGPATH];
2631 
2632  if (conn->whichhost + 1 < conn->nconnhost)
2633  conn->whichhost++;
2634  else
2635  {
2636  /*
2637  * Oops, no more hosts.
2638  *
2639  * If we are trying to connect in "prefer-standby" mode, then drop
2640  * the standby requirement and start over. Don't do this for
2641  * cancel requests though, since we are certain the list of
2642  * servers won't change as the target_server_type option is not
2643  * applicable to those connections.
2644  *
2645  * Otherwise, an appropriate error message is already set up, so
2646  * we just need to set the right status.
2647  */
2649  conn->nconnhost > 0 &&
2650  !conn->cancelRequest)
2651  {
2653  conn->whichhost = 0;
2654  }
2655  else
2656  goto error_return;
2657  }
2658 
2659  /* Drop any address info for previous host */
2661 
2662  /*
2663  * Look up info for the new host. On failure, log the problem in
2664  * conn->errorMessage, then loop around to try the next host. (Note
2665  * we don't clear try_next_host until we've succeeded.)
2666  */
2667  ch = &conn->connhost[conn->whichhost];
2668 
2669  /* Initialize hint structure */
2670  MemSet(&hint, 0, sizeof(hint));
2671  hint.ai_socktype = SOCK_STREAM;
2672  hint.ai_family = AF_UNSPEC;
2673 
2674  /* Figure out the port number we're going to use. */
2675  if (ch->port == NULL || ch->port[0] == '\0')
2676  thisport = DEF_PGPORT;
2677  else
2678  {
2679  if (!pqParseIntParam(ch->port, &thisport, conn, "port"))
2680  goto error_return;
2681 
2682  if (thisport < 1 || thisport > 65535)
2683  {
2684  libpq_append_conn_error(conn, "invalid port number: \"%s\"", ch->port);
2685  goto keep_going;
2686  }
2687  }
2688  snprintf(portstr, sizeof(portstr), "%d", thisport);
2689 
2690  /* Use pg_getaddrinfo_all() to resolve the address */
2691  switch (ch->type)
2692  {
2693  case CHT_HOST_NAME:
2694  ret = pg_getaddrinfo_all(ch->host, portstr, &hint,
2695  &addrlist);
2696  if (ret || !addrlist)
2697  {
2698  libpq_append_conn_error(conn, "could not translate host name \"%s\" to address: %s",
2699  ch->host, gai_strerror(ret));
2700  goto keep_going;
2701  }
2702  break;
2703 
2704  case CHT_HOST_ADDRESS:
2705  hint.ai_flags = AI_NUMERICHOST;
2706  ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint,
2707  &addrlist);
2708  if (ret || !addrlist)
2709  {
2710  libpq_append_conn_error(conn, "could not parse network address \"%s\": %s",
2711  ch->hostaddr, gai_strerror(ret));
2712  goto keep_going;
2713  }
2714  break;
2715 
2716  case CHT_UNIX_SOCKET:
2717  hint.ai_family = AF_UNIX;
2718  UNIXSOCK_PATH(portstr, thisport, ch->host);
2719  if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
2720  {
2721  libpq_append_conn_error(conn, "Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
2722  portstr,
2723  (int) (UNIXSOCK_PATH_BUFLEN - 1));
2724  goto keep_going;
2725  }
2726 
2727  /*
2728  * NULL hostname tells pg_getaddrinfo_all to parse the service
2729  * name as a Unix-domain socket path.
2730  */
2731  ret = pg_getaddrinfo_all(NULL, portstr, &hint,
2732  &addrlist);
2733  if (ret || !addrlist)
2734  {
2735  libpq_append_conn_error(conn, "could not translate Unix-domain socket path \"%s\" to address: %s",
2736  portstr, gai_strerror(ret));
2737  goto keep_going;
2738  }
2739  break;
2740  }
2741 
2742  /*
2743  * Store a copy of the addrlist in private memory so we can perform
2744  * randomization for load balancing.
2745  */
2746  ret = store_conn_addrinfo(conn, addrlist);
2747  pg_freeaddrinfo_all(hint.ai_family, addrlist);
2748  if (ret)
2749  goto error_return; /* message already logged */
2750 
2751  /*
2752  * If random load balancing is enabled we shuffle the addresses.
2753  */
2755  {
2756  /*
2757  * This is the "inside-out" variant of the Fisher-Yates shuffle
2758  * algorithm. Notionally, we append each new value to the array
2759  * and then swap it with a randomly-chosen array element (possibly
2760  * including itself, else we fail to generate permutations with
2761  * the last integer last). The swap step can be optimized by
2762  * combining it with the insertion.
2763  *
2764  * We don't need to initialize conn->prng_state here, because that
2765  * already happened in pqConnectOptions2.
2766  */
2767  for (int i = 1; i < conn->naddr; i++)
2768  {
2769  int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
2770  AddrInfo temp = conn->addr[j];
2771 
2772  conn->addr[j] = conn->addr[i];
2773  conn->addr[i] = temp;
2774  }
2775  }
2776 
2777  reset_connection_state_machine = true;
2778  conn->try_next_host = false;
2779  }
2780 
2781  /* Reset connection state machine? */
2782  if (reset_connection_state_machine)
2783  {
2784  /*
2785  * (Re) initialize our connection control variables for a set of
2786  * connection attempts to a single server address. These variables
2787  * must persist across individual connection attempts, but we must
2788  * reset them when we start to consider a new server.
2789  */
2790  conn->pversion = PG_PROTOCOL(3, 0);
2791  conn->send_appname = true;
2792 #ifdef USE_SSL
2793  /* initialize these values based on SSL mode */
2794  conn->allow_ssl_try = (conn->sslmode[0] != 'd'); /* "disable" */
2795  conn->wait_ssl_try = (conn->sslmode[0] == 'a'); /* "allow" */
2796 #endif
2797 #ifdef ENABLE_GSS
2798  conn->try_gss = (conn->gssencmode[0] != 'd'); /* "disable" */
2799 #endif
2800 
2801  reset_connection_state_machine = false;
2802  need_new_connection = true;
2803  }
2804 
2805  /* Force a new connection (perhaps to the same server as before)? */
2806  if (need_new_connection)
2807  {
2808  /* Drop any existing connection */
2809  pqDropConnection(conn, true);
2810 
2811  /* Reset all state obtained from old server */
2813 
2814  /* Drop any PGresult we might have, too */
2819 
2820  /* Reset conn->status to put the state machine in the right state */
2822 
2823  need_new_connection = false;
2824  }
2825 
2826  /* Now try to advance the state machine for this connection */
2827  switch (conn->status)
2828  {
2829  case CONNECTION_NEEDED:
2830  {
2831  /*
2832  * Try to initiate a connection to one of the addresses
2833  * returned by pg_getaddrinfo_all(). conn->whichaddr is the
2834  * next one to try.
2835  *
2836  * The extra level of braces here is historical. It's not
2837  * worth reindenting this whole switch case to remove 'em.
2838  */
2839  {
2840  char host_addr[NI_MAXHOST];
2841  int sock_type;
2842  AddrInfo *addr_cur;
2843 
2844  /*
2845  * Advance to next possible host, if we've tried all of
2846  * the addresses for the current host.
2847  */
2848  if (conn->whichaddr == conn->naddr)
2849  {
2850  conn->try_next_host = true;
2851  goto keep_going;
2852  }
2853  addr_cur = &conn->addr[conn->whichaddr];
2854 
2855  /* Remember current address for possible use later */
2856  memcpy(&conn->raddr, &addr_cur->addr, sizeof(SockAddr));
2857 
2858  /*
2859  * Set connip, too. Note we purposely ignore strdup
2860  * failure; not a big problem if it fails.
2861  */
2862  if (conn->connip != NULL)
2863  {
2864  free(conn->connip);
2865  conn->connip = NULL;
2866  }
2867  getHostaddr(conn, host_addr, NI_MAXHOST);
2868  if (host_addr[0])
2869  conn->connip = strdup(host_addr);
2870 
2871  /* Try to create the socket */
2872  sock_type = SOCK_STREAM;
2873 #ifdef SOCK_CLOEXEC
2874 
2875  /*
2876  * Atomically mark close-on-exec, if possible on this
2877  * platform, so that there isn't a window where a
2878  * subprogram executed by another thread inherits the
2879  * socket. See fallback code below.
2880  */
2881  sock_type |= SOCK_CLOEXEC;
2882 #endif
2883 #ifdef SOCK_NONBLOCK
2884 
2885  /*
2886  * We might as well skip a system call for nonblocking
2887  * mode too, if we can.
2888  */
2889  sock_type |= SOCK_NONBLOCK;
2890 #endif
2891  conn->sock = socket(addr_cur->family, sock_type, 0);
2892  if (conn->sock == PGINVALID_SOCKET)
2893  {
2894  int errorno = SOCK_ERRNO;
2895 
2896  /*
2897  * Silently ignore socket() failure if we have more
2898  * addresses to try; this reduces useless chatter in
2899  * cases where the address list includes both IPv4 and
2900  * IPv6 but kernel only accepts one family.
2901  */
2902  if (conn->whichaddr < conn->naddr ||
2903  conn->whichhost + 1 < conn->nconnhost)
2904  {
2905  conn->try_next_addr = true;
2906  goto keep_going;
2907  }
2908  emitHostIdentityInfo(conn, host_addr);
2909  libpq_append_conn_error(conn, "could not create socket: %s",
2910  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2911  goto error_return;
2912  }
2913 
2914  /*
2915  * Once we've identified a target address, all errors
2916  * except the preceding socket()-failure case should be
2917  * prefixed with host-identity information. (If the
2918  * connection succeeds, the contents of conn->errorMessage
2919  * won't matter, so this is harmless.)
2920  */
2921  emitHostIdentityInfo(conn, host_addr);
2922 
2923  /*
2924  * Select socket options: no delay of outgoing data for
2925  * TCP sockets, nonblock mode, close-on-exec. Try the
2926  * next address if any of this fails.
2927  */
2928  if (addr_cur->family != AF_UNIX)
2929  {
2930  if (!connectNoDelay(conn))
2931  {
2932  /* error message already created */
2933  conn->try_next_addr = true;
2934  goto keep_going;
2935  }
2936  }
2937 #ifndef SOCK_NONBLOCK
2938  if (!pg_set_noblock(conn->sock))
2939  {
2940  libpq_append_conn_error(conn, "could not set socket to nonblocking mode: %s",
2941  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2942  conn->try_next_addr = true;
2943  goto keep_going;
2944  }
2945 #endif
2946 
2947 #ifndef SOCK_CLOEXEC
2948 #ifdef F_SETFD
2949  if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
2950  {
2951  libpq_append_conn_error(conn, "could not set socket to close-on-exec mode: %s",
2952  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2953  conn->try_next_addr = true;
2954  goto keep_going;
2955  }
2956 #endif /* F_SETFD */
2957 #endif
2958 
2959  if (addr_cur->family != AF_UNIX)
2960  {
2961 #ifndef WIN32
2962  int on = 1;
2963 #endif
2964  int usekeepalives = useKeepalives(conn);
2965  int err = 0;
2966 
2967  if (usekeepalives < 0)
2968  {
2969  libpq_append_conn_error(conn, "keepalives parameter must be an integer");
2970  err = 1;
2971  }
2972  else if (usekeepalives == 0)
2973  {
2974  /* Do nothing */
2975  }
2976 #ifndef WIN32
2977  else if (setsockopt(conn->sock,
2978  SOL_SOCKET, SO_KEEPALIVE,
2979  (char *) &on, sizeof(on)) < 0)
2980  {
2981  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2982  "setsockopt",
2983  "SO_KEEPALIVE",
2984  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2985  err = 1;
2986  }
2987  else if (!setKeepalivesIdle(conn)
2989  || !setKeepalivesCount(conn))
2990  err = 1;
2991 #else /* WIN32 */
2992 #ifdef SIO_KEEPALIVE_VALS
2993  else if (!prepKeepalivesWin32(conn))
2994  err = 1;
2995 #endif /* SIO_KEEPALIVE_VALS */
2996 #endif /* WIN32 */
2997  else if (!setTCPUserTimeout(conn))
2998  err = 1;
2999 
3000  if (err)
3001  {
3002  conn->try_next_addr = true;
3003  goto keep_going;
3004  }
3005  }
3006 
3007  /*----------
3008  * We have three methods of blocking SIGPIPE during
3009  * send() calls to this socket:
3010  *
3011  * - setsockopt(sock, SO_NOSIGPIPE)
3012  * - send(sock, ..., MSG_NOSIGNAL)
3013  * - setting the signal mask to SIG_IGN during send()
3014  *
3015  * The third method requires three syscalls per send,
3016  * so we prefer either of the first two, but they are
3017  * less portable. The state is tracked in the following
3018  * members of PGconn:
3019  *
3020  * conn->sigpipe_so - we have set up SO_NOSIGPIPE
3021  * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
3022  *
3023  * If we can use SO_NOSIGPIPE, then set sigpipe_so here
3024  * and we're done. Otherwise, set sigpipe_flag so that
3025  * we will try MSG_NOSIGNAL on sends. If we get an error
3026  * with MSG_NOSIGNAL, we'll clear that flag and revert to
3027  * signal masking.
3028  *----------
3029  */
3030  conn->sigpipe_so = false;
3031 #ifdef MSG_NOSIGNAL
3032  conn->sigpipe_flag = true;
3033 #else
3034  conn->sigpipe_flag = false;
3035 #endif /* MSG_NOSIGNAL */
3036 
3037 #ifdef SO_NOSIGPIPE
3038  optval = 1;
3039  if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
3040  (char *) &optval, sizeof(optval)) == 0)
3041  {
3042  conn->sigpipe_so = true;
3043  conn->sigpipe_flag = false;
3044  }
3045 #endif /* SO_NOSIGPIPE */
3046 
3047  /*
3048  * Start/make connection. This should not block, since we
3049  * are in nonblock mode. If it does, well, too bad.
3050  */
3051  if (connect(conn->sock, (struct sockaddr *) &addr_cur->addr.addr,
3052  addr_cur->addr.salen) < 0)
3053  {
3054  if (SOCK_ERRNO == EINPROGRESS ||
3055 #ifdef WIN32
3056  SOCK_ERRNO == EWOULDBLOCK ||
3057 #endif
3058  SOCK_ERRNO == EINTR)
3059  {
3060  /*
3061  * This is fine - we're in non-blocking mode, and
3062  * the connection is in progress. Tell caller to
3063  * wait for write-ready on socket.
3064  */
3066  return PGRES_POLLING_WRITING;
3067  }
3068  /* otherwise, trouble */
3069  }
3070  else
3071  {
3072  /*
3073  * Hm, we're connected already --- seems the "nonblock
3074  * connection" wasn't. Advance the state machine and
3075  * go do the next stuff.
3076  */
3078  goto keep_going;
3079  }
3080 
3081  /*
3082  * This connection failed. Add the error report to
3083  * conn->errorMessage, then try the next address if any.
3084  */
3086  conn->try_next_addr = true;
3087  goto keep_going;
3088  }
3089  }
3090 
3091  case CONNECTION_STARTED:
3092  {
3093  socklen_t optlen = sizeof(optval);
3094 
3095  /*
3096  * Write ready, since we've made it here, so the connection
3097  * has been made ... or has failed.
3098  */
3099 
3100  /*
3101  * Now check (using getsockopt) that there is not an error
3102  * state waiting for us on the socket.
3103  */
3104 
3105  if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
3106  (char *) &optval, &optlen) == -1)
3107  {
3108  libpq_append_conn_error(conn, "could not get socket error status: %s",
3109  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3110  goto error_return;
3111  }
3112  else if (optval != 0)
3113  {
3114  /*
3115  * When using a nonblocking connect, we will typically see
3116  * connect failures at this point, so provide a friendly
3117  * error message.
3118  */
3119  connectFailureMessage(conn, optval);
3120 
3121  /*
3122  * Try the next address if any, just as in the case where
3123  * connect() returned failure immediately.
3124  */
3125  conn->try_next_addr = true;
3126  goto keep_going;
3127  }
3128 
3129  /* Fill in the client address */
3130  conn->laddr.salen = sizeof(conn->laddr.addr);
3131  if (getsockname(conn->sock,
3132  (struct sockaddr *) &conn->laddr.addr,
3133  &conn->laddr.salen) < 0)
3134  {
3135  libpq_append_conn_error(conn, "could not get client address from socket: %s",
3136  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3137  goto error_return;
3138  }
3139 
3140  /*
3141  * Make sure we can write before advancing to next step.
3142  */
3144  return PGRES_POLLING_WRITING;
3145  }
3146 
3147  case CONNECTION_MADE:
3148  {
3149  char *startpacket;
3150  int packetlen;
3151 
3152  /*
3153  * Implement requirepeer check, if requested and it's a
3154  * Unix-domain socket.
3155  */
3156  if (conn->requirepeer && conn->requirepeer[0] &&
3157  conn->raddr.addr.ss_family == AF_UNIX)
3158  {
3159 #ifndef WIN32
3160  char *remote_username;
3161 #endif
3162  uid_t uid;
3163  gid_t gid;
3164 
3165  errno = 0;
3166  if (getpeereid(conn->sock, &uid, &gid) != 0)
3167  {
3168  /*
3169  * Provide special error message if getpeereid is a
3170  * stub
3171  */
3172  if (errno == ENOSYS)
3173  libpq_append_conn_error(conn, "requirepeer parameter is not supported on this platform");
3174  else
3175  libpq_append_conn_error(conn, "could not get peer credentials: %s",
3176  strerror_r(errno, sebuf, sizeof(sebuf)));
3177  goto error_return;
3178  }
3179 
3180 #ifndef WIN32
3181  remote_username = pg_fe_getusername(uid,
3182  &conn->errorMessage);
3183  if (remote_username == NULL)
3184  goto error_return; /* message already logged */
3185 
3186  if (strcmp(remote_username, conn->requirepeer) != 0)
3187  {
3188  libpq_append_conn_error(conn, "requirepeer specifies \"%s\", but actual peer user name is \"%s\"",
3189  conn->requirepeer, remote_username);
3190  free(remote_username);
3191  goto error_return;
3192  }
3193  free(remote_username);
3194 #else /* WIN32 */
3195  /* should have failed with ENOSYS above */
3196  Assert(false);
3197 #endif /* WIN32 */
3198  }
3199 
3200  if (conn->raddr.addr.ss_family == AF_UNIX)
3201  {
3202  /* Don't request SSL or GSSAPI over Unix sockets */
3203 #ifdef USE_SSL
3204  conn->allow_ssl_try = false;
3205 #endif
3206 #ifdef ENABLE_GSS
3207  conn->try_gss = false;
3208 #endif
3209  }
3210 
3211 #ifdef ENABLE_GSS
3212 
3213  /*
3214  * If GSSAPI encryption is enabled, then call
3215  * pg_GSS_have_cred_cache() which will return true if we can
3216  * acquire credentials (and give us a handle to use in
3217  * conn->gcred), and then send a packet to the server asking
3218  * for GSSAPI Encryption (and skip past SSL negotiation and
3219  * regular startup below).
3220  */
3221  if (conn->try_gss && !conn->gctx)
3222  conn->try_gss = pg_GSS_have_cred_cache(&conn->gcred);
3223  if (conn->try_gss && !conn->gctx)
3224  {
3226 
3227  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3228  {
3229  libpq_append_conn_error(conn, "could not send GSSAPI negotiation packet: %s",
3230  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3231  goto error_return;
3232  }
3233 
3234  /* Ok, wait for response */
3236  return PGRES_POLLING_READING;
3237  }
3238  else if (!conn->gctx && conn->gssencmode[0] == 'r')
3239  {
3241  "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)");
3242  goto error_return;
3243  }
3244 #endif
3245 
3246 #ifdef USE_SSL
3247 
3248  /*
3249  * Enable the libcrypto callbacks before checking if SSL needs
3250  * to be done. This is done before sending the startup packet
3251  * as depending on the type of authentication done, like MD5
3252  * or SCRAM that use cryptohashes, the callbacks would be
3253  * required even without a SSL connection
3254  */
3255  if (pqsecure_initialize(conn, false, true) < 0)
3256  goto error_return;
3257 
3258  /*
3259  * If SSL is enabled and we haven't already got encryption of
3260  * some sort running, request SSL instead of sending the
3261  * startup message.
3262  */
3263  if (conn->allow_ssl_try && !conn->wait_ssl_try &&
3264  !conn->ssl_in_use
3265 #ifdef ENABLE_GSS
3266  && !conn->gssenc
3267 #endif
3268  )
3269  {
3270  ProtocolVersion pv;
3271 
3272  /*
3273  * Send the SSL request packet.
3274  *
3275  * Theoretically, this could block, but it really
3276  * shouldn't since we only got here if the socket is
3277  * write-ready.
3278  */
3280  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3281  {
3282  libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s",
3283  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3284  goto error_return;
3285  }
3286  /* Ok, wait for response */
3288  return PGRES_POLLING_READING;
3289  }
3290 #endif /* USE_SSL */
3291 
3292  /*
3293  * For cancel requests this is as far as we need to go in the
3294  * connection establishment. Now we can actually send our
3295  * cancellation request.
3296  */
3297  if (conn->cancelRequest)
3298  {
3299  CancelRequestPacket cancelpacket;
3300 
3301  packetlen = sizeof(cancelpacket);
3303  cancelpacket.backendPID = pg_hton32(conn->be_pid);
3304  cancelpacket.cancelAuthCode = pg_hton32(conn->be_key);
3305  if (pqPacketSend(conn, 0, &cancelpacket, packetlen) != STATUS_OK)
3306  {
3307  libpq_append_conn_error(conn, "could not send cancel packet: %s",
3308  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3309  goto error_return;
3310  }
3312  return PGRES_POLLING_READING;
3313  }
3314 
3315  /*
3316  * Build the startup packet.
3317  */
3318  startpacket = pqBuildStartupPacket3(conn, &packetlen,
3320  if (!startpacket)
3321  {
3322  libpq_append_conn_error(conn, "out of memory");
3323  goto error_return;
3324  }
3325 
3326  /*
3327  * Send the startup packet.
3328  *
3329  * Theoretically, this could block, but it really shouldn't
3330  * since we only got here if the socket is write-ready.
3331  */
3332  if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
3333  {
3334  libpq_append_conn_error(conn, "could not send startup packet: %s",
3335  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3336  free(startpacket);
3337  goto error_return;
3338  }
3339 
3340  free(startpacket);
3341 
3343  return PGRES_POLLING_READING;
3344  }
3345 
3346  /*
3347  * Handle SSL negotiation: wait for postmaster messages and
3348  * respond as necessary.
3349  */
3351  {
3352 #ifdef USE_SSL
3353  PostgresPollingStatusType pollres;
3354 
3355  /*
3356  * On first time through, get the postmaster's response to our
3357  * SSL negotiation packet.
3358  */
3359  if (!conn->ssl_in_use)
3360  {
3361  /*
3362  * We use pqReadData here since it has the logic to
3363  * distinguish no-data-yet from connection closure. Since
3364  * conn->ssl isn't set, a plain recv() will occur.
3365  */
3366  char SSLok;
3367  int rdresult;
3368 
3369  rdresult = pqReadData(conn);
3370  if (rdresult < 0)
3371  {
3372  /* errorMessage is already filled in */
3373  goto error_return;
3374  }
3375  if (rdresult == 0)
3376  {
3377  /* caller failed to wait for data */
3378  return PGRES_POLLING_READING;
3379  }
3380  if (pqGetc(&SSLok, conn) < 0)
3381  {
3382  /* should not happen really */
3383  return PGRES_POLLING_READING;
3384  }
3385  if (SSLok == 'S')
3386  {
3387  /* mark byte consumed */
3388  conn->inStart = conn->inCursor;
3389 
3390  /*
3391  * Set up global SSL state if required. The crypto
3392  * state has already been set if libpq took care of
3393  * doing that, so there is no need to make that happen
3394  * again.
3395  */
3396  if (pqsecure_initialize(conn, true, false) != 0)
3397  goto error_return;
3398  }
3399  else if (SSLok == 'N')
3400  {
3401  /* mark byte consumed */
3402  conn->inStart = conn->inCursor;
3403  /* OK to do without SSL? */
3404  if (conn->sslmode[0] == 'r' || /* "require" */
3405  conn->sslmode[0] == 'v') /* "verify-ca" or
3406  * "verify-full" */
3407  {
3408  /* Require SSL, but server does not want it */
3409  libpq_append_conn_error(conn, "server does not support SSL, but SSL was required");
3410  goto error_return;
3411  }
3412  /* Otherwise, proceed with normal startup */
3413  conn->allow_ssl_try = false;
3414  /* We can proceed using this connection */
3416  return PGRES_POLLING_WRITING;
3417  }
3418  else if (SSLok == 'E')
3419  {
3420  /*
3421  * Server failure of some sort, such as failure to
3422  * fork a backend process. We need to process and
3423  * report the error message, which might be formatted
3424  * according to either protocol 2 or protocol 3.
3425  * Rather than duplicate the code for that, we flip
3426  * into AWAITING_RESPONSE state and let the code there
3427  * deal with it. Note we have *not* consumed the "E"
3428  * byte here.
3429  */
3431  goto keep_going;
3432  }
3433  else
3434  {
3435  libpq_append_conn_error(conn, "received invalid response to SSL negotiation: %c",
3436  SSLok);
3437  goto error_return;
3438  }
3439  }
3440 
3441  /*
3442  * Begin or continue the SSL negotiation process.
3443  */
3444  pollres = pqsecure_open_client(conn);
3445  if (pollres == PGRES_POLLING_OK)
3446  {
3447  /*
3448  * At this point we should have no data already buffered.
3449  * If we do, it was received before we performed the SSL
3450  * handshake, so it wasn't encrypted and indeed may have
3451  * been injected by a man-in-the-middle.
3452  */
3453  if (conn->inCursor != conn->inEnd)
3454  {
3455  libpq_append_conn_error(conn, "received unencrypted data after SSL response");
3456  goto error_return;
3457  }
3458 
3459  /* SSL handshake done, ready to send startup packet */
3461  return PGRES_POLLING_WRITING;
3462  }
3463  if (pollres == PGRES_POLLING_FAILED)
3464  {
3465  /*
3466  * Failed ... if sslmode is "prefer" then do a non-SSL
3467  * retry
3468  */
3469  if (conn->sslmode[0] == 'p' /* "prefer" */
3470  && conn->allow_ssl_try /* redundant? */
3471  && !conn->wait_ssl_try) /* redundant? */
3472  {
3473  /* only retry once */
3474  conn->allow_ssl_try = false;
3475  need_new_connection = true;
3476  goto keep_going;
3477  }
3478  /* Else it's a hard failure */
3479  goto error_return;
3480  }
3481  /* Else, return POLLING_READING or POLLING_WRITING status */
3482  return pollres;
3483 #else /* !USE_SSL */
3484  /* can't get here */
3485  goto error_return;
3486 #endif /* USE_SSL */
3487  }
3488 
3490  {
3491 #ifdef ENABLE_GSS
3492  PostgresPollingStatusType pollres;
3493 
3494  /*
3495  * If we haven't yet, get the postmaster's response to our
3496  * negotiation packet
3497  */
3498  if (conn->try_gss && !conn->gctx)
3499  {
3500  char gss_ok;
3501  int rdresult = pqReadData(conn);
3502 
3503  if (rdresult < 0)
3504  /* pqReadData fills in error message */
3505  goto error_return;
3506  else if (rdresult == 0)
3507  /* caller failed to wait for data */
3508  return PGRES_POLLING_READING;
3509  if (pqGetc(&gss_ok, conn) < 0)
3510  /* shouldn't happen... */
3511  return PGRES_POLLING_READING;
3512 
3513  if (gss_ok == 'E')
3514  {
3515  /*
3516  * Server failure of some sort. Assume it's a
3517  * protocol version support failure, and let's see if
3518  * we can't recover (if it's not, we'll get a better
3519  * error message on retry). Server gets fussy if we
3520  * don't hang up the socket, though.
3521  */
3522  conn->try_gss = false;
3523  need_new_connection = true;
3524  goto keep_going;
3525  }
3526 
3527  /* mark byte consumed */
3528  conn->inStart = conn->inCursor;
3529 
3530  if (gss_ok == 'N')
3531  {
3532  /* Server doesn't want GSSAPI; fall back if we can */
3533  if (conn->gssencmode[0] == 'r')
3534  {
3535  libpq_append_conn_error(conn, "server doesn't support GSSAPI encryption, but it was required");
3536  goto error_return;
3537  }
3538 
3539  conn->try_gss = false;
3540  /* We can proceed using this connection */
3542  return PGRES_POLLING_WRITING;
3543  }
3544  else if (gss_ok != 'G')
3545  {
3546  libpq_append_conn_error(conn, "received invalid response to GSSAPI negotiation: %c",
3547  gss_ok);
3548  goto error_return;
3549  }
3550  }
3551 
3552  /* Begin or continue GSSAPI negotiation */
3553  pollres = pqsecure_open_gss(conn);
3554  if (pollres == PGRES_POLLING_OK)
3555  {
3556  /*
3557  * At this point we should have no data already buffered.
3558  * If we do, it was received before we performed the GSS
3559  * handshake, so it wasn't encrypted and indeed may have
3560  * been injected by a man-in-the-middle.
3561  */
3562  if (conn->inCursor != conn->inEnd)
3563  {
3564  libpq_append_conn_error(conn, "received unencrypted data after GSSAPI encryption response");
3565  goto error_return;
3566  }
3567 
3568  /* All set for startup packet */
3570  return PGRES_POLLING_WRITING;
3571  }
3572  else if (pollres == PGRES_POLLING_FAILED)
3573  {
3574  if (conn->gssencmode[0] == 'p')
3575  {
3576  /*
3577  * We failed, but we can retry on "prefer". Have to
3578  * drop the current connection to do so, though.
3579  */
3580  conn->try_gss = false;
3581  need_new_connection = true;
3582  goto keep_going;
3583  }
3584  /* Else it's a hard failure */
3585  goto error_return;
3586  }
3587  /* Else, return POLLING_READING or POLLING_WRITING status */
3588  return pollres;
3589 #else /* !ENABLE_GSS */
3590  /* unreachable */
3591  goto error_return;
3592 #endif /* ENABLE_GSS */
3593  }
3594 
3595  /*
3596  * Handle authentication exchange: wait for postmaster messages
3597  * and respond as necessary.
3598  */
3600  {
3601  char beresp;
3602  int msgLength;
3603  int avail;
3604  AuthRequest areq;
3605  int res;
3606 
3607  /*
3608  * Scan the message from current point (note that if we find
3609  * the message is incomplete, we will return without advancing
3610  * inStart, and resume here next time).
3611  */
3612  conn->inCursor = conn->inStart;
3613 
3614  /* Read type byte */
3615  if (pqGetc(&beresp, conn))
3616  {
3617  /* We'll come back when there is more data */
3618  return PGRES_POLLING_READING;
3619  }
3620 
3621  /*
3622  * Validate message type: we expect only an authentication
3623  * request, NegotiateProtocolVersion, or an error here.
3624  * Anything else probably means it's not Postgres on the other
3625  * end at all.
3626  */
3627  if (beresp != PqMsg_AuthenticationRequest &&
3628  beresp != PqMsg_ErrorResponse &&
3630  {
3631  libpq_append_conn_error(conn, "expected authentication request from server, but received %c",
3632  beresp);
3633  goto error_return;
3634  }
3635 
3636  /* Read message length word */
3637  if (pqGetInt(&msgLength, 4, conn))
3638  {
3639  /* We'll come back when there is more data */
3640  return PGRES_POLLING_READING;
3641  }
3642 
3643  /*
3644  * Try to validate message length before using it.
3645  *
3646  * Authentication requests can't be very large, although GSS
3647  * auth requests may not be that small. Same for
3648  * NegotiateProtocolVersion.
3649  *
3650  * Errors can be a little larger, but not huge. If we see a
3651  * large apparent length in an error, it means we're really
3652  * talking to a pre-3.0-protocol server; cope. (Before
3653  * version 14, the server also used the old protocol for
3654  * errors that happened before processing the startup packet.)
3655  */
3656  if (beresp == PqMsg_AuthenticationRequest &&
3657  (msgLength < 8 || msgLength > 2000))
3658  {
3659  libpq_append_conn_error(conn, "received invalid authentication request");
3660  goto error_return;
3661  }
3662  if (beresp == PqMsg_NegotiateProtocolVersion &&
3663  (msgLength < 8 || msgLength > 2000))
3664  {
3665  libpq_append_conn_error(conn, "received invalid protocol negotiation message");
3666  goto error_return;
3667  }
3668 
3669 #define MAX_ERRLEN 30000
3670  if (beresp == PqMsg_ErrorResponse &&
3671  (msgLength < 8 || msgLength > MAX_ERRLEN))
3672  {
3673  /* Handle error from a pre-3.0 server */
3674  conn->inCursor = conn->inStart + 1; /* reread data */
3676  {
3677  /*
3678  * We may not have authenticated the server yet, so
3679  * don't let the buffer grow forever.
3680  */
3681  avail = conn->inEnd - conn->inCursor;
3682  if (avail > MAX_ERRLEN)
3683  {
3684  libpq_append_conn_error(conn, "received invalid error message");
3685  goto error_return;
3686  }
3687 
3688  /* We'll come back when there is more data */
3689  return PGRES_POLLING_READING;
3690  }
3691  /* OK, we read the message; mark data consumed */
3692  conn->inStart = conn->inCursor;
3693 
3694  /*
3695  * Before 7.2, the postmaster didn't always end its
3696  * messages with a newline, so add one if needed to
3697  * conform to libpq conventions.
3698  */
3699  if (conn->errorMessage.len == 0 ||
3700  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3701  {
3703  }
3704 
3705  goto error_return;
3706  }
3707 #undef MAX_ERRLEN
3708 
3709  /*
3710  * Can't process if message body isn't all here yet.
3711  *
3712  * After this check passes, any further EOF during parsing
3713  * implies that the server sent a bad/truncated message.
3714  * Reading more bytes won't help in that case, so don't return
3715  * PGRES_POLLING_READING after this point.
3716  */
3717  msgLength -= 4;
3718  avail = conn->inEnd - conn->inCursor;
3719  if (avail < msgLength)
3720  {
3721  /*
3722  * Before returning, try to enlarge the input buffer if
3723  * needed to hold the whole message; see notes in
3724  * pqParseInput3.
3725  */
3726  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
3727  conn))
3728  goto error_return;
3729  /* We'll come back when there is more data */
3730  return PGRES_POLLING_READING;
3731  }
3732 
3733  /* Handle errors. */
3734  if (beresp == PqMsg_ErrorResponse)
3735  {
3736  if (pqGetErrorNotice3(conn, true))
3737  {
3738  libpq_append_conn_error(conn, "received invalid error message");
3739  goto error_return;
3740  }
3741  /* OK, we read the message; mark data consumed */
3742  conn->inStart = conn->inCursor;
3743 
3744  /*
3745  * If error is "cannot connect now", try the next host if
3746  * any (but we don't want to consider additional addresses
3747  * for this host, nor is there much point in changing SSL
3748  * or GSS mode). This is helpful when dealing with
3749  * standby servers that might not be in hot-standby state.
3750  */
3751  if (strcmp(conn->last_sqlstate,
3753  {
3754  conn->try_next_host = true;
3755  goto keep_going;
3756  }
3757 
3758  /* Check to see if we should mention pgpassfile */
3760 
3761 #ifdef ENABLE_GSS
3762 
3763  /*
3764  * If gssencmode is "prefer" and we're using GSSAPI, retry
3765  * without it.
3766  */
3767  if (conn->gssenc && conn->gssencmode[0] == 'p')
3768  {
3769  /* only retry once */
3770  conn->try_gss = false;
3771  need_new_connection = true;
3772  goto keep_going;
3773  }
3774 #endif
3775 
3776 #ifdef USE_SSL
3777 
3778  /*
3779  * if sslmode is "allow" and we haven't tried an SSL
3780  * connection already, then retry with an SSL connection
3781  */
3782  if (conn->sslmode[0] == 'a' /* "allow" */
3783  && !conn->ssl_in_use
3784  && conn->allow_ssl_try
3785  && conn->wait_ssl_try)
3786  {
3787  /* only retry once */
3788  conn->wait_ssl_try = false;
3789  need_new_connection = true;
3790  goto keep_going;
3791  }
3792 
3793  /*
3794  * if sslmode is "prefer" and we're in an SSL connection,
3795  * then do a non-SSL retry
3796  */
3797  if (conn->sslmode[0] == 'p' /* "prefer" */
3798  && conn->ssl_in_use
3799  && conn->allow_ssl_try /* redundant? */
3800  && !conn->wait_ssl_try) /* redundant? */
3801  {
3802  /* only retry once */
3803  conn->allow_ssl_try = false;
3804  need_new_connection = true;
3805  goto keep_going;
3806  }
3807 #endif
3808 
3809  goto error_return;
3810  }
3811  else if (beresp == PqMsg_NegotiateProtocolVersion)
3812  {
3814  {
3815  libpq_append_conn_error(conn, "received invalid protocol negotiation message");
3816  goto error_return;
3817  }
3818  /* OK, we read the message; mark data consumed */
3819  conn->inStart = conn->inCursor;
3820  goto error_return;
3821  }
3822 
3823  /* It is an authentication request. */
3824  conn->auth_req_received = true;
3825 
3826  /* Get the type of request. */
3827  if (pqGetInt((int *) &areq, 4, conn))
3828  {
3829  /* can't happen because we checked the length already */
3830  libpq_append_conn_error(conn, "received invalid authentication request");
3831  goto error_return;
3832  }
3833  msgLength -= 4;
3834 
3835  /*
3836  * Process the rest of the authentication request message, and
3837  * respond to it if necessary.
3838  *
3839  * Note that conn->pghost must be non-NULL if we are going to
3840  * avoid the Kerberos code doing a hostname look-up.
3841  */
3842  res = pg_fe_sendauth(areq, msgLength, conn);
3843 
3844  /* OK, we have processed the message; mark data consumed */
3845  conn->inStart = conn->inCursor;
3846 
3847  if (res != STATUS_OK)
3848  goto error_return;
3849 
3850  /*
3851  * Just make sure that any data sent by pg_fe_sendauth is
3852  * flushed out. Although this theoretically could block, it
3853  * really shouldn't since we don't send large auth responses.
3854  */
3855  if (pqFlush(conn))
3856  goto error_return;
3857 
3858  if (areq == AUTH_REQ_OK)
3859  {
3860  /* We are done with authentication exchange */
3862 
3863  /*
3864  * Set asyncStatus so that PQgetResult will think that
3865  * what comes back next is the result of a query. See
3866  * below.
3867  */
3869  }
3870 
3871  /* Look to see if we have more data yet. */
3872  goto keep_going;
3873  }
3874 
3875  case CONNECTION_AUTH_OK:
3876  {
3877  /*
3878  * Now we expect to hear from the backend. A ReadyForQuery
3879  * message indicates that startup is successful, but we might
3880  * also get an Error message indicating failure. (Notice
3881  * messages indicating nonfatal warnings are also allowed by
3882  * the protocol, as are ParameterStatus and BackendKeyData
3883  * messages.) Easiest way to handle this is to let
3884  * PQgetResult() read the messages. We just have to fake it
3885  * out about the state of the connection, by setting
3886  * asyncStatus = PGASYNC_BUSY (done above).
3887  */
3888 
3889  if (PQisBusy(conn))
3890  return PGRES_POLLING_READING;
3891 
3892  res = PQgetResult(conn);
3893 
3894  /*
3895  * NULL return indicating we have gone to IDLE state is
3896  * expected
3897  */
3898  if (res)
3899  {
3901  libpq_append_conn_error(conn, "unexpected message from server during startup");
3902  else if (conn->send_appname &&
3903  (conn->appname || conn->fbappname))
3904  {
3905  /*
3906  * If we tried to send application_name, check to see
3907  * if the error is about that --- pre-9.0 servers will
3908  * reject it at this stage of the process. If so,
3909  * close the connection and retry without sending
3910  * application_name. We could possibly get a false
3911  * SQLSTATE match here and retry uselessly, but there
3912  * seems no great harm in that; we'll just get the
3913  * same error again if it's unrelated.
3914  */
3915  const char *sqlstate;
3916 
3918  if (sqlstate &&
3919  strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
3920  {
3921  PQclear(res);
3922  conn->send_appname = false;
3923  need_new_connection = true;
3924  goto keep_going;
3925  }
3926  }
3927 
3928  /*
3929  * if the resultStatus is FATAL, then conn->errorMessage
3930  * already has a copy of the error; needn't copy it back.
3931  * But add a newline if it's not there already, since
3932  * postmaster error messages may not have one.
3933  */
3934  if (conn->errorMessage.len <= 0 ||
3935  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3937  PQclear(res);
3938  goto error_return;
3939  }
3940 
3941  /* Almost there now ... */
3943  goto keep_going;
3944  }
3945 
3947  {
3948  /*
3949  * If a read-write, read-only, primary, or standby connection
3950  * is required, see if we have one.
3951  */
3954  {
3955  bool read_only_server;
3956 
3957  /*
3958  * If the server didn't report
3959  * "default_transaction_read_only" or "in_hot_standby" at
3960  * startup, we must determine its state by sending the
3961  * query "SHOW transaction_read_only". This GUC exists in
3962  * all server versions that support 3.0 protocol.
3963  */
3966  {
3967  /*
3968  * We use PQsendQueryContinue so that
3969  * conn->errorMessage does not get cleared. We need
3970  * to preserve any error messages related to previous
3971  * hosts we have tried and failed to connect to.
3972  */
3975  "SHOW transaction_read_only"))
3976  goto error_return;
3977  /* We'll return to this state when we have the answer */
3979  return PGRES_POLLING_READING;
3980  }
3981 
3982  /* OK, we can make the test */
3983  read_only_server =
3986 
3988  read_only_server : !read_only_server)
3989  {
3990  /* Wrong server state, reject and try the next host */
3992  libpq_append_conn_error(conn, "session is read-only");
3993  else
3994  libpq_append_conn_error(conn, "session is not read-only");
3995 
3996  /* Close connection politely. */
3999 
4000  /*
4001  * Try next host if any, but we don't want to consider
4002  * additional addresses for this host.
4003  */
4004  conn->try_next_host = true;
4005  goto keep_going;
4006  }
4007  }
4011  {
4012  /*
4013  * If the server didn't report "in_hot_standby" at
4014  * startup, we must determine its state by sending the
4015  * query "SELECT pg_catalog.pg_is_in_recovery()". Servers
4016  * before 9.0 don't have that function, but by the same
4017  * token they don't have any standby mode, so we may just
4018  * assume the result.
4019  */
4020  if (conn->sversion < 90000)
4022 
4024  {
4025  /*
4026  * We use PQsendQueryContinue so that
4027  * conn->errorMessage does not get cleared. We need
4028  * to preserve any error messages related to previous
4029  * hosts we have tried and failed to connect to.
4030  */
4033  "SELECT pg_catalog.pg_is_in_recovery()"))
4034  goto error_return;
4035  /* We'll return to this state when we have the answer */
4037  return PGRES_POLLING_READING;
4038  }
4039 
4040  /* OK, we can make the test */
4044  {
4045  /* Wrong server state, reject and try the next host */
4047  libpq_append_conn_error(conn, "server is in hot standby mode");
4048  else
4049  libpq_append_conn_error(conn, "server is not in hot standby mode");
4050 
4051  /* Close connection politely. */
4054 
4055  /*
4056  * Try next host if any, but we don't want to consider
4057  * additional addresses for this host.
4058  */
4059  conn->try_next_host = true;
4060  goto keep_going;
4061  }
4062  }
4063 
4064  /*
4065  * For non cancel requests we can release the address list
4066  * now. For cancel requests we never actually resolve
4067  * addresses and instead the addrinfo exists for the lifetime
4068  * of the connection.
4069  */
4070  if (!conn->cancelRequest)
4072 
4073  /*
4074  * Contents of conn->errorMessage are no longer interesting
4075  * (and it seems some clients expect it to be empty after a
4076  * successful connection).
4077  */
4079 
4080  /* We are open for business! */
4082  return PGRES_POLLING_OK;
4083  }
4084 
4085  case CONNECTION_CONSUME:
4086  {
4087  /*
4088  * This state just makes sure the connection is idle after
4089  * we've obtained the result of a SHOW or SELECT query. Once
4090  * we're clear, return to CONNECTION_CHECK_TARGET state to
4091  * decide what to do next. We must transiently set status =
4092  * CONNECTION_OK in order to use the result-consuming
4093  * subroutines.
4094  */
4096  if (!PQconsumeInput(conn))
4097  goto error_return;
4098 
4099  if (PQisBusy(conn))
4100  {
4102  return PGRES_POLLING_READING;
4103  }
4104 
4105  /* Call PQgetResult() again until we get a NULL result */
4106  res = PQgetResult(conn);
4107  if (res != NULL)
4108  {
4109  PQclear(res);
4111  return PGRES_POLLING_READING;
4112  }
4113 
4115  goto keep_going;
4116  }
4117 
4119  {
4120  /*
4121  * Waiting for result of "SHOW transaction_read_only". We
4122  * must transiently set status = CONNECTION_OK in order to use
4123  * the result-consuming subroutines.
4124  */
4126  if (!PQconsumeInput(conn))
4127  goto error_return;
4128 
4129  if (PQisBusy(conn))
4130  {
4132  return PGRES_POLLING_READING;
4133  }
4134 
4135  res = PQgetResult(conn);
4136  if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
4137  PQntuples(res) == 1)
4138  {
4139  char *val = PQgetvalue(res, 0, 0);
4140 
4141  /*
4142  * "transaction_read_only = on" proves that at least one
4143  * of default_transaction_read_only and in_hot_standby is
4144  * on, but we don't actually know which. We don't care
4145  * though for the purpose of identifying a read-only
4146  * session, so satisfy the CONNECTION_CHECK_TARGET code by
4147  * claiming they are both on. On the other hand, if it's
4148  * a read-write session, they are certainly both off.
4149  */
4150  if (strncmp(val, "on", 2) == 0)
4151  {
4154  }
4155  else
4156  {
4159  }
4160  PQclear(res);
4161 
4162  /* Finish reading messages before continuing */
4164  goto keep_going;
4165  }
4166 
4167  /* Something went wrong with "SHOW transaction_read_only". */
4168  PQclear(res);
4169 
4170  /* Append error report to conn->errorMessage. */
4171  libpq_append_conn_error(conn, "\"%s\" failed",
4172  "SHOW transaction_read_only");
4173 
4174  /* Close connection politely. */
4177 
4178  /* Try next host. */
4179  conn->try_next_host = true;
4180  goto keep_going;
4181  }
4182 
4184  {
4185  /*
4186  * Waiting for result of "SELECT pg_is_in_recovery()". We
4187  * must transiently set status = CONNECTION_OK in order to use
4188  * the result-consuming subroutines.
4189  */
4191  if (!PQconsumeInput(conn))
4192  goto error_return;
4193 
4194  if (PQisBusy(conn))
4195  {
4197  return PGRES_POLLING_READING;
4198  }
4199 
4200  res = PQgetResult(conn);
4201  if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
4202  PQntuples(res) == 1)
4203  {
4204  char *val = PQgetvalue(res, 0, 0);
4205 
4206  if (strncmp(val, "t", 1) == 0)
4208  else
4210  PQclear(res);
4211 
4212  /* Finish reading messages before continuing */
4214  goto keep_going;
4215  }
4216 
4217  /* Something went wrong with "SELECT pg_is_in_recovery()". */
4218  PQclear(res);
4219 
4220  /* Append error report to conn->errorMessage. */
4221  libpq_append_conn_error(conn, "\"%s\" failed",
4222  "SELECT pg_is_in_recovery()");
4223 
4224  /* Close connection politely. */
4227 
4228  /* Try next host. */
4229  conn->try_next_host = true;
4230  goto keep_going;
4231  }
4232 
4233  default:
4235  "invalid connection state %d, probably indicative of memory corruption",
4236  conn->status);
4237  goto error_return;
4238  }
4239 
4240  /* Unreachable */
4241 
4242 error_return:
4243 
4244  /*
4245  * We used to close the socket at this point, but that makes it awkward
4246  * for those above us if they wish to remove this socket from their own
4247  * records (an fd_set for example). We'll just have this socket closed
4248  * when PQfinish is called (which is compulsory even after an error, since
4249  * the connection structure must be freed).
4250  */
4252  return PGRES_POLLING_FAILED;
4253 }
#define STATUS_OK
Definition: c.h:1156
void err(int eval, const char *fmt,...)
Definition: err.c:43
int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
Definition: fe-auth.c:960
char * pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
Definition: fe-auth.c:1168
#define MAX_ERRLEN
static const PQEnvironmentOption EnvironmentOptions[]
Definition: fe-connect.c:367
static int setKeepalivesCount(PGconn *conn)
Definition: fe-connect.c:2194
static int useKeepalives(PGconn *conn)
Definition: fe-connect.c:2107
static int store_conn_addrinfo(PGconn *conn, struct addrinfo *addrlist)
Definition: fe-connect.c:4536
static void connectFailureMessage(PGconn *conn, int errorno)
Definition: fe-connect.c:2087
#define ERRCODE_APPNAME_UNKNOWN
Definition: fe-connect.c:86
static int setKeepalivesInterval(PGconn *conn)
Definition: fe-connect.c:2159
static int setKeepalivesIdle(PGconn *conn)
Definition: fe-connect.c:2125
static void pgpassfileWarning(PGconn *conn)
Definition: fe-connect.c:7354
static void emitHostIdentityInfo(PGconn *conn, const char *host_addr)
Definition: fe-connect.c:2031
static int setTCPUserTimeout(PGconn *conn)
Definition: fe-connect.c:2291
static int connectNoDelay(PGconn *conn)
Definition: fe-connect.c:1972
static void getHostaddr(PGconn *conn, char *host_addr, int host_addr_len)
Definition: fe-connect.c:1998
int pqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len)
Definition: fe-connect.c:4777
int PQsendQueryContinue(PGconn *conn, const char *query)
Definition: fe-exec.c:1431
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3371
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3441
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1960
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3836
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2007
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2038
bool pg_GSS_have_cred_cache(gss_cred_id_t *cred_out)
int pqReadData(PGconn *conn)
Definition: fe-misc.c:566
int pqFlush(PGconn *conn)
Definition: fe-misc.c:954
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:78
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:217
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:352
int pqGets_append(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:143
int pqGetNegotiateProtocolVersion3(PGconn *conn)
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:881
char * pqBuildStartupPacket3(PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
PostgresPollingStatusType pqsecure_open_gss(PGconn *conn)
PostgresPollingStatusType pqsecure_open_client(PGconn *conn)
Definition: fe-secure.c:153
int pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto)
Definition: fe-secure.c:138
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:82
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:53
@ CONNECTION_CONSUME
Definition: libpq-fe.h:78
@ CONNECTION_CHECK_STANDBY
Definition: libpq-fe.h:82
@ CONNECTION_STARTED
Definition: libpq-fe.h:68
@ CONNECTION_AWAITING_RESPONSE
Definition: libpq-fe.h:70
@ CONNECTION_MADE
Definition: libpq-fe.h:69
@ CONNECTION_CHECK_WRITABLE
Definition: libpq-fe.h:77
@ CONNECTION_GSS_STARTUP
Definition: libpq-fe.h:79
@ CONNECTION_SSL_STARTUP
Definition: libpq-fe.h:75
@ CONNECTION_AUTH_OK
Definition: libpq-fe.h:72
@ CONNECTION_CHECK_TARGET
Definition: libpq-fe.h:80
@ PGRES_FATAL_ERROR
Definition: libpq-fe.h:111
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:103
@ PGRES_POLLING_FAILED
Definition: libpq-fe.h:89
@ PGASYNC_BUSY
Definition: libpq-int.h:222
@ PG_BOOL_YES
Definition: libpq-int.h:257
@ PG_BOOL_NO
Definition: libpq-int.h:258
@ PG_BOOL_UNKNOWN
Definition: libpq-int.h:256
#define pg_hton32(x)
Definition: pg_bswap.h:121
static char portstr[16]
Definition: pg_regress.c:117
bool pg_set_noblock(pgsocket sock)
Definition: noblock.c:25
unsigned int socklen_t
Definition: port.h:40
#define PGINVALID_SOCKET
Definition: port.h:31
#define strerror_r
Definition: port.h:255
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition: getpeereid.c:33
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:132
#define UNIXSOCK_PATH(path, port, sockdir)
Definition: pqcomm.h:44
#define UNIXSOCK_PATH_BUFLEN
Definition: pqcomm.h:60
#define NEGOTIATE_GSS_CODE
Definition: pqcomm.h:148
#define NEGOTIATE_SSL_CODE
Definition: pqcomm.h:147
uint32 ProtocolVersion
Definition: pqcomm.h:99
uint32 AuthRequest
Definition: pqcomm.h:121
ProtocolVersion MsgType
Definition: pqcomm.h:101
#define PG_PROTOCOL(m, n)
Definition: pqcomm.h:89
#define AUTH_REQ_OK
Definition: protocol.h:70
#define PqMsg_AuthenticationRequest
Definition: protocol.h:50
#define PqMsg_NegotiateProtocolVersion
Definition: protocol.h:59
#define PqMsg_ErrorResponse
Definition: protocol.h:44
const char * gai_strerror(int ecode)
int family
Definition: pqcomm.h:38
SockAddr addr
Definition: pqcomm.h:39
MsgType cancelRequestCode
Definition: pqcomm.h:137
uint32 backendPID
Definition: pqcomm.h:138
uint32 cancelAuthCode
Definition: pqcomm.h:139
SockAddr laddr
Definition: libpq-int.h:465
AddrInfo * addr
Definition: libpq-int.h:493
bool sigpipe_flag
Definition: libpq-int.h:473
ProtocolVersion pversion
Definition: libpq-int.h:467
bool send_appname
Definition: libpq-int.h:495
PGTernaryBool in_hot_standby
Definition: libpq-int.h:504
int be_key
Definition: libpq-int.h:499
int naddr
Definition: libpq-int.h:491
int sversion
Definition: libpq-int.h:468
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:503
bool sigpipe_so
Definition: libpq-int.h:472
bool ssl_in_use
Definition: libpq-int.h:551
ExecStatusType resultStatus
Definition: libpq-int.h:180
#define EINTR
Definition: win32_port.h:374
#define EWOULDBLOCK
Definition: win32_port.h:380
#define EINPROGRESS
Definition: win32_port.h:386
int gid_t
Definition: win32_port.h:245
#define socket(af, type, protocol)
Definition: win32_port.h:490
#define connect(s, name, namelen)
Definition: win32_port.h:494
int uid_t
Definition: win32_port.h:244

References AddrInfo::addr, SockAddr::addr, pg_conn::addr, appendPQExpBufferChar(), pg_conn::appname, Assert(), pg_conn::asyncStatus, AUTH_REQ_OK, pg_conn::auth_req_received, CancelRequestPacket::backendPID, pg_conn::be_key, pg_conn::be_pid, CANCEL_REQUEST_CODE, CancelRequestPacket::cancelAuthCode, pg_conn::cancelRequest, CancelRequestPacket::cancelRequestCode, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, conn, connect, connectFailureMessage(), CONNECTION_AUTH_OK, CONNECTION_AWAITING_RESPONSE, CONNECTION_BAD, CONNECTION_CHECK_STANDBY, CONNECTION_CHECK_TARGET, CONNECTION_CHECK_WRITABLE, CONNECTION_CONSUME, CONNECTION_GSS_STARTUP, CONNECTION_MADE, CONNECTION_NEEDED, CONNECTION_OK, CONNECTION_SSL_STARTUP, CONNECTION_STARTED, connectNoDelay(), pg_conn::connhost, pg_conn::connip, PQExpBufferData::data, pg_conn::default_transaction_read_only, EINPROGRESS, EINTR, emitHostIdentityInfo(), EnvironmentOptions, err(), ERRCODE_APPNAME_UNKNOWN, ERRCODE_CANNOT_CONNECT_NOW, pg_conn::errorMessage, EWOULDBLOCK, AddrInfo::family, pg_conn::fbappname, free, gai_strerror(), getHostaddr(), getpeereid(), pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::in_hot_standby, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, j, pg_conn::laddr, pg_conn::last_sqlstate, PQExpBufferData::len, libpq_append_conn_error(), LOAD_BALANCE_RANDOM, pg_conn::load_balance_type, MAX_ERRLEN, MAXPGPATH, MemSet, pg_conn::naddr, pg_conn::nconnhost, NEGOTIATE_GSS_CODE, NEGOTIATE_SSL_CODE, PG_BOOL_NO, PG_BOOL_UNKNOWN, PG_BOOL_YES, PG_DIAG_SQLSTATE, pg_fe_getusername(), pg_fe_sendauth(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_GSS_have_cred_cache(), pg_hton32, pg_prng_uint64_range(), PG_PROTOCOL, pg_set_noblock(), PG_STRERROR_R_BUFLEN, PGASYNC_BUSY, PGASYNC_IDLE, PGINVALID_SOCKET, pgpassfileWarning(), PGRES_FATAL_ERROR, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PGRES_TUPLES_OK, pg_conn::pipelineStatus, pg_conn_host::port, portstr, PQ_PIPELINE_OFF, pqBuildStartupPacket3(), pqCheckInBufferSpace(), PQclear(), pqClearAsyncResult(), pqClearConnErrorState, PQconsumeInput(), pqDropConnection(), pqDropServerData(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetNegotiateProtocolVersion3(), PQgetResult(), pqGets_append(), PQgetvalue(), PQisBusy(), PqMsg_AuthenticationRequest, PqMsg_ErrorResponse, PqMsg_NegotiateProtocolVersion, PQntuples(), pqPacketSend(), pqParseIntParam(), pqReadData(), PQresultErrorField(), PQresultStatus(), pqsecure_initialize(), pqsecure_open_client(), pqsecure_open_gss(), PQsendQueryContinue(), PQTRANS_IDLE, pg_conn::prng_state, pg_conn::pversion, pg_conn::raddr, release_conn_addrinfo(), pg_conn::requirepeer, res, pg_result::resultStatus, SockAddr::salen, pg_conn::send_appname, sendTerminateConn(), SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PREFER_STANDBY_PASS2, SERVER_TYPE_PRIMARY, SERVER_TYPE_READ_ONLY, SERVER_TYPE_READ_WRITE, SERVER_TYPE_STANDBY, setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), setTCPUserTimeout(), pg_conn::sigpipe_flag, pg_conn::sigpipe_so, snprintf, pg_conn::sock, SOCK_ERRNO, SOCK_STRERROR, socket, pg_conn::ssl_in_use, pg_conn::sslmode, pg_conn::status, STATUS_OK, store_conn_addrinfo(), strerror_r, pg_conn::sversion, pg_conn::target_server_type, pg_conn::try_next_addr, pg_conn::try_next_host, pg_conn_host::type, UNIXSOCK_PATH, UNIXSOCK_PATH_BUFLEN, useKeepalives(), val, pg_conn::whichaddr, pg_conn::whichhost, and pg_conn::xactStatus.

Referenced by libpqrcv_connect(), libpqsrv_connect_internal(), PQcancelPoll(), pqConnectDBComplete(), pqConnectDBStart(), and PQresetPoll().

◆ PQconnectStart()

PGconn* PQconnectStart ( const char *  conninfo)

Definition at line 861 of file fe-connect.c.

862 {
863  PGconn *conn;
864 
865  /*
866  * Allocate memory for the conn structure. Note that we also expect this
867  * to initialize conn->errorMessage to empty. All subsequent steps during
868  * connection initialization will only append to that buffer.
869  */
871  if (conn == NULL)
872  return NULL;
873 
874  /*
875  * Parse the conninfo string
876  */
877  if (!connectOptions1(conn, conninfo))
878  return conn;
879 
880  /*
881  * Compute derived options
882  */
883  if (!pqConnectOptions2(conn))
884  return conn;
885 
886  /*
887  * Connect to the database
888  */
889  if (!pqConnectDBStart(conn))
890  {
891  /* Just in case we failed to set it in pqConnectDBStart */
893  }
894 
895  return conn;
896 }
static bool connectOptions1(PGconn *conn, const char *conninfo)
Definition: fe-connect.c:986
bool pqConnectOptions2(PGconn *conn)
Definition: fe-connect.c:1109
PGconn * pqMakeEmptyPGconn(void)
Definition: fe-connect.c:4327
int pqConnectDBStart(PGconn *conn)
Definition: fe-connect.c:2330

References conn, CONNECTION_BAD, connectOptions1(), pqConnectDBStart(), pqConnectOptions2(), pqMakeEmptyPGconn(), and pg_conn::status.

Referenced by libpqsrv_connect(), PQconnectdb(), and PQping().

◆ PQconnectStartParams()

PGconn* PQconnectStartParams ( const char *const *  keywords,
const char *const *  values,
int  expand_dbname 
)

Definition at line 780 of file fe-connect.c.

783 {
784  PGconn *conn;
785  PQconninfoOption *connOptions;
786 
787  /*
788  * Allocate memory for the conn structure. Note that we also expect this
789  * to initialize conn->errorMessage to empty. All subsequent steps during
790  * connection initialization will only append to that buffer.
791  */
793  if (conn == NULL)
794  return NULL;
795 
796  /*
797  * Parse the conninfo arrays
798  */
799  connOptions = conninfo_array_parse(keywords, values,
800  &conn->errorMessage,
801  true, expand_dbname);
802  if (connOptions == NULL)
803  {
805  /* errorMessage is already set */
806  return conn;
807  }
808 
809  /*
810  * Move option values into conn structure
811  */
812  if (!fillPGconn(conn, connOptions))
813  {
814  PQconninfoFree(connOptions);
815  return conn;
816  }
817 
818  /*
819  * Free the option info - all is in conn now
820  */
821  PQconninfoFree(connOptions);
822 
823  /*
824  * Compute derived options
825  */
826  if (!pqConnectOptions2(conn))
827  return conn;
828 
829  /*
830  * Connect to the database
831  */
832  if (!pqConnectDBStart(conn))
833  {
834  /* Just in case we failed to set it in pqConnectDBStart */
836  }
837 
838  return conn;
839 }
static PQconninfoOption * conninfo_array_parse(const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)
Definition: fe-connect.c:5820

References conn, CONNECTION_BAD, conninfo_array_parse(), pg_conn::errorMessage, fillPGconn(), pqConnectDBStart(), pqConnectOptions2(), PQconninfoFree(), pqMakeEmptyPGconn(), pg_conn::status, and values.

Referenced by libpqrcv_connect(), libpqsrv_connect_params(), PQconnectdbParams(), and PQpingParams().

◆ PQconninfo()

PQconninfoOption* PQconninfo ( PGconn conn)

Definition at line 6737 of file fe-connect.c.

6738 {
6739  PQExpBufferData errorBuf;
6740  PQconninfoOption *connOptions;
6741 
6742  if (conn == NULL)
6743  return NULL;
6744 
6745  /*
6746  * We don't actually report any errors here, but callees want a buffer,
6747  * and we prefer not to trash the conn's errorMessage.
6748  */
6749  initPQExpBuffer(&errorBuf);
6750  if (PQExpBufferDataBroken(errorBuf))
6751  return NULL; /* out of memory already :-( */
6752 
6753  connOptions = conninfo_init(&errorBuf);
6754 
6755  if (connOptions != NULL)
6756  {
6758 
6759  for (option = PQconninfoOptions; option->keyword; option++)
6760  {
6761  char **connmember;
6762 
6763  if (option->connofs < 0)
6764  continue;
6765 
6766  connmember = (char **) ((char *) conn + option->connofs);
6767 
6768  if (*connmember)
6769  conninfo_storeval(connOptions, option->keyword, *connmember,
6770  &errorBuf, true, false);
6771  }
6772  }
6773 
6774  termPQExpBuffer(&errorBuf);
6775 
6776  return connOptions;
6777 }

References conn, conninfo_init(), conninfo_storeval(), initPQExpBuffer(), PQconninfoOptions, PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by copy_connection(), do_connect(), GenerateRecoveryConfig(), and libpqrcv_get_conninfo().

◆ PQconninfoFree()

◆ PQconninfoParse()

PQconninfoOption* PQconninfoParse ( const char *  conninfo,
char **  errmsg 
)

Definition at line 5529 of file fe-connect.c.

5530 {
5531  PQExpBufferData errorBuf;
5532  PQconninfoOption *connOptions;
5533 
5534  if (errmsg)
5535  *errmsg = NULL; /* default */
5536  initPQExpBuffer(&errorBuf);
5537  if (PQExpBufferDataBroken(errorBuf))
5538  return NULL; /* out of memory already :-( */
5539  connOptions = parse_connection_string(conninfo, &errorBuf, false);
5540  if (connOptions == NULL && errmsg)
5541  *errmsg = errorBuf.data;
5542  else
5543  termPQExpBuffer(&errorBuf);
5544  return connOptions;
5545 }
int errmsg(const char *fmt,...)
Definition: elog.c:1072

References PQExpBufferData::data, errmsg(), initPQExpBuffer(), parse_connection_string(), PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by connectDatabase(), dblink_connstr_has_pw(), do_connect(), get_base_conninfo(), GetConnection(), GetDbnameFromConnectionOptions(), libpqrcv_check_conninfo(), libpqrcv_get_dbname_from_conninfo(), and main().

◆ pqCopyPGconn()

bool pqCopyPGconn ( PGconn srcConn,
PGconn dstConn 
)

Definition at line 945 of file fe-connect.c.

946 {
948 
949  /* copy over connection options */
950  for (option = PQconninfoOptions; option->keyword; option++)
951  {
952  if (option->connofs >= 0)
953  {
954  const char **tmp = (const char **) ((char *) srcConn + option->connofs);
955 
956  if (*tmp)
957  {
958  char **dstConnmember = (char **) ((char *) dstConn + option->connofs);
959 
960  if (*dstConnmember)
961  free(*dstConnmember);
962  *dstConnmember = strdup(*tmp);
963  if (*dstConnmember == NULL)
964  {
965  libpq_append_conn_error(dstConn, "out of memory");
966  return false;
967  }
968  }
969  }
970  }
971  return true;
972 }

References free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by PQcancelCreate().

◆ PQdb()

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

Definition at line 460 of file fe-connect.c.

461 {
462  /* Drop any SSL state */
464 
465  /* Close the socket itself */
466  if (conn->sock != PGINVALID_SOCKET)
469 
470  /* Optionally discard any unread data */
471  if (flushInput)
472  conn->inStart = conn->inCursor = conn->inEnd = 0;
473 
474  /* Always discard any unsent data */
475  conn->outCount = 0;
476 
477  /* Likewise, discard any pending pipelined commands */
481  conn->cmd_queue_recycle = NULL;
482 
483  /* Free authentication/encryption state */
484 #ifdef ENABLE_GSS
485  {
486  OM_uint32 min_s;
487 
488  if (conn->gcred != GSS_C_NO_CREDENTIAL)
489  {
490  gss_release_cred(&min_s, &conn->gcred);
491  conn->gcred = GSS_C_NO_CREDENTIAL;
492  }
493  if (conn->gctx)
494  gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
495  if (conn->gtarg_nam)
496  gss_release_name(&min_s, &conn->gtarg_nam);
497  if (conn->gss_SendBuffer)
498  {
499  free(conn->gss_SendBuffer);
500  conn->gss_SendBuffer = NULL;
501  }
502  if (conn->gss_RecvBuffer)
503  {
504  free(conn->gss_RecvBuffer);
505  conn->gss_RecvBuffer = NULL;
506  }
507  if (conn->gss_ResultBuffer)
508  {
509  free(conn->gss_ResultBuffer);
510  conn->gss_ResultBuffer = NULL;
511  }
512  conn->gssenc = false;
513  }
514 #endif
515 #ifdef ENABLE_SSPI
516  if (conn->sspitarget)
517  {
518  free(conn->sspitarget);
519  conn->sspitarget = NULL;
520  }
521  if (conn->sspicred)
522  {
523  FreeCredentialsHandle(conn->sspicred);
524  free(conn->sspicred);
525  conn->sspicred = NULL;
526  }
527  if (conn->sspictx)
528  {
529  DeleteSecurityContext(conn->sspictx);
530  free(conn->sspictx);
531  conn->sspictx = NULL;
532  }
533  conn->usesspi = 0;
534 #endif
535  if (conn->sasl_state)
536  {
538  conn->sasl_state = NULL;
539  }
540 }
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition: fe-connect.c:547
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:167
#define closesocket
Definition: port.h:349
const pg_fe_sasl_mech * sasl
Definition: libpq-int.h:546
PGcmdQueueEntry * cmd_queue_recycle
Definition: libpq-int.h:460
PGcmdQueueEntry * cmd_queue_tail
Definition: libpq-int.h:454
void * sasl_state
Definition: libpq-int.h:547
PGcmdQueueEntry * cmd_queue_head
Definition: libpq-int.h:453
void(* free)(void *state)
Definition: fe-auth-sasl.h:140

References closesocket, pg_conn::cmd_queue_head, pg_conn::cmd_queue_recycle, pg_conn::cmd_queue_tail, conn, free, pg_fe_sasl_mech::free, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::outCount, PGINVALID_SOCKET, pqFreeCommandQueue(), pqsecure_close(), pg_conn::sasl, pg_conn::sasl_state, and pg_conn::sock.

Referenced by handleSyncLoss(), pqClosePGconn(), pqConnectDBStart(), PQconnectPoll(), and pqReadData().

◆ pqDropServerData()

static void pqDropServerData ( PGconn conn)
static

Definition at line 573 of file fe-connect.c.

574 {
575  PGnotify *notify;
576  pgParameterStatus *pstatus;
577 
578  /* Forget pending notifies */
579  notify = conn->notifyHead;
580  while (notify != NULL)
581  {
582  PGnotify *prev = notify;
583 
584  notify = notify->next;
585  free(prev);
586  }
587  conn->notifyHead = conn->notifyTail = NULL;
588 
589  /* Reset ParameterStatus data, as well as variables deduced from it */
590  pstatus = conn->pstatus;
591  while (pstatus != NULL)
592  {
593  pgParameterStatus *prev = pstatus;
594 
595  pstatus = pstatus->next;
596  free(prev);
597  }
598  conn->pstatus = NULL;
600  conn->std_strings = false;
604  conn->sversion = 0;
605 
606  /* Drop large-object lookup data */
607  free(conn->lobjfuncs);
608  conn->lobjfuncs = NULL;
609 
610  /* Reset assorted other per-connection state */
611  conn->last_sqlstate[0] = '\0';
612  conn->auth_req_received = false;
613  conn->client_finished_auth = false;
614  conn->password_needed = false;
615  conn->gssapi_used = false;
616  conn->write_failed = false;
618  conn->write_err_msg = NULL;
619 
620  /*
621  * Cancel connections need to retain their be_pid and be_key across
622  * PQcancelReset invocations, otherwise they would not have access to the
623  * secret token of the connection they are supposed to cancel.
624  */
625  if (!conn->cancelRequest)
626  {
627  conn->be_pid = 0;
628  conn->be_key = 0;
629  }
630 }
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
Definition: scram-common.h:50
struct pgNotify * next
Definition: libpq-fe.h:201
struct pgParameterStatus * next
Definition: libpq-int.h:271
PGnotify * notifyHead
Definition: libpq-int.h:440
bool std_strings
Definition: libpq-int.h:502
bool write_failed
Definition: libpq-int.h:474
bool client_finished_auth
Definition: libpq-int.h:481
PGnotify * notifyTail
Definition: libpq-int.h:441
pgParameterStatus * pstatus
Definition: libpq-int.h:500
int scram_sha_256_iterations
Definition: libpq-int.h:548
PGlobjfuncs * lobjfuncs
Definition: libpq-int.h:507

References pg_conn::auth_req_received, pg_conn::be_key, pg_conn::be_pid, pg_conn::cancelRequest, pg_conn::client_encoding, pg_conn::client_finished_auth, conn, pg_conn::default_transaction_read_only, free, pg_conn::gssapi_used, pg_conn::in_hot_standby, pg_conn::last_sqlstate, pg_conn::lobjfuncs, pgNotify::next, pgParameterStatus::next, pg_conn::notifyHead, pg_conn::notifyTail, pg_conn::password_needed, PG_BOOL_UNKNOWN, PG_SQL_ASCII, pg_conn::pstatus, SCRAM_SHA_256_DEFAULT_ITERATIONS, pg_conn::scram_sha_256_iterations, pg_conn::std_strings, pg_conn::sversion, pg_conn::write_err_msg, and pg_conn::write_failed.

Referenced by pqClosePGconn(), and PQconnectPoll().

◆ PQerrorMessage()

char* PQerrorMessage ( const PGconn conn)

Definition at line 6948 of file fe-connect.c.

6949 {
6950  if (!conn)
6951  return libpq_gettext("connection pointer is NULL\n");
6952 
6953  /*
6954  * The errorMessage buffer might be marked "broken" due to having
6955  * previously failed to allocate enough memory for the message. In that
6956  * case, tell the application we ran out of memory.
6957  */
6959  return libpq_gettext("out of memory\n");
6960 
6961  return conn->errorMessage.data;
6962 }
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59

References conn, PQExpBufferData::data, pg_conn::errorMessage, libpq_gettext, and PQExpBufferBroken.

Referenced by _doSetSessionAuth(), _selectOutputSchema(), _selectTableAccessMethod(), _selectTablespace(), AcceptResult(), advanceConnectionState(), BaseBackup(), check_loadable_libraries(), check_prepare_conn(), CheckCopyStreamStop(), cluster_one_database(), compile_database_list(), compile_relation_list_one_db(), confirm_query_canceled_impl(), connect_database(), connect_pg_server(), ConnectDatabase(), connectDatabase(), connectToServer(), copy_connection(), CopyStreamPoll(), CopyStreamReceive(), CreateReplicationSlot(), dblink_connect(), dblink_error_message(), dblink_get_conn(), dblink_res_error(), dblink_send_query(), DescribeQuery(), die_on_query_failure(), do_connect(), do_lo_export(), do_lo_import(), do_lo_unlink(), doConnect(), DropReplicationSlot(), dump_lo_buf(), dumpLOs(), dumpTableData_copy(), ecpg_check_PQresult(), ecpg_raise_backend(), ECPGconnect(), EndDBCopyMode(), exec_command_password(), ExecQueryAndProcessResults(), executeCommand(), executeQuery(), executeQueryOrDie(), ExecuteSqlCommand(), ExecuteSqlCommandBuf(), executeStatement(), GetConnection(), GetSlotInformation(), GetTableInfo(), handleCopyIn(), handleCopyOut(), HandleEndOfCopyStream(), initPopulateTable(), libpqrcv_alter_slot(), libpqrcv_connect(), libpqrcv_create_slot(), libpqrcv_endstreaming(), libpqrcv_exec(), libpqrcv_identify_system(), libpqrcv_readtimelinehistoryfile(), libpqrcv_receive(), libpqrcv_send(), libpqrcv_startstreaming(), main(), my_truncate(), overwrite(), pgfdw_cancel_query_end(), pgfdw_report_error(), pickout(), PQcancelErrorMessage(), prepareCommand(), process_queued_fetch_requests(), process_result(), ProcessXLogDataMsg(), psql_get_variable(), readCommandResponse(), ReceiveCopyData(), RetrieveDataDirCreatePerm(), RetrieveWalSegSize(), run_command(), run_permutation(), run_reindex_command(), run_vacuum_command(), RunIdentifySystem(), send_cancellable_query_impl(), sendFeedback(), SendQuery(), sql_conn(), sql_exec(), start_postmaster(), StartRestoreLO(), storeQueryResult(), StreamLogicalLog(), TableCommandResultHandler(), test_cancel(), test_disallowed_in_pipeline(), test_multi_pipelines(), test_nosync(), test_pipeline_abort(), test_pipeline_idle(), test_pipelined_insert(), test_prepared(), test_simple_pipeline(), test_singlerowmode(), test_transaction(), test_uniqviol(), threadRun(), try_complete_step(), tryExecuteStatement(), vacuumlo(), verify_btree_slot_handler(), verify_heap_slot_handler(), and wait_for_connection_state().

◆ PQfinish()

void PQfinish ( PGconn conn)

Definition at line 4669 of file fe-connect.c.

4670 {
4671  if (conn)
4672  {
4674  freePGconn(conn);
4675  }
4676 }
void pqClosePGconn(PGconn *conn)
Definition: fe-connect.c:4623
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:4426

References conn, freePGconn(), and pqClosePGconn().

Referenced by appendQualifiedRelation(), BaseBackup(), check_for_data_types_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_for_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_logical_replication_slots(), check_new_cluster_subscription_configuration(), check_old_cluster_subscription_state(), check_proper_datallowconn(), CheckConnection(), cluster_all_databases(), cluster_one_database(), ConnectDatabase(), connectDatabase(), connectToServer(), create_logical_replication_slots(), disconnect_atexit(), disconnect_database(), DisconnectDatabase(), disconnectDatabase(), do_connect(), doConnect(), dumpRoleGUCPrivs(), dumpRoleMembership(), dumpTablespaces(), ecpg_finish(), executeCommand(), executeQuery(), executeQueryOrDie(), exit_nicely(), expand_dbname_patterns(), finishCon(), get_db_infos(), get_db_subscription_count(), get_loadable_libraries(), get_old_cluster_logical_slot_infos(), get_parallel_object_list(), get_rel_infos(), get_tablespace_paths(), get_template0_info(), GetConnection(), libpqrcv_connect(), libpqrcv_disconnect(), libpqsrv_connect_internal(), libpqsrv_disconnect(), LogStreamerMain(), main(), old_9_6_invalidate_hash_indexes(), PQcancelFinish(), PQping(), PQpingParams(), ReconnectToServer(), reindex_all_databases(), reindex_one_database(), report_extension_updates(), run_reindex_command(), runInitSteps(), set_frozenxids(), set_locale_and_encoding(), sql_conn(), sql_exec(), start_postmaster(), StreamLog(), StreamLogicalLog(), vacuum_all_databases(), vacuum_one_database(), and vacuumlo().

◆ pqFreeCommandQueue()

static void pqFreeCommandQueue ( PGcmdQueueEntry queue)
static

Definition at line 547 of file fe-connect.c.

548 {
549  while (queue != NULL)
550  {
551  PGcmdQueueEntry *cur = queue;
552 
553  queue = cur->next;
554  free(cur->query);
555  free(cur);
556  }
557 }
struct cursor * cur
Definition: ecpg.c:28
struct cursor * next
Definition: type.h:147

References cur, free, and cursor::next.

Referenced by pqDropConnection().

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char *  buf,
int  bufsize 
)

Definition at line 7456 of file fe-connect.c.

7457 {
7458 #ifndef WIN32
7459  const char *home;
7460 
7461  home = getenv("HOME");
7462  if (home == NULL || home[0] == '\0')
7463  return pg_get_user_home_dir(geteuid(), buf, bufsize);
7464  strlcpy(buf, home, bufsize);
7465  return true;
7466 #else
7467  char tmppath[MAX_PATH];
7468 
7469  ZeroMemory(tmppath, sizeof(tmppath));
7470  if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
7471  return false;
7472  snprintf(buf, bufsize, "%s/postgresql", tmppath);
7473  return true;
7474 #endif
7475 }
#define bufsize
Definition: indent_globs.h:36
bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen)
Definition: user.c:64

References buf, bufsize, pg_get_user_home_dir(), snprintf, and strlcpy().

Referenced by initialize_SSL(), parseServiceInfo(), and pqConnectOptions2().

◆ PQhost()

char* PQhost ( const PGconn conn)

Definition at line 6827 of file fe-connect.c.

6828 {
6829  if (!conn)
6830  return NULL;
6831 
6832  if (conn->connhost != NULL)
6833  {
6834  /*
6835  * Return the verbatim host value provided by user, or hostaddr in its
6836  * lack.
6837  */
6838  if (conn->connhost[conn->whichhost].host != NULL &&
6839  conn->connhost[conn->whichhost].host[0] != '\0')
6840  return conn->connhost[conn->whichhost].host;
6841  else if (conn->connhost[conn->whichhost].hostaddr != NULL &&
6842  conn->connhost[conn->whichhost].hostaddr[0] != '\0')
6843  return conn->connhost[conn->whichhost].hostaddr;
6844  }
6845 
6846  return "";
6847 }

References conn, pg_conn::connhost, pg_conn_host::host, pg_conn_host::hostaddr, and pg_conn::whichhost.

Referenced by do_connect(), exec_command_conninfo(), get_prompt(), libpqrcv_get_senderinfo(), main(), pg_GSS_load_servicename(), and SyncVariables().

◆ PQhostaddr()

char* PQhostaddr ( const PGconn conn)

Definition at line 6850 of file fe-connect.c.

6851 {
6852  if (!conn)
6853  return NULL;
6854 
6855  /* Return the parsed IP address */
6856  if (conn->connhost != NULL && conn->connip != NULL)
6857  return conn->connip;
6858 
6859  return "";
6860 }

References conn, pg_conn::connhost, and pg_conn::connip.

Referenced by do_connect(), and exec_command_conninfo().

◆ pqMakeEmptyPGconn()

PGconn* pqMakeEmptyPGconn ( void  )

Definition at line 4327 of file fe-connect.c.

4328 {
4329  PGconn *conn;
4330 
4331 #ifdef WIN32
4332 
4333  /*
4334  * Make sure socket support is up and running in this process.
4335  *
4336  * Note: the Windows documentation says that we should eventually do a
4337  * matching WSACleanup() call, but experience suggests that that is at
4338  * least as likely to cause problems as fix them. So we don't.
4339  */
4340  static bool wsastartup_done = false;
4341 
4342  if (!wsastartup_done)
4343  {
4344  WSADATA wsaData;
4345 
4346  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
4347  return NULL;
4348  wsastartup_done = true;
4349  }
4350 
4351  /* Forget any earlier error */
4352  WSASetLastError(0);
4353 #endif /* WIN32 */
4354 
4355  conn = (PGconn *) malloc(sizeof(PGconn));
4356  if (conn == NULL)
4357  return conn;
4358 
4359  /* Zero all pointers and booleans */
4360  MemSet(conn, 0, sizeof(PGconn));
4361 
4362  /* install default notice hooks */
4365 
4370  conn->options_valid = false;
4371  conn->nonblocking = false;
4373  conn->std_strings = false; /* unless server says differently */
4380  conn->Pfdebug = NULL;
4381 
4382  /*
4383  * We try to send at least 8K at a time, which is the usual size of pipe
4384  * buffers on Unix systems. That way, when we are sending a large amount
4385  * of data, we avoid incurring extra kernel context swaps for partial
4386  * bufferloads. The output buffer is initially made 16K in size, and we
4387  * try to dump it after accumulating 8K.
4388  *
4389  * With the same goal of minimizing context swaps, the input buffer will
4390  * be enlarged anytime it has less than 8K free, so we initially allocate
4391  * twice that.
4392  */
4393  conn->inBufSize = 16 * 1024;
4394  conn->inBuffer = (char *) malloc(conn->inBufSize);
4395  conn->outBufSize = 16 * 1024;
4396  conn->outBuffer = (char *) malloc(conn->outBufSize);
4397  conn->rowBufLen = 32;
4398  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
4401 
4402  if (conn->inBuffer == NULL ||
4403  conn->outBuffer == NULL ||
4404  conn->rowBuf == NULL ||
4407  {
4408  /* out of memory already :-( */
4409  freePGconn(conn);
4410  conn = NULL;
4411  }
4412 
4413  return conn;
4414 }
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:7150
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:7165
@ PQSHOW_CONTEXT_ERRORS
Definition: libpq-fe.h:139
@ PQERRORS_DEFAULT
Definition: libpq-fe.h:131
PQnoticeReceiver noticeRec
Definition: libpq-int.h:155
int inBufSize
Definition: libpq-int.h:513
PGVerbosity verbosity
Definition: libpq-int.h:505
int rowBufLen
Definition: libpq-int.h:530
int outBufSize
Definition: libpq-int.h:520
PGNoticeHooks noticeHooks
Definition: libpq-int.h:421
FILE * Pfdebug
Definition: libpq-int.h:417
PGContextVisibility show_context
Definition: libpq-int.h:506

References pg_conn::asyncStatus, pg_conn::client_encoding, conn, CONNECTION_BAD, pg_conn::default_transaction_read_only, defaultNoticeProcessor(), defaultNoticeReceiver(), pg_conn::errorMessage, freePGconn(), pg_conn::in_hot_standby, pg_conn::inBuffer, pg_conn::inBufSize, initPQExpBuffer(), malloc, MemSet, pg_conn::nonblocking, pg_conn::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeRec, pg_conn::options_valid, pg_conn::outBuffer, pg_conn::outBufSize, pg_conn::Pfdebug, PG_BOOL_UNKNOWN, PG_SQL_ASCII, PGASYNC_IDLE, PGINVALID_SOCKET, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PQERRORS_DEFAULT, PQExpBufferBroken, PQSHOW_CONTEXT_ERRORS, PQTRANS_IDLE, pg_conn::rowBuf, pg_conn::rowBufLen, SCRAM_SHA_256_DEFAULT_ITERATIONS, pg_conn::scram_sha_256_iterations, pg_conn::show_context, pg_conn::sock, pg_conn::status, pg_conn::std_strings, pg_conn::verbosity, pg_conn::workBuffer, and pg_conn::xactStatus.

Referenced by PQcancelCreate(), PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().

◆ PQoptions()

char* PQoptions ( const PGconn conn)

Definition at line 6887 of file fe-connect.c.

6888 {
6889  if (!conn)
6890  return NULL;
6891  return conn->pgoptions;
6892 }

References conn, and pg_conn::pgoptions.

◆ pqPacketSend()

int pqPacketSend ( PGconn conn,
char  pack_type,
const void *  buf,
size_t  buf_len 
)

Definition at line 4777 of file fe-connect.c.

4779 {
4780  /* Start the message. */
4781  if (pqPutMsgStart(pack_type, conn))
4782  return STATUS_ERROR;
4783 
4784  /* Send the message body. */
4785  if (pqPutnchar(buf, buf_len, conn))
4786  return STATUS_ERROR;
4787 
4788  /* Finish the message. */
4789  if (pqPutMsgEnd(conn))
4790  return STATUS_ERROR;
4791 
4792  /* Flush to ensure backend gets it. */
4793  if (pqFlush(conn))
4794  return STATUS_ERROR;
4795 
4796  return STATUS_OK;
4797 }
#define STATUS_ERROR
Definition: c.h:1157
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition: fe-misc.c:459
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:203
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:518

References buf, conn, pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), STATUS_ERROR, and STATUS_OK.

Referenced by pg_password_sendauth(), pg_SASL_continue(), and PQconnectPoll().

◆ PQparameterStatus()

const char* PQparameterStatus ( const PGconn conn,
const char *  paramName 
)

Definition at line 6913 of file fe-connect.c.

6914 {
6915  const pgParameterStatus *pstatus;
6916 
6917  if (!conn || !paramName)
6918  return NULL;
6919  for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
6920  {
6921  if (strcmp(pstatus->name, paramName) == 0)
6922  return pstatus->value;
6923  }
6924  return NULL;
6925 }

References conn, pgParameterStatus::name, pgParameterStatus::next, pg_conn::pstatus, and pgParameterStatus::value.

Referenced by _check_database_version(), applyRemoteGucs(), BaseBackup(), CheckServerVersionForStreaming(), connectDatabase(), connection_warnings(), ecpg_build_params(), GetConnection(), is_superuser(), main(), printVersion(), session_username(), setup_connection(), standard_strings(), and SyncVariables().

◆ pqParseIntParam()

bool pqParseIntParam ( const char *  value,
int *  result,
PGconn conn,
const char *  context 
)

Definition at line 7483 of file fe-connect.c.

7485 {
7486  char *end;
7487  long numval;
7488 
7489  Assert(value != NULL);
7490 
7491  *result = 0;
7492 
7493  /* strtol(3) skips leading whitespaces */
7494  errno = 0;
7495  numval = strtol(value, &end, 10);
7496 
7497  /*
7498  * If no progress was done during the parsing or an error happened, fail.
7499  * This tests properly for overflows of the result.
7500  */
7501  if (value == end || errno != 0 || numval != (int) numval)
7502  goto error;
7503 
7504  /*
7505  * Skip any trailing whitespace; if anything but whitespace remains before
7506  * the terminating character, fail
7507  */
7508  while (*end != '\0' && isspace((unsigned char) *end))
7509  end++;
7510 
7511  if (*end != '\0')
7512  goto error;
7513 
7514  *result = numval;
7515  return true;
7516 
7517 error:
7518  libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
7519  value, context);
7520  return false;
7521 }
tree context
Definition: radixtree.h:1797
static void error(void)
Definition: sql-dyntest.c:147

References Assert(), conn, context, error(), libpq_append_conn_error(), and value.

Referenced by pqConnectDBComplete(), PQconnectPoll(), PQgetCancel(), setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), and setTCPUserTimeout().

◆ PQpass()

char* PQpass ( const PGconn conn)

Definition at line 6810 of file fe-connect.c.

6811 {
6812  char *password = NULL;
6813 
6814  if (!conn)
6815  return NULL;
6816  if (conn->connhost != NULL)
6818  if (password == NULL)
6819  password = conn->pgpass;
6820  /* Historically we've returned "" not NULL for no password specified */
6821  if (password == NULL)
6822  password = "";
6823  return password;
6824 }

References conn, pg_conn::connhost, password, pg_conn_host::password, pg_conn::pgpass, and pg_conn::whichhost.

Referenced by ConnectDatabase(), and PQconnectionNeedsPassword().

◆ PQping()

PGPing PQping ( const char *  conninfo)

Definition at line 749 of file fe-connect.c.

750 {
751  PGconn *conn = PQconnectStart(conninfo);
752  PGPing ret;
753 
754  ret = internal_ping(conn);
755  PQfinish(conn);
756 
757  return ret;
758 }
static PGPing internal_ping(PGconn *conn)
Definition: fe-connect.c:4263
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4669
PGPing
Definition: libpq-fe.h:149

References conn, internal_ping(), PQconnectStart(), and PQfinish().

◆ PQpingParams()

PGPing PQpingParams ( const char *const *  keywords,
const char *const *  values,
int  expand_dbname 
)

Definition at line 696 of file fe-connect.c.

699 {
700  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
701  PGPing ret;
702 
703  ret = internal_ping(conn);
704  PQfinish(conn);
705 
706  return ret;
707 }

References conn, internal_ping(), PQconnectStartParams(), PQfinish(), and values.

Referenced by main(), and regression_main().

◆ PQpipelineStatus()

PGpipelineStatus PQpipelineStatus ( const PGconn conn)

◆ PQport()

char* PQport ( const PGconn conn)

Definition at line 6863 of file fe-connect.c.

6864 {
6865  if (!conn)
6866  return NULL;
6867 
6868  if (conn->connhost != NULL)
6869  return conn->connhost[conn->whichhost].port;
6870 
6871  return "";
6872 }

References conn, pg_conn::connhost, pg_conn_host::port, and pg_conn::whichhost.

Referenced by do_connect(), exec_command_conninfo(), get_prompt(), libpqrcv_get_senderinfo(), main(), and SyncVariables().

◆ PQprotocolVersion()

int PQprotocolVersion ( const PGconn conn)

Definition at line 6928 of file fe-connect.c.

6929 {
6930  if (!conn)
6931  return 0;
6932  if (conn->status == CONNECTION_BAD)
6933  return 0;
6934  return PG_PROTOCOL_MAJOR(conn->pversion);
6935 }
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:87

References conn, CONNECTION_BAD, PG_PROTOCOL_MAJOR, pg_conn::pversion, and pg_conn::status.

Referenced by handleCopyIn().

◆ PQregisterThreadLock()

pgthreadlock_t PQregisterThreadLock ( pgthreadlock_t  newhandler)

Definition at line 7551 of file fe-connect.c.

7552 {
7554 
7555  if (newhandler)
7556  pg_g_threadlock = newhandler;
7557  else
7559 
7560  return prev;
7561 }
static void default_threadlock(int acquire)
Definition: fe-connect.c:7534
pgthreadlock_t pg_g_threadlock
Definition: fe-connect.c:444
void(* pgthreadlock_t)(int acquire)
Definition: libpq-fe.h:431

References default_threadlock(), and pg_g_threadlock.

◆ pqReleaseConnHosts()

void pqReleaseConnHosts ( PGconn conn)

Definition at line 4507 of file fe-connect.c.

4508 {
4509  if (conn->connhost)
4510  {
4511  for (int i = 0; i < conn->nconnhost; ++i)
4512  {
4513  free(conn->connhost[i].host);
4515  free(conn->connhost[i].port);
4516  if (conn->connhost[i].password != NULL)
4517  {
4519  strlen(conn->connhost[i].password));
4521  }
4522  }
4523  free(conn->connhost);
4524  }
4525 }

References conn, pg_conn::connhost, explicit_bzero(), free, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::nconnhost, pg_conn_host::password, and pg_conn_host::port.

Referenced by freePGconn(), and PQcancelCreate().

◆ PQreset()

void PQreset ( PGconn conn)

Definition at line 4683 of file fe-connect.c.

4684 {
4685  if (conn)
4686  {
4688 
4690  {
4691  /*
4692  * Notify event procs of successful reset.
4693  */
4694  int i;
4695 
4696  for (i = 0; i < conn->nEvents; i++)
4697  {
4698  PGEventConnReset evt;
4699 
4700  evt.conn = conn;
4701  (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
4702  conn->events[i].passThrough);
4703  }
4704  }
4705  }
4706 }
@ PGEVT_CONNRESET
Definition: libpq-events.h:30

References conn, PGEventConnReset::conn, pg_conn::events, i, pg_conn::nEvents, PGEvent::passThrough, PGEVT_CONNRESET, pqClosePGconn(), pqConnectDBComplete(), pqConnectDBStart(), and PGEvent::proc.

Referenced by CheckConnection().

◆ PQresetPoll()

PostgresPollingStatusType PQresetPoll ( PGconn conn)

Definition at line 4735 of file fe-connect.c.

4736 {
4737  if (conn)
4738  {
4740 
4741  if (status == PGRES_POLLING_OK)
4742  {
4743  /*
4744  * Notify event procs of successful reset.
4745  */
4746  int i;
4747 
4748  for (i = 0; i < conn->nEvents; i++)
4749  {
4750  PGEventConnReset evt;
4751 
4752  evt.conn = conn;
4753  (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
4754  conn->events[i].passThrough);
4755  }
4756  }
4757 
4758  return status;
4759  }
4760 
4761  return PGRES_POLLING_FAILED;
4762 }

References conn, PGEventConnReset::conn, pg_conn::events, i, pg_conn::nEvents, PGEvent::passThrough, PGEVT_CONNRESET, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PQconnectPoll(), and PGEvent::proc.

◆ PQresetStart()

int PQresetStart ( PGconn conn)

Definition at line 4716 of file fe-connect.c.

4717 {
4718  if (conn)
4719  {
4721 
4722  return pqConnectDBStart(conn);
4723  }
4724 
4725  return 0;
4726 }

References conn, pqClosePGconn(), and pqConnectDBStart().

◆ PQserverVersion()

◆ PQsetClientEncoding()

int PQsetClientEncoding ( PGconn conn,
const char *  encoding 
)

Definition at line 7044 of file fe-connect.c.

7045 {
7046  char qbuf[128];
7047  static const char query[] = "set client_encoding to '%s'";
7048  PGresult *res;
7049  int status;
7050 
7051  if (!conn || conn->status != CONNECTION_OK)
7052  return -1;
7053 
7054  if (!encoding)
7055  return -1;
7056 
7057  /* Resolve special "auto" value from the locale */
7058  if (strcmp(encoding, "auto") == 0)
7060 
7061  /* check query buffer overflow */
7062  if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
7063  return -1;
7064 
7065  /* ok, now send a query */
7066  sprintf(qbuf, query, encoding);
7067  res = PQexec(conn, qbuf);
7068 
7069  if (res == NULL)
7070  return -1;
7072  status = -1;
7073  else
7074  {
7075  /*
7076  * We rely on the backend to report the parameter value, and we'll
7077  * change state at that time.
7078  */
7079  status = 0; /* everything is ok */
7080  }
7081  PQclear(res);
7082  return status;
7083 }
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2224
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:100
int32 encoding
Definition: pg_database.h:41
#define sprintf
Definition: port.h:240

References conn, CONNECTION_OK, encoding, pg_encoding_to_char, pg_get_encoding_from_locale(), PGRES_COMMAND_OK, PQclear(), PQexec(), res, pg_result::resultStatus, sprintf, and pg_conn::status.

Referenced by dblink_connect(), dblink_get_conn(), exec_command_encoding(), main(), and setup_connection().

◆ PQsetdbLogin()

PGconn* PQsetdbLogin ( const char *  pghost,
const char *  pgport,
const char *  pgoptions,
const char *  pgtty,
const char *  dbName,
const char *  login,
const char *  pwd 
)

Definition at line 1857 of file fe-connect.c.

1860 {
1861  PGconn *conn;
1862 
1863  /*
1864  * Allocate memory for the conn structure. Note that we also expect this
1865  * to initialize conn->errorMessage to empty. All subsequent steps during
1866  * connection initialization will only append to that buffer.
1867  */
1868  conn = pqMakeEmptyPGconn();
1869  if (conn == NULL)
1870  return NULL;
1871 
1872  /*
1873  * If the dbName parameter contains what looks like a connection string,
1874  * parse it into conn struct using connectOptions1.
1875  */
1877  {
1878  if (!connectOptions1(conn, dbName))
1879  return conn;
1880  }
1881  else
1882  {
1883  /*
1884  * Old-style path: first, parse an empty conninfo string in order to
1885  * set up the same defaults that PQconnectdb() would use.
1886  */
1887  if (!connectOptions1(conn, ""))
1888  return conn;
1889 
1890  /* Insert dbName parameter value into struct */
1891  if (dbName && dbName[0] != '\0')
1892  {
1893  free(conn->dbName);
1894  conn->dbName = strdup(dbName);
1895  if (!conn->dbName)
1896  goto oom_error;
1897  }
1898  }
1899 
1900  /*
1901  * Insert remaining parameters into struct, overriding defaults (as well
1902  * as any conflicting data from dbName taken as a conninfo).
1903  */
1904  if (pghost && pghost[0] != '\0')
1905  {
1906  free(conn->pghost);
1907  conn->pghost = strdup(pghost);
1908  if (!conn->pghost)
1909  goto oom_error;
1910  }
1911 
1912  if (pgport && pgport[0] != '\0')
1913  {
1914  free(conn->pgport);
1915  conn->pgport = strdup(pgport);
1916  if (!conn->pgport)
1917  goto oom_error;
1918  }
1919 
1920  if (pgoptions && pgoptions[0] != '\0')
1921  {
1922  free(conn->pgoptions);
1923  conn->pgoptions = strdup(pgoptions);
1924  if (!conn->pgoptions)
1925  goto oom_error;
1926  }
1927 
1928  if (login && login[0] != '\0')
1929  {
1930  free(conn->pguser);
1931  conn->pguser = strdup(login);
1932  if (!conn->pguser)
1933  goto oom_error;
1934  }
1935 
1936  if (pwd && pwd[0] != '\0')
1937  {
1938  free(conn->pgpass);
1939  conn->pgpass = strdup(pwd);
1940  if (!conn->pgpass)
1941  goto oom_error;
1942  }
1943 
1944  /*
1945  * Compute derived options
1946  */
1947  if (!pqConnectOptions2(conn))
1948  return conn;
1949 
1950  /*
1951  * Connect to the database
1952  */
1953  if (pqConnectDBStart(conn))
1954  (void) pqConnectDBComplete(conn);
1955 
1956  return conn;
1957 
1958 oom_error:
1960  libpq_append_conn_error(conn, "out of memory");
1961  return conn;
1962 }
const char * pghost
Definition: pgbench.c:294
const char * pgport
Definition: pgbench.c:295
const char * dbName
Definition: pgbench.c:297

References conn, CONNECTION_BAD, connectOptions1(), dbName, pg_conn::dbName, free, libpq_append_conn_error(), pghost, pg_conn::pghost, pg_conn::pgoptions, pg_conn::pgpass, pgport, pg_conn::pgport, pg_conn::pguser, pqConnectDBComplete(), pqConnectDBStart(), pqConnectOptions2(), pqMakeEmptyPGconn(), recognized_connection_string(), and pg_conn::status.

◆ PQsetErrorContextVisibility()

PGContextVisibility PQsetErrorContextVisibility ( PGconn conn,
PGContextVisibility  show_context 
)

Definition at line 7098 of file fe-connect.c.

7099 {
7100  PGContextVisibility old;
7101 
7102  if (!conn)
7103  return PQSHOW_CONTEXT_ERRORS;
7104  old = conn->show_context;
7105  conn->show_context = show_context;
7106  return old;
7107 }
PGContextVisibility
Definition: libpq-fe.h:137

References conn, PQSHOW_CONTEXT_ERRORS, and pg_conn::show_context.

Referenced by show_context_hook(), and SyncVariables().

◆ PQsetErrorVerbosity()

PGVerbosity PQsetErrorVerbosity ( PGconn conn,
PGVerbosity  verbosity 
)

Definition at line 7086 of file fe-connect.c.

7087 {
7088  PGVerbosity old;
7089 
7090  if (!conn)
7091  return PQERRORS_DEFAULT;
7092  old = conn->verbosity;
7093  conn->verbosity = verbosity;
7094  return old;
7095 }
PGVerbosity
Definition: libpq-fe.h:129

References conn, PQERRORS_DEFAULT, and pg_conn::verbosity.

Referenced by main(), SyncVariables(), and verbosity_hook().

◆ PQsetNoticeProcessor()

PQnoticeProcessor PQsetNoticeProcessor ( PGconn conn,
PQnoticeProcessor  proc,
void *  arg 
)

Definition at line 7127 of file fe-connect.c.

7128 {
7129  PQnoticeProcessor old;
7130 
7131  if (conn == NULL)
7132  return NULL;
7133 
7134  old = conn->noticeHooks.noticeProc;
7135  if (proc)
7136  {
7137  conn->noticeHooks.noticeProc = proc;
7139  }
7140  return old;
7141 }
void(* PQnoticeProcessor)(void *arg, const char *message)
Definition: libpq-fe.h:206

References arg, conn, pg_conn::noticeHooks, PGNoticeHooks::noticeProc, and PGNoticeHooks::noticeProcArg.

Referenced by ConnectDatabase(), do_connect(), main(), and test_pipeline_idle().

◆ PQsetNoticeReceiver()

PQnoticeReceiver PQsetNoticeReceiver ( PGconn conn,
PQnoticeReceiver  proc,
void *  arg 
)

Definition at line 7110 of file fe-connect.c.

7111 {
7112  PQnoticeReceiver old;
7113 
7114  if (conn == NULL)
7115  return NULL;
7116 
7117  old = conn->noticeHooks.noticeRec;
7118  if (proc)
7119  {
7120  conn->noticeHooks.noticeRec = proc;
7122  }
7123  return old;
7124 }
void(* PQnoticeReceiver)(void *arg, const PGresult *res)
Definition: libpq-fe.h:205
void * noticeRecArg
Definition: libpq-int.h:156

References arg, conn, pg_conn::noticeHooks, PGNoticeHooks::noticeRec, and PGNoticeHooks::noticeRecArg.

Referenced by ECPGconnect().

◆ PQsocket()

◆ PQstatus()

◆ PQtransactionStatus()

◆ PQtty()

char* PQtty ( const PGconn conn)

Definition at line 6879 of file fe-connect.c.

6880 {
6881  if (!conn)
6882  return NULL;
6883  return "";
6884 }

References conn.

◆ PQuser()

char* PQuser ( const PGconn conn)

Definition at line 6802 of file fe-connect.c.

6803 {
6804  if (!conn)
6805  return NULL;
6806  return conn->pguser;
6807 }

References conn, and pg_conn::pguser.

Referenced by do_connect(), exec_command_conninfo(), get_prompt(), main(), session_username(), and SyncVariables().

◆ pwdfMatchesString()

static char * pwdfMatchesString ( char *  buf,
const char *  token 
)
static

Definition at line 7177 of file fe-connect.c.

7178 {
7179  char *tbuf;
7180  const char *ttok;
7181  bool bslash = false;
7182 
7183  if (buf == NULL || token == NULL)
7184  return NULL;
7185  tbuf = buf;
7186  ttok = token;
7187  if (tbuf[0] == '*' && tbuf[1] == ':')
7188  return tbuf + 2;
7189  while (*tbuf != 0)
7190  {
7191  if (*tbuf == '\\' && !bslash)
7192  {
7193  tbuf++;
7194  bslash = true;
7195  }
7196  if (*tbuf == ':' && *ttok == 0 && !bslash)
7197  return tbuf + 1;
7198  bslash = false;
7199  if (*ttok == 0)
7200  return NULL;
7201  if (*tbuf == *ttok)
7202  {
7203  tbuf++;
7204  ttok++;
7205  }
7206  else
7207  return NULL;
7208  }
7209  return NULL;
7210 }
#define token
Definition: indent_globs.h:126

References buf, and token.

Referenced by passwordFromFile().

◆ recognized_connection_string()

static bool recognized_connection_string ( const char *  connstr)
static

Definition at line 5633 of file fe-connect.c.

5634 {
5635  return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
5636 }

References connstr, and uri_prefix_length().

Referenced by conninfo_array_parse(), and PQsetdbLogin().

◆ release_conn_addrinfo()

static void release_conn_addrinfo ( PGconn conn)
static

Definition at line 4575 of file fe-connect.c.

4576 {
4577  if (conn->addr)
4578  {
4579  free(conn->addr);
4580  conn->addr = NULL;
4581  }
4582 }

References pg_conn::addr, conn, and free.

Referenced by freePGconn(), pqClosePGconn(), and PQconnectPoll().

◆ sendTerminateConn()

static void sendTerminateConn ( PGconn conn)
static

Definition at line 4589 of file fe-connect.c.

4590 {
4591  /*
4592  * The Postgres cancellation protocol does not have a notion of a
4593  * Terminate message, so don't send one.
4594  */
4595  if (conn->cancelRequest)
4596  return;
4597 
4598  /*
4599  * Note that the protocol doesn't allow us to send Terminate messages
4600  * during the startup phase.
4601  */
4603  {
4604  /*
4605  * Try to send "close connection" message to backend. Ignore any
4606  * error.
4607  */
4609  pqPutMsgEnd(conn);
4610  (void) pqFlush(conn);
4611  }
4612 }
#define PqMsg_Terminate
Definition: protocol.h:28

References pg_conn::cancelRequest, conn, CONNECTION_OK, PGINVALID_SOCKET, pqFlush(), PqMsg_Terminate, pqPutMsgEnd(), pqPutMsgStart(), pg_conn::sock, and pg_conn::status.

Referenced by pqClosePGconn(), and PQconnectPoll().

◆ setKeepalivesCount()

static int setKeepalivesCount ( PGconn conn)
static

Definition at line 2194 of file fe-connect.c.

2195 {
2196  int count;
2197 
2198  if (conn->keepalives_count == NULL)
2199  return 1;
2200 
2201  if (!pqParseIntParam(conn->keepalives_count, &count, conn,
2202  "keepalives_count"))
2203  return 0;
2204  if (count < 0)
2205  count = 0;
2206 
2207 #ifdef TCP_KEEPCNT
2208  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT,
2209  (char *) &count, sizeof(count)) < 0)
2210  {
2211  char sebuf[PG_STRERROR_R_BUFLEN];
2212 
2213  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2214  "setsockopt",
2215  "TCP_KEEPCNT",
2216  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2217  return 0;
2218  }
2219 #endif
2220 
2221  return 1;
2222 }

References conn, pg_conn::keepalives_count, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, pqParseIntParam(), pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

◆ setKeepalivesIdle()

static int setKeepalivesIdle ( PGconn conn)
static

Definition at line 2125 of file fe-connect.c.

2126 {
2127  int idle;
2128 
2129  if (conn->keepalives_idle == NULL)
2130  return 1;
2131 
2132  if (!pqParseIntParam(conn->keepalives_idle, &idle, conn,
2133  "keepalives_idle"))
2134  return 0;
2135  if (idle < 0)
2136  idle = 0;
2137 
2138 #ifdef PG_TCP_KEEPALIVE_IDLE
2139  if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
2140  (char *) &idle, sizeof(idle)) < 0)
2141  {
2142  char sebuf[PG_STRERROR_R_BUFLEN];
2143 
2144  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2145  "setsockopt",
2146  PG_TCP_KEEPALIVE_IDLE_STR,
2147  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2148  return 0;
2149  }
2150 #endif
2151 
2152  return 1;
2153 }

References conn, pg_conn::keepalives_idle, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, pqParseIntParam(), pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

◆ setKeepalivesInterval()

static int setKeepalivesInterval ( PGconn conn)
static

Definition at line 2159 of file fe-connect.c.

2160 {
2161  int interval;
2162 
2163  if (conn->keepalives_interval == NULL)
2164  return 1;
2165 
2167  "keepalives_interval"))
2168  return 0;
2169  if (interval < 0)
2170  interval = 0;
2171 
2172 #ifdef TCP_KEEPINTVL
2173  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL,
2174  (char *) &interval, sizeof(interval)) < 0)
2175  {
2176  char sebuf[PG_STRERROR_R_BUFLEN];
2177 
2178  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2179  "setsockopt",
2180  "TCP_KEEPINTVL",
2181  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2182  return 0;
2183  }
2184 #endif
2185 
2186  return 1;
2187 }

References conn, pg_conn::keepalives_interval, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, pqParseIntParam(), pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

◆ setTCPUserTimeout()

static int setTCPUserTimeout ( PGconn conn)
static

Definition at line 2291 of file fe-connect.c.

2292 {
2293  int timeout;
2294 
2295  if (conn->pgtcp_user_timeout == NULL)
2296  return 1;
2297 
2298  if (!pqParseIntParam(conn->pgtcp_user_timeout, &timeout, conn,
2299  "tcp_user_timeout"))
2300  return 0;
2301 
2302  if (timeout < 0)
2303  timeout = 0;
2304 
2305 #ifdef TCP_USER_TIMEOUT
2306  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_USER_TIMEOUT,
2307  (char *) &timeout, sizeof(timeout)) < 0)
2308  {
2309  char sebuf[256];
2310 
2311  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2312  "setsockopt",
2313  "TCP_USER_TIMEOUT",
2314  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2315  return 0;
2316  }
2317 #endif
2318 
2319  return 1;
2320 }

References conn, libpq_append_conn_error(), pg_conn::pgtcp_user_timeout, pqParseIntParam(), pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

◆ sslVerifyProtocolRange()

static bool sslVerifyProtocolRange ( const char *  min,
const char *  max 
)
static

Definition at line 7403 of file fe-connect.c.

7404 {
7407 
7408  /* If at least one of the bounds is not set, the range is valid */
7409  if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0)
7410  return true;
7411 
7412  /*
7413  * If the minimum version is the lowest one we accept, then all options
7414  * for the maximum are valid.
7415  */
7416  if (pg_strcasecmp(min, "TLSv1") == 0)
7417  return true;
7418 
7419  /*
7420  * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the
7421  * maximum is incorrect.
7422  */
7423  if (pg_strcasecmp(max, "TLSv1") == 0)
7424  return false;
7425 
7426  /*
7427  * At this point we know that we have a mix of TLSv1.1 through 1.3
7428  * versions.
7429  */
7430  if (pg_strcasecmp(min, max) > 0)
7431  return false;
7432 
7433  return true;
7434 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

References Assert(), pg_strcasecmp(), and sslVerifyProtocolVersion().

Referenced by pqConnectOptions2().

◆ sslVerifyProtocolVersion()

static bool sslVerifyProtocolVersion ( const char *  version)
static

Definition at line 7377 of file fe-connect.c.

7378 {
7379  /*
7380  * An empty string and a NULL value are considered valid as it is
7381  * equivalent to ignoring the parameter.
7382  */
7383  if (!version || strlen(version) == 0)
7384  return true;
7385 
7386  if (pg_strcasecmp(version, "TLSv1") == 0 ||
7387  pg_strcasecmp(version, "TLSv1.1") == 0 ||
7388  pg_strcasecmp(version, "TLSv1.2") == 0 ||
7389  pg_strcasecmp(version, "TLSv1.3") == 0)
7390  return true;
7391 
7392  /* anything else is wrong */
7393  return false;
7394 }

References pg_strcasecmp().

Referenced by pqConnectOptions2(), and sslVerifyProtocolRange().

◆ store_conn_addrinfo()

static int store_conn_addrinfo ( PGconn conn,
struct addrinfo *  addrlist 
)
static

Definition at line 4536 of file fe-connect.c.

4537 {
4538  struct addrinfo *ai = addrlist;
4539 
4540  conn->whichaddr = 0;
4541 
4542  conn->naddr = 0;
4543  while (ai)
4544  {
4545  ai = ai->ai_next;
4546  conn->naddr++;
4547  }
4548 
4549  conn->addr = calloc(conn->naddr, sizeof(AddrInfo));
4550  if (conn->addr == NULL)
4551  {
4552  libpq_append_conn_error(conn, "out of memory");
4553  return 1;
4554  }
4555 
4556  ai = addrlist;
4557  for (int i = 0; i < conn->naddr; i++)
4558  {
4559  conn->addr[i].family = ai->ai_family;
4560 
4561  memcpy(&conn->addr[i].addr.addr, ai->ai_addr,
4562  ai->ai_addrlen);
4563  conn->addr[i].addr.salen = ai->ai_addrlen;
4564  ai = ai->ai_next;
4565  }
4566 
4567  return 0;
4568 }

References AddrInfo::addr, SockAddr::addr, pg_conn::addr, calloc, conn, AddrInfo::family, i, libpq_append_conn_error(), pg_conn::naddr, SockAddr::salen, and pg_conn::whichaddr.

Referenced by PQconnectPoll().

◆ uri_prefix_length()

static int uri_prefix_length ( const char *  connstr)
static

Definition at line 5610 of file fe-connect.c.

5611 {
5612  if (strncmp(connstr, uri_designator,
5613  sizeof(uri_designator) - 1) == 0)
5614  return sizeof(uri_designator) - 1;
5615 
5616  if (strncmp(connstr, short_uri_designator,
5617  sizeof(short_uri_designator) - 1) == 0)
5618  return sizeof(short_uri_designator) - 1;
5619 
5620  return 0;
5621 }
static const char short_uri_designator[]
Definition: fe-connect.c:387
static const char uri_designator[]
Definition: fe-connect.c:386

References connstr, short_uri_designator, and uri_designator.

Referenced by conninfo_uri_parse_options(), parse_connection_string(), and recognized_connection_string().

◆ useKeepalives()

static int useKeepalives ( PGconn conn)
static

Definition at line 2107 of file fe-connect.c.

2108 {
2109  char *ep;
2110  int val;
2111 
2112  if (conn->keepalives == NULL)
2113  return 1;
2114  val = strtol(conn->keepalives, &ep, 10);
2115  if (*ep)
2116  return -1;
2117  return val != 0 ? 1 : 0;
2118 }

References conn, pg_conn::keepalives, and val.

Referenced by PQconnectPoll().

Variable Documentation

◆ EnvironmentOptions

const PQEnvironmentOption EnvironmentOptions[]
static
Initial value:
=
{
{
"PGDATESTYLE", "datestyle"
},
{
"PGTZ", "timezone"
},
{
"PGGEQO", "geqo"
},
{
NULL, NULL
}
}

Definition at line 367 of file fe-connect.c.

Referenced by PQconnectPoll().

◆ pg_g_threadlock

Definition at line 444 of file fe-connect.c.

Referenced by PQregisterThreadLock().

◆ PQconninfoOptions

const internalPQconninfoOption PQconninfoOptions[]
static

Definition at line 189 of file fe-connect.c.

Referenced by conninfo_init(), fillPGconn(), PQconninfo(), and pqCopyPGconn().

◆ short_uri_designator

const char short_uri_designator[] = "postgres://"
static

Definition at line 387 of file fe-connect.c.

Referenced by uri_prefix_length().

◆ uri_designator

const char uri_designator[] = "postgresql://"
static

Definition at line 386 of file fe-connect.c.

Referenced by uri_prefix_length().