-
Notifications
You must be signed in to change notification settings - Fork 892
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Service Location Protocol dissector.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
- Loading branch information
Showing
82 changed files
with
2,956 additions
and
1,995 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,286 @@ | ||
/* | ||
* slp.c | ||
* | ||
* Copyright (C) 2023 - ntop.org | ||
* | ||
* 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 <http://www.gnu.org/licenses/>. | ||
* | ||
*/ | ||
|
||
#include "ndpi_protocol_ids.h" | ||
|
||
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_SERVICE_LOCATION | ||
|
||
#include "ndpi_api.h" | ||
|
||
PACK_ON | ||
struct slp_hdr_v1 { | ||
uint8_t version; | ||
uint8_t function; | ||
uint16_t length; | ||
uint8_t flags; | ||
uint8_t dialect; | ||
uint16_t lang_code; | ||
uint16_t encoding; | ||
uint16_t xid; | ||
} PACK_OFF; | ||
|
||
PACK_ON | ||
struct slp_hdr_v2 { | ||
uint8_t version; | ||
uint8_t function_id; | ||
PACK_ON struct { | ||
uint16_t high; | ||
uint8_t low; | ||
} PACK_OFF length; | ||
uint16_t flags; | ||
PACK_ON struct { | ||
uint16_t high; | ||
uint8_t low; | ||
} PACK_OFF next_ext_offset; | ||
uint16_t xid; | ||
uint16_t lang_tag_length; | ||
uint16_t lang_tag; | ||
} PACK_OFF; | ||
|
||
enum function_id { | ||
FID_UNKNOWN = 0, | ||
FID_SrvRqst = 1, | ||
FID_SrvRply = 2, | ||
FID_SrvReg = 3, | ||
FID_SrvDeReg = 4, | ||
FID_SrvAck = 5, | ||
FID_AttrRqst = 6, | ||
FID_AttrRply = 7, | ||
FID_DAAdvert = 8, | ||
FID_SrvTypeRqst = 9, | ||
FID_SrvTypeRply = 10, | ||
FID_MAX_v1 = 11, | ||
FID_SAAdvert = 11, // Not available in version 1 | ||
FID_MAX | ||
}; | ||
|
||
static void ndpi_int_slp_add_connection(struct ndpi_detection_module_struct *ndpi_struct, | ||
struct ndpi_flow_struct *flow) | ||
{ | ||
NDPI_LOG_INFO(ndpi_struct, "found Service Location Protocol\n"); | ||
|
||
ndpi_set_detected_protocol(ndpi_struct, flow, | ||
NDPI_PROTOCOL_SERVICE_LOCATION, NDPI_PROTOCOL_UNKNOWN, | ||
NDPI_CONFIDENCE_DPI); | ||
} | ||
|
||
static int slp_check_packet_length(struct ndpi_detection_module_struct *ndpi_struct, | ||
struct ndpi_flow_struct *flow, | ||
unsigned int packet_length) | ||
{ | ||
struct ndpi_packet_struct const * const packet = &ndpi_struct->packet; | ||
|
||
if (packet->payload_packet_len != packet_length) { | ||
NDPI_EXCLUDE_PROTO(ndpi_struct, flow); | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int slp_check_fid(struct ndpi_detection_module_struct *ndpi_struct, | ||
struct ndpi_flow_struct *flow, | ||
enum function_id fid, uint8_t slp_version) | ||
{ | ||
if (fid <= FID_UNKNOWN) { | ||
NDPI_EXCLUDE_PROTO(ndpi_struct, flow); | ||
return 1; | ||
} | ||
|
||
switch (slp_version) { | ||
case 0x01: | ||
if (fid >= FID_MAX_v1) { | ||
NDPI_EXCLUDE_PROTO(ndpi_struct, flow); | ||
return 1; | ||
} | ||
break; | ||
case 0x02: | ||
if (fid >= FID_MAX) { | ||
NDPI_EXCLUDE_PROTO(ndpi_struct, flow); | ||
return 1; | ||
} | ||
break; | ||
default: | ||
NDPI_EXCLUDE_PROTO(ndpi_struct, flow); | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int ndpi_search_slp_v1(struct ndpi_detection_module_struct *ndpi_struct, | ||
struct ndpi_flow_struct *flow) | ||
{ | ||
struct ndpi_packet_struct const * const packet = &ndpi_struct->packet; | ||
struct slp_hdr_v1 const * const hdr = (struct slp_hdr_v1 *)&packet->payload[0]; | ||
|
||
NDPI_LOG_DBG(ndpi_struct, "search Service Location Protocol v1\n"); | ||
|
||
if (packet->payload_packet_len < sizeof(*hdr)) { | ||
NDPI_EXCLUDE_PROTO(ndpi_struct, flow); | ||
return 1; | ||
} | ||
|
||
const unsigned int packet_length = ntohs(hdr->length); | ||
if (slp_check_packet_length(ndpi_struct, flow, packet_length) != 0) | ||
return 1; | ||
|
||
if (slp_check_fid(ndpi_struct, flow, hdr->function, hdr->version) != 0) | ||
return 1; | ||
|
||
ndpi_int_slp_add_connection(ndpi_struct, flow); | ||
return 0; | ||
} | ||
|
||
static void ndpi_dissect_slp_v1(struct ndpi_detection_module_struct *ndpi_struct, | ||
struct ndpi_flow_struct *flow) | ||
{ | ||
// No dissection support for SLP version 1. | ||
// TODO: Provide a PCAP file. | ||
} | ||
|
||
static int ndpi_search_slp_v2(struct ndpi_detection_module_struct *ndpi_struct, | ||
struct ndpi_flow_struct *flow) | ||
{ | ||
struct ndpi_packet_struct const * const packet = &ndpi_struct->packet; | ||
struct slp_hdr_v2 const * const hdr = (struct slp_hdr_v2 *)&packet->payload[0]; | ||
|
||
NDPI_LOG_DBG(ndpi_struct, "search Service Location Protocol v2\n"); | ||
|
||
if (packet->payload_packet_len < sizeof(*hdr)) { | ||
NDPI_EXCLUDE_PROTO(ndpi_struct, flow); | ||
return 1; | ||
} | ||
|
||
const unsigned int packet_length = (ntohs(hdr->length.high) << 8) | hdr->length.low; | ||
if (slp_check_packet_length(ndpi_struct, flow, packet_length) != 0) | ||
return 1; | ||
|
||
if (slp_check_fid(ndpi_struct, flow, hdr->function_id, hdr->version) != 0) | ||
return 1; | ||
|
||
ndpi_int_slp_add_connection(ndpi_struct, flow); | ||
return 0; | ||
} | ||
|
||
static void ndpi_dissect_slp_v2(struct ndpi_detection_module_struct *ndpi_struct, | ||
struct ndpi_flow_struct *flow) | ||
{ | ||
struct ndpi_packet_struct const * const packet = &ndpi_struct->packet; | ||
struct slp_hdr_v2 const * const hdr = (struct slp_hdr_v2 *)&packet->payload[0]; | ||
int url_offset = -1; // Can be either an offset to <URL String> or <URL Entry> | ||
int url_length_offset = -1; // length of <URL String> | ||
int url_entry_count_offset = -1; // amount of <URL Entry>'s | ||
|
||
switch (hdr->function_id) { | ||
case FID_SrvRply: | ||
url_entry_count_offset = 2; | ||
url_offset = 4; | ||
break; | ||
case FID_SrvReg: | ||
url_offset = 3; // contains always 1 <URL Entry> | ||
break; | ||
case FID_DAAdvert: | ||
url_length_offset = 6; | ||
url_offset = 8; | ||
break; | ||
case FID_SAAdvert: | ||
url_length_offset = 0; | ||
url_offset = 2; | ||
break; | ||
case FID_AttrRqst: | ||
url_length_offset = 4; | ||
url_offset = 6; | ||
break; | ||
case FID_SrvDeReg: | ||
url_offset = 7; // contains always 1 <URL Entry> | ||
break; | ||
} | ||
|
||
if (url_offset >= 0) { | ||
uint16_t url_length_or_count = 0; | ||
|
||
if (url_length_offset > 0 && packet->payload_packet_len >= sizeof(*hdr) + url_length_offset + 2) { | ||
// <URL String> | ||
url_length_or_count = ntohs(*(uint16_t *)&packet->payload[sizeof(*hdr) + url_length_offset]); | ||
if (packet->payload_packet_len >= sizeof(*hdr) + url_length_offset + 2 + url_length_or_count) { | ||
size_t len = ndpi_min(sizeof(flow->protos.slp.url[0]) - 1, url_length_or_count); | ||
flow->protos.slp.url_count = 1; | ||
strncpy(flow->protos.slp.url[0], (char *)&packet->payload[sizeof(*hdr) + url_offset + 2], len); | ||
flow->protos.slp.url[0][len] = 0; | ||
} | ||
} else if (url_entry_count_offset > 0 && packet->payload_packet_len >= sizeof(*hdr) + url_entry_count_offset + 2) { | ||
// TODO: <URL Entry>'s | ||
// Provide a PCAP file. | ||
//url_length_or_count = ntohs(*(uint16_t *)&packet->payload[sizeof(*hdr) + url_entry_count_offset]); | ||
} else if (packet->payload_packet_len >= sizeof(*hdr) + url_offset + 2) { | ||
url_length_or_count = ntohs(*(uint16_t *)&packet->payload[sizeof(*hdr) + url_offset]); // FID_SrvReg or FID_SrvDeReg | ||
if (packet->payload_packet_len >= sizeof(*hdr) + url_length_offset + 2 + url_length_or_count) { | ||
size_t len = ndpi_min(sizeof(flow->protos.slp.url[0]) - 1, url_length_or_count); | ||
flow->protos.slp.url_count = 1; | ||
strncpy(flow->protos.slp.url[0], (char *)&packet->payload[sizeof(*hdr) + url_offset + 2], len); | ||
flow->protos.slp.url[0][len] = 0; | ||
} | ||
} | ||
} | ||
} | ||
|
||
static void ndpi_search_slp(struct ndpi_detection_module_struct *ndpi_struct, | ||
struct ndpi_flow_struct *flow) | ||
{ | ||
struct ndpi_packet_struct const * const packet = &ndpi_struct->packet; | ||
|
||
NDPI_LOG_DBG(ndpi_struct, "search Service Location Protocol\n"); | ||
|
||
if (packet->payload_packet_len < 1) { | ||
NDPI_EXCLUDE_PROTO(ndpi_struct, flow); | ||
return; | ||
} | ||
|
||
switch (packet->payload[0]) { | ||
case 0x01: | ||
if (ndpi_search_slp_v1(ndpi_struct, flow) == 0) | ||
ndpi_dissect_slp_v1(ndpi_struct, flow); | ||
break; | ||
case 0x02: | ||
if (ndpi_search_slp_v2(ndpi_struct, flow) == 0) | ||
ndpi_dissect_slp_v2(ndpi_struct, flow); | ||
break; | ||
default: | ||
NDPI_EXCLUDE_PROTO(ndpi_struct, flow); | ||
break; | ||
} | ||
} | ||
|
||
void init_slp_dissector(struct ndpi_detection_module_struct *ndpi_struct, | ||
u_int32_t *id) | ||
{ | ||
ndpi_set_bitmask_protocol_detection("Service Location Protocol", ndpi_struct, *id, | ||
NDPI_PROTOCOL_SERVICE_LOCATION, | ||
ndpi_search_slp, | ||
NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD, | ||
SAVE_DETECTION_BITMASK_AS_UNKNOWN, | ||
ADD_TO_DETECTION_BITMASK); | ||
|
||
*id += 1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.