PSARC/2007/499 Automatic discovery of network attached printers
authorjacobs
Tue, 23 Oct 2007 07:51:21 -0700
changeset 5307 ea4512a0e608
parent 5306 fedb0b5a9fb4
child 5308 2cc1023bdfa4
PSARC/2007/499 Automatic discovery of network attached printers 6607736 Solaris should detect network attached printers
usr/src/cmd/hal/addons/Makefile
usr/src/cmd/hal/addons/network-devices/Makefile
usr/src/cmd/hal/addons/network-devices/addon-network-discovery.c
usr/src/cmd/hal/addons/network-devices/cache.c
usr/src/cmd/hal/addons/network-devices/common.c
usr/src/cmd/hal/addons/network-devices/network-discovery.h
usr/src/cmd/hal/addons/network-devices/network-discovery.xml
usr/src/cmd/hal/addons/network-devices/snmp.c
usr/src/cmd/hal/addons/network-devices/svc-network-discovery
usr/src/cmd/hal/fdi/Makefile
usr/src/cmd/hal/fdi/policy/10osvendor/10-network-attached.fdi
usr/src/cmd/hal/fdi/preprobe/10osvendor/20-printers.fdi
usr/src/cmd/hal/probing/Makefile
usr/src/cmd/hal/probing/network-printer/Makefile
usr/src/cmd/hal/probing/network-printer/probe-network-printer.c
usr/src/cmd/hal/probing/network-printer/probe-snmp.c
usr/src/cmd/hal/probing/printer/Makefile
usr/src/cmd/hal/probing/printer/probe-printer.c
usr/src/cmd/hal/utils/printer.c
usr/src/cmd/hal/utils/printer.h
usr/src/lib/libsecdb/auth_attr.txt
usr/src/lib/libsecdb/help/auths/Makefile
usr/src/lib/libsecdb/help/auths/SmfNADDStates.html
usr/src/lib/libsecdb/help/auths/SmfValueNADD.html
usr/src/lib/libsecdb/prof_attr.txt
usr/src/pkgdefs/SUNW0on/prototype_com
usr/src/pkgdefs/SUNWcsu/prototype_com
usr/src/pkgdefs/SUNWhal/prototype_com
usr/src/pkgdefs/SUNWhalr/prototype_com
usr/src/tools/scripts/check_rtime.pl
--- a/usr/src/cmd/hal/addons/Makefile	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/cmd/hal/addons/Makefile	Tue Oct 23 07:51:21 2007 -0700
@@ -25,7 +25,7 @@
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
 
-SUBDIRS = storage acpi
+SUBDIRS = storage acpi network-devices
 
 all :=		TARGET= all
 install :=	TARGET= install
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/addons/network-devices/Makefile	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,81 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+PROG =		hald-addon-network-discovery
+OBJS =		addon-network-discovery.o probe-snmp.o snmp.o logger.o cache.o common.o printer.o
+
+MANIFEST =	network-discovery.xml
+SVCMETHOD =	svc-network-discovery
+
+include ../../../Makefile.cmd
+include ../../Makefile.hal
+
+ROOTMANIFESTDIR =	$(ROOTSVCNETWORK)
+$(ROOTMANIFEST) :=	FILEMODE = 444
+$(ROOTLIBSVCMETHOD)/$(SVCMETHOD):= FILEMODE = 555
+
+ROOTCMDDIR =	$(ROOTLIB_HAL)
+
+LDLIBS +=	-lc -ldbus-1 -lhal -lglib-2.0 -ldbus-glib-1
+LDLIBS +=	-lnsl -lsocket
+LDLIBS +=	-L$(SFWLIBDIR) -R$(SFWLIBDIR) $(ZIGNORE) -lnetsnmp
+
+CPPFLAGS +=	$(HAL_DBUS_CPPFLAGS) $(HAL_GLIB_CPPFLAGS) $(HAL_CONFIG_CPPFLAGS)
+CPPFLAGS +=	-I$(ROOT)/usr/include/hal -I../../hald -I../../utils
+CPPFLAGS +=	-I$(SFWINCDIR)
+C99MODE =	$(C99_ENABLE)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+probe-snmp.o: ../../probing/network-printer/probe-snmp.c
+	$(COMPILE.c) -o $@ ../../probing/network-printer/probe-snmp.c
+	$(POST_PROCESS_O)
+
+logger.o: ../../hald/logger.c
+	$(COMPILE.c) -o $@ ../../hald/logger.c
+	$(POST_PROCESS_O)
+
+printer.o: ../../utils/printer.c
+	$(COMPILE.c) -o $@ ../../utils/printer.c
+	$(POST_PROCESS_O)
+
+$(PROG): $(OBJS)
+	$(LINK.c) -o $@ $(OBJS) $(LDLIBS)
+	$(POST_PROCESS)
+
+install: all $(ROOTCMD) $(ROOTMANIFEST) $(ROOTSVCMETHOD)
+
+check: $(CHKMANIFEST)
+
+clean:
+	$(RM) $(OBJS) $(PROG)
+
+FRC:
+
+include ../../../Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/addons/network-devices/addon-network-discovery.c	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/dkio.h>
+#include <sys/stat.h>
+#include <priv.h>
+#include <glib.h>
+
+#include <dbus/dbus-glib-lowlevel.h>
+#include <libhal.h>
+
+#include "../../hald/logger.h"
+
+#include "network-discovery.h"
+#include "printer.h"
+
+#define	DBUS_INTERFACE	"org.freedesktop.Hal.Device.NetworkDiscovery"
+#define	NP(x)	(x?x:"NULL")
+#define	STRDUP(x)	(x?strdup(x):NULL)
+
+typedef struct {
+	LibHalContext *ctx;
+	gboolean enabled;
+	char *parent;
+	char *community;
+	char *network;
+} nds_snmp_cbdata_t;
+
+static nds_snmp_cbdata_t *snmp_cb_data = NULL;
+
+static int
+nds_snmp_scan(LibHalContext *ctx, char *parent, char *community, char *network)
+{
+	time_t start;
+
+	HAL_DEBUG(("nds_snmp_scan(0x%8.8x, %s, %s, %s)",
+			ctx, NP(parent), NP(community), NP(network)));
+	HAL_DEBUG(("NetworkDiscovery snmp scan initated"));
+
+	/* scan for devices */
+	time(&start);
+	if (network == NULL) {
+		GList *elem, *list = broadcast_addresses();
+
+		for (elem = list; elem != NULL; elem = g_list_next(elem)) {
+			scan_for_devices_using_snmp(ctx, parent, community,
+						(char *)elem->data);
+			free(elem->data);
+		}
+		g_list_free(list);
+	} else
+		scan_for_devices_using_snmp(ctx, parent, community, network);
+
+	/* remove devices that haven't been seen since before this scan */
+	scan_for_stale_devices(ctx, start);
+
+	HAL_DEBUG(("NetworkDiscovery snmp scan completed"));
+
+	return (0);
+}
+
+static gboolean
+nds_snmp_scan_cb(gpointer data)
+{
+	nds_snmp_cbdata_t *args = data;
+
+	if (args->enabled == FALSE) {
+		if (args->parent) free(args->parent);
+		if (args->community) free(args->community);
+		if (args->network) free(args->network);
+		free(args);
+		return (FALSE);
+	}
+
+	nds_snmp_scan(args->ctx, args->parent, args->community, args->network);
+
+	return (TRUE);
+}
+
+static int
+nds_EnablePrinterScanningViaSNMP(LibHalContext *ctx, char *parent, int interval,
+		char *community, char *network)
+{
+	HAL_DEBUG(("NetworkDiscovery.EnablePrinterScanningViaSNMP(0x%8.8x, %s, %d, %s, %s)",
+			ctx, NP(parent), interval, NP(community), NP(network)));
+
+	/* are we already discoverying network devices ? */
+	if (snmp_cb_data != NULL) {
+		snmp_cb_data->enabled = FALSE; /* cancel it */
+	}
+
+	/* setup for network device discovery */
+	if ((snmp_cb_data = calloc(1, sizeof (*snmp_cb_data))) != NULL) {
+		snmp_cb_data->ctx = ctx;
+		snmp_cb_data->enabled = TRUE;
+		snmp_cb_data->parent = STRDUP(parent);
+		snmp_cb_data->community = STRDUP(community);
+		snmp_cb_data->network = STRDUP(network);
+
+		/* prime the pump with an initial scan */
+		nds_snmp_scan(ctx, parent, community, network);
+
+		/* add a regular network scan */
+		g_timeout_add(interval * 1000, nds_snmp_scan_cb, snmp_cb_data);
+	}
+
+	return (0);
+}
+
+static int
+nds_DisablePrinterScanningViaSNMP(LibHalContext *ctx)
+{
+	HAL_DEBUG(("NetworkDiscovery.DisablePrinterScanningViaSNMP(0x%8.8x)", ctx));
+
+	if (snmp_cb_data != NULL)
+		snmp_cb_data->enabled = FALSE;
+	snmp_cb_data = NULL;
+
+	return (0);
+}
+
+static int
+nds_ScanForPrintersViaSNMP(LibHalContext *ctx, char *parent, char *community,
+		char *network)
+{
+	time_t start, stop;
+
+	HAL_DEBUG(("NetworkDiscovery.ScanForPrintersViaSNMP(0x%8.8x, %s, %s, %s)",
+			ctx, NP(parent), NP(community), NP(network)));
+
+	return (nds_snmp_scan(ctx, parent, community, network));
+}
+
+static DBusHandlerResult
+nds_filter_function(DBusConnection *connection, DBusMessage *message,
+		void *user_data)
+{
+	LibHalContext *ctx = user_data;
+	DBusMessage *reply;
+	DBusError error;
+	const char *member = dbus_message_get_member(message);
+	const char *path = dbus_message_get_path(message);
+	int rc = -1;
+
+	dbus_error_init(&error);
+
+	HAL_DEBUG(("DBus message: %s, %s ", member, path));
+
+	if (dbus_message_is_method_call(message,
+				DBUS_INTERFACE, "EnablePrinterScanningViaSNMP")) {
+		int interval = -1;
+		char *udi = getenv("UDI");
+		char *community = "public";
+		char *network = "0.0.0.0";
+
+		dbus_message_get_args(message, &error,
+				DBUS_TYPE_INT32, &interval,
+				DBUS_TYPE_STRING, &community,
+				DBUS_TYPE_STRING, &network,
+				DBUS_TYPE_INVALID);
+
+		if (strcmp(network, "0.0.0.0") == 0)
+			network = NULL;
+
+		rc = nds_EnablePrinterScanningViaSNMP(ctx, udi, interval,
+				community, network);
+	} else if (dbus_message_is_method_call(message,
+				DBUS_INTERFACE, "ScanForPrintersViaSNMP")) {
+		int interval = -1;
+		char *udi = getenv("UDI");
+		char *community = "public";
+		char *network = "0.0.0.0";
+
+		dbus_message_get_args(message, &error,
+				DBUS_TYPE_STRING, &community,
+				DBUS_TYPE_STRING, &network,
+				DBUS_TYPE_INVALID);
+
+		if (strcmp(network, "0.0.0.0") == 0)
+			network = NULL;
+
+		rc = nds_ScanForPrintersViaSNMP(ctx, udi, community, network);
+	} else if (dbus_message_is_method_call(message,
+				DBUS_INTERFACE, "DisablePrinterScanningViaSNMP")) {
+		rc = nds_DisablePrinterScanningViaSNMP(ctx);
+	} else
+		HAL_WARNING(("Unknown DBus message: %s, %s ", member, path));
+
+	if (dbus_error_is_set(&error))
+		dbus_error_free(&error);
+
+	if ((reply = dbus_message_new_method_return(message)) == NULL) {
+		HAL_WARNING(("Could not allocate memory for the DBus reply"));
+		return (FALSE);
+	}
+
+	dbus_message_append_args(reply, DBUS_TYPE_INT32, &rc,
+			DBUS_TYPE_INVALID);
+
+	if (!dbus_connection_send(connection, reply, NULL)) {
+		HAL_WARNING(("Could not sent reply"));
+	}
+	dbus_connection_flush(connection);
+	dbus_message_unref(reply);
+
+	return (DBUS_HANDLER_RESULT_HANDLED);
+}
+
+static int
+nds_claim_interface(LibHalContext *ctx, char *udi, DBusError *error)
+{
+	DBusConnection *connection;
+	char *interface_xml =
+		"<method name=\"EnablePrinterScanningViaSNMP\">\n"
+		"  <arg name=\"interval\" direction=\"in\" type=\"i\"/>\n"
+		"  <arg name=\"community\" direction=\"in\" type=\"s\"/>\n"
+		"  <arg name=\"network\" direction=\"in\" type=\"s\"/>\n"
+		"  <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n"
+		"</method>\n"
+		"<method name=\"DisablePrinterScanningViaSNMP\">\n"
+		"  <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n"
+		"</method>\n"
+		"<method name=\"ScanForPrintersViaSNMP\">\n"
+		"  <arg name=\"community\" direction=\"in\" type=\"s\"/>\n"
+		"  <arg name=\"network\" direction=\"in\" type=\"s\"/>\n"
+		"  <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n"
+		"</method>\n";
+
+	HAL_DEBUG(("nds_claim_interface(0x%8.8x, %s, 0x%8.8x): %s",
+			ctx, udi, error, DBUS_INTERFACE));
+
+	if ((connection = libhal_ctx_get_dbus_connection(ctx)) == NULL) {
+		HAL_WARNING(("Could not get DBus connection"));
+		return (-1);
+	}
+
+	if (libhal_device_claim_interface(ctx, udi,
+			DBUS_INTERFACE, interface_xml, error) == 0) {
+		HAL_WARNING(("Could not claim interface: %s", error->message));
+		return (-1);
+	}
+
+	dbus_connection_setup_with_g_main(connection, NULL);
+	dbus_connection_add_filter(connection, nds_filter_function, ctx, NULL);
+	dbus_connection_set_exit_on_disconnect(connection, 0);
+
+	return (0);
+}
+
+static void
+drop_privileges()
+{
+	priv_set_t *pPrivSet = NULL;
+	priv_set_t *lPrivSet = NULL;
+
+	/*
+	 * Start with the 'basic' privilege set and then remove any
+	 * of the 'basic' privileges that will not be needed.
+	 */
+	if ((pPrivSet = priv_str_to_set("basic", ",", NULL)) == NULL) {
+		return;
+	}
+
+	/* Clear privileges we will not need from the 'basic' set */
+	(void) priv_delset(pPrivSet, PRIV_FILE_LINK_ANY);
+	(void) priv_delset(pPrivSet, PRIV_PROC_EXEC);
+	(void) priv_delset(pPrivSet, PRIV_PROC_FORK);
+	(void) priv_delset(pPrivSet, PRIV_PROC_INFO);
+	(void) priv_delset(pPrivSet, PRIV_PROC_SESSION);
+
+	/* Set the permitted privilege set. */
+	if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
+		return;
+	}
+
+	/* Clear the limit set. */
+	if ((lPrivSet = priv_allocset()) == NULL) {
+		return;
+	}
+
+	priv_emptyset(lPrivSet);
+
+	if (setppriv(PRIV_SET, PRIV_LIMIT, lPrivSet) != 0) {
+		return;
+	}
+
+	priv_freeset(lPrivSet);
+}
+
+
+int
+main(int argc, char **argv)
+{
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	GMainLoop *loop = g_main_loop_new(NULL, FALSE);
+	char *udi;
+
+	if ((udi = getenv("UDI")) == NULL) {
+		return (0);
+	}
+
+	drop_privileges();
+
+	setup_logger();
+
+	dbus_error_init(&error);
+
+	if ((ctx = libhal_ctx_init_direct(&error)) == NULL) {
+		return (0);
+	}
+
+	if (!libhal_device_addon_is_ready(ctx, udi, &error)) {
+		return (0);
+	}
+
+	if (nds_claim_interface(ctx, udi, &error) != 0) {
+		return (0);
+	}
+
+	g_main_loop_run(loop);
+
+	/* NOTREACHED */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/addons/network-devices/cache.c	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <libhal.h>
+#include <logger.h>
+
+#include <glib.h>
+
+#include "network-discovery.h"
+
+/*
+ * The interfaces in this file comprise a means of keeping track of devices
+ * that we have already seen and those that have gone missing.  This allows
+ * us to quickly determine if we need to probe the device and quickly search
+ * for devices that are no longer available.
+ */
+
+typedef struct {
+	LibHalContext *ctx;
+	time_t timestamp;
+} removal_args_t;
+
+static GHashTable *seen = NULL;
+
+static gboolean
+device_remove_if_stale(gpointer key, gpointer value, gpointer user_data)
+{
+	gboolean result = FALSE;
+	removal_args_t *args = user_data;
+	char *name = key;
+	time_t *val = value;
+
+	HAL_DEBUG(("test stale: %s (%d > %d)", name, args->timestamp, *val));
+	if (args->timestamp > *val) {
+		DBusError error;
+		char **udi = NULL;
+		int num = 0;
+
+		dbus_error_init(&error);
+		udi = libhal_manager_find_device_string_match(args->ctx,
+					"network_device.address", name,
+					&num, &error);
+
+		if (udi != NULL) {
+			int i;
+
+			for (i = 0; i < num; i++) {
+				libhal_remove_device(args->ctx, udi[i], &error);
+				HAL_DEBUG(("remove: %s (%s)", name, udi[i]));
+			}
+			libhal_free_string_array(udi);
+			result = TRUE;
+		}
+		if (dbus_error_is_set(&error))
+			dbus_error_free(&error);
+	}
+
+	return (result);
+}
+
+void
+scan_for_stale_devices(LibHalContext *ctx, time_t timestamp)
+{
+	if (seen != NULL) {
+		removal_args_t args[1];
+
+		args->ctx = ctx;
+		args->timestamp = timestamp;
+
+		g_hash_table_foreach_remove(seen, device_remove_if_stale, args);
+	}
+}
+
+gboolean
+device_seen(char *name)
+{
+	gboolean result;
+	char *key;
+	time_t *val;
+
+	if (seen == NULL)
+		seen = g_hash_table_new_full(g_str_hash, g_str_equal,
+						free, free);
+
+	result = g_hash_table_lookup_extended(seen, name,
+				(gpointer)&key, (gpointer)&val);
+
+	if ((result == FALSE) && ((val = calloc(1, sizeof (*val))) != NULL)) {
+		g_hash_table_insert(seen, strdup(name), val);
+	}
+	(void) time(val);
+	HAL_DEBUG(("seen: %s (%d)", name, *val));
+
+	return (result);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/addons/network-devices/common.c	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <libhal.h>
+#include <logger.h>
+
+#include <glib.h>
+
+#include "network-discovery.h"
+#define	NP(x)	(x?x:"NULL")
+
+extern int snmp_printer_info(char *hostname, char *community,
+		char **manufacturer, char **model, char **description,
+		char **serial_no, char ***command_set, char **uri);
+
+void
+network_device_name_to_udi(char *udi, size_t size, ...)
+{
+	va_list ap;
+	char *element;
+	int i;
+
+	udi[0] = '\0';
+	va_start(ap, size);
+	while ((element = va_arg(ap, char *)) != NULL) {
+		if (element[0] != '/')
+			strlcat(udi, "/", size);
+		strlcat(udi, element, size);
+	}
+	va_end(ap);
+
+	for (i = 0; udi[i] != NULL; i++)
+		if (udi[i] == '.')
+			udi[i] = '_';
+}
+
+static void nop(int sig) {}
+
+static int
+test_socket_access(struct in6_addr *addr, int port)
+{
+	int sd, rc;
+	struct sockaddr_in6 sin6;
+	void (*hndlr)(int);
+
+	memset(&sin6, 0, sizeof (sin6));
+	sin6.sin6_family = AF_INET6;
+	memcpy(&sin6.sin6_addr, addr, sizeof (*addr));
+	sin6.sin6_port = htons(port);
+
+	sd = socket(AF_INET6, SOCK_STREAM, 0);
+	hndlr = signal(SIGALRM, nop);
+	alarm(1);
+	rc = connect(sd, (struct sockaddr *)&sin6, sizeof (sin6));
+	alarm(0);
+	if (hndlr != NULL)
+		signal(SIGALRM, hndlr);
+	close(sd);
+
+	return ((rc < 0) ? 1 : 0);
+}
+
+int
+is_listening(char *hostname, int port)
+{
+	char *uri = NULL, addr_string[INET6_ADDRSTRLEN];
+	struct in6_addr ipv6addr[1];
+	int errnum;
+	struct hostent *hp;
+
+	hp = getipnodebyname(hostname, AF_INET6,
+			AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED, &errnum);
+	if (hp != NULL) {
+		(void) memcpy(&ipv6addr, hp->h_addr_list[0], hp->h_length);
+	} else
+		return (-1);
+
+	return (test_socket_access(ipv6addr, port));
+}
+
+static char *
+addr_to_string(char *prefix, uchar_t *mac, int mac_len, char *buf, int buf_len)
+{
+	int i, n = 0;
+
+	buf[0] = '\0';
+	if (prefix != NULL)
+		n = sprintf(buf, prefix);
+	for (i = 0; ((i < (mac_len)) && (n < buf_len)); i++)
+		n += sprintf(buf + n, "%2.2X", *mac++);
+
+	return (buf);
+}
+
+static char *
+pseudo_serialno_from_addr(char *name)
+{
+	int sd, rc, errnum;
+	char buf[128];
+	struct hostent *hp;
+	struct xarpreq ar;
+
+	if (name == NULL)
+		return (NULL);
+
+	memset(&ar, 0, sizeof (ar));
+
+	hp = getipnodebyname(name, AF_INET6, AI_ADDRCONFIG, &errnum);
+	if (hp != NULL) {
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ar.xarp_pa;
+
+		sin6->sin6_family = AF_INET6;
+		(void) memcpy(&sin6->sin6_addr, hp->h_addr_list[0],
+				hp->h_length);
+	} else {
+		struct sockaddr_in *sin = (struct sockaddr_in *)&ar.xarp_pa;
+
+		sin->sin_family = AF_INET;
+		sin->sin_addr.s_addr = inet_addr(name);
+	}
+
+	sd = socket(AF_INET, SOCK_DGRAM, 0);
+
+	ar.xarp_ha.sdl_family = AF_LINK;
+	rc = ioctl(sd, SIOCGXARP, (caddr_t)&ar);
+
+	close(sd);
+
+	if (ar.xarp_flags & ATF_COM) {  /* use the MAC address */
+		uchar_t *ea = (uchar_t *)LLADDR(&ar.xarp_ha);
+
+		addr_to_string("LLADDR-", ea, ar.xarp_ha.sdl_alen,
+					buf, sizeof (buf));
+
+	} else if (hp != NULL) {	  /* use the IPv6 address */
+		addr_to_string("IPV6ADDR-", (uchar_t *)&hp->h_addr_list[0],
+					hp->h_length, buf, sizeof (buf));
+	} else {			  /* use the IPv4 address */
+		struct sockaddr_in *sin = (struct sockaddr_in *)&ar.xarp_pa;
+
+		addr_to_string("IPV4ADDR-", (uchar_t *)&sin->sin_addr.s_addr, 4,
+					buf, sizeof (buf));
+	}
+
+	return (strdup(buf));
+}
+
+int
+add_network_printer(LibHalContext *ctx, char *base, char *hostaddr,
+		char *device, char *community)
+{
+	DBusError error;
+	int rc = -1;
+	char udi[128];
+	char *tmp_udi = NULL;
+	static char *parent = NULL;
+	char *manufacturer = NULL, *model = NULL, *description = NULL,
+	     *uri = NULL, *sn, *serial;
+
+	sn = serial = pseudo_serialno_from_addr(hostaddr);
+
+	if (parent == NULL)
+		parent = getenv("UDI");
+
+	dbus_error_init(&error);
+
+	network_device_name_to_udi(udi, sizeof (udi), base, serial, NULL);
+
+	if (libhal_device_exists(ctx, udi, &error) == TRUE)
+		goto out;
+
+	if ((tmp_udi = libhal_new_device(ctx, &error)) == NULL)
+		goto out;
+
+	snmp_printer_info(hostaddr, community, &manufacturer, &model,
+			&description, &serial, NULL, &uri);
+
+	libhal_device_set_property_string(ctx, tmp_udi,
+			"info.parent", parent, &error);
+
+	libhal_device_set_property_string(ctx, tmp_udi,
+			"info.category", "printer", &error);
+
+	libhal_device_property_strlist_append(ctx, tmp_udi,
+				"info.capabilities", "printer", &error);
+	libhal_device_property_strlist_append(ctx, tmp_udi,
+				"info.capabilities", "network_device", &error);
+
+	libhal_device_set_property_string(ctx, tmp_udi,
+			"network_device.address", hostaddr, &error);
+
+	if ((community != NULL) && (strcasecmp(community, "public") != 0))
+		libhal_device_set_property_string(ctx, tmp_udi,
+			"network_device.snmp_community", community, &error);
+
+	if ((uri != NULL) || (device != NULL))
+		libhal_device_set_property_string(ctx, tmp_udi,
+			"printer.device", (uri ? uri : device), &error);
+
+	if (serial != NULL)
+		libhal_device_set_property_string(ctx, tmp_udi,
+			"printer.serial", serial, &error);
+
+	if (manufacturer != NULL)
+		libhal_device_set_property_string(ctx, tmp_udi,
+			"printer.vendor", manufacturer, &error);
+
+	if (model != NULL)
+		libhal_device_set_property_string(ctx, tmp_udi,
+			"printer.product", model, &error);
+
+	if (description != NULL)
+		libhal_device_set_property_string(ctx, tmp_udi,
+			"printer.description", description, &error);
+
+	/* commit the changes to the new UDI */
+	rc = libhal_device_commit_to_gdl(ctx, tmp_udi, udi, &error);
+
+out:
+	HAL_DEBUG(("result: %s (%s): %s, %s, %s, %s, %s", hostaddr, udi,
+		NP(manufacturer), NP(model), NP(description), NP(serial),
+		NP(uri)));
+
+	if (tmp_udi != NULL)
+		free(tmp_udi);
+	if (manufacturer != NULL)
+		free(manufacturer);
+	if (model != NULL)
+		free(model);
+	if (description != NULL)
+		free(description);
+	if (uri != NULL)
+		free(uri);
+	if (sn != NULL)
+		free(sn);
+
+	if (dbus_error_is_set(&error)) {
+		HAL_WARNING(("%s: %s", error.name, error.message));
+		dbus_error_free(&error);
+	}
+
+	HAL_DEBUG(("add: %s (%s)", hostaddr, udi));
+
+	return (rc);
+}
+
+static int
+number_of_interfaces(int s)
+{
+	int rc = -1;
+	struct lifnum n;
+
+	memset(&n, 0 , sizeof (n));
+	n.lifn_family = AF_UNSPEC;
+	if (ioctl(s, SIOCGLIFNUM, (char *)&n) == 0)
+		rc = n.lifn_count;
+
+	return (rc);
+}
+
+static char *
+broadcast_address(int s, char *ifname)
+{
+	char *result = NULL;
+	struct lifreq r;
+
+	memset(&r, 0, sizeof (r));
+	strncpy((char *)&r.lifr_name, ifname, sizeof (r.lifr_name));
+	if (ioctl(s, SIOCGLIFBRDADDR, (char *)&r) == 0) {
+		char buf[INET6_ADDRSTRLEN];
+
+		switch (r.lifr_broadaddr.ss_family) {
+		case AF_INET: {
+			struct sockaddr_in *s =
+				(struct sockaddr_in *)&r.lifr_broadaddr;
+			result = (char *)inet_ntop(AF_INET, &s->sin_addr,
+							buf, sizeof (buf));
+			}
+			break;
+		case AF_INET6: {
+			struct sockaddr_in6 *s =
+				(struct sockaddr_in6 *)&r.lifr_broadaddr;
+			result = (char *)inet_ntop(AF_INET6, &s->sin6_addr,
+							buf, sizeof (buf));
+			}
+			break;
+		}
+
+		if (result != NULL)
+			result = strdup(result);
+	}
+
+	return (result);
+}
+
+GList *
+broadcast_addresses()
+{
+	GList *result = NULL;
+	int s;
+	struct lifconf c;
+	int count;
+
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		return (NULL);
+
+	count = number_of_interfaces(s);
+
+	memset(&c, 0, sizeof (c));
+	c.lifc_family = AF_UNSPEC;
+	c.lifc_flags = IFF_BROADCAST;
+	c.lifc_buf = calloc(count, sizeof (struct lifreq));
+	c.lifc_len = (count * sizeof (struct lifreq));
+
+	if (ioctl(s, SIOCGLIFCONF, (char *)&c) == 0) {
+		struct lifreq *r = c.lifc_req;
+
+		for (count = c.lifc_len / sizeof (struct lifreq);
+		     count > 0; count--, r++) {
+			char *address = broadcast_address(s, r->lifr_name);
+
+			if (address != NULL) /* add it to the list */
+				result = g_list_append(result, address);
+		}
+	}
+	free(c.lifc_buf);
+	close(s);
+
+	return (result);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/addons/network-devices/network-discovery.h	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifndef NETWORK_DEVICE_COMMON_H
+#define	NETWORK_DEVICE_COMMON_H
+
+#include <libhal.h>
+
+extern void network_device_name_to_udi(char *udi, size_t size, ...);
+extern int add_network_printer(LibHalContext *ctx, char *parent, char *hostaddr,
+			char *device, char *community);
+
+extern gboolean scan_for_devices_using_snmp(LibHalContext *ctx, char *parent,
+		char *community, char *network);
+extern void scan_for_stale_devices(LibHalContext *ctx, time_t timestamp);
+extern gboolean device_seen(char *name);
+
+extern int is_listening(char *hostname, int port);
+
+extern GList *broadcast_addresses();
+
+#endif /* NETWORK_DEVICE_COMMON_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/addons/network-devices/network-discovery.xml	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+	Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+	Use is subject to license terms.
+
+        Licensed under the Academic Free License version 2.1
+
+	ident	"%Z%%M%	%I%	%E% SMI"
+
+	NOTE:  This service manifest is not editable; its contents will
+	be overwritten by package or patch operations, including
+	operating system upgrade.  Make customizations in a different
+	file.
+
+	Service manifest for HAL network attached device discovery.
+-->
+
+<service_bundle type='manifest' name='SUNWhalr:device-discovery'>
+
+<service
+	name='network/device-discovery/printers'
+	type='service'
+	version='1'>
+
+	<dependency name='usr'
+		type='service'
+		grouping='require_all'
+		restart_on='none'>
+		<service_fmri value='svc:/system/filesystem/local' />
+	</dependency>
+
+	<dependency name='network-service'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri value='svc:/network/service' />
+	</dependency>
+
+	<dependency name='dbus'
+		type='service'
+		grouping='require_all'
+		restart_on='none'>
+		<service_fmri value='svc:/system/dbus' />
+	</dependency>
+
+	<dependency name='hal'
+		type='service'
+		grouping='require_all'
+		restart_on='refresh'>
+		<service_fmri value='svc:/system/hal' />
+	</dependency>
+
+	<exec_method
+		type='method'
+		name='start'
+		exec='/lib/svc/method/svc-network-discovery %m %i'
+		timeout_seconds='30'>
+	</exec_method>
+
+	<exec_method
+		type='method'
+		name='stop'
+		exec='/lib/svc/method/svc-network-discovery %m %i'
+		timeout_seconds='30'>
+	</exec_method>
+
+	<exec_method
+		type='method'
+		name='refresh'
+		exec='/lib/svc/method/svc-network-discovery %m %i'
+		timeout_seconds='30'>
+	</exec_method>
+
+	<property_group name='startd' type='framework'>
+		<propval name='duration' type='astring' value='transient' />
+	</property_group>
+
+	<instance
+		name='snmp'
+		enabled='false'>
+
+		<method_context>
+			<method_credential user='root' group='root' />
+		</method_context>
+
+		<property_group name='general' type='framework'>
+			<!-- to start/stop the discovery service -->
+			<propval name='action_authorization' type='astring'
+				value='solaris.smf.manage.discovery.printers.snmp' />
+		</property_group>
+
+		<property_group name='config' type='framework'>
+			<!-- authorization to modify config properties -->
+			<propval name='value_authorization' type='astring'
+				value='solaris.smf.value.discovery.printers.snmp' />
+		</property_group>
+	</instance>
+
+	<stability value='Unstable' />
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+		Hardware Abstraction Layer network attached device discovery
+			</loctext>
+		</common_name>
+	</template>
+</service>
+
+</service_bundle>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/addons/network-devices/snmp.c	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <glib.h>
+
+#include <libhal.h>
+#include <logger.h>
+
+#undef PACKAGE_STRING
+#undef PACKAGE_VERSION
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+
+#include "network-discovery.h"
+#include "printer.h"
+
+#define NP(x)   (x?x:"NULL")
+
+static GList *new_addrs = NULL;
+
+static void
+add_snmp_device(LibHalContext *ctx, char *parent, char *name, char *community)
+{
+	/* most printers listen on the appsocket port (9100) */
+	if (is_listening(name, 9100) == 0) {
+		char device[128];
+
+		snprintf(device, sizeof (device), "socket://%s:9100", name);
+
+		add_network_printer(ctx, parent, name, device, community);
+	}
+
+	/*
+	 * This would be a good place to detect other types of devices or other
+	 * device capabilities.  scanners, removable media, storage, ...
+	 */
+}
+
+static int
+snmp_response_cb(int operation, struct snmp_session *sp, int reqid,
+		struct snmp_pdu *pdu, void *data)
+{
+	struct sockaddr_in *addr = pdu->transport_data;
+	char *name;
+
+	name = inet_ntoa(addr->sin_addr);
+
+	/* have we already seen this network device */
+	if (device_seen(name) == FALSE)
+		new_addrs = g_list_append(new_addrs, strdup(name));
+
+	return (0);
+}
+
+gboolean
+scan_for_devices_using_snmp(LibHalContext *ctx, char *parent, char *community,
+		char *network)
+{
+	struct snmp_session session, *ss;
+	struct snmp_pdu *request = NULL, *response = NULL;
+	oid Oid[MAX_OID_LEN];
+	unsigned int oid_len = MAX_OID_LEN;
+	GList *elem;
+
+	HAL_DEBUG(("scan_for_devices_using_snmp(0x%8.8x, %s, %s, %s)",
+			ctx, NP(parent), NP(community), NP(network)));
+
+	init_snmp("snmp-scan");
+	init_mib();
+
+	/* initialize the SNMP session */
+	snmp_sess_init(&session);
+	session.peername = network;
+	session.community = (uchar_t *)community;
+	session.community_len = strlen((const char *)session.community);
+	session.version = SNMP_VERSION_1;
+
+	if ((ss = snmp_open(&session)) == NULL)
+		return (FALSE);
+
+	/* initialize the request PDU */
+	request = snmp_pdu_create(SNMP_MSG_GET);
+
+	/* add the requested data (everyone should have a sysDescr.0) */
+	if (!read_objid("SNMPv2-MIB::sysDescr.0", Oid, &oid_len))
+		snmp_perror("sysDescr.0");
+	snmp_add_null_var(request, Oid, oid_len);
+
+	snmp_async_send(ss, request, snmp_response_cb, NULL);
+
+	/* detect any new devices */
+	while (1) {
+		int fds = 0, block = 0;
+		fd_set fdset;
+		struct timeval timeout;
+
+		FD_ZERO(&fdset);
+		snmp_select_info(&fds, &fdset, &timeout, &block);
+		fds = select(fds, &fdset, NULL, NULL, block ? NULL : &timeout);
+		if (fds < 0) {
+			perror("select failed");
+			continue;
+		} if (fds == 0) {
+			break;
+		} else {
+			snmp_read(&fdset);
+		}
+	}
+
+	snmp_close(ss);
+
+	/* add the newly detected devices */
+	for (elem = new_addrs; elem != NULL; elem = g_list_next(elem)) {
+		add_snmp_device(ctx, parent, (char *)elem->data, community);
+		free(elem->data);
+	}
+	g_list_free(new_addrs);
+	new_addrs = NULL;
+
+	return (TRUE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/addons/network-devices/svc-network-discovery	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,117 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+
+. /lib/svc/share/smf_include.sh
+
+METHOD=${1}
+INSTANCE=${2}
+
+DBUS_DESTINATION="org.freedesktop.Hal"
+MESSAGE_PREFIX="org.freedesktop.Hal.Device.NetworkDiscovery"
+OBJECT_PATH="/org/freedesktop/Hal/devices/network_attached"
+SMF_PROPERTY_GROUP="config"
+HAL_PROPERTY_GROUP="network_discovery"
+SVCS=/usr/bin/svcs
+
+usage() {
+	echo "Usage: $0 { start | stop | refresh } { snmp }"
+	exit $SMF_EXIT_ERR_FATAL
+}
+
+execute() {
+	echo "$*"
+	$*
+
+	return $?
+}
+
+start_snmp() {
+	interval=`/bin/svcprop -p config/interval ${SMF_FMRI} 2>/dev/null`
+	community=`/bin/svcprop -p config/community ${SMF_FMRI} 2>/dev/null`
+	network=`/bin/svcprop -p config/network ${SMF_FMRI} 2>/dev/null`
+	MESSAGE="${MESSAGE_PREFIX}.EnablePrinterScanningViaSNMP"
+	MESSAGE="${MESSAGE} int32:${interval:-60}"
+	MESSAGE="${MESSAGE} string:${community:-public}"
+	MESSAGE="${MESSAGE} string:${network:-0.0.0.0}"
+
+	execute /usr/bin/dbus-send --system --print-reply \
+		--dest=${DBUS_DESTINATION} --type=method_call ${OBJECT_PATH} \
+		${MESSAGE}
+	return $?
+}
+
+stop_snmp() {
+	MESSAGE="${MESSAGE_PREFIX}.DisablePrinterScanningViaSNMP"
+
+	execute /usr/bin/dbus-send --system --print-reply \
+		--dest=${DBUS_DESTINATION} --type=method_call ${OBJECT_PATH} \
+		${MESSAGE}
+	return $?
+}
+
+refresh_snmp() {
+	community=`/bin/svcprop -p config/community ${SMF_FMRI} 2>/dev/null`
+	network=`/bin/svcprop -p config/network ${SMF_FMRI} 2>/dev/null`
+	MESSAGE="${MESSAGE_PREFIX}.EnablePrinterScanningViaSNMP"
+	MESSAGE="${MESSAGE} string:${community:-public}"
+	MESSAGE="${MESSAGE} string:${network:-0.0.0.0}"
+
+	execute /usr/bin/dbus-send --system --print-reply \
+		--dest=${DBUS_DESTINATION} --type=method_call ${OBJECT_PATH} \
+		${MESSAGE}
+	return $?
+}
+
+case "${METHOD}" in
+	'start')
+		;;
+	'stop')
+		count=`$SVCS -o STATE hal 2>>/dev/null | grep -c "^online"`
+		if [ $count -eq 0 ] ; then
+			exit 0	# if HAL isn't running, there is nothing to do
+		fi
+		;;
+	'refresh')
+		;;
+	*)
+		usage
+		;;
+esac
+
+case "${INSTANCE}" in
+	'snmp')
+		;;
+	*)
+		usage
+		;;
+esac
+
+${METHOD}_${INSTANCE}
+exit_code=$?
+
+exit $exit_code
--- a/usr/src/cmd/hal/fdi/Makefile	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/cmd/hal/fdi/Makefile	Tue Oct 23 07:51:21 2007 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -44,13 +44,15 @@
 		information/10freedesktop/10-wireless-mice.fdi \
 		policy/10osvendor/10-keyboard-policy.fdi \
 		policy/10osvendor/10-laptop-panel-mgmt-policy.fdi \
+		policy/10osvendor/10-network-attached.fdi \
 		policy/10osvendor/10-power-mgmt-policy.fdi \
 		policy/10osvendor/10-toshiba-buttons.fdi \
 		policy/10osvendor/20-storage-methods.fdi \
 		policy/10osvendor/20-zfs-methods.fdi \
 		preprobe/10osvendor/10-ide-drives.fdi \
 		preprobe/10osvendor/20-ignore-fixed-storage.fdi \
-		preprobe/10osvendor/20-ignore-lofi.fdi
+		preprobe/10osvendor/20-ignore-lofi.fdi \
+		preprobe/10osvendor/20-printers.fdi
 FDIDIR =	$(ROOT_HAL_FDI)
 ROOTFDIS =	$(FDIS:%=$(FDIDIR)/%)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/fdi/policy/10osvendor/10-network-attached.fdi	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+  Use is subject to license terms.
+
+  Licensed under the Academic Free License version 2.1
+
+  ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<deviceinfo version="0.2">
+
+  <!--
+	Create a place holder in the HAL device tree for the network attached
+	device discovery service to attach.
+  -->
+  <device>
+    <match key="system.kernel.name" string="SunOS">
+      <spawn udi="/org/freedesktop/Hal/devices/network_attached"/>
+    </match>
+  </device>
+
+  <!--
+	Attach an instance of the network attached device discovery service to
+	the new HAL device tree node.
+  -->
+  <device>
+    <match key="info.udi" string="/org/freedesktop/Hal/devices/network_attached">
+
+      <append key="info.product" type="strlist">Network Attached Devices</append>
+      <append key="info.capabilities" type="strlist">network_device_discovery</append>
+      <append key="info.addons" type="strlist">hald-addon-network-discovery</append>
+      <!--
+        The addon implements the 'org.freedesktop.Hal.Device.NetworkDiscovery'
+        interface.  This interface controls the operation of the addon module.
+      -->
+
+    </match>
+  </device>
+
+</deviceinfo>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/fdi/preprobe/10osvendor/20-printers.fdi	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+  Use is subject to license terms.
+
+  Licensed under the Academic Free License version 2.1
+
+  ident	"%Z%%M%	%I%	%E% SMI"
+-->
+
+<deviceinfo version="0.2">
+
+  <!-- probe network attached printers for information -->
+  <device>
+    <match key="network_device.address" exists="true">
+      <match key="info.capabilities" contains="printer">
+        <append key="info.callouts.add" type="strlist">hald-probe-network-printer</append>
+      </match>
+    </match>
+  </device>
+
+  <!-- probe USB printers for information -->
+  <device>
+    <match key="info.solaris.driver" equals="usbprn">
+      <append key="info.callouts.add" type="strlist">hald-probe-printer</append>
+    </match>
+  </device>
+  
+  <!-- probe ECPP parallel ports for printer information -->
+  <device>
+    <match key="info.solaris.driver" contains="ecpp">
+      <append key="info.callouts.add" type="strlist">hald-probe-printer</append>
+    </match>
+  </device>
+  
+</deviceinfo>
+
--- a/usr/src/cmd/hal/probing/Makefile	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/cmd/hal/probing/Makefile	Tue Oct 23 07:51:21 2007 -0700
@@ -25,7 +25,7 @@
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
 
-SUBDIRS = storage volume printer battery
+SUBDIRS = storage volume printer network-printer battery
 
 all :=		TARGET= all
 install :=	TARGET= install
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/probing/network-printer/Makefile	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,68 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# ident	"%Z%%M%	%I%	%E% SMI"
+#
+
+PROG =		hald-probe-network-printer
+OBJS =		probe-network-printer.o logger.o probe-snmp.o printer.o
+SRCS =		probe-network-printer.c
+
+include ../../../Makefile.cmd
+include ../../Makefile.hal
+
+ROOTCMDDIR =	$(ROOTLIB_HAL)
+
+LDLIBS +=	-lc -ldbus-1 -lhal
+LDLIBS +=	-L$(SFWLIBDIR) -R$(SFWLIBDIR) $(ZIGNORE) -lnetsnmp
+
+CPPFLAGS +=	$(HAL_DBUS_CPPFLAGS) $(HAL_CONFIG_CPPFLAGS)
+CPPFLAGS +=	-I$(ROOT)/usr/include/hal -I../../utils -I../../hald
+CPPFLAGS +=	-I$(SFWINCDIR)
+C99MODE =	$(C99_ENABLE)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+logger.o: ../../hald/logger.c
+	$(COMPILE.c) -o $@ ../../hald/logger.c
+	$(POST_PROCESS_O)
+
+printer.o: ../../utils/printer.c
+	$(COMPILE.c) -o $@ ../../utils/printer.c
+	$(POST_PROCESS_O)
+
+$(PROG): $(OBJS)
+	$(LINK.c) -o $@ $(OBJS) $(LDLIBS)
+	$(POST_PROCESS)
+
+install: all $(ROOTCMD)
+
+clean:
+	$(RM) $(OBJS)
+
+FRC:
+
+include ../../../Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/probing/network-printer/probe-network-printer.c	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,118 @@
+/***************************************************************************
+ *
+ * probe-network-printer.c : Probe for snmp printer device information
+ *
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/prnio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <libhal.h>
+#include <logger.h>
+
+#include "printer.h"
+
+int 
+main(int argc, char *argv[])
+{
+	int ret = 1;
+	char *udi;
+	char *printer_address,
+	     *community;
+	DBusError error;
+	LibHalContext *ctx = NULL;
+	LibHalChangeSet *cs = NULL;
+	char *manufacturer = NULL,
+	     *model = NULL,
+	     *serial_number = NULL,
+	     *description = NULL,
+	     **command_set = NULL,
+	     *device_uri = NULL;
+	extern int snmp_printer_info(char *hostname, char *community,
+			char **manufacturer, char **model, char **description,
+			char **serial_number, char ***command_set,
+			char **device_uri);
+
+	dbus_error_init(&error);
+
+	if ((udi = getenv("UDI")) == NULL)
+		goto out;
+
+	printer_address = getenv("HAL_PROP_NETWORK_DEVICE_ADDRESS");
+	if (printer_address == NULL)
+		goto out;
+
+	community = getenv("HAL_PROP_NETWORK_DEVICE_SNMP_COMMUNITY");
+	if (community == NULL)
+		community = "public";
+
+	setup_logger();
+
+	dbus_error_init(&error);
+
+	if ((ctx = libhal_ctx_init_direct(&error)) == NULL)
+		goto out;
+
+	if ((cs = libhal_device_new_changeset(udi)) == NULL) {
+		HAL_DEBUG(("Cannot allocate changeset"));
+		goto out;
+	}
+
+	/* Probe the printer for characteristics via SNMP */
+	ret = snmp_printer_info(printer_address, community, &manufacturer,
+			&model, &description, &serial_number, &command_set,
+			&device_uri);
+	if (ret < 0) {
+		HAL_DEBUG(("Cannot get snmp data for %s: %s",
+				printer_address, strerror(errno)));
+		goto out;
+	}
+
+	/* Add printer characteristics to the HAL device tree */
+	ret = add_printer_info(cs, udi, manufacturer, model, description,
+			serial_number, command_set, device_uri);
+	if (ret < 0) {
+		HAL_DEBUG(("Cannot add printer data for %s to %s: %s",
+				printer_address, udi, strerror(errno)));
+		goto out;
+	}
+
+	libhal_device_commit_changeset(ctx, cs, &error);
+
+	ret = 0;
+
+out:
+	if (cs != NULL) {
+		libhal_device_free_changeset(cs);
+	}
+
+	if (ctx != NULL) {
+		if (dbus_error_is_set(&error)) {
+			dbus_error_free(&error);
+		}
+		libhal_ctx_shutdown(ctx, &error);
+		libhal_ctx_free(ctx);
+	}
+
+	return (ret);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/probing/network-printer/probe-snmp.c	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,507 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <strings.h>
+
+#undef PACKAGE_STRING
+#undef PACKAGE_VERSION
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+
+#include "logger.h"
+#include "printer.h"
+
+static int
+hrDeviceDesc_to_info(char *string, char **manufacturer, char **model,
+		char **description)
+{
+	int rc = -1;
+	char *s;
+
+	if (string == NULL)
+		return (-1);
+
+	/* if it has : and ; in it, it's probably a 1284 device id */
+	if ((strchr(string, ':') != NULL) && (strchr(string, ';') != NULL)) {
+		rc = ieee1284_devid_to_printer_info(string, manufacturer, model,
+				description, NULL, NULL, NULL);
+	} else {
+		rc = 0;
+		*description = strdup(string);
+		*manufacturer = strdup(string);
+		if ((s = strchr(*manufacturer, ' ')) != NULL) {
+			*s++ = NULL;
+			*model = strdup(s);
+		}
+	}
+
+	return (rc);
+}
+
+static struct snmp_pdu *
+snmp_get_item(char *host, char *community, char *mib_item)
+{
+	int status;
+	struct snmp_session session, *ss;
+	struct snmp_pdu *request = NULL, *result = NULL;
+	oid Oid[MAX_OID_LEN];
+	unsigned int oid_len = MAX_OID_LEN;
+
+	/* initialize the SNMP session */
+	snmp_sess_init(&session);
+	session.peername = host;
+	session.community = (uchar_t *)community;
+	session.community_len = strlen((const char *)session.community);
+	session.version = SNMP_VERSION_1;
+	session.retries = 0;
+
+	if ((ss = snmp_open(&session)) == NULL)
+		return (NULL);
+
+	/* add the requested data */
+	if (!read_objid(mib_item, Oid, &oid_len))
+		snmp_perror(mib_item);
+
+	/* initialize the request PDU */
+	request = snmp_pdu_create(SNMP_MSG_GET);
+	snmp_add_null_var(request, Oid, oid_len);
+
+	status = snmp_synch_response(ss, request, &result);
+
+	snmp_close(ss);
+
+	return (result);
+}
+
+static char *
+snmp_get_string(char *host, char *community, char *mib_item)
+{
+	char *result = NULL;
+	struct snmp_pdu *response = NULL;
+
+	response = snmp_get_item(host, community, mib_item);
+
+	if ((response != NULL) && (response->errstat == SNMP_ERR_NOERROR)) {
+		struct variable_list *v = response->variables;
+
+		if (v->type == ASN_OCTET_STR) {
+			result = calloc(1, v->val_len + 1);
+			memcpy(result, v->val.string, v->val_len);
+		}
+	}
+
+	HAL_DEBUG(("snmp_get_string(%s, %s, %s): %s", host, community, mib_item,
+		(result?result:"NULL")));
+
+	if (response != NULL)
+		snmp_free_pdu(response);
+
+	return (result);
+}
+
+static int
+snmp_brother_printer_info(char *hostname, char *community, char **manufacturer,
+		char **model, char **description, char **serial_no,
+		char ***command_set)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	/*
+	 * Brother printers appear to store
+	 *	1284 DevID	SNMPv2-SMI::enterprises.2435.2.3.9.1.1.7.0
+	 *	Serial Number	SNMPv2-SMI::enterprises.2435.2.3.9.4.2.1.5.5.1.0
+	 */
+	tmp = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.2435.2.3.9.1.1.7.0");
+	if (tmp != NULL) {
+		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
+				description, NULL, serial_no, command_set);
+		free(tmp);
+
+		if (*serial_no == NULL)
+			*serial_no = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::enterprises.2435.2.3.9.4.2.1.5.5.1.0");
+	}
+
+	return (rc);
+}
+
+static int
+snmp_ricoh_printer_info(char *hostname, char *community, char **manufacturer,
+		char **model, char **description, char **serial_no,
+		char ***command_set)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	/*
+	 * OKI printers appear to store
+	 *	1284 DevID	SNMPv2-SMI::enterprises.367.3.2.1.1.1.11.0
+	 *	Serial Number	SNMPv2-SMI::enterprises.367.3.2.1.2.1.4.0
+	 */
+	tmp = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.367.3.2.1.1.1.11.0");
+	if (tmp != NULL) {
+		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
+				description, NULL, serial_no, command_set);
+		free(tmp);
+
+		if (*serial_no == NULL)
+			*serial_no = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::enterprises.367.3.2.1.2.1.4.0");
+	}
+
+	return (rc);
+}
+
+static int
+snmp_lexmark_printer_info(char *hostname, char *community, char **manufacturer,
+		char **model, char **description, char **serial_no,
+		char ***command_set)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	/*
+	 * Lexmark printers appear to store
+	 *	1284 DevID	SNMPv2-SMI::enterprises.641.2.1.2.1.3.1
+	 *	Serial Number	SNMPv2-SMI::enterprises.641.2.1.2.1.6.1
+	 */
+	tmp = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.641.2.1.2.1.3.1");
+	if (tmp != NULL) {
+		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
+				description, NULL, serial_no, command_set);
+		free(tmp);
+
+		if (*serial_no == NULL)
+			*serial_no = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::enterprises.641.2.1.2.1.6.1");
+	}
+
+	return (rc);
+}
+
+static int
+snmp_xerox_phaser_printer_info(char *hostname, char *community,
+		char **manufacturer, char **model, char **description,
+		char **serial_no, char ***command_set, char **uri)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	/*
+	 * Xerox Phaser XXXX printers store their
+	 *	1284 DevID	SNMPv2-SMI::enterprises.253.8.51.1.2.1.20.1
+	 *	Manufacturer:
+	 *			SNMPv2-SMI::enterprises.128.2.1.3.1.1.0
+	 *			SNMPv2-SMI::enterprises.23.2.32.3.2.1.10.1.16
+	 *			SNMPv2-SMI::enterprises.23.2.32.4.1.0
+	 *	Model:
+	 *			SNMPv2-SMI::enterprises.128.2.1.3.1.2.0
+	 *			SNMPv2-SMI::enterprises.23.2.32.3.2.1.10.1.17
+	 *			SNMPv2-SMI::enterprises.23.2.32.4.2.0
+	 *	Description	SNMPv2-SMI::enterprises.253.8.53.3.2.1.2.1
+	 *	Serial Number	SNMPv2-SMI::enterprises.253.8.53.3.2.1.3.1
+	 *	Uri		SNMPv2-SMI::enterprises.128.2.1.3.6.23.1.5.1
+	 */
+
+	tmp = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.253.8.51.1.2.1.20.1");
+	if (tmp != NULL) {
+		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
+				description, NULL, serial_no, command_set);
+		free(tmp);
+	}
+
+	if (*manufacturer == NULL)
+		*manufacturer = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.128.2.1.3.1.1.0");
+	if (*manufacturer == NULL)
+		*manufacturer = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.23.2.32.3.2.1.10.1.16");
+	if (*manufacturer == NULL)
+		*manufacturer = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.23.2.32.4.1.0");
+
+	if (*model == NULL)
+		*model = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.128.2.1.3.1.2.0");
+	if (*model == NULL)
+		*model = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.23.2.32.3.2.1.10.1.17");
+	if (*model == NULL)
+		*model = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.23.2.32.4.2.0");
+
+	if (*serial_no == NULL)
+		*serial_no = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.253.8.53.3.2.1.3.1");
+
+	if ((*manufacturer != NULL) && (*model != NULL))
+		rc = 0;
+
+	return (rc);
+}
+
+static int
+snmp_qms_printer_info(char *hostname, char *community, char **manufacturer,
+		char **model, char **description, char **serial_no,
+		char ***command_set, char **uri)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	/*
+	 * MINOLTA-QMS printers appear to store
+	 *	Prouct Name	SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.1.1.16.1
+	 *	Serial Number	SNMPv2-SMI::enterprises.2590.1.1.1.5.5.1.1.3.2
+	 *	URI		SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.2.1.3.1.1
+	 *			SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.2.1.3.1.2
+	 */
+	tmp = snmp_get_string(hostname, community,
+		"SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.1.1.16.1");
+	if (tmp != NULL) {
+		rc = hrDeviceDesc_to_info(tmp, manufacturer, model,
+					description);
+		free(tmp);
+
+		if (*serial_no == NULL)
+			*serial_no = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::enterprises.2590.1.1.1.5.5.1.1.3.2");
+		tmp = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.2.1.3.1.2");
+		if (tmp == NULL)
+			tmp = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::enterprises.2590.1.1.2.1.5.7.14.2.2.1.3.1.1");
+		if (tmp != NULL)
+			*uri = tmp;
+	}
+
+	return (rc);
+}
+
+static int
+snmp_oki_printer_info(char *hostname, char *community, char **manufacturer,
+		char **model, char **description, char **serial_no,
+		char ***command_set)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	/*
+	 * OKI printers appear to store
+	 *	Prouct Name	SNMPv2-SMI::enterprises.2001.1.2.683.1.3
+	 *	Serial Number	SNMPv2-SMI::enterprises.2001.1.2.683.1.5
+	 */
+	tmp = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.2001.1.2.683.1.3");
+	if (tmp != NULL) {
+		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
+				description, NULL, serial_no, command_set);
+		free(tmp);
+
+		if (*serial_no == NULL)
+			*serial_no = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::enterprises.2001.1.2.683.1.5");
+	}
+
+	return (rc);
+}
+
+static int
+snmp_hp_printer_info(char *hostname, char *community, char **manufacturer,
+		char **model, char **description, char **serial_no,
+		char ***command_set)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	/*
+	 * HP printers appear to store
+	 *	1284 DevID	SNMPv2-SMI::enterprises.11.2.3.9.1.1.7.0
+	 *	Serial Number	SNMPv2-SMI::enterprises.2.3.9.4.2.2.5.1.1.17
+	 */
+	tmp = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.11.2.3.9.1.1.7.0");
+	if (tmp != NULL) {
+		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
+				description, NULL, serial_no, command_set);
+		free(tmp);
+
+		if (*serial_no == NULL)
+			*serial_no = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::enterprises.2.3.9.4.2.2.5.1.1.17");
+	}
+
+	return (rc);
+}
+
+static int
+snmp_ppm_printer_info(char *hostname, char *community, char **manufacturer,
+		char **model, char **description, char **serial_no,
+		char ***command_set)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	/*
+	 * The PWG portMon MIB stores
+	 *	1284 DevID	SNMPv2-SMI::enterprises.2699.1.2.1.1.1.3`
+	 */
+	tmp = snmp_get_string(hostname, community,
+			"SNMPv2-SMI::enterprises.2699.1.2.1.1.1.3");
+	if (tmp != NULL) {
+		rc = ieee1284_devid_to_printer_info(tmp, manufacturer, model,
+				description, NULL, serial_no, command_set);
+		free(tmp);
+	}
+
+	return (rc);
+}
+
+static int
+snmp_prt_printer_info(char *hostname, char *community, char **manufacturer,
+		char **model, char **description, char **serial_no,
+		char ***command_set)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	/*
+	 * The Printer Printer MIB stores
+	 *	Vendor	 SNMPv2-SMI::mib-2.43.8.2.1.14.1.1
+	 *	Model	 SNMPv2-SMI::mib-2.43.8.2.1.15.1.1
+	 *	Serial	 SNMPv2-SMI::mib-2.43.8.2.1.17.1.1
+	 */
+
+	if (*manufacturer == NULL)
+		*manufacturer = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::mib-2.43.8.2.1.14.1.1");
+	if (*model == NULL)
+		*model = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::mib-2.43.8.2.1.15.1.1");
+	if (*serial_no == NULL)
+		*serial_no = snmp_get_string(hostname, community,
+				"SNMPv2-SMI::mib-2.43.8.2.1.17.1.1");
+
+	if (*manufacturer != NULL)
+		rc = 0;
+
+	return (rc);
+}
+
+static int
+snmp_host_resource_printer_info(char *hostname, char *community,
+		char **manufacturer, char **model, char **description,
+		char **serial_no, char ***command_set)
+{
+	int rc = -1;
+	char *tmp = NULL;
+
+	tmp = snmp_get_string(hostname, community,
+			"HOST-RESOURCES-MIB::hrDeviceDescr.1");
+	if (tmp != NULL) {
+		rc = hrDeviceDesc_to_info(tmp, manufacturer, model,
+					description);
+		free(tmp);
+	}
+
+	return (rc);
+}
+
+int
+snmp_printer_info(char *hostname, char *community, char **manufacturer,
+		char **model, char **description, char **serial_no,
+		char ***command_set, char **uri)
+{
+	char *tmp = NULL;
+
+	init_snmp("network-printer-probe");
+	init_mib();
+
+	if (snmp_brother_printer_info(hostname, community, manufacturer, model,
+			description, serial_no, command_set) == 0) {
+		return (0);
+	} else if (snmp_ricoh_printer_info(hostname, community, manufacturer,
+			model, description, serial_no, command_set) == 0) {
+		return (0);
+	} else if (snmp_lexmark_printer_info(hostname, community, manufacturer,
+			model, description, serial_no, command_set) == 0) {
+		return (0);
+	} else if (snmp_xerox_phaser_printer_info(hostname, community,
+			manufacturer, model, description, serial_no,
+			command_set, uri) == 0) {
+		return (0);
+	} else if (snmp_qms_printer_info(hostname, community, manufacturer,
+			model, description, serial_no, command_set, uri) == 0) {
+		return (0);
+	} else if (snmp_oki_printer_info(hostname, community, manufacturer,
+			model, description, serial_no, command_set) == 0) {
+		return (0);
+	} else if (snmp_hp_printer_info(hostname, community, manufacturer,
+			model, description, serial_no, command_set) == 0) {
+		return (0);
+	} else if (snmp_ppm_printer_info(hostname, community, manufacturer,
+			model, description, serial_no, command_set) == 0) {
+		return (0);
+	} else if (snmp_prt_printer_info(hostname, community, manufacturer,
+			model, description, serial_no, command_set) == 0) {
+		return (0);
+	} else if (snmp_host_resource_printer_info(hostname, community,
+			manufacturer, model, description, serial_no,
+			command_set) == 0) {
+		return (0);
+	}
+
+	return (-1);
+}
+
+#ifdef NOTDEF
+
+#define	NP(x)	(x?x:"")
+
+int
+main(int ac, char *av[])
+{
+	int i;
+
+	for (i = 1; av[i] != NULL; i++) {
+		char *hostname = av[i], *manufacturer = NULL, *model = NULL,
+		     *description = NULL, *serial_no = NULL,
+		     **command_set = NULL, *uri = NULL;
+		int rc;
+
+		rc = snmp_printer_info(hostname, &manufacturer, &model,
+				&description, &serial_no, &command_set, &uri);
+		printf("SNMP data for %s...(%d)\n", hostname, rc);
+		printf("\tvendor = %s\n", NP(manufacturer));
+		printf("\tproduct = %s\n", NP(model));
+		printf("\tdescription = %s\n", NP(description));
+		printf("\tserial = %s\n", NP(serial_no));
+		printf("\tdevice = %s\n", NP(uri));
+
+		if (command_set != NULL) {
+			int j;
+
+			printf("\tcommand set = \n");
+			for (j = 0; command_set[j] != NULL; j++)
+				printf("\t\t%s\n", command_set[j]);
+		}
+	}
+
+	return (0);
+}
+#endif
--- a/usr/src/cmd/hal/probing/printer/Makefile	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/cmd/hal/probing/printer/Makefile	Tue Oct 23 07:51:21 2007 -0700
@@ -26,7 +26,7 @@
 #
 
 PROG =		hald-probe-printer
-OBJS =		probe-printer.o logger.o
+OBJS =		probe-printer.o logger.o printer.o
 SRCS =		probe-printer.c
 
 include ../../../Makefile.cmd
@@ -48,6 +48,10 @@
 	$(COMPILE.c) -o $@ ../../hald/logger.c
 	$(POST_PROCESS_O)
 
+printer.o: ../../utils/printer.c
+	$(COMPILE.c) -o $@ ../../utils/printer.c
+	$(POST_PROCESS_O)
+
 $(PROG): $(OBJS)
 	$(LINK.c) -o $@ $(OBJS) $(LDLIBS)
 	$(POST_PROCESS)
--- a/usr/src/cmd/hal/probing/printer/probe-printer.c	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/cmd/hal/probing/printer/probe-printer.c	Tue Oct 23 07:51:21 2007 -0700
@@ -12,7 +12,7 @@
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #ifdef HAVE_CONFIG_H
-#  include <config.h>
+#include <config.h>
 #endif
 
 #include <errno.h>
@@ -21,6 +21,9 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <dirent.h>
 #include <sys/ioctl.h>
 #include <sys/prnio.h>
 #include <fcntl.h>
@@ -30,155 +33,142 @@
 #include <libhal.h>
 #include <logger.h>
 
-#define	NELEM(a)	(sizeof (a) / sizeof (*(a)))
-
-static char *
-strip_ws(char *s)
-{
-	if (s != NULL) {
-		char *p;
-
-		/* skip the leading whitespace */
-		for (; ((*s != NULL) && (isspace(*s) != 0)); s++) ;
-
-		/* drop the trailing whitespace */
-		for (p = s + strlen(s) - 1; ((p > s) && (isspace(*p) != 0));
-		     p--) ;
-		*(++p) = '\0';
-	}
-
-	return (s);
-}
+#include "printer.h"
 
 static int
-get_prnio_data(int fd, LibHalChangeSet *cs)
+prnio_printer_info(char *device_file, char **manufacturer, char **model,
+		char **description, char **serial_number, char ***command_set)
 {
 	struct prn_1284_device_id id;
 	char buf[BUFSIZ];
-	char *s, *iter = NULL;
+	int fd = -1, rc = -1;
 
 	memset(&id, 0, sizeof (id));
 	memset(&buf, 0, sizeof (buf));
 	id.id_data = buf;
 	id.id_len = sizeof (buf);
 
+	if ((fd = open (device_file, O_RDONLY | O_NONBLOCK)) < 0) {
+		goto prnio_out;
+	}
+
 	if (ioctl(fd, PRNIOC_GET_1284_DEVID, &id) < 0) {
-		return (-1);
+		goto prnio_out;
 	}
 
-	HAL_DEBUG (("IEEE-1284 DeviceId = %s", buf));
+	HAL_DEBUG(("IEEE-1284 DeviceId = %s", buf));
 
-	for (s = strtok_r(buf, ";\n", &iter); s != NULL;
-	     s = strtok_r(NULL, ";\n", &iter)) {
-		char *t, *u, *iter2 = NULL;
+	rc = ieee1284_devid_to_printer_info(buf, manufacturer, model,
+			description, NULL, serial_number, command_set);
 
-		if ((t = strtok_r(s, ":\n", &iter2)) == NULL) {
-			continue;
-		}
+prnio_out:
+	if (fd != -1)
+		close(fd);
 
-		if ((u = strtok_r(NULL, ":\n", &iter2)) == NULL) {
-			continue;
-		}
+	return (rc);
+}
 
-		if ((strcasecmp(t, "MFG") == 0) ||
-		    (strcasecmp(t, "MANUFACTURER") == 0)) {
-			libhal_changeset_set_property_string (cs,
-					"printer.vendor", strip_ws(u));
-		} else if ((strcasecmp(t, "MDL") == 0) ||
-		    (strcasecmp(t, "MODEL") == 0)) {
-			libhal_changeset_set_property_string (cs,
-					"printer.product", strip_ws(u));
-		} else if ((strcasecmp(t, "SN") == 0) ||
-		    (strcasecmp(t, "SERN") == 0) ||
-		    (strcasecmp(t, "SERIALNUMBER") == 0)) {
-			libhal_changeset_set_property_string (cs,
-					"printer.serial", strip_ws(u));
-		} else if ((strcasecmp(t, "DES") == 0) ||
-		    (strcasecmp(t, "DESCRIPTION") == 0)) {
-			libhal_changeset_set_property_string (cs,
-					"printer.description", strip_ws(u));
-		} else if ((strcasecmp(t, "CMD") == 0) ||
-		    (strcasecmp(t, "COMMAND SET") == 0) ||
-		    (strcasecmp(t, "COMMANDSET") == 0)) {
-			char *v, *iter3 = NULL;
-			const char *cmds[32];
-			int i = 0;
+/*
+ * It is assumed that all devices that support prnio(7i), also have a link
+ * in /dev/printers.  
+ */
+static char *
+prnio_device_name(void)
+{
+	char *result = NULL;
+	char *devfs_path;
+	DIR *dp;
 
-			memset(&cmds, 0, sizeof (cmds));
-			for (v = strtok_r(u, ",\n", &iter3);
-			     ((v != NULL) && (i < NELEM(cmds)));
-			     v = strtok_r(NULL, ",\n", &iter3)) {
-				cmds[i++] = strip_ws(v);
+	if (((devfs_path = getenv("HAL_PROP_SOLARIS_DEVFS_PATH")) != NULL) &&
+	    ((dp = opendir("/dev/printers")) != NULL)) {
+		struct dirent *ep;
+
+		while ((ep = readdir(dp)) != NULL) {
+			char path[MAXPATHLEN], lpath[MAXPATHLEN];
+
+			snprintf(path, sizeof (path), "/dev/printers/%s",
+					ep->d_name);
+			memset(lpath, 0, sizeof (lpath));
+			if ((readlink(path, lpath, sizeof (lpath)) > 0) &&
+			    (strstr(lpath, devfs_path) != NULL)) {
+				result = strdup(path);
+				break;
 			}
-
-			libhal_changeset_set_property_strlist(cs,
-					"printer.commandset", cmds);
 		}
+		closedir(dp);
 	}
 
-	return (0);
+	return (result);
 }
 
-int 
-main (int argc, char *argv[])
+int
+main(int argc, char *argv[])
 {
 	int ret = 1;
-	int fd = -1;
 	char *udi;
 	char *device_file;
+	char *manufacturer = NULL,
+	     *model = NULL,
+	     *serial_number = NULL,
+	     *description = NULL,
+	     **command_set = NULL;
 	DBusError error;
 	LibHalContext *ctx = NULL;
 	LibHalChangeSet *cs = NULL;
 
-	if ((udi = getenv ("UDI")) == NULL)
+	if ((udi = getenv("UDI")) == NULL)
 		goto out;
-	if ((device_file = getenv ("HAL_PROP_PRINTER_DEVICE")) == NULL)
+	if ((device_file = getenv("HAL_PROP_PRINTER_DEVICE")) == NULL)
+		device_file = prnio_device_name();
+
+	if (device_file == NULL)
 		goto out;
 
-	setup_logger ();
+	setup_logger();
 
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+	dbus_error_init(&error);
+	if ((ctx = libhal_ctx_init_direct(&error)) == NULL)
 		goto out;
 
-	if ((cs = libhal_device_new_changeset (udi)) == NULL) {
-		HAL_DEBUG (("Cannot allocate changeset"));
+	if ((cs = libhal_device_new_changeset(udi)) == NULL) {
+		HAL_DEBUG(("Cannot allocate changeset"));
 		goto out;
 	}
 
-	HAL_DEBUG (("Doing probe-printer for %s (udi=%s)", 
-	     device_file, udi));
-
-	if ((fd = open (device_file, O_RDONLY | O_NONBLOCK)) < 0) {
-		HAL_DEBUG (("Cannot open %s: %s", device_file, strerror (errno)));
+	/* Probe the printer for characteristics via prnio(7i) */
+	ret = prnio_printer_info(device_file, &manufacturer, &model,
+			&description, &serial_number, &command_set);
+	if (ret < 0) {
+		HAL_DEBUG(("Cannot get prnio data for %s: %s",
+				device_file, strerror(errno)));
 		goto out;
 	}
 
-	if (get_prnio_data(fd, cs) < 0) {
-		HAL_DEBUG (("Cannot get prnio data %s: %s", device_file, strerror (errno)));
+	/* Add printer characteristics to the HAL device tree */
+	ret = add_printer_info(cs, udi, manufacturer, model, description,
+			serial_number, command_set, device_file);
+	if (ret < 0) {
+		HAL_DEBUG(("Cannot add printer data for %s to %s: %s",
+				device_file, udi, strerror(errno)));
 		goto out;
 	}
 
-	libhal_device_commit_changeset (ctx, cs, &error);
+	libhal_device_commit_changeset(ctx, cs, &error);
 
 	ret = 0;
 
 out:
 	if (cs != NULL) {
-		libhal_device_free_changeset (cs);
-	}
-
-	if (fd >= 0) {
-		close (fd);
+		libhal_device_free_changeset(cs);
 	}
 
 	if (ctx != NULL) {
 		if (dbus_error_is_set(&error)) {
-			dbus_error_free (&error);
+			dbus_error_free(&error);
 		}
-		libhal_ctx_shutdown (ctx, &error);
-		libhal_ctx_free (ctx);
+		libhal_ctx_shutdown(ctx, &error);
+		libhal_ctx_free(ctx);
 	}
 
-	return ret;
+	return (ret);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/utils/printer.c	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <strings.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <libhal.h>
+#include <logger.h>
+
+#include "printer.h"
+
+static char *
+strip_ws(char *s)
+{
+	if (s != NULL) {
+		char *p;
+
+		/* skip the leading whitespace */
+		for (; ((*s != NULL) && (isspace(*s) != 0)); s++);
+
+		/* drop the trailing whitespace */
+		for (p = s + strlen(s) - 1; ((p > s) && (isspace(*p) != 0));
+		     p--);
+		*(++p) = '\0';
+	}
+
+	return (s);
+}
+
+int
+ieee1284_devid_to_printer_info(char *devid_string, char **manufacturer,
+		char **model, char **description, char **class,
+		char **serial_no, char ***command_set)
+{
+	char *iter = NULL;
+	char *s;
+
+	if (devid_string == NULL)
+		return (-1);
+
+	/* parse the 1284 device id string */
+	for (s = (char *)strtok_r(devid_string, ";\n", &iter); s != NULL;
+			s = (char *)strtok_r(NULL, ";\n", &iter)) {
+		char *t, *u, *iter2 = NULL;
+
+		if ((t = (char *)strtok_r(s, ":\n", &iter2)) == NULL)
+			continue;
+
+		if ((u = (char *)strtok_r(NULL, ":\n", &iter2)) == NULL)
+			continue;
+
+		if (((strcasecmp(t, "MFG") == 0) ||
+		     (strcasecmp(t, "MANUFACTURER") == 0)) &&
+		    (manufacturer != NULL))
+				*manufacturer = strdup(strip_ws(u));
+		else if (((strcasecmp(t, "MDL") == 0) ||
+			  (strcasecmp(t, "MODEL") == 0)) &&
+			 (model != NULL))
+				*model = strdup(strip_ws(u));
+		else if (((strcasecmp(t, "DES") == 0) ||
+			  (strcasecmp(t, "DESCRIPTION") == 0)) &&
+			 (description != NULL))
+				*description = strdup(strip_ws(u));
+		else if (((strcasecmp(t, "CLS") == 0) ||
+			  (strcasecmp(t, "CLASS") == 0)) &&
+			 (class != NULL))
+				*class = strdup(strip_ws(u));
+		else if (((strcasecmp(t, "SER") == 0) ||
+			  (strcasecmp(t, "SERNO") == 0)) &&
+			 (serial_no != NULL))
+				*serial_no = strdup(strip_ws(u));
+		else if (((strcasecmp(t, "CMD") == 0) ||
+			  (strcasecmp(t, "COMMAND SET") == 0)) &&
+			 (command_set != NULL)) {
+			/* this should be more dynamic, I got lazy */
+			char *v, *iter3 = NULL;
+			char *cmds[32];
+			int i = 0;
+
+			memset(&cmds, 0, sizeof (cmds));
+#define	NELEM(a)	(sizeof (a) / sizeof (*(a)))
+			for (v = strtok_r(u, ",\n", &iter3);
+			     ((v != NULL) && (i < NELEM(cmds)));
+			     v = strtok_r(NULL, ",\n", &iter3)) {
+				cmds[i++] = strdup(strip_ws(v));
+			}
+#undef NELEM
+			*command_set = calloc(++i, sizeof (char *));
+			for (i = 0; (cmds)[i] != NULL; i++)
+				(*command_set)[i] = cmds[i];
+		}
+	}
+
+	return (0);
+}
+
+
+int
+add_printer_info(LibHalChangeSet *cs, char *udi, char *manufacturer,
+		char *model, char *description, char *serial_number,
+		char **command_set, char *device)
+{
+#define	NP(x)   (x?x:"")
+	HAL_DEBUG(("udi: %s, snmp data: vendor=%s, product=%s, "
+		    "description=%s, serial=%s, device=%s\n",
+		    NP(udi), NP(manufacturer), NP(model), NP(description),
+		    NP(serial_number), NP(device)));
+#undef NP
+
+	if (model != NULL)
+		libhal_changeset_set_property_string(cs,
+					"info.product", model);
+	if (manufacturer != NULL)
+		libhal_changeset_set_property_string(cs,
+					"printer.vendor", manufacturer);
+	if (model != NULL)
+		libhal_changeset_set_property_string(cs,
+					"printer.product", model);
+	if (serial_number != NULL)
+		libhal_changeset_set_property_string(cs,
+					"printer.serial", serial_number);
+	if (description != NULL)
+		libhal_changeset_set_property_string(cs,
+					"printer.description", description);
+	if (command_set != NULL)
+		libhal_changeset_set_property_strlist(cs, "printer.commandset",
+					(const char **)command_set);
+	if (device != NULL)
+		libhal_changeset_set_property_string(cs,
+					"printer.device", device);
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/hal/utils/printer.h	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifndef _PRINTER_H
+#define	_PRINTER_H
+
+#include <libhal.h>
+
+extern int ieee1284_devid_to_printer_info(char *devid_string,
+		char **manufacturer, char **model, char **description,
+		char **class, char **serial_no, char ***command_set);
+
+extern int add_printer_info(LibHalChangeSet *cs, char *udi, char *manufacturer,
+		char *model, char *serial_number, char *description,
+		char **command_set, char *device);
+
+#endif /* _PRINTER_H */
--- a/usr/src/lib/libsecdb/auth_attr.txt	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/lib/libsecdb/auth_attr.txt	Tue Oct 23 07:51:21 2007 -0700
@@ -111,6 +111,7 @@
 solaris.smf.manage.autofs:::Manage Automount Service States::help=SmfAutofsStates.html
 solaris.smf.manage.bind:::Manage DNS Service States::help=BindStates.html
 solaris.smf.manage.cron:::Manage Cron Service States::help=SmfCronStates.html
+solaris.smf.manage.discover.printers.snmp:::Manage Network Attached Device Discovery Service States::help=SmfNADDStates.html
 solaris.smf.manage.hal:::Manage HAL Service States::help=SmfHALStates.html
 solaris.smf.manage.idmap:::Manage Identity Mapping Service States::help=SmfIdmapStates.html
 solaris.smf.manage.inetd:::Manage inetd and inetd managed services States::help=SmfIntedStates.html
@@ -130,6 +131,7 @@
 solaris.smf.manage.tnd:::Manage Trusted Network Daemon::help=TNDaemon.html
 solaris.smf.manage.wpa:::Manage WPA Service States::help=SmfWpaStates.html
 solaris.smf.value.:::Change Values of SMF Service Properties::help=SmfValueHeader.html
+solaris.smf.value.discover.printers.snmp:::Manage Network Attached Device Discovery Service Properties::help=SmfValueNADD.html
 solaris.smf.value.idmap:::Change Values of SMF Identity Mapping Service Properties::help=SmfValueIdmap.html
 solaris.smf.value.inetd:::Change values of SMF Inetd configuration paramaters::help=SmfValueInted.html
 solaris.smf.value.ipsec:::Change Values of SMF IPsec Properties::help=SmfValueIPsec.html
--- a/usr/src/lib/libsecdb/help/auths/Makefile	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/lib/libsecdb/help/auths/Makefile	Tue Oct 23 07:51:21 2007 -0700
@@ -78,6 +78,7 @@
 	SmfModifyHeader.html \
 	SmfModifyMethod.html \
 	SmfNscdStates.html \
+	SmfNADDStates.html \
 	SmfNWAMStates.html \
 	SmfPowerStates.html \
 	SmfRoutingStates.html \
@@ -89,6 +90,7 @@
 	SmfValueIPsec.html \
 	SmfValueIscsitgt.html \
 	SmfValueMDNS.html \
+	SmfValueNADD.html \
 	SmfValueNWAM.html \
 	SmfValueRouting.html \
 	SmfWpaStates.html \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsecdb/help/auths/SmfNADDStates.html	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,40 @@
+<HTML>
+<!--
+    CDDL HEADER START
+
+    The contents of this file are subject to the terms of the
+    Common Development and Distribution License (the "License").
+    You may not use this file except in compliance with the License.
+
+    You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+    or http://www.opensolaris.org/os/licensing.
+    See the License for the specific language governing permissions
+    and limitations under the License.
+
+    When distributing Covered Code, include this CDDL HEADER in each
+    file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+    If applicable, add the following below this CDDL HEADER, with the
+    fields enclosed by brackets "[]" replaced with your own identifying
+    information: Portions Copyright [yyyy] [name of copyright owner]
+
+    CDDL HEADER END
+
+Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+Use is subject to license terms.
+-->
+<!-- SCCS keyword
+#ident	"%Z%%M%	%I%	%E% SMI"
+-->
+<!--
+   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+-->
+<BODY>
+When Manage Network Device Discovery Service States is in the Authorizations
+Include column, it grants the authorization to enable, disable, or restart
+the Network Attached Device Discovery services.
+<p>
+If Manage Network DeviceDiscovery Service States is grayed, then you are not entitled
+to Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsecdb/help/auths/SmfValueNADD.html	Tue Oct 23 07:51:21 2007 -0700
@@ -0,0 +1,40 @@
+<HTML>
+<!--
+    CDDL HEADER START
+
+    The contents of this file are subject to the terms of the
+    Common Development and Distribution License (the "License").
+    You may not use this file except in compliance with the License.
+
+    You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+    or http://www.opensolaris.org/os/licensing.
+    See the License for the specific language governing permissions
+    and limitations under the License.
+
+    When distributing Covered Code, include this CDDL HEADER in each
+    file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+    If applicable, add the following below this CDDL HEADER, with the
+    fields enclosed by brackets "[]" replaced with your own identifying
+    information: Portions Copyright [yyyy] [name of copyright owner]
+
+    CDDL HEADER END
+
+Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+Use is subject to license terms.
+-->
+<!-- SCCS keyword
+#ident	"%Z%%M%	%I%	%E% SMI"
+-->
+<!--
+   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+-->
+<BODY>
+When Value Network Attached Device Discovery Properties is in the Authorizations
+Include column, it grants the the authorization to change Network Attached
+Device Discovery service property values.
+<P> 
+If Value Network Attached Device Discovery Properties is grayed, then you are
+not entitled to Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
--- a/usr/src/lib/libsecdb/prof_attr.txt	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/lib/libsecdb/prof_attr.txt	Tue Oct 23 07:51:21 2007 -0700
@@ -36,7 +36,7 @@
 Audit Review:::Review BSM auditing logs:auths=solaris.audit.read;help=RtAuditReview.html
 Contract Observer:::Reliably observe any/all contract events:help=RtContractObserver.html
 Device Management:::Control Access to Removable Media:auths=solaris.device.*;help=RtDeviceMngmnt.html
-Printer Management:::Manage printers, daemons, spooling:auths=solaris.print.*,solaris.label.print;help=RtPrntAdmin.html
+Printer Management:::Manage printers, daemons, spooling:auths=solaris.print.*,solaris.label.print,solaris.smf.manage.discovery.printers.*,solaris.smf.value.discovery.printers.*;help=RtPrntAdmin.html
 Cron Management:::Manage at and cron jobs:auths=solaris.jobs.*,solaris.smf.manage.cron;help=RtCronMngmnt.html
 Log Management:::Manage log files:help=RtLogMngmnt.html
 Basic Solaris User:::Automatically assigned rights:auths=solaris.profmgr.read,solaris.jobs.user,solaris.mail.mailq,solaris.device.mount.removable;profiles=All;help=RtDefault.html
--- a/usr/src/pkgdefs/SUNW0on/prototype_com	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNW0on/prototype_com	Tue Oct 23 07:51:21 2007 -0700
@@ -251,6 +251,7 @@
 f none usr/lib/help/auths/locale/SmfModifyMethod.html 444 root bin
 f none usr/lib/help/auths/locale/SmfIPsecStates.html 444 root bin
 f none usr/lib/help/auths/locale/SmfNscdStates.html 444 root bin
+f none usr/lib/help/auths/locale/SmfNADDStates.html 444 root bin
 f none usr/lib/help/auths/locale/SmfNWAMStates.html 444 root bin
 f none usr/lib/help/auths/locale/SmfPowerStates.html 444 root bin
 f none usr/lib/help/auths/locale/SmfRoutingStates.html 444 root bin
@@ -262,6 +263,7 @@
 f none usr/lib/help/auths/locale/SmfValueIPsec.html 444 root bin
 f none usr/lib/help/auths/locale/SmfValueIscsitgt.html 444 root bin
 f none usr/lib/help/auths/locale/SmfValueMDNS.html 444 root bin
+f none usr/lib/help/auths/locale/SmfValueNADD.html 444 root bin
 f none usr/lib/help/auths/locale/SmfValueNWAM.html 444 root bin
 f none usr/lib/help/auths/locale/SmfValueRouting.html 444 root bin
 f none usr/lib/help/auths/locale/SmfWpaStates.html 444 root bin
--- a/usr/src/pkgdefs/SUNWcsu/prototype_com	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNWcsu/prototype_com	Tue Oct 23 07:51:21 2007 -0700
@@ -487,6 +487,7 @@
 f none usr/lib/help/auths/locale/C/SmfInetdStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfIPsecStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfNscdStates.html 444 root bin
+f none usr/lib/help/auths/locale/C/SmfNADDStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfNWAMStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfPowerStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfRoutingStates.html 444 root bin
@@ -498,6 +499,7 @@
 f none usr/lib/help/auths/locale/C/SmfValueIPsec.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfValueIscsitgt.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfValueMDNS.html 444 root bin
+f none usr/lib/help/auths/locale/C/SmfValueNADD.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfValueNWAM.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfValueRouting.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfWpaStates.html 444 root bin
--- a/usr/src/pkgdefs/SUNWhal/prototype_com	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNWhal/prototype_com	Tue Oct 23 07:51:21 2007 -0700
@@ -48,8 +48,10 @@
 d none usr/lib/hal 755 root bin
 f none usr/lib/hal/hald 555 root bin
 f none usr/lib/hal/hald-addon-acpi 555 root bin
+f none usr/lib/hal/hald-addon-network-discovery 555 root bin
 f none usr/lib/hal/hald-addon-storage 555 root bin
 f none usr/lib/hal/hald-probe-battery 555 root bin
+f none usr/lib/hal/hald-probe-network-printer 555 root bin
 f none usr/lib/hal/hald-probe-printer 555 root bin
 f none usr/lib/hal/hald-probe-storage 555 root bin
 f none usr/lib/hal/hald-probe-volume 555 root bin
--- a/usr/src/pkgdefs/SUNWhalr/prototype_com	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/pkgdefs/SUNWhalr/prototype_com	Tue Oct 23 07:51:21 2007 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
@@ -68,6 +68,7 @@
 d none etc/hal/fdi/policy/10osvendor 755 root bin
 f none etc/hal/fdi/policy/10osvendor/10-keyboard-policy.fdi 444 root bin
 f none etc/hal/fdi/policy/10osvendor/10-laptop-panel-mgmt-policy.fdi 444 root bin
+f none etc/hal/fdi/policy/10osvendor/10-network-attached.fdi 444 root bin
 f none etc/hal/fdi/policy/10osvendor/10-power-mgmt-policy.fdi 444 root bin
 f none etc/hal/fdi/policy/10osvendor/10-toshiba-buttons.fdi 444 root bin
 f none etc/hal/fdi/policy/10osvendor/20-storage-methods.fdi 444 root bin
@@ -79,14 +80,18 @@
 f none etc/hal/fdi/preprobe/10osvendor/10-ide-drives.fdi 444 root bin
 f none etc/hal/fdi/preprobe/10osvendor/20-ignore-fixed-storage.fdi 444 root bin
 f none etc/hal/fdi/preprobe/10osvendor/20-ignore-lofi.fdi 444 root bin
+f none etc/hal/fdi/preprobe/10osvendor/20-printers.fdi 444 root bin
 d none etc/hal/fdi/preprobe/20thirdparty 755 root bin
 d none etc/hal/fdi/preprobe/30user 755 root bin
 d none lib 755 root bin
 d none lib/svc 0755 root bin
 d none lib/svc/method 0755 root bin
 f none lib/svc/method/svc-hal 555 root bin
+f none lib/svc/method/svc-network-discovery 555 root bin
 d none var 755 root sys
 d none var/svc 755 root sys
 d none var/svc/manifest 755 root sys
+d none var/svc/manifest/network 755 root sys
+f manifest var/svc/manifest/network/network-discovery.xml 444 root sys
 d none var/svc/manifest/system 755 root sys
 f manifest var/svc/manifest/system/hal.xml 444 root sys
--- a/usr/src/tools/scripts/check_rtime.pl	Tue Oct 23 07:41:07 2007 -0700
+++ b/usr/src/tools/scripts/check_rtime.pl	Tue Oct 23 07:51:21 2007 -0700
@@ -215,6 +215,7 @@
 	libmapmalloc\.so\.1;\ unused |
 	unused\ dependency\ of\ .*libstdc\+\+\.so\.6 |
 	unreferenced\ object=.*libstdc\+\+\.so\.6 |
+	unused\ dependency\ of\ .*libnetsnmp\.so\.5 |
 	unused\ dependency\ of\ .*libnetsnmphelpers\.so\.5 |
 	unused\ dependency\ of\ .*libnetsnmpmibs\.so\.5 |
 	unused\ dependency\ of\ .*libnetsnmpagent\.so\.5