/* Initialize communication stuff */ int gtmrecv_comm_init(in_port_t port) { struct addrinfo *ai_ptr = NULL, hints; const int enable_reuseaddr = 1; struct linger disable_linger = {0, 0}; int rc; int errcode; char port_buffer[NI_MAXSERV]; int port_buffer_len; int temp_sock_fd; int af; if (FD_INVALID != gtmrecv_listen_sock_fd) /* Initialization done already */ return (0); /* Create the socket used for communicating with primary */ af = ((GTM_IPV6_SUPPORTED && !ipv4_only) ? AF_INET6 : AF_INET); if (FD_INVALID == (temp_sock_fd = socket(af, SOCK_STREAM, IPPROTO_TCP))) { af = AF_INET; if (FD_INVALID == (temp_sock_fd = socket(af, SOCK_STREAM, IPPROTO_TCP))) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_REPLCOMM, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Error with receiver server socket create"), ERRNO); return (-1); } } /* Make it known to the world that you are ready for a Source Server */ SERVER_HINTS(hints, af); SPRINTF(port_buffer, "%hu", port); if (0 != (errcode = getaddrinfo(NULL, port_buffer, &hints, &ai_ptr))) { CLOSEFILE(temp_sock_fd, rc); RTS_ERROR_ADDRINFO_CTX(NULL, ERR_GETADDRINFO, errcode, "FAILED in obtaining IP address on receiver server."); return -1; } gtmrecv_listen_sock_fd = temp_sock_fd; if (0 > setsockopt(gtmrecv_listen_sock_fd, SOL_SOCKET, SO_LINGER, (const void *)&disable_linger, SIZEOF(disable_linger))) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_REPLCOMM, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Error with receiver server listen socket disable linger"), ERRNO); if (0 > setsockopt(gtmrecv_listen_sock_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&enable_reuseaddr, SIZEOF(enable_reuseaddr))) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_REPLCOMM, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Error with receiver server listen socket enable reuseaddr"), ERRNO); } if (0 > BIND(gtmrecv_listen_sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_REPLCOMM, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Could not bind local address"), ERRNO); CLOSEFILE_RESET(gtmrecv_listen_sock_fd, rc); /* resets "gtmrecv_listen_sock_fd" to FD_INVALID */ return (-1); } if (0 > listen(gtmrecv_listen_sock_fd, 5)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_REPLCOMM, 0, ERR_TEXT, 2, RTS_ERROR_LITERAL("Could not listen"), ERRNO); CLOSEFILE_RESET(gtmrecv_listen_sock_fd, rc); /* resets "gtmrecv_listen_sock_fd" to FD_INVALID */ return (-1); } return (0); }
int gtcm_bgn_net(omi_conn_ll *cll) { extern int4 omi_nxact, omi_nerrs, omi_brecv, omi_bsent; omi_fd fd; int i; int save_errno; int rc; #ifdef NET_TCP struct servent *se; unsigned short port; char port_buffer[NI_MAXSERV]; #endif /* defined(NET_TCP) */ #ifdef BSD_TCP struct addrinfo *ai_ptr, hints; const boolean_t reuseaddr = TRUE; int errcode; #else /* defined(BSD_TCP) */ #ifdef SYSV_TCP struct t_bind *bind; #endif /* defined(SYSV_TCP) */ #endif /* !defined(BSD_TCP) */ /* The linked list of connections */ cll->head = cll->tail = (omi_conn *)0; /* The statistics */ cll->stats.conn = cll->stats.clos = cll->stats.disc = 0; cll->st_cn.bytes_recv = 0; cll->st_cn.bytes_send = 0; cll->st_cn.start = 0; for (i = 0; i < OMI_OP_MAX; i++) cll->st_cn.xact[i] = 0; for (i = 0; i < OMI_ER_MAX; i++) cll->st_cn.errs[i] = 0; omi_nxact = omi_nerrs = omi_brecv = omi_bsent = 0; /* Fall back on a compile time constant */ if (!omi_service) omi_service = SRVC_NAME; #ifdef NET_TCP /* NET_TCP is defined only when BSD_TCP is defined or SYSV_TCP is defined, but SYSV_TCP is never defined (a bug?) * so we move the code of obtaining port information from service down to #ifdef BSD_TCP */ #ifdef SYSV_TCP GTMASSERT; #endif #endif /* defined(NET_TCP) */ #ifdef BSD_TCP /* Create a socket always tries IPv6 first */ SERVER_HINTS(hints, ((GTM_IPV6_SUPPORTED && !ipv4_only) ? AF_INET6 : AF_INET)); if ((fd = socket(hints.ai_family, SOCK_STREAM, 0)) < 0) { if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { save_errno = errno; return save_errno; } hints.ai_family = AF_INET; } /* Bind an address to the socket */ if (0 != (errcode = getaddrinfo(NULL, omi_service, &hints, &ai_ptr))) { RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode); return errcode; } if (ISDIGIT_ASCII(*omi_service)) port = atoi(omi_service); else { if (0 != (errcode = getnameinfo(ai_ptr->ai_addr, ai_ptr->ai_addrlen, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV))) { assert(FALSE); RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode); return errcode; } port = atoi(port_buffer); } /* Reuse a specified address */ if (port && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&reuseaddr, SIZEOF(reuseaddr)) < 0) { save_errno = errno; CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return save_errno; } if (bind(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen) < 0) { save_errno = errno; CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return save_errno; } /* Initialize the listen queue */ if (listen(fd, 5) < 0) { save_errno = errno; CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return save_errno; } /* set up raw socket for use with pinging option */ if (ping_keepalive) psock = init_ping(); /* Store the file descriptor away for use later */ cll->nve = fd; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: socket registered at port %d\n", SRVR_NAME, (int)port)); #ifdef GTCM_RC OMI_DBG((omi_debug, "RC server ID %d, Process ID %d\n", rc_server_id, omi_pid)); #endif if (authenticate) OMI_DBG((omi_debug, "Password verification on OMI connections enabled.\n")); if (!one_conn_per_inaddr) OMI_DBG((omi_debug, "Multiple connections from the same internet address allowed.\n")); if (psock > 0) OMI_DBG((omi_debug, "Keepalive option (-ping) enabled.\n")); return 0; #else /* defined(BSD_TCP) */ #ifdef SYSV_TCP GTMASSERT; if ((fd = t_open(SYSV_TCP, O_RDWR, NULL)) < 0) { save_errno = errno; return save_errno; } if (!(bind = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL))) { save_errno = errno; (void) t_close(fd); return save_errno; } bind->qlen = 5; bind->addr.len = 0; bind->addr.buf = 0; if (t_bind(fd, bind, bind) < 0) { save_errno = errno; (void) t_free(bind, T_BIND); (void) t_close(fd); return save_errno; } /* Store the file descriptor away for use later */ cll->nve = fd; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: socket registered at port %d\n", SRVR_NAME, (int)port)); #ifdef GTCM_RC OMI_DBG((omi_debug, "RC server ID %d\n", rc_server_id)); #endif return 0; #else /* defined(SYSV_TCP) */ cll->nve = FD_INVALID; return -1; #endif /* !defined(SYSV_TCP) */ #endif /* !defined(BSD_TCP) */ }
socket_struct *iosocket_create(char *sockaddr, uint4 bfsize, int file_des, boolean_t listen_specified) { socket_struct *socketptr; socket_struct *prev_socketptr; socket_struct *socklist_head; boolean_t passive = FALSE; unsigned short port; int ii, save_errno, tmplen, errlen, sockaddrlen; char temp_addr[SA_MAXLITLEN], protocolstr[6], *adptr; const char *errptr; struct addrinfo *ai_ptr; struct addrinfo hints, *addr_info_ptr = NULL; #ifndef VMS struct sockaddr_un *sa_un_ptr, sa_un_trans; mval localpath; mstr transpath; int trans_status; #endif enum socket_protocol protocol; int af; int sd; int errcode; char host_buffer[NI_MAXHOST]; char port_buffer[NI_MAXSERV]; int port_buffer_len; int colon_cnt, protooffset; char *last_2colon = NULL; int addrlen; GTM_SOCKLEN_TYPE tmp_addrlen; if (0 > file_des) { /* no socket descriptor yet */ memset(&hints, 0, SIZEOF(hints)); protooffset = colon_cnt = 0; sockaddrlen = STRLEN(sockaddr); for (ii = sockaddrlen - 1; 0 <= ii; ii--) { if (SEPARATOR == sockaddr[ii]) { colon_cnt++; if (1 == colon_cnt) protooffset = ii + 1; else { last_2colon = &sockaddr[ii]; break; } } } if (0 == colon_cnt) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVPORTSPEC); return NULL; } tmplen = sockaddrlen - protooffset; if (SIZEOF(protocolstr) <= tmplen) { /* last piece just too big to be valid */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_PROTNOTSUP, 2, tmplen , &sockaddr[protooffset]); return NULL; } lower_to_upper((uchar_ptr_t)protocolstr, (uchar_ptr_t)&sockaddr[protooffset], tmplen); if (((SIZEOF("TCP") - 1) == tmplen) && (0 == MEMCMP_LIT(protocolstr, "TCP"))) protocol = socket_tcpip; # ifndef VMS else if (((SIZEOF("LOCAL") - 1) == tmplen) && (0 == MEMCMP_LIT(protocolstr, "LOCAL"))) protocol = socket_local; # endif else { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_PROTNOTSUP, 2, tmplen , &sockaddr[protooffset]); return NULL; } if (socket_tcpip == protocol) { if (1 == colon_cnt) { /* for listening socket or broadcasting socket */ if (!listen_specified || (SSCANF(sockaddr, PORT_PROTO_FORMAT, &port, protocolstr) < 2)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVPORTSPEC); return NULL; } passive = TRUE; /* We always first try using IPv6 address, if supported */ af = ((GTM_IPV6_SUPPORTED && !ipv4_only) ? AF_INET6 : AF_INET); if (-1 == (sd = socket(af, SOCK_STREAM, IPPROTO_TCP))) { /* Try creating IPv4 socket */ af = AF_INET; if (-1 == (sd = socket(af, SOCK_STREAM, IPPROTO_TCP))) { save_errno = errno; errptr = (char *)STRERROR(save_errno); errlen = STRLEN(errptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, save_errno, errlen, errptr); return NULL; } } SERVER_HINTS(hints, af); port_buffer_len = 0; I2A(port_buffer, port_buffer_len, port); port_buffer[port_buffer_len]='\0'; if (0 != (errcode = getaddrinfo(NULL, port_buffer, &hints, &addr_info_ptr))) { close(sd); RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode); return NULL; } SOCKET_ALLOC(socketptr); socketptr->local.port = port; socketptr->temp_sd = sd; socketptr->sd = FD_INVALID; ai_ptr = &(socketptr->local.ai); memcpy(ai_ptr, addr_info_ptr, SIZEOF(struct addrinfo)); SOCKET_AI_TO_LOCAL_ADDR(socketptr, addr_info_ptr); ai_ptr->ai_addr = SOCKET_LOCAL_ADDR(socketptr); ai_ptr->ai_addrlen = addr_info_ptr->ai_addrlen; ai_ptr->ai_next = NULL; freeaddrinfo(addr_info_ptr); } else { /* connection socket */ assert(2 == colon_cnt); if (listen_specified || (SSCANF(last_2colon + 1, PORT_PROTO_FORMAT, &port, protocolstr) < 2)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC); return NULL; } /* for connection socket */ SPRINTF(port_buffer, "%hu", port); addrlen = last_2colon - sockaddr; if ('[' == sockaddr[0]) { if (NULL == memchr(sockaddr, ']', addrlen)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC); return NULL; } addrlen -= 2; memcpy(temp_addr, &sockaddr[1], addrlen); } else memcpy(temp_addr, sockaddr, addrlen); temp_addr[addrlen] = 0; CLIENT_HINTS(hints); if (0 != (errcode = getaddrinfo(temp_addr, port_buffer, &hints, &addr_info_ptr))) { RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode); return NULL; } /* we will test all address families in iosocket_connect() */ SOCKET_ALLOC(socketptr); socketptr->remote.ai_head = addr_info_ptr; socketptr->remote.port = port; socketptr->sd = socketptr->temp_sd = FD_INVALID; /* don't mess with 0 */ } # ifndef VMS } else if (socket_local == protocol) { /* should we get_full_path first */ /* check protooffset < sizeof sun_path */ /* protooffset is after colon */ SOCKET_ALLOC(socketptr); socketptr->protocol = socket_local; sa_un_ptr = malloc(SIZEOF(struct sockaddr_un)); sa_un_ptr->sun_family = AF_UNIX; MV_INIT_STRING(&localpath, protooffset - 1, sockaddr); trans_status = TRANS_LOG_NAME(&localpath.str, &transpath, sa_un_trans.sun_path, (int)SIZEOF(sa_un_trans.sun_path), dont_sendmsg_on_log2long); if (SS_LOG2LONG == trans_status) { /* if LOG2LONG, returned len not valid so report untranslated length */ SOCKET_FREE(socketptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ADDRTOOLONG, 4, localpath.str.len, localpath.str.addr, localpath.str.len, SIZEOF(sa_un_trans.sun_path)); return NULL; } memcpy(sa_un_ptr->sun_path, transpath.addr, transpath.len); sa_un_ptr->sun_path[transpath.len] = '\0'; if (listen_specified) { passive = TRUE; socketptr->local.sa = (struct sockaddr *)sa_un_ptr; socketptr->local.ai.ai_family = AF_UNIX; socketptr->local.ai.ai_socktype = SOCK_STREAM; socketptr->local.ai.ai_addrlen = (size_t)((struct sockaddr_un *)0)->sun_path + protooffset; if (-1 == (sd = socket(AF_UNIX, SOCK_STREAM, 0))) { save_errno = errno; SOCKET_FREE(socketptr); errptr = (char *)STRERROR(save_errno); errlen = STRLEN(errptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, save_errno, errlen, errptr); return NULL; } socketptr->temp_sd = sd; socketptr->sd = FD_INVALID; } else { socketptr->remote.sa = (struct sockaddr *)sa_un_ptr; /* setup remote fields */ socketptr->remote.ai.ai_family = AF_UNIX; socketptr->remote.ai.ai_socktype = SOCK_STREAM; socketptr->remote.ai.ai_addrlen = (size_t)((struct sockaddr_un *)0)->sun_path + protooffset; socketptr->sd = socketptr->temp_sd = FD_INVALID; /* don't mess with 0 */ } # endif } else
int tcp_open(char *host, unsigned short port, int4 timeout, boolean_t passive) /* host needs to be NULL terminated */ { boolean_t no_time_left = FALSE, error_given = FALSE; char temp_addr[SA_MAXLEN + 1], addr[SA_MAXLEN + 1]; char *from, *to, *errptr, *temp_ch; char ipname[SA_MAXLEN]; int match, sock, sendbufsize, ii, on = 1, temp_1 = -2; GTM_SOCKLEN_TYPE size; int4 rv, msec_timeout; struct addrinfo *ai_ptr = NULL, *remote_ai_ptr = NULL, *remote_ai_head, hints; char port_buffer[NI_MAXSERV], *brack_pos; int host_len, addr_len, port_len; char msg_buffer[1024]; mstr msg_string; ABS_TIME cur_time, end_time; fd_set tcp_fd; struct sockaddr_storage peer; short retry_num; int save_errno, errlen; const char *terrptr; int errcode; boolean_t af; msg_string.len = SIZEOF(msg_buffer); msg_string.addr = msg_buffer; /* ============================= initialize structures ============================== */ if (NULL != host) { host_len = strlen(host); if ('[' == host[0]) { brack_pos = memchr(host, ']', SA_MAXLEN); if (NULL == brack_pos || (&host[1] == brack_pos)) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC); return -1; } addr_len = brack_pos - &(host[1]); memcpy(addr, &host[1], addr_len); if ('\0' != *(brack_pos + 1)) { /* not allowed to have special symbols other than [ and ] */ rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC); return -1; } } else { /* IPv4 address only */ addr_len = strlen(host); if (0 == addr_len) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVADDRSPEC); return -1; } memcpy(addr, &host[0], addr_len); } addr[addr_len] = '\0'; CLIENT_HINTS(hints); port_len = 0; I2A(port_buffer, port_len, port); port_buffer[port_len]='\0'; if (0 != (errcode = getaddrinfo(addr, port_buffer, &hints, &remote_ai_head))) { RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode); return -1; } } /* ============================== do the connection ============================== */ if (passive) { struct timeval utimeout, save_utimeout; int lsock; af = ((GTM_IPV6_SUPPORTED && !ipv4_only) ? AF_INET6 : AF_INET); lsock = socket(af, SOCK_STREAM, IPPROTO_TCP); if (-1 == lsock) { af = AF_INET; if (-1 == (lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))) { save_errno = errno; errptr = (char *)STRERROR(save_errno); errlen = STRLEN(errptr); gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, save_errno, errlen, errptr); assert(FALSE); return -1; } } SERVER_HINTS(hints, af); /* We can only listen on our own system */ port_len = 0; I2A(port_buffer, port_len, port); port_buffer[port_len]='\0'; if (0 != (errcode = getaddrinfo(NULL, port_buffer, &hints, &ai_ptr))) { RTS_ERROR_ADDRINFO(NULL, ERR_GETADDRINFO, errcode); return -1; } /* allow multiple connections to the same IP address */ if (-1 == setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, SIZEOF(on))) { save_errno = errno; (void)close(lsock); errptr = (char *)STRERROR(save_errno); errlen = STRLEN(errptr); gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, LEN_AND_LIT("SO_REUSEADDR"), save_errno, errlen, errptr); assert(FALSE); return -1; } if (-1 == bind(lsock, ai_ptr->ai_addr, ai_ptr->ai_addrlen)) { save_errno = errno; (void)close(lsock); gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("bind()"), CALLFROM, save_errno); return -1; } freeaddrinfo(ai_ptr); /* establish a queue of length MAX_CONN_PENDING for incoming connections */ if (-1 == listen(lsock, MAX_CONN_PENDING)) { save_errno = errno; (void)close(lsock); errptr = (char *)STRERROR(save_errno); errlen = STRLEN(errptr); gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKLISTEN, 0, ERR_TEXT, 2, errlen, errptr); assert(FALSE); return -1; } if (NO_M_TIMEOUT != timeout) { msec_timeout = timeout2msec(timeout); sys_get_curr_time(&cur_time); add_int_to_abs_time(&cur_time, msec_timeout, &end_time); utimeout.tv_sec = timeout; utimeout.tv_usec = 0; } assertpro(FD_SETSIZE > lsock); FD_ZERO(&tcp_fd); while (TRUE) { while (TRUE) { /* The check for EINTR below is valid and should not be converted to an EINTR wrapper macro * since it might be a timeout. */ FD_SET(lsock, &tcp_fd); save_utimeout = utimeout; rv = select(lsock + 1, (void *)&tcp_fd, (void *)0, (void *)0, (NO_M_TIMEOUT == timeout) ? (struct timeval *)0 : &utimeout); save_errno = errno; utimeout = save_utimeout; if ((0 <= rv) || (EINTR != save_errno)) break; if (NO_M_TIMEOUT != timeout) { sys_get_curr_time(&cur_time); cur_time = sub_abs_time(&end_time, &cur_time); if (0 >= (utimeout.tv_sec = cur_time.at_sec)) { rv = 0; break; } } } if (0 == rv) { (void)close(lsock); util_out_print("Listening timed out.\n", TRUE); assert(FALSE); return -1; } else if (0 > rv) { (void)close(lsock); gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("select()"), CALLFROM, save_errno); assert(FALSE); return -1; } size = SIZEOF(struct sockaddr_storage); ACCEPT_SOCKET(lsock, (struct sockaddr*)(&peer), &size, sock); if (FD_INVALID == sock) { save_errno = errno; # ifdef __hpux if (ENOBUFS == save_errno) continue; # endif (void)close(lsock); errptr = (char *)STRERROR(save_errno); errlen = STRLEN(errptr); gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKACPT, 0, ERR_TEXT, 2, errlen, errptr); assert(FALSE); return -1; } GETNAMEINFO((struct sockaddr*)(&peer), size, temp_addr, SA_MAXLEN + 1, NULL, 0, NI_NUMERICHOST, errcode); if (0 != errcode) { RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode); return -1; } # ifdef DEBUG_ONLINE PRINTF("Connection is from : %s\n", &temp_addr[0]); # endif break; /* previously there is following check here * if ((0 == temp_sin_addr) || (0 == memcmp(&addr[0], &temp_addr[0], strlen(addr)))) * However, temp_sin_addr is always 0 on server side, and addr(local address) shoud not equal to * temp_addr(remote address), so the entire check should be removed */ } (void)close(lsock); } else { /* client side (connection side) */ if (NO_M_TIMEOUT != timeout)