blob: 3490d8b9e786c0f940a1cd211df18d60d23cd460 [file] [log] [blame]
Frédéric Lécaille6d889502017-11-15 14:50:19 +01001/* packet-happp.c
2 * Routines for HAProxy Peers Protocol (HAPPP) dissection
3 * Copyright 2016, Frédéric Lécaille <flecaille@haproxy.com>
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24#include <stdio.h>
Willy Tarreaua1bd1fa2019-03-29 17:26:33 +010025#include <inttypes.h>
Frédéric Lécaille6d889502017-11-15 14:50:19 +010026#include <inttypes.h>
27#include <arpa/inet.h>
28
29#include <config.h>
William Lallemand2be58f72020-04-25 22:03:29 +020030
Frédéric Lécaille6d889502017-11-15 14:50:19 +010031#include <epan/to_str.h>
32#include <epan/packet.h>
33#include <epan/prefs.h>
34#include <epan/conversation.h>
William Lallemand2be58f72020-04-25 22:03:29 +020035#include <epan/strutil.h>
36#include <epan/dissectors/packet-tcp.h>
37#include <epan/tvbuff.h>
38
39#include <ws_version.h>
40
41WS_DLL_PUBLIC_DEF const gchar plugin_version[] = "0.0.1";
42WS_DLL_PUBLIC_DEF const int plugin_want_major = WIRESHARK_VERSION_MAJOR;
43WS_DLL_PUBLIC_DEF const int plugin_want_minor = WIRESHARK_VERSION_MINOR;
44WS_DLL_PUBLIC void plugin_register(void);
45
Frédéric Lécaille6d889502017-11-15 14:50:19 +010046
47#define HAPPP_PROTOCOL "HAProxyS"
48#define HAPPP_MSG_MIN_LEN 2
49
50/* Status messages are the shortest ones (3 digits followed by a LF character) */
51#define STATUS_HANDSHAKE_SUCCEEDED "200"
52#define STATUS_TRY_AGAIN_LATER "300"
53#define STATUS_PROTOCOL_ERROR "501"
54#define STATUS_BAD_VERSION "502"
55#define STATUS_LOCAL_PEER_NAME_MISMATCH "503"
56#define STATUS_REMOTE_PEER_NAME_MISMATCH "504"
57
58#include <stdio.h>
59#include <ctype.h>
60#include <stdarg.h>
61
Frédéric Lécaille6d889502017-11-15 14:50:19 +010062
63#ifdef DEBUG
64static unsigned char dbg_buf[16 << 10];
65
66__attribute__((format (printf, 3, 4)))
67void hexdump(const unsigned char *buf, size_t buflen, const char *title_fmt, ...)
68{
69 size_t i;
70 va_list ap;
71 const unsigned char *p;
72 char str_buf[2 + 1 + 16 + 1 + 1];
73
74 va_start(ap, title_fmt);
75 vfprintf(stderr, title_fmt, ap);
76 va_end(ap);
77
78 p = buf;
79 str_buf[0] = str_buf[1] = ' ';
80 str_buf[2] = '|';
81
82 for (i = 0; i < buflen; i++) {
83 if (!(i & 0xf))
84 fprintf(stderr, "%08X: ", i);
85 fprintf(stderr, " %02x", *p);
86 if (isalnum(*p))
87 str_buf[(i & 0xf) + 3] = *p;
88 else
89 str_buf[(i & 0xf) + 3] = '.';
90 if ((i & 0xf) == 0xf || i == buflen -1) {
91 size_t k;
92
93 for (k = 0; k < (0x10 - (i & 0xf) - 1); k++)
94 fprintf(stderr, " ");
95 str_buf[(i & 0xf) + 4] = '|';
96 str_buf[(i & 0xf) + 5 ] = '\0';
97 fprintf(stderr, "%s\n", str_buf);
98 }
99 p++;
100 }
101}
102
103void hexdump_tvb(tvbuff_t *tvb, const gint offset, size_t len)
104{
105 len = len > sizeof dbg_buf ? sizeof dbg_buf : len;
106 if (tvb_memcpy(tvb, dbg_buf, offset, len)) {
107 hexdump(dbg_buf, len, "tvb buff (%zu bytes):\n", len);
108 } else
109 fprintf(stderr, "tvb buff COPY FAILED\n");
110}
111#endif
112
113/* HAPPP message classes */
114enum {
115 PEER_MSG_CLASS_CONTROL = 0,
116 PEER_MSG_CLASS_ERROR,
117 PEER_MSG_CLASS_STICKTABLE = 0x0a,
118 PEER_MSG_CLASS_RESERVED = 0xff,
119};
120
121enum {
122 CONTROL_CLASS_INDEX,
123 ERROR_CLASS_INDEX,
124 STICK_TABLE_CLASS_INDEX,
125 RESERVED_CLASS_INDEX,
126};
127
128/* Control messages */
129enum {
130 PEER_MSG_CTRL_RESYNCREQ = 0,
131 PEER_MSG_CTRL_RESYNCFINISHED,
132 PEER_MSG_CTRL_RESYNCPARTIAL,
133 PEER_MSG_CTRL_RESYNCCONFIRM,
134};
135
136/* Error messages */
137enum {
138 PEER_MSG_ERR_PROTOCOL = 0,
139 PEER_MSG_ERR_SIZELIMIT,
140};
141
142/* Stick table messages */
143enum {
144 PEER_MSG_STKT_UPDATE = 0x80,
145 PEER_MSG_STKT_INCUPDATE,
146 PEER_MSG_STKT_DEFINE,
147 PEER_MSG_STKT_SWITCH,
148 PEER_MSG_STKT_ACK,
149 PEER_MSG_STKT_UPDATE_TIMED,
150 PEER_MSG_STKT_INCUPDATE_TIMED,
151};
152
153/* This is the different key types of the stick tables.
154 * Same definitions as in HAProxy sources.
155 */
156enum {
157 SMP_T_ANY, /* any type */
158 SMP_T_BOOL, /* boolean */
159 SMP_T_SINT, /* signed 64bits integer type */
160 SMP_T_ADDR, /* ipv4 or ipv6, only used for input type compatibility */
161 SMP_T_IPV4, /* ipv4 type */
162 SMP_T_IPV6, /* ipv6 type */
163 SMP_T_STR, /* char string type */
164 SMP_T_BIN, /* buffer type */
165 SMP_T_METH, /* contain method */
166 SMP_TYPES /* number of types, must always be last */
167};
168
169/* The types of data we can store in a stick table.
Ilya Shipitsince7b00f2020-03-23 22:28:40 +0500170 * Same definitions as in HAProxy sources.
Frédéric Lécaille6d889502017-11-15 14:50:19 +0100171 */
172enum {
173 STKT_DT_SERVER_ID, /* the server ID to use with this stream if > 0 */
174 STKT_DT_GPT0, /* General Purpose Flag 0. */
175 STKT_DT_GPC0, /* General Purpose Counter 0 (unsigned 32-bit integer) */
176 STKT_DT_GPC0_RATE, /* General Purpose Counter 0's event rate */
177 STKT_DT_CONN_CNT, /* cumulated number of connections */
178 STKT_DT_CONN_RATE, /* incoming connection rate */
179 STKT_DT_CONN_CUR, /* concurrent number of connections */
180 STKT_DT_SESS_CNT, /* cumulated number of sessions (accepted connections) */
181 STKT_DT_SESS_RATE, /* accepted sessions rate */
182 STKT_DT_HTTP_REQ_CNT, /* cumulated number of incoming HTTP requests */
183 STKT_DT_HTTP_REQ_RATE, /* incoming HTTP request rate */
184 STKT_DT_HTTP_ERR_CNT, /* cumulated number of HTTP requests errors (4xx) */
185 STKT_DT_HTTP_ERR_RATE, /* HTTP request error rate */
186 STKT_DT_BYTES_IN_CNT, /* cumulated bytes count from client to servers */
187 STKT_DT_BYTES_IN_RATE, /* bytes rate from client to servers */
188 STKT_DT_BYTES_OUT_CNT, /* cumulated bytes count from servers to client */
189 STKT_DT_BYTES_OUT_RATE, /* bytes rate from servers to client */
190 STKT_STATIC_DATA_TYPES, /* number of types above */
191};
192
193/* The types of data in stick stored in stick tables.
194 * Same definitions as in HAProxy sources.
195 */
196enum {
197 STD_T_SINT = 0, /* signed int */
198 STD_T_UINT, /* unsigned int */
199 STD_T_ULL, /* unsigned long long */
200 STD_T_FRQP, /* freq_ctr_period structure made of three unsigned int */
201};
202
203/* Prototypes */
204void proto_reg_handoff_happp(void);
205void proto_register_happp(void);
206
207/* Initialize the protocol and registered fields */
208static int proto_happp = -1;
209static int hf_happp_fake = -1;
210static int hf_happp_version = -1;
211static int hf_happp_remotepeerid = -1;
212static int hf_happp_localpeerid = -1;
213static int hf_happp_processpid = -1;
214static int hf_happp_relativepid = -1;
215static int hf_happp_status = -1;
216static int hf_happp_msg = -1;
217static int hf_happp_msg_class = -1;
218static int hf_happp_msg_type = -1;
219static int hf_happp_msg_len = -1;
220static int hf_happp_stkt_def_id = -1;
221static int hf_happp_stkt_def_name_len = -1;
222static int hf_happp_stkt_def_name_value = -1;
223static int hf_happp_stkt_def_key_type = -1;
224static int hf_happp_stkt_def_key_len = -1;
225static int hf_happp_stkt_def_data_types = -1;
226static int hf_happp_stkt_updt_update_id = -1;
227static int hf_happp_stkt_updt_expire = -1;
228static int hf_happp_stkt_updt_key_len = -1;
229static int hf_happp_stkt_updt_key_ipv4_value = -1;
230static int hf_happp_stkt_updt_key_str_value = -1;
231static int hf_happp_stkt_updt_key_int_value = -1;
232static int hf_happp_stkt_updt_key_bytes_value = -1;
233static int hf_happp_stkt_updt_data_server_id = -1;
234static int hf_happp_stkt_updt_data_gpt0 = -1;
235static int hf_happp_stkt_updt_data_gpc0 = -1;
236static int hf_happp_stkt_updt_data_gpc0_rate_curr_tick = -1;
237static int hf_happp_stkt_updt_data_gpc0_rate_curr_ctr = -1;
238static int hf_happp_stkt_updt_data_gpc0_rate_prev_ctr = -1;
239static int hf_happp_stkt_updt_data_conn_cnt = -1;
240static int hf_happp_stkt_updt_data_conn_rate_curr_tick = -1;
241static int hf_happp_stkt_updt_data_conn_rate_curr_ctr = -1;
242static int hf_happp_stkt_updt_data_conn_rate_prev_ctr = -1;
243static int hf_happp_stkt_updt_data_conn_cur = -1;
244static int hf_happp_stkt_updt_data_sess_cnt = -1;
245static int hf_happp_stkt_updt_data_sess_rate_curr_tick = -1;
246static int hf_happp_stkt_updt_data_sess_rate_curr_ctr = -1;
247static int hf_happp_stkt_updt_data_sess_rate_prev_ctr = -1;
248static int hf_happp_stkt_updt_data_http_req_cnt = -1;
249static int hf_happp_stkt_updt_data_http_req_rate_curr_tick = -1;
250static int hf_happp_stkt_updt_data_http_req_rate_curr_ctr = -1;
251static int hf_happp_stkt_updt_data_http_req_rate_prev_ctr= -1;
252static int hf_happp_stkt_updt_data_http_err_cnt = -1;
253static int hf_happp_stkt_updt_data_http_err_rate_curr_tick = -1;
254static int hf_happp_stkt_updt_data_http_err_rate_curr_ctr = -1;
255static int hf_happp_stkt_updt_data_http_err_rate_prev_ctr = -1;
256static int hf_happp_stkt_updt_data_bytes_in_cnt = -1;
257static int hf_happp_stkt_updt_data_bytes_in_rate_curr_tick = -1;
258static int hf_happp_stkt_updt_data_bytes_in_rate_curr_ctr = -1;
259static int hf_happp_stkt_updt_data_bytes_in_rate_prev_ctr = -1;
260static int hf_happp_stkt_updt_data_bytes_out_cnt = -1;
261static int hf_happp_stkt_updt_data_bytes_out_rate_curr_tick = -1;
262static int hf_happp_stkt_updt_data_bytes_out_rate_curr_ctr = -1;
263static int hf_happp_stkt_updt_data_bytes_out_rate_prev_ctr = -1;
264static int hf_happp_stkt_updt_ack_table_id = -1;
265static int hf_happp_stkt_updt_ack_update_id = -1;
266
267struct happp_cv_data_t {
268 /* Same thing for the type of the the stick table keys */
269 uint64_t stkt_key_type;
270
271 /* Same thing for the length of the stick table keys.
272 * Note that this is true only for key types different of SMT_T_STR (strings)
273 * and SMT_T_SINT (signed ints).
274 */
275 uint64_t stkt_key_len;
276
277 /* Same thing for the types of the stick table data */
278 uint64_t stkt_data_types;
279 void *data;
280};
281
282struct hf_stkt_data_type {
283 const char *name;
284 unsigned int type;
285 int *hf_ids[3];
286 size_t hf_ids_len;
287};
288
289struct hf_stkt_data_type hf_stkt_data_types[] = {
290 [STKT_DT_SERVER_ID] = {
291 .name = "server_id",
292 .type = STD_T_SINT,
293 .hf_ids = {
294 &hf_happp_stkt_updt_data_server_id,
295 },
296 .hf_ids_len = 1,
297 },
298 [STKT_DT_GPT0] = {
299 .name = "gpt0",
300 .type = STD_T_UINT,
301 .hf_ids = {
302 &hf_happp_stkt_updt_data_gpt0,
303 },
304 .hf_ids_len = 1,
305 },
306 [STKT_DT_GPC0] = {
307 .name = "gpc0",
308 .type = STD_T_UINT,
309 .hf_ids = {
310 &hf_happp_stkt_updt_data_gpc0,
311 },
312 .hf_ids_len = 1,
313 },
314 [STKT_DT_GPC0_RATE] = {
315 .name = "gpc0_rate",
316 .type = STD_T_FRQP,
317 .hf_ids = {
318 &hf_happp_stkt_updt_data_gpc0_rate_curr_tick,
319 &hf_happp_stkt_updt_data_gpc0_rate_curr_ctr,
320 &hf_happp_stkt_updt_data_gpc0_rate_prev_ctr,
321 },
322 .hf_ids_len = 3,
323 },
324 [STKT_DT_CONN_CNT] = {
325 .name = "conn_cnt",
326 .type = STD_T_UINT,
327 .hf_ids = {
328 &hf_happp_stkt_updt_data_conn_cnt,
329 },
330 .hf_ids_len = 1,
331 },
332 [STKT_DT_CONN_RATE] = {
333 .name = "conn_rate",
334 .type = STD_T_FRQP,
335 .hf_ids = {
336 &hf_happp_stkt_updt_data_conn_rate_curr_tick,
337 &hf_happp_stkt_updt_data_conn_rate_curr_ctr,
338 &hf_happp_stkt_updt_data_conn_rate_prev_ctr,
339 },
340 .hf_ids_len = 3,
341 },
342 [STKT_DT_CONN_CUR] = {
343 .name = "conn_cur",
344 .type = STD_T_UINT,
345 .hf_ids = {
346 &hf_happp_stkt_updt_data_conn_cur,
347 },
348 .hf_ids_len = 1,
349 },
350 [STKT_DT_SESS_CNT] = {
351 .name = "sess_cnt",
352 .type = STD_T_UINT,
353 .hf_ids = {
354 &hf_happp_stkt_updt_data_sess_cnt,
355 },
356 .hf_ids_len = 1,
357 },
358 [STKT_DT_SESS_RATE] = {
359 .name = "sess_rate",
360 .type = STD_T_FRQP,
361 .hf_ids = {
362 &hf_happp_stkt_updt_data_sess_rate_curr_tick,
363 &hf_happp_stkt_updt_data_sess_rate_curr_ctr,
364 &hf_happp_stkt_updt_data_sess_rate_prev_ctr,
365 },
366 .hf_ids_len = 3,
367 },
368 [STKT_DT_HTTP_REQ_CNT] = {
369 .name = "http_req_cnt",
370 .type = STD_T_UINT,
371 .hf_ids = {
372 &hf_happp_stkt_updt_data_http_req_cnt,
373 },
374 .hf_ids_len = 1,
375 },
376 [STKT_DT_HTTP_REQ_RATE] = {
377 .name = "http_req_rate",
378 .type = STD_T_FRQP,
379 .hf_ids = {
380 &hf_happp_stkt_updt_data_http_req_rate_curr_tick,
381 &hf_happp_stkt_updt_data_http_req_rate_curr_ctr,
382 &hf_happp_stkt_updt_data_http_req_rate_prev_ctr,
383 },
384 .hf_ids_len = 3,
385 },
386 [STKT_DT_HTTP_ERR_CNT] = {
387 .name = "http_err_cnt",
388 .type = STD_T_UINT,
389 .hf_ids = {
390 &hf_happp_stkt_updt_data_http_err_cnt,
391 },
392 .hf_ids_len = 1,
393 },
394 [STKT_DT_HTTP_ERR_RATE] = {
395 .name = "http_err_rate",
396 .type = STD_T_FRQP,
397 .hf_ids = {
398 &hf_happp_stkt_updt_data_http_err_rate_curr_tick,
399 &hf_happp_stkt_updt_data_http_err_rate_curr_ctr,
400 &hf_happp_stkt_updt_data_http_err_rate_prev_ctr,
401 },
402 .hf_ids_len = 3,
403 },
404 [STKT_DT_BYTES_IN_CNT] = {
405 .name = "bytes_in_cnt",
406 .type = STD_T_ULL,
407 .hf_ids = {
408 &hf_happp_stkt_updt_data_bytes_in_cnt,
409 },
410 .hf_ids_len = 1,
411 },
412 [STKT_DT_BYTES_IN_RATE] = {
413 .name = "bytes_in_rate",
414 .type = STD_T_FRQP,
415 .hf_ids = {
416 &hf_happp_stkt_updt_data_bytes_in_rate_curr_tick,
417 &hf_happp_stkt_updt_data_bytes_in_rate_curr_ctr,
418 &hf_happp_stkt_updt_data_bytes_in_rate_prev_ctr,
419 },
420 .hf_ids_len = 3,
421 },
422 [STKT_DT_BYTES_OUT_CNT] = {
423 .name = "bytes_out_cnt",
424 .type = STD_T_ULL,
425 .hf_ids = {
426 &hf_happp_stkt_updt_data_bytes_out_cnt,
427 },
428 .hf_ids_len = 1,
429 },
430 [STKT_DT_BYTES_OUT_RATE] = {
431 .name = "bytes_out_rate",
432 .type = STD_T_FRQP,
433 .hf_ids = {
434 &hf_happp_stkt_updt_data_bytes_out_rate_curr_tick,
435 &hf_happp_stkt_updt_data_bytes_out_rate_curr_ctr,
436 &hf_happp_stkt_updt_data_bytes_out_rate_prev_ctr,
437 },
438 .hf_ids_len = 3,
439 },
440};
441
442
443/* Initialize the subtree pointers */
444static gint ett_happp = -1;
445static gint ett_happp_msg = -1;
446
447static dissector_handle_t happp_tcp_handle;
448
449static const char *control_msg_type_str_from_byte(guint8 c);
450static const char *error_msg_type_str_from_byte(guint8 c);
451static const char *stkt_msg_type_str_from_byte(guint8 c);
452
453struct class_def_t {
454 const char *class_str;
455 const char *col_info_str;
456 const char *(*msg_type_str_func)(guint8 c);
457 unsigned int count;
458};
459
460static struct class_def_t class_def_tab[] = {
461 [CONTROL_CLASS_INDEX] = {
462 .class_str = "Control Class Message",
463 .col_info_str = "Ctl",
464 .msg_type_str_func = control_msg_type_str_from_byte,
465 },
466 [ERROR_CLASS_INDEX] = {
467 .class_str = "Error Class Message",
468 .col_info_str = "Err",
469 .msg_type_str_func = error_msg_type_str_from_byte,
470 },
471 [STICK_TABLE_CLASS_INDEX] = {
472 .class_str = "Stick Table Class Message",
473 .col_info_str = "Stkt",
474 .msg_type_str_func = stkt_msg_type_str_from_byte,
475 },
476 [RESERVED_CLASS_INDEX] = {
477 .class_str = "Reserved Class Message",
478 .col_info_str = "Res",
479 }
480};
481
482static int control_class_index_from_byte(guint8 c)
483{
484 switch (c) {
485 case PEER_MSG_CLASS_CONTROL:
486 return CONTROL_CLASS_INDEX;
487 case PEER_MSG_CLASS_ERROR:
488 return ERROR_CLASS_INDEX;
489 case PEER_MSG_CLASS_STICKTABLE:
490 return STICK_TABLE_CLASS_INDEX;
491 case PEER_MSG_CLASS_RESERVED:
492 return RESERVED_CLASS_INDEX;
493 default:
494 return -1;
495 };
496}
497
498static const char *class_str_from_byte(guint8 c)
499{
500 int class_idx;
501
502 class_idx = control_class_index_from_byte(c);
503 if (class_idx == -1)
504 return "N/A";
505
506 return class_def_tab[class_idx].class_str;
507}
508
509static const char *control_msg_type_str_from_byte(guint8 c)
510{
511 switch (c) {
512 case PEER_MSG_CTRL_RESYNCREQ:
513 return "resync. request";
514 case PEER_MSG_CTRL_RESYNCFINISHED:
515 return "resync. finished";
516 case PEER_MSG_CTRL_RESYNCPARTIAL:
517 return "resync. partial";
518 case PEER_MSG_CTRL_RESYNCCONFIRM:
519 return "resync. confirm";
520 default:
521 return "Unknown";
522 }
523}
524
525static const char *stkt_msg_type_str_from_byte(guint8 c)
526{
527 switch (c) {
528 case PEER_MSG_STKT_UPDATE:
529 return "update";
530 case PEER_MSG_STKT_INCUPDATE:
531 return "inc. update";
532 case PEER_MSG_STKT_DEFINE:
533 return "definition";
534 case PEER_MSG_STKT_SWITCH:
535 return "switch";
536 case PEER_MSG_STKT_ACK:
537 return "ack";
538 case PEER_MSG_STKT_UPDATE_TIMED:
539 return "update (with expiration)";
540 case PEER_MSG_STKT_INCUPDATE_TIMED:
541 return "inc. update (with expiration)";
542 default:
543 return "Unknown";
544 }
545}
546
547static const char *error_msg_type_str_from_byte(guint8 c)
548{
549 switch (c) {
550 case PEER_MSG_ERR_PROTOCOL:
551 return "protocol error";
552 case PEER_MSG_ERR_SIZELIMIT:
553 return "limit size error";
554 default:
555 return "Unknown";
556 }
557}
558
559#define MAX_ENC_LEN 10
560static uint64_t intdecode(unsigned char **str, size_t len) {
561 int i = 0;
562 uint64_t ret;
563
564 if (len < 1 || len > MAX_ENC_LEN) {
565 *str = NULL;
566 return 0;
567 }
568
569 ret = *(*str)++;
570 len--;
571 if ((ret & 0xf0) != 0xf0 || !len)
572 return ret;
573
574 do {
575 /* As shifting value may be greater than 8 (size of **str in bits),
576 * uint64_t cast is required.
577 */
578 ret += (uint64_t)**str << (4 + 7 * i++);
579 } while (len-- && (*(*str)++ & 0x80) == 0x80);
580
581 return ret;
582}
583
584static int dissect_happp_handshake_pdu(tvbuff_t *tvb, packet_info *pinfo,
585 proto_tree *happp_tree)
586{
587 int line_len, token_len;
588 gint offset = 0, next_offset;
589 const guchar *line, *line_end, *next_token;
590 size_t protocol_strlen;
591
592 line_len = tvb_find_line_end(tvb, offset, -1, &next_offset, TRUE);
593 /* XXX TO DO */
594 if (line_len == -1)
595 return -1;
596
597 protocol_strlen = strlen(HAPPP_PROTOCOL);
598
599 line = tvb_get_ptr(tvb, offset, line_len);
600 line_end = line + (next_offset - offset);
601 /* The line must contain at least HAPPP_PROTOCOL string followed by a space,
602 * then version string (at least one character) and a '\n' character.
603 */
604 if (line_len >= (int)protocol_strlen + 3 &&
605 !tvb_strncaseeql(tvb, 0, HAPPP_PROTOCOL, protocol_strlen)) {
606 /* This is an Hello message */
607 col_set_str(pinfo->cinfo, COL_INFO, "Hello message");
608
609 token_len = get_token_len(line + protocol_strlen + 1, line_end, &next_token);
610 proto_tree_add_item(happp_tree, hf_happp_version, tvb,
611 offset + protocol_strlen + 1, token_len,
612 ENC_ASCII | ENC_NA);
613
614 offset = next_offset;
615 line_len = tvb_find_line_end(tvb, offset, -1, &next_offset, TRUE);
616 /* XXX TO DO */
617 if (line_len == -1)
618 return -1;
619
620 line = tvb_get_ptr(tvb, offset, line_len);
621 line_end = line + (next_offset - offset);
622 /* Get next token: remotepeerid */
623 token_len = get_token_len(line, line_end, &next_token);
624 if (!token_len)
625 return -1;
626
627 proto_tree_add_item(happp_tree, hf_happp_remotepeerid, tvb, offset,
628 token_len, ENC_ASCII | ENC_NA);
629
630 /* Retrieve next line */
631 offset = next_offset;
632 line_len = tvb_find_line_end(tvb, offset, -1, &next_offset, TRUE);
633 /* XXX TO DO */
634 if (line_len == -1)
635 return -1;
636
637 line = tvb_get_ptr(tvb, offset, line_len);
638 line_end = line + (next_offset - offset);
639 /* Get next token: localpeerid */
640 token_len = get_token_len(line, line_end, &next_token);
641 if (!token_len)
642 return -1;
643
644 proto_tree_add_item(happp_tree, hf_happp_localpeerid, tvb, offset,
645 token_len, ENC_ASCII | ENC_NA);
646 offset += next_token - line;
647 line = next_token;
648
649 /* Get next token: processpid */
650 token_len = get_token_len(line, line_end, &next_token);
651 if (!token_len)
652 return -1;
653
654 proto_tree_add_item(happp_tree, hf_happp_processpid, tvb, offset,
655 token_len, ENC_ASCII | ENC_NA);
656 offset += next_token - line;
657 line = next_token;
658
659 /* Get next token: relativepid */
660 token_len = get_token_len(line, line_end, &next_token);
661 if (!token_len)
662 return -1;
663
664 proto_tree_add_item(happp_tree, hf_happp_relativepid, tvb, offset,
665 token_len, ENC_ASCII | ENC_NA);
666 offset += next_token - line;
667 line = next_token;
668
669 }
670 else if (line_len == 3) {
671 col_set_str(pinfo->cinfo, COL_INFO, "Status message");
672 token_len = get_token_len(line, line_end, &next_token);
673 if (!token_len)
674 return -1;
675
676 proto_tree_add_item(happp_tree, hf_happp_status, tvb, offset,
677 token_len, ENC_ASCII | ENC_NA);
678 }
679
680 return tvb_captured_length(tvb);
681}
682
683/* Reset to zero all statistics counters of class_def_array */
684static void init_class_def_tab(struct class_def_t *class_def_array, size_t size)
685{
686 size_t i;
687
688 for (i = 0; i < size; i++)
689 class_def_array[i].count = 0;
690}
691
692/* Add statistics counting information about HAPPP message classes to
693 * info column (numbers of messages found in an HAPPP PDU by class).
694 */
695static inline void col_info_append_class(packet_info *pinfo, int class_index,
696 int *first_class)
697{
698 if (!class_def_tab[class_index].count)
699 return;
700
701 col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s=%u",
702 *first_class ? "" : " ",
703 class_def_tab[class_index].col_info_str,
704 class_def_tab[class_index].count);
705 class_def_tab[class_index].count = 0;
706 *first_class = 0;
707}
708
709
710static int intdecode_from_tvbuff(tvbuff_t *tvb, uint64_t *dec_val,
711 guint *offset, guint total)
712{
713 unsigned char *p, enc_buf[MAX_ENC_LEN];
714 size_t max_enc_buf_len, left;
715
716 left = total - *offset;
717 max_enc_buf_len = left < sizeof enc_buf ? left : sizeof enc_buf;
718 if (!tvb_memcpy(tvb, enc_buf, *offset, max_enc_buf_len))
719 return -1;
720
721 p = enc_buf;
722 *dec_val = intdecode(&p, max_enc_buf_len);
723 if (!p)
724 return -1;
725
726 *offset += p - enc_buf;
727
728 return 0;
729}
730
731static int add_enc_field_to_happp_tree(int field_id, proto_tree *tree, tvbuff_t *tvb,
732 guint *offset, guint total, uint64_t *val)
733{
734 uint64_t dec_val;
735 size_t dec_val_len;
736 guint saved_offset;
737
738 saved_offset = *offset;
739 if (intdecode_from_tvbuff(tvb, &dec_val, offset, total) < 0)
740 return -1;
741
742 dec_val_len = *offset - saved_offset;
743 proto_tree_add_uint64_format_value(tree, field_id, tvb, saved_offset,
744 dec_val_len, dec_val, "%" PRIu64, dec_val);
745
746 if (val)
747 *val = dec_val;
748
749 return 0;
750}
751
752static int add_int_field_to_happp_tree(int field_id,
753 tvbuff_t *tvb, proto_tree *tree,
754 guint *offset, guint total _U_)
755{
756 uint32_t val;
757
758 if (!tvb_memcpy(tvb, &val, *offset, sizeof val))
759 return -1;
760
761 val = ntohl(val);
762 proto_tree_add_int_format_value(tree, field_id, tvb, *offset,
763 sizeof val, val, "%" PRId32, val);
764 *offset += sizeof val;
765
766 return 0;
767}
768
769static void dissect_happp_stkt_define_msg(tvbuff_t *tvb, packet_info *pinfo _U_,
770 proto_tree *tree, guint offset, guint total)
771{
772 uint64_t dec_val;
773 uint64_t stkt_key_type;
774 uint64_t stkt_key_len;
775 uint64_t stkt_data_types;
776 struct happp_cv_data_t *happp_cv_data;
777 conversation_t *cv;
778
779 if (add_enc_field_to_happp_tree(hf_happp_stkt_def_id, tree,
780 tvb, &offset, total, NULL) < 0 ||
781 add_enc_field_to_happp_tree(hf_happp_stkt_def_name_len, tree,
782 tvb, &offset, total, &dec_val) < 0)
783 return;
784
785 /* Add the stick table name to HAPPP proto tree */
786 proto_tree_add_item(tree, hf_happp_stkt_def_name_value, tvb, offset, dec_val,
787 ENC_ASCII | ENC_NA);
788 offset += dec_val;
789
790 if (add_enc_field_to_happp_tree(hf_happp_stkt_def_key_type, tree,
791 tvb, &offset, total, &stkt_key_type) < 0 ||
792 add_enc_field_to_happp_tree(hf_happp_stkt_def_key_len, tree,
793 tvb, &offset, total, &stkt_key_len) < 0 ||
794 add_enc_field_to_happp_tree(hf_happp_stkt_def_data_types, tree,
795 tvb, &offset, total, &stkt_data_types) < 0)
796 return;
797
798 cv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
799 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
800 if (!cv)
801 return;
802
803 /*
Joseph Herlantbd0f83f2018-11-09 19:00:24 -0800804 * According to the documentation, it is not our responsibility
Frédéric Lécaille6d889502017-11-15 14:50:19 +0100805 * to free this allocated memory.
806 */
807 happp_cv_data = (struct happp_cv_data_t *)wmem_alloc(wmem_file_scope(),
808 sizeof *happp_cv_data);
809 if (!happp_cv_data)
810 return;
811
812 happp_cv_data->stkt_key_type = stkt_key_type;
813 happp_cv_data->stkt_key_len = stkt_key_len;
814 happp_cv_data->stkt_data_types = stkt_data_types;
815
816 conversation_add_proto_data(cv, proto_happp, happp_cv_data);
817}
818
819static void dissect_happp_stkt_update_msg(tvbuff_t *tvb, packet_info *pinfo _U_,
820 proto_tree *tree, guint offset, guint total,
821 unsigned char msg_type_byte)
822{
823 unsigned int data_type;
824 uint64_t *stkt_key_type;
825 uint64_t *stkt_key_len;
826 struct happp_cv_data_t *happp_cv_data;
827 int has_update_id, has_exp;
828 conversation_t *cv;
829
830 cv = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
831 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
832 if (!cv)
833 return;
834
835 happp_cv_data = (struct happp_cv_data_t *)conversation_get_proto_data(cv, proto_happp);
836 if (!happp_cv_data)
837 return;
838
839 has_update_id = msg_type_byte == PEER_MSG_STKT_UPDATE ||
840 msg_type_byte == PEER_MSG_STKT_UPDATE_TIMED;
841 has_exp = msg_type_byte == PEER_MSG_STKT_UPDATE_TIMED ||
842 msg_type_byte == PEER_MSG_STKT_INCUPDATE_TIMED;
843 /* Add the stick table update ID to HAPPP tree */
844 if (has_update_id &&
845 add_int_field_to_happp_tree(hf_happp_stkt_updt_update_id, tvb, tree,
846 &offset, total) < 0)
847 return;
848
849 if (has_exp &&
850 add_int_field_to_happp_tree(hf_happp_stkt_updt_expire, tvb, tree,
851 &offset, total) < 0)
852 return;
853
854
855 stkt_key_type = &happp_cv_data->stkt_key_type;
856 stkt_key_len = &happp_cv_data->stkt_key_len;
857
858 switch(*stkt_key_type) {
859 case SMP_T_STR:
860 if (add_enc_field_to_happp_tree(hf_happp_stkt_updt_key_len, tree, tvb,
861 &offset, total, stkt_key_len) < 0)
862 return;
863
864 proto_tree_add_item(tree, hf_happp_stkt_updt_key_str_value, tvb,
865 offset, *stkt_key_len, ENC_ASCII | ENC_NA);
866 offset += *stkt_key_len;
867 break;
868 case SMP_T_SINT:
869 if (add_int_field_to_happp_tree(hf_happp_stkt_updt_key_int_value, tvb, tree,
870 &offset, total) < 0)
871 return;
872
873 break;
874 case SMP_T_IPV4:
875 proto_tree_add_ipv4(tree, hf_happp_stkt_updt_key_ipv4_value,
876 tvb, offset, 4, tvb_get_ipv4(tvb, offset));
877 offset += 4;
878 break;
879 default:
880 proto_tree_add_item(tree, hf_happp_stkt_updt_key_bytes_value,
881 tvb, offset, *stkt_key_len, ENC_NA);
882 offset += *stkt_key_len;
883 break;
884 }
885
886 /* Data dissection */
887 for (data_type = 0;
888 data_type < sizeof hf_stkt_data_types / sizeof *hf_stkt_data_types;
889 data_type++) {
890 struct hf_stkt_data_type *hf_stkt_dtype;
891 size_t i;
892
893 if (!(happp_cv_data->stkt_data_types & (1 << data_type)))
894 continue;
895
896 hf_stkt_dtype = &hf_stkt_data_types[data_type];
897
898 for (i = 0; i < hf_stkt_dtype->hf_ids_len; i++)
899 if (add_enc_field_to_happp_tree(*hf_stkt_dtype->hf_ids[i], tree, tvb,
900 &offset, total, NULL) < 0)
901 return;
902 }
903}
904
905static void dissect_happp_stkt_ack_msg(tvbuff_t *tvb, packet_info *pinfo _U_,
906 proto_tree *tree, guint offset, guint total)
907{
908 if (add_enc_field_to_happp_tree(hf_happp_stkt_updt_ack_table_id, tree, tvb,
909 &offset, total, NULL) < 0)
910 return;
911
912 if (add_int_field_to_happp_tree(hf_happp_stkt_updt_ack_update_id, tvb, tree,
913 &offset, total) < 0)
914 return;
915}
916
917static void dissect_happp_stk_msg(tvbuff_t *tvb, packet_info *pinfo _U_,
918 proto_tree *tree, guint8 msg_type_byte,
919 guint offset, guint total)
920{
921 switch (msg_type_byte) {
922 case PEER_MSG_STKT_DEFINE:
923 dissect_happp_stkt_define_msg(tvb, pinfo, tree, offset, total);
924 break;
925 case PEER_MSG_STKT_UPDATE:
926 case PEER_MSG_STKT_INCUPDATE:
927 case PEER_MSG_STKT_UPDATE_TIMED:
928 case PEER_MSG_STKT_INCUPDATE_TIMED:
929 dissect_happp_stkt_update_msg(tvb, pinfo, tree, offset, total, msg_type_byte);
930 break;
931 case PEER_MSG_STKT_ACK:
932 dissect_happp_stkt_ack_msg(tvb, pinfo, tree, offset, total);
933 break;
934 };
935
936}
937
938static void
939dissect_happp_msg(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
940 guint8 msg_class_byte, guint8 msg_type_byte,
941 guint *offset, guint total)
942{
943 unsigned char *p, enc_buf[MAX_ENC_LEN];
944 uint64_t dec_msg_len;
945 size_t max_enc_buf_len, left, dec_val_len;
946
947 left = total - *offset;
948 max_enc_buf_len = left < sizeof enc_buf ? left : sizeof enc_buf;
949 if (!tvb_memcpy(tvb, enc_buf, *offset, max_enc_buf_len))
950 return;
951
952 p = enc_buf;
953 dec_msg_len = intdecode(&p, max_enc_buf_len);
954 if (!p)
955 return;
956
957 dec_val_len = p - enc_buf;
958 proto_tree_add_uint64_format_value(tree, hf_happp_msg_len,
959 tvb, *offset, dec_val_len, dec_msg_len,
960 "%" PRIu64, dec_msg_len);
961 *offset += dec_val_len;
962
963 switch (msg_class_byte) {
964 case PEER_MSG_CLASS_STICKTABLE:
965 dissect_happp_stk_msg(tvb, pinfo, tree, msg_type_byte, *offset, total);
966 break;
967 }
968
969 *offset += dec_msg_len;
970}
971
972/* Code to actually dissect the packets */
973static int
974dissect_happp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
975{
976 /* Set up structures needed to add the protocol subtree and manage it */
977 proto_item *item;
978 proto_tree *happp_tree;
979 /* Other misc. local variables. */
980 guint total, offset;
981 int first_message, first_class, curr_class, prev_class;
982 guint8 first_byte;
983 size_t sizeof_class_def_tab;
984
985 offset = 0;
986 first_message = first_class = 1;
987 total = tvb_reported_length(tvb);
988
989 /* create display subtree for the protocol */
990 item = proto_tree_add_item(tree, proto_happp, tvb, offset, -1, ENC_NA);
991 happp_tree = proto_item_add_subtree(item, ett_happp);
992
993 /* Set the protocol column value */
994 col_set_str(pinfo->cinfo, COL_PROTOCOL, "happp");
995
996 first_byte = (gchar)tvb_get_guint8(tvb, offset);
997 if (first_byte != PEER_MSG_CLASS_CONTROL &&
998 first_byte != PEER_MSG_CLASS_ERROR &&
999 first_byte != PEER_MSG_CLASS_STICKTABLE &&
1000 first_byte != PEER_MSG_CLASS_RESERVED)
1001 return dissect_happp_handshake_pdu(tvb, pinfo, happp_tree);
1002
1003 /* Reset class_def_tab message class counters */
1004 sizeof_class_def_tab = sizeof class_def_tab / sizeof *class_def_tab;
1005 init_class_def_tab(class_def_tab, sizeof_class_def_tab);
1006
1007 prev_class = curr_class = -1;
1008 col_set_str(pinfo->cinfo, COL_INFO, "[");
1009 while (offset < total) {
1010 guint8 msg_class_byte, msg_type_byte;
1011 const char *(*msg_type_str_func)(guint8 c);
1012 struct class_def_t *class_def;
1013
1014 if (first_message) {
1015 msg_class_byte = first_byte;
1016 }
1017 else {
1018 msg_class_byte = tvb_get_guint8(tvb, offset);
1019 }
1020 curr_class = control_class_index_from_byte(msg_class_byte);
1021 if (curr_class == -1)
1022 return -1;
1023
1024 if (first_message) {
1025 prev_class = curr_class;
1026 first_message = 0;
1027 }
1028
1029 class_def = &class_def_tab[curr_class];
1030 class_def->count++;
1031 msg_type_str_func = class_def->msg_type_str_func;
1032
1033 /* Insert a line separator */
1034 proto_tree_add_item(happp_tree, hf_happp_fake, tvb,
1035 offset, 0,
1036 ENC_ASCII | ENC_NA);
1037 proto_tree_add_uint_format_value(happp_tree, hf_happp_msg_class,
1038 tvb, offset++, 1, msg_class_byte,
1039 "%u (%s)", msg_class_byte,
1040 class_str_from_byte(msg_class_byte));
1041 msg_type_byte = tvb_get_guint8(tvb, offset);
1042
1043 /* First byte: message class */
1044 switch (msg_class_byte) {
1045 case PEER_MSG_CLASS_CONTROL:
1046 case PEER_MSG_CLASS_ERROR:
1047 case PEER_MSG_CLASS_STICKTABLE:
1048 /* Second byte: message type in the class */
1049 proto_tree_add_uint_format_value(happp_tree, hf_happp_msg_type,
1050 tvb, offset++, 1, msg_type_byte,
1051 "%u (%s)", msg_type_byte,
1052 msg_type_str_func(msg_type_byte));
1053 break;
1054 case PEER_MSG_CLASS_RESERVED:
1055 col_append_str(pinfo->cinfo, COL_INFO, "NON IMPLEMENTED");
1056 break;
1057 }
1058 if (msg_class_byte >= PEER_MSG_CLASS_STICKTABLE)
1059 dissect_happp_msg(tvb, pinfo, happp_tree,
1060 msg_class_byte, msg_type_byte, &offset, total);
1061
1062 /* Sequentially add counting information to info column about
1063 * number of messages found by class in an HAPPP PDU.
1064 * For instance if an HAPPP PDU contains this sequence of messages:
1065 * 1 Control message - 2 Stick Table messages - 3 Control messages
1066 * column information displays: [Ctl=1 Stkt=2 Ctl=3].
1067 */
1068 if (curr_class != prev_class) {
1069 col_info_append_class(pinfo, prev_class, &first_class);
1070 col_info_append_class(pinfo, curr_class, &first_class);
1071 prev_class = curr_class;
1072 }
1073 else if (offset >= total) {
1074 /* Last message */
1075 col_info_append_class(pinfo, curr_class, &first_class);
1076 }
1077 }
1078 col_append_str(pinfo->cinfo, COL_INFO, "]");
1079
1080 return tvb_captured_length(tvb);
1081}
1082
1083static guint
1084get_happp_msg_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1085{
1086 guint ret, len, left;
1087 gint next_offset, line_len;
1088 guint8 first_byte;
1089 uint64_t dec_len;
1090 int saved_offset;
1091
1092 /* 0 means there is not enough data to get length. */
1093 ret = 0;
1094
1095 len = tvb_reported_length(tvb);
1096 left = len - offset;
1097 if (left < HAPPP_MSG_MIN_LEN)
1098 goto out;
1099
1100 saved_offset = offset;
1101 first_byte = (gchar)tvb_get_guint8(tvb, offset);
1102 if (first_byte == PEER_MSG_CLASS_CONTROL ||
1103 first_byte == PEER_MSG_CLASS_ERROR ||
1104 first_byte == PEER_MSG_CLASS_RESERVED) {
1105 ret = HAPPP_MSG_MIN_LEN;
1106 } else if (first_byte == PEER_MSG_CLASS_STICKTABLE) {
1107 int soff;
1108
1109 left -= HAPPP_MSG_MIN_LEN;
1110 offset += HAPPP_MSG_MIN_LEN;
1111 soff = offset;
1112 if (intdecode_from_tvbuff(tvb, &dec_len, &offset, len) < 0)
1113 goto out;
1114
1115 left -= offset - soff;
1116 if (left < dec_len)
1117 goto out;
1118
1119 ret = dec_len + offset - saved_offset;
1120 } else {
1121 /* hello message: add line lengths to compute this message length. */
1122 for (;;) {
1123 line_len = tvb_find_line_end(tvb, offset, -1, &next_offset, TRUE);
1124 if (line_len == -1)
1125 break;
1126
1127 ret += line_len + 1;
1128 offset += line_len + 1;
1129 }
1130 }
1131
1132 out:
1133 return ret;
1134 }
1135
1136static int
1137dissect_happp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1138{
1139 tcp_dissect_pdus(tvb, pinfo, tree, TRUE,
1140 HAPPP_MSG_MIN_LEN, get_happp_msg_len, dissect_happp_pdu, data);
1141
1142 return tvb_captured_length(tvb);
1143}
1144
1145/* Register the protocol with Wireshark.
1146 *
1147 * This format is require because a script is used to build the C function that
1148 * calls all the protocol registration.
1149 */
1150void
1151proto_register_happp(void)
1152{
1153 /* Setup list of header fields See Section 1.5 of README.dissector for
1154 * details. */
1155 static hf_register_info hf[] = {
1156 {
1157 /* This one is used as separator between HAPPP messages */
1158 &hf_happp_fake,
1159 {
1160 ":-----------------------------------------------", "happp.fake",
1161 FT_STRING, STR_ASCII, NULL, 0, "FAKE", HFILL
1162 }
1163 },
1164 {
1165 &hf_happp_version,
1166 {
1167 "version", "happp.version",
1168 FT_STRING, STR_ASCII, NULL, 0, "version", HFILL
1169 }
1170 },
1171 {
1172 &hf_happp_remotepeerid,
1173 {
1174 "remotepeerid", "happp.remotepeerid",
1175 FT_STRING, STR_ASCII, NULL, 0, "remote peer id", HFILL
1176 }
1177 },
1178 {
1179 &hf_happp_localpeerid,
1180 {
1181 "localpeerid", "happp.localpeerid",
1182 FT_STRING, STR_ASCII, NULL, 0, "local peer id", HFILL
1183 }
1184 },
1185 {
1186 &hf_happp_processpid,
1187 {
1188 "processpid", "happp.processpid",
1189 FT_STRING, STR_ASCII, NULL, 0, "process pid", HFILL
1190 }
1191 },
1192 {
1193 &hf_happp_relativepid,
1194 {
1195 "relativepid", "happp.relativepid",
1196 FT_STRING, STR_ASCII, NULL, 0, "relative pid", HFILL
1197 }
1198 },
1199 {
1200 &hf_happp_status,
1201 {
1202 "status", "happp.status",
1203 FT_STRING, STR_ASCII, NULL, 0, "status message", HFILL
1204 }
1205 },
1206 {
1207 &hf_happp_msg,
1208 {
1209 "message", "happp.msg",
1210 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1211 }
1212 },
1213 {
1214 &hf_happp_msg_class,
1215 {
1216 "message class", "happp.msg.class",
1217 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1218 }
1219 },
1220 {
1221 &hf_happp_msg_type,
1222 {
1223 "message type", "happp.msg.type",
1224 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1225 }
1226 },
1227 {
1228 &hf_happp_msg_len,
1229 {
1230 "message length", "happp.msg.len",
1231 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1232 }
1233 },
1234 {
1235 &hf_happp_stkt_def_id,
1236 {
1237 " ID", "happp.msg.stkt.def.id",
1238 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1239 }
1240 },
1241 {
1242 &hf_happp_stkt_def_name_len,
1243 {
1244 " name length", "happp.msg.stkt.def.name.length",
1245 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1246 }
1247 },
1248 {
1249 &hf_happp_stkt_def_name_value,
1250 {
1251 " name", "happp.msg.stkt.def.name.value",
1252 FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL
1253 }
1254 },
1255 {
1256 &hf_happp_stkt_def_key_type,
1257 {
1258 " key type", "happp.msg.stkt.def.key.type",
1259 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1260 }
1261 },
1262 {
1263 &hf_happp_stkt_def_key_len,
1264 {
1265 " key length", "happp.msg.stkt.def.key.len",
1266 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1267 }
1268 },
1269 {
1270 &hf_happp_stkt_def_data_types,
1271 {
1272 " data types", "happp.msg.stkt.def.data_types",
1273 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1274 }
1275 },
1276 {
1277 &hf_happp_stkt_updt_update_id,
1278 {
1279 " update ID", "happp.msg.stkt.updt.update_id",
1280 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL
1281 }
1282 },
1283 {
1284 &hf_happp_stkt_updt_expire,
1285 {
1286 " expiration", "happp.msg.stkt.updt.expiration",
1287 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL
1288 }
1289 },
1290 {
1291 &hf_happp_stkt_updt_key_len,
1292 {
1293 " key length", "happp.msg.stkt.updt.key.len",
1294 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1295 }
1296 },
1297 {
1298 &hf_happp_stkt_updt_key_str_value,
1299 {
1300 " key value", "happp.msg.stkt.updt.key.str.value",
1301 FT_STRING, STR_ASCII, NULL, 0, NULL, HFILL
1302 }
1303 },
1304 {
1305 &hf_happp_stkt_updt_key_int_value,
1306 {
1307 " key value", "happp.msg.stkt.updt.key.int.value",
1308 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL
1309 }
1310 },
1311 {
1312 &hf_happp_stkt_updt_key_ipv4_value,
1313 {
1314 " key IPv4 value", "happp.msg.stkt.updt.key.ipv4.value",
1315 FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL
1316 }
1317 },
1318 {
1319 &hf_happp_stkt_updt_key_bytes_value,
1320 {
1321 " key value", "happp.msg.stkt.updt.key.bytes.value",
1322 FT_BYTES, 0, NULL, 0, NULL, HFILL
1323 }
1324 },
1325 {
1326 &hf_happp_stkt_updt_data_server_id,
1327 {
1328 " server_id", "happp.msg.stkt.updt.data.server_id",
1329 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1330 }
1331 },
1332 {
1333 &hf_happp_stkt_updt_data_gpt0,
1334 {
1335 " gpt0", "happp.msg.stkt.updt.data.gpt0",
1336 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1337 }
1338 },
1339 {
1340 &hf_happp_stkt_updt_data_gpc0,
1341 {
1342 " gpc0", "happp.msg.stkt.updt.data.gpc0",
1343 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1344 }
1345 },
1346 {
1347 &hf_happp_stkt_updt_data_gpc0_rate_curr_tick,
1348 {
1349 " gpc0 curr. tick",
1350 "happp.msg.stkt.updt.data.gpc0_rate.curr_tick",
1351 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1352 }
1353 },
1354 {
1355 &hf_happp_stkt_updt_data_gpc0_rate_curr_ctr,
1356 {
1357 " gpc0 curr. ctr.",
1358 "happp.msg.stkt.updt.data.gpc0_rate.curr_ctr",
1359 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1360 }
1361 },
1362 {
1363 &hf_happp_stkt_updt_data_gpc0_rate_prev_ctr,
1364 {
1365 " gpc0 prev. ctr.",
1366 "happp.msg.stkt.updt.data.gpc0_rate.prev_ctr",
1367 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1368 }
1369 },
1370 {
1371 &hf_happp_stkt_updt_data_conn_cnt,
1372 {
1373 " conn_cnt",
1374 "happp.msg.stkt.updt.data.conn_cnt",
1375 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1376 }
1377 },
1378 {
1379 &hf_happp_stkt_updt_data_conn_rate_curr_tick,
1380 {
1381 " conn_rate curr. tick",
1382 "happp.msg.stkt.updt.data.conn_rate.curr_tick",
1383 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1384 }
1385 },
1386 {
1387 &hf_happp_stkt_updt_data_conn_rate_curr_ctr,
1388 {
1389 " conn_rate curr. ctr.",
1390 "happp.msg.stkt.updt.data.conn_rate.curr_ctr",
1391 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1392 }
1393 },
1394 {
1395 &hf_happp_stkt_updt_data_conn_rate_prev_ctr,
1396 {
1397 " conn_rate prev. ctr.",
1398 "happp.msg.stkt.updt.data.conn_rate.prev_ctr",
1399 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1400 }
1401 },
1402 {
1403 &hf_happp_stkt_updt_data_conn_cur,
1404 {
1405 " conn_curr curr. tick",
1406 "happp.msg.stkt.updt.data.conn_cur",
1407 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1408 }
1409 },
1410 {
1411 &hf_happp_stkt_updt_data_sess_cnt,
1412 {
1413 " sess_cnt", "happp.msg.stkt.updt.data.sess_cnt",
1414 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1415 }
1416 },
1417 {
1418 &hf_happp_stkt_updt_data_sess_rate_curr_tick,
1419 {
1420 " sess_rate curr. tick",
1421 "happp.msg.stkt.updt.data.sess_rate.curr_tick",
1422 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1423 }
1424 },
1425 {
1426 &hf_happp_stkt_updt_data_sess_rate_curr_ctr,
1427 {
1428 " sess_rate curr. ctr.",
1429 "happp.msg.stkt.updt.data.sess_rate.curr_ctr",
1430 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1431 }
1432 },
1433 {
1434 &hf_happp_stkt_updt_data_sess_rate_prev_ctr,
1435 {
1436 " sess_rate prev. ctr.",
1437 "happp.msg.stkt.updt.data.sess_rate.prev_ctr",
1438 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1439 }
1440 },
1441 {
1442 &hf_happp_stkt_updt_data_http_req_cnt,
1443 {
1444 " http_req_cnt",
1445 "happp.msg.stkt.updt.data.http_req_cnt",
1446 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1447 }
1448 },
1449 {
1450 &hf_happp_stkt_updt_data_http_req_rate_curr_tick,
1451 {
1452 " http_req_rate curr. tick",
1453 "happp.msg.stkt.updt.data.http_req_rate.curr_tick",
1454 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1455 }
1456 },
1457 {
1458 &hf_happp_stkt_updt_data_http_req_rate_curr_ctr,
1459 {
1460 " http_req_rate curr. ctr.",
1461 "happp.msg.stkt.updt.data.http_req_rate.curr_ctr",
1462 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1463 }
1464 },
1465 {
1466 &hf_happp_stkt_updt_data_http_req_rate_prev_ctr,
1467 {
1468 " http_req_rate prev. ctr.",
1469 "happp.msg.stkt.updt.data.http_req_rate.prev_ctr",
1470 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1471 }
1472 },
1473 {
1474 &hf_happp_stkt_updt_data_http_err_cnt,
1475 {
1476 " http_err_cnt",
1477 "happp.msg.stkt.updt.data.http_err_cnt",
1478 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1479 }
1480 },
1481 {
1482 &hf_happp_stkt_updt_data_http_err_rate_curr_tick,
1483 {
1484 " http_err_rate curr. tick",
1485 "happp.msg.stkt.updt.data.http_err_rate.curr_tick",
1486 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1487 }
1488 },
1489 {
1490 &hf_happp_stkt_updt_data_http_err_rate_curr_ctr,
1491 {
1492 " http_err_rate curr. ctr.",
1493 "happp.msg.stkt.updt.data.http_err_rate.curr_ctr",
1494 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1495 }
1496 },
1497 {
1498 &hf_happp_stkt_updt_data_http_err_rate_prev_ctr,
1499 {
1500 " http_err_rate prev. ctr.",
1501 "happp.msg.stkt.updt.data.http_err_rate.prev_ctr",
1502 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1503 }
1504 },
1505 {
1506 &hf_happp_stkt_updt_data_bytes_in_cnt,
1507 {
1508 " bytes_in_cnt",
1509 "happp.msg.stkt.updt.data.bytes_in_cnt",
1510 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1511 }
1512 },
1513 {
1514 &hf_happp_stkt_updt_data_bytes_in_rate_curr_tick,
1515 {
1516 " bytes_in_rate curr. tick",
1517 "happp.msg.stkt.updt.data.bytes_in_rate.curr_tick",
1518 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1519 }
1520 },
1521 {
1522 &hf_happp_stkt_updt_data_bytes_in_rate_curr_ctr,
1523 {
1524 " bytes_in_rate curr. ctr.",
1525 "happp.msg.stkt.updt.data.bytes_in_rate.curr_ctr",
1526 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1527 }
1528 },
1529 {
1530 &hf_happp_stkt_updt_data_bytes_in_rate_prev_ctr,
1531 {
1532 " bytes_in_rate prev. ctr.",
1533 "happp.msg.stkt.updt.data.bytes_in_rate.prev_ctr",
1534 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1535 }
1536 },
1537 {
1538 &hf_happp_stkt_updt_data_bytes_out_cnt,
1539 {
1540 " bytes_out_cnt",
1541 "happp.msg.stkt.updt.data.bytes_out_cnt",
1542 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1543 }
1544 },
1545 {
1546 &hf_happp_stkt_updt_data_bytes_out_rate_curr_tick,
1547 {
1548 " bytes_out_rate curr. tick",
1549 "happp.msg.stkt.updt.data.bytes_out_rate.curr_tick",
1550 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1551 }
1552 },
1553 {
1554 &hf_happp_stkt_updt_data_bytes_out_rate_curr_ctr,
1555 {
1556 " bytes_out_rate curr. ctr.",
1557 "happp.msg.stkt.updt.data.bytes_out_rate.curr_ctr",
1558 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1559 }
1560 },
1561 {
1562 &hf_happp_stkt_updt_data_bytes_out_rate_prev_ctr,
1563 {
1564 " bytes_out_rate prev. ctr.",
1565 "happp.msg.stkt.updt.data.bytes_out_rate.prev_ctr",
1566 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1567 }
1568 },
1569 {
1570 &hf_happp_stkt_updt_ack_table_id,
1571 {
1572 " remote table Id",
1573 "happp.msg.stkt.updt.ack.table_id",
1574 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL
1575 }
1576 },
1577 {
1578 &hf_happp_stkt_updt_ack_update_id,
1579 {
1580 " update Id", "happp.msg.stkt.updt.ack.update_id",
1581 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL
1582 }
1583 },
1584 };
1585
1586 /* Setup protocol subtree array */
1587 static gint *ett[] = {
1588 &ett_happp,
1589 &ett_happp_msg
1590 };
1591
1592 /* Register the protocol name and description */
1593 proto_happp = proto_register_protocol("HAProxy Peers Protocol", "HAPPP", "happp");
1594
1595 /* Required function calls to register the header fields and subtrees */
1596 proto_register_field_array(proto_happp, hf, array_length(hf));
1597 proto_register_subtree_array(ett, array_length(ett));
1598}
1599
1600static gboolean
1601dissect_happp_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1602{
1603 size_t proto_strlen;
1604 conversation_t *conversation;
1605
1606 proto_strlen = strlen(HAPPP_PROTOCOL);
1607
1608 if (tvb_captured_length(tvb) < proto_strlen + 1)
1609 return FALSE;
1610
Joseph Herlantbd0f83f2018-11-09 19:00:24 -08001611 /* Check that we received a line beginning with HAPPP_PROTOCOL
Frédéric Lécaille6d889502017-11-15 14:50:19 +01001612 * followed by a space character.
1613 */
1614 if (tvb_strneql(tvb, 0, HAPPP_PROTOCOL, proto_strlen) ||
1615 tvb_get_guint8(tvb, proto_strlen) != ' ')
1616 return FALSE;
1617
1618 conversation = find_or_create_conversation(pinfo);
1619 if (!conversation)
1620 return FALSE;
1621
1622 conversation_set_dissector(conversation, happp_tcp_handle);
1623 dissect_happp_tcp(tvb, pinfo, tree, data);
1624
1625 return TRUE;
1626}
1627
1628/* Simpler form of proto_reg_handoff_happp which can be used if there are
1629 * no prefs-dependent registration function calls. */
1630void
1631proto_reg_handoff_happp(void)
1632{
1633 /* Use create_dissector_handle() to indicate that dissect_happp_tcp()
1634 * returns the number of bytes it dissected (or 0 if it thinks the packet
1635 * does not belong to HAProxy Peers Protocol).
1636 */
1637 happp_tcp_handle = create_dissector_handle(dissect_happp_tcp, proto_happp);
1638 heur_dissector_add("tcp", dissect_happp_heur_tcp, "HAPPP over TCP", "happp_tcp",
1639 proto_happp, HEURISTIC_ENABLE);
1640}
1641
William Lallemand2be58f72020-04-25 22:03:29 +02001642
1643void
1644plugin_register(void)
1645{
1646 static proto_plugin plug;
1647
1648 plug.register_protoinfo = proto_register_happp;
1649 plug.register_handoff = proto_reg_handoff_happp;
1650 proto_register_plugin(&plug);
1651}