diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2015-11-18 01:56:03 +0900 |
---|---|---|
committer | Lorenzo Colitti <lorenzo@google.com> | 2015-11-18 02:00:43 +0900 |
commit | 14d6844fd311cac51fdf5f3e0d800927dbe651bc (patch) | |
tree | d91d5e87bc2f424cb23645353ca4d1e43d201530 | |
parent | 46e72b15acc9965d180a4136dc81335fb0c166d9 (diff) | |
download | android_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-x | src/network.c | 66 |
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) |