From d68c2ca2b7896d6127f9b32d402f299e0b9cf593 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 18 Feb 2014 22:30:30 +0000 Subject: [PATCH] Cleanup of server reading code, preparation, for dynamic reading from files. --- src/dbus.c | 132 +++++-------------------------------- src/dnsmasq.h | 7 ++ src/network.c | 175 ++++++++++++++++++++++++++++++++------------------ src/option.c | 7 ++ 4 files changed, 145 insertions(+), 176 deletions(-) diff --git a/src/dbus.c b/src/dbus.c index 5e9fdc9..eb0ce6b 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -108,108 +108,6 @@ static void remove_watch(DBusWatch *watch, void *data) w = data; /* no warning */ } -static void add_update_server(union mysockaddr *addr, - union mysockaddr *source_addr, - const char *interface, - const char *domain) -{ - struct server *serv; - - /* See if there is a suitable candidate, and unmark */ - for (serv = daemon->servers; serv; serv = serv->next) - if ((serv->flags & SERV_FROM_DBUS) && - (serv->flags & SERV_MARK)) - { - if (domain) - { - if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain)) - continue; - } - else - { - if (serv->flags & SERV_HAS_DOMAIN) - continue; - } - - serv->flags &= ~SERV_MARK; - - break; - } - - if (!serv && (serv = whine_malloc(sizeof (struct server)))) - { - /* Not found, create a new one. */ - memset(serv, 0, sizeof(struct server)); - - if (domain && !(serv->domain = whine_malloc(strlen(domain)+1))) - { - free(serv); - serv = NULL; - } - else - { - serv->next = daemon->servers; - daemon->servers = serv; - serv->flags = SERV_FROM_DBUS; - if (domain) - { - strcpy(serv->domain, domain); - serv->flags |= SERV_HAS_DOMAIN; - } - } - } - - if (serv) - { - if (interface) - strcpy(serv->interface, interface); - else - serv->interface[0] = 0; - - if (source_addr->in.sin_family == AF_INET && - addr->in.sin_addr.s_addr == 0 && - serv->domain) - serv->flags |= SERV_NO_ADDR; - else - { - serv->flags &= ~SERV_NO_ADDR; - serv->addr = *addr; - serv->source_addr = *source_addr; - } - } -} - -static void mark_dbus(void) -{ - struct server *serv; - - /* mark everything from DBUS */ - for (serv = daemon->servers; serv; serv = serv->next) - if (serv->flags & SERV_FROM_DBUS) - serv->flags |= SERV_MARK; -} - -static void cleanup_dbus() -{ - struct server *serv, *tmp, **up; - - /* unlink and free anything still marked. */ - for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp) - { - tmp = serv->next; - if (serv->flags & SERV_MARK) - { - server_gone(serv); - *up = serv->next; - if (serv->domain) - free(serv->domain); - free(serv); - } - else - up = &serv->next; - } -} - static void dbus_read_servers(DBusMessage *message) { DBusMessageIter iter; @@ -218,8 +116,8 @@ static void dbus_read_servers(DBusMessage *message) dbus_message_iter_init(message, &iter); - mark_dbus(); - + mark_servers(SERV_FROM_DBUS); + while (1) { int skip = 0; @@ -289,13 +187,13 @@ static void dbus_read_servers(DBusMessage *message) domain = NULL; if (!skip) - add_update_server(&addr, &source_addr, NULL, domain); + add_update_server(SERV_FROM_DBUS, &addr, &source_addr, NULL, domain); } while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING); } /* unlink and free anything still marked. */ - cleanup_dbus(); + cleanup_servers(); } static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings) @@ -319,7 +217,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings) strings ? "Expected array of string" : "Expected array of string arrays"); } - mark_dbus(); + mark_servers(SERV_FROM_DBUS); /* array_iter points to each "as" element in the outer array */ dbus_message_iter_recurse(&iter, &array_iter); @@ -327,6 +225,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings) { const char *str = NULL; union mysockaddr addr, source_addr; + int flags; char interface[IF_NAMESIZE]; char *str_addr, *str_domain = NULL; @@ -416,16 +315,19 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings) memset(&interface, 0, sizeof(interface)); /* parse the IP address */ - addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, NULL); - - if (addr_err) - { + if ((addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, &flags))) + { error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS, "Invalid IP address '%s': %s", str, addr_err); break; } - + + /* 0.0.0.0 for server address == NULL, for Dbus */ + if (addr.in.sin_family == AF_INET && + addr.in.sin_addr.s_addr == 0) + flags |= SERV_NO_ADDR; + if (strings) { char *p; @@ -439,7 +341,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings) else p = NULL; - add_update_server(&addr, &source_addr, interface, str_domain); + add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain); } while ((str_domain = p)); } else @@ -454,7 +356,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings) dbus_message_iter_get_basic(&string_iter, &str); dbus_message_iter_next (&string_iter); - add_update_server(&addr, &source_addr, interface, str); + add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str); } while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING); } @@ -462,7 +364,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings) dbus_message_iter_next(&array_iter); } - cleanup_dbus(); + cleanup_servers(); if (dup) free(dup); diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 29ae295..59d9e9e 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -1153,6 +1153,13 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp); int random_sock(int family); void pre_allocate_sfds(void); int reload_servers(char *fname); +void mark_servers(int flag); +void cleanup_servers(void); +void add_update_server(int flags, + union mysockaddr *addr, + union mysockaddr *source_addr, + const char *interface, + const char *domain); void check_servers(void); int enumerate_interfaces(int reset); void create_wildcard_listeners(void); diff --git a/src/network.c b/src/network.c index f068454..183dc04 100644 --- a/src/network.c +++ b/src/network.c @@ -1254,18 +1254,120 @@ void pre_allocate_sfds(void) } } +void mark_servers(int flag) +{ + struct server *serv; + + /* mark everything with argument flag */ + for (serv = daemon->servers; serv; serv = serv->next) + if (serv->flags & flag) + serv->flags |= SERV_MARK; +} + +void cleanup_servers(void) +{ + struct server *serv, *tmp, **up; + + /* unlink and free anything still marked. */ + for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp) + { + tmp = serv->next; + if (serv->flags & SERV_MARK) + { + server_gone(serv); + *up = serv->next; + if (serv->domain) + free(serv->domain); + free(serv); + } + else + up = &serv->next; + } +} + +void add_update_server(int flags, + union mysockaddr *addr, + union mysockaddr *source_addr, + const char *interface, + const char *domain) +{ + struct server *serv; + + /* See if there is a suitable candidate, and unmark */ + for (serv = daemon->servers; serv; serv = serv->next) + if (serv->flags & SERV_MARK) + { + if (domain) + { + if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain)) + continue; + } + else + { + if (serv->flags & SERV_HAS_DOMAIN) + continue; + } + + serv->flags &= ~SERV_MARK; + + break; + } + + if (!serv && (serv = whine_malloc(sizeof (struct server)))) + { + /* Not found, create a new one. */ + memset(serv, 0, sizeof(struct server)); + + if (domain && !(serv->domain = whine_malloc(strlen(domain)+1))) + { + free(serv); + serv = NULL; + } + else + { + struct server *s; + /* Add to the end of the chain, for order */ + if (!daemon->servers) + daemon->servers = serv; + else + { + for (s = daemon->servers; s->next; s = s->next); + s->next = serv; + } + if (domain) + strcpy(serv->domain, domain); + } + } + + if (serv) + { + serv->flags = flags; + serv->queries = serv->failed_queries = 0; + + if (domain) + serv->flags |= SERV_HAS_DOMAIN; + + if (interface) + strcpy(serv->interface, interface); + else + serv->interface[0] = 0; + + serv->addr = *addr; + serv->source_addr = *source_addr; + } +} void check_servers(void) { struct irec *iface; - struct server *new, *tmp, *ret = NULL; + struct server *new, *tmp, **up; int port = 0; /* interface may be new since startup */ if (!option_bool(OPT_NOWILD)) enumerate_interfaces(0); - for (new = daemon->servers; new; new = tmp) + for (up = &daemon->servers, new = daemon->servers; new; new = tmp) { tmp = new->next; @@ -1277,6 +1379,7 @@ void check_servers(void) if (new->addr.sa.sa_family == AF_INET && new->addr.in.sin_addr.s_addr == 0) { + *up = tmp; free(new); continue; } @@ -1287,6 +1390,7 @@ void check_servers(void) if (iface) { my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff); + *up = tmp; free(new); continue; } @@ -1299,15 +1403,12 @@ void check_servers(void) my_syslog(LOG_WARNING, _("ignoring nameserver %s - cannot make/bind socket: %s"), daemon->namebuff, strerror(errno)); + *up = tmp; free(new); continue; } } - /* reverse order - gets it right. */ - new->next = ret; - ret = new; - if (!(new->flags & SERV_NO_REBIND)) { if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV)) @@ -1332,9 +1433,9 @@ void check_servers(void) else my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); } + + up = &new->next; } - - daemon->servers = ret; } /* Return zero if no servers found, in that case we keep polling. @@ -1343,9 +1444,6 @@ int reload_servers(char *fname) { FILE *f; char *line; - struct server *old_servers = NULL; - struct server *new_servers = NULL; - struct server *serv; int gotone = 0; /* buff happens to be MAXDNAME long... */ @@ -1354,28 +1452,9 @@ int reload_servers(char *fname) my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno)); return 0; } - - /* move old servers to free list - we can reuse the memory - and not risk malloc if there are the same or fewer new servers. - Servers which were specced on the command line go to the new list. */ - for (serv = daemon->servers; serv;) - { - struct server *tmp = serv->next; - if (serv->flags & SERV_FROM_RESOLV) - { - serv->next = old_servers; - old_servers = serv; - /* forward table rules reference servers, so have to blow them away */ - server_gone(serv); - } - else - { - serv->next = new_servers; - new_servers = serv; - } - serv = tmp; - } - + + mark_servers(SERV_FROM_RESOLV); + while ((line = fgets(daemon->namebuff, MAXDNAME, f))) { union mysockaddr addr, source_addr; @@ -1434,38 +1513,12 @@ int reload_servers(char *fname) continue; #endif - if (old_servers) - { - serv = old_servers; - old_servers = old_servers->next; - } - else if (!(serv = whine_malloc(sizeof (struct server)))) - continue; - - /* this list is reverse ordered: - it gets reversed again in check_servers */ - serv->next = new_servers; - new_servers = serv; - serv->addr = addr; - serv->source_addr = source_addr; - serv->domain = NULL; - serv->interface[0] = 0; - serv->sfd = NULL; - serv->flags = SERV_FROM_RESOLV; - serv->queries = serv->failed_queries = 0; + add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL); gotone = 1; } - /* Free any memory not used. */ - while (old_servers) - { - struct server *tmp = old_servers->next; - free(old_servers); - old_servers = tmp; - } - - daemon->servers = new_servers; fclose(f); + cleanup_servers(); return gotone; } diff --git a/src/option.c b/src/option.c index f3d107d..b090381 100644 --- a/src/option.c +++ b/src/option.c @@ -689,6 +689,13 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a char *scope_id; #endif + if (!arg || strlen(arg) == 0) + { + *flags |= SERV_NO_ADDR; + *interface = 0; + return NULL; + } + if ((source = split_chr(arg, '@')) && /* is there a source. */ (portno = split_chr(source, '#')) && !atoi_check16(portno, &source_port)) -- 2.39.2