]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
resolve: Maintain order of DNS servers also when installing in resolv.conf
authorTobias Brunner <tobias@strongswan.org>
Fri, 16 Jun 2023 11:46:17 +0000 (13:46 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 19 Jun 2023 12:56:24 +0000 (14:56 +0200)
This always writes the complete set of DNS servers to make modifications
simpler.

src/libcharon/plugins/resolve/resolve_handler.c

index 702c0b5bece5a5d3f1fa123d95af8e055b33a1e7..f93371a888ff48ebb333443ff4959c2a3626eb45 100644 (file)
@@ -32,6 +32,9 @@
 /* default interface/protocol used for resolvconf (should have high prio) */
 #define RESOLVCONF_IFACE "lo.ipsec"
 
+/* suffix added to lines in resolv.conf */
+#define RESOLV_CONF_SUFFIX "   # by strongSwan"
+
 typedef struct private_resolve_handler_t private_resolve_handler_t;
 
 /**
@@ -106,13 +109,15 @@ static bool dns_server_equals(const void *a, const void *b)
 }
 
 /**
- * Writes the given nameserver to resolv.conf
+ * Writes the given nameservers to resolv.conf
  */
-static bool write_nameserver(private_resolve_handler_t *this, host_t *addr)
+static bool write_nameservers(private_resolve_handler_t *this,
+                                                         hashtable_t *servers)
 {
        FILE *in, *out;
-       char buf[1024];
-       size_t len;
+       enumerator_t *enumerator;
+       dns_server_t *dns;
+       char line[1024];
        bool handled = FALSE;
 
        in = fopen(this->file, "r");
@@ -121,63 +126,35 @@ static bool write_nameserver(private_resolve_handler_t *this, host_t *addr)
        out = fopen(this->file, "w");
        if (out)
        {
-               fprintf(out, "nameserver %H   # by strongSwan\n", addr);
-               DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file);
-               handled = TRUE;
-
-               /* copy rest of the file */
-               if (in)
+               /* write our current set of servers */
+               enumerator = servers->create_enumerator(servers);
+               while (enumerator->enumerate(enumerator, NULL, &dns))
                {
-                       while ((len = fread(buf, 1, sizeof(buf), in)))
-                       {
-                               ignore_result(fwrite(buf, 1, len, out));
-                       }
+                       fprintf(out, "nameserver %H" RESOLV_CONF_SUFFIX "\n", dns->server);
                }
-               fclose(out);
-       }
-       if (in)
-       {
-               fclose(in);
-       }
-       return handled;
-}
+               enumerator->destroy(enumerator);
 
-/**
- * Removes the given nameserver from resolv.conf
- */
-static void remove_nameserver(private_resolve_handler_t *this, host_t *addr)
-{
-       FILE *in, *out;
-       char line[1024], matcher[512];
-
-       in = fopen(this->file, "r");
-       if (in)
-       {
-               /* allows us to stream from in to out */
-               unlink(this->file);
-               out = fopen(this->file, "w");
-               if (out)
+               if (in)
                {
-                       snprintf(matcher, sizeof(matcher),
-                                        "nameserver %H   # by strongSwan\n", addr);
-
-                       /* copy all, but matching line */
+                       /* copy the rest of the file, except our previous servers */
                        while (fgets(line, sizeof(line), in))
                        {
-                               if (strpfx(line, matcher))
-                               {
-                                       DBG1(DBG_IKE, "removing DNS server %H from %s",
-                                                addr, this->file);
-                               }
-                               else
+                               if (!strstr(line, RESOLV_CONF_SUFFIX "\n"))
                                {
                                        fputs(line, out);
                                }
                        }
-                       fclose(out);
                }
+
+               handled = TRUE;
+
+               fclose(out);
+       }
+       if (in)
+       {
                fclose(in);
        }
+       return handled;
 }
 
 /**
@@ -303,7 +280,8 @@ METHOD(attribute_handler_t, handle, bool,
                }
                else
                {
-                       handled = write_nameserver(this, addr);
+                       DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file);
+                       handled = write_nameservers(this, this->servers);
                }
                if (!handled)
                {
@@ -372,7 +350,9 @@ METHOD(attribute_handler_t, release, void,
                        }
                        else
                        {
-                               remove_nameserver(this, addr);
+                               DBG1(DBG_IKE, "removing DNS server %H from %s", addr,
+                                        this->file);
+                               write_nameservers(this, this->servers);
                        }
                }
        }