Loading...
Searching...
No Matches
XrdOucPup.cc
Go to the documentation of this file.
/******************************************************************************/
/* */
/* X r d O u c P u p . c c */
/* */
/* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University */
/* All Rights Reserved */
/* Produced by Andrew Hanushevsky for Stanford University under contract */
/* DE-AC02-76-SFO0515 with the Department of Energy */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD 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 Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/
#include <cerrno>
#include <sys/uio.h>
#include <netinet/in.h>
#include <cinttypes>
#include <cstdio>
#include <cstring>
#ifdef WIN32
#include <direct.h>
#include "XrdSys/XrdWin32.hh"
#endif
#include "XrdOuc/XrdOucPup.hh"
#include "XrdSys/XrdSysError.hh"
#include "XrdSys/XrdSysHeaders.hh"
#include "XrdSys/XrdSysPlatform.hh"
/******************************************************************************/
/* P a c k */
/******************************************************************************/
int XrdOucPup::Pack(struct iovec **iovP,
const char *data,
unsigned short &buff)
{
unsigned short dlen;
struct iovec *vP = *iovP;
// Pack the data as "<short len><char>" if data is present or "<short 0>" o/w.
// When data is present, the null byte is always included.
//
vP->iov_base = (char *)&buff; vP->iov_len = sizeof(buff); vP++;
if (data)
{dlen = static_cast<unsigned short>(strlen(data)+1);
buff = htons(dlen);
vP->iov_base = (char *)data; vP->iov_len = dlen; vP++;
} else {buff = 0; dlen = 0;}
*iovP = vP;
return dlen+sizeof(buff);
}
/******************************************************************************/
int XrdOucPup::Pack(struct iovec **iovP,
const char *data,
unsigned short &buff,
int dlen)
{
struct iovec *vP = *iovP;
vP->iov_base = (char *)&buff; vP->iov_len = sizeof(buff); vP++;
if (data)
{buff = htons(static_cast<unsigned short>(dlen));
vP->iov_base = (char *)data; vP->iov_len = dlen; vP++;
} else {buff = 0; dlen = 0;}
*iovP = vP;
return dlen+sizeof(buff);
}
/******************************************************************************/
int XrdOucPup::Pack(char **buff,
const char *data,
int dlen)
{
char *bp = *buff;
unsigned short xlen;
if (data)
{if (dlen < 0) dlen = strlen(data)+1;
xlen = htons(static_cast<unsigned short>(dlen));
memcpy(bp, &xlen, sizeof(xlen)); bp += sizeof(xlen);
memcpy(bp, data, dlen);
bp += dlen;
} else {*bp++ = '\0'; *bp++ = '\0'; dlen = 0;}
*buff = bp;
return dlen+sizeof(xlen);
}
/******************************************************************************/
int XrdOucPup::Pack(char **buff,
unsigned int data)
{
unsigned int netData = htonl(data);
char *bp = *buff;
if (netData & PT_Mask)
{*bp = static_cast<char>(PT_int);
memcpy(bp+1, &netData, sizeof(netData));
*buff = bp + sizeof(netData)+1;
return sizeof(netData)+1;
}
(*(char *)&netData) |= PT_int | PT_Inline;
memcpy(bp, &netData, sizeof(netData));
*buff = bp + sizeof(netData);
return sizeof(netData);
}
/******************************************************************************/
int XrdOucPup::Pack(struct iovec *iovP, struct iovec *iovE, XrdOucPupArgs *pup,
char *base, char *Work)
{
static char Nil[] = {PT_char, '\0'};
static const int Sz16 = sizeof(short) + 1;
static const int Sz32 = sizeof(int) + 1;
static const int Sz64 = sizeof(long long) + 1;
struct iovec *vP = iovP;
XrdOucPupArgs *pP = pup;
char *wP = Work;
int Dtype, dlen = 0, TotLen = 0;
unsigned long long n64;
unsigned int n32;
unsigned short n16;
union {unsigned long long *B64;
unsigned int *B32;
unsigned short *B16;
char **B08;} Base;
Dtype = pP->Dtype;
do {Base.B08 = (char **)(base + pP->Doffs);
//std::cerr <<"arg " <<pP-pup <<" type " <<Dtype <<' '
// <<(Names->NList[pP->Name] ? Names->NList[pP->Name] : "?") <<std::endl;
switch(Dtype)
{case PT_char:
/* Null Pointer */ if (!*Base.B08) {vP->iov_base = Nil; vP->iov_len = 2;
vP++; TotLen += 2; break;
}
dlen = (pP->Dlen < 0 ? strlen(*Base.B08)+1 : pP->Dlen);
/* Full String */ if (dlen > MaxLen)
return eMsg("string too long packing", int(pP-pup), pP);
if (vP >= iovE)
return eMsg("too many args packing", int(pP-pup), pP);
n16 = htons(static_cast<unsigned short>(dlen));
vP->iov_base = wP; vP->iov_len = sizeof(n16); vP++;
memcpy(wP, &n16, sizeof(n16)); wP += sizeof(n16);
vP->iov_base = *Base.B08; vP->iov_len = dlen; vP++;
TotLen += dlen + sizeof(n16);
break;
case PT_short:
n16 = htons(*Base.B16);
*wP = static_cast<char>(PT_short);
memcpy(wP+1, &n16, sizeof(n16));
vP->iov_base = wP; vP->iov_len = Sz16; vP++;
wP += Sz16; TotLen += Sz16; dlen = sizeof(n16);
break;
case PT_int:
n32 = htonl(*Base.B32);
*wP = static_cast<char>(PT_int);
memcpy(wP+1, &n32, sizeof(n32));
vP->iov_base = wP; vP->iov_len = Sz32; vP++;
wP += Sz32; TotLen += Sz32; dlen = sizeof(n32);
break;
case PT_longlong:
h2nll(*Base.B64, n64);
*wP = static_cast<char>(PT_longlong);
memcpy(wP+1, &n64, sizeof(n64));
vP->iov_base = wP; vP->iov_len = Sz64; vP++;
wP += Sz64; TotLen += Sz64; dlen = sizeof(n64);
break;
case PT_special: break;
case PT_Fence: break;
case PT_Ignore: break;
case PT_MandS:
case PT_Mark:
*Base.B08 = (char *)vP;
if (pP->Dtype == PT_Mark) break;
vP++;
break;
case PT_Skip:
vP++;
break;
case PT_Datlen:
*Base.B32 = dlen;
break;
case PT_Totlen:
*Base.B32 = TotLen;
break;
case PT_EndFill:
*Base.B16 = htons(static_cast<unsigned short>(TotLen));
return static_cast<int>(vP-iovP);
case PT_End:
return static_cast<int>(vP-iovP);
default: {}
}
pP++;
Dtype = pP->Dtype;
} while(vP < iovE || (vP==iovE && Dtype != PT_Skip && (Dtype & PT_MaskD)));
// We over-ran the iovec array
//
return eMsg("arg list too long packing", int(pP-pup), pup);
}
/******************************************************************************/
/* U n p a c k */
/******************************************************************************/
int XrdOucPup::Unpack( char **buff,
const char *bend,
char **data,
int &dlen)
{
unsigned short temp;
char *bnxt = *buff;
// Grab the length but make sure it's within bounds
//
if ((bnxt = bnxt+sizeof(temp)) > bend) return 0;
memcpy(&temp, *buff, sizeof(temp));
dlen = static_cast<int>(ntohs(temp));
// Now grab the data
//
if (dlen) {*data = (char *)bnxt; bnxt += dlen;}
else *data = 0;
*buff = bnxt;
return (bnxt <= bend);
}
/******************************************************************************/
int XrdOucPup::Unpack(const char *buff, const char *bend,
XrdOucPupArgs *pup, char *base)
{
const char *bp = buff, *dp;
XrdOucPupArgs *uP = pup;
int dlen = 0, Dtype, Aok = 0, Done = 0;
union {unsigned long long b64;
unsigned int b32;
unsigned short b16;
unsigned char b08;} Temp;
union {unsigned long long *B64;
unsigned int *B32;
unsigned short *B16;
char **B08;} Base;
while(!Done)
{Base.B08 = (char **)(base+uP->Doffs);
if (uP->Dtype & PT_MaskD)
{switch(uP->Dtype)
{case PT_Fence: Aok = 1; break;
case PT_Datlen: *Base.B32 = dlen; break;
case PT_End:
case PT_EndFill: Done = 1; uP--; break;
default: {}
}
uP++; continue;
}
if (bp+2 > bend)
{if (bp == bend && Aok) {Done = 1; uP--; break;}
return eMsg("buffer overrun unpacking", int(uP-pup), uP);
}
if (uP->Dtype == PT_char && !(*bp & PT_short))
{memcpy(&Temp.b16, bp, sizeof(unsigned short));
dlen = static_cast<int>(ntohs(Temp.b16));
bp += sizeof(unsigned short);
if (dlen)
if (bp+dlen > bend)
return eMsg("buffer overrun unpacking", int(uP-pup), uP);
else *Base.B08 = (char *)bp;
else if (!Aok) break;
else *Base.B08 = 0;
} else {
Dtype = static_cast<int>(*bp & PT_MaskT);
if ((unsigned char)Dtype != uP->Dtype)
return eMsg("arg/data mismatch unpacking", int(uP-pup), uP);
if (!(dlen = (*bp & PT_MaskB)>>3)) dlen = sizeof(unsigned short);
dp = (*bp & PT_Inline ? bp : bp+1);
if (dp+dlen > bend)
return eMsg("buffer overrun unpacking", int(uP-pup), uP);
memcpy(&Temp.b64, dp, dlen);
if (bp == dp) Temp.b08 &= PT_MaskD;
else bp++;
switch(Dtype)
{case PT_short: *Base.B16 = ntohs(Temp.b16); break;
case PT_int: *Base.B32 = ntohl(Temp.b32); break;
case PT_longlong: *Base.B64 = ntohll(Temp.b64); break;
default: {}
}
}
uP++; bp += dlen;
};
// Make sure we are not missing any items
//
if (Aok || uP->Dtype == PT_End || uP->Dtype == PT_EndFill)
return static_cast<int>(uP-pup);
return eMsg("missing arg unpacking", int(uP-pup), uP);
}
/******************************************************************************/
/* e M s g */
/******************************************************************************/
int XrdOucPup::eMsg(const char *etxt, int ino, XrdOucPupArgs *pup)
{
const char *dtn;
char buff[1024];
// Check if we can print an error message
//
if (!eDest) return 0;
// Get type name
//
switch(pup->Dtype)
{case PT_char: dtn = "char"; break;
case PT_short: dtn = "short"; break;
case PT_int: dtn = "int"; break;
case PT_longlong: dtn = "long long"; break;
case PT_special: dtn = "special"; break;
default: dtn = ""; break;
};
// Format the message
//
sprintf(buff, "%s arg %d: %s.", dtn, ino,
(!Names||pup->Name >= Names->NLnum ? "?" : Names->NList[pup->Name]));
eDest->Emsg("Pup", etxt, buff);
return 0;
}
eDest
static XrdSysError eDest(0,"crypto_")
XrdOucPup.hh
XrdOucPupArgs::Dlen
short Dlen
Definition XrdOucPup.hh:72
XrdOucPupArgs::Name
unsigned char Name
Definition XrdOucPup.hh:73
XrdOucPupArgs::Doffs
int Doffs
Definition XrdOucPup.hh:71
PT_Totlen
@ PT_Totlen
Definition XrdOucPup.hh:52
PT_MandS
@ PT_MandS
Definition XrdOucPup.hh:49
PT_special
@ PT_special
Definition XrdOucPup.hh:61
PT_short
@ PT_short
Definition XrdOucPup.hh:58
PT_MaskD
@ PT_MaskD
Definition XrdOucPup.hh:67
PT_Datlen
@ PT_Datlen
Definition XrdOucPup.hh:51
PT_Fence
@ PT_Fence
Definition XrdOucPup.hh:50
PT_int
@ PT_int
Definition XrdOucPup.hh:59
PT_Mask
@ PT_Mask
Definition XrdOucPup.hh:66
PT_EndFill
@ PT_EndFill
Definition XrdOucPup.hh:54
PT_MaskT
@ PT_MaskT
Definition XrdOucPup.hh:65
PT_Skip
@ PT_Skip
Definition XrdOucPup.hh:48
PT_MaskB
@ PT_MaskB
Definition XrdOucPup.hh:64
PT_Inline
@ PT_Inline
Definition XrdOucPup.hh:63
PT_char
@ PT_char
Definition XrdOucPup.hh:57
PT_longlong
@ PT_longlong
Definition XrdOucPup.hh:60
PT_Mark
@ PT_Mark
Definition XrdOucPup.hh:47
PT_Ignore
@ PT_Ignore
Definition XrdOucPup.hh:46
PT_End
@ PT_End
Definition XrdOucPup.hh:53
XrdOucPupArgs::Dtype
unsigned char Dtype
Definition XrdOucPup.hh:74
XrdOucPupArgs
Definition XrdOucPup.hh:71
eMsg
#define eMsg(x)
Definition XrdSecsssAdmin.cc:53
XrdSysError.hh
XrdSysHeaders.hh
XrdSysPlatform.hh
XrdOucPup::MaxLen
static const int MaxLen
Definition XrdOucPup.hh:102
XrdOucPup::Unpack
static int Unpack(char **buff, const char *bend, char **data, int &dlen)
Definition XrdOucPup.cc:250
XrdOucPup::Pack
static int Pack(struct iovec **, const char *, unsigned short &buff)
Definition XrdOucPup.cc:52