~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjlib/src/pj/addr_resolv_sock.c

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: addr_resolv_sock.c 3553 2011-05-05 06:14:19Z nanang $ */
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/addr_resolv.h>
21
 
#include <pj/assert.h>
22
 
#include <pj/string.h>
23
 
#include <pj/errno.h>
24
 
#include <pj/ip_helper.h>
25
 
#include <pj/compat/socket.h>
26
 
 
27
 
#if defined(PJ_GETADDRINFO_USE_CFHOST) && PJ_GETADDRINFO_USE_CFHOST!=0
28
 
#   include <CoreFoundation/CFString.h>
29
 
#   include <CFNetwork/CFHost.h>
30
 
#endif
31
 
 
32
 
PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *hostname, pj_hostent *phe)
33
 
{
34
 
    struct hostent *he;
35
 
    char copy[PJ_MAX_HOSTNAME];
36
 
 
37
 
    pj_assert(hostname && hostname ->slen < PJ_MAX_HOSTNAME);
38
 
    
39
 
    if (hostname->slen >= PJ_MAX_HOSTNAME)
40
 
        return PJ_ENAMETOOLONG;
41
 
 
42
 
    pj_memcpy(copy, hostname->ptr, hostname->slen);
43
 
    copy[ hostname->slen ] = '\0';
44
 
 
45
 
    he = gethostbyname(copy);
46
 
    if (!he) {
47
 
        return PJ_ERESOLVE;
48
 
        /* DO NOT use pj_get_netos_error() since host resolution error
49
 
         * is reported in h_errno instead of errno!
50
 
        return pj_get_netos_error();
51
 
         */
52
 
    }
53
 
 
54
 
    phe->h_name = he->h_name;
55
 
    phe->h_aliases = he->h_aliases;
56
 
    phe->h_addrtype = he->h_addrtype;
57
 
    phe->h_length = he->h_length;
58
 
    phe->h_addr_list = he->h_addr_list;
59
 
 
60
 
    return PJ_SUCCESS;
61
 
}
62
 
 
63
 
/* Resolve IPv4/IPv6 address */
64
 
PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename,
65
 
                                   unsigned *count, pj_addrinfo ai[])
66
 
{
67
 
#if defined(PJ_SOCK_HAS_GETADDRINFO) && PJ_SOCK_HAS_GETADDRINFO!=0
68
 
    char nodecopy[PJ_MAX_HOSTNAME];
69
 
    pj_bool_t has_addr = PJ_FALSE;
70
 
    unsigned i;
71
 
#if defined(PJ_GETADDRINFO_USE_CFHOST) && PJ_GETADDRINFO_USE_CFHOST!=0
72
 
    CFStringRef hostname;
73
 
    CFHostRef hostRef;
74
 
    pj_status_t status = PJ_SUCCESS;
75
 
#else
76
 
    int rc;
77
 
    struct addrinfo hint, *res, *orig_res;
78
 
#endif
79
 
 
80
 
    PJ_ASSERT_RETURN(nodename && count && *count && ai, PJ_EINVAL);
81
 
    PJ_ASSERT_RETURN(nodename->ptr && nodename->slen, PJ_EINVAL);
82
 
    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6 ||
83
 
                     af==PJ_AF_UNSPEC, PJ_EINVAL);
84
 
 
85
 
    /* Check if nodename is IP address */
86
 
    pj_bzero(&ai[0], sizeof(ai[0]));
87
 
    if ((af==PJ_AF_INET || af==PJ_AF_UNSPEC) &&
88
 
        pj_inet_pton(PJ_AF_INET, nodename,
89
 
                     &ai[0].ai_addr.ipv4.sin_addr) == PJ_SUCCESS)
90
 
    {
91
 
        af = PJ_AF_INET;
92
 
        has_addr = PJ_TRUE;
93
 
    } else if ((af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) &&
94
 
               pj_inet_pton(PJ_AF_INET6, nodename,
95
 
                            &ai[0].ai_addr.ipv6.sin6_addr) == PJ_SUCCESS)
96
 
    {
97
 
        af = PJ_AF_INET6;
98
 
        has_addr = PJ_TRUE;
99
 
    }
100
 
 
101
 
    if (has_addr) {
102
 
        pj_str_t tmp;
103
 
 
104
 
        tmp.ptr = ai[0].ai_canonname;
105
 
        pj_strncpy_with_null(&tmp, nodename, PJ_MAX_HOSTNAME);
106
 
        ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af;
107
 
        *count = 1;
108
 
 
109
 
        return PJ_SUCCESS;
110
 
    }
111
 
 
112
 
    /* Copy node name to null terminated string. */
113
 
    if (nodename->slen >= PJ_MAX_HOSTNAME)
114
 
        return PJ_ENAMETOOLONG;
115
 
    pj_memcpy(nodecopy, nodename->ptr, nodename->slen);
116
 
    nodecopy[nodename->slen] = '\0';
117
 
 
118
 
#if defined(PJ_GETADDRINFO_USE_CFHOST) && PJ_GETADDRINFO_USE_CFHOST!=0
119
 
    hostname =  CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, nodecopy,
120
 
                                                kCFStringEncodingASCII,
121
 
                                                kCFAllocatorNull);
122
 
    hostRef = CFHostCreateWithName(kCFAllocatorDefault, hostname);
123
 
    if (CFHostStartInfoResolution(hostRef, kCFHostAddresses, nil)) {
124
 
        CFArrayRef addrRef = CFHostGetAddressing(hostRef, nil);
125
 
        i = 0;
126
 
        if (addrRef != nil) {
127
 
            CFIndex idx, naddr;
128
 
            
129
 
            naddr = CFArrayGetCount(addrRef);
130
 
            for (idx = 0; idx < naddr && i < *count; idx++) {
131
 
                struct sockaddr *addr;
132
 
                
133
 
                addr = (struct sockaddr *)
134
 
                       CFDataGetBytePtr(CFArrayGetValueAtIndex(addrRef, idx));
135
 
                /* This should not happen. */
136
 
                pj_assert(addr);
137
 
                
138
 
                /* Ignore unwanted address families */
139
 
                if (af!=PJ_AF_UNSPEC && addr->sa_family != af)
140
 
                    continue;
141
 
 
142
 
                /* Store canonical name */
143
 
                pj_ansi_strcpy(ai[i].ai_canonname, nodecopy);
144
 
                
145
 
                /* Store address */
146
 
                PJ_ASSERT_ON_FAIL(sizeof(*addr) <= sizeof(pj_sockaddr),
147
 
                                  continue);
148
 
                pj_memcpy(&ai[i].ai_addr, addr, sizeof(*addr));
149
 
                PJ_SOCKADDR_RESET_LEN(&ai[i].ai_addr);
150
 
                
151
 
                i++;
152
 
            }
153
 
        }
154
 
        
155
 
        *count = i;
156
 
    } else {
157
 
        status = PJ_ERESOLVE;
158
 
    }
159
 
    
160
 
    CFRelease(hostRef);
161
 
    CFRelease(hostname);
162
 
    
163
 
    return status;
164
 
#else
165
 
    /* Call getaddrinfo() */
166
 
    pj_bzero(&hint, sizeof(hint));
167
 
    hint.ai_family = af;
168
 
 
169
 
    rc = getaddrinfo(nodecopy, NULL, &hint, &res);
170
 
    if (rc != 0)
171
 
        return PJ_ERESOLVE;
172
 
 
173
 
    orig_res = res;
174
 
 
175
 
    /* Enumerate each item in the result */
176
 
    for (i=0; i<*count && res; res=res->ai_next) {
177
 
        /* Ignore unwanted address families */
178
 
        if (af!=PJ_AF_UNSPEC && res->ai_family != af)
179
 
            continue;
180
 
 
181
 
        /* Store canonical name (possibly truncating the name) */
182
 
        if (res->ai_canonname) {
183
 
            pj_ansi_strncpy(ai[i].ai_canonname, res->ai_canonname,
184
 
                            sizeof(ai[i].ai_canonname));
185
 
            ai[i].ai_canonname[sizeof(ai[i].ai_canonname)-1] = '\0';
186
 
        } else {
187
 
            pj_ansi_strcpy(ai[i].ai_canonname, nodecopy);
188
 
        }
189
 
 
190
 
        /* Store address */
191
 
        PJ_ASSERT_ON_FAIL(res->ai_addrlen <= sizeof(pj_sockaddr), continue);
192
 
        pj_memcpy(&ai[i].ai_addr, res->ai_addr, res->ai_addrlen);
193
 
        PJ_SOCKADDR_RESET_LEN(&ai[i].ai_addr);
194
 
 
195
 
        /* Next slot */
196
 
        ++i;
197
 
    }
198
 
 
199
 
    *count = i;
200
 
 
201
 
    freeaddrinfo(orig_res);
202
 
 
203
 
    /* Done */
204
 
    return PJ_SUCCESS;
205
 
#endif
206
 
 
207
 
#else   /* PJ_SOCK_HAS_GETADDRINFO */
208
 
    pj_bool_t has_addr = PJ_FALSE;
209
 
 
210
 
    PJ_ASSERT_RETURN(count && *count, PJ_EINVAL);
211
 
 
212
 
    /* Check if nodename is IP address */
213
 
    pj_bzero(&ai[0], sizeof(ai[0]));
214
 
    if ((af==PJ_AF_INET || af==PJ_AF_UNSPEC) &&
215
 
        pj_inet_pton(PJ_AF_INET, nodename,
216
 
                     &ai[0].ai_addr.ipv4.sin_addr) == PJ_SUCCESS)
217
 
    {
218
 
        af = PJ_AF_INET;
219
 
        has_addr = PJ_TRUE;
220
 
    }
221
 
    else if ((af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) &&
222
 
             pj_inet_pton(PJ_AF_INET6, nodename,
223
 
                          &ai[0].ai_addr.ipv6.sin6_addr) == PJ_SUCCESS)
224
 
    {
225
 
        af = PJ_AF_INET6;
226
 
        has_addr = PJ_TRUE;
227
 
    }
228
 
 
229
 
    if (has_addr) {
230
 
        pj_str_t tmp;
231
 
 
232
 
        tmp.ptr = ai[0].ai_canonname;
233
 
        pj_strncpy_with_null(&tmp, nodename, PJ_MAX_HOSTNAME);
234
 
        ai[0].ai_addr.addr.sa_family = (pj_uint16_t)af;
235
 
        *count = 1;
236
 
 
237
 
        return PJ_SUCCESS;
238
 
    }
239
 
 
240
 
    if (af == PJ_AF_INET || af == PJ_AF_UNSPEC) {
241
 
        pj_hostent he;
242
 
        unsigned i, max_count;
243
 
        pj_status_t status;
244
 
        
245
 
        /* VC6 complains that "he" is uninitialized */
246
 
        #ifdef _MSC_VER
247
 
        pj_bzero(&he, sizeof(he));
248
 
        #endif
249
 
 
250
 
        status = pj_gethostbyname(nodename, &he);
251
 
        if (status != PJ_SUCCESS)
252
 
            return status;
253
 
 
254
 
        max_count = *count;
255
 
        *count = 0;
256
 
 
257
 
        pj_bzero(ai, max_count * sizeof(pj_addrinfo));
258
 
 
259
 
        for (i=0; he.h_addr_list[i] && *count<max_count; ++i) {
260
 
            pj_ansi_strncpy(ai[*count].ai_canonname, he.h_name,
261
 
                            sizeof(ai[*count].ai_canonname));
262
 
            ai[*count].ai_canonname[sizeof(ai[*count].ai_canonname)-1] = '\0';
263
 
 
264
 
            ai[*count].ai_addr.ipv4.sin_family = PJ_AF_INET;
265
 
            pj_memcpy(&ai[*count].ai_addr.ipv4.sin_addr,
266
 
                      he.h_addr_list[i], he.h_length);
267
 
            PJ_SOCKADDR_RESET_LEN(&ai[*count].ai_addr);
268
 
 
269
 
            (*count)++;
270
 
        }
271
 
 
272
 
        return PJ_SUCCESS;
273
 
 
274
 
    } else {
275
 
        /* IPv6 is not supported */
276
 
        *count = 0;
277
 
 
278
 
        return PJ_EIPV6NOTSUP;
279
 
    }
280
 
#endif  /* PJ_SOCK_HAS_GETADDRINFO */
281
 
}
282