void updateentry(struct tcptable *table, struct tcptableent *tableentry, struct tcphdr *transpacket, char *packet, int linkproto, unsigned long packetlength, unsigned int bcount, unsigned int fragofs, int logging, int *revlook, int rvnfd, FILE *logfile) { char msgstring[MSGSTRING_MAX]; char newmacaddr[18]; if (tableentry->s_fstat != RESOLVED) { tableentry->s_fstat = revname(revlook, &tableentry->saddr, tableentry->s_fqdn, sizeof(tableentry->s_fqdn), rvnfd); strcpy(tableentry->oth_connection->d_fqdn, tableentry->s_fqdn); tableentry->oth_connection->d_fstat = tableentry->s_fstat; } if (tableentry->d_fstat != RESOLVED) { tableentry->d_fstat = revname(revlook, &tableentry->daddr, tableentry->d_fqdn, sizeof(tableentry->d_fqdn), rvnfd); strcpy(tableentry->oth_connection->s_fqdn, tableentry->d_fqdn); tableentry->oth_connection->s_fstat = tableentry->d_fstat; } tableentry->pcount++; tableentry->bcount += bcount; tableentry->psize = packetlength; tableentry->spanbr += bcount; if (options.mac) { memset(newmacaddr, 0, sizeof(newmacaddr)); /* change updateentry to take struct pkt to remove this */ if (linkproto == ARPHRD_ETHER) { convmacaddr((char *) (((struct ethhdr *) packet)-> h_source), newmacaddr); } else if (linkproto == ARPHRD_FDDI) { convmacaddr((char *) (((struct fddihdr *) packet)-> saddr), newmacaddr); } if (tableentry->smacaddr[0] != '\0') { if (strcmp(tableentry->smacaddr, newmacaddr) != 0) { snprintf(msgstring, MSGSTRING_MAX, "TCP; %s; from %s:%s to %s:%s: new source MAC address %s (previously %s)", tableentry->ifname, tableentry->s_fqdn, tableentry->s_sname, tableentry->d_fqdn, tableentry->d_sname, newmacaddr, tableentry->smacaddr); writelog(logging, logfile, msgstring); strcpy(tableentry->smacaddr, newmacaddr); } } else strcpy(tableentry->smacaddr, newmacaddr); } /* * If this is not the first TCP fragment, skip interpretation of the * TCP header. */ if ((ntohs(fragofs) & 0x1fff) != 0) { tableentry->lastupdate = tableentry->oth_connection->lastupdate = time(NULL); return; } /* * At this point, we have a TCP header, and we proceed to process it. */ if (tableentry->pcount == 1) { if ((transpacket->syn) || (transpacket->rst)) tableentry->partial = 0; else tableentry->partial = 1; } tableentry->win = ntohs(transpacket->window); tableentry->stat = 0; if (transpacket->syn) tableentry->stat |= FLAG_SYN; if (transpacket->ack) { tableentry->stat |= FLAG_ACK; /* * The following sequences are used when the ACK is in response to * a FIN (see comments for FIN below). If the opposite direction * already has its indicator set to 1 (FIN sent, not ACKed), and * the incoming ACK has the same sequence number as the previously * stored FIN's ack number (i.e. the ACK in response to the opposite * flow's FIN), the opposite direction's state is set to 2 (FIN sent * and ACKed). */ if ((tableentry->oth_connection->finsent == 1) && (ntohl(transpacket->seq) == tableentry->oth_connection->finack)) { tableentry->oth_connection->finsent = 2; if (logging) { writetcplog(logging, logfile, tableentry, tableentry->psize, "FIN acknowleged"); } } } /* * The closing sequence is similar, but not identical to the TCP close * sequence described in the RFC. This sequence is primarily cosmetic. * * When a FIN is sent in a direction, a state indicator is set to 1, * to indicate a FIN sent, but not ACKed yet. For comparison later, * the acknowlegement number is also saved in the entry. See comments * in ACK above. */ if (transpacket->fin) { /* * First, we check if the opposite direction has no counts, in which * case we simply mark the entire connection available for reuse. * This is in case packets from a machine pass an interface, but * on the return, completely bypasses any interface on our machine. * * Q: Could such a situation really happen in practice? I managed to * do it but under *really* ridiculous circumstances. * * A: (as of version 2.5.0, June 2001): Yes this DOES happen in * practice. Unidirectional satellite feeds can send data straight * to a remote network using you as your upstream. */ if (tableentry->oth_connection->pcount == 0) addtoclosedlist(table, tableentry); else { /* * That aside, mark the direction as being done, and make it * ready for a complete close upon receipt of an ACK. We save * the acknowlegement number for identification of the proper * ACK packet when it arrives in the other direction. */ tableentry->finsent = 1; tableentry->finack = ntohl(transpacket->ack_seq); } if (logging) { char flowrate[64]; sprintf(msgstring, "FIN sent; %lu packets, %lu bytes, %s", tableentry->pcount, tableentry->bcount, tcplog_flowrate_msg(tableentry, flowrate, sizeof(flowrate))); writetcplog(logging, logfile, tableentry, tableentry->psize, msgstring); } } if (transpacket->rst) { tableentry->stat |= FLAG_RST; if (!(tableentry->inclosed)) addtoclosedlist(table, tableentry); if (logging) { char flowrate1[64]; char flowrate2[64]; snprintf(msgstring, MSGSTRING_MAX, "Connection reset; %lu packets, %lu bytes, %s; opposite direction %lu packets, %lu bytes; %s", tableentry->pcount, tableentry->bcount, tcplog_flowrate_msg(tableentry, flowrate1, sizeof(flowrate1)), tableentry->oth_connection->pcount, tableentry->oth_connection->bcount, tcplog_flowrate_msg(tableentry->oth_connection, flowrate2, sizeof(flowrate2))); writetcplog(logging, logfile, tableentry, tableentry->psize, msgstring); } } if (transpacket->psh) tableentry->stat |= FLAG_PSH; if (transpacket->urg) tableentry->stat |= FLAG_URG; tableentry->lastupdate = tableentry->oth_connection->lastupdate = time(NULL); /* * Shall we add this entry to the closed entry list? If both * directions have their state indicators set to 2, or one direction * is set to 2, and the other 1, that's it. */ if ((!tableentry->inclosed) && (((tableentry->finsent == 2) && ((tableentry->oth_connection->finsent == 1) || (tableentry->oth_connection->finsent == 2))) || ((tableentry->oth_connection->finsent == 2) && ((tableentry->finsent == 1) || (tableentry->finsent == 2))))) addtoclosedlist(table, tableentry); }
struct othptabent *add_othp_entry(struct othptable *table, struct pkt_hdr *pkt, struct sockaddr_storage *saddr, struct sockaddr_storage *daddr, int is_ip, int protocol, char *packet2, char *ifname, int *rev_lookup, int rvnfd, int logging, FILE *logfile, int fragment) { struct othptabent *new_entry; struct othptabent *temp; new_entry = xmallocz(sizeof(struct othptabent)); new_entry->is_ip = is_ip; new_entry->fragment = fragment; if (options.mac || !is_ip) { if (pkt->pkt_hatype == ARPHRD_ETHER) { convmacaddr((char *) pkt->ethhdr->h_source, new_entry->smacaddr); convmacaddr((char *) pkt->ethhdr->h_dest, new_entry->dmacaddr); } else if (pkt->pkt_hatype == ARPHRD_FDDI) { convmacaddr((char *) pkt->fddihdr->saddr, new_entry->smacaddr); convmacaddr((char *) pkt->fddihdr->daddr, new_entry->dmacaddr); } } if (is_ip) { sockaddr_copy(&new_entry->saddr, saddr); sockaddr_copy(&new_entry->daddr, daddr); revname(rev_lookup, saddr, new_entry->s_fqdn, sizeof(new_entry->s_fqdn), rvnfd); revname(rev_lookup, daddr, new_entry->d_fqdn, sizeof(new_entry->d_fqdn), rvnfd); if (!fragment) { if (protocol == IPPROTO_ICMP) { new_entry->un.icmp.type = ((struct icmphdr *) packet2)->type; new_entry->un.icmp.code = ((struct icmphdr *) packet2)->code; } else if (protocol == IPPROTO_ICMPV6) { new_entry->un.icmp6.type = ((struct icmp6_hdr *) packet2)->icmp6_type; new_entry->un.icmp6.code = ((struct icmp6_hdr *) packet2)->icmp6_code; } else if (protocol == IPPROTO_UDP) { servlook(ntohs(((struct udphdr *) packet2)->source), IPPROTO_UDP, new_entry->un.udp.s_sname, 10); servlook(ntohs(((struct udphdr *) packet2)->dest), IPPROTO_UDP, new_entry->un.udp.d_sname, 10); } else if (protocol == IPPROTO_OSPFIGP) { new_entry->un.ospf.type = ((struct ospfhdr *) packet2)->ospf_type; new_entry->un.ospf.area = ntohl(((struct ospfhdr *) packet2)-> ospf_areaid.s_addr); inet_ntop(AF_INET, &((struct ospfhdr *)packet2)->ospf_routerid, new_entry->un.ospf.routerid, sizeof(new_entry->un.ospf.routerid)); } } } else { new_entry->linkproto = pkt->pkt_hatype; if (protocol == ETH_P_ARP) { new_entry->un.arp.opcode = ((struct arp_hdr *) packet2)->ar_op; memcpy(&(new_entry->un.arp.src_ip_address), &(((struct arp_hdr *) packet2)->ar_sip), 4); memcpy(&(new_entry->un.arp.dest_ip_address), &(((struct arp_hdr *) packet2)->ar_tip), 4); } else if (protocol == ETH_P_RARP) { new_entry->un.rarp.opcode = ((struct arphdr *) packet2)->ar_op; memcpy(&(new_entry->un.rarp.src_mac_address), &(((struct arp_hdr *) packet2)->ar_sha), 6); memcpy(&(new_entry->un.rarp.dest_mac_address), &(((struct arp_hdr *) packet2)->ar_tha), 6); } } new_entry->protocol = protocol; strcpy(new_entry->iface, ifname); new_entry->pkt_length = pkt->pkt_len; if (table->head == NULL) { new_entry->prev_entry = NULL; table->head = new_entry; table->firstvisible = new_entry; } /* * Max number of entries in the lower window is 512. Upon reaching * this figure, oldest entries are thrown out. */ if (table->count == 512) { if (table->firstvisible == table->head) { wscrl(table->othpwin, 1); printothpentry(table, table->lastvisible->next_entry, table->oimaxy - 1, logging, logfile); table->firstvisible = table->firstvisible->next_entry; table->lastvisible = table->lastvisible->next_entry; } temp = table->head; table->head = table->head->next_entry; table->head->prev_entry = NULL; free(temp); } else table->count++; if (table->tail != NULL) { new_entry->prev_entry = table->tail; table->tail->next_entry = new_entry; } table->tail = new_entry; new_entry->next_entry = NULL; table->lastpos++; new_entry->index = table->lastpos; if (table->count <= table->oimaxy) { table->lastvisible = new_entry; printothpentry(table, new_entry, table->count - 1, logging, logfile); } else if (table->lastvisible == table->tail->prev_entry) { wscrl(table->othpwin, 1); table->firstvisible = table->firstvisible->next_entry; table->lastvisible = table->tail; printothpentry(table, new_entry, table->oimaxy - 1, logging, logfile); } return new_entry; }
struct tcptableent *addentry(struct tcptable *table, struct sockaddr_storage *saddr, struct sockaddr_storage *daddr, int protocol, char *ifname, int *rev_lookup, int rvnfd) { struct tcptableent *new_entry; struct closedlist *ctemp; /* * Allocate and attach a new node if no closed entries found */ if (table->closedentries == NULL) { new_entry = xmalloc(sizeof(struct tcptableent)); new_entry->oth_connection = xmalloc(sizeof(struct tcptableent)); new_entry->oth_connection->oth_connection = new_entry; if (table->head == NULL) { new_entry->prev_entry = NULL; table->head = new_entry; table->firstvisible = new_entry; } if (table->tail != NULL) { table->tail->next_entry = new_entry; new_entry->prev_entry = table->tail; } table->lastpos++; new_entry->index = table->lastpos; table->lastpos++; new_entry->oth_connection->index = table->lastpos; table->tail = new_entry->oth_connection; new_entry->next_entry = new_entry->oth_connection; new_entry->next_entry->prev_entry = new_entry; new_entry->next_entry->next_entry = NULL; if (new_entry->oth_connection->index <= table->firstvisible->index + (table->imaxy - 1)) table->lastvisible = new_entry->oth_connection; else if (new_entry->index <= table->firstvisible->index + (table->imaxy - 1)) table->lastvisible = new_entry; new_entry->reused = new_entry->oth_connection->reused = 0; table->count++; rate_alloc(&new_entry->rate, 5); rate_alloc(&new_entry->oth_connection->rate, 5); print_tcp_num_entries(table); } else { /* * If we reach this point, we're allocating off the list of closed * entries. In this case, we take the top entry, let the new_entry * variable point to whatever the top is pointing to. The new_entry's * oth_connection also points to the reused entry's oth_connection */ new_entry = table->closedentries->closedentry; new_entry->oth_connection = table->closedentries->pair; ctemp = table->closedentries; table->closedentries = table->closedentries->next_entry; free(ctemp); /* * Mark the closed list's tail as NULL if we use the last entry * in the list to prevent a dangling reference. */ if (table->closedentries == NULL) table->closedtail = NULL; new_entry->reused = new_entry->oth_connection->reused = 1; /* * Delete the old hash entries for this reallocated node; */ del_tcp_hash_node(table, new_entry); del_tcp_hash_node(table, new_entry->oth_connection); } /* * Fill in address fields with raw IP addresses */ sockaddr_copy(&new_entry->saddr, saddr); sockaddr_copy(&new_entry->oth_connection->daddr, saddr); sockaddr_copy(&new_entry->daddr, daddr); sockaddr_copy(&new_entry->oth_connection->saddr, daddr); new_entry->protocol = protocol; /* * Initialize count fields */ new_entry->pcount = new_entry->bcount = 0; new_entry->win = new_entry->psize = 0; new_entry->timedout = new_entry->oth_connection->timedout = 0; new_entry->oth_connection->pcount = new_entry->oth_connection->bcount = 0; new_entry->oth_connection->win = new_entry->oth_connection->psize = 0; /* * Store interface name */ strcpy(new_entry->ifname, ifname); strcpy(new_entry->oth_connection->ifname, ifname); /* * Zero out MAC address fields */ memset(new_entry->smacaddr, 0, sizeof(new_entry->smacaddr)); memset(new_entry->oth_connection->smacaddr, 0, sizeof(new_entry->oth_connection->smacaddr)); new_entry->stat = new_entry->oth_connection->stat = 0; new_entry->s_fstat = revname(rev_lookup, &new_entry->saddr, new_entry->s_fqdn, sizeof(new_entry->s_fqdn), rvnfd); new_entry->d_fstat = revname(rev_lookup, &new_entry->daddr, new_entry->d_fqdn, sizeof(new_entry->d_fqdn), rvnfd); /* set port service names (where applicable) */ servlook(sockaddr_get_port(saddr), IPPROTO_TCP, new_entry->s_sname, 10); servlook(sockaddr_get_port(daddr), IPPROTO_TCP, new_entry->d_sname, 10); strcpy(new_entry->oth_connection->s_sname, new_entry->d_sname); strcpy(new_entry->oth_connection->d_sname, new_entry->s_sname); strcpy(new_entry->oth_connection->d_fqdn, new_entry->s_fqdn); strcpy(new_entry->oth_connection->s_fqdn, new_entry->d_fqdn); new_entry->oth_connection->s_fstat = new_entry->d_fstat; new_entry->oth_connection->d_fstat = new_entry->s_fstat; if (new_entry->index < new_entry->oth_connection->index) { new_entry->half_bracket = ACS_ULCORNER; new_entry->oth_connection->half_bracket = ACS_LLCORNER; } else { new_entry->half_bracket = ACS_LLCORNER; new_entry->oth_connection->half_bracket = ACS_ULCORNER; } new_entry->inclosed = new_entry->oth_connection->inclosed = 0; new_entry->finack = new_entry->oth_connection->finack = 0; new_entry->finsent = new_entry->oth_connection->finsent = 0; new_entry->partial = new_entry->oth_connection->partial = 0; new_entry->spanbr = new_entry->oth_connection->spanbr = 0; new_entry->conn_starttime = new_entry->oth_connection->conn_starttime = time(NULL); rate_init(&new_entry->rate); rate_init(&new_entry->oth_connection->rate); /* * Mark flow rate start time and byte counter for flow computation * if the highlight bar is on either flow of the new connection. */ if (table->barptr == new_entry) { new_entry->starttime = time(NULL); new_entry->spanbr = 0; } else if (table->barptr == new_entry->oth_connection) { new_entry->oth_connection->starttime = time(NULL); new_entry->oth_connection->spanbr = 0; } /* * Add entries to hash table */ add_tcp_hash_entry(table, new_entry); add_tcp_hash_entry(table, new_entry->oth_connection); return new_entry; }
struct othptabent *add_othp_entry(struct othptable *table, struct tcptable *tcptab, unsigned long saddr, unsigned long daddr, int is_ip, int protocol, unsigned short linkproto, char *packet, char *packet2, unsigned int br, char *ifname, int *rev_lookup, int rvnfd, unsigned int tm, int logging, FILE * logfile, int servnames, int fragment, int *nomem) { struct othptabent *new_entry; struct othptabent *temp; struct in_addr isaddr, idaddr; new_entry = malloc(sizeof(struct othptabent)); if (new_entry == NULL) { printnomem(); *nomem = 1; return NULL; } bzero(new_entry, sizeof(struct othptabent)); new_entry->is_ip = is_ip; new_entry->fragment = fragment; if ((table->mac) || (!is_ip)) { if ((linkproto == LINK_ETHERNET) || (linkproto == LINK_PLIP)) { convmacaddr(((struct ethhdr *) packet)->h_source, new_entry->smacaddr); convmacaddr(((struct ethhdr *) packet)->h_dest, new_entry->dmacaddr); } else if (linkproto == LINK_FDDI) { convmacaddr(((struct fddihdr *) packet)->saddr, new_entry->smacaddr); convmacaddr(((struct fddihdr *) packet)->daddr, new_entry->dmacaddr); } else if (linkproto == LINK_TR) { convmacaddr(((struct trh_hdr *) packet)->saddr, new_entry->smacaddr); convmacaddr(((struct trh_hdr *) packet)->daddr, new_entry->dmacaddr); } } if (is_ip) { new_entry->saddr = isaddr.s_addr = saddr; new_entry->daddr = idaddr.s_addr = daddr; revname(rev_lookup, &isaddr, new_entry->s_fqdn, rvnfd); revname(rev_lookup, &idaddr, new_entry->d_fqdn, rvnfd); if (!fragment) { if (protocol == IPPROTO_ICMP) { new_entry->un.icmp.type = ((struct icmphdr *) packet2)->type; new_entry->un.icmp.code = ((struct icmphdr *) packet2)->code; } else if (protocol == IPPROTO_UDP) { servlook(servnames, ((struct udphdr *) packet2)->source, IPPROTO_UDP, new_entry->un.udp.s_sname, 10); servlook(servnames, ((struct udphdr *) packet2)->dest, IPPROTO_UDP, new_entry->un.udp.d_sname, 10); } else if (protocol == IPPROTO_OSPFIGP) { new_entry->un.ospf.type = ((struct ospfhdr *) packet2)->ospf_type; new_entry->un.ospf.area = ntohl(((struct ospfhdr *) packet2)->ospf_areaid. s_addr); strcpy(new_entry->un.ospf.routerid, inet_ntoa(((struct ospfhdr *) packet2)->ospf_routerid)); } } } else { new_entry->linkproto = linkproto; if (protocol == ETH_P_ARP) { new_entry->un.arp.opcode = ((struct arp_hdr *) packet2)->ar_op; memcpy(&(new_entry->un.arp.src_ip_address), &(((struct arp_hdr *) packet2)->ar_sip), 4); memcpy(&(new_entry->un.arp.dest_ip_address), &(((struct arp_hdr *) packet2)->ar_tip), 4); } else if (protocol == ETH_P_RARP) { new_entry->un.rarp.opcode = ((struct arphdr *) packet2)->ar_op; memcpy(&(new_entry->un.rarp.src_mac_address), &(((struct arp_hdr *) packet2)->ar_sha), 6); memcpy(&(new_entry->un.rarp.dest_mac_address), &(((struct arp_hdr *) packet2)->ar_tha), 6); } } new_entry->protocol = protocol; strcpy(new_entry->iface, ifname); new_entry->pkt_length = br; if (table->head == NULL) { new_entry->prev_entry = NULL; table->head = new_entry; table->firstvisible = new_entry; } /* * Max number of entries in the lower window is 512. Upon reaching * this figure, oldest entries are thrown out. */ if (table->count == 512) { if (table->firstvisible == table->head) { wscrl(table->othpwin, 1); printothpentry(table, table->lastvisible->next_entry, table->oimaxy - 1, logging, logfile); table->firstvisible = table->firstvisible->next_entry; table->lastvisible = table->lastvisible->next_entry; } temp = table->head; table->head = table->head->next_entry; table->head->prev_entry = NULL; free(temp); } else table->count++; if (table->tail != NULL) { new_entry->prev_entry = table->tail; table->tail->next_entry = new_entry; } table->tail = new_entry; new_entry->next_entry = NULL; table->lastpos++; new_entry->index = table->lastpos; if (table->count <= table->oimaxy) { table->lastvisible = new_entry; printothpentry(table, new_entry, table->count - 1, logging, logfile); } else if (table->lastvisible == table->tail->prev_entry) { wscrl(table->othpwin, 1); table->firstvisible = table->firstvisible->next_entry; table->lastvisible = table->tail; printothpentry(table, new_entry, table->oimaxy - 1, logging, logfile); } return new_entry; }