~ubuntu-branches/ubuntu/oneiric/dma/oneiric

« back to all changes in this revision

Viewing changes to .pc/39-fix-add-host.patch/dns.c

  • Committer: Bazaar Package Importer
  • Author(s): Tarun Kumar Mall
  • Date: 2011-03-09 17:46:56 UTC
  • mfrom: (7.2.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110309174656-7s0buxoxvsos8ua1
Tags: 0.0.2010.06.17-10ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Patch 38_fix_ftbfs_binutils-gold.patch imported from previous
    ubuntu version.
  - Patch 38_fix_ftbfs_binutils-gold.patch renamed to
    42_fix_ftbfs_binutils-gold.patch
  - Patch 43_fix_ftbfs_Werror.patch added to fix 
    crypto.c:92:7: error: assignment discards 'const' qualifier 
    from pointer target type [-Werror] "Closes: #622052"

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
 
3
 *
 
4
 * This code is derived from software contributed to The DragonFly Project
 
5
 * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions
 
9
 * are met:
 
10
 *
 
11
 * 1. Redistributions of source code must retain the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer.
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in
 
15
 *    the documentation and/or other materials provided with the
 
16
 *    distribution.
 
17
 * 3. Neither the name of The DragonFly Project nor the names of its
 
18
 *    contributors may be used to endorse or promote products derived
 
19
 *    from this software without specific, prior written permission.
 
20
 *
 
21
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
22
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
23
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 
24
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 
25
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 
26
 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
 
27
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
28
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 
29
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
30
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 
31
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
32
 * SUCH DAMAGE.
 
33
 */
 
34
 
 
35
#include <sys/types.h>
 
36
#include <netinet/in.h>
 
37
#include <arpa/inet.h>
 
38
#include <arpa/nameser.h>
 
39
#include <errno.h>
 
40
#include <netdb.h>
 
41
#include <resolv.h>
 
42
#include <string.h>
 
43
#include <stdlib.h>
 
44
 
 
45
#include "dma.h"
 
46
 
 
47
static int
 
48
sort_pref(const void *a, const void *b)
 
49
{
 
50
        const struct mx_hostentry *ha = a, *hb = b;
 
51
        int v;
 
52
 
 
53
        /* sort increasing by preference primarily */
 
54
        v = ha->pref - hb->pref;
 
55
        if (v != 0)
 
56
                return (v);
 
57
 
 
58
        /* sort PF_INET6 before PF_INET */
 
59
        v = - (ha->ai.ai_family - hb->ai.ai_family);
 
60
        return (v);
 
61
}
 
62
 
 
63
static int
 
64
add_host(int pref, const char *host, int port, struct mx_hostentry **he, size_t *ps)
 
65
{
 
66
        struct addrinfo hints, *res, *res0 = NULL;
 
67
        char servname[10];
 
68
        struct mx_hostentry *p;
 
69
        size_t onhosts;
 
70
        const int count_inc = 10;
 
71
        int err;
 
72
 
 
73
        onhosts = *ps;
 
74
 
 
75
        memset(&hints, 0, sizeof(hints));
 
76
        hints.ai_family = PF_UNSPEC;
 
77
        hints.ai_socktype = SOCK_STREAM;
 
78
        hints.ai_protocol = IPPROTO_TCP;
 
79
 
 
80
        snprintf(servname, sizeof(servname), "%d", port);
 
81
        err = getaddrinfo(host, servname, &hints, &res0);
 
82
        if (err)
 
83
                return (err == EAI_AGAIN ? 1 : -1);
 
84
 
 
85
        for (res = res0; res != NULL; res = res->ai_next) {
 
86
                if (*ps + 1 >= roundup(*ps, count_inc)) {
 
87
                        size_t newsz = roundup(*ps + 2, count_inc);
 
88
                        *he = reallocf(*he, newsz * sizeof(**he));
 
89
                        if (*he == NULL)
 
90
                                goto out;
 
91
                }
 
92
 
 
93
                p = &(*he)[*ps];
 
94
                strlcpy(p->host, host, sizeof(p->host));
 
95
                p->pref = pref;
 
96
                p->ai = *res;
 
97
                p->ai.ai_addr = NULL;
 
98
                bcopy(res->ai_addr, &p->sa, p->ai.ai_addrlen);
 
99
 
 
100
                getnameinfo((struct sockaddr *)&p->sa, p->ai.ai_addrlen,
 
101
                            p->addr, sizeof(p->addr),
 
102
                            NULL, 0, NI_NUMERICHOST);
 
103
 
 
104
                (*ps)++;
 
105
        }
 
106
        freeaddrinfo(res0);
 
107
 
 
108
        return (*ps - onhosts);
 
109
 
 
110
out:
 
111
        if (res0 != NULL)
 
112
                freeaddrinfo(res0);
 
113
        return (1);
 
114
}
 
115
 
 
116
int
 
117
dns_get_mx_list(const char *host, int port, struct mx_hostentry **he, int no_mx)
 
118
{
 
119
        char outname[MAXDNAME];
 
120
        ns_msg msg;
 
121
        ns_rr rr;
 
122
        const char *searchhost;
 
123
        const char *cp;
 
124
        char *ans;
 
125
        struct mx_hostentry *hosts = NULL;
 
126
        size_t nhosts = 0;
 
127
        size_t anssz;
 
128
        int pref;
 
129
        int cname_recurse;
 
130
        int have_mx = 0;
 
131
        int err;
 
132
        int i;
 
133
 
 
134
        res_init();
 
135
        searchhost = host;
 
136
        cname_recurse = 0;
 
137
 
 
138
        anssz = 65536;
 
139
        ans = malloc(anssz);
 
140
        if (ans == NULL)
 
141
                return (1);
 
142
 
 
143
        if (no_mx)
 
144
                goto out;
 
145
 
 
146
repeat:
 
147
        err = res_search(searchhost, ns_c_in, ns_t_mx, ans, anssz);
 
148
        if (err < 0) {
 
149
                switch (h_errno) {
 
150
                case NO_DATA:
 
151
                        /*
 
152
                         * Host exists, but no MX (or CNAME) entry.
 
153
                         * Not an error, use host name instead.
 
154
                         */
 
155
                        goto out;
 
156
                case TRY_AGAIN:
 
157
                        /* transient error */
 
158
                        goto transerr;
 
159
                case NO_RECOVERY:
 
160
                case HOST_NOT_FOUND:
 
161
                default:
 
162
                        errno = ENOENT;
 
163
                        goto err;
 
164
                }
 
165
        }
 
166
 
 
167
        if (!ns_initparse(ans, anssz, &msg))
 
168
                goto transerr;
 
169
 
 
170
        switch (ns_msg_getflag(msg, ns_f_rcode)) {
 
171
        case ns_r_noerror:
 
172
                break;
 
173
        case ns_r_nxdomain:
 
174
                goto err;
 
175
        default:
 
176
                goto transerr;
 
177
        }
 
178
 
 
179
        for (i = 0; i < ns_msg_count(msg, ns_s_an); i++) {
 
180
                if (ns_parserr(&msg, ns_s_an, i, &rr))
 
181
                        goto transerr;
 
182
 
 
183
                cp = (const char *)ns_rr_rdata(rr);
 
184
 
 
185
                switch (ns_rr_type(rr)) {
 
186
                case ns_t_mx:
 
187
                        have_mx = 1;
 
188
                        pref = ns_get16(cp);
 
189
                        cp += 2;
 
190
                        err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
 
191
                                                 cp, outname, sizeof(outname));
 
192
                        if (err < 0)
 
193
                                goto transerr;
 
194
 
 
195
                        err = add_host(pref, outname, port, &hosts, &nhosts);
 
196
                        if (err == -1)
 
197
                                goto err;
 
198
                        break;
 
199
 
 
200
                case ns_t_cname:
 
201
                        err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
 
202
                                                 cp, outname, sizeof(outname));
 
203
                        if (err < 0)
 
204
                                goto transerr;
 
205
 
 
206
                        /* Prevent a CNAME loop */
 
207
                        if (cname_recurse++ > 10)
 
208
                                goto err;
 
209
 
 
210
                        searchhost = outname;
 
211
                        goto repeat;
 
212
 
 
213
                default:
 
214
                        break;
 
215
                }
 
216
        }
 
217
 
 
218
out:
 
219
        err = 0;
 
220
        if (0) {
 
221
transerr:
 
222
                if (nhosts == 0)
 
223
                        err = 1;
 
224
        }
 
225
        if (0) {
 
226
err:
 
227
                err = -1;
 
228
        }
 
229
 
 
230
        free(ans);
 
231
 
 
232
        if (err == 0) {
 
233
                if (!have_mx) {
 
234
                        /*
 
235
                         * If we didn't find any MX, use the hostname instead.
 
236
                         */
 
237
                        err = add_host(0, host, port, &hosts, &nhosts);
 
238
                } else if (nhosts == 0) {
 
239
                        /*
 
240
                         * We did get MX, but couldn't resolve any of them
 
241
                         * due to transient errors.
 
242
                         */
 
243
                        err = 1;
 
244
                }
 
245
        }
 
246
 
 
247
        if (nhosts > 0) {
 
248
                qsort(hosts, nhosts, sizeof(*hosts), sort_pref);
 
249
                /* terminate list */
 
250
                *hosts[nhosts].host = 0;
 
251
        } else {
 
252
                if (hosts != NULL)
 
253
                        free(hosts);
 
254
                hosts = NULL;
 
255
        }
 
256
 
 
257
        *he = hosts;
 
258
        return (err);
 
259
 
 
260
        free(ans);
 
261
        if (hosts != NULL)
 
262
                free(hosts);
 
263
        return (err);
 
264
}
 
265
 
 
266
#if defined(TESTING)
 
267
int
 
268
main(int argc, char **argv)
 
269
{
 
270
        struct mx_hostentry *he, *p;
 
271
        int err;
 
272
 
 
273
        err = dns_get_mx_list(argv[1], 53, &he, 0);
 
274
        if (err)
 
275
                return (err);
 
276
 
 
277
        for (p = he; *p->host != 0; p++) {
 
278
                printf("%d\t%s\t%s\n", p->pref, p->host, p->addr);
 
279
        }
 
280
 
 
281
        return (0);
 
282
}
 
283
#endif