2003-10-30 11:32:26 +03:00
/*
Unix SMB / CIFS implementation .
2003-11-03 09:22:45 +03:00
2003-10-30 11:32:26 +03:00
libndr interface
2003-11-03 09:22:45 +03:00
2003-10-30 11:32:26 +03:00
Copyright ( C ) Andrew Tridgell 2003
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-10-30 11:32:26 +03:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-10-30 11:32:26 +03:00
*/
/*
2003-11-03 09:22:45 +03:00
this provides the core routines for NDR parsing functions
see http : //www.opengroup.org/onlinepubs/9629399/chap14.htm for details
of NDR encoding rules
2003-10-30 11:32:26 +03:00
*/
# include "includes.h"
2006-03-18 18:42:57 +03:00
# include "librpc/ndr/libndr.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2008-10-13 18:09:48 +04:00
# if _SAMBA_BUILD_ == 4
2007-12-14 00:46:09 +03:00
# include "param/param.h"
2008-10-13 18:09:48 +04:00
# endif
2003-10-30 11:32:26 +03:00
2003-11-05 02:12:44 +03:00
# define NDR_BASE_MARSHALL_SIZE 1024
2005-12-27 19:47:09 +03:00
/* this guid indicates NDR encoding in a protocol tower */
2007-08-18 10:57:49 +04:00
const struct ndr_syntax_id ndr_transfer_syntax = {
2005-12-27 19:47:09 +03:00
{ 0x8a885d04 , 0x1ceb , 0x11c9 , { 0x9f , 0xe8 } , { 0x08 , 0x00 , 0x2b , 0x10 , 0x48 , 0x60 } } ,
2
} ;
2007-08-18 10:57:49 +04:00
const struct ndr_syntax_id ndr64_transfer_syntax = {
2005-12-27 19:47:09 +03:00
{ 0x71710533 , 0xbeba , 0x4937 , { 0x83 , 0x19 } , { 0xb5 , 0xdb , 0xef , 0x9c , 0xcc , 0x36 } } ,
1
} ;
2003-11-23 09:28:12 +03:00
/*
work out the number of bytes needed to align on a n byte boundary
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ size_t ndr_align_size ( uint32_t offset , size_t n )
2003-11-23 09:28:12 +03:00
{
if ( ( offset & ( n - 1 ) ) = = 0 ) return 0 ;
return n - ( offset & ( n - 1 ) ) ;
}
2003-10-30 11:32:26 +03:00
/*
initialise a ndr parse structure from a data blob
*/
2007-12-14 00:46:27 +03:00
_PUBLIC_ struct ndr_pull * ndr_pull_init_blob ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx , struct smb_iconv_convenience * iconv_convenience )
2003-10-30 11:32:26 +03:00
{
2003-11-03 09:22:45 +03:00
struct ndr_pull * ndr ;
2003-10-30 11:32:26 +03:00
2005-01-27 10:08:20 +03:00
ndr = talloc_zero ( mem_ctx , struct ndr_pull ) ;
2003-10-30 11:32:26 +03:00
if ( ! ndr ) return NULL ;
2005-08-18 05:24:08 +04:00
ndr - > current_mem_ctx = mem_ctx ;
2003-10-30 11:32:26 +03:00
ndr - > data = blob - > data ;
ndr - > data_size = blob - > length ;
2007-12-14 00:46:27 +03:00
ndr - > iconv_convenience = talloc_reference ( ndr , iconv_convenience ) ;
2003-10-30 11:32:26 +03:00
return ndr ;
}
/*
advance by ' size ' bytes
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_advance ( struct ndr_pull * ndr , uint32_t size )
2003-10-30 11:32:26 +03:00
{
ndr - > offset + = size ;
if ( ndr - > offset > ndr - > data_size ) {
2003-11-22 11:11:32 +03:00
return ndr_pull_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_pull_advance by %u failed " ,
size ) ;
2003-10-30 11:32:26 +03:00
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-10-30 11:32:26 +03:00
}
/*
set the parse offset to ' ofs '
*/
2007-11-09 21:23:40 +03:00
static enum ndr_err_code ndr_pull_set_offset ( struct ndr_pull * ndr , uint32_t ofs )
2003-10-30 11:32:26 +03:00
{
ndr - > offset = ofs ;
if ( ndr - > offset > ndr - > data_size ) {
2003-11-22 11:11:32 +03:00
return ndr_pull_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_pull_set_offset %u failed " ,
ofs ) ;
2003-10-30 11:32:26 +03:00
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-10-30 11:32:26 +03:00
}
2003-11-03 09:22:45 +03:00
/* create a ndr_push structure, ready for some marshalling */
2007-12-14 00:46:23 +03:00
_PUBLIC_ struct ndr_push * ndr_push_init_ctx ( TALLOC_CTX * mem_ctx , struct smb_iconv_convenience * iconv_convenience )
2003-11-03 09:22:45 +03:00
{
struct ndr_push * ndr ;
2005-01-27 10:08:20 +03:00
ndr = talloc_zero ( mem_ctx , struct ndr_push ) ;
2003-11-03 09:22:45 +03:00
if ( ! ndr ) {
return NULL ;
}
ndr - > flags = 0 ;
ndr - > alloc_size = NDR_BASE_MARSHALL_SIZE ;
2005-01-27 10:08:20 +03:00
ndr - > data = talloc_array ( ndr , uint8_t , ndr - > alloc_size ) ;
2003-11-03 09:22:45 +03:00
if ( ! ndr - > data ) {
return NULL ;
}
2007-12-14 00:46:23 +03:00
ndr - > iconv_convenience = talloc_reference ( ndr , iconv_convenience ) ;
2004-08-12 09:15:41 +04:00
2003-11-03 09:22:45 +03:00
return ndr ;
}
/* return a DATA_BLOB structure for the current ndr_push marshalled data */
2006-03-05 20:15:19 +03:00
_PUBLIC_ DATA_BLOB ndr_push_blob ( struct ndr_push * ndr )
2003-11-03 09:22:45 +03:00
{
DATA_BLOB blob ;
2007-11-08 11:07:51 +03:00
blob = data_blob_const ( ndr - > data , ndr - > offset ) ;
2005-07-17 13:13:05 +04:00
if ( ndr - > alloc_size > ndr - > offset ) {
ndr - > data [ ndr - > offset ] = 0 ;
}
2003-11-03 09:22:45 +03:00
return blob ;
}
/*
2007-03-13 07:18:07 +03:00
expand the available space in the buffer to ndr - > offset + extra_size
2003-11-03 09:22:45 +03:00
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_expand ( struct ndr_push * ndr , uint32_t extra_size )
2003-11-03 09:22:45 +03:00
{
2007-03-13 07:18:07 +03:00
uint32_t size = extra_size + ndr - > offset ;
if ( size < ndr - > offset ) {
/* extra_size overflowed the offset */
2007-03-13 07:42:49 +03:00
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE , " Overflow in push_expand to %u " ,
size ) ;
2007-03-13 07:18:07 +03:00
}
2005-07-17 13:08:19 +04:00
if ( ndr - > alloc_size > size ) {
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-03 09:22:45 +03:00
}
2003-11-12 08:34:21 +03:00
ndr - > alloc_size + = NDR_BASE_MARSHALL_SIZE ;
2005-07-17 13:08:19 +04:00
if ( size + 1 > ndr - > alloc_size ) {
ndr - > alloc_size = size + 1 ;
2003-11-12 08:34:21 +03:00
}
2005-01-07 07:39:16 +03:00
ndr - > data = talloc_realloc ( ndr , ndr - > data , uint8_t , ndr - > alloc_size ) ;
2003-11-03 09:22:45 +03:00
if ( ! ndr - > data ) {
2003-11-22 11:11:32 +03:00
return ndr_push_error ( ndr , NDR_ERR_ALLOC , " Failed to push_expand to %u " ,
ndr - > alloc_size ) ;
2003-11-03 09:22:45 +03:00
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-03 09:22:45 +03:00
}
2008-10-13 17:17:41 +04:00
_PUBLIC_ void ndr_print_debug_helper ( struct ndr_print * ndr , const char * format , . . . )
2003-11-11 07:04:36 +03:00
{
va_list ap ;
char * s = NULL ;
2008-10-13 17:17:41 +04:00
int i , ret ;
2003-11-11 07:04:36 +03:00
va_start ( ap , format ) ;
2008-10-13 17:17:41 +04:00
ret = vasprintf ( & s , format , ap ) ;
2003-11-11 07:04:36 +03:00
va_end ( ap ) ;
2008-10-13 17:17:41 +04:00
if ( ret = = - 1 ) {
return ;
}
2003-11-11 07:04:36 +03:00
for ( i = 0 ; i < ndr - > depth ; i + + ) {
2009-02-14 15:18:28 +03:00
DEBUGADD ( 1 , ( " " ) ) ;
2003-11-11 07:04:36 +03:00
}
2009-02-14 15:18:28 +03:00
DEBUGADD ( 1 , ( " %s \n " , s ) ) ;
2003-11-11 07:04:36 +03:00
free ( s ) ;
}
2008-04-02 06:53:27 +04:00
_PUBLIC_ void ndr_print_string_helper ( struct ndr_print * ndr , const char * format , . . . )
2005-12-31 07:29:34 +03:00
{
va_list ap ;
int i ;
for ( i = 0 ; i < ndr - > depth ; i + + ) {
2007-09-15 03:21:00 +04:00
ndr - > private_data = talloc_asprintf_append_buffer (
2007-09-07 19:08:14 +04:00
( char * ) ndr - > private_data , " " ) ;
2005-12-31 07:29:34 +03:00
}
va_start ( ap , format ) ;
2007-09-15 03:21:00 +04:00
ndr - > private_data = talloc_vasprintf_append_buffer ( ( char * ) ndr - > private_data ,
2007-09-07 19:08:14 +04:00
format , ap ) ;
2005-12-31 07:29:34 +03:00
va_end ( ap ) ;
2007-09-15 03:21:00 +04:00
ndr - > private_data = talloc_asprintf_append_buffer ( ( char * ) ndr - > private_data ,
2007-09-07 19:08:14 +04:00
" \n " ) ;
2005-12-31 07:29:34 +03:00
}
2003-11-11 07:04:36 +03:00
/*
a useful helper function for printing idl structures via DEBUG ( )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_debug ( ndr_print_fn_t fn , const char * name , void * ptr )
2003-11-11 07:04:36 +03:00
{
2004-08-21 11:43:29 +04:00
struct ndr_print * ndr ;
2003-11-11 07:04:36 +03:00
2009-02-14 15:18:28 +03:00
DEBUG ( 1 , ( " " ) ) ;
2009-01-17 20:13:31 +03:00
2005-04-04 09:52:53 +04:00
ndr = talloc_zero ( NULL , struct ndr_print ) ;
2004-08-21 11:43:29 +04:00
if ( ! ndr ) return ;
ndr - > print = ndr_print_debug_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
fn ( ndr , name , ptr ) ;
talloc_free ( ndr ) ;
2003-11-11 07:04:36 +03:00
}
2003-11-11 07:38:51 +03:00
2005-05-11 03:33:56 +04:00
/*
a useful helper function for printing idl unions via DEBUG ( )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_union_debug ( ndr_print_fn_t fn , const char * name , uint32_t level , void * ptr )
2005-05-11 03:33:56 +04:00
{
struct ndr_print * ndr ;
2009-02-14 15:18:28 +03:00
DEBUG ( 1 , ( " " ) ) ;
2009-01-17 20:13:31 +03:00
2005-05-11 03:33:56 +04:00
ndr = talloc_zero ( NULL , struct ndr_print ) ;
if ( ! ndr ) return ;
ndr - > print = ndr_print_debug_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
ndr_print_set_switch_value ( ndr , ptr , level ) ;
fn ( ndr , name , ptr ) ;
talloc_free ( ndr ) ;
}
2003-11-17 14:55:56 +03:00
/*
a useful helper function for printing idl function calls via DEBUG ( )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_function_debug ( ndr_print_function_t fn , const char * name , int flags , void * ptr )
2003-11-17 14:55:56 +03:00
{
2004-08-21 11:43:29 +04:00
struct ndr_print * ndr ;
2003-11-17 14:55:56 +03:00
2009-02-14 15:18:28 +03:00
DEBUG ( 1 , ( " " ) ) ;
2009-01-17 20:13:31 +03:00
2005-04-04 09:52:53 +04:00
ndr = talloc_zero ( NULL , struct ndr_print ) ;
2004-08-21 11:43:29 +04:00
if ( ! ndr ) return ;
ndr - > print = ndr_print_debug_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
2009-09-03 06:50:19 +04:00
/* this is a s4 hack until we build up the courage to pass
* this all the way down
*/
# if _SAMBA_BUILD_ == 4
2009-08-25 19:39:06 +04:00
ndr - > iconv_convenience = smb_iconv_convenience_init ( talloc_autofree_context ( ) , " ASCII " , " UTF-8 " , true ) ;
2009-09-03 06:50:19 +04:00
# endif
2004-08-21 11:43:29 +04:00
fn ( ndr , name , flags , ptr ) ;
talloc_free ( ndr ) ;
2003-11-17 14:55:56 +03:00
}
2006-05-15 18:38:04 +04:00
/*
a useful helper function for printing idl structures to a string
*/
_PUBLIC_ char * ndr_print_struct_string ( TALLOC_CTX * mem_ctx , ndr_print_fn_t fn , const char * name , void * ptr )
{
struct ndr_print * ndr ;
char * ret = NULL ;
ndr = talloc_zero ( mem_ctx , struct ndr_print ) ;
if ( ! ndr ) return NULL ;
ndr - > private_data = talloc_strdup ( ndr , " " ) ;
if ( ! ndr - > private_data ) {
goto failed ;
}
ndr - > print = ndr_print_string_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
2009-09-03 06:50:19 +04:00
/* this is a s4 hack until we build up the courage to pass
* this all the way down
*/
# if _SAMBA_BUILD_ == 4
ndr - > iconv_convenience = smb_iconv_convenience_init ( talloc_autofree_context ( ) , " ASCII " , " UTF-8 " , true ) ;
# endif
2006-05-15 18:38:04 +04:00
fn ( ndr , name , ptr ) ;
2007-09-07 19:08:14 +04:00
ret = talloc_steal ( mem_ctx , ( char * ) ndr - > private_data ) ;
2006-05-15 18:38:04 +04:00
failed :
talloc_free ( ndr ) ;
return ret ;
}
/*
a useful helper function for printing idl unions to a string
*/
_PUBLIC_ char * ndr_print_union_string ( TALLOC_CTX * mem_ctx , ndr_print_fn_t fn , const char * name , uint32_t level , void * ptr )
{
struct ndr_print * ndr ;
char * ret = NULL ;
ndr = talloc_zero ( mem_ctx , struct ndr_print ) ;
if ( ! ndr ) return NULL ;
ndr - > private_data = talloc_strdup ( ndr , " " ) ;
if ( ! ndr - > private_data ) {
goto failed ;
}
ndr - > print = ndr_print_string_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
ndr_print_set_switch_value ( ndr , ptr , level ) ;
fn ( ndr , name , ptr ) ;
2007-09-07 19:08:14 +04:00
ret = talloc_steal ( mem_ctx , ( char * ) ndr - > private_data ) ;
2006-05-15 18:38:04 +04:00
failed :
talloc_free ( ndr ) ;
return ret ;
}
2005-12-31 07:29:34 +03:00
/*
a useful helper function for printing idl function calls to a string
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * ndr_print_function_string ( TALLOC_CTX * mem_ctx ,
2005-12-31 07:29:34 +03:00
ndr_print_function_t fn , const char * name ,
int flags , void * ptr )
{
struct ndr_print * ndr ;
2006-01-11 23:38:10 +03:00
char * ret = NULL ;
2005-12-31 07:29:34 +03:00
ndr = talloc_zero ( mem_ctx , struct ndr_print ) ;
if ( ! ndr ) return NULL ;
2006-05-04 15:01:10 +04:00
ndr - > private_data = talloc_strdup ( ndr , " " ) ;
if ( ! ndr - > private_data ) {
2006-01-11 23:38:10 +03:00
goto failed ;
}
2005-12-31 07:29:34 +03:00
ndr - > print = ndr_print_string_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
fn ( ndr , name , flags , ptr ) ;
2007-09-07 19:08:14 +04:00
ret = talloc_steal ( mem_ctx , ( char * ) ndr - > private_data ) ;
2006-01-11 23:38:10 +03:00
failed :
2005-12-31 07:29:34 +03:00
talloc_free ( ndr ) ;
2006-01-10 00:59:42 +03:00
return ret ;
2005-12-31 07:29:34 +03:00
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_set_flags ( uint32_t * pflags , uint32_t new_flags )
2004-10-14 13:07:41 +04:00
{
/* the big/little endian flags are inter-dependent */
if ( new_flags & LIBNDR_FLAG_LITTLE_ENDIAN ) {
( * pflags ) & = ~ LIBNDR_FLAG_BIGENDIAN ;
2009-09-17 20:08:47 +04:00
( * pflags ) & = ~ LIBNDR_FLAG_NDR64 ;
2004-10-14 13:07:41 +04:00
}
if ( new_flags & LIBNDR_FLAG_BIGENDIAN ) {
( * pflags ) & = ~ LIBNDR_FLAG_LITTLE_ENDIAN ;
2009-09-17 20:08:47 +04:00
( * pflags ) & = ~ LIBNDR_FLAG_NDR64 ;
2004-10-14 13:07:41 +04:00
}
2005-09-10 12:46:28 +04:00
if ( new_flags & LIBNDR_FLAG_REMAINING ) {
( * pflags ) & = ~ LIBNDR_ALIGN_FLAGS ;
}
if ( new_flags & LIBNDR_ALIGN_FLAGS ) {
( * pflags ) & = ~ LIBNDR_FLAG_REMAINING ;
}
2004-10-14 13:07:41 +04:00
( * pflags ) | = new_flags ;
}
2003-11-22 11:11:32 +03:00
2003-11-13 12:26:53 +03:00
/*
return and possibly log an NDR error
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_error ( struct ndr_pull * ndr ,
2006-03-22 17:33:06 +03:00
enum ndr_err_code ndr_err ,
2008-04-02 06:53:27 +04:00
const char * format , . . . )
2003-11-13 12:26:53 +03:00
{
char * s = NULL ;
va_list ap ;
2008-10-13 17:17:41 +04:00
int ret ;
2003-11-13 12:26:53 +03:00
va_start ( ap , format ) ;
2008-10-13 17:17:41 +04:00
ret = vasprintf ( & s , format , ap ) ;
2003-11-13 12:26:53 +03:00
va_end ( ap ) ;
2008-10-13 17:17:41 +04:00
if ( ret = = - 1 ) {
return NDR_ERR_ALLOC ;
}
DEBUG ( 1 , ( " ndr_pull_error(%u): %s \n " , ndr_err , s ) ) ;
2003-11-13 12:26:53 +03:00
free ( s ) ;
2003-11-22 11:11:32 +03:00
2007-11-09 21:23:40 +03:00
return ndr_err ;
2003-11-13 12:26:53 +03:00
}
2003-11-14 10:20:46 +03:00
/*
return and possibly log an NDR error
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_error ( struct ndr_push * ndr ,
2006-03-22 17:33:06 +03:00
enum ndr_err_code ndr_err ,
2008-10-13 17:17:41 +04:00
const char * format , . . . )
2003-11-14 10:20:46 +03:00
{
char * s = NULL ;
va_list ap ;
2008-10-13 17:17:41 +04:00
int ret ;
2003-11-14 10:20:46 +03:00
va_start ( ap , format ) ;
2008-10-13 17:17:41 +04:00
ret = vasprintf ( & s , format , ap ) ;
2003-11-14 10:20:46 +03:00
va_end ( ap ) ;
2008-10-13 17:17:41 +04:00
if ( ret = = - 1 ) {
return NDR_ERR_ALLOC ;
}
DEBUG ( 1 , ( " ndr_push_error(%u): %s \n " , ndr_err , s ) ) ;
2003-11-14 10:20:46 +03:00
free ( s ) ;
2003-11-22 11:11:32 +03:00
2007-11-09 21:23:40 +03:00
return ndr_err ;
2003-11-14 10:20:46 +03:00
}
2003-11-16 09:00:15 +03:00
2003-11-21 16:14:17 +03:00
/*
handle subcontext buffers , which in midl land are user - marshalled , but
we use magic in pidl to make them easier to cope with
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start ( struct ndr_pull * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_pull * * _subndr ,
size_t header_size ,
ssize_t size_is )
2003-11-21 16:14:17 +03:00
{
2005-08-18 04:45:19 +04:00
struct ndr_pull * subndr ;
uint32_t r_content_size ;
2008-08-18 19:10:59 +04:00
bool force_le = false ;
bool force_be = false ;
2005-01-29 06:17:14 +03:00
2005-03-15 17:33:38 +03:00
switch ( header_size ) {
2003-11-21 16:14:17 +03:00
case 0 : {
2005-03-15 17:33:38 +03:00
uint32_t content_size = ndr - > data_size - ndr - > offset ;
if ( size_is > = 0 ) {
content_size = size_is ;
}
2005-08-18 04:45:19 +04:00
r_content_size = content_size ;
2003-11-21 16:14:17 +03:00
break ;
}
case 2 : {
2005-03-15 17:33:38 +03:00
uint16_t content_size ;
NDR_CHECK ( ndr_pull_uint16 ( ndr , NDR_SCALARS , & content_size ) ) ;
if ( size_is > = 0 & & size_is ! = content_size ) {
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) size_is(%d) mismatch content_size %d " ,
2005-07-17 13:08:19 +04:00
( int ) size_is , ( int ) content_size ) ;
2005-03-15 17:33:38 +03:00
}
2005-08-18 04:45:19 +04:00
r_content_size = content_size ;
2003-11-21 16:14:17 +03:00
break ;
}
case 4 : {
2005-03-15 17:33:38 +03:00
uint32_t content_size ;
2009-09-18 02:14:31 +04:00
NDR_CHECK ( ndr_pull_uint3264 ( ndr , NDR_SCALARS , & content_size ) ) ;
2005-03-15 17:33:38 +03:00
if ( size_is > = 0 & & size_is ! = content_size ) {
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) size_is(%d) mismatch content_size %d " ,
2005-07-17 13:08:19 +04:00
( int ) size_is , ( int ) content_size ) ;
2005-03-15 17:33:38 +03:00
}
2005-08-18 04:45:19 +04:00
r_content_size = content_size ;
2003-11-21 16:14:17 +03:00
break ;
}
2008-08-18 19:10:59 +04:00
case 0xFFFFFC01 : {
/*
* Common Type Header for the Serialization Stream
* See [ MS - RPCE ] 2.2 .6 Type Serialization Version 1
*/
uint8_t version ;
uint8_t drep ;
uint16_t hdrlen ;
uint32_t filler ;
uint32_t content_size ;
uint32_t reserved ;
/* version */
NDR_CHECK ( ndr_pull_uint8 ( ndr , NDR_SCALARS , & version ) ) ;
if ( version ! = 1 ) {
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT ,
" Bad subcontext (PULL) Common Type Header version %d != 1 " ,
( int ) version ) ;
}
/*
* 0x10 little endian
* 0x00 big endian
*/
NDR_CHECK ( ndr_pull_uint8 ( ndr , NDR_SCALARS , & drep ) ) ;
if ( drep = = 0x10 ) {
force_le = true ;
} else if ( drep = = 0x00 ) {
force_be = true ;
} else {
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT ,
" Bad subcontext (PULL) Common Type Header invalid drep 0x%02X " ,
( unsigned int ) drep ) ;
}
/* length of the "Private Header for Constructed Type" */
NDR_CHECK ( ndr_pull_uint16 ( ndr , NDR_SCALARS , & hdrlen ) ) ;
if ( hdrlen ! = 8 ) {
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT ,
" Bad subcontext (PULL) Common Type Header length %d != 8 " ,
( int ) hdrlen ) ;
}
/* filler should be ignored */
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & filler ) ) ;
/*
* Private Header for Constructed Type
*/
/* length - will be updated latter */
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & content_size ) ) ;
if ( size_is > = 0 & & size_is ! = content_size ) {
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) size_is(%d) mismatch content_size %d " ,
( int ) size_is , ( int ) content_size ) ;
}
/* the content size must be a multiple of 8 */
if ( ( content_size % 8 ) ! = 0 ) {
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT ,
" Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d " ,
( int ) size_is , ( int ) content_size ) ;
}
r_content_size = content_size ;
/* reserved */
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & reserved ) ) ;
break ;
}
2003-11-21 16:14:17 +03:00
default :
2005-03-15 17:33:38 +03:00
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) header_size %d " ,
2005-07-17 13:08:19 +04:00
( int ) header_size ) ;
2003-11-21 16:14:17 +03:00
}
2005-08-18 04:45:19 +04:00
NDR_PULL_NEED_BYTES ( ndr , r_content_size ) ;
subndr = talloc_zero ( ndr , struct ndr_pull ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( subndr ) ;
2009-09-18 02:14:31 +04:00
subndr - > flags = ndr - > flags & ~ LIBNDR_FLAG_NDR64 ;
2005-08-18 05:24:08 +04:00
subndr - > current_mem_ctx = ndr - > current_mem_ctx ;
2005-08-18 04:45:19 +04:00
subndr - > data = ndr - > data + ndr - > offset ;
subndr - > offset = 0 ;
subndr - > data_size = r_content_size ;
2007-12-13 14:19:33 +03:00
subndr - > iconv_convenience = talloc_reference ( subndr , ndr - > iconv_convenience ) ;
2005-08-18 04:45:19 +04:00
2008-08-18 19:10:59 +04:00
if ( force_le ) {
ndr_set_flags ( & ndr - > flags , LIBNDR_FLAG_LITTLE_ENDIAN ) ;
} else if ( force_be ) {
ndr_set_flags ( & ndr - > flags , LIBNDR_FLAG_BIGENDIAN ) ;
}
2005-08-18 04:45:19 +04:00
* _subndr = subndr ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-08-18 04:45:19 +04:00
}
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end ( struct ndr_pull * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_pull * subndr ,
size_t header_size ,
ssize_t size_is )
{
uint32_t advance ;
if ( size_is > = 0 ) {
advance = size_is ;
} else if ( header_size > 0 ) {
advance = subndr - > data_size ;
} else {
advance = subndr - > offset ;
}
NDR_CHECK ( ndr_pull_advance ( ndr , advance ) ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-08-18 04:45:19 +04:00
}
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_subcontext_start ( struct ndr_push * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_push * * _subndr ,
size_t header_size ,
ssize_t size_is )
{
struct ndr_push * subndr ;
2007-12-14 00:46:23 +03:00
subndr = ndr_push_init_ctx ( ndr , ndr - > iconv_convenience ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( subndr ) ;
2009-09-18 02:14:31 +04:00
subndr - > flags = ndr - > flags & ~ LIBNDR_FLAG_NDR64 ;
2005-08-18 04:45:19 +04:00
2009-12-17 00:54:02 +03:00
if ( size_is > 0 ) {
NDR_CHECK ( ndr_push_zero ( subndr , size_is ) ) ;
subndr - > offset = 0 ;
}
2005-08-18 04:45:19 +04:00
* _subndr = subndr ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-21 16:14:17 +03:00
}
2003-11-22 11:11:32 +03:00
/*
push a subcontext header
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_subcontext_end ( struct ndr_push * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_push * subndr ,
size_t header_size ,
ssize_t size_is )
2003-11-22 11:11:32 +03:00
{
2008-08-18 19:10:59 +04:00
ssize_t padding_len ;
2005-03-15 17:33:38 +03:00
if ( size_is > = 0 ) {
2008-08-18 19:10:59 +04:00
padding_len = size_is - subndr - > offset ;
2009-12-17 00:54:02 +03:00
if ( padding_len < 0 ) {
2005-03-15 17:33:38 +03:00
return ndr_push_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PUSH) content_size %d is larger than size_is(%d) " ,
2005-08-18 04:45:19 +04:00
( int ) subndr - > offset , ( int ) size_is ) ;
2005-03-15 17:33:38 +03:00
}
2009-12-17 00:54:02 +03:00
subndr - > offset = size_is ;
2005-03-15 17:33:38 +03:00
}
switch ( header_size ) {
2003-11-22 11:11:32 +03:00
case 0 :
break ;
case 2 :
2005-08-18 04:45:19 +04:00
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , subndr - > offset ) ) ;
2003-11-22 11:11:32 +03:00
break ;
case 4 :
2009-09-18 02:14:31 +04:00
NDR_CHECK ( ndr_push_uint3264 ( ndr , NDR_SCALARS , subndr - > offset ) ) ;
2003-11-22 11:11:32 +03:00
break ;
2008-08-18 19:10:59 +04:00
case 0xFFFFFC01 :
/*
* Common Type Header for the Serialization Stream
* See [ MS - RPCE ] 2.2 .6 Type Serialization Version 1
*/
padding_len = NDR_ROUND ( subndr - > offset , 8 ) - subndr - > offset ;
if ( padding_len > 0 ) {
NDR_CHECK ( ndr_push_zero ( subndr , padding_len ) ) ;
}
/* version */
NDR_CHECK ( ndr_push_uint8 ( ndr , NDR_SCALARS , 1 ) ) ;
/*
* 0x10 little endian
* 0x00 big endian
*/
NDR_CHECK ( ndr_push_uint8 ( ndr , NDR_SCALARS , NDR_BE ( ndr ) ? 0x00 : 0x10 ) ) ;
/* length of the "Private Header for Constructed Type" */
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , 8 ) ) ;
/* filler */
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , 0xCCCCCCCC ) ) ;
/*
* Private Header for Constructed Type
*/
/* length - will be updated latter */
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , subndr - > offset ) ) ;
/* reserved */
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , 0 ) ) ;
break ;
2003-11-22 11:11:32 +03:00
default :
2005-03-15 17:33:38 +03:00
return ndr_push_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext header size %d " ,
2005-07-17 13:08:19 +04:00
( int ) header_size ) ;
2003-11-22 11:11:32 +03:00
}
2005-08-18 04:45:19 +04:00
NDR_CHECK ( ndr_push_bytes ( ndr , subndr - > data , subndr - > offset ) ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-22 11:11:32 +03:00
}
2004-08-12 09:15:41 +04:00
/*
store a token in the ndr context , for later retrieval
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_token_store ( TALLOC_CTX * mem_ctx ,
2005-07-07 23:13:32 +04:00
struct ndr_token_list * * list ,
const void * key ,
uint32_t value )
2004-08-12 09:15:41 +04:00
{
struct ndr_token_list * tok ;
2005-01-27 10:08:20 +03:00
tok = talloc ( mem_ctx , struct ndr_token_list ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( tok ) ;
2004-08-12 09:15:41 +04:00
tok - > key = key ;
tok - > value = value ;
DLIST_ADD ( ( * list ) , tok ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2004-08-12 09:15:41 +04:00
}
2003-11-16 16:49:14 +03:00
/*
2005-07-07 23:13:32 +04:00
retrieve a token from a ndr context , using cmp_fn to match the tokens
2003-11-16 16:49:14 +03:00
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_token_retrieve_cmp_fn ( struct ndr_token_list * * list , const void * key , uint32_t * v ,
2007-09-25 20:05:08 +04:00
comparison_fn_t _cmp_fn , bool _remove_tok )
2003-11-16 16:49:14 +03:00
{
2004-08-12 09:15:41 +04:00
struct ndr_token_list * tok ;
for ( tok = * list ; tok ; tok = tok - > next ) {
2005-07-07 23:13:32 +04:00
if ( _cmp_fn & & _cmp_fn ( tok - > key , key ) = = 0 ) goto found ;
else if ( ! _cmp_fn & & tok - > key = = key ) goto found ;
2004-12-09 10:05:00 +03:00
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_TOKEN ;
2005-07-07 23:13:32 +04:00
found :
* v = tok - > value ;
if ( _remove_tok ) {
DLIST_REMOVE ( ( * list ) , tok ) ;
talloc_free ( tok ) ;
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-07-07 23:13:32 +04:00
}
/*
retrieve a token from a ndr context
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_token_retrieve ( struct ndr_token_list * * list , const void * key , uint32_t * v )
2005-07-07 23:13:32 +04:00
{
2007-09-25 20:05:08 +04:00
return ndr_token_retrieve_cmp_fn ( list , key , v , NULL , true ) ;
2004-12-09 10:05:00 +03:00
}
/*
peek at but don ' t removed a token from a ndr context
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_token_peek ( struct ndr_token_list * * list , const void * key )
2004-12-09 10:05:00 +03:00
{
2007-11-09 21:23:40 +03:00
enum ndr_err_code status ;
2005-07-07 23:13:32 +04:00
uint32_t v ;
2007-11-02 12:59:43 +03:00
2007-09-25 20:05:08 +04:00
status = ndr_token_retrieve_cmp_fn ( list , key , & v , NULL , false ) ;
2007-11-09 21:23:40 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( status ) ) {
2007-11-02 12:59:43 +03:00
return 0 ;
}
return v ;
2004-08-12 09:15:41 +04:00
}
2004-12-09 10:05:00 +03:00
/*
pull an array size field and add it to the array_size_list token list
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_array_size ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
uint32_t size ;
2009-09-17 10:57:32 +04:00
NDR_CHECK ( ndr_pull_uint3264 ( ndr , NDR_SCALARS , & size ) ) ;
2004-12-09 10:05:00 +03:00
return ndr_token_store ( ndr , & ndr - > array_size_list , p , size ) ;
}
/*
get the stored array size field
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_get_array_size ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
return ndr_token_peek ( & ndr - > array_size_list , p ) ;
}
/*
check the stored array size field
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_check_array_size ( struct ndr_pull * ndr , void * p , uint32_t size )
2004-12-09 10:05:00 +03:00
{
2004-12-11 01:36:46 +03:00
uint32_t stored ;
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:
IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }
This makes the ndr_parser.pm internals much more sane.
Other changes include:
- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
most other IDL compilers). This can be overridden using the
default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
useful for making sure IDL files work with other IDL compilers.
oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)
2005-05-25 17:50:27 +04:00
stored = ndr_token_peek ( & ndr - > array_size_list , p ) ;
2004-12-09 10:05:00 +03:00
if ( stored ! = size ) {
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
" Bad array size - got %u expected %u \n " ,
stored , size ) ;
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2004-12-09 10:05:00 +03:00
}
/*
pull an array length field and add it to the array_length_list token list
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_array_length ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
uint32_t length , offset ;
2009-09-17 10:57:32 +04:00
NDR_CHECK ( ndr_pull_uint3264 ( ndr , NDR_SCALARS , & offset ) ) ;
2004-12-09 10:05:00 +03:00
if ( offset ! = 0 ) {
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
" non-zero array offset %u \n " , offset ) ;
}
2009-09-17 10:57:32 +04:00
NDR_CHECK ( ndr_pull_uint3264 ( ndr , NDR_SCALARS , & length ) ) ;
2004-12-09 10:05:00 +03:00
return ndr_token_store ( ndr , & ndr - > array_length_list , p , length ) ;
}
/*
get the stored array length field
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_get_array_length ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
return ndr_token_peek ( & ndr - > array_length_list , p ) ;
}
/*
check the stored array length field
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_check_array_length ( struct ndr_pull * ndr , void * p , uint32_t length )
2004-12-09 10:05:00 +03:00
{
uint32_t stored ;
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:
IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }
This makes the ndr_parser.pm internals much more sane.
Other changes include:
- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
most other IDL compilers). This can be overridden using the
default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
useful for making sure IDL files work with other IDL compilers.
oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)
2005-05-25 17:50:27 +04:00
stored = ndr_token_peek ( & ndr - > array_length_list , p ) ;
2004-12-09 10:05:00 +03:00
if ( stored ! = length ) {
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
" Bad array length - got %u expected %u \n " ,
stored , length ) ;
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2004-12-09 10:05:00 +03:00
}
2004-08-12 09:15:41 +04:00
2005-03-06 20:02:14 +03:00
/*
store a switch value
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_set_switch_value ( struct ndr_push * ndr , const void * p , uint32_t val )
2005-03-06 20:02:14 +03:00
{
return ndr_token_store ( ndr , & ndr - > switch_list , p , val ) ;
}
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_set_switch_value ( struct ndr_pull * ndr , const void * p , uint32_t val )
2005-03-06 20:02:14 +03:00
{
return ndr_token_store ( ndr , & ndr - > switch_list , p , val ) ;
}
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_print_set_switch_value ( struct ndr_print * ndr , const void * p , uint32_t val )
2005-04-04 18:22:28 +04:00
{
return ndr_token_store ( ndr , & ndr - > switch_list , p , val ) ;
}
2005-03-06 20:02:14 +03:00
/*
retrieve a switch value
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_push_get_switch_value ( struct ndr_push * ndr , const void * p )
2005-03-06 20:02:14 +03:00
{
return ndr_token_peek ( & ndr - > switch_list , p ) ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_pull_get_switch_value ( struct ndr_pull * ndr , const void * p )
2005-03-06 20:02:14 +03:00
{
return ndr_token_peek ( & ndr - > switch_list , p ) ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_print_get_switch_value ( struct ndr_print * ndr , const void * p )
2005-04-03 00:57:27 +04:00
{
return ndr_token_peek ( & ndr - > switch_list , p ) ;
}
2003-11-17 07:56:59 +03:00
/*
pull a struct from a blob using NDR
*/
2008-01-02 07:05:13 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx , struct smb_iconv_convenience * iconv_convenience , void * p ,
2004-11-05 10:29:02 +03:00
ndr_pull_flags_fn_t fn )
2003-11-17 07:56:59 +03:00
{
struct ndr_pull * ndr ;
2008-01-02 07:05:13 +03:00
ndr = ndr_pull_init_blob ( blob , mem_ctx , iconv_convenience ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2009-09-12 09:21:33 +04:00
NDR_CHECK_FREE ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
talloc_free ( ndr ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-17 07:56:59 +03:00
}
2003-11-24 04:24:29 +03:00
2005-05-10 05:58:34 +04:00
/*
pull a struct from a blob using NDR - failing if all bytes are not consumed
*/
2008-01-02 07:05:13 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx ,
struct smb_iconv_convenience * iconv_convenience ,
void * p , ndr_pull_flags_fn_t fn )
2005-05-10 05:58:34 +04:00
{
struct ndr_pull * ndr ;
2009-11-20 13:34:53 +03:00
uint32_t highest_ofs ;
2008-01-02 07:05:13 +03:00
ndr = ndr_pull_init_blob ( blob , mem_ctx , iconv_convenience ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2009-09-12 09:21:33 +04:00
NDR_CHECK_FREE ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
2009-11-20 13:34:53 +03:00
if ( ndr - > offset > ndr - > relative_highest_offset ) {
highest_ofs = ndr - > offset ;
} else {
highest_ofs = ndr - > relative_highest_offset ;
}
if ( highest_ofs < ndr - > data_size ) {
enum ndr_err_code ret ;
ret = ndr_pull_error ( ndr , NDR_ERR_UNREAD_BYTES ,
" not all bytes consumed ofs[%u] size[%u] " ,
highest_ofs , ndr - > data_size ) ;
talloc_free ( ndr ) ;
return ret ;
2005-05-10 05:58:34 +04:00
}
2009-09-12 09:21:33 +04:00
talloc_free ( ndr ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-05-10 05:58:34 +04:00
}
2005-05-11 03:33:56 +04:00
/*
pull a union from a blob using NDR , given the union discriminator
*/
2008-01-02 07:05:13 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_union_blob ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx ,
struct smb_iconv_convenience * iconv_convenience , void * p ,
2005-05-11 03:33:56 +04:00
uint32_t level , ndr_pull_flags_fn_t fn )
2007-11-01 10:10:54 +03:00
{
struct ndr_pull * ndr ;
2008-01-02 07:05:13 +03:00
ndr = ndr_pull_init_blob ( blob , mem_ctx , iconv_convenience ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2009-09-12 09:21:33 +04:00
NDR_CHECK_FREE ( ndr_pull_set_switch_value ( ndr , p , level ) ) ;
NDR_CHECK_FREE ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
talloc_free ( ndr ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2007-11-01 10:10:54 +03:00
}
/*
pull a union from a blob using NDR , given the union discriminator ,
failing if all bytes are not consumed
*/
2008-01-02 07:05:13 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx ,
struct smb_iconv_convenience * iconv_convenience , void * p ,
2007-11-01 10:10:54 +03:00
uint32_t level , ndr_pull_flags_fn_t fn )
2005-05-11 03:33:56 +04:00
{
struct ndr_pull * ndr ;
2009-11-20 13:34:53 +03:00
uint32_t highest_ofs ;
2008-01-02 07:05:13 +03:00
ndr = ndr_pull_init_blob ( blob , mem_ctx , iconv_convenience ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2009-09-12 09:21:33 +04:00
NDR_CHECK_FREE ( ndr_pull_set_switch_value ( ndr , p , level ) ) ;
NDR_CHECK_FREE ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
2009-11-20 13:34:53 +03:00
if ( ndr - > offset > ndr - > relative_highest_offset ) {
highest_ofs = ndr - > offset ;
} else {
highest_ofs = ndr - > relative_highest_offset ;
}
if ( highest_ofs < ndr - > data_size ) {
2009-09-12 09:21:33 +04:00
enum ndr_err_code ret ;
ret = ndr_pull_error ( ndr , NDR_ERR_UNREAD_BYTES ,
" not all bytes consumed ofs[%u] size[%u] " ,
2009-11-20 13:34:53 +03:00
highest_ofs , ndr - > data_size ) ;
2009-09-12 09:21:33 +04:00
talloc_free ( ndr ) ;
return ret ;
2005-05-11 03:33:56 +04:00
}
2009-09-12 09:21:33 +04:00
talloc_free ( ndr ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-05-11 03:33:56 +04:00
}
2003-11-26 04:16:41 +03:00
/*
push a struct to a blob using NDR
*/
2008-01-02 07:05:05 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_struct_blob ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx , struct smb_iconv_convenience * iconv_convenience , const void * p , ndr_push_flags_fn_t fn )
2003-11-26 04:16:41 +03:00
{
struct ndr_push * ndr ;
2008-01-02 07:05:05 +03:00
ndr = ndr_push_init_ctx ( mem_ctx , iconv_convenience ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2007-11-02 12:26:49 +03:00
NDR_CHECK ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
2003-11-24 04:24:29 +03:00
2003-11-26 04:16:41 +03:00
* blob = ndr_push_blob ( ndr ) ;
2006-10-16 15:03:12 +04:00
talloc_steal ( mem_ctx , blob - > data ) ;
talloc_free ( ndr ) ;
2003-11-26 04:16:41 +03:00
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-26 04:16:41 +03:00
}
2005-01-05 05:01:19 +03:00
2005-05-12 12:27:04 +04:00
/*
push a union to a blob using NDR
*/
2008-01-02 07:05:13 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_union_blob ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx , struct smb_iconv_convenience * iconv_convenience , void * p ,
2005-05-12 12:27:04 +04:00
uint32_t level , ndr_push_flags_fn_t fn )
{
struct ndr_push * ndr ;
2008-01-02 07:05:13 +03:00
ndr = ndr_push_init_ctx ( mem_ctx , iconv_convenience ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2007-11-02 12:26:49 +03:00
2007-11-02 12:29:19 +03:00
NDR_CHECK ( ndr_push_set_switch_value ( ndr , p , level ) ) ;
2007-11-02 12:26:49 +03:00
NDR_CHECK ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
2005-05-12 12:27:04 +04:00
* blob = ndr_push_blob ( ndr ) ;
2006-10-16 18:32:07 +04:00
talloc_steal ( mem_ctx , blob - > data ) ;
talloc_free ( ndr ) ;
2005-05-12 12:27:04 +04:00
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-05-12 12:27:04 +04:00
}
2005-01-05 05:01:19 +03:00
/*
generic ndr_size_ * ( ) handler for structures
*/
2009-01-01 06:45:33 +03:00
_PUBLIC_ size_t ndr_size_struct ( const void * p , int flags , ndr_push_flags_fn_t push , struct smb_iconv_convenience * iconv_convenience )
2005-01-05 05:01:19 +03:00
{
struct ndr_push * ndr ;
2007-11-09 21:23:40 +03:00
enum ndr_err_code status ;
2005-01-05 05:01:19 +03:00
size_t ret ;
2005-03-11 13:09:16 +03:00
/* avoid recursion */
if ( flags & LIBNDR_FLAG_NO_NDR_SIZE ) return 0 ;
2009-01-01 06:45:33 +03:00
ndr = ndr_push_init_ctx ( NULL , iconv_convenience ) ;
2005-01-05 05:01:19 +03:00
if ( ! ndr ) return 0 ;
2005-03-11 13:09:16 +03:00
ndr - > flags | = flags | LIBNDR_FLAG_NO_NDR_SIZE ;
2005-01-05 05:01:19 +03:00
status = push ( ndr , NDR_SCALARS | NDR_BUFFERS , discard_const ( p ) ) ;
2007-11-09 21:23:40 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( status ) ) {
2007-11-02 13:01:18 +03:00
talloc_free ( ndr ) ;
2005-01-05 05:01:19 +03:00
return 0 ;
}
ret = ndr - > offset ;
talloc_free ( ndr ) ;
return ret ;
}
2005-01-21 09:54:10 +03:00
/*
generic ndr_size_ * ( ) handler for unions
*/
2009-01-01 06:45:33 +03:00
_PUBLIC_ size_t ndr_size_union ( const void * p , int flags , uint32_t level , ndr_push_flags_fn_t push , struct smb_iconv_convenience * iconv_convenience )
2005-01-21 09:54:10 +03:00
{
struct ndr_push * ndr ;
2007-11-09 21:23:40 +03:00
enum ndr_err_code status ;
2005-01-21 09:54:10 +03:00
size_t ret ;
2005-03-11 13:09:16 +03:00
/* avoid recursion */
if ( flags & LIBNDR_FLAG_NO_NDR_SIZE ) return 0 ;
2009-01-01 06:45:33 +03:00
ndr = ndr_push_init_ctx ( NULL , iconv_convenience ) ;
2005-01-21 09:54:10 +03:00
if ( ! ndr ) return 0 ;
2005-03-11 13:09:16 +03:00
ndr - > flags | = flags | LIBNDR_FLAG_NO_NDR_SIZE ;
2007-11-02 13:01:18 +03:00
status = ndr_push_set_switch_value ( ndr , p , level ) ;
2007-11-09 21:23:40 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( status ) ) {
2007-11-02 13:01:18 +03:00
talloc_free ( ndr ) ;
return 0 ;
}
2005-07-04 06:25:33 +04:00
status = push ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ;
2007-11-09 21:23:40 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( status ) ) {
2007-11-02 13:01:18 +03:00
talloc_free ( ndr ) ;
2005-01-21 09:54:10 +03:00
return 0 ;
}
ret = ndr - > offset ;
talloc_free ( ndr ) ;
return ret ;
}
2005-06-02 07:41:12 +04:00
/*
get the current base for relative pointers for the push
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_push_get_relative_base_offset ( struct ndr_push * ndr )
2005-06-02 07:41:12 +04:00
{
return ndr - > relative_base_offset ;
}
/*
restore the old base for relative pointers for the push
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_push_restore_relative_base_offset ( struct ndr_push * ndr , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
}
/*
setup the current base for relative pointers for the push
called in the NDR_SCALAR stage
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset1 ( struct ndr_push * ndr , const void * p , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
return ndr_token_store ( ndr , & ndr - > relative_base_list , p , offset ) ;
}
/*
setup the current base for relative pointers for the push
called in the NDR_BUFFERS stage
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset2 ( struct ndr_push * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
return ndr_token_retrieve ( & ndr - > relative_base_list , p , & ndr - > relative_base_offset ) ;
}
/*
push a relative object - stage1
this is called during SCALARS processing
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1 ( struct ndr_push * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
if ( p = = NULL ) {
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , 0 ) ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-06-02 07:41:12 +04:00
}
NDR_CHECK ( ndr_push_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_token_store ( ndr , & ndr - > relative_list , p , ndr - > offset ) ) ;
return ndr_push_uint32 ( ndr , NDR_SCALARS , 0xFFFFFFFF ) ;
}
2009-12-10 10:04:48 +03:00
/*
push a short relative object - stage1
this is called during SCALARS processing
*/
_PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr1 ( struct ndr_push * ndr , const void * p )
{
if ( p = = NULL ) {
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , 0 ) ) ;
return NDR_ERR_SUCCESS ;
}
NDR_CHECK ( ndr_push_align ( ndr , 2 ) ) ;
NDR_CHECK ( ndr_token_store ( ndr , & ndr - > relative_list , p , ndr - > offset ) ) ;
return ndr_push_uint16 ( ndr , NDR_SCALARS , 0xFFFF ) ;
}
2005-06-02 07:41:12 +04:00
/*
push a relative object - stage2
this is called during buffers processing
*/
2010-02-17 22:00:36 +03:00
static enum ndr_err_code ndr_push_relative_ptr2 ( struct ndr_push * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
2007-11-20 13:07:57 +03:00
uint32_t save_offset ;
2005-06-02 10:25:48 +04:00
uint32_t ptr_offset = 0xFFFFFFFF ;
2005-06-02 07:41:12 +04:00
if ( p = = NULL ) {
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-06-02 07:41:12 +04:00
}
2007-11-20 13:07:57 +03:00
save_offset = ndr - > offset ;
2005-06-02 10:25:48 +04:00
NDR_CHECK ( ndr_token_retrieve ( & ndr - > relative_list , p , & ptr_offset ) ) ;
if ( ptr_offset > ndr - > offset ) {
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u) " ,
ptr_offset , ndr - > offset ) ;
}
ndr - > offset = ptr_offset ;
2007-11-20 13:07:57 +03:00
if ( save_offset < ndr - > relative_base_offset ) {
2005-06-02 10:25:48 +04:00
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
2007-11-20 13:07:57 +03:00
" ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u) " ,
save_offset , ndr - > relative_base_offset ) ;
2005-06-02 10:25:48 +04:00
}
2007-11-20 13:07:57 +03:00
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , save_offset - ndr - > relative_base_offset ) ) ;
2009-12-10 10:04:48 +03:00
ndr - > offset = save_offset ;
return NDR_ERR_SUCCESS ;
}
/*
push a short relative object - stage2
this is called during buffers processing
*/
_PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr2 ( struct ndr_push * ndr , const void * p )
{
uint32_t save_offset ;
uint32_t ptr_offset = 0xFFFF ;
if ( p = = NULL ) {
return NDR_ERR_SUCCESS ;
}
save_offset = ndr - > offset ;
NDR_CHECK ( ndr_token_retrieve ( & ndr - > relative_list , p , & ptr_offset ) ) ;
if ( ptr_offset > ndr - > offset ) {
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u) " ,
ptr_offset , ndr - > offset ) ;
}
ndr - > offset = ptr_offset ;
if ( save_offset < ndr - > relative_base_offset ) {
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u) " ,
save_offset , ndr - > relative_base_offset ) ;
}
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , save_offset - ndr - > relative_base_offset ) ) ;
2007-11-20 13:07:57 +03:00
ndr - > offset = save_offset ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-06-02 07:41:12 +04:00
}
2009-12-14 16:08:34 +03:00
/*
push a relative object - stage2 start
this is called during buffers processing
*/
_PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start ( struct ndr_push * ndr , const void * p )
{
if ( p = = NULL ) {
return NDR_ERR_SUCCESS ;
}
return ndr_push_relative_ptr2 ( ndr , p ) ;
}
/*
push a relative object - stage2 end
this is called during buffers processing
*/
_PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_end ( struct ndr_push * ndr , const void * p )
{
if ( p = = NULL ) {
return NDR_ERR_SUCCESS ;
}
return NDR_ERR_SUCCESS ;
}
2005-06-02 07:41:12 +04:00
/*
get the current base for relative pointers for the pull
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_pull_get_relative_base_offset ( struct ndr_pull * ndr )
2005-06-02 07:41:12 +04:00
{
return ndr - > relative_base_offset ;
}
/*
restore the old base for relative pointers for the pull
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_pull_restore_relative_base_offset ( struct ndr_pull * ndr , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
}
/*
setup the current base for relative pointers for the pull
called in the NDR_SCALAR stage
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset1 ( struct ndr_pull * ndr , const void * p , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
return ndr_token_store ( ndr , & ndr - > relative_base_list , p , offset ) ;
}
/*
setup the current base for relative pointers for the pull
called in the NDR_BUFFERS stage
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset2 ( struct ndr_pull * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
return ndr_token_retrieve ( & ndr - > relative_base_list , p , & ndr - > relative_base_offset ) ;
}
/*
pull a relative object - stage1
called during SCALARS processing
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr1 ( struct ndr_pull * ndr , const void * p , uint32_t rel_offset )
2005-06-02 07:41:12 +04:00
{
rel_offset + = ndr - > relative_base_offset ;
2005-06-02 10:25:48 +04:00
if ( rel_offset > ndr - > data_size ) {
return ndr_pull_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u) " ,
rel_offset , ndr - > data_size ) ;
}
2005-06-02 07:41:12 +04:00
return ndr_token_store ( ndr , & ndr - > relative_list , p , rel_offset ) ;
}
/*
pull a relative object - stage2
called during BUFFERS processing
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr2 ( struct ndr_pull * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
uint32_t rel_offset ;
NDR_CHECK ( ndr_token_retrieve ( & ndr - > relative_list , p , & rel_offset ) ) ;
return ndr_pull_set_offset ( ndr , rel_offset ) ;
}
2009-01-26 19:31:22 +03:00
const static struct {
enum ndr_err_code err ;
const char * string ;
} ndr_err_code_strings [ ] = {
{ NDR_ERR_SUCCESS , " Success " } ,
{ NDR_ERR_ARRAY_SIZE , " Bad Array Size " } ,
{ NDR_ERR_BAD_SWITCH , " Bad Switch " } ,
{ NDR_ERR_OFFSET , " Offset Error " } ,
{ NDR_ERR_RELATIVE , " Relative Pointer Error " } ,
{ NDR_ERR_CHARCNV , " Character Conversion Error " } ,
{ NDR_ERR_LENGTH , " Length Error " } ,
{ NDR_ERR_SUBCONTEXT , " Subcontext Error " } ,
{ NDR_ERR_COMPRESSION , " Compression Error " } ,
{ NDR_ERR_STRING , " String Error " } ,
{ NDR_ERR_VALIDATE , " Validate Error " } ,
{ NDR_ERR_BUFSIZE , " Buffer Size Error " } ,
{ NDR_ERR_ALLOC , " Allocation Error " } ,
{ NDR_ERR_RANGE , " Range Error " } ,
{ NDR_ERR_TOKEN , " Token Error " } ,
{ NDR_ERR_IPV4ADDRESS , " IPv4 Address Error " } ,
{ NDR_ERR_INVALID_POINTER , " Invalid Pointer " } ,
{ NDR_ERR_UNREAD_BYTES , " Unread Bytes " } ,
2009-09-17 20:08:47 +04:00
{ NDR_ERR_NDR64 , " NDR64 assertion error " } ,
2009-01-26 19:31:22 +03:00
{ 0 , NULL }
} ;
_PUBLIC_ const char * ndr_map_error2string ( enum ndr_err_code ndr_err )
{
int i ;
for ( i = 0 ; ndr_err_code_strings [ i ] . string ! = NULL ; i + + ) {
if ( ndr_err_code_strings [ i ] . err = = ndr_err )
return ndr_err_code_strings [ i ] . string ;
}
return " Unknown error " ;
}