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

« back to all changes in this revision

Viewing changes to .pc/38-unresolvable-mx.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 (-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 err;
 
131
        int i;
 
132
 
 
133
        res_init();
 
134
        searchhost = host;
 
135
        cname_recurse = 0;
 
136
 
 
137
        anssz = 65536;
 
138
        ans = malloc(anssz);
 
139
        if (ans == NULL)
 
140
                return (1);
 
141
 
 
142
        if (no_mx)
 
143
                goto out;
 
144
 
 
145
repeat:
 
146
        err = res_search(searchhost, ns_c_in, ns_t_mx, ans, anssz);
 
147
        if (err < 0) {
 
148
                switch (h_errno) {
 
149
                case NO_DATA:
 
150
                        /*
 
151
                         * Host exists, but no MX (or CNAME) entry.
 
152
                         * Not an error, use host name instead.
 
153
                         */
 
154
                        goto out;
 
155
                case TRY_AGAIN:
 
156
                        /* transient error */
 
157
                        goto transerr;
 
158
                case NO_RECOVERY:
 
159
                case HOST_NOT_FOUND:
 
160
                default:
 
161
                        errno = ENOENT;
 
162
                        goto err;
 
163
                }
 
164
        }
 
165
 
 
166
        if (!ns_initparse(ans, anssz, &msg))
 
167
                goto transerr;
 
168
 
 
169
        switch (ns_msg_getflag(msg, ns_f_rcode)) {
 
170
        case ns_r_noerror:
 
171
                break;
 
172
        case ns_r_nxdomain:
 
173
                goto err;
 
174
        default:
 
175
                goto transerr;
 
176
        }
 
177
 
 
178
        for (i = 0; i < ns_msg_count(msg, ns_s_an); i++) {
 
179
                if (ns_parserr(&msg, ns_s_an, i, &rr))
 
180
                        goto transerr;
 
181
 
 
182
                cp = (const char *)ns_rr_rdata(rr);
 
183
 
 
184
                switch (ns_rr_type(rr)) {
 
185
                case ns_t_mx:
 
186
                        pref = ns_get16(cp);
 
187
                        cp += 2;
 
188
                        err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
 
189
                                                 cp, outname, sizeof(outname));
 
190
                        if (err < 0)
 
191
                                goto transerr;
 
192
 
 
193
                        add_host(pref, outname, port, &hosts, &nhosts);
 
194
                        break;
 
195
 
 
196
                case ns_t_cname:
 
197
                        err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
 
198
                                                 cp, outname, sizeof(outname));
 
199
                        if (err < 0)
 
200
                                goto transerr;
 
201
 
 
202
                        /* Prevent a CNAME loop */
 
203
                        if (cname_recurse++ > 10)
 
204
                                goto err;
 
205
 
 
206
                        searchhost = outname;
 
207
                        goto repeat;
 
208
 
 
209
                default:
 
210
                        break;
 
211
                }
 
212
        }
 
213
 
 
214
out:
 
215
        err = 0;
 
216
        if (0) {
 
217
transerr:
 
218
                if (nhosts == 0)
 
219
                        err = 1;
 
220
        }
 
221
        if (0) {
 
222
err:
 
223
                err = -1;
 
224
        }
 
225
 
 
226
        free(ans);
 
227
 
 
228
        if (!err) {
 
229
                /*
 
230
                 * If we didn't find any MX, use the hostname instead.
 
231
                 */
 
232
                if (nhosts == 0)
 
233
                        add_host(0, searchhost, port, &hosts, &nhosts);
 
234
 
 
235
                qsort(hosts, nhosts, sizeof(*hosts), sort_pref);
 
236
        }
 
237
 
 
238
        if (nhosts > 0) {
 
239
                /* terminate list */
 
240
                *hosts[nhosts].host = 0;
 
241
        } else {
 
242
                if (hosts != NULL)
 
243
                        free(hosts);
 
244
                hosts = NULL;
 
245
        }
 
246
 
 
247
        *he = hosts;
 
248
        return (err);
 
249
 
 
250
        free(ans);
 
251
        if (hosts != NULL)
 
252
                free(hosts);
 
253
        return (err);
 
254
}
 
255
 
 
256
#if defined(TESTING)
 
257
int
 
258
main(int argc, char **argv)
 
259
{
 
260
        struct mx_hostentry *he, *p;
 
261
        int err;
 
262
 
 
263
        err = dns_get_mx_list(argv[1], 53, &he, 0);
 
264
        if (err)
 
265
                return (err);
 
266
 
 
267
        for (p = he; *p->host != 0; p++) {
 
268
                printf("%d\t%s\t%s\n", p->pref, p->host, p->addr);
 
269
        }
 
270
 
 
271
        return (0);
 
272
}
 
273
#endif