/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 | } |