Esempio n. 1
0
int mapi_close_flow(int fd)
{
  flowlist_t *flow_item = NULL;

  if (!minit)
  {
    printf("MAPI not initialized! [%s:%d]\n", __FILE__, __LINE__);
    local_err = MAPI_INIT_ERROR;
    return -1;
  }
  else if (fd <= 0)
  {
    printf("ERROR: Wrong fd (fd: %d) in mapi_close_flow\n", fd);
    return -1;
  }

  if (flowlist && (flow_item = flist_get(flowlist, fd)) == NULL)
  {
    printf("ERROR: Invalid flow %d [%s:%d]\n", fd, __FILE__, __LINE__);
    local_err = MAPI_INVALID_FLOW;
    return -1;
  }
  else
  {
    flow_item = flist_remove(flowlist,fd);

    flowdrv_close_flow = drv_get_funct(flow_item->driver, "flowdrv_close_flow");
    return (*flowdrv_close_flow)(flow_item);
  }
}
Esempio n. 2
0
static void cleanup_flow(struct flow *f) {
	/* delete device if offline flow */
	if (f->offline != 0) {
		mapidrv_delete_device = get_drv_funct(f->drv->handle,
				"mapidrv_delete_device");
		mapidrv_delete_device(f->drv->devid);
	} else {

		/* Call driver - ignore error */
		mapidrv_close_flow
				= get_drv_funct(f->drv->handle, "mapidrv_close_flow");
		mapidrv_close_flow(f->drv->devid, f->fd);
	}

	// clear mapid flow resources
	f = (struct flow*)flist_remove(flowlist, f->fd);

	flows--;
	//FIX:is it ok here to leave flows-- unprotected by locks?
	/*
	 // clear mapid flow resources
	 f = (struct flow *) flist_remove (flowlist, f->fd);
	 flows--;
	 */
	// _may_ be wrong to deallocate 
	free(f);
}
Esempio n. 3
0
/**
 * closes a flow described by fd
 * if send_reply is non-zero, a response is sent to client's mapi stub,
 * (send_reply=0 is used for local clean-ups)
 */
static void cmd_close_flow(int fd, int pid, int sock, int send_reply) {
	struct flow *f;
	struct client *cl;
	struct mapiipcbuf buf;
	long file_size;

	f=(struct flow*)flist_get(flowlist, fd);

	if (f) {
		/* to avoid reading memory after it's freed */
		int tmpfd = f->fd;
		/* prevent closing flows of other processes */
		if (pid != f->id) {
			DEBUG_CMD(Debug_Message(
					"Proc %d tried to close flow %d, which belongs to proc %d",
					pid, f->fd, f->id));
			report_error(MAPI_INVALID_FLOW, pid, sock);
			return;
		}

		cleanup_flow(f);

		while(__sync_lock_test_and_set(&clientlist_lock,1));
		cl = flist_get(clientlist, pid);
		f = (struct flow *) flist_remove(cl->flowlist, fd);
		cl->numflows--;
		clientlist_lock = 0;

		//send an ACK that flow closed
		if (send_reply) {

			buf.mtype = pid;
			buf.cmd = CLOSE_FLOW_ACK;
			buf.fd = tmpfd;
			mapiipc_daemon_write((struct mapiipcbuf *) &buf, sock);

			if (log_to_file) {
				file_size = acquire_write_lock(log_fd_info);
				write_to_file(log_fd_info, "MAPID: flow %d was closed at ",
						buf.fd);
				write_date(log_fd_info);
				write_newline(log_fd_info, "\n");
				release_write_lock(log_fd_info, file_size);
			}
			if (log_to_syslog)
				log_message("flow %d was closed", buf.fd);
		}
	} else {
		report_error(MAPI_INVALID_FLOW, pid, sock);
	}
}
Esempio n. 4
0
int ipfix_decode(anonpacket * p, struct IPFIX *ipfix, struct anonflow *flow)
{
	uint16_t        i = 0, j = 0, set_length = 0;
	unsigned char  *payload = NULL;

	struct ipfix_template_set *tmp_template = NULL;
	struct ipfix_template_record *tmp_record = NULL;

	if (!ipfix)
		return (-1);
	if (!(p->iph))
		return (-1);
	if (p->data == NULL || p->dsize < sizeof(struct ipfix_header))
		return (-1);

	if (!(p->udph) && !(p->tcph))
		return (-1);

	memset(ipfix, 0, sizeof(struct IPFIX));
	payload = (unsigned char *)p->data;

	ipfix->header = (struct ipfix_header *)payload;
	payload += sizeof(struct ipfix_header);

	if (ntohs(ipfix->header->length) > p->dsize)
		return (-1);	// XXX could IPFIX span multiple datagrams?

	while ((uint16_t) (payload - p->data) < p->dsize) {
		i = ntohs(*(uint16_t *) payload);

		if (i == 2)	// Template set
		{
			ipfix->templates =
			    realloc(ipfix->templates,
				    (++ipfix->ntemplates) * sizeof(struct ipfix_template_set *));
			ipfix->templates[ipfix->ntemplates - 1] =
			    malloc(sizeof(struct ipfix_template_set));
			ipfix->templates[ipfix->ntemplates - 1]->header =
			    (struct ipfix_set_header *)payload;

			i = sizeof(struct ipfix_set_header);
			payload += i;

			tmp_template = ipfix->templates[ipfix->ntemplates - 1];
			tmp_template->nrecords = 0;
			tmp_template->records = NULL;

			set_length = ntohs(tmp_template->header->length);

			while (i < set_length) {
				if (*(uint16_t *) payload == 0)	{ // Padding!
					payload =
					    (unsigned char *)tmp_template->header +
					    ntohs(tmp_template->header->length);
					break;
				}

				tmp_template->records =
				    realloc(tmp_template->records,
					    (++tmp_template->nrecords) *
					    sizeof(struct ipfix_template_record *));
				tmp_template->records[tmp_template->nrecords - 1] =
				    malloc(sizeof(struct ipfix_template_record));
				tmp_template->records[tmp_template->nrecords - 1]->header =
				    malloc(sizeof(struct ipfix_template_header));
				tmp_template->records[tmp_template->nrecords - 1]->header->id =
				    ntohs(((struct ipfix_template_header *)payload)->id);
				tmp_template->records[tmp_template->nrecords - 1]->header->count =
				    ntohs(((struct ipfix_template_header *)payload)->count);

				i += sizeof(struct ipfix_template_header);
				payload += sizeof(struct ipfix_template_header);

				tmp_record = tmp_template->records[tmp_template->nrecords - 1];
				tmp_record->nvendor = tmp_record->nietf = 0;
				tmp_record->ietf_fields = NULL;
				tmp_record->vendor_fields = NULL;
				tmp_record->nfields = ntohs(tmp_record->header->count);
				tmp_record->fields =
				    malloc(tmp_record->nfields * sizeof(unsigned char *));

				for (j = 0; j < tmp_record->nfields; j++) {
					tmp_record->fields[j] = payload;
					if (testBit(*payload, 7)) {
						tmp_record->nvendor++;
						tmp_record->vendor_fields =
						    realloc(tmp_record->vendor_fields,
							    tmp_record->nvendor *
							    sizeof(struct
								   ipfix_vendor_field_specifier));
						tmp_record->vendor_fields[tmp_record->nvendor -
									  1].id =
						    ntohs(*(uint16_t *) payload);
						payload += sizeof(uint16_t);
						tmp_record->vendor_fields[tmp_record->nvendor -
									  1].length =
						    ntohs(*(uint16_t *) payload);
						payload += sizeof(uint16_t);
						tmp_record->vendor_fields[tmp_record->nvendor -
									  1].enterprise =
						    ntohl(*(uint32_t *) payload);
						payload += sizeof(uint32_t);
						i += sizeof(struct ipfix_vendor_field_specifier);
					} else {
						tmp_record->nietf++;
						tmp_record->ietf_fields =
						    realloc(tmp_record->ietf_fields,
							    tmp_record->nietf *
							    sizeof(struct
								   ipfix_ietf_field_specifier));
						tmp_record->ietf_fields[tmp_record->nietf - 1].id =
						    ntohs(*(uint16_t *) payload);
						payload += sizeof(uint16_t);
						tmp_record->ietf_fields[tmp_record->nietf -
									1].length =
						    ntohs(*(uint16_t *) payload);
						payload += sizeof(uint16_t);
						i += sizeof(struct ipfix_ietf_field_specifier);
					}
				}
			}

			// Check against template records with the same ID and replace/insert.
			struct ipfix_template_record *tmp = NULL;
			for (j = 0; j < tmp_template->nrecords; j++) {
				if ((tmp =
				     flist_remove(flow->ipfix_templates,
						  tmp_template->records[j]->header->id,
						  FLIST_LEAVE_DATA)) != NULL) {
					// free it.
				}
				// Insert the new template record.
				flist_append(flow->ipfix_templates,
					     tmp_template->records[j]->header->id,
					     tmp_template->records[j]);
			}
		} else if (i == 3) {// Option Template set
		} else if (i >= 4 && i <= 255) { // reserved for future use
			payload += sizeof(uint16_t);
			payload += ntohs(*(uint16_t *) payload);
			continue;
		} else if (i > 256) { // Data set
			ipfix->data =
			    realloc(ipfix->data,
				    ++(ipfix->ndata) * sizeof(struct ipfix_data_set *));
			ipfix->data[ipfix->ndata - 1] = malloc(sizeof(struct ipfix_data_set));
			ipfix->data[ipfix->ndata - 1]->header = (struct ipfix_set_header *)payload;
			ipfix->data[ipfix->ndata - 1]->nfields = 0;
			payload += sizeof(struct ipfix_set_header);

			i = sizeof(struct ipfix_set_header);
			// If you try debugging this, good luck.
			while (i < ntohs(ipfix->data[ipfix->ndata - 1]->header->length)) {
				if (*(uint16_t *) payload == 0) { // Padding!
					payload =
					    (unsigned char *)ipfix->data[ipfix->ndata - 1]->header +
					    ntohs(ipfix->data[ipfix->ndata - 1]->header->length);
					break;
				}

				ipfix->data[ipfix->ndata - 1]->fields =
				    realloc(ipfix->data[ipfix->ndata - 1]->fields,
					    ++(ipfix->data[ipfix->ndata - 1]->nfields) *
					    sizeof(unsigned char *));
				ipfix->data[ipfix->ndata -
					    1]->fields[ipfix->data[ipfix->ndata - 1]->nfields - 1] =
				    payload;

				payload +=
				    ((unsigned char)(*payload & (1 << 8))) ? sizeof(struct
										    ipfix_vendor_field_specifier)
				    : sizeof(struct ipfix_ietf_field_specifier);
				i += ((unsigned char)(*payload & (1 << 8))) ? sizeof(struct
										     ipfix_vendor_field_specifier)
				    : sizeof(struct ipfix_ietf_field_specifier);
			}
		} else
			return (-1);
	}
	return (0);
}
Esempio n. 5
0
/*
 * Decodes a NetFlow v9 packet.
 * mfukar
 * Jan 12 2006
 */
int netflow_v9_decode(anonpacket * p, struct NETFLOW_V9 *netflow, struct anonflow *flow)
{
	int             i = 0;
	unsigned char  *payload = NULL;
	int             flowsets = 0;

	uint16_t        flowset_length = 0;

	uint16_t        int16 = 0;

	struct NF9_TEMPLATE_FLOWSET *tmp_template_flowset = NULL;

	struct NF9_OPTIONS_TEMPLATE *tmp_options_template = NULL;

	if (!netflow)
		return (-1);

	// Expecting a UDP datagram.
	if (!(p->udph))
		return (-1);
	// We are at least expecting a header.
	if (p->data == NULL || p->dsize < 20)
		return (-1);

	// Initialisations.
	memset(netflow, 0, sizeof(struct NETFLOW_V9));

	payload = p->data;

	netflow->header = (struct NF9_HEADER *)payload;
	payload += sizeof(struct NF9_HEADER);

	// Now get the flowsets.
	for (flowsets = ntohs(netflow->header->count); flowsets >= 0; flowsets--) {
		/*
		 * In most cases (ie. all), the header count field doesn't report
		 * the correct number of flowsets.
		 * This ugly piece of code will make sure we don't see any
		 * "additional" flowsets that in fact don't exist.
		 */
		if (((uint16_t) (payload - p->data)) >= p->dsize)
			return (1);

		//Switch on flowset's ID.
		int16 = ntohs(*((unsigned short *)payload));

		if (int16 == 0)	{ // Template flowset
			struct NF9_TEMPLATE *template_cache = NULL;
			// Allocate memory for the new flowset.
			netflow->template_flowsets =
			    realloc(netflow->template_flowsets,
				    (++netflow->ntemplates) *
				    sizeof(struct NF9_TEMPLATE_FLOWSET *));
			netflow->template_flowsets[netflow->ntemplates - 1] =
			    malloc(sizeof(struct NF9_TEMPLATE_FLOWSET));
			netflow->template_flowsets[netflow->ntemplates - 1]->c =
			    (struct NF9_FLOWSET_COMMON *)payload;

			tmp_template_flowset = netflow->template_flowsets[netflow->ntemplates - 1];
			tmp_template_flowset->ntemps = 0;
			tmp_template_flowset->templates = 0;

			payload += sizeof(struct NF9_FLOWSET_COMMON);

			flowset_length = ntohs(tmp_template_flowset->c->length);
			int16 = sizeof(struct NF9_FLOWSET_COMMON);

			while (int16 + sizeof(uint16_t) < flowset_length) {
				template_cache = malloc(sizeof(struct NF9_TEMPLATE));
				tmp_template_flowset->templates =
				    realloc(tmp_template_flowset->templates,
					    (++tmp_template_flowset->ntemps) *
					    sizeof(struct NF9_TEMPLATE *));
				tmp_template_flowset->templates[tmp_template_flowset->ntemps - 1] =
				    malloc(sizeof(struct NF9_TEMPLATE));
				tmp_template_flowset->templates[tmp_template_flowset->ntemps -
								1]->inf =
				    (struct NF9_TEMPLATE_INFO *)payload;
				payload += 2 * sizeof(uint16_t);
				int16 += 2 * sizeof(uint16_t);

				tmp_template_flowset->templates[tmp_template_flowset->ntemps -
								1]->records =
				    malloc(ntohs
					   (tmp_template_flowset->
					    templates[tmp_template_flowset->ntemps -
						      1]->inf->field_count) *
					   sizeof(struct NF9_TEMPLATE_RECORD *));

				for (i = 0;
				     i <
				     ntohs(tmp_template_flowset->
					   templates[tmp_template_flowset->ntemps -
						     1]->inf->field_count); i++) {
					tmp_template_flowset->templates[tmp_template_flowset->
									ntemps - 1]->records[i] =
					    (struct NF9_TEMPLATE_RECORD *)payload;
					payload += sizeof(struct NF9_TEMPLATE_RECORD);
				}

				int16 +=
				    ntohs(tmp_template_flowset->
					  templates[tmp_template_flowset->ntemps -
						    1]->inf->field_count) *
				    sizeof(struct NF9_TEMPLATE_RECORD);

				template_cache->inf = malloc(sizeof(struct NF9_TEMPLATE_INFO));
				template_cache->inf->template_id =
				    ntohs(tmp_template_flowset->
					  templates[tmp_template_flowset->ntemps -
						    1]->inf->template_id);
				template_cache->inf->field_count =
				    ntohs(tmp_template_flowset->
					  templates[tmp_template_flowset->ntemps -
						    1]->inf->field_count);
				template_cache->records =
				    malloc(template_cache->inf->field_count *
					   sizeof(struct NF9_TEMPLATE_RECORD *));

				for (i = 0; i < template_cache->inf->field_count; i++) {
					template_cache->records[i] =
					    malloc(sizeof(struct NF9_TEMPLATE_RECORD));
					template_cache->records[i]->field_type =
					    ntohs(tmp_template_flowset->
						  templates[tmp_template_flowset->ntemps -
							    1]->records[i]->field_type);
					template_cache->records[i]->field_length =
					    ntohs(tmp_template_flowset->
						  templates[tmp_template_flowset->ntemps -
							    1]->records[i]->field_length);
				}
				/*
				 * If a template with the same ID already exists,
				 * replace it with this one.
				 */
				struct NF9_TEMPLATE *tmp =
				    flist_remove(flow->nf9_templates,
						 template_cache->inf->template_id,
						 FLIST_LEAVE_DATA);
				if (tmp != NULL) {
					for (i = 0; i < tmp->inf->field_count; i++) {
						free(tmp->records[i]);
					}
					free(tmp->records);
					free(tmp->inf);
					free(tmp);
				}

				flist_append(flow->nf9_templates, template_cache->inf->template_id,
					     template_cache);
			}

			if (int16 != flowset_length)
				payload += sizeof(uint16_t);
		} else if (int16 == 1) { // This is an option template flowset.
			struct NF9_OPTIONS_TEMPLATE *options = NULL;
			// Allocate memory for the new flowset.
			netflow->option_templates = realloc(netflow->option_templates,
							    ++(netflow->noptions) *
							    sizeof(struct NF9_OPTIONS_TEMPLATE *));

			netflow->option_templates[netflow->noptions - 1] =
			    malloc(sizeof(struct NF9_OPTIONS_TEMPLATE));
			netflow->option_templates[netflow->noptions - 1]->c =
			    (struct NF9_FLOWSET_COMMON *)payload;
			payload += sizeof(struct NF9_FLOWSET_COMMON);

			tmp_options_template = netflow->option_templates[netflow->noptions - 1];
			tmp_options_template->inf = malloc(sizeof(struct NF9_OPTIONS_INFO));
			tmp_options_template->inf = (struct NF9_OPTIONS_INFO *)payload;
			payload += 3 * sizeof(uint16_t);

			tmp_options_template->nscopes =
			    tmp_options_template->inf->option_scope_len /
			    sizeof(struct NF9_TEMPLATE_RECORD);
			tmp_options_template->nopts =
			    tmp_options_template->inf->option_len /
			    sizeof(struct NF9_TEMPLATE_RECORD);

			// Grab the scope fields.
			tmp_options_template->scope_fields =
			    malloc(tmp_options_template->nscopes *
				   sizeof(struct NF9_TEMPLATE_RECORD *));
			for (i = 0; i < tmp_options_template->nscopes; i++) {
				tmp_options_template->scope_fields[i] =
				    (struct NF9_TEMPLATE_RECORD *)payload;
				payload += sizeof(struct NF9_TEMPLATE_RECORD);
			}

			// ..and the option fields.
			tmp_options_template->option_fields =
			    malloc(tmp_options_template->nopts *
				   sizeof(struct NF9_TEMPLATE_RECORD *));
			for (i = 0; i < tmp_options_template->nopts; i++) {
				tmp_options_template->option_fields[i] =
				    (struct NF9_TEMPLATE_RECORD *)payload;
				payload += sizeof(struct NF9_TEMPLATE_RECORD);
			}

			int16 = sizeof(struct NF9_FLOWSET_COMMON)
			    + 3 * sizeof(uint16_t)
			    + tmp_options_template->inf->option_scope_len
			    + tmp_options_template->inf->option_len;
			if (int16 != flowset_length)
				payload += sizeof(uint16_t);

			//  Insert the options template flowset in the list.
			options->c = malloc(sizeof(struct NF9_FLOWSET_COMMON));
			options->c->flowset_id = ntohs(tmp_options_template->c->flowset_id);
			options->c->length = ntohs(tmp_options_template->c->length);

			options->inf = malloc(sizeof(struct NF9_OPTIONS_INFO));
			options->inf->template_id = tmp_options_template->inf->template_id;
			options->inf->option_scope_len =
			    tmp_options_template->inf->option_scope_len;
			options->inf->option_len = tmp_options_template->inf->option_len;

			options->scope_fields = malloc(tmp_options_template->inf->option_scope_len);
			for (i = 0; i < tmp_options_template->nscopes; i++) {
				options->scope_fields[i]->field_type =
				    ntohs(tmp_options_template->scope_fields[i]->field_type);
				options->scope_fields[i]->field_length =
				    ntohs(tmp_options_template->scope_fields[i]->field_length);
			}
			options->option_fields = malloc(tmp_options_template->inf->option_len);
			for (i = 0; i < tmp_options_template->nopts; i++) {
				options->option_fields[i]->field_type =
				    ntohs(tmp_options_template->option_fields[i]->field_type);
				options->option_fields[i]->field_length =
				    ntohs(tmp_options_template->option_fields[i]->field_length);
			}
			flist_append(flow->nf9_option_templates, options->inf->template_id,
				     options);
		} else { // This is a data flowset.
			netflow->data_flowsets = realloc(netflow->data_flowsets,
							 ++(netflow->ndata) *
							 sizeof(struct NF9_DATA_FLOWSET *));
			netflow->data_flowsets[netflow->ndata - 1] =
			    malloc(sizeof(struct NF9_DATA_FLOWSET));
			netflow->data_flowsets[netflow->ndata - 1]->c =
			    (struct NF9_FLOWSET_COMMON *)payload;

			netflow->data_flowsets[netflow->ndata - 1]->field_values =
			    payload + sizeof(struct NF9_FLOWSET_COMMON);
			payload += ntohs(netflow->data_flowsets[netflow->ndata - 1]->c->length);
		}
	}
	return (1);
}
Esempio n. 6
0
static void mapidcom()
//Communicates with clients through IPC
{
	fd_set active_fd_set; // active file descriptor list
	fd_set read_fd_set; // temp file descriptor list for select()
	int fdmax; // maximum file descriptor number
	int yes = 1; // for setsockopt() SO_REUSEADDR, below
	struct sockaddr_un mapidaddr;
	struct sockaddr_un remoteaddr;
	struct mapiipcbuf qbuf;
	socklen_t addrlen;
	int nbytes, len, s;
	struct client *cl= NULL;
	flist_node_t *tmpnode;
	conf_category_entry_t *cat=NULL;
	char *local;
	struct group *mapi_group;
  conf_category_t *conf;

	mapidsocket=strdup(MAPIDSOCKGLOBAL);

	if ((conf = pc_load(mapid_conf)) != NULL) {
		cat = pc_get_category(conf, "");
		local=pc_get_param(cat, "local");
		if (local!=NULL && strcmp(local, "1")==0) {
			free(mapidsocket);
			mapidsocket=printf_string(MAPIDSOCKHOME, getenv("HOME") );
		}
		pc_close(conf);

	}
	//  create the listener socket
	if ((listenerfd = socket(AF_LOCAL, SOCK_STREAM, 0)) == -1) {
		DEBUG_CMD(Debug_Message("ERROR: socket: %s", strerror(errno)));
		exit(EXIT_FAILURE);
	}
	// avoid "address already in use" error message
	if (setsockopt(listenerfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))
			== -1) {
		DEBUG_CMD(Debug_Message("ERROR: setsockopt: %s", strerror(errno)));
		exit(EXIT_FAILURE);
	}
	//  set up the address we will be binding to
	memset(&mapidaddr, 0, sizeof (mapidaddr));
	mapidaddr.sun_family = AF_LOCAL;

	memcpy(mapidaddr.sun_path, mapidsocket, strlen(mapidsocket)+1);
	unlink(mapidsocket);

	len = sizeof mapidaddr.sun_family + strlen(mapidaddr.sun_path);
	if (bind(listenerfd, (struct sockaddr *) &mapidaddr, len)) {
		DEBUG_CMD(Debug_Message("ERROR: bind: %s", strerror(errno)));
		exit(EXIT_FAILURE);
	}

	// allow any member of our own group to connect
	chmod(mapidsocket, S_IRWXU | S_IRWXG);

	// if a mapi user group exists, set group permissions accordingly,
	// otherwise the group ID will be equal to the user ID of the user that
	// invoked mapid
	mapi_group = getgrnam(MAPI_GROUP_NAME);
	if (mapi_group != NULL) {
		chown(mapidsocket, -1, mapi_group->gr_gid);
	}

	if (listen(listenerfd, BACKLOG) == -1) {
		DEBUG_CMD(Debug_Message("ERROR: listen: %s", strerror(errno)));
		exit(EXIT_FAILURE);
	}

	FD_ZERO (&active_fd_set);
	// add the listener to the active set
	FD_SET (listenerfd, &active_fd_set)
;
  // keep track of the biggest file descriptor
  		fdmax = listenerfd; // so far, it's just this one

	// wait for commands from the mapi stub, for ever...
	while (1) {
		read_fd_set = active_fd_set; // copy it
		if (select(fdmax + 1, &read_fd_set, NULL, NULL, NULL) == -1) {
			DEBUG_CMD(Debug_Message("ERROR: select: %s", strerror(errno)));
			break;
		}

		// run through the existing connections
		for (s = 0; s <= fdmax; s++) {
			if (FD_ISSET (s, &read_fd_set)) {

				// connection on the original listener socket
				if (s == listenerfd) {
					addrlen = sizeof (remoteaddr);
					if ((newfd = accept(listenerfd,
							(struct sockaddr *) &remoteaddr, &addrlen)) == -1) {
						DEBUG_CMD(Debug_Message("accept: %s", strerror(errno)));
					} else {
						FD_SET (newfd, &active_fd_set)
;						// add to active set
						if (newfd > fdmax)
						{ // keep track of the maximum
							fdmax = newfd;
						}
					}
				}
				// handle data from an existing client
				else
				{
					if ((nbytes = recv (s, &qbuf, MAX_SEND_SIZE, 0)) <= 0)
					{
						if (nbytes == 0)
						{
							// connection closed - find client's pid
							while(__sync_lock_test_and_set(&clientlist_lock,1));
							tmpnode = (flist_node_t *) flist_head (clientlist);

							cl = NULL;
							while (tmpnode != NULL)
							{
								if (((struct client *) tmpnode->data)->sock == s)
								{
									cl = (struct client *) tmpnode->data;
									break;
								}
								tmpnode = flist_next (tmpnode);
							}
							clientlist_lock = 0;

							if (cl == NULL)
							{/* This is not interesting, as it will occur upon requests from clients without flows etc.
							 WARNING_CMD (printf
							 ("WARNING: Zero bytes from socket %d [%s:%d]\n",
							 s, __FILE__, __LINE__));
							 */
								/* shouldn't really exit here? 
								 * this will cause the program to exit on errors with an empty
								 * client-list which isn't really an error (IMHO)
								 */
								//exit(EXIT_FAILURE);
							}
							else
							{
								while(__sync_lock_test_and_set(&clientlist_lock,1));
								//clean up any remaining flows
								tmpnode = (flist_node_t *) flist_head (cl->flowlist);
								while (tmpnode != NULL)
								{
									cleanup_flow ((struct flow *) tmpnode->data);
									tmpnode = flist_next (tmpnode);
								}
								tmpnode = (flist_node_t *) flist_head (cl->devicelist);
								while (tmpnode != NULL)
								{
									mapidrv_delete_device = get_drv_funct (tmpnode->data, "mapidrv_delete_device");
									mapidrv_delete_device (tmpnode->id);
									tmpnode = flist_next (tmpnode);
								}
								flist_destroy (cl->flowlist);
								flist_destroy (cl->devicelist);
								free(cl->devicelist);
								free (cl->flowlist);
								//remove this client from global client list
								free(flist_remove (clientlist, cl->pid));
								clientlist_lock = 0;
							}
						}
						else
						{
							DEBUG_CMD(Debug_Message("WARNING: recv: %s at", strerror (errno)));
						}
						close (s);
						FD_CLR (s, &active_fd_set); // remove it from active set
					}
					else
					{
						// we got some data from a client: process request
						switch (qbuf.cmd)
						{
							case GET_LIBS:
							cmd_get_libs (qbuf.pid, s);
							break;
							case GET_LIBPATH:
							cmd_get_libpath (qbuf.pid, s);
							break;
							case CREATE_FLOW:
							cmd_create_flow ((char *)qbuf.data, qbuf.pid, qbuf.uid, s);
							break;
							case CLOSE_FLOW:
							cmd_close_flow (qbuf.fd, qbuf.pid, s, 1);
							break;
							case GET_FLOW_INFO:
							cmd_get_flow_info (qbuf.fd, qbuf.pid, s);
							break;
							case GET_FUNCTION_INFO:
							cmd_get_function_info (qbuf.fd, qbuf.fid, qbuf.pid, s);
							break;
							case GET_NEXT_FUNCTION_INFO:
							cmd_get_next_function_info (qbuf.fd, qbuf.fid, qbuf.pid, s);
							break;
							case GET_NEXT_FLOW_INFO:
							cmd_get_next_flow_info (qbuf.fd, qbuf.pid, s);
							break;
							case GET_NEXT_DEVICE_INFO:
							cmd_get_next_device_info (qbuf.fd, qbuf.pid, s);
							break;
							case GET_DEVICE_INFO:
							cmd_get_device_info (qbuf.fd, qbuf.pid, s);
							break;
						case MAPI_STATS:
						  cmd_stats ((char *)qbuf.data, qbuf.pid, qbuf.uid, s);
						  break;
							case APPLY_FUNCTION:
							cmd_apply_function (&qbuf, qbuf.pid, s);
							break;
							case READ_RESULT:
							cmd_read_results (qbuf.fd, qbuf.fid, qbuf.pid, s);
							break;
							case CONNECT:
							cmd_connect (qbuf.fd, qbuf.pid, s);
							break;
							case CREATE_FLOW_ACK:
							case APPLY_FUNCTION_ACK:
							case READ_RESULT_ACK:
							case CONNECT_ACK:
							case CLOSE_FLOW_ACK:
							case SET_AUTHDATA_ACK:
							break;
							case READ_ERROR_ACK:
							break;
							case ERROR_ACK:
							break;
							case CREATE_OFFLINE_DEVICE:
							cmd_create_offline_device ((char *)qbuf.data, qbuf.fid, qbuf.pid, s);
							break;
							case CREATE_OFFLINE_DEVICE_ACK:
							break;
							case START_OFFLINE_DEVICE:
							cmd_start_offline_device ((char *)qbuf.data, qbuf.pid, s);
							break;
							case START_OFFLINE_DEVICE_ACK:
							break;
							case DELETE_OFFLINE_DEVICE:
							cmd_delete_offline_device ((char *)qbuf.data, qbuf.pid, s);
							break;
							case DELETE_OFFLINE_DEVICE_ACK:
							break;
							case CREATE_OFFLINE_FLOW_ACK:
							break;
							case LOAD_LIBRARY:
							cmd_load_library ((char *)qbuf.data, qbuf.pid, s);
							default:
							break;
						}
					}
				}
			}
		} // for
	} // while(1)
}