connect.c revision fb5e8d76
1266e564dSmrg/****************************************************************************** 2266e564dSmrg 3266e564dSmrg 4266e564dSmrgCopyright 1993, 1998 The Open Group 5266e564dSmrg 6266e564dSmrgPermission to use, copy, modify, distribute, and sell this software and its 7266e564dSmrgdocumentation for any purpose is hereby granted without fee, provided that 8266e564dSmrgthe above copyright notice appear in all copies and that both that 9266e564dSmrgcopyright notice and this permission notice appear in supporting 10266e564dSmrgdocumentation. 11266e564dSmrg 12266e564dSmrgThe above copyright notice and this permission notice shall be included in 13266e564dSmrgall copies or substantial portions of the Software. 14266e564dSmrg 15266e564dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16266e564dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17266e564dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18266e564dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19266e564dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20266e564dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21266e564dSmrg 22266e564dSmrgExcept as contained in this notice, the name of The Open Group shall not be 23266e564dSmrgused in advertising or otherwise to promote the sale, use or other dealings 24266e564dSmrgin this Software without prior written authorization from The Open Group. 25266e564dSmrg 26266e564dSmrgAuthor: Ralph Mor, X Consortium 27266e564dSmrg******************************************************************************/ 28266e564dSmrg 29266e564dSmrg#ifdef HAVE_CONFIG_H 30266e564dSmrg#include <config.h> 31266e564dSmrg#endif 32266e564dSmrg#include <X11/ICE/ICElib.h> 33266e564dSmrg#include "ICElibint.h" 34266e564dSmrg#include <X11/Xtrans/Xtrans.h> 35266e564dSmrg#include "globals.h" 36266e564dSmrg 37266e564dSmrgstatic XtransConnInfo ConnectToPeer(char *networkIdsList, 38266e564dSmrg char **actualConnectionRet); 39266e564dSmrg 40266e564dSmrg#define Strstr strstr 41266e564dSmrg 42266e564dSmrgIceConn 43c5629e66SmrgIceOpenConnection ( 44c5629e66Smrg char *networkIdsList, 45c5629e66Smrg IcePointer context, 46c5629e66Smrg Bool mustAuthenticate, 47c5629e66Smrg int majorOpcodeCheck, 48c5629e66Smrg int errorLength, 49c5629e66Smrg char *errorStringRet 50c5629e66Smrg) 51266e564dSmrg{ 52266e564dSmrg IceConn iceConn; 53266e564dSmrg int extra, i, j; 54266e564dSmrg int endian; 55266e564dSmrg Bool gotReply, ioErrorOccured; 56266e564dSmrg unsigned long setup_sequence; 57266e564dSmrg iceByteOrderMsg *pByteOrderMsg; 58266e564dSmrg iceConnectionSetupMsg *pSetupMsg; 59266e564dSmrg char *pData; 60266e564dSmrg IceReplyWaitInfo replyWait; 61266e564dSmrg _IceReply reply; 62266e564dSmrg int authUsableCount; 63266e564dSmrg int authUsableFlags[MAX_ICE_AUTH_NAMES]; 64266e564dSmrg int authIndices[MAX_ICE_AUTH_NAMES]; 65266e564dSmrg 66266e564dSmrg if (errorStringRet && errorLength > 0) 67266e564dSmrg *errorStringRet = '\0'; 68266e564dSmrg 69266e564dSmrg if (networkIdsList == NULL || *networkIdsList == '\0') 70266e564dSmrg { 71266e564dSmrg strncpy (errorStringRet, 72266e564dSmrg "networkIdsList argument is NULL", errorLength); 73266e564dSmrg return (NULL); 74266e564dSmrg } 75266e564dSmrg 76266e564dSmrg /* 77266e564dSmrg * Check to see if we can use a previously created ICE connection. 78266e564dSmrg * 79266e564dSmrg * If iceConn->want_to_close is True, or iceConn->free_asap is True, 80266e564dSmrg * we can not use the iceConn. 81266e564dSmrg * 82266e564dSmrg * If 'context' is non-NULL, we will only use a previously opened ICE 83266e564dSmrg * connection if the specified 'context' is equal to the context 84266e564dSmrg * associated with the ICE connection, or if the context associated 85266e564dSmrg * with the ICE connection is NULL. 869ef0b394Smrg * 87266e564dSmrg * If 'majorOpcodeCheck' is non-zero, it will contain a protocol major 88266e564dSmrg * opcode that we should make sure is not already active on the ICE 89266e564dSmrg * connection. Some clients will want two seperate connections for the 90266e564dSmrg * same protocol to the same destination client. 91266e564dSmrg */ 92266e564dSmrg 93266e564dSmrg for (i = 0; i < _IceConnectionCount; i++) 94266e564dSmrg { 95266e564dSmrg char *strptr; 96266e564dSmrg if ((strptr = (char *) Strstr ( 97266e564dSmrg networkIdsList, _IceConnectionStrings[i])) != NULL) 98266e564dSmrg { 99266e564dSmrg char ch = *(strptr + strlen (_IceConnectionStrings[i])); 100266e564dSmrg if (ch == ',' || ch == '\0') 101266e564dSmrg { 102266e564dSmrg /* 103266e564dSmrg * OK, we found a connection. Make sure we can reuse it. 104266e564dSmrg */ 105266e564dSmrg 106266e564dSmrg IceConn iceConn = _IceConnectionObjs[i]; 107266e564dSmrg 108266e564dSmrg if (iceConn->want_to_close || iceConn->free_asap || 109266e564dSmrg (context && iceConn->context && 110266e564dSmrg iceConn->context != context)) 111266e564dSmrg { 112266e564dSmrg /* force a new connection to be created */ 113266e564dSmrg break; 114266e564dSmrg } 115266e564dSmrg 116266e564dSmrg if (majorOpcodeCheck) 117266e564dSmrg { 118266e564dSmrg for (j = iceConn->his_min_opcode; 119266e564dSmrg j <= iceConn->his_max_opcode; j++) 120266e564dSmrg { 121266e564dSmrg if (iceConn->process_msg_info[ 122266e564dSmrg j - iceConn->his_min_opcode].in_use && 123266e564dSmrg iceConn->process_msg_info[ 124266e564dSmrg j - iceConn->his_min_opcode].my_opcode == 125266e564dSmrg majorOpcodeCheck) 126266e564dSmrg break; 127266e564dSmrg } 128266e564dSmrg 129266e564dSmrg if (j <= iceConn->his_max_opcode || 130266e564dSmrg (iceConn->protosetup_to_you && 131266e564dSmrg iceConn->protosetup_to_you->my_opcode == 132266e564dSmrg majorOpcodeCheck)) 133266e564dSmrg { 134266e564dSmrg /* force a new connection to be created */ 135266e564dSmrg break; 136266e564dSmrg } 137266e564dSmrg } 138266e564dSmrg 139266e564dSmrg iceConn->open_ref_count++; 140266e564dSmrg if (context && !iceConn->context) 141266e564dSmrg iceConn->context = context; 142266e564dSmrg return (iceConn); 143266e564dSmrg } 144266e564dSmrg } 145266e564dSmrg } 146266e564dSmrg 147fb5e8d76Smrg if ((iceConn = malloc (sizeof (struct _IceConn))) == NULL) 148266e564dSmrg { 149266e564dSmrg strncpy (errorStringRet, "Can't malloc", errorLength); 150266e564dSmrg return (NULL); 151266e564dSmrg } 152266e564dSmrg 153266e564dSmrg 154266e564dSmrg /* 155266e564dSmrg * Open a network connection with the peer client. 156266e564dSmrg */ 157266e564dSmrg 158266e564dSmrg if ((iceConn->trans_conn = ConnectToPeer (networkIdsList, 159266e564dSmrg &iceConn->connection_string)) == NULL) 160266e564dSmrg { 161fb5e8d76Smrg free (iceConn); 162266e564dSmrg strncpy (errorStringRet, "Could not open network socket", errorLength); 163266e564dSmrg return (NULL); 164266e564dSmrg } 165266e564dSmrg 166266e564dSmrg /* 167266e564dSmrg * Set close-on-exec so that programs that fork() don't get confused. 168266e564dSmrg */ 169266e564dSmrg 170266e564dSmrg _IceTransSetOption (iceConn->trans_conn, TRANS_CLOSEONEXEC, 1); 171266e564dSmrg 172266e564dSmrg iceConn->listen_obj = NULL; 173266e564dSmrg 174266e564dSmrg iceConn->connection_status = IceConnectPending; 175266e564dSmrg iceConn->io_ok = True; 176266e564dSmrg iceConn->dispatch_level = 0; 177266e564dSmrg iceConn->context = context; 178266e564dSmrg iceConn->my_ice_version_index = 0; 179266e564dSmrg iceConn->send_sequence = 0; 180266e564dSmrg iceConn->receive_sequence = 0; 181266e564dSmrg 182266e564dSmrg iceConn->vendor = NULL; 183266e564dSmrg iceConn->release = NULL; 184266e564dSmrg iceConn->outbuf = NULL; 185266e564dSmrg 186266e564dSmrg iceConn->scratch = NULL; 187266e564dSmrg iceConn->scratch_size = 0; 188266e564dSmrg 189266e564dSmrg iceConn->process_msg_info = NULL; 190266e564dSmrg 191266e564dSmrg iceConn->connect_to_you = NULL; 192266e564dSmrg iceConn->protosetup_to_you = NULL; 193266e564dSmrg 194266e564dSmrg iceConn->connect_to_me = NULL; 195266e564dSmrg iceConn->protosetup_to_me = NULL; 196266e564dSmrg 197fb5e8d76Smrg if ((iceConn->inbuf = iceConn->inbufptr = malloc (ICE_INBUFSIZE)) == NULL) 198266e564dSmrg { 199266e564dSmrg _IceFreeConnection (iceConn); 200266e564dSmrg strncpy (errorStringRet, "Can't malloc", errorLength); 201266e564dSmrg return (NULL); 202266e564dSmrg } 203266e564dSmrg 204266e564dSmrg iceConn->inbufmax = iceConn->inbuf + ICE_INBUFSIZE; 205266e564dSmrg 206fb5e8d76Smrg if ((iceConn->outbuf = iceConn->outbufptr = calloc (1, ICE_OUTBUFSIZE)) == NULL) 207266e564dSmrg { 208266e564dSmrg _IceFreeConnection (iceConn); 209266e564dSmrg strncpy (errorStringRet, "Can't malloc", errorLength); 210266e564dSmrg return (NULL); 211266e564dSmrg } 212266e564dSmrg 213266e564dSmrg iceConn->outbufmax = iceConn->outbuf + ICE_OUTBUFSIZE; 214266e564dSmrg 215266e564dSmrg iceConn->open_ref_count = 1; 216266e564dSmrg iceConn->proto_ref_count = 0; 217266e564dSmrg 218266e564dSmrg iceConn->skip_want_to_close = False; 219266e564dSmrg iceConn->want_to_close = False; 220266e564dSmrg iceConn->free_asap = False; 221266e564dSmrg 222266e564dSmrg iceConn->saved_reply_waits = NULL; 223266e564dSmrg iceConn->ping_waits = NULL; 224266e564dSmrg 225fb5e8d76Smrg iceConn->connect_to_you = malloc (sizeof (_IceConnectToYouInfo)); 226266e564dSmrg iceConn->connect_to_you->auth_active = 0; 227266e564dSmrg 228266e564dSmrg /* 229266e564dSmrg * Send our byte order. 230266e564dSmrg */ 231266e564dSmrg 232266e564dSmrg IceGetHeader (iceConn, 0, ICE_ByteOrder, 233266e564dSmrg SIZEOF (iceByteOrderMsg), iceByteOrderMsg, pByteOrderMsg); 234266e564dSmrg 235266e564dSmrg endian = 1; 236266e564dSmrg if (*(char *) &endian) 237266e564dSmrg pByteOrderMsg->byteOrder = IceLSBfirst; 238266e564dSmrg else 239266e564dSmrg pByteOrderMsg->byteOrder = IceMSBfirst; 240266e564dSmrg 241266e564dSmrg IceFlush (iceConn); 242266e564dSmrg 243266e564dSmrg 244266e564dSmrg /* 245266e564dSmrg * Now read the ByteOrder message from the other client. 246266e564dSmrg * iceConn->swap should be set to the appropriate boolean 247266e564dSmrg * value after the call to IceProcessMessages. 248266e564dSmrg */ 249266e564dSmrg 250266e564dSmrg iceConn->waiting_for_byteorder = True; 251266e564dSmrg 252266e564dSmrg ioErrorOccured = False; 253266e564dSmrg while (iceConn->waiting_for_byteorder == True && !ioErrorOccured) 254266e564dSmrg { 255266e564dSmrg ioErrorOccured = (IceProcessMessages ( 256266e564dSmrg iceConn, NULL, NULL) == IceProcessMessagesIOError); 257266e564dSmrg } 258266e564dSmrg 259266e564dSmrg if (ioErrorOccured) 260266e564dSmrg { 261266e564dSmrg _IceFreeConnection (iceConn); 262266e564dSmrg strncpy (errorStringRet, "IO error occured opening connection", 263266e564dSmrg errorLength); 264266e564dSmrg return (NULL); 265266e564dSmrg } 266266e564dSmrg 267266e564dSmrg if (iceConn->connection_status == IceConnectRejected) 268266e564dSmrg { 269266e564dSmrg /* 270266e564dSmrg * We failed to get the required ByteOrder message. 271266e564dSmrg */ 272266e564dSmrg 273266e564dSmrg _IceFreeConnection (iceConn); 274266e564dSmrg strncpy (errorStringRet, 275266e564dSmrg "Internal error - did not receive the expected ByteOrder message", 276266e564dSmrg errorLength); 277266e564dSmrg return (NULL); 278266e564dSmrg } 279266e564dSmrg 280266e564dSmrg 281266e564dSmrg /* 282266e564dSmrg * Determine which authentication methods are available for 283266e564dSmrg * the Connection Setup authentication. 284266e564dSmrg */ 285266e564dSmrg 286266e564dSmrg _IceGetPoValidAuthIndices ( 287266e564dSmrg "ICE", iceConn->connection_string, 288266e564dSmrg _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices); 289266e564dSmrg 290266e564dSmrg for (i = 0; i < _IceAuthCount; i++) 291266e564dSmrg { 292266e564dSmrg authUsableFlags[i] = 0; 293266e564dSmrg for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++) 294266e564dSmrg authUsableFlags[i] = (authIndices[j] == i); 295266e564dSmrg } 296266e564dSmrg 297266e564dSmrg 298266e564dSmrg /* 299266e564dSmrg * Now send a Connection Setup message. 300266e564dSmrg */ 301266e564dSmrg 302266e564dSmrg extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString); 303266e564dSmrg 304266e564dSmrg for (i = 0; i < _IceAuthCount; i++) 305266e564dSmrg if (authUsableFlags[i]) 306266e564dSmrg { 307266e564dSmrg extra += STRING_BYTES (_IceAuthNames[i]); 308266e564dSmrg } 309266e564dSmrg 310266e564dSmrg extra += (_IceVersionCount * 4); 311266e564dSmrg 312266e564dSmrg IceGetHeaderExtra (iceConn, 0, ICE_ConnectionSetup, 313266e564dSmrg SIZEOF (iceConnectionSetupMsg), WORD64COUNT (extra), 314266e564dSmrg iceConnectionSetupMsg, pSetupMsg, pData); 315266e564dSmrg 316266e564dSmrg setup_sequence = iceConn->send_sequence; 317266e564dSmrg 318266e564dSmrg pSetupMsg->versionCount = _IceVersionCount; 319266e564dSmrg pSetupMsg->authCount = authUsableCount; 320266e564dSmrg pSetupMsg->mustAuthenticate = mustAuthenticate; 321266e564dSmrg 322266e564dSmrg STORE_STRING (pData, IceVendorString); 323266e564dSmrg STORE_STRING (pData, IceReleaseString); 324266e564dSmrg 325266e564dSmrg for (i = 0; i < _IceAuthCount; i++) 326266e564dSmrg if (authUsableFlags[i]) 327266e564dSmrg { 328266e564dSmrg STORE_STRING (pData, _IceAuthNames[i]); 329266e564dSmrg } 330266e564dSmrg 331266e564dSmrg for (i = 0; i < _IceVersionCount; i++) 332266e564dSmrg { 333266e564dSmrg STORE_CARD16 (pData, _IceVersions[i].major_version); 334266e564dSmrg STORE_CARD16 (pData, _IceVersions[i].minor_version); 335266e564dSmrg } 336266e564dSmrg 337266e564dSmrg IceFlush (iceConn); 338266e564dSmrg 339266e564dSmrg 340266e564dSmrg /* 341266e564dSmrg * Process messages until we get a Connection Reply or an Error Message. 342266e564dSmrg * Authentication will take place behind the scenes. 343266e564dSmrg */ 344266e564dSmrg 345266e564dSmrg replyWait.sequence_of_request = setup_sequence; 346266e564dSmrg replyWait.major_opcode_of_request = 0; 347266e564dSmrg replyWait.minor_opcode_of_request = ICE_ConnectionSetup; 348266e564dSmrg replyWait.reply = (IcePointer) &reply; 349266e564dSmrg 350266e564dSmrg gotReply = False; 351266e564dSmrg ioErrorOccured = False; 352266e564dSmrg 353266e564dSmrg while (!gotReply && !ioErrorOccured) 354266e564dSmrg { 355266e564dSmrg ioErrorOccured = (IceProcessMessages ( 356266e564dSmrg iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); 357266e564dSmrg 358266e564dSmrg if (ioErrorOccured) 359266e564dSmrg { 360266e564dSmrg strncpy (errorStringRet, "IO error occured opening connection", 361266e564dSmrg errorLength); 362266e564dSmrg _IceFreeConnection (iceConn); 363266e564dSmrg iceConn = NULL; 364266e564dSmrg } 365266e564dSmrg else if (gotReply) 366266e564dSmrg { 367266e564dSmrg if (reply.type == ICE_CONNECTION_REPLY) 368266e564dSmrg { 369266e564dSmrg if (reply.connection_reply.version_index >= _IceVersionCount) 370266e564dSmrg { 371266e564dSmrg strncpy (errorStringRet, 372266e564dSmrg "Got a bad version index in the Connection Reply", 373266e564dSmrg errorLength); 374266e564dSmrg 375266e564dSmrg free (reply.connection_reply.vendor); 376266e564dSmrg free (reply.connection_reply.release); 377266e564dSmrg _IceFreeConnection (iceConn); 378266e564dSmrg iceConn = NULL; 379266e564dSmrg } 380266e564dSmrg else 381266e564dSmrg { 382266e564dSmrg iceConn->my_ice_version_index = 383266e564dSmrg reply.connection_reply.version_index; 384266e564dSmrg iceConn->vendor = reply.connection_reply.vendor; 385266e564dSmrg iceConn->release = reply.connection_reply.release; 386266e564dSmrg 387266e564dSmrg _IceConnectionObjs[_IceConnectionCount] = iceConn; 388266e564dSmrg _IceConnectionStrings[_IceConnectionCount] = 389266e564dSmrg iceConn->connection_string; 390266e564dSmrg _IceConnectionCount++; 391266e564dSmrg 392fb5e8d76Smrg free (iceConn->connect_to_you); 393266e564dSmrg iceConn->connect_to_you = NULL; 394266e564dSmrg 395266e564dSmrg iceConn->connection_status = IceConnectAccepted; 396266e564dSmrg } 397266e564dSmrg } 398266e564dSmrg else /* reply.type == ICE_CONNECTION_ERROR */ 399266e564dSmrg { 400266e564dSmrg /* Connection failed */ 401266e564dSmrg 402266e564dSmrg strncpy (errorStringRet, reply.connection_error.error_message, 403266e564dSmrg errorLength); 404266e564dSmrg 405266e564dSmrg free (reply.connection_error.error_message); 406266e564dSmrg 407266e564dSmrg _IceFreeConnection (iceConn); 408266e564dSmrg iceConn = NULL; 409266e564dSmrg } 410266e564dSmrg } 411266e564dSmrg } 412266e564dSmrg 413266e564dSmrg if (iceConn && _IceWatchProcs) 414266e564dSmrg { 415266e564dSmrg /* 416266e564dSmrg * Notify the watch procedures that an iceConn was opened. 417266e564dSmrg */ 418266e564dSmrg 419266e564dSmrg _IceConnectionOpened (iceConn); 420266e564dSmrg } 421266e564dSmrg 422266e564dSmrg return (iceConn); 423266e564dSmrg} 424266e564dSmrg 425266e564dSmrg 426266e564dSmrg 427266e564dSmrgIcePointer 428c5629e66SmrgIceGetConnectionContext ( 429c5629e66Smrg IceConn iceConn 430c5629e66Smrg) 431266e564dSmrg{ 432266e564dSmrg return (iceConn->context); 433266e564dSmrg} 434266e564dSmrg 435266e564dSmrg 436266e564dSmrg 437266e564dSmrg/* ------------------------------------------------------------------------- * 438266e564dSmrg * local routines * 439266e564dSmrg * ------------------------------------------------------------------------- */ 440266e564dSmrg 441266e564dSmrg#define ICE_CONNECTION_RETRIES 5 442266e564dSmrg 443266e564dSmrg 444266e564dSmrgstatic XtransConnInfo 445266e564dSmrgConnectToPeer (char *networkIdsList, char **actualConnectionRet) 446266e564dSmrg{ 447266e564dSmrg char addrbuf[256]; 448266e564dSmrg char* address; 449266e564dSmrg char *ptr, *endptr, *delim; 450266e564dSmrg int madeConnection = 0; 451fb5e8d76Smrg size_t len; 452fb5e8d76Smrg int retry, connect_stat; 453fb5e8d76Smrg size_t address_size; 454266e564dSmrg XtransConnInfo trans_conn = NULL; 455266e564dSmrg 456266e564dSmrg *actualConnectionRet = NULL; 457266e564dSmrg 458266e564dSmrg ptr = networkIdsList; 459266e564dSmrg len = strlen (networkIdsList); 460266e564dSmrg endptr = networkIdsList + len; 461266e564dSmrg 462266e564dSmrg if (len < sizeof addrbuf) 463266e564dSmrg { 464266e564dSmrg address = addrbuf; 465266e564dSmrg address_size = 256; 466266e564dSmrg } 467266e564dSmrg else 468266e564dSmrg { 469266e564dSmrg address = malloc (len + 1); 470266e564dSmrg address_size = len; 4719ef0b394Smrg } 472266e564dSmrg 473266e564dSmrg while (ptr < endptr && !madeConnection) 474266e564dSmrg { 475266e564dSmrg if ((delim = (char *) strchr (ptr, ',')) == NULL) 476266e564dSmrg delim = endptr; 477266e564dSmrg 478266e564dSmrg len = delim - ptr; 479266e564dSmrg if (len > address_size - 1) 480266e564dSmrg len = address_size - 1; 481266e564dSmrg strncpy (address, ptr, len); 482266e564dSmrg address[len] = '\0'; 483266e564dSmrg 484266e564dSmrg ptr = delim + 1; 485266e564dSmrg 486266e564dSmrg for (retry = ICE_CONNECTION_RETRIES; retry >= 0; retry--) 487266e564dSmrg { 488266e564dSmrg if ((trans_conn = _IceTransOpenCOTSClient (address)) == NULL) 489266e564dSmrg { 490266e564dSmrg break; 491266e564dSmrg } 492266e564dSmrg 493266e564dSmrg if ((connect_stat = _IceTransConnect (trans_conn, address)) < 0) 494266e564dSmrg { 495266e564dSmrg _IceTransClose (trans_conn); 496266e564dSmrg 497266e564dSmrg if (connect_stat == TRANS_TRY_CONNECT_AGAIN) 498266e564dSmrg { 499266e564dSmrg sleep(1); 500266e564dSmrg continue; 501266e564dSmrg } 502266e564dSmrg else 503266e564dSmrg break; 504266e564dSmrg } 505266e564dSmrg else 506266e564dSmrg { 507266e564dSmrg madeConnection = 1; 508266e564dSmrg break; 509266e564dSmrg } 510266e564dSmrg } 511266e564dSmrg } 512266e564dSmrg 5139ef0b394Smrg if (madeConnection) 514266e564dSmrg { 515266e564dSmrg /* 516266e564dSmrg * We need to return the actual network connection string 517266e564dSmrg */ 518266e564dSmrg 519266e564dSmrg *actualConnectionRet = strdup(address); 5209ef0b394Smrg 521266e564dSmrg /* 522266e564dSmrg * Return the file descriptor 523266e564dSmrg */ 5249ef0b394Smrg } 525266e564dSmrg else trans_conn = NULL; 526266e564dSmrg 527266e564dSmrg if (address != addrbuf) free (address); 528266e564dSmrg 529266e564dSmrg return trans_conn; 530266e564dSmrg} 531