gnutella.c 9.94 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
#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"
17
18
19
#include "acsmx2.h"
#include "mapi_errors.h"

's avatar
committed
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#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
43
#include "log.h"
44
#include "trackflib.h"
's avatar
committed
45

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

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

61
#define GNUTELLA_STRING_NO 4
's avatar
committed
62

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

65
struct mapid_gnutella {
66
#ifndef __WITH_AHO__
67
68
	int *shift[GNUTELLA_STRING_NO];
	int *skip[GNUTELLA_STRING_NO];
69
70
71
#else
	ACSM_STRUCT2 *acsm;
#endif 
's avatar
committed
72
	struct list **gnulist;
's avatar
committed
73
74
};

's avatar
committed
75
int isGnutella(mapidflib_function_instance_t *,  unsigned char *, unsigned int );
76

77
static int gnutella_init(mapidflib_function_instance_t *instance, MAPI_UNUSED int fd)
's avatar
committed
78
{
79
	int i=0;
80
81
82
#ifdef __WITH_AHO__
	char *p;
#endif
's avatar
committed
83

's avatar
committed
84
	instance->internal_data = malloc(sizeof(struct mapid_gnutella));
's avatar
committed
85
86
87
88
89
90
91
	((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;
	}
92
#ifndef __WITH_AHO__
93
	for(i=0;i<GNUTELLA_STRING_NO;i++) {
94
95
96
		((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]));
	}
97
98
99
100
101
102
103
104
105
106
107
#else 
	((struct mapid_gnutella*)instance->internal_data)->acsm = acsmNew2();

	if(!(((struct mapid_gnutella*)instance->internal_data)->acsm)) {
		return MAPID_MEM_ALLOCATION_ERROR;
	}
	for(i = 0; i < GNUTELLA_STRING_NO; i++) {
		p = gnutella_strings[i];

		acsmAddPattern2(((struct mapid_gnutella*)instance->internal_data)->acsm, p, strlen(p), 1, 0, 100,(void*)p, i);
	}
's avatar
committed
108

109
110
	acsmCompile2(((struct mapid_gnutella*)instance->internal_data)->acsm);
#endif
's avatar
committed
111
112
113
	return 0;
}	

114
115
116
117
118
119
120
121
122
123
124
125
126
127
#ifdef __WITH_AHO__

static int global_index = -1;
static char *found = NULL;

	int gnutella_matchFound(void* id, int my_index, MAPI_UNUSED void *data) 
	{
  		global_index = my_index;
		found = (char *)id;

		return my_index;
	}
#endif

's avatar
committed
128
int isGnutella(mapidflib_function_instance_t *instance, unsigned char *pkt, unsigned int len)
's avatar
committed
129
{
130
#ifndef __WITH_AHO__
131
	int i=0;
132

133
	for(i=0;i<GNUTELLA_STRING_NO;i++) {
's avatar
committed
134
135
		if(len < strlen(gnutella_strings[i]))
				continue;
's avatar
committed
136

's avatar
committed
137
138
		if(len < 100) {
			if(mSearch((char *)(pkt), len, gnutella_strings[i], strlen(gnutella_strings[i]),
139
				((struct mapid_gnutella *)instance->internal_data)->skip[i],
's avatar
committed
140
141
142
143
144
145
146
147
148
149
				((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;
			}
150
151
		}
	}
152
153
154
155
156
157
158
159
160
161
162

#else
	global_index = -1;
	found = NULL;

	acsmSearch2(((struct mapid_gnutella*)instance->internal_data)->acsm, pkt, len, gnutella_matchFound, (void *)0);
	
	return global_index;

#endif
	
's avatar
committed
163
	return -1;
's avatar
committed
164
165
166
167

}

static int gnutella_process(mapidflib_function_instance_t *instance,
's avatar
committed
168
169
			MAPI_UNUSED  unsigned char* dev_pkt,
			 unsigned char* pkt,
's avatar
committed
170
171
172
173
			mapid_pkthdr_t* pkt_head)
{
	struct filters *temp = NULL, *prev = NULL, *new = NULL;
	int len = pkt_head->caplen;
's avatar
committed
174
	 unsigned char *p = NULL;
's avatar
committed
175
176
	struct timeval ts;

's avatar
committed
177
	struct list **gnulist = ((struct mapid_gnutella*)instance->internal_data)->gnulist;
's avatar
committed
178
179
180
181
182
183
	uint16_t ethertype;
	struct ether_header *ep = NULL;
	struct iphdr *iph = NULL;
	struct tcphdr *tcph = NULL;
	struct udphdr *udph = NULL;
	
's avatar
committed
184
185
	struct vlan_802q_header *vlan_header;

's avatar
committed
186
	unsigned int saddr, daddr;
's avatar
committed
187
188
	struct in_addr source, dest;

's avatar
committed
189
190
	uint16_t sp, dp;

's avatar
committed
191
	unsigned int hashval = 0;
's avatar
committed
192
	int i = 0;
193
194
195
196

	int pkt_color = pkt_head->color;

	if(pkt_color != 0 && pkt_color != GNUTELLA_COLOR) {
197
198
199
		return 0;
	}

's avatar
committed
200
201
202
203
204
205
206
	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
207
	len -= sizeof(struct ether_header);
's avatar
committed
208
209
210

	ethertype = ntohs(ep->ether_type);

's avatar
committed
211
212
213
214
215
216
	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
217
218
219
220
221
222
223
224
225
	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
226
227
228
229
230

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

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

's avatar
committed
232
	p += iph->ihl * 4;
's avatar
committed
233
234
	len -= iph->ihl * 4;

's avatar
committed
235
236
237
238
239
240
	if(iph->protocol == 6)	// TCP
	{
		tcph = (struct tcphdr *)p;
		
		sp = ntohs(tcph->source);
		dp = ntohs(tcph->dest);
's avatar
committed
241
242
243

		p += tcph->doff * 4;

's avatar
committed
244
		if((unsigned int)(p - pkt) == pkt_head->caplen) {
's avatar
committed
245
246
247
			return 0;
		}
		len -= tcph->doff * 4;
's avatar
committed
248
249
250
251
252
253
254
	}
	else if(iph->protocol == 17)	// UDP
	{
		udph = (struct udphdr *)p;

		sp = ntohs(udph->source);
		dp = ntohs(udph->dest);
's avatar
committed
255
256
257

		p += sizeof(struct udphdr);
		
's avatar
committed
258
		if((unsigned int)(p -pkt) == pkt_head->caplen) {
's avatar
committed
259
260
261
			return 0;
		}
		len -= sizeof(struct udphdr);
's avatar
committed
262
263
264
265
266
267
	}
	else
	{
		return 0;
	}

's avatar
committed
268
269
	gettimeofday(&ts, NULL);

's avatar
committed
270
	for(temp = gnulist[hashval]->head, prev = gnulist[hashval]->head; temp != NULL; prev = temp, temp = temp->next)
271
272
273
274
275
276
277
278
	{
		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
279
280
				gettimeofday(&(temp->ts), NULL);

's avatar
committed
281
				//printf("found same\n");
's avatar
committed
282
				if(iph->protocol == 6 && tcph->fin)	{
's avatar
committed
283
284
					if(temp == gnulist[hashval]->head) {
						gnulist[hashval]->head = temp->next;
's avatar
committed
285
						//printf("removing from list\n");
's avatar
committed
286
287
288
289
					}
					else {
						prev->next = temp->next;
					}
290
291
292
					temp->next = NULL;
					free(temp);
				}
's avatar
committed
293
					
294
			pkt_head->color = GNUTELLA_COLOR;
295
296
			return 1;
		}
's avatar
committed
297
298
		
		if(ts.tv_sec - temp->ts.tv_sec > 60) {
's avatar
committed
299
300
			if(temp == gnulist[hashval]->head) {
				gnulist[hashval]->head = temp->next;
's avatar
committed
301
302
303
304
305
306
307
			}
			else {
				prev->next = temp->next;
			}
			temp->next = NULL;
			free(temp);
		}
308
309
	}

's avatar
committed
310
	if((i = isGnutella(instance,pkt,len)) >= 0)
's avatar
committed
311
	{
's avatar
committed
312
		//return 1;
313
314
315
316
		new = (struct filters*)malloc(sizeof(struct filters));
		if(new == NULL)
			printf("new = NULL\n");
		
's avatar
committed
317
318
319
320
321
322
		new->protocol = iph->protocol;
		new->saddr = saddr;
		new->daddr = daddr;
		new->sp = sp;
		new->dp = dp;

323
#ifdef __TRACKFLIB_LOGGING__
324
	#ifndef __WITH_AHO__
's avatar
committed
325
		write_to_log("GNUTELLA", gnutella_strings[i], iph->protocol, source, sp, dest, dp, pkt, len); 
326
327
328
	#else
		write_to_log("GNUTELLA", found, iph->protocol, source, sp, dest, dp, pkt, len); 
	#endif
329
#endif
's avatar
committed
330
331
332
333
334
335
336
337
338
339
/*	
		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
340
		for(temp = gnulist[hashval]->head; temp != NULL; temp = temp->next)
's avatar
committed
341
342
343
344
345
346
347
348
		{
			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
349
				//printf("exists do not enter\n");
350
				pkt_head->color = GNUTELLA_COLOR;
's avatar
committed
351
352
353
354
				return 1;
			}
		}

's avatar
committed
355
356
		gettimeofday(&(new->ts), NULL);

's avatar
committed
357
358
		new->next = gnulist[hashval]->head;
		gnulist[hashval]->head = new;
359
360
	
		pkt_head->color = GNUTELLA_COLOR;
's avatar
committed
361
362
363
364
365
366
367
368
369
		return 1;
	}

	return 0;
}

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

's avatar
committed
372
373
  if(instance->internal_data != NULL){

's avatar
committed
374
375
376
377
378
379
380
381
	  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);
		  }
382
		  free(((struct mapid_gnutella*)instance->internal_data)->gnulist[i]);
's avatar
committed
383
	  }
384
385
386
387
388
389
390
391
#ifndef __WITH_AHO__
        for(i=0;i<GNUTELLA_STRING_NO;i++) {
                free(((struct mapid_gnutella*)instance->internal_data)->shift[i]);
                free(((struct mapid_gnutella*)instance->internal_data)->skip[i]);
        }
#else
        acsmFree2(((struct mapid_gnutella*)instance->internal_data)->acsm);
#endif
's avatar
committed
392

's avatar
committed
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
	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
408
409
  1, //filters packets
  MAPIOPT_NONE,
's avatar
committed
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  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;
};