Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-ouch.c
blob9fc55cc464a81fa5de9ce9d575342d9510bcec47
1 /* packet-ouch.c
2 * Routines for OUCH 4.x protocol dissection
3 * Copyright (C) 2013, 2015, 2016 David Arnold <d@0x1.org>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 /* OUCH is a stock exchange order entry protocol published and used by
13 * NASDAQ. This dissector supports versions 4.x, which differ from
14 * earlier versions by adopting binary encoding for numeric values.
16 * OUCH is usually encapsulated within NASDAQ's SoupBinTCP protocol,
17 * running over a TCP connection from the trading application to the
18 * exchange. SOUP provides framing, heartbeats and authentication;
19 * consequently none of these is present in OUCH.
21 * Other exchanges have created order entry protocols very similar to
22 * OUCH, but typically they differ in subtle ways (and continue to
23 * diverge as time progresses) so I have not attempted to dissect
24 * anything other than proper NASDAQ OUCH in this code.
26 * Specifications are available from NASDAQ's website, although the
27 * links to find them tend to move around over time. At the time of
28 * writing, the correct URL is:
30 * http://www.nasdaqtrader.com/content/technicalsupport/specifications/TradingProducts/OUCH4.2.pdf
34 #include "config.h"
36 #include <epan/packet.h>
38 void proto_register_ouch(void);
39 void proto_reg_handoff_ouch(void);
41 static const value_string pkt_type_val[] = {
42 { 'O', "Enter Order" },
43 { 'U', "Replace Order" },
44 { 'X', "Cancel Order" },
45 { 'M', "Modify Order" },
46 { 'S', "System Event" },
47 { 'A', "Accepted" },
48 { 'R', "Replaced" }, /* 'U' on the wire, but use 'R' to disambiguate */
49 { 'C', "Canceled" },
50 { 'D', "AIQ Canceled" },
51 { 'E', "Executed" },
52 { 'F', "Trade Correction" },
53 { 'G', "Executed with Reference Price" },
54 { 'B', "Broken Trade" },
55 { 'K', "Price Correction" },
56 { 'J', "Rejected" },
57 { 'P', "Cancel Pending" },
58 { 'I', "Cancel Reject" },
59 { 'T', "Order Priority Update" },
60 { 'm', "Order Modified" }, /* 'M' on the wire; 'm' to disambiguate */
61 { 0, NULL }
65 static const value_string ouch_bbo_weight_indicator_val[] = {
66 { '0', "0 - 0.2%" },
67 { '1', "0.2 - 1%" },
68 { '2', "1 - 2%" },
69 { '3', "Greater than 2%" },
70 { ' ', "Unspecified" },
71 { 'S', "Sets the QBBO while joining the NBBO" },
72 { 'N', "Improves the NBBO upon entry" },
73 { 0, NULL }
76 static const value_string ouch_broken_trade_reason_val[] = {
77 { 'E', "Erroneous" },
78 { 'C', "Consent" },
79 { 'S', "Supervisory" },
80 { 'X', "External" },
81 { 0, NULL }
84 static const value_string ouch_buy_sell_indicator_val[] = {
85 { 'B', "Buy Order" },
86 { 'S', "Sell Order" },
87 { 'T', "Sell Short" },
88 { 'E', "Sell Short Exempt" },
89 { 0, NULL }
92 static const value_string ouch_cancel_reason_val[] = {
93 { 'C', "Cross cancel" },
94 { 'D', "Regulatory restriction" },
95 { 'E', "Closed" },
96 { 'H', "Halted" },
97 { 'I', "Immediate or Cancel order" },
98 { 'K', "Market Collars" },
99 { 'Q', "Self-match prevention" },
100 { 'S', "Supervisory" },
101 { 'T', "Timeout" },
102 { 'U', "User requested cancel" },
103 { 'X', "Open Protection" },
104 { 'Z', "System cancel" },
105 { 0, NULL }
108 static const value_string ouch_capacity_val[] = {
109 { 'A', "Agency" },
110 { 'O', "Other" },
111 { 'P', "Principal" },
112 { 'R', "Riskless" },
113 { 0, NULL }
116 static const value_string ouch_cross_type_val[] = {
117 { 'N', "No Cross" },
118 { 'O', "Opening Cross" },
119 { 'C', "Closing Cross" },
120 { 'I', "Intra-day Cross" }, /* Seems to have been removed */
121 { 'H', "Halt/IPO Cross" },
122 { 'R', "Retail" }, /* Not in 4.0 */
123 { 'S', "Supplemental Order" },
124 { 0, NULL }
127 /* Not in 4.0 */
128 static const value_string ouch_customer_type_val[] = {
129 { 'R', "Retail designated order" },
130 { 'N', "Not a retail designated order" },
131 { ' ', "Default configured for port" },
132 { 0, NULL }
135 static const value_string ouch_display_val[] = {
136 { 'A', "Attributable-Price to Display" },
137 { 'I', "Imbalance-Only" },
138 { 'L', "Post-Only and Attributable - Price to Display" },
139 { 'M', "Mid-Point Peg" },
140 { 'N', "Non-Display" },
141 { 'O', "Retail Order Type 1" }, /* Not in 4.0 */
142 { 'P', "Post-Only" },
143 { 'Q', "Retail Price Improvement Order" }, /* Not in 4.0 */
144 { 'R', "Round-Lot Only" }, /* Seems to have been removed? */
145 { 'T', "Retail Order Type 2" }, /* Not in 4.0 */
146 { 'W', "Mid-point Peg Post Only" },
147 { 'Y', "Anonymous-Price to Comply" },
148 { 'Z', "Entered as displayed bu changed to non-displayed "
149 "(Priced to comply)" }, /* New in 4.2 */
150 { 0, NULL}
153 static const value_string ouch_event_code_val[] = {
154 { 'S', "Start of Day" },
155 { 'E', "End of Day" },
156 { 0, NULL}
159 static const value_string ouch_iso_eligibility_val[] = {
160 { 'Y', "Eligible" },
161 { 'N', "Not eligible" },
162 { 0, NULL }
165 static const value_string ouch_liquidity_flag_val[] = {
166 { '0', "Supplemental Order Execution" },
167 { '4', "Added displayed liquidity in a Group A Symbol" },
168 { '5', "Added non-displayed liquidity in a Group A Symbol" },
169 { '6', "Removed liquidity in a Group A Symbol" },
170 { '7', "Displayed, liquidity-adding order improves the NBBO" },
171 { '8', "Displayed, liquidity-adding order sets the QBBO while joining the NBBO" },
172 { 'A', "Added" },
173 { 'C', "Closing Cross" },
174 { 'H', "Halt/IPO Cross" },
175 { 'I', "Intraday/Post-Market Cross" }, /* Seems to have been removed */
176 { 'J', "Non-displayed adding liquidity" },
177 { 'K', "Halt Cross" },
178 { 'L', "Closing Cross (imbalance-only)" },
179 { 'M', "Opening Cross (imbalance-only)" },
180 { 'N', "Halt Cross, orders entered in pilot symbols during the LULD Trading Pause" },
181 { 'O', "Opening Cross" },
182 { 'R', "Removed" },
183 { 'W', "Added post-only" }, /* Removed 4.2 2013/02/05 */
184 { 'a', "Added displayed liquidity in a SCIP Symbol" },
185 { 'b', "Displayed, liquidity-adding order improves the NBBO in pilot symbol during specified LULD Pricing Pilot timeframe" },
186 { 'c', "Added displayed liquidity in a pilot symbol during specified LULD Pricing Pilot timeframe" },
187 { 'd', "Retail designated execution that removed liquidity" },
188 { 'e', "Retail designated execution that added displayed liquidity" },
189 { 'f', "Retail designated execution that added non-displayed liquidity" },
190 { 'g', "Added non-displayed mid-point liquidity in a Group A Symbol" },
191 { 'h', "Removed liquidity in a pilot symbol during specified LULD Pricing Pilot timeframe" },
192 { 'j', "RPI (Retail Price Improving) order provides liquidity" },
193 { 'k', "Added liquidity via a midpoint order" },
194 { 'm', "Removed liquidity at a midpoint" },
195 { 'r', "Retail Order removes RPI liquidity" },
196 { 't', "Retail Order removes price improving non-displayed liquidity other than RPI liquidity" },
197 { 'x', "Displayed, liquidity-adding order improves the NBBO in a SCIP Symbol" },
198 { 'y', "Displayed, liquidity-adding order set the QBBO while joining the NBBO in a SCIP Symbol" },
199 { 0, NULL }
202 static const value_string ouch_order_state_val[] = {
203 { 'L', "Order Live" },
204 { 'D', "Order Dead" },
205 { 0, NULL }
208 static const value_string ouch_price_correction_reason_val[] = {
209 { 'E', "Erroneous" },
210 { 'C', "Consent" },
211 { 'S', "Supervisory" },
212 { 'X', "External" },
213 { 0, NULL }
216 static const value_string ouch_reference_price_type_val[] = {
217 { 'I', "Intraday Indicative Value" },
218 { 0, NULL }
221 static const value_string ouch_reject_reason_val[] = {
222 { 'T', "Test Mode" },
223 { 'H', "Halted" },
224 { 'Z', "Shares exceeds configured safety threshold" },
225 { 'S', "Invalid Stock" },
226 { 'D', "Invalid Display Type" },
227 { 'C', "NASDAQ is Closed" },
228 { 'L', "Requested firm not authorized for requested clearing "
229 "type on this account" },
230 { 'M', "Outside of permitted times for requested clearing type" },
231 { 'R', "This order is not allowed in this type of cross" },
232 { 'X', "Invalid Price" },
233 { 'N', "Invalid Minimum Quantity" },
234 { 'O', "Other" },
235 { 'W', "Invalid Mid-point Post Only Price" },
236 { 'a', "Reject All enabled" },
237 { 'b', "Easy to Borrow (ETB) reject" },
238 { 'c', "Restricted symbol list reject" },
239 { 'd', "ISO order restriction" },
240 { 'e', "Odd lot order restriction" },
241 { 'f', "Mid-Point order restriction" },
242 { 'g', "Pre-market order restriction" },
243 { 'h', "Post-market order restriction" },
244 { 'i', "Short sale order restriction" },
245 { 'j', "On Open order restriction" },
246 { 'k', "On Close order restriction" },
247 { 'l', "Two sided quote reject" },
248 { 'm', "Exceeded shares limit" },
249 { 'n', "Exceeded dollar value limit" },
250 { 0, NULL}
253 static const value_string ouch_trade_correction_reason_val[] = {
254 { 'N', "Adjusted to NAV" },
255 { 0, NULL }
259 /* Initialize the protocol and registered fields */
260 static int proto_ouch;
261 static dissector_handle_t ouch_handle;
263 /* Initialize the subtree pointers */
264 static int ett_ouch;
266 static int hf_ouch_bbo_weight_indicator;
267 static int hf_ouch_broken_trade_reason;
268 static int hf_ouch_buy_sell_indicator;
269 static int hf_ouch_cancel_reason;
270 static int hf_ouch_capacity;
271 static int hf_ouch_cross_type;
272 static int hf_ouch_customer_type;
273 static int hf_ouch_decrement_shares;
274 static int hf_ouch_display;
275 static int hf_ouch_event_code;
276 static int hf_ouch_executed_shares;
277 static int hf_ouch_execution_price;
278 static int hf_ouch_existing_order_token;
279 static int hf_ouch_firm;
280 static int hf_ouch_iso_eligible;
281 static int hf_ouch_liquidity_flag;
282 static int hf_ouch_match_number;
283 static int hf_ouch_message;
284 static int hf_ouch_min_quantity;
285 static int hf_ouch_new_execution_price;
286 static int hf_ouch_order_reference_number;
287 static int hf_ouch_order_state;
288 static int hf_ouch_order_token;
289 static int hf_ouch_packet_type;
290 static int hf_ouch_previous_order_token;
291 static int hf_ouch_price;
292 static int hf_ouch_price_correction_reason;
293 static int hf_ouch_quantity_prevented_from_trading;
294 static int hf_ouch_reference_price;
295 static int hf_ouch_reference_price_type;
296 static int hf_ouch_reject_reason;
297 static int hf_ouch_replacement_order_token;
298 static int hf_ouch_shares;
299 static int hf_ouch_stock;
300 static int hf_ouch_tif;
301 static int hf_ouch_timestamp;
302 static int hf_ouch_trade_correction_reason;
305 /** Format an OUCH timestamp into a useful string
307 * We use this function rather than a BASE_CUSTOM formatter because
308 * BASE_CUSTOM doesn't support passing a 64-bit value to the
309 * formatting function. */
310 static void
311 ouch_tree_add_timestamp(
312 packet_info *pinfo,
313 proto_tree *tree,
314 const int hf,
315 tvbuff_t *tvb,
316 int offset)
318 uint64_t ts = tvb_get_ntoh64(tvb, offset);
319 char *buf = (char *)wmem_alloc(pinfo->pool, ITEM_LABEL_LENGTH);
320 uint32_t tmp, hours, mins, secs, nsecs;
322 nsecs = (uint32_t)(ts % UINT64_C(1000000000));
323 tmp = (uint32_t)(ts / UINT64_C(1000000000));
325 hours = tmp / 3600;
326 mins = (tmp % 3600) / 60;
327 secs = tmp % 60;
329 snprintf(buf, ITEM_LABEL_LENGTH,
330 "%u:%02u:%02u.%09u",
331 hours, mins, secs, nsecs);
333 proto_tree_add_string(tree, hf, tvb, offset, 8, buf);
336 /** BASE_CUSTOM formatter for prices
338 * OUCH prices are integers, with four implicit decimal places. So we
339 * insert the decimal point, and add a leading dollar sign as well. */
340 static void
341 format_price(
342 char *buf,
343 uint32_t value)
345 if (value == 0x7fffffff) {
346 snprintf(buf, ITEM_LABEL_LENGTH, "%s", "Market");
347 } else {
348 snprintf(buf, ITEM_LABEL_LENGTH,
349 "$%u.%04u",
350 value / 10000, value % 10000);
354 /** BASE_CUSTOM formatter for reference price type code
356 * Displays the code value as a character, not its ASCII value, as
357 * would be done by BASE_DEC and friends. */
358 static void
359 format_reference_price_type(
360 char *buf,
361 uint32_t value)
363 snprintf(buf, ITEM_LABEL_LENGTH,
364 "%s (%c)",
365 val_to_str_const(value,
366 ouch_reference_price_type_val,
367 "Unknown"),
368 value);
371 /** BASE_CUSTOM formatter for the Time In Force (TIF) code
373 * There are three reserved values for the TIF: 0, 99998 and 99999.
374 * These are trapped and displayed as an appropriate string. All
375 * other values are printed as a duration in hours, minutes and
376 * seconds. */
377 static void
378 format_tif(
379 char *buf,
380 uint32_t value)
382 uint32_t hours;
383 uint32_t mins;
384 uint32_t secs;
386 switch (value) {
387 case 0:
388 snprintf(buf, ITEM_LABEL_LENGTH, "Immediate Or Cancel (%u)", value);
389 break;
391 case 99998:
392 snprintf(buf, ITEM_LABEL_LENGTH, "Market Hours (%u)", value);
393 break;
395 case 99999:
396 snprintf(buf, ITEM_LABEL_LENGTH, "System Hours (%u)", value);
397 break;
399 default:
400 hours = value / 3600;
401 mins = (value % 3600) / 60;
402 secs = value % 60;
404 snprintf(buf, ITEM_LABEL_LENGTH,
405 "%uh %02um %02us (%u seconds)",
406 hours, mins, secs,
407 value);
408 break;
413 static int
414 dissect_ouch(
415 tvbuff_t *tvb,
416 packet_info *pinfo,
417 proto_tree *tree,
418 void *data _U_)
420 proto_item *ti;
421 proto_tree *ouch_tree = NULL;
422 const char *pkt_name;
423 uint16_t reported_len;
424 uint8_t pkt_type;
425 int offset = 0;
427 /* Get the OUCH message type value */
428 pkt_type = tvb_get_uint8(tvb, offset);
429 reported_len = tvb_reported_length(tvb);
431 /* OUCH has two messages with the same code: Replace Order and
432 * Replaced. It's possible to tell which is which because clients
433 * send the Replace Order, and NASDAQ sends Replaced replies.
434 * Nonetheless, this complicates the switch, so instead we
435 * distinguish between them by length, and use 'R' for Replaced
436 * (like XPRS does). */
437 if (pkt_type == 'U' && (reported_len == 79 || reported_len == 80)) {
438 pkt_type = 'R';
441 /* OUCH has two messages with the same code: Modify Order and
442 * Modified. Again, one is sent by clients, the other sent by
443 * NASDAQ. We change Modified to 'm' for simplicity in the
444 * switch. */
445 if (pkt_type == 'M' && reported_len == 28) {
446 pkt_type = 'm';
449 /* Since we use the packet name a few times, get and save that value */
450 pkt_name = val_to_str(pkt_type, pkt_type_val, "Unknown (%u)");
452 /* Set the protocol name in the summary display */
453 col_set_str(pinfo->cinfo, COL_PROTOCOL, "OUCH");
455 /* Set the packet name in the info column */
456 col_add_str(pinfo->cinfo, COL_INFO, pkt_name);
458 if (tree) {
459 /* Create a sub-tree for the OUCH packet details */
460 ti = proto_tree_add_item(tree,
461 proto_ouch,
462 tvb, 0, -1, ENC_NA);
464 ouch_tree = proto_item_add_subtree(ti, ett_ouch);
466 /* Append the packet name to the sub-tree item */
467 proto_item_append_text(ti, ", %s", pkt_name);
469 /* Packet type (using the cooked value). */
470 proto_tree_add_item(ouch_tree, hf_ouch_packet_type,
471 tvb, offset, 1, ENC_ASCII|ENC_NA);
472 offset += 1;
474 switch (pkt_type) {
475 case 'O': /* Enter Order */
476 proto_tree_add_item(ouch_tree,
477 hf_ouch_order_token,
478 tvb, offset, 14,
479 ENC_ASCII);
480 offset += 14;
482 proto_tree_add_item(ouch_tree,
483 hf_ouch_buy_sell_indicator,
484 tvb, offset, 1,
485 ENC_ASCII|ENC_NA);
486 offset += 1;
488 proto_tree_add_item(ouch_tree,
489 hf_ouch_shares,
490 tvb, offset, 4,
491 ENC_BIG_ENDIAN);
492 offset += 4;
494 proto_tree_add_item(ouch_tree,
495 hf_ouch_stock,
496 tvb, offset, 8,
497 ENC_ASCII);
498 offset += 8;
500 proto_tree_add_item(ouch_tree,
501 hf_ouch_price,
502 tvb, offset, 4,
503 ENC_BIG_ENDIAN);
504 offset += 4;
506 proto_tree_add_item(ouch_tree,
507 hf_ouch_tif,
508 tvb, offset, 4,
509 ENC_BIG_ENDIAN);
510 offset += 4;
512 proto_tree_add_item(ouch_tree,
513 hf_ouch_firm,
514 tvb, offset, 4,
515 ENC_ASCII);
516 offset += 4;
518 proto_tree_add_item(ouch_tree,
519 hf_ouch_display,
520 tvb, offset, 1,
521 ENC_ASCII|ENC_NA);
522 offset += 1;
524 proto_tree_add_item(ouch_tree,
525 hf_ouch_capacity,
526 tvb, offset, 1,
527 ENC_ASCII|ENC_NA);
528 offset += 1;
530 proto_tree_add_item(ouch_tree,
531 hf_ouch_iso_eligible,
532 tvb, offset, 1,
533 ENC_ASCII|ENC_NA);
534 offset += 1;
536 proto_tree_add_item(ouch_tree,
537 hf_ouch_min_quantity,
538 tvb, offset, 4,
539 ENC_BIG_ENDIAN);
540 offset += 4;
542 proto_tree_add_item(ouch_tree,
543 hf_ouch_cross_type,
544 tvb, offset, 1,
545 ENC_ASCII|ENC_NA);
546 offset += 1;
548 if (reported_len >= 49) { /* Added in 4.1 */
549 proto_tree_add_item(ouch_tree,
550 hf_ouch_customer_type,
551 tvb, offset, 1,
552 ENC_ASCII|ENC_NA);
553 offset += 1;
555 break;
557 case 'A': /* Accepted */
558 ouch_tree_add_timestamp(pinfo, ouch_tree,
559 hf_ouch_timestamp,
560 tvb, offset);
561 offset += 8;
563 proto_tree_add_item(ouch_tree,
564 hf_ouch_order_token,
565 tvb, offset, 14,
566 ENC_ASCII);
567 offset += 14;
569 proto_tree_add_item(ouch_tree,
570 hf_ouch_buy_sell_indicator,
571 tvb, offset, 1,
572 ENC_BIG_ENDIAN);
573 offset += 1;
575 proto_tree_add_item(ouch_tree,
576 hf_ouch_shares,
577 tvb, offset, 4,
578 ENC_BIG_ENDIAN);
579 offset += 4;
581 proto_tree_add_item(ouch_tree,
582 hf_ouch_stock,
583 tvb, offset, 8,
584 ENC_ASCII);
585 offset += 8;
587 proto_tree_add_item(ouch_tree,
588 hf_ouch_price,
589 tvb, offset, 4,
590 ENC_BIG_ENDIAN);
591 offset += 4;
593 proto_tree_add_item(ouch_tree,
594 hf_ouch_tif,
595 tvb, offset, 4,
596 ENC_BIG_ENDIAN);
597 offset += 4;
599 proto_tree_add_item(ouch_tree,
600 hf_ouch_firm,
601 tvb, offset, 4,
602 ENC_ASCII);
603 offset += 4;
605 proto_tree_add_item(ouch_tree,
606 hf_ouch_display,
607 tvb, offset, 1,
608 ENC_ASCII|ENC_NA);
609 offset += 1;
611 proto_tree_add_item(ouch_tree,
612 hf_ouch_order_reference_number,
613 tvb, offset, 8,
614 ENC_BIG_ENDIAN);
615 offset += 8;
617 proto_tree_add_item(ouch_tree,
618 hf_ouch_capacity,
619 tvb, offset, 1,
620 ENC_ASCII|ENC_NA);
621 offset += 1;
623 proto_tree_add_item(ouch_tree,
624 hf_ouch_iso_eligible,
625 tvb, offset, 1,
626 ENC_ASCII|ENC_NA);
627 offset += 1;
629 proto_tree_add_item(ouch_tree,
630 hf_ouch_min_quantity,
631 tvb, offset, 4,
632 ENC_BIG_ENDIAN);
633 offset += 4;
635 proto_tree_add_item(ouch_tree,
636 hf_ouch_cross_type,
637 tvb, offset, 1,
638 ENC_ASCII|ENC_NA);
639 offset += 1;
641 proto_tree_add_item(ouch_tree,
642 hf_ouch_order_state,
643 tvb, offset, 1,
644 ENC_ASCII|ENC_NA);
645 offset += 1;
647 if (reported_len >= 66) { /* Added in 4.2 */
648 proto_tree_add_item(ouch_tree,
649 hf_ouch_bbo_weight_indicator,
650 tvb, offset, 1,
651 ENC_ASCII|ENC_NA);
652 offset += 1;
654 break;
656 case 'U': /* Replace Order */
657 proto_tree_add_item(ouch_tree,
658 hf_ouch_existing_order_token,
659 tvb, offset, 14,
660 ENC_ASCII);
661 offset += 14;
663 proto_tree_add_item(ouch_tree,
664 hf_ouch_replacement_order_token,
665 tvb, offset, 14,
666 ENC_ASCII);
667 offset += 14;
669 proto_tree_add_item(ouch_tree,
670 hf_ouch_shares,
671 tvb, offset, 4,
672 ENC_BIG_ENDIAN);
673 offset += 4;
675 proto_tree_add_item(ouch_tree,
676 hf_ouch_price,
677 tvb, offset, 4,
678 ENC_BIG_ENDIAN);
679 offset += 4;
681 proto_tree_add_item(ouch_tree,
682 hf_ouch_tif,
683 tvb, offset, 4,
684 ENC_BIG_ENDIAN);
685 offset += 4;
687 proto_tree_add_item(ouch_tree,
688 hf_ouch_display,
689 tvb, offset, 1,
690 ENC_ASCII|ENC_NA);
691 offset += 1;
693 proto_tree_add_item(ouch_tree,
694 hf_ouch_iso_eligible,
695 tvb, offset, 1,
696 ENC_ASCII|ENC_NA);
697 offset += 1;
699 proto_tree_add_item(ouch_tree,
700 hf_ouch_min_quantity,
701 tvb, offset, 4,
702 ENC_BIG_ENDIAN);
703 offset += 4;
704 break;
706 case 'X': /* Cancel Order */
707 proto_tree_add_item(ouch_tree,
708 hf_ouch_order_token,
709 tvb, offset, 14,
710 ENC_ASCII);
711 offset += 14;
713 proto_tree_add_item(ouch_tree,
714 hf_ouch_shares,
715 tvb, offset, 4,
716 ENC_BIG_ENDIAN);
717 offset += 4;
718 break;
720 case 'M': /* Modify Order (from 4.2 onwards) */
721 proto_tree_add_item(ouch_tree,
722 hf_ouch_order_token,
723 tvb, offset, 14,
724 ENC_ASCII);
725 offset += 14;
727 proto_tree_add_item(ouch_tree,
728 hf_ouch_buy_sell_indicator,
729 tvb, offset, 1,
730 ENC_BIG_ENDIAN);
731 offset += 1;
733 proto_tree_add_item(ouch_tree,
734 hf_ouch_shares,
735 tvb, offset, 4,
736 ENC_BIG_ENDIAN);
737 offset += 4;
738 break;
740 case 'S': /* System Event */
741 ouch_tree_add_timestamp(pinfo, ouch_tree,
742 hf_ouch_timestamp,
743 tvb, offset);
744 offset += 8;
746 proto_tree_add_item(ouch_tree,
747 hf_ouch_event_code,
748 tvb, offset, 1,
749 ENC_ASCII|ENC_NA);
750 offset += 1;
751 break;
753 case 'R': /* Replaced */
754 ouch_tree_add_timestamp(pinfo, ouch_tree,
755 hf_ouch_timestamp,
756 tvb, offset);
757 offset += 8;
759 proto_tree_add_item(ouch_tree,
760 hf_ouch_replacement_order_token,
761 tvb, offset, 14,
762 ENC_ASCII);
763 offset += 14;
765 proto_tree_add_item(ouch_tree,
766 hf_ouch_buy_sell_indicator,
767 tvb, offset, 1,
768 ENC_BIG_ENDIAN);
769 offset += 1;
771 proto_tree_add_item(ouch_tree,
772 hf_ouch_shares,
773 tvb, offset, 4,
774 ENC_BIG_ENDIAN);
775 offset += 4;
777 proto_tree_add_item(ouch_tree,
778 hf_ouch_stock,
779 tvb, offset, 8,
780 ENC_ASCII);
781 offset += 8;
783 proto_tree_add_item(ouch_tree,
784 hf_ouch_price,
785 tvb, offset, 4,
786 ENC_BIG_ENDIAN);
787 offset += 4;
789 proto_tree_add_item(ouch_tree,
790 hf_ouch_tif,
791 tvb, offset, 4,
792 ENC_BIG_ENDIAN);
793 offset += 4;
795 proto_tree_add_item(ouch_tree,
796 hf_ouch_firm,
797 tvb, offset, 4,
798 ENC_ASCII);
799 offset += 4;
801 proto_tree_add_item(ouch_tree,
802 hf_ouch_display,
803 tvb, offset, 1,
804 ENC_ASCII|ENC_NA);
805 offset += 1;
807 proto_tree_add_item(ouch_tree,
808 hf_ouch_order_reference_number,
809 tvb, offset, 8,
810 ENC_BIG_ENDIAN);
811 offset += 8;
813 proto_tree_add_item(ouch_tree,
814 hf_ouch_capacity,
815 tvb, offset, 1,
816 ENC_ASCII|ENC_NA);
817 offset += 1;
819 proto_tree_add_item(ouch_tree,
820 hf_ouch_iso_eligible,
821 tvb, offset, 1,
822 ENC_ASCII|ENC_NA);
823 offset += 1;
825 proto_tree_add_item(ouch_tree,
826 hf_ouch_min_quantity,
827 tvb, offset, 4,
828 ENC_BIG_ENDIAN);
829 offset += 4;
831 proto_tree_add_item(ouch_tree,
832 hf_ouch_cross_type,
833 tvb, offset, 1,
834 ENC_ASCII|ENC_NA);
835 offset += 1;
837 proto_tree_add_item(ouch_tree,
838 hf_ouch_order_state,
839 tvb, offset, 1,
840 ENC_ASCII|ENC_NA);
841 offset += 1;
843 proto_tree_add_item(ouch_tree,
844 hf_ouch_previous_order_token,
845 tvb, offset, 14,
846 ENC_ASCII);
847 offset += 14;
849 if (reported_len >= 80) { /* Added in 4.2 */
850 proto_tree_add_item(ouch_tree,
851 hf_ouch_bbo_weight_indicator,
852 tvb, offset, 1,
853 ENC_BIG_ENDIAN);
854 offset += 1;
856 break;
858 case 'C': /* Canceled */
859 ouch_tree_add_timestamp(pinfo, ouch_tree,
860 hf_ouch_timestamp,
861 tvb, offset);
862 offset += 8;
864 proto_tree_add_item(ouch_tree,
865 hf_ouch_order_token,
866 tvb, offset, 14,
867 ENC_ASCII);
868 offset += 14;
870 proto_tree_add_item(ouch_tree,
871 hf_ouch_decrement_shares,
872 tvb, offset, 4,
873 ENC_BIG_ENDIAN);
874 offset += 4;
876 proto_tree_add_item(ouch_tree,
877 hf_ouch_cancel_reason,
878 tvb, offset, 1,
879 ENC_ASCII|ENC_NA);
880 offset += 1;
881 break;
883 case 'D': /* AIQ Canceled */
884 ouch_tree_add_timestamp(pinfo, ouch_tree,
885 hf_ouch_timestamp,
886 tvb, offset);
887 offset += 8;
889 proto_tree_add_item(ouch_tree,
890 hf_ouch_order_token,
891 tvb, offset, 14,
892 ENC_ASCII);
893 offset += 14;
895 proto_tree_add_item(ouch_tree,
896 hf_ouch_decrement_shares,
897 tvb, offset, 4,
898 ENC_BIG_ENDIAN);
899 offset += 4;
901 proto_tree_add_item(ouch_tree,
902 hf_ouch_cancel_reason,
903 tvb, offset, 1,
904 ENC_ASCII|ENC_NA);
905 offset += 1;
907 proto_tree_add_item(ouch_tree,
908 hf_ouch_quantity_prevented_from_trading,
909 tvb, offset, 4,
910 ENC_BIG_ENDIAN);
911 offset += 4;
913 proto_tree_add_item(ouch_tree,
914 hf_ouch_execution_price,
915 tvb, offset, 4,
916 ENC_BIG_ENDIAN);
917 offset += 4;
919 proto_tree_add_item(ouch_tree,
920 hf_ouch_liquidity_flag,
921 tvb, offset, 1,
922 ENC_ASCII|ENC_NA);
923 offset += 1;
924 break;
926 case 'E': /* Executed */
927 ouch_tree_add_timestamp(pinfo, ouch_tree,
928 hf_ouch_timestamp,
929 tvb, offset);
930 offset += 8;
932 proto_tree_add_item(ouch_tree,
933 hf_ouch_order_token,
934 tvb, offset, 14,
935 ENC_ASCII);
936 offset += 14;
938 proto_tree_add_item(ouch_tree,
939 hf_ouch_executed_shares,
940 tvb, offset, 4,
941 ENC_BIG_ENDIAN);
942 offset += 4;
944 proto_tree_add_item(ouch_tree,
945 hf_ouch_execution_price,
946 tvb, offset, 4,
947 ENC_BIG_ENDIAN);
948 offset += 4;
950 proto_tree_add_item(ouch_tree,
951 hf_ouch_liquidity_flag,
952 tvb, offset, 1,
953 ENC_ASCII|ENC_NA);
954 offset += 1;
956 proto_tree_add_item(ouch_tree,
957 hf_ouch_match_number,
958 tvb, offset, 8,
959 ENC_BIG_ENDIAN);
960 offset += 8;
961 break;
963 case 'B': /* Broken Trade */
964 ouch_tree_add_timestamp(pinfo, ouch_tree,
965 hf_ouch_timestamp,
966 tvb, offset);
967 offset += 8;
969 proto_tree_add_item(ouch_tree,
970 hf_ouch_order_token,
971 tvb, offset, 14,
972 ENC_ASCII);
973 offset += 14;
975 proto_tree_add_item(ouch_tree,
976 hf_ouch_match_number,
977 tvb, offset, 8,
978 ENC_BIG_ENDIAN);
979 offset += 8;
981 proto_tree_add_item(ouch_tree,
982 hf_ouch_broken_trade_reason,
983 tvb, offset, 1,
984 ENC_ASCII|ENC_NA);
985 offset += 1;
986 break;
988 case 'F': /* Trade Correction (4.2 onwards) */
989 ouch_tree_add_timestamp(pinfo, ouch_tree,
990 hf_ouch_timestamp,
991 tvb, offset);
992 offset += 8;
994 proto_tree_add_item(ouch_tree,
995 hf_ouch_order_token,
996 tvb, offset, 14,
997 ENC_ASCII);
998 offset += 14;
1000 proto_tree_add_item(ouch_tree,
1001 hf_ouch_executed_shares,
1002 tvb, offset, 4,
1003 ENC_BIG_ENDIAN);
1004 offset += 4;
1006 proto_tree_add_item(ouch_tree,
1007 hf_ouch_execution_price,
1008 tvb, offset, 4,
1009 ENC_BIG_ENDIAN);
1010 offset += 4;
1012 proto_tree_add_item(ouch_tree,
1013 hf_ouch_liquidity_flag,
1014 tvb, offset, 1,
1015 ENC_ASCII|ENC_NA);
1016 offset += 1;
1018 proto_tree_add_item(ouch_tree,
1019 hf_ouch_match_number,
1020 tvb, offset, 8,
1021 ENC_BIG_ENDIAN);
1022 offset += 8;
1024 proto_tree_add_item(ouch_tree,
1025 hf_ouch_trade_correction_reason,
1026 tvb, offset, 1,
1027 ENC_ASCII|ENC_NA);
1028 offset += 1;
1029 break;
1031 case 'G': /* Executed with Reference Price (4.2 onwards) */
1032 ouch_tree_add_timestamp(pinfo, ouch_tree,
1033 hf_ouch_timestamp,
1034 tvb, offset);
1035 offset += 8;
1037 proto_tree_add_item(ouch_tree,
1038 hf_ouch_order_token,
1039 tvb, offset, 14,
1040 ENC_ASCII);
1041 offset += 14;
1043 proto_tree_add_item(ouch_tree,
1044 hf_ouch_executed_shares,
1045 tvb, offset, 4,
1046 ENC_BIG_ENDIAN);
1047 offset += 4;
1049 proto_tree_add_item(ouch_tree,
1050 hf_ouch_execution_price,
1051 tvb, offset, 4,
1052 ENC_BIG_ENDIAN);
1053 offset += 4;
1055 proto_tree_add_item(ouch_tree,
1056 hf_ouch_liquidity_flag,
1057 tvb, offset, 1,
1058 ENC_ASCII|ENC_NA);
1059 offset += 1;
1061 proto_tree_add_item(ouch_tree,
1062 hf_ouch_match_number,
1063 tvb, offset, 8,
1064 ENC_BIG_ENDIAN);
1065 offset += 8;
1067 proto_tree_add_item(ouch_tree,
1068 hf_ouch_reference_price,
1069 tvb, offset, 4,
1070 ENC_BIG_ENDIAN);
1071 offset += 4;
1073 proto_tree_add_item(ouch_tree,
1074 hf_ouch_reference_price_type,
1075 tvb, offset, 1,
1076 ENC_BIG_ENDIAN);
1077 offset += 1;
1078 break;
1080 case 'K': /* Price Correction */
1081 ouch_tree_add_timestamp(pinfo, ouch_tree,
1082 hf_ouch_timestamp,
1083 tvb, offset);
1084 offset += 8;
1086 proto_tree_add_item(ouch_tree,
1087 hf_ouch_order_token,
1088 tvb, offset, 14,
1089 ENC_ASCII);
1090 offset += 14;
1092 proto_tree_add_item(ouch_tree,
1093 hf_ouch_match_number,
1094 tvb, offset, 8,
1095 ENC_BIG_ENDIAN);
1096 offset += 8;
1098 proto_tree_add_item(ouch_tree,
1099 hf_ouch_new_execution_price,
1100 tvb, offset, 4,
1101 ENC_BIG_ENDIAN);
1102 offset += 4;
1104 proto_tree_add_item(ouch_tree,
1105 hf_ouch_price_correction_reason,
1106 tvb, offset, 1,
1107 ENC_ASCII|ENC_NA);
1108 offset += 1;
1109 break;
1111 case 'J': /* Rejected Order */
1112 ouch_tree_add_timestamp(pinfo, ouch_tree,
1113 hf_ouch_timestamp,
1114 tvb, offset);
1115 offset += 8;
1117 proto_tree_add_item(ouch_tree,
1118 hf_ouch_order_token,
1119 tvb, offset, 14,
1120 ENC_ASCII);
1121 offset += 14;
1123 proto_tree_add_item(ouch_tree,
1124 hf_ouch_reject_reason,
1125 tvb, offset, 1,
1126 ENC_ASCII|ENC_NA);
1127 offset += 1;
1128 break;
1130 case 'P': /* Cancel Pending */
1131 ouch_tree_add_timestamp(pinfo, ouch_tree,
1132 hf_ouch_timestamp,
1133 tvb, offset);
1134 offset += 8;
1136 proto_tree_add_item(ouch_tree,
1137 hf_ouch_order_token,
1138 tvb, offset, 14,
1139 ENC_ASCII);
1140 offset += 14;
1141 break;
1143 case 'I': /* Cancel Reject */
1144 ouch_tree_add_timestamp(pinfo, ouch_tree,
1145 hf_ouch_timestamp,
1146 tvb, offset);
1147 offset += 8;
1149 proto_tree_add_item(ouch_tree,
1150 hf_ouch_order_token,
1151 tvb, offset, 14,
1152 ENC_ASCII);
1153 offset += 14;
1154 break;
1156 case 'T': /* Order Priority Update (4.2 onwards) */
1157 ouch_tree_add_timestamp(pinfo, ouch_tree,
1158 hf_ouch_timestamp,
1159 tvb, offset);
1160 offset += 8;
1162 proto_tree_add_item(ouch_tree,
1163 hf_ouch_order_token,
1164 tvb, offset, 14,
1165 ENC_ASCII);
1166 offset += 14;
1168 proto_tree_add_item(ouch_tree,
1169 hf_ouch_price,
1170 tvb, offset, 4,
1171 ENC_BIG_ENDIAN);
1172 offset += 4;
1174 proto_tree_add_item(ouch_tree,
1175 hf_ouch_display,
1176 tvb, offset, 1,
1177 ENC_ASCII|ENC_NA);
1178 offset += 1;
1180 proto_tree_add_item(ouch_tree,
1181 hf_ouch_order_reference_number,
1182 tvb, offset, 8,
1183 ENC_BIG_ENDIAN);
1184 offset += 8;
1185 break;
1187 case 'm': /* Order Modified (4.2 onwards) */
1188 ouch_tree_add_timestamp(pinfo, ouch_tree,
1189 hf_ouch_timestamp,
1190 tvb, offset);
1191 offset += 8;
1193 proto_tree_add_item(ouch_tree,
1194 hf_ouch_order_token,
1195 tvb, offset, 14,
1196 ENC_ASCII);
1197 offset += 14;
1199 proto_tree_add_item(ouch_tree,
1200 hf_ouch_buy_sell_indicator,
1201 tvb, offset, 1,
1202 ENC_BIG_ENDIAN);
1203 offset += 1;
1205 proto_tree_add_item(ouch_tree,
1206 hf_ouch_shares,
1207 tvb, offset, 4,
1208 ENC_BIG_ENDIAN);
1209 offset += 4;
1210 break;
1212 default:
1213 /* Unknown */
1214 proto_tree_add_item(tree,
1215 hf_ouch_message,
1216 tvb, offset, -1, ENC_NA);
1217 offset += reported_len - 1;
1218 break;
1222 return offset;
1225 /** Returns a guess if a packet is OUCH or not
1227 * Since SOUP doesn't have a sub-protocol type flag, we have to use a
1228 * heuristic decision to determine if the contained protocol is OUCH
1229 * or ITCH (or something else entirely). We look at the message type
1230 * code, and since we know that we're being called from SOUP, we can
1231 * check the passed-in length too: if the type code and the length
1232 * match, we guess at OUCH. */
1233 static bool
1234 dissect_ouch_heur(
1235 tvbuff_t *tvb,
1236 packet_info *pinfo,
1237 proto_tree *tree,
1238 void *data _U_)
1240 uint8_t msg_type = tvb_get_uint8(tvb, 0);
1241 unsigned msg_len = tvb_reported_length(tvb);
1243 switch (msg_type) {
1244 case 'O': /* Enter order (with or without optional customer type) */
1245 if (msg_len != 48 && msg_len != 49) {
1246 return false;
1248 break;
1250 case 'U': /* Replace order or Replaced (4.0, 4.1) or Replaced (4.2) */
1251 if (msg_len != 47 && msg_len != 79 && msg_len != 80) {
1252 return false;
1254 break;
1256 case 'X': /* Cancel order */
1257 if (msg_len != 19) {
1258 return false;
1260 break;
1262 case 'M': /* Modify Order or Order Modified (added 4.2) */
1263 if (msg_len != 20 && msg_len != 28) {
1264 return false;
1266 break;
1268 case 'S': /* System event */
1269 if (msg_len != 10) {
1270 return false;
1272 break;
1274 case 'A': /* Accepted */
1275 if (msg_len != 65 && msg_len != 66) {
1276 return false;
1278 break;
1280 case 'C': /* Canceled */
1281 if (msg_len != 28) {
1282 return false;
1284 break;
1286 case 'D': /* AIQ Canceled */
1287 if (msg_len != 37) {
1288 return false;
1290 break;
1291 case 'E': /* Executed */
1292 if (msg_len != 40) {
1293 return false;
1295 break;
1297 case 'F': /* Trade Correction */
1298 if (msg_len != 41) {
1299 return false;
1301 break;
1303 case 'G': /* Executed with Reference Price */
1304 if (msg_len != 45) {
1305 return false;
1307 break;
1309 case 'B': /* Broken Trade */
1310 if (msg_len != 32) {
1311 return false;
1313 break;
1315 case 'K': /* Correction */
1316 if (msg_len != 36) {
1317 return false;
1319 break;
1321 case 'J': /* Rejected */
1322 if (msg_len != 24) {
1323 return false;
1325 break;
1327 case 'P': /* Cancel Pending */
1328 if (msg_len != 23) {
1329 return false;
1331 break;
1333 case 'I': /* Cancel Reject */
1334 if (msg_len != 23) {
1335 return false;
1337 break;
1339 case 'T': /* Order Priority Update */
1340 if (msg_len != 36) {
1341 return false;
1343 break;
1345 default:
1346 /* Not a known OUCH message code */
1347 return false;
1350 /* Perform dissection of this (initial) packet */
1351 dissect_ouch(tvb, pinfo, tree, NULL);
1353 return true;
1357 void
1358 proto_register_ouch(void)
1360 /* Setup list of header fields See Section 1.6.1 for details*/
1361 static hf_register_info hf[] = {
1363 { &hf_ouch_bbo_weight_indicator,
1364 { "BBO Weight Indicator", "ouch.bbo_weight_indicator",
1365 FT_CHAR, BASE_HEX, VALS(ouch_bbo_weight_indicator_val), 0x0,
1366 NULL, HFILL }},
1368 { &hf_ouch_broken_trade_reason,
1369 { "Broken Trade Reason", "ouch.broken_trade_reason",
1370 FT_CHAR, BASE_HEX, VALS(ouch_broken_trade_reason_val), 0x0,
1371 NULL, HFILL }},
1373 { &hf_ouch_buy_sell_indicator,
1374 { "Buy/Sell Indicator", "ouch.buy_sell_indicator",
1375 FT_CHAR, BASE_HEX, VALS(ouch_buy_sell_indicator_val), 0x0,
1376 NULL, HFILL }},
1378 { &hf_ouch_cancel_reason,
1379 { "Cancel Reason", "ouch.cancel_reason",
1380 FT_CHAR, BASE_HEX, VALS(ouch_cancel_reason_val), 0x0,
1381 NULL, HFILL }},
1383 { &hf_ouch_capacity,
1384 { "Capacity", "ouch.capacity",
1385 FT_CHAR, BASE_HEX, VALS(ouch_capacity_val), 0x0,
1386 NULL, HFILL }},
1388 { &hf_ouch_cross_type,
1389 { "Cross Type", "ouch.cross_type",
1390 FT_CHAR, BASE_HEX, VALS(ouch_cross_type_val), 0x0,
1391 NULL, HFILL }},
1393 { &hf_ouch_customer_type,
1394 { "Customer Type", "ouch.customer_type",
1395 FT_CHAR, BASE_HEX, VALS(ouch_customer_type_val), 0x0,
1396 NULL, HFILL }},
1398 { &hf_ouch_decrement_shares,
1399 { "Decrement Shares", "ouch.decrement_shares",
1400 FT_UINT32, BASE_DEC, NULL, 0x0,
1401 NULL, HFILL }},
1403 { &hf_ouch_display,
1404 { "Display", "ouch.display",
1405 FT_CHAR, BASE_HEX, VALS(ouch_display_val), 0x0,
1406 NULL, HFILL }},
1408 { &hf_ouch_event_code,
1409 { "Event Code", "ouch.event_code",
1410 FT_CHAR, BASE_HEX, VALS(ouch_event_code_val), 0x0,
1411 NULL, HFILL }},
1413 { &hf_ouch_executed_shares,
1414 { "Executed Shares", "ouch.executed_shares",
1415 FT_UINT32, BASE_DEC, NULL, 0x0,
1416 NULL, HFILL }},
1418 { &hf_ouch_execution_price,
1419 { "Execution Price", "ouch.execution_price",
1420 FT_UINT32, BASE_CUSTOM, CF_FUNC(format_price), 0x0,
1421 NULL, HFILL }},
1423 { &hf_ouch_existing_order_token,
1424 { "Existing Order Token", "ouch.existing_order_token",
1425 FT_STRING, BASE_NONE, NULL, 0x0,
1426 NULL, HFILL }},
1428 { &hf_ouch_firm,
1429 { "Firm", "ouch.firm",
1430 FT_STRING, BASE_NONE, NULL, 0x0,
1431 NULL, HFILL }},
1433 { &hf_ouch_iso_eligible,
1434 { "Intermarket Sweep Eligibility", "ouch.iso_eligible",
1435 FT_CHAR, BASE_HEX, VALS(ouch_iso_eligibility_val), 0x0,
1436 NULL, HFILL }},
1438 { &hf_ouch_liquidity_flag,
1439 { "Liquidity Flag", "ouch.liquidity_flag",
1440 FT_CHAR, BASE_HEX, VALS(ouch_liquidity_flag_val), 0x0,
1441 NULL, HFILL }},
1443 { &hf_ouch_match_number,
1444 { "Match Number", "ouch.match_number",
1445 FT_UINT64, BASE_DEC, NULL, 0x0,
1446 NULL, HFILL }},
1448 { &hf_ouch_message,
1449 { "Unknown Message", "ouch.unknown_message",
1450 FT_BYTES, BASE_NONE, NULL, 0x0,
1451 NULL, HFILL }},
1453 { &hf_ouch_min_quantity,
1454 { "Minimum Quantity", "ouch.min_quantity",
1455 FT_UINT32, BASE_DEC, NULL, 0x0,
1456 NULL, HFILL }},
1458 { &hf_ouch_new_execution_price,
1459 { "New Execution Price", "ouch.new_execution_price",
1460 FT_UINT32, BASE_CUSTOM, CF_FUNC(format_price), 0x0,
1461 NULL, HFILL }},
1463 { &hf_ouch_order_reference_number,
1464 { "Order Reference Number", "ouch.order_reference_number",
1465 FT_UINT64, BASE_DEC, NULL, 0x0,
1466 NULL, HFILL }},
1468 { &hf_ouch_order_state,
1469 { "Order State", "ouch.order_state",
1470 FT_CHAR, BASE_HEX, VALS(ouch_order_state_val), 0x0,
1471 NULL, HFILL }},
1473 { &hf_ouch_order_token,
1474 { "Order Token", "ouch.order_token",
1475 FT_STRING, BASE_NONE, NULL, 0x0,
1476 NULL, HFILL }},
1478 { &hf_ouch_packet_type,
1479 { "Packet Type", "ouch.packet_type",
1480 FT_CHAR, BASE_HEX, VALS(pkt_type_val), 0x0,
1481 NULL, HFILL }},
1483 { &hf_ouch_previous_order_token,
1484 { "Previous Order Token", "ouch.previous_order_token",
1485 FT_STRING, BASE_NONE, NULL, 0x0,
1486 NULL, HFILL }},
1488 { &hf_ouch_price,
1489 { "Price", "ouch.price",
1490 FT_UINT32, BASE_CUSTOM, CF_FUNC(format_price), 0x0,
1491 NULL, HFILL }},
1493 { &hf_ouch_price_correction_reason,
1494 { "Price Correction Reason", "ouch.price_correction_reason",
1495 FT_CHAR, BASE_HEX, VALS(ouch_price_correction_reason_val), 0x0,
1496 NULL, HFILL }},
1498 { &hf_ouch_quantity_prevented_from_trading,
1499 { "Quantity Prevented from Trading",
1500 "ouch.quantity_prevented_from_trading",
1501 FT_UINT32, BASE_DEC, NULL, 0x0,
1502 NULL, HFILL }},
1504 { &hf_ouch_reference_price,
1505 { "Reference Price", "ouch.reference_price",
1506 FT_UINT32, BASE_CUSTOM, CF_FUNC(format_price), 0x0,
1507 NULL, HFILL }},
1509 { &hf_ouch_reference_price_type,
1510 { "Reference Price Type", "ouch.reference_price_type",
1511 FT_UINT32, BASE_CUSTOM, CF_FUNC(format_reference_price_type), 0x0,
1512 NULL, HFILL }},
1514 { &hf_ouch_reject_reason,
1515 { "Reject Reason", "ouch.reject_reason",
1516 FT_CHAR, BASE_HEX, VALS(ouch_reject_reason_val), 0x0,
1517 NULL, HFILL }},
1519 { &hf_ouch_replacement_order_token,
1520 { "Replacement Order Token", "ouch.replacement_order_token",
1521 FT_STRING, BASE_NONE, NULL, 0x0,
1522 NULL, HFILL }},
1524 { &hf_ouch_shares,
1525 { "Shares", "ouch.shares",
1526 FT_UINT32, BASE_DEC, NULL, 0x0,
1527 NULL, HFILL }},
1529 { &hf_ouch_stock,
1530 { "Stock", "ouch.stock",
1531 FT_STRING, BASE_NONE, NULL, 0x0,
1532 NULL, HFILL }},
1534 { &hf_ouch_tif,
1535 { "Time In Force", "ouch.tif",
1536 FT_UINT32, BASE_CUSTOM, CF_FUNC(format_tif), 0x0,
1537 NULL, HFILL }},
1539 { &hf_ouch_timestamp,
1540 { "Timestamp", "ouch.timestamp",
1541 FT_STRING, BASE_NONE, NULL, 0x0,
1542 NULL, HFILL }},
1544 { &hf_ouch_trade_correction_reason,
1545 { "Trade Correction Reason", "ouch.trade_correction_reason",
1546 FT_CHAR, BASE_HEX, VALS(ouch_trade_correction_reason_val), 0x0,
1547 NULL, HFILL }}
1550 /* Setup protocol subtree array */
1551 static int *ett[] = {
1552 &ett_ouch
1555 /* Register the protocol name and description */
1556 proto_ouch = proto_register_protocol("OUCH", "OUCH", "ouch");
1558 /* Required function calls to register the header fields and
1559 * subtrees used */
1560 proto_register_field_array(proto_ouch, hf, array_length(hf));
1561 proto_register_subtree_array(ett, array_length(ett));
1563 /* Register the dissector */
1564 ouch_handle = register_dissector("ouch", dissect_ouch, proto_ouch);
1568 /* If this dissector uses sub-dissector registration add a
1569 * registration routine. This format is required because a script is
1570 * used to find these routines and create the code that calls these
1571 * routines. */
1572 void
1573 proto_reg_handoff_ouch(void)
1575 heur_dissector_add("soupbintcp", dissect_ouch_heur, "OUCH over SoupBinTCP", "ouch_soupbintcp", proto_ouch, HEURISTIC_ENABLE);
1576 dissector_add_uint_range_with_preference("tcp.port", "", ouch_handle);
1582 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1584 * Local variables:
1585 * c-basic-offset: 4
1586 * tab-width: 8
1587 * indent-tabs-mode: nil
1588 * End:
1590 * vi: set shiftwidth=4 tabstop=8 expandtab:
1591 * :indentSize=4:tabSize=8:noTabs=true: