/src/ndpi/src/lib/protocols/coap.c
Line | Count | Source |
1 | | /* |
2 | | * coap.c |
3 | | * |
4 | | * Copyright (C) 2016 Sorin Zamfir <sorin.zamfir@yahoo.com> |
5 | | * |
6 | | * This file is part of nDPI, an open source deep packet inspection |
7 | | * library based on the OpenDPI and PACE technology by ipoque GmbH |
8 | | * |
9 | | * nDPI is free software: you can redistribute it and/or modify |
10 | | * it under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation, either version 3 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * nDPI is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with nDPI. If not, see <http://www.gnu.org/licenses/>. |
21 | | * |
22 | | */ |
23 | | |
24 | | #include "ndpi_protocol_ids.h" |
25 | | |
26 | | #define NDPI_CURRENT_PROTO NDPI_PROTOCOL_COAP |
27 | | |
28 | | #include "ndpi_api.h" |
29 | | #include "ndpi_private.h" |
30 | | |
31 | | |
32 | 0 | #define CON 0 |
33 | 0 | #define NO_CON 1 |
34 | 0 | #define ACK 2 |
35 | 0 | #define RST 3 |
36 | | |
37 | | struct ndpi_coap_hdr |
38 | | { |
39 | | #if defined(__BIG_ENDIAN__) |
40 | | u_int8_t version:2, type:2, tkl:4; |
41 | | #elif defined(__LITTLE_ENDIAN__) |
42 | | u_int8_t tkl:4, type:2, version:2; |
43 | | #else |
44 | | #error "Missing endian macro definitions." |
45 | | #endif |
46 | | u_int8_t code; |
47 | | u_int16_t message_id; //if needed, remember to convert in host number |
48 | | }; |
49 | | |
50 | | |
51 | | /** |
52 | | VALUE OF -CODE- FIELD |
53 | | |
54 | | [0] = "Empty", |
55 | | [1] = "GET", |
56 | | [2] = "POST", |
57 | | [3] = "PUT", |
58 | | [4] = "DELETE", |
59 | | [65] = "2.01 Created", |
60 | | [66] = "2.02 Deleted", |
61 | | [67] = "2.03 Valid", |
62 | | [68] = "2.04 Changed", |
63 | | [69] = "2.05 Content", |
64 | | [128] = "4.00 Bad Request", |
65 | | [129] = "4.01 Unauthorized", |
66 | | [130] = "4.02 Bad Option", |
67 | | [131] = "4.03 Forbidden", |
68 | | [132] = "4.04 Not Found", |
69 | | [133] = "4.05 Method Not Allowed", |
70 | | [134] = "4.06 Not Acceptable", |
71 | | [140] = "4.12 Precondition Failed", |
72 | | [141] = "4.13 Request Entity Too Large", |
73 | | [143] = "4.15 Unsupported Content-Format", |
74 | | [160] = "5.00 Internal Server Error", |
75 | | [161] = "5.01 Not Implemented", |
76 | | [162] = "5.02 Bad Gateway", |
77 | | [163] = "5.03 Service Unavailable", |
78 | | [164] = "5.04 Gateway Timeout", |
79 | | [165] = "5.05 Proxying Not Supported" |
80 | | **/ |
81 | | |
82 | | |
83 | | /** |
84 | | * Entry point when protocol is identified. |
85 | | */ |
86 | | static void ndpi_int_coap_add_connection (struct ndpi_detection_module_struct *ndpi_struct, |
87 | | struct ndpi_flow_struct *flow) |
88 | 0 | { |
89 | 0 | ndpi_set_detected_protocol(ndpi_struct,flow,NDPI_PROTOCOL_COAP,NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI); |
90 | 0 | } |
91 | | |
92 | | /** |
93 | | * Check if the default port is acceptable |
94 | | * |
95 | | * UDP Port 5683 (mandatory) |
96 | | * UDP Ports 61616-61631 compressed 6lowPAN |
97 | | */ |
98 | 0 | static int isCoAPport(u_int16_t port) { |
99 | 0 | if((port == 5683) |
100 | 0 | || ((port >= 61616) && (port <= 61631))) |
101 | 0 | return(1); |
102 | 0 | else |
103 | 0 | return(0); |
104 | 0 | } |
105 | | |
106 | | /** |
107 | | * Dissector function that searches CoAP headers |
108 | | */ |
109 | | static void ndpi_search_coap(struct ndpi_detection_module_struct *ndpi_struct, |
110 | | struct ndpi_flow_struct *flow) |
111 | 0 | { |
112 | 0 | struct ndpi_packet_struct *packet = &ndpi_struct->packet; |
113 | 0 | struct ndpi_coap_hdr * h = (struct ndpi_coap_hdr*) packet->payload; |
114 | | |
115 | | // search for udp packet |
116 | 0 | if(packet->udp != NULL) { |
117 | 0 | u_int16_t s_port = ntohs(packet->udp->source); |
118 | 0 | u_int16_t d_port = ntohs(packet->udp->dest); |
119 | |
|
120 | 0 | if((!isCoAPport(s_port) && !isCoAPport(d_port)) |
121 | 0 | || (packet->payload_packet_len < 4) ) { // header too short |
122 | 0 | NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow); |
123 | 0 | return; |
124 | 0 | } |
125 | | |
126 | 0 | NDPI_LOG_DBG2(ndpi_struct, "calculating coap over udp\n"); |
127 | | |
128 | | // check values in header |
129 | 0 | if(h->version == 1) { |
130 | 0 | if(h->type == CON || h->type == NO_CON || h->type == ACK || h->type == RST ) { |
131 | 0 | if(h->tkl < 8) { |
132 | 0 | if((/* h->code >= 0 && */ h->code <= 5) || (h->code >= 65 && h->code <= 69) || |
133 | 0 | (h->code >= 128 && h->code <= 134) || (h->code >= 140 && h->code <= 143) || |
134 | 0 | (h->code >= 160 && h->code <= 165)) { |
135 | |
|
136 | 0 | NDPI_LOG_INFO(ndpi_struct, "found Coap\n"); |
137 | 0 | ndpi_int_coap_add_connection(ndpi_struct,flow); |
138 | 0 | return; |
139 | 0 | } |
140 | 0 | } |
141 | 0 | } |
142 | 0 | } |
143 | 0 | } |
144 | | |
145 | 0 | NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow); |
146 | 0 | return; |
147 | 0 | } |
148 | | |
149 | | /** |
150 | | * Entry point for the ndpi library |
151 | | */ |
152 | | void init_coap_dissector (struct ndpi_detection_module_struct *ndpi_struct) |
153 | 0 | { |
154 | 0 | register_dissector("COAP", ndpi_struct, |
155 | 0 | ndpi_search_coap, |
156 | 0 | NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD, |
157 | 0 | 1, NDPI_PROTOCOL_COAP); |
158 | 0 | } |
159 | | |