3 * Routines for NetWare Core Protocol. This C code gets #include'd
4 * into packet-ncp2222.c, which is generated from ncp2222.py. It's
5 * #include'd instead of being in a separate compilation unit so
6 * that all the data tables in packet-ncp2222.c can remain static.
8 * Gilbert Ramirez <gram@xiexie.org>
10 * $Id: packet-ncp2222.inc,v 1.2 2000/10/21 05:52:21 guy Exp $
12 * Ethereal - Network traffic analyzer
13 * By Gerald Combs <gerald@zing.org>
14 * Copyright 2000 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 /* Does NCP func require a subfunction code? */
33 ncp_requires_subfunc(guint8 func)
35 const guint8 *ncp_func_requirement = ncp_func_requires_subfunc;
37 while (*ncp_func_requirement != 0) {
38 if (*ncp_func_requirement == func) {
41 ncp_func_requirement++;
46 /* Return a ncp_record* based on func and possibly subfunc */
47 static const ncp_record *
48 ncp_record_find(guint8 func, guint8 subfunc)
50 const ncp_record *ncp_rec = ncp_packets;
52 while(ncp_rec->func != 0 || ncp_rec->subfunc != 0 ||
53 ncp_rec->name != NULL ) {
54 if (ncp_rec->func == func &&
55 ncp_rec->subfunc == (subfunc & ncp_rec->submask)) {
63 /* Run through the table of ptv_record's and add info to the tree */
65 process_ptvc_record(ptvcursor_t *ptvc, const ptvc_record *rec)
67 while(rec->hf_ptr != NULL) {
68 ptvcursor_add(ptvc, *rec->hf_ptr, rec->length,
75 /* Given an error_equivalency table and a completion code, return
76 * the string representing the error. */
78 ncp_error_string(const error_equivalency *errors, guint8 completion_code)
80 while (errors->ncp_error_index != -1) {
81 if (errors->error_in_packet == completion_code) {
82 return ncp_errors[errors->ncp_error_index];
91 dissect_ncp_request(tvbuff_t *tvb, packet_info *pinfo,
92 guint16 nw_connection, guint8 sequence,
93 guint16 type, proto_tree *ncp_tree, proto_tree *tree)
95 guint8 func, subfunc = 0;
96 gboolean requires_subfunc;
97 const ncp_record *ncp_rec;
98 conversation_t *conversation;
99 ptvcursor_t *ptvc = NULL;
101 func = tvb_get_guint8(tvb, 6);
103 requires_subfunc = ncp_requires_subfunc(func);
104 if (requires_subfunc) {
105 subfunc = tvb_get_guint8(tvb, 9);
108 ncp_rec = ncp_record_find(func, subfunc);
110 if (check_col(pinfo->fd, COL_INFO)) {
112 col_add_fstr(pinfo->fd, COL_INFO, "C %s", ncp_rec->name);
115 if (requires_subfunc) {
116 col_add_fstr(pinfo->fd, COL_INFO,
117 "C Unknown Function 0x%02X/0x%02x",
121 col_add_fstr(pinfo->fd, COL_INFO,
122 "C Unknown Function 0x%02x",
128 if (!pinfo->fd->flags.visited) {
129 /* This is the first time we've looked at this packet.
130 Keep track of the address and connection whence the request
131 came, and the address and connection to which the request
132 is being sent, so that we can match up calls with replies.
133 (We don't include the sequence number, as we may want
134 to have all packets over the same connection treated
135 as being part of a single conversation so that we can
136 let the user select that conversation to be displayed.) */
137 conversation = find_conversation(&pi.src, &pi.dst,
138 PT_NCP, nw_connection, nw_connection, 0);
139 if (conversation == NULL) {
140 /* It's not part of any conversation - create a new one. */
141 conversation = conversation_new(&pi.src, &pi.dst,
142 PT_NCP, nw_connection, nw_connection, NULL, 0);
144 ncp_hash_insert(conversation, sequence, 0x2222, ncp_rec);
148 proto_tree_add_uint_format(ncp_tree, hf_ncp_func, tvb, 6, 1,
149 func, "Function Code: 0x%02X (%s)",
150 func, ncp_rec ? ncp_rec->name : "Unknown");
152 if (requires_subfunc) {
153 proto_tree_add_item(ncp_tree, hf_ncp_length, tvb, 7,
155 proto_tree_add_item(ncp_tree, hf_ncp_subfunc, tvb, 9,
157 ptvc = ptvcursor_new(ncp_tree, tvb, 10);
160 ptvc = ptvcursor_new(ncp_tree, tvb, 7);
163 /* The group is not part of the packet, but it's useful
164 * information to display anyway. */
166 proto_tree_add_text(ncp_tree, tvb, 6, 1, "Group: %s",
167 ncp_groups[ncp_rec->group]);
170 if (ncp_rec && ncp_rec->request_ptvc) {
171 process_ptvc_record(ptvc, ncp_rec->request_ptvc);
173 ptvcursor_free(ptvc);
179 dissect_ncp_reply(tvbuff_t *tvb, packet_info *pinfo,
180 guint16 nw_connection, guint8 sequence,
181 proto_tree *ncp_tree, proto_tree *tree) {
183 conversation_t *conversation;
184 const ncp_record *ncp_rec = NULL;
186 gboolean found_request = FALSE;
187 guint8 completion_code;
189 ptvcursor_t *ptvc = NULL;
190 const char *error_string;
192 /* Find the conversation whence the request would have come. */
193 conversation = find_conversation(&pi.src, &pi.dst,
194 PT_NCP, nw_connection, nw_connection, 0);
195 if (conversation != NULL) {
196 /* find the record telling us the request made that caused
198 found_request = ncp_hash_lookup(conversation, sequence,
199 &ncp_type, &ncp_rec);
201 /* else... we haven't seen an NCP Request for that conversation and sequence. */
203 /* A completion code of 0 always means OK. Non-zero means failure,
204 * but each non-zero value has a different meaning. And the same value
205 * can have different meanings, depending on the ncp.func (and ncp.subfunc)
207 completion_code = tvb_get_guint8(tvb, 6);
208 if (ncp_rec && ncp_rec->errors) {
209 error_string = ncp_error_string(ncp_rec->errors, completion_code);
211 else if (completion_code == 0) {
215 error_string = "Not OK";
218 if (check_col(pinfo->fd, COL_INFO)) {
219 col_add_fstr(pinfo->fd, COL_INFO, "R %s", error_string);
224 /* Put the func (and maybe subfunc) from the request packet
225 * in the proto tree, but hidden. That way filters on ncp.func
226 * or ncp.subfunc will find both the requests and the replies.
229 proto_tree_add_uint(ncp_tree, hf_ncp_func, tvb,
230 6, 0, ncp_rec->func);
231 if (ncp_requires_subfunc(ncp_rec->func)) {
232 proto_tree_add_uint(ncp_tree, hf_ncp_subfunc,
233 tvb, 6, 0, ncp_rec->subfunc);
237 proto_tree_add_uint_format(ncp_tree, hf_ncp_completion_code, tvb, 6, 1,
238 completion_code, "Completion Code: 0x%02x (%s)",
239 completion_code, error_string);
241 proto_tree_add_item(ncp_tree, hf_ncp_connection_status, tvb, 7, 1, FALSE);
243 length = tvb_length(tvb);
244 if (!ncp_rec && length > 8) {
245 proto_tree_add_text(ncp_tree, tvb, 8, length - 8,
246 "No request record found. Parsing is impossible.");
248 else if (ncp_rec && ncp_rec->reply_ptvc) {
249 /* If a non-zero completion code was found, it is
250 * legal to not have any fields, even if the packet
251 * type is defined as having fields. */
252 if (completion_code != 0 && tvb_length(tvb) == 8) {
256 ptvc = ptvcursor_new(ncp_tree, tvb, 8);
257 process_ptvc_record(ptvc, ncp_rec->reply_ptvc);
258 ptvcursor_free(ptvc);