HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-ouch.c
blob0d857a80ee5c3ded4364d67eab2379d3e3c721d0
1 /* packet-ouch.c
2 * Routines for OUCH 4.x protocol dissection
3 * Copyright 2013 David Arnold <davida@pobox.com>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the
23 * Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301 USA.
28 /* OUCH is a stock exchange order entry protocol published and used by
29 * NASDAQ. This dissector supports versions 4.x, which differ from
30 * earlier versions by adopting binary encoding for numeric values.
32 * OUCH is usually encapsulated within NASDAQ's SoupBinTCP protocol,
33 * running over a TCP connection from the trading application to the
34 * exchange. SOUP provides framing, heartbeats and authentication;
35 * consequently none of these is present in OUCH.
37 * Other exchanges have created order entry protocols very similar to
38 * OUCH, but typically they differ in subtle ways (and continue to
39 * diverge as time progresses) so I have not attempted to dissect
40 * anything other than proper NASDAQ OUCH in this code.
42 * Specifications are available from NASDAQ's website, although the
43 * links to find them tend to move around over time. At the time of
44 * writing, the correct URL is:
46 * http://www.nasdaqtrader.com/content/technicalsupport/specifications/TradingProducts/OUCH4.2.pdf
50 #include "config.h"
52 #include <epan/packet.h>
53 #include <epan/prefs.h>
54 #include <epan/wmem/wmem.h>
56 #include "packet-tcp.h"
59 static const value_string pkt_type_val[] = {
60 { 'O', "Enter Order" },
61 { 'U', "Replace Order" },
62 { 'X', "Cancel Order" },
63 { 'M', "Modify Order" }, /* Not in 4.0 or 4.1 */
64 { 'S', "System Event" },
65 { 'A', "Accepted" },
66 { 'R', "Replaced" }, /* 'U' on the wire, but use 'R' to disambiguate */
67 { 'C', "Canceled" },
68 { 'D', "AIQ Canceled" },
69 { 'E', "Executed" },
70 { 'B', "Broken Trade" },
71 { 'K', "Price Correction" },
72 { 'J', "Rejected" },
73 { 'P', "Cancel Pending" },
74 { 'I', "Cancel Reject" },
75 { 0, NULL }
79 static const value_string ouch_bbo_weight_indicator_val[] = {
80 { '0', "0 - 0.2%" },
81 { '1', "0.2 - 1%" },
82 { '2', "1 - 2%" },
83 { '3', "Greater than 2%" },
84 { ' ', "Unspecified" },
85 { 'S', "Sets the QBBO while joining the NBBO" },
86 { 'N', "Improves the NBBO upon entry" },
87 { 0, NULL }
90 static const value_string ouch_broken_trade_reason_val[] = {
91 { 'E', "Erroneous" },
92 { 'C', "Consent" },
93 { 'S', "Supervisory" },
94 { 'X', "External" },
95 { 0, NULL }
98 static const value_string ouch_buy_sell_indicator_val[] = {
99 { 'B', "Buy Order" },
100 { 'S', "Sell Order" },
101 { 'T', "Sell Short" },
102 { 'E', "Sell Short Exempt" },
103 { 0, NULL }
106 static const value_string ouch_cancel_reason_val[] = {
107 { 'U', "User requested cancel" },
108 { 'I', "Immediate or Cancel order" },
109 { 'T', "Timeout" },
110 { 'S', "Supervisory" },
111 { 'D', "Regulatory restriction" },
112 { 'Q', "Self-match prevention" },
113 { 'Z', "System cancel" },
114 { 0, NULL }
117 static const value_string ouch_capacity_val[] = {
118 { 'A', "Agency" },
119 { 'O', "Other" },
120 { 'P', "Principal" },
121 { 'R', "Riskless" },
122 { 0, NULL }
125 static const value_string ouch_cross_type_val[] = {
126 { 'N', "No Cross" },
127 { 'O', "Opening Cross" },
128 { 'C', "Closing Cross" },
129 { 'I', "Intra-day Cross" },
130 { 'H', "Halt/IPO Cross" },
131 { 'R', "Retail" }, /* Not in 4.0 */
132 { 'S', "Supplemental Order" },
133 { 0, NULL }
136 /* Not in 4.0 */
137 static const value_string ouch_customer_type_val[] = {
138 { 'R', "Retail designated order" },
139 { 'N', "Not a retail designated order" },
140 { ' ', "Default configured for port" },
141 { 0, NULL }
144 static const value_string ouch_display_val[] = {
145 { 'A', "Attributable-Price to Display" },
146 { 'I', "Imbalance-Only" },
147 { 'L', "Post-Only and Attributable - Price to Display" },
148 { 'M', "Mid-Point Peg" },
149 { 'N', "Non-Display" },
150 { 'O', "Retail Order Type 1" }, /* Not in 4.0 */
151 { 'P', "Post-Only" },
152 { 'Q', "Retail Price Improvement Order" }, /* Not in 4.0 */
153 { 'R', "Round-Lot Only" },
154 { 'T', "Retail Order Type 2" }, /* Not in 4.0 */
155 { 'W', "Mid-point Peg Post Only" },
156 { 'Y', "Anonymous-Price to Comply" },
157 { 0, NULL}
160 static const value_string ouch_event_code_val[] = {
161 { 'S', "Start of Day" },
162 { 'E', "End of Day" },
163 { 0, NULL}
166 static const value_string ouch_iso_eligibility_val[] = {
167 { 'Y', "Eligible" },
168 { 'N', "Not eligible" },
169 { 0, NULL }
172 static const value_string ouch_liquidity_flag_val[] = {
173 { 'A', "Added" },
174 { 'R', "Removed" },
175 { 'O', "Opening Cross (billable)" },
176 { 'M', "Opening Cross (non-billable)" },
177 { 'C', "Closing Cross (billable)" },
178 { 'L', "Closing Cross (non-billable)" },
179 { 'H', "Halt/IPO Cross (billable)" },
180 { 'K', "Halt/IPO Cross (non-billable)" },
181 { 'I', "Intraday/Post-Market Cross" },
182 { 'J', "Non-displayed adding liquidity" },
183 { 'm', "Removed liquidity at a midpoint" },
184 { 'k', "Added liquidity via a midpoint order" },
185 { '0', "Supplemental Order Execution" },
186 { '7', "Displayed, liquidity-adding order improves the NBBO" },
187 { '8', "Displayed, liquidity-adding order sets the QBBO while "
188 "joining the NBBO" },
189 /* Added in 4.1 */
190 { 'd', "Retail designated execution that removed liquidity" },
191 { 'e', "Retail designated execution that added displayed liquidity" },
192 { 'f', "Retail designated execution that added non-displayed liquidity" },
193 { 'j', "RPI (Retail Price Improving) order provides liquidity" },
194 { 'r', "Retail Order removes RPI liquidity" },
195 { 't', "Retail Order removes price improving non-displayed liquidity "
196 "other than RPI liquidity" },
197 { '6', "Liquidity Removing Order in designated securities" },
198 { 0, NULL }
201 static const value_string ouch_order_state_val[] = {
202 { 'L', "Order Live" },
203 { 'D', "Order Dead" },
204 { 0, NULL }
207 static const value_string ouch_price_correction_reason_val[] = {
208 { 'E', "Erroneous" },
209 { 'C', "Consent" },
210 { 'S', "Supervisory" },
211 { 'X', "External" },
212 { 0, NULL }
215 static const value_string ouch_reject_reason_val[] = {
216 { 'T', "Test Mode" },
217 { 'H', "Halted" },
218 { 'Z', "Shares exceeds configured safety threshold" },
219 { 'S', "Invalid Stock" },
220 { 'D', "Invalid Display Type" },
221 { 'C', "NASDAQ is Closed" },
222 { 'L', "Requested firm not authorized for requested clearing type on this account" },
223 { 'M', "Outside of permitted times for requested clearing type" },
224 { 'R', "This order is not allowed in this type of cross" },
225 { 'X', "Invalid Price" },
226 { 'N', "Invalid Minimum Quantity" },
227 { 'O', "Other" },
228 { 'a', "Reject All enabled" },
229 { 'b', "Easy to Borrow (ETB) reject" },
230 { 'c', "Restricted symbol list reject" },
231 { 'd', "ISO order restriction" },
232 { 'e', "Odd lot order restriction" },
233 { 'f', "Mid-Point order restriction" },
234 { 'g', "Pre-market order restriction" },
235 { 'h', "Post-market order restriction" },
236 { 'i', "Short sale order restriction" },
237 { 'j', "On Open order restriction" },
238 { 'k', "On Close order restriction" },
239 { 'l', "Two sided quote reject" },
240 { 'm', "Exceeded shares limit" },
241 { 'n', "Exceeded dollar value limit" },
242 { 0, NULL}
246 /* Initialize the protocol and registered fields */
247 static int proto_ouch = -1;
248 static dissector_handle_t ouch_handle;
250 static range_t *global_ouch_range = NULL;
251 static range_t *ouch_range = NULL;
253 /* Initialize the subtree pointers */
254 static gint ett_ouch = -1;
256 static int hf_ouch_bbo_weight_indicator = -1;
257 static int hf_ouch_broken_trade_reason = -1;
258 static int hf_ouch_buy_sell_indicator = -1;
259 static int hf_ouch_cancel_reason = -1;
260 static int hf_ouch_capacity = -1;
261 static int hf_ouch_cross_type = -1;
262 static int hf_ouch_customer_type = -1;
263 static int hf_ouch_decrement_shares = -1;
264 static int hf_ouch_display = -1;
265 static int hf_ouch_event_code = -1;
266 static int hf_ouch_executed_shares = -1;
267 static int hf_ouch_execution_price = -1;
268 static int hf_ouch_existing_order_token = -1;
269 static int hf_ouch_firm = -1;
270 static int hf_ouch_iso_eligible = -1;
271 static int hf_ouch_liquidity_flag = -1;
272 static int hf_ouch_match_number = -1;
273 static int hf_ouch_message = -1;
274 static int hf_ouch_min_quantity = -1;
275 static int hf_ouch_new_execution_price = -1;
276 static int hf_ouch_order_reference_number = -1;
277 static int hf_ouch_order_state = -1;
278 static int hf_ouch_order_token = -1;
279 static int hf_ouch_packet_type = -1;
280 static int hf_ouch_previous_order_token = -1;
281 static int hf_ouch_price = -1;
282 static int hf_ouch_price_correction_reason = -1;
283 static int hf_ouch_quantity_prevented_from_trading = -1;
284 static int hf_ouch_reject_reason = -1;
285 static int hf_ouch_replacement_order_token = -1;
286 static int hf_ouch_shares = -1;
287 static int hf_ouch_stock = -1;
288 static int hf_ouch_tif = -1;
289 static int hf_ouch_timestamp = -1;
292 /** Format an OUCH timestamp into a useful string
294 * We use this function rather than a BASE_CUSTOM formatter because
295 * BASE_CUSTOM doesn't support passing a 64-bit value to the
296 * formatting function. */
297 static void
298 ouch_tree_add_timestamp(
299 proto_tree *tree,
300 const int hf,
301 tvbuff_t *tvb,
302 gint offset)
304 guint64 ts = tvb_get_ntoh64(tvb, offset);
305 char *buf = (char *)wmem_alloc(wmem_packet_scope(), ITEM_LABEL_LENGTH);
306 guint32 tmp, hours, mins, secs, nsecs;
308 nsecs = (guint32)(ts % G_GUINT64_CONSTANT(1000000000));
309 tmp = (guint32)(ts / G_GUINT64_CONSTANT(1000000000));
311 hours = tmp / 3600;
312 mins = (tmp % 3600) / 60;
313 secs = tmp % 60;
315 g_snprintf(buf, ITEM_LABEL_LENGTH,
316 "%u:%02u:%02u.%09u",
317 hours, mins, secs, nsecs);
319 proto_tree_add_string(tree, hf, tvb, offset, 8, buf);
323 /** BASE_CUSTOM formatter for BBO weight indicator code
325 * Displays the code value as a character, not its ASCII value, as
326 * would be done by BASE_DEC and friends. */
327 static void
328 format_bbo_weight_indicator(
329 gchar *buf,
330 guint32 value)
332 g_snprintf(buf, ITEM_LABEL_LENGTH,
333 "%s (%c)",
334 val_to_str_const(value,
335 ouch_bbo_weight_indicator_val,
336 "Unknown"),
337 value);
340 /** BASE_CUSTOM formatter for broken trade reason code
342 * Displays the code value as a character, not its ASCII value, as
343 * would be done by BASE_DEC and friends. */
344 static void
345 format_broken_trade_reason(
346 gchar *buf,
347 guint32 value)
349 g_snprintf(buf, ITEM_LABEL_LENGTH,
350 "%s (%c)",
351 val_to_str_const(value,
352 ouch_broken_trade_reason_val,
353 "Unknown"),
354 value);
357 /** BASE_CUSTOM formatter for buy/sell indicator code
359 * Displays the code value as a character, not its ASCII value, as
360 * would be done by BASE_DEC and friends. */
361 static void
362 format_buy_sell_indicator(
363 gchar *buf,
364 guint32 value)
366 g_snprintf(buf, ITEM_LABEL_LENGTH,
367 "%s (%c)",
368 val_to_str_const(value, ouch_buy_sell_indicator_val, "Unknown"),
369 value);
372 /** BASE_CUSTOM formatter for cancel reason code
374 * Displays the code value as a character, not its ASCII value, as
375 * would be done by BASE_DEC and friends. */
376 static void
377 format_cancel_reason(
378 gchar *buf,
379 guint32 value)
381 g_snprintf(buf, ITEM_LABEL_LENGTH,
382 "%s (%c)",
383 val_to_str_const(value, ouch_cancel_reason_val, "Unknown"),
384 value);
387 /** BASE_CUSTOM formatter for the capacity code
389 * Displays the code value as a character, not its ASCII value, as
390 * would be done by BASE_DEC and friends. */
391 static void
392 format_capacity(
393 char *buf,
394 guint32 value)
396 g_snprintf(buf, ITEM_LABEL_LENGTH,
397 "%s (%c)",
398 val_to_str_const(value, ouch_capacity_val, "Unknown"),
399 value);
402 /** BASE_CUSTOM formatter for the cross type code
404 * Displays the code value as a character, not its ASCII value, as
405 * would be done by BASE_DEC and friends. */
406 static void
407 format_cross_type(
408 char *buf,
409 guint32 value)
411 g_snprintf(buf, ITEM_LABEL_LENGTH,
412 "%s (%c)",
413 val_to_str_const(value, ouch_cross_type_val, "Unknown"),
414 value);
417 /** BASE_CUSTOM formatter for the customer type code
419 * Displays the code value as a character, not its ASCII value, as
420 * would be done by BASE_DEC and friends. */
421 static void
422 format_customer_type(
423 char *buf,
424 guint32 value)
426 g_snprintf(buf, ITEM_LABEL_LENGTH,
427 "%s (%c)",
428 val_to_str_const(value, ouch_customer_type_val, "Unknown"),
429 value);
432 /** BASE_CUSTOM formatter for the display code
434 * Displays the code value as a character, not its ASCII value, as
435 * would be done by BASE_DEC and friends. */
436 static void
437 format_display(
438 char *buf,
439 guint32 value)
441 g_snprintf(buf, ITEM_LABEL_LENGTH,
442 "%s (%c)",
443 val_to_str_const(value, ouch_display_val, "Unknown"),
444 value);
447 /** BASE_CUSTOM formatter for the system event code
449 * Displays the code value as a character, not its ASCII value, as
450 * would be done by BASE_DEC and friends. */
451 static void
452 format_event_code(
453 char *buf,
454 guint32 value)
456 g_snprintf(buf, ITEM_LABEL_LENGTH,
457 "%s (%c)",
458 val_to_str_const(value, ouch_event_code_val, "Unknown"),
459 value);
462 /** BASE_CUSTOM formatter for the ISO eligibility code
464 * Displays the code value as a character, not its ASCII value, as
465 * would be done by BASE_DEC and friends. */
466 static void
467 format_iso_eligibility(
468 char *buf,
469 guint32 value)
471 g_snprintf(buf, ITEM_LABEL_LENGTH,
472 "%s (%c)",
473 val_to_str_const(value, ouch_iso_eligibility_val, "Unknown"),
474 value);
477 /** BASE_CUSTOM formatter for the liquidity flag code
479 * Displays the code value as a character, not its ASCII value, as
480 * would be done by BASE_DEC and friends. */
481 static void
482 format_liquidity_flag(
483 char *buf,
484 guint32 value)
486 g_snprintf(buf, ITEM_LABEL_LENGTH,
487 "%s (%c)",
488 val_to_str_const(value, ouch_liquidity_flag_val, "Unknown"),
489 value);
492 /** BASE_CUSTOM formatter for order state code
494 * Displays the code value as a character, not its ASCII value, as
495 * would be done by BASE_DEC and friends. */
496 static void
497 format_order_state(
498 char *buf,
499 guint32 value)
501 g_snprintf(buf, ITEM_LABEL_LENGTH,
502 "%s (%c)",
503 val_to_str_const(value, ouch_order_state_val, "Unknown"),
504 value);
507 /** BASE_CUSTOM formatter for the packet type code
509 * Displays the code value as a character, not its ASCII value, as
510 * would be done by BASE_DEC and friends. */
511 static void
512 format_packet_type(
513 char *buf,
514 guint32 value)
516 g_snprintf(buf, ITEM_LABEL_LENGTH,
517 "%s (%c)",
518 val_to_str_const(value, pkt_type_val, "Unknown"),
519 value);
522 /** BASE_CUSTOM formatter for prices
524 * OUCH prices are integers, with four implicit decimal places. So we
525 * insert the decimal point, and add a leading dollar sign as well. */
526 static void
527 format_price(
528 char *buf,
529 guint32 value)
531 g_snprintf(buf, ITEM_LABEL_LENGTH,
532 "$%u.%04u",
533 value / 10000, value % 10000);
536 /** BASE_CUSTOM formatter for price correction reason code
538 * Displays the code value as a character, not its ASCII value, as
539 * would be done by BASE_DEC and friends. */
540 static void
541 format_price_correction_reason(
542 char *buf,
543 guint32 value)
545 g_snprintf(buf, ITEM_LABEL_LENGTH,
546 "%s (%c)",
547 val_to_str_const(value,
548 ouch_price_correction_reason_val,
549 "Unknown"),
550 value);
553 /** BASE_CUSTOM formatter for the reject reason code
555 * Displays the code value as a character, not its ASCII value, as
556 * would be done by BASE_DEC and friends. */
557 static void
558 format_reject_reason(
559 char *buf,
560 guint32 value)
562 g_snprintf(buf, ITEM_LABEL_LENGTH,
563 "%s (%c)",
564 val_to_str_const(value, ouch_reject_reason_val, "Unknown"),
565 value);
568 /** BASE_CUSTOM formatter for the Time In Force (TIF) code
570 * There are three reserved values for the TIF: 0, 99998 and 99999.
571 * These are trapped and displayed as an appropriate string. All
572 * other values are printed as a duration in hours, minutes and
573 * seconds. */
574 static void
575 format_tif(
576 gchar *buf,
577 guint32 value)
579 guint32 hours;
580 guint32 mins;
581 guint32 secs;
583 switch (value) {
584 case 0:
585 g_snprintf(buf, ITEM_LABEL_LENGTH, "Immediate Or Cancel (%u)", value);
586 break;
588 case 99998:
589 g_snprintf(buf, ITEM_LABEL_LENGTH, "Market Hours (%u)", value);
590 break;
592 case 99999:
593 g_snprintf(buf, ITEM_LABEL_LENGTH, "System Hours (%u)", value);
594 break;
596 default:
597 hours = value / 3600;
598 mins = (value % 3600) / 60;
599 secs = value % 60;
601 g_snprintf(buf, ITEM_LABEL_LENGTH,
602 "%uh %02um %02us (%u seconds)",
603 hours, mins, secs,
604 value);
605 break;
610 static int
611 dissect_ouch(
612 tvbuff_t *tvb,
613 packet_info *pinfo,
614 proto_tree *tree,
615 void *data _U_)
617 proto_item *ti;
618 proto_tree *ouch_tree = NULL;
619 const char *pkt_name;
620 guint16 reported_len;
621 guint8 pkt_type;
622 int offset = 0;
624 /* Get the OUCH message type value */
625 pkt_type = tvb_get_guint8(tvb, 0);
626 reported_len = tvb_reported_length(tvb);
628 /* OUCH has two messages with the same code: Replace Order and
629 * Replaced. It's possible to tell which is which because clients
630 * send the Replace Order, and NASDAQ sends Replaced replies.
631 * Nonetheless, this complicates the switch, so instead we
632 * distinguish between them by length, and use 'R' for Replaced
633 * (like XPRS does). */
634 if (pkt_type == 'U' && (reported_len == 79 || reported_len == 80)) {
635 pkt_type = 'R';
638 /* Since we use the packet name a few times, get and save that value */
639 pkt_name = val_to_str(pkt_type, pkt_type_val, "Unknown (%u)");
641 /* Set the protocol name in the summary display */
642 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OUCH");
644 /* Set the packet name in the info column */
645 col_add_str(pinfo->cinfo, COL_INFO, pkt_name);
647 if (tree) {
648 /* Create a sub-tree for the OUCH packet details */
649 ti = proto_tree_add_item(tree,
650 proto_ouch,
651 tvb, 0, -1, FALSE);
653 ouch_tree = proto_item_add_subtree(ti, ett_ouch);
655 /* Append the packet name to the sub-tree item */
656 proto_item_append_text(ti, ", %s", pkt_name);
658 /* Packet type (from the buffer, not the modified one we use
659 * for switching) */
660 proto_tree_add_item(ouch_tree,
661 hf_ouch_packet_type,
662 tvb, offset, 1, ENC_BIG_ENDIAN);
663 offset += 1;
665 switch (pkt_type) {
666 case 'O': /* Enter Order */
667 proto_tree_add_item(ouch_tree,
668 hf_ouch_order_token,
669 tvb, offset, 14,
670 ENC_ASCII);
671 offset += 14;
673 proto_tree_add_item(ouch_tree,
674 hf_ouch_buy_sell_indicator,
675 tvb, offset, 1,
676 ENC_BIG_ENDIAN);
677 offset += 1;
679 proto_tree_add_item(ouch_tree,
680 hf_ouch_shares,
681 tvb, offset, 4,
682 ENC_BIG_ENDIAN);
683 offset += 4;
685 proto_tree_add_item(ouch_tree,
686 hf_ouch_stock,
687 tvb, offset, 8,
688 ENC_ASCII);
689 offset += 8;
691 proto_tree_add_item(ouch_tree,
692 hf_ouch_price,
693 tvb, offset, 4,
694 ENC_BIG_ENDIAN);
695 offset += 4;
697 proto_tree_add_item(ouch_tree,
698 hf_ouch_tif,
699 tvb, offset, 4,
700 ENC_BIG_ENDIAN);
701 offset += 4;
703 proto_tree_add_item(ouch_tree,
704 hf_ouch_firm,
705 tvb, offset, 4,
706 ENC_ASCII);
707 offset += 4;
709 proto_tree_add_item(ouch_tree,
710 hf_ouch_display,
711 tvb, offset, 1,
712 ENC_BIG_ENDIAN);
713 offset += 1;
715 proto_tree_add_item(ouch_tree,
716 hf_ouch_capacity,
717 tvb, offset, 1,
718 ENC_BIG_ENDIAN);
719 offset += 1;
721 proto_tree_add_item(ouch_tree,
722 hf_ouch_iso_eligible,
723 tvb, offset, 1,
724 ENC_BIG_ENDIAN);
725 offset += 1;
727 proto_tree_add_item(ouch_tree,
728 hf_ouch_min_quantity,
729 tvb, offset, 4,
730 ENC_BIG_ENDIAN);
731 offset += 4;
733 proto_tree_add_item(ouch_tree,
734 hf_ouch_cross_type,
735 tvb, offset, 1,
736 ENC_BIG_ENDIAN);
737 offset += 1;
739 if (reported_len == 49) { /* Added in 4.1 */
740 proto_tree_add_item(ouch_tree,
741 hf_ouch_customer_type,
742 tvb, offset, 1,
743 ENC_BIG_ENDIAN);
744 offset += 1;
746 break;
748 case 'A': /* Accepted */
749 ouch_tree_add_timestamp(ouch_tree,
750 hf_ouch_timestamp,
751 tvb, offset);
752 offset += 8;
754 proto_tree_add_item(ouch_tree,
755 hf_ouch_order_token,
756 tvb, offset, 14,
757 ENC_ASCII);
758 offset += 14;
760 proto_tree_add_item(ouch_tree,
761 hf_ouch_buy_sell_indicator,
762 tvb, offset, 1,
763 ENC_BIG_ENDIAN);
764 offset += 1;
766 proto_tree_add_item(ouch_tree,
767 hf_ouch_shares,
768 tvb, offset, 4,
769 ENC_BIG_ENDIAN);
770 offset += 4;
772 proto_tree_add_item(ouch_tree,
773 hf_ouch_stock,
774 tvb, offset, 8,
775 ENC_ASCII);
776 offset += 8;
778 proto_tree_add_item(ouch_tree,
779 hf_ouch_price,
780 tvb, offset, 4,
781 ENC_BIG_ENDIAN);
782 offset += 4;
784 proto_tree_add_item(ouch_tree,
785 hf_ouch_tif,
786 tvb, offset, 4,
787 ENC_BIG_ENDIAN);
788 offset += 4;
790 proto_tree_add_item(ouch_tree,
791 hf_ouch_firm,
792 tvb, offset, 4,
793 ENC_ASCII);
794 offset += 4;
796 proto_tree_add_item(ouch_tree,
797 hf_ouch_display,
798 tvb, offset, 1,
799 ENC_BIG_ENDIAN);
800 offset += 1;
802 proto_tree_add_item(ouch_tree,
803 hf_ouch_order_reference_number,
804 tvb, offset, 8,
805 ENC_BIG_ENDIAN);
806 offset += 8;
808 proto_tree_add_item(ouch_tree,
809 hf_ouch_capacity,
810 tvb, offset, 1,
811 ENC_BIG_ENDIAN);
812 offset += 1;
814 proto_tree_add_item(ouch_tree,
815 hf_ouch_iso_eligible,
816 tvb, offset, 1,
817 ENC_BIG_ENDIAN);
818 offset += 1;
820 proto_tree_add_item(ouch_tree,
821 hf_ouch_min_quantity,
822 tvb, offset, 4,
823 ENC_BIG_ENDIAN);
824 offset += 4;
826 proto_tree_add_item(ouch_tree,
827 hf_ouch_cross_type,
828 tvb, offset, 1,
829 ENC_BIG_ENDIAN);
830 offset += 1;
832 proto_tree_add_item(ouch_tree,
833 hf_ouch_order_state,
834 tvb, offset, 1,
835 ENC_BIG_ENDIAN);
836 offset += 1;
838 if (reported_len == 66) { /* Added in 4.2 */
839 proto_tree_add_item(ouch_tree,
840 hf_ouch_bbo_weight_indicator,
841 tvb, offset, 1,
842 ENC_BIG_ENDIAN);
843 offset += 1;
845 break;
847 case 'U': /* Replace Order */
848 proto_tree_add_item(ouch_tree,
849 hf_ouch_existing_order_token,
850 tvb, offset, 14,
851 ENC_ASCII);
852 offset += 14;
854 proto_tree_add_item(ouch_tree,
855 hf_ouch_replacement_order_token,
856 tvb, offset, 14,
857 ENC_ASCII);
858 offset += 14;
860 proto_tree_add_item(ouch_tree,
861 hf_ouch_shares,
862 tvb, offset, 4,
863 ENC_BIG_ENDIAN);
864 offset += 4;
866 proto_tree_add_item(ouch_tree,
867 hf_ouch_price,
868 tvb, offset, 4,
869 ENC_BIG_ENDIAN);
870 offset += 4;
872 proto_tree_add_item(ouch_tree,
873 hf_ouch_tif,
874 tvb, offset, 4,
875 ENC_BIG_ENDIAN);
876 offset += 4;
878 proto_tree_add_item(ouch_tree,
879 hf_ouch_display,
880 tvb, offset, 1,
881 ENC_BIG_ENDIAN);
882 offset += 1;
884 proto_tree_add_item(ouch_tree,
885 hf_ouch_iso_eligible,
886 tvb, offset, 1,
887 ENC_BIG_ENDIAN);
888 offset += 1;
890 proto_tree_add_item(ouch_tree,
891 hf_ouch_min_quantity,
892 tvb, offset, 4,
893 ENC_BIG_ENDIAN);
894 offset += 4;
895 break;
897 case 'X': /* Cancel Order */
898 proto_tree_add_item(ouch_tree,
899 hf_ouch_order_token,
900 tvb, offset, 14,
901 ENC_ASCII);
902 offset += 14;
904 proto_tree_add_item(ouch_tree,
905 hf_ouch_shares,
906 tvb, offset, 4,
907 ENC_BIG_ENDIAN);
908 offset += 4;
909 break;
911 case 'M': /* Modify Order (from 4.2 onwards) */
912 proto_tree_add_item(ouch_tree,
913 hf_ouch_order_token,
914 tvb, offset, 14,
915 ENC_ASCII);
916 offset += 14;
918 proto_tree_add_item(ouch_tree,
919 hf_ouch_buy_sell_indicator,
920 tvb, offset, 1,
921 ENC_BIG_ENDIAN);
922 offset += 1;
924 proto_tree_add_item(ouch_tree,
925 hf_ouch_shares,
926 tvb, offset, 4,
927 ENC_BIG_ENDIAN);
928 offset += 4;
929 break;
931 case 'S': /* System Event */
932 ouch_tree_add_timestamp(ouch_tree,
933 hf_ouch_timestamp,
934 tvb, offset);
935 offset += 8;
937 proto_tree_add_item(ouch_tree,
938 hf_ouch_event_code,
939 tvb, offset, 1,
940 ENC_ASCII);
941 offset += 1;
942 break;
944 case 'R': /* Replaced */
945 ouch_tree_add_timestamp(ouch_tree,
946 hf_ouch_timestamp,
947 tvb, offset);
948 offset += 8;
950 proto_tree_add_item(ouch_tree,
951 hf_ouch_replacement_order_token,
952 tvb, offset, 14,
953 ENC_ASCII);
954 offset += 14;
956 proto_tree_add_item(ouch_tree,
957 hf_ouch_buy_sell_indicator,
958 tvb, offset, 1,
959 ENC_BIG_ENDIAN);
960 offset += 1;
962 proto_tree_add_item(ouch_tree,
963 hf_ouch_shares,
964 tvb, offset, 4,
965 ENC_BIG_ENDIAN);
966 offset += 4;
968 proto_tree_add_item(ouch_tree,
969 hf_ouch_stock,
970 tvb, offset, 8,
971 ENC_ASCII);
972 offset += 8;
974 proto_tree_add_item(ouch_tree,
975 hf_ouch_price,
976 tvb, offset, 4,
977 ENC_BIG_ENDIAN);
978 offset += 4;
980 proto_tree_add_item(ouch_tree,
981 hf_ouch_tif,
982 tvb, offset, 4,
983 ENC_BIG_ENDIAN);
984 offset += 4;
986 proto_tree_add_item(ouch_tree,
987 hf_ouch_firm,
988 tvb, offset, 4,
989 ENC_ASCII);
990 offset += 4;
992 proto_tree_add_item(ouch_tree,
993 hf_ouch_display,
994 tvb, offset, 1,
995 ENC_BIG_ENDIAN);
996 offset += 1;
998 proto_tree_add_item(ouch_tree,
999 hf_ouch_order_reference_number,
1000 tvb, offset, 8,
1001 ENC_BIG_ENDIAN);
1002 offset += 8;
1004 proto_tree_add_item(ouch_tree,
1005 hf_ouch_capacity,
1006 tvb, offset, 1,
1007 ENC_BIG_ENDIAN);
1008 offset += 1;
1010 proto_tree_add_item(ouch_tree,
1011 hf_ouch_iso_eligible,
1012 tvb, offset, 1,
1013 ENC_BIG_ENDIAN);
1014 offset += 1;
1016 proto_tree_add_item(ouch_tree,
1017 hf_ouch_min_quantity,
1018 tvb, offset, 4,
1019 ENC_BIG_ENDIAN);
1020 offset += 4;
1022 proto_tree_add_item(ouch_tree,
1023 hf_ouch_cross_type,
1024 tvb, offset, 1,
1025 ENC_BIG_ENDIAN);
1026 offset += 1;
1028 proto_tree_add_item(ouch_tree,
1029 hf_ouch_order_state,
1030 tvb, offset, 1,
1031 ENC_BIG_ENDIAN);
1032 offset += 1;
1034 proto_tree_add_item(ouch_tree,
1035 hf_ouch_previous_order_token,
1036 tvb, offset, 14,
1037 ENC_ASCII);
1038 offset += 14;
1040 if (reported_len == 80) { /* Added in 4.2 */
1041 proto_tree_add_item(ouch_tree,
1042 hf_ouch_bbo_weight_indicator,
1043 tvb, offset, 1,
1044 ENC_BIG_ENDIAN);
1045 offset += 1;
1047 break;
1049 case 'C': /* Canceled */
1050 ouch_tree_add_timestamp(ouch_tree,
1051 hf_ouch_timestamp,
1052 tvb, offset);
1053 offset += 8;
1055 proto_tree_add_item(ouch_tree,
1056 hf_ouch_order_token,
1057 tvb, offset, 14,
1058 ENC_ASCII);
1059 offset += 14;
1061 proto_tree_add_item(ouch_tree,
1062 hf_ouch_decrement_shares,
1063 tvb, offset, 4,
1064 ENC_BIG_ENDIAN);
1065 offset += 4;
1067 proto_tree_add_item(ouch_tree,
1068 hf_ouch_cancel_reason,
1069 tvb, offset, 1,
1070 ENC_BIG_ENDIAN);
1071 offset += 1;
1072 break;
1074 case 'D': /* AIQ Canceled */
1075 ouch_tree_add_timestamp(ouch_tree,
1076 hf_ouch_timestamp,
1077 tvb, offset);
1078 offset += 8;
1080 proto_tree_add_item(ouch_tree,
1081 hf_ouch_order_token,
1082 tvb, offset, 14,
1083 ENC_ASCII);
1084 offset += 14;
1086 proto_tree_add_item(ouch_tree,
1087 hf_ouch_decrement_shares,
1088 tvb, offset, 4,
1089 ENC_BIG_ENDIAN);
1090 offset += 4;
1092 proto_tree_add_item(ouch_tree,
1093 hf_ouch_cancel_reason,
1094 tvb, offset, 1,
1095 ENC_BIG_ENDIAN);
1096 offset += 1;
1098 proto_tree_add_item(ouch_tree,
1099 hf_ouch_quantity_prevented_from_trading,
1100 tvb, offset, 4,
1101 ENC_BIG_ENDIAN);
1102 offset += 4;
1104 proto_tree_add_item(ouch_tree,
1105 hf_ouch_execution_price,
1106 tvb, offset, 4,
1107 ENC_BIG_ENDIAN);
1108 offset += 4;
1110 proto_tree_add_item(ouch_tree,
1111 hf_ouch_liquidity_flag,
1112 tvb, offset, 1,
1113 ENC_BIG_ENDIAN);
1114 offset += 1;
1115 break;
1117 case 'E': /* Executed */
1118 ouch_tree_add_timestamp(ouch_tree,
1119 hf_ouch_timestamp,
1120 tvb, offset);
1121 offset += 8;
1123 proto_tree_add_item(ouch_tree,
1124 hf_ouch_order_token,
1125 tvb, offset, 14,
1126 ENC_ASCII);
1127 offset += 14;
1129 proto_tree_add_item(ouch_tree,
1130 hf_ouch_executed_shares,
1131 tvb, offset, 4,
1132 ENC_BIG_ENDIAN);
1133 offset += 4;
1135 proto_tree_add_item(ouch_tree,
1136 hf_ouch_execution_price,
1137 tvb, offset, 4,
1138 ENC_BIG_ENDIAN);
1139 offset += 4;
1141 proto_tree_add_item(ouch_tree,
1142 hf_ouch_liquidity_flag,
1143 tvb, offset, 1,
1144 ENC_BIG_ENDIAN);
1145 offset += 1;
1147 proto_tree_add_item(ouch_tree,
1148 hf_ouch_match_number,
1149 tvb, offset, 8,
1150 ENC_BIG_ENDIAN);
1151 offset += 8;
1152 break;
1154 case 'B': /* Broken Trade */
1155 ouch_tree_add_timestamp(ouch_tree,
1156 hf_ouch_timestamp,
1157 tvb, offset);
1158 offset += 8;
1160 proto_tree_add_item(ouch_tree,
1161 hf_ouch_order_token,
1162 tvb, offset, 14,
1163 ENC_ASCII);
1164 offset += 14;
1166 proto_tree_add_item(ouch_tree,
1167 hf_ouch_match_number,
1168 tvb, offset, 8,
1169 ENC_BIG_ENDIAN);
1170 offset += 8;
1172 proto_tree_add_item(ouch_tree,
1173 hf_ouch_broken_trade_reason,
1174 tvb, offset, 1,
1175 ENC_BIG_ENDIAN);
1176 offset += 1;
1177 break;
1179 case 'K': /* Price Correction */
1180 ouch_tree_add_timestamp(ouch_tree,
1181 hf_ouch_timestamp,
1182 tvb, offset);
1183 offset += 8;
1185 proto_tree_add_item(ouch_tree,
1186 hf_ouch_order_token,
1187 tvb, offset, 14,
1188 ENC_ASCII);
1189 offset += 14;
1191 proto_tree_add_item(ouch_tree,
1192 hf_ouch_match_number,
1193 tvb, offset, 8,
1194 ENC_BIG_ENDIAN);
1195 offset += 8;
1197 proto_tree_add_item(ouch_tree,
1198 hf_ouch_new_execution_price,
1199 tvb, offset, 4,
1200 ENC_BIG_ENDIAN);
1201 offset += 4;
1203 proto_tree_add_item(ouch_tree,
1204 hf_ouch_price_correction_reason,
1205 tvb, offset, 1,
1206 ENC_BIG_ENDIAN);
1207 offset += 1;
1208 break;
1210 case 'J': /* Rejected Order */
1211 ouch_tree_add_timestamp(ouch_tree,
1212 hf_ouch_timestamp,
1213 tvb, offset);
1214 offset += 8;
1216 proto_tree_add_item(ouch_tree,
1217 hf_ouch_order_token,
1218 tvb, offset, 14,
1219 ENC_ASCII);
1220 offset += 14;
1222 proto_tree_add_item(ouch_tree,
1223 hf_ouch_reject_reason,
1224 tvb, offset, 1,
1225 ENC_BIG_ENDIAN);
1226 offset += 1;
1227 break;
1229 case 'P': /* Cancel Pending */
1230 ouch_tree_add_timestamp(ouch_tree,
1231 hf_ouch_timestamp,
1232 tvb, offset);
1233 offset += 8;
1235 proto_tree_add_item(ouch_tree,
1236 hf_ouch_order_token,
1237 tvb, offset, 14,
1238 ENC_ASCII);
1239 offset += 14;
1240 break;
1242 case 'I': /* Cancel Reject */
1243 ouch_tree_add_timestamp(ouch_tree,
1244 hf_ouch_timestamp,
1245 tvb, offset);
1246 offset += 8;
1248 proto_tree_add_item(ouch_tree,
1249 hf_ouch_order_token,
1250 tvb, offset, 14,
1251 ENC_ASCII);
1252 offset += 14;
1253 break;
1255 default:
1256 /* Unknown */
1257 proto_tree_add_item(tree,
1258 hf_ouch_message,
1259 tvb, offset, -1, ENC_ASCII|ENC_NA);
1260 offset += reported_len - 1;
1261 break;
1265 return offset;
1269 /* Register the protocol with Wireshark */
1271 static void
1272 ouch_prefs(void)
1274 dissector_delete_uint_range("tcp.port", ouch_range, ouch_handle);
1275 g_free(ouch_range);
1276 ouch_range = range_copy(global_ouch_range);
1277 dissector_add_uint_range("tcp.port", ouch_range, ouch_handle);
1281 /** Returns a guess if a packet is OUCH or not
1283 * Since SOUP doesn't have a sub-protocol type flag, we have to use a
1284 * heuristic decision to determine if the contained protocol is OUCH
1285 * or ITCH (or something else entirely). We look at the message type
1286 * code, and since we know that we're being called from SOUP, we can
1287 * check the passed-in length too: if the type code and the length
1288 * match, we guess at OUCH. */
1289 static gboolean
1290 dissect_ouch_heur(
1291 tvbuff_t *tvb,
1292 packet_info *pinfo,
1293 proto_tree *tree,
1294 void *data _U_)
1296 guint8 msg_type = tvb_get_guint8(tvb, 0);
1297 guint msg_len = tvb_reported_length(tvb);
1299 switch (msg_type) {
1300 case 'O': /* Enter order (with or without optional customer type) */
1301 if (msg_len != 48 && msg_len != 49) {
1302 return FALSE;
1304 break;
1306 case 'U': /* Replace order or Replaced (4.0, 4.1) or Replaced (4.2) */
1307 if (msg_len != 47 && msg_len != 79 && msg_len != 80) {
1308 return FALSE;
1310 break;
1312 case 'X': /* Cancel order */
1313 if (msg_len != 19) {
1314 return FALSE;
1316 break;
1318 case 'S': /* System event */
1319 if (msg_len != 10) {
1320 return FALSE;
1322 break;
1324 case 'A': /* Accepted */
1325 if (msg_len != 65 && msg_len != 66) {
1326 return FALSE;
1328 break;
1330 case 'C': /* Canceled */
1331 if (msg_len != 28) {
1332 return FALSE;
1334 break;
1336 case 'D': /* AIQ Canceled */
1337 if (msg_len != 37) {
1338 return FALSE;
1340 break;
1341 case 'E': /* Executed */
1342 if (msg_len != 40) {
1343 return FALSE;
1345 break;
1347 case 'B': /* Broken Trade */
1348 if (msg_len != 32) {
1349 return FALSE;
1351 break;
1353 case 'K': /* Correction */
1354 if (msg_len != 36) {
1355 return FALSE;
1357 break;
1359 case 'J': /* Rejected */
1360 if (msg_len != 24) {
1361 return FALSE;
1363 break;
1365 case 'P': /* Cancel Pending */
1366 if (msg_len != 23) {
1367 return FALSE;
1369 break;
1371 case 'I': /* Cancel Reject */
1372 if (msg_len != 23) {
1373 return FALSE;
1375 break;
1377 default:
1378 /* Not a known OUCH message code */
1379 return FALSE;
1382 /* Peform dissection of this (initial) packet */
1383 dissect_ouch(tvb, pinfo, tree, NULL);
1385 return TRUE;
1389 void
1390 proto_register_ouch(void)
1392 module_t *ouch_module;
1394 /* Setup list of header fields See Section 1.6.1 for details*/
1395 static hf_register_info hf[] = {
1397 { &hf_ouch_bbo_weight_indicator,
1398 { "BBO Weight Indicator", "ouch.bbo_weight_indicator",
1399 FT_UINT8, BASE_CUSTOM, format_bbo_weight_indicator, 0x0,
1400 NULL, HFILL }},
1402 { &hf_ouch_broken_trade_reason,
1403 { "Broken Trade Reason", "ouch.broken_trade_reason",
1404 FT_UINT8, BASE_CUSTOM, format_broken_trade_reason, 0x0,
1405 NULL, HFILL }},
1407 { &hf_ouch_buy_sell_indicator,
1408 { "Buy/Sell Indicator", "ouch.buy_sell_indicator",
1409 FT_UINT8, BASE_CUSTOM, format_buy_sell_indicator, 0x0,
1410 NULL, HFILL }},
1412 { &hf_ouch_cancel_reason,
1413 { "Cancel Reason", "ouch.cancel_reason",
1414 FT_UINT8, BASE_CUSTOM, format_cancel_reason, 0x0,
1415 NULL, HFILL }},
1417 { &hf_ouch_capacity,
1418 { "Capacity", "ouch.capacity",
1419 FT_UINT8, BASE_CUSTOM, format_capacity, 0x0,
1420 NULL, HFILL }},
1422 { &hf_ouch_cross_type,
1423 { "Cross Type", "ouch.cross_type",
1424 FT_UINT8, BASE_CUSTOM, format_cross_type, 0x0,
1425 NULL, HFILL }},
1427 { &hf_ouch_customer_type,
1428 { "Customer Type", "ouch.customer_type",
1429 FT_UINT8, BASE_CUSTOM, format_customer_type, 0x0,
1430 NULL, HFILL }},
1432 { &hf_ouch_decrement_shares,
1433 { "Decrement Shares", "ouch.decrement_shares",
1434 FT_UINT32, BASE_DEC, NULL, 0x0,
1435 NULL, HFILL }},
1437 { &hf_ouch_display,
1438 { "Display", "ouch.display",
1439 FT_UINT8, BASE_CUSTOM, format_display, 0x0,
1440 NULL, HFILL }},
1442 { &hf_ouch_event_code,
1443 { "Event Code", "ouch.event_code",
1444 FT_UINT8, BASE_CUSTOM, format_event_code, 0x0,
1445 NULL, HFILL }},
1447 { &hf_ouch_executed_shares,
1448 { "Executed Shares", "ouch.executed_shares",
1449 FT_UINT32, BASE_DEC, NULL, 0x0,
1450 NULL, HFILL }},
1452 { &hf_ouch_execution_price,
1453 { "Execution Price", "ouch.execution_price",
1454 FT_UINT32, BASE_CUSTOM, format_price, 0x0,
1455 NULL, HFILL }},
1457 { &hf_ouch_existing_order_token,
1458 { "Existing Order Token", "ouch.existing_order_token",
1459 FT_STRING, BASE_NONE, NULL, 0x0,
1460 NULL, HFILL }},
1462 { &hf_ouch_firm,
1463 { "Firm", "ouch.firm",
1464 FT_STRING, BASE_NONE, NULL, 0x0,
1465 NULL, HFILL }},
1467 { &hf_ouch_iso_eligible,
1468 { "Intermarket Sweep Eligibility", "ouch.iso_eligible",
1469 FT_UINT8, BASE_CUSTOM, format_iso_eligibility, 0x0,
1470 NULL, HFILL }},
1472 { &hf_ouch_liquidity_flag,
1473 { "Liquidity Flag", "ouch.liquidity_flag",
1474 FT_UINT8, BASE_CUSTOM, format_liquidity_flag, 0x0,
1475 NULL, HFILL }},
1477 { &hf_ouch_match_number,
1478 { "Match Number", "ouch.match_number",
1479 FT_UINT64, BASE_DEC, NULL, 0x0,
1480 NULL, HFILL }},
1482 { &hf_ouch_message,
1483 { "Unknown Message", "ouch.unknown_message",
1484 FT_BYTES, BASE_NONE, NULL, 0x0,
1485 NULL, HFILL }},
1487 { &hf_ouch_min_quantity,
1488 { "Minimum Quantity", "ouch.min_quantity",
1489 FT_UINT32, BASE_DEC, NULL, 0x0,
1490 NULL, HFILL }},
1492 { &hf_ouch_new_execution_price,
1493 { "New Execution Price", "ouch.new_execution_price",
1494 FT_UINT32, BASE_CUSTOM, format_price, 0x0,
1495 NULL, HFILL }},
1497 { &hf_ouch_order_reference_number,
1498 { "Order Reference Number", "ouch.order_reference_number",
1499 FT_UINT64, BASE_DEC, NULL, 0x0,
1500 NULL, HFILL }},
1502 { &hf_ouch_order_state,
1503 { "Order State", "ouch.order_state",
1504 FT_UINT8, BASE_CUSTOM, format_order_state, 0x0,
1505 NULL, HFILL }},
1507 { &hf_ouch_order_token,
1508 { "Order Token", "ouch.order_token",
1509 FT_STRING, BASE_NONE, NULL, 0x0,
1510 NULL, HFILL }},
1512 { &hf_ouch_packet_type,
1513 { "Packet Type", "ouch.packet_type",
1514 FT_UINT8, BASE_CUSTOM, format_packet_type, 0x0,
1515 NULL, HFILL }},
1517 { &hf_ouch_previous_order_token,
1518 { "Previous Order Token", "ouch.previous_order_token",
1519 FT_STRING, BASE_NONE, NULL, 0x0,
1520 NULL, HFILL }},
1522 { &hf_ouch_price,
1523 { "Price", "ouch.price",
1524 FT_UINT32, BASE_CUSTOM, format_price, 0x0,
1525 NULL, HFILL }},
1527 { &hf_ouch_price_correction_reason,
1528 { "Price Correction Reason", "ouch.price_correction_reason",
1529 FT_UINT8, BASE_CUSTOM, format_price_correction_reason, 0x0,
1530 NULL, HFILL }},
1532 { &hf_ouch_quantity_prevented_from_trading,
1533 { "Quanity Prevented from Trading",
1534 "ouch.quantity_prevented_from_trading",
1535 FT_UINT32, BASE_DEC, NULL, 0x0,
1536 NULL, HFILL }},
1538 { &hf_ouch_reject_reason,
1539 { "Reject Reason", "ouch.reject_reason",
1540 FT_UINT8, BASE_CUSTOM, format_reject_reason, 0x0,
1541 NULL, HFILL }},
1543 { &hf_ouch_replacement_order_token,
1544 { "Replacement Order Token", "ouch.replacement_order_token",
1545 FT_STRING, BASE_NONE, NULL, 0x0,
1546 NULL, HFILL }},
1548 { &hf_ouch_shares,
1549 { "Shares", "ouch.shares",
1550 FT_UINT32, BASE_DEC, NULL, 0x0,
1551 NULL, HFILL }},
1553 { &hf_ouch_stock,
1554 { "Stock", "ouch.stock",
1555 FT_STRING, BASE_NONE, NULL, 0x0,
1556 NULL, HFILL }},
1558 { &hf_ouch_tif,
1559 { "Time In Force", "ouch.tif",
1560 FT_UINT32, BASE_CUSTOM, format_tif, 0x0,
1561 NULL, HFILL }},
1563 { &hf_ouch_timestamp,
1564 { "Timestamp", "ouch.timestamp",
1565 FT_STRING, BASE_NONE, NULL, 0x0,
1566 NULL, HFILL }}
1569 /* Setup protocol subtree array */
1570 static gint *ett[] = {
1571 &ett_ouch
1574 /* Register the protocol name and description */
1575 proto_ouch = proto_register_protocol("OUCH", "OUCH", "ouch");
1577 /* Required function calls to register the header fields and
1578 * subtrees used */
1579 proto_register_field_array(proto_ouch, hf, array_length(hf));
1580 proto_register_subtree_array(ett, array_length(ett));
1582 ouch_module = prefs_register_protocol(proto_ouch, ouch_prefs);
1584 prefs_register_range_preference(ouch_module,
1585 "tcp.port",
1586 "TCP Ports",
1587 "TCP Ports range",
1588 &global_ouch_range,
1589 65535);
1590 ouch_range = range_empty();
1594 /* If this dissector uses sub-dissector registration add a
1595 * registration routine. This format is required because a script is
1596 * used to find these routines and create the code that calls these
1597 * routines. */
1598 void
1599 proto_reg_handoff_ouch(void)
1601 ouch_handle = new_create_dissector_handle(dissect_ouch, proto_ouch);
1602 heur_dissector_add("soupbintcp", dissect_ouch_heur, proto_ouch);
1608 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1610 * Local variables:
1611 * c-basic-offset: 4
1612 * tab-width: 8
1613 * indent-tabs-mode: nil
1614 * End:
1616 * vi: set shiftwidth=4 tabstop=8 expandtab:
1617 * :indentSize=4:tabSize=8:noTabs=true: