libipm: Add support for sending file descriptors

This commit is contained in:
matt335672 2023-01-07 17:37:19 +00:00
parent 02a3821f4d
commit 8a71322fe4
4 changed files with 89 additions and 2 deletions

View File

@ -32,6 +32,35 @@
const char *libipm_valid_type_chars = "ybnqiuxtsdhogB";
/**************************************************************************//**
* Send function for a struct trans initialised with libipm_init_trans()
*
* @param trans Transport to send on
* @param data pointer to data to send
* @param len Length of data to send
* @return As for write(2)
*/
static int
libipm_trans_send_proc(struct trans *self, const char *data, int len)
{
int rv;
struct libipm_priv *priv = (struct libipm_priv *)self->extra_data;
if (priv != NULL && data == self->out_s->data)
{
/* We're sending the message header. Send any file descriptors
* as ancillary data */
rv = g_sck_send_fd_set(self->sck, data, len,
priv->out_fds, priv->out_fd_count);
}
else
{
rv = g_sck_send(self->sck, data, len, 0);
}
return rv;
}
/**************************************************************************//**
* Destructor for a struct trans initialised with libipm_init_trans()
*
@ -83,6 +112,7 @@ libipm_init_trans(struct trans *trans,
priv->facility = facility;
priv->msgno_to_str = msgno_to_str;
trans->trans_send = libipm_trans_send_proc;
trans->extra_data = priv;
trans->extra_destructor = libipm_trans_destructor;

View File

@ -67,6 +67,7 @@ enum libipm_status
E_LI_UNIMPLEMENTED_TYPE, /***< Specified type code is unimplemented */
E_LI_UNEXPECTED_TYPE, /***< Encountered unexpected type on input */
E_LI_BUFFER_OVERFLOW, /***< End of buffer reached unexpectedly */
E_LI_TOO_MANY_FDS, /***< Too many file descriptors encountered */
E_LI_BAD_VALUE, /***< Specified (or incoming) value is out of range */
E_LI_BAD_HEADER, /***< Bad incoming message header */
E_LI_TRANSPORT_ERROR /***< Error detected at the transport level */
@ -154,14 +155,17 @@ libipm_msg_out_init(struct trans *trans, unsigned short msgno,
* x |int64_t | Signed (two's complement) 64-bit integer
* t |uint64_t | Unsigned 64-bit integer
* s |char * | NULL-terminated string
* h |int | File descriptor
* d | - | (reserved)
* h | - | (reserved)
* o | - | (reserved)
* g | - | (reserved)
*
* For the 'b' type, only values 0 and 1 are allowed. Other values
* generate an error.
*
* The 'h' type can only be used where the underlying transport is a
* UNIX domain socket.
*
* The following additions to the D-Bus type system are also supported:-
*
* Char |C Type | Description

View File

@ -39,7 +39,12 @@ enum
/**
* Size of libipm header
*/
HEADER_SIZE = 12
HEADER_SIZE = 12,
/**
* Max number of file descriptors in a message
*/
MAX_FD_PER_MSG = 8
};
/**
@ -52,6 +57,8 @@ struct libipm_priv
const char *(*msgno_to_str)(unsigned short msgno);
unsigned short out_msgno;
unsigned short out_param_count;
unsigned short out_fd_count;
int out_fds[MAX_FD_PER_MSG];
unsigned short in_msgno;
unsigned short in_param_count;
};

View File

@ -306,6 +306,47 @@ append_char_ptr_type(char c, struct trans *trans, va_list *argptr)
return rv;
}
/**************************************************************************//**
* Add a file descriptor to the output stream
*
* @param c Type letter which triggered the call
* @param trans libipm transport
* @param argptr Pointer to value in argument stack (promoted to int)
* @return != 0 for error
*/
static enum libipm_status
append_fd_type(char c, va_list *argptr, struct trans *trans)
{
enum libipm_status rv = E_LI_SUCCESS;
struct stream *s = trans->out_s;
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
int fd = va_arg(*argptr, int);
if (fd < 0)
{
log_append_error(trans, "File descriptor cannot be < 0");
rv = E_LI_PROGRAM_ERROR;
}
else if (!s_check_rem_out(s, 1))
{
log_append_error(trans,
"Not enough space in output buffer for '%c'", c);
rv = E_LI_BUFFER_OVERFLOW;
}
else if (priv->out_fd_count >= MAX_FD_PER_MSG)
{
log_append_error(trans,
"Too many file descriptors for '%c'", c);
rv = E_LI_TOO_MANY_FDS;
}
else
{
out_uint8(s, c);
priv->out_fds[priv->out_fd_count++] = fd;
}
return rv;
}
/**************************************************************************//**
* Append a fixed size block to the output stream
*
@ -405,6 +446,10 @@ libipm_msg_out_appendv(struct trans *trans, const char *format, va_list *argptr)
rv = append_char_ptr_type(c, trans, argptr);
break;
case 'h':
rv = append_fd_type(c, argptr, trans);
break;
case 'B':
rv = append_fsb_type(c, trans, argptr);
break;
@ -441,6 +486,7 @@ init_output_buffer(struct trans *trans, unsigned short msgno)
priv->out_msgno = msgno;
priv->out_param_count = 0;
priv->out_fd_count = 0;
}
/*****************************************************************************/