LCOV - differential code coverage report
Current view: top level - src/backend/tcop - backend_startup.c (source / functions) Coverage Total Hit UNC GNC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 78.4 % 232 182 50 182
Current Date: 2024-04-14 14:21:10 Functions: 57.1 % 7 4 3 4
Baseline: 16@8cea358b128 Branches: 54.1 % 233 126 107 126
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 78.4 % 232 182 50 182
Function coverage date bins:
[..60] days: 57.1 % 7 4 3 4
Branch coverage date bins:
[..60] days: 54.1 % 233 126 107 126

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * backend_startup.c
                                  4                 :                :  *    Backend startup code
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/tcop/backend_startup.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : 
                                 16                 :                : #include "postgres.h"
                                 17                 :                : 
                                 18                 :                : #include <unistd.h>
                                 19                 :                : 
                                 20                 :                : #include "access/xlog.h"
                                 21                 :                : #include "common/ip.h"
                                 22                 :                : #include "common/string.h"
                                 23                 :                : #include "libpq/libpq.h"
                                 24                 :                : #include "libpq/libpq-be.h"
                                 25                 :                : #include "libpq/pqformat.h"
                                 26                 :                : #include "libpq/pqsignal.h"
                                 27                 :                : #include "miscadmin.h"
                                 28                 :                : #include "postmaster/postmaster.h"
                                 29                 :                : #include "replication/walsender.h"
                                 30                 :                : #include "storage/fd.h"
                                 31                 :                : #include "storage/ipc.h"
                                 32                 :                : #include "storage/proc.h"
                                 33                 :                : #include "tcop/backend_startup.h"
                                 34                 :                : #include "tcop/tcopprot.h"
                                 35                 :                : #include "utils/builtins.h"
                                 36                 :                : #include "utils/memutils.h"
                                 37                 :                : #include "utils/ps_status.h"
                                 38                 :                : #include "utils/timeout.h"
                                 39                 :                : 
                                 40                 :                : /* GUCs */
                                 41                 :                : bool        Trace_connection_negotiation = false;
                                 42                 :                : 
                                 43                 :                : static void BackendInitialize(ClientSocket *client_sock, CAC_state cac);
                                 44                 :                : static int  ProcessSSLStartup(Port *port);
                                 45                 :                : static int  ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done);
                                 46                 :                : static void SendNegotiateProtocolVersion(List *unrecognized_protocol_options);
                                 47                 :                : static void process_startup_packet_die(SIGNAL_ARGS);
                                 48                 :                : static void StartupPacketTimeoutHandler(void);
                                 49                 :                : 
                                 50                 :                : /*
                                 51                 :                :  * Entry point for a new backend process.
                                 52                 :                :  *
                                 53                 :                :  * Initialize the connection, read the startup packet, authenticate the
                                 54                 :                :  * client, and start the main processing loop.
                                 55                 :                :  */
                                 56                 :                : void
   27 heikki.linnakangas@i       57                 :GNC       11437 : BackendMain(char *startup_data, size_t startup_data_len)
                                 58                 :                : {
                                 59                 :          11437 :     BackendStartupData *bsdata = (BackendStartupData *) startup_data;
                                 60                 :                : 
                                 61         [ -  + ]:          11437 :     Assert(startup_data_len == sizeof(BackendStartupData));
                                 62         [ -  + ]:          11437 :     Assert(MyClientSocket != NULL);
                                 63                 :                : 
                                 64                 :                : #ifdef EXEC_BACKEND
                                 65                 :                : 
                                 66                 :                :     /*
                                 67                 :                :      * Need to reinitialize the SSL library in the backend, since the context
                                 68                 :                :      * structures contain function pointers and cannot be passed through the
                                 69                 :                :      * parameter file.
                                 70                 :                :      *
                                 71                 :                :      * If for some reason reload fails (maybe the user installed broken key
                                 72                 :                :      * files), soldier on without SSL; that's better than all connections
                                 73                 :                :      * becoming impossible.
                                 74                 :                :      *
                                 75                 :                :      * XXX should we do this in all child processes?  For the moment it's
                                 76                 :                :      * enough to do it in backend children.
                                 77                 :                :      */
                                 78                 :                : #ifdef USE_SSL
                                 79                 :                :     if (EnableSSL)
                                 80                 :                :     {
                                 81                 :                :         if (secure_initialize(false) == 0)
                                 82                 :                :             LoadedSSL = true;
                                 83                 :                :         else
                                 84                 :                :             ereport(LOG,
                                 85                 :                :                     (errmsg("SSL configuration could not be loaded in child process")));
                                 86                 :                :     }
                                 87                 :                : #endif
                                 88                 :                : #endif
                                 89                 :                : 
                                 90                 :                :     /* Perform additional initialization and collect startup packet */
                                 91                 :          11437 :     BackendInitialize(MyClientSocket, bsdata->canAcceptConnections);
                                 92                 :                : 
                                 93                 :                :     /*
                                 94                 :                :      * Create a per-backend PGPROC struct in shared memory.  We must do this
                                 95                 :                :      * before we can use LWLocks or access any shared memory.
                                 96                 :                :      */
                                 97                 :          11233 :     InitProcess();
                                 98                 :                : 
                                 99                 :                :     /*
                                100                 :                :      * Make sure we aren't in PostmasterContext anymore.  (We can't delete it
                                101                 :                :      * just yet, though, because InitPostgres will need the HBA data.)
                                102                 :                :      */
                                103                 :          11231 :     MemoryContextSwitchTo(TopMemoryContext);
                                104                 :                : 
                                105                 :          11231 :     PostgresMain(MyProcPort->database_name, MyProcPort->user_name);
                                106                 :                : }
                                107                 :                : 
                                108                 :                : 
                                109                 :                : /*
                                110                 :                :  * BackendInitialize -- initialize an interactive (postmaster-child)
                                111                 :                :  *              backend process, and collect the client's startup packet.
                                112                 :                :  *
                                113                 :                :  * returns: nothing.  Will not return at all if there's any failure.
                                114                 :                :  *
                                115                 :                :  * Note: this code does not depend on having any access to shared memory.
                                116                 :                :  * Indeed, our approach to SIGTERM/timeout handling *requires* that
                                117                 :                :  * shared memory not have been touched yet; see comments within.
                                118                 :                :  * In the EXEC_BACKEND case, we are physically attached to shared memory
                                119                 :                :  * but have not yet set up most of our local pointers to shmem structures.
                                120                 :                :  */
                                121                 :                : static void
                                122                 :          11437 : BackendInitialize(ClientSocket *client_sock, CAC_state cac)
                                123                 :                : {
                                124                 :                :     int         status;
                                125                 :                :     int         ret;
                                126                 :                :     Port       *port;
                                127                 :                :     char        remote_host[NI_MAXHOST];
                                128                 :                :     char        remote_port[NI_MAXSERV];
                                129                 :                :     StringInfoData ps_data;
                                130                 :                :     MemoryContext oldcontext;
                                131                 :                : 
                                132                 :                :     /* Tell fd.c about the long-lived FD associated with the client_sock */
                                133                 :          11437 :     ReserveExternalFD();
                                134                 :                : 
                                135                 :                :     /*
                                136                 :                :      * PreAuthDelay is a debugging aid for investigating problems in the
                                137                 :                :      * authentication cycle: it can be set in postgresql.conf to allow time to
                                138                 :                :      * attach to the newly-forked backend with a debugger.  (See also
                                139                 :                :      * PostAuthDelay, which we allow clients to pass through PGOPTIONS, but it
                                140                 :                :      * is not honored until after authentication.)
                                141                 :                :      */
                                142         [ -  + ]:          11437 :     if (PreAuthDelay > 0)
   27 heikki.linnakangas@i      143                 :UNC           0 :         pg_usleep(PreAuthDelay * 1000000L);
                                144                 :                : 
                                145                 :                :     /* This flag will remain set until InitPostgres finishes authentication */
   27 heikki.linnakangas@i      146                 :GNC       11437 :     ClientAuthInProgress = true;    /* limit visibility of log messages */
                                147                 :                : 
                                148                 :                :     /*
                                149                 :                :      * Initialize libpq and enable reporting of ereport errors to the client.
                                150                 :                :      * Must do this now because authentication uses libpq to send messages.
                                151                 :                :      *
                                152                 :                :      * The Port structure and all data structures attached to it are allocated
                                153                 :                :      * in TopMemoryContext, so that they survive into PostgresMain execution.
                                154                 :                :      * We need not worry about leaking this storage on failure, since we
                                155                 :                :      * aren't in the postmaster process anymore.
                                156                 :                :      */
                                157                 :          11437 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
                                158                 :          11437 :     port = MyProcPort = pq_init(client_sock);
                                159                 :          11437 :     MemoryContextSwitchTo(oldcontext);
                                160                 :                : 
                                161                 :          11437 :     whereToSendOutput = DestRemote; /* now safe to ereport to client */
                                162                 :                : 
                                163                 :                :     /* set these to empty in case they are needed before we set them up */
                                164                 :          11437 :     port->remote_host = "";
                                165                 :          11437 :     port->remote_port = "";
                                166                 :                : 
                                167                 :                :     /*
                                168                 :                :      * We arrange to do _exit(1) if we receive SIGTERM or timeout while trying
                                169                 :                :      * to collect the startup packet; while SIGQUIT results in _exit(2).
                                170                 :                :      * Otherwise the postmaster cannot shutdown the database FAST or IMMED
                                171                 :                :      * cleanly if a buggy client fails to send the packet promptly.
                                172                 :                :      *
                                173                 :                :      * Exiting with _exit(1) is only possible because we have not yet touched
                                174                 :                :      * shared memory; therefore no outside-the-process state needs to get
                                175                 :                :      * cleaned up.
                                176                 :                :      */
                                177                 :          11437 :     pqsignal(SIGTERM, process_startup_packet_die);
                                178                 :                :     /* SIGQUIT handler was already set up by InitPostmasterChild */
                                179                 :          11437 :     InitializeTimeouts();       /* establishes SIGALRM handler */
                                180                 :          11437 :     sigprocmask(SIG_SETMASK, &StartupBlockSig, NULL);
                                181                 :                : 
                                182                 :                :     /*
                                183                 :                :      * Get the remote host name and port for logging and status display.
                                184                 :                :      */
                                185                 :          11437 :     remote_host[0] = '\0';
                                186                 :          11437 :     remote_port[0] = '\0';
                                187   [ +  +  -  + ]:          11437 :     if ((ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
                                188                 :                :                                   remote_host, sizeof(remote_host),
                                189                 :                :                                   remote_port, sizeof(remote_port),
                                190                 :                :                                   (log_hostname ? 0 : NI_NUMERICHOST) | NI_NUMERICSERV)) != 0)
   27 heikki.linnakangas@i      191         [ #  # ]:UNC           0 :         ereport(WARNING,
                                192                 :                :                 (errmsg_internal("pg_getnameinfo_all() failed: %s",
                                193                 :                :                                  gai_strerror(ret))));
                                194                 :                : 
                                195                 :                :     /*
                                196                 :                :      * Save remote_host and remote_port in port structure (after this, they
                                197                 :                :      * will appear in log_line_prefix data for log messages).
                                198                 :                :      */
   27 heikki.linnakangas@i      199                 :GNC       11437 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
                                200                 :          11437 :     port->remote_host = pstrdup(remote_host);
                                201                 :          11437 :     port->remote_port = pstrdup(remote_port);
                                202                 :                : 
                                203                 :                :     /* And now we can issue the Log_connections message, if wanted */
                                204         [ +  + ]:          11437 :     if (Log_connections)
                                205                 :                :     {
                                206         [ +  + ]:            873 :         if (remote_port[0])
                                207         [ +  - ]:            595 :             ereport(LOG,
                                208                 :                :                     (errmsg("connection received: host=%s port=%s",
                                209                 :                :                             remote_host,
                                210                 :                :                             remote_port)));
                                211                 :                :         else
                                212         [ +  - ]:            278 :             ereport(LOG,
                                213                 :                :                     (errmsg("connection received: host=%s",
                                214                 :                :                             remote_host)));
                                215                 :                :     }
                                216                 :                : 
                                217                 :                :     /*
                                218                 :                :      * If we did a reverse lookup to name, we might as well save the results
                                219                 :                :      * rather than possibly repeating the lookup during authentication.
                                220                 :                :      *
                                221                 :                :      * Note that we don't want to specify NI_NAMEREQD above, because then we'd
                                222                 :                :      * get nothing useful for a client without an rDNS entry.  Therefore, we
                                223                 :                :      * must check whether we got a numeric IPv4 or IPv6 address, and not save
                                224                 :                :      * it into remote_hostname if so.  (This test is conservative and might
                                225                 :                :      * sometimes classify a hostname as numeric, but an error in that
                                226                 :                :      * direction is safe; it only results in a possible extra lookup.)
                                227                 :                :      */
                                228   [ +  +  +  - ]:          11437 :     if (log_hostname &&
                                229                 :            114 :         ret == 0 &&
                                230         [ +  - ]:            114 :         strspn(remote_host, "0123456789.") < strlen(remote_host) &&
                                231         [ +  - ]:            114 :         strspn(remote_host, "0123456789ABCDEFabcdef:") < strlen(remote_host))
                                232                 :                :     {
                                233                 :            114 :         port->remote_hostname = pstrdup(remote_host);
                                234                 :                :     }
                                235                 :          11437 :     MemoryContextSwitchTo(oldcontext);
                                236                 :                : 
                                237                 :                :     /*
                                238                 :                :      * Ready to begin client interaction.  We will give up and _exit(1) after
                                239                 :                :      * a time delay, so that a broken client can't hog a connection
                                240                 :                :      * indefinitely.  PreAuthDelay and any DNS interactions above don't count
                                241                 :                :      * against the time limit.
                                242                 :                :      *
                                243                 :                :      * Note: AuthenticationTimeout is applied here while waiting for the
                                244                 :                :      * startup packet, and then again in InitPostgres for the duration of any
                                245                 :                :      * authentication operations.  So a hostile client could tie up the
                                246                 :                :      * process for nearly twice AuthenticationTimeout before we kick him off.
                                247                 :                :      *
                                248                 :                :      * Note: because PostgresMain will call InitializeTimeouts again, the
                                249                 :                :      * registration of STARTUP_PACKET_TIMEOUT will be lost.  This is okay
                                250                 :                :      * since we never use it again after this function.
                                251                 :                :      */
                                252                 :          11437 :     RegisterTimeout(STARTUP_PACKET_TIMEOUT, StartupPacketTimeoutHandler);
                                253                 :          11437 :     enable_timeout_after(STARTUP_PACKET_TIMEOUT, AuthenticationTimeout * 1000);
                                254                 :                : 
                                255                 :                :     /* Handle direct SSL handshake */
    6                           256                 :          11437 :     status = ProcessSSLStartup(port);
                                257                 :                : 
                                258                 :                :     /*
                                259                 :                :      * Receive the startup packet (which might turn out to be a cancel request
                                260                 :                :      * packet).
                                261                 :                :      */
                                262         [ +  + ]:          11437 :     if (status == STATUS_OK)
                                263                 :          11411 :         status = ProcessStartupPacket(port, false, false);
                                264                 :                : 
                                265                 :                :     /*
                                266                 :                :      * If we're going to reject the connection due to database state, say so
                                267                 :                :      * now instead of wasting cycles on an authentication exchange. (This also
                                268                 :                :      * allows a pg_ping utility to be written.)
                                269                 :                :      */
   27                           270         [ +  + ]:          11437 :     if (status == STATUS_OK)
                                271                 :                :     {
                                272   [ +  +  +  +  :          11356 :         switch (cac)
                                           -  +  - ]
                                273                 :                :         {
                                274                 :            104 :             case CAC_STARTUP:
                                275         [ +  - ]:            104 :                 ereport(FATAL,
                                276                 :                :                         (errcode(ERRCODE_CANNOT_CONNECT_NOW),
                                277                 :                :                          errmsg("the database system is starting up")));
                                278                 :                :                 break;
                                279                 :              1 :             case CAC_NOTCONSISTENT:
                                280         [ +  - ]:              1 :                 if (EnableHotStandby)
                                281         [ +  - ]:              1 :                     ereport(FATAL,
                                282                 :                :                             (errcode(ERRCODE_CANNOT_CONNECT_NOW),
                                283                 :                :                              errmsg("the database system is not yet accepting connections"),
                                284                 :                :                              errdetail("Consistent recovery state has not been yet reached.")));
                                285                 :                :                 else
   27 heikki.linnakangas@i      286         [ #  # ]:UNC           0 :                     ereport(FATAL,
                                287                 :                :                             (errcode(ERRCODE_CANNOT_CONNECT_NOW),
                                288                 :                :                              errmsg("the database system is not accepting connections"),
                                289                 :                :                              errdetail("Hot standby mode is disabled.")));
                                290                 :                :                 break;
   27 heikki.linnakangas@i      291                 :GNC          14 :             case CAC_SHUTDOWN:
                                292         [ +  - ]:             14 :                 ereport(FATAL,
                                293                 :                :                         (errcode(ERRCODE_CANNOT_CONNECT_NOW),
                                294                 :                :                          errmsg("the database system is shutting down")));
                                295                 :                :                 break;
                                296                 :              4 :             case CAC_RECOVERY:
                                297         [ +  - ]:              4 :                 ereport(FATAL,
                                298                 :                :                         (errcode(ERRCODE_CANNOT_CONNECT_NOW),
                                299                 :                :                          errmsg("the database system is in recovery mode")));
                                300                 :                :                 break;
   27 heikki.linnakangas@i      301                 :UNC           0 :             case CAC_TOOMANY:
                                302         [ #  # ]:              0 :                 ereport(FATAL,
                                303                 :                :                         (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
                                304                 :                :                          errmsg("sorry, too many clients already")));
                                305                 :                :                 break;
   27 heikki.linnakangas@i      306                 :GNC       11233 :             case CAC_OK:
                                307                 :          11233 :                 break;
                                308                 :                :         }
                                309                 :                :     }
                                310                 :                : 
                                311                 :                :     /*
                                312                 :                :      * Disable the timeout, and prevent SIGTERM again.
                                313                 :                :      */
                                314                 :          11314 :     disable_timeout(STARTUP_PACKET_TIMEOUT, false);
                                315                 :          11314 :     sigprocmask(SIG_SETMASK, &BlockSig, NULL);
                                316                 :                : 
                                317                 :                :     /*
                                318                 :                :      * As a safety check that nothing in startup has yet performed
                                319                 :                :      * shared-memory modifications that would need to be undone if we had
                                320                 :                :      * exited through SIGTERM or timeout above, check that no on_shmem_exit
                                321                 :                :      * handlers have been registered yet.  (This isn't terribly bulletproof,
                                322                 :                :      * since someone might misuse an on_proc_exit handler for shmem cleanup,
                                323                 :                :      * but it's a cheap and helpful check.  We cannot disallow on_proc_exit
                                324                 :                :      * handlers unfortunately, since pq_init() already registered one.)
                                325                 :                :      */
                                326                 :          11314 :     check_on_shmem_exit_lists_are_empty();
                                327                 :                : 
                                328                 :                :     /*
                                329                 :                :      * Stop here if it was bad or a cancel packet.  ProcessStartupPacket
                                330                 :                :      * already did any appropriate error reporting.
                                331                 :                :      */
                                332         [ +  + ]:          11314 :     if (status != STATUS_OK)
                                333                 :             81 :         proc_exit(0);
                                334                 :                : 
                                335                 :                :     /*
                                336                 :                :      * Now that we have the user and database name, we can set the process
                                337                 :                :      * title for ps.  It's good to do this as early as possible in startup.
                                338                 :                :      */
                                339                 :          11233 :     initStringInfo(&ps_data);
                                340         [ +  + ]:          11233 :     if (am_walsender)
                                341                 :           1031 :         appendStringInfo(&ps_data, "%s ", GetBackendTypeDesc(B_WAL_SENDER));
                                342                 :          11233 :     appendStringInfo(&ps_data, "%s ", port->user_name);
                                343         [ +  + ]:          11233 :     if (port->database_name[0] != '\0')
                                344                 :          10788 :         appendStringInfo(&ps_data, "%s ", port->database_name);
                                345                 :          11233 :     appendStringInfoString(&ps_data, port->remote_host);
                                346         [ +  + ]:          11233 :     if (port->remote_port[0] != '\0')
                                347                 :            581 :         appendStringInfo(&ps_data, "(%s)", port->remote_port);
                                348                 :                : 
                                349                 :          11233 :     init_ps_display(ps_data.data);
                                350                 :          11233 :     pfree(ps_data.data);
                                351                 :                : 
                                352                 :          11233 :     set_ps_display("initializing");
                                353                 :          11233 : }
                                354                 :                : 
                                355                 :                : /*
                                356                 :                :  * Check for a direct SSL connection.
                                357                 :                :  *
                                358                 :                :  * This happens before the startup packet so we are careful not to actually
                                359                 :                :  * read any bytes from the stream if it's not a direct SSL connection.
                                360                 :                :  */
                                361                 :                : static int
    6                           362                 :          11437 : ProcessSSLStartup(Port *port)
                                363                 :                : {
                                364                 :                :     int         firstbyte;
                                365                 :                : 
                                366         [ -  + ]:          11437 :     Assert(!port->ssl_in_use);
                                367                 :                : 
                                368                 :          11437 :     pq_startmsgread();
                                369                 :          11437 :     firstbyte = pq_peekbyte();
                                370                 :          11437 :     pq_endmsgread();
                                371         [ -  + ]:          11437 :     if (firstbyte == EOF)
                                372                 :                :     {
                                373                 :                :         /*
                                374                 :                :          * Like in ProcessStartupPacket, if we get no data at all, don't
                                375                 :                :          * clutter the log with a complaint.
                                376                 :                :          */
    6 heikki.linnakangas@i      377                 :UNC           0 :         return STATUS_ERROR;
                                378                 :                :     }
                                379                 :                : 
    6 heikki.linnakangas@i      380         [ +  + ]:GNC       11437 :     if (firstbyte != 0x16)
                                381                 :                :     {
                                382                 :                :         /* Not an SSL handshake message */
                                383                 :          11363 :         return STATUS_OK;
                                384                 :                :     }
                                385                 :                : 
                                386                 :                :     /*
                                387                 :                :      * First byte indicates standard SSL handshake message
                                388                 :                :      *
                                389                 :                :      * (It can't be a Postgres startup length because in network byte order
                                390                 :                :      * that would be a startup packet hundreds of megabytes long)
                                391                 :                :      */
                                392                 :                : 
                                393                 :                : #ifdef USE_SSL
                                394   [ +  +  -  + ]:             74 :     if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX)
                                395                 :                :     {
                                396                 :                :         /* SSL not supported */
                                397                 :             26 :         goto reject;
                                398                 :                :     }
                                399                 :                : 
                                400         [ -  + ]:             48 :     if (secure_open_server(port) == -1)
                                401                 :                :     {
                                402                 :                :         /*
                                403                 :                :          * we assume secure_open_server() sent an appropriate TLS alert
                                404                 :                :          * already
                                405                 :                :          */
    6 heikki.linnakangas@i      406                 :UNC           0 :         goto reject;
                                407                 :                :     }
    6 heikki.linnakangas@i      408         [ -  + ]:GNC          48 :     Assert(port->ssl_in_use);
                                409                 :                : 
                                410         [ -  + ]:             48 :     if (!port->alpn_used)
                                411                 :                :     {
    6 heikki.linnakangas@i      412         [ #  # ]:UNC           0 :         ereport(COMMERROR,
                                413                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                414                 :                :                  errmsg("received direct SSL connection request without ALPN protocol negotiation extension")));
                                415                 :              0 :         goto reject;
                                416                 :                :     }
                                417                 :                : 
    6 heikki.linnakangas@i      418         [ +  - ]:GNC          48 :     if (Trace_connection_negotiation)
                                419         [ +  - ]:             48 :         ereport(LOG,
                                420                 :                :                 (errmsg("direct SSL connection accepted")));
                                421                 :             48 :     return STATUS_OK;
                                422                 :                : #else
                                423                 :                :     /* SSL not supported by this build */
                                424                 :                :     goto reject;
                                425                 :                : #endif
                                426                 :                : 
                                427                 :             26 : reject:
                                428         [ +  - ]:             26 :     if (Trace_connection_negotiation)
                                429         [ +  - ]:             26 :         ereport(LOG,
                                430                 :                :                 (errmsg("direct SSL connection rejected")));
                                431                 :             26 :     return STATUS_ERROR;
                                432                 :                : }
                                433                 :                : 
                                434                 :                : /*
                                435                 :                :  * Read a client's startup packet and do something according to it.
                                436                 :                :  *
                                437                 :                :  * Returns STATUS_OK or STATUS_ERROR, or might call ereport(FATAL) and
                                438                 :                :  * not return at all.
                                439                 :                :  *
                                440                 :                :  * (Note that ereport(FATAL) stuff is sent to the client, so only use it
                                441                 :                :  * if that's what you want.  Return STATUS_ERROR if you don't want to
                                442                 :                :  * send anything to the client, which would typically be appropriate
                                443                 :                :  * if we detect a communications failure.)
                                444                 :                :  *
                                445                 :                :  * Set ssl_done and/or gss_done when negotiation of an encrypted layer
                                446                 :                :  * (currently, TLS or GSSAPI) is completed. A successful negotiation of either
                                447                 :                :  * encryption layer sets both flags, but a rejected negotiation sets only the
                                448                 :                :  * flag for that layer, since the client may wish to try the other one. We
                                449                 :                :  * should make no assumption here about the order in which the client may make
                                450                 :                :  * requests.
                                451                 :                :  */
                                452                 :                : static int
   27                           453                 :          11859 : ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
                                454                 :                : {
                                455                 :                :     int32       len;
                                456                 :                :     char       *buf;
                                457                 :                :     ProtocolVersion proto;
                                458                 :                :     MemoryContext oldcontext;
                                459                 :                : 
                                460                 :          11859 :     pq_startmsgread();
                                461                 :                : 
                                462                 :                :     /*
                                463                 :                :      * Grab the first byte of the length word separately, so that we can tell
                                464                 :                :      * whether we have no data at all or an incomplete packet.  (This might
                                465                 :                :      * sound inefficient, but it's not really, because of buffering in
                                466                 :                :      * pqcomm.c.)
                                467                 :                :      */
                                468         [ +  + ]:          11859 :     if (pq_getbytes((char *) &len, 1) == EOF)
                                469                 :                :     {
                                470                 :                :         /*
                                471                 :                :          * If we get no data at all, don't clutter the log with a complaint;
                                472                 :                :          * such cases often occur for legitimate reasons.  An example is that
                                473                 :                :          * we might be here after responding to NEGOTIATE_SSL_CODE, and if the
                                474                 :                :          * client didn't like our response, it'll probably just drop the
                                475                 :                :          * connection.  Service-monitoring software also often just opens and
                                476                 :                :          * closes a connection without sending anything.  (So do port
                                477                 :                :          * scanners, which may be less benign, but it's not really our job to
                                478                 :                :          * notice those.)
                                479                 :                :          */
                                480                 :             27 :         return STATUS_ERROR;
                                481                 :                :     }
                                482                 :                : 
                                483         [ -  + ]:          11832 :     if (pq_getbytes(((char *) &len) + 1, 3) == EOF)
                                484                 :                :     {
                                485                 :                :         /* Got a partial length word, so bleat about that */
   27 heikki.linnakangas@i      486   [ #  #  #  # ]:UNC           0 :         if (!ssl_done && !gss_done)
                                487         [ #  # ]:              0 :             ereport(COMMERROR,
                                488                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                489                 :                :                      errmsg("incomplete startup packet")));
                                490                 :              0 :         return STATUS_ERROR;
                                491                 :                :     }
                                492                 :                : 
   27 heikki.linnakangas@i      493                 :GNC       11832 :     len = pg_ntoh32(len);
                                494                 :          11832 :     len -= 4;
                                495                 :                : 
                                496         [ +  - ]:          11832 :     if (len < (int32) sizeof(ProtocolVersion) ||
                                497         [ -  + ]:          11832 :         len > MAX_STARTUP_PACKET_LENGTH)
                                498                 :                :     {
   27 heikki.linnakangas@i      499         [ #  # ]:UNC           0 :         ereport(COMMERROR,
                                500                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                501                 :                :                  errmsg("invalid length of startup packet")));
                                502                 :              0 :         return STATUS_ERROR;
                                503                 :                :     }
                                504                 :                : 
                                505                 :                :     /*
                                506                 :                :      * Allocate space to hold the startup packet, plus one extra byte that's
                                507                 :                :      * initialized to be zero.  This ensures we will have null termination of
                                508                 :                :      * all strings inside the packet.
                                509                 :                :      */
   27 heikki.linnakangas@i      510                 :GNC       11832 :     buf = palloc(len + 1);
                                511                 :          11832 :     buf[len] = '\0';
                                512                 :                : 
                                513         [ -  + ]:          11832 :     if (pq_getbytes(buf, len) == EOF)
                                514                 :                :     {
   27 heikki.linnakangas@i      515         [ #  # ]:UNC           0 :         ereport(COMMERROR,
                                516                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                517                 :                :                  errmsg("incomplete startup packet")));
                                518                 :              0 :         return STATUS_ERROR;
                                519                 :                :     }
   27 heikki.linnakangas@i      520                 :GNC       11832 :     pq_endmsgread();
                                521                 :                : 
                                522                 :                :     /*
                                523                 :                :      * The first field is either a protocol version number or a special
                                524                 :                :      * request code.
                                525                 :                :      */
                                526                 :          11832 :     port->proto = proto = pg_ntoh32(*((ProtocolVersion *) buf));
                                527                 :                : 
                                528         [ +  + ]:          11832 :     if (proto == CANCEL_REQUEST_CODE)
                                529                 :                :     {
                                530                 :                :         CancelRequestPacket *canc;
                                531                 :                :         int         backendPID;
                                532                 :                :         int32       cancelAuthCode;
                                533                 :                : 
                                534         [ -  + ]:             10 :         if (len != sizeof(CancelRequestPacket))
                                535                 :                :         {
   27 heikki.linnakangas@i      536         [ #  # ]:UNC           0 :             ereport(COMMERROR,
                                537                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                538                 :                :                      errmsg("invalid length of startup packet")));
                                539                 :              0 :             return STATUS_ERROR;
                                540                 :                :         }
   27 heikki.linnakangas@i      541                 :GNC          10 :         canc = (CancelRequestPacket *) buf;
                                542                 :             10 :         backendPID = (int) pg_ntoh32(canc->backendPID);
                                543                 :             10 :         cancelAuthCode = (int32) pg_ntoh32(canc->cancelAuthCode);
                                544                 :                : 
                                545                 :             10 :         processCancelRequest(backendPID, cancelAuthCode);
                                546                 :                :         /* Not really an error, but we don't want to proceed further */
                                547                 :             10 :         return STATUS_ERROR;
                                548                 :                :     }
                                549                 :                : 
                                550   [ +  +  +  - ]:          11822 :     if (proto == NEGOTIATE_SSL_CODE && !ssl_done)
                                551                 :                :     {
                                552                 :                :         char        SSLok;
                                553                 :                : 
                                554                 :                : #ifdef USE_SSL
                                555                 :                : 
                                556                 :                :         /*
                                557                 :                :          * No SSL when disabled or on Unix sockets.
                                558                 :                :          *
                                559                 :                :          * Also no SSL negotiation if we already have a direct SSL connection
                                560                 :                :          */
    6                           561   [ +  +  +  -  :            233 :         if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX || port->ssl_in_use)
                                              -  + ]
   27                           562                 :             96 :             SSLok = 'N';
                                563                 :                :         else
                                564                 :            137 :             SSLok = 'S';        /* Support for SSL */
                                565                 :                : #else
                                566                 :                :         SSLok = 'N';            /* No support for SSL */
                                567                 :                : #endif
                                568                 :                : 
    6                           569         [ +  + ]:            233 :         if (Trace_connection_negotiation)
                                570                 :                :         {
                                571         [ +  + ]:             50 :             if (SSLok == 'S')
                                572         [ +  - ]:             24 :                 ereport(LOG,
                                573                 :                :                         (errmsg("SSLRequest accepted")));
                                574                 :                :             else
                                575         [ +  - ]:             26 :                 ereport(LOG,
                                576                 :                :                         (errmsg("SSLRequest rejected")));
                                577                 :                :         }
                                578                 :                : 
                                579         [ -  + ]:            233 :         while (secure_write(port, &SSLok, 1) != 1)
                                580                 :                :         {
   27 heikki.linnakangas@i      581         [ #  # ]:UNC           0 :             if (errno == EINTR)
    6                           582                 :              0 :                 continue;       /* if interrupted, just retry */
   27                           583         [ #  # ]:              0 :             ereport(COMMERROR,
                                584                 :                :                     (errcode_for_socket_access(),
                                585                 :                :                      errmsg("failed to send SSL negotiation response: %m")));
                                586                 :              0 :             return STATUS_ERROR;    /* close the connection */
                                587                 :                :         }
                                588                 :                : 
                                589                 :                : #ifdef USE_SSL
   27 heikki.linnakangas@i      590   [ +  +  +  + ]:GNC         233 :         if (SSLok == 'S' && secure_open_server(port) == -1)
                                591                 :             18 :             return STATUS_ERROR;
                                592                 :                : #endif
                                593                 :                : 
                                594                 :                :         /*
                                595                 :                :          * At this point we should have no data already buffered.  If we do,
                                596                 :                :          * it was received before we performed the SSL handshake, so it wasn't
                                597                 :                :          * encrypted and indeed may have been injected by a man-in-the-middle.
                                598                 :                :          * We report this case to the client.
                                599                 :                :          */
    6                           600         [ -  + ]:            215 :         if (pq_buffer_remaining_data() > 0)
   27 heikki.linnakangas@i      601         [ #  # ]:UNC           0 :             ereport(FATAL,
                                602                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                603                 :                :                      errmsg("received unencrypted data after SSL request"),
                                604                 :                :                      errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
                                605                 :                : 
                                606                 :                :         /*
                                607                 :                :          * regular startup packet, cancel, etc packet should follow, but not
                                608                 :                :          * another SSL negotiation request, and a GSS request should only
                                609                 :                :          * follow if SSL was rejected (client may negotiate in either order)
                                610                 :                :          */
   27 heikki.linnakangas@i      611                 :GNC         215 :         return ProcessStartupPacket(port, true, SSLok == 'S');
                                612                 :                :     }
                                613   [ +  +  +  - ]:          11589 :     else if (proto == NEGOTIATE_GSS_CODE && !gss_done)
                                614                 :                :     {
                                615                 :            233 :         char        GSSok = 'N';
                                616                 :                : 
                                617                 :                : #ifdef ENABLE_GSS
                                618                 :                :         /* No GSSAPI encryption when on Unix socket */
                                619         [ +  - ]:            233 :         if (port->laddr.addr.ss_family != AF_UNIX)
                                620                 :            233 :             GSSok = 'G';
                                621                 :                : #endif
                                622                 :                : 
    6                           623         [ +  + ]:            233 :         if (Trace_connection_negotiation)
                                624                 :                :         {
                                625         [ +  - ]:            193 :             if (GSSok == 'G')
                                626         [ +  - ]:            193 :                 ereport(LOG,
                                627                 :                :                         (errmsg("GSSENCRequest accepted")));
                                628                 :                :             else
    6 heikki.linnakangas@i      629         [ #  # ]:UNC           0 :                 ereport(LOG,
                                630                 :                :                         (errmsg("GSSENCRequest rejected")));
                                631                 :                :         }
                                632                 :                : 
    6 heikki.linnakangas@i      633         [ -  + ]:GNC         233 :         while (secure_write(port, &GSSok, 1) != 1)
                                634                 :                :         {
   27 heikki.linnakangas@i      635         [ #  # ]:UNC           0 :             if (errno == EINTR)
                                636                 :              0 :                 continue;
                                637         [ #  # ]:              0 :             ereport(COMMERROR,
                                638                 :                :                     (errcode_for_socket_access(),
                                639                 :                :                      errmsg("failed to send GSSAPI negotiation response: %m")));
                                640                 :              0 :             return STATUS_ERROR;    /* close the connection */
                                641                 :                :         }
                                642                 :                : 
                                643                 :                : #ifdef ENABLE_GSS
   27 heikki.linnakangas@i      644   [ +  -  -  + ]:GNC         233 :         if (GSSok == 'G' && secure_open_gssapi(port) == -1)
   27 heikki.linnakangas@i      645                 :UNC           0 :             return STATUS_ERROR;
                                646                 :                : #endif
                                647                 :                : 
                                648                 :                :         /*
                                649                 :                :          * At this point we should have no data already buffered.  If we do,
                                650                 :                :          * it was received before we performed the GSS handshake, so it wasn't
                                651                 :                :          * encrypted and indeed may have been injected by a man-in-the-middle.
                                652                 :                :          * We report this case to the client.
                                653                 :                :          */
    6 heikki.linnakangas@i      654         [ -  + ]:GNC         233 :         if (pq_buffer_remaining_data() > 0)
   27 heikki.linnakangas@i      655         [ #  # ]:UNC           0 :             ereport(FATAL,
                                656                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                657                 :                :                      errmsg("received unencrypted data after GSSAPI encryption request"),
                                658                 :                :                      errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
                                659                 :                : 
                                660                 :                :         /*
                                661                 :                :          * regular startup packet, cancel, etc packet should follow, but not
                                662                 :                :          * another GSS negotiation request, and an SSL request should only
                                663                 :                :          * follow if GSS was rejected (client may negotiate in either order)
                                664                 :                :          */
   27 heikki.linnakangas@i      665                 :GNC         233 :         return ProcessStartupPacket(port, GSSok == 'G', true);
                                666                 :                :     }
                                667                 :                : 
                                668                 :                :     /* Could add additional special packet types here */
                                669                 :                : 
                                670                 :                :     /*
                                671                 :                :      * Set FrontendProtocol now so that ereport() knows what format to send if
                                672                 :                :      * we fail during startup.
                                673                 :                :      */
                                674                 :          11356 :     FrontendProtocol = proto;
                                675                 :                : 
                                676                 :                :     /* Check that the major protocol version is in range. */
                                677         [ +  - ]:          11356 :     if (PG_PROTOCOL_MAJOR(proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
                                678         [ -  + ]:          11356 :         PG_PROTOCOL_MAJOR(proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST))
   27 heikki.linnakangas@i      679         [ #  # ]:UNC           0 :         ereport(FATAL,
                                680                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                681                 :                :                  errmsg("unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u",
                                682                 :                :                         PG_PROTOCOL_MAJOR(proto), PG_PROTOCOL_MINOR(proto),
                                683                 :                :                         PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST),
                                684                 :                :                         PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST),
                                685                 :                :                         PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST))));
                                686                 :                : 
                                687                 :                :     /*
                                688                 :                :      * Now fetch parameters out of startup packet and save them into the Port
                                689                 :                :      * structure.
                                690                 :                :      */
   27 heikki.linnakangas@i      691                 :GNC       11356 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
                                692                 :                : 
                                693                 :                :     /* Handle protocol version 3 startup packet */
                                694                 :                :     {
                                695                 :          11356 :         int32       offset = sizeof(ProtocolVersion);
                                696                 :          11356 :         List       *unrecognized_protocol_options = NIL;
                                697                 :                : 
                                698                 :                :         /*
                                699                 :                :          * Scan packet body for name/option pairs.  We can assume any string
                                700                 :                :          * beginning within the packet body is null-terminated, thanks to
                                701                 :                :          * zeroing extra byte above.
                                702                 :                :          */
                                703                 :          11356 :         port->guc_options = NIL;
                                704                 :                : 
                                705         [ +  - ]:          54287 :         while (offset < len)
                                706                 :                :         {
                                707                 :          54287 :             char       *nameptr = buf + offset;
                                708                 :                :             int32       valoffset;
                                709                 :                :             char       *valptr;
                                710                 :                : 
                                711         [ +  + ]:          54287 :             if (*nameptr == '\0')
                                712                 :          11356 :                 break;          /* found packet terminator */
                                713                 :          42931 :             valoffset = offset + strlen(nameptr) + 1;
                                714         [ -  + ]:          42931 :             if (valoffset >= len)
   27 heikki.linnakangas@i      715                 :UNC           0 :                 break;          /* missing value, will complain below */
   27 heikki.linnakangas@i      716                 :GNC       42931 :             valptr = buf + valoffset;
                                717                 :                : 
                                718         [ +  + ]:          42931 :             if (strcmp(nameptr, "database") == 0)
                                719                 :          11356 :                 port->database_name = pstrdup(valptr);
                                720         [ +  + ]:          31575 :             else if (strcmp(nameptr, "user") == 0)
                                721                 :          11356 :                 port->user_name = pstrdup(valptr);
                                722         [ +  + ]:          20219 :             else if (strcmp(nameptr, "options") == 0)
                                723                 :           3048 :                 port->cmdline_options = pstrdup(valptr);
                                724         [ +  + ]:          17171 :             else if (strcmp(nameptr, "replication") == 0)
                                725                 :                :             {
                                726                 :                :                 /*
                                727                 :                :                  * Due to backward compatibility concerns the replication
                                728                 :                :                  * parameter is a hybrid beast which allows the value to be
                                729                 :                :                  * either boolean or the string 'database'. The latter
                                730                 :                :                  * connects to a specific database which is e.g. required for
                                731                 :                :                  * logical decoding while.
                                732                 :                :                  */
                                733         [ +  + ]:           1050 :                 if (strcmp(valptr, "database") == 0)
                                734                 :                :                 {
                                735                 :            599 :                     am_walsender = true;
                                736                 :            599 :                     am_db_walsender = true;
                                737                 :                :                 }
                                738         [ -  + ]:            451 :                 else if (!parse_bool(valptr, &am_walsender))
   27 heikki.linnakangas@i      739         [ #  # ]:UNC           0 :                     ereport(FATAL,
                                740                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                741                 :                :                              errmsg("invalid value for parameter \"%s\": \"%s\"",
                                742                 :                :                                     "replication",
                                743                 :                :                                     valptr),
                                744                 :                :                              errhint("Valid values are: \"false\", 0, \"true\", 1, \"database\".")));
                                745                 :                :             }
   27 heikki.linnakangas@i      746         [ -  + ]:GNC       16121 :             else if (strncmp(nameptr, "_pq_.", 5) == 0)
                                747                 :                :             {
                                748                 :                :                 /*
                                749                 :                :                  * Any option beginning with _pq_. is reserved for use as a
                                750                 :                :                  * protocol-level option, but at present no such options are
                                751                 :                :                  * defined.
                                752                 :                :                  */
                                753                 :                :                 unrecognized_protocol_options =
   27 heikki.linnakangas@i      754                 :UNC           0 :                     lappend(unrecognized_protocol_options, pstrdup(nameptr));
                                755                 :                :             }
                                756                 :                :             else
                                757                 :                :             {
                                758                 :                :                 /* Assume it's a generic GUC option */
   27 heikki.linnakangas@i      759                 :GNC       16121 :                 port->guc_options = lappend(port->guc_options,
                                760                 :          16121 :                                             pstrdup(nameptr));
                                761                 :          16121 :                 port->guc_options = lappend(port->guc_options,
                                762                 :          16121 :                                             pstrdup(valptr));
                                763                 :                : 
                                764                 :                :                 /*
                                765                 :                :                  * Copy application_name to port if we come across it.  This
                                766                 :                :                  * is done so we can log the application_name in the
                                767                 :                :                  * connection authorization message.  Note that the GUC would
                                768                 :                :                  * be used but we haven't gone through GUC setup yet.
                                769                 :                :                  */
                                770         [ +  + ]:          16121 :                 if (strcmp(nameptr, "application_name") == 0)
                                771                 :                :                 {
                                772                 :          11351 :                     port->application_name = pg_clean_ascii(valptr, 0);
                                773                 :                :                 }
                                774                 :                :             }
                                775                 :          42931 :             offset = valoffset + strlen(valptr) + 1;
                                776                 :                :         }
                                777                 :                : 
                                778                 :                :         /*
                                779                 :                :          * If we didn't find a packet terminator exactly at the end of the
                                780                 :                :          * given packet length, complain.
                                781                 :                :          */
                                782         [ -  + ]:          11356 :         if (offset != len - 1)
   27 heikki.linnakangas@i      783         [ #  # ]:UNC           0 :             ereport(FATAL,
                                784                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                785                 :                :                      errmsg("invalid startup packet layout: expected terminator as last byte")));
                                786                 :                : 
                                787                 :                :         /*
                                788                 :                :          * If the client requested a newer protocol version or if the client
                                789                 :                :          * requested any protocol options we didn't recognize, let them know
                                790                 :                :          * the newest minor protocol version we do support and the names of
                                791                 :                :          * any unrecognized options.
                                792                 :                :          */
   27 heikki.linnakangas@i      793   [ +  -  -  + ]:GNC       11356 :         if (PG_PROTOCOL_MINOR(proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST) ||
                                794                 :                :             unrecognized_protocol_options != NIL)
   27 heikki.linnakangas@i      795                 :UNC           0 :             SendNegotiateProtocolVersion(unrecognized_protocol_options);
                                796                 :                :     }
                                797                 :                : 
                                798                 :                :     /* Check a user name was given. */
   27 heikki.linnakangas@i      799   [ +  -  -  + ]:GNC       11356 :     if (port->user_name == NULL || port->user_name[0] == '\0')
   27 heikki.linnakangas@i      800         [ #  # ]:UNC           0 :         ereport(FATAL,
                                801                 :                :                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                                802                 :                :                  errmsg("no PostgreSQL user name specified in startup packet")));
                                803                 :                : 
                                804                 :                :     /* The database defaults to the user name. */
   27 heikki.linnakangas@i      805   [ +  -  -  + ]:GNC       11356 :     if (port->database_name == NULL || port->database_name[0] == '\0')
   27 heikki.linnakangas@i      806                 :UNC           0 :         port->database_name = pstrdup(port->user_name);
                                807                 :                : 
   27 heikki.linnakangas@i      808         [ +  + ]:GNC       11356 :     if (am_walsender)
                                809                 :           1050 :         MyBackendType = B_WAL_SENDER;
                                810                 :                :     else
                                811                 :          10306 :         MyBackendType = B_BACKEND;
                                812                 :                : 
                                813                 :                :     /*
                                814                 :                :      * Normal walsender backends, e.g. for streaming replication, are not
                                815                 :                :      * connected to a particular database. But walsenders used for logical
                                816                 :                :      * replication need to connect to a specific database. We allow streaming
                                817                 :                :      * replication commands to be issued even if connected to a database as it
                                818                 :                :      * can make sense to first make a basebackup and then stream changes
                                819                 :                :      * starting from that.
                                820                 :                :      */
                                821   [ +  +  +  + ]:          11356 :     if (am_walsender && !am_db_walsender)
                                822                 :            451 :         port->database_name[0] = '\0';
                                823                 :                : 
                                824                 :                :     /*
                                825                 :                :      * Done filling the Port structure
                                826                 :                :      */
                                827                 :          11356 :     MemoryContextSwitchTo(oldcontext);
                                828                 :                : 
                                829                 :          11356 :     return STATUS_OK;
                                830                 :                : }
                                831                 :                : 
                                832                 :                : /*
                                833                 :                :  * Send a NegotiateProtocolVersion to the client.  This lets the client know
                                834                 :                :  * that they have requested a newer minor protocol version than we are able
                                835                 :                :  * to speak.  We'll speak the highest version we know about; the client can,
                                836                 :                :  * of course, abandon the connection if that's a problem.
                                837                 :                :  *
                                838                 :                :  * We also include in the response a list of protocol options we didn't
                                839                 :                :  * understand.  This allows clients to include optional parameters that might
                                840                 :                :  * be present either in newer protocol versions or third-party protocol
                                841                 :                :  * extensions without fear of having to reconnect if those options are not
                                842                 :                :  * understood, while at the same time making certain that the client is aware
                                843                 :                :  * of which options were actually accepted.
                                844                 :                :  */
                                845                 :                : static void
   27 heikki.linnakangas@i      846                 :UNC           0 : SendNegotiateProtocolVersion(List *unrecognized_protocol_options)
                                847                 :                : {
                                848                 :                :     StringInfoData buf;
                                849                 :                :     ListCell   *lc;
                                850                 :                : 
                                851                 :              0 :     pq_beginmessage(&buf, PqMsg_NegotiateProtocolVersion);
                                852                 :              0 :     pq_sendint32(&buf, PG_PROTOCOL_LATEST);
                                853                 :              0 :     pq_sendint32(&buf, list_length(unrecognized_protocol_options));
                                854   [ #  #  #  #  :              0 :     foreach(lc, unrecognized_protocol_options)
                                              #  # ]
                                855                 :              0 :         pq_sendstring(&buf, lfirst(lc));
                                856                 :              0 :     pq_endmessage(&buf);
                                857                 :                : 
                                858                 :                :     /* no need to flush, some other message will follow */
                                859                 :              0 : }
                                860                 :                : 
                                861                 :                : 
                                862                 :                : /*
                                863                 :                :  * SIGTERM while processing startup packet.
                                864                 :                :  *
                                865                 :                :  * Running proc_exit() from a signal handler would be quite unsafe.
                                866                 :                :  * However, since we have not yet touched shared memory, we can just
                                867                 :                :  * pull the plug and exit without running any atexit handlers.
                                868                 :                :  *
                                869                 :                :  * One might be tempted to try to send a message, or log one, indicating
                                870                 :                :  * why we are disconnecting.  However, that would be quite unsafe in itself.
                                871                 :                :  * Also, it seems undesirable to provide clues about the database's state
                                872                 :                :  * to a client that has not yet completed authentication, or even sent us
                                873                 :                :  * a startup packet.
                                874                 :                :  */
                                875                 :                : static void
                                876                 :              0 : process_startup_packet_die(SIGNAL_ARGS)
                                877                 :                : {
    0 andres@anarazel.de        878                 :              0 :     immediate_exit(1);
                                879                 :                : }
                                880                 :                : 
                                881                 :                : /*
                                882                 :                :  * Timeout while processing startup packet.
                                883                 :                :  * As for process_startup_packet_die(), we exit via immediate_exit(1).
                                884                 :                :  */
                                885                 :                : static void
   27 heikki.linnakangas@i      886                 :              0 : StartupPacketTimeoutHandler(void)
                                887                 :                : {
    0 andres@anarazel.de        888                 :              0 :     immediate_exit(1);
                                889                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622