18b52a31eSHanoh Haim/*
28b52a31eSHanoh HaimCopyright (c) 2015-2015 Cisco Systems, Inc.
38b52a31eSHanoh Haim
48b52a31eSHanoh HaimLicensed under the Apache License, Version 2.0 (the "License");
58b52a31eSHanoh Haimyou may not use this file except in compliance with the License.
68b52a31eSHanoh HaimYou may obtain a copy of the License at
78b52a31eSHanoh Haim
88b52a31eSHanoh Haim    http://www.apache.org/licenses/LICENSE-2.0
98b52a31eSHanoh Haim
108b52a31eSHanoh HaimUnless required by applicable law or agreed to in writing, software
118b52a31eSHanoh Haimdistributed under the License is distributed on an "AS IS" BASIS,
128b52a31eSHanoh HaimWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b52a31eSHanoh HaimSee the License for the specific language governing permissions and
148b52a31eSHanoh Haimlimitations under the License.
158b52a31eSHanoh Haim*/
168b52a31eSHanoh Haim#include "captureFile.h"
178b52a31eSHanoh Haim#include "pcap.h"
188b52a31eSHanoh Haim#include "erf.h"
198b52a31eSHanoh Haim#include "basic_utils.h"
208b52a31eSHanoh Haim#include <stdlib.h>
218b52a31eSHanoh Haim#include <errno.h>
228b52a31eSHanoh Haim#include <string.h>
238b52a31eSHanoh Haim#include <math.h>
248b52a31eSHanoh Haim
258b52a31eSHanoh Haim
268b52a31eSHanoh Haimvoid CPktNsecTimeStamp::Dump(FILE *fd){
278b52a31eSHanoh Haim    fprintf(fd,"%.6f [%x:%x]",getNsec(),m_time_sec,m_time_nsec );
288b52a31eSHanoh Haim}
298b52a31eSHanoh Haim
308b52a31eSHanoh Haim
318b52a31eSHanoh Haimvoid * CAlignMalloc::malloc(uint16_t size,uint8_t align){
328b52a31eSHanoh Haim    assert(m_p==0);
338b52a31eSHanoh Haim    m_p=(char *)::malloc(size+align);
348b52a31eSHanoh Haim    uintptr_t v =(uintptr_t)m_p;
358b52a31eSHanoh Haim    char *p=(char *)my_utl_align_up( v,align);
368b52a31eSHanoh Haim    return  (void *)p;
378b52a31eSHanoh Haim}
388b52a31eSHanoh Haim
398b52a31eSHanoh Haimvoid CAlignMalloc::free(){
408b52a31eSHanoh Haim    ::free(m_p);
418b52a31eSHanoh Haim    m_p=0;
428b52a31eSHanoh Haim}
438b52a31eSHanoh Haim
448b52a31eSHanoh Haim#define PKT_ALIGN 128
458b52a31eSHanoh Haim
468b52a31eSHanoh Haim
478b52a31eSHanoh HaimCCapPktRaw::CCapPktRaw(CCapPktRaw  *obj){
488b52a31eSHanoh Haim    flags =0;
498b52a31eSHanoh Haim    pkt_cnt=obj->pkt_cnt;
508b52a31eSHanoh Haim    pkt_len=obj->pkt_len;
518b52a31eSHanoh Haim    time_sec=obj->time_sec;
528b52a31eSHanoh Haim    time_nsec=obj->time_nsec;
538b52a31eSHanoh Haim    assert ((pkt_len>0) && (pkt_len<MAX_PKT_SIZE) );
548b52a31eSHanoh Haim    raw = (char *)m_handle.malloc(pkt_len,PKT_ALIGN);
558b52a31eSHanoh Haim    // copy the packet
568b52a31eSHanoh Haim    memcpy(raw,obj->raw,pkt_len);
578b52a31eSHanoh Haim}
588b52a31eSHanoh Haim
598b52a31eSHanoh Haim
608b52a31eSHanoh HaimCCapPktRaw::CCapPktRaw(int size){
618b52a31eSHanoh Haim    pkt_cnt=0;
628b52a31eSHanoh Haim    flags =0;
638b52a31eSHanoh Haim    pkt_len=size;
648b52a31eSHanoh Haim    time_sec=0;
658b52a31eSHanoh Haim    time_nsec=0;
668b52a31eSHanoh Haim    if (size==0) {
678b52a31eSHanoh Haim        raw =0;
688b52a31eSHanoh Haim    }else{
698b52a31eSHanoh Haim        raw = (char *)m_handle.malloc(size,PKT_ALIGN);
708b52a31eSHanoh Haim        memset(raw,0xee,size);
718b52a31eSHanoh Haim    }
728b52a31eSHanoh Haim
738b52a31eSHanoh Haim}
748b52a31eSHanoh Haim
758b52a31eSHanoh HaimCCapPktRaw::CCapPktRaw(){
768b52a31eSHanoh Haim    flags =0;
778b52a31eSHanoh Haim	pkt_cnt=0;
788b52a31eSHanoh Haim	pkt_len=0;
798b52a31eSHanoh Haim	time_sec=0;
808b52a31eSHanoh Haim	time_nsec=0;
818b52a31eSHanoh Haim	raw = (char *)m_handle.malloc((uint16_t)MAX_PKT_SIZE,PKT_ALIGN);
828b52a31eSHanoh Haim    memset(raw,0xee,MAX_PKT_SIZE);
838b52a31eSHanoh Haim}
848b52a31eSHanoh Haim
858b52a31eSHanoh HaimCCapPktRaw::~CCapPktRaw(){
868b52a31eSHanoh Haim	if (raw && (getDoNotFree()==false) ) {
878b52a31eSHanoh Haim		m_handle.free();
888b52a31eSHanoh Haim	}
898b52a31eSHanoh Haim}
908b52a31eSHanoh Haim
918b52a31eSHanoh Haimchar * CCapPktRaw::append(uint16_t len){
928b52a31eSHanoh Haim    CAlignMalloc h;
938b52a31eSHanoh Haim    char * p;
948b52a31eSHanoh Haim    char * new_raw = (char *)h.malloc(pkt_len+len,PKT_ALIGN);
958b52a31eSHanoh Haim    memcpy(new_raw,raw,pkt_len);
968b52a31eSHanoh Haim    m_handle.free();
978b52a31eSHanoh Haim    raw=new_raw;
988b52a31eSHanoh Haim    p= raw+pkt_len;
998b52a31eSHanoh Haim    pkt_len+=len;
1008b52a31eSHanoh Haim    m_handle.m_p =h.m_p;
1018b52a31eSHanoh Haim    /* new pointer */
1028b52a31eSHanoh Haim    return(p);
1038b52a31eSHanoh Haim}
1048b52a31eSHanoh Haim
1058b52a31eSHanoh Haim
1068b52a31eSHanoh Haimvoid CCapPktRaw::CloneShalow(CCapPktRaw  *obj){
1078b52a31eSHanoh Haim    pkt_len=obj->pkt_len;
1088b52a31eSHanoh Haim    raw = obj->raw;
1098b52a31eSHanoh Haim    setDoNotFree(true);
1108b52a31eSHanoh Haim}
1118b52a31eSHanoh Haim
1128b52a31eSHanoh Haimvoid CCapPktRaw::Dump(FILE *fd,int verbose){
1133b372bbeSimarom	fprintf(fd," =>pkt (%p) %llu , len %d, time [%x:%x] \n",raw, (unsigned long long)pkt_cnt,pkt_len,time_sec,time_nsec);
1148b52a31eSHanoh Haim	if (verbose) {
1158b52a31eSHanoh Haim		utl_DumpBuffer(fd,raw,pkt_len,0);
1168b52a31eSHanoh Haim	}
1178b52a31eSHanoh Haim}
1188b52a31eSHanoh Haim
1198b52a31eSHanoh Haim
1208b52a31eSHanoh Haimbool CCapPktRaw::Compare(CCapPktRaw * obj,int dump,double dsec){
1218b52a31eSHanoh Haim
1228b52a31eSHanoh Haim    if (pkt_len != obj->pkt_len) {
1238b52a31eSHanoh Haim        if ( dump ){
12403d70c42SIdo Barnea            printf(" ERROR: len is not eq. First len is %d, second is %d \n", pkt_len, obj->pkt_len);
1258b52a31eSHanoh Haim        }
1268b52a31eSHanoh Haim        return (false);
1278b52a31eSHanoh Haim    }
1288b52a31eSHanoh Haim
1298b52a31eSHanoh Haim    if ( getInterface() != obj->getInterface() ){
13003d70c42SIdo Barnea        printf(" ERROR: original packet from if=%d and cur packet from if=%d \n",getInterface(),obj->getInterface());
1318b52a31eSHanoh Haim        return (false);
1328b52a31eSHanoh Haim    }
1338b52a31eSHanoh Haim
1348b52a31eSHanoh Haim    CPktNsecTimeStamp t1(time_sec,time_nsec);
1358b52a31eSHanoh Haim    CPktNsecTimeStamp t2(obj->time_sec,obj->time_nsec);
1368b52a31eSHanoh Haim    if ( t1.diff(t2) > dsec ){
1378b52a31eSHanoh Haim        if ( dump ){
13858d22eefSimarom            printf(" ERROR: diff of %lf seconds while only %lf allowed\n", t1.diff(t2), dsec);
1398b52a31eSHanoh Haim        }
1408b52a31eSHanoh Haim        return (false);
1418b52a31eSHanoh Haim    }
1428b52a31eSHanoh Haim
1438b52a31eSHanoh Haim    if ( memcmp(raw,obj->raw,pkt_len) == 0 ){
1448b52a31eSHanoh Haim        return (true);
1458b52a31eSHanoh Haim    }else{
1468b52a31eSHanoh Haim        if ( dump ){
14703d70c42SIdo Barnea            fprintf(stdout," ERROR: buffers not the same \n");
1488b52a31eSHanoh Haim            fprintf(stdout," B1 \n");
1498b52a31eSHanoh Haim            fprintf(stdout," ---------------\n");
1508b52a31eSHanoh Haim            utl_DumpBuffer(stdout,raw,pkt_len,0);
1518b52a31eSHanoh Haim            fprintf(stdout," B2 \n");
1528b52a31eSHanoh Haim            fprintf(stdout," ---------------\n");
1538b52a31eSHanoh Haim
1548b52a31eSHanoh Haim            utl_DumpBuffer(stdout,obj->raw,obj->pkt_len,0);
1558b52a31eSHanoh Haim        }
1568b52a31eSHanoh Haim        return (false);
1578b52a31eSHanoh Haim    }
1588b52a31eSHanoh Haim}
1598b52a31eSHanoh Haim
160f6901ca1SHanoh Haim#define  CPY_BUFSIZE 1024
161f6901ca1SHanoh Haim
162f6901ca1SHanoh Haimbool CErfCmp::cpy(std::string src,std::string dst){
163f6901ca1SHanoh Haim
164f6901ca1SHanoh Haim    char mybuf[CPY_BUFSIZE] ;
165f6901ca1SHanoh Haim    FILE *ifd = NULL;
166f6901ca1SHanoh Haim    FILE *ofd = NULL;
167f6901ca1SHanoh Haim    ifd = fopen( src.c_str(), "rb" );
168f6901ca1SHanoh Haim    ofd = fopen( dst.c_str(), "w+");
169f6901ca1SHanoh Haim    assert(ifd!=NULL);
170f6901ca1SHanoh Haim    assert(ofd!=NULL);
171f6901ca1SHanoh Haim
172f6901ca1SHanoh Haim    int n;
173f6901ca1SHanoh Haim    while ( true){
174f6901ca1SHanoh Haim        n = fread(mybuf, sizeof(char), CPY_BUFSIZE ,ifd);
175f6901ca1SHanoh Haim        if (n>0) {
176f6901ca1SHanoh Haim            fwrite(mybuf, sizeof(char),n,ofd);
177f6901ca1SHanoh Haim        }else{
178f6901ca1SHanoh Haim            break;
179f6901ca1SHanoh Haim        }
180f6901ca1SHanoh Haim    }
181f6901ca1SHanoh Haim
182f6901ca1SHanoh Haim    fclose(ifd);
183f6901ca1SHanoh Haim    fclose(ofd);
184f6901ca1SHanoh Haim    return true;
185f6901ca1SHanoh Haim}
186f6901ca1SHanoh Haim
1878b52a31eSHanoh Haim
1888b52a31eSHanoh Haimbool CErfCmp::compare(std::string f1, std::string f2 ){
1898b52a31eSHanoh Haim
1908b52a31eSHanoh Haim    if ( dump ){
1918b52a31eSHanoh Haim        printf(" compare %s %s \n",f1.c_str(),f2.c_str());
1928b52a31eSHanoh Haim    }
1938b52a31eSHanoh Haim    bool res=true;
1948b52a31eSHanoh Haim    CCapReaderBase * lp1=CCapReaderFactory::CreateReader((char *)f1.c_str(),0);
1958b52a31eSHanoh Haim    if (lp1 == 0) {
1968b52a31eSHanoh Haim        if ( dump ){
1978b52a31eSHanoh Haim            printf(" ERROR file %s does not exits or not supported \n",(char *)f1.c_str());
1988b52a31eSHanoh Haim        }
1998b52a31eSHanoh Haim        return (false);
2008b52a31eSHanoh Haim    }
2018b52a31eSHanoh Haim
2028b52a31eSHanoh Haim    CCapReaderBase * lp2=CCapReaderFactory::CreateReader((char *)f2.c_str(),0);
2038b52a31eSHanoh Haim    if (lp2 == 0) {
2048b52a31eSHanoh Haim        delete lp1;
2058b52a31eSHanoh Haim        if ( dump ){
2068b52a31eSHanoh Haim            printf(" ERROR file %s does not exits or not supported \n",(char *)f2.c_str());
2078b52a31eSHanoh Haim        }
2088b52a31eSHanoh Haim        return (false);
2098b52a31eSHanoh Haim    }
2108b52a31eSHanoh Haim
2118b52a31eSHanoh Haim    CCapPktRaw raw_packet1;
2128b52a31eSHanoh Haim    bool has_pkt1;
2138b52a31eSHanoh Haim    CCapPktRaw raw_packet2;
2148b52a31eSHanoh Haim    bool has_pkt2;
2158b52a31eSHanoh Haim
2168b52a31eSHanoh Haim    int pkt_cnt=1;
2178b52a31eSHanoh Haim    while ( true ) {
2188b52a31eSHanoh Haim        /* read packet */
2198b52a31eSHanoh Haim         has_pkt1 = lp1->ReadPacket(&raw_packet1) ;
2208b52a31eSHanoh Haim         has_pkt2 = lp2->ReadPacket(&raw_packet2) ;
2218b52a31eSHanoh Haim
2228b52a31eSHanoh Haim         /* one has finished */
2238b52a31eSHanoh Haim         if ( !has_pkt1  || !has_pkt2 ) {
2248b52a31eSHanoh Haim             if (has_pkt1 != has_pkt2 ) {
2258b52a31eSHanoh Haim                 if ( dump ){
2268b52a31eSHanoh Haim                     printf(" ERROR not the same number of packets  \n");
2278b52a31eSHanoh Haim                 }
2288b52a31eSHanoh Haim                 res=false;
2298b52a31eSHanoh Haim             }
2308b52a31eSHanoh Haim             break;
2318b52a31eSHanoh Haim         }
2328b52a31eSHanoh Haim        if (!raw_packet1.Compare(&raw_packet2,true,d_sec)  ){
2338b52a31eSHanoh Haim            res=false;
2348b52a31eSHanoh Haim            printf(" ERROR in pkt %d \n",pkt_cnt);
2358b52a31eSHanoh Haim            break;
2368b52a31eSHanoh Haim        }
2378b52a31eSHanoh Haim
2388b52a31eSHanoh Haim
2398b52a31eSHanoh Haim        pkt_cnt++;
2408b52a31eSHanoh Haim    }
2418b52a31eSHanoh Haim
2428b52a31eSHanoh Haim    delete lp1;
2438b52a31eSHanoh Haim    delete lp2;
2448b52a31eSHanoh Haim    return (res);
2458b52a31eSHanoh Haim}
2468b52a31eSHanoh Haim
2478b52a31eSHanoh Haim/**
2488b52a31eSHanoh Haim * try to create type by type
2498b52a31eSHanoh Haim * @param name
2508b52a31eSHanoh Haim *
2518b52a31eSHanoh Haim * @return CCapReaderBase*
2528b52a31eSHanoh Haim */
2538691f401SimaromCCapReaderBase * CCapReaderFactory::CreateReader(char * name, int loops, std::ostream &err)
2548b52a31eSHanoh Haim{
2558691f401Simarom    assert(name);
2568b52a31eSHanoh Haim
2578b52a31eSHanoh Haim    /* make sure we have a file */
2588b52a31eSHanoh Haim    FILE * f = CAP_FOPEN_64(name, "rb");
2598b52a31eSHanoh Haim    if (f == NULL) {
2608b52a31eSHanoh Haim        if (errno == ENOENT) {
2618691f401Simarom            err << "CAP file '" << name << "' not found";
2628b52a31eSHanoh Haim        } else {
2638691f401Simarom            err << "failed to open CAP file '" << name << "' with errno " << errno;
2648b52a31eSHanoh Haim        }
2658b52a31eSHanoh Haim        return NULL;
2668b52a31eSHanoh Haim    }
2678b52a31eSHanoh Haim    // close the file
2688b52a31eSHanoh Haim    fclose(f);
2698b52a31eSHanoh Haim
2708b52a31eSHanoh Haim    for (capture_type_e i = LIBPCAP ; i<LAST_TYPE ; i = (capture_type_e(i+1)) )
2718b52a31eSHanoh Haim	{
2728b52a31eSHanoh Haim		CCapReaderBase * next = CCapReaderFactory::CreateReaderInstace(i);
2738b52a31eSHanoh Haim		if (next == NULL || next->Create(name,loops)) {
2748b52a31eSHanoh Haim			return next;
2758b52a31eSHanoh Haim		}
2768b52a31eSHanoh Haim		delete next;
2778b52a31eSHanoh Haim	}
2788b52a31eSHanoh Haim
2798691f401Simarom    err << "unsupported CAP format (not PCAP or ERF): " << name << "\n";
2808b52a31eSHanoh Haim
2818b52a31eSHanoh Haim	return NULL;
2828b52a31eSHanoh Haim}
2838b52a31eSHanoh Haim
2848b52a31eSHanoh HaimCCapReaderBase * CCapReaderFactory::CreateReaderInstace(capture_type_e type)
2858b52a31eSHanoh Haim{
2868b52a31eSHanoh Haim	switch(type)
2878b52a31eSHanoh Haim	{
2888b52a31eSHanoh Haim	case  ERF:
2898b52a31eSHanoh Haim		return new CErfFileReader();
2908b52a31eSHanoh Haim	case LIBPCAP:
2918b52a31eSHanoh Haim		return new LibPCapReader();
2928b52a31eSHanoh Haim	default:
2938b52a31eSHanoh Haim		printf("Got unsupported file type\n");
2948b52a31eSHanoh Haim		return NULL;
2958b52a31eSHanoh Haim	}
2968b52a31eSHanoh Haim
2978b52a31eSHanoh Haim}
2988b52a31eSHanoh Haim
2998b52a31eSHanoh Haim
3008b52a31eSHanoh Haim
3018b52a31eSHanoh Haim/**
3028b52a31eSHanoh Haim * The factory function will create the matching reader instance
3038b52a31eSHanoh Haim * according to the type.
3048b52a31eSHanoh Haim *
3058b52a31eSHanoh Haim * @param type - the foramt
3068b52a31eSHanoh Haim * @param name - new file name
3078b52a31eSHanoh Haim *
3088b52a31eSHanoh Haim * @return CCapWriter* - return pointer to the writer instance
3098b52a31eSHanoh Haim *         or NULL if failed from some reason. Instance user
3108b52a31eSHanoh Haim *         should relase memory when instance not needed
3118b52a31eSHanoh Haim *         anymore.
3128b52a31eSHanoh Haim */
3138b52a31eSHanoh HaimCFileWriterBase  * CCapWriterFactory::CreateWriter(capture_type_e type ,char * name)
3148b52a31eSHanoh Haim{
3158b52a31eSHanoh Haim	if (name == NULL) {
3168b52a31eSHanoh Haim		return NULL;
3178b52a31eSHanoh Haim	}
3188b52a31eSHanoh Haim
3198b52a31eSHanoh Haim	CFileWriterBase  * toRet = CCapWriterFactory::createWriterInsance(type);
3208b52a31eSHanoh Haim
3218b52a31eSHanoh Haim	if (toRet) {
3228b52a31eSHanoh Haim		if (!toRet->Create(name)) {
3238b52a31eSHanoh Haim            delete toRet;
3248b52a31eSHanoh Haim			toRet = NULL;
3258b52a31eSHanoh Haim		}
3268b52a31eSHanoh Haim	}
3278b52a31eSHanoh Haim
3288b52a31eSHanoh Haim	return toRet;
3298b52a31eSHanoh Haim}
3308b52a31eSHanoh Haim
3318b52a31eSHanoh Haim/**
3328b52a31eSHanoh Haim * Create instance for writer if type is supported.
3338b52a31eSHanoh Haim * @param type
3348b52a31eSHanoh Haim *
3358b52a31eSHanoh Haim * @return CFileWriterBase*
3368b52a31eSHanoh Haim */
3378b52a31eSHanoh HaimCFileWriterBase  * CCapWriterFactory::createWriterInsance(capture_type_e type )
3388b52a31eSHanoh Haim{
3398b52a31eSHanoh Haim	switch(type) {
3408b52a31eSHanoh Haim	case LIBPCAP:
3418b52a31eSHanoh Haim		return new LibPCapWriter();
3428b52a31eSHanoh Haim	case ERF:
3438b52a31eSHanoh Haim		return new CErfFileWriter();
3448b52a31eSHanoh Haim		// other is not supported yet.
3458b52a31eSHanoh Haim	default:
3468b52a31eSHanoh Haim		return NULL;
3478b52a31eSHanoh Haim	}
3488b52a31eSHanoh Haim}
3498b52a31eSHanoh Haim