libipm: Add support for receiving file descriptors
This commit is contained in:
parent
8a71322fe4
commit
c9adb3a2a6
@ -32,6 +32,23 @@
|
|||||||
|
|
||||||
const char *libipm_valid_type_chars = "ybnqiuxtsdhogB";
|
const char *libipm_valid_type_chars = "ybnqiuxtsdhogB";
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
void
|
||||||
|
libipm_msg_in_close_file_descriptors(struct trans *self)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)self->extra_data;
|
||||||
|
if (priv != NULL)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = priv->in_fd_index ; i < priv->in_fd_count; ++i)
|
||||||
|
{
|
||||||
|
g_file_close(priv->in_fds[i]);
|
||||||
|
}
|
||||||
|
priv->in_fd_count = 0;
|
||||||
|
priv->in_fd_index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************//**
|
/**************************************************************************//**
|
||||||
* Send function for a struct trans initialised with libipm_init_trans()
|
* Send function for a struct trans initialised with libipm_init_trans()
|
||||||
*
|
*
|
||||||
@ -60,6 +77,52 @@ libipm_trans_send_proc(struct trans *self, const char *data, int len)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Receive function for a struct trans initialised with libipm_init_trans()
|
||||||
|
*
|
||||||
|
* @param trans Transport to receive on
|
||||||
|
* @param data pointer to receive data buffer
|
||||||
|
* @param len Length of data to read
|
||||||
|
* @return As for read(2)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
libipm_trans_recv_proc(struct trans *self, char *data, int len)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)self->extra_data;
|
||||||
|
if (priv != NULL && data == self->in_s->data)
|
||||||
|
{
|
||||||
|
/* We're receiving the message header */
|
||||||
|
unsigned int fdcount;
|
||||||
|
|
||||||
|
/* Check there are no live file descriptors in the input
|
||||||
|
* buffer from a previous message. This shouldn't happen, but
|
||||||
|
* if by some chance it does, we could leak file descriptors */
|
||||||
|
if (priv->in_fd_count > 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_WARNING, "Unconsumed file descriptors detected");
|
||||||
|
libipm_msg_in_close_file_descriptors(self);
|
||||||
|
}
|
||||||
|
rv = g_sck_recv_fd_set(self->sck, data, len,
|
||||||
|
priv->in_fds, MAX_FD_PER_MSG,
|
||||||
|
&fdcount);
|
||||||
|
if (fdcount > MAX_FD_PER_MSG)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_WARNING,
|
||||||
|
"%d file descriptors were discarded on recvmsg()",
|
||||||
|
fdcount - MAX_FD_PER_MSG);
|
||||||
|
fdcount = MAX_FD_PER_MSG;
|
||||||
|
}
|
||||||
|
priv->in_fd_count = fdcount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = g_sck_recv(self->sck, data, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************//**
|
/**************************************************************************//**
|
||||||
* Destructor for a struct trans initialised with libipm_init_trans()
|
* Destructor for a struct trans initialised with libipm_init_trans()
|
||||||
@ -71,6 +134,7 @@ libipm_trans_destructor(struct trans *trans)
|
|||||||
{
|
{
|
||||||
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
|
||||||
|
libipm_msg_in_close_file_descriptors(trans);
|
||||||
if (priv != NULL)
|
if (priv != NULL)
|
||||||
{
|
{
|
||||||
if ((priv->flags & LIBIPM_E_MSG_IN_ERASE_AFTER_USE) != 0 &&
|
if ((priv->flags & LIBIPM_E_MSG_IN_ERASE_AFTER_USE) != 0 &&
|
||||||
@ -113,6 +177,7 @@ libipm_init_trans(struct trans *trans,
|
|||||||
priv->msgno_to_str = msgno_to_str;
|
priv->msgno_to_str = msgno_to_str;
|
||||||
|
|
||||||
trans->trans_send = libipm_trans_send_proc;
|
trans->trans_send = libipm_trans_send_proc;
|
||||||
|
trans->trans_recv = libipm_trans_recv_proc;
|
||||||
trans->extra_data = priv;
|
trans->extra_data = priv;
|
||||||
trans->extra_destructor = libipm_trans_destructor;
|
trans->extra_destructor = libipm_trans_destructor;
|
||||||
|
|
||||||
|
@ -300,8 +300,8 @@ libipm_msg_in_peek_type(struct trans *trans);
|
|||||||
* x | int64_t * | Signed (two's complement) 64-bit integer
|
* x | int64_t * | Signed (two's complement) 64-bit integer
|
||||||
* t | uint64_t * | Unsigned 64-bit integer
|
* t | uint64_t * | Unsigned 64-bit integer
|
||||||
* s | char ** | NULL-terminated string
|
* s | char ** | NULL-terminated string
|
||||||
|
* h | int * | File descriptor
|
||||||
* d | - | (reserved)
|
* d | - | (reserved)
|
||||||
* h | - | (reserved)
|
|
||||||
* o | - | (reserved)
|
* o | - | (reserved)
|
||||||
* g | - | (reserved)
|
* g | - | (reserved)
|
||||||
*
|
*
|
||||||
@ -315,6 +315,9 @@ libipm_msg_in_peek_type(struct trans *trans);
|
|||||||
* returned. This pointer will only be valid until the next call to
|
* returned. This pointer will only be valid until the next call to
|
||||||
* libipm_msg_in_reset()
|
* libipm_msg_in_reset()
|
||||||
*
|
*
|
||||||
|
* The 'h' type can only be used where the underlying transport is a
|
||||||
|
* UNIX domain socket.
|
||||||
|
*
|
||||||
* For the 'B' type, pass in the address of an initialised descriptor
|
* For the 'B' type, pass in the address of an initialised descriptor
|
||||||
* containing the address and size of the object to copy the data
|
* containing the address and size of the object to copy the data
|
||||||
* to. The size in the descriptor must match the size of the object
|
* to. The size in the descriptor must match the size of the object
|
||||||
@ -330,6 +333,9 @@ libipm_msg_in_parse(struct trans *trans, const char *format, ...);
|
|||||||
* If the LIBIPM_E_MSG_IN_ERASE_AFTER_USE flag is set for the transport,
|
* If the LIBIPM_E_MSG_IN_ERASE_AFTER_USE flag is set for the transport,
|
||||||
* the entire buffer is erased, and the flag is cleared
|
* the entire buffer is erased, and the flag is cleared
|
||||||
*
|
*
|
||||||
|
* Any file descriptors received from the other end but not parsed
|
||||||
|
* by the application are closed.
|
||||||
|
*
|
||||||
* @param trans libipm transport
|
* @param trans libipm transport
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
@ -61,6 +61,11 @@ struct libipm_priv
|
|||||||
int out_fds[MAX_FD_PER_MSG];
|
int out_fds[MAX_FD_PER_MSG];
|
||||||
unsigned short in_msgno;
|
unsigned short in_msgno;
|
||||||
unsigned short in_param_count;
|
unsigned short in_param_count;
|
||||||
|
/** Pointer to next fd to be consumed by the app */
|
||||||
|
unsigned short in_fd_index;
|
||||||
|
/** Number of fds in the incoming message */
|
||||||
|
unsigned short in_fd_count;
|
||||||
|
int in_fds[MAX_FD_PER_MSG];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,4 +76,15 @@ struct libipm_priv
|
|||||||
*/
|
*/
|
||||||
extern const char *libipm_valid_type_chars;
|
extern const char *libipm_valid_type_chars;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close input file descriptors for an input message
|
||||||
|
*
|
||||||
|
* If file descriptors are read from the other end, but not passed to the
|
||||||
|
* application, they must be closed to prevent file descriptor leaks
|
||||||
|
*
|
||||||
|
* @param trans Transport to close file descriptors for
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
libipm_msg_in_close_file_descriptors(struct trans *self);
|
||||||
|
|
||||||
#endif /* LIBIPM__PRIVATE_H */
|
#endif /* LIBIPM__PRIVATE_H */
|
||||||
|
@ -460,6 +460,36 @@ extract_char_ptr_type(char c, struct trans *trans, va_list *argptr)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Extract a file descriptor from the input stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr argptr to pointer to receive the value
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
extract_fd_type(char c, struct trans *trans, va_list *argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
|
||||||
|
/* File descriptor available? */
|
||||||
|
if (priv->in_fd_index >= priv->in_fd_count)
|
||||||
|
{
|
||||||
|
log_parse_error(trans, "No file descriptors available");
|
||||||
|
rv = E_LI_TOO_MANY_FDS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int *tmp = va_arg(*argptr, int *);
|
||||||
|
|
||||||
|
*tmp = priv->in_fds[priv->in_fd_index++];
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************//**
|
/**************************************************************************//**
|
||||||
* Extract a fixed size block from the input stream
|
* Extract a fixed size block from the input stream
|
||||||
*
|
*
|
||||||
@ -588,6 +618,10 @@ libipm_msg_in_parsev(struct trans *trans, const char *format, va_list *argptr)
|
|||||||
rv = extract_char_ptr_type(c, trans, argptr);
|
rv = extract_char_ptr_type(c, trans, argptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
rv = extract_fd_type(c, trans, argptr);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'B':
|
case 'B':
|
||||||
rv = extract_fsb_type(c, trans, argptr);
|
rv = extract_fsb_type(c, trans, argptr);
|
||||||
break;
|
break;
|
||||||
@ -650,6 +684,7 @@ libipm_msg_in_reset(struct trans *trans)
|
|||||||
}
|
}
|
||||||
priv->in_msgno = 0;
|
priv->in_msgno = 0;
|
||||||
priv->in_param_count = 0;
|
priv->in_param_count = 0;
|
||||||
|
libipm_msg_in_close_file_descriptors(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
trans->extra_flags = 0;
|
trans->extra_flags = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user