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/capwap.c
Line
Count
Source
1
/*
2
 * capwap.c
3
 *
4
 * Copyright (C) 2019 - ntop.org
5
 *
6
 * nDPI is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * nDPI is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with nDPI.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 */
20
21
22
#include "ndpi_protocol_ids.h"
23
24
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_CAPWAP
25
26
#include "ndpi_api.h"
27
#include "ndpi_private.h"
28
29
2.97M
#define NDPI_CAPWAP_CONTROL_PORT 5246
30
1.98M
#define NDPI_CAPWAP_DATA_PORT    5247
31
32
33
static void ndpi_int_capwap_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
34
861
             struct ndpi_flow_struct *flow) {
35
861
  ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_CAPWAP, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
36
861
}
37
38
static int is_capwap_multicast(const struct ndpi_packet_struct *packet)
39
5.29k
{
40
  /* RFC 5115 Sec 3.3
41
     "The WTP MUST send the Discovery Request
42
      message to either the limited broadcast IP address (255.255.255.255),
43
      the well-known CAPWAP multicast address (224.0.1.140), or to the
44
      unicast IP address of the AC.  For IPv6 networks, since broadcast
45
      does not exist, the use of "All ACs multicast address" (FF0X:0:0:0:0:
46
      0:0:18C) is used instead.
47
  */
48
5.29k
  if(packet->iph) {
49
4.12k
    if((packet->iph->daddr == 0xFFFFFFFF) ||
50
3.72k
       (ntohl(packet->iph->daddr) == 0XE000018C))
51
424
      return 1;
52
4.12k
  } else if(packet->iphv6) {
53
1.17k
    if(((ntohl(packet->iphv6->ip6_dst.u6_addr.u6_addr32[0] & 0xFFF0FFFF) == 0xFF000000)) &&
54
275
       (packet->iphv6->ip6_dst.u6_addr.u6_addr32[1] == 0) &&
55
161
       (packet->iphv6->ip6_dst.u6_addr.u6_addr32[2] == 0) &&
56
63
       (ntohl(packet->iphv6->ip6_dst.u6_addr.u6_addr32[3] == 0x0000018C)))
57
3
      return 1;
58
1.17k
  }
59
4.86k
  return 0;
60
5.29k
}
61
62
/* ************************************************** */
63
64
static void ndpi_search_setup_capwap(struct ndpi_detection_module_struct *ndpi_struct,
65
991k
             struct ndpi_flow_struct *flow) {
66
991k
  struct ndpi_packet_struct *packet = &ndpi_struct->packet;
67
991k
  u_int16_t sport, dport;
68
   
69
991k
  sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
70
  
71
991k
  if((dport == NDPI_CAPWAP_CONTROL_PORT)
72
1.93k
     && (is_capwap_multicast(packet))
73
269
     && (packet->payload_packet_len >= 16)
74
211
     && (packet->payload[0] == 0x0)
75
143
     && (packet->payload[8] == 6 /* Mac len */)
76
991k
     )
77
79
    goto capwap_found;
78
  
79
991k
  if(((sport == NDPI_CAPWAP_CONTROL_PORT) || (dport == NDPI_CAPWAP_CONTROL_PORT))
80
2.51k
     && ((packet->payload[0] == 0x0) || (packet->payload[0] == 0x1))
81
991k
     ) {
82
1.40k
    u_int16_t msg_len, offset, to_add;
83
84
1.40k
    if(packet->payload[0] == 0x0)
85
781
      offset = 13, to_add = 13;
86
621
    else
87
621
      offset = 15, to_add = 17;
88
89
1.40k
    if (packet->payload_packet_len >= offset + sizeof(u_int16_t)) {
90
973
      msg_len = ntohs(*(u_int16_t*)&packet->payload[offset]);
91
92
973
      if((msg_len+to_add) == packet->payload_packet_len)
93
240
        goto capwap_found;
94
973
    }
95
1.40k
  }
96
  
97
991k
  if(
98
991k
     (((dport == NDPI_CAPWAP_DATA_PORT) && (!is_capwap_multicast(packet))) || (sport == NDPI_CAPWAP_DATA_PORT))
99
5.96k
     && (packet->payload_packet_len >= 16)
100
3.38k
     && (packet->payload[0] == 0x0)
101
991k
     ) {
102
1.93k
    u_int8_t is_80211_data = (packet->payload[9] & 0x0C) >> 2;
103
104
      
105
1.93k
    if((sport == NDPI_CAPWAP_DATA_PORT) && (is_80211_data == 2 /* IEEE 802.11 Data */))
106
114
      goto capwap_found;
107
1.81k
    else if(dport == NDPI_CAPWAP_DATA_PORT) {
108
1.48k
      u_int16_t msg_len = ntohs(*(u_int16_t*)&packet->payload[13]);
109
      
110
1.48k
      if((packet->payload[8] == 1 /* Mac len */)
111
1.26k
   || (packet->payload[8] == 6 /* Mac len */)
112
1.20k
   || (packet->payload[8] == 4 /* Wireless len */)
113
1.11k
   || ((msg_len+15) == packet->payload_packet_len))
114
428
  goto capwap_found;  
115
1.48k
    }
116
1.93k
  }
117
  
118
991k
  NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
119
991k
  return;
120
121
861
 capwap_found:
122
861
  ndpi_int_capwap_add_connection(ndpi_struct, flow);
123
861
}
124
125
static void ndpi_search_capwap(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
126
991k
{
127
991k
  struct ndpi_packet_struct *packet = &ndpi_struct->packet;
128
129
991k
  if(packet->udp && (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN))
130
991k
    ndpi_search_setup_capwap(ndpi_struct, flow);
131
991k
}
132
133
134
void init_capwap_dissector(struct ndpi_detection_module_struct *ndpi_struct)
135
20.4k
{
136
20.4k
  ndpi_register_dissector("CAPWAP", ndpi_struct,
137
20.4k
                     ndpi_search_capwap,
138
20.4k
                     NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
139
20.4k
                     1, NDPI_PROTOCOL_CAPWAP);
140
20.4k
}