summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2015-11-18 01:56:03 +0900
committerLorenzo Colitti <lorenzo@google.com>2015-11-18 02:00:43 +0900
commit14d6844fd311cac51fdf5f3e0d800927dbe651bc (patch)
treed91d5e87bc2f424cb23645353ca4d1e43d201530
parent46e72b15acc9965d180a4136dc81335fb0c166d9 (diff)
downloadandroid_external_dnsmasq-14d6844fd311cac51fdf5f3e0d800927dbe651bc.tar.gz
android_external_dnsmasq-14d6844fd311cac51fdf5f3e0d800927dbe651bc.tar.bz2
android_external_dnsmasq-14d6844fd311cac51fdf5f3e0d800927dbe651bc.zip
Support freeing multiple wildcard listeners.
Currently, close_bound_listener only frees one listener. This is correct for listeners that are bound to IP addresses, but it is not correct for wildcard listeners, because if IPv6 is enabled there is one wildcard listener per address family. Bug: 9580643 Change-Id: I772ff967e8a2681878f1d7c1f6a114ffdc20dfe7
-rwxr-xr-xsrc/network.c66
1 files changed, 43 insertions, 23 deletions
diff --git a/src/network.c b/src/network.c
index 676701c..a71570b 100755
--- a/src/network.c
+++ b/src/network.c
@@ -508,34 +508,21 @@ void fixup_possible_existing_listener(struct irec *new_iface) {
}
/**
- * Close the sockets listening on the given interface
+ * Closes the sockets of the specified listener, deletes it from the list, and frees it.
*
- * This new function is needed as we're dynamically changing the interfaces
- * we listen on. Before they'd be opened once in create_bound_listeners and stay
- * until we exited. Now, if an interface moves off the to-listen list we need to
- * close out the listeners and keep trucking.
- *
- * interface - input of the interface details to listen on
*/
-int close_bound_listener(struct irec *interface)
+int delete_listener(struct listener **l)
{
- /* find the listener */
- struct listener **l, *listener;
- for (l = &(daemon->listeners); *l; l = &((*l)->next)) {
- struct irec *listener_iface = (*l)->iface;
- if (listener_iface && interface) {
- if (sockaddr_isequal(&listener_iface->addr, &interface->addr)) {
- break;
- }
- } else {
- if (interface == NULL && listener_iface == NULL) {
- break;
- }
- }
- }
- listener = *l;
+ struct listener *listener = *l;
if (listener == NULL) return 0;
+ if (listener->iface) {
+ int port = prettyprint_addr(&listener->iface->addr, daemon->namebuff);
+ my_syslog(LOG_INFO, _("Closing listener [%s]:%d"), daemon->namebuff, port);
+ } else {
+ my_syslog(LOG_INFO, _("Closing wildcard listener family=%d"), listener->family);
+ }
+
if (listener->tftpfd != -1)
{
close(listener->tftpfd);
@@ -555,6 +542,39 @@ int close_bound_listener(struct irec *interface)
free(listener);
return -1;
}
+
+/**
+ * Close the sockets listening on the given interface
+ *
+ * This new function is needed as we're dynamically changing the interfaces
+ * we listen on. Before they'd be opened once in create_bound_listeners and stay
+ * until we exited. Now, if an interface moves off the to-listen list we need to
+ * close out the listeners and keep trucking.
+ *
+ * interface - input of the interface details to listen on
+ */
+int close_bound_listener(struct irec *iface)
+{
+ /* find the listener */
+ int ret = 0;
+ struct listener **l = &daemon->listeners;
+ while (*l) {
+ struct irec *listener_iface = (*l)->iface;
+ struct listener **next = &((*l)->next);
+ if (iface && listener_iface && sockaddr_isequal(&listener_iface->addr, &iface->addr)) {
+ // Listener bound to an IP address. There can be only one of these.
+ ret = delete_listener(l);
+ break;
+ }
+ if (iface == NULL && listener_iface == NULL) {
+ // Wildcard listener. There is one of these per address family.
+ ret = delete_listener(l);
+ continue;
+ }
+ l = next;
+ }
+ return ret;
+}
#endif /* __ANDROID__ */
struct listener *create_bound_listeners(void)