Пример #1
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);
}
Пример #2
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);
}
Пример #3
0
static void cmd_create_offline_device(char *dev, int format, int pid, int sock)
//Create a new flow
//dev = device
//if = IPC id used to send ack message back to client
{
	struct mapiipcbuf buf;
	mapidrv *drv, *drv2, *lok;
	int err;
	int file;
	struct client *cl;
	char *format_;
	long file_size;

	//Get file descriptor
	buf.mtype = pid;
	buf.cmd = SEND_FD;
	mapiipc_daemon_write((struct mapiipcbuf *) &buf, sock);
	file = mapiipc_read_fd(sock);

	//Decide which driver to use
	for (drv = drvlist; drv != NULL; drv = drv->next) {
		if (drv->format == format) {
			DEBUG_CMD(Debug_Message("Using driver %s for %s", drv->name, dev));
			break;
		}
	}

	if (drv == NULL) {
		DEBUG_CMD(Debug_Message("ERROR: No driver found for %s", dev));
		report_error(MAPID_NO_DRIVER, pid, sock);
		return;
	}

	//Calls driver
	//First create new "device" for the file 
	drv2 = malloc(sizeof(mapidrv));
	drv2->device = malloc(strlen(dev)+7);
	sprintf(drv2->device, "%s@%d", dev, deviceid);
	lok=drvlist;

	while (lok->next!=NULL)
		lok = lok->next;
	lok->next = drv2;
	drv2->next=NULL;
	drv2->handle = drv->handle;
	drv2->name = strdup(drv->name);
	drv2->format = drv->format;
	drv2->devid = -deviceid++;
	drv2->offline = 1;
	drv2->active = 1;
	drv2->description = strdup(drv->description);
	drv2->offline_status = DEVICE_SETUP;

	mapidrv_add_device = get_drv_funct(drv->handle, "mapidrv_add_device");
	err = mapidrv_add_device(dev, file, drv2->devid, gflist,
			&drv2->offline_status);

	if (err != 0) {
		report_error(err, pid, sock);
		return;
	}

	// save a reference to the newly created flow to client's flow list
	cl = flist_get(clientlist, pid);
	if (cl == NULL) {
		cl = (struct client *) malloc(sizeof(struct client));
		cl->pid = pid;
		cl->sock = sock;
		// init the list that holds references to the flows of this client
		if ((cl->flowlist = malloc(sizeof(flist_t))) == NULL) {
			DEBUG_CMD(Debug_Message(
					"ERROR: cmd_create_flow - malloc new client struct: %s",
					strerror(errno)));
			exit(EXIT_FAILURE);
		}
		if ((cl->devicelist = malloc(sizeof(flist_t))) == NULL) {
			DEBUG_CMD(Debug_Message(
					"ERROR: cmd_create_flow - malloc new client struct: %s",
					strerror(errno)));
			exit(EXIT_FAILURE);
		}
		flist_init(cl->flowlist);
		flist_init(cl->devicelist);
		cl->numflows = 0;
		flist_append(clientlist, pid, cl);
	}

	flist_append(cl->devicelist, drv2->devid, drv->handle);
	cl->numdevs++;

	//Send ack back to user
	buf.mtype = pid;
	buf.cmd = CREATE_OFFLINE_DEVICE_ACK;
	strcpy((char *)buf.data, drv2->device);
	buf.fd = -1;

	if (format == 0)
		format_ = strdup("MFF_PCAP");
	else if (format == 1)
		format_ = strdup("MFF_RAW");
	else if (format == 2)
		format_ = strdup("MFF_DAG_ERF");
	else if (format == 4)
		format_ = strdup("MFF_NAPATECH");

	if (log_to_file) {
		file_size = acquire_write_lock(log_fd_info);
		write_to_file(
				log_fd_info,
				"MAPID: new offline device was created ( tracefile: %s, format: %s, device name returned: %s ) at ",
				dev, format_, buf.data);
		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(
				"new offline device was created ( tracefile: %s, format: %s, device name returned: %s )",
				dev, format_, buf.data);

	free(format_);
	mapiipc_daemon_write((struct mapiipcbuf *) &buf, sock);
}
Пример #4
0
int flowdrv_create_flow(const char *dev)
//Create new flow
//dev = device that should be used
{
  struct mapiipcbuf qbuf;
  flowdescr_t *flow, *tmpflow;

  pthread_once(&mapi_is_initialized, (void*)mapi_init);
  
  while(__sync_lock_test_and_set(mapi_lock,1));

  if (((*get_numflows)() == 0) && ((*get_totalflows)() > 0) && *minit){ // socket has been closed, re-create it
    if(mapiipc_client_init() == -1) {
      *local_err = MCOM_INIT_SOCKET_ERROR;
      *mapi_lock = 0;
      return -1;
    }
    (*incr_numflows)();
  }
  else 
    (*incr_numflows)();
  
  *mapi_lock = 0;

  strncpy((char *)qbuf.data,dev,DATA_SIZE);

  qbuf.mtype = 1;
  qbuf.cmd = CREATE_FLOW;
  qbuf.fd = getpid();
  qbuf.pid = getpid();
  
  while(__sync_lock_test_and_set(mapi_lock,1));

  if (mapiipc_write((struct mapiipcbuf*)&qbuf) < 0)
  {
    *local_err = MCOM_SOCKET_ERROR;
    *mapi_lock = 0;
    (*decr_numflows)();
    return -1;
  }
  if (mapiipc_read((struct mapiipcbuf*)&qbuf) < 0)
  {
    *local_err = MCOM_SOCKET_ERROR;
    *mapi_lock = 0;
    (*decr_numflows)();
    return -1;
  }
  *mapi_lock = 0;
  switch(qbuf.cmd)
  {
    case CREATE_FLOW_ACK:
      tmpflow = flist_get(*flowlist, qbuf.fd);
      if (tmpflow != NULL) 
      {
        printf("ERROR: Mapid gave us a fd (%d) which already exist in our lists, exiting [%s:%d]\n",
            qbuf.fd, __FILE__, __LINE__);
        (*decr_numflows)();
        return -1;
      }
      flow = malloc(sizeof(flowdescr_t));
      if (flow == NULL)
      {
        printf("ERROR: Out of memory [%s:%d]\n", __FILE__, __LINE__);
        (*decr_numflows)();
        return -1;
      }
      flow->fd = qbuf.fd;
      flow->devtype = (char *) malloc(strlen((char *)qbuf.data) + 1);
      flow->flist = malloc(sizeof(flist_t));

      flow->shm_base = NULL;
      flow->shm_spinlock = NULL;
      flow->file = -1;  // in case of online flow, assigned to -1
      flow->is_connected = 0;
      flow->numfd = 0;  // initialize number of open file descriptors to zero
      flist_init(flow->flist);
      strcpy(flow->devtype, (char *)qbuf.data);
      
      flowlist_t *flow_item = malloc(sizeof(flowlist_t));
      if (flow_item == NULL)
      {
        printf("ERROR: Out of memory [%s:%d]\n", __FILE__, __LINE__);
        (*decr_numflows)();
        return -1;
      }
      
      while(__sync_lock_test_and_set(mapi_lock,1));
      
      flow_item->fd = ++(*fd_counter);
      flow_item->flowtype = FLOWTYPE_LOCAL;
      flow_item->driver = *localdrv; // get_driver ?
      flow_item->flowdescr = flow;
      
      flist_append(*flowlist, *fd_counter, flow_item);
      (*incr_totalflows)();
      
      *mapi_lock = 0;
      
      return *fd_counter;
      
    /* should probably have a separate error message for ERROR_ACK? */
    case ERROR_ACK:
      (*decr_numflows)();
      *local_err = qbuf.remote_errorcode;
      return -1;
    default:
      (*decr_numflows)();
      *local_err = MCOM_UNKNOWN_ERROR;
      return -1;
  }
}
Пример #5
0
static void cmd_create_flow(char *device, int pid, uid_t uid, int sock) /*removed id, id==pid here */
//Create a new flow
//dev = device
//if = IPC id used to send ack message back to client
{
	struct flow *fl = (struct flow *) malloc(sizeof(struct flow));
	struct client *cl;
	struct mapiipcbuf buf;
	char *devtype;
	mapidrv *drv;
	int err = 0;
	char* dev=device;
	long file_size;

	fl->id = pid;
	fl->fd = ++fdseed;
	fl->drv = NULL;
	fl->uid = uid;
	fl->offline = 0;

	if (running_shutdown)
		err = MAPI_SHUTTING_DOWN;

	//Decide which driver to use
	for (drv = drvlist; drv != NULL; drv = drv->next) {
		if (drv->device != NULL)
			if (strcmp(dev, drv->device) == 0) {
				fl->drv = drv;
				DEBUG_CMD(Debug_Message("Using driver %s for %s", drv->name,
						dev));
				break;
			}
	}

	if (fl->drv == NULL) {
		DEBUG_CMD(Debug_Message("No driver found for %s", dev));
		report_error(MAPID_NO_DRIVER, pid, sock);
		free(fl);
		return;
	}

	++flows; //total number of currently registered flows

	//Calls driver
	if (err == 0) {
		mapidrv_create_flow = get_drv_funct(fl->drv->handle,
				"mapidrv_create_flow");
		err = mapidrv_create_flow(drv->devid, fl->fd, &devtype);

	}

	if (err != 0) {
		/* flow wasn't created */
		/* we can't leave the flow in place, but we need it for errno... */
		/* cleanup? */
		flows--;
		report_error(err, pid, sock);
		free(fl);
		return;
	} else {
		flist_append(flowlist, fl->fd, fl);

		//check if this is the first time we hear from this client
		cl = flist_get(clientlist, pid);
		if (cl == NULL) {
			cl = (struct client *) malloc(sizeof(struct client));
			cl->pid = pid;
			cl->sock = sock;
			// init the list that holds references to the flows of this client
			if ((cl->flowlist = malloc(sizeof(flist_t))) == NULL) {
				DEBUG_CMD(Debug_Message(
						"ERROR: cmd_create_flow - malloc new client struct: %s",
						strerror(errno)));
				exit(EXIT_FAILURE);
			}
			flist_init(cl->flowlist);
			if ((cl->devicelist = malloc(sizeof(flist_t))) == NULL) {
				DEBUG_CMD(Debug_Message(
						"ERROR: cmd_create_flow - malloc new client struct: %s",
						strerror(errno)));
				exit(EXIT_FAILURE);
			}
			flist_init(cl->devicelist);
			cl->numflows = 0;
			cl->numdevs = 0;
			flist_append(clientlist, pid, cl);
		}

		// save a reference to the newly created flow to client's flow list
		cl->numflows++;
		flist_append(cl->flowlist, fl->fd, fl);

		//Send ack back to user
		buf.mtype = pid;
		strcpy((char *)buf.data, devtype);
		buf.cmd = CREATE_FLOW_ACK;
		buf.fd = fl->fd;

		if (log_to_file) {
			file_size = acquire_write_lock(log_fd_info);
			write_to_file(log_fd_info,
					"MAPID: new flow was created ( device: %s, fd: %d ) at ",
					device, fl->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("new flow was created ( device: %s, fd: %d )", device,
					fl->fd);
	}

	mapiipc_daemon_write(&buf, sock);
}