- 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
|
||||
$(CC) $(FLAGS) $(INC) $(LIB) sipcap.c -o sipcap
|
||||
|
||||
test: sipcap testrun.sh
|
||||
/bin/sh testrun.sh
|
||||
|
||||
clean:
|
||||
\/bin/rm -f sipcap
|
||||
|
250
sipcap/sipcap.c
250
sipcap/sipcap.c
@ -1,17 +1,58 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <pcap.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#define SIPCAP_VERSION 1.2
|
||||
|
||||
#define ETHER_TYPE_IP (0x0800)
|
||||
#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
|
||||
int pkt_count = 0;
|
||||
static int pkt_count = 0;
|
||||
int live_pcap = 0;
|
||||
int offline_pcap = 0;
|
||||
int has_expression = 0;
|
||||
@ -37,6 +78,7 @@ void error(char *msg) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void parse_options(int argc, char *argv[]) {
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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++;
|
||||
|
||||
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[])
|
||||
@ -92,6 +329,8 @@ int main(int argc, char *argv[])
|
||||
struct bpf_program fp;
|
||||
bpf_u_int32 devnet, devmask;
|
||||
|
||||
signal(SIGINT, intHandler);
|
||||
|
||||
parse_options(argc, argv);
|
||||
|
||||
if (live_pcap) {
|
||||
@ -115,7 +354,10 @@ int main(int argc, char *argv[])
|
||||
if (pcap == NULL) error(errbuf);
|
||||
|
||||
pcap_loop(pcap, -1, &process_packet, NULL);
|
||||
printf("finished processing %d packets\n", pkt_count);
|
||||
|
||||
pcap_close(pcap);
|
||||
|
||||
print_stat();
|
||||
|
||||
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