MMS: Add IEC 61850 decoding to some fields
Based on https://github.com/robidev/iec61850-dissector and IEC 61850-8-1 found googling
This commit is contained in:
parent
f98f501b61
commit
cd5630e375
|
@ -25,30 +25,47 @@ IMPORTS
|
|||
FROM ISO-8650-ACSE-1;
|
||||
|
||||
|
||||
-- WS additions for IEC 61850
|
||||
|
||||
ReportedOptFlds ::= BIT STRING {
|
||||
reserved(0),
|
||||
sequence-number(1),
|
||||
report-time-stamp(2),
|
||||
reason-for-inclusion(3),
|
||||
data-set-name(4),
|
||||
data-reference(5),
|
||||
buffer-overflow(6),
|
||||
entryID(7),
|
||||
conf-revision(8),
|
||||
segmentation(9)
|
||||
}
|
||||
|
||||
-- End WS additions for IEC 61850
|
||||
|
||||
MMSpdu ::= CHOICE
|
||||
{
|
||||
confirmed-RequestPDU [0] IMPLICIT Confirmed-RequestPDU,
|
||||
confirmed-ResponsePDU [1] IMPLICIT Confirmed-ResponsePDU,
|
||||
confirmed-RequestPDU [0] IMPLICIT Confirmed-RequestPDU,
|
||||
confirmed-ResponsePDU [1] IMPLICIT Confirmed-ResponsePDU,
|
||||
confirmed-ErrorPDU [2] IMPLICIT Confirmed-ErrorPDU,
|
||||
unconfirmed-PDU [3] IMPLICIT Unconfirmed-PDU,
|
||||
rejectPDU [4] IMPLICIT RejectPDU,
|
||||
rejectPDU [4] IMPLICIT RejectPDU,
|
||||
cancel-RequestPDU [5] IMPLICIT Cancel-RequestPDU,
|
||||
cancel-ResponsePDU [6] IMPLICIT Cancel-ResponsePDU,
|
||||
cancel-ErrorPDU [7] IMPLICIT Cancel-ErrorPDU,
|
||||
initiate-RequestPDU [8] IMPLICIT Initiate-RequestPDU,
|
||||
initiate-ResponsePDU [9] IMPLICIT Initiate-ResponsePDU,
|
||||
initiate-ResponsePDU [9] IMPLICIT Initiate-ResponsePDU,
|
||||
initiate-ErrorPDU [10] IMPLICIT Initiate-ErrorPDU,
|
||||
conclude-RequestPDU [11] IMPLICIT Conclude-RequestPDU,
|
||||
conclude-ResponsePDU [12] IMPLICIT Conclude-ResponsePDU,
|
||||
conclude-ResponsePDU [12] IMPLICIT Conclude-ResponsePDU,
|
||||
conclude-ErrorPDU [13] IMPLICIT Conclude-ErrorPDU
|
||||
}
|
||||
|
||||
|
||||
Confirmed-RequestPDU ::= SEQUENCE
|
||||
{
|
||||
invokeID Unsigned32,
|
||||
invokeID Unsigned32,
|
||||
listOfModifier SEQUENCE OF Modifier OPTIONAL,
|
||||
confirmedServiceRequest ConfirmedServiceRequest,
|
||||
confirmedServiceRequest ConfirmedServiceRequest,
|
||||
cs-request-detail [79] CS-Request-Detail OPTIONAL
|
||||
}
|
||||
|
||||
|
@ -95,86 +112,86 @@ Modifier ::= CHOICE
|
|||
|
||||
ConfirmedServiceRequest ::= CHOICE
|
||||
{
|
||||
status [0] IMPLICIT Status-Request,
|
||||
getNameList [1] IMPLICIT GetNameList-Request,
|
||||
identify [2] IMPLICIT Identify-Request,
|
||||
rename [3] IMPLICIT Rename-Request,
|
||||
read [4] IMPLICIT Read-Request,
|
||||
write [5] IMPLICIT Write-Request,
|
||||
getVariableAccessAttributes [6] GetVariableAccessAttributes-Request,
|
||||
defineNamedVariable [7] IMPLICIT DefineNamedVariable-Request,
|
||||
defineScatteredAccess [8] IMPLICIT DefineScatteredAccess-Request,
|
||||
getScatteredAccessAttributes [9] IMPLICIT GetScatteredAccessAttributes-Request,
|
||||
status [0] IMPLICIT Status-Request,
|
||||
getNameList [1] IMPLICIT GetNameList-Request,
|
||||
identify [2] IMPLICIT Identify-Request,
|
||||
rename [3] IMPLICIT Rename-Request,
|
||||
read [4] IMPLICIT Read-Request,
|
||||
write [5] IMPLICIT Write-Request,
|
||||
getVariableAccessAttributes [6] GetVariableAccessAttributes-Request,
|
||||
defineNamedVariable [7] IMPLICIT DefineNamedVariable-Request,
|
||||
defineScatteredAccess [8] IMPLICIT DefineScatteredAccess-Request,
|
||||
getScatteredAccessAttributes [9] IMPLICIT GetScatteredAccessAttributes-Request,
|
||||
deleteVariableAccess [10] IMPLICIT DeleteVariableAccess-Request,
|
||||
defineNamedVariableList [11] IMPLICIT DefineNamedVariableList-Request,
|
||||
getNamedVariableListAttributes [12] IMPLICIT GetNamedVariableListAttributes-Request,
|
||||
getNamedVariableListAttributes [12] IMPLICIT GetNamedVariableListAttributes-Request,
|
||||
deleteNamedVariableList [13] IMPLICIT DeleteNamedVariableList-Request,
|
||||
defineNamedType [14] IMPLICIT DefineNamedType-Request,
|
||||
defineNamedType [14] IMPLICIT DefineNamedType-Request,
|
||||
getNamedTypeAttributes [15] IMPLICIT GetNamedTypeAttributes-Request,
|
||||
deleteNamedType [16] IMPLICIT DeleteNamedType-Request,
|
||||
input [17] IMPLICIT Input-Request,
|
||||
output [18] IMPLICIT Output-Request,
|
||||
takeControl [19] IMPLICIT TakeControl-Request,
|
||||
relinquishControl [20] IMPLICIT RelinquishControl-Request,
|
||||
defineSemaphore [21] IMPLICIT DefineSemaphore-Request,
|
||||
deleteSemaphore [22] IMPLICIT DeleteSemaphore-Request,
|
||||
deleteNamedType [16] IMPLICIT DeleteNamedType-Request,
|
||||
input [17] IMPLICIT Input-Request,
|
||||
output [18] IMPLICIT Output-Request,
|
||||
takeControl [19] IMPLICIT TakeControl-Request,
|
||||
relinquishControl [20] IMPLICIT RelinquishControl-Request,
|
||||
defineSemaphore [21] IMPLICIT DefineSemaphore-Request,
|
||||
deleteSemaphore [22] IMPLICIT DeleteSemaphore-Request,
|
||||
reportSemaphoreStatus [23] IMPLICIT ReportSemaphoreStatus-Request,
|
||||
reportPoolSemaphoreStatus [24] IMPLICIT ReportPoolSemaphoreStatus-Request,
|
||||
reportSemaphoreEntryStatus [25] IMPLICIT ReportSemaphoreEntryStatus-Request,
|
||||
initiateDownloadSequence [26] IMPLICIT InitiateDownloadSequence-Request,
|
||||
downloadSegment [27] IMPLICIT DownloadSegment-Request,
|
||||
downloadSegment [27] IMPLICIT DownloadSegment-Request,
|
||||
terminateDownloadSequence [28] IMPLICIT TerminateDownloadSequence-Request,
|
||||
initiateUploadSequence [29] IMPLICIT InitiateUploadSequence-Request,
|
||||
uploadSegment [30] IMPLICIT UploadSegment-Request,
|
||||
uploadSegment [30] IMPLICIT UploadSegment-Request,
|
||||
terminateUploadSequence [31] IMPLICIT TerminateUploadSequence-Request,
|
||||
requestDomainDownload [32] IMPLICIT RequestDomainDownload-Request,
|
||||
requestDomainUpload [33] IMPLICIT RequestDomainUpload-Request,
|
||||
loadDomainContent [34] IMPLICIT LoadDomainContent-Request,
|
||||
storeDomainContent [35] IMPLICIT StoreDomainContent-Request,
|
||||
deleteDomain [36] IMPLICIT DeleteDomain-Request,
|
||||
getDomainAttributes [37] IMPLICIT GetDomainAttributes-Request,
|
||||
requestDomainUpload [33] IMPLICIT RequestDomainUpload-Request,
|
||||
loadDomainContent [34] IMPLICIT LoadDomainContent-Request,
|
||||
storeDomainContent [35] IMPLICIT StoreDomainContent-Request,
|
||||
deleteDomain [36] IMPLICIT DeleteDomain-Request,
|
||||
getDomainAttributes [37] IMPLICIT GetDomainAttributes-Request,
|
||||
createProgramInvocation [38] IMPLICIT CreateProgramInvocation-Request,
|
||||
deleteProgramInvocation [39] IMPLICIT DeleteProgramInvocation-Request,
|
||||
start [40] IMPLICIT Start-Request,
|
||||
stop [41] IMPLICIT Stop-Request,
|
||||
resume [42] IMPLICIT Resume-Request,
|
||||
reset [43] IMPLICIT Reset-Request,
|
||||
kill [44] IMPLICIT Kill-Request,
|
||||
getProgramInvocationAttributes [45] IMPLICIT GetProgramInvocationAttributes-Request,
|
||||
obtainFile [46] IMPLICIT ObtainFile-Request,
|
||||
start [40] IMPLICIT Start-Request,
|
||||
stop [41] IMPLICIT Stop-Request,
|
||||
resume [42] IMPLICIT Resume-Request,
|
||||
reset [43] IMPLICIT Reset-Request,
|
||||
kill [44] IMPLICIT Kill-Request,
|
||||
getProgramInvocationAttributes [45] IMPLICIT GetProgramInvocationAttributes-Request,
|
||||
obtainFile [46] IMPLICIT ObtainFile-Request,
|
||||
defineEventCondition [47] IMPLICIT DefineEventCondition-Request,
|
||||
deleteEventCondition [48] DeleteEventCondition-Request,
|
||||
getEventConditionAttributes [49] GetEventConditionAttributes-Request,
|
||||
reportEventConditionStatus [50] ReportEventConditionStatus-Request,
|
||||
alterEventConditionMonitoring [51] IMPLICIT AlterEventConditionMonitoring-Request,
|
||||
triggerEvent [52] IMPLICIT TriggerEvent-Request,
|
||||
defineEventAction [53] IMPLICIT DefineEventAction-Request,
|
||||
deleteEventAction [54] DeleteEventAction-Request,
|
||||
alterEventConditionMonitoring [51] IMPLICIT AlterEventConditionMonitoring-Request,
|
||||
triggerEvent [52] IMPLICIT TriggerEvent-Request,
|
||||
defineEventAction [53] IMPLICIT DefineEventAction-Request,
|
||||
deleteEventAction [54] DeleteEventAction-Request,
|
||||
getEventActionAttributes [55] GetEventActionAttributes-Request,
|
||||
reportEventActionStatus [56] ReportEventActionStatus-Request,
|
||||
defineEventEnrollment [57] IMPLICIT DefineEventEnrollment-Request,
|
||||
deleteEventEnrollment [58] DeleteEventEnrollment-Request,
|
||||
alterEventEnrollment [59] IMPLICIT AlterEventEnrollment-Request,
|
||||
reportEventEnrollmentStatus [60] ReportEventEnrollmentStatus-Request,
|
||||
getEventEnrollmentAttributes [61] IMPLICIT GetEventEnrollmentAttributes-Request,
|
||||
acknowledgeEventNotification [62] IMPLICIT AcknowledgeEventNotification-Request,
|
||||
getAlarmSummary [63] IMPLICIT GetAlarmSummary-Request,
|
||||
getEventEnrollmentAttributes [61] IMPLICIT GetEventEnrollmentAttributes-Request,
|
||||
acknowledgeEventNotification [62] IMPLICIT AcknowledgeEventNotification-Request,
|
||||
getAlarmSummary [63] IMPLICIT GetAlarmSummary-Request,
|
||||
getAlarmEnrollmentSummary [64] IMPLICIT GetAlarmEnrollmentSummary-Request,
|
||||
readJournal [65] IMPLICIT ReadJournal-Request,
|
||||
writeJournal [66] IMPLICIT WriteJournal-Request,
|
||||
initializeJournal [67] IMPLICIT InitializeJournal-Request,
|
||||
reportJournalStatus [68] IMPLICIT ReportJournalStatus-Request,
|
||||
createJournal [69] IMPLICIT CreateJournal-Request,
|
||||
deleteJournal [70] IMPLICIT DeleteJournal-Request,
|
||||
getCapabilityList [71] IMPLICIT GetCapabilityList-Request,
|
||||
fileOpen [72] IMPLICIT FileOpen-Request,
|
||||
fileRead [73] IMPLICIT FileRead-Request,
|
||||
fileClose [74] IMPLICIT FileClose-Request,
|
||||
fileRename [75] IMPLICIT FileRename-Request,
|
||||
fileDelete [76] IMPLICIT FileDelete-Request,
|
||||
fileDirectory [77] IMPLICIT FileDirectory-Request
|
||||
readJournal [65] IMPLICIT ReadJournal-Request,
|
||||
writeJournal [66] IMPLICIT WriteJournal-Request,
|
||||
initializeJournal [67] IMPLICIT InitializeJournal-Request,
|
||||
reportJournalStatus [68] IMPLICIT ReportJournalStatus-Request,
|
||||
createJournal [69] IMPLICIT CreateJournal-Request,
|
||||
deleteJournal [70] IMPLICIT DeleteJournal-Request,
|
||||
getCapabilityList [71] IMPLICIT GetCapabilityList-Request,
|
||||
fileOpen [72] IMPLICIT FileOpen-Request,
|
||||
fileRead [73] IMPLICIT FileRead-Request,
|
||||
fileClose [74] IMPLICIT FileClose-Request,
|
||||
fileRename [75] IMPLICIT FileRename-Request,
|
||||
fileDelete [76] IMPLICIT FileDelete-Request,
|
||||
fileDirectory [77] IMPLICIT FileDirectory-Request
|
||||
-- XXX this one is neither in this ASN nor in the IMPORTS
|
||||
-- additionalService [78] AdditionalService-Request
|
||||
-- additionalService [78] AdditionalService-Request
|
||||
}
|
||||
|
||||
CS-Request-Detail ::= CHOICE {
|
||||
|
@ -291,7 +308,7 @@ Unsigned32 ::= INTEGER
|
|||
ObjectName ::= CHOICE
|
||||
{
|
||||
vmd-specific [0] IMPLICIT Identifier,
|
||||
domain-specific [1] IMPLICIT SEQUENCE
|
||||
domain-specific [1] IMPLICIT SEQUENCE
|
||||
{
|
||||
domainId Identifier,
|
||||
itemId Identifier
|
||||
|
@ -302,7 +319,7 @@ ObjectName ::= CHOICE
|
|||
|
||||
ApplicationReference ::= SEQUENCE
|
||||
{
|
||||
ap-title [0] AP-title OPTIONAL,
|
||||
ap-title [0] AP-title OPTIONAL,
|
||||
ap-invocation-id [1] AP-invocation-identifier OPTIONAL,
|
||||
ae-qualifier [2] AE-qualifier OPTIONAL,
|
||||
ae-invocation-id [3] AE-invocation-identifier OPTIONAL
|
||||
|
@ -2295,7 +2312,5 @@ FileAttributes ::= SEQUENCE {
|
|||
lastModified [1] IMPLICIT GeneralizedTime OPTIONAL
|
||||
}
|
||||
|
||||
|
||||
|
||||
END
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ MMSpdu
|
|||
#.NO_EMIT
|
||||
|
||||
#.TYPE_RENAME
|
||||
ObjectName/domain-specific/itemId ObjectName_domain_specific_itemid
|
||||
|
||||
#.TYPE_ATTR
|
||||
TimeOfDay TYPE = FT_STRING DISPLAY = BASE_NONE
|
||||
|
@ -43,12 +44,13 @@ GetDomainAttributes-Response/state getDomainAttributes-Response
|
|||
GetProgramInvocationAttributes-Response/state getProgramInvocationAttributes-Response_state
|
||||
ReportSemaphoreEntryStatus-Request/state reportSemaphoreEntryStatus-Request_state
|
||||
AlterEventEnrollment-Response/currentState/state alterEventEnrollment-Response_currentState_state
|
||||
ObjectName/domain-specific/itemId objectName-domain-specific-itemId
|
||||
|
||||
#.FIELD_ATTR
|
||||
ConfirmedServiceRequest/deleteEventCondition ABBREV=confirmedServiceRequest.deleteEventCondition
|
||||
ConfirmedServiceResponse/deleteEventCondition ABBREV=confirmedServiceResponse.deleteEventCondition
|
||||
ConfirmedServiceRequest/deleteEventAction ABBREV=confirmedServiceRequest.deleteEventAction
|
||||
ConfirmedServiceResponse/deleteEventAction ABBREV=confirmedServiceRequest.deleteEventAction
|
||||
ConfirmedServiceResponse/deleteEventAction ABBREV=confirmedServiceRequest.deleteEventAction
|
||||
ConfirmedServiceRequest/deleteEventEnrollment ABBREV=confirmedServiceRequest.deleteEventEnrollment
|
||||
ConfirmedServiceResponse/deleteEventEnrollment ABBREV=confirmedServiceResponse.deleteEventEnrollment
|
||||
TypeSpecification/bit-string ABBREV=typeSpecification_bit-string
|
||||
|
@ -71,131 +73,453 @@ AlterEventEnrollment-Response/currentState/state ABBREV=alterEventEnrollment-
|
|||
|
||||
|
||||
#.FN_BODY ApplicationReference/ap-title
|
||||
offset=dissect_acse_AP_title(FALSE, tvb, offset, actx, tree, hf_mms_ap_title);
|
||||
offset=dissect_acse_AP_title(FALSE, tvb, offset, actx, tree, hf_mms_ap_title);
|
||||
|
||||
#.FN_BODY ApplicationReference/ap-invocation-id
|
||||
offset=dissect_acse_AP_invocation_identifier(FALSE, tvb, offset, actx, tree, hf_mms_ap_invocation_id);
|
||||
offset=dissect_acse_AP_invocation_identifier(FALSE, tvb, offset, actx, tree, hf_mms_ap_invocation_id);
|
||||
|
||||
#.FN_BODY ApplicationReference/ae-qualifier
|
||||
offset=dissect_acse_AE_qualifier(FALSE, tvb, offset, actx, tree, hf_mms_ae_qualifier);
|
||||
offset=dissect_acse_AE_qualifier(FALSE, tvb, offset, actx, tree, hf_mms_ae_qualifier);
|
||||
|
||||
#.FN_BODY ApplicationReference/ae-invocation-id
|
||||
offset=dissect_acse_AE_invocation_identifier(FALSE, tvb, offset, actx, tree, hf_mms_ae_invocation_id);
|
||||
offset=dissect_acse_AE_invocation_identifier(FALSE, tvb, offset, actx, tree, hf_mms_ae_invocation_id);
|
||||
|
||||
#.FN_BODY MMSpdu VAL_PTR=&branch_taken
|
||||
gint branch_taken;
|
||||
int branch_taken;
|
||||
gint8 ber_class;
|
||||
bool pc;
|
||||
gint32 tag;
|
||||
|
||||
get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
mms_priv->mms_pdu_type = tag;
|
||||
|
||||
|
||||
%(DEFAULT_BODY)s
|
||||
|
||||
if( (branch_taken!=-1) && mms_MMSpdu_vals[branch_taken].strptr ){
|
||||
if (mms_has_private_data(actx))
|
||||
col_append_fstr(actx->pinfo->cinfo, COL_INFO, "%%s%%s%%s",
|
||||
private_data_get_preCinfo(actx), mms_MMSpdu_vals[branch_taken].strptr, private_data_get_moreCinfo(actx));
|
||||
else
|
||||
col_append_fstr(actx->pinfo->cinfo, COL_INFO, "%%s",
|
||||
mms_MMSpdu_vals[branch_taken].strptr);
|
||||
}
|
||||
if( (branch_taken!=-1) && mms_MMSpdu_vals[branch_taken].strptr ){
|
||||
if (mms_has_private_data(actx)){
|
||||
col_append_fstr(actx->pinfo->cinfo, COL_INFO, "%%s%%s%%s",
|
||||
private_data_get_preCinfo(actx), mms_MMSpdu_vals[branch_taken].strptr, private_data_get_moreCinfo(actx));
|
||||
}else{
|
||||
col_append_fstr(actx->pinfo->cinfo, COL_INFO, "%%s",
|
||||
mms_MMSpdu_vals[branch_taken].strptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#.FN_BODY TimeOfDay
|
||||
|
||||
guint32 len;
|
||||
guint32 milliseconds;
|
||||
guint16 days;
|
||||
gchar * ptime;
|
||||
nstime_t ts;
|
||||
uint32_t len;
|
||||
uint32_t milliseconds;
|
||||
uint16_t days;
|
||||
gchar * ptime;
|
||||
nstime_t ts;
|
||||
|
||||
len = tvb_reported_length_remaining(tvb, offset);
|
||||
len = tvb_reported_length_remaining(tvb, offset);
|
||||
|
||||
if(len == 4)
|
||||
{
|
||||
milliseconds = tvb_get_ntohl(tvb, offset);
|
||||
ptime = signed_time_msecs_to_str(actx->pinfo->pool, milliseconds);
|
||||
if(len == 4)
|
||||
{
|
||||
milliseconds = tvb_get_ntohl(tvb, offset);
|
||||
ptime = signed_time_msecs_to_str(actx->pinfo->pool, milliseconds);
|
||||
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, ptime);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, ptime);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
if(len == 6)
|
||||
{
|
||||
milliseconds = tvb_get_ntohl(tvb, offset);
|
||||
days = tvb_get_ntohs(tvb, offset+4);
|
||||
if(len == 6)
|
||||
{
|
||||
milliseconds = tvb_get_ntohl(tvb, offset);
|
||||
days = tvb_get_ntohs(tvb, offset+4);
|
||||
|
||||
/* 5113 days between 01-01-1970 and 01-01-1984 */
|
||||
/* 86400 seconds in one day */
|
||||
/* 5113 days between 01-01-1970 and 01-01-1984 */
|
||||
/* 86400 seconds in one day */
|
||||
|
||||
ts.secs = (days + 5113) * 86400 + milliseconds / 1000;
|
||||
ts.nsecs = (milliseconds %% 1000) * 1000000U;
|
||||
ts.secs = (days + 5113) * 86400 + milliseconds / 1000;
|
||||
ts.nsecs = (milliseconds %% 1000) * 1000000U;
|
||||
|
||||
ptime = abs_time_to_str(actx->pinfo->pool, &ts, ABSOLUTE_TIME_UTC, TRUE);
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, ptime);
|
||||
}
|
||||
ptime = abs_time_to_str(actx->pinfo->pool, &ts, ABSOLUTE_TIME_UTC, TRUE);
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, ptime);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
proto_tree_add_expert_format(tree, actx->pinfo, &ei_mms_mal_timeofday_encoding,
|
||||
tvb, offset, len, "BER Error: malformed TimeOfDay encoding, length must be 4 or 6 bytes");
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, "????");
|
||||
}
|
||||
proto_tree_add_expert_format(tree, actx->pinfo, &ei_mms_mal_timeofday_encoding,
|
||||
tvb, offset, len, "BER Error: malformed TimeOfDay encoding, length must be 4 or 6 bytes");
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, "????");
|
||||
}
|
||||
|
||||
#.FN_BODY UtcTime
|
||||
|
||||
guint32 len;
|
||||
guint32 seconds;
|
||||
guint32 fraction;
|
||||
guint32 nanoseconds;
|
||||
nstime_t ts;
|
||||
gchar * ptime;
|
||||
uint32_t len;
|
||||
uint32_t seconds;
|
||||
uint32_t fraction;
|
||||
uint32_t nanoseconds;
|
||||
nstime_t ts;
|
||||
gchar * ptime;
|
||||
|
||||
len = tvb_reported_length_remaining(tvb, offset);
|
||||
static int * const TimeQuality_bits[] = {
|
||||
&hf_mms_iec61850_timequality80,
|
||||
&hf_mms_iec61850_timequality40,
|
||||
&hf_mms_iec61850_timequality20,
|
||||
&hf_mms_iec61850_timequality1F,
|
||||
NULL
|
||||
};
|
||||
len = tvb_reported_length_remaining(tvb, offset);
|
||||
|
||||
if(len != 8)
|
||||
{
|
||||
proto_tree_add_expert_format(tree, actx->pinfo, &ei_mms_mal_utctime_encoding,
|
||||
tvb, offset, len, "BER Error: malformed IEC61850 UTCTime encoding, length must be 8 bytes");
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, "????");
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
if(len != 8)
|
||||
{
|
||||
/* The octet format shall be (using ASN.1 bstring notation):
|
||||
* ‘ssssssssssssssssssssssssssssssssffffffffffffffffffffffffqqqqqqqq’B
|
||||
* q stands for TimeQuality, i.e. reserved to represent TimeQuality based upon the referencing standard.
|
||||
*/
|
||||
proto_tree_add_expert_format(tree, actx->pinfo, &ei_mms_mal_utctime_encoding,
|
||||
tvb, offset, len, "BER Error: malformed IEC61850 UTCTime encoding, length must be 8 bytes");
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, "????");
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
seconds = tvb_get_ntohl(tvb, offset);
|
||||
fraction = tvb_get_ntoh24(tvb, offset+4) * 0x100; /* Only 3 bytes are recommended */
|
||||
nanoseconds = (guint32)( ((guint64)fraction * G_GUINT64_CONSTANT(1000000000)) / G_GUINT64_CONSTANT(0x100000000) ) ;
|
||||
seconds = tvb_get_ntohl(tvb, offset);
|
||||
fraction = tvb_get_ntoh24(tvb, offset+4) * 0x100; /* Only 3 bytes are recommended */
|
||||
nanoseconds = (uint32_t )( ((guint64)fraction * G_GUINT64_CONSTANT(1000000000)) / G_GUINT64_CONSTANT(0x100000000) ) ;
|
||||
|
||||
ts.secs = seconds;
|
||||
ts.nsecs = nanoseconds;
|
||||
ts.secs = seconds;
|
||||
ts.nsecs = nanoseconds;
|
||||
|
||||
ptime = abs_time_to_str(actx->pinfo->pool, &ts, ABSOLUTE_TIME_UTC, TRUE);
|
||||
ptime = abs_time_to_str(actx->pinfo->pool, &ts, ABSOLUTE_TIME_UTC, TRUE);
|
||||
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, ptime);
|
||||
}
|
||||
if(hf_index > 0)
|
||||
{
|
||||
proto_tree_add_string(tree, hf_index, tvb, offset, len, ptime);
|
||||
proto_tree_add_bitmask_list(tree, tvb, offset+7, 1, TimeQuality_bits, ENC_BIG_ENDIAN);
|
||||
}
|
||||
|
||||
|
||||
#.FN_BODY Unsigned32 VAL_PTR=&val
|
||||
guint32 val;
|
||||
uint32_t val;
|
||||
conversation_t *conversation;
|
||||
mms_conv_info_t *mms_info;
|
||||
mms_transaction_t *mms_trans;
|
||||
|
||||
%(DEFAULT_BODY)s
|
||||
if (hf_index == hf_mms_invokeID)
|
||||
private_data_add_preCinfo(actx, val);
|
||||
if (hf_index == hf_mms_invokeID){
|
||||
mms_actx_private_data_t* mms_priv = (mms_actx_private_data_t*)actx->private_data;
|
||||
mms_priv->invokeid=val;
|
||||
private_data_add_preCinfo(actx, val);
|
||||
conversation = find_or_create_conversation(actx->pinfo);
|
||||
|
||||
mms_info = (mms_conv_info_t *)conversation_get_proto_data(conversation, proto_mms);
|
||||
if (!mms_info) {
|
||||
/*
|
||||
* No. Attach that information to the conversation, and add
|
||||
* it to the list of information structures.
|
||||
*/
|
||||
mms_info = wmem_new(wmem_file_scope(), mms_conv_info_t);
|
||||
mms_info->pdus=wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
|
||||
|
||||
conversation_add_proto_data(conversation, proto_mms, mms_info);
|
||||
}
|
||||
/* Request or response? */
|
||||
bool is_request;
|
||||
|
||||
switch(mms_priv->mms_pdu_type){
|
||||
case 0:
|
||||
/* Confirmed-RequestPDU */
|
||||
is_request = true;
|
||||
break;
|
||||
case 1:
|
||||
/* confirmed-ResponsePDU */
|
||||
is_request = false;
|
||||
break;
|
||||
case 2:
|
||||
/* Confirmed-ErrorPDU */
|
||||
is_request = false;
|
||||
break;
|
||||
default:
|
||||
is_request = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!PINFO_FD_VISITED(actx->pinfo)) {
|
||||
if (is_request==true) {
|
||||
/* This is a request */
|
||||
mms_trans=wmem_new(wmem_file_scope(), mms_transaction_t);
|
||||
mms_trans->req_frame = actx->pinfo->num;
|
||||
mms_trans->rep_frame = 0;
|
||||
mms_trans->req_time = actx->pinfo->fd->abs_ts;
|
||||
wmem_map_insert(mms_info->pdus, GUINT_TO_POINTER(mms_priv->invokeid), (void *)mms_trans);
|
||||
} else {
|
||||
mms_trans=(mms_transaction_t *)wmem_map_lookup(mms_info->pdus, GUINT_TO_POINTER(mms_priv->invokeid));
|
||||
if (mms_trans) {
|
||||
mms_trans->rep_frame = actx->pinfo->num;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mms_trans=(mms_transaction_t *)wmem_map_lookup(mms_info->pdus, GUINT_TO_POINTER(mms_priv->invokeid));
|
||||
}
|
||||
if (!mms_trans) {
|
||||
/* create a "fake" mms_trans structure */
|
||||
mms_trans=wmem_new(actx->pinfo->pool, mms_transaction_t);
|
||||
mms_trans->req_frame = 0;
|
||||
mms_trans->rep_frame = 0;
|
||||
mms_trans->req_time = actx->pinfo->fd->abs_ts;
|
||||
}
|
||||
mms_priv->mms_trans = mms_trans;
|
||||
|
||||
/* print state tracking in the tree */
|
||||
if (is_request) {
|
||||
/* This is a request */
|
||||
if (mms_trans->rep_frame) {
|
||||
proto_item *it;
|
||||
|
||||
it = proto_tree_add_uint(actx->subtree.top_tree, hf_mms_response_in, tvb, 0, 0, mms_trans->rep_frame);
|
||||
proto_item_set_generated(it);
|
||||
}
|
||||
} else {
|
||||
/* This is a reply */
|
||||
if (mms_trans->req_frame) {
|
||||
proto_item *it;
|
||||
nstime_t ns;
|
||||
|
||||
it = proto_tree_add_uint(actx->subtree.top_tree, hf_mms_response_to, tvb, 0, 0, mms_trans->req_frame);
|
||||
proto_item_set_generated(it);
|
||||
|
||||
nstime_delta(&ns, &actx->pinfo->fd->abs_ts, &mms_trans->req_time);
|
||||
it = proto_tree_add_time(actx->subtree.top_tree, hf_mms_response_time, tvb, 0, 0, &ns);
|
||||
proto_item_set_generated(it);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#.FN_BODY FloatingPoint
|
||||
%(DEFAULT_BODY)s
|
||||
private_data_add_moreCinfo_float(actx, tvb);
|
||||
private_data_add_moreCinfo_float(actx, tvb);
|
||||
|
||||
#.FN_BODY Identifier VAL_PTR= ¶meter_tvb
|
||||
tvbuff_t *parameter_tvb;
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
|
||||
#.FN_BODY Identifier
|
||||
int offset_id = offset;
|
||||
%(DEFAULT_BODY)s
|
||||
if ((hf_index == hf_mms_domainId) || (hf_index == hf_mms_itemId)) {
|
||||
if (tvb_get_guint8(tvb, offset_id) == 0x1a)
|
||||
private_data_add_moreCinfo_id(actx,tvb);
|
||||
}
|
||||
if (hf_index == hf_mms_domainId) {
|
||||
private_data_add_moreCinfo_id(actx,tvb);
|
||||
}
|
||||
if (hf_index == hf_mms_objectName_domain_specific_itemId) {
|
||||
private_data_add_moreCinfo_id(actx,tvb);
|
||||
const char *itemid_str = tvb_get_string_enc(actx->pinfo->pool, tvb, 0, tvb_reported_length(tvb), ENC_ASCII|ENC_NA);
|
||||
if(g_str_has_suffix(itemid_str,"$ctlModel")){
|
||||
mms_priv->mms_trans->itemid = IEC61850_ITEM_ID_CTLMODEL;
|
||||
}else if(g_str_has_suffix(itemid_str,"$q")){
|
||||
mms_priv->mms_trans->itemid = IEC61850_ITEM_ID_Q;
|
||||
}
|
||||
}
|
||||
|
||||
if (hf_index == hf_mms_vmd_specific){
|
||||
const char *vmd_specific_str = tvb_get_string_enc(actx->pinfo->pool, tvb, 0, tvb_reported_length(tvb), ENC_ASCII|ENC_NA);
|
||||
if (strcmp(vmd_specific_str, "RPT") == 0) {
|
||||
mms_priv->vmd_specific = IEC61850_8_1_RPT;
|
||||
}
|
||||
}
|
||||
|
||||
#.FN_BODY InformationReport/listOfAccessResult
|
||||
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
mms_priv->listOfAccessResult_cnt = 0;
|
||||
|
||||
%(DEFAULT_BODY)s
|
||||
|
||||
#.FN_BODY AccessResult
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
|
||||
/* If listOfAccessResult_cnt > 2 we are into the optional data.
|
||||
* if data is not present increase count.
|
||||
*/
|
||||
bool present;
|
||||
do {
|
||||
mms_priv->listOfAccessResult_cnt+=1;
|
||||
present = TRUE;
|
||||
switch(mms_priv->listOfAccessResult_cnt){
|
||||
case 1: /*RptID*/
|
||||
break;
|
||||
case 2: /* Reported OptFlds */
|
||||
break;
|
||||
case 3: /* SeqNum Shall be present if OptFlds.sequence-number is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x4000) != 0x4000){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
case 4: /*TimeOfEntry Shall be present if OptFlds.report-time-stamp is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x2000) != 0x2000){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
case 5: /*DatSet Shall be present if OptFlds.data-set-name is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x0800) !=0x0800){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
case 6: /*BufOvfl Shall be present if OptFlds.buffer-overflow is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x0200) !=0x0200){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
case 7: /*EntryID Shall be present if OptFlds.entryID is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x0100) !=0x0100){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
case 8: /*ConfRev Shall be present if OptFlds.conf-rev is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x0080) !=0x0080){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
case 9: /*SubSeqNum Shall be present if OptFlds.segmentation is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x0040) !=0x0040){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
case 10: /*MoreSegmentsFollow Shall be present if OptFlds.segmentation is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x0040) !=0x0040){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
case 11: /*Inclusion-bitstring Shall be present */
|
||||
break;
|
||||
case 12: /*data-reference(s) Shall be present if OptFlds.data-reference is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x0400) !=0x0400){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
case 13: /*value(s) See AccessResult for value(s) */
|
||||
break;
|
||||
case 14: /*ReasonCode(s) Shall be present if OptFlds OptFlds.reason-for-inclusion is TRUE */
|
||||
if((mms_priv->reported_optflds & 0x1000) !=0x1000){
|
||||
present = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while(!present);
|
||||
|
||||
%(DEFAULT_BODY)s
|
||||
|
||||
#.FN_BODY Data/visible-string
|
||||
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
if(mms_priv->vmd_specific == IEC61850_8_1_RPT ){
|
||||
if(mms_priv->listOfAccessResult_cnt == 1){
|
||||
/* IEC 61850-8-1 RptID */
|
||||
hf_index = hf_mms_iec61850_rptid;
|
||||
}else if(mms_priv->listOfAccessResult_cnt == 5){
|
||||
/* IEC 61850-8-1 DatSet */
|
||||
hf_index = hf_mms_iec61850_datset;
|
||||
}
|
||||
|
||||
}
|
||||
%(DEFAULT_BODY)s
|
||||
|
||||
#.FN_BODY Data/bit-string VAL_PTR= ¶meter_tvb
|
||||
|
||||
static int* const quality_field_bits_oct1[] = {
|
||||
&hf_mms_iec61850_QualityC0,
|
||||
&hf_mms_iec61850_Quality20,
|
||||
&hf_mms_iec61850_Quality10,
|
||||
&hf_mms_iec61850_Quality8,
|
||||
&hf_mms_iec61850_Quality4,
|
||||
&hf_mms_iec61850_Quality2,
|
||||
&hf_mms_iec61850_Quality1,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int* const quality_field_bits_oct2[] = {
|
||||
&hf_mms_iec61850_Quality0080,
|
||||
&hf_mms_iec61850_Quality0040,
|
||||
&hf_mms_iec61850_Quality0020,
|
||||
&hf_mms_iec61850_Quality0010,
|
||||
&hf_mms_iec61850_Quality0008,
|
||||
NULL
|
||||
};
|
||||
tvbuff_t *parameter_tvb;
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
if(mms_priv->vmd_specific == IEC61850_8_1_RPT ){
|
||||
if(mms_priv->listOfAccessResult_cnt == 2){
|
||||
/* IEC 61850-8-1 Reported OptFlds */
|
||||
return dissect_mms_ReportedOptFlds(implicit_tag, tvb, offset, actx, tree, hf_mms_iec61850_reported_optflds);
|
||||
}else{
|
||||
if(mms_priv->listOfAccessResult_cnt == 11){
|
||||
hf_index = hf_mms_iec61850_inclusion_bitstring;
|
||||
}
|
||||
}
|
||||
}else if((mms_priv->mms_trans)&&(mms_priv->mms_trans->itemid == IEC61850_ITEM_ID_Q)){
|
||||
hf_index = hf_mms_iec61850_quality_bitstring;
|
||||
}
|
||||
|
||||
%(DEFAULT_BODY)s
|
||||
|
||||
if((parameter_tvb)&&(mms_priv->mms_trans)&&(mms_priv->mms_trans->itemid == IEC61850_ITEM_ID_Q)){
|
||||
proto_tree *sub_tree;
|
||||
sub_tree = proto_item_add_subtree(actx->created_item, ett_mms_iec61850_quality_bitstring);
|
||||
proto_tree_add_bitmask_list(sub_tree, parameter_tvb, 0, 1, quality_field_bits_oct1, ENC_NA);
|
||||
proto_tree_add_bitmask_list(sub_tree, parameter_tvb, 1, 1, quality_field_bits_oct2, ENC_NA);
|
||||
}
|
||||
|
||||
#.FN_BODY ReportedOptFlds VAL_PTR= ¶meter_tvb
|
||||
tvbuff_t *parameter_tvb;
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
%(DEFAULT_BODY)s
|
||||
mms_priv->reported_optflds = tvb_get_ntohs(parameter_tvb,0);
|
||||
|
||||
#.FN_BODY Data/unsigned
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
if(mms_priv->vmd_specific == IEC61850_8_1_RPT ){
|
||||
if(mms_priv->listOfAccessResult_cnt == 3){
|
||||
/* IEC 61850-8-1 SeqNum */
|
||||
hf_index = hf_mms_iec61850_seqnum;
|
||||
}else if(mms_priv->listOfAccessResult_cnt == 8){
|
||||
/* IEC 61850-8-1 ConfRev */
|
||||
hf_index = hf_mms_iec61850_confrev;
|
||||
}
|
||||
}
|
||||
%(DEFAULT_BODY)s
|
||||
|
||||
#.FN_BODY Data/boolean
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
if(mms_priv->vmd_specific == IEC61850_8_1_RPT ){
|
||||
if(mms_priv->listOfAccessResult_cnt == 6){
|
||||
/* IEC 61850-8-1 BufOvfl */
|
||||
hf_index = hf_mms_iec61850_bufovfl;
|
||||
}
|
||||
}
|
||||
%(DEFAULT_BODY)s
|
||||
|
||||
#.FN_BODY Data/binary-time
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
if(mms_priv->vmd_specific == IEC61850_8_1_RPT ){
|
||||
if(mms_priv->listOfAccessResult_cnt == 4){
|
||||
/* IEC 61850-8-1 TimeOfEntry */
|
||||
hf_index = hf_mms_iec61850_timeofentry;
|
||||
}
|
||||
}
|
||||
%(DEFAULT_BODY)s
|
||||
|
||||
#.FN_BODY Data/integer
|
||||
mms_actx_private_data_t *mms_priv = (mms_actx_private_data_t *)actx->private_data;
|
||||
|
||||
if((mms_priv->mms_trans)&&(mms_priv->mms_trans->itemid == IEC61850_ITEM_ID_CTLMODEL)){
|
||||
hf_index = hf_mms_iec61850_ctlModel;
|
||||
}
|
||||
|
||||
%(DEFAULT_BODY)s
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <epan/asn1.h>
|
||||
#include <epan/expert.h>
|
||||
#include <epan/proto_data.h>
|
||||
#include <epan/conversation.h>
|
||||
|
||||
#include "packet-ber.h"
|
||||
#include "packet-acse.h"
|
||||
|
@ -31,10 +32,44 @@ void proto_reg_handoff_mms(void);
|
|||
/* Initialize the protocol and registered fields */
|
||||
static int proto_mms;
|
||||
|
||||
/* Converstaion */
|
||||
static int hf_mms_response_in;
|
||||
static int hf_mms_response_to;
|
||||
static int hf_mms_response_time;
|
||||
|
||||
/* IEC 61850-8-1 filters */
|
||||
static int hf_mms_iec61850_rptid;
|
||||
static int hf_mms_iec61850_reported_optflds;
|
||||
static int hf_mms_iec61850_seqnum;
|
||||
static int hf_mms_iec61850_timeofentry;
|
||||
static int hf_mms_iec61850_datset;
|
||||
static int hf_mms_iec61850_bufovfl;
|
||||
static int hf_mms_iec61850_confrev;
|
||||
static int hf_mms_iec61850_inclusion_bitstring;
|
||||
static int hf_mms_iec61850_ctlModel;
|
||||
|
||||
static int hf_mms_iec61850_QualityC0;
|
||||
static int hf_mms_iec61850_Quality20;
|
||||
static int hf_mms_iec61850_Quality10;
|
||||
static int hf_mms_iec61850_Quality8;
|
||||
static int hf_mms_iec61850_Quality4;
|
||||
static int hf_mms_iec61850_Quality2;
|
||||
static int hf_mms_iec61850_Quality1;
|
||||
static int hf_mms_iec61850_Quality0080;
|
||||
static int hf_mms_iec61850_Quality0040;
|
||||
static int hf_mms_iec61850_Quality0020;
|
||||
static int hf_mms_iec61850_Quality0010;
|
||||
static int hf_mms_iec61850_Quality0008;
|
||||
static int hf_mms_iec61850_quality_bitstring;
|
||||
static int hf_mms_iec61850_timequality80;
|
||||
static int hf_mms_iec61850_timequality40;
|
||||
static int hf_mms_iec61850_timequality20;
|
||||
static int hf_mms_iec61850_timequality1F;
|
||||
#include "packet-mms-hf.c"
|
||||
|
||||
/* Initialize the subtree pointers */
|
||||
static gint ett_mms;
|
||||
static int ett_mms;
|
||||
static int ett_mms_iec61850_quality_bitstring;
|
||||
#include "packet-mms-ett.c"
|
||||
|
||||
static expert_field ei_mms_mal_timeofday_encoding;
|
||||
|
@ -50,72 +85,164 @@ static expert_field ei_mms_zero_pdu;
|
|||
#define BUFFER_SIZE_PRE 10
|
||||
#define BUFFER_SIZE_MORE 1024
|
||||
|
||||
typedef enum _iec61850_8_1_vmd_specific {
|
||||
IEC61850_8_1_NOT_SET = 0,
|
||||
IEC61850_8_1_RPT
|
||||
} iec61850_8_1_vmd_specific;
|
||||
|
||||
typedef enum _itemid_type {
|
||||
IEC61850_ITEM_ID_NOT_SET = 0,
|
||||
IEC61850_ITEM_ID_CTLMODEL,
|
||||
IEC61850_ITEM_ID_Q
|
||||
} itemid_type;
|
||||
|
||||
typedef struct _mms_transaction_t {
|
||||
uint32_t req_frame;
|
||||
uint32_t rep_frame;
|
||||
nstime_t req_time;
|
||||
/* Rquest info*/
|
||||
itemid_type itemid; /* Numeric representation of ItemId substring */
|
||||
} mms_transaction_t;
|
||||
|
||||
typedef struct _mms_conv_info_t {
|
||||
wmem_map_t* pdus;
|
||||
} mms_conv_info_t;
|
||||
|
||||
typedef struct mms_private_data_t
|
||||
{
|
||||
char preCinfo[BUFFER_SIZE_PRE];
|
||||
char moreCinfo[BUFFER_SIZE_MORE];
|
||||
char preCinfo[BUFFER_SIZE_PRE];
|
||||
char moreCinfo[BUFFER_SIZE_MORE];
|
||||
} mms_private_data_t;
|
||||
|
||||
|
||||
typedef struct mms_actx_private_data_t
|
||||
{
|
||||
int mms_pdu_type; /* MMSpdu type taken from MMSpdu CHOISE branch_taken */
|
||||
int invokeid;
|
||||
iec61850_8_1_vmd_specific vmd_specific; /* Numeric representation of decode vmd_specific strings */
|
||||
int listOfAccessResult_cnt; /* Posision in the list, 1 count*/
|
||||
guint16 reported_optflds; /* Bitmap over included fields*/
|
||||
mms_transaction_t* mms_trans;
|
||||
} mms_actx_private_data_t;
|
||||
|
||||
|
||||
static const value_string mms_iec6150_cntmodel_vals[] = {
|
||||
{0, "status-only"},
|
||||
{1, "direct-with-normal-security"},
|
||||
{2, "sbo-with-normal-security"},
|
||||
{3, "direct-with-enhanced-security"},
|
||||
{4, "sbo-with-enhanced-security"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const value_string mms_iec6150_validity_vals[] = {
|
||||
{0, "Good"},
|
||||
{1, "Invalid"},
|
||||
{2, "Reserved"},
|
||||
{3, "Questionable"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const value_string mms_iec6150_source_vals[] = {
|
||||
{0, "Process"},
|
||||
{1, "Substituted"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const value_string mms_iec6150_timeaccuracy_vals[] = {
|
||||
{0, "0 bits accuracy"},
|
||||
{1, "1 bits accuracy"},
|
||||
{2, "2 bits accuracy"},
|
||||
{3, "3 bits accuracy"},
|
||||
{4, "4 bits accuracy"},
|
||||
{5, "5 bits accuracy"},
|
||||
{6, "6 bits accuracy"},
|
||||
{7, "7 bits accuracy"},
|
||||
{8, "8 bits accuracy"},
|
||||
{9, "9 bits accuracy"},
|
||||
{10, "10 bits accuracy"},
|
||||
{11, "11 bits accuracy"},
|
||||
{12, "12 bits accuracy"},
|
||||
{13, "13 bits accuracy"},
|
||||
{14, "14 bits accuracy"},
|
||||
{15, "15 bits accuracy"},
|
||||
{16, "16 bits accuracy"},
|
||||
{17, "17 bits accuracy"},
|
||||
{18, "18 bits accuracy"},
|
||||
{19, "19 bits accuracy"},
|
||||
{20, "20 bits accuracy"},
|
||||
{21, "21 bits accuracy"},
|
||||
{22, "22 bits accuracy"},
|
||||
{23, "23 bits accuracy"},
|
||||
{24, "24 bits accuracy"},
|
||||
{25, "25 bits accuracy"},
|
||||
{26, "26 bits accuracy"},
|
||||
{27, "27 bits accuracy"},
|
||||
{28, "28 bits accuracy"},
|
||||
{29, "29 bits accuracy"},
|
||||
{30, "Invalid"},
|
||||
{31, "Unspecified"},
|
||||
{0, NULL}
|
||||
};
|
||||
/* Helper function to get or create the private data struct */
|
||||
static
|
||||
mms_private_data_t* mms_get_private_data(asn1_ctx_t *actx)
|
||||
mms_private_data_t* mms_get_private_data(asn1_ctx_t* actx)
|
||||
{
|
||||
packet_info *pinfo = actx->pinfo;
|
||||
mms_private_data_t *private_data = (mms_private_data_t *)p_get_proto_data(pinfo->pool, pinfo, proto_mms, pinfo->curr_layer_num);
|
||||
if(private_data != NULL )
|
||||
return private_data;
|
||||
else {
|
||||
private_data = wmem_new0(pinfo->pool, mms_private_data_t);
|
||||
p_add_proto_data(pinfo->pool, pinfo, proto_mms, pinfo->curr_layer_num, private_data);
|
||||
return private_data;
|
||||
}
|
||||
packet_info* pinfo = actx->pinfo;
|
||||
mms_private_data_t* private_data = (mms_private_data_t*)p_get_proto_data(pinfo->pool, pinfo, proto_mms, pinfo->curr_layer_num);
|
||||
if (private_data != NULL) {
|
||||
return private_data;
|
||||
} else {
|
||||
private_data = wmem_new0(pinfo->pool, mms_private_data_t);
|
||||
p_add_proto_data(pinfo->pool, pinfo, proto_mms, pinfo->curr_layer_num, private_data);
|
||||
return private_data;
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function to test presence of private data struct */
|
||||
static gboolean
|
||||
mms_has_private_data(asn1_ctx_t *actx)
|
||||
mms_has_private_data(asn1_ctx_t* actx)
|
||||
{
|
||||
packet_info *pinfo = actx->pinfo;
|
||||
return (p_get_proto_data(pinfo->pool, pinfo, proto_mms, pinfo->curr_layer_num) != NULL);
|
||||
packet_info* pinfo = actx->pinfo;
|
||||
return (p_get_proto_data(pinfo->pool, pinfo, proto_mms, pinfo->curr_layer_num) != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
private_data_add_preCinfo(asn1_ctx_t *actx, guint32 val)
|
||||
private_data_add_preCinfo(asn1_ctx_t* actx, guint32 val)
|
||||
{
|
||||
mms_private_data_t *private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
snprintf(private_data->preCinfo, BUFFER_SIZE_PRE, "%02d ", val);
|
||||
mms_private_data_t* private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
snprintf(private_data->preCinfo, BUFFER_SIZE_PRE, "%02d ", val);
|
||||
}
|
||||
|
||||
static char*
|
||||
private_data_get_preCinfo(asn1_ctx_t *actx)
|
||||
private_data_get_preCinfo(asn1_ctx_t* actx)
|
||||
{
|
||||
mms_private_data_t *private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
return private_data->preCinfo;
|
||||
mms_private_data_t* private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
return private_data->preCinfo;
|
||||
}
|
||||
|
||||
static void
|
||||
private_data_add_moreCinfo_id(asn1_ctx_t *actx, tvbuff_t *tvb)
|
||||
private_data_add_moreCinfo_id(asn1_ctx_t* actx, tvbuff_t* tvb)
|
||||
{
|
||||
mms_private_data_t *private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
(void) g_strlcat(private_data->moreCinfo, " ", BUFFER_SIZE_MORE);
|
||||
(void) g_strlcat(private_data->moreCinfo, tvb_get_string_enc(actx->pinfo->pool,
|
||||
tvb, 2, tvb_get_guint8(tvb, 1), ENC_STRING), BUFFER_SIZE_MORE);
|
||||
mms_private_data_t* private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
(void)g_strlcat(private_data->moreCinfo, " ", BUFFER_SIZE_MORE);
|
||||
(void)g_strlcat(private_data->moreCinfo, tvb_get_string_enc(actx->pinfo->pool,
|
||||
tvb, 2, tvb_get_guint8(tvb, 1), ENC_STRING), BUFFER_SIZE_MORE);
|
||||
}
|
||||
|
||||
static void
|
||||
private_data_add_moreCinfo_float(asn1_ctx_t *actx, tvbuff_t *tvb)
|
||||
private_data_add_moreCinfo_float(asn1_ctx_t* actx, tvbuff_t* tvb)
|
||||
{
|
||||
mms_private_data_t *private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
snprintf(private_data->moreCinfo, BUFFER_SIZE_MORE,
|
||||
" %f", tvb_get_ieee_float(tvb, 1, ENC_BIG_ENDIAN));
|
||||
mms_private_data_t* private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
snprintf(private_data->moreCinfo, BUFFER_SIZE_MORE,
|
||||
" %f", tvb_get_ieee_float(tvb, 1, ENC_BIG_ENDIAN));
|
||||
}
|
||||
|
||||
static char*
|
||||
private_data_get_moreCinfo(asn1_ctx_t *actx)
|
||||
private_data_get_moreCinfo(asn1_ctx_t* actx)
|
||||
{
|
||||
mms_private_data_t *private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
return private_data->moreCinfo;
|
||||
mms_private_data_t* private_data = (mms_private_data_t*)mms_get_private_data(actx);
|
||||
return private_data->moreCinfo;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -127,122 +254,244 @@ private_data_get_moreCinfo(asn1_ctx_t *actx)
|
|||
* Dissect MMS PDUs inside a PPDU.
|
||||
*/
|
||||
static int
|
||||
dissect_mms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
|
||||
dissect_mms(tvbuff_t* tvb, packet_info* pinfo, proto_tree* parent_tree, void* data _U_)
|
||||
{
|
||||
int offset = 0;
|
||||
int old_offset;
|
||||
proto_item *item=NULL;
|
||||
proto_tree *tree=NULL;
|
||||
asn1_ctx_t asn1_ctx;
|
||||
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
|
||||
int offset = 0;
|
||||
int old_offset;
|
||||
proto_item* item = NULL;
|
||||
proto_tree* tree = NULL;
|
||||
asn1_ctx_t asn1_ctx;
|
||||
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
|
||||
|
||||
if(parent_tree){
|
||||
item = proto_tree_add_item(parent_tree, proto_mms, tvb, 0, -1, ENC_NA);
|
||||
tree = proto_item_add_subtree(item, ett_mms);
|
||||
}
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "MMS");
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
if (parent_tree) {
|
||||
item = proto_tree_add_item(parent_tree, proto_mms, tvb, 0, -1, ENC_NA);
|
||||
tree = proto_item_add_subtree(item, ett_mms);
|
||||
asn1_ctx.subtree.top_tree = parent_tree;
|
||||
}
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "MMS");
|
||||
col_clear(pinfo->cinfo, COL_INFO);
|
||||
|
||||
while (tvb_reported_length_remaining(tvb, offset) > 0){
|
||||
old_offset=offset;
|
||||
offset=dissect_mms_MMSpdu(FALSE, tvb, offset, &asn1_ctx , tree, -1);
|
||||
if(offset == old_offset){
|
||||
proto_tree_add_expert(tree, pinfo, &ei_mms_zero_pdu, tvb, offset, -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tvb_captured_length(tvb);
|
||||
while (tvb_reported_length_remaining(tvb, offset) > 0) {
|
||||
old_offset = offset;
|
||||
asn1_ctx.private_data = (void*)wmem_new0(pinfo->pool, mms_actx_private_data_t);
|
||||
offset = dissect_mms_MMSpdu(FALSE, tvb, offset, &asn1_ctx, tree, -1);
|
||||
wmem_free(pinfo->pool, asn1_ctx.private_data);
|
||||
if (offset == old_offset) {
|
||||
proto_tree_add_expert(tree, pinfo, &ei_mms_zero_pdu, tvb, offset, -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tvb_captured_length(tvb);
|
||||
}
|
||||
|
||||
|
||||
/*--- proto_register_mms -------------------------------------------*/
|
||||
void proto_register_mms(void) {
|
||||
|
||||
/* List of fields */
|
||||
static hf_register_info hf[] =
|
||||
{
|
||||
/* List of fields */
|
||||
static hf_register_info hf[] =
|
||||
{
|
||||
{ &hf_mms_response_in,
|
||||
{ "Response In", "mms.response_in",
|
||||
FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
|
||||
"The response to this mms request is in this frame", HFILL }
|
||||
},
|
||||
{ &hf_mms_response_to,
|
||||
{ "Request In", "mms.response_to",
|
||||
FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
|
||||
"This is a response to the mms request in this frame", HFILL }
|
||||
},
|
||||
{ &hf_mms_response_time,
|
||||
{ "Response Time", "mms.response_time",
|
||||
FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
|
||||
"The time between the Call and the Reply", HFILL }
|
||||
},
|
||||
{ &hf_mms_iec61850_rptid,
|
||||
{ "RptID", "mms.iec61850.rptid",
|
||||
FT_STRING, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_reported_optflds,
|
||||
{ "Reported OptFlds", "mms.iec61850.reported_optfld",
|
||||
FT_BYTES, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_seqnum,
|
||||
{ "SeqNum", "mms.iec61850.seqnum",
|
||||
FT_INT32, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_timeofentry,
|
||||
{ "TimeOfEntry", "mms.iec61850.timeofentry",
|
||||
FT_STRING, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_datset,
|
||||
{ "DatSet", "mms.iec61850.datset",
|
||||
FT_STRING, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_bufovfl,
|
||||
{ "BufOvfl", "mms.iec61850.bufovfl",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_confrev,
|
||||
{ "ConfRev", "mms.iec61850.confrev",
|
||||
FT_INT32, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_inclusion_bitstring,
|
||||
{ "Inclusion-bitstring", "mms.iec61850.inclusion_bitstring",
|
||||
FT_BYTES, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_ctlModel,
|
||||
{ "ctlModel", "mms.iec61850.ctlmodel",
|
||||
FT_UINT8, BASE_DEC, VALS(mms_iec6150_cntmodel_vals), 0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_QualityC0,
|
||||
{ "Validity", "mms.iec61850.validity",
|
||||
FT_UINT8, BASE_HEX, VALS(mms_iec6150_validity_vals), 0xC0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality20,
|
||||
{ "Overflow", "mms.iec61850.overflow",
|
||||
FT_BOOLEAN, 8, NULL, 0x20,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality10,
|
||||
{ "OutofRange", "mms.iec61850.outofrange",
|
||||
FT_BOOLEAN, 8, NULL, 0x10,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality8,
|
||||
{ "BadReference", "mms.iec61850.badreference",
|
||||
FT_BOOLEAN, 8, NULL, 0x08,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality4,
|
||||
{ "Oscillatory", "mms.iec61850.oscillatory",
|
||||
FT_BOOLEAN, 8, NULL, 0x04,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality2,
|
||||
{ "Failure", "mms.iec61850.failure",
|
||||
FT_BOOLEAN, 8, NULL, 0x02,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality1,
|
||||
{ "OldData", "mms.iec61850.oldData",
|
||||
FT_BOOLEAN, 8, NULL, 0x01,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality0080,
|
||||
{ "Inconsistent", "mms.iec61850.inconsistent",
|
||||
FT_BOOLEAN, 8, NULL, 0x80,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality0040,
|
||||
{ "Inaccurate", "mms.iec61850.inaccurate",
|
||||
FT_BOOLEAN, 8, NULL, 0x40,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality0020,
|
||||
{ "Source", "mms.iec61850.source",
|
||||
FT_UINT8, BASE_HEX, VALS(mms_iec6150_source_vals), 0x20,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality0010,
|
||||
{ "Test", "mms.iec61850.test",
|
||||
FT_BOOLEAN, 8, NULL, 0x10,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_Quality0008,
|
||||
{ "OperatorBlocked", "mms.iec61850.operatorblocked",
|
||||
FT_BOOLEAN, 8, NULL, 0x08,
|
||||
NULL, HFILL }},
|
||||
{ &hf_mms_iec61850_quality_bitstring,
|
||||
{ "Quality", "mms.iec61850.quality_bitstring",
|
||||
FT_BYTES, BASE_NONE, NULL, 0,
|
||||
NULL, HFILL } },
|
||||
{ &hf_mms_iec61850_timequality80,
|
||||
{ "Leap Second Known", "mms.iec61850.leapsecondknown",
|
||||
FT_BOOLEAN, 8, NULL, 0x80,
|
||||
NULL, HFILL } },
|
||||
{ &hf_mms_iec61850_timequality40,
|
||||
{ "ClockFailure", "mms.iec61850.clockfailure",
|
||||
FT_BOOLEAN, 8, NULL, 0x40,
|
||||
NULL, HFILL } },
|
||||
{ &hf_mms_iec61850_timequality20,
|
||||
{ "Clock not synchronized", "mms.iec61850.clocknotsynchronized",
|
||||
FT_BOOLEAN, 8, NULL, 0x20,
|
||||
NULL, HFILL } },
|
||||
{ &hf_mms_iec61850_timequality1F,
|
||||
{ "Time Accuracy", "mms.iec61850.timeaccuracy",
|
||||
FT_UINT8, BASE_HEX, VALS(mms_iec6150_timeaccuracy_vals), 0x1F,
|
||||
NULL, HFILL } },
|
||||
#include "packet-mms-hfarr.c"
|
||||
};
|
||||
};
|
||||
|
||||
/* List of subtrees */
|
||||
static gint *ett[] = {
|
||||
&ett_mms,
|
||||
/* List of subtrees */
|
||||
static gint* ett[] = {
|
||||
&ett_mms,
|
||||
#include "packet-mms-ettarr.c"
|
||||
};
|
||||
};
|
||||
|
||||
static ei_register_info ei[] = {
|
||||
{ &ei_mms_mal_timeofday_encoding, { "mms.malformed.timeofday_encoding", PI_MALFORMED, PI_WARN, "BER Error: malformed TimeOfDay encoding", EXPFILL }},
|
||||
{ &ei_mms_mal_utctime_encoding, { "mms.malformed.utctime", PI_MALFORMED, PI_WARN, "BER Error: malformed IEC61850 UTCTime encoding", EXPFILL }},
|
||||
{ &ei_mms_zero_pdu, { "mms.zero_pdu", PI_PROTOCOL, PI_ERROR, "Internal error, zero-byte MMS PDU", EXPFILL }},
|
||||
};
|
||||
static ei_register_info ei[] = {
|
||||
{ &ei_mms_mal_timeofday_encoding, { "mms.malformed.timeofday_encoding", PI_MALFORMED, PI_WARN, "BER Error: malformed TimeOfDay encoding", EXPFILL }},
|
||||
{ &ei_mms_mal_utctime_encoding, { "mms.malformed.utctime", PI_MALFORMED, PI_WARN, "BER Error: malformed IEC61850 UTCTime encoding", EXPFILL }},
|
||||
{ &ei_mms_zero_pdu, { "mms.zero_pdu", PI_PROTOCOL, PI_ERROR, "Internal error, zero-byte MMS PDU", EXPFILL }},
|
||||
};
|
||||
|
||||
expert_module_t* expert_mms;
|
||||
expert_module_t* expert_mms;
|
||||
|
||||
/* Register protocol */
|
||||
proto_mms = proto_register_protocol(PNAME, PSNAME, PFNAME);
|
||||
register_dissector("mms", dissect_mms, proto_mms);
|
||||
/* Register fields and subtrees */
|
||||
proto_register_field_array(proto_mms, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
expert_mms = expert_register_protocol(proto_mms);
|
||||
expert_register_field_array(expert_mms, ei, array_length(ei));
|
||||
/* Register protocol */
|
||||
proto_mms = proto_register_protocol(PNAME, PSNAME, PFNAME);
|
||||
register_dissector("mms", dissect_mms, proto_mms);
|
||||
/* Register fields and subtrees */
|
||||
proto_register_field_array(proto_mms, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
expert_mms = expert_register_protocol(proto_mms);
|
||||
expert_register_field_array(expert_mms, ei, array_length(ei));
|
||||
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
dissect_mms_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
|
||||
dissect_mms_heur(tvbuff_t* tvb, packet_info* pinfo, proto_tree* parent_tree, void* data _U_)
|
||||
{
|
||||
/* must check that this really is an mms packet */
|
||||
int offset = 0;
|
||||
guint32 length = 0 ;
|
||||
guint32 oct;
|
||||
gint idx = 0 ;
|
||||
/* must check that this really is an mms packet */
|
||||
int offset = 0;
|
||||
guint32 length = 0;
|
||||
guint32 oct;
|
||||
gint idx = 0;
|
||||
|
||||
gint8 tmp_class;
|
||||
bool tmp_pc;
|
||||
gint32 tmp_tag;
|
||||
gint8 tmp_class;
|
||||
bool tmp_pc;
|
||||
gint32 tmp_tag;
|
||||
|
||||
/* first, check do we have at least 2 bytes (pdu) */
|
||||
if (!tvb_bytes_exist(tvb, 0, 2))
|
||||
return FALSE; /* no */
|
||||
/* first, check do we have at least 2 bytes (pdu) */
|
||||
if (!tvb_bytes_exist(tvb, 0, 2))
|
||||
return FALSE; /* no */
|
||||
|
||||
/* can we recognize MMS PDU ? Return FALSE if not */
|
||||
/* get MMS PDU type */
|
||||
offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
|
||||
/* can we recognize MMS PDU ? Return FALSE if not */
|
||||
/* get MMS PDU type */
|
||||
offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
|
||||
|
||||
/* check MMS type */
|
||||
/* check MMS type */
|
||||
|
||||
/* Class should be constructed */
|
||||
if (tmp_class!=BER_CLASS_CON)
|
||||
return FALSE;
|
||||
/* Class should be constructed */
|
||||
if (tmp_class != BER_CLASS_CON)
|
||||
return FALSE;
|
||||
|
||||
/* see if the tag is a valid MMS PDU */
|
||||
try_val_to_str_idx(tmp_tag, mms_MMSpdu_vals, &idx);
|
||||
if (idx == -1) {
|
||||
return FALSE; /* no, it isn't an MMS PDU */
|
||||
}
|
||||
/* see if the tag is a valid MMS PDU */
|
||||
try_val_to_str_idx(tmp_tag, mms_MMSpdu_vals, &idx);
|
||||
if (idx == -1) {
|
||||
return FALSE; /* no, it isn't an MMS PDU */
|
||||
}
|
||||
|
||||
/* check MMS length */
|
||||
oct = tvb_get_guint8(tvb, offset)& 0x7F;
|
||||
if (oct==0)
|
||||
/* MMS requires length after tag so not MMS if indefinite length*/
|
||||
return FALSE;
|
||||
/* check MMS length */
|
||||
oct = tvb_get_guint8(tvb, offset) & 0x7F;
|
||||
if (oct == 0)
|
||||
/* MMS requires length after tag so not MMS if indefinite length*/
|
||||
return FALSE;
|
||||
|
||||
offset = get_ber_length(tvb, offset, &length, NULL);
|
||||
/* do we have enough bytes? */
|
||||
if (!tvb_bytes_exist(tvb, offset, length))
|
||||
return FALSE;
|
||||
offset = get_ber_length(tvb, offset, &length, NULL);
|
||||
/* do we have enough bytes? */
|
||||
if (!tvb_bytes_exist(tvb, offset, length))
|
||||
return FALSE;
|
||||
|
||||
dissect_mms(tvb, pinfo, parent_tree, data);
|
||||
return TRUE;
|
||||
dissect_mms(tvb, pinfo, parent_tree, data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*--- proto_reg_handoff_mms --- */
|
||||
void proto_reg_handoff_mms(void) {
|
||||
register_ber_oid_dissector("1.0.9506.2.3", dissect_mms, proto_mms,"MMS");
|
||||
register_ber_oid_dissector("1.0.9506.2.1", dissect_mms, proto_mms,"mms-abstract-syntax-version1(1)");
|
||||
heur_dissector_add("cotp", dissect_mms_heur, "MMS over COTP", "mms_cotp", proto_mms, HEURISTIC_ENABLE);
|
||||
heur_dissector_add("cotp_is", dissect_mms_heur, "MMS over COTP (inactive subset)", "mms_cotp_is", proto_mms, HEURISTIC_ENABLE);
|
||||
register_ber_oid_dissector("1.0.9506.2.3", dissect_mms, proto_mms, "MMS");
|
||||
register_ber_oid_dissector("1.0.9506.2.1", dissect_mms, proto_mms, "mms-abstract-syntax-version1(1)");
|
||||
heur_dissector_add("cotp", dissect_mms_heur, "MMS over COTP", "mms_cotp", proto_mms, HEURISTIC_ENABLE);
|
||||
heur_dissector_add("cotp_is", dissect_mms_heur, "MMS over COTP (inactive subset)", "mms_cotp_is", proto_mms, HEURISTIC_ENABLE);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue