void gtcm_cn_disc(omi_conn *cptr, omi_conn_ll *cll) { time_t end; int i, nxact, nerrs; int rc; /* Cumulative statistics */ end = time((time_t *)0); cll->st_cn.start += end - cptr->stats.start; cll->st_cn.bytes_recv += cptr->stats.bytes_recv; cll->st_cn.bytes_send += cptr->stats.bytes_send; for (i = 0, nxact = 0; i < OMI_OP_MAX; i++) { cll->st_cn.xact[i] += cptr->stats.xact[i]; nxact += cptr->stats.xact[i]; } for (i = 0, nerrs = 0; i < OMI_ER_MAX; i++) { cll->st_cn.errs[i] += cptr->stats.errs[i]; nerrs += cptr->stats.errs[i]; } cll->stats.disc++; if (cptr->state != OMI_ST_DISC) cll->stats.clos++; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: connection %d to %s closed\n", SRVR_NAME, cptr->stats.id, gtcm_hname(&cptr->stats.sin))); OMI_DBG((omi_debug, "%s:\t%ld seconds connect time\n", SRVR_NAME, end - cptr->stats.start)); OMI_DBG((omi_debug, "%s:\t%d transactions\n", SRVR_NAME, nxact)); OMI_DBG((omi_debug, "%s:\t%d errors\n", SRVR_NAME, nerrs)); OMI_DBG((omi_debug, "%s:\t%d bytes recv'd\n", SRVR_NAME, cptr->stats.bytes_recv)); OMI_DBG((omi_debug, "%s:\t%d bytes sent\n", SRVR_NAME, cptr->stats.bytes_send)); #ifdef BSD_TCP /* Close out the network connection */ CLOSEFILE_RESET(cptr->fd, rc); /* resets "cptr->fd" to FD_INVALID */ #endif /* defined(BSD_TCP) */ if (FD_INVALID != cptr->pklog) CLOSEFILE_RESET(cptr->pklog, rc); /* resets "cptr->pklog" to FD_INVALID */ #ifdef GTCM_RC if (cptr->of) rc_oflow_fin(cptr->of); #endif /* defined(GTCM_RC) */ /* Release locks held on this connection */ omi_prc_unla(cptr, cptr->buff, cptr->buff, cptr->buff); /* Release the buffer and connection structure */ free(cptr->buff); free(cptr); return; }
/* dump packet with connection information...*/ void gtcm_cpktdmp(char *ptr, int length, char *msg) { char newmsg[512]; struct hostent *peer; if (curr_conn && (512-strlen(msg)) > 25) { SPRINTF(newmsg,"Conn: %s - %s", gtcm_hname(&curr_conn->stats.ai), msg); gtcm_pktdmp(ptr, length, newmsg); } else gtcm_pktdmp(ptr, length, msg); }
int omi_prc_conn(omi_conn *cptr, char *xend, char *buff, char *bend) { omi_si si, eightbit, chartran, ss_len, ext_cnt; omi_li li_min, li_max, ext; uns_short li_val; int len, i; char *bptr, *eptr; char *ag_name, *ag_pass, *s; bptr = buff; /* Version numbers */ OMI_SI_READ(&si, cptr->xptr); if (si.value != OMI_PROTO_MAJOR) return -OMI_ER_SE_VRSNOTSUPP; OMI_SI_WRIT(OMI_PROTO_MAJOR, bptr); /* XXX minor version numbers */ OMI_SI_READ(&si, cptr->xptr); OMI_SI_WRIT(OMI_PROTO_MINOR, bptr); /* Minimum and maximum parameters */ /* Data */ OMI_LI_READ(&li_min, cptr->xptr); if (OMI_MAX_DATA < li_min.value) { cptr->state = OMI_ST_CLOS; return -OMI_ER_SE_LENMIN; } OMI_LI_READ(&li_max, cptr->xptr); li_val = MIN(li_max.value, OMI_MAX_DATA); OMI_LI_WRIT(li_val, bptr); /* Subscript */ OMI_LI_READ(&li_min, cptr->xptr); if (OMI_MAX_SUBSCR < li_min.value) { cptr->state = OMI_ST_CLOS; return -OMI_ER_SE_LENMIN; } OMI_LI_READ(&li_max, cptr->xptr); li_val = MIN(li_max.value, OMI_MAX_SUBSCR); OMI_LI_WRIT(li_val, bptr); /* Reference */ OMI_LI_READ(&li_min, cptr->xptr); if (OMI_MAX_REF < li_min.value) { cptr->state = OMI_ST_CLOS; return -OMI_ER_SE_LENMIN; } OMI_LI_READ(&li_max, cptr->xptr); li_val = MIN(li_max.value, OMI_MAX_REF); OMI_LI_WRIT(li_val, bptr); /* Message */ OMI_LI_READ(&li_min, cptr->xptr); if (cptr->bsiz < li_min.value) { cptr->state = OMI_ST_CLOS; return -OMI_ER_SE_LENMIN; } OMI_LI_READ(&li_max, cptr->xptr); li_val = MIN(li_max.value, cptr->bsiz); OMI_LI_WRIT(li_val, bptr); /* Oustanding */ OMI_LI_READ(&li_min, cptr->xptr); if (1 < li_min.value) { cptr->state = OMI_ST_CLOS; return -OMI_ER_SE_LENMIN; } OMI_LI_READ(&li_max, cptr->xptr); li_val = MIN(li_max.value, 1); OMI_LI_WRIT(li_val, bptr); /* Other parameters */ OMI_SI_READ(&eightbit, cptr->xptr); OMI_SI_WRIT(eightbit.value, bptr); OMI_SI_READ(&chartran, cptr->xptr); OMI_SI_WRIT(chartran.value, bptr); /* Bounds checking */ if (cptr->xptr > xend || bptr >= bend) return -OMI_ER_PR_INVMSGFMT; /* Implementation ID (in) */ OMI_SI_READ(&ss_len, cptr->xptr); cptr->xptr += ss_len.value; /* Agent name (in) */ OMI_SI_READ(&ss_len, cptr->xptr); if ((ag_name = (char *) malloc(ss_len.value + 1)) == NULL) { OMI_DBG((omi_debug, "%s: memory allocation error (insufficient resources) while\n", SRVR_NAME)); OMI_DBG((omi_debug, "processing connect request from connection %d, %s.\n", cptr->stats.id, gtcm_hname(&cptr->stats.ai))); return -OMI_ER_DB_UNRECOVER; } assert(ss_len.value < MAX_USER_NAME && ss_len.value > 0); memcpy(ag_name, cptr->xptr, ss_len.value); ag_name[ss_len.value] = '\0'; strcpy(cptr->ag_name, ag_name); cptr->xptr += ss_len.value; /* Agent password (in) */ OMI_SI_READ(&ss_len, cptr->xptr); if ((ag_pass = (char *) malloc(ss_len.value + 1)) == NULL) { OMI_DBG((omi_debug, "%s: memory allocation error (insufficient resources) while\n", SRVR_NAME)); OMI_DBG((omi_debug, "processing connect request from connection %d, %s.\n", cptr->stats.id, gtcm_hname(&cptr->stats.ai))); return -OMI_ER_DB_UNRECOVER; } memcpy(ag_pass, cptr->xptr, ss_len.value); ag_pass[ss_len.value] = '\0'; cptr->xptr += ss_len.value; /* No support for authentication on SCO, Linux, Cygwin, or z/OS at the moment...*/ #if !(defined(SCO) || defined(__linux__) || defined(__CYGWIN__) || defined(__MVS__)) if (authenticate) /* verify password and user name */ { #ifdef SHADOWPW struct spwd *spass, *getspnam(); struct stat buf; #endif struct passwd *pass; char *pw, *syspw; /* lowercase agent name */ for(s = ag_name; *s; s++) if (ISUPPER_ASCII(*s)) *s = TOLOWER(*s); #ifdef SHADOWPW if (!Stat("/etc/shadow", &buf)) { if ((spass = getspnam(ag_name)) == NULL) { if (errno) { OMI_DBG((omi_debug, "%s: error opening /etc/shadow for input\n", SRVR_NAME, ag_name)); PERROR("/etc/shadow"); return -OMI_ER_DB_USERNOAUTH; } OMI_DBG((omi_debug, "%s: user %s not found in /etc/shadow\n", SRVR_NAME, ag_name)); return -OMI_ER_DB_USERNOAUTH; } syspw = spass->sp_pwdp; } else if ((pass = getpwnam(ag_name)) == NULL) { OMI_DBG((omi_debug, "%s: user %s not found in /etc/passwd\n", SRVR_NAME, ag_name)); return -OMI_ER_DB_USERNOAUTH; } else syspw = pass->pw_passwd; #else /* ndef SHADOWPW */ if ((pass = getpwnam(ag_name)) == NULL) { OMI_DBG((omi_debug, "%s: user %s not found in /etc/passwd\n", SRVR_NAME, ag_name)); return -OMI_ER_DB_USERNOAUTH; } else syspw = pass->pw_passwd; #endif /* SHADOWPW */ pw = (char *) crypt(ag_pass, syspw); if (strcmp(pw, syspw) != 0) { OMI_DBG((omi_debug, "%s: login attempt for user %s failed.\n", SRVR_NAME, ag_name)); return -OMI_ER_DB_USERNOAUTH; } } #endif /* SCO or linux or cygwin or z/OS */ /* Server name (in) */ OMI_SI_READ(&ss_len, cptr->xptr); cptr->xptr += ss_len.value; /* Implementation ID (out) */ len = SIZEOF(GTM_RELEASE_NAME) - 1; OMI_SI_WRIT(len, bptr); (void) memcpy(bptr, GTM_RELEASE_NAME, len); bptr += len; /* Server name (out) */ OMI_SI_WRIT(0, bptr); /* Server password (out) */ OMI_SI_WRIT(0, bptr); /* Bounds checking */ if (cptr->xptr > xend || bptr >= bend) return -OMI_ER_PR_INVMSGFMT; /* Extensions (in) -- count through them */ OMI_SI_READ(&ext_cnt, cptr->xptr); for (i = 0; i < ext_cnt.value; i++) { OMI_LI_READ(&ext, cptr->xptr); cptr->exts |= (1 << (ext.value - 1)); } /* Mask off extensions we don't support */ cptr->exts &= OMI_EXTENSIONS; /* Negotiate extension combinations */ if (cptr->exts & OMI_XTF_RC && cptr->exts & OMI_XTF_BUNCH) cptr->exts &= ~OMI_XTF_BUNCH; #ifdef GTCM_RC if (cptr->exts & OMI_XTF_RC) cptr->of = rc_oflow_alc(); #endif /* defined(GTCM_RC) */ /* Extensions (out) */ eptr = bptr; bptr += OMI_SI_SIZ; i = 0; if (cptr->exts & OMI_XTF_BUNCH) { OMI_LI_WRIT(OMI_XTN_BUNCH, bptr); i++; } if (cptr->exts & OMI_XTF_GGR) { OMI_LI_WRIT(OMI_XTN_GGR, bptr); i++; } if (cptr->exts & OMI_XTF_NEWOP) { OMI_LI_WRIT(OMI_XTN_NEWOP, bptr); i++; } if (cptr->exts & OMI_XTF_RC) { OMI_LI_WRIT(OMI_XTN_RC, bptr); i++; } /* Number of extensions */ OMI_SI_WRIT(i, eptr); /* Bounds checking */ if (cptr->xptr > xend || bptr >= bend) return -OMI_ER_PR_INVMSGFMT; /* Change the state of the connection */ cptr->state = OMI_ST_CONN; return (int)(bptr - buff); }
int gtcm_cn_acpt(omi_conn_ll *cll, int now) /* now --> current time in seconds */ { int i; omi_conn *cptr; omi_fd fd; int rc; char *tmp_time; #ifdef BSD_TCP GTM_SOCKLEN_TYPE sln; struct sockaddr_storage sas; int optsize; const boolean_t keepalive = TRUE; /* Accept the connection from the network layer */ sln = SIZEOF(sas); if ((fd = accept(cll->nve, (struct sockaddr *)&sas, (GTM_SOCKLEN_TYPE *)&sln)) < 0) return -1; #endif /* defined(BSD_TCP) */ /* Build the client data structure */ if (!(cptr = (omi_conn *)malloc(SIZEOF(omi_conn))) || !(cptr->buff = (char *)malloc(OMI_BUFSIZ))) { if (cptr) free(cptr); CLOSEFILE_RESET(fd, rc); /* resets "fd" to FD_INVALID */ return -1; } /* Initialize the connection structure */ cptr->next = (omi_conn *)0; cptr->fd = fd; cptr->ping_cnt = 0; cptr->timeout = now + conn_timeout; cptr->bsiz = OMI_BUFSIZ; cptr->bptr = cptr->buff; cptr->xptr = (char *)0; cptr->blen = 0; cptr->exts = 0; cptr->state = OMI_ST_DISC; cptr->ga = (ga_struct *)0; /* struct gd_addr_struct */ cptr->of = (oof_struct *) malloc(SIZEOF(struct rc_oflow)); memset(cptr->of, 0, SIZEOF(struct rc_oflow)); cptr->pklog = FD_INVALID; /* Initialize the statistics */ memcpy(&cptr->stats.sas, &sas, sln); cptr->stats.ai.ai_addr = (struct sockaddr *)&cptr->stats.sas; cptr->stats.ai.ai_addrlen = sln; cptr->stats.bytes_recv = 0; cptr->stats.bytes_send = 0; cptr->stats.start = time((time_t *)0); for (i = 0; i < OMI_OP_MAX; i++) cptr->stats.xact[i] = 0; for (i = 0; i < OMI_ER_MAX; i++) cptr->stats.errs[i] = 0; /* if we only allowing one connection per internet address, close any existing ones with the same addr. */ if (one_conn_per_inaddr) { omi_conn *this, *prev; for (prev = NULL, this = cll->head; this; prev = this, this = this->next) { if (0 == memcmp((sockaddr_ptr)(&this->stats.sas), (sockaddr_ptr)&sas, sln)) { if (cll->tail == this) cll->tail = cptr; if (prev) prev->next = cptr; else cll->head = cptr; cptr->next = this->next; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: dropping old connection to %s\n", SRVR_NAME, gtcm_hname(&cptr->stats.ai))); gtcm_cn_disc(this, cll); break; } } /* not found - add to the end of the list */ if (!this) { if (cll->tail) { cll->tail->next = cptr; cll->tail = cptr; } else cll->head = cll->tail = cptr; } } else { /* Insert the client into the list of connections */ if (cll->tail) { cll->tail->next = cptr; cll->tail = cptr; } else cll->head = cll->tail = cptr; } cptr->stats.id = ++cll->stats.conn; DEBUG_ONLY( if (omi_pklog) { int errno_save; char pklog[1024]; (void)SPRINTF(pklog, "%s.%04d", omi_pklog, cptr->stats.id); if (INV_FD_P((cptr->pklog = OPEN3(pklog, O_WRONLY|O_CREAT|O_APPEND|O_TRUNC, 0644)))) { errno_save = errno; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: unable to open packet log \"%s\"\n\t%s\n", SRVR_NAME, pklog, STRERROR(errno_save))); } } )
cll->head = cll->tail = cptr; } cptr->stats.id = ++cll->stats.conn; DEBUG_ONLY( if (omi_pklog) { int errno_save; char pklog[1024]; (void)SPRINTF(pklog, "%s.%04d", omi_pklog, cptr->stats.id); if (INV_FD_P((cptr->pklog = OPEN3(pklog, O_WRONLY|O_CREAT|O_APPEND|O_TRUNC, 0644)))) { errno_save = errno; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: unable to open packet log \"%s\"\n\t%s\n", SRVR_NAME, pklog, STRERROR(errno_save))); } } ) GTM_CTIME(tmp_time, &cptr->stats.start); OMI_DBG((omi_debug, "%s: connection %d from %s by user <%s> at %s", SRVR_NAME, cptr->stats.id, gtcm_hname(&cptr->stats.ai), cptr->ag_name, tmp_time)); if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive, SIZEOF(keepalive)) < 0) { PERROR("setsockopt:"); return -1; } return 0; }
cll->head = cll->tail = cptr; } cptr->stats.id = ++cll->stats.conn; DEBUG_ONLY( if (omi_pklog) { int errno_save; char pklog[1024]; (void)SPRINTF(pklog, "%s.%04d", omi_pklog, cptr->stats.id); if (INV_FD_P((cptr->pklog = OPEN3(pklog, O_WRONLY|O_CREAT|O_APPEND|O_TRUNC, 0644)))) { errno_save = errno; OMI_DBG_STMP; OMI_DBG((omi_debug, "%s: unable to open packet log \"%s\"\n\t%s\n", SRVR_NAME, pklog, STRERROR(errno_save))); } } ) OMI_DBG((omi_debug, "%s: connection %d from %s by user <%s> at %s", SRVR_NAME, cptr->stats.id, gtcm_hname(&cptr->stats.sin), cptr->ag_name, GTM_CTIME(&cptr->stats.start))); option = -1; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&option, SIZEOF(option)) < 0) { PERROR("setsockopt:"); return -1; } return 0; }