示例#1
0
/**
 * Prints the ``port'' followed by host address ``ha'' to ``dst''. The string
 * written to ``dst'' is always NUL-terminated unless ``size'' is zero. If
 * ``size'' is too small, the string will be truncated.
 *
 * @param dst the destination buffer; may be NULL iff ``size'' is zero.
 * @param port the port number.
 * @param ha the host address.
 * @param size the size of ``dst'' in bytes.
 *
 * @return The length of the resulting string assuming ``size'' is sufficient.
 */
size_t
host_port_addr_to_string_buf(uint16 port, const host_addr_t ha,
	char *dst, size_t size)
{
	char port_buf[UINT32_DEC_BUFLEN];
	char host_buf[HOST_ADDR_BUFLEN];
	size_t n;

	uint32_to_string_buf(port, port_buf, sizeof port_buf);
	host_addr_to_string_buf(ha, host_buf, sizeof host_buf);

	switch (host_addr_net(ha)) {
	case NET_TYPE_IPV6:
		n = concat_strings(dst, size, port_buf, ":[", host_buf, "]",
			(void *) 0);
		break;
	case NET_TYPE_IPV4:
		n = concat_strings(dst, size, port_buf, ":", host_buf, (void *) 0);
		break;
	default:
		n = g_strlcpy(dst, host_buf, size);
	}

	return n;
}
示例#2
0
/**
 * Same as host_addr_to_string(), but in another static buffer.
 */
const char *
host_addr_to_string2(const host_addr_t ha)
{
	static char buf[HOST_ADDR_BUFLEN];
	size_t n;

	n = host_addr_to_string_buf(ha, buf, sizeof buf);
	g_assert(n < sizeof buf);
	return buf;
}
示例#3
0
/**
 * Same as host_addr_to_string(), but in another static buffer.
 */
const char *
host_addr_to_string2(const host_addr_t ha)
{
	buf_t *b = buf_private(G_STRFUNC, HOST_ADDR_BUFLEN);
	char *p = buf_data(b);
	size_t len, n = buf_size(b);

	len = host_addr_to_string_buf(ha, p, n);
	g_assert(len < n);
	return p;
}
示例#4
0
/**
 * Add a port forwarding (*:ext_port -> addr:port) [IP or PPP connection].
 *
 * @param usd		the UPnP service to contact
 * @param proto		mapping protocol
 * @param ext_port	the mapped external port for which we want the mapping
 * @param int_addr	the internal client address
 * @param int_port	the internal port for which we want the mapping
 * @param desc		comment description
 * @param lease		lease duration (0 = permanent)
 * @param cb		callback to invoke when reply is available
 * @param arg		additional callback argument
 *
 * @return UPnP request handle if the SOAP RPC was initiated, NULL otherwise
 * (in which case callbacks will never be called).
 */
upnp_ctrl_t *
upnp_ctrl_AddPortMapping(const upnp_service_t *usd,
	enum upnp_map_proto proto, guint16 ext_port,
	host_addr_t int_addr, guint16 int_port,
	const char *desc, time_delta_t lease,
	upnp_ctrl_cb_t cb, void *arg)
{
	nv_pair_t *argv[8];
	char ext_port_buf[UINT16_DEC_BUFLEN];
	char int_port_buf[UINT16_DEC_BUFLEN];
	char int_addr_buf[HOST_ADDR_BUFLEN];
	char lease_buf[UINT32_DEC_BUFLEN];
	const char *protocol;
	const char *description;

	g_assert(lease >= 0);
	g_assert(lease <= MAX_INT_VAL(gint32));
	g_assert(ext_port != 0);
	g_assert(int_port != 0);

	int32_to_string_buf(ext_port, ext_port_buf, sizeof ext_port_buf);
	int32_to_string_buf(int_port, int_port_buf, sizeof int_port_buf);
	host_addr_to_string_buf(int_addr, int_addr_buf, sizeof int_addr_buf);
	protocol = upnp_map_proto_to_string(proto);
	int32_to_string_buf(lease, lease_buf, sizeof lease_buf);
	description = str_smsg("%s (%s)", desc, protocol);

	argv[0] = nv_pair_make_static_str(ARG_REMOTE_HOST, EMPTY);	/* Wildcard */
	argv[1] = nv_pair_make_static_str(ARG_EXTERNAL_PORT, ext_port_buf);
	argv[2] = nv_pair_make_static_str(ARG_PROTOCOL, protocol);
	argv[3] = nv_pair_make_static_str(ARG_INTERNAL_PORT, int_port_buf);
	argv[4] = nv_pair_make_static_str(ARG_INTERNAL_CLIENT, int_addr_buf);
	argv[5] = nv_pair_make_static_str(ARG_ENABLED, ONE);		/* Enable! */
	argv[6] = nv_pair_make_static_str(ARG_PORTMAP_DESC, description);
	argv[7] = nv_pair_make_static_str(ARG_LEASE_DURATION, lease_buf);

	/*
	 * TODO: when talking to a v2 WANIPConnection service, we can use
	 * the AddAnyPortMapping() call.  This will require that GTKG maintains
	 * knowledge about the remote port so that it can advertise that remote
	 * port instead of the local listening port.
	 *
	 * Attempts must be made to get the same external port for both TCP and UDP,
	 * or this will create problems to servents assuming that they will always
	 * be identical (like GTKG does when it uses the TCP listening port of
	 * a remote host to send a push-proxy request via UDP)..
	 *		--RAM, 2011-01-18
	 */

	return upnp_ctrl_launch(usd, "AddPortMapping",
		argv, G_N_ELEMENTS(argv), cb, arg,
		NULL);
}
示例#5
0
/**
 * Resolves an IP address to a hostname per DNS.
 *
 * @param ha	The host address to resolve.
 * @return		On success, the hostname is returned. Otherwise, NULL is
 *				returned. The resulting string points to a static buffer.
 */
const char *
host_addr_to_name(host_addr_t addr)
{
	socket_addr_t sa;

	if (host_addr_can_convert(addr, NET_TYPE_IPV4)) {
		(void) host_addr_convert(addr, &addr, NET_TYPE_IPV4);
	}
	if (0 == socket_addr_set(&sa, addr, 0)) {
		return NULL;
	}

#ifdef HAS_GETNAMEINFO
	{
		static char host[1025];
		int error;

		error = getnameinfo(socket_addr_get_const_sockaddr(&sa),
					socket_addr_get_len(&sa), host, sizeof host, NULL, 0, 0);
		if (error) {
			char buf[HOST_ADDR_BUFLEN];

			host_addr_to_string_buf(addr, buf, sizeof buf);
			g_message("getnameinfo() failed for \"%s\": %s",
				buf, gai_strerror(error));
			return NULL;
		}
		return host;
	}
#else	/* !HAS_GETNAMEINFO */
	{
		const struct hostent *he;
		socklen_t len = 0;
		const char *ptr = NULL;

		switch (host_addr_net(addr)) {
		case NET_TYPE_IPV4:
			ptr = cast_to_gchar_ptr(&sa.inet4.sin_addr);
			len = sizeof sa.inet4.sin_addr;
			break;
		case NET_TYPE_IPV6:
#ifdef HAS_IPV6
			ptr = cast_to_gchar_ptr(&sa.inet6.sin6_addr);
			len = sizeof sa.inet6.sin6_addr;
			break;
#endif /* HAS_IPV6 */
		case NET_TYPE_LOCAL:
		case NET_TYPE_NONE:
			return NULL;
		}
		g_return_val_if_fail(ptr, NULL);
		g_return_val_if_fail(0 != len, NULL);

		he = gethostbyaddr(ptr, len, socket_addr_get_family(&sa));
		if (!he) {
			char buf[HOST_ADDR_BUFLEN];

			host_addr_to_string_buf(addr, buf, sizeof buf);
			gethostbyname_error(buf);
			return NULL;
		}
		return he->h_name;
	}
#endif	/* HAS_GETNAMEINFO */
}