2 * Routines for the COPS (Common Open Policy Service) protocol dissection
5 * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
7 * $Id: packet-cops.c,v 1.4 2000/08/13 14:08:07 deniel Exp $
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@zing.org>
11 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40 #define TCP_PORT_COPS 3288
42 #define COPS_OBJECT_HDR_SIZE 4
44 static const value_string cops_flags_vals[] = {
46 { 0x01, "Solicited Message Flag Bit" },
50 /* The different COPS message types */
52 COPS_NO_MSG, /* Not a COPS Message type */
54 COPS_MSG_REQ, /* Request (REQ) */
55 COPS_MSG_DEC, /* Decision (DEC) */
56 COPS_MSG_RPT, /* Report State (RPT) */
57 COPS_MSG_DRQ, /* Delete Request State (DRQ) */
58 COPS_MSG_SSQ, /* Synchronize State Req (SSQ) */
59 COPS_MSG_OPN, /* Client-Open (OPN) */
60 COPS_MSG_CAT, /* Client-Accept (CAT) */
61 COPS_MSG_CC, /* Client-Close (CC) */
62 COPS_MSG_KA, /* Keep-Alive (KA) */
63 COPS_MSG_SSC, /* Synchronize Complete (SSC) */
65 COPS_LAST_OP_CODE /* For error checking */
68 static const value_string cops_op_code_vals[] = {
69 { COPS_MSG_REQ, "Request (REQ)" },
70 { COPS_MSG_DEC, "Decision (DEC)" },
71 { COPS_MSG_RPT, "Report State (RPT)" },
72 { COPS_MSG_DRQ, "Delete Request State (DRQ)" },
73 { COPS_MSG_SSQ, "Synchronize State Req (SSQ)" },
74 { COPS_MSG_OPN, "Client-Open (OPN)" },
75 { COPS_MSG_CAT, "Client-Accept (CAT)" },
76 { COPS_MSG_CC, "Client-Close (CC)" },
77 { COPS_MSG_KA, "Keep-Alive (KA)" },
78 { COPS_MSG_SSC, "Synchronize Complete (SSC)" },
83 /* The different objects in COPS messages */
85 COPS_NO_OBJECT, /* Not a COPS Object type */
87 COPS_OBJ_HANDLE, /* Handle Object (Handle) */
88 COPS_OBJ_CONTEXT, /* Context Object (Context) */
89 COPS_OBJ_IN_INT, /* In-Interface Object (IN-Int) */
90 COPS_OBJ_OUT_INT, /* Out-Interface Object (OUT-Int) */
91 COPS_OBJ_REASON, /* Reason Object (Reason) */
92 COPS_OBJ_DECISION, /* Decision Object (Decision) */
93 COPS_OBJ_LPDPDECISION, /* LPDP Decision Object (LPDPDecision) */
94 COPS_OBJ_ERROR, /* Error Object (Error) */
95 COPS_OBJ_CLIENTSI, /* Client Specific Information Object (ClientSI) */
96 COPS_OBJ_KATIMER, /* Keep-Alive Timer Object (KATimer) */
97 COPS_OBJ_PEPID, /* PEP Identification Object (PEPID) */
98 COPS_OBJ_REPORT_TYPE, /* Report-Type Object (Report-Type) */
99 COPS_OBJ_PDPREDIRADDR, /* PDP Redirect Address Object (PDPRedirAddr) */
100 COPS_OBJ_LASTPDPADDR, /* Last PDP Address (LastPDPaddr) */
101 COPS_OBJ_ACCTTIMER, /* Accounting Timer Object (AcctTimer) */
102 COPS_OBJ_INTEGRITY, /* Message Integrity Object (Integrity) */
104 COPS_LAST_C_NUM /* For error checking */
107 static const value_string cops_c_num_vals[] = {
108 { COPS_OBJ_HANDLE, " Handle Object (Handle)" },
109 { COPS_OBJ_CONTEXT, " Context Object (Context)" },
110 { COPS_OBJ_IN_INT, " In-Interface Object (IN-Int)" },
111 { COPS_OBJ_OUT_INT, " Out-Interface Object (OUT-Int)" },
112 { COPS_OBJ_REASON, " Reason Object (Reason)" },
113 { COPS_OBJ_DECISION, " Decision Object (Decision)" },
114 { COPS_OBJ_LPDPDECISION, " LPDP Decision Object (LPDPDecision)" },
115 { COPS_OBJ_ERROR, " Error Object (Error)" },
116 { COPS_OBJ_CLIENTSI, " Client Specific Information Object (ClientSI)" },
117 { COPS_OBJ_KATIMER, " Keep-Alive Timer Object (KATimer)" },
118 { COPS_OBJ_PEPID, " PEP Identification Object (PEPID)" },
119 { COPS_OBJ_REPORT_TYPE, " Report-Type Object (Report-Type)" },
120 { COPS_OBJ_PDPREDIRADDR, " PDP Redirect Address Object (PDPRedirAddr)" },
121 { COPS_OBJ_LASTPDPADDR, " Last PDP Address (LastPDPaddr)" },
122 { COPS_OBJ_ACCTTIMER, " Accounting Timer Object (AcctTimer)" },
123 { COPS_OBJ_INTEGRITY, " Message Integrity Object (Integrity)" },
128 /* Initialize the protocol and registered fields */
129 static gint proto_cops = -1;
130 static gint hf_cops_ver_flags = -1;
131 static gint hf_cops_version = -1;
132 static gint hf_cops_flags = -1;
134 static gint hf_cops_op_code = -1;
135 static gint hf_cops_client_type = -1;
136 static gint hf_cops_msg_len = -1;
138 static gint hf_cops_obj_len = -1;
139 static gint hf_cops_obj_c_num = -1;
140 static gint hf_cops_obj_c_type = -1;
142 /* Initialize the subtree pointers */
143 static gint ett_cops = -1;
144 static gint ett_cops_ver_flags = -1;
145 static gint ett_cops_obj = -1;
147 static int dissect_cops_object(tvbuff_t *tvb, guint32 offset, proto_tree *tree);
149 /* Code to actually dissect the packets */
150 static void dissect_cops(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
154 CHECK_DISPLAY_AS_DATA(proto_cops, tvb, pinfo, tree);
156 pinfo->current_proto = "COPS";
157 if (check_col(pinfo->fd, COL_PROTOCOL))
158 col_add_str(pinfo->fd, COL_PROTOCOL, "COPS");
160 op_code = tvb_get_guint8(tvb, 1);
161 if (check_col(pinfo->fd, COL_INFO))
162 col_add_fstr(pinfo->fd, COL_INFO, "COPS %s",
163 val_to_str(op_code, cops_op_code_vals, "Unknown Op Code"));
167 proto_tree *cops_tree, *ver_flags_tree;
168 guint32 offset, msg_len, carbage;
173 ti = proto_tree_add_item(tree, proto_cops, tvb, offset, tvb_length(tvb), FALSE);
174 cops_tree = proto_item_add_subtree(ti, ett_cops);
176 /* Version and flags share the same byte, put them in a subtree */
177 ver_flags = tvb_get_guint8(tvb, offset);
178 tv = proto_tree_add_uint_format(cops_tree, hf_cops_ver_flags, tvb, offset, 1,
179 ver_flags, "Version: %u, Flags: %s",
180 hi_nibble(ver_flags),
181 val_to_str(lo_nibble(ver_flags), cops_flags_vals, "Unknown"));
182 ver_flags_tree = proto_item_add_subtree(tv, ett_cops_ver_flags);
183 proto_tree_add_uint(ver_flags_tree, hf_cops_version, tvb, offset, 1, ver_flags);
184 proto_tree_add_uint(ver_flags_tree, hf_cops_flags, tvb, offset, 1, ver_flags);
187 proto_tree_add_uint(cops_tree, hf_cops_op_code, tvb, offset, 1, tvb_get_guint8(tvb, offset));
189 proto_tree_add_uint(cops_tree, hf_cops_client_type, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
192 msg_len = tvb_get_ntohl(tvb, offset);
193 proto_tree_add_uint(cops_tree, hf_cops_msg_len, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
196 while (msg_len >= COPS_OBJECT_HDR_SIZE) {
199 consumed = dissect_cops_object(tvb, offset, cops_tree);
206 carbage = tvb_length_remaining(tvb, offset);
208 proto_tree_add_text(cops_tree, tvb, offset, carbage,
209 "Trailing carbage: %u byte%s", carbage,
210 plurality(carbage, "", "s"));
216 static int dissect_cops_object(tvbuff_t *tvb, guint32 offset, proto_tree *tree)
218 guint16 object_len, contents_len;
219 guint8 c_num, c_type;
221 proto_tree *obj_tree;
223 if (tvb_length_remaining(tvb, offset) < COPS_OBJECT_HDR_SIZE)
226 object_len = tvb_get_ntohs(tvb, offset);
227 c_num = tvb_get_guint8(tvb, offset + 2);
228 c_type = tvb_get_guint8(tvb, offset + 3);
230 ti = proto_tree_add_uint_format(tree, hf_cops_obj_c_num, tvb, offset, object_len, c_num,
231 "Object Type: %s", val_to_str(c_num, cops_c_num_vals, "Unknown"));
232 obj_tree = proto_item_add_subtree(ti, ett_cops_obj);
234 proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
237 proto_tree_add_uint(obj_tree, hf_cops_obj_c_num, tvb, offset, 1, tvb_get_guint8(tvb, offset));
240 proto_tree_add_uint(obj_tree, hf_cops_obj_c_type, tvb, offset, 1, tvb_get_guint8(tvb, offset));
243 contents_len = object_len - COPS_OBJECT_HDR_SIZE;
244 proto_tree_add_text(obj_tree, tvb, offset, contents_len,
245 "Object contents: %u bytes", contents_len);
247 /* Pad to 32bit boundary */
248 if (object_len % sizeof (guint32))
249 object_len += (sizeof (guint32) - object_len % sizeof (guint32));
255 /* Register the protocol with Ethereal */
256 void proto_register_cops(void)
259 /* Setup list of header fields */
260 static hf_register_info hf[] = {
261 { &hf_cops_ver_flags,
262 { "Version and Flags", "cops.ver_flags",
263 FT_UINT8, BASE_HEX, NULL, 0x0,
264 "Version and Flags in COPS Common Header" }
267 { "Version", "cops.version",
268 FT_UINT8, BASE_DEC, NULL, 0xF0,
269 "Version in COPS Common Header" }
272 { "Flags", "cops.flags",
273 FT_UINT8, BASE_HEX, VALS(cops_flags_vals), 0x0F,
274 "Flags in COPS Common Header" }
277 { "Op Code", "cops.op_code",
278 FT_UINT8, BASE_DEC, VALS(cops_op_code_vals), 0x0,
279 "Op Code in COPS Common Header" }
281 { &hf_cops_client_type,
282 { "Client Type", "cops.client_type",
283 FT_UINT16, BASE_DEC, NULL, 0x0,
284 "Client Type in COPS Common Header" }
287 { "Message Length", "cops.msg_len",
288 FT_UINT32, BASE_DEC, NULL, 0x0,
289 "Message Length in COPS Common Header" }
292 { "Object Length", "cops.obj.len",
293 FT_UINT32, BASE_DEC, NULL, 0x0,
294 "Object Length in COPS Object Header" }
296 { &hf_cops_obj_c_num,
297 { "C-Num", "cops.obj.c_num",
298 FT_UINT8, BASE_DEC, VALS(cops_c_num_vals), 0x0,
299 "C-Num in COPS Object Header" }
301 { &hf_cops_obj_c_type,
302 { "C-Type", "cops.obj.c_type",
303 FT_UINT8, BASE_DEC, NULL, 0x0,
304 "C-Type in COPS Object Header" }
308 /* Setup protocol subtree array */
309 static gint *ett[] = {
315 /* Register the protocol name and description */
316 proto_cops = proto_register_protocol("Common Open Policy Service", "cops");
318 /* Required function calls to register the header fields and subtrees used */
319 proto_register_field_array(proto_cops, hf, array_length(hf));
320 proto_register_subtree_array(ett, array_length(ett));
324 proto_reg_handoff_cops(void)
326 dissector_add("tcp.port", TCP_PORT_COPS, dissect_cops);