1 /* resolv.c resolver glue.
2 * Copyright (C) 2003 Simon Josefsson
3 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4 * Ryan Eatmon, Robert Norris
6 * This file is part of Shishi.
8 * Shishi is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * Shishi is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Shishi; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* This file comes from jabberd - Jabber Open Source Server, licensed
31 /* the largest packet we'll send and receive */
33 # define MAX_PACKET PACKETSZ
35 # define MAX_PACKET (1024)
41 unsigned char buf
[MAX_PACKET
];
45 _a_rr (dns_packet_t packet
, unsigned char *eom
, unsigned char **scan
)
49 GETLONG (in
.s_addr
, *scan
);
50 in
.s_addr
= ntohl (in
.s_addr
);
52 return strdup (inet_ntoa (in
));
56 _srv_rr (dns_packet_t packet
, unsigned char *eom
, unsigned char **scan
)
58 unsigned int priority
, weight
, port
;
63 GETSHORT (priority
, *scan
);
64 GETSHORT (weight
, *scan
);
65 GETSHORT (port
, *scan
);
67 len
= dn_expand (packet
.buf
, eom
, *scan
, host
, 256);
70 *scan
= (unsigned char *) (*scan
+ len
);
72 srv
= (dns_srv_t
) malloc (sizeof (struct dns_srv_st
));
74 srv
->priority
= priority
;
78 /* figure out the randomised weight */
79 /* !!! this seems wrong, but I don't have the RFC on hand */
81 srv
->rweight
= 1 + random () % (10000 * weight
);
85 strcpy (srv
->name
, host
);
90 /* compare two srv structures, order by priority then by randomised weight */
92 _srv_compare (const void *a
, const void *b
)
101 aa
= (dns_srv_t
) (*((dnshost_t
*) a
))->rr
;
102 bb
= (dns_srv_t
) (*((dnshost_t
*) b
))->rr
;
104 if (aa
->priority
> bb
->priority
)
106 if (aa
->priority
< bb
->priority
)
109 if (aa
->rweight
> bb
->rweight
)
111 if (aa
->rweight
< bb
->rweight
)
117 /* the actual resolver function */
119 _shishi_resolv (const char *zone
, unsigned int query_type
)
123 int len
, qdcount
, ancount
, an
, n
;
124 unsigned char *eom
, *scan
;
125 dnshost_t
*reply
, first
;
126 unsigned int type
, class, ttl
;
128 if (zone
== NULL
|| *zone
== '\0')
141 /* do the actual query */
142 if ((len
= res_query (zone
, C_IN
, query_type
, packet
.buf
, MAX_PACKET
)) == -1
143 || len
< sizeof (HEADER
))
146 /* we got a valid result, containing two types of records - packet
147 * and answer .. we have to skip over the packet records */
149 /* no. of packets, no. of answers */
150 qdcount
= ntohs (packet
.hdr
.qdcount
);
151 ancount
= ntohs (packet
.hdr
.ancount
);
153 /* end of the returned message */
154 eom
= (unsigned char *) (packet
.buf
+ len
);
156 /* our current location */
157 scan
= (unsigned char *) (packet
.buf
+ sizeof (HEADER
));
159 /* skip over the packet records */
160 while (qdcount
> 0 && scan
< eom
)
163 if ((len
= dn_expand (packet
.buf
, eom
, scan
, host
, 256)) < 0)
165 scan
= (unsigned char *) (scan
+ len
+ QFIXEDSZ
);
168 /* create an array to store the replies in */
169 reply
= (dnshost_t
*) malloc (sizeof (dnshost_t
) * ancount
);
170 memset (reply
, 0, sizeof (dnshost_t
) * ancount
);
173 /* loop through the answer buffer and extract SRV records */
174 while (ancount
> 0 && scan
< eom
)
177 len
= dn_expand (packet
.buf
, eom
, scan
, host
, 256);
180 for (n
= 0; n
< an
; n
++)
188 /* extract the various parts of the record */
189 GETSHORT (type
, scan
);
190 GETSHORT (class, scan
);
192 GETSHORT (len
, scan
);
194 /* skip records we're not interested in */
195 if (type
!= query_type
)
197 scan
= (unsigned char *) (scan
+ len
);
201 /* create a new reply structure to save it in */
202 reply
[an
] = (dnshost_t
) malloc (sizeof (struct dnshost_st
));
204 reply
[an
]->type
= type
;
205 reply
[an
]->class = class;
206 reply
[an
]->ttl
= ttl
;
208 reply
[an
]->next
= NULL
;
210 /* type-specific processing */
214 reply
[an
]->rr
= _a_rr (packet
, eom
, &scan
);
218 reply
[an
]->rr
= _srv_rr (packet
, eom
, &scan
);
222 scan
= (unsigned char *) (scan
+ len
);
226 /* fell short, we're done */
227 if (reply
[an
]->rr
== NULL
)
234 /* on to the next one */
238 /* sort srv records them */
239 if (query_type
== T_SRV
)
240 qsort (reply
, an
, sizeof (dnshost_t
), _srv_compare
);
242 /* build a linked list out of the array elements */
243 for (n
= 0; n
< an
- 1; n
++)
244 reply
[n
]->next
= reply
[n
+ 1];
253 /* free an srv structure */
255 _shishi_resolv_free (dnshost_t dns
)
271 _shishi_resolv (const char *zone
, unsigned int query_type
)
277 _shishi_resolv_free (dnshost_t dns
)