mapicommd.c 22.3 KB
Newer Older
1
2
3
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
's avatar
committed
4
5
#include <stdio.h>
#include <stdlib.h>
's avatar
committed
6
7
8
#include <string.h>
#include <unistd.h>
#include <ctype.h>
's avatar
committed
9
10
#include <pthread.h>
#include <signal.h>
's avatar
committed
11
#include <getopt.h>
's avatar
committed
12
13
#include <sys/types.h>
#include <sys/socket.h>
's avatar
committed
14
#include <arpa/inet.h>
's avatar
committed
15
#include <sys/time.h>
's avatar
committed
16
#include <errno.h>
17
#include <fcntl.h>
's avatar
committed
18
19
#include "mapi.h"
#include "mapiipc.h"
's avatar
committed
20
#include "parseconf.h"
21
#include "mapi_errors.h"
's avatar
committed
22
#include "mapilibhandler.h"
's avatar
committed
23
#include "printfstring.h"
24
25
#include "debug.h"
#include "log.h"
's avatar
committed
26

's avatar
committed
27
#define MAXPENDING 500    /* Maximum outstanding connection requests */
's avatar
committed
28

's avatar
committed
29
int service_count;
's avatar
committed
30
int dimapi_port;
31

's avatar
committed
32
int log_fd_info = -1;	// support for logging to file
's avatar
committed
33

's avatar
committed
34
35
static char daemonize = 0;

36
37
38
39
40
#ifdef DIMAPISSL
struct overload *inst = NULL;
SSL_CTX *ctx;
#endif

41
extern void set_agent();
's avatar
committed
42
43
44
void *handle_request(void *);
int die(char *msg);
int getfid(struct dmapiipcbuf *dbuf);
45
void mapicommd_shutdown(int exit_value);
46

's avatar
committed
47
48
static void print_usage (const char *name) {
	printf ("Usage: %s [OPTIONS]\n", name);
49
50
51
	printf("  -d, --daemon		Run as daemon\n");
	printf("  -s, --syslog		Logging to syslog\n");
	printf("  -h, --help		Display this message\n");
's avatar
committed
52
53
}

's avatar
committed
54
static void parse_arguments (int argc, char **argv) {
55

's avatar
committed
56
	int c;
57
	static const char optstring[] = "dhs";
's avatar
committed
58
59
	static const struct option longopts[] = {
		{"daemon", no_argument, NULL, 'd'},
60
		{"syslog", no_argument, NULL, 's'},
's avatar
committed
61
62
63
		{"help", no_argument, NULL, 'h'},
		{NULL, 0, NULL, 0}
	};
's avatar
committed
64

's avatar
committed
65
66
67
68
69
	while ((c = getopt_long (argc, argv, optstring, longopts, NULL)) != -1) {
		switch (c) {
			case 'd':
				daemonize = 1;
				break;
70
71
72
			case 's':	// logging to syslog enabled
				log_to_syslog = 1;
				break;
's avatar
committed
73
74
75
76
77
78
79
			case 'h':
			case '?':
			default:
				print_usage(argv[0]);
			exit(EXIT_FAILURE);
		}
	}
's avatar
committed
80
81
82
83
84
85
86
87
88
89
90
}

static int continue_as_daemon() {
	int nullfd;

	printf("Closing stdin, stdout, stderr and going into background.\n");

	switch(fork()) {
		case 0: 
			break;
		case -1:
91
			DEBUG_CMD(Debug_Message("ERROR: fork() failed %d - %s", errno, strerror(errno)));
's avatar
committed
92
93
94
95
96
97
			return EXIT_FAILURE;
			break;
		default:
			_exit(0);
			break;
	}
's avatar
typo    
committed
98
	if(setsid() == -1) {
99
		DEBUG_CMD(Debug_Message("ERROR: setsid() failed %d - %s", errno, strerror(errno)));
's avatar
committed
100
101
		return EXIT_FAILURE;
	}
102

's avatar
committed
103
	setpgrp();
104

's avatar
committed
105
106
107
108
	switch(fork()) {
		case 0: 
			break;
		case -1:
109
			DEBUG_CMD(Debug_Message("ERROR: fork() failed %d - %s", errno, strerror(errno)));
's avatar
committed
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
			return EXIT_FAILURE;
			break;
		default:
			_exit(0);
			break;
	}
	
	chdir("/");

	nullfd = open("/dev/null", O_RDONLY);
	dup2(nullfd, STDIN_FILENO);
	close(nullfd);
	nullfd = open("/dev/null", O_WRONLY);
	dup2(nullfd, STDOUT_FILENO);
	dup2(nullfd, STDERR_FILENO);
	close(nullfd);
	
	return EXIT_SUCCESS;
}

int main (int argc, char *argv[]){
131

's avatar
committed
132
133
134
135
	int serv_sock = 0;
	int new_sock = 0;      /* client's socket descriptor (from connect()) */
	socklen_t clnt_len;    /* length of client address data structure */
	int yes=1;
136
	char* mapi_conf;
137
	long file_size;
138
	pthread_t chld_thr;
's avatar
committed
139
140
	struct sockaddr_in serv_addr;
	struct sockaddr_in clnt_addr;
141

142
	parse_arguments (argc, argv);
's avatar
committed
143

's avatar
committed
144
#ifdef DIMAPISSL
145
146
147
148
149
	SSL *con = NULL;
	OpenSSL_add_all_algorithms();	// adds all algorithms to the table (digests and ciphers)
					// OpenSSL keeps an internal table of digest algorithms and ciphers
	SSL_library_init();		// registers the available ciphers and digests
	SSL_load_error_strings();	// registers the error strings for all libcrypto functions and libssl
150
#endif
151
152
153
154

	signal (SIGTERM, mapicommd_shutdown);
	signal (SIGQUIT, mapicommd_shutdown);
	signal (SIGINT, mapicommd_shutdown);
155

156
	mapi_conf = printf_string( CONFDIR"/"CONF_FILE );
157

158
	printf("using %s\n", mapi_conf);
159
160
#ifdef DIMAPISSL
	printf("SSL enabled\n");
161
#endif
162
	log_level = get_log_level(mapi_conf);	// get log level from mapi.conf	
163

164
	if(log_to_syslog)	// logging to syslog is enabled
165
		open_syslog(log_level, "MAPICOMMD");
166
	
167
168
169
170
	log_to_file = set_logging_to_file(mapi_conf, &log_fd_info, &log_fd_debug);	// support for logging to file
	
	if(log_to_syslog == 0 && log_to_file == 0)
		log_level = LOGGING_DISABLED;
171

172
	if(pc_load (mapi_conf))
173
174
		dimapi_port = atoi(pc_get_param(pc_get_category(""), "dimapi_port"));
	else{
's avatar
committed
175
		printf("Error: cannot load mapi.conf file.\n");
176
		mapicommd_shutdown(1);
177
	}
's avatar
committed
178
179
	free(mapi_conf);
	pc_close();
's avatar
committed
180

181
182
183
184
	if(log_to_syslog == 0)	printf("logging to syslog: disabled\n");
	else			printf("logging to syslog: enabled - LogLevel: %d\n", log_level);

	if(log_to_file){
185
186
		daemon_started(log_fd_info, "MAPICOMMD", daemonize, 0);
		daemon_started(log_fd_debug, "MAPICOMMD", daemonize, 0);
187
188
189
190
191
192
193
194
195
	}
	
	if(log_to_syslog){
		log_message("MAPICOMMD was started %s", daemonize ? " ( is running as daemon )" : "");
#ifdef DIMAPISSL
		log_message("SSL enabled");
#endif
	}

's avatar
committed
196
	if ((serv_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
's avatar
committed
197
		die("Unexpected error on socket()");
198
		mapicommd_shutdown(-1);
's avatar
committed
199
	}
's avatar
committed
200

201
202
203
	memset(&serv_addr, 0, sizeof serv_addr);

	serv_addr.sin_family = AF_INET;
's avatar
committed
204
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
's avatar
committed
205
	serv_addr.sin_port = htons(dimapi_port);
's avatar
committed
206

's avatar
committed
207
208
209
#ifdef DIMAPISSL
	if ((ctx=SSL_CTX_new(SSLv3_server_method())) == NULL) {
		ERR_print_errors_fp(stderr);
's avatar
committed
210
		return -1;
's avatar
committed
211
	}
212
	if (SSL_CTX_use_certificate_file(ctx, CONFDIR"/"MAPICOMMD_SSL_CERT_FILE, SSL_FILETYPE_PEM) <= 0) {
's avatar
committed
213
		ERR_print_errors_fp(stderr);
's avatar
committed
214
		return -1;
's avatar
committed
215
	}
216

217
	if (SSL_CTX_use_PrivateKey_file(ctx, CONFDIR"/"MAPICOMMD_SSL_KEY_FILE, SSL_FILETYPE_PEM) <= 0) {
's avatar
committed
218
		ERR_print_errors_fp(stderr);
's avatar
committed
219
		return -1;
's avatar
committed
220
221
222
	}
#endif

's avatar
committed
223
224
225
226
227
228
229
230
231
	/* DANGEROUS, but useful for debugging, so leave it for now */
	if (setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
		close(serv_sock);
		die("Unexpected error on setsockopt()");
	}

	if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof serv_addr) == -1) {
		close(serv_sock);
		die("Unexpected error on bind()");
232
		mapicommd_shutdown(-1);
's avatar
committed
233
234
235
236
237
238
239
	}

	/* queue max 5 connections */
	if (listen(serv_sock, MAXPENDING) == -1) {
		shutdown(serv_sock, SHUT_RDWR);
		close(serv_sock);
		die("Unexpected error on listen()");
240
		mapicommd_shutdown(-1);
's avatar
committed
241
242
	}

243
	set_agent();
's avatar
committed
244

's avatar
committed
245
246
	if(daemonize) continue_as_daemon();

's avatar
committed
247
248
249
	while(1) {

		clnt_len = sizeof clnt_addr;
's avatar
committed
250
		if ((new_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_len)) == -1) {
's avatar
committed
251
			die("Unexpected error on accept()");
's avatar
committed
252
253
			continue;
		}
's avatar
committed
254

's avatar
committed
255
256
257
#ifdef DIMAPISSL
		if ((con=SSL_new(ctx)) == NULL) {
			ERR_print_errors_fp(stderr);
's avatar
committed
258
			continue;
's avatar
committed
259
260
261
		}
		if (SSL_set_fd(con, new_sock) == 0) {
			ERR_print_errors_fp(stderr);
's avatar
committed
262
			continue;
's avatar
committed
263
264
265
		}
		if (SSL_accept(con) <= 0) {
			ERR_print_errors_fp(stderr);
's avatar
committed
266
			continue;
's avatar
committed
267
268
		}
#endif
's avatar
committed
269
		printf("<*> got connection from %s\n", inet_ntoa(clnt_addr.sin_addr));
270

271
		if(log_to_file){
272
273
274
275
276
			file_size = acquire_write_lock(log_fd_info);
			write_to_file(log_fd_info, "MAPICOMMD: mapicommd got connection from * %s * at ", inet_ntoa(clnt_addr.sin_addr));
			write_date(log_fd_info);
			write_newline(log_fd_info, "\n");
			release_write_lock(log_fd_info, file_size);
277
		}
278
279
		if(log_to_syslog)
			log_message("mapicommd got connection from * %s *", inet_ntoa(clnt_addr.sin_addr));
's avatar
committed
280
#ifdef DIMAPISSL
281
		inst = (struct overload *)malloc(sizeof(struct overload));
's avatar
committed
282
283
		inst->connection = con;
		inst->sock = new_sock;
284

285
		if (pthread_create(&chld_thr, NULL, handle_request, (void *) inst) != 0){
's avatar
committed
286
287
288
			die("pthread_create() failed");
			continue;
		}
289
#else
290
		if (pthread_create(&chld_thr, NULL, handle_request, (void *) &new_sock) != 0) {
291
			die("pthread_create() failed");
's avatar
committed
292
293
			continue;
		}
's avatar
committed
294
#endif
295
	} /* while (1) */
's avatar
committed
296
297
298
299
	return 0; /* never reached */
}

void *handle_request(void *arg) {
's avatar
committed
300
301
302
303
#ifdef DIMAPISSL
	SSL *con ;
	con = ((struct overload*)arg)->connection;
	int sock = ((struct overload*)arg)->sock;
304
#else
305
	int sock = *(int *)arg;
306
#endif
's avatar
committed
307
308
309
	int recv_bytes;
	struct dmapiipcbuf *dbuf=NULL;
	int mapid_result;
's avatar
committed
310
	mapi_results_t *result;
's avatar
committed
311
312
313
314
315
	int i;
	int *active_flows = NULL;
	int ac_fl_size=0;
	mapi_function_info_t funct_info;
	mapi_flow_info_t flow_info;
316
	mapi_device_info_t device_info;
's avatar
committed
317
318
	struct timeval tv; /*used for timestamping results when produced */
	struct mapipkt *pkt;
's avatar
committed
319
	int errno;
320
	char errorstr[MAPI_ERRORSTR_LENGTH], str[30];
321
	long file_size;
322
323
	struct mapi_stat stats;
	char* dev;
's avatar
committed
324
325
326
#ifdef RECONNECT
	int flag = 0;
#endif
's avatar
committed
327
328

	/* Guarantees that thread resources are deallocated upon return */
329
	pthread_detach(pthread_self());
's avatar
committed
330
	dbuf = (struct dmapiipcbuf *)malloc(sizeof(struct dmapiipcbuf));
331

's avatar
committed
332
#ifdef DIMAPISSL
333
	DEBUG_CMD(Debug_Message("<+> new thread %lu, socket number = %d", pthread_self(),(int) con));
334
	sprintf(str, "%d", (int) con);
335
336
337
338
339

	if(inst != NULL){
		free(inst);
		inst = NULL;
	}
340
#else
341
	DEBUG_CMD(Debug_Message("<+> new thread %lu, socket number = %d", pthread_self(), sock));
342
	sprintf(str, "%d", sock);
's avatar
committed
343
#endif
344
	if(log_to_file){
345
346
347
		file_size = acquire_write_lock(log_fd_info);
		write_to_file(log_fd_info, "MAPICOMMD: new thread %lu, socket number %s\n\n", pthread_self(), str);
		release_write_lock(log_fd_info, file_size);
348
	}
349

's avatar
committed
350
351
	while(1) {

's avatar
committed
352
353
#ifdef DIMAPISSL
		recv_bytes = SSL_readn(con,dbuf,BASIC_SIZE);
354
#else
's avatar
committed
355
356
		recv_bytes=readn(sock, dbuf, BASIC_SIZE);
#endif
's avatar
committed
357
		if (recv_bytes == 0) { // the peer has gone
358
359
360
			DEBUG_CMD(Debug_Message("Peer has gone"));

			if(log_to_file){
361
362
363
364
365
				file_size = acquire_write_lock(log_fd_info);
				write_to_file(log_fd_info, "MAPICOMMD: Peer has gone at ");
				write_date(log_fd_info);
				write_newline(log_fd_info, "\n");
				release_write_lock(log_fd_info, file_size);
366
			}
's avatar
committed
367
368
369
370
371
372
373
374
			break;
		}
		else if (recv_bytes == -1) {
			die("recv()");
			break;
		}

		if (dbuf->length > DIMAPI_DATA_SIZE) {
375
			DEBUG_CMD(Debug_Message("WARNING: Ignoring invalid message"));
376
			
377
			if(log_to_file){
378
379
380
				file_size = acquire_write_lock(log_fd_info);
				write_to_file(log_fd_info, "MAPICOMMD: Warning - Ignoring invalid message\n");
				release_write_lock(log_fd_info, file_size);
381
			}
's avatar
committed
382
383
			continue;
		}
's avatar
committed
384

's avatar
committed
385
		if (dbuf->length-BASIC_SIZE>0) {
's avatar
committed
386
387
#ifdef DIMAPISSL
			recv_bytes = SSL_readn(con,(char *)dbuf+BASIC_SIZE,dbuf->length-BASIC_SIZE);
388
#else
's avatar
committed
389
			recv_bytes=readn(sock, (char*)dbuf+BASIC_SIZE, dbuf->length-BASIC_SIZE);
's avatar
committed
390
#endif
's avatar
committed
391
			if (recv_bytes == 0) { // the peer has gone
392
393
394
				DEBUG_CMD(Debug_Message("Peer has gone"));

				if(log_to_file){
395
396
397
398
399
					file_size = acquire_write_lock(log_fd_info);
					write_to_file(log_fd_info, "MAPICOMMD: Peer has gone at ");
					write_date(log_fd_info);
					write_newline(log_fd_info, "\n");
					release_write_lock(log_fd_info, file_size);
400
				}
's avatar
committed
401
402
403
404
405
406
407
				break;
			}
			else if (recv_bytes == -1) {
				die("recv()");
				break;
			}
		}
's avatar
committed
408
409
410
411
412
413
414
415
416
417
418
#ifdef RECONNECT

		if(dbuf->cmd == IGNORE_SLEEP){	// ignore some messages
			flag = 1;
			continue;
		}

		if(dbuf->cmd == IGNORE_NOTIFY){	// accept all kind of messages
			flag = 0;
			continue;
		}
419

's avatar
committed
420
421
422
		if(dbuf->cmd != CREATE_FLOW && dbuf->cmd != APPLY_FUNCTION && dbuf->cmd != CONNECT && dbuf->cmd != AUTHENTICATE && flag == 1)
			continue;
#endif
's avatar
committed
423
424
		switch(dbuf->cmd) {
			case CREATE_FLOW:
's avatar
committed
425
				mapid_result = mapi_create_flow(dbuf->data);
's avatar
committed
426
				fprintf(stdout,"CREATE_FLOW (%s, %d)\n",dbuf->data, mapid_result);
427
				mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, mapid_result);
's avatar
committed
428
				if(mapid_result <0) {
's avatar
committed
429
					dbuf->cmd = ERROR_ACK;
430
					mapi_read_error(&errno, errorstr);
's avatar
committed
431
432
433
					memcpy(dbuf->data, &errno, sizeof(int));
				}
				else {
's avatar
committed
434
					dbuf->cmd = CREATE_FLOW_ACK;
's avatar
committed
435
436
437
438
					memcpy(dbuf->data, &mapid_result, sizeof(int));
					active_flows = realloc(active_flows,(ac_fl_size+1)*sizeof(int));
					active_flows[ac_fl_size++] = mapid_result;
				}
's avatar
committed
439
440
441
442
443
				dbuf->length = BASIC_SIZE+sizeof(int);
				break;
			case CLOSE_FLOW:
				fprintf(stdout,"CLOSE_FLOW (%d)\n",dbuf->fd);
				mapid_result = mapi_close_flow(dbuf->fd);
444
				mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, mapid_result);
's avatar
committed
445
446
447
448
				if(!mapid_result){
					for(i=0;i<ac_fl_size;++i){
						if(active_flows[i] == dbuf->fd){
							active_flows[i] = active_flows[--ac_fl_size];
's avatar
committed
449
							active_flows = realloc(active_flows,ac_fl_size*sizeof(int));
's avatar
committed
450
451
452
						}
					}
				}
's avatar
committed
453
				//no need to send responce
's avatar
committed
454
455
456
457
				break;
			case CONNECT:
				fprintf(stdout,"CONNECT (%d)",dbuf->fd);
				mapid_result = mapi_connect(dbuf->fd);
458
				mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, mapid_result);
's avatar
committed
459
460
461
				if(mapid_result >= 0){
					dbuf->cmd = CONNECT_ACK;
					fprintf(stdout," OK\n");
's avatar
committed
462
					dbuf->length = BASIC_SIZE;
's avatar
committed
463
464
465
				}
				else{
					dbuf->cmd = ERROR_ACK;
466
					mapi_read_error(&errno, errorstr);
's avatar
committed
467
					memcpy(dbuf->data, &errno, sizeof(int));
's avatar
committed
468
					fprintf(stdout," FAILED\n");
's avatar
committed
469
					dbuf->length = BASIC_SIZE+sizeof(int);
's avatar
committed
470
471
472
				}
				break;
			case APPLY_FUNCTION:
's avatar
committed
473
				fprintf(stdout,"APPLY_FUNCTION\n");
's avatar
committed
474
				if((( dbuf->fid = getfid(dbuf))!=-1)){
475
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, 0);
's avatar
committed
476
					dbuf->cmd = APPLY_FUNCTION_ACK;
's avatar
committed
477
					dbuf->length = BASIC_SIZE;
's avatar
committed
478
479
				}
				else{
480
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
's avatar
committed
481
					dbuf->cmd = ERROR_ACK;
482
					mapi_read_error(&errno, errorstr);
's avatar
committed
483
484
					memcpy(dbuf->data, &errno, sizeof(int));
					dbuf->length = BASIC_SIZE+sizeof(int);
's avatar
committed
485
486
487
				}
				break;
			case READ_RESULT:
's avatar
committed
488
489
490
491
492
493
494
495
496
497
#ifdef RECONNECT
				if (mapi_is_sensor_down(dbuf->fd)==1) {
					printf("SENSOR DOWN\n");
					int local_err=MAPI_READ_RESULT_RECONNECTION;
					dbuf->cmd = ERROR_ACK;
					memcpy(dbuf->data, &local_err, sizeof(int));
					dbuf->length = BASIC_SIZE + sizeof(int);
					break;
				}
#endif
498
				result = mapi_read_results(dbuf->fd,dbuf->fid);
499
				if(result!=NULL && result->size < DIMAPI_DATA_SIZE){
's avatar
committed
500
					dbuf->cmd = READ_RESULT_ACK;
's avatar
committed
501
502
503
					dbuf->timestamp = result->ts;
					memcpy(dbuf->data, result->res, result->size);
					dbuf->length = BASIC_SIZE + result->size;
's avatar
committed
504
505
506
				}
				else{
					fprintf(stdout,"mapi_read_results failed...\n");
507
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
's avatar
committed
508
					dbuf->cmd = ERROR_ACK;
509
					mapi_read_error(&errno, errorstr);
's avatar
committed
510
511
					memcpy(dbuf->data, &errno, sizeof(int));
					dbuf->length = BASIC_SIZE+sizeof(int);
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
#ifdef RECONNECT
					if(errno == MAPI_READ_RESULT_RECONNECTION){	// mapid is down ...
#ifdef DIMAPISSL
						SSL_write(con, dbuf, dbuf->length);
#else
						send(sock, dbuf, dbuf->length, 0);
#endif						// dummy read result operation to enable reconnection mechanism
						result = mapi_read_results(dbuf->fd, dbuf->fid);
						
						if(result != NULL && result->size < DIMAPI_DATA_SIZE){
							dbuf->cmd = READ_RESULT_ACK_RECONNECT;
							dbuf->timestamp = result->ts;
							memcpy(dbuf->data, result->res, result->size);
							dbuf->length = BASIC_SIZE + result->size;
						}
						else{
							dbuf->cmd = ERROR_ACK;
							mapi_read_error(&errno, errorstr);
							memcpy(dbuf->data, &errno, sizeof(int));
							dbuf->length = BASIC_SIZE+sizeof(int);
						}
					}
#endif
's avatar
committed
535
536
537
538
				}
				break;
			case GET_NEXT_PKT:
				pkt = (struct mapipkt *)mapi_get_next_pkt(dbuf->fd,dbuf->fid);
's avatar
committed
539
				gettimeofday(&tv, NULL);
's avatar
committed
540
541
542
543
544
545
546
				dbuf->timestamp = tv.tv_usec;
				if(pkt!=NULL){
					dbuf->cmd = GET_NEXT_PKT_ACK;
					memcpy(dbuf->data, pkt, sizeof(struct mapipkt)-4+pkt->caplen);
					dbuf->length = BASIC_SIZE + sizeof(struct mapipkt) - 4 + pkt->caplen;
				}
				else{
547
					dbuf->cmd = GET_NEXT_PKT_ACK;
's avatar
committed
548
549
550
551
552
553
					dbuf->length = BASIC_SIZE;
				}
				break;
			case GET_FLOW_INFO:
				fprintf(stdout,"GET_FLOW_INFO\n");
				if(mapi_get_flow_info(dbuf->fd, &flow_info)){
554
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
555
556
557
558
					dbuf->cmd = MAPI_FLOW_INFO_ERR;
					dbuf->length = BASIC_SIZE;
				}
				else{
559
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, 0);
560
561
562
563
564
565
566
567
					dbuf->cmd = GET_FLOW_INFO_ACK;
					memcpy(dbuf->data,&flow_info,sizeof(mapi_flow_info_t));
					dbuf->length = BASIC_SIZE+sizeof(mapi_flow_info_t);
				}
				break;
			case GET_NEXT_FLOW_INFO:
				fprintf(stdout,"GET_NEXT_FLOW_INFO\n");
				if(mapi_get_next_flow_info(dbuf->fd, &flow_info)){
568
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
's avatar
committed
569
570
571
572
					dbuf->cmd = MAPI_FLOW_INFO_ERR;
					dbuf->length = BASIC_SIZE;
				}
				else{
573
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, 0);
's avatar
committed
574
575
576
577
578
					dbuf->cmd = GET_FLOW_INFO_ACK;
					memcpy(dbuf->data,&flow_info,sizeof(mapi_flow_info_t));
					dbuf->length = BASIC_SIZE+sizeof(mapi_flow_info_t);
				}
				break;
579
580
581
			case GET_DEVICE_INFO:
				fprintf(stdout,"GET_DEVICE_INFO\n");
				if(mapi_get_flow_info(dbuf->fd, &flow_info)){
582
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
583
584
585
586
587
					dbuf->cmd = GET_DEVICE_INFO_NACK;
					dbuf->length = BASIC_SIZE;
				}

				if(mapi_get_device_info(flow_info.devid, &device_info)<0){
588
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
589
590
591
592
					dbuf->cmd = GET_DEVICE_INFO_NACK;
					dbuf->length = BASIC_SIZE;
				}
				else{
593
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, 0);
594
595
596
597
598
599
600
601
					dbuf->cmd = GET_DEVICE_INFO_ACK;
					memcpy(dbuf->data,&device_info,sizeof(mapi_device_info_t));
					dbuf->length = BASIC_SIZE+sizeof(mapi_device_info_t);
				}
				break;
			case GET_NEXT_DEVICE_INFO:
				fprintf(stdout,"GET_NEXT_DEVICE_INFO\n");
				if(mapi_get_flow_info(dbuf->fd, &flow_info)){
602
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
603
604
605
606
607
					dbuf->cmd = GET_DEVICE_INFO_NACK;
					dbuf->length = BASIC_SIZE;
				}

				if(mapi_get_next_device_info(flow_info.devid, &device_info)<0){
608
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
609
610
611
612
					dbuf->cmd = GET_DEVICE_INFO_NACK;
					dbuf->length = BASIC_SIZE;
				}
				else{
613
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, 0);
614
615
616
617
618
					dbuf->cmd = GET_DEVICE_INFO_ACK;
					memcpy(dbuf->data,&device_info,sizeof(mapi_device_info_t));
					dbuf->length = BASIC_SIZE+sizeof(mapi_device_info_t);
				}
				break;
's avatar
committed
619
620
621
			case GET_FUNCTION_INFO:
				fprintf(stdout,"GET_FUNCTION_INFO\n");
				if(mapi_get_function_info(dbuf->fd, dbuf->fid, &funct_info)){
622
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
's avatar
committed
623
624
625
626
					dbuf->cmd = MAPI_FUNCTION_INFO_ERR;
					dbuf->length = BASIC_SIZE;
				}
				else{
627
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, 0);
's avatar
committed
628
629
630
631
632
633
634
635
					dbuf->cmd = GET_FUNCTION_INFO_ACK;
					memcpy(dbuf->data,&funct_info,sizeof(mapi_function_info_t));
					dbuf->length = BASIC_SIZE+sizeof(mapi_function_info_t);
				}
				break;
			case GET_NEXT_FUNCTION_INFO:
				fprintf(stdout,"GET_NEXT_FUNCTION_INFO\n");
				if(mapi_get_next_function_info(dbuf->fd, dbuf->fid, &funct_info)){
636
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
's avatar
committed
637
638
639
640
					dbuf->cmd = MAPI_FUNCTION_INFO_ERR;
					dbuf->length = BASIC_SIZE;
				}
				else{
641
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, 0);
's avatar
committed
642
643
644
645
					dbuf->cmd = GET_FUNCTION_INFO_ACK;
					memcpy(dbuf->data,&funct_info,sizeof(mapi_function_info_t));
					dbuf->length = BASIC_SIZE+sizeof(mapi_function_info_t);
				}
646
				break;
's avatar
committed
647
648
649
650
651
652
653
654
655
656
657
658
659
#ifdef WITH_ADMISSION_CONTROL
			case SET_AUTHDATA:
				fprintf(stdout,"SET_AUTHDATA\n");
				if(!agent_send_authdata(dbuf)){
					dbuf->cmd = SET_AUTHDATA_ACK;
				}
				else{
					dbuf->cmd = ERROR_ACK;
				}

				dbuf->length = BASIC_SIZE;
				break;
#endif
's avatar
committed
660
661
#ifdef WITH_AUTHENTICATION
			case AUTHENTICATE:
662
				fprintf(stdout, "AUTHENTICATE\n");
663
				if(!agent_authenticate(dbuf)){
664
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, 0);
665
					dbuf->cmd = AUTHENTICATE_ACK;
666
667
				}
				else{
668
					mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, -1);
669
					dbuf->cmd = ERROR_ACK;
670
				}
's avatar
   
committed
671
				dbuf->length = BASIC_SIZE;
's avatar
committed
672
673
				break;
#endif
674
675
676
			case MAPI_STATS:
				dev=strdup(dbuf->data);
				mapid_result = mapi_stats(dev, &stats);
677
				mapicommd_logging(log_to_file, log_to_syslog, log_fd_info, dbuf, mapid_result);
678
679
680
681
682
683
684
685
686
				if(mapid_result <0) {
					dbuf->cmd = MAPI_STATS_ERR;
					mapi_read_error(&errno, errorstr);
					memcpy(dbuf->data, &errno, sizeof(int));
					dbuf->length = BASIC_SIZE+sizeof(int);
				}
				else {
					dbuf->cmd = MAPI_STATS_ACK;
					memcpy(dbuf->data, &stats, sizeof(struct mapi_stat));
's avatar
committed
687
					dbuf->length = BASIC_SIZE+sizeof(struct mapi_stat);
688
689
690
				}
				free(dev);
				break;
691
			default:
's avatar
committed
692
				die("Default case found in handle_request loop!\n");
693
				break;
's avatar
committed
694
695
	        }

's avatar
committed
696
697
		//no need to send responce on mapi_close_flow
		if (dbuf->cmd!=CLOSE_FLOW) {
's avatar
committed
698
699
#ifdef DIMAPISSL
			SSL_write(con,dbuf,dbuf->length);
700
#else
's avatar
committed
701
702
			send(sock,dbuf, dbuf->length,0);
#endif
's avatar
committed
703
		}
's avatar
committed
704
	}
705

's avatar
committed
706
	for(i=0;i<ac_fl_size;++i){//close all remaining flows before this thread exits
's avatar
committed
707
		if(active_flows[i]>0){//this should always be positive or realloc does not work
's avatar
committed
708
709
710
711
			mapi_close_flow(active_flows[i]);
		}
	}
	free(active_flows);
712
	free(dbuf);
's avatar
committed
713
	dbuf = NULL;
's avatar
committed
714

's avatar
committed
715
716
717
	shutdown(sock, SHUT_RDWR);
	close(sock);

's avatar
committed
718
#ifdef DIMAPISSL
719
	if (SSL_shutdown(con) == -1)	// shut down a TLS/SSL connection
's avatar
committed
720
		ERR_print_errors_fp(stderr);
721

722
723
724
	SSL_free(con);			// decrements the reference count of ssl, and removes the SSL structure pointed to by ssl
       					// frees up the allocated memory if the the reference count has reached 0
#endif
's avatar
committed
725
726
727

	/* update the global service counter */
	service_count++;
728
729
730
731
	DEBUG_CMD(Debug_Message("<+> thread %lu exiting", pthread_self()));
	DEBUG_CMD(Debug_Message("<+> total sockets served: %d", service_count));

	if(log_to_file){
732
733
734
735
736
		file_size = acquire_write_lock(log_fd_info);
		write_to_file(log_fd_info, "MAPICOMMD: thread %lu exiting at ", pthread_self());
		write_date(log_fd_info);
		write_to_file(log_fd_info, "\nMAPICOMMD: Total sockets served: %d\n", service_count);
		release_write_lock(log_fd_info, file_size);
737
738
	}
	
's avatar
committed
739
740
741
	pthread_exit((void *)0);
}

742
743
744
745
int die(char *msg){

	long file_size;
	
746
	if(log_to_file){
747
748
749
		file_size = acquire_write_lock(log_fd_info);
		write_to_file(log_fd_info, "MAPICOMMD: %s\n", msg);
		release_write_lock(log_fd_info, file_size);
750
751
	}

's avatar
committed
752
753
754
755
756
757
758
	perror(msg);
	return EXIT_FAILURE;
}

//calls the appropriate mapi_apply_function and returns the fid from mapid
int getfid(struct dmapiipcbuf *dbuf){
	int result;
759

760
	char *function = (char *)dbuf->data;
's avatar
committed
761
	char *data = (char *)(dbuf->data+strlen(function)+1);
's avatar
committed
762

's avatar
committed
763
764
	result = mapi_apply_function(dbuf->fd, function, data);
	return (result);
's avatar
committed
765
766
}

767
768
769
770
void mapicommd_shutdown(int exit_value){

#ifdef DIMAPISSL
	
771
772
773
774
775
776
777
	if(ctx != NULL)
		SSL_CTX_free(ctx);	// decrements the reference count of ctx, and removes the SSL_CTX object pointed to by ctx
					// frees up the allocated memory if the the reference count has reached 0
	CRYPTO_cleanup_all_ex_data();	// clean up all allocated state
	ERR_free_strings();		// frees all previously loaded error strings
	ERR_remove_state(0);		// the current thread will have its error queue removed
	EVP_cleanup();			// removes all ciphers and digests from the table
778
779
#endif
	
780
	if(log_to_file){
781
		
782
783
		daemon_terminated(log_fd_info, "MAPICOMMD", daemonize, 0);
		daemon_terminated(log_fd_debug, "MAPICOMMD", daemonize, 0);
784

785
	}
786
787
	if(log_to_syslog)
		log_message("MAPICOMMD was terminated %s", daemonize ? " ( was running as daemon )" : "");
's avatar
committed
788

789
	exit(exit_value);
790
}