BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file BAddr.h
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * @section DESCRIPTION
30 *
31 * Network address abstractions.
32 */
33  
34 #ifndef BADVPN_SYSTEM_BADDR_H
35 #define BADVPN_SYSTEM_BADDR_H
36  
37 #include <stdint.h>
38 #include <limits.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <stdio.h>
42  
43 #ifdef BADVPN_USE_WINAPI
44 #include <ws2tcpip.h>
45 #else
46 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <netdb.h>
49 #include <netinet/in.h>
50 #endif
51  
52 #include <misc/byteorder.h>
53 #include <misc/debug.h>
54 #include <misc/print_macros.h>
55 #include <misc/read_write_int.h>
56 #include <misc/compare.h>
57  
58 #define BADDR_TYPE_NONE 0
59 #define BADDR_TYPE_IPV4 1
60 #define BADDR_TYPE_IPV6 2
61 #ifdef BADVPN_LINUX
62 #define BADDR_TYPE_PACKET 5
63 #endif
64  
65 #define BADDR_MAX_ADDR_LEN 128
66  
67 #define BIPADDR_MAX_PRINT_LEN 40
68 #define BADDR_MAX_PRINT_LEN 120
69  
70 #define BADDR_PACKET_HEADER_TYPE_ETHERNET 1
71  
72 #define BADDR_PACKET_PACKET_TYPE_HOST 1
73 #define BADDR_PACKET_PACKET_TYPE_BROADCAST 2
74 #define BADDR_PACKET_PACKET_TYPE_MULTICAST 3
75 #define BADDR_PACKET_PACKET_TYPE_OTHERHOST 4
76 #define BADDR_PACKET_PACKET_TYPE_OUTGOING 5
77  
78 typedef struct {
79 int type;
80 union {
81 uint32_t ipv4;
82 uint8_t ipv6[16];
83 };
84 } BIPAddr;
85  
86 static void BIPAddr_InitInvalid (BIPAddr *addr);
87  
88 static void BIPAddr_InitIPv4 (BIPAddr *addr, uint32_t ip);
89  
90 static void BIPAddr_InitIPv6 (BIPAddr *addr, uint8_t *ip);
91  
92 static void BIPAddr_Assert (BIPAddr *addr);
93  
94 static int BIPAddr_IsInvalid (BIPAddr *addr);
95  
96 static int BIPAddr_Resolve (BIPAddr *addr, char *str, int noresolve) WARN_UNUSED;
97  
98 static int BIPAddr_Compare (BIPAddr *addr1, BIPAddr *addr2);
99  
100 static void BIPAddr_InitLocalhost (BIPAddr *addr, int addr_type);
101  
102 /**
103 * Converts an IP address to human readable form.
104 *
105 * @param addr IP address to convert
106 * @param out destination buffer. Must be at least BIPADDR_MAX_PRINT_LEN characters long.
107 */
108 static void BIPAddr_Print (BIPAddr *addr, char *out);
109  
110 /**
111 * Socket address - IP address and transport protocol port number
112 */
113 typedef struct {
114 int type;
115 union {
116 struct {
117 uint32_t ip;
118 uint16_t port;
119 } ipv4;
120 struct {
121 uint8_t ip[16];
122 uint16_t port;
123 } ipv6;
124 struct {
125 uint16_t phys_proto;
126 int interface_index;
127 int header_type;
128 int packet_type;
129 uint8_t phys_addr[8];
130 } packet;
131 };
132 } BAddr;
133  
134 /**
135 * Makes an invalid address.
136 */
137 static BAddr BAddr_MakeNone (void);
138  
139 /**
140 * Makes an IPv4 address.
141 *
142 * @param ip IP address in network byte order
143 * @param port port number in network byte order
144 */
145 static BAddr BAddr_MakeIPv4 (uint32_t ip, uint16_t port);
146  
147 /**
148 * Makes an IPv6 address.
149 *
150 * @param ip IP address (16 bytes)
151 * @param port port number in network byte order
152 */
153 static BAddr BAddr_MakeIPv6 (const uint8_t *ip, uint16_t port);
154  
155 /**
156 * Makes an address from a BIPAddr and port number.
157 *
158 * @param ipaddr the BIPAddr
159 * @param port port number in network byte order
160 */
161 static BAddr BAddr_MakeFromIpaddrAndPort (BIPAddr ipaddr, uint16_t port);
162  
163 /**
164 * Deprecated, use BAddr_MakeNone.
165 */
166 static void BAddr_InitNone (BAddr *addr);
167  
168 /**
169 * Deprecated, use BAddr_MakeIPv4.
170 */
171 static void BAddr_InitIPv4 (BAddr *addr, uint32_t ip, uint16_t port);
172  
173 /**
174 * Deprecated, use BAddr_MakeIPv6.
175 */
176 static void BAddr_InitIPv6 (BAddr *addr, uint8_t *ip, uint16_t port);
177  
178 /**
179 * Deprecated, use BAddr_MakeFromIpaddrAndPort.
180 */
181 static void BAddr_InitFromIpaddrAndPort (BAddr *addr, BIPAddr ipaddr, uint16_t port);
182  
183 /**
184 * Initializes a packet socket (data link layer) address.
185 * Only Ethernet addresses are supported.
186 *
187 * @param addr the object
188 * @param phys_proto identifier for the upper protocol, network byte order (EtherType)
189 * @param interface_index network interface index
190 * @param header_type data link layer header type. Must be BADDR_PACKET_HEADER_TYPE_ETHERNET.
191 * @param packet_type the manner in which packets are sent/received. Must be one of
192 * BADDR_PACKET_PACKET_TYPE_HOST, BADDR_PACKET_PACKET_TYPE_BROADCAST,
193 * BADDR_PACKET_PACKET_TYPE_MULTICAST, BADDR_PACKET_PACKET_TYPE_OTHERHOST,
194 * BADDR_PACKET_PACKET_TYPE_OUTGOING.
195 * @param phys_addr data link layer address (MAC address)
196 */
197 static void BAddr_InitPacket (BAddr *addr, uint16_t phys_proto, int interface_index, int header_type, int packet_type, uint8_t *phys_addr);
198  
199 /**
200 * Does nothing.
201 *
202 * @param addr the object
203 */
204 static void BAddr_Assert (BAddr *addr);
205  
206 /**
207 * Determines whether the address is an invalid address.
208 *
209 * @param addr the object
210 * @return 1 if invalid, 0 if invalid
211 **/
212 static int BAddr_IsInvalid (BAddr *addr);
213  
214 /**
215 * Returns the port number in the address.
216 *
217 * @param addr the object
218 * Must be an IPv4 or IPv6 address.
219 * @return port number, in network byte order
220 */
221 static uint16_t BAddr_GetPort (BAddr *addr);
222  
223 /**
224 * Returns the IP address in the address.
225 *
226 * @param addr the object
227 * @param ipaddr IP address will be returned here. If \a addr is not
228 * an IPv4 or IPv6 address, an invalid address will be
229 * returned.
230 */
231 static void BAddr_GetIPAddr (BAddr *addr, BIPAddr *ipaddr);
232  
233 /**
234 * Sets the port number in the address.
235 *
236 * @param addr the object
237 * Must be an IPv4 or IPv6 address.
238 * @param port port number, in network byte order
239 */
240 static void BAddr_SetPort (BAddr *addr, uint16_t port);
241  
242 /**
243 * Converts an IP address to human readable form.
244 *
245 * @param addr address to convert
246 * @param out destination buffer. Must be at least BADDR_MAX_PRINT_LEN characters long.
247 */
248 static void BAddr_Print (BAddr *addr, char *out);
249  
250 /**
251 * Resolves an address string.
252 * Format is "addr:port" for IPv4, "[addr]:port" for IPv6.
253 * addr is be a numeric address or a name.
254 * port is a numeric port number.
255 *
256 * @param addr output address
257 * @param name if not NULL, the name portion of the address will be
258 * stored here
259 * @param name_len if name is not NULL, the size of the name buffer
260 * @param noresolve only accept numeric addresses. Avoids blocking the caller.
261 * @return 1 on success, 0 on parse error
262 */
263 static int BAddr_Parse2 (BAddr *addr, char *str, char *name, int name_len, int noresolve) WARN_UNUSED;
264  
265 /**
266 * Resolves an address string.
267 * IPv4 input format is "a.b.c.d:p", where a.b.c.d is the IP address
268 * and d is the port number.
269 * IPv6 input format is "[addr]:p", where addr is an IPv6 addres in
270 * standard notation and p is the port number.
271 *
272 * @param addr output address
273 * @param name if not NULL, the name portion of the address will be
274 * stored here
275 * @param name_len if name is not NULL, the size of the name buffer
276 * @return 1 on success, 0 on parse error
277 */
278 static int BAddr_Parse (BAddr *addr, char *str, char *name, int name_len) WARN_UNUSED;
279  
280 static int BAddr_Compare (BAddr *addr1, BAddr *addr2);
281  
282 static int BAddr_CompareOrder (BAddr *addr1, BAddr *addr2);
283  
284 void BIPAddr_InitInvalid (BIPAddr *addr)
285 {
286 addr->type = BADDR_TYPE_NONE;
287 }
288  
289 void BIPAddr_InitIPv4 (BIPAddr *addr, uint32_t ip)
290 {
291 addr->type = BADDR_TYPE_IPV4;
292 addr->ipv4 = ip;
293 }
294  
295 void BIPAddr_InitIPv6 (BIPAddr *addr, uint8_t *ip)
296 {
297 addr->type = BADDR_TYPE_IPV6;
298 memcpy(addr->ipv6, ip, 16);
299 }
300  
301 void BIPAddr_Assert (BIPAddr *addr)
302 {
303 switch (addr->type) {
304 case BADDR_TYPE_NONE:
305 case BADDR_TYPE_IPV4:
306 case BADDR_TYPE_IPV6:
307 return;
308 default:
309 ASSERT(0);
310 }
311 }
312  
313 int BIPAddr_IsInvalid (BIPAddr *addr)
314 {
315 BIPAddr_Assert(addr);
316  
317 return (addr->type == BADDR_TYPE_NONE);
318 }
319  
320 int BIPAddr_Resolve (BIPAddr *addr, char *str, int noresolve)
321 {
322 int len = strlen(str);
323  
324 char *addr_start;
325 int addr_len;
326  
327 // determine address type
328 if (len >= 1 && str[0] == '[' && str[len - 1] == ']') {
329 addr->type = BADDR_TYPE_IPV6;
330 addr_start = str + 1;
331 addr_len = len - 2;
332 } else {
333 addr->type = BADDR_TYPE_IPV4;
334 addr_start = str;
335 addr_len = len;
336 }
337  
338 // copy
339 char addr_str[BADDR_MAX_ADDR_LEN + 1];
340 if (addr_len > BADDR_MAX_ADDR_LEN) {
341 return 0;
342 }
343 memcpy(addr_str, addr_start, addr_len);
344 addr_str[addr_len] = '\0';
345  
346 // initialize hints
347 struct addrinfo hints;
348 memset(&hints, 0, sizeof(hints));
349 switch (addr->type) {
350 case BADDR_TYPE_IPV6:
351 hints.ai_family = AF_INET6;
352 break;
353 case BADDR_TYPE_IPV4:
354 hints.ai_family = AF_INET;
355 break;
356 }
357 if (noresolve) {
358 hints.ai_flags |= AI_NUMERICHOST;
359 }
360  
361 // call getaddrinfo
362 struct addrinfo *addrs;
363 int res;
364 if ((res = getaddrinfo(addr_str, NULL, &hints, &addrs)) != 0) {
365 return 0;
366 }
367  
368 // set address
369 switch (addr->type) {
370 case BADDR_TYPE_IPV6:
371 memcpy(addr->ipv6, ((struct sockaddr_in6 *)addrs->ai_addr)->sin6_addr.s6_addr, sizeof(addr->ipv6));
372 break;
373 case BADDR_TYPE_IPV4:
374 addr->ipv4 = ((struct sockaddr_in *)addrs->ai_addr)->sin_addr.s_addr;
375 break;
376 }
377  
378 freeaddrinfo(addrs);
379  
380 return 1;
381 }
382  
383 int BIPAddr_Compare (BIPAddr *addr1, BIPAddr *addr2)
384 {
385 BIPAddr_Assert(addr1);
386 BIPAddr_Assert(addr2);
387  
388 if (addr1->type != addr2->type) {
389 return 0;
390 }
391  
392 switch (addr1->type) {
393 case BADDR_TYPE_NONE:
394 return 0;
395 case BADDR_TYPE_IPV4:
396 return (addr1->ipv4 == addr2->ipv4);
397 case BADDR_TYPE_IPV6:
398 return (!memcmp(addr1->ipv6, addr2->ipv6, sizeof(addr1->ipv6)));
399 default:
400 ASSERT(0)
401 return 0;
402 }
403 }
404  
405 uint16_t BAddr_GetPort (BAddr *addr)
406 {
407 BAddr_Assert(addr);
408 ASSERT(addr->type == BADDR_TYPE_IPV4 || addr->type == BADDR_TYPE_IPV6)
409  
410 switch (addr->type) {
411 case BADDR_TYPE_IPV4:
412 return addr->ipv4.port;
413 case BADDR_TYPE_IPV6:
414 return addr->ipv6.port;
415 default:
416 ASSERT(0)
417 return 0;
418 }
419 }
420  
421 void BAddr_GetIPAddr (BAddr *addr, BIPAddr *ipaddr)
422 {
423 BAddr_Assert(addr);
424  
425 switch (addr->type) {
426 case BADDR_TYPE_IPV4:
427 BIPAddr_InitIPv4(ipaddr, addr->ipv4.ip);
428 return;
429 case BADDR_TYPE_IPV6:
430 BIPAddr_InitIPv6(ipaddr, addr->ipv6.ip);
431 return;
432 default:
433 BIPAddr_InitInvalid(ipaddr);
434 }
435 }
436  
437 void BAddr_SetPort (BAddr *addr, uint16_t port)
438 {
439 BAddr_Assert(addr);
440 ASSERT(addr->type == BADDR_TYPE_IPV4 || addr->type == BADDR_TYPE_IPV6)
441  
442 switch (addr->type) {
443 case BADDR_TYPE_IPV4:
444 addr->ipv4.port = port;
445 break;
446 case BADDR_TYPE_IPV6:
447 addr->ipv6.port = port;
448 break;
449 default:
450 ASSERT(0);
451 }
452 }
453  
454 void BIPAddr_Print (BIPAddr *addr, char *out)
455 {
456 switch (addr->type) {
457 case BADDR_TYPE_NONE:
458 sprintf(out, "(none)");
459 break;
460 case BADDR_TYPE_IPV4:
461 sprintf(out, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8,
462 *((uint8_t *)&addr->ipv4 + 0),
463 *((uint8_t *)&addr->ipv4 + 1),
464 *((uint8_t *)&addr->ipv4 + 2),
465 *((uint8_t *)&addr->ipv4 + 3)
466 );
467 break;
468 case BADDR_TYPE_IPV6: {
469 const char *ptr = (const char *)addr->ipv6;
470 sprintf(out,
471 "%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16":"
472 "%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16,
473 badvpn_read_be16(ptr + 0),
474 badvpn_read_be16(ptr + 2),
475 badvpn_read_be16(ptr + 4),
476 badvpn_read_be16(ptr + 6),
477 badvpn_read_be16(ptr + 8),
478 badvpn_read_be16(ptr + 10),
479 badvpn_read_be16(ptr + 12),
480 badvpn_read_be16(ptr + 14)
481 );
482 } break;
483 default:
484 ASSERT(0);
485 }
486 }
487  
488 BAddr BAddr_MakeNone (void)
489 {
490 BAddr addr;
491 addr.type = BADDR_TYPE_NONE;
492 return addr;
493 }
494  
495 BAddr BAddr_MakeIPv4 (uint32_t ip, uint16_t port)
496 {
497 BAddr addr;
498 addr.type = BADDR_TYPE_IPV4;
499 addr.ipv4.ip = ip;
500 addr.ipv4.port = port;
501 return addr;
502 }
503  
504 BAddr BAddr_MakeIPv6 (const uint8_t *ip, uint16_t port)
505 {
506 BAddr addr;
507 addr.type = BADDR_TYPE_IPV6;
508 memcpy(addr.ipv6.ip, ip, 16);
509 addr.ipv6.port = port;
510 return addr;
511 }
512  
513 BAddr BAddr_MakeFromIpaddrAndPort (BIPAddr ipaddr, uint16_t port)
514 {
515 BIPAddr_Assert(&ipaddr);
516  
517 switch (ipaddr.type) {
518 case BADDR_TYPE_NONE:
519 return BAddr_MakeNone();
520 case BADDR_TYPE_IPV4:
521 return BAddr_MakeIPv4(ipaddr.ipv4, port);
522 case BADDR_TYPE_IPV6:
523 return BAddr_MakeIPv6(ipaddr.ipv6, port);
524 default:
525 ASSERT(0);
526 return BAddr_MakeNone();
527 }
528 }
529  
530 void BAddr_InitNone (BAddr *addr)
531 {
532 *addr = BAddr_MakeNone();
533 }
534  
535 void BAddr_InitIPv4 (BAddr *addr, uint32_t ip, uint16_t port)
536 {
537 *addr = BAddr_MakeIPv4(ip, port);
538 }
539  
540 void BAddr_InitIPv6 (BAddr *addr, uint8_t *ip, uint16_t port)
541 {
542 *addr = BAddr_MakeIPv6(ip, port);
543 }
544  
545 void BAddr_InitFromIpaddrAndPort (BAddr *addr, BIPAddr ipaddr, uint16_t port)
546 {
547 BIPAddr_Assert(&ipaddr);
548  
549 *addr = BAddr_MakeFromIpaddrAndPort(ipaddr, port);
550 }
551  
552 #ifdef BADVPN_LINUX
553  
554 void BAddr_InitPacket (BAddr *addr, uint16_t phys_proto, int interface_index, int header_type, int packet_type, uint8_t *phys_addr)
555 {
556 ASSERT(header_type == BADDR_PACKET_HEADER_TYPE_ETHERNET)
557 ASSERT(packet_type == BADDR_PACKET_PACKET_TYPE_HOST || packet_type == BADDR_PACKET_PACKET_TYPE_BROADCAST ||
558 packet_type == BADDR_PACKET_PACKET_TYPE_MULTICAST || packet_type == BADDR_PACKET_PACKET_TYPE_OTHERHOST ||
559 packet_type == BADDR_PACKET_PACKET_TYPE_OUTGOING)
560  
561 addr->type = BADDR_TYPE_PACKET;
562 addr->packet.phys_proto = phys_proto;
563 addr->packet.interface_index = interface_index;
564 addr->packet.header_type = header_type;
565 addr->packet.packet_type = packet_type;
566 memcpy(addr->packet.phys_addr, phys_addr, 6);
567 }
568  
569 #endif
570  
571 void BAddr_Assert (BAddr *addr)
572 {
573 switch (addr->type) {
574 case BADDR_TYPE_NONE:
575 case BADDR_TYPE_IPV4:
576 case BADDR_TYPE_IPV6:
577 #ifdef BADVPN_LINUX
578 case BADDR_TYPE_PACKET:
579 #endif
580 return;
581 default:
582 ASSERT(0);
583 }
584 }
585  
586 int BAddr_IsInvalid (BAddr *addr)
587 {
588 BAddr_Assert(addr);
589  
590 return (addr->type == BADDR_TYPE_NONE);
591 }
592  
593 void BAddr_Print (BAddr *addr, char *out)
594 {
595 BAddr_Assert(addr);
596  
597 BIPAddr ipaddr;
598  
599 switch (addr->type) {
600 case BADDR_TYPE_NONE:
601 sprintf(out, "(none)");
602 break;
603 case BADDR_TYPE_IPV4:
604 BIPAddr_InitIPv4(&ipaddr, addr->ipv4.ip);
605 BIPAddr_Print(&ipaddr, out);
606 sprintf(out + strlen(out), ":%"PRIu16, ntoh16(addr->ipv4.port));
607 break;
608 case BADDR_TYPE_IPV6:
609 BIPAddr_InitIPv6(&ipaddr, addr->ipv6.ip);
610 BIPAddr_Print(&ipaddr, out);
611 sprintf(out + strlen(out), ":%"PRIu16, ntoh16(addr->ipv6.port));
612 break;
613 #ifdef BADVPN_LINUX
614 case BADDR_TYPE_PACKET:
615 ASSERT(addr->packet.header_type == BADDR_PACKET_HEADER_TYPE_ETHERNET)
616 sprintf(out, "proto=%"PRIu16",ifindex=%d,htype=eth,ptype=%d,addr=%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8,
617 addr->packet.phys_proto, (int)addr->packet.interface_index, (int)addr->packet.packet_type,
618 addr->packet.phys_addr[0], addr->packet.phys_addr[1], addr->packet.phys_addr[2],
619 addr->packet.phys_addr[3], addr->packet.phys_addr[4], addr->packet.phys_addr[5]);
620 break;
621 #endif
622 default:
623 ASSERT(0);
624 }
625 }
626  
627 int BAddr_Parse2 (BAddr *addr, char *str, char *name, int name_len, int noresolve)
628 {
629 int len = strlen(str);
630 if (len < 1 || len > 1000) {
631 return 0;
632 }
633  
634 int addr_start;
635 int addr_len;
636 int port_start;
637 int port_len;
638  
639 // leading '[' indicates an IPv6 address
640 if (str[0] == '[') {
641 addr->type = BADDR_TYPE_IPV6;
642 // find ']'
643 int i=1;
644 while (i < len && str[i] != ']') i++;
645 if (i >= len) {
646 return 0;
647 }
648 addr_start = 1;
649 addr_len = i - addr_start;
650 // follows ':' and port number
651 if (i + 1 >= len || str[i + 1] != ':') {
652 return 0;
653 }
654 port_start = i + 2;
655 port_len = len - port_start;
656 }
657 // otherwise it's an IPv4 address
658 else {
659 addr->type = BADDR_TYPE_IPV4;
660 // find ':'
661 int i=0;
662 while (i < len && str[i] != ':') i++;
663 if (i >= len) {
664 return 0;
665 }
666 addr_start = 0;
667 addr_len = i - addr_start;
668 port_start = i + 1;
669 port_len = len - port_start;
670 }
671  
672 // copy address and port to zero-terminated buffers
673  
674 char addr_str[128];
675 if (addr_len >= sizeof(addr_str)) {
676 return 0;
677 }
678 memcpy(addr_str, str + addr_start, addr_len);
679 addr_str[addr_len] = '\0';
680  
681 char port_str[6];
682 if (port_len >= sizeof(port_str)) {
683 return 0;
684 }
685 memcpy(port_str, str + port_start, port_len);
686 port_str[port_len] = '\0';
687  
688 // parse port
689 char *err;
690 long int conv_res = strtol(port_str, &err, 10);
691 if (port_str[0] == '\0' || *err != '\0') {
692 return 0;
693 }
694 if (conv_res < 0 || conv_res > UINT16_MAX) {
695 return 0;
696 }
697 uint16_t port = conv_res;
698 port = hton16(port);
699  
700 // initialize hints
701 struct addrinfo hints;
702 memset(&hints, 0, sizeof(hints));
703 switch (addr->type) {
704 case BADDR_TYPE_IPV6:
705 hints.ai_family = AF_INET6;
706 break;
707 case BADDR_TYPE_IPV4:
708 hints.ai_family = AF_INET;
709 break;
710 }
711 if (noresolve) {
712 hints.ai_flags |= AI_NUMERICHOST;
713 }
714  
715 // call getaddrinfo
716 struct addrinfo *addrs;
717 int res;
718 if ((res = getaddrinfo(addr_str, NULL, &hints, &addrs)) != 0) {
719 return 0;
720 }
721  
722 // set address
723 switch (addr->type) {
724 case BADDR_TYPE_IPV6:
725 memcpy(addr->ipv6.ip, ((struct sockaddr_in6 *)addrs->ai_addr)->sin6_addr.s6_addr, sizeof(addr->ipv6.ip));
726 addr->ipv6.port = port;
727 break;
728 case BADDR_TYPE_IPV4:
729 addr->ipv4.ip = ((struct sockaddr_in *)addrs->ai_addr)->sin_addr.s_addr;
730 addr->ipv4.port = port;
731 break;
732 }
733  
734 freeaddrinfo(addrs);
735  
736 if (name) {
737 if (strlen(addr_str) >= name_len) {
738 return 0;
739 }
740 strcpy(name, addr_str);
741 }
742  
743 return 1;
744 }
745  
746 int BAddr_Parse (BAddr *addr, char *str, char *name, int name_len)
747 {
748 return BAddr_Parse2(addr, str, name, name_len, 0);
749 }
750  
751 int BAddr_Compare (BAddr *addr1, BAddr *addr2)
752 {
753 BAddr_Assert(addr1);
754 BAddr_Assert(addr2);
755  
756 if (addr1->type != addr2->type) {
757 return 0;
758 }
759  
760 switch (addr1->type) {
761 case BADDR_TYPE_IPV4:
762 return (addr1->ipv4.ip == addr2->ipv4.ip && addr1->ipv4.port == addr2->ipv4.port);
763 case BADDR_TYPE_IPV6:
764 return (!memcmp(addr1->ipv6.ip, addr2->ipv6.ip, sizeof(addr1->ipv6.ip)) && addr1->ipv6.port == addr2->ipv6.port);
765 default:
766 return 0;
767 }
768 }
769  
770 int BAddr_CompareOrder (BAddr *addr1, BAddr *addr2)
771 {
772 BAddr_Assert(addr1);
773 BAddr_Assert(addr2);
774  
775 int cmp = B_COMPARE(addr1->type, addr2->type);
776 if (cmp) {
777 return cmp;
778 }
779  
780 switch (addr1->type) {
781 case BADDR_TYPE_NONE: {
782 return 0;
783 } break;
784 case BADDR_TYPE_IPV4: {
785 uint32_t ip1 = ntoh32(addr1->ipv4.ip);
786 uint32_t ip2 = ntoh32(addr2->ipv4.ip);
787 cmp = B_COMPARE(ip1, ip2);
788 if (cmp) {
789 return cmp;
790 }
791 uint16_t port1 = ntoh16(addr1->ipv4.port);
792 uint16_t port2 = ntoh16(addr2->ipv4.port);
793 return B_COMPARE(port1, port2);
794 } break;
795 case BADDR_TYPE_IPV6: {
796 cmp = memcmp(addr1->ipv6.ip, addr2->ipv6.ip, sizeof(addr1->ipv6.ip));
797 if (cmp) {
798 return B_COMPARE(cmp, 0);
799 }
800 uint16_t port1 = ntoh16(addr1->ipv6.port);
801 uint16_t port2 = ntoh16(addr2->ipv6.port);
802 return B_COMPARE(port1, port2);
803 } break;
804 default: {
805 return 0;
806 } break;
807 }
808 }
809  
810 void BIPAddr_InitLocalhost (BIPAddr *addr, int addr_type)
811 {
812 if (addr_type == BADDR_TYPE_IPV4) {
813 addr->type = addr_type;
814 addr->ipv4 = hton32(0x7f000001);
815 }
816 else if (addr_type == BADDR_TYPE_IPV6) {
817 addr->type = addr_type;
818 memset(addr->ipv6, 0, 16);
819 addr->ipv6[15] = 1;
820 }
821 else {
822 addr->type = BADDR_TYPE_NONE;
823 }
824 }
825  
826 #endif