- Add basic Ethernet ,IP, TCP and UDP dissector (IPv4 suite only)
- Add test script - Add SIGINT (CTRL+C) handler to print statistics before quitting
This commit is contained in:
parent
97b57d0055
commit
d18f1a8533
@ -5,5 +5,8 @@ FLAGS=-m32 -march=corei7 -mfpmath=sse -O3 #-g
|
|||||||
sipcap: sipcap.c Makefile
|
sipcap: sipcap.c Makefile
|
||||||
$(CC) $(FLAGS) $(INC) $(LIB) sipcap.c -o sipcap
|
$(CC) $(FLAGS) $(INC) $(LIB) sipcap.c -o sipcap
|
||||||
|
|
||||||
|
test: sipcap testrun.sh
|
||||||
|
/bin/sh testrun.sh
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
\/bin/rm -f sipcap
|
\/bin/rm -f sipcap
|
||||||
|
250
sipcap/sipcap.c
250
sipcap/sipcap.c
@ -1,17 +1,58 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <pcap.h>
|
#include <pcap.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <netinet/udp.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/if_ether.h>
|
||||||
|
|
||||||
#define SIPCAP_VERSION 1.2
|
#define SIPCAP_VERSION 1.2
|
||||||
|
|
||||||
#define ETHER_TYPE_IP (0x0800)
|
#define ETHER_TYPE_IP (0x0800)
|
||||||
#define ETHER_TYPE_8021Q (0x8100)
|
#define ETHER_TYPE_8021Q (0x8100)
|
||||||
|
|
||||||
|
/* tcpdump header (ether.h) defines ETHER_HDRLEN) */
|
||||||
|
#ifndef ETHER_HDRLEN
|
||||||
|
#define ETHER_HDRLEN 14
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UDP_HDRLEN 8
|
||||||
|
#define MAX_PAYLOAD_LEN 5000
|
||||||
|
|
||||||
|
// Global Structs
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure of an internet header, naked of options.
|
||||||
|
*
|
||||||
|
* Stolen from tcpdump source (thanks tcpdump people)
|
||||||
|
*
|
||||||
|
* We declare ip_len and ip_off to be short, rather than u_short
|
||||||
|
* pragmatically since otherwise unsigned comparisons can result
|
||||||
|
* against negative integers quite easily, and fail in subtle ways.
|
||||||
|
*/
|
||||||
|
struct my_ip {
|
||||||
|
u_int8_t ip_vhl; /* header length, version */
|
||||||
|
#define IP_V(ip) (((ip)->ip_vhl & 0xf0) >> 4)
|
||||||
|
#define IP_HL(ip) ((ip)->ip_vhl & 0x0f)
|
||||||
|
u_int8_t ip_tos; /* type of service */
|
||||||
|
u_int16_t ip_len; /* total length */
|
||||||
|
u_int16_t ip_id; /* identification */
|
||||||
|
u_int16_t ip_off; /* fragment offset field */
|
||||||
|
#define IP_DF 0x4000 /* dont fragment flag */
|
||||||
|
#define IP_MF 0x2000 /* more fragments flag */
|
||||||
|
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||||
|
u_int8_t ip_ttl; /* time to live */
|
||||||
|
u_int8_t ip_p; /* protocol */
|
||||||
|
u_int16_t ip_sum; /* checksum */
|
||||||
|
struct in_addr ip_src,ip_dst; /* source and dest address */
|
||||||
|
};
|
||||||
|
|
||||||
// Global Vars
|
// Global Vars
|
||||||
int pkt_count = 0;
|
static int pkt_count = 0;
|
||||||
int live_pcap = 0;
|
int live_pcap = 0;
|
||||||
int offline_pcap = 0;
|
int offline_pcap = 0;
|
||||||
int has_expression = 0;
|
int has_expression = 0;
|
||||||
@ -37,6 +78,7 @@ void error(char *msg) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void parse_options(int argc, char *argv[]) {
|
void parse_options(int argc, char *argv[]) {
|
||||||
|
|
||||||
// TODO: Add "-c" option that stops after capturing n packets
|
// TODO: Add "-c" option that stops after capturing n packets
|
||||||
@ -78,10 +120,205 @@ void parse_options(int argc, char *argv[]) {
|
|||||||
if (!live_pcap && !offline_pcap) help(1);
|
if (!live_pcap && !offline_pcap) help(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
|
u_char* handle_UDP
|
||||||
|
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char*
|
||||||
|
packet)
|
||||||
|
{
|
||||||
|
const struct udphdr* udp;
|
||||||
|
|
||||||
// we do actual packet processing here
|
const u_char *payload_data;
|
||||||
|
u_short payload_len;
|
||||||
|
char payload_str[MAX_PAYLOAD_LEN];
|
||||||
|
|
||||||
|
udp = (struct udphdr*) packet;
|
||||||
|
fprintf(stdout, "\tsport: %hu dport: %hu\n", ntohs(udp->uh_sport), ntohs(udp-> uh_dport));
|
||||||
|
|
||||||
|
payload_len = ntohs(udp->uh_ulen) - UDP_HDRLEN;
|
||||||
|
|
||||||
|
if (payload_len <= 0) return NULL;
|
||||||
|
|
||||||
|
payload_data = packet + UDP_HDRLEN;
|
||||||
|
|
||||||
|
(void)strncpy(payload_str, (const char*)payload_data, payload_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Now I have UDP payload as an string here and need to parse it
|
||||||
|
*/
|
||||||
|
// printf("\n\n%s\n\n", payload_str);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_char* handle_TCP
|
||||||
|
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char*
|
||||||
|
packet, u_int tcplen)
|
||||||
|
{
|
||||||
|
const struct tcphdr* tcp;
|
||||||
|
|
||||||
|
const u_char *payload_data;
|
||||||
|
u_short payload_len;
|
||||||
|
u_int hlen;
|
||||||
|
char payload_str[MAX_PAYLOAD_LEN];
|
||||||
|
|
||||||
|
tcp = (struct tcphdr*) packet;
|
||||||
|
fprintf(stdout, "\tsport: %hu dport: %hu\n", ntohs(tcp->th_sport), ntohs(tcp-> th_dport));
|
||||||
|
|
||||||
|
hlen = (tcp->th_off * 4);
|
||||||
|
|
||||||
|
payload_len = tcplen - hlen;
|
||||||
|
if (payload_len <= 0) return NULL;
|
||||||
|
|
||||||
|
payload_data = packet + hlen;
|
||||||
|
|
||||||
|
(void)strncpy(payload_str, (const char*)payload_data, payload_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Damn! I have TCP payload here too! Now need to write a parser.
|
||||||
|
*/
|
||||||
|
// printf("\n\n%s\n\n", payload_str);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_char* handle_IP
|
||||||
|
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char*
|
||||||
|
packet)
|
||||||
|
{
|
||||||
|
const struct my_ip* ip;
|
||||||
|
u_int length = pkthdr->len;
|
||||||
|
u_int hlen,off,version;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* jump pass the ethernet header */
|
||||||
|
ip = (struct my_ip*)(packet + sizeof(struct ether_header));
|
||||||
|
length -= sizeof(struct ether_header);
|
||||||
|
|
||||||
|
/* check to see we have a packet of valid length */
|
||||||
|
if (length < sizeof(struct my_ip))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ntohs(ip->ip_len);
|
||||||
|
hlen = IP_HL(ip); /* header length */
|
||||||
|
version = IP_V(ip);/* ip version */
|
||||||
|
|
||||||
|
/* check version */
|
||||||
|
if(version != 4)
|
||||||
|
{
|
||||||
|
fprintf(stdout,"Unknown version %d\n",version);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check header length */
|
||||||
|
if(hlen < 5 )
|
||||||
|
{
|
||||||
|
fprintf(stdout,"bad-hlen %d \n",hlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* see if we have as much packet as we should */
|
||||||
|
if(length < len)
|
||||||
|
printf("\ntruncated IP - %d bytes missing\n",len - length);
|
||||||
|
|
||||||
|
/* Check to see if we have the first fragment */
|
||||||
|
off = ntohs(ip->ip_off);
|
||||||
|
if((off & 0x1fff) == 0 )/* aka no 1's in first 13 bits */
|
||||||
|
{/* print SOURCE DESTINATION hlen version len offset */
|
||||||
|
|
||||||
|
switch (ip->ip_p) {
|
||||||
|
case 1:
|
||||||
|
fprintf(stdout, "ICMP");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
fprintf(stdout, "TCP");
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
fprintf(stdout, "UDP");
|
||||||
|
break;
|
||||||
|
case 41:
|
||||||
|
fprintf(stdout, "IPv6");
|
||||||
|
break;
|
||||||
|
case 47:
|
||||||
|
fprintf(stdout, "GRE");
|
||||||
|
break;
|
||||||
|
case 50:
|
||||||
|
fprintf(stdout, "ESP");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stdout, "UNKNOWN (%d)", ip->ip_p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout,":\t%s\t%s",
|
||||||
|
inet_ntoa(ip->ip_src),
|
||||||
|
inet_ntoa(ip->ip_dst));
|
||||||
|
|
||||||
|
fprintf(stdout,"\tlen= %3d hlen = %3d", len, hlen);
|
||||||
|
|
||||||
|
switch (ip->ip_p) {
|
||||||
|
case 6:
|
||||||
|
handle_TCP(args, pkthdr, packet + sizeof(struct ether_header) + (hlen * 4), len - (hlen * 4));
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
handle_UDP(args, pkthdr, packet + sizeof(struct ether_header) + (hlen * 4));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int16_t handle_ethernet
|
||||||
|
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char*
|
||||||
|
packet)
|
||||||
|
{
|
||||||
|
u_int caplen = pkthdr->caplen;
|
||||||
|
u_int length = pkthdr->len;
|
||||||
|
struct ether_header *eptr; /* net/ethernet.h */
|
||||||
|
u_short ether_type;
|
||||||
|
|
||||||
|
if (caplen < ETHER_HDRLEN)
|
||||||
|
{
|
||||||
|
// Bad Packet Captured - Try capturing full packet (or increase snaplen)
|
||||||
|
fprintf(stderr,"!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lets start with the ether header... */
|
||||||
|
eptr = (struct ether_header *) packet;
|
||||||
|
ether_type = ntohs(eptr->ether_type);
|
||||||
|
|
||||||
|
return ether_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
||||||
|
{
|
||||||
pkt_count++;
|
pkt_count++;
|
||||||
|
|
||||||
|
u_int16_t type = handle_ethernet(args, header, packet);
|
||||||
|
|
||||||
|
if (type != ETHERTYPE_IP) return;
|
||||||
|
handle_IP(args, header, packet);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_stat()
|
||||||
|
{
|
||||||
|
printf("finished processing %d packets\n", pkt_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void intHandler(int dummy) {
|
||||||
|
printf("\n");
|
||||||
|
print_stat();
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@ -92,6 +329,8 @@ int main(int argc, char *argv[])
|
|||||||
struct bpf_program fp;
|
struct bpf_program fp;
|
||||||
bpf_u_int32 devnet, devmask;
|
bpf_u_int32 devnet, devmask;
|
||||||
|
|
||||||
|
signal(SIGINT, intHandler);
|
||||||
|
|
||||||
parse_options(argc, argv);
|
parse_options(argc, argv);
|
||||||
|
|
||||||
if (live_pcap) {
|
if (live_pcap) {
|
||||||
@ -115,7 +354,10 @@ int main(int argc, char *argv[])
|
|||||||
if (pcap == NULL) error(errbuf);
|
if (pcap == NULL) error(errbuf);
|
||||||
|
|
||||||
pcap_loop(pcap, -1, &process_packet, NULL);
|
pcap_loop(pcap, -1, &process_packet, NULL);
|
||||||
printf("finished processing %d packets\n", pkt_count);
|
|
||||||
pcap_close(pcap);
|
pcap_close(pcap);
|
||||||
|
|
||||||
|
print_stat();
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
6
sipcap/testrun.sh
Executable file
6
sipcap/testrun.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
for i in `find ~/pcapfarm/*.pcap`; do
|
||||||
|
echo "Processing ${i}"
|
||||||
|
./sipcap -f ${i} | grep UNK
|
||||||
|
done
|
Loading…
x
Reference in New Issue
Block a user