bool decode(FILE* infile, FILE* outfile) { // get the header info unsigned int maxBits = getBits(NBITS_MAXBITS, infile); unsigned int window = getBits(NBITS_WINDOW, infile); char eFlag = getBits(NBITS_EFLAG, infile); stringTable* table = (eFlag == 1) ? stringTableNew(maxBits, true) : stringTableNew(maxBits, false); pruneInfo* pi = pruneInfoNew(maxBits); unsigned int oldCode = EMPTY_PREFIX; // the previous code read from infile unsigned int newCode; // the code just read from infile unsigned int code; // initially equal to newCode, but then set to its // prefixes to obtain the entire string of newCode unsigned char finalK = 0, k; // characters in newCode stack* kStack = stackNew(); // holds characters from newCode in order to // put them in the correct order by reversal unsigned char nbits = (eFlag) ? 2 : 9; // number of bits per code while((newCode = code = getBits(nbits, infile)) != STOP_CODE) { switch(code) { case EOF: { // getting EOF before the STOP_CODE is an error stringTableDelete(table); stackDelete(kStack); pruneInfoDelete(pi); return false; break; } case GROW_NBITS_CODE: { nbits++; if(nbits > maxBits) { stringTableDelete(table); stackDelete(kStack); pruneInfoDelete(pi); return false; } break; } case PRUNE_CODE: { if(window == 0) { stringTableDelete(table); stackDelete(kStack); pruneInfoDelete(pi); return false; } else { table = stringTablePrune(table, pi, window, &oldCode); oldCode = EMPTY_PREFIX; // update nbits for(nbits = 2; (1 << nbits) -1 < table->highestCode; nbits++); } break; } case ESCAPE_CODE: { if(eFlag == 0) { stringTableDelete(table); stackDelete(kStack); pruneInfoDelete(pi); return false; } unsigned char escapedChar = getBits(8, infile); fputc(escapedChar, outfile); if(oldCode != EMPTY_PREFIX) { stringTableAdd(table, oldCode, escapedChar, NULL); } unsigned int tempCode; stringTableAdd(table, EMPTY_PREFIX, escapedChar, &tempCode); pruneInfoSawCode(pi, tempCode); oldCode = EMPTY_PREFIX; // reset prefix to EMPTY break; } default: { pruneInfoSawCode(pi, newCode); if(!stringTableCodeSearch(table, code)) { stackPush(kStack, finalK); code = oldCode; } // push string for code onto kStack until we get to the code // with an empty prefix, which goes into finalK tableElt* elt = stringTableCodeSearch(table, code); while(elt && elt->prefix != EMPTY_PREFIX) { stackPush(kStack, elt->k); code = elt->prefix; elt = stringTableCodeSearch(table, code); } finalK = elt->k; // print the characters in correct order now that they've been // reversed by pushing them onto kStack fputc(finalK, outfile); while(stackPop(kStack, &k)) { fputc(k, outfile); } // add oldCode to the table, then update it to the current code if(oldCode != EMPTY_PREFIX) { stringTableAdd(table, oldCode, finalK, NULL); } oldCode = newCode; break; } } } stringTableDelete(table); stackDelete(kStack); pruneInfoDelete(pi); return true; }
bool DVBevents::tableEIT( unsigned char* buffer ) { unsigned char* buf = buffer; unsigned int length, loop, sid, tid, eid, tsid, sn, lsn, nid; int i, sec; EventDesc *desc=0, *itdesc=0; EventSid *slist; QPtrList<EventDesc> *currentEvents; bool nodesc, parse; QDateTime start, cur, dt; unsigned int cdt = QDateTime::currentDateTime().toTime_t(); tid = getBits(buf,0,8); length = getBits(buf,12,12); sid = getBits(buf,24,16); sn = getBits(buf,48,8); lsn = getBits(buf,56,8); tsid = getBits(buf,64,16); nid = getBits(buf,80,16); length -=11; buf +=14; slist = currentSrc->getEventSid( nid, tsid, sid ); if ( !slist ) return false; slist->lock(); currentEvents = slist->getEvents(); QPtrListIterator<EventDesc> it( *currentEvents ); while ( length>4 ) { nodesc=parse=false; if ( !safeLen( buf+2 ) ) goto stop; eid = getBits(buf,0,16); if ( !safeLen( buf+2+5 ) ) goto stop; start = getDateTime( buf+2 ); nodesc=parse=true; it.toFirst(); while ( (desc=it.current())!=0 ) { if ( desc->sid==sid ) { if ( desc->startDateTime==start || desc->eid==eid ) { if ( desc->tid==0x4e && tid!=0x4e ) { parse = false; nodesc = false; break; } else { nodesc = false; if ( (cdt-desc->loop)<300 ) { // only reparse events every 300 seconds parse = false; } else { desc->extEvents.clear(); desc->shortEvents.clear(); desc->title=desc->subtitle=""; } break; } } } ++it; } if ( nodesc ) desc = new EventDesc(); if ( parse ) { if ( !safeLen( buf+10 ) ) goto stop; desc->duration = getTime( buf+7 ); if ( !safeLen( buf+11 ) ) goto stop; desc->running = getBits(buf,80,3); desc->sid = sid; desc->tid = tid; desc->tsid = tsid; desc->nid = nid; desc->lsn = lsn; desc->sn = sn; desc->eid = eid; desc->loop = cdt; } if ( desc->sn != sn ) { slist->unlock(); return false; } if ( !safeLen( buf+12 ) ) goto stop; loop = getBits(buf,84,12); buf +=12; length -=(12+loop); while ( loop>0 ) { if ( parse ) { if ( !safeLen( buf+1 ) ) goto stop; switch ( getBits(buf,0,8) ) { case 0x4D : if ( !shortEventDesc( buf, desc ) ) goto stop; break; case 0x4E : if ( !extEventDesc( buf, desc ) ) goto stop; break; default : break; } } if ( !safeLen( buf+2 ) ) goto stop; loop -=( getBits(buf,8,8)+2 ); buf +=( getBits(buf,8,8)+2 ); } //out: if ( parse ) { if ( !nodesc ) { if ( start==desc->startDateTime ) goto ifend; currentEvents->take( currentEvents->find( desc ) ); } desc->startDateTime = start; for ( i=0; i<(int)currentEvents->count(); i++ ) { itdesc = currentEvents->at(i); if ( desc->startDateTime<itdesc->startDateTime ) { currentEvents->insert( i, desc ); break; } itdesc = 0; } if ( !itdesc ) currentEvents->append( desc ); } ifend: if ( parse ) ++(desc->sn); if ( nodesc ) { cur = QDateTime::currentDateTime(); dt = desc->startDateTime; sec = desc->duration.hour()*3600+desc->duration.minute()*60+desc->duration.second(); if ( dt.addSecs( sec )<cur || desc->title.length()<3 ) { currentEvents->remove( desc ); } else desc->source = currentSrc->getSource(); } } slist->unlock(); return true; stop: slist->unlock(); fprintf( stderr, "Stop parsing EIT (%d:%d)\n", adapter, tuner ); if ( nodesc ) delete desc; return false; }
void net_IP_data (int v, u_char *b, int len) { int ip_version; int protocol = -1; // print_databytes (v, "IP_datagram_bytes", b, len); out_NL (v); out_nl (v,"IP_datagram_bytes:"); indent (+1); ip_version = outBit_Sx_NL (v, "Version: ", b, 0, 4); if (ip_version == 4) { // -- RFC 791 IPv4 int header_len; int ip; header_len = outBit_Sx_NL (v, "IP header length: ", b, 4, 4); outBit_Sx_NL (v, "Type of service: ", b, 8, 8); outBit_Sx_NL (v, "Total length: ", b, 16, 16); outBit_Sx_NL (v, "Identification: ", b, 32, 16); outBit_Sx_NL (v, "Reserved: ", b, 48, 1); outBit_Sx_NL (v, "DF: ", b, 49, 1); outBit_Sx_NL (v, "MF: ", b, 50, 1); outBit_Sx_NL (v, "Fragment offset: ", b, 51, 13); outBit_Sx_NL (v, "Time to live: ", b, 64, 8); protocol = outBit_S2x_NL(v, "Protocol: ", b, 72, 8, (char *(*)(u_long))netStr_RFC790_protocol_nr ); outBit_Sx_NL (v, "Header checksum: ", b, 80, 16); ip = getBits (b, 0, 96, 32); out (v,"Source address: %08lx [= ", ip); displ_IPv4_addr (v, ip); out_nl (v,"]"); ip = getBits (b, 0, 128, 32); out (v,"Destination address: %08lx [= ", ip); displ_IPv4_addr (v, ip); out_nl (v,"]"); b += (5*4); // 5*4 = header length len -= (5*4); // -- IPv4 Options & Padding // --- n = number of options // --- Total bit length: ( ( 5+n ) * 32 ), 5 is minimum header if (header_len > 5) { // -- TODO Options & Padding print_databytes (v, "Options & Padding ", b, len); b += (header_len-5)*4; len -= (header_len-5)*4; } } else if (ip_version == 6) { // -- RFC 2460 for IPv6 struct IPv6ADDR x; outBit_Sx_NL (v, "Traffic class: ", b, 4, 8); outBit_Sx_NL (v, "Flow label: ", b, 12, 20); outBit_Sx_NL (v, "Payload length: ", b, 32, 16); protocol = outBit_Sx_NL (v, "Next header: ", b, 48, 16); outBit_Sx_NL (v, "Hop limit: ", b, 64, 16); getIPv6Addr (b+8, &x); out (v, "Source address: %08lx%08lx%08lx%08lx [= ", x.ip[0], x.ip[1], x.ip[2], x.ip[3] ); displ_IPv6_addr (4, &x); out_nl (v,"]"); getIPv6Addr (b+24, &x); out (v, "Destination address: %08lx%08lx%08lx%08lx [= ", x.ip[0], x.ip[1], x.ip[2], x.ip[3] ); displ_IPv6_addr (4, &x); out_nl (v,"]"); b += 40; len -= 40; } // -- ICMP, RFC 792 if (protocol == 1) { out_NL (v); out_nl (v,"ICMP_data: "); indent (+1); print_databytes (v, "Data", b, len); // $$$ TODO b += len; len = 0; indent (-1); } // -- TCP, RFC 793 if (protocol == 6) { out_NL (v); out_nl (v,"TCP_data: "); indent (+1); print_databytes (v, "Data", b, len); // $$$ TODO b += len; len = 0; indent (-1); } // -- UDP datagram, RFC 768 if (protocol == 17) { int udp_header_len; out_NL (v); out_nl (v,"UDP_datagram: "); indent (+1); outBit_Sx_NL (v, "Source port: ", b, 0, 16); outBit_Sx_NL (v, "Destination port: ", b, 16, 16); udp_header_len = outBit_Sx_NL (v, "Length: ", b, 32, 16); outBit_Sx_NL (v, "Checksum: ", b, 48, 16); print_databytes (v, "Data", b+8, udp_header_len-8); b += udp_header_len; // -- length is complete header + data len -= udp_header_len; indent (-1); } if (len > 0) { print_databytes (v, "Unknown Data / Padding", b, len); b += len; len -= len; } out_NL (v); indent (-1); }
// decodes using lzw algorithm void decode() { int code, newcode; int maxbits = getFlags(2); int maxcodes = (1 << maxbits); int p = getFlags(1); int e = getFlags(1); Trie st; createT(&st, e); int bitCount = (e) ? 2 : 9; int codeCount = (e) ? 3 : 259; int oldc = EMPTY; bool kwk = false; char baseK; int pruneCount=0, kwkcount=0; while((newcode=code=getBits(bitCount))!=EOFILE) { // under these conditions, a valid prune can occur if(p && code==EMPTY) { pruneCount++; Trie newst; createT(&newst, e); int oldCodeCount=codeCount; codeCount=pruneT(&st, &newst, e, oldCodeCount); destroyT(&st, oldCodeCount); st=newst; bitCount=codeLength(codeCount); oldc=EMPTY; continue; } if(newcode>=codeCount+1) { ERROR("code impossible to decode\n"); } // read an escaped character else if(e && code==ESC) { if(tableFilled(codeCount+1)&&bitCount!=codeLength(codeCount+1)) { if(bitCount<maxbits) { bitCount++; } } code=getBits(8); baseK=(char)code; putchar(baseK); if(codeCount<maxcodes) { if(tableFilled(codeCount+1)) { expandT(&st, (codeCount)*2); } addT(&st, oldc, code, codeCount); codeCount++; // then we need to add the char k as it's own code if(oldc!=EMPTY) { if(tableFilled(codeCount+1)) { expandT(&st, (codeCount)*2); } addT(&st, EMPTY, code, codeCount); codeCount++; if(tableFilled(codeCount)&&bitCount!=codeLength(codeCount)) { if(bitCount<maxbits) { bitCount++; } } } } oldc=EMPTY; } else { // no escape character called, would read c and k normally if(newcode==codeCount) { kwk=true; code=oldc; // omega, need to print k after } baseK=outputCode(&st, code, true); if(kwk) { putchar(baseK); kwkcount++; } // oldc is empty on the first read, and when the e-flag is present // oldc is zero when the last character read was escaped if(oldc!=EMPTY) { if(codeCount<maxcodes) { if(tableFilled(codeCount+1)) { expandT(&st, (codeCount)*2); } addT(&st, oldc, (int)baseK, codeCount); codeCount++; if(kwk) { // we added kwk after seeing it once already in the prev // scan through so we should increase its number of apps st[newcode].appearances++; // this scenario means we have kkk, without w in between // so if(st[st[oldc].prefix].prefix==EMPTY&&kwkcount==1) { st[oldc].appearances--; } kwk=false; } if(tableFilled(codeCount+1)) { if(bitCount<maxbits&&bitCount!=codeLength(codeCount+1)) { bitCount++; } } } } else if(e) { // if e-flag & last char was excaped, increase bit count if // table is filled now if(tableFilled(codeCount+1)) { if(bitCount<maxbits) { bitCount++; } } } oldc = newcode; } } destroyT(&st, codeCount); }
void section_PAT (u_char *b, int len) { /* IS13818-1 S. 62 */ typedef struct _PAT { u_int table_id; u_int section_syntax_indicator; u_int reserved_1; u_int section_length; u_int transport_stream_id; u_int reserved_2; u_int version_number; u_int current_next_indicator; u_int section_number; u_int last_section_number; // N pat_list u_long CRC; } PAT; typedef struct _PAT_LIST { u_int program_number; u_int reserved; u_int network_pmt_PID; } PAT_LIST; PAT p; PAT_LIST pl; int n; p.table_id = b[0]; p.section_syntax_indicator = getBits (b, 0, 8, 1); p.reserved_1 = getBits (b, 0, 10, 2); p.section_length = getBits (b, 0, 12, 12); p.transport_stream_id = getBits (b, 0, 24, 16); p.reserved_2 = getBits (b, 0, 40, 2); p.version_number = getBits (b, 0, 42, 5); p.current_next_indicator = getBits (b, 0, 47, 1); p.section_number = getBits (b, 0, 48, 8); p.last_section_number = getBits (b, 0, 56, 8); out_nl (3,"PAT-decoding...."); out_S2B_NL (3,"Table_ID: ",p.table_id, dvbstrTableID (p.table_id)); if (p.table_id != 0x00) { out_nl (3,"wrong Table ID"); return; } out_SB_NL (3,"section_syntax_indicator: ",p.section_syntax_indicator); out_SB_NL (6,"(fixed): ",0); out_SB_NL (6,"reserved_1: ",p.reserved_1); out_SW_NL (5,"Section_length: ",p.section_length); out_SW_NL (3,"Transport_Stream_ID: ",p.transport_stream_id); out_SB_NL (6,"reserved_2: ",p.reserved_2); out_SB_NL (3,"Version_number: ",p.version_number); out_S2B_NL(3,"current_next_indicator: ",p.current_next_indicator, dvbstrCurrentNextIndicator(p.current_next_indicator)); out_SB_NL (3,"Section_number: ",p.section_number); out_SB_NL (3,"Last_Section_number: ",p.last_section_number); // PID list... // n = section_length - CRC - front bytes // n = len / anzahl bytes pro pid angabe. // Buffer to start of List n = p.section_length - 5 - 4; b = b + 8; indent (+1); for (; n>=4; n=n-4) { pl.program_number = getBits (b, 0, 0, 16); pl.reserved = getBits (b, 0, 16, 3); pl.network_pmt_PID = getBits (b, 0, 19, 13); b += 4; store_PidToMem (pl.network_pmt_PID); out_NL (3); out_SW_NL (3,"Program_number: ",pl.program_number); out_SB_NL (6,"reserved: ",pl.reserved); out_SW_NL (3,(pl.program_number) ?"Program_map_PID: " :"Network_PID: ", pl.network_pmt_PID); } indent (-1); out_NL (3); p.CRC = getBits (b,0,0,32); out_SL_NL (5,"CRC: ",p.CRC); }
uint32_t getRN(uint32_t inst){ return getBits(inst,16,19); }
unsigned char getByteNumber(int byteNo, unsigned int source) { int lower = byteNo * 8; int higher = lower + 7; return getBits(lower, higher, source); }
//----------------------------------------------------------------------- uint32_t getRD(uint32_t inst){ return getBits(inst,12,15); }
Boolean validateConfig(char *config, UInt32 *audioChannels, UInt32 *sampleRate, UInt32 *subFrames, UInt8 *esds, UInt32 *esdsSize) { UInt8 *buffer = 0, *p, *q; bitStreamRecord bits; UInt32 length = FskStrLen(config); UInt32 configBitsRemaining; Boolean valid = false; UInt8 audioMuxVersion, numSubFrames, numProgram, numLayer; UInt8 audioObjectType, samplingFrequencyIndex, channelConfiguration; UInt8 dependsOnCoreCoder, extensionFlag, frameLengthType; UInt32 samplingFrequency; const UInt32 samplingFrequencyTable[] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350}; BAIL_IF_ERR(FskMemPtrNewClear(length, &buffer)); p = (UInt8*)config; q = buffer; while (*p) { UInt8 a, b; if (*p >= '0' && *p <= '9') a = *p - '0'; else if (*p >= 'a' && *p <= 'f') a = *p - 'a' + 10; else a = *p - 'A' + 10; ++p; if (*p >= '0' && *p <= '9') b = *p - '0'; else if (*p >= 'a' && *p <= 'f') b = *p - 'a' + 10; else b = *p - 'A' + 10; ++p; *q++ = (a << 4) + b; } // Parse the StreamMuxConfig bits.data = buffer; bits.position = 0; audioMuxVersion = (UInt8)getBits(&bits, 1); if (0 != audioMuxVersion) goto bail; (void)getBits(&bits, 1); // allStreamsSameTimeFraming numSubFrames = (UInt8)getBits(&bits, 6); numProgram = (UInt8)getBits(&bits, 4); numLayer = (UInt8)getBits(&bits, 3); // We only handle one layer/sub-frame/program // Note these bit fields are stored "minus one", i.e. one layer == (0 == numLayer) if (0 != numProgram || 0 != numLayer) goto bail; // Parse the AudioSpecificConfig audioObjectType = (UInt8)getBits(&bits, 5); if (2 != audioObjectType) goto bail; // AAC LC samplingFrequencyIndex = (UInt8)getBits(&bits, 4); if ( samplingFrequencyIndex==0xf ) samplingFrequency = getBits(&bits, 24); else if (samplingFrequencyIndex > 0xC) goto bail; else samplingFrequency = samplingFrequencyTable[samplingFrequencyIndex]; channelConfiguration = (UInt8)getBits(&bits, 4); if (channelConfiguration == 0 || channelConfiguration > 2) goto bail; valid = true; // Parse the GASpecificConfig (void)getBits(&bits, 1); // frameLengthFlag dependsOnCoreCoder = (UInt8)getBits(&bits, 1); if (dependsOnCoreCoder) { (void)getBits(&bits, 14); // coreCoderDelay } extensionFlag = (UInt8)getBits(&bits, 1); if (extensionFlag) { getBits(&bits, 1); // extensionFlag3 } // Back to StreamMuxConfig() frameLengthType = (UInt8)getBits(&bits, 3); if (0 == frameLengthType) { (void)getBits(&bits, 8); // latmBufferFullness } if (NULL != audioChannels) *audioChannels = channelConfiguration; if (NULL != sampleRate) *sampleRate = samplingFrequency; if (NULL != subFrames) *subFrames = numSubFrames; // Generate the esds from the AudioSpecificConfig if (NULL != esds) { UInt8 *esdsPtr = esds; *esdsPtr++ = 0x4; // <DecoderConfigDesciptorTag> *esdsPtr++ = 0; // pad *esdsPtr++ = 0x40; // <objectTypeIndication> *esdsPtr++ = 0x14; // <streamType>, <upstream>, <reserved> esdsPtr += 3; // buffersize DB esdsPtr += 4; // max bitrate esdsPtr += 4; // avg bitrate *esdsPtr++ = 0x05; // <DecoderSpecificInfoTag> *esdsPtr++ = 0; // pad // Rewind back to the AudioSpecificConfig bits.data = buffer; bits.position = 0; getBits(&bits, 15); configBitsRemaining = (length * 4) - 15; // Append the AudioSpecificConfig and GASpecificConfig to the esds while (configBitsRemaining) { UInt8 nBits = (UInt8)(configBitsRemaining > 8 ? 8 : configBitsRemaining); *esdsPtr++ = (UInt8)getBits(&bits, nBits); configBitsRemaining -= nBits; } *esdsSize = (UInt32)(esdsPtr - esds); } bail: FskMemPtrDispose(buffer); return valid; }
int print_vps_decode (int v, u_char *b, int len) { // warning! Nipples e.g. _2_7 may not be msb...lsb order! // see: ETSI EN 300 231 for this notation! u_int pcs; u_int cni_1_4; u_int pil; u_int pty; u_int day, month, hour, minute; u_int country_5_8; u_int npp, npp_0_1, npp_2_7; out_nl (v,"VPS data:"); print_databytes (8,"Data:", b, len); indent (+1); // -- starts at EN 300 231 8.2.2 Fig.9 Table // -- Byte 3..15 , so byte 3 => [0] // -- vps_data_block: // -- Byte 3+4: not relevant to PDC // -- Info from datasheet SAA4700 (Philips) outBit_Sx_NL (v,"(program source identification (binary coded)): ", b, 0, 8); outBit_Sx_NL (v,"(program source identification (ASCII seq)): ", b+1, 0, 8); // -- PCS pcs = outBit_S2x_NL (v,"PCS audio: ", b+2, 0, 2, (char *(*)(u_long)) dvbstrVPS_pcs_audio ); pcs = outBit_Sx_NL (v,"PCS reserved: ", b+2, 2, 2); cni_1_4 = outBit_Sx (v,"CNI reserved: ", b+2, 4, 4); if (cni_1_4 == 0x0F) out_nl (4, " [= Unenhanced VPS]"); else out_nl (4, " [= Enhanced VPS]"); // -- Byte 6..10: not relevant to PDC // -- Info from datasheet SAA4700 (Philips) outBit_Sx_NL (v,"(program/test picture identification): ", b+3, 0, 8); outBit_Sx_NL (v,"(internal information exchange): ", b+4, 0, 8); outBit_Sx_NL (v,"(address assignment of signal distribution): ", b+5, 0, 16); outBit_Sx_NL (v,"(messages/commands): ", b+7, 0, 8); pil = getBits (b, 8, 2, 20); npp_0_1 = getBits (b, 8, 0, 2); day = getBits (b, 8, 2, 5); month = getBits (b, 8, 7, 4); hour = getBits (b, 8, 11, 5); minute = getBits (b, 8, 16, 6); country_5_8 = getBits (b, 8, 22, 4); npp_2_7 = getBits (b, 8, 26, 6); pty = getBits (b, 8, 32, 8); // byte 15 out_SB_NL (v,"NPP_1: ", npp_0_1); out_ST (v,"Program Identificaion Label (PIL): ", pil); if (day != 0x00) { out_nl (v," [= month=%d day=%d hour=%d min=%d]", month, day, hour, minute); } else { char *s; switch (pil) { case 0x07FFF: s = "Timer-control code (TC)"; break; case 0x07FBF: s = "Record inhibit/Terminate (RI/T)"; break; case 0x07F7F: s = "Interrruption code (INT)"; break; case 0x07F3F: s = "Continuation code"; break; case 0xFFFFF: s = "Program selected by PTY"; break; default: s = "UNKOWN code"; break; } out_nl (v," [= %s]",s); } out_S2B_NL (v,"Country: ", country_5_8, dvbstrVPS_cni_countrycode(1+(country_5_8 << 4)) ); out_SB_NL (v,"NPP_2: ", npp_2_7); npp = (npp_0_1 << 6) + (npp_2_7); // msb ... lsb out_S2B_NL (v," ==> Network/Program Provider (NPP): ", npp, dvbstrVPS_npp(npp) ); out_S2B_NL (v,"Program Type (PTY): ", pty, dvbstrVPS_pty(pty) ); indent (-1); return len; }
// !!!! WDS not yet implemented BOOLEAN read_packets(void) { int i, start; time_t tt; unsigned char * h80211; size_t bytes_read; i=0; memset( &stats, 0, sizeof( stats ) ); tt = time( NULL ); switch(_pfh_in.linktype) { case LINKTYPE_PRISM_HEADER: start = 144; // based on madwifi-ng break; case LINKTYPE_RADIOTAP_HDR: start = (int)(buffer[2]); // variable length! break; case LINKTYPE_IEEE802_11: // 0 case LINKTYPE_PPI_HDR: // ? default: start = 0; break; } // Show link type printf("Link type (Prism: %d - Radiotap: %d - 80211: %d - PPI - %d): ", LINKTYPE_PRISM_HEADER, LINKTYPE_RADIOTAP_HDR, LINKTYPE_IEEE802_11, LINKTYPE_PPI_HDR); switch (_pfh_in.linktype) { case LINKTYPE_PRISM_HEADER: puts("Prism"); break; case LINKTYPE_RADIOTAP_HDR: puts("Radiotap"); break; case LINKTYPE_IEEE802_11: puts("802.11"); break; case LINKTYPE_PPI_HDR: puts("PPI"); default: printf("Unknown (%d)\n", _pfh_in.linktype); break; } // Initialize double linked list. initialize_linked_list(); while( 1 ) { if( time( NULL ) - tt > 0 ) { // update the status line every second printf( "\33[KRead %ld packets...\r", stats.nb_read ); fflush( stdout ); tt = time( NULL ); } /* read one packet */ // Only malloc if complete add_node_if_not_complete(); //puts("Reading packet header"); bytes_read = fread( &( _packet_elt_head->current->header ), 1, PACKET_HEADER_SIZE, _input_file ); if( bytes_read != (size_t) PACKET_HEADER_SIZE ) { if (bytes_read != 0) { printf("Failed to read packet header.\n"); } else { // Normal, reached EOF. //printf("Reached EOF.\n"); } break; } if( _pfh_in.magic == TCPDUMP_CIGAM ) SWAP32( _packet_elt_head->current->header.caplen ); if( _packet_elt_head->current->header.caplen <= 0 || _packet_elt_head->current->header.caplen > 65535 ) { printf( "Corrupted file? Invalid packet length %d.\n", _packet_elt_head->current->header.caplen ); break; } // Reset buffer memset(buffer, 0, 65536); // Read packet from file bytes_read = fread( buffer, 1, _packet_elt_head->current->header.caplen, _input_file ); if( bytes_read != (size_t) _packet_elt_head->current->header.caplen ) { printf("Error reading the file: read %lu bytes out of %d.\n", (unsigned long) bytes_read, _packet_elt_head->current->header.caplen); break; } stats.nb_read++; // Put all stuff in the packet header and // ---------------------------- Don't remove anything ---------------------- // ---------------------------- Just know where the packet start ----------- h80211 = buffer + start; // Know the kind of packet _packet_elt_head->current->frame_type = getBits(*h80211, 2, 2); #ifdef DEBUG printf("Frame type: %d\n", _packet_elt_head->current->frame_type); #endif _packet_elt_head->current->version_type_subtype = *h80211; #ifdef DEBUG printf("First byte: %x\n",*h80211); #endif // Filter out unknown packet types and control frames if (_packet_elt_head->current->frame_type != FRAME_TYPE_DATA && _packet_elt_head->current->frame_type != FRAME_TYPE_MANAGEMENT) { // Don't care about the frame if it's a control or unknown frame). if (_packet_elt_head->current->frame_type != FRAME_TYPE_CONTROL) { // Unknown frame type, log it //printf("Unknown frame type: %d\n", packet->frame_type); // ------------- May be interesting to put all those packets in a separate file } continue; } if (_packet_elt_head->current->frame_type == FRAME_TYPE_MANAGEMENT) { // Assumption: Management packets are not cloaked (may change in the future) _packet_elt_head->current->is_cloaked = VALID_FRAME_UNCLOAKED; } else if (_packet_elt_head->current->frame_type == FRAME_TYPE_DATA){ _packet_elt_head->current->is_cloaked = UKNOWN_FRAME_CLOAKING_STATUS; } // Retry bit _packet_elt_head->current->retry_bit = getBit(*(h80211+1), 3); // More fragments bit _packet_elt_head->current->more_fragments_bit = getBit(*(h80211+1), 2); if (_packet_elt_head->current->more_fragments_bit && _options_drop_fragments) { _packet_elt_head->current->is_dropped = 1; } // TODO: Get the speed from the packet if radiotap/prism header exist. // TODO: Get also the channel from the headers (the sensor may inject // cloaked frames on a channel is not the same as the AP) #ifdef DEBUG printf("Retry bit: %d\n", _packet_elt_head->current->retry_bit); printf("More fragments bit: %d\n", _packet_elt_head->current->more_fragments_bit); #endif /*------------------------------- drop if control frame (does not contains SN) ----------------------*/ // TODO: We should care about control frames since they are not cloaked // and they can be usefull for signal filtering (have a better average). /* check the BSSID */ switch( h80211[1] & 3 ) { case 0: // To DS = 0, From DS = 0: DA, SA, BSSID (Ad Hoc) memcpy( _packet_elt_head->current->destination, h80211 + 4, 6 ); memcpy( _packet_elt_head->current->source, h80211 + 10, 6 ); memcpy( _packet_elt_head->current->bssid, h80211 + 16, 6 ); _packet_elt_head->current->fromDS = 0; _packet_elt_head->current->toDS = 0; break; case 1: // To DS = 1, From DS = 0: BSSID, SA, DA (To DS) memcpy( _packet_elt_head->current->bssid, h80211 + 4, 6 ); memcpy( _packet_elt_head->current->source, h80211 + 10, 6 ); memcpy( _packet_elt_head->current->destination, h80211 + 16, 6 ); _packet_elt_head->current->fromDS = 0; _packet_elt_head->current->toDS = 1; break; case 2: // To DS = 0, From DS = 1: DA, BSSID, SA (From DS) memcpy( _packet_elt_head->current->destination, h80211 + 4, 6 ); memcpy( _packet_elt_head->current->bssid, h80211 + 10, 6 ); memcpy( _packet_elt_head->current->source, h80211 + 16, 6 ); _packet_elt_head->current->fromDS = 1; _packet_elt_head->current->toDS = 0; break; case 3: // To DS = 1, From DS = 1: RA, TA, DA, SA (WDS) memcpy( _packet_elt_head->current->source, h80211 + 24, 6 ); memcpy( _packet_elt_head->current->bssid, h80211 + 10, 6 ); memcpy( _packet_elt_head->current->destination, h80211 + 16, 6 ); _packet_elt_head->current->fromDS = 1; _packet_elt_head->current->toDS = 1; break; } #ifdef DEBUG printf("From DS: %d - ToDS: %d\n", _packet_elt_head->current->fromDS, packet->toDS); printf("BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n", _packet_elt_head->current->bssid[0], _packet_elt_head->current->bssid[1], _packet_elt_head->current->bssid[2], _packet_elt_head->current->bssid[3], _packet_elt_head->current->bssid[4], _packet_elt_head->current->bssid[5]); printf("Source: %02X:%02X:%02X:%02X:%02X:%02X\n", _packet_elt_head->current->source[0], _packet_elt_head->current->source[1], _packet_elt_head->current->source[2], _packet_elt_head->current->source[3], _packet_elt_head->current->source[4], _packet_elt_head->current->source[5]); printf("Dest: %02X:%02X:%02X:%02X:%02X:%02X\n", _packet_elt_head->current->destination[0], _packet_elt_head->current->destination[1], _packet_elt_head->current->destination[2], _packet_elt_head->current->destination[3], _packet_elt_head->current->destination[4], _packet_elt_head->current->destination[5]); #endif // Filter out packets not belonging to our BSSID if ( memcmp( _packet_elt_head->current->bssid, _bssid, 6)) { // Not the BSSID we are looking for //printf("It's not the BSSID we are looking for.\n"); continue; } // Grab sequence number and fragment number _packet_elt_head->current->sequence_number = ((h80211[22]>>4)+(h80211[23]<<4)); // 12 bits _packet_elt_head->current->fragment_number = getBits(h80211[23], 4,4); // 4 bits // drop frag option if (_options_drop_fragments && _packet_elt_head->current->fragment_number) { _packet_elt_head->current->is_dropped = 1; } #ifdef DEBUG printf("Sequence: %d - Fragment: %d\n", _packet_elt_head->current->sequence_number, _packet_elt_head->current->fragment_number); #endif // Get the first beacon and search for WEP only // if not (data) wep, stop completely processing (_is_wep) if (_packet_elt_head->current->frame_type == FRAME_TYPE_MANAGEMENT) { // Get encryption from beacon/probe response if( h80211[0] == BEACON_FRAME || h80211[0] == PROBE_RESPONSE ) { if( ( h80211[34] & 0x10 ) >> 4 ) { _is_wep = 1; // Make sure it's not WPA // TODO: See airodump-ng around line 1500 } else { // Completely stop processing printf("FATAL ERROR: The network is not WEP (byte 34: %d)\n.", h80211[34]); exit(1); } } } if (_packet_elt_head->current->frame_type == FRAME_TYPE_DATA) { // Copy IV memcpy(_packet_elt_head->current->iv, (h80211 + 24), 3); #ifdef DEBUG printf("IV: %X %X %X\n", _packet_elt_head->current->iv[0], _packet_elt_head->current->iv[1], _packet_elt_head->current->iv[2]); #endif // Copy key index _packet_elt_head->current->key_index = h80211[27]; #ifdef DEBUG printf("Key index: %d\n", packet->key_index); #endif // Copy checksum memcpy(_packet_elt_head->current->icv, buffer + (_packet_elt_head->current->header.caplen) - 4, 4); #ifdef DEBUG printf("ICV: %X %X %X %X\n", _packet_elt_head->current->icv[0], _packet_elt_head->current->icv[1], _packet_elt_head->current->icv[2], _packet_elt_head->current->icv[3]); #endif } else { // Management packet (control packets were filtered out. _packet_elt_head->current->iv[0] = _packet_elt_head->current->iv[1] = _packet_elt_head->current->iv[2] = 0; _packet_elt_head->current->key_index = 0; _packet_elt_head->current->icv[0] = _packet_elt_head->current->icv[1] = _packet_elt_head->current->icv[2] = _packet_elt_head->current->icv[3] = 0; #ifdef DEBUG printf("Not a data packet thus no IV, no key index, no ICV\n"); #endif } // Copy the packet itself _packet_elt_head->current->packet = (unsigned char *) malloc(_packet_elt_head->current->header.caplen); memcpy(_packet_elt_head->current->packet, buffer, _packet_elt_head->current->header.caplen); // Copy signal if exist _packet_elt_head->current->signal_quality = -1; if (_pfh_in.linktype == LINKTYPE_PRISM_HEADER) { // Hack: pos 0x44 (at least on madwifi-ng) _packet_elt_head->current->signal_quality = buffer[0x44]; } else if (_pfh_in.linktype == LINKTYPE_RADIOTAP_HDR) { _packet_elt_head->current->signal_quality = get_rtap_signal( _packet_elt_head->current->header.caplen); } #ifdef DEBUG printf("Signal quality: %d\n", _packet_elt_head->current->signal_quality); #endif // Append to the list #ifdef ONLY_FIRST_PACKET puts("!!! Don't forget to append"); break; #else set_node_complete(); #endif }
void section_RST (u_char *b, int len) { typedef struct _RST { u_int table_id; u_int section_syntax_indicator; u_int reserved_1; u_int reserved_2; u_int section_length; // N1 RST_LIST2 } RST; typedef struct _RST_LIST2 { u_int transport_stream_id; u_int original_network_id; u_int service_id; u_int event_id; u_int reserved_1; u_int running_status; } RST_LIST2; RST r; RST_LIST2 r2; int len1; r.table_id = b[0]; r.section_syntax_indicator = getBits (b, 0, 8, 1); r.reserved_1 = getBits (b, 0, 9, 1); r.reserved_2 = getBits (b, 0, 10, 2); r.section_length = getBits (b, 0, 12, 12); out_nl (3,"RST-decoding...."); out_S2B_NL (3,"Table_ID: ",r.table_id, dvbstrTableID (r.table_id)); if (r.table_id != 0x71) { out_nl (3,"wrong Table ID"); return; } out_SB_NL (3,"section_syntax_indicator: ",r.section_syntax_indicator); out_SB_NL (6,"reserved_1: ",r.reserved_1); out_SB_NL (6,"reserved_2: ",r.reserved_2); out_SW_NL (5,"Section_length: ",r.section_length); len1 = r.section_length - 3; b += 3; indent (+1); while (len1 > 0) { r2.transport_stream_id = getBits (b, 0, 0, 16); r2.original_network_id = getBits (b, 0, 16, 16); r2.service_id = getBits (b, 0, 32, 16); r2.event_id = getBits (b, 0, 48, 16); r2.reserved_1 = getBits (b, 0, 64, 5); r2.running_status = getBits (b, 0, 69, 3); b += 9; len1 -= 9; out_NL (3); out_SW_NL (3,"Transport_stream_ID: ",r2.transport_stream_id); out_S2W_NL (3,"Original_network_ID: ",r2.original_network_id, dvbstrOriginalNetwork_ID(r2.original_network_id)); out_S2W_NL (3,"Service_ID: ",r2.service_id, " --> refers to PMT program_number"); out_SW_NL (3,"Event_ID: ",r2.event_id); out_SB_NL (6,"reserved_1: ",r2.reserved_1); out_S2B_NL (3,"Running_status: ",r2.running_status, dvbstrRunningStatus_FLAG (r2.running_status)); } // while len1 indent (-1); }