pcsc-lite 1.6.4
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  * Copyright (C) 2003-2004
00007  *  Damien Sauveron <damien.sauveron@labri.fr>
00008  * Copyright (C) 2002-2010
00009  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00010  *
00011  * $Id: winscard_msg_srv.c 4951 2010-05-18 09:35:09Z rousseau $
00012  */
00013 
00023 #include "config.h"
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <sys/socket.h>
00029 #include <sys/time.h>
00030 #include <sys/un.h>
00031 #include <sys/ioctl.h>
00032 #include <errno.h>
00033 #include <stdio.h>
00034 #include <time.h>
00035 #include <string.h>
00036 #ifdef HAVE_SYS_FILIO_H
00037 #include <sys/filio.h>
00038 #endif
00039 
00040 #include "misc.h"
00041 #include "pcscd.h"
00042 #include "winscard.h"
00043 #include "debuglog.h"
00044 #include "winscard_msg.h"
00045 
00049 static int commonSocket = 0;
00050 extern char AraKiri;
00051 
00063 static int ProcessCommonChannelRequest(/*@out@*/ uint32_t *pdwClientID)
00064 {
00065     socklen_t clnt_len;
00066     int new_sock;
00067     struct sockaddr_un clnt_addr;
00068 
00069     clnt_len = sizeof(clnt_addr);
00070 
00071     if ((new_sock = accept(commonSocket, (struct sockaddr *) &clnt_addr,
00072                 &clnt_len)) < 0)
00073     {
00074         Log2(PCSC_LOG_CRITICAL, "Accept on common socket: %s",
00075             strerror(errno));
00076         return -1;
00077     }
00078 
00079     *pdwClientID = new_sock;
00080 
00081     return 0;
00082 }
00083 
00098 INTERNAL int32_t InitializeSocket(void)
00099 {
00100     static struct sockaddr_un serv_adr;
00101 
00102     /*
00103      * Create the common shared connection socket
00104      */
00105     if ((commonSocket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
00106     {
00107         Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
00108             strerror(errno));
00109         return -1;
00110     }
00111 
00112     serv_adr.sun_family = AF_UNIX;
00113     strncpy(serv_adr.sun_path, PCSCLITE_CSOCK_NAME,
00114         sizeof(serv_adr.sun_path));
00115     (void)remove(PCSCLITE_CSOCK_NAME);
00116 
00117     if (bind(commonSocket, (struct sockaddr *) &serv_adr,
00118             sizeof(serv_adr.sun_family) + strlen(serv_adr.sun_path) + 1) < 0)
00119     {
00120         Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
00121             strerror(errno));
00122         CleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
00123         return -1;
00124     }
00125 
00126     if (listen(commonSocket, 1) < 0)
00127     {
00128         Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
00129             strerror(errno));
00130         CleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
00131         return -1;
00132     }
00133 
00134     /*
00135      * Chmod the public entry channel
00136      */
00137     (void)chmod(PCSCLITE_CSOCK_NAME, S_IRWXO | S_IRWXG | S_IRWXU);
00138 
00139     return 0;
00140 }
00141 
00155 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
00156 #define DO_TIMEOUT
00157 #endif
00158 INTERNAL int32_t ProcessEventsServer(uint32_t *pdwClientID)
00159 {
00160     fd_set read_fd;
00161     int selret;
00162 #ifdef DO_TIMEOUT
00163     struct timeval tv;
00164 
00165     tv.tv_sec = 1;
00166     tv.tv_usec = 0;
00167 #endif
00168 
00169     FD_ZERO(&read_fd);
00170 
00171     /*
00172      * Set up the bit masks for select
00173      */
00174     FD_SET(commonSocket, &read_fd);
00175 
00176     selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
00177         (fd_set *) NULL,
00178 #ifdef DO_TIMEOUT
00179         &tv
00180 #else
00181         NULL
00182 #endif
00183         );
00184 
00185     if (selret < 0)
00186     {
00187         if (EINTR == errno)
00188             return -2;
00189 
00190         Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
00191             strerror(errno));
00192         return -1;
00193     }
00194 
00195     if (selret == 0)
00196         /* timeout. On *BSD only */
00197         return 2;
00198 
00199     /*
00200      * A common pipe packet has arrived - it could be a new application
00201      */
00202     if (FD_ISSET(commonSocket, &read_fd))
00203     {
00204         Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
00205         if (ProcessCommonChannelRequest(pdwClientID) == -1)
00206         {
00207             Log2(PCSC_LOG_ERROR,
00208                 "error in ProcessCommonChannelRequest: %d", *pdwClientID);
00209             return -1;
00210         }
00211     }
00212     else
00213         return -1;
00214 
00215     Log2(PCSC_LOG_DEBUG,
00216         "ProcessCommonChannelRequest detects: %d", *pdwClientID);
00217 
00218     return 0;
00219 }
00220