Coverage Report

Created: 2026-06-16 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ndpi/src/lib/protocols/tinc.c
Line
Count
Source
1
/*
2
 * tinc.c
3
 *
4
 * Copyright (C) 2017 - William Guglielmo <william@deselmo.com>
5
 * Copyright (C) 2017-22 - ntop.org
6
 *
7
 * nDPI is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * nDPI is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with nDPI.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 */
21
#include "ndpi_protocol_ids.h"
22
23
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_TINC
24
25
#include "ndpi_api.h"
26
#include "ndpi_private.h"
27
#include "libcache.h"
28
29
PACK_ON struct tinc_cache_entry {
30
  u_int32_t src_address;
31
  u_int32_t dst_address;
32
  u_int16_t dst_port;
33
} PACK_OFF;
34
35
static void ndpi_check_tinc(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
36
4.26M
{
37
4.26M
  struct ndpi_packet_struct *packet = &ndpi_struct->packet;
38
4.26M
  const u_int8_t *packet_payload = packet->payload;
39
4.26M
  u_int32_t payload_len = packet->payload_packet_len;
40
  
41
4.26M
  if(packet->udp != NULL) {
42
934k
    if(ndpi_struct->tinc_cache != NULL) {
43
767k
      struct tinc_cache_entry tinc_cache_entry1 = {
44
767k
        .src_address = packet->iph->saddr,
45
767k
        .dst_address = packet->iph->daddr,
46
767k
        .dst_port = packet->udp->dest
47
767k
      };
48
49
767k
      struct tinc_cache_entry tinc_cache_entry2 = {
50
767k
        .src_address = packet->iph->daddr,
51
767k
        .dst_address = packet->iph->saddr,
52
767k
        .dst_port = packet->udp->source
53
767k
      };
54
55
767k
      if(cache_remove(ndpi_struct->tinc_cache, &tinc_cache_entry1, sizeof(tinc_cache_entry1)) == CACHE_NO_ERROR ||
56
767k
   cache_remove(ndpi_struct->tinc_cache, &tinc_cache_entry2, sizeof(tinc_cache_entry2)) == CACHE_NO_ERROR) {
57
58
68
        cache_remove(ndpi_struct->tinc_cache, &tinc_cache_entry1, sizeof(tinc_cache_entry1));
59
68
        cache_remove(ndpi_struct->tinc_cache, &tinc_cache_entry2, sizeof(tinc_cache_entry2));
60
61
  /* cache_free(ndpi_struct->tinc_cache); */
62
63
68
        NDPI_LOG_INFO(ndpi_struct, "found tinc udp connection\n");
64
68
        ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_TINC, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI_CACHE);
65
68
      }
66
767k
    }
67
    
68
934k
    NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
69
934k
    return;
70
3.33M
  } else if(packet->tcp != NULL) {
71
72
3.33M
    switch(flow->tinc_state) {
73
3.32M
    case 0:
74
3.33M
    case 1:
75
3.33M
      if(payload_len > 6 && memcmp(packet_payload, "0 ", 2) == 0 && packet_payload[2] != ' ') {
76
3.27k
  u_int32_t i = 3;
77
66.9k
  while(i < payload_len && packet_payload[i++] != ' ');
78
3.27k
  if(i+3 == payload_len && memcmp((packet_payload+i), "17\n", 3) == 0) {
79
1.98k
    flow->tinc_state++;
80
1.98k
    return;
81
1.98k
  }
82
3.27k
      }
83
3.32M
      break;
84
85
3.32M
    case 2:
86
938
    case 3:
87
938
      if(payload_len > 11 && memcmp(packet_payload, "1 ", 2) == 0 && packet_payload[2] != ' ') {
88
743
  u_int16_t i = 3;
89
743
  u_int8_t numbers_left = 4;
90
3.34k
  while(numbers_left) {
91
17.4k
    while(i < payload_len && packet_payload[i] >= '0' && packet_payload[i] <= '9') {
92
14.7k
      i++;
93
14.7k
    }
94
95
2.72k
    if(i < payload_len && packet_payload[i++] == ' ') {
96
2.60k
      numbers_left--;
97
2.60k
    }
98
121
    else break;
99
2.72k
  }
100
          
101
743
  if(numbers_left) break;
102
          
103
460k
  while(i < payload_len &&
104
460k
        ((packet_payload[i] >= '0' && packet_payload[i] <= '9') ||
105
460k
         (packet_payload[i] >= 'A' && packet_payload[i] <= 'Z'))) {
106
460k
    i++;
107
460k
  }
108
          
109
622
  if(i < payload_len && packet_payload[i] == '\n') {
110
407
    if(++flow->tinc_state > 3) {
111
166
      struct tinc_cache_entry tinc_cache_entry = {
112
166
        .src_address = flow->c_address.v4,
113
166
        .dst_address = flow->s_address.v4,
114
166
        .dst_port = flow->s_port,
115
166
      };
116
117
166
      if(ndpi_struct->tinc_cache == NULL)
118
12
        ndpi_struct->tinc_cache = cache_new(TINC_CACHE_MAX_SIZE);              
119
120
166
      cache_add(ndpi_struct->tinc_cache, &tinc_cache_entry, sizeof(tinc_cache_entry));
121
166
      NDPI_LOG_INFO(ndpi_struct, "found tinc tcp connection\n");
122
166
      ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_TINC, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
123
166
    }
124
407
    return;
125
407
  }
126
622
      }
127
410
      break;
128
      
129
410
    default: break;
130
3.33M
    }
131
3.33M
  }
132
133
3.32M
  NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
134
3.32M
}
135
136
4.26M
static void ndpi_search_tinc(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) {
137
4.26M
  NDPI_LOG_DBG(ndpi_struct, "tinc detection\n");
138
139
4.26M
  if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_TINC) {
140
4.26M
    ndpi_check_tinc(ndpi_struct, flow);
141
4.26M
  }
142
4.26M
}
143
144
void init_tinc_dissector(struct ndpi_detection_module_struct *ndpi_struct)
145
20.4k
{
146
20.4k
  ndpi_register_dissector("TINC", ndpi_struct,
147
20.4k
                     ndpi_search_tinc,
148
20.4k
                     NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION, /* TODO: IPv6? */
149
20.4k
                     1, NDPI_PROTOCOL_TINC);
150
20.4k
}
151