|
SASC
DVBSoftCAM
|
00001 /* Compile as follows: 00002 * gcc -O -fbuiltin -fomit-frame-pointer -fPIC -shared -o ca.so ca.c -ldl 00003 * 00004 * run cccam with: 00005 * LD_PRELOAD=./ca.so ./xxx.i386 00006 * 00007 * Will then send CWs to vdr-sc cardclient cccam 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Library General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Library General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Library General Public 00020 * License along with this library; if not, write to the 00021 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00022 * Boston, MA 02111-1307, USA. 00023 */ 00024 00025 //#define DEBUG 00026 00027 #if defined(__GNUC__) && !defined(__STRICT_ANSI__) 00028 00029 #include <dlfcn.h> 00030 #include <stdarg.h> 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #include <unistd.h> 00034 #include <fcntl.h> 00035 #include <sys/types.h> 00036 #include <sys/stat.h> 00037 #include <linux/dvb/ca.h> 00038 #include <linux/dvb/dmx.h> 00039 #include <linux/dvb/frontend.h> 00040 #include <linux/ioctl.h> 00041 #include <stdio.h> 00042 #include <time.h> 00043 #include <sys/socket.h> 00044 #include <netinet/in.h> 00045 #include <arpa/inet.h> 00046 #include <sys/un.h> 00047 #include <syslog.h> 00048 #include <errno.h> 00049 00050 #if defined(RTLD_NEXT) 00051 #define REAL_LIBC RTLD_NEXT 00052 #else 00053 #define REAL_LIBC ((void *) -1L) 00054 #endif 00055 00056 #define PORT 9000 00057 #define MAX_CA 4 00058 00059 static int cafd[MAX_CA] = {-1,-1,-1,-1}; 00060 static int cafdc[MAX_CA] = {0,0,0,0}; 00061 00062 #define MAX_INDEX 64 00063 #define KEY_SIZE 8 00064 #define INFO_SIZE (2+KEY_SIZE+KEY_SIZE) 00065 #define EVEN_OFF (2) 00066 #define ODD_OFF (2+KEY_SIZE) 00067 00068 static unsigned char ca_info[MAX_CA][MAX_INDEX][INFO_SIZE]; 00069 00070 #define CA_BASE "/dev/dvb/adapter0/ca" 00071 #define DEMUX_BASE "/dev/dvb/adapter0/demux" 00072 #define DEMUX_MAP "/dev/dvb/adapter%d/demux0" 00073 #define CPUINFO_BASE "/proc/cpuinfo" 00074 #define CPUINFO_MAP "/tmp/cpuinfo" 00075 00076 //#define DBG(x...) {syslog(LOG_INFO, x);} 00077 #define DBG(x...) 00078 #define INF(x...) {syslog(LOG_INFO, x);} 00079 #define ERR(x...) {syslog(LOG_ERR, x);} 00080 00081 int proginfo=0; 00082 #define PROGINFO() {if(!proginfo){syslog(LOG_INFO,"ca.so for cccam V1.09");proginfo=1;}} 00083 00084 int sendcw(int fd, unsigned char *buff) { 00085 DBG(">>>>>>>> sendcw %02x%02x %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5], buff[6], buff[7], buff[8], buff[9], buff[10], buff[11], buff[12], buff[13], buff[14], buff[15], buff[16], buff[17], buff[18]); 00086 if ( send(fd,buff, 18, 0) == -1 ) { 00087 ERR("ca.so: Send cw failed %d", errno); 00088 return 0; 00089 } // if 00090 return 1; 00091 } // sendcw 00092 00093 static int cactl (int fd, int cai, int request, void *argp) { 00094 ca_descr_t *ca = (ca_descr_t *)argp; 00095 ca_pid_t *cpd = (ca_pid_t *)argp; 00096 switch (request) { 00097 case CA_SET_DESCR: 00098 DBG(">>>>>>>> cactl CA_SET_DESCR fd %d cai %d req %d par %d idx %d %02x%02x%02x%02x%02x%02x%02x%02x", fd, cai, request, ca->parity, ca->index, ca->cw[0], ca->cw[1], ca->cw[2], ca->cw[3], ca->cw[4], ca->cw[5], ca->cw[6], ca->cw[7]); 00099 if(ca->parity==0) 00100 memcpy(&ca_info[cai][ca->index][EVEN_OFF],ca->cw,KEY_SIZE); // even key 00101 else if(ca->parity==1) 00102 memcpy(&ca_info[cai][ca->index][ODD_OFF],ca->cw,KEY_SIZE); // odd key 00103 else 00104 ERR("ca.so: Invalid parity %d in CA_SET_DESCR for ca id %d", ca->parity, cai); 00105 sendcw(fd, ca_info[cai][ca->index]); 00106 break; 00107 case CA_SET_PID: 00108 DBG(">>>>>>>> cactl CA_SET_PID fd %d cai %d req %d (%d %04x)", fd, cai, request, cpd->index, cpd->pid); 00109 if (cpd->index >=0 && cpd->index < MAX_INDEX) { 00110 ca_info[cai][cpd->index][0] = (cpd->pid >> 0) & 0xff; 00111 ca_info[cai][cpd->index][1] = (cpd->pid >> 8) & 0xff; 00112 } else if (cpd->index == -1) { 00113 memset(&ca_info[cai], 0, sizeof(ca_info[cai])); 00114 } else 00115 ERR("ca.so: Invalid index %d in CA_SET_PID (%d) for ca id %d", cpd->index, MAX_INDEX, cai); 00116 return 1; 00117 case CA_RESET: 00118 DBG(">>>>>>>> cactl CA_RESET cai %d", cai); 00119 break; 00120 case CA_GET_CAP: 00121 DBG(">>>>>>>> cactl CA_GET_CAP cai %d", cai); 00122 break; 00123 case CA_GET_SLOT_INFO: 00124 DBG(">>>>>>>> cactl CA_GET_SLOT_INFO cai %d", cai); 00125 break; 00126 default: 00127 DBG(">>>>>>>> cactl unhandled req %d cai %d", request, cai); 00128 //errno = EINVAL; 00129 //return -1; 00130 } // switch 00131 return 0; 00132 } // cactl 00133 00134 /* 00135 CPU Model 00136 Brcm4380 V4.2 // DM8000 00137 Brcm7401 V0.0 // DM800 00138 MIPS 4KEc V4.8 // DM7025 00139 */ 00140 00141 static const char *cpuinfo_file = "\ 00142 system type : ATI XILLEON HDTV SUPERTOLL\n\ 00143 processor : 0\n\ 00144 cpu model : Brcm4380 V4.2\n\ 00145 BogoMIPS : 297.98\n\ 00146 wait instruction : yes\n\ 00147 microsecond timers : yes\n\ 00148 tlb_entries : 16\n\ 00149 extra interrupt vector : yes\n\ 00150 hardware watchpoint : yes\n\ 00151 VCED exceptions : not available\n\ 00152 VCEI exceptions : not available\n\ 00153 "; 00154 00155 int write_cpuinfo (void) { 00156 static FILE* (*func) (const char *, const char *) = NULL; 00157 func = (FILE* (*) (const char *, const char *)) dlsym (REAL_LIBC, "fopen"); 00158 FILE* file = func(CPUINFO_MAP, "w"); 00159 00160 00161 if(file == NULL) { 00162 printf("error \"%s\" opening file\n", strerror(errno)); 00163 return -1; 00164 } 00165 int ret = fwrite(cpuinfo_file, strlen(cpuinfo_file), 1, file); 00166 fclose(file); 00167 return 0; 00168 } 00169 00170 FILE *fopen(const char *path, const char *mode){ 00171 static FILE* (*func) (const char *, const char *) = NULL; 00172 write_cpuinfo(); 00173 if (!func) func = (FILE* (*) (const char *, const char *)) dlsym (REAL_LIBC, "fopen"); 00174 if (!strcmp(path, CPUINFO_BASE)) { 00175 INF("ca.so fopen %s mapped to %s", path, CPUINFO_MAP); 00176 return (*func) (CPUINFO_MAP, mode); 00177 } // if 00178 DBG(">>>>>>>> fopen %s", path); 00179 return (*func) (path, mode); 00180 } // fopen 00181 00182 int open (const char *pathname, int flags, ...) { 00183 static int (*func) (const char *, int, mode_t) = NULL; 00184 if (!func) func = (int (*) (const char *, int, mode_t)) dlsym (REAL_LIBC, "open"); 00185 PROGINFO(); 00186 00187 va_list args; 00188 mode_t mode; 00189 00190 va_start (args, flags); 00191 mode = va_arg (args, mode_t); 00192 va_end (args); 00193 00194 if(strstr(pathname, CA_BASE)) { 00195 int cai=pathname[strlen(CA_BASE)]-'0'; 00196 if((cai >= 0) && (cai < MAX_CA)) { 00197 DBG(">>>>>>>> open cafd[%d] flags %d %s (%d)", cai, flags, pathname, cafdc[cai]); 00198 if(cafd[cai]==-1) { 00199 cafd[cai] = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); 00200 if(cafd[cai]==-1) { 00201 ERR("Failed to open socket (%d)", errno); 00202 } else { 00203 struct sockaddr_in saddr; 00204 fcntl(cafd[cai],F_SETFL,O_NONBLOCK); 00205 bzero(&saddr,sizeof(saddr)); 00206 saddr.sin_family = AF_INET; 00207 saddr.sin_port = htons(PORT); 00208 saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 00209 int r = connect(cafd[cai], (struct sockaddr *) &saddr, sizeof(saddr)); 00210 if (r<0) { 00211 ERR("Failed to connect socket (%d)", errno); 00212 close(cafd[cai]); 00213 cafd[cai]=-1; 00214 } // if 00215 } // if 00216 } // if 00217 if(cafd[cai]!=-1) 00218 cafdc[cai]++; 00219 else 00220 cafdc[cai] = 0; 00221 return (cafd[cai]); 00222 } // if 00223 } else if (strstr(pathname, DEMUX_BASE)) { 00224 int cai=pathname[strlen(DEMUX_BASE)]-'0'; 00225 if((cai >= 0) && (cai < MAX_CA)) { 00226 char dest[256]; 00227 sprintf(dest, DEMUX_MAP, cai); 00228 DBG(">>>>>>>> open %s mapped to %s", pathname, dest); 00229 return (*func) (dest, flags, mode); 00230 } // if 00231 } // if 00232 DBG(">>>>>>>> open %s", pathname); 00233 return (*func) (pathname, flags, mode); 00234 } // open 00235 00236 int ioctl (int fd, int request, void *a) { 00237 static int (*func) (int, int, void *) = NULL; 00238 if (!func) func = (int (*) (int, int, void *)) dlsym (REAL_LIBC, "ioctl"); 00239 int i; 00240 for(i=0;i<MAX_CA;i++) 00241 if (fd == cafd[i]) 00242 return cactl (fd, i, request, a); 00243 return (*func) (fd, request, a); 00244 } // ioctl 00245 00246 int close (int fd) { 00247 static int (*func) (int) = NULL; 00248 if (!func) func = (int (*) (int)) dlsym (REAL_LIBC, "close"); 00249 int i; 00250 for(i=0;i<MAX_CA;i++) { 00251 if (fd == cafd[i]) { 00252 DBG(">>>>>>>> close cafd[%d] (%d)", i, cafdc[i]); 00253 if(--cafdc[i]) return 0; 00254 cafd[i] = -1; 00255 } // if 00256 } // for 00257 return (*func) (fd); 00258 } // close 00259 00260 #endif 00261