10 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
11 |
|
* notice, this list of conditions and the following disclaimer in the |
12 |
|
* documentation and/or other materials provided with the distribution. |
13 |
– |
* 3. All advertising materials mentioning features or use of this software |
14 |
– |
* must display the following acknowledgement: |
15 |
– |
* This product includes software developed by the University of |
16 |
– |
* California, Berkeley and its contributors. |
13 |
|
* 4. Neither the name of the University nor the names of its contributors |
14 |
|
* may be used to endorse or promote products derived from this software |
15 |
|
* without specific prior written permission. |
77 |
|
*/ |
78 |
|
|
79 |
|
#include "stdinc.h" |
84 |
– |
#include "irc_reslib.h" |
85 |
– |
#include "irc_res.h" |
80 |
|
#include "ircd_defs.h" |
81 |
< |
#include "fileio.h" |
81 |
> |
#include "irc_res.h" |
82 |
> |
#include "irc_reslib.h" |
83 |
|
#include "irc_string.h" |
89 |
– |
#include "irc_getaddrinfo.h" |
84 |
|
|
85 |
|
#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */ |
86 |
|
#define DNS_LABELTYPE_BITSTRING 0x41 |
87 |
|
#define MAXLINE 128 |
88 |
|
|
89 |
< |
/* $Id: irc_reslib.c,v 7.26 2005/07/26 03:33:04 adx Exp $ */ |
89 |
> |
/* $Id$ */ |
90 |
|
|
91 |
|
struct irc_ssaddr irc_nsaddr_list[IRCD_MAXNS]; |
92 |
|
int irc_nscount = 0; |
99 |
– |
char irc_domain[HOSTLEN + 1]; |
93 |
|
|
94 |
+ |
static const char digits[] = "0123456789"; |
95 |
|
static const char digitvalue[256] = { |
96 |
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ |
97 |
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ |
111 |
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ |
112 |
|
}; |
113 |
|
|
120 |
– |
static int parse_resvconf(void); |
121 |
– |
static void add_nameserver(char *arg); |
122 |
– |
|
123 |
– |
static const char digits[] = "0123456789"; |
114 |
|
static int labellen(const unsigned char *lp); |
115 |
|
static int special(int ch); |
116 |
|
static int printable(int ch); |
117 |
< |
static int irc_decode_bitstring(const char **cpp, char *dn, const char *eom); |
117 |
> |
static int irc_decode_bitstring(const unsigned char **cpp, char *dn, const char *eom); |
118 |
|
static int irc_ns_name_compress(const char *src, unsigned char *dst, size_t dstsiz, |
119 |
|
const unsigned char **dnptrs, const unsigned char **lastdnptr); |
120 |
|
static int irc_dn_find(const unsigned char *, const unsigned char *, const unsigned char * const *, |
121 |
|
const unsigned char * const *); |
122 |
|
static int irc_encode_bitsring(const char **, const char *, unsigned char **, unsigned char **, |
123 |
< |
const char *); |
123 |
> |
const unsigned char *); |
124 |
|
static int irc_ns_name_uncompress(const unsigned char *, const unsigned char *, |
125 |
|
const unsigned char *, char *, size_t); |
126 |
|
static int irc_ns_name_unpack(const unsigned char *, const unsigned char *, |
127 |
|
const unsigned char *, unsigned char *, |
128 |
|
size_t); |
129 |
< |
static int irc_ns_name_ntop(const char *, char *, size_t); |
129 |
> |
static int irc_ns_name_ntop(const unsigned char *, char *, size_t); |
130 |
|
static int irc_ns_name_skip(const unsigned char **, const unsigned char *); |
131 |
|
static int mklower(int ch); |
132 |
|
|
133 |
< |
int |
134 |
< |
irc_res_init(void) |
133 |
> |
|
134 |
> |
/* add_nameserver() |
135 |
> |
* |
136 |
> |
* input - either an IPV4 address in dotted quad |
137 |
> |
* or an IPV6 address in : format |
138 |
> |
* output - NONE |
139 |
> |
* side effects - entry in irc_nsaddr_list is filled in as needed |
140 |
> |
*/ |
141 |
> |
static void |
142 |
> |
add_nameserver(const char *arg) |
143 |
|
{ |
144 |
< |
irc_nscount = 0; |
145 |
< |
return parse_resvconf(); |
144 |
> |
struct addrinfo hints, *res; |
145 |
> |
|
146 |
> |
/* Done max number of nameservers? */ |
147 |
> |
if (irc_nscount >= IRCD_MAXNS) |
148 |
> |
return; |
149 |
> |
|
150 |
> |
memset(&hints, 0, sizeof(hints)); |
151 |
> |
hints.ai_family = PF_UNSPEC; |
152 |
> |
hints.ai_socktype = SOCK_DGRAM; |
153 |
> |
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; |
154 |
> |
|
155 |
> |
if (getaddrinfo(arg, "domain", &hints, &res)) |
156 |
> |
return; |
157 |
> |
|
158 |
> |
if (res == NULL) |
159 |
> |
return; |
160 |
> |
|
161 |
> |
memcpy(&irc_nsaddr_list[irc_nscount].ss, res->ai_addr, res->ai_addrlen); |
162 |
> |
irc_nsaddr_list[irc_nscount++].ss_len = res->ai_addrlen; |
163 |
> |
freeaddrinfo(res); |
164 |
|
} |
165 |
|
|
166 |
|
/* parse_resvconf() |
169 |
|
* output - -1 if failure 0 if success |
170 |
|
* side effects - fills in irc_nsaddr_list |
171 |
|
*/ |
172 |
< |
static int |
172 |
> |
static void |
173 |
|
parse_resvconf(void) |
174 |
|
{ |
175 |
|
char *p; |
176 |
|
char *opt; |
177 |
|
char *arg; |
178 |
|
char input[MAXLINE]; |
179 |
< |
FBFILE *file; |
179 |
> |
FILE *file; |
180 |
|
|
181 |
< |
/* XXX "/etc/resolv.conf" should be from a define in setup.h perhaps |
181 |
> |
/* XXX "/etc/resolv.conf" should be from a define in config.h perhaps |
182 |
|
* for cygwin support etc. this hardcodes it to unix for now -db |
183 |
|
*/ |
184 |
< |
if ((file = fbopen("/etc/resolv.conf", "r")) == NULL) |
185 |
< |
return(-1); |
184 |
> |
if ((file = fopen("/etc/resolv.conf", "r")) == NULL) |
185 |
> |
return; |
186 |
|
|
187 |
< |
while (fbgets(input, MAXLINE, file) != NULL) |
187 |
> |
while (fgets(input, sizeof(input), file) != NULL) |
188 |
|
{ |
189 |
|
/* blow away any newline */ |
190 |
|
if ((p = strpbrk(input, "\r\n")) != NULL) |
191 |
|
*p = '\0'; |
192 |
|
|
177 |
– |
/* Ignore comment lines immediately */ |
178 |
– |
if (*input == '#') |
179 |
– |
continue; |
180 |
– |
|
193 |
|
p = input; |
194 |
+ |
|
195 |
|
/* skip until something thats not a space is seen */ |
196 |
|
while (IsSpace(*p)) |
197 |
< |
p++; |
197 |
> |
++p; |
198 |
> |
|
199 |
|
/* if at this point, have a '\0' then continue */ |
200 |
|
if (*p == '\0') |
201 |
|
continue; |
202 |
|
|
203 |
+ |
/* Ignore comment lines immediately */ |
204 |
+ |
if (*p == ';' || *p == '#') |
205 |
+ |
continue; |
206 |
+ |
|
207 |
|
/* skip until a space is found */ |
208 |
< |
opt = input; |
209 |
< |
while (!IsSpace(*p)) |
210 |
< |
if (*p++ == '\0') |
211 |
< |
continue; /* no arguments?.. ignore this line */ |
208 |
> |
opt = p; |
209 |
> |
while (!IsSpace(*p) && *p) |
210 |
> |
++p; |
211 |
> |
|
212 |
> |
if (*p == '\0') |
213 |
> |
continue; /* no arguments?.. ignore this line */ |
214 |
> |
|
215 |
|
/* blow away the space character */ |
216 |
|
*p++ = '\0'; |
217 |
|
|
218 |
|
/* skip these spaces that are before the argument */ |
219 |
|
while (IsSpace(*p)) |
220 |
< |
p++; |
220 |
> |
++p; |
221 |
> |
|
222 |
|
/* Now arg should be right where p is pointing */ |
223 |
|
arg = p; |
224 |
+ |
|
225 |
|
if ((p = strpbrk(arg, " \t")) != NULL) |
226 |
|
*p = '\0'; /* take the first word */ |
227 |
|
|
228 |
< |
if (irccmp(opt, "domain") == 0) |
206 |
< |
strlcpy(irc_domain, arg, HOSTLEN); |
207 |
< |
else if (irccmp(opt, "nameserver") == 0) |
228 |
> |
if (!irccmp(opt, "nameserver")) |
229 |
|
add_nameserver(arg); |
230 |
|
} |
231 |
|
|
232 |
< |
fbclose(file); |
212 |
< |
return(0); |
232 |
> |
fclose(file); |
233 |
|
} |
234 |
|
|
235 |
< |
/* add_nameserver() |
236 |
< |
* |
217 |
< |
* input - either an IPV4 address in dotted quad |
218 |
< |
* or an IPV6 address in : format |
219 |
< |
* output - NONE |
220 |
< |
* side effects - entry in irc_nsaddr_list is filled in as needed |
221 |
< |
*/ |
222 |
< |
static void |
223 |
< |
add_nameserver(char *arg) |
235 |
> |
void |
236 |
> |
irc_res_init(void) |
237 |
|
{ |
238 |
< |
struct addrinfo hints, *res; |
239 |
< |
/* Done max number of nameservers? */ |
227 |
< |
if ((irc_nscount) >= IRCD_MAXNS) |
228 |
< |
return; |
229 |
< |
|
230 |
< |
memset(&hints, 0, sizeof(hints)); |
231 |
< |
hints.ai_family = PF_UNSPEC; |
232 |
< |
hints.ai_socktype = SOCK_DGRAM; |
233 |
< |
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; |
234 |
< |
|
235 |
< |
if (irc_getaddrinfo(arg, "domain", &hints, &res)) |
236 |
< |
return; |
238 |
> |
irc_nscount = 0; |
239 |
> |
memset(irc_nsaddr_list, 0, sizeof(irc_nsaddr_list)); |
240 |
|
|
241 |
< |
if (res == NULL) |
239 |
< |
return; |
241 |
> |
parse_resvconf(); |
242 |
|
|
243 |
< |
memcpy(&irc_nsaddr_list[irc_nscount].ss, res->ai_addr, res->ai_addrlen); |
244 |
< |
irc_nsaddr_list[irc_nscount].ss_len = res->ai_addrlen; |
243 |
< |
irc_nscount++; |
244 |
< |
irc_freeaddrinfo(res); |
243 |
> |
if (!irc_nscount) |
244 |
> |
add_nameserver("127.0.0.1"); |
245 |
|
} |
246 |
|
|
247 |
|
/* |
260 |
|
if (n > 0 && dst[0] == '.') |
261 |
|
dst[0] = '\0'; |
262 |
|
return(n); |
263 |
< |
} |
263 |
> |
} /*2*/ |
264 |
|
|
265 |
|
/* |
266 |
|
* irc_ns_name_uncompress(msg, eom, src, dst, dstsiz) |
279 |
|
|
280 |
|
if ((n = irc_ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) |
281 |
|
return(-1); |
282 |
< |
if (irc_ns_name_ntop((char*)tmp, dst, dstsiz) == -1) |
282 |
> |
if (irc_ns_name_ntop(tmp, dst, dstsiz) == -1) |
283 |
|
return(-1); |
284 |
|
return(n); |
285 |
< |
} |
285 |
> |
} /*2*/ |
286 |
> |
|
287 |
|
/* |
288 |
|
* irc_ns_name_unpack(msg, eom, src, dst, dstsiz) |
289 |
|
* Unpack a domain name from a message, source may be compressed. |
363 |
|
if (len < 0) |
364 |
|
len = srcp - src; |
365 |
|
return (len); |
366 |
< |
} |
366 |
> |
} /*2*/ |
367 |
|
|
368 |
|
/* |
369 |
|
* irc_ns_name_ntop(src, dst, dstsiz) |
375 |
|
* All other domains are returned in non absolute form |
376 |
|
*/ |
377 |
|
static int |
378 |
< |
irc_ns_name_ntop(const char *src, char *dst, size_t dstsiz) |
378 |
> |
irc_ns_name_ntop(const unsigned char *src, char *dst, size_t dstsiz) |
379 |
|
{ |
380 |
< |
const char *cp; |
380 |
> |
const unsigned char *cp; |
381 |
|
char *dn, *eom; |
382 |
|
unsigned char c; |
383 |
|
unsigned int n; |
400 |
|
} |
401 |
|
*dn++ = '.'; |
402 |
|
} |
403 |
< |
if ((l = labellen((unsigned char*)(cp - 1))) < 0) { |
403 |
> |
if ((l = labellen((cp - 1))) < 0) { |
404 |
|
errno = EMSGSIZE; /* XXX */ |
405 |
|
return(-1); |
406 |
|
} |
464 |
|
} |
465 |
|
*dn++ = '\0'; |
466 |
|
return (dn - dst); |
467 |
< |
} |
467 |
< |
|
468 |
< |
/* |
469 |
< |
* Pack domain name 'exp_dn' in presentation form into 'comp_dn'. |
470 |
< |
* Return the size of the compressed name or -1. |
471 |
< |
* 'length' is the size of the array pointed to by 'comp_dn'. |
472 |
< |
*/ |
473 |
< |
static int |
474 |
< |
irc_dn_comp(const char *src, unsigned char *dst, int dstsiz, |
475 |
< |
unsigned char **dnptrs, unsigned char **lastdnptr) |
476 |
< |
{ |
477 |
< |
return(irc_ns_name_compress(src, dst, (size_t)dstsiz, |
478 |
< |
(const unsigned char **)dnptrs, |
479 |
< |
(const unsigned char **)lastdnptr)); |
480 |
< |
} |
467 |
> |
} /*2*/ |
468 |
|
|
469 |
|
/* |
470 |
|
* Skip over a compressed domain name. Return the size or -1. |
476 |
|
if (irc_ns_name_skip(&ptr, eom) == -1) |
477 |
|
return(-1); |
478 |
|
return(ptr - saveptr); |
479 |
< |
} |
479 |
> |
} /*2*/ |
480 |
|
|
481 |
|
/* |
482 |
|
* ns_name_skip(ptrptr, eom) |
529 |
|
|
530 |
|
*ptrptr = cp; |
531 |
|
return(0); |
532 |
< |
} |
532 |
> |
} /*2*/ |
533 |
|
|
534 |
|
unsigned int |
535 |
|
irc_ns_get16(const unsigned char *src) |
588 |
|
default: |
589 |
|
return(0); |
590 |
|
} |
591 |
< |
} |
591 |
> |
} /*2*/ |
592 |
|
|
593 |
|
static int |
594 |
|
labellen(const unsigned char *lp) |
615 |
|
} |
616 |
|
|
617 |
|
return(l); |
618 |
< |
} |
618 |
> |
} /*2*/ |
619 |
|
|
620 |
|
|
621 |
|
/* |
629 |
|
printable(int ch) |
630 |
|
{ |
631 |
|
return(ch > 0x20 && ch < 0x7f); |
632 |
< |
} |
632 |
> |
} /*2*/ |
633 |
|
|
634 |
|
static int |
635 |
< |
irc_decode_bitstring(const char **cpp, char *dn, const char *eom) |
635 |
> |
irc_decode_bitstring(const unsigned char **cpp, char *dn, const char *eom) |
636 |
|
{ |
637 |
< |
const char *cp = *cpp; |
637 |
> |
const unsigned char *cp = *cpp; |
638 |
|
char *beg = dn, tc; |
639 |
|
int b, blen, plen; |
640 |
|
|
661 |
|
|
662 |
|
*cpp = cp; |
663 |
|
return(dn - beg); |
664 |
< |
} |
664 |
> |
} /*2*/ |
665 |
|
|
666 |
|
/* |
667 |
|
* irc_ns_name_pton(src, dst, dstsiz) |
697 |
|
cp + 2, |
698 |
|
&label, |
699 |
|
&bp, |
700 |
< |
(const char *)eom)) |
700 |
> |
eom)) |
701 |
|
!= 0) { |
702 |
|
errno = e; |
703 |
|
return(-1); |
801 |
|
} |
802 |
|
|
803 |
|
return (0); |
804 |
< |
} |
804 |
> |
} /*2*/ |
805 |
|
|
806 |
|
/* |
807 |
|
* irc_ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) |
910 |
|
return (-1); |
911 |
|
} |
912 |
|
return(dstp - dst); |
913 |
< |
} |
913 |
> |
} /*2*/ |
914 |
|
|
915 |
|
static int |
916 |
|
irc_ns_name_compress(const char *src, unsigned char *dst, size_t dstsiz, |
925 |
|
|
926 |
|
static int |
927 |
|
irc_encode_bitsring(const char **bp, const char *end, unsigned char **labelp, |
928 |
< |
unsigned char **dst, const char *eom) |
928 |
> |
unsigned char **dst, const unsigned char *eom) |
929 |
|
{ |
930 |
|
int afterslash = 0; |
931 |
|
const char *cp = *bp; |
932 |
< |
char *tp, c; |
932 |
> |
unsigned char *tp; |
933 |
> |
char c; |
934 |
|
const char *beg_blen; |
935 |
|
char *end_blen = NULL; |
936 |
|
int value = 0, count = 0, tbcount = 0, blen = 0; |
947 |
|
if (!isxdigit((*cp) & 0xff)) /* reject '\[x/BLEN]' */ |
948 |
|
return(EINVAL); |
949 |
|
|
950 |
< |
for (tp = (char*)(dst + 1); cp < end && tp < eom; cp++) { |
950 |
> |
for (tp = *dst + 1; cp < end && tp < eom; cp++) { |
951 |
|
switch((c = *cp)) { |
952 |
|
case ']': /* end of the bitstring */ |
953 |
|
if (afterslash) { |
1024 |
|
**dst = blen; |
1025 |
|
|
1026 |
|
*bp = cp; |
1027 |
< |
*dst = (unsigned char*)tp; |
1027 |
> |
*dst = tp; |
1028 |
|
|
1029 |
|
return(0); |
1030 |
< |
} |
1030 |
> |
} /*2*/ |
1031 |
|
|
1032 |
|
/* |
1033 |
|
* dn_find(domain, msg, dnptrs, lastdnptr) |
1096 |
|
} |
1097 |
|
errno = ENOENT; |
1098 |
|
return (-1); |
1099 |
< |
} |
1099 |
> |
} /*2*/ |
1100 |
|
|
1101 |
|
/* |
1102 |
|
* * Thinking in noninternationalized USASCII (per the DNS spec), |
1109 |
|
return(ch + 0x20); |
1110 |
|
|
1111 |
|
return(ch); |
1112 |
< |
} |
1112 |
> |
} /*2*/ |
1113 |
|
|
1114 |
|
/* From resolv/mkquery.c */ |
1115 |
|
|
1127 |
|
HEADER *hp; |
1128 |
|
unsigned char *cp; |
1129 |
|
int n; |
1130 |
< |
unsigned char *dnptrs[20], **dpp, **lastdnptr; |
1130 |
> |
const unsigned char *dnptrs[20], **dpp, **lastdnptr; |
1131 |
|
|
1132 |
|
/* |
1133 |
|
* Initialize header fields. |
1150 |
|
|
1151 |
|
if ((buflen -= QFIXEDSZ) < 0) |
1152 |
|
return (-1); |
1153 |
< |
if ((n = irc_dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) |
1153 |
> |
if ((n = irc_ns_name_compress(dname, cp, buflen, dnptrs, |
1154 |
> |
lastdnptr)) < 0) |
1155 |
|
return (-1); |
1156 |
|
|
1157 |
|
cp += n; |