/* Perform a GETATTR operation. */ gpg_error_t app_getattr (app_t app, ctrl_t ctrl, const char *name) { gpg_error_t err; if (!app || !name || !*name) return gpg_error (GPG_ERR_INV_VALUE); if (!app->ref_count) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (app->apptype && name && !strcmp (name, "APPTYPE")) { send_status_info (ctrl, "APPTYPE", app->apptype, strlen (app->apptype), NULL, 0); return 0; } if (name && !strcmp (name, "SERIALNO")) { char *serial; time_t stamp; int rc; rc = app_get_serial_and_stamp (app, &serial, &stamp); if (rc) return rc; send_status_info (ctrl, "SERIALNO", serial, strlen (serial), NULL, 0); xfree (serial); return 0; } if (!app->fnc.getattr) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_reader (app->slot, ctrl); if (err) return err; err = app->fnc.getattr (app, ctrl, name); unlock_reader (app->slot); return err; }
/* Write out the application specifig status lines for the LEARN command. */ gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { gpg_error_t err; if (!app) return gpg_error (GPG_ERR_INV_VALUE); if (!app->ref_count) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.learn_status) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); /* We do not send APPTYPE if only keypairinfo is requested. */ if (app->apptype && !(flags & 1)) send_status_info (ctrl, "APPTYPE", app->apptype, strlen (app->apptype), NULL, 0); err = lock_reader (app->slot, ctrl); if (err) return err; err = app->fnc.learn_status (app, ctrl, flags); unlock_reader (app->slot); return err; }
int loop_socket_handle(int socket, int tt_ms) { unsigned char outhexbuf[ONE_TCP_MAX_LEN] = {0}; PRO *pro = (PRO*)malloc(sizeof(PRO)); memset(pro, 0, sizeof(PRO)); pro->payload = (unsigned char*)malloc(ONLINE_MAX_LEN); memset(pro->payload, 0, (ONLINE_MAX_LEN)); int ret = 0; int login_ok = 0; unsigned int sendseq = 0; int outinx = 0; int hexlen = 0; MACH_STAT stat = IDLE; while(1) { debug(LOG_NOTICE, "stat=%d,login_flag=%d,outinx=%d,last_cmd=%04x,last_recv_ret=%d,dev_work_status=%d\n", stat,login_ok,outinx,pro->hd.cmd,ret,dev_work_status); switch(stat) { case IDLE: //sleep_intp_s(5); //will block tcp recving break; case TO_LOGIN: memset(&pro->hd, 0, sizeof(PRO_HD)); memset(pro->payload, 0, (ONLINE_MAX_LEN)); send_login_info(socket, pro, sendseq++); break; case TO_DEVSTATUS: //recv_uart(); //send_dev_data(); if(glb_cfg.glb_sock != socket) glb_cfg.glb_sock = socket; // uart thread will write glb_sock directly. break; case TO_WORKSTATUS: memset(pro->payload, 0, (ONLINE_MAX_LEN)); if(dev_work_status == E_DEV_TAKEUP) { send_busy_info(socket, pro, dev_work_status, sendseq++); } else { send_status_info(socket, pro, dev_work_status, sendseq++); } stat = IDLE; break; case TO_RESPSTATUS: memset(pro->payload, 0, (ONLINE_MAX_LEN)); response_status_info(socket, pro, dev_work_status, sendseq++); stat = IDLE; break; case TO_HEART: memset(&pro->hd, 0, sizeof(PRO_HD)); send_heart_info(socket, &pro->hd, sendseq++); if(outinx++ > HEART_EXIT_COUNT) goto EXIT_ERR; else stat = IDLE; break; case TO_RESP: //for testing;all back pro->hd.stat = PRO_RSP; memset(outhexbuf, 0, sizeof(outhexbuf)); hexlen = 0; pro_pro2hexbuf(pro,outhexbuf,&hexlen); send(socket, outhexbuf, hexlen, sendseq++); debug(LOG_DEBUG, "Send Resp Len:%d\n",hexlen); stat = IDLE; break; case NET_DISCONN: goto EXIT_ERR; break; default: break; } //memset(pro, 0, sizeof(PRO)); //NOTE***: will init payload as NULL; this will cause crash!!! memset(&pro->hd, 0, sizeof(PRO_HD)); memset(pro->payload, 0, (ONLINE_MAX_LEN)); ret = socket_recv_tt(socket, pro, tt_ms); if(ret == 0) { // timeout if(!login_ok) { stat = TO_LOGIN; } else { stat = TO_HEART; } } else if(ret < 0) { // socket error goto EXIT_ERR; } else if( (ret != sizeof(PRO_HD)) && (ret != sizeof(PRO_HD)+pro->hd.len) ) { debug(LOG_NOTICE, "Recv Length %d Error!\n",ret); continue; } else { // handle data... switch(pro->hd.cmd) { case IDM_DEV_LOGIN: debug(LOG_NOTICE, "---< server back: login\n"); login_ok = 1; if(dev_work_status != E_DEV_TAKEUP) dev_work_status = E_DEV_ONLINE; stat = TO_DEVSTATUS; break; case IDM_DEV_HEART: debug(LOG_NOTICE, "---< server back: heart\n"); outinx = 0; break; case IDM_GETDEV: debug(LOG_NOTICE, "---< server cmd: get dev\n"); stat = TO_RESPSTATUS; break; /* for response testing */ case 0xfffe: debug(LOG_NOTICE, "---< server cmd: test response\n"); stat = TO_RESP; break; case IDM_TAKEUPDEV: case IDM_RELEASEDEV: case IDM_RESET: case IDM_DOSTART: case IDM_DOSTOP: case IDM_SETPARS: case IDM_DELPARS: if(0 == memcmp(taskid, pro->payload+32, 32)) { break; } else { if(dev_work_status == E_DEV_TAKEUP) { debug(LOG_WARNING, "---< server taskid is not correct!\n"); stat = TO_WORKSTATUS; continue; } else { /* Firstly takeup device */ break; } } default: debug(LOG_ERR, "==== Handle: Unknow Server CMD 0x%02x\n", pro->hd.cmd); continue; } switch(pro->hd.cmd) { /* handle at local */ case IDM_TAKEUPDEV: debug(LOG_NOTICE, "---< server cmd: takeup dev\n"); dev_work_status = E_DEV_TAKEUP; stat = TO_WORKSTATUS; memcpy(taskid, pro->payload+32, sizeof(taskid)); /* skip devid 32*/ break; case IDM_RELEASEDEV: debug(LOG_NOTICE, "---< server cmd: release dev\n"); dev_work_status = E_DEV_ONLINE; stat = TO_WORKSTATUS; memset(taskid, 0, sizeof(taskid)); break; /* send to uart */ case IDM_RESET: debug(LOG_NOTICE, "---< server cmd: reset dev\n"); dev_work_status = E_DEV_ONLINE; stat = TO_WORKSTATUS; /* stop and clear */ dev_reset(pro->payload, pro->hd.len); break; case IDM_DOSTART: debug(LOG_NOTICE, "---< server cmd: start dev\n"); glb_cfg.rsp_cmd_type = SVR_NEED_TASK_RET; glb_cfg.rsp_cmd_type |= SVR_NEED_TASK_PERCT; /* only send payload to uart */ ret = dev_start(pro->payload, pro->hd.len); debug(LOG_DEBUG, "---Send To Com ret %d\n",ret); break; case IDM_DOSTOP: debug(LOG_NOTICE, "---< server cmd: stop dev\n"); glb_cfg.rsp_cmd_type = SVR_NEED_TASK_RET; /* only send payload to uart */ ret = dev_stop(pro->payload, pro->hd.len); debug(LOG_DEBUG, "---Send To Com ret %d\n",ret); break; case IDM_SETPARS: debug(LOG_NOTICE, "---< server cmd: set params dev\n"); /* only send params to uart */ ret = dev_setpar(pro->payload+64+2, (pro->hd.len-66)>0?(pro->hd.len-66):0); debug(LOG_DEBUG, "---Send To Com ret %d\n",ret); break; case IDM_DELPARS: debug(LOG_NOTICE, "---< server cmd: del params\n"); /* only send payload to uart */ ret = dev_clrpar(pro->payload, pro->hd.len); debug(LOG_DEBUG, "---Send To Com ret %d\n",ret); break; } } continue; } /* end while(1) */ EXIT_ERR: debug(LOG_NOTICE, "<--- Socket recv out!\n"); glb_cfg.glb_sock = -1; glb_cfg.rsp_cmd_type = 0; if(socket > 0) close(socket); if(pro && pro->payload) { free(pro->payload); free(pro); } return -1; }
gogoc_status tspStartLocal( int socket, tConf *c, tTunnel *t, net_tools_t *nt ) { TUNNEL_LOOP_CONFIG tun_loop_cfg; gogoc_status status = STATUS_SUCCESS_INIT; int ka_interval = 0; int tunfd = -1; //int pid; // Check if we got root privileges. if( geteuid() != 0 ) { // Error: we don't have root privileges. Display( LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_FATAL_NOT_ROOT_FOR_TUN ); return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); } // Check if we're already daemon. Calling multiple times the daemon() messes up pthreads. if( !c->nodaemon && getppid() != 1 ) { // Detach from controlling terminal and run in the background. Display( LOG_LEVEL_3, ELInfo, "tspStartLocal", GOGO_STR_GOING_DAEMON ); if( daemon(1, 0) == -1 ) { // Error: Failed to detach. Display( LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_CANT_FORK ); return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); } } // Check tunnel mode. if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V4V6) == 0 ) { // V4V6 encapsulation (DSTM) not supported on darwin. Display( LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_NO_V4V6_ON_PLATFORM ); return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); } else if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6UDPV4) == 0 ) { // When using V6UDPV4 encapsulation, open the TUN device. tunfd = TunInit(c->if_tunnel_v6udpv4); if( tunfd == -1 ) { // Error: Failed to open TUN device. Display( LOG_LEVEL_1, ELError, "tspStartLocal", STR_MISC_FAIL_TUN_INIT ); return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); } // Get the real name of the opened tun device for the template script. free( c->if_tunnel_v6udpv4 ); c->if_tunnel_v6udpv4 = (char*) malloc( IFNAMSIZ ); TunName( tunfd, c->if_tunnel_v6udpv4, IFNAMSIZ ); } t->originalgateway = routepr(); while( 1 ) // Dummy loop. 'break' instruction at the end. { // Run the config script in another thread, without giving it our tunnel // descriptor. This is important because otherwise the tunnel will stay // open if we get killed. // // pid = fork(); // if( pid < 0 ) // { // fork() error // status = make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); // break; // } // else if( pid == 0 ) // { // Child processing: run template script. // if( tunfd != -1 ) // { // close(tunfd); // } status = tspSetupInterface(c, t); // exit( status ); // } // else // { // Parent processing // int s = 0; // Wait for child process to exit. // Display( LOG_LEVEL_3, ELInfo, "tspStartLocal", GOGO_STR_WAITING_FOR_SETUP_SCRIPT ); // if( wait(&s) != pid ) // { // // Error occured: we have no other child // Display( LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_ERR_WAITING_SCRIPT ); // status = make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); // break; // } // Check if process waited upon has exited. // if( !WIFEXITED(s) ) // { // // Error: child has not exited properly. Maybe killed ? // Display( LOG_LEVEL_1, ELError, "tspStartLocal", STR_GEN_SCRIPT_EXEC_FAILED ); // Display( LOG_LEVEL_1, ELError, "tspStartLocal", "status 0x%08X %s (%d).", s, strerror(s), errno); // status = make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); // break; // } // Check child exit code. // status = WEXITSTATUS(s); if( status_number(status) != SUCCESS ) { break; } // } gStatusInfo.eStatus = GOGOC_CLISTAT__CONNECTED; gStatusInfo.nStatus = GOGOCM_UIS__NOERROR; send_status_info(); // Retrieve keepalive inteval, if found in tunnel parameters. if( t->keepalive_interval != NULL ) { ka_interval = atoi(t->keepalive_interval); } // Start the tunnel loop, depending on tunnel mode // if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6UDPV4) == 0 ) { status = TunMainLoop( tunfd, socket, c->keepalive, ka_interval, t->client_address_ipv6, t->keepalive_address ); LOG( LOG_LEVEL_2, ELInfo, "end TunMainLoop. Starting tspClose."); // We got out of main V6UDPV4 loop. tspClose(socket, nt); LOG( LOG_LEVEL_2, ELInfo, "end tspClose."); } else if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6V4) == 0 ) { memset( &tun_loop_cfg, 0x00, sizeof(TUNNEL_LOOP_CONFIG) ); tun_loop_cfg.ka_interval = ka_interval; tun_loop_cfg.ka_src_addr = t->client_address_ipv6; tun_loop_cfg.ka_dst_addr = t->keepalive_address; tun_loop_cfg.sa_family = AF_INET6; tun_loop_cfg.tun_lifetime = 0; status = tspPerformTunnelLoop( &tun_loop_cfg ); } break; // END of DUMMY loop. } // Cleanup: Close tunnel descriptor, if it was opened. if( tunfd != -1 ) { LOG( LOG_LEVEL_2, ELInfo, "Closing tunnel descriptor"); // The tunnel file descriptor should be closed before attempting to tear // down the tunnel. Destruction of the tunnel interface may fail if // descriptor is not closed. close( tunfd ); } // Cleanup: Handle tunnel teardown. LOG( LOG_LEVEL_2, ELInfo, "Handle tunnel teardown"); tspTearDownTunnel( c, t ); return status; }