Merge lp:~davewalker/ubuntu/lucid/asterisk/lp605358 into lp:ubuntu/lucid/asterisk
- Lucid (10.04)
- lp605358
- Merge into lucid
Status: | Merged |
---|---|
Merge reported by: | Dave Walker |
Merged at revision: | not available |
Proposed branch: | lp:~davewalker/ubuntu/lucid/asterisk/lp605358 |
Merge into: | lp:ubuntu/lucid/asterisk |
Diff against target: |
1432 lines (+1252/-13) 12 files modified
.pc/.quilt_patches (+1/-0) .pc/.quilt_series (+1/-0) .pc/applied-patches (+1/-0) .pc/dnsmgr-A-SRV-handling/include/asterisk/dnsmgr.h (+105/-0) .pc/dnsmgr-A-SRV-handling/main/acl.c (+541/-0) .pc/dnsmgr-A-SRV-handling/main/dnsmgr.c (+439/-0) debian/changelog (+8/-0) debian/patches/dnsmgr-A-SRV-handling (+132/-0) debian/patches/series (+1/-0) include/asterisk/dnsmgr.h (+4/-3) main/acl.c (+1/-0) main/dnsmgr.c (+18/-10) |
To merge this branch: | bzr merge lp:~davewalker/ubuntu/lucid/asterisk/lp605358 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Stable Release Updates Team | Pending | ||
Ubuntu Sponsors | Pending | ||
Review via email: mp+29860@code.launchpad.net |
Commit message
Description of the change
asterisk (1:1.6.
* debian/
SRV record changes and problem with multiple A/SRV records returned.
Patch based on Asterisk project's upstream patch. (LP: #605358)
-- Dave Walker (Daviey) <email address hidden> Wed, 14 Jul 2010 11:40:55 +0100
SRU:-
IMPACT: New users or users upgrading to Lucid, who use a provider that has multiple A/SRV records, after a short amount of time will not be able to make outgoing calls.
FIX: Patch derived from upstream asterisk addresses this issue with better dnsmgr handling
TEST CASE: Install asterisk, set up a peer using multiple A or SRV records, observe:
"[Jul 14 12:07:57] WARNING[25721]: chan_sip.c:3581 __sip_xmit: sip_xmit of 0xb9bdb680 (len 536) to X.X.X.X:5060 returned -1: Address family not supported by protocol", and therefore outgoing calls fail.
Notes: Applied in current upstream trunk and stable, and therefore will be in Maverick in a forthcoming merge.
- 58. By Dave Walker
-
debian/changelog: Removed .patch extension from new patch
- 59. By Dave Walker
-
Added .pc quilt meta files for completness
Dave Walker (davewalker) wrote : | # |
Preview Diff
1 | === added file '.pc/.quilt_patches' |
2 | --- .pc/.quilt_patches 1970-01-01 00:00:00 +0000 |
3 | +++ .pc/.quilt_patches 2010-07-16 10:16:00 +0000 |
4 | @@ -0,0 +1,1 @@ |
5 | +debian/patches |
6 | |
7 | === added file '.pc/.quilt_series' |
8 | --- .pc/.quilt_series 1970-01-01 00:00:00 +0000 |
9 | +++ .pc/.quilt_series 2010-07-16 10:16:00 +0000 |
10 | @@ -0,0 +1,1 @@ |
11 | +series |
12 | |
13 | === added file '.pc/allow-tilde-destdir/.timestamp' |
14 | === modified file '.pc/applied-patches' |
15 | --- .pc/applied-patches 2010-03-02 10:00:03 +0000 |
16 | +++ .pc/applied-patches 2010-07-16 10:16:00 +0000 |
17 | @@ -11,3 +11,4 @@ |
18 | dahdi_ptmp_nt |
19 | dahdi_pri_debug_spannums |
20 | sound_files |
21 | +dnsmgr-A-SRV-handling |
22 | |
23 | === added file '.pc/astgenkey-security/.timestamp' |
24 | === added file '.pc/dahdi-fxsks-hookstate/.timestamp' |
25 | === added file '.pc/dahdi_pri_debug_spannums/.timestamp' |
26 | === added file '.pc/dahdi_ptmp_nt/.timestamp' |
27 | === added directory '.pc/dnsmgr-A-SRV-handling' |
28 | === added file '.pc/dnsmgr-A-SRV-handling/.timestamp' |
29 | === added directory '.pc/dnsmgr-A-SRV-handling/include' |
30 | === added directory '.pc/dnsmgr-A-SRV-handling/include/asterisk' |
31 | === added file '.pc/dnsmgr-A-SRV-handling/include/asterisk/dnsmgr.h' |
32 | --- .pc/dnsmgr-A-SRV-handling/include/asterisk/dnsmgr.h 1970-01-01 00:00:00 +0000 |
33 | +++ .pc/dnsmgr-A-SRV-handling/include/asterisk/dnsmgr.h 2010-07-16 10:16:00 +0000 |
34 | @@ -0,0 +1,105 @@ |
35 | +/* |
36 | + * Asterisk -- An open source telephony toolkit. |
37 | + * |
38 | + * Copyright (C) 1999 - 2005, Digium, Inc. |
39 | + * |
40 | + * Kevin P. Fleming <kpfleming@digium.com> |
41 | + * |
42 | + * See http://www.asterisk.org for more information about |
43 | + * the Asterisk project. Please do not directly contact |
44 | + * any of the maintainers of this project for assistance; |
45 | + * the project provides a web site, mailing lists and IRC |
46 | + * channels for your use. |
47 | + * |
48 | + * This program is free software, distributed under the terms of |
49 | + * the GNU General Public License Version 2. See the LICENSE file |
50 | + * at the top of the source tree. |
51 | + */ |
52 | + |
53 | +/*! \file |
54 | + * \brief Background DNS update manager |
55 | + */ |
56 | + |
57 | +#ifndef _ASTERISK_DNSMGR_H |
58 | +#define _ASTERISK_DNSMGR_H |
59 | + |
60 | +#if defined(__cplusplus) || defined(c_plusplus) |
61 | +extern "C" { |
62 | +#endif |
63 | + |
64 | +#include "asterisk/network.h" |
65 | +#include "asterisk/srv.h" |
66 | + |
67 | +/*! |
68 | + * \brief A DNS manager entry |
69 | + * |
70 | + * This is an opaque type. |
71 | + */ |
72 | +struct ast_dnsmgr_entry; |
73 | + |
74 | +/*! |
75 | + * \brief Allocate a new DNS manager entry |
76 | + * |
77 | + * \param name the hostname |
78 | + * \param result where the DNS manager should store the IP address as it refreshes it. |
79 | + * it. |
80 | + * |
81 | + * This function allocates a new DNS manager entry object, and fills it with the |
82 | + * provided hostname and IP address. This function does not force an initial lookup |
83 | + * of the IP address. So, generally, this should be used when the initial address |
84 | + * is already known. |
85 | + * |
86 | + * \return a DNS manager entry |
87 | + * \version 1.6.1 result changed from struct in_addr to struct sockaddr_in to store port number |
88 | + */ |
89 | +struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct sockaddr_in *result, const char *service); |
90 | + |
91 | +/*! |
92 | + * \brief Free a DNS manager entry |
93 | + * |
94 | + * \param entry the DNS manager entry to free |
95 | + * |
96 | + * \return nothing |
97 | + */ |
98 | +void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry); |
99 | + |
100 | +/*! |
101 | + * \brief Allocate and initialize a DNS manager entry |
102 | + * |
103 | + * \param name the hostname |
104 | + * \param result where to store the IP address as the DNS manager refreshes it |
105 | + * \param dnsmgr Where to store the allocate DNS manager entry |
106 | + * |
107 | + * This function allocates a new DNS manager entry object, and fills it with |
108 | + * the provided hostname and IP address. This function _does_ force an initial |
109 | + * lookup, so it may block for some period of time. |
110 | + * |
111 | + * \retval 0 success |
112 | + * \retval non-zero failure |
113 | + * \version 1.6.1 result changed from struct in_addr to struct aockaddr_in to store port number |
114 | + */ |
115 | +int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_dnsmgr_entry **dnsmgr, const char *service); |
116 | + |
117 | +/*! |
118 | + * \brief Force a refresh of a dnsmgr entry |
119 | + * |
120 | + * \retval non-zero if the result is different than the previous result |
121 | + * \retval zero if the result is the same as the previous result |
122 | + */ |
123 | +int ast_dnsmgr_refresh(struct ast_dnsmgr_entry *entry); |
124 | + |
125 | +/*! |
126 | + * \brief Check is see if a dnsmgr entry has changed |
127 | + * |
128 | + * \retval non-zero if the dnsmgr entry has changed since the last call to |
129 | + * this function |
130 | + * \retval zero if the dnsmgr entry has not changed since the last call to |
131 | + * this function |
132 | + */ |
133 | +int ast_dnsmgr_changed(struct ast_dnsmgr_entry *entry); |
134 | + |
135 | +#if defined(__cplusplus) || defined(c_plusplus) |
136 | +} |
137 | +#endif /* c_plusplus */ |
138 | + |
139 | +#endif /* ASTERISK_DNSMGR_H */ |
140 | |
141 | === added directory '.pc/dnsmgr-A-SRV-handling/main' |
142 | === added file '.pc/dnsmgr-A-SRV-handling/main/acl.c' |
143 | --- .pc/dnsmgr-A-SRV-handling/main/acl.c 1970-01-01 00:00:00 +0000 |
144 | +++ .pc/dnsmgr-A-SRV-handling/main/acl.c 2010-07-16 10:16:00 +0000 |
145 | @@ -0,0 +1,541 @@ |
146 | +/* |
147 | + * Asterisk -- An open source telephony toolkit. |
148 | + * |
149 | + * Copyright (C) 1999 - 2006, Digium, Inc. |
150 | + * |
151 | + * Mark Spencer <markster@digium.com> |
152 | + * |
153 | + * See http://www.asterisk.org for more information about |
154 | + * the Asterisk project. Please do not directly contact |
155 | + * any of the maintainers of this project for assistance; |
156 | + * the project provides a web site, mailing lists and IRC |
157 | + * channels for your use. |
158 | + * |
159 | + * This program is free software, distributed under the terms of |
160 | + * the GNU General Public License Version 2. See the LICENSE file |
161 | + * at the top of the source tree. |
162 | + */ |
163 | + |
164 | +/*! \file |
165 | + * |
166 | + * \brief Various sorts of access control |
167 | + * |
168 | + * \author Mark Spencer <markster@digium.com> |
169 | + */ |
170 | + |
171 | +#include "asterisk.h" |
172 | + |
173 | +ASTERISK_FILE_VERSION(__FILE__, "$Revision: 248849 $") |
174 | + |
175 | +#include "asterisk/network.h" |
176 | + |
177 | +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__) |
178 | +#include <fcntl.h> |
179 | +#include <net/route.h> |
180 | +#endif |
181 | + |
182 | +#if defined(SOLARIS) |
183 | +#include <sys/sockio.h> |
184 | +#include <net/if.h> |
185 | +#elif defined(HAVE_GETIFADDRS) |
186 | +#include <ifaddrs.h> |
187 | +#endif |
188 | + |
189 | +#include "asterisk/acl.h" |
190 | +#include "asterisk/channel.h" |
191 | +#include "asterisk/utils.h" |
192 | +#include "asterisk/lock.h" |
193 | +#include "asterisk/srv.h" |
194 | + |
195 | +#if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS)) |
196 | +static int get_local_address(struct in_addr *ourip) |
197 | +{ |
198 | + return -1; |
199 | +} |
200 | +#else |
201 | +static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score) |
202 | +{ |
203 | + const char *address; |
204 | + int score; |
205 | + |
206 | + address = ast_inet_ntoa(sin->sin_addr); |
207 | + |
208 | + /* RFC 1700 alias for the local network */ |
209 | + if (address[0] == '0') { |
210 | + score = -25; |
211 | + /* RFC 1700 localnet */ |
212 | + } else if (strncmp(address, "127", 3) == 0) { |
213 | + score = -20; |
214 | + /* RFC 1918 non-public address space */ |
215 | + } else if (strncmp(address, "10.", 3) == 0) { |
216 | + score = -5; |
217 | + /* RFC 1918 non-public address space */ |
218 | + } else if (strncmp(address, "172", 3) == 0) { |
219 | + /* 172.16.0.0 - 172.19.255.255, but not 172.160.0.0 - 172.169.255.255 */ |
220 | + if (address[4] == '1' && address[5] >= '6' && address[6] == '.') { |
221 | + score = -5; |
222 | + /* 172.20.0.0 - 172.29.255.255, but not 172.200.0.0 - 172.255.255.255 nor 172.2.0.0 - 172.2.255.255 */ |
223 | + } else if (address[4] == '2' && address[6] == '.') { |
224 | + score = -5; |
225 | + /* 172.30.0.0 - 172.31.255.255 */ |
226 | + } else if (address[4] == '3' && address[5] <= '1') { |
227 | + score = -5; |
228 | + /* All other 172 addresses are public */ |
229 | + } else { |
230 | + score = 0; |
231 | + } |
232 | + /* RFC 2544 Benchmark test range (198.18.0.0 - 198.19.255.255, but not 198.180.0.0 - 198.199.255.255) */ |
233 | + } else if (strncmp(address, "198.1", 5) == 0 && address[5] >= '8' && address[6] == '.') { |
234 | + score = -10; |
235 | + /* RFC 1918 non-public address space */ |
236 | + } else if (strncmp(address, "192.168", 7) == 0) { |
237 | + score = -5; |
238 | + /* RFC 3330 Zeroconf network */ |
239 | + } else if (strncmp(address, "169.254", 7) == 0) { |
240 | + /*!\note Better score than a test network, but not quite as good as RFC 1918 |
241 | + * address space. The reason is that some Linux distributions automatically |
242 | + * configure a Zeroconf address before trying DHCP, so we want to prefer a |
243 | + * DHCP lease to a Zeroconf address. |
244 | + */ |
245 | + score = -10; |
246 | + /* RFC 3330 Test network */ |
247 | + } else if (strncmp(address, "192.0.2.", 8) == 0) { |
248 | + score = -15; |
249 | + /* Every other address should be publically routable */ |
250 | + } else { |
251 | + score = 0; |
252 | + } |
253 | + |
254 | + if (score > *best_score) { |
255 | + *best_score = score; |
256 | + memcpy(best_addr, &sin->sin_addr, sizeof(*best_addr)); |
257 | + } |
258 | +} |
259 | + |
260 | +static int get_local_address(struct in_addr *ourip) |
261 | +{ |
262 | + int s, res = -1; |
263 | +#ifdef SOLARIS |
264 | + struct lifreq *ifr = NULL; |
265 | + struct lifnum ifn; |
266 | + struct lifconf ifc; |
267 | + struct sockaddr_in *sa; |
268 | + char *buf = NULL; |
269 | + int bufsz, x; |
270 | +#endif /* SOLARIS */ |
271 | +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) |
272 | + struct ifaddrs *ifap, *ifaphead; |
273 | + int rtnerr; |
274 | + const struct sockaddr_in *sin; |
275 | +#endif /* BSD_OR_LINUX */ |
276 | + struct in_addr best_addr; |
277 | + int best_score = -100; |
278 | + memset(&best_addr, 0, sizeof(best_addr)); |
279 | + |
280 | +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) |
281 | + rtnerr = getifaddrs(&ifaphead); |
282 | + if (rtnerr) { |
283 | + perror(NULL); |
284 | + return -1; |
285 | + } |
286 | +#endif /* BSD_OR_LINUX */ |
287 | + |
288 | + s = socket(AF_INET, SOCK_STREAM, 0); |
289 | + |
290 | + if (s > 0) { |
291 | +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) |
292 | + for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) { |
293 | + |
294 | + if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) { |
295 | + sin = (const struct sockaddr_in *) ifap->ifa_addr; |
296 | + score_address(sin, &best_addr, &best_score); |
297 | + res = 0; |
298 | + |
299 | + if (best_score == 0) { |
300 | + break; |
301 | + } |
302 | + } |
303 | + } |
304 | +#endif /* BSD_OR_LINUX */ |
305 | + |
306 | + /* There is no reason whatsoever that this shouldn't work on Linux or BSD also. */ |
307 | +#ifdef SOLARIS |
308 | + /* Get a count of interfaces on the machine */ |
309 | + ifn.lifn_family = AF_INET; |
310 | + ifn.lifn_flags = 0; |
311 | + ifn.lifn_count = 0; |
312 | + if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) { |
313 | + close(s); |
314 | + return -1; |
315 | + } |
316 | + |
317 | + bufsz = ifn.lifn_count * sizeof(struct lifreq); |
318 | + if (!(buf = malloc(bufsz))) { |
319 | + close(s); |
320 | + return -1; |
321 | + } |
322 | + memset(buf, 0, bufsz); |
323 | + |
324 | + /* Get a list of interfaces on the machine */ |
325 | + ifc.lifc_len = bufsz; |
326 | + ifc.lifc_buf = buf; |
327 | + ifc.lifc_family = AF_INET; |
328 | + ifc.lifc_flags = 0; |
329 | + if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) { |
330 | + close(s); |
331 | + free(buf); |
332 | + return -1; |
333 | + } |
334 | + |
335 | + for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) { |
336 | + sa = (struct sockaddr_in *)&(ifr->lifr_addr); |
337 | + score_address(sa, &best_addr, &best_score); |
338 | + res = 0; |
339 | + |
340 | + if (best_score == 0) { |
341 | + break; |
342 | + } |
343 | + } |
344 | + |
345 | + free(buf); |
346 | +#endif /* SOLARIS */ |
347 | + |
348 | + close(s); |
349 | + } |
350 | +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__) |
351 | + freeifaddrs(ifaphead); |
352 | +#endif /* BSD_OR_LINUX */ |
353 | + |
354 | + if (res == 0 && ourip) { |
355 | + memcpy(ourip, &best_addr, sizeof(*ourip)); |
356 | + } |
357 | + return res; |
358 | +} |
359 | +#endif /* HAVE_GETIFADDRS */ |
360 | + |
361 | +/* Free HA structure */ |
362 | +void ast_free_ha(struct ast_ha *ha) |
363 | +{ |
364 | + struct ast_ha *hal; |
365 | + while (ha) { |
366 | + hal = ha; |
367 | + ha = ha->next; |
368 | + ast_free(hal); |
369 | + } |
370 | +} |
371 | + |
372 | +/* Copy HA structure */ |
373 | +void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to) |
374 | +{ |
375 | + memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr)); |
376 | + memcpy(&to->netmask, &from->netmask, sizeof(from->netmask)); |
377 | + to->sense = from->sense; |
378 | +} |
379 | + |
380 | +/* Create duplicate of ha structure */ |
381 | +static struct ast_ha *ast_duplicate_ha(struct ast_ha *original) |
382 | +{ |
383 | + struct ast_ha *new_ha; |
384 | + |
385 | + if ((new_ha = ast_malloc(sizeof(*new_ha)))) { |
386 | + /* Copy from original to new object */ |
387 | + ast_copy_ha(original, new_ha); |
388 | + } |
389 | + |
390 | + return new_ha; |
391 | +} |
392 | + |
393 | +/* Create duplicate HA link list */ |
394 | +/* Used in chan_sip2 templates */ |
395 | +struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original) |
396 | +{ |
397 | + struct ast_ha *start = original; |
398 | + struct ast_ha *ret = NULL; |
399 | + struct ast_ha *current, *prev = NULL; |
400 | + |
401 | + while (start) { |
402 | + current = ast_duplicate_ha(start); /* Create copy of this object */ |
403 | + if (prev) { |
404 | + prev->next = current; /* Link previous to this object */ |
405 | + } |
406 | + |
407 | + if (!ret) { |
408 | + ret = current; /* Save starting point */ |
409 | + } |
410 | + |
411 | + start = start->next; /* Go to next object */ |
412 | + prev = current; /* Save pointer to this object */ |
413 | + } |
414 | + return ret; /* Return start of list */ |
415 | +} |
416 | + |
417 | +struct ast_ha *ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error) |
418 | +{ |
419 | + struct ast_ha *ha; |
420 | + char *nm; |
421 | + struct ast_ha *prev = NULL; |
422 | + struct ast_ha *ret; |
423 | + int x; |
424 | + char *tmp = ast_strdupa(stuff); |
425 | + |
426 | + ret = path; |
427 | + while (path) { |
428 | + prev = path; |
429 | + path = path->next; |
430 | + } |
431 | + |
432 | + if (!(ha = ast_malloc(sizeof(*ha)))) { |
433 | + return ret; |
434 | + } |
435 | + |
436 | + if (!(nm = strchr(tmp, '/'))) { |
437 | + /* assume /32. Yes, htonl does not do anything for this particular mask |
438 | + but we better use it to show we remember about byte order */ |
439 | + ha->netmask.s_addr = htonl(0xFFFFFFFF); |
440 | + } else { |
441 | + *nm = '\0'; |
442 | + nm++; |
443 | + |
444 | + if (!strchr(nm, '.')) { |
445 | + if ((sscanf(nm, "%30d", &x) == 1) && (x >= 0) && (x <= 32)) { |
446 | + if (x == 0) { |
447 | + /* This is special-cased to prevent unpredictable |
448 | + * behavior of shifting left 32 bits |
449 | + */ |
450 | + ha->netmask.s_addr = 0; |
451 | + } else { |
452 | + ha->netmask.s_addr = htonl(0xFFFFFFFF << (32 - x)); |
453 | + } |
454 | + } else { |
455 | + ast_log(LOG_WARNING, "Invalid CIDR in %s\n", stuff); |
456 | + ast_free(ha); |
457 | + if (error) { |
458 | + *error = 1; |
459 | + } |
460 | + return ret; |
461 | + } |
462 | + } else if (!inet_aton(nm, &ha->netmask)) { |
463 | + ast_log(LOG_WARNING, "Invalid mask in %s\n", stuff); |
464 | + ast_free(ha); |
465 | + if (error) { |
466 | + *error = 1; |
467 | + } |
468 | + return ret; |
469 | + } |
470 | + } |
471 | + |
472 | + if (!inet_aton(tmp, &ha->netaddr)) { |
473 | + ast_log(LOG_WARNING, "Invalid IP address in %s\n", stuff); |
474 | + ast_free(ha); |
475 | + if (error) { |
476 | + *error = 1; |
477 | + } |
478 | + return ret; |
479 | + } |
480 | + |
481 | + ha->netaddr.s_addr &= ha->netmask.s_addr; |
482 | + |
483 | + ha->sense = strncasecmp(sense, "p", 1) ? AST_SENSE_DENY : AST_SENSE_ALLOW; |
484 | + |
485 | + ha->next = NULL; |
486 | + if (prev) { |
487 | + prev->next = ha; |
488 | + } else { |
489 | + ret = ha; |
490 | + } |
491 | + |
492 | + ast_debug(1, "%s/%s sense %d appended to acl for peer\n", ast_strdupa(ast_inet_ntoa(ha->netaddr)), ast_strdupa(ast_inet_ntoa(ha->netmask)), ha->sense); |
493 | + |
494 | + return ret; |
495 | +} |
496 | + |
497 | +int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin) |
498 | +{ |
499 | + /* Start optimistic */ |
500 | + int res = AST_SENSE_ALLOW; |
501 | + while (ha) { |
502 | +#if 0 /* debugging code */ |
503 | + char iabuf[INET_ADDRSTRLEN]; |
504 | + char iabuf2[INET_ADDRSTRLEN]; |
505 | + /* DEBUG */ |
506 | + ast_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf)); |
507 | + ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2)); |
508 | + ast_debug(1, "##### Testing %s with %s\n", iabuf, iabuf2); |
509 | +#endif |
510 | + /* For each rule, if this address and the netmask = the net address |
511 | + apply the current rule */ |
512 | + if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == ha->netaddr.s_addr) { |
513 | + res = ha->sense; |
514 | + } |
515 | + ha = ha->next; |
516 | + } |
517 | + return res; |
518 | +} |
519 | + |
520 | +int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service) |
521 | +{ |
522 | + struct hostent *hp; |
523 | + struct ast_hostent ahp; |
524 | + char srv[256]; |
525 | + char host[256]; |
526 | + int tportno = ntohs(sin->sin_port); |
527 | + if (service) { |
528 | + snprintf(srv, sizeof(srv), "%s.%s", service, value); |
529 | + if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) { |
530 | + sin->sin_port = htons(tportno); |
531 | + value = host; |
532 | + } |
533 | + } |
534 | + if ((hp = ast_gethostbyname(value, &ahp))) { |
535 | + memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); |
536 | + } else { |
537 | + ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value); |
538 | + return -1; |
539 | + } |
540 | + return 0; |
541 | +} |
542 | + |
543 | +struct dscp_codepoint { |
544 | + char *name; |
545 | + unsigned int space; |
546 | +}; |
547 | + |
548 | +/* IANA registered DSCP codepoints */ |
549 | + |
550 | +static const struct dscp_codepoint dscp_pool1[] = { |
551 | + { "CS0", 0x00 }, |
552 | + { "CS1", 0x08 }, |
553 | + { "CS2", 0x10 }, |
554 | + { "CS3", 0x18 }, |
555 | + { "CS4", 0x20 }, |
556 | + { "CS5", 0x28 }, |
557 | + { "CS6", 0x30 }, |
558 | + { "CS7", 0x38 }, |
559 | + { "AF11", 0x0A }, |
560 | + { "AF12", 0x0C }, |
561 | + { "AF13", 0x0E }, |
562 | + { "AF21", 0x12 }, |
563 | + { "AF22", 0x14 }, |
564 | + { "AF23", 0x16 }, |
565 | + { "AF31", 0x1A }, |
566 | + { "AF32", 0x1C }, |
567 | + { "AF33", 0x1E }, |
568 | + { "AF41", 0x22 }, |
569 | + { "AF42", 0x24 }, |
570 | + { "AF43", 0x26 }, |
571 | + { "EF", 0x2E }, |
572 | +}; |
573 | + |
574 | +int ast_str2cos(const char *value, unsigned int *cos) |
575 | +{ |
576 | + int fval; |
577 | + |
578 | + if (sscanf(value, "%30d", &fval) == 1) { |
579 | + if (fval < 8) { |
580 | + *cos = fval; |
581 | + return 0; |
582 | + } |
583 | + } |
584 | + |
585 | + return -1; |
586 | +} |
587 | + |
588 | +int ast_str2tos(const char *value, unsigned int *tos) |
589 | +{ |
590 | + int fval; |
591 | + unsigned int x; |
592 | + |
593 | + if (sscanf(value, "%30i", &fval) == 1) { |
594 | + *tos = fval & 0xFF; |
595 | + return 0; |
596 | + } |
597 | + |
598 | + for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) { |
599 | + if (!strcasecmp(value, dscp_pool1[x].name)) { |
600 | + *tos = dscp_pool1[x].space << 2; |
601 | + return 0; |
602 | + } |
603 | + } |
604 | + |
605 | + return -1; |
606 | +} |
607 | + |
608 | +const char *ast_tos2str(unsigned int tos) |
609 | +{ |
610 | + unsigned int x; |
611 | + |
612 | + for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) { |
613 | + if (dscp_pool1[x].space == (tos >> 2)) { |
614 | + return dscp_pool1[x].name; |
615 | + } |
616 | + } |
617 | + |
618 | + return "unknown"; |
619 | +} |
620 | + |
621 | +int ast_get_ip(struct sockaddr_in *sin, const char *value) |
622 | +{ |
623 | + return ast_get_ip_or_srv(sin, value, NULL); |
624 | +} |
625 | + |
626 | +int ast_ouraddrfor(struct in_addr *them, struct in_addr *us) |
627 | +{ |
628 | + int s; |
629 | + struct sockaddr_in sin; |
630 | + socklen_t slen; |
631 | + |
632 | + if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { |
633 | + ast_log(LOG_ERROR, "Cannot create socket\n"); |
634 | + return -1; |
635 | + } |
636 | + sin.sin_family = AF_INET; |
637 | + sin.sin_port = htons(5060); |
638 | + sin.sin_addr = *them; |
639 | + if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) { |
640 | + ast_log(LOG_WARNING, "Cannot connect\n"); |
641 | + close(s); |
642 | + return -1; |
643 | + } |
644 | + slen = sizeof(sin); |
645 | + if (getsockname(s, (struct sockaddr *)&sin, &slen)) { |
646 | + ast_log(LOG_WARNING, "Cannot get socket name\n"); |
647 | + close(s); |
648 | + return -1; |
649 | + } |
650 | + close(s); |
651 | + ast_debug(3, "Found IP address for this socket\n"); |
652 | + *us = sin.sin_addr; |
653 | + return 0; |
654 | +} |
655 | + |
656 | +int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr) |
657 | +{ |
658 | + char ourhost[MAXHOSTNAMELEN] = ""; |
659 | + struct ast_hostent ahp; |
660 | + struct hostent *hp; |
661 | + struct in_addr saddr; |
662 | + |
663 | + /* just use the bind address if it is nonzero */ |
664 | + if (ntohl(bindaddr.sin_addr.s_addr)) { |
665 | + memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip)); |
666 | + ast_debug(3, "Attached to given IP address\n"); |
667 | + return 0; |
668 | + } |
669 | + /* try to use our hostname */ |
670 | + if (gethostname(ourhost, sizeof(ourhost) - 1)) { |
671 | + ast_log(LOG_WARNING, "Unable to get hostname\n"); |
672 | + } else { |
673 | + if ((hp = ast_gethostbyname(ourhost, &ahp))) { |
674 | + memcpy(ourip, hp->h_addr, sizeof(*ourip)); |
675 | + ast_debug(3, "Found one IP address based on local hostname %s.\n", ourhost); |
676 | + return 0; |
677 | + } |
678 | + } |
679 | + ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n"); |
680 | + /* A.ROOT-SERVERS.NET. */ |
681 | + if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip)) { |
682 | + return 0; |
683 | + } |
684 | + return get_local_address(ourip); |
685 | +} |
686 | + |
687 | |
688 | === added file '.pc/dnsmgr-A-SRV-handling/main/dnsmgr.c' |
689 | --- .pc/dnsmgr-A-SRV-handling/main/dnsmgr.c 1970-01-01 00:00:00 +0000 |
690 | +++ .pc/dnsmgr-A-SRV-handling/main/dnsmgr.c 2010-07-16 10:16:00 +0000 |
691 | @@ -0,0 +1,439 @@ |
692 | +/* |
693 | + * Asterisk -- An open source telephony toolkit. |
694 | + * |
695 | + * Copyright (C) 2005-2006, Kevin P. Fleming |
696 | + * |
697 | + * Kevin P. Fleming <kpfleming@digium.com> |
698 | + * |
699 | + * See http://www.asterisk.org for more information about |
700 | + * the Asterisk project. Please do not directly contact |
701 | + * any of the maintainers of this project for assistance; |
702 | + * the project provides a web site, mailing lists and IRC |
703 | + * channels for your use. |
704 | + * |
705 | + * This program is free software, distributed under the terms of |
706 | + * the GNU General Public License Version 2. See the LICENSE file |
707 | + * at the top of the source tree. |
708 | + */ |
709 | + |
710 | +/*! \file |
711 | + * |
712 | + * \brief Background DNS update manager |
713 | + * |
714 | + * \author Kevin P. Fleming <kpfleming@digium.com> |
715 | + * |
716 | + * \bug There is a minor race condition. In the event that an IP address |
717 | + * of a dnsmgr managed host changes, there is the potential for the consumer |
718 | + * of that address to access the in_addr data at the same time that the dnsmgr |
719 | + * thread is in the middle of updating it to the new address. |
720 | + */ |
721 | + |
722 | +#include "asterisk.h" |
723 | + |
724 | +ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211580 $") |
725 | + |
726 | +#include "asterisk/_private.h" |
727 | +#include <regex.h> |
728 | +#include <signal.h> |
729 | + |
730 | +#include "asterisk/dnsmgr.h" |
731 | +#include "asterisk/linkedlists.h" |
732 | +#include "asterisk/utils.h" |
733 | +#include "asterisk/config.h" |
734 | +#include "asterisk/sched.h" |
735 | +#include "asterisk/cli.h" |
736 | +#include "asterisk/manager.h" |
737 | +#include "asterisk/acl.h" |
738 | + |
739 | +static struct sched_context *sched; |
740 | +static int refresh_sched = -1; |
741 | +static pthread_t refresh_thread = AST_PTHREADT_NULL; |
742 | + |
743 | +struct ast_dnsmgr_entry { |
744 | + /*! where we will store the resulting IP address and port number */ |
745 | + struct sockaddr_in *result; |
746 | + /*! the last result, used to check if address/port has changed */ |
747 | + struct sockaddr_in last; |
748 | + /*! SRV record to lookup, if provided. Composed of service, protocol, and domain name: _Service._Proto.Name */ |
749 | + char *service; |
750 | + /*! Set to 1 if the entry changes */ |
751 | + unsigned int changed:1; |
752 | + ast_mutex_t lock; |
753 | + AST_RWLIST_ENTRY(ast_dnsmgr_entry) list; |
754 | + /*! just 1 here, but we use calloc to allocate the correct size */ |
755 | + char name[1]; |
756 | +}; |
757 | + |
758 | +static AST_RWLIST_HEAD_STATIC(entry_list, ast_dnsmgr_entry); |
759 | + |
760 | +AST_MUTEX_DEFINE_STATIC(refresh_lock); |
761 | + |
762 | +#define REFRESH_DEFAULT 300 |
763 | + |
764 | +static int enabled; |
765 | +static int refresh_interval; |
766 | + |
767 | +struct refresh_info { |
768 | + struct entry_list *entries; |
769 | + int verbose; |
770 | + unsigned int regex_present:1; |
771 | + regex_t filter; |
772 | +}; |
773 | + |
774 | +static struct refresh_info master_refresh_info = { |
775 | + .entries = &entry_list, |
776 | + .verbose = 0, |
777 | +}; |
778 | + |
779 | +struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct sockaddr_in *result, const char *service) |
780 | +{ |
781 | + struct ast_dnsmgr_entry *entry; |
782 | + int total_size = sizeof(*entry) + strlen(name) + (service ? strlen(service) + 1 : 0); |
783 | + |
784 | + if (!result || ast_strlen_zero(name) || !(entry = ast_calloc(1, total_size))) |
785 | + return NULL; |
786 | + |
787 | + entry->result = result; |
788 | + ast_mutex_init(&entry->lock); |
789 | + strcpy(entry->name, name); |
790 | + memcpy(&entry->last, result, sizeof(entry->last)); |
791 | + if (service) { |
792 | + entry->service = ((char *) entry) + sizeof(*entry) + strlen(name); |
793 | + strcpy(entry->service, service); |
794 | + } |
795 | + |
796 | + AST_RWLIST_WRLOCK(&entry_list); |
797 | + AST_RWLIST_INSERT_HEAD(&entry_list, entry, list); |
798 | + AST_RWLIST_UNLOCK(&entry_list); |
799 | + |
800 | + return entry; |
801 | +} |
802 | + |
803 | +void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry) |
804 | +{ |
805 | + if (!entry) |
806 | + return; |
807 | + |
808 | + AST_RWLIST_WRLOCK(&entry_list); |
809 | + AST_RWLIST_REMOVE(&entry_list, entry, list); |
810 | + AST_RWLIST_UNLOCK(&entry_list); |
811 | + ast_verb(4, "removing dns manager for '%s'\n", entry->name); |
812 | + |
813 | + ast_mutex_destroy(&entry->lock); |
814 | + ast_free(entry); |
815 | +} |
816 | + |
817 | +int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_dnsmgr_entry **dnsmgr, const char *service) |
818 | +{ |
819 | + if (ast_strlen_zero(name) || !result || !dnsmgr) |
820 | + return -1; |
821 | + |
822 | + if (*dnsmgr && !strcasecmp((*dnsmgr)->name, name)) |
823 | + return 0; |
824 | + |
825 | + /* if it's actually an IP address and not a name, |
826 | + there's no need for a managed lookup */ |
827 | + if (inet_aton(name, &result->sin_addr)) |
828 | + return 0; |
829 | + |
830 | + ast_verb(4, "doing dnsmgr_lookup for '%s'\n", name); |
831 | + |
832 | + /* do a lookup now but add a manager so it will automagically get updated in the background */ |
833 | + ast_get_ip_or_srv(result, name, service); |
834 | + |
835 | + /* if dnsmgr is not enable don't bother adding an entry */ |
836 | + if (!enabled) |
837 | + return 0; |
838 | + |
839 | + ast_verb(3, "adding dns manager for '%s'\n", name); |
840 | + *dnsmgr = ast_dnsmgr_get(name, result, service); |
841 | + return !*dnsmgr; |
842 | +} |
843 | + |
844 | +/* |
845 | + * Refresh a dnsmgr entry |
846 | + */ |
847 | +static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose) |
848 | +{ |
849 | + char iabuf[INET_ADDRSTRLEN]; |
850 | + char iabuf2[INET_ADDRSTRLEN]; |
851 | + struct sockaddr_in tmp; |
852 | + int changed = 0; |
853 | + |
854 | + ast_mutex_lock(&entry->lock); |
855 | + if (verbose) |
856 | + ast_verb(3, "refreshing '%s'\n", entry->name); |
857 | + |
858 | + tmp.sin_port = entry->last.sin_port; |
859 | + |
860 | + if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service) && inaddrcmp(&tmp, &entry->last)) { |
861 | + ast_copy_string(iabuf, ast_inet_ntoa(entry->last.sin_addr), sizeof(iabuf)); |
862 | + ast_copy_string(iabuf2, ast_inet_ntoa(tmp.sin_addr), sizeof(iabuf2)); |
863 | + ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s:%d to %s:%d\n", |
864 | + entry->name, iabuf, ntohs(entry->last.sin_port), iabuf2, ntohs(tmp.sin_port)); |
865 | + *entry->result = tmp; |
866 | + entry->last = tmp; |
867 | + changed = entry->changed = 1; |
868 | + } |
869 | + |
870 | + ast_mutex_unlock(&entry->lock); |
871 | + return changed; |
872 | +} |
873 | + |
874 | +int ast_dnsmgr_refresh(struct ast_dnsmgr_entry *entry) |
875 | +{ |
876 | + return dnsmgr_refresh(entry, 0); |
877 | +} |
878 | + |
879 | +/* |
880 | + * Check if dnsmgr entry has changed from since last call to this function |
881 | + */ |
882 | +int ast_dnsmgr_changed(struct ast_dnsmgr_entry *entry) |
883 | +{ |
884 | + int changed; |
885 | + |
886 | + ast_mutex_lock(&entry->lock); |
887 | + |
888 | + changed = entry->changed; |
889 | + entry->changed = 0; |
890 | + |
891 | + ast_mutex_unlock(&entry->lock); |
892 | + |
893 | + return changed; |
894 | +} |
895 | + |
896 | +static void *do_refresh(void *data) |
897 | +{ |
898 | + for (;;) { |
899 | + pthread_testcancel(); |
900 | + usleep((ast_sched_wait(sched)*1000)); |
901 | + pthread_testcancel(); |
902 | + ast_sched_runq(sched); |
903 | + } |
904 | + return NULL; |
905 | +} |
906 | + |
907 | +static int refresh_list(const void *data) |
908 | +{ |
909 | + struct refresh_info *info = (struct refresh_info *)data; |
910 | + struct ast_dnsmgr_entry *entry; |
911 | + |
912 | + /* if a refresh or reload is already in progress, exit now */ |
913 | + if (ast_mutex_trylock(&refresh_lock)) { |
914 | + if (info->verbose) |
915 | + ast_log(LOG_WARNING, "DNS Manager refresh already in progress.\n"); |
916 | + return -1; |
917 | + } |
918 | + |
919 | + ast_verb(3, "Refreshing DNS lookups.\n"); |
920 | + AST_RWLIST_RDLOCK(info->entries); |
921 | + AST_RWLIST_TRAVERSE(info->entries, entry, list) { |
922 | + if (info->regex_present && regexec(&info->filter, entry->name, 0, NULL, 0)) |
923 | + continue; |
924 | + |
925 | + dnsmgr_refresh(entry, info->verbose); |
926 | + } |
927 | + AST_RWLIST_UNLOCK(info->entries); |
928 | + |
929 | + ast_mutex_unlock(&refresh_lock); |
930 | + |
931 | + /* automatically reschedule based on the interval */ |
932 | + return refresh_interval * 1000; |
933 | +} |
934 | + |
935 | +void dnsmgr_start_refresh(void) |
936 | +{ |
937 | + if (refresh_sched > -1) { |
938 | + AST_SCHED_DEL(sched, refresh_sched); |
939 | + refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); |
940 | + } |
941 | +} |
942 | + |
943 | +static int do_reload(int loading); |
944 | + |
945 | +static char *handle_cli_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
946 | +{ |
947 | + switch (cmd) { |
948 | + case CLI_INIT: |
949 | + e->command = "dnsmgr reload"; |
950 | + e->usage = |
951 | + "Usage: dnsmgr reload\n" |
952 | + " Reloads the DNS manager configuration.\n"; |
953 | + return NULL; |
954 | + case CLI_GENERATE: |
955 | + return NULL; |
956 | + } |
957 | + if (a->argc > 2) |
958 | + return CLI_SHOWUSAGE; |
959 | + |
960 | + do_reload(0); |
961 | + return CLI_SUCCESS; |
962 | +} |
963 | + |
964 | +static char *handle_cli_refresh(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
965 | +{ |
966 | + struct refresh_info info = { |
967 | + .entries = &entry_list, |
968 | + .verbose = 1, |
969 | + }; |
970 | + switch (cmd) { |
971 | + case CLI_INIT: |
972 | + e->command = "dnsmgr refresh"; |
973 | + e->usage = |
974 | + "Usage: dnsmgr refresh [pattern]\n" |
975 | + " Peforms an immediate refresh of the managed DNS entries.\n" |
976 | + " Optional regular expression pattern is used to filter the entries to refresh.\n"; |
977 | + return NULL; |
978 | + case CLI_GENERATE: |
979 | + return NULL; |
980 | + } |
981 | + |
982 | + if (!enabled) { |
983 | + ast_cli(a->fd, "DNS Manager is disabled.\n"); |
984 | + return 0; |
985 | + } |
986 | + |
987 | + if (a->argc > 3) { |
988 | + return CLI_SHOWUSAGE; |
989 | + } |
990 | + |
991 | + if (a->argc == 3) { |
992 | + if (regcomp(&info.filter, a->argv[2], REG_EXTENDED | REG_NOSUB)) { |
993 | + return CLI_SHOWUSAGE; |
994 | + } else { |
995 | + info.regex_present = 1; |
996 | + } |
997 | + } |
998 | + |
999 | + refresh_list(&info); |
1000 | + |
1001 | + if (info.regex_present) { |
1002 | + regfree(&info.filter); |
1003 | + } |
1004 | + |
1005 | + return CLI_SUCCESS; |
1006 | +} |
1007 | + |
1008 | +static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
1009 | +{ |
1010 | + int count = 0; |
1011 | + struct ast_dnsmgr_entry *entry; |
1012 | + switch (cmd) { |
1013 | + case CLI_INIT: |
1014 | + e->command = "dnsmgr status"; |
1015 | + e->usage = |
1016 | + "Usage: dnsmgr status\n" |
1017 | + " Displays the DNS manager status.\n"; |
1018 | + return NULL; |
1019 | + case CLI_GENERATE: |
1020 | + return NULL; |
1021 | + } |
1022 | + |
1023 | + if (a->argc > 2) |
1024 | + return CLI_SHOWUSAGE; |
1025 | + |
1026 | + ast_cli(a->fd, "DNS Manager: %s\n", enabled ? "enabled" : "disabled"); |
1027 | + ast_cli(a->fd, "Refresh Interval: %d seconds\n", refresh_interval); |
1028 | + AST_RWLIST_RDLOCK(&entry_list); |
1029 | + AST_RWLIST_TRAVERSE(&entry_list, entry, list) |
1030 | + count++; |
1031 | + AST_RWLIST_UNLOCK(&entry_list); |
1032 | + ast_cli(a->fd, "Number of entries: %d\n", count); |
1033 | + |
1034 | + return CLI_SUCCESS; |
1035 | +} |
1036 | + |
1037 | +static struct ast_cli_entry cli_reload = AST_CLI_DEFINE(handle_cli_reload, "Reloads the DNS manager configuration"); |
1038 | +static struct ast_cli_entry cli_refresh = AST_CLI_DEFINE(handle_cli_refresh, "Performs an immediate refresh"); |
1039 | +static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the DNS manager status"); |
1040 | + |
1041 | +int dnsmgr_init(void) |
1042 | +{ |
1043 | + if (!(sched = sched_context_create())) { |
1044 | + ast_log(LOG_ERROR, "Unable to create schedule context.\n"); |
1045 | + return -1; |
1046 | + } |
1047 | + ast_cli_register(&cli_reload); |
1048 | + ast_cli_register(&cli_status); |
1049 | + ast_cli_register(&cli_refresh); |
1050 | + return do_reload(1); |
1051 | +} |
1052 | + |
1053 | +int dnsmgr_reload(void) |
1054 | +{ |
1055 | + return do_reload(0); |
1056 | +} |
1057 | + |
1058 | +static int do_reload(int loading) |
1059 | +{ |
1060 | + struct ast_config *config; |
1061 | + struct ast_flags config_flags = { loading ? 0 : CONFIG_FLAG_FILEUNCHANGED }; |
1062 | + const char *interval_value; |
1063 | + const char *enabled_value; |
1064 | + int interval; |
1065 | + int was_enabled; |
1066 | + int res = -1; |
1067 | + |
1068 | + config = ast_config_load2("dnsmgr.conf", "dnsmgr", config_flags); |
1069 | + if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEUNCHANGED || config == CONFIG_STATUS_FILEINVALID) { |
1070 | + return 0; |
1071 | + } |
1072 | + |
1073 | + /* ensure that no refresh cycles run while the reload is in progress */ |
1074 | + ast_mutex_lock(&refresh_lock); |
1075 | + |
1076 | + /* reset defaults in preparation for reading config file */ |
1077 | + refresh_interval = REFRESH_DEFAULT; |
1078 | + was_enabled = enabled; |
1079 | + enabled = 0; |
1080 | + |
1081 | + AST_SCHED_DEL(sched, refresh_sched); |
1082 | + |
1083 | + if (config) { |
1084 | + if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { |
1085 | + enabled = ast_true(enabled_value); |
1086 | + } |
1087 | + if ((interval_value = ast_variable_retrieve(config, "general", "refreshinterval"))) { |
1088 | + if (sscanf(interval_value, "%30d", &interval) < 1) |
1089 | + ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", interval_value); |
1090 | + else if (interval < 0) |
1091 | + ast_log(LOG_WARNING, "Invalid refresh interval '%d' specified, using default\n", interval); |
1092 | + else |
1093 | + refresh_interval = interval; |
1094 | + } |
1095 | + ast_config_destroy(config); |
1096 | + } |
1097 | + |
1098 | + if (enabled && refresh_interval) |
1099 | + ast_log(LOG_NOTICE, "Managed DNS entries will be refreshed every %d seconds.\n", refresh_interval); |
1100 | + |
1101 | + /* if this reload enabled the manager, create the background thread |
1102 | + if it does not exist */ |
1103 | + if (enabled) { |
1104 | + if (!was_enabled && (refresh_thread == AST_PTHREADT_NULL)) { |
1105 | + if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) { |
1106 | + ast_log(LOG_ERROR, "Unable to start refresh thread.\n"); |
1107 | + } |
1108 | + } |
1109 | + /* make a background refresh happen right away */ |
1110 | + refresh_sched = ast_sched_add_variable(sched, 100, refresh_list, &master_refresh_info, 1); |
1111 | + res = 0; |
1112 | + } |
1113 | + /* if this reload disabled the manager and there is a background thread, |
1114 | + kill it */ |
1115 | + else if (!enabled && was_enabled && (refresh_thread != AST_PTHREADT_NULL)) { |
1116 | + /* wake up the thread so it will exit */ |
1117 | + pthread_cancel(refresh_thread); |
1118 | + pthread_kill(refresh_thread, SIGURG); |
1119 | + pthread_join(refresh_thread, NULL); |
1120 | + refresh_thread = AST_PTHREADT_NULL; |
1121 | + res = 0; |
1122 | + } |
1123 | + else |
1124 | + res = 0; |
1125 | + |
1126 | + ast_mutex_unlock(&refresh_lock); |
1127 | + manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: DNSmgr\r\nStatus: %s\r/nMessage: DNSmgr reload Requested\r\n", enabled ? "Enabled" : "Disabled"); |
1128 | + |
1129 | + return res; |
1130 | +} |
1131 | |
1132 | === added file '.pc/h323-fix-makefile/.timestamp' |
1133 | === added file '.pc/h323-no-deps-on-asterisk/.timestamp' |
1134 | === added file '.pc/h323-workaround-openh323-segfault/.timestamp' |
1135 | === added file '.pc/hack-multiple-app-voicemail/.timestamp' |
1136 | === added file '.pc/make-clean-fixes/.timestamp' |
1137 | === added file '.pc/safe_asterisk-config/.timestamp' |
1138 | === added file '.pc/safe_asterisk-nobg/.timestamp' |
1139 | === added file '.pc/sound_files/.timestamp' |
1140 | === modified file 'debian/changelog' |
1141 | --- debian/changelog 2010-04-13 16:27:27 +0000 |
1142 | +++ debian/changelog 2010-07-16 10:16:00 +0000 |
1143 | @@ -1,3 +1,11 @@ |
1144 | +asterisk (1:1.6.2.5-0ubuntu1.1) lucid-proposed; urgency=low |
1145 | + |
1146 | + * debian/patches/dnsmgr-A-SRV-handling: Resolve handling of A and SRV |
1147 | + record changes and problem with multiple A/SRV records returned. |
1148 | + Patch based on Asterisk project's upstream patch. (LP: #605358) |
1149 | + |
1150 | + -- Dave Walker (Daviey) <DaveWalker@ubuntu.com> Wed, 14 Jul 2010 11:40:55 +0100 |
1151 | + |
1152 | asterisk (1:1.6.2.5-0ubuntu1) lucid; urgency=low |
1153 | |
1154 | * New upstream bugfix release (1.6.2.5) |
1155 | |
1156 | === added file 'debian/patches/dnsmgr-A-SRV-handling' |
1157 | --- debian/patches/dnsmgr-A-SRV-handling 1970-01-01 00:00:00 +0000 |
1158 | +++ debian/patches/dnsmgr-A-SRV-handling 2010-07-16 10:16:00 +0000 |
1159 | @@ -0,0 +1,132 @@ |
1160 | +Description: Resolve handling of A and SRV record changes and problem with multiple A/SRV records returned. |
1161 | +Origin: upstream, https://issues.asterisk.org/file_download.php?file_id=25360&type=bug |
1162 | +Bug: https://issues.asterisk.org/view.php?id=15827 |
1163 | +Bug-Ubuntu: https://launchpad.net/bugs/605358 |
1164 | +Last-Update: 2010-07-14 |
1165 | +--- a/include/asterisk/dnsmgr.h |
1166 | ++++ b/include/asterisk/dnsmgr.h |
1167 | +@@ -42,12 +42,12 @@ |
1168 | + * |
1169 | + * \param name the hostname |
1170 | + * \param result where the DNS manager should store the IP address as it refreshes it. |
1171 | +- * it. |
1172 | ++ * \param service SRV prefix (optional, set to NULL to disable SRV) |
1173 | + * |
1174 | + * This function allocates a new DNS manager entry object, and fills it with the |
1175 | + * provided hostname and IP address. This function does not force an initial lookup |
1176 | +- * of the IP address. So, generally, this should be used when the initial address |
1177 | +- * is already known. |
1178 | ++ * of the IP address. So, this should be used when the initial address |
1179 | ++ * is already known and stored in result. |
1180 | + * |
1181 | + * \return a DNS manager entry |
1182 | + * \version 1.6.1 result changed from struct in_addr to struct sockaddr_in to store port number |
1183 | +@@ -69,6 +69,7 @@ |
1184 | + * \param name the hostname |
1185 | + * \param result where to store the IP address as the DNS manager refreshes it |
1186 | + * \param dnsmgr Where to store the allocate DNS manager entry |
1187 | ++ * \param service SRV prefix (optional, set to NULL to disable SRV) |
1188 | + * |
1189 | + * This function allocates a new DNS manager entry object, and fills it with |
1190 | + * the provided hostname and IP address. This function _does_ force an initial |
1191 | +--- a/main/acl.c |
1192 | ++++ b/main/acl.c |
1193 | +@@ -387,6 +387,7 @@ |
1194 | + } |
1195 | + } |
1196 | + if ((hp = ast_gethostbyname(value, &ahp))) { |
1197 | ++ sin->sin_family = hp->h_addrtype; |
1198 | + memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); |
1199 | + } else { |
1200 | + ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value); |
1201 | +--- a/main/dnsmgr.c |
1202 | ++++ b/main/dnsmgr.c |
1203 | +@@ -52,8 +52,6 @@ |
1204 | + struct ast_dnsmgr_entry { |
1205 | + /*! where we will store the resulting IP address and port number */ |
1206 | + struct sockaddr_in *result; |
1207 | +- /*! the last result, used to check if address/port has changed */ |
1208 | +- struct sockaddr_in last; |
1209 | + /*! SRV record to lookup, if provided. Composed of service, protocol, and domain name: _Service._Proto.Name */ |
1210 | + char *service; |
1211 | + /*! Set to 1 if the entry changes */ |
1212 | +@@ -85,6 +83,9 @@ |
1213 | + .verbose = 0, |
1214 | + }; |
1215 | + |
1216 | ++/* |
1217 | ++ * Allocate a new DNS manager entry |
1218 | ++ */ |
1219 | + struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct sockaddr_in *result, const char *service) |
1220 | + { |
1221 | + struct ast_dnsmgr_entry *entry; |
1222 | +@@ -96,7 +97,6 @@ |
1223 | + entry->result = result; |
1224 | + ast_mutex_init(&entry->lock); |
1225 | + strcpy(entry->name, name); |
1226 | +- memcpy(&entry->last, result, sizeof(entry->last)); |
1227 | + if (service) { |
1228 | + entry->service = ((char *) entry) + sizeof(*entry) + strlen(name); |
1229 | + strcpy(entry->service, service); |
1230 | +@@ -109,6 +109,9 @@ |
1231 | + return entry; |
1232 | + } |
1233 | + |
1234 | ++/* |
1235 | ++ * Free a DNS manager entry |
1236 | ++ */ |
1237 | + void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry) |
1238 | + { |
1239 | + if (!entry) |
1240 | +@@ -123,6 +126,9 @@ |
1241 | + ast_free(entry); |
1242 | + } |
1243 | + |
1244 | ++/* |
1245 | ++ * Allocate a new DNS manager entry and perform the initial lookup before returning |
1246 | ++ */ |
1247 | + int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_dnsmgr_entry **dnsmgr, const char *service) |
1248 | + { |
1249 | + if (ast_strlen_zero(name) || !result || !dnsmgr) |
1250 | +@@ -133,8 +139,10 @@ |
1251 | + |
1252 | + /* if it's actually an IP address and not a name, |
1253 | + there's no need for a managed lookup */ |
1254 | +- if (inet_aton(name, &result->sin_addr)) |
1255 | ++ if (inet_aton(name, &result->sin_addr)) { |
1256 | ++ result->sin_family = AF_INET; |
1257 | + return 0; |
1258 | ++ } |
1259 | + |
1260 | + ast_verb(4, "doing dnsmgr_lookup for '%s'\n", name); |
1261 | + |
1262 | +@@ -151,7 +159,7 @@ |
1263 | + } |
1264 | + |
1265 | + /* |
1266 | +- * Refresh a dnsmgr entry |
1267 | ++ * Force a refresh of a dnsmgr entry |
1268 | + */ |
1269 | + static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose) |
1270 | + { |
1271 | +@@ -164,15 +172,15 @@ |
1272 | + if (verbose) |
1273 | + ast_verb(3, "refreshing '%s'\n", entry->name); |
1274 | + |
1275 | +- tmp.sin_port = entry->last.sin_port; |
1276 | ++ memset(&tmp, 0, sizeof(tmp)); |
1277 | ++ tmp.sin_port = entry->result->sin_port; |
1278 | + |
1279 | +- if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service) && inaddrcmp(&tmp, &entry->last)) { |
1280 | +- ast_copy_string(iabuf, ast_inet_ntoa(entry->last.sin_addr), sizeof(iabuf)); |
1281 | ++ if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service) && inaddrcmp(&tmp, entry->result)) { |
1282 | ++ ast_copy_string(iabuf, ast_inet_ntoa(entry->result->sin_addr), sizeof(iabuf)); |
1283 | + ast_copy_string(iabuf2, ast_inet_ntoa(tmp.sin_addr), sizeof(iabuf2)); |
1284 | + ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s:%d to %s:%d\n", |
1285 | +- entry->name, iabuf, ntohs(entry->last.sin_port), iabuf2, ntohs(tmp.sin_port)); |
1286 | ++ entry->name, iabuf, ntohs(entry->result->sin_port), iabuf2, ntohs(tmp.sin_port)); |
1287 | + *entry->result = tmp; |
1288 | +- entry->last = tmp; |
1289 | + changed = entry->changed = 1; |
1290 | + } |
1291 | + |
1292 | |
1293 | === modified file 'debian/patches/series' |
1294 | --- debian/patches/series 2010-02-16 14:08:54 +0000 |
1295 | +++ debian/patches/series 2010-07-16 10:16:00 +0000 |
1296 | @@ -17,3 +17,4 @@ |
1297 | dahdi_ptmp_nt |
1298 | dahdi_pri_debug_spannums |
1299 | sound_files |
1300 | +dnsmgr-A-SRV-handling |
1301 | |
1302 | === modified file 'include/asterisk/dnsmgr.h' |
1303 | --- include/asterisk/dnsmgr.h 2009-03-29 22:21:47 +0000 |
1304 | +++ include/asterisk/dnsmgr.h 2010-07-16 10:16:00 +0000 |
1305 | @@ -42,12 +42,12 @@ |
1306 | * |
1307 | * \param name the hostname |
1308 | * \param result where the DNS manager should store the IP address as it refreshes it. |
1309 | - * it. |
1310 | + * \param service SRV prefix (optional, set to NULL to disable SRV) |
1311 | * |
1312 | * This function allocates a new DNS manager entry object, and fills it with the |
1313 | * provided hostname and IP address. This function does not force an initial lookup |
1314 | - * of the IP address. So, generally, this should be used when the initial address |
1315 | - * is already known. |
1316 | + * of the IP address. So, this should be used when the initial address |
1317 | + * is already known and stored in result. |
1318 | * |
1319 | * \return a DNS manager entry |
1320 | * \version 1.6.1 result changed from struct in_addr to struct sockaddr_in to store port number |
1321 | @@ -69,6 +69,7 @@ |
1322 | * \param name the hostname |
1323 | * \param result where to store the IP address as the DNS manager refreshes it |
1324 | * \param dnsmgr Where to store the allocate DNS manager entry |
1325 | + * \param service SRV prefix (optional, set to NULL to disable SRV) |
1326 | * |
1327 | * This function allocates a new DNS manager entry object, and fills it with |
1328 | * the provided hostname and IP address. This function _does_ force an initial |
1329 | |
1330 | === modified file 'main/acl.c' |
1331 | --- main/acl.c 2010-04-13 16:27:27 +0000 |
1332 | +++ main/acl.c 2010-07-16 10:16:00 +0000 |
1333 | @@ -387,6 +387,7 @@ |
1334 | } |
1335 | } |
1336 | if ((hp = ast_gethostbyname(value, &ahp))) { |
1337 | + sin->sin_family = hp->h_addrtype; |
1338 | memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); |
1339 | } else { |
1340 | ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value); |
1341 | |
1342 | === modified file 'main/dnsmgr.c' |
1343 | --- main/dnsmgr.c 2010-02-16 14:08:54 +0000 |
1344 | +++ main/dnsmgr.c 2010-07-16 10:16:00 +0000 |
1345 | @@ -52,8 +52,6 @@ |
1346 | struct ast_dnsmgr_entry { |
1347 | /*! where we will store the resulting IP address and port number */ |
1348 | struct sockaddr_in *result; |
1349 | - /*! the last result, used to check if address/port has changed */ |
1350 | - struct sockaddr_in last; |
1351 | /*! SRV record to lookup, if provided. Composed of service, protocol, and domain name: _Service._Proto.Name */ |
1352 | char *service; |
1353 | /*! Set to 1 if the entry changes */ |
1354 | @@ -85,6 +83,9 @@ |
1355 | .verbose = 0, |
1356 | }; |
1357 | |
1358 | +/* |
1359 | + * Allocate a new DNS manager entry |
1360 | + */ |
1361 | struct ast_dnsmgr_entry *ast_dnsmgr_get(const char *name, struct sockaddr_in *result, const char *service) |
1362 | { |
1363 | struct ast_dnsmgr_entry *entry; |
1364 | @@ -96,7 +97,6 @@ |
1365 | entry->result = result; |
1366 | ast_mutex_init(&entry->lock); |
1367 | strcpy(entry->name, name); |
1368 | - memcpy(&entry->last, result, sizeof(entry->last)); |
1369 | if (service) { |
1370 | entry->service = ((char *) entry) + sizeof(*entry) + strlen(name); |
1371 | strcpy(entry->service, service); |
1372 | @@ -109,6 +109,9 @@ |
1373 | return entry; |
1374 | } |
1375 | |
1376 | +/* |
1377 | + * Free a DNS manager entry |
1378 | + */ |
1379 | void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry) |
1380 | { |
1381 | if (!entry) |
1382 | @@ -123,6 +126,9 @@ |
1383 | ast_free(entry); |
1384 | } |
1385 | |
1386 | +/* |
1387 | + * Allocate a new DNS manager entry and perform the initial lookup before returning |
1388 | + */ |
1389 | int ast_dnsmgr_lookup(const char *name, struct sockaddr_in *result, struct ast_dnsmgr_entry **dnsmgr, const char *service) |
1390 | { |
1391 | if (ast_strlen_zero(name) || !result || !dnsmgr) |
1392 | @@ -133,8 +139,10 @@ |
1393 | |
1394 | /* if it's actually an IP address and not a name, |
1395 | there's no need for a managed lookup */ |
1396 | - if (inet_aton(name, &result->sin_addr)) |
1397 | + if (inet_aton(name, &result->sin_addr)) { |
1398 | + result->sin_family = AF_INET; |
1399 | return 0; |
1400 | + } |
1401 | |
1402 | ast_verb(4, "doing dnsmgr_lookup for '%s'\n", name); |
1403 | |
1404 | @@ -151,7 +159,7 @@ |
1405 | } |
1406 | |
1407 | /* |
1408 | - * Refresh a dnsmgr entry |
1409 | + * Force a refresh of a dnsmgr entry |
1410 | */ |
1411 | static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose) |
1412 | { |
1413 | @@ -164,15 +172,15 @@ |
1414 | if (verbose) |
1415 | ast_verb(3, "refreshing '%s'\n", entry->name); |
1416 | |
1417 | - tmp.sin_port = entry->last.sin_port; |
1418 | + memset(&tmp, 0, sizeof(tmp)); |
1419 | + tmp.sin_port = entry->result->sin_port; |
1420 | |
1421 | - if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service) && inaddrcmp(&tmp, &entry->last)) { |
1422 | - ast_copy_string(iabuf, ast_inet_ntoa(entry->last.sin_addr), sizeof(iabuf)); |
1423 | + if (!ast_get_ip_or_srv(&tmp, entry->name, entry->service) && inaddrcmp(&tmp, entry->result)) { |
1424 | + ast_copy_string(iabuf, ast_inet_ntoa(entry->result->sin_addr), sizeof(iabuf)); |
1425 | ast_copy_string(iabuf2, ast_inet_ntoa(tmp.sin_addr), sizeof(iabuf2)); |
1426 | ast_log(LOG_NOTICE, "dnssrv: host '%s' changed from %s:%d to %s:%d\n", |
1427 | - entry->name, iabuf, ntohs(entry->last.sin_port), iabuf2, ntohs(tmp.sin_port)); |
1428 | + entry->name, iabuf, ntohs(entry->result->sin_port), iabuf2, ntohs(tmp.sin_port)); |
1429 | *entry->result = tmp; |
1430 | - entry->last = tmp; |
1431 | changed = entry->changed = 1; |
1432 | } |
1433 |
Merged, uploaded etc - marking as such.