diff options
author | João Valverde <joao.valverde@tecnico.ulisboa.pt> | 2019-11-07 23:11:00 +0000 |
---|---|---|
committer | João Valverde <j@v6e.pt> | 2019-11-11 17:17:36 +0000 |
commit | 5d18c9b4dffb6733e90b5205bccabcf18d8fa04a (patch) | |
tree | 2bc538d12f16a29c983402bff8390181067c95b5 /wsutil/socket.c | |
parent | d7d1686a95868d5df1f8e2ba5e6097c622ba1b64 (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/socket.c')
-rw-r--r-- | wsutil/socket.c | 102 |
1 files changed, 102 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; +} |