Coverage Report

Created: 2026-02-21 07:19

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.81M
#define NDPI_CAPWAP_CONTROL_PORT 5246
30
1.87M
#define NDPI_CAPWAP_DATA_PORT    5247
31
32
33
static void ndpi_int_capwap_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
34
929
             struct ndpi_flow_struct *flow) {
35
929
  ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_CAPWAP, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
36
929
}
37
38
static int is_capwap_multicast(const struct ndpi_packet_struct *packet)
39
4.70k
{
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
4.70k
  if(packet->iph) {
49
3.57k
    if((packet->iph->daddr == 0xFFFFFFFF) ||
50
3.22k
       (ntohl(packet->iph->daddr) == 0XE000018C))
51
352
      return 1;
52
3.57k
  } else if(packet->iphv6) {
53
1.12k
    if(((ntohl(packet->iphv6->ip6_dst.u6_addr.u6_addr32[0] & 0xFFF0FFFF) == 0xFF000000)) &&
54
310
       (packet->iphv6->ip6_dst.u6_addr.u6_addr32[1] == 0) &&
55
169
       (packet->iphv6->ip6_dst.u6_addr.u6_addr32[2] == 0) &&
56
66
       (ntohl(packet->iphv6->ip6_dst.u6_addr.u6_addr32[3] == 0x0000018C)))
57
2
      return 1;
58
1.12k
  }
59
4.34k
  return 0;
60
4.70k
}
61
62
/* ************************************************** */
63
64
static void ndpi_search_setup_capwap(struct ndpi_detection_module_struct *ndpi_struct,
65
937k
             struct ndpi_flow_struct *flow) {
66
937k
  struct ndpi_packet_struct *packet = &ndpi_struct->packet;
67
937k
  u_int16_t sport, dport;
68
   
69
937k
  sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
70
  
71
937k
  if((dport == NDPI_CAPWAP_CONTROL_PORT)
72
1.74k
     && (is_capwap_multicast(packet))
73
265
     && (packet->payload_packet_len >= 16)
74
222
     && (packet->payload[0] == 0x0)
75
163
     && (packet->payload[8] == 6 /* Mac len */)
76
937k
     )
77
91
    goto capwap_found;
78
  
79
937k
  if(((sport == NDPI_CAPWAP_CONTROL_PORT) || (dport == NDPI_CAPWAP_CONTROL_PORT))
80
2.39k
     && ((packet->payload[0] == 0x0) || (packet->payload[0] == 0x1))
81
937k
     ) {
82
1.36k
    u_int16_t msg_len, offset, to_add;
83
84
1.36k
    if(packet->payload[0] == 0x0)
85
642
      offset = 13, to_add = 13;
86
719
    else
87
719
      offset = 15, to_add = 17;
88
89
1.36k
    if (packet->payload_packet_len >= offset + sizeof(u_int16_t)) {
90
1.07k
      msg_len = ntohs(*(u_int16_t*)&packet->payload[offset]);
91
92
1.07k
      if((msg_len+to_add) == packet->payload_packet_len)
93
356
        goto capwap_found;
94
1.07k
    }
95
1.36k
  }
96
  
97
936k
  if(
98
936k
     (((dport == NDPI_CAPWAP_DATA_PORT) && (!is_capwap_multicast(packet))) || (sport == NDPI_CAPWAP_DATA_PORT))
99
5.00k
     && (packet->payload_packet_len >= 16)
100
2.87k
     && (packet->payload[0] == 0x0)
101
936k
     ) {
102
1.76k
    u_int8_t is_80211_data = (packet->payload[9] & 0x0C) >> 2;
103
104
      
105
1.76k
    if((sport == NDPI_CAPWAP_DATA_PORT) && (is_80211_data == 2 /* IEEE 802.11 Data */))
106
110
      goto capwap_found;
107
1.65k
    else if(dport == NDPI_CAPWAP_DATA_PORT) {
108
1.34k
      u_int16_t msg_len = ntohs(*(u_int16_t*)&packet->payload[13]);
109
      
110
1.34k
      if((packet->payload[8] == 1 /* Mac len */)
111
1.17k
   || (packet->payload[8] == 6 /* Mac len */)
112
1.10k
   || (packet->payload[8] == 4 /* Wireless len */)
113
1.01k
   || ((msg_len+15) == packet->payload_packet_len))
114
372
  goto capwap_found;  
115
1.34k
    }
116
1.76k
  }
117
  
118
936k
  NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
119
936k
  return;
120
121
929
 capwap_found:
122
929
  ndpi_int_capwap_add_connection(ndpi_struct, flow);
123
929
}
124
125
static void ndpi_search_capwap(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
126
937k
{
127
937k
  struct ndpi_packet_struct *packet = &ndpi_struct->packet;
128
129
937k
  if(packet->udp && (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN))
130
937k
    ndpi_search_setup_capwap(ndpi_struct, flow);
131
937k
}
132
133
134
void init_capwap_dissector(struct ndpi_detection_module_struct *ndpi_struct)
135
11.4k
{
136
11.4k
  ndpi_register_dissector("CAPWAP", ndpi_struct,
137
11.4k
                     ndpi_search_capwap,
138
11.4k
                     NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
139
11.4k
                     1, NDPI_PROTOCOL_CAPWAP);
140
11.4k
}