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 Ipv6 support. Display( LOG_LEVEL_2, ELInfo, "tspStartLocal", GOGO_STR_CHECKING_LINUX_IPV6_SUPPORT ); status = tspTestIPv6Support(); if( status_number(status) != SUCCESS ) { // Error: It seems the user does not have IPv6 support in kernel. return status; } // 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 tunnel mode is not supported on this platform. 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); } } 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 ); status = make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); break; } // Check child exit code. status = WEXITSTATUS(s); if( status_number(status) != SUCCESS ) { break; } } // 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); /* We got out of V6UDPV4 "TUN" tunnel loop */ tspClose(socket, nt); } 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 ) { // 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. tspTearDownTunnel( c, t ); return status; }
// -------------------------------------------------------------------------- // setup interface and any daemons or anything needed // tspSetupTunnel() will callback here // int tspStartLocal( int socket, tConf *c, tTunnel *t, net_tools_t *nt ) { TUNNEL_LOOP_CONFIG tun_loop_cfg; int status = NO_ERROR; int keepalive_interval = 0; /* Test for root privileges */ if( geteuid() != 0 ) { Display( LOG_LEVEL_1, ELError, "tspStartLocal", HEX_STR_FATAL_NOT_ROOT_FOR_TUN ); return INTERFACE_SETUP_FAILED; } if( t->keepalive_interval != NULL ) { keepalive_interval = atoi(t->keepalive_interval); Display( LOG_LEVEL_3, ELInfo, "tspStartLocal", HEX_STR_KEEPALIVE_INTERVAL, t->keepalive_interval ); } { int tunfd = (-1); Display( LOG_LEVEL_3, ELInfo, "tspStartLocal", HEX_STR_GOING_DAEMON ); if (daemon(1, 0) == -1) { Display( LOG_LEVEL_3, ELError, "tspStartLocal", HEX_STR_CANT_FORK ); return INTERFACE_SETUP_FAILED; } if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6UDPV4) == 0 ) { tunfd = TunInit(c->if_tunnel_v6udpv4); if( tunfd == -1 ) { Display( LOG_LEVEL_1, ELError, "tspStartLocal", HEX_STR_UNABLE_INIT_TUN_DEV ); return(INTERFACE_SETUP_FAILED); } /* We need the real name of the tun device for the template */ free( c->if_tunnel_v6udpv4 ); c->if_tunnel_v6udpv4 = (char*) malloc( IFNAMSIZ ); TunName(tunfd, c->if_tunnel_v6udpv4, IFNAMSIZ ); } if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V4V6) == 0 ) { Display( LOG_LEVEL_1, ELError, "tspStartLocal", HEX_STR_NO_V4V6_ON_PLATFORM ); return(INTERFACE_SETUP_FAILED); } /* Run the config script without giving it our tunnel file descriptor. // // This is important because otherwise the tunnnel will stay open even // if we get killed */ { int pid = fork(); if( pid < 0 ) { // fork() error return INTERFACE_SETUP_FAILED; } else if( pid == 0 ) { // Child processing: run template script. close(tunfd); if( tspSetupInterface(c, t) != 0 ) exit(INTERFACE_SETUP_FAILED); exit(0); } else { // Parent processing int s = 0; // Wait for child process to exit. Display( LOG_LEVEL_3, ELInfo, "tspStartLocal", HEX_STR_WAITING_FOR_SETUP_SCRIPT ); if (wait(&s) == pid) { // ok our child returned if( !WIFEXITED(s) ) { Display( LOG_LEVEL_3, ELError, "tspStartLocal", HEX_STR_SCRIPT_FAILED ); return INTERFACE_SETUP_FAILED; } // Check child exit code. if( WEXITSTATUS(s) != 0 ) { Display( LOG_LEVEL_3, ELError, "tspStartLocal", HEX_STR_SCRIPT_FAILED ); return INTERFACE_SETUP_FAILED; } // else everything is fine } else { // Error occured: we have no other child Display( LOG_LEVEL_1, ELError, "tspStartLocal", HEX_STR_ERR_WAITING_SCRIPT ); return INTERFACE_SETUP_FAILED; } } } if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6UDPV4) == 0 ) { status = TunMainLoop( tunfd, socket, c->keepalive, keepalive_interval, t->client_address_ipv6, t->keepalive_address ); /* We got out of main V6 UDP V4 loop */ close(tunfd); tspClose(socket, nt); } else if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6V4) == 0 ) { memset( &tun_loop_cfg, 0x00, sizeof(TUNNEL_LOOP_CONFIG) ); tun_loop_cfg.ka_interval = keepalive_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 ); } } // Handle tunnel teardown. if( tspTearDownTunnel( c, t ) != 0 ) { // Log the error. Display( LOG_LEVEL_2, ELError, "tspStartLocal", HEX_STR_SCRIPT_FAILED ); } return status; }
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; }
gogoc_status tspStartLocal(int socket, tConf *c, tTunnel *t, net_tools_t *nt) { TUNNEL_LOOP_CONFIG tun_loop_cfg; int keepalive_interval = 0; gogoc_status status = STATUS_SUCCESS_INIT; /* Test for root privileges */ if(geteuid() != 0) { Display(LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_FATAL_NOT_ROOT_FOR_TUN); return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); } /* start the tunneler service */ if (t->keepalive_interval != NULL) { keepalive_interval = atoi(t->keepalive_interval); } { Display(LOG_LEVEL_3, ELInfo, "tspStartLocal", GOGO_STR_GOING_DAEMON); // Check if we're already daemon. Calling multiple times the daemon() messes up pthreads. if( !c->nodaemon && getppid() != 1 ) { if (daemon(1, 0) == -1) { Display(LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_CANT_FORK); return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); } } if (strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6UDPV4) == 0 ) { Display(LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_NO_V6UDPV4_ON_PLATFORM); return(make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED)); } if (strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V4V6) == 0 ) { Display(LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_NO_V4V6_ON_PLATFORM); return(make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED)); } /* now, run the config script without giving it our tunnel file descriptor. // // This is important because otherwise the tunnnel will stay open even // if we get killed. */ { int pid = fork(); if (pid < 0) { // fork() error return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); } else if (pid == 0) { // Child process status = tspSetupInterface(c, t); exit(status); } else { // Parent process int s = 0; Display(LOG_LEVEL_3, ELInfo, "tspStartLocal", GOGO_STR_WAITING_FOR_SETUP_SCRIPT); if (wait(&s) == pid) { // Our child returned if ( !WIFEXITED(s) ) { Display(LOG_LEVEL_1, ELError, "tspStartLocal", STR_GEN_SCRIPT_EXEC_FAILED); return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); } // Check exit status. status = WEXITSTATUS(s); if( status_number(status) != SUCCESS ) { return status; } } else { // Error occured: we have no other child Display(LOG_LEVEL_1, ELError, "tspStartLocal", GOGO_STR_ERR_WAITING_SCRIPT); return make_status(CTX_TUNINTERFACESETUP, ERR_INTERFACE_SETUP_FAILED); } } } if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6V4) == 0 ) { memset( &tun_loop_cfg, 0x00, sizeof(TUNNEL_LOOP_CONFIG) ); tun_loop_cfg.ka_interval = keepalive_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 ); } /* v4v6 not supported yet if( strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V4V6) == 0 ) { memset( &tun_loop_cfg, 0x00, sizeof(TUNNEL_LOOP_CONFIG) ); tun_loop_cfg.ka_interval = keepalive_interval; tun_loop_cfg.ka_src_addr = t->client_address_ipv4; tun_loop_cfg.ka_dst_addr = t->keepalive_address; tun_loop_cfg.sa_family = AF_INET; tun_loop_cfg.tun_lifetime = atoi(t->lifetime); status = tspPerformTunnelLoop( &tun_loop_cfg ); } */ } // Handle tunnel teardown. tspTearDownTunnel( c, t ); return status; }
int tspStartLocal(int socket, tConf *c, tTunnel *t, net_tools_t *nt) { int status = NO_ERROR; int keepalive_interval = 0; /* Test for root privileges */ if(geteuid() != 0) { Display(LOG_LEVEL_1, ELError, "tspStartLocal", HEX_STR_FATAL_NOT_ROOT_FOR_TUN); return INTERFACE_SETUP_FAILED; } if (t->keepalive_interval != NULL) { keepalive_interval = atoi(t->keepalive_interval); Display(LOG_LEVEL_3, ELInfo, "tspStartLocal", HEX_STR_KEEPALIVE_INTERVAL, t->keepalive_interval); } Display(LOG_LEVEL_3, ELInfo, "tspStartLocal", HEX_STR_GOING_DAEMON); if (daemon(1, 0) == -1) { Display(LOG_LEVEL_3, ELError, "tspStartLocal", HEX_STR_CANT_FORK); return INTERFACE_SETUP_FAILED; } if (strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6UDPV4) == 0 ) { Display(LOG_LEVEL_1, ELError, "tspStartLocal", HEX_STR_NO_V6UDPV4_ON_PLATFORM); return(INTERFACE_SETUP_FAILED); } if (strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V4V6) == 0 ) { Display(LOG_LEVEL_1, ELError, "tspStartLocal", HEX_STR_NO_V4V6_ON_PLATFORM); return(INTERFACE_SETUP_FAILED); } /* Run the config script without giving it our tunnel file descriptor. // // This is important because otherwise the tunnnel will stay open even if // we get killed */ { int pid = fork(); if( pid < 0 ) { // fork() error return INTERFACE_SETUP_FAILED; } else if( pid == 0 ) { // Perform child processing: Configure tunneling interface. if( tspSetupInterface(c, t) != 0 ) exit(INTERFACE_SETUP_FAILED); exit(0); } else { // Parent process. int s = 0; Display(LOG_LEVEL_3, ELInfo, "tspStartLocal", HEX_STR_WAITING_FOR_SETUP_SCRIPT); // Wait for child process to exit. if( wait(&s) == pid ) { // The child process has finished. if ( !WIFEXITED(s) ) { Display(LOG_LEVEL_3, ELError, "tspStartLocal", HEX_STR_SCRIPT_FAILED); return INTERFACE_SETUP_FAILED; } if( WEXITSTATUS(s) != 0 ) { Display(LOG_LEVEL_3, ELError, "tspStartLocal", HEX_STR_SCRIPT_FAILED); return INTERFACE_SETUP_FAILED; } // else everything is fine } else { // Error occured: we have no other child Display(LOG_LEVEL_1, ELError, "tspStartLocal", HEX_STR_ERR_WAITING_SCRIPT); return INTERFACE_SETUP_FAILED; } } } /* v4v6 not supported yet if (strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V4V6) == 0 ) { TUNNEL_LOOP_CONFIG tun_loop_cfg; memset( &tun_loop_cfg, 0x00, sizeof(TUNNEL_LOOP_CONFIG) ); tun_loop_cfg.ka_interval = keepalive_interval; tun_loop_cfg.ka_src_addr = t->client_address_ipv4; tun_loop_cfg.ka_dst_addr = t->keepalive_address; tun_loop_cfg.sa_family = AF_INET; tun_loop_cfg.tun_lifetime = 0; status = tspPerformTunnelLoop( &tun_loop_cfg ); } */ if (strcasecmp(t->type, STR_CONFIG_TUNNELMODE_V6V4) == 0 ) { TUNNEL_LOOP_CONFIG tun_loop_cfg; memset( &tun_loop_cfg, 0x00, sizeof(TUNNEL_LOOP_CONFIG) ); tun_loop_cfg.ka_interval = keepalive_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 ); } // Handle tunnel teardown. if( tspTearDownTunnel( c, t ) != 0 ) { // Log the error. Display(LOG_LEVEL_2, ELError, "tspStartLocal", HEX_STR_SCRIPT_FAILED); } return status; }