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); }
/* * 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); }
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); }
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; } }
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); }