"Fossies" - the Fresh Open Source Software Archive

Member "haproxy-2.0.9/contrib/wireshark-dissectors/peers/packet-happp.c" (15 Nov 2019, 45403 Bytes) of package /linux/misc/haproxy-2.0.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "packet-happp.c" see the Fossies "Dox" file reference documentation.

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