完善过滤最内层数据包处理逻辑.

This commit is contained in:
lijia
2018-11-16 11:42:54 +08:00
parent 42956e1602
commit e601cdb8ca
2 changed files with 154 additions and 19 deletions

View File

@@ -27,7 +27,7 @@ static int vlan8021q_jump_to_layer(const char *raw_data, int raw_layer_type, in
static int ipv4_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type);
static int ipv6_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type);
static int treat_vlan_as_mac_in_mac_sw = 1;
int treat_vlan_as_mac_in_mac_sw = 0; /* <20><>vlanǿ<6E>ư<EFBFBD>mac_in_mac<61><63>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>, <20>Ȳ<EFBFBD><C8B2><EFBFBD><EFBFBD>ݸ<EFBFBD>sapp, <20><>ΪӰ<CEAA><D3B0>sappȫ<70>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/* ascii<69>ַ<EFBFBD>ת16<31><36><EFBFBD><EFBFBD> */
char MESA_ascii_to_hex(char ascii)
@@ -124,10 +124,19 @@ static int udp_jump_to_layer(const char *raw_data, int raw_layer_type, int expe
if((2152 == usport) && (2152 == udport)){
skip_len = gtp_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), ADDR_TYPE_UDP, expect_layer_type);
}else if(4789 == udport){
/* vxlanģʽ<C4A3><CABD>ʱֻ֧<D6BB><D6A7>ethernet. TODO: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>hdlc, ppp<70><70>װ, <20><>Ҫʵ<D2AA><CAB5>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>vxlan_jump_to_layer()<29><><EFBFBD><EFBFBD> */
skip_len = eth_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr)+8, ADDR_TYPE_MAC, expect_layer_type);
if(skip_len < 0){
return -1;
}
skip_len += 8; /* skip vxlan header */
}else if((3544 == usport) || (3544 == udport)){
;
//TODO
//skip_len = teredo_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), ADDR_TYPE_UDP, expect_layer_type);
/* teredoʵ<6F><CAB5>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD>ͷ, ֱ<><D6B1><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ipv6<76><EFBFBD><E3BCB4> */
skip_len = ipv6_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
if(skip_len < 0){
return -1;
}
}else{
/* <20><><EFBFBD><EFBFBD>UDP<44><50><EFBFBD>Ͳ<EFBFBD>֧<EFBFBD><D6A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת */
return -1;
@@ -247,6 +256,7 @@ static int ipv6_jump_to_layer(const char *raw_data, int raw_layer_type, int exp
if(ADDR_TYPE_UDP == expect_layer_type){
skip_len = next_hdr_ptr - (UINT8 *)raw_data;
}else{
/* TODO: IPv6<76><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ */
skip_len = -1;
}
goto done;
@@ -478,7 +488,7 @@ static int vlan8021q_jump_to_layer(const char *raw_data, int raw_layer_type, in
break;
default:
printf("TODO: jmp unsupport type in vlan8021q, 0x%x!\n", ntohs(vlan_hdr->type));
printf("unsupport type in vlan8021q, 0x%x, You can try set the '--vlan-as-mac-in-mac' arg!\n", ntohs(vlan_hdr->type));
skip_len = -1;
}

153
tcpdump.c
View File

@@ -52,7 +52,11 @@ const char *tcpdump_thread_index_str;
int tcpdump_perceptive_flag = 0;
unsigned int perceptive_pkt_seq[256]; /* <20><><EFBFBD><EFBFBD>֧<EFBFBD><D6A7>256<35><36><EFBFBD>߳<EFBFBD> */
static int greedy_seek_flag = 0; /* ƫ<>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>ڲ<EFBFBD>IP, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3>²<EFBFBD><C2B2><EFBFBD>BUG */
static int dump_to_file_flag = 0; /* <20>Ƿ<EFBFBD><C7B7><EFBFBD>-w <20><><EFBFBD><EFBFBD> */
static int dump_to_file_flag = 0; /* <20>Ƿ<EFBFBD><C7B7><EFBFBD>-w <20><><EFBFBD><EFBFBD>, ԭ<>б<EFBFBD>׼<EFBFBD><D7BC>WFileName<6D><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>main()<29>ľֲ<C4BE><D6B2><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>, ʹ<>ô˱<C3B4><CBB1><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>Ƿ<EFBFBD>д<EFBFBD>ļ<EFBFBD> */
static int has_device_flag = 0; /* <20>Ƿ<EFBFBD><C7B7><EFBFBD>-i, -r<><72><EFBFBD><EFBFBD>, ԭ<>б<EFBFBD>׼<EFBFBD><D7BC>device<63><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>main()<29>ľֲ<C4BE><D6B2><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>, ʹ<>ô˱<C3B4><CBB1><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
static int has_bpf_filter_flag = 0; /* <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>BPF<50><46><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
extern int treat_vlan_as_mac_in_mac_sw;
#endif
#ifndef lint
@@ -207,6 +211,10 @@ static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_
static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
static void droproot(const char *, const char *);
static void MESA_dump_print_packet(unsigned char *user, const struct pcap_pkthdr *h, const unsigned char *pkt);
static void MESA_dump_packet(unsigned char *user, const struct pcap_pkthdr *h, const unsigned char *raw_pkt);
#ifdef SIGNAL_REQ_INFO
RETSIGTYPE requestinfo(int);
#endif
@@ -517,6 +525,10 @@ show_devices_and_exit (void)
#define OPTION_TSTAMP_PRECISION 129
#define OPTION_IMMEDIATE_MODE 130
#if MESA_DUMP
#define OPTION_VLAN_AS_MAC_IN_MAC 131 /* <20>̲<EFBFBD><CCB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD><EFBFBD><EFBFBD> */
#endif
static const struct option longopts[] = {
#if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
{ "buffer-size", required_argument, NULL, 'B' },
@@ -556,6 +568,9 @@ static const struct option longopts[] = {
{ "relinquish-privileges", required_argument, NULL, 'Z' },
{ "number", no_argument, NULL, '#' },
{ "version", no_argument, NULL, OPTION_VERSION },
#if MESA_DUMP
{ "vlan-as-mac-in-mac", no_argument, NULL, OPTION_VLAN_AS_MAC_IN_MAC },
#endif
{ NULL, 0, NULL, 0 }
};
@@ -810,7 +825,7 @@ static int MESA_dump_seek_to_inner(char *pkt_buf, int pktlen)
ip4hdr_greedy = (struct mesa_ip4_hdr *)MESA_net_jump_to_layer_greedy(pkt_buf, ADDR_TYPE_MAC, __ADDR_TYPE_IP_PAIR_V4);
if(ip4hdr_greedy){
if((char *)ip4hdr_greedy == first_ip_layer){
bpf_match_pkt_len = pktlen; /* <20><><EFBFBD>ڲ<EFBFBD><DAB2>͵<EFBFBD>һ<EFBFBD><D2BB>IPһ<50><D2BB>, ˵<><CBB5><EFBFBD>DZ<EFBFBD>׼ethernet->IPv4<76><34>, <20><><EFBFBD><EFBFBD>memmove<76><65><EFBFBD><EFBFBD> */
bpf_match_pkt_len = pktlen; /* <20><><EFBFBD>ڲ<EFBFBD><DAB2>͵<EFBFBD>һ<EFBFBD><D2BB>IPһ<50><D2BB>, ˵<><CBB5><EFBFBD>Ƿdz<EFBFBD><EFBFBD><EFBFBD>׼<EFBFBD><EFBFBD>ethernet->IPv4<76><34>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>memmove<76><65><EFBFBD><EFBFBD> */
}else{
memmove(pkt_buf + sizeof(struct mesa_ethernet_hdr),
ip4hdr_greedy,
@@ -835,7 +850,7 @@ static int MESA_dump_seek_to_inner(char *pkt_buf, int pktlen)
ip6hdr_greedy = (struct mesa_ip6_hdr *)MESA_net_jump_to_layer_greedy(pkt_buf, ADDR_TYPE_MAC, __ADDR_TYPE_IP_PAIR_V6);
if(ip6hdr_greedy){
if((char *)ip6hdr_greedy == first_ip_layer){
bpf_match_pkt_len = pktlen; /* <20><><EFBFBD>ڲ<EFBFBD><DAB2>͵<EFBFBD>һ<EFBFBD><D2BB>IPһ<50><D2BB>, ˵<><CBB5><EFBFBD>DZ<EFBFBD>׼ethernet->IPv6<76><36>, <20><><EFBFBD><EFBFBD>memmove<76><65><EFBFBD><EFBFBD> */
bpf_match_pkt_len = pktlen; /* <20><><EFBFBD>ڲ<EFBFBD><DAB2>͵<EFBFBD>һ<EFBFBD><D2BB>IPһ<50><D2BB>, ˵<><CBB5><EFBFBD>Ƿdz<EFBFBD><EFBFBD><EFBFBD>׼<EFBFBD><EFBFBD>ethernet->IPv6<76><36>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>memmove<76><65><EFBFBD><EFBFBD> */
}else{
memmove(pkt_buf + sizeof(struct mesa_ethernet_hdr),
ip6hdr_greedy,
@@ -1187,6 +1202,9 @@ static void _build_perceptive_pkt(pcap_handler callback, u_char *pcap_userdata,
}
}
/*
<09><>sapp<70><70><EFBFBD><EFBFBD>, <20><><EFBFBD>DZ<EFBFBD>׼tcpdump<6D><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
*/
static void MESA_dump(pcap_handler callback, u_char *pcap_userdata, char *filter,
int tot_pkt, unsigned short sapp_cmd_port )
{
@@ -1274,10 +1292,14 @@ done:
close(udp_rcv_fd);
}
exit(1);
return;
}
#endif
static struct bpf_program fcode; /* lijia modify, <20><>Ϊȫ<CEAA>ֱ<EFBFBD><D6B1><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD> */
int
main(int argc, char **argv)
{
@@ -1288,7 +1310,7 @@ main(int argc, char **argv)
pcap_handler callback;
int dlt;
const char *dlt_name;
struct bpf_program fcode;
#ifndef _WIN32
RETSIGTYPE (*oldhandler)(int);
#endif
@@ -1511,6 +1533,9 @@ main(int argc, char **argv)
}
#endif /* HAVE_PCAP_FINDALLDEVS */
device = optarg;
#if MESA_DUMP
has_device_flag = 1;
#endif
break;
#ifdef HAVE_PCAP_CREATE
@@ -1650,12 +1675,10 @@ main(int argc, char **argv)
#endif /* HAVE_PCAP_SETDIRECTION */
case 'r':
#if MESA_DUMP
printf("tcpdump_mesa not support -r arg, only support capture from sapp so far, TODO!\n");
exit(1);
#else
RFileName = optarg;
#endif
#if MESA_DUMP
has_device_flag = 1;
#endif
break;
case 's':
@@ -1803,6 +1826,12 @@ main(int argc, char **argv)
break;
#endif
#if MESA_DUMP
case OPTION_VLAN_AS_MAC_IN_MAC:
treat_vlan_as_mac_in_mac_sw = 1;
break;
#endif
default:
print_usage();
exit(1);
@@ -2145,8 +2174,12 @@ main(int argc, char **argv)
#ifdef HAVE_PCAP_SET_OPTIMIZER_DEBUG
pcap_set_optimizer_debug(dflag);
#endif
if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0){
error("%s", pcap_geterr(pd));
}else{
has_bpf_filter_flag = 1;
}
if (dflag) {
bpf_dump(&fcode, dflag);
pcap_close(pd);
@@ -2220,8 +2253,23 @@ main(int argc, char **argv)
}
#endif /* _WIN32 */
#if MESA_DUMP
/*
<09><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD> -g<><67><EFBFBD><EFBFBD>, <20><>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>IP,PORT<52><54>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>ֱ<EFBFBD>ӽ<EFBFBD>bpfӦ<66>õ<EFBFBD>pcap<61><70><EFBFBD><EFBFBD>,
<09><>Ϊ<EFBFBD>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, һ<><D2BB><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>˲<EFBFBD><CBB2><EFBFBD>.
<09>˴<EFBFBD><CBB4><EFBFBD><EFBFBD>ܼӹ<DCBC><D3B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>bpf_filter()<29>ټ<EFBFBD><D9BC><EFBFBD>һ<EFBFBD><D2BB>,
<09><>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>pcap<61>ײ<EFBFBD>Ӧ<EFBFBD><D3A6>bpfЧ<66><D0A7><EFBFBD>е<EFBFBD><D0B5><EFBFBD>.
*/
if(0 == greedy_seek_flag){
if (pcap_setfilter(pd, &fcode) < 0)
error("%s", pcap_geterr(pd));
}
#else
if (pcap_setfilter(pd, &fcode) < 0)
error("%s", pcap_geterr(pd));
#endif
#ifdef HAVE_CAPSICUM
if (RFileName == NULL && VFileName == NULL) {
static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
@@ -2304,6 +2352,12 @@ main(int argc, char **argv)
pcap_userdata = (u_char *)&dumpinfo;
} else {
callback = dump_packet;
#if MESA_DUMP
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B6A8>greedyѡ<79><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>BPF<50><46><EFBFBD><EFBFBD>, <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>MESA_dump_packet(), ƫ<>Ƶ<EFBFBD><C6B5>ڲ<EFBFBD>IP<49>ٱ<EFBFBD><D9B1><EFBFBD> */
if((greedy_seek_flag != 0) && (has_bpf_filter_flag != 0)){
callback = MESA_dump_packet; /* <20><><EFBFBD><EFBFBD>callbackָ<6B><D6B8> */
}
#endif
pcap_userdata = (u_char *)p;
}
#ifdef HAVE_PCAP_DUMP_FLUSH
@@ -2314,6 +2368,12 @@ main(int argc, char **argv)
dlt = pcap_datalink(pd);
ndo->ndo_if_printer = get_if_printer(ndo, dlt);
callback = print_packet;
#if MESA_DUMP
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B6A8>greedyѡ<79><D1A1>, <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>MESA_dump_print_packet(), ƫ<>Ƶ<EFBFBD><C6B5>ڲ<EFBFBD>IP<49>ٴ<EFBFBD><D9B4><EFBFBD> */
if(greedy_seek_flag != 0){
callback = MESA_dump_print_packet; /* <20><><EFBFBD><EFBFBD>callbackָ<6B><D6B8> */
}
#endif
pcap_userdata = (u_char *)ndo;
}
@@ -2376,7 +2436,11 @@ main(int argc, char **argv)
#endif /* HAVE_CAPSICUM */
/***************************** starting capture... ***********************************/
#if (0 == MESA_DUMP)
if(0 == has_device_flag){
MESA_dump(callback, pcap_userdata, cmdbuf, cnt, sapp_cmd_port);
}
do {
status = pcap_loop(pd, cnt, callback, pcap_userdata);
if (WFileName == NULL) {
@@ -2491,9 +2555,6 @@ main(int argc, char **argv)
}
}
while (ret != NULL);
#else
MESA_dump(callback, pcap_userdata, cmdbuf, cnt, sapp_cmd_port);
#endif
free(cmdbuf);
pcap_freecode(&fcode);
@@ -2875,6 +2936,40 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
info(0);
}
static void
MESA_dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *raw_pkt)
{
char modify_pkt_buf[2048];
int inner_pkt_len;
++packets_captured;
++infodelay;
memcpy(modify_pkt_buf, raw_pkt, h->caplen >= 2048? 2048:h->caplen);
inner_pkt_len = MESA_dump_seek_to_inner(modify_pkt_buf, h->caplen);
if(inner_pkt_len < 0){
return;
}
if(has_bpf_filter_flag != 0){
if(0 == bpf_filter(fcode.bf_insns,
(const unsigned char *)modify_pkt_buf, inner_pkt_len, inner_pkt_len)){
return;
}
}
/* -w<><77><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><E6B4A2>, ʵ<>ʴ洢<CAB4>İ<EFBFBD><C4B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭʼ<D4AD><CABC><EFBFBD><EFBFBD>, ֻ<><D6BB>BPF<50><46><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD> */
pcap_dump(user, h, raw_pkt);
#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
pcap_dump_flush((pcap_dumper_t *)user);
#endif
--infodelay;
if (infoprint)
info(0);
}
static void
print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
{
@@ -2889,6 +2984,34 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
info(0);
}
static void
MESA_dump_print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
{
int inner_pkt_len;
/* <20>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>tcpdump<6D><70>Ļ<EFBFBD><C4BB>ӡ, ֱ<><D6B1><EFBFBD>޸<EFBFBD>pktԭʼ<D4AD><CABC>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>copyһ<79><D2BB>, <20><>Լ<EFBFBD><D4BC>CPU */
inner_pkt_len = MESA_dump_seek_to_inner(pkt, h->caplen);
if(inner_pkt_len < 0){
return;
}
if(has_bpf_filter_flag != 0){
if(0 == bpf_filter(fcode.bf_insns,
(const unsigned char *)pkt, inner_pkt_len, inner_pkt_len)){
return;
}
}
/* <20><>Ϊ<EFBFBD>µ<EFBFBD><C2B5>޸ĺ<DEB8><C4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><DDB0><EFBFBD><EFBFBD><EFBFBD> */
((struct pcap_pkthdr *)h)->caplen = (unsigned int)inner_pkt_len;
((struct pcap_pkthdr *)h)->len = (unsigned int)inner_pkt_len;
print_packet(user, h, pkt);
}
#ifdef _WIN32
/*
* XXX - there should really be libpcap calls to get the version
@@ -3029,6 +3152,8 @@ print_usage(void)
"\t\t[ -o offset ] to assign offset from MAC, for skip some low layer data, for example: vxlan=50, mac_in_mac=14.\n");
(void)fprintf(stderr,
"\t\t[ -P port ] to assign sapp recv command port.\n");
(void)fprintf(stderr,
"\t\t[ --vlan-as-mac-in-mac ] force VLAN to be analysed as MAC-IN-MAC format.\n");
#endif
}
/*