|
SASC
DVBSoftCAM
|
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 }