⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcptable.c

📁 一个网络流量分析的完整的程序
💻 C
📖 第 1 页 / 共 3 页
字号:
     * 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     */    *nomem = add_tcp_hash_entry(table, new_entry);    *nomem = add_tcp_hash_entry(table, new_entry->oth_connection);    return new_entry;}void addtoclosedlist(struct tcptable *table, struct tcptableent *entry,		     int *nomem){    struct closedlist *ctemp;    ctemp = malloc(sizeof(struct closedlist));    if (ctemp == NULL) {	printnomem();	*nomem = 1;	return;    }    /*     * Point to closed entries     */    ctemp->closedentry = entry;    ctemp->pair = entry->oth_connection;    entry->inclosed = entry->oth_connection->inclosed = 1;    /*     * Add node to closed entry list.     */    if (table->closedtail != NULL)	table->closedtail->next_entry = ctemp;    table->closedtail = ctemp;    table->closedtail->next_entry = NULL;    if (table->closedentries == NULL)	table->closedentries = ctemp;}char *tcplog_flowrate_msg(struct tcptableent *entry, struct OPTIONS *opts){    char rateunit[10];    float rate = 0;    static char message[60];    time_t interval;    interval = time(NULL) / (float) (entry->conn_starttime - time(NULL));        if (opts->actmode == KBITS) {         strcpy(rateunit, "kbits/s");                  if (interval > 0)             rate = (float) (entry->bcount * 8 / 1000) / (float) interval;         else             rate = 0.00;    } else {        strcpy(rateunit, "kbytes/s");                if (interval > 0)            rate = (float) (entry->bcount / 1024) / (float) interval;        else            rate = 0.00;    }       snprintf(message, 60, "avg flow rate %.2f %s", rate, rateunit);    return message;}void write_timeout_log(int logging, FILE * logfile,		       struct tcptableent *tcpnode, struct OPTIONS *opts){    char msgstring[MSGSTRING_MAX];    if (logging) {	snprintf(msgstring, MSGSTRING_MAX,		"TCP; Connection %s:%s to %s:%s timed out, %lu packets, %lu bytes, %s; opposite direction %lu packets, %lu bytes, %s",		tcpnode->s_fqdn, tcpnode->s_sname,		tcpnode->d_fqdn, tcpnode->d_sname,		tcpnode->pcount, tcpnode->bcount,		tcplog_flowrate_msg(tcpnode, opts),		tcpnode->oth_connection->pcount,		tcpnode->oth_connection->bcount,		tcplog_flowrate_msg(tcpnode->oth_connection, opts));	writelog(logging, logfile, msgstring);    }}struct tcptableent *in_table(struct tcptable *table, unsigned long saddr,			     unsigned long daddr, unsigned int sport,			     unsigned int dport, char *ifname,			     int logging, FILE * logfile,			     int *nomem, struct OPTIONS *opts){    struct tcp_hashentry *hashptr;    unsigned int hp;    int hastimeouts = 0;    time_t now;    time_t timeout;        if (opts != NULL)        timeout = opts->timeout;    else        timeout = 0;    if (table->head == NULL) {	return 0;    }    /*     * Determine hash table index for this set of addresses and ports     */    hp = tcp_hash(saddr, sport, daddr, dport, ifname);    hashptr = table->hash_table[hp];    while (hashptr != NULL) {	if ((hashptr->tcpnode->saddr.s_addr == saddr) &&	    (hashptr->tcpnode->daddr.s_addr == daddr) &&	    (hashptr->tcpnode->sport == sport) &&	    (hashptr->tcpnode->dport == dport) &&	    (strcmp(hashptr->tcpnode->ifname, ifname) == 0))	    break;	now = time(NULL);	/*	 * Add the timed out entries to the closed list in case we didn't	 * find any closed ones.	 */	if ((timeout > 0) && ((now - hashptr->tcpnode->lastupdate) / 60 > timeout)	    && (!(hashptr->tcpnode->inclosed))) {	    hashptr->tcpnode->timedout = 1;	    hashptr->tcpnode->oth_connection->timedout = 1;	    addtoclosedlist(table, hashptr->tcpnode, nomem);	    if (!(*nomem))		hastimeouts = 1;	    if (logging)		write_timeout_log(logging, logfile, hashptr->tcpnode, opts);	}	hashptr = hashptr->next_entry;    }    if (hashptr != NULL) {	/* needed to avoid SIGSEGV */	if ((((hashptr->tcpnode->finsent == 2) &&	      (hashptr->tcpnode->oth_connection->finsent == 2))) ||	    (((hashptr->tcpnode->stat & FLAG_RST) ||	      (hashptr->tcpnode->oth_connection->stat & FLAG_RST)))) {	    return NULL;	} else {	    return hashptr->tcpnode;	}    } else {	return NULL;    }}             /* * Update the TCP status record should an applicable packet arrive. */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, 		 struct OPTIONS *opts, FILE * logfile, int *nomem){    char msgstring[MSGSTRING_MAX];    char newmacaddr[15];    if (tableentry->s_fstat != RESOLVED) {	tableentry->s_fstat = revname(revlook, &(tableentry->saddr),				      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, 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 (opts->mac) {        bzero(newmacaddr, 15);        	if ((linkproto == LINK_ETHERNET) || (linkproto == LINK_PLIP)) {	    convmacaddr(((struct ethhdr *) packet)->h_source,			newmacaddr);	} else if (linkproto == LINK_FDDI) {	    convmacaddr(((struct fddihdr *) packet)->saddr,			newmacaddr);        } else if (linkproto == LINK_TR) {            convmacaddr(((struct trh_hdr *) 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, opts->mac, "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, nomem);	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) {	    sprintf(msgstring, "FIN sent; %lu packets, %lu bytes, %s",		    tableentry->pcount, tableentry->bcount, tcplog_flowrate_msg(tableentry, opts));	    writetcplog(logging, logfile, tableentry, tableentry->psize,			opts->mac, msgstring);	}    }    if (transpacket->rst) {	tableentry->stat |= FLAG_RST;	if (!(tableentry->inclosed))	    addtoclosedlist(table, tableentry, nomem);	if (logging) {	    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, opts),		    tableentry->oth_connection->pcount,		    tableentry->oth_connection->bcount, tcplog_flowrate_msg(tableentry->oth_connection, opts));	    writetcplog(logging, logfile, tableentry, tableentry->psize,			opts->mac, 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, nomem);}/* * Clears out the resolved IP addresses from the window.  This prevents * overlapping port numbers (in cases where the resolved DNS name is shorter * than its IP address), that may cause the illusion of large ports.  Plus, * such output, while may be interpreted by people with a little know-how, * is just plain wrong. * * Returns immediately if the entry is not visible in the window. */void clearaddr(struct tcptable *table, struct tcptableent *tableentry,	       unsigned int screen_idx){    unsigned int target_row;    if ((tableentry->index < screen_idx) ||	(tableentry->index > screen_idx + (table->imaxy - 1)))	return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -