void analyze(flow * flowrec) { if (flowrec->datapkts==pktlimit) { if (action==ACTION_LABEL) { if (!flowrec->isSSL) { flowrec->label=labeling(assign(flowrec->pkt_sizes,threshold),flowrec->dport); } else { flowrec->label=SSL_labeling(assign(flowrec->pkt_sizes,threshold),flowrec->dport); } } else { flowrec->label=LABEL_PARSED; } if (sslparsing && flowrec->label>0 && flowrec->label<=model.nbapplis && model.SSLapplis[flowrec->label-1]) { //If connection is SSL we continue the parsing flowrec->isSSL=1; flowrec->SSLdata=0; flowrec->datapkts=0; bzero(flowrec->pkt_sizes,pktlimit*sizeof(int16_t)); flowrec->labelSSL=flowrec->label; flowrec->label=LABEL_NONE; return; } if (memory>=OPT_NOSTORE) { //If we want to minimize memory usage, we print information about the connection and remove it from the hashtable print_flow(flowrec); clear_hash_entry(flow_hash,flowrec); } } }
static void dump_flows(flow * list) { flow * flowrec; for (flowrec = list; flowrec; flowrec = flowrec->next) { print_flow(flowrec); clear_hash_entry(flow_hash,flowrec); } }
static void clean_flows(flow * list, uint32_t ts) { flow * flowrec; flow * savflow; int i=0; flowrec=list; while (flowrec && ts-flowrec->ts_latest>EXP_TIME) { i++; savflow=flowrec; print_flow(flowrec); clear_hash_entry(flow_hash,flowrec); flowrec=savflow->next; } }
/*ARGSUSED*/ static int show_flow(dladm_handle_t handle, dladm_flow_attr_t *attr, void *arg) { show_flow_state_t *statep = arg; dladm_status_t status; flow_fields_buf_t fbuf; /* * first get all the flow attributes into fbuf; */ bzero(&fbuf, sizeof (fbuf)); status = print_flow(statep, attr, &fbuf); if (status != DLADM_STATUS_OK) goto done; ofmt_print(statep->fs_ofmt, (void *)&fbuf); done: statep->fs_status = status; return (DLADM_WALK_CONTINUE); }
static void dump_reader(u_char *user, const struct pcap_pkthdr *h, const u_char *p) { /* clear aguri_flow to be filled in parsers */ memset(&aguri_flow, 0, sizeof(aguri_flow)); (*net_reader)(user, h, p); if (aguri_flow.agflow_fs.fs_ipver == 0) /* not a IP packet */ return; aguri_flow.agflow_packets = htonl(1); aguri_flow.agflow_bytes = htonl(h->len); aguri_flow.agflow_first = aguri_flow.agflow_last = htonl((u_int32_t)h->ts.tv_sec); if (debug == 0) { if (fwrite(&aguri_flow, sizeof(aguri_flow), 1, stdout) != 1) err(1, "fwrite failed!"); } else print_flow(&aguri_flow); }
static int app_pipeline_fa_flow_ls(struct app_params *app, uint32_t pipeline_id) { struct app_pipeline_fa *p; uint32_t i; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id, &pipeline_flow_actions); if (p == NULL) return -1; for (i = 0; i < p->params.n_flows; i++) { struct app_pipeline_fa_flow *flow = &p->flows[i]; print_flow(p, i, flow); } return 0; }
int parse_sflow5(const char **p) { u_int32_t format, len; u_int32_t seqno, src_id, srate, total, drops, input, output, nrecords; u_int32_t record_type, record_len; u_int32_t protocol, framelen, stripped; int snaplen, i; format = buffer_read_4(p) & 0xfff; len = buffer_read_4(p); if (verbose > 1) fprintf(stderr, "sflow5: format:%u, len:%u\n", format, len); switch (format) { case 1: /* flow sample */ seqno = buffer_read_4(p); src_id = buffer_read_4(p); srate = buffer_read_4(p); total = buffer_read_4(p); drops = buffer_read_4(p); input = buffer_read_4(p); output = buffer_read_4(p); nrecords = buffer_read_4(p); sampling_rate = srate; if (verbose > 1) fprintf(stderr, "flow sample: srate:%u, nrecords:%u\n", srate, nrecords); for (i = 0; i < nrecords; i++) { record_type = buffer_read_4(p); record_len = buffer_read_4(p); /* clear aguri_flow to be filled in parsers */ memset(&aguri_flow, 0, sizeof(aguri_flow)); switch (record_type) { case 1: /* raw packet header */ protocol = buffer_read_4(p); framelen = buffer_read_4(p); stripped = buffer_read_4(p); record_len -= 12; if (verbose > 1) fprintf(stderr, "record type: raw header: proto:%u, rlen:%u flen:%u, stripped:%u\n", protocol, record_len, framelen, stripped); switch (protocol) { case 1: /* ethernet */ /* read the first 4 bytes for snaplen */ snaplen = ntohl(*((u_int32_t *)*p)); snapend = *p + 4 + snaplen; /* frame_length holds ethernet frame * length; we remove 4 bytes of FCS to * be consistent with pcap */ frame_length = framelen - 4; etherhdr_parse(*p + 4, snaplen); break; default: break; } buffer_skip(p, record_len); break; default: if (verbose > 1) fprintf(stderr, "record type:%u, len:%u\n", record_type, record_len); buffer_skip(p, record_len); break; } /* switch */ if (aguri_flow.agflow_fs.fs_ipver != 0) { /* flow info was filled by the parser: * for frame_length, we remove 4 bytes of FCS * to be consistent with pcap */ aguri_flow.agflow_packets = htonl(1 * srate); aguri_flow.agflow_bytes = htonl((framelen - 4) * srate); aguri_flow.agflow_first = aguri_flow.agflow_last = htonl((u_int32_t)timestamp); if (debug == 0) { if (fwrite(&aguri_flow, sizeof(aguri_flow), 1, stdout) != 1) err(1, "fwrite failed!"); } else print_flow(&aguri_flow); } } /* nrecords in sample */ break; case 2: /* counter sample */ buffer_skip(p, len); break; case 3: /* expanded flow sample */ buffer_skip(p, len); break; case 4: /* expanded counter sample */ buffer_skip(p, len); break; default: buffer_skip(p, len); break; } return (0); }
int parse_sflow4_sample(const char **p) { u_int32_t sample_type, packetdata_type; u_int32_t seqno, src_id, srate, total, drops, input, output; u_int32_t protocol, framelen, snaplen; u_int32_t interval, counters_version; u_int32_t nextended, extended_type, addr_type; u_int32_t aspath_len, asn_len, community_len, str_len; int i; sample_type = buffer_read_4(p); if (verbose > 1) fprintf(stderr, "sflow4: sample_type:%u\n", sample_type); switch (sample_type) { case 1: /* flow sample */ seqno = buffer_read_4(p); src_id = buffer_read_4(p); srate = buffer_read_4(p); total = buffer_read_4(p); drops = buffer_read_4(p); input = buffer_read_4(p); output = buffer_read_4(p); sampling_rate = srate; packetdata_type = buffer_read_4(p); if (verbose > 1) fprintf(stderr, "flow_sample: packetdata_type:%u, srate:%u\n", packetdata_type, srate); switch (packetdata_type) { case 1: /* header */ protocol = buffer_read_4(p); framelen = buffer_read_4(p); snaplen = buffer_read_4(p); if (verbose > 0) fprintf(stderr, "header: framelen:%u, snaplen:%u, proto:%u\n", framelen, snaplen, protocol); /* clear aguri_flow to be filled in parsers */ memset(&aguri_flow, 0, sizeof(aguri_flow)); switch (protocol) { case 1: /* ethernet */ snapend = *p + snaplen; etherhdr_parse(*p, snaplen); break; default: if (verbose > 0) fprintf(stderr, "unknown proto:%u\n", protocol); break; } buffer_skip(p, snaplen); if (aguri_flow.agflow_fs.fs_ipver != 0) { /* flow info was filled by the parser: * for frame_length, we remove 4 bytes of FCS * to be consistent with pcap */ aguri_flow.agflow_packets = htonl(1 * srate); aguri_flow.agflow_bytes = htonl((framelen - 4) * srate); aguri_flow.agflow_first = aguri_flow.agflow_last = htonl((u_int32_t)timestamp); if (debug == 0) { if (fwrite(&aguri_flow, sizeof(aguri_flow), 1, stdout) != 1) err(1, "fwrite failed!"); } else print_flow(&aguri_flow); } break; case 2: /* IPv4 */ buffer_skip(p, 8*4); if (verbose > 0) fprintf(stderr, "packetdata IPv4 not supported\n"); break; case 3: /* IPv6 */ buffer_skip(p, 14*4); if (verbose > 0) fprintf(stderr, "packetdata IPv6 not supported\n"); break; default: if (verbose > 0) fprintf(stderr, "unknown packetdata_type:%u\n", packetdata_type); return (-1); } /* extended data */ nextended = buffer_read_4(p); if (verbose > 0) fprintf(stderr, "extended data:%u\n", nextended); for (i = 0; i < nextended; i++) { extended_type = buffer_read_4(p); switch (extended_type) { case 1: /* switch */ buffer_skip(p, 4*4); break; case 2: /* router */ addr_type = buffer_read_4(p); switch (addr_type) { case 1: /* IPv4 */ buffer_skip(p, 4); break; case 2: /* IPv6 */ buffer_skip(p, 16); break; default: return (-1); } buffer_skip(p, 2*4); break; case 3: /* gateway */ buffer_skip(p, 3*4); aspath_len = buffer_read_4(p); while (aspath_len-- > 0) { buffer_skip(p, 4); if (sflow_version >= 4) { asn_len = buffer_read_4(p); while (asn_len-- > 0) buffer_skip(p, 4); } } community_len = buffer_read_4(p); buffer_skip(p, community_len * 4); buffer_skip(p, 4); break; case 4: /* user */ str_len = buffer_read_4(p); buffer_skip(p, str_len); str_len = buffer_read_4(p); buffer_skip(p, str_len); break; case 5: /* url */ buffer_skip(p, 4); str_len = buffer_read_4(p); buffer_skip(p, str_len); break; default: return (-1); } } break; case 2: /* counter sample */ seqno = buffer_read_4(p); src_id = buffer_read_4(p); interval = buffer_read_4(p); counters_version = buffer_read_4(p); if (verbose > 0) fprintf(stderr, "counter sample: type:%u\n", counters_version); switch (counters_version) { case 1: /* generic */ buffer_skip(p, 22*4); break; case 2: /* ethernet */ buffer_skip(p, 22*4); buffer_skip(p, 13*4); break; case 3: /* tokenring */ buffer_skip(p, 22*4); buffer_skip(p, 18*4); break; case 4: /* fddi */ buffer_skip(p, 22*4); break; case 5: /* 100basevg */ buffer_skip(p, 22*4); buffer_skip(p, 20*4); break; case 6: /* wan */ buffer_skip(p, 22*4); break; case 7: /* vlan */ buffer_skip(p, 7*4); break; default: if (verbose > 0) fprintf(stderr, "counter sample %d not supported\n", counters_version); return (-1); } break; default: if (verbose > 0) fprintf(stderr, "unknown sample_type %u\n", sample_type); return (-1); } return (0); }
void count_flow (const struct ip * ip,uint16_t iplen,uint32_t tspkt) { flow tmp, tmp_peer; flow * flowrec=NULL; uint16_t hsize,psize,sslsize; uint32_t seq; struct tcphdr *t; int direction=0; t=(struct tcphdr *)(((uint8_t*)ip) + ip->ip_hl*4); hsize=ip->ip_hl*4+t->doff*4; psize=ntohs(ip->ip_len)-hsize; seq=ntohl(t->seq); if (psize>0) { // If this packet is a data packet, we look for its connection in the hashtable /* Set the key to the source/destination address pair. */ tmp.src.s_addr = ip->ip_src.s_addr; tmp.dst.s_addr = ip->ip_dst.s_addr; tmp.sport = ntohs (t->source); tmp.dport = ntohs (t->dest); // Peer tmp_peer.src.s_addr = tmp.dst.s_addr; tmp_peer.dst.s_addr = tmp.src.s_addr; tmp_peer.sport = tmp.dport; tmp_peer.dport = tmp.sport; direction=0; if (flowrec = (flow *) find_hash_entry (flow_hash, &tmp)) { direction=1; } else if (flowrec = (flow *) find_hash_entry (flow_hash, &tmp_peer)) { direction=2; } if (direction>0 && flowrec->label==LABEL_NONE) { // Connection exists, is classifiable (SYN seen) and in sequence //First we reorder the list of connection (connections with most recent packets at the end of the list) if (flowrec->next) { //Else connection is already the last in the last so no modification //Connection cannot be the first we have a special empty pointer for the head of the list (first_flow) flowrec->prev->next=flowrec->next; flowrec->next->prev=flowrec->prev; active_flows->next=flowrec; flowrec->prev=active_flows; flowrec->next=NULL; active_flows=flowrec; } flowrec->ts_latest=tspkt; if (direction==1) { if (flowrec->data1==0) { //First packet with data flowrec->data1=1; flowrec->nextseq=seq+psize; } else if (flowrec->nextseq!=seq) { //Out of sequence packet, we remove the entry for this connection flowrec->label=LABEL_OUTOFSEQ; if (memory>=OPT_NOSTORE) { print_flow(flowrec); clear_hash_entry(flow_hash,flowrec); return ; } } else { flowrec->nextseq+=psize; } } if (direction==2) { if (flowrec->data2==0) { //First packet in reverse direction, initialize sequence number flowrec->data2=1; flowrec->nextseqpeer=seq+psize; } else if (flowrec->nextseqpeer!=seq) { flowrec->label=LABEL_OUTOFSEQ; if (memory>=OPT_NOSTORE) { print_flow(flowrec); clear_hash_entry(flow_hash,flowrec); return ; } } else { flowrec->nextseqpeer+=psize; } } if (!flowrec->isSSL) { assert(flowrec->datapkts<pktlimit); flowrec->pkt_sizes[flowrec->datapkts]=(direction==1) ? psize : -psize; flowrec->datapkts+=1; analyze(flowrec); } //If packet is SSL we parse it if (flowrec->isSSL) { sslsize=0; if (!flowrec->SSLdata) { sslsize=sslpayload(((uint8_t*)t)+t->doff*4,psize,iplen-hsize); if (sslsize>0) flowrec->SSLdata=1; } else sslsize=psize-5; //5: length of SSL header if (flowrec->SSLdata) { assert(flowrec->datapkts<pktlimit); flowrec->pkt_sizes[flowrec->datapkts]=(direction==1) ? clearsize(sslsize) : -clearsize(sslsize); flowrec->datapkts+=1; analyze(flowrec); } } } // Else: Connection is not classifiable: ignored } else if (t->syn==1 && t->ack==0) { // We are only intersted in SYN packets when there is no data flowrec = (flow *) malloc (sizeof (flow)); if (flowrec == NULL) { fprintf (stderr, "Can't malloc new connection\n"); abort (); } flowrec->pkt_sizes=(int16_t *)malloc(pktlimit*sizeof(int16_t)); if (flowrec->pkt_sizes == NULL) { fprintf (stderr, "Can't malloc new connection\n"); abort (); } flowrec->label=LABEL_NONE; bzero(flowrec->pkt_sizes,pktlimit*sizeof(int16_t)); flowrec->src.s_addr=ip->ip_src.s_addr; flowrec->dst.s_addr=ip->ip_dst.s_addr; flowrec->sport=ntohs (t->source); flowrec->dport=ntohs (t->dest); flowrec->nextseq=0; flowrec->nextseqpeer=0; flowrec->data1=0; flowrec->data2=0; flowrec->isSSL=0; flowrec->SSLdata=0; flowrec->datapkts=0; flowrec->ts_latest=tspkt; flowrec->prev = active_flows; flowrec->next = NULL; active_flows->next = flowrec; active_flows = flowrec; nbflows++; add_hash_entry (flow_hash, flowrec); } else if (memory>=OPT_GARBAGE && (t->rst || t->fin)) { // We remove connections in which we see RST or FIN /* Set the key to the source/destination address pair. */ tmp.src.s_addr = ip->ip_src.s_addr; tmp.dst.s_addr = ip->ip_dst.s_addr; tmp.sport = ntohs (t->source); tmp.dport = ntohs (t->dest); // Peer tmp_peer.src.s_addr = tmp.dst.s_addr; tmp_peer.dst.s_addr = tmp.src.s_addr; tmp_peer.sport = tmp.dport; tmp_peer.dport = tmp.sport; flowrec = (flow *) find_hash_entry (flow_hash, &tmp); if (!flowrec) flowrec = (flow *) find_hash_entry (flow_hash, &tmp_peer); if (flowrec) { print_flow(flowrec); clear_hash_entry(flow_hash,flowrec); return ; } } flowrec; }