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 
28 #define NDPI_CAPWAP_CONTROL_PORT 5246
29 #define NDPI_CAPWAP_DATA_PORT    5247
30 
31 
ndpi_int_capwap_add_connection(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow)32 static void ndpi_int_capwap_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
33 					   struct ndpi_flow_struct *flow) {
34   ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_CAPWAP, NDPI_PROTOCOL_UNKNOWN);
35 }
36 
37 /* ************************************************** */
38 
ndpi_search_setup_capwap(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow)39 static void ndpi_search_setup_capwap(struct ndpi_detection_module_struct *ndpi_struct,
40 				     struct ndpi_flow_struct *flow) {
41   struct ndpi_packet_struct *packet = &flow->packet;
42   u_int16_t sport, dport;
43 
44   if(!packet->iph) {
45     NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
46     return;
47   }
48 
49   sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
50 
51   if((dport == NDPI_CAPWAP_CONTROL_PORT)
52      && (packet->iph->daddr == 0xFFFFFFFF)
53      && (packet->payload_packet_len >= 16)
54      && (packet->payload[0] == 0x0)
55      && (packet->payload[8] == 6 /* Mac len */)
56      )
57     goto capwap_found;
58 
59   if(((sport == NDPI_CAPWAP_CONTROL_PORT) || (dport == NDPI_CAPWAP_CONTROL_PORT))
60      && ((packet->payload[0] == 0x0) || (packet->payload[0] == 0x1))
61      ) {
62     u_int16_t msg_len, offset, to_add;
63 
64     if(packet->payload[0] == 0x0)
65       offset = 13, to_add = 13;
66     else
67       offset = 15, to_add = 17;
68 
69     if (packet->payload_packet_len >= offset + sizeof(u_int16_t)) {
70       msg_len = ntohs(*(u_int16_t*)&packet->payload[offset]);
71 
72       if((msg_len+to_add) == packet->payload_packet_len)
73         goto capwap_found;
74     }
75   }
76 
77   if(
78      (((dport == NDPI_CAPWAP_DATA_PORT) && (packet->iph->daddr != 0xFFFFFFFF)) || (sport == NDPI_CAPWAP_DATA_PORT))
79      && (packet->payload_packet_len >= 16)
80      && (packet->payload[0] == 0x0)
81      ) {
82     u_int8_t is_80211_data = (packet->payload[9] & 0x0C) >> 2;
83 
84 
85     if((sport == NDPI_CAPWAP_DATA_PORT) && (is_80211_data == 2 /* IEEE 802.11 Data */))
86       goto capwap_found;
87     else if(dport == NDPI_CAPWAP_DATA_PORT) {
88       u_int16_t msg_len = ntohs(*(u_int16_t*)&packet->payload[13]);
89 
90       if((packet->payload[8] == 1 /* Mac len */)
91 	 || (packet->payload[8] == 6 /* Mac len */)
92 	 || (packet->payload[8] == 4 /* Wireless len */)
93 	 || ((msg_len+15) == packet->payload_packet_len))
94 	goto capwap_found;
95     }
96   }
97 
98   NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
99   return;
100 
101  capwap_found:
102   ndpi_int_capwap_add_connection(ndpi_struct, flow);
103 }
104 
ndpi_search_capwap(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow)105 void ndpi_search_capwap(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
106 {
107   struct ndpi_packet_struct *packet = &flow->packet;
108 
109   if(packet->udp && (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN))
110     ndpi_search_setup_capwap(ndpi_struct, flow);
111 }
112 
113 
init_capwap_dissector(struct ndpi_detection_module_struct * ndpi_struct,u_int32_t * id,NDPI_PROTOCOL_BITMASK * detection_bitmask)114 void init_capwap_dissector(struct ndpi_detection_module_struct *ndpi_struct,
115 			   u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
116 {
117   ndpi_set_bitmask_protocol_detection("CAPWAP", ndpi_struct, detection_bitmask, *id,
118 				      NDPI_PROTOCOL_CAPWAP,
119 				      ndpi_search_capwap,
120 				      NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
121 				      SAVE_DETECTION_BITMASK_AS_UNKNOWN,
122 				      ADD_TO_DETECTION_BITMASK);
123 
124   *id += 1;
125 }
126