winscard_msg_srv.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_srv.c 2377 2007-02-05 13:13:56Z 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 "pcscd.h"
00040 #include "winscard.h"
00041 #include "debuglog.h"
00042 #include "winscard_msg.h"
00043 #include "sys_generic.h"
00044 
00048 static int commonSocket = 0;
00049 extern char AraKiri;
00050 extern char ReCheckSerialReaders;
00051 
00064 static int SHMProcessCommonChannelRequest(PDWORD pdwClientID)
00065 {
00066     socklen_t clnt_len;
00067     int new_sock;
00068     struct sockaddr_un clnt_addr;
00069     int one;
00070 
00071     clnt_len = sizeof(clnt_addr);
00072 
00073     if ((new_sock = accept(commonSocket, (struct sockaddr *) &clnt_addr,
00074                 &clnt_len)) < 0)
00075     {
00076         Log2(PCSC_LOG_CRITICAL, "Accept on common socket: %s",
00077             strerror(errno));
00078         return -1;
00079     }
00080 
00081     *pdwClientID = new_sock;
00082 
00083     one = 1;
00084     if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
00085     {
00086         Log2(PCSC_LOG_CRITICAL, "Error: cannot set socket nonblocking: %s",
00087             strerror(errno));
00088         SYS_CloseFile(*pdwClientID);
00089         *pdwClientID = -1;
00090         return -1;
00091     }
00092 
00093     return 0;
00094 }
00095 
00110 INTERNAL int SHMInitializeCommonSegment(void)
00111 {
00112     static struct sockaddr_un serv_adr;
00113 
00114     /*
00115      * Create the common shared connection socket
00116      */
00117     if ((commonSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
00118     {
00119         Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
00120             strerror(errno));
00121         return -1;
00122     }
00123 
00124     serv_adr.sun_family = AF_UNIX;
00125     strncpy(serv_adr.sun_path, PCSCLITE_CSOCK_NAME,
00126         sizeof(serv_adr.sun_path));
00127     SYS_Unlink(PCSCLITE_CSOCK_NAME);
00128 
00129     if (bind(commonSocket, (struct sockaddr *) &serv_adr,
00130             sizeof(serv_adr.sun_family) + strlen(serv_adr.sun_path) + 1) < 0)
00131     {
00132         Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
00133             strerror(errno));
00134         SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
00135         return -1;
00136     }
00137 
00138     if (listen(commonSocket, 1) < 0)
00139     {
00140         Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
00141             strerror(errno));
00142         SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
00143         return -1;
00144     }
00145 
00146     /*
00147      * Chmod the public entry channel
00148      */
00149     SYS_Chmod(PCSCLITE_CSOCK_NAME, S_IRWXO | S_IRWXG | S_IRWXU);
00150 
00151     return 0;
00152 }
00153 
00168 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
00169 #define DO_TIMEOUT
00170 #endif
00171 INTERNAL int SHMProcessEventsServer(PDWORD pdwClientID, int blocktime)
00172 {
00173     fd_set read_fd;
00174     int selret;
00175 #ifdef DO_TIMEOUT
00176     struct timeval tv;
00177         
00178     tv.tv_sec = 1;
00179     tv.tv_usec = 0;
00180 #endif
00181 
00182     FD_ZERO(&read_fd);
00183 
00184     /*
00185      * Set up the bit masks for select
00186      */
00187     FD_SET(commonSocket, &read_fd);
00188 
00189     selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
00190         (fd_set *) NULL,
00191 #ifdef DO_TIMEOUT
00192         &tv
00193 #else
00194         NULL
00195 #endif
00196         );
00197 
00198     if (selret < 0)
00199     {
00200         if (EINTR == errno)
00201             return -2;
00202 
00203         Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
00204             strerror(errno));
00205         return -1;
00206     }
00207 
00208     if (selret == 0)
00209         /* timeout. On *BSD only */
00210         return 2;
00211 
00212     /*
00213      * A common pipe packet has arrived - it could be a new application
00214      */
00215     if (FD_ISSET(commonSocket, &read_fd))
00216     {
00217         Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
00218         if (SHMProcessCommonChannelRequest(pdwClientID) == -1)
00219         {
00220             Log2(PCSC_LOG_ERROR,
00221                 "error in SHMProcessCommonChannelRequest: %d", *pdwClientID);
00222             return -1;
00223         } else
00224         {
00225             Log2(PCSC_LOG_DEBUG,
00226                 "SHMProcessCommonChannelRequest detects: %d", *pdwClientID);
00227             return 0;
00228         }
00229     }
00230 
00231     return -1;
00232 }
00233 
00239 INTERNAL int SHMProcessEventsContext(PDWORD pdwClientID, psharedSegmentMsg msgStruct, int blocktime)
00240 {
00241     fd_set read_fd;
00242     int selret, rv;
00243     struct timeval tv;
00244 
00245     tv.tv_sec = 1;
00246     tv.tv_usec = 0;
00247 
00248     FD_ZERO(&read_fd);
00249     FD_SET(*pdwClientID, &read_fd);
00250 
00251     selret = select(*pdwClientID + 1, &read_fd, (fd_set *) NULL,
00252         (fd_set *) NULL, &tv);
00253 
00254     if (selret < 0)
00255     {
00256         Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00257             strerror(errno));
00258         return -1;
00259     }
00260 
00261     if (selret == 0)
00262         /* timeout */
00263         return 2;
00264 
00265     if (FD_ISSET(*pdwClientID, &read_fd))
00266     {
00267         /*
00268          * Return the current handle
00269          */
00270         rv = SHMMessageReceive(msgStruct, sizeof(*msgStruct), *pdwClientID,
00271                        PCSCLITE_SERVER_ATTEMPTS);
00272 
00273         if (rv == -1)
00274         {   /* The client has died */
00275             Log2(PCSC_LOG_DEBUG, "Client has disappeared: %d",
00276                 *pdwClientID);
00277             msgStruct->mtype = CMD_CLIENT_DIED;
00278             msgStruct->command = 0;
00279             SYS_CloseFile(*pdwClientID);
00280 
00281             return 0;
00282         }
00283 
00284         /*
00285          * Set the identifier handle
00286          */
00287         Log2(PCSC_LOG_DEBUG, "correctly processed client: %d",
00288             *pdwClientID);
00289         return 1;
00290     }
00291 
00292     return -1;
00293 }
00294 

Generated on Thu Feb 21 01:47:31 2008 for pcsc-lite by  doxygen 1.5.5