HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-knet.c
blob4098220888c17a4a726d542eec019baab088fcdc
1 /* packet-knet.c
2 * Routines for the KristalliNet (kNet) protocol.
3 * Kari Vatjus-Anttila <kari.vatjus-anttila@cie.fi>
4 * Ville Saarinen <ville.saarinen@cie.fi>
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 #include <epan/packet.h>
30 #include <epan/prefs.h>
31 #include <epan/wmem/wmem.h>
32 #include <epan/dissectors/packet-tcp.h>
34 #define PROTO_TAG_KNET "KNET" /*!< Definition of kNet Protocol */
35 #define PORT 2345
37 #define KNET_SCTP_PACKET 1000
38 #define KNET_TCP_PACKET 1001
39 #define KNET_UDP_PACKET 1002
41 /**
42 * @addtogroup messageids kNet Message ID:s
43 * Message ID:s of the kNet protocol
45 /**@{*/
46 #define PINGREQUEST 1 /*!< Message ID definition: Ping Request */
47 #define PINGREPLY 2 /*!< Message ID definition: Ping Reply */
48 #define FLOWCONTROLREQUEST 3 /*!< Message ID definition: Flow Control Request */
49 #define PACKETACK 4 /*!< Message ID definition: Packet Acknowledge */
50 #define DISCONNECT 255 /*!< Message ID definition: Disconnect */
51 #define DISCONNECTACK 254 /*!< Message ID definition: Disconnect Ack */
52 #define CONNECTSYN 253 /*!< Message ID definition: Connect Syn */
53 #define CONNECTSYNACK 252 /*!< Message ID definition: Connect Syn Acknowledge */
54 #define CONNECTACK 251 /*!< Message ID definition: Connect Acknowledge */
55 /**@}*/
57 #define UDP_DATAGRAM_RELIABLE_FLAG 0x40
58 #define UDP_MSG_BLOCK_RELIABLE_FLAG 0x10
60 void proto_reg_handoff_knet(void); /* Forward declaration for use in preferences registration */
62 /**
63 * @addtogroup protocols Protocol Variables
64 * Protocol variables.
66 /**@{*/
67 static int proto_knet = -1;
68 /**@}*/
70 /**
71 * @addtogroup headerfields Dissector Header Fields
72 * Header fields of the kNet datagram
74 /* *@{*/
76 /* Fields used by the TCP/SCTP dissector */
77 static int hf_knet_message_tree = -1; /*!< Message tree */
78 static int hf_knet_content_length_vle = -1; /*!< Content Length */
80 /* Fields used by the UDP dissector */
81 static int hf_knet_content_length = -1; /*!< Content Length */
82 static int hf_knet_datagram_tree = -1; /*!< Datagram subtree */
83 static int hf_knet_flags = -1; /*!< UDP Flags subtree */
84 static int hf_knet_inorder = -1; /*!< Inorder Flag */
85 static int hf_knet_reliable = -1; /*!< Reliable Flag */
86 static int hf_knet_packetid = -1; /*!< PacketID */
87 static int hf_knet_rmib = -1; /*!< Reliable Message Index Base */
88 static int hf_knet_msg_flags = -1; /*!< Message Block Flags subtree */
89 static int hf_knet_msg_fs = -1; /*!< Fragment Start */
90 static int hf_knet_msg_ff = -1; /*!< Fragment Flag */
91 static int hf_knet_msg_inorder = -1; /*!< Inorder Flag */
92 static int hf_knet_msg_reliable = -1; /*!< Reliable Flag */
93 static int hf_knet_msg_reliable_message_number = -1; /*!< Reliable Message Number */
95 static int hf_knet_payload_tree = -1; /*!< Payload subtree */
96 static int hf_knet_payload = -1; /*!< Payload subtree */
97 static int hf_knet_messageid = -1; /*!< MessageID of the packet */
98 static int hf_knet_pingid = -1;
99 static int hf_knet_flowctrlreq = -1;
100 static int hf_knet_packetack = -1;
101 static int hf_knet_seqnumber = -1;
102 /**@}*/
105 * @addtogroup trees Subtrees used by the dissectors
107 /* *@{*/
109 /*Knet Subtrees */
110 static gint ett_knet_main = -1; /*!< Main kNet tree */
111 static gint ett_knet_message = -1; /*!< Message tree */
112 static gint ett_knet_payload = -1; /*!< Payload tree */
113 static gint ett_knet_message_flags = -1; /*!< Message flags tree */
114 static gint ett_knet_datagram = -1;
115 static gint ett_knet_flags = -1;
116 /**@}*/
118 static dissector_handle_t knet_handle_sctp;
119 static dissector_handle_t knet_handle_tcp;
120 static dissector_handle_t knet_handle_udp;
122 /* Ports used by the dissectors */
123 static guint32 knet_sctp_port = PORT; /*!< Port used by kNet SCTP */
124 static guint32 knet_tcp_port = PORT; /*!< Port used by kNet TCP */
125 static guint32 knet_udp_port = PORT; /*!< Port used by kNet UDP */
127 static const value_string packettypenames[] = { /*!< Messageid List */
128 { PINGREQUEST, "Ping Request" },
129 { PINGREPLY, "Ping Reply" },
130 { FLOWCONTROLREQUEST, "Flowcontrol Request" },
131 { PACKETACK, "Packet Ack" },
132 { DISCONNECT, "Disconnect" },
133 { DISCONNECTACK, "Disconnect Ack" },
134 { CONNECTSYN, "Connect Syn" },
135 { CONNECTSYNACK, "Connect Syn Ack" },
136 { CONNECTACK, "Connect Ack" },
137 { 0, NULL }
141 * counts length of the variable length encoded field
143 * @param tvb the buffer to the data
144 * @param offset the offset of data in the buffer
145 * @return int returns number of bytes used
148 static int
149 count_vle_bytes(tvbuff_t *tvb, int offset)
151 int byte_count = 1;
153 if(tvb_get_guint8(tvb, offset) & 0x80) /* If the first bit of the first byte is 1 */
154 byte_count = 2; /* There's at least 2 bytes of content length */
155 if(tvb_get_guint8(tvb, offset+1) & 0x80) /* If the next one is also 1 */
156 byte_count = 4;
158 return byte_count;
162 * dissect_packetid is a utility function which calculates
163 * the packets Packet ID from the data. Packet ID is a field
164 * located in the datagram header.
166 * @see dissect_reliable_message_index_base()
167 * @see dissect_reliable_message_number()
168 * @see dissect_content_length()
169 * @see dissect_messageid()
170 * @see dissect_payload()
171 * @param buffer the buffer to the data
172 * @param offset the offset where to start reading the data
173 * @param tree the parent tree where the dissected data is going to be inserted
174 * @return int returns the new offset
177 static guint32
178 dissect_packetid(tvbuff_t *buffer, int offset, proto_tree *tree)
180 guint32 packetid;
182 packetid = tvb_get_guint8(buffer, offset+2) << 14;
183 packetid += tvb_get_guint8(buffer, offset+1) << 6;
184 packetid += tvb_get_guint8(buffer, offset) & 63;
186 proto_tree_add_uint(tree, hf_knet_packetid, buffer, 0, 3, packetid);
187 return packetid;
191 * dissect_reliable_message_index_base is a utility function
192 * which calculates the packets RMIB if and only if the reliable
193 * flag is set to 1.
195 * @see dissect_packetid()
196 * @see dissect_content_length()
197 * @see dissect_reliable_message_number()
198 * @see dissect_messageid()
199 * @see dissect_payload()
200 * @param buffer the buffer to the data
201 * @param offset the offset where to start reading the data
202 * @param tree the parent tree where the dissected data is going to be inserted
203 * @return int returns the new offset
206 static int
207 dissect_reliable_message_index_base(tvbuff_t *buffer, int offset, proto_tree *tree)
209 int byte_count = 2;
211 if(tvb_get_guint8(buffer, offset+1) & 0x80)
212 byte_count = 4;
214 proto_tree_add_item(tree, hf_knet_rmib, buffer, offset, byte_count, ENC_LITTLE_ENDIAN);
216 return byte_count;
220 * dissect_content_length_vle is a utility function which
221 * calculates how long is the payload section of the message
222 * in bytes which is VLE encoded.
224 * @see dissect_packetid()
225 * @see dissect_reliable_message_index_base()
226 * @see dissect_reliable_message_number()
227 * @see dissect_messageid()
228 * @see dissect_payload()
229 * @param buffer the buffer to the data
230 * @param offset the offset where to start reading the data
231 * @param tree the parent tree where the dissected data is going to be inserted
232 * @return int returns the content length of the packet
235 static int
236 dissect_content_length_vle(tvbuff_t *buffer, int *offset, proto_tree *tree)
238 int byte_count;
239 guint32 length;
241 length = 0;
242 byte_count = count_vle_bytes(buffer, *offset);
244 switch(byte_count) /*We must calculate length by hand because we use the length later */
246 case 4:
247 length = tvb_get_guint8(buffer, (*offset) + 3) << 23;
248 length += (tvb_get_guint8(buffer, (*offset) + 2) << 15);
249 /* FALLTHRU */
250 case 2:
251 length += (tvb_get_guint8(buffer, (*offset) + 1) << 7);
252 /* FALLTHRU */
253 case 1:
254 length += (tvb_get_guint8(buffer, (*offset)) & 0x7F);
255 break;
256 default:
257 REPORT_DISSECTOR_BUG("Error in Content Length calculation");
258 break;
261 proto_tree_add_uint(tree, hf_knet_content_length_vle, buffer, (*offset), byte_count, length);
262 (*offset) += byte_count;
264 return length;
268 * dissect_content_length is a utility function which
269 * calculates how long is the payload section of the message
270 * in bytes. Used only by the UDP dissector.
272 * @see dissect_packetid()
273 * @see dissect_reliable_message_index_base()
274 * @see dissect_reliable_message_number()
275 * @see dissect_messageid()
276 * @see dissect_payload()
277 * @param buffer the buffer to the data
278 * @param offset the offset where to start reading the data
279 * @param tree the parent tree where the dissected data is going to be inserted
280 * @return int returns the content length of the packet
283 static int
284 dissect_content_length(tvbuff_t *buffer, int offset, proto_tree *tree)
286 proto_item *msgflags_ti;
287 proto_tree *msgflags_tree;
288 guint32 length;
290 length = tvb_get_bits8(buffer, offset * 8 + 12, 4) << 8;
291 length += tvb_get_bits8(buffer, offset * 8, 8);
293 if(tree != NULL)
295 msgflags_ti = proto_tree_add_item(tree, hf_knet_msg_flags, buffer, offset + 1, 1, ENC_NA);
296 msgflags_tree = proto_item_add_subtree(msgflags_ti, ett_knet_message_flags);
298 proto_tree_add_item(msgflags_tree, hf_knet_msg_fs, buffer, offset+1, 1, ENC_NA); /* Fragment start flag */
299 proto_tree_add_item(msgflags_tree, hf_knet_msg_ff, buffer, offset+1, 1, ENC_NA); /* Fragment flag */
300 proto_tree_add_item(msgflags_tree, hf_knet_msg_inorder, buffer, offset+1, 1, ENC_NA); /* Inorder flag */
301 proto_tree_add_item(msgflags_tree, hf_knet_msg_reliable, buffer, offset+1, 1, ENC_NA); /* Reliable flag */
303 proto_tree_add_uint(tree, hf_knet_content_length, buffer, offset, 2, length);
306 return length;
310 * dissect_reliable_message_number is a utility function which
311 * calculates the RMN if and only if the reliable flag in the
312 * message block is set to 1.
314 * @see dissect_packetid()
315 * @see dissect_reliable_message_index_base()
316 * @see dissect_content_length()
317 * @see dissect_messageid()
318 * @see dissect_payload()
319 * @param buffer the buffer to the data
320 * @param offset the offset where to start reading the data
321 * @param tree the parent tree where the dissected data is going to be inserted
322 * @return int returns the new offset
325 static int
326 dissect_reliable_message_number(tvbuff_t *buffer, int offset, proto_tree *tree)
328 int byte_count = 1;
330 if(tvb_get_guint8(buffer, offset) & 0x80)
331 byte_count = 2;
333 proto_tree_add_item(tree, hf_knet_msg_reliable_message_number, buffer, offset, byte_count, ENC_LITTLE_ENDIAN);
335 return byte_count;
339 * dissect_messageid is a utility function which
340 * calculates the ID of the message.
342 * @see dissect_packetid()
343 * @see dissect_reliable_message_index_base()
344 * @see dissect_content_length()
345 * @see dissect_reliable_message_number()
346 * @see dissect_payload()
347 * @param buffer the buffer to the data
348 * @param offset the offset where to start reading the data
349 * @param tree the parent tree where the dissected data is going to be inserted
350 * @return int returns the messageid
353 static int
354 dissect_messageid(tvbuff_t *buffer, int *offset, proto_tree *tree, packet_info *pinfo, gboolean separator)
356 gint messageid_length;
357 guint8 messageid;
358 gboolean col_write;
360 messageid = tvb_get_guint8(buffer, (*offset));
362 switch(messageid)
364 case DISCONNECT:
365 case DISCONNECTACK:
366 case CONNECTSYN:
367 case CONNECTSYNACK:
368 case CONNECTACK:
369 messageid_length = 4;
370 break;
371 default:
372 messageid_length = 1;
373 break;
376 proto_tree_add_uint_format_value(tree, hf_knet_messageid, buffer, *offset, messageid_length, messageid,
377 "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData or Malformed Message ID"), messageid);
379 /* XXX - TCP reassembly disables writing columns which prevents populating COL_INFO if multiple KNET messages
380 appear in a single packet that needed to be reassembled.
381 Force making columns writable.
383 if (separator)
385 col_write = col_get_writable(pinfo->cinfo);
386 col_set_writable(pinfo->cinfo, TRUE);
387 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid);
388 col_set_writable(pinfo->cinfo, col_write);
390 else
392 col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%d)", val_to_str_const(messageid, packettypenames, "AppData"), messageid);
395 *offset += messageid_length;
397 return messageid;
401 * dissect_payload is a utility function which
402 * calculates the actual payload of the message.
404 * @see dissect_packetid()
405 * @see dissect_reliable_message_index_base()
406 * @see dissect_content_length()
407 * @see dissect_reliable_message_number()
408 * @see dissect_messageid()
409 * @param buffer the buffer to the data
410 * @param offset the offset where to start reading the data
411 * @param messageid the messageid of the received message
412 * @param tree the parent tree where the dissected data is going to be inserted
413 * @param content_length the content length of the payload
414 * @return int returns 0 at the moment
417 static int
418 dissect_payload(tvbuff_t *buffer, int offset, int messageid, proto_tree *tree, int content_length)
420 proto_item *payload_ti;
421 proto_tree *payload_tree;
423 payload_ti = proto_tree_add_item(tree, hf_knet_payload_tree, buffer, offset, content_length - 1, ENC_NA);
424 payload_tree = proto_item_add_subtree(payload_ti, ett_knet_payload);
426 switch(messageid)
428 case PINGREQUEST:
429 case PINGREPLY:
430 proto_tree_add_item(payload_tree, hf_knet_pingid, buffer, offset, 1, ENC_LITTLE_ENDIAN);
431 break;
432 case FLOWCONTROLREQUEST:
433 proto_tree_add_item(payload_tree, hf_knet_flowctrlreq, buffer, offset, 3, ENC_LITTLE_ENDIAN);
434 break;
435 case PACKETACK:
436 proto_tree_add_item(payload_tree, hf_knet_packetack, buffer, offset, 3, ENC_LITTLE_ENDIAN);
437 offset += 3;
438 proto_tree_add_item(payload_tree, hf_knet_seqnumber, buffer, offset, 4, ENC_LITTLE_ENDIAN);
439 break;
440 case DISCONNECT: /*No payload*/
441 case DISCONNECTACK: /*No payload*/
442 proto_tree_add_text(payload_tree, buffer, offset, 0, "No Payload");
443 break;
444 case CONNECTSYN: /*TODO: Not yet implemented, implement when available*/
445 case CONNECTSYNACK: /*TODO: Not yet implemented, implement when available*/
446 case CONNECTACK: /*TODO: Not yet implemented, implement when available*/
447 proto_tree_add_item(payload_tree, hf_knet_payload, buffer, offset, content_length-1, ENC_NA);
448 break;
449 default: /* Application Specific Message */
450 proto_tree_add_item(payload_tree, hf_knet_payload, buffer, offset, content_length-1, ENC_NA);
451 break;
454 return 0;
458 * dissect_knet_message is the subdissector which is called
459 * by dissect_knet when the dissector has dissected the
460 * datagram header. This subdissector dissects all of the
461 * messages which are encapsulated in the kNet datagram.
463 * @see dissect_knet()
464 * @param tvb the buffer to the data
465 * @param pinfo the packet info structure
466 * @param tree the parent tree where the dissected data is going to be inserted
469 static int
470 dissect_knet_message(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, int messageindex)
472 int content_length, total_length, messageid;
473 int start_offset = offset;
475 proto_item *msgblock_ti;
476 proto_tree *msgblock_tree;
478 msgblock_ti = proto_tree_add_item(tree, hf_knet_message_tree, tvb, offset, -1, ENC_NA);
479 msgblock_tree = proto_item_add_subtree(msgblock_ti, ett_knet_message);
481 content_length = dissect_content_length(tvb, offset, msgblock_tree); /* Calculates the Content Length of this packet. */
483 if(tvb_get_guint8(tvb, offset+1) & UDP_MSG_BLOCK_RELIABLE_FLAG) /* If the reliable flag is 1 then calculate RMN */
484 offset += dissect_reliable_message_number(tvb, offset+2, msgblock_tree);
486 offset += 2; /* Move the offset the amount of contentlength and flags fields */
488 total_length = (offset-start_offset)+content_length;
489 proto_item_set_len(msgblock_ti, total_length);
491 messageid = dissect_messageid(tvb, &offset, msgblock_tree, pinfo, messageindex != 0);
493 dissect_payload(tvb, offset, messageid, msgblock_tree, content_length);
495 return total_length;
499 * dissect_knet is the dissector which is called
500 * by Wireshark when kNet packets are captured. Here
501 * is dissected the SCTP and TCP packets in its own
502 * section and UDP packets in its own, because UDP
503 * packets differ quite a lot from SCTP and TCP.
504 * SCTP and TCP in the other hand has quite the same
505 * structure.
507 * @param tvb the buffer to the data
508 * @param pinfo the packet info structure
509 * @param tree the parent tree where the dissected data is going to be inserted
512 static void
513 dissect_knet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int current_protocol)
515 proto_item *knet_ti, *message_ti;
516 proto_tree *knet_tree, *message_tree;
518 int offset = 0, content_length, messageid;
520 /* Attach kNet main tree to Wireshark tree */
521 knet_ti = proto_tree_add_item(tree, proto_knet, tvb, 0, -1, ENC_NA);
522 knet_tree = proto_item_add_subtree(knet_ti, ett_knet_main);
524 /* Attach message tree to kNet tree */
525 message_ti = proto_tree_add_item(knet_tree, hf_knet_message_tree, tvb, offset, -1, ENC_NA);
526 message_tree = proto_item_add_subtree(message_ti, ett_knet_message);
528 content_length = dissect_content_length_vle(tvb, &offset, message_tree); /* Calculate length and add it to the tree-view */
529 proto_item_set_len(message_ti, (current_protocol == KNET_SCTP_PACKET ? content_length + 1 : content_length + 2));
531 messageid = dissect_messageid(tvb, &offset, message_tree, pinfo, TRUE); /* Calculate messageid and add it to the tree-view */
533 dissect_payload(tvb, offset, messageid, message_tree, content_length); /* Calculate payload and add it to the tree-view */
535 col_set_fence(pinfo->cinfo, COL_INFO);
539 * Callback function that returns the pdu length.
540 * Used by TCP dissector.
542 * @param pinfo the info about the packet
543 * @param tvb the data buffer
544 * @param offset the offset to the tvb buffer
545 * @return guint returns pdu length
548 static guint
549 get_knet_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
551 return count_vle_bytes(tvb, offset) + dissect_content_length_vle(tvb, &offset, NULL);
555 * dissect_knet_tcp is the dissector which is called
556 * by Wireshark when kNet TCP packets are captured.
558 * @param tvb the buffer to the data
559 * @param pinfo the packet info structure
560 * @param tree the parent tree where the dissected data is going to be inserted
563 static int
564 dissect_knet_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
566 dissect_knet(tvb, pinfo, tree, KNET_TCP_PACKET);
567 return tvb_length(tvb);
570 static int
571 dissect_knet_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
573 col_clear(pinfo->cinfo, COL_INFO);
574 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNET");
576 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 2, get_knet_pdu_len, dissect_knet_tcp_pdu, data);
577 return tvb_length(tvb);
581 * dissect_knet_sctp is the dissector which is called
582 * by Wireshark when kNet STCP packets are captured.
584 * @param tvb the buffer to the data
585 * @param pinfo the packet info structure
586 * @param tree the parent tree where the dissected data is going to be inserted
589 static void
590 dissect_knet_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
592 col_clear(pinfo->cinfo, COL_INFO);
593 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNET");
595 dissect_knet(tvb, pinfo, tree, KNET_SCTP_PACKET);
599 * dissect_knet_udp is the dissector which is called
600 * by Wireshark when kNet UDP packets are captured.
602 * @param tvb the buffer to the data
603 * @param pinfo the packet info structure
604 * @param tree the parent tree where the dissected data is going to be inserted
607 static void
608 dissect_knet_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
610 /* Common subtrees */
611 proto_item *knet_ti;
612 proto_tree *knet_tree;
614 /* Subtrees used in kNet UDP dissector */
615 proto_item *datagram_ti, *udpflags_ti;
616 proto_tree *datagram_tree, /* Tree containing all header related info */
617 *udpflags_tree; /* Tree containing UDP Datagram Flags */
619 int offset = 0;
620 guint32 packetid; /* Contains info about PacketID */
621 int messageindex = 0; /*!< Index of the kNet message inside a datagram */
623 col_clear(pinfo->cinfo, COL_INFO);
624 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNET");
626 /*kNet UDP Tree*/
627 knet_ti = proto_tree_add_item(tree, proto_knet, tvb, 0, -1, ENC_NA); /* Attach kNet tree to wireshark main tree */
628 knet_tree = proto_item_add_subtree(knet_ti, ett_knet_main);
630 /*Datagram Header Tree*/
631 datagram_ti = proto_tree_add_item(knet_ti, hf_knet_datagram_tree, tvb, 0, 3, ENC_NA); /* Attach Header tree to wireshark main tree */
632 datagram_tree = proto_item_add_subtree(datagram_ti, ett_knet_datagram);
634 packetid = dissect_packetid(tvb, 0, datagram_tree); /* Lets calculate our packetid! */
635 col_add_fstr(pinfo->cinfo, COL_INFO, "Packet ID %d: ", packetid);
637 /*UDPFlags Tree*/
638 udpflags_ti = proto_tree_add_item(datagram_ti, hf_knet_flags, tvb, 0, 1, ENC_NA); /* Attach UDP Flags tree to kNet tree */
639 udpflags_tree = proto_item_add_subtree(udpflags_ti, ett_knet_flags);
641 proto_tree_add_item(udpflags_tree, hf_knet_inorder, tvb, 0, 1, ENC_NA); /* Add inorder flag to UDP Flags tree */
642 proto_tree_add_item(udpflags_tree, hf_knet_reliable, tvb, 0, 1, ENC_NA); /* Add reliable flag to UDP Flags tree */
644 offset += 3;
646 if(tvb_get_guint8(tvb, 0) & UDP_DATAGRAM_RELIABLE_FLAG)
647 offset += dissect_reliable_message_index_base(tvb, 3, datagram_tree); /* Calculate RMIB */
649 while ((tvb_length_remaining(tvb, offset) > 2) && /* If theres at least 2 bytes available in the buffer */
650 (dissect_content_length(tvb, offset, NULL) > 0)) /* Empty data Abort */
652 offset += dissect_knet_message(tvb, pinfo, knet_tree, offset, messageindex); /* Call the message subdissector */
653 messageindex++;
657 * proto_register_knet registers our kNet protocol,
658 * headerfield- and subtree-array to Wireshark.
661 void
662 proto_register_knet(void)
664 module_t *knet_module;
666 static hf_register_info hf_knet[] =
668 /* TCP & SCTP Header */
669 {&hf_knet_content_length_vle,
670 {"Content Length", "knet.length",
671 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
672 {&hf_knet_message_tree,
673 {"Message Block", "knet.msg",
674 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
676 /* UDP Header */
677 {&hf_knet_datagram_tree,
678 {"Datagram Header", "knet.datagram",
679 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
680 {&hf_knet_flags,
681 {"Flags", "knet.datagram.flags",
682 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
683 {&hf_knet_inorder,
684 {"Inorder Flag", "knet.datagram.inorder",
685 FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}},
686 {&hf_knet_reliable,
687 {"Reliable Flag", "knet.datagram.reliable",
688 FT_BOOLEAN, 8, NULL, UDP_DATAGRAM_RELIABLE_FLAG, NULL, HFILL}},
689 {&hf_knet_packetid,
690 {"Packet ID", "knet.datagram.packetid",
691 FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}},
692 {&hf_knet_rmib,
693 {"Reliable Message Index Base", "knet.datagram.rmib",
694 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
695 {&hf_knet_msg_flags,
696 {"Flags", "knet.msg.flags",
697 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
698 {&hf_knet_msg_fs,
699 {"Fragment Start", "knet.msg.flags.fs",
700 FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}},
701 {&hf_knet_msg_ff,
702 {"Fragment Flag", "knet.msg.flags.ff",
703 FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL}},
704 {&hf_knet_msg_inorder,
705 {"Inorder Flag", "knet.msg.flags.inorder",
706 FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL}},
707 {&hf_knet_msg_reliable,
708 {"Reliable Flag", "knet.msg.flags.reliable",
709 FT_BOOLEAN, 8, NULL, UDP_MSG_BLOCK_RELIABLE_FLAG, NULL, HFILL}},
710 {&hf_knet_content_length,
711 {"Content Length", "knet.length",
712 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
713 {&hf_knet_msg_reliable_message_number,
714 {"Reliable Message Number", "knet.msg.reliable_number",
715 FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}},
717 /* Payload */
718 {&hf_knet_payload_tree,
719 {"Payload", "knet.payload.tree",
720 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
721 {&hf_knet_payload,
722 {"Payload", "knet.payload.data",
723 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
724 {&hf_knet_messageid,
725 {"Message ID", "knet.payload.messageid",
726 FT_UINT32, BASE_DEC, VALS(packettypenames), 0x0, NULL, HFILL}},
727 {&hf_knet_pingid,
728 {"Ping ID", "knet.payload.pingid",
729 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
730 {&hf_knet_flowctrlreq,
731 {"Flowcontrol Request", "knet.payload.flowctrlreq",
732 FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}},
733 {&hf_knet_packetack,
734 {"Packet Ack", "knet.payload.packetack",
735 FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL}},
736 {&hf_knet_seqnumber,
737 {"Sequence Number", "knet.payload.seqnumber",
738 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}
741 static gint *ett_knet[] =
743 &ett_knet_main,
744 &ett_knet_datagram,
745 &ett_knet_flags,
746 &ett_knet_message,
747 &ett_knet_message_flags,
748 &ett_knet_payload
751 /* Register header field & subtree arrays */
752 proto_register_field_array(proto_knet, hf_knet, array_length(hf_knet));
753 proto_register_subtree_array(ett_knet, array_length(ett_knet));
755 /* Register protocols */
756 proto_knet = proto_register_protocol ("kNet Protocol", "KNET", "knet");
758 knet_handle_sctp = register_dissector("knetsctp", dissect_knet_sctp, proto_knet);
759 knet_handle_tcp = new_register_dissector("knettcp", dissect_knet_tcp, proto_knet);
760 knet_handle_udp = register_dissector("knetudp", dissect_knet_udp, proto_knet);
762 knet_module = prefs_register_protocol(proto_knet, proto_reg_handoff_knet);
764 prefs_register_uint_preference(knet_module, "sctp.port", "kNet SCTP Port",
765 "Set the SCTP port for kNet messages",
766 10, &knet_sctp_port);
768 prefs_register_uint_preference(knet_module, "tcp.port", "kNet TCP Port",
769 "Set the TCP port for kNet messages",
770 10, &knet_tcp_port);
772 prefs_register_uint_preference(knet_module, "udp.port", "kNet UDP Port",
773 "Set the UDP port for kNet messages",
774 10, &knet_udp_port);
778 * proto_reg_handoff_knet registers our kNet dissectors to Wireshark
781 void
782 proto_reg_handoff_knet(void)
784 static gboolean initialized = FALSE;
786 static guint current_sctp_port;
787 static guint current_tcp_port;
788 static guint current_udp_port;
790 if(!initialized)
792 initialized = TRUE;
794 else
796 dissector_delete_uint("sctp.port", current_sctp_port, knet_handle_sctp);
797 dissector_delete_uint("tcp.port", current_tcp_port, knet_handle_tcp);
798 dissector_delete_uint("udp.port", current_udp_port, knet_handle_udp);
801 current_sctp_port = knet_sctp_port;
802 dissector_add_uint("sctp.port", current_sctp_port, knet_handle_sctp);
804 current_tcp_port = knet_tcp_port;
805 dissector_add_uint("tcp.port", current_tcp_port, knet_handle_tcp);
807 current_udp_port = knet_udp_port;
808 dissector_add_uint("udp.port", current_udp_port, knet_handle_udp);
811 * Editor modelines - http://www.wireshark.org/tools/modelines.html
813 * Local variables:
814 * c-basic-offset: 4
815 * tab-width: 8
816 * indent-tabs-mode: nil
817 * End:
819 * ex: set shiftwidth=4 tabstop=8 expandtab:
820 * :indentSize=4:tabSize=8:noTabs=true: