need help regarding a packet capture program - timer

The following is a program that captures TCP packets < port 80 > and prints header related information in the console for every packet. I have also included a timer , so that after every 1000 millisec i.e. 1 sec , the frequency of occurence of various flags , and distinct number of Src IPs , Ack nos and Seq nos encountered are written into a file. I'm working in fedora core 5. I am encountering the following problems :
1.file writing part works fine during some executions , but most of the other times ,in the same machine , the file is not at all written to.
2.When i execute this program in my house , about 30 packets are captured every second. But when i run the same program in my lab , just 1 packet is captured per second. ( though i do the same amount of browsing in both places )
#define INTERVAL 1000 /* number of milliseconds to go off */
#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h> // for setitimer
#include<unistd.h> // for pause
#include <signal.h> /* for signal */
/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518
/* ethernet headers are always exactly 14 bytes [1] */
#define SIZE_ETHERNET 14
/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6
/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* IP header */
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) >> 4)
/* TCP header */
typedef u_int tcp_seq;
struct sniff_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};
u_short sport[100];int spd=0;
u_int seq[100];int seqd=0;
u_short win[100];int wind=0;
FILE* urlfile;
int count = 1,flag=0,t=0;
float sc=0,ac=0,fc=0,pc=0,uc=0,rc=0;
void
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
void
print_payload(const u_char *payload, int len);
void
print_hex_ascii_line(const u_char *payload, int len, int offset);
void
print_app_usage(void);
void DoStuff(void);
void DoStuff(void) {
t++;
printf("Timer %d went off.########################################\n",t);
// fprintf(urlfile,"\n hi hi");
fprintf(urlfile,"\ntime %d 1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f 9:%f",t,sc/count,ac/count,fc/count,pc/count,uc/count,rc/count,(float)spd/count,(float)wind/count,(float)seqd/count);
printf("\ntime %d 1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f 9:%f",t,sc/count,ac/count,fc/count,pc/count,uc/count,rc/count,(float)spd/count,(float)wind/count,(float)seqd/count);
printf("\n a_count : %f , total_packets : %d , frequency : %f",ac,count,ac/count);
printf("\n r_count : %f , total_packets : %d , frequency : %f",rc,count,rc/count);
printf("\n p_count : %f , total_packets : %d , frequency : %f",pc,count,pc/count);
printf("\n s_count : %f , total_packets : %d , frequency : %f",sc,count,sc/count);
printf("\n u_count : %f , total_packets : %d , frequency : %f",uc,count,uc/count);
printf("\n f_count : %f , total_packets : %d , frequency : %f",fc,count,fc/count);
printf("\ncount of distinct seq nos : %d no/pcount : %f ",seqd,(float)seqd/count);
printf("\ncount of distinct sports : %d no/pcount : %f ",spd,(float)spd/count);
printf("\ncount of distinct win nos : %d no/pcount : %f\n\n ",wind,(float)wind/count);
ac=rc=pc=fc=sc=uc=0;count=1;
spd=seqd=wind=0;
}
void
print_app_usage(void)
{
printf("Usage: ./a.out [interface]\n");
printf("\n");
printf("Options:\n");
printf(" interface Listen on <interface> for packets.\n");
printf("\n");
return;
}
/*
* dissect/print packet
*/
void
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
/* packet counter */
int j;
/* declare pointers to packet headers */
const struct sniff_ethernet *ethernet; /* The ethernet header [1] */
const struct sniff_ip *ip; /* The IP header */
const struct sniff_tcp *tcp; /* The TCP header */
const char *payload; /* Packet payload */
int size_ip;
int size_tcp;
int size_payload;
printf("\nPacket number %d:\n", count);
count++;
/* define ethernet header */
ethernet = (struct sniff_ethernet*)(packet);
/* define/compute ip header offset */
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
size_ip = IP_HL(ip)*4;
if (size_ip < 20) {
printf(" * Invalid IP header length: %u bytes\n", size_ip);
return;
}
switch(ip->ip_p) {
case IPPROTO_TCP:
printf(" Protocol: TCP\n");
break;
case IPPROTO_UDP:
printf(" Protocol: UDP\n");
return;
case IPPROTO_ICMP:
printf(" Protocol: ICMP\n");
return;
case IPPROTO_IP:
printf(" Protocol: IP\n");
return;
default:
printf(" Protocol: unknown\n");
return;
}
/* define/compute tcp header offset */
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
size_tcp = TH_OFF(tcp)*4;
if (size_tcp < 20) {
printf(" * Invalid TCP header length: %u bytes\n", size_tcp);
return;
}
flag=0;
for(j=0;j<spd;j++)
{
if(sport[j]==ntohs(tcp->th_sport)) { flag=1; break; }
}
if(flag==0) sport[spd++]=ntohs(tcp->th_sport);
flag=0;
for(j=0;j<seqd;j++)
{
if(seq[j]==ntohs(tcp->th_seq)) { flag=1; break; }
}
if(flag==0) seq[seqd++]=ntohs(tcp->th_seq);
flag=0;
for(j=0;j<wind;j++)
{
if(win[j]==ntohs(tcp->th_win)) { flag=1; break; }
}
if(flag==0) win[wind++]=ntohs(tcp->th_win);
printf(" Src port: %d\n", ntohs(tcp->th_sport));
printf(" Window: %d\n", ntohs(tcp->th_win));
printf(" Sequence no: %d\n", ntohs(tcp->th_seq));
if (tcp->th_flags & TH_URG){
printf(" Flag: TH_URG");uc++;
}
if (tcp->th_flags & TH_RST){
printf(" Flag: TH_RST");rc++;
}
if (tcp->th_flags & TH_ACK){
printf(" Flag: TH_ACK");ac++;
}
if (tcp->th_flags & TH_PUSH){
printf(" Flag: TH_PUSH");pc++;
}
if (tcp->th_flags & TH_SYN){
printf(" Flag: TH_SYN");sc++;
}
if (tcp->th_flags & TH_FIN){
printf(" Flag: TH_FIN");fc++;
}
if (size_payload > 0) {
printf(" Payload (%d bytes):\n", size_payload);
}
return;
}
int main(int argc, char **argv)
{
char *dev = NULL; /* capture device name */
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_t *handle; /* packet capture handle */
char filter_exp[] = "tcp port 80";
struct bpf_program fp; /* compiled filter program (expression) */
bpf_u_int32 mask; /* subnet mask */
bpf_u_int32 net; /* ip */
//int num_packets = 10; /* number of packets to capture */
/* check for capture device name on command-line */
if (argc == 2) {
dev = argv[1];
}
else if (argc > 2) {
fprintf(stderr, "error: unrecognized command-line options\n\n");
print_app_usage();
exit(EXIT_FAILURE);
}
else {
/* find a capture device if not specified on command-line */
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n",
errbuf);
exit(EXIT_FAILURE);
}
}
/* get network number and mask associated with capture device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
dev, errbuf);
net = 0;
mask = 0;
}
/* print capture info */
printf("Device: %s\n", dev);
printf("Filter expression: %s\n", filter_exp);
/* open capture device */
handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
exit(EXIT_FAILURE);
}
/* make sure we're capturing on an Ethernet device [2] */
if (pcap_datalink(handle) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", dev);
exit(EXIT_FAILURE);
}
/* compile the filter expression */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* apply the compiled filter */
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
urlfile=fopen("output.txt","w");
if(urlfile==NULL) printf("Unable to create file.");
// timer code
struct itimerval it_val; /* for setting itimer */
/* Upon SIGALRM, call DoStuff().
* Set interval timer. We want frequency in ms,
* but the setitimer call needs seconds and useconds. */
if (signal(SIGALRM, (void (*)(int)) DoStuff) == SIG_ERR) {
perror("Unable to catch SIGALRM");
exit(1);
}
it_val.it_value.tv_sec = INTERVAL/1000;
it_val.it_value.tv_usec = (INTERVAL*1000) % 1000000;
it_val.it_interval = it_val.it_value;
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) {
perror("error calling setitimer()");
exit(1);
}
/* now we can set our callback function */
//pcap_loop(handle, num_packets, got_packet, NULL);
pcap_loop(handle,-1, got_packet, NULL);// set num_packets to -1 to capture indefinitely.
/* cleanup */
pcap_freecode(&fp);
pcap_close(handle);
fclose(urlfile);
printf("\nCapture complete.\n");
return 0;
}
As this is a part of my project , i'm right now stuck at this point.. Can anyone please suggest regarding what may have gone wrong.. Thanks in advance.

Have you tried fflush()?

I could solve the problem no [2] , with just a small change in the filter expression : i changed it from "tcp port 80" to "tcp". And , now this program is working as well in my lab as it did at my home.
still , the problem no [1] is yet unresolved.. And moreover , The file writing is not keeping in pace with the console i/o.. By the time the console displays capture details for 120 seconds , the file has only around 90 second - data filled in.. I wonder if this is a general problem with file i/o..

Related

How can I write many rows in my file CSV?

How can I create a .csv file? In this .csv I want to write information of the packets.
This is my code: https://www.tcpdump.org/sniffex.c
I want to write into my file .csv some prints, for example the ip, tcp, etc.
This is my previous question: How can i create a file .csv?
#define APP_NAME "sniffex"
#define APP_DESC "Sniffer example using libpcap"
#define APP_COPYRIGHT "Copyright (c) 2005 The Tcpdump Group"
#define APP_DISCLAIMER "THERE IS ABSOLUTELY NO WARRANTY FOR THIS PROGRAM."
#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518
/* ethernet headers are always exactly 14 bytes [1] */
#define SIZE_ETHERNET 14
/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6
FILE *f = fopen("test", "w");
/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* IP header */
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) >> 4)
/* TCP header */
typedef u_int tcp_seq;
struct sniff_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};
void
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
void
print_payload(const u_char *payload, int len);
void
print_hex_ascii_line(const u_char *payload, int len, int offset);
void
print_app_banner(void);
void
print_app_usage(void);
/*
* app name/banner
*/
void
print_app_banner(void)
{
printf("%s - %s\n", APP_NAME, APP_DESC);
printf("%s\n", APP_COPYRIGHT);
printf("%s\n", APP_DISCLAIMER);
printf("\n");
return;
}
/*
* print help text
*/
void
print_app_usage(void)
{
printf("Usage: %s [interface]\n", APP_NAME);
printf("\n");
printf("Options:\n");
printf(" interface Listen on <interface> for packets.\n");
printf("\n");
return;
}
/*
* print data in rows of 16 bytes: offset hex ascii
*
* 00000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1..
*/
void
print_hex_ascii_line(const u_char *payload, int len, int offset)
{
int i;
int gap;
const u_char *ch;
/* offset */
printf("%05d ", offset);
/* hex */
ch = payload;
for(i = 0; i < len; i++) {
printf("%02x ", *ch);
ch++;
/* print extra space after 8th byte for visual aid */
if (i == 7)
printf(" ");
}
/* print space to handle line less than 8 bytes */
if (len < 8)
printf(" ");
/* fill hex gap with spaces if not full line */
if (len < 16) {
gap = 16 - len;
for (i = 0; i < gap; i++) {
printf(" ");
}
}
printf(" ");
/* ascii (if printable) */
ch = payload;
for(i = 0; i < len; i++) {
if (isprint(*ch))
printf("%c", *ch);
else
printf(".");
ch++;
}
printf("\n");
return;
}
/*
* print packet payload data (avoid printing binary data)
*/
void
print_payload(const u_char *payload, int len)
{
int len_rem = len;
int line_width = 16; /* number of bytes per line */
int line_len;
int offset = 0; /* zero-based offset counter */
const u_char *ch = payload;
if (len <= 0)
return;
/* data fits on one line */
if (len <= line_width) {
print_hex_ascii_line(ch, len, offset);
return;
}
/* data spans multiple lines */
for ( ;; ) {
/* compute current line length */
line_len = line_width % len_rem;
/* print line */
print_hex_ascii_line(ch, line_len, offset);
/* compute total remaining */
len_rem = len_rem - line_len;
/* shift pointer to remaining bytes to print */
ch = ch + line_len;
/* add offset */
offset = offset + line_width;
/* check if we have line width chars or less */
if (len_rem <= line_width) {
/* print last line and get out */
print_hex_ascii_line(ch, len_rem, offset);
break;
}
}
return;
}
/*
* dissect/print packet
*/
void
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
static int count = 1; /* packet counter */
/* declare pointers to packet headers */
const struct sniff_ethernet *ethernet; /* The ethernet header [1] */
const struct sniff_ip *ip; /* The IP header */
const struct sniff_tcp *tcp; /* The TCP header */
const char *payload; /* Packet payload */
int size_ip;
int size_tcp;
int size_payload;
printf("\nPacket number %d:\n", count);
count++;
/* define ethernet header */
ethernet = (struct sniff_ethernet*)(packet);
/* define/compute ip header offset */
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
size_ip = IP_HL(ip)*4;
if (size_ip < 20) {
printf(" * Invalid IP header length: %u bytes\n", size_ip);
return;
}
/* print source and destination IP addresses */
printf(" From: %s\n", inet_ntoa(ip->ip_src));
printf(" To: %s\n", inet_ntoa(ip->ip_dst));
/* determine protocol */
switch(ip->ip_p) {
case IPPROTO_TCP:
printf(" Protocol: TCP\n");
break;
case IPPROTO_UDP:
printf(" Protocol: UDP\n");
return;
case IPPROTO_ICMP:
printf(" Protocol: ICMP\n");
return;
case IPPROTO_IP:
printf(" Protocol: IP\n");
return;
default:
printf(" Protocol: unknown\n");
return;
}
/*
* OK, this packet is TCP.
*/
/* define/compute tcp header offset */
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
size_tcp = TH_OFF(tcp)*4;
if (size_tcp < 20) {
printf(" * Invalid TCP header length: %u bytes\n", size_tcp);
return;
}
printf(" Src port: %d\n", ntohs(tcp->th_sport));
printf(" Dst port: %d\n", ntohs(tcp->th_dport));
/* define/compute tcp payload (segment) offset */
payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
/* compute tcp payload (segment) size */
size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);
/*
* Print payload data; it might be binary, so don't just
* treat it as a string.
*/
if (size_payload > 0) {
printf(" Payload (%d bytes):\n", size_payload);
print_payload(payload, size_payload);
}
return;
}
int main(int argc, char **argv)
{
char *dev = NULL; /* capture device name */
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_t *handle; /* packet capture handle */
char filter_exp[] = "ip"; /* filter expression [3] */
struct bpf_program fp; /* compiled filter program (expression) */
bpf_u_int32 mask; /* subnet mask */
bpf_u_int32 net; /* ip */
int num_packets = 10; /* number of packets to capture */
print_app_banner();
/* check for capture device name on command-line */
if (argc == 2) {
dev = argv[1];
}
else if (argc > 2) {
fprintf(stderr, "error: unrecognized command-line options\n\n");
print_app_usage();
exit(EXIT_FAILURE);
}
else {
/* find a capture device if not specified on command-line */
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n",
errbuf);
exit(EXIT_FAILURE);
}
}
/* get network number and mask associated with capture device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
dev, errbuf);
net = 0;
mask = 0;
}
/* print capture info */
printf("Device: %s\n", dev);
printf("Number of packets: %d\n", num_packets);
printf("Filter expression: %s\n", filter_exp);
/* open capture device */
handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
exit(EXIT_FAILURE);
}
/* make sure we're capturing on an Ethernet device [2] */
if (pcap_datalink(handle) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", dev);
exit(EXIT_FAILURE);
}
/* compile the filter expression */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* apply the compiled filter */
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* now we can set our callback function */
pcap_loop(handle, num_packets, got_packet, NULL);
/* cleanup */
pcap_freecode(&fp);
pcap_close(handle);
printf("\nCapture complete.\n");
return 0;
}
I was following this steps but just get for one packet, I want to write rows for every packet
typedef struct CsvRow
{
char ipLocal[32];
char ipRemote[32];
...
struct csvRow* next;
} Csvrow;
CsvRow* first;
CsvRow* last;
// collecting
CsvRow* newLine = malloc(sizeof(CsvRow));
newLine->next = NULL;
if (last == NULL)
{
first = last = newLine;
}
else
{
last->next = newLine;
}
// then when you are gathering information just add that in last
strcpy(last->ipLocal, "someip");
..
// at the end of your main function do
FILE* fp = fopen("test.csv", "w");
if (fp == NULL)
{
fprintf(stderr, "file access denied");
abort();
}
for (CsvRow* p = first; p != NULL; p = p->next)
{
fprintf(fp, "%s,%s\n", p->ipLocal, p->ipRemote);
}
fclose(fp);
// free memory
CsvRow* q = first;
while (q != NULL)
{
CsvRow* next = q->next;
free(q);
q = next;
}
the got_packet is a callback so every time that function is called you should create a new CsvRow struct and add it to your list, inside of got_packet fill the struct. then at program end (before return 0), open the file and write your list starting with first
e.g.
typedef struct {
char from[32];
char to[32];
.. and whatever else you want to put in
} CsvRow;
CsvRow* first = NULL;
CsvRow* last = NULL;
void got_packet( .. )
{
CsvRow* newLine = malloc(sizeof(CsvRow));
newLine->next = NULL;
if (last == NULL)
{
first = last = newLine;
}
else
{
last->next = newLine;
last = newLine; // new last
}
strcpy(last->from, inet_ntoa(ip->ip_src));
strcpy(last->to, inet_ntoa(ip->ip_dst));
... and fill in whatever else you want to store
}
then at the end of main()
FILE *fp = fopen("yourfile","w");
for (CsvRow* p = first; p != NULL; p=p->next)
{
fprintf(fp,"%s,%s", p->from, p->to );
}
fclose(fp);

How can i create a file .csv?

How i can create a file .csv?, i want to create only a file, because i want to declare outside the main() my File. as well i have a functions, and de main() function.
my is this: https://www.tcpdump.org/sniffex.c i want to write in my file .csv some prints, for example the ip, tcp, etc.
#define APP_NAME "sniffex"
#define APP_DESC "Sniffer example using libpcap"
#define APP_COPYRIGHT "Copyright (c) 2005 The Tcpdump Group"
#define APP_DISCLAIMER "THERE IS ABSOLUTELY NO WARRANTY FOR THIS PROGRAM."
#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518
/* ethernet headers are always exactly 14 bytes [1] */
#define SIZE_ETHERNET 14
/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6
FILE *f = fopen("test", "w");
/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* IP header */
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) >> 4)
/* TCP header */
typedef u_int tcp_seq;
struct sniff_tcp {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};
void
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
void
print_payload(const u_char *payload, int len);
void
print_hex_ascii_line(const u_char *payload, int len, int offset);
void
print_app_banner(void);
void
print_app_usage(void);
/*
* app name/banner
*/
void
print_app_banner(void)
{
printf("%s - %s\n", APP_NAME, APP_DESC);
printf("%s\n", APP_COPYRIGHT);
printf("%s\n", APP_DISCLAIMER);
printf("\n");
return;
}
/*
* print help text
*/
void
print_app_usage(void)
{
printf("Usage: %s [interface]\n", APP_NAME);
printf("\n");
printf("Options:\n");
printf(" interface Listen on <interface> for packets.\n");
printf("\n");
return;
}
/*
* print data in rows of 16 bytes: offset hex ascii
*
* 00000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1..
*/
void
print_hex_ascii_line(const u_char *payload, int len, int offset)
{
int i;
int gap;
const u_char *ch;
/* offset */
printf("%05d ", offset);
/* hex */
ch = payload;
for(i = 0; i < len; i++) {
printf("%02x ", *ch);
ch++;
/* print extra space after 8th byte for visual aid */
if (i == 7)
printf(" ");
}
/* print space to handle line less than 8 bytes */
if (len < 8)
printf(" ");
/* fill hex gap with spaces if not full line */
if (len < 16) {
gap = 16 - len;
for (i = 0; i < gap; i++) {
printf(" ");
}
}
printf(" ");
/* ascii (if printable) */
ch = payload;
for(i = 0; i < len; i++) {
if (isprint(*ch))
printf("%c", *ch);
else
printf(".");
ch++;
}
printf("\n");
return;
}
/*
* print packet payload data (avoid printing binary data)
*/
void
print_payload(const u_char *payload, int len)
{
int len_rem = len;
int line_width = 16; /* number of bytes per line */
int line_len;
int offset = 0; /* zero-based offset counter */
const u_char *ch = payload;
if (len <= 0)
return;
/* data fits on one line */
if (len <= line_width) {
print_hex_ascii_line(ch, len, offset);
return;
}
/* data spans multiple lines */
for ( ;; ) {
/* compute current line length */
line_len = line_width % len_rem;
/* print line */
print_hex_ascii_line(ch, line_len, offset);
/* compute total remaining */
len_rem = len_rem - line_len;
/* shift pointer to remaining bytes to print */
ch = ch + line_len;
/* add offset */
offset = offset + line_width;
/* check if we have line width chars or less */
if (len_rem <= line_width) {
/* print last line and get out */
print_hex_ascii_line(ch, len_rem, offset);
break;
}
}
return;
}
/*
* dissect/print packet
*/
void
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
static int count = 1; /* packet counter */
/* declare pointers to packet headers */
const struct sniff_ethernet *ethernet; /* The ethernet header [1] */
const struct sniff_ip *ip; /* The IP header */
const struct sniff_tcp *tcp; /* The TCP header */
const char *payload; /* Packet payload */
int size_ip;
int size_tcp;
int size_payload;
printf("\nPacket number %d:\n", count);
count++;
/* define ethernet header */
ethernet = (struct sniff_ethernet*)(packet);
/* define/compute ip header offset */
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
size_ip = IP_HL(ip)*4;
if (size_ip < 20) {
printf(" * Invalid IP header length: %u bytes\n", size_ip);
return;
}
/* print source and destination IP addresses */
printf(" From: %s\n", inet_ntoa(ip->ip_src));
printf(" To: %s\n", inet_ntoa(ip->ip_dst));
/* determine protocol */
switch(ip->ip_p) {
case IPPROTO_TCP:
printf(" Protocol: TCP\n");
break;
case IPPROTO_UDP:
printf(" Protocol: UDP\n");
return;
case IPPROTO_ICMP:
printf(" Protocol: ICMP\n");
return;
case IPPROTO_IP:
printf(" Protocol: IP\n");
return;
default:
printf(" Protocol: unknown\n");
return;
}
/*
* OK, this packet is TCP.
*/
/* define/compute tcp header offset */
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
size_tcp = TH_OFF(tcp)*4;
if (size_tcp < 20) {
printf(" * Invalid TCP header length: %u bytes\n", size_tcp);
return;
}
printf(" Src port: %d\n", ntohs(tcp->th_sport));
printf(" Dst port: %d\n", ntohs(tcp->th_dport));
/* define/compute tcp payload (segment) offset */
payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
/* compute tcp payload (segment) size */
size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);
/*
* Print payload data; it might be binary, so don't just
* treat it as a string.
*/
if (size_payload > 0) {
printf(" Payload (%d bytes):\n", size_payload);
print_payload(payload, size_payload);
}
return;
}
int main(int argc, char **argv)
{
char *dev = NULL; /* capture device name */
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_t *handle; /* packet capture handle */
char filter_exp[] = "ip"; /* filter expression [3] */
struct bpf_program fp; /* compiled filter program (expression) */
bpf_u_int32 mask; /* subnet mask */
bpf_u_int32 net; /* ip */
int num_packets = 10; /* number of packets to capture */
print_app_banner();
/* check for capture device name on command-line */
if (argc == 2) {
dev = argv[1];
}
else if (argc > 2) {
fprintf(stderr, "error: unrecognized command-line options\n\n");
print_app_usage();
exit(EXIT_FAILURE);
}
else {
/* find a capture device if not specified on command-line */
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n",
errbuf);
exit(EXIT_FAILURE);
}
}
/* get network number and mask associated with capture device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
dev, errbuf);
net = 0;
mask = 0;
}
/* print capture info */
printf("Device: %s\n", dev);
printf("Number of packets: %d\n", num_packets);
printf("Filter expression: %s\n", filter_exp);
/* open capture device */
handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
exit(EXIT_FAILURE);
}
/* make sure we're capturing on an Ethernet device [2] */
if (pcap_datalink(handle) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", dev);
exit(EXIT_FAILURE);
}
/* compile the filter expression */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* apply the compiled filter */
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* now we can set our callback function */
pcap_loop(handle, num_packets, got_packet, NULL);
/* cleanup */
pcap_freecode(&fp);
pcap_close(handle);
printf("\nCapture complete.\n");
return 0;
}
but i got this error:
error: initializer element is not constant
FILE *f = fopen("test", "w");
If you want to write the results in a file, move
FILE *f = fopen("test", "w");
into your main() function (also check return value since the function can fail), if you want the file format to be csv then you should add the extension .csv so that other people know it has that format e.g. "test.csv" instead of "test". pass the file pointer to all the functions where you need to write to the csv-file.
Now to serialize the contents that you have collected and since the format of a csv-file is row based you need to collect the information before you write it (easier that way). So decide on a structure that will contain all the information you want to put in a row in the csv-file and fill that structure, have a linked list of these structures that you create as you are gathering information, then once you are done collecting, go through the list and write one row to the csv-file per structure.
E.g.
typedef struct CsvRow
{
char ipLocal[32];
char ipRemote[32];
...
struct csvRow* next;
} Csvrow;
CsvRow* first;
CsvRow* last;
// collecting
CsvRow* newLine = malloc(sizeof(CsvRow));
newLine->next = NULL;
if (last == NULL)
{
first = last = newLine;
}
else
{
last->next = newLine;
last = newLine;
}
// then when you are gathering information just add that in last
strcpy(last->ipLocal, "someip");
..
// at the end of your main function do
FILE* fp = fopen("test.csv", "w");
if (fp == NULL)
{
fprintf(stderr, "file access denied");
abort();
}
for (CsvRow* p = first; p != NULL; p = p->next)
{
fprintf(fp, "%s,%s\n", p->ipLocal, p->ipRemote);
}
fclose(fp);
// free memory
CsvRow* q = first;
while (q != NULL)
{
CsvRow* next = q->next;
free(q);
q = next;
}
You need to split the line into opening the file, and declaring the variable, the declaration can stay where it is:
FILE *f;
The open must occur in your main() function:
main()
{
f = fopen("test.csv", "w");
...
Then you can use that in your code anywwhere:
fprintf(f,"some stuff");
And remember to close the file when your program finishes (this would be at the end of your main() function...
fclose(f);

printing out TCP flag information from pcap

I'm writing a program to get certain pieces of information from the headers in a pcap. I'm not sure if I did this right. It works with all of my professor's tests, however, there are hidden tests that I need to be aware of. It's the TCP flags I'm not sure about. It works in index 47, but don't know why, should be 46. (Ethernet Header(14) + IPv4 header(20) + 13th byte in TCP header (13) -1 (to account for arrays starting at 0) = 46). Is it a fluke that it works on spot 47?
Here's my code:
#include <pcap/pcap.h>
#include <stdlib.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
/*
* Most of this file is the background functionality to open a capture file or to
* open an inteface for a live capture. You can ignore all this unless you are
* interested in an example of how pcap works.
*
* To use the file, simply insert your code in the "Put your code here" section and
* create a Makefile for compilation.
*/
/* Maximum time that the OS will buffer packets before giving them to your program. */
#define MAX_BUFFER_TIME_MS (300)
/* Maximum time the program will wait for a packet during live capture.
* Measured in MAX_BUFFER_TIME_MS units. Program closes when it expires. */
#define MAX_IDLE_TIME 100 /* 100*MAX_BUFFER_TIME_MS idle time at most */
/* Function that creates the structures necessary to perform a packet capture and
* determines capture source depending on arguments. Function will terminate the
* program on error, so return value always valid. */
pcap_t* setup_capture(int argc, char *argv[], char *use_file);
/* Cleanup the state of the capture. */
void cleanup_capture(pcap_t *handle);
/* Check for abnormal conditions during capture.
* 1 returned if a packet is ready, 0 if a packet is not available.
* Terminates program if an unrecoverable error occurs. */
char valid_capture(int return_value, pcap_t *pcap_handle, char use_file);
int main(int argc, char *argv[]) {
pcap_t *pcap_handle = NULL; /* Handle for PCAP library */
struct pcap_pkthdr *packet_hdr = NULL; /* Packet header from PCAP */
const u_char *packet_data = NULL; /* Packet data from PCAP */
int ret = 0; /* Return value from library calls */
char use_file = 0; /* Flag to use file or live capture */
/* Setup the capture and get the valid handle. */
pcap_handle = setup_capture(argc, argv, &use_file);
/* Loop through all the packets in the trace file.
* ret will equal -2 when the trace file ends.
* ret will never equal -2 for a live capture. */
ret = pcap_next_ex(pcap_handle, &packet_hdr, &packet_data);
struct ether_header
{
u_int8_t ether_dhost[6]; /* destination eth addr */
u_int8_t ether_shost[6]; /* source ether addr */
u_int16_t ether_type; /* packet type ID field */
};
struct ether_header *eptr;
char src[INET_ADDRSTRLEN];
char dst[INET_ADDRSTRLEN];
char src6[INET6_ADDRSTRLEN];
char dst6[INET6_ADDRSTRLEN];
while( ret != -2 ) {
if( valid_capture(ret, pcap_handle, use_file) ){
eptr = (struct ether_header *) packet_data;
fprintf(stdout,"%s -> ",ether_ntoa((const struct ether_addr *)&eptr->ether_shost));
fprintf(stdout,"%s \n",ether_ntoa((const struct ether_addr *)&eptr->ether_dhost));
if(packet_data[12] == 0x08 && packet_data[13] == 0x00)
{
printf(" [IPv4] ");
fprintf(stdout,"%s -> ", inet_ntop(AF_INET,(const void *)packet_data+26,src,INET_ADDRSTRLEN));
fprintf(stdout,"%s\n", inet_ntop(AF_INET,(const void *)packet_data+30,dst,INET_ADDRSTRLEN));
if(packet_data[23] == 0x06)
{
printf(" [TCP] %d -> ",packet_data[34]*256+packet_data[35]);
printf("%d ",packet_data[36]*256+packet_data[37]);
// printf("%02X ",packet_data[47]); //print out value of flag;
if(packet_data[47] & (1!=0))
printf("FIN \n");
else if((packet_data[47] == 0x02 || packet_data[47] == 0x12) & (2!=0))
printf("SYN \n");
else{
printf("\n");
}
}
else if(packet_data[23] == 0x11)
{
printf(" [UDP] %d -> ",packet_data[34]*256+packet_data[35]);
printf("%d \n",packet_data[36]*256+packet_data[37]);
}
else{
printf(" [%d] \n",packet_data[23]);
}
}
else if(packet_data[12] == 0x86 && packet_data[13] == 0xdd)
{
printf(" [IPv6] ");
printf("%s -> ", inet_ntop(AF_INET6, (const void *)packet_data+22, src6, INET6_ADDRSTRLEN));
printf("%s \n", inet_ntop(AF_INET6, (const void *)packet_data+38, dst6, INET6_ADDRSTRLEN));
if(packet_data[20] == 0x06)
{
printf(" [TCP] %d -> ",packet_data[54]*256+packet_data[55]);
printf("%d ",packet_data[56]*256+packet_data[57]);
// printf("%02X ",packet_data[67]); //print out value of flag
if(packet_data[67] & (1!=0))
printf("FIN \n");
else if((packet_data[67] == 0x02 || packet_data[67] == 0x12) & (2!=0))
printf("SYN \n");
else{
printf("\n");
}
}
else if(packet_data[20] == 0x11)
{
printf(" [UDP] %d -> ",packet_data[54]*256+packet_data[55]);
printf("%d \n",packet_data[56]*256+packet_data[57]);
}
else{
printf(" [%d] \n",packet_data[20]);
}
} else {
fprintf(stdout," [%d] \n",ntohs(eptr->ether_type));
}
}
/* Get the next packet */
ret = pcap_next_ex(pcap_handle, &packet_hdr, &packet_data);
}
cleanup_capture(pcap_handle);
return 0;
}
pcap_t* setup_capture(int argc, char *argv[], char *use_file) {
char *trace_file = NULL; /* Trace file to process */
pcap_t *pcap_handle = NULL; /* Handle for PCAP library to return */
char pcap_buff[PCAP_ERRBUF_SIZE]; /* Error buffer used by pcap functions */
char *dev_name = NULL; /* Device name for live capture */
/* Check command line arguments */
if( argc > 2 ) {
fprintf(stderr, "Usage: %s [trace_file]\n", argv[0]);
exit(-1);
}
else if( argc > 1 ){
*use_file = 1;
trace_file = argv[1];
}
else {
*use_file = 0;
}
/* Open the trace file, if appropriate */
if( *use_file ){
pcap_handle = pcap_open_offline(trace_file, pcap_buff);
if( pcap_handle == NULL ){
fprintf(stderr, "Error opening trace file \"%s\": %s\n", trace_file, pcap_buff);
exit(-1);
}
}
/* Lookup and open the default device if trace file not used */
else{
dev_name = pcap_lookupdev(pcap_buff);
if( dev_name == NULL ){
fprintf(stderr, "Error finding default capture device: %s\n", pcap_buff);
exit(-1);
}
/* Use buffer length as indication of warning, per pcap_open_live(3). */
pcap_buff[0] = 0;
pcap_handle = pcap_open_live(dev_name, BUFSIZ, 1, MAX_BUFFER_TIME_MS, pcap_buff);
if( pcap_handle == NULL ){
fprintf(stderr, "Error opening capture device %s: %s\n", dev_name, pcap_buff);
exit(-1);
}
if( pcap_buff[0] != 0 ) {
printf("Warning: %s\n", pcap_buff);
}
printf("Capturing on interface '%s'\n", dev_name);
}
return pcap_handle;
}
void cleanup_capture(pcap_t *handle) {
/* Close the trace file or device */
pcap_close(handle);
}
char valid_capture(int return_value, pcap_t *pcap_handle, char use_file) {
static int idle_count = 0; /* Count of idle periods with no packets */
char ret = 0; /* Return value, invalid by default */
/* A general error occurred */
if( return_value == -1 ) {
pcap_perror(pcap_handle, "Error processing packet:");
cleanup_capture(pcap_handle);
exit(-1);
}
/* Timeout occured for a live packet capture */
else if( (return_value == 0) && (use_file == 0) ){
if( ++idle_count >= MAX_IDLE_TIME ){
printf("Timeout waiting for additional packets on interface\n");
cleanup_capture(pcap_handle);
exit(0);
}
}
/* Unexpected/unknown return value */
else if( return_value != 1 ) {
fprintf(stderr, "Unexpected return value (%i) from pcap_next_ex()\n", return_value);
cleanup_capture(pcap_handle);
exit(-1);
}
/* Normal operation, packet arrived */
else{
idle_count = 0;
ret = 1;
}
return ret;
}
Here's a few sample print outs: (the left is the professors results, the right is mine, I have extra printout to see what's in that spot in the array). Thanks
0:0:86:5:80:da -> 0:60:97:7:69:ea 0:0:86:5:80:da -> 0:60:97:7:69:ea
[IPv6] 3ffe:507:0:1:200:86ff:fe05:80da -> 3ffe:501:410:0:2c0:dfff:fe47:33e [IPv6] 3ffe:507:0:1:200:86ff:fe05:80da -> 3ffe:501:410:0:2c0:dfff:fe47:33e
[TCP] 1022 -> 22 SYN | [TCP] 1022 -> 22 02 SYN
0:60:97:7:69:ea -> 0:0:86:5:80:da 0:60:97:7:69:ea -> 0:0:86:5:80:da
[IPv6] 3ffe:501:410:0:2c0:dfff:fe47:33e -> 3ffe:507:0:1:200:86ff:fe05:80da [IPv6] 3ffe:501:410:0:2c0:dfff:fe47:33e -> 3ffe:507:0:1:200:86ff:fe05:80da
[TCP] 22 -> 1022 SYN | [TCP] 22 -> 1022 12 SYN
Here's how you can locate the TCP flags:
If we assume that we are talking about Ethernet, the Ethernet frame header will be 14 bytes: a 6 byte destination followed by a 6 byte source and then a 2 byte ether type (for 802.3/SNAP/Ethernet II, which is most likely)
If the Ethertype at offset 12/13 from the start of the frame contains 0x0800, you are looking at TCP/IP.
if(frame[12]==0x08 && frame[13]==0x00) { /* IP packet inside */ }
Assuming that you have an IP Ethertype, the next byte will contain two nibble sized fields: The IP version number (likely 0x40 for you) and then the IP header length (likely 0x05). Putting those nibbles together, you would have 0x45 sitting in that field. It is very important to check that field. You could mask off the upper nibble like so:
ihl = frame[14]&0x0f;
to grab the IP header length field. This number will tell you where to find the next protocol layer's header. Typically you will have a 5 here (20 byte header), but if there are IP options, this number will be larger. Let's take this number and calculate from here:
embedded_protocol_header = frame[ihl * 4];
Next, you should verify that you actually have a TCP packet. This can be verified by examining byte offset 9 in the IP header:
ip_header_start = frame[14];
embedded_protocol = ip_header_start[9];
if(embedded_protocol == 6) { tcp_header = embedded_protocol_header; }
Now that we know it is TCP, we can grab the TCP flags. These will be at offset 13 in the TCP header:
tcp_flags = tcp_header[13];
To examine the SYN/ACK bits, you can mask everything else off:
synack = tcp_flags & 0x3f;
You can now check to see if it's a SYN ACK:
if(synack == 0x12) { /* SYN and ACK were set */
You may wonder about the 0x3f mask above. The reason for it is that the two high order bits in the TCP flags are used for ECN if the system supports ECN. If it is supported, ECN negotiation occurs during the 3 way handshake in these bits and the two low order bits in the TOS byte of the IP header (differentiated services byte). Rather than dealing with all of the possible cases, the simplest thing is to turn those bits off completely and check to see if you still have SYN and ACK.

Read nanosecond pcap file using libpcap

I have a nanosecond libpcap (nanosec.pcap) file and the nanosecond timestamp (eg 2.123456789) can be displayed by using Wireshark. Now i would like to open the nanosecond libpcap file using C language and have the source code as following. When I try to open the the nanosec.pcap by using pcap_open_offine(), it would return "unknown file format" error. Additionally, by changing the magic number at the header of nanosec.pcap to that of normal pcap (0x1A2B3C4D) and I got a segmentation fault error from the terminal (Ubuntu). Any expert here could advice how could I display the nanosecond part of the timestamp by using libpcap? Thanks in advance!
Following is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <pcap.h>
struct UDP_hdr {
u_short uh_sport; /* source port */
u_short uh_dport; /* destination port */
u_short uh_ulen; /* datagram length */
u_short uh_sum; /* datagram checksum */
};
/* Some helper functions, which we define at the end of this file. */
/* Returns a string representation of a timestamp. */
const char *timestamp_string(struct timeval ts);
/* Report a problem with dumping the packet with the given timestamp. */
void problem_pkt(struct timeval ts, const char *reason);
/* Report the specific problem of a packet being too short. */
void too_short(struct timeval ts, const char *truncated_hdr);
void dump_UDP_packet(const unsigned char *packet, struct timeval ts,
unsigned int capture_len)
{
struct ip *ip;
struct UDP_hdr *udp;
unsigned int IP_header_length;
/* For simplicity, we assume Ethernet encapsulation. */
if (capture_len < sizeof(struct ether_header))
{
/* We didn't even capture a full Ethernet header, so we
* can't analyze this any further.
*/
too_short(ts, "Ethernet header");
return;
}
/* Skip over the Ethernet header. */
packet += sizeof(struct ether_header);
capture_len -= sizeof(struct ether_header);
if (capture_len < sizeof(struct ip))
{ /* Didn't capture a full IP header */
too_short(ts, "IP header");
return;
}
ip = (struct ip*) packet;
IP_header_length = ip->ip_hl * 4; /* ip_hl is in 4-byte words */
if (capture_len < IP_header_length)
{ /* didn't capture the full IP header including options */
too_short(ts, "IP header with options");
return;
}
if (ip->ip_p != IPPROTO_UDP)
{
problem_pkt(ts, "non-UDP packet");
return;
}
/* Skip over the IP header to get to the UDP header. */
packet += IP_header_length;
capture_len -= IP_header_length;
if (capture_len < sizeof(struct UDP_hdr))
{
too_short(ts, "UDP header");
return;
}
udp = (struct UDP_hdr*) packet;
printf("%s UDP src_port=%d dst_port=%d length=%d\n",
timestamp_string(ts),
ntohs(udp->uh_sport),
ntohs(udp->uh_dport),
ntohs(udp->uh_ulen));
}
int main(int argc, char *argv[])
{
pcap_t *pcap;
const unsigned char *packet;
char errbuf[PCAP_ERRBUF_SIZE];
struct pcap_pkthdr header;
/* Skip over the program name. */
++argv; --argc;
/* We expect exactly one argument, the name of the file to dump. */
if ( argc != 1 )
{
fprintf(stderr, "program requires one argument, the trace file to dump\n");
exit(1);
}
pcap = pcap_open_offline(argv[0], errbuf);
if (pcap == NULL)
{
fprintf(stderr, "error reading pcap file: %s\n", errbuf);
exit(1);
}
/* Now just loop through extracting packets as long as we have
* some to read.
*/
while ((packet = pcap_next(pcap, &header)) != NULL)
dump_UDP_packet(packet, header.ts, header.caplen);
// terminate
return 0;
}
/* Note, this routine returns a pointer into a static buffer, and
* so each call overwrites the value returned by the previous call.
*/
const char *timestamp_string(struct timeval ts)
{
static char timestamp_string_buf[256];
sprintf(timestamp_string_buf, "%d.%09d",
(int) ts.tv_sec, (int) ts.tv_usec);
return timestamp_string_buf;
}
void problem_pkt(struct timeval ts, const char *reason)
{
fprintf(stderr, "%s: %s\n", timestamp_string(ts), reason);
}
void too_short(struct timeval ts, const char *truncated_hdr)
{
fprintf(stderr, "packet with timestamp %s is truncated and lacks a full %s\n",
timestamp_string(ts), truncated_hdr);
}
Any expert here could advice how could I display the nanosecond part of the timestamp by using libpcap?
Use the top-of-the-Git-trunk version of libpcap, open the capture file with
pcap_open_offline_with_tstamp_precision(pathname, PCAP_TSTAMP_PRECISION_NANO, errbuf);
and treat the struct timeval in the pcap_pkthdr structure as being seconds and nanoseconds rather than seconds and microseconds (i.e., have your program treat tv_usec as nanoseconds rather than microseconds - a bit confusing, but I'm not sure there's a less-ugly solution).

why can't my program (coded with libpcap) capture wireless 80211 packets?

I have written a program to capture wireless network packets from my network interface card(ralink 2870(USB),atheros(PCI),etc).Now I am not able to capture the correct format packet I needed,even no packets was captured.1st,I tried turned my card to monitor mode or add a interface mon0 for it.but it output "do not support that interface".2nd,this program can only clarify the "this is the ethernet link type" via pcap_datalink(),why?my wlan0 interface is that link type?. Here is my code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<unistd.h>
#include<net/if.h>
#include<netinet/if_ether.h>
#include<pcap.h>
/*ugly shortcuts - Defining our header types*/
#define ETH_HEADER_SIZE 14
#define AVS_HEADER_SIZE 64 /*AVS capture header size*/
#define DATA_80211_FRAME_SIZE 24 /*header for 802.11 data packet*/
#define LLC_HEADER_SIZE 8 /*LLC frame for encapsulation*/
#define MAC_MASK (0XFF)
/*
#define uint8 unsigned char;
#define int8 char;
#define uint16 int;
#define int16 int;
#define u_int32_t unsigned int;
#define int32 signed int;
*/
/*for the sake of clarity we'll use globals for a few things*/
char *device; /*device to sniff on*/
int verbose = 0; /*verbose output about the device*/
int wired = 0; /*flag for the opened pcap session*/
pcap_t *handle; /*handle for the opened pcap session*/
/*8 bytes SNAP LLC header format*/
struct snap_header_t{
u_int8_t dsap;
u_int8_t ssap;
u_int8_t ctl;
u_int16_t org;
u_int8_t org2;
u_int16_t ether_type; /* ethernet type */
}__attribute__((__PACKED__));
//24 bytes 80211 header
struct wireless_80211_header_t{
u_int16_t fc; /*2 bytes */
u_int16_t dur; /*2 bytes duration*/
u_int8_t da[6]; /*6 bytes destination*/
u_int8_t sa[6]; /*6 bytes source*/
u_int8_t bssid[6]; /*6 bytes bssid*/
u_int16_t seq_ctrl; /*2 bytes sequence control*/
};
//64 bytes AVS header
struct AVS_header_t
{
u_int32_t version;
u_int32_t length;
u_int64_t mactime;
u_int64_t hosttime;
u_int32_t phytype;
u_int32_t channel;
u_int32_t datarate;
u_int32_t antenna;
u_int32_t priority;
u_int32_t ssi_type;
int32_t ssi_signal;
int32_t ssi_noise;
u_int32_t preamble;
u_int32_t encoding;
};
/*========defined but not used=========*/
/*prism value */
struct prism_value{
u_int32_t did;
u_int16_t status;
u_int16_t len;
u_int32_t data;
};
/*prism header for traditional wireless card*/
struct prism_header{
u_int32_t msgcode;
u_int32_t msglen;
struct prism_value hosttime;
struct prism_value mactime;
struct prism_value channel;
struct prism_value rssi;
struct prism_value sq;
struct prism_value signal;
struct prism_value noise;
struct prism_value rate;
struct prism_value istx;
struct prism_value frmlen;
};
/*===============================*/
/*gracefully handle a Control + C action*/
void
ctrl_c()
{
printf("\nExiting\n");
pcap_breakloop(handle); /*tell pcap_loop or pcap_dispatch to stop capturing*/
pcap_close(handle);
exit(0);
}
/*Usage of this program*/
void
usage (char *name)
{
printf("\n%s - simple ARP sniffer\n",name);
printf("Usage: %s [-i interface] [-l] [-v]\n",name);
printf("\t-i\tinterface to sniff on\n");
printf("\t-l\tlist available interfaces\n");
printf("\t-v\tprint verbose info\n");
exit(1);
}
/*callback function to process a packet when captured*/
void
process_packet(u_char *args, const struct pcap_pkthdr *header,\
const u_char *packet)
{
struct ether_header *eth_header; /*in ethernet.h included by if_eth.h*/
struct wireless_80211_header_t *wireless_header; /*80211 header*/
struct snap_header_t *llc_header; /*RFC 1042 encapsulation header*/
struct ether_arp *arp_packet; /*from if_eth.h*/
if(wired) /*global flag - wired or wireless*/
{
eth_header = (struct ether_header *) packet;
arp_packet = (struct ether_arp *) (packet + ETH_HEADER_SIZE);
if(ntohs(eth_header->ether_type) != ETHERTYPE_ARP)return;
}
else
{
/*wireless*/
wireless_header = (struct wireless_80211_header_t *)
(packet + AVS_HEADER_SIZE);
llc_header = (struct snap_header_t *)
(packet + AVS_HEADER_SIZE + DATA_80211_FRAME_SIZE);
arp_packet = (struct ether_arp *)
(packet + AVS_HEADER_SIZE + DATA_80211_FRAME_SIZE + LLC_HEADER_SIZE);
if(ntohs(llc_header->ether_type) != ETHERTYPE_ARP)return;
}
printf("SRC: %.2X.%.2X.%.2X.%.2X.%.2X.%.2X--> DES:"
"%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\n",
wireless_header->sa[0]&MAC_MASK,
wireless_header->sa[1]&MAC_MASK,
wireless_header->sa[2]&MAC_MASK,
wireless_header->sa[3]&MAC_MASK,
wireless_header->sa[4]&MAC_MASK,
wireless_header->sa[5]&MAC_MASK,
wireless_header->da[0]&MAC_MASK,
wireless_header->da[1]&MAC_MASK,
wireless_header->da[2]&MAC_MASK,
wireless_header->da[3]&MAC_MASK,
wireless_header->da[4]&MAC_MASK,
wireless_header->da[5]&MAC_MASK);
printf("Src: %d.%d.%d.%d--> Des: %d.%d.%d.%d\n",
arp_packet->arp_spa[0],
arp_packet->arp_spa[1],
arp_packet->arp_spa[2],
arp_packet->arp_spa[3],
arp_packet->arp_tpa[0],
arp_packet->arp_tpa[1],
arp_packet->arp_tpa[2],
arp_packet->arp_tpa[3]);
}/*end of process_packet*/
/*the main function*/
int
main(int argc,char *argv[])
{
char opt; /*for option processing*/
char errbuf[PCAP_ERRBUF_SIZE]; /*pcap error messages buffer*/
struct pcap_pkthdr header; /*packet header from pcap*/
const u_char *packet; /*packet*/
bpf_u_int32 netp; /*ip address of interface*/
bpf_u_int32 maskp; /*subnet mask of interface*/
char *filter = "arp"; /*filter for BPF (human readable)*/
struct bpf_program fp; /*compiled BPF filter*/
int ret; /*gegeric return value*/
pcap_if_t *alldevsp; /*list of interfaces*/
while((opt = getopt(argc, argv, "i:vl")) > 0)
{
switch(opt)
{
case 'i':
device = optarg;
break;
case 'l':
if(pcap_findalldevs (&alldevsp,errbuf) < 0)
{
fprintf(stderr,"erros in find all devs: %s\n",errbuf);
exit(1);
}
while(alldevsp != NULL)
{
printf("%s\n",alldevsp->name);
alldevsp = alldevsp->next;
}
exit(0);
case 'v':
verbose = 1;
break;
default:
usage(argv[0]);
break;
}//end of switch
}//end of while
/*setup signal handler to Control+C will graceful*/
signal(SIGINT,ctrl_c);
/*find device for sniffing if needed*/
if(device == NULL)/*if user hasn't specified a device*/
{
device = pcap_lookupdev(errbuf);/*let pcap find a compatible device*/
if(device == NULL)//there was an error
{
fprintf(stderr,"%s\n",errbuf);
exit(1);
}
}
/*set errbuf to 0 length string to check for warnings*/
//memset(errbuf,PCAP_ERRBUF_SIZE,0);
errbuf[0] = 0;
/*open device for sniffing*/
handle = pcap_open_live(device, /*device to sniff on*/
BUFSIZ, /*maximum number of bytes to capture per packet*/
1, /*set 1 for promisc mode,0 to not*/
0, /*0,snigg until an error occurs*/
errbuf);
if(handle == NULL)
{
fprintf(stderr,"%s\n",errbuf);
exit(1);
}
if(strlen(errbuf) > 0)
{
fprintf(stderr,"warning: %s\n",errbuf);
errbuf[0] = 0;
}
if(verbose)
{
printf("Using device: %s\n",device);
printf("libpcap version: %s\n",(char *)pcap_lib_version);
}
/*find out the datalink type of the connection*/
if(pcap_datalink (handle) == DLT_EN10MB)
{
wired = 1;/*ethernet link*/
printf("this is a ethernet link\n");
}
else if((pcap_datalink (handle) == DLT_IEEE802_11_RADIO_AVS)\
||(pcap_datalink (handle) == DLT_IEEE802_11_RADIO)\
||(pcap_datalink (handle) == DLT_IEEE802_11)\
||(pcap_datalink (handle) == DLT_PRISM_HEADER))
{
wired = 0;
printf("this is a wireless link\n");
}
else
{
fprintf(stderr,"do not support this interface type!\n");
exit(1);
}
/*get the IP subnet mask of the device,so we set a filter on it*/
if(pcap_lookupnet(device,&netp,&maskp,errbuf) == -1)
{
fprintf(stderr,"%s\n",errbuf);
exit(1);
}
/*compile the filter,so we can capture only stuff we are interested in*/
if(pcap_compile(handle,&fp,filter,0,maskp) == -1)
{
fprintf(stderr,"%s\n",pcap_geterr(handle));
exit(1);
}
/*set the filter for the device we have opened*/
if(pcap_setfilter(handle,&fp) == -1)
{
fprintf(stderr,"%s\n",pcap_geterr(handle));
exit(1);
}
/*it will be nice and free the memory used for the compiled filter*/
pcap_freecode(&fp);
/*the 'main loop' of capturing packet with our callback function*/
if((ret = pcap_loop(handle, /*our session created previous*/
-1, /*(count) a negative number means sniff until error*/
process_packet, /*callback function*/
NULL)) < 0)/*arg can be transfer to callback function*/
{
if(ret == -1)
{ fprintf(stderr,"%s\n",pcap_geterr(handle));
exit(1);
}/*otherwise return should be -2,meaning pcap_breakloop has been called*/
}
/*close our session*/
pcap_close(handle);
return 0;
}

Resources