PostgreSQL Source Code git master
Loading...
Searching...
No Matches
libpq-int.h File Reference
#include "libpq-events.h"
#include <netdb.h>
#include <sys/socket.h>
#include <time.h>
#include <pthread.h>
#include <signal.h>
#include "libpq/pqcomm.h"
#include "fe-auth-sasl.h"
#include "pqexpbuffer.h"
#include "libpq/pg-gssapi.h"
#include "common/pg_prng.h"
Include dependency graph for libpq-int.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

union  pgresult_data
 
struct  pgresParamDesc
 
struct  pgresAttValue
 
struct  pgMessageField
 
struct  PGNoticeHooks
 
struct  PGEvent
 
struct  pg_result
 
struct  PQEnvironmentOption
 
struct  pgParameterStatus
 
struct  pgLobjfuncs
 
struct  pgDataValue
 
struct  PGcmdQueueEntry
 
struct  pg_conn_host
 
struct  pg_conn
 

Macros

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */
 
#define NULL_LEN   (-1) /* pg_result len for NULL value */
 
#define ENC_ERROR   0
 
#define ENC_PLAINTEXT   0x01
 
#define ENC_GSSAPI   0x02
 
#define ENC_SSL   0x04
 
#define AUTH_RESPONSE_GSS   'G'
 
#define AUTH_RESPONSE_PASSWORD   'P'
 
#define AUTH_RESPONSE_SASL_INITIAL   'I'
 
#define AUTH_RESPONSE_SASL   'S'
 
#define pglock_thread()   pg_g_threadlock(true)
 
#define pgunlock_thread()   pg_g_threadlock(false)
 
#define pqClearConnErrorState(conn)
 
#define pgHavePendingResult(conn)    ((conn)->result != NULL || (conn)->error_result)
 
#define pqIsnonblocking(conn)   ((conn)->nonblocking)
 
#define OUTBUFFER_THRESHOLD   65536
 
#define libpq_gettext(x)   (x)
 
#define libpq_ngettext(s, p, n)   ((n) == 1 ? (s) : (p))
 
#define SOCK_ERRNO   errno
 
#define SOCK_STRERROR   strerror_r
 
#define SOCK_ERRNO_SET(e)   (errno = (e))
 

Typedefs

typedef union pgresult_data PGresult_data
 
typedef struct pgresParamDesc PGresParamDesc
 
typedef struct pgresAttValue PGresAttValue
 
typedef struct pgMessageField PGMessageField
 
typedef struct PGEvent PGEvent
 
typedef struct PQEnvironmentOption PQEnvironmentOption
 
typedef struct pgParameterStatus pgParameterStatus
 
typedef struct pgLobjfuncs PGlobjfuncs
 
typedef struct pgDataValue PGdataValue
 
typedef enum pg_conn_host_type pg_conn_host_type
 
typedef struct PGcmdQueueEntry PGcmdQueueEntry
 
typedef struct pg_conn_host pg_conn_host
 

Enumerations

enum  PGAsyncStatusType {
  PGASYNC_IDLE , PGASYNC_BUSY , PGASYNC_READY , PGASYNC_READY_MORE ,
  PGASYNC_COPY_IN , PGASYNC_COPY_OUT , PGASYNC_COPY_BOTH , PGASYNC_PIPELINE_IDLE
}
 
enum  PGTargetServerType {
  SERVER_TYPE_ANY = 0 , SERVER_TYPE_READ_WRITE , SERVER_TYPE_READ_ONLY , SERVER_TYPE_PRIMARY ,
  SERVER_TYPE_STANDBY , SERVER_TYPE_PREFER_STANDBY , SERVER_TYPE_PREFER_STANDBY_PASS2
}
 
enum  PGLoadBalanceType { LOAD_BALANCE_DISABLE = 0 , LOAD_BALANCE_RANDOM }
 
enum  PGTernaryBool { PG_BOOL_UNKNOWN = 0 , PG_BOOL_YES , PG_BOOL_NO }
 
enum  pg_conn_host_type { CHT_HOST_NAME , CHT_HOST_ADDRESS , CHT_UNIX_SOCKET }
 
enum  PGQueryClass {
  PGQUERY_SIMPLE , PGQUERY_EXTENDED , PGQUERY_PREPARE , PGQUERY_DESCRIBE ,
  PGQUERY_SYNC , PGQUERY_CLOSE
}
 

Functions

void pqDropConnection (PGconn *conn, bool flushInput)
 
bool pqConnectOptions2 (PGconn *conn)
 
int pqConnectDBStart (PGconn *conn)
 
int pqConnectDBComplete (PGconn *conn)
 
PGconnpqMakeEmptyPGconn (void)
 
void pqReleaseConnHosts (PGconn *conn)
 
void pqClosePGconn (PGconn *conn)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
bool pqCopyPGconn (PGconn *srcConn, PGconn *dstConn)
 
bool pqParseIntParam (const char *value, int *result, PGconn *conn, const char *context)
 
void pqSetResultError (PGresult *res, PQExpBuffer errorMessage, int offset)
 
voidpqResultAlloc (PGresult *res, size_t nBytes, bool isBinary)
 
charpqResultStrdup (PGresult *res, const char *str)
 
void pqClearAsyncResult (PGconn *conn)
 
void pqSaveErrorResult (PGconn *conn)
 
PGresultpqPrepareAsyncResult (PGconn *conn)
 
void pqInternalNotice (const PGNoticeHooks *hooks, const char *fmt,...) pg_attribute_printf(2
 
void void pqSaveMessageField (PGresult *res, char code, const char *value)
 
int pqSaveParameterStatus (PGconn *conn, const char *name, const char *value)
 
int pqRowProcessor (PGconn *conn, const char **errmsgp)
 
void pqCommandQueueAdvance (PGconn *conn, bool isReadyForQuery, bool gotSync)
 
int PQsendQueryContinue (PGconn *conn, const char *query)
 
PGresultPQnfn (PGconn *conn, int fnid, int *result_buf, int buf_size, int *result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
charpqBuildStartupPacket3 (PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
 
void pqParseInput3 (PGconn *conn)
 
int pqGetErrorNotice3 (PGconn *conn, bool isError)
 
void pqBuildErrorMessage3 (PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
 
int pqGetNegotiateProtocolVersion3 (PGconn *conn)
 
int pqGetCopyData3 (PGconn *conn, char **buffer, int async)
 
int pqGetline3 (PGconn *conn, char *s, int maxlen)
 
int pqGetlineAsync3 (PGconn *conn, char *buffer, int bufsize)
 
int pqEndcopy3 (PGconn *conn)
 
PGresultpqFunctionCall3 (PGconn *conn, Oid fnid, int *result_buf, int buf_size, int *actual_result_len, int result_is_int, const PQArgBlock *args, int nargs)
 
int PQsendCancelRequest (PGconn *cancelConn)
 
int pqCheckOutBufferSpace (size_t bytes_needed, PGconn *conn)
 
int pqCheckInBufferSpace (size_t bytes_needed, PGconn *conn)
 
void pqParseDone (PGconn *conn, int newInStart)
 
int pqGetc (char *result, PGconn *conn)
 
int pqPutc (char c, PGconn *conn)
 
int pqGets (PQExpBuffer buf, PGconn *conn)
 
int pqGets_append (PQExpBuffer buf, PGconn *conn)
 
int pqPuts (const char *s, PGconn *conn)
 
int pqGetnchar (void *s, size_t len, PGconn *conn)
 
int pqSkipnchar (size_t len, PGconn *conn)
 
int pqPutnchar (const void *s, size_t len, PGconn *conn)
 
int pqGetInt (int *result, size_t bytes, PGconn *conn)
 
int pqPutInt (int value, size_t bytes, PGconn *conn)
 
int pqPutMsgStart (char msg_type, PGconn *conn)
 
int pqPutMsgEnd (PGconn *conn)
 
int pqReadData (PGconn *conn)
 
int pqFlush (PGconn *conn)
 
int pqWait (int forRead, int forWrite, PGconn *conn)
 
int pqWaitTimed (int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
 
int pqReadReady (PGconn *conn)
 
int pqWriteReady (PGconn *conn)
 
PostgresPollingStatusType pqsecure_open_client (PGconn *)
 
void pqsecure_close (PGconn *)
 
ssize_t pqsecure_read (PGconn *, void *ptr, size_t len)
 
ssize_t pqsecure_bytes_pending (PGconn *)
 
ssize_t pqsecure_write (PGconn *, const void *ptr, size_t len)
 
ssize_t pqsecure_raw_read (PGconn *, void *ptr, size_t len)
 
ssize_t pqsecure_raw_write (PGconn *, const void *ptr, size_t len)
 
int pq_block_sigpipe (sigset_t *osigset, bool *sigpipe_pending)
 
void pq_reset_sigpipe (sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
 
PostgresPollingStatusType pgtls_open_client (PGconn *conn)
 
void pgtls_close (PGconn *conn)
 
ssize_t pgtls_read (PGconn *conn, void *ptr, size_t len)
 
ssize_t pgtls_bytes_pending (PGconn *conn)
 
ssize_t pgtls_write (PGconn *conn, const void *ptr, size_t len)
 
charpgtls_get_peer_certificate_hash (PGconn *conn, size_t *len)
 
int pgtls_verify_peer_name_matches_certificate_guts (PGconn *conn, int *names_examined, char **first_name)
 
void pqTraceOutputMessage (PGconn *conn, const char *message, bool toServer)
 
void pqTraceOutputNoTypeByteMessage (PGconn *conn, const char *message)
 
void pqTraceOutputCharResponse (PGconn *conn, const char *responseType, char response)
 
void libpq_append_error (PQExpBuffer errorMessage, const char *fmt,...) pg_attribute_printf(2
 
void void libpq_append_conn_error (PGconn *conn, const char *fmt,...) pg_attribute_printf(2
 
void void void libpq_append_grease_info (PGconn *conn)
 

Variables

char *const pgresStatus []
 
pgthreadlock_t pg_g_threadlock
 

Macro Definition Documentation

◆ AUTH_RESPONSE_GSS

#define AUTH_RESPONSE_GSS   'G'

Definition at line 337 of file libpq-int.h.

◆ AUTH_RESPONSE_PASSWORD

#define AUTH_RESPONSE_PASSWORD   'P'

Definition at line 338 of file libpq-int.h.

◆ AUTH_RESPONSE_SASL

#define AUTH_RESPONSE_SASL   'S'

Definition at line 340 of file libpq-int.h.

◆ AUTH_RESPONSE_SASL_INITIAL

#define AUTH_RESPONSE_SASL_INITIAL   'I'

Definition at line 339 of file libpq-int.h.

◆ CMDSTATUS_LEN

#define CMDSTATUS_LEN   64 /* should match COMPLETION_TAG_BUFSIZE */

Definition at line 83 of file libpq-int.h.

◆ ENC_ERROR

#define ENC_ERROR   0

Definition at line 230 of file libpq-int.h.

◆ ENC_GSSAPI

#define ENC_GSSAPI   0x02

Definition at line 232 of file libpq-int.h.

◆ ENC_PLAINTEXT

#define ENC_PLAINTEXT   0x01

Definition at line 231 of file libpq-int.h.

◆ ENC_SSL

#define ENC_SSL   0x04

Definition at line 233 of file libpq-int.h.

◆ libpq_gettext

#define libpq_gettext (   x)    (x)

Definition at line 960 of file libpq-int.h.

◆ libpq_ngettext

#define libpq_ngettext (   s,
  p,
 
)    ((n) == 1 ? (s) : (p))

Definition at line 961 of file libpq-int.h.

◆ NULL_LEN

#define NULL_LEN   (-1) /* pg_result len for NULL value */

Definition at line 131 of file libpq-int.h.

◆ OUTBUFFER_THRESHOLD

#define OUTBUFFER_THRESHOLD   65536

Definition at line 954 of file libpq-int.h.

◆ pgHavePendingResult

#define pgHavePendingResult (   conn)     ((conn)->result != NULL || (conn)->error_result)

Definition at line 942 of file libpq-int.h.

960 : (p))
961#endif
962/*
963 * libpq code should use the above, not _(), since that would use the
964 * surrounding programs's message catalog.
965 */
966#undef _
967
968extern void libpq_append_error(PQExpBuffer errorMessage, const char *fmt, ...) pg_attribute_printf(2, 3);
971
972/*
973 * These macros are needed to let error-handling code be portable between
974 * Unix and Windows. (ugh)
975 */
976#ifdef WIN32
977#define SOCK_ERRNO (WSAGetLastError())
978#define SOCK_STRERROR winsock_strerror
979#define SOCK_ERRNO_SET(e) WSASetLastError(e)
980#else
981#define SOCK_ERRNO errno
982#define SOCK_STRERROR strerror_r
983#define SOCK_ERRNO_SET(e) (errno = (e))
984#endif
985
986#endif /* LIBPQ_INT_H */
#define pg_attribute_printf(f, a)
Definition c.h:327
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...) pg_attribute_printf(2
void void libpq_append_conn_error(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void void void libpq_append_grease_info(PGconn *conn)
Definition fe-misc.c:1576
static int fb(int x)
PGconn * conn
Definition streamutil.c:52

◆ pglock_thread

#define pglock_thread ( )    pg_g_threadlock(true)

Definition at line 748 of file libpq-int.h.

◆ pgunlock_thread

#define pgunlock_thread ( )    pg_g_threadlock(false)

Definition at line 749 of file libpq-int.h.

◆ pqClearConnErrorState

#define pqClearConnErrorState (   conn)
Value:
(resetPQExpBuffer(&(conn)->errorMessage), \
(conn)->errorReported = 0)
void resetPQExpBuffer(PQExpBuffer str)

Definition at line 933 of file libpq-int.h.

◆ pqIsnonblocking

#define pqIsnonblocking (   conn)    ((conn)->nonblocking)

Definition at line 949 of file libpq-int.h.

◆ SOCK_ERRNO

#define SOCK_ERRNO   errno

Definition at line 982 of file libpq-int.h.

◆ SOCK_ERRNO_SET

#define SOCK_ERRNO_SET (   e)    (errno = (e))

Definition at line 984 of file libpq-int.h.

◆ SOCK_STRERROR

#define SOCK_STRERROR   strerror_r

Definition at line 983 of file libpq-int.h.

Typedef Documentation

◆ pg_conn_host

◆ pg_conn_host_type

◆ PGcmdQueueEntry

◆ PGdataValue

◆ PGEvent

◆ PGlobjfuncs

◆ PGMessageField

◆ pgParameterStatus

◆ PGresAttValue

◆ PGresParamDesc

◆ PGresult_data

Definition at line 99 of file libpq-int.h.

◆ PQEnvironmentOption

Enumeration Type Documentation

◆ pg_conn_host_type

Enumerator
CHT_HOST_NAME 
CHT_HOST_ADDRESS 
CHT_UNIX_SOCKET 

Definition at line 309 of file libpq-int.h.

310{
pg_conn_host_type
Definition libpq-int.h:310
@ CHT_UNIX_SOCKET
Definition libpq-int.h:313
@ CHT_HOST_ADDRESS
Definition libpq-int.h:312
@ CHT_HOST_NAME
Definition libpq-int.h:311

◆ PGAsyncStatusType

Enumerator
PGASYNC_IDLE 
PGASYNC_BUSY 
PGASYNC_READY 
PGASYNC_READY_MORE 
PGASYNC_COPY_IN 
PGASYNC_COPY_OUT 
PGASYNC_COPY_BOTH 
PGASYNC_PIPELINE_IDLE 

Definition at line 214 of file libpq-int.h.

215{
216 PGASYNC_IDLE, /* nothing's happening, dude */
217 PGASYNC_BUSY, /* query in progress */
218 PGASYNC_READY, /* query done, waiting for client to fetch
219 * result */
220 PGASYNC_READY_MORE, /* query done, waiting for client to fetch
221 * result, more results expected from this
222 * query */
223 PGASYNC_COPY_IN, /* Copy In data transfer in progress */
224 PGASYNC_COPY_OUT, /* Copy Out data transfer in progress */
225 PGASYNC_COPY_BOTH, /* Copy In/Out data transfer in progress */
226 PGASYNC_PIPELINE_IDLE, /* "Idle" between commands in pipeline mode */
PGAsyncStatusType
Definition libpq-int.h:215
@ PGASYNC_COPY_OUT
Definition libpq-int.h:224
@ PGASYNC_READY_MORE
Definition libpq-int.h:220
@ PGASYNC_READY
Definition libpq-int.h:218
@ PGASYNC_COPY_BOTH
Definition libpq-int.h:225
@ PGASYNC_IDLE
Definition libpq-int.h:216
@ PGASYNC_COPY_IN
Definition libpq-int.h:223
@ PGASYNC_BUSY
Definition libpq-int.h:217
@ PGASYNC_PIPELINE_IDLE
Definition libpq-int.h:226

◆ PGLoadBalanceType

Enumerator
LOAD_BALANCE_DISABLE 
LOAD_BALANCE_RANDOM 

Definition at line 248 of file libpq-int.h.

249{
250 LOAD_BALANCE_DISABLE = 0, /* Use the existing host order (default) */
251 LOAD_BALANCE_RANDOM, /* Randomly shuffle the hosts */
PGLoadBalanceType
Definition libpq-int.h:249
@ LOAD_BALANCE_DISABLE
Definition libpq-int.h:250
@ LOAD_BALANCE_RANDOM
Definition libpq-int.h:251

◆ PGQueryClass

Enumerator
PGQUERY_SIMPLE 
PGQUERY_EXTENDED 
PGQUERY_PREPARE 
PGQUERY_DESCRIBE 
PGQUERY_SYNC 
PGQUERY_CLOSE 

Definition at line 320 of file libpq-int.h.

321{
322 PGQUERY_SIMPLE, /* simple Query protocol (PQexec) */
323 PGQUERY_EXTENDED, /* full Extended protocol (PQexecParams) */
324 PGQUERY_PREPARE, /* Parse only (PQprepare) */
325 PGQUERY_DESCRIBE, /* Describe Statement or Portal */
326 PGQUERY_SYNC, /* Sync (at end of a pipeline) */
327 PGQUERY_CLOSE /* Close Statement or Portal */
PGQueryClass
Definition libpq-int.h:321
@ PGQUERY_SIMPLE
Definition libpq-int.h:322
@ PGQUERY_SYNC
Definition libpq-int.h:326
@ PGQUERY_EXTENDED
Definition libpq-int.h:323
@ PGQUERY_DESCRIBE
Definition libpq-int.h:325
@ PGQUERY_CLOSE
Definition libpq-int.h:327
@ PGQUERY_PREPARE
Definition libpq-int.h:324

◆ PGTargetServerType

Enumerator
SERVER_TYPE_ANY 
SERVER_TYPE_READ_WRITE 
SERVER_TYPE_READ_ONLY 
SERVER_TYPE_PRIMARY 
SERVER_TYPE_STANDBY 
SERVER_TYPE_PREFER_STANDBY 
SERVER_TYPE_PREFER_STANDBY_PASS2 

Definition at line 236 of file libpq-int.h.

237{
238 SERVER_TYPE_ANY = 0, /* Any server (default) */
239 SERVER_TYPE_READ_WRITE, /* Read-write server */
240 SERVER_TYPE_READ_ONLY, /* Read-only server */
241 SERVER_TYPE_PRIMARY, /* Primary server */
242 SERVER_TYPE_STANDBY, /* Standby server */
243 SERVER_TYPE_PREFER_STANDBY, /* Prefer standby server */
244 SERVER_TYPE_PREFER_STANDBY_PASS2 /* second pass - behaves same as ANY */
PGTargetServerType
Definition libpq-int.h:237
@ SERVER_TYPE_STANDBY
Definition libpq-int.h:242
@ SERVER_TYPE_PRIMARY
Definition libpq-int.h:241
@ SERVER_TYPE_ANY
Definition libpq-int.h:238
@ SERVER_TYPE_READ_WRITE
Definition libpq-int.h:239
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition libpq-int.h:244
@ SERVER_TYPE_PREFER_STANDBY
Definition libpq-int.h:243
@ SERVER_TYPE_READ_ONLY
Definition libpq-int.h:240

◆ PGTernaryBool

Enumerator
PG_BOOL_UNKNOWN 
PG_BOOL_YES 
PG_BOOL_NO 

Definition at line 255 of file libpq-int.h.

256{
257 PG_BOOL_UNKNOWN = 0, /* Currently unknown */
258 PG_BOOL_YES, /* Yes (true) */
259 PG_BOOL_NO /* No (false) */
PGTernaryBool
Definition libpq-int.h:256
@ PG_BOOL_YES
Definition libpq-int.h:258
@ PG_BOOL_NO
Definition libpq-int.h:259
@ PG_BOOL_UNKNOWN
Definition libpq-int.h:257

Function Documentation

◆ libpq_append_conn_error()

void void libpq_append_conn_error ( PGconn conn,
const char fmt,
  ... 
)
extern

◆ libpq_append_error()

void libpq_append_error ( PQExpBuffer  errorMessage,
const char fmt,
  ... 
)
extern

◆ libpq_append_grease_info()

void void void libpq_append_grease_info ( PGconn conn)
extern

Definition at line 1576 of file fe-misc.c.

1577{
1578 /* translator: %s is a URL */
1580 "\tThis indicates a bug in either the server being contacted\n"
1581 "\tor a proxy handling the connection. Please consider\n"
1582 "\treporting this to the maintainers of that software.\n"
1583 "\tFor more information, including instructions on how to\n"
1584 "\twork around this issue for now, visit\n"
1585 "\t\t%s",
1586 "https://wiki.postgresql.org/wiki/Grease");
1587}
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition fe-misc.c:1548

References conn, and libpq_append_conn_error().

Referenced by PQconnectPoll(), and pqGetNegotiateProtocolVersion3().

◆ pgtls_bytes_pending()

ssize_t pgtls_bytes_pending ( PGconn conn)
extern

Definition at line 235 of file fe-secure-openssl.c.

236{
237 int pending;
238
239 /*
240 * OpenSSL readahead is documented to break SSL_pending(). Plus, we can't
241 * afford to have OpenSSL take bytes off the socket without processing
242 * them; that breaks the postconditions for pqsecure_drain_pending().
243 */
245
246 pending = SSL_pending(conn->ssl);
247 if (pending < 0)
248 {
249 /* shouldn't be possible */
250 Assert(false);
251 libpq_append_conn_error(conn, "OpenSSL reports negative bytes pending");
252 return -1;
253 }
254 else if (pending == INT_MAX)
255 {
256 /*
257 * If we ever found a legitimate way to hit this, we'd need to loop
258 * around in the caller to call pgtls_bytes_pending() again. Throw an
259 * error rather than complicate the code in that way, because
260 * SSL_read() should be bounded to the size of a single TLS record,
261 * and conn->inBuffer can't currently go past INT_MAX in size anyway.
262 */
263 libpq_append_conn_error(conn, "OpenSSL reports INT_MAX bytes pending");
264 return -1;
265 }
266
267 return (ssize_t) pending;
268}
#define Assert(condition)
Definition c.h:1002

References Assert, conn, fb(), and libpq_append_conn_error().

Referenced by pqsecure_bytes_pending().

◆ pgtls_close()

void pgtls_close ( PGconn conn)
extern

Definition at line 1534 of file fe-secure-openssl.c.

1535{
1536 if (conn->ssl_in_use)
1537 {
1538 if (conn->ssl)
1539 {
1540 /*
1541 * We can't destroy everything SSL-related here due to the
1542 * possible later calls to OpenSSL routines which may need our
1543 * thread callbacks, so set a flag here and check at the end.
1544 */
1545
1546 SSL_shutdown(conn->ssl);
1547 SSL_free(conn->ssl);
1548 conn->ssl = NULL;
1549 conn->ssl_in_use = false;
1550 conn->ssl_handshake_started = false;
1551 }
1552
1553 if (conn->peer)
1554 {
1555 X509_free(conn->peer);
1556 conn->peer = NULL;
1557 }
1558
1559#ifdef USE_SSL_ENGINE
1560 if (conn->engine)
1561 {
1562 ENGINE_finish(conn->engine);
1563 ENGINE_free(conn->engine);
1564 conn->engine = NULL;
1565 }
1566#endif
1567 }
1568}
bool ssl_handshake_started
Definition libpq-int.h:624
bool ssl_in_use
Definition libpq-int.h:623

References conn, fb(), pg_conn::ssl_handshake_started, and pg_conn::ssl_in_use.

Referenced by open_client_SSL(), pgtls_open_client(), and pqsecure_close().

◆ pgtls_get_peer_certificate_hash()

char * pgtls_get_peer_certificate_hash ( PGconn conn,
size_t len 
)
extern

Definition at line 371 of file fe-secure-openssl.c.

372{
374 const EVP_MD *algo_type;
375 unsigned char hash[EVP_MAX_MD_SIZE]; /* size for SHA-512 */
376 unsigned int hash_size;
377 int algo_nid;
378 char *cert_hash;
379
380 *len = 0;
381
382 if (!conn->peer)
383 return NULL;
384
385 peer_cert = conn->peer;
386
387 /*
388 * Get the signature algorithm of the certificate to determine the hash
389 * algorithm to use for the result. Prefer X509_get_signature_info(),
390 * introduced in OpenSSL 1.1.1, which can handle RSA-PSS signatures.
391 */
392#if HAVE_X509_GET_SIGNATURE_INFO
394#else
396 &algo_nid, NULL))
397#endif
398 {
399 libpq_append_conn_error(conn, "could not determine server certificate signature algorithm");
400 return NULL;
401 }
402
403 /*
404 * The TLS server's certificate bytes need to be hashed with SHA-256 if
405 * its signature algorithm is MD5 or SHA-1 as per RFC 5929
406 * (https://tools.ietf.org/html/rfc5929#section-4.1). If something else
407 * is used, the same hash as the signature algorithm is used.
408 */
409 switch (algo_nid)
410 {
411 case NID_md5:
412 case NID_sha1:
414 break;
415 default:
417 if (algo_type == NULL)
418 {
419 libpq_append_conn_error(conn, "could not find digest for NID %s",
421 return NULL;
422 }
423 break;
424 }
425
427 {
428 libpq_append_conn_error(conn, "could not generate peer certificate hash");
429 return NULL;
430 }
431
432 /* save result */
434 if (cert_hash == NULL)
435 {
436 libpq_append_conn_error(conn, "out of memory");
437 return NULL;
438 }
440 *len = hash_size;
441
442 return cert_hash;
443}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
const void size_t len
static unsigned hash(unsigned *uv, int n)
Definition rege_dfa.c:724
#define malloc(a)

References conn, fb(), hash(), len, libpq_append_conn_error(), malloc, and memcpy().

Referenced by build_client_final_message().

◆ pgtls_open_client()

PostgresPollingStatusType pgtls_open_client ( PGconn conn)
extern

Definition at line 97 of file fe-secure-openssl.c.

98{
99 /* First time through? */
100 if (conn->ssl == NULL)
101 {
102 /*
103 * Create a connection-specific SSL object, and load client
104 * certificate, private key, and trusted CA certs.
105 */
106 if (initialize_SSL(conn) != 0)
107 {
108 /* initialize_SSL already put a message in conn->errorMessage */
111 }
112 }
113
114 /* Begin or continue the actual handshake */
115 return open_client_SSL(conn);
116}
static int initialize_SSL(PGconn *conn)
static PostgresPollingStatusType open_client_SSL(PGconn *conn)
void pgtls_close(PGconn *conn)
@ PGRES_POLLING_FAILED
Definition libpq-fe.h:121

References conn, fb(), initialize_SSL(), open_client_SSL(), PGRES_POLLING_FAILED, and pgtls_close().

Referenced by pqsecure_open_client().

◆ pgtls_read()

ssize_t pgtls_read ( PGconn conn,
void ptr,
size_t  len 
)
extern

Definition at line 119 of file fe-secure-openssl.c.

120{
121 ssize_t n;
122 int result_errno = 0;
124 int err;
125 unsigned long ecode;
126
127rloop:
128
129 /*
130 * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
131 * queue. In general, the current thread's error queue must be empty
132 * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
133 * not work reliably. Since the possibility exists that other OpenSSL
134 * clients running in the same thread but not under our control will fail
135 * to call ERR_get_error() themselves (after their own I/O operations),
136 * pro-actively clear the per-thread error queue now.
137 */
140 n = SSL_read(conn->ssl, ptr, len);
141 err = SSL_get_error(conn->ssl, n);
142
143 /*
144 * Other clients of OpenSSL may fail to call ERR_get_error(), but we
145 * always do, so as to not cause problems for OpenSSL clients that don't
146 * call ERR_clear_error() defensively. Be sure that this happens by
147 * calling now. SSL_get_error() relies on the OpenSSL per-thread error
148 * queue being intact, so this is the earliest possible point
149 * ERR_get_error() may be called.
150 */
151 ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
152 switch (err)
153 {
154 case SSL_ERROR_NONE:
155 if (n < 0)
156 {
157 /* Not supposed to happen, so we don't translate the msg */
159 "SSL_read failed but did not provide error information\n");
160 /* assume the connection is broken */
162 }
163 break;
165 n = 0;
166 break;
168
169 /*
170 * Returning 0 here would cause caller to wait for read-ready,
171 * which is not correct since what SSL wants is wait for
172 * write-ready. The former could get us stuck in an infinite
173 * wait, so don't risk it; busy-loop instead.
174 */
175 goto rloop;
177 if (n < 0 && SOCK_ERRNO != 0)
178 {
180 if (result_errno == EPIPE ||
182 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
183 "\tThis probably means the server terminated abnormally\n"
184 "\tbefore or while processing the request.");
185 else
186 libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
188 sebuf, sizeof(sebuf)));
189 }
190 else
191 {
192 libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
193 /* assume the connection is broken */
195 n = -1;
196 }
197 break;
198 case SSL_ERROR_SSL:
199 {
200 char *errm = SSLerrmessage(ecode);
201
202 libpq_append_conn_error(conn, "SSL error: %s", errm);
204 /* assume the connection is broken */
206 n = -1;
207 break;
208 }
210
211 /*
212 * Per OpenSSL documentation, this error code is only returned for
213 * a clean connection closure, so we should not report it as a
214 * server crash.
215 */
216 libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
218 n = -1;
219 break;
220 default:
221 libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
222 /* assume the connection is broken */
224 n = -1;
225 break;
226 }
227
228 /* ensure we return the intended errno to caller */
230
231 return n;
232}
void err(int eval, const char *fmt,...)
Definition err.c:43
static void SSLerrfree(char *buf)
static char * SSLerrmessage(unsigned long ecode)
#define SOCK_STRERROR
Definition libpq-int.h:983
#define SOCK_ERRNO
Definition oauth-utils.c:86
#define SOCK_ERRNO_SET(e)
Definition oauth-utils.c:87
#define PG_STRERROR_R_BUFLEN
Definition port.h:279
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
PQExpBufferData errorMessage
Definition libpq-int.h:686
#define ECONNRESET
Definition win32_port.h:388

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, fb(), len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_read().

◆ pgtls_verify_peer_name_matches_certificate_guts()

int pgtls_verify_peer_name_matches_certificate_guts ( PGconn conn,
int names_examined,
char **  first_name 
)
extern

Definition at line 576 of file fe-secure-openssl.c.

579{
581 int i;
582 int rc = 0;
583 char *host = conn->connhost[conn->whichhost].host;
584 int host_type;
585 bool check_cn = true;
586
587 Assert(host && host[0]); /* should be guaranteed by caller */
588
589 /*
590 * We try to match the NSS behavior here, which is a slight departure from
591 * the spec but seems to make more intuitive sense:
592 *
593 * If connhost contains a DNS name, and the certificate's SANs contain any
594 * dNSName entries, then we'll ignore the Subject Common Name entirely;
595 * otherwise, we fall back to checking the CN. (This behavior matches the
596 * RFC.)
597 *
598 * If connhost contains an IP address, and the SANs contain iPAddress
599 * entries, we again ignore the CN. Otherwise, we allow the CN to match,
600 * EVEN IF there is a dNSName in the SANs. (RFC 6125 prohibits this: "A
601 * client MUST NOT seek a match for a reference identifier of CN-ID if the
602 * presented identifiers include a DNS-ID, SRV-ID, URI-ID, or any
603 * application-specific identifier types supported by the client.")
604 *
605 * NOTE: Prior versions of libpq did not consider iPAddress entries at
606 * all, so this new behavior might break a certificate that has different
607 * IP addresses in the Subject CN and the SANs.
608 */
609 if (is_ip_address(host))
611 else
613
614 /*
615 * First, get the Subject Alternative Names (SANs) from the certificate,
616 * and compare them against the originally given hostname.
617 */
620
621 if (peer_san)
622 {
624
625 for (i = 0; i < san_len; i++)
626 {
628 char *alt_name = NULL;
629
630 if (name->type == host_type)
631 {
632 /*
633 * This SAN is of the same type (IP or DNS) as our host name,
634 * so don't allow a fallback check of the CN.
635 */
636 check_cn = false;
637 }
638
639 if (name->type == GEN_DNS)
640 {
641 (*names_examined)++;
643 name->d.dNSName,
644 &alt_name);
645 }
646 else if (name->type == GEN_IPADD)
647 {
648 (*names_examined)++;
650 name->d.iPAddress,
651 &alt_name);
652 }
653
654 if (alt_name)
655 {
656 if (!*first_name)
658 else
659 free(alt_name);
660 }
661
662 if (rc != 0)
663 {
664 /*
665 * Either we hit an error or a match, and either way we should
666 * not fall back to the CN.
667 */
668 check_cn = false;
669 break;
670 }
671 }
673 }
674
675 /*
676 * If there is no subjectAltName extension of the matching type, check the
677 * Common Name.
678 *
679 * (Per RFC 2818 and RFC 6125, if the subjectAltName extension of type
680 * dNSName is present, the CN must be ignored. We break this rule if host
681 * is an IP address; see the comment above.)
682 */
683 if (check_cn)
684 {
685 const X509_NAME *subject_name;
686
688 if (subject_name != NULL)
689 {
690 int cn_index;
691
693 NID_commonName, -1);
694 if (cn_index >= 0)
695 {
696 char *common_name = NULL;
697
698 (*names_examined)++;
701 &common_name);
702
703 if (common_name)
704 {
705 if (!*first_name)
707 else
709 }
710 }
711 }
712 }
713
714 return rc;
715}
#define unconstify(underlying_type, expr)
Definition c.h:1370
static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, const ASN1_STRING *name_entry, char **store_name)
static int openssl_verify_peer_name_matches_certificate_ip(PGconn *conn, ASN1_OCTET_STRING *addr_entry, char **store_name)
static bool is_ip_address(const char *host)
int i
Definition isn.c:77
#define free(a)
char * host
Definition libpq-int.h:360
int whichhost
Definition libpq-int.h:484
pg_conn_host * connhost
Definition libpq-int.h:485
const char * name

References Assert, conn, pg_conn::connhost, fb(), free, pg_conn_host::host, i, is_ip_address(), name, openssl_verify_peer_name_matches_certificate_ip(), openssl_verify_peer_name_matches_certificate_name(), unconstify, and pg_conn::whichhost.

Referenced by pq_verify_peer_name_matches_certificate().

◆ pgtls_write()

ssize_t pgtls_write ( PGconn conn,
const void ptr,
size_t  len 
)
extern

Definition at line 271 of file fe-secure-openssl.c.

272{
273 ssize_t n;
274 int result_errno = 0;
276 int err;
277 unsigned long ecode;
278
281 n = SSL_write(conn->ssl, ptr, len);
282 err = SSL_get_error(conn->ssl, n);
283 ecode = (err != SSL_ERROR_NONE || n < 0) ? ERR_get_error() : 0;
284 switch (err)
285 {
286 case SSL_ERROR_NONE:
287 if (n < 0)
288 {
289 /* Not supposed to happen, so we don't translate the msg */
291 "SSL_write failed but did not provide error information\n");
292 /* assume the connection is broken */
294 }
295 break;
297
298 /*
299 * Returning 0 here causes caller to wait for write-ready, which
300 * is not really the right thing, but it's the best we can do.
301 */
302 n = 0;
303 break;
305 n = 0;
306 break;
308
309 /*
310 * If errno is still zero then assume it's a read EOF situation,
311 * and report EOF. (This seems possible because SSL_write can
312 * also do reads.)
313 */
314 if (n < 0 && SOCK_ERRNO != 0)
315 {
318 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
319 "\tThis probably means the server terminated abnormally\n"
320 "\tbefore or while processing the request.");
321 else
322 libpq_append_conn_error(conn, "SSL SYSCALL error: %s",
324 sebuf, sizeof(sebuf)));
325 }
326 else
327 {
328 libpq_append_conn_error(conn, "SSL SYSCALL error: EOF detected");
329 /* assume the connection is broken */
331 n = -1;
332 }
333 break;
334 case SSL_ERROR_SSL:
335 {
336 char *errm = SSLerrmessage(ecode);
337
338 libpq_append_conn_error(conn, "SSL error: %s", errm);
340 /* assume the connection is broken */
342 n = -1;
343 break;
344 }
346
347 /*
348 * Per OpenSSL documentation, this error code is only returned for
349 * a clean connection closure, so we should not report it as a
350 * server crash.
351 */
352 libpq_append_conn_error(conn, "SSL connection has been closed unexpectedly");
354 n = -1;
355 break;
356 default:
357 libpq_append_conn_error(conn, "unrecognized SSL error code: %d", err);
358 /* assume the connection is broken */
360 n = -1;
361 break;
362 }
363
364 /* ensure we return the intended errno to caller */
366
367 return n;
368}

References appendPQExpBufferStr(), conn, ECONNRESET, err(), pg_conn::errorMessage, fb(), len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, SSLerrfree(), and SSLerrmessage().

Referenced by pqsecure_write().

◆ pq_block_sigpipe()

int pq_block_sigpipe ( sigset_t osigset,
bool sigpipe_pending 
)
extern

Definition at line 94 of file oauth-utils.c.

95{
98
101
102 /* Block SIGPIPE and save previous mask for later reset */
104 if (SOCK_ERRNO)
105 return -1;
106
107 /* We can have a pending SIGPIPE only if it was blocked before */
109 {
110 /* Is there a pending SIGPIPE? */
111 if (sigpending(&sigset) != 0)
112 return -1;
113
115 *sigpipe_pending = true;
116 else
117 *sigpipe_pending = false;
118 }
119 else
120 *sigpipe_pending = false;
121
122 return 0;
123}
#define SIGPIPE
Definition win32_port.h:163

References fb(), SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by pg_fe_run_oauth_flow(), and PQprint().

◆ pq_reset_sigpipe()

void pq_reset_sigpipe ( sigset_t osigset,
bool  sigpipe_pending,
bool  got_epipe 
)
extern

Definition at line 130 of file oauth-utils.c.

131{
133 int signo;
135
136 /* Clear SIGPIPE only if none was pending */
137 if (got_epipe && !sigpipe_pending)
138 {
139 if (sigpending(&sigset) == 0 &&
141 {
143
146
148 }
149 }
150
151 /* Restore saved block mask */
153
155}

References fb(), SIGPIPE, SOCK_ERRNO, and SOCK_ERRNO_SET.

Referenced by pg_fe_run_oauth_flow(), and PQprint().

◆ pqBuildErrorMessage3()

void pqBuildErrorMessage3 ( PQExpBuffer  msg,
const PGresult res,
PGVerbosity  verbosity,
PGContextVisibility  show_context 
)
extern

Definition at line 1031 of file fe-protocol3.c.

1033{
1034 const char *val;
1035 const char *querytext = NULL;
1036 int querypos = 0;
1037
1038 /* If we couldn't allocate a PGresult, just say "out of memory" */
1039 if (res == NULL)
1040 {
1041 appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
1042 return;
1043 }
1044
1045 /*
1046 * If we don't have any broken-down fields, just return the base message.
1047 * This mainly applies if we're given a libpq-generated error result.
1048 */
1049 if (res->errFields == NULL)
1050 {
1051 if (res->errMsg && res->errMsg[0])
1052 appendPQExpBufferStr(msg, res->errMsg);
1053 else
1054 appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
1055 return;
1056 }
1057
1058 /* Else build error message from relevant fields */
1060 if (val)
1061 appendPQExpBuffer(msg, "%s: ", val);
1062
1063 if (verbosity == PQERRORS_SQLSTATE)
1064 {
1065 /*
1066 * If we have a SQLSTATE, print that and nothing else. If not (which
1067 * shouldn't happen for server-generated errors, but might possibly
1068 * happen for libpq-generated ones), fall back to TERSE format, as
1069 * that seems better than printing nothing at all.
1070 */
1072 if (val)
1073 {
1074 appendPQExpBuffer(msg, "%s\n", val);
1075 return;
1076 }
1077 verbosity = PQERRORS_TERSE;
1078 }
1079
1080 if (verbosity == PQERRORS_VERBOSE)
1081 {
1083 if (val)
1084 appendPQExpBuffer(msg, "%s: ", val);
1085 }
1087 if (val)
1090 if (val)
1091 {
1092 if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1093 {
1094 /* emit position as a syntax cursor display */
1095 querytext = res->errQuery;
1096 querypos = atoi(val);
1097 }
1098 else
1099 {
1100 /* emit position as text addition to primary message */
1101 /* translator: %s represents a digit string */
1102 appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1103 val);
1104 }
1105 }
1106 else
1107 {
1109 if (val)
1110 {
1112 if (verbosity != PQERRORS_TERSE && querytext != NULL)
1113 {
1114 /* emit position as a syntax cursor display */
1115 querypos = atoi(val);
1116 }
1117 else
1118 {
1119 /* emit position as text addition to primary message */
1120 /* translator: %s represents a digit string */
1121 appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1122 val);
1123 }
1124 }
1125 }
1126 appendPQExpBufferChar(msg, '\n');
1127 if (verbosity != PQERRORS_TERSE)
1128 {
1129 if (querytext && querypos > 0)
1131 res->client_encoding);
1133 if (val)
1134 appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1136 if (val)
1137 appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1139 if (val)
1140 appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1141 if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1142 (show_context == PQSHOW_CONTEXT_ERRORS &&
1144 {
1146 if (val)
1147 appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1148 val);
1149 }
1150 }
1151 if (verbosity == PQERRORS_VERBOSE)
1152 {
1154 if (val)
1156 libpq_gettext("SCHEMA NAME: %s\n"), val);
1158 if (val)
1160 libpq_gettext("TABLE NAME: %s\n"), val);
1162 if (val)
1164 libpq_gettext("COLUMN NAME: %s\n"), val);
1166 if (val)
1168 libpq_gettext("DATATYPE NAME: %s\n"), val);
1170 if (val)
1172 libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1173 }
1174 if (verbosity == PQERRORS_VERBOSE)
1175 {
1176 const char *valf;
1177 const char *vall;
1178
1182 if (val || valf || vall)
1183 {
1184 appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1185 if (val)
1186 appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1187 if (valf && vall) /* unlikely we'd have just one */
1188 appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1189 valf, vall);
1190 appendPQExpBufferChar(msg, '\n');
1191 }
1192 }
1193}
static void reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
long val
Definition informix.c:689
#define PQresultErrorField
@ PGRES_FATAL_ERROR
Definition libpq-fe.h:142
@ PQSHOW_CONTEXT_ALWAYS
Definition libpq-fe.h:172
@ PQSHOW_CONTEXT_ERRORS
Definition libpq-fe.h:171
@ PQERRORS_VERBOSE
Definition libpq-fe.h:164
@ PQERRORS_TERSE
Definition libpq-fe.h:162
@ PQERRORS_SQLSTATE
Definition libpq-fe.h:165
#define libpq_gettext(x)
Definition oauth-utils.h:44
#define PG_DIAG_INTERNAL_QUERY
#define PG_DIAG_SCHEMA_NAME
#define PG_DIAG_CONSTRAINT_NAME
#define PG_DIAG_DATATYPE_NAME
#define PG_DIAG_SOURCE_LINE
#define PG_DIAG_STATEMENT_POSITION
#define PG_DIAG_SOURCE_FILE
#define PG_DIAG_MESSAGE_HINT
#define PG_DIAG_SQLSTATE
#define PG_DIAG_TABLE_NAME
#define PG_DIAG_MESSAGE_PRIMARY
#define PG_DIAG_COLUMN_NAME
#define PG_DIAG_MESSAGE_DETAIL
#define PG_DIAG_CONTEXT
#define PG_DIAG_SEVERITY
#define PG_DIAG_SOURCE_FUNCTION
#define PG_DIAG_INTERNAL_POSITION
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
char * errMsg
Definition libpq-int.h:194
PGMessageField * errFields
Definition libpq-int.h:195
ExecStatusType resultStatus
Definition libpq-int.h:175
char * errQuery
Definition libpq-int.h:196
int client_encoding
Definition libpq-int.h:187

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), pg_result::client_encoding, pg_result::errFields, pg_result::errMsg, pg_result::errQuery, fb(), libpq_gettext, PG_DIAG_COLUMN_NAME, PG_DIAG_CONSTRAINT_NAME, PG_DIAG_CONTEXT, PG_DIAG_DATATYPE_NAME, PG_DIAG_INTERNAL_POSITION, PG_DIAG_INTERNAL_QUERY, PG_DIAG_MESSAGE_DETAIL, PG_DIAG_MESSAGE_HINT, PG_DIAG_MESSAGE_PRIMARY, PG_DIAG_SCHEMA_NAME, PG_DIAG_SEVERITY, PG_DIAG_SOURCE_FILE, PG_DIAG_SOURCE_FUNCTION, PG_DIAG_SOURCE_LINE, PG_DIAG_SQLSTATE, PG_DIAG_STATEMENT_POSITION, PG_DIAG_TABLE_NAME, PGRES_FATAL_ERROR, PQERRORS_SQLSTATE, PQERRORS_TERSE, PQERRORS_VERBOSE, PQresultErrorField, PQSHOW_CONTEXT_ALWAYS, PQSHOW_CONTEXT_ERRORS, reportErrorPosition(), pg_result::resultStatus, and val.

Referenced by pqGetErrorNotice3(), and PQresultVerboseErrorMessage().

◆ pqBuildStartupPacket3()

char * pqBuildStartupPacket3 ( PGconn conn,
int packetlen,
const PQEnvironmentOption options 
)
extern

Definition at line 2449 of file fe-protocol3.c.

2451{
2452 char *startpacket;
2453 size_t len;
2454
2456 if (len == 0 || len > INT_MAX)
2457 return NULL;
2458
2459 *packetlen = len;
2460 startpacket = (char *) malloc(*packetlen);
2461 if (!startpacket)
2462 return NULL;
2463
2465 Assert(*packetlen == len);
2466
2467 return startpacket;
2468}
static size_t build_startup_packet(const PGconn *conn, char *packet, const PQEnvironmentOption *options)

References Assert, build_startup_packet(), conn, fb(), len, and malloc.

Referenced by PQconnectPoll().

◆ pqCheckInBufferSpace()

int pqCheckInBufferSpace ( size_t  bytes_needed,
PGconn conn 
)
extern

Definition at line 353 of file fe-misc.c.

354{
355 int newsize = conn->inBufSize;
356 char *newbuf;
357
358 /* Quick exit if we have enough space */
359 if (bytes_needed <= (size_t) newsize)
360 return 0;
361
362 /*
363 * Before concluding that we need to enlarge the buffer, left-justify
364 * whatever is in it and recheck. The caller's value of bytes_needed
365 * includes any data to the left of inStart, but we can delete that in
366 * preference to enlarging the buffer. It's slightly ugly to have this
367 * function do this, but it's better than making callers worry about it.
368 */
370
371 if (conn->inStart < conn->inEnd)
372 {
373 if (conn->inStart > 0)
374 {
376 conn->inEnd - conn->inStart);
377 conn->inEnd -= conn->inStart;
379 conn->inStart = 0;
380 }
381 }
382 else
383 {
384 /* buffer is logically empty, reset it */
385 conn->inStart = conn->inCursor = conn->inEnd = 0;
386 }
387
388 /* Recheck whether we have enough space */
389 if (bytes_needed <= (size_t) newsize)
390 return 0;
391
392 /*
393 * If we need to enlarge the buffer, we first try to double it in size; if
394 * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
395 * the malloc pool by repeated small enlargements.
396 *
397 * Note: tests for newsize > 0 are to catch integer overflow.
398 */
399 do
400 {
401 newsize *= 2;
402 } while (newsize > 0 && bytes_needed > (size_t) newsize);
403
404 if (newsize > 0 && bytes_needed <= (size_t) newsize)
405 {
407 if (newbuf)
408 {
409 /* realloc succeeded */
412 return 0;
413 }
414 }
415
417 do
418 {
419 newsize += 8192;
420 } while (newsize > 0 && bytes_needed > (size_t) newsize);
421
422 if (newsize > 0 && bytes_needed <= (size_t) newsize)
423 {
425 if (newbuf)
426 {
427 /* realloc succeeded */
430 return 0;
431 }
432 }
433
434 /* realloc failed. Probably out of memory */
436 "cannot allocate memory for input buffer\n");
437 return EOF;
438}
#define realloc(a, b)
char * inBuffer
Definition libpq-int.h:579
int inCursor
Definition libpq-int.h:582
int inEnd
Definition libpq-int.h:583
int inBufSize
Definition libpq-int.h:580
int inStart
Definition libpq-int.h:581

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, fb(), pg_conn::inBuffer, pg_conn::inBufSize, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, and realloc.

Referenced by getCopyDataMessage(), PQconnectPoll(), pqDrainPending(), pqFunctionCall3(), pqParseInput3(), and pqReadData_internal().

◆ pqCheckOutBufferSpace()

int pqCheckOutBufferSpace ( size_t  bytes_needed,
PGconn conn 
)
extern

Definition at line 289 of file fe-misc.c.

290{
291 int newsize = conn->outBufSize;
292 char *newbuf;
293
294 /* Quick exit if we have enough space */
295 if (bytes_needed <= (size_t) newsize)
296 return 0;
297
298 /*
299 * If we need to enlarge the buffer, we first try to double it in size; if
300 * that doesn't work, enlarge in multiples of 8K. This avoids thrashing
301 * the malloc pool by repeated small enlargements.
302 *
303 * Note: tests for newsize > 0 are to catch integer overflow.
304 */
305 do
306 {
307 newsize *= 2;
308 } while (newsize > 0 && bytes_needed > (size_t) newsize);
309
310 if (newsize > 0 && bytes_needed <= (size_t) newsize)
311 {
313 if (newbuf)
314 {
315 /* realloc succeeded */
318 return 0;
319 }
320 }
321
323 do
324 {
325 newsize += 8192;
326 } while (newsize > 0 && bytes_needed > (size_t) newsize);
327
328 if (newsize > 0 && bytes_needed <= (size_t) newsize)
329 {
331 if (newbuf)
332 {
333 /* realloc succeeded */
336 return 0;
337 }
338 }
339
340 /* realloc failed. Probably out of memory */
342 "cannot allocate memory for output buffer\n");
343 return EOF;
344}
int outBufSize
Definition libpq-int.h:587
char * outBuffer
Definition libpq-int.h:586

References appendPQExpBufferStr(), conn, pg_conn::errorMessage, fb(), pg_conn::outBuffer, pg_conn::outBufSize, and realloc.

Referenced by PQputCopyData(), pqPutMsgBytes(), and pqPutMsgStart().

◆ pqClearAsyncResult()

void pqClearAsyncResult ( PGconn conn)
extern

◆ pqClosePGconn()

void pqClosePGconn ( PGconn conn)
extern

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

5313{
5314 /*
5315 * If possible, send Terminate message to close the connection politely.
5316 */
5318
5319 /*
5320 * Must reset the blocking status so a possible reconnect will work.
5321 *
5322 * Don't call PQsetnonblocking() because it will fail if it's unable to
5323 * flush the connection.
5324 */
5325 conn->nonblocking = false;
5326
5327 /*
5328 * Close the connection, reset all transient state, flush I/O buffers.
5329 * Note that this includes clearing conn's error state; we're no longer
5330 * interested in any failures associated with the old connection, and we
5331 * want a clean slate for any new connection attempt.
5332 */
5333 pqDropConnection(conn, true);
5334 conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
5339 pqClearAsyncResult(conn); /* deallocate result */
5341
5342 /*
5343 * Release addrinfo, but since cancel requests never change their addrinfo
5344 * we don't do that. Otherwise we would have to rebuild it during a
5345 * PQcancelReset.
5346 */
5347 if (!conn->cancelRequest)
5349
5350 /* Reset all state obtained from server, too */
5352}
void pqClearOAuthToken(PGconn *conn)
void pqDropConnection(PGconn *conn, bool flushInput)
Definition fe-connect.c:537
static void sendTerminateConn(PGconn *conn)
static void release_conn_addrinfo(PGconn *conn)
static void pqDropServerData(PGconn *conn)
Definition fe-connect.c:663
void pqClearAsyncResult(PGconn *conn)
Definition fe-exec.c:785
@ CONNECTION_BAD
Definition libpq-fe.h:91
@ PQTRANS_IDLE
Definition libpq-fe.h:153
@ PQ_PIPELINE_OFF
Definition libpq-fe.h:193
#define pqClearConnErrorState(conn)
Definition libpq-int.h:933
PGTransactionStatusType xactStatus
Definition libpq-int.h:467
bool cancelRequest
Definition libpq-int.h:436
bool nonblocking
Definition libpq-int.h:470
PGAsyncStatusType asyncStatus
Definition libpq-int.h:466
PGpipelineStatus pipelineStatus
Definition libpq-int.h:472
ConnStatusType status
Definition libpq-int.h:465

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

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

◆ pqCommandQueueAdvance()

void pqCommandQueueAdvance ( PGconn conn,
bool  isReadyForQuery,
bool  gotSync 
)
extern

Definition at line 3173 of file fe-exec.c.

3174{
3176
3177 if (conn->cmd_queue_head == NULL)
3178 return;
3179
3180 /*
3181 * If processing a query of simple query protocol, we only advance the
3182 * queue when we receive the ReadyForQuery message for it.
3183 */
3185 return;
3186
3187 /*
3188 * If we're waiting for a SYNC, don't advance the queue until we get one.
3189 */
3191 return;
3192
3193 /* delink element from queue */
3196
3197 /* If the queue is now empty, reset the tail too */
3198 if (conn->cmd_queue_head == NULL)
3200
3201 /* and make the queue element recyclable */
3202 prevquery->next = NULL;
3204}
static void pqRecycleCmdQueueEntry(PGconn *conn, PGcmdQueueEntry *entry)
Definition fe-exec.c:1403
PGQueryClass queryclass
Definition libpq-int.h:347
struct PGcmdQueueEntry * next
Definition libpq-int.h:349
PGcmdQueueEntry * cmd_queue_tail
Definition libpq-int.h:493
PGcmdQueueEntry * cmd_queue_head
Definition libpq-int.h:492

References pg_conn::cmd_queue_head, pg_conn::cmd_queue_tail, conn, fb(), PGcmdQueueEntry::next, PGQUERY_SIMPLE, PGQUERY_SYNC, pqRecycleCmdQueueEntry(), and PGcmdQueueEntry::queryclass.

Referenced by PQgetResult(), and pqParseInput3().

◆ pqConnectDBComplete()

int pqConnectDBComplete ( PGconn conn)
extern

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

2805{
2808 int timeout = 0;
2809 int last_whichhost = -2; /* certainly different from whichhost */
2810 int last_whichaddr = -2; /* certainly different from whichaddr */
2811
2812 if (conn == NULL || conn->status == CONNECTION_BAD)
2813 return 0;
2814
2815 /*
2816 * Set up a time limit, if connect_timeout is greater than zero.
2817 */
2818 if (conn->connect_timeout != NULL)
2819 {
2821 "connect_timeout"))
2822 {
2823 /* mark the connection as bad to report the parsing failure */
2825 return 0;
2826 }
2827 }
2828
2829 for (;;)
2830 {
2831 int ret = 0;
2832
2833 /*
2834 * (Re)start the connect_timeout timer if it's active and we are
2835 * considering a different host than we were last time through. If
2836 * we've already succeeded, though, needn't recalculate.
2837 */
2838 if (flag != PGRES_POLLING_OK &&
2839 timeout > 0 &&
2842 {
2846 }
2847
2848 /*
2849 * Wait, if necessary. Note that the initial state (just after
2850 * PQconnectStart) is to wait for the socket to select for writing.
2851 */
2852 switch (flag)
2853 {
2854 case PGRES_POLLING_OK:
2855 return 1; /* success! */
2856
2858 ret = pqWaitTimed(1, 0, conn, end_time);
2859 if (ret == -1)
2860 {
2861 /* hard failure, eg select() problem, aborts everything */
2863 return 0;
2864 }
2865 break;
2866
2868 ret = pqWaitTimed(0, 1, conn, end_time);
2869 if (ret == -1)
2870 {
2871 /* hard failure, eg select() problem, aborts everything */
2873 return 0;
2874 }
2875 break;
2876
2877 default:
2878 /* Just in case we failed to set it in PQconnectPoll */
2880 return 0;
2881 }
2882
2883 if (ret == 1) /* connect_timeout elapsed */
2884 {
2885 /*
2886 * Give up on current server/address, try the next one.
2887 */
2888 conn->try_next_addr = true;
2890 }
2891
2892 /*
2893 * Now try to advance the state machine.
2894 */
2895 if (conn->cancelRequest)
2897 else
2899 }
2900}
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
Definition fe-cancel.c:226
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
pg_usec_time_t PQgetCurrentTimeUSec(void)
Definition fe-misc.c:1379
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
Definition fe-misc.c:1181
@ CONNECTION_NEEDED
Definition libpq-fe.h:106
int64_t pg_usec_time_t
Definition libpq-fe.h:251
PostgresPollingStatusType
Definition libpq-fe.h:120
@ PGRES_POLLING_OK
Definition libpq-fe.h:124
@ PGRES_POLLING_READING
Definition libpq-fe.h:122
@ PGRES_POLLING_WRITING
Definition libpq-fe.h:123
static int64 end_time
Definition pgbench.c:176
int whichaddr
Definition libpq-int.h:543
char * connect_timeout
Definition libpq-int.h:386
bool try_next_addr
Definition libpq-int.h:540
char * flag(int b)
Definition test-ctype.c:33

References pg_conn::cancelRequest, conn, pg_conn::connect_timeout, CONNECTION_BAD, CONNECTION_NEEDED, end_time, fb(), flag(), PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQcancelPoll(), PQconnectPoll(), PQgetCurrentTimeUSec(), 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().

◆ pqConnectDBStart()

int pqConnectDBStart ( PGconn conn)
extern

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

2727{
2728 if (!conn)
2729 return 0;
2730
2731 if (!conn->options_valid)
2732 goto connect_errReturn;
2733
2734 /*
2735 * Check for bad linking to backend-internal versions of src/common
2736 * functions (see comments in link-canary.c for the reason we need this).
2737 * Nobody but developers should see this message, so we don't bother
2738 * translating it.
2739 */
2741 {
2743 "libpq is incorrectly linked to backend functions\n");
2744 goto connect_errReturn;
2745 }
2746
2747 /* Ensure our buffers are empty */
2748 conn->inStart = conn->inCursor = conn->inEnd = 0;
2749 conn->outCount = 0;
2750
2751 /*
2752 * Set up to try to connect to the first host. (Setting whichhost = -1 is
2753 * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2754 * anything else looks at it.)
2755 *
2756 * Cancel requests are special though, they should only try one host and
2757 * address, and these fields have already been set up in PQcancelCreate,
2758 * so leave these fields alone for cancel requests.
2759 */
2760 if (!conn->cancelRequest)
2761 {
2762 conn->whichhost = -1;
2763 conn->try_next_host = true;
2764 conn->try_next_addr = false;
2765 }
2766
2768
2769 /* Also reset the target_server_type state if needed */
2772
2773 /*
2774 * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2775 * so that it can easily be re-executed if needed again during the
2776 * asynchronous startup process. However, we must run it once here,
2777 * because callers expect a success return from this routine to mean that
2778 * we are in PGRES_POLLING_WRITING connection state.
2779 */
2781 return 1;
2782
2784
2785 /*
2786 * If we managed to open a socket, close it immediately rather than
2787 * waiting till PQfinish. (The application cannot have gotten the socket
2788 * from PQsocket yet, so this doesn't risk breaking anything.)
2789 */
2790 pqDropConnection(conn, true);
2792 return 0;
2793}
bool try_next_host
Definition libpq-int.h:541
bool options_valid
Definition libpq-int.h:469
PGTargetServerType target_server_type
Definition libpq-int.h:537
int outCount
Definition libpq-int.h:588

References appendPQExpBufferStr(), pg_conn::cancelRequest, conn, CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, fb(), 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().

◆ pqConnectOptions2()

bool pqConnectOptions2 ( PGconn conn)
extern

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

1258{
1259 /*
1260 * Allocate memory for details about each host to which we might possibly
1261 * try to connect. For that, count the number of elements in the hostaddr
1262 * or host options. If neither is given, assume one host.
1263 */
1264 conn->whichhost = 0;
1265 if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1267 else if (conn->pghost && conn->pghost[0] != '\0')
1269 else
1270 conn->nconnhost = 1;
1272 calloc(conn->nconnhost, sizeof(pg_conn_host));
1273 if (conn->connhost == NULL)
1274 goto oom_error;
1275
1276 /*
1277 * We now have one pg_conn_host structure per possible host. Fill in the
1278 * host and hostaddr fields for each, by splitting the parameter strings.
1279 */
1280 if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1281 {
1282 int i;
1283 char *s = conn->pghostaddr;
1284 bool more = true;
1285
1286 for (i = 0; i < conn->nconnhost && more; i++)
1287 {
1289 if (conn->connhost[i].hostaddr == NULL)
1290 goto oom_error;
1291 }
1292
1293 /*
1294 * If hostaddr was given, the array was allocated according to the
1295 * number of elements in the hostaddr list, so it really should be the
1296 * right size.
1297 */
1298 Assert(!more);
1299 Assert(i == conn->nconnhost);
1300 }
1301
1302 if (conn->pghost != NULL && conn->pghost[0] != '\0')
1303 {
1304 int i;
1305 char *s = conn->pghost;
1306 bool more = true;
1307
1308 for (i = 0; i < conn->nconnhost && more; i++)
1309 {
1311 if (conn->connhost[i].host == NULL)
1312 goto oom_error;
1313 }
1314
1315 /* Check for wrong number of host items. */
1316 if (more || i != conn->nconnhost)
1317 {
1319 libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
1321 return false;
1322 }
1323 }
1324
1325 /*
1326 * Now, for each host slot, identify the type of address spec, and fill in
1327 * the default address if nothing was given.
1328 */
1329 for (int i = 0; i < conn->nconnhost; i++)
1330 {
1332
1333 if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1335 else if (ch->host != NULL && ch->host[0] != '\0')
1336 {
1337 ch->type = CHT_HOST_NAME;
1338 if (is_unixsock_path(ch->host))
1339 ch->type = CHT_UNIX_SOCKET;
1340 }
1341 else
1342 {
1343 free(ch->host);
1344
1345 /*
1346 * This bit selects the default host location. If you change
1347 * this, see also pg_regress.
1348 */
1349 if (DEFAULT_PGSOCKET_DIR[0])
1350 {
1352 ch->type = CHT_UNIX_SOCKET;
1353 }
1354 else
1355 {
1356 ch->host = strdup(DefaultHost);
1357 ch->type = CHT_HOST_NAME;
1358 }
1359 if (ch->host == NULL)
1360 goto oom_error;
1361 }
1362 }
1363
1364 /*
1365 * Next, work out the port number corresponding to each host name.
1366 *
1367 * Note: unlike the above for host names, this could leave the port fields
1368 * as null or empty strings. We will substitute DEF_PGPORT whenever we
1369 * read such a port field.
1370 */
1371 if (conn->pgport != NULL && conn->pgport[0] != '\0')
1372 {
1373 int i;
1374 char *s = conn->pgport;
1375 bool more = true;
1376
1377 for (i = 0; i < conn->nconnhost && more; i++)
1378 {
1380 if (conn->connhost[i].port == NULL)
1381 goto oom_error;
1382 }
1383
1384 /*
1385 * If exactly one port was given, use it for every host. Otherwise,
1386 * there must be exactly as many ports as there were hosts.
1387 */
1388 if (i == 1 && !more)
1389 {
1390 for (i = 1; i < conn->nconnhost; i++)
1391 {
1393 if (conn->connhost[i].port == NULL)
1394 goto oom_error;
1395 }
1396 }
1397 else if (more || i != conn->nconnhost)
1398 {
1400 libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
1402 return false;
1403 }
1404 }
1405
1406 /*
1407 * If user name was not given, fetch it. (Most likely, the fetch will
1408 * fail, since the only way we get here is if pg_fe_getauthname() failed
1409 * during conninfo_add_defaults(). But now we want an error message.)
1410 */
1411 if (conn->pguser == NULL || conn->pguser[0] == '\0')
1412 {
1413 free(conn->pguser);
1415 if (!conn->pguser)
1416 {
1418 return false;
1419 }
1420 }
1421
1422 /*
1423 * If database name was not given, default it to equal user name
1424 */
1425 if (conn->dbName == NULL || conn->dbName[0] == '\0')
1426 {
1427 free(conn->dbName);
1429 if (!conn->dbName)
1430 goto oom_error;
1431 }
1432
1433 /*
1434 * If password was not given, try to look it up in password file. Note
1435 * that the result might be different for each host/port pair.
1436 */
1437 if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1438 {
1439 /* If password file wasn't specified, use ~/PGPASSFILE */
1440 if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1441 {
1442 char homedir[MAXPGPATH];
1443
1444 if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1445 {
1448 if (!conn->pgpassfile)
1449 goto oom_error;
1450 snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1452 }
1453 }
1454
1455 if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1456 {
1457 for (int i = 0; i < conn->nconnhost; i++)
1458 {
1459 /*
1460 * Try to get a password for this host from file. We use host
1461 * for the hostname search key if given, else hostaddr (at
1462 * least one of them is guaranteed nonempty by now).
1463 */
1464 const char *pwhost = conn->connhost[i].host;
1465 const char *password_errmsg = NULL;
1466
1467 if (pwhost == NULL || pwhost[0] == '\0')
1469
1472 conn->connhost[i].port,
1473 conn->dbName,
1474 conn->pguser,
1477
1478 if (password_errmsg != NULL)
1479 {
1482 return false;
1483 }
1484 }
1485 }
1486 }
1487
1488 /*
1489 * parse and validate require_auth option
1490 */
1491 if (conn->require_auth && conn->require_auth[0])
1492 {
1493 char *s = conn->require_auth;
1494 bool first,
1495 more;
1496 bool negated = false;
1497
1498 /*
1499 * By default, start from an empty set of allowed methods and
1500 * mechanisms, and add to it.
1501 */
1502 conn->auth_required = true;
1505
1506 for (first = true, more = true; more; first = false)
1507 {
1508 char *method,
1509 *part;
1510 uint32 bits = 0;
1511 const pg_fe_sasl_mech *mech = NULL;
1512
1514 if (part == NULL)
1515 goto oom_error;
1516
1517 /*
1518 * Check for negation, e.g. '!password'. If one element is
1519 * negated, they all have to be.
1520 */
1521 method = part;
1522 if (*method == '!')
1523 {
1524 if (first)
1525 {
1526 /*
1527 * Switch to a permissive set of allowed methods and
1528 * mechanisms, and subtract from it.
1529 */
1530 conn->auth_required = false;
1533 }
1534 else if (!negated)
1535 {
1537 libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
1538 method);
1539
1540 free(part);
1541 return false;
1542 }
1543
1544 negated = true;
1545 method++;
1546 }
1547 else if (negated)
1548 {
1550 libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
1551 method);
1552
1553 free(part);
1554 return false;
1555 }
1556
1557 /*
1558 * First group: methods that can be handled solely with the
1559 * authentication request codes.
1560 */
1561 if (strcmp(method, "password") == 0)
1562 {
1563 bits = (1 << AUTH_REQ_PASSWORD);
1564 }
1565 else if (strcmp(method, "md5") == 0)
1566 {
1567 bits = (1 << AUTH_REQ_MD5);
1568 }
1569 else if (strcmp(method, "gss") == 0)
1570 {
1571 bits = (1 << AUTH_REQ_GSS);
1572 bits |= (1 << AUTH_REQ_GSS_CONT);
1573 }
1574 else if (strcmp(method, "sspi") == 0)
1575 {
1576 bits = (1 << AUTH_REQ_SSPI);
1577 bits |= (1 << AUTH_REQ_GSS_CONT);
1578 }
1579
1580 /*
1581 * Next group: SASL mechanisms. All of these use the same request
1582 * codes, so the list of allowed mechanisms is tracked separately.
1583 *
1584 * supported_sasl_mechs must contain all mechanisms handled here.
1585 */
1586 else if (strcmp(method, "scram-sha-256") == 0)
1587 {
1589 }
1590 else if (strcmp(method, "oauth") == 0)
1591 {
1593 }
1594
1595 /*
1596 * Final group: meta-options.
1597 */
1598 else if (strcmp(method, "none") == 0)
1599 {
1600 /*
1601 * Special case: let the user explicitly allow (or disallow)
1602 * connections where the server does not send an explicit
1603 * authentication challenge, such as "trust" and "cert" auth.
1604 */
1605 if (negated) /* "!none" */
1606 {
1607 if (conn->auth_required)
1608 goto duplicate;
1609
1610 conn->auth_required = true;
1611 }
1612 else /* "none" */
1613 {
1614 if (!conn->auth_required)
1615 goto duplicate;
1616
1617 conn->auth_required = false;
1618 }
1619
1620 free(part);
1621 continue; /* avoid the bitmask manipulation below */
1622 }
1623 else
1624 {
1626 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1627 "require_auth", method);
1628
1629 free(part);
1630 return false;
1631 }
1632
1633 if (mech)
1634 {
1635 /*
1636 * Update the mechanism set only. The method bitmask will be
1637 * updated for SASL further down.
1638 */
1639 Assert(!bits);
1640
1641 if (negated)
1642 {
1643 int i;
1644
1645 /* Remove the existing mechanism from the list. */
1647 if (i < 0)
1648 goto duplicate;
1649
1651 }
1652 else
1653 {
1654 int i;
1655
1656 /*
1657 * Find a space to put the new mechanism (after making
1658 * sure it's not already there).
1659 */
1661 if (i >= 0)
1662 goto duplicate;
1663
1665 if (i < 0)
1666 {
1667 /* Should not happen; the pointer list is corrupted. */
1668 Assert(false);
1669
1672 "internal error: no space in allowed_sasl_mechs");
1673 free(part);
1674 return false;
1675 }
1676
1678 }
1679 }
1680 else
1681 {
1682 /* Update the method bitmask. */
1683 Assert(bits);
1684
1685 if (negated)
1686 {
1687 if ((conn->allowed_auth_methods & bits) == 0)
1688 goto duplicate;
1689
1691 }
1692 else
1693 {
1694 if ((conn->allowed_auth_methods & bits) == bits)
1695 goto duplicate;
1696
1697 conn->allowed_auth_methods |= bits;
1698 }
1699 }
1700
1701 free(part);
1702 continue;
1703
1704 duplicate:
1705
1706 /*
1707 * A duplicated method probably indicates a typo in a setting
1708 * where typos are extremely risky.
1709 */
1711 libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
1712 part);
1713
1714 free(part);
1715 return false;
1716 }
1717
1718 /*
1719 * Finally, allow SASL authentication requests if (and only if) we've
1720 * allowed any mechanisms.
1721 */
1722 {
1723 bool allowed = false;
1724 const uint32 sasl_bits =
1725 (1 << AUTH_REQ_SASL)
1726 | (1 << AUTH_REQ_SASL_CONT)
1727 | (1 << AUTH_REQ_SASL_FIN);
1728
1729 for (size_t i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1730 {
1732 {
1733 allowed = true;
1734 break;
1735 }
1736 }
1737
1738 /*
1739 * For the standard case, add the SASL bits to the (default-empty)
1740 * set if needed. For the negated case, remove them.
1741 */
1742 if (!negated && allowed)
1744 else if (negated && !allowed)
1746 }
1747 }
1748
1749 /*
1750 * validate channel_binding option
1751 */
1752 if (conn->channel_binding)
1753 {
1754 if (strcmp(conn->channel_binding, "disable") != 0
1755 && strcmp(conn->channel_binding, "prefer") != 0
1756 && strcmp(conn->channel_binding, "require") != 0)
1757 {
1759 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1760 "channel_binding", conn->channel_binding);
1761 return false;
1762 }
1763 }
1764 else
1765 {
1767 if (!conn->channel_binding)
1768 goto oom_error;
1769 }
1770
1771#ifndef USE_SSL
1772
1773 /*
1774 * sslrootcert=system is not supported. Since setting this changes the
1775 * default sslmode, check this _before_ we validate sslmode, to avoid
1776 * confusing the user with errors for an option they may not have set.
1777 */
1778 if (conn->sslrootcert
1779 && strcmp(conn->sslrootcert, "system") == 0)
1780 {
1782 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1783 "sslrootcert", conn->sslrootcert);
1784 return false;
1785 }
1786#endif
1787
1788 /*
1789 * validate sslmode option
1790 */
1791 if (conn->sslmode)
1792 {
1793 if (strcmp(conn->sslmode, "disable") != 0
1794 && strcmp(conn->sslmode, "allow") != 0
1795 && strcmp(conn->sslmode, "prefer") != 0
1796 && strcmp(conn->sslmode, "require") != 0
1797 && strcmp(conn->sslmode, "verify-ca") != 0
1798 && strcmp(conn->sslmode, "verify-full") != 0)
1799 {
1801 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1802 "sslmode", conn->sslmode);
1803 return false;
1804 }
1805
1806#ifndef USE_SSL
1807 switch (conn->sslmode[0])
1808 {
1809 case 'a': /* "allow" */
1810 case 'p': /* "prefer" */
1811
1812 /*
1813 * warn user that an SSL connection will never be negotiated
1814 * since SSL was not compiled in?
1815 */
1816 break;
1817
1818 case 'r': /* "require" */
1819 case 'v': /* "verify-ca" or "verify-full" */
1821 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1822 "sslmode", conn->sslmode);
1823 return false;
1824 }
1825#endif
1826 }
1827 else
1828 {
1830 if (!conn->sslmode)
1831 goto oom_error;
1832 }
1833
1834 /*
1835 * validate sslnegotiation option, default is "postgres" for the postgres
1836 * style negotiated connection with an extra round trip but more options.
1837 */
1838 if (conn->sslnegotiation)
1839 {
1840 if (strcmp(conn->sslnegotiation, "postgres") != 0
1841 && strcmp(conn->sslnegotiation, "direct") != 0)
1842 {
1844 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1845 "sslnegotiation", conn->sslnegotiation);
1846 return false;
1847 }
1848
1849#ifndef USE_SSL
1850 if (conn->sslnegotiation[0] != 'p')
1851 {
1853 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1854 "sslnegotiation", conn->sslnegotiation);
1855 return false;
1856 }
1857#endif
1858
1859 /*
1860 * Don't allow direct SSL negotiation with sslmode='prefer', because
1861 * that poses a risk of unintentional fallback to plaintext connection
1862 * when connecting to a pre-v17 server that does not support direct
1863 * SSL connections. To keep things simple, don't allow it with
1864 * sslmode='allow' or sslmode='disable' either. If a user goes through
1865 * the trouble of setting sslnegotiation='direct', they probably
1866 * intend to use SSL, and sslmode=disable or allow is probably a user
1867 * mistake anyway.
1868 */
1869 if (conn->sslnegotiation[0] == 'd' &&
1870 conn->sslmode[0] != 'r' && conn->sslmode[0] != 'v')
1871 {
1873 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")",
1874 conn->sslmode);
1875 return false;
1876 }
1877 }
1878 else
1879 {
1881 if (!conn->sslnegotiation)
1882 goto oom_error;
1883 }
1884
1885#ifdef USE_SSL
1886
1887 /*
1888 * If sslrootcert=system, make sure our chosen sslmode is compatible.
1889 */
1890 if (conn->sslrootcert
1891 && strcmp(conn->sslrootcert, "system") == 0
1892 && strcmp(conn->sslmode, "verify-full") != 0)
1893 {
1895 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
1896 conn->sslmode);
1897 return false;
1898 }
1899#endif
1900
1901 /*
1902 * Validate TLS protocol versions for ssl_min_protocol_version and
1903 * ssl_max_protocol_version.
1904 */
1906 {
1908 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1909 "ssl_min_protocol_version",
1911 return false;
1912 }
1914 {
1916 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1917 "ssl_max_protocol_version",
1919 return false;
1920 }
1921
1922 /*
1923 * Check if the range of SSL protocols defined is correct. This is done
1924 * at this early step because this is independent of the SSL
1925 * implementation used, and this avoids unnecessary cycles with an
1926 * already-built SSL context when the connection is being established, as
1927 * it would be doomed anyway.
1928 */
1931 {
1933 libpq_append_conn_error(conn, "invalid SSL protocol version range");
1934 return false;
1935 }
1936
1937 /*
1938 * validate sslcertmode option
1939 */
1940 if (conn->sslcertmode)
1941 {
1942 if (strcmp(conn->sslcertmode, "disable") != 0 &&
1943 strcmp(conn->sslcertmode, "allow") != 0 &&
1944 strcmp(conn->sslcertmode, "require") != 0)
1945 {
1947 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1948 "sslcertmode", conn->sslcertmode);
1949 return false;
1950 }
1951#ifndef USE_SSL
1952 if (strcmp(conn->sslcertmode, "require") == 0)
1953 {
1955 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1956 "sslcertmode", conn->sslcertmode);
1957 return false;
1958 }
1959#endif
1960#ifndef HAVE_SSL_CTX_SET_CERT_CB
1961
1962 /*
1963 * Without a certificate callback, the current implementation can't
1964 * figure out if a certificate was actually requested, so "require" is
1965 * useless.
1966 */
1967 if (strcmp(conn->sslcertmode, "require") == 0)
1968 {
1970 libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
1971 "sslcertmode", conn->sslcertmode);
1972 return false;
1973 }
1974#endif
1975 }
1976 else
1977 {
1979 if (!conn->sslcertmode)
1980 goto oom_error;
1981 }
1982
1983 /*
1984 * validate gssencmode option
1985 */
1986 if (conn->gssencmode)
1987 {
1988 if (strcmp(conn->gssencmode, "disable") != 0 &&
1989 strcmp(conn->gssencmode, "prefer") != 0 &&
1990 strcmp(conn->gssencmode, "require") != 0)
1991 {
1993 libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1994 return false;
1995 }
1996#ifndef ENABLE_GSS
1997 if (strcmp(conn->gssencmode, "require") == 0)
1998 {
2000 libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
2001 conn->gssencmode);
2002 return false;
2003 }
2004#endif
2005 }
2006 else
2007 {
2009 if (!conn->gssencmode)
2010 goto oom_error;
2011 }
2012
2013 /*
2014 * validate target_session_attrs option, and set target_server_type
2015 */
2017 {
2018 if (strcmp(conn->target_session_attrs, "any") == 0)
2020 else if (strcmp(conn->target_session_attrs, "read-write") == 0)
2022 else if (strcmp(conn->target_session_attrs, "read-only") == 0)
2024 else if (strcmp(conn->target_session_attrs, "primary") == 0)
2026 else if (strcmp(conn->target_session_attrs, "standby") == 0)
2028 else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
2030 else
2031 {
2033 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
2034 "target_session_attrs",
2036 return false;
2037 }
2038 }
2039 else
2041
2043 {
2044 int len;
2045
2049 goto oom_error;
2052 if (len < 0)
2053 {
2054 libpq_append_conn_error(conn, "invalid SCRAM client key");
2055 return false;
2056 }
2057 if (len != SCRAM_MAX_KEY_LEN)
2058 {
2059 libpq_append_conn_error(conn, "invalid SCRAM client key length: %d", len);
2060 return false;
2061 }
2063 }
2064
2066 {
2067 int len;
2068
2072 goto oom_error;
2075 if (len < 0)
2076 {
2077 libpq_append_conn_error(conn, "invalid SCRAM server key");
2078 return false;
2079 }
2080 if (len != SCRAM_MAX_KEY_LEN)
2081 {
2082 libpq_append_conn_error(conn, "invalid SCRAM server key length: %d", len);
2083 return false;
2084 }
2086 }
2087
2088 /*
2089 * validate load_balance_hosts option, and set load_balance_type
2090 */
2092 {
2093 if (strcmp(conn->load_balance_hosts, "disable") == 0)
2095 else if (strcmp(conn->load_balance_hosts, "random") == 0)
2097 else
2098 {
2100 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
2101 "load_balance_hosts",
2103 return false;
2104 }
2105 }
2106 else
2108
2110 {
2112
2113 /*
2114 * This is the "inside-out" variant of the Fisher-Yates shuffle
2115 * algorithm. Notionally, we append each new value to the array and
2116 * then swap it with a randomly-chosen array element (possibly
2117 * including itself, else we fail to generate permutations with the
2118 * last integer last). The swap step can be optimized by combining it
2119 * with the insertion.
2120 */
2121 for (int i = 1; i < conn->nconnhost; i++)
2122 {
2123 int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
2125
2126 conn->connhost[j] = conn->connhost[i];
2127 conn->connhost[i] = temp;
2128 }
2129 }
2130
2132 {
2133 if (!pqParseProtocolVersion(conn->min_protocol_version, &conn->min_pversion, conn, "min_protocol_version"))
2134 {
2136 return false;
2137 }
2138 }
2139 else
2140 {
2142 }
2143
2145 {
2146 if (!pqParseProtocolVersion(conn->max_protocol_version, &conn->max_pversion, conn, "max_protocol_version"))
2147 {
2149 return false;
2150 }
2151 }
2152 else
2153 {
2154 /*
2155 * Default to PG_PROTOCOL_GREASE, which is larger than all real
2156 * versions, to test negotiation. The server should automatically
2157 * downgrade to a supported version.
2158 *
2159 * This behavior is for 19beta only. It will be reverted before RC1.
2160 */
2162 }
2163
2165 {
2167 libpq_append_conn_error(conn, "\"%s\" is greater than \"%s\"", "min_protocol_version", "max_protocol_version");
2168 return false;
2169 }
2170
2171 /*
2172 * Resolve special "auto" client_encoding from the locale
2173 */
2175 strcmp(conn->client_encoding_initial, "auto") == 0)
2176 {
2180 goto oom_error;
2181 }
2182
2183 /*
2184 * Only if we get this far is it appropriate to try to connect. (We need a
2185 * state flag, rather than just the boolean result of this function, in
2186 * case someone tries to PQreset() the PGconn.)
2187 */
2188 conn->options_valid = true;
2189
2190 return true;
2191
2192oom_error:
2194 libpq_append_conn_error(conn, "out of memory");
2195 return false;
2196}
int pg_b64_dec_len(int srclen)
Definition base64.c:239
int pg_b64_decode(const char *src, int len, uint8 *dst, int dstlen)
Definition base64.c:116
uint32_t uint32
Definition c.h:683
#define lengthof(array)
Definition c.h:932
const pg_fe_sasl_mech pg_oauth_mech
const pg_fe_sasl_mech pg_scram_mech
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition fe-auth.c:1344
static bool pqParseProtocolVersion(const char *value, ProtocolVersion *result, PGconn *conn, const char *context)
#define DefaultHost
Definition fe-connect.c:121
static bool sslVerifyProtocolRange(const char *min, const char *max)
static void libpq_prng_init(PGconn *conn)
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile, const char **errmsg)
bool pqGetHomeDirectory(char *buf, int bufsize)
#define DefaultSSLMode
Definition fe-connect.c:134
#define DefaultGSSMode
Definition fe-connect.c:142
static int count_comma_separated_elems(const char *input)
static void clear_allowed_sasl_mechs(PGconn *conn)
static void fill_allowed_sasl_mechs(PGconn *conn)
#define DefaultChannelBinding
Definition fe-connect.c:126
static int index_of_allowed_sasl_mech(PGconn *conn, const pg_fe_sasl_mech *mech)
static bool sslVerifyProtocolVersion(const char *version)
#define DefaultSSLNegotiation
Definition fe-connect.c:137
#define PGPASSFILE
Definition fe-connect.c:79
#define DefaultSSLCertMode
Definition fe-connect.c:135
static char * parse_comma_separated_list(char **startptr, bool *more)
int j
Definition isn.c:78
#define MAXPGPATH
#define DEFAULT_PGSOCKET_DIR
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:483
#define snprintf
Definition port.h:261
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition chklocale.c:301
#define PG_PROTOCOL_EARLIEST
Definition pqcomm.h:94
static bool is_unixsock_path(const char *path)
Definition pqcomm.h:66
#define PG_PROTOCOL_GREASE
Definition pqcomm.h:115
#define AUTH_REQ_SSPI
Definition protocol.h:105
#define AUTH_REQ_SASL_CONT
Definition protocol.h:107
#define AUTH_REQ_GSS
Definition protocol.h:103
#define AUTH_REQ_MD5
Definition protocol.h:101
#define AUTH_REQ_PASSWORD
Definition protocol.h:99
#define AUTH_REQ_GSS_CONT
Definition protocol.h:104
#define AUTH_REQ_SASL
Definition protocol.h:106
#define AUTH_REQ_SASL_FIN
Definition protocol.h:108
#define SCRAM_MAX_KEY_LEN
#define calloc(a, b)
char * password
Definition libpq-int.h:364
char * port
Definition libpq-int.h:362
char * hostaddr
Definition libpq-int.h:361
pg_conn_host_type type
Definition libpq-int.h:359
uint8 * scram_client_key_binary
Definition libpq-int.h:548
char * sslrootcert
Definition libpq-int.h:415
char * sslnegotiation
Definition libpq-int.h:409
int nconnhost
Definition libpq-int.h:483
char * require_auth
Definition libpq-int.h:430
char * channel_binding
Definition libpq-int.h:400
char * pghost
Definition libpq-int.h:376
size_t scram_client_key_len
Definition libpq-int.h:547
char * ssl_max_protocol_version
Definition libpq-int.h:428
uint8 * scram_server_key_binary
Definition libpq-int.h:550
char * pgpass
Definition libpq-int.h:398
ProtocolVersion min_pversion
Definition libpq-int.h:551
char * dbName
Definition libpq-int.h:392
char * sslcertmode
Definition libpq-int.h:414
uint32 allowed_auth_methods
Definition libpq-int.h:520
char * target_session_attrs
Definition libpq-int.h:429
bool auth_required
Definition libpq-int.h:518
char * max_protocol_version
Definition libpq-int.h:426
char * load_balance_hosts
Definition libpq-int.h:431
char * pguser
Definition libpq-int.h:397
char * min_protocol_version
Definition libpq-int.h:425
char * client_encoding_initial
Definition libpq-int.h:388
char * sslmode
Definition libpq-int.h:408
pg_prng_state prng_state
Definition libpq-int.h:566
char * ssl_min_protocol_version
Definition libpq-int.h:427
char * gssencmode
Definition libpq-int.h:420
char * scram_server_key
Definition libpq-int.h:433
char * pghostaddr
Definition libpq-int.h:380
char * scram_client_key
Definition libpq-int.h:432
ProtocolVersion max_pversion
Definition libpq-int.h:552
char * pgpassfile
Definition libpq-int.h:399
PGLoadBalanceType load_balance_type
Definition libpq-int.h:538
size_t scram_server_key_len
Definition libpq-int.h:549
char * pgport
Definition libpq-int.h:384
const pg_fe_sasl_mech * allowed_sasl_mechs[2]
Definition libpq-int.h:522

References pg_conn::allowed_auth_methods, pg_conn::allowed_sasl_mechs, 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, clear_allowed_sasl_mechs(), 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, DefaultSSLNegotiation, pg_conn::errorMessage, fb(), fill_allowed_sasl_mechs(), free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, index_of_allowed_sasl_mech(), is_unixsock_path(), j, len, lengthof, libpq_append_conn_error(), libpq_prng_init(), LOAD_BALANCE_DISABLE, pg_conn::load_balance_hosts, LOAD_BALANCE_RANDOM, pg_conn::load_balance_type, malloc, pg_conn::max_protocol_version, pg_conn::max_pversion, MAXPGPATH, pg_conn::min_protocol_version, pg_conn::min_pversion, pg_conn::nconnhost, pg_conn::options_valid, parse_comma_separated_list(), pg_conn_host::password, passwordFromFile(), pg_b64_dec_len(), pg_b64_decode(), pg_encoding_to_char, pg_fe_getauthname(), pg_get_encoding_from_locale(), pg_oauth_mech, pg_prng_uint64_range(), PG_PROTOCOL_EARLIEST, PG_PROTOCOL_GREASE, pg_scram_mech, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgpass, PGPASSFILE, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pguser, pg_conn_host::port, pqGetHomeDirectory(), pqParseProtocolVersion(), pg_conn::prng_state, pg_conn::require_auth, pg_conn::scram_client_key, pg_conn::scram_client_key_binary, pg_conn::scram_client_key_len, SCRAM_MAX_KEY_LEN, pg_conn::scram_server_key, pg_conn::scram_server_key_binary, pg_conn::scram_server_key_len, 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::sslnegotiation, 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().

◆ pqCopyPGconn()

bool pqCopyPGconn ( PGconn srcConn,
PGconn dstConn 
)
extern

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

1043{
1045
1046 /* copy over connection options */
1047 for (option = PQconninfoOptions; option->keyword; option++)
1048 {
1049 if (option->connofs >= 0)
1050 {
1051 const char **tmp = (const char **) ((char *) srcConn + option->connofs);
1052
1053 if (*tmp)
1054 {
1055 char **dstConnmember = (char **) ((char *) dstConn + option->connofs);
1056
1057 if (*dstConnmember)
1059 *dstConnmember = strdup(*tmp);
1060 if (*dstConnmember == NULL)
1061 {
1062 libpq_append_conn_error(dstConn, "out of memory");
1063 return false;
1064 }
1065 }
1066 }
1067 }
1068 return true;
1069}
static const internalPQconninfoOption PQconninfoOptions[]
Definition fe-connect.c:201

References fb(), free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by PQcancelCreate().

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)
extern

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

538{
539 /* Drop any SSL state */
541
542 /* Close the socket itself */
543 if (conn->sock != PGINVALID_SOCKET)
546
547 /* Optionally discard any unread data */
548 if (flushInput)
549 conn->inStart = conn->inCursor = conn->inEnd = 0;
550
551 /* Always discard any unsent data */
552 conn->outCount = 0;
553
554 /* Likewise, discard any pending pipelined commands */
559
560 /* Free authentication/encryption state */
562 {
563 /*
564 * Any in-progress async authentication should be torn down first so
565 * that cleanup_async_auth() can depend on the other authentication
566 * state if necessary.
567 */
570 }
572 /* cleanup_async_auth() should have done this, but make sure */
574#ifdef ENABLE_GSS
575 {
577
578 if (conn->gcred != GSS_C_NO_CREDENTIAL)
579 {
580 gss_release_cred(&min_s, &conn->gcred);
581 conn->gcred = GSS_C_NO_CREDENTIAL;
582 }
583 if (conn->gctx)
585 if (conn->gtarg_nam)
586 gss_release_name(&min_s, &conn->gtarg_nam);
587 if (conn->gss_SendBuffer)
588 {
589 free(conn->gss_SendBuffer);
590 conn->gss_SendBuffer = NULL;
591 }
592 if (conn->gss_RecvBuffer)
593 {
594 free(conn->gss_RecvBuffer);
595 conn->gss_RecvBuffer = NULL;
596 }
597 if (conn->gss_ResultBuffer)
598 {
599 free(conn->gss_ResultBuffer);
600 conn->gss_ResultBuffer = NULL;
601 }
602 conn->gssenc = false;
603 }
604#endif
605#ifdef ENABLE_SSPI
606 if (conn->sspitarget)
607 {
608 free(conn->sspitarget);
609 conn->sspitarget = NULL;
610 }
611 if (conn->sspicred)
612 {
613 FreeCredentialsHandle(conn->sspicred);
614 free(conn->sspicred);
615 conn->sspicred = NULL;
616 }
617 if (conn->sspictx)
618 {
619 DeleteSecurityContext(conn->sspictx);
620 free(conn->sspictx);
621 conn->sspictx = NULL;
622 }
623 conn->usesspi = 0;
624#endif
625 if (conn->sasl_state)
626 {
629 }
630}
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition fe-connect.c:637
void pqsecure_close(PGconn *conn)
Definition fe-secure.c:152
#define PGINVALID_SOCKET
Definition port.h:31
#define closesocket
Definition port.h:398
pgsocket sock
Definition libpq-int.h:502
const pg_fe_sasl_mech * sasl
Definition libpq-int.h:614
void(* cleanup_async_auth)(PGconn *conn)
Definition libpq-int.h:532
PGcmdQueueEntry * cmd_queue_recycle
Definition libpq-int.h:499
pgsocket altsock
Definition libpq-int.h:533
PostgresPollingStatusType(* async_auth)(PGconn *conn)
Definition libpq-int.h:531
void * sasl_state
Definition libpq-int.h:615
void(* free)(void *state)

References pg_conn::altsock, pg_conn::async_auth, pg_conn::cleanup_async_auth, closesocket, pg_conn::cmd_queue_head, pg_conn::cmd_queue_recycle, pg_conn::cmd_queue_tail, conn, fb(), 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 handleFatalError(), pqClosePGconn(), pqConnectDBStart(), PQconnectPoll(), and pqReadData_internal().

◆ pqEndcopy3()

int pqEndcopy3 ( PGconn conn)
extern

Definition at line 2115 of file fe-protocol3.c.

2116{
2118
2122 {
2123 libpq_append_conn_error(conn, "no COPY in progress");
2124 return 1;
2125 }
2126
2127 /* Send the CopyDone message if needed */
2130 {
2131 if (pqPutMsgStart(PqMsg_CopyDone, conn) < 0 ||
2132 pqPutMsgEnd(conn) < 0)
2133 return 1;
2134
2135 /*
2136 * If we sent the COPY command in extended-query mode, we must issue a
2137 * Sync as well.
2138 */
2139 if (conn->cmd_queue_head &&
2141 {
2142 if (pqPutMsgStart(PqMsg_Sync, conn) < 0 ||
2143 pqPutMsgEnd(conn) < 0)
2144 return 1;
2145 }
2146 }
2147
2148 /*
2149 * make sure no data is waiting to be sent, abort if we are non-blocking
2150 * and the flush fails
2151 */
2153 return 1;
2154
2155 /* Return to active duty */
2157
2158 /*
2159 * Non blocking connections may have to abort at this point. If everyone
2160 * played the game there should be no problem, but in error scenarios the
2161 * expected messages may not have arrived yet. (We are assuming that the
2162 * backend's packetizing will ensure that CommandComplete arrives along
2163 * with the CopyDone; are there corner cases where that doesn't happen?)
2164 */
2166 return 1;
2167
2168 /* Wait for the completion response */
2170
2171 /* Expecting a successful result */
2172 if (result && result->resultStatus == PGRES_COMMAND_OK)
2173 {
2174 PQclear(result);
2175 return 0;
2176 }
2177
2178 /*
2179 * Trouble. For backwards-compatibility reasons, we issue the error
2180 * message as if it were a notice (would be nice to get rid of this
2181 * silliness, but too many apps probably don't handle errors from
2182 * PQendcopy reasonably). Note that the app can still obtain the error
2183 * status from the PGconn object.
2184 */
2185 if (conn->errorMessage.len > 0)
2186 {
2187 /* We have to strip the trailing newline ... pain in neck... */
2189
2190 if (svLast == '\n')
2191 conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
2194 }
2195
2196 PQclear(result);
2197
2198 return 1;
2199}
uint32 result
void pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
Definition fe-exec.c:944
int PQisBusy(PGconn *conn)
Definition fe-exec.c:2048
int pqFlush(PGconn *conn)
Definition fe-misc.c:1140
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition fe-misc.c:475
int pqPutMsgEnd(PGconn *conn)
Definition fe-misc.c:534
#define PQgetResult
@ PGRES_COMMAND_OK
Definition libpq-fe.h:131
#define pqIsnonblocking(conn)
Definition libpq-int.h:949
#define PqMsg_CopyDone
Definition protocol.h:64
#define PqMsg_Sync
Definition protocol.h:27
PGNoticeHooks noticeHooks
Definition libpq-int.h:457

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, PQExpBufferData::data, pg_conn::errorMessage, fb(), PQExpBufferData::len, libpq_append_conn_error(), pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGQUERY_SIMPLE, PGRES_COMMAND_OK, PQclear, pqFlush(), PQgetResult, pqInternalNotice(), PQisBusy(), pqIsnonblocking, PqMsg_CopyDone, PqMsg_Sync, pqPutMsgEnd(), pqPutMsgStart(), PGcmdQueueEntry::queryclass, and result.

Referenced by PQendcopy().

◆ pqFlush()

int pqFlush ( PGconn conn)
extern

◆ pqFunctionCall3()

PGresult * pqFunctionCall3 ( PGconn conn,
Oid  fnid,
int result_buf,
int  buf_size,
int actual_result_len,
int  result_is_int,
const PQArgBlock args,
int  nargs 
)
extern

Definition at line 2208 of file fe-protocol3.c.

2212{
2213 bool needInput = false;
2215 char id;
2216 int msgLength;
2217 int avail;
2218 int i;
2219
2220 /* already validated by PQfn */
2222
2223 /* PQfn already validated connection state */
2224
2226 pqPutInt(fnid, 4, conn) < 0 || /* function id */
2227 pqPutInt(1, 2, conn) < 0 || /* # of format codes */
2228 pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
2229 pqPutInt(nargs, 2, conn) < 0) /* # of args */
2230 {
2231 /* error message should be set up already */
2232 return NULL;
2233 }
2234
2235 for (i = 0; i < nargs; ++i)
2236 { /* len.int4 + contents */
2237 if (pqPutInt(args[i].len, 4, conn))
2238 return NULL;
2239 if (args[i].len == -1)
2240 continue; /* it's NULL */
2241
2242 if (args[i].isint)
2243 {
2244 if (pqPutInt(args[i].u.integer, args[i].len, conn))
2245 return NULL;
2246 }
2247 else
2248 {
2249 if (pqPutnchar(args[i].u.ptr, args[i].len, conn))
2250 return NULL;
2251 }
2252 }
2253
2254 if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
2255 return NULL;
2256
2257 if (pqPutMsgEnd(conn) < 0 ||
2258 pqFlush(conn))
2259 return NULL;
2260
2261 for (;;)
2262 {
2263 if (needInput)
2264 {
2265 /* Wait for some data to arrive (or for the channel to close) */
2266 if (pqWait(true, false, conn) ||
2267 pqReadData(conn) < 0)
2268 break;
2269 }
2270
2271 /*
2272 * Scan the message. If we run out of data, loop around to try again.
2273 */
2274 needInput = true;
2275
2277 if (pqGetc(&id, conn))
2278 continue;
2279 if (pqGetInt(&msgLength, 4, conn))
2280 continue;
2281
2282 /*
2283 * Try to validate message type/length here. A length less than 4 is
2284 * definitely broken. Large lengths should only be believed for a few
2285 * message types.
2286 */
2287 if (msgLength < 4)
2288 {
2290 break;
2291 }
2292 if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
2293 {
2295 break;
2296 }
2297
2298 /*
2299 * Can't process if message body isn't all here yet.
2300 */
2301 msgLength -= 4;
2302 avail = conn->inEnd - conn->inCursor;
2303 if (avail < msgLength)
2304 {
2305 /*
2306 * Before looping, enlarge the input buffer if needed to hold the
2307 * whole message. See notes in parseInput.
2308 */
2310 conn))
2311 {
2312 /*
2313 * Abandon the connection. There's not much else we can
2314 * safely do; we can't just ignore the message or we could
2315 * miss important changes to the connection state.
2316 * pqCheckInBufferSpace() already reported the error.
2317 */
2319 break;
2320 }
2321 continue;
2322 }
2323
2324 /*
2325 * We should see V or E response to the command, but might get N
2326 * and/or A notices first. We also need to swallow the final Z before
2327 * returning.
2328 */
2329 switch (id)
2330 {
2333 continue;
2334 if (*actual_result_len != -1)
2335 {
2336 if (result_is_int)
2337 {
2339 continue;
2340 }
2341 else
2342 {
2343 /*
2344 * If the server returned too much data for the
2345 * buffer, something fishy is going on. Abandon ship.
2346 */
2347 if (buf_size != -1 && *actual_result_len > buf_size)
2348 {
2349 libpq_append_conn_error(conn, "server returned too much data");
2351 return pqPrepareAsyncResult(conn);
2352 }
2353
2356 conn))
2357 continue;
2358 }
2359 }
2360 /* correctly finished function result message */
2361 status = PGRES_COMMAND_OK;
2362 break;
2364 if (pqGetErrorNotice3(conn, true))
2365 continue;
2366 status = PGRES_FATAL_ERROR;
2367 break;
2369 /* handle notify and go back to processing return values */
2370 if (getNotify(conn))
2371 continue;
2372 break;
2374 /* handle notice and go back to processing return values */
2375 if (pqGetErrorNotice3(conn, false))
2376 continue;
2377 break;
2380 continue;
2381
2382 /* consume the message */
2384
2385 /*
2386 * If we already have a result object (probably an error), use
2387 * that. Otherwise, if we saw a function result message,
2388 * report COMMAND_OK. Otherwise, the backend violated the
2389 * protocol, so complain.
2390 */
2392 {
2393 if (status == PGRES_COMMAND_OK)
2394 {
2395 conn->result = PQmakeEmptyPGresult(conn, status);
2396 if (!conn->result)
2397 {
2398 libpq_append_conn_error(conn, "out of memory");
2400 }
2401 }
2402 else
2403 {
2404 libpq_append_conn_error(conn, "protocol error: no function result");
2406 }
2407 }
2408 /* and we're out */
2409 return pqPrepareAsyncResult(conn);
2412 continue;
2413 break;
2414 default:
2415 /* The backend violates the protocol. */
2416 libpq_append_conn_error(conn, "protocol error: id=0x%x", id);
2418
2419 /*
2420 * We can't call parsing done due to the protocol violation
2421 * (so message tracing wouldn't work), but trust the specified
2422 * message length as what to skip.
2423 */
2424 conn->inStart += 5 + msgLength;
2425 return pqPrepareAsyncResult(conn);
2426 }
2427
2428 /* Completed parsing this message, keep going */
2430 needInput = false;
2431 }
2432
2433 /*
2434 * We fall out of the loop only upon failing to read data.
2435 * conn->errorMessage has been set by pqWait or pqReadData. We want to
2436 * append it to any already-received error message.
2437 */
2439 return pqPrepareAsyncResult(conn);
2440}
PGresult * pqPrepareAsyncResult(PGconn *conn)
Definition fe-exec.c:857
void pqSaveErrorResult(PGconn *conn)
Definition fe-exec.c:809
PGresult * PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
Definition fe-exec.c:160
int pqReadData(PGconn *conn)
Definition fe-misc.c:615
int pqPutInt(int value, size_t bytes, PGconn *conn)
Definition fe-misc.c:255
void pqParseDone(PGconn *conn, int newInStart)
Definition fe-misc.c:445
int pqGetc(char *result, PGconn *conn)
Definition fe-misc.c:79
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition fe-misc.c:218
int pqWait(int forRead, int forWrite, PGconn *conn)
Definition fe-misc.c:1165
int pqPutnchar(const void *s, size_t len, PGconn *conn)
Definition fe-misc.c:204
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition fe-misc.c:353
int pqGetnchar(void *s, size_t len, PGconn *conn)
Definition fe-misc.c:167
static int getNotify(PGconn *conn)
static int getParameterStatus(PGconn *conn)
static void handleFatalError(PGconn *conn)
#define VALID_LONG_MESSAGE_TYPE(id)
static void handleSyncLoss(PGconn *conn, char id, int msgLength)
static int getReadyForQuery(PGconn *conn)
int pqGetErrorNotice3(PGconn *conn, bool isError)
ExecStatusType
Definition libpq-fe.h:129
#define pgHavePendingResult(conn)
Definition libpq-int.h:942
#define PqMsg_NotificationResponse
Definition protocol.h:41
#define PqMsg_FunctionCall
Definition protocol.h:23
#define PqMsg_FunctionCallResponse
Definition protocol.h:53
#define PqMsg_ReadyForQuery
Definition protocol.h:55
#define PqMsg_ParameterStatus
Definition protocol.h:51
#define PqMsg_ErrorResponse
Definition protocol.h:44
#define PqMsg_NoticeResponse
Definition protocol.h:49

References Assert, conn, fb(), getNotify(), getParameterStatus(), getReadyForQuery(), handleFatalError(), handleSyncLoss(), i, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, len, libpq_append_conn_error(), pgHavePendingResult, PGRES_COMMAND_OK, PGRES_FATAL_ERROR, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqCheckInBufferSpace(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetnchar(), PQmakeEmptyPGresult(), PqMsg_ErrorResponse, PqMsg_FunctionCall, PqMsg_FunctionCallResponse, PqMsg_NoticeResponse, PqMsg_NotificationResponse, PqMsg_ParameterStatus, PqMsg_ReadyForQuery, pqParseDone(), pqPrepareAsyncResult(), pqPutInt(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), pqReadData(), pqSaveErrorResult(), pqWait(), pg_conn::result, and VALID_LONG_MESSAGE_TYPE.

Referenced by PQnfn().

◆ pqGetc()

int pqGetc ( char result,
PGconn conn 
)
extern

◆ pqGetCopyData3()

int pqGetCopyData3 ( PGconn conn,
char **  buffer,
int  async 
)
extern

Definition at line 1950 of file fe-protocol3.c.

1951{
1952 int msgLength;
1953
1954 for (;;)
1955 {
1956 /*
1957 * Collect the next input message. To make life simpler for async
1958 * callers, we keep returning 0 until the next message is fully
1959 * available, even if it is not Copy Data.
1960 */
1962 if (msgLength < 0)
1963 return msgLength; /* end-of-copy or error */
1964 if (msgLength == 0)
1965 {
1966 /* Don't block if async read requested */
1967 if (async)
1968 return 0;
1969 /* Need to load more data */
1970 if (pqWait(true, false, conn) ||
1971 pqReadData(conn) < 0)
1972 return -2;
1973 continue;
1974 }
1975
1976 /*
1977 * Drop zero-length messages (shouldn't happen anyway). Otherwise
1978 * pass the data back to the caller.
1979 */
1980 msgLength -= 4;
1981 if (msgLength > 0)
1982 {
1983 *buffer = (char *) malloc(msgLength + 1);
1984 if (*buffer == NULL)
1985 {
1986 libpq_append_conn_error(conn, "out of memory");
1987 return -2;
1988 }
1989 memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1990 (*buffer)[msgLength] = '\0'; /* Add terminating null */
1991
1992 /* Mark message consumed */
1994
1995 return msgLength;
1996 }
1997
1998 /* Empty, so drop it and loop around for another */
2000 }
2001}
static int getCopyDataMessage(PGconn *conn)

References conn, fb(), getCopyDataMessage(), pg_conn::inBuffer, pg_conn::inCursor, libpq_append_conn_error(), malloc, memcpy(), pqParseDone(), pqReadData(), and pqWait().

Referenced by PQgetCopyData().

◆ pqGetErrorNotice3()

int pqGetErrorNotice3 ( PGconn conn,
bool  isError 
)
extern

Definition at line 899 of file fe-protocol3.c.

900{
901 PGresult *res = NULL;
902 bool have_position = false;
904 char id;
905
906 /* If in pipeline mode, set error indicator for it */
909
910 /*
911 * If this is an error message, pre-emptively clear any incomplete query
912 * result we may have. We'd just throw it away below anyway, and
913 * releasing it before collecting the error might avoid out-of-memory.
914 */
915 if (isError)
917
918 /*
919 * Since the fields might be pretty long, we create a temporary
920 * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
921 * for stuff that is expected to be short. We shouldn't use
922 * conn->errorMessage either, since this might be only a notice.
923 */
925
926 /*
927 * Make a PGresult to hold the accumulated fields. We temporarily lie
928 * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
929 * copy conn->errorMessage.
930 *
931 * NB: This allocation can fail, if you run out of memory. The rest of the
932 * function handles that gracefully, and we still try to set the error
933 * message as the connection's error message.
934 */
936 if (res)
938
939 /*
940 * Read the fields and save into res.
941 *
942 * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
943 * we saw a PG_DIAG_STATEMENT_POSITION field.
944 */
945 for (;;)
946 {
947 if (pqGetc(&id, conn))
948 goto fail;
949 if (id == '\0')
950 break; /* terminator found */
951 if (pqGets(&workBuf, conn))
952 goto fail;
953 pqSaveMessageField(res, id, workBuf.data);
954 if (id == PG_DIAG_SQLSTATE)
956 sizeof(conn->last_sqlstate));
957 else if (id == PG_DIAG_STATEMENT_POSITION)
958 have_position = true;
959 }
960
961 /*
962 * Save the active query text, if any, into res as well; but only if we
963 * might need it for an error cursor display, which is only true if there
964 * is a PG_DIAG_STATEMENT_POSITION field.
965 */
968
969 /*
970 * Now build the "overall" error message for PQresultErrorMessage.
971 */
974
975 /*
976 * Either save error as current async result, or just emit the notice.
977 */
978 if (isError)
979 {
980 pqClearAsyncResult(conn); /* redundant, but be safe */
981 if (res)
982 {
983 pqSetResultError(res, &workBuf, 0);
984 conn->result = res;
985 }
986 else
987 {
988 /* Fall back to using the internal-error processing paths */
989 conn->error_result = true;
990 }
991
993 libpq_append_conn_error(conn, "out of memory");
994 else
996 }
997 else
998 {
999 /* if we couldn't allocate the result set, just discard the NOTICE */
1000 if (res)
1001 {
1002 /*
1003 * We can cheat a little here and not copy the message. But if we
1004 * were unlucky enough to run out of memory while filling workBuf,
1005 * insert "out of memory", as in pqSetResultError.
1006 */
1008 res->errMsg = libpq_gettext("out of memory\n");
1009 else
1010 res->errMsg = workBuf.data;
1011 if (res->noticeHooks.noticeRec != NULL)
1013 PQclear(res);
1014 }
1015 }
1016
1018 return 0;
1019
1020fail:
1021 PQclear(res);
1023 return EOF;
1024}
void pqSaveMessageField(PGresult *res, char code, const char *value)
Definition fe-exec.c:1066
void pqSetResultError(PGresult *res, PQExpBuffer errorMessage, int offset)
Definition fe-exec.c:698
char * pqResultStrdup(PGresult *res, const char *str)
Definition fe-exec.c:681
int pqGets(PQExpBuffer buf, PGconn *conn)
Definition fe-misc.c:138
void pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context)
@ PGRES_EMPTY_QUERY
Definition libpq-fe.h:130
@ PGRES_NONFATAL_ERROR
Definition libpq-fe.h:141
@ PQ_PIPELINE_ABORTED
Definition libpq-fe.h:195
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
#define PQExpBufferDataBroken(buf)
Definition pqexpbuffer.h:67
PQnoticeReceiver noticeRec
Definition libpq-int.h:150
void * noticeRecArg
Definition libpq-int.h:151
PGVerbosity verbosity
Definition libpq-int.h:563
char last_sqlstate[6]
Definition libpq-int.h:468
PGContextVisibility show_context
Definition libpq-int.h:564
PGNoticeHooks noticeHooks
Definition libpq-int.h:184

References appendPQExpBufferStr(), pg_conn::cmd_queue_head, conn, PQExpBufferData::data, pg_result::errMsg, pg_conn::error_result, pg_conn::errorMessage, pg_result::errQuery, fb(), initPQExpBuffer(), pg_conn::last_sqlstate, libpq_append_conn_error(), libpq_gettext, pg_result::noticeHooks, PGNoticeHooks::noticeRec, PGNoticeHooks::noticeRecArg, PG_DIAG_SQLSTATE, PG_DIAG_STATEMENT_POSITION, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_NONFATAL_ERROR, pg_conn::pipelineStatus, PQ_PIPELINE_ABORTED, PQ_PIPELINE_OFF, pqBuildErrorMessage3(), PQclear, pqClearAsyncResult(), PQExpBufferDataBroken, pqGetc(), pqGets(), PQmakeEmptyPGresult(), pqResultStrdup(), pqSaveMessageField(), pqSetResultError(), PGcmdQueueEntry::query, resetPQExpBuffer(), pg_conn::result, pg_result::resultStatus, pg_conn::show_context, strlcpy(), termPQExpBuffer(), and pg_conn::verbosity.

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), and pqParseInput3().

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char buf,
int  bufsize 
)
extern

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

8288{
8289#ifndef WIN32
8290 const char *home;
8291
8292 home = getenv("HOME");
8293 if (home && home[0])
8294 {
8296 return true;
8297 }
8298 else
8299 {
8300 struct passwd pwbuf;
8301 struct passwd *pw;
8302 char tmpbuf[1024];
8303 int rc;
8304
8305 rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw);
8306 if (rc != 0 || !pw)
8307 return false;
8308 strlcpy(buf, pw->pw_dir, bufsize);
8309 return true;
8310 }
8311#else
8312 char tmppath[MAX_PATH];
8313
8314 ZeroMemory(tmppath, sizeof(tmppath));
8316 return false;
8317 snprintf(buf, bufsize, "%s/postgresql", tmppath);
8318 return true;
8319#endif
8320}
#define bufsize
static char buf[DEFAULT_XLOG_SEG_SIZE]
static StringInfoData tmpbuf
Definition walsender.c:195

References buf, bufsize, fb(), snprintf, strlcpy(), and tmpbuf.

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

◆ pqGetInt()

int pqGetInt ( int result,
size_t  bytes,
PGconn conn 
)
extern

Definition at line 218 of file fe-misc.c.

219{
220 uint16 tmp2;
221 uint32 tmp4;
222
223 switch (bytes)
224 {
225 case 2:
226 if (conn->inCursor + 2 > conn->inEnd)
227 return EOF;
229 conn->inCursor += 2;
230 *result = (int) pg_ntoh16(tmp2);
231 break;
232 case 4:
233 if (conn->inCursor + 4 > conn->inEnd)
234 return EOF;
236 conn->inCursor += 4;
237 *result = (int) pg_ntoh32(tmp4);
238 break;
239 default:
241 "integer of size %zu not supported by pqGetInt",
242 bytes);
243 return EOF;
244 }
245
246 return 0;
247}
uint16_t uint16
Definition c.h:682
#define pg_ntoh32(x)
Definition pg_bswap.h:125
#define pg_ntoh16(x)
Definition pg_bswap.h:124

References conn, fb(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, memcpy(), pg_conn::noticeHooks, pg_ntoh16, pg_ntoh32, pqInternalNotice(), and result.

Referenced by getAnotherTuple(), getBackendKeyData(), getCopyDataMessage(), getCopyStart(), getNotify(), getParamDescriptions(), getRowDescriptions(), PQconnectPoll(), pqFunctionCall3(), pqGetNegotiateProtocolVersion3(), and pqParseInput3().

◆ pqGetline3()

int pqGetline3 ( PGconn conn,
char s,
int  maxlen 
)
extern

Definition at line 2009 of file fe-protocol3.c.

2010{
2011 int status;
2012
2013 if (conn->sock == PGINVALID_SOCKET ||
2017 {
2018 libpq_append_conn_error(conn, "PQgetline: not doing text COPY OUT");
2019 *s = '\0';
2020 return EOF;
2021 }
2022
2023 while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
2024 {
2025 /* need to load more data */
2026 if (pqWait(true, false, conn) ||
2027 pqReadData(conn) < 0)
2028 {
2029 *s = '\0';
2030 return EOF;
2031 }
2032 }
2033
2034 if (status < 0)
2035 {
2036 /* End of copy detected; gin up old-style terminator */
2037 strcpy(s, "\\.");
2038 return 0;
2039 }
2040
2041 /* Add null terminator, and strip trailing \n if present */
2042 if (s[status - 1] == '\n')
2043 {
2044 s[status - 1] = '\0';
2045 return 0;
2046 }
2047 else
2048 {
2049 s[status] = '\0';
2050 return 1;
2051 }
2052}
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
Definition fe-exec.c:2918
char copy_is_binary
Definition libpq-int.h:477

References pg_conn::asyncStatus, conn, pg_conn::copy_is_binary, fb(), libpq_append_conn_error(), PGASYNC_COPY_BOTH, PGASYNC_COPY_OUT, PGINVALID_SOCKET, PQgetlineAsync(), pqReadData(), pqWait(), and pg_conn::sock.

Referenced by PQgetline().

◆ pqGetlineAsync3()

int pqGetlineAsync3 ( PGconn conn,
char buffer,
int  bufsize 
)
extern

Definition at line 2060 of file fe-protocol3.c.

2061{
2062 int msgLength;
2063 int avail;
2064
2067 return -1; /* we are not doing a copy... */
2068
2069 /*
2070 * Recognize the next input message. To make life simpler for async
2071 * callers, we keep returning 0 until the next message is fully available
2072 * even if it is not Copy Data. This should keep PQendcopy from blocking.
2073 * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
2074 */
2076 if (msgLength < 0)
2077 return -1; /* end-of-copy or error */
2078 if (msgLength == 0)
2079 return 0; /* no data yet */
2080
2081 /*
2082 * Move data from libpq's buffer to the caller's. In the case where a
2083 * prior call found the caller's buffer too small, we use
2084 * conn->copy_already_done to remember how much of the row was already
2085 * returned to the caller.
2086 */
2088 avail = msgLength - 4 - conn->copy_already_done;
2089 if (avail <= bufsize)
2090 {
2091 /* Able to consume the whole message */
2092 memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
2093 /* Mark message consumed */
2094 conn->inStart = conn->inCursor + avail;
2095 /* Reset state for next time */
2097 return avail;
2098 }
2099 else
2100 {
2101 /* We must return a partial message */
2102 memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
2103 /* The message is NOT consumed from libpq's buffer */
2105 return bufsize;
2106 }
2107}
int copy_already_done
Definition libpq-int.h:478

References pg_conn::asyncStatus, bufsize, conn, pg_conn::copy_already_done, fb(), getCopyDataMessage(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inStart, memcpy(), PGASYNC_COPY_BOTH, and PGASYNC_COPY_OUT.

Referenced by PQgetlineAsync().

◆ pqGetnchar()

int pqGetnchar ( void s,
size_t  len,
PGconn conn 
)
extern

Definition at line 167 of file fe-misc.c.

168{
169 if (len > (size_t) (conn->inEnd - conn->inCursor))
170 return EOF;
171
173 /* no terminating null */
174
175 conn->inCursor += len;
176
177 return 0;
178}

References conn, fb(), pg_conn::inBuffer, pg_conn::inCursor, pg_conn::inEnd, len, and memcpy().

Referenced by getBackendKeyData(), pg_password_sendauth(), pg_SASL_continue(), and pqFunctionCall3().

◆ pqGetNegotiateProtocolVersion3()

int pqGetNegotiateProtocolVersion3 ( PGconn conn)
extern

Definition at line 1444 of file fe-protocol3.c.

1445{
1446 int their_version;
1447 int num;
1450
1451 /*
1452 * During 19beta only, if protocol grease is in use, assume that it's the
1453 * cause of any invalid messages encountered below. We'll print extra
1454 * information for the end user in that case.
1455 */
1457
1458 if (pqGetInt(&their_version, 4, conn) != 0)
1459 goto eof;
1460
1461 if (pqGetInt(&num, 4, conn) != 0)
1462 goto eof;
1463
1464 /*
1465 * Check the protocol version.
1466 *
1467 * PG_PROTOCOL_GREASE is intentionally unsupported and reserved. It's
1468 * higher than any real version, so check for that first, to get the most
1469 * specific error message. Then check the upper and lower bounds.
1470 */
1472 {
1473 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested \"grease\" protocol version 3.9999");
1474 goto failure;
1475 }
1476
1478 {
1479 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to a higher-numbered version");
1480 goto failure;
1481 }
1482
1483 if (their_version < PG_PROTOCOL(3, 0))
1484 {
1485 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to pre-3.0 protocol version");
1486 goto failure;
1487 }
1488
1489 /* 3.1 never existed, we went straight from 3.0 to 3.2 */
1491 {
1492 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to non-existent 3.1 protocol version");
1493 goto failure;
1494 }
1495
1496 if (num < 0)
1497 {
1498 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported negative number of unsupported parameters");
1499 goto failure;
1500 }
1501
1502 if (their_version == conn->pversion && num == 0)
1503 {
1504 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server negotiated but asks for no changes");
1505 goto failure;
1506 }
1507
1508 if (their_version < conn->min_pversion)
1509 {
1510 libpq_append_conn_error(conn, "server only supports protocol version %d.%d, but \"%s\" was set to %d.%d",
1513 "min_protocol_version",
1516
1517 need_grease_info = false; /* this is valid server behavior */
1518 goto failure;
1519 }
1520
1521 /* the version is acceptable */
1523
1524 /*
1525 * Check that all expected unsupported parameters are reported by the
1526 * server.
1527 */
1530
1531 for (int i = 0; i < num; i++)
1532 {
1533 if (pqGets(&conn->workBuffer, conn))
1534 {
1535 goto eof;
1536 }
1537 if (strncmp(conn->workBuffer.data, "_pq_.", 5) != 0)
1538 {
1539 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported unsupported parameter name without a \"%s\" prefix (\"%s\")", "_pq_.", conn->workBuffer.data);
1540 goto failure;
1541 }
1542
1543 /* Check if this is the expected test parameter */
1545 strcmp(conn->workBuffer.data, "_pq_.test_protocol_negotiation") == 0)
1546 {
1548 }
1549 else
1550 {
1551 libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")",
1553 goto failure;
1554 }
1555 }
1556
1557 /*
1558 * If we requested protocol grease, the server must report
1559 * _pq_.test_protocol_negotiation as unsupported. This ensures
1560 * comprehensive NegotiateProtocolVersion implementation.
1561 */
1563 {
1564 libpq_append_conn_error(conn, "server did not report the unsupported \"%s\" parameter in its protocol negotiation message",
1565 "_pq_.test_protocol_negotiation");
1566 goto failure;
1567 }
1568
1569 return 0;
1570
1571eof:
1572 libpq_append_conn_error(conn, "received invalid protocol negotiation message: message too short");
1573failure:
1574 if (need_grease_info)
1578 return 1;
1579}
void libpq_append_grease_info(PGconn *conn)
Definition fe-misc.c:1576
#define PG_PROTOCOL_MAJOR(v)
Definition pqcomm.h:86
#define PG_PROTOCOL_RESERVED_31
Definition pqcomm.h:105
#define PG_PROTOCOL(m, n)
Definition pqcomm.h:89
#define PG_PROTOCOL_MINOR(v)
Definition pqcomm.h:87
ProtocolVersion pversion
Definition libpq-int.h:506
PQExpBufferData workBuffer
Definition libpq-int.h:690

References pg_conn::asyncStatus, conn, PQExpBufferData::data, fb(), i, libpq_append_conn_error(), libpq_append_grease_info(), pg_conn::max_pversion, pg_conn::min_pversion, PG_PROTOCOL, PG_PROTOCOL_GREASE, PG_PROTOCOL_MAJOR, PG_PROTOCOL_MINOR, PG_PROTOCOL_RESERVED_31, PGASYNC_READY, pqGetInt(), pqGets(), pqSaveErrorResult(), pg_conn::pversion, and pg_conn::workBuffer.

Referenced by PQconnectPoll().

◆ pqGets()

int pqGets ( PQExpBuffer  buf,
PGconn conn 
)
extern

Definition at line 138 of file fe-misc.c.

139{
140 return pqGets_internal(buf, conn, true);
141}
static int pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
Definition fe-misc.c:111

References buf, conn, and pqGets_internal().

Referenced by getNotify(), getParameterStatus(), getRowDescriptions(), pg_SASL_init(), pqGetErrorNotice3(), pqGetNegotiateProtocolVersion3(), and pqParseInput3().

◆ pqGets_append()

int pqGets_append ( PQExpBuffer  buf,
PGconn conn 
)
extern

Definition at line 144 of file fe-misc.c.

145{
146 return pqGets_internal(buf, conn, false);
147}

References buf, conn, and pqGets_internal().

Referenced by PQconnectPoll().

◆ pqInternalNotice()

void pqInternalNotice ( const PGNoticeHooks hooks,
const char fmt,
  ... 
)
extern

◆ pqMakeEmptyPGconn()

PGconn * pqMakeEmptyPGconn ( void  )
extern

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

4997{
4998 PGconn *conn;
4999
5000#ifdef WIN32
5001
5002 /*
5003 * Make sure socket support is up and running in this process.
5004 *
5005 * Note: the Windows documentation says that we should eventually do a
5006 * matching WSACleanup() call, but experience suggests that that is at
5007 * least as likely to cause problems as fix them. So we don't.
5008 */
5009 static bool wsastartup_done = false;
5010
5011 if (!wsastartup_done)
5012 {
5014
5015 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
5016 return NULL;
5017 wsastartup_done = true;
5018 }
5019
5020 /* Forget any earlier error */
5021 WSASetLastError(0);
5022#endif /* WIN32 */
5023
5024 conn = (PGconn *) malloc(sizeof(PGconn));
5025 if (conn == NULL)
5026 return conn;
5027
5028 /* Zero all pointers and booleans */
5029 MemSet(conn, 0, sizeof(PGconn));
5030
5031 /* install default notice hooks */
5034
5039 conn->options_valid = false;
5040 conn->nonblocking = false;
5042 conn->std_strings = false; /* unless server says differently */
5050 conn->Pfdebug = NULL;
5051
5052 /*
5053 * We try to send at least 8K at a time, which is the usual size of pipe
5054 * buffers on Unix systems. That way, when we are sending a large amount
5055 * of data, we avoid incurring extra kernel context swaps for partial
5056 * bufferloads. The output buffer is initially made 16K in size, and we
5057 * try to dump it after accumulating 8K.
5058 *
5059 * With the same goal of minimizing context swaps, the input buffer will
5060 * be enlarged anytime it has less than 8K free, so we initially allocate
5061 * twice that.
5062 */
5063 conn->inBufSize = 16 * 1024;
5064 conn->inBuffer = (char *) malloc(conn->inBufSize);
5065 conn->outBufSize = 16 * 1024;
5066 conn->outBuffer = (char *) malloc(conn->outBufSize);
5067 conn->rowBufLen = 32;
5071
5072 if (conn->inBuffer == NULL ||
5073 conn->outBuffer == NULL ||
5074 conn->rowBuf == NULL ||
5077 {
5078 /* out of memory already :-( */
5080 conn = NULL;
5081 }
5082
5083 return conn;
5084}
#define MemSet(start, val, len)
Definition c.h:1147
static void defaultNoticeReceiver(void *arg, const PGresult *res)
static void defaultNoticeProcessor(void *arg, const char *message)
static void freePGconn(PGconn *conn)
@ PQERRORS_DEFAULT
Definition libpq-fe.h:163
@ PG_BOOL_UNKNOWN
Definition oauth-utils.h:33
@ PG_SQL_ASCII
Definition pg_wchar.h:76
#define PQExpBufferBroken(str)
Definition pqexpbuffer.h:59
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
PQnoticeProcessor noticeProc
Definition libpq-int.h:152
PGdataValue * rowBuf
Definition libpq-int.h:596
bool std_strings
Definition libpq-int.h:560
PGTernaryBool in_hot_standby
Definition libpq-int.h:562
int client_encoding
Definition libpq-int.h:559
PGTernaryBool default_transaction_read_only
Definition libpq-int.h:561
int rowBufLen
Definition libpq-int.h:597
int scram_sha_256_iterations
Definition libpq-int.h:616

References pg_conn::altsock, pg_conn::asyncStatus, pg_conn::client_encoding, conn, CONNECTION_BAD, pg_conn::default_transaction_read_only, defaultNoticeProcessor(), defaultNoticeReceiver(), pg_conn::errorMessage, fb(), 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().

◆ PQnfn()

PGresult * PQnfn ( PGconn conn,
int  fnid,
int result_buf,
int  buf_size,
int result_len,
int  result_is_int,
const PQArgBlock args,
int  nargs 
)
extern

Definition at line 3016 of file fe-exec.c.

3018{
3019 *result_len = 0;
3020
3021 if (!conn)
3022 return NULL;
3023
3024 /*
3025 * Since this is the beginning of a query cycle, reset the error state.
3026 * However, in pipeline mode with something already queued, the error
3027 * buffer belongs to that command and we shouldn't clear it.
3028 */
3029 if (conn->cmd_queue_head == NULL)
3031
3033 {
3034 libpq_append_conn_error(conn, "%s not allowed in pipeline mode", "PQfn");
3035 return NULL;
3036 }
3037
3040 {
3041 libpq_append_conn_error(conn, "connection in wrong state");
3042 return NULL;
3043 }
3044
3045 return pqFunctionCall3(conn, fnid,
3048 args, nargs);
3049}
PGresult * pqFunctionCall3(PGconn *conn, Oid fnid, int *result_buf, int buf_size, int *actual_result_len, int result_is_int, const PQArgBlock *args, int nargs)

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, conn, fb(), libpq_append_conn_error(), PGASYNC_IDLE, pgHavePendingResult, PGINVALID_SOCKET, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqClearConnErrorState, pqFunctionCall3(), and pg_conn::sock.

Referenced by lo_lseek64(), lo_read(), lo_tell64(), and PQfn().

◆ pqPacketSend()

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

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

5469{
5470 /* Start the message. */
5472 return STATUS_ERROR;
5473
5474 /* Send the message body. */
5475 if (pqPutnchar(buf, buf_len, conn))
5476 return STATUS_ERROR;
5477
5478 /* Finish the message. */
5479 if (pqPutMsgEnd(conn))
5480 return STATUS_ERROR;
5481
5482 /* Flush to ensure backend gets it. */
5483 if (pqFlush(conn))
5484 return STATUS_ERROR;
5485
5486 return STATUS_OK;
5487}
#define STATUS_OK
Definition c.h:1298
#define STATUS_ERROR
Definition c.h:1299

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

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

◆ pqParseDone()

void pqParseDone ( PGconn conn,
int  newInStart 
)
extern

Definition at line 445 of file fe-misc.c.

446{
447 /* trace server-to-client message */
448 if (conn->Pfdebug)
450
451 /* Mark message as done */
453}
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
Definition fe-trace.c:625

References conn, fb(), pg_conn::inBuffer, pg_conn::inStart, pg_conn::Pfdebug, and pqTraceOutputMessage().

Referenced by getCopyDataMessage(), PQconnectPoll(), pqFunctionCall3(), pqGetCopyData3(), and pqParseInput3().

◆ pqParseInput3()

void pqParseInput3 ( PGconn conn)
extern

Definition at line 71 of file fe-protocol3.c.

72{
73 char id;
74 int msgLength;
75 int avail;
76
77 /*
78 * Loop to parse successive complete messages available in the buffer.
79 */
80 for (;;)
81 {
82 /*
83 * Try to read a message. First get the type code and length. Return
84 * if not enough data.
85 */
87 if (pqGetc(&id, conn))
88 return;
89 if (pqGetInt(&msgLength, 4, conn))
90 return;
91
92 /*
93 * Try to validate message type/length here. A length less than 4 is
94 * definitely broken. Large lengths should only be believed for a few
95 * message types.
96 */
97 if (msgLength < 4)
98 {
100 return;
101 }
102 if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
103 {
105 return;
106 }
107
108 /*
109 * Can't process if message body isn't all here yet.
110 */
111 msgLength -= 4;
112 avail = conn->inEnd - conn->inCursor;
113 if (avail < msgLength)
114 {
115 /*
116 * Before returning, enlarge the input buffer if needed to hold
117 * the whole message. This is better than leaving it to
118 * pqReadData because we can avoid multiple cycles of realloc()
119 * when the message is large; also, we can implement a reasonable
120 * recovery strategy if we are unable to make the buffer big
121 * enough.
122 */
124 conn))
125 {
126 /*
127 * Abandon the connection. There's not much else we can
128 * safely do; we can't just ignore the message or we could
129 * miss important changes to the connection state.
130 * pqCheckInBufferSpace() already reported the error.
131 */
133 }
134 return;
135 }
136
137 /*
138 * NOTIFY and NOTICE messages can happen in any state; always process
139 * them right away.
140 *
141 * Most other messages should only be processed while in BUSY state.
142 * (In particular, in READY state we hold off further parsing until
143 * the application collects the current PGresult.)
144 *
145 * However, if the state is IDLE then we got trouble; we need to deal
146 * with the unexpected message somehow.
147 *
148 * ParameterStatus ('S') messages are a special case: in IDLE state we
149 * must process 'em (this case could happen if a new value was adopted
150 * from config file due to SIGHUP), but otherwise we hold off until
151 * BUSY state.
152 */
154 {
155 if (getNotify(conn))
156 return;
157 }
158 else if (id == PqMsg_NoticeResponse)
159 {
160 if (pqGetErrorNotice3(conn, false))
161 return;
162 }
163 else if (conn->asyncStatus != PGASYNC_BUSY)
164 {
165 /* If not IDLE state, just wait ... */
167 return;
168
169 /*
170 * Unexpected message in IDLE state; need to recover somehow.
171 * ERROR messages are handled using the notice processor;
172 * ParameterStatus is handled normally; anything else is just
173 * dropped on the floor after displaying a suitable warning
174 * notice. (An ERROR is very possibly the backend telling us why
175 * it is about to close the connection, so we don't want to just
176 * discard it...)
177 */
178 if (id == PqMsg_ErrorResponse)
179 {
180 if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
181 return;
182 }
183 else if (id == PqMsg_ParameterStatus)
184 {
186 return;
187 }
188 else
189 {
190 /* Any other case is unexpected and we summarily skip it */
192 "message type 0x%02x arrived from server while idle",
193 id);
194 /* Discard the unexpected message */
196 }
197 }
198 else
199 {
200 /*
201 * In BUSY state, we can process everything.
202 */
203 switch (id)
204 {
206 if (pqGets(&conn->workBuffer, conn))
207 return;
209 {
212 if (!conn->result)
213 {
214 libpq_append_conn_error(conn, "out of memory");
216 }
217 }
218 if (conn->result)
222 break;
224 if (pqGetErrorNotice3(conn, true))
225 return;
227 break;
230 return;
232 {
235 if (!conn->result)
236 {
237 libpq_append_conn_error(conn, "out of memory");
239 }
240 else
241 {
244 }
245 }
246 else
247 {
248 /* Advance the command queue and set us idle */
249 pqCommandQueueAdvance(conn, true, false);
251 }
252 break;
255 {
258 if (!conn->result)
259 {
260 libpq_append_conn_error(conn, "out of memory");
262 }
263 }
265 break;
267 /* If we're doing PQprepare, we're done; else ignore */
268 if (conn->cmd_queue_head &&
270 {
272 {
275 if (!conn->result)
276 {
277 libpq_append_conn_error(conn, "out of memory");
279 }
280 }
282 }
283 break;
285 /* Nothing to do for this message type */
286 break;
288 /* If we're doing PQsendClose, we're done; else ignore */
289 if (conn->cmd_queue_head &&
291 {
293 {
296 if (!conn->result)
297 {
298 libpq_append_conn_error(conn, "out of memory");
300 }
301 }
303 }
304 break;
307 return;
308 break;
310
311 /*
312 * This is expected only during backend startup, but it's
313 * just as easy to handle it as part of the main loop.
314 * Save the data and continue processing.
315 */
317 return;
318 break;
320 if (conn->error_result ||
321 (conn->result != NULL &&
323 {
324 /*
325 * We've already choked for some reason. Just discard
326 * the data till we get to the end of the query.
327 */
329 }
330 else if (conn->result == NULL ||
333 {
334 /* First 'T' in a query sequence */
336 return;
337 }
338 else
339 {
340 /*
341 * A new 'T' message is treated as the start of
342 * another PGresult. (It is not clear that this is
343 * really possible with the current backend.) We stop
344 * parsing until the application accepts the current
345 * result.
346 */
348 return;
349 }
350 break;
351 case PqMsg_NoData:
352
353 /*
354 * NoData indicates that we will not be seeing a
355 * RowDescription message because the statement or portal
356 * inquired about doesn't return rows.
357 *
358 * If we're doing a Describe, we have to pass something
359 * back to the client, so set up a COMMAND_OK result,
360 * instead of PGRES_TUPLES_OK. Otherwise we can just
361 * ignore this message.
362 */
363 if (conn->cmd_queue_head &&
365 {
367 {
370 if (!conn->result)
371 {
372 libpq_append_conn_error(conn, "out of memory");
374 }
375 }
377 }
378 break;
381 return;
382 break;
383 case PqMsg_DataRow:
384 if (conn->result != NULL &&
387 {
388 /* Read another tuple of a normal query response */
390 return;
391 }
392 else if (conn->error_result ||
393 (conn->result != NULL &&
395 {
396 /*
397 * We've already choked for some reason. Just discard
398 * tuples till we get to the end of the query.
399 */
401 }
402 else
403 {
404 /* Set up to report error at end of query */
405 libpq_append_conn_error(conn, "server sent data (\"D\" message) without prior row description (\"T\" message)");
407 /* Discard the unexpected message */
409 }
410 break;
413 return;
415 break;
418 return;
421 break;
424 return;
427 break;
428 case PqMsg_CopyData:
429
430 /*
431 * If we see Copy Data, just silently drop it. This would
432 * only occur if application exits COPY OUT mode too
433 * early.
434 */
436 break;
437 case PqMsg_CopyDone:
438
439 /*
440 * If we see Copy Done, just silently drop it. This is
441 * the normal case during PQendcopy. We will keep
442 * swallowing data, expecting to see command-complete for
443 * the COPY command.
444 */
445 break;
446 default:
447 libpq_append_conn_error(conn, "unexpected response from server; first received character was \"%c\"", id);
448 /* build an error result holding the error message */
450 /* not sure if we will see more, so go to ready state */
452 /* Discard the unexpected message */
454 break;
455 } /* switch on protocol character */
456 }
457 /* Successfully consumed this message */
458 if (conn->inCursor == conn->inStart + 5 + msgLength)
459 {
460 /* Normal case: parsing agrees with specified length */
462 }
463 else if (conn->error_result && conn->status == CONNECTION_BAD)
464 {
465 /* The connection was abandoned and we already reported it */
466 return;
467 }
468 else
469 {
470 /* Trouble --- report it */
471 libpq_append_conn_error(conn, "message contents do not agree with length in message type \"%c\"", id);
472 /* build an error result holding the error message */
475 /* trust the specified message length as what to skip */
476 conn->inStart += 5 + msgLength;
477 }
478 }
479}
void pqCommandQueueAdvance(PGconn *conn, bool isReadyForQuery, bool gotSync)
Definition fe-exec.c:3173
static int getAnotherTuple(PGconn *conn, int msgLength)
static int getRowDescriptions(PGconn *conn, int msgLength)
static int getCopyStart(PGconn *conn, ExecStatusType copytype)
static int getBackendKeyData(PGconn *conn, int msgLength)
static int getParamDescriptions(PGconn *conn, int msgLength)
@ PGRES_COPY_IN
Definition libpq-fe.h:138
@ PGRES_COPY_BOTH
Definition libpq-fe.h:143
@ PGRES_TUPLES_CHUNK
Definition libpq-fe.h:148
@ PGRES_COPY_OUT
Definition libpq-fe.h:137
@ PGRES_PIPELINE_SYNC
Definition libpq-fe.h:145
@ PGRES_TUPLES_OK
Definition libpq-fe.h:134
@ PQ_PIPELINE_ON
Definition libpq-fe.h:194
#define CMDSTATUS_LEN
Definition libpq-int.h:83
#define PqMsg_CloseComplete
Definition protocol.h:40
#define PqMsg_BindComplete
Definition protocol.h:39
#define PqMsg_CopyData
Definition protocol.h:65
#define PqMsg_ParameterDescription
Definition protocol.h:58
#define PqMsg_CopyInResponse
Definition protocol.h:45
#define PqMsg_EmptyQueryResponse
Definition protocol.h:47
#define PqMsg_RowDescription
Definition protocol.h:52
#define PqMsg_CopyBothResponse
Definition protocol.h:54
#define PqMsg_NoData
Definition protocol.h:56
#define PqMsg_BackendKeyData
Definition protocol.h:48
#define PqMsg_CommandComplete
Definition protocol.h:42
#define PqMsg_DataRow
Definition protocol.h:43
#define PqMsg_CopyOutResponse
Definition protocol.h:46
#define PqMsg_ParseComplete
Definition protocol.h:38
char cmdStatus[CMDSTATUS_LEN]
Definition libpq-int.h:176

References pg_conn::asyncStatus, pg_conn::cmd_queue_head, pg_result::cmdStatus, CMDSTATUS_LEN, conn, CONNECTION_BAD, pg_conn::copy_already_done, PQExpBufferData::data, pg_conn::error_result, fb(), getAnotherTuple(), getBackendKeyData(), getCopyStart(), getNotify(), getParamDescriptions(), getParameterStatus(), getReadyForQuery(), getRowDescriptions(), handleFatalError(), handleSyncLoss(), pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, libpq_append_conn_error(), pg_conn::noticeHooks, PGASYNC_BUSY, PGASYNC_COPY_BOTH, PGASYNC_COPY_IN, PGASYNC_COPY_OUT, PGASYNC_IDLE, PGASYNC_READY, pgHavePendingResult, PGQUERY_CLOSE, PGQUERY_DESCRIBE, PGQUERY_PREPARE, PGRES_COMMAND_OK, PGRES_COPY_BOTH, PGRES_COPY_IN, PGRES_COPY_OUT, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PGRES_PIPELINE_SYNC, PGRES_TUPLES_CHUNK, PGRES_TUPLES_OK, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PQ_PIPELINE_ON, pqCheckInBufferSpace(), pqCommandQueueAdvance(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGets(), pqInternalNotice(), PQmakeEmptyPGresult(), PqMsg_BackendKeyData, PqMsg_BindComplete, PqMsg_CloseComplete, PqMsg_CommandComplete, PqMsg_CopyBothResponse, PqMsg_CopyData, PqMsg_CopyDone, PqMsg_CopyInResponse, PqMsg_CopyOutResponse, PqMsg_DataRow, PqMsg_EmptyQueryResponse, PqMsg_ErrorResponse, PqMsg_NoData, PqMsg_NoticeResponse, PqMsg_NotificationResponse, PqMsg_ParameterDescription, PqMsg_ParameterStatus, PqMsg_ParseComplete, PqMsg_ReadyForQuery, PqMsg_RowDescription, pqParseDone(), pqSaveErrorResult(), PGcmdQueueEntry::queryclass, pg_conn::result, pg_result::resultStatus, pg_conn::status, strlcpy(), VALID_LONG_MESSAGE_TYPE, and pg_conn::workBuffer.

Referenced by parseInput().

◆ pqParseIntParam()

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

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

8330{
8331 char *end;
8332 long numval;
8333
8334 Assert(value != NULL);
8335
8336 *result = 0;
8337
8338 /* strtol(3) skips leading whitespaces */
8339 errno = 0;
8340 numval = strtol(value, &end, 10);
8341
8342 /*
8343 * If no progress was done during the parsing or an error happened, fail.
8344 * This tests properly for overflows of the result.
8345 */
8346 if (value == end || errno != 0 || numval != (int) numval)
8347 goto error;
8348
8349 /*
8350 * Skip any trailing whitespace; if anything but whitespace remains before
8351 * the terminating character, fail
8352 */
8353 while (*end != '\0' && isspace((unsigned char) *end))
8354 end++;
8355
8356 if (*end != '\0')
8357 goto error;
8358
8359 *result = numval;
8360 return true;
8361
8362error:
8363 libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
8364 value, context);
8365 return false;
8366}
static struct @175 value
static void error(void)

References Assert, conn, error(), fb(), libpq_append_conn_error(), result, and value.

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

◆ pqPrepareAsyncResult()

PGresult * pqPrepareAsyncResult ( PGconn conn)
extern

Definition at line 857 of file fe-exec.c.

858{
859 PGresult *res;
860
861 res = conn->result;
862 if (res)
863 {
864 /*
865 * If the pre-existing result is an ERROR (presumably something
866 * received from the server), assume that it represents whatever is in
867 * conn->errorMessage, and advance errorReported.
868 */
871 }
872 else
873 {
874 /*
875 * We get here after internal-to-libpq errors. We should probably
876 * always have error_result = true, but if we don't, gin up some error
877 * text.
878 */
879 if (!conn->error_result)
880 libpq_append_conn_error(conn, "no error text available");
881
882 /* Paranoia: be sure errorReported offset is sane */
883 if (conn->errorReported < 0 ||
885 conn->errorReported = 0;
886
887 /*
888 * Make a PGresult struct for the error. We temporarily lie about the
889 * result status, so that PQmakeEmptyPGresult doesn't uselessly copy
890 * all of conn->errorMessage.
891 */
893 if (res)
894 {
895 /*
896 * Report whatever new error text we have, and advance
897 * errorReported.
898 */
902 }
903 else
904 {
905 /*
906 * Ouch, not enough memory for a PGresult. Fortunately, we have a
907 * card up our sleeve: we can use the static OOM_result. Casting
908 * away const here is a bit ugly, but it seems best to declare
909 * OOM_result as const, in hopes it will be allocated in read-only
910 * storage.
911 */
912 res = unconstify(PGresult *, &OOM_result);
913
914 /*
915 * Don't advance errorReported. Perhaps we'll be able to report
916 * the text later.
917 */
918 }
919 }
920
921 /*
922 * Replace conn->result with saved_result, if any. In the normal case
923 * there isn't a saved result and we're just dropping ownership of the
924 * current result. In partial-result mode this restores the situation to
925 * what it was before we created the current partial result.
926 */
928 conn->error_result = false; /* saved_result is never an error */
930
931 return res;
932}
static const PGresult OOM_result
Definition fe-exec.c:50
int errorReported
Definition libpq-int.h:687

References conn, pg_conn::error_result, pg_conn::errorMessage, pg_conn::errorReported, fb(), PQExpBufferData::len, libpq_append_conn_error(), OOM_result, PGRES_EMPTY_QUERY, PGRES_FATAL_ERROR, PQmakeEmptyPGresult(), pqSetResultError(), pg_conn::result, pg_result::resultStatus, pg_conn::saved_result, and unconstify.

Referenced by getCopyResult(), pqFunctionCall3(), and PQgetResult().

◆ pqPutc()

int pqPutc ( char  c,
PGconn conn 
)
extern

Definition at line 94 of file fe-misc.c.

95{
96 if (pqPutMsgBytes(&c, 1, conn))
97 return EOF;
98
99 return 0;
100}
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
Definition fe-misc.c:511
char * c

References conn, fb(), and pqPutMsgBytes().

Referenced by PQsendQueryGuts(), and PQsendTypedCommand().

◆ pqPutInt()

int pqPutInt ( int  value,
size_t  bytes,
PGconn conn 
)
extern

Definition at line 255 of file fe-misc.c.

256{
257 uint16 tmp2;
258 uint32 tmp4;
259
260 switch (bytes)
261 {
262 case 2:
264 if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
265 return EOF;
266 break;
267 case 4:
269 if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
270 return EOF;
271 break;
272 default:
274 "integer of size %zu not supported by pqPutInt",
275 bytes);
276 return EOF;
277 }
278
279 return 0;
280}
#define pg_hton32(x)
Definition pg_bswap.h:121
#define pg_hton16(x)
Definition pg_bswap.h:120

References conn, fb(), pg_conn::noticeHooks, pg_hton16, pg_hton32, pqInternalNotice(), pqPutMsgBytes(), and value.

Referenced by pg_SASL_init(), pqFunctionCall3(), PQsendPrepare(), and PQsendQueryGuts().

◆ pqPutMsgEnd()

int pqPutMsgEnd ( PGconn conn)
extern

Definition at line 534 of file fe-misc.c.

535{
536 /* Fill in length word if needed */
537 if (conn->outMsgStart >= 0)
538 {
540
543 }
544
545 /* trace client-to-server message */
546 if (conn->Pfdebug)
547 {
550 else
553 }
554
555 /* Make message eligible to send */
557
558 /* If appropriate, try to push out some data */
559 if (conn->outCount >= 8192)
560 {
561 int toSend = conn->outCount;
562
563 /*
564 * On Unix-pipe connections, it seems profitable to prefer sending
565 * pipe-buffer-sized packets not randomly-sized ones, so retain the
566 * last partial-8K chunk in our buffer for now. On TCP connections,
567 * the advantage of that is far less clear. Moreover, it flat out
568 * isn't safe when using SSL or GSSAPI, because those code paths have
569 * API stipulations that if they fail to send all the data that was
570 * offered in the previous write attempt, we mustn't offer less data
571 * in this write attempt. The previous write attempt might've been
572 * pqFlush attempting to send everything in the buffer, so we mustn't
573 * offer less now. (Presently, we won't try to use SSL or GSSAPI on
574 * Unix connections, so those checks are just Asserts. They'll have
575 * to become part of the regular if-test if we ever change that.)
576 */
577 if (conn->raddr.addr.ss_family == AF_UNIX)
578 {
579#ifdef USE_SSL
581#endif
582#ifdef ENABLE_GSS
583 Assert(!conn->gssenc);
584#endif
585 toSend -= toSend % 8192;
586 }
587
588 if (pqSendSome(conn, toSend) < 0)
589 return EOF;
590 /* in nonblock mode, don't complain if unable to send it all */
591 }
592
593 return 0;
594}
void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
Definition fe-trace.c:843
struct sockaddr_storage addr
Definition pqcomm.h:32
int outMsgStart
Definition libpq-int.h:591
SockAddr raddr
Definition libpq-int.h:505
int outMsgEnd
Definition libpq-int.h:593

References SockAddr::addr, Assert, conn, fb(), memcpy(), pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, pg_conn::Pfdebug, pg_hton32, pqSendSome(), pqTraceOutputMessage(), pqTraceOutputNoTypeByteMessage(), pg_conn::raddr, and pg_conn::ssl_in_use.

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall3(), pqPacketSend(), pqPipelineSyncInternal(), PQputCopyData(), PQputCopyEnd(), PQsendCancelRequest(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), PQsendTypedCommand(), and sendTerminateConn().

◆ pqPutMsgStart()

int pqPutMsgStart ( char  msg_type,
PGconn conn 
)
extern

Definition at line 475 of file fe-misc.c.

476{
477 int lenPos;
478 int endPos;
479
480 /* allow room for message type byte */
481 if (msg_type)
482 endPos = conn->outCount + 1;
483 else
485
486 /* do we want a length word? */
487 lenPos = endPos;
488 /* allow room for message length */
489 endPos += 4;
490
491 /* make sure there is room for message header */
493 return EOF;
494 /* okay, save the message type byte if any */
495 if (msg_type)
497 /* set up the message pointers */
500 /* length word, if needed, will be filled in by pqPutMsgEnd */
501
502 return 0;
503}
int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
Definition fe-misc.c:289

References conn, fb(), pg_conn::outBuffer, pg_conn::outCount, pg_conn::outMsgEnd, pg_conn::outMsgStart, and pqCheckOutBufferSpace().

Referenced by pg_SASL_init(), pqEndcopy3(), pqFunctionCall3(), pqPacketSend(), pqPipelineSyncInternal(), PQputCopyData(), PQputCopyEnd(), PQsendCancelRequest(), PQsendFlushRequest(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), PQsendTypedCommand(), and sendTerminateConn().

◆ pqPutnchar()

int pqPutnchar ( const void s,
size_t  len,
PGconn conn 
)
extern

Definition at line 204 of file fe-misc.c.

205{
206 if (pqPutMsgBytes(s, len, conn))
207 return EOF;
208
209 return 0;
210}

References conn, fb(), len, and pqPutMsgBytes().

Referenced by pg_SASL_init(), pqFunctionCall3(), pqPacketSend(), PQputCopyData(), PQsendCancelRequest(), and PQsendQueryGuts().

◆ pqPuts()

int pqPuts ( const char s,
PGconn conn 
)
extern

Definition at line 154 of file fe-misc.c.

155{
156 if (pqPutMsgBytes(s, strlen(s) + 1, conn))
157 return EOF;
158
159 return 0;
160}

References conn, fb(), and pqPutMsgBytes().

Referenced by pg_SASL_init(), PQputCopyEnd(), PQsendPrepare(), PQsendQueryGuts(), PQsendQueryInternal(), and PQsendTypedCommand().

◆ pqReadData()

int pqReadData ( PGconn conn)
extern

Definition at line 615 of file fe-misc.c.

616{
617 int available;
618
619 if (conn->sock == PGINVALID_SOCKET)
620 {
621 libpq_append_conn_error(conn, "connection not open");
622 return -1;
623 }
624
626 if (available < 0)
627 return -1;
628 else if (available > 0)
629 {
630 /*
631 * Make sure there are no bytes stuck in layers between conn->inBuffer
632 * and the socket, to make it safe for clients to poll on PQsocket().
633 */
634 if (pqDrainPending(conn))
635 return -1;
636 }
637 else
638 {
639 /*
640 * If we're not returning any bytes from the underlying transport,
641 * that must imply there aren't any in the transport buffer...
642 */
644 }
645
646 return available;
647}
static int pqReadData_internal(PGconn *conn)
Definition fe-misc.c:654
static int pqDrainPending(PGconn *conn)
Definition fe-misc.c:916
ssize_t pqsecure_bytes_pending(PGconn *conn)
Definition fe-secure.c:255

References Assert, conn, fb(), libpq_append_conn_error(), PGINVALID_SOCKET, pqDrainPending(), pqReadData_internal(), pqsecure_bytes_pending(), and pg_conn::sock.

Referenced by PQcancelPoll(), PQconnectPoll(), PQconsumeInput(), pqFunctionCall3(), pqGetCopyData3(), pqGetline3(), PQgetResult(), and pqSendSome().

◆ pqReadReady()

int pqReadReady ( PGconn conn)
extern

Definition at line 1204 of file fe-misc.c.

1205{
1206 return pqSocketCheck(conn, 1, 0, 0);
1207}
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, pg_usec_time_t end_time)
Definition fe-misc.c:1229

References conn, and pqSocketCheck().

Referenced by gss_read(), and pqReadData_internal().

◆ pqReleaseConnHosts()

void pqReleaseConnHosts ( PGconn conn)
extern

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

5196{
5197 if (conn->connhost)
5198 {
5199 for (int i = 0; i < conn->nconnhost; ++i)
5200 {
5201 free(conn->connhost[i].host);
5203 free(conn->connhost[i].port);
5204 if (conn->connhost[i].password != NULL)
5205 {
5209 }
5210 }
5211 free(conn->connhost);
5212 conn->connhost = NULL;
5213 }
5214}
void explicit_bzero(void *buf, size_t len)

References conn, pg_conn::connhost, explicit_bzero(), fb(), 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().

◆ pqResultAlloc()

void * pqResultAlloc ( PGresult res,
size_t  nBytes,
bool  isBinary 
)
extern

Definition at line 564 of file fe-exec.c.

565{
566 char *space;
567 PGresult_data *block;
568
569 if (!res)
570 return NULL;
571
572 if (nBytes <= 0)
573 return res->null_field;
574
575 /*
576 * If alignment is needed, round up the current position to an alignment
577 * boundary.
578 */
579 if (isBinary)
580 {
581 int offset = res->curOffset % PGRESULT_ALIGN_BOUNDARY;
582
583 if (offset)
584 {
585 res->curOffset += PGRESULT_ALIGN_BOUNDARY - offset;
586 res->spaceLeft -= PGRESULT_ALIGN_BOUNDARY - offset;
587 }
588 }
589
590 /* If there's enough space in the current block, no problem. */
591 if (nBytes <= (size_t) res->spaceLeft)
592 {
593 space = res->curBlock->space + res->curOffset;
594 res->curOffset += nBytes;
595 res->spaceLeft -= nBytes;
596 return space;
597 }
598
599 /*
600 * If the requested object is very large, give it its own block; this
601 * avoids wasting what might be most of the current block to start a new
602 * block. (We'd have to special-case requests bigger than the block size
603 * anyway.) The object is always given binary alignment in this case.
604 */
606 {
607 size_t alloc_size;
608
609 /* Don't wrap around with overly large requests. */
611 return NULL;
612
614 block = (PGresult_data *) malloc(alloc_size);
615 if (!block)
616 return NULL;
617 res->memorySize += alloc_size;
618 space = block->space + PGRESULT_BLOCK_OVERHEAD;
619 if (res->curBlock)
620 {
621 /*
622 * Tuck special block below the active block, so that we don't
623 * have to waste the free space in the active block.
624 */
625 block->next = res->curBlock->next;
626 res->curBlock->next = block;
627 }
628 else
629 {
630 /* Must set up the new block as the first active block. */
631 block->next = NULL;
632 res->curBlock = block;
633 res->spaceLeft = 0; /* be sure it's marked full */
634 }
635 return space;
636 }
637
638 /* Otherwise, start a new block. */
640 if (!block)
641 return NULL;
643 block->next = res->curBlock;
644 res->curBlock = block;
645 if (isBinary)
646 {
647 /* object needs full alignment */
650 }
651 else
652 {
653 /* we can cram it right after the overhead pointer */
654 res->curOffset = sizeof(PGresult_data);
656 }
657
658 space = block->space + res->curOffset;
659 res->curOffset += nBytes;
660 res->spaceLeft -= nBytes;
661 return space;
662}
#define PGRESULT_DATA_BLOCKSIZE
Definition fe-exec.c:143
#define PGRESULT_BLOCK_OVERHEAD
Definition fe-exec.c:145
#define PGRESULT_SEP_ALLOC_THRESHOLD
Definition fe-exec.c:146
#define PGRESULT_ALIGN_BOUNDARY
Definition fe-exec.c:144
union pgresult_data PGresult_data
Definition libpq-int.h:99
size_t memorySize
Definition libpq-int.h:210
int curOffset
Definition libpq-int.h:207
char null_field[1]
Definition libpq-int.h:199
int spaceLeft
Definition libpq-int.h:208
PGresult_data * curBlock
Definition libpq-int.h:206
PGresult_data * next
Definition libpq-int.h:103
char space[1]
Definition libpq-int.h:104

References pg_result::curBlock, pg_result::curOffset, fb(), malloc, pg_result::memorySize, pgresult_data::next, pg_result::null_field, PGRESULT_ALIGN_BOUNDARY, PGRESULT_BLOCK_OVERHEAD, PGRESULT_DATA_BLOCKSIZE, PGRESULT_SEP_ALLOC_THRESHOLD, pgresult_data::space, and pg_result::spaceLeft.

Referenced by getCopyStart(), getParamDescriptions(), getRowDescriptions(), pqInternalNotice(), PQresultAlloc(), pqResultStrdup(), pqRowProcessor(), pqSaveMessageField(), and PQsetvalue().

◆ pqResultStrdup()

char * pqResultStrdup ( PGresult res,
const char str 
)
extern

Definition at line 681 of file fe-exec.c.

682{
683 char *space = (char *) pqResultAlloc(res, strlen(str) + 1, false);
684
685 if (space)
686 strcpy(space, str);
687 return space;
688}
void * pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
Definition fe-exec.c:564
const char * str

References fb(), pqResultAlloc(), and str.

Referenced by getRowDescriptions(), pqGetErrorNotice3(), PQsetResultAttrs(), and pqSetResultError().

◆ pqRowProcessor()

int pqRowProcessor ( PGconn conn,
const char **  errmsgp 
)
extern

Definition at line 1223 of file fe-exec.c.

1224{
1225 PGresult *res = conn->result;
1226 int nfields = res->numAttributes;
1227 const PGdataValue *columns = conn->rowBuf;
1229 int i;
1230
1231 /*
1232 * In partial-result mode, if we don't already have a partial PGresult
1233 * then make one by cloning conn->result (which should hold the correct
1234 * result metadata by now). Then the original conn->result is moved over
1235 * to saved_result so that we can re-use it as a reference for future
1236 * partial results. The saved result will become active again after
1237 * pqPrepareAsyncResult() returns the partial result to the application.
1238 */
1240 {
1241 /* Copy everything that should be in the result at this point */
1242 res = PQcopyResult(res,
1245 if (!res)
1246 return 0;
1247 /* Change result status to appropriate special value */
1249 /* And stash it as the active result */
1251 conn->result = res;
1252 }
1253
1254 /*
1255 * Basically we just allocate space in the PGresult for each field and
1256 * copy the data over.
1257 *
1258 * Note: on malloc failure, we return 0 leaving *errmsgp still NULL, which
1259 * caller will take to mean "out of memory". This is preferable to trying
1260 * to set up such a message here, because evidently there's not enough
1261 * memory for gettext() to do anything.
1262 */
1263 tup = (PGresAttValue *)
1264 pqResultAlloc(res, nfields * sizeof(PGresAttValue), true);
1265 if (tup == NULL)
1266 return 0;
1267
1268 for (i = 0; i < nfields; i++)
1269 {
1270 int clen = columns[i].len;
1271
1272 if (clen < 0)
1273 {
1274 /* null field */
1275 tup[i].len = NULL_LEN;
1276 tup[i].value = res->null_field;
1277 }
1278 else
1279 {
1280 bool isbinary = (res->attDescs[i].format != 0);
1281 char *val;
1282
1283 val = (char *) pqResultAlloc(res, (size_t) clen + 1, isbinary);
1284 if (val == NULL)
1285 return 0;
1286
1287 /* copy and zero-terminate the data (even if it's binary) */
1288 memcpy(val, columns[i].value, clen);
1289 val[clen] = '\0';
1290
1291 tup[i].len = clen;
1292 tup[i].value = val;
1293 }
1294 }
1295
1296 /* And add the tuple to the PGresult's tuple array */
1297 if (!pqAddTuple(res, tup, errmsgp))
1298 return 0;
1299
1300 /*
1301 * Success. In partial-result mode, if we have enough rows then make the
1302 * result available to the client immediately.
1303 */
1304 if (conn->partialResMode && res->ntups >= conn->maxChunkSize)
1306
1307 return 1;
1308}
PGresult * PQcopyResult(const PGresult *src, int flags)
Definition fe-exec.c:319
static bool pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp)
Definition fe-exec.c:999
@ PGRES_SINGLE_TUPLE
Definition libpq-fe.h:144
#define PG_COPYRES_ATTRS
Definition libpq-fe.h:75
#define PG_COPYRES_EVENTS
Definition libpq-fe.h:77
#define PG_COPYRES_NOTICEHOOKS
Definition libpq-fe.h:78
#define NULL_LEN
Definition libpq-int.h:131
int maxChunkSize
Definition libpq-int.h:475
bool singleRowMode
Definition libpq-int.h:474
bool partialResMode
Definition libpq-int.h:473
PGresAttDesc * attDescs
Definition libpq-int.h:169
int numAttributes
Definition libpq-int.h:168

References pg_conn::asyncStatus, pg_result::attDescs, conn, fb(), pgresAttDesc::format, i, pgDataValue::len, pg_conn::maxChunkSize, memcpy(), pg_result::ntups, pg_result::null_field, NULL_LEN, pg_result::numAttributes, pg_conn::partialResMode, PG_COPYRES_ATTRS, PG_COPYRES_EVENTS, PG_COPYRES_NOTICEHOOKS, PGASYNC_READY_MORE, PGRES_SINGLE_TUPLE, PGRES_TUPLES_CHUNK, pqAddTuple(), PQcopyResult(), pqResultAlloc(), pg_conn::result, pg_result::resultStatus, pg_conn::rowBuf, pg_conn::saved_result, pg_conn::singleRowMode, val, and value.

Referenced by getAnotherTuple().

◆ pqSaveErrorResult()

void pqSaveErrorResult ( PGconn conn)
extern

Definition at line 809 of file fe-exec.c.

810{
811 /* Drop any pending result ... */
813 /* ... and set flag to remember to make an error result later */
814 conn->error_result = true;
815}

References conn, pg_conn::error_result, and pqClearAsyncResult().

Referenced by getAnotherTuple(), getCopyResult(), getParamDescriptions(), getRowDescriptions(), handleFatalError(), pqFunctionCall3(), pqGetNegotiateProtocolVersion3(), PQgetResult(), pqParseInput3(), pqPipelineProcessQueue(), and pqSaveWriteError().

◆ pqSaveMessageField()

void void pqSaveMessageField ( PGresult res,
char  code,
const char value 
)
extern

Definition at line 1066 of file fe-exec.c.

1067{
1069
1071 pqResultAlloc(res,
1072 offsetof(PGMessageField, contents) +
1073 strlen(value) + 1,
1074 true);
1075 if (!pfield)
1076 return; /* out of memory? */
1077 pfield->code = code;
1078 strcpy(pfield->contents, value);
1079 pfield->next = res->errFields;
1080 res->errFields = pfield;
1081}

References pgMessageField::code, pg_result::errFields, fb(), pqResultAlloc(), and value.

Referenced by pqGetErrorNotice3(), and pqInternalNotice().

◆ pqSaveParameterStatus()

int pqSaveParameterStatus ( PGconn conn,
const char name,
const char value 
)
extern

Definition at line 1091 of file fe-exec.c.

1092{
1093 pgParameterStatus *pstatus;
1094 pgParameterStatus *prev;
1095
1096 /*
1097 * Forget any old information about the parameter
1098 */
1099 for (pstatus = conn->pstatus, prev = NULL;
1100 pstatus != NULL;
1101 prev = pstatus, pstatus = pstatus->next)
1102 {
1103 if (strcmp(pstatus->name, name) == 0)
1104 {
1105 if (prev)
1106 prev->next = pstatus->next;
1107 else
1108 conn->pstatus = pstatus->next;
1109 free(pstatus); /* frees name and value strings too */
1110 break;
1111 }
1112 }
1113
1114 /*
1115 * Store new info as a single malloc block
1116 */
1117 pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) +
1118 strlen(name) + strlen(value) + 2);
1119 if (pstatus)
1120 {
1121 char *ptr;
1122
1123 ptr = ((char *) pstatus) + sizeof(pgParameterStatus);
1124 pstatus->name = ptr;
1125 strcpy(ptr, name);
1126 ptr += strlen(name) + 1;
1127 pstatus->value = ptr;
1128 strcpy(ptr, value);
1129 pstatus->next = conn->pstatus;
1130 conn->pstatus = pstatus;
1131 }
1132 else
1133 {
1134 /* out of memory */
1135 return 0;
1136 }
1137
1138 /*
1139 * Save values of settings that are of interest to libpq in fields of the
1140 * PGconn object. We keep client_encoding and standard_conforming_strings
1141 * in static variables as well, so that PQescapeString and PQescapeBytea
1142 * can behave somewhat sanely (at least in single-connection-using
1143 * programs).
1144 */
1145 if (strcmp(name, "client_encoding") == 0)
1146 {
1148 /* if we don't recognize the encoding name, fall back to SQL_ASCII */
1149 if (conn->client_encoding < 0)
1152 }
1153 else if (strcmp(name, "standard_conforming_strings") == 0)
1154 {
1155 conn->std_strings = (strcmp(value, "on") == 0);
1157 }
1158 else if (strcmp(name, "server_version") == 0)
1159 {
1160 /* We convert the server version to numeric form. */
1161 int cnt;
1162 int vmaj,
1163 vmin,
1164 vrev;
1165
1166 cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
1167
1168 if (cnt == 3)
1169 {
1170 /* old style, e.g. 9.6.1 */
1171 conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
1172 }
1173 else if (cnt == 2)
1174 {
1175 if (vmaj >= 10)
1176 {
1177 /* new style, e.g. 10.1 */
1178 conn->sversion = 100 * 100 * vmaj + vmin;
1179 }
1180 else
1181 {
1182 /* old style without minor version, e.g. 9.6devel */
1183 conn->sversion = (100 * vmaj + vmin) * 100;
1184 }
1185 }
1186 else if (cnt == 1)
1187 {
1188 /* new style without minor version, e.g. 10devel */
1189 conn->sversion = 100 * 100 * vmaj;
1190 }
1191 else
1192 conn->sversion = 0; /* unknown */
1193 }
1194 else if (strcmp(name, "default_transaction_read_only") == 0)
1195 {
1197 (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1198 }
1199 else if (strcmp(name, "in_hot_standby") == 0)
1200 {
1202 (strcmp(value, "on") == 0) ? PG_BOOL_YES : PG_BOOL_NO;
1203 }
1204 else if (strcmp(name, "scram_iterations") == 0)
1205 {
1207 }
1208
1209 return 1;
1210}
static bool static_std_strings
Definition fe-exec.c:61
static int static_client_encoding
Definition fe-exec.c:60
@ PG_BOOL_YES
Definition oauth-utils.h:34
@ PG_BOOL_NO
Definition oauth-utils.h:35
#define pg_char_to_encoding
Definition pg_wchar.h:482
struct pgParameterStatus * next
Definition libpq-int.h:272
int sversion
Definition libpq-int.h:507
pgParameterStatus * pstatus
Definition libpq-int.h:558

References pg_conn::client_encoding, conn, pg_conn::default_transaction_read_only, fb(), free, pg_conn::in_hot_standby, malloc, name, pgParameterStatus::name, pgParameterStatus::next, PG_BOOL_NO, PG_BOOL_YES, pg_char_to_encoding, PG_SQL_ASCII, pg_conn::pstatus, pg_conn::scram_sha_256_iterations, static_client_encoding, static_std_strings, pg_conn::std_strings, pg_conn::sversion, value, and pgParameterStatus::value.

Referenced by getParameterStatus().

◆ pqsecure_bytes_pending()

ssize_t pqsecure_bytes_pending ( PGconn conn)
extern

Definition at line 255 of file fe-secure.c.

256{
257#ifdef USE_SSL
258 if (conn->ssl_in_use)
260#endif
261#ifdef ENABLE_GSS
262 if (conn->gssenc)
264#endif
265
266 /* Plaintext connections have no transport buffer. */
267 return 0;
268}
ssize_t pg_GSS_bytes_pending(PGconn *conn)
ssize_t pgtls_bytes_pending(PGconn *conn)

References conn, pg_GSS_bytes_pending(), pgtls_bytes_pending(), and pg_conn::ssl_in_use.

Referenced by pqDrainPending(), pqReadData(), and pqSocketCheck().

◆ pqsecure_close()

void pqsecure_close ( PGconn conn)
extern

Definition at line 152 of file fe-secure.c.

153{
154#ifdef USE_SSL
156#endif
157}

References conn, and pgtls_close().

Referenced by pqDropConnection().

◆ pqsecure_open_client()

PostgresPollingStatusType pqsecure_open_client ( PGconn conn)
extern

Definition at line 138 of file fe-secure.c.

139{
140#ifdef USE_SSL
141 return pgtls_open_client(conn);
142#else
143 /* shouldn't get here */
145#endif
146}
PostgresPollingStatusType pgtls_open_client(PGconn *conn)

References conn, PGRES_POLLING_FAILED, and pgtls_open_client().

Referenced by PQconnectPoll().

◆ pqsecure_raw_read()

ssize_t pqsecure_raw_read ( PGconn conn,
void ptr,
size_t  len 
)
extern

Definition at line 193 of file fe-secure.c.

194{
195 ssize_t n;
196 int result_errno = 0;
198
200
201 n = recv(conn->sock, ptr, len, 0);
202
203 if (n < 0)
204 {
206
207 /* Set error message if appropriate */
208 switch (result_errno)
209 {
210#ifdef EAGAIN
211 case EAGAIN:
212#endif
213#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
214 case EWOULDBLOCK:
215#endif
216 case EINTR:
217 /* no error message, caller is expected to retry */
218 break;
219
220 case EPIPE:
221 case ECONNRESET:
222 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
223 "\tThis probably means the server terminated abnormally\n"
224 "\tbefore or while processing the request.");
225 break;
226
227 case 0:
228 /* If errno didn't get set, treat it as regular EOF */
229 n = 0;
230 break;
231
232 default:
233 libpq_append_conn_error(conn, "could not receive data from server: %s",
235 sebuf, sizeof(sebuf)));
236 break;
237 }
238 }
239
240 /* ensure we return the intended errno to caller */
242
243 return n;
244}
#define EINTR
Definition win32_port.h:378
#define EWOULDBLOCK
Definition win32_port.h:384
#define recv(s, buf, len, flags)
Definition win32_port.h:518
#define EAGAIN
Definition win32_port.h:376

References conn, EAGAIN, ECONNRESET, EINTR, EWOULDBLOCK, fb(), len, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, recv, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, and SOCK_STRERROR.

Referenced by gss_read(), pg_GSS_read(), pgconn_bio_read(), and pqsecure_read().

◆ pqsecure_raw_write()

ssize_t pqsecure_raw_write ( PGconn conn,
const void ptr,
size_t  len 
)
extern

Definition at line 340 of file fe-secure.c.

341{
342 ssize_t n;
343 int flags = 0;
344 int result_errno = 0;
345 char msgbuf[1024];
347
349
350 /*
351 * If we already had a write failure, we will never again try to send data
352 * on that connection. Even if the kernel would let us, we've probably
353 * lost message boundary sync with the server. conn->write_failed
354 * therefore persists until the connection is reset, and we just discard
355 * all data presented to be written.
356 */
357 if (conn->write_failed)
358 return len;
359
360#ifdef MSG_NOSIGNAL
361 if (conn->sigpipe_flag)
362 flags |= MSG_NOSIGNAL;
363
365#endif /* MSG_NOSIGNAL */
366
367 DISABLE_SIGPIPE(conn, spinfo, return -1);
368
369 n = send(conn->sock, ptr, len, flags);
370
371 if (n < 0)
372 {
374
375 /*
376 * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
377 * on this machine. So, clear sigpipe_flag so we don't try the flag
378 * again, and retry the send().
379 */
380#ifdef MSG_NOSIGNAL
381 if (flags != 0 && result_errno == EINVAL)
382 {
383 conn->sigpipe_flag = false;
384 flags = 0;
385 goto retry_masked;
386 }
387#endif /* MSG_NOSIGNAL */
388
389 /* Set error message if appropriate */
390 switch (result_errno)
391 {
392#ifdef EAGAIN
393 case EAGAIN:
394#endif
395#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
396 case EWOULDBLOCK:
397#endif
398 case EINTR:
399 /* no error message, caller is expected to retry */
400 break;
401
402 case EPIPE:
403 /* Set flag for EPIPE */
404 REMEMBER_EPIPE(spinfo, true);
405
407
408 case ECONNRESET:
409 conn->write_failed = true;
410 /* Store error message in conn->write_err_msg, if possible */
411 /* (strdup failure is OK, we'll cope later) */
412 snprintf(msgbuf, sizeof(msgbuf),
413 libpq_gettext("server closed the connection unexpectedly\n"
414 "\tThis probably means the server terminated abnormally\n"
415 "\tbefore or while processing the request."));
416 /* keep newline out of translated string */
417 strlcat(msgbuf, "\n", sizeof(msgbuf));
419 /* Now claim the write succeeded */
420 n = len;
421 break;
422
423 default:
424 conn->write_failed = true;
425 /* Store error message in conn->write_err_msg, if possible */
426 /* (strdup failure is OK, we'll cope later) */
427 snprintf(msgbuf, sizeof(msgbuf),
428 libpq_gettext("could not send data to server: %s"),
430 sebuf, sizeof(sebuf)));
431 /* keep newline out of translated string */
432 strlcat(msgbuf, "\n", sizeof(msgbuf));
434 /* Now claim the write succeeded */
435 n = len;
436 break;
437 }
438 }
439
441
442 /* ensure we return the intended errno to caller */
444
445 return n;
446}
#define pg_fallthrough
Definition c.h:220
#define REMEMBER_EPIPE(spinfo, cond)
Definition fe-secure.c:77
#define DISABLE_SIGPIPE(conn, spinfo, failaction)
Definition fe-secure.c:66
#define DECLARE_SIGPIPE_INFO(spinfo)
Definition fe-secure.c:64
#define RESTORE_SIGPIPE(conn, spinfo)
Definition fe-secure.c:83
size_t strlcat(char *dst, const char *src, size_t siz)
Definition strlcat.c:34
#define EINVAL
Definition private.h:69
char * write_err_msg
Definition libpq-int.h:516
bool sigpipe_flag
Definition libpq-int.h:514
bool write_failed
Definition libpq-int.h:515
#define send(s, buf, len, flags)
Definition win32_port.h:519

References conn, DECLARE_SIGPIPE_INFO, DISABLE_SIGPIPE, EAGAIN, ECONNRESET, EINTR, EINVAL, EWOULDBLOCK, fb(), len, libpq_gettext, pg_fallthrough, PG_STRERROR_R_BUFLEN, REMEMBER_EPIPE, RESTORE_SIGPIPE, send, pg_conn::sigpipe_flag, snprintf, pg_conn::sock, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, strlcat(), pg_conn::write_err_msg, and pg_conn::write_failed.

Referenced by pg_GSS_write(), pgconn_bio_write(), pqsecure_open_gss(), and pqsecure_write().

◆ pqsecure_read()

ssize_t pqsecure_read ( PGconn conn,
void ptr,
size_t  len 
)
extern

Definition at line 167 of file fe-secure.c.

168{
169 ssize_t n;
170
171#ifdef USE_SSL
172 if (conn->ssl_in_use)
173 {
174 n = pgtls_read(conn, ptr, len);
175 }
176 else
177#endif
178#ifdef ENABLE_GSS
179 if (conn->gssenc)
180 {
181 n = pg_GSS_read(conn, ptr, len);
182 }
183 else
184#endif
185 {
186 n = pqsecure_raw_read(conn, ptr, len);
187 }
188
189 return n;
190}
ssize_t pg_GSS_read(PGconn *conn, void *ptr, size_t len)
ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len)
ssize_t pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
Definition fe-secure.c:193

References conn, fb(), len, pg_GSS_read(), pgtls_read(), pqsecure_raw_read(), and pg_conn::ssl_in_use.

Referenced by pqDrainPending(), and pqReadData_internal().

◆ pqsecure_write()

ssize_t pqsecure_write ( PGconn conn,
const void ptr,
size_t  len 
)
extern

Definition at line 291 of file fe-secure.c.

292{
293 ssize_t n;
294
295#ifdef USE_SSL
296 if (conn->ssl_in_use)
297 {
298 n = pgtls_write(conn, ptr, len);
299 }
300 else
301#endif
302#ifdef ENABLE_GSS
303 if (conn->gssenc)
304 {
305 n = pg_GSS_write(conn, ptr, len);
306 }
307 else
308#endif
309 {
310 n = pqsecure_raw_write(conn, ptr, len);
311 }
312
313 return n;
314}
ssize_t pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len)
ssize_t pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
Definition fe-secure.c:340

References conn, fb(), len, pg_GSS_write(), pgtls_write(), pqsecure_raw_write(), and pg_conn::ssl_in_use.

Referenced by pqSendSome().

◆ PQsendCancelRequest()

int PQsendCancelRequest ( PGconn cancelConn)
extern

Definition at line 472 of file fe-cancel.c.

473{
475
476 /* Start the message. */
478 return STATUS_ERROR;
479
480 /* Send the message body. */
481 memset(&req, 0, offsetof(CancelRequestPacket, cancelAuthCode));
482 req.cancelRequestCode = pg_hton32(CANCEL_REQUEST_CODE);
483 req.backendPID = pg_hton32(cancelConn->be_pid);
484 if (pqPutnchar(&req, offsetof(CancelRequestPacket, cancelAuthCode), cancelConn))
485 return STATUS_ERROR;
486 if (pqPutnchar(cancelConn->be_cancel_key, cancelConn->be_cancel_key_len, cancelConn))
487 return STATUS_ERROR;
488
489 /* Finish the message. */
491 return STATUS_ERROR;
492
493 /* Flush to ensure backend gets it. */
494 if (pqFlush(cancelConn))
495 return STATUS_ERROR;
496
497 return STATUS_OK;
498}
static PGcancel *volatile cancelConn
Definition cancel.c:73
#define CANCEL_REQUEST_CODE
Definition pqcomm.h:122
int be_pid
Definition fe-cancel.c:43

References pg_cancel::be_pid, CANCEL_REQUEST_CODE, cancelConn, fb(), pg_hton32, pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), STATUS_ERROR, and STATUS_OK.

Referenced by PQconnectPoll().

◆ PQsendQueryContinue()

int PQsendQueryContinue ( PGconn conn,
const char query 
)
extern

Definition at line 1439 of file fe-exec.c.

1440{
1441 return PQsendQueryInternal(conn, query, false);
1442}
static int PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
Definition fe-exec.c:1445

References conn, and PQsendQueryInternal().

Referenced by PQconnectPoll().

◆ pqSetResultError()

void pqSetResultError ( PGresult res,
PQExpBuffer  errorMessage,
int  offset 
)
extern

Definition at line 698 of file fe-exec.c.

699{
700 char *msg;
701
702 if (!res)
703 return;
704
705 /*
706 * We handle two OOM scenarios here. The errorMessage buffer might be
707 * marked "broken" due to having previously failed to allocate enough
708 * memory for the message, or it might be fine but pqResultStrdup fails
709 * and returns NULL. In either case, just make res->errMsg point directly
710 * at a constant "out of memory" string.
711 */
712 if (!PQExpBufferBroken(errorMessage))
713 msg = pqResultStrdup(res, errorMessage->data + offset);
714 else
715 msg = NULL;
716 if (msg)
717 res->errMsg = msg;
718 else
719 res->errMsg = libpq_gettext("out of memory\n");
720}

References PQExpBufferData::data, pg_result::errMsg, fb(), libpq_gettext, PQExpBufferBroken, and pqResultStrdup().

Referenced by pqGetErrorNotice3(), PQmakeEmptyPGresult(), and pqPrepareAsyncResult().

◆ pqSkipnchar()

int pqSkipnchar ( size_t  len,
PGconn conn 
)
extern

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

190{
191 if (len > (size_t) (conn->inEnd - conn->inCursor))
192 return EOF;
193
194 conn->inCursor += len;
195
196 return 0;
197}

References conn, fb(), pg_conn::inCursor, pg_conn::inEnd, and len.

Referenced by getAnotherTuple().

◆ pqTraceOutputCharResponse()

void pqTraceOutputCharResponse ( PGconn conn,
const char responseType,
char  response 
)
extern

Definition at line 918 of file fe-trace.c.

920{
922 {
923 char timestr[128];
924
926 fprintf(conn->Pfdebug, "%s\t", timestr);
927 }
928
929 fprintf(conn->Pfdebug, "B\t1\t%s\t %c\n", responseType, response);
930}
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
static void pqTraceFormatTimestamp(char *timestr, size_t ts_len)
Definition fe-trace.c:80
#define PQTRACE_SUPPRESS_TIMESTAMPS
Definition libpq-fe.h:495
int traceFlags
Definition libpq-int.h:454

References conn, fb(), fprintf, pg_conn::Pfdebug, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), and pg_conn::traceFlags.

Referenced by PQconnectPoll().

◆ pqTraceOutputMessage()

void pqTraceOutputMessage ( PGconn conn,
const char message,
bool  toServer 
)
extern

Definition at line 625 of file fe-trace.c.

626{
627 char id;
628 int length;
629 char *prefix = toServer ? "F" : "B";
630 int logCursor = 0;
631 bool regress;
632
634 {
635 char timestr[128];
636
638 fprintf(conn->Pfdebug, "%s\t", timestr);
639 }
641
642 id = message[logCursor++];
643
644 memcpy(&length, message + logCursor, 4);
645 length = (int) pg_ntoh32(length);
646 logCursor += 4;
647
648 /*
649 * In regress mode, suppress the length of ErrorResponse and
650 * NoticeResponse. The F (file name), L (line number) and R (routine
651 * name) fields can change as server code is modified, and if their
652 * lengths differ from the originals, that would break tests.
653 */
654 if (regress && !toServer && (id == PqMsg_ErrorResponse || id == PqMsg_NoticeResponse))
655 fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
656 else
657 fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
658
659 switch (id)
660 {
662 fprintf(conn->Pfdebug, "ParseComplete");
663 /* No message content */
664 break;
666 fprintf(conn->Pfdebug, "BindComplete");
667 /* No message content */
668 break;
670 fprintf(conn->Pfdebug, "CloseComplete");
671 /* No message content */
672 break;
675 break;
676 case PqMsg_Bind:
678 break;
679 case PqMsg_CopyDone:
680 fprintf(conn->Pfdebug, "CopyDone");
681 /* No message content */
682 break;
684 /* Close(F) and CommandComplete(B) use the same identifier. */
686 if (toServer)
688 else
690 break;
691 case PqMsg_CopyData:
693 length, regress);
694 break;
695 case PqMsg_Describe:
696 /* Describe(F) and DataRow(B) use the same identifier. */
698 if (toServer)
700 else
702 break;
703 case PqMsg_Execute:
704 /* Execute(F) and ErrorResponse(B) use the same identifier. */
706 if (toServer)
708 else
710 break;
711 case PqMsg_CopyFail:
713 break;
718
719 /*
720 * These messages share a common type byte, so we discriminate by
721 * having the code store the auth type separately.
722 */
724 {
727 &logCursor, length, regress);
728 break;
731 &logCursor);
732 break;
736 break;
739 &logCursor, length, regress);
740 break;
741 default:
742 fprintf(conn->Pfdebug, "UnknownAuthenticationResponse");
743 break;
744 }
746 break;
749 break;
752 break;
753 case PqMsg_Flush:
754 /* Flush(F) and CopyOutResponse(B) use the same identifier */
756 if (toServer)
757 fprintf(conn->Pfdebug, "Flush"); /* no message content */
758 else
760 break;
762 fprintf(conn->Pfdebug, "EmptyQueryResponse");
763 /* No message content */
764 break;
767 length, regress);
768 break;
769 case PqMsg_NoData:
770 fprintf(conn->Pfdebug, "NoData");
771 /* No message content */
772 break;
775 break;
776 case PqMsg_Parse:
778 break;
779 case PqMsg_Query:
781 break;
784 length, regress);
785 break;
787 fprintf(conn->Pfdebug, "PortalSuspended");
788 /* No message content */
789 break;
790 case PqMsg_Sync:
791 /* ParameterStatus(B) and Sync(F) use the same identifier */
793 if (toServer)
794 fprintf(conn->Pfdebug, "Sync"); /* no message content */
795 else
797 break;
800 break;
803 break;
806 break;
809 break;
812 break;
813 case PqMsg_Terminate:
814 fprintf(conn->Pfdebug, "Terminate");
815 /* No message content */
816 break;
819 break;
820 default:
821 fprintf(conn->Pfdebug, "Unknown message: %02x", id);
822 break;
823 }
824
825 fputc('\n', conn->Pfdebug);
826
827 /*
828 * Verify the printing routine did it right. Note that the one-byte
829 * message identifier is not included in the length, but our cursor does
830 * include it.
831 */
832 if (logCursor - 1 != length)
834 "mismatched message length: consumed %d, expected %d\n",
835 logCursor - 1, length);
836}
static void pqTraceOutput_RowDescription(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:560
static void pqTraceOutput_GSSResponse(FILE *f, const char *message, int *cursor, int length, bool regress)
Definition fe-trace.c:367
static void pqTraceOutput_FunctionCall(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:403
static void pqTraceOutput_CopyInResponse(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:429
static void pqTraceOutput_Authentication(FILE *f, const char *message, int *cursor, int length, bool suppress)
Definition fe-trace.c:485
static void pqTraceOutput_Parse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:464
static void pqTraceOutput_NoticeResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:346
static void pqTraceOutput_ParameterDescription(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:548
static void pqTraceOutput_DataRow(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:293
static void pqTraceOutput_SASLResponse(FILE *f, const char *message, int *cursor, int length, bool regress)
Definition fe-trace.c:395
static void pqTraceOutput_Query(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:478
static void pqTraceOutput_CopyData(FILE *f, const char *message, int *cursor, int length, bool suppress)
Definition fe-trace.c:285
static void pqTraceOutput_SASLInitialResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:382
static void pqTraceOutput_NegotiateProtocolVersion(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:580
static void pqTraceOutput_CopyBothResponse(FILE *f, const char *message, int *cursor, int length)
Definition fe-trace.c:605
static void pqTraceOutput_Bind(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:240
static void pqTraceOutput_ErrorResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:340
static void pqTraceOutput_Close(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:270
static void pqTraceOutput_Describe(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:311
static void pqTraceOutput_NotificationResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:231
static void pqTraceOutput_CommandComplete(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:278
static void pqTraceOutput_BackendKeyData(FILE *f, const char *message, int *cursor, int length, bool regress)
Definition fe-trace.c:455
static void pqTraceOutput_ParameterStatus(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:540
static void pqTraceOutput_Execute(FILE *f, const char *message, int *cursor, bool regress)
Definition fe-trace.c:352
static void pqTraceOutput_CopyOutResponse(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:442
static void pqTraceOutput_ReadyForQuery(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:615
static void pqTraceOutput_CopyFail(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:360
static void pqTraceOutput_PasswordMessage(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:375
static void pqTraceOutput_FunctionCallResponse(FILE *f, const char *message, int *cursor)
Definition fe-trace.c:594
#define PQTRACE_REGRESS_MODE
Definition libpq-fe.h:497
#define AUTH_RESPONSE_PASSWORD
Definition libpq-int.h:338
#define AUTH_RESPONSE_SASL
Definition libpq-int.h:340
#define AUTH_RESPONSE_SASL_INITIAL
Definition libpq-int.h:339
#define AUTH_RESPONSE_GSS
Definition libpq-int.h:337
#define PqMsg_GSSResponse
Definition protocol.h:30
#define PqMsg_SASLResponse
Definition protocol.h:33
#define PqMsg_Describe
Definition protocol.h:21
#define PqMsg_SASLInitialResponse
Definition protocol.h:32
#define PqMsg_AuthenticationRequest
Definition protocol.h:50
#define PqMsg_NegotiateProtocolVersion
Definition protocol.h:59
#define PqMsg_PortalSuspended
Definition protocol.h:57
#define PqMsg_Parse
Definition protocol.h:25
#define PqMsg_Bind
Definition protocol.h:19
#define PqMsg_PasswordMessage
Definition protocol.h:31
#define PqMsg_CopyFail
Definition protocol.h:29
#define PqMsg_Flush
Definition protocol.h:24
#define PqMsg_Query
Definition protocol.h:26
#define PqMsg_Terminate
Definition protocol.h:28
#define PqMsg_Execute
Definition protocol.h:22
#define PqMsg_Close
Definition protocol.h:20
char current_auth_response
Definition libpq-int.h:526

References Assert, AUTH_RESPONSE_GSS, AUTH_RESPONSE_PASSWORD, AUTH_RESPONSE_SASL, AUTH_RESPONSE_SASL_INITIAL, conn, pg_conn::current_auth_response, fb(), fprintf, memcpy(), pg_conn::Pfdebug, pg_ntoh32, PqMsg_AuthenticationRequest, PqMsg_BackendKeyData, PqMsg_Bind, PqMsg_BindComplete, PqMsg_Close, PqMsg_CloseComplete, PqMsg_CommandComplete, PqMsg_CopyBothResponse, PqMsg_CopyData, PqMsg_CopyDone, PqMsg_CopyFail, PqMsg_CopyInResponse, PqMsg_CopyOutResponse, PqMsg_DataRow, PqMsg_Describe, PqMsg_EmptyQueryResponse, PqMsg_ErrorResponse, PqMsg_Execute, PqMsg_Flush, PqMsg_FunctionCall, PqMsg_FunctionCallResponse, PqMsg_GSSResponse, PqMsg_NegotiateProtocolVersion, PqMsg_NoData, PqMsg_NoticeResponse, PqMsg_NotificationResponse, PqMsg_ParameterDescription, PqMsg_ParameterStatus, PqMsg_Parse, PqMsg_ParseComplete, PqMsg_PasswordMessage, PqMsg_PortalSuspended, PqMsg_Query, PqMsg_ReadyForQuery, PqMsg_RowDescription, PqMsg_SASLInitialResponse, PqMsg_SASLResponse, PqMsg_Sync, PqMsg_Terminate, PQTRACE_REGRESS_MODE, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), pqTraceOutput_Authentication(), pqTraceOutput_BackendKeyData(), pqTraceOutput_Bind(), pqTraceOutput_Close(), pqTraceOutput_CommandComplete(), pqTraceOutput_CopyBothResponse(), pqTraceOutput_CopyData(), pqTraceOutput_CopyFail(), pqTraceOutput_CopyInResponse(), pqTraceOutput_CopyOutResponse(), pqTraceOutput_DataRow(), pqTraceOutput_Describe(), pqTraceOutput_ErrorResponse(), pqTraceOutput_Execute(), pqTraceOutput_FunctionCall(), pqTraceOutput_FunctionCallResponse(), pqTraceOutput_GSSResponse(), pqTraceOutput_NegotiateProtocolVersion(), pqTraceOutput_NoticeResponse(), pqTraceOutput_NotificationResponse(), pqTraceOutput_ParameterDescription(), pqTraceOutput_ParameterStatus(), pqTraceOutput_Parse(), pqTraceOutput_PasswordMessage(), pqTraceOutput_Query(), pqTraceOutput_ReadyForQuery(), pqTraceOutput_RowDescription(), pqTraceOutput_SASLInitialResponse(), pqTraceOutput_SASLResponse(), and pg_conn::traceFlags.

Referenced by pg_password_sendauth(), pg_SASL_continue(), pg_SASL_init(), pqParseDone(), and pqPutMsgEnd().

◆ pqTraceOutputNoTypeByteMessage()

void pqTraceOutputNoTypeByteMessage ( PGconn conn,
const char message 
)
extern

Definition at line 843 of file fe-trace.c.

844{
845 int length;
846 int version;
847 bool regress;
848 int logCursor = 0;
849
851
853 {
854 char timestr[128];
855
857 fprintf(conn->Pfdebug, "%s\t", timestr);
858 }
859
860 memcpy(&length, message + logCursor, 4);
861 length = (int) pg_ntoh32(length);
862 logCursor += 4;
863
864 fprintf(conn->Pfdebug, "F\t%d\t", length);
865
866 if (length < 8)
867 {
868 fprintf(conn->Pfdebug, "Unknown message\n");
869 return;
870 }
871
872 memcpy(&version, message + logCursor, 4);
873 version = (int) pg_ntoh32(version);
874
875 if (version == CANCEL_REQUEST_CODE && length >= 16)
876 {
877 fprintf(conn->Pfdebug, "CancelRequest\t");
881 pqTraceOutputNchar(conn->Pfdebug, length - logCursor, message,
883 }
884 else if (version == NEGOTIATE_SSL_CODE)
885 {
886 fprintf(conn->Pfdebug, "SSLRequest\t");
889 }
890 else if (version == NEGOTIATE_GSS_CODE)
891 {
892 fprintf(conn->Pfdebug, "GSSENCRequest\t");
895 }
896 else
897 {
898 fprintf(conn->Pfdebug, "StartupMessage\t");
901 while (message[logCursor] != '\0')
902 {
903 /* XXX should we suppress anything in regress mode? */
904 pqTraceOutputString(conn->Pfdebug, message, &logCursor, false);
905 pqTraceOutputString(conn->Pfdebug, message, &logCursor, false);
906 }
907 }
908
909 fputc('\n', conn->Pfdebug);
910}
static void pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition fe-trace.c:166
static void pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor, bool suppress)
Definition fe-trace.c:193
static int pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
Definition fe-trace.c:126
static int pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition fe-trace.c:145
#define NEGOTIATE_GSS_CODE
Definition pqcomm.h:129
#define NEGOTIATE_SSL_CODE
Definition pqcomm.h:128

References CANCEL_REQUEST_CODE, conn, fb(), fprintf, memcpy(), NEGOTIATE_GSS_CODE, NEGOTIATE_SSL_CODE, pg_conn::Pfdebug, pg_ntoh32, PQTRACE_REGRESS_MODE, PQTRACE_SUPPRESS_TIMESTAMPS, pqTraceFormatTimestamp(), pqTraceOutputInt16(), pqTraceOutputInt32(), pqTraceOutputNchar(), pqTraceOutputString(), and pg_conn::traceFlags.

Referenced by pqPutMsgEnd().

◆ pqWait()

int pqWait ( int  forRead,
int  forWrite,
PGconn conn 
)
extern

Definition at line 1165 of file fe-misc.c.

1166{
1167 return pqWaitTimed(forRead, forWrite, conn, -1);
1168}

References conn, fb(), and pqWaitTimed().

Referenced by pqFunctionCall3(), pqGetCopyData3(), pqGetline3(), PQgetResult(), and pqSendSome().

◆ pqWaitTimed()

int pqWaitTimed ( int  forRead,
int  forWrite,
PGconn conn,
pg_usec_time_t  end_time 
)
extern

Definition at line 1181 of file fe-misc.c.

1182{
1183 int result;
1184
1186
1187 if (result < 0)
1188 return -1; /* errorMessage is already set */
1189
1190 if (result == 0)
1191 {
1192 libpq_append_conn_error(conn, "timeout expired");
1193 return 1;
1194 }
1195
1196 return 0;
1197}

References conn, end_time, fb(), libpq_append_conn_error(), pqSocketCheck(), and result.

Referenced by pqConnectDBComplete(), and pqWait().

◆ pqWriteReady()

int pqWriteReady ( PGconn conn)
extern

Definition at line 1214 of file fe-misc.c.

1215{
1216 return pqSocketCheck(conn, 0, 1, 0);
1217}

References conn, and pqSocketCheck().

Variable Documentation

◆ pg_g_threadlock

pgthreadlock_t pg_g_threadlock
extern

Definition at line 35 of file oauth-utils.c.

Referenced by libpq_oauth_init(), PQgetThreadLock(), and PQregisterThreadLock().

◆ pgresStatus

char* const pgresStatus[]
extern

Definition at line 33 of file fe-exec.c.

33 {
34 "PGRES_EMPTY_QUERY",
35 "PGRES_COMMAND_OK",
36 "PGRES_TUPLES_OK",
37 "PGRES_COPY_OUT",
38 "PGRES_COPY_IN",
39 "PGRES_BAD_RESPONSE",
40 "PGRES_NONFATAL_ERROR",
41 "PGRES_FATAL_ERROR",
42 "PGRES_COPY_BOTH",
43 "PGRES_SINGLE_TUPLE",
44 "PGRES_PIPELINE_SYNC",
45 "PGRES_PIPELINE_ABORTED",
46 "PGRES_TUPLES_CHUNK"
47};

Referenced by PQresStatus().