示例#1
0
gboolean
ndmp_connection_mover_listen(
	NDMPConnection *self,
	ndmp9_mover_mode mode,
	ndmp9_addr_type addr_type,
	DirectTCPAddr **addrs)
{
    unsigned int naddrs, i;
    *addrs = NULL;

    g_assert(!self->startup_err);

    NDMP_TRANS(self, ndmp4_mover_listen)
	request->mode = mode;
	request->addr_type = addr_type;
	NDMP_CALL(self);

	if (request->addr_type != reply->connect_addr.addr_type) {
	    g_warning("MOVER_LISTEN addr_type mismatch; got %d", reply->connect_addr.addr_type);
	}

	if (reply->connect_addr.addr_type == NDMP4_ADDR_TCP) {
	    naddrs = reply->connect_addr.ndmp4_addr_u.tcp_addr.tcp_addr_len;
	    *addrs = g_new0(DirectTCPAddr, naddrs+1);
	    for (i = 0; i < naddrs; i++) {
		ndmp4_tcp_addr *na = &reply->connect_addr.ndmp4_addr_u.tcp_addr.tcp_addr_val[i];
		(*addrs)[i].sin.sin_family = AF_INET;
		(*addrs)[i].sin.sin_addr.s_addr = htonl(na->ip_addr);
		SU_SET_PORT(&((*addrs)[i]), na->port);
	    }
	}
	NDMP_FREE();
    NDMP_END
    return TRUE;
}
示例#2
0
static sockaddr_union *
unmap_v4mapped(
    sockaddr_union *sa,
    sockaddr_union *tmp)
{
    if (SU_GET_FAMILY(sa) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) {
	SU_INIT(tmp, AF_INET);
	SU_SET_PORT(tmp, SU_GET_PORT(sa));
	/* extract the v4 address from byte 12 of the v6 address */
	memcpy(&tmp->sin.sin_addr.s_addr,
	       &sa->sin6.sin6_addr.s6_addr[12],
	       sizeof(struct in_addr));
	return tmp;
    }

    return sa;
}
示例#3
0
static int
do_directtcp_connect(
    XferElementGlue *self,
    DirectTCPAddr *addrs)
{
    XferElement *elt = XFER_ELEMENT(self);
    sockaddr_union addr;
    int sock;
#ifdef WORKING_IPV6
    char strsockaddr[INET6_ADDRSTRLEN + 20];
#else
    char strsockaddr[INET_ADDRSTRLEN + 20];
#endif

    if (!addrs) {
	g_debug("element-glue got no directtcp addresses to connect to!");
	if (!elt->cancelled) {
	    xfer_cancel_with_error(elt,
		"%s got no directtcp addresses to connect to",
		xfer_element_repr(elt));
	}
	goto cancel_wait;
    }

    /* set up the sockaddr -- IPv4 only */
    copy_sockaddr(&addr, addrs);

    str_sockaddr_r(&addr, strsockaddr, sizeof(strsockaddr));

    if (strncmp(strsockaddr,"255.255.255.255:", 16) == 0) {
	char  buffer[32770];
	char *s;
	int   size;
	char *data_host;
	int   data_port;

	g_debug("do_directtcp_connect making indirect data connection to %s",
		strsockaddr);
	data_port = SU_GET_PORT(&addr);
	sock = stream_client(NULL, "localhost", data_port,
                                   STREAM_BUFSIZE, 0, NULL, 0);
	if (sock < 0) {
	    xfer_cancel_with_error(elt, "stream_client(): %s", strerror(errno));
	    goto cancel_wait;
	}
	size = full_read(sock, buffer, 32768);
	if (size < 0 ) {
	    xfer_cancel_with_error(elt, "failed to read from indirecttcp: %s",
				   strerror(errno));
	    goto cancel_wait;
	}
	close(sock);
	buffer[size++] = ' ';
	buffer[size] = '\0';
	if ((s = strchr(buffer, ':')) == NULL) {
	    xfer_cancel_with_error(elt,
				   "Failed to parse indirect data stream: %s",
				   buffer);
	    goto cancel_wait;
	}
	*s++ = '\0';
	data_host = buffer;
	data_port = atoi(s);

	str_to_sockaddr(data_host, &addr);
	SU_SET_PORT(&addr, data_port);

	str_sockaddr_r(&addr, strsockaddr, sizeof(strsockaddr));
    }

    sock = socket(SU_GET_FAMILY(&addr), SOCK_STREAM, 0);

    g_debug("do_directtcp_connect making data connection to %s", strsockaddr);

    if (sock < 0) {
	xfer_cancel_with_error(elt,
	    "socket(): %s", strerror(errno));
	goto cancel_wait;
    }
    if (connect(sock, (struct sockaddr *)&addr, SS_LEN(&addr)) < 0) {
	xfer_cancel_with_error(elt,
	    "connect(): %s", strerror(errno));
	close(sock);
	goto cancel_wait;
    }

    g_debug("do_directtcp_connect: connected to %s, fd %d", strsockaddr, sock);

    return sock;

cancel_wait:
    wait_until_xfer_cancelled(elt->xfer);
    return -1;
}
示例#4
0
文件: stream.c 项目: B-Rich/amanda
static int
stream_client_internal(
    const char *hostname,
    in_port_t port,
    size_t sendsize,
    size_t recvsize,
    in_port_t *localport,
    int nonblock,
    int priv)
{
    sockaddr_union svaddr, claddr;
    int save_errno = 0;
    int client_socket = 0;
    int *portrange = NULL;
    int result;
    struct addrinfo *res, *res_addr;

    result = resolve_hostname(hostname, SOCK_STREAM, &res, NULL);
    if(result != 0) {
	g_debug(_("resolve_hostname(%s): %s"), hostname, gai_strerror(result));
	errno = EHOSTUNREACH;
	return -1;
    }
    if(!res) {
	g_debug(_("resolve_hostname(%s): no results"), hostname);
	errno = EHOSTUNREACH;
	return -1;
    }

    for (res_addr = res; res_addr != NULL; res_addr = res_addr->ai_next) {
	/* copy the first (preferred) address we found */
	copy_sockaddr(&svaddr, (sockaddr_union *)res_addr->ai_addr);
	SU_SET_PORT(&svaddr, port);

	SU_INIT(&claddr, SU_GET_FAMILY(&svaddr));
	SU_SET_INADDR_ANY(&claddr);

	/*
	 * If a privileged port range was requested, we try to get a port in
	 * that range first and fail if it is not available.  Next, we try
	 * to get a port in the range built in when Amanda was configured.
	 * If that fails, we just go for any port.
	 *
	 * It is up to the caller to make sure we have the proper permissions
	 * to get the desired port, and to make sure we return a port that
	 * is within the range it requires.
	 */
	if (priv) {
	    portrange = getconf_intrange(CNF_RESERVED_TCP_PORT);
	} else {
	    portrange = getconf_intrange(CNF_UNRESERVED_TCP_PORT);
	}
	client_socket = connect_portrange(&claddr, (in_port_t)portrange[0],
					  (in_port_t)portrange[1],
					  "tcp", &svaddr, nonblock);
	save_errno = errno;
	if (client_socket > 0)
	    break;
    }

    freeaddrinfo(res);
					  
    if (client_socket > 0)
	goto out;

    g_debug(_("stream_client: Could not bind to port in range %d-%d."),
	      portrange[0], portrange[1]);

    errno = save_errno;
    return -1;

out:
    try_socksize(client_socket, SO_SNDBUF, sendsize);
    try_socksize(client_socket, SO_RCVBUF, recvsize);
    if (localport != NULL)
	*localport = SU_GET_PORT(&claddr);
    return client_socket;
}
示例#5
0
/*
 * Bind to a port in the given range.  Takes a begin,end pair of port numbers.
 *
 * Returns negative on error (EGAIN if all ports are in use).  Returns 0
 * on success.
 */
int
bind_portrange(
    int			s,
    sockaddr_union *addrp,
    in_port_t		first_port,
    in_port_t		last_port,
    char *		proto)
{
    in_port_t port;
    in_port_t cnt;
    socklen_t_equiv socklen;
    struct servent *servPort;
    const in_port_t num_ports = (in_port_t)(last_port - first_port + 1);
    int save_errno = EAGAIN;

    assert(first_port <= last_port);

    /*
     * We pick a different starting port based on our pid and the current
     * time to avoid always picking the same reserved port twice.
     */
    port = (in_port_t)(((getpid() + time(0)) % num_ports) + first_port);

    /*
     * Scan through the range, trying all available ports that are either 
     * not taken in /etc/services or registered for *amanda*.  Wrap around
     * if we don't happen to start at the beginning.
     */
    for (cnt = 0; cnt < num_ports; cnt++) {
	servPort = getservbyport((int)htons(port), proto);
	if ((servPort == NULL) || strstr(servPort->s_name, AMANDA_SERVICE_NAME)) {
	    SU_SET_PORT(addrp, port);
	    socklen = SS_LEN(addrp);
	    if (bind(s, (struct sockaddr *)addrp, socklen) >= 0) {
		if (servPort == NULL) {
		    g_debug(_("bind_portrange2: Try  port %d: Available - Success"), port);
		} else {
		    g_debug(_("bind_portrange2: Try  port %d: Owned by %s - Success."), port, servPort->s_name);
		}
		return 0;
	    }
	    if (errno != EAGAIN && errno != EBUSY)
		save_errno = errno;
	    if (servPort == NULL) {
		g_debug(_("bind_portrange2: Try  port %d: Available - %s"),
			port, strerror(errno));
	    } else {
		g_debug(_("bind_portrange2: Try  port %d: Owned by %s - %s"),
			port, servPort->s_name, strerror(errno));
	    }
	} else {
	        g_debug(_("bind_portrange2: Skip port %d: Owned by %s."),
		      port, servPort->s_name);
	}
	if (++port > last_port)
	    port = first_port;
    }
    g_debug(_("bind_portrange: all ports between %d and %d busy"),
		  first_port,
		  last_port);
    errno = save_errno;
    return -1;
}
示例#6
0
/* return >0: this is the connected socket */
int
connect_port(
    sockaddr_union *addrp,
    in_port_t  		port,
    char *		proto,
    sockaddr_union *svaddr,
    int			nonblock)
{
    int			save_errno;
    struct servent *	servPort;
    socklen_t_equiv	len;
    socklen_t_equiv	socklen;
    int			s;

    servPort = getservbyport((int)htons(port), proto);
    if (servPort != NULL && !strstr(servPort->s_name, AMANDA_SERVICE_NAME)) {
	dbprintf(_("connect_port: Skip port %d: owned by %s.\n"),
		  port, servPort->s_name);
	errno = EBUSY;
	return -1;
    }

    if ((s = make_socket(SU_GET_FAMILY(addrp))) == -1) return -2;

    SU_SET_PORT(addrp, port);
    socklen = SS_LEN(addrp);
    if (bind(s, (struct sockaddr *)addrp, socklen) != 0) {
	save_errno = errno;
	aclose(s);
	if(servPort == NULL) {
	    dbprintf(_("connect_port: Try  port %d: available - %s\n"),
		     port, strerror(errno));
	} else {
	    dbprintf(_("connect_port: Try  port %d: owned by %s - %s\n"),
		     port, servPort->s_name, strerror(errno));
	}
	if (save_errno != EADDRINUSE) {
	    errno = save_errno;
	    return -2;
	}

	errno = save_errno;
	return -1;
    }
    if(servPort == NULL) {
	dbprintf(_("connect_port: Try  port %d: available - Success\n"), port);
    } else {
	dbprintf(_("connect_port: Try  port %d: owned by %s - Success\n"),
		  port, servPort->s_name);
    }

    /* find out what port was actually used */

    len = sizeof(*addrp);
    if (getsockname(s, (struct sockaddr *)addrp, &len) == -1) {
	save_errno = errno;
	dbprintf(_("connect_port: getsockname() failed: %s\n"),
		  strerror(save_errno));
	aclose(s);
	errno = save_errno;
	return -1;
    }

    if (nonblock) {
	int r = fcntl(s, F_GETFL, 0);
	if (r < 0) {
	    save_errno = errno;
	    g_debug("Can't fcntl(F_GETFL): %s", strerror(errno));
	    aclose(s);
	    errno = save_errno;
	    return -1;
	}
	r = fcntl(s, F_SETFL, r|O_NONBLOCK);
	if (r < 0) {
	    save_errno = errno;
	    g_debug("Can't fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno));
	    errno = save_errno;
	    aclose(s);
	    return -1;
	}
    }
    if (connect(s, (struct sockaddr *)svaddr, SS_LEN(svaddr)) == -1 && !nonblock) {
	save_errno = errno;
	dbprintf(_("connect_portrange: Connect from %s failed: %s\n"),
		  str_sockaddr(addrp),
		  strerror(save_errno));
	dbprintf(_("connect_portrange: connect to %s failed: %s\n"),
		  str_sockaddr(svaddr),
		  strerror(save_errno));
	aclose(s);
	errno = save_errno;
	if (save_errno == ECONNREFUSED ||
	    save_errno == EHOSTUNREACH ||
	    save_errno == ENETUNREACH ||
	    save_errno == ETIMEDOUT)  {
	    return -2	;
	}
	return -1;
    }

    dbprintf(_("connected to %s\n"),
              str_sockaddr(svaddr));
    dbprintf(_("our side is %s\n"),
              str_sockaddr(addrp));
    return s;
}