|  | 
| 1 | 1 | #include "lib.h" | 
| 2 |  | -#include "wiregasm.h" | 
| 3 |  | -#include <epan/conversation_table.h> | 
| 4 |  | -#include <epan/maxmind_db.h> | 
| 5 | 2 | 
 | 
| 6 | 3 | 
 | 
| 7 | 4 | static guint32 cum_bytes; | 
| 8 | 5 | static frame_data ref_frame; | 
| 9 | 6 | 
 | 
|  | 7 | + | 
|  | 8 | +#define WG_IOGRAPH_MAX_ITEMS 250000 /* 250k limit of items is taken from wireshark-qt, on x86_64 sizeof(io_graph_item_t) is 152, so single graph can take max 36 MB */ | 
|  | 9 | + | 
|  | 10 | +struct wg_iograph | 
|  | 11 | +{ | 
|  | 12 | +  /* config */ | 
|  | 13 | +  int hf_index; | 
|  | 14 | +  io_graph_item_unit_t calc_type; | 
|  | 15 | +  guint32 interval; | 
|  | 16 | + | 
|  | 17 | +  /* result */ | 
|  | 18 | +  int space_items; | 
|  | 19 | +  int num_items; | 
|  | 20 | +  io_graph_item_t *items; | 
|  | 21 | +  GString *error; | 
|  | 22 | +}; | 
|  | 23 | + | 
| 10 | 24 | struct wg_conv_tap_data | 
| 11 | 25 | { | 
| 12 | 26 |   const char *type; | 
| @@ -1639,7 +1653,7 @@ wg_session_process_tap_conv_cb(void *tapdata) | 
| 1639 | 1653 |  * | 
| 1640 | 1654 |  *   (m) err   - error code | 
| 1641 | 1655 |  */ | 
| 1642 |  | -TapResponse wg_session_process_tap(capture_file *cfile, TapInput taps) | 
|  | 1656 | +TapResponse wg_session_process_tap(capture_file *cfile, MapInput taps) | 
| 1643 | 1657 | { | 
| 1644 | 1658 |   TapResponse buf; | 
| 1645 | 1659 |   void *taps_data[16]; | 
| @@ -1785,3 +1799,205 @@ TapResponse wg_session_process_tap(capture_file *cfile, TapInput taps) | 
| 1785 | 1799 |   } | 
| 1786 | 1800 |   return buf; | 
| 1787 | 1801 | } | 
|  | 1802 | + | 
|  | 1803 | + | 
|  | 1804 | +static tap_packet_status | 
|  | 1805 | +wg_iograph_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, const void *dummy _U_, tap_flags_t flags _U_) | 
|  | 1806 | +{ | 
|  | 1807 | +  struct wg_iograph *graph = (struct wg_iograph *)g; | 
|  | 1808 | +  int idx; | 
|  | 1809 | +  bool update_succeeded; | 
|  | 1810 | + | 
|  | 1811 | +  idx = get_io_graph_index(pinfo, graph->interval); | 
|  | 1812 | +  if (idx < 0 || idx >= WG_IOGRAPH_MAX_ITEMS) | 
|  | 1813 | +    return TAP_PACKET_DONT_REDRAW; | 
|  | 1814 | + | 
|  | 1815 | +  if (idx + 1 > graph->num_items) | 
|  | 1816 | +  { | 
|  | 1817 | +    if (idx + 1 > graph->space_items) | 
|  | 1818 | +    { | 
|  | 1819 | +      int new_size = idx + 1024; | 
|  | 1820 | + | 
|  | 1821 | +      graph->items = (io_graph_item_t *)g_realloc(graph->items, sizeof(io_graph_item_t) * new_size); | 
|  | 1822 | +      reset_io_graph_items(&graph->items[graph->space_items], new_size - graph->space_items); | 
|  | 1823 | + | 
|  | 1824 | +      graph->space_items = new_size; | 
|  | 1825 | +    } | 
|  | 1826 | +    else if (graph->items == NULL) | 
|  | 1827 | +    { | 
|  | 1828 | +      graph->items = g_new(io_graph_item_t, graph->space_items); | 
|  | 1829 | +      reset_io_graph_items(graph->items, graph->space_items); | 
|  | 1830 | +    } | 
|  | 1831 | + | 
|  | 1832 | +    graph->num_items = idx + 1; | 
|  | 1833 | +  } | 
|  | 1834 | + | 
|  | 1835 | +  update_succeeded = update_io_graph_item(graph->items, idx, pinfo, edt, graph->hf_index, graph->calc_type, graph->interval); | 
|  | 1836 | +  /* XXX - TAP_PACKET_FAILED if the item couldn't be updated, with an error message? */ | 
|  | 1837 | +  return update_succeeded ? TAP_PACKET_REDRAW : TAP_PACKET_DONT_REDRAW; | 
|  | 1838 | +} | 
|  | 1839 | + | 
|  | 1840 | +/** | 
|  | 1841 | + * wg_session_process_iograph() | 
|  | 1842 | + * | 
|  | 1843 | + * Process iograph request | 
|  | 1844 | + * | 
|  | 1845 | + * Input: | 
|  | 1846 | + *   (o) interval - interval time in ms, if not specified: 1000ms | 
|  | 1847 | + *   (m) graph0             - First graph request | 
|  | 1848 | + *   (o) graph1...graph9    - Other graph requests | 
|  | 1849 | + *   (o) filter0            - First graph filter | 
|  | 1850 | + *   (o) filter1...filter9  - Other graph filters | 
|  | 1851 | + * | 
|  | 1852 | + * Graph requests can be one of: "packets", "bytes", "bits", "sum:<field>", "frames:<field>", "max:<field>", "min:<field>", "avg:<field>", "load:<field>", | 
|  | 1853 | + * if you use variant with <field>, you need to pass field name in filter request. | 
|  | 1854 | + * | 
|  | 1855 | + * Output object with attributes: | 
|  | 1856 | + *       error   - graph cannot be constructed | 
|  | 1857 | + *   (m) iograph - array of graph results with attributes: | 
|  | 1858 | + *                  items  - graph values, zeros are skipped, if value is not a number it's next index encoded as hex string | 
|  | 1859 | + */ | 
|  | 1860 | +IoGraphResult wg_session_process_iograph(capture_file *cfile, MapInput input) | 
|  | 1861 | +{ | 
|  | 1862 | +  IoGraphResult buf; | 
|  | 1863 | +  // interval should be an integer | 
|  | 1864 | +  const char *tok_interval = input["interval"].c_str(); | 
|  | 1865 | +  struct wg_iograph graphs[10]; | 
|  | 1866 | +  bool is_any_ok = false; | 
|  | 1867 | +  int graph_count; | 
|  | 1868 | + | 
|  | 1869 | +  guint32 interval_ms = 1000; /* default: one per second */ | 
|  | 1870 | +  int i; | 
|  | 1871 | + | 
|  | 1872 | +  if (tok_interval) | 
|  | 1873 | +    ws_strtou32(tok_interval, NULL, &interval_ms); | 
|  | 1874 | + | 
|  | 1875 | +  for (i = graph_count = 0; i < (int)G_N_ELEMENTS(graphs); i++) | 
|  | 1876 | +  { | 
|  | 1877 | +    struct wg_iograph *graph = &graphs[graph_count]; | 
|  | 1878 | + | 
|  | 1879 | +    const char *tok_graph; | 
|  | 1880 | +    const char *tok_filter; | 
|  | 1881 | +    char tok_format_buf[32]; | 
|  | 1882 | +    const char *field_name; | 
|  | 1883 | + | 
|  | 1884 | +    snprintf(tok_format_buf, sizeof(tok_format_buf), "graph%d", i); | 
|  | 1885 | +    tok_graph = input[tok_format_buf].c_str(); | 
|  | 1886 | +    if (!tok_graph) | 
|  | 1887 | +      break; | 
|  | 1888 | + | 
|  | 1889 | +    snprintf(tok_format_buf, sizeof(tok_format_buf), "filter%d", i); | 
|  | 1890 | +    tok_filter = input[tok_format_buf].c_str(); | 
|  | 1891 | + | 
|  | 1892 | +    if (!strcmp(tok_graph, "packets")) | 
|  | 1893 | +      graph->calc_type = IOG_ITEM_UNIT_PACKETS; | 
|  | 1894 | +    else if (!strcmp(tok_graph, "bytes")) | 
|  | 1895 | +      graph->calc_type = IOG_ITEM_UNIT_BYTES; | 
|  | 1896 | +    else if (!strcmp(tok_graph, "bits")) | 
|  | 1897 | +      graph->calc_type = IOG_ITEM_UNIT_BITS; | 
|  | 1898 | +    else if (g_str_has_prefix(tok_graph, "sum:")) | 
|  | 1899 | +      graph->calc_type = IOG_ITEM_UNIT_CALC_SUM; | 
|  | 1900 | +    else if (g_str_has_prefix(tok_graph, "frames:")) | 
|  | 1901 | +      graph->calc_type = IOG_ITEM_UNIT_CALC_FRAMES; | 
|  | 1902 | +    else if (g_str_has_prefix(tok_graph, "fields:")) | 
|  | 1903 | +      graph->calc_type = IOG_ITEM_UNIT_CALC_FIELDS; | 
|  | 1904 | +    else if (g_str_has_prefix(tok_graph, "max:")) | 
|  | 1905 | +      graph->calc_type = IOG_ITEM_UNIT_CALC_MAX; | 
|  | 1906 | +    else if (g_str_has_prefix(tok_graph, "min:")) | 
|  | 1907 | +      graph->calc_type = IOG_ITEM_UNIT_CALC_MIN; | 
|  | 1908 | +    else if (g_str_has_prefix(tok_graph, "avg:")) | 
|  | 1909 | +      graph->calc_type = IOG_ITEM_UNIT_CALC_AVERAGE; | 
|  | 1910 | +    else if (g_str_has_prefix(tok_graph, "load:")) | 
|  | 1911 | +      graph->calc_type = IOG_ITEM_UNIT_CALC_LOAD; | 
|  | 1912 | +    else | 
|  | 1913 | +      break; | 
|  | 1914 | + | 
|  | 1915 | +    field_name = strchr(tok_graph, ':'); | 
|  | 1916 | +    if (field_name) | 
|  | 1917 | +      field_name = field_name + 1; | 
|  | 1918 | + | 
|  | 1919 | +    graph->interval = interval_ms; | 
|  | 1920 | + | 
|  | 1921 | +    graph->hf_index = -1; | 
|  | 1922 | +    graph->error = check_field_unit(field_name, &graph->hf_index, graph->calc_type); | 
|  | 1923 | + | 
|  | 1924 | +    graph->space_items = 0; /* TODO, can avoid realloc()s in wg_iograph_packet() by calculating: capture_time / interval */ | 
|  | 1925 | +    graph->num_items = 0; | 
|  | 1926 | +    graph->items = NULL; | 
|  | 1927 | + | 
|  | 1928 | +    if (!graph->error) | 
|  | 1929 | +      graph->error = register_tap_listener( | 
|  | 1930 | +        "frame", | 
|  | 1931 | +        graph, | 
|  | 1932 | +        tok_filter, | 
|  | 1933 | +        TL_REQUIRES_PROTO_TREE, | 
|  | 1934 | +        NULL, | 
|  | 1935 | +        wg_iograph_packet, | 
|  | 1936 | +        NULL, | 
|  | 1937 | +        NULL | 
|  | 1938 | +      ); | 
|  | 1939 | + | 
|  | 1940 | +    graph_count++; | 
|  | 1941 | + | 
|  | 1942 | +    if (graph->error) | 
|  | 1943 | +    { | 
|  | 1944 | +      buf.error = graph->error->str; | 
|  | 1945 | +      return buf; | 
|  | 1946 | +    } | 
|  | 1947 | + | 
|  | 1948 | +    if (graph->error == NULL) | 
|  | 1949 | +      is_any_ok = true; | 
|  | 1950 | +  } | 
|  | 1951 | + | 
|  | 1952 | +  /* retap only if we have at least one ok */ | 
|  | 1953 | +  if (is_any_ok) | 
|  | 1954 | +    wg_retap(cfile); | 
|  | 1955 | + | 
|  | 1956 | +  for (i = 0; i < graph_count; i++) | 
|  | 1957 | +  { | 
|  | 1958 | +    struct wg_iograph *graph = &graphs[i]; | 
|  | 1959 | +    IoGraph g; | 
|  | 1960 | + | 
|  | 1961 | +    if (graph->error) | 
|  | 1962 | +    { | 
|  | 1963 | +      g_string_free(graph->error, true); | 
|  | 1964 | +      buf.error = g_strdup_printf("Error processing graph %d", i); | 
|  | 1965 | +      return buf; | 
|  | 1966 | +    } | 
|  | 1967 | +    else | 
|  | 1968 | +    { | 
|  | 1969 | +      int idx; | 
|  | 1970 | +      int next_idx = 0; | 
|  | 1971 | + | 
|  | 1972 | +      for (idx = 0; idx < graph->num_items; idx++) | 
|  | 1973 | +      { | 
|  | 1974 | +        double val; | 
|  | 1975 | + | 
|  | 1976 | +        val = get_io_graph_item( | 
|  | 1977 | +          graph->items, | 
|  | 1978 | +          graph->calc_type, | 
|  | 1979 | +          idx, | 
|  | 1980 | +          graph->hf_index, | 
|  | 1981 | +          cfile, | 
|  | 1982 | +          graph->interval, | 
|  | 1983 | +          graph->num_items | 
|  | 1984 | +        ); | 
|  | 1985 | + | 
|  | 1986 | +        /* if it's zero, don't display */ | 
|  | 1987 | +        if (val == 0.0) | 
|  | 1988 | +          continue; | 
|  | 1989 | + | 
|  | 1990 | +        /* cause zeros are not printed, need to output index */ | 
|  | 1991 | +        if (next_idx != idx) { | 
|  | 1992 | +          g.items.push_back(idx); | 
|  | 1993 | +        } | 
|  | 1994 | +        g.items.push_back(val); | 
|  | 1995 | +        next_idx = idx + 1; | 
|  | 1996 | +      } | 
|  | 1997 | +    } | 
|  | 1998 | +    buf.iograph.push_back(g); | 
|  | 1999 | +    remove_tap_listener(graph); | 
|  | 2000 | +    g_free(graph->items); | 
|  | 2001 | +  } | 
|  | 2002 | +  return buf; | 
|  | 2003 | +} | 
0 commit comments