static unsigned char * get_ip_data(unsigned char *packet, const int pkt_len, int *p_l2_len) { int l2_len; u_char *ptr; pcap_t *pcap = clt_settings.pcap; l2_len = get_l2_len(packet, pkt_len, pcap_datalink(pcap)); *p_l2_len = l2_len; if (pkt_len <= l2_len) { return NULL; } #ifdef FORCE_ALIGN if (l2_len % 4 == 0) { ptr = (&(packet)[l2_len]); } else { ptr = pcap_ip_buf; memcpy(ptr, (&(packet)[l2_len]), pkt_len - l2_len); } #else ptr = (&(packet)[l2_len]); #endif return ptr; }
static void pcap_retrieve(unsigned char *args, const struct pcap_pkthdr *pkt_hdr, unsigned char *frame) { int l2_len, ip_pack_len, frame_len; pcap_t *pcap; unsigned char *ip_data; struct ethernet_hdr *ether; if (pkt_hdr->len < ETHERNET_HDR_LEN) { tc_log_info(LOG_ERR, 0, "recv len is less than:%d", ETHERNET_HDR_LEN); return; } pcap = (pcap_t *) args; frame_len = pkt_hdr->len; l2_len = get_l2_len(frame, frame_len, pcap_datalink(pcap)); if (l2_len != ETHERNET_HDR_LEN) { if (l2_len > ETHERNET_HDR_LEN) { ip_data = get_ip_data(pcap, frame, pkt_hdr->len, &l2_len); frame = ip_data - ETHERNET_HDR_LEN; frame_len = frame_len - l2_len + ETHERNET_HDR_LEN; } else if (l2_len == 0) { /* tunnel frames without ethernet header */ pcap_tunnel_retrieve(pcap, pkt_hdr, frame); return; } else { tc_log_info(LOG_WARN, 0, "l2 len is %d", l2_len); return; } } else { ether = (struct ethernet_hdr *) frame; if (ntohs(ether->ether_type) != ETH_P_IP) { return; } } ip_pack_len = pkt_hdr->len - l2_len; dispose_packet(frame, frame_len, ip_pack_len, NULL); }