gnutella.c 8.24 KB
Newer Older
1
2
3
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
's avatar
committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include <string.h>
#include <errno.h>
#include "mapidflib.h"
#include "mapidlib.h"
#include "mapidevices.h"
#include "mapid.h"
#include "fhelp.h"
#include "debug.h"
#include "mapiipc.h"
#include "mstring.h"
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>

#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <time.h>

's avatar
committed
40
#include "log.h"
41
#include "trackflib.h"
's avatar
committed
42

's avatar
committed
43
44
45
46
47
48
struct filters {
	int protocol;
	unsigned int saddr;
	unsigned int daddr;
	uint16_t sp;
	uint16_t dp;
's avatar
committed
49
	struct timeval ts;
's avatar
committed
50
51
52
53
54
55
56
57
	struct filters *next;
};

struct list{
	struct filters *head;
	struct filters *tail;
};

's avatar
committed
58
#define HASHTABLESIZE 1024
59
#define GNUTELLA_STRING_NO 4
's avatar
committed
60

61
char *gnutella_strings[GNUTELLA_STRING_NO]={"GET /uri-res/N2R?urn:sha1:","GNUTELLA CONNECT/","GNUTELLA/", "Server: LimeWire/"};//,"GET /get/"};
's avatar
committed
62

63
struct mapid_gnutella {
64
65
	int *shift[GNUTELLA_STRING_NO];
	int *skip[GNUTELLA_STRING_NO];
's avatar
committed
66
	struct list **gnulist;
's avatar
committed
67
68
};

's avatar
committed
69
int isGnutella(mapidflib_function_instance_t *,  unsigned char *, unsigned int );
70

71
static int gnutella_init(mapidflib_function_instance_t *instance, MAPI_UNUSED int fd)
's avatar
committed
72
{
73
	int i=0;
's avatar
committed
74

's avatar
committed
75
	instance->internal_data = malloc(sizeof(struct mapid_gnutella));
's avatar
committed
76
77
78
79
80
81
82
	((struct mapid_gnutella*)instance->internal_data)->gnulist = (struct list**)malloc(sizeof(struct list *)*HASHTABLESIZE);
	memset(((struct mapid_gnutella*)instance->internal_data)->gnulist, 0, (sizeof(struct list*)*HASHTABLESIZE));
	for(i = 0; i < HASHTABLESIZE; i ++) {
		((struct mapid_gnutella*)instance->internal_data)->gnulist[i] = (struct list*)malloc(sizeof(struct list));
		((struct mapid_gnutella*)instance->internal_data)->gnulist[i]->head = NULL;
		((struct mapid_gnutella*)instance->internal_data)->gnulist[i]->tail = NULL;
	}
83
	for(i=0;i<GNUTELLA_STRING_NO;i++) {
84
85
86
		((struct mapid_gnutella*)instance->internal_data)->shift[i] = make_shift(gnutella_strings[i],strlen(gnutella_strings[i]));
		((struct mapid_gnutella*)instance->internal_data)->skip[i] = make_skip(gnutella_strings[i], strlen(gnutella_strings[i]));
	}
's avatar
committed
87

's avatar
committed
88
89
90
	return 0;
}	

's avatar
committed
91
int isGnutella(mapidflib_function_instance_t *instance, unsigned char *pkt, unsigned int len)
's avatar
committed
92
{
93
	int i=0;
's avatar
committed
94
	
95
	for(i=0;i<GNUTELLA_STRING_NO;i++) {
's avatar
committed
96
97
		if(len < strlen(gnutella_strings[i]))
				continue;
's avatar
committed
98

's avatar
committed
99
100
		if(len < 100) {
			if(mSearch((char *)(pkt), len, gnutella_strings[i], strlen(gnutella_strings[i]),
101
				((struct mapid_gnutella *)instance->internal_data)->skip[i],
's avatar
committed
102
103
104
105
106
107
108
109
110
111
				((struct mapid_gnutella *)instance->internal_data)->shift[i])) {
				return i;
			}
		}
		else {
			if(mSearch((char *)(pkt), 100, gnutella_strings[i], strlen(gnutella_strings[i]),
				((struct mapid_gnutella *)instance->internal_data)->skip[i],
				((struct mapid_gnutella *)instance->internal_data)->shift[i])){
				return i;
			}
112
113
		}
	}
's avatar
committed
114
	return -1;
's avatar
committed
115
116
117
118

}

static int gnutella_process(mapidflib_function_instance_t *instance,
's avatar
committed
119
120
			MAPI_UNUSED  unsigned char* dev_pkt,
			 unsigned char* pkt,
's avatar
committed
121
122
123
124
			mapid_pkthdr_t* pkt_head)
{
	struct filters *temp = NULL, *prev = NULL, *new = NULL;
	int len = pkt_head->caplen;
's avatar
committed
125
	 unsigned char *p = NULL;
's avatar
committed
126
127
	struct timeval ts;

's avatar
committed
128
	struct list **gnulist = ((struct mapid_gnutella*)instance->internal_data)->gnulist;
's avatar
committed
129
130
131
132
133
134
	uint16_t ethertype;
	struct ether_header *ep = NULL;
	struct iphdr *iph = NULL;
	struct tcphdr *tcph = NULL;
	struct udphdr *udph = NULL;
	
's avatar
committed
135
136
	struct vlan_802q_header *vlan_header;

's avatar
committed
137
	unsigned int saddr, daddr;
's avatar
committed
138
139
	struct in_addr source, dest;

's avatar
committed
140
141
	uint16_t sp, dp;

's avatar
committed
142
	unsigned int hashval = 0;
's avatar
committed
143
	int i = 0;
's avatar
committed
144
	
145
146
147
148
	if(color != 0 && color != GNUTELLA_COLOR) {
		return 0;
	}

's avatar
committed
149
150
151
152
153
154
155
	p = pkt;

	// lay the Ethernet header struct over the packet data
	ep = (struct ether_header *)p;

	// skip ethernet header
	p += sizeof(struct ether_header);
's avatar
committed
156
	len -= sizeof(struct ether_header);
's avatar
committed
157
158
159

	ethertype = ntohs(ep->ether_type);

's avatar
committed
160
161
162
163
164
165
	if(ethertype == ETHERTYPE_8021Q) {
		vlan_header = (struct vlan_802q_header*)p;
		ethertype = ntohs(vlan_header->ether_type);
		p += sizeof(struct vlan_802q_header);
	}
	
's avatar
committed
166
167
168
169
170
171
172
173
174
	if(ethertype != ETHERTYPE_IP) {
		return 0;
	}
	
	// IP header struct over the packet data;
	iph = (struct iphdr*)p;

	saddr = *((unsigned int *)&(iph->saddr));
	daddr = *((unsigned int *)&(iph->daddr));
's avatar
committed
175
176
177
178
179

	source.s_addr = (unsigned long int)iph->saddr;
	dest.s_addr = (unsigned long int)iph->daddr;

	hashval = (saddr + daddr) % HASHTABLESIZE;
's avatar
committed
180

's avatar
committed
181
	p += iph->ihl * 4;
's avatar
committed
182
183
	len -= iph->ihl * 4;

's avatar
committed
184
185
186
187
188
189
	if(iph->protocol == 6)	// TCP
	{
		tcph = (struct tcphdr *)p;
		
		sp = ntohs(tcph->source);
		dp = ntohs(tcph->dest);
's avatar
committed
190
191
192

		p += tcph->doff * 4;

's avatar
committed
193
		if((unsigned int)(p - pkt) == pkt_head->caplen) {
's avatar
committed
194
195
196
			return 0;
		}
		len -= tcph->doff * 4;
's avatar
committed
197
198
199
200
201
202
203
	}
	else if(iph->protocol == 17)	// UDP
	{
		udph = (struct udphdr *)p;

		sp = ntohs(udph->source);
		dp = ntohs(udph->dest);
's avatar
committed
204
205
206

		p += sizeof(struct udphdr);
		
's avatar
committed
207
		if((unsigned int)(p -pkt) == pkt_head->caplen) {
's avatar
committed
208
209
210
			return 0;
		}
		len -= sizeof(struct udphdr);
's avatar
committed
211
212
213
214
215
216
	}
	else
	{
		return 0;
	}

's avatar
committed
217
218
	gettimeofday(&ts, NULL);

's avatar
committed
219
	for(temp = gnulist[hashval]->head, prev = gnulist[hashval]->head; temp != NULL; prev = temp, temp = temp->next)
220
221
222
223
224
225
226
227
	{
		if(temp->protocol == iph->protocol &&
				(
				 (temp->saddr == saddr && temp->daddr == daddr && temp->sp == sp && temp->dp == dp)
				 ||
				 (temp->saddr == daddr && temp->daddr == saddr && temp->sp == dp && temp->dp == sp))
				)
		{
's avatar
committed
228
229
				gettimeofday(&(temp->ts), NULL);

's avatar
committed
230
				//printf("found same\n");
's avatar
committed
231
				if(iph->protocol == 6 && tcph->fin)	{
's avatar
committed
232
233
					if(temp == gnulist[hashval]->head) {
						gnulist[hashval]->head = temp->next;
's avatar
committed
234
						//printf("removing from list\n");
's avatar
committed
235
236
237
238
					}
					else {
						prev->next = temp->next;
					}
239
240
241
					temp->next = NULL;
					free(temp);
				}
's avatar
committed
242
					
243
244
			return 1;
		}
's avatar
committed
245
246
		
		if(ts.tv_sec - temp->ts.tv_sec > 60) {
's avatar
committed
247
248
			if(temp == gnulist[hashval]->head) {
				gnulist[hashval]->head = temp->next;
's avatar
committed
249
250
251
252
253
254
255
			}
			else {
				prev->next = temp->next;
			}
			temp->next = NULL;
			free(temp);
		}
256
257
	}

's avatar
committed
258
	if((i = isGnutella(instance,pkt,len)) >= 0)
's avatar
committed
259
	{
's avatar
committed
260
		//return 1;
261
262
263
264
		new = (struct filters*)malloc(sizeof(struct filters));
		if(new == NULL)
			printf("new = NULL\n");
		
's avatar
committed
265
266
267
268
269
270
		new->protocol = iph->protocol;
		new->saddr = saddr;
		new->daddr = daddr;
		new->sp = sp;
		new->dp = dp;

's avatar
committed
271
272
273
274
275
276
277
278
279
280
281
		write_to_log("GNUTELLA", gnutella_strings[i], iph->protocol, source, sp, dest, dp, pkt, len); 
/*	
		fprintf(fp, "%d---%s:%d -> ", new->protocol, inet_ntoa(source), sp);
		fprintf(fp, " %s:%d\t", inet_ntoa(dest), dp);
		for(i = 0; i < 100; i++) {
			fprintf(fp, "%c", p[i]);
		}
		fprintf(fp, "\n\n");

		//printf("on port %d -> %d\n", new->sp, new->dp);
*/
's avatar
committed
282
		for(temp = gnulist[hashval]->head; temp != NULL; temp = temp->next)
's avatar
committed
283
284
285
286
287
288
289
290
		{
			if(new->protocol == temp->protocol && (
					(new->saddr == temp->saddr && new->daddr == temp->daddr && new->sp == temp->sp && new->dp == temp->dp) 
					||
					(new->daddr == temp->saddr && new->saddr == temp->daddr && new->dp == temp->sp && new->sp == temp->dp)
					)
				)
			{
's avatar
committed
291
				//printf("exists do not enter\n");
's avatar
committed
292
293
294
295
				return 1;
			}
		}

's avatar
committed
296
297
		gettimeofday(&(new->ts), NULL);

's avatar
committed
298
299
		new->next = gnulist[hashval]->head;
		gnulist[hashval]->head = new;
's avatar
committed
300
301
302
303
304
305
306
307
308
309

		return 1;
	}

	return 0;
}

static int gnutella_cleanup(mapidflib_function_instance_t *instance) 
{
	struct filters *temp = NULL, *tmp = NULL;
's avatar
committed
310
311
	int i = 0;

's avatar
committed
312
313
  if(instance->internal_data != NULL){

's avatar
committed
314
315
316
317
318
319
320
321
322
323
	  for(i = 0; i < HASHTABLESIZE; i++) {
		  temp = ((struct mapid_gnutella*)instance->internal_data)->gnulist[i]->head;
		  
		  while(temp != NULL) {
			  tmp = temp;
			  temp = temp->next;
			  free(tmp);
		  }
	  }

's avatar
committed
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
	free(((struct mapid_gnutella*)instance->internal_data)->gnulist);
	free(instance->internal_data);
  }
  return 0;
}

static mapidflib_function_def_t finfo={
  "",
  "TRACK_GNUTELLA",
  "Searches for Gnutella packets\n",
  "",
  MAPI_DEVICE_ALL,
  MAPIRES_NONE,
  0, //shm size
  0, //modifies_pkts
339
340
  1, //filters packets
  MAPIOPT_NONE,
's avatar
committed
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  NULL,
  gnutella_init,
  gnutella_process,
  NULL, //get_result
  NULL, //reset
  gnutella_cleanup,
  NULL, //client_init
  NULL, //client_read_result
  NULL  //client_cleanup
};

mapidflib_function_def_t* gnutella_get_funct_info();
mapidflib_function_def_t* gnutella_get_funct_info() {
  return &finfo;
};