Lely core libraries 2.3.4
addr.c
Go to the documentation of this file.
1
24#include "io.h"
25
26#if !LELY_NO_STDIO
27
28#include <lely/io/addr.h>
29#include <lely/io/sock.h>
30#include <lely/util/cmp.h>
31#include <lely/util/errnum.h>
32
33#include <assert.h>
34#include <string.h>
35
36#if _WIN32
37
38#include <ctype.h>
39#include <stdio.h>
40#include <stdlib.h>
41
42static int ba2str(const BTH_ADDR *ba, char *str);
43static int str2ba(const char *str, BTH_ADDR *ba);
44static int bachk(const char *str);
45
46#elif _POSIX_C_SOURCE >= 200112L
47#include <netdb.h>
48#endif
49
50int
51io_addr_cmp(const void *p1, const void *p2)
52{
53 if (p1 == p2)
54 return 0;
55
56 if (!p1)
57 return -1;
58 if (!p2)
59 return 1;
60
61 const io_addr_t *a1 = p1;
62 const io_addr_t *a2 = p2;
63
64 int cmp = memcmp(&a1->addr, &a2->addr, MIN(a1->addrlen, a2->addrlen));
65 if (!cmp)
66 cmp = (a2->addrlen < a1->addrlen) - (a1->addrlen < a2->addrlen);
67 return cmp;
68}
69
70// clang-format off
71#if _WIN32 || (defined(__linux__) \
72 && defined(HAVE_BLUETOOTH_BLUETOOTH_H) \
73 && defined(HAVE_BLUETOOTH_RFCOMM_H))
74// clang-format on
75
76int
77io_addr_get_rfcomm_a(const io_addr_t *addr, char *ba, int *port)
78{
79 assert(addr);
80
81#if _WIN32
82 if (addr->addrlen < (int)sizeof(SOCKADDR_BTH)) {
83 WSASetLastError(WSAEINVAL);
84 return -1;
85 }
86
87 const SOCKADDR_BTH *addr_bth = (const SOCKADDR_BTH *)&addr->addr;
88 if (addr_bth->addressFamily != AF_BTH) {
89 WSASetLastError(WSAEAFNOSUPPORT);
90 return -1;
91 }
92
93 if (port)
94 *port = addr_bth->port == BT_PORT_ANY ? 0 : addr_bth->port;
95 if (ba && ba2str(&addr_bth->btAddr, ba) < 0)
96 return -1;
97#else
98 if (addr->addrlen < (int)sizeof(struct sockaddr_rc)) {
99 errno = EINVAL;
100 return -1;
101 }
102
103 const struct sockaddr_rc *addr_rc =
104 (const struct sockaddr_rc *)&addr->addr;
105 if (addr_rc->rc_family != AF_BLUETOOTH) {
106 errno = EAFNOSUPPORT;
107 return -1;
108 }
109
110 if (port)
111 *port = btohs(addr_rc->rc_channel);
112 if (ba && ba2str(&addr_rc->rc_bdaddr, ba) < 0)
113 return -1;
114#endif
115
116 return 0;
117}
118
119int
120io_addr_set_rfcomm_a(io_addr_t *addr, const char *ba, int port)
121{
122 assert(addr);
123
124 memset(addr, 0, sizeof(*addr));
125#if _WIN32
126 addr->addrlen = sizeof(SOCKADDR_BTH);
127 SOCKADDR_BTH *addr_bth = (SOCKADDR_BTH *)&addr->addr;
128
129 addr_bth->addressFamily = AF_BTH;
130 addr_bth->port = port ? (ULONG)port : BT_PORT_ANY;
131 addr_bth->btAddr = 0;
132 if (ba && *ba) {
133 if (str2ba(ba, &addr_bth->btAddr) < 0)
134 return -1;
135 }
136#else
137 addr->addrlen = sizeof(struct sockaddr_rc);
138 struct sockaddr_rc *addr_rc = (struct sockaddr_rc *)&addr->addr;
139
140 addr_rc->rc_family = AF_BLUETOOTH;
141 addr_rc->rc_channel = htobs(port);
142 if (ba && *ba) {
143 if (str2ba(ba, &addr_rc->rc_bdaddr) < 0)
144 return -1;
145 } else {
146 bacpy(&addr_rc->rc_bdaddr, BDADDR_ANY);
147 }
148#endif
149
150 return 0;
151}
152
153int
154io_addr_get_rfcomm_n(const io_addr_t *addr, uint8_t ba[6], int *port)
155{
156 assert(addr);
157
158#if _WIN32
159 if (addr->addrlen < (int)sizeof(SOCKADDR_BTH)) {
160 WSASetLastError(WSAEINVAL);
161 return -1;
162 }
163
164 const SOCKADDR_BTH *addr_bth = (const SOCKADDR_BTH *)&addr->addr;
165 if (addr_bth->addressFamily != AF_BTH) {
166 WSASetLastError(WSAEAFNOSUPPORT);
167 return -1;
168 }
169
170 if (port)
171 *port = addr_bth->port == BT_PORT_ANY ? 0 : addr_bth->port;
172 if (ba) {
173 for (int i = 0; i < 6; i++)
174 ba[i] = (addr_bth->btAddr >> (7 - i) * 8) & 0xff;
175 }
176#else
177 if (addr->addrlen < (int)sizeof(struct sockaddr_rc)) {
178 errno = EINVAL;
179 return -1;
180 }
181
182 const struct sockaddr_rc *addr_rc =
183 (const struct sockaddr_rc *)&addr->addr;
184 if (addr_rc->rc_family != AF_BLUETOOTH) {
185 errno = EAFNOSUPPORT;
186 return -1;
187 }
188
189 if (port)
190 *port = btohs(addr_rc->rc_channel);
191 if (ba)
192 memcpy(ba, &addr_rc->rc_bdaddr, 6);
193#endif
194
195 return 0;
196}
197
198void
199io_addr_set_rfcomm_n(io_addr_t *addr, const uint8_t ba[6], int port)
200{
201 assert(addr);
202
203 memset(addr, 0, sizeof(*addr));
204#if _WIN32
205 addr->addrlen = sizeof(SOCKADDR_BTH);
206 SOCKADDR_BTH *addr_bth = (SOCKADDR_BTH *)&addr->addr;
207
208 addr_bth->addressFamily = AF_BTH;
209 addr_bth->port = port ? (ULONG)port : BT_PORT_ANY;
210 addr_bth->btAddr = 0;
211 if (ba && *ba) {
212 for (int i = 0; i < 6; i++)
213 addr_bth->btAddr |= (BTH_ADDR)ba[i] << (7 - i) * 8;
214 }
215#else
216 addr->addrlen = sizeof(struct sockaddr_rc);
217 struct sockaddr_rc *addr_rc = (struct sockaddr_rc *)&addr->addr;
218
219 addr_rc->rc_family = AF_BLUETOOTH;
220 addr_rc->rc_channel = htobs(port);
221 if (ba && *ba)
222 memcpy(&addr_rc->rc_bdaddr, ba, 6);
223 else
224 bacpy(&addr_rc->rc_bdaddr, BDADDR_ANY);
225#endif
226}
227
228void
230{
231 assert(addr);
232
233 memset(addr, 0, sizeof(*addr));
234#if _WIN32
235 addr->addrlen = sizeof(SOCKADDR_BTH);
236 SOCKADDR_BTH *addr_bth = (SOCKADDR_BTH *)&addr->addr;
237
238 addr_bth->addressFamily = AF_BTH;
239 addr_bth->port = port ? (ULONG)port : BT_PORT_ANY;
240 addr_bth->btAddr = (BTH_ADDR)0xffffff000000ull;
241#else
242 addr->addrlen = sizeof(struct sockaddr_rc);
243 struct sockaddr_rc *addr_rc = (struct sockaddr_rc *)&addr->addr;
244
245 addr_rc->rc_family = AF_BLUETOOTH;
246 addr_rc->rc_channel = htobs(port);
247 bacpy(&addr_rc->rc_bdaddr, BDADDR_LOCAL);
248#endif
249}
250
251// clang-format off
252#endif // _WIN32 || (__linux__ && HAVE_BLUETOOTH_BLUETOOTH_H && HAVE_BLUETOOTH_RFCOMM_H)
253// clang-format on
254
255#if _WIN32 || _POSIX_C_SOURCE >= 200112L
256
257int
258io_addr_get_ipv4_a(const io_addr_t *addr, char *ip, int *port)
259{
260 assert(addr);
261
262 if (addr->addrlen < (int)sizeof(struct sockaddr_in)) {
264 return -1;
265 }
266
267 const struct sockaddr_in *addr_in =
268 (const struct sockaddr_in *)&addr->addr;
269 if (addr_in->sin_family != AF_INET) {
271 return -1;
272 }
273
274 if (port)
275 *port = ntohs(addr_in->sin_port);
276 // clang-format off
277 if (ip && !inet_ntop(AF_INET, (void *)&addr_in->sin_addr, ip,
279 // clang-format on
280 return -1;
281
282 return 0;
283}
284
285int
286io_addr_set_ipv4_a(io_addr_t *addr, const char *ip, int port)
287{
288 assert(addr);
289
290 memset(addr, 0, sizeof(*addr));
291 addr->addrlen = sizeof(struct sockaddr_in);
292 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr->addr;
293
294 addr_in->sin_family = AF_INET;
295 addr_in->sin_port = htons(port);
296 if (ip && *ip) {
297 if (inet_pton(AF_INET, ip, &addr_in->sin_addr) != 1)
298 return -1;
299 } else {
300 addr_in->sin_addr.s_addr = htonl(INADDR_ANY);
301 }
302
303 return 0;
304}
305
306int
307io_addr_get_ipv4_n(const io_addr_t *addr, uint8_t ip[4], int *port)
308{
309 assert(addr);
310
311 if (addr->addrlen < (int)sizeof(struct sockaddr_in)) {
313 return -1;
314 }
315
316 const struct sockaddr_in *addr_in =
317 (const struct sockaddr_in *)&addr->addr;
318 if (addr_in->sin_family != AF_INET) {
320 return -1;
321 }
322
323 if (port)
324 *port = ntohs(addr_in->sin_port);
325 if (ip)
326 memcpy(ip, &addr_in->sin_addr.s_addr, 4);
327
328 return 0;
329}
330
331void
332io_addr_set_ipv4_n(io_addr_t *addr, const uint8_t ip[4], int port)
333{
334 assert(addr);
335
336 memset(addr, 0, sizeof(*addr));
337 addr->addrlen = sizeof(struct sockaddr_in);
338 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr->addr;
339
340 addr_in->sin_family = AF_INET;
341 addr_in->sin_port = htons(port);
342 if (ip)
343 memcpy(&addr_in->sin_addr.s_addr, ip, 4);
344 else
345 addr_in->sin_addr.s_addr = htonl(INADDR_ANY);
346}
347
348void
350{
351 assert(addr);
352
353 memset(addr, 0, sizeof(*addr));
354 addr->addrlen = sizeof(struct sockaddr_in);
355 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr->addr;
356
357 addr_in->sin_family = AF_INET;
358 addr_in->sin_port = htons(port);
359 addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
360}
361
362void
364{
365 assert(addr);
366
367 memset(addr, 0, sizeof(*addr));
368 addr->addrlen = sizeof(struct sockaddr_in);
369 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr->addr;
370
371 addr_in->sin_family = AF_INET;
372 addr_in->sin_port = htons(port);
373 addr_in->sin_addr.s_addr = htonl(INADDR_BROADCAST);
374}
375
376int
377io_addr_get_ipv6_a(const io_addr_t *addr, char *ip, int *port)
378{
379 assert(addr);
380
381 if (addr->addrlen < (int)sizeof(struct sockaddr_in6)) {
383 return -1;
384 }
385
386 const struct sockaddr_in6 *addr_in6 =
387 (const struct sockaddr_in6 *)&addr->addr;
388 if (addr_in6->sin6_family != AF_INET6) {
390 return -1;
391 }
392
393 if (port)
394 *port = ntohs(addr_in6->sin6_port);
395 // clang-format off
396 if (ip && !inet_ntop(AF_INET6, (void *)&addr_in6->sin6_addr, ip,
398 // clang-format on
399 return -1;
400
401 return 0;
402}
403
404int
405io_addr_set_ipv6_a(io_addr_t *addr, const char *ip, int port)
406{
407 assert(addr);
408
409 memset(addr, 0, sizeof(*addr));
410 addr->addrlen = sizeof(struct sockaddr_in6);
411 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr->addr;
412
413 addr_in6->sin6_family = AF_INET6;
414 addr_in6->sin6_port = htons(port);
415 if (ip && *ip) {
416 if (inet_pton(AF_INET6, ip, &addr_in6->sin6_addr) != 1)
417 return -1;
418 } else {
419 addr_in6->sin6_addr = in6addr_any;
420 }
421
422 return 0;
423}
424
425int
426io_addr_get_ipv6_n(const io_addr_t *addr, uint8_t ip[16], int *port)
427{
428 assert(addr);
429
430 if (addr->addrlen < (int)sizeof(struct sockaddr_in6)) {
432 return -1;
433 }
434
435 const struct sockaddr_in6 *addr_in6 =
436 (const struct sockaddr_in6 *)&addr->addr;
437 if (addr_in6->sin6_family != AF_INET6) {
439 return -1;
440 }
441
442 if (port)
443 *port = ntohs(addr_in6->sin6_port);
444 if (ip)
445 memcpy(ip, &addr_in6->sin6_addr.s6_addr, 16);
446
447 return 0;
448}
449
450void
451io_addr_set_ipv6_n(io_addr_t *addr, const uint8_t ip[16], int port)
452{
453 assert(addr);
454
455 memset(addr, 0, sizeof(*addr));
456 addr->addrlen = sizeof(struct sockaddr_in6);
457 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr->addr;
458
459 addr_in6->sin6_family = AF_INET6;
460 addr_in6->sin6_port = htons(port);
461 if (ip)
462 memcpy(&addr_in6->sin6_addr.s6_addr, ip, 16);
463 else
464 addr_in6->sin6_addr = in6addr_any;
465}
466
467void
469{
470 assert(addr);
471
472 memset(addr, 0, sizeof(*addr));
473 addr->addrlen = sizeof(struct sockaddr_in6);
474 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr->addr;
475
476 addr_in6->sin6_family = AF_INET6;
477 addr_in6->sin6_port = htons(port);
478 addr_in6->sin6_addr = in6addr_loopback;
479}
480
481#endif // _WIN32 || _POSIX_C_SOURCE >= 200112L
482
483#if _POSIX_C_SOURCE >= 200112L
484
485int
486io_addr_get_unix(const io_addr_t *addr, char *path)
487{
488 assert(addr);
489
490 if (addr->addrlen < (int)sizeof(struct sockaddr_un)) {
491 errno = EINVAL;
492 return -1;
493 }
494
495 const struct sockaddr_un *addr_un =
496 (const struct sockaddr_un *)&addr->addr;
497 if (addr_un->sun_family != AF_UNIX) {
498 errno = EAFNOSUPPORT;
499 return -1;
500 }
501
502 if (path)
503 strncpy(path, addr_un->sun_path, IO_ADDR_UNIX_STRLEN);
504
505 return 0;
506}
507
508void
509io_addr_set_unix(io_addr_t *addr, const char *path)
510{
511 assert(addr);
512 assert(path);
513
514 memset(addr, 0, sizeof(*addr));
515 addr->addrlen = sizeof(struct sockaddr_un);
516 struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr->addr;
517
518 addr_un->sun_family = AF_UNIX;
519
520 size_t n = MIN(strlen(path), sizeof(addr_un->sun_path) - 1);
521 memcpy(addr_un->sun_path, path, n);
522 addr_un->sun_path[n] = '\0';
523}
524
525#endif // _POSIX_C_SOURCE >= 200112L
526
527#if _WIN32 || _POSIX_C_SOURCE >= 200112L
528
529int
531{
532 assert(addr);
533
534 switch (((const struct sockaddr *)&addr->addr)->sa_family) {
535#if _WIN32
536 case AF_BTH: return IO_SOCK_BTH;
537#elif defined(__linux__) && defined(HAVE_BLUETOOTH_BLUETOOTH_H) \
538 && defined(HAVE_BLUETOOTH_RFCOMM_H)
539 case AF_BLUETOOTH: return IO_SOCK_BTH;
540#endif
541 case AF_INET: return IO_SOCK_IPV4;
542 case AF_INET6: return IO_SOCK_IPV6;
543#if _POSIX_C_SOURCE >= 200112L
544 case AF_UNIX: return IO_SOCK_UNIX;
545#endif
546 default: set_errnum(ERRNUM_AFNOSUPPORT); return -1;
547 }
548}
549
550int
551io_addr_get_port(const io_addr_t *addr, int *port)
552{
553 assert(addr);
554
555 if (addr->addrlen < (int)sizeof(sa_family_t)) {
557 return -1;
558 }
559
560 switch (((const struct sockaddr *)&addr->addr)->sa_family) {
561#if _WIN32
562 case AF_BTH: {
563 if (addr->addrlen < (int)sizeof(SOCKADDR_BTH)) {
564 WSASetLastError(WSAEINVAL);
565 return -1;
566 }
567 const SOCKADDR_BTH *addr_bth =
568 (const SOCKADDR_BTH *)&addr->addr;
569 if (port)
570 // clang-format off
571 *port = addr_bth->port == BT_PORT_ANY
572 ? 0 : addr_bth->port;
573 // clang-format on
574 return 0;
575 }
576#elif defined(__linux__) && defined(HAVE_BLUETOOTH_BLUETOOTH_H) \
577 && defined(HAVE_BLUETOOTH_RFCOMM_H)
578 case AF_BLUETOOTH: {
579 if (addr->addrlen < (int)sizeof(struct sockaddr_rc)) {
580 errno = EINVAL;
581 return -1;
582 }
583 const struct sockaddr_rc *addr_rc =
584 (const struct sockaddr_rc *)&addr->addr;
585 if (port)
586 *port = btohs(addr_rc->rc_channel);
587 return 0;
588 }
589#endif
590 case AF_INET: {
591 if (addr->addrlen < (int)sizeof(struct sockaddr_in)) {
593 return -1;
594 }
595 const struct sockaddr_in *addr_in =
596 (const struct sockaddr_in *)&addr->addr;
597 if (port)
598 *port = ntohs(addr_in->sin_port);
599 return 0;
600 }
601 case AF_INET6: {
602 if (addr->addrlen < (int)sizeof(struct sockaddr_in6)) {
604 return -1;
605 }
606 const struct sockaddr_in6 *addr_in6 =
607 (const struct sockaddr_in6 *)&addr->addr;
608 if (port)
609 *port = ntohs(addr_in6->sin6_port);
610 return 0;
611 }
612 default: set_errnum(ERRNUM_AFNOSUPPORT); return -1;
613 }
614}
615
616int
618{
619 assert(addr);
620
621 if (addr->addrlen < (int)sizeof(sa_family_t)) {
623 return -1;
624 }
625
626 switch (((struct sockaddr *)&addr->addr)->sa_family) {
627#if _WIN32
628 case AF_BTH:
629 if (addr->addrlen < (int)sizeof(SOCKADDR_BTH)) {
630 WSASetLastError(WSAEINVAL);
631 return -1;
632 }
633 ((SOCKADDR_BTH *)&addr->addr)->port =
634 port ? (ULONG)port : BT_PORT_ANY;
635 ;
636 return 0;
637#elif defined(__linux__) && defined(HAVE_BLUETOOTH_BLUETOOTH_H) \
638 && defined(HAVE_BLUETOOTH_RFCOMM_H)
639 case AF_BLUETOOTH:
640 if (addr->addrlen < (int)sizeof(struct sockaddr_rc)) {
641 errno = EINVAL;
642 return -1;
643 }
644 ((struct sockaddr_rc *)&addr->addr)->rc_channel = htobs(port);
645 return 0;
646#endif
647 case AF_INET:
648 if (addr->addrlen < (int)sizeof(struct sockaddr_in)) {
650 return -1;
651 }
652 ((struct sockaddr_in *)&addr->addr)->sin_port = htons(port);
653 return 0;
654 case AF_INET6:
655 if (addr->addrlen < (int)sizeof(struct sockaddr_in6)) {
657 return -1;
658 }
659 ((struct sockaddr_in6 *)&addr->addr)->sin6_port = htons(port);
660 return 0;
661 default: set_errnum(ERRNUM_AFNOSUPPORT); return -1;
662 }
663}
664
665int
667{
668 assert(addr);
669
670 if (addr->addrlen < (int)sizeof(sa_family_t))
671 return 0;
672
673 switch (((const struct sockaddr *)&addr->addr)->sa_family) {
674 case AF_INET: {
675 if (addr->addrlen < (int)sizeof(struct sockaddr_in))
676 return 0;
677 const struct sockaddr_in *addr_in =
678 (const struct sockaddr_in *)&addr->addr;
679 return ntohl(addr_in->sin_addr.s_addr) == INADDR_LOOPBACK;
680 }
681 case AF_INET6: {
682 if (addr->addrlen < (int)sizeof(struct sockaddr_in6))
683 return 0;
684 const struct sockaddr_in6 *addr_in6 =
685 (const struct sockaddr_in6 *)&addr->addr;
686 return !memcmp(&addr_in6->sin6_addr, &in6addr_any,
687 sizeof(in6addr_any));
688 }
689 default: return 0;
690 }
691}
692
693int
695{
696 assert(addr);
697
698 if (addr->addrlen < (int)sizeof(sa_family_t))
699 return 0;
700
701 switch (((const struct sockaddr *)&addr->addr)->sa_family) {
702 case AF_INET: {
703 if (addr->addrlen < (int)sizeof(struct sockaddr_in))
704 return 0;
705 const struct sockaddr_in *addr_in =
706 (const struct sockaddr_in *)&addr->addr;
707 return ntohl(addr_in->sin_addr.s_addr) == INADDR_BROADCAST;
708 }
709 default: return 0;
710 }
711}
712
713int
715{
716 assert(addr);
717
718 if (addr->addrlen < (int)sizeof(sa_family_t))
719 return 0;
720
721 switch (((const struct sockaddr *)&addr->addr)->sa_family) {
722 case AF_INET: {
723 if (addr->addrlen < (int)sizeof(struct sockaddr_in))
724 return 0;
725 const struct sockaddr_in *addr_in =
726 (const struct sockaddr_in *)&addr->addr;
727 return (ntohl(addr_in->sin_addr.s_addr) >> 28) == 0xe;
728 }
729 case AF_INET6: {
730 if (addr->addrlen < (int)sizeof(struct sockaddr_in6))
731 return 0;
732 const struct sockaddr_in6 *addr_in6 =
733 (const struct sockaddr_in6 *)&addr->addr;
734 return addr_in6->sin6_addr.s6_addr[0] == 0xff;
735 }
736 default: return 0;
737 }
738}
739
740int
741io_get_addrinfo(int maxinfo, struct io_addrinfo *info, const char *nodename,
742 const char *servname, const struct io_addrinfo *hints)
743{
744 if (!info)
745 maxinfo = 0;
746
747 int ecode = 0;
748
749 struct addrinfo ai_hints = { .ai_family = AF_UNSPEC };
750 if (hints) {
751 switch (hints->domain) {
752 case 0: break;
753 case IO_SOCK_IPV4: ai_hints.ai_family = AF_INET; break;
754 case IO_SOCK_IPV6: ai_hints.ai_family = AF_INET6; break;
755 default: ecode = EAI_FAMILY; break;
756 }
757
758 switch (hints->type) {
759 case 0: break;
760 case IO_SOCK_STREAM: ai_hints.ai_socktype = SOCK_STREAM; break;
761 case IO_SOCK_DGRAM: ai_hints.ai_socktype = SOCK_DGRAM; break;
762 default: ecode = EAI_SOCKTYPE; break;
763 }
764 }
765
766 struct addrinfo *res = NULL;
767 if (!ecode)
768 ecode = getaddrinfo(nodename, servname, &ai_hints, &res);
769 if (ecode) {
770 switch (ecode) {
771 case EAI_AGAIN: set_errnum(ERRNUM_AI_AGAIN); break;
772 case EAI_BADFLAGS: set_errnum(ERRNUM_AI_BADFLAGS); break;
773 case EAI_FAIL: set_errnum(ERRNUM_AI_FAIL); break;
774 case EAI_FAMILY: set_errnum(ERRNUM_AI_FAMILY); break;
775 case EAI_MEMORY: set_errnum(ERRNUM_AI_MEMORY); break;
776 case EAI_NONAME: set_errnum(ERRNUM_AI_NONAME); break;
777 case EAI_SERVICE: set_errnum(ERRNUM_AI_SERVICE); break;
778 case EAI_SOCKTYPE: set_errnum(ERRNUM_AI_SOCKTYPE); break;
779#ifdef EAI_SYSTEM
780 case EAI_SYSTEM: break;
781#endif
782 }
783 return -1;
784 }
785 assert(res);
786
787 int ninfo = 0;
788 for (struct addrinfo *ai = res; ai; ai = ai->ai_next) {
789 int domain;
790 switch (ai->ai_family) {
791 case AF_INET: domain = IO_SOCK_IPV4; break;
792 case AF_INET6: domain = IO_SOCK_IPV6; break;
793 default: continue;
794 }
795
796 int type;
797 switch (ai->ai_socktype) {
798 case SOCK_STREAM: type = IO_SOCK_STREAM; break;
799 case SOCK_DGRAM: type = IO_SOCK_DGRAM; break;
800 default: continue;
801 }
802
803 if (ninfo++ < maxinfo) {
804 memset(info, 0, sizeof(*info));
805 info->domain = domain;
806 info->type = type;
807 info->addr.addrlen = ai->ai_addrlen;
808 memcpy(&info->addr.addr, ai->ai_addr, ai->ai_addrlen);
809 info++;
810 }
811 }
812
813 freeaddrinfo(res);
814
815 return ninfo;
816}
817
818#endif // _WIN32 || _POSIX_C_SOURCE >= 200112L
819
820#if _WIN32
821
822static int
823ba2str(const BTH_ADDR *ba, char *str)
824{
825 return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
826 (int)((*ba >> 40) & 0xff), (int)((*ba >> 32) & 0xff),
827 (int)((*ba >> 24) & 0xff), (int)((*ba >> 16) & 0xff),
828 ((int)(*ba >> 8) & 0xff), (int)(*ba & 0xff));
829}
830
831static int
832str2ba(const char *str, BTH_ADDR *ba)
833{
834 if (bachk(str) < 0) {
835 *ba = 0;
836 return -1;
837 }
838
839 for (int i = 5; i >= 0; i--, str += 3)
840 *ba |= (BTH_ADDR)strtol(str, NULL, 16) << (i * 8);
841
842 return 0;
843}
844
845static int
846bachk(const char *str)
847{
848 assert(str);
849
850 if (strlen(str) != 17)
851 return -1;
852
853 while (*str) {
854 if (!isxdigit(*str++))
855 return -1;
856 if (!isxdigit(*str++))
857 return -1;
858 if (!*str)
859 break;
860 if (*str++ != ':')
861 return -1;
862 }
863
864 return 0;
865}
866
867#endif // _WIN32
868
869#endif // !LELY_NO_STDIO
int io_addr_get_domain(const io_addr_t *addr)
Obtains the domain of a network address.
Definition: addr.c:530
int io_addr_get_ipv6_n(const io_addr_t *addr, uint8_t ip[16], int *port)
Obtains an IPv6 address and port number from a network address.
Definition: addr.c:426
void io_addr_set_ipv4_n(io_addr_t *addr, const uint8_t ip[4], int port)
Initializes a network address from an IPv4 address and port number.
Definition: addr.c:332
void io_addr_set_ipv6_n(io_addr_t *addr, const uint8_t ip[16], int port)
Initializes a network address from an IPv6 address and port number.
Definition: addr.c:451
int io_addr_is_broadcast(const io_addr_t *addr)
Returns 1 if the network address is a broadcast address, and 0 if not.
Definition: addr.c:694
int io_get_addrinfo(int maxinfo, struct io_addrinfo *info, const char *nodename, const char *servname, const struct io_addrinfo *hints)
Obtains a list of network addresses corresponding to a host and/or service name.
Definition: addr.c:741
void io_addr_set_rfcomm_n(io_addr_t *addr, const uint8_t ba[6], int port)
Initializes a network address from an RFCOMM Bluetooth device address and port number.
Definition: addr.c:199
void io_addr_set_ipv6_loopback(io_addr_t *addr, int port)
Initializes a network address with the IPv6 loopback address and a port number.
Definition: addr.c:468
void io_addr_set_rfcomm_local(io_addr_t *addr, int port)
Initializes a network address with the local Bluetooth (RFCOMM) device address (FF:FF:FF:00:00:00) an...
Definition: addr.c:229
int io_addr_set_port(io_addr_t *addr, int port)
Initializes the port number of an IPv4 or IPv6 network address.
Definition: addr.c:617
int io_addr_is_multicast(const io_addr_t *addr)
Returns 1 if the network address is a multicast address, and 0 if not.
Definition: addr.c:714
int io_addr_cmp(const void *p1, const void *p2)
Compares two network addresses.
Definition: addr.c:51
int io_addr_set_ipv6_a(io_addr_t *addr, const char *ip, int port)
Initializes a network address from an IPv6 address and port number.
Definition: addr.c:405
int io_addr_get_port(const io_addr_t *addr, int *port)
Obtains the port number of an IPv4 or IPv6 network address.
Definition: addr.c:551
int io_addr_get_rfcomm_n(const io_addr_t *addr, uint8_t ba[6], int *port)
Obtains an RFCOMM Bluetooth device address and port number from a network address.
Definition: addr.c:154
void io_addr_set_ipv4_broadcast(io_addr_t *addr, int port)
Initializes a network address with the IPv4 broadcast address and a port number.
Definition: addr.c:363
int io_addr_get_ipv4_a(const io_addr_t *addr, char *ip, int *port)
Obtains an IPv4 address and port number from a network address.
Definition: addr.c:258
int io_addr_get_ipv6_a(const io_addr_t *addr, char *ip, int *port)
Obtains an IPv6 address and port number from a network address.
Definition: addr.c:377
int io_addr_get_ipv4_n(const io_addr_t *addr, uint8_t ip[4], int *port)
Obtains an IPv4 address and port number from a network address.
Definition: addr.c:307
int io_addr_get_rfcomm_a(const io_addr_t *addr, char *ba, int *port)
Obtains an RFCOMM Bluetooth device address and port number from a network address.
Definition: addr.c:77
int io_addr_set_rfcomm_a(io_addr_t *addr, const char *ba, int port)
Initializes a network address from an RFCOMM Bluetooth device address and port number.
Definition: addr.c:120
int io_addr_is_loopback(const io_addr_t *addr)
Returns 1 if the network address is a loopback address, and 0 if not.
Definition: addr.c:666
int io_addr_set_ipv4_a(io_addr_t *addr, const char *ip, int port)
Initializes a network address from an IPv4 address and port number.
Definition: addr.c:286
int io_addr_get_unix(const io_addr_t *addr, char *path)
Obtains a UNIX domain socket path name from a network address.
Definition: addr.c:486
void io_addr_set_unix(io_addr_t *addr, const char *path)
Initializes a network address from a UNIX domain socket path name.
Definition: addr.c:509
void io_addr_set_ipv4_loopback(io_addr_t *addr, int port)
Initializes a network address with the IPv4 loopback address and a port number.
Definition: addr.c:349
This header file is part of the I/O library; it contains the network address declarations.
#define IO_ADDR_IPV6_STRLEN
The maximum number of bytes required to hold the text representation of an IPv6 internet address,...
Definition: addr.h:67
#define IO_ADDR_IPV4_STRLEN
The maximum number of bytes required to hold the text representation of an IPv4 internet address,...
Definition: addr.h:61
#define IO_ADDR_UNIX_STRLEN
The maximum number of bytes required to hold the text representation of a UNIX domain socket path nam...
Definition: addr.h:73
This header file is part of the utilities library; it contains the comparison function definitions.
This header file is part of the utilities library; it contains the native and platform-independent er...
@ ERRNUM_AI_MEMORY
There was a memory allocation failure.
Definition: errnum.h:251
@ ERRNUM_AFNOSUPPORT
Address family not supported.
Definition: errnum.h:87
@ ERRNUM_AI_BADFLAGS
The flags had an invalid value.
Definition: errnum.h:242
@ ERRNUM_AI_SOCKTYPE
The intended socket type was not recognized.
Definition: errnum.h:259
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:132
@ ERRNUM_AI_AGAIN
The name could not be resolved at this time.
Definition: errnum.h:240
@ ERRNUM_AI_FAIL
A non-recoverable error occurred.
Definition: errnum.h:244
@ ERRNUM_AI_FAMILY
The address family was not recognized or the address length was invalid for the specified family.
Definition: errnum.h:249
@ ERRNUM_AI_SERVICE
The service passed was not recognized for the specified socket type.
Definition: errnum.h:257
@ ERRNUM_AI_NONAME
The name does not resolve for the supplied parameters.
Definition: errnum.h:253
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:424
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
This header file is part of the I/O library; it contains the network socket declarations.
@ IO_SOCK_DGRAM
A datagram-oriented, typically connectionless-mode, socket type.
Definition: sock.h:48
@ IO_SOCK_STREAM
A stream-oriented connection-mode socket type.
Definition: sock.h:43
@ IO_SOCK_IPV4
An IPv4 socket.
Definition: sock.h:31
@ IO_SOCK_UNIX
A UNIX domain socket (only supported on POSIX platforms).
Definition: sock.h:35
@ IO_SOCK_IPV6
An IPv6 socket.
Definition: sock.h:33
@ IO_SOCK_BTH
A Bluetooth socket.
Definition: sock.h:29
This is the internal header file of the Windows-specific I/O declarations.
This header file is part of the C11 and POSIX compatibility library; it includes <stdio....
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
This header file is part of the C11 and POSIX compatibility library; it includes <string....
An opaque network address type.
Definition: addr.h:30
union __io_addr::@5 addr
The network address.
int addrlen
The size (in bytes) of addr.
Definition: addr.h:32
A network address info structure.
Definition: addr.h:76
int type
The type of the socket (either IO_SOCK_STREAM or IO_SOCK_DGRAM).
Definition: addr.h:83
int domain
The domain of the socket (only IO_SOCK_IPV4 and IO_SOCK_IPV6 are supported).
Definition: addr.h:81
io_addr_t addr
The network address.
Definition: addr.h:85