//INFO: function can be removed if no certification is required static bool checkValidityOfOriginParameter(MmsValue* origin) { if (MmsValue_getType(origin) != MMS_STRUCTURE) return false; if (MmsValue_getArraySize(origin) != 2) return false; MmsValue* orIdent = MmsValue_getElement(origin, 1); if (MmsValue_getType(orIdent) != MMS_OCTET_STRING) return false; if (MmsValue_getOctetStringSize(orIdent) > 64) return false; MmsValue* orCat = MmsValue_getElement(origin, 0); if (MmsValue_getType(orCat) != MMS_INTEGER) return false; int orCatIntValue = MmsValue_toInt32(orCat); if ((orCatIntValue < 0) || (orCatIntValue > 8)) return false; return true; }
static int encodeArrayAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encode) { int elementsSize = 0; int i; int arraySize = MmsValue_getArraySize(value); for (i = 0; i < arraySize; i++) { MmsValue* element = MmsValue_getElement(value, i); elementsSize += mmsServer_encodeAccessResult(element, NULL, 0, false); } if (encode) { buffer[bufPos++] = 0xa1; /* tag for array */ bufPos = BerEncoder_encodeLength(elementsSize, buffer, bufPos); for (i = 0; i < arraySize; i++) { MmsValue* element = MmsValue_getElement(value, i); bufPos = mmsServer_encodeAccessResult(element, buffer, bufPos, true); } return bufPos; } else { int size = 1 + elementsSize + BerEncoder_determineLengthSize(elementsSize); return size; } }
static void updateOrClone(MmsValue** valuePtr, MmsValue* values, int index) { if (*valuePtr != NULL) MmsValue_update(*valuePtr, MmsValue_getElement(values, index)); else *valuePtr = MmsValue_clone(MmsValue_getElement(values, index)); }
static MmsValue* getOperParameterCtlNum(MmsValue* operParameters) { if (MmsValue_getType(operParameters) == MMS_STRUCTURE) { if (MmsValue_getArraySize(operParameters) == 7) return MmsValue_getElement(operParameters, 3); else if (MmsValue_getArraySize(operParameters) == 6) return MmsValue_getElement(operParameters, 2); } return NULL; }
static MmsValue* getCancelParameterOrigin(MmsValue* operParameters) { if (MmsValue_getType(operParameters) == MMS_STRUCTURE) { if (MmsValue_getArraySize(operParameters) == 6) return MmsValue_getElement(operParameters, 2); else if (MmsValue_getArraySize(operParameters) == 5) return MmsValue_getElement(operParameters, 1); } return NULL; }
static MmsValue* getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsTypeSpecification* namedVariable, MmsValue* structuredValue) { if (isAccessToArrayComponent(alternateAccess)) { Identifier_t component = alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess ->list.array[0]->choice.unnamed->choice.selectAccess.choice.component; if (component.size > 129) return NULL; int elementCount = namedVariable->typeSpec.structure.elementCount; MmsTypeSpecification* structSpec = namedVariable->typeSpec.array.elementTypeSpec; int i; for (i = 0; i < elementCount; i++) { if (strncmp (structSpec->typeSpec.structure.elements[i]->name, (const char*) component.buf, component.size) == 0) { MmsValue* value = MmsValue_getElement(structuredValue, i); return value; } } } return NULL; }
uint16_t ClientGooseControlBlock_getDstAddress_appid(ClientGooseControlBlock self) { if (self->dstAddress != NULL) return (uint16_t) MmsValue_toUint32(MmsValue_getElement(self->dstAddress, 3)); else return 0; }
uint8_t ClientGooseControlBlock_getDstAddress_priority(ClientGooseControlBlock self) { if (self->dstAddress != NULL) return (uint8_t) MmsValue_toUint32(MmsValue_getElement(self->dstAddress, 1)); else return 0; }
MmsValue* ClientGooseControlBlock_getDstAddress_addr(ClientGooseControlBlock self) { if (self->dstAddress != NULL) return MmsValue_getElement(self->dstAddress, 0); else return NULL; }
static void printDataSetValues(MmsValue* dataSet) { int i; for (i = 0; i < 4; i++) { printf(" GGIO1.SPCSO%i.stVal: %i\n", i, MmsValue_getBoolean(MmsValue_getElement(dataSet, i))); } }
void ClientGooseControlBlock_setDstAddress_appid(ClientGooseControlBlock self, uint16_t appidValue) { if (self->dstAddress == NULL) self->dstAddress = newEmptyPhyCommAddress(); MmsValue* appid = MmsValue_getElement(self->dstAddress, 3); MmsValue_setUint16(appid, appidValue); }
void ClientGooseControlBlock_setDstAddress_priority(ClientGooseControlBlock self, uint8_t priorityValue) { if (self->dstAddress == NULL) self->dstAddress = newEmptyPhyCommAddress(); MmsValue* priority = MmsValue_getElement(self->dstAddress, 1); MmsValue_setUint8(priority, priorityValue); }
void ClientGooseControlBlock_setDstAddress_addr(ClientGooseControlBlock self, MmsValue* macAddr) { if (self->dstAddress == NULL) self->dstAddress = newEmptyPhyCommAddress(); MmsValue* addr = MmsValue_getElement(self->dstAddress, 0); MmsValue_update(addr, macAddr); }
static MmsValue* getOperParameterTime(MmsValue* operParameters) { MmsValue* timeParameter = NULL; if (MmsValue_getType(operParameters) == MMS_STRUCTURE) { if (MmsValue_getArraySize(operParameters) == 7) timeParameter = MmsValue_getElement(operParameters, 4); else if (MmsValue_getArraySize(operParameters) == 6) timeParameter = MmsValue_getElement(operParameters, 3); } if (timeParameter != NULL) if ((MmsValue_getType(timeParameter) == MMS_UTC_TIME) || (MmsValue_getType(timeParameter) == MMS_BINARY_TIME)) return timeParameter; return NULL; }
static MmsValue* getCtlVal(MmsValue* ctlParameters) { if (ctlParameters->type == MMS_STRUCTURE) { if (ctlParameters->value.structure.size > 5) { return MmsValue_getElement(ctlParameters, 0); } } return NULL; }
static MmsValue* getOperParameterOperTime(MmsValue* operParameters) { if (MmsValue_getType(operParameters) == MMS_STRUCTURE) { if (MmsValue_getArraySize(operParameters) == 7) return MmsValue_getElement(operParameters, 1); } return NULL; }
static MmsValue* getCtlVal(MmsValue* operParameters) { if (MmsValue_getType(operParameters) == MMS_STRUCTURE) { if (MmsValue_getArraySize(operParameters) > 5) { return MmsValue_getElement(operParameters, 0); } } return NULL; }
bool private_ClientReportControlBlock_updateValues(ClientReportControlBlock self, MmsValue* values) { int rcbElementCount = MmsValue_getArraySize(values); updateOrClone(&(self->rptId), values, 0); updateOrClone(&(self->rptEna), values, 1); if (self->isBuffered) { updateOrClone(&(self->datSet), values, 2); updateOrClone(&(self->confRev), values, 3); updateOrClone(&(self->optFlds), values, 4); updateOrClone(&(self->bufTm), values, 5); updateOrClone(&(self->sqNum), values, 6); updateOrClone(&(self->trgOps), values,7); updateOrClone(&(self->intgPd), values, 8); updateOrClone(&(self->gi), values, 9); updateOrClone(&(self->purgeBuf), values, 10); updateOrClone(&(self->entryId), values, 11); updateOrClone(&(self->timeOfEntry), values, 12); if (rcbElementCount > 13) { MmsValue* element13 = MmsValue_getElement(values, 13); if (MmsValue_getType(element13) == MMS_OCTET_STRING) updateOrClone(&(self->owner), values, 13); else { updateOrClone(&(self->resvTms), values, 13); if (rcbElementCount > 14) updateOrClone(&(self->owner), values, 14); } } } else { updateOrClone(&(self->resv), values, 2); updateOrClone(&(self->datSet), values, 3); updateOrClone(&(self->confRev), values, 4); updateOrClone(&(self->optFlds), values, 5); updateOrClone(&(self->bufTm), values, 6); updateOrClone(&(self->sqNum), values, 7); updateOrClone(&(self->trgOps), values, 8); updateOrClone(&(self->intgPd), values, 9); updateOrClone(&(self->gi), values, 10); if (rcbElementCount == 12) /* owner is optional */ updateOrClone(&(self->owner), values, 11); } return true; }
void handleLastApplErrorMessage(IedConnection self, MmsValue* value) { if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: received LastApplError\n"); MmsValue* lastApplError = value; MmsValue* cntrlObj = MmsValue_getElement(lastApplError, 0); MmsValue* error = MmsValue_getElement(lastApplError, 1); //MmsValue* origin = MmsValue_getElement(lastApplError, 2); MmsValue* ctlNum = MmsValue_getElement(lastApplError, 3); MmsValue* addCause = MmsValue_getElement(lastApplError, 4); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: CntrlObj: %s\n", MmsValue_toString(cntrlObj)); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: ctlNum: %u\n", MmsValue_toUint32(ctlNum)); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: addCause: %i\n", MmsValue_toInt32(addCause)); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: error: %i\n", MmsValue_toInt32(error)); self->lastApplError.ctlNum = MmsValue_toUint32(ctlNum); self->lastApplError.addCause = MmsValue_toInt32(addCause); self->lastApplError.error = MmsValue_toInt32(error); LinkedList control = LinkedList_getNext(self->clientControls); while (control != NULL) { ControlObjectClient object = (ControlObjectClient) control->data; char* objectRef = ControlObjectClient_getObjectReference(object); if (doesControlObjectMatch(objectRef, MmsValue_toString(cntrlObj))) ControlObjectClient_setLastApplError(object, self->lastApplError); control = LinkedList_getNext(control); } }
void reportCallbackFunction(void* parameter, ClientReport report) { MmsValue* dataSetValues = ClientReport_getDataSetValues(report); printf("received report for %s\n", ClientReport_getRcbReference(report)); int i; for (i = 0; i < 4; i++) { ReasonForInclusion reason = ClientReport_getReasonForInclusion(report, i); if (reason != REASON_NOT_INCLUDED) { printf(" GGIO1.SPCSO%i.stVal: %i (included for reason %i)\n", i, MmsValue_getBoolean(MmsValue_getElement(dataSetValues, i)), reason); } } }
static void alternateArrayAccess(MmsServerConnection* connection, AlternateAccess_t* alternateAccess, MmsDomain* domain, char* itemId, LinkedList values, MmsTypeSpecification* namedVariable) { if (mmsServer_isIndexAccess(alternateAccess)) { int lowIndex = mmsServer_getLowIndex(alternateAccess); int numberOfElements = mmsServer_getNumberOfElements(alternateAccess); if (DEBUG) printf("Alternate access index: %i elements %i\n", lowIndex, numberOfElements); int index = lowIndex; MmsValue* value = NULL; MmsValue* arrayValue = mmsServer_getValue(connection->server, domain, itemId); if (arrayValue != NULL) { if (numberOfElements == 0) if (isAccessToArrayComponent(alternateAccess)) { if (namedVariable->typeSpec.array.elementTypeSpec->type == MMS_STRUCTURE) { MmsValue* structValue = MmsValue_getElement(arrayValue, index); if (structValue != NULL) value = getComponentOfArrayElement(alternateAccess, namedVariable, structValue); } } else value = MmsValue_getElement(arrayValue, index); else { value = MmsValue_createEmtpyArray(numberOfElements); MmsValue_setDeletable(value); int resultIndex = 0; while (index < lowIndex + numberOfElements) { MmsValue* elementValue = NULL; elementValue = MmsValue_getElement(arrayValue, index); if (!MmsValue_isDeletable(elementValue)) elementValue = MmsValue_clone(elementValue); MmsValue_setElement(value, resultIndex, elementValue); index++; resultIndex++; } } appendValueToResultList(value, values); if (MmsValue_isDeletable(arrayValue)) MmsValue_delete(arrayValue); } else /* access error */ appendErrorToResultList(values, 10 /* object-non-existant*/); } else { // invalid access if (DEBUG) printf("Invalid alternate access\n"); appendErrorToResultList(values, 10 /* object-non-existant*/); } }
ControlObjectClient ControlObjectClient_create(const char* objectReference, IedConnection connection) { ControlObjectClient self = NULL; /* request control model from server */ char domainId[65]; char itemId[65]; char* domainName = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainId); if (domainName == NULL) goto exit_function; convertToMmsAndInsertFC(itemId, objectReference + strlen(domainId) + 1, "CF"); int controlObjectItemIdLen = strlen(itemId); strncat(itemId, "$ctlModel", 64 - controlObjectItemIdLen); MmsError mmsError; MmsValue* ctlModel = MmsConnection_readVariable(IedConnection_getMmsConnection(connection), &mmsError, domainId, itemId); if (ctlModel == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: ControlObjectClient_create: failed to get ctlModel from server\n"); goto exit_function; } int ctlModelVal = MmsValue_toUint32(ctlModel); MmsValue_delete(ctlModel); IedClientError error; LinkedList dataDirectory = IedConnection_getDataDirectory(connection, &error, objectReference); if (dataDirectory == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: ControlObjectClient_create: failed to get data directory of control object\n"); goto exit_function; } /* check what control elements are available */ bool hasOper = false; LinkedList element = LinkedList_getNext(dataDirectory); while (element != NULL) { char* objectName = (char*) element->data; if (strcmp(objectName, "Oper") == 0) hasOper = true; element = LinkedList_getNext(element); } LinkedList_destroy(dataDirectory); if (hasOper == false) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: control is missing required element \"Oper\"\n"); goto exit_function; } /* check for time activated control */ bool hasTimeActivatedControl = false; strcpy(itemId, objectReference); strcat(itemId, ".Oper"); dataDirectory = IedConnection_getDataDirectory(connection, &error, itemId); if (dataDirectory == NULL) goto exit_function; element = LinkedList_getNext(dataDirectory); while (element != NULL) { char* objectName = (char*) element->data; if (strcmp(objectName, "operTm") == 0) { hasTimeActivatedControl = true; break; } element = LinkedList_getNext(element); } LinkedList_destroy(dataDirectory); /* get default parameters for Oper control variable */ MmsValue* oper = IedConnection_readObject(connection, &error, itemId, IEC61850_FC_CO); if (oper == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: reading \"Oper\" failed!\n"); goto exit_function; } self = (ControlObjectClient) GLOBAL_CALLOC(1, sizeof(struct sControlObjectClient)); if (self == NULL) goto exit_function; self->objectReference = copyString(objectReference); self->connection = connection; self->ctlModel = (ControlModel) ctlModelVal; self->hasTimeActivatedMode = hasTimeActivatedControl; self->ctlVal = MmsValue_getElement(oper, 0); /* Check for T element type (EntryTime -> Ed.1, Timestamp -> Ed.2) */ MmsValue* t; if (hasTimeActivatedControl) t = MmsValue_getElement(oper, 4); else t = MmsValue_getElement(oper, 3); if (MmsValue_getType(t) == MMS_BINARY_TIME) self->edition = 1; else self->edition = 2; if (DEBUG_IED_CLIENT) printf("IED_CLIENT: Detected edition %i control\n", self->edition); MmsValue_setElement(oper, 0, NULL); MmsValue_delete(oper); private_IedConnection_addControlClient(connection, self); exit_function: return self; }
static int parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues) { int bufPos = 0; int elementLength = 0; int elementIndex = 0; int maxIndex = MmsValue_getArraySize(dataSetValues) - 1; while (bufPos < allDataLength) { uint8_t tag = buffer[bufPos++]; if (elementIndex > maxIndex) { if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: too much elements!\n"); return 0; } MmsValue* value = MmsValue_getElement(dataSetValues, elementIndex); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength); if (bufPos + elementLength > allDataLength) { if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n"); return 0; } switch (tag) { case 0x80: /* reserved for access result */ printf("GOOSE_SUBSCRIBER: found reserved value (tag 0x80)!\n"); break; case 0xa1: /* array */ if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found array\n"); if (MmsValue_getType(value) == MMS_ARRAY) { if (!parseAllData(buffer + bufPos, elementLength, value)) return -1; } break; case 0xa2: /* structure */ if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found structure\n"); if (MmsValue_getType(value) == MMS_STRUCTURE) { if (!parseAllData(buffer + bufPos, elementLength, value)) return -1; } break; case 0x83: /* boolean */ if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found boolean\n"); if (MmsValue_getType(value) == MMS_BOOLEAN) { MmsValue_setBoolean(value, BerDecoder_decodeBoolean(buffer, bufPos)); } else if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: message contains value of wrong type!\n"); break; case 0x84: /* BIT STRING */ if (MmsValue_getType(value) == MMS_BIT_STRING) { int padding = buffer[bufPos]; int bitStringLength = (8 * (elementLength - 1)) - padding; if (bitStringLength == value->value.bitString.size) { memcpy(value->value.bitString.buf, buffer + bufPos + 1, elementLength - 1); } else if (DEBUG_GOOSE_SUBSCRIBER) printf("bit-string is of wrong size"); } break; case 0x85: /* integer */ if (MmsValue_getType(value) == MMS_INTEGER) { if (elementLength <= value->value.integer->maxSize) { value->value.integer->size = elementLength; memcpy(value->value.integer->octets, buffer + bufPos, elementLength); } } break; case 0x86: /* unsigned integer */ if (MmsValue_getType(value) == MMS_UNSIGNED) { if (elementLength <= value->value.integer->maxSize) { value->value.integer->size = elementLength; memcpy(value->value.integer->octets, buffer + bufPos, elementLength); } } break; case 0x87: /* Float */ if (MmsValue_getType(value) == MMS_FLOAT) { if (elementLength == 9) { MmsValue_setDouble(value, BerDecoder_decodeDouble(buffer, bufPos)); } else if (elementLength == 5) { MmsValue_setFloat(value, BerDecoder_decodeFloat(buffer, bufPos)); } } break; case 0x89: /* octet string */ if (MmsValue_getType(value) == MMS_OCTET_STRING) { if (elementLength <= value->value.octetString.maxSize) { value->value.octetString.size = elementLength; memcpy(value->value.octetString.buf, buffer + bufPos, elementLength); } } break; case 0x8a: /* visible string */ if (MmsValue_getType(value) == MMS_VISIBLE_STRING) { if (value->value.visibleString.buf != NULL) { if ((int32_t) value->value.visibleString.size >= elementLength) { memcpy(value->value.visibleString.buf, buffer + bufPos, elementLength); value->value.visibleString.buf[elementLength] = 0; } else { GLOBAL_FREEMEM(value->value.visibleString.buf); createNewStringFromBufferElement(value, buffer + bufPos, elementLength); } } else createNewStringFromBufferElement(value, buffer + bufPos, elementLength); } break; case 0x8c: /* binary time */ if (MmsValue_getType(value) == MMS_BINARY_TIME) { if ((elementLength == 4) || (elementLength == 6)) { memcpy(value->value.binaryTime.buf, buffer + bufPos, elementLength); } } break; case 0x91: /* Utctime */ if (elementLength == 8) { if (MmsValue_getType(value) == MMS_UTC_TIME) { MmsValue_setUtcTimeByBuffer(value, buffer + bufPos); } else if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: message contains value of wrong type!\n"); } else if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: UTCTime element is of wrong size!\n"); break; default: if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found unkown tag %02x\n", tag); break; } bufPos += elementLength; elementIndex++; } return 1; }
/********************************************************************************************** * mmsServer_handleWriteRequest * возвращает MmsServiceError *********************************************************************************************/ int mmsServer_handleWriteRequest( MmsServerConnection* connection, WriteRequest_t* writeRequest, int invokeId, ByteBuffer* response) { ListOfVariableSeq_t* varSpec; Identifier_t domainId; char* domainIdStr; MmsDevice* device; MmsDomain* domain; Identifier_t nameId; char* nameIdStr; MmsTypeSpecification* variable; AlternateAccess_t* alternateAccess; Data_t* dataElement; MmsValue* value; MmsValueIndication valueIndication; if (writeRequest->variableAccessSpecification.choice.listOfVariable.list.count != 1) return -1; varSpec = writeRequest->variableAccessSpecification.choice.listOfVariable.list.array[0]; if (varSpec->variableSpecification.present != VariableSpecification_PR_name) { createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); return 0; } if (varSpec->variableSpecification.choice.name.present != ObjectName_PR_domainspecific) { createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); return 0; } domainId = varSpec->variableSpecification.choice.name.choice.domainspecific.domainId; domainIdStr = createStringFromBuffer(domainId.buf, domainId.size); device = MmsServer_getDevice(connection->server); domain = MmsDevice_getDomain(device, domainIdStr); free(domainIdStr); if (domain == NULL) { createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); return 0; } nameId = varSpec->variableSpecification.choice.name.choice.domainspecific.itemId; nameIdStr = createStringFromBuffer(nameId.buf, nameId.size); variable = MmsDomain_getNamedVariable(domain, nameIdStr); if (variable == NULL) goto return_access_denied; if (writeRequest->listOfData.list.count != 1) goto return_access_denied; alternateAccess = varSpec->alternateAccess; if (alternateAccess != NULL) { if (variable->type != MMS_ARRAY) goto return_access_denied; if (!mmsServer_isIndexAccess(alternateAccess)) goto return_access_denied; } dataElement = writeRequest->listOfData.list.array[0]; value = mmsMsg_parseDataElement(dataElement); if (value == NULL) goto return_access_denied; if (alternateAccess != NULL) { MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr); int index; MmsValue* elementValue; if (cachedArray == NULL) { MmsValue_delete(value); goto return_access_denied; } index = mmsServer_getLowIndex(alternateAccess); elementValue = MmsValue_getElement(cachedArray, index); if (elementValue == NULL) { MmsValue_delete(value); goto return_access_denied; } if (MmsValue_update(elementValue, value) == false) { MmsValue_delete(value); goto return_access_denied; } } MmsServer_lockModel(connection->server); valueIndication = mmsServer_setValue(connection->server, domain, nameIdStr, value, connection); MmsServer_unlockModel(connection->server); createMmsWriteResponse(connection, invokeId, response, valueIndication); MmsValue_delete(value); free(nameIdStr); return 0; return_access_denied: createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); free(nameIdStr); return 0; }
static void createControlObjects(IedServer self, MmsDomain* domain, char* lnName, MmsVariableSpecification* typeSpec, char* namePrefix) { MmsMapping* mapping = self->mmsMapping; if (typeSpec->type == MMS_STRUCTURE) { int coCount = typeSpec->typeSpec.structure.elementCount; int i; for (i = 0; i < coCount; i++) { char objectName[65]; objectName[0] = 0; if (namePrefix != NULL) { strcat(objectName, namePrefix); strcat(objectName, "$"); } bool isControlObject = false; bool hasCancel = false; int cancelIndex = 0; bool hasSBOw = false; int sBOwIndex = 0; int operIndex = 0; MmsVariableSpecification* coSpec = typeSpec->typeSpec.structure.elements[i]; if (coSpec->type == MMS_STRUCTURE) { int coElementCount = coSpec->typeSpec.structure.elementCount; int j; for (j = 0; j < coElementCount; j++) { MmsVariableSpecification* coElementSpec = coSpec->typeSpec.structure.elements[j]; if (strcmp(coElementSpec->name, "Oper") == 0) { isControlObject = true; operIndex = j; } else if (strcmp(coElementSpec->name, "Cancel") == 0) { hasCancel = true; cancelIndex = j; } else if (strcmp(coElementSpec->name, "SBOw") == 0) { hasSBOw = true; sBOwIndex = j; } else if (!(strcmp(coElementSpec->name, "SBO") == 0)) { if (DEBUG_IED_SERVER) printf("IED_SERVER: createControlObjects: Unknown element in CO: %s! --> seems not to be a control object\n", coElementSpec->name); assert(false); break; } } if (isControlObject) { strcat(objectName, coSpec->name); if (DEBUG_IED_SERVER) printf("IED_SERVER: create control object LN:%s DO:%s\n", lnName, objectName); ControlObject* controlObject = ControlObject_create(self, domain, lnName, objectName); MmsValue* structure = MmsValue_newDefaultValue(coSpec); ControlObject_setMmsValue(controlObject, structure); ControlObject_setTypeSpec(controlObject, coSpec); MmsValue* operVal = MmsValue_getElement(structure, operIndex); ControlObject_setOper(controlObject, operVal); if (hasCancel) { MmsValue* cancelVal = MmsValue_getElement(structure, cancelIndex); ControlObject_setCancel(controlObject, cancelVal); } if (hasSBOw) { MmsValue* sbowVal = MmsValue_getElement(structure, sBOwIndex); ControlObject_setSBOw(controlObject, sbowVal); } MmsMapping_addControlObject(mapping, controlObject); } else { strcat(objectName, coSpec->name); createControlObjects(self, domain, lnName, coSpec, objectName); } } } } }
void mmsServer_handleWriteRequest( MmsServerConnection* connection, uint8_t* buffer, int bufPos, int maxBufPos, uint32_t invokeId, ByteBuffer* response) { WriteRequest_t* writeRequest = 0; MmsPdu_t* mmsPdu = 0; asn_dec_rval_t rval; /* Decoder return value */ rval = ber_decode(NULL, &asn_DEF_MmsPdu, (void**) &mmsPdu, buffer, CONFIG_MMS_MAXIMUM_PDU_SIZE); if (rval.code != RC_OK) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response); return; } writeRequest = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.write); int numberOfWriteItems = writeRequest->variableAccessSpecification.choice.listOfVariable.list.count; if (numberOfWriteItems < 1) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response); return; } if (numberOfWriteItems > CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_OTHER, response); return; } if (writeRequest->listOfData.list.count != numberOfWriteItems) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response); return; } MmsDataAccessError accessResults[CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS * sizeof(MmsDataAccessError)]; bool sendResponse = true; int i; for (i = 0; i < numberOfWriteItems; i++) { ListOfVariableSeq_t* varSpec = writeRequest->variableAccessSpecification.choice.listOfVariable.list.array[i]; if (varSpec->variableSpecification.present != VariableSpecification_PR_name) { accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; continue; } if (varSpec->variableSpecification.choice.name.present != ObjectName_PR_domainspecific) { accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; continue; } Identifier_t domainId = varSpec->variableSpecification.choice.name.choice.domainspecific.domainId; char* domainIdStr = createStringFromBuffer(domainId.buf, domainId.size); MmsDevice* device = MmsServer_getDevice(connection->server); MmsDomain* domain = MmsDevice_getDomain(device, domainIdStr); free(domainIdStr); if (domain == NULL) { accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; continue; } Identifier_t nameId = varSpec->variableSpecification.choice.name.choice.domainspecific.itemId; char* nameIdStr = createStringFromBuffer(nameId.buf, nameId.size); MmsVariableSpecification* variable = MmsDomain_getNamedVariable(domain, nameIdStr); if (variable == NULL) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; continue; } AlternateAccess_t* alternateAccess = varSpec->alternateAccess; if (alternateAccess != NULL) { if (variable->type != MMS_ARRAY) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } if (!mmsServer_isIndexAccess(alternateAccess)) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; continue; } } Data_t* dataElement = writeRequest->listOfData.list.array[i]; MmsValue* value = mmsMsg_parseDataElement(dataElement); if (value == NULL) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } if (alternateAccess != NULL) { MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr); if (cachedArray == NULL) { free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } int index = mmsServer_getLowIndex(alternateAccess); MmsValue* elementValue = MmsValue_getElement(cachedArray, index); if (elementValue == NULL) { free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } if (MmsValue_update(elementValue, value) == false) { free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT; continue; } free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_SUCCESS; continue; } MmsDataAccessError valueIndication = mmsServer_setValue(connection->server, domain, nameIdStr, value, connection); if (valueIndication == DATA_ACCESS_ERROR_NO_RESPONSE) sendResponse = false; accessResults[i] = valueIndication; MmsValue_delete(value); free(nameIdStr); } if (sendResponse) { mmsServer_createMmsWriteResponse(connection, invokeId, response, numberOfWriteItems, accessResults); } asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); }
Data_t* mmsMsg_createBasicDataElement(MmsValue* value) { Data_t* dataElement = (Data_t*) GLOBAL_CALLOC(1, sizeof(Data_t)); switch (value->type) { case MMS_ARRAY: { int size = MmsValue_getArraySize(value); dataElement->present = Data_PR_array; dataElement->choice.array = (DataSequence_t*) GLOBAL_CALLOC(1, sizeof(DataSequence_t)); dataElement->choice.array->list.count = size; dataElement->choice.array->list.size = size; dataElement->choice.array->list.array = (Data_t**) GLOBAL_CALLOC(size, sizeof(Data_t*)); int i; for (i = 0; i < size; i++) { dataElement->choice.array->list.array[i] = mmsMsg_createBasicDataElement(MmsValue_getElement(value, i)); } } break; case MMS_STRUCTURE: { int size = value->value.structure.size; dataElement->present = Data_PR_structure; dataElement->choice.structure = (DataSequence_t*) GLOBAL_CALLOC(1, sizeof(DataSequence_t)); dataElement->choice.structure->list.count = size; dataElement->choice.structure->list.size = size; dataElement->choice.structure->list.array = (Data_t**) GLOBAL_CALLOC(size, sizeof(Data_t*)); int i; for (i = 0; i < size; i++) { dataElement->choice.structure->list.array[i] = mmsMsg_createBasicDataElement( value->value.structure.components[i]); } } break; case MMS_BIT_STRING: { dataElement->present = Data_PR_bitstring; dataElement->choice.bitstring.buf = value->value.bitString.buf; int size = (value->value.bitString.size / 8) + ((value->value.bitString.size % 8) > 0); int unused = 8 - (value->value.bitString.size % 8); dataElement->choice.bitstring.size = size; /* size in bytes */ dataElement->choice.bitstring.bits_unused = unused; } break; case MMS_BOOLEAN: dataElement->present = Data_PR_boolean; dataElement->choice.boolean = value->value.boolean; break; case MMS_FLOAT: dataElement->present = Data_PR_floatingpoint; mmsMsg_createFloatData(value, &dataElement->choice.floatingpoint.size, &dataElement->choice.floatingpoint.buf); break; case MMS_UTC_TIME: dataElement->present = Data_PR_utctime; dataElement->choice.utctime.buf = (uint8_t*) GLOBAL_MALLOC(8); memcpy(dataElement->choice.utctime.buf, value->value.utcTime, 8); dataElement->choice.utctime.size = 8; break; case MMS_INTEGER: dataElement->present = Data_PR_integer; dataElement->choice.integer.size = value->value.integer->size; dataElement->choice.integer.buf = value->value.integer->octets; break; case MMS_UNSIGNED: dataElement->present = Data_PR_unsigned; dataElement->choice.Unsigned.size = value->value.integer->size; dataElement->choice.Unsigned.buf = value->value.integer->octets; break; case MMS_VISIBLE_STRING: dataElement->present = Data_PR_visiblestring; if (value->value.visibleString.buf != NULL ) { dataElement->choice.visiblestring.buf = (uint8_t*) value->value.visibleString.buf; dataElement->choice.visiblestring.size = strlen(value->value.visibleString.buf); } else dataElement->choice.visiblestring.size = 0; break; case MMS_OCTET_STRING: dataElement->present = Data_PR_octetstring; if (value->value.octetString.buf != NULL ) { dataElement->choice.octetstring.buf = value->value.octetString.buf; dataElement->choice.octetstring.size = value->value.octetString.size; } else dataElement->choice.octetstring.size = 0; break; case MMS_STRING: dataElement->present = Data_PR_mMSString; if (value->value.visibleString.buf != NULL ) { dataElement->choice.mMSString.buf = (uint8_t*) value->value.visibleString.buf; dataElement->choice.mMSString.size = strlen(value->value.visibleString.buf); } else dataElement->choice.mMSString.size = 0; break; case MMS_BINARY_TIME: dataElement->present = Data_PR_binarytime; dataElement->choice.binarytime.size = value->value.binaryTime.size; dataElement->choice.binarytime.buf = value->value.binaryTime.buf; break; default: dataElement->present = Data_PR_NOTHING; break; } return dataElement; }
MmsValue* ReportControl_getRCBValue(ReportControl* rc, char* elementName) { if (rc->bufferd) { if (strcmp(elementName, "RptID") == 0) return MmsValue_getElement(rc->rcbValues, 0); else if (strcmp(elementName, "RptEna") == 0) return MmsValue_getElement(rc->rcbValues, 1); else if (strcmp(elementName, "DatSet") == 0) return MmsValue_getElement(rc->rcbValues, 2); else if (strcmp(elementName, "ConfRev") == 0) return MmsValue_getElement(rc->rcbValues, 3); else if (strcmp(elementName, "OptFlds") == 0) return MmsValue_getElement(rc->rcbValues, 4); else if (strcmp(elementName, "BufTm") == 0) return MmsValue_getElement(rc->rcbValues, 5); else if (strcmp(elementName, "SqNum") == 0) return MmsValue_getElement(rc->rcbValues, 6); else if (strcmp(elementName, "TrgOps") == 0) return MmsValue_getElement(rc->rcbValues, 7); else if (strcmp(elementName, "IntgPd") == 0) return MmsValue_getElement(rc->rcbValues, 8); else if (strcmp(elementName, "GI") == 0) return MmsValue_getElement(rc->rcbValues, 9); else if (strcmp(elementName, "PurgeBuf") == 0) return MmsValue_getElement(rc->rcbValues, 10); else if (strcmp(elementName, "EntryID") == 0) return MmsValue_getElement(rc->rcbValues, 11); else if (strcmp(elementName, "TimeOfEntry") == 0) return MmsValue_getElement(rc->rcbValues, 12); else if (strcmp(elementName, "ResvTms") == 0) return MmsValue_getElement(rc->rcbValues, 13); else if (strcmp(elementName, "Owner") == 0) return MmsValue_getElement(rc->rcbValues, 14); } else { if (strcmp(elementName, "RptID") == 0) return MmsValue_getElement(rc->rcbValues, 0); else if (strcmp(elementName, "RptEna") == 0) return MmsValue_getElement(rc->rcbValues, 1); else if (strcmp(elementName, "Resv") == 0) return MmsValue_getElement(rc->rcbValues, 2); else if (strcmp(elementName, "DatSet") == 0) return MmsValue_getElement(rc->rcbValues, 3); else if (strcmp(elementName, "ConfRev") == 0) return MmsValue_getElement(rc->rcbValues, 4); else if (strcmp(elementName, "OptFlds") == 0) return MmsValue_getElement(rc->rcbValues, 5); else if (strcmp(elementName, "BufTm") == 0) return MmsValue_getElement(rc->rcbValues, 6); else if (strcmp(elementName, "SqNum") == 0) return MmsValue_getElement(rc->rcbValues, 7); else if (strcmp(elementName, "TrgOps") == 0) return MmsValue_getElement(rc->rcbValues, 8); else if (strcmp(elementName, "IntgPd") == 0) return MmsValue_getElement(rc->rcbValues, 9); else if (strcmp(elementName, "GI") == 0) return MmsValue_getElement(rc->rcbValues, 10); else if (strcmp(elementName, "Owner") == 0) return MmsValue_getElement(rc->rcbValues, 11); } return NULL ; }