dcerpc-nt: add UNION_ALIGN_TO... helpers
[wireshark-sm.git] / wsutil / socket.c
blob88297f80a2a18068e03ea799394f2dfb4a3fb6d4
1 /* socket.c
2 * Socket wrappers
4 * Copyright 2019, Gerald Combs
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
14 #include "socket.h"
16 #include <stdlib.h>
17 #include <errno.h>
19 #include <wsutil/inet_addr.h>
21 #ifdef _WIN32
22 #include <wsutil/win32-utils.h>
23 #define in_port_t uint16_t
24 #endif
26 char *
27 ws_init_sockets(void)
29 char *errmsg = NULL;
30 #ifdef _WIN32
31 int err;
32 WORD wVersionRequested;
33 WSADATA wsaData;
35 wVersionRequested = MAKEWORD(2, 2);
36 err = WSAStartup(wVersionRequested, &wsaData);
37 if (err != 0) {
38 errmsg = ws_strdup_printf("Couldn't initialize Windows Sockets: %s",
39 win32strerror(err));
41 #endif
42 return errmsg;
45 void
46 ws_cleanup_sockets(void)
48 #ifdef _WIN32
49 /* XXX - any reason to check the error return? */
50 WSACleanup();
51 #endif
54 int
55 ws_socket_ptoa(struct sockaddr_storage *dst, const char *src,
56 uint16_t def_port)
58 int ret = -1, af = -1;
59 char *addr_src, *p;
60 char *addr_str = NULL, *port_str = NULL;
61 union {
62 ws_in4_addr ip4;
63 ws_in6_addr ip6;
64 } addr;
65 char *endptr;
66 long num;
67 in_port_t port;
69 addr_src = g_strdup(src);
71 /* Is it an IPv6/IPv4 literal address enclosed in braces? */
72 if (*addr_src == '[') {
73 addr_str = addr_src + 1;
74 if ((p = strchr(addr_str, ']')) == NULL) {
75 errno = EINVAL;
76 goto out;
78 *p++ = '\0';
79 if (*p == ':') {
80 port_str = p + 1;
82 else if (*p != '\0') {
83 errno = EINVAL;
84 goto out;
86 if (ws_inet_pton6(addr_str, &addr.ip6)) {
87 af = AF_INET6;
89 else if (ws_inet_pton4(addr_str, &addr.ip4)) {
90 af = AF_INET;
92 else {
93 errno = EINVAL;
94 goto out;
97 else {
98 /* It is an IPv4 dotted decimal. */
99 addr_str = addr_src;
100 if ((p = strchr(addr_str, ':')) != NULL) {
101 *p++ = '\0';
102 port_str = p;
104 if (ws_inet_pton4(addr_str, &addr.ip4)) {
105 af = AF_INET;
107 else {
108 errno = EINVAL;
109 goto out;
113 if (port_str != NULL && *port_str != '\0') {
114 num = strtol(port_str, &endptr, 10);
115 /* We want the entire string to be a valid decimal representation. */
116 if (endptr == port_str || *endptr != '\0' || num < 0 || num > UINT16_MAX) {
117 errno = EINVAL;
118 goto out;
120 port = g_htons(num);
122 else {
123 port = g_htons(def_port);
126 /* sockaddr_storage is guaranteed to fit any sockaddr type. */
127 if (af == AF_INET6) {
128 struct sockaddr_in6 *sa = (struct sockaddr_in6 *)dst;
129 memset(sa, 0, sizeof(struct sockaddr_in6));
130 sa->sin6_family = AF_INET6;
131 sa->sin6_port = port;
132 memcpy(&sa->sin6_addr, &addr.ip6, sizeof(struct in6_addr));
133 ret = 0;
135 else if (af == AF_INET) {
136 struct sockaddr_in *sa = (struct sockaddr_in *)dst;
137 memset(sa, 0, sizeof(struct sockaddr_in));
138 sa->sin_family = AF_INET;
139 sa->sin_port = port;
140 memcpy(&sa->sin_addr, &addr.ip4, sizeof(struct in_addr));
141 ret = 0;
143 else {
144 ws_assert_not_reached();
147 out:
148 g_free(addr_src);
149 return ret;