mapivindrv.c 8.72 KB
Newer Older
's avatar
committed
1
2
3
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
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include <pcap.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <netinet/in.h>
#include <dirent.h>
#include <time.h>
#include "mapi.h"
#include "mapidrv.h"
#include "mapidlib.h"
#include "printfstring.h"

#include "mapi_errors.h"
#include "mapidevices.h"
#include "flist.h"
#include "debug.h"

#define BUFSIZE 32768

's avatar
committed
31
#define NIC_PKTCAP_LEN 1514
's avatar
committed
32
33
34
35

__attribute__ ((constructor)) void init ();
__attribute__ ((destructor))  void fini ();

36
static void mapidrv_proc_loop(void *);
's avatar
committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

typedef struct vin_instance {
  pthread_t th_proc;
  char *name;
  int id;
  char *trace_dir;
  int listeners;
  //mapi_offline_device_status_t *offline_status;
  mapid_hw_info_t hwinfo;
  mapidlib_instance_t mapidlib;
} vin_instance_t;

static flist_t *devlist;

/* for mapidlib errorcode */
int 
mapidrv_get_errno(int devid,int fd)
{
  vin_instance_t *i=flist_get(devlist,devid);
  return mapid_get_errno(&i->mapidlib,fd);
}

int
60
mapidrv_apply_function (int devid,int fd, int flags, char* function, mapiFunctArg *fargs)
's avatar
committed
61
62
{
  vin_instance_t *i=flist_get(devlist,devid);
63
  return mapid_apply_function(&i->mapidlib,fd, function, fargs, flags);
's avatar
committed
64
65
66
67
68
69
70
71
72
}

int dir_filter(const struct dirent *a) {
	return (a->d_name[0] == '.')?0:1;
}

int mapidrv_add_device(const char *devname, MAPI_UNUSED int file,int devid, global_function_list_t *gflist, void *trace_dir)
{
	if (trace_dir == NULL) {
73
		DEBUG_CMD(Debug_Message("ERROR: mapivindrv - null trace directory specified"));
's avatar
committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
		return -1;
	}

  vin_instance_t *i=malloc(sizeof(vin_instance_t));
  
  i->name=strdup(devname);
  i->id=devid;
  i->trace_dir=trace_dir;
  i->listeners=0;
  i->th_proc=0;
  i->hwinfo.offline=0;
  i->hwinfo.gflist=gflist;
  i->hwinfo.pkt_drop=0;

88
  DEBUG_CMD(Debug_Message("Added device %d: %s", devid, devname));
's avatar
committed
89
90

  flist_append(devlist,devid,i);
91
92
93
94
95
#ifdef WITH_AUTHENTICATION
  mapid_init(&i->mapidlib, &i->hwinfo);
#else
  mapid_init(&i->mapidlib);
#endif
's avatar
committed
96
97
98
99
100
101
  return 0;
}

int mapidrv_delete_device(int devid)
{
  vin_instance_t *i=flist_remove(devlist,devid);
102
  DEBUG_CMD(Debug_Message("---deleting device %d", devid));
's avatar
committed
103
104

  if (i!=NULL) {
105
106
107
108
109
	  mapid_destroy(&i->mapidlib);
	  DEBUG_CMD(Debug_Message(" %s %s", i->name, i->trace_dir));
	  free(i->name);
	  free(i->trace_dir);
	  free(i);
's avatar
committed
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  }

  if (devlist->size == 0) {
	  mapid_destroy(NULL);
  }

  return 0;
}


static unsigned 
process_pkts(void *buf,unsigned len, vin_instance_t *i,MAPI_UNUSED int devid, int last)
{
  unsigned c = 0;
  int rlen = 0;
  struct pcap_pkthdr *rec;
  unsigned char *packet;
  mapid_pkthdr_t mhdr;

 rec = (struct pcap_pkthdr *) buf;
 rlen = rec->caplen+sizeof(struct pcap_pkthdr);

  while (c + rlen <= len) 
    {
      char *p = buf;
      buf = p + rlen;
      c += rlen;
      mhdr.caplen = rec->caplen;
      mhdr.ifindex = 0;
      mhdr.wlen = rec->len;
 
      mhdr.ts = (((unsigned long long)rec->ts.tv_sec)<<32)+(((rec->ts.tv_usec << 12) + (rec->ts.tv_usec<<8) - ((rec->ts.tv_usec*1825)>>5)) & 0xffffffff);
      
      // increase counter for packets seen so far
      i->hwinfo.pkts++;      
      
      packet=(unsigned char*)rec+(sizeof(struct pcap_pkthdr));

      if(last<BUFSIZE && c+rlen>len)
		i->hwinfo.offline=3;
150
151
152
153
154

#ifdef PRECLASSIFICATION
      mhdr.preclassification = 0;       /* process all packets */
#endif

's avatar
committed
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
      mapid_process_pkt(&i->mapidlib,(unsigned char*)rec,packet,&mhdr); 
      
      rec = (struct pcap_pkthdr *) buf;
      rlen = rec->caplen+sizeof(struct pcap_pkthdr);
    }

  return len - c;

}

static int process_dir(vin_instance_t *i, int devid, char *trace_dir) {
  struct dirent **dlist;
  int file_num, left=0, c, file, j;
  struct pcap_file_header head;
  char buf[BUFSIZE], *b=buf, *fname;

  file_num = scandir(trace_dir, &dlist, dir_filter, alphasort);

173
  DEBUG_CMD(Debug_Message("---processing directory '%s' (%d files)", trace_dir, file_num));
's avatar
committed
174
175
  
  if (file_num == -1) {
176
	DEBUG_CMD(Debug_Message("ERROR: in mapivindrv - scandir return -1"));
's avatar
committed
177
178
179
180
181
182
	return -1;
  }

  for (j=0; j < file_num; j++) {
	fname = printf_string("%s/%s", trace_dir, dlist[j]->d_name);
	if ((file=open(fname, O_LARGEFILE)) == -1) {
183
		DEBUG_CMD(Debug_Message("ERROR: in mapivindrv - error opening file %s", dlist[j]->d_name));
's avatar
committed
184
185
186
187
		perror("open");
		return -1;
	}
	
188
	DEBUG_CMD(Debug_Message("--- reading file %s", fname));
's avatar
committed
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
	//usleep(1000000);

  	c=read(file,&head,sizeof(struct pcap_file_header));
  	c=read(file,b,BUFSIZE);

  	while(c>0) {
    	left=process_pkts(buf,c+left,i,devid,c);
		pthread_yield();
		//nanosleep(&nap, NULL);
    	//Copy last bytes to beginning of buffer
    	memcpy(buf,b+c-left,left);
    	b=buf+left;
    	c=read(file,b,BUFSIZE-left);
  	}
	close(file);
	free(fname);
  }
  return 0;
}

static void
210
mapidrv_proc_loop(void *arg)
's avatar
committed
211
{
212
  int devid = *(int *)arg;
's avatar
committed
213
214
215
216
217
  int err;

  vin_instance_t *i=flist_get(devlist,devid);

  if(i==NULL) {
218
	DEBUG_CMD(Debug_Message("ERROR: MAPIDRV_PROC_LOOP - vin instance with id %d not in list", devid));
's avatar
committed
219
220
221
222
	return;
  }

  if ((err=pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) != 0) {
223
     DEBUG_CMD(Debug_Message("ERROR: pthread_setcanceltype failed (%s)", strerror(err)));
's avatar
committed
224
225
226
227
     return;
  }
  
  if ((err=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) != 0) {
228
     DEBUG_CMD(Debug_Message("ERROR: pthread_setcancelstate (%s) failed", strerror(err)));
's avatar
committed
229
230
231
     return;
  }

232
  DEBUG_CMD(Debug_Message("--- entering proc loop"));
's avatar
committed
233
234
235
236
237
238
239

  while (1) {
	  if (process_dir(i, devid, i->trace_dir) != 0)
		  break;
  }
 
  mapid_finished(&i->mapidlib);
240
  DEBUG_CMD(Debug_Message("Finished reading file, pkts %lld", i->hwinfo.pkts));
's avatar
committed
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
}


int
mapidrv_read_results (int devid,int fd, int fid, mapid_result_t** result)
{
  vin_instance_t *i=flist_get(devlist,devid);
  return mapid_read_results(&i->mapidlib,fd,fid,result);
}

mapid_funct_info_t* mapidrv_get_flow_functions(int devid,int fd)
{
  vin_instance_t *i=flist_get(devlist,devid);
  return mapid_get_flow_functions(&i->mapidlib,fd);
}

int mapidrv_get_flow_info(int devid,int fd,mapi_flow_info_t *info) {
  vin_instance_t *i=flist_get(devlist,devid);
  return mapid_get_flow_info(&i->mapidlib,fd,info);
}

int
mapidrv_create_offline_flow (MAPI_UNUSED int devid, MAPI_UNUSED int format,
	MAPI_UNUSED int fd, MAPI_UNUSED char **devtype)
{
266
	DEBUG_CMD(Debug_Message("ERROR: mapivindrv does not support offline flows"));
's avatar
committed
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
	return VINDRV_OFF_ERR;
}

int
mapidrv_create_flow (int devid, int fd, char **devtype)
{
  vin_instance_t *i=flist_get(devlist,devid);
  *devtype=MAPI_DEVICE_VIN;

  i->listeners++;
  i->hwinfo.link_type=DLT_EN10MB;
  i->hwinfo.cap_length=1500;
  i->hwinfo.devtype=MAPI_DEVICE_VIN;
  i->hwinfo.devid=i->id;
  i->hwinfo.pkts=0;

283
  DEBUG_CMD(Debug_Message("---Created flow %d for dev %s", fd, i->name));
's avatar
committed
284
285
286
287
288
289
290
291
292
293
294

  return mapid_add_flow(&i->mapidlib,fd,&i->hwinfo,NULL);
}

int
mapidrv_connect (int devid,int fd)
{
  vin_instance_t *i=flist_get(devlist,devid);

  if (i->th_proc == 0) {
  	//Start processing thread
295
  	if (pthread_create(&i->th_proc, NULL, (void *) mapidrv_proc_loop, (void *) &devid) != 0) {
296
297
   		DEBUG_CMD(Debug_Message("ERROR: pthread_create failed"));
	    	return VINDRV_PTHR_ERR;
's avatar
committed
298
  	}
299
300
301
302
	DEBUG_CMD(Debug_Message("---connect - created thread"));
  }
  else{
	DEBUG_CMD(Debug_Message("---connect - thread was running"));
's avatar
committed
303
304
305
306
307
308
309
310
  }
  
  return mapid_connect(&i->mapidlib,fd);
}

int 
mapidrv_start_offline_device(MAPI_UNUSED int devid)
{
311
	DEBUG_CMD(Debug_Message("ERROR: mapivindrv does not support offline flows"));
's avatar
committed
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
	return VINDRV_OFF_ERR;
}


int
mapidrv_close_flow (int devid,int fd)
{
  int err;
  vin_instance_t *i=flist_get(devlist,devid);
  
  if(i==NULL)
  	return VINDRV_DEVID_NOT_FOUND;

  i->listeners--;

  if (i->listeners == 0) {
  	  if ((err=pthread_cancel(i->th_proc))!=0) {
        if (!(i->hwinfo.offline>2 && err==ESRCH)) {
330
          DEBUG_CMD(Debug_Message("WARNING: Could not cancel thread for devid %d (%s)", devid, strerror(err)));
's avatar
committed
331
332
333
334
335
        }
      }
      
      if ((err=pthread_join(i->th_proc,NULL))!=0) {
        if (!(i->hwinfo.offline==1 && err==ESRCH)) {
336
          DEBUG_CMD(Debug_Message("WARNING: Could not join thread for devid %d (%s)", devid, strerror(err)));
's avatar
committed
337
338
339
        }
      }
	  i->th_proc = 0;
340
341
342
343
	  DEBUG_CMD(Debug_Message("---closing flow -- stopping thread"));
  }
  else{
	  DEBUG_CMD(Debug_Message("---closing flow -- NOT stopping thread"));
's avatar
committed
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  }

  return mapid_close_flow(&i->mapidlib,fd);
}

int 
mapidrv_load_library(MAPI_UNUSED int devid,char* lib)
{
  return mapid_load_library(lib);
}


__attribute__ ((constructor))
     void init ()
{
  devlist=malloc(sizeof(flist_t));
  flist_init(devlist);
361
  printf("VIN driver loaded [%s:%d]\n", __FILE__, __LINE__);
's avatar
committed
362
363
364
365
366
367
}

__attribute__ ((destructor))
     void fini ()
{
  free(devlist);
368
  printf("VIN driver unloaded [%s:%d]\n", __FILE__, __LINE__);
's avatar
committed
369
370
}