1
/* $Id: sock_common.c 4343 2013-02-07 09:35:34Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
21
#include <pj/assert.h>
24
#include <pj/ip_helper.h>
26
#include <pj/addr_resolv.h>
28
#include <pj/string.h>
29
#include <pj/compat/socket.h>
32
/* Enable some tracing */
34
#define THIS_FILE "sock_common.c"
35
#define TRACE_(arg) PJ_LOG(4,arg)
42
* Convert address string with numbers and dots to binary IP address.
44
PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
48
pj_inet_aton(cp, &addr);
53
* Convert address string with numbers and dots to binary IP address.
55
PJ_DEF(pj_in_addr) pj_inet_addr2(const char *cp)
57
pj_str_t str = pj_str((char*)cp);
58
return pj_inet_addr(&str);
62
* Get text representation.
64
PJ_DEF(char*) pj_inet_ntop2( int af, const void *src,
69
status = pj_inet_ntop(af, src, dst, size);
70
return (status==PJ_SUCCESS)? dst : NULL;
74
* Print socket address.
76
PJ_DEF(char*) pj_sockaddr_print( const pj_sockaddr_t *addr,
85
char txt[PJ_INET6_ADDRSTRLEN];
87
const pj_addr_hdr *h = (const pj_addr_hdr*)addr;
88
char *bquote, *equote;
91
status = pj_inet_ntop(h->sa_family, pj_sockaddr_get_addr(addr),
93
if (status != PJ_SUCCESS)
96
if (h->sa_family != PJ_AF_INET6 || (flags & WITH_BRACKETS)==0) {
97
bquote = ""; equote = "";
99
bquote = "["; equote = "]";
102
if (flags & WITH_PORT) {
103
pj_ansi_snprintf(port, sizeof(port), ":%d",
104
pj_sockaddr_get_port(addr));
109
pj_ansi_snprintf(buf, size, "%s%s%s%s",
110
bquote, txt, equote, port);
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
122
PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
123
const pj_str_t *str_addr)
127
PJ_ASSERT_RETURN(!str_addr || str_addr->slen < PJ_MAX_HOSTNAME,
128
(addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
130
PJ_SOCKADDR_RESET_LEN(addr);
131
addr->sin_family = AF_INET;
132
pj_bzero(addr->sin_zero, sizeof(addr->sin_zero));
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) {
140
rc = pj_gethostbyname(str_addr, &he);
142
addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
144
addr->sin_addr.s_addr = PJ_INADDR_NONE;
150
addr->sin_addr.s_addr = 0;
156
/* Set address from a name */
157
PJ_DEF(pj_status_t) pj_sockaddr_set_str_addr(int af,
159
const pj_str_t *str_addr)
163
if (af == PJ_AF_INET) {
164
return pj_sockaddr_in_set_str_addr(&addr->ipv4, str_addr);
167
PJ_ASSERT_RETURN(af==PJ_AF_INET6, PJ_EAFNOTSUP);
171
addr->ipv6.sin6_family = PJ_AF_INET6;
172
PJ_SOCKADDR_RESET_LEN(addr);
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) {
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));
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.
199
PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
200
const pj_str_t *str_addr,
203
PJ_ASSERT_RETURN(addr, (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
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);
213
* Initialize IP socket address based on the address and port info.
215
PJ_DEF(pj_status_t) pj_sockaddr_init(int af,
222
if (af == PJ_AF_INET) {
223
return pj_sockaddr_in_init(&addr->ipv4, cp, port);
227
PJ_ASSERT_RETURN(af==PJ_AF_INET6, PJ_EAFNOTSUP);
229
pj_bzero(addr, sizeof(pj_sockaddr_in6));
230
addr->addr.sa_family = PJ_AF_INET6;
232
status = pj_sockaddr_set_str_addr(af, addr, cp);
233
if (status != PJ_SUCCESS)
236
addr->ipv6.sin6_port = pj_htons(port);
241
* Compare two socket addresses.
243
PJ_DEF(int) pj_sockaddr_cmp( const pj_sockaddr_t *addr1,
244
const pj_sockaddr_t *addr2)
246
const pj_sockaddr *a1 = (const pj_sockaddr*) addr1;
247
const pj_sockaddr *a2 = (const pj_sockaddr*) addr2;
251
/* Compare address family */
252
if (a1->addr.sa_family < a2->addr.sa_family)
254
else if (a1->addr.sa_family > a2->addr.sa_family)
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));
264
/* Compare port number */
265
port1 = pj_sockaddr_get_port(a1);
266
port2 = pj_sockaddr_get_port(a2);
270
else if (port1 > port2)
274
* Do we need to compare flow label and scope id in IPv6?
282
* Get first IP address associated with the hostname.
284
PJ_DEF(pj_in_addr) pj_gethostaddr(void)
287
const pj_str_t *hostname = pj_gethostname();
289
pj_sockaddr_in_set_str_addr(&addr, hostname);
290
return addr.sin_addr;
294
* Get port number of a pj_sockaddr_in
296
PJ_DEF(pj_uint16_t) pj_sockaddr_in_get_port(const pj_sockaddr_in *addr)
298
return pj_ntohs(addr->sin_port);
302
* Get the address part
304
PJ_DEF(void*) pj_sockaddr_get_addr(const pj_sockaddr_t *addr)
306
const pj_sockaddr *a = (const pj_sockaddr*)addr;
308
PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
309
a->addr.sa_family == PJ_AF_INET6, NULL);
311
if (a->addr.sa_family == PJ_AF_INET6)
312
return (void*) &a->ipv6.sin6_addr;
314
return (void*) &a->ipv4.sin_addr;
318
* Check if sockaddr contains a non-zero address
320
PJ_DEF(pj_bool_t) pj_sockaddr_has_addr(const pj_sockaddr_t *addr)
322
const pj_sockaddr *a = (const pj_sockaddr*)addr;
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.
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.
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.
341
//PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
342
// a->addr.sa_family == PJ_AF_INET6, PJ_FALSE);
344
if (a->addr.sa_family!=PJ_AF_INET && a->addr.sa_family!=PJ_AF_INET6) {
346
} else if (a->addr.sa_family == PJ_AF_INET6) {
348
pj_bzero(zero, sizeof(zero));
349
return pj_memcmp(a->ipv6.sin6_addr.s6_addr, zero,
350
sizeof(pj_in6_addr)) != 0;
352
return a->ipv4.sin_addr.s_addr != PJ_INADDR_ANY;
358
PJ_DEF(pj_uint16_t) pj_sockaddr_get_port(const pj_sockaddr_t *addr)
360
const pj_sockaddr *a = (const pj_sockaddr*) addr;
362
PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
363
a->addr.sa_family == PJ_AF_INET6, (pj_uint16_t)0xFFFF);
365
return pj_ntohs((pj_uint16_t)(a->addr.sa_family == PJ_AF_INET6 ?
366
a->ipv6.sin6_port : a->ipv4.sin_port));
370
* Get the length of the address part.
372
PJ_DEF(unsigned) pj_sockaddr_get_addr_len(const pj_sockaddr_t *addr)
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);
382
* Get socket address length.
384
PJ_DEF(unsigned) pj_sockaddr_get_len(const pj_sockaddr_t *addr)
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);
394
* Copy only the address part (sin_addr/sin6_addr) of a socket address.
396
PJ_DEF(void) pj_sockaddr_copy_addr( pj_sockaddr *dst,
397
const pj_sockaddr *src)
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));
406
* Copy socket address.
408
PJ_DEF(void) pj_sockaddr_cp(pj_sockaddr_t *dst, const pj_sockaddr_t *src)
410
pj_memcpy(dst, src, pj_sockaddr_get_len(src));
414
* Set port number of pj_sockaddr_in
416
PJ_DEF(void) pj_sockaddr_in_set_port(pj_sockaddr_in *addr,
417
pj_uint16_t hostport)
419
addr->sin_port = pj_htons(hostport);
423
* Set port number of pj_sockaddr
425
PJ_DEF(pj_status_t) pj_sockaddr_set_port(pj_sockaddr *addr,
426
pj_uint16_t hostport)
428
int af = addr->addr.sa_family;
430
PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL);
432
if (af == PJ_AF_INET6)
433
addr->ipv6.sin6_port = pj_htons(hostport);
435
addr->ipv4.sin_port = pj_htons(hostport);
443
PJ_DEF(pj_in_addr) pj_sockaddr_in_get_addr(const pj_sockaddr_in *addr)
446
in_addr.s_addr = pj_ntohl(addr->sin_addr.s_addr);
453
PJ_DEF(void) pj_sockaddr_in_set_addr(pj_sockaddr_in *addr,
454
pj_uint32_t hostaddr)
456
addr->sin_addr.s_addr = pj_htonl(hostaddr);
462
PJ_DEF(pj_status_t) pj_sockaddr_parse2(int af, unsigned options,
464
pj_str_t *p_hostpart,
468
const char *end = str->ptr + str->slen;
469
const char *last_colon_pos = NULL;
470
unsigned colon_cnt = 0;
473
PJ_ASSERT_RETURN((af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) &&
475
str!=NULL, PJ_EINVAL);
477
/* Special handling for empty input */
478
if (str->slen==0 || str->ptr==NULL) {
480
p_hostpart->slen = 0;
488
/* Count the colon and get the last colon */
489
for (p=str->ptr; p!=end; ++p) {
496
/* Deduce address family if it's not given */
497
if (af == PJ_AF_UNSPEC) {
502
} else if (af == PJ_AF_INET && colon_cnt > 1)
508
if (af == PJ_AF_INET) {
509
/* Parse as IPv4. Supported formats:
519
hostpart.ptr = (char*)str->ptr;
521
if (last_colon_pos) {
525
hostpart.slen = last_colon_pos - str->ptr;
527
port_part.ptr = (char*)last_colon_pos + 1;
528
port_part.slen = end - port_part.ptr;
530
/* Make sure port number is valid */
531
for (i=0; i<port_part.slen; ++i) {
532
if (!pj_isdigit(port_part.ptr[i]))
535
port = pj_strtoul(&port_part);
539
hostpart.slen = str->slen;
544
*p_hostpart = hostpart;
546
*p_port = (pj_uint16_t)port;
550
} else if (af == PJ_AF_INET6) {
552
/* Parse as IPv6. Supported formats:
553
* - "fe::01:80" ==> note: port number is zero in this case, not 80!
566
pj_str_t hostpart, port_part;
568
if (*str->ptr == '[') {
573
if (last_colon_pos == NULL)
576
end_bracket = pj_strchr(str, ']');
577
if (end_bracket == NULL)
580
hostpart.ptr = (char*)str->ptr + 1;
581
hostpart.slen = end_bracket - hostpart.ptr;
583
if (last_colon_pos < end_bracket) {
584
port_part.ptr = NULL;
587
port_part.ptr = (char*)last_colon_pos + 1;
588
port_part.slen = end - port_part.ptr;
591
/* Make sure port number is valid */
592
for (i=0; i<port_part.slen; ++i) {
593
if (!pj_isdigit(port_part.ptr[i]))
596
port = pj_strtoul(&port_part);
601
*p_hostpart = hostpart;
603
*p_port = (pj_uint16_t)port;
608
/* Treat everything as part of the IPv6 IP address */
626
PJ_DEF(pj_status_t) pj_sockaddr_parse( int af, unsigned options,
634
PJ_ASSERT_RETURN(addr, PJ_EINVAL);
635
PJ_ASSERT_RETURN(af==PJ_AF_UNSPEC ||
637
af==PJ_AF_INET6, PJ_EINVAL);
638
PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
640
status = pj_sockaddr_parse2(af, options, str, &hostpart, &port, &af);
641
if (status != PJ_SUCCESS)
644
#if !defined(PJ_HAS_IPV6) || !PJ_HAS_IPV6
646
return PJ_EIPV6NOTSUP;
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.
655
const char *last_colon_pos=NULL, *p;
656
const char *end = str->ptr + str->slen;
657
unsigned long long_port;
661
/* Parse as IPv6:port */
662
for (p=str->ptr; p!=end; ++p) {
667
if (last_colon_pos == NULL)
670
hostpart.ptr = (char*)str->ptr;
671
hostpart.slen = last_colon_pos - str->ptr;
673
port_part.ptr = (char*)last_colon_pos + 1;
674
port_part.slen = end - port_part.ptr;
676
/* Make sure port number is valid */
677
for (i=0; i<port_part.slen; ++i) {
678
if (!pj_isdigit(port_part.ptr[i]))
681
long_port = pj_strtoul(&port_part);
682
if (long_port > 65535)
685
port = (pj_uint16_t)long_port;
687
status = pj_sockaddr_init(PJ_AF_INET6, addr, &hostpart, port);
694
/* Resolve the IP address of local machine */
695
PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr)
697
unsigned i, count, cand_cnt;
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,
709
MIN_WEIGHT = WEIGHT_DISABLED+1 /* minimum weight to use */
712
pj_sockaddr cand_addr[CAND_CNT];
713
int cand_weight[CAND_CNT];
715
char strip[PJ_INET6_ADDRSTRLEN+10];
716
/* Special IPv4 addresses. */
724
/* 127.0.0.0/8, loopback addr will be used if there is no other
727
{ 0x7f000000, 0xFF000000, WEIGHT_LOOPBACK },
729
/* 0.0.0.0/8, special IP that doesn't seem to be practically useful */
730
{ 0x00000000, 0xFF000000, WEIGHT_DISABLED },
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
736
{ 0xa9fe0000, 0xFFFF0000, WEIGHT_LINK_LOCAL }
738
/* Special IPv6 addresses */
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},
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},
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},
769
/* May not be used if TRACE_ is disabled */
770
PJ_UNUSED_ARG(strip);
773
/* Get rid of "uninitialized he variable" with MS compilers */
774
pj_bzero(&ai, sizeof(ai));
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]);
785
addr->addr.sa_family = (pj_uint16_t)af;
786
PJ_SOCKADDR_RESET_LEN(addr);
788
#if !defined(PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION) || \
789
PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION == 0
790
/* Get hostname's IP address */
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;
800
TRACE_((THIS_FILE, "hostname IP is %s",
801
pj_sockaddr_print(&ai.ai_addr, strip, sizeof(strip), 0)));
805
PJ_UNUSED_ARG(count);
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)));
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)
821
cand_weight[i] += WEIGHT_DEF_ROUTE;
823
pj_sockaddr_copy_addr(&cand_addr[i], addr);
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;
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);
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.
846
for (i=0; i<cand_cnt; ++i) {
848
for (j=0; j<count; ++j) {
849
if (pj_sockaddr_cmp(&cand_addr[i],
850
&cand_addr[start_if+j])==0)
856
cand_weight[i] -= WEIGHT_INTERFACE;
858
cand_weight[i] += WEIGHT_INTERFACE;
862
/* Add remaining interface to candidate list. */
863
for (i=0; i<count; ++i) {
865
for (j=0; j<cand_cnt; ++j) {
866
if (pj_sockaddr_cmp(&cand_addr[start_if+i],
872
pj_sockaddr_copy_addr(&cand_addr[cand_cnt],
873
&cand_addr[start_if+i]);
874
cand_weight[cand_cnt] += WEIGHT_INTERFACE;
881
/* Apply weight adjustment for special IPv4/IPv6 addresses
882
* See http://trac.pjsip.org/repos/ticket/1046
884
if (af == PJ_AF_INET) {
885
for (i=0; i<cand_cnt; ++i) {
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;
892
if ((a & pm) == pa) {
893
cand_weight[i] += spec_ipv4[j].weight;
898
} else if (af == PJ_AF_INET6) {
899
for (i=0; i<PJ_ARRAY_SIZE(spec_ipv6); ++i) {
901
for (j=0; j<cand_cnt; ++j) {
902
pj_uint8_t *a = cand_addr[j].ipv6.sin6_addr.s6_addr;
904
pj_uint8_t *pa = spec_ipv6[i].addr;
905
pj_uint8_t *pm = spec_ipv6[i].mask;
908
for (k=0; k<16; ++k) {
909
am[k] = (pj_uint8_t)((a[k] & pm[k]) & 0xFF);
912
if (pj_memcmp(am, pa, 16)==0) {
913
cand_weight[j] += spec_ipv6[i].weight;
921
/* Enumerate candidates to get the best IP address to choose */
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),
928
if (cand_weight[i] < MIN_WEIGHT) {
932
if (selected_cand == -1)
934
else if (cand_weight[i] > cand_weight[selected_cand])
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);
943
pj_in6_addr *s6_addr;
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;
949
TRACE_((THIS_FILE, "Loopback IP %s returned",
950
pj_sockaddr_print(addr, strip, sizeof(strip), 0)));
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)));
960
/* Get IP interface for sending to the specified destination */
961
PJ_DEF(pj_status_t) pj_getipinterface(int af,
963
pj_sockaddr *itf_addr,
964
pj_bool_t allow_resolve,
965
pj_sockaddr *p_dst_addr)
967
pj_sockaddr dst_addr;
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. */
978
status = pj_sockaddr_init(af, &dst_addr, dst, 53);
982
if (af == PJ_AF_INET) {
983
cp = pj_str("1.1.1.1");
987
status = pj_sockaddr_init(af, &dst_addr, &cp, 53);
990
if (status != PJ_SUCCESS)
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) {
1000
status = pj_sock_connect(fd, &dst_addr, pj_sockaddr_get_len(&dst_addr));
1001
if (status != PJ_SUCCESS) {
1006
len = sizeof(*itf_addr);
1007
status = pj_sock_getsockname(fd, itf_addr, &len);
1008
if (status != PJ_SUCCESS) {
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)
1020
return PJ_ENOTFOUND;
1024
*p_dst_addr = dst_addr;
1029
/* Get the default IP interface */
1030
PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr)
1034
if (af == PJ_AF_INET) {
1035
cp = pj_str("1.1.1.1");
1037
cp = pj_str("1::1");
1040
return pj_getipinterface(af, &cp, addr, PJ_FALSE, NULL);
1045
* Bind socket at random port.
1047
PJ_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)
1052
pj_sockaddr bind_addr;
1054
pj_uint16_t base_port;
1055
pj_status_t status = PJ_SUCCESS;
1059
PJ_ASSERT_RETURN(addr, PJ_EINVAL);
1061
pj_sockaddr_cp(&bind_addr, addr);
1062
addr_len = pj_sockaddr_get_len(addr);
1063
base_port = pj_sockaddr_get_port(addr);
1065
if (base_port == 0 || port_range == 0) {
1066
return pj_sock_bind(sockfd, &bind_addr, addr_len);
1069
for (; max_try; --max_try) {
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)
1082
/* Only need to implement these in DLL build */
1085
PJ_DEF(pj_uint16_t) pj_AF_UNSPEC(void)
1087
return PJ_AF_UNSPEC;
1090
PJ_DEF(pj_uint16_t) pj_AF_UNIX(void)
1095
PJ_DEF(pj_uint16_t) pj_AF_INET(void)
1100
PJ_DEF(pj_uint16_t) pj_AF_INET6(void)
1105
PJ_DEF(pj_uint16_t) pj_AF_PACKET(void)
1107
return PJ_AF_PACKET;
1110
PJ_DEF(pj_uint16_t) pj_AF_IRDA(void)
1115
PJ_DEF(int) pj_SOCK_STREAM(void)
1117
return PJ_SOCK_STREAM;
1120
PJ_DEF(int) pj_SOCK_DGRAM(void)
1122
return PJ_SOCK_DGRAM;
1125
PJ_DEF(int) pj_SOCK_RAW(void)
1130
PJ_DEF(int) pj_SOCK_RDM(void)
1135
PJ_DEF(pj_uint16_t) pj_SOL_SOCKET(void)
1137
return PJ_SOL_SOCKET;
1140
PJ_DEF(pj_uint16_t) pj_SOL_IP(void)
1145
PJ_DEF(pj_uint16_t) pj_SOL_TCP(void)
1150
PJ_DEF(pj_uint16_t) pj_SOL_UDP(void)
1155
PJ_DEF(pj_uint16_t) pj_SOL_IPV6(void)
1160
PJ_DEF(int) pj_IP_TOS(void)
1165
PJ_DEF(int) pj_IPTOS_LOWDELAY(void)
1167
return PJ_IPTOS_LOWDELAY;
1170
PJ_DEF(int) pj_IPTOS_THROUGHPUT(void)
1172
return PJ_IPTOS_THROUGHPUT;
1175
PJ_DEF(int) pj_IPTOS_RELIABILITY(void)
1177
return PJ_IPTOS_RELIABILITY;
1180
PJ_DEF(int) pj_IPTOS_MINCOST(void)
1182
return PJ_IPTOS_MINCOST;
1185
PJ_DEF(pj_uint16_t) pj_SO_TYPE(void)
1190
PJ_DEF(pj_uint16_t) pj_SO_RCVBUF(void)
1192
return PJ_SO_RCVBUF;
1195
PJ_DEF(pj_uint16_t) pj_SO_SNDBUF(void)
1197
return PJ_SO_SNDBUF;
1200
PJ_DEF(pj_uint16_t) pj_TCP_NODELAY(void)
1202
return PJ_TCP_NODELAY;
1205
PJ_DEF(pj_uint16_t) pj_SO_REUSEADDR(void)
1207
return PJ_SO_REUSEADDR;
1210
PJ_DEF(pj_uint16_t) pj_SO_NOSIGPIPE(void)
1212
return PJ_SO_NOSIGPIPE;
1215
PJ_DEF(pj_uint16_t) pj_SO_PRIORITY(void)
1217
return PJ_SO_PRIORITY;
1220
PJ_DEF(pj_uint16_t) pj_IP_MULTICAST_IF(void)
1222
return PJ_IP_MULTICAST_IF;
1225
PJ_DEF(pj_uint16_t) pj_IP_MULTICAST_TTL(void)
1227
return PJ_IP_MULTICAST_TTL;
1230
PJ_DEF(pj_uint16_t) pj_IP_MULTICAST_LOOP(void)
1232
return PJ_IP_MULTICAST_LOOP;
1235
PJ_DEF(pj_uint16_t) pj_IP_ADD_MEMBERSHIP(void)
1237
return PJ_IP_ADD_MEMBERSHIP;
1240
PJ_DEF(pj_uint16_t) pj_IP_DROP_MEMBERSHIP(void)
1242
return PJ_IP_DROP_MEMBERSHIP;
1245
PJ_DEF(int) pj_MSG_OOB(void)
1250
PJ_DEF(int) pj_MSG_PEEK(void)
1255
PJ_DEF(int) pj_MSG_DONTROUTE(void)
1257
return PJ_MSG_DONTROUTE;