char * str_sockaddr( sockaddr_union *sa) { #ifdef WORKING_IPV6 char ipstr[INET6_ADDRSTRLEN]; #else char ipstr[INET_ADDRSTRLEN]; #endif int port; port = SU_GET_PORT(sa); #ifdef WORKING_IPV6 if ( SU_GET_FAMILY(sa) == AF_INET6) { inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr)); } else #endif { inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr)); } g_snprintf(mystr_sockaddr,sizeof(mystr_sockaddr),"%s.%d", ipstr, port); mystr_sockaddr[sizeof(mystr_sockaddr)-1] = '\0'; return mystr_sockaddr; }
gboolean ndmp_connection_mover_connect( NDMPConnection *self, ndmp9_mover_mode mode, DirectTCPAddr *addrs) { unsigned int naddrs, i; ndmp4_tcp_addr *na; g_assert(!self->startup_err); /* count addrs */ g_assert(addrs); for (naddrs = 0; SU_GET_FAMILY(&addrs[naddrs]) != 0; naddrs++) ; /* convert addrs to an ndmp4_tcp_addr */ na = g_new0(ndmp4_tcp_addr, naddrs); for (i = 0; i < naddrs; i++) { na[i].ip_addr = ntohl(addrs[i].sin.sin_addr.s_addr); na[i].port = SU_GET_PORT(&addrs[i]); } NDMP_TRANS(self, ndmp4_mover_connect) request->mode = mode; request->addr.addr_type = NDMP4_ADDR_TCP; request->addr.ndmp4_addr_u.tcp_addr.tcp_addr_len = naddrs; request->addr.ndmp4_addr_u.tcp_addr.tcp_addr_val = na; NDMP_CALL(self); NDMP_FREE(); NDMP_END return TRUE; }
void dump_sockaddr( sockaddr_union *sa) { #ifdef WORKING_IPV6 char ipstr[INET6_ADDRSTRLEN]; #else char ipstr[INET_ADDRSTRLEN]; #endif int port; port = SU_GET_PORT(sa); #ifdef WORKING_IPV6 if (SU_GET_FAMILY(sa) == AF_INET6) { inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr)); dbprintf("(sockaddr_in6 *)%p = { %d, %d, %s }\n", sa, SU_GET_FAMILY(sa), port, ipstr); } else #endif { inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr)); dbprintf("(sockaddr_in *)%p = { %d, %d, %s }\n", sa, SU_GET_FAMILY(sa), port, ipstr); } }
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; }
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; }
int stream_server( int family, in_port_t *portp, size_t sendsize, size_t recvsize, int priv) { int server_socket, retries; socklen_t_equiv len; #if defined(SO_KEEPALIVE) || defined(USE_REUSEADDR) const int on = 1; int r; #endif sockaddr_union server; int save_errno; int *portrange; socklen_t_equiv socklen; int socket_family; *portp = USHRT_MAX; /* in case we error exit */ if (family == -1) { socket_family = AF_NATIVE; } else { socket_family = family; } g_debug("stream_server opening socket with family %d (requested family was %d)", socket_family, family); server_socket = socket(socket_family, SOCK_STREAM, 0); #ifdef WORKING_IPV6 /* if that address family actually isn't supported, just try AF_INET */ if (server_socket == -1 && errno == EAFNOSUPPORT) { g_debug("stream_server retrying socket with AF_INET"); socket_family = AF_INET; server_socket = socket(AF_INET, SOCK_STREAM, 0); } #endif if (server_socket == -1) { save_errno = errno; g_debug(_("stream_server: socket() failed: %s"), strerror(save_errno)); errno = save_errno; return -1; } if(server_socket < 0 || server_socket >= (int)FD_SETSIZE) { aclose(server_socket); errno = EMFILE; /* out of range */ save_errno = errno; g_debug(_("stream_server: socket out of range: %d"), server_socket); errno = save_errno; return -1; } SU_INIT(&server, socket_family); SU_SET_INADDR_ANY(&server); #ifdef USE_REUSEADDR r = setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&on, (socklen_t_equiv)sizeof(on)); if (r < 0) { g_debug(_("stream_server: setsockopt(SO_REUSEADDR) failed: %s"), strerror(errno)); } #endif try_socksize(server_socket, SO_SNDBUF, sendsize); try_socksize(server_socket, SO_RCVBUF, recvsize); /* * If a port range was specified, we try to get a port in that * range first. Next, we try to get a reserved port. If that * fails, we just go for any port. * * In all cases, not to use port that's assigned to other services. * * 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. */ for (retries = 0; ; retries++) { if (priv) { portrange = getconf_intrange(CNF_RESERVED_TCP_PORT); } else { portrange = getconf_intrange(CNF_UNRESERVED_TCP_PORT); } if (portrange[0] != 0 && portrange[1] != 0) { if (bind_portrange(server_socket, &server, (in_port_t)portrange[0], (in_port_t)portrange[1], "tcp") == 0) goto out; g_debug(_("stream_server: Could not bind to port in range: %d - %d."), portrange[0], portrange[1]); } else { socklen = SS_LEN(&server); if (bind(server_socket, (struct sockaddr *)&server, socklen) == 0) goto out; g_debug(_("stream_server: Could not bind to any port: %s"), strerror(errno)); } if (retries >= BIND_CYCLE_RETRIES) break; g_debug(_("stream_server: Retrying entire range after 10 second delay.")); sleep(15); } save_errno = errno; g_debug(_("stream_server: bind(in6addr_any) failed: %s"), strerror(save_errno)); aclose(server_socket); errno = save_errno; return -1; out: listen(server_socket, 1); /* find out what port was actually used */ len = sizeof(server); if(getsockname(server_socket, (struct sockaddr *)&server, &len) == -1) { save_errno = errno; g_debug(_("stream_server: getsockname() failed: %s"), strerror(save_errno)); aclose(server_socket); errno = save_errno; return -1; } #ifdef SO_KEEPALIVE r = setsockopt(server_socket, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, (socklen_t_equiv)sizeof(on)); if(r == -1) { save_errno = errno; g_debug(_("stream_server: setsockopt(SO_KEEPALIVE) failed: %s"), strerror(save_errno)); aclose(server_socket); errno = save_errno; return -1; } #endif *portp = SU_GET_PORT(&server); g_debug(_("stream_server: waiting for connection: %s"), str_sockaddr(&server)); return server_socket; }
int stream_accept( int server_socket, int timeout, size_t sendsize, size_t recvsize) { time_t timeout_time; int connected_socket; int save_errno; in_port_t port; assert(server_socket >= 0); /* set the time we want to stop accepting */ timeout_time = time(NULL) + timeout; while(1) { addrlen = (socklen_t_equiv)sizeof(sockaddr_union); connected_socket = interruptible_accept(server_socket, (struct sockaddr *)&addr, &addrlen, stream_accept_prolong, &timeout_time); if(connected_socket < 0) { if (errno == 0) { g_debug(plural(_("stream_accept: timeout after %d second"), _("stream_accept: timeout after %d seconds"), timeout), timeout); errno = ETIMEDOUT; return -1; } break; } g_debug(_("stream_accept: connection from %s"), str_sockaddr(&addr)); /* * Make certain we got an inet connection and that it is not * from port 20 (a favorite unauthorized entry tool). */ if (SU_GET_FAMILY(&addr) == AF_INET #ifdef WORKING_IPV6 || SU_GET_FAMILY(&addr) == AF_INET6 #endif ){ port = SU_GET_PORT(&addr); if (port != (in_port_t)20) { try_socksize(connected_socket, SO_SNDBUF, sendsize); try_socksize(connected_socket, SO_RCVBUF, recvsize); return connected_socket; } else { g_debug(_("remote port is %u: ignored"), (unsigned int)port); } } else { #ifdef WORKING_IPV6 g_debug(_("family is %d instead of %d(AF_INET)" " or %d(AF_INET6): ignored"), SU_GET_FAMILY(&addr), AF_INET, AF_INET6); #else g_debug(_("family is %d instead of %d(AF_INET)" ": ignored"), SU_GET_FAMILY(&addr), AF_INET); #endif } aclose(connected_socket); } save_errno = errno; g_debug(_("stream_accept: accept() failed: %s"), strerror(save_errno)); errno = save_errno; return -1; }
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; }
int dgram_bind( dgram_t * dgram, sa_family_t family, in_port_t * portp) { int s, retries; socklen_t_equiv len; sockaddr_union name; int save_errno; int *portrange; int sndbufsize = MAX_DGRAM; portrange = getconf_intrange(CNF_RESERVED_UDP_PORT); *portp = (in_port_t)0; g_debug("dgram_bind: setting up a socket with family %d", family); if((s = socket(family, SOCK_DGRAM, 0)) == -1) { save_errno = errno; dbprintf(_("dgram_bind: socket() failed: %s\n"), strerror(save_errno)); errno = save_errno; return -1; } if(s < 0 || s >= (int)FD_SETSIZE) { dbprintf(_("dgram_bind: socket out of range: %d\n"), s); aclose(s); errno = EMFILE; /* out of range */ return -1; } /* try setting the buffer size (= maximum allowable UDP packet size) */ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void *) &sndbufsize, sizeof(sndbufsize)) < 0) { dbprintf("dgram_bind: could not set udp send buffer to %d: %s (ignored)\n", sndbufsize, strerror(errno)); } SU_INIT(&name, family); SU_SET_INADDR_ANY(&name); /* * If a port range was specified, we try to get a port in that * range first. Next, we try to get a reserved port. If that * fails, we just go for any port. * * In all cases, not to use port that's assigned to other services. * * 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. */ for (retries = 0; ; retries++) { if (bind_portrange(s, &name, portrange[0], portrange[1], "udp") == 0) goto out; dbprintf(_("dgram_bind: Could not bind to port in range: %d - %d.\n"), portrange[0], portrange[1]); if (retries >= BIND_CYCLE_RETRIES) { dbprintf(_("dgram_bind: Giving up...\n")); break; } dbprintf(_("dgram_bind: Retrying entire range after 10 second delay.\n")); sleep(15); } save_errno = errno; dbprintf(_("dgram_bind: bind(in6addr_any) failed: %s\n"), strerror(save_errno)); aclose(s); errno = save_errno; return -1; out: /* find out what name was actually used */ len = (socklen_t_equiv)sizeof(name); if(getsockname(s, (struct sockaddr *)&name, &len) == -1) { save_errno = errno; dbprintf(_("dgram_bind: getsockname() failed: %s\n"), strerror(save_errno)); errno = save_errno; aclose(s); return -1; } *portp = SU_GET_PORT(&name); dgram->socket = s; dbprintf(_("dgram_bind: socket %d bound to %s\n"), dgram->socket, str_sockaddr(&name)); return 0; }