12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475 |
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <pcap/pcap-inttypes.h>
- #include <errno.h>
- #include <memory.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "pcap-int.h"
- #include "pcap-common.h"
- #ifdef HAVE_OS_PROTO_H
- #include "os-proto.h"
- #endif
- #include "sf-pcapng.h"
- struct block_header {
- bpf_u_int32 block_type;
- bpf_u_int32 total_length;
- };
- struct block_trailer {
- bpf_u_int32 total_length;
- };
- #define OPT_ENDOFOPT 0
- #define OPT_COMMENT 1
- struct option_header {
- u_short option_code;
- u_short option_length;
- };
- #define BT_SHB 0x0A0D0D0A
- struct section_header_block {
- bpf_u_int32 byte_order_magic;
- u_short major_version;
- u_short minor_version;
- uint64_t section_length;
-
- };
- #define BYTE_ORDER_MAGIC 0x1A2B3C4D
- #define PCAP_NG_VERSION_MAJOR 1
- #define PCAP_NG_VERSION_MINOR 0
- #define BT_IDB 0x00000001
- struct interface_description_block {
- u_short linktype;
- u_short reserved;
- bpf_u_int32 snaplen;
-
- };
- #define IF_NAME 2
- #define IF_DESCRIPTION 3
- #define IF_IPV4ADDR 4
- #define IF_IPV6ADDR 5
- #define IF_MACADDR 6
- #define IF_EUIADDR 7
- #define IF_SPEED 8
- #define IF_TSRESOL 9
- #define IF_TZONE 10
- #define IF_FILTER 11
- #define IF_OS 12
- #define IF_FCSLEN 13
- #define IF_TSOFFSET 14
- #define BT_EPB 0x00000006
- struct enhanced_packet_block {
- bpf_u_int32 interface_id;
- bpf_u_int32 timestamp_high;
- bpf_u_int32 timestamp_low;
- bpf_u_int32 caplen;
- bpf_u_int32 len;
-
- };
- #define BT_SPB 0x00000003
- struct simple_packet_block {
- bpf_u_int32 len;
-
- };
- #define BT_PB 0x00000002
- struct packet_block {
- u_short interface_id;
- u_short drops_count;
- bpf_u_int32 timestamp_high;
- bpf_u_int32 timestamp_low;
- bpf_u_int32 caplen;
- bpf_u_int32 len;
-
- };
- struct block_cursor {
- u_char *data;
- size_t data_remaining;
- bpf_u_int32 block_type;
- };
- typedef enum {
- PASS_THROUGH,
- SCALE_UP_DEC,
- SCALE_DOWN_DEC,
- SCALE_UP_BIN,
- SCALE_DOWN_BIN
- } tstamp_scale_type_t;
- struct pcap_ng_if {
- uint64_t tsresol;
- tstamp_scale_type_t scale_type;
- uint64_t scale_factor;
- uint64_t tsoffset;
- };
- struct pcap_ng_sf {
- uint64_t user_tsresol;
- u_int max_blocksize;
- bpf_u_int32 ifcount;
- bpf_u_int32 ifaces_size;
- struct pcap_ng_if *ifaces;
- };
- #define MAX_BLOCKSIZE(max_snaplen) (sizeof (struct block_header) + \
- sizeof (struct enhanced_packet_block) + \
- (max_snaplen) + 131072 + \
- sizeof (struct block_trailer))
- static void pcap_ng_cleanup(pcap_t *p);
- static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
- u_char **data);
- static int
- read_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof,
- char *errbuf)
- {
- size_t amt_read;
- amt_read = fread(buf, 1, bytes_to_read, fp);
- if (amt_read != bytes_to_read) {
- if (ferror(fp)) {
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
- errno, "error reading dump file");
- } else {
- if (amt_read == 0 && !fail_on_eof)
- return (0);
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "truncated dump file; tried to read %lu bytes, only got %lu",
- (unsigned long)bytes_to_read,
- (unsigned long)amt_read);
- }
- return (-1);
- }
- return (1);
- }
- static int
- read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
- {
- struct pcap_ng_sf *ps;
- int status;
- struct block_header bhdr;
- u_char *bdata;
- size_t data_remaining;
- ps = p->priv;
- status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
- if (status <= 0)
- return (status);
- if (p->swapped) {
- bhdr.block_type = SWAPLONG(bhdr.block_type);
- bhdr.total_length = SWAPLONG(bhdr.total_length);
- }
-
- if (bhdr.total_length > 16*1024*1024) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "pcapng block size %u > maximum %u",
- bhdr.total_length, 16*1024*1024);
- return (-1);
- }
-
- if (bhdr.total_length < sizeof(struct block_header) +
- sizeof(struct block_trailer)) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "block in pcapng dump file has a length of %u < %lu",
- bhdr.total_length,
- (unsigned long)(sizeof(struct block_header) + sizeof(struct block_trailer)));
- return (-1);
- }
-
- if (p->bufsize < bhdr.total_length) {
-
- void *bigger_buffer;
- if (bhdr.total_length > ps->max_blocksize) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "block is larger than maximum block size %u",
- ps->max_blocksize);
- return (-1);
- }
- bigger_buffer = realloc(p->buffer, bhdr.total_length);
- if (bigger_buffer == NULL) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
- return (-1);
- }
- p->buffer = bigger_buffer;
- }
-
- memcpy(p->buffer, &bhdr, sizeof(bhdr));
- bdata = (u_char *)p->buffer + sizeof(bhdr);
- data_remaining = bhdr.total_length - sizeof(bhdr);
- if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1)
- return (-1);
-
- cursor->data = bdata;
- cursor->data_remaining = data_remaining - sizeof(struct block_trailer);
- cursor->block_type = bhdr.block_type;
- return (1);
- }
- static void *
- get_from_block_data(struct block_cursor *cursor, size_t chunk_size,
- char *errbuf)
- {
- void *data;
-
- if (cursor->data_remaining < chunk_size) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "block of type %u in pcapng dump file is too short",
- cursor->block_type);
- return (NULL);
- }
-
- data = cursor->data;
- cursor->data += chunk_size;
- cursor->data_remaining -= chunk_size;
- return (data);
- }
- static struct option_header *
- get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf)
- {
- struct option_header *opthdr;
- opthdr = get_from_block_data(cursor, sizeof(*opthdr), errbuf);
- if (opthdr == NULL) {
-
- return (NULL);
- }
-
- if (p->swapped) {
- opthdr->option_code = SWAPSHORT(opthdr->option_code);
- opthdr->option_length = SWAPSHORT(opthdr->option_length);
- }
- return (opthdr);
- }
- static void *
- get_optvalue_from_block_data(struct block_cursor *cursor,
- struct option_header *opthdr, char *errbuf)
- {
- size_t padded_option_len;
- void *optvalue;
-
- padded_option_len = opthdr->option_length;
- padded_option_len = ((padded_option_len + 3)/4)*4;
- optvalue = get_from_block_data(cursor, padded_option_len, errbuf);
- if (optvalue == NULL) {
-
- return (NULL);
- }
- return (optvalue);
- }
- static int
- process_idb_options(pcap_t *p, struct block_cursor *cursor, uint64_t *tsresol,
- uint64_t *tsoffset, int *is_binary, char *errbuf)
- {
- struct option_header *opthdr;
- void *optvalue;
- int saw_tsresol, saw_tsoffset;
- uint8_t tsresol_opt;
- u_int i;
- saw_tsresol = 0;
- saw_tsoffset = 0;
- while (cursor->data_remaining != 0) {
-
- opthdr = get_opthdr_from_block_data(p, cursor, errbuf);
- if (opthdr == NULL) {
-
- return (-1);
- }
-
- optvalue = get_optvalue_from_block_data(cursor, opthdr,
- errbuf);
- if (optvalue == NULL) {
-
- return (-1);
- }
- switch (opthdr->option_code) {
- case OPT_ENDOFOPT:
- if (opthdr->option_length != 0) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Interface Description Block has opt_endofopt option with length %u != 0",
- opthdr->option_length);
- return (-1);
- }
- goto done;
- case IF_TSRESOL:
- if (opthdr->option_length != 1) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Interface Description Block has if_tsresol option with length %u != 1",
- opthdr->option_length);
- return (-1);
- }
- if (saw_tsresol) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Interface Description Block has more than one if_tsresol option");
- return (-1);
- }
- saw_tsresol = 1;
- memcpy(&tsresol_opt, optvalue, sizeof(tsresol_opt));
- if (tsresol_opt & 0x80) {
-
- uint8_t tsresol_shift = (tsresol_opt & 0x7F);
- if (tsresol_shift > 63) {
-
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Interface Description Block if_tsresol option resolution 2^-%u is too high",
- tsresol_shift);
- return (-1);
- }
- *is_binary = 1;
- *tsresol = ((uint64_t)1) << tsresol_shift;
- } else {
-
- if (tsresol_opt > 19) {
-
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Interface Description Block if_tsresol option resolution 10^-%u is too high",
- tsresol_opt);
- return (-1);
- }
- *is_binary = 0;
- *tsresol = 1;
- for (i = 0; i < tsresol_opt; i++)
- *tsresol *= 10;
- }
- break;
- case IF_TSOFFSET:
- if (opthdr->option_length != 8) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Interface Description Block has if_tsoffset option with length %u != 8",
- opthdr->option_length);
- return (-1);
- }
- if (saw_tsoffset) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Interface Description Block has more than one if_tsoffset option");
- return (-1);
- }
- saw_tsoffset = 1;
- memcpy(tsoffset, optvalue, sizeof(*tsoffset));
- if (p->swapped)
- *tsoffset = SWAPLL(*tsoffset);
- break;
- default:
- break;
- }
- }
- done:
- return (0);
- }
- static int
- add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
- {
- struct pcap_ng_sf *ps;
- uint64_t tsresol;
- uint64_t tsoffset;
- int is_binary;
- ps = p->priv;
-
- ps->ifcount++;
-
- if (ps->ifcount > ps->ifaces_size) {
-
- bpf_u_int32 new_ifaces_size;
- struct pcap_ng_if *new_ifaces;
- if (ps->ifaces_size == 0) {
-
- new_ifaces_size = 1;
- new_ifaces = malloc(sizeof (struct pcap_ng_if));
- } else {
-
- if (ps->ifaces_size * 2 < ps->ifaces_size) {
-
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "more than %u interfaces in the file",
- 0x80000000U);
- return (0);
- }
-
- new_ifaces_size = ps->ifaces_size * 2;
-
- if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) {
-
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "more than %u interfaces in the file",
- 0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if)));
- return (0);
- }
- new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if));
- }
- if (new_ifaces == NULL) {
-
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "out of memory for per-interface information (%u interfaces)",
- ps->ifcount);
- return (0);
- }
- ps->ifaces_size = new_ifaces_size;
- ps->ifaces = new_ifaces;
- }
-
- tsresol = 1000000;
- is_binary = 0;
- tsoffset = 0;
-
- if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary,
- errbuf) == -1)
- return (0);
- ps->ifaces[ps->ifcount - 1].tsresol = tsresol;
- ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset;
-
- if (tsresol == ps->user_tsresol) {
-
- ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
- } else if (tsresol > ps->user_tsresol) {
-
- if (is_binary)
- ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN;
- else {
-
- ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol;
- ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC;
- }
- } else {
-
- if (is_binary)
- ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN;
- else {
-
- ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol;
- ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC;
- }
- }
- return (1);
- }
- pcap_t *
- pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
- int *err)
- {
- size_t amt_read;
- bpf_u_int32 total_length;
- bpf_u_int32 byte_order_magic;
- struct block_header *bhdrp;
- struct section_header_block *shbp;
- pcap_t *p;
- int swapped = 0;
- struct pcap_ng_sf *ps;
- int status;
- struct block_cursor cursor;
- struct interface_description_block *idbp;
-
- *err = 0;
-
- if (magic != BT_SHB) {
-
- return (NULL);
- }
-
- amt_read = fread(&total_length, 1, sizeof(total_length), fp);
- if (amt_read < sizeof(total_length)) {
- if (ferror(fp)) {
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
- errno, "error reading dump file");
- *err = 1;
- return (NULL);
- }
-
- return (NULL);
- }
- amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
- if (amt_read < sizeof(byte_order_magic)) {
- if (ferror(fp)) {
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
- errno, "error reading dump file");
- *err = 1;
- return (NULL);
- }
-
- return (NULL);
- }
- if (byte_order_magic != BYTE_ORDER_MAGIC) {
- byte_order_magic = SWAPLONG(byte_order_magic);
- if (byte_order_magic != BYTE_ORDER_MAGIC) {
-
- return (NULL);
- }
- swapped = 1;
- total_length = SWAPLONG(total_length);
- }
-
- if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "Section Header Block in pcapng dump file has a length of %u < %lu",
- total_length,
- (unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer)));
- *err = 1;
- return (NULL);
- }
-
- p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf));
- if (p == NULL) {
-
- *err = 1;
- return (NULL);
- }
- p->swapped = swapped;
- ps = p->priv;
-
- switch (precision) {
- case PCAP_TSTAMP_PRECISION_MICRO:
- ps->user_tsresol = 1000000;
- break;
- case PCAP_TSTAMP_PRECISION_NANO:
- ps->user_tsresol = 1000000000;
- break;
- default:
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "unknown time stamp resolution %u", precision);
- free(p);
- *err = 1;
- return (NULL);
- }
- p->opt.tstamp_precision = precision;
-
- p->bufsize = 2048;
- if (p->bufsize < total_length)
- p->bufsize = total_length;
- p->buffer = malloc(p->bufsize);
- if (p->buffer == NULL) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
- free(p);
- *err = 1;
- return (NULL);
- }
- ps->max_blocksize = MAX_BLOCKSIZE(MAXIMUM_SNAPLEN);
-
- bhdrp = (struct block_header *)p->buffer;
- shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header));
- bhdrp->block_type = magic;
- bhdrp->total_length = total_length;
- shbp->byte_order_magic = byte_order_magic;
- if (read_bytes(fp,
- (u_char *)p->buffer + (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
- total_length - (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)),
- 1, errbuf) == -1)
- goto fail;
- if (p->swapped) {
-
- shbp->major_version = SWAPSHORT(shbp->major_version);
- shbp->minor_version = SWAPSHORT(shbp->minor_version);
-
- }
-
- if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR &&
- shbp->minor_version == PCAP_NG_VERSION_MINOR)) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "unsupported pcapng savefile version %u.%u",
- shbp->major_version, shbp->minor_version);
- goto fail;
- }
- p->version_major = shbp->major_version;
- p->version_minor = shbp->minor_version;
-
- p->opt.tstamp_precision = precision;
-
- for (;;) {
-
- status = read_block(fp, p, &cursor, errbuf);
- if (status == 0) {
-
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "the capture file has no Interface Description Blocks");
- goto fail;
- }
- if (status == -1)
- goto fail;
- switch (cursor.block_type) {
- case BT_IDB:
-
- idbp = get_from_block_data(&cursor, sizeof(*idbp),
- errbuf);
- if (idbp == NULL)
- goto fail;
-
- if (p->swapped) {
- idbp->linktype = SWAPSHORT(idbp->linktype);
- idbp->snaplen = SWAPLONG(idbp->snaplen);
- }
-
- if (!add_interface(p, &cursor, errbuf))
- goto fail;
- goto done;
- case BT_EPB:
- case BT_SPB:
- case BT_PB:
-
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "the capture file has a packet block before any Interface Description Blocks");
- goto fail;
- default:
-
- break;
- }
- }
- done:
- p->tzoff = 0;
- p->snapshot = idbp->snaplen;
- if (p->snapshot <= 0) {
-
- p->snapshot = max_snaplen_for_dlt(idbp->linktype);
- }
- p->linktype = linktype_to_dlt(idbp->linktype);
- p->linktype_ext = 0;
-
- if (MAX_BLOCKSIZE(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize)
- ps->max_blocksize = MAX_BLOCKSIZE(max_snaplen_for_dlt(p->linktype));
- p->next_packet_op = pcap_ng_next_packet;
- p->cleanup_op = pcap_ng_cleanup;
- return (p);
- fail:
- free(ps->ifaces);
- free(p->buffer);
- free(p);
- *err = 1;
- return (NULL);
- }
- static void
- pcap_ng_cleanup(pcap_t *p)
- {
- struct pcap_ng_sf *ps = p->priv;
- free(ps->ifaces);
- sf_cleanup(p);
- }
- static int
- pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
- {
- struct pcap_ng_sf *ps = p->priv;
- struct block_cursor cursor;
- int status;
- struct enhanced_packet_block *epbp;
- struct simple_packet_block *spbp;
- struct packet_block *pbp;
- bpf_u_int32 interface_id = 0xFFFFFFFF;
- struct interface_description_block *idbp;
- struct section_header_block *shbp;
- FILE *fp = p->rfile;
- uint64_t t, sec, frac;
-
- for (;;) {
-
- status = read_block(fp, p, &cursor, p->errbuf);
- if (status == 0)
- return (1);
- if (status == -1)
- return (-1);
- switch (cursor.block_type) {
- case BT_EPB:
-
- epbp = get_from_block_data(&cursor, sizeof(*epbp),
- p->errbuf);
- if (epbp == NULL)
- return (-1);
-
- if (p->swapped) {
-
- interface_id = SWAPLONG(epbp->interface_id);
- hdr->caplen = SWAPLONG(epbp->caplen);
- hdr->len = SWAPLONG(epbp->len);
- t = ((uint64_t)SWAPLONG(epbp->timestamp_high)) << 32 |
- SWAPLONG(epbp->timestamp_low);
- } else {
- interface_id = epbp->interface_id;
- hdr->caplen = epbp->caplen;
- hdr->len = epbp->len;
- t = ((uint64_t)epbp->timestamp_high) << 32 |
- epbp->timestamp_low;
- }
- goto found;
- case BT_SPB:
-
- spbp = get_from_block_data(&cursor, sizeof(*spbp),
- p->errbuf);
- if (spbp == NULL)
- return (-1);
-
- interface_id = 0;
-
- if (p->swapped) {
-
- hdr->len = SWAPLONG(spbp->len);
- } else
- hdr->len = spbp->len;
-
- hdr->caplen = hdr->len;
- if (hdr->caplen > (bpf_u_int32)p->snapshot)
- hdr->caplen = p->snapshot;
- t = 0;
- goto found;
- case BT_PB:
-
- pbp = get_from_block_data(&cursor, sizeof(*pbp),
- p->errbuf);
- if (pbp == NULL)
- return (-1);
-
- if (p->swapped) {
-
- interface_id = SWAPSHORT(pbp->interface_id);
- hdr->caplen = SWAPLONG(pbp->caplen);
- hdr->len = SWAPLONG(pbp->len);
- t = ((uint64_t)SWAPLONG(pbp->timestamp_high)) << 32 |
- SWAPLONG(pbp->timestamp_low);
- } else {
- interface_id = pbp->interface_id;
- hdr->caplen = pbp->caplen;
- hdr->len = pbp->len;
- t = ((uint64_t)pbp->timestamp_high) << 32 |
- pbp->timestamp_low;
- }
- goto found;
- case BT_IDB:
-
- idbp = get_from_block_data(&cursor, sizeof(*idbp),
- p->errbuf);
- if (idbp == NULL)
- return (-1);
-
- if (p->swapped) {
- idbp->linktype = SWAPSHORT(idbp->linktype);
- idbp->snaplen = SWAPLONG(idbp->snaplen);
- }
-
- if (p->linktype != idbp->linktype) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "an interface has a type %u different from the type of the first interface",
- idbp->linktype);
- return (-1);
- }
- if ((bpf_u_int32)p->snapshot != idbp->snaplen) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "an interface has a snapshot length %u different from the type of the first interface",
- idbp->snaplen);
- return (-1);
- }
-
- if (!add_interface(p, &cursor, p->errbuf))
- return (-1);
- break;
- case BT_SHB:
-
- shbp = get_from_block_data(&cursor, sizeof(*shbp),
- p->errbuf);
- if (shbp == NULL)
- return (-1);
-
- if (p->swapped) {
- shbp->byte_order_magic =
- SWAPLONG(shbp->byte_order_magic);
- shbp->major_version =
- SWAPSHORT(shbp->major_version);
- }
-
- switch (shbp->byte_order_magic) {
- case BYTE_ORDER_MAGIC:
-
- break;
- case SWAPLONG(BYTE_ORDER_MAGIC):
-
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "the file has sections with different byte orders");
- return (-1);
- default:
-
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "the file has a section with a bad byte order magic field");
- return (-1);
- }
-
- if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "unknown pcapng savefile major version number %u",
- shbp->major_version);
- return (-1);
- }
-
- ps->ifcount = 0;
- break;
- default:
-
- break;
- }
- }
- found:
-
- if (interface_id >= ps->ifcount) {
-
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "a packet arrived on interface %u, but there's no Interface Description Block for that interface",
- interface_id);
- return (-1);
- }
- if (hdr->caplen > (bpf_u_int32)p->snapshot) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "invalid packet capture length %u, bigger than "
- "snaplen of %d", hdr->caplen, p->snapshot);
- return (-1);
- }
-
- sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset;
- frac = t % ps->ifaces[interface_id].tsresol;
-
- switch (ps->ifaces[interface_id].scale_type) {
- case PASS_THROUGH:
-
- break;
- case SCALE_UP_DEC:
-
- frac *= ps->ifaces[interface_id].scale_factor;
- break;
- case SCALE_UP_BIN:
-
- frac *= ps->user_tsresol;
- frac /= ps->ifaces[interface_id].tsresol;
- break;
- case SCALE_DOWN_DEC:
-
- frac /= ps->ifaces[interface_id].scale_factor;
- break;
- case SCALE_DOWN_BIN:
-
- frac *= ps->user_tsresol;
- frac /= ps->ifaces[interface_id].tsresol;
- break;
- }
- #ifdef _WIN32
-
- hdr->ts.tv_sec = (long)sec;
- hdr->ts.tv_usec = (long)frac;
- #else
-
- hdr->ts.tv_sec = (time_t)sec;
- hdr->ts.tv_usec = (int)frac;
- #endif
-
- *data = get_from_block_data(&cursor, hdr->caplen, p->errbuf);
- if (*data == NULL)
- return (-1);
- if (p->swapped)
- swap_pseudo_headers(p->linktype, hdr, *data);
- return (0);
- }
|