SASC-NG
DVBSoftCAM

parse.c

Go to the documentation of this file.
00001 /*
00002  * Softcam plugin to VDR (C++)
00003  *
00004  * This code is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This code is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
00018  */
00019 
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022 #include <string.h>
00023 
00024 #include "parse.h"
00025 #include "misc.h"
00026 #include "log.h"
00027 
00028 // -----------------------------------------------------------------------------
00029 
00030 static void SortNanos(unsigned char *dest, const unsigned char *src, int len)
00031 {
00032   int w=0, c=-1;
00033   while(1) {
00034     int n=0x100;
00035     for(int j=0; j<len;) {
00036       int l=src[j+1]+2;
00037       if(src[j]==c) {
00038         if(w+l>len) {
00039           PRINTF(L_GEN_ERROR,"sortnanos: sanity check failed. Exceeding memory area. Probably corrupted nanos!");
00040           memset(dest,0,len); // zero out everything
00041           return;
00042           }
00043         memcpy(&dest[w],&src[j],l);
00044         w+=l;
00045         }
00046       else if(src[j]>c && src[j]<n)
00047         n=src[j];
00048       j+=l;
00049       }
00050     if(n==0x100) break;
00051     c=n;
00052     }
00053 }
00054 
00055 // -- cProviders ---------------------------------------------------------------
00056 
00057 void cProviders::AddProv(cProvider *p)
00058 {
00059   if(p) Add(p);
00060 }
00061 
00062 cProvider *cProviders::FindProv(const unsigned char *data)
00063 {
00064   cProvider *p=First();
00065   while(p) {
00066     if(p->MatchID(data)) break;
00067     p=Next(p);
00068     }
00069   return p;
00070 }
00071 
00072 cProvider *cProviders::MatchProv(const unsigned char *data)
00073 {
00074   cProvider *p=First();
00075   while(p) {
00076     if(p->MatchEMM(data)) break;
00077     p=Next(p);
00078     }
00079   return p;
00080 }
00081 
00082 // -- cAssSct ------------------------------------------------------------------
00083 
00084 cAssSct::cAssSct(const unsigned char *Data)
00085 {
00086   data=Data;
00087 }
00088 
00089 // -- cAssembleData ------------------------------------------------------------
00090 
00091 cAssembleData::cAssembleData(const unsigned char *Data)
00092 {
00093   data=Data;
00094   curr=0;
00095 }
00096 
00097 void cAssembleData::SetAssembled(const unsigned char *Data)
00098 {
00099   Add(new cAssSct(Data));
00100   curr=First();
00101 }
00102 
00103 const unsigned char *cAssembleData::Assembled(void)
00104 {
00105   const unsigned char *ret=0;
00106   if(First()) {
00107     if(curr) {
00108       ret=curr->Data();
00109       curr=Next(curr);
00110       }
00111     }
00112   else {
00113     ret=data;
00114     data=0;
00115     }
00116   return ret;
00117 }
00118 
00119 // -- cIdSet -------------------------------------------------------------------
00120 
00121 cIdSet::cIdSet(void)
00122 {
00123   card=0;
00124 }
00125 
00126 cIdSet::~cIdSet()
00127 {
00128   delete card;
00129 }
00130 
00131 void cIdSet::ResetIdSet(void)
00132 {
00133   delete card; card=0;
00134   Clear();
00135 }
00136 
00137 void cIdSet::SetCard(cCard *c)
00138 {
00139   delete card;
00140   card=c;
00141 }
00142 
00143 bool cIdSet::MatchEMM(const unsigned char *data)
00144 {
00145   return (card && card->MatchEMM(data)) || MatchProv(data);
00146 }
00147 
00148 bool cIdSet::MatchAndAssemble(cAssembleData *ad, int *updtype, cProvider **prov)
00149 {
00150   const unsigned char *data=ad->Data();
00151   cProvider *p;
00152   if(card && card->MatchEMM(data)) {
00153     if(updtype) *updtype=card->UpdateType(data);
00154     if(prov) *prov=0;
00155     if(card->Assemble(ad)>=0) return true;
00156     }
00157   else if((p=MatchProv(data))) {
00158     if(updtype) *updtype=p->UpdateType(data);
00159     if(prov) *prov=p;
00160     if(p->Assemble(ad)>=0) return true;
00161     }
00162   return false;
00163 }
00164 
00165 // -- cProviderIrdeto ----------------------------------------------------------
00166 
00167 cProviderIrdeto::cProviderIrdeto(unsigned char pb, const unsigned char *pi)
00168 {
00169   provBase=pb;
00170   memcpy(provId,pi,sizeof(provId));
00171 }
00172 
00173 bool cProviderIrdeto::MatchID(const unsigned char *data)
00174 {
00175   const unsigned int mode=cParseIrdeto::AddrBase(data);
00176   return (mode<0x10 && mode==provBase);
00177 }
00178 
00179 bool cProviderIrdeto::MatchEMM(const unsigned char *data)
00180 {
00181   const unsigned int len=cParseIrdeto::AddrLen(data);
00182   const unsigned int mode=cParseIrdeto::AddrBase(data);
00183   return (   mode<0x10 && len<=sizeof(provId)
00184           && mode==provBase && (!len || !memcmp(&data[4],provId,len)));
00185 }
00186 
00187 unsigned long long cProviderIrdeto::ProvId(void)
00188 {
00189   return (provId[0]<<24)+(provId[1]<<16)+(provId[2]<<8)+provBase;
00190 }
00191 
00192 // -- cCardIrdeto --------------------------------------------------------------
00193 
00194 cCardIrdeto::cCardIrdeto(unsigned char hb, const unsigned char *hs)
00195 {
00196   hexBase=hb;
00197   memcpy(hexSer,hs,sizeof(hexSer));
00198 }
00199 
00200 bool cCardIrdeto::MatchEMM(const unsigned char *data)
00201 {
00202   const unsigned int len=cParseIrdeto::AddrLen(data);
00203   const unsigned int mode=cParseIrdeto::AddrBase(data);
00204   return (   mode>=0x10 && len<=sizeof(hexSer)
00205           && mode==hexBase && (!len || !memcmp(&data[4],hexSer,len)));
00206 }
00207 
00208 int cCardIrdeto::UpdateType(const unsigned char *data)
00209 {
00210   switch(cParseIrdeto::AddrLen(data)) {
00211     case 0:  return 0; // global
00212     case 1:
00213     case 2:  return 2; // shared
00214     default: return 3; // unique
00215     }
00216 }
00217 
00218 // -- cParseIrdeto -------------------------------------------------------------
00219 
00220 unsigned int cParseIrdeto::AddrLen(const unsigned char *data)
00221 {
00222   return data[3] & 0x07;
00223 }
00224 
00225 unsigned int cParseIrdeto::AddrBase(const unsigned char *data)
00226 {
00227   return data[3] >> 3;
00228 }
00229 
00230 // -- cProviderSeca ------------------------------------------------------------
00231 
00232 cProviderSeca::cProviderSeca(const unsigned char *pi, const unsigned char *s)
00233 {
00234   memcpy(provId,pi,sizeof(provId));
00235   memcpy(sa,s,sizeof(sa));
00236 }
00237 
00238 bool cProviderSeca::MatchID(const unsigned char *data)
00239 {
00240   const unsigned char *id=cParseSeca::ProvIdPtr(data);
00241   return id && !memcmp(id,provId,sizeof(provId));
00242 }
00243 
00244 bool cProviderSeca::MatchEMM(const unsigned char *data)
00245 {
00246   return TID(data)==0x84 &&
00247          !memcmp(SID(data),provId,sizeof(provId)) && !memcmp(SA(data),sa,sizeof(sa));
00248 }
00249 
00250 unsigned long long cProviderSeca::ProvId(void)
00251 {
00252   return (provId[0]<<8)+provId[1];
00253 }
00254 
00255 // -- cCardSeca ----------------------------------------------------------------
00256 
00257 cCardSeca::cCardSeca(const unsigned char *u)
00258 {
00259   memcpy(ua,u,sizeof(ua));
00260 }
00261 
00262 bool cCardSeca::MatchEMM(const unsigned char *data)
00263 {
00264   return TID(data)==0x82 &&
00265          !memcmp(UA(data),ua,sizeof(ua));
00266 }
00267 
00268 // -- cParseSeca ---------------------------------------------------------------
00269 
00270 int cParseSeca::CmdLen(const unsigned char *data)
00271 {
00272   struct SecaCmd *s=(struct SecaCmd *)data;
00273   return ((s->cmdLen1&0x0f)<<8) | s->cmdLen2;
00274 }
00275 
00276 int cParseSeca::Payload(const unsigned char *data, const unsigned char **payload)
00277 {
00278   int l;
00279   switch(TID(data)) {
00280     case 0x80:
00281     case 0x81: l=sizeof(struct SecaEcm); break;
00282     case 0x82: l=sizeof(struct SecaEmmUnique); break;
00283     case 0x84: l=sizeof(struct SecaEmmShared); break;
00284     default: return -1;
00285     }
00286   if(payload) *payload=&data[l];
00287   return CmdLen(data)-l+sizeof(struct SecaCmd);
00288 }
00289 
00290 int cParseSeca::SysMode(const unsigned char *data)
00291 {
00292   switch(TID(data)) {
00293     case 0x80:
00294     case 0x81: return ((struct SecaEcm *)data)->sm; break;
00295     case 0x82: return ((struct SecaEmmUnique *)data)->sm; break;
00296     case 0x84: return ((struct SecaEmmShared *)data)->sm; break;
00297     default: return -1;
00298     }
00299 }
00300 
00301 int cParseSeca::KeyNr(const unsigned char *data)
00302 {
00303   switch(TID(data)) {
00304     case 0x80:
00305     case 0x81: return ((struct SecaEcm *)data)->keyNr; break;
00306     case 0x82: return ((struct SecaEmmUnique *)data)->keyNr; break;
00307     case 0x84: return ((struct SecaEmmShared *)data)->keyNr; break;
00308     default: return -1;
00309     }
00310 }
00311 
00312 const unsigned char *cParseSeca::ProvIdPtr(const unsigned char *data)
00313 {
00314   switch(TID(data)) {
00315     case 0x80:
00316     case 0x81: return ((struct SecaEcm *)data)->id;
00317     case 0x82: return ((struct SecaEmmUnique *)data)->id;
00318     case 0x84: return ((struct SecaEmmShared *)data)->id;
00319     }
00320   return 0;
00321 }
00322 
00323 int cParseSeca::ProvId(const unsigned char *data)
00324 {
00325   const unsigned char *id=cParseSeca::ProvIdPtr(data);
00326   return id ? (id[0]<<8)+id[1] : -1;
00327 }
00328 
00329 // -- cProviderViaccess --------------------------------------------------------
00330 
00331 cProviderViaccess::cProviderViaccess(void)
00332 {
00333   sharedEmm=0; sharedLen=sharedToggle=0;
00334 }
00335 
00336 cProviderViaccess::cProviderViaccess(const unsigned char *id, const unsigned char *s)
00337 {
00338   sharedEmm=0; sharedLen=sharedToggle=0;
00339   memcpy(ident,id,sizeof(ident));
00340   ident[2]&=0xf0;
00341   memcpy(sa,s,sizeof(sa));
00342 }
00343 
00344 cProviderViaccess::~cProviderViaccess()
00345 {
00346   free(sharedEmm);
00347 }
00348 
00349 bool cProviderViaccess::MatchID(const unsigned char *data)
00350 {
00351   const unsigned char *id=cParseViaccess::ProvIdPtr(data);
00352   return id && id[0]==ident[0] && id[1]==ident[1] && (id[2]&0xf0)==ident[2];
00353 }
00354 
00355 bool cProviderViaccess::MatchEMM(const unsigned char *data)
00356 {
00357   switch(data[0]) {
00358     case 0x8e: 
00359       if(memcmp(&data[3],sa,sizeof(sa)-1)) break;
00360       if((data[6]&2)==0)
00361         return sharedEmm && MatchID(sharedEmm);
00362       // fall through
00363     case 0x8c:
00364     case 0x8d:
00365       return MatchID(data);
00366     }
00367   return false;
00368 }
00369 
00370 unsigned long long cProviderViaccess::ProvId(void)
00371 {
00372   return (ident[0]<<16)+(ident[1]<<8)+ident[2];
00373 }
00374 
00375 int cProviderViaccess::UpdateType(const unsigned char *data)
00376 {
00377   switch(data[0]) {
00378     case 0x8e: return 2; // shared
00379     case 0x8c:
00380     case 0x8d:
00381     default:   return 0; // global
00382     }
00383 }
00384 
00385 int cProviderViaccess::Assemble(cAssembleData *ad)
00386 {
00387   const unsigned char *data=ad->Data();
00388   int len=SCT_LEN(data);
00389   switch(data[0]) {
00390     case 0x8C:
00391     case 0x8D:
00392       if(data[0]!=sharedToggle) {
00393         free(sharedEmm);
00394         sharedLen=len;
00395         sharedEmm=(unsigned char *)malloc(len);
00396         if(sharedEmm) memcpy(sharedEmm,data,sharedLen);
00397         sharedToggle=data[0];
00398         }
00399       break;
00400 
00401     case 0x8E:
00402       if(sharedEmm) {
00403         unsigned char *tmp=AUTOMEM(len+sharedLen);
00404         unsigned char *ass=(unsigned char *)cParseViaccess::NanoStart(data);
00405         len-=(ass-data);
00406         if((data[6]&2)==0) {
00407           const int addrlen=len-8;
00408           len=0;
00409           tmp[len++]=0x9e;
00410           tmp[len++]=addrlen;
00411           memcpy(&tmp[len],&ass[0],addrlen); len+=addrlen;
00412           tmp[len++]=0xf0;
00413           tmp[len++]=0x08;
00414           memcpy(&tmp[len],&ass[addrlen],8); len+=8;
00415           }
00416         else {
00417           memcpy(tmp,ass,len);
00418           }
00419         ass=(unsigned char *)cParseViaccess::NanoStart(sharedEmm);
00420         int l=sharedLen-(ass-sharedEmm);
00421         memcpy(&tmp[len],ass,l); len+=l;
00422 
00423         ass=(unsigned char *)malloc(len+7);
00424         if(ass) {
00425           memcpy(ass,data,7);
00426           SortNanos(ass+7,tmp,len);
00427           SetSctLen(ass,len+4);
00428           ad->SetAssembled(ass);
00429           return 1; // assembled
00430           }
00431         }
00432       break;
00433     }
00434   return -1; // ignore
00435 }
00436 
00437 // -- cCardViaccess ------------------------------------------------------------
00438 
00439 cCardViaccess::cCardViaccess(const unsigned char *u)
00440 {
00441   memcpy(ua,u,sizeof(ua));
00442 }
00443 
00444 bool cCardViaccess::MatchEMM(const unsigned char *data)
00445 {
00446   return data[0]==0x88 && !memcmp(&data[3],ua,sizeof(ua));
00447 }
00448 
00449 // -- cParseViaccess -----------------------------------------------------------
00450 
00451 const unsigned char *cParseViaccess::PayloadStart(const unsigned char *data)
00452 {
00453   switch(data[0]) {
00454     case 0x88: return &data[8];
00455     case 0x8e: return &data[7];
00456     case 0x8c:
00457     case 0x8d: return &data[3];
00458     case 0x80:
00459     case 0x81: return &data[4];
00460     }
00461   return 0;
00462 }
00463 
00464 const unsigned char *cParseViaccess::NanoStart(const unsigned char *data)
00465 {
00466   const unsigned char *p=PayloadStart(data);
00467   switch(data[0]) {
00468     case 0x80:
00469     case 0x81: if(p && p[0]==0xD2) return p+p[1]+2; // skip TPS
00470     }
00471   return p;
00472 }
00473 
00474 const unsigned char *cParseViaccess::CheckNano90(const unsigned char *data)
00475 {
00476   return CheckNano90FromNano(NanoStart(data));
00477 }
00478 
00479 const unsigned char *cParseViaccess::CheckNano90FromNano(const unsigned char *data)
00480 {
00481   if(data && (data[0]==0x90 || data[0]==0x40) && data[1]==0x03) return data;
00482   return 0;
00483 }
00484 
00485 int cParseViaccess::KeyNr(const unsigned char *data)
00486 {
00487   return KeyNrFromNano(CheckNano90(data));
00488 }
00489 
00490 int cParseViaccess::KeyNrFromNano(const unsigned char *data)
00491 {
00492   return data ? data[4]&0x0f : -1;
00493 }
00494 
00495 const unsigned char *cParseViaccess::ProvIdPtr(const unsigned char *data)
00496 {
00497   data=CheckNano90(data);
00498   return data ? &data[2] : 0;
00499 }
00500 
00501 int cParseViaccess::ProvId(const unsigned char *data)
00502 {
00503   const unsigned char *id=cParseViaccess::ProvIdPtr(data);
00504   return id ? (id[0]<<16)+(id[1]<<8)+(id[2]&0xf0) : -1;
00505 }
00506 
00507 // -- cCardNagra2 --------------------------------------------------------------
00508 
00509 cCardNagra2::cCardNagra2(const unsigned char *a)
00510 {
00511   addr[0]=a[2];
00512   addr[1]=a[1];
00513   addr[2]=a[0];
00514   addr[3]=a[3];
00515 }
00516 
00517 bool cCardNagra2::MatchEMM(const unsigned char *data)
00518 {
00519   return data[0]==0x82 ||
00520         (data[0]==0x84 && data[1]==0x70 && data[2]==0x96) ||
00521         (data[0]==0x83 && !memcmp(&data[3],addr,(data[7]==0x10)?3:4));
00522 }
00523 
00524 int cCardNagra2::UpdateType(const unsigned char *data)
00525 {
00526   if(data[0]==0x83) return (data[7]==0x10) ? 2:3;
00527   return 0;
00528 }
00529 
00530 // -- cProviderConax -----------------------------------------------------------
00531 
00532 cProviderConax::cProviderConax(const unsigned char *a)
00533 {
00534   memcpy(addr,a,sizeof(addr));
00535 }
00536 
00537 bool cProviderConax::MatchID(const unsigned char *data)
00538 {
00539   return MatchEMM(data);
00540 }
00541 
00542 bool cProviderConax::MatchEMM(const unsigned char *data)
00543 {
00544   return !memcmp(&data[3],addr,sizeof(addr));
00545 }
00546 
00547 unsigned long long cProviderConax::ProvId(void)
00548 {
00549   return Bin2LongLong(addr,sizeof(addr));
00550 }
00551 
00552 // -- cCardConax ---------------------------------------------------------------
00553 
00554 cCardConax::cCardConax(const unsigned char *a)
00555 {
00556   memcpy(addr,a,sizeof(addr));
00557 }
00558 
00559 bool cCardConax::MatchEMM(const unsigned char *data)
00560 {
00561   return !memcmp(&data[3],addr,sizeof(addr));
00562 }
00563 
00564 // -- cProviderCryptoworks -----------------------------------------------------
00565 
00566 cProviderCryptoworks::cProviderCryptoworks(const unsigned char *a)
00567 {
00568   memcpy(addr,a,sizeof(addr));
00569 }
00570 
00571 bool cProviderCryptoworks::MatchID(const unsigned char *data)
00572 {
00573   return MatchEMM(data);
00574 }
00575 
00576 bool cProviderCryptoworks::MatchEMM(const unsigned char *data)
00577 {
00578   return false;
00579 }
00580 
00581 unsigned long long cProviderCryptoworks::ProvId(void)
00582 {
00583   return Bin2LongLong(addr,sizeof(addr));
00584 }
00585 
00586 // -- cCardCryptoworks----------------------------------------------------------
00587 
00588 cCardCryptoworks::cCardCryptoworks(const unsigned char *a)
00589 {
00590   memcpy(addr,a,sizeof(addr));
00591   sharedEmm=0; sharedLen=globalToggle=0; globalCrc=0;
00592 }
00593 
00594 cCardCryptoworks::~cCardCryptoworks()
00595 {
00596   free(sharedEmm);
00597 }
00598 
00599 bool cCardCryptoworks::MatchEMM(const unsigned char *data)
00600 {
00601   if((data[1]&0xF0)==0x70 && data[3]==0xA9 && data[4]==0xff) {
00602     switch(data[0]) {
00603       case 0x82: return !memcmp(&data[5],addr,sizeof(addr));
00604       case 0x84: return !memcmp(&data[5],addr,sizeof(addr)-1);
00605       case 0x86:
00606       case 0x88:
00607       case 0x89: return true;
00608       }
00609     }
00610   return false;
00611 }
00612 
00613 int cCardCryptoworks::UpdateType(const unsigned char *data)
00614 {
00615   switch(data[0]) {
00616     case 0x82: return 3; // unique
00617     case 0x84:
00618     case 0x86: return 2; // shared
00619     default:   return 0; // global
00620     }
00621 }
00622 
00623 int cCardCryptoworks::Assemble(cAssembleData *ad)
00624 {
00625   const unsigned char *data=ad->Data();
00626   int len=SCT_LEN(data);
00627   switch(data[0]) {
00628     case 0x82:
00629       return 0; // no assemble needed
00630 
00631     case 0x84:
00632       free(sharedEmm);
00633       sharedEmm=(unsigned char *)malloc(len);
00634       if(sharedEmm) {
00635         memcpy(sharedEmm,data,len);
00636         sharedLen=len;
00637         }
00638       break;
00639 
00640     case 0x86:
00641       if(sharedEmm) {
00642         int alen=len-5 + sharedLen-12;
00643         unsigned char *tmp=AUTOMEM(alen);
00644         memcpy(tmp,&data[5],len-5);
00645         memcpy(tmp+len-5,&sharedEmm[12],sharedLen-12);
00646 
00647         unsigned char *ass=(unsigned char *)malloc(alen+12);
00648         if(!ass) return -1; // ignore
00649         memcpy(ass,sharedEmm,12);
00650         SortNanos(ass+12,tmp,alen);
00651         SetSctLen(ass,alen+9);
00652         free(sharedEmm); sharedEmm=0;
00653         if(ass[11]==alen) { // sanity check
00654           ad->SetAssembled(ass);
00655           return 1; // assembled
00656           }
00657         }
00658       break;
00659 
00660     case 0x88:
00661     case 0x89:
00662       if(data[0]!=globalToggle) {
00663         globalToggle=data[0];
00664         unsigned int crc=crc32_le(0,data+1,len-1);
00665         if(crc!=globalCrc) {
00666           globalCrc=crc;
00667           return 0; // no assemble needed
00668           }
00669         }
00670       break;
00671     }
00672   return -1; // ignore
00673 }
00674 
00675 // -- cProviderNDS -------------------------------------------------------------
00676 
00677 cProviderNDS::cProviderNDS(const unsigned char *s)
00678 {
00679   memcpy(sa,s,sizeof(sa));
00680 }
00681 
00682 bool cProviderNDS::MatchID(const unsigned char *data)
00683 {
00684   return MatchEMM(data);
00685 }
00686 
00687 bool cProviderNDS::MatchEMM(const unsigned char *data)
00688 {
00689   return cParseNDS::HasAddr(data,sa);
00690 }
00691 
00692 unsigned long long cProviderNDS::ProvId(void)
00693 {
00694   return Bin2LongLong(sa,sizeof(sa));
00695 }
00696 
00697 int cProviderNDS::Assemble(cAssembleData *ad)
00698 {
00699   return cParseNDS::Assemble(ad,sa);
00700 }
00701 
00702 // -- cCardNDS -----------------------------------------------------------------
00703 
00704 cCardNDS::cCardNDS(const unsigned char *u)
00705 {
00706   memcpy(ua,u,sizeof(ua));
00707 }
00708 
00709 bool cCardNDS::MatchEMM(const unsigned char *data)
00710 {
00711   return cParseNDS::HasAddr(data,ua);
00712 }
00713 
00714 int cCardNDS::Assemble(cAssembleData *ad)
00715 {
00716   return cParseNDS::Assemble(ad,ua);
00717 }
00718 
00719 // -- cParseNDS ----------------------------------------------------------------
00720 
00721 unsigned int cParseNDS::NumAddr(const unsigned char *data)
00722 {
00723   return ((data[3]&0x30)>>4)+1;
00724 }
00725 
00726 int cParseNDS::AddrMode(const unsigned char *data)
00727 {
00728   switch(data[3]&0xC0) {
00729     case 0x40: return 3;
00730     case 0x80: return 2;
00731     default:   return 0;
00732     }
00733 }
00734 
00735 bool cParseNDS::HasAddr(const unsigned char *data, const unsigned char *a)
00736 {
00737   int s;
00738   switch(AddrMode(data)) {
00739     case 2: s=3; break;
00740     case 3: s=4; break;
00741     default: return true;
00742     }
00743   for(int l=NumAddr(data)-1; l>=0; l--) {
00744     if(!memcmp(&data[l*4+4],a,s)) return true;
00745     }
00746   return false;
00747 }
00748 
00749 const unsigned char *cParseNDS::PayloadStart(const unsigned char *data, const unsigned char *a)
00750 {
00751   if(AddrMode(data)==0) return &data[4];
00752   else {
00753     int l;
00754     for(l=NumAddr(data)-1; l>=0; l--) {
00755       if(!memcmp(&data[l*4+4],a,AddrMode(data)+1)) break;
00756       }
00757     const unsigned char *pl;
00758     pl=&data[4+NumAddr(data)*4];  // skip address list
00759     if(*pl!=0x02 && *pl!=0x07) {
00760       pl+=2;                      // skip 00 00 separator
00761       pl++;                       // skip the 1st bitmap len
00762       }
00763     while(l--) {
00764       pl+=2+pl[1];                // skip IRD-EMM part, 02 00 or 02 06 xx aabbccdd yy
00765       pl+=1+*pl;                  // skip sub-EMM payload
00766       if (*pl == 0x00) pl++;      // skip sub-EMM separator
00767       pl++;                       // skip the 1st bitmap len
00768       }
00769     return pl;
00770     }
00771 }
00772 
00773 int cParseNDS::PayloadSize(const unsigned char *data, const unsigned char *a)
00774 {
00775   int l=SCT_LEN(data);
00776   if(AddrMode(data)==0) return l-(4);
00777   else {
00778     const unsigned char *pl=cParseNDS::PayloadStart(data,a); //points to 02 xx yy
00779     pl+=2+pl[1];
00780     return *pl;
00781     }
00782 }
00783 
00784 int cParseNDS::Assemble(cAssembleData *ad, const unsigned char *a)
00785 {
00786   const unsigned char *data=ad->Data();
00787   int len=cParseNDS::PayloadSize(data,a);
00788   const unsigned char *pl=cParseNDS::PayloadStart(data,a);
00789   switch(cParseNDS::AddrMode(data)) {
00790     case 0:
00791      {
00792      int n=*(pl-1) & 0x01;
00793      for(int i=cParseNDS::NumAddr(data); i>0 && len>0; i--) {
00794        int l;
00795        if(n) { 
00796          l=(((*pl & 0x3F)<<8) + *(pl+1)) << 1;
00797          pl+=2; len-=2;
00798          }
00799        else {
00800          l=(*pl & 0x3F) << 1;
00801          pl++; len--;
00802          }
00803        if(l>0 && l<=len) {
00804          unsigned char *ass=(unsigned char *)malloc(len+4); if(!ass) return -1; // ignore
00805          ass[0]=data[0];
00806          ass[3]=data[3]&0x0F;
00807          memcpy(&ass[4],pl,l);
00808          SetSctLen(ass,l+1);
00809          ad->SetAssembled(ass);
00810          pl+=l; len-=l;
00811          }
00812        }
00813      return 1; // assembled
00814      }
00815 
00816     case 2:
00817     case 3:
00818       {
00819       unsigned char *ass=(unsigned char *)malloc(len+3+8); if(!ass) return -1; // ignore
00820       ass[0]=data[0];
00821       ass[3]=data[3]&0xCF;
00822       memcpy(&ass[4],a,4);
00823       memcpy(&ass[8],pl,len+3);
00824       SetSctLen(ass,len+3+5);
00825       ad->SetAssembled(ass);
00826       return 1; // assembled
00827       }
00828     }
00829   return -1; // ignore
00830 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines