17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
59291337pwernau * Common Development and Distribution License (the "License").
69291337pwernau * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
22130b5e3Dan McDonald * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bdstevel@tonic-gate */
247c478bdstevel@tonic-gate
257c478bdstevel@tonic-gate#include <stdio.h>
267c478bdstevel@tonic-gate#include <sys/types.h>
277c478bdstevel@tonic-gate#include <sys/stat.h>
287c478bdstevel@tonic-gate#include <strings.h>
297c478bdstevel@tonic-gate#include <stropts.h>
307c478bdstevel@tonic-gate#include <fcntl.h>
317c478bdstevel@tonic-gate#include <stdlib.h>
327c478bdstevel@tonic-gate#include <unistd.h>
337c478bdstevel@tonic-gate#include <string.h>
347c478bdstevel@tonic-gate#include <ctype.h>
357c478bdstevel@tonic-gate#include <arpa/inet.h>
367c478bdstevel@tonic-gate#include <locale.h>
377c478bdstevel@tonic-gate#include <syslog.h>
387c478bdstevel@tonic-gate#include <pwd.h>
397c478bdstevel@tonic-gate#include <sys/param.h>
407c478bdstevel@tonic-gate#include <sys/sysmacros.h>	/* MIN, MAX */
417c478bdstevel@tonic-gate#include <sys/sockio.h>
427c478bdstevel@tonic-gate#include <net/pfkeyv2.h>
437c478bdstevel@tonic-gate#include <net/pfpolicy.h>
447c478bdstevel@tonic-gate#include <inet/ipsec_impl.h>
457c478bdstevel@tonic-gate#include <signal.h>
467c478bdstevel@tonic-gate#include <errno.h>
477c478bdstevel@tonic-gate#include <netdb.h>
487c478bdstevel@tonic-gate#include <sys/socket.h>
497c478bdstevel@tonic-gate#include <sys/systeminfo.h>
507c478bdstevel@tonic-gate#include <nss_dbdefs.h>					/* NSS_BUFLEN_HOSTS */
517c478bdstevel@tonic-gate#include <netinet/in.h>
527c478bdstevel@tonic-gate#include <assert.h>
537c478bdstevel@tonic-gate#include <inet/ip.h>
547c478bdstevel@tonic-gate#include <ipsec_util.h>
557c478bdstevel@tonic-gate#include <netinet/in_systm.h>
567c478bdstevel@tonic-gate#include <netinet/ip_icmp.h>
577c478bdstevel@tonic-gate#include <netinet/icmp6.h>
587c478bdstevel@tonic-gate
597c478bdstevel@tonic-gate/*
60e3320f4markfen * Globals
61e3320f4markfen */
62e3320f4markfenint lfd;
63e3320f4markfenchar *my_fmri;
64e3320f4markfenFILE *debugfile = stderr;
65e3320f4markfen
66e3320f4markfen#define	USAGE() if (!smf_managed) usage()
67e3320f4markfen/*
687c478bdstevel@tonic-gate * Buffer length to read in pattern/properties.
697c478bdstevel@tonic-gate */
707c478bdstevel@tonic-gate#define	MAXLEN			1024
717c478bdstevel@tonic-gate
728810c16danmcd/* Max length of tunnel interface string identifier */
738810c16danmcd#define	TUNNAMEMAXLEN		LIFNAMSIZ
748810c16danmcd
757c478bdstevel@tonic-gate/*
767c478bdstevel@tonic-gate * Used by parse_one and parse/parse_action to communicate
777c478bdstevel@tonic-gate * the errors. -1 is failure, which is not defined here.
787c478bdstevel@tonic-gate */
797c478bdstevel@tonic-gateenum parse_errors {PARSE_SUCCESS, PARSE_EOF};
807c478bdstevel@tonic-gate
817c478bdstevel@tonic-gate/*
827c478bdstevel@tonic-gate * For spdsock_get_ext() diagnostics.
837c478bdstevel@tonic-gate */
847c478bdstevel@tonic-gate#define	SPDSOCK_DIAG_BUF_LEN	128
857c478bdstevel@tonic-gatestatic char spdsock_diag_buf[SPDSOCK_DIAG_BUF_LEN];
867c478bdstevel@tonic-gate
877c478bdstevel@tonic-gate/*
887c478bdstevel@tonic-gate * Define CURL here so that while you are reading
897c478bdstevel@tonic-gate * this code, it does not affect "vi" in pattern
907c478bdstevel@tonic-gate * matching.
917c478bdstevel@tonic-gate */
927c478bdstevel@tonic-gate#define	CURL_BEGIN		'{'
937c478bdstevel@tonic-gate#define	CURL_END		'}'
94d575148markfen#define	BACK_SLASH		'\\'
957c478bdstevel@tonic-gate#define	MAXARGS			20
9643c889dmarkfen#define	NOERROR			0
977c478bdstevel@tonic-gate
987c478bdstevel@tonic-gate/*
997c478bdstevel@tonic-gate * IPSEC_CONF_ADD should start with 1, so that when multiple commands
1007c478bdstevel@tonic-gate * are given, we can fail the request.
1017c478bdstevel@tonic-gate */
1027c478bdstevel@tonic-gate
103eeda67cjojemannenum ipsec_cmds {IPSEC_CONF_ADD = 1, IPSEC_CONF_DEL, IPSEC_CONF_VIEW,
1045033e0cMark Fenwick    IPSEC_CONF_FLUSH, IPSEC_CONF_LIST, IPSEC_CONF_SUB, IPSEC_CONF_REPLACE};
1057c478bdstevel@tonic-gate
1067c478bdstevel@tonic-gatestatic const char policy_conf_file[] = "/var/run/ipsecpolicy.conf";
1077c478bdstevel@tonic-gatestatic const char lock_file[] = "/var/run/ipsecconf.lock";
1087c478bdstevel@tonic-gatestatic const char index_tag[] = "#INDEX";
1097c478bdstevel@tonic-gate
1107c478bdstevel@tonic-gate#define	POLICY_CONF_FILE	policy_conf_file
1117c478bdstevel@tonic-gate#define	LOCK_FILE		lock_file
1127c478bdstevel@tonic-gate#define	INDEX_TAG		index_tag
1137c478bdstevel@tonic-gate
1147c478bdstevel@tonic-gate/*
1157c478bdstevel@tonic-gate * Valid algorithm length.
1167c478bdstevel@tonic-gate */
1177c478bdstevel@tonic-gate#define	VALID_ALG_LEN		40
1187c478bdstevel@tonic-gate
1197c478bdstevel@tonic-gate/* Types of Error messages */
120eeda67cjojemanntypedef enum error_type {BAD_ERROR, DUP_ERROR, REQ_ERROR} error_type_t;
1217c478bdstevel@tonic-gate
1228810c16danmcd/* Error message human readable conversions */
1238810c16danmcdstatic char *sys_error_message(int);
1248810c16danmcdstatic void error_message(error_type_t, int, int);
125e3320f4markfenstatic int get_pf_pol_socket(void);
1268810c16danmcd
1277c478bdstevel@tonic-gatestatic int cmd;
1287c478bdstevel@tonic-gatestatic char *filename;
1297c478bdstevel@tonic-gatestatic char lo_buf[MAXLEN];			/* Leftover buffer */
1307c478bdstevel@tonic-gate
1318810c16danmcd/*
1328810c16danmcd * The new SPD_EXT_TUN_NAME extension has a tunnel name in it.  Use the empty
1338810c16danmcd * string ("", stored in the char value "all_polheads") for all policy heads
1348810c16danmcd * (global and all tunnels).  Set interface_name to NULL for global-only, or
1358810c16danmcd * specify a name of an IP-in-IP tunnel.
1368810c16danmcd */
1378810c16danmcdstatic char *interface_name;
1388810c16danmcdstatic char all_polheads;	/* So we can easily get "". */
1398810c16danmcd
1407c478bdstevel@tonic-gate/* Error reporting stuff */
141130b5e3Dan McDonald#define	CBUF_LEN		8192		/* Maximum size of the cmd */
1427c478bdstevel@tonic-gate/*
1437c478bdstevel@tonic-gate * Following are used for reporting errors with arguments.
1447c478bdstevel@tonic-gate * We store the line numbers of each argument as we parse them,
1457c478bdstevel@tonic-gate * so that the error reporting is more specific. We can have only
146d575148markfen * (MAXARGS - 1) arguments between any pair of CURL_BEGIN CURL_END.
147d575148markfen * Because a single command can be made up of multiple action/property
148d575148markfen * combinations, the maximum command size is (2 * (MAXARGS -1)) for each
149d575148markfen * of patterns, properties and actions.
1507c478bdstevel@tonic-gate */
151d575148markfen#define	ARG_BUF_LEN		((2 * 3 * (MAXARGS - 1)) + 1)
1527c478bdstevel@tonic-gatestatic int arg_indices[ARG_BUF_LEN];
1537c478bdstevel@tonic-gatestatic int argindex;
1547c478bdstevel@tonic-gatestatic int linecount;
1557c478bdstevel@tonic-gatestatic char cbuf[CBUF_LEN];				/* Command buffer */
1567c478bdstevel@tonic-gatestatic int cbuf_offset;
1577c478bdstevel@tonic-gate
1587c478bdstevel@tonic-gate
1597c478bdstevel@tonic-gate#define	BYPASS_POLICY_BOOST		0x00800000
1607c478bdstevel@tonic-gate#define	ESP_POLICY_BOOST		0x00400000
1617c478bdstevel@tonic-gate#define	AH_POLICY_BOOST			0x00200000
1627c478bdstevel@tonic-gate#define	INITIAL_BASE_PRIORITY		0x000fffff
1637c478bdstevel@tonic-gate
1647c478bdstevel@tonic-gate/*
1657c478bdstevel@tonic-gate * the number used to order the
1667c478bdstevel@tonic-gate * rules starts at a certain base and
1677c478bdstevel@tonic-gate * goes down.  i.e. rules earlier in
1687c478bdstevel@tonic-gate * the file are checked first
1697c478bdstevel@tonic-gate */
1707c478bdstevel@tonic-gatestatic uint32_t priority = INITIAL_BASE_PRIORITY;
1717c478bdstevel@tonic-gate
1727c478bdstevel@tonic-gate#define	AH_AUTH		0
1737c478bdstevel@tonic-gate#define	ESP_ENCR	1
1747c478bdstevel@tonic-gate#define	ESP_AUTH	2
1757c478bdstevel@tonic-gate
1767c478bdstevel@tonic-gate
1777c478bdstevel@tonic-gate/*
1787c478bdstevel@tonic-gate * for deleting adds on error
1797c478bdstevel@tonic-gate */
1807c478bdstevel@tonic-gate
1817c478bdstevel@tonic-gatetypedef struct d_list_s
1827c478bdstevel@tonic-gate{
1837c478bdstevel@tonic-gate	struct d_list_s *next;
1847c478bdstevel@tonic-gate	int index;
1857c478bdstevel@tonic-gate} d_list_t;
1867c478bdstevel@tonic-gate
1877c478bdstevel@tonic-gatestatic d_list_t *d_list = NULL;
1887c478bdstevel@tonic-gatestatic d_list_t *d_tail = NULL;
1897c478bdstevel@tonic-gate
1907c478bdstevel@tonic-gate
1917c478bdstevel@tonic-gate/*
1927c478bdstevel@tonic-gate * Used for multi-homed source/dest hosts.
1937c478bdstevel@tonic-gate */
1947c478bdstevel@tonic-gatestatic struct hostent *shp, *dhp;
1957c478bdstevel@tonic-gatestatic unsigned int splen, dplen;
1968810c16danmcdstatic char tunif[TUNNAMEMAXLEN];
1977c478bdstevel@tonic-gatestatic boolean_t has_saprefix, has_daprefix;
1987c478bdstevel@tonic-gatestatic uint32_t seq_cnt = 0;
1997c478bdstevel@tonic-gate
2007c478bdstevel@tonic-gate/* lexxed out action and related properties */
2017c478bdstevel@tonic-gatetypedef struct ap_s
2027c478bdstevel@tonic-gate{
2037c478bdstevel@tonic-gate	char *act;
2047c478bdstevel@tonic-gate	char *prop[MAXARGS + 1];
2057c478bdstevel@tonic-gate} ap_t;
2067c478bdstevel@tonic-gate
2077c478bdstevel@tonic-gate
2087c478bdstevel@tonic-gate/* one lexxed out rule */
2097c478bdstevel@tonic-gatetypedef struct act_prop_s {
210d575148markfen	char *pattern[MAXARGS + 1];
2117c478bdstevel@tonic-gate	ap_t ap[MAXARGS + 1];
2127c478bdstevel@tonic-gate} act_prop_t;
2137c478bdstevel@tonic-gate
2147c478bdstevel@tonic-gatetypedef struct
2157c478bdstevel@tonic-gate{
2167c478bdstevel@tonic-gate	uint8_t	 alg_id;
2177c478bdstevel@tonic-gate	uint32_t alg_minbits;
2187c478bdstevel@tonic-gate	uint32_t alg_maxbits;
2197c478bdstevel@tonic-gate} algreq_t;
2207c478bdstevel@tonic-gate
2217c478bdstevel@tonic-gate/* structure to hold all information for one act_prop_t */
2227c478bdstevel@tonic-gatetypedef struct ips_act_props_s {
2237c478bdstevel@tonic-gate	struct ips_act_props_s	*iap_next;
2247c478bdstevel@tonic-gate	struct ips_conf_s		*iap_head;
2257c478bdstevel@tonic-gate
2267c478bdstevel@tonic-gate/*
2277c478bdstevel@tonic-gate * IPsec action types (in SPD_ATTR_TYPE attribute)
2287c478bdstevel@tonic-gate * SPD_ACTTYPE_DROP	0x0001
2297c478bdstevel@tonic-gate * SPD_ACTTYPE_PASS	0x0002
2307c478bdstevel@tonic-gate * SPD_ACTTYPE_IPSEC	0x0003
2317c478bdstevel@tonic-gate */
2327c478bdstevel@tonic-gate	uint16_t	iap_action;
2337c478bdstevel@tonic-gate	uint16_t	iap_act_tok;
2347c478bdstevel@tonic-gate
2357c478bdstevel@tonic-gate/*
2367c478bdstevel@tonic-gate * Action ATTR flags (in SPD_ATTR_FLAGS attribute)
2377c478bdstevel@tonic-gate *	SPD_APPLY_AH		0x0001
2387c478bdstevel@tonic-gate *	SPD_APPLY_ESP		0x0002
2397c478bdstevel@tonic-gate *	SPD_APPLY_SE		0x0004  * self-encapsulation *
2407c478bdstevel@tonic-gate *	SPD_APPLY_COMP		0x0008	* compression; NYI *
2417c478bdstevel@tonic-gate *	SPD_APPLY_UNIQUE	0x0010	* unique per-flow SA *
2427c478bdstevel@tonic-gate *	SPD_APPLY_BYPASS	0x0020	* bypass policy *
2437c478bdstevel@tonic-gate */
2447c478bdstevel@tonic-gate	uint16_t	iap_attr;
2457c478bdstevel@tonic-gate	uint16_t	iap_attr_tok[5];
2467c478bdstevel@tonic-gate
2477c478bdstevel@tonic-gate	algreq_t	iap_aauth;
2487c478bdstevel@tonic-gate	algreq_t	iap_eencr;
2497c478bdstevel@tonic-gate	algreq_t	iap_eauth;
2507c478bdstevel@tonic-gate
2517c478bdstevel@tonic-gate	uint32_t iap_life_soft_time;
2527c478bdstevel@tonic-gate	uint32_t iap_life_hard_time;
2537c478bdstevel@tonic-gate	uint32_t iap_life_soft_bytes;
2547c478bdstevel@tonic-gate	uint32_t iap_life_hard_bytes;
2557c478bdstevel@tonic-gate
2567c478bdstevel@tonic-gate} ips_act_props_t;
2577c478bdstevel@tonic-gate
2587c478bdstevel@tonic-gate#define	V4_PART_OF_V6(v6)	v6._S6_un._S6_u32[3]
2597c478bdstevel@tonic-gate
2607c478bdstevel@tonic-gatetypedef struct ips_conf_s {
2617c478bdstevel@tonic-gate	/* selector */
2627c478bdstevel@tonic-gate	uint16_t patt_tok[8];
2637c478bdstevel@tonic-gate	uint8_t has_saddr;
2647c478bdstevel@tonic-gate	uint8_t has_daddr;
2657c478bdstevel@tonic-gate	uint8_t has_smask;
2667c478bdstevel@tonic-gate	uint8_t has_dmask;
2677c478bdstevel@tonic-gate	uint8_t has_type;
2687c478bdstevel@tonic-gate	uint8_t has_code;
2698810c16danmcd	uint8_t has_negotiate;
2708810c16danmcd	uint8_t has_tunnel;
2717c478bdstevel@tonic-gate	uint16_t swap;
2727c478bdstevel@tonic-gate
2737c478bdstevel@tonic-gate	struct in6_addr	ips_src_addr_v6;
2747c478bdstevel@tonic-gate	struct in6_addr	ips_src_mask_v6;
2757c478bdstevel@tonic-gate	struct in6_addr	ips_dst_addr_v6;
2767c478bdstevel@tonic-gate	struct in6_addr	ips_dst_mask_v6;
2777c478bdstevel@tonic-gate	uint8_t 		ips_src_mask_len;
2787c478bdstevel@tonic-gate	uint8_t 		ips_dst_mask_len;
2797c478bdstevel@tonic-gate	in_port_t		ips_src_port_min;
2807c478bdstevel@tonic-gate	in_port_t		ips_src_port_max;
2817c478bdstevel@tonic-gate	in_port_t		ips_dst_port_min;
2827c478bdstevel@tonic-gate	in_port_t		ips_dst_port_max;
2837c478bdstevel@tonic-gate	uint8_t			ips_icmp_type;
2847c478bdstevel@tonic-gate	uint8_t			ips_icmp_type_end;
2857c478bdstevel@tonic-gate	uint8_t			ips_icmp_code;
2867c478bdstevel@tonic-gate	uint8_t			ips_icmp_code_end;
2877c478bdstevel@tonic-gate	uint8_t			ips_ulp_prot;
2887c478bdstevel@tonic-gate	uint8_t			ips_ipsec_prot;
2897c478bdstevel@tonic-gate	uint8_t			ips_isv4;
2907c478bdstevel@tonic-gate	/*
2917c478bdstevel@tonic-gate	 * SPD_RULE_FLAG_INBOUND		0x0001
2927c478bdstevel@tonic-gate	 * SPD_RULE_FLAG_OUTBOUND		0x0002
2937c478bdstevel@tonic-gate	 */
2947c478bdstevel@tonic-gate	uint8_t			ips_dir;
2958810c16danmcd	/*
2968810c16danmcd	 * Keep track of tunnel separately due to explosion of ways to set
2978810c16danmcd	 * inbound/outbound.
2988810c16danmcd	 */
2998810c16danmcd	boolean_t		ips_tunnel;
3007c478bdstevel@tonic-gate	uint64_t		ips_policy_index;
3017c478bdstevel@tonic-gate	uint32_t		ips_act_cnt;
3027c478bdstevel@tonic-gate	ips_act_props_t	*ips_acts;
3037c478bdstevel@tonic-gate} ips_conf_t;
3047c478bdstevel@tonic-gate
3057c478bdstevel@tonic-gate#define	ips_src_addr	V4_PART_OF_V6(ips_src_addr_v6)
3067c478bdstevel@tonic-gate#define	ips_dst_addr	V4_PART_OF_V6(ips_dst_addr_v6)
3077c478bdstevel@tonic-gate
3087c478bdstevel@tonic-gatestatic int ipsecconf_nflag;		/* Used only with -l option */
3097c478bdstevel@tonic-gatestatic int ipsecconf_qflag;		/* Used only with -a|-r option */
3107c478bdstevel@tonic-gate
3117c478bdstevel@tonic-gatetypedef struct str_val {
3127c478bdstevel@tonic-gate	const char *string;
3137c478bdstevel@tonic-gate	int value;
3147c478bdstevel@tonic-gate} str_val_t;
3157c478bdstevel@tonic-gate
3167c478bdstevel@tonic-gatetypedef struct str_tval {
3177c478bdstevel@tonic-gate	const char *string;
3187c478bdstevel@tonic-gate	int tok_val;
3197c478bdstevel@tonic-gate	int value;
3207c478bdstevel@tonic-gate} str_tval_t;
3217c478bdstevel@tonic-gate
3227c478bdstevel@tonic-gatestatic int	parse_int(const char *);
3238810c16danmcdstatic int	parse_index(const char *, char *);
3248810c16danmcdstatic int	attach_tunname(spd_if_t *);
3257c478bdstevel@tonic-gatestatic void	usage(void);
3267c478bdstevel@tonic-gatestatic int	ipsec_conf_del(int, boolean_t);
3275033e0cMark Fenwickstatic int	ipsec_conf_add(boolean_t, boolean_t, boolean_t);
3287c478bdstevel@tonic-gatestatic int	ipsec_conf_sub(void);
3297c478bdstevel@tonic-gatestatic int	ipsec_conf_flush(int);
3307c478bdstevel@tonic-gatestatic int	ipsec_conf_view(void);
3317c478bdstevel@tonic-gatestatic int	ipsec_conf_list(void);
3327c478bdstevel@tonic-gatestatic int	lock(void);
3337c478bdstevel@tonic-gatestatic int	unlock(int);
3347c478bdstevel@tonic-gatestatic int	parse_one(FILE *, act_prop_t *);
3357c478bdstevel@tonic-gatestatic void	reconfigure();
3367c478bdstevel@tonic-gatestatic void	in_prefixlentomask(unsigned int, uchar_t *);
3378810c16danmcdstatic int	in_getprefixlen(char *);
3387c478bdstevel@tonic-gatestatic int	parse_address(int, char *);
3397c478bdstevel@tonic-gate#ifdef DEBUG_HEAVY
3407c478bdstevel@tonic-gatestatic void	pfpol_msg_dump(spd_msg_t *msg, char *);
3417c478bdstevel@tonic-gate#endif /* DEBUG_HEAVY */
3427c478bdstevel@tonic-gatestatic void	print_pfpol_msg(spd_msg_t *);
3437c478bdstevel@tonic-gatestatic int	pfp_delete_rule(uint64_t);
3447c478bdstevel@tonic-gatestatic void	ipsec_conf_admin(uint8_t);
3457c478bdstevel@tonic-gatestatic void	print_bit_range(int, int);
3467c478bdstevel@tonic-gatestatic void	nuke_adds();
347130b5e3Dan McDonaldstatic boolean_t combined_mode(uint_t);
3487c478bdstevel@tonic-gate
3497c478bdstevel@tonic-gate#ifdef DEBUG
3507c478bdstevel@tonic-gatestatic void	dump_conf(ips_conf_t *);
3517c478bdstevel@tonic-gate#endif
3527c478bdstevel@tonic-gate
3537c478bdstevel@tonic-gatetypedef struct
3547c478bdstevel@tonic-gate{
3557c478bdstevel@tonic-gate	uint32_t	id;
3567c478bdstevel@tonic-gate	uint32_t	minkeybits;
3577c478bdstevel@tonic-gate	uint32_t	maxkeybits;
3587c478bdstevel@tonic-gate	uint32_t	defkeybits;
3597c478bdstevel@tonic-gate	uint32_t	incr;
3607c478bdstevel@tonic-gate} alginfo_t;
3617c478bdstevel@tonic-gate
3627c478bdstevel@tonic-gatestatic int ipsec_nalgs[3];
3637c478bdstevel@tonic-gatestatic alginfo_t known_algs[3][256];
3647c478bdstevel@tonic-gate
3657c478bdstevel@tonic-gate#define	IPS_SRC_MASK SPD_EXT_LCLADDR + 100
3667c478bdstevel@tonic-gate#define	IPS_DST_MASK SPD_EXT_REMADDR + 100
3677c478bdstevel@tonic-gate
3687c478bdstevel@tonic-gate/*
3697c478bdstevel@tonic-gate * if inbound, src=remote, dst=local
3707c478bdstevel@tonic-gate * if outbound, src=local, dst=remote
3717c478bdstevel@tonic-gate */
3727c478bdstevel@tonic-gate
3737c478bdstevel@tonic-gate#define	TOK_saddr	1
3747c478bdstevel@tonic-gate#define	TOK_daddr	2
3757c478bdstevel@tonic-gate#define	TOK_sport	3
3767c478bdstevel@tonic-gate#define	TOK_dport	4
3777c478bdstevel@tonic-gate#define	TOK_smask	5
3787c478bdstevel@tonic-gate#define	TOK_dmask	6
3797c478bdstevel@tonic-gate#define	TOK_ulp	7
3807c478bdstevel@tonic-gate#define	TOK_local	8
3817c478bdstevel@tonic-gate#define	TOK_lport	9
3827c478bdstevel@tonic-gate#define	TOK_remote	10
3837c478bdstevel@tonic-gate#define	TOK_rport	11
3847c478bdstevel@tonic-gate#define	TOK_dir 	12
3857c478bdstevel@tonic-gate#define	TOK_type	13
3867c478bdstevel@tonic-gate#define	TOK_code	14
3878810c16danmcd#define	TOK_negotiate	15
3888810c16danmcd#define	TOK_tunnel	16
3897c478bdstevel@tonic-gate
3907c478bdstevel@tonic-gate#define	IPS_SA SPD_ATTR_END
3917c478bdstevel@tonic-gate#define	IPS_DIR SPD_ATTR_EMPTY
3928810c16danmcd#define	IPS_NEG SPD_ATTR_NOP
3937c478bdstevel@tonic-gate
3947c478bdstevel@tonic-gate
3957c478bdstevel@tonic-gatestatic str_tval_t pattern_table[] = {
3967c478bdstevel@tonic-gate	{"saddr", 		TOK_saddr,		SPD_EXT_LCLADDR},
3977c478bdstevel@tonic-gate	{"src",			TOK_saddr,		SPD_EXT_LCLADDR},
3987c478bdstevel@tonic-gate	{"srcaddr",		TOK_saddr,		SPD_EXT_LCLADDR},
3997c478bdstevel@tonic-gate	{"daddr", 		TOK_daddr,		SPD_EXT_REMADDR},
4007c478bdstevel@tonic-gate	{"dst",			TOK_daddr,		SPD_EXT_REMADDR},
4017c478bdstevel@tonic-gate	{"dstaddr",		TOK_daddr,		SPD_EXT_REMADDR},
4027c478bdstevel@tonic-gate	{"sport", 		TOK_sport,		SPD_EXT_LCLPORT},
4037c478bdstevel@tonic-gate	{"dport", 		TOK_dport,		SPD_EXT_REMPORT},
4047c478bdstevel@tonic-gate	{"smask", 		TOK_smask,		IPS_SRC_MASK},
4057c478bdstevel@tonic-gate	{"dmask", 		TOK_dmask,		IPS_DST_MASK},
4067c478bdstevel@tonic-gate	{"ulp", 		TOK_ulp,		SPD_EXT_PROTO},
4077c478bdstevel@tonic-gate	{"proto", 		TOK_ulp,		SPD_EXT_PROTO},
4087c478bdstevel@tonic-gate	{"local",		TOK_local,		SPD_EXT_LCLADDR},
4097c478bdstevel@tonic-gate	{"laddr",		TOK_local,		SPD_EXT_LCLADDR},
4107c478bdstevel@tonic-gate	{"lport",		TOK_lport,		SPD_EXT_LCLPORT},
4117c478bdstevel@tonic-gate	{"remote",		TOK_remote,		SPD_EXT_REMADDR},
4127c478bdstevel@tonic-gate	{"raddr",		TOK_remote,		SPD_EXT_REMADDR},
4137c478bdstevel@tonic-gate	{"rport",		TOK_rport,		SPD_EXT_REMPORT},
4147c478bdstevel@tonic-gate	{"dir",			TOK_dir,		IPS_DIR},
4157c478bdstevel@tonic-gate	{"type",		TOK_type,		SPD_EXT_ICMP_TYPECODE},
4167c478bdstevel@tonic-gate	{"code",		TOK_code,		SPD_EXT_ICMP_TYPECODE},
4178810c16danmcd	{"negotiate",		TOK_negotiate,		IPS_NEG},
4188810c16danmcd	{"tunnel",		TOK_tunnel,		SPD_EXT_TUN_NAME},
4197c478bdstevel@tonic-gate	{NULL, 			0,				0},
4207c478bdstevel@tonic-gate};
4217c478bdstevel@tonic-gate
4227c478bdstevel@tonic-gate#define	TOK_apply	1
4237c478bdstevel@tonic-gate#define	TOK_permit	2
4247c478bdstevel@tonic-gate#define	TOK_ipsec	3
4257c478bdstevel@tonic-gate#define	TOK_bypass	4
4267c478bdstevel@tonic-gate#define	TOK_drop	5
4277c478bdstevel@tonic-gate#define	TOK_or		6
4287c478bdstevel@tonic-gate
4297c478bdstevel@tonic-gatestatic str_tval_t action_table[] = {
4307c478bdstevel@tonic-gate	{"apply", 		TOK_apply,		SPD_ACTTYPE_IPSEC},
4317c478bdstevel@tonic-gate	{"permit", 		TOK_permit,		SPD_ACTTYPE_IPSEC},
4327c478bdstevel@tonic-gate	{"ipsec", 		TOK_ipsec,		SPD_ACTTYPE_IPSEC},
4337c478bdstevel@tonic-gate	{"bypass", 		TOK_bypass,		SPD_ACTTYPE_PASS},
4347c478bdstevel@tonic-gate	{"pass", 		TOK_bypass,		SPD_ACTTYPE_PASS},
4357c478bdstevel@tonic-gate	{"drop", 		TOK_drop,		SPD_ACTTYPE_DROP},
4367c478bdstevel@tonic-gate	{"or",			TOK_or,			0},
4377c478bdstevel@tonic-gate	{NULL, 			0,				0},
4387c478bdstevel@tonic-gate};
4397c478bdstevel@tonic-gate
4407c478bdstevel@tonic-gatestatic str_val_t property_table[] = {
4417c478bdstevel@tonic-gate	{"auth_algs", 		SPD_ATTR_AH_AUTH},
4427c478bdstevel@tonic-gate	{"encr_algs", 		SPD_ATTR_ESP_ENCR},
4437c478bdstevel@tonic-gate	{"encr_auth_algs",	SPD_ATTR_ESP_AUTH},
4447c478bdstevel@tonic-gate	{"sa",				IPS_SA},
4457c478bdstevel@tonic-gate	{"dir",				IPS_DIR},
4467c478bdstevel@tonic-gate	{NULL,				0},
4477c478bdstevel@tonic-gate};
4487c478bdstevel@tonic-gate
4497c478bdstevel@tonic-gatestatic str_val_t icmp_type_table[] = {
4507c478bdstevel@tonic-gate	{"unreach",	ICMP_UNREACH},
4517c478bdstevel@tonic-gate	{"echo",	ICMP_ECHO},
4527c478bdstevel@tonic-gate	{"echorep",	ICMP_ECHOREPLY},
4537c478bdstevel@tonic-gate	{"squench",	ICMP_SOURCEQUENCH},
4547c478bdstevel@tonic-gate	{"redir",	ICMP_REDIRECT},
4557c478bdstevel@tonic-gate	{"timex",	ICMP_TIMXCEED},
4567c478bdstevel@tonic-gate	{"paramprob",	ICMP_PARAMPROB},
4577c478bdstevel@tonic-gate	{"timest",	ICMP_TSTAMP},
4587c478bdstevel@tonic-gate	{"timestrep",	ICMP_TSTAMPREPLY},
4597c478bdstevel@tonic-gate	{"inforeq",	ICMP_IREQ},
4607c478bdstevel@tonic-gate	{"inforep",	ICMP_IREQREPLY},
4617c478bdstevel@tonic-gate	{"maskreq",	ICMP_MASKREQ},
4627c478bdstevel@tonic-gate	{"maskrep",	ICMP_MASKREPLY},
4637c478bdstevel@tonic-gate	{"unreach6",	ICMP6_DST_UNREACH},
4647c478bdstevel@tonic-gate	{"pkttoobig6",	ICMP6_PACKET_TOO_BIG},
4657c478bdstevel@tonic-gate	{"timex6",	ICMP6_TIME_EXCEEDED},
4667c478bdstevel@tonic-gate	{"paramprob6",	ICMP6_PARAM_PROB},
4677c478bdstevel@tonic-gate	{"echo6", 	ICMP6_ECHO_REQUEST},
4687c478bdstevel@tonic-gate	{"echorep6",	ICMP6_ECHO_REPLY},
4697c478bdstevel@tonic-gate	{"router-sol6",	ND_ROUTER_SOLICIT},
4707c478bdstevel@tonic-gate	{"router-ad6",	ND_ROUTER_ADVERT},
4717c478bdstevel@tonic-gate	{"neigh-sol6",	ND_NEIGHBOR_SOLICIT},
4727c478bdstevel@tonic-gate	{"neigh-ad6",	ND_NEIGHBOR_ADVERT},
4737c478bdstevel@tonic-gate	{"redir6",	ND_REDIRECT},
4747c478bdstevel@tonic-gate	{NULL,		0},
4757c478bdstevel@tonic-gate};
4767c478bdstevel@tonic-gate
4777c478bdstevel@tonic-gatestatic str_val_t icmp_code_table[] = {
4787c478bdstevel@tonic-gate	{"net-unr",		ICMP_UNREACH_NET},
4797c478bdstevel@tonic-gate	{"host-unr",		ICMP_UNREACH_HOST},
4807c478bdstevel@tonic-gate	{"proto-unr",		ICMP_UNREACH_PROTOCOL},
4817c478bdstevel@tonic-gate	{"port-unr",		ICMP_UNREACH_PORT},
4827c478bdstevel@tonic-gate	{"needfrag",		ICMP_UNREACH_NEEDFRAG},
4837c478bdstevel@tonic-gate	{"srcfail",		ICMP_UNREACH_SRCFAIL},
4847c478bdstevel@tonic-gate	{"net-unk",		ICMP_UNREACH_NET_UNKNOWN},
4857c478bdstevel@tonic-gate	{"host-unk",		ICMP_UNREACH_HOST_UNKNOWN},
4867c478bdstevel@tonic-gate	{"isolate",		ICMP_UNREACH_ISOLATED},
4877c478bdstevel@tonic-gate	{"net-prohib",		ICMP_UNREACH_NET_PROHIB},
4887c478bdstevel@tonic-gate	{"host-prohib",		ICMP_UNREACH_HOST_PROHIB},
4897c478bdstevel@tonic-gate	{"net-tos",		ICMP_UNREACH_TOSNET},
4907c478bdstevel@tonic-gate	{"host-tos",		ICMP_UNREACH_TOSHOST},
4917c478bdstevel@tonic-gate	{"filter-prohib",	ICMP_UNREACH_FILTER_PROHIB},
4927c478bdstevel@tonic-gate	{"host-preced",		ICMP_UNREACH_HOST_PRECEDENCE},
4937c478bdstevel@tonic-gate	{"cutoff-preced",	ICMP_UNREACH_PRECEDENCE_CUTOFF},
4947c478bdstevel@tonic-gate	{"no-route6",		ICMP6_DST_UNREACH_NOROUTE},
4957c478bdstevel@tonic-gate	{"adm-prohib6",		ICMP6_DST_UNREACH_ADMIN},
4967c478bdstevel@tonic-gate	{"addr-unr6",		ICMP6_DST_UNREACH_ADDR},
4977c478bdstevel@tonic-gate	{"port-unr6",		ICMP6_DST_UNREACH_NOPORT},
4987c478bdstevel@tonic-gate	{"hop-limex6",		ICMP6_TIME_EXCEED_TRANSIT},
4997c478bdstevel@tonic-gate	{"frag-re-timex6",	ICMP6_TIME_EXCEED_REASSEMBLY},
5007c478bdstevel@tonic-gate	{"err-head6",		ICMP6_PARAMPROB_HEADER},
5017c478bdstevel@tonic-gate	{"unrec-head6",		ICMP6_PARAMPROB_NEXTHEADER},
5027c478bdstevel@tonic-gate	{"unreq-opt6",		ICMP6_PARAMPROB_OPTION},
5037c478bdstevel@tonic-gate	{NULL,			0},
5047c478bdstevel@tonic-gate};
5057c478bdstevel@tonic-gate
5067c478bdstevel@tonic-gatestatic sigset_t set, oset;
5077c478bdstevel@tonic-gate
5087c478bdstevel@tonic-gate
5097c478bdstevel@tonic-gatestatic boolean_t
5107c478bdstevel@tonic-gateadd_index(int index)
5117c478bdstevel@tonic-gate{
5127c478bdstevel@tonic-gate	d_list_t *temp = malloc(sizeof (d_list_t));
5137c478bdstevel@tonic-gate
5147c478bdstevel@tonic-gate	if (temp == NULL) {
5157c478bdstevel@tonic-gate		warn("malloc");
5167c478bdstevel@tonic-gate		return (B_TRUE);
5177c478bdstevel@tonic-gate	}
5187c478bdstevel@tonic-gate
5197c478bdstevel@tonic-gate	temp->index = index;
5207c478bdstevel@tonic-gate	temp->next = NULL;
5217c478bdstevel@tonic-gate
5227c478bdstevel@tonic-gate	if (d_tail == NULL) {
5237c478bdstevel@tonic-gate		d_list = d_tail = temp;
5247c478bdstevel@tonic-gate		return (B_FALSE);
5257c478bdstevel@tonic-gate	}
5267c478bdstevel@tonic-gate
5277c478bdstevel@tonic-gate	d_tail->next = temp;
5287c478bdstevel@tonic-gate	d_tail = temp;
5297c478bdstevel@tonic-gate
5307c478bdstevel@tonic-gate	return (B_FALSE);
5317c478bdstevel@tonic-gate}
5327c478bdstevel@tonic-gate
5337c478bdstevel@tonic-gatestatic int
5347c478bdstevel@tonic-gateblock_all_signals()
5357c478bdstevel@tonic-gate{
5367c478bdstevel@tonic-gate	if (sigfillset(&set) == -1) {
5377c478bdstevel@tonic-gate		warn("sigfillset");
5387c478bdstevel@tonic-gate		return (-1);
5397c478bdstevel@tonic-gate	}
5407c478bdstevel@tonic-gate	if (sigprocmask(SIG_SETMASK, &set, &oset) == -1) {
5417c478bdstevel@tonic-gate		warn("sigprocmask");
5427c478bdstevel@tonic-gate		return (-1);
5437c478bdstevel@tonic-gate	}
5447c478bdstevel@tonic-gate	return (0);
5457c478bdstevel@tonic-gate}
5467c478bdstevel@tonic-gate
5477c478bdstevel@tonic-gatestatic int
5487c478bdstevel@tonic-gaterestore_all_signals()
5497c478bdstevel@tonic-gate{
5507c478bdstevel@tonic-gate	if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) {
5517c478bdstevel@tonic-gate		warn("sigprocmask");
5527c478bdstevel@tonic-gate		return (-1);
5537c478bdstevel@tonic-gate	}
5547c478bdstevel@tonic-gate	return (0);
5557c478bdstevel@tonic-gate}
5567c478bdstevel@tonic-gate
5577c478bdstevel@tonic-gate/* allocate an ips_act_props_t and link it in correctly */
5587c478bdstevel@tonic-gatestatic ips_act_props_t *
5597c478bdstevel@tonic-gatealloc_iap(ips_conf_t *parent)
5607c478bdstevel@tonic-gate{
5617c478bdstevel@tonic-gate	ips_act_props_t *ret;
5627c478bdstevel@tonic-gate	ips_act_props_t *next = parent->ips_acts;
5637c478bdstevel@tonic-gate	ips_act_props_t *current = NULL;
5647c478bdstevel@tonic-gate
5657c478bdstevel@tonic-gate	ret = (ips_act_props_t *)calloc(sizeof (ips_act_props_t), 1);
5667c478bdstevel@tonic-gate
5677c478bdstevel@tonic-gate	if (ret == NULL)
5687c478bdstevel@tonic-gate		return (NULL);
5697c478bdstevel@tonic-gate
5707c478bdstevel@tonic-gate	ret->iap_head = parent;
5717c478bdstevel@tonic-gate
5727c478bdstevel@tonic-gate	while (next != NULL) {
5737c478bdstevel@tonic-gate		current = next;
5747c478bdstevel@tonic-gate		next = next->iap_next;
5757c478bdstevel@tonic-gate	}
5767c478bdstevel@tonic-gate
5777c478bdstevel@tonic-gate	if (current != NULL)
5787c478bdstevel@tonic-gate		current->iap_next = ret;
5797c478bdstevel@tonic-gate	else
5807c478bdstevel@tonic-gate		parent->ips_acts = ret;
5817c478bdstevel@tonic-gate
5827c478bdstevel@tonic-gate	parent->ips_act_cnt++;
5837c478bdstevel@tonic-gate
5847c478bdstevel@tonic-gate	return (ret);
5857c478bdstevel@tonic-gate}
5867c478bdstevel@tonic-gate
5877c478bdstevel@tonic-gate/*
5887c478bdstevel@tonic-gate * This function exit()s if it fails.
5897c478bdstevel@tonic-gate */
5907c478bdstevel@tonic-gatestatic void
5917c478bdstevel@tonic-gatefetch_algorithms()
5927c478bdstevel@tonic-gate{
5937c478bdstevel@tonic-gate	struct spd_msg msg;
5947c478bdstevel@tonic-gate	struct spd_ext_actions *actp;
5957c478bdstevel@tonic-gate	struct spd_attribute *attr, *endattr;
5967c478bdstevel@tonic-gate	spd_ext_t *exts[SPD_EXT_MAX+1];
5977c478bdstevel@tonic-gate	uint64_t reply_buf[256];
598e3320f4markfen	int sfd;
5997c478bdstevel@tonic-gate	int cnt, retval;
6007c478bdstevel@tonic-gate	uint64_t *start, *end;
6017c478bdstevel@tonic-gate	alginfo_t alg = {0, 0, 0, 0, 0};
6027c478bdstevel@tonic-gate	uint_t algtype;
6037c478bdstevel@tonic-gate	static boolean_t has_run = B_FALSE;
6047c478bdstevel@tonic-gate
6057c478bdstevel@tonic-gate	if (has_run)
6067c478bdstevel@tonic-gate		return;
6077c478bdstevel@tonic-gate	else
6087c478bdstevel@tonic-gate		has_run = B_TRUE;
6097c478bdstevel@tonic-gate
610e3320f4markfen	sfd = get_pf_pol_socket();
6117c478bdstevel@tonic-gate	if (sfd < 0) {
6127c478bdstevel@tonic-gate		err(-1, gettext("unable to open policy socket"));
6137c478bdstevel@tonic-gate	}
6147c478bdstevel@tonic-gate
6157c478bdstevel@tonic-gate	(void) memset(&msg, 0, sizeof (msg));
6167c478bdstevel@tonic-gate	msg.spd_msg_version = PF_POLICY_V1;
6177c478bdstevel@tonic-gate	msg.spd_msg_type = SPD_ALGLIST;
6187c478bdstevel@tonic-gate	msg.spd_msg_len = SPD_8TO64(sizeof (msg));
6197c478bdstevel@tonic-gate
6207c478bdstevel@tonic-gate	cnt = write(sfd, &msg, sizeof (msg));
6217c478bdstevel@tonic-gate	if (cnt != sizeof (msg)) {
6227c478bdstevel@tonic-gate		if (cnt < 0) {
6237c478bdstevel@tonic-gate			err(-1, gettext("alglist failed: write"));
6247c478bdstevel@tonic-gate		} else {
6258810c16danmcd			errx(-1, gettext("alglist failed: short write"));
6267c478bdstevel@tonic-gate		}
6277c478bdstevel@tonic-gate	}
6287c478bdstevel@tonic-gate
6297c478bdstevel@tonic-gate	cnt = read(sfd, reply_buf, sizeof (reply_buf));
6307c478bdstevel@tonic-gate
6317c478bdstevel@tonic-gate	retval = spdsock_get_ext(exts, (spd_msg_t *)reply_buf, SPD_8TO64(cnt),
6327c478bdstevel@tonic-gate	    spdsock_diag_buf, SPDSOCK_DIAG_BUF_LEN);
6337c478bdstevel@tonic-gate
6347c478bdstevel@tonic-gate	if (retval == KGE_LEN && exts[0]->spd_ext_len == 0) {
6357c478bdstevel@tonic-gate		/*
6367c478bdstevel@tonic-gate		 * No algorithms are defined in the kernel, which caused
6377c478bdstevel@tonic-gate		 * the extension length to be zero, and spdsock_get_ext()
6387c478bdstevel@tonic-gate		 * to fail with a KGE_LEN error. This is not an error
6397c478bdstevel@tonic-gate		 * condition, so we return nicely.
6407c478bdstevel@tonic-gate		 */
6413abcb96pwernau		(void) close(sfd);
6427c478bdstevel@tonic-gate		return;
6437c478bdstevel@tonic-gate	} else if (retval != 0) {
6447c478bdstevel@tonic-gate		if (strlen(spdsock_diag_buf) != 0)
6457c478bdstevel@tonic-gate			warnx(spdsock_diag_buf);
6467c478bdstevel@tonic-gate		err(1, gettext("fetch_algorithms failed"));
6477c478bdstevel@tonic-gate	}
6487c478bdstevel@tonic-gate
6497c478bdstevel@tonic-gate	if (!exts[SPD_EXT_ACTION]) {
6507c478bdstevel@tonic-gate		errx(1, gettext("fetch_algorithms: action missing?!"));
6517c478bdstevel@tonic-gate	}
6527c478bdstevel@tonic-gate
6537c478bdstevel@tonic-gate	actp = (struct spd_ext_actions *)exts[SPD_EXT_ACTION];
6547c478bdstevel@tonic-gate	start = (uint64_t *)actp;
6557c478bdstevel@tonic-gate	end = (start + actp->spd_actions_len);
6567c478bdstevel@tonic-gate	endattr = (struct spd_attribute *)end;
6577c478bdstevel@tonic-gate	attr = (struct spd_attribute *)&actp[1];
6587c478bdstevel@tonic-gate
6597c478bdstevel@tonic-gate	algtype = 0;
6607c478bdstevel@tonic-gate
6617c478bdstevel@tonic-gate	while (attr < endattr) {
6627c478bdstevel@tonic-gate		switch (attr->spd_attr_tag) {
6637c478bdstevel@tonic-gate		case SPD_ATTR_NOP:
6647c478bdstevel@tonic-gate		case SPD_ATTR_EMPTY:
6657c478bdstevel@tonic-gate			break;
6667c478bdstevel@tonic-gate		case SPD_ATTR_END:
6677c478bdstevel@tonic-gate			attr = endattr;
6687c478bdstevel@tonic-gate			/* FALLTHRU */
6697c478bdstevel@tonic-gate		case SPD_ATTR_NEXT:
6707c478bdstevel@tonic-gate			known_algs[algtype][ipsec_nalgs[algtype]] = alg;
6717c478bdstevel@tonic-gate			ipsec_nalgs[algtype]++;
6727c478bdstevel@tonic-gate			break;
6737c478bdstevel@tonic-gate
6747c478bdstevel@tonic-gate		case SPD_ATTR_ENCR_MINBITS:
6757c478bdstevel@tonic-gate		case SPD_ATTR_AH_MINBITS:
6767c478bdstevel@tonic-gate		case SPD_ATTR_ESPA_MINBITS:
6777c478bdstevel@tonic-gate			alg.minkeybits = attr->spd_attr_value;
6787c478bdstevel@tonic-gate			break;
6797c478bdstevel@tonic-gate
6807c478bdstevel@tonic-gate		case SPD_ATTR_ENCR_MAXBITS:
6817c478bdstevel@tonic-gate		case SPD_ATTR_AH_MAXBITS:
6827c478bdstevel@tonic-gate		case SPD_ATTR_ESPA_MAXBITS:
6837c478bdstevel@tonic-gate			alg.maxkeybits = attr->spd_attr_value;
6847c478bdstevel@tonic-gate			break;
6857c478bdstevel@tonic-gate
6867c478bdstevel@tonic-gate		case SPD_ATTR_ENCR_DEFBITS:
6877c478bdstevel@tonic-gate		case SPD_ATTR_AH_DEFBITS:
6887c478bdstevel@tonic-gate		case SPD_ATTR_ESPA_DEFBITS:
6897c478bdstevel@tonic-gate			alg.defkeybits = attr->spd_attr_value;
6907c478bdstevel@tonic-gate			break;
6917c478bdstevel@tonic-gate
6927c478bdstevel@tonic-gate		case SPD_ATTR_ENCR_INCRBITS:
6937c478bdstevel@tonic-gate		case SPD_ATTR_AH_INCRBITS:
6947c478bdstevel@tonic-gate		case SPD_ATTR_ESPA_INCRBITS:
6957c478bdstevel@tonic-gate			alg.incr = attr->spd_attr_value;
6967c478bdstevel@tonic-gate			break;
6977c478bdstevel@tonic-gate
6987c478bdstevel@tonic-gate		case SPD_ATTR_AH_AUTH:
6997c478bdstevel@tonic-gate		case SPD_ATTR_ESP_AUTH:
7007c478bdstevel@tonic-gate		case SPD_ATTR_ESP_ENCR:
7017c478bdstevel@tonic-gate			alg.id = attr->spd_attr_value;
7027c478bdstevel@tonic-gate			algtype = attr->spd_attr_tag - SPD_ATTR_AH_AUTH;
7037c478bdstevel@tonic-gate			break;
7047c478bdstevel@tonic-gate		}
7057c478bdstevel@tonic-gate		attr++;
7067c478bdstevel@tonic-gate	}
7077c478bdstevel@tonic-gate
7087c478bdstevel@tonic-gate	(void) close(sfd);
7097c478bdstevel@tonic-gate}
7107c478bdstevel@tonic-gate
7117c478bdstevel@tonic-gate/* data dependant transform (act_cnt) */
7127c478bdstevel@tonic-gate#define	ATTR(ap, tag, value) \
7137c478bdstevel@tonic-gatedo { (ap)->spd_attr_tag = (tag); \
7147c478bdstevel@tonic-gate	(ap)->spd_attr_value = (value); \
7157c478bdstevel@tonic-gate	ap++; } while (0)
7167c478bdstevel@tonic-gate
7177c478bdstevel@tonic-gatestatic struct spd_attribute *
7187c478bdstevel@tonic-gateemit_alg(struct spd_attribute *ap, int type, const algreq_t *ar,
7197c478bdstevel@tonic-gate    int algattr, int minbitattr, int maxbitattr)
7207c478bdstevel@tonic-gate{
7217c478bdstevel@tonic-gate	int id = ar->alg_id;
7227c478bdstevel@tonic-gate	int minbits, i;
7237c478bdstevel@tonic-gate
7247c478bdstevel@tonic-gate	if (id != 0) {
7257c478bdstevel@tonic-gate		/* LINTED E_CONST_COND */
7267c478bdstevel@tonic-gate		ATTR(ap, algattr, ar->alg_id);
7277c478bdstevel@tonic-gate
7287c478bdstevel@tonic-gate		minbits = ar->alg_minbits;
7297c478bdstevel@tonic-gate		if (minbits == 0) {
7307c478bdstevel@tonic-gate			for (i = 0; i < ipsec_nalgs[type]; i++) {
7317c478bdstevel@tonic-gate				if (known_algs[type][i].id == id)
7327c478bdstevel@tonic-gate					break;
7337c478bdstevel@tonic-gate			}
7347c478bdstevel@tonic-gate			if (i < ipsec_nalgs[type])
7357c478bdstevel@tonic-gate				minbits = known_algs[type][i].defkeybits;
7367c478bdstevel@tonic-gate		}
7377c478bdstevel@tonic-gate		if (minbits != 0)
7387c478bdstevel@tonic-gate			/* LINTED E_CONST_COND */
7397c478bdstevel@tonic-gate			ATTR(ap, minbitattr, minbits);
7407c478bdstevel@tonic-gate		if (ar->alg_maxbits != SPD_MAX_MAXBITS)
7417c478bdstevel@tonic-gate			/* LINTED E_CONST_COND */
7427c478bdstevel@tonic-gate			ATTR(ap, maxbitattr, ar->alg_maxbits);
7437c478bdstevel@tonic-gate	}
7447c478bdstevel@tonic-gate
7457c478bdstevel@tonic-gate	return (ap);
7467c478bdstevel@tonic-gate}
7477c478bdstevel@tonic-gate
7487c478bdstevel@tonic-gate
7497c478bdstevel@tonic-gate
7507c478bdstevel@tonic-gatestatic struct spd_attribute *
7517c478bdstevel@tonic-gateips_act_props_to_action(struct spd_attribute *ap, uint32_t *rule_priorityp,
7527c478bdstevel@tonic-gate    const ips_act_props_t *act_ptr)
7537c478bdstevel@tonic-gate{
7547c478bdstevel@tonic-gate	uint32_t rule_priority = *rule_priorityp;
7557c478bdstevel@tonic-gate
7567c478bdstevel@tonic-gate	/* LINTED E_CONST_COND */
7577c478bdstevel@tonic-gate	ATTR(ap, SPD_ATTR_EMPTY, 0);
7587c478bdstevel@tonic-gate
7597c478bdstevel@tonic-gate	/* type */
7607c478bdstevel@tonic-gate	/* LINTED E_CONST_COND */
7617c478bdstevel@tonic-gate	ATTR(ap, SPD_ATTR_TYPE, act_ptr->iap_action);
7627c478bdstevel@tonic-gate
7637c478bdstevel@tonic-gate	if (act_ptr->iap_action == SPD_ACTTYPE_PASS)
7647c478bdstevel@tonic-gate		rule_priority |= BYPASS_POLICY_BOOST;
7657c478bdstevel@tonic-gate
7667c478bdstevel@tonic-gate	/* flags */
7677c478bdstevel@tonic-gate	if (act_ptr->iap_attr != 0)
7687c478bdstevel@tonic-gate		/* LINTED E_CONST_COND */
7697c478bdstevel@tonic-gate		ATTR(ap, SPD_ATTR_FLAGS, act_ptr->iap_attr);
7707c478bdstevel@tonic-gate
7717c478bdstevel@tonic-gate	/* esp */
7727c478bdstevel@tonic-gate	if (act_ptr->iap_attr & SPD_APPLY_ESP) {
7737c478bdstevel@tonic-gate		rule_priority |= ESP_POLICY_BOOST;
7747c478bdstevel@tonic-gate
7757c478bdstevel@tonic-gate		/* encr */
7767c478bdstevel@tonic-gate		ap = emit_alg(ap, ESP_ENCR, &act_ptr->iap_eencr,
7777c478bdstevel@tonic-gate		    SPD_ATTR_ESP_ENCR,
7787c478bdstevel@tonic-gate		    SPD_ATTR_ENCR_MINBITS, SPD_ATTR_ENCR_MAXBITS);
7797c478bdstevel@tonic-gate
7807c478bdstevel@tonic-gate		/* auth */
7817c478bdstevel@tonic-gate		ap = emit_alg(ap, ESP_AUTH, &act_ptr->iap_eauth,
7827c478bdstevel@tonic-gate		    SPD_ATTR_ESP_AUTH,
7837c478bdstevel@tonic-gate		    SPD_ATTR_ESPA_MINBITS, SPD_ATTR_ESPA_MAXBITS);
7847c478bdstevel@tonic-gate	}
7857c478bdstevel@tonic-gate
7867c478bdstevel@tonic-gate	/* ah */
7877c478bdstevel@tonic-gate	if (act_ptr->iap_attr & SPD_APPLY_AH) {
7887c478bdstevel@tonic-gate		rule_priority |= AH_POLICY_BOOST;
7897c478bdstevel@tonic-gate		/* auth */
7907c478bdstevel@tonic-gate		ap = emit_alg(ap, AH_AUTH, &act_ptr->iap_aauth,
7917c478bdstevel@tonic-gate		    SPD_ATTR_AH_AUTH,
7927c478bdstevel@tonic-gate		    SPD_ATTR_AH_MINBITS, SPD_ATTR_AH_MAXBITS);
7937c478bdstevel@tonic-gate	}
7947c478bdstevel@tonic-gate
7957c478bdstevel@tonic-gate	/* lifetimes */
7967c478bdstevel@tonic-gate	if (act_ptr->iap_life_soft_time != 0)
7977c478bdstevel@tonic-gate		/* LINTED E_CONST_COND */
7987c478bdstevel@tonic-gate		ATTR(ap, SPD_ATTR_LIFE_SOFT_TIME, act_ptr->iap_life_soft_time);
7997c478bdstevel@tonic-gate	if (act_ptr->iap_life_hard_time != 0)
8007c478bdstevel@tonic-gate		/* LINTED E_CONST_COND */
8017c478bdstevel@tonic-gate		ATTR(ap, SPD_ATTR_LIFE_HARD_TIME, act_ptr->iap_life_hard_time);
8027c478bdstevel@tonic-gate	if (act_ptr->iap_life_soft_bytes != 0)
8037c478bdstevel@tonic-gate		/* LINTED E_CONST_COND */
8047c478bdstevel@tonic-gate		ATTR(ap, SPD_ATTR_LIFE_SOFT_BYTES,
8057c478bdstevel@tonic-gate		    act_ptr->iap_life_soft_bytes);
8067c478bdstevel@tonic-gate	if (act_ptr->iap_life_hard_bytes != 0)
8077c478bdstevel@tonic-gate		/* LINTED E_CONST_COND */
8087c478bdstevel@tonic-gate		ATTR(ap, SPD_ATTR_LIFE_HARD_BYTES,
8097c478bdstevel@tonic-gate		    act_ptr->iap_life_hard_bytes);
8107c478bdstevel@tonic-gate
8117c478bdstevel@tonic-gate	/* LINTED E_CONST_COND */
8127c478bdstevel@tonic-gate	ATTR(ap, SPD_ATTR_NEXT, 0);
8137c478bdstevel@tonic-gate
8147c478bdstevel@tonic-gate	*rule_priorityp = rule_priority;
8157c478bdstevel@tonic-gate
8167c478bdstevel@tonic-gate	return (ap);
8177c478bdstevel@tonic-gate}
8187c478bdstevel@tonic-gate
8197c478bdstevel@tonic-gatestatic boolean_t
8207c478bdstevel@tonic-gatealg_rangecheck(uint_t type, uint_t algid, const algreq_t *ar)
8217c478bdstevel@tonic-gate{
8227c478bdstevel@tonic-gate	int i;
8237c478bdstevel@tonic-gate	uint_t minbits = ar->alg_minbits;
8247c478bdstevel@tonic-gate	uint_t maxbits = ar->alg_maxbits;
8257c478bdstevel@tonic-gate
8267c478bdstevel@tonic-gate	for (i = 0; i < ipsec_nalgs[type]; i++) {
8277c478bdstevel@tonic-gate		if (known_algs[type][i].id == algid)
8287c478bdstevel@tonic-gate			break;
8297c478bdstevel@tonic-gate	}
8307c478bdstevel@tonic-gate
8317c478bdstevel@tonic-gate	if (i >= ipsec_nalgs[type]) {
8327c478bdstevel@tonic-gate		/*
8337c478bdstevel@tonic-gate		 * The kernel (where we populate known_algs from) doesn't
8347c478bdstevel@tonic-gate		 * return the id's associated with NONE algorithms so we
8357c478bdstevel@tonic-gate		 * test here if this was the reason the algorithm wasn't
8367c478bdstevel@tonic-gate		 * found before wrongly failing.
8377c478bdstevel@tonic-gate		 */
8387c478bdstevel@tonic-gate		if (((type == ESP_ENCR) && (algid == SADB_EALG_NONE)) ||
8397c478bdstevel@tonic-gate		    ((type == ESP_AUTH) && (algid == SADB_AALG_NONE)) ||
8407c478bdstevel@tonic-gate		    ((type == AH_AUTH) && (algid == SADB_AALG_NONE))) {
8417c478bdstevel@tonic-gate			return (B_TRUE);
8427c478bdstevel@tonic-gate		} else {
8437c478bdstevel@tonic-gate			return (B_FALSE); /* not found */
8447c478bdstevel@tonic-gate		}
8457c478bdstevel@tonic-gate	}
8467c478bdstevel@tonic-gate
8477c478bdstevel@tonic-gate	if ((minbits == 0) && (maxbits == 0))
8487c478bdstevel@tonic-gate		return (B_TRUE);
8497c478bdstevel@tonic-gate
8507c478bdstevel@tonic-gate	minbits = MAX(minbits, known_algs[type][i].minkeybits);
8517c478bdstevel@tonic-gate	maxbits = MIN(maxbits, known_algs[type][i].maxkeybits);
8527c478bdstevel@tonic-gate
8537c478bdstevel@tonic-gate	/* we could also check key increments here.. */
8547c478bdstevel@tonic-gate	return (minbits <= maxbits); /* non-null intersection */
8557c478bdstevel@tonic-gate}
8567c478bdstevel@tonic-gate
8577c478bdstevel@tonic-gate/*
8587c478bdstevel@tonic-gate * Inspired by uts/common/inet/spd.c:ipsec_act_wildcard_expand()
8597c478bdstevel@tonic-gate */
8607c478bdstevel@tonic-gate
8617c478bdstevel@tonic-gatestatic struct spd_attribute *
8627c478bdstevel@tonic-gateips_act_wild_props_to_action(struct spd_attribute *ap,
8637c478bdstevel@tonic-gate    uint32_t *rule_priorityp, uint16_t *act_cntp,
8647c478bdstevel@tonic-gate    const ips_act_props_t *act_ptr)
8657c478bdstevel@tonic-gate{
8667c478bdstevel@tonic-gate	ips_act_props_t tact = *act_ptr;
867130b5e3Dan McDonald	boolean_t use_ah, use_esp, use_espa, combined;
8687c478bdstevel@tonic-gate	boolean_t wild_auth, wild_encr, wild_eauth;
8697c478bdstevel@tonic-gate	uint_t	auth_alg, auth_idx, auth_min, auth_max;
8707c478bdstevel@tonic-gate	uint_t	eauth_alg, eauth_idx, eauth_min, eauth_max;
8717c478bdstevel@tonic-gate	uint_t  encr_alg, encr_idx, encr_min, encr_max;
8727c478bdstevel@tonic-gate
8737c478bdstevel@tonic-gate	use_ah = !!(act_ptr->iap_attr & SPD_APPLY_AH);
8747c478bdstevel@tonic-gate	use_esp = !!(act_ptr->iap_attr & SPD_APPLY_ESP);
8757c478bdstevel@tonic-gate	use_espa = !!(act_ptr->iap_attr & SPD_APPLY_ESPA);
8767c478bdstevel@tonic-gate	auth_alg = act_ptr->iap_aauth.alg_id;
8777c478bdstevel@tonic-gate	eauth_alg = act_ptr->iap_eauth.alg_id;
8787c478bdstevel@tonic-gate	encr_alg = act_ptr->iap_eencr.alg_id;
8797c478bdstevel@tonic-gate
8807c478bdstevel@tonic-gate	wild_auth = use_ah && (auth_alg == SADB_AALG_NONE);
8817c478bdstevel@tonic-gate	wild_eauth = use_espa && (eauth_alg == SADB_AALG_NONE);
8827c478bdstevel@tonic-gate	wild_encr = use_esp && (encr_alg == SADB_EALG_NONE);
8837c478bdstevel@tonic-gate
8847c478bdstevel@tonic-gate	auth_min = auth_max = auth_alg;
8857c478bdstevel@tonic-gate	eauth_min = eauth_max = eauth_alg;
8867c478bdstevel@tonic-gate	encr_min = encr_max = encr_alg;
8877c478bdstevel@tonic-gate
8887c478bdstevel@tonic-gate	/*
8897c478bdstevel@tonic-gate	 * set up for explosion.. for each dimension, expand output
8907c478bdstevel@tonic-gate	 * size by the explosion factor.
8917c478bdstevel@tonic-gate	 */
8927c478bdstevel@tonic-gate	if (wild_auth) {
8937c478bdstevel@tonic-gate		auth_min = 0;
8947c478bdstevel@tonic-gate		auth_max = ipsec_nalgs[AH_AUTH] - 1;
8957c478bdstevel@tonic-gate	}
8967c478bdstevel@tonic-gate	if (wild_eauth) {
8977c478bdstevel@tonic-gate		eauth_min = 0;
8987c478bdstevel@tonic-gate		eauth_max = ipsec_nalgs[ESP_AUTH] - 1;
8997c478bdstevel@tonic-gate	}
9007c478bdstevel@tonic-gate	if (wild_encr) {
9017c478bdstevel@tonic-gate		encr_min = 0;
9027c478bdstevel@tonic-gate		encr_max = ipsec_nalgs[ESP_ENCR] - 1;
9037c478bdstevel@tonic-gate	}
9047c478bdstevel@tonic-gate
9057c478bdstevel@tonic-gate#define	WHICH_ALG(type, wild, idx) ((wild)?(known_algs[type][idx].id):(idx))
9067c478bdstevel@tonic-gate
9077c478bdstevel@tonic-gate	for (encr_idx = encr_min; encr_idx <= encr_max; encr_idx++) {
9087c478bdstevel@tonic-gate		encr_alg = WHICH_ALG(ESP_ENCR, wild_encr, encr_idx);
9097c478bdstevel@tonic-gate
9107c478bdstevel@tonic-gate		if (use_esp &&
9117c478bdstevel@tonic-gate		    !alg_rangecheck(ESP_ENCR, encr_alg, &act_ptr->iap_eencr))
9127c478bdstevel@tonic-gate			continue;
9137c478bdstevel@tonic-gate
914130b5e3Dan McDonald		combined = combined_mode(encr_alg);
915130b5e3Dan McDonald
9167c478bdstevel@tonic-gate		for (auth_idx = auth_min; auth_idx <= auth_max; auth_idx++) {
9177c478bdstevel@tonic-gate			auth_alg = WHICH_ALG(AH_AUTH, wild_auth, auth_idx);
9187c478bdstevel@tonic-gate
9197c478bdstevel@tonic-gate			if (use_ah &&
9207c478bdstevel@tonic-gate			    !alg_rangecheck(AH_AUTH, auth_alg,
921d575148markfen			    &act_ptr->iap_aauth))
9227c478bdstevel@tonic-gate				continue;
9237c478bdstevel@tonic-gate
9247c478bdstevel@tonic-gate
9257c478bdstevel@tonic-gate			for (eauth_idx = eauth_min; eauth_idx <= eauth_max;
9267c478bdstevel@tonic-gate			    eauth_idx++) {
9277c478bdstevel@tonic-gate				eauth_alg = WHICH_ALG(ESP_AUTH, wild_eauth,
9287c478bdstevel@tonic-gate				    eauth_idx);
9297c478bdstevel@tonic-gate
930130b5e3Dan McDonald				if (!combined && use_espa &&
9317c478bdstevel@tonic-gate				    !alg_rangecheck(ESP_AUTH, eauth_alg,
9327c478bdstevel@tonic-gate				    &act_ptr->iap_eauth))
9337c478bdstevel@tonic-gate					continue;
9347c478bdstevel@tonic-gate
9357c478bdstevel@tonic-gate				tact.iap_eencr.alg_id = encr_alg;
9367c478bdstevel@tonic-gate				tact.iap_aauth.alg_id = auth_alg;
9377c478bdstevel@tonic-gate
938130b5e3Dan McDonald				/*
939130b5e3Dan McDonald				 * If the cipher is combined-mode don't do any
940130b5e3Dan McDonald				 * ESP authentication.
941130b5e3Dan McDonald				 */
942130b5e3Dan McDonald				tact.iap_eauth.alg_id =
943130b5e3Dan McDonald				    combined ? SADB_AALG_NONE : eauth_alg;
944130b5e3Dan McDonald
9457c478bdstevel@tonic-gate				(*act_cntp)++;
9467c478bdstevel@tonic-gate				ap = ips_act_props_to_action(ap,
9477c478bdstevel@tonic-gate				    rule_priorityp, &tact);
948130b5e3Dan McDonald
949130b5e3Dan McDonald				/* Stop now if the cipher is combined-mode. */
950130b5e3Dan McDonald				if (combined)
951130b5e3Dan McDonald					break;	/* Out of for loop. */
9527c478bdstevel@tonic-gate			}
9537c478bdstevel@tonic-gate		}
9547c478bdstevel@tonic-gate	}
9557c478bdstevel@tonic-gate
9567c478bdstevel@tonic-gate#undef WHICH_ALG
9577c478bdstevel@tonic-gate
9587c478bdstevel@tonic-gate	return (ap);
9597c478bdstevel@tonic-gate}
9607c478bdstevel@tonic-gate
9617c478bdstevel@tonic-gate/* huge, but not safe since no length checking is done */
9627c478bdstevel@tonic-gate#define	MAX_POL_MSG_LEN 16384
9637c478bdstevel@tonic-gate
9647c478bdstevel@tonic-gate
9657c478bdstevel@tonic-gate/*
9667c478bdstevel@tonic-gate * hand in some ips_conf_t's, get back an
9677c478bdstevel@tonic-gate * iovec of pfpol messages.
9687c478bdstevel@tonic-gate * this function converts the internal ips_conf_t into
9697c478bdstevel@tonic-gate * a form that pf_pol can use.
9707c478bdstevel@tonic-gate * return 0 on success, 1 on failure
9717c478bdstevel@tonic-gate */
9727c478bdstevel@tonic-gatestatic int
9737c478bdstevel@tonic-gateips_conf_to_pfpol_msg(int ipsec_cmd, ips_conf_t *inConf, int num_ips,
9747c478bdstevel@tonic-gate    struct iovec *msg)
9757c478bdstevel@tonic-gate{
9767c478bdstevel@tonic-gate	int i;
9777c478bdstevel@tonic-gate	ips_conf_t *conf;
9787c478bdstevel@tonic-gate	uint64_t *scratch = NULL;
9797c478bdstevel@tonic-gate
9807c478bdstevel@tonic-gate	for (i = 0; i < num_ips; i++) {
9817c478bdstevel@tonic-gate		uint16_t *msg_len;
9827c478bdstevel@tonic-gate		uint16_t act_cnt = 0;
9837c478bdstevel@tonic-gate		uint64_t *next = NULL;
9847c478bdstevel@tonic-gate		spd_msg_t *spd_msg;
9857c478bdstevel@tonic-gate		spd_address_t *spd_address;
9867c478bdstevel@tonic-gate		struct spd_rule *spd_rule;
9877c478bdstevel@tonic-gate		struct spd_proto *spd_proto;
9887c478bdstevel@tonic-gate		struct spd_portrange *spd_portrange;
9897c478bdstevel@tonic-gate		struct spd_ext_actions *spd_ext_actions;
9907c478bdstevel@tonic-gate		struct spd_attribute *ap;
9917c478bdstevel@tonic-gate		struct spd_typecode *spd_typecode;
9928810c16danmcd		spd_if_t *spd_if;
9937c478bdstevel@tonic-gate		ips_act_props_t *act_ptr;
9947c478bdstevel@tonic-gate		uint32_t rule_priority = 0;
9957c478bdstevel@tonic-gate
9967c478bdstevel@tonic-gate		scratch = calloc(1, MAX_POL_MSG_LEN);
9977c478bdstevel@tonic-gate		msg[i].iov_base = (char *)scratch;
9987c478bdstevel@tonic-gate		if (scratch == NULL) {
9997c478bdstevel@tonic-gate			warn(gettext("memory"));
10007c478bdstevel@tonic-gate			return (1);
10017c478bdstevel@tonic-gate		}
10027c478bdstevel@tonic-gate		conf = &(inConf[i]);
10037c478bdstevel@tonic-gate
10047c478bdstevel@tonic-gate		spd_msg = (spd_msg_t *)scratch;
10057c478bdstevel@tonic-gate		next = (uint64_t *)&(spd_msg[1]);
10067c478bdstevel@tonic-gate
10077c478bdstevel@tonic-gate		msg_len = &(spd_msg->spd_msg_len);
10087c478bdstevel@tonic-gate
10097c478bdstevel@tonic-gate		spd_msg->spd_msg_version = PF_POLICY_V1;
10107c478bdstevel@tonic-gate		spd_msg->spd_msg_pid = getpid();
10117c478bdstevel@tonic-gate		spd_msg->spd_msg_seq = ++seq_cnt;
10127c478bdstevel@tonic-gate
10137c478bdstevel@tonic-gate		switch (ipsec_cmd) {
10147c478bdstevel@tonic-gate		case SPD_ADDRULE:
10157c478bdstevel@tonic-gate			spd_msg->spd_msg_type = SPD_ADDRULE;
10167c478bdstevel@tonic-gate			break;
10177c478bdstevel@tonic-gate
10187c478bdstevel@tonic-gate		default:
10197c478bdstevel@tonic-gate			warnx("%s %d", gettext("bad command:"), ipsec_cmd);
10207c478bdstevel@tonic-gate			spd_msg->spd_msg_type = SPD_ADDRULE;
10217c478bdstevel@tonic-gate			break;
10227c478bdstevel@tonic-gate		}
10237c478bdstevel@tonic-gate
10247c478bdstevel@tonic-gate		/*
10257c478bdstevel@tonic-gate		 * SELECTOR
10267c478bdstevel@tonic-gate		 */
10277c478bdstevel@tonic-gate
10287c478bdstevel@tonic-gate		spd_msg->spd_msg_spdid = SPD_STANDBY;
10297c478bdstevel@tonic-gate
10307c478bdstevel@tonic-gate		/* rule */
10317c478bdstevel@tonic-gate		spd_rule = (struct spd_rule *)next;
10327c478bdstevel@tonic-gate
10337c478bdstevel@tonic-gate		spd_rule->spd_rule_len = SPD_8TO64(sizeof (struct spd_rule));
10347c478bdstevel@tonic-gate		spd_rule->spd_rule_type = SPD_EXT_RULE;
10357c478bdstevel@tonic-gate		spd_rule->spd_rule_flags = conf->ips_dir;
10368810c16danmcd		if (conf->ips_tunnel)
10378810c16danmcd			spd_rule->spd_rule_flags |= SPD_RULE_FLAG_TUNNEL;
10387c478bdstevel@tonic-gate
10397c478bdstevel@tonic-gate		next = (uint64_t *)&(spd_rule[1]);
10407c478bdstevel@tonic-gate
10417c478bdstevel@tonic-gate		/* proto */
10427c478bdstevel@tonic-gate		if (conf->ips_ulp_prot != 0) {
10437c478bdstevel@tonic-gate			spd_proto = (struct spd_proto *)next;
10447c478bdstevel@tonic-gate			spd_proto->spd_proto_len =
1045d575148markfen			    SPD_8TO64(sizeof (struct spd_proto));
10467c478bdstevel@tonic-gate			spd_proto->spd_proto_exttype = SPD_EXT_PROTO;
10477c478bdstevel@tonic-gate			spd_proto->spd_proto_number = conf->ips_ulp_prot;
10487c478bdstevel@tonic-gate			next = (uint64_t *)&(spd_proto[1]);
10497c478bdstevel@tonic-gate		}
10507c478bdstevel@tonic-gate
10518810c16danmcd		/* tunnel */
10528810c16danmcd		if (conf->has_tunnel != 0) {
10538810c16danmcd			spd_if = (spd_if_t *)next;
10548810c16danmcd			spd_if->spd_if_len =
10558810c16danmcd			    SPD_8TO64(P2ROUNDUP(strlen(tunif) + 1, 8) +
10568810c16danmcd			    sizeof (spd_if_t));
10578810c16danmcd			spd_if->spd_if_exttype = SPD_EXT_TUN_NAME;
10588810c16danmcd			(void) strlcpy((char *)spd_if->spd_if_name, tunif,
1059d575148markfen			    TUNNAMEMAXLEN);
10608810c16danmcd			next = (uint64_t *)(spd_if) + spd_if->spd_if_len;
10618810c16danmcd		}
10628810c16danmcd
10637c478bdstevel@tonic-gate		/* icmp type/code */
10647c478bdstevel@tonic-gate		if (conf->ips_ulp_prot == IPPROTO_ICMP ||
10657c478bdstevel@tonic-gate		    conf->ips_ulp_prot == IPPROTO_ICMPV6) {
10667c478bdstevel@tonic-gate			if (conf->has_type) {
10677c478bdstevel@tonic-gate				spd_typecode = (struct spd_typecode *)next;
10687c478bdstevel@tonic-gate				spd_typecode->spd_typecode_len =
10697c478bdstevel@tonic-gate				    SPD_8TO64(sizeof (struct spd_typecode));
10707c478bdstevel@tonic-gate				spd_typecode->spd_typecode_exttype =
10717c478bdstevel@tonic-gate				    SPD_EXT_ICMP_TYPECODE;
10727c478bdstevel@tonic-gate				spd_typecode->spd_typecode_type =
10737c478bdstevel@tonic-gate				    conf->ips_icmp_type;
10747c478bdstevel@tonic-gate				spd_typecode->spd_typecode_type_end =
10757c478bdstevel@tonic-gate				    conf->ips_icmp_type_end;
10767c478bdstevel@tonic-gate				if (conf->has_code) {
10777c478bdstevel@tonic-gate					spd_typecode->spd_typecode_code =
10787c478bdstevel@tonic-gate					    conf->ips_icmp_code;
10797c478bdstevel@tonic-gate					spd_typecode->spd_typecode_code_end =
10807c478bdstevel@tonic-gate					    conf->ips_icmp_code_end;
10817c478bdstevel@tonic-gate				} else {
10827c478bdstevel@tonic-gate					spd_typecode->spd_typecode_code = 255;
10837c478bdstevel@tonic-gate					spd_typecode->spd_typecode_code_end
10847c478bdstevel@tonic-gate					    = 255;
10857c478bdstevel@tonic-gate				}
10867c478bdstevel@tonic-gate				next = (uint64_t *)&(spd_typecode[1]);
10877c478bdstevel@tonic-gate			}
10887c478bdstevel@tonic-gate		}
10897c478bdstevel@tonic-gate
10907c478bdstevel@tonic-gate		/* src port */
10917c478bdstevel@tonic-gate		if (conf->ips_src_port_min != 0 ||
10927c478bdstevel@tonic-gate		    conf->ips_src_port_max != 0) {
10937c478bdstevel@tonic-gate			spd_portrange = (struct spd_portrange *)next;
10947c478bdstevel@tonic-gate			spd_portrange->spd_ports_len =
1095d575148markfen			    SPD_8TO64(sizeof (struct spd_portrange));
10967c478bdstevel@tonic-gate			spd_portrange->spd_ports_exttype =
1097d575148markfen			    (conf->swap)?SPD_EXT_REMPORT:SPD_EXT_LCLPORT;
10987c478bdstevel@tonic-gate			spd_portrange->spd_ports_minport =
1099d575148markfen			    conf->ips_src_port_min;
11007c478bdstevel@tonic-gate			spd_portrange->spd_ports_maxport =
1101d575148markfen			    conf->ips_src_port_max;
11027c478bdstevel@tonic-gate			next = (uint64_t *)&(spd_portrange[1]);
11037c478bdstevel@tonic-gate		}
11047c478bdstevel@tonic-gate		/* dst port */
11057c478bdstevel@tonic-gate		if (conf->ips_dst_port_min != 0 ||
11067c478bdstevel@tonic-gate		    conf->ips_dst_port_max != 0) {
11077c478bdstevel@tonic-gate			spd_portrange = (struct spd_portrange *)next;
11087c478bdstevel@tonic-gate			spd_portrange->spd_ports_len =
1109d575148markfen			    SPD_8TO64(sizeof (struct spd_portrange));
11107c478bdstevel@tonic-gate			spd_portrange->spd_ports_exttype =
1111d575148markfen			    (conf->swap)?SPD_EXT_LCLPORT:SPD_EXT_REMPORT;
11127c478bdstevel@tonic-gate			spd_portrange->spd_ports_minport =
1113d575148markfen			    conf->ips_dst_port_min;
11147c478bdstevel@tonic-gate			spd_portrange->spd_ports_maxport =
1115d575148markfen			    conf->ips_dst_port_max;
11167c478bdstevel@tonic-gate			next = (uint64_t *)&(spd_portrange[1]);
11177c478bdstevel@tonic-gate		}
11187c478bdstevel@tonic-gate
11197c478bdstevel@tonic-gate		/* saddr */
11207c478bdstevel@tonic-gate		if (conf->has_saddr) {
11217c478bdstevel@tonic-gate			spd_address = (spd_address_t *)next;
11227c478bdstevel@tonic-gate			next = (uint64_t *)(spd_address + 1);
11237c478bdstevel@tonic-gate
11247c478bdstevel@tonic-gate			spd_address->spd_address_exttype =
1125d575148markfen			    (conf->swap)?SPD_EXT_REMADDR:SPD_EXT_LCLADDR;
11267c478bdstevel@tonic-gate			spd_address->spd_address_prefixlen =
1127d575148markfen			    conf->ips_src_mask_len;
11287c478bdstevel@tonic-gate
11297c478bdstevel@tonic-gate			if (conf->ips_isv4) {
11307c478bdstevel@tonic-gate				spd_address->spd_address_af = AF_INET;
11317c478bdstevel@tonic-gate				(void) memcpy(next, &(conf->ips_src_addr),
1132d575148markfen				    sizeof (ipaddr_t));
11337c478bdstevel@tonic-gate				spd_address->spd_address_len = 2;
11347c478bdstevel@tonic-gate				next += SPD_8TO64(sizeof (ipaddr_t) + 4);
11357c478bdstevel@tonic-gate				if (!conf->has_smask)
11367c478bdstevel@tonic-gate					spd_address->spd_address_prefixlen = 32;
11377c478bdstevel@tonic-gate			} else {
11387c478bdstevel@tonic-gate				spd_address->spd_address_af = AF_INET6;
11397c478bdstevel@tonic-gate				(void) memcpy(next, &(conf->ips_src_addr_v6),
11407c478bdstevel@tonic-gate				    sizeof (in6_addr_t));
11417c478bdstevel@tonic-gate				spd_address->spd_address_len = 3;
11427c478bdstevel@tonic-gate				next += SPD_8TO64(sizeof (in6_addr_t));
11437c478bdstevel@tonic-gate				if (!conf->has_smask)
11447c478bdstevel@tonic-gate					spd_address->spd_address_prefixlen
1145d575148markfen					    = 128;
11467c478bdstevel@tonic-gate			}
11477c478bdstevel@tonic-gate		}
11487c478bdstevel@tonic-gate
11497c478bdstevel@tonic-gate		/* daddr */
11507c478bdstevel@tonic-gate		if (conf->has_daddr) {
11517c478bdstevel@tonic-gate			spd_address = (spd_address_t *)next;
11527c478bdstevel@tonic-gate
11537c478bdstevel@tonic-gate			next = (uint64_t *)(spd_address + 1);
11547c478bdstevel@tonic-gate
11557c478bdstevel@tonic-gate			spd_address->spd_address_exttype =
1156d575148markfen			    (conf->swap)?SPD_EXT_LCLADDR:SPD_EXT_REMADDR;
11577c478bdstevel@tonic-gate			spd_address->spd_address_prefixlen =
1158d575148markfen			    conf->ips_dst_mask_len;
11597c478bdstevel@tonic-gate
11607c478bdstevel@tonic-gate			if (conf->ips_isv4) {
11617c478bdstevel@tonic-gate				spd_address->spd_address_af = AF_INET;
11627c478bdstevel@tonic-gate				(void) memcpy(next, &conf->ips_dst_addr,
11637c478bdstevel@tonic-gate				    sizeof (ipaddr_t));
11647c478bdstevel@tonic-gate				spd_address->spd_address_len = 2;
11657c478bdstevel@tonic-gate				/* "+ 4" below is for padding. */
11667c478bdstevel@tonic-gate				next += SPD_8TO64(sizeof (ipaddr_t) + 4);
11677c478bdstevel@tonic-gate				if (!conf->has_dmask)
11687c478bdstevel@tonic-gate					spd_address->spd_address_prefixlen = 32;
11697c478bdstevel@tonic-gate			} else {
11707c478bdstevel@tonic-gate				spd_address->spd_address_af = AF_INET6;
11717c478bdstevel@tonic-gate				(void) memcpy(next, &(conf->ips_dst_addr_v6),
11727c478bdstevel@tonic-gate				    sizeof (in6_addr_t));
11737c478bdstevel@tonic-gate				spd_address->spd_address_len = 3;
11747c478bdstevel@tonic-gate				next += SPD_8TO64(sizeof (in6_addr_t));
11757c478bdstevel@tonic-gate				if (!conf->has_dmask)
11767c478bdstevel@tonic-gate					spd_address->spd_address_prefixlen
1177d575148markfen					    = 128;
11787c478bdstevel@tonic-gate			}
11797c478bdstevel@tonic-gate		}
11807c478bdstevel@tonic-gate
11817c478bdstevel@tonic-gate		/* actions */
11827c478bdstevel@tonic-gate		spd_ext_actions = (struct spd_ext_actions *)next;
11837c478bdstevel@tonic-gate
11847c478bdstevel@tonic-gate		spd_ext_actions->spd_actions_exttype = SPD_EXT_ACTION;
11857c478bdstevel@tonic-gate
11867c478bdstevel@tonic-gate		act_ptr = conf->ips_acts;
11877c478bdstevel@tonic-gate		ap = (struct spd_attribute *)(&spd_ext_actions[1]);
11887c478bdstevel@tonic-gate
11897c478bdstevel@tonic-gate		rule_priority = priority--;
11907c478bdstevel@tonic-gate
11917c478bdstevel@tonic-gate		for (act_ptr = conf->ips_acts; act_ptr != NULL;
11927c478bdstevel@tonic-gate		    act_ptr = act_ptr->iap_next) {
11937c478bdstevel@tonic-gate			ap = ips_act_wild_props_to_action(ap, &rule_priority,
11947c478bdstevel@tonic-gate			    &act_cnt, act_ptr);
11957c478bdstevel@tonic-gate		}
11967c478bdstevel@tonic-gate		ap[-1].spd_attr_tag = SPD_ATTR_END;
11977c478bdstevel@tonic-gate
11987c478bdstevel@tonic-gate		next = (uint64_t *)ap;
11997c478bdstevel@tonic-gate
12007c478bdstevel@tonic-gate		spd_rule->spd_rule_priority = rule_priority;
12017c478bdstevel@tonic-gate
12027c478bdstevel@tonic-gate		msg[i].iov_len = (uintptr_t)next - (uintptr_t)msg[i].iov_base;
12037c478bdstevel@tonic-gate		*msg_len = (uint16_t)SPD_8TO64(msg[i].iov_len);
12047c478bdstevel@tonic-gate		spd_ext_actions->spd_actions_count = act_cnt;
12057c478bdstevel@tonic-gate		spd_ext_actions->spd_actions_len =
12067c478bdstevel@tonic-gate		    SPD_8TO64((uintptr_t)next - (uintptr_t)spd_ext_actions);
12077c478bdstevel@tonic-gate#ifdef DEBUG_HEAVY
12087c478bdstevel@tonic-gate		printf("pfpol msg len in uint64_t's = %d\n", *msg_len);
12097c478bdstevel@tonic-gate		printf("pfpol test_len in bytes = %d\n", msg[i].iov_len);
12107c478bdstevel@tonic-gate		pfpol_msg_dump((spd_msg_t *)scratch,
12117c478bdstevel@tonic-gate		    "ips_conf_to_pfpol_msg");
12127c478bdstevel@tonic-gate#endif
12137c478bdstevel@tonic-gate	}
12147c478bdstevel@tonic-gate
12157c478bdstevel@tonic-gate#undef ATTR
12167c478bdstevel@tonic-gate	return (0);
12177c478bdstevel@tonic-gate}
12187c478bdstevel@tonic-gate
12197c478bdstevel@tonic-gatestatic int
12207c478bdstevel@tonic-gateget_pf_pol_socket(void)
12217c478bdstevel@tonic-gate{
12227c478bdstevel@tonic-gate	int s = socket(PF_POLICY, SOCK_RAW, PF_POLICY_V1);
12237c478bdstevel@tonic-gate	if (s < 0) {
1224e3320f4markfen		if (errno == EPERM) {
1225e3320f4markfen			EXIT_BADPERM("Insufficient privileges to open "
1226e3320f4markfen			    "PF_POLICY socket.");
1227e3320f4markfen		} else {
1228e3320f4markfen			warn(gettext("(loading pf_policy) socket:"));
1229e3320f4markfen		}
12307c478bdstevel@tonic-gate	}
12317c478bdstevel@tonic-gate
12327c478bdstevel@tonic-gate	return (s);
12337c478bdstevel@tonic-gate}
12347c478bdstevel@tonic-gate
12357c478bdstevel@tonic-gate
12367c478bdstevel@tonic-gatestatic int
12378810c16danmcdsend_pf_pol_message(int ipsec_cmd, ips_conf_t *conf, int *diag)
12387c478bdstevel@tonic-gate{
12397c478bdstevel@tonic-gate	int retval;
12407c478bdstevel@tonic-gate	int cnt;
12417c478bdstevel@tonic-gate	int total_len;
12427c478bdstevel@tonic-gate	struct iovec polmsg;
12437c478bdstevel@tonic-gate	spd_msg_t *return_buf;
12447c478bdstevel@tonic-gate	spd_ext_t *exts[SPD_EXT_MAX+1];
12457c478bdstevel@tonic-gate	int fd = get_pf_pol_socket();
12467c478bdstevel@tonic-gate
12478810c16danmcd	*diag = 0;
12488810c16danmcd
12497c478bdstevel@tonic-gate	if (fd < 0)
125043c889dmarkfen		return (EBADF);
12517c478bdstevel@tonic-gate
12527c478bdstevel@tonic-gate	retval = ips_conf_to_pfpol_msg(ipsec_cmd, conf, 1, &polmsg);
12537c478bdstevel@tonic-gate
12547c478bdstevel@tonic-gate	if (retval) {
12557c478bdstevel@tonic-gate		(void) close(fd);
125643c889dmarkfen		return (ENOMEM);
12577c478bdstevel@tonic-gate	}
12587c478bdstevel@tonic-gate
12597c478bdstevel@tonic-gate	total_len = polmsg.iov_len;
12607c478bdstevel@tonic-gate
12617c478bdstevel@tonic-gate	cnt = writev(fd, &polmsg, 1);
12627c478bdstevel@tonic-gate
12637c478bdstevel@tonic-gate#ifdef DEBUG_HEAVY
12647c478bdstevel@tonic-gate	(void) printf("cnt = %d\n", cnt);
12657c478bdstevel@tonic-gate#endif
12667c478bdstevel@tonic-gate	if (cnt < 0) {
12677c478bdstevel@tonic-gate		warn(gettext("pf_pol write"));
12687c478bdstevel@tonic-gate	} else {
12697c478bdstevel@tonic-gate		return_buf = (spd_msg_t *)calloc(total_len, 1);
12707c478bdstevel@tonic-gate
12717c478bdstevel@tonic-gate		if (return_buf == NULL) {
12727c478bdstevel@tonic-gate			warn(gettext("memory"));
12737c478bdstevel@tonic-gate		} else {
12747c478bdstevel@tonic-gate			cnt = read(fd, (void*)return_buf, total_len);
12757c478bdstevel@tonic-gate#ifdef	DEBUG_HEAVY
12767c478bdstevel@tonic-gate			(void) printf("pf_pol read: cnt = %d(%d)\n", cnt,
12777c478bdstevel@tonic-gate			    total_len);
12787c478bdstevel@tonic-gate#endif
12797c478bdstevel@tonic-gate
12807c478bdstevel@tonic-gate			if (cnt > 8 && return_buf->spd_msg_errno) {
12818810c16danmcd				*diag = return_buf->spd_msg_diagnostic;
128243c889dmarkfen				if (!ipsecconf_qflag) {
128343c889dmarkfen					warnx("%s: %s",
12848810c16danmcd					    gettext("Kernel returned"),
12858810c16danmcd					    sys_error_message(
128643c889dmarkfen					    return_buf->spd_msg_errno));
128743c889dmarkfen				}
12888810c16danmcd				if (*diag != 0)
12898810c16danmcd					(void) printf(gettext(
12908810c16danmcd					    "\t(spdsock diagnostic: %s)\n"),
12918810c16danmcd					    spdsock_diag(*diag));
12927c478bdstevel@tonic-gate#ifdef DEBUG_HEAVY
12937c478bdstevel@tonic-gate				pfpol_msg_dump((spd_msg_t *)polmsg.iov_base,
12947c478bdstevel@tonic-gate				    "message in");
12957c478bdstevel@tonic-gate				pfpol_msg_dump(return_buf,
12967c478bdstevel@tonic-gate				    "send_pf_pol_message");
12977c478bdstevel@tonic-gate#endif
129843c889dmarkfen				retval = return_buf->spd_msg_errno;
12997c478bdstevel@tonic-gate				free(return_buf);
13007c478bdstevel@tonic-gate				free(polmsg.iov_base);
13017c478bdstevel@tonic-gate				(void) close(fd);
130243c889dmarkfen				return (retval);
13037c478bdstevel@tonic-gate			}
13047c478bdstevel@tonic-gate
13057c478bdstevel@tonic-gate			retval = spdsock_get_ext(exts, return_buf,
13067c478bdstevel@tonic-gate			    return_buf->spd_msg_len, NULL, 0);
13077c478bdstevel@tonic-gate			/* ignore retval */
13087c478bdstevel@tonic-gate
13097c478bdstevel@tonic-gate			if (exts[SPD_EXT_RULE]) {
13107c478bdstevel@tonic-gate				conf->ips_policy_index =
13117c478bdstevel@tonic-gate				    ((struct spd_rule *)
1312d575148markfen				    exts[SPD_EXT_RULE])->spd_rule_index;
13137c478bdstevel@tonic-gate
13147c478bdstevel@tonic-gate				if (add_index(conf->ips_policy_index)) {
13157c478bdstevel@tonic-gate					free(return_buf);
13167c478bdstevel@tonic-gate					free(polmsg.iov_base);
13177c478bdstevel@tonic-gate					(void) close(fd);
131843c889dmarkfen					return (ENOMEM);
13197c478bdstevel@tonic-gate				}
13207c478bdstevel@tonic-gate			}
13217c478bdstevel@tonic-gate
13227c478bdstevel@tonic-gate			free(return_buf);
13237c478bdstevel@tonic-gate		}
13247c478bdstevel@tonic-gate	}
13257c478bdstevel@tonic-gate
13267c478bdstevel@tonic-gate	free(polmsg.iov_base);
13277c478bdstevel@tonic-gate	(void) close(fd);
13287c478bdstevel@tonic-gate
13297c478bdstevel@tonic-gate	return (0);
13307c478bdstevel@tonic-gate
13317c478bdstevel@tonic-gate}
13327c478bdstevel@tonic-gate
13337c478bdstevel@tonic-gateint
13347c478bdstevel@tonic-gatemain(int argc, char *argv[])
13357c478bdstevel@tonic-gate{
13367c478bdstevel@tonic-gate	int ret, flushret;
13377c478bdstevel@tonic-gate	int c;
13387c478bdstevel@tonic-gate	int index;
1339e3320f4markfen	boolean_t smf_managed;
1340e3320f4markfen	boolean_t just_check = B_FALSE;
13415033e0cMark Fenwick	boolean_t replace_policy = B_FALSE;
1342e3320f4markfen
1343e3320f4markfen	char *smf_warning = gettext(
1344d575148markfen	    "\n\tIPsec policy should be managed using smf(5). Modifying\n"
1345d575148markfen	    "\tthe IPsec policy from the command line while the 'policy'\n"
1346d575148markfen	    "\tservice is enabled could result in an inconsistent\n"
1347d575148markfen	    "\tsecurity policy.\n\n");
1348e3320f4markfen
1349e3320f4markfen	flushret = 0;
13505033e0cMark Fenwick	cmd = 0;
13517c478bdstevel@tonic-gate
13527c478bdstevel@tonic-gate	(void) setlocale(LC_ALL, "");
13537c478bdstevel@tonic-gate#if !defined(TEXT_DOMAIN)
13547c478bdstevel@tonic-gate#define	TEXT_DOMAIN "SYS_TEST"
13557c478bdstevel@tonic-gate#endif
13567c478bdstevel@tonic-gate	(void) textdomain(TEXT_DOMAIN);
13577c478bdstevel@tonic-gate
13587c478bdstevel@tonic-gate	openlog("ipsecconf", LOG_CONS, LOG_AUTH);
13597c478bdstevel@tonic-gate
13607c478bdstevel@tonic-gate	/*
13617c478bdstevel@tonic-gate	 * We don't immediately check for privilege here. This is done by IP
13627c478bdstevel@tonic-gate	 * when we open /dev/ip below.
13637c478bdstevel@tonic-gate	 */
13647c478bdstevel@tonic-gate
13657c478bdstevel@tonic-gate	if (argc == 1) {
13667c478bdstevel@tonic-gate		cmd = IPSEC_CONF_VIEW;
13677c478bdstevel@tonic-gate		goto done;
13687c478bdstevel@tonic-gate	}
1369e3320f4markfen	my_fmri = getenv("SMF_FMRI");
1370e3320f4markfen	if (my_fmri == NULL)
1371e3320f4markfen		smf_managed = B_FALSE;
1372e3320f4markfen	else
1373e3320f4markfen		smf_managed = B_TRUE;
1374e3320f4markfen
1375e3320f4markfen	while ((c = getopt(argc, argv, "nlfLFa:qd:r:i:c:")) != EOF) {
13767c478bdstevel@tonic-gate		switch (c) {
13778810c16danmcd		case 'F':
13788810c16danmcd			if (interface_name != NULL) {
1379e3320f4markfen				USAGE();
1380e3320f4markfen				EXIT_FATAL("interface name not required.");
13818810c16danmcd			}
13828810c16danmcd			/* Apply to all policy heads - global and tunnels. */
13838810c16danmcd			interface_name = &all_polheads;
13848810c16danmcd			/* FALLTHRU */
13857c478bdstevel@tonic-gate		case 'f':
13865033e0cMark Fenwick			/*
13875033e0cMark Fenwick			 * The policy flush command can be specified with -a
13885033e0cMark Fenwick			 * to perform an atomic policy replace. It can't be
13895033e0cMark Fenwick			 * specified with any other flags.
13905033e0cMark Fenwick			 */
13915033e0cMark Fenwick			if (cmd == IPSEC_CONF_ADD) {
13925033e0cMark Fenwick				cmd = IPSEC_CONF_REPLACE;
13935033e0cMark Fenwick				break;
13945033e0cMark Fenwick			}
13957c478bdstevel@tonic-gate			if (cmd != 0) {
1396e3320f4markfen				USAGE();
1397e3320f4markfen				EXIT_FATAL("Multiple commands specified");
13987c478bdstevel@tonic-gate			}
13997c478bdstevel@tonic-gate			cmd = IPSEC_CONF_FLUSH;
14007c478bdstevel@tonic-gate			break;
14018810c16danmcd		case 'L':
14028810c16danmcd			if (interface_name != NULL) {
1403e3320f4markfen				USAGE();
1404e3320f4markfen				EXIT_FATAL("interface name not required.");
14058810c16danmcd			}
14068810c16danmcd			/* Apply to all policy heads - global and tunnels. */
14078810c16danmcd			interface_name = &all_polheads;
14088810c16danmcd			/* FALLTHRU */
14097c478bdstevel@tonic-gate		case 'l':
14107c478bdstevel@tonic-gate			/* Only one command at a time */
14117c478bdstevel@tonic-gate			if (cmd != 0) {
1412e3320f4markfen				USAGE();
1413e3320f4markfen				EXIT_FATAL("Multiple commands specified");
14147c478bdstevel@tonic-gate			}
14157c478bdstevel@tonic-gate			cmd = IPSEC_CONF_LIST;
14167c478bdstevel@tonic-gate			break;
1417e3320f4markfen		case 'c':
1418e3320f4markfen			just_check = B_TRUE;
1419e3320f4markfen			ipsecconf_qflag++;
1420e3320f4markfen			/* FALLTHRU */
14217c478bdstevel@tonic-gate		case 'a':
14225033e0cMark Fenwick			if (cmd == IPSEC_CONF_FLUSH) {
14235033e0cMark Fenwick				cmd = IPSEC_CONF_REPLACE;
14245033e0cMark Fenwick				filename = optarg;
14255033e0cMark Fenwick				break;
14265033e0cMark Fenwick			}
14278810c16danmcd			/* Only one command at a time, and no interface name */
14288810c16danmcd			if (cmd != 0 || interface_name != NULL) {
1429e3320f4markfen				USAGE();
1430e3320f4markfen				EXIT_FATAL("Multiple commands or interface "
1431e3320f4markfen				    "not required.");
14327c478bdstevel@tonic-gate			}
14337c478bdstevel@tonic-gate			cmd = IPSEC_CONF_ADD;
14347c478bdstevel@tonic-gate			filename = optarg;
14357c478bdstevel@tonic-gate			break;
14367c478bdstevel@tonic-gate		case 'd':
14378810c16danmcd			/*
14388810c16danmcd			 * Only one command at a time.  Interface name is
14398810c16danmcd			 * optional.
14408810c16danmcd			 */
14417c478bdstevel@tonic-gate			if (cmd != 0) {
1442e3320f4markfen				USAGE();
1443e3320f4markfen				EXIT_FATAL("Multiple commands specified");
14447c478bdstevel@tonic-gate			}
14457c478bdstevel@tonic-gate			cmd = IPSEC_CONF_DEL;
14468810c16danmcd			index = parse_index(optarg, NULL);
14477c478bdstevel@tonic-gate			break;
14487c478bdstevel@tonic-gate		case 'n' :
14497c478bdstevel@tonic-gate			ipsecconf_nflag++;
14507c478bdstevel@tonic-gate			break;
14517c478bdstevel@tonic-gate		case 'q' :
14527c478bdstevel@tonic-gate			ipsecconf_qflag++;
14537c478bdstevel@tonic-gate			break;
14547c478bdstevel@tonic-gate		case 'r' :
14558810c16danmcd			/* Only one command at a time, and no interface name */
14568810c16danmcd			if (cmd != 0 || interface_name != NULL) {
1457e3320f4markfen				USAGE();
1458e3320f4markfen				EXIT_FATAL("Multiple commands or interface "
1459e3320f4markfen				    "not required.");
14607c478bdstevel@tonic-gate			}
14617c478bdstevel@tonic-gate			cmd = IPSEC_CONF_SUB;
14627c478bdstevel@tonic-gate			filename = optarg;
14637c478bdstevel@tonic-gate			break;
14648810c16danmcd		case 'i':
14658810c16danmcd			if (interface_name != NULL) {
1466e3320f4markfen				EXIT_FATAL("Interface name already selected");
14678810c16danmcd			}
14688810c16danmcd			interface_name = optarg;
14698810c16danmcd			/* Check for some cretin using the all-polheads name. */
14708810c16danmcd			if (strlen(optarg) == 0) {
1471e3320f4markfen				USAGE();
1472e3320f4markfen				EXIT_FATAL("Invalid interface name.");
14738810c16danmcd			}
14748810c16danmcd			break;
14757c478bdstevel@tonic-gate		default :
1476e3320f4markfen			USAGE();
1477e3320f4markfen			EXIT_FATAL("Bad usage.");
14787c478bdstevel@tonic-gate		}
14797c478bdstevel@tonic-gate	}
14807c478bdstevel@tonic-gate
14817c478bdstevel@tonic-gatedone:
14827c478bdstevel@tonic-gate	ret = 0;
14837c478bdstevel@tonic-gate	lfd = lock();
14847c478bdstevel@tonic-gate
14857c478bdstevel@tonic-gate	/*
14867c478bdstevel@tonic-gate	 * ADD, FLUSH, DELETE needs to do two operations.
14877c478bdstevel@tonic-gate	 *
14887c478bdstevel@tonic-gate	 * 1) Update/delete/empty the POLICY_CONF_FILE.
14897c478bdstevel@tonic-gate	 * 2) Make an ioctl and tell IP to update its state.
14907c478bdstevel@tonic-gate	 *
14917c478bdstevel@tonic-gate	 * We already lock()ed so that only one instance of this
14927c478bdstevel@tonic-gate	 * program runs. We also need to make sure that the above
14937c478bdstevel@tonic-gate	 * operations are atomic i.e we don't want to update the file
14947c478bdstevel@tonic-gate	 * and get interrupted before we could tell IP. To make it
14957c478bdstevel@tonic-gate	 * atomic we block all the signals and restore them.
14967c478bdstevel@tonic-gate	 */
14977c478bdstevel@tonic-gate	switch (cmd) {
14987c478bdstevel@tonic-gate	case IPSEC_CONF_LIST:
14997c478bdstevel@tonic-gate		fetch_algorithms();
15007c478bdstevel@tonic-gate		ret = ipsec_conf_list();
15017c478bdstevel@tonic-gate		break;
15027c478bdstevel@tonic-gate	case IPSEC_CONF_FLUSH:
15037c478bdstevel@tonic-gate		if ((ret = block_all_signals()) == -1) {
15047c478bdstevel@tonic-gate			break;
15057c478bdstevel@tonic-gate		}
1506e3320f4markfen		if (!smf_managed && !ipsecconf_qflag)
1507e3320f4markfen			(void) fprintf(stdout, "%s", smf_warning);
15087c478bdstevel@tonic-gate		ret = ipsec_conf_flush(SPD_ACTIVE);
15097c478bdstevel@tonic-gate		(void) restore_all_signals();
15107c478bdstevel@tonic-gate		break;
15117c478bdstevel@tonic-gate	case IPSEC_CONF_VIEW:
15128810c16danmcd		if (interface_name != NULL) {
1513e3320f4markfen			EXIT_FATAL("Cannot view for one interface only.");
15148810c16danmcd		}
15157c478bdstevel@tonic-gate		ret = ipsec_conf_view();
15167c478bdstevel@tonic-gate		break;
15177c478bdstevel@tonic-gate	case IPSEC_CONF_DEL:
15187c478bdstevel@tonic-gate		if (index == -1) {
15197c478bdstevel@tonic-gate			warnx(gettext("Invalid index"));
15207c478bdstevel@tonic-gate			ret = -1;
15217c478bdstevel@tonic-gate			break;
15227c478bdstevel@tonic-gate		}
15237c478bdstevel@tonic-gate		if ((ret = block_all_signals()) == -1) {
15247c478bdstevel@tonic-gate			break;
15257c478bdstevel@tonic-gate		}
1526e3320f4markfen		if (!smf_managed && !ipsecconf_qflag)
1527e3320f4markfen			(void) fprintf(stdout, "%s", smf_warning);
15287c478bdstevel@tonic-gate		ret = ipsec_conf_del(index, B_FALSE);
15297c478bdstevel@tonic-gate		(void) restore_all_signals();
1530e3320f4markfen		flushret = ipsec_conf_flush(SPD_STANDBY);
15317c478bdstevel@tonic-gate		break;
15325033e0cMark Fenwick	case IPSEC_CONF_REPLACE:
15335033e0cMark Fenwick		replace_policy = B_TRUE;
15345033e0cMark Fenwick		/* FALLTHRU */
15357c478bdstevel@tonic-gate	case IPSEC_CONF_ADD:
1536e3320f4markfen		/*
1537e3320f4markfen		 * The IPsec kernel modules should only be loaded
1538e3320f4markfen		 * if there is a policy to install, for this
1539e3320f4markfen		 * reason ipsec_conf_add() calls fetch_algorithms()
1540e3320f4markfen		 * and ipsec_conf_flush() only when appropriate.
1541e3320f4markfen		 */
15427c478bdstevel@tonic-gate		if ((ret = block_all_signals()) == -1) {
15437c478bdstevel@tonic-gate			break;
15447c478bdstevel@tonic-gate		}
1545e3320f4markfen		if (!smf_managed && !ipsecconf_qflag)
1546e3320f4markfen			(void) fprintf(stdout, "%s", smf_warning);
15475033e0cMark Fenwick		ret = ipsec_conf_add(just_check, smf_managed, replace_policy);
15487c478bdstevel@tonic-gate		(void) restore_all_signals();
15497c478bdstevel@tonic-gate		break;
15507c478bdstevel@tonic-gate	case IPSEC_CONF_SUB:
15517c478bdstevel@tonic-gate		fetch_algorithms();
15527c478bdstevel@tonic-gate		if ((ret = block_all_signals()) == -1) {
15537c478bdstevel@tonic-gate			break;
15547c478bdstevel@tonic-gate		}
1555e3320f4markfen		if (!smf_managed && !ipsecconf_qflag)
1556e3320f4markfen			(void) fprintf(stdout, "%s", smf_warning);
15577c478bdstevel@tonic-gate		ret = ipsec_conf_sub();
15587c478bdstevel@tonic-gate		(void) restore_all_signals();
1559e3320f4markfen		flushret = ipsec_conf_flush(SPD_STANDBY);
15607c478bdstevel@tonic-gate		break;
15617c478bdstevel@tonic-gate	default :
15627c478bdstevel@tonic-gate		/* If no argument is given but a "-" */
1563e3320f4markfen		USAGE();
1564e3320f4markfen		EXIT_FATAL("Bad usage.");
15657c478bdstevel@tonic-gate	}
15667c478bdstevel@tonic-gate
15677c478bdstevel@tonic-gate	(void) unlock(lfd);
15687c478bdstevel@tonic-gate	if (ret != 0 || flushret != 0)
15697c478bdstevel@tonic-gate		ret = 1;
15707c478bdstevel@tonic-gate	return (ret);
15717c478bdstevel@tonic-gate}
15727c478bdstevel@tonic-gate
1573e3320f4markfenstatic void
15747c478bdstevel@tonic-gateperm_check(void)
15757c478bdstevel@tonic-gate{
1576e3320f4markfen	if (errno == EACCES)
1577e3320f4markfen		EXIT_BADPERM("Insufficient privilege to run ipsecconf.");
15787c478bdstevel@tonic-gate	else
1579e3320f4markfen		warn(gettext("Cannot open lock file %s"), LOCK_FILE);
1580e3320f4markfen
1581e3320f4markfen	EXIT_BADPERM(NULL);
15827c478bdstevel@tonic-gate}
15837c478bdstevel@tonic-gate
15847c478bdstevel@tonic-gatestatic int
15857c478bdstevel@tonic-gatelock()
15867c478bdstevel@tonic-gate{
15877c478bdstevel@tonic-gate	int fd;
15887c478bdstevel@tonic-gate	struct stat sbuf1;
15897c478bdstevel@tonic-gate	struct stat sbuf2;
15907c478bdstevel@tonic-gate
15917c478bdstevel@tonic-gate	/*
15927c478bdstevel@tonic-gate	 * Open the file with O_CREAT|O_EXCL. If it exists already, it
15937c478bdstevel@tonic-gate	 * will fail. If it already exists, check whether it looks like
15947c478bdstevel@tonic-gate	 * the one we created.
15957c478bdstevel@tonic-gate	 */
15967c478bdstevel@tonic-gate	(void) umask(0077);
15977c478bdstevel@tonic-gate	if ((fd = open(LOCK_FILE, O_EXCL|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR))
15987c478bdstevel@tonic-gate	    == -1) {
15997c478bdstevel@tonic-gate		if (errno != EEXIST) {
1600e3320f4markfen			/* Some other problem. Will exit. */
1601e3320f4markfen			perm_check();
16027c478bdstevel@tonic-gate		}
16037c478bdstevel@tonic-gate
16047c478bdstevel@tonic-gate		/*
16057c478bdstevel@tonic-gate		 * open() returned an EEXIST error. We don't fail yet
16067c478bdstevel@tonic-gate		 * as it could be a residual from a previous
160743c889dmarkfen		 * execution.
16087c478bdstevel@tonic-gate		 * File exists. make sure it is OK. We need to lstat()
16097c478bdstevel@tonic-gate		 * as fstat() stats the file pointed to by the symbolic
16107c478bdstevel@tonic-gate		 * link.
16117c478bdstevel@tonic-gate		 */
16127c478bdstevel@tonic-gate		if (lstat(LOCK_FILE, &sbuf1) == -1) {
1613e3320f4markfen			EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE);
16147c478bdstevel@tonic-gate		}
16157c478bdstevel@tonic-gate		/*
16167c478bdstevel@tonic-gate		 * Check whether it is a regular file and not a symbolic
16177c478bdstevel@tonic-gate		 * link. Its link count should be 1. The owner should be
16187c478bdstevel@tonic-gate		 * root and the file should be empty.
16197c478bdstevel@tonic-gate		 */
16204bc0a2ecasper		if (!S_ISREG(sbuf1.st_mode) ||
16217c478bdstevel@tonic-gate		    sbuf1.st_nlink != 1 ||
16227c478bdstevel@tonic-gate		    sbuf1.st_uid != 0 ||
16237c478bdstevel@tonic-gate		    sbuf1.st_size != 0) {
1624e3320f4markfen			EXIT_FATAL2("Bad lock file %s", LOCK_FILE);
16257c478bdstevel@tonic-gate		}
16267c478bdstevel@tonic-gate		if ((fd = open(LOCK_FILE, O_CREAT|O_RDWR,
16277c478bdstevel@tonic-gate		    S_IRUSR|S_IWUSR)) == -1) {
1628e3320f4markfen			/* Will exit */
1629e3320f4markfen			perm_check();
16307c478bdstevel@tonic-gate		}
16317c478bdstevel@tonic-gate		/*
16327c478bdstevel@tonic-gate		 * Check whether we opened the file that we lstat()ed.
16337c478bdstevel@tonic-gate		 */
16347c478bdstevel@tonic-gate		if (fstat(fd, &sbuf2) == -1) {
1635e3320f4markfen			EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE);
16367c478bdstevel@tonic-gate		}
16377c478bdstevel@tonic-gate		if (sbuf1.st_dev != sbuf2.st_dev ||
16387c478bdstevel@tonic-gate		    sbuf1.st_ino != sbuf2.st_ino) {
16397c478bdstevel@tonic-gate			/* File changed after we did the lstat() above */
1640e3320f4markfen			EXIT_FATAL2("Bad lock file %s", LOCK_FILE);
16417c478bdstevel@tonic-gate		}
16427c478bdstevel@tonic-gate	}
16437c478bdstevel@tonic-gate	if (lockf(fd, F_LOCK, 0) == -1) {
1644e3320f4markfen		EXIT_FATAL2("Cannot lockf %s", LOCK_FILE);
16457c478bdstevel@tonic-gate	}
16467c478bdstevel@tonic-gate	return (fd);
16477c478bdstevel@tonic-gate}
16487c478bdstevel@tonic-gate
16497c478bdstevel@tonic-gatestatic int
16507c478bdstevel@tonic-gateunlock(int fd)
16517c478bdstevel@tonic-gate{
16527c478bdstevel@tonic-gate	if (lockf(fd, F_ULOCK, 0) == -1) {
16537c478bdstevel@tonic-gate		warn("lockf");
16547c478bdstevel@tonic-gate		return (-1);
16557c478bdstevel@tonic-gate	}
16567c478bdstevel@tonic-gate	return (0);
16577c478bdstevel@tonic-gate}
16587c478bdstevel@tonic-gate
16597c478bdstevel@tonic-gate/* send in TOK_* */
16607c478bdstevel@tonic-gatestatic void
16617c478bdstevel@tonic-gateprint_pattern_string(int type)
16627c478bdstevel@tonic-gate{
16637c478bdstevel@tonic-gate	int j;
16647c478bdstevel@tonic-gate
16657c478bdstevel@tonic-gate	for (j = 0; pattern_table[j].string != NULL; j++) {
16667c478bdstevel@tonic-gate		if (type == pattern_table[j].tok_val) {
16677c478bdstevel@tonic-gate			(void) printf("%s ", pattern_table[j].string);
16687c478bdstevel@tonic-gate			return;
16697c478bdstevel@tonic-gate		}
16707c478bdstevel@tonic-gate	}
16717c478bdstevel@tonic-gate}
16727c478bdstevel@tonic-gate
16737c478bdstevel@tonic-gatestatic void
16747c478bdstevel@tonic-gateprint_icmp_typecode(uint8_t type, uint8_t type_end, uint8_t code,
16757c478bdstevel@tonic-gate    uint8_t code_end)
16767c478bdstevel@tonic-gate{
16777c478bdstevel@tonic-gate	(void) printf("type %d", type);
16787c478bdstevel@tonic-gate	if (type_end != type)
16797c478bdstevel@tonic-gate		(void) printf("-%d ", type_end);
16807c478bdstevel@tonic-gate	else
16817c478bdstevel@tonic-gate		(void) printf(" ");
16827c478bdstevel@tonic-gate	if (code != 255) {
16837c478bdstevel@tonic-gate		(void) printf("code %d", code);
16847c478bdstevel@tonic-gate		if (code_end != code)
16857c478bdstevel@tonic-gate			(void) printf("-%d ", code_end);
16867c478bdstevel@tonic-gate		else
16877c478bdstevel@tonic-gate			(void) printf(" ");
16887c478bdstevel@tonic-gate	}
16897c478bdstevel@tonic-gate}
16907c478bdstevel@tonic-gate
16917c478bdstevel@tonic-gate
16927c478bdstevel@tonic-gatestatic void
16937c478bdstevel@tonic-gateprint_spd_flags(uint32_t flags)
16947c478bdstevel@tonic-gate{
16957c478bdstevel@tonic-gate	flags &= (SPD_RULE_FLAG_INBOUND|SPD_RULE_FLAG_OUTBOUND);
16967c478bdstevel@tonic-gate
16977c478bdstevel@tonic-gate	if (flags == SPD_RULE_FLAG_OUTBOUND)
16987c478bdstevel@tonic-gate		(void) printf("dir out ");
16997c478bdstevel@tonic-gate	else if (flags == SPD_RULE_FLAG_INBOUND)
17007c478bdstevel@tonic-gate		(void) printf("dir in ");
17017c478bdstevel@tonic-gate	else if (flags == (SPD_RULE_FLAG_INBOUND|SPD_RULE_FLAG_OUTBOUND))
17027c478bdstevel@tonic-gate		(void) printf("dir both ");
17037c478bdstevel@tonic-gate}
17047c478bdstevel@tonic-gate
17057c478bdstevel@tonic-gatestatic void
17067c478bdstevel@tonic-gateprint_bit_range(int min, int max)
17077c478bdstevel@tonic-gate{
17087c478bdstevel@tonic-gate	if (min != 0 || (max != 0 && max != SPD_MAX_MAXBITS)) {
17097c478bdstevel@tonic-gate		(void) printf("(");
17107c478bdstevel@tonic-gate		if (min != 0)
17117c478bdstevel@tonic-gate			(void) printf("%d", min);
17127c478bdstevel@tonic-gate		if (min != 0 && max != 0 && min != max) {
17137c478bdstevel@tonic-gate			(void) printf("..");
17147c478bdstevel@tonic-gate			if (max != 0 && max != SPD_MAX_MAXBITS)
17157c478bdstevel@tonic-gate				(void) printf("%d", max);
17167c478bdstevel@tonic-gate		}
17177c478bdstevel@tonic-gate		(void) printf(")");
17187c478bdstevel@tonic-gate	}
17197c478bdstevel@tonic-gate}
17207c478bdstevel@tonic-gate
17217c478bdstevel@tonic-gatestatic void
17227c478bdstevel@tonic-gateprint_alg(const char *tag, algreq_t *algreq, int proto_num)
17237c478bdstevel@tonic-gate{
17247c478bdstevel@tonic-gate	int min = algreq->alg_minbits;
17257c478bdstevel@tonic-gate	int max = algreq->alg_maxbits;
17267c478bdstevel@tonic-gate	struct ipsecalgent *alg;
17277c478bdstevel@tonic-gate
17287c478bdstevel@tonic-gate	/*
17297c478bdstevel@tonic-gate	 * This function won't be called with alg_id == 0, so we don't
17307c478bdstevel@tonic-gate	 * have to worry about ANY vs. NONE here.
17317c478bdstevel@tonic-gate	 */
17327c478bdstevel@tonic-gate
17337c478bdstevel@tonic-gate	(void) printf("%s ", tag);
17347c478bdstevel@tonic-gate
17357c478bdstevel@tonic-gate	alg = getipsecalgbynum(algreq->alg_id, proto_num, NULL);
17367c478bdstevel@tonic-gate	if (alg == NULL) {
17377c478bdstevel@tonic-gate		(void) printf("%d", algreq->alg_id);
17387c478bdstevel@tonic-gate	} else {
17397c478bdstevel@tonic-gate		(void) printf("%s", alg->a_names[0]);
17407c478bdstevel@tonic-gate		freeipsecalgent(alg);
17417c478bdstevel@tonic-gate	}
17427c478bdstevel@tonic-gate
17437c478bdstevel@tonic-gate	print_bit_range(min, max);
17447c478bdstevel@tonic-gate	(void) printf(" ");
17457c478bdstevel@tonic-gate}
17467c478bdstevel@tonic-gate
17477c478bdstevel@tonic-gatestatic void
17487c478bdstevel@tonic-gateprint_ulp(uint8_t proto)
17497c478bdstevel@tonic-gate{
17507c478bdstevel@tonic-gate	struct protoent *pe;
17517c478bdstevel@tonic-gate
17527c478bdstevel@tonic-gate	if (proto == 0)
17537c478bdstevel@tonic-gate		return;
17547c478bdstevel@tonic-gate
17557c478bdstevel@tonic-gate	print_pattern_string(TOK_ulp);
17567c478bdstevel@tonic-gate	pe = NULL;
17577c478bdstevel@tonic-gate	if (!ipsecconf_nflag) {
17587c478bdstevel@tonic-gate		pe = getprotobynumber(proto);
17597c478bdstevel@tonic-gate	}
17607c478bdstevel@tonic-gate	if (pe != NULL)
17617c478bdstevel@tonic-gate		(void) printf("%s ", pe->p_name);
17627c478bdstevel@tonic-gate	else
17637c478bdstevel@tonic-gate		(void) printf("%d ", proto);
17647c478bdstevel@tonic-gate}
17657c478bdstevel@tonic-gate
17667c478bdstevel@tonic-gate/* needs to do ranges */
17677c478bdstevel@tonic-gatestatic void
17687c478bdstevel@tonic-gateprint_port(uint16_t in_port, int type)
17697c478bdstevel@tonic-gate{
17707c478bdstevel@tonic-gate	in_port_t port = ntohs(in_port);
17717c478bdstevel@tonic-gate	struct servent *sp;
17727c478bdstevel@tonic-gate
17737c478bdstevel@tonic-gate	if (port == 0)
17747c478bdstevel@tonic-gate		return;
17757c478bdstevel@tonic-gate
17767c478bdstevel@tonic-gate	print_pattern_string(type);
17777c478bdstevel@tonic-gate	sp = NULL;
17787c478bdstevel@tonic-gate	if (!ipsecconf_nflag)
17797c478bdstevel@tonic-gate		sp = getservbyport(port, NULL);
17807c478bdstevel@tonic-gate
17817c478bdstevel@tonic-gate	if (sp != NULL)
17827c478bdstevel@tonic-gate		(void) printf("%s ", sp->s_name);
17837c478bdstevel@tonic-gate	else
17847c478bdstevel@tonic-gate		(void) printf("%d ", port);
17857c478bdstevel@tonic-gate}
17867c478bdstevel@tonic-gate
17877c478bdstevel@tonic-gate/*
17888810c16danmcd * Print the address, given as "raw" input via the void pointer.
17897c478bdstevel@tonic-gate */
17907c478bdstevel@tonic-gatestatic void
17918810c16danmcdprint_raw_address(void *input, boolean_t isv4)
17927c478bdstevel@tonic-gate{
17937c478bdstevel@tonic-gate	char  *cp;
17947c478bdstevel@tonic-gate	struct hostent *hp;
17957c478bdstevel@tonic-gate	char	domain[MAXHOSTNAMELEN + 1];
17967c478bdstevel@tonic-gate	struct in_addr addr;
17977c478bdstevel@tonic-gate	struct in6_addr addr6;
17987c478bdstevel@tonic-gate	char abuf[INET6_ADDRSTRLEN];
17997c478bdstevel@tonic-gate	int error_num;
18007c478bdstevel@tonic-gate	struct in6_addr in_addr;
18017c478bdstevel@tonic-gate	uchar_t *addr_ptr;
18027c478bdstevel@tonic-gate	sa_family_t af;
18037c478bdstevel@tonic-gate	int addr_len;
18047c478bdstevel@tonic-gate
18057c478bdstevel@tonic-gate	if (isv4) {
18067c478bdstevel@tonic-gate		af = AF_INET;
18077c478bdstevel@tonic-gate		(void) memcpy(&V4_PART_OF_V6(in_addr), input, 4);
18087c478bdstevel@tonic-gate		/* we don't print unspecified addresses */
18097c478bdstevel@tonic-gate		IN6_V4MAPPED_TO_INADDR(&in_addr, &addr);
18107c478bdstevel@tonic-gate		if (addr.s_addr == INADDR_ANY)
18117c478bdstevel@tonic-gate			return;
18127c478bdstevel@tonic-gate		addr_ptr = (uchar_t *)&addr.s_addr;
18137c478bdstevel@tonic-gate		addr_len = IPV4_ADDR_LEN;
18147c478bdstevel@tonic-gate	} else {
18157c478bdstevel@tonic-gate		(void) memcpy(&addr6, input, 16);
18167c478bdstevel@tonic-gate		af = AF_INET6;
18177c478bdstevel@tonic-gate		/* we don't print unspecified addresses */
18187c478bdstevel@tonic-gate		if (IN6_IS_ADDR_UNSPECIFIED(&addr6))
18197c478bdstevel@tonic-gate			return;
18207c478bdstevel@tonic-gate		addr_ptr = (uchar_t *)&addr6.s6_addr;
18217c478bdstevel@tonic-gate		addr_len = sizeof (struct in6_addr);
18227c478bdstevel@tonic-gate	}
18237c478bdstevel@tonic-gate
18247c478bdstevel@tonic-gate	cp = NULL;
18257c478bdstevel@tonic-gate	if (!ipsecconf_nflag) {
18267c478bdstevel@tonic-gate		if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 &&
1827d575148markfen		    (cp = strchr(domain, '.')) != NULL) {
1828e3320f4markfen			(void) strlcpy(domain, cp + 1, sizeof (domain));
18297c478bdstevel@tonic-gate		} else {
18307c478bdstevel@tonic-gate			domain[0] = 0;
18317c478bdstevel@tonic-gate		}
1832a13e0a0pwernau		cp = NULL;
18337c478bdstevel@tonic-gate		hp = getipnodebyaddr(addr_ptr, addr_len, af, &error_num);
18347c478bdstevel@tonic-gate		if (hp) {
18357c478bdstevel@tonic-gate			if ((cp = strchr(hp->h_name, '.')) != 0 &&
1836d575148markfen			    strcasecmp(cp + 1, domain) == 0)
18377c478bdstevel@tonic-gate				*cp = 0;
18387c478bdstevel@tonic-gate			cp = hp->h_name;
18397c478bdstevel@tonic-gate		}
18407c478bdstevel@tonic-gate	}
18417c478bdstevel@tonic-gate
18427c478bdstevel@tonic-gate	if (cp) {
18437c478bdstevel@tonic-gate		(void) printf("%s", cp);
18447c478bdstevel@tonic-gate	} else {
18457c478bdstevel@tonic-gate		(void) printf("%s", inet_ntop(af, addr_ptr, abuf,
18467c478bdstevel@tonic-gate		    INET6_ADDRSTRLEN));
18477c478bdstevel@tonic-gate	}
18487c478bdstevel@tonic-gate}
1849