Ejemplo n.º 1
0
Archivo: tcp.c Proyecto: netroby/zsh
mod_export Tcp_session
tcp_socket(int domain, int type, int protocol, int ztflags)
{
    Tcp_session sess;

    sess = zts_alloc(ztflags);
    if (!sess) return NULL;

    sess->fd = socket(domain, type, protocol);
    return sess;
}
Ejemplo n.º 2
0
Archivo: tcp.c Proyecto: zsh-users/zsh
mod_export Tcp_session
tcp_socket(int domain, int type, int protocol, int ztflags)
{
    Tcp_session sess;

    sess = zts_alloc(ztflags);
    if (!sess) return NULL;

    sess->fd = socket(domain, type, protocol);
    /* We'll check failure and tidy up in caller */
    addmodulefd(sess->fd, FDT_MODULE);
    return sess;
}
Ejemplo n.º 3
0
Archivo: tcp.c Proyecto: zsh-users/zsh
static int
bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
{
    int herrno, err=1, destport, force=0, verbose=0, test=0, targetfd=0;
    ZSOCKLEN_T  len;
    char **addrp, *desthost;
    const char *localname, *remotename;
    struct hostent *zthost = NULL, *ztpeer = NULL;
    struct servent *srv;
    Tcp_session sess = NULL;

    if (OPT_ISSET(ops,'f'))
	force = 1;

    if (OPT_ISSET(ops,'v'))
	verbose = 1;

    if (OPT_ISSET(ops,'t'))
        test = 1;

    if (OPT_ISSET(ops,'d')) {
	targetfd = atoi(OPT_ARG(ops,'d'));
	if (!targetfd) {
	    zwarnnam(nam, "%s is an invalid argument to -d", OPT_ARG(ops,'d'));
	    return 1;
	}
    }


    if (OPT_ISSET(ops,'c')) {
	if (!args[0]) {
	    tcp_cleanup();
	}
	else {
	    targetfd = atoi(args[0]);
	    sess = zts_byfd(targetfd);
	    if(!targetfd) {
		zwarnnam(nam, "%s is an invalid argument to -c", args[0]);
		return 1;
	    }

	    if (sess)
	    {
		if ((sess->flags & ZTCP_ZFTP) && !force)
		{
		    zwarnnam(nam, "use -f to force closure of a zftp control connection");
		    return 1;
		}
		tcp_close(sess);
		return 0;
	    }
	    else
	    {
		zwarnnam(nam, "fd %s not found in tcp table", args[0]);
		return 1;
	    }
	}
    }
    else if (OPT_ISSET(ops,'l')) {
	int lport = 0;

	if (!args[0]) {
	    zwarnnam(nam, "-l requires an argument");
	    return 1;
	}

	srv = getservbyname(args[0], "tcp");
	if (srv)
	    lport = srv->s_port;
	else
	    lport = htons(atoi(args[0]));
	if (!lport) { zwarnnam(nam, "bad service name or port number");
	return 1;
	}
	sess = tcp_socket(PF_INET, SOCK_STREAM, 0, ZTCP_LISTEN);

	if (!sess) {
	    zwarnnam(nam, "unable to allocate a TCP session slot");
	    return 1;
	}
#ifdef SO_OOBINLINE
	len = 1;
	setsockopt(sess->fd, SOL_SOCKET, SO_OOBINLINE, (char *)&len, sizeof(len));
#endif
	if (!zsh_inet_aton("0.0.0.0", &(sess->sock.in.sin_addr)))
	{
	    zwarnnam(nam, "bad address: %s", "0.0.0.0");
	    return 1;
	}

	sess->sock.in.sin_family = AF_INET;
	sess->sock.in.sin_port = lport;


	if (bind(sess->fd, (struct sockaddr *)&sess->sock.in, sizeof(struct sockaddr_in)))
	{
	    char buf[DIGBUFSIZE];
	    convbase(buf, (zlong)ntohs(lport), 10);
	    zwarnnam(nam, "could not bind to port %s: %e", buf, errno);
	    tcp_close(sess);
	    return 1;
	}

	if (listen(sess->fd, 1))
	{
	    zwarnnam(nam, "could not listen on socket: %e", errno);
	    tcp_close(sess);
	    return 1;
	}

	if (targetfd) {
	    sess->fd = redup(sess->fd, targetfd);
	}
	else {
	    /* move the fd since no one will want to read from it */
	    sess->fd = movefd(sess->fd);
	}

	if (sess->fd == -1) {
	    zwarnnam(nam, "cannot duplicate fd %d: %e", sess->fd, errno);
	    tcp_close(sess);
	    return 1;
	}

	setiparam_no_convert("REPLY", (zlong)sess->fd);

	if (verbose)
	    printf("%d listener is on fd %d\n", ntohs(sess->sock.in.sin_port), sess->fd);

	return 0;

    }
    else if (OPT_ISSET(ops,'a'))
    {
	int lfd, rfd;

	if (!args[0]) {
	    zwarnnam(nam, "-a requires an argument");
	    return 1;
	}

	lfd = atoi(args[0]);

	if (!lfd) {
	    zwarnnam(nam, "invalid numerical argument");
	    return 1;
	}

	sess = zts_byfd(lfd);
	if (!sess) {
	    zwarnnam(nam, "fd %s is not registered as a tcp connection", args[0]);
	    return 1;
	}

	if (!(sess->flags & ZTCP_LISTEN))
	{
	    zwarnnam(nam, "tcp connection not a listener");
	    return 1;
	}

	if (test) {
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
# ifdef HAVE_POLL
	    struct pollfd pfd;
	    int ret;

	    pfd.fd = lfd;
	    pfd.events = POLLIN;
	    if ((ret = poll(&pfd, 1, 0)) == 0) return 1;
	    else if (ret == -1)
	    {
		zwarnnam(nam, "poll error: %e", errno);
		return 1;
	    }
# else
	    fd_set rfds;
	    struct timeval tv;
	    int ret;
	    
	    FD_ZERO(&rfds);
	    FD_SET(lfd, &rfds);
	    tv.tv_sec = 0;
	    tv.tv_usec = 0;
	    
	    if ((ret = select(lfd+1, &rfds, NULL, NULL, &tv)) == 0) return 1;
	    else if (ret == -1)
	    {
		zwarnnam(nam, "select error: %e", errno);
		return 1;
	    }
	    
# endif
	    
#else
	    zwarnnam(nam, "not currently supported");
	    return 1;
#endif
	}
	sess = zts_alloc(ZTCP_INBOUND);

	len = sizeof(sess->peer.in);
	do {
	    rfd = accept(lfd, (struct sockaddr *)&sess->peer.in, &len);
	} while (rfd < 0 && errno == EINTR && !errflag);

	if (rfd == -1) {
	    zwarnnam(nam, "could not accept connection: %e", errno);
	    tcp_close(sess);
	    return 1;
	}

	/* redup expects fd is already registered */
	addmodulefd(rfd, FDT_MODULE);

	if (targetfd) {
	    sess->fd = redup(rfd, targetfd);
	    if (sess->fd < 0) {
		zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno);
		return 1;
	    }
	}
	else {
	    sess->fd = rfd;
	}

	setiparam_no_convert("REPLY", (zlong)sess->fd);

	if (verbose)
	    printf("%d is on fd %d\n", ntohs(sess->peer.in.sin_port), sess->fd);
    }
    else
    {
	if (!args[0]) {
	    LinkNode node;
	    for(node = firstnode(ztcp_sessions); node; incnode(node))
	    {
		sess = (Tcp_session)getdata(node);

		if (sess->fd != -1)
		{
		    zthost = gethostbyaddr((const void *)&(sess->sock.in.sin_addr), sizeof(sess->sock.in.sin_addr), AF_INET);
		    if (zthost)
			localname = zthost->h_name;
		    else
			localname = inet_ntoa(sess->sock.in.sin_addr);
		    ztpeer = gethostbyaddr((const void *)&(sess->peer.in.sin_addr), sizeof(sess->peer.in.sin_addr), AF_INET);
		    if (ztpeer)
			remotename = ztpeer->h_name;
		    else
			remotename = inet_ntoa(sess->peer.in.sin_addr);
		    if (OPT_ISSET(ops,'L')) {
			int schar;
			if (sess->flags & ZTCP_ZFTP)
			    schar = 'Z';
			else if (sess->flags & ZTCP_LISTEN)
			    schar = 'L';
			else if (sess->flags & ZTCP_INBOUND)
			    schar = 'I';
			else
			    schar = 'O';
			printf("%d %c %s %d %s %d\n",
			       sess->fd, schar,
			       localname, ntohs(sess->sock.in.sin_port),
			       remotename, ntohs(sess->peer.in.sin_port));
		    } else {
			printf("%s:%d %s %s:%d is on fd %d%s\n",
			       localname, ntohs(sess->sock.in.sin_port),
			       ((sess->flags & ZTCP_LISTEN) ? "-<" :
				((sess->flags & ZTCP_INBOUND) ? "<-" : "->")),
			       remotename, ntohs(sess->peer.in.sin_port),
			       sess->fd,
			       (sess->flags & ZTCP_ZFTP) ? " ZFTP" : "");
		    }
		}
	    }
	    return 0;
	}
	else if (!args[1]) {
	    destport = htons(23);
	}
	else {

	    srv = getservbyname(args[1],"tcp");
	    if (srv)
		destport = srv->s_port;
	    else
		destport = htons(atoi(args[1]));
	}
	
	desthost = ztrdup(args[0]);
	
	zthost = zsh_getipnodebyname(desthost, AF_INET, 0, &herrno);
	if (!zthost || errflag) {
	    zwarnnam(nam, "host resolution failure: %s", desthost);
	    zsfree(desthost);
	    return 1;
	}
	
	sess = tcp_socket(PF_INET, SOCK_STREAM, 0, 0);

	if (!sess) {
	    zwarnnam(nam, "unable to allocate a TCP session slot");
	    zsfree(desthost);
	    return 1;
	}

#ifdef SO_OOBINLINE
	len = 1;
	setsockopt(sess->fd, SOL_SOCKET, SO_OOBINLINE, (char *)&len, sizeof(len));
#endif

	if (sess->fd < 0) {
	    zwarnnam(nam, "socket creation failed: %e", errno);
	    zsfree(desthost);
	    zts_delete(sess);
	    return 1;
	}
	
	for (addrp = zthost->h_addr_list; err && *addrp; addrp++) {
	    if (zthost->h_length != 4)
		zwarnnam(nam, "address length mismatch");
	    do {
		err = tcp_connect(sess, *addrp, zthost, destport);
	    } while (err && errno == EINTR && !errflag);
	}
	
	if (err) {
	    zwarnnam(nam, "connection failed: %e", errno);
	    tcp_close(sess);
	    zsfree(desthost);
	    return 1;
	}
	else
	{
	    if (targetfd) {
		sess->fd = redup(sess->fd, targetfd);
		if (sess->fd < 0) {
		    zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno);
		    zsfree(desthost);
		    tcp_close(sess);
		    return 1;
		}
	    }

	    setiparam_no_convert("REPLY", (zlong)sess->fd);

	    if (verbose)
		printf("%s:%d is now on fd %d\n",
			desthost, destport, sess->fd);
	}
	
	zsfree(desthost);
    }

    return 0;
}