winscard_msg.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 2001-2004
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  *  Damien Sauveron <damien.sauveron@labri.fr>
00007  *  Ludoic Rousseau <ludovic.rousseau@free.fr>
00008  *
00009  * $Id: winscard_msg.c 2321 2007-01-09 15:30:45Z rousseau $
00010  */
00011 
00021 #include "config.h"
00022 #include <fcntl.h>
00023 #include <unistd.h>
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <sys/socket.h>
00027 #include <sys/time.h>
00028 #include <sys/un.h>
00029 #include <sys/ioctl.h>
00030 #include <errno.h>
00031 #include <stdio.h>
00032 #include <time.h>
00033 #include <string.h>
00034 #ifdef HAVE_SYS_FILIO_H
00035 #include <sys/filio.h>
00036 #endif
00037 
00038 #include "misc.h"
00039 #include "pcsclite.h"
00040 #include "winscard.h"
00041 #include "debug.h"
00042 #include "winscard_msg.h"
00043 #include "sys_generic.h"
00044 
00056 INTERNAL int SHMClientRead(psharedSegmentMsg msgStruct, DWORD dwClientID, int blockamount)
00057 {
00058     return SHMMessageReceive(msgStruct, sizeof(*msgStruct), dwClientID, blockamount);
00059 }
00060 
00074 INTERNAL int SHMClientSetupSession(PDWORD pdwClientID)
00075 {
00076     struct sockaddr_un svc_addr;
00077     int one;
00078     int ret;
00079 
00080     ret = socket(AF_UNIX, SOCK_STREAM, 0);
00081     if (ret < 0)
00082     {
00083         Log2(PCSC_LOG_CRITICAL, "Error: create on client socket: %s",
00084             strerror(errno));
00085         return -1;
00086     }
00087     *pdwClientID = ret;
00088 
00089     svc_addr.sun_family = AF_UNIX;
00090     strncpy(svc_addr.sun_path, PCSCLITE_CSOCK_NAME,
00091         sizeof(svc_addr.sun_path));
00092 
00093     if (connect(*pdwClientID, (struct sockaddr *) &svc_addr,
00094             sizeof(svc_addr.sun_family) + strlen(svc_addr.sun_path) + 1) < 0)
00095     {
00096         Log2(PCSC_LOG_CRITICAL, "Error: connect to client socket: %s",
00097             strerror(errno));
00098         SYS_CloseFile(*pdwClientID);
00099         return -1;
00100     }
00101 
00102     one = 1;
00103     if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
00104     {
00105         Log2(PCSC_LOG_CRITICAL, "Error: cannot set socket nonblocking: %s",
00106             strerror(errno));
00107         SYS_CloseFile(*pdwClientID);
00108         return -1;
00109     }
00110 
00111     return 0;
00112 }
00113 
00121 INTERNAL int SHMClientCloseSession(DWORD dwClientID)
00122 {
00123     SYS_CloseFile(dwClientID);
00124     return 0;
00125 }
00126 
00142 INTERNAL int SHMMessageSend(void *buffer_void, size_t buffer_size,
00143     int filedes, int blockAmount)
00144 {
00145     char *buffer = buffer_void;
00146 
00147     /*
00148      * default is success
00149      */
00150     int retval = 0;
00151     /*
00152      * record the time when we started
00153      */
00154     time_t start = time(0);
00155     /*
00156      * how many bytes remains to be written
00157      */
00158     size_t remaining = buffer_size;
00159 
00160     /*
00161      * repeat until all data is written
00162      */
00163     while (remaining > 0)
00164     {
00165         fd_set write_fd;
00166         struct timeval timeout;
00167         int selret;
00168 
00169         FD_ZERO(&write_fd);
00170         FD_SET(filedes, &write_fd);
00171 
00172         timeout.tv_usec = 0;
00173         if ((timeout.tv_sec = start + blockAmount - time(0)) < 0)
00174         {
00175             /*
00176              * we already timed out
00177              */
00178             retval = -1;
00179             break;
00180         }
00181 
00182         selret = select(filedes + 1, NULL, &write_fd, NULL, &timeout);
00183 
00184         /*
00185          * try to write only when the file descriptor is writable
00186          */
00187         if (selret > 0)
00188         {
00189             int written;
00190 
00191             if (!FD_ISSET(filedes, &write_fd))
00192             {
00193                 /*
00194                  * very strange situation. it should be an assert really
00195                  */
00196                 retval = -1;
00197                 break;
00198             }
00199             written = write(filedes, buffer, remaining);
00200 
00201             if (written > 0)
00202             {
00203                 /*
00204                  * we wrote something
00205                  */
00206                 buffer += written;
00207                 remaining -= written;
00208             } else if (written == 0)
00209             {
00210                 /*
00211                  * peer closed the socket
00212                  */
00213                 retval = -1;
00214                 break;
00215             } else
00216             {
00217                 /*
00218                  * we ignore the signals and socket full situations, all
00219                  * other errors are fatal
00220                  */
00221                 if (errno != EINTR && errno != EAGAIN)
00222                 {
00223                     retval = -1;
00224                     break;
00225                 }
00226             }
00227         } else if (selret == 0)
00228         {
00229             /*
00230              * timeout
00231              */
00232             retval = -1;
00233             break;
00234         } else
00235         {
00236             /*
00237              * ignore signals
00238              */
00239             if (errno != EINTR)
00240             {
00241                 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00242                     strerror(errno));
00243                 retval = -1;
00244                 break;
00245             }
00246         }
00247     }
00248 
00249     return retval;
00250 }
00251 
00267 INTERNAL int SHMMessageReceive(void *buffer_void, size_t buffer_size,
00268     int filedes, int blockAmount)
00269 {
00270     char *buffer = buffer_void;
00271 
00272     /*
00273      * default is success
00274      */
00275     int retval = 0;
00276     /*
00277      * record the time when we started
00278      */
00279     time_t start = time(0);
00280     /*
00281      * how many bytes we must read
00282      */
00283     size_t remaining = buffer_size;
00284 
00285     /*
00286      * repeate until we get the whole message
00287      */
00288     while (remaining > 0)
00289     {
00290         fd_set read_fd;
00291         struct timeval timeout;
00292         int selret;
00293 
00294         FD_ZERO(&read_fd);
00295         FD_SET(filedes, &read_fd);
00296 
00297         timeout.tv_usec = 0;
00298         if ((timeout.tv_sec = start + blockAmount - time(0)) < 0)
00299         {
00300             /*
00301              * we already timed out
00302              */
00303             retval = -1;
00304             break;
00305         }
00306 
00307         selret = select(filedes + 1, &read_fd, NULL, NULL, &timeout);
00308 
00309         /*
00310          * try to read only when socket is readable
00311          */
00312         if (selret > 0)
00313         {
00314             int readed;
00315 
00316             if (!FD_ISSET(filedes, &read_fd))
00317             {
00318                 /*
00319                  * very strange situation. it should be an assert really
00320                  */
00321                 retval = -1;
00322                 break;
00323             }
00324             readed = read(filedes, buffer, remaining);
00325 
00326             if (readed > 0)
00327             {
00328                 /*
00329                  * we got something
00330                  */
00331                 buffer += readed;
00332                 remaining -= readed;
00333             } else if (readed == 0)
00334             {
00335                 /*
00336                  * peer closed the socket
00337                  */
00338                 retval = -1;
00339                 break;
00340             } else
00341             {
00342                 /*
00343                  * we ignore the signals and empty socket situations, all
00344                  * other errors are fatal
00345                  */
00346                 if (errno != EINTR && errno != EAGAIN)
00347                 {
00348                     retval = -1;
00349                     break;
00350                 }
00351             }
00352         } else if (selret == 0)
00353         {
00354             /*
00355              * timeout
00356              */
00357             retval = -1;
00358             break;
00359         } else
00360         {
00361             /*
00362              * we ignore signals, all other errors are fatal
00363              */
00364             if (errno != EINTR)
00365             {
00366                 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00367                     strerror(errno));
00368                 retval = -1;
00369                 break;
00370             }
00371         }
00372     }
00373 
00374     return retval;
00375 }
00376 
00392 INTERNAL int WrapSHMWrite(unsigned int command, DWORD dwClientID,
00393     unsigned int size, unsigned int blockAmount, void *data_void)
00394 {
00395     char *data = data_void;
00396 
00397     sharedSegmentMsg msgStruct;
00398     int ret;
00399 
00400     /*
00401      * Set the appropriate packet parameters
00402      */
00403 
00404     memset(&msgStruct, 0, sizeof(msgStruct));
00405     msgStruct.mtype = CMD_FUNCTION;
00406     msgStruct.user_id = SYS_GetUID();
00407     msgStruct.group_id = SYS_GetGID();
00408     msgStruct.command = command;
00409     msgStruct.date = time(NULL);
00410     if ((SCARD_TRANSMIT_EXTENDED == command)
00411         || (SCARD_CONTROL_EXTENDED == command))
00412     {
00413         /* first block */
00414         memcpy(msgStruct.data, data, PCSCLITE_MAX_MESSAGE_SIZE);
00415         ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00416             blockAmount);
00417         if (ret)
00418             return ret;
00419 
00420         /* do not send an empty second block */
00421         if (size > PCSCLITE_MAX_MESSAGE_SIZE)
00422         {
00423             /* second block */
00424             ret = SHMMessageSend(data+PCSCLITE_MAX_MESSAGE_SIZE,
00425                 size-PCSCLITE_MAX_MESSAGE_SIZE, dwClientID, blockAmount);
00426             if (ret)
00427                 return ret;
00428         }
00429     }
00430     else
00431     {
00432         memcpy(msgStruct.data, data, size);
00433 
00434         ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00435             blockAmount);
00436     }
00437     return ret;
00438 }
00439 
00449 INTERNAL void SHMCleanupSharedSegment(int sockValue, const char *pcFilePath)
00450 {
00451     SYS_CloseFile(sockValue);
00452     SYS_Unlink(pcFilePath);
00453 }
00454 

Generated on Tue Feb 6 21:24:44 2007 for pcsc-lite by  doxygen 1.5.1