1 /*
2  * spotify.c
3  *
4  * Copyright (C) 2011-18 by ntop.org
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_SPOTIFY
27 
28 #include "ndpi_api.h"
29 
30 
ndpi_int_spotify_add_connection(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow,u_int8_t due_to_correlation)31 static void ndpi_int_spotify_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
32 					    struct ndpi_flow_struct *flow,
33 					    u_int8_t due_to_correlation)
34 {
35   ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SPOTIFY, NDPI_PROTOCOL_UNKNOWN);
36 }
37 
38 
ndpi_check_spotify(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow)39 static void ndpi_check_spotify(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
40 {
41   struct ndpi_packet_struct *packet = &flow->packet;
42   // const u_int8_t *packet_payload = packet->payload;
43   u_int32_t payload_len = packet->payload_packet_len;
44 
45   if(packet->udp != NULL) {
46     u_int16_t spotify_port = htons(57621);
47 
48     if((packet->udp->source == spotify_port)
49        && (packet->udp->dest == spotify_port)) {
50       if(payload_len >= 7) {
51 	if(memcmp(packet->payload, "SpotUdp", 7) == 0) {
52 	  NDPI_LOG_INFO(ndpi_struct, "found spotify udp dissector\n");
53 	  ndpi_int_spotify_add_connection(ndpi_struct, flow, 0);
54 	  return;
55 	}
56       }
57     }
58   } else if(packet->tcp != NULL) {
59 
60     if(payload_len >= 9 && packet->payload[0] == 0x00 && packet->payload[1] == 0x04 &&
61        packet->payload[2] == 0x00 && packet->payload[3] == 0x00&&
62        packet->payload[6] == 0x52 && (packet->payload[7] == 0x0e || packet->payload[7] == 0x0f) &&
63        packet->payload[8] == 0x50 ) {
64       NDPI_LOG_INFO(ndpi_struct, "found spotify tcp dissector\n");
65       ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SPOTIFY, NDPI_PROTOCOL_UNKNOWN);
66     }
67 
68 
69     if(packet->iph /* IPv4 Only: we need to support packet->iphv6 at some point */) {
70       /* if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) */ {
71 	/*
72 	Spotify
73 
74 	78.31.8.0 - 78.31.15.255 (78.31.8.0/22)
75 	AS29017
76 
77 	193.235.232.0 - 193.235.235.255 (193.235.232.0/22)
78 	AS29017
79 
80       194.132.196.0 - 194.132.199.255 (194.132.198.147/22)
81       AS43650
82 
83       194.132.176.0 - 194.132.179.255  (194.132.176.0/22)
84       AS43650
85 
86       194.132.162.0 - 194.132.163.255   (194.132.162.0/24)
87       AS43650
88       */
89 
90 	//printf("%08X - %08X\n", ntohl(packet->iph->saddr), ntohl(packet->iph->daddr));
91 
92     long src_addr = ntohl(packet->iph->saddr);
93     long dst_addr = ntohl(packet->iph->daddr);
94     long src_addr_masked_22 = src_addr & 0xFFFFFC00; // */22
95     long dst_addr_masked_22 = dst_addr & 0xFFFFFC00; // */22
96     long src_addr_masked_24 = src_addr & 0xFFFFFF00; // */24
97     long dst_addr_masked_24 = dst_addr & 0xFFFFFF00; // */24
98 
99 	if(   src_addr_masked_22 == 0x4E1F0800 /* 78.31.8.0 */
100 	   || dst_addr_masked_22 == 0x4E1F0800 /* 78.31.8.0 */
101 	   /* **** */
102 	   || src_addr_masked_22 == 0xC1EBE800 /* 193.235.232.0 */
103 	   || dst_addr_masked_22 == 0xC1EBE800 /* 193.235.232.0 */
104        /* **** */
105        || src_addr_masked_22 == 0xC284C400 /* 194.132.196.0 */
106        || dst_addr_masked_22 == 0xC284C400 /* 194.132.196.0 */
107        /* **** */
108        || src_addr_masked_24 == 0xC284A200 /* 194.132.162.0 */
109        || dst_addr_masked_24 == 0xC284A200 /* 194.132.162.0 */
110 	   ) {
111         NDPI_LOG_INFO(ndpi_struct, "found spotify via ip range\n");
112 	ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SPOTIFY, NDPI_PROTOCOL_UNKNOWN);
113 	  return;
114 	}
115       }
116     }
117   }
118 
119   NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
120 }
121 
ndpi_search_spotify(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow)122 void ndpi_search_spotify(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
123 {
124   struct ndpi_packet_struct *packet = &flow->packet;
125 
126   NDPI_LOG_DBG(ndpi_struct, "search spotify\n");
127 
128   /* skip marked packets */
129   if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SPOTIFY) {
130     if (packet->tcp_retransmission == 0) {
131       ndpi_check_spotify(ndpi_struct, flow);
132     }
133   }
134 }
135 
136 
init_spotify_dissector(struct ndpi_detection_module_struct * ndpi_struct,u_int32_t * id,NDPI_PROTOCOL_BITMASK * detection_bitmask)137 void init_spotify_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
138 {
139   ndpi_set_bitmask_protocol_detection("SPOTIFY", ndpi_struct, detection_bitmask, *id,
140 				      NDPI_PROTOCOL_SPOTIFY,
141 				      ndpi_search_spotify,
142 				      NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
143 				      SAVE_DETECTION_BITMASK_AS_UNKNOWN,
144 				      ADD_TO_DETECTION_BITMASK);
145 
146   *id += 1;
147 }
148 
149