// -------------------------------------------------------------------------- // AuthPLAIN: Performs a plain-text username and password authentication with // the server. // gogoc_status AuthPLAIN(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list) { char BufferIn[1024]; char BufferOut[REDIRECT_RECEIVE_BUFFER_SIZE]; char string[] = "AUTHENTICATE PLAIN\r\n"; int Length; sint32_t tsp_status; // Send authentication mode. if( nt->netsend(socket, string, sizeof(string)) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthPLAIN", STR_NET_FAIL_W_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } memset(BufferIn, 0, sizeof(BufferIn)); Length = pal_snprintf(BufferIn, sizeof(BufferIn), "%c%s%c%s\r\n", '\0', conf->userid, '\0', conf->passwd); // Send username/password for authentication. if( nt->netsendrecv(socket, BufferIn, Length, BufferOut, sizeof(BufferOut)) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthPLAIN", STR_NET_FAIL_RW_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(BufferOut); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(BufferOut, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } // Check if authentication was successful. switch( tsp_status ) { case TSP_PROTOCOL_SUCCESS: break; case TSP_PROTOCOL_AUTH_FAILED: Display(LOG_LEVEL_1, ELError, "AuthPLAIN", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); default: Display(LOG_LEVEL_1, ELError, "AuthPLAIN", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status)); return make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR); } // Successful plain text authentication. return make_status(CTX_TSPAUTHENTICATION, SUCCESS); }
/* Execute cmd and send output to log subsystem */ sint32_t execScript( const char *cmd ) { char buf[1024]; FILE* f_log; sint32_t retVal; // Run the command. memset( buf, 0, sizeof(buf) ); pal_snprintf( buf, sizeof(buf), "%s > %s", cmd, SCRIPT_TMP_FILE ); retVal = pal_system( buf ); // Open resulting output file. f_log = fopen( SCRIPT_TMP_FILE, "r" ); if( f_log == NULL ) { Display( LOG_LEVEL_1, ELError, "execScript", HEX_STR_CANT_OPEN_TMP_FILE SCRIPT_TMP_FILE ); return -1; } // Loop on the output file, and log the contents. while( !feof( f_log ) ) { if( fgets( buf, sizeof(buf), f_log ) != NULL ) { Display( LOG_LEVEL_MAX, ELInfo, "execScript", "%s", buf ); } } // Close file fclose( f_log ); // Remove command output. pal_unlink( SCRIPT_TMP_FILE ); return retVal; }
/* Snmp HEXA Dump */ void snmp_xdump (struct lib_globals *zg, char *prefix, u_char *ptr, size_t length) { s_int32_t i = 0, col = 0, offset = 0; char buf[80]; zlog_info (zg, "%s-XDUMP:", prefix); buf[0] = '\0'; while (i < length) { pal_snprintf (buf + offset, 80 - offset, "%02x ", ptr[i]); offset += 3; i++; if (++col == 16) { buf[offset] = '\0'; zlog_info (zg, "%s", buf); offset = 0; col = 0; } } }
/* Snmp OID Dump */ void snmp_oid_dump (struct lib_globals *zg, char *prefix, oid *oid, size_t oid_len) { s_int32_t i; s_int32_t first = 1; int j; char buf[MAX_OID_LEN * 3]; int offset = 0; buf[0] = '\0'; j = MAX_OID_LEN * 3; for (i = 0; i < oid_len; i++) { pal_snprintf (buf + offset, j - offset, "%s%2d", first ? "" : ".", (s_int32_t) oid[i]); if (first) offset += 2; else offset += 3; first = 0; } buf[offset] = '\0'; zlog_info (zg, "%s: %s", prefix, buf); }
result_t pal_sysctl_set_int_val_by_path (char *kpath, char *vname, int val) { char cmd[PAL_SYSCTL_CMD_LEN]; pal_snprintf (cmd, PAL_SYSCTL_CMD_LEN, "echo %d > /proc/sys/%s/%s", val, kpath, vname); return (system (cmd) != 0 ? RESULT_ERROR : RESULT_OK); }
result_t pal_sysctl_set_int_val(char *kpath, char *vname, int val) { char cmd[PAL_SYSCTL_CMD_LEN]; pal_snprintf (cmd, PAL_SYSCTL_CMD_LEN, "sysctl -w %s/%s=%d", kpath, vname, val); return (system (cmd) != 0 ? RESULT_ERROR : RESULT_OK); }
/* Add a new broker element to a list of brokers */ tRedirectStatus tspAddBrokerToList(tBrokerList **broker_list, char *address, tBrokerAddressType address_type, uint32_t distance) { tBrokerList *new_broker = NULL; /* Some internal error checking */ if (broker_list == NULL) { Display(LOG_LEVEL_1, ELError, "tspAddBrokerToList", GOGO_STR_RDR_ADD_BROKER_INTERNAL_ERR); return TSP_REDIRECT_INTERNAL_ERR; } if (address == NULL) { Display(LOG_LEVEL_1, ELError, "tspAddBrokerToList", GOGO_STR_RDR_ADD_BROKER_INTERNAL_ERR); return TSP_REDIRECT_INTERNAL_ERR; } /* Allocate a new broker element */ if ((new_broker = (tBrokerList *)pal_malloc(sizeof(tBrokerList))) == NULL) { Display(LOG_LEVEL_1, ELError, "tspAddBrokerToList", GOGO_STR_RDR_ADD_BROKER_NO_MEM); return TSP_REDIRECT_CANT_ALLOCATE_MEM; } /* Set the broker address */ pal_snprintf(new_broker->address, MAX_REDIRECT_ADDRESS_LENGTH, "%s", address); /* Validate that the address was set correctly */ if (strlen(new_broker->address) != strlen(address)) { pal_free(new_broker); Display(LOG_LEVEL_1, ELError, "tspAddBrokerToList", GOGO_STR_RDR_ADD_BROKER_ADDRESS_TRUNC); return TSP_REDIRECT_ADDRESS_TRUNCATED; } /* Set the broker distance */ new_broker->distance = distance; /* Set the broker address type */ new_broker->address_type = address_type; /* Add the new broker element at the end of the list */ new_broker->next = NULL; if (*broker_list == NULL) { *broker_list = new_broker; } else { while ((*broker_list)->next != NULL) { broker_list = &((*broker_list)->next); } (*broker_list)->next = new_broker; } return TSP_REDIRECT_OK; }
result_t pal_sysctl_get_int_val_by_path (char *kpath, char *vname, int *val) { char tmp_fn[PAL_SYSCTL_TMP_FNAME_LEN]; char cmd[PAL_SYSCTL_CMD_LEN]; /* Create name of tmp file. */ pal_snprintf (tmp_fn, PAL_SYSCTL_TMP_FNAME_LEN, "/tmp/bgpsdn_%s", vname); /* Copy value to tmp file. */ pal_snprintf (cmd, PAL_SYSCTL_CMD_LEN, "cat /proc/sys/%s/%s > %s", kpath, vname, tmp_fn); if (system (cmd) != 0) return RESULT_ERROR; else { FILE *fp = NULL; char *sp= &cmd[0]; /* Reusing the command buffer. */ fp = fopen (tmp_fn, "r"); if (fp == NULL) return RESULT_ERROR; if (fgets (sp, PAL_SYSCTL_CMD_LEN, fp) == sp) { /* We expect exactly 1 value. */ if (sscanf (sp, "%d", val) == 1) { fclose (fp); return RESULT_OK; } } fclose (fp); return RESULT_ERROR; } }
s_int32_t bpn_sock_listen (struct bgp *bgp, u_int16_t port) { struct bgp_listen_sock_lnode *tmp_lnode; u_int8_t port_str [SU_ADDRSTRLEN]; struct pal_addrinfo *ainfo_save[2], *ainfo_head; struct pal_addrinfo *ainfo; struct pal_sockaddr_in4 ain4; struct pal_sockaddr_in6 ain6; struct pal_addrinfo req; struct thread *t_accept; s_int32_t bgp_sock; u_int8_t addr_set; fib_id_t fib_id; s_int32_t ret; int i, flags = 1; pal_mem_set (&req, 0, sizeof (struct pal_addrinfo)); t_accept = NULL; ainfo_save[0] = NULL; ainfo_save[1] = NULL; ret = 0; addr_set = 0; if (! bgp) { zlog_err (&BLG, "[NETWORK] Server Sock: Invalid 'bgp' instance"); return -1; } fib_id = LIB_VRF_GET_FIB_ID (bgp->owning_ivrf); req.ai_flags = AI_PASSIVE; req.ai_family = AF_UNSPEC; req.ai_socktype = SOCK_STREAM; pal_snprintf (port_str, SU_ADDRSTRLEN, "%d", port); port_str[sizeof (port_str) - 1] = '\0'; ret = pal_sock_getaddrinfo (NULL, port_str, &req, &ainfo); if (ret != 0) { zlog_err (&BLG, "[NETWORK] Server Sock: getaddrinfo() failed: %d-%s", errno, pal_strerror (errno)); return ret; } ainfo_head = ainfo; /* IPv4 can connect to IPv6 socket, not other way around. */ while (ainfo) { if (ainfo->ai_family == AF_INET) ainfo_save[1] = ainfo; else if (ainfo->ai_family == AF_INET6) ainfo_save[0] = ainfo; ainfo = ainfo->ai_next; } for (i = 0; i < 2; i++) { ainfo = ainfo_save[i]; if (! ainfo) continue; if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6) continue; bgp_sock = pal_sock (&BLG, ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol); if (bgp_sock < 0) { zlog_err (&BLG, "[NETWORK] Server Sock: socket() Failed for AF" "=%d, FIB-ID %d, Err:%d-%s", ainfo->ai_family, fib_id, errno, pal_strerror (errno)); continue; } /* set socket as ipv6 only */ if (ainfo->ai_family == AF_INET6) { ret = setsockopt(bgp_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &flags, sizeof(flags)); if (ret < 0) { zlog_err (&BLG, "[NETWORK] Server Sock: socket() failed to" "set option for AF=%d, Err:%d-%s", ainfo->ai_family, errno, pal_strerror (errno)); } } ret = pal_sock_set_reuseaddr (bgp_sock, PAL_TRUE); pal_sock_set_reuseport (bgp_sock, PAL_TRUE); /* Bind socket to FIB. */ ret = pal_sock_set_bindtofib (bgp_sock, fib_id); if (ret < 0) { zlog_err (&BLG, "[NETWORK] Server Sock: bindtofib() Failed for" " AF=%d, Sock %d, FIB-ID %d, Err:%d-%s", ainfo->ai_family, bgp_sock, fib_id, errno, pal_strerror (errno)); SSOCK_FD_CLOSE (&BLG, bgp_sock); ret = 0; continue; } /* If the ai_addr is NULL, bind it to the port. */ if (ainfo->ai_addr == NULL) { if (ainfo->ai_family == AF_INET) { pal_mem_set (&ain4, 0, sizeof (ain4)); ain4.sin_family = AF_INET; ain4.sin_port = pal_hton16 (port); ainfo->ai_addr = (struct pal_sockaddr *) &ain4; ainfo->ai_addrlen = sizeof (struct pal_sockaddr_in4); addr_set = 1; } else if (ainfo->ai_family == AF_INET6) { pal_mem_set (&ain6, 0, sizeof (ain6)); ain6.sin6_family = AF_INET6; ain6.sin6_port = pal_hton16 (port); ainfo->ai_addr = (struct pal_sockaddr *) &ain6; ainfo->ai_addrlen = sizeof (struct pal_sockaddr_in6); addr_set = 1; } else { zlog_err (&BLG, "[NETWORK] Server Sock: getaddrinfo() returned" "invalid address" " AF=%d, Sock %d", ainfo->ai_family, bgp_sock); SSOCK_FD_CLOSE (&BLG, bgp_sock); ret = 0; continue; } } ret = pal_sock_bind (bgp_sock, ainfo->ai_addr, ainfo->ai_addrlen); if (addr_set) ainfo->ai_addr = NULL; if (ret < 0) { zlog_err (&BLG, "[NETWORK] Server Sock: bind() Failed for AF=" "%d, Err: %d-%s, port[%d]", ainfo->ai_family, errno, pal_strerror (errno), port); SSOCK_FD_CLOSE (&BLG, bgp_sock); ret = 0; continue; } #ifdef HAVE_TCP_MD5SIG bgp_md5_set_server (bgp, bgp_sock); #endif /* TCP_MD5SIG */ ret = pal_sock_listen (bgp_sock, BGP_SOCK_LISTEN_BACKLOG); if (ret < 0) { zlog_err (&BLG, "[NETWORK] Server Sock: listen() Failed for " "AF=%d, Sock %d, FIB-ID %d, Err:%d-%s", ainfo->ai_family, bgp_sock, fib_id, errno, pal_strerror (errno)); SSOCK_FD_CLOSE (&BLG, bgp_sock); ret = 0; continue; } /* Start a fresh Accept Thread */ t_accept = NULL; BGP_READ_ON (&BLG, t_accept, bgp, bpn_sock_accept, bgp_sock); /* Add thread to Listen Thread List */ tmp_lnode = XCALLOC (MTYPE_TMP, sizeof (struct bgp_listen_sock_lnode)); if (! tmp_lnode) { zlog_err (&BLG, "[NETWORK] Server Sock:" " Cannot allocate memory (%d) @ %s:%d", sizeof (struct bgp_peer_inconn_req), __FILE__, __LINE__); SSOCK_FD_CLOSE (&BLG, bgp_sock); BGP_READ_OFF (&BLG, t_accept); continue; } tmp_lnode->listen_sock = bgp_sock; tmp_lnode->t_accept = t_accept; if (bgp->listen_sock_lnode) tmp_lnode->next = bgp->listen_sock_lnode; bgp->listen_sock_lnode = tmp_lnode; } pal_sock_freeaddrinfo (ainfo_head); return ret; }
void set_tsp_env_variables( const tConf* pConfig, const tTunnel* pTunnelInfo ) { char buffer[8]; // Specify log verbosity (MAXIMAL). pal_snprintf( buffer, sizeof buffer, "%d", LOG_LEVEL_MAX ); tspSetEnv("TSP_VERBOSE", buffer, 1); // Specify Gateway6 Client installation directory. tspSetEnv("TSP_HOME_DIR", TspHomeDir, 1); // Specify the tunnel mode. tspSetEnv("TSP_TUNNEL_MODE", pTunnelInfo->type, 1); // Specify host type {router, host} tspSetEnv("TSP_HOST_TYPE", pConfig->host_type, 1); // Specify tunnel interface, for setup. if (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6V4) == 0 ) { tspSetEnv("TSP_TUNNEL_INTERFACE", pConfig->if_tunnel_v6v4, 1); gTunnelInfo.eTunnelType = TUNTYPE_V6V4; } else if (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6UDPV4) == 0 ) { tspSetEnv("TSP_TUNNEL_INTERFACE", pConfig->if_tunnel_v6udpv4, 1); gTunnelInfo.eTunnelType = TUNTYPE_V6UDPV4; } #ifdef V4V6_SUPPORT else if (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V4V6) == 0 ) { tspSetEnv("TSP_TUNNEL_INTERFACE", pConfig->if_tunnel_v4v6, 1); gTunnelInfo.eTunnelType = TUNTYPE_V4V6; } #endif /* V4V6_SUPPORT */ // Specify what interface will be used for routing advertizement, // if enabled. tspSetEnv("TSP_HOME_INTERFACE", pConfig->if_prefix, 1); // Specify local endpoint IPv4 address tspSetEnv("TSP_CLIENT_ADDRESS_IPV4", pTunnelInfo->client_address_ipv4, 1); gTunnelInfo.szIPV4AddrLocalEndpoint = pTunnelInfo->client_address_ipv4; // Specify local endpoint IPv6 address tspSetEnv("TSP_CLIENT_ADDRESS_IPV6", pTunnelInfo->client_address_ipv6, 1); gTunnelInfo.szIPV6AddrLocalEndpoint = pTunnelInfo->client_address_ipv6; // Specify local endpoint domain name if( pTunnelInfo->client_dns_name != NULL) { tspSetEnv("TSP_CLIENT_DNS_NAME", pTunnelInfo->client_dns_name, 1); gTunnelInfo.szUserDomain = pTunnelInfo->client_dns_name; } // Specify remote endpoint IPv4 address. tspSetEnv("TSP_SERVER_ADDRESS_IPV4", pTunnelInfo->server_address_ipv4, 1); gTunnelInfo.szIPV4AddrRemoteEndpoint = pTunnelInfo->server_address_ipv4; // Specify remote endpoint IPv6 address. tspSetEnv("TSP_SERVER_ADDRESS_IPV6", pTunnelInfo->server_address_ipv6, 1); gTunnelInfo.szIPV6AddrRemoteEndpoint = pTunnelInfo->server_address_ipv6; // Specify prefix for tunnel endpoint. if ((pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6V4) == 0) || (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6UDPV4) == 0)) tspSetEnv("TSP_TUNNEL_PREFIXLEN", "128", 1); #ifdef V4V6_SUPPORT else tspSetEnv("TSP_TUNNEL_PREFIXLEN", "32", 1); #endif /* V4V6_SUPPORT */ // Free and clear delegated prefix from tunnel info. if( gTunnelInfo.szDelegatedPrefix != NULL ) { pal_free( gTunnelInfo.szDelegatedPrefix ); gTunnelInfo.szDelegatedPrefix = NULL; } // Have we been allocated a prefix for routing advertizement..? if( pTunnelInfo->prefix != NULL ) { char chPrefix[128]; size_t len, sep; /* Compute the number of characters that are significant out of the prefix. */ /* This is meaningful only for IPv6 prefixes; no contraction is possible for IPv4. */ if ((pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6V4) == 0) || (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6UDPV4) == 0)) { len = (atoi(pTunnelInfo->prefix_length) % 16) ? (atoi(pTunnelInfo->prefix_length) / 16 + 1) * 4 : atoi(pTunnelInfo->prefix_length) / 16 * 4; sep = (atoi(pTunnelInfo->prefix_length) % 16) ? (atoi(pTunnelInfo->prefix_length) / 16) : (atoi(pTunnelInfo->prefix_length) / 16) -1; } else { len = pal_strlen( pTunnelInfo->prefix ); sep = 0; } memset(chPrefix, 0, 128); memcpy(chPrefix, pTunnelInfo->prefix, len+sep); // Specify delegated prefix for routing advertizement, if enabled. tspSetEnv("TSP_PREFIX", chPrefix, 1); gTunnelInfo.szDelegatedPrefix = (char*) pal_malloc( pal_strlen(chPrefix) + 10/*To append prefix_length*/ ); strcpy( gTunnelInfo.szDelegatedPrefix, chPrefix ); // Specify prefix length for routing advertizement, if enabled. tspSetEnv("TSP_PREFIXLEN", pTunnelInfo->prefix_length, 1); strcat( gTunnelInfo.szDelegatedPrefix, "/" ); strcat( gTunnelInfo.szDelegatedPrefix, pTunnelInfo->prefix_length ); } }
/* Comment ******************************************************************** * 팬택의 PM-L300S의 상태 정보를 읽어옵니다. * */ void get_l300s_status(ZEBOS_LTE_MODULE_t *mod) { int read_bytes = 0; char buf[LTE_BUF_LENGTH+1] = {0}; char buf_temp[LTE_BUF_LENGTH+1] = {0}; // dummy at 명령을 수행해 모듈을 초기화합니다. memset (buf, 0x00, LTE_BUF_LENGTH); read_bytes = lte_xmit_serial ("at", buf); //state memset (buf, 0x00, LTE_BUF_LENGTH); read_bytes = lte_xmit_serial ("at*regsts?", buf); DBG("%s \r\n", buf); if (read_bytes > 0) { memset (buf_temp, 0x00, LTE_BUF_LENGTH); lte_strtok (buf, read_bytes, 2, buf_temp); mod->state = atoi (buf_temp); if (mod->state >= 0 && mod->state < ARRAY_SIZE (l300s_state_list)) pal_snprintf (mod->state_name, MAX_BUF_LENGTH, "%s", l300s_state_list[mod->state].name); else pal_snprintf (mod->state_name, MAX_BUF_LENGTH, "%s", "UNKNOWN"); } // imei memset (buf, 0x00, LTE_BUF_LENGTH); read_bytes = lte_xmit_serial ("at*imei?", buf); DBG("%s \r\n", buf); if (read_bytes > 0) lte_strtok (buf, read_bytes, 2, mod->imei); // number memset (buf, 0x00, LTE_BUF_LENGTH); read_bytes = lte_xmit_serial ("at*minfo", buf); DBG("%s \r\n", buf); if (read_bytes > 0) lte_strtok (buf, read_bytes, 3, mod->number); // info (모듈 이름) memset (buf, 0x00, LTE_BUF_LENGTH); read_bytes = lte_xmit_serial ("at*minfo", buf); DBG("%s \r\n", buf); if (read_bytes > 0) lte_strtok (buf, read_bytes, 2, mod->info); // name (항상 SKT로 보여집니다) snprintf (mod->name, MAX_BUF_LENGTH, "%s", "SKT"); // network 망 확인 memset(buf, 0x00, LTE_BUF_LENGTH); read_bytes = lte_xmit_serial("at*antlvl?", buf); DBG("%s \r\n", buf); if (read_bytes > 0) lte_strtok (buf, read_bytes, 3, mod->type); // rssi // 안테나 값은 0 - 10 까지 주어집니다. // 하지만 rssi 값은 제공 되지 않았습니다. // 그래서 임의로 rssi 값을 출력하도록 합니다. // NTmore LM200Q 모듈의 data를 근거로 작성하였습니다. memset(buf, 0x00, LTE_BUF_LENGTH); memset(buf_temp, 0x00, LTE_BUF_LENGTH); read_bytes = lte_xmit_serial("at*antlvl?", buf); DBG("%s \r\n", pbuf); if (read_bytes > 0) { lte_strtok (buf, read_bytes, 2, buf_temp); mod->level = atoi(buf_temp) * 10; } }
// -------------------------------------------------------------------------- // Function : tspAuthenticate // // Synopsys: Will authenticate a session with the broker. // // Description: // First, we'll try to find the most secure common authentication method. // Once the authentication method has been chosen, the authentication // process is initiated with the broker. // // Arguments: (only local-specific arguments are listed here) // cap: bitfield [IN], The authentication methods suported by the broker. // conf: tConf* [IN], The global configuration object. // // Return values: // A gogoc_status status. // // -------------------------------------------------------------------------- gogoc_status tspAuthenticate(pal_socket_t socket, tCapability cap, net_tools_t *nt, tConf *conf, tBrokerList **broker_list, int version_index) { gogoc_status status = make_status(CTX_TSPAUTHENTICATION, ERR_NO_COMMON_AUTHENTICATION); tCapability Mechanism; // Get mechanism, depending on requested authentication method. if( pal_strcasecmp( conf->auth_method, "any" ) == 0 ) Mechanism = AUTH_ANY; else Mechanism = tspSetCapability("AUTH", conf->auth_method); if( pal_strcasecmp( conf->auth_method, "anonymous" ) != 0 ) { // Try the most secure authentication methods first: #ifndef NO_OPENSSL if( Mechanism & cap & AUTH_PASSDSS_3DES_1 ) { Display(LOG_LEVEL_3, ELInfo, "tspAuthenticate", GOGO_STR_USING_AUTH_PASSDSS_3DES_1); status = AuthPASSDSS_3DES_1(socket, nt, conf, broker_list); goto EndAuthenticate; } #endif if( Mechanism & cap & AUTH_DIGEST_MD5 ) { Display(LOG_LEVEL_3, ELInfo, "tspAuthenticate", GOGO_STR_USING_AUTH_DIGEST_MD5); status = AuthDIGEST_MD5(socket, nt, conf, broker_list, version_index); goto EndAuthenticate; } if( Mechanism & cap & AUTH_PLAIN ) { Display(LOG_LEVEL_3, ELInfo, "tspAuthenticate", GOGO_STR_USING_AUTH_PLAIN); status = AuthPLAIN(socket, nt, conf, broker_list); goto EndAuthenticate; } } else { // Finally, try anonymous if possible. if( Mechanism & cap & AUTH_ANONYMOUS ) { Display(LOG_LEVEL_3, ELInfo, "tspAuthenticate", GOGO_STR_USING_AUTH_ANONYMOUS); status = AuthANONYMOUS(socket, nt, conf, broker_list); goto EndAuthenticate; } } EndAuthenticate: if( status_number(status) == ERR_NO_COMMON_AUTHENTICATION ) { const char* szStrings[] = { "Server Authentication Capabilities: ", "Your Configured Authentication: " }; size_t nWritten; char bufDisplay[256]; // Display server authentication capabilities. pal_snprintf( bufDisplay, sizeof(bufDisplay), "%s", szStrings[0] ); nWritten = pal_strlen( szStrings[0] ); tspFormatCapabilities( bufDisplay + nWritten, sizeof(bufDisplay) - nWritten, cap ); Display( LOG_LEVEL_1, ELWarning, "tspAuthenticate", bufDisplay ); // Display user authentication choice. pal_snprintf( bufDisplay, sizeof(bufDisplay), "%s", szStrings[1] ); nWritten = pal_strlen( szStrings[1] ); tspFormatCapabilities( bufDisplay + nWritten, sizeof(bufDisplay) - nWritten, Mechanism ); Display( LOG_LEVEL_1, ELWarning, "tspAuthenticate", bufDisplay ); // Failed to find a common authentication method. Display(LOG_LEVEL_1, ELError, "tspAuthenticate", STR_TSP_NO_COMMON_AUTHENTICATION); } return status; }
// -------------------------------------------------------------------------- // AuthDIGEST_MD5: Performs a Digest-MD5 authentication with the server. // gogoc_status AuthDIGEST_MD5(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list, int version_index) { char Buffer[4096], Response[33], cResponse[33], *ChallengeString; char string[] = "AUTHENTICATE DIGEST-MD5\r\n"; char BufferIn[REDIRECT_RECEIVE_BUFFER_SIZE]; time_t cnonce = pal_time(NULL); tChallenge c; sint32_t tsp_status; // Send authentication mode. memset(BufferIn, 0, sizeof(BufferIn)); if( nt->netsendrecv(socket, string, sizeof(string), BufferIn, sizeof(BufferIn)) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_NET_FAIL_RW_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(BufferIn); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } // Check for error in status. if( tsp_status == TSP_PROTOCOL_AUTH_FAILED ) { // Failed authentication. Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); } // Allocate memory for challenge string. if( (ChallengeString = pal_malloc(pal_strlen(BufferIn) + 1)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } base64decode(ChallengeString, BufferIn); ExtractChallenge(&c, ChallengeString); pal_free(ChallengeString); { /*-----------------------------------------------------------*/ /* Extract from : RFC 2831 Digest SASL Mechanism Let H(s) be the 16 octet MD5 hash [RFC 1321] of the octet string s. Let KD(k, s) be H({k, ":", s}), i.e., the 16 octet hash of the string k, a colon and the string s. Let HEX(n) be the representation of the 16 octet MD5 hash n as a string of 32 hex digits (with alphabetic characters always in lower case, since MD5 is case sensitive). response-value = HEX( KD ( HEX(H(A1)), { nonce-value, ":" nc-value, ":", cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) If authzid is not specified, then A1 is A1 = { H( { username-value, ":", realm-value, ":", passwd } ), ":", nonce-value, ":", cnonce-value } If the "qop" directive's value is "auth", then A2 is: A2 = { "AUTHENTICATE:", digest-uri-value } */ char *A1_1Fmt = "%s:%s:%s", #ifndef WIN32 *A1Fmt = ":%s:%lu", *ChallRespFmt = "%s:%s:00000001:%lu:%s:%s", *ResponseFmt = "charset=%s,username=\"%s\",realm=\"%s\",nonce=\"%s\",nc=00000001,cnonce=\"%lu\",digest-uri=\"tsp/%s\",response=%s,qop=auth", #else // 64 bit version. *A1Fmt = ":%s:%I64d", *ChallRespFmt = "%s:%s:00000001:%I64d:%s:%s", *ResponseFmt = "charset=%s,username=\"%s\",realm=\"%s\",nonce=\"%s\",nc=00000001,cnonce=\"%I64d\",digest-uri=\"tsp/%s\",response=%s,qop=auth", #endif *A2Fmt = "%s:tsp/%s", A1[33], A1_1[33], A2[33], cA2[33], *String; size_t len; /*-----------------------------------------------------------*/ /* Build HEX(H(A2)) & HEX(H(cA2)) */ len = pal_strlen(A2Fmt) + 12 /* AUTHENTICATE */ + pal_strlen(conf->server) + 1; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, A2Fmt, "AUTHENTICATE", conf->server); #if defined(_DEBUG) || defined(DEBUG) printf("A2 = %s\n", String); #endif strncpy(A2, md5(String, pal_strlen(String)), 33); pal_snprintf(String, len, A2Fmt, "", conf->server); #if defined(_DEBUG) || defined(DEBUG) printf("cA2 = %s\n", String); #endif strncpy(cA2, md5(String, pal_strlen(String)), 33); pal_free(String); /*-----------------------------------------------------------*/ /* Build HEX(H(A1)) */ /* A1_1 = { username-value, ":", realm-value, ":", passwd } */ /* A1 = { H( A1_1 ), ":", nonce-value, ":", cnonce-value } */ len = pal_strlen(A1_1Fmt) + pal_strlen(conf->userid) + pal_strlen(c.realm) + pal_strlen(conf->passwd) + 1; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, A1_1Fmt, conf->userid, c.realm, conf->passwd); #if defined(_DEBUG) || defined(DEBUG) printf("A1_1 = %s\n", String); #endif md5digest(String, pal_strlen(String), A1_1); pal_free(String); len = 16 /* A1_1 */ + 1 + pal_strlen(c.nonce) + 16 /* cnonce */ + 1; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } memcpy(String, A1_1, 16); pal_snprintf(String + 16, len - 16, A1Fmt, c.nonce, cnonce); #ifdef SUPPORT_MD5_BUG1455 A1_1[16] = '\0'; if ((pal_strlen(A1_1) < 16) && !((pal_strlen(TSPProtoVerStr[version_index]) > 5) || (strcmp(TSPProtoVerStr[version_index], CLIENT_VERSION_STRING_2_0_0) > 0))) strncpy(A1, md5(String, pal_strlen(String)), 33); else #endif /* SUPPORT_MD5_BUG1455 */ strncpy(A1, md5(String, 16 + pal_strlen(String + 16)), 33); pal_free(String); #if defined(_DEBUG) || defined(DEBUG) printf("A1 = [%s]\n", A1); #endif /*-----------------------------------------------------------*/ /* Build server's and client's challenge responses */ len = pal_strlen(ChallRespFmt) + 32 /* md5(A1) */ + pal_strlen(c.nonce) +16 /* cnonce */ + pal_strlen(c.qop) + 32 /* md5(A2) */ + 1; if((String = pal_malloc(len)) == NULL) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, ChallRespFmt, A1, c.nonce, cnonce, c.qop, A2); #if defined(_DEBUG) || defined(DEBUG) printf("Response = [%s]\n", String); #endif strncpy(Response, md5(String, pal_strlen(String)), 33); #if defined(_DEBUG) || defined(DEBUG) printf("MD5 Response = %s\n", Response); #endif pal_snprintf(String, len, ChallRespFmt, A1, c.nonce, cnonce, c.qop, cA2); #if defined(_DEBUG) || defined(DEBUG) printf("cResponse = [%s]\n", String); #endif strncpy(cResponse, md5(String, pal_strlen(String)), 33); #if defined(_DEBUG) || defined(DEBUG) printf("MD5 cResponse = %s\n", cResponse); #endif pal_free(String); /*-----------------------------------------------------------*/ /* Build Response */ { char userid[512]; // UserId is theorically limited to 253 chars. char * cc; size_t i; // Escape malicious " and \ from conf->userid. for(cc=conf->userid, i=0; *cc && i<512; cc++, i++) { // Prepend a backslash (\). if( *cc == '"' || *cc == '\\' ) userid[i++] = '\\'; // Copy character. userid[i] = *cc; } userid[i] = '\0'; len = pal_strlen(ResponseFmt) + pal_strlen(c.charset) + pal_strlen(userid) + pal_strlen(c.realm) + pal_strlen(c.nonce) + 16 /*cnonce*/ + pal_strlen(conf->server) + 32 /* md5 response */; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, ResponseFmt, c.charset, userid, c.realm, c.nonce, cnonce, conf->server, Response); memset(Buffer, 0, sizeof(Buffer)); base64encode(Buffer, String, (int)pal_strlen(String)); pal_free(String); } } // Send authentication data. memset(BufferIn, 0, sizeof(BufferIn)); if( nt->netprintf(socket, BufferIn, sizeof(BufferIn), "%s\r\n", Buffer) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_NET_FAIL_W_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(BufferIn); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } /*-----------------------------------------------------------*/ /* Verify server response */ if( tsp_status == TSP_PROTOCOL_AUTH_FAILED ) { // Failed authentication. Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); } if( (ChallengeString = pal_malloc(pal_strlen(BufferIn) + 1)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } base64decode(ChallengeString, BufferIn); ExtractChallenge(&c, ChallengeString); pal_free(ChallengeString); if( memcmp(c.rspauth, cResponse, 32) ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_MISC_INVALID_MD5_RESPONSE); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); } // Receive reply. if( nt->netrecv(socket, Buffer, sizeof(Buffer) ) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_NET_FAIL_R_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(Buffer); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(Buffer, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } // Check if authentication was successful. switch( tsp_status ) { case TSP_PROTOCOL_SUCCESS: break; case TSP_PROTOCOL_AUTH_FAILED: Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); default: Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status)); return make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR); } // Successful MD5 authentication. return make_status(CTX_TSPAUTHENTICATION, SUCCESS); }
/* Calculate the roundtrip time to a brokre using a TSP echo request */ tRedirectStatus timeEchoRequestReply(pal_socket_t sfd, char *address, rttengine_stat_t *engine, uint32_t *distance) { char data_in[ECHO_REQUEST_IN_BUF_SIZE]; char data_out[ECHO_REQUEST_OUT_BUF_SIZE]; sint32_t data_in_size = 0; size_t data_out_size = 0; rudp_msghdr_t *imh = NULL; rudp_msghdr_t *omh = NULL; void *om = NULL; void *im = NULL; sint32_t length_sent = 0; sint32_t ret = 0; fd_set fs; struct timeval tv_select; /* The receive buffer is empty */ memset(data_in, 0, sizeof(data_in)); /* The send buffer contains the "ECHO REQUEST" command */ pal_snprintf(data_out, sizeof(data_out), ECHO_REQUEST_COMMAND); /* Calculate the buffer sizes */ data_in_size = sizeof(data_in); data_out_size = pal_strlen(data_out); /* Prepare RUDP messages */ im = internal_prepare_message(&imh, data_in_size); om = internal_prepare_message(&omh, data_out_size); /* A NULL message is an error */ if ((im == NULL) || (om == NULL)) { rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_ERROR_ADJUST; Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_ERROR_PREPARING_RUDP_MSG, address); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } /* Zero them out */ memset(im, 0, data_in_size); memset(om, 0, data_out_size); /* Copy the outgoing data to the data part of the outgoing message */ memcpy((char*)om + sizeof(rudp_msghdr_t), data_out, data_out_size); /* Set the outgoing message's sequence number */ omh->sequence = htonl(engine->sequence++ | 0xf0000000); send_loop: /* Fail if we have reached the maximum number of echo request attempts */ if (engine->retries == ECHO_REQUEST_ATTEMPTS) { rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_TIMEOUT_ADJUST; Display(LOG_LEVEL_3, ELWarning, "timeEchoRequestReply", GOGO_STR_RDR_MAX_ECHO_REPLY_ATTEMPTS, ECHO_REQUEST_ATTEMPTS, address); return TSP_REDIRECT_ECHO_REQUEST_TIMEOUT; } /* Set the timestamp for the outgoing message */ omh->timestamp = htonl(internal_get_timestamp(engine)); /* Try to send the outgoing message */ Display(LOG_LEVEL_3, ELInfo, "timeEchoRequestReply", GOGO_STR_RDR_SENDING_ECHO_REQUEST, (engine->retries + 1), address); if ((length_sent = send(sfd, om, (sint32_t)(data_out_size + sizeof(rudp_msghdr_t)), 0)) == -1) { rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_ERROR_ADJUST; Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_SEND_ECHO_REQUEST_FAILED, address); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } /* Set the timeout for the select */ /* This is the maximum time we will wait for an echo reply */ tv_select.tv_sec = ECHO_REQUEST_TIMEOUT / 1000; tv_select.tv_usec = (ECHO_REQUEST_TIMEOUT % 1000) * 1000; select_loop: FD_ZERO(&fs); FD_SET(sfd, &fs); Display(LOG_LEVEL_3, ELInfo, "timeEchoRequestReply", GOGO_STR_RDR_WAITING_ECHO_REPLY, address); /* Wait on the socket set */ ret = select((sint32_t)sfd + 1, &fs, NULL, NULL, &tv_select); switch(ret) { /* Select timed out, try again */ case 0: Display(LOG_LEVEL_3, ELWarning, "timeEchoRequestReply", GOGO_STR_RDR_WAITING_ECHO_REPLY_TIMEOUT, address); engine->retries++; goto send_loop; /* Ok, select got something */ case 1: Display(LOG_LEVEL_3, ELWarning, "timeEchoRequestReply", GOGO_STR_RDR_RECEIVING_RUDP_MESSAGE, address); /* Receive the incoming data, and store it in the incoming message */ ret = recv(sfd, im, (sizeof(rudp_msghdr_t) + data_in_size), 0); /* This is a fatal read error */ if (ret == -1) { rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_ERROR_ADJUST; Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_ERR_RECEIVING_RUDP_FROM, address); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } /* If we have the same sequence number, this is the message we want */ if (imh->sequence == omh->sequence) { *distance += internal_get_timestamp(engine) - ntohl(omh->timestamp); ret = ret - sizeof(rudp_msghdr_t); Display(LOG_LEVEL_3, ELInfo, "timeEchoRequestReply", GOGO_STR_RDR_RECEIVED_RUDP_OK, address); break; } /* If the sequence numbers are different, see if we get something else */ else { Display(LOG_LEVEL_3, ELWarning, "timeEchoRequestReply", GOGO_STR_RDR_RECV_RUDP_SEQ_DIFFERS, address); goto select_loop; } /* This is an unknown error */ default: rttengine_deinit(engine, im, om); *distance += ECHO_REQUEST_ERROR_ADJUST; Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_ERR_WAITING_ECHO_REPLY, address); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } /* Update the stat engine */ rttengine_update(engine, (internal_get_timestamp(engine) - ntohl(imh->timestamp))); /* Copy the data part of the incoming message to the receiving buffer */ memcpy(data_in, (char*)im + sizeof(rudp_msghdr_t), ret); /* Free the messages */ internal_discard_message(im); internal_discard_message(om); engine->retries = 0; /* Validate that we got the right answer from the broker */ if (tspGetStatusCode(data_in) != ECHO_REQUEST_SUCCESS_STATUS) { Display(LOG_LEVEL_1, ELError, "timeEchoRequestReply", GOGO_STR_RDR_RCV_UNEXPECTED_ECHO_REPLY, address, data_in); return TSP_REDIRECT_ECHO_REQUEST_ERROR; } Display(LOG_LEVEL_3, ELInfo, "timeEchoRequestReply", GOGO_STR_RDR_RCV_EXPECTED_ECHO_REPLY, address, data_in); return TSP_REDIRECT_OK; }
// -------------------------------------------------------------------------- // tspGetCapabilities: // gogoc_status tspGetCapabilities(pal_socket_t socket, net_tools_t *nt, tCapability *capability, int version_index, tConf *conf, tBrokerList **broker_list) { char dataout[256]; char datain[REDIRECT_RECEIVE_BUFFER_SIZE]; sint32_t tsp_status; gogoc_status status = make_status(CTX_TSPCAPABILITIES, SUCCESS); memset( datain, 0, sizeof(datain) ); pal_snprintf(dataout, sizeof(dataout), "VERSION=%s\r\n", TSPProtoVerStr[version_index]); // Send TSP version to the server. Server should reply with the capabilities. if( nt->netsendrecv(socket, dataout, pal_strlen(dataout), datain, (sint32_t)sizeof(datain)) == -1 ) { // Error reading/writing to the socket. return make_status(CTX_TSPCAPABILITIES, ERR_SOCKET_IO); } // Check if we received the TSP capabilities. if( memcmp("CAPABILITY ", datain, 11) == 0 ) { // Extract the capabilities. *capability = tspExtractCapability(datain); } else { // Retrieve the TSP status from the reply. tsp_status = tspGetStatusCode(datain); // Check if it is a redirect TSP status. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(datain, conf, broker_list) == TSP_REDIRECT_OK ) { // REDIRECT event. status = make_status(CTX_TSPCAPABILITIES, EVNT_BROKER_REDIRECTION); } else { // Redirect error. status = make_status(CTX_TSPCAPABILITIES, ERR_BROKER_REDIRECTION); } } else { switch( tsp_status ) { case TSP_PROTOCOL_SERVER_TOO_BUSY: // Ze server iz too busy. Display(LOG_LEVEL_1, ELWarning, "tspGetCapabilities", STR_TSP_SERVER_TOO_BUSY); status = make_status(CTX_TSPCAPABILITIES, ERR_TSP_SERVER_TOO_BUSY); break; case TSP_PROTOCOL_UNSUP_TSP_VER: // The status was an invalid TSP version. Display(LOG_LEVEL_1, ELWarning, "tspGetCapabilities", STR_TSP_INVALID_VERSION, TSPProtoVerStr[version_index]); status = make_status(CTX_TSPCAPABILITIES, ERR_INVAL_TSP_VERSION); break; default: // Unknown / unexpected TSP error occurred. Display(LOG_LEVEL_1, ELError, "tspGetCapabilities", STR_TSP_GEN_ERROR, tsp_status, tspGetTspStatusStr(tsp_status)); status = make_status(CTX_TSPCAPABILITIES, ERR_TSP_GENERIC_ERROR); break; } Display(LOG_LEVEL_1, ELError, "tspGetCapabilities", STR_TSP_GETCAPABILITIES_ERROR); } } // Successful operation. return status; }
int main (int argc, char ** argv) { int nsend = 5 , i; PAL_HANDLE handles[nsend]; if (argc == 1) /* parent */ { pal_printf("Parent: Executing the program\n"); const char *args[3] = { "HandleSend", "child", NULL }; char * data = "Hello World"; char content[20]; char uri[80]; PAL_HANDLE child; int bytes; pal_printf("Parent: Creating handles\n"); // Sending pipe handle handles[0] = DkStreamOpen("pipe.srv:012", PAL_ACCESS_RDWR, 0, PAL_CREAT_TRY, 0); if (handles[0] == NULL) { pal_printf("Parent: DkStreamOpen for pipe failed\n"); goto out; } // Sending pipe handle handles[1] = DkStreamOpen("udp:127.0.0.1:8000", PAL_ACCESS_RDWR, 0, PAL_CREAT_TRY, 0); if (handles[1] == NULL) { pal_printf("Parent: DkStreamOpen for socket failed\n"); goto out; } for (i = 2 ; i < nsend; i++) { pal_snprintf(uri, 80, "file:test_file_%d", i - 2); handles[i] = DkStreamOpen(uri, PAL_ACCESS_RDWR, 0600, PAL_CREAT_TRY, 0); if (handles[i] == NULL) { pal_printf("Parent: DkStreamOpen failed\n"); goto out; } DkStreamSetLength(handles[i], 0); } for (i = 0 ; i < nsend ; i++) { /* do some write */ pal_snprintf(content, sizeof(content), "%s%d", data, i); bytes = DkStreamWrite(handles[i], 0, sizeof(content), content, NULL); if (bytes < 0) { pal_printf("Parent: DKStreamWrite failed\n"); goto out; } DkStreamFlush(handles[i]); } pal_printf("Parent: Forking child\n"); child = DkProcessCreate ("file:HandleSend", 0, args); if (!child) { pal_printf("Parent: Failed creating process\n"); DkProcessExit(1); } for (i = 0 ; i < nsend ; i++) { pal_printf("Parent: Sending Handle %d\n", i); if (!DkSendHandle(child, handles[i])) { pal_printf("Send handle failed\n"); goto out; } DkObjectClose(handles[i]); } pal_printf("Parent: Finished execution\n"); DkObjectClose(child); } else /* child */ { PAL_HANDLE parent = pal_control.parent_process; for (i = 0 ; i < nsend ; i++) { pal_printf("Child: Receiving Handle %d\n", i); handles[i] = DkReceiveHandle(parent); if (!handles[i]) { pal_printf("Child: Failed receiving handle\n"); DkProcessExit(1); } } pal_printf("Child: Reading the handles\n"); for (i = 0 ; i < nsend ; i++) { /* do some read */ pal_printf("Child: Handle %d Type ", i); char data[20]; switch(__PAL_GET_TYPE(handles[i])) { case pal_type_file: if ((DkStreamRead(handles[i], 0, 20, data, NULL, 0))) pal_printf("File Data: %s\n", data); else pal_printf("Couldn't read\n"); break; case pal_type_pipesrv: pal_printf("Pipe\n"); break; case pal_type_udp: pal_printf("Udp\n"); break; default: pal_printf("Unknown\n"); } DkObjectClose(handles[i]); } pal_printf("Child: Finished execution\n\n"); DkObjectClose(parent); } out: for (i = 0 ; i < nsend ; i++) DkObjectClose(handles[i]); return 0; }