📄 udp.c
字号:
/* This file is part of sniffer, a packet capture utility and network moniter The author can be contacted at <mistral@stev.org> the lastest version is avilable from http://stev.org This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>#include <netinet/in.h>#include "config.h"#include "locks.h"#include "list.h"#include "log.h"#include "stat.h"#include "in_ntoa.h"#include "hex.h"#include "lookup.h"#include "udp.h"struct gen_stat udp_stat;pthread_mutex_t udp_mutex = PTHREAD_MUTEX_INITIALIZER;WINDOW *udp_gui_window = NULL;pthread_mutex_t udp_gui_mutex = PTHREAD_MUTEX_INITIALIZER;struct list_t *udp_slist;pthread_mutex_t udp_mutex_slist = PTHREAD_MUTEX_INITIALIZER;/****************************************************************************** UDP Packets *********************************************************************************************************/int udp_handle(struct pkt_ip *ip, struct pkt_udp *udp) { void *pointer; unsigned short length; int index; char *ip_source = NULL, *ip_dest = NULL;#ifdef UDP_CHECKSUM unsigned short oldcheck;#endif struct udp_conn conn_search, *conn_tmp; pointer = (void *) udp + sizeof(struct pkt_udp); udp_stat.packets++; length = ntohs(udp->len) - 8;#ifdef UDP_CHECKSUM /* udp packet do not requie a checksum when the cksum is == 0 */ if (udp->check != 0) { oldcheck = udp->check; udp->check = 0; udp->check = udp_check(udp, length + 8, ip->saddr, ip->daddr); if (oldcheck != udp->check) { ip_source = lookup(ip->saddr, 0); ip_dest = lookup(ip->daddr, 0); log_error("FAILED UDP CHECKSUM: %s -> %s Packet: %u Sniffer: %u L:%u\n", ip_source, ip_dest, oldcheck, udp->check, length); udp_stat.dropped++; return -1; } }#endif udp_stat.bytes += length + 8; conn_search.saddr = ip->saddr; conn_search.daddr = ip->daddr; conn_search.sport = udp->source; conn_search.dport = udp->dest; SLOCK(&udp_mutex_slist); index = list_search(udp_slist, &conn_search); if (index < 0) { /* we now need to search in a different order */ conn_search.saddr = ip->daddr; conn_search.daddr = ip->saddr; conn_search.sport = udp->dest; conn_search.dport = udp->source; index = list_search(udp_slist, &conn_search); } if (index < 0) { conn_tmp = malloc(sizeof(struct udp_conn)); if (!conn_tmp) { log_err("malloc"); SUNLOCK(&udp_mutex_slist); return udp_gui_print(ip, udp, length); } conn_tmp->delme = 50; conn_tmp->saddr = ip->saddr; conn_tmp->saddr_str = in_ntoa(ip->saddr); conn_tmp->saddr_name = NULL; conn_tmp->daddr = ip->daddr; conn_tmp->daddr_str = in_ntoa(ip->saddr); conn_tmp->daddr_name = NULL; conn_tmp->sport = udp->source; conn_tmp->dport = udp->dest; init_stat(&conn_tmp->stat_in, NULL); init_stat(&conn_tmp->stat_out, NULL); list_add_sort(udp_slist, conn_tmp); } else { conn_tmp = list_get(udp_slist, index); } if (!conn_tmp) { /* this should not occur */ log_unreach(); SUNLOCK(&udp_mutex_slist); return udp_gui_print(ip, udp, length); } conn_tmp->delme = 50; if (conn_tmp->saddr == ip->saddr) { conn_tmp->stat_out.packets++; conn_tmp->stat_out.bytes += length; } else { conn_tmp->stat_in.packets++; conn_tmp->stat_in.bytes += length; } SUNLOCK(&udp_mutex_slist); return udp_gui_print(ip, udp, length);}int udp_cmp(struct udp_conn *c1, struct udp_conn *c2) { if (c1->saddr > c2->saddr) return -1; if (c1->saddr < c2->saddr) return 1; if (c1->daddr > c2->daddr) return -1; if (c1->daddr < c2->daddr) return 1; if (c1->sport > c2->sport) return -1; if (c1->sport < c2->sport) return 1; if (c1->dport > c2->dport) return -1; if (c1->dport < c2->dport) return 1; return 0;}int udp_dump_all(struct pkt_ip *ip, struct pkt_udp *udp, char *data, unsigned short data_len) { char *ip_source = NULL; char *ip_dest = NULL; int length; char buff[1024]; char *tmp; ip_source = lookup(ip->saddr, 0); ip_dest = lookup(ip->daddr, 0); length = sprintf(&buff[0], "%s [%u] -> %s [%u] L:%u\n", ip_source, ntohs(udp->source), ip_dest, ntohs(udp->dest), data_len); tmp = hex_conv(data, data_len); if (length < 0) { log_s("No Data in buffer"); } else { //write(log_fd_udp, &buff, length); //write(log_fd_udp, tmp, strlen(tmp)); } if (tmp) free(tmp); return 0;}inline unsigned short udp_check(struct pkt_udp *th, unsigned short len, unsigned long saddr, unsigned long daddr) { unsigned long sum = 0; unsigned short *buff; unsigned long ans; /* add the sorce address */ buff = (unsigned short *) &saddr; sum += *buff++; sum += *buff; /* add the dest address */ buff = (unsigned short *) &daddr; sum += *buff++; sum += *buff; /* add the zero + protocol */ sum += IP_UDP * 256; /* add the length */ sum += htons(len) & 0xffff; /* add the rest of the packet */ buff = (unsigned short *) th; while(len > 1) { sum += *buff++; len -= 2; } if (len == 1) /* do we need to mop up an odd byte ? */ sum += (*buff & 0xff); sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); ans = (~sum) & 0xffff; if (ans == 0) /* if udp cksum == 0 then it gets passed as all 1's */ ans = ~0; return ans;}void udp_gui_conn (struct gui_t *p, int y, int x) { WINDOW *draw; char *foot_back, buff[80]; int length, i, offset = 0; int cury; struct udp_conn *udp; draw = newwin(p->twin->_maxy - 1, p->twin->_maxx - 1, 1, 1); if (!draw) { log_s("subwin failed"); return; } wbkgd(draw, COLOR_PAIR(COL_BACK)); werase(draw); wrefresh(draw); foot_back = p->footer; while (1) { werase(draw); cury = 0; i = offset; if (offset > 0) mvwprintw(draw, 1, draw->_maxx - 12, "--more--"); stat_process(&udp_stat); snprintf(&buff[0], 80, "UDP Packets: %llu Data: %llu %s Drop: %llu", udp_stat.packets, udp_stat.readable, udp_stat.messure, udp_stat.dropped); gui_footer(p, &buff[0]); SLOCK(&udp_mutex_slist); length = list_len(udp_slist); while(cury < draw->_maxy && i < length) { udp = list_get(udp_slist, i); stat_process(&udp->stat_in); stat_process(&udp->stat_out); if (udp->saddr_name) { mvwprintw(draw, cury++, 0, "/%24.24s [%u] \t%4lli:%llu %s\t%.0f:%.2f/Sec", udp->saddr_name, ntohs(udp->sport), udp->stat_out.packets, udp->stat_out.readable, udp->stat_out.messure, udp->stat_out.rate_packets, udp->stat_out.rate_kb); } else { udp->saddr_name = lookup(udp->saddr, 1); mvwprintw(draw, cury++, 0, "/%24.24s [%u] \t%4lli:%llu %s\t%.0f:%.2f/Sec", udp->saddr_str, ntohs(udp->sport), udp->stat_out.packets, udp->stat_out.readable, udp->stat_out.messure, udp->stat_out.rate_packets, udp->stat_out.rate_kb); } if (udp->daddr_name) { mvwprintw(draw, cury++, 0, "\\%24.24s [%u] \t%4lli:%llu %s\t%.0f:%.2f/Sec", udp->daddr_name, ntohs(udp->dport), udp->stat_in.packets, udp->stat_in.readable, udp->stat_in.messure, udp->stat_in.rate_packets, udp->stat_in.rate_kb); } else { udp->daddr_name = lookup(udp->daddr, 1); mvwprintw(draw, cury++, 0, "\\%24.24s [%u] \t%4lli:%llu %s\t%.0f:%.2f/Sec", udp->daddr_str, ntohs(udp->dport), udp->stat_in.packets, udp->stat_in.readable, udp->stat_in.messure, udp->stat_in.rate_packets, udp->stat_in.rate_kb); } i++; } SUNLOCK(&udp_mutex_slist); if (cury == 0) /* do we have any entries ? */ mvwprintw(draw, cury++, 0, " -- No Entries --"); else mvwprintw(draw, cury++, 0, " -- END --"); if (cury > draw->_maxy - 1) mvwprintw(draw, draw->_maxy , draw->_maxx - 8, "--more--"); wrefresh(draw); switch(gui_scroll(250, 0, length, &offset)) { case -1: /* error / timeout */ break; case 0: /* it did something */ break; default: goto get_out; break; } /* end of switch gui_utils_scroll */ } /* end of while(1) */get_out: gui_footer(p, foot_back); werase(draw); wrefresh(draw); delwin(draw); return;}void udp_gui(struct gui_t *p, int y, int x) { WINDOW *draw; char *foot_back, buff[80]; SLOCK(&udp_gui_mutex); draw = newwin(p->twin->_maxy - 1, p->twin->_maxx - 1, 1, 1); if (!draw) { log_s("subwin failed"); SUNLOCK(&udp_gui_mutex); return; } wbkgd(draw, COLOR_PAIR(COL_BACK)); scrollok(draw, TRUE); werase(draw); wrefresh(draw); foot_back = p->footer; udp_gui_window = draw; SUNLOCK(&udp_gui_mutex); while (1) { if (gui_wait(250, 0) == 1) { switch(getch()) { default: goto get_out; break; } } else { stat_process(&udp_stat); SLOCK(&udp_gui_mutex); wrefresh(draw); snprintf(&buff[0], 80, "UDP Packets: %llu Data: %llu %s Drop: %llu", udp_stat.packets, udp_stat.readable, udp_stat.messure, udp_stat.dropped); gui_footer(p, &buff[0]); SUNLOCK(&udp_gui_mutex); } }get_out: gui_footer(p, foot_back); SLOCK(&udp_gui_mutex); udp_gui_window = NULL; SUNLOCK(&udp_gui_mutex); werase(draw); wrefresh(draw); delwin(draw); return;}int udp_gui_print(struct pkt_ip *ip, struct pkt_udp *udp, unsigned short length) { if (!udp_gui_window) return 0; SLOCK(&udp_gui_mutex); gui_print(udp_gui_window, "%13s(%5u) -> %13s(%5u) L:%u\n", lookup(ip->saddr, 0), ntohs(udp->source), lookup(ip->daddr, 0), ntohs(udp->dest), length); SUNLOCK(&udp_gui_mutex); return 0;}int udp_tidy() { struct udp_conn *tmp; int i, max = 15; SLOCK(&udp_mutex_slist); for(i=0;i<list_len(udp_slist);i++) { tmp = list_get(udp_slist, i); if (!tmp) { SUNLOCK(&udp_mutex_slist); return -1; } if (tmp->delme < 1) { list_del(udp_slist, i); i--; if (tmp->saddr_str) free(tmp->saddr_str); if (tmp->daddr_str) free(tmp->daddr_str); free(tmp); } else { tmp->delme--; } if (max < 1) { SUNLOCK(&udp_mutex_slist); max = 15; SLOCK(&udp_mutex_slist); } } SUNLOCK(&udp_mutex_slist); return 0;}int udp_init() { SLOCK(&udp_mutex_slist); udp_slist = list_init(); list_setcmp(udp_slist, (void *) udp_cmp); SUNLOCK(&udp_mutex_slist); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -