components/pflogd/patches/002-smf.patch
changeset 5618 a7df12d981ea
child 5826 9c90e4a8156c
equal deleted inserted replaced
5617:58e4e2a36e77 5618:a7df12d981ea
       
     1 # This patch comes from Oracle. It turns the component into
       
     2 # a well-behaving SMF service. It adds code manipulating service
       
     3 # properties, service instances, and also provides security
       
     4 # in cooperation with the service manifest (especially, extra
       
     5 # privileges are dropped when not needed).
       
     6 #
       
     7 # This patch is not going to upstream, the changes are Solaris-specific.
       
     8 
       
     9 diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/Makefile pflogd-OPENBSD_5_5-OPENBSD_5_5/Makefile
       
    10 --- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/Makefile	2016-02-17 02:08:53.410106245 -0800
       
    11 +++ pflogd-OPENBSD_5_5-OPENBSD_5_5/Makefile	2016-02-16 05:02:32.489035397 -0800
       
    12 @@ -3,7 +3,7 @@
       
    13  CFLAGS+= -m64 -errwarn
       
    14  
       
    15  PROG=pflogd
       
    16 -SRCS=pflogd.c privsep.c privsep_fdpass.c
       
    17 +SRCS=pflogd.c privsep.c privsep_fdpass.c smf-config.c
       
    18  OBJS=$(SRCS:.c=.o)
       
    19  MAN=pflogd.8
       
    20  
       
    21 diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.8 pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.8
       
    22 --- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.8	2016-02-17 02:32:29.857912548 -0800
       
    23 +++ pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.8	2016-03-14 07:10:13.031600727 -0700
       
    24 @@ -33,7 +33,7 @@
       
    25  .Sh SYNOPSIS
       
    26  .Nm pflogd
       
    27  .Bk -words
       
    28 -.Op Fl "Dx"
       
    29 +.Op Fl C Ar new-pflog-instance-name | Fl c Ar pflog-instance-name
       
    30  .Op Fl d Ar delay
       
    31  .Op Fl f Ar filename
       
    32  .Op Fl i Ar interface
       
    33 @@ -60,6 +60,7 @@
       
    34  hopefully offline in case there are bugs in the packet parsing code of
       
    35  .Xr tcpdump 8 .
       
    36  .Pp
       
    37 +
       
    38  .Nm
       
    39  closes and then re-opens the log file when it receives
       
    40  .Dv SIGHUP ,
       
    41 @@ -101,22 +102,52 @@
       
    42  .Pp
       
    43  The options are as follows:
       
    44  .Bl -tag -width Ds
       
    45 -.It Fl D
       
    46 -Debugging mode.
       
    47 +.It Fl C Ar new-pflog-instance-name
       
    48 +Creates a new
       
    49  .Nm
       
    50 -does not disassociate from the controlling terminal.
       
    51 +instance with the specified name. If additional options are used to specify
       
    52 +configuration, it is stored into the
       
    53 +.Xr smf 5
       
    54 +repository. Default values are used for
       
    55 +.Xr smf 5
       
    56 +properties unless overriden by a command-line option. The exception is
       
    57 +pflog/interface (set to equal the instance name) and pflog/logfile
       
    58 +(set to a file with name equal to the instance name followed by the
       
    59 +.Pa .pkt
       
    60 +extension located inside the
       
    61 +.Pa /var/log/firewall/pflog/
       
    62 +directory) if the service instance name forms a valid linkname. If the
       
    63 +service instance name is not a valid linkname, the values must be
       
    64 +given explicitly.
       
    65 +.It Fl c Ar pflog-instance-name
       
    66 +Shows/changes the configuration of the given
       
    67 +.Nm
       
    68 +instance in
       
    69 +.Xr smf 5
       
    70 +repository. Attributes specified by additional options are placed into the
       
    71 +.Xr smf 5
       
    72 +repository.
       
    73  .It Fl d Ar delay
       
    74  Time in seconds to delay between automatic flushes of the file.
       
    75  This may be specified with a value between 5 and 3600 seconds.
       
    76  If not specified, the default is 60 seconds.
       
    77  .It Fl f Ar filename
       
    78 -Log output filename.
       
    79 +Log output filename. When neither
       
    80 +.Fl C
       
    81 +nor
       
    82 +.Fl c
       
    83 +is used, the default value
       
    84 +.Pa pflog.pkt
       
    85 +is used.
       
    86  .It Fl i Ar interface
       
    87  Specifies the capture link interface to use.
       
    88 -By default,
       
    89 -.Nm
       
    90 -will use
       
    91 -.Pa pflog0 .
       
    92 +When neither
       
    93 +.Fl C
       
    94 +nor
       
    95 +.Fl c
       
    96 +is used, the default value
       
    97 +.Pa pflog0
       
    98 +is assumed.
       
    99  .It Fl s Ar snaplen
       
   100  Analyze at most the first
       
   101  .Ar snaplen
       
   102 @@ -124,8 +155,6 @@
       
   103  The default of 160 is adequate for IP, ICMP, TCP, and UDP headers but may
       
   104  truncate protocol information for other protocols.
       
   105  Other file parsers may desire a higher snaplen.
       
   106 -.It Fl x
       
   107 -Check the integrity of an existing log file, and return.
       
   108  .It Ar expression
       
   109  Selects which packets will be dumped, using the regular language of
       
   110  .Xr tcpdump 8 .
       
   111 @@ -164,11 +193,59 @@
       
   112  The direction was outbound.
       
   113  .El
       
   114  .El
       
   115 -.Sh FILES
       
   116 -.Bl -tag -width /var/run/pflogd.pid -compact
       
   117 -.It Pa /var/log/firewall/pflog/pflog0.pkt
       
   118 -Default log file.
       
   119 +.Sh SOLARIS
       
   120 +The
       
   121 +.Nm
       
   122 +daemon must be started as an
       
   123 +.Xr smf 5
       
   124 +service with the following FMRI:
       
   125 +.Bd -literal -offset indent
       
   126 +svc:/network/firewall/pflog
       
   127 +.Ed
       
   128 +.Pp
       
   129 +Command line options described above are set via the following
       
   130 +.Xr smf 5
       
   131 +properties.
       
   132 +.Bl -tag -width "pflog/interface" -offset 3n -compact
       
   133 +.It pflog/delay
       
   134 +Automatic flush interval.
       
   135 +The default value is 60.
       
   136 +Used as the argument for the
       
   137 +.Fl d
       
   138 +option.
       
   139 +.It pflog/filter
       
   140 +Packet filter expression in
       
   141 +.Xr tcpdump 8
       
   142 +format.
       
   143 +No expression is defined by default.
       
   144 +.It pflog/interface
       
   145 +The capture link name from which to read packets.
       
   146 +Used as the argument for the
       
   147 +.Fl i
       
   148 +option.
       
   149 +.It pflog/logfile
       
   150 +Path to the logfile (for security reasons, only paths starting by the
       
   151 +.Pa /var/log/firewall/
       
   152 +directory are allowed.
       
   153 +Used as the argument for the
       
   154 +.Fl f
       
   155 +option.
       
   156 +.It pflog/snaplen
       
   157 +An upper bound on how many bytes from each packet to analyze.
       
   158 +The default value is 160.
       
   159 +Used as the argument for the
       
   160 +.Fl s
       
   161 +option.
       
   162  .El
       
   163 +.Pp
       
   164 +The start method creates a (temporal) capture link the particular
       
   165 +instance is using.
       
   166 +.Pp
       
   167 +The refresh method sends
       
   168 +.Dv SIGHUP
       
   169 +to
       
   170 +.Nm
       
   171 +owned by particular service instance.
       
   172  .Sh EXAMPLES
       
   173  Log specific TCP packets to a different log file with a large snaplen
       
   174  (useful with a
       
   175 @@ -202,6 +279,32 @@
       
   176  .Bd -literal -offset indent
       
   177  # tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0
       
   178  .Ed
       
   179 +.Sh SECURITY
       
   180 +The
       
   181 +.Nm
       
   182 +daemon is a privilege-aware application which runs as the
       
   183 +.Dq daemon
       
   184 +user possessing
       
   185 +.Sy PRIV_NET_OBSERVABILITY
       
   186 +privilege that is required for using
       
   187 +.Xr bpf 7d
       
   188 +to read packets. See
       
   189 +.Xr privileges 5
       
   190 +for details.
       
   191 +The service start method uses
       
   192 +.Xr dladm 1M
       
   193 +to create capture link if it does not exist already.
       
   194 +.Pp
       
   195 +To configure the
       
   196 +.Nm
       
   197 +service one has to obtain the
       
   198 +.Sy solaris.smf.value.network.firewall
       
   199 +authorization.
       
   200 +To manage the service (disable/enable/refresh) one must have the
       
   201 +.Sy solaris.smf.manage.network.firewall
       
   202 +authorization.
       
   203 +Both authorizations are granted through the Network Firewall Management profile.
       
   204 +To create new service instances, you need the solaris.smf.modify authorization.
       
   205  .Sh SEE ALSO
       
   206  .Xr pcap 3 ,
       
   207  .Xr pf.conf 5 ,
       
   208 diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.c pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.c
       
   209 --- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.c	2016-02-18 12:05:03.256562087 -0800
       
   210 +++ pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.c	2016-02-18 12:01:49.900876863 -0800
       
   211 @@ -54,6 +54,7 @@
       
   212  #include <strings.h>
       
   213  #include <zone.h>
       
   214  #include <libuutil.h>
       
   215 +#include "smf-config.h"
       
   216  #else /* !_SOLARIS_ */
       
   217  #include <util.h>
       
   218  #endif	/* _SOLARIS_ */
       
   219 @@ -63,7 +64,7 @@
       
   220  static FILE *dpcap;
       
   221  
       
   222  int Debug = 0;
       
   223 -static int snaplen = DEF_SNAPLEN;
       
   224 +static int64_t snaplen = DEF_SNAPLEN;
       
   225  static int cur_snaplen = DEF_SNAPLEN;
       
   226  
       
   227  volatile sig_atomic_t gotsig_close, gotsig_alrm, gotsig_hup, gotsig_usr1;
       
   228 @@ -75,7 +76,7 @@
       
   229  char errbuf[PCAP_ERRBUF_SIZE];
       
   230  
       
   231  int log_debug = 0;
       
   232 -unsigned int delay = FLUSH_DELAY;
       
   233 +int64_t delay = FLUSH_DELAY;
       
   234  
       
   235  char *copy_argv(char * const *);
       
   236  void  dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
       
   237 @@ -124,6 +125,15 @@
       
   238  
       
   239  #endif	/* _SOLARIS_ */
       
   240  
       
   241 +#ifdef	_SOLARIS_
       
   242 +#define	PFLOGD_GETOPTS	"c:C:Dd:f:i:s:"
       
   243 +#define	CFG_SETFLAG(_flags_, _f_)	((_flags_) |= (_f_))
       
   244 +#define	SKIP_CHK(_x_)	((_x_) == NULL)
       
   245 +#else /* !_SOLARIS_ */
       
   246 +#define	PFLOGD_GETOPTS	"Dxd:f:i:s:"
       
   247 +#define	CFG_SETFLAG(_flags_, _f_)
       
   248 +#define	SKIP_CHK(_x_)	(1)
       
   249 +#endif	/* _SOLARIS_ */
       
   250  static int try_reset_dump(int);
       
   251  
       
   252  /* buffer must always be greater than snaplen */
       
   253 @@ -290,6 +300,8 @@
       
   254  init_pcap(void)
       
   255  {
       
   256  	hpcap = pcap_open_live(interface, snaplen, 1, PCAP_TO_MS, errbuf);
       
   257 +	DROP_PRIV(PRIV_NET_OBSERVABILITY);
       
   258 +
       
   259  	if (hpcap == NULL) {
       
   260  		logmsg(LOG_ERR, "Failed to initialize: %s", errbuf);
       
   261  		return (-1);
       
   262 @@ -690,12 +702,20 @@
       
   263  	int ch, np, ret, Xflag = 0;
       
   264  	pcap_handler phandler = dump_packet;
       
   265  	const char *errstr = NULL;
       
   266 +#ifdef	_SOLARIS_
       
   267 +	unsigned int	create = 0;
       
   268 +	unsigned int	cfg_flags = 0;
       
   269 +	const char	*smf_instance = NULL;
       
   270 +#endif	/* _SOLARIS_ */
       
   271 +
       
   272 +	DROP_PRIV(PRIV_SYS_IP_CONFIG);
       
   273 +	DROP_PRIV(PRIV_PROC_EXEC);
       
   274  
       
   275  	ret = 0;
       
   276  
       
   277  	closefrom(STDERR_FILENO + 1);
       
   278  
       
   279 -	while ((ch = getopt(argc, argv, "Dxd:f:i:s:")) != -1) {
       
   280 +	while ((ch = getopt(argc, argv, PFLOGD_GETOPTS)) != -1) {
       
   281  		switch (ch) {
       
   282  		case 'D':
       
   283  			Debug = 1;
       
   284 @@ -704,12 +724,15 @@
       
   285  			delay = strtonum(optarg, 5, 60*60, &errstr);
       
   286  			if (errstr)
       
   287  				usage();
       
   288 +			CFG_SETFLAG(cfg_flags, SMF_CFG_DELAY_SET);
       
   289  			break;
       
   290  		case 'f':
       
   291  			filename = optarg;
       
   292 +			CFG_SETFLAG(cfg_flags, SMF_CFG_LOGFILE_SET);
       
   293  			break;
       
   294  		case 'i':
       
   295  			interface = optarg;
       
   296 +			CFG_SETFLAG(cfg_flags, SMF_CFG_INTERFACE_SET);
       
   297  			break;
       
   298  		case 's':
       
   299  			snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
       
   300 @@ -718,10 +741,27 @@
       
   301  				snaplen = DEF_SNAPLEN;
       
   302  			if (errstr)
       
   303  				snaplen = PFLOGD_MAXSNAPLEN;
       
   304 +			CFG_SETFLAG(cfg_flags, SMF_CFG_SNAPLEN_SET);
       
   305  			break;
       
   306 +#ifndef	_SOLARIS_
       
   307 +		/*
       
   308 +		 * This option requires a special securing on Solaris as
       
   309 +		 * pflogd will be started manually in the case it is used.
       
   310 +		 * Also, some polishing is needed so that the response
       
   311 +		 * from 'pflogd -x' is shown to the user and not put into
       
   312 +		 * a logfile.
       
   313 +		 */
       
   314  		case 'x':
       
   315  			Xflag++;
       
   316  			break;
       
   317 +#endif /* !_SOLARIS_ */
       
   318 +#ifdef	_SOLARIS_
       
   319 +		case 'C': 
       
   320 +			create = 1;	/* FALLTHRU */
       
   321 +		case 'c':
       
   322 +			smf_instance = optarg;
       
   323 +			break;
       
   324 +#endif	/* _SOLARIS_ */
       
   325  		default:
       
   326  			usage();
       
   327  		}
       
   328 @@ -732,14 +772,14 @@
       
   329  	argv += optind;
       
   330  
       
   331  	/* does interface exist */
       
   332 -	if (!if_exists(interface)) {
       
   333 +	if (SKIP_CHK(smf_instance) && !if_exists(interface)) {
       
   334  		warn("Failed to initialize: %s", interface);
       
   335  		logmsg(LOG_ERR, "Failed to initialize: %s", interface);
       
   336  		logmsg(LOG_ERR, "Exiting, init failure");
       
   337  		exit(1);
       
   338  	}
       
   339  
       
   340 -	if (!Debug) {
       
   341 +	if (SKIP_CHK(smf_instance) && !Debug) {
       
   342  		openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON);
       
   343  		if (daemon(0, 0)) {
       
   344  			logmsg(LOG_WARNING, "Failed to become daemon: %s",
       
   345 @@ -757,6 +797,31 @@
       
   346  			logmsg(LOG_NOTICE, "Failed to form filter expression");
       
   347  	}
       
   348  
       
   349 +#ifdef	_SOLARIS_
       
   350 +	if (smf_instance != NULL) {
       
   351 +		if (filter != NULL) {
       
   352 +			CFG_SETFLAG(cfg_flags, SMF_CFG_EXPRESSION_SET);
       
   353 +		} else {
       
   354 +			filter = "";
       
   355 +		}
       
   356 +		if ((cfg_flags == 0) && (create == 0)) {
       
   357 +			if (smf_print_pflogcfg(smf_instance)) {
       
   358 +				exit (-1);
       
   359 +			}
       
   360 +		} else {
       
   361 +			smf_pflogd_cfg.cfg_set = cfg_flags;
       
   362 +			smf_pflogd_cfg.cfg_expression = strdup(filter);
       
   363 +			smf_pflogd_cfg.cfg_interface = strdup(interface);
       
   364 +			smf_pflogd_cfg.cfg_logfile = strdup(filename);
       
   365 +			smf_pflogd_cfg.cfg_delay = delay;
       
   366 +			smf_pflogd_cfg.cfg_snaplen = snaplen;
       
   367 +
       
   368 +			smf_write_pflogcfg(smf_instance, create);
       
   369 +		}
       
   370 +		exit(0);
       
   371 +	}
       
   372 +#endif	/* _SOLARIS_ */
       
   373 +
       
   374  	/* initialize pcap before dropping privileges */
       
   375  	if (init_pcap()) {
       
   376  		logmsg(LOG_ERR, "Exiting, init failure");
       
   377 @@ -768,7 +833,6 @@
       
   378  		logmsg(LOG_ERR, "unable to privsep");
       
   379  		exit(1);
       
   380  	}
       
   381 -
       
   382  	setproctitle("[initializing]");
       
   383  	/* Process is now unprivileged and inside a chroot */
       
   384  #ifdef	_SOLARIS_
       
   385 diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.h pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.h
       
   386 --- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/pflogd.h	2016-02-18 12:08:42.414919276 -0800
       
   387 +++ pflogd-OPENBSD_5_5-OPENBSD_5_5/pflogd.h	2016-02-18 12:09:18.796727948 -0800
       
   388 @@ -18,6 +18,8 @@
       
   389  
       
   390  #ifdef	_SOLARIS_
       
   391  #include <limits.h>
       
   392 +#include <sys/types.h>
       
   393 +#include <priv.h>
       
   394  #else /* !_SOLARIS_ */
       
   395  #include <sys/limits.h>
       
   396  #endif	/* _SOLARIS_ */
       
   397 @@ -55,3 +57,27 @@
       
   398  int  receive_fd(int);
       
   399  
       
   400  extern int Debug;
       
   401 +
       
   402 +#ifdef _SOLARIS_
       
   403 +#define DROP_PRIV(priv)                                         \
       
   404 +	do {                                                    \
       
   405 +		if (priv_set(PRIV_OFF, PRIV_PERMITTED, (priv),  \
       
   406 +		    NULL) != 0) {                               \
       
   407 +			fprintf(stderr,                         \
       
   408 +			    "Unable to drop privileges.\n");    \
       
   409 +			exit (-1);                              \
       
   410 +		}                                               \
       
   411 +	} while (0)
       
   412 +
       
   413 +#define DROP_PFLAG(flag)				\
       
   414 +	do {						\
       
   415 +		if (setpflags((flag), 0) != 0) {	\
       
   416 +			fprintf(stderr,			\
       
   417 +			    "Unable to drop pflag.\n");	\
       
   418 +			exit (-1);			\
       
   419 +		}					\
       
   420 +} while (0)
       
   421 +#else /* !_SOLARIS_ */
       
   422 +#define DROP_PRIV(priv)
       
   423 +#define DROP_PFLAG(flag)
       
   424 +#endif /* _SOLARIS_ */
       
   425 diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/privsep.c pflogd-OPENBSD_5_5-OPENBSD_5_5/privsep.c
       
   426 --- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/privsep.c	2016-02-18 12:07:34.219667793 -0800
       
   427 +++ pflogd-OPENBSD_5_5-OPENBSD_5_5/privsep.c	2016-02-18 11:55:14.949135348 -0800
       
   428 @@ -112,6 +112,7 @@
       
   429  #endif	/* !_SOLARIS_ */
       
   430  
       
   431  	child_pid = fork();
       
   432 +	DROP_PRIV(PRIV_PROC_FORK);
       
   433  	if (child_pid < 0)
       
   434  		err(1, "fork() failed");
       
   435  
       
   436 @@ -133,6 +134,7 @@
       
   437  		if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
       
   438  			err(1, "setresuid() failed");
       
   439  #endif	/* !_SOLARIS_ */
       
   440 +		DROP_PFLAG(PRIV_XPOLICY);
       
   441  
       
   442  		close(socks[0]);
       
   443  		priv_fd = socks[1];
       
   444 diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/smf-config.c pflogd-OPENBSD_5_5-OPENBSD_5_5/smf-config.c
       
   445 --- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/smf-config.c	1969-12-31 16:00:00.000000000 -0800
       
   446 +++ pflogd-OPENBSD_5_5-OPENBSD_5_5/smf-config.c	2016-02-24 08:24:57.408744180 -0800
       
   447 @@ -0,0 +1,713 @@
       
   448 +/*
       
   449 + * CDDL HEADER START
       
   450 + *
       
   451 + * The contents of this file are subject to the terms of the
       
   452 + * Common Development and Distribution License (the "License").
       
   453 + * You may not use this file except in compliance with the License.
       
   454 + *
       
   455 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
   456 + * or http://www.opensolaris.org/os/licensing.
       
   457 + * See the License for the specific language governing permissions
       
   458 + * and limitations under the License.
       
   459 + *
       
   460 + * When distributing Covered Code, include this CDDL HEADER in each
       
   461 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
   462 + * If applicable, add the following below this CDDL HEADER, with the
       
   463 + * fields enclosed by brackets "[]" replaced with your own identifying
       
   464 + * information: Portions Copyright [yyyy] [name of copyright owner]
       
   465 + *
       
   466 + * CDDL HEADER END
       
   467 + *
       
   468 + */
       
   469 +
       
   470 +/*
       
   471 + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
       
   472 + */
       
   473 +
       
   474 +#include <string.h>
       
   475 +#include <strings.h>
       
   476 +#include <stdlib.h>
       
   477 +#include <err.h>
       
   478 +#include <stdarg.h>
       
   479 +#include <stdio.h>
       
   480 +#include <libscf.h>
       
   481 +#include <stddef.h>
       
   482 +#include <libscf_priv.h>
       
   483 +
       
   484 +#include "pflogd.h"
       
   485 +#include "smf-config.h"
       
   486 +
       
   487 +#define	PFLOGD_PG	"pflog"
       
   488 +#define PFLOGD_PROP_VALUE_AUTH	"value_authorization"
       
   489 +#define PFLOGD_PROP_ACTION_AUTH	"action_authorization"
       
   490 +#define PFLOGD_VALUE_AUTH	"solaris.smf.value.network.firewall"
       
   491 +#define PFLOGD_MANAGE_AUTH	"solaris.smf.manage.network.firewall"
       
   492 +
       
   493 +#define	SKIP_PROP(_pv_)		\
       
   494 +	((strcmp((_pv_)->pv_prop, "action_authorization") == 0) || \
       
   495 +	(strcmp((_pv_)->pv_prop, "value_authorization") == 0))
       
   496 +
       
   497 +#define	STRIP_SVC(_x_)	((_x_) + (sizeof ("svc:/") - 1))
       
   498 +
       
   499 +/*
       
   500 + * smf_pflogd_cfg
       
   501 + * FTP proxy configuration container.
       
   502 + */
       
   503 +smf_pflogd_cfg_t	smf_pflogd_cfg;
       
   504 +
       
   505 +#define	SMF_OPT_OPTIONAL	0
       
   506 +#define	SMF_OPT_MANDATORY	1
       
   507 +/*
       
   508 + * X-macro table.
       
   509 + * Columns are as follows:
       
   510 + * 	value key/index 
       
   511 + *	SMF property name name
       
   512 + *	member in smf_pflogd_cfg_t structure
       
   513 + *	function which converts ASCIIZ to member type in smf_pflogd_cfg_t
       
   514 + *	function which converts member in smf_pflogd_cfg_t to ASCIIZ
       
   515 + *	optional/mandatory status
       
   516 + *      property type
       
   517 + */
       
   518 +#define	X_CFG_PROPS	\
       
   519 +	X(SMF_LOGFILE, "logfile", cfg_logfile, nop_in, nop_out,		\
       
   520 +	    SMF_OPT_MANDATORY, SCF_TYPE_ASTRING)			\
       
   521 +	X(SMF_SNAPLEN, "snaplen", cfg_snaplen, int_in, int_out,		\
       
   522 +	    SMF_OPT_MANDATORY, SCF_TYPE_INTEGER)			\
       
   523 +	X(SMF_INTERFACE, "interface", cfg_interface, nop_in, nop_out,	\
       
   524 +	    SMF_OPT_MANDATORY, SCF_TYPE_ASTRING)			\
       
   525 +	X(SMF_DELAY, "delay",	cfg_delay, int_in, int_out,		\
       
   526 +	    SMF_OPT_OPTIONAL, SCF_TYPE_INTEGER)				\
       
   527 +	X(SMF_EXPRESSION, "filter", cfg_expression, nop_in, nop_out,	\
       
   528 +	    SMF_OPT_OPTIONAL, SCF_TYPE_ASTRING)
       
   529 +
       
   530 +static void nop_in(void *, void *);
       
   531 +static void nop_out(void *, void *);
       
   532 +static void int_in(void *, void *);
       
   533 +static void int_out(void *, void *);
       
   534 +
       
   535 +/*
       
   536 + * smf_keys
       
   537 + * Keys (indexes) to `smf_propnames` dictionary.
       
   538 + */
       
   539 +#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
       
   540 +    _type_) _const_,
       
   541 +enum smf_keys {
       
   542 +	X_CFG_PROPS
       
   543 +	SMF_CFG_PROP_COUNT
       
   544 +};
       
   545 +#undef	X
       
   546 +
       
   547 +/*
       
   548 + * smf_propnames
       
   549 + * It's an array (dictionary), which translates property code (SMF_*) to
       
   550 + * property value name found `ftp-proxy` property group.
       
   551 + */
       
   552 +#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
       
   553 +    _type_) _propname_,
       
   554 +static const char *smf_propnames[] = {
       
   555 +	X_CFG_PROPS
       
   556 +	NULL
       
   557 +};
       
   558 +#undef	X
       
   559 +
       
   560 +/*
       
   561 + * smf_cfg_offsets
       
   562 + * Table of smf_pflogd_cfg_t members.
       
   563 + */
       
   564 +#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
       
   565 +    _type_) offsetof(smf_pflogd_cfg_t, _decl_),
       
   566 +static size_t smf_cfg_offsets[] = {
       
   567 +	X_CFG_PROPS
       
   568 +	sizeof (smf_pflogd_cfg_t)
       
   569 +};
       
   570 +#undef	X
       
   571 +
       
   572 +typedef void(*conv_in_f)(void *, void *);
       
   573 +typedef void(*conv_out_f)(void *, void *);
       
   574 +/*
       
   575 + * smf_convert_in
       
   576 + * Table of conversion functions, which convert particular smf_pflogd_cfg_t
       
   577 + * member into ASCIIZ.
       
   578 + */
       
   579 +#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
       
   580 +    _type_) _conv_in_,
       
   581 +static conv_in_f smf_conv_in[] = {
       
   582 +	X_CFG_PROPS
       
   583 +	NULL
       
   584 +};
       
   585 +#undef	X
       
   586 +
       
   587 +/*
       
   588 + * smf_conv_out
       
   589 + * Table of conversion functions, which convert ASCIIZ fetched from smf(5)
       
   590 + * repository to member of smf_pflogd_cfg_t structure.
       
   591 + */
       
   592 +#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
       
   593 +    _type_) _conv_out_,
       
   594 +static conv_out_f smf_conv_out[] = {
       
   595 +	X_CFG_PROPS
       
   596 +	NULL
       
   597 +};
       
   598 +#undef	X
       
   599 +
       
   600 +/*
       
   601 + * smf_mandatory
       
   602 + * Table marks configuration parameters, which must be defined by admin,
       
   603 + * before the service is enabled for the first time.
       
   604 + */
       
   605 +#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
       
   606 +    _type_) _mandatory_,
       
   607 +static int smf_mandatory[] = {
       
   608 +	X_CFG_PROPS
       
   609 +	0
       
   610 +};
       
   611 +#undef	X
       
   612 +
       
   613 +/*
       
   614 + * smf_type
       
   615 + * Table of types of SMF properties.
       
   616 + */
       
   617 +#define	X(_const_, _propname_, _decl_, _conv_in_, _conv_out_, _mandatory_, \
       
   618 +    _type_) _type_,
       
   619 +static int smf_type[] = {
       
   620 +	X_CFG_PROPS
       
   621 +	0
       
   622 +};
       
   623 +#undef	X
       
   624 +
       
   625 +/*
       
   626 + * pflogd property group properties
       
   627 + * +1 for NULL termination.
       
   628 + * +1 for value_authorization
       
   629 + */
       
   630 +static scf_propvec_t	prop_vec[SMF_CFG_PROP_COUNT + 1 + 1];
       
   631 +
       
   632 +/*
       
   633 + * general property group properties
       
   634 + * +1 for NULL termination.
       
   635 + * +2 for value_authorization/action_authorization
       
   636 + */
       
   637 +static scf_propvec_t	gen_prop_vec[1 + 2];
       
   638 +
       
   639 +static int atexit_set = 0;
       
   640 +static int complete_pflogdcfg(const char *);
       
   641 +
       
   642 +/*
       
   643 + * nop_in()
       
   644 + * Dummy conversion ASCIIZ to ASCIIZ, no allocation happens. Used when
       
   645 + * configuration is from smf(5).
       
   646 + */
       
   647 +static void
       
   648 +nop_in(void *asciiz, void *result)
       
   649 +{
       
   650 +	*((char **)result) = (char *)asciiz;
       
   651 +}
       
   652 +
       
   653 +/*
       
   654 + * nop_out()
       
   655 + * Dummy conversion ASCIIZ to ASCIIZ, function allocates memory for result by
       
   656 + * strdup(3C). Used when configuration is written to smf(5) repository.
       
   657 + */
       
   658 +static void
       
   659 +nop_out(void *asciiz, void *val)
       
   660 +{
       
   661 +	*((char **)asciiz) = strdup(*(char **)val);
       
   662 +}
       
   663 +
       
   664 +/*
       
   665 + * int_in()
       
   666 + * Dummy conversion of int64_t. No allocation happens. Used when reading
       
   667 + * values from smf.
       
   668 + */
       
   669 +static void
       
   670 +int_in(void *in, void *out) {
       
   671 +	*((int64_t *)out) = *((int64_t *)in);
       
   672 +}
       
   673 +
       
   674 +/*
       
   675 + * int_out()
       
   676 + * Dummy conversion of int64_t, storing into a newly allocated memory.
       
   677 + * Used when storing values to smf repository.
       
   678 + */
       
   679 +static void
       
   680 +int_out(void *out, void *in) {
       
   681 +	int64_t **out_ = (int64_t **)out;
       
   682 +
       
   683 +	*out_ = malloc(sizeof (int64_t));
       
   684 +	if (*out_ != NULL)
       
   685 +		**out_ = *((int64_t *)in);
       
   686 +}
       
   687 +
       
   688 +static void
       
   689 +clear_prop_vec2(scf_propvec_t *prop_vec_ptr, int count)
       
   690 +{
       
   691 +	while (count--) {
       
   692 +		prop_vec_ptr->pv_prop = NULL;
       
   693 +		prop_vec_ptr->pv_desc = NULL;
       
   694 +		prop_vec_ptr->pv_type = 0;
       
   695 +		prop_vec_ptr->pv_aux = 0;
       
   696 +		prop_vec_ptr->pv_mval = 0;
       
   697 +
       
   698 +		if (prop_vec_ptr->pv_ptr != NULL) {
       
   699 +			free(prop_vec_ptr->pv_ptr);
       
   700 +			prop_vec_ptr->pv_ptr = NULL;
       
   701 +		}
       
   702 +
       
   703 +		prop_vec_ptr++;
       
   704 +	}
       
   705 +}
       
   706 +
       
   707 +/*
       
   708 + * clear_prop_vec()
       
   709 + * Function clears global variables `prop_vec` and `gen_prop_vec`,
       
   710 + * which are vectors of properties.
       
   711 + */
       
   712 +static void
       
   713 +clear_prop_vec()
       
   714 +{
       
   715 +	clear_prop_vec2(prop_vec,
       
   716 +	    sizeof (prop_vec) / sizeof (scf_propvec_t));
       
   717 +	clear_prop_vec2(gen_prop_vec,
       
   718 +	    sizeof (gen_prop_vec) / sizeof (scf_propvec_t));
       
   719 +}
       
   720 +
       
   721 +/*
       
   722 + * cfg_to_prop_vec()
       
   723 + * Function converts smf_pflogd_cfg global variable, which holds configuration
       
   724 + * parsed from command line arguments, to prop_vec, which is a smf(5) friendly
       
   725 + * representation of pflogd configuration. 
       
   726 + *
       
   727 + * Additionally, it populates gen_prop_vec to specify needed authorizations.
       
   728 + *
       
   729 + * Returns 0 on success, -1 on out of memory error.
       
   730 + */
       
   731 +static int
       
   732 +cfg_to_prop_vec(void)
       
   733 +{
       
   734 +	int		cfg_bit = 1;
       
   735 +	int		i;
       
   736 +	scf_propvec_t	*prop_vec_ptr = prop_vec;
       
   737 +	conv_out_f	conv_func;
       
   738 +
       
   739 +	clear_prop_vec();
       
   740 +
       
   741 +	for (i = 0; i < SMF_CFG_PROP_COUNT; i++) {
       
   742 +		if ((smf_pflogd_cfg.cfg_set & cfg_bit) != 0) {
       
   743 +			prop_vec_ptr->pv_prop = smf_propnames[i];
       
   744 +			conv_func = smf_conv_out[i];
       
   745 +
       
   746 +			conv_func(&prop_vec_ptr->pv_ptr,
       
   747 +			    ((char *)&smf_pflogd_cfg + smf_cfg_offsets[i]));
       
   748 +			if (prop_vec_ptr->pv_ptr == NULL)
       
   749 +				return (-1);
       
   750 +			prop_vec_ptr->pv_type = smf_type[i];
       
   751 +			prop_vec_ptr++;
       
   752 +		}
       
   753 +		cfg_bit = cfg_bit << 1;
       
   754 +	}
       
   755 +	prop_vec_ptr->pv_type = SCF_TYPE_ASTRING;
       
   756 +	prop_vec_ptr->pv_prop = PFLOGD_PROP_VALUE_AUTH;
       
   757 +	prop_vec_ptr->pv_ptr = strdup(PFLOGD_VALUE_AUTH);
       
   758 +	prop_vec_ptr++;
       
   759 +
       
   760 +	gen_prop_vec[0].pv_type = SCF_TYPE_ASTRING;
       
   761 +	gen_prop_vec[0].pv_prop = PFLOGD_PROP_VALUE_AUTH;
       
   762 +	gen_prop_vec[0].pv_ptr = strdup(PFLOGD_MANAGE_AUTH);
       
   763 +	gen_prop_vec[1].pv_type = SCF_TYPE_ASTRING;
       
   764 +	gen_prop_vec[1].pv_prop = PFLOGD_PROP_ACTION_AUTH;
       
   765 +	gen_prop_vec[1].pv_ptr = strdup(PFLOGD_MANAGE_AUTH);
       
   766 +
       
   767 +	return (0);
       
   768 +}
       
   769 +
       
   770 +/*
       
   771 + * prop_vec_to_cfg()
       
   772 + * Converts global variable `prop_vec` to `smf_pflogd_cfg` global variable,
       
   773 + * which is understood by main().
       
   774 + */
       
   775 +static void
       
   776 +prop_vec_to_cfg(void)
       
   777 +{
       
   778 +	int		i;
       
   779 +	scf_propvec_t	*prop_vec_ptr = prop_vec;
       
   780 +	conv_in_f	conv_func;
       
   781 +
       
   782 +	for (i = 0; i < SMF_CFG_PROP_COUNT; i++, prop_vec_ptr++) {
       
   783 +		if (SKIP_PROP(prop_vec_ptr)) {
       
   784 +			/*
       
   785 +			 * We have `hidden` properties: action/value smf
       
   786 +			 * authorization. Those two are not kept in
       
   787 +			 * smf_ftp_cfg.
       
   788 +			 *
       
   789 +			 * So we must to skip to next property in vector
       
   790 +			 * without letting for loop to advance its counter, so
       
   791 +			 * we compensate here by doing `i--`.
       
   792 +			 */
       
   793 +			i--;
       
   794 +			continue;
       
   795 +		};
       
   796 +		conv_func = smf_conv_in[i];
       
   797 +		conv_func(prop_vec_ptr->pv_ptr,
       
   798 +		    ((char *)&smf_pflogd_cfg + smf_cfg_offsets[i]));
       
   799 +	}
       
   800 +}
       
   801 +
       
   802 +/*
       
   803 + * smf_print_pflogcfg()
       
   804 + * Function loads pflogdcfg from smf(5) repository and prints configuration to
       
   805 + * standard output. We use `scf_simple_prop_get(3SCF)`.
       
   806 + *
       
   807 + * Returns 0 on success, -1 on error.
       
   808 + */
       
   809 +int
       
   810 +smf_print_pflogcfg(const char *smf_instance)
       
   811 +{
       
   812 +	scf_simple_prop_t	*prop;
       
   813 +	char			*propval;
       
   814 +	int			i;
       
   815 +	scf_propvec_t		*prop_vec_ptr = prop_vec;
       
   816 +	int			cfg_undefined = 0;
       
   817 +	char			*fmri;
       
   818 +
       
   819 +	if (atexit_set == 0) {
       
   820 +		atexit(clear_prop_vec);
       
   821 +		bzero(&smf_pflogd_cfg, sizeof (smf_pflogd_cfg_t));
       
   822 +		atexit_set = 1;
       
   823 +	}
       
   824 +
       
   825 +	(void) asprintf(&fmri, "%s:%s", BASE_FMRI, smf_instance);
       
   826 +	if (fmri == NULL) {
       
   827 +		fprintf(stderr, "Out of memory.\n");
       
   828 +		return (-1);
       
   829 +	}
       
   830 +
       
   831 +	clear_prop_vec();
       
   832 +
       
   833 +	for (i = 0; i < SMF_CFG_PROP_COUNT; i++) {
       
   834 +		prop = scf_simple_prop_get(NULL, fmri, PFLOGD_PG,
       
   835 +		    smf_propnames[i]);
       
   836 +		prop_vec_ptr->pv_prop = smf_propnames[i];
       
   837 +
       
   838 +		if (prop == NULL) {
       
   839 +			/*
       
   840 +			 * Property not defined, so we create a kind of
       
   841 +			 * 'placeholder' with empty value.
       
   842 +			 *
       
   843 +			 * calloc() works well for both astring and integer.
       
   844 +			 */
       
   845 +			prop_vec_ptr->pv_type = smf_type[i];
       
   846 +			prop_vec_ptr->pv_ptr = calloc(1, sizeof (int64_t));
       
   847 +			cfg_undefined |= smf_mandatory[i];
       
   848 +		} else {
       
   849 +			prop_vec_ptr->pv_type = scf_simple_prop_type(prop);
       
   850 +			if (prop_vec_ptr->pv_type == -1) {
       
   851 +				free(fmri);
       
   852 +				fprintf(stderr,
       
   853 +				    "Failed to get property type.\n");
       
   854 +				return (-1);
       
   855 +			}
       
   856 +			if (prop_vec_ptr->pv_type != smf_type[i]) {
       
   857 +				free(fmri);
       
   858 +				fprintf(stderr,
       
   859 +				    "Property %s has unexpected type.\n",
       
   860 +				    smf_propnames[i]);
       
   861 +				return (-1);
       
   862 +			}
       
   863 +
       
   864 +			if (smf_type[i] == SCF_TYPE_ASTRING) {
       
   865 +				char	*propval;
       
   866 +				propval = scf_simple_prop_next_astring(prop);
       
   867 +				if (propval == NULL) {
       
   868 +					propval = "";
       
   869 +				}
       
   870 +				prop_vec_ptr->pv_ptr = strdup(propval);
       
   871 +
       
   872 +				if (propval[0] == 0) {
       
   873 +					cfg_undefined |= smf_mandatory[i];
       
   874 +				}
       
   875 +			} else {
       
   876 +				/* smf_type[i] == SCF_TYPE_INTEGER */
       
   877 +				int64_t	*propval;
       
   878 +				int64_t propval_;
       
   879 +
       
   880 +				propval = scf_simple_prop_next_integer(prop);
       
   881 +				propval_ = (propval == NULL) ? (0) : (*propval);
       
   882 +
       
   883 +				prop_vec_ptr->pv_ptr = malloc(sizeof (int64_t));
       
   884 +				if (prop_vec_ptr->pv_ptr != NULL) {
       
   885 +					*((int64_t *)prop_vec_ptr->pv_ptr) =
       
   886 +					    propval_;
       
   887 +				}
       
   888 +				if (propval_ == 0) {
       
   889 +					cfg_undefined |= smf_mandatory[i];
       
   890 +				}
       
   891 +			}
       
   892 +			scf_simple_prop_free(prop);
       
   893 +		}
       
   894 +		if (prop_vec_ptr->pv_ptr == NULL) {
       
   895 +			free(fmri);
       
   896 +			fprintf(stderr, "Out of memory.\n");
       
   897 +			return (-1);
       
   898 +		}
       
   899 +
       
   900 +		prop_vec_ptr++;
       
   901 +	}
       
   902 +
       
   903 +	printf("PF pflogd configuration:\n");
       
   904 +
       
   905 +	prop_vec_ptr = prop_vec;
       
   906 +	for (i = 0; i < SMF_CFG_PROP_COUNT; i++) {
       
   907 +		if (smf_type[i] == SCF_TYPE_ASTRING) {
       
   908 +			const char *val = (const char *)prop_vec_ptr->pv_ptr;
       
   909 +			printf("\t- %s:\n\t\t%s\n", prop_vec_ptr->pv_prop,
       
   910 +			    ((val[0] == '\0') ?  "?? undefined ??" : val));
       
   911 +		} else {
       
   912 +			/* smf_type[i] == SCF_TYPE_INTEGER */
       
   913 +			int64_t val = *((int64_t *)prop_vec_ptr->pv_ptr);
       
   914 +			if (val == 0) {
       
   915 +				printf("\t- %s:\n\t\t%s\n", prop_vec_ptr->pv_prop,
       
   916 +			    	    "?? undefined ??");
       
   917 +			} else {
       
   918 +				printf("\t- %s:\n\t\t%d\n", prop_vec_ptr->pv_prop,
       
   919 +			    	    (int)val);
       
   920 +			}
       
   921 +		}
       
   922 +		prop_vec_ptr++;
       
   923 +	}
       
   924 +	if (cfg_undefined) {
       
   925 +		printf("\n\nConfiguration for %s is incomplete."
       
   926 +		    " Service will not run.\n\n", fmri);
       
   927 +	} else {
       
   928 +		prop_vec_to_cfg();
       
   929 +		printf(
       
   930 +		    "\n\n%s service is being launched using cmd line below\n",
       
   931 +		    fmri);
       
   932 +		printf("pflogd -d %d -i %s -s %d -f %s %s\n\n",
       
   933 +		    (int)smf_pflogd_cfg.cfg_delay, smf_pflogd_cfg.cfg_interface,
       
   934 +		    (int)smf_pflogd_cfg.cfg_snaplen, smf_pflogd_cfg.cfg_logfile,
       
   935 +		    smf_pflogd_cfg.cfg_expression);
       
   936 +	}
       
   937 +
       
   938 +	free(fmri);
       
   939 +
       
   940 +	return (0);
       
   941 +}
       
   942 +
       
   943 +/*
       
   944 + * smf_create_pflogd_instance()
       
   945 + * Function creates a new instance in smf(5) repository.
       
   946 + */
       
   947 +static int
       
   948 +smf_create_pflogd_instance(const char *smf_instance)
       
   949 +{
       
   950 +	scf_handle_t	*h_scf = NULL;
       
   951 +	scf_scope_t	*scp_scf = NULL;
       
   952 +	scf_service_t	*svc_scf = NULL;
       
   953 +	scf_instance_t	*sin_scf = NULL;
       
   954 +	int	rv = -1;
       
   955 +
       
   956 + 	h_scf = scf_handle_create(SCF_VERSION);
       
   957 +	if ((h_scf == NULL) || (scf_handle_bind(h_scf) == -1)) {
       
   958 +		(void) fprintf(stderr, "scf_handle_bind() failed - %s\n",
       
   959 +		    scf_strerror(scf_error()));
       
   960 +		if (h_scf != NULL) {
       
   961 +			scf_handle_destroy(h_scf);
       
   962 +		}
       
   963 +		return (-1);
       
   964 +	}
       
   965 +
       
   966 +	if ((scp_scf = scf_scope_create(h_scf)) == NULL) {
       
   967 +		(void) fprintf(stderr, "could not create scope - %s\n",
       
   968 +		    scf_strerror(scf_error()));
       
   969 +		goto unbind;
       
   970 +	}
       
   971 +
       
   972 +	if (scf_handle_get_local_scope(h_scf, scp_scf) != 0) {
       
   973 +		(void) fprintf(stderr, "could not get scope - %s\n",
       
   974 +		    scf_strerror(scf_error()));
       
   975 +		goto scope_destroy;
       
   976 +	}
       
   977 +
       
   978 +	if ((svc_scf = scf_service_create(h_scf)) == NULL) {
       
   979 +		(void) fprintf(stderr, "could not create service - %s\n",
       
   980 +		    scf_strerror(scf_error()));
       
   981 +		goto scope_destroy;
       
   982 +	}
       
   983 +
       
   984 +	if ((sin_scf = scf_instance_create(h_scf)) == NULL) {
       
   985 +		(void) fprintf(stderr, "could not get instance handle - %s\n",
       
   986 +		    scf_strerror(scf_error()));
       
   987 +		goto service_destroy;
       
   988 +	}
       
   989 +
       
   990 +	if (scf_scope_get_service(scp_scf, STRIP_SVC(BASE_FMRI), svc_scf) !=
       
   991 +	    SCF_SUCCESS) {
       
   992 +		(void) fprintf(stderr, "could not select service (%s)\n",
       
   993 +		    scf_strerror(scf_error()));
       
   994 +		goto instance_destroy;
       
   995 +	}
       
   996 +
       
   997 +	if (scf_service_add_instance(svc_scf, smf_instance, sin_scf) != 0) {
       
   998 +		(void) fprintf(stderr, "could not add %s instance - %s\n",
       
   999 +		    smf_instance, scf_strerror(scf_error()));
       
  1000 +		goto instance_destroy;
       
  1001 +	}
       
  1002 +
       
  1003 +	if (scf_instance_add_pg(sin_scf, "general", "framework", 0,
       
  1004 +	    NULL) != SCF_SUCCESS) {
       
  1005 +		(void) fprintf(stderr,
       
  1006 +		    "could not create property group - %s\n",
       
  1007 +		    scf_strerror(scf_error()));
       
  1008 +		goto instance_delete;
       
  1009 +	}
       
  1010 +
       
  1011 +	if (scf_instance_add_pg(sin_scf, PFLOGD_PG, "application", 0,
       
  1012 +	    NULL) != SCF_SUCCESS) {
       
  1013 +		(void) fprintf(stderr,
       
  1014 +		    "could not create property group - %s\n",
       
  1015 +		    scf_strerror(scf_error()));
       
  1016 +		goto instance_delete;
       
  1017 +	}
       
  1018 +
       
  1019 +	rv = 0;
       
  1020 +	goto instance_destroy;
       
  1021 +
       
  1022 +instance_delete:
       
  1023 +	if (scf_instance_delete(sin_scf) != 0) {
       
  1024 +		fprintf(stderr, "Can't delete the newly created instance:");
       
  1025 +		fprintf(stderr, "\t%s\n", scf_strerror(scf_error()));
       
  1026 +	}
       
  1027 +instance_destroy:
       
  1028 +	scf_instance_destroy(sin_scf);
       
  1029 +service_destroy:
       
  1030 +	scf_service_destroy(svc_scf);
       
  1031 +scope_destroy:
       
  1032 +	scf_scope_destroy(scp_scf);
       
  1033 +unbind:
       
  1034 +	scf_handle_unbind(h_scf);
       
  1035 +	scf_handle_destroy(h_scf);
       
  1036 +
       
  1037 +	return (rv);
       
  1038 +}
       
  1039 +
       
  1040 +/*
       
  1041 + * smf_write_pflogcfg()
       
  1042 + * Function writes pflogd configuration to smf(5) repository.
       
  1043 + */
       
  1044 +int
       
  1045 +smf_write_pflogcfg(const char *smf_instance, int create)
       
  1046 +{
       
  1047 +	int	i;
       
  1048 +	scf_propvec_t
       
  1049 +		*bad_prop_vec = NULL;
       
  1050 +	char	*fmri;
       
  1051 +
       
  1052 +	if (atexit_set == 0) {
       
  1053 +		atexit(clear_prop_vec);
       
  1054 +		bzero(prop_vec, sizeof (prop_vec));
       
  1055 +		atexit_set = 1;
       
  1056 +	}
       
  1057 +
       
  1058 +	if (create && (complete_pflogdcfg(smf_instance) != 0)) {
       
  1059 +		fprintf(stderr, "Out of memory.\n");
       
  1060 +		return (-1);
       
  1061 +	}
       
  1062 +
       
  1063 +	if (cfg_to_prop_vec() != 0) {
       
  1064 +		fprintf(stderr, "Out of memory.\n");
       
  1065 +		return (-1);
       
  1066 +	}
       
  1067 +
       
  1068 +	(void) asprintf(&fmri, "%s:%s", BASE_FMRI, smf_instance);
       
  1069 +	if (fmri == NULL) {
       
  1070 +		fprintf(stderr, "Out of memory.\n");
       
  1071 +		return (-1);
       
  1072 +	}
       
  1073 +
       
  1074 +	if (create) {
       
  1075 +		if (smf_create_pflogd_instance(smf_instance) != 0) {
       
  1076 +			free(fmri);
       
  1077 +			return (-1);
       
  1078 +		}
       
  1079 +	}
       
  1080 +
       
  1081 +	if (create && (scf_write_propvec(fmri, "general", gen_prop_vec,
       
  1082 +	    &bad_prop_vec) != SCF_SUCCESS)) {
       
  1083 +		fprintf(stderr, "Can't update %s configuration:", fmri);
       
  1084 +		fprintf(stderr, "\t%s\n", scf_strerror(scf_error()));
       
  1085 +		if (bad_prop_vec != NULL) {
       
  1086 +			fprintf(stderr, "Could not set %s\n",
       
  1087 +			    bad_prop_vec->pv_prop);
       
  1088 +		}
       
  1089 +		free(fmri);
       
  1090 +		exit(1);
       
  1091 +	}
       
  1092 +
       
  1093 +	bad_prop_vec = NULL;
       
  1094 +	if (scf_write_propvec(fmri, PFLOGD_PG, prop_vec, &bad_prop_vec)
       
  1095 +	    != SCF_SUCCESS) {
       
  1096 +		fprintf(stderr, "Can't update %s configuration:", fmri);
       
  1097 +		fprintf(stderr, "\t%s\n", scf_strerror(scf_error()));
       
  1098 +		if (bad_prop_vec != NULL) {
       
  1099 +			fprintf(stderr, "Could not set %s\n",
       
  1100 +			    bad_prop_vec->pv_prop);
       
  1101 +		}
       
  1102 +		free(fmri);
       
  1103 +		exit(1);
       
  1104 +	}
       
  1105 +
       
  1106 +	free(fmri);
       
  1107 +	return (0);
       
  1108 +}
       
  1109 +
       
  1110 +/*
       
  1111 + * complete_pflogdcfg()
       
  1112 + * Function sets default values to properties, which are unset/undefined when
       
  1113 + * new smf(5) instance is being created.
       
  1114 + *
       
  1115 + * Returns 0 on success, -1 on out of memory error.
       
  1116 + */
       
  1117 +static int
       
  1118 +complete_pflogdcfg(const char *smf_instance)
       
  1119 +{
       
  1120 +	int	i;
       
  1121 +	int	f = 1;
       
  1122 +
       
  1123 +	for (i = 0; i < SMF_CFG_PROP_COUNT; i++) {
       
  1124 +		if ((smf_pflogd_cfg.cfg_set & f) == 0) {
       
  1125 +			switch (i) {
       
  1126 +			case SMF_LOGFILE:
       
  1127 +				(void) asprintf(&smf_pflogd_cfg.cfg_logfile,
       
  1128 +				    "%s/%s", PFLOGD_LOG_DIR, smf_instance);
       
  1129 +				if (smf_pflogd_cfg.cfg_logfile == NULL) {
       
  1130 +					return (-1);
       
  1131 +				}
       
  1132 +				smf_pflogd_cfg.cfg_set |= SMF_CFG_LOGFILE_SET;	
       
  1133 +				break;
       
  1134 +			case SMF_INTERFACE:
       
  1135 +				smf_pflogd_cfg.cfg_interface = strdup(smf_instance);
       
  1136 +				if (smf_pflogd_cfg.cfg_interface == NULL) {
       
  1137 +					return (-1);
       
  1138 +				}
       
  1139 +				smf_pflogd_cfg.cfg_set |= SMF_CFG_INTERFACE_SET;
       
  1140 +				break;
       
  1141 +			case SMF_SNAPLEN:
       
  1142 +				smf_pflogd_cfg.cfg_snaplen = DEF_SNAPLEN;
       
  1143 +				smf_pflogd_cfg.cfg_set |= SMF_CFG_SNAPLEN_SET;
       
  1144 +				break;
       
  1145 +			case SMF_DELAY:
       
  1146 +				smf_pflogd_cfg.cfg_delay = FLUSH_DELAY;
       
  1147 +				smf_pflogd_cfg.cfg_set |= SMF_CFG_DELAY_SET;
       
  1148 +				break;
       
  1149 +			case SMF_EXPRESSION:
       
  1150 +				smf_pflogd_cfg.cfg_expression = strdup("");
       
  1151 +				smf_pflogd_cfg.cfg_set |= SMF_CFG_EXPRESSION_SET;
       
  1152 +				break;
       
  1153 +			default: ;
       
  1154 +			}
       
  1155 +		}
       
  1156 +		f = f << 1;
       
  1157 +	}
       
  1158 +
       
  1159 +	return (0);
       
  1160 +}
       
  1161 diff -Naur pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/smf-config.h pflogd-OPENBSD_5_5-OPENBSD_5_5/smf-config.h
       
  1162 --- pflogd-OPENBSD_5_5-OPENBSD_5_5.pre-smf/smf-config.h	1969-12-31 16:00:00.000000000 -0800
       
  1163 +++ pflogd-OPENBSD_5_5-OPENBSD_5_5/smf-config.h	2016-02-17 01:17:14.520118386 -0800
       
  1164 @@ -0,0 +1,53 @@
       
  1165 +/*
       
  1166 + * CDDL HEADER START
       
  1167 + *
       
  1168 + * The contents of this file are subject to the terms of the
       
  1169 + * Common Development and Distribution License (the "License").
       
  1170 + * You may not use this file except in compliance with the License.
       
  1171 + *
       
  1172 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
  1173 + * or http://www.opensolaris.org/os/licensing.
       
  1174 + * See the License for the specific language governing permissions
       
  1175 + * and limitations under the License.
       
  1176 + *
       
  1177 + * When distributing Covered Code, include this CDDL HEADER in each
       
  1178 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
  1179 + * If applicable, add the following below this CDDL HEADER, with the
       
  1180 + * fields enclosed by brackets "[]" replaced with your own identifying
       
  1181 + * information: Portions Copyright [yyyy] [name of copyright owner]
       
  1182 + *
       
  1183 + * CDDL HEADER END
       
  1184 + *
       
  1185 + */
       
  1186 +
       
  1187 +/*
       
  1188 + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
       
  1189 + */
       
  1190 +
       
  1191 +#ifndef	_SMF_CONFIG_H_
       
  1192 +#define	_SMF_CONFIG_H_
       
  1193 +
       
  1194 +#define	BASE_FMRI		"svc:/network/firewall/pflog"
       
  1195 +#define	DEFAULT_INSTANCE	"pflog0"
       
  1196 +
       
  1197 +#define	SMF_CFG_LOGFILE_SET	0x00000001
       
  1198 +#define	SMF_CFG_SNAPLEN_SET	0x00000002
       
  1199 +#define	SMF_CFG_INTERFACE_SET	0x00000004
       
  1200 +#define	SMF_CFG_DELAY_SET	0x00000008
       
  1201 +#define	SMF_CFG_EXPRESSION_SET	0x00000010
       
  1202 +
       
  1203 +typedef struct smf_pflogd_cfg {
       
  1204 +	unsigned int	cfg_set;	/* SMF_CFG_*_SET bit field */
       
  1205 +	char		*cfg_logfile;
       
  1206 +	int64_t		cfg_snaplen;
       
  1207 +	char 		*cfg_interface;
       
  1208 +	int64_t		cfg_delay;
       
  1209 +	char		*cfg_expression;
       
  1210 +} smf_pflogd_cfg_t;
       
  1211 +
       
  1212 +extern smf_pflogd_cfg_t	smf_pflogd_cfg;
       
  1213 +
       
  1214 +extern int smf_print_pflogcfg(const char *);
       
  1215 +extern int smf_write_pflogcfg(const char *, int);
       
  1216 +
       
  1217 +#endif	/* !_SMF_CONFIG_H_ */