public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top
Subject: [PATCH v2 2/4] Parse resolv.conf with new lineread implementation
Date: Fri, 24 Jun 2022 12:17:30 +1000	[thread overview]
Message-ID: <20220624021732.4062212-3-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20220624021732.4062212-1-david@gibson.dropbear.id.au>

[-- Attachment #1: Type: text/plain, Size: 2283 bytes --]

Switch the resolv.conf parsing in conf.c to use the new lineread
implementation.  This means that it can now handle a resolv.conf file which
contains blank lines.

There are quite a few other fragilities with the resolv.conf parsing, but
that's out of scope for this patch.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 conf.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/conf.c b/conf.c
index 3a5d650..22949fd 100644
--- a/conf.c
+++ b/conf.c
@@ -38,6 +38,7 @@
 #include "udp.h"
 #include "tcp.h"
 #include "pasta.h"
+#include "lineread.h"
 
 /**
  * get_bound_ports() - Get maps of ports with bound sockets
@@ -320,7 +321,9 @@ static void get_dns(struct ctx *c)
 	struct in6_addr *dns6 = &c->dns6[0];
 	struct fqdn *s = c->dns_search;
 	uint32_t *dns4 = &c->dns4[0];
-	char buf[BUFSIZ], *p, *end;
+	struct lineread resolvconf;
+	int line_len;
+	char *line, *p, *end;
 
 	dns4_set = !c->v4  || !!*dns4;
 	dns6_set = !c->v6  || !IN6_IS_ADDR_UNSPECIFIED(dns6);
@@ -333,13 +336,14 @@ static void get_dns(struct ctx *c)
 	if ((fd = open("/etc/resolv.conf", O_RDONLY | O_CLOEXEC)) < 0)
 		goto out;
 
-	for (*buf = 0; line_read(buf, BUFSIZ, fd); *buf = 0) {
-		if (!dns_set && strstr(buf, "nameserver ") == buf) {
-			p = strrchr(buf, ' ');
+	lineread_init(&resolvconf, fd);
+	while ((line_len = lineread_get(&resolvconf, &line)) > 0) {
+		if (!dns_set && strstr(line, "nameserver ") == line) {
+			p = strrchr(line, ' ');
 			if (!p)
 				continue;
 
-			end = strpbrk(buf, "%\n");
+			end = strpbrk(line, "%\n");
 			if (end)
 				*end = 0;
 
@@ -356,13 +360,13 @@ static void get_dns(struct ctx *c)
 				dns6++;
 				memset(dns6, 0, sizeof(*dns6));
 			}
-		} else if (!dnss_set && strstr(buf, "search ") == buf &&
+		} else if (!dnss_set && strstr(line, "search ") == line &&
 			   s == c->dns_search) {
-			end = strpbrk(buf, "\n");
+			end = strpbrk(line, "\n");
 			if (end)
 				*end = 0;
 
-			if (!strtok(buf, " \t"))
+			if (!strtok(line, " \t"))
 				continue;
 
 			while (s - c->dns_search < ARRAY_SIZE(c->dns_search) - 1
@@ -374,6 +378,8 @@ static void get_dns(struct ctx *c)
 		}
 	}
 
+	if (line_len < 0)
+		warn("Error reading /etc/resolv.conf: %s", strerror(errno));
 	close(fd);
 
 out:
-- 
@@ -38,6 +38,7 @@
 #include "udp.h"
 #include "tcp.h"
 #include "pasta.h"
+#include "lineread.h"
 
 /**
  * get_bound_ports() - Get maps of ports with bound sockets
@@ -320,7 +321,9 @@ static void get_dns(struct ctx *c)
 	struct in6_addr *dns6 = &c->dns6[0];
 	struct fqdn *s = c->dns_search;
 	uint32_t *dns4 = &c->dns4[0];
-	char buf[BUFSIZ], *p, *end;
+	struct lineread resolvconf;
+	int line_len;
+	char *line, *p, *end;
 
 	dns4_set = !c->v4  || !!*dns4;
 	dns6_set = !c->v6  || !IN6_IS_ADDR_UNSPECIFIED(dns6);
@@ -333,13 +336,14 @@ static void get_dns(struct ctx *c)
 	if ((fd = open("/etc/resolv.conf", O_RDONLY | O_CLOEXEC)) < 0)
 		goto out;
 
-	for (*buf = 0; line_read(buf, BUFSIZ, fd); *buf = 0) {
-		if (!dns_set && strstr(buf, "nameserver ") == buf) {
-			p = strrchr(buf, ' ');
+	lineread_init(&resolvconf, fd);
+	while ((line_len = lineread_get(&resolvconf, &line)) > 0) {
+		if (!dns_set && strstr(line, "nameserver ") == line) {
+			p = strrchr(line, ' ');
 			if (!p)
 				continue;
 
-			end = strpbrk(buf, "%\n");
+			end = strpbrk(line, "%\n");
 			if (end)
 				*end = 0;
 
@@ -356,13 +360,13 @@ static void get_dns(struct ctx *c)
 				dns6++;
 				memset(dns6, 0, sizeof(*dns6));
 			}
-		} else if (!dnss_set && strstr(buf, "search ") == buf &&
+		} else if (!dnss_set && strstr(line, "search ") == line &&
 			   s == c->dns_search) {
-			end = strpbrk(buf, "\n");
+			end = strpbrk(line, "\n");
 			if (end)
 				*end = 0;
 
-			if (!strtok(buf, " \t"))
+			if (!strtok(line, " \t"))
 				continue;
 
 			while (s - c->dns_search < ARRAY_SIZE(c->dns_search) - 1
@@ -374,6 +378,8 @@ static void get_dns(struct ctx *c)
 		}
 	}
 
+	if (line_len < 0)
+		warn("Error reading /etc/resolv.conf: %s", strerror(errno));
 	close(fd);
 
 out:
-- 
2.36.1


  parent reply	other threads:[~2022-06-24  2:17 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-24  2:17 [PATCH v2 0/4] New line reading implementation David Gibson
2022-06-24  2:17 ` [PATCH v2 1/4] Add cleaner line-by-line reading primitives David Gibson
2022-06-27 10:36   ` Stefano Brivio
2022-06-28  0:47     ` David Gibson
2022-06-24  2:17 ` David Gibson [this message]
2022-06-24  2:17 ` [PATCH v2 3/4] Use new lineread implementation for procfs_scan_listen() David Gibson
2022-06-24  2:17 ` [PATCH v2 4/4] Remove unused line_read() David Gibson
2022-07-06 17:46 ` [PATCH v2 0/4] New line reading implementation Stefano Brivio

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220624021732.4062212-3-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).