Skip to content

Commit

Permalink
Merge pull request #457 from zowe/bugfix/long-parm-support
Browse files Browse the repository at this point in the history
Add support for longer cross-memory server parms
  • Loading branch information
JoeNemo authored Aug 22, 2024
2 parents 59be7a4 + 488a8e9 commit 02bd07f
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 18 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## `2.18.1`
- Bugfix: IARV64 results must be checked for 0x7FFFF000 (#474)
- Bugfix: SLH should not ABEND when MEMLIMIT is reached (additional NULL check)
- Bugfix: support cross-memory server parameters longer than 128 characters
(zowe/zss#684)

## `2.18.0`
- Minor `components.zss.logLevels._zss.httpserver=5` debug messages enhancement (#471)
Expand Down
193 changes: 176 additions & 17 deletions c/crossmemory.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include "utils.h"
#include "zvt.h"

#define CMS_STATIC_ASSERT($expr) typedef char p[($expr) ? 1 : -1]

#define CROSS_MEMORY_SERVER_MIN_NAME_LENGTH 4
#define CROSS_MEMORY_SERVER_MAX_NAME_LENGTH 16

Expand Down Expand Up @@ -598,12 +600,32 @@ typedef struct CrossMemoryServerConfigServiceParm_tag {
char eyecatcher[8];
#define CMS_CONFIG_SERVICE_PARM_EYECATCHER "RSCMSCSY"
char nameNullTerm[CMS_CONFIG_PARM_MAX_NAME_LENGTH + 1];
char padding[7];
CrossMemoryServerConfigParm result;
uint8_t version;
#define CMS_CONFIG_SERVICE_PARM_VERSION_0 0
#define CMS_CONFIG_SERVICE_PARM_VERSION_2 2
#define CMS_CONFIG_SERVICE_PARM_SIZE_V0 227
#define CMS_CONFIG_SERVICE_PARM_SIZE_V2 227
#define CMS_CONFIG_SERVICE_PARM_VERSION CMS_CONFIG_SERVICE_PARM_VERSION_2
char padding[6];
union {
CrossMemoryServerConfigParm result;
struct { // only for versions >= 2
int32_t nameLength;
int32_t valueBufferLength;
PAD_LONG(0, const char *name);
PAD_LONG(1, void *valueBuffer);
CrossMemoryServerConfigParmExt result;
} ext;
};
} CrossMemoryServerConfigServiceParm;

ZOWE_PRAGMA_PACK_RESET

CMS_STATIC_ASSERT(CMS_CONFIG_SERVICE_PARM_SIZE_V0 ==
sizeof(CrossMemoryServerConfigServiceParm));
CMS_STATIC_ASSERT(CMS_CONFIG_SERVICE_PARM_SIZE_V2 ==
sizeof(CrossMemoryServerConfigServiceParm));

static void initLogMessagePrefix(LogMessagePrefix *prefix) {
LogTimestamp currentTime;
getCurrentLogTimestamp(&currentTime);
Expand Down Expand Up @@ -984,7 +1006,7 @@ int cmsAddConfigParm(CrossMemoryServer *server,
ShortLivedHeap *slh = server->slh;

size_t keyLength = strlen(name);
if (keyLength > CMS_CONFIG_PARM_MAX_NAME_LENGTH) {
if (keyLength > CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH) {
return RC_CMS_CONFIG_PARM_NAME_TOO_LONG;
}

Expand All @@ -995,28 +1017,33 @@ int cmsAddConfigParm(CrossMemoryServer *server,

strcpy(keyNullTerm, name);

CrossMemoryServerConfigParm *parm =
(CrossMemoryServerConfigParm *)SLHAlloc(
CrossMemoryServerConfigParmExt *parm =
(CrossMemoryServerConfigParmExt *)SLHAlloc(
slh,
sizeof(CrossMemoryServerConfigParm)
sizeof(CrossMemoryServerConfigParmExt)
);
if (parm == NULL) {
return RC_CMS_SLH_ALLOC_FAILED;
}

memcpy(parm->eyecatcher, CMS_PARM_EYECATCHER, sizeof(parm->eyecatcher));
memcpy(parm->eyecatcher, CMS_CONFIG_PARM_EXT_EYECATCHER,
sizeof(parm->eyecatcher));
parm->type = type;

switch (type) {
case CMS_CONFIG_PARM_TYPE_CHAR:
{
const char *charValueNullTerm = value;
size_t valueLength = strlen(charValueNullTerm);
if (valueLength > sizeof(parm->charValueNullTerm) - 1) {
if (valueLength > CMS_CONFIG_PARM_EXT_MAX_VALUE_SIZE) {
return RC_CMS_CHAR_PARM_TOO_LONG;
}
parm->valueLength = valueLength;
strcpy(parm->charValueNullTerm, charValueNullTerm);
parm->value = SLHAlloc(slh, valueLength + 1);
if (parm->value == NULL) {
return RC_CMS_SLH_ALLOC_FAILED;
}
strcpy(parm->value, charValueNullTerm);
}
break;
default:
Expand Down Expand Up @@ -1784,6 +1811,9 @@ static int handleConfigService(CrossMemoryServer *server,
return RC_CMS_STDSVC_PARM_NULL;
}

// Copying different versions using the same size is fine because both v0 and
// v2 have the same size, but, if this changes in the future, more complicated
// logic would need to be implemented.
CrossMemoryServerConfigServiceParm localParm;
cmCopyFromSecondaryWithCallerKey(&localParm, callerParm,
sizeof(CrossMemoryServerConfigServiceParm));
Expand All @@ -1793,16 +1823,58 @@ static int handleConfigService(CrossMemoryServer *server,
return RC_CMS_STDSVC_PARM_BAD_EYECATCHER;
}

localParm.nameNullTerm[sizeof(localParm.nameNullTerm) - 1] = '\0';

CrossMemoryServerConfigParm *configParm =
htGet(server->configParms, localParm.nameNullTerm);
if (configParm == NULL) {
return RC_CMS_CONFIG_PARM_NOT_FOUND;
if (localParm.version != CMS_CONFIG_SERVICE_PARM_VERSION_0 &&
localParm.version != CMS_CONFIG_SERVICE_PARM_VERSION_2) {
return RC_CMS_STDSVC_PARM_BAD_VERSION;
}

cmCopyToSecondaryWithCallerKey(&callerParm->result, configParm,
sizeof(callerParm->result));
if (localParm.version == CMS_CONFIG_SERVICE_PARM_VERSION_0) {
localParm.nameNullTerm[sizeof(localParm.nameNullTerm) - 1] = '\0';
CrossMemoryServerConfigParmExt *configParm = htGet(server->configParms,
localParm.nameNullTerm);
if (configParm == NULL) {
return RC_CMS_CONFIG_PARM_NOT_FOUND;
}
size_t valueCopyLength = configParm->type == CMS_CONFIG_PARM_TYPE_CHAR ?
configParm->valueLength + 1 : configParm->valueLength;
if (valueCopyLength > sizeof(localParm.result.charValueNullTerm)) {
return RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL;
}
localParm.result = (CrossMemoryServerConfigParm) {
.eyecatcher = CMS_PARM_EYECATCHER,
.valueLength = configParm->valueLength,
.type = configParm->type,
};
memcpy(localParm.result.charValueNullTerm, configParm->value,
valueCopyLength);
cmCopyToSecondaryWithCallerKey(callerParm, &localParm,
CMS_CONFIG_SERVICE_PARM_SIZE_V0);
} else {
char nameLocalBuffer[CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH + 1];
if (localParm.ext.nameLength > sizeof(nameLocalBuffer) - 1) {
return RC_CMS_CONFIG_PARM_NAME_TOO_LONG;
}
cmCopyFromSecondaryWithCallerKey(nameLocalBuffer, localParm.ext.name,
localParm.ext.nameLength);
nameLocalBuffer[localParm.ext.nameLength] = '\0';
CrossMemoryServerConfigParmExt *configParm = htGet(server->configParms,
nameLocalBuffer);
if (configParm == NULL) {
return RC_CMS_CONFIG_PARM_NOT_FOUND;
}
size_t valueCopyLength = configParm->type == CMS_CONFIG_PARM_TYPE_CHAR ?
configParm->valueLength + 1 : configParm->valueLength;
localParm.ext.result = *configParm;
localParm.ext.result.value = localParm.ext.valueBuffer;
cmCopyToSecondaryWithCallerKey(callerParm, &localParm,
CMS_CONFIG_SERVICE_PARM_SIZE_V2);
if (valueCopyLength > localParm.ext.valueBufferLength) {
return RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL;
}
cmCopyToSecondaryWithCallerKey(localParm.ext.valueBuffer,
configParm->value,
valueCopyLength);
}

return RC_CMS_OK;
}
Expand Down Expand Up @@ -5335,6 +5407,7 @@ int cmsGetConfigParm(const CrossMemoryServerName *serverName, const char *name,
memcpy(parmList.eyecatcher, CMS_CONFIG_SERVICE_PARM_EYECATCHER,
sizeof(parmList.eyecatcher));
memcpy(parmList.nameNullTerm, name, nameLength);
parmList.version = CMS_CONFIG_SERVICE_PARM_VERSION_0;

int serviceRC = cmsCallService(
serverName,
Expand Down Expand Up @@ -5364,6 +5437,7 @@ int cmsGetConfigParmUnchecked(const CrossMemoryServerName *serverName,
memcpy(parmList.eyecatcher, CMS_CONFIG_SERVICE_PARM_EYECATCHER,
sizeof(parmList.eyecatcher));
memcpy(parmList.nameNullTerm, name, nameLength);
parmList.version = CMS_CONFIG_SERVICE_PARM_VERSION_0;

CrossMemoryServerGlobalArea *cmsGA = NULL;
int getGlobalAreaRC = cmsGetGlobalArea(serverName, &cmsGA);
Expand All @@ -5387,6 +5461,91 @@ int cmsGetConfigParmUnchecked(const CrossMemoryServerName *serverName,
return RC_CMS_OK;
}

int cmsGetConfigParmExt(const CrossMemoryServerName *serverName,
const char *name,
void *valueBuffer,
int valueBufferSize,
CrossMemoryServerConfigParmExt *parm,
int *rsn) {

size_t nameLength = strlen(name);
if (nameLength > CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH) {
return RC_CMS_CONFIG_PARM_NAME_TOO_LONG;
}

CrossMemoryServerConfigServiceParm parmList = {
.eyecatcher = CMS_CONFIG_SERVICE_PARM_EYECATCHER,
.version = CMS_CONFIG_SERVICE_PARM_VERSION,
.ext.nameLength = nameLength,
.ext.name = name,
.ext.valueBufferLength = valueBufferSize,
.ext.valueBuffer = valueBuffer,
};

int serviceRC = cmsCallService(
serverName,
CROSS_MEMORY_SERVER_CONFIG_SERVICE_ID,
&parmList,
rsn
);
if (serviceRC != RC_CMS_OK) {
if (serviceRC == RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL) {
*parm = parmList.ext.result;
}
return serviceRC;
}

*parm = parmList.ext.result;

return RC_CMS_OK;
}

int cmsGetConfigParmExtUnchecked(const CrossMemoryServerName *serverName,
const char *name,
void *valueBuffer,
int valueBufferSize,
CrossMemoryServerConfigParmExt *parm,
int *rsn) {

size_t nameLength = strlen(name);
if (nameLength > CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH) {
return RC_CMS_CONFIG_PARM_NAME_TOO_LONG;
}

CrossMemoryServerConfigServiceParm parmList = {
.eyecatcher = CMS_CONFIG_SERVICE_PARM_EYECATCHER,
.version = CMS_CONFIG_SERVICE_PARM_VERSION,
.ext.nameLength = nameLength,
.ext.name = name,
.ext.valueBufferLength = valueBufferSize,
.ext.valueBuffer = valueBuffer,
};

CrossMemoryServerGlobalArea *cmsGA = NULL;
int getGlobalAreaRC = cmsGetGlobalArea(serverName, &cmsGA);
if (getGlobalAreaRC != RC_CMS_OK) {
return getGlobalAreaRC;
}

int serviceRC = cmsCallService3(
cmsGA,
CROSS_MEMORY_SERVER_CONFIG_SERVICE_ID,
&parmList,
CMS_CALL_FLAG_NO_SAF_CHECK,
rsn
);
if (serviceRC != RC_CMS_OK) {
if (serviceRC == RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL) {
*parm = parmList.ext.result;
}
return serviceRC;
}

*parm = parmList.ext.result;

return RC_CMS_OK;
}

int cmsGetPCLogLevel(const CrossMemoryServerName *serverName) {

int logLevel = ZOWE_LOG_NA;
Expand Down
58 changes: 57 additions & 1 deletion h/crossmemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@
#define RC_CMS_NO_ROOM_FOR_CMS_GETTER 91
#define RC_CMS_LANC_NOT_LOCKED 92
#define RC_CMS_LANC_NOT_RELEASED 93
#define RC_CMS_MAX_RC 93
#define RC_CMS_STDSVC_PARM_BAD_VERSION 94
#define RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL 95
#define RC_CMS_MAX_RC 95

extern const char *CMS_RC_DESCRIPTION[];

Expand Down Expand Up @@ -377,9 +379,11 @@ typedef struct CrossMemoryServerParmList_tag {
PAD_LONG(1, void *callerData);
} CrossMemoryServerParmList;

#pragma enum(1)
typedef enum CrossMemoryServerParmType_tag {
CMS_CONFIG_PARM_TYPE_CHAR
} CrossMemoryServerParmType;
#pragma enum(reset)

#define CMS_CONFIG_PARM_MAX_NAME_LENGTH 72
#define CMS_CONFIG_PARM_MAX_VALUE_SIZE 128
Expand All @@ -394,6 +398,19 @@ typedef struct CrossMemoryServerConfigParm_tag {
};
} CrossMemoryServerConfigParm;

typedef struct CrossMemoryServerConfigParmExt_tag {
char eyecatcher[8];
#define CMS_CONFIG_PARM_EXT_EYECATCHER "RSCMSCFX"
uint8_t version;
#define CMS_CONFIG_PARM_EXT_VERSION 1
CrossMemoryServerParmType type;
char padding0[2];
#define CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH 1024
#define CMS_CONFIG_PARM_EXT_MAX_VALUE_SIZE INT32_MAX
int32_t valueLength;
PAD_LONG(0, void *value);
} CrossMemoryServerConfigParmExt;

typedef struct CrossMemoryServerStatus_tag {
int cmsRC;
char descriptionNullTerm[64];
Expand Down Expand Up @@ -424,6 +441,8 @@ ZOWE_PRAGMA_PACK_RESET
#define cmsHexDump CMHEXDMP
#define cmsGetConfigParm CMGETPRM
#define cmsGetConfigParmUnchecked CMGETPRU
#define cmsGetConfigParmExt CMGETPRX
#define cmsGetConfigParmExtUnchecked CMGETPUX
#define cmsGetPCLogLevel CMGETLOG
#define cmsGetStatus CMGETSTS
#define cmsMakeServerName CMMKSNAM
Expand Down Expand Up @@ -559,6 +578,43 @@ int cmsGetConfigParm(const CrossMemoryServerName *serverName, const char *name,
int cmsGetConfigParmUnchecked(const CrossMemoryServerName *serverName,
const char *name,
CrossMemoryServerConfigParm *parm);
/**
* @brief Get a parameter from the cross-memory server's PARMLIB
* @param[in] serverName Cross-memory server whose parameter is to be read
* @param[in] name Name of the parameter
* @param[out] valueBuffer Buffer for the result value
* @param[out] valueBufferSize Size of the value buffer
* @param[out] parm Result parameter entry
* @param[out] rsn Reason code provided by the service in case of a failure
* @return RC_CMS_OK in case of success, and one of the RC_CMS_nn values in
* case of failure
*/
int cmsGetConfigParmExt(const CrossMemoryServerName *serverName,
const char *name,
void *valueBuffer,
int valueBufferSize,
CrossMemoryServerConfigParmExt *parm,
int *rsn);


/**
* @brief Get a parameter from the cross-memory server's PARMLIB without the
* authorization check (the caller must be SUP or system key)
* @param[in] serverName Cross-memory server whose parameter is to be read
* @param[in] name Name of the parameter
* @param[out] valueBuffer Buffer for the result value
* @param[out] valueBufferSize Size of the value buffer
* @param[out] parm Result parameter entry
* @param[out] rsn Reason code provided by the service in case of a failure
* @return RC_CMS_OK in case of success, and one of the RC_CMS_nn values in
* case of failure
*/
int cmsGetConfigParmExtUnchecked(const CrossMemoryServerName *serverName,
const char *name,
void *valueBuffer,
int valueBufferSize,
CrossMemoryServerConfigParmExt *parm,
int *rsn);

int cmsGetPCLogLevel(const CrossMemoryServerName *serverName);
CrossMemoryServerStatus cmsGetStatus(const CrossMemoryServerName *serverName);
Expand Down

0 comments on commit 02bd07f

Please sign in to comment.