static int TRANS(TLIConnect)(XtransConnInfo ciptr, struct t_call *sndcall ) { prmsg(2, "TLIConnect(%x->%d,%x)\n", ciptr, ciptr->fd, sndcall); if( t_connect(ciptr->fd,sndcall,NULL) < 0 ) { extern char *t_errlist[]; extern int t_errno; prmsg(1, "TLIConnect() t_connect() failed\n"); prmsg(1, "TLIConnect: %s\n", t_errlist[t_errno]); t_free((char *)sndcall,T_CALL); if (t_errno == TLOOK && t_look(ciptr->fd) == T_DISCONNECT) { t_rcvdis(ciptr->fd,NULL); return TRANS_TRY_CONNECT_AGAIN; } else return TRANS_CONNECT_FAILED; } t_free((char *)sndcall,T_CALL); /* * Sync up the address fields of ciptr. */ if( TRANS(TLIGetAddr)(ciptr) < 0 ) { prmsg(1, "TLIConnect: ...TLIGetAddr() failed: %d\n", errno); return TRANS_CONNECT_FAILED; } if( TRANS(TLIGetPeerAddr)(ciptr) < 0 ) { prmsg(1, "TLIConnect: ...TLIGetPeerAddr() failed: %d\n", errno); return TRANS_CONNECT_FAILED; } if( ioctl(ciptr->fd, I_POP,"timod") < 0 ) { prmsg(1, "TLIConnect() ioctl(I_POP,\"timod\") failed %d\n", errno); return TRANS_CONNECT_FAILED; } if( ioctl(ciptr->fd, I_PUSH,"tirdwr") < 0 ) { prmsg(1, "TLIConnect() ioctl(I_PUSH,\"tirdwr\") failed %d\n", errno); return TRANS_CONNECT_FAILED; } return 0; }
int accept_client(int fd, struct t_call *call) { int sd; if ((sd = t_open(DEV_XTI, O_RDWR, NULL)) < 0) error("serwer->accept_client->t_open", fd, sd); if (t_bind(sd, NULL, NULL) < 0) error("serwer->accept_client->t_bind", fd, sd); if (t_accept(fd, sd, call) < 0) { if (t_errno == TLOOK) { if (t_rcvdis(fd, NULL) < 0) error("serwer->accept_client->t_rcvdis", fd, sd); if (t_close(sd) < 0) error("serwer->accept_client->t_close", fd, sd); return -1; } error("t_accept failed", fd, sd); } return(sd); }
/* * Handle a TLOOK notification received during a t_accept() call. * Returns -1 on failure, else 0. */ static int process_tlook(const char *fmri, tlx_info_t *tlx_info) { int event; int fd = tlx_info->pr_info.listen_fd; debug_msg("Entering process_tlook:"); switch (event = t_look(fd)) { case T_LISTEN: { struct t_call *call; debug_msg("process_tlook: T_LISTEN event"); if ((call = get_new_conind(fd)) == NULL) return (-1); if (queue_conind(tlx_info->conn_ind_queue, call) == -1) { error_msg(gettext("Failed to queue connection " "indication for instance %s"), fmri); (void) t_free((char *)call, T_CALL); return (-1); } break; } case T_DISCONNECT: { /* * Note: In Solaris 2.X (SunOS 5.X) bundled * connection-oriented transport drivers * [ e.g /dev/tcp and /dev/ticots and * /dev/ticotsord (tl)] we do not send disconnect * indications to listening endpoints. * So this will not be seen with endpoints on Solaris * bundled transport devices. However, Streams TPI * allows for this (broken?) behavior and so we account * for it here because of the possibility of unbundled * transport drivers causing this. */ tlx_conn_ind_t *cip; struct t_discon *discon; debug_msg("process_tlook: T_DISCONNECT event"); /* LINTED */ if ((discon = (struct t_discon *) t_alloc(fd, T_DIS, T_ALL)) == NULL) { error_msg("t_alloc: %s", t_strerror(t_errno)); return (-1); } if (t_rcvdis(fd, discon) < 0) { error_msg("t_rcvdis: %s", t_strerror(t_errno)); (void) t_free((char *)discon, T_DIS); return (-1); } /* * Find any queued connection pending that matches this * disconnect notice and remove from the pending queue. */ cip = uu_list_first(tlx_info->conn_ind_queue); while ((cip != NULL) && (cip->call->sequence != discon->sequence)) { cip = uu_list_next(tlx_info->conn_ind_queue, cip); } if (cip != NULL) { /* match found */ uu_list_remove(tlx_info->conn_ind_queue, cip); (void) t_free((char *)cip->call, T_CALL); free(cip); } (void) t_free((char *)discon, T_DIS); break; } case -1: error_msg("t_look: %s", t_errno); return (-1); default: error_msg(gettext("do_tlook: unexpected t_look event: %d"), event); return (-1); } return (0); }
static XtransConnInfo TRANS(TLIAccept)(XtransConnInfo ciptr, int *status) { struct t_call *call; XtransConnInfo newciptr; int i; prmsg(2,"TLIAccept(%x->%d)\n", ciptr, ciptr->fd); if( (call=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_ALL)) == NULL ) { prmsg(1, "TLIAccept() failed to allocate a t_call\n"); *status = TRANS_ACCEPT_BAD_MALLOC; return NULL; } if( t_listen(ciptr->fd,call) < 0 ) { extern char *t_errlist[]; extern int t_errno; prmsg(1, "TLIAccept() t_listen() failed\n"); prmsg(1, "TLIAccept: %s\n", t_errlist[t_errno]); t_free((char *)call,T_CALL); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } /* * Now we need to set up the new endpoint for the incoming connection. */ i=ciptr->index; /* Makes the next line more readable */ if( (newciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL ) { prmsg(1, "TLIAccept() failed to open a new endpoint\n"); t_free((char *)call,T_CALL); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( TRANS(TLITLIBindLocal)(newciptr->fd,TLItrans2devtab[i].family,"") < 0 ) { prmsg(1, "TLIAccept: TRANS(TLITLIBindLocal)() failed: %d\n", errno); t_free((char *)call,T_CALL); t_close(newciptr->fd); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( t_accept(ciptr->fd,newciptr->fd,call) < 0 ) { extern char *t_errlist[]; extern int t_errno; prmsg(1, "TLIAccept() t_accept() failed\n"); prmsg(1, "TLIAccept: %s\n", t_errlist[t_errno]); if( t_errno == TLOOK ) { int evtype = t_look(ciptr->fd); prmsg(1, "TLIAccept() t_look() returned %d\n", evtype); switch( evtype ) { case T_DISCONNECT: if( t_rcvdis(ciptr->fd, NULL) < 0 ) { prmsg(1, "TLIAccept() t_rcvdis() failed\n"); prmsg(1, "TLIAccept: %s\n", t_errlist[t_errno]); } break; default: break; } } t_free((char *)call,T_CALL); t_close(newciptr->fd); free(newciptr); *status = TRANS_ACCEPT_FAILED; return NULL; } t_free((char *)call,T_CALL); if( TRANS(TLIGetAddr)(newciptr) < 0 ) { prmsg(1, "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n", errno); t_close(newciptr->fd); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( TRANS(TLIGetPeerAddr)(newciptr) < 0 ) { prmsg(1, "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n", errno); t_close(newciptr->fd); free(newciptr->addr); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( ioctl(newciptr->fd, I_POP,"timod") < 0 ) { prmsg(1, "TLIAccept() ioctl(I_POP, \"timod\") failed %d\n", errno); t_close(newciptr->fd); free(newciptr->addr); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } if( ioctl(newciptr->fd, I_PUSH,"tirdwr") < 0 ) { prmsg(1, "TLIAccept() ioctl(I_PUSH,\"tirdwr\") failed %d\n", errno); t_close(newciptr->fd); free(newciptr->addr); free(newciptr); *status = TRANS_ACCEPT_MISC_ERROR; return NULL; } *status = 0; return newciptr; }
int tcp_connect(const char *host, const char *serv) { int tfd, i; void *handle; struct t_call tcall; struct t_discon tdiscon; struct netconfig *ncp; struct nd_hostserv hs; struct nd_addrlist *alp; struct netbuf *np; struct t_opthdr *topt; handle = Setnetpath(); hs.h_host = (char *) host; hs.h_serv = (char *) serv; while ( (ncp = getnetpath(handle)) != NULL) { if (strcmp(ncp->nc_proto, "tcp") != 0) continue; if (netdir_getbyname(ncp, &hs, &alp) != 0) continue; /* try each server address */ for (i = 0, np = alp->n_addrs; i < alp->n_cnt; i++, np++) { tfd = T_open(ncp->nc_device, O_RDWR, NULL); T_bind(tfd, NULL, NULL); tcall.addr.len = np->len; tcall.addr.buf = np->buf; /* pointer copy */ tcall.opt.len = 0; /* no options */ tcall.udata.len = 0; /* no user data with connect */ if (t_connect(tfd, &tcall, NULL) == 0) { endnetpath(handle); /* success, connected to server */ netdir_free(alp, ND_ADDRLIST); req = T_alloc(fd, T_OPTMGMT, T_ALL); ret = T_alloc(fd, T_OPTMGMT, T_ALL); topt = (struct t_opthdr *) req->opt.buf; topt->level = T_INET_TCP; topt->name = T_TCP_MAXSEG; topt->len = sizeof(struct t_opthdr) + sizeof(u_long); req->opt.len = topt->len; topt = OPT_NEXTHDR(req->opt.buf, req->opt.maxlen, topt); topt->level = XTI_GENERIC; topt->name = XTI_SNDBUF; topt->len = sizeof(struct t_opthdr) + sizeof(u_long); req->opt.len += topt->len; return(tfd); } if (t_errno == TLOOK && t_look(tfd) == T_DISCONNECT) { t_rcvdis(tfd, &tdiscon); errno = tdiscon.reason; } t_close(tfd); } netdir_free(alp, ND_ADDRLIST); } endnetpath(handle); return(-1); }