/** * 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; }
/** * 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; }
/** * 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; }
/** * 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); }
/** * 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 */ }