mapicommd.c 11.8 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() {
36

's avatar
committed
37 38 39 40
	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;
41

's avatar
committed
42 43
	struct sockaddr_in serv_addr;
	struct sockaddr_in clnt_addr;
44

's avatar
committed
45 46 47 48 49 50
#ifdef DIMAPISSL
	struct overload *inst;
	SSL *con=NULL;
	OpenSSL_add_all_algorithms();	/* load & register all cryptos, etc. */
	SSL_library_init();
	SSL_load_error_strings();
51
#endif
's avatar
committed
52

's avatar
committed
53
	pthread_t chld_thr;
54

's avatar
committed
55
	char* mapi_conf;
56 57 58
	//mapi_conf = malloc(sizeof(CONF_FILE)-2+strlen(getenv("HOME")));
	//sprintf(mapi_conf,CONF_FILE,getenv("HOME"));
	mapi_conf = printf_string( CONFDIR"/"CONF_FILE );
59

60
	printf("using %s\n", mapi_conf);
61 62 63 64
#ifdef DIMAPISSL
	printf("SSL enabled\n");
#endif

's avatar
committed
65 66 67 68
	if (pc_load (mapi_conf))
	  {
		dimapi_port = atoi( pc_get_param (pc_get_category(""), "dimapi_port") );
	  }
69
	else
's avatar
committed
70 71 72 73 74 75
	  {
		printf("Error: cannot load mapi.conf file.\n");
		exit(1);
	  }
	free(mapi_conf);
	pc_close();
's avatar
committed
76

's avatar
committed
77
	if ((serv_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
's avatar
committed
78
		die("Unexpected error on socket()");
's avatar
committed
79 80
		exit(-1);
	}
's avatar
committed
81

82 83 84
	memset(&serv_addr, 0, sizeof serv_addr);

	serv_addr.sin_family = AF_INET;
's avatar
committed
85
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
's avatar
committed
86
	serv_addr.sin_port = htons(dimapi_port);
's avatar
committed
87

's avatar
committed
88 89 90 91 92
#ifdef DIMAPISSL
	if ((ctx=SSL_CTX_new(SSLv3_server_method())) == NULL) {
		ERR_print_errors_fp(stderr);
		return 0;
	}
93
	if (SSL_CTX_use_certificate_file(ctx, CONFDIR"/"MAPICOMMD_SSL_CERT_FILE, SSL_FILETYPE_PEM) <= 0) {
's avatar
committed
94 95 96
		ERR_print_errors_fp(stderr);
		return 0;
	}
97
	if (SSL_CTX_use_PrivateKey_file(ctx, CONFDIR"/"MAPICOMMD_SSL_KEY_FILE, SSL_FILETYPE_PEM) <= 0) {
's avatar
committed
98 99 100 101 102
		ERR_print_errors_fp(stderr);
		return 0;
	}
#endif

's avatar
committed
103 104 105 106 107 108 109 110 111
	/* 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
112
		exit(1);
's avatar
committed
113 114 115 116 117 118 119
	}

	/* 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
120
		exit(-1);
's avatar
committed
121 122
	}

123
	set_agent();
's avatar
committed
124

's avatar
committed
125 126 127
	while(1) {

		clnt_len = sizeof clnt_addr;
's avatar
committed
128
		if ((new_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_len)) == -1) {
's avatar
committed
129
			die("Unexpected error on accept()");
's avatar
committed
130 131
			continue;
		}
's avatar
committed
132

's avatar
committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146
#ifdef DIMAPISSL
		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
's avatar
committed
147
		printf("<*> got connection from %s\n", inet_ntoa(clnt_addr.sin_addr));
148

's avatar
committed
149
#ifdef DIMAPISSL
150
		inst = (struct overload *)malloc(sizeof(struct overload));
's avatar
committed
151 152
		inst->connection = con;
		inst->sock = new_sock;
153

's avatar
committed
154 155 156 157
		if (pthread_create(&chld_thr, NULL, handle_request,(void *) inst) != 0){
			die("pthread_create() failed");
			continue;
		}
158
#else
's avatar
committed
159
		if (pthread_create(&chld_thr, NULL, handle_request, (void *)new_sock) != 0) {
160
			die("pthread_create() failed");
's avatar
committed
161 162
			continue;
		}
's avatar
committed
163
#endif
164
	} /* while (1) */
's avatar
committed
165 166 167 168
	return 0; /* never reached */
}

void *handle_request(void *arg) {
's avatar
committed
169 170 171 172
#ifdef DIMAPISSL
	SSL *con ;
	con = ((struct overload*)arg)->connection;
	int sock = ((struct overload*)arg)->sock;
173
#else
's avatar
committed
174
	int sock=(int)arg;
175
#endif
's avatar
committed
176
	int recv_bytes;
's avatar
committed
177
	//char buffer[DIMAPI_DATA_SIZE];	DELETE
's avatar
committed
178 179
	struct dmapiipcbuf *dbuf=NULL;
	int mapid_result;
's avatar
committed
180
	mapi_results_t *result;
's avatar
committed
181
	//unsigned int dbuf_bytes=0;		DELETE
's avatar
committed
182 183 184 185 186 187 188 189 190
	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;

	/* Guarantees that thread resources are deallocated upon return */
191
	pthread_detach(pthread_self());
's avatar
committed
192
	dbuf = (struct dmapiipcbuf *)malloc(sizeof(struct dmapiipcbuf));
's avatar
committed
193 194
#ifdef DIMAPISSL
	printf("<+> new thread %d, socket number = %d\n", (int)pthread_self(),(int) con);
195
#else
's avatar
committed
196
	printf("<+> new thread %d, socket number = %d\n", (int)pthread_self(), sock);
's avatar
committed
197
#endif
198

's avatar
committed
199 200
	while(1) {

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

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

's avatar
committed
205
			if (recv_bytes == 0) { // the peer has gone
's avatar
committed
206 207 208 209 210 211 212 213 214 215 216 217
				printf("Peer has gone\n");
				break;
			}
			else if (recv_bytes == -1) {
				die("recv()");
				break;
			}

			dbuf_bytes += recv_bytes;
		}


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

's avatar
committed
220 221
#ifdef DIMAPISSL
		recv_bytes = SSL_readn(con,dbuf,BASIC_SIZE);
222
#else
's avatar
committed
223 224
		recv_bytes=readn(sock, dbuf, BASIC_SIZE);
#endif
's avatar
committed
225 226 227 228 229 230 231 232 233 234 235 236 237
		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
238

's avatar
committed
239
		if (dbuf->length-BASIC_SIZE>0) {
's avatar
committed
240 241
#ifdef DIMAPISSL
			recv_bytes = SSL_readn(con,(char *)dbuf+BASIC_SIZE,dbuf->length-BASIC_SIZE);
242
#else
's avatar
committed
243
			recv_bytes=readn(sock, (char*)dbuf+BASIC_SIZE, dbuf->length-BASIC_SIZE);
's avatar
committed
244
#endif
's avatar
committed
245 246 247 248 249 250 251 252 253
			if (recv_bytes == 0) { // the peer has gone
				printf("Peer has gone\n");
				break;
			}
			else if (recv_bytes == -1) {
				die("recv()");
				break;
			}
		}
254

's avatar
committed
255
		//memcpy(dbuf,buffer,((struct dmapiipcbuf *)buffer)->length);	DELETE
's avatar
committed
256 257
		switch(dbuf->cmd) {
			case CREATE_FLOW:
's avatar
committed
258
				mapid_result = mapi_create_flow(dbuf->data);
's avatar
committed
259 260 261
				fprintf(stdout,"CREATE_FLOW (%s, %d)\n",dbuf->data, mapid_result);
				if(mapid_result <0)
					dbuf->cmd = ERROR_ACK;
262
				else
's avatar
committed
263 264
					dbuf->cmd = CREATE_FLOW_ACK;
				memcpy(dbuf->data, &mapid_result, sizeof(int));
's avatar
committed
265
				active_flows = realloc(active_flows,(ac_fl_size+1)*sizeof(int));
's avatar
committed
266 267 268 269 270 271 272 273 274 275
				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
276
							active_flows = realloc(active_flows,ac_fl_size*sizeof(int));
's avatar
committed
277 278 279
						}
					}
				}
's avatar
committed
280
				//no need to send responce
's avatar
committed
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
				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
296
				fprintf(stdout,"APPLY_FUNCTION\n");
's avatar
committed
297 298 299 300 301 302 303 304 305 306 307
				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;
308
				result = mapi_read_results(dbuf->fd,dbuf->fid);
's avatar
committed
309
				if(result!=NULL){
's avatar
committed
310 311 312
					dbuf->timestamp = result->ts;
					memcpy(dbuf->data, result->res, result->size);
					dbuf->length = BASIC_SIZE + result->size;
's avatar
committed
313 314 315 316 317 318 319 320
				}
				else{
					fprintf(stdout,"mapi_read_results failed...\n");
					dbuf->cmd = ERROR_ACK;
					dbuf->length = BASIC_SIZE;
				}
				break;
			case GET_NEXT_PKT:
's avatar
committed
321
				//fprintf(stdout,"GET_NEXT_PKT\n");
's avatar
committed
322
				pkt = (struct mapipkt *)mapi_get_next_pkt(dbuf->fd,dbuf->fid);
's avatar
committed
323
				gettimeofday(&tv, NULL);
's avatar
committed
324 325 326 327 328 329 330 331 332
				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;
333
					fprintf(stdout,"mapi_get_next_pkt failed...\n");
's avatar
committed
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 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
				}
				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
397 398
#ifdef WITH_AUTHENTICATION
			case AUTHENTICATE:
399
				fprintf(stdout, "AUTHENTICATE\n");
's avatar
 
committed
400
				if(!agent_authenticate(dbuf))
401 402 403
					dbuf->cmd = AUTHENTICATE_ACK;
				else
					dbuf->cmd = ERROR_ACK;
's avatar
 
committed
404
				dbuf->length = BASIC_SIZE;
's avatar
committed
405 406
				break;
#endif
407
			default:
's avatar
committed
408
				die("Default case found in handle_request loop!\n");
409
				break;
's avatar
committed
410 411
	        }

's avatar
committed
412 413
		//no need to send responce on mapi_close_flow
		if (dbuf->cmd!=CLOSE_FLOW) {
's avatar
committed
414 415
#ifdef DIMAPISSL
			SSL_write(con,dbuf,dbuf->length);
416
#else
's avatar
committed
417 418
			send(sock,dbuf, dbuf->length,0);
#endif
's avatar
committed
419
		}
's avatar
committed
420 421
		//dbuf_bytes=dbuf_bytes-((struct dmapiipcbuf *)buffer)->length;			DELETE
		//memcpy(buffer,buffer+((struct dmapiipcbuf *)buffer)->length,dbuf_bytes);	DELETE
's avatar
committed
422
	}
423

's avatar
committed
424
	for(i=0;i<ac_fl_size;++i){//close all remaining flows before this thread exits
's avatar
committed
425
		if(active_flows[i]>0){//this should always be positive or realloc does not work
's avatar
committed
426 427 428 429
			mapi_close_flow(active_flows[i]);
		}
	}
	free(active_flows);
430
	free(dbuf);
's avatar
committed
431

432

's avatar
committed
433 434 435 436
#ifdef DIMAPISSL
if (SSL_shutdown(con) == -1)
		ERR_print_errors_fp(stderr);
#endif
437

's avatar
committed
438 439 440 441
	shutdown(sock, SHUT_RDWR);
	close(sock);

	/* update the global service counter */
's avatar
committed
442
	//pthread_mutex_lock(&lock);	DELETE
's avatar
committed
443
	service_count++;
's avatar
committed
444
	//pthread_mutex_unlock(&lock);	DELETE
's avatar
committed
445 446 447 448 449 450 451 452 453 454 455 456 457 458
	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;
459

460
	char *function = (char *)dbuf->data;
's avatar
committed
461
	char *data = (char *)(dbuf->data+strlen(function)+1);
's avatar
committed
462

's avatar
committed
463 464
	result = mapi_apply_function(dbuf->fd, function, data);
	return (result);
's avatar
committed
465 466
}

's avatar
committed
467 468 469 470