From 22ac1594ef6eefcc5f7f07447e49ea3ef6f99b12 Mon Sep 17 00:00:00 2001 From: Jacob Champion Date: Wed, 18 Feb 2026 12:11:49 -0800 Subject: [PATCH v8 2/2] squash! libpq: Grease the protocol by default Also attempt to notify the user when the server closes the connection suspiciously. --- src/interfaces/libpq/fe-connect.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 418c71a9aa8..b42a0cb4c78 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -91,8 +91,9 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options, /* This is part of the protocol so just define it */ #define ERRCODE_INVALID_PASSWORD "28P01" -/* This too */ +/* These too */ #define ERRCODE_CANNOT_CONNECT_NOW "57P03" +#define ERRCODE_PROTOCOL_VIOLATION "08P01" /* * Cope with the various platform-specific ways to spell TCP keepalive socket @@ -4154,6 +4155,32 @@ keep_going: /* We will come back to here until there is /* Check to see if we should mention pgpassfile */ pgpassfileWarning(conn); + /* + * ...and whether we should mention grease. If the error + * message contains the PG_PROTOCOL_GREASE number (in + * major.minor, decimal, or hex format) or a complaint + * about a protocol violation before we've even started an + * authentication exchange, it's probably caused by a + * grease interaction. + */ + if (conn->max_pversion == PG_PROTOCOL_GREASE && + !conn->auth_req_received) + { + const char *sqlstate = PQresultErrorField(conn->result, + PG_DIAG_SQLSTATE); + + if ((sqlstate && + strcmp(sqlstate, ERRCODE_PROTOCOL_VIOLATION) == 0) || + (conn->errorMessage.len > 0 && + (strstr(conn->errorMessage.data, "3.9999") || + strstr(conn->errorMessage.data, "206607") || + strstr(conn->errorMessage.data, "3270F") || + strstr(conn->errorMessage.data, "3270f")))) + { + libpq_append_grease_info(conn); + } + } + CONNECTION_FAILED(); } /* Handle NegotiateProtocolVersion */ -- 2.34.1