gnutella.c 8.18 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
	
	
's avatar
committed
146
147
148
149
150
151
152
	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
153
	len -= sizeof(struct ether_header);
's avatar
committed
154
155
156

	ethertype = ntohs(ep->ether_type);

's avatar
committed
157
158
159
160
161
162
	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
163
164
165
166
167
168
169
170
171
	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
172
173
174
175
176

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

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

's avatar
committed
178
	p += iph->ihl * 4;
's avatar
committed
179
180
	len -= iph->ihl * 4;

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

		p += tcph->doff * 4;

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

		sp = ntohs(udph->source);
		dp = ntohs(udph->dest);
's avatar
committed
201
202
203

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

's avatar
committed
214
215
	gettimeofday(&ts, NULL);

's avatar
committed
216
	for(temp = gnulist[hashval]->head, prev = gnulist[hashval]->head; temp != NULL; prev = temp, temp = temp->next)
217
218
219
220
221
222
223
224
	{
		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
225
226
				gettimeofday(&(temp->ts), NULL);

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

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

's avatar
committed
268
269
270
271
272
273
274
275
276
277
278
		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
279
		for(temp = gnulist[hashval]->head; temp != NULL; temp = temp->next)
's avatar
committed
280
281
282
283
284
285
286
287
		{
			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
288
				//printf("exists do not enter\n");
's avatar
committed
289
290
291
292
				return 1;
			}
		}

's avatar
committed
293
294
		gettimeofday(&(new->ts), NULL);

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

		return 1;
	}

	return 0;
}

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

's avatar
committed
309
310
  if(instance->internal_data != NULL){

's avatar
committed
311
312
313
314
315
316
317
318
319
320
	  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
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
	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
336
337
  1, //filters packets
  MAPIOPT_NONE,
's avatar
committed
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  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;
};