3.3.1 Session control

3.3.1.1 Start Session Request

This message is used to start a control channel between peers. This must be the first control message sent from one peer to another once the TCP connection reaches the ESTABLISHED state.


    /*
     * The following constants are bit fields that define the
     * framing capabilities of the sender of the StartSessionRequest
     * and StartSessionReply messages. These values are stored
     * in the "framingCapability" field of both messages.
     *
     * PPTP_FRAME_CAP_ASYNC:      Can do async PPP framing.
     *
     * PPRP_FRAME_CAP_SYNC:       Can do sync PPP framing.
     */

#define PPTP_FRAME_CAP_ASYNC      0x00000001L
#define PPTP_FRAME_CAP_SYNC       0x00000002L

    /*
     * The following constants are bit fields that define the
     * bearer capabilities of the sender of the StartSessionRequest
     * and StartSessionReply messages. These values are stored
     * in the "bearerCapability" field of both messages.
     *
     * PPTP_BEARER_CAP_ANALOG:    Can do analog calls.
     *
     * PPTP_BEARER_CAP_DIGITAL:   Can do digital calls.
     */

#define PPTP_BEARER_CAP_ANALOG    0x00000001L
#define PPTP_BEARER_CAP_DIGITAL   0x00000002L

The format of this message is the following:


    /*
     * The PPTP Start Session Control Message. This message can be sent
     * by the Windows NT Server or the FEP to start a control 
     * channel. A control channel must be opened before any other
     * commands can be issued.
     *
     *  protocolVersion:         The Protocol Version that I speak.
     *
     *  framingCapability:       Describes what type of framing
     *                           sender of this message can support.
     *                           See PPTP_FRAME_CAP_* above.
     *
     *  bearerCapability:        Describes what type of bearer
     *                           capabilities is available to the
     *                           sender of this message. See
     *                           PPTP_BEARER_CAP_* above.
     *
     *  maxChannel:              Total number of channel this box
     *                           can handle. Valid only if the
     *                           FEP initiates the session.
     *
     *  firmwareRevision:        The revision of the operating
     *                           firmware of the sender of this 
     *                           message. This field contains the
     *                           firmware revision if the FEP
     *                           send this message, or the driver
     *                           version if the NT server sends this
     *                           message.
     *
     *  hostName:                My host name.
     *
     *  vendorString:            A sender-specific ASCII string
     *                           to describe the sender's equipment.
     */

typedef struct {
    Word      protocolVersion;
    Byte      reserved1;
    Byte      reserved2;
    LongWord  framingCapability;
    LongWord  bearerCapability;
    Word      maxChannels;
    Word      firmwareRevision;
    Byte      hostName[ 64 ];
    Byte      vendorString[ 64 ];
} PptpStartSessionRequest;
Back to table of contents.

3.3.1.1.1 A note about Start Session collisions

A Start Session collision can happen when the two endpoints (the Windows NT Server and the FEP) attempt to open a session simultaneously. In such a case, arbitration is done by comparing the IP addresses of the endpoint. The peer with the higher IP address wins. For example, in a collision between 192.33.45.17 and 192.33.45.89, .89 will be the winner. The TCP connection initiated by the loser must be closed, and the loser must send a Start Session Reply to the winner on the TCP connection initiated by the winner. The TCP connection initiated by the loser must be closed by both sides.

3.3.1.2 Start Session Reply

This message is the result of the Start Session Request message. The result code can be one of the following:


    /*
     * The possible result codes returned by the Comm Server in the
     * StartSessionReply message.
     *
     *  PPTP_START_OK:                  Session opened successfully.
     *
     *  PPTP_START_ALREADY_CONNECTED:   I already have an open
     *                                  connection with you.
     *
     *  PPTP_START_NOT_AUTHORIZED:      I've been told I can't talk to you.
     *
     *  PPTP_START_UNKNOWN_PROTOCOL:    I don't know the protocol version
     *                                  that you know.
     */

typedef enum {
    PPTP_START_OK = 1,
    PPTP_START_GENERAL_ERROR = 2,
    PPTP_START_ALREADY_CONNECTED,
    PPTP_START_NOT_AUTHORIZED,
    PPTP_START_UNKNOWN_PROTOCOL,
} PptpStartSessionResultCode;

The packet format for the Start Session Reply is the following:


    /*
     * The PPTP Start Session Reply Message. This message is sent as
     * a reply to the StartSessionRequest.
     *
     *  protocolVersion:       The PPTP protocol version being
     *                         run by the sender of this message.
     *
     *  resultCode:            One of PptpStartSessionResultCode.
     *
     *  generalErrorCode:      Valid resultCode is 
     *                         PPTP_START_GENERAL_ERROR.
     *
     *  framingCapability:     Describes what type of framing
     *                         sender of this message can support.
     *                         See PPTP_FRAME_CAP_* above.
     *
     *  bearerCapability:      Describes what type of bearer
     *                         capabilities is available to the
     *                         sender of this message. See
     *                         PPTP_BEARER_CAP_* above.
     *
     *  maxChannels:           Total number of channels the
     *                         sender can handle. The receiver
     *                         of the message should not make
     *                         any assumptions on channel 
     *                         availability at any point in time.
     *
     *  firmwareRevision:      The revision of the operating
     *                         firmware of the sender of this 
     *                         message.
     *
     *  hostName:              The hostname of the sender of 
     *                         this message.
     *
     *  vendorString:          A sender-specific ASCII string
     *                         to describe the sender's equipment.
     *                         This string must be NULL-terminated.
     *
     */

typedef struct {
    Word      protocolVersion;
    Byte      resultCode;
    Byte      generalErrorCode;
    LongWord  framingCapability;
    LongWord  bearerCapability;
    Word      maxChannels;
    Word      firmwareRevision;
    Byte      hostName[ 64 ];
    Byte      vendorString[ 64 ];
} PptpStartSessionReply;
Back to table of contents.

3.3.1.2.1 A note about protocol versions

Special attention must be given to the protocol version field during the Session Start Request and Reply phase. Each peer must examine the protocol version field and must "step down" to the lowest common version of the protocol. If the receiver of the Start Reply (that is, the sender of the Start Request) cannot or is not willing to step back, it must close the session by sending a Stop Session Request with the reason field set to PPTP_STOP_PROTOCOL. If the receiver of the Start Request cannot or is not willing to step back, it must send a Start Session Reply with an error code of PPTP_START_UNKNOWN_PROTOCOL.

3.3.1.3 Stop Session Request

The Stop Session Request message is used when one end does not need or want to talk to the peer and wants to close the control channel. All active calls are implicitly cleared.


    /*
     * Possible reasons for stopping a session.
     *
     * PPTP_STOP_NONE:            I felt like it.
     *
     * PPTP_STOP_PROTOCOL:        Can't support your version of the
     *                            PPTP protocol.
     *
     * PPTP_STOP_LOCAL_SHUTDOWN:  I am being shut down.
     */

typedef enum {
    PPTP_STOP_NONE = 1,
    PPTP_STOP_PROTOCOL,
    PPTP_STOP_LOCAL_SHUTDOWN
} PptpStopReasons;
        
    /*
     * The PPTP StopSessionRequest.
     *
     * This command will clear all calls and listens and close the
     * control channel.
     *
     * reason:                    One of PptpStopReasons.
     */

typedef struct {
   Byte         reason;
} PptpStopSessionRequest;
Back to table of contents.

3.3.1.4 Stop Session Reply

This command is the reply to the Stop Session Request. The possible result codes are the following:


    /*
     * The SessionStopReply Result Code.
     *
     * PPTP_STOP_OK:               Control channel closed.
     *
     * PPTP_STOP_GENERAL_ERROR:    See the generalErrorCode field.
     */

typedef enum {
   PPTP_STOP_OK = 1,
   PPTP_STOP_GENERAL_ERROR = 2
} PptpStopSessionResultCode;

    /*
     * The PPTP SessionStopReply packet.
     *
     * resultCode:                One of PptpStopSessionResultCode
     *                            listed above.
     *
     * generalErrorCode:          Contains the general error if
     *                            resultCode is *_GENERAL_ERROR.
     */

typedef struct {
   Byte      resultCode;
   Byte      generalErrorCode;
} PptpStopSessionReply;
Back to table of contents.

3.3.1.5 Echo Request

The Echo Request can be sent by either peer to the other. This command is to be used as a "keep-alive" type command. This packet must be sent by either end after 60 seconds of no activity. If an Echo Reply is not received within 60 seconds, the control channel must be shut down.

The format of the command is the following:


    /*
     * The Echo-Request packet format.
     *
     *  identNumber:      This number is set by the sender of the
     *                    echo request. It is used to match up 
     *                    replies with requests.
     */

typedef struct {
   LongWord      identNumber;
} PptpEchoRequest;
Back to table of contents.

3.3.1.6 Echo Reply

This packet is sent as a response to an Echo Request.

The format for this packet is the following:


    /*
     * PptpEchoReplyResultCode contains the specific result codes 
     * for the resultCode field in the PPTP_ECHO_REPLY message
     *
     * PPTP_ECHO_OK                    The echo reply is valid.
     *
     * PPTP_ECHO_GENERAL_ERROR         A general error has occurred;
     *                                 look at the generalErrorCode
     *                                 field to determine the error.
     */

typedef enum {
    PPTP_ECHO_OK = 1,
    PPTP_ECHO_GENERAL_ERROR
} PptpEchoReplyResultCode;

    /*
     * The Echo-Reply packet format.
     *
     * identNumber:                    Must match the indentNumber of the Echo
     *                                 request.
     *
     * resultCode:                     If non-zero, then generalErrorCode 
     *                                 indicates some sort of error.
     *
     * generalErrorCode:               Contains the general error if non-zero.
     */

typedef struct {
    LongWord      identNumber;
    Byte          resultCode;
    Byte          generalErrorCode;
    Word          reserved;
} PptpEchoReply;
Back to table of contents.