|
SASC-NG
DVBSoftCAM
|
00001 #include <stdio.h> 00002 #include <stdlib.h> 00003 #include <dirent.h> 00004 #include <string.h> 00005 #include <unistd.h> 00006 #include <signal.h> 00007 #include <fcntl.h> 00008 00009 #include <sys/stat.h> 00010 #include <sys/socket.h> 00011 #include <sys/un.h> 00012 #include <sys/wait.h> 00013 #include <sys/types.h> 00014 #include <linux/dvb/ca.h> 00015 00016 void _SetCaPid(ca_pid_t * ca_pid); 00017 void _SetCaDescr(ca_descr_t * ca_descr); 00018 void _ForceIndex(int index); 00019 00020 bool is_file(char *path) { 00021 struct stat st; 00022 if (stat(path, &st) != 0) { 00023 return false; 00024 } 00025 return true; 00026 } 00027 00028 /* this function finds all pids that are attached to the unix socket 'origstr'. 00029 It does this by sniffing through /proc, so it is definitely non-portable */ 00030 int find_pid_from_socket(char *origstr) { 00031 int found = 0, pid = 0; 00032 char path[256], buf[512]; 00033 char path1[256], buf1[512]; 00034 DIR *DH, *DH1; 00035 struct dirent *dirent, *dirent1; 00036 DH = opendir("/proc"); 00037 while ((dirent = readdir(DH))) { 00038 if ((pid = strtol(dirent->d_name, NULL, 10)) == 0) { 00039 continue; 00040 } 00041 snprintf(path, 256, "/proc/%s/root", dirent->d_name); 00042 memset(buf, 0, sizeof(buf)); 00043 if (readlink(path, buf, 512) == -1) 00044 continue; 00045 if (strstr(origstr, buf) != origstr) 00046 continue; 00047 snprintf(path, 256, "/proc/%s/fd", dirent->d_name); 00048 DH1 = opendir(path); 00049 if(! DH1) 00050 continue; 00051 if(buf[strlen(buf)-1] == '/') 00052 buf[strlen(buf)-1] = 0; 00053 while ((dirent1 = readdir(DH1))) { 00054 int sock; 00055 memset(buf1, 0, sizeof(buf1)); 00056 snprintf(path1, 256, "%s/%s", path, dirent1->d_name); 00057 if (readlink(path1, buf1, 512) == -1) 00058 continue; 00059 if (strstr(buf1, "socket") != buf1) 00060 continue; 00061 sock = atoi(buf1+8); 00062 if (sock == 0) 00063 continue; 00064 { 00065 FILE *FH; 00066 char buf2[256]; 00067 char *tok; 00068 FH=fopen("/proc/net/unix", "r"); 00069 while (fgets(buf2, 256, FH) ) { 00070 int i; 00071 char delim[] =" \t"; 00072 char *ptr = buf2; 00073 int trysock; 00074 for(i = 0; i < 7; i++) { 00075 tok = strtok(ptr, delim); 00076 if(! tok) 00077 break; 00078 ptr = NULL; 00079 } 00080 if (! tok) 00081 continue; 00082 trysock = atoi(tok); 00083 if (trysock == 0 || sock != trysock) 00084 continue; 00085 tok = strtok(NULL, delim); 00086 if (! tok) 00087 continue; 00088 char newstr[256]; 00089 snprintf(newstr, 256, "%s%s", buf, tok); 00090 if (strncmp(origstr, newstr, strlen(origstr)) == 0) { 00091 found = 1; 00092 break; 00093 } 00094 } 00095 fclose(FH); 00096 break; 00097 } 00098 } 00099 closedir(DH1); 00100 if (found) 00101 break; 00102 } 00103 closedir(DH); 00104 if (found) 00105 return pid; 00106 return 0; 00107 } 00108 00109 bool shutdown_evocamd(int cardnum) { 00110 char path[256], line[256]; 00111 int pid = 0; 00112 snprintf(path, 256, "/tmp/sasc-chroot-%d/tmp/camd.socket", cardnum); 00113 if (is_file(path)) { 00114 while((pid = find_pid_from_socket(path))) { 00115 printf("Killing evocamd at pid %d\n", pid); 00116 kill(pid, SIGTERM); 00117 sleep(1); 00118 } 00119 } 00120 snprintf(path, 256, "/tmp/sasc-chroot-%d", cardnum); 00121 if (is_file(path)) { 00122 snprintf(line, 256, "rm -rf %s", path); 00123 system(line); 00124 } 00125 return true; 00126 } 00127 00128 int send_evocamd(int cardnum, unsigned short servid, unsigned short msg) { 00129 int evocamdSocket; 00130 char sockBuffer[3]; 00131 char sockname[256]; 00132 struct sockaddr_un servaddr; 00133 int clilen; 00134 00135 snprintf(sockname, 256, "/tmp/sasc-chroot-%d/tmp/camd.socket", cardnum); 00136 servaddr.sun_family = AF_UNIX; 00137 strcpy(servaddr.sun_path, sockname); 00138 clilen = sizeof(servaddr.sun_family) + strlen(servaddr.sun_path); 00139 if ((evocamdSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 00140 { 00141 fprintf(stderr, "[Evocamd] socket creation failed\n"); 00142 return 0; 00143 } 00144 if (connect(evocamdSocket, (struct sockaddr*) &servaddr, clilen) < 0) 00145 { 00146 fprintf(stderr, "[Evocamd] socket connection failed\n"); 00147 return 0; 00148 } 00149 sockBuffer[0] = servid >> 8; 00150 sockBuffer[1] = servid & 0xff; 00151 sockBuffer[2] = msg; 00152 //printf("Sending %d/%d to evocamd\n", servid, msg); 00153 if (write(evocamdSocket, sockBuffer, 3) < 0) 00154 { 00155 fprintf(stderr, "[Evocamd] write failed\n"); 00156 return 0; 00157 } 00158 close(evocamdSocket); 00159 return 1; 00160 } 00161 00162 bool init_evocamd(int cardnum, char *scDir) { 00163 char path[512]; 00164 char cmd[512]; 00165 00166 //shutdown any evocamd daemons that are already running 00167 shutdown_evocamd(cardnum); 00168 snprintf(path, 512, "/tmp/sasc-chroot-%d", cardnum); 00169 mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP); 00170 chdir(path); 00171 snprintf(path, 512, "%s/camd.tar.gz", scDir); 00172 if (! is_file(path)) { 00173 fprintf(stderr, "Failed to find camd.tar.gz. Aborting."); 00174 return false; 00175 } 00176 snprintf(cmd, 512, "tar -xvzf %s", path); 00177 if(system(cmd)) { 00178 fprintf(stderr, "Evocamd extract failed\n"); 00179 return false; 00180 } 00181 snprintf(cmd, 512, "sasc-chroot-dvb %d evocamd", cardnum); 00182 if(system(cmd)) { 00183 fprintf(stderr, "Evocamd call failed\n"); 00184 return false; 00185 } 00186 return true; 00187 } 00188 00189 int start_loopbackca(int cardnum) { 00190 char path[256]; 00191 int fd; 00192 00193 snprintf(path, 256, "/proc/ca_emu_%d", cardnum); 00194 00195 fd = open(path, O_RDONLY); 00196 if(fd < 0) { 00197 perror("Failed to open loopback-ca\n"); 00198 return 0; 00199 } 00200 pid_t pid = fork(); 00201 if (pid == 0) // child 00202 { 00203 //ca_emu_* is processed as follows: 00204 // data[0] : number of records to read (<=10) 00205 // data[i*100 + 1] : ioctl command 00206 // &data[i*100 + 2] : data record from ioctl 00207 unsigned char data[1024], *dataptr; 00208 _ForceIndex(1); 00209 while(1) { 00210 int bytes = read(fd, data, 1024); 00211 lseek(fd, SEEK_SET, 0); 00212 //printf("Read %d bytes from ca-loopback (%d cmds)\n", bytes, data[0]); 00213 if (bytes != 1024) { 00214 continue; 00215 } 00216 int count = data[0]; 00217 for (int i=0; i < count; i++) { 00218 unsigned int cmd; 00219 memcpy(&cmd, data+ i*100 + 1, sizeof(cmd)); 00220 //printf("Parsing command: %d\n", cmd); 00221 dataptr = data+ i*100 + 1 + sizeof(cmd); 00222 switch(cmd) { 00223 case 135: //CA_SET_PID 00224 { 00225 ca_pid_t ca_pid; 00226 memcpy(&ca_pid, dataptr, sizeof(ca_pid)); 00227 ca_pid.index = 1; 00228 _SetCaPid(&ca_pid); 00229 break; 00230 } 00231 case 134: //CA_SET_DESCR 00232 { 00233 ca_descr_t ca_descr; 00234 memcpy(&ca_descr, dataptr, sizeof(ca_descr)); 00235 ca_descr.index = 1; 00236 _SetCaDescr(&ca_descr); 00237 break; 00238 } 00239 default: 00240 fprintf(stderr, "CA Loopback unknown command: %d\n", cmd); 00241 break; 00242 } 00243 } 00244 } 00245 close(fd); 00246 exit(0); 00247 } 00248 close(fd); 00249 return(pid); 00250 } 00251