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;
}
Exemple #2
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);
}
Exemple #3
0
/*
 * 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);
}