components/pflogd/patches/002-smf.patch
changeset 5569 c3326e2b8b45
parent 5567 1d593061210b
child 5570 0b0946d94dd3
--- a/components/pflogd/patches/002-smf.patch	Wed Mar 09 08:20:13 2016 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1217 +0,0 @@
-# This patch comes from Oracle. It turns the component into
-# a well-behaving SMF service. It adds code manipulating service
-# properties, service instances, and also provides security
-# in cooperation with the service manifest (especially, extra
-# privileges are dropped when not needed).
-#
-# This patch is not going to upstream, the changes are Solaris-specific.
-
-diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/Makefile pflogd-OPENBSD_5_5-OPENBSD_5_5/Makefile
---- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/Makefile	2016-02-17 02:08:53.410106245 -0800
-+++ pflogd-OPENBSD_5_5-OPENBSD_5_5/Makefile	2016-02-16 05:02:32.489035397 -0800
-@@ -3,7 +3,7 @@
- CFLAGS+= -m64 -errwarn
- 
- PROG=pflogd
--SRCS=pflogd.c privsep.c privsep_fdpass.c
-+SRCS=pflogd.c privsep.c privsep_fdpass.c smf-config.c
- OBJS=$(SRCS:.c=.o)
- MAN=pflogd.8
- 
-diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.8 pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.8
---- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.8	2016-02-17 02:32:29.857912548 -0800
-+++ pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.8	2016-02-24 21:24:27.453116577 -0800
-@@ -33,7 +33,7 @@
- .Sh SYNOPSIS
- .Nm pflogd
- .Bk -words
--.Op Fl "Dx"
-+.Op Fl C Ar new-pflog-instance-name | Fl c Ar pflog-instance-name
- .Op Fl d Ar delay
- .Op Fl f Ar filename
- .Op Fl i Ar interface
-@@ -60,6 +60,7 @@
- hopefully offline in case there are bugs in the packet parsing code of
- .Xr tcpdump 8 .
- .Pp
-+
- .Nm
- closes and then re-opens the log file when it receives
- .Dv SIGHUP ,
-@@ -101,22 +102,52 @@
- .Pp
- The options are as follows:
- .Bl -tag -width Ds
--.It Fl D
--Debugging mode.
-+.It Fl C Ar new-pflog-instance-name
-+Creates a new
- .Nm
--does not disassociate from the controlling terminal.
-+instance with the specified name. If additional options are used to specify
-+configuration, it is stored into the
-+.Xr smf 5
-+repository. Default values are used for
-+.Xr smf 5
-+properties unless overriden by a command-line option. The exception is
-+pflog/interface (set to equal the instance name) and pflog/logfile
-+(set to a file with name equal to the instance name followed by the
-+.Pa .pkt
-+extension located inside the
-+.Pa /var/log/firewall/pflog/
-+directory) if the service instance name forms a valid linkname. If the
-+service instance name is not a valid linkname, the values must be
-+given explicitly.
-+.It Fl c Ar pflog-instance-name
-+Shows/changes the configuration of the given
-+.Nm
-+instance in
-+.Xr smf 5
-+repository. Attributes specified by additional options are placed into the
-+.Xr smf 5
-+repository.
- .It Fl d Ar delay
- Time in seconds to delay between automatic flushes of the file.
- This may be specified with a value between 5 and 3600 seconds.
- If not specified, the default is 60 seconds.
- .It Fl f Ar filename
--Log output filename.
-+Log output filename. When neither
-+.Fl C
-+nor
-+.Fl c
-+is used, the default value
-+.Pa pflog.pkt
-+is used.
- .It Fl i Ar interface
- Specifies the capture link interface to use.
--By default,
--.Nm
--will use
--.Pa pflog0 .
-+When neither
-+.Fl C
-+nor
-+.Fl c
-+is used, the default value
-+.Pa pflog0
-+is assumed.
- .It Fl s Ar snaplen
- Analyze at most the first
- .Ar snaplen
-@@ -124,8 +155,6 @@
- The default of 160 is adequate for IP, ICMP, TCP, and UDP headers but may
- truncate protocol information for other protocols.
- Other file parsers may desire a higher snaplen.
--.It Fl x
--Check the integrity of an existing log file, and return.
- .It Ar expression
- Selects which packets will be dumped, using the regular language of
- .Xr tcpdump 8 .
-@@ -164,11 +193,59 @@
- The direction was outbound.
- .El
- .El
--.Sh FILES
--.Bl -tag -width /var/run/pflogd.pid -compact
--.It Pa /var/log/firewall/pflog/pflog0.pkt
--Default log file.
-+.Sh SOLARIS
-+The
-+.Nm
-+daemon runs as an
-+.Xr smf 5
-+service with the following FMRI:
-+.Bd -literal -offset indent
-+svc:/network/firewall/pflog
-+.Ed
-+.Pp
-+Command line options described above are set via the following
-+.Xr smf 5
-+properties.
-+.Bl -tag -width "pflog/interface" -offset 3n -compact
-+.It pflog/delay
-+Automatic flush interval.
-+The default value is 60.
-+Used as the argument for the
-+.Fl d
-+option.
-+.It pflog/filter
-+Packet filter expression in
-+.Xr tcpdump 8
-+format.
-+No expression is defined by default.
-+.It pflog/interface
-+The capture link name from which to read packets.
-+Used as the argument for the
-+.Fl i
-+option.
-+.It pflog/logfile
-+Path to the logfile (for security reasons, only paths starting by the
-+.Pa /var/log/firewall/
-+directory are allowed.
-+Used as the argument for the
-+.Fl f
-+option.
-+.It pflog/snaplen
-+An upper bound on how many bytes from each packet to analyze.
-+The default value is 160.
-+Used as the argument for the
-+.Fl s
-+option.
- .El
-+.Pp
-+The start method creates a (temporal) capture link the particular
-+instance is using.
-+.Pp
-+The refresh method sends
-+.Dv SIGHUP
-+to
-+.Nm
-+owned by particular service instance.
- .Sh EXAMPLES
- Log specific TCP packets to a different log file with a large snaplen
- (useful with a
-@@ -202,6 +279,32 @@
- .Bd -literal -offset indent
- # tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0
- .Ed
-+.Sh SECURITY
-+The
-+.Nm
-+daemon is a privilege-aware application which runs as the
-+.Dq daemon
-+user possessing
-+.Sy PRIV_NET_OBSERVABILITY
-+privilege that is required for using
-+.Xr bpf 7d
-+to read packets. See
-+.Xr privileges 5
-+for details.
-+The service start method uses
-+.Xr dladm 1M
-+to create capture link if it does not exist already.
-+.Pp
-+To configure the
-+.Nm
-+service one has to obtain the
-+.Sy solaris.smf.value.network.firewall
-+authorization.
-+To manage the service (disable/enable/refresh) one must have the
-+.Sy solaris.smf.manage.network.firewall
-+authorization.
-+Both authorizations are granted through the Network Firewall Management profile.
-+To create new service instances, you need the solaris.smf.modify authorization.
- .Sh SEE ALSO
- .Xr pcap 3 ,
- .Xr pf.conf 5 ,
-diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.c pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.c
---- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.c	2016-02-18 12:05:03.256562087 -0800
-+++ pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.c	2016-02-18 12:01:49.900876863 -0800
-@@ -54,6 +54,7 @@
- #include <strings.h>
- #include <zone.h>
- #include <libuutil.h>
-+#include "smf-config.h"
- #else /* !_SOLARIS_ */
- #include <util.h>
- #endif	/* _SOLARIS_ */
-@@ -63,7 +64,7 @@
- static FILE *dpcap;
- 
- int Debug = 0;
--static int snaplen = DEF_SNAPLEN;
-+static int64_t snaplen = DEF_SNAPLEN;
- static int cur_snaplen = DEF_SNAPLEN;
- 
- volatile sig_atomic_t gotsig_close, gotsig_alrm, gotsig_hup, gotsig_usr1;
-@@ -75,7 +76,7 @@
- char errbuf[PCAP_ERRBUF_SIZE];
- 
- int log_debug = 0;
--unsigned int delay = FLUSH_DELAY;
-+int64_t delay = FLUSH_DELAY;
- 
- char *copy_argv(char * const *);
- void  dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
-@@ -124,6 +125,15 @@
- 
- #endif	/* _SOLARIS_ */
- 
-+#ifdef	_SOLARIS_
-+#define	PFLOGD_GETOPTS	"c:C:Dd:f:i:s:"
-+#define	CFG_SETFLAG(_flags_, _f_)	((_flags_) |= (_f_))
-+#define	SKIP_CHK(_x_)	((_x_) == NULL)
-+#else /* !_SOLARIS_ */
-+#define	PFLOGD_GETOPTS	"Dxd:f:i:s:"
-+#define	CFG_SETFLAG(_flags_, _f_)
-+#define	SKIP_CHK(_x_)	(1)
-+#endif	/* _SOLARIS_ */
- static int try_reset_dump(int);
- 
- /* buffer must always be greater than snaplen */
-@@ -290,6 +300,8 @@
- init_pcap(void)
- {
- 	hpcap = pcap_open_live(interface, snaplen, 1, PCAP_TO_MS, errbuf);
-+	DROP_PRIV(PRIV_NET_OBSERVABILITY);
-+
- 	if (hpcap == NULL) {
- 		logmsg(LOG_ERR, "Failed to initialize: %s", errbuf);
- 		return (-1);
-@@ -690,12 +702,20 @@
- 	int ch, np, ret, Xflag = 0;
- 	pcap_handler phandler = dump_packet;
- 	const char *errstr = NULL;
-+#ifdef	_SOLARIS_
-+	unsigned int	create = 0;
-+	unsigned int	cfg_flags = 0;
-+	const char	*smf_instance = NULL;
-+#endif	/* _SOLARIS_ */
-+
-+	DROP_PRIV(PRIV_SYS_IP_CONFIG);
-+	DROP_PRIV(PRIV_PROC_EXEC);
- 
- 	ret = 0;
- 
- 	closefrom(STDERR_FILENO + 1);
- 
--	while ((ch = getopt(argc, argv, "Dxd:f:i:s:")) != -1) {
-+	while ((ch = getopt(argc, argv, PFLOGD_GETOPTS)) != -1) {
- 		switch (ch) {
- 		case 'D':
- 			Debug = 1;
-@@ -704,12 +724,15 @@
- 			delay = strtonum(optarg, 5, 60*60, &errstr);
- 			if (errstr)
- 				usage();
-+			CFG_SETFLAG(cfg_flags, SMF_CFG_DELAY_SET);
- 			break;
- 		case 'f':
- 			filename = optarg;
-+			CFG_SETFLAG(cfg_flags, SMF_CFG_LOGFILE_SET);
- 			break;
- 		case 'i':
- 			interface = optarg;
-+			CFG_SETFLAG(cfg_flags, SMF_CFG_INTERFACE_SET);
- 			break;
- 		case 's':
- 			snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
-@@ -718,10 +741,27 @@
- 				snaplen = DEF_SNAPLEN;
- 			if (errstr)
- 				snaplen = PFLOGD_MAXSNAPLEN;
-+			CFG_SETFLAG(cfg_flags, SMF_CFG_SNAPLEN_SET);
- 			break;
-+#ifndef	_SOLARIS_
-+		/*
-+		 * This option requires a special securing on Solaris as
-+		 * pflogd will be started manually in the case it is used.
-+		 * Also, some polishing is needed so that the response
-+		 * from 'pflogd -x' is shown to the user and not put into
-+		 * a logfile.
-+		 */
- 		case 'x':
- 			Xflag++;
- 			break;
-+#endif /* !_SOLARIS_ */
-+#ifdef	_SOLARIS_
-+		case 'C': 
-+			create = 1;	/* FALLTHRU */
-+		case 'c':
-+			smf_instance = optarg;
-+			break;
-+#endif	/* _SOLARIS_ */
- 		default:
- 			usage();
- 		}
-@@ -732,14 +772,14 @@
- 	argv += optind;
- 
- 	/* does interface exist */
--	if (!if_exists(interface)) {
-+	if (SKIP_CHK(smf_instance) && !if_exists(interface)) {
- 		warn("Failed to initialize: %s", interface);
- 		logmsg(LOG_ERR, "Failed to initialize: %s", interface);
- 		logmsg(LOG_ERR, "Exiting, init failure");
- 		exit(1);
- 	}
- 
--	if (!Debug) {
-+	if (SKIP_CHK(smf_instance) && !Debug) {
- 		openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON);
- 		if (daemon(0, 0)) {
- 			logmsg(LOG_WARNING, "Failed to become daemon: %s",
-@@ -757,6 +797,31 @@
- 			logmsg(LOG_NOTICE, "Failed to form filter expression");
- 	}
- 
-+#ifdef	_SOLARIS_
-+	if (smf_instance != NULL) {
-+		if (filter != NULL) {
-+			CFG_SETFLAG(cfg_flags, SMF_CFG_EXPRESSION_SET);
-+		} else {
-+			filter = "";
-+		}
-+		if ((cfg_flags == 0) && (create == 0)) {
-+			if (smf_print_pflogcfg(smf_instance)) {
-+				exit (-1);
-+			}
-+		} else {
-+			smf_pflogd_cfg.cfg_set = cfg_flags;
-+			smf_pflogd_cfg.cfg_expression = strdup(filter);
-+			smf_pflogd_cfg.cfg_interface = strdup(interface);
-+			smf_pflogd_cfg.cfg_logfile = strdup(filename);
-+			smf_pflogd_cfg.cfg_delay = delay;
-+			smf_pflogd_cfg.cfg_snaplen = snaplen;
-+
-+			smf_write_pflogcfg(smf_instance, create);
-+		}
-+		exit(0);
-+	}
-+#endif	/* _SOLARIS_ */
-+
- 	/* initialize pcap before dropping privileges */
- 	if (init_pcap()) {
- 		logmsg(LOG_ERR, "Exiting, init failure");
-@@ -768,7 +833,6 @@
- 		logmsg(LOG_ERR, "unable to privsep");
- 		exit(1);
- 	}
--
- 	setproctitle("[initializing]");
- 	/* Process is now unprivileged and inside a chroot */
- #ifdef	_SOLARIS_
-diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.h pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.h
---- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.h	2016-02-18 12:08:42.414919276 -0800
-+++ pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.h	2016-02-18 12:09:18.796727948 -0800
-@@ -18,6 +18,8 @@
- 
- #ifdef	_SOLARIS_
- #include <limits.h>
-+#include <sys/types.h>
-+#include <priv.h>
- #else /* !_SOLARIS_ */
- #include <sys/limits.h>
- #endif	/* _SOLARIS_ */
-@@ -55,3 +57,27 @@
- int  receive_fd(int);
- 
- extern int Debug;
-+
-+#ifdef _SOLARIS_
-+#define DROP_PRIV(priv)                                         \
-+	do {                                                    \
-+		if (priv_set(PRIV_OFF, PRIV_PERMITTED, (priv),  \
-+		    NULL) != 0) {                               \
-+			fprintf(stderr,                         \
-+			    "Unable to drop privileges.\n");    \
-+			exit (-1);                              \
-+		}                                               \
-+	} while (0)
-+
-+#define DROP_PFLAG(flag)				\
-+	do {						\
-+		if (setpflags((flag), 0) != 0) {	\
-+			fprintf(stderr,			\
-+			    "Unable to drop pflag.\n");	\
-+			exit (-1);			\
-+		}					\
-+} while (0)
-+#else /* !_SOLARIS_ */
-+#define DROP_PRIV(priv)
-+#define DROP_PFLAG(flag)
-+#endif /* _SOLARIS_ */
-diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/privsep.c pflogd-OPENBSD_5_5-OPENBSD_5_5/privsep.c
---- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/privsep.c	2016-02-18 12:07:34.219667793 -0800
-+++ pflogd-OPENBSD_5_5-OPENBSD_5_5/privsep.c	2016-02-18 11:55:14.949135348 -0800
-@@ -112,6 +112,7 @@
- #endif	/* !_SOLARIS_ */
- 
- 	child_pid = fork();
-+	DROP_PRIV(PRIV_PROC_FORK);
- 	if (child_pid < 0)
- 		err(1, "fork() failed");
- 
-@@ -133,6 +134,7 @@
- 		if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
- 			err(1, "setresuid() failed");
- #endif	/* !_SOLARIS_ */
-+		DROP_PFLAG(PRIV_XPOLICY);
- 
- 		close(socks[0]);
- 		priv_fd = socks[1];
-diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/smf-config.c pflogd-OPENBSD_5_5-OPENBSD_5_5/smf-config.c
---- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/smf-config.c	1969-12-31 16:00:00.000000000 -0800
-+++ pflogd-OPENBSD_5_5-OPENBSD_5_5/smf-config.c	2016-02-24 08:24:57.408744180 -0800
-@@ -0,0 +1,713 @@
-+/*
-+ * 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 (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#include <string.h>
-+#include <strings.h>
-+#include <stdlib.h>
-+#include <err.h>
-+#include <stdarg.h>
-+#include <stdio.h>
-+#include <libscf.h>
-+#include <stddef.h>
-+#include <libscf_priv.h>
-+
-+#include "pflogd.h"
-+#include "smf-config.h"
-+
-+#define	PFLOGD_PG	"pflog"
-+#define PFLOGD_PROP_VALUE_AUTH	"value_authorization"
-+#define PFLOGD_PROP_ACTION_AUTH	"action_authorization"
-+#define PFLOGD_VALUE_AUTH	"solaris.smf.value.network.firewall"
-+#define PFLOGD_MANAGE_AUTH	"solaris.smf.manage.network.firewall"
-+
-+#define	SKIP_PROP(_pv_)		\
-+	((strcmp((_pv_)->pv_prop, "action_authorization") == 0) || \
-+	(strcmp((_pv_)->pv_prop, "value_authorization") == 0))
-+
-+#define	STRIP_SVC(_x_)	((_x_) + (sizeof ("svc:/") - 1))
-+
-+/*
-+ * smf_pflogd_cfg
-+ * FTP proxy configuration container.
-+ */
-+smf_pflogd_cfg_t	smf_pflogd_cfg;
-+
-+#define	SMF_OPT_OPTIONAL	0
-+#define	SMF_OPT_MANDATORY	1
-+/*
-+ * X-macro table.
-+ * Columns are as follows:
-+ * 	value key/index 
-+ *	SMF property name name
-+ *	member in smf_pflogd_cfg_t structure
-+ *	function which converts ASCIIZ to member type in smf_pflogd_cfg_t
-+ *	function which converts member in smf_pflogd_cfg_t to ASCIIZ
-+ *	optional/mandatory status
-+ *      property type
-+ */
-+#define	X_CFG_PROPS	\
-+	X(SMF_LOGFILE, "logfile", cfg_logfile, nop_in, nop_out,		\
-+	    SMF_OPT_MANDATORY, SCF_TYPE_ASTRING)			\
-+	X(SMF_SNAPLEN, "snaplen", cfg_snaplen, int_in, int_out,		\
-+	    SMF_OPT_MANDATORY, SCF_TYPE_INTEGER)			\
-+	X(SMF_INTERFACE, "interface", cfg_interface, nop_in, nop_out,	\
-+	    SMF_OPT_MANDATORY, SCF_TYPE_ASTRING)			\
-+	X(SMF_DELAY, "delay",	cfg_delay, int_in, int_out,		\
-+	    SMF_OPT_OPTIONAL, SCF_TYPE_INTEGER)				\
-+	X(SMF_EXPRESSION, "filter", cfg_expression, nop_in, nop_out,	\
-+	    SMF_OPT_OPTIONAL, SCF_TYPE_ASTRING)
-+
-+static void nop_in(void *, void *);
-+static void nop_out(void *, void *);
-+static void int_in(void *, void *);
-+static void int_out(void *, void *);
-+
-+/*
-+ * smf_keys
-+ * Keys (indexes) to `smf_propnames` dictionary.
-+ */
-+#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
-+    _type_) _const_,
-+enum smf_keys {
-+	X_CFG_PROPS
-+	SMF_CFG_PROP_COUNT
-+};
-+#undef	X
-+
-+/*
-+ * smf_propnames
-+ * It's an array (dictionary), which translates property code (SMF_*) to
-+ * property value name found `ftp-proxy` property group.
-+ */
-+#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
-+    _type_) _propname_,
-+static const char *smf_propnames[] = {
-+	X_CFG_PROPS
-+	NULL
-+};
-+#undef	X
-+
-+/*
-+ * smf_cfg_offsets
-+ * Table of smf_pflogd_cfg_t members.
-+ */
-+#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
-+    _type_) offsetof(smf_pflogd_cfg_t, _decl_),
-+static size_t smf_cfg_offsets[] = {
-+	X_CFG_PROPS
-+	sizeof (smf_pflogd_cfg_t)
-+};
-+#undef	X
-+
-+typedef void(*conv_in_f)(void *, void *);
-+typedef void(*conv_out_f)(void *, void *);
-+/*
-+ * smf_convert_in
-+ * Table of conversion functions, which convert particular smf_pflogd_cfg_t
-+ * member into ASCIIZ.
-+ */
-+#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
-+    _type_) _conv_in_,
-+static conv_in_f smf_conv_in[] = {
-+	X_CFG_PROPS
-+	NULL
-+};
-+#undef	X
-+
-+/*
-+ * smf_conv_out
-+ * Table of conversion functions, which convert ASCIIZ fetched from smf(5)
-+ * repository to member of smf_pflogd_cfg_t structure.
-+ */
-+#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
-+    _type_) _conv_out_,
-+static conv_out_f smf_conv_out[] = {
-+	X_CFG_PROPS
-+	NULL
-+};
-+#undef	X
-+
-+/*
-+ * smf_mandatory
-+ * Table marks configuration parameters, which must be defined by admin,
-+ * before the service is enabled for the first time.
-+ */
-+#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
-+    _type_) _mandatory_,
-+static int smf_mandatory[] = {
-+	X_CFG_PROPS
-+	0
-+};
-+#undef	X
-+
-+/*
-+ * smf_type
-+ * Table of types of SMF properties.
-+ */
-+#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
-+    _type_) _type_,
-+static int smf_type[] = {
-+	X_CFG_PROPS
-+	0
-+};
-+#undef	X
-+
-+/*
-+ * pflogd property group properties
-+ * +1 for NULL termination.
-+ * +1 for value_authorization
-+ */
-+static scf_propvec_t	prop_vec[SMF_CFG_PROP_COUNT + 1 + 1];
-+
-+/*
-+ * general property group properties
-+ * +1 for NULL termination.
-+ * +2 for value_authorization/action_authorization
-+ */
-+static scf_propvec_t	gen_prop_vec[1 + 2];
-+
-+static int atexit_set = 0;
-+static int complete_pflogdcfg(const char *);
-+
-+/*
-+ * nop_in()
-+ * Dummy conversion ASCIIZ to ASCIIZ, no allocation happens. Used when
-+ * configuration is from smf(5).
-+ */
-+static void
-+nop_in(void *asciiz, void *result)
-+{
-+	*((char **)result) = (char *)asciiz;
-+}
-+
-+/*
-+ * nop_out()
-+ * Dummy conversion ASCIIZ to ASCIIZ, function allocates memory for result by
-+ * strdup(3C). Used when configuration is written to smf(5) repository.
-+ */
-+static void
-+nop_out(void *asciiz, void *val)
-+{
-+	*((char **)asciiz) = strdup(*(char **)val);
-+}
-+
-+/*
-+ * int_in()
-+ * Dummy conversion of int64_t. No allocation happens. Used when reading
-+ * values from smf.
-+ */
-+static void
-+int_in(void *in, void *out) {
-+	*((int64_t *)out) = *((int64_t *)in);
-+}
-+
-+/*
-+ * int_out()
-+ * Dummy conversion of int64_t, storing into a newly allocated memory.
-+ * Used when storing values to smf repository.
-+ */
-+static void
-+int_out(void *out, void *in) {
-+	int64_t **out_ = (int64_t **)out;
-+
-+	*out_ = malloc(sizeof (int64_t));
-+	if (*out_ != NULL)
-+		**out_ = *((int64_t *)in);
-+}
-+
-+static void
-+clear_prop_vec2(scf_propvec_t *prop_vec_ptr, int count)
-+{
-+	while (count--) {
-+		prop_vec_ptr->pv_prop = NULL;
-+		prop_vec_ptr->pv_desc = NULL;
-+		prop_vec_ptr->pv_type = 0;
-+		prop_vec_ptr->pv_aux = 0;
-+		prop_vec_ptr->pv_mval = 0;
-+
-+		if (prop_vec_ptr->pv_ptr != NULL) {
-+			free(prop_vec_ptr->pv_ptr);
-+			prop_vec_ptr->pv_ptr = NULL;
-+		}
-+
-+		prop_vec_ptr++;
-+	}
-+}
-+
-+/*
-+ * clear_prop_vec()
-+ * Function clears global variables `prop_vec` and `gen_prop_vec`,
-+ * which are vectors of properties.
-+ */
-+static void
-+clear_prop_vec()
-+{
-+	clear_prop_vec2(prop_vec,
-+	    sizeof (prop_vec) / sizeof (scf_propvec_t));
-+	clear_prop_vec2(gen_prop_vec,
-+	    sizeof (gen_prop_vec) / sizeof (scf_propvec_t));
-+}
-+
-+/*
-+ * cfg_to_prop_vec()
-+ * Function converts smf_pflogd_cfg global variable, which holds configuration
-+ * parsed from command line arguments, to prop_vec, which is a smf(5) friendly
-+ * representation of pflogd configuration. 
-+ *
-+ * Additionally, it populates gen_prop_vec to specify needed authorizations.
-+ *
-+ * Returns 0 on success, -1 on out of memory error.
-+ */
-+static int
-+cfg_to_prop_vec(void)
-+{
-+	int		cfg_bit = 1;
-+	int		i;
-+	scf_propvec_t	*prop_vec_ptr = prop_vec;
-+	conv_out_f	conv_func;
-+
-+	clear_prop_vec();
-+
-+	for (i = 0; i < SMF_CFG_PROP_COUNT; i++) {
-+		if ((smf_pflogd_cfg.cfg_set & cfg_bit) != 0) {
-+			prop_vec_ptr->pv_prop = smf_propnames[i];
-+			conv_func = smf_conv_out[i];
-+
-+			conv_func(&prop_vec_ptr->pv_ptr,
-+			    ((char *)&smf_pflogd_cfg + smf_cfg_offsets[i]));
-+			if (prop_vec_ptr->pv_ptr == NULL)
-+				return (-1);
-+			prop_vec_ptr->pv_type = smf_type[i];
-+			prop_vec_ptr++;
-+		}
-+		cfg_bit = cfg_bit << 1;
-+	}
-+	prop_vec_ptr->pv_type = SCF_TYPE_ASTRING;
-+	prop_vec_ptr->pv_prop = PFLOGD_PROP_VALUE_AUTH;
-+	prop_vec_ptr->pv_ptr = strdup(PFLOGD_VALUE_AUTH);
-+	prop_vec_ptr++;
-+
-+	gen_prop_vec[0].pv_type = SCF_TYPE_ASTRING;
-+	gen_prop_vec[0].pv_prop = PFLOGD_PROP_VALUE_AUTH;
-+	gen_prop_vec[0].pv_ptr = strdup(PFLOGD_MANAGE_AUTH);
-+	gen_prop_vec[1].pv_type = SCF_TYPE_ASTRING;
-+	gen_prop_vec[1].pv_prop = PFLOGD_PROP_ACTION_AUTH;
-+	gen_prop_vec[1].pv_ptr = strdup(PFLOGD_MANAGE_AUTH);
-+
-+	return (0);
-+}
-+
-+/*
-+ * prop_vec_to_cfg()
-+ * Converts global variable `prop_vec` to `smf_pflogd_cfg` global variable,
-+ * which is understood by main().
-+ */
-+static void
-+prop_vec_to_cfg(void)
-+{
-+	int		i;
-+	scf_propvec_t	*prop_vec_ptr = prop_vec;
-+	conv_in_f	conv_func;
-+
-+	for (i = 0; i < SMF_CFG_PROP_COUNT; i++, prop_vec_ptr++) {
-+		if (SKIP_PROP(prop_vec_ptr)) {
-+			/*
-+			 * We have `hidden` properties: action/value smf
-+			 * authorization. Those two are not kept in
-+			 * smf_ftp_cfg.
-+			 *
-+			 * So we must to skip to next property in vector
-+			 * without letting for loop to advance its counter, so
-+			 * we compensate here by doing `i--`.
-+			 */
-+			i--;
-+			continue;
-+		};
-+		conv_func = smf_conv_in[i];
-+		conv_func(prop_vec_ptr->pv_ptr,
-+		    ((char *)&smf_pflogd_cfg + smf_cfg_offsets[i]));
-+	}
-+}
-+
-+/*
-+ * smf_print_pflogcfg()
-+ * Function loads pflogdcfg from smf(5) repository and prints configuration to
-+ * standard output. We use `scf_simple_prop_get(3SCF)`.
-+ *
-+ * Returns 0 on success, -1 on error.
-+ */
-+int
-+smf_print_pflogcfg(const char *smf_instance)
-+{
-+	scf_simple_prop_t	*prop;
-+	char			*propval;
-+	int			i;
-+	scf_propvec_t		*prop_vec_ptr = prop_vec;
-+	int			cfg_undefined = 0;
-+	char			*fmri;
-+
-+	if (atexit_set == 0) {
-+		atexit(clear_prop_vec);
-+		bzero(&smf_pflogd_cfg, sizeof (smf_pflogd_cfg_t));
-+		atexit_set = 1;
-+	}
-+
-+	(void) asprintf(&fmri, "%s:%s", BASE_FMRI, smf_instance);
-+	if (fmri == NULL) {
-+		fprintf(stderr, "Out of memory.\n");
-+		return (-1);
-+	}
-+
-+	clear_prop_vec();
-+
-+	for (i = 0; i < SMF_CFG_PROP_COUNT; i++) {
-+		prop = scf_simple_prop_get(NULL, fmri, PFLOGD_PG,
-+		    smf_propnames[i]);
-+		prop_vec_ptr->pv_prop = smf_propnames[i];
-+
-+		if (prop == NULL) {
-+			/*
-+			 * Property not defined, so we create a kind of
-+			 * 'placeholder' with empty value.
-+			 *
-+			 * calloc() works well for both astring and integer.
-+			 */
-+			prop_vec_ptr->pv_type = smf_type[i];
-+			prop_vec_ptr->pv_ptr = calloc(1, sizeof (int64_t));
-+			cfg_undefined |= smf_mandatory[i];
-+		} else {
-+			prop_vec_ptr->pv_type = scf_simple_prop_type(prop);
-+			if (prop_vec_ptr->pv_type == -1) {
-+				free(fmri);
-+				fprintf(stderr,
-+				    "Failed to get property type.\n");
-+				return (-1);
-+			}
-+			if (prop_vec_ptr->pv_type != smf_type[i]) {
-+				free(fmri);
-+				fprintf(stderr,
-+				    "Property %s has unexpected type.\n",
-+				    smf_propnames[i]);
-+				return (-1);
-+			}
-+
-+			if (smf_type[i] == SCF_TYPE_ASTRING) {
-+				char	*propval;
-+				propval = scf_simple_prop_next_astring(prop);
-+				if (propval == NULL) {
-+					propval = "";
-+				}
-+				prop_vec_ptr->pv_ptr = strdup(propval);
-+
-+				if (propval[0] == 0) {
-+					cfg_undefined |= smf_mandatory[i];
-+				}
-+			} else {
-+				/* smf_type[i] == SCF_TYPE_INTEGER */
-+				int64_t	*propval;
-+				int64_t propval_;
-+
-+				propval = scf_simple_prop_next_integer(prop);
-+				propval_ = (propval == NULL) ? (0) : (*propval);
-+
-+				prop_vec_ptr->pv_ptr = malloc(sizeof (int64_t));
-+				if (prop_vec_ptr->pv_ptr != NULL) {
-+					*((int64_t *)prop_vec_ptr->pv_ptr) =
-+					    propval_;
-+				}
-+				if (propval_ == 0) {
-+					cfg_undefined |= smf_mandatory[i];
-+				}
-+			}
-+			scf_simple_prop_free(prop);
-+		}
-+		if (prop_vec_ptr->pv_ptr == NULL) {
-+			free(fmri);
-+			fprintf(stderr, "Out of memory.\n");
-+			return (-1);
-+		}
-+
-+		prop_vec_ptr++;
-+	}
-+
-+	printf("PF pflogd configuration:\n");
-+
-+	prop_vec_ptr = prop_vec;
-+	for (i = 0; i < SMF_CFG_PROP_COUNT; i++) {
-+		if (smf_type[i] == SCF_TYPE_ASTRING) {
-+			const char *val = (const char *)prop_vec_ptr->pv_ptr;
-+			printf("\t- %s:\n\t\t%s\n", prop_vec_ptr->pv_prop,
-+			    ((val[0] == '\0') ?  "?? undefined ??" : val));
-+		} else {
-+			/* smf_type[i] == SCF_TYPE_INTEGER */
-+			int64_t val = *((int64_t *)prop_vec_ptr->pv_ptr);
-+			if (val == 0) {
-+				printf("\t- %s:\n\t\t%s\n", prop_vec_ptr->pv_prop,
-+			    	    "?? undefined ??");
-+			} else {
-+				printf("\t- %s:\n\t\t%d\n", prop_vec_ptr->pv_prop,
-+			    	    (int)val);
-+			}
-+		}
-+		prop_vec_ptr++;
-+	}
-+	if (cfg_undefined) {
-+		printf("\n\nConfiguration for %s is incomplete."
-+		    " Service will not run.\n\n", fmri);
-+	} else {
-+		prop_vec_to_cfg();
-+		printf(
-+		    "\n\n%s service is being launched using cmd line below\n",
-+		    fmri);
-+		printf("pflogd -d %d -i %s -s %d -f %s %s\n\n",
-+		    (int)smf_pflogd_cfg.cfg_delay, smf_pflogd_cfg.cfg_interface,
-+		    (int)smf_pflogd_cfg.cfg_snaplen, smf_pflogd_cfg.cfg_logfile,
-+		    smf_pflogd_cfg.cfg_expression);
-+	}
-+
-+	free(fmri);
-+
-+	return (0);
-+}
-+
-+/*
-+ * smf_create_pflogd_instance()
-+ * Function creates a new instance in smf(5) repository.
-+ */
-+static int
-+smf_create_pflogd_instance(const char *smf_instance)
-+{
-+	scf_handle_t	*h_scf = NULL;
-+	scf_scope_t	*scp_scf = NULL;
-+	scf_service_t	*svc_scf = NULL;
-+	scf_instance_t	*sin_scf = NULL;
-+	int	rv = -1;
-+
-+ 	h_scf = scf_handle_create(SCF_VERSION);
-+	if ((h_scf == NULL) || (scf_handle_bind(h_scf) == -1)) {
-+		(void) fprintf(stderr, "scf_handle_bind() failed - %s\n",
-+		    scf_strerror(scf_error()));
-+		if (h_scf != NULL) {
-+			scf_handle_destroy(h_scf);
-+		}
-+		return (-1);
-+	}
-+
-+	if ((scp_scf = scf_scope_create(h_scf)) == NULL) {
-+		(void) fprintf(stderr, "could not create scope - %s\n",
-+		    scf_strerror(scf_error()));
-+		goto unbind;
-+	}
-+
-+	if (scf_handle_get_local_scope(h_scf, scp_scf) != 0) {
-+		(void) fprintf(stderr, "could not get scope - %s\n",
-+		    scf_strerror(scf_error()));
-+		goto scope_destroy;
-+	}
-+
-+	if ((svc_scf = scf_service_create(h_scf)) == NULL) {
-+		(void) fprintf(stderr, "could not create service - %s\n",
-+		    scf_strerror(scf_error()));
-+		goto scope_destroy;
-+	}
-+
-+	if ((sin_scf = scf_instance_create(h_scf)) == NULL) {
-+		(void) fprintf(stderr, "could not get instance handle - %s\n",
-+		    scf_strerror(scf_error()));
-+		goto service_destroy;
-+	}
-+
-+	if (scf_scope_get_service(scp_scf, STRIP_SVC(BASE_FMRI), svc_scf) !=
-+	    SCF_SUCCESS) {
-+		(void) fprintf(stderr, "could not select service (%s)\n",
-+		    scf_strerror(scf_error()));
-+		goto instance_destroy;
-+	}
-+
-+	if (scf_service_add_instance(svc_scf, smf_instance, sin_scf) != 0) {
-+		(void) fprintf(stderr, "could not add %s instance - %s\n",
-+		    smf_instance, scf_strerror(scf_error()));
-+		goto instance_destroy;
-+	}
-+
-+	if (scf_instance_add_pg(sin_scf, "general", "framework", 0,
-+	    NULL) != SCF_SUCCESS) {
-+		(void) fprintf(stderr,
-+		    "could not create property group - %s\n",
-+		    scf_strerror(scf_error()));
-+		goto instance_delete;
-+	}
-+
-+	if (scf_instance_add_pg(sin_scf, PFLOGD_PG, "application", 0,
-+	    NULL) != SCF_SUCCESS) {
-+		(void) fprintf(stderr,
-+		    "could not create property group - %s\n",
-+		    scf_strerror(scf_error()));
-+		goto instance_delete;
-+	}
-+
-+	rv = 0;
-+	goto instance_destroy;
-+
-+instance_delete:
-+	if (scf_instance_delete(sin_scf) != 0) {
-+		fprintf(stderr, "Can't delete the newly created instance:");
-+		fprintf(stderr, "\t%s\n", scf_strerror(scf_error()));
-+	}
-+instance_destroy:
-+	scf_instance_destroy(sin_scf);
-+service_destroy:
-+	scf_service_destroy(svc_scf);
-+scope_destroy:
-+	scf_scope_destroy(scp_scf);
-+unbind:
-+	scf_handle_unbind(h_scf);
-+	scf_handle_destroy(h_scf);
-+
-+	return (rv);
-+}
-+
-+/*
-+ * smf_write_pflogcfg()
-+ * Function writes pflogd configuration to smf(5) repository.
-+ */
-+int
-+smf_write_pflogcfg(const char *smf_instance, int create)
-+{
-+	int	i;
-+	scf_propvec_t
-+		*bad_prop_vec = NULL;
-+	char	*fmri;
-+
-+	if (atexit_set == 0) {
-+		atexit(clear_prop_vec);
-+		bzero(prop_vec, sizeof (prop_vec));
-+		atexit_set = 1;
-+	}
-+
-+	if (create && (complete_pflogdcfg(smf_instance) != 0)) {
-+		fprintf(stderr, "Out of memory.\n");
-+		return (-1);
-+	}
-+
-+	if (cfg_to_prop_vec() != 0) {
-+		fprintf(stderr, "Out of memory.\n");
-+		return (-1);
-+	}
-+
-+	(void) asprintf(&fmri, "%s:%s", BASE_FMRI, smf_instance);
-+	if (fmri == NULL) {
-+		fprintf(stderr, "Out of memory.\n");
-+		return (-1);
-+	}
-+
-+	if (create) {
-+		if (smf_create_pflogd_instance(smf_instance) != 0) {
-+			free(fmri);
-+			return (-1);
-+		}
-+	}
-+
-+	if (create && (scf_write_propvec(fmri, "general", gen_prop_vec,
-+	    &bad_prop_vec) != SCF_SUCCESS)) {
-+		fprintf(stderr, "Can't update %s configuration:", fmri);
-+		fprintf(stderr, "\t%s\n", scf_strerror(scf_error()));
-+		if (bad_prop_vec != NULL) {
-+			fprintf(stderr, "Could not set %s\n",
-+			    bad_prop_vec->pv_prop);
-+		}
-+		free(fmri);
-+		exit(1);
-+	}
-+
-+	bad_prop_vec = NULL;
-+	if (scf_write_propvec(fmri, PFLOGD_PG, prop_vec, &bad_prop_vec)
-+	    != SCF_SUCCESS) {
-+		fprintf(stderr, "Can't update %s configuration:", fmri);
-+		fprintf(stderr, "\t%s\n", scf_strerror(scf_error()));
-+		if (bad_prop_vec != NULL) {
-+			fprintf(stderr, "Could not set %s\n",
-+			    bad_prop_vec->pv_prop);
-+		}
-+		free(fmri);
-+		exit(1);
-+	}
-+
-+	free(fmri);
-+	return (0);
-+}
-+
-+/*
-+ * complete_pflogdcfg()
-+ * Function sets default values to properties, which are unset/undefined when
-+ * new smf(5) instance is being created.
-+ *
-+ * Returns 0 on success, -1 on out of memory error.
-+ */
-+static int
-+complete_pflogdcfg(const char *smf_instance)
-+{
-+	int	i;
-+	int	f = 1;
-+
-+	for (i = 0; i < SMF_CFG_PROP_COUNT; i++) {
-+		if ((smf_pflogd_cfg.cfg_set & f) == 0) {
-+			switch (i) {
-+			case SMF_LOGFILE:
-+				(void) asprintf(&smf_pflogd_cfg.cfg_logfile,
-+				    "%s/%s", PFLOGD_LOG_DIR, smf_instance);
-+				if (smf_pflogd_cfg.cfg_logfile == NULL) {
-+					return (-1);
-+				}
-+				smf_pflogd_cfg.cfg_set |= SMF_CFG_LOGFILE_SET;	
-+				break;
-+			case SMF_INTERFACE:
-+				smf_pflogd_cfg.cfg_interface = strdup(smf_instance);
-+				if (smf_pflogd_cfg.cfg_interface == NULL) {
-+					return (-1);
-+				}
-+				smf_pflogd_cfg.cfg_set |= SMF_CFG_INTERFACE_SET;
-+				break;
-+			case SMF_SNAPLEN:
-+				smf_pflogd_cfg.cfg_snaplen = DEF_SNAPLEN;
-+				smf_pflogd_cfg.cfg_set |= SMF_CFG_SNAPLEN_SET;
-+				break;
-+			case SMF_DELAY:
-+				smf_pflogd_cfg.cfg_delay = FLUSH_DELAY;
-+				smf_pflogd_cfg.cfg_set |= SMF_CFG_DELAY_SET;
-+				break;
-+			case SMF_EXPRESSION:
-+				smf_pflogd_cfg.cfg_expression = strdup("");
-+				smf_pflogd_cfg.cfg_set |= SMF_CFG_EXPRESSION_SET;
-+				break;
-+			default: ;
-+			}
-+		}
-+		f = f << 1;
-+	}
-+
-+	return (0);
-+}
-diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/smf-config.h pflogd-OPENBSD_5_5-OPENBSD_5_5/smf-config.h
---- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/smf-config.h	1969-12-31 16:00:00.000000000 -0800
-+++ pflogd-OPENBSD_5_5-OPENBSD_5_5/smf-config.h	2016-02-17 01:17:14.520118386 -0800
-@@ -0,0 +1,53 @@
-+/*
-+ * 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 (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
-+ */
-+
-+#ifndef	_SMF_CONFIG_H_
-+#define	_SMF_CONFIG_H_
-+
-+#define	BASE_FMRI		"svc:/network/firewall/pflog"
-+#define	DEFAULT_INSTANCE	"pflog0"
-+
-+#define	SMF_CFG_LOGFILE_SET	0x00000001
-+#define	SMF_CFG_SNAPLEN_SET	0x00000002
-+#define	SMF_CFG_INTERFACE_SET	0x00000004
-+#define	SMF_CFG_DELAY_SET	0x00000008
-+#define	SMF_CFG_EXPRESSION_SET	0x00000010
-+
-+typedef struct smf_pflogd_cfg {
-+	unsigned int	cfg_set;	/* SMF_CFG_*_SET bit field */
-+	char		*cfg_logfile;
-+	int64_t		cfg_snaplen;
-+	char 		*cfg_interface;
-+	int64_t		cfg_delay;
-+	char		*cfg_expression;
-+} smf_pflogd_cfg_t;
-+
-+extern smf_pflogd_cfg_t	smf_pflogd_cfg;
-+
-+extern int smf_print_pflogcfg(const char *);
-+extern int smf_write_pflogcfg(const char *, int);
-+
-+#endif	/* !_SMF_CONFIG_H_ */