aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-oipf.c
blob: 4723aaeeaebac8cb6481b83cef2769cea492ba56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/* packet-oipf.c
 * Dissector for Open IPTV Forum protocols
 * Copyright 2012, Martin Kaiser <martin@kaiser.cx>
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

/* This dissector supports the CI+ Content and Service Protection Gateway
   (CSPG-CI+) as defined in in Open IPTV Forum Specification Volume 7 V2.1
   http://www.openiptvforum.org/release_2.html */

#include "config.h"

#include <epan/packet.h>

void proto_register_oipf(void);
void proto_reg_handoff_oipf(void);

static dissector_handle_t oipf_ciplus_handle;

static int proto_oipf_ciplus;

static gint ett_oipf_ciplus;

static int hf_oipf_ciplus_cmd_id;
static int hf_oipf_ciplus_ca_sys_id;
static int hf_oipf_ciplus_trx_id;
static int hf_oipf_ciplus_send_datatype_nbr;
static int hf_oipf_ciplus_dat_id;
static int hf_oipf_ciplus_dat_len;
static int hf_oipf_ciplus_data;

/* the application id for this protocol in the CI+ SAS resource
   this is actually a 64bit hex number, we can't use a 64bit number as a key
   for the dissector table directly, we have to process it as a string
   (the string must not be a local variable as glib stores a pointer to
   it in the hash table) */
static const gchar sas_app_id_str_oipf[] = "0x0108113101190000";

static const value_string oipf_ciplus_cmd_id[] = {
    { 0x01, "send_msg" },
    { 0x02, "reply_msg" },
    { 0x03, "parental_control_info" },
    { 0x04, "rights_info" },
    { 0x05, "system_info" },
    { 0, NULL }
};

static const value_string oipf_ciplus_dat_id[] = {
    { 0x01, "oipf_ca_vendor_specific_information" },
    { 0x02, "oipf_country_code" },
    { 0x03, "oipf_parental_control_url" },
    { 0x04, "oipf_rating_type" },
    { 0x05, "oipf_rating_value" },
    { 0x06, "oipf_rights_issuer_url" },
    { 0x07, "oipf_access_status" },
    { 0x08, "oipf_status" },
    { 0, NULL }
};


static int
dissect_oipf_ciplus(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
    gint        msg_len;
    proto_tree *oipf_ciplus_tree;
    guint       offset           = 0;
    guint8      i, send_datatype_nbr;
    guint16     dat_len;

    /* an OIPF CI+ message minimally contains command_id (1 byte),
       ca sys id (2 bytes), transaction id (4 bytes) and
       number of sent datatypes (1 byte) */
    msg_len = tvb_reported_length(tvb);
    if (msg_len < 8)
        return 0;

    oipf_ciplus_tree = proto_tree_add_subtree(tree, tvb, 0, msg_len, ett_oipf_ciplus, NULL, "Open IPTV Forum CSPG-CI+");

    proto_tree_add_item(oipf_ciplus_tree, hf_oipf_ciplus_cmd_id,
            tvb, offset, 1, ENC_BIG_ENDIAN);
    offset++;
    proto_tree_add_item(oipf_ciplus_tree, hf_oipf_ciplus_ca_sys_id,
            tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;
    proto_tree_add_item(oipf_ciplus_tree, hf_oipf_ciplus_trx_id,
            tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;

    send_datatype_nbr = tvb_get_guint8(tvb, offset);
    proto_tree_add_item(oipf_ciplus_tree, hf_oipf_ciplus_send_datatype_nbr,
            tvb, offset, 1, ENC_BIG_ENDIAN);
    offset++;

    for (i=0; i<send_datatype_nbr; i++) {
        proto_tree_add_item(oipf_ciplus_tree, hf_oipf_ciplus_dat_id,
                tvb, offset, 1, ENC_BIG_ENDIAN);
        offset++;

        dat_len = tvb_get_ntohs(tvb, offset);
        proto_tree_add_item(oipf_ciplus_tree, hf_oipf_ciplus_dat_len,
                tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        proto_tree_add_item(oipf_ciplus_tree, hf_oipf_ciplus_data,
                tvb, offset, dat_len, ENC_NA);
        offset += dat_len;
    }

    return offset;
}

void
proto_register_oipf(void)
{
    static gint *ett[] = {
        &ett_oipf_ciplus
    };

    static hf_register_info hf[] = {
        { &hf_oipf_ciplus_cmd_id,
            { "Command ID", "oipf.ciplus.cmd_id", FT_UINT8, BASE_HEX,
               VALS(oipf_ciplus_cmd_id), 0, NULL, HFILL } },
        { &hf_oipf_ciplus_ca_sys_id,
            { "CA system ID", "oipf.ciplus.ca_system_id", FT_UINT16, BASE_HEX,
                NULL, 0, NULL, HFILL } },
        { &hf_oipf_ciplus_trx_id,
            { "Transaction ID", "oipf.ciplus.transaction_id",
                FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
        { &hf_oipf_ciplus_send_datatype_nbr,
            { "Number of data items", "oipf.ciplus.num_items", FT_UINT8,
                BASE_DEC, NULL, 0, NULL, HFILL } },
        { &hf_oipf_ciplus_dat_id,
            { "Datatype ID", "oipf.ciplus.datatype_id", FT_UINT8, BASE_HEX,
                VALS(oipf_ciplus_dat_id), 0, NULL, HFILL } },
        { &hf_oipf_ciplus_dat_len,
            { "Datatype length", "oipf.ciplus.datatype_len", FT_UINT16,
                BASE_DEC, NULL, 0, NULL, HFILL } },
        { &hf_oipf_ciplus_data,
            { "Data", "oipf.ciplus.data", FT_BYTES, BASE_NONE,
                NULL, 0, NULL, HFILL } }
    };

    proto_oipf_ciplus = proto_register_protocol("Open IPTV Forum CSPG-CI+", "OIPF CI+", "oipf.ciplus");
    proto_register_field_array(proto_oipf_ciplus, hf, array_length(hf));
    proto_register_subtree_array(ett, array_length(ett));

    oipf_ciplus_handle = register_dissector("oipf.ciplus", dissect_oipf_ciplus, proto_oipf_ciplus);
}

void
proto_reg_handoff_oipf(void)
{
    dissector_add_string("dvb-ci.sas.app_id_str",
            sas_app_id_str_oipf, oipf_ciplus_handle);
}

/*
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
 *
 * Local variables:
 * c-basic-offset: 4
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 *
 * vi: set shiftwidth=4 tabstop=8 expandtab:
 * :indentSize=4:tabSize=8:noTabs=true:
 */