SASC
DVBSoftCAM

othercamd.cpp

Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines