shithub: plan9front

Download patch

ref: 2402025982aa44c91e452fd792abdfc880461944
parent: 358551de19c9ff5bab9cd9c98769224f63fb7e94
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Jan 4 14:25:05 EST 2023

ndb/dns: allow specifying local ip addresses for serving dns

Allow specifying the local IP addresses that
the UDP dns server will listen on when the
-s flag is given.

--- a/sys/man/8/ndb
+++ b/sys/man/8/ndb
@@ -57,7 +57,7 @@
 .br
 .B ndb/dns
 [
-.B -norRs
+.B -norR
 ] [
 .B -a
 .I maxage
@@ -73,7 +73,12 @@
 ] [
 .B -z
 .I program
+] [
+.B -s
+[
+.I addrs...
 ]
+]
 .br
 .B ndb/dnstcp
 [
@@ -390,7 +395,13 @@
 Do not complete lookups on behalf of remote systems.
 .TP
 .B -s
-also answer domain requests sent to UDP port 53.
+also answer domain requests sent to IP
+.I addrs
+on UDP port 53.
+If no IP
+.I addrs
+are given, listen on any interface on network mount point
+.IR netmtpt .
 .TP
 .B -x
 specifies the mount point of the
--- a/sys/src/cmd/ndb/dn.c
+++ b/sys/src/cmd/ndb/dn.c
@@ -144,7 +144,6 @@
 ding(void*, char *msg)
 {
 	if(strstr(msg, "alarm") != nil) {
-		stats.alarms++;
 		noted(NCONT);		/* resume with system call error */
 	} else
 		noted(NDFLT);		/* die */
--- a/sys/src/cmd/ndb/dnnotify.c
+++ b/sys/src/cmd/ndb/dnnotify.c
@@ -73,7 +73,7 @@
 
 /* notify a slave that an area has changed. */
 static void
-send_notify(char *slave, RR *soa, Request *req)
+send_notify(char *mntpt, char *slave, RR *soa, Request *req)
 {
 	int i, j, len, n, reqno, fd, nips, send;
 	uchar ips[8*IPaddrlen], ibuf[Maxudp+Udphdrsize], obuf[Maxudp+Udphdrsize];
@@ -91,7 +91,7 @@
 	reqno = rand();
 	n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno);
 
-	fd = udpport(nil);
+	fd = udpport(mntpt);
 	if(fd < 0)
 		return;
 
@@ -130,7 +130,7 @@
 
 /* send notifies for any updated areas */
 static void
-notify_areas(Area *a, Request *req)
+notify_areas(char *mntpt, Area *a, Request *req)
 {
 	Server *s;
 
@@ -140,7 +140,7 @@
 
 		/* send notifies to all slaves */
 		for(s = a->soarr->soa->slaves; s != nil; s = s->next)
-			send_notify(s->name, a->soarr, req);
+			send_notify(mntpt, s->name, a->soarr, req);
 		a->neednotify = 0;
 	}
 }
@@ -150,7 +150,7 @@
  *  (also reads in new databases)
  */
 void
-notifyproc(void)
+notifyproc(char *mntpt)
 {
 	Request req;
 
@@ -169,7 +169,7 @@
 
 	for(;;){
 		getactivity(&req, 0);
-		notify_areas(owned, &req);
+		notify_areas(mntpt, owned, &req);
 		putactivity(0);
 		sleep(60*1000);
 	}
--- a/sys/src/cmd/ndb/dnresolve.c
+++ b/sys/src/cmd/ndb/dnresolve.c
@@ -473,38 +473,40 @@
 }
 
 /*
- *  Get a udp port for sending requests and reading replies.  Put the port
- *  into "headers" mode.
+ *  Get a udp port for sending requests and reading replies.
+ *  Put the port into "headers" mode.
  */
-static char *hmsg = "headers";
-
 int
-udpport(char *mtpt)
+udpport(char *mntpt)
 {
-	int fd, ctl;
+	static char hmsg[] = "headers";
+	static char imsg[] = "ignoreadvice";
+
 	char ds[64], adir[64];
+	int fd, ctl;
 
 	/* get a udp port */
-	snprint(ds, sizeof ds, "%s/udp!*!0", (mtpt && *mtpt) ? mtpt : "/net");
+	snprint(ds, sizeof ds, "%s/udp!*!0", mntpt);
 	ctl = announce(ds, adir);
-	if(ctl < 0){
-		/* warning("can't get udp port"); */
+	if(ctl < 0)
 		return -1;
-	}
 
 	/* turn on header style interface */
-	if(write(ctl, hmsg, strlen(hmsg)) != strlen(hmsg)){
+	if(write(ctl, hmsg, sizeof(hmsg)-1) < 0){
+		warning("can't enable %s on %s: %r", hmsg, adir);
 		close(ctl);
-		warning(hmsg);
 		return -1;
 	}
 
+	/* ignore ICMP advice */
+	write(ctl, imsg, sizeof(imsg)-1);
+
 	/* grab the data file */
 	snprint(ds, sizeof ds, "%s/data", adir);
 	fd = open(ds, ORDWR);
-	close(ctl);
 	if(fd < 0)
 		warning("can't open udp port %s: %r", ds);
+	close(ctl);
 	return fd;
 }
 
--- a/sys/src/cmd/ndb/dns.c
+++ b/sys/src/cmd/ndb/dns.c
@@ -103,8 +103,8 @@
 void
 usage(void)
 {
-	fprint(2, "usage: %s [-FnorRs] [-a maxage] [-f ndb-file] [-N target] "
-		"[-T forwip] [-x netmtpt] [-z refreshprog]\n", argv0);
+	fprint(2, "usage: %s [-FnorR] [-a maxage] [-f ndb-file] [-N target] "
+		"[-T forwip] [-x netmtpt] [-z refreshprog] [-s [addrs...]]\n", argv0);
 	exits("usage");
 }
 
@@ -167,12 +167,13 @@
 		usage();
 		break;
 	}ARGEND
-	if(argc != 0)
+
+	if(argc != 0 && !cfg.serve)
 		usage();
 
 	rfork(RFREND|RFNOTEG);
 
-	cfg.inside = (*mntpt == '\0' || strcmp(mntpt, "/net") == 0);
+	cfg.inside = strcmp(mntpt, "/net") == 0;
 
 	/* start syslog before we fork */
 	fmtinstall('F', fcallfmt);
@@ -203,10 +204,16 @@
 	if (cfg.straddle && !seerootns())
 		dnslog("straddle server misconfigured; can't see root name servers");
 
-	if(cfg.serve)
-		dnudpserver(mntpt);
+	if(cfg.serve){
+		if(argc == 0)
+			dnudpserver(mntpt, "*");
+		else {
+			while(argc-- > 0)
+				dnudpserver(mntpt, *argv++);
+		}
+	}
 	if(sendnotifies)
-		notifyproc();
+		notifyproc(mntpt);
 
 	io();
 	_exits(0);
--- a/sys/src/cmd/ndb/dns.h
+++ b/sys/src/cmd/ndb/dns.h
@@ -392,7 +392,6 @@
 	ulong	qrecvdudp;
 	ulong	qsent;
 	ulong	qrecvd9prpc;	/* packet count */
-	ulong	alarms;
 	/* reply times by count */
 	ulong	under10ths[3*10+2];	/* under n*0.1 seconds, n is index */
 	ulong	tmout;
@@ -527,11 +526,11 @@
 
 /* dnserver.c */
 void	dnserver(DNSmsg*, DNSmsg*, Request*, uchar *, int);
-void	dnudpserver(char*);
+void	dnudpserver(char*, char*);
 
 /* dnnotify.c */
 void	dnnotify(DNSmsg*, DNSmsg*, Request*);
-void	notifyproc(void);
+void	notifyproc(char*);
 
 /* convDNS2M.c */
 int	convDNS2M(DNSmsg*, uchar*, int);
--- a/sys/src/cmd/ndb/dnudpserver.c
+++ b/sys/src/cmd/ndb/dnudpserver.c
@@ -7,7 +7,7 @@
 	Logqueries = 0,
 };
 
-static int	udpannounce(char*);
+static int	udpannounce(char*, char*);
 static void	reply(int, uchar*, DNSmsg*, Request*);
 
 typedef struct Inprogress Inprogress;
@@ -31,8 +31,6 @@
 Forwtarg forwtarg[10];
 int forwtcount;
 
-static char *hmsg = "headers";
-
 /*
  *  record client id and ignore retransmissions.
  *  we're still single thread at this point.
@@ -129,9 +127,9 @@
  *  a process to act as a dns server for outside reqeusts
  */
 void
-dnudpserver(char *mntpt)
+dnudpserver(char *mntpt, char *addr)
 {
-	volatile int fd, len, op, rcode;
+	volatile int fd, len, op, rcode, served;
 	char *volatile err;
 	volatile char tname[32];
 	volatile uchar buf[Udphdrsize + Maxudp + 1024];
@@ -153,15 +151,16 @@
 		return;
 	}
 
-	fd = -1;
+	served = 0;
 restart:
-	procsetname("udp server announcing");
-	if(fd >= 0)
-		close(fd);
-	while((fd = udpannounce(mntpt)) < 0)
-		sleep(5000);
+	procsetname("%s: udp server announcing %s", mntpt, addr);
+	if((fd = udpannounce(mntpt, addr)) < 0){
+		warning("can't announce %s on %s: %r", addr, mntpt);
+		do {
+			sleep(5000);
+		} while((fd = udpannounce(mntpt, addr)) < 0);
+	}
 
-//	procsetname("udp server");
 	memset(&req, 0, sizeof req);
 	if(setjmp(req.mret))
 		putactivity(0);
@@ -171,8 +170,7 @@
 
 	/* loop on requests */
 	for(;; putactivity(0)){
-		procsetname("served %lud udp; %lud alarms",
-			stats.qrecvdudp, stats.alarms);
+		procsetname("%s: udp server %s: served %d", mntpt, addr, served);
 		memset(&repmsg, 0, sizeof repmsg);
 		memset(&reqmsg, 0, sizeof reqmsg);
 
@@ -179,8 +177,10 @@
 		alarm(60*1000);
 		len = read(fd, buf, sizeof buf);
 		alarm(0);
-		if(len <= Udphdrsize)
+		if(len <= Udphdrsize){
+			close(fd);
 			goto restart;
+		}
 
 		if(forwtcount > 0)
 			redistrib(buf, len);
@@ -194,6 +194,8 @@
 		req.aborttime = timems() + Maxreqtm;
 		req.from = smprint("%I", buf);
 		rcode = 0;
+
+		served++;
 		stats.qrecvdudp++;
 
 		err = convM2DNS(&buf[Udphdrsize], len, &reqmsg, &rcode);
@@ -279,39 +281,33 @@
  *  announce on well-known dns udp port and set message style interface
  */
 static int
-udpannounce(char *mntpt)
+udpannounce(char *mntpt, char *addr)
 {
-	int data, ctl;
+	static char hmsg[] = "headers";
+	static char imsg[] = "ignoreadvice";
+
 	char dir[64], datafile[64+6];
-	static int whined;
+	int data, ctl;
 
-	/* get a udp port */
-	sprint(datafile, "%s/udp!*!dns", mntpt);
+	snprint(datafile, sizeof(datafile), "%s/udp!%s!dns", mntpt, addr);
 	ctl = announce(datafile, dir);
-	if(ctl < 0){
-		if(!whined++)
-			warning("can't announce on %s", datafile);
+	if(ctl < 0)
 		return -1;
-	}
 
 	/* turn on header style interface */
-	if(write(ctl, hmsg, strlen(hmsg)) != strlen(hmsg)){
+	if(write(ctl, hmsg, sizeof(hmsg)-1) < 0){
+		warning("can't enable %s on %s: %r", hmsg, datafile);
 		close(ctl);
-		if(!whined++)
-			warning("can't enable headers on %s", datafile);
 		return -1;
 	}
 
+	/* ignore ICMP advice */
+	write(ctl, imsg, sizeof(imsg)-1);
+
 	snprint(datafile, sizeof(datafile), "%s/data", dir);
 	data = open(datafile, ORDWR);
-	if(data < 0){
-		close(ctl);
-		if(!whined++)
-			warning("can't open %s to announce on dns udp port",
-				datafile);
-		return -1;
-	}
-
+	if(data < 0)
+		warning("can't open udp port %s: %r", datafile);
 	close(ctl);
 	return data;
 }