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
/*
 ****************************************************************
 *	Obtém o número de bytes disponíveis para leitura	*
 ****************************************************************
 */
int
tcp_nread (int fd, int *pend)
{
	int	nbytes;

	nbytes = t_nread (fd);

	if (nbytes < 0)
	{	/*
		 *	Examina se foi desconexão.
		 */
		if (errno == TLOOK && t_look (fd) == T_ORDREL)
			errno = EPIPE, *pend = 0;
		else
			*pend = -1;

		return (-1);
	}

	*pend = nbytes;
	return (0);

}	/* end tcp_nread */
Exemple #3
0
/*
 * Called to read and interpret the event on a connectionless descriptor.
 * Returns 0 if successful, or a UNIX error code if failure.
 */
static int
do_poll_clts_action(int fd, int conn_index)
{
	int error;
	int ret;
	int flags;
	struct netconfig *nconf = &conn_polled[conn_index].nc;
	static struct t_unitdata *unitdata = NULL;
	static struct t_uderr *uderr = NULL;
	static int oldfd = -1;
	struct nd_hostservlist *host = NULL;
	struct strbuf ctl[1], data[1];
	/*
	 * We just need to have some space to consume the
	 * message in the event we can't use the TLI interface to do the
	 * job.
	 *
	 * We flush the message using getmsg(). For the control part
	 * we allocate enough for any TPI header plus 32 bytes for address
	 * and options. For the data part, there is nothing magic about
	 * the size of the array, but 256 bytes is probably better than
	 * 1 byte, and we don't expect any data portion anyway.
	 *
	 * If the array sizes are too small, we handle this because getmsg()
	 * (called to consume the message) will return MOREDATA|MORECTL.
	 * Thus we just call getmsg() until it's read the message.
	 */
	char ctlbuf[sizeof (union T_primitives) + 32];
	char databuf[256];

	/*
	 * If this is the same descriptor as the last time
	 * do_poll_clts_action was called, we can save some
	 * de-allocation and allocation.
	 */
	if (oldfd != fd) {
		oldfd = fd;

		if (unitdata) {
			(void) t_free((char *)unitdata, T_UNITDATA);
			unitdata = NULL;
		}
		if (uderr) {
			(void) t_free((char *)uderr, T_UDERROR);
			uderr = NULL;
		}
	}

	/*
	 * Allocate a unitdata structure for receiving the event.
	 */
	if (unitdata == NULL) {
		/* LINTED pointer alignment */
		unitdata = (struct t_unitdata *)t_alloc(fd, T_UNITDATA, T_ALL);
		if (unitdata == NULL) {
			if (t_errno == TSYSERR) {
				/*
				 * Save the error code across
				 * syslog(), just in case
				 * syslog() gets its own error
				 * and therefore overwrites errno.
				 */
				error = errno;
				(void) syslog(LOG_ERR,
	"t_alloc(file descriptor %d/transport %s, T_UNITDATA) failed: %m",
				    fd, nconf->nc_proto);
				return (error);
			}
			(void) syslog(LOG_ERR,
"t_alloc(file descriptor %d/transport %s, T_UNITDATA) failed TLI error %d",
			    fd, nconf->nc_proto, t_errno);
			goto flush_it;
		}
	}

try_again:
	flags = 0;

	/*
	 * The idea is we wait for T_UNITDATA_IND's. Of course,
	 * we don't get any, because rpcmod filters them out.
	 * However, we need to call t_rcvudata() to let TLI
	 * tell us we have a T_UDERROR_IND.
	 *
	 * algorithm is:
	 * 	t_rcvudata(), expecting TLOOK.
	 * 	t_look(), expecting T_UDERR.
	 * 	t_rcvuderr(), expecting success (0).
	 * 	expand destination address into ASCII,
	 *	and dump it.
	 */

	ret = t_rcvudata(fd, unitdata, &flags);
	if (ret == 0 || t_errno == TBUFOVFLW) {
		(void) syslog(LOG_WARNING,
"t_rcvudata(file descriptor %d/transport %s) got unexpected data, %d bytes",
		    fd, nconf->nc_proto, unitdata->udata.len);

		/*
		 * Even though we don't expect any data, in case we do,
		 * keep reading until there is no more.
		 */
		if (flags & T_MORE)
			goto try_again;

		return (0);
	}

	switch (t_errno) {
	case TNODATA:
		return (0);
	case TSYSERR:
		/*
		 * System errors are returned to caller.
		 * Save the error code across
		 * syslog(), just in case
		 * syslog() gets its own error
		 * and therefore overwrites errno.
		 */
		error = errno;
		(void) syslog(LOG_ERR,
		    "t_rcvudata(file descriptor %d/transport %s) %m",
		    fd, nconf->nc_proto);
		return (error);
	case TLOOK:
		break;
	default:
		(void) syslog(LOG_ERR,
		"t_rcvudata(file descriptor %d/transport %s) TLI error %d",
		    fd, nconf->nc_proto, t_errno);
		goto flush_it;
	}

	ret = t_look(fd);
	switch (ret) {
	case 0:
		return (0);
	case -1:
		/*
		 * System errors are returned to caller.
		 */
		if (t_errno == TSYSERR) {
			/*
			 * Save the error code across
			 * syslog(), just in case
			 * syslog() gets its own error
			 * and therefore overwrites errno.
			 */
			error = errno;
			(void) syslog(LOG_ERR,
			    "t_look(file descriptor %d/transport %s) %m",
			    fd, nconf->nc_proto);
			return (error);
		}
		(void) syslog(LOG_ERR,
		    "t_look(file descriptor %d/transport %s) TLI error %d",
		    fd, nconf->nc_proto, t_errno);
		goto flush_it;
	case T_UDERR:
		break;
	default:
		(void) syslog(LOG_WARNING,
	"t_look(file descriptor %d/transport %s) returned %d not T_UDERR (%d)",
		    fd, nconf->nc_proto, ret, T_UDERR);
	}

	if (uderr == NULL) {
		/* LINTED pointer alignment */
		uderr = (struct t_uderr *)t_alloc(fd, T_UDERROR, T_ALL);
		if (uderr == NULL) {
			if (t_errno == TSYSERR) {
				/*
				 * Save the error code across
				 * syslog(), just in case
				 * syslog() gets its own error
				 * and therefore overwrites errno.
				 */
				error = errno;
				(void) syslog(LOG_ERR,
	"t_alloc(file descriptor %d/transport %s, T_UDERROR) failed: %m",
				    fd, nconf->nc_proto);
				return (error);
			}
			(void) syslog(LOG_ERR,
"t_alloc(file descriptor %d/transport %s, T_UDERROR) failed TLI error: %d",
			    fd, nconf->nc_proto, t_errno);
			goto flush_it;
		}
	}

	ret = t_rcvuderr(fd, uderr);
	if (ret == 0) {

		/*
		 * Save the datagram error in errno, so that the
		 * %m argument to syslog picks up the error string.
		 */
		errno = uderr->error;

		/*
		 * Log the datagram error, then log the host that
		 * probably triggerred. Cannot log both in the
		 * same transaction because of packet size limitations
		 * in /dev/log.
		 */
		(void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING,
"NFS response over <file descriptor %d/transport %s> generated error: %m",
		    fd, nconf->nc_proto);

		/*
		 * Try to map the client's address back to a
		 * name.
		 */
		ret = netdir_getbyaddr(nconf, &host, &uderr->addr);
		if (ret != -1 && host && host->h_cnt > 0 &&
		    host->h_hostservs) {
		(void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING,
"Bad NFS response was sent to client with host name: %s; service port: %s",
		    host->h_hostservs->h_host,
		    host->h_hostservs->h_serv);
		} else {
			int i, j;
			char *buf;
			char *hex = "0123456789abcdef";

			/*
			 * Mapping failed, print the whole thing
			 * in ASCII hex.
			 */
			buf = (char *)malloc(uderr->addr.len * 2 + 1);
			for (i = 0, j = 0; i < uderr->addr.len; i++, j += 2) {
				buf[j] = hex[((uderr->addr.buf[i]) >> 4) & 0xf];
				buf[j+1] = hex[uderr->addr.buf[i] & 0xf];
			}
			buf[j] = '\0';
		(void) syslog((errno == ECONNREFUSED) ? LOG_DEBUG : LOG_WARNING,
	"Bad NFS response was sent to client with transport address: 0x%s",
		    buf);
			free((void *)buf);
		}

		if (ret == 0 && host != NULL)
			netdir_free((void *)host, ND_HOSTSERVLIST);
		return (0);
	}
Exemple #4
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);
}