mapicommd.c 12.1 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 11 12
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
's avatar
committed
13
#include <arpa/inet.h>
's avatar
committed
14
#include <sys/time.h>
's avatar
committed
15
#include <errno.h>
's avatar
committed
16 17
#include "mapi.h"
#include "mapiipc.h"
's avatar
committed
18
#include "parseconf.h"
19
#include "mapi_errors.h"
's avatar
committed
20
#include "mapilibhandler.h"
's avatar
committed
21
#include "printfstring.h"
's avatar
committed
22

's avatar
committed
23
#define MAXPENDING 500    /* Maximum outstanding connection requests */
's avatar
committed
24

25 26
extern void set_agent();

's avatar
committed
27
//pthread_mutex_t lock;	DELETE
's avatar
committed
28
int service_count;
's avatar
committed
29
int dimapi_port;
's avatar
committed
30 31 32 33 34

void *handle_request(void *);
int die(char *msg);
int getfid(struct dmapiipcbuf *dbuf);

's avatar
committed
35
int main() {
's avatar
committed
36 37 38 39 40 41 42 43 44
	
	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;
	
	struct sockaddr_in serv_addr;
	struct sockaddr_in clnt_addr;
	
's avatar
committed
45 46 47 48 49 50 51 52 53
#ifdef DIMAPISSL
	struct overload *inst;
	SSL *con=NULL;
	OpenSSL_add_all_algorithms();	/* load & register all cryptos, etc. */
	SSL_library_init();
	SSL_load_error_strings();
#endif	

	
's avatar
committed
54
	pthread_t chld_thr;
's avatar
committed
55 56
	
	char* mapi_conf;
57 58 59 60 61
	//mapi_conf = malloc(sizeof(CONF_FILE)-2+strlen(getenv("HOME")));
	//sprintf(mapi_conf,CONF_FILE,getenv("HOME"));
	mapi_conf = printf_string( CONFDIR"/"CONF_FILE );
	printf("using %s\n", mapi_conf);
	
's avatar
committed
62 63 64 65 66 67 68 69 70 71 72
	if (pc_load (mapi_conf))
	  {
		dimapi_port = atoi( pc_get_param (pc_get_category(""), "dimapi_port") );
	  }
	else 
	  {
		printf("Error: cannot load mapi.conf file.\n");
		exit(1);
	  }
	free(mapi_conf);
	pc_close();
's avatar
committed
73

's avatar
committed
74
	if ((serv_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
's avatar
committed
75
		die("Unexpected error on socket()");
's avatar
committed
76 77
		exit(-1);
	}
's avatar
committed
78 79 80 81 82
	
	memset(&serv_addr, 0, sizeof serv_addr);  

	serv_addr.sin_family = AF_INET;   
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
's avatar
committed
83
	serv_addr.sin_port = htons(dimapi_port);
's avatar
committed
84

's avatar
committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
#ifdef DIMAPISSL
	/**** SSL CHANGES **********/

	if ((ctx=SSL_CTX_new(SSLv3_server_method())) == NULL) {
		ERR_print_errors_fp(stderr);
		return 0;
	}


	if (SSL_CTX_use_certificate_file(ctx, "/usr/local/share/mapi/cacert.pem", SSL_FILETYPE_PEM) <= 0) {
		ERR_print_errors_fp(stderr);
		return 0;
	}
	if (SSL_CTX_use_PrivateKey_file(ctx, "/usr/local/share/mapi/privkey.pem", SSL_FILETYPE_PEM) <= 0) {
		ERR_print_errors_fp(stderr);
		return 0;
	}


	/*** END OF SSL CHANGES *****/
#endif

's avatar
committed
107 108 109 110 111 112 113 114 115
	/* 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()");
's avatar
committed
116
		exit(1);
's avatar
committed
117 118 119 120 121 122 123
	}

	/* queue max 5 connections */
	if (listen(serv_sock, MAXPENDING) == -1) {
		shutdown(serv_sock, SHUT_RDWR);
		close(serv_sock);
		die("Unexpected error on listen()");
's avatar
committed
124
		exit(-1);
's avatar
committed
125 126
	}

127
	set_agent();
's avatar
committed
128

's avatar
committed
129 130 131
	while(1) {

		clnt_len = sizeof clnt_addr;
's avatar
committed
132
		if ((new_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_len)) == -1) {
's avatar
committed
133
			die("Unexpected error on accept()");
's avatar
committed
134 135
			continue;
		}
's avatar
committed
136

's avatar
committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
#ifdef DIMAPISSL
		printf("\n\t\tDiMAPI (SSL ENCRYPTION)\n");
		
		if ((con=SSL_new(ctx)) == NULL) {
			ERR_print_errors_fp(stderr);
			return 0;;
		}

		if (SSL_set_fd(con, new_sock) == 0) {
			ERR_print_errors_fp(stderr);
			return 0;
		}

		if (SSL_accept(con) <= 0) {
			ERR_print_errors_fp(stderr);
			return 0;
		}
#endif


#ifndef DIMAPISSL
		printf("\n\t\tDiMAPI (no encryption)\n");
#endif

's avatar
committed
161
		printf("<*> got connection from %s\n", inet_ntoa(clnt_addr.sin_addr));
's avatar
committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175
#ifdef DIMAPISSL
		inst = (struct overload *)malloc(sizeof(struct overload));	
		inst->connection = con;
		inst->sock = new_sock;
		
		if (pthread_create(&chld_thr, NULL, handle_request,(void *) inst) != 0){
			die("pthread_create() failed");
			continue;
		}
#endif

#ifndef DIMAPISSL

					
's avatar
committed
176
		if (pthread_create(&chld_thr, NULL, handle_request, (void *)new_sock) != 0) {
's avatar
committed
177
            		die("pthread_create() failed");
's avatar
committed
178 179
			continue;
		}
's avatar
committed
180
#endif
's avatar
committed
181 182
	}

's avatar
committed
183 184


's avatar
committed
185 186 187 188 189
	return 0; /* never reached */
}

void *handle_request(void *arg) {
	
's avatar
committed
190 191 192 193 194 195 196 197

#ifdef DIMAPISSL
	SSL *con ;
	con = ((struct overload*)arg)->connection;
	int sock = ((struct overload*)arg)->sock;
#endif

#ifndef DIMAPISSL
's avatar
committed
198
	int sock=(int)arg;
's avatar
committed
199
#endif	
's avatar
committed
200
	int recv_bytes;
's avatar
committed
201
	//char buffer[DIMAPI_DATA_SIZE];	DELETE
's avatar
committed
202 203
	struct dmapiipcbuf *dbuf=NULL;
	int mapid_result;
's avatar
committed
204
	mapi_results_t *result;
's avatar
committed
205
	//unsigned int dbuf_bytes=0;		DELETE
's avatar
committed
206 207 208 209 210 211 212 213
	int i;
	int *active_flows = NULL;
	int ac_fl_size=0;
	mapi_function_info_t funct_info;
	mapi_flow_info_t flow_info;
	struct timeval tv; /*used for timestamping results when produced */
	struct mapipkt *pkt;

's avatar
committed
214 215
	

's avatar
committed
216 217 218
	/* Guarantees that thread resources are deallocated upon return */
	pthread_detach(pthread_self()); 
	dbuf = (struct dmapiipcbuf *)malloc(sizeof(struct dmapiipcbuf));
's avatar
committed
219 220 221 222 223 224
#ifdef DIMAPISSL
	printf("<+> new thread %d, socket number = %d\n", (int)pthread_self(),(int) con);
#endif

#ifndef DIMAPISSL

's avatar
committed
225 226
	printf("<+> new thread %d, socket number = %d\n", (int)pthread_self(), sock);
	
's avatar
committed
227
#endif
's avatar
committed
228 229
	while(1) {

's avatar
committed
230
		/*if (dbuf_bytes==0 || dbuf_bytes<((struct dmapiipcbuf *)buffer)->length){
's avatar
committed
231

's avatar
committed
232
			recv_bytes = recv(sock, (char*)buffer+dbuf_bytes, DIMAPI_DATA_SIZE, 0);
's avatar
committed
233

's avatar
committed
234
			if (recv_bytes == 0) { // the peer has gone
's avatar
committed
235 236 237 238 239 240 241 242 243 244 245 246
				printf("Peer has gone\n");
				break;
			}
			else if (recv_bytes == -1) {
				die("recv()");
				break;
			}

			dbuf_bytes += recv_bytes;
		}


's avatar
committed
247 248
		if (dbuf_bytes<((struct dmapiipcbuf *)buffer)->length) continue;*/

's avatar
committed
249 250 251
#ifdef DIMAPISSL
		recv_bytes = SSL_readn(con,dbuf,BASIC_SIZE);
#endif
's avatar
committed
252

's avatar
committed
253 254 255
#ifndef DIMAPISSL
		recv_bytes=readn(sock, dbuf, BASIC_SIZE);
#endif
's avatar
committed
256 257 258 259 260 261 262 263 264 265 266 267 268
		if (recv_bytes == 0) { // the peer has gone
			printf("Peer has gone\n");
			break;
		}
		else if (recv_bytes == -1) {
			die("recv()");
			break;
		}

		if (dbuf->length > DIMAPI_DATA_SIZE) {
			fprintf(stderr,"Warning: Ignoring invalid message\n");
			continue;
		}
's avatar
committed
269

's avatar
committed
270
		if (dbuf->length-BASIC_SIZE>0) {
's avatar
committed
271 272 273 274 275
#ifdef DIMAPISSL
			recv_bytes = SSL_readn(con,(char *)dbuf+BASIC_SIZE,dbuf->length-BASIC_SIZE);
#endif

#ifndef DIMAPISSL
's avatar
committed
276
			recv_bytes=readn(sock, (char*)dbuf+BASIC_SIZE, dbuf->length-BASIC_SIZE);
's avatar
committed
277
#endif
's avatar
committed
278 279 280 281 282 283 284 285 286 287 288
			if (recv_bytes == 0) { // the peer has gone
				printf("Peer has gone\n");
				break;
			}
			else if (recv_bytes == -1) {
				die("recv()");
				break;
			}
		}
		
		//memcpy(dbuf,buffer,((struct dmapiipcbuf *)buffer)->length);	DELETE
's avatar
committed
289 290
		switch(dbuf->cmd) {
			case CREATE_FLOW:
's avatar
committed
291
				mapid_result = mapi_create_flow(dbuf->data);
's avatar
committed
292 293 294 295 296 297
				fprintf(stdout,"CREATE_FLOW (%s, %d)\n",dbuf->data, mapid_result);
				if(mapid_result <0)
					dbuf->cmd = ERROR_ACK;
				else					
					dbuf->cmd = CREATE_FLOW_ACK;
				memcpy(dbuf->data, &mapid_result, sizeof(int));
's avatar
committed
298
				active_flows = realloc(active_flows,(ac_fl_size+1)*sizeof(int));
's avatar
committed
299 300 301 302 303 304 305 306 307 308
				active_flows[ac_fl_size++] = mapid_result;
				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);
				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
309
							active_flows = realloc(active_flows,ac_fl_size*sizeof(int));
's avatar
committed
310 311 312
						}
					}
				}
's avatar
committed
313
				//no need to send responce
's avatar
committed
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
				break;
			case CONNECT:
				fprintf(stdout,"CONNECT (%d)",dbuf->fd);
				mapid_result = mapi_connect(dbuf->fd);
				if(mapid_result >= 0){
					dbuf->cmd = CONNECT_ACK;
					fprintf(stdout," OK\n");
				}
				else{
					dbuf->cmd = ERROR_ACK;
					fprintf(stdout," FAILED\n");
				}
				dbuf->length = BASIC_SIZE;
				break;
			case APPLY_FUNCTION:
's avatar
committed
329
				fprintf(stdout,"APPLY_FUNCTION\n");
's avatar
committed
330 331 332 333 334 335 336 337 338 339 340
				if((( dbuf->fid = getfid(dbuf))!=-1)){
					dbuf->cmd = APPLY_FUNCTION_ACK;
				}
				else{
					dbuf->cmd = ERROR_ACK;
				}
				dbuf->length = BASIC_SIZE;
				break;
			case READ_RESULT:
				//fprintf(stdout,"READ_RESULT\n");
				dbuf->cmd = READ_RESULT_ACK;
341
				result = mapi_read_results(dbuf->fd,dbuf->fid);
's avatar
committed
342
				if(result!=NULL){
's avatar
committed
343 344 345
					dbuf->timestamp = result->ts;
					memcpy(dbuf->data, result->res, result->size);
					dbuf->length = BASIC_SIZE + result->size;
's avatar
committed
346 347 348 349 350 351 352 353
				}
				else{
					fprintf(stdout,"mapi_read_results failed...\n");
					dbuf->cmd = ERROR_ACK;
					dbuf->length = BASIC_SIZE;
				}
				break;
			case GET_NEXT_PKT:
's avatar
committed
354
				//fprintf(stdout,"GET_NEXT_PKT\n");
's avatar
committed
355
				pkt = (struct mapipkt *)mapi_get_next_pkt(dbuf->fd,dbuf->fid);
's avatar
committed
356
				gettimeofday(&tv, NULL);
's avatar
committed
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
				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{
					dbuf->cmd = ERROR_ACK;
					dbuf->length = BASIC_SIZE;
					fprintf(stdout,"mapi_get_next_pkt failed...\n");					
				}
				break;
			case GET_FLOW_INFO:
				fprintf(stdout,"GET_FLOW_INFO\n");
				if(mapi_get_flow_info(dbuf->fd, &flow_info)){
					dbuf->cmd = MAPI_FLOW_INFO_ERR;
					dbuf->length = BASIC_SIZE;
				}
				else{
					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_FUNCTION_INFO:
				fprintf(stdout,"GET_FUNCTION_INFO\n");
				if(mapi_get_function_info(dbuf->fd, dbuf->fid, &funct_info)){
					dbuf->cmd = MAPI_FUNCTION_INFO_ERR;
					dbuf->length = BASIC_SIZE;
				}
				else{
					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)){
					dbuf->cmd = MAPI_FUNCTION_INFO_ERR;
					dbuf->length = BASIC_SIZE;
				}
				else{
					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;				break;
			case GET_NEXT_FLOW_INFO:
				fprintf(stdout,"GET_NEXT_FLOW_INFO\n");
				if(mapi_get_next_flow_info(dbuf->fd, &flow_info)){
					dbuf->cmd = MAPI_FLOW_INFO_ERR;
					dbuf->length = BASIC_SIZE;
				}
				else{
					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;
#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
430 431
#ifdef WITH_AUTHENTICATION
			case AUTHENTICATE:
432
				fprintf(stdout, "AUTHENTICATE\n");
's avatar
 
committed
433
				if(!agent_authenticate(dbuf))
434 435 436
					dbuf->cmd = AUTHENTICATE_ACK;
				else
					dbuf->cmd = ERROR_ACK;
's avatar
 
committed
437
				dbuf->length = BASIC_SIZE;
's avatar
committed
438 439
				break;
#endif
's avatar
committed
440 441 442 443 444
	              default:
				die("Default case found in handle_request loop!\n");
        	        break;
	        }

's avatar
committed
445 446
		//no need to send responce on mapi_close_flow
		if (dbuf->cmd!=CLOSE_FLOW) {
's avatar
committed
447 448 449 450 451 452 453
#ifdef DIMAPISSL
			SSL_write(con,dbuf,dbuf->length);
#endif

#ifndef DIMAPISSL
			send(sock,dbuf, dbuf->length,0);
#endif
's avatar
committed
454
		}
's avatar
committed
455

's avatar
committed
456 457
		//dbuf_bytes=dbuf_bytes-((struct dmapiipcbuf *)buffer)->length;			DELETE
		//memcpy(buffer,buffer+((struct dmapiipcbuf *)buffer)->length,dbuf_bytes);	DELETE
's avatar
committed
458 459 460
	}
	
	for(i=0;i<ac_fl_size;++i){//close all remaining flows before this thread exits
's avatar
committed
461
		if(active_flows[i]>0){//this should always be positive or realloc does not work
's avatar
committed
462 463 464 465
			mapi_close_flow(active_flows[i]);
		}
	}
	free(active_flows);
466
	free(dbuf);
's avatar
committed
467 468 469 470 471 472 473

	
#ifdef DIMAPISSL
if (SSL_shutdown(con) == -1)
		ERR_print_errors_fp(stderr);
#endif
	
's avatar
committed
474 475 476 477
	shutdown(sock, SHUT_RDWR);
	close(sock);

	/* update the global service counter */
's avatar
committed
478
	//pthread_mutex_lock(&lock);	DELETE
's avatar
committed
479
	service_count++;
's avatar
committed
480
	//pthread_mutex_unlock(&lock);	DELETE
's avatar
committed
481 482 483 484 485 486 487 488 489 490 491 492 493 494
	printf("<+> thread %d exiting\n<+> total sockets served: %d\n", (int)pthread_self(), service_count);

	pthread_exit((void *)0);
}


int die(char *msg) {
	perror(msg);
	return EXIT_FAILURE;
}

//calls the appropriate mapi_apply_function and returns the fid from mapid
int getfid(struct dmapiipcbuf *dbuf){
	int result;
's avatar
committed
495
	
496
	char *function = (char *)dbuf->data;
's avatar
committed
497
	char *data = (char *)(dbuf->data+strlen(function)+1);
's avatar
committed
498

's avatar
committed
499 500
	result = mapi_apply_function(dbuf->fd, function, data);
	return (result);
's avatar
committed
501 502
}

's avatar
committed
503 504 505 506