Example #1
0
/*
 *	Open a socket TO the given IP and port.
 */
int fr_tcp_client_socket(fr_ipaddr_t *src_ipaddr,
			 fr_ipaddr_t *dst_ipaddr, uint16_t dst_port)
{
	int sockfd;
	struct sockaddr_storage salocal;
	socklen_t	salen;

	if (!dst_ipaddr) return -1;

	sockfd = socket(dst_ipaddr->af, SOCK_STREAM, 0);
	if (sockfd < 0) {
		return sockfd;
	}

	/*
	 *	Allow the caller to bind us to a specific source IP.
	 */
	if (src_ipaddr && (src_ipaddr->af != AF_UNSPEC)) {
		if (!fr_ipaddr2sockaddr(src_ipaddr, 0, &salocal, &salen)) {
			close(sockfd);
			return -1;
		}

		if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
			fr_strerror_printf("Failure binding to IP: %s", fr_syserror(errno));
			close(sockfd);
			return -1;
		}
	}

	if (!fr_ipaddr2sockaddr(dst_ipaddr, dst_port, &salocal, &salen)) {
		close(sockfd);
		return -1;
	}

	/*
	 *	FIXME: If EINPROGRESS, then tell the caller that
	 *	somehow.  The caller can then call connect() when the
	 *	socket is ready...
	 */
	if (connect(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
		fr_strerror_printf("Failed in connect(): %s", fr_syserror(errno));
		close(sockfd);
		return -1;
	}

	return sockfd;
}
Example #2
0
/*
 *	Wrapper for sendto which handles sendfromto, IPv6, and all
 *	possible combinations.
 *
 *	FIXME:  This is just a copy of rad_sendto().
 *	Duplicate code is bad.
 */
static int vqp_sendto(int sockfd, void *data, size_t data_len, int flags,
		      fr_ipaddr_t *src_ipaddr, fr_ipaddr_t *dst_ipaddr,
		      int dst_port)
{
	struct sockaddr_storage	dst;
	socklen_t		sizeof_dst;

#ifdef WITH_UDPFROMTO
	struct sockaddr_storage	src;
	socklen_t		sizeof_src;

	fr_ipaddr2sockaddr(src_ipaddr, 0, &src, &sizeof_src);
#else
	src_ipaddr = src_ipaddr; /* -Wunused */
#endif

	if (!fr_ipaddr2sockaddr(dst_ipaddr, dst_port, &dst, &sizeof_dst)) {
		return -1;   /* Unknown address family, Die Die Die! */
	}

#ifdef WITH_UDPFROMTO
	/*
	 *	Only IPv4 is supported for udpfromto.
	 *
	 *	And if they don't specify a source IP address, don't
	 *	use udpfromto.
	 */
	if ((dst_ipaddr->af == AF_INET) ||
	    (src_ipaddr->af != AF_UNSPEC)) {
		return sendfromto(sockfd, data, data_len, flags,
				  (struct sockaddr *)&src, sizeof_src, 
				  (struct sockaddr *)&dst, sizeof_dst);
	}
#else
	src_ipaddr = src_ipaddr; /* -Wunused */
#endif

	/*
	 *	No udpfromto, OR an IPv6 socket, fail gracefully.
	 */
	return sendto(sockfd, data, data_len, flags, 
		      (struct sockaddr *)&dst, sizeof_dst);
}
Example #3
0
/*
 *	Open a socket on the given IP and port.
 */
int fr_tcp_socket(fr_ipaddr_t *ipaddr, int port)
{
	int sockfd;
	int on = 1;
	struct sockaddr_storage salocal;
	socklen_t	salen;

	if ((port < 0) || (port > 65535)) {
		fr_strerror_printf("Port %d is out of allowed bounds", port);
		return -1;
	}

	sockfd = socket(ipaddr->af, SOCK_STREAM, 0);
	if (sockfd < 0) {
		return sockfd;
	}

	if (fr_nonblock(sockfd) < 0) {
		close(sockfd);
		return -1;
	}

	if (!fr_ipaddr2sockaddr(ipaddr, port, &salocal, &salen)) {
		close(sockfd);
		return -1;
	}

#ifdef HAVE_STRUCT_SOCKADDR_IN6
	if (ipaddr->af == AF_INET6) {
		/*
		 *	Listening on '::' does NOT get you IPv4 to
		 *	IPv6 mapping.  You've got to listen on an IPv4
		 *	address, too.  This makes the rest of the server
		 *	design a little simpler.
		 */
#ifdef IPV6_V6ONLY

		if (IN6_IS_ADDR_UNSPECIFIED(&ipaddr->ipaddr.ip6addr)) {
			if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
				       (char *)&on, sizeof(on)) < 0) {
				fr_strerror_printf("Failed in setsockopt(): %s",
						   fr_syserror(errno));
				close(sockfd);
				return -1;
			}
		}
#endif /* IPV6_V6ONLY */
	}
#endif /* HAVE_STRUCT_SOCKADDR_IN6 */

	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
		fr_strerror_printf("Failed in setsockopt(): %s", fr_syserror(errno));
		close(sockfd);
		return -1;
	}

	if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
		fr_strerror_printf("Failed in bind(): %s", fr_syserror(errno));
		close(sockfd);
		return -1;
	}

	if (listen(sockfd, 8) < 0) {
		fr_strerror_printf("Failed in listen(): %s", fr_syserror(errno));
		close(sockfd);
		return -1;
	}

	return sockfd;
}
Example #4
0
/*
 *	Open a socket TO the given IP and port.
 */
int fr_tcp_client_socket(fr_ipaddr_t *src_ipaddr,
			 fr_ipaddr_t *dst_ipaddr, int dst_port)
{
	int sockfd;
	struct sockaddr_storage salocal;
	socklen_t	salen;

	if ((dst_port < 0) || (dst_port > 65535)) {
		fr_strerror_printf("Port %d is out of allowed bounds",
				   dst_port);
		return -1;
	}

	if (!dst_ipaddr) return -1;

	sockfd = socket(dst_ipaddr->af, SOCK_STREAM, 0);
	if (sockfd < 0) {
		return sockfd;
	}

#if 0
#ifdef O_NONBLOCK
	{
		int flags;

		if ((flags = fcntl(sockfd, F_GETFL, NULL)) < 0)  {
			fr_strerror_printf("Failure getting socket flags: %s", fr_syserror(errno));
			close(sockfd);
			return -1;
		}

		flags |= O_NONBLOCK;
		if( fcntl(sockfd, F_SETFL, flags) < 0) {
			fr_strerror_printf("Failure setting socket flags: %s", fr_syserror(errno));
			close(sockfd);
			return -1;
		}
	}
#endif
#endif
	/*
	 *	Allow the caller to bind us to a specific source IP.
	 */
	if (src_ipaddr && (src_ipaddr->af != AF_UNSPEC)) {
		if (!fr_ipaddr2sockaddr(src_ipaddr, 0, &salocal, &salen)) {
			close(sockfd);
			return -1;
		}

		if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
			fr_strerror_printf("Failure binding to IP: %s", fr_syserror(errno));
			close(sockfd);
			return -1;
		}
	}

	if (!fr_ipaddr2sockaddr(dst_ipaddr, dst_port, &salocal, &salen)) {
			close(sockfd);
		return -1;
	}

	/*
	 *	FIXME: If EINPROGRESS, then tell the caller that
	 *	somehow.  The caller can then call connect() when the
	 *	socket is ready...
	 */
	if (connect(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
		fr_strerror_printf("Failed in connect(): %s", fr_syserror(errno));
		close(sockfd);
		return -1;
	}

	return sockfd;
}
Example #5
0
/*
 *	Open a socket on the given IP and port.
 */
int fr_socket(fr_ipaddr_t *ipaddr, int port)
{
	int sockfd;
	struct sockaddr_storage salocal;
	socklen_t	salen;

	if ((port < 0) || (port > 65535)) {
		fr_strerror_printf("Port %d is out of allowed bounds", port);
		return -1;
	}

	sockfd = socket(ipaddr->af, SOCK_DGRAM, 0);
	if (sockfd < 0) {
		fr_strerror_printf("cannot open socket: %s", strerror(errno));
		return sockfd;
	}

#ifdef WITH_UDPFROMTO
	/*
	 *	Initialize udpfromto for all sockets.
	 */
	if (udpfromto_init(sockfd) != 0) {
		close(sockfd);
		fr_strerror_printf("cannot initialize udpfromto: %s", strerror(errno));
		return -1;
	}
#endif


	if (!fr_ipaddr2sockaddr(ipaddr, port, &salocal, &salen)) {
		return sockfd;
	}

#ifdef HAVE_STRUCT_SOCKADDR_IN6
	if (ipaddr->af == AF_INET6) {
		/*
		 *	Listening on '::' does NOT get you IPv4 to
		 *	IPv6 mapping.  You've got to listen on an IPv4
		 *	address, too.  This makes the rest of the server
		 *	design a little simpler.
		 */
#ifdef IPV6_V6ONLY

		if (IN6_IS_ADDR_UNSPECIFIED(&ipaddr->ipaddr.ip6addr)) {
			int on = 1;

			setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
				   (char *)&on, sizeof(on));
		}
#endif /* IPV6_V6ONLY */
	}
#endif /* HAVE_STRUCT_SOCKADDR_IN6 */

	if (ipaddr->af == AF_INET) {
		UNUSED int flag;
		
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
		/*
		 *	Disable PMTU discovery.  On Linux, this
		 *	also makes sure that the "don't fragment"
		 *	flag is zero.
		 */
		flag = IP_PMTUDISC_DONT;
		setsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER,
			   &flag, sizeof(flag));
#endif

#if defined(IP_DONTFRAG)
		/*
		 *	Ensure that the "don't fragment" flag is zero.
		 */
		flag = 0;
		setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG,
			   &flag, sizeof(flag));
#endif
	}

	if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
		close(sockfd);
		fr_strerror_printf("cannot bind socket: %s", strerror(errno));
		return -1;
	}

	return sockfd;
}
Example #6
0
/*
 *	Open a socket TO the given IP and port.
 */
int fr_tcp_client_socket(fr_ipaddr_t *src_ipaddr,
			 fr_ipaddr_t *dst_ipaddr, int dst_port)
{
	int sockfd;
	struct sockaddr_storage salocal;
	socklen_t	salen;

	if ((dst_port < 0) || (dst_port > 65535)) {
		fr_strerror_printf("Port %d is out of allowed bounds",
				   dst_port);
		return -1;
	}

	if (!dst_ipaddr) return -1;

	sockfd = socket(dst_ipaddr->af, SOCK_STREAM, 0);
	if (sockfd < 0) {
		return sockfd;
	}

	/*
	 *	Allow the caller to bind us to a specific source IP.
	 */
	if (src_ipaddr && (src_ipaddr->af != AF_UNSPEC)) {
		if (!fr_ipaddr2sockaddr(src_ipaddr, 0, &salocal, &salen)) {
			close(sockfd);
			return -1;
		}

		if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
			fr_strerror_printf("Failure binding to IP: %s", fr_syserror(errno));
			close(sockfd);
			return -1;
		}
	}

	if (!fr_ipaddr2sockaddr(dst_ipaddr, dst_port, &salocal, &salen)) {
		close(sockfd);
		return -1;
	}

	/*
	 *	FIXME: If EINPROGRESS, then tell the caller that
	 *	somehow.  The caller can then call connect() when the
	 *	socket is ready...
	 */
	if (connect(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
		fr_strerror_printf("Failed in connect(): %s", fr_syserror(errno));
		close(sockfd);
		return -1;
	}

	/*
	 *	Set non-block *AFTER* connecting to the remote server
	 *	so it doesn't return immediately.
	 */
	if (fr_nonblock(sockfd) < 0) {
		close(sockfd);
		return -1;
	}

	return sockfd;
}