blob: 94fa52e4f95e702216c8a6e3a381e18a8f37a80d [file] [log] [blame]
Alexandre Lision67916dd2014-01-24 13:33:04 -05001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pj/sock.h>
21#include <pj/assert.h>
22#include <pj/ctype.h>
23#include <pj/errno.h>
24#include <pj/ip_helper.h>
25#include <pj/os.h>
26#include <pj/addr_resolv.h>
27#include <pj/rand.h>
28#include <pj/string.h>
29#include <pj/compat/socket.h>
30
31#if 0
32 /* Enable some tracing */
33 #include <pj/log.h>
34 #define THIS_FILE "sock_common.c"
35 #define TRACE_(arg) PJ_LOG(4,arg)
36#else
37 #define TRACE_(arg)
38#endif
39
40
41/*
42 * Convert address string with numbers and dots to binary IP address.
43 */
44PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
45{
46 pj_in_addr addr;
47
48 pj_inet_aton(cp, &addr);
49 return addr;
50}
51
52/*
53 * Convert address string with numbers and dots to binary IP address.
54 */
55PJ_DEF(pj_in_addr) pj_inet_addr2(const char *cp)
56{
57 pj_str_t str = pj_str((char*)cp);
58 return pj_inet_addr(&str);
59}
60
61/*
62 * Get text representation.
63 */
64PJ_DEF(char*) pj_inet_ntop2( int af, const void *src,
65 char *dst, int size)
66{
67 pj_status_t status;
68
69 status = pj_inet_ntop(af, src, dst, size);
70 return (status==PJ_SUCCESS)? dst : NULL;
71}
72
73/*
74 * Print socket address.
75 */
76PJ_DEF(char*) pj_sockaddr_print( const pj_sockaddr_t *addr,
77 char *buf, int size,
78 unsigned flags)
79{
80 enum {
81 WITH_PORT = 1,
82 WITH_BRACKETS = 2
83 };
84
85 char txt[PJ_INET6_ADDRSTRLEN];
86 char port[32];
87 const pj_addr_hdr *h = (const pj_addr_hdr*)addr;
88 char *bquote, *equote;
89 pj_status_t status;
90
91 status = pj_inet_ntop(h->sa_family, pj_sockaddr_get_addr(addr),
92 txt, sizeof(txt));
93 if (status != PJ_SUCCESS)
94 return "";
95
96 if (h->sa_family != PJ_AF_INET6 || (flags & WITH_BRACKETS)==0) {
97 bquote = ""; equote = "";
98 } else {
99 bquote = "["; equote = "]";
100 }
101
102 if (flags & WITH_PORT) {
103 pj_ansi_snprintf(port, sizeof(port), ":%d",
104 pj_sockaddr_get_port(addr));
105 } else {
106 port[0] = '\0';
107 }
108
109 pj_ansi_snprintf(buf, size, "%s%s%s%s",
110 bquote, txt, equote, port);
111
112 return buf;
113}
114
115/*
116 * Set the IP address of an IP socket address from string address,
117 * with resolving the host if necessary. The string address may be in a
118 * standard numbers and dots notation or may be a hostname. If hostname
119 * is specified, then the function will resolve the host into the IP
120 * address.
121 */
122PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
123 const pj_str_t *str_addr)
124{
125 PJ_CHECK_STACK();
126
127 PJ_ASSERT_RETURN(!str_addr || str_addr->slen < PJ_MAX_HOSTNAME,
128 (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
129
130 PJ_SOCKADDR_RESET_LEN(addr);
131 addr->sin_family = AF_INET;
132 pj_bzero(addr->sin_zero, sizeof(addr->sin_zero));
133
134 if (str_addr && str_addr->slen) {
135 addr->sin_addr = pj_inet_addr(str_addr);
136 if (addr->sin_addr.s_addr == PJ_INADDR_NONE) {
137 pj_hostent he;
138 pj_status_t rc;
139
140 rc = pj_gethostbyname(str_addr, &he);
141 if (rc == 0) {
142 addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
143 } else {
144 addr->sin_addr.s_addr = PJ_INADDR_NONE;
145 return rc;
146 }
147 }
148
149 } else {
150 addr->sin_addr.s_addr = 0;
151 }
152
153 return PJ_SUCCESS;
154}
155
156/* Set address from a name */
157PJ_DEF(pj_status_t) pj_sockaddr_set_str_addr(int af,
158 pj_sockaddr *addr,
159 const pj_str_t *str_addr)
160{
161 pj_status_t status;
162
163 if (af == PJ_AF_INET) {
164 return pj_sockaddr_in_set_str_addr(&addr->ipv4, str_addr);
165 }
166
167 PJ_ASSERT_RETURN(af==PJ_AF_INET6, PJ_EAFNOTSUP);
168
169 /* IPv6 specific */
170
171 addr->ipv6.sin6_family = PJ_AF_INET6;
172 PJ_SOCKADDR_RESET_LEN(addr);
173
174 if (str_addr && str_addr->slen) {
175 status = pj_inet_pton(PJ_AF_INET6, str_addr, &addr->ipv6.sin6_addr);
176 if (status != PJ_SUCCESS) {
177 pj_addrinfo ai;
178 unsigned count = 1;
179
180 status = pj_getaddrinfo(PJ_AF_INET6, str_addr, &count, &ai);
181 if (status==PJ_SUCCESS) {
182 pj_memcpy(&addr->ipv6.sin6_addr, &ai.ai_addr.ipv6.sin6_addr,
183 sizeof(pj_sockaddr_in6));
184 }
185 }
186 } else {
187 status = PJ_SUCCESS;
188 }
189
190 return status;
191}
192
193/*
194 * Set the IP address and port of an IP socket address.
195 * The string address may be in a standard numbers and dots notation or
196 * may be a hostname. If hostname is specified, then the function will
197 * resolve the host into the IP address.
198 */
199PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
200 const pj_str_t *str_addr,
201 pj_uint16_t port)
202{
203 PJ_ASSERT_RETURN(addr, (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
204
205 PJ_SOCKADDR_RESET_LEN(addr);
206 addr->sin_family = PJ_AF_INET;
207 pj_bzero(addr->sin_zero, sizeof(addr->sin_zero));
208 pj_sockaddr_in_set_port(addr, port);
209 return pj_sockaddr_in_set_str_addr(addr, str_addr);
210}
211
212/*
213 * Initialize IP socket address based on the address and port info.
214 */
215PJ_DEF(pj_status_t) pj_sockaddr_init(int af,
216 pj_sockaddr *addr,
217 const pj_str_t *cp,
218 pj_uint16_t port)
219{
220 pj_status_t status;
221
222 if (af == PJ_AF_INET) {
223 return pj_sockaddr_in_init(&addr->ipv4, cp, port);
224 }
225
226 /* IPv6 specific */
227 PJ_ASSERT_RETURN(af==PJ_AF_INET6, PJ_EAFNOTSUP);
228
229 pj_bzero(addr, sizeof(pj_sockaddr_in6));
230 addr->addr.sa_family = PJ_AF_INET6;
231
232 status = pj_sockaddr_set_str_addr(af, addr, cp);
233 if (status != PJ_SUCCESS)
234 return status;
235
236 addr->ipv6.sin6_port = pj_htons(port);
237 return PJ_SUCCESS;
238}
239
240/*
241 * Compare two socket addresses.
242 */
243PJ_DEF(int) pj_sockaddr_cmp( const pj_sockaddr_t *addr1,
244 const pj_sockaddr_t *addr2)
245{
246 const pj_sockaddr *a1 = (const pj_sockaddr*) addr1;
247 const pj_sockaddr *a2 = (const pj_sockaddr*) addr2;
248 int port1, port2;
249 int result;
250
251 /* Compare address family */
252 if (a1->addr.sa_family < a2->addr.sa_family)
253 return -1;
254 else if (a1->addr.sa_family > a2->addr.sa_family)
255 return 1;
256
257 /* Compare addresses */
258 result = pj_memcmp(pj_sockaddr_get_addr(a1),
259 pj_sockaddr_get_addr(a2),
260 pj_sockaddr_get_addr_len(a1));
261 if (result != 0)
262 return result;
263
264 /* Compare port number */
265 port1 = pj_sockaddr_get_port(a1);
266 port2 = pj_sockaddr_get_port(a2);
267
268 if (port1 < port2)
269 return -1;
270 else if (port1 > port2)
271 return 1;
272
273 /* TODO:
274 * Do we need to compare flow label and scope id in IPv6?
275 */
276
277 /* Looks equal */
278 return 0;
279}
280
281/*
282 * Get first IP address associated with the hostname.
283 */
284PJ_DEF(pj_in_addr) pj_gethostaddr(void)
285{
286 pj_sockaddr_in addr;
287 const pj_str_t *hostname = pj_gethostname();
288
289 pj_sockaddr_in_set_str_addr(&addr, hostname);
290 return addr.sin_addr;
291}
292
293/*
294 * Get port number of a pj_sockaddr_in
295 */
296PJ_DEF(pj_uint16_t) pj_sockaddr_in_get_port(const pj_sockaddr_in *addr)
297{
298 return pj_ntohs(addr->sin_port);
299}
300
301/*
302 * Get the address part
303 */
304PJ_DEF(void*) pj_sockaddr_get_addr(const pj_sockaddr_t *addr)
305{
306 const pj_sockaddr *a = (const pj_sockaddr*)addr;
307
308 PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
309 a->addr.sa_family == PJ_AF_INET6, NULL);
310
311 if (a->addr.sa_family == PJ_AF_INET6)
312 return (void*) &a->ipv6.sin6_addr;
313 else
314 return (void*) &a->ipv4.sin_addr;
315}
316
317/*
318 * Check if sockaddr contains a non-zero address
319 */
320PJ_DEF(pj_bool_t) pj_sockaddr_has_addr(const pj_sockaddr_t *addr)
321{
322 const pj_sockaddr *a = (const pj_sockaddr*)addr;
323
324 /* It's probably not wise to raise assertion here if
325 * the address doesn't contain a valid address family, and
326 * just return PJ_FALSE instead.
327 *
328 * The reason is because application may need to distinguish
329 * these three conditions with sockaddr:
330 * a) sockaddr is not initialized. This is by convention
331 * indicated by sa_family==0.
332 * b) sockaddr is initialized with zero address. This is
333 * indicated with the address field having zero address.
334 * c) sockaddr is initialized with valid address/port.
335 *
336 * If we enable this assertion, then application will loose
337 * the capability to specify condition a), since it will be
338 * forced to always initialize sockaddr (even with zero address).
339 * This may break some parts of upper layer libraries.
340 */
341 //PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
342 // a->addr.sa_family == PJ_AF_INET6, PJ_FALSE);
343
344 if (a->addr.sa_family!=PJ_AF_INET && a->addr.sa_family!=PJ_AF_INET6) {
345 return PJ_FALSE;
346 } else if (a->addr.sa_family == PJ_AF_INET6) {
347 pj_uint8_t zero[24];
348 pj_bzero(zero, sizeof(zero));
349 return pj_memcmp(a->ipv6.sin6_addr.s6_addr, zero,
350 sizeof(pj_in6_addr)) != 0;
351 } else
352 return a->ipv4.sin_addr.s_addr != PJ_INADDR_ANY;
353}
354
355/*
356 * Get port number
357 */
358PJ_DEF(pj_uint16_t) pj_sockaddr_get_port(const pj_sockaddr_t *addr)
359{
360 const pj_sockaddr *a = (const pj_sockaddr*) addr;
361
362 PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
363 a->addr.sa_family == PJ_AF_INET6, (pj_uint16_t)0xFFFF);
364
365 return pj_ntohs((pj_uint16_t)(a->addr.sa_family == PJ_AF_INET6 ?
366 a->ipv6.sin6_port : a->ipv4.sin_port));
367}
368
369/*
370 * Get the length of the address part.
371 */
372PJ_DEF(unsigned) pj_sockaddr_get_addr_len(const pj_sockaddr_t *addr)
373{
374 const pj_sockaddr *a = (const pj_sockaddr*) addr;
375 PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
376 a->addr.sa_family == PJ_AF_INET6, 0);
377 return a->addr.sa_family == PJ_AF_INET6 ?
378 sizeof(pj_in6_addr) : sizeof(pj_in_addr);
379}
380
381/*
382 * Get socket address length.
383 */
384PJ_DEF(unsigned) pj_sockaddr_get_len(const pj_sockaddr_t *addr)
385{
386 const pj_sockaddr *a = (const pj_sockaddr*) addr;
387 PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
388 a->addr.sa_family == PJ_AF_INET6, 0);
389 return a->addr.sa_family == PJ_AF_INET6 ?
390 sizeof(pj_sockaddr_in6) : sizeof(pj_sockaddr_in);
391}
392
393/*
394 * Copy only the address part (sin_addr/sin6_addr) of a socket address.
395 */
396PJ_DEF(void) pj_sockaddr_copy_addr( pj_sockaddr *dst,
397 const pj_sockaddr *src)
398{
399 /* Destination sockaddr might not be initialized */
400 const char *srcbuf = (char*)pj_sockaddr_get_addr(src);
401 char *dstbuf = ((char*)dst) + (srcbuf - (char*)src);
402 pj_memcpy(dstbuf, srcbuf, pj_sockaddr_get_addr_len(src));
403}
404
405/*
406 * Copy socket address.
407 */
408PJ_DEF(void) pj_sockaddr_cp(pj_sockaddr_t *dst, const pj_sockaddr_t *src)
409{
410 pj_memcpy(dst, src, pj_sockaddr_get_len(src));
411}
412
413/*
414 * Set port number of pj_sockaddr_in
415 */
416PJ_DEF(void) pj_sockaddr_in_set_port(pj_sockaddr_in *addr,
417 pj_uint16_t hostport)
418{
419 addr->sin_port = pj_htons(hostport);
420}
421
422/*
423 * Set port number of pj_sockaddr
424 */
425PJ_DEF(pj_status_t) pj_sockaddr_set_port(pj_sockaddr *addr,
426 pj_uint16_t hostport)
427{
428 int af = addr->addr.sa_family;
429
430 PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL);
431
432 if (af == PJ_AF_INET6)
433 addr->ipv6.sin6_port = pj_htons(hostport);
434 else
435 addr->ipv4.sin_port = pj_htons(hostport);
436
437 return PJ_SUCCESS;
438}
439
440/*
441 * Get IPv4 address
442 */
443PJ_DEF(pj_in_addr) pj_sockaddr_in_get_addr(const pj_sockaddr_in *addr)
444{
445 pj_in_addr in_addr;
446 in_addr.s_addr = pj_ntohl(addr->sin_addr.s_addr);
447 return in_addr;
448}
449
450/*
451 * Set IPv4 address
452 */
453PJ_DEF(void) pj_sockaddr_in_set_addr(pj_sockaddr_in *addr,
454 pj_uint32_t hostaddr)
455{
456 addr->sin_addr.s_addr = pj_htonl(hostaddr);
457}
458
459/*
460 * Parse address
461 */
462PJ_DEF(pj_status_t) pj_sockaddr_parse2(int af, unsigned options,
463 const pj_str_t *str,
464 pj_str_t *p_hostpart,
465 pj_uint16_t *p_port,
466 int *raf)
467{
468 const char *end = str->ptr + str->slen;
469 const char *last_colon_pos = NULL;
470 unsigned colon_cnt = 0;
471 const char *p;
472
473 PJ_ASSERT_RETURN((af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) &&
474 options==0 &&
475 str!=NULL, PJ_EINVAL);
476
477 /* Special handling for empty input */
478 if (str->slen==0 || str->ptr==NULL) {
479 if (p_hostpart)
480 p_hostpart->slen = 0;
481 if (p_port)
482 *p_port = 0;
483 if (raf)
484 *raf = PJ_AF_INET;
485 return PJ_SUCCESS;
486 }
487
488 /* Count the colon and get the last colon */
489 for (p=str->ptr; p!=end; ++p) {
490 if (*p == ':') {
491 ++colon_cnt;
492 last_colon_pos = p;
493 }
494 }
495
496 /* Deduce address family if it's not given */
497 if (af == PJ_AF_UNSPEC) {
498 if (colon_cnt > 1)
499 af = PJ_AF_INET6;
500 else
501 af = PJ_AF_INET;
502 } else if (af == PJ_AF_INET && colon_cnt > 1)
503 return PJ_EINVAL;
504
505 if (raf)
506 *raf = af;
507
508 if (af == PJ_AF_INET) {
509 /* Parse as IPv4. Supported formats:
510 * - "10.0.0.1:80"
511 * - "10.0.0.1"
512 * - "10.0.0.1:"
513 * - ":80"
514 * - ":"
515 */
516 pj_str_t hostpart;
517 unsigned long port;
518
519 hostpart.ptr = (char*)str->ptr;
520
521 if (last_colon_pos) {
522 pj_str_t port_part;
523 int i;
524
525 hostpart.slen = last_colon_pos - str->ptr;
526
527 port_part.ptr = (char*)last_colon_pos + 1;
528 port_part.slen = end - port_part.ptr;
529
530 /* Make sure port number is valid */
531 for (i=0; i<port_part.slen; ++i) {
532 if (!pj_isdigit(port_part.ptr[i]))
533 return PJ_EINVAL;
534 }
535 port = pj_strtoul(&port_part);
536 if (port > 65535)
537 return PJ_EINVAL;
538 } else {
539 hostpart.slen = str->slen;
540 port = 0;
541 }
542
543 if (p_hostpart)
544 *p_hostpart = hostpart;
545 if (p_port)
546 *p_port = (pj_uint16_t)port;
547
548 return PJ_SUCCESS;
549
550 } else if (af == PJ_AF_INET6) {
551
552 /* Parse as IPv6. Supported formats:
553 * - "fe::01:80" ==> note: port number is zero in this case, not 80!
554 * - "[fe::01]:80"
555 * - "fe::01"
556 * - "fe::01:"
557 * - "[fe::01]"
558 * - "[fe::01]:"
559 * - "[::]:80"
560 * - ":::80"
561 * - "[::]"
562 * - "[::]:"
563 * - ":::"
564 * - "::"
565 */
566 pj_str_t hostpart, port_part;
567
568 if (*str->ptr == '[') {
569 char *end_bracket;
570 int i;
571 unsigned long port;
572
573 if (last_colon_pos == NULL)
574 return PJ_EINVAL;
575
576 end_bracket = pj_strchr(str, ']');
577 if (end_bracket == NULL)
578 return PJ_EINVAL;
579
580 hostpart.ptr = (char*)str->ptr + 1;
581 hostpart.slen = end_bracket - hostpart.ptr;
582
583 if (last_colon_pos < end_bracket) {
584 port_part.ptr = NULL;
585 port_part.slen = 0;
586 } else {
587 port_part.ptr = (char*)last_colon_pos + 1;
588 port_part.slen = end - port_part.ptr;
589 }
590
591 /* Make sure port number is valid */
592 for (i=0; i<port_part.slen; ++i) {
593 if (!pj_isdigit(port_part.ptr[i]))
594 return PJ_EINVAL;
595 }
596 port = pj_strtoul(&port_part);
597 if (port > 65535)
598 return PJ_EINVAL;
599
600 if (p_hostpart)
601 *p_hostpart = hostpart;
602 if (p_port)
603 *p_port = (pj_uint16_t)port;
604
605 return PJ_SUCCESS;
606
607 } else {
608 /* Treat everything as part of the IPv6 IP address */
609 if (p_hostpart)
610 *p_hostpart = *str;
611 if (p_port)
612 *p_port = 0;
613
614 return PJ_SUCCESS;
615 }
616
617 } else {
618 return PJ_EAFNOTSUP;
619 }
620
621}
622
623/*
624 * Parse address
625 */
626PJ_DEF(pj_status_t) pj_sockaddr_parse( int af, unsigned options,
627 const pj_str_t *str,
628 pj_sockaddr *addr)
629{
630 pj_str_t hostpart;
631 pj_uint16_t port;
632 pj_status_t status;
633
634 PJ_ASSERT_RETURN(addr, PJ_EINVAL);
635 PJ_ASSERT_RETURN(af==PJ_AF_UNSPEC ||
636 af==PJ_AF_INET ||
637 af==PJ_AF_INET6, PJ_EINVAL);
638 PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
639
640 status = pj_sockaddr_parse2(af, options, str, &hostpart, &port, &af);
641 if (status != PJ_SUCCESS)
642 return status;
643
644#if !defined(PJ_HAS_IPV6) || !PJ_HAS_IPV6
645 if (af==PJ_AF_INET6)
646 return PJ_EIPV6NOTSUP;
647#endif
648
649 status = pj_sockaddr_init(af, addr, &hostpart, port);
650#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
651 if (status != PJ_SUCCESS && af == PJ_AF_INET6) {
652 /* Parsing does not yield valid address. Try to treat the last
653 * portion after the colon as port number.
654 */
655 const char *last_colon_pos=NULL, *p;
656 const char *end = str->ptr + str->slen;
657 unsigned long long_port;
658 pj_str_t port_part;
659 int i;
660
661 /* Parse as IPv6:port */
662 for (p=str->ptr; p!=end; ++p) {
663 if (*p == ':')
664 last_colon_pos = p;
665 }
666
667 if (last_colon_pos == NULL)
668 return status;
669
670 hostpart.ptr = (char*)str->ptr;
671 hostpart.slen = last_colon_pos - str->ptr;
672
673 port_part.ptr = (char*)last_colon_pos + 1;
674 port_part.slen = end - port_part.ptr;
675
676 /* Make sure port number is valid */
677 for (i=0; i<port_part.slen; ++i) {
678 if (!pj_isdigit(port_part.ptr[i]))
679 return status;
680 }
681 long_port = pj_strtoul(&port_part);
682 if (long_port > 65535)
683 return status;
684
685 port = (pj_uint16_t)long_port;
686
687 status = pj_sockaddr_init(PJ_AF_INET6, addr, &hostpart, port);
688 }
689#endif
690
691 return status;
692}
693
694/* Resolve the IP address of local machine */
695PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr)
696{
697 unsigned i, count, cand_cnt;
698 enum {
699 CAND_CNT = 8,
700
701 /* Weighting to be applied to found addresses */
702 WEIGHT_HOSTNAME = 1, /* hostname IP is not always valid! */
703 WEIGHT_DEF_ROUTE = 2,
704 WEIGHT_INTERFACE = 1,
705 WEIGHT_LOOPBACK = -5,
706 WEIGHT_LINK_LOCAL = -4,
707 WEIGHT_DISABLED = -50,
708
709 MIN_WEIGHT = WEIGHT_DISABLED+1 /* minimum weight to use */
710 };
711 /* candidates: */
712 pj_sockaddr cand_addr[CAND_CNT];
713 int cand_weight[CAND_CNT];
714 int selected_cand;
715 char strip[PJ_INET6_ADDRSTRLEN+10];
716 /* Special IPv4 addresses. */
717 struct spec_ipv4_t
718 {
719 pj_uint32_t addr;
720 pj_uint32_t mask;
721 int weight;
722 } spec_ipv4[] =
723 {
724 /* 127.0.0.0/8, loopback addr will be used if there is no other
725 * addresses.
726 */
727 { 0x7f000000, 0xFF000000, WEIGHT_LOOPBACK },
728
729 /* 0.0.0.0/8, special IP that doesn't seem to be practically useful */
730 { 0x00000000, 0xFF000000, WEIGHT_DISABLED },
731
732 /* 169.254.0.0/16, a zeroconf/link-local address, which has higher
733 * priority than loopback and will be used if there is no other
734 * valid addresses.
735 */
736 { 0xa9fe0000, 0xFFFF0000, WEIGHT_LINK_LOCAL }
737 };
738 /* Special IPv6 addresses */
739 struct spec_ipv6_t
740 {
741 pj_uint8_t addr[16];
742 pj_uint8_t mask[16];
743 int weight;
744 } spec_ipv6[] =
745 {
746 /* Loopback address, ::1/128 */
747 { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
748 {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
749 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
750 WEIGHT_LOOPBACK
751 },
752
753 /* Link local, fe80::/10 */
754 { {0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
755 {0xff,0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
756 WEIGHT_LINK_LOCAL
757 },
758
759 /* Disabled, ::/128 */
760 { {0x0,0x0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
761 { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
762 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
763 WEIGHT_DISABLED
764 }
765 };
766 pj_addrinfo ai;
767 pj_status_t status;
768
769 /* May not be used if TRACE_ is disabled */
770 PJ_UNUSED_ARG(strip);
771
772#ifdef _MSC_VER
773 /* Get rid of "uninitialized he variable" with MS compilers */
774 pj_bzero(&ai, sizeof(ai));
775#endif
776
777 cand_cnt = 0;
778 pj_bzero(cand_addr, sizeof(cand_addr));
779 pj_bzero(cand_weight, sizeof(cand_weight));
780 for (i=0; i<PJ_ARRAY_SIZE(cand_addr); ++i) {
781 cand_addr[i].addr.sa_family = (pj_uint16_t)af;
782 PJ_SOCKADDR_RESET_LEN(&cand_addr[i]);
783 }
784
785 addr->addr.sa_family = (pj_uint16_t)af;
786 PJ_SOCKADDR_RESET_LEN(addr);
787
788#if !defined(PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION) || \
789 PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION == 0
790 /* Get hostname's IP address */
791 count = 1;
792 status = pj_getaddrinfo(af, pj_gethostname(), &count, &ai);
793 if (status == PJ_SUCCESS) {
794 pj_assert(ai.ai_addr.addr.sa_family == (pj_uint16_t)af);
795 pj_sockaddr_copy_addr(&cand_addr[cand_cnt], &ai.ai_addr);
796 pj_sockaddr_set_port(&cand_addr[cand_cnt], 0);
797 cand_weight[cand_cnt] += WEIGHT_HOSTNAME;
798 ++cand_cnt;
799
800 TRACE_((THIS_FILE, "hostname IP is %s",
801 pj_sockaddr_print(&ai.ai_addr, strip, sizeof(strip), 0)));
802 }
803#else
804 PJ_UNUSED_ARG(ai);
805 PJ_UNUSED_ARG(count);
806#endif
807
808 /* Get default interface (interface for default route) */
809 if (cand_cnt < PJ_ARRAY_SIZE(cand_addr)) {
810 status = pj_getdefaultipinterface(af, addr);
811 if (status == PJ_SUCCESS) {
812 TRACE_((THIS_FILE, "default IP is %s",
813 pj_sockaddr_print(addr, strip, sizeof(strip), 0)));
814
815 pj_sockaddr_set_port(addr, 0);
816 for (i=0; i<cand_cnt; ++i) {
817 if (pj_sockaddr_cmp(&cand_addr[i], addr)==0)
818 break;
819 }
820
821 cand_weight[i] += WEIGHT_DEF_ROUTE;
822 if (i >= cand_cnt) {
823 pj_sockaddr_copy_addr(&cand_addr[i], addr);
824 ++cand_cnt;
825 }
826 }
827 }
828
829
830 /* Enumerate IP interfaces */
831 if (cand_cnt < PJ_ARRAY_SIZE(cand_addr)) {
832 unsigned start_if = cand_cnt;
833 unsigned count = PJ_ARRAY_SIZE(cand_addr) - start_if;
834
835 status = pj_enum_ip_interface(af, &count, &cand_addr[start_if]);
836 if (status == PJ_SUCCESS && count) {
837 /* Clear the port number */
838 for (i=0; i<count; ++i)
839 pj_sockaddr_set_port(&cand_addr[start_if+i], 0);
840
841 /* For each candidate that we found so far (that is the hostname
842 * address and default interface address, check if they're found
843 * in the interface list. If found, add the weight, and if not,
844 * decrease the weight.
845 */
846 for (i=0; i<cand_cnt; ++i) {
847 unsigned j;
848 for (j=0; j<count; ++j) {
849 if (pj_sockaddr_cmp(&cand_addr[i],
850 &cand_addr[start_if+j])==0)
851 break;
852 }
853
854 if (j == count) {
855 /* Not found */
856 cand_weight[i] -= WEIGHT_INTERFACE;
857 } else {
858 cand_weight[i] += WEIGHT_INTERFACE;
859 }
860 }
861
862 /* Add remaining interface to candidate list. */
863 for (i=0; i<count; ++i) {
864 unsigned j;
865 for (j=0; j<cand_cnt; ++j) {
866 if (pj_sockaddr_cmp(&cand_addr[start_if+i],
867 &cand_addr[j])==0)
868 break;
869 }
870
871 if (j == cand_cnt) {
872 pj_sockaddr_copy_addr(&cand_addr[cand_cnt],
873 &cand_addr[start_if+i]);
874 cand_weight[cand_cnt] += WEIGHT_INTERFACE;
875 ++cand_cnt;
876 }
877 }
878 }
879 }
880
881 /* Apply weight adjustment for special IPv4/IPv6 addresses
882 * See http://trac.pjsip.org/repos/ticket/1046
883 */
884 if (af == PJ_AF_INET) {
885 for (i=0; i<cand_cnt; ++i) {
886 unsigned j;
887 for (j=0; j<PJ_ARRAY_SIZE(spec_ipv4); ++j) {
888 pj_uint32_t a = pj_ntohl(cand_addr[i].ipv4.sin_addr.s_addr);
889 pj_uint32_t pa = spec_ipv4[j].addr;
890 pj_uint32_t pm = spec_ipv4[j].mask;
891
892 if ((a & pm) == pa) {
893 cand_weight[i] += spec_ipv4[j].weight;
894 break;
895 }
896 }
897 }
898 } else if (af == PJ_AF_INET6) {
899 for (i=0; i<PJ_ARRAY_SIZE(spec_ipv6); ++i) {
900 unsigned j;
901 for (j=0; j<cand_cnt; ++j) {
902 pj_uint8_t *a = cand_addr[j].ipv6.sin6_addr.s6_addr;
903 pj_uint8_t am[16];
904 pj_uint8_t *pa = spec_ipv6[i].addr;
905 pj_uint8_t *pm = spec_ipv6[i].mask;
906 unsigned k;
907
908 for (k=0; k<16; ++k) {
909 am[k] = (pj_uint8_t)((a[k] & pm[k]) & 0xFF);
910 }
911
912 if (pj_memcmp(am, pa, 16)==0) {
913 cand_weight[j] += spec_ipv6[i].weight;
914 }
915 }
916 }
917 } else {
918 return PJ_EAFNOTSUP;
919 }
920
921 /* Enumerate candidates to get the best IP address to choose */
922 selected_cand = -1;
923 for (i=0; i<cand_cnt; ++i) {
924 TRACE_((THIS_FILE, "Checking candidate IP %s, weight=%d",
925 pj_sockaddr_print(&cand_addr[i], strip, sizeof(strip), 0),
926 cand_weight[i]));
927
928 if (cand_weight[i] < MIN_WEIGHT) {
929 continue;
930 }
931
932 if (selected_cand == -1)
933 selected_cand = i;
934 else if (cand_weight[i] > cand_weight[selected_cand])
935 selected_cand = i;
936 }
937
938 /* If else fails, returns loopback interface as the last resort */
939 if (selected_cand == -1) {
940 if (af==PJ_AF_INET) {
941 addr->ipv4.sin_addr.s_addr = pj_htonl (0x7f000001);
942 } else {
943 pj_in6_addr *s6_addr;
944
945 s6_addr = (pj_in6_addr*) pj_sockaddr_get_addr(addr);
946 pj_bzero(s6_addr, sizeof(pj_in6_addr));
947 s6_addr->s6_addr[15] = 1;
948 }
949 TRACE_((THIS_FILE, "Loopback IP %s returned",
950 pj_sockaddr_print(addr, strip, sizeof(strip), 0)));
951 } else {
952 pj_sockaddr_copy_addr(addr, &cand_addr[selected_cand]);
953 TRACE_((THIS_FILE, "Candidate %s selected",
954 pj_sockaddr_print(addr, strip, sizeof(strip), 0)));
955 }
956
957 return PJ_SUCCESS;
958}
959
960/* Get IP interface for sending to the specified destination */
961PJ_DEF(pj_status_t) pj_getipinterface(int af,
962 const pj_str_t *dst,
963 pj_sockaddr *itf_addr,
964 pj_bool_t allow_resolve,
965 pj_sockaddr *p_dst_addr)
966{
967 pj_sockaddr dst_addr;
968 pj_sock_t fd;
969 int len;
970 pj_uint8_t zero[64];
971 pj_status_t status;
972
973 pj_sockaddr_init(af, &dst_addr, NULL, 53);
974 status = pj_inet_pton(af, dst, pj_sockaddr_get_addr(&dst_addr));
975 if (status != PJ_SUCCESS) {
976 /* "dst" is not an IP address. */
977 if (allow_resolve) {
978 status = pj_sockaddr_init(af, &dst_addr, dst, 53);
979 } else {
980 pj_str_t cp;
981
982 if (af == PJ_AF_INET) {
983 cp = pj_str("1.1.1.1");
984 } else {
985 cp = pj_str("1::1");
986 }
987 status = pj_sockaddr_init(af, &dst_addr, &cp, 53);
988 }
989
990 if (status != PJ_SUCCESS)
991 return status;
992 }
993
994 /* Create UDP socket and connect() to the destination IP */
995 status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &fd);
996 if (status != PJ_SUCCESS) {
997 return status;
998 }
999
1000 status = pj_sock_connect(fd, &dst_addr, pj_sockaddr_get_len(&dst_addr));
1001 if (status != PJ_SUCCESS) {
1002 pj_sock_close(fd);
1003 return status;
1004 }
1005
1006 len = sizeof(*itf_addr);
1007 status = pj_sock_getsockname(fd, itf_addr, &len);
1008 if (status != PJ_SUCCESS) {
1009 pj_sock_close(fd);
1010 return status;
1011 }
1012
1013 pj_sock_close(fd);
1014
1015 /* Check that the address returned is not zero */
1016 pj_bzero(zero, sizeof(zero));
1017 if (pj_memcmp(pj_sockaddr_get_addr(itf_addr), zero,
1018 pj_sockaddr_get_addr_len(itf_addr))==0)
1019 {
1020 return PJ_ENOTFOUND;
1021 }
1022
1023 if (p_dst_addr)
1024 *p_dst_addr = dst_addr;
1025
1026 return PJ_SUCCESS;
1027}
1028
1029/* Get the default IP interface */
1030PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr)
1031{
1032 pj_str_t cp;
1033
1034 if (af == PJ_AF_INET) {
1035 cp = pj_str("1.1.1.1");
1036 } else {
1037 cp = pj_str("1::1");
1038 }
1039
1040 return pj_getipinterface(af, &cp, addr, PJ_FALSE, NULL);
1041}
1042
1043
1044/*
1045 * Bind socket at random port.
1046 */
1047PJ_DEF(pj_status_t) pj_sock_bind_random( pj_sock_t sockfd,
1048 const pj_sockaddr_t *addr,
1049 pj_uint16_t port_range,
1050 pj_uint16_t max_try)
1051{
1052 pj_sockaddr bind_addr;
1053 int addr_len;
1054 pj_uint16_t base_port;
1055 pj_status_t status = PJ_SUCCESS;
1056
1057 PJ_CHECK_STACK();
1058
1059 PJ_ASSERT_RETURN(addr, PJ_EINVAL);
1060
1061 pj_sockaddr_cp(&bind_addr, addr);
1062 addr_len = pj_sockaddr_get_len(addr);
1063 base_port = pj_sockaddr_get_port(addr);
1064
1065 if (base_port == 0 || port_range == 0) {
1066 return pj_sock_bind(sockfd, &bind_addr, addr_len);
1067 }
1068
1069 for (; max_try; --max_try) {
1070 pj_uint16_t port;
1071 port = (pj_uint16_t)(base_port + pj_rand() % (port_range + 1));
1072 pj_sockaddr_set_port(&bind_addr, port);
1073 status = pj_sock_bind(sockfd, &bind_addr, addr_len);
1074 if (status == PJ_SUCCESS)
1075 break;
1076 }
1077
1078 return status;
1079}
1080
1081
1082/*
1083 * Adjust socket send/receive buffer size.
1084 */
1085PJ_DEF(pj_status_t) pj_sock_setsockopt_sobuf( pj_sock_t sockfd,
1086 pj_uint16_t optname,
1087 pj_bool_t auto_retry,
1088 unsigned *buf_size)
1089{
1090 pj_status_t status;
1091 int try_size, cur_size, i, step, size_len;
1092 enum { MAX_TRY = 20 };
1093
1094 PJ_CHECK_STACK();
1095
1096 PJ_ASSERT_RETURN(sockfd != PJ_INVALID_SOCKET &&
1097 buf_size &&
1098 *buf_size > 0 &&
1099 (optname == pj_SO_RCVBUF() ||
1100 optname == pj_SO_SNDBUF()),
1101 PJ_EINVAL);
1102
1103 size_len = sizeof(cur_size);
1104 status = pj_sock_getsockopt(sockfd, pj_SOL_SOCKET(), optname,
1105 &cur_size, &size_len);
1106 if (status != PJ_SUCCESS)
1107 return status;
1108
1109 try_size = *buf_size;
1110 step = (try_size - cur_size) / MAX_TRY;
1111 if (step < 4096)
1112 step = 4096;
1113
1114 for (i = 0; i < (MAX_TRY-1); ++i) {
1115 if (try_size <= cur_size) {
1116 /* Done, return current size */
1117 *buf_size = cur_size;
1118 break;
1119 }
1120
1121 status = pj_sock_setsockopt(sockfd, pj_SOL_SOCKET(), optname,
1122 &try_size, sizeof(try_size));
1123 if (status == PJ_SUCCESS) {
1124 status = pj_sock_getsockopt(sockfd, pj_SOL_SOCKET(), optname,
1125 &cur_size, &size_len);
1126 if (status != PJ_SUCCESS) {
1127 /* Ops! No info about current size, just return last try size
1128 * and quit.
1129 */
1130 *buf_size = try_size;
1131 break;
1132 }
1133 }
1134
1135 if (!auto_retry)
1136 break;
1137
1138 try_size -= step;
1139 }
1140
1141 return status;
1142}
1143
1144
1145/* Only need to implement these in DLL build */
1146#if defined(PJ_DLL)
1147
1148PJ_DEF(pj_uint16_t) pj_AF_UNSPEC(void)
1149{
1150 return PJ_AF_UNSPEC;
1151}
1152
1153PJ_DEF(pj_uint16_t) pj_AF_UNIX(void)
1154{
1155 return PJ_AF_UNIX;
1156}
1157
1158PJ_DEF(pj_uint16_t) pj_AF_INET(void)
1159{
1160 return PJ_AF_INET;
1161}
1162
1163PJ_DEF(pj_uint16_t) pj_AF_INET6(void)
1164{
1165 return PJ_AF_INET6;
1166}
1167
1168PJ_DEF(pj_uint16_t) pj_AF_PACKET(void)
1169{
1170 return PJ_AF_PACKET;
1171}
1172
1173PJ_DEF(pj_uint16_t) pj_AF_IRDA(void)
1174{
1175 return PJ_AF_IRDA;
1176}
1177
1178PJ_DEF(int) pj_SOCK_STREAM(void)
1179{
1180 return PJ_SOCK_STREAM;
1181}
1182
1183PJ_DEF(int) pj_SOCK_DGRAM(void)
1184{
1185 return PJ_SOCK_DGRAM;
1186}
1187
1188PJ_DEF(int) pj_SOCK_RAW(void)
1189{
1190 return PJ_SOCK_RAW;
1191}
1192
1193PJ_DEF(int) pj_SOCK_RDM(void)
1194{
1195 return PJ_SOCK_RDM;
1196}
1197
1198PJ_DEF(pj_uint16_t) pj_SOL_SOCKET(void)
1199{
1200 return PJ_SOL_SOCKET;
1201}
1202
1203PJ_DEF(pj_uint16_t) pj_SOL_IP(void)
1204{
1205 return PJ_SOL_IP;
1206}
1207
1208PJ_DEF(pj_uint16_t) pj_SOL_TCP(void)
1209{
1210 return PJ_SOL_TCP;
1211}
1212
1213PJ_DEF(pj_uint16_t) pj_SOL_UDP(void)
1214{
1215 return PJ_SOL_UDP;
1216}
1217
1218PJ_DEF(pj_uint16_t) pj_SOL_IPV6(void)
1219{
1220 return PJ_SOL_IPV6;
1221}
1222
1223PJ_DEF(int) pj_IP_TOS(void)
1224{
1225 return PJ_IP_TOS;
1226}
1227
1228PJ_DEF(int) pj_IPTOS_LOWDELAY(void)
1229{
1230 return PJ_IPTOS_LOWDELAY;
1231}
1232
1233PJ_DEF(int) pj_IPTOS_THROUGHPUT(void)
1234{
1235 return PJ_IPTOS_THROUGHPUT;
1236}
1237
1238PJ_DEF(int) pj_IPTOS_RELIABILITY(void)
1239{
1240 return PJ_IPTOS_RELIABILITY;
1241}
1242
1243PJ_DEF(int) pj_IPTOS_MINCOST(void)
1244{
1245 return PJ_IPTOS_MINCOST;
1246}
1247
1248PJ_DEF(pj_uint16_t) pj_SO_TYPE(void)
1249{
1250 return PJ_SO_TYPE;
1251}
1252
1253PJ_DEF(pj_uint16_t) pj_SO_RCVBUF(void)
1254{
1255 return PJ_SO_RCVBUF;
1256}
1257
1258PJ_DEF(pj_uint16_t) pj_SO_SNDBUF(void)
1259{
1260 return PJ_SO_SNDBUF;
1261}
1262
1263PJ_DEF(pj_uint16_t) pj_TCP_NODELAY(void)
1264{
1265 return PJ_TCP_NODELAY;
1266}
1267
1268PJ_DEF(pj_uint16_t) pj_SO_REUSEADDR(void)
1269{
1270 return PJ_SO_REUSEADDR;
1271}
1272
1273PJ_DEF(pj_uint16_t) pj_SO_NOSIGPIPE(void)
1274{
1275 return PJ_SO_NOSIGPIPE;
1276}
1277
1278PJ_DEF(pj_uint16_t) pj_SO_PRIORITY(void)
1279{
1280 return PJ_SO_PRIORITY;
1281}
1282
1283PJ_DEF(pj_uint16_t) pj_IP_MULTICAST_IF(void)
1284{
1285 return PJ_IP_MULTICAST_IF;
1286}
1287
1288PJ_DEF(pj_uint16_t) pj_IP_MULTICAST_TTL(void)
1289{
1290 return PJ_IP_MULTICAST_TTL;
1291}
1292
1293PJ_DEF(pj_uint16_t) pj_IP_MULTICAST_LOOP(void)
1294{
1295 return PJ_IP_MULTICAST_LOOP;
1296}
1297
1298PJ_DEF(pj_uint16_t) pj_IP_ADD_MEMBERSHIP(void)
1299{
1300 return PJ_IP_ADD_MEMBERSHIP;
1301}
1302
1303PJ_DEF(pj_uint16_t) pj_IP_DROP_MEMBERSHIP(void)
1304{
1305 return PJ_IP_DROP_MEMBERSHIP;
1306}
1307
1308PJ_DEF(int) pj_MSG_OOB(void)
1309{
1310 return PJ_MSG_OOB;
1311}
1312
1313PJ_DEF(int) pj_MSG_PEEK(void)
1314{
1315 return PJ_MSG_PEEK;
1316}
1317
1318PJ_DEF(int) pj_MSG_DONTROUTE(void)
1319{
1320 return PJ_MSG_DONTROUTE;
1321}
1322
1323#endif /* PJ_DLL */
1324