2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
SMB Byte handling
Copyright ( C ) Andrew Tridgell 1992 - 1998
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-08-13 05:53:07 +04: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-08-13 05:53:07 +04:00
*/
# ifndef _BYTEORDER_H
# define _BYTEORDER_H
/*
This file implements macros for machine independent short and
int manipulation
Here is a description of this file that I emailed to the samba list once :
> I am confused about the way that byteorder . h works in Samba . I have
> looked at it , and I would have thought that you might make a distinction
> between LE and BE machines , but you only seem to distinguish between 386
> and all other architectures .
>
> Can you give me a clue ?
sure .
Ok , now to the macros themselves . I ' ll take a simple example , say we
want to extract a 2 byte integer from a SMB packet and put it into a
2004-05-25 21:24:24 +04:00
type called uint16_t that is in the local machines byte order , and you
want to do it with only the assumption that uint16_t is _at_least_ 16
2003-08-13 05:53:07 +04:00
bits long ( this last condition is very important for architectures
that don ' t have any int types that are 2 bytes long )
You do this :
2004-05-29 12:11:46 +04:00
# define CVAL(buf,pos) (((uint8_t *)(buf))[pos])
2010-01-05 20:40:54 +03:00
# define PVAL(buf,pos) ((unsigned int)CVAL(buf,pos))
2003-08-13 05:53:07 +04:00
# define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
2004-05-25 21:24:24 +04:00
then to extract a uint16_t value at offset 25 in a buffer you do this :
2003-08-13 05:53:07 +04:00
char * buffer = foo_bar ( ) ;
2004-05-25 21:24:24 +04:00
uint16_t xx = SVAL ( buffer , 25 ) ;
2003-08-13 05:53:07 +04:00
We are using the byteoder independence of the ANSI C bitshifts to do
the work . A good optimising compiler should turn this into efficient
code , especially if it happens to have the right byteorder : - )
I know these macros can be made a bit tidier by removing some of the
casts , but you need to look at byteorder . h as a whole to see the
reasoning behind them . byteorder . h defines the following macros :
SVAL ( buf , pos ) - extract a 2 byte SMB value
IVAL ( buf , pos ) - extract a 4 byte SMB value
2006-12-31 15:28:16 +03:00
BVAL ( buf , pos ) - extract a 8 byte SMB value
SVALS ( buf , pos ) - signed version of SVAL ( )
IVALS ( buf , pos ) - signed version of IVAL ( )
BVALS ( buf , pos ) - signed version of BVAL ( )
2003-08-13 05:53:07 +04:00
SSVAL ( buf , pos , val ) - put a 2 byte SMB value into a buffer
SIVAL ( buf , pos , val ) - put a 4 byte SMB value into a buffer
2006-12-31 15:28:16 +03:00
SBVAL ( buf , pos , val ) - put a 8 byte SMB value into a buffer
2003-08-13 05:53:07 +04:00
SSVALS ( buf , pos , val ) - signed version of SSVAL ( )
SIVALS ( buf , pos , val ) - signed version of SIVAL ( )
2006-12-31 15:28:16 +03:00
SBVALS ( buf , pos , val ) - signed version of SBVAL ( )
2003-08-13 05:53:07 +04:00
RSVAL ( buf , pos ) - like SVAL ( ) but for NMB byte ordering
RSVALS ( buf , pos ) - like SVALS ( ) but for NMB byte ordering
RIVAL ( buf , pos ) - like IVAL ( ) but for NMB byte ordering
RIVALS ( buf , pos ) - like IVALS ( ) but for NMB byte ordering
RSSVAL ( buf , pos , val ) - like SSVAL ( ) but for NMB ordering
RSIVAL ( buf , pos , val ) - like SIVAL ( ) but for NMB ordering
RSIVALS ( buf , pos , val ) - like SIVALS ( ) but for NMB ordering
it also defines lots of intermediate macros , just ignore those : - )
*/
2004-10-14 09:26:35 +04:00
/*
2014-05-05 15:42:36 +04:00
* On powerpc we can use the magic instructions to load / store in little endian .
* The instructions are reverse - indexing , so assume a big endian Power
* processor . Power8 can be big or little endian , so we need to explicitly
* check .
*/
# if (defined(__powerpc__) && defined(__GNUC__) && HAVE_BIG_ENDIAN)
2004-10-14 09:26:35 +04:00
static __inline__ uint16_t ld_le16 ( const uint16_t * addr )
{
uint16_t val ;
__asm__ ( " lhbrx %0,0,%1 " : " =r " ( val ) : " r " ( addr ) , " m " ( * addr ) ) ;
return val ;
}
static __inline__ void st_le16 ( uint16_t * addr , const uint16_t val )
{
__asm__ ( " sthbrx %1,0,%2 " : " =m " ( * addr ) : " r " ( val ) , " r " ( addr ) ) ;
}
static __inline__ uint32_t ld_le32 ( const uint32_t * addr )
{
uint32_t val ;
__asm__ ( " lwbrx %0,0,%1 " : " =r " ( val ) : " r " ( addr ) , " m " ( * addr ) ) ;
return val ;
}
static __inline__ void st_le32 ( uint32_t * addr , const uint32_t val )
{
__asm__ ( " stwbrx %1,0,%2 " : " =m " ( * addr ) : " r " ( val ) , " r " ( addr ) ) ;
}
# define HAVE_ASM_BYTEORDER 1
2008-07-25 11:43:21 +04:00
# else
# define HAVE_ASM_BYTEORDER 0
2004-10-14 09:26:35 +04:00
# endif
2010-01-05 20:40:54 +03:00
# define CVAL(buf,pos) ((unsigned int)(((const uint8_t *)(buf))[pos]))
2004-05-29 12:11:46 +04:00
# define CVAL_NC(buf,pos) (((uint8_t *)(buf))[pos]) /* Non-const version of CVAL */
2003-08-13 05:53:07 +04:00
# define PVAL(buf,pos) (CVAL(buf,pos))
# define SCVAL(buf,pos,val) (CVAL_NC(buf,pos) = (val))
2004-10-14 09:26:35 +04:00
# if HAVE_ASM_BYTEORDER
2009-02-02 17:43:32 +03:00
# define _PTRPOS(buf,pos) (((const uint8_t *)(buf))+(pos))
2004-10-14 09:26:35 +04:00
# define SVAL(buf,pos) ld_le16((const uint16_t *)_PTRPOS(buf,pos))
# define IVAL(buf,pos) ld_le32((const uint32_t *)_PTRPOS(buf,pos))
2004-10-14 09:38:48 +04:00
# define SSVAL(buf,pos,val) st_le16((uint16_t *)_PTRPOS(buf,pos), val)
# define SIVAL(buf,pos,val) st_le32((uint32_t *)_PTRPOS(buf,pos), val)
2004-10-14 09:26:35 +04:00
# define SVALS(buf,pos) ((int16_t)SVAL(buf,pos))
# define IVALS(buf,pos) ((int32_t)IVAL(buf,pos))
# define SSVALS(buf,pos,val) SSVAL((buf),(pos),((int16_t)(val)))
# define SIVALS(buf,pos,val) SIVAL((buf),(pos),((int32_t)(val)))
2003-08-13 05:53:07 +04:00
2013-11-14 21:36:41 +04:00
# else /* not HAVE_ASM_BYTEORDER */
2003-08-13 05:53:07 +04:00
# define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
# define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
2004-05-29 12:11:46 +04:00
# define SSVALX(buf,pos,val) (CVAL_NC(buf,pos)=(uint8_t)((val)&0xFF),CVAL_NC(buf,pos+1)=(uint8_t)((val)>>8))
2003-08-13 05:53:07 +04:00
# define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
2004-05-25 21:24:24 +04:00
# define SVALS(buf,pos) ((int16_t)SVAL(buf,pos))
2004-05-25 20:24:13 +04:00
# define IVALS(buf,pos) ((int32_t)IVAL(buf,pos))
2004-05-25 21:24:24 +04:00
# define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16_t)(val)))
2004-05-25 20:24:13 +04:00
# define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32_t)(val)))
2004-05-25 21:24:24 +04:00
# define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16_t)(val)))
2004-05-25 20:24:13 +04:00
# define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32_t)(val)))
2003-08-13 05:53:07 +04:00
2013-11-14 21:36:41 +04:00
# endif /* not HAVE_ASM_BYTEORDER */
2003-08-13 05:53:07 +04:00
2011-04-23 13:01:34 +04:00
/* 64 bit macros */
# define BVAL(p, ofs) (IVAL(p,ofs) | (((uint64_t)IVAL(p,(ofs)+4)) << 32))
# define BVALS(p, ofs) ((int64_t)BVAL(p,ofs))
# define SBVAL(p, ofs, v) (SIVAL(p,ofs,(v)&0xFFFFFFFF), SIVAL(p,(ofs)+4,((uint64_t)(v))>>32))
# define SBVALS(p, ofs, v) (SBVAL(p,ofs,(uint64_t)v))
2003-08-13 05:53:07 +04:00
/* now the reverse routines - these are used in nmb packets (mostly) */
# define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
# define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
2015-06-17 02:01:10 +03:00
# define BREV(x) ((IREV((uint64_t)x)<<32) | (IREV(((uint64_t)x)>>32)))
2003-08-13 05:53:07 +04:00
# define RSVAL(buf,pos) SREV(SVAL(buf,pos))
# define RSVALS(buf,pos) SREV(SVALS(buf,pos))
# define RIVAL(buf,pos) IREV(IVAL(buf,pos))
# define RIVALS(buf,pos) IREV(IVALS(buf,pos))
2011-04-23 13:01:34 +04:00
# define RBVAL(buf,pos) BREV(BVAL(buf,pos))
# define RBVALS(buf,pos) BREV(BVALS(buf,pos))
2003-08-13 05:53:07 +04:00
# define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
# define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
# define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
# define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
2011-04-23 13:01:34 +04:00
# define RSBVAL(buf,pos,val) SBVAL(buf,pos,BREV(val))
# define RSBVALS(buf,pos,val) SBVALS(buf,pos,BREV(val))
2003-08-13 05:53:07 +04:00
/* Alignment macros. */
# define ALIGN4(p,base) ((p) + ((4 - (PTR_DIFF((p), (base)) & 3)) & 3))
# define ALIGN2(p,base) ((p) + ((2 - (PTR_DIFF((p), (base)) & 1)) & 1))
/* macros for accessing SMB protocol elements */
# define VWV(vwv) ((vwv)*2)
# endif /* _BYTEORDER_H */