aboutsummaryrefslogtreecommitdiffstats
path: root/wsutil
diff options
context:
space:
mode:
authorJoão Valverde <joao.valverde@tecnico.ulisboa.pt>2019-11-07 23:11:00 +0000
committerJoão Valverde <j@v6e.pt>2019-11-11 17:17:36 +0000
commit5d18c9b4dffb6733e90b5205bccabcf18d8fa04a (patch)
tree2bc538d12f16a29c983402bff8390181067c95b5 /wsutil
parentd7d1686a95868d5df1f8e2ba5e6097c622ba1b64 (diff)
dumpcap: Add support for TCP@IPv6 socket captures
Bug: 15820 Change-Id: Id32f376190c115b0808ba72e5b63e019e2a70274 Reviewed-on: https://code.wireshark.org/review/35030 Petri-Dish: João Valverde <j@v6e.pt> Tested-by: Petri Dish Buildbot Reviewed-by: João Valverde <j@v6e.pt>
Diffstat (limited to 'wsutil')
-rw-r--r--wsutil/socket.c102
-rw-r--r--wsutil/socket.h9
2 files changed, 111 insertions, 0 deletions
diff --git a/wsutil/socket.c b/wsutil/socket.c
index af0c970fb5..3b13c7f0be 100644
--- a/wsutil/socket.c
+++ b/wsutil/socket.c
@@ -12,12 +12,16 @@
#include <config.h>
+#include <stdlib.h>
+#include <errno.h>
#include <glib.h>
#include <wsutil/socket.h>
+#include <wsutil/inet_addr.h>
#ifdef _WIN32
#include <wsutil/win32-utils.h>
+#define in_port_t guint16
#endif
gchar *
@@ -47,3 +51,101 @@ ws_cleanup_sockets(void)
WSACleanup();
#endif
}
+
+int
+ws_socket_ptoa(struct sockaddr_storage *dst, const gchar *src,
+ guint16 def_port)
+{
+ int ret = -1, af = -1;
+ char *addr_src, *p;
+ char *addr_str = NULL, *port_str = NULL;
+ union {
+ ws_in4_addr ip4;
+ ws_in6_addr ip6;
+ } addr;
+ char *endptr;
+ long num;
+ in_port_t port;
+
+ addr_src = g_strdup(src);
+
+ /* Is it an IPv6/IPv4 literal address enclosed in braces? */
+ if (*addr_src == '[') {
+ addr_str = addr_src + 1;
+ if ((p = strchr(addr_str, ']')) == NULL) {
+ errno = EINVAL;
+ goto out;
+ }
+ *p++ = '\0';
+ if (*p == ':') {
+ port_str = p + 1;
+ }
+ else if (*p != '\0') {
+ errno = EINVAL;
+ goto out;
+ }
+ if (ws_inet_pton6(addr_str, &addr.ip6)) {
+ af = AF_INET6;
+ }
+ else if (ws_inet_pton4(addr_str, &addr.ip4)) {
+ af = AF_INET;
+ }
+ else {
+ errno = EINVAL;
+ goto out;
+ }
+ }
+ else {
+ /* It is an IPv4 dotted decimal. */
+ addr_str = addr_src;
+ if ((p = strchr(addr_str, ':')) != NULL) {
+ *p++ = '\0';
+ port_str = p;
+ }
+ if (ws_inet_pton4(addr_str, &addr.ip4)) {
+ af = AF_INET;
+ }
+ else {
+ errno = EINVAL;
+ goto out;
+ }
+ }
+
+ if (port_str != NULL && *port_str != '\0') {
+ num = strtol(port_str, &endptr, 10);
+ /* We want the entire string to be a valid decimal representation. */
+ if (endptr == port_str || *endptr != '\0' || num < 0 || num > G_MAXUINT16) {
+ errno = EINVAL;
+ goto out;
+ }
+ port = g_htons(num);
+ }
+ else {
+ port = g_htons(def_port);
+ }
+
+ /* sockaddr_storage is guaranteed to fit any sockaddr type. */
+ if (af == AF_INET6) {
+ struct sockaddr_in6 *sa = (struct sockaddr_in6 *)dst;
+ memset(sa, 0, sizeof(struct sockaddr_in6));
+ sa->sin6_family = AF_INET6;
+ sa->sin6_port = port;
+ memcpy(&sa->sin6_addr, &addr.ip6, sizeof(struct in6_addr));
+ ret = 0;
+ }
+ else if (af == AF_INET) {
+ struct sockaddr_in *sa = (struct sockaddr_in *)dst;
+ memset(sa, 0, sizeof(struct sockaddr_in));
+ sa->sin_family = AF_INET;
+ sa->sin_port = port;
+ memcpy(&sa->sin_addr, &addr.ip4, sizeof(struct in_addr));
+ ret = 0;
+ }
+ else {
+ g_assert_not_reached();
+ }
+
+out:
+ g_free(addr_src);
+ return ret;
+}
diff --git a/wsutil/socket.h b/wsutil/socket.h
index 55e9a90310..99fd07d085 100644
--- a/wsutil/socket.h
+++ b/wsutil/socket.h
@@ -64,6 +64,15 @@ WS_DLL_PUBLIC gchar *ws_init_sockets(void);
*/
WS_DLL_PUBLIC void ws_cleanup_sockets(void);
+/*
+ * Convert the strings ipv4_address:port or [ipv6_address]:port to a
+ * sockaddr object. Ports are optional. Receives default port
+ * in host byte order.
+ */
+WS_DLL_PUBLIC int
+ws_socket_ptoa(struct sockaddr_storage *dst, const gchar *src,
+ guint16 def_port);
+
#ifdef __cplusplus
}
#endif