2015-04-14 10:20:05 +03:00
/*
CTDB protocol marshalling
Copyright ( C ) Amitay Isaacs 2015
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "replace.h"
# include "system/network.h"
# include <talloc.h>
# include <tdb.h>
# include "protocol.h"
# include "protocol_api.h"
# include "protocol_private.h"
struct ctdb_req_call_wire {
struct ctdb_req_header hdr ;
uint32_t flags ;
uint32_t db_id ;
uint32_t callid ;
uint32_t hopcount ;
uint32_t keylen ;
uint32_t calldatalen ;
uint8_t data [ 1 ] ; /* key[] followed by calldata[] */
} ;
struct ctdb_reply_call_wire {
struct ctdb_req_header hdr ;
uint32_t status ;
uint32_t datalen ;
uint8_t data [ 1 ] ;
} ;
struct ctdb_reply_error_wire {
struct ctdb_req_header hdr ;
uint32_t status ;
uint32_t msglen ;
uint8_t msg [ 1 ] ;
} ;
struct ctdb_req_dmaster_wire {
struct ctdb_req_header hdr ;
uint32_t db_id ;
uint64_t rsn ;
uint32_t dmaster ;
uint32_t keylen ;
uint32_t datalen ;
uint8_t data [ 1 ] ;
} ;
struct ctdb_reply_dmaster_wire {
struct ctdb_req_header hdr ;
uint32_t db_id ;
uint64_t rsn ;
uint32_t keylen ;
uint32_t datalen ;
uint8_t data [ 1 ] ;
} ;
int ctdb_req_call_push ( struct ctdb_req_header * h , struct ctdb_req_call * c ,
TALLOC_CTX * mem_ctx , uint8_t * * pkt , size_t * pkt_len )
{
struct ctdb_req_call_wire * wire ;
uint8_t * buf ;
size_t length , buflen ;
int ret ;
if ( c - > key . dsize = = 0 ) {
return EINVAL ;
}
length = offsetof ( struct ctdb_req_call_wire , data ) +
2016-04-21 16:50:01 +03:00
ctdb_tdb_data_len ( c - > key ) +
ctdb_tdb_data_len ( c - > calldata ) ;
2015-04-14 10:20:05 +03:00
ret = allocate_pkt ( mem_ctx , length , & buf , & buflen ) ;
if ( ret ! = 0 ) {
return ret ;
}
wire = ( struct ctdb_req_call_wire * ) buf ;
h - > length = buflen ;
2016-04-21 17:19:49 +03:00
ctdb_req_header_push ( h , ( uint8_t * ) & wire - > hdr ) ;
2015-04-14 10:20:05 +03:00
wire - > flags = c - > flags ;
wire - > db_id = c - > db_id ;
wire - > callid = c - > callid ;
wire - > hopcount = c - > hopcount ;
2016-04-21 16:50:01 +03:00
wire - > keylen = ctdb_tdb_data_len ( c - > key ) ;
wire - > calldatalen = ctdb_tdb_data_len ( c - > calldata ) ;
ctdb_tdb_data_push ( c - > key , wire - > data ) ;
ctdb_tdb_data_push ( c - > calldata , wire - > data + wire - > keylen ) ;
2015-04-14 10:20:05 +03:00
* pkt = buf ;
* pkt_len = buflen ;
return 0 ;
}
int ctdb_req_call_pull ( uint8_t * pkt , size_t pkt_len ,
struct ctdb_req_header * h ,
TALLOC_CTX * mem_ctx ,
struct ctdb_req_call * c )
{
struct ctdb_req_call_wire * wire ;
size_t length ;
2016-04-21 16:50:01 +03:00
int ret ;
2015-04-14 10:20:05 +03:00
length = offsetof ( struct ctdb_req_call_wire , data ) ;
if ( pkt_len < length ) {
return EMSGSIZE ;
}
wire = ( struct ctdb_req_call_wire * ) pkt ;
if ( pkt_len < length + wire - > keylen + wire - > calldatalen ) {
return EMSGSIZE ;
}
2016-03-10 07:43:37 +03:00
if ( h ! = NULL ) {
2016-04-21 17:19:49 +03:00
ret = ctdb_req_header_pull ( ( uint8_t * ) & wire - > hdr , pkt_len , h ) ;
if ( ret ! = 0 ) {
return ret ;
}
2016-03-10 07:43:37 +03:00
}
2015-04-14 10:20:05 +03:00
c - > flags = wire - > flags ;
c - > db_id = wire - > db_id ;
c - > callid = wire - > callid ;
c - > hopcount = wire - > hopcount ;
2016-04-21 16:50:01 +03:00
ret = ctdb_tdb_data_pull ( wire - > data , wire - > keylen , mem_ctx , & c - > key ) ;
if ( ret ! = 0 ) {
return ret ;
2015-04-14 10:20:05 +03:00
}
2016-04-21 16:50:01 +03:00
ret = ctdb_tdb_data_pull ( wire - > data + wire - > keylen , wire - > calldatalen ,
mem_ctx , & c - > calldata ) ;
if ( ret ! = 0 ) {
return ret ;
2015-04-14 10:20:05 +03:00
}
return 0 ;
}
int ctdb_reply_call_push ( struct ctdb_req_header * h , struct ctdb_reply_call * c ,
TALLOC_CTX * mem_ctx , uint8_t * * pkt , size_t * pkt_len )
{
struct ctdb_reply_call_wire * wire ;
uint8_t * buf ;
size_t length , buflen ;
int ret ;
2016-04-21 16:50:01 +03:00
length = offsetof ( struct ctdb_reply_call_wire , data ) +
ctdb_tdb_data_len ( c - > data ) ;
2015-04-14 10:20:05 +03:00
ret = allocate_pkt ( mem_ctx , length , & buf , & buflen ) ;
if ( ret ! = 0 ) {
return ret ;
}
wire = ( struct ctdb_reply_call_wire * ) buf ;
h - > length = buflen ;
2016-04-21 17:19:49 +03:00
ctdb_req_header_push ( h , ( uint8_t * ) & wire - > hdr ) ;
2015-04-14 10:20:05 +03:00
wire - > status = c - > status ;
2016-04-21 16:50:01 +03:00
wire - > datalen = ctdb_tdb_data_len ( c - > data ) ;
ctdb_tdb_data_push ( c - > data , wire - > data ) ;
2015-04-14 10:20:05 +03:00
* pkt = buf ;
* pkt_len = buflen ;
return 0 ;
}
int ctdb_reply_call_pull ( uint8_t * pkt , size_t pkt_len ,
struct ctdb_req_header * h ,
TALLOC_CTX * mem_ctx ,
struct ctdb_reply_call * c )
{
struct ctdb_reply_call_wire * wire ;
size_t length ;
2016-04-21 16:50:01 +03:00
int ret ;
2015-04-14 10:20:05 +03:00
length = offsetof ( struct ctdb_reply_call_wire , data ) ;
if ( pkt_len < length ) {
return EMSGSIZE ;
}
wire = ( struct ctdb_reply_call_wire * ) pkt ;
if ( pkt_len < length + wire - > datalen ) {
return EMSGSIZE ;
}
2016-03-10 07:43:37 +03:00
if ( h ! = NULL ) {
2016-04-21 17:19:49 +03:00
ret = ctdb_req_header_pull ( ( uint8_t * ) & wire - > hdr , pkt_len , h ) ;
if ( ret ! = 0 ) {
return ret ;
}
2016-03-10 07:43:37 +03:00
}
2015-04-14 10:20:05 +03:00
c - > status = wire - > status ;
2016-04-21 16:50:01 +03:00
ret = ctdb_tdb_data_pull ( wire - > data , wire - > datalen , mem_ctx , & c - > data ) ;
if ( ret ! = 0 ) {
return ret ;
2015-04-14 10:20:05 +03:00
}
return 0 ;
}
int ctdb_reply_error_push ( struct ctdb_req_header * h , struct ctdb_reply_error * c ,
TALLOC_CTX * mem_ctx , uint8_t * * pkt , size_t * pkt_len )
{
struct ctdb_reply_error_wire * wire ;
uint8_t * buf ;
size_t length , buflen ;
int ret ;
2016-04-21 16:50:01 +03:00
length = offsetof ( struct ctdb_reply_error_wire , msg ) +
ctdb_tdb_data_len ( c - > msg ) ;
2015-04-14 10:20:05 +03:00
ret = allocate_pkt ( mem_ctx , length , & buf , & buflen ) ;
if ( ret ! = 0 ) {
return ret ;
}
wire = ( struct ctdb_reply_error_wire * ) buf ;
h - > length = buflen ;
2016-04-21 17:19:49 +03:00
ctdb_req_header_push ( h , ( uint8_t * ) & wire - > hdr ) ;
2015-04-14 10:20:05 +03:00
wire - > status = c - > status ;
2016-04-21 16:50:01 +03:00
wire - > msglen = ctdb_tdb_data_len ( c - > msg ) ;
ctdb_tdb_data_push ( c - > msg , wire - > msg ) ;
2015-04-14 10:20:05 +03:00
* pkt = buf ;
* pkt_len = buflen ;
return 0 ;
}
int ctdb_reply_error_pull ( uint8_t * pkt , size_t pkt_len ,
struct ctdb_req_header * h ,
TALLOC_CTX * mem_ctx ,
struct ctdb_reply_error * c )
{
struct ctdb_reply_error_wire * wire ;
size_t length ;
2016-04-21 16:50:01 +03:00
int ret ;
2015-04-14 10:20:05 +03:00
length = offsetof ( struct ctdb_reply_error_wire , msg ) ;
if ( pkt_len < length ) {
return EMSGSIZE ;
}
wire = ( struct ctdb_reply_error_wire * ) pkt ;
if ( pkt_len < length + wire - > msglen ) {
return EMSGSIZE ;
}
2016-03-10 07:43:37 +03:00
if ( h ! = NULL ) {
2016-04-21 17:19:49 +03:00
ret = ctdb_req_header_pull ( ( uint8_t * ) & wire - > hdr , pkt_len , h ) ;
if ( ret ! = 0 ) {
return ret ;
}
2016-03-10 07:43:37 +03:00
}
2015-04-14 10:20:05 +03:00
c - > status = wire - > status ;
2016-04-21 16:50:01 +03:00
ret = ctdb_tdb_data_pull ( wire - > msg , wire - > msglen , mem_ctx , & c - > msg ) ;
if ( ret ! = 0 ) {
return ret ;
2015-04-14 10:20:05 +03:00
}
return 0 ;
}
int ctdb_req_dmaster_push ( struct ctdb_req_header * h , struct ctdb_req_dmaster * c ,
TALLOC_CTX * mem_ctx , uint8_t * * pkt , size_t * pkt_len )
{
struct ctdb_req_dmaster_wire * wire ;
uint8_t * buf ;
size_t length , buflen ;
int ret ;
length = offsetof ( struct ctdb_req_dmaster_wire , data ) +
2016-04-21 16:50:01 +03:00
ctdb_tdb_data_len ( c - > key ) +
ctdb_tdb_data_len ( c - > data ) ;
2015-04-14 10:20:05 +03:00
ret = allocate_pkt ( mem_ctx , length , & buf , & buflen ) ;
if ( ret ! = 0 ) {
return ret ;
}
wire = ( struct ctdb_req_dmaster_wire * ) buf ;
h - > length = buflen ;
2016-04-21 17:19:49 +03:00
ctdb_req_header_push ( h , ( uint8_t * ) & wire - > hdr ) ;
2015-04-14 10:20:05 +03:00
wire - > db_id = c - > db_id ;
wire - > rsn = c - > rsn ;
wire - > dmaster = c - > dmaster ;
2016-04-21 16:50:01 +03:00
wire - > keylen = ctdb_tdb_data_len ( c - > key ) ;
wire - > datalen = ctdb_tdb_data_len ( c - > data ) ;
ctdb_tdb_data_push ( c - > key , wire - > data ) ;
ctdb_tdb_data_push ( c - > data , wire - > data + wire - > keylen ) ;
2015-04-14 10:20:05 +03:00
* pkt = buf ;
* pkt_len = buflen ;
return 0 ;
}
int ctdb_req_dmaster_pull ( uint8_t * pkt , size_t pkt_len ,
struct ctdb_req_header * h ,
TALLOC_CTX * mem_ctx ,
struct ctdb_req_dmaster * c )
{
struct ctdb_req_dmaster_wire * wire ;
size_t length ;
2016-04-21 16:50:01 +03:00
int ret ;
2015-04-14 10:20:05 +03:00
length = offsetof ( struct ctdb_req_dmaster_wire , data ) ;
if ( pkt_len < length ) {
return EMSGSIZE ;
}
wire = ( struct ctdb_req_dmaster_wire * ) pkt ;
if ( pkt_len < length + wire - > keylen + wire - > datalen ) {
return EMSGSIZE ;
}
2016-03-10 07:43:37 +03:00
if ( h ! = NULL ) {
2016-04-21 17:19:49 +03:00
ret = ctdb_req_header_pull ( ( uint8_t * ) & wire - > hdr , pkt_len , h ) ;
if ( ret ! = 0 ) {
return ret ;
}
2016-03-10 07:43:37 +03:00
}
2015-04-14 10:20:05 +03:00
c - > db_id = wire - > db_id ;
c - > rsn = wire - > rsn ;
c - > dmaster = wire - > dmaster ;
2016-04-21 16:50:01 +03:00
ret = ctdb_tdb_data_pull ( wire - > data , wire - > keylen , mem_ctx , & c - > key ) ;
if ( ret ! = 0 ) {
return ret ;
2015-04-14 10:20:05 +03:00
}
2016-04-21 16:50:01 +03:00
ret = ctdb_tdb_data_pull ( wire - > data + wire - > keylen , wire - > datalen ,
mem_ctx , & c - > data ) ;
if ( ret ! = 0 ) {
return ret ;
2015-04-14 10:20:05 +03:00
}
return 0 ;
}
int ctdb_reply_dmaster_push ( struct ctdb_req_header * h ,
struct ctdb_reply_dmaster * c ,
TALLOC_CTX * mem_ctx , uint8_t * * pkt , size_t * pkt_len )
{
struct ctdb_reply_dmaster_wire * wire ;
uint8_t * buf ;
size_t length , buflen ;
int ret ;
length = offsetof ( struct ctdb_reply_dmaster_wire , data ) +
2016-04-21 16:50:01 +03:00
ctdb_tdb_data_len ( c - > key ) +
ctdb_tdb_data_len ( c - > data ) ;
2015-04-14 10:20:05 +03:00
ret = allocate_pkt ( mem_ctx , length , & buf , & buflen ) ;
if ( ret ! = 0 ) {
return ret ;
}
wire = ( struct ctdb_reply_dmaster_wire * ) buf ;
h - > length = buflen ;
2016-04-21 17:19:49 +03:00
ctdb_req_header_push ( h , ( uint8_t * ) & wire - > hdr ) ;
2015-04-14 10:20:05 +03:00
wire - > db_id = c - > db_id ;
wire - > rsn = c - > rsn ;
2016-04-21 16:50:01 +03:00
wire - > keylen = ctdb_tdb_data_len ( c - > key ) ;
wire - > datalen = ctdb_tdb_data_len ( c - > data ) ;
ctdb_tdb_data_push ( c - > key , wire - > data ) ;
ctdb_tdb_data_push ( c - > data , wire - > data + wire - > keylen ) ;
2015-04-14 10:20:05 +03:00
* pkt = buf ;
* pkt_len = buflen ;
return 0 ;
}
int ctdb_reply_dmaster_pull ( uint8_t * pkt , size_t pkt_len ,
struct ctdb_req_header * h ,
TALLOC_CTX * mem_ctx ,
struct ctdb_reply_dmaster * c )
{
struct ctdb_reply_dmaster_wire * wire ;
size_t length ;
2016-04-21 16:50:01 +03:00
int ret ;
2015-04-14 10:20:05 +03:00
length = offsetof ( struct ctdb_reply_dmaster_wire , data ) ;
if ( pkt_len < length ) {
return EMSGSIZE ;
}
wire = ( struct ctdb_reply_dmaster_wire * ) pkt ;
if ( pkt_len < length + wire - > keylen + wire - > datalen ) {
return EMSGSIZE ;
}
2016-03-10 07:43:37 +03:00
if ( h ! = NULL ) {
2016-04-21 17:19:49 +03:00
ret = ctdb_req_header_pull ( ( uint8_t * ) & wire - > hdr , pkt_len , h ) ;
if ( ret ! = 0 ) {
return ret ;
}
2016-03-10 07:43:37 +03:00
}
2015-04-14 10:20:05 +03:00
c - > db_id = wire - > db_id ;
c - > rsn = wire - > rsn ;
2016-04-21 16:50:01 +03:00
ret = ctdb_tdb_data_pull ( wire - > data , wire - > keylen , mem_ctx , & c - > key ) ;
if ( ret ! = 0 ) {
return ret ;
2015-04-14 10:20:05 +03:00
}
2016-04-21 16:50:01 +03:00
ret = ctdb_tdb_data_pull ( wire - > data + wire - > keylen , wire - > datalen ,
mem_ctx , & c - > data ) ;
if ( ret ! = 0 ) {
return ret ;
2015-04-14 10:20:05 +03:00
}
return 0 ;
}