diff options
author | Thomas Wiens <th.wiens@gmx.de> | 2016-06-24 23:53:36 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2016-06-27 06:54:32 +0000 |
commit | fbb23e27dddbc2f05a749df2cd07e5d8dd8335ee (patch) | |
tree | ea5b9ef4cddd528473e57a4c56b4117a5d793ee5 /epan/dissectors/packet-s7comm.c | |
parent | 76ae2d9721b870937a92c97328f6f316ebac5f13 (diff) |
s7comm: Sinumerik NC file transfer
Added decoding of up-/downloading files from/to a Sinumerik NC CNC control
machine.
Change-Id: If7939e56e972fc2b8feb12150c4184a880b0cdae
Reviewed-on: https://code.wireshark.org/review/16129
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-s7comm.c')
-rw-r--r-- | epan/dissectors/packet-s7comm.c | 118 |
1 files changed, 117 insertions, 1 deletions
diff --git a/epan/dissectors/packet-s7comm.c b/epan/dissectors/packet-s7comm.c index f1b7f866a9..648a11ff97 100644 --- a/epan/dissectors/packet-s7comm.c +++ b/epan/dissectors/packet-s7comm.c @@ -576,10 +576,39 @@ static const value_string blocklanguage_names[] = { * Names of types in userdata parameter part */ +#define S7COMM_UD_TYPE_NCPUSH 0x3 +#define S7COMM_UD_TYPE_NCREQ 0x7 +#define S7COMM_UD_TYPE_NCRES 0xb + static const value_string userdata_type_names[] = { - { S7COMM_UD_TYPE_PUSH, "Push" }, /* this type occurs when 2 telegrams follow after another from the same partner, or initiated from PLC */ + { S7COMM_UD_TYPE_PUSH, "Push" }, /* this type occurs when 2 telegrams follow after another from the same partner, or initiated from PLC */ { S7COMM_UD_TYPE_REQ, "Request" }, { S7COMM_UD_TYPE_RES, "Response" }, + { S7COMM_UD_TYPE_NCPUSH, "NC Push" }, /* used only by Sinumerik NC */ + { S7COMM_UD_TYPE_NCREQ, "NC Request" }, /* used only by Sinumerik NC */ + { S7COMM_UD_TYPE_NCRES, "NC Response" }, /* used only by Sinumerik NC */ + { 0, NULL } +}; + +/************************************************************************** + * Subfunctions only used in Sinumerik NC file download + */ +#define S7COMM_NCPRG_FUNCREQUESTDOWNLOAD 1 +#define S7COMM_NCPRG_FUNCDOWNLOADBLOCK 2 +#define S7COMM_NCPRG_FUNCCONTDOWNLOAD 3 +#define S7COMM_NCPRG_FUNCDOWNLOADENDED 4 +#define S7COMM_NCPRG_FUNCSTARTUPLOAD 6 +#define S7COMM_NCPRG_FUNCUPLOAD 7 +#define S7COMM_NCPRG_FUNCCONTUPLOAD 8 + +static const value_string userdata_ncprg_subfunc_names[] = { + { S7COMM_NCPRG_FUNCREQUESTDOWNLOAD, "Request download" }, + { S7COMM_NCPRG_FUNCDOWNLOADBLOCK, "Download block" }, + { S7COMM_NCPRG_FUNCCONTDOWNLOAD, "Continue download" }, + { S7COMM_NCPRG_FUNCDOWNLOADENDED, "Download ended" }, + { S7COMM_NCPRG_FUNCSTARTUPLOAD, "Start upload" }, + { S7COMM_NCPRG_FUNCUPLOAD, "Upload" }, + { S7COMM_NCPRG_FUNCCONTUPLOAD, "Continue upload" }, { 0, NULL } }; @@ -606,6 +635,7 @@ static const value_string userdata_lastdataunit_names[] = { #define S7COMM_UD_FUNCGROUP_SEC 0x5 /* Security functions e.g. plc password */ #define S7COMM_UD_FUNCGROUP_PBC 0x6 /* PBC = Programmable Block Communication (PBK in german) */ #define S7COMM_UD_FUNCGROUP_TIME 0x7 +#define S7COMM_UD_FUNCGROUP_NCPRG 0xf static const value_string userdata_functiongroup_names[] = { { S7COMM_UD_FUNCGROUP_MODETRANS, "Mode-transition" }, @@ -616,6 +646,7 @@ static const value_string userdata_functiongroup_names[] = { { S7COMM_UD_FUNCGROUP_SEC, "Security" }, { S7COMM_UD_FUNCGROUP_PBC, "PBC BSEND/BRECV" }, { S7COMM_UD_FUNCGROUP_TIME, "Time functions" }, + { S7COMM_UD_FUNCGROUP_NCPRG, "NC programming" }, { 0, NULL } }; @@ -1068,6 +1099,7 @@ static gint hf_s7comm_userdata_param_subfunc_block = -1; static gint hf_s7comm_userdata_param_subfunc_cpu = -1; static gint hf_s7comm_userdata_param_subfunc_sec = -1; static gint hf_s7comm_userdata_param_subfunc_time = -1; +static gint hf_s7comm_userdata_param_subfunc_ncprg = -1; static gint hf_s7comm_userdata_param_subfunc = -1; /* for all other subfunctions */ static gint hf_s7comm_userdata_param_seq_num = -1; static gint hf_s7comm_userdata_param_dataunitref = -1; @@ -1401,6 +1433,7 @@ static const int *s7comm_data_blockcontrol_status_fields[] = { }; static gint ett_s7comm_plcfilename = -1; +static gint hf_s7comm_data_ncprg_unackcount = -1; /* Variable table */ static gint hf_s7comm_vartab_data_type = -1; /* Type of data, 1 byte, stringlist userdata_prog_vartab_type_names */ @@ -3664,6 +3697,71 @@ s7comm_decode_ud_pbc_subfunc(tvbuff_t *tvb, /******************************************************************************************************* * + * PDU Type: User Data -> NC programming functions (file download/upload) + * + *******************************************************************************************************/ +static guint32 +s7comm_decode_ud_ncprg_subfunc(tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *data_tree, + guint8 type, /* Type of data (request/response) */ + guint8 subfunc, /* Subfunction */ + guint16 dlength, /* length of data part given in header */ + guint32 offset) /* Offset on data part +4 */ +{ + const guint8 *str_filename; + + dlength -= 4; /* There are always 4 bytes header information in data part */ + if (dlength >= 2) { + if (type == S7COMM_UD_TYPE_NCREQ && subfunc == S7COMM_NCPRG_FUNCREQUESTDOWNLOAD) { + proto_tree_add_item_ret_string(data_tree, hf_s7comm_data_blockcontrol_filename, tvb, offset, dlength, + ENC_ASCII|ENC_NA, wmem_packet_scope(), &str_filename); + col_append_fstr(pinfo->cinfo, COL_INFO, " File:[%s]", str_filename); + offset += dlength; + } else if (type == S7COMM_UD_TYPE_NCREQ && subfunc == S7COMM_NCPRG_FUNCSTARTUPLOAD) { + proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_unackcount, tvb, offset, 1, ENC_NA); + offset += 1; + dlength -= 1; + proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 1, ENC_NA); + offset += 1; + dlength -= 1; + proto_tree_add_item_ret_string(data_tree, hf_s7comm_data_blockcontrol_filename, tvb, offset, dlength, + ENC_ASCII|ENC_NA, wmem_packet_scope(), &str_filename); + col_append_fstr(pinfo->cinfo, COL_INFO, " File:[%s]", str_filename); + offset += dlength; + } else if (type == S7COMM_UD_TYPE_NCRES && subfunc == S7COMM_NCPRG_FUNCREQUESTDOWNLOAD) { + proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_unackcount, tvb, offset, 1, ENC_NA); + offset += 1; + dlength -= 1; + proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 1, ENC_NA); + offset += 1; + dlength -= 1; + } else if (type == S7COMM_UD_TYPE_NCPUSH && (subfunc == S7COMM_NCPRG_FUNCCONTUPLOAD || subfunc == S7COMM_NCPRG_FUNCCONTDOWNLOAD)) { + proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_unackcount, tvb, offset, 1, ENC_NA); + offset += 1; + dlength -= 1; + /* Guess: If 1, then this is the last telegram of up/download, otherwise 0 */ + proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 1, ENC_NA); + offset += 1; + dlength -= 1; + } else { + /* There is always a 2 bytes header before the data. + * Guess: first byte is used as "data unit reference" + */ + proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA); + offset += 2; + dlength -= 2; + if (dlength >= 4) { + proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA); + offset += dlength; + } + } + } + return offset; +} + +/******************************************************************************************************* + * * PDU Type: User Data -> Message services * *******************************************************************************************************/ @@ -4625,6 +4723,12 @@ s7comm_decode_ud(tvbuff_t *tvb, val_to_str(subfunc, modetrans_param_subfunc_names, "Unknown subfunc: 0x%02x")); proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, modetrans_param_subfunc_names, "Unknown subfunc: 0x%02x")); break; + case S7COMM_UD_FUNCGROUP_NCPRG: + proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_ncprg, tvb, offset_temp, 1, subfunc); + col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]", + val_to_str(subfunc, userdata_ncprg_subfunc_names, "Unknown subfunc: 0x%02x")); + proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, userdata_ncprg_subfunc_names, "Unknown subfunc: 0x%02x")); + break; default: proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc, tvb, offset_temp, 1, subfunc); break; @@ -4716,6 +4820,9 @@ s7comm_decode_ud(tvbuff_t *tvb, case S7COMM_UD_FUNCGROUP_TIME: offset = s7comm_decode_ud_time_subfunc(tvb, data_tree, type, subfunc, ret_val, dlength, offset); break; + case S7COMM_UD_FUNCGROUP_NCPRG: + offset = s7comm_decode_ud_ncprg_subfunc(tvb, pinfo, data_tree, type, subfunc, dlength, offset); + break; default: break; } @@ -5199,6 +5306,9 @@ proto_register_s7comm (void) { &hf_s7comm_userdata_param_subfunc, { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_s7comm_userdata_param_subfunc_ncprg, + { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_ncprg_subfunc_names), 0x0, + NULL, HFILL }}, { &hf_s7comm_userdata_param_seq_num, { "Sequence number", "s7comm.param.userdata.seq_num", FT_UINT8, BASE_DEC, NULL, 0x0, @@ -5698,6 +5808,12 @@ proto_register_s7comm (void) { &hf_s7comm_data_blockcontrol_functionstatus_error, { "Error", "s7comm.param.blockcontrol.functionstatus.error", FT_BOOLEAN, 8, NULL, 0x02, "An error occured", HFILL }}, + + /* NC programming functions */ + { &hf_s7comm_data_ncprg_unackcount, + { "Number of telegrams sent without acknowledge", "s7comm.data.ncprg.unackcount", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + /* Variable table */ { &hf_s7comm_vartab_data_type, { "Type of data", "s7comm.vartab.data_type", FT_UINT8, BASE_DEC, VALS(userdata_prog_vartab_type_names), 0x0, |