/* * Copyright (c) Likewise Software. All rights Reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Module Name: * * connection-private.h * * Abstract: * * Connection API (private header) * * Authors: Brian Koropoff (bkoropoff@likewisesoftware.com) * */ #ifndef __LWMSG_CONNECTION_PRIVATE_H__ #define __LWMSG_CONNECTION_PRIVATE_H__ #include #include #include #include #include #include "assoc-private.h" #include "util-private.h" #if (defined(HAVE_GETPEEREID) && HAVE_DECL_GETPEEREID) || HAVE_DECL_SO_PEERCRED #define HAVE_PEERID_METHOD #endif #define PACKED __attribute__((packed)) #define CONNECTION_PRIVATE(assoc) ((ConnectionPrivate*) (assoc)) typedef enum ConnectionState { /* No state */ CONNECTION_STATE_NONE, /* Start state */ CONNECTION_STATE_START, /* Begin connect */ CONNECTION_STATE_BEGIN_CONNECT, /* Finish connect() call */ CONNECTION_STATE_FINISH_CONNECT, /* Begin sending handshake */ CONNECTION_STATE_BEGIN_SEND_HANDSHAKE, /* Finish sending handshake */ CONNECTION_STATE_FINISH_SEND_HANDSHAKE, /* Begin receiving handshake */ CONNECTION_STATE_BEGIN_RECV_HANDSHAKE, /* Finish receiving handshake */ CONNECTION_STATE_FINISH_RECV_HANDSHAKE, /* Established */ CONNECTION_STATE_ESTABLISHED, /* Begin a close */ CONNECTION_STATE_BEGIN_CLOSE, /* Finish a close */ CONNECTION_STATE_FINISH_CLOSE, /* Begin a reset */ CONNECTION_STATE_BEGIN_RESET, /* Finish a reset */ CONNECTION_STATE_FINISH_RESET, /* Closed */ CONNECTION_STATE_CLOSED, /* Error */ CONNECTION_STATE_ERROR } ConnectionState; typedef enum ConnectionEvent { /* No event */ CONNECTION_EVENT_NONE, /* Establish session */ CONNECTION_EVENT_ESTABLISH, /* Send a message (start or send fragment) */ CONNECTION_EVENT_SEND, /* Receive a message (start or receive fragment) */ CONNECTION_EVENT_RECV, /* Close connection */ CONNECTION_EVENT_CLOSE, /* Reset connection */ CONNECTION_EVENT_RESET, /* Abort connection */ CONNECTION_EVENT_ABORT, /* Finish operation */ CONNECTION_EVENT_FINISH } ConnectionEvent; typedef struct ConnectionFragment { LWMsgRing ring; unsigned char* cursor; unsigned char data[]; } ConnectionFragment; typedef struct ConnectionBuffer { ConnectionFragment* current; LWMsgRing fragments; size_t fd_capacity; size_t fd_length; int* fd; } ConnectionBuffer; typedef enum ConnectionPacketType { CONNECTION_PACKET_MESSAGE = 1, CONNECTION_PACKET_GREETING = 4, CONNECTION_PACKET_SHUTDOWN = 5 } ConnectionPacketType; typedef struct ConnectionPrivate { LWMsgAssoc base; /* Connection mode */ LWMsgConnectionMode mode; /* Socket file descriptor */ int fd; /* Endpoint string */ char* endpoint; /* Buffer for outgoing packets */ ConnectionBuffer sendbuffer; /* Buffer for incoming packets */ ConnectionBuffer recvbuffer; /* Pending message read */ LWMsgMessage* incoming; /* Pending message write */ LWMsgMessage* outgoing; /* Current state of connection state machine */ ConnectionState state; /* Parameters passed into state machine */ union { LWMsgMessage* message; struct { LWMsgSessionConstructFunction construct; LWMsgSessionDestructFunction destruct; void* construct_data; } establish; } params; /* Timeouts (relative) */ struct { /* Timeout for establishing session */ LWMsgTime establish; /* Timeout for transceiving messages */ LWMsgTime message; /* Currently relevant timeout value */ LWMsgTime* current; } timeout; /* Negotiated packet size */ size_t packet_size; /* Peer security token */ LWMsgSecurityToken* sec_token; /* Session handle */ LWMsgSession* session; /* Flag: this connection is nonblocking */ unsigned is_nonblock:1; /* Marshal handle */ LWMsgDataContext* marshal_context; } ConnectionPrivate; typedef enum ConnectionGreetingFlags { CONNECTION_GREETING_AUTH_LOCAL = 1 } ConnectionGreetingFlags; typedef enum ConnectionPacketFlags { CONNECTION_PACKET_FLAG_FIRST_FRAGMENT = 0x1, CONNECTION_PACKET_FLAG_LAST_FRAGMENT = 0x2 } ConnectionPacketFlags; #define CONNECTION_PACKET_FLAG_SINGLE (CONNECTION_PACKET_FLAG_FIRST_FRAGMENT | CONNECTION_PACKET_FLAG_LAST_FRAGMENT) typedef struct ConnectionPacket { uint32_t length; uint8_t type; uint8_t flags; union { struct ConnectionPacketBase { } PACKED base; struct ConnectionPacketMsg { uint8_t flags; uint32_t status; uint16_t cookie; int16_t tag; } PACKED msg; struct ConnectionPacketGreeting { uint8_t flags; uint32_t packet_size; uint8_t smid[8]; } PACKED greeting; struct ConnectionPacketShutdown { uint32_t status; } PACKED shutdown; } PACKED contents; } PACKED ConnectionPacket; typedef struct LocalTokenPrivate { uid_t euid; gid_t egid; pid_t pid; } LocalTokenPrivate; #define CONNECTION_PACKET_SIZE(_type_) (offsetof(struct ConnectionPacket, contents) + sizeof(struct _type_)) #define MAX_FD_PAYLOAD 256 void lwmsg_connection_buffer_empty( ConnectionBuffer* buffer ); LWMsgStatus lwmsg_connection_buffer_construct( ConnectionBuffer* buffer ); void lwmsg_connection_buffer_destruct( ConnectionBuffer* buffer ); LWMsgStatus lwmsg_connection_buffer_ensure_fd_capacity( ConnectionBuffer* buffer, size_t needed ); LWMsgStatus lwmsg_connection_buffer_create_fragment( ConnectionBuffer* buffer, size_t length, ConnectionFragment** fragment ); void lwmsg_connection_buffer_queue_fragment( ConnectionBuffer* buffer, ConnectionFragment* fragment ); ConnectionFragment* lwmsg_connection_buffer_dequeue_fragment( ConnectionBuffer* buffer ); ConnectionFragment* lwmsg_connection_buffer_get_first_fragment( ConnectionBuffer* buffer ); ConnectionFragment* lwmsg_connection_buffer_get_last_fragment( ConnectionBuffer* buffer ); void lwmsg_connection_buffer_free_fragment( ConnectionBuffer* buffer, ConnectionFragment* fragment ); LWMsgStatus lwmsg_connection_run( LWMsgAssoc* assoc, ConnectionEvent event ); LWMsgStatus lwmsg_connection_queue_fd( LWMsgAssoc* assoc, int fd ); LWMsgStatus lwmsg_connection_dequeue_fd( LWMsgAssoc* assoc, int* out_fd ); LWMsgStatus lwmsg_connection_begin_timeout( LWMsgAssoc* assoc, LWMsgTime* value ); LWMsgStatus lwmsg_connection_send_all_fragments( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_recv_next_fragment( LWMsgAssoc* assoc, ConnectionFragment** fragment ); LWMsgStatus lwmsg_local_token_new( uid_t euid, gid_t egid, pid_t pid, LWMsgSecurityToken** out_token ); LWMsgStatus lwmsg_local_token_from_socket_peer( int fd, LWMsgSecurityToken** out_token ); LWMsgStatus lwmsg_connection_get_endpoint_owner( LWMsgAssoc* assoc, const char* endpoint, uid_t *uid, gid_t *gid ); LWMsgStatus lwmsg_connection_begin_connect( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_finish_connect( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_connect_existing( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_begin_send_handshake( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_finish_send_handshake( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_begin_recv_handshake( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_finish_recv_handshake( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_begin_send_message( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_finish_send_message( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_begin_recv_message( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_finish_recv_message( LWMsgAssoc* assoc ); LWMsgStatus lwmsg_connection_begin_send_shutdown( LWMsgAssoc* assoc, LWMsgStatus reason ); LWMsgStatus lwmsg_connection_finish_send_shutdown( LWMsgAssoc* assoc ); #endif