UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
net.h File Reference
#include <cstddef>
#include <cstdint>
Include dependency graph for net.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define CLOSESOCKET   close
 
#define IN6_BLACKHOLE_SERVER_MODE_STR   "100::556C:7472:4772:6453"
 
#define IN6_MAX_ASCII_LEN   39
 

Functions

bool get_local_addresses (struct sockaddr_storage *addrs, size_t *len, int ip_version)
 
unsigned get_sockaddr_addr_port (struct sockaddr *sa)
 
void get_sockaddr_addr_str (struct sockaddr *sa, char *buf, size_t n)
 
const char * get_sockaddr_str (struct sockaddr *sa)
 
bool is_addr_linklocal (struct sockaddr *sa)
 
bool is_addr_loopback (struct sockaddr *sa)
 
bool is_addr_multicast (const char *addr)
 
bool is_addr_private (struct sockaddr *sa)
 
bool is_host_loopback (const char *hostname)
 
bool is_host_private (const char *hostname)
 
bool is_ipv6_supported (void)
 
uint16_t socket_get_recv_port (int fd)
 
const char * ug_gai_strerror (int errcode)
 

Detailed Description

Author
Martin Pulec pulec.nosp@m.@ces.nosp@m.net.c.nosp@m.z

Definition in file net.h.

Macro Definition Documentation

◆ CLOSESOCKET

#define CLOSESOCKET   close

Definition at line 77 of file net.h.

◆ IN6_BLACKHOLE_SERVER_MODE_STR

#define IN6_BLACKHOLE_SERVER_MODE_STR   "100::556C:7472:4772:6453"

◆ IN6_MAX_ASCII_LEN

#define IN6_MAX_ASCII_LEN   39

Function Documentation

◆ get_local_addresses()

bool get_local_addresses ( struct sockaddr_storage * addrs,
size_t * len,
int ip_version )

Returns (in output parameter) list of local public IP addresses

Code was taken perhaps from: https://social.msdn.microsoft.com/Forums/en-US/3b6a92ac-93d3-4f59-a914-340c1ba41cff/how-to-retrieve-ip-addresses-of-the-network-cards-with-getadaptersaddresses

Parameters
[out]addrsstorage allocate to copy the addresses
[in]lenlength of allocated space (in bytes)
[out]lenlength of returned addresses (in parameter addrs, in bytes)
ip_version6 for IPv6, 4 for IPv6, 0 both

Definition at line 229 of file net.c.

230{
231 assert(ip_version == 0 || ip_version == 4 || ip_version == 6);
232#ifdef _WIN32
233#define WORKING_BUFFER_SIZE 15000
234#define MAX_TRIES 3
235 /* Declare and initialize variables */
236 DWORD dwRetVal = 0;
237 size_t len_remaining = *len;
238 *len = 0;
239
240 PIP_ADAPTER_ADDRESSES pAddresses = NULL;
241 ULONG outBufLen = 0;
242 ULONG Iterations = 0;
243
244 PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
245 PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
246
247 // Allocate a 15 KB buffer to start with.
248 outBufLen = WORKING_BUFFER_SIZE;
249
250 do {
251 pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen);
252 if (pAddresses == NULL) {
253 printf
254 ("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
255 return false;
256 }
257
258 ULONG family = ip_version == 4 ? AF_INET
259 : ip_version == 6 ? AF_INET6
260 : AF_UNSPEC; // both
261 dwRetVal =
262 GetAdaptersAddresses(family, 0, NULL, pAddresses, &outBufLen);
263
264 if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
265 free(pAddresses);
266 pAddresses = NULL;
267 } else {
268 break;
269 }
270 Iterations++;
271 } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));
272
273 if (dwRetVal == NO_ERROR) {
274 // If successful, output some information from the data we received
275 pCurrAddresses = pAddresses;
276 while (pCurrAddresses) {
277
278 pUnicast = pCurrAddresses->FirstUnicastAddress;
279 while (pUnicast != NULL) {
280 if (len_remaining < sizeof(addrs[0])) {
281 printf("Warning: insufficient space for all addresses.\n");
282 return true;
283 }
284 size_t sa_len = pUnicast->Address.lpSockaddr->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
285 memcpy(addrs, pUnicast->Address.lpSockaddr, sa_len);
286 addrs += 1;
287 *len += sizeof(addrs[0]);
288 len_remaining -= sizeof(addrs[0]);
289 pUnicast = pUnicast->Next;
290 }
291
292 pCurrAddresses = pCurrAddresses->Next;
293 }
294 } else {
295 printf("Call to GetAdaptersAddresses failed with error: %ld\n",
296 dwRetVal);
297 if (dwRetVal == ERROR_NO_DATA)
298 printf("\tNo addresses were found for the requested parameters\n");
299 else {
300 log_msg(LOG_LEVEL_ERROR, "Error: %s\n",
301 get_win32_error(dwRetVal));
302 if (pAddresses)
303 free(pAddresses);
304 return false;
305 }
306 }
307
308 if (pAddresses) {
309 free(pAddresses);
310 }
311
312 return true;
313#else // ! defined _WIN32
314 size_t available_len = *len;
315 *len = 0;
316 struct ifaddrs* a = NULL;
317 getifaddrs(&a);
318 struct ifaddrs* p = a;
319 while (NULL != p) {
320 if (p->ifa_addr == NULL ||
321 (ip_version == 0 && (p->ifa_addr->sa_family != AF_INET &&
322 p->ifa_addr->sa_family != AF_INET6)) ||
323 (ip_version == 4 && p->ifa_addr->sa_family != AF_INET) ||
324 (ip_version == 6 && p->ifa_addr->sa_family != AF_INET6)) {
325 p = p->ifa_next;
326 continue;
327 }
328 if (available_len < sizeof addrs[0]) {
329 MSG(WARNING,
330 "Warning: insufficient space for all addresses.\n");
331 return true;
332 }
333 size_t sa_len = p->ifa_addr->sa_family == AF_INET
334 ? sizeof(struct sockaddr_in)
335 : sizeof(struct sockaddr_in6);
336 memcpy(addrs, p->ifa_addr, sa_len);
337 addrs += 1;
338 *len += sizeof(addrs[0]);
339 available_len -= sizeof(addrs[0]);
340
341 p = p->ifa_next;
342 }
343 if (NULL != a) {
344 freeifaddrs(a);
345 }
346 return true;
347#endif
348}
int void size_t * len
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MSG(l, fmt,...)
Definition debug.h:96

References len, LOG_LEVEL_ERROR, log_msg(), and MSG.

Referenced by new_sdp().

Here is the call graph for this function:

◆ get_sockaddr_addr_port()

unsigned get_sockaddr_addr_port ( struct sockaddr * sa)

Definition at line 414 of file net.c.

414 {
415 unsigned port = 0;
416 if (sa->sa_family == AF_INET6) {
417 port = ntohs(((struct sockaddr_in6 *)(void *) sa)->sin6_port);
418 } else if (sa->sa_family == AF_INET) {
419 port = ntohs(((struct sockaddr_in *)(void *) sa)->sin_port);
420 } else {
421 return UINT_MAX;
422 }
423
424 return port;
425}

Referenced by get_sockaddr_str(), and Participant_manager::tick().

◆ get_sockaddr_addr_str()

void get_sockaddr_addr_str ( struct sockaddr * sa,
char * buf,
size_t n )

Definition at line 427 of file net.c.

427 {
428 assert(n >= IN6_MAX_ASCII_LEN + 3 /* []: */ + 1 /* \0 */);
429 const void *src = NULL;
430 if (sa->sa_family == AF_INET6) {
431 snprintf(buf, n, "[");
432 src = &((struct sockaddr_in6 *)(void *) sa)->sin6_addr;
433 } else if (sa->sa_family == AF_INET) {
434 src = &((struct sockaddr_in *)(void *) sa)->sin_addr;
435 } else {
436 snprintf(buf, n, "(unknown)");
437 return;
438 }
439 if (inet_ntop(sa->sa_family, src, buf + strlen(buf), n - strlen(buf)) == NULL) {
440 perror("get_sockaddr_str");
441 snprintf(buf, n, "(error)");
442 return;
443 }
444
445 if (sa->sa_family == AF_INET6) {
446 snprintf(buf + strlen(buf), n - strlen(buf), "]");
447 }
448}
#define IN6_MAX_ASCII_LEN
Definition net.h:50

References IN6_MAX_ASCII_LEN.

Referenced by get_sockaddr_str(), and Participant_manager::tick().

◆ get_sockaddr_str()

const char * get_sockaddr_str ( struct sockaddr * sa)

Definition at line 450 of file net.c.

451{
452 enum { ADDR_LEN = IN6_MAX_ASCII_LEN + 3 /* []: */ + 5 /* port */ + 1 /* \0 */ };
453 _Thread_local static char addr[ADDR_LEN] = "";
454 addr[0] = '\0';
455
456 get_sockaddr_addr_str(sa, addr, sizeof(addr));
457
458 unsigned port = get_sockaddr_addr_port(sa);
459 if(port == UINT_MAX)
460 return addr;
461 snprintf(addr + strlen(addr), ADDR_LEN - strlen(addr), ":%u", port);
462
463 return addr;
464}
unsigned get_sockaddr_addr_port(struct sockaddr *sa)
Definition net.c:414
void get_sockaddr_addr_str(struct sockaddr *sa, char *buf, size_t n)
Definition net.c:427

References get_sockaddr_addr_port(), get_sockaddr_addr_str(), and IN6_MAX_ASCII_LEN.

Referenced by rtp_process_data(), and Participant_manager::tick().

Here is the call graph for this function:

◆ is_addr_linklocal()

bool is_addr_linklocal ( struct sockaddr * sa)

Definition at line 79 of file net.c.

80{
81 switch (sa->sa_family) {
82 case AF_INET:
83 {
84 struct sockaddr_in *sin = (struct sockaddr_in *)(void *) sa;
85 uint32_t addr = ntohl(sin->sin_addr.s_addr);
86 if ((addr >> 16u) == IPV4_LL_PREFIX) {
87 return true;
88 }
89 return false;
90 }
91 case AF_INET6:
92 {
93 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)(void *) sa;
94 if (IN6_IS_ADDR_V4MAPPED(&sin->sin6_addr)) {
95 uint32_t v4_addr = ntohl(*((uint32_t*)(void *)(sin->sin6_addr.s6_addr + 12)));
96 if ((v4_addr >> 16u) == IPV4_LL_PREFIX) {
97 return true;
98 }
99 return false;
100 }
101 return IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr);
102 }
103 default:
104 return false;
105 }
106}
#define IPV4_LL_PREFIX
Definition net.c:70

References IPV4_LL_PREFIX.

Referenced by new_sdp().

◆ is_addr_loopback()

bool is_addr_loopback ( struct sockaddr * sa)

Definition at line 108 of file net.c.

109{
110 switch (sa->sa_family) {
111 case AF_UNIX:
112 return true;
113 case AF_INET:
114 {
115 struct sockaddr_in *sin = (struct sockaddr_in *)(void *) sa;
116 uint32_t addr = ntohl(sin->sin_addr.s_addr);
117 if ((addr >> 24u) == IN_LOOPBACKNET) {
118 return true;
119 }
120 return false;
121 }
122 case AF_INET6:
123 {
124 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)(void *) sa;
125 if (IN6_IS_ADDR_V4MAPPED(&sin->sin6_addr)) {
126 uint32_t v4_addr = ntohl(*((uint32_t*)(void *)(sin->sin6_addr.s6_addr + 12)));
127 if ((v4_addr >> 24u) == IN_LOOPBACKNET) {
128 return true;
129 }
130 return false;
131 }
132 return IN6_IS_ADDR_LOOPBACK(&sin->sin6_addr);
133 }
134 default:
135 return false;
136 }
137}
#define IN_LOOPBACKNET
Definition net.c:74

References IN_LOOPBACKNET.

Referenced by control_thread(), is_host_loopback(), is_host_private(), and new_sdp().

◆ is_addr_multicast()

bool is_addr_multicast ( const char * addr)

Definition at line 382 of file net.c.

383{
384 if (is_addr4(addr)) {
385 unsigned int first_addr_byte = atoi(addr);
386 if ((first_addr_byte >> 4) == 0xe) {
387 return true;
388 }
389 return false;
390
391 }
392 if (is_addr6(addr)) {
393 if (strlen(addr) >= 2 && addr[0] == 'f' && addr[1] == 'f') {
394 return true;
395 }
396 return false;
397
398 }
399 return false;
400}
static bool is_addr6(const char *addr)
Definition net.c:368
static bool is_addr4(const char *addr)
Definition net.c:353

References is_addr4(), and is_addr6().

Referenced by udp_init_if().

Here is the call graph for this function:

◆ is_addr_private()

bool is_addr_private ( struct sockaddr * sa)

Definition at line 139 of file net.c.

140{
141 switch (sa->sa_family) {
142 case AF_UNIX:
143 return true;
144 case AF_INET:
145 {
146 struct sockaddr_in *sin = (struct sockaddr_in *)(void *) sa;
147 uint32_t addr = ntohl(sin->sin_addr.s_addr);
148 return ((addr >> 24U) == 10) || ((addr >> 20U) == 2753) || ((addr >> 16U) == 49320);
149 }
150 case AF_INET6:
151 {
152 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)(void *) sa;
153 return (sin->sin6_addr.s6_addr[0] & 0xFEU) == 0xFCU; // ULA
154 }
155 default:
156 return false;
157 }
158}

Referenced by start_nat_traverse().

◆ is_host_loopback()

bool is_host_loopback ( const char * hostname)

Definition at line 174 of file net.c.

175{
176 struct addrinfo *ai = resolve_host(hostname, "is_host_loopback: ");
177 if (ai == NULL) {
178 return false;
179 }
180
181 bool ret = is_addr_loopback(ai->ai_addr);
182 freeaddrinfo(ai);
183
184 return ret;
185}
static struct addrinfo * resolve_host(const char *hostname, const char *err_prefix)
Definition net.c:160
bool is_addr_loopback(struct sockaddr *sa)
Definition net.c:108

References is_addr_loopback(), and resolve_host().

Referenced by adjust_params(), rtp_init_if(), start_nat_traverse(), and udp_init_if().

Here is the call graph for this function:

◆ is_host_private()

bool is_host_private ( const char * hostname)

Definition at line 187 of file net.c.

188{
189 struct addrinfo *ai = resolve_host(hostname, "is_host_private: ");
190 if (ai == NULL) {
191 return false;
192 }
193
194 bool ret = is_addr_loopback(ai->ai_addr);
195 freeaddrinfo(ai);
196
197 return ret;
198}

References is_addr_loopback(), and resolve_host().

Referenced by start_nat_traverse().

Here is the call graph for this function:

◆ is_ipv6_supported()

bool is_ipv6_supported ( void )

Definition at line 402 of file net.c.

403{
404 fd_t fd = socket(AF_INET6, SOCK_DGRAM, 0);
405 if (fd == INVALID_SOCKET && errno == EAFNOSUPPORT) {
406 return false;
407 }
408 if (fd != INVALID_SOCKET) {
409 closesocket(fd);
410 }
411 return true;
412}
int fd_t
#define INVALID_SOCKET
Definition net.c:53
#define closesocket
Definition net.c:52

References closesocket, and INVALID_SOCKET.

Referenced by adjust_params().

◆ socket_get_recv_port()

uint16_t socket_get_recv_port ( int fd)

Definition at line 200 of file net.c.

201{
202 struct sockaddr_storage ss;
203 socklen_t len = sizeof(ss);
204 if (getsockname(fd, (struct sockaddr *)&ss, &len) == -1) {
205 perror("getsockname");
206 return 0;
207 }
208 switch (ss.ss_family) {
209 case AF_INET:
210 return ntohs(((struct sockaddr_in *) &ss)->sin_port);
211 case AF_INET6:
212 return ntohs(((struct sockaddr_in6 *) &ss)->sin6_port);
213 default:
214 return 0;
215 }
216}

References len.

Referenced by control_start(), and process_messages().

◆ ug_gai_strerror()

const char * ug_gai_strerror ( int errcode)

Definition at line 466 of file net.c.

467{
468#ifdef _WIN32
469 UNUSED(errcode);
470 // also `win_wstr_to_str(gai_strerrorW(errcode);` would work; it is localized, but with correct diacritics
471 return get_win32_error(WSAGetLastError());
472#else
473 return gai_strerror(errcode);
474#endif // ! defined _WIN32
475}
#define UNUSED(x)

References UNUSED.

Referenced by resolve_addrinfo(), resolve_host(), udp_host_addr6(), and udp_init_if().