/* * coap.c * * Copyright (C) 2016 Sorin Zamfir * * This file is part of nDPI, an open source deep packet inspection * library based on the OpenDPI and PACE technology by ipoque GmbH * * nDPI is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * nDPI is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with nDPI. If not, see . * */ #include "ndpi_protocol_ids.h" #define NDPI_CURRENT_PROTO NDPI_PROTOCOL_COAP #include "ndpi_api.h" #include "ndpi_private.h" #define CON 0 #define NO_CON 1 #define ACK 2 #define RST 3 struct ndpi_coap_hdr { #if defined(__BIG_ENDIAN__) u_int8_t version:2, type:2, tkl:4; #elif defined(__LITTLE_ENDIAN__) u_int8_t tkl:4, type:2, version:2; #else #error "Missing endian macro definitions." #endif u_int8_t code; u_int16_t message_id; //if needed, remember to convert in host number }; /** VALUE OF -CODE- FIELD [0] = "Empty", [1] = "GET", [2] = "POST", [3] = "PUT", [4] = "DELETE", [65] = "2.01 Created", [66] = "2.02 Deleted", [67] = "2.03 Valid", [68] = "2.04 Changed", [69] = "2.05 Content", [128] = "4.00 Bad Request", [129] = "4.01 Unauthorized", [130] = "4.02 Bad Option", [131] = "4.03 Forbidden", [132] = "4.04 Not Found", [133] = "4.05 Method Not Allowed", [134] = "4.06 Not Acceptable", [140] = "4.12 Precondition Failed", [141] = "4.13 Request Entity Too Large", [143] = "4.15 Unsupported Content-Format", [160] = "5.00 Internal Server Error", [161] = "5.01 Not Implemented", [162] = "5.02 Bad Gateway", [163] = "5.03 Service Unavailable", [164] = "5.04 Gateway Timeout", [165] = "5.05 Proxying Not Supported" **/ /** * Entry point when protocol is identified. */ static void ndpi_int_coap_add_connection (struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { ndpi_set_detected_protocol(ndpi_struct,flow,NDPI_PROTOCOL_COAP,NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI); } /** * Check if the default port is acceptable * * UDP Port 5683 (mandatory) * UDP Ports 61616-61631 compressed 6lowPAN */ static int isCoAPport(u_int16_t port) { if((port == 5683) || ((port >= 61616) && (port <= 61631))) return(1); else return(0); } /** * Dissector function that searches CoAP headers */ static void ndpi_search_coap(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &ndpi_struct->packet; struct ndpi_coap_hdr * h = (struct ndpi_coap_hdr*) packet->payload; // search for udp packet if(packet->udp != NULL) { u_int16_t s_port = ntohs(packet->udp->source); u_int16_t d_port = ntohs(packet->udp->dest); if((!isCoAPport(s_port) && !isCoAPport(d_port)) || (packet->payload_packet_len < 4) ) { // header too short NDPI_EXCLUDE_PROTO(ndpi_struct, flow); return; } NDPI_LOG_DBG2(ndpi_struct, "calculating coap over udp\n"); // check values in header if(h->version == 1) { if(h->type == CON || h->type == NO_CON || h->type == ACK || h->type == RST ) { if(h->tkl < 8) { if((/* h->code >= 0 && */ h->code <= 5) || (h->code >= 65 && h->code <= 69) || (h->code >= 128 && h->code <= 134) || (h->code >= 140 && h->code <= 143) || (h->code >= 160 && h->code <= 165)) { NDPI_LOG_INFO(ndpi_struct, "found Coap\n"); ndpi_int_coap_add_connection(ndpi_struct,flow); return; } } } } } NDPI_EXCLUDE_PROTO(ndpi_struct, flow); return; } /** * Entry point for the ndpi library */ void init_coap_dissector (struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id) { ndpi_set_bitmask_protocol_detection ("COAP", ndpi_struct, *id, NDPI_PROTOCOL_COAP, ndpi_search_coap, NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD, SAVE_DETECTION_BITMASK_AS_UNKNOWN, ADD_TO_DETECTION_BITMASK); *id +=1; }