📄 sniff.c
字号:
/* * * This is free software. You can redistribute it and/or modify under * the terms of the GNU General Public License version 2. * * Copyright (C) 1998 by kra * */#include "hunt.h"#include <sys/stat.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <ctype.h>#include <errno.h>#define SNIFF_FILE_DIR ".sniff"int o_newline = 0;struct sniff_log { unsigned int src_addr; unsigned int dst_addr; unsigned short src_port; unsigned short dst_port; int src_to_dst; int loged_bytes; char *buf; int state; int file_close; FILE *file; struct sniff_log *next;};struct sniff_info { unsigned int src_addr; unsigned int dst_addr; int src_mask; int dst_mask; int src_ports[MAX_PORTS + 1]; int dst_ports[MAX_PORTS + 1]; int srch_mode; char *search; int log_mode; int log_bytes; int file_close; FILE *file; struct list log; pthread_mutex_t mutex;};static struct ifunc_item ifunc_sniff;static int sniffer_running = 0;static struct list l_sniff_pkt = LIST_INIT(struct packet, p_next[MODULE_SNIFF]);static pthread_t sniff_thr;static struct list l_sniff_db = LIST_INIT(struct sniff_log, next);#define STATE_SRCH 1#define STATE_LOG 2#define LOG_BUF_SIZE 2048 void free_sniff_log(struct sniff_log *slog){ if (slog->buf) free(slog->buf); if (slog->file_close) fclose(slog->file); free(slog);}void free_sniff_info(struct sniff_info *si){ struct sniff_log *slog; if (si->search) free(si->search); while ((slog = list_pop(&si->log))) free_sniff_log(slog); if (si->file && si->file_close) fclose(si->file); free(si);}static void sniff_item_print(FILE *f, int i, struct sniff_info *si){ char *str_srch_mode, *str_log_mode; char buf_src_ports[BUFSIZE], buf_dst_ports[BUFSIZE]; char buf[BUFSIZE], *b; char host_buf[BUFSIZE]; str_srch_mode = sdbmode_to_char(si->srch_mode); str_log_mode = sdbmode_to_char(si->log_mode); sprintf_db_ports(si->src_ports, buf_src_ports, sizeof(buf_src_ports), 1); sprintf_db_ports(si->dst_ports, buf_dst_ports, sizeof(buf_dst_ports), 1); b = buf; if (si->search) b += sprintf(b, "%s for X ", str_srch_mode); b += sprintf(b, "log %s %dB", str_log_mode, si->log_bytes); sprintf(host_buf, "%s/%d [%s]", host_lookup(si->src_addr, hl_mode), count_mask(si->src_mask), buf_src_ports); fprintf(f, "%2d) %-22s --> %s/%d [%s] %s\n", i, host_buf, host_lookup(si->dst_addr, hl_mode), count_mask(si->dst_mask), buf_dst_ports, buf);}static void sniff_log_item_print(FILE *f, struct sniff_info *si, struct sniff_log *slog){ char *direction; if (slog->src_to_dst) direction = "-->"; else direction = "<--"; fprintf(f, "%s [%d] %s %s [%d]\n", host_lookup(slog->src_addr, hl_mode), ntohs(slog->src_port), direction, host_lookup(slog->dst_addr, hl_mode), ntohs(slog->dst_port));}/**************************************************************************** * * functions called from hunt * */static inline int sniff_packet_match(struct packet *p, struct sniff_info *si){ struct iphdr *iph = p->p_iph; struct tcphdr *tcph = p->p_hdr.p_tcph; if ((si->srch_mode == MODE_SRC || si->srch_mode == MODE_BOTH || si->log_mode == MODE_SRC || si->log_mode == MODE_BOTH) && (iph->saddr & si->src_mask) == (si->src_addr & si->src_mask) && (iph->daddr & si->dst_mask) == (si->dst_addr & si->dst_mask) && port_match(tcph->source, si->src_ports) && port_match(tcph->dest, si->dst_ports)) return 1; if ((si->srch_mode == MODE_DST || si->srch_mode == MODE_BOTH || si->log_mode == MODE_DST || si->log_mode == MODE_BOTH) && (iph->saddr & si->dst_mask) == (si->dst_addr & si->dst_mask) && (iph->daddr & si->src_mask) == (si->src_addr & si->src_mask) && port_match(tcph->source, si->dst_ports) && port_match(tcph->dest, si->src_ports)) return 1; return 0;}static void func_sniff(struct packet *p, void *arg){ struct list_iterator li; struct sniff_info *si;/* * locking l_sniff_db and si->mutex is needed as the si is set to the packet message * and will be used in sniff daemon */ list_lock(&l_sniff_db); list_iter_set(&li, &l_sniff_db); while ((si = list_iter_get(&li))) { if (sniff_packet_match(p, si)) { packet_want(p); pthread_mutex_lock(&si->mutex); p->p_arg[MODULE_SNIFF] = si; list_produce(&l_sniff_pkt, p); break; } } list_iter_end(&li); list_unlock(&l_sniff_db);}/**************************************************************************************** * * functions for sniff daemon * */void sniffer_log_print(struct sniff_info *si, struct sniff_log *slog){ char file_name[BUFSIZE], file_name_buf[BUFSIZE]; struct stat stat_buf; FILE *f; int i; if (!slog->loged_bytes) return; if (!slog->file) { if (!si->file) { sprintf(file_name_buf, "%s/%s:%d_%s:%d", SNIFF_FILE_DIR, host_lookup(slog->src_addr, HL_MODE_DEFERRED), ntohs(slog->src_port), host_lookup(slog->dst_addr, HL_MODE_DEFERRED), ntohs(slog->dst_port)); errno = 0; i = 0; strcpy(file_name, file_name_buf); while (stat(file_name, &stat_buf) >= 0 && errno != ENOENT) sprintf(file_name, "%s_%d", file_name_buf, ++i); if (!(f = fopen(file_name, "w"))) { printf("can't open %s for writing\n", file_name); return; } slog->file = f; slog->file_close = 1; } else { slog->file = si->file; slog->file_close = 0; } } sniff_log_item_print(slog->file, si, slog); for (i = 0; i < slog->loged_bytes; i++) { if (isprint(slog->buf[i]) || (o_newline && isspace(slog->buf[i]))) fputc(slog->buf[i], slog->file); else fprintf(slog->file, "[0x%X]", (unsigned char) slog->buf[i]); } fprintf(slog->file, "\n\n"); fflush(slog->file); slog->loged_bytes = 0;}char *memfind(char *data, int data_len, char *str, int str_len){ char *d; if (data_len == 0 || str_len == 0 || data_len < str_len) return NULL;#if 0 { int i; for (i = 0; i < data_len; i++) { if (isprint(data[i])) fputc(data[i], stdout); else fprintf(stdout, "[0x%X]", (unsigned char) data[i]); } fprintf(stdout, "\n\n"); }#endif while (data_len >= str_len) { if ((d = memchr(data, str[0], data_len - str_len + 1))) { if (memcmp(d, str, str_len) == 0) { return d; } data_len -= (d - data) + 1; data = d + 1; } else break; } return NULL;}char *sniff_log_match(struct packet *p, struct sniff_info *si, struct sniff_log *slog){ struct iphdr *iph = p->p_iph; struct tcphdr *tcph = p->p_hdr.p_tcph; int m_src_to_dst, m_dst_to_src; int find; char *log_data, *retval = NULL; find = 0; m_src_to_dst = m_dst_to_src = 0; if (iph->saddr == slog->src_addr && iph->daddr == slog->dst_addr && tcph->source == slog->src_port && tcph->dest == slog->dst_port) m_src_to_dst = 1; if (iph->daddr == slog->src_addr && iph->saddr == slog->dst_addr && tcph->dest == slog->src_port && tcph->source == slog->dst_port) m_dst_to_src = 1; if (!m_dst_to_src && !m_src_to_dst) return NULL; log_data = p->p_data; switch (slog->state) { case STATE_SRCH: if ((si->srch_mode == MODE_SRC || si->srch_mode == MODE_BOTH) && m_src_to_dst) find = 1; else if ((si->srch_mode == MODE_DST || si->srch_mode == MODE_BOTH) && m_dst_to_src) find = 1; if (find) { if (si->search) { log_data = memfind(p->p_data, p->p_data_len, si->search, strlen(si->search)); if (log_data) { slog->state = STATE_LOG; } } else { log_data = p->p_data; slog->state = STATE_LOG; } } if (slog->state != STATE_LOG) break; /* go through */ case STATE_LOG: if ((si->log_mode == MODE_SRC || si->log_mode == MODE_BOTH) && m_src_to_dst) { retval = log_data; } else if ((si->log_mode == MODE_DST || si->log_mode == MODE_BOTH) && m_dst_to_src) { retval = log_data; } break; default: fprintf(stderr, "sniffer - bad state\n"); retval = NULL; break; } if (!retval) retval = (void *) 1; return retval;}char *sniffer_match(struct packet *p, struct sniff_info *si, struct sniff_log **__slog){ struct iphdr *iph = p->p_iph; struct tcphdr *tcph = p->p_hdr.p_tcph; char *retval = NULL; struct list_iterator li; struct sniff_log *slog; list_iter_set(&li, &si->log); retval = NULL; while ((slog = list_iter_get(&li))) { if ((retval = sniff_log_match(p, si, slog))) break; } list_iter_end(&li); if (!retval && p->p_data_len) { slog = malloc(sizeof(struct sniff_log)); if (ntohs(tcph->dest) >= 1024 && ntohs(tcph->source) < 1024) { slog->src_addr = iph->daddr; slog->dst_addr = iph->saddr; slog->src_port = tcph->dest; slog->dst_port = tcph->source; } else { slog->src_addr = iph->saddr; slog->dst_addr = iph->daddr; slog->src_port = tcph->source; slog->dst_port = tcph->dest; } slog->file = NULL; slog->file_close = 0; slog->src_to_dst = 0; slog->loged_bytes = 0; slog->buf = NULL; slog->state = si->search ? STATE_SRCH : STATE_LOG; slog->next = NULL; list_push(&si->log, slog); retval = sniff_log_match(p, si, slog); /* ok, request - resolve addresses for future use */ host_lookup(slog->src_addr, HL_MODE_DEFERRED); host_lookup(slog->dst_addr, HL_MODE_DEFERRED); } if (retval) { if (p->p_hdr.p_tcph->rst || p->p_hdr.p_tcph->fin) { /* ok, wee don't handle half open connection */ sniffer_log_print(si, slog); assert(list_remove(&si->log, slog)); free_sniff_log(slog); retval = NULL; } } if (retval == (void *) 1) retval = NULL; if (retval) *__slog = slog; else *__slog = NULL; return retval;}#if 0static void log_data(FILE *f, char *data, int data_len){ char *d; for (d = data; d < data + data_len; d++) { if (isprint(*d) || (o_newline && isspace(*d))) fputc(*d, f); else fprintf(f, "[0x%X]", (unsigned char) *d); }}#endifvoid sniffer_log(char *data, struct packet *p, struct sniff_info *si, struct sniff_log *slog){ int data_len, space, i; if (!data) return; if (!slog->buf) slog->buf = malloc(LOG_BUF_SIZE); data_len = p->p_data_len - (data - p->p_data);#if 0 printf("log data_len = %d: --", data_len); log_data(stdout, data, data_len); printf("\n");#endif if (data_len || slog->loged_bytes >= si->log_bytes) { struct iphdr *iph = p->p_iph; if (slog->src_to_dst && slog->src_addr == iph->daddr) { sniffer_log_print(si, slog); slog->src_to_dst = 0; } else if (!slog->src_to_dst && slog->src_addr == iph->saddr) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -