Module Name:    src
Committed By:   jkunz
Date:           Thu Oct 22 16:34:27 UTC 2009

Modified Files:
        src/usr.sbin/inetd: Makefile inetd.8 inetd.c

Log Message:
Add mDNS Service Directory support to inetd(8).
inetd(8) can now advertize services in the mDNS-SD.
(Per service configuration option in inetd.conf(5).)


To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.22 src/usr.sbin/inetd/Makefile
cvs rdiff -u -r1.52 -r1.53 src/usr.sbin/inetd/inetd.8
cvs rdiff -u -r1.113 -r1.114 src/usr.sbin/inetd/inetd.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/inetd/Makefile
diff -u src/usr.sbin/inetd/Makefile:1.21 src/usr.sbin/inetd/Makefile:1.22
--- src/usr.sbin/inetd/Makefile:1.21	Mon May 28 12:06:35 2007
+++ src/usr.sbin/inetd/Makefile	Thu Oct 22 16:34:27 2009
@@ -1,5 +1,5 @@
 #	from: @(#)Makefile	8.1 (Berkeley) 6/6/93
-#	$NetBSD: Makefile,v 1.21 2007/05/28 12:06:35 tls Exp $
+#	$NetBSD: Makefile,v 1.22 2009/10/22 16:34:27 jkunz Exp $
 
 .include <bsd.own.mk>
 
@@ -20,6 +20,12 @@
 CPPFLAGS+=-DINET6
 .endif
 
+.if (${MKMDNS} != "no")
+CPPFLAGS+=-DMDNS
+LDADD+= -ldns_sd
+DPADD+=	${LIBDNS_SD}
+.endif
+
 CPPFLAGS+=-DIPSEC
 SRCS+=	ipsec.c
 LDADD+= -lipsec

Index: src/usr.sbin/inetd/inetd.8
diff -u src/usr.sbin/inetd/inetd.8:1.52 src/usr.sbin/inetd/inetd.8:1.53
--- src/usr.sbin/inetd/inetd.8:1.52	Tue Jul 14 08:24:15 2009
+++ src/usr.sbin/inetd/inetd.8	Thu Oct 22 16:34:27 2009
@@ -1,4 +1,4 @@
-.\"	$NetBSD: inetd.8,v 1.52 2009/07/14 08:24:15 wiz Exp $
+.\"	$NetBSD: inetd.8,v 1.53 2009/10/22 16:34:27 jkunz Exp $
 .\"
 .\" Copyright (c) 1998 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -118,7 +118,7 @@
 [addr:]service-name
 socket-type[:accept_filter]
 protocol[,sndbuf=size][,rcvbuf=size]
-wait/nowait[:max]
+[mdns,]wait/nowait[:max]
 user[:group]
 server-program
 server program arguments
@@ -132,7 +132,7 @@
 service-name/version
 socket-type
 rpc/protocol[,sndbuf=size][,rcvbuf=size]
-wait/nowait[:max]
+[mdns,]wait/nowait[:max]
 user[:group]
 server-program
 server program arguments
@@ -145,7 +145,7 @@
 path
 socket-type
 unix[,sndbuf=size][,rcvbuf=size]
-wait/nowait[:max]
+[mdns,]wait/nowait[:max]
 user[:group]
 server-program
 server program arguments
@@ -279,6 +279,16 @@
 Socket buffer sizes may be specified for all
 services and protocols except for tcpmux services.
 .Pp
+If the
+.Em mdns
+option is present then
+.Nm
+advertises the service in the mDNS Service Directory.
+.Xr mdnsd 8
+needs to run for this to work. Note that mDNS does not distinguish IPv4 and
+IPv6. If a service is enabled for IPv6 only and IPv4 addresses are configured
+on the affected interface, the service will be advertized for IPv4 and IPv6.
+.Pp
 The
 .Em wait/nowait
 entry is used to tell

Index: src/usr.sbin/inetd/inetd.c
diff -u src/usr.sbin/inetd/inetd.c:1.113 src/usr.sbin/inetd/inetd.c:1.114
--- src/usr.sbin/inetd/inetd.c:1.113	Mon Jul 13 19:05:41 2009
+++ src/usr.sbin/inetd/inetd.c	Thu Oct 22 16:34:27 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: inetd.c,v 1.113 2009/07/13 19:05:41 roy Exp $	*/
+/*	$NetBSD: inetd.c,v 1.114 2009/10/22 16:34:27 jkunz Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
 #if 0
 static char sccsid[] = "@(#)inetd.c	8.4 (Berkeley) 4/13/94";
 #else
-__RCSID("$NetBSD: inetd.c,v 1.113 2009/07/13 19:05:41 roy Exp $");
+__RCSID("$NetBSD: inetd.c,v 1.114 2009/10/22 16:34:27 jkunz Exp $");
 #endif
 #endif /* not lint */
 
@@ -98,7 +98,8 @@
  *	socket type[:accf[,arg]]	stream/dgram/raw/rdm/seqpacket,
 					only stream can name an accept filter
  *	protocol			must be in /etc/protocols
- *	wait/nowait[:max]		single-threaded/multi-threaded, max #
+ *	[mdns,]wait/nowait[:max]	single-threaded/multi-threaded, max #
+ *					if "mdns" register service in mDNS-SD
  *	user[:group]			user/group to run daemon as
  *	server program			full path name
  *	server program arguments	maximum of MAXARGS (20)
@@ -107,7 +108,8 @@
  *      service name/version            must be in /etc/rpc
  *	socket type			stream/dgram/raw/rdm/seqpacket
  *	protocol			must be in /etc/protocols
- *	wait/nowait[:max]		single-threaded/multi-threaded
+ *	[mdns,]wait/nowait[:max]	single-threaded/multi-threaded
+ *					if "mdns" register service in mDNS-SD
  *	user[:group]			user to run daemon as
  *	server program			full path name
  *	server program arguments	maximum of MAXARGS (20)
@@ -255,6 +257,10 @@
 int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
 #endif
 
+#ifdef MDNS
+#include <dns_sd.h>
+#endif /* MDNS */
+
 #define	TOOMANY		40		/* don't start more than TOOMANY */
 #define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
 #define	RETRYTIME	(60*10)		/* retry after bind or server fail */
@@ -320,6 +326,7 @@
 	} se_un;			/* bound address */
 #define se_ctrladdr	se_un.se_un_ctrladdr
 #define se_ctrladdr_in	se_un.se_un_ctrladdr_in
+#define se_ctrladdr_in6	se_un.se_un_ctrladdr_in6
 #define se_ctrladdr_un	se_un.se_un_ctrladdr_un
 	int	se_ctrladdr_size;
 	int	se_max;			/* max # of instances of this service */
@@ -329,6 +336,10 @@
 	int	se_log;
 #define MULOG_RFC931	0x40000000
 #endif
+	int	se_mdns;
+#ifdef MDNS
+	DNSServiceRef se_mdns_reg;
+#endif /* MDNS */
 	struct	servtab *se_next;
 } *servtab;
 
@@ -388,6 +399,11 @@
 static void	timeout(int);
 static char    *rfc931_name(struct sockaddr *, int);
 #endif
+#ifdef MDNS
+static int	iface_idx(struct servtab *);
+static void	register_mdns(struct servtab *);
+#endif /* MDNS */
+
 
 struct biltin {
 	const char *bi_service;		/* internally provided service name */
@@ -990,6 +1006,10 @@
 			continue;
 		}
 		*sepp = sep->se_next;
+#ifdef MDNS
+		if (sep->se_mdns_reg != NULL)
+			DNSServiceRefDeallocate(sep->se_mdns_reg);
+#endif /* MDNS */
 		if (sep->se_fd >= 0)
 			close_sep(sep);
 		if (isrpcservice(sep))
@@ -1047,12 +1067,118 @@
 				unregister_rpc(sep);
 			break;
 		}
+#ifdef MDNS
+		if (sep->se_mdns_reg != NULL)
+			DNSServiceRefDeallocate(sep->se_mdns_reg);
+#endif /* MDNS */
 		(void)close(sep->se_fd);
 		sep->se_fd = -1;
 	}
 	exit(0);
 }
 
+
+#ifdef MDNS
+static int
+iface_idx(struct servtab *sep)
+{
+	int if_idx;
+	struct ifaddrs *ifp;
+	struct ifaddrs *ifa;
+
+	if (sep->se_hostaddr[0] == '*' && sep->se_hostaddr[1] == '\0')
+		return 0;
+	/* Optimize: getifaddrs(3) once and cache result. */
+	if (getifaddrs(&ifp) < 0)
+		return 0;
+	if_idx = 0;
+	for (ifa = ifp; ifa != NULL; ifa = ifa->ifa_next) {
+		if (ifa->ifa_addr->sa_family == AF_INET &&
+		    sep->se_family == AF_INET &&
+		    ((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr ==
+		    sep->se_ctrladdr_in.sin_addr.s_addr) {
+			if_idx = if_nametoindex(ifa->ifa_name);
+			break;
+		}
+#ifdef INET6
+		if (ifa->ifa_addr->sa_family == AF_INET6 &&
+		    sep->se_family == AF_INET6 &&
+		    IN6_ARE_ADDR_EQUAL(
+		    &((struct sockaddr_in6*) ifa->ifa_addr)->sin6_addr,
+		    &sep->se_ctrladdr_in6.sin6_addr)) {
+			if_idx = if_nametoindex(ifa->ifa_name);
+			break;
+		}
+#endif /* INET6 */
+	}
+	freeifaddrs(ifp);
+	return if_idx;
+}
+
+
+static void
+register_mdns(struct servtab *sep)
+{
+	char regtype[kDNSServiceMaxDomainName];
+	int port, iface, err;
+#ifdef INET6
+	struct servtab *sep2;
+
+	/* skip INET6 if there is a registration for INET */
+	for (sep2 = servtab; sep2 != NULL; sep2 = sep2->se_next)
+		if (strcmp(sep2->se_service, sep->se_service) == 0 &&
+		    strncmp(sep2->se_proto, sep->se_proto, 3) == 0 &&
+		    ISMUX(sep2) == ISMUX(sep) &&
+		    sep->se_family == AF_INET6 &&
+		    sep2->se_family == AF_INET && sep2->se_mdns != 0)
+			break;
+	if (sep2 != NULL)
+		return;
+#endif /* INET6 */
+	if (sep->se_socktype == SOCK_STREAM)
+		snprintf(regtype, sizeof(regtype), "_%s._tcp",
+		    sep->se_service);
+	else
+		snprintf(regtype, sizeof(regtype), "_%s._udp",
+		    sep->se_service);
+#ifdef INET6
+	if (sep->se_family == AF_INET)
+		port = sep->se_ctrladdr_in.sin_port;
+	else
+		port = sep->se_ctrladdr_in6.sin6_port;
+#else /* INET6 */
+	port = sep->se_ctrladdr_in.sin_port;
+#endif /* else INET6 */
+	iface = iface_idx(sep);
+	if (sep->se_mdns_reg != NULL)
+		DNSServiceRefDeallocate(sep->se_mdns_reg);
+	err = DNSServiceRegister(&sep->se_mdns_reg, 0, iface, NULL, regtype,
+	    NULL, NULL, port, 0, NULL, NULL, NULL);
+	if (err != kDNSServiceErr_NoError) {
+		syslog(LOG_ERR, "Can't register mDNS service %s, error=%d.",
+		    sep->se_service, err);
+		DNSServiceRefDeallocate(sep->se_mdns_reg);
+		sep->se_mdns_reg = NULL;
+	} else {
+		if (fcntl(DNSServiceRefSockFD(sep->se_mdns_reg), F_SETFD,
+		    FD_CLOEXEC) < 0)
+			syslog(LOG_ERR, "MDNS: %s/%s: fcntl(F_SETFD, "
+			    "FD_CLOEXEC): %m", sep->se_service, sep->se_proto);
+		if (DNSServiceRefSockFD(sep->se_mdns_reg) > maxsock) {
+			maxsock = DNSServiceRefSockFD(sep->se_mdns_reg);
+			if (maxsock > (int)(rlim_ofile_cur - FD_MARGIN))
+				bump_nofile();
+		}
+	}
+	if (debug)
+		fprintf(stderr, "MDNS: regtype=%s port=%d iface=%d fd=%d "
+		    "error=%d\n", regtype, port, iface,
+		    sep->se_mdns_reg == NULL ? -1 :
+		    DNSServiceRefSockFD(sep->se_mdns_reg), err);
+}
+#endif /* MDNS */
+
+
 static void
 setup(struct servtab *sep)
 {
@@ -1145,6 +1271,20 @@
 	ev = allocchange();
 	EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
 	    (intptr_t)sep);
+	if (sep->se_mdns != 0 && ! isrpcservice(sep) &&
+#ifdef INET6
+	    (sep->se_family == AF_INET || sep->se_family == AF_INET6)) {
+#else /* INET6 */
+	    (sep->se_family == AF_INET)) {
+#endif /* else INET6 */
+#ifdef MDNS
+		register_mdns(sep);
+#else /* MDNS */
+		syslog(LOG_WARNING, "Warning: mDNS-SD registation for service "
+		    "%s requested by inetd.conf(5), but mDNS is disabled at "
+		    "compile time.", sep->se_service);
+#endif /* else MDNS */
+	}
 	if (sep->se_fd > maxsock) {
 		maxsock = sep->se_fd;
 		if (maxsock > (int)(rlim_ofile_cur - FD_MARGIN))
@@ -1607,6 +1747,10 @@
 		}
 	}
 	arg = sskip(&cp);
+	if (strncmp(arg, "mdns,", 5) == 0) {
+		sep->se_mdns = 1;
+		arg += 5;
+	}
 	{
 		char *cp1;
 		if ((cp1 = strchr(arg, ':')) == NULL)

Reply via email to