Fixup: tvb_get_string(z) -> tvb_get_string(z)_enc
[metze/wireshark/wip.git] / epan / dissectors / packet-dvbci.c
1 /* packet-dvbci.c
2  * Routines for DVB-CI (Common Interface) dissection
3  * Copyright 2011-2014, Martin Kaiser <martin@kaiser.cx>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 /* This dissector supports DVB-CI as defined in EN50221 and
25  * CI+ (www.ci-plus.com).
26  * For more details, see http://wiki.wireshark.org/DVB-CI.
27  *
28  * The pcap input format for this dissector is documented at
29  * http://www.kaiser.cx/pcap-dvbci.html.
30  */
31
32 #include "config.h"
33
34 #include <glib.h>
35 #include <epan/addr_resolv.h>
36 #include <epan/circuit.h>
37 #include <epan/dvb_chartbl.h>
38 #include <epan/packet.h>
39 #include <epan/exported_pdu.h>
40 #include <epan/reassemble.h>
41 #include <epan/prefs.h>
42 #include <epan/tap.h>
43 #include <epan/expert.h>
44 #include <epan/asn1.h>
45 #include <epan/dissectors/packet-dvbci.h>
46 #include <epan/dissectors/packet-mpeg-descriptor.h>
47 #include <epan/dissectors/packet-mpeg-sect.h>
48 #include <epan/dissectors/packet-mpeg-pmt.h>
49 #include <epan/dissectors/packet-x509af.h>
50 #include <epan/dissectors/packet-x509ce.h>
51
52 #include "packet-ber.h"
53
54 #ifdef HAVE_LIBGCRYPT
55 #include <wsutil/wsgcrypt.h>
56 #endif
57
58 void proto_register_dvbci(void);
59 void proto_reg_handoff_dvbci(void);
60
61 #define AES_BLOCK_LEN 16
62 #define AES_KEY_LEN 16
63
64 #define EXPORTED_SAC_MSG_PROTO "CI+ SAC message"
65
66 #define IS_DATA_TRANSFER(e) (e==DVBCI_EVT_DATA_CAM_TO_HOST || e==DVBCI_EVT_DATA_HOST_TO_CAM)
67
68 /* direction of data transfer in [as]pdu_info_t and elsewhere */
69 #define DATA_CAM_TO_HOST  DVBCI_EVT_DATA_CAM_TO_HOST
70 #define DATA_HOST_TO_CAM  DVBCI_EVT_DATA_HOST_TO_CAM
71 #define DIRECTION_ANY     0x0
72
73 /* source/destination address field */
74 #define ADDR_HOST "Host"
75 #define ADDR_CAM  "CAM"
76
77 /* hardware event */
78 #define CAM_IN    0x01
79 #define CAM_OUT   0x02
80 #define POWER_ON  0x03
81 #define POWER_OFF 0x04
82 #define TS_ROUTE  0x05
83 #define TS_BYPASS 0x06
84 #define RESET_H   0x07
85 #define RESET_L   0x08
86 #define READY_H   0x09
87 #define READY_L   0x0A
88
89 /* Card Information Structure (CIS) */
90
91 /* tuples */
92 #define CISTPL_NO_LINK       0x14
93 #define CISTPL_VERS_1        0x15
94 #define CISTPL_CONFIG        0x1A
95 #define CISTPL_CFTABLE_ENTRY 0x1B
96 #define CISTPL_DEVICE_OC     0x1C
97 #define CISTPL_DEVICE_OA     0x1D
98 #define CISTPL_MANFID        0x20
99 #define CISTPL_END           0xFF
100 /* subtuple */
101 #define CCSTPL_CIF           0xC0
102 /* interface types */
103 #define TPCE_IF_TYPE_MEM     0
104 #define TPCE_IF_TYPE_IO_MEM  1
105 #define TPCE_IF_TYPE_CUST0   4
106 #define TPCE_IF_TYPE_CUST1   5
107 #define TPCE_IF_TYPE_CUST2   6
108 #define TPCE_IF_TYPE_CUST3   7
109
110 /* link layer */
111 #define ML_MORE 0x80
112 #define ML_LAST 0x00
113
114 /* base values of sequence ids for reassembly of fragmented tpdus
115    if there's two open transport connections, their tpdu fragments may be
116     interleaved, we must add the tcid to the base value in order to
117     distinguish between different transport connections
118    TPDU_SEQ_ID_BASE and SPDU_SEQ_ID_BASE can be arbitrary 32bit values, they
119     must be more than 256 apart since we add the 8bit tcid */
120 #define TPDU_SEQ_ID_BASE       123
121 /* same as above, the spdu fragments are also demultiplexed based on the
122     t_c_id field */
123 #define SPDU_SEQ_ID_BASE      2417
124
125 /* transport layer */
126 #define NO_TAG        0x00
127 #define T_SB          0x80
128 #define T_RCV         0x81
129 #define T_CREATE_T_C  0x82
130 #define T_C_T_C_REPLY 0x83
131 #define T_DELETE_T_C  0x84
132 #define T_D_T_C_REPLY 0x85
133 #define T_REQUEST_T_C 0x86
134 #define T_NEW_T_C     0x87
135 #define T_T_C_ERROR   0x88
136 #define T_DATA_LAST   0xA0
137 #define T_DATA_MORE   0xA1
138
139 #define SB_VAL_MSG_AVAILABLE    0x80
140 #define SB_VAL_NO_MSG_AVAILABLE 0x00
141
142 /* session layer */
143 #define T_SESSION_NUMBER          0x90
144 #define T_OPEN_SESSION_REQUEST    0x91
145 #define T_OPEN_SESSION_RESPONSE   0x92
146 #define T_CREATE_SESSION          0x93
147 #define T_CREATE_SESSION_RESPONSE 0x94
148 #define T_CLOSE_SESSION_REQUEST   0x95
149 #define T_CLOSE_SESSION_RESPONSE  0x96
150
151 /* status for open/create session */
152 #define SESS_OPENED                   0x00
153 #define SESS_NOT_OPENED_RES_NON_EXIST 0xF0
154 #define SESS_NOT_OPENED_RES_UNAVAIL   0xF1
155 #define SESS_NOT_OPENED_RES_VER_LOWER 0xF2
156 #define SESS_NOT_OPENED_RES_BUSY      0xF3
157
158 /* status for close session */
159 #define SESS_CLOSED       0x00
160 #define SESS_NB_NOT_ALLOC 0xF0
161
162 /* circuit id from session number (16bit) and transport connection id * (8bit) */
163 #define CT_ID(s,t) ((guint32)(s<<8|t))
164
165 /* resource id */
166 #define RES_ID_TYPE_MASK 0xC0000000
167 #define RES_CLASS_MASK   0x3FFF0000
168 #define RES_TYPE_MASK    0x0000FFC0
169 #define RES_VER_MASK     0x0000003F
170
171 /* resource class */
172 #define RES_CLASS_RM  0x01
173 #define RES_CLASS_AP  0x02
174 #define RES_CLASS_CA  0x03
175 #define RES_CLASS_AUT 0x10
176 #define RES_CLASS_HC  0x20
177 #define RES_CLASS_DT  0x24
178 #define RES_CLASS_MMI 0x40
179 #define RES_CLASS_AMI 0x41
180 #define RES_CLASS_LSC 0x60
181 #define RES_CLASS_CC  0x8C
182 #define RES_CLASS_HLC 0x8D
183 #define RES_CLASS_CUP 0x8E
184 #define RES_CLASS_OPP 0x8F
185 #define RES_CLASS_SAS 0x96
186
187 #define RES_ID_LEN 4 /* bytes */
188 #define RES_CLASS(_res_id) (_res_id & RES_CLASS_MASK) >> 16
189 #define RES_VER(_res_id)   (_res_id & RES_VER_MASK)
190
191 /* appinfo resource */
192 #define APP_TYPE_CA  0x1
193 #define APP_TYPE_EPG 0x2
194
195 #define DATA_RATE_72 0x0
196 #define DATA_RATE_96 0x1
197
198 /* ca resource */
199 #define LIST_MGMT_MORE   0x0
200 #define LIST_MGMT_FIRST  0x1
201 #define LIST_MGMT_LAST   0x2
202 #define LIST_MGMT_ONLY   0x3
203 #define LIST_MGMT_ADD    0x4
204 #define LIST_MGMT_UPDATE 0x5
205
206 #define CMD_ID_OK_DESCR     0x1
207 #define CMD_ID_OK_MMI       0x2
208 #define CMD_ID_QUERY        0x3
209 #define CMD_ID_NOT_SELECTED 0x4
210
211 #define CA_DESC_TAG 0x9
212
213 #define CA_ENAB_DESC_OK             0x01
214 #define CA_ENAB_DESC_OK_PURCHASE    0x02
215 #define CA_ENAB_DESC_OK_TECH        0x03
216 #define CA_ENAB_DESC_NG_ENTITLEMENT 0x71
217 #define CA_ENAB_DESC_NG_TECH        0x73
218
219 /* host control resource */
220 #define HC_STAT_OK            0x0
221 #define HC_STAT_ERR_DLVRY     0x1
222 #define HC_STAT_ERR_LOCK      0x2
223 #define HC_STAT_ERR_BUSY      0x3
224 #define HC_STAT_ERR_PARAM     0x4
225 #define HC_STAT_ERR_NOT_FOUND 0x5
226 #define HC_STAT_ERR_UNKNOWN   0x6
227
228 #define HC_RELEASE_OK      0x0
229 #define HC_RELEASE_REFUSED 0x1
230
231 /* mmi resource */
232 #define CLOSE_MMI_CMD_ID_IMMEDIATE 0x0
233 #define CLOSE_MMI_CMD_ID_DELAY     0x1
234
235 /* only commands and parameters for high-level mmi are supported */
236 #define DISP_CMD_SET_MMI_MODE 1
237 #define DISP_CMD_GET_DISP_TBL 2
238 #define DISP_CMD_GET_INP_TBL  3
239
240 #define MMI_MODE_HIGH 1
241
242 #define DISP_REP_ID_MMI_MODE_ACK     0x01
243 #define DISP_REP_ID_DISP_CHAR_TBL    0x02
244 #define DISP_REP_ID_INP_CHAR_TBL     0x03
245 #define DISP_REP_ID_UNKNOWN_CMD      0xF0
246 #define DISP_REP_ID_UNKNOWN_MMI_MODE 0xF1
247 #define DISP_REP_ID_UNKNOWN_CHAR_TBL 0xF2
248
249 #define VISIBLE_ANS 0
250 #define BLIND_ANS   1
251
252 #define ANSW_ID_CANCEL 0x00
253 #define ANSW_ID_ANSWER 0x01
254
255 /* used for answer_text_length, choice_nb and item_nb */
256 #define NB_UNKNOWN 0xFF
257
258 /* cam upgrade resource */
259 #define CUP_DELAYED   0x0
260 #define CUP_IMMEDIATE 0x1
261
262 #define CUP_ANS_NO  0x0
263 #define CUP_ANS_YES 0x1
264 #define CUP_ANS_ASK 0x2
265
266 #define CUP_RESET_PCMCIA 0x0
267 #define CUP_RESET_CMDIF  0x1
268 #define CUP_RESET_NONE   0x2
269
270 /* content control resource */
271 #define CC_ID_HOST_ID            0x05
272 #define CC_ID_CICAM_ID           0x06
273 #define CC_ID_HOST_BRAND_CERT    0x07
274 #define CC_ID_CICAM_BRAND_CERT   0x08
275 #define CC_ID_KP                 0x0C
276 #define CC_ID_DHPH               0x0D
277 #define CC_ID_DHPM               0x0E
278 #define CC_ID_HOST_DEV_CERT      0x0F
279 #define CC_ID_CICAM_DEV_CERT     0x10
280 #define CC_ID_SIG_A              0x11
281 #define CC_ID_SIG_B              0x12
282 #define CC_ID_AUTH_NONCE         0x13
283 #define CC_ID_NS_HOST            0x14
284 #define CC_ID_NS_MODULE          0x15
285 #define CC_ID_AKH                0x16
286 #define CC_ID_URI                0x19
287 #define CC_ID_PROG_NUM           0x1A
288 #define CC_ID_URI_CNF            0x1B
289 #define CC_ID_KEY_REGISTER       0x1C
290 #define CC_ID_URI_VERSIONS       0x1D
291 #define CC_ID_STATUS_FIELD       0x1E
292 #define CC_ID_SRM_DATA           0x1F
293 #define CC_ID_SRM_CONFIRM        0x20
294 #define CC_ID_CICAM_LICENSE      0x21
295 #define CC_ID_LICENSE_STATUS     0x22
296 #define CC_ID_LICENSE_RCV_STATUS 0x23
297 #define CC_ID_HOST_LICENSE       0x24
298 #define CC_ID_PLAY_COUNT         0x25
299 #define CC_ID_OPERATING_MODE     0x26
300 #define CC_ID_PINCODE_DATA       0x27
301 #define CC_ID_REC_START_STATUS   0x28
302 #define CC_ID_MODE_CHG_STATUS    0x29
303 #define CC_ID_REC_STOP_STATUS    0x2A
304
305 #define CC_EMI_FREE    0x00
306 #define CC_EMI_NO_MORE 0x01
307 #define CC_EMI_ONCE    0x02
308 #define CC_EMI_NEVER   0x03
309
310 #define CC_KEY_EVEN 0x0
311 #define CC_KEY_ODD  0x1
312
313 #define CC_STATUS_OK                    0x0
314 #define CC_STATUS_NO_CC_SUPPORT         0x1
315 #define CC_STATUS_HOST_BUSY             0x2
316 #define CC_STATUS_AUTH_FAILED_OR_NO_SRM 0x3
317 #define CC_STATUS_CICAM_BUSY            0x4
318 #define CC_STATUS_REC_MODE_ERR          0x5
319
320 #define SAC_MSG_HDR_LEN 8
321
322 #define CC_SAC_AUTH_AES128_XCBC_MAC 0x0
323 #define CC_SAC_ENC_AES128_CBC       0x0
324
325 #define CC_CAP_NONE               0x0
326 #define CC_CAP_CAS_PIN            0x1
327 #define CC_CAP_CAS_FTA_PIN        0x2
328 #define CC_CAP_CAS_PIN_CACHED     0x3
329 #define CC_CAP_CAS_FTA_PIN_CACHED 0x4
330
331 /* length of DVB-SI utc time field in bytes */
332 #define UTC_TIME_LEN 5
333
334 #define CC_PIN_BAD         0x0
335 #define CC_PIN_CAM_BUSY    0x1
336 #define CC_PIN_OK          0x2
337 #define CC_PIN_UNCONFIRMED 0x3
338 #define CC_PIN_VB_NOT_REQ  0x4
339 #define CC_PIN_CSA         0x5
340
341 #define CC_OP_MODE_WATCH_BUFFER 0x0
342 #define CC_OP_MODE_TIMESHIFT    0x1
343 #define CC_OP_MODE_UNATTENDED   0x2
344
345 /* application mmi resource */
346 #define ACK_CODE_OK        0x1
347 #define ACK_CODE_WRONG_API 0x2
348 #define ACK_CODE_API_BUSY  0x3
349
350 #define REQ_TYPE_FILE      0x0
351 #define REQ_TYPE_DATA      0x1
352 #define REQ_TYPE_FILE_HASH 0x2
353 #define REQ_TYPE_REQ       0x3
354
355 /* lsc resource */
356 #define COMMS_CMD_ID_CONNECT_ON_CHANNEL    1
357 #define COMMS_CMD_ID_DISCONNECT_ON_CHANNEL 2
358 #define COMMS_CMD_ID_SET_PARAMS            3
359 #define COMMS_CMD_ID_ENQUIRE_STATUS        4
360 #define COMMS_CMD_ID_GET_NEXT_BUFFER       5
361
362 #define CONN_DESC_TEL      1
363 #define CONN_DESC_CABLE    2
364 #define CONN_DESC_IP       3
365 #define CONN_DESC_HOSTNAME 4
366
367 #define LSC_DESC_IP       0xCF
368 #define LSC_DESC_HOSTNAME 0xCD
369
370 #define LSC_IPV4 1
371 #define LSC_IPV6 2
372
373 #define LSC_TCP 1
374 #define LSC_UDP 2
375
376 #define COMMS_REP_ID_CONNECT_ACK         1
377 #define COMMS_REP_ID_DISCONNECT_ACK      2
378 #define COMMS_REP_ID_SET_PARAMS_ACK      3
379 #define COMMS_REP_ID_STATUS_REPLY        4
380 #define COMMS_REP_ID_GET_NEXT_BUFFER_ACK 5
381 #define COMMS_REP_ID_SEND_ACK            6
382
383 #define LSC_RET_OK 0
384 #define LSC_RET_DISCONNECTED 0
385 #define LSC_RET_CONNECTED    1
386 #define LSC_RET_TOO_BIG 0xFE
387
388 /* operator profile resource */
389 #define TABLE_ID_CICAM_NIT 0x40  /* CICAM NIT must be a NIT actual */
390
391 #define OPP_REF_REG_FLG_NONE  0
392 #define OPP_REF_REG_FLG_ADV   1
393 #define OPP_REF_REG_FLG_URG   2
394 #define OPP_REF_REG_FLG_SCHED 3
395
396 #define OPP_ERR_FLG_OK          0
397 #define OPP_ERR_FLG_PROF        1
398 #define OPP_ERR_FLG_UNSUPPORTED 2
399 #define OPP_ERR_FLG_CANCELLED   3
400
401 /* EIT p/f, EIT schedule usage */
402 #define OPP_EIT_ABSENT 0
403 #define OPP_EIT_NOT_X  1
404 #define OPP_EIT_FULL_X 2
405 #define OPP_EIT_BARKER 3
406 #define OPP_EPG_APP    4
407
408 #define OPP_EXT_EVT_DIFF 0
409 #define OPP_EXT_EVT_ADD  1
410
411 /* these values match the delivery system descriptor tags */
412 #define OPP_DLV_CAP_S  0x43
413 #define OPP_DLV_CAP_C  0x44
414 #define OPP_DLV_CAP_T  0x5A
415 #define OPP_DLV_CAP_S2 0x79
416
417 #define OPP_TUNE_OK          0
418 #define OPP_TUNE_UNSUPPORTED 1
419 #define OPP_TUNE_INVALID     2
420 #define OPP_TUNE_ERR         3
421
422 #define OPP_NO_MORE_DESC 0xFF
423
424 /* sas resource */
425 #define SAS_SESS_STATE_CONNECTED 0
426 #define SAS_SESS_STATE_NOT_FOUND 1
427 #define SAS_SESS_STATE_DENIED    2
428
429
430 /* application layer */
431
432 #define APDU_TAG_SIZE 3
433
434 /* "don't care" value for min_len_field and len_field (this can't be 0) */
435 #define LEN_FIELD_ANY G_MAXUINT32
436
437 static GHashTable *apdu_table = NULL;
438
439 typedef struct _apdu_info_t {
440     guint32 tag;
441     /* the minimum length required for this apdu */
442     guint32 min_len_field;
443     /* if the apdu has a well-known length, we enforce it here
444      * (otherwise, we set this to LEN_FIELD_ANY) */
445     guint32 len_field;
446     guint8 direction;
447     guint16 res_class;
448     guint8  res_min_ver;
449     void (*dissect_payload)(guint32, gint,
450             tvbuff_t *, gint, circuit_t *, packet_info *, proto_tree *);
451 } apdu_info_t;
452
453
454 static void
455 dissect_dvbci_payload_rm(guint32 tag, gint len_field,
456         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
457         packet_info *pinfo, proto_tree *tree);
458 static void
459 dissect_dvbci_payload_ap(guint32 tag, gint len_field _U_,
460         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
461         packet_info *pinfo, proto_tree *tree);
462 static void
463 dissect_dvbci_payload_ca(guint32 tag, gint len_field,
464         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
465         packet_info *pinfo, proto_tree *tree);
466 static void
467 dissect_dvbci_payload_aut(guint32 tag, gint len_field _U_,
468         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
469         packet_info *pinfo _U_, proto_tree *tree);
470 static void
471 dissect_dvbci_payload_hc(guint32 tag, gint len_field _U_,
472         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
473         packet_info *pinfo, proto_tree *tree);
474 static void
475 dissect_dvbci_payload_dt(guint32 tag, gint len_field,
476         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
477         packet_info *pinfo, proto_tree *tree);
478 static void
479 dissect_dvbci_payload_mmi(guint32 tag, gint len_field,
480         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
481         packet_info *pinfo, proto_tree *tree);
482 static void
483 dissect_dvbci_payload_hlc(guint32 tag, gint len_field _U_,
484         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
485         packet_info *pinfo, proto_tree *tree);
486 static void
487 dissect_dvbci_payload_cup(guint32 tag, gint len_field _U_,
488         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
489         packet_info *pinfo, proto_tree *tree);
490 static void
491 dissect_dvbci_payload_cc(guint32 tag, gint len_field _U_,
492         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
493         packet_info *pinfo, proto_tree *tree);
494 static void
495 dissect_dvbci_payload_ami(guint32 tag, gint len_field _U_,
496         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
497         packet_info *pinfo, proto_tree *tree);
498 static void
499 dissect_dvbci_payload_lsc(guint32 tag, gint len_field,
500         tvbuff_t *tvb, gint offset, circuit_t *circuit,
501         packet_info *pinfo, proto_tree *tree);
502 static void
503 dissect_dvbci_payload_opp(guint32 tag, gint len_field _U_,
504         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
505         packet_info *pinfo, proto_tree *tree);
506 static void
507 dissect_dvbci_payload_sas(guint32 tag, gint len_field _U_,
508         tvbuff_t *tvb, gint offset, circuit_t *circuit,
509         packet_info *pinfo, proto_tree *tree);
510
511
512 /* apdu defines */
513 #define T_PROFILE_ENQ                   0x9F8010
514 #define T_PROFILE                       0x9F8011
515 #define T_PROFILE_CHANGE                0x9F8012
516 #define T_APP_INFO_ENQ                  0x9F8020
517 #define T_APP_INFO                      0x9F8021
518 #define T_ENTER_MENU                    0x9F8022
519 #define T_REQUEST_CICAM_RESET           0x9F8023
520 #define T_DATARATE_INFO                 0x9F8024
521 #define T_CA_INFO_ENQ                   0x9F8030
522 #define T_CA_INFO                       0x9F8031
523 #define T_CA_PMT                        0x9F8032
524 #define T_CA_PMT_REPLY                  0x9F8033
525 #define T_AUTH_REQ                      0x9F8200
526 #define T_AUTH_RESP                     0x9F8201
527 #define T_TUNE                          0x9F8400
528 #define T_REPLACE                       0x9F8401
529 #define T_CLEAR_REPLACE                 0x9F8402
530 #define T_ASK_RELEASE                   0x9F8403
531 #define T_TUNE_BROADCAST_REQ            0x9F8404
532 #define T_TUNE_REPLY                    0x9F8405
533 #define T_ASK_RELEASE_REPLY             0x9F8406
534 #define T_DATE_TIME_ENQ                 0x9F8440
535 #define T_DATE_TIME                     0x9F8441
536 #define T_CLOSE_MMI                     0x9F8800
537 #define T_DISPLAY_CONTROL               0x9F8801
538 #define T_DISPLAY_REPLY                 0x9F8802
539 #define T_ENQ                           0x9F8807
540 #define T_ANSW                          0x9F8808
541 #define T_MENU_LAST                     0x9F8809
542 #define T_MENU_MORE                     0x9F880A
543 #define T_MENU_ANSW                     0x9F880B
544 #define T_LIST_LAST                     0x9F880C
545 #define T_LIST_MORE                     0x9F880D
546 #define T_HOST_COUNTRY_ENQ              0x9F8100
547 #define T_HOST_COUNTRY                  0x9F8101
548 #define T_HOST_LANGUAGE_ENQ             0x9F8110
549 #define T_HOST_LANGUAGE                 0x9F8111
550 #define T_CAM_FIRMWARE_UPGRADE          0x9F9D01
551 #define T_CAM_FIRMWARE_UPGRADE_REPLY    0x9F9D02
552 #define T_CAM_FIRMWARE_UPGRADE_PROGRESS 0x9F9D03
553 #define T_CAM_FIRMWARE_UPGRADE_COMPLETE 0x9F9D04
554 #define T_CC_OPEN_REQ                   0x9F9001
555 #define T_CC_OPEN_CNF                   0x9F9002
556 #define T_CC_DATA_REQ                   0x9F9003
557 #define T_CC_DATA_CNF                   0x9F9004
558 #define T_CC_SYNC_REQ                   0x9F9005
559 #define T_CC_SYNC_CNF                   0x9F9006
560 #define T_CC_SAC_DATA_REQ               0x9F9007
561 #define T_CC_SAC_DATA_CNF               0x9F9008
562 #define T_CC_SAC_SYNC_REQ               0x9F9009
563 #define T_CC_SAC_SYNC_CNF               0x9F9010
564 #define T_CC_PIN_CAPABILITIES_REQ       0x9F9011
565 #define T_CC_PIN_CAPABILITIES_REPLY     0x9F9012
566 #define T_CC_PIN_CMD                    0x9F9013
567 #define T_CC_PIN_REPLY                  0x9F9014
568 #define T_CC_PIN_EVENT                  0x9F9015
569 #define T_CC_PIN_PLAYBACK               0x9F9016
570 #define T_CC_PIN_MMI_REQ                0x9F9017
571 #define T_REQUEST_START                 0x9F8000
572 #define T_REQUEST_START_ACK             0x9F8001
573 #define T_FILE_REQUEST                  0x9F8002
574 #define T_FILE_ACKNOWLEDGE              0x9F8003
575 #define T_APP_ABORT_REQUEST             0x9F8004
576 #define T_APP_ABORT_ACK                 0x9F8005
577 #define T_COMMS_CMD                     0x9F8C00
578 #define T_COMMS_REPLY                   0x9F8C02
579 #define T_COMMS_SEND_LAST               0x9F8C03
580 #define T_COMMS_SEND_MORE               0x9F8C04
581 #define T_COMMS_RCV_LAST                0x9F8C05
582 #define T_COMMS_RCV_MORE                0x9F8C06
583 #define T_OPERATOR_STATUS_REQ           0x9F9C00
584 #define T_OPERATOR_STATUS               0x9F9C01
585 #define T_OPERATOR_NIT_REQ              0x9F9C02
586 #define T_OPERATOR_NIT                  0x9F9C03
587 #define T_OPERATOR_INFO_REQ             0x9F9C04
588 #define T_OPERATOR_INFO                 0x9F9C05
589 #define T_OPERATOR_SEARCH_START         0x9F9C06
590 #define T_OPERATOR_SEARCH_STATUS        0x9F9C07
591 #define T_OPERATOR_EXIT                 0x9F9C08
592 #define T_OPERATOR_TUNE                 0x9F9C09
593 #define T_OPERATOR_TUNE_STATUS          0x9F9C0A
594 #define T_OPERATOR_ENTITLEMENT_ACK      0x9F9C0B
595 #define T_OPERATOR_SEARCH_CANCEL        0x9F9C0C
596 #define T_SAS_CONNECT_RQST              0x9F9A00
597 #define T_SAS_CONNECT_CNF               0x9F9A01
598 #define T_SAS_ASYNC_MSG                 0x9F9A07
599
600 /* these are no real apdus, they just use the same format */
601 #define T_TEXT_LAST             0x9F8803
602 #define T_TEXT_MORE             0x9F8804
603 #define T_CONNECTION_DESCRIPTOR 0x9F8C01
604
605 #define IS_MENU_APDU(t) (t==T_MENU_MORE || t==T_MENU_LAST)
606
607
608 static const apdu_info_t apdu_info[] = {
609     {T_PROFILE_ENQ,         0, 0,             DIRECTION_ANY,    RES_CLASS_RM, 1, NULL},
610     {T_PROFILE,             0, LEN_FIELD_ANY, DIRECTION_ANY,    RES_CLASS_RM, 1, dissect_dvbci_payload_rm},
611     {T_PROFILE_CHANGE,      0, 0,             DIRECTION_ANY,    RES_CLASS_RM, 1, NULL},
612
613     {T_APP_INFO_ENQ,        0, 0,             DATA_HOST_TO_CAM, RES_CLASS_AP, 1, NULL},
614     {T_APP_INFO,            6, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_AP, 1, dissect_dvbci_payload_ap},
615     {T_ENTER_MENU,          0, 0,             DATA_HOST_TO_CAM, RES_CLASS_AP, 1, NULL},
616     {T_REQUEST_CICAM_RESET, 0, 0,             DATA_CAM_TO_HOST, RES_CLASS_AP, 3, NULL},
617     {T_DATARATE_INFO,       0, 1,             DATA_HOST_TO_CAM, RES_CLASS_AP, 3, dissect_dvbci_payload_ap},
618
619     {T_CA_INFO_ENQ,         0, 0,             DATA_HOST_TO_CAM, RES_CLASS_CA, 1, NULL},
620     {T_CA_INFO,             0, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_CA, 1, dissect_dvbci_payload_ca},
621     {T_CA_PMT,              6, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_CA, 1, dissect_dvbci_payload_ca},
622     {T_CA_PMT_REPLY,        8, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_CA, 1, dissect_dvbci_payload_ca},
623
624     {T_AUTH_REQ,            2, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_AUT, 1, dissect_dvbci_payload_aut},
625     {T_AUTH_RESP,           2, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_AUT, 1, dissect_dvbci_payload_aut},
626
627     {T_TUNE,                0, 8,             DATA_CAM_TO_HOST, RES_CLASS_HC, 1, dissect_dvbci_payload_hc},
628     {T_REPLACE,             0, 5,             DATA_CAM_TO_HOST, RES_CLASS_HC, 1, dissect_dvbci_payload_hc},
629     {T_CLEAR_REPLACE,       0, 1,             DATA_CAM_TO_HOST, RES_CLASS_HC, 1, dissect_dvbci_payload_hc},
630     {T_ASK_RELEASE,         0, 0,             DATA_HOST_TO_CAM, RES_CLASS_HC, 1, NULL},
631     {T_TUNE_BROADCAST_REQ,  5, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_HC, 2, dissect_dvbci_payload_hc},
632     {T_TUNE_REPLY,          1, 1,             DATA_HOST_TO_CAM, RES_CLASS_HC, 2, dissect_dvbci_payload_hc},
633     {T_ASK_RELEASE_REPLY,   1, 1,             DATA_CAM_TO_HOST, RES_CLASS_HC, 2, dissect_dvbci_payload_hc},
634
635     {T_DATE_TIME_ENQ,       0, 1,             DATA_CAM_TO_HOST, RES_CLASS_DT, 1, dissect_dvbci_payload_dt},
636     {T_DATE_TIME,           5, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_DT, 1, dissect_dvbci_payload_dt},
637
638     {T_CLOSE_MMI,           1, LEN_FIELD_ANY, DIRECTION_ANY,    RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
639     {T_DISPLAY_CONTROL,     1, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
640     {T_DISPLAY_REPLY,       1, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
641     {T_ENQ,                 2, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
642     {T_ANSW,                1, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
643     {T_MENU_LAST,          13, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
644     {T_MENU_MORE,          13, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
645     {T_MENU_ANSW,           0, 1,             DATA_HOST_TO_CAM, RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
646     {T_LIST_LAST,          13, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
647     {T_LIST_MORE,          13, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_MMI, 1, dissect_dvbci_payload_mmi},
648
649     {T_HOST_COUNTRY_ENQ,    0, 0,             DATA_CAM_TO_HOST, RES_CLASS_HLC, 1, NULL},
650     {T_HOST_COUNTRY,        0, 3,             DATA_HOST_TO_CAM, RES_CLASS_HLC, 1, dissect_dvbci_payload_hlc},
651     {T_HOST_LANGUAGE_ENQ,   0, 0,             DATA_CAM_TO_HOST, RES_CLASS_HLC, 1, NULL},
652     {T_HOST_LANGUAGE,       0, 3,             DATA_HOST_TO_CAM, RES_CLASS_HLC, 1, dissect_dvbci_payload_hlc},
653
654     {T_CAM_FIRMWARE_UPGRADE,          0, 3, DATA_CAM_TO_HOST, RES_CLASS_CUP, 1, dissect_dvbci_payload_cup},
655     {T_CAM_FIRMWARE_UPGRADE_REPLY,    0, 1, DATA_HOST_TO_CAM, RES_CLASS_CUP, 1, dissect_dvbci_payload_cup},
656     {T_CAM_FIRMWARE_UPGRADE_PROGRESS, 0, 1, DATA_CAM_TO_HOST, RES_CLASS_CUP, 1, dissect_dvbci_payload_cup},
657     {T_CAM_FIRMWARE_UPGRADE_COMPLETE, 0, 1, DATA_CAM_TO_HOST, RES_CLASS_CUP, 1, dissect_dvbci_payload_cup},
658
659     {T_CC_OPEN_REQ,                0,  0,             DATA_CAM_TO_HOST, RES_CLASS_CC, 1, NULL},
660     {T_CC_OPEN_CNF,                0,  1,             DATA_HOST_TO_CAM, RES_CLASS_CC, 1, dissect_dvbci_payload_cc},
661     {T_CC_DATA_REQ,                3,  LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_CC, 1, dissect_dvbci_payload_cc},
662     {T_CC_DATA_CNF,                2,  LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_CC, 1, dissect_dvbci_payload_cc},
663     {T_CC_SYNC_REQ,                0,  0,             DATA_CAM_TO_HOST, RES_CLASS_CC, 1, NULL},
664     {T_CC_SYNC_CNF,                0,  1,             DATA_HOST_TO_CAM, RES_CLASS_CC, 1, dissect_dvbci_payload_cc},
665     {T_CC_SAC_DATA_REQ,            8,  LEN_FIELD_ANY, DIRECTION_ANY,    RES_CLASS_CC, 1, dissect_dvbci_payload_cc},
666     {T_CC_SAC_DATA_CNF,            8,  LEN_FIELD_ANY, DIRECTION_ANY,    RES_CLASS_CC, 1, dissect_dvbci_payload_cc},
667     {T_CC_SAC_SYNC_REQ,            8,  LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_CC, 1, dissect_dvbci_payload_cc},
668     {T_CC_SAC_SYNC_CNF,            8,  LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_CC, 1, dissect_dvbci_payload_cc},
669     {T_CC_PIN_CAPABILITIES_REQ,    0,  0,             DATA_HOST_TO_CAM, RES_CLASS_CC, 2, NULL},
670     {T_CC_PIN_CAPABILITIES_REPLY,  7,  7,             DATA_CAM_TO_HOST, RES_CLASS_CC, 2, dissect_dvbci_payload_cc},
671     {T_CC_PIN_CMD,                 1,  LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_CC, 2, dissect_dvbci_payload_cc},
672     {T_CC_PIN_REPLY,               1,  1,             DATA_CAM_TO_HOST, RES_CLASS_CC, 2, dissect_dvbci_payload_cc},
673     {T_CC_PIN_EVENT,              25, 25,             DATA_CAM_TO_HOST, RES_CLASS_CC, 2, dissect_dvbci_payload_cc},
674     {T_CC_PIN_PLAYBACK,           16, 16,             DATA_HOST_TO_CAM, RES_CLASS_CC, 2, dissect_dvbci_payload_cc},
675     {T_CC_PIN_MMI_REQ,             1,  LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_CC, 2, dissect_dvbci_payload_cc},
676
677     {T_REQUEST_START,       2, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_AMI, 1, dissect_dvbci_payload_ami},
678     {T_REQUEST_START_ACK,   0, 1,             DATA_HOST_TO_CAM, RES_CLASS_AMI, 1, dissect_dvbci_payload_ami},
679     {T_FILE_REQUEST,        1, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_AMI, 1, dissect_dvbci_payload_ami},
680     {T_FILE_ACKNOWLEDGE,    2, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_AMI, 1, dissect_dvbci_payload_ami},
681     {T_APP_ABORT_REQUEST,   0, LEN_FIELD_ANY, DIRECTION_ANY,    RES_CLASS_AMI, 1, dissect_dvbci_payload_ami},
682     {T_APP_ABORT_ACK,       0, LEN_FIELD_ANY, DIRECTION_ANY,    RES_CLASS_AMI, 1, dissect_dvbci_payload_ami},
683
684     {T_COMMS_CMD,           1, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_LSC, 1, dissect_dvbci_payload_lsc},
685     {T_COMMS_REPLY,         0, 2,             DATA_HOST_TO_CAM, RES_CLASS_LSC, 1, dissect_dvbci_payload_lsc},
686     {T_COMMS_SEND_LAST,     2, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_LSC, 1, dissect_dvbci_payload_lsc},
687     {T_COMMS_SEND_MORE,     2, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_LSC, 1, dissect_dvbci_payload_lsc},
688     {T_COMMS_RCV_LAST,      2, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_LSC, 1, dissect_dvbci_payload_lsc},
689     {T_COMMS_RCV_MORE,      2, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_LSC, 1, dissect_dvbci_payload_lsc},
690
691     {T_OPERATOR_STATUS_REQ,       0, 0,             DATA_HOST_TO_CAM, RES_CLASS_OPP, 1, NULL},
692     {T_OPERATOR_STATUS,           0, 6,             DATA_CAM_TO_HOST, RES_CLASS_OPP, 1, dissect_dvbci_payload_opp},
693     {T_OPERATOR_NIT_REQ,          0, 0,             DATA_HOST_TO_CAM, RES_CLASS_OPP, 1, NULL},
694     {T_OPERATOR_NIT,              2, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_OPP, 1, dissect_dvbci_payload_opp},
695     {T_OPERATOR_INFO_REQ,         0, 0,             DATA_HOST_TO_CAM, RES_CLASS_OPP, 1, NULL},
696     {T_OPERATOR_INFO,             1, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_OPP, 1, dissect_dvbci_payload_opp},
697     {T_OPERATOR_SEARCH_START,     3, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_OPP, 1, dissect_dvbci_payload_opp},
698     {T_OPERATOR_SEARCH_STATUS,    0, 6,             DATA_CAM_TO_HOST, RES_CLASS_OPP, 1, dissect_dvbci_payload_opp},
699     {T_OPERATOR_EXIT,             0, 0,             DATA_HOST_TO_CAM, RES_CLASS_OPP, 1, NULL},
700     {T_OPERATOR_TUNE,             2, LEN_FIELD_ANY, DATA_CAM_TO_HOST, RES_CLASS_OPP, 1, dissect_dvbci_payload_opp},
701     {T_OPERATOR_TUNE_STATUS,      5, LEN_FIELD_ANY, DATA_HOST_TO_CAM, RES_CLASS_OPP, 1, dissect_dvbci_payload_opp},
702     {T_OPERATOR_ENTITLEMENT_ACK,  0, 0,             DATA_HOST_TO_CAM, RES_CLASS_OPP, 1, NULL},
703     {T_OPERATOR_SEARCH_CANCEL,    0, 0,             DATA_HOST_TO_CAM, RES_CLASS_OPP, 1, NULL},
704
705     {T_SAS_CONNECT_RQST,    0, 8,             DATA_HOST_TO_CAM, RES_CLASS_SAS, 1, dissect_dvbci_payload_sas},
706     {T_SAS_CONNECT_CNF,     0, 9,             DATA_CAM_TO_HOST, RES_CLASS_SAS, 1, dissect_dvbci_payload_sas},
707     {T_SAS_ASYNC_MSG,       3, LEN_FIELD_ANY, DIRECTION_ANY,    RES_CLASS_SAS, 1, dissect_dvbci_payload_sas}
708 };
709
710 static const value_string dvbci_apdu_tag[] = {
711     { T_PROFILE_ENQ,                   "Profile enquiry" },
712     { T_PROFILE,                       "Profile information" },
713     { T_PROFILE_CHANGE,                "Profile change notification" },
714     { T_APP_INFO_ENQ,                  "Application info enquiry" },
715     { T_APP_INFO,                      "Application info" },
716     { T_ENTER_MENU,                    "Enter menu" },
717     { T_REQUEST_CICAM_RESET,           "Request CICAM reset" },
718     { T_DATARATE_INFO,                 "Datarate info" },
719     { T_CA_INFO_ENQ,                   "CA info enquiry" },
720     { T_CA_INFO,                       "CA info" },
721     { T_CA_PMT,                        "CA PMT" },
722     { T_CA_PMT_REPLY,                  "CA PMT reply" },
723     { T_AUTH_REQ,                      "Authentication request" },
724     { T_AUTH_RESP,                     "Authentication response" },
725     { T_TUNE,                          "Tune" },
726     { T_REPLACE,                       "Replace" },
727     { T_CLEAR_REPLACE,                 "Clear replace" },
728     { T_ASK_RELEASE,                   "Ask release" },
729     { T_TUNE_BROADCAST_REQ,            "Tune broadcast request" },
730     { T_TUNE_REPLY,                    "Tune reply" },
731     { T_ASK_RELEASE_REPLY,             "Ask release reply" },
732     { T_DATE_TIME_ENQ,                 "Date-Time enquiry" },
733     { T_DATE_TIME,                     "Date-Time" },
734     { T_CLOSE_MMI,                     "Close MMI" },
735     { T_DISPLAY_CONTROL,               "Display control" },
736     { T_DISPLAY_REPLY,                 "Display reply" },
737     { T_TEXT_LAST,                     "Text last" },
738     { T_TEXT_MORE,                     "Text more" },
739     { T_ENQ,                           "Enquiry" },
740     { T_ANSW,                          "Answer" },
741     { T_MENU_LAST,                     "Menu last" },
742     { T_MENU_MORE,                     "Menu more" },
743     { T_MENU_ANSW,                     "Menu answer" },
744     { T_LIST_LAST,                     "List last" },
745     { T_LIST_MORE,                     "List more" },
746     { T_HOST_COUNTRY_ENQ,              "Host country enquiry" },
747     { T_HOST_COUNTRY,                  "Host country" },
748     { T_HOST_LANGUAGE_ENQ,             "Host language enquiry" },
749     { T_HOST_LANGUAGE,                 "Host language" },
750     { T_CAM_FIRMWARE_UPGRADE,          "CAM firmware upgrade" },
751     { T_CAM_FIRMWARE_UPGRADE_REPLY,    "CAM firmware upgrade reply" },
752     { T_CAM_FIRMWARE_UPGRADE_PROGRESS, "CAM firmware upgrade progress" },
753     { T_CAM_FIRMWARE_UPGRADE_COMPLETE, "CAM firmware upgrade complete" },
754     { T_CC_OPEN_REQ,                   "CC open request" },
755     { T_CC_OPEN_CNF,                   "CC open confirm" },
756     { T_CC_DATA_REQ,                   "CC data request" },
757     { T_CC_DATA_CNF,                   "CC data confirm" },
758     { T_CC_SYNC_REQ,                   "CC sync request" },
759     { T_CC_SYNC_CNF,                   "CC sync confirm" },
760     { T_CC_SAC_DATA_REQ,               "CC SAC data request" },
761     { T_CC_SAC_DATA_CNF,               "CC SAC data confirm" },
762     { T_CC_SAC_SYNC_REQ,               "CC SAC sync request" },
763     { T_CC_SAC_SYNC_CNF,               "CC SAC sync confirm" },
764     { T_CC_PIN_CAPABILITIES_REQ,       "CC PIN capabilities request" },
765     { T_CC_PIN_CAPABILITIES_REPLY,     "CC PIN capabilities reply" },
766     { T_CC_PIN_CMD,                    "CC PIN command" },
767     { T_CC_PIN_REPLY,                  "CC PIN reply" },
768     { T_CC_PIN_EVENT,                  "CC PIN event" },
769     { T_CC_PIN_PLAYBACK,               "CC PIN playback" },
770     { T_CC_PIN_MMI_REQ,                "CC PIN MMI request" },
771     { T_REQUEST_START,                 "Request start" },
772     { T_REQUEST_START_ACK,             "Request start ack" },
773     { T_FILE_REQUEST,                  "File request" },
774     { T_FILE_ACKNOWLEDGE,              "File acknowledge" },
775     { T_APP_ABORT_REQUEST,             "App abort request" },
776     { T_APP_ABORT_ACK,                 "App abort ack" },
777     { T_COMMS_CMD,                     "Comms command" },
778     { T_COMMS_REPLY,                   "Comms reply" },
779     { T_CONNECTION_DESCRIPTOR,         "Connection descriptor" },
780     { T_COMMS_SEND_LAST,               "Comms send last" },
781     { T_COMMS_SEND_MORE,               "Comms send more" },
782     { T_COMMS_RCV_LAST,                "Comms receive last" },
783     { T_COMMS_RCV_MORE,                "Comms receive more" },
784     { T_OPERATOR_STATUS_REQ,           "Operator status request" },
785     { T_OPERATOR_STATUS,               "Operator status" },
786     { T_OPERATOR_NIT_REQ,              "Operator NIT request" },
787     { T_OPERATOR_NIT,                  "Operator NIT" },
788     { T_OPERATOR_INFO_REQ,             "Operator info request" },
789     { T_OPERATOR_INFO,                 "Operator info" },
790     { T_OPERATOR_SEARCH_START,         "Operator search start" },
791     { T_OPERATOR_SEARCH_STATUS,        "Operator search status" },
792     { T_OPERATOR_EXIT,                 "Operator exit" },
793     { T_OPERATOR_TUNE,                 "Operator tune" },
794     { T_OPERATOR_TUNE_STATUS,          "Operator tune status" },
795     { T_OPERATOR_ENTITLEMENT_ACK,      "Operator entitlement acknowledge" },
796     { T_OPERATOR_SEARCH_CANCEL,        "Operator search cancel" },
797     { T_SAS_CONNECT_RQST,              "SAS connect request" },
798     { T_SAS_CONNECT_CNF,               "SAS connect confirm" },
799     { T_SAS_ASYNC_MSG,                 "SAS async message" },
800     { 0, NULL }
801 };
802
803 static int proto_dvbci = -1;
804
805 static const gchar *dvbci_sek = NULL;
806 static const gchar *dvbci_siv = NULL;
807 static gboolean dvbci_dissect_lsc_msg = FALSE;
808
809 /* the output of pref_key_string_to_bin() applied to dvbci_sek and _siv */
810 static unsigned char *dvbci_sek_bin = NULL;
811 static unsigned char *dvbci_siv_bin = NULL;
812
813 static dissector_handle_t data_handle;
814 static dissector_handle_t mpeg_pmt_handle;
815 static dissector_handle_t dvb_nit_handle;
816 static dissector_handle_t png_handle;
817 static dissector_table_t tcp_dissector_table;
818 static dissector_table_t udp_dissector_table;
819
820 static gint exported_pdu_tap = -1;
821
822 static gint ett_dvbci = -1;
823 static gint ett_dvbci_hdr = -1;
824 static gint ett_dvbci_cis = -1;
825 static gint ett_dvbci_cis_tpl = -1;
826 static gint ett_dvbci_cis_subtpl = -1;
827 static gint ett_dvbci_link = -1;
828 static gint ett_dvbci_link_frag = -1;
829 static gint ett_dvbci_link_frags = -1;
830 static gint ett_dvbci_transport = -1;
831 static gint ett_dvbci_transport_frag = -1;
832 static gint ett_dvbci_transport_frags = -1;
833 static gint ett_dvbci_session = -1;
834 static gint ett_dvbci_res = -1;
835 static gint ett_dvbci_application = -1;
836 static gint ett_dvbci_es = -1;
837 static gint ett_dvbci_ca_desc = -1;
838 static gint ett_dvbci_text = -1;
839 static gint ett_dvbci_cc_item = -1;
840 static gint ett_dvbci_sac_msg_body = -1;
841 static gint ett_dvbci_ami_req_types = -1;
842 static gint ett_dvbci_lsc_conn_desc = -1;
843 static gint ett_dvbci_opp_cap_loop = -1;
844 static gint ett_dvbci_dlv_sys_hint = -1;
845
846
847 static int hf_dvbci_event = -1;
848 static int hf_dvbci_hw_event = -1;
849 static int hf_dvbci_cor_addr = -1;
850 static int hf_dvbci_cor_val = -1;
851 static int hf_dvbci_cis_tpl_code = -1;
852 static int hf_dvbci_cis_tpl_len = -1;
853 static int hf_dvbci_cis_tpl_data = -1;
854 static int hf_dvbci_cis_tpll_v1_major = -1;
855 static int hf_dvbci_cis_tpll_v1_minor = -1;
856 static int hf_dvbci_cis_tpll_v1_info_manuf = -1;
857 static int hf_dvbci_cis_tpll_v1_info_name = -1;
858 static int hf_dvbci_cis_tpll_v1_info_additional = -1;
859 static int hf_dvbci_cis_tpll_v1_end = -1;
860 static int hf_dvbci_cis_tpcc_rfsz = -1;
861 static int hf_dvbci_cis_tpcc_rmsz = -1;
862 static int hf_dvbci_cis_tpcc_rasz = -1;
863 static int hf_dvbci_cis_tpcc_last = -1;
864 static int hf_dvbci_cis_tpcc_radr = -1;
865 static int hf_dvbci_cis_tpcc_rmsk = -1;
866 static int hf_dvbci_cis_st_code = -1;
867 static int hf_dvbci_cis_st_len = -1;
868 static int hf_dvbci_cis_stci_ifn_size = -1;
869 static int hf_dvbci_cis_stci_ifn = -1;
870 static int hf_dvbci_cis_stci_str = -1;
871 static int hf_dvbci_cis_tpce_indx_intface = -1;
872 static int hf_dvbci_cis_tpce_indx_default = -1;
873 static int hf_dvbci_cis_tpce_indx_cnf_entry = -1;
874 static int hf_dvbci_cis_tpce_if_type = -1;
875 static int hf_dvbci_cis_tpce_fs_mem_space = -1;
876 static int hf_dvbci_cis_tpce_fs_irq = -1;
877 static int hf_dvbci_cis_tpce_fs_io = -1;
878 static int hf_dvbci_cis_tplmid_manf = -1;
879 static int hf_dvbci_cis_tplmid_card = -1;
880 static int hf_dvbci_buf_size = -1;
881 static int hf_dvbci_tcid = -1;
882 static int hf_dvbci_ml = -1;
883 static int hf_dvbci_l_frags = -1;
884 static int hf_dvbci_l_frag = -1;
885 static int hf_dvbci_l_frag_overlap = -1;
886 static int hf_dvbci_l_frag_overlap_conflicts = -1;
887 static int hf_dvbci_l_frag_multiple_tails = -1;
888 static int hf_dvbci_l_frag_too_long_frag = -1;
889 static int hf_dvbci_l_frag_err = -1;
890 static int hf_dvbci_l_frag_cnt = -1;
891 static int hf_dvbci_l_reass_in = -1;
892 static int hf_dvbci_l_reass_len = -1;
893 static int hf_dvbci_c_tpdu_tag = -1;
894 static int hf_dvbci_r_tpdu_tag = -1;
895 static int hf_dvbci_t_c_id = -1;
896 static int hf_dvbci_sb_value = -1;
897 static int hf_dvbci_t_frags = -1;
898 static int hf_dvbci_t_frag = -1;
899 static int hf_dvbci_t_frag_overlap = -1;
900 static int hf_dvbci_t_frag_overlap_conflicts = -1;
901 static int hf_dvbci_t_frag_multiple_tails = -1;
902 static int hf_dvbci_t_frag_too_long_frag = -1;
903 static int hf_dvbci_t_frag_err = -1;
904 static int hf_dvbci_t_frag_cnt = -1;
905 static int hf_dvbci_t_reass_in = -1;
906 static int hf_dvbci_t_reass_len = -1;
907 static int hf_dvbci_spdu_tag = -1;
908 static int hf_dvbci_sess_status = -1;
909 static int hf_dvbci_sess_nb = -1;
910 static int hf_dvbci_close_sess_status = -1;
911 static int hf_dvbci_res_id_type = -1;
912 static int hf_dvbci_res_class = -1;
913 static int hf_dvbci_res_type = -1;
914 static int hf_dvbci_res_ver = -1;
915 static int hf_dvbci_apdu_tag = -1;
916 static int hf_dvbci_app_type = -1;
917 static int hf_dvbci_app_manf = -1;
918 static int hf_dvbci_manf_code = -1;
919 static int hf_dvbci_menu_str_len = -1;
920 static int hf_dvbci_ap_char_tbl = -1;
921 static int hf_dvbci_menu_str = -1;
922 static int hf_dvbci_data_rate = -1;
923 static int hf_dvbci_ca_sys_id = -1;
924 static int hf_dvbci_ca_pmt_list_mgmt = -1;
925 static int hf_dvbci_prog_num = -1;
926 static int hf_dvbci_prog_info_len = -1;
927 static int hf_dvbci_stream_type = -1;
928 static int hf_dvbci_es_pid = -1;
929 static int hf_dvbci_es_info_len = -1;
930 static int hf_dvbci_ca_pmt_cmd_id = -1;
931 static int hf_dvbci_descr_len = -1;
932 static int hf_dvbci_ca_pid = -1;
933 static int hf_dvbci_ca_enable_flag = -1;
934 static int hf_dvbci_ca_enable = -1;
935 static int hf_dvbci_auth_proto_id = -1;
936 static int hf_dvbci_auth_req_bytes = -1;
937 static int hf_dvbci_auth_resp_bytes = -1;
938 static int hf_dvbci_network_id = -1;
939 static int hf_dvbci_original_network_id = -1;
940 static int hf_dvbci_transport_stream_id = -1;
941 static int hf_dvbci_service_id = -1;
942 static int hf_dvbci_replacement_ref = -1;
943 static int hf_dvbci_replaced_pid = -1;
944 static int hf_dvbci_replacement_pid = -1;
945 static int hf_dvbci_pmt_flag = -1;
946 static int hf_dvbci_hc_desc_loop_len = -1;
947 static int hf_dvbci_hc_status = -1;
948 static int hf_dvbci_hc_release_reply = -1;
949 static int hf_dvbci_resp_intv = -1;
950 static int hf_dvbci_utc_time = -1;
951 static int hf_dvbci_local_offset = -1;
952 static int hf_dvbci_close_mmi_cmd_id = -1;
953 static int hf_dvbci_close_mmi_delay = -1;
954 static int hf_dvbci_disp_ctl_cmd = -1;
955 static int hf_dvbci_mmi_mode = -1;
956 static int hf_dvbci_disp_rep_id = -1;
957 static int hf_dvbci_mmi_char_tbl = -1;
958 static int hf_dvbci_blind_ans = -1;
959 static int hf_dvbci_ans_txt_len = -1;
960 static int hf_dvbci_enq = -1;
961 static int hf_dvbci_ans_id = -1;
962 static int hf_dvbci_ans = -1;
963 static int hf_dvbci_choice_nb = -1;
964 static int hf_dvbci_choice_ref = -1;
965 static int hf_dvbci_item_nb = -1;
966 static int hf_dvbci_title = -1;
967 static int hf_dvbci_subtitle = -1;
968 static int hf_dvbci_bottom = -1;
969 static int hf_dvbci_item = -1;
970 static int hf_dvbci_host_country = -1;
971 static int hf_dvbci_host_language = -1;
972 static int hf_dvbci_cup_type = -1;
973 static int hf_dvbci_cup_download_time = -1;
974 static int hf_dvbci_cup_answer = -1;
975 static int hf_dvbci_cup_progress = -1;
976 static int hf_dvbci_cup_reset = -1;
977 static int hf_dvbci_cc_sys_id_bitmask = -1;
978 static int hf_dvbci_cc_dat_id = -1;
979 static int hf_dvbci_brand_cert = -1;
980 static int hf_dvbci_dev_cert = -1;
981 static int hf_dvbci_uri_ver = -1;
982 static int hf_dvbci_uri_aps = -1;
983 static int hf_dvbci_uri_emi = -1;
984 static int hf_dvbci_uri_ict = -1;
985 static int hf_dvbci_uri_rct = -1;
986 static int hf_dvbci_uri_dot = -1;
987 static int hf_dvbci_uri_rl = -1;
988 static int hf_dvbci_cc_key_register = -1;
989 static int hf_dvbci_cc_status_field = -1;
990 static int hf_dvbci_cc_op_mode = -1;
991 static int hf_dvbci_cc_data = -1;
992 static int hf_dvbci_sac_msg_ctr = -1;
993 static int hf_dvbci_sac_proto_ver = -1;
994 static int hf_dvbci_sac_auth_cip = -1;
995 static int hf_dvbci_sac_payload_enc = -1;
996 static int hf_dvbci_sac_enc_cip = -1;
997 static int hf_dvbci_sac_payload_len = -1;
998 static int hf_dvbci_sac_enc_body = -1;
999 static int hf_dvbci_sac_padding = -1;
1000 static int hf_dvbci_sac_signature = -1;
1001 static int hf_dvbci_rating = -1;
1002 static int hf_dvbci_capability_field = -1;
1003 static int hf_dvbci_pin_chg_time = -1;
1004 static int hf_dvbci_pincode_status = -1;
1005 static int hf_dvbci_cc_prog_num = -1;
1006 static int hf_dvbci_pin_evt_time = -1;
1007 static int hf_dvbci_pin_evt_cent = -1;
1008 static int hf_dvbci_cc_priv_data = -1;
1009 static int hf_dvbci_pincode = -1;
1010 static int hf_dvbci_app_dom_id = -1;
1011 static int hf_dvbci_init_obj = -1;
1012 static int hf_dvbci_ack_code = -1;
1013 static int hf_dvbci_req_type = -1;
1014 static int hf_dvbci_file_hash = -1;
1015 static int hf_dvbci_file_name = -1;
1016 static int hf_dvbci_ami_priv_data = -1;
1017 static int hf_dvbci_req_ok = -1;
1018 static int hf_dvbci_file_ok = -1;
1019 static int hf_dvbci_file_data = -1;
1020 static int hf_dvbci_abort_req_code = -1;
1021 static int hf_dvbci_abort_ack_code = -1;
1022 static int hf_dvbci_phase_id = -1;
1023 static int hf_dvbci_comms_rep_id = -1;
1024 static int hf_dvbci_lsc_buf_size = -1;
1025 static int hf_dvbci_lsc_ret_val = -1;
1026 static int hf_dvbci_comms_cmd_id = -1;
1027 static int hf_dvbci_conn_desc_type = -1;
1028 static int hf_dvbci_lsc_media_tag = -1;
1029 static int hf_dvbci_lsc_media_len = -1;
1030 static int hf_dvbci_lsc_ip_ver = -1;
1031 static int hf_dvbci_lsc_ipv4_addr = -1;
1032 static int hf_dvbci_lsc_ipv6_addr = -1;
1033 static int hf_dvbci_lsc_dst_port = -1;
1034 static int hf_dvbci_lsc_proto = -1;
1035 static int hf_dvbci_lsc_hostname = -1;
1036 static int hf_dvbci_lsc_retry_count = -1;
1037 static int hf_dvbci_lsc_timeout = -1;
1038 static int hf_dvbci_info_ver_op_status = -1;
1039 static int hf_dvbci_nit_ver = -1;
1040 static int hf_dvbci_pro_typ = -1;
1041 static int hf_dvbci_init_flag = -1;
1042 static int hf_dvbci_ent_chg_flag = -1;
1043 static int hf_dvbci_ent_val_flag = -1;
1044 static int hf_dvbci_ref_req_flag = -1;
1045 static int hf_dvbci_err_flag = -1;
1046 static int hf_dvbci_dlv_sys_hint = -1;
1047 static int hf_dvbci_dlv_sys_hint_t = -1;
1048 static int hf_dvbci_dlv_sys_hint_s = -1;
1049 static int hf_dvbci_dlv_sys_hint_c = -1;
1050 static int hf_dvbci_refr_req_date = -1;
1051 static int hf_dvbci_refr_req_time = -1;
1052 static int hf_dvbci_nit_loop_len = -1;
1053 static int hf_dvbci_info_valid = -1;
1054 static int hf_dvbci_info_ver_op_info = -1;
1055 static int hf_dvbci_cicam_onid = -1;
1056 static int hf_dvbci_cicam_id = -1;
1057 static int hf_dvbci_opp_char_tbl = -1;
1058 static int hf_dvbci_sdt_rst_trusted = -1;
1059 static int hf_dvbci_eit_rst_trusted = -1;
1060 static int hf_dvbci_eit_pf_usage = -1;
1061 static int hf_dvbci_eit_sch_usage = -1;
1062 static int hf_dvbci_ext_evt_usage = -1;
1063 static int hf_dvbci_sdt_oth_trusted = -1;
1064 static int hf_dvbci_eit_evt_trigger = -1;
1065 static int hf_dvbci_opp_lang_code = -1;
1066 static int hf_dvbci_prof_name = -1;
1067 static int hf_dvbci_unattended = -1;
1068 static int hf_dvbci_opp_srv_type = -1;
1069 static int hf_dvbci_dlv_cap_byte = -1;
1070 static int hf_dvbci_app_cap_bytes = -1;
1071 static int hf_dvbci_desc_num = -1;
1072 static int hf_dvbci_sig_strength = -1;
1073 static int hf_dvbci_sig_qual = -1;
1074 static int hf_dvbci_opp_tune_status = -1;
1075 static int hf_dvbci_opp_desc_loop_len = -1;
1076 static int hf_dvbci_sas_app_id = -1;
1077 static int hf_dvbci_sas_sess_state = -1;
1078 static int hf_dvbci_sas_msg_nb = -1;
1079 static int hf_dvbci_sas_msg_len = -1;
1080
1081 static const int *dvbci_opp_dlv_sys_hint_fields[] = {
1082     &hf_dvbci_dlv_sys_hint_t,
1083     &hf_dvbci_dlv_sys_hint_s,
1084     &hf_dvbci_dlv_sys_hint_c,
1085     NULL
1086 };
1087
1088
1089 static expert_field ei_dvbci_spdu_tag = EI_INIT;
1090 static expert_field ei_dvbci_sac_payload_enc = EI_INIT;
1091 static expert_field ei_dvbci_buf_size = EI_INIT;
1092 static expert_field ei_dvbci_cicam_nit_table_id = EI_INIT;
1093 static expert_field ei_dvbci_c_tpdu_tag = EI_INIT;
1094 static expert_field ei_dvbci_res_class = EI_INIT;
1095 static expert_field ei_dvbci_bad_length = EI_INIT;
1096 static expert_field ei_dvbci_apdu_not_supported = EI_INIT;
1097 static expert_field ei_dvbci_not_text_more_or_text_last = EI_INIT;
1098 static expert_field ei_dvbci_apu_cam_to_host = EI_INIT;
1099 static expert_field ei_dvbci_ca_pmt_cmd_id = EI_INIT;
1100 static expert_field ei_dvbci_ml = EI_INIT;
1101 static expert_field ei_dvbci_cup_progress = EI_INIT;
1102 static expert_field ei_dvbci_sb_value = EI_INIT;
1103 static expert_field ei_dvbci_spdu_cam_to_host = EI_INIT;
1104 static expert_field ei_dvbci_spdu_host_to_cam = EI_INIT;
1105 static expert_field ei_dvbci_network_id = EI_INIT;
1106 static expert_field ei_dvbci_invalid_char_tbl = EI_INIT;
1107 static expert_field ei_dvbci_t_c_id = EI_INIT;
1108 static expert_field ei_dvbci_tpdu_status_tag = EI_INIT;
1109 static expert_field ei_dvbci_r_tpdu_tag = EI_INIT;
1110 static expert_field ei_dvbci_cor_addr = EI_INIT;
1111 static expert_field ei_dvbci_pin_evt_cent = EI_INIT;
1112 static expert_field ei_dvbci_res_ver = EI_INIT;
1113 static expert_field ei_dvbci_apdu_tag = EI_INIT;
1114 static expert_field ei_dvbci_r_tpdu_status_mandatory = EI_INIT;
1115 static expert_field ei_dvbci_apu_host_to_cam = EI_INIT;
1116 static expert_field ei_dvbci_sig_qual = EI_INIT;
1117
1118 static dissector_table_t sas_msg_dissector_table;
1119
1120 static reassembly_table tpdu_reassembly_table;
1121 static reassembly_table spdu_reassembly_table;
1122
1123 static const fragment_items tpdu_frag_items = {
1124     &ett_dvbci_link_frag,
1125     &ett_dvbci_link_frags,
1126
1127     &hf_dvbci_l_frags,
1128     &hf_dvbci_l_frag,
1129     &hf_dvbci_l_frag_overlap,
1130     &hf_dvbci_l_frag_overlap_conflicts,
1131     &hf_dvbci_l_frag_multiple_tails,
1132     &hf_dvbci_l_frag_too_long_frag,
1133     &hf_dvbci_l_frag_err,
1134     &hf_dvbci_l_frag_cnt,
1135
1136     &hf_dvbci_l_reass_in,
1137     &hf_dvbci_l_reass_len,
1138     /* Reassembled data field */
1139     NULL,
1140     "Tpdu fragments"
1141 };
1142 static const fragment_items spdu_frag_items = {
1143     &ett_dvbci_transport_frag,
1144     &ett_dvbci_transport_frags,
1145
1146     &hf_dvbci_t_frags,
1147     &hf_dvbci_t_frag,
1148     &hf_dvbci_t_frag_overlap,
1149     &hf_dvbci_t_frag_overlap_conflicts,
1150     &hf_dvbci_t_frag_multiple_tails,
1151     &hf_dvbci_t_frag_too_long_frag,
1152     &hf_dvbci_t_frag_err,
1153     &hf_dvbci_t_frag_cnt,
1154
1155     &hf_dvbci_t_reass_in,
1156     &hf_dvbci_t_reass_len,
1157     /* Reassembled data field */
1158     NULL,
1159     "Spdu fragments"
1160 };
1161
1162
1163
1164 typedef struct _spdu_info_t {
1165     guint8 tag;
1166     guint8 direction;
1167     guint8 len_field;
1168 } spdu_info_t;
1169
1170 static const value_string dvbci_hw_event[] = {
1171     { CAM_IN,    "CI Module is inserted" },
1172     { CAM_OUT,   "CI Module is removed" },
1173     { POWER_ON,  "CI slot power on" },
1174     { POWER_OFF, "CI slot power off" },
1175     { TS_ROUTE,  "Transport stream routed through the CI Module" },
1176     { TS_BYPASS, "Transport stream bypasses the CI Module" },
1177     { RESET_H,   "Reset pin is high" },
1178     { RESET_L,   "Reset pin is low" },
1179     { READY_H,   "Ready pin is high" },
1180     { READY_L,   "Ready pin is low" },
1181     { 0, NULL }
1182 };
1183 static const value_string dvbci_cis_tpl_code[] = {
1184     { CISTPL_NO_LINK, "No-link tuple" },
1185     { CISTPL_VERS_1, "Level 1 version/product information" },
1186     { CISTPL_CONFIG, "Configuration for a 16bit PC-Card" },
1187     { CISTPL_CFTABLE_ENTRY, "Configuration-table entry" },
1188     { CISTPL_DEVICE_OC, "Device information for Common Memory" },
1189     { CISTPL_DEVICE_OA, "Device information for Attribute Memory" },
1190     { CISTPL_MANFID, "Manufacturer indentification string" },
1191     { CISTPL_END, "End of chain" },
1192     { 0, NULL }
1193 };
1194 static const value_string dvbci_cis_subtpl_code[] = {
1195     { CCSTPL_CIF, "Custom interface subtuple" },
1196     { 0, NULL }
1197 };
1198 static const value_string dvbci_cis_tpce_if_type[] = {
1199     { TPCE_IF_TYPE_MEM,    "Memory" },
1200     { TPCE_IF_TYPE_IO_MEM, "I/O and Memory" },
1201     { TPCE_IF_TYPE_CUST0,  "Custom Interface 0" },
1202     { TPCE_IF_TYPE_CUST1,  "Custom Interface 1" },
1203     { TPCE_IF_TYPE_CUST2,  "Custom Interface 2" },
1204     { TPCE_IF_TYPE_CUST3,  "Custom Interface 3" },
1205     { 0, NULL }
1206 };
1207 static const value_string dvbci_ml[] = {
1208     { ML_MORE, "more TPDU fragments pending" },
1209     { ML_LAST, "last TPDU fragment" },
1210     { 0, NULL }
1211 };
1212 static const value_string dvbci_c_tpdu[] = {
1213     { T_RCV, "T_RCV" },
1214     { T_CREATE_T_C,  "T_create_t_c" },
1215     { T_DELETE_T_C,  "T_delete_t_c" },
1216     { T_D_T_C_REPLY, "T_d_t_c_reply" },
1217     { T_NEW_T_C,     "T_new_t_c" },
1218     { T_T_C_ERROR,   "T_t_c_error" },
1219     { T_DATA_LAST,   "T_data_last" },
1220     { T_DATA_MORE,   "T_data_more" },
1221     { 0, NULL }
1222 };
1223 static const value_string dvbci_r_tpdu[] = {
1224     { T_C_T_C_REPLY, "T_c_tc_reply" },
1225     { T_DELETE_T_C,  "T_delete_t_c" },
1226     { T_D_T_C_REPLY, "T_d_t_c_reply" },
1227     { T_REQUEST_T_C, "T_request_t_c" },
1228     { T_DATA_LAST,   "T_data_last" },
1229     { T_DATA_MORE,   "T_data_more" },
1230     { 0, NULL }
1231 };
1232 static const value_string dvbci_sb_value[] = {
1233     { SB_VAL_MSG_AVAILABLE,    "message available" },
1234     { SB_VAL_NO_MSG_AVAILABLE, "no message available" },
1235     { 0, NULL }
1236 };
1237 static const value_string dvbci_spdu_tag[] = {
1238     { T_SESSION_NUMBER,          "Session Number (payload data)" },
1239     { T_OPEN_SESSION_REQUEST,    "Open Session Request" },
1240     { T_OPEN_SESSION_RESPONSE,   "Open Session Response" },
1241     { T_CREATE_SESSION,          "Create Session" },
1242     { T_CREATE_SESSION_RESPONSE, "Create Session Response" },
1243     { T_CLOSE_SESSION_REQUEST,   "Close Session Request" },
1244     { T_CLOSE_SESSION_RESPONSE,  "Close Session Response" },
1245     { 0, NULL }
1246 };
1247 static GHashTable *spdu_table = NULL;
1248 static const spdu_info_t spdu_info[] = {
1249     { T_SESSION_NUMBER,          DIRECTION_ANY, 2 },
1250     { T_OPEN_SESSION_REQUEST,    DATA_CAM_TO_HOST, 4 },
1251     { T_OPEN_SESSION_RESPONSE,   DATA_HOST_TO_CAM, 7 },
1252     { T_CREATE_SESSION,          DATA_HOST_TO_CAM, 6 },
1253     { T_CREATE_SESSION_RESPONSE, DATA_CAM_TO_HOST, 7 },
1254     { T_CLOSE_SESSION_REQUEST,   DIRECTION_ANY, 2 },
1255     { T_CLOSE_SESSION_RESPONSE,  DIRECTION_ANY, 3 }
1256 };
1257 static const value_string dvbci_sess_status[] = {
1258     { SESS_OPENED,
1259       "Session opened" },
1260     { SESS_NOT_OPENED_RES_NON_EXIST,
1261       "Resource does not exist" },
1262     { SESS_NOT_OPENED_RES_UNAVAIL,
1263       "Resource exists but it's unavailable" },
1264     { SESS_NOT_OPENED_RES_VER_LOWER,
1265       "Existing resource's version is lower than requested version" },
1266     { SESS_NOT_OPENED_RES_BUSY,
1267       "Resource is busy" },
1268     { 0, NULL }
1269 };
1270 static const value_string dvbci_close_sess_status[] = {
1271     { SESS_CLOSED,       "Session closed" },
1272     { SESS_NB_NOT_ALLOC, "Session number not allocated" },
1273     { 0, NULL }
1274 };
1275 static const value_string dvbci_res_class[] = {
1276     { RES_CLASS_RM,  "Resource Manager" },
1277     { RES_CLASS_AP,  "Application Info" },
1278     { RES_CLASS_CA,  "Conditional Access" },
1279     { RES_CLASS_AUT, "Authentication" },
1280     { RES_CLASS_HC,  "Host Control" },
1281     { RES_CLASS_DT,  "Date-Time" },
1282     { RES_CLASS_MMI, "Man-machine interface (MMI)" },
1283     { RES_CLASS_AMI, "Application MMI" },
1284     { RES_CLASS_LSC, "Low-Speed Communication" },
1285     { RES_CLASS_CC,  "Content Control" },
1286     { RES_CLASS_HLC, "Host Language & Country" },
1287     { RES_CLASS_CUP, "CAM Upgrade" },
1288     { RES_CLASS_OPP, "Operator Profile" },
1289     { RES_CLASS_SAS, "Specific Application Support" },
1290     { 0, NULL }
1291 };
1292 static const value_string dvbci_app_type[] = {
1293     { APP_TYPE_CA,  "Conditional Access" },
1294     { APP_TYPE_EPG, "Electronic Progam Guide" },
1295     { 0, NULL }
1296 };
1297 static const value_string dvbci_data_rate[] = {
1298     { DATA_RATE_72, "72 Mbit/s" },
1299     { DATA_RATE_96, "96 Mbit/s" },
1300     { 0, NULL }
1301 };
1302 static const value_string dvbci_ca_pmt_list_mgmt[] = {
1303     { LIST_MGMT_MORE,   "more" },
1304     { LIST_MGMT_FIRST,  "first" },
1305     { LIST_MGMT_LAST,   "last" },
1306     { LIST_MGMT_ONLY,   "only" },
1307     { LIST_MGMT_ADD,    "add" },
1308     { LIST_MGMT_UPDATE, "update" },
1309     { 0, NULL }
1310 };
1311 static const value_string dvbci_ca_pmt_cmd_id[] = {
1312     { CMD_ID_OK_DESCR,     "ok descrambling" },
1313     { CMD_ID_OK_MMI,       "ok mmi" },
1314     { CMD_ID_QUERY,        "query" },
1315     { CMD_ID_NOT_SELECTED, "not selected" },
1316     { 0, NULL }
1317 };
1318 static const value_string dvbci_ca_enable[] = {
1319     { CA_ENAB_DESC_OK, "descrambling possible" },
1320     { CA_ENAB_DESC_OK_PURCHASE,
1321         "descrambling possible under conditions (purchase dialogue)" },
1322     { CA_ENAB_DESC_OK_TECH,
1323         "descrambling possible under conditions (technical dialogue)" },
1324     { CA_ENAB_DESC_NG_ENTITLEMENT,
1325         "descrambling not possible (because no entitlement)" },
1326     { CA_ENAB_DESC_NG_TECH,
1327         "descrambling not possible (for technical reasons)" },
1328     { 0, NULL }
1329 };
1330 static const value_string dvbci_hc_status[] = {
1331     { HC_STAT_OK, "ok" },
1332     { HC_STAT_ERR_DLVRY, "unsupported delivery system descriptor" },
1333     { HC_STAT_ERR_LOCK, "tuner not locking" },
1334     { HC_STAT_ERR_BUSY, "tuner busy" },
1335     { HC_STAT_ERR_PARAM, "bad or missing parameters" },
1336     { HC_STAT_ERR_NOT_FOUND, "service not found" },
1337     { HC_STAT_ERR_UNKNOWN, "unknown error" },
1338     { 0, NULL }
1339 };
1340 static const value_string dvbci_hc_release_reply[] = {
1341     { HC_RELEASE_OK, "Host regains control of the tuner" },
1342     { HC_RELEASE_REFUSED, "CICAM retains control of the tuner" },
1343     { 0, NULL }
1344 };
1345 static const value_string dvbci_close_mmi_cmd_id[] = {
1346     { CLOSE_MMI_CMD_ID_IMMEDIATE, "immediate close" },
1347     { CLOSE_MMI_CMD_ID_DELAY, "delayed close" },
1348     { 0, NULL }
1349 };
1350 static const value_string dvbci_disp_ctl_cmd[] = {
1351     { DISP_CMD_SET_MMI_MODE, "set MMI mode" },
1352     { DISP_CMD_GET_DISP_TBL, "get display character tables" },
1353     { DISP_CMD_GET_INP_TBL,  "get input character tables" },
1354     { 0, NULL }
1355 };
1356 static const value_string dvbci_mmi_mode[] = {
1357     { MMI_MODE_HIGH, "High-level MMI" },
1358     { 0, NULL }
1359 };
1360 static const value_string dvbci_disp_rep_id[] = {
1361     { DISP_REP_ID_MMI_MODE_ACK,     "MMI mode acknowledge" },
1362     { DISP_REP_ID_DISP_CHAR_TBL,    "list display character tables" },
1363     { DISP_REP_ID_INP_CHAR_TBL,     "list input character tables" },
1364     { DISP_REP_ID_UNKNOWN_CMD,      "unknown display control command" },
1365     { DISP_REP_ID_UNKNOWN_MMI_MODE, "unknown MMI mode" },
1366     { DISP_REP_ID_UNKNOWN_CHAR_TBL, "unknown character table" },
1367     { 0, NULL }
1368 };
1369 static const value_string dvbci_blind_ans[] = {
1370     { VISIBLE_ANS, "visible" },
1371     { BLIND_ANS,   "blind" },
1372     { 0, NULL }
1373 };
1374 static const value_string dvbci_ans_id[] = {
1375     { ANSW_ID_CANCEL, "cancel" },
1376     { ANSW_ID_ANSWER, "answer" },
1377     { 0, NULL }
1378 };
1379 static const value_string dvbci_cup_type[] = {
1380     { CUP_DELAYED, "delayed" },
1381     { CUP_IMMEDIATE, "immediate" },
1382     { 0, NULL }
1383 };
1384 static const value_string dvbci_cup_answer[] = {
1385     { CUP_ANS_NO,  "upgrade denied" },
1386     { CUP_ANS_YES, "upgrade allowed" },
1387     { CUP_ANS_ASK, "ask the user for permission" },
1388     { 0, NULL }
1389 };
1390 static const value_string dvbci_cup_reset[] = {
1391     { CUP_RESET_PCMCIA, "PCMCIA reset" },
1392     { CUP_RESET_CMDIF,  "CI command interface reset" },
1393     { CUP_RESET_NONE,   "no reset" },
1394     { 0, NULL }
1395 };
1396 static const value_string dvbci_cc_dat_id[] = {
1397     { CC_ID_HOST_ID,            "Host ID" },
1398     { CC_ID_CICAM_ID,           "Cicam ID" },
1399     { CC_ID_HOST_BRAND_CERT,    "Host brand certificate" },
1400     { CC_ID_CICAM_BRAND_CERT,   "Cicam brand certificate" },
1401     { CC_ID_KP,                 "Key precursor for CCK" },
1402     { CC_ID_DHPH,               "Host Diffie-Hellman public key" },
1403     { CC_ID_DHPM,               "Cicam Diffie-Hellman public key" },
1404     { CC_ID_HOST_DEV_CERT,      "Host device certificate" },
1405     { CC_ID_CICAM_DEV_CERT,     "Cicam device certificate" },
1406     { CC_ID_SIG_A,              "Signature of host Diffie-Hellman public key" },
1407     { CC_ID_SIG_B,              "Signature of cicam Diffie-Hellman public key" },
1408     { CC_ID_NS_HOST,            "Host nonce" },
1409     { CC_ID_AUTH_NONCE,         "Nonce for authentication" },
1410     { CC_ID_NS_MODULE,          "Cicam nonce" },
1411     { CC_ID_AKH,                "Host authentication key" },
1412     { CC_ID_URI,                "URI" },
1413     { CC_ID_PROG_NUM,           "Program number" },
1414     { CC_ID_URI_CNF,            "URI confirmation" },
1415     { CC_ID_KEY_REGISTER,       "Key register" },
1416     { CC_ID_URI_VERSIONS,       "Supported URI versions" },
1417     { CC_ID_STATUS_FIELD,       "Status field" },
1418     { CC_ID_SRM_DATA,           "SRM for HDCP" },
1419     { CC_ID_SRM_CONFIRM,        "SRM confirmation hash" },
1420     { CC_ID_CICAM_LICENSE,      "License received from the cicam" },
1421     { CC_ID_LICENSE_STATUS,     "Current status of the license" },
1422     { CC_ID_LICENSE_RCV_STATUS, "Status of the license exchange" },
1423     { CC_ID_HOST_LICENSE,
1424         "License for which the host requests the current status" },
1425     { CC_ID_PLAY_COUNT,         "Play count" },
1426     { CC_ID_OPERATING_MODE,     "Operating mode" },
1427     { CC_ID_PINCODE_DATA,       "Pincode data" },
1428     { CC_ID_REC_START_STATUS,   "Record start status" },
1429     { CC_ID_MODE_CHG_STATUS,    "Change operating mode status" },
1430     { CC_ID_REC_STOP_STATUS,    "Record stop status" },
1431     { 0, NULL }
1432 };
1433 static const value_string dvbci_cc_uri_emi[] = {
1434     { CC_EMI_FREE,    "Copy free" },
1435     { CC_EMI_NO_MORE, "Copy no more" },
1436     { CC_EMI_ONCE,    "Copy once" },
1437     { CC_EMI_NEVER,   "Copy never" },
1438     { 0, NULL }
1439 };
1440 static const value_string dvbci_cc_key_register[] = {
1441     { CC_KEY_EVEN,  "Even" },
1442     { CC_KEY_ODD,   "Odd" },
1443     { 0, NULL }
1444 };
1445 static const value_string dvbci_cc_status[] = {
1446     { CC_STATUS_OK,                    "Ok" },
1447     { CC_STATUS_NO_CC_SUPPORT,         "No CC support" },
1448     { CC_STATUS_HOST_BUSY,             "Host busy" },
1449     { CC_STATUS_AUTH_FAILED_OR_NO_SRM, "Authentication failed / SRM not required" },
1450     { CC_STATUS_CICAM_BUSY,            "CICAM busy" },
1451     { CC_STATUS_REC_MODE_ERR,          "Recording mode error" },
1452     { 0, NULL }
1453 };
1454 static const value_string dvbci_cc_sac_auth[] = {
1455     { CC_SAC_AUTH_AES128_XCBC_MAC, "AES 128 XCBC MAC" },
1456     { 0, NULL }
1457 };
1458 static const value_string dvbci_cc_sac_enc[] = {
1459     { CC_SAC_ENC_AES128_CBC, "AES 128 CBC" },
1460     { 0, NULL }
1461 };
1462 static const value_string dvbci_cc_cap[] = {
1463     { CC_CAP_NONE,
1464         "No PIN handling capability" },
1465     { CC_CAP_CAS_PIN,
1466         "CAM can do PIN handling on CAS services" },
1467     { CC_CAP_CAS_FTA_PIN,
1468         "CAM can do PIN handling on CAS and free services" },
1469     { CC_CAP_CAS_PIN_CACHED,
1470         "CAM can do PIN handling on CAS services and supports PIN caching" },
1471     { CC_CAP_CAS_FTA_PIN_CACHED,
1472         "CAM can do PIN handling on CAS and free services, supports PIN caching" },
1473     { 0, NULL }
1474 };
1475 static const value_string dvbci_pincode_status[] = {
1476     { CC_PIN_BAD,         "Bad pin code" },
1477     { CC_PIN_CAM_BUSY,    "CAM busy" },
1478     { CC_PIN_OK,          "Pin code correct" },
1479     { CC_PIN_UNCONFIRMED, "Pin code unconfirmed" },
1480     { CC_PIN_VB_NOT_REQ,  "Video blanking not required" },
1481     { CC_PIN_CSA,         "Content still CSA scrambled" },
1482     { 0, NULL }
1483 };
1484 static const value_string dvbci_cc_op_mode[] = {
1485     { CC_OP_MODE_WATCH_BUFFER, "Watch and buffer" },
1486     { CC_OP_MODE_TIMESHIFT,    "Timeshift" },
1487     { CC_OP_MODE_UNATTENDED,   "Unattended recording" },
1488     { 0, NULL }
1489 };
1490 static const value_string dvbci_ack_code[] = {
1491     { ACK_CODE_OK, "Ok" },
1492     { ACK_CODE_WRONG_API,  "Application Domain unsupported" },
1493     { ACK_CODE_API_BUSY,   "Application Domain currently unavailable" },
1494     { 0, NULL }
1495 };
1496 static const value_string dvbci_req_type[] = {
1497     { REQ_TYPE_FILE, "File" },
1498     { REQ_TYPE_DATA, "Data" },
1499     { REQ_TYPE_FILE_HASH, "FileHash" },
1500     { REQ_TYPE_REQ, "List supported request types" },
1501     { 0, NULL }
1502 };
1503 static const value_string dvbci_comms_cmd_id[] = {
1504     { COMMS_CMD_ID_CONNECT_ON_CHANNEL, "connect on channel" },
1505     { COMMS_CMD_ID_DISCONNECT_ON_CHANNEL, "disconnect on channel" },
1506     { COMMS_CMD_ID_SET_PARAMS, "set parameters" },
1507     { COMMS_CMD_ID_ENQUIRE_STATUS, "status enquiry" },
1508     { COMMS_CMD_ID_GET_NEXT_BUFFER, "get next buffer" },
1509     { 0, NULL }
1510 };
1511 static const value_string dvbci_conn_desc_type[] = {
1512     { CONN_DESC_TEL, "DVB-SI telephone descriptor" },
1513     { CONN_DESC_CABLE, "cable return channel" },
1514     { CONN_DESC_IP, "IP descriptor" },
1515     { CONN_DESC_HOSTNAME, "hostname descriptor" },
1516     { 0, NULL }
1517 };
1518 static const value_string dvbci_lsc_desc_tag[] = {
1519     { LSC_DESC_IP, "IP descriptor" },
1520     { LSC_DESC_HOSTNAME, "hostname descriptor" },
1521     { 0, NULL }
1522 };
1523 static const value_string dvbci_lsc_ip_ver[] = {
1524     { LSC_IPV4, "IPv4" },
1525     { LSC_IPV6, "IPv6" },
1526     { 0, NULL }
1527 };
1528 static const value_string dvbci_lsc_proto[] = {
1529     { LSC_TCP, "TCP" },
1530     { LSC_UDP, "UDP" },
1531     { 0, NULL }
1532 };
1533 static const value_string dvbci_comms_rep_id[] = {
1534     { COMMS_REP_ID_CONNECT_ACK, "connect ack" },
1535     { COMMS_REP_ID_DISCONNECT_ACK, "disconnect ack" },
1536     { COMMS_REP_ID_SET_PARAMS_ACK, "set parameters ack" },
1537     { COMMS_REP_ID_STATUS_REPLY, "status reply" },
1538     { COMMS_REP_ID_GET_NEXT_BUFFER_ACK, "get next buffer ack" },
1539     { COMMS_REP_ID_SEND_ACK, "send ack" },
1540     { 0, NULL }
1541 };
1542 static const value_string dvbci_lsc_ret_val[] = {
1543     { LSC_RET_OK, "ok" },
1544     { 0, NULL }
1545 };
1546 static const value_string dvbci_lsc_ret_val_connect[] = {
1547     { LSC_RET_DISCONNECTED, "disconnected" },
1548     { LSC_RET_CONNECTED, "connected" },
1549     { 0, NULL }
1550 };
1551 static const value_string dvbci_lsc_ret_val_params[] = {
1552     { LSC_RET_OK, "ok" },
1553     { LSC_RET_TOO_BIG, "buffer size too big" },
1554     { 0, NULL }
1555 };
1556 static const value_string dvbci_opp_ref_req_flag[] = {
1557     { OPP_REF_REG_FLG_NONE,  "none" },
1558     { OPP_REF_REG_FLG_ADV,   "advance warning" },
1559     { OPP_REF_REG_FLG_URG,   "urgent" },
1560     { OPP_REF_REG_FLG_SCHED, "scheduled" },
1561     { 0, NULL }
1562 };
1563 static const value_string dvbci_opp_err_flag[] = {
1564     { OPP_ERR_FLG_OK,          "no error" },
1565     { OPP_ERR_FLG_PROF,        "CICAM can't acquire the profile" },
1566     { OPP_ERR_FLG_UNSUPPORTED, "unsupported delivery system" },
1567     { OPP_ERR_FLG_CANCELLED,   "operator search was cancelled" },
1568     { 0, NULL }
1569 };
1570 static const value_string dvbci_opp_eit_pf_usage[] = {
1571     { OPP_EIT_ABSENT, "no EIT present" },
1572     { OPP_EIT_NOT_X,  "EIT is not fully ross-carried" },
1573     { OPP_EIT_FULL_X, "EIT is fully cross-carried" },
1574     { 0, NULL }
1575 };
1576 static const value_string dvbci_opp_eit_sch_usage[] = {
1577     { OPP_EIT_ABSENT, "no EIT present" },
1578     { OPP_EIT_NOT_X,  "EIT is not fully ross-carried" },
1579     { OPP_EIT_FULL_X, "EIT is fully cross-carried" },
1580     { OPP_EIT_BARKER, "EIT is available from a barker channel" },
1581     { OPP_EPG_APP,    "EPG is delivered using an application" },
1582     { 0, NULL }
1583 };
1584 static const value_string dvbci_opp_ext_evt[] = {
1585     { OPP_EXT_EVT_DIFF, "extended event info is different from short event" },
1586     { OPP_EXT_EVT_ADD,  "extended event info includes short event" },
1587     { 0, NULL }
1588 };
1589 static const value_string dvbci_opp_dlv_cap[] = {
1590     { OPP_DLV_CAP_S,  "DVB-S" },
1591     { OPP_DLV_CAP_C,  "DVB-C" },
1592     { OPP_DLV_CAP_T,  "DVB-T" },
1593     { OPP_DLV_CAP_S2, "DVB-S2" },
1594     { 0, NULL }
1595 };
1596 static const value_string dvbci_opp_tune_stat[] = {
1597     { OPP_TUNE_OK,          "success" },
1598     { OPP_TUNE_UNSUPPORTED, "unsupported delivery system descriptor" },
1599     { OPP_TUNE_INVALID,     "invalid delivery system descriptor" },
1600     { OPP_TUNE_ERR,         "failed" },
1601     { 0, NULL }
1602 };
1603 static const value_string dvbci_sas_sess_state[] = {
1604     { SAS_SESS_STATE_CONNECTED, "connected" },
1605     { SAS_SESS_STATE_NOT_FOUND, "application not found" },
1606     { SAS_SESS_STATE_DENIED, "denied, no more connections available" },
1607     { 0, NULL }
1608 };
1609
1610
1611 static guint16 buf_size_cam;    /* buffer size proposal by the CAM */
1612 /* buffer size proposal by the host == negotiated buffer size */
1613 static guint16 buf_size_host;
1614
1615
1616 gint
1617 dvbci_set_addrs(guint8 event, packet_info *pinfo)
1618 {
1619     if (!IS_DATA_TRANSFER(event))
1620         return -1;
1621
1622     if (event == DVBCI_EVT_DATA_HOST_TO_CAM) {
1623         SET_ADDRESS(&pinfo->src, AT_STRINGZ,
1624                 (int)strlen(ADDR_HOST)+1, ADDR_HOST);
1625         SET_ADDRESS(&pinfo->dst, AT_STRINGZ,
1626                 (int)strlen(ADDR_CAM)+1 , ADDR_CAM);
1627     }
1628     else {
1629         SET_ADDRESS(&pinfo->src, AT_STRINGZ,
1630                 (int)strlen(ADDR_CAM)+1 , ADDR_CAM);
1631         SET_ADDRESS(&pinfo->dst, AT_STRINGZ,
1632                 (int)strlen(ADDR_HOST)+1, ADDR_HOST);
1633     }
1634
1635     return 1;
1636 }
1637
1638
1639 guint8
1640 dvbci_get_evt_from_addrs(packet_info *pinfo)
1641 {
1642     /* this should be working from C89 on */
1643     static const address a_cam  = { AT_STRINGZ, -1, sizeof(ADDR_CAM), ADDR_CAM };
1644     static const address a_host = { AT_STRINGZ, -1, sizeof(ADDR_HOST), ADDR_HOST };
1645
1646     if ( ADDRESSES_EQUAL(&(pinfo->src), &a_cam) &&
1647          ADDRESSES_EQUAL(&(pinfo->dst), &a_host) ) {
1648         return DVBCI_EVT_DATA_CAM_TO_HOST;
1649     }
1650     else if ( ADDRESSES_EQUAL(&(pinfo->src), &a_host) &&
1651               ADDRESSES_EQUAL(&(pinfo->dst), &a_cam) ) {
1652         return DVBCI_EVT_DATA_HOST_TO_CAM;
1653     }
1654     else
1655         return DVBCI_EVT_INVALID_EVT;
1656 }
1657
1658
1659 /* this must be a function, not a macro,
1660    so that we can enforce the return type */
1661 static inline gint16 two_comp_to_int16(guint16 x)
1662 {
1663    return (x&0x8000) ? -~(x-1) : x;
1664 }
1665
1666
1667 /* initialize/reset per capture state data */
1668 static void
1669 dvbci_init(void)
1670 {
1671     buf_size_cam  = 0;
1672     buf_size_host = 0;
1673
1674     reassembly_table_init(&tpdu_reassembly_table,
1675                           &addresses_reassembly_table_functions);
1676     reassembly_table_init(&spdu_reassembly_table,
1677                           &addresses_reassembly_table_functions);
1678 }
1679
1680
1681 /* dissect a delivery system descriptor loop
1682    and the preceding length field
1683    (used for host control and operator profile)
1684    return the number of bytes dissected */
1685 static gint
1686 dissect_desc_loop(int len_hf,
1687         tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, proto_tree *tree)
1688 {
1689     gint offset_start;
1690     guint16 desc_loop_len;
1691     guint desc_len;
1692
1693     offset_start = offset;
1694
1695     desc_loop_len = tvb_get_ntohs(tvb, offset) & 0x0FFF;
1696     proto_tree_add_item(tree, len_hf, tvb, offset, 2, ENC_BIG_ENDIAN);
1697     offset += 2;
1698     while (offset-offset_start < 2+desc_loop_len) {
1699         desc_len = proto_mpeg_descriptor_dissect(tvb, offset, tree);
1700         if (desc_len==0)
1701             break;
1702         offset += desc_len;
1703     }
1704
1705     return offset-offset_start;
1706 }
1707
1708
1709 /* dissect operator profile's status body, return its length */
1710 static gint
1711 dissect_opp_status_body(tvbuff_t *tvb, gint offset,
1712         packet_info *pinfo _U_, proto_tree *tree)
1713 {
1714     gint offset_start;
1715
1716     offset_start = offset;
1717     proto_tree_add_item(tree, hf_dvbci_info_ver_op_status,
1718             tvb, offset, 1, ENC_BIG_ENDIAN);
1719     proto_tree_add_item(tree, hf_dvbci_nit_ver,
1720             tvb, offset, 1, ENC_BIG_ENDIAN);
1721     offset++;
1722     proto_tree_add_item(tree, hf_dvbci_pro_typ,
1723             tvb, offset, 1, ENC_BIG_ENDIAN);
1724     proto_tree_add_item(tree, hf_dvbci_init_flag,
1725             tvb, offset, 1, ENC_BIG_ENDIAN);
1726     proto_tree_add_item(tree, hf_dvbci_ent_chg_flag,
1727             tvb, offset, 1, ENC_BIG_ENDIAN);
1728     proto_tree_add_item(tree, hf_dvbci_ent_val_flag,
1729             tvb, offset, 1, ENC_BIG_ENDIAN);
1730     proto_tree_add_item(tree, hf_dvbci_ref_req_flag,
1731             tvb, offset, 1, ENC_BIG_ENDIAN);
1732     offset++;
1733     proto_tree_add_item(tree, hf_dvbci_err_flag,
1734             tvb, offset, 1, ENC_BIG_ENDIAN);
1735     proto_tree_add_bitmask(tree, tvb, offset,
1736             hf_dvbci_dlv_sys_hint, ett_dvbci_dlv_sys_hint,
1737             dvbci_opp_dlv_sys_hint_fields, ENC_BIG_ENDIAN);
1738     offset++;
1739     proto_tree_add_item(tree, hf_dvbci_refr_req_date,
1740             tvb, offset, 2, ENC_BIG_ENDIAN);
1741     offset += 2;
1742     proto_tree_add_item(tree, hf_dvbci_refr_req_time,
1743             tvb, offset, 1, ENC_BIG_ENDIAN);
1744     offset++;
1745
1746     return offset-offset_start;
1747 }
1748
1749
1750 /* dissect a capability loop in an operator_search_start apdu */
1751 static gint
1752 dissect_opp_cap_loop(guint8 cap_loop_len, const gchar *title,
1753         int item_hf, guint item_len,
1754         tvbuff_t *tvb, gint offset,
1755         packet_info *pinfo _U_, proto_tree *tree)
1756 {
1757     proto_item *ti        = NULL;
1758     proto_tree *loop_tree = NULL;
1759     guint       i;
1760
1761     if (!title)
1762         return -1;
1763     if (item_len==0)
1764         return -1;
1765
1766     if (tree && cap_loop_len>0) {
1767         ti = proto_tree_add_text(tree, tvb, offset, cap_loop_len, "%s", title);
1768         loop_tree = proto_item_add_subtree(ti, ett_dvbci_opp_cap_loop);
1769     }
1770     for (i=0; i<cap_loop_len; i+=item_len) {
1771         proto_tree_add_item(loop_tree, item_hf,
1772                 tvb, offset+i, item_len, ENC_BIG_ENDIAN);
1773     }
1774
1775     return cap_loop_len;
1776 }
1777
1778
1779 /* dissect age rating byte encoded as defined in
1780    DVB-SI parental rating descriptor
1781    returns rating's length in bytes or -1 for error */
1782 static gint
1783 dissect_rating(tvbuff_t *tvb, gint offset,
1784         packet_info *pinfo _U_, proto_tree *tree)
1785 {
1786     guint8 rating;
1787
1788     rating = tvb_get_guint8(tvb, offset);
1789     if (1<=rating && rating<=0x0F) {
1790         proto_tree_add_uint_format(tree, hf_dvbci_rating,
1791                 tvb, offset, 1, rating,
1792                 "Rating is %d years (%d+3)", rating+3, rating);
1793     } else {
1794         proto_tree_add_uint_format(tree, hf_dvbci_rating,
1795                 tvb, offset, 1, rating,
1796                 "Rating is unknown/undefined (%d)", rating);
1797     }
1798
1799     return 1;
1800 }
1801
1802
1803 /* if there's a dissector for the protocol and target port of our
1804     lsc connection, store it in the lsc session's circuit */
1805 static void
1806 store_lsc_msg_dissector(circuit_t *circuit, guint8 ip_proto, guint16 port)
1807 {
1808     dissector_handle_t msg_handle = NULL;
1809
1810     if (!circuit)
1811         return;
1812
1813     if (ip_proto==LSC_TCP)
1814         msg_handle = dissector_get_uint_handle(tcp_dissector_table, port);
1815     else if (ip_proto==LSC_UDP)
1816         msg_handle = dissector_get_uint_handle(udp_dissector_table, port);
1817
1818     circuit_set_dissector(circuit, msg_handle);
1819 }
1820
1821
1822 /* dissect a connection_descriptor for the lsc resource
1823    returns its length or -1 for error */
1824 static gint
1825 dissect_conn_desc(tvbuff_t *tvb, gint offset,  circuit_t *circuit,
1826         packet_info *pinfo, proto_tree *tree)
1827 {
1828     proto_item *ti             = NULL;
1829     proto_tree *conn_desc_tree = NULL;
1830     guint32     tag;
1831     gint        offset_start, offset_body;
1832     gint        len_field;
1833     guint8      conn_desc_type;
1834     guint8      ip_ver, ip_proto;
1835     guint16     port;
1836     proto_item *port_item      = NULL;
1837     gint        hostname_len;
1838
1839     offset_start = offset;
1840
1841     tag = tvb_get_ntoh24(tvb, offset);
1842     if (tag!= T_CONNECTION_DESCRIPTOR)
1843         return 0;
1844
1845     ti = proto_tree_add_text(tree, tvb,
1846             offset_start, -1, "Connection descriptor");
1847     conn_desc_tree = proto_item_add_subtree(ti, ett_dvbci_lsc_conn_desc);
1848
1849     proto_tree_add_item(conn_desc_tree, hf_dvbci_apdu_tag,
1850             tvb, offset, APDU_TAG_SIZE, ENC_BIG_ENDIAN);
1851     offset += APDU_TAG_SIZE;
1852     offset = dissect_ber_length(pinfo, conn_desc_tree,
1853                     tvb, offset, &len_field, NULL);
1854     offset_body = offset;
1855
1856     conn_desc_type = tvb_get_guint8(tvb, offset);
1857     proto_tree_add_item(conn_desc_tree, hf_dvbci_conn_desc_type,
1858                     tvb, offset, 1, ENC_BIG_ENDIAN);
1859     offset++;
1860
1861     if (conn_desc_type == CONN_DESC_IP) {
1862         proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_media_tag,
1863                     tvb, offset, 1, ENC_BIG_ENDIAN);
1864         offset++;
1865         proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_media_len,
1866                     tvb, offset, 1, ENC_BIG_ENDIAN);
1867         offset++;
1868         ip_ver = tvb_get_guint8(tvb, offset);
1869         proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_ip_ver,
1870                     tvb, offset, 1, ENC_BIG_ENDIAN);
1871         offset++;
1872
1873         if (ip_ver == LSC_IPV4) {
1874             offset += FT_IPv6_LEN-FT_IPv4_LEN;
1875             proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_ipv4_addr,
1876                     tvb, offset, FT_IPv4_LEN, ENC_BIG_ENDIAN);
1877             offset += FT_IPv4_LEN;
1878         }
1879         else if (ip_ver == LSC_IPV6) {
1880             proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_ipv6_addr,
1881                     tvb, offset, FT_IPv6_LEN, ENC_NA);
1882             offset += FT_IPv6_LEN;
1883         }
1884         else
1885             offset += FT_IPv6_LEN;
1886
1887         port = tvb_get_ntohs(tvb, offset);
1888         port_item = proto_tree_add_item(conn_desc_tree,
1889                 hf_dvbci_lsc_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1890         offset +=2;
1891         ip_proto = tvb_get_guint8(tvb, offset);
1892         proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_proto,
1893                     tvb, offset, 1, ENC_BIG_ENDIAN);
1894         offset ++;
1895         if (port_item) {
1896             if (ip_proto==LSC_TCP && ep_tcp_port_to_display(port)) {
1897                 proto_item_append_text(port_item, " (%s)",
1898                         ep_tcp_port_to_display(port));
1899             }
1900             else if (ip_proto==LSC_UDP && ep_udp_port_to_display(port)) {
1901                 proto_item_append_text(port_item, " (%s)",
1902                         ep_udp_port_to_display(port));
1903             }
1904         }
1905         store_lsc_msg_dissector(circuit, ip_proto, port);
1906
1907     } else if (conn_desc_type == CONN_DESC_HOSTNAME) {
1908         proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_media_tag,
1909                     tvb, offset, 1, ENC_BIG_ENDIAN);
1910         offset++;
1911         proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_media_len,
1912                     tvb, offset, 1, ENC_BIG_ENDIAN);
1913         offset++;
1914         ip_proto = tvb_get_guint8(tvb, offset);
1915         proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_proto,
1916                     tvb, offset, 1, ENC_BIG_ENDIAN);
1917         offset ++;
1918         port = tvb_get_ntohs(tvb, offset);
1919         port_item = proto_tree_add_item(conn_desc_tree,
1920                 hf_dvbci_lsc_dst_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1921         offset +=2;
1922         if (port_item) {
1923             if (ip_proto==LSC_TCP && ep_tcp_port_to_display(port)) {
1924                 proto_item_append_text(port_item, " (%s)",
1925                         ep_tcp_port_to_display(port));
1926             }
1927             else if (ip_proto==LSC_UDP && ep_udp_port_to_display(port)) {
1928                 proto_item_append_text(port_item, " (%s)",
1929                         ep_udp_port_to_display(port));
1930             }
1931         }
1932         store_lsc_msg_dissector(circuit, ip_proto, port);
1933
1934         /* everything from here to the descriptor's end is a hostname */
1935         hostname_len = (offset_body+len_field)-offset;
1936         proto_tree_add_item(conn_desc_tree, hf_dvbci_lsc_hostname,
1937                 tvb, offset, hostname_len, ENC_ASCII|ENC_NA);
1938         offset += hostname_len;
1939     } else {
1940         proto_tree_add_text(conn_desc_tree, tvb,
1941                 offset, len_field-1, "media specific data");
1942         offset += len_field-1;
1943     }
1944
1945     proto_item_set_len(ti, offset-offset_start);
1946     return offset-offset_start;
1947 }
1948
1949
1950 /* check if the given CC resource item may appear in the clear
1951    as part of an exported PDU */
1952 static inline gboolean
1953 is_cc_item_exportable(guint8 dat_id)
1954 {
1955     /* the CCK precursor value does not contain sensitive information as such
1956        nevertheless, it is safer to prevent people from exporting this value
1957        accidentially */
1958     if (dat_id == CC_ID_KP)
1959         return FALSE;
1960     /* we could add some more items here which do not appear in SAC messages
1961        normally: CC_ID_DHPH, CC_ID_DHPM */
1962
1963     return TRUE;
1964 }
1965
1966
1967 /* dissect the URI, return the number of bytes processed or -1 for error */
1968 static gint
1969 dissect_uri(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree)
1970 {
1971     gint        offset_start;
1972     guint8      uri_ver, emi, rl;
1973     proto_item *rl_item;
1974
1975     offset_start = offset;
1976
1977     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "URI");
1978
1979     uri_ver = tvb_get_guint8(tvb, offset);
1980     proto_tree_add_item(tree, hf_dvbci_uri_ver,
1981             tvb, offset, 1, ENC_BIG_ENDIAN);
1982     offset++;
1983
1984     proto_tree_add_item(tree, hf_dvbci_uri_aps,
1985             tvb, offset, 1, ENC_BIG_ENDIAN);
1986     emi = (tvb_get_guint8(tvb, offset) & 0x30) >> 4;
1987     proto_tree_add_item(tree, hf_dvbci_uri_emi,
1988             tvb, offset, 1, ENC_BIG_ENDIAN);
1989     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s",
1990             val_to_str_const(emi, dvbci_cc_uri_emi, "unknown"));
1991     proto_tree_add_item(tree, hf_dvbci_uri_ict,
1992             tvb, offset, 1, ENC_BIG_ENDIAN);
1993     if (emi==CC_EMI_FREE) {
1994         proto_tree_add_item(tree, hf_dvbci_uri_rct,
1995                 tvb, offset, 1, ENC_BIG_ENDIAN);
1996     }
1997     if (uri_ver>=2 && emi==CC_EMI_NEVER) {
1998         proto_tree_add_item(tree, hf_dvbci_uri_dot,
1999                 tvb, offset, 1, ENC_BIG_ENDIAN);
2000     }
2001     offset++;
2002
2003     if (emi==CC_EMI_NEVER) {
2004         if (uri_ver==1)
2005             rl = tvb_get_guint8(tvb, offset) & 0x3F;
2006         else
2007             rl = tvb_get_guint8(tvb, offset);
2008
2009         rl_item = proto_tree_add_uint(tree, hf_dvbci_uri_rl,
2010                 tvb, offset, 1, rl);
2011
2012         if (rl==0x00)
2013             proto_item_append_text(rl_item, " (90 minutes)");
2014         else if (rl==0x01)
2015             proto_item_append_text(rl_item, " (6 hours)");
2016         else if (rl==0x02)
2017             proto_item_append_text(rl_item, " (12 hours)");
2018         else if (uri_ver>=2 && rl==0xFF)
2019             proto_item_append_text(rl_item, " (unlimited)");
2020         else {
2021             /* no need for a range check, rl 0x3F mask was applied above */
2022             proto_item_append_text(rl_item, " (%d days)", rl-2);
2023         }
2024     }
2025
2026     return offset-offset_start;
2027 }
2028
2029
2030 /* dissect an item from cc_(sac_)data_req/cc_(sac_)data_cnf,
2031    returns its length or -1 for error
2032    if dat_id_ptr is not NULL, fill in the datatype id */
2033 static gint
2034 dissect_cc_item(tvbuff_t *tvb, gint offset,
2035         packet_info *pinfo, proto_tree *tree, guint8 *dat_id_ptr)
2036 {
2037     proto_item *ti           = NULL;
2038     proto_tree *cc_item_tree = NULL;
2039     gint        offset_start;
2040     guint16     dat_len;
2041     guint8      dat_id;
2042     asn1_ctx_t  asn1_ctx;
2043     int         hf_cert_index;
2044     guint16     prog_num;
2045     guint8      status;
2046
2047
2048     offset_start = offset;
2049     dat_id = tvb_get_guint8(tvb, offset);
2050     if (dat_id_ptr)
2051         *dat_id_ptr = dat_id;
2052
2053     ti = proto_tree_add_text(tree, tvb, offset_start, -1, "CC data item: %s",
2054             val_to_str_const(dat_id, dvbci_cc_dat_id, "unknown"));
2055     cc_item_tree = proto_item_add_subtree(ti, ett_dvbci_cc_item);
2056
2057     proto_tree_add_item(cc_item_tree, hf_dvbci_cc_dat_id,
2058             tvb, offset, 1, ENC_BIG_ENDIAN);
2059     offset++;
2060     dat_len = tvb_get_ntohs(tvb, offset);
2061     proto_tree_add_text(cc_item_tree, tvb, offset, 2, "Length: %d", dat_len);
2062     offset += 2;
2063     switch (dat_id) {
2064         case CC_ID_HOST_BRAND_CERT:
2065         case CC_ID_CICAM_BRAND_CERT:
2066         case CC_ID_HOST_DEV_CERT:
2067         case CC_ID_CICAM_DEV_CERT:
2068             asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
2069             hf_cert_index = (dat_id==CC_ID_HOST_BRAND_CERT ||
2070                              dat_id==CC_ID_CICAM_BRAND_CERT) ?
2071                 hf_dvbci_brand_cert : hf_dvbci_dev_cert;
2072
2073             /* enable dissection of CI+ specific X.509 extensions
2074                only for our certificates */
2075             x509ce_enable_ciplus();
2076             dissect_x509af_Certificate(FALSE, tvb, offset,
2077                     &asn1_ctx, cc_item_tree, hf_cert_index);
2078             x509ce_disable_ciplus();
2079             break;
2080         case CC_ID_URI:
2081             dissect_uri(tvb, offset, pinfo, cc_item_tree);
2082             break;
2083         case CC_ID_PROG_NUM:
2084             prog_num = tvb_get_ntohs(tvb, offset);
2085             col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
2086                     "Program number 0x%x", prog_num);
2087             proto_tree_add_item(cc_item_tree, hf_dvbci_cc_prog_num,
2088                     tvb, offset, 2, ENC_BIG_ENDIAN);
2089             break;
2090         case CC_ID_KEY_REGISTER:
2091             proto_tree_add_item(cc_item_tree, hf_dvbci_cc_key_register,
2092                     tvb, offset, 1, ENC_BIG_ENDIAN);
2093             break;
2094         case CC_ID_STATUS_FIELD:
2095         case CC_ID_REC_START_STATUS:
2096         case CC_ID_MODE_CHG_STATUS:
2097         case CC_ID_REC_STOP_STATUS:
2098             status = tvb_get_guint8(tvb, offset);
2099             col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Status: %s",
2100                     val_to_str_const(status, dvbci_cc_status, "unknown"));
2101             proto_tree_add_item(cc_item_tree, hf_dvbci_cc_status_field,
2102                     tvb, offset, 1, ENC_BIG_ENDIAN);
2103             break;
2104         case CC_ID_OPERATING_MODE:
2105             proto_tree_add_item(cc_item_tree, hf_dvbci_cc_op_mode,
2106                     tvb, offset, 1, ENC_BIG_ENDIAN);
2107             break;
2108         default:
2109             proto_tree_add_item(cc_item_tree, hf_dvbci_cc_data,
2110                     tvb, offset, dat_len, ENC_NA);
2111             break;
2112     }
2113     offset += dat_len;
2114
2115     proto_item_set_len(ti, offset-offset_start);
2116     return offset-offset_start;
2117 }
2118
2119
2120 /* add the CC protocol name and step to the info column */
2121 static void
2122 add_cc_protocol_name_step(packet_info *pinfo,
2123     guint64 snd_dat_ids, guint64 req_dat_ids)
2124 {
2125     gboolean chk_snd_ids = FALSE;
2126
2127     switch (req_dat_ids) {
2128         case CC_ID_DHPH<<24|CC_ID_SIG_A<<16|CC_ID_HOST_DEV_CERT<<8|CC_ID_HOST_BRAND_CERT:
2129             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2130                     "(Authentication Step 1)");
2131             break;
2132         case CC_ID_STATUS_FIELD:
2133             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2134                     "(Authentication Step 3)");
2135             break;
2136         case CC_ID_AKH:
2137             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2138                     "(AuthKey Step 1)");
2139             break;
2140         case CC_ID_HOST_ID<<8|CC_ID_STATUS_FIELD:
2141             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2142                     "(CC key calculation Step 1)");
2143             break;
2144         case CC_ID_HOST_ID<<8|CC_ID_NS_HOST:
2145             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2146                     "(SAC key calculation Step 1)");
2147             break;
2148         case CC_ID_URI_CNF:
2149             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2150                     "(URI transmission Step 1)");
2151             break;
2152         case CC_ID_URI_VERSIONS:
2153             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2154                     "(URI version negotiation Step 1)");
2155             break;
2156         case CC_ID_LICENSE_RCV_STATUS:
2157             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2158                     "(CICAM to Host License Exchange Step 1)");
2159             break;
2160         case CC_ID_PROG_NUM<<24|CC_ID_LICENSE_STATUS<<16|CC_ID_URI<<8|CC_ID_CICAM_LICENSE:
2161             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2162                     "(Playback License Exchange Step 1)");
2163             break;
2164         case CC_ID_LICENSE_STATUS<<8|CC_ID_PLAY_COUNT:
2165             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2166                     "(License Check Exchange Step 1)");
2167             break;
2168         case CC_ID_REC_START_STATUS:
2169             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2170                     "(Record Start Step 1)");
2171             break;
2172         case CC_ID_MODE_CHG_STATUS:
2173             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2174                     "(Change Operating Mode Step 1)");
2175             break;
2176         case CC_ID_REC_STOP_STATUS:
2177             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2178                     "(Record Stop Step 1)");
2179             break;
2180         case CC_ID_STATUS_FIELD<<8|CC_ID_SRM_CONFIRM:
2181             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2182                     "(SRM Transmission Step 1)");
2183             break;
2184         default:
2185             /* unable to determine the protocol from the requested ids
2186                check the sent ids as well */
2187             chk_snd_ids = TRUE;
2188             break;
2189     }
2190     if (!chk_snd_ids)
2191         return;
2192
2193     switch (snd_dat_ids) {
2194         case CC_ID_DHPH<<24|CC_ID_SIG_A<<16|CC_ID_HOST_DEV_CERT<<8|CC_ID_HOST_BRAND_CERT:
2195             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2196                     "(Authentication Step 2)");
2197             break;
2198         case CC_ID_STATUS_FIELD:
2199             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2200                     "(Authentication Step 4)");
2201             break;
2202         case CC_ID_AKH:
2203             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2204                     "(AuthKey Step 2)");
2205             break;
2206         case CC_ID_HOST_ID<<8|CC_ID_STATUS_FIELD:
2207             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2208                     "(CC key calculation Step 2)");
2209             break;
2210         case CC_ID_HOST_ID<<8|CC_ID_NS_HOST:
2211             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2212                     "(SAC key calculation Step 2)");
2213             break;
2214         case CC_ID_URI_CNF:
2215             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2216                     "(URI transmission Step 2)");
2217             break;
2218         case CC_ID_URI_VERSIONS:
2219             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2220                     "(URI version negotiation Step 2)");
2221             break;
2222         case CC_ID_LICENSE_RCV_STATUS:
2223             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2224                     "(CICAM to Host License Exchange Step 2)");
2225             break;
2226         case CC_ID_PROG_NUM<<24|CC_ID_LICENSE_STATUS<<16|CC_ID_URI<<8|CC_ID_CICAM_LICENSE:
2227             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2228                     "(Playback License Exchange Step 2)");
2229             break;
2230         case CC_ID_LICENSE_STATUS<<8|CC_ID_PLAY_COUNT:
2231             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2232                     "(License Check Exchange Step 2)");
2233             break;
2234         case CC_ID_REC_START_STATUS:
2235             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2236                     "(Record Start Step 2)");
2237             break;
2238         case CC_ID_MODE_CHG_STATUS:
2239             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2240                     "(Change Operating Mode Step 2)");
2241             break;
2242         case CC_ID_REC_STOP_STATUS:
2243             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2244                     "(Record Stop Step 2)");
2245             break;
2246         case CC_ID_STATUS_FIELD<<8|CC_ID_SRM_CONFIRM:
2247             col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
2248                     "(SRM Transmission Step 2)");
2249             break;
2250     }
2251 }
2252
2253
2254 /* dissect the payload of a cc message that contains data items
2255    if not NULL, set exportable_flag to TRUE if the message contains no
2256     sensitive data and can be passed to the export PDU mechanism */
2257 static gint
2258 dissect_cc_data_payload(guint32 tag, tvbuff_t *tvb, gint offset,
2259         packet_info *pinfo, proto_tree *tree, gboolean *exportable_flag)
2260 {
2261     gint        offset_start;
2262     guint8      i, snd_dat_nbr, req_dat_nbr;
2263     guint8      dat_id;
2264     gint        item_len;
2265     /* the last 8 sent/requested datatype ids */
2266     guint64     snd_dat_ids=0, req_dat_ids=0;
2267
2268     /* we only export cc_sac_data_req and cc_sac_data_cnf
2269        the only meta info in the exported PDU is the data transfer
2270         direction, if we only ever export  cc_sac_data_req and
2271         cc_sac_data_cnf, this info is enough to recover the apdu tag from the
2272         direction
2273        cc_sac_sync req and cc_sac_sync_cnf contain no interesting data */
2274     if (exportable_flag)
2275         *exportable_flag = (tag==T_CC_SAC_DATA_REQ || tag==T_CC_SAC_DATA_CNF);
2276
2277     offset_start = offset;
2278
2279     proto_tree_add_item(
2280             tree, hf_dvbci_cc_sys_id_bitmask, tvb, offset, 1, ENC_BIG_ENDIAN);
2281     offset++;
2282     snd_dat_nbr = tvb_get_guint8(tvb, offset);
2283     proto_tree_add_text(tree, tvb, offset, 1,
2284             "Number of sent data items: %d", snd_dat_nbr);
2285     offset++;
2286     for(i=0; i<snd_dat_nbr &&
2287             tvb_reported_length_remaining(tvb, offset)>0; i++) {
2288         item_len = dissect_cc_item(tvb, offset, pinfo, tree, &dat_id);
2289         if (item_len < 0)
2290             return -1;
2291         offset += item_len;
2292         /* for more than 8 sent datatype ids, some ids might get lost by
2293          * the shift, that's ok, we're only using the last 8 ids for
2294          * protocol detection */
2295         snd_dat_ids = snd_dat_ids<<8|dat_id;
2296         if (!exportable_flag || *exportable_flag==FALSE)
2297             continue;
2298         if (!is_cc_item_exportable(dat_id))
2299             *exportable_flag = FALSE;
2300     }
2301
2302     if (tag==T_CC_DATA_REQ || tag==T_CC_SAC_DATA_REQ) {
2303         req_dat_nbr = tvb_get_guint8(tvb, offset);
2304         proto_tree_add_text(tree, tvb, offset, 1,
2305                 "Number of requested data items: %d", req_dat_nbr);
2306         offset++;
2307         for(i=0; i<req_dat_nbr &&
2308                 tvb_reported_length_remaining(tvb, offset)>0; i++) {
2309             dat_id = tvb_get_guint8(tvb, offset);
2310             req_dat_ids = req_dat_ids<<8|dat_id;
2311             proto_tree_add_item(
2312                     tree, hf_dvbci_cc_dat_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2313             offset++;
2314         }
2315     }
2316
2317     add_cc_protocol_name_step(pinfo, snd_dat_ids, req_dat_ids);
2318
2319     return offset-offset_start;
2320 }
2321
2322
2323 #ifdef HAVE_LIBGCRYPT
2324 /* convert a 0-terminated preference key_string that contains a hex number
2325  *  into its binary representation
2326  * e.g. key_string "abcd" will be converted into two bytes 0xab, 0xcd
2327  * return the number of binary bytes or -1 for error */
2328 static gint
2329 pref_key_string_to_bin(const gchar *key_string, unsigned char **key_bin)
2330 {
2331     int  key_string_len;
2332     int  i, j;
2333     char input[3];
2334
2335     if (!key_string || !key_bin)
2336         return -1;
2337     key_string_len = (int)strlen(key_string);
2338     if (key_string_len != 2*AES_KEY_LEN)
2339         return -1;
2340     *key_bin = (unsigned char*)g_malloc(key_string_len/2);
2341     input[2] = '\0';
2342
2343     j=0;
2344     for (i=0; i<key_string_len-1; i+=2) {
2345         input[0] = key_string[0+i];
2346         input[1] = key_string[1+i];
2347         /* attention, brackets are required */
2348         (*key_bin)[j++] = (unsigned char)strtoul((const char*)&input, NULL, 16);
2349     }
2350
2351     return key_string_len/2;
2352 }
2353
2354
2355 static tvbuff_t *
2356 decrypt_sac_msg_body(
2357         guint8 enc_cip, tvbuff_t *encrypted_tvb, gint offset, gint len)
2358 {
2359     gboolean         opened = FALSE;
2360     gcry_cipher_hd_t cipher;
2361     gcry_error_t     err;
2362     gint             clear_len;
2363     unsigned char    *clear_data = NULL;
2364     tvbuff_t         *clear_tvb = NULL;
2365
2366     if (enc_cip != CC_SAC_ENC_AES128_CBC)
2367         goto end;
2368     if (len%AES_BLOCK_LEN != 0)
2369         goto end;
2370
2371     if (!dvbci_sek_bin || !dvbci_siv_bin)
2372         goto end;
2373
2374     err = gcry_cipher_open(&cipher, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
2375     if (gcry_err_code (err))
2376         goto end;
2377     opened = TRUE;
2378     err = gcry_cipher_setkey (cipher, dvbci_sek_bin, AES_KEY_LEN);
2379     if (gcry_err_code (err))
2380         goto end;
2381     err = gcry_cipher_setiv (cipher, dvbci_siv_bin, AES_BLOCK_LEN);
2382     if (gcry_err_code (err))
2383         goto end;
2384
2385     clear_len = len;
2386     clear_data = (unsigned char *)g_malloc(clear_len);
2387
2388     err = gcry_cipher_decrypt (cipher, clear_data, clear_len,
2389             tvb_memdup(wmem_packet_scope(), encrypted_tvb, offset, len), len);
2390     if (gcry_err_code (err))
2391         goto end;
2392
2393     clear_tvb = tvb_new_child_real_data(encrypted_tvb,
2394                         (const guint8 *)clear_data, clear_len, clear_len);
2395     tvb_set_free_cb(clear_tvb, g_free);
2396
2397 end:
2398     if (opened)
2399         gcry_cipher_close (cipher);
2400     if (!clear_tvb && clear_data)
2401        g_free(clear_data);
2402     return clear_tvb;
2403 }
2404
2405 #else
2406 /* HAVE_LIBGRYPT is not set */
2407 static gint
2408 pref_key_string_to_bin(const gchar *key_string _U_, unsigned char **key_bin _U_)
2409 {
2410     return 0;
2411 }
2412
2413 static tvbuff_t *
2414 decrypt_sac_msg_body(guint8 enc_cip _U_,
2415         tvbuff_t *encrypted_tvb _U_, gint offset _U_, gint len _U_)
2416 {
2417     return NULL;
2418 }
2419
2420 #endif
2421
2422
2423 /* dissect a text string that is encoded according to DVB-SI (EN 300 468) */
2424 static void
2425 dissect_si_string(tvbuff_t *tvb, gint offset, gint str_len,
2426         packet_info *pinfo, proto_tree *tree, int hf, const gchar *title,
2427         gboolean show_col_info)
2428 {
2429     guint           enc_len;
2430     dvb_encoding_e  encoding;
2431     guint8         *si_str = NULL;
2432
2433     if (!title)  /* we always have a title for our strings */
2434         return;
2435     /* str_len==-1 is not supported, we need an actual length */
2436     if (str_len<=0)
2437         return;
2438
2439     enc_len = dvb_analyze_string_charset(tvb, offset, str_len, &encoding);
2440     dvb_add_chartbl(tree, hf_dvbci_mmi_char_tbl, tvb, offset, enc_len, encoding);
2441
2442     offset += enc_len;
2443     str_len -= enc_len;
2444
2445     si_str = tvb_get_string_enc(wmem_packet_scope(),
2446             tvb, offset, str_len, dvb_enc_to_item_enc(encoding));
2447     if (!si_str)
2448         return;
2449
2450     proto_tree_add_string_format(tree, hf,
2451             tvb, offset, str_len, si_str, "%s: %s", title, si_str);
2452
2453     if (show_col_info)
2454         col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "%s", si_str);
2455 }
2456
2457
2458 /* dissect ca_enable_flag and ca_enable fields in the ca_pmt_reply
2459  * return true if descrambling is possible, false otherwise */
2460 static gboolean
2461 dissect_ca_enable(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2462         proto_tree *tree)
2463 {
2464     gboolean desc_ok = FALSE;
2465     guint8   byte, ca_enab;
2466
2467     byte = tvb_get_guint8(tvb,offset);
2468     proto_tree_add_item(tree, hf_dvbci_ca_enable_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
2469     if (byte&0x80) {
2470         ca_enab = byte & ~0x80;
2471         proto_tree_add_item(tree, hf_dvbci_ca_enable, tvb, offset, 1, ENC_BIG_ENDIAN);
2472         if (ca_enab==CA_ENAB_DESC_OK ||
2473             ca_enab==CA_ENAB_DESC_OK_PURCHASE ||
2474             ca_enab==CA_ENAB_DESC_OK_TECH) {
2475             desc_ok = TRUE;
2476         }
2477     }
2478
2479     return desc_ok;
2480 }
2481
2482
2483 /* dissect a ca descriptor in the ca_pmt */
2484 static gint
2485 dissect_ca_desc(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2486         proto_tree *tree)
2487 {
2488     gint        offset_start;
2489     guint8      tag, len_byte;
2490     proto_item *ti           = NULL;
2491     proto_tree *ca_desc_tree = NULL;
2492
2493     offset_start = offset;
2494
2495     tag = tvb_get_guint8(tvb,offset);
2496     if (tag != CA_DESC_TAG) {
2497         /* we could skip unknown descriptors and make this a warning */
2498         proto_tree_add_expert(tree, pinfo, &ei_dvbci_ca_pmt_cmd_id, tvb, offset, 1);
2499         return 0;
2500     }
2501
2502     ti = proto_tree_add_text(
2503             tree, tvb, offset_start, -1, "Conditional Access descriptor");
2504     ca_desc_tree = proto_item_add_subtree(ti, ett_dvbci_ca_desc);
2505     offset++;
2506
2507     len_byte = tvb_get_guint8(tvb,offset);
2508     proto_tree_add_item(
2509             ca_desc_tree, hf_dvbci_descr_len, tvb, offset, 1, ENC_BIG_ENDIAN);
2510     offset++;
2511
2512     proto_tree_add_item(
2513             ca_desc_tree, hf_dvbci_ca_sys_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2514     offset += 2;
2515
2516     proto_tree_add_item(
2517             ca_desc_tree, hf_dvbci_ca_pid, tvb, offset, 2, ENC_BIG_ENDIAN);
2518     offset += 2;
2519
2520     if ((len_byte-4) != 0) {
2521         proto_tree_add_text(
2522                 ca_desc_tree, tvb, offset, len_byte-4, "private data");
2523         offset += (len_byte-4);
2524     }
2525
2526     proto_item_set_len(ti, offset-offset_start);
2527     return offset-offset_start;
2528 }
2529
2530
2531 /* dissect an elementary stream entry in the ca_pmt */
2532 static gint
2533 dissect_es(tvbuff_t *tvb, gint offset,
2534         packet_info *pinfo, proto_tree *tree, gboolean *scrambled)
2535 {
2536     proto_item *ti      = NULL;
2537     proto_tree *es_tree = NULL;
2538     gint        offset_start, ca_desc_len;
2539     gint        es_info_len, all_len;
2540
2541     offset_start = offset;
2542
2543     if (scrambled) {
2544         /* default to free service until we found a ca descriptor
2545            (we could have es info len > 0 and no ca descriptors) */
2546         *scrambled = FALSE;
2547     }
2548
2549     ti = proto_tree_add_text(tree, tvb, offset_start, -1, "Elementary Stream");
2550     es_tree = proto_item_add_subtree(ti, ett_dvbci_application);
2551
2552     proto_tree_add_item(
2553             es_tree, hf_dvbci_stream_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2554     offset++;
2555     proto_tree_add_item(
2556             es_tree, hf_dvbci_es_pid, tvb, offset, 2, ENC_BIG_ENDIAN);
2557     offset += 2;
2558     es_info_len = tvb_get_ntohs(tvb, offset) & 0x0FFF;
2559     /* the definition of hf_dvbci_es_info_len also applies the mask */
2560     proto_tree_add_item(
2561             es_tree, hf_dvbci_es_info_len, tvb, offset, 2, ENC_BIG_ENDIAN);
2562     offset += 2;
2563     if (es_info_len>0) {
2564         all_len = offset + es_info_len;
2565
2566         proto_tree_add_item(
2567                 es_tree, hf_dvbci_ca_pmt_cmd_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2568         offset++;
2569         while (offset < all_len) {
2570             ca_desc_len = dissect_ca_desc(tvb, offset, pinfo, es_tree);
2571             if (ca_desc_len <= 0)
2572                 return -1;
2573             offset += ca_desc_len;
2574             if (scrambled)
2575                 *scrambled = TRUE;
2576         }
2577     }
2578     else {
2579         proto_tree_add_text(
2580                 es_tree, tvb, 0, 0,
2581                 "No CA descriptors for this elementary stream");
2582     }
2583
2584     proto_item_set_len(ti, offset-offset_start);
2585     return offset-offset_start;
2586 }
2587
2588 /* dissect a text pseudo-apdu */
2589 static gint
2590 dissect_dvbci_text(const gchar *title, tvbuff_t *tvb, gint offset,
2591                    packet_info *pinfo, proto_tree *tree, int hf)
2592 {
2593     proto_item *ti = NULL;
2594     proto_tree *text_tree;
2595     guint32     tag;
2596     gint        offset_start;
2597     gint        len_field;
2598
2599     offset_start = offset;
2600
2601     if (!title)
2602         return 0;
2603
2604     /* check the tag before setting up the tree */
2605     tag = tvb_get_ntoh24(tvb, offset);
2606     if (tag!=T_TEXT_LAST && tag!=T_TEXT_MORE)
2607         return 0;
2608
2609     ti = proto_tree_add_text(tree, tvb, offset_start, -1, "%s", title);
2610     text_tree = proto_item_add_subtree(ti, ett_dvbci_text);
2611
2612     proto_tree_add_item(text_tree, hf_dvbci_apdu_tag,
2613             tvb, offset, APDU_TAG_SIZE, ENC_BIG_ENDIAN);
2614     offset += APDU_TAG_SIZE;
2615     offset = dissect_ber_length(pinfo, text_tree, tvb, offset, &len_field, NULL);
2616     dissect_si_string(tvb, offset, len_field, pinfo, text_tree,
2617             hf, "Text", FALSE);
2618     offset += len_field;
2619
2620     proto_item_set_len(ti, offset-offset_start);
2621     return (offset-offset_start);
2622 }
2623
2624
2625 static proto_item *
2626 dissect_res_id(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2627         proto_tree *tree, guint32 res_id, gboolean show_col_info)
2628 {
2629     proto_item *ti       = NULL;
2630     proto_tree *res_tree = NULL;
2631     gint        tvb_data_len;
2632
2633     /* there's two possible inputs for this function
2634         the resource id is either in a tvbuff_t (tvb!=NULL, res_id==0)
2635         or in a guint32 (tvb==NULL, res_id!=0) */
2636
2637     if (tvb) {
2638         /* resource id comes in via tvbuff */
2639         if (res_id!=0)
2640             return NULL;
2641         res_id = tvb_get_ntohl(tvb, offset);
2642         tvb_data_len = RES_ID_LEN;
2643     }
2644     else {
2645         /* resource id comes in via guint32 */
2646         if (res_id==0)
2647             return NULL;
2648         /* we'll call proto_tree_add_...( tvb==NULL, offset==0, length==0 )
2649            this creates a filterable item without any reference to a tvb */
2650         offset = 0;
2651         tvb_data_len = 0;
2652     }
2653
2654     if (show_col_info) {
2655         col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s Version %d",
2656                 val_to_str_const(RES_CLASS(res_id), dvbci_res_class,
2657                     "Invalid Resource class"),
2658                 RES_VER(res_id));
2659     }
2660
2661     ti = proto_tree_add_text(tree, tvb, offset, tvb_data_len,
2662             "Resource ID: 0x%04x", res_id);
2663     res_tree = proto_item_add_subtree(ti, ett_dvbci_res);
2664
2665     /* parameter "value" == complete resource id,
2666        RES_..._MASK will be applied by the hf definition */
2667     proto_tree_add_uint(res_tree, hf_dvbci_res_id_type,
2668             tvb, offset, tvb_data_len, res_id);
2669     proto_tree_add_uint(res_tree, hf_dvbci_res_class,
2670             tvb, offset, tvb_data_len, res_id);
2671     proto_tree_add_uint(res_tree, hf_dvbci_res_type,
2672             tvb, offset, tvb_data_len, res_id);
2673     proto_tree_add_uint(res_tree, hf_dvbci_res_ver,
2674             tvb, offset, tvb_data_len, res_id);
2675
2676     return ti;
2677 }
2678
2679 /* dissect the body of a resource manager apdu */
2680 static void
2681 dissect_dvbci_payload_rm(guint32 tag, gint len_field,
2682         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
2683         packet_info *pinfo, proto_tree *tree)
2684 {
2685     const gchar *tag_str;
2686
2687     if (tag==T_PROFILE) {
2688         if (len_field % RES_ID_LEN) {
2689             tag_str = val_to_str(tag, dvbci_apdu_tag, "Unknown: %d");
2690             proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb, 0, APDU_TAG_SIZE,
2691                    "Invalid APDU length field, %s must be a multiple of 4 bytes",
2692                    tag_str);
2693             return;
2694         }
2695
2696         while (tvb_reported_length_remaining(tvb, offset) > 0) {
2697             dissect_res_id(tvb, offset, pinfo, tree, 0, FALSE);
2698             offset += RES_ID_LEN;
2699         }
2700     }
2701 }
2702
2703 static void
2704 dissect_dvbci_payload_ap(guint32 tag, gint len_field _U_,
2705         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
2706         packet_info *pinfo, proto_tree *tree)
2707 {
2708     guint8          menu_str_len;
2709     guint           enc_len;
2710     dvb_encoding_e  encoding;
2711     guint8         *menu_string;
2712     guint8          data_rate;
2713
2714     if (tag==T_APP_INFO) {
2715         proto_tree_add_item(tree, hf_dvbci_app_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2716         offset++;
2717         proto_tree_add_item(
2718                 tree, hf_dvbci_app_manf, tvb, offset, 2, ENC_BIG_ENDIAN);
2719         offset+=2;
2720         proto_tree_add_item(
2721                 tree, hf_dvbci_manf_code, tvb, offset, 2, ENC_BIG_ENDIAN);
2722         offset+=2;
2723         menu_str_len = tvb_get_guint8(tvb,offset);
2724         proto_tree_add_item(
2725                 tree, hf_dvbci_menu_str_len, tvb, offset, 1, ENC_BIG_ENDIAN);
2726         offset++;
2727         if (menu_str_len > 0) {
2728             enc_len = dvb_analyze_string_charset(
2729                     tvb, offset, menu_str_len, &encoding);
2730             dvb_add_chartbl(
2731                     tree, hf_dvbci_ap_char_tbl, tvb, offset, enc_len, encoding);
2732             offset += enc_len;
2733             menu_str_len -= enc_len;
2734             menu_string = tvb_get_string_enc(wmem_packet_scope(),
2735                     tvb, offset, menu_str_len, dvb_enc_to_item_enc(encoding));
2736             col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
2737                     "Module name %s", menu_string);
2738             proto_tree_add_string_format(tree, hf_dvbci_menu_str,
2739                     tvb, offset, menu_str_len, menu_string,
2740                     "Menu string: %s", menu_string);
2741         }
2742     }
2743     else if (tag== T_DATARATE_INFO) {
2744         data_rate = tvb_get_guint8(tvb, offset);
2745         col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s",
2746                     val_to_str(data_rate, dvbci_data_rate, "unknown (0x%x)"));
2747         proto_tree_add_item(tree, hf_dvbci_data_rate, tvb, offset, 1, ENC_BIG_ENDIAN);
2748     }
2749 }
2750
2751 static void
2752 dissect_dvbci_payload_ca(guint32 tag, gint len_field,
2753         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
2754         packet_info *pinfo, proto_tree *tree)
2755 {
2756     const gchar *tag_str;
2757     proto_item  *pi;
2758     guint16      prog_num;
2759     guint8       byte;
2760     guint        prog_info_len;
2761     gint         es_info_len, all_len;
2762     gint         ca_desc_len;
2763     gboolean     scrambled = FALSE;
2764     gboolean     es_scrambled = FALSE;
2765     proto_tree  *es_tree = NULL;
2766     gboolean     desc_ok = FALSE;
2767
2768
2769     if (tag==T_CA_INFO) {
2770         if (len_field % 2) {
2771             tag_str = val_to_str(tag, dvbci_apdu_tag, "Unknown: %d");
2772             proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb, 0, APDU_TAG_SIZE,
2773                     "Invalid APDU length field, %s must be a multiple of 2 bytes",
2774                     tag_str);
2775             return;
2776         }
2777
2778         while (tvb_reported_length_remaining(tvb, offset) > 0) {
2779             proto_tree_add_item(
2780                     tree, hf_dvbci_ca_sys_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2781             offset += 2;
2782         }
2783     }
2784     else if (tag==T_CA_PMT) {
2785         proto_tree_add_item(
2786                 tree, hf_dvbci_ca_pmt_list_mgmt, tvb, offset, 1, ENC_BIG_ENDIAN);
2787         offset++;
2788         prog_num = tvb_get_ntohs(tvb, offset);
2789         col_append_sep_fstr(
2790                 pinfo->cinfo, COL_INFO, NULL, "Program number %x", prog_num);
2791         proto_tree_add_item(
2792                 tree, hf_dvbci_prog_num, tvb, offset, 2, ENC_BIG_ENDIAN);
2793         offset += 2;
2794         byte = tvb_get_guint8(tvb,offset);
2795         proto_tree_add_text(tree, tvb, offset, 1,
2796                 "Version number: 0x%x, Current-next indicator: 0x%x",
2797                 (byte&0x3E) >> 1, byte&0x01);
2798         offset++;
2799         prog_info_len = tvb_get_ntohs(tvb, offset) & 0x0FFF;
2800         /* the definition of hf_dvbci_prog_info_len also applies the mask */
2801         proto_tree_add_item(
2802                 tree, hf_dvbci_prog_info_len, tvb, offset, 2, ENC_BIG_ENDIAN);
2803         offset += 2;
2804         if (prog_info_len != 0) {
2805             all_len = offset + prog_info_len;
2806
2807             proto_tree_add_item(
2808                     tree, hf_dvbci_ca_pmt_cmd_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2809             offset++;
2810             while (offset < all_len) {
2811                 ca_desc_len = dissect_ca_desc(tvb, offset, pinfo, tree);
2812                 if (ca_desc_len <= 0)
2813                     return;
2814                 offset += ca_desc_len;
2815                 /* set this only if we've seen at least one valid ca descriptor */
2816                 scrambled = TRUE;
2817             }
2818         }
2819         else {
2820             proto_tree_add_text(
2821                     tree, tvb, 0, 0, "No CA descriptors at program level");
2822         }
2823
2824         while (tvb_reported_length_remaining(tvb, offset) > 0) {
2825             es_info_len = dissect_es(tvb, offset, pinfo, tree, &es_scrambled);
2826             if (es_info_len <= 0)
2827                 return;
2828             offset += es_info_len;
2829             if (es_scrambled)
2830                 scrambled = TRUE;
2831         }
2832
2833         col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
2834                 scrambled ? "scrambled service" : "free service");
2835     }
2836     else if (tag==T_CA_PMT_REPLY) {
2837         prog_num = tvb_get_ntohs(tvb, offset);
2838         col_append_sep_fstr(
2839                 pinfo->cinfo, COL_INFO, NULL, "Program number %x", prog_num);
2840         proto_tree_add_item(
2841                 tree, hf_dvbci_prog_num, tvb, offset, 2, ENC_BIG_ENDIAN);
2842         offset += 2;
2843         byte = tvb_get_guint8(tvb,offset);
2844         proto_tree_add_text(tree, tvb, offset, 1,
2845                 "Version number: 0x%x, Current-next indicator: 0x%x",
2846                 (byte&0x3E) >> 1, byte&0x01);
2847         offset++;
2848         desc_ok |= dissect_ca_enable(tvb, offset, pinfo, tree);
2849         offset++;
2850         while (tvb_reported_length_remaining(tvb, offset) > 0) {
2851             /* there's no need to check for tree==NULL */
2852             pi = proto_tree_add_text(tree, tvb, offset, 3, "Elementary Stream");
2853             es_tree = proto_item_add_subtree(pi, ett_dvbci_application);
2854
2855             proto_tree_add_item(es_tree, hf_dvbci_es_pid,
2856                     tvb, offset, 2, ENC_BIG_ENDIAN);
2857             offset += 2;
2858             desc_ok |= dissect_ca_enable(tvb, offset, pinfo, es_tree);
2859             offset++;
2860         }
2861         if (desc_ok) {
2862             col_append_sep_fstr(
2863                 pinfo->cinfo, COL_INFO, NULL, "descrambling possible");
2864         }
2865      }
2866 }
2867
2868
2869 static void
2870 dissect_dvbci_payload_aut(guint32 tag, gint len_field _U_,
2871         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
2872         packet_info *pinfo _U_, proto_tree *tree)
2873 {
2874     gint bytes_len;
2875
2876     proto_tree_add_item(tree, hf_dvbci_auth_proto_id,
2877             tvb, offset, 2, ENC_BIG_ENDIAN);
2878     offset += 2;
2879
2880     bytes_len = tvb_reported_length_remaining(tvb, offset);
2881     if (bytes_len <= 0)
2882         return;
2883
2884     if (tag==T_AUTH_REQ) {
2885         proto_tree_add_item(tree, hf_dvbci_auth_req_bytes,
2886             tvb, offset, bytes_len, ENC_NA);
2887     }
2888     else if (tag==T_AUTH_RESP) {
2889         proto_tree_add_item(tree, hf_dvbci_auth_resp_bytes,
2890             tvb, offset, bytes_len, ENC_NA);
2891     }
2892 }
2893
2894
2895 static void
2896 dissect_dvbci_payload_hc(guint32 tag, gint len_field _U_,
2897         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
2898         packet_info *pinfo, proto_tree *tree)
2899 {
2900     proto_item *pi;
2901     guint16     nid, onid, tsid, svcid;
2902     guint8      ref;
2903     guint16     old_pid, new_pid;
2904     gboolean    pmt_flag;
2905     gint        desc_loop_len;
2906     tvbuff_t   *pmt_tvb = NULL;
2907     guint8      status;
2908
2909
2910     switch (tag) {
2911         case T_TUNE:
2912             nid = tvb_get_ntohs(tvb, offset);
2913             pi = proto_tree_add_item(
2914                     tree, hf_dvbci_network_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2915             if (nid) {
2916                 expert_add_info(pinfo, pi, &ei_dvbci_network_id);
2917             }
2918             offset += 2;
2919             onid = tvb_get_ntohs(tvb, offset);
2920             proto_tree_add_item(tree, hf_dvbci_original_network_id,
2921                     tvb, offset, 2, ENC_BIG_ENDIAN);
2922             offset += 2;
2923             tsid = tvb_get_ntohs(tvb, offset);
2924             proto_tree_add_item(tree, hf_dvbci_transport_stream_id,
2925                     tvb, offset, 2, ENC_BIG_ENDIAN);
2926             offset += 2;
2927             svcid = tvb_get_ntohs(tvb, offset);
2928             proto_tree_add_item(
2929                     tree, hf_dvbci_service_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2930             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
2931                     "nid 0x%x, onid 0x%x, tsid 0x%x, svcid 0x%x",
2932                     nid, onid, tsid, svcid);
2933             break;
2934         case T_REPLACE:
2935             ref = tvb_get_guint8(tvb, offset);
2936             proto_tree_add_item(tree, hf_dvbci_replacement_ref,
2937                     tvb, offset, 1, ENC_BIG_ENDIAN);
2938             offset++;
2939             old_pid = tvb_get_ntohs(tvb, offset) & 0x1FFF;
2940             proto_tree_add_item(tree, hf_dvbci_replaced_pid,
2941                     tvb, offset, 2, ENC_BIG_ENDIAN);
2942             offset += 2;
2943             new_pid = tvb_get_ntohs(tvb, offset) & 0x1FFF;
2944             proto_tree_add_item( tree, hf_dvbci_replacement_pid,
2945                     tvb, offset, 2, ENC_BIG_ENDIAN);
2946             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
2947                     "ref 0x%x, 0x%x -> 0x%x", ref, old_pid, new_pid);
2948             break;
2949         case T_CLEAR_REPLACE:
2950             ref = tvb_get_guint8(tvb, offset);
2951             proto_tree_add_item(tree, hf_dvbci_replacement_ref,
2952                     tvb, offset, 1, ENC_BIG_ENDIAN);
2953             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "ref 0x%x", ref);
2954             break;
2955         case T_TUNE_BROADCAST_REQ:
2956             pmt_flag = ((tvb_get_guint8(tvb, offset) & 0x01) == 0x01);
2957             proto_tree_add_item(tree, hf_dvbci_pmt_flag,
2958                     tvb, offset, 1, ENC_BIG_ENDIAN);
2959             offset++;
2960             proto_tree_add_item(
2961                     tree, hf_dvbci_service_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2962             offset += 2;
2963             desc_loop_len = dissect_desc_loop(hf_dvbci_hc_desc_loop_len,
2964                                 tvb, offset, pinfo, tree);
2965             if (desc_loop_len<0)
2966                 break;
2967             offset += desc_loop_len;
2968             if (pmt_flag) {
2969                 pmt_tvb = tvb_new_subset_remaining(tvb, offset);
2970                 if (mpeg_pmt_handle) {
2971                     col_append_str(pinfo->cinfo, COL_INFO, ", ");
2972                     /* prevent mpeg_pmt dissector from clearing col_info */
2973                     col_set_fence(pinfo->cinfo, COL_INFO);
2974                     call_dissector(mpeg_pmt_handle, pmt_tvb, pinfo, tree);
2975                 }
2976                 else
2977                     call_dissector(data_handle, pmt_tvb, pinfo, tree);
2978             }
2979             break;
2980         case T_TUNE_REPLY:
2981             status = tvb_get_guint8(tvb, offset);
2982             proto_tree_add_item(tree, hf_dvbci_hc_status,
2983                     tvb, offset, 1, ENC_BIG_ENDIAN);
2984             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
2985                         (status == HC_STAT_OK ?  "ok" : "error"));
2986             break;
2987         case T_ASK_RELEASE_REPLY:
2988             proto_tree_add_item(tree, hf_dvbci_hc_release_reply,
2989                     tvb, offset, 1, ENC_BIG_ENDIAN);
2990             break;
2991         default:
2992             break;
2993     }
2994 }
2995
2996
2997 static void
2998 dissect_dvbci_payload_dt(guint32 tag, gint len_field,
2999         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
3000         packet_info *pinfo, proto_tree *tree)
3001 {
3002     nstime_t     resp_intv;
3003     proto_item  *pi = NULL;
3004     const gchar *tag_str;
3005     gint         time_field_len;
3006     nstime_t     utc_time;
3007     gint16       local_offset;  /* field in the apdu */
3008
3009
3010     if (tag==T_DATE_TIME_ENQ) {
3011         nstime_set_zero(&resp_intv);
3012         resp_intv.secs = tvb_get_guint8(tvb, offset);
3013         pi = proto_tree_add_time(tree, hf_dvbci_resp_intv,
3014                 tvb, offset, 1, &resp_intv);
3015         if (resp_intv.secs==0) {
3016             col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "individual query");
3017             if (pi)
3018                 proto_item_append_text(pi, " (individual query)");
3019         }
3020         else {
3021             col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
3022                     "update every %s", rel_time_to_str(wmem_packet_scope(), &resp_intv));
3023         }
3024     }
3025     else if (tag==T_DATE_TIME) {
3026         if (len_field!=5 && len_field!=7) {
3027             tag_str = val_to_str_const(tag, dvbci_apdu_tag, "unknown");
3028             proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb, APDU_TAG_SIZE, offset-APDU_TAG_SIZE,
3029                     "Invalid APDU length field, %s must be 5 or 7 bytes", tag_str);
3030             return;
3031         }
3032
3033         time_field_len = packet_mpeg_sect_mjd_to_utc_time(tvb, offset, &utc_time);
3034         if (time_field_len<0) {
3035             proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb, offset, 5,
3036                 "Invalid UTC time field, 2 bytes MJD, 3 bytes BCD time hhmmss");
3037             return;
3038         }
3039         proto_tree_add_time(tree, hf_dvbci_utc_time,
3040                 tvb, offset, time_field_len, &utc_time);
3041         col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s UTC",
3042                 abs_time_to_str(wmem_packet_scope(), &utc_time, ABSOLUTE_TIME_UTC, FALSE));
3043         offset += time_field_len;
3044
3045         if (len_field==7) {
3046             local_offset = two_comp_to_int16(tvb_get_ntohs(tvb, offset));
3047             proto_tree_add_int_format(tree, hf_dvbci_local_offset,
3048                     tvb, offset, 2, local_offset,
3049                     "offset between UTC and local time is %d minutes",
3050                     local_offset);
3051         }
3052         else {
3053             proto_tree_add_text(tree, tvb, 0, 0,
3054                     "Offset between UTC and local time is unknown");
3055         }
3056     }
3057 }
3058
3059
3060 static void
3061 dissect_dvbci_payload_mmi(guint32 tag, gint len_field,
3062         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
3063         packet_info *pinfo, proto_tree *tree)
3064 {
3065     gint            offset_start;
3066     guint8          close_mmi_cmd_id;
3067     guint8          disp_ctl_cmd, disp_rep_id;
3068     const gchar    *disp_ctl_cmd_str = NULL, *disp_rep_id_str = NULL;
3069     gint            msg_len;
3070     guint           enc_len;
3071     dvb_encoding_e  encoding;
3072     guint8          ans_txt_len;
3073     guint8          ans_id;
3074     guint8          choice_or_item_nb;
3075     gint            text_len;
3076     guint8          choice_ref;
3077
3078
3079     offset_start = offset;
3080
3081     switch(tag) {
3082         case T_CLOSE_MMI:
3083             close_mmi_cmd_id = tvb_get_guint8(tvb,offset);
3084             proto_tree_add_item(tree, hf_dvbci_close_mmi_cmd_id,
3085                     tvb, offset, 1, ENC_BIG_ENDIAN);
3086             offset++;
3087             /* apdu layer len field checks are sufficient for "immediate" */
3088             if (close_mmi_cmd_id == CLOSE_MMI_CMD_ID_DELAY) {
3089                 if (len_field != 2) {
3090                     proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb,
3091                             APDU_TAG_SIZE, offset_start-APDU_TAG_SIZE,
3092                             "Length field must be 2");
3093                     return;
3094                 }
3095                 proto_tree_add_item(tree, hf_dvbci_close_mmi_delay, tvb,
3096                         offset, 1, ENC_BIG_ENDIAN);
3097             }
3098             break;
3099         case T_DISPLAY_CONTROL:
3100             disp_ctl_cmd = tvb_get_guint8(tvb,offset);
3101             disp_ctl_cmd_str = val_to_str_const(disp_ctl_cmd,
3102                                                 dvbci_disp_ctl_cmd, "unknown command");
3103             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
3104                     "%s", disp_ctl_cmd_str);
3105             proto_tree_add_item(tree, hf_dvbci_disp_ctl_cmd, tvb,
3106                     offset, 1, ENC_BIG_ENDIAN);
3107             offset++;
3108             if (disp_ctl_cmd == DISP_CMD_SET_MMI_MODE)
3109             {
3110                 proto_tree_add_item(tree, hf_dvbci_mmi_mode, tvb,
3111                         offset, 1, ENC_BIG_ENDIAN);
3112                 if (len_field != 2) {
3113                     proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb,
3114                             APDU_TAG_SIZE, offset_start-APDU_TAG_SIZE,
3115                             "Length field must be 2");
3116                     return;
3117                 }
3118             }
3119             break;
3120         case T_DISPLAY_REPLY:
3121             disp_rep_id = tvb_get_guint8(tvb,offset);
3122             disp_rep_id_str = val_to_str_const(disp_rep_id,
3123                     dvbci_disp_rep_id, "unknown command");
3124             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
3125                     "%s", disp_rep_id_str);
3126             proto_tree_add_item(tree, hf_dvbci_disp_rep_id,
3127                     tvb, offset, 1, ENC_BIG_ENDIAN);
3128             offset++;
3129             if (disp_rep_id == DISP_REP_ID_MMI_MODE_ACK) {
3130                 proto_tree_add_item(tree, hf_dvbci_mmi_mode,
3131                         tvb, offset, 1, ENC_BIG_ENDIAN);
3132             }
3133             else if (disp_rep_id == DISP_REP_ID_DISP_CHAR_TBL ||
3134                      disp_rep_id == DISP_REP_ID_INP_CHAR_TBL) {
3135                 while ((msg_len=tvb_reported_length_remaining(tvb, offset)) > 0) {
3136                     enc_len = dvb_analyze_string_charset(
3137                             tvb, offset, msg_len, &encoding);
3138                     if (enc_len==0) {
3139                         proto_tree_add_expert(tree, pinfo,
3140                             &ei_dvbci_invalid_char_tbl, tvb, offset, msg_len);
3141                         break;
3142                     }
3143                     dvb_add_chartbl(tree, hf_dvbci_mmi_char_tbl,
3144                             tvb, offset, enc_len, encoding);
3145                     offset += enc_len;
3146                  }
3147             }
3148             break;
3149         case T_ENQ:
3150             proto_tree_add_item(tree, hf_dvbci_blind_ans,
3151                     tvb, offset, 1, ENC_BIG_ENDIAN);
3152             offset++;
3153             ans_txt_len = tvb_get_guint8(tvb,offset);
3154             if (ans_txt_len == NB_UNKNOWN) {
3155                 proto_tree_add_text(tree, tvb, offset, 1,
3156                         "Length of expected answer is unknown");
3157             }
3158             else
3159                 proto_tree_add_item(tree, hf_dvbci_ans_txt_len,
3160                         tvb, offset, 1, ENC_BIG_ENDIAN);
3161             offset++;
3162             dissect_si_string(tvb, offset,
3163                     tvb_reported_length_remaining(tvb, offset),
3164                     pinfo, tree, hf_dvbci_enq, "Enquiry string", FALSE);
3165             break;
3166         case T_ANSW:
3167             ans_id = tvb_get_guint8(tvb,offset);
3168             proto_tree_add_item(tree, hf_dvbci_ans_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3169             offset++;
3170             if (ans_id == ANSW_ID_ANSWER) {
3171                 dissect_si_string(tvb, offset,
3172                     tvb_reported_length_remaining(tvb, offset),
3173                     pinfo, tree, hf_dvbci_ans, "Answer", TRUE);
3174             }
3175             break;
3176         case T_MENU_LAST:
3177         case T_MENU_MORE:
3178         case T_LIST_LAST:
3179         case T_LIST_MORE:
3180             choice_or_item_nb = tvb_get_guint8(tvb,offset);
3181             if (choice_or_item_nb == NB_UNKNOWN)
3182             {
3183                 proto_tree_add_text(tree, tvb, offset, 1,
3184                         "Number of items is unknown");
3185             }
3186             else
3187             {
3188                 if (IS_MENU_APDU(tag)) {
3189                     proto_tree_add_item(
3190                             tree, hf_dvbci_choice_nb, tvb, offset, 1, ENC_BIG_ENDIAN);
3191                 }
3192                 else {
3193                     proto_tree_add_item(
3194                             tree, hf_dvbci_item_nb, tvb, offset, 1, ENC_BIG_ENDIAN);
3195                 }
3196             }
3197             offset++;
3198             text_len = dissect_dvbci_text("Title", tvb, offset,
3199                     pinfo, tree, hf_dvbci_title);
3200             offset += text_len;
3201             text_len = dissect_dvbci_text("Sub-title", tvb, offset,
3202                     pinfo, tree, hf_dvbci_subtitle);
3203             offset += text_len;
3204             text_len = dissect_dvbci_text("Bottom line", tvb, offset,
3205                     pinfo, tree, hf_dvbci_bottom);
3206             offset += text_len;
3207             while (tvb_reported_length_remaining(tvb, offset) > 0) {
3208                 text_len = dissect_dvbci_text("Item", tvb, offset, pinfo, tree, hf_dvbci_item);
3209                 /* minimum is apdu tag + 1 byte len field */
3210                 if (text_len<APDU_TAG_SIZE+1) {
3211                     proto_tree_add_expert(tree, pinfo, &ei_dvbci_not_text_more_or_text_last, tvb, offset, -1);
3212                     return;
3213                 }
3214                 offset += text_len;
3215             }
3216             break;
3217         case T_MENU_ANSW:
3218             choice_ref = tvb_get_guint8(tvb,offset);
3219             if (choice_ref == 0x0) {
3220                 proto_tree_add_text(tree, tvb, offset, 1,
3221                         "Selection was cancelled.");
3222                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
3223                         "cancelled");
3224             }
3225             else {
3226                 proto_tree_add_item(
3227                         tree, hf_dvbci_choice_ref, tvb, offset, 1, ENC_BIG_ENDIAN);
3228                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
3229                         "Item %d", choice_ref);
3230             }
3231             break;
3232         default:
3233             break;
3234     }
3235 }
3236
3237
3238 static void
3239 dissect_dvbci_payload_hlc(guint32 tag, gint len_field _U_,
3240         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
3241         packet_info *pinfo, proto_tree *tree)
3242 {
3243   guint8 *str;
3244
3245   if (tag==T_HOST_COUNTRY) {
3246       proto_tree_add_item(tree, hf_dvbci_host_country,
3247               tvb, offset, tvb_reported_length_remaining(tvb, offset),
3248               ENC_ISO_8859_1|ENC_NA);
3249   }
3250   else if (tag==T_HOST_LANGUAGE) {
3251       proto_tree_add_item(tree, hf_dvbci_host_language,
3252               tvb, offset, tvb_reported_length_remaining(tvb, offset),
3253               ENC_ISO_8859_1|ENC_NA);
3254   }
3255
3256   /* both apdus' body is only a country code, this can be shared */
3257   str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset,
3258               tvb_reported_length_remaining(tvb, offset),
3259               ENC_ISO_8859_1|ENC_NA);
3260   if (str)
3261       col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s", str);
3262 }
3263
3264
3265 static void
3266 dissect_dvbci_payload_cup(guint32 tag, gint len_field _U_,
3267         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
3268         packet_info *pinfo, proto_tree *tree)
3269 {
3270   guint8      upgrade_type;
3271   guint16     download_time;
3272   guint8      answer, progress;
3273
3274   switch(tag) {
3275     case T_CAM_FIRMWARE_UPGRADE:
3276       upgrade_type = tvb_get_guint8(tvb, offset);
3277       proto_tree_add_item(tree, hf_dvbci_cup_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3278       col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)",
3279                     val_to_str_const(upgrade_type, dvbci_cup_type, "unknown"));
3280       offset++;
3281       download_time = tvb_get_ntohs(tvb, offset);
3282       if (download_time == 0) {
3283           proto_tree_add_uint_format(tree, hf_dvbci_cup_download_time,
3284                   tvb, offset, 2, download_time,
3285                   "estimated download time is unknown");
3286       }
3287       else {
3288           proto_tree_add_uint_format(tree, hf_dvbci_cup_download_time,
3289                   tvb, offset, 2, download_time,
3290                   "estimated download time is %d seconds",
3291                   download_time);
3292       }
3293       break;
3294     case T_CAM_FIRMWARE_UPGRADE_REPLY:
3295       answer = tvb_get_guint8(tvb, offset);
3296       proto_tree_add_item(tree, hf_dvbci_cup_answer, tvb, offset, 1, ENC_BIG_ENDIAN);
3297       col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s",
3298                     val_to_str_const(answer, dvbci_cup_answer, "unknown"));
3299       break;
3300     case T_CAM_FIRMWARE_UPGRADE_PROGRESS:
3301       progress = tvb_get_guint8(tvb, offset);
3302       if (progress > 100) {
3303         proto_tree_add_expert(tree, pinfo, &ei_dvbci_cup_progress, tvb, offset, 1);
3304       }
3305       else {
3306           col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%d%%", progress);
3307           proto_tree_add_uint_format(tree, hf_dvbci_cup_progress,
3308                   tvb, offset, 1, progress,
3309                   "download progress %d%%", progress);
3310       }
3311       break;
3312     case T_CAM_FIRMWARE_UPGRADE_COMPLETE:
3313       proto_tree_add_item(tree, hf_dvbci_cup_reset, tvb, offset, 1, ENC_BIG_ENDIAN);
3314       break;
3315     default:
3316       break;
3317   }
3318 }
3319
3320
3321 static void
3322 dissect_sac_msg(guint32 tag, tvbuff_t *tvb, gint offset,
3323         packet_info *pinfo, proto_tree *tree, gboolean exported)
3324 {
3325     gint        offset_start;
3326     guint32     msg_ctr;
3327     guint8      enc_flag, enc_cip;
3328     proto_item *enc_flag_pi, *ti;
3329     guint16     sac_payload_len;          /* payload data and padding */
3330     gint        sac_payload_data_len = 0; /* just payload data */
3331     tvbuff_t   *clear_sac_body_tvb;
3332     proto_tree *sac_tree             = NULL;
3333     gboolean    is_exportable        = FALSE;
3334
3335     offset_start = offset;
3336
3337     /* it's not useful to move sac header dissection to a separate
3338        function, we need enc/auth cipher etc here to handle the body */
3339     msg_ctr = tvb_get_ntohl(tvb, offset);
3340     proto_tree_add_item(tree, hf_dvbci_sac_msg_ctr,
3341             tvb, offset, 4, ENC_BIG_ENDIAN);
3342     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
3343             "message #%d", msg_ctr);
3344     offset += 4;
3345     proto_tree_add_item(tree, hf_dvbci_sac_proto_ver,
3346             tvb, offset, 1, ENC_BIG_ENDIAN);
3347     proto_tree_add_item(tree, hf_dvbci_sac_auth_cip,
3348             tvb, offset, 1, ENC_BIG_ENDIAN);
3349     enc_flag = tvb_get_guint8(tvb, offset) & 0x1;
3350     enc_flag_pi = proto_tree_add_item(tree, hf_dvbci_sac_payload_enc,
3351             tvb, offset, 1, ENC_BIG_ENDIAN);
3352     if (exported && enc_flag) {
3353         expert_add_info(pinfo, enc_flag_pi, &ei_dvbci_sac_payload_enc);
3354         enc_flag = 0;
3355     }
3356     offset++;
3357     enc_cip = (tvb_get_guint8(tvb, offset)&0xE0) >> 5;
3358     proto_tree_add_item(tree, hf_dvbci_sac_enc_cip,
3359             tvb, offset, 1, ENC_BIG_ENDIAN);
3360     offset++;
3361     sac_payload_len = tvb_get_ntohs(tvb, offset);
3362     proto_tree_add_item(tree, hf_dvbci_sac_payload_len,
3363             tvb, offset, 2, ENC_BIG_ENDIAN);
3364     offset += 2;
3365     if (tvb_reported_length_remaining(tvb, offset) < 0)
3366         return;
3367     if (enc_flag) {
3368         clear_sac_body_tvb = decrypt_sac_msg_body(enc_cip,
3369                 tvb, offset, tvb_reported_length_remaining(tvb, offset));
3370     }
3371     else {
3372         clear_sac_body_tvb = tvb_new_subset_remaining(tvb, offset);
3373     }
3374     if (!clear_sac_body_tvb) {
3375         /* we could not decrypt (or access) the clear sac message body */
3376         proto_tree_add_item(tree, hf_dvbci_sac_enc_body, tvb, offset,
3377                 tvb_reported_length_remaining(tvb, offset), ENC_NA);
3378         return;
3379     }
3380     if (enc_flag)
3381         add_new_data_source(pinfo, clear_sac_body_tvb, "Clear SAC message body");
3382     if (sac_payload_len>0) {
3383         ti = proto_tree_add_text(tree, clear_sac_body_tvb, 0, sac_payload_len,
3384                 "SAC message payload");
3385         sac_tree = proto_item_add_subtree(ti, ett_dvbci_sac_msg_body);
3386         if (tag==T_CC_SAC_DATA_REQ || tag==T_CC_SAC_DATA_CNF) {
3387             sac_payload_data_len = dissect_cc_data_payload(tag,
3388                     clear_sac_body_tvb, 0, pinfo, sac_tree, &is_exportable);
3389         }
3390         else if (tag==T_CC_SAC_SYNC_REQ) {
3391             sac_payload_data_len = 0;
3392         }
3393         else if (tag==T_CC_SAC_SYNC_CNF) {
3394             proto_tree_add_item(sac_tree, hf_dvbci_cc_status_field,
3395                     clear_sac_body_tvb, 0, 1, ENC_BIG_ENDIAN);
3396             sac_payload_data_len = 1;
3397         }
3398
3399         if (sac_payload_data_len < 0)
3400             return;
3401         if (sac_payload_len > sac_payload_data_len) {
3402             proto_tree_add_item(sac_tree, hf_dvbci_sac_padding,
3403                     clear_sac_body_tvb, sac_payload_data_len,
3404                     sac_payload_len-sac_payload_data_len, ENC_NA);
3405         }
3406     }
3407     proto_tree_add_item(tree, hf_dvbci_sac_signature,
3408             clear_sac_body_tvb, sac_payload_len,
3409             tvb_reported_length_remaining(clear_sac_body_tvb,
3410                 sac_payload_len), ENC_NA);
3411
3412     /* we call this function also to dissect exported SAC messages,
3413         dont' try to export them a second time */
3414     if (!exported && is_exportable && have_tap_listener(exported_pdu_tap)) {
3415
3416         tvbuff_t       *clear_sac_msg_tvb;
3417         exp_pdu_data_t *exp_pdu_data;
3418         guint8          tags[2];
3419
3420         clear_sac_msg_tvb = tvb_new_composite();
3421         tvb_composite_append(clear_sac_msg_tvb,
3422                 tvb_clone_offset_len(tvb, offset_start, SAC_MSG_HDR_LEN));
3423         tvb_composite_append(clear_sac_msg_tvb, clear_sac_body_tvb);
3424         tvb_composite_finalize(clear_sac_msg_tvb);
3425
3426         tags[0] = 0;
3427         tags[1] = EXP_PDU_TAG_DVBCI_EVT_BIT;
3428         exp_pdu_data = load_export_pdu_tags(
3429                 pinfo, EXPORTED_SAC_MSG_PROTO, -1, tags, 2);
3430
3431         exp_pdu_data->tvb_captured_length = tvb_captured_length(clear_sac_msg_tvb);
3432         exp_pdu_data->tvb_reported_length = tvb_reported_length(clear_sac_msg_tvb);
3433         exp_pdu_data->pdu_tvb = clear_sac_msg_tvb;
3434         tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
3435     }
3436 }
3437
3438
3439 static int
3440 dissect_dvbci_exported_sac_msg(
3441         tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3442 {
3443     guint8 evt;
3444     guint32 tag;
3445
3446     evt = dvbci_get_evt_from_addrs(pinfo);
3447     if (!IS_DATA_TRANSFER(evt))
3448         return 0;
3449
3450     col_append_sep_fstr(pinfo->cinfo, COL_PROTOCOL, NULL, EXPORTED_SAC_MSG_PROTO);
3451     col_clear(pinfo->cinfo, COL_INFO);
3452
3453     /* we only export cc_sac_data_req and _cnf, therefore, the tag can be
3454        derived from the direction of the transfer */
3455     if (evt== DVBCI_EVT_DATA_CAM_TO_HOST)
3456        tag = T_CC_SAC_DATA_REQ;
3457     else
3458        tag = T_CC_SAC_DATA_CNF;
3459
3460     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s",
3461             val_to_str_const(tag, dvbci_apdu_tag, "unknown"));
3462
3463     dissect_sac_msg(tag, tvb, 0, pinfo, tree, TRUE);
3464     return tvb_reported_length(tvb);
3465 }
3466
3467
3468 static void
3469 dissect_dvbci_payload_cc(guint32 tag, gint len_field _U_,
3470         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
3471         packet_info *pinfo, proto_tree *tree)
3472 {
3473     guint8      status;
3474     proto_item *pi;
3475     nstime_t    utc_time;
3476     guint8      pin_stat;
3477     guint8      evt_cent;
3478
3479     switch(tag) {
3480         case T_CC_OPEN_CNF:
3481             proto_tree_add_item(tree, hf_dvbci_cc_sys_id_bitmask,
3482                     tvb, offset, 1, ENC_BIG_ENDIAN);
3483             break;
3484         case T_CC_DATA_REQ:
3485         case T_CC_DATA_CNF:
3486             dissect_cc_data_payload(tag, tvb, offset, pinfo, tree, NULL);
3487             break;
3488         case T_CC_SYNC_CNF:
3489             status = tvb_get_guint8(tvb, offset);
3490             proto_tree_add_item(
3491                     tree, hf_dvbci_cc_status_field, tvb, offset, 1, ENC_BIG_ENDIAN);
3492             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s",
3493                     val_to_str_const(status, dvbci_cc_status, "unknown"));
3494             break;
3495         case T_CC_SAC_DATA_REQ:
3496         case T_CC_SAC_DATA_CNF:
3497         case T_CC_SAC_SYNC_REQ:
3498         case T_CC_SAC_SYNC_CNF:
3499             dissect_sac_msg(tag, tvb, offset, pinfo, tree, FALSE);
3500             break;
3501         case T_CC_PIN_CAPABILITIES_REPLY:
3502             proto_tree_add_item(tree, hf_dvbci_capability_field,
3503                     tvb, offset, 1 , ENC_BIG_ENDIAN);
3504             offset++;
3505             /* we can't packet_mpeg_sect_mjd_to_utc_time()
3506                and check with nstime_is_zero() */
3507             if (tvb_get_ntoh40(tvb, offset) == 0) {
3508                 proto_tree_add_text(tree, tvb, offset, UTC_TIME_LEN,
3509                         "CICAM PIN has never been changed");
3510             }
3511             else {
3512                 if (packet_mpeg_sect_mjd_to_utc_time(tvb, offset, &utc_time) < 0) {
3513                     proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb, offset, UTC_TIME_LEN,
3514                             "Invalid UTC time field, 2 bytes MJD, 3 bytes BCD time hhmmss");
3515                     break;
3516                 }
3517                 else {
3518                     /* abs_time_to_ep_str() never returns NULL */
3519                     proto_tree_add_time(tree, hf_dvbci_pin_chg_time,
3520                             tvb, offset, UTC_TIME_LEN, &utc_time);
3521                 }
3522             }
3523             offset += UTC_TIME_LEN;
3524             dissect_rating(tvb, offset, pinfo, tree);
3525             break;
3526         case T_CC_PIN_REPLY:
3527             pin_stat = tvb_get_guint8(tvb, offset);
3528             proto_tree_add_item(tree, hf_dvbci_pincode_status,
3529                     tvb, offset, 1, ENC_BIG_ENDIAN);
3530             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s",
3531                     val_to_str_const(pin_stat, dvbci_pincode_status, "unknown"));
3532             break;
3533         case T_CC_PIN_EVENT:
3534             proto_tree_add_item(tree, hf_dvbci_cc_prog_num,
3535                     tvb, offset, 2, ENC_BIG_ENDIAN);
3536             offset += 2;
3537             proto_tree_add_item(tree, hf_dvbci_pincode_status,
3538                     tvb, offset, 1, ENC_BIG_ENDIAN);
3539             offset++;
3540             dissect_rating(tvb, offset, pinfo, tree);
3541             offset++;
3542             if (packet_mpeg_sect_mjd_to_utc_time(tvb, offset, &utc_time) < 0) {
3543                 proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb, offset, UTC_TIME_LEN,
3544                         "Invalid UTC time field, 2 bytes MJD, 3 bytes BCD time hhmmss");
3545                 break;
3546             }
3547             else {
3548                 proto_tree_add_time(tree, hf_dvbci_pin_evt_time,
3549                         tvb, offset, UTC_TIME_LEN, &utc_time);
3550             }
3551             offset += UTC_TIME_LEN;
3552             evt_cent = tvb_get_guint8(tvb, offset);
3553             pi = proto_tree_add_item(tree, hf_dvbci_pin_evt_cent,
3554                     tvb, offset, 1, ENC_BIG_ENDIAN);
3555             if (evt_cent > 100) {
3556                 expert_add_info(pinfo, pi, &ei_dvbci_pin_evt_cent);
3557             }
3558             offset++;
3559             /* length field was already checked by the caller */
3560             proto_tree_add_item(tree, hf_dvbci_cc_priv_data, tvb, offset,
3561                     tvb_reported_length_remaining(tvb, offset), ENC_NA);
3562             break;
3563         case T_CC_PIN_PLAYBACK:
3564             dissect_rating(tvb, offset, pinfo, tree);
3565             offset++;
3566             /* length field was already checked by the caller */
3567             proto_tree_add_item(tree, hf_dvbci_cc_priv_data, tvb, offset,
3568                     tvb_reported_length_remaining(tvb, offset), ENC_NA);
3569             break;
3570         case T_CC_PIN_CMD:
3571         case T_CC_PIN_MMI_REQ:
3572             proto_tree_add_item(tree, hf_dvbci_pincode, tvb, offset,
3573                     tvb_reported_length_remaining(tvb, offset),
3574                     ENC_ASCII|ENC_NA);
3575             break;
3576         default:
3577             break;
3578     }
3579 }
3580
3581
3582 static void
3583 dissect_dvbci_ami_file_ack(tvbuff_t *tvb, gint offset,
3584         packet_info *pinfo, proto_tree *tree)
3585 {
3586     guint8      req_type;
3587     gboolean    req_ok = FALSE, file_ok;
3588     guint8      file_name_len;
3589     guint8     *file_name_str;
3590     guint32     file_data_len;
3591     tvbuff_t   *png_file_tvb = NULL;
3592     proto_item *ti;
3593     proto_tree *req_tree;
3594
3595     req_type = tvb_get_guint8(tvb, offset+1);
3596     if (req_type==REQ_TYPE_FILE_HASH) {
3597         req_ok = ((tvb_get_guint8(tvb, offset) & 0x02) == 0x02);
3598         proto_tree_add_item(tree, hf_dvbci_req_ok,
3599                 tvb, offset, 1, ENC_BIG_ENDIAN);
3600     }
3601     file_ok = ((tvb_get_guint8(tvb, offset) & 0x01) == 0x01);
3602     proto_tree_add_item(tree, hf_dvbci_file_ok, tvb, offset, 1, ENC_BIG_ENDIAN);
3603     offset++;
3604     proto_tree_add_item(tree, hf_dvbci_req_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3605     col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s",
3606             val_to_str_const(req_type, dvbci_req_type, "unknown"));
3607     offset++;
3608     if (req_type==REQ_TYPE_FILE || req_type==REQ_TYPE_FILE_HASH) {
3609         file_name_len = tvb_get_guint8(tvb, offset);
3610         proto_tree_add_text(tree, tvb, offset, 1,
3611                 "File name length %d", file_name_len);
3612         offset++;
3613         file_name_str = tvb_get_string_enc(wmem_packet_scope(),
3614                 tvb, offset, file_name_len, ENC_ASCII);
3615         if (!file_name_str)
3616             return;
3617         col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
3618                 "%s", file_name_str);
3619         proto_tree_add_string_format_value(tree, hf_dvbci_file_name,
3620                 tvb, offset, file_name_len, file_name_str,
3621                 "%s", file_name_str);
3622         offset += file_name_len;
3623         file_data_len = tvb_get_ntohl(tvb, offset);
3624         proto_tree_add_text(tree, tvb, offset, 4,
3625                 "File data length %d", file_data_len);
3626         offset += 4;
3627         if (file_data_len > 0) {
3628             if (file_name_len>4) {
3629                 gchar *suffix_lo;
3630                 suffix_lo = wmem_ascii_strdown(wmem_packet_scope(),
3631                         &file_name_str[file_name_len-4], -1);
3632                 if (g_strcmp0(suffix_lo, ".png")==0) {
3633                     png_file_tvb = tvb_new_subset_length(
3634                             tvb, offset, file_data_len);
3635                 }
3636             }
3637
3638             if (png_handle && png_file_tvb) {
3639                 col_set_fence(pinfo->cinfo, COL_PROTOCOL);
3640                 col_set_fence(pinfo->cinfo, COL_INFO);
3641                 call_dissector(png_handle, png_file_tvb, pinfo, tree);
3642             }
3643             else {
3644                 proto_tree_add_item(tree, hf_dvbci_file_data,
3645                         tvb, offset, file_data_len, ENC_NA);
3646             }
3647         }
3648     }
3649     else if (req_type==REQ_TYPE_DATA) {
3650         if (tvb_reported_length_remaining(tvb, offset) <= 0)
3651             return;
3652         proto_tree_add_item(tree, hf_dvbci_ami_priv_data, tvb, offset,
3653                 tvb_reported_length_remaining(tvb, offset), ENC_NA);
3654     }
3655     else if (req_type==REQ_TYPE_REQ) {
3656         ti = proto_tree_add_text(tree, tvb,
3657                 offset, tvb_reported_length_remaining(tvb, offset),
3658                 "Supported request types");
3659         req_tree = proto_item_add_subtree(
3660                 ti, ett_dvbci_ami_req_types);
3661         while (tvb_reported_length_remaining(tvb, offset) > 0) {
3662             proto_tree_add_item(req_tree, hf_dvbci_req_type,
3663                     tvb, offset, 1, ENC_BIG_ENDIAN);
3664             offset++;
3665         }
3666     }
3667
3668     if (req_type==REQ_TYPE_FILE_HASH && req_ok && !file_ok) {
3669         col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
3670                 "cached copy is valid");
3671     }
3672 }
3673
3674
3675 static void
3676 dissect_dvbci_payload_ami(guint32 tag, gint len_field _U_,
3677         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
3678         packet_info *pinfo, proto_tree *tree)
3679 {
3680     guint8  app_dom_id_len, init_obj_len;
3681     guint8 *app_dom_id;
3682     guint8  ack_code;
3683     guint8  req_type;
3684     guint8 *req_str;
3685
3686     switch(tag) {
3687         case T_REQUEST_START:
3688             /* no filter for length items */
3689             app_dom_id_len = tvb_get_guint8(tvb, offset);
3690             proto_tree_add_text(tree, tvb, offset, 1,
3691                     "Application Domain Identifier length %d", app_dom_id_len);
3692             offset++;
3693             init_obj_len = tvb_get_guint8(tvb, offset);
3694             proto_tree_add_text(tree, tvb, offset, 1,
3695                     "Initial Object length %d", init_obj_len);
3696             offset++;
3697             proto_tree_add_item(tree, hf_dvbci_app_dom_id,
3698                     tvb, offset, app_dom_id_len, ENC_ASCII|ENC_NA);
3699             app_dom_id = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, app_dom_id_len, ENC_ASCII);
3700             if (app_dom_id) {
3701                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ",
3702                         "for %s", app_dom_id);
3703             }
3704             offset += app_dom_id_len;
3705             proto_tree_add_item(tree, hf_dvbci_init_obj,
3706                     tvb, offset, init_obj_len, ENC_ASCII|ENC_NA);
3707             break;
3708         case T_REQUEST_START_ACK:
3709             ack_code = tvb_get_guint8(tvb, offset);
3710             proto_tree_add_item(
3711                     tree, hf_dvbci_ack_code, tvb, offset, 1, ENC_BIG_ENDIAN);
3712             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s",
3713                     val_to_str_const(ack_code, dvbci_ack_code, "unknown"));
3714             break;
3715         case T_FILE_REQUEST:
3716             req_type = tvb_get_guint8(tvb, offset);
3717             proto_tree_add_item(tree, hf_dvbci_req_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3718             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s",
3719                     val_to_str_const(req_type, dvbci_req_type, "unknown"));
3720             offset++;
3721             if (req_type==REQ_TYPE_FILE_HASH) {
3722                 proto_tree_add_item(tree, hf_dvbci_file_hash,
3723                         tvb, offset, 16, ENC_NA);
3724                 offset += 16;
3725             }
3726             if (tvb_reported_length_remaining(tvb, offset) <= 0)
3727               break;
3728             if (req_type==REQ_TYPE_FILE || req_type==REQ_TYPE_FILE_HASH) {
3729                 req_str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset,
3730                         tvb_reported_length_remaining(tvb, offset), ENC_ASCII);
3731                 if (!req_str)
3732                     break;
3733                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "%s", req_str);
3734                 proto_tree_add_string_format_value(tree, hf_dvbci_file_name,
3735                         tvb, offset, tvb_reported_length_remaining(tvb, offset),
3736                         req_str, "%s", req_str);
3737             }
3738             else if (req_type==REQ_TYPE_DATA) {
3739                 proto_tree_add_item(tree, hf_dvbci_ami_priv_data, tvb, offset,
3740                         tvb_reported_length_remaining(tvb, offset), ENC_NA);
3741             }
3742             break;
3743         case T_FILE_ACKNOWLEDGE:
3744             dissect_dvbci_ami_file_ack(tvb, offset, pinfo, tree);
3745             break;
3746         case T_APP_ABORT_REQUEST:
3747             if (tvb_reported_length_remaining(tvb, offset) > 0) {
3748                 proto_tree_add_item(tree, hf_dvbci_abort_req_code, tvb, offset,
3749                         tvb_reported_length_remaining(tvb, offset), ENC_NA);
3750             }
3751             break;
3752         case T_APP_ABORT_ACK:
3753             if (tvb_reported_length_remaining(tvb, offset) > 0) {
3754                 proto_tree_add_item(tree, hf_dvbci_abort_ack_code, tvb, offset,
3755                         tvb_reported_length_remaining(tvb, offset), ENC_NA);
3756             }
3757             break;
3758         default:
3759             break;
3760     }
3761 }
3762
3763
3764 static void
3765 dissect_dvbci_payload_lsc(guint32 tag, gint len_field,
3766         tvbuff_t *tvb, gint offset, circuit_t *circuit,
3767         packet_info *pinfo, proto_tree *tree)
3768 {
3769     gint                offset_start;
3770     guint8              id, timeout, ret_val, phase_id;
3771     gint                conn_desc_len, param_len;
3772     guint16             buf_size;
3773     proto_item         *pi          = NULL;
3774     const gchar        *ret_val_str = NULL;
3775     gint                msg_len;
3776     tvbuff_t           *msg_tvb;
3777     dissector_handle_t  msg_handle;
3778
3779     offset_start = offset;
3780
3781     switch(tag) {
3782         case T_COMMS_CMD:
3783             proto_tree_add_item(tree, hf_dvbci_comms_cmd_id,
3784                     tvb, offset, 1, ENC_BIG_ENDIAN);
3785             id = tvb_get_guint8(tvb, offset);
3786             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s",
3787                     val_to_str(id, dvbci_comms_cmd_id, "Unknown: %d"));
3788             offset++;
3789             switch(id) {
3790                 case COMMS_CMD_ID_CONNECT_ON_CHANNEL:
3791                     conn_desc_len = dissect_conn_desc(tvb, offset,
3792                             circuit, pinfo, tree);
3793                     if (conn_desc_len < 0)
3794                         break;
3795                     offset += conn_desc_len;
3796                     proto_tree_add_item(tree, hf_dvbci_lsc_retry_count,
3797                             tvb, offset, 1, ENC_BIG_ENDIAN);
3798                     offset++;
3799                     timeout = tvb_get_guint8(tvb, offset);
3800                     if (timeout==0) {
3801                         proto_tree_add_uint_format(tree, hf_dvbci_lsc_timeout,
3802                                 tvb, offset, 1, timeout, "Infinite timeout");
3803                     } else {
3804                         proto_tree_add_uint_format(tree, hf_dvbci_lsc_timeout,
3805                                 tvb, offset, 1, timeout,
3806                                 "Timeout is %d seconds", timeout);
3807                     }
3808                     break;
3809                 case COMMS_CMD_ID_DISCONNECT_ON_CHANNEL:
3810                 case COMMS_CMD_ID_ENQUIRE_STATUS:
3811                     /* len_field == 1 -> only id, no further parameters */
3812                     if (len_field != 1) {
3813                         proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb,
3814                             APDU_TAG_SIZE, offset_start-APDU_TAG_SIZE,
3815                             "Length field must be 1");
3816                     }
3817                     break;
3818                 case COMMS_CMD_ID_SET_PARAMS:
3819                     param_len = tvb_reported_length_remaining(tvb, offset);
3820                     if (param_len == 2)
3821                         buf_size = (guint16)tvb_get_guint8(tvb, offset);
3822                     else if (param_len == 3)
3823                         buf_size = tvb_get_ntohs(tvb, offset);
3824                     else {
3825                         /* length field == 1 byte id + param_len */
3826                         proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb,
3827                             APDU_TAG_SIZE, offset_start-APDU_TAG_SIZE,
3828                             "Length field must be 3 or 4");
3829                         break;
3830                     }
3831                     proto_tree_add_uint_format(tree, hf_dvbci_lsc_buf_size,
3832                             tvb, offset, param_len-1, buf_size,
3833                             "buffer size %d bytes", buf_size);
3834                     offset += param_len-1;
3835                     timeout = tvb_get_guint8(tvb, offset);
3836                     proto_tree_add_uint_format(tree, hf_dvbci_lsc_timeout,
3837                             tvb, offset, 1, timeout,
3838                             "timeout is %d milliseconds", timeout*10);
3839                     break;
3840                 case COMMS_CMD_ID_GET_NEXT_BUFFER:
3841                     phase_id = tvb_get_guint8(tvb, offset);
3842                     proto_tree_add_item(tree, hf_dvbci_phase_id, 
3843                             tvb, offset, 1, ENC_BIG_ENDIAN);
3844                     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
3845                             "received #%d", phase_id);
3846                     break;
3847                 default:
3848                     break;
3849             }
3850             break;
3851         case T_COMMS_REPLY:
3852             proto_tree_add_item(tree, hf_dvbci_comms_rep_id,
3853                     tvb, offset, 1, ENC_BIG_ENDIAN);
3854             id = tvb_get_guint8(tvb,offset);
3855             col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s",
3856                     val_to_str(id, dvbci_comms_rep_id, "Unknown: %d"));
3857             offset++;
3858             ret_val = tvb_get_guint8(tvb,offset);
3859             pi = proto_tree_add_item(tree, hf_dvbci_lsc_ret_val,
3860                     tvb, offset, 1, ENC_BIG_ENDIAN);
3861             switch (id) {
3862                 case COMMS_REP_ID_SEND_ACK:
3863                     col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
3864                         "sent #%d", ret_val);
3865                     if (pi)
3866                         proto_item_append_text(pi, " (sent #%d)", ret_val);
3867                     break;
3868                 case COMMS_REP_ID_SET_PARAMS_ACK:
3869                     ret_val_str = val_to_str_const(ret_val,
3870                             dvbci_lsc_ret_val_params, "unknown/error");
3871                     break;
3872                 case COMMS_REP_ID_STATUS_REPLY:
3873                     ret_val_str = val_to_str_const(ret_val,
3874                             dvbci_lsc_ret_val_connect, "unknown/error");
3875                     break;
3876                 default:
3877                     ret_val_str = val_to_str_const(ret_val,
3878                             dvbci_lsc_ret_val, "unknown/error");
3879                     break;
3880             }
3881             if (ret_val_str) {
3882                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
3883                             "%s", ret_val_str);
3884                 if (pi)
3885                     proto_item_append_text(pi, " (%s)", ret_val_str);
3886             }
3887             break;
3888         case T_COMMS_SEND_LAST:
3889         case T_COMMS_SEND_MORE:
3890         case T_COMMS_RCV_LAST:
3891         case T_COMMS_RCV_MORE:
3892             phase_id = tvb_get_guint8(tvb, offset);
3893             proto_tree_add_item(tree, hf_dvbci_phase_id,
3894                     tvb, offset, 1, ENC_BIG_ENDIAN);
3895             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
3896                     "Phase ID %d", phase_id);
3897             offset++;
3898             msg_len = tvb_reported_length_remaining(tvb, offset);
3899             if (msg_len<=0)
3900                 break;
3901             msg_tvb = tvb_new_subset_remaining(tvb, offset);
3902             if (!msg_tvb)
3903                 break;
3904             if (dvbci_dissect_lsc_msg && circuit && circuit->dissector_handle) {
3905                 msg_handle = circuit->dissector_handle;
3906                 col_append_str(pinfo->cinfo, COL_INFO, ", ");
3907                 col_set_fence(pinfo->cinfo, COL_INFO);
3908                 col_append_str(pinfo->cinfo, COL_PROTOCOL, ", ");
3909                 col_set_fence(pinfo->cinfo, COL_PROTOCOL);
3910             }
3911             else {
3912                 msg_handle = data_handle;
3913             }
3914             if (msg_handle)
3915                 call_dissector(msg_handle, msg_tvb, pinfo, tree);
3916             break;
3917         default:
3918             break;
3919     }
3920 }
3921
3922
3923 static void
3924 dissect_dvbci_payload_opp(guint32 tag, gint len_field _U_,
3925         tvbuff_t *tvb, gint offset, circuit_t *circuit _U_,
3926         packet_info *pinfo, proto_tree *tree)
3927 {
3928     guint16         nit_loop_len, nit_loop_offset;
3929     tvbuff_t       *nit_loop_tvb, *nit_loop_partial_tvb;
3930     guint           dvb_nit_bytes;
3931     guint8          table_id;
3932     guint8          cap_loop_len;
3933     gboolean        info_valid;
3934     guint           enc_len;
3935     dvb_encoding_e  encoding;
3936     guint8          desc_num;
3937     guint8          sig_strength, sig_qual;
3938     proto_item     *pi;
3939
3940     switch(tag) {
3941         case T_OPERATOR_STATUS:
3942         case T_OPERATOR_SEARCH_STATUS:
3943             dissect_opp_status_body(tvb, offset, pinfo, tree);
3944           break;
3945         case T_OPERATOR_NIT:
3946           nit_loop_len = tvb_get_ntohs(tvb, offset);
3947           proto_tree_add_item(tree, hf_dvbci_nit_loop_len,
3948                   tvb, offset, 2, ENC_BIG_ENDIAN);
3949           if (nit_loop_len==0)
3950               break;
3951           offset += 2;
3952           nit_loop_tvb = tvb_new_subset_length(
3953                   tvb, offset, nit_loop_len);
3954           nit_loop_offset = 0;
3955           if (!dvb_nit_handle) {
3956               call_dissector(data_handle, nit_loop_tvb, pinfo, tree);
3957               break;
3958           }
3959           /* prevent dvb_nit dissector from clearing the dvb-ci infos */
3960           col_append_str(pinfo->cinfo, COL_INFO, ", ");
3961           col_set_fence(pinfo->cinfo, COL_INFO);
3962           do {
3963               table_id = tvb_get_guint8(nit_loop_tvb, nit_loop_offset);
3964               if (table_id != TABLE_ID_CICAM_NIT) {
3965                   proto_tree_add_expert(tree, pinfo, &ei_dvbci_cicam_nit_table_id,
3966                           nit_loop_tvb, nit_loop_offset, 1);
3967               }
3968               nit_loop_partial_tvb =
3969                   tvb_new_subset_remaining(nit_loop_tvb, nit_loop_offset);
3970               dvb_nit_bytes = call_dissector(
3971                       dvb_nit_handle, nit_loop_partial_tvb, pinfo, tree);
3972               nit_loop_offset += dvb_nit_bytes;
3973               /* offsets go from 0 to nit_loop_len-1 */
3974           } while (dvb_nit_bytes>0 && nit_loop_offset<nit_loop_len-1);
3975           break;
3976         case T_OPERATOR_INFO:
3977           info_valid = ((tvb_get_guint8(tvb, offset) & 0x08) == 0x08);
3978           proto_tree_add_item(tree, hf_dvbci_info_valid,
3979                   tvb, offset, 1, ENC_BIG_ENDIAN);
3980           proto_tree_add_item(tree, hf_dvbci_info_ver_op_info,
3981                   tvb, offset, 1, ENC_BIG_ENDIAN);
3982           if (!info_valid)
3983               break;
3984           offset++;
3985           proto_tree_add_item(tree, hf_dvbci_cicam_onid,
3986                   tvb, offset, 2, ENC_BIG_ENDIAN);
3987           offset += 2;
3988           proto_tree_add_item(tree, hf_dvbci_cicam_id,
3989                   tvb, offset, 4, ENC_BIG_ENDIAN);
3990           offset += 4;
3991
3992           enc_len = dvb_analyze_string_charset(tvb, offset,
3993                   tvb_reported_length_remaining(tvb, offset), &encoding);
3994           if (enc_len==0) {
3995               proto_tree_add_expert(tree, pinfo,
3996                       &ei_dvbci_invalid_char_tbl, tvb, offset,
3997                       tvb_reported_length_remaining(tvb, offset));
3998               break;
3999           }
4000           dvb_add_chartbl(tree, hf_dvbci_opp_char_tbl,
4001                   tvb, offset, enc_len, encoding);
4002           offset += enc_len;
4003
4004           proto_tree_add_item(tree, hf_dvbci_sdt_rst_trusted,
4005                   tvb, offset, 1, ENC_BIG_ENDIAN);
4006           proto_tree_add_item(tree, hf_dvbci_eit_rst_trusted,
4007                   tvb, offset, 1, ENC_BIG_ENDIAN);
4008           proto_tree_add_item(tree, hf_dvbci_eit_pf_usage,
4009                   tvb, offset, 1, ENC_BIG_ENDIAN);
4010           proto_tree_add_item(tree, hf_dvbci_eit_sch_usage,
4011                   tvb, offset, 1, ENC_BIG_ENDIAN);
4012           proto_tree_add_item(tree, hf_dvbci_ext_evt_usage,
4013                   tvb, offset, 1, ENC_BIG_ENDIAN);
4014           offset++;
4015           proto_tree_add_item(tree, hf_dvbci_sdt_oth_trusted,
4016                   tvb, offset, 1, ENC_BIG_ENDIAN);
4017           proto_tree_add_item(tree, hf_dvbci_eit_evt_trigger,
4018                   tvb, offset, 1, ENC_BIG_ENDIAN);
4019           offset++;
4020           proto_tree_add_item(tree, hf_dvbci_opp_lang_code,
4021                   tvb, offset, 3, ENC_ASCII|ENC_NA);
4022           offset += 3;
4023           /* hf_dvbci_prof_name is an FT_UINT_STRING, one leading len byte */
4024           proto_tree_add_item(tree, hf_dvbci_prof_name,
4025               tvb, offset, 1, ENC_ASCII|ENC_NA);
4026           break;
4027         case T_OPERATOR_SEARCH_START:
4028           proto_tree_add_item(tree, hf_dvbci_unattended,
4029                   tvb, offset, 1, ENC_BIG_ENDIAN);
4030
4031           /* no filters for the loop lengths, one is 7bit, others are 8bit */
4032           cap_loop_len = tvb_get_guint8(tvb, offset) & 0x7F;
4033           proto_tree_add_text(tree, tvb, offset, 1,
4034                   "Service type loop length: %d", cap_loop_len);
4035           offset++;
4036           /* no need for error checking, we continue anyway */
4037           dissect_opp_cap_loop(cap_loop_len, "Service type loop",
4038                   hf_dvbci_opp_srv_type, 1, tvb, offset, pinfo, tree);
4039           offset += cap_loop_len;
4040
4041           cap_loop_len = tvb_get_guint8(tvb, offset);
4042           proto_tree_add_text(tree, tvb, offset, 1,
4043                   "Delivery system capabilities loop length: %d",
4044                   cap_loop_len);
4045           offset++;
4046           /* XXX - handle multi-byte delivery capabilities */
4047           dissect_opp_cap_loop(cap_loop_len,
4048                   "Delivery system capabilities loop",
4049                   hf_dvbci_dlv_cap_byte, 1,
4050                   tvb, offset, pinfo, tree);
4051           offset += cap_loop_len;
4052
4053           cap_loop_len = tvb_get_guint8(tvb, offset);
4054           proto_tree_add_text(tree, tvb, offset, 1,
4055                   "Application capabilities loop length: %d", cap_loop_len);
4056           offset++;
4057           dissect_opp_cap_loop(cap_loop_len,
4058                   "Application capabilities loop",
4059                   hf_dvbci_app_cap_bytes, 2,
4060                   tvb, offset, pinfo, tree);
4061           break;
4062         case T_OPERATOR_TUNE_STATUS:
4063           desc_num = tvb_get_guint8(tvb, offset);
4064           pi = proto_tree_add_item(tree, hf_dvbci_desc_num,
4065                   tvb, offset, 1, ENC_BIG_ENDIAN);
4066           if (desc_num==OPP_NO_MORE_DESC)
4067               proto_item_append_text(pi, " (all descriptors were processed)");
4068           offset++;
4069           sig_strength = tvb_get_guint8(tvb, offset);
4070           proto_tree_add_item(tree, hf_dvbci_sig_strength,
4071                   tvb, offset, 1, ENC_BIG_ENDIAN);
4072           offset++;
4073           sig_qual = tvb_get_guint8(tvb, offset);
4074           proto_tree_add_item(tree, hf_dvbci_sig_qual,
4075                   tvb, offset, 1, ENC_BIG_ENDIAN);
4076           if (sig_strength>100 || sig_qual>100) {
4077               pi = proto_tree_add_text(tree, tvb, offset, 1,
4078                       "Invalid value for signal strength / signal quality");
4079               expert_add_info(pinfo, pi, &ei_dvbci_sig_qual);
4080           }
4081           offset++;
4082           proto_tree_add_item(tree, hf_dvbci_opp_tune_status,
4083                   tvb, offset, 1, ENC_BIG_ENDIAN);
4084           dissect_desc_loop(hf_dvbci_opp_desc_loop_len,
4085                   tvb, offset, pinfo, tree);
4086           break;
4087         case T_OPERATOR_TUNE:
4088           dissect_desc_loop(hf_dvbci_opp_desc_loop_len,
4089                   tvb, offset, pinfo, tree);
4090           break;
4091         default:
4092           break;
4093     }
4094 }
4095
4096
4097 static void
4098 dissect_dvbci_payload_sas(guint32 tag, gint len_field _U_,
4099         tvbuff_t *tvb, gint offset, circuit_t *circuit,
4100         packet_info *pinfo, proto_tree *tree)
4101 {
4102     gchar   app_id_str[2+16+1]; /* "0x", string of 16 hex digits, trailing 0 */
4103     guint8  sas_status;
4104     dissector_handle_t msg_handle;
4105     guint8  msg_nb;
4106     guint16 msg_len;
4107     tvbuff_t *msg_tvb;
4108
4109     switch(tag) {
4110         case T_SAS_CONNECT_RQST:
4111         case T_SAS_CONNECT_CNF:
4112             g_snprintf(app_id_str, sizeof(app_id_str),
4113                     "0x%016" G_GINT64_MODIFIER "x", tvb_get_ntoh64(tvb, offset));
4114             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s", app_id_str);
4115             proto_tree_add_item(tree, hf_dvbci_sas_app_id,
4116                     tvb, offset, 8, ENC_BIG_ENDIAN);
4117             offset += 8;
4118             if (tag == T_SAS_CONNECT_CNF) {
4119                 sas_status = tvb_get_guint8(tvb, offset);
4120                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
4121                         (sas_status == SAS_SESS_STATE_CONNECTED ?
4122                          "Ok" : "Error"));
4123                 proto_tree_add_item(tree, hf_dvbci_sas_sess_state,
4124                         tvb, offset, 1, ENC_BIG_ENDIAN);
4125                 if (!circuit)
4126                     break;
4127                 if (sas_status == SAS_SESS_STATE_CONNECTED) {
4128                     msg_handle = dissector_get_string_handle(
4129                             sas_msg_dissector_table, app_id_str);
4130                     /* this clears the dissector for msg_handle==NULL */
4131                     circuit_set_dissector(circuit, msg_handle);
4132                 }
4133                 else
4134                     circuit_set_dissector(circuit, NULL);
4135             }
4136             break;
4137         case T_SAS_ASYNC_MSG:
4138             msg_nb = tvb_get_guint8(tvb, offset);
4139             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
4140                     "Message #%d ", msg_nb);
4141             proto_tree_add_item(tree, hf_dvbci_sas_msg_nb,
4142                     tvb, offset, 1, ENC_BIG_ENDIAN);
4143             offset++;
4144             msg_len = tvb_get_ntohs(tvb, offset);
4145             proto_tree_add_item(tree, hf_dvbci_sas_msg_len,
4146                     tvb, offset, 2, ENC_BIG_ENDIAN);
4147             offset += 2;
4148             msg_tvb = tvb_new_subset_length(tvb, offset, msg_len);
4149             msg_handle = (circuit && circuit->dissector_handle) ?
4150                 circuit->dissector_handle : data_handle;
4151             call_dissector(msg_handle, msg_tvb, pinfo, tree);
4152             break;
4153         default:
4154           break;
4155     }
4156 }
4157
4158
4159 static void
4160 dissect_dvbci_apdu(tvbuff_t *tvb, circuit_t *circuit,
4161         packet_info *pinfo, proto_tree *tree, guint8 direction)
4162 {
4163     proto_item  *ti;
4164     proto_tree  *app_tree;
4165     guint32      apdu_len, tag, len_field;
4166     const gchar *tag_str;
4167     gint         offset;
4168     proto_item  *pi;
4169     apdu_info_t *ai;
4170     guint32      apdu_res_id;
4171     const gchar *ai_res_class_str;
4172
4173
4174     apdu_len = tvb_reported_length(tvb);
4175
4176     ti = proto_tree_add_text(tree, tvb, 0, apdu_len, "Application Layer");
4177     app_tree = proto_item_add_subtree(ti, ett_dvbci_application);
4178
4179     tag = tvb_get_ntoh24(tvb, 0);
4180     tag_str = try_val_to_str(tag, dvbci_apdu_tag);
4181     offset = APDU_TAG_SIZE;
4182
4183     col_set_str(pinfo->cinfo, COL_INFO,
4184             val_to_str_const(tag, dvbci_apdu_tag, "Unknown/invalid APDU"));
4185     pi = proto_tree_add_item(
4186                 app_tree, hf_dvbci_apdu_tag, tvb, 0, APDU_TAG_SIZE, ENC_BIG_ENDIAN);
4187     if (tag_str == NULL) {
4188         expert_add_info(pinfo, pi, &ei_dvbci_apdu_tag);
4189         return;
4190     }
4191
4192     offset = dissect_ber_length(pinfo, app_tree, tvb, offset, &len_field, NULL);
4193     if ((offset+len_field) != apdu_len) {
4194         proto_tree_add_expert_format(app_tree, pinfo, &ei_dvbci_bad_length, tvb,
4195                 APDU_TAG_SIZE, offset-APDU_TAG_SIZE,
4196                 "Length field is different from the number of apdu payload bytes");
4197         /* we need len_field bytes of apdu payload to call
4198            ai->dissect_payload() and continue dissecting */
4199         if (apdu_len < offset+len_field)
4200             return;
4201     }
4202
4203     ai = (apdu_info_t *)g_hash_table_lookup(apdu_table,
4204                                             GUINT_TO_POINTER((guint)tag));
4205     if (!ai) {
4206         proto_tree_add_expert(app_tree, pinfo, &ei_dvbci_apdu_not_supported, tvb, 0, APDU_TAG_SIZE);
4207         return;
4208     }
4209     if (ai->direction!=DIRECTION_ANY && ai->direction!=direction) {
4210         if (ai->direction==DATA_HOST_TO_CAM) {
4211             proto_tree_add_expert(app_tree, pinfo, &ei_dvbci_apu_host_to_cam, tvb, 0, APDU_TAG_SIZE);
4212         }
4213         else {
4214             proto_tree_add_expert(app_tree, pinfo, &ei_dvbci_apu_cam_to_host, tvb, 0, APDU_TAG_SIZE);
4215         }
4216         /* don't return, we can continue dissecting the APDU */
4217     }
4218     if (ai->min_len_field!=LEN_FIELD_ANY && len_field<ai->min_len_field) {
4219         proto_tree_add_expert_format(app_tree, pinfo, &ei_dvbci_bad_length, tvb, 0, APDU_TAG_SIZE,
4220                 "Invalid APDU length field, minimum length field for %s is %d", tag_str, ai->min_len_field);
4221         return;
4222     }
4223     if (ai->len_field!=LEN_FIELD_ANY && len_field!=ai->len_field) {
4224         proto_tree_add_expert_format(app_tree, pinfo, &ei_dvbci_bad_length, tvb, 0, APDU_TAG_SIZE,
4225                 "Invalid APDU length field, length field for %s must be %d", tag_str, ai->len_field);
4226         return;
4227     }
4228     if (circuit) {
4229         apdu_res_id = GPOINTER_TO_UINT(
4230                 (gpointer)circuit_get_proto_data(circuit, proto_dvbci));
4231
4232         ai_res_class_str = val_to_str_const(ai->res_class, dvbci_res_class, "Unknown");
4233
4234         if(RES_CLASS(apdu_res_id) != ai->res_class) {
4235             proto_tree_add_expert_format(app_tree, pinfo, &ei_dvbci_res_class, tvb, 0, APDU_TAG_SIZE,
4236                     "Invalid resource class for this apdu, %s can only be sent on a %s session",
4237                     tag_str, ai_res_class_str);
4238         }
4239         if(RES_VER(apdu_res_id) < ai->res_min_ver) {
4240             proto_tree_add_expert_format(app_tree, pinfo, &ei_dvbci_res_ver, tvb, 0, APDU_TAG_SIZE,
4241                     "Invalid resource version for this apdu, %s apdu requires at least %s version %d",
4242                     tag_str, ai_res_class_str, ai->res_min_ver);
4243         }
4244         /* don't return, we can continue dissecting the APDU */
4245     }
4246     if (ai->len_field!=0) {
4247         if (!ai->dissect_payload) {
4248             /* don't display an error, getting here means we have illegal
4249              * data in apdu_info[] */
4250             return;
4251         }
4252         ai->dissect_payload(
4253                 tag, len_field, tvb, offset, circuit, pinfo, app_tree);
4254     }
4255 }
4256
4257 static void
4258 dissect_dvbci_spdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4259         guint8 direction, guint8 tcid)
4260 {
4261     guint32            spdu_len;
4262     proto_item        *ti;
4263     proto_tree        *sess_tree;
4264     guint8             tag;
4265     const gchar       *tag_str;
4266     circuit_t         *circuit     = NULL;
4267     proto_item        *pi;
4268     gint               offset;
4269     guint32            len_field;
4270     const spdu_info_t *si;
4271     proto_item        *res_id_it   = NULL;
4272     guint32            res_id;
4273     guint16 ssnb                   = 0;  /* session numbers start with 1, 0 is invalid */
4274     guint8             sess_stat;
4275     tvbuff_t          *payload_tvb = NULL;
4276
4277
4278     spdu_len = tvb_reported_length(tvb);
4279
4280     ti = proto_tree_add_text(tree, tvb, 0, -1, "Session Layer");
4281     sess_tree = proto_item_add_subtree(ti, ett_dvbci_session);
4282
4283     tag = tvb_get_guint8(tvb,0);
4284     tag_str = try_val_to_str(tag, dvbci_spdu_tag);
4285     col_set_str(pinfo->cinfo, COL_INFO,
4286             val_to_str_const(tag, dvbci_spdu_tag, "Invalid SPDU"));
4287     pi = proto_tree_add_item(sess_tree, hf_dvbci_spdu_tag, tvb, 0, 1, ENC_BIG_ENDIAN);
4288     if (tag_str == NULL) {
4289         expert_add_info(pinfo, pi, &ei_dvbci_spdu_tag);
4290         return;
4291     }
4292
4293     offset = dissect_ber_length(pinfo, sess_tree, tvb, 1, &len_field, NULL);
4294
4295     si = (spdu_info_t *)g_hash_table_lookup(spdu_table,
4296                                             GUINT_TO_POINTER((guint)tag));
4297     if (!si)
4298         return;
4299     if (si->direction!=0 && si->direction!=direction) {
4300         if (si->direction==DATA_HOST_TO_CAM) {
4301             proto_tree_add_expert(sess_tree, pinfo, &ei_dvbci_spdu_host_to_cam, tvb, 0, 1);
4302         }
4303         else {
4304             proto_tree_add_expert(sess_tree, pinfo, &ei_dvbci_spdu_cam_to_host, tvb, 0, 1);
4305         }
4306     }
4307     if (si->len_field != len_field) {
4308         /* offset points to 1st byte after the length field */
4309         proto_tree_add_expert_format(sess_tree, pinfo, &ei_dvbci_bad_length, tvb, 1, offset-1,
4310                 "Invalid SPDU length field, correct length field for %s is %d", tag_str, si->len_field);
4311         return;
4312     }
4313
4314     switch(tag)
4315     {
4316         case T_OPEN_SESSION_REQUEST:
4317             res_id_it = dissect_res_id(tvb, offset, pinfo, sess_tree, 0, TRUE);
4318             break;
4319         case T_CREATE_SESSION:
4320             res_id_it = dissect_res_id(tvb, offset, pinfo, sess_tree, 0, TRUE);
4321             /* DVB-CI uses network byte order == big endian */
4322             ssnb = tvb_get_ntohs(tvb, offset+RES_ID_LEN);
4323             proto_tree_add_item(sess_tree, hf_dvbci_sess_nb,
4324                     tvb, offset+RES_ID_LEN, 2, ENC_BIG_ENDIAN);
4325             break;
4326         case T_OPEN_SESSION_RESPONSE:
4327         case T_CREATE_SESSION_RESPONSE:
4328             sess_stat = tvb_get_guint8(tvb, offset);
4329             proto_tree_add_item(sess_tree, hf_dvbci_sess_status,
4330                     tvb, offset, 1, ENC_BIG_ENDIAN);
4331             res_id = tvb_get_ntohl(tvb, offset+1);
4332             res_id_it = dissect_res_id(tvb, offset+1, pinfo, sess_tree, 0, TRUE);
4333             ssnb = tvb_get_ntohs(tvb, offset+1+RES_ID_LEN);
4334             proto_tree_add_item(sess_tree, hf_dvbci_sess_nb, tvb,
4335                     offset+1+RES_ID_LEN, 2, ENC_BIG_ENDIAN);
4336             if (sess_stat != SESS_OPENED) {
4337                 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Error");
4338                 break;
4339             }
4340             col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Session opened");
4341             circuit = circuit_new(CT_DVBCI, CT_ID(ssnb, tcid), pinfo->fd->num);
4342             if (circuit) {
4343                 /* we always add the resource id immediately after the circuit
4344                    was created */
4345                 circuit_add_proto_data(
4346                         circuit, proto_dvbci, GUINT_TO_POINTER(res_id));
4347             }
4348             break;
4349         case T_CLOSE_SESSION_REQUEST:
4350             ssnb = tvb_get_ntohs(tvb, offset);
4351             proto_tree_add_item(
4352                     sess_tree, hf_dvbci_sess_nb, tvb,
4353                     offset, 2, ENC_BIG_ENDIAN);
4354             break;
4355         case T_CLOSE_SESSION_RESPONSE:
4356             sess_stat = tvb_get_guint8(tvb, offset);
4357             proto_tree_add_item(
4358                     sess_tree, hf_dvbci_close_sess_status, tvb,
4359                     offset, 1, ENC_BIG_ENDIAN);
4360             col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
4361                     sess_stat==SESS_CLOSED ? "Session closed" : "Error");
4362             ssnb = tvb_get_ntohs(tvb, offset+1);
4363             proto_tree_add_item(sess_tree, hf_dvbci_sess_nb,
4364                     tvb, offset+1, 2, ENC_BIG_ENDIAN);
4365             circuit = find_circuit(CT_DVBCI, CT_ID(ssnb, tcid), pinfo->fd->num);
4366             if (circuit)
4367                 close_circuit(circuit, pinfo->fd->num);
4368             break;
4369         case T_SESSION_NUMBER:
4370             ssnb = tvb_get_ntohs(tvb, offset);
4371             proto_tree_add_item(
4372                     sess_tree, hf_dvbci_sess_nb, tvb,
4373                     offset, 2, ENC_BIG_ENDIAN);
4374             payload_tvb =
4375                 tvb_new_subset_remaining(tvb, offset+2);
4376             break;
4377         default:
4378             break;
4379     }
4380
4381     if (ssnb && !circuit)
4382         circuit = find_circuit(CT_DVBCI, CT_ID(ssnb, tcid), pinfo->fd->num);
4383
4384     /* if the packet contains no resource id, we add the cached id from
4385        the circuit so that each packet has a resource id that can be
4386        used for filtering */
4387     if (circuit && !res_id_it) {
4388         /* when a circuit is found, it always contains a valid resource id */
4389         res_id = GPOINTER_TO_UINT(
4390                 (gpointer)circuit_get_proto_data(circuit, proto_dvbci));
4391         res_id_it = dissect_res_id(NULL, 0, pinfo, sess_tree, res_id, TRUE);
4392         PROTO_ITEM_SET_GENERATED(res_id_it);
4393     }
4394
4395     if (payload_tvb) {
4396         proto_item_set_len(ti, spdu_len-tvb_reported_length(payload_tvb));
4397         dissect_dvbci_apdu(payload_tvb, circuit, pinfo, tree, direction);
4398     }
4399     else {
4400         proto_item_set_len(ti, spdu_len);
4401     }
4402 }
4403
4404 /* dissect the status of an r_tpdu, return its length or -1 for error */
4405 static gint
4406 dissect_dvbci_tpdu_status(tvbuff_t *tvb, gint offset,
4407         packet_info *pinfo, proto_tree *tree,
4408         guint8 lpdu_tcid, guint8 r_tpdu_tag)
4409 {
4410     gint         offset_new, len_start_offset;
4411     guint8       tag;
4412     guint32      len_field;
4413     guint8       t_c_id, sb_value;
4414     const gchar *sb_str;
4415     proto_item  *pi;
4416
4417     offset_new = offset;
4418
4419     tag = tvb_get_guint8(tvb, offset_new);
4420     if (tag!=T_SB) {
4421         proto_tree_add_expert(tree, pinfo, &ei_dvbci_tpdu_status_tag, tvb, offset_new, 1);
4422         return -1;
4423     }
4424     col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "T_SB");
4425     proto_tree_add_text(tree, tvb, offset_new, 1, "Response TPDU status");
4426     offset_new++;
4427
4428     len_start_offset = offset_new;
4429     offset_new = dissect_ber_length(
4430             pinfo, tree, tvb, offset_new, &len_field, NULL);
4431     if (len_field != 2) {
4432         proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb, len_start_offset, offset_new-len_start_offset,
4433                 "Invalid status length field, this must always be 2");
4434
4435         return -1;
4436     }
4437
4438     t_c_id = tvb_get_guint8(tvb, offset_new);
4439     proto_tree_add_item(tree, hf_dvbci_t_c_id, tvb, offset_new, 1, ENC_BIG_ENDIAN);
4440     /* tcid in transport header and link layer must only match for data
4441      * transmission commands */
4442     if (t_c_id!=lpdu_tcid) {
4443         if (r_tpdu_tag==NO_TAG ||
4444                 r_tpdu_tag==T_DATA_MORE || r_tpdu_tag==T_DATA_LAST) {
4445
4446             pi = proto_tree_add_text(tree, tvb, offset_new, 1,
4447                     "Transport Connection ID mismatch");
4448             expert_add_info_format(pinfo, pi, &ei_dvbci_t_c_id, "Transport Connection ID mismatch, tcid is %d in the transport layer and %d in the link layer", t_c_id, lpdu_tcid);
4449
4450             return -1;
4451         }
4452     }
4453     offset_new++;
4454
4455     sb_value = tvb_get_guint8(tvb, offset_new);
4456     sb_str = try_val_to_str(sb_value, dvbci_sb_value);
4457     pi = proto_tree_add_item(tree, hf_dvbci_sb_value, tvb,
4458             offset_new, 1, ENC_BIG_ENDIAN);
4459     if (sb_str) {
4460         col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "%s", sb_str);
4461     }
4462     else {
4463         proto_tree_add_text(tree, tvb, offset_new, 1,
4464                 "Invalid SB_value");
4465         expert_add_info(pinfo, pi, &ei_dvbci_sb_value);
4466     }
4467     offset_new++;
4468
4469     return offset_new-offset;
4470 }
4471
4472
4473 /* dissect the header of a c_tpdu or r_tpdu
4474    return the length of the header (tag, len_field, t_c_id) or -1 for error */
4475 static gint
4476 dissect_dvbci_tpdu_hdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4477         guint8 direction, guint8 lpdu_tcid, guint32 tpdu_len,
4478         guint8 *hdr_tag, guint32 *body_len)
4479 {
4480     guint8       c_tpdu_tag, r_tpdu_tag, *tag = NULL;
4481     const gchar *c_tpdu_str, *r_tpdu_str;
4482     proto_item  *pi;
4483     gint         offset;
4484     guint32      len_field;
4485     guint8       t_c_id;
4486
4487     if (direction==DATA_HOST_TO_CAM) {
4488         c_tpdu_tag = tvb_get_guint8(tvb, 0);
4489         tag = &c_tpdu_tag;
4490         c_tpdu_str = try_val_to_str(c_tpdu_tag, dvbci_c_tpdu);
4491         pi = proto_tree_add_item(tree, hf_dvbci_c_tpdu_tag, tvb, 0, 1, ENC_BIG_ENDIAN);
4492         if (c_tpdu_str) {
4493             col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s", c_tpdu_str);
4494         }
4495         else {
4496             col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
4497                     "Invalid Command-TPDU tag");
4498             expert_add_info(pinfo, pi, &ei_dvbci_c_tpdu_tag);
4499             return -1;
4500         }
4501     }
4502     else {
4503         r_tpdu_tag = tvb_get_guint8(tvb, 0);
4504         tag = &r_tpdu_tag;
4505         r_tpdu_str = try_val_to_str(r_tpdu_tag, dvbci_r_tpdu);
4506         pi = proto_tree_add_item(tree, hf_dvbci_r_tpdu_tag, tvb, 0, 1, ENC_BIG_ENDIAN);
4507         if (r_tpdu_str) {
4508             col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s", r_tpdu_str);
4509         }
4510         else {
4511             if (r_tpdu_tag == T_SB) {
4512                 /* we have an r_tpdu without header and body,
4513                    it contains only the status part */
4514                 if (hdr_tag)
4515                     *hdr_tag = NO_TAG;
4516                 if (body_len)
4517                     *body_len = 0;
4518                 return 0;
4519             }
4520             else {
4521                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
4522                         "Invalid Response-TPDU tag");
4523                 expert_add_info(pinfo, pi, &ei_dvbci_r_tpdu_tag);
4524                 return -1;
4525             }
4526         }
4527     }
4528
4529     offset = dissect_ber_length(pinfo, tree, tvb, 1, &len_field, NULL);
4530     /* len_field must be at least 1 for the following t_c_id
4531        c_tpdu's len_field must match tvbuff exactly
4532        r_tpdu's len_field does not include the status part after the body */
4533     if (len_field==0 ||
4534         ((direction==DATA_HOST_TO_CAM) && ((offset+len_field)!=tpdu_len)) ||
4535         ((direction==DATA_CAM_TO_HOST) && ((offset+len_field)>tpdu_len))) {
4536         /* offset points to 1st byte after the length field */
4537         proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_bad_length, tvb, 1, offset-1,
4538             len_field==0 ? "Invalid length field, length field must be at least 1" :
4539                            "Invalid length field, length field mismatch");
4540         return -1;
4541     }
4542
4543     t_c_id = tvb_get_guint8(tvb, offset);
4544     pi = proto_tree_add_item(tree, hf_dvbci_t_c_id, tvb, offset, 1, ENC_BIG_ENDIAN);
4545     /* tcid in transport header and link layer must only match for
4546      * data transmission commands */
4547     if (t_c_id!=lpdu_tcid) {
4548         if (tag && (*tag==T_RCV || *tag==T_DATA_MORE || *tag==T_DATA_LAST)) {
4549             expert_add_info_format(pinfo, pi, &ei_dvbci_t_c_id, "Transport Connection ID mismatch, tcid is %d in the transport layer and %d in the link layer",
4550                     t_c_id, lpdu_tcid);
4551         }
4552     }
4553     else {
4554         col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "tcid %d", t_c_id);
4555     }
4556     offset++;
4557
4558     if (hdr_tag && tag)
4559         *hdr_tag = *tag;
4560     if (body_len)
4561         *body_len = len_field-1;  /* -1 for t_c_id */
4562     return offset;
4563 }
4564
4565 static void
4566 dissect_dvbci_tpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4567         guint8 direction, guint8 lpdu_tcid)
4568 {
4569     guint32        tpdu_len, body_len;
4570     proto_item    *ti;
4571     proto_tree    *trans_tree;
4572     gint           offset, status_len;
4573     guint8         hdr_tag                = NO_TAG;
4574     tvbuff_t      *body_tvb, *payload_tvb = NULL;
4575     fragment_head *frag_msg               = NULL;
4576
4577
4578     tpdu_len = tvb_reported_length(tvb);
4579
4580     col_clear(pinfo->cinfo, COL_INFO);
4581
4582     ti = proto_tree_add_text(tree, tvb, 0, -1, "Transport Layer");
4583     trans_tree = proto_item_add_subtree(ti, ett_dvbci_transport);
4584
4585     offset = dissect_dvbci_tpdu_hdr(tvb, pinfo, trans_tree, direction,
4586             lpdu_tcid, tpdu_len, &hdr_tag, &body_len);
4587     if (offset==-1)
4588         return;
4589     proto_item_set_len(ti, offset);
4590     if ((offset>0) && (body_len!=0)) {
4591         /* for unfragmented data, the reassembly api behaviour is unclear
4592             if we put the body part of the tvb into fragment_add_seq_next(),
4593             process_reassembled_data() returns the remainder of the tvb
4594             which is body|status part
4595            if there's more than one fragment, payload_tvb contains only
4596             the reassembled bodies as expected
4597            to work around this issue, we use a dedicated body_tvb as
4598             input to reassembly routines */
4599         body_tvb = tvb_new_subset_length(tvb, offset, body_len);
4600         /* dissect_dvbci_tpdu_hdr() checked that lpdu_tcid==t_c_id */
4601         frag_msg = fragment_add_seq_next(&spdu_reassembly_table,
4602                 body_tvb, 0, pinfo, SPDU_SEQ_ID_BASE+lpdu_tcid, NULL,
4603                 body_len,
4604                 hdr_tag == T_DATA_MORE ? 1 : 0);
4605         payload_tvb = process_reassembled_data(body_tvb, 0, pinfo,
4606                 "Reassembled SPDU", frag_msg, &spdu_frag_items,
4607                 NULL, trans_tree);
4608         if (!payload_tvb) {
4609             if (hdr_tag == T_DATA_MORE) {
4610                 pinfo->fragmented = TRUE;
4611                 col_append_str(pinfo->cinfo, COL_INFO, " (Message fragment)");
4612             } else {
4613                 payload_tvb = body_tvb;
4614             }
4615         }
4616         offset += body_len;
4617     }
4618
4619     if (direction==DATA_CAM_TO_HOST) {
4620         /* minimum length of an rtpdu status is 4 bytes */
4621         if (tpdu_len-offset < 4) {
4622             proto_tree_add_expert(trans_tree, pinfo, &ei_dvbci_r_tpdu_status_mandatory, tvb, 0, 0);
4623             return;
4624         }
4625         status_len = dissect_dvbci_tpdu_status(
4626                 tvb, offset, pinfo, trans_tree, lpdu_tcid, hdr_tag);
4627         if (status_len<0)
4628             return;
4629         proto_tree_set_appendix(trans_tree, tvb, offset, status_len);
4630     }
4631
4632     if (payload_tvb)
4633         dissect_dvbci_spdu(payload_tvb, pinfo, tree, direction, lpdu_tcid);
4634 }
4635
4636
4637 static void
4638 dissect_dvbci_lpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4639         guint8 direction)
4640 {
4641     proto_item    *ti;
4642     proto_tree    *link_tree;
4643     guint32        payload_len;
4644     guint8         tcid, more_last;
4645     proto_item    *pi;
4646     tvbuff_t      *payload_tvb;
4647     fragment_head *frag_msg;
4648
4649
4650     payload_len = tvb_reported_length(tvb);
4651
4652     col_set_str(pinfo->cinfo, COL_INFO, "LPDU");
4653
4654     ti = proto_tree_add_text(tree, tvb, 0, 2, "Link Layer");
4655     link_tree = proto_item_add_subtree(ti, ett_dvbci_link);
4656
4657     tcid = tvb_get_guint8(tvb, 0);
4658     col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ", "tcid %d", tcid);
4659     proto_tree_add_item(link_tree, hf_dvbci_tcid, tvb, 0, 1, ENC_BIG_ENDIAN);
4660
4661     more_last = tvb_get_guint8(tvb, 1);
4662     pi = proto_tree_add_item(link_tree, hf_dvbci_ml, tvb, 1, 1, ENC_BIG_ENDIAN);
4663     if (try_val_to_str(more_last, dvbci_ml) == NULL) {
4664         expert_add_info(pinfo, pi, &ei_dvbci_ml);
4665     }
4666
4667     /* buf_size_host==0 -> we did not capture the buffer size negotiation */
4668     if (buf_size_host!=0 && payload_len>buf_size_host) {
4669         proto_tree_add_expert_format(link_tree, pinfo, &ei_dvbci_bad_length, tvb, 2, payload_len,
4670                 "Payload too large, maximum payload length is the negotiated buffer size (%d bytes)", buf_size_host);
4671     }
4672
4673     frag_msg = fragment_add_seq_next(&tpdu_reassembly_table,
4674             tvb, 2, pinfo, TPDU_SEQ_ID_BASE+tcid, NULL,
4675             tvb_reported_length_remaining(tvb, 2),
4676             more_last == ML_MORE ? 1 : 0);
4677
4678     payload_tvb = process_reassembled_data(tvb, 2, pinfo,
4679             "Reassembled TPDU", frag_msg, &tpdu_frag_items,
4680             NULL, link_tree);
4681     if (!payload_tvb) {
4682         if (more_last == ML_MORE) {
4683             pinfo->fragmented = TRUE;
4684             col_append_str(pinfo->cinfo, COL_INFO, " (Message fragment)");
4685        } else
4686             payload_tvb = tvb_new_subset_remaining(tvb, 2);
4687     }
4688     if (payload_tvb)
4689         dissect_dvbci_tpdu(payload_tvb, pinfo, tree, direction, tcid);
4690 }
4691
4692 /* dissect DVB-CI buffer size negotiation */
4693 static void
4694 dissect_dvbci_buf_neg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4695         guint8 direction)
4696 {
4697     guint16     buf_size;
4698     proto_item *pi;
4699
4700     buf_size = tvb_get_ntohs(tvb, 0);
4701
4702     col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %u bytes",
4703                  direction == DATA_HOST_TO_CAM ?
4704                  "negotiated buffer size" : "buffer size proposal",
4705                  buf_size);
4706
4707     if (direction == DATA_HOST_TO_CAM) {
4708         buf_size_host = buf_size;
4709         pi = proto_tree_add_uint_format(tree, hf_dvbci_buf_size, tvb,
4710                 0, 2, buf_size,
4711                 "Negotiated buffer size: %u bytes", buf_size);
4712         if (buf_size_host > buf_size_cam) {
4713             /* ATTENTION:
4714                wireshark may run through each packet multiple times
4715                if we didn't check the direction, we'd get the error when
4716                wireshark runs through the initial CAM packet for the 2nd time
4717              */
4718             expert_add_info_format(pinfo, pi, &ei_dvbci_buf_size, "Illegal buffer size command. Host shall not request a buffer size larger than the CAM proposal");
4719         }
4720     }
4721     else if (direction == DATA_CAM_TO_HOST) {
4722         buf_size_cam = buf_size;
4723         proto_tree_add_uint_format(tree, hf_dvbci_buf_size, tvb,
4724                 0, 2, buf_size,
4725                 "Buffer size proposal by the CAM: %u bytes", buf_size);
4726     }
4727
4728     if (buf_size < 16) {
4729         proto_tree_add_expert_format(tree, pinfo, &ei_dvbci_buf_size, tvb, 0, 2,
4730                "Illegal buffer size, minimum buffer size is 16 bytes");
4731     }
4732 }
4733
4734 /* dissect Level 1 version/product information tuple's payload
4735    data_tvb is a separate tvb for the tuple payload (without tag and len)
4736    return the number of dissected bytes or -1 for error */
4737 static gint
4738 dissect_dvbci_cis_payload_tpll_v1(tvbuff_t *data_tvb,
4739         packet_info *pinfo _U_, proto_tree *tree)
4740 {
4741     gint offset=0, offset_str_end;
4742
4743     /* the CIS is defined by PCMCIA, all multi-byte values are little endian
4744        (the rest of DVB-CI is a big-endian protocol) */
4745     proto_tree_add_item(tree, hf_dvbci_cis_tpll_v1_major,
4746             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4747     offset++;
4748     proto_tree_add_item(tree, hf_dvbci_cis_tpll_v1_minor,
4749             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4750     offset++;
4751
4752     /* manufacturer, name and additional infos are 0-terminated strings */
4753     offset_str_end = tvb_find_guint8(data_tvb, offset, -1, 0x0);
4754     if (offset_str_end<offset) /* offset_str_end==offset is ok */
4755         return offset;
4756     proto_tree_add_item(tree, hf_dvbci_cis_tpll_v1_info_manuf,
4757             data_tvb, offset, offset_str_end-offset, ENC_ASCII|ENC_NA);
4758     offset = offset_str_end+1; /* +1 for 0 termination */
4759
4760     offset_str_end = tvb_find_guint8(data_tvb, offset, -1, 0x0);
4761     if (offset_str_end<offset)
4762         return offset;
4763     proto_tree_add_item(tree, hf_dvbci_cis_tpll_v1_info_name,
4764             data_tvb, offset, offset_str_end-offset, ENC_ASCII|ENC_NA);
4765     offset = offset_str_end+1;
4766
4767     /* the pc-card spec mentions two additional info strings,
4768         it's unclear if both are mandatory
4769        >1 because the last byte is the tuple end marker */
4770     while (tvb_reported_length_remaining(data_tvb, offset)>1) {
4771         offset_str_end = tvb_find_guint8(data_tvb, offset, -1, 0x0);
4772         if (offset_str_end<offset)
4773             break;
4774         proto_tree_add_item(tree, hf_dvbci_cis_tpll_v1_info_additional,
4775                 data_tvb, offset, offset_str_end-offset, ENC_ASCII|ENC_NA);
4776         offset = offset_str_end+1;
4777     }
4778
4779     proto_tree_add_item(tree, hf_dvbci_cis_tpll_v1_end,
4780             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4781     offset++;
4782
4783     return offset;
4784 }
4785
4786 static gint
4787 dissect_dvbci_cis_payload_config(tvbuff_t *data_tvb,
4788         packet_info *pinfo _U_, proto_tree *tree)
4789 {
4790     gint         offset = 0;
4791     /* these are the actual sizes, the CIS stores rmsz-1 and rasz-1 */
4792     guint8       rfsz, rmsz, rasz;
4793     guint8       st_code, st_len;
4794     const gchar *st_code_str;
4795     proto_item  *st_item = NULL;
4796     proto_tree  *st_tree = NULL;
4797     guint8       stci_ifn_size;   /* actual size, see comment above */
4798
4799     rfsz = (tvb_get_guint8(data_tvb, offset)&0xC0) >> 6;
4800     proto_tree_add_item(tree, hf_dvbci_cis_tpcc_rfsz,
4801             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4802     rmsz = ((tvb_get_guint8(data_tvb, offset)&0x3C) >> 2) + 1;
4803     proto_tree_add_item(tree, hf_dvbci_cis_tpcc_rmsz,
4804             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4805     rasz = (tvb_get_guint8(data_tvb, offset)&0x03) + 1;
4806     proto_tree_add_item(tree, hf_dvbci_cis_tpcc_rasz,
4807             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4808     offset++;
4809
4810     proto_tree_add_item(tree, hf_dvbci_cis_tpcc_last,
4811             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4812     offset++;
4813
4814     proto_tree_add_item(tree, hf_dvbci_cis_tpcc_radr,
4815             data_tvb, offset, rasz, ENC_LITTLE_ENDIAN);
4816     offset += rasz;
4817     proto_tree_add_item(tree, hf_dvbci_cis_tpcc_rmsk,
4818             data_tvb, offset, rmsz, ENC_NA);
4819     offset += rmsz;
4820     offset += rfsz; /* skip reserved bytes */
4821
4822     while (tvb_reported_length_remaining(data_tvb, offset) > 0) {
4823         st_code = tvb_get_guint8(data_tvb, offset);
4824         st_code_str = val_to_str_const(st_code, dvbci_cis_subtpl_code, "unknown");
4825         st_item = proto_tree_add_text(tree, data_tvb, offset, -1,
4826                 "Subtuple: %s (0x%x)", st_code_str, st_code);
4827         st_tree = proto_item_add_subtree(st_item, ett_dvbci_cis_subtpl);
4828         proto_tree_add_item(st_tree, hf_dvbci_cis_st_code,
4829             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4830         offset++;
4831         st_len = tvb_get_guint8(data_tvb, offset);
4832         proto_item_set_len(st_item, 2+st_len); /* tag, len byte, body */
4833         proto_tree_add_item(st_tree, hf_dvbci_cis_st_len,
4834             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4835         offset++;
4836         if (st_code == CCSTPL_CIF) {
4837             stci_ifn_size = ((tvb_get_guint8(data_tvb, offset) & 0xC0)>>6)+1;
4838             proto_tree_add_item(st_tree, hf_dvbci_cis_stci_ifn_size,
4839                     data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4840             /* don't increment offset,
4841                size and actual value's LSB share the same byte */
4842             proto_tree_add_item(st_tree, hf_dvbci_cis_stci_ifn,
4843                     data_tvb, offset, stci_ifn_size, ENC_LITTLE_ENDIAN);
4844             offset += stci_ifn_size;
4845             /* the stci_str field could consist of multiple strings,
4846                this case is not supported for now */
4847             proto_tree_add_item(st_tree, hf_dvbci_cis_stci_str,
4848                     data_tvb, offset, st_len-stci_ifn_size, ENC_ASCII|ENC_NA);
4849             offset += st_len-stci_ifn_size;
4850         }
4851         else {
4852             /* skip unknown subtuple's content */
4853             offset += st_len;
4854         }
4855     }
4856
4857     return offset;
4858 }
4859
4860
4861 static gint
4862 dissect_dvbci_cis_payload_cftable_entry(tvbuff_t *data_tvb,
4863         packet_info *pinfo _U_, proto_tree *tree)
4864 {
4865     gint offset = 0;
4866     gboolean intface_flag;
4867
4868     intface_flag = ((tvb_get_guint8(data_tvb, offset) & 0x80) == 0x80);
4869     /* tpce_indx byte */
4870     proto_tree_add_item(tree, hf_dvbci_cis_tpce_indx_intface,
4871             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4872     proto_tree_add_item(tree, hf_dvbci_cis_tpce_indx_default,
4873             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4874     proto_tree_add_item(tree, hf_dvbci_cis_tpce_indx_cnf_entry,
4875             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4876     offset++;
4877
4878     if (intface_flag) {
4879         /* tpce_if byte */
4880         proto_tree_add_item(tree, hf_dvbci_cis_tpce_if_type,
4881             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4882         /* XXX parse other components of tpce_if */
4883         offset++;
4884     }
4885
4886     /* tpce_fs byte: this is present in any case */
4887     proto_tree_add_item(tree, hf_dvbci_cis_tpce_fs_mem_space,
4888             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4889     proto_tree_add_item(tree, hf_dvbci_cis_tpce_fs_irq,
4890             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4891     proto_tree_add_item(tree, hf_dvbci_cis_tpce_fs_io,
4892             data_tvb, offset, 1, ENC_LITTLE_ENDIAN);
4893     /* XXX parse other components of tpce_fs */
4894     offset++;
4895
4896     return offset;
4897 }
4898
4899 static void
4900 dissect_dvbci_cis(tvbuff_t *tvb, gint offset,
4901         packet_info *pinfo, proto_tree *tree)
4902 {
4903     gint         offset_start;
4904     proto_tree  *cis_tree = NULL, *tpl_tree = NULL;
4905     proto_item  *ti_main  = NULL, *ti_tpl;
4906     guint8       tpl_code;
4907     const gchar *tpl_code_str = NULL;
4908     guint8       len_field;
4909     tvbuff_t    *tpl_data_tvb;
4910
4911     offset_start = offset;
4912
4913     ti_main = proto_tree_add_text(tree, tvb, offset, -1,
4914             "Card Information Structure (CIS)");
4915     cis_tree = proto_item_add_subtree(ti_main, ett_dvbci_cis);
4916
4917     do {
4918         tpl_code = tvb_get_guint8(tvb, offset);
4919         tpl_code_str = val_to_str_const(tpl_code, dvbci_cis_tpl_code, "unknown");
4920
4921         ti_tpl = proto_tree_add_text(cis_tree,
4922                 tvb, offset, -1, "CIS tuple: %s", tpl_code_str);
4923         tpl_tree = proto_item_add_subtree(ti_tpl, ett_dvbci_cis_tpl);
4924
4925         proto_tree_add_uint_format(tpl_tree, hf_dvbci_cis_tpl_code,
4926                 tvb, offset, 1, tpl_code, "Tuple code: %s (0x%x)",
4927                 tpl_code_str, tpl_code);
4928         offset++;
4929
4930         if (tpl_code == CISTPL_END) {
4931             proto_item_set_len(ti_tpl, 1); /* only tag (no len and content) */
4932             break;
4933         }
4934
4935         len_field = tvb_get_guint8(tvb, offset);
4936         proto_tree_add_item(tpl_tree, hf_dvbci_cis_tpl_len,
4937                 tvb, offset, 1, ENC_LITTLE_ENDIAN);
4938         offset++;
4939
4940         tpl_data_tvb = tvb_new_subset_length(tvb, offset, len_field);
4941         switch (tpl_code) {
4942             case CISTPL_VERS_1:
4943                 dissect_dvbci_cis_payload_tpll_v1(
4944                         tpl_data_tvb, pinfo, tpl_tree);
4945                 offset += len_field;
4946                 break;
4947             case CISTPL_CONFIG:
4948                 dissect_dvbci_cis_payload_config(tpl_data_tvb, pinfo, tpl_tree);
4949                 offset += len_field;
4950                 break;
4951             case CISTPL_CFTABLE_ENTRY:
4952                 dissect_dvbci_cis_payload_cftable_entry(
4953                         tpl_data_tvb, pinfo, tpl_tree);
4954                 offset += len_field;
4955                 break;
4956             case CISTPL_MANFID:
4957                 proto_tree_add_item(tpl_tree, hf_dvbci_cis_tplmid_manf,
4958                         tvb, offset, 2, ENC_LITTLE_ENDIAN);
4959                 offset+=2;
4960                 proto_tree_add_item(tpl_tree, hf_dvbci_cis_tplmid_card,
4961                         tvb, offset, 2, ENC_LITTLE_ENDIAN);
4962                 offset+=2;
4963                 break;
4964             default:
4965                 if (len_field>0) {
4966                     proto_tree_add_item(tpl_tree, hf_dvbci_cis_tpl_data,
4967                             tvb, offset, len_field, ENC_NA);
4968                 }
4969                 offset += len_field;
4970                 break;
4971         }
4972
4973         proto_item_set_len(ti_tpl, 2+len_field); /* tag, len byte, content */
4974
4975     } while (tvb_reported_length_remaining(tvb, offset) > 0);
4976
4977     proto_item_set_len(ti_main, offset-offset_start);
4978 }
4979
4980
4981 static int
4982 dissect_dvbci(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
4983 {
4984     gint         packet_len, offset = 0, offset_ver, offset_evt, offset_len_field;
4985     guint8       version, event;
4986     const gchar *event_str;
4987     guint16      len_field;
4988     proto_item  *ti, *ti_hdr;
4989     proto_tree  *dvbci_tree, *hdr_tree;
4990     tvbuff_t    *payload_tvb;
4991     guint16      cor_addr;
4992     guint8       cor_value;
4993     proto_item  *pi;
4994     guint8       hw_event;
4995
4996     if (tvb_length(tvb) < 4)
4997         return 0;
4998
4999     offset_ver = offset;
5000     version = tvb_get_guint8(tvb, offset++);
5001     if (version != 0)
5002         return 0;
5003
5004     offset_evt = offset;
5005     event = tvb_get_guint8(tvb, offset++);
5006     event_str = try_val_to_str(event, dvbci_event);
5007     if (!event_str)
5008         return 0;
5009
5010     packet_len = tvb_reported_length(tvb);
5011     offset_len_field = offset;
5012     len_field = tvb_get_ntohs(tvb, offset);
5013     if (len_field != (packet_len-4))
5014         return 0;
5015     offset += 2;
5016
5017     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DVB-CI");
5018     col_set_str(pinfo->cinfo, COL_INFO, event_str);
5019
5020     ti = proto_tree_add_protocol_format(tree, proto_dvbci,
5021             tvb, 0, packet_len, "DVB Common Interface: %s", event_str);
5022     dvbci_tree = proto_item_add_subtree(ti, ett_dvbci);
5023     ti_hdr = proto_tree_add_text(dvbci_tree, tvb, 0, offset, "Pseudo header");
5024     hdr_tree = proto_item_add_subtree(ti_hdr, ett_dvbci_hdr);
5025     proto_tree_add_text(hdr_tree, tvb, offset_ver, 1, "Version: %d", version);
5026     proto_tree_add_item(hdr_tree, hf_dvbci_event, tvb, offset_evt, 1, ENC_BIG_ENDIAN);
5027     proto_tree_add_text(hdr_tree, tvb, offset_len_field, 2,
5028             "Length field: %d", len_field);
5029
5030     if (IS_DATA_TRANSFER(event)) {
5031         dvbci_set_addrs(event, pinfo);
5032
5033         payload_tvb = tvb_new_subset_remaining( tvb, offset);
5034         if (len_field == 2) {
5035             dissect_dvbci_buf_neg(payload_tvb, pinfo, dvbci_tree, event);
5036         }
5037         else {
5038             dissect_dvbci_lpdu(payload_tvb, pinfo, dvbci_tree, event);
5039         }
5040     }
5041     else if (event==DVBCI_EVT_COR_WRITE) {
5042         /* PCAP format for DVB-CI defines COR address as big endian */
5043         pi = proto_tree_add_item(dvbci_tree, hf_dvbci_cor_addr,
5044                 tvb, offset, 2, ENC_BIG_ENDIAN);
5045         cor_addr = tvb_get_ntohs(tvb, offset);
5046         if (cor_addr == 0xFFFF) {
5047             proto_item_append_text(pi, " (COR address is unknown)");
5048             col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", "unknown address");
5049         }
5050         else if (cor_addr > 0xFFE) {
5051             expert_add_info(pinfo, pi, &ei_dvbci_cor_addr);
5052         }
5053         else {
5054             col_append_sep_fstr(pinfo->cinfo, COL_INFO, ": ",
5055                 "address 0x%x", cor_addr);
5056         }
5057         offset += 2;
5058         cor_value = tvb_get_guint8(tvb, offset);
5059         proto_tree_add_item(dvbci_tree, hf_dvbci_cor_val,
5060                 tvb, offset, 1, ENC_BIG_ENDIAN);
5061         col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
5062             "value 0x%x", cor_value);
5063     }
5064     else if (event==DVBCI_EVT_CIS_READ) {
5065         dissect_dvbci_cis(tvb, offset, pinfo, dvbci_tree);
5066     }
5067     else if (event==DVBCI_EVT_HW_EVT) {
5068         hw_event = tvb_get_guint8(tvb, offset);
5069         col_set_str(pinfo->cinfo, COL_INFO,
5070                 val_to_str_const(hw_event, dvbci_hw_event, "Invalid hardware event"));
5071         proto_tree_add_item(dvbci_tree, hf_dvbci_hw_event,
5072                 tvb, offset, 1, ENC_BIG_ENDIAN);
5073     }
5074
5075     return packet_len;
5076 }
5077
5078
5079 void
5080 proto_register_dvbci(void)
5081 {
5082     guint     i;
5083     module_t *dvbci_module;
5084     expert_module_t* expert_dvbci;
5085
5086     static gint *ett[] = {
5087         &ett_dvbci,
5088         &ett_dvbci_hdr,
5089         &ett_dvbci_cis,
5090         &ett_dvbci_cis_tpl,
5091         &ett_dvbci_cis_subtpl,
5092         &ett_dvbci_link,
5093         &ett_dvbci_link_frag,
5094         &ett_dvbci_link_frags,
5095         &ett_dvbci_transport,
5096         &ett_dvbci_transport_frag,
5097         &ett_dvbci_transport_frags,
5098         &ett_dvbci_session,
5099         &ett_dvbci_res,
5100         &ett_dvbci_application,
5101         &ett_dvbci_es,
5102         &ett_dvbci_ca_desc,
5103         &ett_dvbci_text,
5104         &ett_dvbci_cc_item,
5105         &ett_dvbci_sac_msg_body,
5106         &ett_dvbci_ami_req_types,
5107         &ett_dvbci_lsc_conn_desc,
5108         &ett_dvbci_opp_cap_loop,
5109         &ett_dvbci_dlv_sys_hint
5110     };
5111
5112     static hf_register_info hf[] = {
5113         { &hf_dvbci_event,
5114           { "Event", "dvb-ci.event",
5115             FT_UINT8, BASE_HEX, VALS(dvbci_event), 0, NULL, HFILL }
5116         },
5117         { &hf_dvbci_hw_event,
5118           { "Hardware event", "dvb-ci.hw_event",
5119             FT_UINT8, BASE_HEX, VALS(dvbci_hw_event), 0, NULL, HFILL }
5120         },
5121         { &hf_dvbci_cor_addr,
5122           { "COR address", "dvb-ci.cor_address",
5123             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5124         },
5125         { &hf_dvbci_cor_val,
5126           { "COR value", "dvb-ci.cor_value",
5127             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5128         },
5129         { &hf_dvbci_cis_tpl_code,
5130           { "CIS tuple code", "dvb-ci.cis.tpl_code",
5131             FT_UINT8, BASE_HEX, VALS(dvbci_cis_tpl_code), 0, NULL, HFILL }
5132         },
5133         { &hf_dvbci_cis_tpl_len,
5134           { "Length field", "dvb-ci.cis.tpl_len",
5135             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5136         },
5137         { &hf_dvbci_cis_tpl_data,
5138           { "Tuple data", "dvb-ci.cis.tpl_data",
5139             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5140         },
5141         { &hf_dvbci_cis_tpll_v1_major,
5142           { "Major version number", "dvb-ci.cis.tpll_v1_major",
5143             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5144         },
5145         { &hf_dvbci_cis_tpll_v1_minor,
5146           { "Minor version number", "dvb-ci.cis.tpll_v1_minor",
5147             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5148         },
5149         { &hf_dvbci_cis_tpll_v1_info_manuf,
5150           { "Manufacturer", "dvb-ci.cis.tpll_v1_info.manufacturer",
5151             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
5152         },
5153         { &hf_dvbci_cis_tpll_v1_info_name,
5154           { "Name", "dvb-ci.cis.tpll_v1_info.name",
5155             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
5156         },
5157         { &hf_dvbci_cis_tpll_v1_info_additional,
5158           { "Additional info", "dvb-ci.cis.tpll_v1_info.additional",
5159             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
5160         },
5161         { &hf_dvbci_cis_tpll_v1_end,
5162           { "End of chain", "dvb-ci.cis.tpll_v1_end",
5163             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5164         },
5165         { &hf_dvbci_cis_tpcc_rfsz,
5166           { "Size of reserved area", "dvb-ci.cis.tpcc_rfsz",
5167             FT_UINT8, BASE_HEX, NULL, 0xC0, NULL, HFILL }
5168         },
5169         { &hf_dvbci_cis_tpcc_rmsz,
5170           { "Size of TPCC_RMSK field - 1", "dvb-ci.cis.tpcc_rmsz",
5171             FT_UINT8, BASE_HEX, NULL, 0x3C, NULL, HFILL }
5172         },
5173         { &hf_dvbci_cis_tpcc_rasz,
5174           { "Size of TPCC_RADR - 1", "dvb-ci.cis.tpcc_rasz",
5175             FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL }
5176         },
5177         { &hf_dvbci_cis_tpcc_last,
5178           { "Index of the last cftable entry", "dvb-ci.cis.tpcc_last",
5179             FT_UINT8, BASE_HEX, NULL, 0x3F, NULL, HFILL }
5180         },
5181         { &hf_dvbci_cis_tpcc_radr,
5182           { "COR base address", "dvb-ci.cis.tpcc_radr",
5183             FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
5184         },
5185         { &hf_dvbci_cis_tpcc_rmsk,
5186           { "Configuration register presence mask", "dvb-ci.cis.tpcc_rmsk",
5187             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5188         },
5189         { &hf_dvbci_cis_st_code,
5190           { "Subtuple tag", "dvb-ci.cis.st_code",
5191             FT_UINT8, BASE_HEX, VALS(dvbci_cis_subtpl_code), 0, NULL, HFILL }
5192         },
5193         { &hf_dvbci_cis_st_len,
5194           { "Subtuple length", "dvb-ci.cis.st_len",
5195             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5196         },
5197         { &hf_dvbci_cis_stci_ifn_size,
5198           { "Size of interface ID number - 1", "dvb-ci.cis.stci_ifn_size",
5199             FT_UINT8, BASE_HEX, NULL, 0xC0, NULL, HFILL }
5200         },
5201         { &hf_dvbci_cis_stci_ifn,
5202           { "Interface ID number", "dvb-ci.cis.stci_ifn",
5203             FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
5204         },
5205         { &hf_dvbci_cis_stci_str,
5206           { "Interface description strings", "dvb-ci.cis.stci_str",
5207             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
5208         },
5209         { &hf_dvbci_cis_tpce_indx_intface,
5210           { "Intface", "dvb-ci.cis.tpce_indx.intface",
5211             FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL }
5212         },
5213         { &hf_dvbci_cis_tpce_indx_default,
5214           { "Default", "dvb-ci.cis.tpce_indx.default",
5215             FT_UINT8, BASE_HEX, NULL, 0x40, NULL, HFILL }
5216         },
5217         { &hf_dvbci_cis_tpce_indx_cnf_entry,
5218           { "Configuration entry number", "dvb-ci.cis.tpce_indx.cnf_entry",
5219             FT_UINT8, BASE_HEX, NULL, 0x3F, NULL, HFILL }
5220         },
5221         { &hf_dvbci_cis_tpce_if_type,
5222           { "Interface type", "dvb-ci.cis.tpce_if.type", FT_UINT8, BASE_HEX,
5223               VALS(dvbci_cis_tpce_if_type), 0x0F, NULL, HFILL }
5224         },
5225         { &hf_dvbci_cis_tpce_fs_mem_space,
5226           { "Mem space", "dvb-ci.cis.tpce_fs.mem_space",
5227             FT_UINT8, BASE_HEX, NULL, 0x60, NULL, HFILL }
5228         },
5229         { &hf_dvbci_cis_tpce_fs_irq,
5230           { "IRQ", "dvb-ci.cis.tpce_fs.irq",
5231             FT_UINT8, BASE_HEX, NULL, 0x10, NULL, HFILL }
5232         },
5233         { &hf_dvbci_cis_tpce_fs_io,
5234           { "IO Space", "dvb-ci.cis.tpce_fs.io",
5235             FT_UINT8, BASE_HEX, NULL, 0x08, NULL, HFILL }
5236         },
5237         { &hf_dvbci_cis_tplmid_manf,
5238           { "PC Card manufacturer code", "dvb-ci.cis.tplmid_manf",
5239             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5240         },
5241         { &hf_dvbci_cis_tplmid_card,
5242           { "Manufacturer info", "dvb-ci.cis.tplmid_card",
5243             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5244         },
5245         { &hf_dvbci_buf_size,
5246           { "Buffer Size", "dvb-ci.buf_size",
5247             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5248         },
5249         { &hf_dvbci_tcid,
5250           { "Transport Connection ID", "dvb-ci.tcid",
5251             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5252         },
5253         { &hf_dvbci_ml,
5254           { "More/Last indicator", "dvb-ci.more_last",
5255             FT_UINT8, BASE_HEX, VALS(dvbci_ml), 0, NULL, HFILL }
5256         },
5257         /* on the link layer, tpdus are reassembled */
5258         { &hf_dvbci_l_frags,
5259           { "Tpdu fragments", "dvb-ci.tpdu_fragments",
5260            FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
5261         },
5262         { &hf_dvbci_l_frag,
5263           { "Tpdu fragment", "dvb-ci.tpdu_fragment",
5264            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
5265         },
5266         { &hf_dvbci_l_frag_overlap,
5267           { "Tpdu fragment overlap", "dvb-ci.tpdu_fragment.overlap",
5268            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
5269         },
5270         { &hf_dvbci_l_frag_overlap_conflicts,
5271           { "Tpdu fragment overlapping with conflicting data",
5272            "dvb-ci.tpdu_fragment.overlap.conflicts",
5273            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
5274         },
5275         { &hf_dvbci_l_frag_multiple_tails,
5276           { "Tpdu has multiple tail fragments",
5277            "dvb-ci.tpdu_fragment.multiple_tails",
5278           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
5279         },
5280         { &hf_dvbci_l_frag_too_long_frag,
5281           { "Tpdu fragment too long", "dvb-ci.tpdu_fragment.too_long_fragment",
5282            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
5283         },
5284         { &hf_dvbci_l_frag_err,
5285           { "Tpdu defragmentation error", "dvb-ci.tpdu_fragment.error",
5286            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
5287         },
5288         { &hf_dvbci_l_frag_cnt,
5289           { "Tpdu fragment count", "dvb-ci.tpdu_fragment.count",
5290            FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
5291         },
5292         { &hf_dvbci_l_reass_in,
5293           { "Tpdu reassembled in", "dvb-ci.tpdu_reassembled.in",
5294            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
5295         },
5296         { &hf_dvbci_l_reass_len,
5297           { "Reassembled tpdu length", "dvb-ci.tpdu_reassembled.length",
5298            FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
5299         },
5300         { &hf_dvbci_c_tpdu_tag,
5301           { "Command TPDU Tag", "dvb-ci.c_tpdu_tag",
5302             FT_UINT8, BASE_HEX, VALS(dvbci_c_tpdu), 0, NULL, HFILL }
5303         },
5304         { &hf_dvbci_r_tpdu_tag,
5305            { "Response TPDU Tag", "dvb-ci.r_tpdu_tag",
5306              FT_UINT8, BASE_HEX, VALS(dvbci_r_tpdu), 0, NULL, HFILL }
5307         },
5308         { &hf_dvbci_t_c_id,
5309            { "Transport Connection ID", "dvb-ci.t_c_id",
5310              FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5311         },
5312         { &hf_dvbci_sb_value,
5313           { "SB Value", "dvb-ci.sb_value", FT_UINT8, BASE_HEX,
5314             VALS(dvbci_sb_value), 0, NULL, HFILL } },
5315
5316         /* on the transport layer, spdus are reassembled */
5317         { &hf_dvbci_t_frags,
5318           { "Spdu fragments", "dvb-ci.spdu_fragments",
5319            FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
5320         },
5321         { &hf_dvbci_t_frag,
5322           { "Spdu fragment", "dvb-ci.spdu_fragment",
5323            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
5324         },
5325         { &hf_dvbci_t_frag_overlap,
5326           { "Spdu fragment overlap", "dvb-ci.spdu_fragment.overlap",
5327            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
5328         },
5329         { &hf_dvbci_t_frag_overlap_conflicts,
5330           { "Spdu fragment overlapping with conflicting data",
5331            "dvb-ci.tpdu_fragment.overlap.conflicts",
5332           FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
5333         },
5334         { &hf_dvbci_t_frag_multiple_tails,
5335           { "Spdu has multiple tail fragments",
5336            "dvb-ci.spdu_fragment.multiple_tails",
5337            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
5338         },
5339         { &hf_dvbci_t_frag_too_long_frag,
5340           { "Spdu fragment too long", "dvb-ci.spdu_fragment.too_long_fragment",
5341            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
5342         },
5343         { &hf_dvbci_t_frag_err,
5344           { "Spdu defragmentation error", "dvb-ci.spdu_fragment.error",
5345            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
5346         },
5347         { &hf_dvbci_t_frag_cnt,
5348           { "Spdu fragment count", "dvb-ci.spdu_fragment.count",
5349            FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
5350         },
5351         { &hf_dvbci_t_reass_in,
5352           { "Spdu reassembled in", "dvb-ci.spdu_reassembled.in",
5353            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
5354         },
5355         { &hf_dvbci_t_reass_len,
5356           { "Reassembled spdu length", "dvb-ci.spdu_reassembled.length",
5357            FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
5358         },
5359         { &hf_dvbci_spdu_tag,
5360           { "SPDU Tag", "dvb-ci.spdu_tag",
5361            FT_UINT8, BASE_HEX, VALS(dvbci_spdu_tag), 0, NULL, HFILL }
5362         },
5363         { &hf_dvbci_sess_status,
5364           { "Session Status", "dvb-ci.session_status",
5365             FT_UINT8, BASE_HEX, VALS(dvbci_sess_status), 0, NULL, HFILL }
5366         },
5367         { &hf_dvbci_sess_nb,
5368           { "Session Number", "dvb-ci.session_nb",
5369             FT_UINT16, BASE_DEC, NULL , 0, NULL, HFILL }
5370         },
5371         { &hf_dvbci_close_sess_status,
5372           { "Session Status", "dvb-ci.close_session_status",
5373             FT_UINT8, BASE_HEX, VALS(dvbci_close_sess_status), 0, NULL, HFILL }
5374         },
5375         { &hf_dvbci_res_id_type,
5376           { "Resource ID Type", "dvb-ci.res.id_type",
5377             FT_UINT32, BASE_HEX, NULL, RES_ID_TYPE_MASK, NULL, HFILL }
5378         },
5379         { &hf_dvbci_res_class,
5380           { "Resource Class", "dvb-ci.res.class",
5381             FT_UINT32, BASE_HEX, VALS(dvbci_res_class), RES_CLASS_MASK, NULL, HFILL }
5382         },
5383         { &hf_dvbci_res_type,
5384           { "Resource Type", "dvb-ci.res.type",
5385             FT_UINT32, BASE_HEX, NULL, RES_TYPE_MASK, NULL, HFILL }
5386         },
5387         { &hf_dvbci_res_ver,
5388           { "Resource Version", "dvb-ci.res.version",
5389             FT_UINT32, BASE_HEX, NULL, RES_VER_MASK, NULL, HFILL }
5390         },
5391         { &hf_dvbci_apdu_tag,
5392           { "APDU Tag", "dvb-ci.apdu_tag",
5393             FT_UINT24, BASE_HEX, VALS(dvbci_apdu_tag), 0, NULL, HFILL }
5394         },
5395         { &hf_dvbci_app_type,
5396           { "Application type", "dvb-ci.ap.type",
5397             FT_UINT8, BASE_HEX, VALS(dvbci_app_type), 0, NULL, HFILL }
5398         },
5399         { &hf_dvbci_app_manf,
5400           { "Application manufacturer", "dvb-ci.ap.manufacturer",
5401             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5402         },
5403         { &hf_dvbci_manf_code,
5404           { "Manufacturer code", "dvb-ci.ap.manufacturer_code",
5405             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5406         },
5407         { &hf_dvbci_menu_str_len,
5408           { "Menu string length", "dvb-ci.ap.menu_string_length",
5409             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5410         },
5411         { &hf_dvbci_ap_char_tbl,
5412           { "Character table", "dvb-ci.ap.menu_char_tbl",
5413             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL}
5414         },
5415         { &hf_dvbci_menu_str,
5416           { "Menu string", "dvb-ci.ap.menu_string",
5417             FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }
5418         },
5419         { &hf_dvbci_data_rate,
5420           { "Transport stream data rate supported by the host",
5421             "dvb-ci.ap.data_rate",
5422             FT_UINT8, BASE_HEX, VALS(dvbci_data_rate), 0, NULL, HFILL }
5423         },
5424         { &hf_dvbci_ca_sys_id,
5425           { "CA system ID", "dvb-ci.ca.ca_system_id",
5426             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5427         },
5428         { &hf_dvbci_ca_pmt_list_mgmt,
5429           { "CA PMT list management", "dvb-ci.ca.ca_pmt_list_management",
5430             FT_UINT8, BASE_HEX, VALS(dvbci_ca_pmt_list_mgmt), 0, NULL,
5431             HFILL }
5432         },
5433         { &hf_dvbci_prog_num,
5434           { "Program number", "dvb-ci.ca.program_number",
5435             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5436         },
5437         { &hf_dvbci_prog_info_len,
5438           { "Program info length", "dvb-ci.ca.program_info_length",
5439             FT_UINT16, BASE_HEX, NULL, 0x0FFF, NULL, HFILL }
5440         },
5441         { &hf_dvbci_stream_type,
5442           { "Stream type", "dvb-ci.ca.stream_type", FT_UINT8,
5443               BASE_HEX|BASE_EXT_STRING, &mpeg_pmt_stream_type_vals_ext,
5444               0, NULL, HFILL }
5445         },
5446         { &hf_dvbci_es_pid,
5447           { "Elementary stream PID", "dvb-ci.ca.elementary_pid",
5448             FT_UINT16, BASE_HEX, NULL, 0x1FFF, NULL, HFILL }
5449         },
5450         { &hf_dvbci_es_info_len,
5451           { "Elementary stream info length", "dvb-ci.ca.es_info_length",
5452             FT_UINT16, BASE_HEX, NULL, 0x0FFF, NULL, HFILL }
5453         },
5454         { &hf_dvbci_ca_pmt_cmd_id,
5455           { "CA PMT command ID", "dvb-ci.ca.ca_pmt_cmd_id",
5456             FT_UINT8, BASE_HEX, VALS(dvbci_ca_pmt_cmd_id), 0, NULL, HFILL }
5457         },
5458         { &hf_dvbci_descr_len,
5459           { "CA descriptor length", "dvb-ci.ca.ca_desc_len",
5460             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5461         },
5462         { &hf_dvbci_ca_pid,
5463           { "CA PID", "dvb-ci.ca.ca_pid",
5464             FT_UINT16, BASE_HEX, NULL, 0x1FFF, NULL, HFILL }
5465         },
5466         { &hf_dvbci_ca_enable_flag,
5467           { "CA enable flag", "dvb-ci.ca.ca_enable_flag",
5468             FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL }
5469         },
5470         { &hf_dvbci_ca_enable,
5471           { "CA enable", "dvb-ci.ca.ca_enable",
5472             FT_UINT8, BASE_HEX, VALS(dvbci_ca_enable), 0x7F, NULL, HFILL }
5473         },
5474         { &hf_dvbci_auth_proto_id,
5475           { "Authentication protocol ID", "dvb-ci.aut.proto_id",
5476             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5477         },
5478         { &hf_dvbci_auth_req_bytes,
5479           { "Authentication request data", "dvb-ci.aut.req",
5480             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5481         },
5482         { &hf_dvbci_auth_resp_bytes,
5483           { "Authentication response data", "dvb-ci.aut.resp",
5484             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5485         },
5486         { &hf_dvbci_network_id,
5487           { "Network ID", "dvb-ci.hc.nid",
5488             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5489         },
5490         { &hf_dvbci_original_network_id,
5491           { "Original network ID", "dvb-ci.hc.onid",
5492             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5493         },
5494         { &hf_dvbci_transport_stream_id,
5495           { "Transport stream ID", "dvb-ci.hc.tsid",
5496             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5497         },
5498         { &hf_dvbci_service_id,
5499           { "Service ID", "dvb-ci.hc.svcid",
5500             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5501         },
5502         { &hf_dvbci_replacement_ref,
5503           { "Replacement reference", "dvb-ci.hc.replacement_ref",
5504             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5505         },
5506         { &hf_dvbci_replaced_pid,
5507           { "Replaced PID", "dvb-ci.hc.replaced_pid",
5508             FT_UINT16, BASE_HEX, NULL, 0x1FFF, NULL, HFILL }
5509         },
5510         { &hf_dvbci_replacement_pid,
5511           { "Replacement PID", "dvb-ci.hc.replacement_pid",
5512             FT_UINT16, BASE_HEX, NULL, 0x1FFF, NULL, HFILL }
5513         },
5514         { &hf_dvbci_pmt_flag,
5515           { "PMT flag", "dvb-ci.hc.pmt_flag",
5516             FT_UINT8, BASE_HEX, NULL, 0x01, NULL, HFILL }
5517         },
5518         { &hf_dvbci_hc_desc_loop_len,
5519           { "Descriptor loop length", "dvb-ci.hc.desc_loop_len",
5520             FT_UINT16, BASE_DEC, NULL, 0x0FFF, NULL, HFILL }
5521         },
5522         { &hf_dvbci_hc_status,
5523           { "Status field", "dvb-ci.hc.status_field",
5524             FT_UINT8, BASE_HEX, VALS(dvbci_hc_status), 0, NULL, HFILL }
5525         },
5526         { &hf_dvbci_hc_release_reply,
5527           { "Release reply", "dvb-ci.hc.release_reply",
5528             FT_UINT8, BASE_HEX, VALS(dvbci_hc_release_reply), 0, NULL, HFILL }
5529         },
5530         { &hf_dvbci_resp_intv,
5531           { "Response interval", "dvb-ci.dt.resp_interval",
5532             FT_RELATIVE_TIME, BASE_NONE, NULL, 0, NULL, HFILL }
5533         },
5534         { &hf_dvbci_utc_time,
5535           { "UTC time", "dvb-ci.dt.utc_time",
5536             FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
5537         },
5538
5539         /* we have to use FT_INT16 instead of FT_RELATIVE_TIME,
5540            local offset can be negative */
5541         { &hf_dvbci_local_offset,
5542           { "Local time offset", "dvb-ci.dt.local_offset",
5543             FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
5544         },
5545         { &hf_dvbci_close_mmi_cmd_id,
5546           { "Command ID", "dvb-ci.mmi.close_mmi_cmd_id",
5547             FT_UINT8, BASE_HEX, VALS(dvbci_close_mmi_cmd_id), 0, NULL, HFILL }
5548         },
5549         { &hf_dvbci_close_mmi_delay,
5550           { "Delay (in sec)", "dvb-ci.mmi.delay",
5551             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5552         },
5553         { &hf_dvbci_disp_ctl_cmd,
5554           { "Command", "dvb-ci.mmi.disp_ctl_cmd",
5555             FT_UINT8, BASE_HEX, VALS(dvbci_disp_ctl_cmd), 0, NULL, HFILL }
5556         },
5557         { &hf_dvbci_mmi_mode,
5558           { "MMI mode", "dvb-ci.mmi.mode",
5559             FT_UINT8, BASE_HEX, VALS(dvbci_mmi_mode), 0, NULL, HFILL }
5560         },
5561         { &hf_dvbci_disp_rep_id,
5562           { "Reply ID", "dvb-ci.mmi.disp_rep_id",
5563             FT_UINT8, BASE_HEX, VALS(dvbci_disp_rep_id), 0, NULL, HFILL }
5564         },
5565         { &hf_dvbci_mmi_char_tbl,
5566           { "Character table", "dvb-ci.mmi.char_tbl",
5567             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL}
5568         },
5569         { &hf_dvbci_blind_ans,
5570           { "Blind answer flag", "dvb-ci.mmi.blind_ans",
5571             FT_UINT8, BASE_HEX, VALS(dvbci_blind_ans), 0x01, NULL, HFILL }
5572         },
5573         { &hf_dvbci_ans_txt_len,
5574           { "Answer text length", "dvb-ci.mmi.ans_txt_len",
5575             FT_UINT8, BASE_DEC, NULL , 0, NULL, HFILL }
5576         },
5577         { &hf_dvbci_enq,
5578           { "Enquiry string", "dvb-ci.mmi.enq",
5579             FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }
5580         },
5581         { &hf_dvbci_ans_id,
5582           { "Answer ID", "dvb-ci.mmi.ans_id",
5583             FT_UINT8, BASE_HEX, VALS(dvbci_ans_id) , 0, NULL, HFILL }
5584         },
5585         { &hf_dvbci_ans,
5586           { "Answer", "dvb-ci.mmi.ans",
5587             FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }
5588         },
5589         { &hf_dvbci_choice_nb,
5590           { "Number of menu items", "dvb-ci.mmi.choice_nb",
5591             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5592         },
5593         { &hf_dvbci_choice_ref,
5594           { "Selected item", "dvb-ci.mmi.choice_ref",
5595             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5596         },
5597         { &hf_dvbci_item_nb,
5598           { "Number of list items", "dvb-ci.mmi.item_nb",
5599             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5600         },
5601         { &hf_dvbci_title,
5602           { "Title", "dvb-ci.mmi.title",
5603             FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }
5604         },
5605         { &hf_dvbci_subtitle,
5606           { "Sub-title", "dvb-ci.mmi.subtitle",
5607             FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }
5608         },
5609         { &hf_dvbci_bottom,
5610           { "Bottom line", "dvb-ci.mmi.bottom",
5611             FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }
5612         },
5613         { &hf_dvbci_item,
5614           { "Item", "dvb-ci.mmi.item",
5615             FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }
5616         },
5617         { &hf_dvbci_host_country,
5618           { "Host country", "dvb-ci.hlc.country",
5619             FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }
5620         },
5621         { &hf_dvbci_host_language,
5622           { "Host language", "dvb-ci.hlc.language",
5623             FT_STRING, STR_UNICODE, NULL, 0, NULL, HFILL }
5624         },
5625         { &hf_dvbci_cup_type,
5626           { "CAM upgrade type", "dvb-ci.cup.type",
5627             FT_UINT8, BASE_HEX, VALS(dvbci_cup_type), 0, NULL, HFILL }
5628         },
5629         { &hf_dvbci_cup_download_time,
5630           { "Download time", "dvb-ci.cup.download_time",
5631             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5632         },
5633         { &hf_dvbci_cup_answer,
5634           { "CAM upgrade answer", "dvb-ci.cup.answer",
5635             FT_UINT8, BASE_HEX, VALS(dvbci_cup_answer), 0, NULL, HFILL }
5636         },
5637         { &hf_dvbci_cup_progress,
5638           { "CAM upgrade progress", "dvb-ci.cup.progress",
5639             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5640         },
5641         { &hf_dvbci_cup_reset,
5642           { "requested CAM reset", "dvb-ci.cup.reset",
5643             FT_UINT8, BASE_HEX, VALS(dvbci_cup_reset), 0, NULL, HFILL }
5644         },
5645         { &hf_dvbci_cc_sys_id_bitmask,
5646           { "CC system id bitmask", "dvb-ci.cc.sys_id_bitmask",
5647             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5648         },
5649         { &hf_dvbci_cc_dat_id,
5650           { "CC datatype id", "dvb-ci.cc.datatype_id",
5651             FT_UINT8, BASE_HEX, VALS(dvbci_cc_dat_id), 0, NULL, HFILL }
5652         },
5653         { &hf_dvbci_brand_cert,
5654           { "Brand certificate", "dvb-ci.cc.brand_cert",
5655             FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
5656         },
5657         { &hf_dvbci_dev_cert,
5658           { "Device certificate", "dvb-ci.cc.dev_cert",
5659             FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
5660         },
5661         { &hf_dvbci_uri_ver,
5662           { "URI version", "dvb-ci.cc.uri.version",
5663             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5664         },
5665         { &hf_dvbci_uri_aps,
5666           { "APS", "dvb-ci.cc.uri.aps",
5667             FT_UINT8, BASE_HEX, NULL, 0xC0, NULL, HFILL }
5668         },
5669         { &hf_dvbci_uri_emi,
5670           { "EMI", "dvb-ci.cc.uri.emi",
5671             FT_UINT8, BASE_HEX, VALS(dvbci_cc_uri_emi), 0x30, NULL, HFILL }
5672         },
5673         { &hf_dvbci_uri_ict,
5674           { "Image constraint token", "dvb-ci.cc.uri.ict",
5675             FT_UINT8, BASE_HEX, NULL, 0x08, NULL, HFILL }
5676         },
5677         { &hf_dvbci_uri_rct,
5678           { "Redistribution control trigger (RCT)", "dvb-ci.cc.uri.rct",
5679             FT_UINT8, BASE_HEX, NULL, 0x04, NULL, HFILL }
5680         },
5681         { &hf_dvbci_uri_dot,
5682           { "Digital only token (DOT)", "dvb-ci.cc.uri.dot",
5683             FT_UINT8, BASE_HEX, NULL, 0x01, NULL, HFILL }
5684         },
5685         /* retention limit is 6bit in URIv1 and 8bit in URIv2 and later
5686            the position depends on the version, we can't define a mask here */
5687         { &hf_dvbci_uri_rl,
5688           { "Retention limit", "dvb-ci.cc.uri.rl",
5689             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5690         },
5691         { &hf_dvbci_cc_key_register,
5692           { "Key register", "dvb-ci.cc.key_register",
5693             FT_UINT8, BASE_HEX, VALS(dvbci_cc_key_register), 0, NULL, HFILL }
5694         },
5695         { &hf_dvbci_cc_status_field,
5696           { "Status field", "dvb-ci.cc.status_field",
5697             FT_UINT8, BASE_HEX, VALS(dvbci_cc_status), 0, NULL, HFILL }
5698         },
5699         { &hf_dvbci_cc_op_mode,
5700           { "Operating mode", "dvb-ci.cc.op_mode",
5701             FT_UINT8, BASE_HEX, VALS(dvbci_cc_op_mode), 0, NULL, HFILL }
5702         },
5703         { &hf_dvbci_cc_data,
5704           { "Data", "dvb-ci.cc.data",
5705             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5706         },
5707         { &hf_dvbci_sac_msg_ctr,
5708           { "Message counter", "dvb-ci.cc.sac.msg_ctr",
5709             FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
5710         },
5711         { &hf_dvbci_sac_proto_ver,
5712           { "Protocol version", "dvb-ci.cc.sac.proto_ver",
5713             FT_UINT8, BASE_HEX, NULL, 0xF0, NULL, HFILL }
5714         },
5715         { &hf_dvbci_sac_auth_cip,
5716           { "Authentication cipher", "dvb-ci.cc.sac.auth_cip",
5717             FT_UINT8, BASE_HEX, VALS(dvbci_cc_sac_auth), 0x0E, NULL, HFILL }
5718         },
5719         { &hf_dvbci_sac_payload_enc,
5720           { "Payload encryption flag", "dvb-ci.cc.sac.payload_enc",
5721             FT_UINT8, BASE_HEX, NULL, 0x01, NULL, HFILL }
5722         },
5723         { &hf_dvbci_sac_enc_cip,
5724           { "Encryption cipher", "dvb-ci.cc.sac.enc_cip",
5725             FT_UINT8, BASE_HEX, VALS(dvbci_cc_sac_enc), 0xE0, NULL, HFILL }
5726         },
5727         { &hf_dvbci_sac_payload_len,
5728           { "Payload length", "dvb-ci.cc.sac.payload_len",
5729             FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
5730         },
5731         { &hf_dvbci_sac_enc_body,
5732           { "Encrypted SAC body", "dvb-ci.cc.sac.enc_body",
5733             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5734         },
5735         { &hf_dvbci_sac_padding,
5736           { "Padding", "dvb-ci.cc.sac.padding",
5737             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5738         },
5739         { &hf_dvbci_sac_signature,
5740           { "Signature", "dvb-ci.cc.sac.signature",
5741             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5742         },
5743         { &hf_dvbci_rating,
5744           { "Rating", "dvb-ci.cc.rating",
5745             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5746         },
5747         { &hf_dvbci_capability_field,
5748           { "Capability field", "dvb-ci.cc.capability_field",
5749             FT_UINT8, BASE_HEX, VALS(dvbci_cc_cap), 0, NULL, HFILL }
5750         },
5751         { &hf_dvbci_pin_chg_time,
5752           { "PIN change time (UTC)", "dvb-ci.cc.pin_change_time",
5753             FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
5754         },
5755         { &hf_dvbci_pincode_status,
5756           { "Pincode status field", "dvb-ci.cc.pincode_status_field",
5757             FT_UINT8, BASE_HEX, VALS(dvbci_pincode_status), 0, NULL, HFILL }
5758         },
5759         { &hf_dvbci_cc_prog_num,
5760           { "Program number", "dvb-ci.cc.program_number",
5761             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5762         },
5763         { &hf_dvbci_pin_evt_time,
5764           { "PIN event time (UTC)", "dvb-ci.cc.pin_event_time",
5765             FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
5766         },
5767         { &hf_dvbci_pin_evt_cent,
5768           { "PIN event time centiseconds", "dvb-ci.cc.pin_event_time_centi",
5769             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5770         },
5771         { &hf_dvbci_cc_priv_data,
5772           { "Private data", "dvb-ci.cc.private_data",
5773             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5774         },
5775         { &hf_dvbci_pincode,
5776           { "PIN code", "dvb-ci.cc.pincode",
5777             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
5778         },
5779         { &hf_dvbci_app_dom_id,
5780           { "Application Domain Identifier", "dvb-ci.ami.app_dom_id",
5781             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
5782         },
5783         { &hf_dvbci_init_obj,
5784           { "Initial Object", "dvb-ci.ami.init_obj",
5785             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
5786         },
5787         { &hf_dvbci_ack_code,
5788           { "Acknowledgement", "dvb-ci.ami.ack_code",
5789             FT_UINT8, BASE_HEX, VALS(dvbci_ack_code), 0, NULL, HFILL }
5790         },
5791         { &hf_dvbci_req_type,
5792           { "Request type", "dvb-ci.ami.req_type",
5793             FT_UINT8, BASE_HEX, VALS(dvbci_req_type), 0, NULL, HFILL }
5794         },
5795         { &hf_dvbci_file_hash,
5796           { "File hash", "dvb-ci.ami.file_hash",
5797             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5798         },
5799         { &hf_dvbci_file_name,
5800           { "File name", "dvb-ci.ami.file_name",
5801             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
5802         },
5803         { &hf_dvbci_ami_priv_data,
5804           { "Private data", "dvb-ci.ami.private_data",
5805             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5806         },
5807         { &hf_dvbci_req_ok,
5808           { "RequestOK", "dvb-ci.ami.request_ok",
5809             FT_UINT8, BASE_HEX, NULL, 0x02, NULL, HFILL }
5810         },
5811         { &hf_dvbci_file_ok,
5812           { "FileOK", "dvb-ci.ami.file_ok",
5813             FT_UINT8, BASE_HEX, NULL, 0x01, NULL, HFILL }
5814         },
5815         { &hf_dvbci_file_data,
5816           { "File data", "dvb-ci.ami.file_data",
5817             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5818         },
5819         { &hf_dvbci_abort_req_code,
5820           { "Abort request code", "dvb-ci.ami.abort_req_code",
5821             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5822         },
5823         { &hf_dvbci_abort_ack_code,
5824           { "Abort acknowledgement code", "dvb-ci.ami.abort_ack_code",
5825             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
5826         },
5827         { &hf_dvbci_phase_id,
5828           { "Phase ID", "dvb-ci.lsc.comms_phase_id",
5829             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5830         },
5831         { &hf_dvbci_comms_rep_id,
5832           { "Comms reply ID", "dvb-ci.lsc.comms_reply_id",
5833             FT_UINT8, BASE_HEX, VALS(dvbci_comms_rep_id), 0, NULL, HFILL }
5834         },
5835         { &hf_dvbci_lsc_buf_size,
5836           { "Buffer size", "dvb-ci.lsc.buf_size",
5837             FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
5838         },
5839         { &hf_dvbci_lsc_ret_val,
5840           { "Return value", "dvb-ci.lsc.return_value",
5841             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5842         },
5843         { &hf_dvbci_comms_cmd_id,
5844           { "Comms command ID", "dvb-ci.lsc.comms_cmd_id",
5845             FT_UINT8, BASE_HEX, VALS(dvbci_comms_cmd_id), 0, NULL, HFILL }
5846         },
5847         { &hf_dvbci_conn_desc_type,
5848           { "Type", "dvb-ci.lsc.conn_desc_type",
5849             FT_UINT8, BASE_HEX, VALS(dvbci_conn_desc_type), 0, NULL, HFILL }
5850         },
5851         { &hf_dvbci_lsc_media_tag,
5852           { "Tag", "dvb-ci.lsc.media_tag",
5853             FT_UINT8, BASE_HEX, VALS(dvbci_lsc_desc_tag), 0, NULL, HFILL }
5854         },
5855         { &hf_dvbci_lsc_media_len,
5856           { "Length", "dvb-ci.lsc.media_len",
5857             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5858         },
5859         { &hf_dvbci_lsc_ip_ver,
5860           { "IP version", "dvb-ci.lsc.ip_version",
5861             FT_UINT8, BASE_DEC, VALS(dvbci_lsc_ip_ver), 0, NULL, HFILL }
5862         },
5863         { &hf_dvbci_lsc_ipv4_addr,
5864           { "IP address", "dvb-ci.lsc.ipv4_addr",
5865             FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }
5866         },
5867         { &hf_dvbci_lsc_ipv6_addr,
5868           { "IPv6 address", "dvb-ci.lsc.ipv6_addr",
5869             FT_IPv6, BASE_NONE, NULL, 0, NULL, HFILL }
5870         },
5871         { &hf_dvbci_lsc_dst_port,
5872           { "Destination port", "dvb-ci.lsc.dst_port",
5873             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5874         },
5875         { &hf_dvbci_lsc_proto,
5876           { "Protocol", "dvb-ci.lsc.protocol",
5877             FT_UINT8, BASE_HEX, VALS(dvbci_lsc_proto), 0, NULL, HFILL }
5878         },
5879         { &hf_dvbci_lsc_hostname,
5880           { "Hostname", "dvb-ci.lsc.hostname",
5881             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
5882         },
5883         { &hf_dvbci_lsc_retry_count,
5884           { "Retry count", "dvb-ci.lsc.retry_count",
5885             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5886         },
5887         { &hf_dvbci_lsc_timeout,
5888           { "Timeout", "dvb-ci.lsc.timeout",
5889             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
5890         },
5891
5892         /* filter string for hf_dvbci_info_ver_op_status and
5893          * hf_dvbci_info_ver_op_info below is the same, it seems this is ok */
5894         { &hf_dvbci_info_ver_op_status,
5895           { "Info version", "dvb-ci.opp.info_ver",
5896             FT_UINT8, BASE_HEX, NULL, 0xE0, NULL, HFILL }
5897         },
5898         { &hf_dvbci_nit_ver,
5899           { "NIT version", "dvb-ci.opp.nit_ver",
5900             FT_UINT8, BASE_HEX, NULL, 0x1F, NULL, HFILL }
5901         },
5902         { &hf_dvbci_pro_typ,
5903           { "Profile type", "dvb-ci.opp.profile_type",
5904             FT_UINT8, BASE_HEX, NULL, 0xC0, NULL, HFILL }
5905         },
5906         { &hf_dvbci_init_flag,
5907           { "Initialized flag", "dvb-ci.opp.init_flag",
5908             FT_UINT8, BASE_HEX, NULL, 0x20, NULL, HFILL }
5909         },
5910         { &hf_dvbci_ent_chg_flag,
5911           { "Entitlement change flag", "dvb-ci.opp.ent_chg_flag",
5912             FT_UINT8, BASE_HEX, NULL, 0x10, NULL, HFILL }
5913         },
5914         { &hf_dvbci_ent_val_flag,
5915           { "Entitlement valid flag", "dvb-ci.opp.ent_val_flag",
5916             FT_UINT8, BASE_HEX, NULL, 0x08, NULL, HFILL }
5917         },
5918         { &hf_dvbci_ref_req_flag,
5919           { "Refresh request flag", "dvb-ci.opp.refresh_req_flag",
5920             FT_UINT8, BASE_HEX, VALS(dvbci_opp_ref_req_flag), 0x03, NULL, HFILL }
5921         },
5922         { &hf_dvbci_err_flag,
5923           { "Error flag", "dvb-ci.opp.err_flag",
5924             FT_UINT8, BASE_HEX, VALS(dvbci_opp_err_flag), 0xF0, NULL, HFILL }
5925         },
5926         { &hf_dvbci_dlv_sys_hint,
5927           { "Delivery system hint", "dvb-ci.opp.dlv_sys_hint",
5928             FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }
5929         },
5930         { &hf_dvbci_dlv_sys_hint_t,
5931           { "terrestrial network (DVB-T/T2)", "dvb-ci.opp.dlv_sys_hint.t",
5932              FT_BOOLEAN, 4, TFS(&tfs_set_notset), 0x04, NULL, HFILL }
5933         },
5934         { &hf_dvbci_dlv_sys_hint_s,
5935           { "satellite network (DVB-S/S2)", "dvb-ci.opp.dlv_sys_hint.s",
5936              FT_BOOLEAN, 4, TFS(&tfs_set_notset), 0x02, NULL, HFILL }
5937         },
5938         { &hf_dvbci_dlv_sys_hint_c,
5939           { "cable network (DVB-C/C2)", "dvb-ci.opp.dlv_sys_hint.c",
5940              FT_BOOLEAN, 4, TFS(&tfs_set_notset), 0x01, NULL, HFILL }
5941         },
5942         { &hf_dvbci_refr_req_date,
5943           { "Refresh request date", "dvb-ci.opp.refresh_req_date",
5944             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5945         },
5946         { &hf_dvbci_refr_req_time,
5947           { "Refresh request time", "dvb-ci.opp.refresh_req_time",
5948             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
5949         },
5950         { &hf_dvbci_nit_loop_len,
5951           { "NIT loop length", "dvb-ci.opp.nit_loop_len",
5952             FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
5953         },
5954         { &hf_dvbci_info_valid,
5955           { "Info valid", "dvb-ci.opp.info_valid",
5956             FT_UINT8, BASE_HEX, NULL, 0x08, NULL, HFILL }
5957         },
5958         { &hf_dvbci_info_ver_op_info,
5959           { "Info version", "dvb-ci.opp.info_ver",
5960             FT_UINT8, BASE_HEX, NULL, 0x07, NULL, HFILL }
5961         },
5962         { &hf_dvbci_cicam_onid,
5963           { "CICAM original network id", "dvb-ci.opp.cicam_onid",
5964             FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
5965         },
5966         { &hf_dvbci_cicam_id,
5967           { "CICAM ID", "dvb-ci.opp.cicam_id",
5968             FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
5969         },
5970         { &hf_dvbci_opp_char_tbl,
5971           { "Character table", "dvb-ci.opp.char_tbl",
5972             FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL}
5973         },
5974         { &hf_dvbci_sdt_rst_trusted,
5975           { "SDT running status trusted", "dvb-ci.opp.sdt_rst_trusted",
5976             FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL }
5977         },
5978         { &hf_dvbci_eit_rst_trusted,
5979           { "EIT running status trusted", "dvb-ci.opp.eit_rst_trusted",
5980             FT_UINT8, BASE_HEX, NULL, 0x40, NULL, HFILL }
5981         },
5982         { &hf_dvbci_eit_pf_usage,
5983           { "EIT present/following usage", "dvb-ci.opp.eit_pf_usage",
5984             FT_UINT8, BASE_HEX, VALS(dvbci_opp_eit_pf_usage), 0x30, NULL, HFILL }
5985         },
5986         { &hf_dvbci_eit_sch_usage,
5987           { "EIT schedule usage", "dvb-ci.opp.eit_sch_usage",
5988             FT_UINT8, BASE_HEX, VALS(dvbci_opp_eit_sch_usage), 0x0E, NULL, HFILL }
5989         },
5990         { &hf_dvbci_ext_evt_usage,
5991           { "Extended event usage", "dvb-ci.opp.ext_evt_usage",
5992             FT_UINT8, BASE_HEX, VALS(dvbci_opp_ext_evt), 0x01, NULL, HFILL }
5993         },
5994         { &hf_dvbci_sdt_oth_trusted,
5995           { "SDT_other trusted", "dvb-ci.opp.sdt_oth_trusted",
5996             FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL }
5997         },
5998         { &hf_dvbci_eit_evt_trigger,
5999           { "EIT event trigger", "dvb-ci.opp.eit_evt_trigger",
6000             FT_UINT8, BASE_HEX, NULL, 0x40, NULL, HFILL }
6001         },
6002         { &hf_dvbci_opp_lang_code,
6003           { "Language code", "dvb-ci.opp.lang_code",
6004             FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL }
6005         },
6006         { &hf_dvbci_prof_name,
6007           { "Profile name", "dvb-ci.opp.profile_name",
6008             FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
6009         },
6010         { &hf_dvbci_unattended,
6011           { "Unattended flag", "dvb-ci.opp.unattended_flag",
6012             FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL }
6013         },
6014         { &hf_dvbci_opp_srv_type,
6015           { "Service type", "dvb-ci.opp.service_type", FT_UINT8,
6016               BASE_HEX|BASE_EXT_STRING, &mpeg_descr_service_type_vals_ext,
6017               0, NULL, HFILL }
6018         },
6019         { &hf_dvbci_dlv_cap_byte,
6020           { "Delivery capability byte", "dvb-ci.opp.dlv_cap_byte",
6021             FT_UINT8, BASE_HEX, VALS(dvbci_opp_dlv_cap), 0, NULL, HFILL }
6022         },
6023
6024         /* the CI+ spec is not particularly clear about this but an
6025          * application id in the capability loop must always be 2 bytes */
6026         { &hf_dvbci_app_cap_bytes,
6027           { "Application capability bytes", "dvb-ci.opp.app_cap_bytes",
6028             FT_UINT16, BASE_HEX|BASE_EXT_STRING,
6029             &mpeg_descr_data_bcast_id_vals_ext, 0, NULL, HFILL }
6030         },
6031         { &hf_dvbci_desc_num,
6032           { "Next unprocessed descriptor number", "dvb-ci.opp.desc_num",
6033             FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
6034         },
6035         { &hf_dvbci_sig_strength,
6036           { "Signal strength", "dvb-ci.opp.sig_strength",
6037             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
6038         },
6039         { &hf_dvbci_sig_qual,
6040           { "Signal quality", "dvb-ci.opp.sig_qual",
6041             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
6042         },
6043         { &hf_dvbci_opp_tune_status,
6044           { "Tuning status", "dvb-ci.opp.tune_status",
6045             FT_UINT8, BASE_HEX, VALS(dvbci_opp_tune_stat), 0xF0, NULL, HFILL }
6046         },
6047         { &hf_dvbci_opp_desc_loop_len,
6048           { "Descriptor loop length", "dvb-ci.opp.desc_loop_len",
6049             FT_UINT16, BASE_DEC, NULL, 0x0FFF, NULL, HFILL }
6050         },
6051         { &hf_dvbci_sas_app_id,
6052           { "Application ID", "dvb-ci.sas.app_id",
6053             FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL }
6054         },
6055         { &hf_dvbci_sas_sess_state,
6056           { "Connection state", "dvb-ci.sas.sess_state",
6057             FT_UINT8, BASE_DEC, VALS(dvbci_sas_sess_state), 0, NULL, HFILL }
6058         },
6059         { &hf_dvbci_sas_msg_nb,
6060           { "Message number", "dvb-ci.sas.msg_nb",
6061             FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
6062         },
6063         { &hf_dvbci_sas_msg_len,
6064           { "Message length", "dvb-ci.sas.msg_len",
6065             FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
6066         }
6067     };
6068
6069     static ei_register_info ei[] = {
6070         { &ei_dvbci_invalid_char_tbl,
6071             { "dvb-ci.invalid_char_tbl", PI_MALFORMED, PI_ERROR,
6072                 "Invalid character table", EXPFILL }},
6073         { &ei_dvbci_ca_pmt_cmd_id, { "dvb-ci.ca.ca_pmt_cmd_id.ca_pmt", PI_MALFORMED, PI_ERROR, "The ca_pmt shall only contain ca descriptors (tag 0x9)", EXPFILL }},
6074         { &ei_dvbci_bad_length, { "dvb-ci.bad_length", PI_MALFORMED, PI_ERROR, "Invalid APDU length field, %s must be a multiple of 4 bytes", EXPFILL }},
6075         { &ei_dvbci_network_id, { "dvb-ci.hc.nid.ignored", PI_PROTOCOL, PI_NOTE, "Network ID is usually ignored by hosts", EXPFILL }},
6076         { &ei_dvbci_not_text_more_or_text_last, { "dvb-ci.not_text_more_or_text_last", PI_MALFORMED, PI_ERROR, "Items must be text_more() or text_last() objects", EXPFILL }},
6077         { &ei_dvbci_cup_progress, { "dvb-ci.cup.progress.invalid", PI_PROTOCOL, PI_WARN, "progress is in percent, value must be between 0 and 100", EXPFILL }},
6078         { &ei_dvbci_sac_payload_enc, { "dvb-ci.cc.sac.payload_enc.clear", PI_PROTOCOL, PI_NOTE, "The original PDU was encrypted, this exported PDU is in the clear", EXPFILL }},
6079         { &ei_dvbci_pin_evt_cent, { "dvb-ci.cc.pin_event_time_centi.invalid", PI_PROTOCOL, PI_WARN, "Invalid value for event time centiseconds, Value must be between 0 and 100", EXPFILL }},
6080         { &ei_dvbci_cicam_nit_table_id, { "dvb-ci.cicam_nit.table_id.invalid", PI_PROTOCOL, PI_WARN, "CICAM NIT must have table id 0x40 (NIT actual)", EXPFILL }},
6081         { &ei_dvbci_sig_qual, { "dvb-ci.opp.sig_qual.invalid", PI_PROTOCOL, PI_WARN, "Invalid value for signal strength / signal quality, values are in percent (0 to 100)", EXPFILL }},
6082         { &ei_dvbci_apdu_tag, { "dvb-ci.apdu_tag.invalid", PI_MALFORMED, PI_ERROR, "Invalid or unsupported APDU tag", EXPFILL }},
6083         { &ei_dvbci_apdu_not_supported, { "dvb-ci.apdu_not_supported", PI_PROTOCOL, PI_WARN, "Dissection of this APDU is not supported", EXPFILL }},
6084         { &ei_dvbci_apu_host_to_cam, { "dvb-ci.apu.host_to_cam", PI_PROTOCOL, PI_WARN, "Invalid APDU direction, this APDU must be sent from host to CAM", EXPFILL }},
6085         { &ei_dvbci_apu_cam_to_host, { "dvb-ci.apu.cam_to_host", PI_PROTOCOL, PI_WARN, "Invalid APDU direction, this APDU must be sent from CAM to host", EXPFILL }},
6086         { &ei_dvbci_res_class, { "dvb-ci.res.class.invalid", PI_PROTOCOL, PI_WARN, "Invalid resource class for this apdu", EXPFILL }},
6087         { &ei_dvbci_res_ver, { "dvb-ci.res.version.old", PI_PROTOCOL, PI_WARN, "Invalid resource version for this apdu", EXPFILL }},
6088         { &ei_dvbci_spdu_tag, { "dvb-ci.spdu_tag.invalid", PI_MALFORMED, PI_ERROR, "Invalid SPDU tag, See table 14 in the DVB-CI specification", EXPFILL }},
6089         { &ei_dvbci_spdu_host_to_cam, { "dvb-ci.spdu.host_to_cam", PI_PROTOCOL, PI_WARN, "Invalid SPDU direction, this SPDU must be sent from host to CAM", EXPFILL }},
6090         { &ei_dvbci_spdu_cam_to_host, { "dvb-ci.spdu.cam_to_host", PI_PROTOCOL, PI_WARN, "Invalid SPDU direction, this SPDU must be sent from CAM to host", EXPFILL }},
6091         { &ei_dvbci_tpdu_status_tag, { "dvb-ci.tpdu.status_tag.invalid", PI_MALFORMED, PI_ERROR, "Invalid status tag, this must always be T_SB (0x80)", EXPFILL }},
6092         { &ei_dvbci_t_c_id, { "dvb-ci.t_c_id.invalid", PI_PROTOCOL, PI_WARN, "Transport Connection ID mismatch, tcid is %d in the transport layer and %d in the link layer", EXPFILL }},
6093         { &ei_dvbci_sb_value, { "dvb-ci.sb_value.invalid", PI_PROTOCOL, PI_WARN, "Invalid SB_value, must be 0x00 or 0x80", EXPFILL }},
6094         { &ei_dvbci_c_tpdu_tag, { "dvb-ci.c_tpdu_tag.invalid", PI_MALFORMED, PI_ERROR, "Invalid Command-TPDU tag, see DVB-CI specification, table A.16 for valid values", EXPFILL }},
6095         { &ei_dvbci_r_tpdu_tag, { "dvb-ci.r_tpdu_tag.invalid", PI_MALFORMED, PI_ERROR, "Invalid Response-TPDU tag, see DVB-CI specification, table A.16 for valid values", EXPFILL }},
6096         { &ei_dvbci_r_tpdu_status_mandatory, { "dvb-ci.r_tpdu_status.mandatory", PI_MALFORMED, PI_ERROR, "Response TPDU's status part is missing, RTPDU status is mandatory", EXPFILL }},
6097         { &ei_dvbci_ml, { "dvb-ci.more_last.invalid", PI_PROTOCOL, PI_WARN, "Invalid More/Last indicator, second byte of an LPDU must be 0x80 or 0x00", EXPFILL }},
6098         { &ei_dvbci_buf_size, { "dvb-ci.buf_size.invalid", PI_PROTOCOL, PI_WARN, "Illegal buffer size command", EXPFILL }},
6099         { &ei_dvbci_cor_addr, { "dvb-ci.cor_address.invalid", PI_PROTOCOL, PI_WARN, "COR address must not be greater than 0xFFE (DVB-CI spec, A.5.6)", EXPFILL }},
6100     };
6101
6102     spdu_table = g_hash_table_new(g_direct_hash, g_direct_equal);
6103     for(i=0; i<array_length(spdu_info); i++) {
6104         g_hash_table_insert(spdu_table,
6105                             GUINT_TO_POINTER((guint)spdu_info[i].tag),
6106                             (const gpointer)(&spdu_info[i]));
6107     }
6108
6109     apdu_table = g_hash_table_new(g_direct_hash, g_direct_equal);
6110     for(i=0; i<array_length(apdu_info); i++) {
6111         g_hash_table_insert(apdu_table,
6112                             GUINT_TO_POINTER((guint)apdu_info[i].tag),
6113                             (const gpointer)(&apdu_info[i]));
6114     }
6115
6116     proto_dvbci = proto_register_protocol("DVB Common Interface", "DVB-CI", "dvb-ci");
6117     proto_register_field_array(proto_dvbci, hf, array_length(hf));
6118     proto_register_subtree_array(ett, array_length(ett));
6119     expert_dvbci = expert_register_protocol(proto_dvbci);
6120     expert_register_field_array(expert_dvbci, ei, array_length(ei));
6121
6122     dvbci_module = prefs_register_protocol(
6123         proto_dvbci, proto_reg_handoff_dvbci);
6124     prefs_register_string_preference(dvbci_module,
6125             "sek", "SAC Encryption Key", "SAC Encryption Key (16 hex bytes)",
6126             &dvbci_sek);
6127     prefs_register_string_preference(dvbci_module,
6128             "siv", "SAC Init Vector", "SAC Init Vector (16 hex bytes)",
6129             &dvbci_siv);
6130     prefs_register_bool_preference(dvbci_module,
6131             "dissect_lsc_msg",
6132             "Dissect LSC messages",
6133             "Dissect the content of messages transmitted "
6134                 "on the Low-Speed Communication resource. "
6135                 "This requires a dissector for the protocol and target port "
6136                 "contained in the connection descriptor.",
6137             &dvbci_dissect_lsc_msg);
6138
6139     sas_msg_dissector_table = register_dissector_table("dvb-ci.sas.app_id_str",
6140                 "SAS application id", FT_STRING, STR_ASCII);
6141
6142     register_init_routine(dvbci_init);
6143
6144     /* the dissector for decrypted CI+ SAC messages which we can export */
6145     new_register_dissector(EXPORTED_SAC_MSG_PROTO,
6146         dissect_dvbci_exported_sac_msg, proto_dvbci);
6147 }
6148
6149
6150 void
6151 proto_reg_handoff_dvbci(void)
6152 {
6153     dissector_handle_t dvbci_handle;
6154
6155     dvbci_handle = new_create_dissector_handle(dissect_dvbci, proto_dvbci);
6156     dissector_add_uint("wtap_encap", WTAP_ENCAP_DVBCI, dvbci_handle);
6157
6158     data_handle = find_dissector("data");
6159     mpeg_pmt_handle = find_dissector("mpeg_pmt");
6160     dvb_nit_handle = find_dissector("dvb_nit");
6161     png_handle = find_dissector("png");
6162     tcp_dissector_table = find_dissector_table("tcp.port");
6163     udp_dissector_table = find_dissector_table("udp.port");
6164
6165     exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_DVB_CI);
6166
6167     if (dvbci_sek_bin) {
6168         g_free(dvbci_sek_bin);
6169         dvbci_sek_bin = NULL;
6170     }
6171     if (dvbci_siv_bin) {
6172         g_free(dvbci_siv_bin);
6173         dvbci_siv_bin = NULL;
6174     }
6175     pref_key_string_to_bin(dvbci_sek, &dvbci_sek_bin);
6176     pref_key_string_to_bin(dvbci_siv, &dvbci_siv_bin);
6177 }
6178
6179 /*
6180  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
6181  *
6182  * Local variables:
6183  * c-basic-offset: 4
6184  * tab-width: 8
6185  * indent-tabs-mode: nil
6186  * End:
6187  *
6188  * vi: set shiftwidth=4 tabstop=8 expandtab:
6189  * :indentSize=4:tabSize=8:noTabs=true:
6190  */