Пример #1
0
int main(int argc, char *argv[] )
{
    int length, i;
    char sendbuffer[4096] ;
	int			tfd;
	struct t_call		*callptr;
	struct sockaddr_in	serv_addr;

	pname = argv[0];

	/*
	 * Create a TCP transport endpoint and bind it.
	 */

	if ( (tfd = t_open(DEV_TCP, O_RDWR, 0)) < 0)
    {
		printf("client: can't t_open %s........\n", DEV_TCP);
        exit(1);
     }

	if (t_bind(tfd, (struct t_bind *) 0, (struct t_bind *) 0) < 0)
    {
		printf("client: t_bind error.....\n");
        exit(1);
     }

	/*
	 * Fill in the structure "serv_addr" with the address of the
	 * server that we want to connect with.
	 */

	bzero((char *) &serv_addr, sizeof(serv_addr));
	serv_addr.sin_family      = AF_INET;
	serv_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR);
	serv_addr.sin_port        = htons(SERV_TCP_PORT);

	/*
	 * Allocate a t_call structure, and initialize it.
	 * Let t_alloc() initialize the addr structure of the t_call structure.
	 */

	if ( (callptr = (struct t_call *) t_alloc(tfd, T_CALL, T_ADDR)) == NULL)
    {
		printf("client: t_alloc error.......\n");
    }
	callptr->addr.maxlen = sizeof(serv_addr);
	callptr->addr.len    = sizeof(serv_addr);
	callptr->addr.buf    = (char *) &serv_addr;
	callptr->opt.len     = 0;		/* no options */
	callptr->udata.len   = 0;		/* no user data with connect */

    /* get raw usage data */
    if(get_raw_usage_data(sendbuffer, length) != FALSE)
    {
	   process_client_service(tfd, callptr, sendbuffer, length);

    }

    if(*sendbuffer)
         free(sendbuffer);

	close(tfd);
	exit(1);
}
Пример #2
0
p_stack stack_new() {
	p_stack ret;
	ret = (p_stack)t_alloc( sizeof( s_stack ) );
	ret->top = NULL;
	return ret;
}
Пример #3
0
int
nfslib_bindit(struct netconfig *nconf, struct netbuf **addr,
	struct nd_hostserv *hs, int backlog)
{
	int fd;
	struct t_bind  *ntb;
	struct t_bind tb;
	struct nd_addrlist *addrlist;
	struct t_optmgmt req, resp;
	struct opthdr *opt;
	char reqbuf[128];
	bool_t use_any = FALSE;
	bool_t gzone = TRUE;

	if ((fd = nfslib_transport_open(nconf)) == -1) {
		syslog(LOG_ERR, "cannot establish transport service over %s",
			nconf->nc_device);
		return (-1);
	}

	addrlist = (struct nd_addrlist *)NULL;

	/* nfs4_callback service does not used a fieed port number */

	if (strcmp(hs->h_serv, "nfs4_callback") == 0) {
		tb.addr.maxlen = 0;
		tb.addr.len = 0;
		tb.addr.buf = 0;
		use_any = TRUE;
		gzone = (getzoneid() == GLOBAL_ZONEID);
	} else if (netdir_getbyname(nconf, hs, &addrlist) != 0) {

		syslog(LOG_ERR,
		"Cannot get address for transport %s host %s service %s",
			nconf->nc_netid, hs->h_host, hs->h_serv);
		(void) t_close(fd);
		return (-1);
	}

	if (strcmp(nconf->nc_proto, "tcp") == 0) {
		/*
		 * If we're running over TCP, then set the
		 * SO_REUSEADDR option so that we can bind
		 * to our preferred address even if previously
		 * left connections exist in FIN_WAIT states.
		 * This is somewhat bogus, but otherwise you have
		 * to wait 2 minutes to restart after killing it.
		 */
		if (reuseaddr(fd) == -1) {
			syslog(LOG_WARNING,
			"couldn't set SO_REUSEADDR option on transport");
		}
	} else if (strcmp(nconf->nc_proto, "udp") == 0) {
		/*
		 * In order to run MLP on UDP, we need to handle creds.
		 */
		if (recvucred(fd) == -1) {
			syslog(LOG_WARNING,
			    "couldn't set SO_RECVUCRED option on transport");
		}
	}

	/*
	 * Make non global zone nfs4_callback port MLP
	 */
	if (use_any && is_system_labeled() && !gzone) {
		if (anonmlp(fd) == -1) {
			/*
			 * failing to set this option means nfs4_callback
			 * could fail silently later. So fail it with
			 * with an error message now.
			 */
			syslog(LOG_ERR,
			    "couldn't set SO_ANON_MLP option on transport");
			(void) t_close(fd);
			return (-1);
		}
	}

	if (nconf->nc_semantics == NC_TPI_CLTS)
		tb.qlen = 0;
	else
		tb.qlen = backlog;

	/* LINTED pointer alignment */
	ntb = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL);
	if (ntb == (struct t_bind *)NULL) {
		syslog(LOG_ERR, "t_alloc failed:  t_errno %d, %m", t_errno);
		(void) t_close(fd);
		netdir_free((void *)addrlist, ND_ADDRLIST);
		return (-1);
	}

	/*
	 * XXX - what about the space tb->addr.buf points to? This should
	 * be either a memcpy() to/from the buf fields, or t_alloc(fd,T_BIND,)
	 * should't be called with T_ALL.
	 */
	if (addrlist)
		tb.addr = *(addrlist->n_addrs);		/* structure copy */

	if (t_bind(fd, &tb, ntb) == -1) {
		syslog(LOG_ERR, "t_bind failed:  t_errno %d, %m", t_errno);
		(void) t_free((char *)ntb, T_BIND);
		netdir_free((void *)addrlist, ND_ADDRLIST);
		(void) t_close(fd);
		return (-1);
	}

	/* make sure we bound to the right address */
	if (use_any == FALSE &&
	    (tb.addr.len != ntb->addr.len ||
	    memcmp(tb.addr.buf, ntb->addr.buf, tb.addr.len) != 0)) {
		syslog(LOG_ERR, "t_bind to wrong address");
		(void) t_free((char *)ntb, T_BIND);
		netdir_free((void *)addrlist, ND_ADDRLIST);
		(void) t_close(fd);
		return (-1);
	}

	/*
	 * Call nfs4svc_setport so that the kernel can be
	 * informed what port number the daemon is listing
	 * for incoming connection requests.
	 */

	if ((nconf->nc_semantics == NC_TPI_COTS ||
	    nconf->nc_semantics == NC_TPI_COTS_ORD) && Mysvc4 != NULL)
		(*Mysvc4)(fd, NULL, nconf, NFS4_SETPORT, &ntb->addr);

	*addr = &ntb->addr;
	netdir_free((void *)addrlist, ND_ADDRLIST);

	if (strcmp(nconf->nc_proto, "tcp") == 0) {
		/*
		 * Disable the Nagle algorithm on TCP connections.
		 * Connections accepted from this listener will
		 * inherit the listener options.
		 */

		/* LINTED pointer alignment */
		opt = (struct opthdr *)reqbuf;
		opt->level = IPPROTO_TCP;
		opt->name = TCP_NODELAY;
		opt->len = sizeof (int);

		/* LINTED pointer alignment */
		*(int *)((char *)opt + sizeof (*opt)) = 1;

		req.flags = T_NEGOTIATE;
		req.opt.len = sizeof (*opt) + opt->len;
		req.opt.buf = (char *)opt;
		resp.flags = 0;
		resp.opt.buf = reqbuf;
		resp.opt.maxlen = sizeof (reqbuf);

		if (t_optmgmt(fd, &req, &resp) < 0 ||
				resp.flags != T_SUCCESS) {
			syslog(LOG_ERR,
	"couldn't set NODELAY option for proto %s: t_errno = %d, %m",
				nconf->nc_proto, t_errno);
		}
	}

	return (fd);
}
Пример #4
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);
	}
Пример #5
0
static int
TRANS(TLITLIBindLocal)(int fd, int family, char *port)

{
    struct sockaddr_un	*sunaddr=NULL;
    struct t_bind	*req=NULL;

    prmsg(2, "TLITLIBindLocal(%d,%d,%s)\n", fd, family, port);

    if( family == AF_UNIX )
    {
	if( (req=(struct t_bind *)t_alloc(fd,T_BIND,0)) == NULL )
	{
	    prmsg(1,
		  "TLITLIBindLocal() failed to allocate a t_bind\n");
	    return -1;
	}

	if( (sunaddr=(struct sockaddr_un *)
	     malloc(sizeof(struct sockaddr_un))) == NULL )
	{
	    prmsg(1,
		  "TLITLIBindLocal: failed to allocate a sockaddr_un\n");
	    t_free((char *)req,T_BIND);
	    return -1;
	}

	sunaddr->sun_family=AF_UNIX;

#ifdef nuke
	if( *port == '/' ) { /* A full pathname */
	    (void) strcpy(sunaddr->sun_path, port);
	} else {
	    (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
	}
#endif /*NUKE*/

	(void) sprintf(sunaddr->sun_path,"%s%d",
		       TLINODENAME, getpid()^time(NULL) );

	prmsg(4, "TLITLIBindLocal: binding to %s\n",
	      sunaddr->sun_path);

	req->addr.buf=(char *)sunaddr;
	req->addr.len=sizeof(*sunaddr);
	req->addr.maxlen=sizeof(*sunaddr);
    }

    if( t_bind(fd, req, NULL) < 0 )
    {
	prmsg(1,
	      "TLIBindLocal: Unable to bind TLI device to %s\n",
	      port);
	if (sunaddr)
	    free((char *) sunaddr);
	if (req)
	    t_free((char *)req,T_BIND);
	return -1;
    }
    return 0;
}
Пример #6
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;
}
Пример #7
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) */
}
Пример #8
0
/*
 * How to bind to reserved ports.
 * (port-only) version.
 */
int
bind_resv_port2(u_short *pp)
{
  int td, rc = -1, port;
  struct t_bind *treq, *tret;
  struct sockaddr_in *sin;
  extern char *t_errlist[];
  extern int t_errno;
  struct netconfig *nc = (struct netconfig *) NULL;
  voidp nc_handle;

  if ((nc_handle = setnetconfig()) == (voidp) NULL) {
    plog(XLOG_ERROR, "Cannot rewind netconfig: %s", nc_sperror());
    return -1;
  }
  /*
   * Search the netconfig table for INET/UDP.
   * This loop will terminate if there was an error in the /etc/netconfig
   * file or if you reached the end of the file without finding the udp
   * device.  Either way your machine has probably far more problems (for
   * example, you cannot have nfs v2 w/o UDP).
   */
  while (1) {
    if ((nc = getnetconfig(nc_handle)) == (struct netconfig *) NULL) {
      plog(XLOG_ERROR, "Error accessing getnetconfig: %s", nc_sperror());
      endnetconfig(nc_handle);
      return -1;
    }
    if (STREQ(nc->nc_protofmly, NC_INET) &&
	STREQ(nc->nc_proto, NC_UDP))
      break;
  }

  /*
   * This is the primary reason for the getnetconfig code above: to get the
   * correct device name to udp, and t_open a descriptor to be used in
   * t_bind below.
   */
  td = t_open(nc->nc_device, O_RDWR, (struct t_info *) 0);
  endnetconfig(nc_handle);

  if (td < 0) {
    plog(XLOG_ERROR, "t_open failed: %d: %s", t_errno, t_errlist[t_errno]);
    return -1;
  }
  treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
  if (!treq) {
    plog(XLOG_ERROR, "t_alloc req");
    return -1;
  }
  tret = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
  if (!tret) {
    t_free((char *) treq, T_BIND);
    plog(XLOG_ERROR, "t_alloc ret");
    return -1;
  }
  memset((char *) treq->addr.buf, 0, treq->addr.len);
  sin = (struct sockaddr_in *) treq->addr.buf;
  sin->sin_family = AF_INET;
  treq->qlen = 0;
  treq->addr.len = treq->addr.maxlen;
  errno = EADDRINUSE;
  port = IPPORT_RESERVED;

  do {
    --port;
    sin->sin_port = htons(port);
    rc = t_bind(td, treq, tret);
    if (rc < 0) {
      plog(XLOG_ERROR, "t_bind for port %d: %s", port, t_errlist[t_errno]);
    } else {
      if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0)
	break;
      else
	t_unbind(td);
    }
  } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2);

  if (pp && rc == 0)
    *pp = port;
  t_free((char *) tret, T_BIND);
  t_free((char *) treq, T_BIND);
  return rc;
}
Пример #9
0
enum error
proto_make_listener(Var desc, int *fd, Var * canon, const char **name)
{
    struct sockaddr_in req_addr, rec_addr;
    struct t_bind requested, received;
    int s, port;
    static Stream *st = 0;

    if (!st)
	st = new_stream(20);

    if (desc.type != TYPE_INT)
	return E_TYPE;

    port = desc.v.num;
    s = t_open((void *) "/dev/tcp", O_RDWR, 0);
    if (s < 0) {
	log_ti_error("Creating listening endpoint");
	return E_QUOTA;
    }
    req_addr.sin_family = AF_INET;
    req_addr.sin_addr.s_addr = bind_local_ip;
    req_addr.sin_port = htons(port);

    requested.addr.maxlen = sizeof(req_addr);
    requested.addr.len = sizeof(req_addr);
    requested.addr.buf = (void *) &req_addr;
    requested.qlen = 5;

    received.addr.maxlen = sizeof(rec_addr);
    received.addr.len = sizeof(rec_addr);
    received.addr.buf = (void *) &rec_addr;

    if (t_bind(s, &requested, &received) < 0) {
	enum error e = E_QUOTA;

	log_ti_error("Binding to listening address");
	t_close(s);
	if (t_errno == TACCES || (t_errno == TSYSERR && errno == EACCES))
	    e = E_PERM;
	return e;
    } else if (port != 0 && rec_addr.sin_port != htons(port)) {
	errlog("Can't bind to requested port!\n");
	t_close(s);
	return E_QUOTA;
    }
    if (!call)
	call = (struct t_call *) t_alloc(s, T_CALL, T_ADDR);
    if (!call) {
	log_ti_error("Allocating T_CALL structure");
	t_close(s);
	return E_QUOTA;
    }
    canon->type = TYPE_INT;
    canon->v.num = ntohs(rec_addr.sin_port);

    stream_printf(st, "port %d", canon->v.num);
    *name = reset_stream(st);

    *fd = s;
    return E_NONE;
}
Пример #10
0
/*
 * Bind a fd to a privileged IP port.
 * This is slightly different from the code in netdir_options
 * because it has a different interface - main thing is that it
 * needs to know its own address.  We also wanted to set the qlen.
 * t_getname() can be used for those purposes and perhaps job can be done.
 */
int
__rpc_bindresvport_ipv6(int fd, struct sockaddr *sin, int *portp, int qlen,
			char *fmly)
{
	int res;
	static in_port_t port, *sinport;
	struct sockaddr_in6 myaddr;
	int i;
	struct t_bind tbindstr, *tres;
	struct t_info tinfo;
	extern mutex_t portnum_lock;

	/* VARIABLES PROTECTED BY portnum_lock: port */

#define	STARTPORT 600
#define	ENDPORT (IPPORT_RESERVED - 1)
#define	NPORTS	(ENDPORT - STARTPORT + 1)

	if (sin == 0 && fmly == 0) {
		errno = EINVAL;
		return (-1);
	}
	if (geteuid()) {
		errno = EACCES;
		return (-1);
	}
	if ((i = t_getstate(fd)) != T_UNBND) {
		if (t_errno == TBADF)
			errno = EBADF;
		if (i != -1)
			errno = EISCONN;
		return (-1);
	}
	if (sin == 0) {
		sin = (struct sockaddr *)&myaddr;
		get_myaddress_ipv6(fmly, sin);
	}
	if (sin->sa_family == AF_INET) {
		/* LINTED pointer cast */
		sinport = &((struct sockaddr_in *)sin)->sin_port;
	} else if (sin->sa_family == AF_INET6) {
		/* LINTED pointer cast */
		sinport = &((struct sockaddr_in6 *)sin)->sin6_port;
	} else {
		errno = EPFNOSUPPORT;
		return (-1);
	}

	/* Transform sockaddr to netbuf */
	if (t_getinfo(fd, &tinfo) == -1) {
		return (-1);
	}
	/* LINTED pointer cast */
	tres = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR);
	if (tres == NULL)
		return (-1);

	tbindstr.qlen = qlen;
	tbindstr.addr.buf = (char *)sin;
	tbindstr.addr.len = tbindstr.addr.maxlen = __rpc_get_a_size(tinfo.addr);
	/* LINTED pointer cast */
	sin = (struct sockaddr *)tbindstr.addr.buf;

	res = -1;
	(void) mutex_lock(&portnum_lock);
	if (port == 0)
		port = (getpid() % NPORTS) + STARTPORT;
	for (i = 0; i < NPORTS; i++) {
		*sinport = htons(port++);
		if (port > ENDPORT)
			port = STARTPORT;
		res = t_bind(fd, &tbindstr, tres);
		if (res == 0) {
			if ((tbindstr.addr.len == tres->addr.len) &&
				(memcmp(tbindstr.addr.buf, tres->addr.buf,
					(int)tres->addr.len) == 0))
				break;
			(void) t_unbind(fd);
			res = -1;
		} else if (t_errno != TSYSERR || errno != EADDRINUSE)
			break;
	}
	(void) mutex_unlock(&portnum_lock);

	if ((portp != NULL) && (res == 0))
		*portp = *sinport;
	(void) t_free((char *)tres, T_BIND);
	return (res);
}
Пример #11
0
void dfa_to_table( const p_dfa pa, int** weight_list, int *weight_size, int** state_table, int *state_size ) {
	p_nodelist pnl;
	p_node pn;
	p_edgelist pel;
	p_edge pe;
	int weight_map[256];
	int i, j;

	for (i = 0; i < 256; i ++) weight_map[i] = 0;
	j = 1;
	*state_size = 0;

	pnl = pa->pnl_f;
	while (pnl != NULL) {
		pn = pnl->element;
		pel = pn->pel_f;
		while (pel != NULL) {
			pe = pel->element;
			weight_map[pe->weight] = 1; 
			pel = pel->next;
		}
		pnl = pnl->next;
		(*state_size) ++;
	}

	for (i = 0, j = 1; i < 256; i ++) {
		if (weight_map[i] == 1) weight_map[i] = j++;
	}

	*weight_size = j;
	*weight_list = (int*)t_alloc( sizeof(int)*(*weight_size) );
	(*weight_list)[0] = 0;
	for (i = 0; i < 256; i ++) {
		if (weight_map[i] > 0) {
			(*weight_list)[weight_map[i]] = i;
		}
	}

	*state_table = (int*)t_alloc( sizeof(int) * ((*state_size) * (*weight_size) ) );

	for (i = 0; i < (*state_size)*(*weight_size); i ++) (*state_table)[i] = 0;

	i = 0;
	pnl = pa->pnl_f;
	while (pnl != NULL) {
		pn = pnl->element;

		(*state_table)[i * (*weight_size) + 0] = pn->id;
		pel = pn->pel_f;
		while (pel != NULL) {
			pe = pel->element;
			(*state_table)[i * (*weight_size) + weight_map[pe->weight]] = pe->dest->id;
			pel = pel->next;
		}

		i++;
		pnl = pnl->next;
	}

	/* dump the id */
	/*
	id_map = (int*)t_alloc( sizeof(int)*state_size );
	i = 0;
	pnl = pa->pnl_f;
	while (pnl != NULL) {
		id_map[i++] = pnl->element->id;
		pnl = pnl->next;
	}

	t_free( id_map );
	*/
}
Пример #12
0
static int
get_tcp_socket(
	char *machine,		/* remote host */
	char *service,		/* nttp/smtp etc. */
	unsigned short port)	/* tcp port number */
{
	int s = -1;
	int save_errno = 0;
	struct sockaddr_in sock_in;
#	ifdef TLI /* Transport Level Interface */
	char device[20];
	char *env_device;
	extern int t_errno;
	extern struct hostent *gethostbyname();
	struct hostent *hp;
	struct t_call *callptr;

	/*
	 * Create a TCP transport endpoint.
	 */
	if ((env_device = getenv("DEV_TCP")) != NULL) /* SCO uses DEV_TCP, most other OS use /dev/tcp */
		STRCPY(device, env_device);
	else
		strcpy(device, "/dev/tcp");

	if ((s = t_open(device, O_RDWR, (struct t_info *) 0)) < 0){
		t_error(txt_error_topen);
		return -EPROTO;
	}
	if (t_bind(s, (struct t_bind *) 0, (struct t_bind *) 0) < 0) {
		t_error("t_bind");
		t_close(s);
		return -EPROTO;
	}
	memset((char *) &sock_in, '\0', sizeof(sock_in));
	sock_in.sin_family = AF_INET;
	sock_in.sin_port = htons(port);

	if (!isdigit((unsigned char)*machine) ||
#		ifdef HAVE_INET_ATON
	    !inet_aton(machine, &sock_in)
#		else
#			ifdef HAVE_INET_ADDR
	    (long) (sock_in.sin_addr.s_addr = inet_addr(machine)) == INADDR_NONE)
#			endif /* HAVE_INET_ADDR */
#		endif /* HAVE_INET_ATON */
	{
		if ((hp = gethostbyname(machine)) == NULL) {
			my_fprintf(stderr, _(txt_gethostbyname), "gethostbyname() ", machine);
			t_close(s);
			return -EHOSTUNREACH;
		}
		memcpy((char *) &sock_in.sin_addr, hp->h_addr, hp->h_length);
	}

	/*
	 * Allocate a t_call structure and initialize it.
	 * Let t_alloc() initialize the addr structure of the t_call structure.
	 */
	if ((callptr = (struct t_call *) t_alloc(s, T_CALL, T_ADDR)) == NULL){
		t_error("t_alloc");
		t_close(s);
		return -EPROTO;
	}

	callptr->addr.maxlen = sizeof(sock_in);
	callptr->addr.len = sizeof(sock_in);
	callptr->addr.buf = (char *) &sock_in;
	callptr->opt.len = 0;			/* no options */
	callptr->udata.len = 0;			/* no user data with connect */

	/*
	 * Connect to the server.
	 */
	if (t_connect(s, callptr, (struct t_call *) 0) < 0) {
		save_errno = t_errno;
		if (save_errno == TLOOK)
			fprintf(stderr, _(txt_error_server_unavailable));
		else
			t_error("t_connect");
		t_free((char *) callptr, T_CALL);
		t_close(s);
		return -save_errno;
	}

	/*
	 * Now replace the timod module with the tirdwr module so that
	 * standard read() and write() system calls can be used on the
	 * descriptor.
	 */

	t_free((char *) callptr, T_CALL);

	if (ioctl(s, I_POP, (char *) 0) < 0) {
		perror("I_POP(timod)");
		t_close(s);
		return -EPROTO;
	}

	if (ioctl(s, I_PUSH, "tirdwr") < 0) {
		perror("I_PUSH(tirdwr)");
		t_close(s);
		return -EPROTO;
	}

#	else
#		ifndef EXCELAN
	struct servent *sp;
	struct hostent *hp;
#			ifdef h_addr
	int x = 0;
	char **cp;
	static char *alist[2] = {0, 0};
#			endif /* h_addr */
	static struct hostent def;
	static struct in_addr defaddr;
	static char namebuf[256];

#			ifdef HAVE_GETSERVBYNAME
	if ((sp = (struct servent *) getservbyname(service, "tcp")) == NULL) {
		my_fprintf(stderr, _(txt_error_unknown_service), service);
		return -EHOSTUNREACH;
	}
#			else
	sp = my_malloc(sizeof(struct servent));
	sp->s_port = htons(IPPORT_NNTP);
#			endif /* HAVE_GETSERVBYNAME */

	/* If not a raw ip address, try nameserver */
	if (!isdigit((unsigned char) *machine) ||
#			ifdef HAVE_INET_ATON
	    !inet_aton(machine, &defaddr)
#			else
#				ifdef HAVE_INET_ADDR
	    (long) (defaddr.s_addr = (long) inet_addr(machine)) == -1
#				endif /* HAVE_INET_ADDR */
#			endif /* HAVE_INET_ATON */
	    )
	{
		hp = gethostbyname(machine);
	} else {
		/* Raw ip address, fake */
		STRCPY(namebuf, machine);
		def.h_name = (char *) namebuf;
#			ifdef h_addr
		def.h_addr_list = alist;
#			endif /* h_addr */
		def.h_addr = (char *) &defaddr;
		def.h_length = sizeof(struct in_addr);
		def.h_addrtype = AF_INET;
		def.h_aliases = 0;
		hp = &def;
	}

	if (hp == NULL) {
		my_fprintf(stderr, _(txt_gethostbyname), "\n", machine);
		return -EHOSTUNREACH;
	}

	memset((char *) &sock_in, '\0', sizeof(sock_in));
	sock_in.sin_family = hp->h_addrtype;
	sock_in.sin_port = htons(port);
/*	sock_in.sin_port = sp->s_port; */
#		else
	memset((char *) &sock_in, '\0', sizeof(sock_in));
	sock_in.sin_family = AF_INET;
#		endif /* !EXCELAN */

	/*
	 * The following is kinda gross. The name server under 4.3
	 * returns a list of addresses, each of which should be tried
	 * in turn if the previous one fails. However, 4.2 hostent
	 * structure doesn't have this list of addresses.
	 * Under 4.3, h_addr is a #define to h_addr_list[0].
	 * We use this to figure out whether to include the NS specific
	 * code...
	 */

#		ifdef h_addr
	/*
	 * Get a socket and initiate connection -- use multiple addresses
	 */
	for (cp = hp->h_addr_list; cp && *cp; cp++) {
#			if defined(__hpux) && defined(SVR4)
		unsigned long socksize, socksizelen;
#			endif /* __hpux && SVR4 */

		if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
			perror("socket");
			return -errno;
		}

		memcpy((char *) &sock_in.sin_addr, *cp, hp->h_length);

#			ifdef HAVE_INET_NTOA
		if (x < 0)
			my_fprintf(stderr, _(txt_trying), (char *) inet_ntoa(sock_in.sin_addr));
#			endif /* HAVE_INET_NTOA */

#			if defined(__hpux) && defined(SVR4)	/* recommended by [email protected] */
#				define HPSOCKSIZE 0x8000
		getsockopt(s, SOL_SOCKET, SO_SNDBUF, /* (caddr_t) */ &socksize, /* (caddr_t) */ &socksizelen);
		if (socksize < HPSOCKSIZE) {
			socksize = HPSOCKSIZE;
			setsockopt(s, SOL_SOCKET, SO_SNDBUF, /* (caddr_t) */ &socksize, sizeof(socksize));
		}
		socksize = 0;
		socksizelen = sizeof(socksize);
		getsockopt(s, SOL_SOCKET, SO_RCVBUF, /* (caddr_t) */ &socksize, /* (caddr_t) */ &socksizelen);
		if (socksize < HPSOCKSIZE) {
			socksize = HPSOCKSIZE;
			setsockopt(s, SOL_SOCKET, SO_RCVBUF, /* (caddr_t) */ &socksize, sizeof(socksize));
		}
#			endif /* __hpux && SVR4 */

		if ((x = connect(s, (struct sockaddr *) &sock_in, sizeof(sock_in))) == 0)
			break;

		save_errno = errno;									/* Keep for later */
#			ifdef HAVE_INET_NTOA
		my_fprintf(stderr, _(txt_connection_to), (char *) inet_ntoa(sock_in.sin_addr));
		perror("");
#			endif /* HAVE_INET_NTOA */
		(void) s_close(s);
	}

	if (x < 0) {
		my_fprintf(stderr, _(txt_giving_up));
		return -save_errno;					/* Return the last errno we got */
	}
#		else

#			ifdef EXCELAN
	if ((s = socket(SOCK_STREAM, (struct sockproto *) NULL, &sock_in, SO_KEEPALIVE)) < 0) {
		perror("socket");
		return -errno;
	}

	/* set up addr for the connect */
	memset((char *) &sock_in, '\0', sizeof(sock_in));
	sock_in.sin_family = AF_INET;
	sock_in.sin_port = htons(IPPORT_NNTP);

	if ((sock_in.sin_addr.s_addr = rhost(&machine)) == -1) {
		my_fprintf(stderr, _(txt_gethostbyname), "\n", machine);
		return -1;
	}

	/* And connect */
	if (connect(s, (struct sockaddr *) &sock_in) < 0) {
		save_errno = errno;
		perror("connect");
		(void) s_close(s);
		return -save_errno;
	}

#			else
	if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		perror("socket");
		return -errno;
	}

	/* And then connect */

	memcpy((char *) &sock_in.sin_addr, hp->h_addr, hp->h_length);

	if (connect(s, (struct sockaddr *) &sock_in, sizeof(sock_in)) < 0) {
		save_errno = errno;
		perror("connect");
		(void) s_close(s);
		return -save_errno;
	}

#			endif /* !EXCELAN */
#		endif /* !h_addr */
#	endif /* !TLI */
	return s;
}
Пример #13
0
/*
 * Bind to preferred AMQ port.
 */
static int
bind_preferred_amq_port(u_short pref_port,
			const struct netconfig *ncp,
			struct t_bind **tretpp)
{
  int td = -1, rc = -1;
  struct t_bind *treq;
  struct sockaddr_in *sin, *sin2;
  extern char *t_errlist[];
  extern int t_errno;

  if (!ncp) {
    plog(XLOG_ERROR, "null ncp");
    return -1;
  }

  td = t_open(ncp->nc_device, O_RDWR, (struct t_info *) NULL);
  if (td < 0) {
    plog(XLOG_ERROR, "t_open failed: %d: %s", t_errno, t_errlist[t_errno]);
    return -1;
  }
  treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
  if (!treq) {
    plog(XLOG_ERROR, "t_alloc req");
    return -1;
  }
  *tretpp = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
  if (!*tretpp) {
    t_free((char *) treq, T_BIND);
    plog(XLOG_ERROR, "t_alloc tretpp");
    return -1;
  }
  memset((char *) treq->addr.buf, 0, treq->addr.len);
  sin = (struct sockaddr_in *) treq->addr.buf;
  sin->sin_family = AF_INET;
  treq->qlen = 64; /* must be greater than 0 to work for TCP connections */
  treq->addr.len = treq->addr.maxlen;

  if (pref_port > 0) {
    sin->sin_port = htons(pref_port);
    sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* XXX: may not be needed */
    rc = t_bind(td, treq, *tretpp);
    if (rc < 0) {
      plog(XLOG_ERROR, "t_bind return err %d", rc);
      goto out;
    }
    /* check if we got the port we asked for */
    sin2 = (struct sockaddr_in *) (*tretpp)->addr.buf;
    if (sin->sin_port != sin2->sin_port) {
      plog(XLOG_ERROR, "asked for port %d, got different one (%d)",
	   ntohs(sin->sin_port), ntohs(sin2->sin_port));
      t_errno = TNOADDR; /* XXX: is this correct? */
      rc = -1;
      goto out;
    }
    if (sin->sin_addr.s_addr != sin2->sin_addr.s_addr) {
      plog(XLOG_ERROR, "asked for address %x, got different one (%x)",
	   (int) ntohl(sin->sin_addr.s_addr), (int) ntohl(sin2->sin_addr.s_addr));
      t_errno = TNOADDR; /* XXX: is this correct? */
      rc = -1;
      goto out;
    }
  }
out:
  t_free((char *) treq, T_BIND);
  return (rc < 0 ? rc : td);
}