17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 592913378Spwernau * Common Development and Distribution License (the "License"). 692913378Spwernau * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22e3320f40Smarkfen * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <stdio.h> 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate #include <sys/stat.h> 317c478bd9Sstevel@tonic-gate #include <strings.h> 327c478bd9Sstevel@tonic-gate #include <stropts.h> 337c478bd9Sstevel@tonic-gate #include <fcntl.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <unistd.h> 367c478bd9Sstevel@tonic-gate #include <string.h> 377c478bd9Sstevel@tonic-gate #include <ctype.h> 387c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 397c478bd9Sstevel@tonic-gate #include <locale.h> 407c478bd9Sstevel@tonic-gate #include <syslog.h> 417c478bd9Sstevel@tonic-gate #include <pwd.h> 427c478bd9Sstevel@tonic-gate #include <sys/param.h> 437c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> /* MIN, MAX */ 447c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 457c478bd9Sstevel@tonic-gate #include <net/pfkeyv2.h> 467c478bd9Sstevel@tonic-gate #include <net/pfpolicy.h> 477c478bd9Sstevel@tonic-gate #include <inet/ipsec_impl.h> 487c478bd9Sstevel@tonic-gate #include <signal.h> 497c478bd9Sstevel@tonic-gate #include <errno.h> 507c478bd9Sstevel@tonic-gate #include <netdb.h> 517c478bd9Sstevel@tonic-gate #include <sys/socket.h> 527c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 537c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h> /* NSS_BUFLEN_HOSTS */ 547c478bd9Sstevel@tonic-gate #include <netinet/in.h> 557c478bd9Sstevel@tonic-gate #include <assert.h> 567c478bd9Sstevel@tonic-gate #include <inet/ip.h> 577c478bd9Sstevel@tonic-gate #include <ipsec_util.h> 587c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h> 597c478bd9Sstevel@tonic-gate #include <netinet/ip_icmp.h> 607c478bd9Sstevel@tonic-gate #include <netinet/icmp6.h> 617c478bd9Sstevel@tonic-gate 62e3320f40Smarkfen /* 63e3320f40Smarkfen * Globals 64e3320f40Smarkfen */ 65e3320f40Smarkfen int lfd; 66e3320f40Smarkfen char *my_fmri; 67e3320f40Smarkfen FILE *debugfile = stderr; 68e3320f40Smarkfen 69e3320f40Smarkfen #define USAGE() if (!smf_managed) usage() 707c478bd9Sstevel@tonic-gate /* 717c478bd9Sstevel@tonic-gate * Buffer length to read in pattern/properties. 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate #define MAXLEN 1024 747c478bd9Sstevel@tonic-gate 758810c16bSdanmcd /* Max length of tunnel interface string identifier */ 768810c16bSdanmcd #define TUNNAMEMAXLEN LIFNAMSIZ 778810c16bSdanmcd 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * Used by parse_one and parse/parse_action to communicate 807c478bd9Sstevel@tonic-gate * the errors. -1 is failure, which is not defined here. 817c478bd9Sstevel@tonic-gate */ 827c478bd9Sstevel@tonic-gate enum parse_errors {PARSE_SUCCESS, PARSE_EOF}; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * For spdsock_get_ext() diagnostics. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate #define SPDSOCK_DIAG_BUF_LEN 128 887c478bd9Sstevel@tonic-gate static char spdsock_diag_buf[SPDSOCK_DIAG_BUF_LEN]; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /* 917c478bd9Sstevel@tonic-gate * Define CURL here so that while you are reading 927c478bd9Sstevel@tonic-gate * this code, it does not affect "vi" in pattern 937c478bd9Sstevel@tonic-gate * matching. 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate #define CURL_BEGIN '{' 967c478bd9Sstevel@tonic-gate #define CURL_END '}' 97d5751483Smarkfen #define BACK_SLASH '\\' 987c478bd9Sstevel@tonic-gate #define MAXARGS 20 9943c889d3Smarkfen #define NOERROR 0 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * IPSEC_CONF_ADD should start with 1, so that when multiple commands 1037c478bd9Sstevel@tonic-gate * are given, we can fail the request. 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate 106eeda67c6Sjojemann enum ipsec_cmds {IPSEC_CONF_ADD = 1, IPSEC_CONF_DEL, IPSEC_CONF_VIEW, 1077c478bd9Sstevel@tonic-gate IPSEC_CONF_FLUSH, IPSEC_CONF_LIST, IPSEC_CONF_SUB}; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate static const char policy_conf_file[] = "/var/run/ipsecpolicy.conf"; 1107c478bd9Sstevel@tonic-gate static const char lock_file[] = "/var/run/ipsecconf.lock"; 1117c478bd9Sstevel@tonic-gate static const char index_tag[] = "#INDEX"; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate #define POLICY_CONF_FILE policy_conf_file 1147c478bd9Sstevel@tonic-gate #define LOCK_FILE lock_file 1157c478bd9Sstevel@tonic-gate #define INDEX_TAG index_tag 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate /* 1187c478bd9Sstevel@tonic-gate * Valid algorithm length. 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate #define VALID_ALG_LEN 40 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* Types of Error messages */ 123eeda67c6Sjojemann typedef enum error_type {BAD_ERROR, DUP_ERROR, REQ_ERROR} error_type_t; 1247c478bd9Sstevel@tonic-gate 1258810c16bSdanmcd /* Error message human readable conversions */ 1268810c16bSdanmcd static char *sys_error_message(int); 1278810c16bSdanmcd static void error_message(error_type_t, int, int); 128e3320f40Smarkfen static int get_pf_pol_socket(void); 1298810c16bSdanmcd 1307c478bd9Sstevel@tonic-gate static int cmd; 1317c478bd9Sstevel@tonic-gate static char *filename; 1327c478bd9Sstevel@tonic-gate static char lo_buf[MAXLEN]; /* Leftover buffer */ 1337c478bd9Sstevel@tonic-gate 1348810c16bSdanmcd /* 1358810c16bSdanmcd * The new SPD_EXT_TUN_NAME extension has a tunnel name in it. Use the empty 1368810c16bSdanmcd * string ("", stored in the char value "all_polheads") for all policy heads 1378810c16bSdanmcd * (global and all tunnels). Set interface_name to NULL for global-only, or 1388810c16bSdanmcd * specify a name of an IP-in-IP tunnel. 1398810c16bSdanmcd */ 1408810c16bSdanmcd static char *interface_name; 1418810c16bSdanmcd static char all_polheads; /* So we can easily get "". */ 1428810c16bSdanmcd 1437c478bd9Sstevel@tonic-gate /* Error reporting stuff */ 1447c478bd9Sstevel@tonic-gate #define CBUF_LEN 4096 /* Maximum size of the cmd */ 1457c478bd9Sstevel@tonic-gate /* 1467c478bd9Sstevel@tonic-gate * Following are used for reporting errors with arguments. 1477c478bd9Sstevel@tonic-gate * We store the line numbers of each argument as we parse them, 1487c478bd9Sstevel@tonic-gate * so that the error reporting is more specific. We can have only 149d5751483Smarkfen * (MAXARGS - 1) arguments between any pair of CURL_BEGIN CURL_END. 150d5751483Smarkfen * Because a single command can be made up of multiple action/property 151d5751483Smarkfen * combinations, the maximum command size is (2 * (MAXARGS -1)) for each 152d5751483Smarkfen * of patterns, properties and actions. 1537c478bd9Sstevel@tonic-gate */ 154d5751483Smarkfen #define ARG_BUF_LEN ((2 * 3 * (MAXARGS - 1)) + 1) 1557c478bd9Sstevel@tonic-gate static int arg_indices[ARG_BUF_LEN]; 1567c478bd9Sstevel@tonic-gate static int argindex; 1577c478bd9Sstevel@tonic-gate static int linecount; 1587c478bd9Sstevel@tonic-gate static char cbuf[CBUF_LEN]; /* Command buffer */ 1597c478bd9Sstevel@tonic-gate static int cbuf_offset; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate #define BYPASS_POLICY_BOOST 0x00800000 1637c478bd9Sstevel@tonic-gate #define ESP_POLICY_BOOST 0x00400000 1647c478bd9Sstevel@tonic-gate #define AH_POLICY_BOOST 0x00200000 1657c478bd9Sstevel@tonic-gate #define INITIAL_BASE_PRIORITY 0x000fffff 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * the number used to order the 1697c478bd9Sstevel@tonic-gate * rules starts at a certain base and 1707c478bd9Sstevel@tonic-gate * goes down. i.e. rules earlier in 1717c478bd9Sstevel@tonic-gate * the file are checked first 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate static uint32_t priority = INITIAL_BASE_PRIORITY; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate #define AH_AUTH 0 1767c478bd9Sstevel@tonic-gate #define ESP_ENCR 1 1777c478bd9Sstevel@tonic-gate #define ESP_AUTH 2 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * for deleting adds on error 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate typedef struct d_list_s 1857c478bd9Sstevel@tonic-gate { 1867c478bd9Sstevel@tonic-gate struct d_list_s *next; 1877c478bd9Sstevel@tonic-gate int index; 1887c478bd9Sstevel@tonic-gate } d_list_t; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate static d_list_t *d_list = NULL; 1917c478bd9Sstevel@tonic-gate static d_list_t *d_tail = NULL; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * Used for multi-homed source/dest hosts. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate static struct hostent *shp, *dhp; 1987c478bd9Sstevel@tonic-gate static unsigned int splen, dplen; 1998810c16bSdanmcd static char tunif[TUNNAMEMAXLEN]; 2007c478bd9Sstevel@tonic-gate static boolean_t has_saprefix, has_daprefix; 2017c478bd9Sstevel@tonic-gate static uint32_t seq_cnt = 0; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* lexxed out action and related properties */ 2047c478bd9Sstevel@tonic-gate typedef struct ap_s 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate char *act; 2077c478bd9Sstevel@tonic-gate char *prop[MAXARGS + 1]; 2087c478bd9Sstevel@tonic-gate } ap_t; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate /* one lexxed out rule */ 2127c478bd9Sstevel@tonic-gate typedef struct act_prop_s { 213d5751483Smarkfen char *pattern[MAXARGS + 1]; 2147c478bd9Sstevel@tonic-gate ap_t ap[MAXARGS + 1]; 2157c478bd9Sstevel@tonic-gate } act_prop_t; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate typedef struct 2187c478bd9Sstevel@tonic-gate { 2197c478bd9Sstevel@tonic-gate uint8_t alg_id; 2207c478bd9Sstevel@tonic-gate uint32_t alg_minbits; 2217c478bd9Sstevel@tonic-gate uint32_t alg_maxbits; 2227c478bd9Sstevel@tonic-gate } algreq_t; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* structure to hold all information for one act_prop_t */ 2257c478bd9Sstevel@tonic-gate typedef struct ips_act_props_s { 2267c478bd9Sstevel@tonic-gate struct ips_act_props_s *iap_next; 2277c478bd9Sstevel@tonic-gate struct ips_conf_s *iap_head; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate * IPsec action types (in SPD_ATTR_TYPE attribute) 2317c478bd9Sstevel@tonic-gate * SPD_ACTTYPE_DROP 0x0001 2327c478bd9Sstevel@tonic-gate * SPD_ACTTYPE_PASS 0x0002 2337c478bd9Sstevel@tonic-gate * SPD_ACTTYPE_IPSEC 0x0003 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate uint16_t iap_action; 2367c478bd9Sstevel@tonic-gate uint16_t iap_act_tok; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Action ATTR flags (in SPD_ATTR_FLAGS attribute) 2407c478bd9Sstevel@tonic-gate * SPD_APPLY_AH 0x0001 2417c478bd9Sstevel@tonic-gate * SPD_APPLY_ESP 0x0002 2427c478bd9Sstevel@tonic-gate * SPD_APPLY_SE 0x0004 * self-encapsulation * 2437c478bd9Sstevel@tonic-gate * SPD_APPLY_COMP 0x0008 * compression; NYI * 2447c478bd9Sstevel@tonic-gate * SPD_APPLY_UNIQUE 0x0010 * unique per-flow SA * 2457c478bd9Sstevel@tonic-gate * SPD_APPLY_BYPASS 0x0020 * bypass policy * 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate uint16_t iap_attr; 2487c478bd9Sstevel@tonic-gate uint16_t iap_attr_tok[5]; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate algreq_t iap_aauth; 2517c478bd9Sstevel@tonic-gate algreq_t iap_eencr; 2527c478bd9Sstevel@tonic-gate algreq_t iap_eauth; 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate uint32_t iap_life_soft_time; 2557c478bd9Sstevel@tonic-gate uint32_t iap_life_hard_time; 2567c478bd9Sstevel@tonic-gate uint32_t iap_life_soft_bytes; 2577c478bd9Sstevel@tonic-gate uint32_t iap_life_hard_bytes; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate } ips_act_props_t; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate #define V4_PART_OF_V6(v6) v6._S6_un._S6_u32[3] 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate typedef struct ips_conf_s { 2647c478bd9Sstevel@tonic-gate /* selector */ 2657c478bd9Sstevel@tonic-gate uint16_t patt_tok[8]; 2667c478bd9Sstevel@tonic-gate uint8_t has_saddr; 2677c478bd9Sstevel@tonic-gate uint8_t has_daddr; 2687c478bd9Sstevel@tonic-gate uint8_t has_smask; 2697c478bd9Sstevel@tonic-gate uint8_t has_dmask; 2707c478bd9Sstevel@tonic-gate uint8_t has_type; 2717c478bd9Sstevel@tonic-gate uint8_t has_code; 2728810c16bSdanmcd uint8_t has_negotiate; 2738810c16bSdanmcd uint8_t has_tunnel; 2747c478bd9Sstevel@tonic-gate uint16_t swap; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate struct in6_addr ips_src_addr_v6; 2777c478bd9Sstevel@tonic-gate struct in6_addr ips_src_mask_v6; 2787c478bd9Sstevel@tonic-gate struct in6_addr ips_dst_addr_v6; 2797c478bd9Sstevel@tonic-gate struct in6_addr ips_dst_mask_v6; 2807c478bd9Sstevel@tonic-gate uint8_t ips_src_mask_len; 2817c478bd9Sstevel@tonic-gate uint8_t ips_dst_mask_len; 2827c478bd9Sstevel@tonic-gate in_port_t ips_src_port_min; 2837c478bd9Sstevel@tonic-gate in_port_t ips_src_port_max; 2847c478bd9Sstevel@tonic-gate in_port_t ips_dst_port_min; 2857c478bd9Sstevel@tonic-gate in_port_t ips_dst_port_max; 2867c478bd9Sstevel@tonic-gate uint8_t ips_icmp_type; 2877c478bd9Sstevel@tonic-gate uint8_t ips_icmp_type_end; 2887c478bd9Sstevel@tonic-gate uint8_t ips_icmp_code; 2897c478bd9Sstevel@tonic-gate uint8_t ips_icmp_code_end; 2907c478bd9Sstevel@tonic-gate uint8_t ips_ulp_prot; 2917c478bd9Sstevel@tonic-gate uint8_t ips_ipsec_prot; 2927c478bd9Sstevel@tonic-gate uint8_t ips_isv4; 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * SPD_RULE_FLAG_INBOUND 0x0001 2957c478bd9Sstevel@tonic-gate * SPD_RULE_FLAG_OUTBOUND 0x0002 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate uint8_t ips_dir; 2988810c16bSdanmcd /* 2998810c16bSdanmcd * Keep track of tunnel separately due to explosion of ways to set 3008810c16bSdanmcd * inbound/outbound. 3018810c16bSdanmcd */ 3028810c16bSdanmcd boolean_t ips_tunnel; 3037c478bd9Sstevel@tonic-gate uint64_t ips_policy_index; 3047c478bd9Sstevel@tonic-gate uint32_t ips_act_cnt; 3057c478bd9Sstevel@tonic-gate ips_act_props_t *ips_acts; 3067c478bd9Sstevel@tonic-gate } ips_conf_t; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate #define ips_src_addr V4_PART_OF_V6(ips_src_addr_v6) 3097c478bd9Sstevel@tonic-gate #define ips_dst_addr V4_PART_OF_V6(ips_dst_addr_v6) 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate static int ipsecconf_nflag; /* Used only with -l option */ 3127c478bd9Sstevel@tonic-gate static int ipsecconf_qflag; /* Used only with -a|-r option */ 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate typedef struct str_val { 3157c478bd9Sstevel@tonic-gate const char *string; 3167c478bd9Sstevel@tonic-gate int value; 3177c478bd9Sstevel@tonic-gate } str_val_t; 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate typedef struct str_tval { 3207c478bd9Sstevel@tonic-gate const char *string; 3217c478bd9Sstevel@tonic-gate int tok_val; 3227c478bd9Sstevel@tonic-gate int value; 3237c478bd9Sstevel@tonic-gate } str_tval_t; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate static int parse_int(const char *); 3268810c16bSdanmcd static int parse_index(const char *, char *); 3278810c16bSdanmcd static int attach_tunname(spd_if_t *); 3287c478bd9Sstevel@tonic-gate static void usage(void); 3297c478bd9Sstevel@tonic-gate static int ipsec_conf_del(int, boolean_t); 330e3320f40Smarkfen static int ipsec_conf_add(boolean_t, boolean_t); 3317c478bd9Sstevel@tonic-gate static int ipsec_conf_sub(void); 3327c478bd9Sstevel@tonic-gate static int ipsec_conf_flush(int); 3337c478bd9Sstevel@tonic-gate static int ipsec_conf_view(void); 3347c478bd9Sstevel@tonic-gate static int ipsec_conf_list(void); 3357c478bd9Sstevel@tonic-gate static int lock(void); 3367c478bd9Sstevel@tonic-gate static int unlock(int); 3377c478bd9Sstevel@tonic-gate static int parse_one(FILE *, act_prop_t *); 3387c478bd9Sstevel@tonic-gate static void reconfigure(); 3397c478bd9Sstevel@tonic-gate static void in_prefixlentomask(unsigned int, uchar_t *); 3408810c16bSdanmcd static int in_getprefixlen(char *); 3417c478bd9Sstevel@tonic-gate static int parse_address(int, char *); 3427c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 3437c478bd9Sstevel@tonic-gate static void pfpol_msg_dump(spd_msg_t *msg, char *); 3447c478bd9Sstevel@tonic-gate #endif /* DEBUG_HEAVY */ 3457c478bd9Sstevel@tonic-gate static void print_pfpol_msg(spd_msg_t *); 3467c478bd9Sstevel@tonic-gate static int pfp_delete_rule(uint64_t); 3477c478bd9Sstevel@tonic-gate static void ipsec_conf_admin(uint8_t); 3487c478bd9Sstevel@tonic-gate static void print_bit_range(int, int); 3497c478bd9Sstevel@tonic-gate static void nuke_adds(); 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate #ifdef DEBUG 3527c478bd9Sstevel@tonic-gate static void dump_conf(ips_conf_t *); 3537c478bd9Sstevel@tonic-gate #endif 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate typedef struct 3567c478bd9Sstevel@tonic-gate { 3577c478bd9Sstevel@tonic-gate uint32_t id; 3587c478bd9Sstevel@tonic-gate uint32_t minkeybits; 3597c478bd9Sstevel@tonic-gate uint32_t maxkeybits; 3607c478bd9Sstevel@tonic-gate uint32_t defkeybits; 3617c478bd9Sstevel@tonic-gate uint32_t incr; 3627c478bd9Sstevel@tonic-gate } alginfo_t; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate static int ipsec_nalgs[3]; 3657c478bd9Sstevel@tonic-gate static alginfo_t known_algs[3][256]; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate #define IPS_SRC_MASK SPD_EXT_LCLADDR + 100 3687c478bd9Sstevel@tonic-gate #define IPS_DST_MASK SPD_EXT_REMADDR + 100 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate /* 3717c478bd9Sstevel@tonic-gate * if inbound, src=remote, dst=local 3727c478bd9Sstevel@tonic-gate * if outbound, src=local, dst=remote 3737c478bd9Sstevel@tonic-gate */ 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate #define TOK_saddr 1 3767c478bd9Sstevel@tonic-gate #define TOK_daddr 2 3777c478bd9Sstevel@tonic-gate #define TOK_sport 3 3787c478bd9Sstevel@tonic-gate #define TOK_dport 4 3797c478bd9Sstevel@tonic-gate #define TOK_smask 5 3807c478bd9Sstevel@tonic-gate #define TOK_dmask 6 3817c478bd9Sstevel@tonic-gate #define TOK_ulp 7 3827c478bd9Sstevel@tonic-gate #define TOK_local 8 3837c478bd9Sstevel@tonic-gate #define TOK_lport 9 3847c478bd9Sstevel@tonic-gate #define TOK_remote 10 3857c478bd9Sstevel@tonic-gate #define TOK_rport 11 3867c478bd9Sstevel@tonic-gate #define TOK_dir 12 3877c478bd9Sstevel@tonic-gate #define TOK_type 13 3887c478bd9Sstevel@tonic-gate #define TOK_code 14 3898810c16bSdanmcd #define TOK_negotiate 15 3908810c16bSdanmcd #define TOK_tunnel 16 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate #define IPS_SA SPD_ATTR_END 3937c478bd9Sstevel@tonic-gate #define IPS_DIR SPD_ATTR_EMPTY 3948810c16bSdanmcd #define IPS_NEG SPD_ATTR_NOP 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate static str_tval_t pattern_table[] = { 3987c478bd9Sstevel@tonic-gate {"saddr", TOK_saddr, SPD_EXT_LCLADDR}, 3997c478bd9Sstevel@tonic-gate {"src", TOK_saddr, SPD_EXT_LCLADDR}, 4007c478bd9Sstevel@tonic-gate {"srcaddr", TOK_saddr, SPD_EXT_LCLADDR}, 4017c478bd9Sstevel@tonic-gate {"daddr", TOK_daddr, SPD_EXT_REMADDR}, 4027c478bd9Sstevel@tonic-gate {"dst", TOK_daddr, SPD_EXT_REMADDR}, 4037c478bd9Sstevel@tonic-gate {"dstaddr", TOK_daddr, SPD_EXT_REMADDR}, 4047c478bd9Sstevel@tonic-gate {"sport", TOK_sport, SPD_EXT_LCLPORT}, 4057c478bd9Sstevel@tonic-gate {"dport", TOK_dport, SPD_EXT_REMPORT}, 4067c478bd9Sstevel@tonic-gate {"smask", TOK_smask, IPS_SRC_MASK}, 4077c478bd9Sstevel@tonic-gate {"dmask", TOK_dmask, IPS_DST_MASK}, 4087c478bd9Sstevel@tonic-gate {"ulp", TOK_ulp, SPD_EXT_PROTO}, 4097c478bd9Sstevel@tonic-gate {"proto", TOK_ulp, SPD_EXT_PROTO}, 4107c478bd9Sstevel@tonic-gate {"local", TOK_local, SPD_EXT_LCLADDR}, 4117c478bd9Sstevel@tonic-gate {"laddr", TOK_local, SPD_EXT_LCLADDR}, 4127c478bd9Sstevel@tonic-gate {"lport", TOK_lport, SPD_EXT_LCLPORT}, 4137c478bd9Sstevel@tonic-gate {"remote", TOK_remote, SPD_EXT_REMADDR}, 4147c478bd9Sstevel@tonic-gate {"raddr", TOK_remote, SPD_EXT_REMADDR}, 4157c478bd9Sstevel@tonic-gate {"rport", TOK_rport, SPD_EXT_REMPORT}, 4167c478bd9Sstevel@tonic-gate {"dir", TOK_dir, IPS_DIR}, 4177c478bd9Sstevel@tonic-gate {"type", TOK_type, SPD_EXT_ICMP_TYPECODE}, 4187c478bd9Sstevel@tonic-gate {"code", TOK_code, SPD_EXT_ICMP_TYPECODE}, 4198810c16bSdanmcd {"negotiate", TOK_negotiate, IPS_NEG}, 4208810c16bSdanmcd {"tunnel", TOK_tunnel, SPD_EXT_TUN_NAME}, 4217c478bd9Sstevel@tonic-gate {NULL, 0, 0}, 4227c478bd9Sstevel@tonic-gate }; 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate #define TOK_apply 1 4257c478bd9Sstevel@tonic-gate #define TOK_permit 2 4267c478bd9Sstevel@tonic-gate #define TOK_ipsec 3 4277c478bd9Sstevel@tonic-gate #define TOK_bypass 4 4287c478bd9Sstevel@tonic-gate #define TOK_drop 5 4297c478bd9Sstevel@tonic-gate #define TOK_or 6 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate static str_tval_t action_table[] = { 4327c478bd9Sstevel@tonic-gate {"apply", TOK_apply, SPD_ACTTYPE_IPSEC}, 4337c478bd9Sstevel@tonic-gate {"permit", TOK_permit, SPD_ACTTYPE_IPSEC}, 4347c478bd9Sstevel@tonic-gate {"ipsec", TOK_ipsec, SPD_ACTTYPE_IPSEC}, 4357c478bd9Sstevel@tonic-gate {"bypass", TOK_bypass, SPD_ACTTYPE_PASS}, 4367c478bd9Sstevel@tonic-gate {"pass", TOK_bypass, SPD_ACTTYPE_PASS}, 4377c478bd9Sstevel@tonic-gate {"drop", TOK_drop, SPD_ACTTYPE_DROP}, 4387c478bd9Sstevel@tonic-gate {"or", TOK_or, 0}, 4397c478bd9Sstevel@tonic-gate {NULL, 0, 0}, 4407c478bd9Sstevel@tonic-gate }; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate static str_val_t property_table[] = { 4437c478bd9Sstevel@tonic-gate {"auth_algs", SPD_ATTR_AH_AUTH}, 4447c478bd9Sstevel@tonic-gate {"encr_algs", SPD_ATTR_ESP_ENCR}, 4457c478bd9Sstevel@tonic-gate {"encr_auth_algs", SPD_ATTR_ESP_AUTH}, 4467c478bd9Sstevel@tonic-gate {"sa", IPS_SA}, 4477c478bd9Sstevel@tonic-gate {"dir", IPS_DIR}, 4487c478bd9Sstevel@tonic-gate {NULL, 0}, 4497c478bd9Sstevel@tonic-gate }; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate static str_val_t icmp_type_table[] = { 4527c478bd9Sstevel@tonic-gate {"unreach", ICMP_UNREACH}, 4537c478bd9Sstevel@tonic-gate {"echo", ICMP_ECHO}, 4547c478bd9Sstevel@tonic-gate {"echorep", ICMP_ECHOREPLY}, 4557c478bd9Sstevel@tonic-gate {"squench", ICMP_SOURCEQUENCH}, 4567c478bd9Sstevel@tonic-gate {"redir", ICMP_REDIRECT}, 4577c478bd9Sstevel@tonic-gate {"timex", ICMP_TIMXCEED}, 4587c478bd9Sstevel@tonic-gate {"paramprob", ICMP_PARAMPROB}, 4597c478bd9Sstevel@tonic-gate {"timest", ICMP_TSTAMP}, 4607c478bd9Sstevel@tonic-gate {"timestrep", ICMP_TSTAMPREPLY}, 4617c478bd9Sstevel@tonic-gate {"inforeq", ICMP_IREQ}, 4627c478bd9Sstevel@tonic-gate {"inforep", ICMP_IREQREPLY}, 4637c478bd9Sstevel@tonic-gate {"maskreq", ICMP_MASKREQ}, 4647c478bd9Sstevel@tonic-gate {"maskrep", ICMP_MASKREPLY}, 4657c478bd9Sstevel@tonic-gate {"unreach6", ICMP6_DST_UNREACH}, 4667c478bd9Sstevel@tonic-gate {"pkttoobig6", ICMP6_PACKET_TOO_BIG}, 4677c478bd9Sstevel@tonic-gate {"timex6", ICMP6_TIME_EXCEEDED}, 4687c478bd9Sstevel@tonic-gate {"paramprob6", ICMP6_PARAM_PROB}, 4697c478bd9Sstevel@tonic-gate {"echo6", ICMP6_ECHO_REQUEST}, 4707c478bd9Sstevel@tonic-gate {"echorep6", ICMP6_ECHO_REPLY}, 4717c478bd9Sstevel@tonic-gate {"router-sol6", ND_ROUTER_SOLICIT}, 4727c478bd9Sstevel@tonic-gate {"router-ad6", ND_ROUTER_ADVERT}, 4737c478bd9Sstevel@tonic-gate {"neigh-sol6", ND_NEIGHBOR_SOLICIT}, 4747c478bd9Sstevel@tonic-gate {"neigh-ad6", ND_NEIGHBOR_ADVERT}, 4757c478bd9Sstevel@tonic-gate {"redir6", ND_REDIRECT}, 4767c478bd9Sstevel@tonic-gate {NULL, 0}, 4777c478bd9Sstevel@tonic-gate }; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate static str_val_t icmp_code_table[] = { 4807c478bd9Sstevel@tonic-gate {"net-unr", ICMP_UNREACH_NET}, 4817c478bd9Sstevel@tonic-gate {"host-unr", ICMP_UNREACH_HOST}, 4827c478bd9Sstevel@tonic-gate {"proto-unr", ICMP_UNREACH_PROTOCOL}, 4837c478bd9Sstevel@tonic-gate {"port-unr", ICMP_UNREACH_PORT}, 4847c478bd9Sstevel@tonic-gate {"needfrag", ICMP_UNREACH_NEEDFRAG}, 4857c478bd9Sstevel@tonic-gate {"srcfail", ICMP_UNREACH_SRCFAIL}, 4867c478bd9Sstevel@tonic-gate {"net-unk", ICMP_UNREACH_NET_UNKNOWN}, 4877c478bd9Sstevel@tonic-gate {"host-unk", ICMP_UNREACH_HOST_UNKNOWN}, 4887c478bd9Sstevel@tonic-gate {"isolate", ICMP_UNREACH_ISOLATED}, 4897c478bd9Sstevel@tonic-gate {"net-prohib", ICMP_UNREACH_NET_PROHIB}, 4907c478bd9Sstevel@tonic-gate {"host-prohib", ICMP_UNREACH_HOST_PROHIB}, 4917c478bd9Sstevel@tonic-gate {"net-tos", ICMP_UNREACH_TOSNET}, 4927c478bd9Sstevel@tonic-gate {"host-tos", ICMP_UNREACH_TOSHOST}, 4937c478bd9Sstevel@tonic-gate {"filter-prohib", ICMP_UNREACH_FILTER_PROHIB}, 4947c478bd9Sstevel@tonic-gate {"host-preced", ICMP_UNREACH_HOST_PRECEDENCE}, 4957c478bd9Sstevel@tonic-gate {"cutoff-preced", ICMP_UNREACH_PRECEDENCE_CUTOFF}, 4967c478bd9Sstevel@tonic-gate {"no-route6", ICMP6_DST_UNREACH_NOROUTE}, 4977c478bd9Sstevel@tonic-gate {"adm-prohib6", ICMP6_DST_UNREACH_ADMIN}, 4987c478bd9Sstevel@tonic-gate {"addr-unr6", ICMP6_DST_UNREACH_ADDR}, 4997c478bd9Sstevel@tonic-gate {"port-unr6", ICMP6_DST_UNREACH_NOPORT}, 5007c478bd9Sstevel@tonic-gate {"hop-limex6", ICMP6_TIME_EXCEED_TRANSIT}, 5017c478bd9Sstevel@tonic-gate {"frag-re-timex6", ICMP6_TIME_EXCEED_REASSEMBLY}, 5027c478bd9Sstevel@tonic-gate {"err-head6", ICMP6_PARAMPROB_HEADER}, 5037c478bd9Sstevel@tonic-gate {"unrec-head6", ICMP6_PARAMPROB_NEXTHEADER}, 5047c478bd9Sstevel@tonic-gate {"unreq-opt6", ICMP6_PARAMPROB_OPTION}, 5057c478bd9Sstevel@tonic-gate {NULL, 0}, 5067c478bd9Sstevel@tonic-gate }; 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate static sigset_t set, oset; 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate static boolean_t 5127c478bd9Sstevel@tonic-gate add_index(int index) 5137c478bd9Sstevel@tonic-gate { 5147c478bd9Sstevel@tonic-gate d_list_t *temp = malloc(sizeof (d_list_t)); 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate if (temp == NULL) { 5177c478bd9Sstevel@tonic-gate warn("malloc"); 5187c478bd9Sstevel@tonic-gate return (B_TRUE); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate temp->index = index; 5227c478bd9Sstevel@tonic-gate temp->next = NULL; 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate if (d_tail == NULL) { 5257c478bd9Sstevel@tonic-gate d_list = d_tail = temp; 5267c478bd9Sstevel@tonic-gate return (B_FALSE); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate d_tail->next = temp; 5307c478bd9Sstevel@tonic-gate d_tail = temp; 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate return (B_FALSE); 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate static int 5367c478bd9Sstevel@tonic-gate block_all_signals() 5377c478bd9Sstevel@tonic-gate { 5387c478bd9Sstevel@tonic-gate if (sigfillset(&set) == -1) { 5397c478bd9Sstevel@tonic-gate warn("sigfillset"); 5407c478bd9Sstevel@tonic-gate return (-1); 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate if (sigprocmask(SIG_SETMASK, &set, &oset) == -1) { 5437c478bd9Sstevel@tonic-gate warn("sigprocmask"); 5447c478bd9Sstevel@tonic-gate return (-1); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate return (0); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate static int 5507c478bd9Sstevel@tonic-gate restore_all_signals() 5517c478bd9Sstevel@tonic-gate { 5527c478bd9Sstevel@tonic-gate if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) { 5537c478bd9Sstevel@tonic-gate warn("sigprocmask"); 5547c478bd9Sstevel@tonic-gate return (-1); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate return (0); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* allocate an ips_act_props_t and link it in correctly */ 5607c478bd9Sstevel@tonic-gate static ips_act_props_t * 5617c478bd9Sstevel@tonic-gate alloc_iap(ips_conf_t *parent) 5627c478bd9Sstevel@tonic-gate { 5637c478bd9Sstevel@tonic-gate ips_act_props_t *ret; 5647c478bd9Sstevel@tonic-gate ips_act_props_t *next = parent->ips_acts; 5657c478bd9Sstevel@tonic-gate ips_act_props_t *current = NULL; 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate ret = (ips_act_props_t *)calloc(sizeof (ips_act_props_t), 1); 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate if (ret == NULL) 5707c478bd9Sstevel@tonic-gate return (NULL); 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate ret->iap_head = parent; 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate while (next != NULL) { 5757c478bd9Sstevel@tonic-gate current = next; 5767c478bd9Sstevel@tonic-gate next = next->iap_next; 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate if (current != NULL) 5807c478bd9Sstevel@tonic-gate current->iap_next = ret; 5817c478bd9Sstevel@tonic-gate else 5827c478bd9Sstevel@tonic-gate parent->ips_acts = ret; 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate parent->ips_act_cnt++; 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate return (ret); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * This function exit()s if it fails. 5917c478bd9Sstevel@tonic-gate */ 5927c478bd9Sstevel@tonic-gate static void 5937c478bd9Sstevel@tonic-gate fetch_algorithms() 5947c478bd9Sstevel@tonic-gate { 5957c478bd9Sstevel@tonic-gate struct spd_msg msg; 5967c478bd9Sstevel@tonic-gate struct spd_ext_actions *actp; 5977c478bd9Sstevel@tonic-gate struct spd_attribute *attr, *endattr; 5987c478bd9Sstevel@tonic-gate spd_ext_t *exts[SPD_EXT_MAX+1]; 5997c478bd9Sstevel@tonic-gate uint64_t reply_buf[256]; 600e3320f40Smarkfen int sfd; 6017c478bd9Sstevel@tonic-gate int cnt, retval; 6027c478bd9Sstevel@tonic-gate uint64_t *start, *end; 6037c478bd9Sstevel@tonic-gate alginfo_t alg = {0, 0, 0, 0, 0}; 6047c478bd9Sstevel@tonic-gate uint_t algtype; 6057c478bd9Sstevel@tonic-gate static boolean_t has_run = B_FALSE; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate if (has_run) 6087c478bd9Sstevel@tonic-gate return; 6097c478bd9Sstevel@tonic-gate else 6107c478bd9Sstevel@tonic-gate has_run = B_TRUE; 6117c478bd9Sstevel@tonic-gate 612e3320f40Smarkfen sfd = get_pf_pol_socket(); 6137c478bd9Sstevel@tonic-gate if (sfd < 0) { 6147c478bd9Sstevel@tonic-gate err(-1, gettext("unable to open policy socket")); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate (void) memset(&msg, 0, sizeof (msg)); 6187c478bd9Sstevel@tonic-gate msg.spd_msg_version = PF_POLICY_V1; 6197c478bd9Sstevel@tonic-gate msg.spd_msg_type = SPD_ALGLIST; 6207c478bd9Sstevel@tonic-gate msg.spd_msg_len = SPD_8TO64(sizeof (msg)); 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate cnt = write(sfd, &msg, sizeof (msg)); 6237c478bd9Sstevel@tonic-gate if (cnt != sizeof (msg)) { 6247c478bd9Sstevel@tonic-gate if (cnt < 0) { 6257c478bd9Sstevel@tonic-gate err(-1, gettext("alglist failed: write")); 6267c478bd9Sstevel@tonic-gate } else { 6278810c16bSdanmcd errx(-1, gettext("alglist failed: short write")); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate cnt = read(sfd, reply_buf, sizeof (reply_buf)); 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate retval = spdsock_get_ext(exts, (spd_msg_t *)reply_buf, SPD_8TO64(cnt), 6347c478bd9Sstevel@tonic-gate spdsock_diag_buf, SPDSOCK_DIAG_BUF_LEN); 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate if (retval == KGE_LEN && exts[0]->spd_ext_len == 0) { 6377c478bd9Sstevel@tonic-gate /* 6387c478bd9Sstevel@tonic-gate * No algorithms are defined in the kernel, which caused 6397c478bd9Sstevel@tonic-gate * the extension length to be zero, and spdsock_get_ext() 6407c478bd9Sstevel@tonic-gate * to fail with a KGE_LEN error. This is not an error 6417c478bd9Sstevel@tonic-gate * condition, so we return nicely. 6427c478bd9Sstevel@tonic-gate */ 643*3abcb969Spwernau (void) close(sfd); 6447c478bd9Sstevel@tonic-gate return; 6457c478bd9Sstevel@tonic-gate } else if (retval != 0) { 6467c478bd9Sstevel@tonic-gate if (strlen(spdsock_diag_buf) != 0) 6477c478bd9Sstevel@tonic-gate warnx(spdsock_diag_buf); 6487c478bd9Sstevel@tonic-gate err(1, gettext("fetch_algorithms failed")); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate if (!exts[SPD_EXT_ACTION]) { 6527c478bd9Sstevel@tonic-gate errx(1, gettext("fetch_algorithms: action missing?!")); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate actp = (struct spd_ext_actions *)exts[SPD_EXT_ACTION]; 6567c478bd9Sstevel@tonic-gate start = (uint64_t *)actp; 6577c478bd9Sstevel@tonic-gate end = (start + actp->spd_actions_len); 6587c478bd9Sstevel@tonic-gate endattr = (struct spd_attribute *)end; 6597c478bd9Sstevel@tonic-gate attr = (struct spd_attribute *)&actp[1]; 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate algtype = 0; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate while (attr < endattr) { 6647c478bd9Sstevel@tonic-gate switch (attr->spd_attr_tag) { 6657c478bd9Sstevel@tonic-gate case SPD_ATTR_NOP: 6667c478bd9Sstevel@tonic-gate case SPD_ATTR_EMPTY: 6677c478bd9Sstevel@tonic-gate break; 6687c478bd9Sstevel@tonic-gate case SPD_ATTR_END: 6697c478bd9Sstevel@tonic-gate attr = endattr; 6707c478bd9Sstevel@tonic-gate /* FALLTHRU */ 6717c478bd9Sstevel@tonic-gate case SPD_ATTR_NEXT: 6727c478bd9Sstevel@tonic-gate known_algs[algtype][ipsec_nalgs[algtype]] = alg; 6737c478bd9Sstevel@tonic-gate ipsec_nalgs[algtype]++; 6747c478bd9Sstevel@tonic-gate break; 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate case SPD_ATTR_ENCR_MINBITS: 6777c478bd9Sstevel@tonic-gate case SPD_ATTR_AH_MINBITS: 6787c478bd9Sstevel@tonic-gate case SPD_ATTR_ESPA_MINBITS: 6797c478bd9Sstevel@tonic-gate alg.minkeybits = attr->spd_attr_value; 6807c478bd9Sstevel@tonic-gate break; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate case SPD_ATTR_ENCR_MAXBITS: 6837c478bd9Sstevel@tonic-gate case SPD_ATTR_AH_MAXBITS: 6847c478bd9Sstevel@tonic-gate case SPD_ATTR_ESPA_MAXBITS: 6857c478bd9Sstevel@tonic-gate alg.maxkeybits = attr->spd_attr_value; 6867c478bd9Sstevel@tonic-gate break; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate case SPD_ATTR_ENCR_DEFBITS: 6897c478bd9Sstevel@tonic-gate case SPD_ATTR_AH_DEFBITS: 6907c478bd9Sstevel@tonic-gate case SPD_ATTR_ESPA_DEFBITS: 6917c478bd9Sstevel@tonic-gate alg.defkeybits = attr->spd_attr_value; 6927c478bd9Sstevel@tonic-gate break; 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate case SPD_ATTR_ENCR_INCRBITS: 6957c478bd9Sstevel@tonic-gate case SPD_ATTR_AH_INCRBITS: 6967c478bd9Sstevel@tonic-gate case SPD_ATTR_ESPA_INCRBITS: 6977c478bd9Sstevel@tonic-gate alg.incr = attr->spd_attr_value; 6987c478bd9Sstevel@tonic-gate break; 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate case SPD_ATTR_AH_AUTH: 7017c478bd9Sstevel@tonic-gate case SPD_ATTR_ESP_AUTH: 7027c478bd9Sstevel@tonic-gate case SPD_ATTR_ESP_ENCR: 7037c478bd9Sstevel@tonic-gate alg.id = attr->spd_attr_value; 7047c478bd9Sstevel@tonic-gate algtype = attr->spd_attr_tag - SPD_ATTR_AH_AUTH; 7057c478bd9Sstevel@tonic-gate break; 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate attr++; 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate (void) close(sfd); 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate /* data dependant transform (act_cnt) */ 7147c478bd9Sstevel@tonic-gate #define ATTR(ap, tag, value) \ 7157c478bd9Sstevel@tonic-gate do { (ap)->spd_attr_tag = (tag); \ 7167c478bd9Sstevel@tonic-gate (ap)->spd_attr_value = (value); \ 7177c478bd9Sstevel@tonic-gate ap++; } while (0) 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate static struct spd_attribute * 7207c478bd9Sstevel@tonic-gate emit_alg(struct spd_attribute *ap, int type, const algreq_t *ar, 7217c478bd9Sstevel@tonic-gate int algattr, int minbitattr, int maxbitattr) 7227c478bd9Sstevel@tonic-gate { 7237c478bd9Sstevel@tonic-gate int id = ar->alg_id; 7247c478bd9Sstevel@tonic-gate int minbits, i; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate if (id != 0) { 7277c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 7287c478bd9Sstevel@tonic-gate ATTR(ap, algattr, ar->alg_id); 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate minbits = ar->alg_minbits; 7317c478bd9Sstevel@tonic-gate if (minbits == 0) { 7327c478bd9Sstevel@tonic-gate for (i = 0; i < ipsec_nalgs[type]; i++) { 7337c478bd9Sstevel@tonic-gate if (known_algs[type][i].id == id) 7347c478bd9Sstevel@tonic-gate break; 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate if (i < ipsec_nalgs[type]) 7377c478bd9Sstevel@tonic-gate minbits = known_algs[type][i].defkeybits; 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate if (minbits != 0) 7407c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 7417c478bd9Sstevel@tonic-gate ATTR(ap, minbitattr, minbits); 7427c478bd9Sstevel@tonic-gate if (ar->alg_maxbits != SPD_MAX_MAXBITS) 7437c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 7447c478bd9Sstevel@tonic-gate ATTR(ap, maxbitattr, ar->alg_maxbits); 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate return (ap); 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate static struct spd_attribute * 7537c478bd9Sstevel@tonic-gate ips_act_props_to_action(struct spd_attribute *ap, uint32_t *rule_priorityp, 7547c478bd9Sstevel@tonic-gate const ips_act_props_t *act_ptr) 7557c478bd9Sstevel@tonic-gate { 7567c478bd9Sstevel@tonic-gate uint32_t rule_priority = *rule_priorityp; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 7597c478bd9Sstevel@tonic-gate ATTR(ap, SPD_ATTR_EMPTY, 0); 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate /* type */ 7627c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 7637c478bd9Sstevel@tonic-gate ATTR(ap, SPD_ATTR_TYPE, act_ptr->iap_action); 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate if (act_ptr->iap_action == SPD_ACTTYPE_PASS) 7667c478bd9Sstevel@tonic-gate rule_priority |= BYPASS_POLICY_BOOST; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate /* flags */ 7697c478bd9Sstevel@tonic-gate if (act_ptr->iap_attr != 0) 7707c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 7717c478bd9Sstevel@tonic-gate ATTR(ap, SPD_ATTR_FLAGS, act_ptr->iap_attr); 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate /* esp */ 7747c478bd9Sstevel@tonic-gate if (act_ptr->iap_attr & SPD_APPLY_ESP) { 7757c478bd9Sstevel@tonic-gate rule_priority |= ESP_POLICY_BOOST; 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* encr */ 7787c478bd9Sstevel@tonic-gate ap = emit_alg(ap, ESP_ENCR, &act_ptr->iap_eencr, 7797c478bd9Sstevel@tonic-gate SPD_ATTR_ESP_ENCR, 7807c478bd9Sstevel@tonic-gate SPD_ATTR_ENCR_MINBITS, SPD_ATTR_ENCR_MAXBITS); 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate /* auth */ 7837c478bd9Sstevel@tonic-gate ap = emit_alg(ap, ESP_AUTH, &act_ptr->iap_eauth, 7847c478bd9Sstevel@tonic-gate SPD_ATTR_ESP_AUTH, 7857c478bd9Sstevel@tonic-gate SPD_ATTR_ESPA_MINBITS, SPD_ATTR_ESPA_MAXBITS); 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate /* ah */ 7897c478bd9Sstevel@tonic-gate if (act_ptr->iap_attr & SPD_APPLY_AH) { 7907c478bd9Sstevel@tonic-gate rule_priority |= AH_POLICY_BOOST; 7917c478bd9Sstevel@tonic-gate /* auth */ 7927c478bd9Sstevel@tonic-gate ap = emit_alg(ap, AH_AUTH, &act_ptr->iap_aauth, 7937c478bd9Sstevel@tonic-gate SPD_ATTR_AH_AUTH, 7947c478bd9Sstevel@tonic-gate SPD_ATTR_AH_MINBITS, SPD_ATTR_AH_MAXBITS); 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate /* lifetimes */ 7987c478bd9Sstevel@tonic-gate if (act_ptr->iap_life_soft_time != 0) 7997c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 8007c478bd9Sstevel@tonic-gate ATTR(ap, SPD_ATTR_LIFE_SOFT_TIME, act_ptr->iap_life_soft_time); 8017c478bd9Sstevel@tonic-gate if (act_ptr->iap_life_hard_time != 0) 8027c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 8037c478bd9Sstevel@tonic-gate ATTR(ap, SPD_ATTR_LIFE_HARD_TIME, act_ptr->iap_life_hard_time); 8047c478bd9Sstevel@tonic-gate if (act_ptr->iap_life_soft_bytes != 0) 8057c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 8067c478bd9Sstevel@tonic-gate ATTR(ap, SPD_ATTR_LIFE_SOFT_BYTES, 8077c478bd9Sstevel@tonic-gate act_ptr->iap_life_soft_bytes); 8087c478bd9Sstevel@tonic-gate if (act_ptr->iap_life_hard_bytes != 0) 8097c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 8107c478bd9Sstevel@tonic-gate ATTR(ap, SPD_ATTR_LIFE_HARD_BYTES, 8117c478bd9Sstevel@tonic-gate act_ptr->iap_life_hard_bytes); 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate /* LINTED E_CONST_COND */ 8147c478bd9Sstevel@tonic-gate ATTR(ap, SPD_ATTR_NEXT, 0); 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate *rule_priorityp = rule_priority; 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate return (ap); 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate static boolean_t 8227c478bd9Sstevel@tonic-gate alg_rangecheck(uint_t type, uint_t algid, const algreq_t *ar) 8237c478bd9Sstevel@tonic-gate { 8247c478bd9Sstevel@tonic-gate int i; 8257c478bd9Sstevel@tonic-gate uint_t minbits = ar->alg_minbits; 8267c478bd9Sstevel@tonic-gate uint_t maxbits = ar->alg_maxbits; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate for (i = 0; i < ipsec_nalgs[type]; i++) { 8297c478bd9Sstevel@tonic-gate if (known_algs[type][i].id == algid) 8307c478bd9Sstevel@tonic-gate break; 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate if (i >= ipsec_nalgs[type]) { 8347c478bd9Sstevel@tonic-gate /* 8357c478bd9Sstevel@tonic-gate * The kernel (where we populate known_algs from) doesn't 8367c478bd9Sstevel@tonic-gate * return the id's associated with NONE algorithms so we 8377c478bd9Sstevel@tonic-gate * test here if this was the reason the algorithm wasn't 8387c478bd9Sstevel@tonic-gate * found before wrongly failing. 8397c478bd9Sstevel@tonic-gate */ 8407c478bd9Sstevel@tonic-gate if (((type == ESP_ENCR) && (algid == SADB_EALG_NONE)) || 8417c478bd9Sstevel@tonic-gate ((type == ESP_AUTH) && (algid == SADB_AALG_NONE)) || 8427c478bd9Sstevel@tonic-gate ((type == AH_AUTH) && (algid == SADB_AALG_NONE))) { 8437c478bd9Sstevel@tonic-gate return (B_TRUE); 8447c478bd9Sstevel@tonic-gate } else { 8457c478bd9Sstevel@tonic-gate return (B_FALSE); /* not found */ 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate if ((minbits == 0) && (maxbits == 0)) 8507c478bd9Sstevel@tonic-gate return (B_TRUE); 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate minbits = MAX(minbits, known_algs[type][i].minkeybits); 8537c478bd9Sstevel@tonic-gate maxbits = MIN(maxbits, known_algs[type][i].maxkeybits); 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate /* we could also check key increments here.. */ 8567c478bd9Sstevel@tonic-gate return (minbits <= maxbits); /* non-null intersection */ 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate /* 8607c478bd9Sstevel@tonic-gate * Inspired by uts/common/inet/spd.c:ipsec_act_wildcard_expand() 8617c478bd9Sstevel@tonic-gate */ 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate static struct spd_attribute * 8647c478bd9Sstevel@tonic-gate ips_act_wild_props_to_action(struct spd_attribute *ap, 8657c478bd9Sstevel@tonic-gate uint32_t *rule_priorityp, uint16_t *act_cntp, 8667c478bd9Sstevel@tonic-gate const ips_act_props_t *act_ptr) 8677c478bd9Sstevel@tonic-gate { 8687c478bd9Sstevel@tonic-gate ips_act_props_t tact = *act_ptr; 8697c478bd9Sstevel@tonic-gate boolean_t use_ah, use_esp, use_espa; 8707c478bd9Sstevel@tonic-gate boolean_t wild_auth, wild_encr, wild_eauth; 8717c478bd9Sstevel@tonic-gate uint_t auth_alg, auth_idx, auth_min, auth_max; 8727c478bd9Sstevel@tonic-gate uint_t eauth_alg, eauth_idx, eauth_min, eauth_max; 8737c478bd9Sstevel@tonic-gate uint_t encr_alg, encr_idx, encr_min, encr_max; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate use_ah = !!(act_ptr->iap_attr & SPD_APPLY_AH); 8767c478bd9Sstevel@tonic-gate use_esp = !!(act_ptr->iap_attr & SPD_APPLY_ESP); 8777c478bd9Sstevel@tonic-gate use_espa = !!(act_ptr->iap_attr & SPD_APPLY_ESPA); 8787c478bd9Sstevel@tonic-gate auth_alg = act_ptr->iap_aauth.alg_id; 8797c478bd9Sstevel@tonic-gate eauth_alg = act_ptr->iap_eauth.alg_id; 8807c478bd9Sstevel@tonic-gate encr_alg = act_ptr->iap_eencr.alg_id; 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate wild_auth = use_ah && (auth_alg == SADB_AALG_NONE); 8837c478bd9Sstevel@tonic-gate wild_eauth = use_espa && (eauth_alg == SADB_AALG_NONE); 8847c478bd9Sstevel@tonic-gate wild_encr = use_esp && (encr_alg == SADB_EALG_NONE); 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate auth_min = auth_max = auth_alg; 8877c478bd9Sstevel@tonic-gate eauth_min = eauth_max = eauth_alg; 8887c478bd9Sstevel@tonic-gate encr_min = encr_max = encr_alg; 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate /* 8917c478bd9Sstevel@tonic-gate * set up for explosion.. for each dimension, expand output 8927c478bd9Sstevel@tonic-gate * size by the explosion factor. 8937c478bd9Sstevel@tonic-gate */ 8947c478bd9Sstevel@tonic-gate if (wild_auth) { 8957c478bd9Sstevel@tonic-gate auth_min = 0; 8967c478bd9Sstevel@tonic-gate auth_max = ipsec_nalgs[AH_AUTH] - 1; 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate if (wild_eauth) { 8997c478bd9Sstevel@tonic-gate eauth_min = 0; 9007c478bd9Sstevel@tonic-gate eauth_max = ipsec_nalgs[ESP_AUTH] - 1; 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate if (wild_encr) { 9037c478bd9Sstevel@tonic-gate encr_min = 0; 9047c478bd9Sstevel@tonic-gate encr_max = ipsec_nalgs[ESP_ENCR] - 1; 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate #define WHICH_ALG(type, wild, idx) ((wild)?(known_algs[type][idx].id):(idx)) 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate for (encr_idx = encr_min; encr_idx <= encr_max; encr_idx++) { 9107c478bd9Sstevel@tonic-gate encr_alg = WHICH_ALG(ESP_ENCR, wild_encr, encr_idx); 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate if (use_esp && 9137c478bd9Sstevel@tonic-gate !alg_rangecheck(ESP_ENCR, encr_alg, &act_ptr->iap_eencr)) 9147c478bd9Sstevel@tonic-gate continue; 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate for (auth_idx = auth_min; auth_idx <= auth_max; auth_idx++) { 9177c478bd9Sstevel@tonic-gate auth_alg = WHICH_ALG(AH_AUTH, wild_auth, auth_idx); 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate if (use_ah && 9207c478bd9Sstevel@tonic-gate !alg_rangecheck(AH_AUTH, auth_alg, 921d5751483Smarkfen &act_ptr->iap_aauth)) 9227c478bd9Sstevel@tonic-gate continue; 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate for (eauth_idx = eauth_min; eauth_idx <= eauth_max; 9267c478bd9Sstevel@tonic-gate eauth_idx++) { 9277c478bd9Sstevel@tonic-gate eauth_alg = WHICH_ALG(ESP_AUTH, wild_eauth, 9287c478bd9Sstevel@tonic-gate eauth_idx); 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate if (use_espa && 9317c478bd9Sstevel@tonic-gate !alg_rangecheck(ESP_AUTH, eauth_alg, 9327c478bd9Sstevel@tonic-gate &act_ptr->iap_eauth)) 9337c478bd9Sstevel@tonic-gate continue; 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate tact.iap_eencr.alg_id = encr_alg; 9367c478bd9Sstevel@tonic-gate tact.iap_eauth.alg_id = eauth_alg; 9377c478bd9Sstevel@tonic-gate tact.iap_aauth.alg_id = auth_alg; 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate (*act_cntp)++; 9407c478bd9Sstevel@tonic-gate ap = ips_act_props_to_action(ap, 9417c478bd9Sstevel@tonic-gate rule_priorityp, &tact); 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate #undef WHICH_ALG 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate return (ap); 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate /* huge, but not safe since no length checking is done */ 9527c478bd9Sstevel@tonic-gate #define MAX_POL_MSG_LEN 16384 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate /* 9567c478bd9Sstevel@tonic-gate * hand in some ips_conf_t's, get back an 9577c478bd9Sstevel@tonic-gate * iovec of pfpol messages. 9587c478bd9Sstevel@tonic-gate * this function converts the internal ips_conf_t into 9597c478bd9Sstevel@tonic-gate * a form that pf_pol can use. 9607c478bd9Sstevel@tonic-gate * return 0 on success, 1 on failure 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate static int 9637c478bd9Sstevel@tonic-gate ips_conf_to_pfpol_msg(int ipsec_cmd, ips_conf_t *inConf, int num_ips, 9647c478bd9Sstevel@tonic-gate struct iovec *msg) 9657c478bd9Sstevel@tonic-gate { 9667c478bd9Sstevel@tonic-gate int i; 9677c478bd9Sstevel@tonic-gate ips_conf_t *conf; 9687c478bd9Sstevel@tonic-gate uint64_t *scratch = NULL; 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate for (i = 0; i < num_ips; i++) { 9717c478bd9Sstevel@tonic-gate uint16_t *msg_len; 9727c478bd9Sstevel@tonic-gate uint16_t act_cnt = 0; 9737c478bd9Sstevel@tonic-gate uint64_t *next = NULL; 9747c478bd9Sstevel@tonic-gate spd_msg_t *spd_msg; 9757c478bd9Sstevel@tonic-gate spd_address_t *spd_address; 9767c478bd9Sstevel@tonic-gate struct spd_rule *spd_rule; 9777c478bd9Sstevel@tonic-gate struct spd_proto *spd_proto; 9787c478bd9Sstevel@tonic-gate struct spd_portrange *spd_portrange; 9797c478bd9Sstevel@tonic-gate struct spd_ext_actions *spd_ext_actions; 9807c478bd9Sstevel@tonic-gate struct spd_attribute *ap; 9817c478bd9Sstevel@tonic-gate struct spd_typecode *spd_typecode; 9828810c16bSdanmcd spd_if_t *spd_if; 9837c478bd9Sstevel@tonic-gate ips_act_props_t *act_ptr; 9847c478bd9Sstevel@tonic-gate uint32_t rule_priority = 0; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate scratch = calloc(1, MAX_POL_MSG_LEN); 9877c478bd9Sstevel@tonic-gate msg[i].iov_base = (char *)scratch; 9887c478bd9Sstevel@tonic-gate if (scratch == NULL) { 9897c478bd9Sstevel@tonic-gate warn(gettext("memory")); 9907c478bd9Sstevel@tonic-gate return (1); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate conf = &(inConf[i]); 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate spd_msg = (spd_msg_t *)scratch; 9957c478bd9Sstevel@tonic-gate next = (uint64_t *)&(spd_msg[1]); 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate msg_len = &(spd_msg->spd_msg_len); 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate spd_msg->spd_msg_version = PF_POLICY_V1; 10007c478bd9Sstevel@tonic-gate spd_msg->spd_msg_pid = getpid(); 10017c478bd9Sstevel@tonic-gate spd_msg->spd_msg_seq = ++seq_cnt; 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate switch (ipsec_cmd) { 10047c478bd9Sstevel@tonic-gate case SPD_ADDRULE: 10057c478bd9Sstevel@tonic-gate spd_msg->spd_msg_type = SPD_ADDRULE; 10067c478bd9Sstevel@tonic-gate break; 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate default: 10097c478bd9Sstevel@tonic-gate warnx("%s %d", gettext("bad command:"), ipsec_cmd); 10107c478bd9Sstevel@tonic-gate spd_msg->spd_msg_type = SPD_ADDRULE; 10117c478bd9Sstevel@tonic-gate break; 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate /* 10157c478bd9Sstevel@tonic-gate * SELECTOR 10167c478bd9Sstevel@tonic-gate */ 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate spd_msg->spd_msg_spdid = SPD_STANDBY; 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* rule */ 10217c478bd9Sstevel@tonic-gate spd_rule = (struct spd_rule *)next; 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate spd_rule->spd_rule_len = SPD_8TO64(sizeof (struct spd_rule)); 10247c478bd9Sstevel@tonic-gate spd_rule->spd_rule_type = SPD_EXT_RULE; 10257c478bd9Sstevel@tonic-gate spd_rule->spd_rule_flags = conf->ips_dir; 10268810c16bSdanmcd if (conf->ips_tunnel) 10278810c16bSdanmcd spd_rule->spd_rule_flags |= SPD_RULE_FLAG_TUNNEL; 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate next = (uint64_t *)&(spd_rule[1]); 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate /* proto */ 10327c478bd9Sstevel@tonic-gate if (conf->ips_ulp_prot != 0) { 10337c478bd9Sstevel@tonic-gate spd_proto = (struct spd_proto *)next; 10347c478bd9Sstevel@tonic-gate spd_proto->spd_proto_len = 1035d5751483Smarkfen SPD_8TO64(sizeof (struct spd_proto)); 10367c478bd9Sstevel@tonic-gate spd_proto->spd_proto_exttype = SPD_EXT_PROTO; 10377c478bd9Sstevel@tonic-gate spd_proto->spd_proto_number = conf->ips_ulp_prot; 10387c478bd9Sstevel@tonic-gate next = (uint64_t *)&(spd_proto[1]); 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate 10418810c16bSdanmcd /* tunnel */ 10428810c16bSdanmcd if (conf->has_tunnel != 0) { 10438810c16bSdanmcd spd_if = (spd_if_t *)next; 10448810c16bSdanmcd spd_if->spd_if_len = 10458810c16bSdanmcd SPD_8TO64(P2ROUNDUP(strlen(tunif) + 1, 8) + 10468810c16bSdanmcd sizeof (spd_if_t)); 10478810c16bSdanmcd spd_if->spd_if_exttype = SPD_EXT_TUN_NAME; 10488810c16bSdanmcd (void) strlcpy((char *)spd_if->spd_if_name, tunif, 1049d5751483Smarkfen TUNNAMEMAXLEN); 10508810c16bSdanmcd next = (uint64_t *)(spd_if) + spd_if->spd_if_len; 10518810c16bSdanmcd } 10528810c16bSdanmcd 10537c478bd9Sstevel@tonic-gate /* icmp type/code */ 10547c478bd9Sstevel@tonic-gate if (conf->ips_ulp_prot == IPPROTO_ICMP || 10557c478bd9Sstevel@tonic-gate conf->ips_ulp_prot == IPPROTO_ICMPV6) { 10567c478bd9Sstevel@tonic-gate if (conf->has_type) { 10577c478bd9Sstevel@tonic-gate spd_typecode = (struct spd_typecode *)next; 10587c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_len = 10597c478bd9Sstevel@tonic-gate SPD_8TO64(sizeof (struct spd_typecode)); 10607c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_exttype = 10617c478bd9Sstevel@tonic-gate SPD_EXT_ICMP_TYPECODE; 10627c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_type = 10637c478bd9Sstevel@tonic-gate conf->ips_icmp_type; 10647c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_type_end = 10657c478bd9Sstevel@tonic-gate conf->ips_icmp_type_end; 10667c478bd9Sstevel@tonic-gate if (conf->has_code) { 10677c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_code = 10687c478bd9Sstevel@tonic-gate conf->ips_icmp_code; 10697c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_code_end = 10707c478bd9Sstevel@tonic-gate conf->ips_icmp_code_end; 10717c478bd9Sstevel@tonic-gate } else { 10727c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_code = 255; 10737c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_code_end 10747c478bd9Sstevel@tonic-gate = 255; 10757c478bd9Sstevel@tonic-gate } 10767c478bd9Sstevel@tonic-gate next = (uint64_t *)&(spd_typecode[1]); 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate /* src port */ 10817c478bd9Sstevel@tonic-gate if (conf->ips_src_port_min != 0 || 10827c478bd9Sstevel@tonic-gate conf->ips_src_port_max != 0) { 10837c478bd9Sstevel@tonic-gate spd_portrange = (struct spd_portrange *)next; 10847c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_len = 1085d5751483Smarkfen SPD_8TO64(sizeof (struct spd_portrange)); 10867c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_exttype = 1087d5751483Smarkfen (conf->swap)?SPD_EXT_REMPORT:SPD_EXT_LCLPORT; 10887c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_minport = 1089d5751483Smarkfen conf->ips_src_port_min; 10907c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_maxport = 1091d5751483Smarkfen conf->ips_src_port_max; 10927c478bd9Sstevel@tonic-gate next = (uint64_t *)&(spd_portrange[1]); 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate /* dst port */ 10957c478bd9Sstevel@tonic-gate if (conf->ips_dst_port_min != 0 || 10967c478bd9Sstevel@tonic-gate conf->ips_dst_port_max != 0) { 10977c478bd9Sstevel@tonic-gate spd_portrange = (struct spd_portrange *)next; 10987c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_len = 1099d5751483Smarkfen SPD_8TO64(sizeof (struct spd_portrange)); 11007c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_exttype = 1101d5751483Smarkfen (conf->swap)?SPD_EXT_LCLPORT:SPD_EXT_REMPORT; 11027c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_minport = 1103d5751483Smarkfen conf->ips_dst_port_min; 11047c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_maxport = 1105d5751483Smarkfen conf->ips_dst_port_max; 11067c478bd9Sstevel@tonic-gate next = (uint64_t *)&(spd_portrange[1]); 11077c478bd9Sstevel@tonic-gate } 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate /* saddr */ 11107c478bd9Sstevel@tonic-gate if (conf->has_saddr) { 11117c478bd9Sstevel@tonic-gate spd_address = (spd_address_t *)next; 11127c478bd9Sstevel@tonic-gate next = (uint64_t *)(spd_address + 1); 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate spd_address->spd_address_exttype = 1115d5751483Smarkfen (conf->swap)?SPD_EXT_REMADDR:SPD_EXT_LCLADDR; 11167c478bd9Sstevel@tonic-gate spd_address->spd_address_prefixlen = 1117d5751483Smarkfen conf->ips_src_mask_len; 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate if (conf->ips_isv4) { 11207c478bd9Sstevel@tonic-gate spd_address->spd_address_af = AF_INET; 11217c478bd9Sstevel@tonic-gate (void) memcpy(next, &(conf->ips_src_addr), 1122d5751483Smarkfen sizeof (ipaddr_t)); 11237c478bd9Sstevel@tonic-gate spd_address->spd_address_len = 2; 11247c478bd9Sstevel@tonic-gate next += SPD_8TO64(sizeof (ipaddr_t) + 4); 11257c478bd9Sstevel@tonic-gate if (!conf->has_smask) 11267c478bd9Sstevel@tonic-gate spd_address->spd_address_prefixlen = 32; 11277c478bd9Sstevel@tonic-gate } else { 11287c478bd9Sstevel@tonic-gate spd_address->spd_address_af = AF_INET6; 11297c478bd9Sstevel@tonic-gate (void) memcpy(next, &(conf->ips_src_addr_v6), 11307c478bd9Sstevel@tonic-gate sizeof (in6_addr_t)); 11317c478bd9Sstevel@tonic-gate spd_address->spd_address_len = 3; 11327c478bd9Sstevel@tonic-gate next += SPD_8TO64(sizeof (in6_addr_t)); 11337c478bd9Sstevel@tonic-gate if (!conf->has_smask) 11347c478bd9Sstevel@tonic-gate spd_address->spd_address_prefixlen 1135d5751483Smarkfen = 128; 11367c478bd9Sstevel@tonic-gate } 11377c478bd9Sstevel@tonic-gate } 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate /* daddr */ 11407c478bd9Sstevel@tonic-gate if (conf->has_daddr) { 11417c478bd9Sstevel@tonic-gate spd_address = (spd_address_t *)next; 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate next = (uint64_t *)(spd_address + 1); 11447c478bd9Sstevel@tonic-gate 11457c478bd9Sstevel@tonic-gate spd_address->spd_address_exttype = 1146d5751483Smarkfen (conf->swap)?SPD_EXT_LCLADDR:SPD_EXT_REMADDR; 11477c478bd9Sstevel@tonic-gate spd_address->spd_address_prefixlen = 1148d5751483Smarkfen conf->ips_dst_mask_len; 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate if (conf->ips_isv4) { 11517c478bd9Sstevel@tonic-gate spd_address->spd_address_af = AF_INET; 11527c478bd9Sstevel@tonic-gate (void) memcpy(next, &conf->ips_dst_addr, 11537c478bd9Sstevel@tonic-gate sizeof (ipaddr_t)); 11547c478bd9Sstevel@tonic-gate spd_address->spd_address_len = 2; 11557c478bd9Sstevel@tonic-gate /* "+ 4" below is for padding. */ 11567c478bd9Sstevel@tonic-gate next += SPD_8TO64(sizeof (ipaddr_t) + 4); 11577c478bd9Sstevel@tonic-gate if (!conf->has_dmask) 11587c478bd9Sstevel@tonic-gate spd_address->spd_address_prefixlen = 32; 11597c478bd9Sstevel@tonic-gate } else { 11607c478bd9Sstevel@tonic-gate spd_address->spd_address_af = AF_INET6; 11617c478bd9Sstevel@tonic-gate (void) memcpy(next, &(conf->ips_dst_addr_v6), 11627c478bd9Sstevel@tonic-gate sizeof (in6_addr_t)); 11637c478bd9Sstevel@tonic-gate spd_address->spd_address_len = 3; 11647c478bd9Sstevel@tonic-gate next += SPD_8TO64(sizeof (in6_addr_t)); 11657c478bd9Sstevel@tonic-gate if (!conf->has_dmask) 11667c478bd9Sstevel@tonic-gate spd_address->spd_address_prefixlen 1167d5751483Smarkfen = 128; 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate /* actions */ 11727c478bd9Sstevel@tonic-gate spd_ext_actions = (struct spd_ext_actions *)next; 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate spd_ext_actions->spd_actions_exttype = SPD_EXT_ACTION; 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate act_ptr = conf->ips_acts; 11777c478bd9Sstevel@tonic-gate ap = (struct spd_attribute *)(&spd_ext_actions[1]); 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate rule_priority = priority--; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate for (act_ptr = conf->ips_acts; act_ptr != NULL; 11827c478bd9Sstevel@tonic-gate act_ptr = act_ptr->iap_next) { 11837c478bd9Sstevel@tonic-gate ap = ips_act_wild_props_to_action(ap, &rule_priority, 11847c478bd9Sstevel@tonic-gate &act_cnt, act_ptr); 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate ap[-1].spd_attr_tag = SPD_ATTR_END; 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate next = (uint64_t *)ap; 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate spd_rule->spd_rule_priority = rule_priority; 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate msg[i].iov_len = (uintptr_t)next - (uintptr_t)msg[i].iov_base; 11937c478bd9Sstevel@tonic-gate *msg_len = (uint16_t)SPD_8TO64(msg[i].iov_len); 11947c478bd9Sstevel@tonic-gate spd_ext_actions->spd_actions_count = act_cnt; 11957c478bd9Sstevel@tonic-gate spd_ext_actions->spd_actions_len = 11967c478bd9Sstevel@tonic-gate SPD_8TO64((uintptr_t)next - (uintptr_t)spd_ext_actions); 11977c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 11987c478bd9Sstevel@tonic-gate printf("pfpol msg len in uint64_t's = %d\n", *msg_len); 11997c478bd9Sstevel@tonic-gate printf("pfpol test_len in bytes = %d\n", msg[i].iov_len); 12007c478bd9Sstevel@tonic-gate pfpol_msg_dump((spd_msg_t *)scratch, 12017c478bd9Sstevel@tonic-gate "ips_conf_to_pfpol_msg"); 12027c478bd9Sstevel@tonic-gate #endif 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate #undef ATTR 12067c478bd9Sstevel@tonic-gate return (0); 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate static int 12107c478bd9Sstevel@tonic-gate get_pf_pol_socket(void) 12117c478bd9Sstevel@tonic-gate { 12127c478bd9Sstevel@tonic-gate int s = socket(PF_POLICY, SOCK_RAW, PF_POLICY_V1); 12137c478bd9Sstevel@tonic-gate if (s < 0) { 1214e3320f40Smarkfen if (errno == EPERM) { 1215e3320f40Smarkfen EXIT_BADPERM("Insufficient privileges to open " 1216e3320f40Smarkfen "PF_POLICY socket."); 1217e3320f40Smarkfen } else { 1218e3320f40Smarkfen warn(gettext("(loading pf_policy) socket:")); 1219e3320f40Smarkfen } 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate return (s); 12237c478bd9Sstevel@tonic-gate } 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate 12267c478bd9Sstevel@tonic-gate static int 12278810c16bSdanmcd send_pf_pol_message(int ipsec_cmd, ips_conf_t *conf, int *diag) 12287c478bd9Sstevel@tonic-gate { 12297c478bd9Sstevel@tonic-gate int retval; 12307c478bd9Sstevel@tonic-gate int cnt; 12317c478bd9Sstevel@tonic-gate int total_len; 12327c478bd9Sstevel@tonic-gate struct iovec polmsg; 12337c478bd9Sstevel@tonic-gate spd_msg_t *return_buf; 12347c478bd9Sstevel@tonic-gate spd_ext_t *exts[SPD_EXT_MAX+1]; 12357c478bd9Sstevel@tonic-gate int fd = get_pf_pol_socket(); 12367c478bd9Sstevel@tonic-gate 12378810c16bSdanmcd *diag = 0; 12388810c16bSdanmcd 12397c478bd9Sstevel@tonic-gate if (fd < 0) 124043c889d3Smarkfen return (EBADF); 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate retval = ips_conf_to_pfpol_msg(ipsec_cmd, conf, 1, &polmsg); 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate if (retval) { 12457c478bd9Sstevel@tonic-gate (void) close(fd); 124643c889d3Smarkfen return (ENOMEM); 12477c478bd9Sstevel@tonic-gate } 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate total_len = polmsg.iov_len; 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate cnt = writev(fd, &polmsg, 1); 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 12547c478bd9Sstevel@tonic-gate (void) printf("cnt = %d\n", cnt); 12557c478bd9Sstevel@tonic-gate #endif 12567c478bd9Sstevel@tonic-gate if (cnt < 0) { 12577c478bd9Sstevel@tonic-gate warn(gettext("pf_pol write")); 12587c478bd9Sstevel@tonic-gate } else { 12597c478bd9Sstevel@tonic-gate return_buf = (spd_msg_t *)calloc(total_len, 1); 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate if (return_buf == NULL) { 12627c478bd9Sstevel@tonic-gate warn(gettext("memory")); 12637c478bd9Sstevel@tonic-gate } else { 12647c478bd9Sstevel@tonic-gate cnt = read(fd, (void*)return_buf, total_len); 12657c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 12667c478bd9Sstevel@tonic-gate (void) printf("pf_pol read: cnt = %d(%d)\n", cnt, 12677c478bd9Sstevel@tonic-gate total_len); 12687c478bd9Sstevel@tonic-gate #endif 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate if (cnt > 8 && return_buf->spd_msg_errno) { 12718810c16bSdanmcd *diag = return_buf->spd_msg_diagnostic; 127243c889d3Smarkfen if (!ipsecconf_qflag) { 127343c889d3Smarkfen warnx("%s: %s", 12748810c16bSdanmcd gettext("Kernel returned"), 12758810c16bSdanmcd sys_error_message( 127643c889d3Smarkfen return_buf->spd_msg_errno)); 127743c889d3Smarkfen } 12788810c16bSdanmcd if (*diag != 0) 12798810c16bSdanmcd (void) printf(gettext( 12808810c16bSdanmcd "\t(spdsock diagnostic: %s)\n"), 12818810c16bSdanmcd spdsock_diag(*diag)); 12827c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 12837c478bd9Sstevel@tonic-gate pfpol_msg_dump((spd_msg_t *)polmsg.iov_base, 12847c478bd9Sstevel@tonic-gate "message in"); 12857c478bd9Sstevel@tonic-gate pfpol_msg_dump(return_buf, 12867c478bd9Sstevel@tonic-gate "send_pf_pol_message"); 12877c478bd9Sstevel@tonic-gate #endif 128843c889d3Smarkfen retval = return_buf->spd_msg_errno; 12897c478bd9Sstevel@tonic-gate free(return_buf); 12907c478bd9Sstevel@tonic-gate free(polmsg.iov_base); 12917c478bd9Sstevel@tonic-gate (void) close(fd); 129243c889d3Smarkfen return (retval); 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate retval = spdsock_get_ext(exts, return_buf, 12967c478bd9Sstevel@tonic-gate return_buf->spd_msg_len, NULL, 0); 12977c478bd9Sstevel@tonic-gate /* ignore retval */ 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_RULE]) { 13007c478bd9Sstevel@tonic-gate conf->ips_policy_index = 13017c478bd9Sstevel@tonic-gate ((struct spd_rule *) 1302d5751483Smarkfen exts[SPD_EXT_RULE])->spd_rule_index; 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate if (add_index(conf->ips_policy_index)) { 13057c478bd9Sstevel@tonic-gate free(return_buf); 13067c478bd9Sstevel@tonic-gate free(polmsg.iov_base); 13077c478bd9Sstevel@tonic-gate (void) close(fd); 130843c889d3Smarkfen return (ENOMEM); 13097c478bd9Sstevel@tonic-gate } 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate free(return_buf); 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate } 13157c478bd9Sstevel@tonic-gate 13167c478bd9Sstevel@tonic-gate free(polmsg.iov_base); 13177c478bd9Sstevel@tonic-gate (void) close(fd); 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate return (0); 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate } 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate int 13247c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 13257c478bd9Sstevel@tonic-gate { 13267c478bd9Sstevel@tonic-gate int ret, flushret; 13277c478bd9Sstevel@tonic-gate int c; 13287c478bd9Sstevel@tonic-gate int index; 1329e3320f40Smarkfen boolean_t smf_managed; 1330e3320f40Smarkfen boolean_t just_check = B_FALSE; 1331e3320f40Smarkfen 1332e3320f40Smarkfen char *smf_warning = gettext( 1333d5751483Smarkfen "\n\tIPsec policy should be managed using smf(5). Modifying\n" 1334d5751483Smarkfen "\tthe IPsec policy from the command line while the 'policy'\n" 1335d5751483Smarkfen "\tservice is enabled could result in an inconsistent\n" 1336d5751483Smarkfen "\tsecurity policy.\n\n"); 1337e3320f40Smarkfen 1338e3320f40Smarkfen flushret = 0; 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 13417c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 13427c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 13437c478bd9Sstevel@tonic-gate #endif 13447c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate openlog("ipsecconf", LOG_CONS, LOG_AUTH); 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate /* 13497c478bd9Sstevel@tonic-gate * We don't immediately check for privilege here. This is done by IP 13507c478bd9Sstevel@tonic-gate * when we open /dev/ip below. 13517c478bd9Sstevel@tonic-gate */ 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate if (argc == 1) { 13547c478bd9Sstevel@tonic-gate cmd = IPSEC_CONF_VIEW; 13557c478bd9Sstevel@tonic-gate goto done; 13567c478bd9Sstevel@tonic-gate } 1357e3320f40Smarkfen my_fmri = getenv("SMF_FMRI"); 1358e3320f40Smarkfen if (my_fmri == NULL) 1359e3320f40Smarkfen smf_managed = B_FALSE; 1360e3320f40Smarkfen else 1361e3320f40Smarkfen smf_managed = B_TRUE; 1362e3320f40Smarkfen 1363e3320f40Smarkfen while ((c = getopt(argc, argv, "nlfLFa:qd:r:i:c:")) != EOF) { 13647c478bd9Sstevel@tonic-gate switch (c) { 13658810c16bSdanmcd case 'F': 13668810c16bSdanmcd if (interface_name != NULL) { 1367e3320f40Smarkfen USAGE(); 1368e3320f40Smarkfen EXIT_FATAL("interface name not required."); 13698810c16bSdanmcd } 13708810c16bSdanmcd /* Apply to all policy heads - global and tunnels. */ 13718810c16bSdanmcd interface_name = &all_polheads; 13728810c16bSdanmcd /* FALLTHRU */ 13737c478bd9Sstevel@tonic-gate case 'f': 13747c478bd9Sstevel@tonic-gate /* Only one command at a time */ 13757c478bd9Sstevel@tonic-gate if (cmd != 0) { 1376e3320f40Smarkfen USAGE(); 1377e3320f40Smarkfen EXIT_FATAL("Multiple commands specified"); 13787c478bd9Sstevel@tonic-gate } 13797c478bd9Sstevel@tonic-gate cmd = IPSEC_CONF_FLUSH; 13807c478bd9Sstevel@tonic-gate break; 13818810c16bSdanmcd case 'L': 13828810c16bSdanmcd if (interface_name != NULL) { 1383e3320f40Smarkfen USAGE(); 1384e3320f40Smarkfen EXIT_FATAL("interface name not required."); 13858810c16bSdanmcd } 13868810c16bSdanmcd /* Apply to all policy heads - global and tunnels. */ 13878810c16bSdanmcd interface_name = &all_polheads; 13888810c16bSdanmcd /* FALLTHRU */ 13897c478bd9Sstevel@tonic-gate case 'l': 13907c478bd9Sstevel@tonic-gate /* Only one command at a time */ 13917c478bd9Sstevel@tonic-gate if (cmd != 0) { 1392e3320f40Smarkfen USAGE(); 1393e3320f40Smarkfen EXIT_FATAL("Multiple commands specified"); 13947c478bd9Sstevel@tonic-gate } 13957c478bd9Sstevel@tonic-gate cmd = IPSEC_CONF_LIST; 13967c478bd9Sstevel@tonic-gate break; 1397e3320f40Smarkfen case 'c': 1398e3320f40Smarkfen just_check = B_TRUE; 1399e3320f40Smarkfen ipsecconf_qflag++; 1400e3320f40Smarkfen /* FALLTHRU */ 14017c478bd9Sstevel@tonic-gate case 'a': 14028810c16bSdanmcd /* Only one command at a time, and no interface name */ 14038810c16bSdanmcd if (cmd != 0 || interface_name != NULL) { 1404e3320f40Smarkfen USAGE(); 1405e3320f40Smarkfen EXIT_FATAL("Multiple commands or interface " 1406e3320f40Smarkfen "not required."); 14077c478bd9Sstevel@tonic-gate } 14087c478bd9Sstevel@tonic-gate cmd = IPSEC_CONF_ADD; 14097c478bd9Sstevel@tonic-gate filename = optarg; 14107c478bd9Sstevel@tonic-gate break; 14117c478bd9Sstevel@tonic-gate case 'd': 14128810c16bSdanmcd /* 14138810c16bSdanmcd * Only one command at a time. Interface name is 14148810c16bSdanmcd * optional. 14158810c16bSdanmcd */ 14167c478bd9Sstevel@tonic-gate if (cmd != 0) { 1417e3320f40Smarkfen USAGE(); 1418e3320f40Smarkfen EXIT_FATAL("Multiple commands specified"); 14197c478bd9Sstevel@tonic-gate } 14207c478bd9Sstevel@tonic-gate cmd = IPSEC_CONF_DEL; 14218810c16bSdanmcd index = parse_index(optarg, NULL); 14227c478bd9Sstevel@tonic-gate break; 14237c478bd9Sstevel@tonic-gate case 'n' : 14247c478bd9Sstevel@tonic-gate ipsecconf_nflag++; 14257c478bd9Sstevel@tonic-gate break; 14267c478bd9Sstevel@tonic-gate case 'q' : 14277c478bd9Sstevel@tonic-gate ipsecconf_qflag++; 14287c478bd9Sstevel@tonic-gate break; 14297c478bd9Sstevel@tonic-gate case 'r' : 14308810c16bSdanmcd /* Only one command at a time, and no interface name */ 14318810c16bSdanmcd if (cmd != 0 || interface_name != NULL) { 1432e3320f40Smarkfen USAGE(); 1433e3320f40Smarkfen EXIT_FATAL("Multiple commands or interface " 1434e3320f40Smarkfen "not required."); 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate cmd = IPSEC_CONF_SUB; 14377c478bd9Sstevel@tonic-gate filename = optarg; 14387c478bd9Sstevel@tonic-gate break; 14398810c16bSdanmcd case 'i': 14408810c16bSdanmcd if (interface_name != NULL) { 1441e3320f40Smarkfen EXIT_FATAL("Interface name already selected"); 14428810c16bSdanmcd } 14438810c16bSdanmcd interface_name = optarg; 14448810c16bSdanmcd /* Check for some cretin using the all-polheads name. */ 14458810c16bSdanmcd if (strlen(optarg) == 0) { 1446e3320f40Smarkfen USAGE(); 1447e3320f40Smarkfen EXIT_FATAL("Invalid interface name."); 14488810c16bSdanmcd } 14498810c16bSdanmcd break; 14507c478bd9Sstevel@tonic-gate default : 1451e3320f40Smarkfen USAGE(); 1452e3320f40Smarkfen EXIT_FATAL("Bad usage."); 14537c478bd9Sstevel@tonic-gate } 14547c478bd9Sstevel@tonic-gate } 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate done: 14577c478bd9Sstevel@tonic-gate ret = 0; 14587c478bd9Sstevel@tonic-gate lfd = lock(); 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate /* 14617c478bd9Sstevel@tonic-gate * ADD, FLUSH, DELETE needs to do two operations. 14627c478bd9Sstevel@tonic-gate * 14637c478bd9Sstevel@tonic-gate * 1) Update/delete/empty the POLICY_CONF_FILE. 14647c478bd9Sstevel@tonic-gate * 2) Make an ioctl and tell IP to update its state. 14657c478bd9Sstevel@tonic-gate * 14667c478bd9Sstevel@tonic-gate * We already lock()ed so that only one instance of this 14677c478bd9Sstevel@tonic-gate * program runs. We also need to make sure that the above 14687c478bd9Sstevel@tonic-gate * operations are atomic i.e we don't want to update the file 14697c478bd9Sstevel@tonic-gate * and get interrupted before we could tell IP. To make it 14707c478bd9Sstevel@tonic-gate * atomic we block all the signals and restore them. 14717c478bd9Sstevel@tonic-gate */ 14727c478bd9Sstevel@tonic-gate switch (cmd) { 14737c478bd9Sstevel@tonic-gate case IPSEC_CONF_LIST: 14747c478bd9Sstevel@tonic-gate fetch_algorithms(); 14757c478bd9Sstevel@tonic-gate ret = ipsec_conf_list(); 14767c478bd9Sstevel@tonic-gate break; 14777c478bd9Sstevel@tonic-gate case IPSEC_CONF_FLUSH: 14787c478bd9Sstevel@tonic-gate if ((ret = block_all_signals()) == -1) { 14797c478bd9Sstevel@tonic-gate break; 14807c478bd9Sstevel@tonic-gate } 1481e3320f40Smarkfen if (!smf_managed && !ipsecconf_qflag) 1482e3320f40Smarkfen (void) fprintf(stdout, "%s", smf_warning); 14837c478bd9Sstevel@tonic-gate ret = ipsec_conf_flush(SPD_ACTIVE); 14847c478bd9Sstevel@tonic-gate (void) restore_all_signals(); 14857c478bd9Sstevel@tonic-gate break; 14867c478bd9Sstevel@tonic-gate case IPSEC_CONF_VIEW: 14878810c16bSdanmcd if (interface_name != NULL) { 1488e3320f40Smarkfen EXIT_FATAL("Cannot view for one interface only."); 14898810c16bSdanmcd } 14907c478bd9Sstevel@tonic-gate ret = ipsec_conf_view(); 14917c478bd9Sstevel@tonic-gate break; 14927c478bd9Sstevel@tonic-gate case IPSEC_CONF_DEL: 14937c478bd9Sstevel@tonic-gate if (index == -1) { 14947c478bd9Sstevel@tonic-gate warnx(gettext("Invalid index")); 14957c478bd9Sstevel@tonic-gate ret = -1; 14967c478bd9Sstevel@tonic-gate break; 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate if ((ret = block_all_signals()) == -1) { 14997c478bd9Sstevel@tonic-gate break; 15007c478bd9Sstevel@tonic-gate } 1501e3320f40Smarkfen if (!smf_managed && !ipsecconf_qflag) 1502e3320f40Smarkfen (void) fprintf(stdout, "%s", smf_warning); 15037c478bd9Sstevel@tonic-gate ret = ipsec_conf_del(index, B_FALSE); 15047c478bd9Sstevel@tonic-gate (void) restore_all_signals(); 1505e3320f40Smarkfen flushret = ipsec_conf_flush(SPD_STANDBY); 15067c478bd9Sstevel@tonic-gate break; 15077c478bd9Sstevel@tonic-gate case IPSEC_CONF_ADD: 1508e3320f40Smarkfen /* 1509e3320f40Smarkfen * The IPsec kernel modules should only be loaded 1510e3320f40Smarkfen * if there is a policy to install, for this 1511e3320f40Smarkfen * reason ipsec_conf_add() calls fetch_algorithms() 1512e3320f40Smarkfen * and ipsec_conf_flush() only when appropriate. 1513e3320f40Smarkfen */ 15147c478bd9Sstevel@tonic-gate if ((ret = block_all_signals()) == -1) { 15157c478bd9Sstevel@tonic-gate break; 15167c478bd9Sstevel@tonic-gate } 1517e3320f40Smarkfen if (!smf_managed && !ipsecconf_qflag) 1518e3320f40Smarkfen (void) fprintf(stdout, "%s", smf_warning); 1519e3320f40Smarkfen ret = ipsec_conf_add(just_check, smf_managed); 15207c478bd9Sstevel@tonic-gate (void) restore_all_signals(); 15217c478bd9Sstevel@tonic-gate break; 15227c478bd9Sstevel@tonic-gate case IPSEC_CONF_SUB: 15237c478bd9Sstevel@tonic-gate fetch_algorithms(); 15247c478bd9Sstevel@tonic-gate if ((ret = block_all_signals()) == -1) { 15257c478bd9Sstevel@tonic-gate break; 15267c478bd9Sstevel@tonic-gate } 1527e3320f40Smarkfen if (!smf_managed && !ipsecconf_qflag) 1528e3320f40Smarkfen (void) fprintf(stdout, "%s", smf_warning); 15297c478bd9Sstevel@tonic-gate ret = ipsec_conf_sub(); 15307c478bd9Sstevel@tonic-gate (void) restore_all_signals(); 1531e3320f40Smarkfen flushret = ipsec_conf_flush(SPD_STANDBY); 15327c478bd9Sstevel@tonic-gate break; 15337c478bd9Sstevel@tonic-gate default : 15347c478bd9Sstevel@tonic-gate /* If no argument is given but a "-" */ 1535e3320f40Smarkfen USAGE(); 1536e3320f40Smarkfen EXIT_FATAL("Bad usage."); 15377c478bd9Sstevel@tonic-gate } 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate (void) unlock(lfd); 15407c478bd9Sstevel@tonic-gate if (ret != 0 || flushret != 0) 15417c478bd9Sstevel@tonic-gate ret = 1; 15427c478bd9Sstevel@tonic-gate return (ret); 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate 1545e3320f40Smarkfen static void 15467c478bd9Sstevel@tonic-gate perm_check(void) 15477c478bd9Sstevel@tonic-gate { 1548e3320f40Smarkfen if (errno == EACCES) 1549e3320f40Smarkfen EXIT_BADPERM("Insufficient privilege to run ipsecconf."); 15507c478bd9Sstevel@tonic-gate else 1551e3320f40Smarkfen warn(gettext("Cannot open lock file %s"), LOCK_FILE); 1552e3320f40Smarkfen 1553e3320f40Smarkfen EXIT_BADPERM(NULL); 15547c478bd9Sstevel@tonic-gate } 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate static int 15577c478bd9Sstevel@tonic-gate lock() 15587c478bd9Sstevel@tonic-gate { 15597c478bd9Sstevel@tonic-gate int fd; 15607c478bd9Sstevel@tonic-gate struct stat sbuf1; 15617c478bd9Sstevel@tonic-gate struct stat sbuf2; 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate /* 15647c478bd9Sstevel@tonic-gate * Open the file with O_CREAT|O_EXCL. If it exists already, it 15657c478bd9Sstevel@tonic-gate * will fail. If it already exists, check whether it looks like 15667c478bd9Sstevel@tonic-gate * the one we created. 15677c478bd9Sstevel@tonic-gate */ 15687c478bd9Sstevel@tonic-gate (void) umask(0077); 15697c478bd9Sstevel@tonic-gate if ((fd = open(LOCK_FILE, O_EXCL|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) 15707c478bd9Sstevel@tonic-gate == -1) { 15717c478bd9Sstevel@tonic-gate if (errno != EEXIST) { 1572e3320f40Smarkfen /* Some other problem. Will exit. */ 1573e3320f40Smarkfen perm_check(); 15747c478bd9Sstevel@tonic-gate } 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate /* 15777c478bd9Sstevel@tonic-gate * open() returned an EEXIST error. We don't fail yet 15787c478bd9Sstevel@tonic-gate * as it could be a residual from a previous 157943c889d3Smarkfen * execution. 15807c478bd9Sstevel@tonic-gate * File exists. make sure it is OK. We need to lstat() 15817c478bd9Sstevel@tonic-gate * as fstat() stats the file pointed to by the symbolic 15827c478bd9Sstevel@tonic-gate * link. 15837c478bd9Sstevel@tonic-gate */ 15847c478bd9Sstevel@tonic-gate if (lstat(LOCK_FILE, &sbuf1) == -1) { 1585e3320f40Smarkfen EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE); 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate /* 15887c478bd9Sstevel@tonic-gate * Check whether it is a regular file and not a symbolic 15897c478bd9Sstevel@tonic-gate * link. Its link count should be 1. The owner should be 15907c478bd9Sstevel@tonic-gate * root and the file should be empty. 15917c478bd9Sstevel@tonic-gate */ 15924bc0a2efScasper if (!S_ISREG(sbuf1.st_mode) || 15937c478bd9Sstevel@tonic-gate sbuf1.st_nlink != 1 || 15947c478bd9Sstevel@tonic-gate sbuf1.st_uid != 0 || 15957c478bd9Sstevel@tonic-gate sbuf1.st_size != 0) { 1596e3320f40Smarkfen EXIT_FATAL2("Bad lock file %s", LOCK_FILE); 15977c478bd9Sstevel@tonic-gate } 15987c478bd9Sstevel@tonic-gate if ((fd = open(LOCK_FILE, O_CREAT|O_RDWR, 15997c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR)) == -1) { 1600e3320f40Smarkfen /* Will exit */ 1601e3320f40Smarkfen perm_check(); 16027c478bd9Sstevel@tonic-gate } 16037c478bd9Sstevel@tonic-gate /* 16047c478bd9Sstevel@tonic-gate * Check whether we opened the file that we lstat()ed. 16057c478bd9Sstevel@tonic-gate */ 16067c478bd9Sstevel@tonic-gate if (fstat(fd, &sbuf2) == -1) { 1607e3320f40Smarkfen EXIT_FATAL2("Cannot lstat lock file %s", LOCK_FILE); 16087c478bd9Sstevel@tonic-gate } 16097c478bd9Sstevel@tonic-gate if (sbuf1.st_dev != sbuf2.st_dev || 16107c478bd9Sstevel@tonic-gate sbuf1.st_ino != sbuf2.st_ino) { 16117c478bd9Sstevel@tonic-gate /* File changed after we did the lstat() above */ 1612e3320f40Smarkfen EXIT_FATAL2("Bad lock file %s", LOCK_FILE); 16137c478bd9Sstevel@tonic-gate } 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate if (lockf(fd, F_LOCK, 0) == -1) { 1616e3320f40Smarkfen EXIT_FATAL2("Cannot lockf %s", LOCK_FILE); 16177c478bd9Sstevel@tonic-gate } 16187c478bd9Sstevel@tonic-gate return (fd); 16197c478bd9Sstevel@tonic-gate } 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate static int 16227c478bd9Sstevel@tonic-gate unlock(int fd) 16237c478bd9Sstevel@tonic-gate { 16247c478bd9Sstevel@tonic-gate if (lockf(fd, F_ULOCK, 0) == -1) { 16257c478bd9Sstevel@tonic-gate warn("lockf"); 16267c478bd9Sstevel@tonic-gate return (-1); 16277c478bd9Sstevel@tonic-gate } 16287c478bd9Sstevel@tonic-gate return (0); 16297c478bd9Sstevel@tonic-gate } 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate /* send in TOK_* */ 16327c478bd9Sstevel@tonic-gate static void 16337c478bd9Sstevel@tonic-gate print_pattern_string(int type) 16347c478bd9Sstevel@tonic-gate { 16357c478bd9Sstevel@tonic-gate int j; 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate for (j = 0; pattern_table[j].string != NULL; j++) { 16387c478bd9Sstevel@tonic-gate if (type == pattern_table[j].tok_val) { 16397c478bd9Sstevel@tonic-gate (void) printf("%s ", pattern_table[j].string); 16407c478bd9Sstevel@tonic-gate return; 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate static void 16467c478bd9Sstevel@tonic-gate print_icmp_typecode(uint8_t type, uint8_t type_end, uint8_t code, 16477c478bd9Sstevel@tonic-gate uint8_t code_end) 16487c478bd9Sstevel@tonic-gate { 16497c478bd9Sstevel@tonic-gate (void) printf("type %d", type); 16507c478bd9Sstevel@tonic-gate if (type_end != type) 16517c478bd9Sstevel@tonic-gate (void) printf("-%d ", type_end); 16527c478bd9Sstevel@tonic-gate else 16537c478bd9Sstevel@tonic-gate (void) printf(" "); 16547c478bd9Sstevel@tonic-gate if (code != 255) { 16557c478bd9Sstevel@tonic-gate (void) printf("code %d", code); 16567c478bd9Sstevel@tonic-gate if (code_end != code) 16577c478bd9Sstevel@tonic-gate (void) printf("-%d ", code_end); 16587c478bd9Sstevel@tonic-gate else 16597c478bd9Sstevel@tonic-gate (void) printf(" "); 16607c478bd9Sstevel@tonic-gate } 16617c478bd9Sstevel@tonic-gate } 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate static void 16657c478bd9Sstevel@tonic-gate print_spd_flags(uint32_t flags) 16667c478bd9Sstevel@tonic-gate { 16677c478bd9Sstevel@tonic-gate flags &= (SPD_RULE_FLAG_INBOUND|SPD_RULE_FLAG_OUTBOUND); 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate if (flags == SPD_RULE_FLAG_OUTBOUND) 16707c478bd9Sstevel@tonic-gate (void) printf("dir out "); 16717c478bd9Sstevel@tonic-gate else if (flags == SPD_RULE_FLAG_INBOUND) 16727c478bd9Sstevel@tonic-gate (void) printf("dir in "); 16737c478bd9Sstevel@tonic-gate else if (flags == (SPD_RULE_FLAG_INBOUND|SPD_RULE_FLAG_OUTBOUND)) 16747c478bd9Sstevel@tonic-gate (void) printf("dir both "); 16757c478bd9Sstevel@tonic-gate } 16767c478bd9Sstevel@tonic-gate 16777c478bd9Sstevel@tonic-gate static void 16787c478bd9Sstevel@tonic-gate print_bit_range(int min, int max) 16797c478bd9Sstevel@tonic-gate { 16807c478bd9Sstevel@tonic-gate if (min != 0 || (max != 0 && max != SPD_MAX_MAXBITS)) { 16817c478bd9Sstevel@tonic-gate (void) printf("("); 16827c478bd9Sstevel@tonic-gate if (min != 0) 16837c478bd9Sstevel@tonic-gate (void) printf("%d", min); 16847c478bd9Sstevel@tonic-gate if (min != 0 && max != 0 && min != max) { 16857c478bd9Sstevel@tonic-gate (void) printf(".."); 16867c478bd9Sstevel@tonic-gate if (max != 0 && max != SPD_MAX_MAXBITS) 16877c478bd9Sstevel@tonic-gate (void) printf("%d", max); 16887c478bd9Sstevel@tonic-gate } 16897c478bd9Sstevel@tonic-gate (void) printf(")"); 16907c478bd9Sstevel@tonic-gate } 16917c478bd9Sstevel@tonic-gate } 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate static void 16947c478bd9Sstevel@tonic-gate print_alg(const char *tag, algreq_t *algreq, int proto_num) 16957c478bd9Sstevel@tonic-gate { 16967c478bd9Sstevel@tonic-gate int min = algreq->alg_minbits; 16977c478bd9Sstevel@tonic-gate int max = algreq->alg_maxbits; 16987c478bd9Sstevel@tonic-gate struct ipsecalgent *alg; 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate /* 17017c478bd9Sstevel@tonic-gate * This function won't be called with alg_id == 0, so we don't 17027c478bd9Sstevel@tonic-gate * have to worry about ANY vs. NONE here. 17037c478bd9Sstevel@tonic-gate */ 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate (void) printf("%s ", tag); 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate alg = getipsecalgbynum(algreq->alg_id, proto_num, NULL); 17087c478bd9Sstevel@tonic-gate if (alg == NULL) { 17097c478bd9Sstevel@tonic-gate (void) printf("%d", algreq->alg_id); 17107c478bd9Sstevel@tonic-gate } else { 17117c478bd9Sstevel@tonic-gate (void) printf("%s", alg->a_names[0]); 17127c478bd9Sstevel@tonic-gate freeipsecalgent(alg); 17137c478bd9Sstevel@tonic-gate } 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate print_bit_range(min, max); 17167c478bd9Sstevel@tonic-gate (void) printf(" "); 17177c478bd9Sstevel@tonic-gate } 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate static void 17207c478bd9Sstevel@tonic-gate print_ulp(uint8_t proto) 17217c478bd9Sstevel@tonic-gate { 17227c478bd9Sstevel@tonic-gate struct protoent *pe; 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate if (proto == 0) 17257c478bd9Sstevel@tonic-gate return; 17267c478bd9Sstevel@tonic-gate 17277c478bd9Sstevel@tonic-gate print_pattern_string(TOK_ulp); 17287c478bd9Sstevel@tonic-gate pe = NULL; 17297c478bd9Sstevel@tonic-gate if (!ipsecconf_nflag) { 17307c478bd9Sstevel@tonic-gate pe = getprotobynumber(proto); 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate if (pe != NULL) 17337c478bd9Sstevel@tonic-gate (void) printf("%s ", pe->p_name); 17347c478bd9Sstevel@tonic-gate else 17357c478bd9Sstevel@tonic-gate (void) printf("%d ", proto); 17367c478bd9Sstevel@tonic-gate } 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate /* needs to do ranges */ 17397c478bd9Sstevel@tonic-gate static void 17407c478bd9Sstevel@tonic-gate print_port(uint16_t in_port, int type) 17417c478bd9Sstevel@tonic-gate { 17427c478bd9Sstevel@tonic-gate in_port_t port = ntohs(in_port); 17437c478bd9Sstevel@tonic-gate struct servent *sp; 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate if (port == 0) 17467c478bd9Sstevel@tonic-gate return; 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate print_pattern_string(type); 17497c478bd9Sstevel@tonic-gate sp = NULL; 17507c478bd9Sstevel@tonic-gate if (!ipsecconf_nflag) 17517c478bd9Sstevel@tonic-gate sp = getservbyport(port, NULL); 17527c478bd9Sstevel@tonic-gate 17537c478bd9Sstevel@tonic-gate if (sp != NULL) 17547c478bd9Sstevel@tonic-gate (void) printf("%s ", sp->s_name); 17557c478bd9Sstevel@tonic-gate else 17567c478bd9Sstevel@tonic-gate (void) printf("%d ", port); 17577c478bd9Sstevel@tonic-gate } 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate /* 17608810c16bSdanmcd * Print the address, given as "raw" input via the void pointer. 17617c478bd9Sstevel@tonic-gate */ 17627c478bd9Sstevel@tonic-gate static void 17638810c16bSdanmcd print_raw_address(void *input, boolean_t isv4) 17647c478bd9Sstevel@tonic-gate { 17657c478bd9Sstevel@tonic-gate char *cp; 17667c478bd9Sstevel@tonic-gate struct hostent *hp; 17677c478bd9Sstevel@tonic-gate char domain[MAXHOSTNAMELEN + 1]; 17687c478bd9Sstevel@tonic-gate struct in_addr addr; 17697c478bd9Sstevel@tonic-gate struct in6_addr addr6; 17707c478bd9Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 17717c478bd9Sstevel@tonic-gate int error_num; 17727c478bd9Sstevel@tonic-gate struct in6_addr in_addr; 17737c478bd9Sstevel@tonic-gate uchar_t *addr_ptr; 17747c478bd9Sstevel@tonic-gate sa_family_t af; 17757c478bd9Sstevel@tonic-gate int addr_len; 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate if (isv4) { 17787c478bd9Sstevel@tonic-gate af = AF_INET; 17797c478bd9Sstevel@tonic-gate (void) memcpy(&V4_PART_OF_V6(in_addr), input, 4); 17807c478bd9Sstevel@tonic-gate /* we don't print unspecified addresses */ 17817c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR(&in_addr, &addr); 17827c478bd9Sstevel@tonic-gate if (addr.s_addr == INADDR_ANY) 17837c478bd9Sstevel@tonic-gate return; 17847c478bd9Sstevel@tonic-gate addr_ptr = (uchar_t *)&addr.s_addr; 17857c478bd9Sstevel@tonic-gate addr_len = IPV4_ADDR_LEN; 17867c478bd9Sstevel@tonic-gate } else { 17877c478bd9Sstevel@tonic-gate (void) memcpy(&addr6, input, 16); 17887c478bd9Sstevel@tonic-gate af = AF_INET6; 17897c478bd9Sstevel@tonic-gate /* we don't print unspecified addresses */ 17907c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) 17917c478bd9Sstevel@tonic-gate return; 17927c478bd9Sstevel@tonic-gate addr_ptr = (uchar_t *)&addr6.s6_addr; 17937c478bd9Sstevel@tonic-gate addr_len = sizeof (struct in6_addr); 17947c478bd9Sstevel@tonic-gate } 17957c478bd9Sstevel@tonic-gate 17967c478bd9Sstevel@tonic-gate cp = NULL; 17977c478bd9Sstevel@tonic-gate if (!ipsecconf_nflag) { 17987c478bd9Sstevel@tonic-gate if (sysinfo(SI_HOSTNAME, domain, MAXHOSTNAMELEN) != -1 && 1799d5751483Smarkfen (cp = strchr(domain, '.')) != NULL) { 1800e3320f40Smarkfen (void) strlcpy(domain, cp + 1, sizeof (domain)); 18017c478bd9Sstevel@tonic-gate } else { 18027c478bd9Sstevel@tonic-gate domain[0] = 0; 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate hp = getipnodebyaddr(addr_ptr, addr_len, af, &error_num); 18057c478bd9Sstevel@tonic-gate if (hp) { 18067c478bd9Sstevel@tonic-gate if ((cp = strchr(hp->h_name, '.')) != 0 && 1807d5751483Smarkfen strcasecmp(cp + 1, domain) == 0) 18087c478bd9Sstevel@tonic-gate *cp = 0; 18097c478bd9Sstevel@tonic-gate cp = hp->h_name; 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate } 18127c478bd9Sstevel@tonic-gate 18137c478bd9Sstevel@tonic-gate if (cp) { 18147c478bd9Sstevel@tonic-gate (void) printf("%s", cp); 18157c478bd9Sstevel@tonic-gate } else { 18167c478bd9Sstevel@tonic-gate (void) printf("%s", inet_ntop(af, addr_ptr, abuf, 18177c478bd9Sstevel@tonic-gate INET6_ADDRSTRLEN)); 18187c478bd9Sstevel@tonic-gate } 18197c478bd9Sstevel@tonic-gate } 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate /* 18227c478bd9Sstevel@tonic-gate * Get the next SPD_DUMP message from the PF_POLICY socket. A single 18237c478bd9Sstevel@tonic-gate * read may contain multiple messages. This function uses static buffers, 18247c478bd9Sstevel@tonic-gate * and is therefore non-reentrant, so if you lift it for an MT application, 18257c478bd9Sstevel@tonic-gate * be careful. 18267c478bd9Sstevel@tonic-gate * 18277c478bd9Sstevel@tonic-gate * Return NULL if there's an error. 18287c478bd9Sstevel@tonic-gate */ 18297c478bd9Sstevel@tonic-gate static spd_msg_t * 18307c478bd9Sstevel@tonic-gate ipsec_read_dump(int pfd) 18317c478bd9Sstevel@tonic-gate { 18327c478bd9Sstevel@tonic-gate static uint64_t buf[SADB_8TO64(CBUF_LEN)]; 18337c478bd9Sstevel@tonic-gate static uint64_t *offset; 18347c478bd9Sstevel@tonic-gate static int len; /* In uint64_t units. */ 18357c478bd9Sstevel@tonic-gate spd_msg_t *retval; 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate /* Assume offset and len are initialized to NULL and 0. */ 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate if ((offset - len == buf) || (offset == NULL)) { 18407c478bd9Sstevel@tonic-gate /* read a new block from the socket. */ 18417c478bd9Sstevel@tonic-gate len = read(pfd, &buf, sizeof (buf)); 18427c478bd9Sstevel@tonic-gate if (len == -1) { 18437c478bd9Sstevel@tonic-gate warn(gettext("rule dump: bad read")); 18447c478bd9Sstevel@tonic-gate return (NULL); 18457c478bd9Sstevel@tonic-gate } 18467c478bd9Sstevel@tonic-gate offset = buf; 18477c478bd9Sstevel@tonic-gate len = SADB_8TO64(len); 18487c478bd9Sstevel@tonic-gate } /* Else I still have more messages from a previous read. */ 18497c478bd9Sstevel@tonic-gate 18507c478bd9Sstevel@tonic-gate retval = (spd_msg_t *)offset; 18517c478bd9Sstevel@tonic-gate offset += retval->spd_msg_len; 18527c478bd9Sstevel@tonic-gate if (offset > buf + len) { 18537c478bd9Sstevel@tonic-gate warnx(gettext("dump read: message corruption," 18547c478bd9Sstevel@tonic-gate " %d len exceeds %d boundary."), 18557c478bd9Sstevel@tonic-gate SADB_64TO8((uintptr_t)(offset - buf)), 18567c478bd9Sstevel@tonic-gate SADB_64TO8((uintptr_t)(buf + len))); 18577c478bd9Sstevel@tonic-gate return (NULL); 18587c478bd9Sstevel@tonic-gate } 18597c478bd9Sstevel@tonic-gate 18607c478bd9Sstevel@tonic-gate return (retval); 18617c478bd9Sstevel@tonic-gate } 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate /* 18647c478bd9Sstevel@tonic-gate * returns 0 on success 18657c478bd9Sstevel@tonic-gate * -1 on read error 18667c478bd9Sstevel@tonic-gate * >0 on invalid returned message 18677c478bd9Sstevel@tonic-gate */ 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate static int 18707c478bd9Sstevel@tonic-gate ipsec_conf_list(void) 18717c478bd9Sstevel@tonic-gate { 18727c478bd9Sstevel@tonic-gate int ret; 18737c478bd9Sstevel@tonic-gate int pfd; 18748810c16bSdanmcd struct spd_msg *msg; 18757c478bd9Sstevel@tonic-gate int cnt; 18767c478bd9Sstevel@tonic-gate spd_msg_t *rmsg; 18777c478bd9Sstevel@tonic-gate spd_ext_t *exts[SPD_EXT_MAX+1]; 18788810c16bSdanmcd /* 18798810c16bSdanmcd * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation 18808810c16bSdanmcd * issues. 18818810c16bSdanmcd */ 18828810c16bSdanmcd uint64_t buffer[ 18838810c16bSdanmcd SPD_8TO64(sizeof (*msg) + sizeof (spd_if_t) + LIFNAMSIZ) + 1]; 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate pfd = get_pf_pol_socket(); 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate if (pfd == -1) { 18887c478bd9Sstevel@tonic-gate warnx(gettext("Error getting list of policies from kernel")); 18897c478bd9Sstevel@tonic-gate return (-1); 18907c478bd9Sstevel@tonic-gate } 18917c478bd9Sstevel@tonic-gate 18928810c16bSdanmcd (void) memset(buffer, 0, sizeof (buffer)); 18938810c16bSdanmcd msg = (struct spd_msg *)buffer; 18948810c16bSdanmcd msg->spd_msg_version = PF_POLICY_V1; 18958810c16bSdanmcd msg->spd_msg_type = SPD_DUMP; 18968810c16bSdanmcd msg->spd_msg_len = SPD_8TO64(sizeof (*msg)); 18977c478bd9Sstevel@tonic-gate 18988810c16bSdanmcd msg->spd_msg_len += attach_tunname((spd_if_t *)(msg + 1)); 18998810c16bSdanmcd 19008810c16bSdanmcd cnt = write(pfd, msg, SPD_64TO8(msg->spd_msg_len)); 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate if (cnt < 0) { 19037c478bd9Sstevel@tonic-gate warn(gettext("dump: invalid write() return")); 19047c478bd9Sstevel@tonic-gate (void) close(pfd); 19057c478bd9Sstevel@tonic-gate return (-1); 19067c478bd9Sstevel@tonic-gate } 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate rmsg = ipsec_read_dump(pfd); 19097c478bd9Sstevel@tonic-gate 19107c478bd9Sstevel@tonic-gate if (rmsg == NULL || rmsg->spd_msg_errno != 0) { 19117c478bd9Sstevel@tonic-gate warnx("%s: %s", gettext("ruleset dump failed"), 19127c478bd9Sstevel@tonic-gate (rmsg == NULL ? 1913d5751483Smarkfen gettext("read error") : 1914d5751483Smarkfen sys_error_message(rmsg->spd_msg_errno))); 19157c478bd9Sstevel@tonic-gate (void) close(pfd); 19167c478bd9Sstevel@tonic-gate return (-1); 19177c478bd9Sstevel@tonic-gate } 19187c478bd9Sstevel@tonic-gate 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate for (;;) { 19217c478bd9Sstevel@tonic-gate /* read rule */ 19227c478bd9Sstevel@tonic-gate rmsg = ipsec_read_dump(pfd); 19237c478bd9Sstevel@tonic-gate 19247c478bd9Sstevel@tonic-gate if (rmsg == NULL) { 19257c478bd9Sstevel@tonic-gate (void) close(pfd); 19267c478bd9Sstevel@tonic-gate return (-1); 19277c478bd9Sstevel@tonic-gate } 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate if (rmsg->spd_msg_errno != 0) { 19307c478bd9Sstevel@tonic-gate warnx("%s: %s", gettext("dump read: bad message"), 19318810c16bSdanmcd sys_error_message(rmsg->spd_msg_errno)); 19327c478bd9Sstevel@tonic-gate (void) close(pfd); 19337c478bd9Sstevel@tonic-gate return (-1); 19347c478bd9Sstevel@tonic-gate } 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate ret = spdsock_get_ext(exts, rmsg, rmsg->spd_msg_len, 19377c478bd9Sstevel@tonic-gate spdsock_diag_buf, SPDSOCK_DIAG_BUF_LEN); 19387c478bd9Sstevel@tonic-gate if (ret != 0) { 19397c478bd9Sstevel@tonic-gate if (strlen(spdsock_diag_buf) != 0) 19407c478bd9Sstevel@tonic-gate warnx(spdsock_diag_buf); 19417c478bd9Sstevel@tonic-gate warnx("%s: %s", gettext("dump read: bad message"), 19428810c16bSdanmcd sys_error_message(rmsg->spd_msg_errno)); 19437c478bd9Sstevel@tonic-gate (void) close(pfd); 19447c478bd9Sstevel@tonic-gate return (ret); 19457c478bd9Sstevel@tonic-gate } 19467c478bd9Sstevel@tonic-gate 19477c478bd9Sstevel@tonic-gate /* 19487c478bd9Sstevel@tonic-gate * End of dump.. 19497c478bd9Sstevel@tonic-gate */ 19507c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_RULESET] != NULL) 19517c478bd9Sstevel@tonic-gate break; /* and return 0. */ 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate print_pfpol_msg(rmsg); 19547c478bd9Sstevel@tonic-gate } 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate (void) close(pfd); 19577c478bd9Sstevel@tonic-gate return (0); 19587c478bd9Sstevel@tonic-gate } 19597c478bd9Sstevel@tonic-gate 19607c478bd9Sstevel@tonic-gate static void 19617c478bd9Sstevel@tonic-gate print_iap(ips_act_props_t *iap) 19627c478bd9Sstevel@tonic-gate { 19637c478bd9Sstevel@tonic-gate 19647c478bd9Sstevel@tonic-gate /* action */ 19657c478bd9Sstevel@tonic-gate switch (iap->iap_action) { 19667c478bd9Sstevel@tonic-gate case SPD_ACTTYPE_PASS: 19677c478bd9Sstevel@tonic-gate (void) printf("pass "); 19687c478bd9Sstevel@tonic-gate break; 19697c478bd9Sstevel@tonic-gate case SPD_ACTTYPE_DROP: 19707c478bd9Sstevel@tonic-gate (void) printf("drop "); 19717c478bd9Sstevel@tonic-gate break; 19727c478bd9Sstevel@tonic-gate case SPD_ACTTYPE_IPSEC: 19737c478bd9Sstevel@tonic-gate (void) printf("ipsec "); 19747c478bd9Sstevel@tonic-gate break; 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate /* properties */ 19787c478bd9Sstevel@tonic-gate (void) printf("%c ", CURL_BEGIN); 19797c478bd9Sstevel@tonic-gate if (iap->iap_action == SPD_ACTTYPE_IPSEC) { 19807c478bd9Sstevel@tonic-gate if (iap->iap_attr & SPD_APPLY_AH && 19817c478bd9Sstevel@tonic-gate iap->iap_aauth.alg_id != 0) 19827c478bd9Sstevel@tonic-gate print_alg("auth_algs", &iap->iap_aauth, 19837c478bd9Sstevel@tonic-gate IPSEC_PROTO_AH); 19847c478bd9Sstevel@tonic-gate 19857c478bd9Sstevel@tonic-gate if (iap->iap_attr & SPD_APPLY_ESP) { 19867c478bd9Sstevel@tonic-gate print_alg("encr_algs", &iap->iap_eencr, 19877c478bd9Sstevel@tonic-gate IPSEC_PROTO_ESP); 19887c478bd9Sstevel@tonic-gate if (iap->iap_eauth.alg_id != 0) 19897c478bd9Sstevel@tonic-gate print_alg("encr_auth_algs", &iap->iap_eauth, 19907c478bd9Sstevel@tonic-gate IPSEC_PROTO_AH); 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate if (iap->iap_attr & SPD_APPLY_UNIQUE) 19937c478bd9Sstevel@tonic-gate (void) printf("sa unique "); 19947c478bd9Sstevel@tonic-gate else 19957c478bd9Sstevel@tonic-gate (void) printf("sa shared "); 19967c478bd9Sstevel@tonic-gate } 19977c478bd9Sstevel@tonic-gate (void) printf("%c ", CURL_END); 19987c478bd9Sstevel@tonic-gate } 19997c478bd9Sstevel@tonic-gate 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate static void 20027c478bd9Sstevel@tonic-gate print_pfpol_msg(spd_msg_t *msg) 20037c478bd9Sstevel@tonic-gate { 20047c478bd9Sstevel@tonic-gate spd_ext_t *exts[SPD_EXT_MAX+1]; 20057c478bd9Sstevel@tonic-gate spd_address_t *spd_address; 20067c478bd9Sstevel@tonic-gate struct spd_rule *spd_rule; 20077c478bd9Sstevel@tonic-gate struct spd_proto *spd_proto; 20087c478bd9Sstevel@tonic-gate struct spd_portrange *spd_portrange; 20097c478bd9Sstevel@tonic-gate struct spd_ext_actions *spd_ext_actions; 20107c478bd9Sstevel@tonic-gate struct spd_typecode *spd_typecode; 20117c478bd9Sstevel@tonic-gate struct spd_attribute *app; 20128810c16bSdanmcd spd_if_t *spd_if; 20137c478bd9Sstevel@tonic-gate uint32_t rv; 20147c478bd9Sstevel@tonic-gate uint16_t act_count; 20157c478bd9Sstevel@tonic-gate 20167c478bd9Sstevel@tonic-gate rv = spdsock_get_ext(exts, msg, msg->spd_msg_len, spdsock_diag_buf, 20177c478bd9Sstevel@tonic-gate SPDSOCK_DIAG_BUF_LEN); 20187c478bd9Sstevel@tonic-gate 20197c478bd9Sstevel@tonic-gate if (rv == KGE_OK && exts[SPD_EXT_RULE] != NULL) { 20208810c16bSdanmcd spd_if = (spd_if_t *)exts[SPD_EXT_TUN_NAME]; 20217c478bd9Sstevel@tonic-gate spd_rule = (struct spd_rule *)exts[SPD_EXT_RULE]; 20228810c16bSdanmcd if (spd_if == NULL) { 20238810c16bSdanmcd (void) printf("%s %lld\n", INDEX_TAG, 20248810c16bSdanmcd spd_rule->spd_rule_index); 20258810c16bSdanmcd } else { 20268810c16bSdanmcd (void) printf("%s %s,%lld\n", INDEX_TAG, 20278810c16bSdanmcd (char *)spd_if->spd_if_name, 20288810c16bSdanmcd spd_rule->spd_rule_index); 20298810c16bSdanmcd } 20307c478bd9Sstevel@tonic-gate } else { 20317c478bd9Sstevel@tonic-gate if (strlen(spdsock_diag_buf) != 0) 20327c478bd9Sstevel@tonic-gate warnx(spdsock_diag_buf); 20337c478bd9Sstevel@tonic-gate warnx(gettext("print_pfpol_msg: malformed PF_POLICY message.")); 20347c478bd9Sstevel@tonic-gate return; 20357c478bd9Sstevel@tonic-gate } 20367c478bd9Sstevel@tonic-gate 20377c478bd9Sstevel@tonic-gate (void) printf("%c ", CURL_BEGIN); 20387c478bd9Sstevel@tonic-gate 20398810c16bSdanmcd if (spd_if != NULL) { 20408810c16bSdanmcd (void) printf("tunnel %s negotiate %s ", 20418810c16bSdanmcd (char *)spd_if->spd_if_name, 20428810c16bSdanmcd (spd_rule->spd_rule_flags & SPD_RULE_FLAG_TUNNEL) ? 20438810c16bSdanmcd "tunnel" : "transport"); 20448810c16bSdanmcd } 20458810c16bSdanmcd 20467c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_PROTO] != NULL) { 20477c478bd9Sstevel@tonic-gate spd_proto = (struct spd_proto *)exts[SPD_EXT_PROTO]; 20487c478bd9Sstevel@tonic-gate print_ulp(spd_proto->spd_proto_number); 20497c478bd9Sstevel@tonic-gate } 20507c478bd9Sstevel@tonic-gate 20517c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_LCLADDR] != NULL) { 20527c478bd9Sstevel@tonic-gate spd_address = (spd_address_t *)exts[SPD_EXT_LCLADDR]; 20537c478bd9Sstevel@tonic-gate 20547c478bd9Sstevel@tonic-gate (void) printf("laddr "); 20558810c16bSdanmcd print_raw_address((spd_address + 1), 20568810c16bSdanmcd (spd_address->spd_address_len == 2)); 20577c478bd9Sstevel@tonic-gate (void) printf("/%d ", spd_address->spd_address_prefixlen); 20587c478bd9Sstevel@tonic-gate } 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_LCLPORT] != NULL) { 20617c478bd9Sstevel@tonic-gate spd_portrange = (struct spd_portrange *)exts[SPD_EXT_LCLPORT]; 20627c478bd9Sstevel@tonic-gate if (spd_portrange->spd_ports_minport != 0) { 20637c478bd9Sstevel@tonic-gate print_port(spd_portrange->spd_ports_minport, 20647c478bd9Sstevel@tonic-gate TOK_lport); 20657c478bd9Sstevel@tonic-gate } 20667c478bd9Sstevel@tonic-gate } 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_REMADDR] != NULL) { 20707c478bd9Sstevel@tonic-gate spd_address = (spd_address_t *)exts[SPD_EXT_REMADDR]; 20717c478bd9Sstevel@tonic-gate 20727c478bd9Sstevel@tonic-gate (void) printf("raddr "); 20738810c16bSdanmcd print_raw_address((spd_address + 1), 20748810c16bSdanmcd (spd_address->spd_address_len == 2)); 20757c478bd9Sstevel@tonic-gate (void) printf("/%d ", spd_address->spd_address_prefixlen); 20767c478bd9Sstevel@tonic-gate } 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_REMPORT] != NULL) { 20797c478bd9Sstevel@tonic-gate spd_portrange = 2080d5751483Smarkfen (struct spd_portrange *)exts[SPD_EXT_REMPORT]; 20817c478bd9Sstevel@tonic-gate if (spd_portrange->spd_ports_minport != 0) { 20827c478bd9Sstevel@tonic-gate print_port( 2083d5751483Smarkfen spd_portrange->spd_ports_minport, TOK_rport); 20847c478bd9Sstevel@tonic-gate } 20857c478bd9Sstevel@tonic-gate } 20867c478bd9Sstevel@tonic-gate 20877c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_ICMP_TYPECODE] != NULL) { 20887c478bd9Sstevel@tonic-gate spd_typecode = 20897c478bd9Sstevel@tonic-gate (struct spd_typecode *)exts[SPD_EXT_ICMP_TYPECODE]; 20907c478bd9Sstevel@tonic-gate print_icmp_typecode(spd_typecode->spd_typecode_type, 20917c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_type_end, 20927c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_code, 20937c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_code_end); 20947c478bd9Sstevel@tonic-gate } 20957c478bd9Sstevel@tonic-gate 20967c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_RULE] != NULL) { 20977c478bd9Sstevel@tonic-gate spd_rule = (struct spd_rule *)exts[SPD_EXT_RULE]; 20987c478bd9Sstevel@tonic-gate print_spd_flags(spd_rule->spd_rule_flags); 20997c478bd9Sstevel@tonic-gate } 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate 21027c478bd9Sstevel@tonic-gate (void) printf("%c ", CURL_END); 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate if (exts[SPD_EXT_ACTION] != NULL) { 21057c478bd9Sstevel@tonic-gate ips_act_props_t iap; 21067c478bd9Sstevel@tonic-gate int or_needed = 0; 21077c478bd9Sstevel@tonic-gate 21087c478bd9Sstevel@tonic-gate (void) memset(&iap, 0, sizeof (iap)); 21097c478bd9Sstevel@tonic-gate spd_ext_actions = 21107c478bd9Sstevel@tonic-gate (struct spd_ext_actions *)exts[SPD_EXT_ACTION]; 21117c478bd9Sstevel@tonic-gate app = (struct spd_attribute *)(spd_ext_actions + 1); 21127c478bd9Sstevel@tonic-gate 21137c478bd9Sstevel@tonic-gate for (act_count = 0; 21147c478bd9Sstevel@tonic-gate act_count < spd_ext_actions->spd_actions_len -1; 2115d5751483Smarkfen act_count++) { 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate switch (app->spd_attr_tag) { 21187c478bd9Sstevel@tonic-gate 21197c478bd9Sstevel@tonic-gate case SPD_ATTR_NOP: 21207c478bd9Sstevel@tonic-gate break; 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate case SPD_ATTR_END: 21237c478bd9Sstevel@tonic-gate /* print */ 21247c478bd9Sstevel@tonic-gate if (or_needed) { 21257c478bd9Sstevel@tonic-gate (void) printf("or "); 21267c478bd9Sstevel@tonic-gate } else { 21277c478bd9Sstevel@tonic-gate or_needed = 1; 21287c478bd9Sstevel@tonic-gate } 21297c478bd9Sstevel@tonic-gate print_iap(&iap); 21307c478bd9Sstevel@tonic-gate break; 21317c478bd9Sstevel@tonic-gate 21327c478bd9Sstevel@tonic-gate case SPD_ATTR_EMPTY: 21337c478bd9Sstevel@tonic-gate /* clear */ 21347c478bd9Sstevel@tonic-gate (void) memset(&iap, 0, sizeof (iap)); 21357c478bd9Sstevel@tonic-gate break; 21367c478bd9Sstevel@tonic-gate 21377c478bd9Sstevel@tonic-gate case SPD_ATTR_NEXT: 21387c478bd9Sstevel@tonic-gate /* print */ 21397c478bd9Sstevel@tonic-gate if (or_needed) { 21407c478bd9Sstevel@tonic-gate (void) printf("or "); 21417c478bd9Sstevel@tonic-gate } else { 21427c478bd9Sstevel@tonic-gate or_needed = 1; 21437c478bd9Sstevel@tonic-gate } 21447c478bd9Sstevel@tonic-gate 21457c478bd9Sstevel@tonic-gate print_iap(&iap); 21467c478bd9Sstevel@tonic-gate break; 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate case SPD_ATTR_TYPE: 21497c478bd9Sstevel@tonic-gate iap.iap_action = app->spd_attr_value; 21507c478bd9Sstevel@tonic-gate break; 21517c478bd9Sstevel@tonic-gate 21527c478bd9Sstevel@tonic-gate case SPD_ATTR_FLAGS: 21537c478bd9Sstevel@tonic-gate iap.iap_attr = app->spd_attr_value; 21547c478bd9Sstevel@tonic-gate break; 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate case SPD_ATTR_AH_AUTH: 21577c478bd9Sstevel@tonic-gate iap.iap_aauth.alg_id = app->spd_attr_value; 21587c478bd9Sstevel@tonic-gate break; 21597c478bd9Sstevel@tonic-gate 21607c478bd9Sstevel@tonic-gate case SPD_ATTR_ESP_ENCR: 21617c478bd9Sstevel@tonic-gate iap.iap_eencr.alg_id = app->spd_attr_value; 21627c478bd9Sstevel@tonic-gate break; 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate case SPD_ATTR_ESP_AUTH: 21657c478bd9Sstevel@tonic-gate iap.iap_eauth.alg_id = app->spd_attr_value; 21667c478bd9Sstevel@tonic-gate break; 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate case SPD_ATTR_ENCR_MINBITS: 21697c478bd9Sstevel@tonic-gate iap.iap_eencr.alg_minbits = app->spd_attr_value; 21707c478bd9Sstevel@tonic-gate break; 21717c478bd9Sstevel@tonic-gate 21727c478bd9Sstevel@tonic-gate case SPD_ATTR_ENCR_MAXBITS: 21737c478bd9Sstevel@tonic-gate iap.iap_eencr.alg_maxbits = app->spd_attr_value; 21747c478bd9Sstevel@tonic-gate break; 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate case SPD_ATTR_AH_MINBITS: 21777c478bd9Sstevel@tonic-gate iap.iap_aauth.alg_minbits = app->spd_attr_value; 21787c478bd9Sstevel@tonic-gate break; 21797c478bd9Sstevel@tonic-gate 21807c478bd9Sstevel@tonic-gate case SPD_ATTR_AH_MAXBITS: 21817c478bd9Sstevel@tonic-gate iap.iap_aauth.alg_maxbits = app->spd_attr_value; 21827c478bd9Sstevel@tonic-gate break; 21837c478bd9Sstevel@tonic-gate 21847c478bd9Sstevel@tonic-gate case SPD_ATTR_ESPA_MINBITS: 21857c478bd9Sstevel@tonic-gate iap.iap_eauth.alg_minbits = app->spd_attr_value; 21867c478bd9Sstevel@tonic-gate break; 21877c478bd9Sstevel@tonic-gate 21887c478bd9Sstevel@tonic-gate case SPD_ATTR_ESPA_MAXBITS: 21897c478bd9Sstevel@tonic-gate iap.iap_eauth.alg_maxbits = app->spd_attr_value; 21907c478bd9Sstevel@tonic-gate break; 21917c478bd9Sstevel@tonic-gate 21927c478bd9Sstevel@tonic-gate case SPD_ATTR_LIFE_SOFT_TIME: 21937c478bd9Sstevel@tonic-gate case SPD_ATTR_LIFE_HARD_TIME: 21947c478bd9Sstevel@tonic-gate case SPD_ATTR_LIFE_SOFT_BYTES: 21957c478bd9Sstevel@tonic-gate case SPD_ATTR_LIFE_HARD_BYTES: 21967c478bd9Sstevel@tonic-gate default: 21977c478bd9Sstevel@tonic-gate (void) printf("\tattr %d: %X-%d\n", 21987c478bd9Sstevel@tonic-gate act_count, 21997c478bd9Sstevel@tonic-gate app->spd_attr_tag, 22007c478bd9Sstevel@tonic-gate app->spd_attr_value); 22017c478bd9Sstevel@tonic-gate break; 22027c478bd9Sstevel@tonic-gate } 22037c478bd9Sstevel@tonic-gate app++; 22047c478bd9Sstevel@tonic-gate } 22057c478bd9Sstevel@tonic-gate } 22067c478bd9Sstevel@tonic-gate 22077c478bd9Sstevel@tonic-gate (void) printf("\n"); 22087c478bd9Sstevel@tonic-gate } 22097c478bd9Sstevel@tonic-gate 22107c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 22117c478bd9Sstevel@tonic-gate static void 22127c478bd9Sstevel@tonic-gate pfpol_msg_dump(spd_msg_t *msg, char *tag) 22137c478bd9Sstevel@tonic-gate { 22147c478bd9Sstevel@tonic-gate spd_ext_t *exts[SPD_EXT_MAX+1]; 22157c478bd9Sstevel@tonic-gate uint32_t i; 22167c478bd9Sstevel@tonic-gate spd_address_t *spd_address; 22177c478bd9Sstevel@tonic-gate struct spd_rule *spd_rule; 22187c478bd9Sstevel@tonic-gate struct spd_proto *spd_proto; 22197c478bd9Sstevel@tonic-gate struct spd_portrange *spd_portrange; 22207c478bd9Sstevel@tonic-gate struct spd_typecode *spd_typecode; 22217c478bd9Sstevel@tonic-gate struct spd_ext_actions *spd_ext_actions; 22227c478bd9Sstevel@tonic-gate struct spd_attribute *app; 22238810c16bSdanmcd spd_if_t *spd_if; 22247c478bd9Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 22257c478bd9Sstevel@tonic-gate uint32_t rv; 22267c478bd9Sstevel@tonic-gate uint16_t act_count; 22277c478bd9Sstevel@tonic-gate 22287c478bd9Sstevel@tonic-gate rv = spdsock_get_ext(exts, msg, msg->spd_msg_len, NULL, 0); 22297c478bd9Sstevel@tonic-gate if (rv != KGE_OK) 22307c478bd9Sstevel@tonic-gate return; 22317c478bd9Sstevel@tonic-gate 22327c478bd9Sstevel@tonic-gate (void) printf("===========%s==============\n", tag); 22337c478bd9Sstevel@tonic-gate (void) printf("pfpol_msg_dump %d\n-------------------\n", rv); 22347c478bd9Sstevel@tonic-gate 22357c478bd9Sstevel@tonic-gate (void) printf("spd_msg_version:%d\n", msg->spd_msg_version); 22367c478bd9Sstevel@tonic-gate (void) printf("spd_msg_type:%d\n", msg->spd_msg_type); 22377c478bd9Sstevel@tonic-gate (void) printf("spd_msg_errno:%d\n", msg->spd_msg_errno); 22387c478bd9Sstevel@tonic-gate (void) printf("spd_msg_spdid:%d\n", msg->spd_msg_spdid); 22397c478bd9Sstevel@tonic-gate (void) printf("spd_msg_len:%d\n", msg->spd_msg_len); 22407c478bd9Sstevel@tonic-gate (void) printf("spd_msg_diagnostic:%d\n", msg->spd_msg_diagnostic); 22417c478bd9Sstevel@tonic-gate (void) printf("spd_msg_seq:%d\n", msg->spd_msg_seq); 22427c478bd9Sstevel@tonic-gate (void) printf("spd_msg_pid:%d\n", msg->spd_msg_pid); 22437c478bd9Sstevel@tonic-gate 22447c478bd9Sstevel@tonic-gate for (i = 1; i <= SPD_EXT_MAX; i++) { 22457c478bd9Sstevel@tonic-gate if (exts[i] == NULL) { 22467c478bd9Sstevel@tonic-gate printf("skipped %d\n", i); 22477c478bd9Sstevel@tonic-gate continue; 22487c478bd9Sstevel@tonic-gate } 22497c478bd9Sstevel@tonic-gate 22507c478bd9Sstevel@tonic-gate switch (i) { 22518810c16bSdanmcd case SPD_EXT_TUN_NAME: 22528810c16bSdanmcd spd_if = (spd_if_t *)exts[i]; 22538810c16bSdanmcd (void) printf("spd_if = %s\n", spd_if->spd_if_name); 22548810c16bSdanmcd break; 22558810c16bSdanmcd 22567c478bd9Sstevel@tonic-gate case SPD_EXT_ICMP_TYPECODE: 22577c478bd9Sstevel@tonic-gate spd_typecode = (struct spd_typecode *)exts[i]; 22587c478bd9Sstevel@tonic-gate (void) printf("icmp type %d-%d code %d-%d\n", 22597c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_type, 22607c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_type_end, 22617c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_code, 22627c478bd9Sstevel@tonic-gate spd_typecode->spd_typecode_code_end); 22637c478bd9Sstevel@tonic-gate break; 22647c478bd9Sstevel@tonic-gate 22657c478bd9Sstevel@tonic-gate case SPD_EXT_LCLPORT: 22667c478bd9Sstevel@tonic-gate spd_portrange = (struct spd_portrange *)exts[i]; 22677c478bd9Sstevel@tonic-gate (void) printf("local ports %d-%d\n", 22687c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_minport, 22697c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_maxport); 22707c478bd9Sstevel@tonic-gate 22717c478bd9Sstevel@tonic-gate break; 22727c478bd9Sstevel@tonic-gate 22737c478bd9Sstevel@tonic-gate case SPD_EXT_REMPORT: 22747c478bd9Sstevel@tonic-gate spd_portrange = (struct spd_portrange *)exts[i]; 22757c478bd9Sstevel@tonic-gate (void) printf("remote ports %d-%d\n", 22767c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_minport, 22777c478bd9Sstevel@tonic-gate spd_portrange->spd_ports_maxport); 22787c478bd9Sstevel@tonic-gate 22797c478bd9Sstevel@tonic-gate break; 22807c478bd9Sstevel@tonic-gate 22817c478bd9Sstevel@tonic-gate case SPD_EXT_PROTO: 22827c478bd9Sstevel@tonic-gate spd_proto = (struct spd_proto *)exts[i]; 22837c478bd9Sstevel@tonic-gate (void) printf("proto:spd_proto_exttype %d\n", 22847c478bd9Sstevel@tonic-gate spd_proto->spd_proto_exttype); 22857c478bd9Sstevel@tonic-gate (void) printf("proto:spd_proto_number %d\n", 22867c478bd9Sstevel@tonic-gate spd_proto->spd_proto_number); 22877c478bd9Sstevel@tonic-gate break; 22887c478bd9Sstevel@tonic-gate 22897c478bd9Sstevel@tonic-gate case SPD_EXT_LCLADDR: 22907c478bd9Sstevel@tonic-gate case SPD_EXT_REMADDR: 22917c478bd9Sstevel@tonic-gate spd_address = (spd_address_t *)exts[i]; 22927c478bd9Sstevel@tonic-gate if (i == SPD_EXT_LCLADDR) 22937c478bd9Sstevel@tonic-gate (void) printf("local addr "); 22947c478bd9Sstevel@tonic-gate else 22957c478bd9Sstevel@tonic-gate (void) printf("remote addr "); 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate 22987c478bd9Sstevel@tonic-gate (void) printf("%s\n", 22997c478bd9Sstevel@tonic-gate inet_ntop(spd_address->spd_address_af, 2300d5751483Smarkfen (void *) (spd_address +1), abuf, 2301d5751483Smarkfen INET6_ADDRSTRLEN)); 23027c478bd9Sstevel@tonic-gate 23037c478bd9Sstevel@tonic-gate (void) printf("prefixlen: %d\n", 23047c478bd9Sstevel@tonic-gate spd_address->spd_address_prefixlen); 23057c478bd9Sstevel@tonic-gate break; 23067c478bd9Sstevel@tonic-gate 23077c478bd9Sstevel@tonic-gate case SPD_EXT_ACTION: 23087c478bd9Sstevel@tonic-gate spd_ext_actions = (struct spd_ext_actions *)exts[i]; 23097c478bd9Sstevel@tonic-gate (void) printf("spd_ext_action\n"); 23107c478bd9Sstevel@tonic-gate (void) printf("spd_actions_count %d\n", 23117c478bd9Sstevel@tonic-gate spd_ext_actions->spd_actions_count); 23127c478bd9Sstevel@tonic-gate app = (struct spd_attribute *)(spd_ext_actions + 1); 23137c478bd9Sstevel@tonic-gate 23147c478bd9Sstevel@tonic-gate for (act_count = 0; 23157c478bd9Sstevel@tonic-gate act_count < spd_ext_actions->spd_actions_len -1; 23167c478bd9Sstevel@tonic-gate act_count++) { 23177c478bd9Sstevel@tonic-gate (void) printf("\tattr %d: %X-%d\n", act_count, 23187c478bd9Sstevel@tonic-gate app->spd_attr_tag, app->spd_attr_value); 23197c478bd9Sstevel@tonic-gate app++; 23207c478bd9Sstevel@tonic-gate } 23217c478bd9Sstevel@tonic-gate 23227c478bd9Sstevel@tonic-gate break; 23237c478bd9Sstevel@tonic-gate 23247c478bd9Sstevel@tonic-gate case SPD_EXT_RULE: 23257c478bd9Sstevel@tonic-gate spd_rule = (struct spd_rule *)exts[i]; 23267c478bd9Sstevel@tonic-gate (void) printf("spd_rule_priority: 0x%x\n", 23277c478bd9Sstevel@tonic-gate spd_rule->spd_rule_priority); 23287c478bd9Sstevel@tonic-gate (void) printf("spd_rule_flags: %d\n", 23297c478bd9Sstevel@tonic-gate spd_rule->spd_rule_flags); 23307c478bd9Sstevel@tonic-gate break; 23317c478bd9Sstevel@tonic-gate 23327c478bd9Sstevel@tonic-gate case SPD_EXT_RULESET: 23337c478bd9Sstevel@tonic-gate (void) printf("spd_ext_ruleset\n"); 23347c478bd9Sstevel@tonic-gate break; 23357c478bd9Sstevel@tonic-gate default: 23367c478bd9Sstevel@tonic-gate (void) printf("default\n"); 23377c478bd9Sstevel@tonic-gate break; 23387c478bd9Sstevel@tonic-gate } 23397c478bd9Sstevel@tonic-gate } 23407c478bd9Sstevel@tonic-gate 23417c478bd9Sstevel@tonic-gate (void) printf("-------------------\n"); 23427c478bd9Sstevel@tonic-gate (void) printf("=========================\n"); 23437c478bd9Sstevel@tonic-gate } 23447c478bd9Sstevel@tonic-gate #endif /* DEBUG_HEAVY */ 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate static int 23477c478bd9Sstevel@tonic-gate ipsec_conf_view() 23487c478bd9Sstevel@tonic-gate { 23497c478bd9Sstevel@tonic-gate char buf[MAXLEN]; 23507c478bd9Sstevel@tonic-gate FILE *fp; 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate fp = fopen(POLICY_CONF_FILE, "r"); 23537c478bd9Sstevel@tonic-gate if (fp == NULL) { 23547c478bd9Sstevel@tonic-gate if (errno == ENOENT) { 23557c478bd9Sstevel@tonic-gate /* 23567c478bd9Sstevel@tonic-gate * The absence of POLICY_CONF_FILE should 23577c478bd9Sstevel@tonic-gate * not cause the command to exit with a 23587c478bd9Sstevel@tonic-gate * non-zero status, since this condition 23597c478bd9Sstevel@tonic-gate * is valid when no policies were previously 23607c478bd9Sstevel@tonic-gate * defined. 23617c478bd9Sstevel@tonic-gate */ 23627c478bd9Sstevel@tonic-gate return (0); 23637c478bd9Sstevel@tonic-gate } 23647c478bd9Sstevel@tonic-gate warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 23657c478bd9Sstevel@tonic-gate return (-1); 23667c478bd9Sstevel@tonic-gate } 23677c478bd9Sstevel@tonic-gate while (fgets(buf, MAXLEN, fp) != NULL) { 23687c478bd9Sstevel@tonic-gate /* Don't print removed entries */ 23697c478bd9Sstevel@tonic-gate if (*buf == ';') 23707c478bd9Sstevel@tonic-gate continue; 23717c478bd9Sstevel@tonic-gate if (strlen(buf) != 0) 23727c478bd9Sstevel@tonic-gate buf[strlen(buf) - 1] = '\0'; 23737c478bd9Sstevel@tonic-gate (void) puts(buf); 23747c478bd9Sstevel@tonic-gate } 23757c478bd9Sstevel@tonic-gate return (0); 23767c478bd9Sstevel@tonic-gate } 23777c478bd9Sstevel@tonic-gate 23787c478bd9Sstevel@tonic-gate /* 23797c478bd9Sstevel@tonic-gate * Delete nlines from start in the POLICY_CONF_FILE. 23807c478bd9Sstevel@tonic-gate */ 23817c478bd9Sstevel@tonic-gate static int 23827c478bd9Sstevel@tonic-gate delete_from_file(int start, int nlines) 23837c478bd9Sstevel@tonic-gate { 23847c478bd9Sstevel@tonic-gate FILE *fp; 23857c478bd9Sstevel@tonic-gate char ibuf[MAXLEN]; 23867c478bd9Sstevel@tonic-gate int len; 23877c478bd9Sstevel@tonic-gate 23887c478bd9Sstevel@tonic-gate if ((fp = fopen(POLICY_CONF_FILE, "r+b")) == NULL) { 23897c478bd9Sstevel@tonic-gate warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 23907c478bd9Sstevel@tonic-gate return (-1); 23917c478bd9Sstevel@tonic-gate } 23927c478bd9Sstevel@tonic-gate 23937c478bd9Sstevel@tonic-gate /* 23947c478bd9Sstevel@tonic-gate * Insert a ";", read the line and discard it. Repeat 23957c478bd9Sstevel@tonic-gate * this logic nlines - 1 times. For the last line there 23967c478bd9Sstevel@tonic-gate * is just a newline character. We can't just insert a 23977c478bd9Sstevel@tonic-gate * single ";" character instead of the newline character 23987c478bd9Sstevel@tonic-gate * as it would affect the next line. Thus when we comment 23997c478bd9Sstevel@tonic-gate * the last line we seek one less and insert a ";" 24007c478bd9Sstevel@tonic-gate * character, which will replace the newline of the 24017c478bd9Sstevel@tonic-gate * penultimate line with ; and newline of the last line 24027c478bd9Sstevel@tonic-gate * will become part of the previous line. 24037c478bd9Sstevel@tonic-gate */ 24047c478bd9Sstevel@tonic-gate do { 24057c478bd9Sstevel@tonic-gate /* 24067c478bd9Sstevel@tonic-gate * It is not enough to seek just once and expect the 24077c478bd9Sstevel@tonic-gate * subsequent fgets below to take you to the right 24087c478bd9Sstevel@tonic-gate * offset of the next line. fgets below seems to affect 24097c478bd9Sstevel@tonic-gate * the offset. Thus we need to seek, replace with ";", 24107c478bd9Sstevel@tonic-gate * and discard a line using fgets for every line. 24117c478bd9Sstevel@tonic-gate */ 24127c478bd9Sstevel@tonic-gate if (fseek(fp, start, SEEK_SET) == -1) { 24137c478bd9Sstevel@tonic-gate warn("fseek"); 24147c478bd9Sstevel@tonic-gate return (-1); 24157c478bd9Sstevel@tonic-gate } 24167c478bd9Sstevel@tonic-gate if (fputc(';', fp) < 0) { 24177c478bd9Sstevel@tonic-gate warn("fputc"); 24187c478bd9Sstevel@tonic-gate return (-1); 24197c478bd9Sstevel@tonic-gate } 24207c478bd9Sstevel@tonic-gate /* 24217c478bd9Sstevel@tonic-gate * Flush the above ";" character before we do the fgets(). 24227c478bd9Sstevel@tonic-gate * Without this, fgets() gets confused with offsets. 24237c478bd9Sstevel@tonic-gate */ 24247c478bd9Sstevel@tonic-gate (void) fflush(fp); 24257c478bd9Sstevel@tonic-gate len = 0; 24267c478bd9Sstevel@tonic-gate while (fgets(ibuf, MAXLEN, fp) != NULL) { 24277c478bd9Sstevel@tonic-gate len += strlen(ibuf); 24287c478bd9Sstevel@tonic-gate if (ibuf[len - 1] == '\n') { 24297c478bd9Sstevel@tonic-gate /* 24307c478bd9Sstevel@tonic-gate * We have read a complete line. 24317c478bd9Sstevel@tonic-gate */ 24327c478bd9Sstevel@tonic-gate break; 24337c478bd9Sstevel@tonic-gate } 24347c478bd9Sstevel@tonic-gate } 24357c478bd9Sstevel@tonic-gate /* 24367c478bd9Sstevel@tonic-gate * We read the line after ";" character has been inserted. 24377c478bd9Sstevel@tonic-gate * Thus len does not count ";". To advance to the next line 24387c478bd9Sstevel@tonic-gate * increment by 1. 24397c478bd9Sstevel@tonic-gate */ 24407c478bd9Sstevel@tonic-gate start += (len + 1); 24417c478bd9Sstevel@tonic-gate /* 24427c478bd9Sstevel@tonic-gate * If nlines == 2, we will be commenting out the last 24437c478bd9Sstevel@tonic-gate * line next, which has only one newline character. 24447c478bd9Sstevel@tonic-gate * If we blindly replace it with ";", it will be 24457c478bd9Sstevel@tonic-gate * read as part of the next line which could have 24467c478bd9Sstevel@tonic-gate * a INDEX string and thus confusing ipsec_conf_view. 24477c478bd9Sstevel@tonic-gate * Thus, we seek one less and replace the previous 24487c478bd9Sstevel@tonic-gate * line's newline character with ";", and the 24497c478bd9Sstevel@tonic-gate * last line's newline character will become part of 24507c478bd9Sstevel@tonic-gate * the previous line. 24517c478bd9Sstevel@tonic-gate */ 24527c478bd9Sstevel@tonic-gate if (nlines == 2) 24537c478bd9Sstevel@tonic-gate start--; 24547c478bd9Sstevel@tonic-gate } while (--nlines != 0); 24557c478bd9Sstevel@tonic-gate (void) fclose(fp); 24567c478bd9Sstevel@tonic-gate if (nlines != 0) 24577c478bd9Sstevel@tonic-gate return (-1); 24587c478bd9Sstevel@tonic-gate else 24597c478bd9Sstevel@tonic-gate return (0); 24607c478bd9Sstevel@tonic-gate } 24617c478bd9Sstevel@tonic-gate 24627c478bd9Sstevel@tonic-gate /* 24637c478bd9Sstevel@tonic-gate * Delete an entry from the file by inserting a ";" at the 24647c478bd9Sstevel@tonic-gate * beginning of the lines to be removed. 24657c478bd9Sstevel@tonic-gate */ 24667c478bd9Sstevel@tonic-gate static int 24677c478bd9Sstevel@tonic-gate ipsec_conf_del(int policy_index, boolean_t ignore_spd) 24687c478bd9Sstevel@tonic-gate { 24697c478bd9Sstevel@tonic-gate act_prop_t *act_props = malloc(sizeof (act_prop_t)); 24707c478bd9Sstevel@tonic-gate char *buf; 24717c478bd9Sstevel@tonic-gate FILE *fp; 24727c478bd9Sstevel@tonic-gate char ibuf[MAXLEN]; 24737c478bd9Sstevel@tonic-gate int ibuf_len, index_len, index; 24747c478bd9Sstevel@tonic-gate int ret = 0; 24757c478bd9Sstevel@tonic-gate int offset, prev_offset; 24767c478bd9Sstevel@tonic-gate int nlines; 24778810c16bSdanmcd char lifname[LIFNAMSIZ]; 24787c478bd9Sstevel@tonic-gate 24797c478bd9Sstevel@tonic-gate if (act_props == NULL) { 24807c478bd9Sstevel@tonic-gate warn(gettext("memory")); 24817c478bd9Sstevel@tonic-gate return (-1); 24827c478bd9Sstevel@tonic-gate } 24837c478bd9Sstevel@tonic-gate 24847c478bd9Sstevel@tonic-gate fp = fopen(POLICY_CONF_FILE, "r"); 24857c478bd9Sstevel@tonic-gate if (fp == NULL) { 24867c478bd9Sstevel@tonic-gate warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 24877c478bd9Sstevel@tonic-gate free(act_props); 24887c478bd9Sstevel@tonic-gate return (-1); 24897c478bd9Sstevel@tonic-gate } 24907c478bd9Sstevel@tonic-gate 24917c478bd9Sstevel@tonic-gate index_len = strlen(INDEX_TAG); 24927c478bd9Sstevel@tonic-gate index = 0; 24937c478bd9Sstevel@tonic-gate for (offset = prev_offset = 0; fgets(ibuf, MAXLEN, fp) != NULL; 24947c478bd9Sstevel@tonic-gate offset += ibuf_len) { 24957c478bd9Sstevel@tonic-gate prev_offset = offset; 24967c478bd9Sstevel@tonic-gate ibuf_len = strlen(ibuf); 24977c478bd9Sstevel@tonic-gate 24987c478bd9Sstevel@tonic-gate if (strncmp(ibuf, INDEX_TAG, index_len) != 0) { 24997c478bd9Sstevel@tonic-gate continue; 25007c478bd9Sstevel@tonic-gate } 25017c478bd9Sstevel@tonic-gate 25027c478bd9Sstevel@tonic-gate /* 25037c478bd9Sstevel@tonic-gate * This line contains INDEX_TAG 25047c478bd9Sstevel@tonic-gate */ 25057c478bd9Sstevel@tonic-gate buf = ibuf + index_len; 25067c478bd9Sstevel@tonic-gate buf++; /* Skip the space */ 25078810c16bSdanmcd index = parse_index(buf, lifname); 25087c478bd9Sstevel@tonic-gate if (index == -1) { 25097c478bd9Sstevel@tonic-gate warnx(gettext("Invalid index in the file")); 25107c478bd9Sstevel@tonic-gate free(act_props); 25117c478bd9Sstevel@tonic-gate return (-1); 25127c478bd9Sstevel@tonic-gate } 25138810c16bSdanmcd if (index == policy_index && 25148810c16bSdanmcd (interface_name == NULL || 2515d5751483Smarkfen strncmp(interface_name, lifname, LIFNAMSIZ) == 0)) { 25167c478bd9Sstevel@tonic-gate if (!ignore_spd) { 25177c478bd9Sstevel@tonic-gate ret = parse_one(fp, act_props); 25187c478bd9Sstevel@tonic-gate if (ret == -1) { 25197c478bd9Sstevel@tonic-gate warnx(gettext("Invalid policy entry " 25207c478bd9Sstevel@tonic-gate "in the file")); 25217c478bd9Sstevel@tonic-gate free(act_props); 25227c478bd9Sstevel@tonic-gate return (-1); 25237c478bd9Sstevel@tonic-gate } 25247c478bd9Sstevel@tonic-gate } 25257c478bd9Sstevel@tonic-gate /* 25267c478bd9Sstevel@tonic-gate * nlines is the number of lines we should comment 25277c478bd9Sstevel@tonic-gate * out. linecount tells us how many lines this command 25287c478bd9Sstevel@tonic-gate * spans. And we need to remove the line with INDEX 25297c478bd9Sstevel@tonic-gate * and an extra line we added during ipsec_conf_add. 25307c478bd9Sstevel@tonic-gate * 25317c478bd9Sstevel@tonic-gate * NOTE : If somebody added a policy entry which does 25327c478bd9Sstevel@tonic-gate * not have a newline, ipsec_conf_add() fills in the 25337c478bd9Sstevel@tonic-gate * newline. Hence, there is always 2 extra lines 25347c478bd9Sstevel@tonic-gate * to delete. 25357c478bd9Sstevel@tonic-gate */ 25367c478bd9Sstevel@tonic-gate nlines = linecount + 2; 25377c478bd9Sstevel@tonic-gate goto delete; 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate } 25407c478bd9Sstevel@tonic-gate 25417c478bd9Sstevel@tonic-gate if (!ignore_spd) 25427c478bd9Sstevel@tonic-gate ret = pfp_delete_rule(policy_index); 25437c478bd9Sstevel@tonic-gate 25447c478bd9Sstevel@tonic-gate if (ret != 0) { 25457c478bd9Sstevel@tonic-gate warnx(gettext("Deletion incomplete. Please " 25467c478bd9Sstevel@tonic-gate "flush all the entries and re-configure :")); 25477c478bd9Sstevel@tonic-gate reconfigure(); 25487c478bd9Sstevel@tonic-gate free(act_props); 25497c478bd9Sstevel@tonic-gate return (ret); 25507c478bd9Sstevel@tonic-gate } 25517c478bd9Sstevel@tonic-gate free(act_props); 25527c478bd9Sstevel@tonic-gate return (ret); 25537c478bd9Sstevel@tonic-gate 25547c478bd9Sstevel@tonic-gate delete: 25557c478bd9Sstevel@tonic-gate /* Delete nlines from prev_offset */ 25567c478bd9Sstevel@tonic-gate (void) fclose(fp); 25577c478bd9Sstevel@tonic-gate ret = delete_from_file(prev_offset, nlines); 25587c478bd9Sstevel@tonic-gate 25597c478bd9Sstevel@tonic-gate if (ret != 0) { 25607c478bd9Sstevel@tonic-gate warnx(gettext("Deletion incomplete. Please " 25617c478bd9Sstevel@tonic-gate "flush all the entries and re-configure :")); 25627c478bd9Sstevel@tonic-gate reconfigure(); 25637c478bd9Sstevel@tonic-gate free(act_props); 25647c478bd9Sstevel@tonic-gate return (ret); 25657c478bd9Sstevel@tonic-gate } 25667c478bd9Sstevel@tonic-gate 25677c478bd9Sstevel@tonic-gate if (!ignore_spd) 25687c478bd9Sstevel@tonic-gate ret = pfp_delete_rule(policy_index); 25697c478bd9Sstevel@tonic-gate 25707c478bd9Sstevel@tonic-gate if (ret != 0) { 25717c478bd9Sstevel@tonic-gate warnx(gettext("Deletion incomplete. Please " 25727c478bd9Sstevel@tonic-gate "flush all the entries and re-configure :")); 25737c478bd9Sstevel@tonic-gate reconfigure(); 25747c478bd9Sstevel@tonic-gate free(act_props); 25757c478bd9Sstevel@tonic-gate return (ret); 25767c478bd9Sstevel@tonic-gate } 25777c478bd9Sstevel@tonic-gate free(act_props); 25787c478bd9Sstevel@tonic-gate return (0); 25797c478bd9Sstevel@tonic-gate } 25807c478bd9Sstevel@tonic-gate 25817c478bd9Sstevel@tonic-gate static int 25827c478bd9Sstevel@tonic-gate pfp_delete_rule(uint64_t index) 25837c478bd9Sstevel@tonic-gate { 25847c478bd9Sstevel@tonic-gate struct spd_msg *msg; 25857c478bd9Sstevel@tonic-gate struct spd_rule *rule; 2586e3320f40Smarkfen int sfd; 25878810c16bSdanmcd int cnt, len, alloclen; 25887c478bd9Sstevel@tonic-gate 2589e3320f40Smarkfen sfd = get_pf_pol_socket(); 25907c478bd9Sstevel@tonic-gate if (sfd < 0) { 25917c478bd9Sstevel@tonic-gate warn(gettext("unable to open policy socket")); 25927c478bd9Sstevel@tonic-gate return (-1); 25937c478bd9Sstevel@tonic-gate } 25947c478bd9Sstevel@tonic-gate 25958810c16bSdanmcd /* 25968810c16bSdanmcd * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation 25978810c16bSdanmcd * issues. 25988810c16bSdanmcd */ 25998810c16bSdanmcd alloclen = sizeof (spd_msg_t) + sizeof (struct spd_rule) + 26008810c16bSdanmcd sizeof (spd_if_t) + LIFNAMSIZ + 8; 26018810c16bSdanmcd msg = (spd_msg_t *)malloc(alloclen); 26027c478bd9Sstevel@tonic-gate 26037c478bd9Sstevel@tonic-gate if (msg == NULL) { 26047c478bd9Sstevel@tonic-gate warn("malloc"); 26057c478bd9Sstevel@tonic-gate return (-1); 26067c478bd9Sstevel@tonic-gate } 26077c478bd9Sstevel@tonic-gate 26087c478bd9Sstevel@tonic-gate rule = (struct spd_rule *)(msg + 1); 26097c478bd9Sstevel@tonic-gate 26108810c16bSdanmcd (void) memset(msg, 0, alloclen); 26117c478bd9Sstevel@tonic-gate msg->spd_msg_version = PF_POLICY_V1; 26127c478bd9Sstevel@tonic-gate msg->spd_msg_type = SPD_DELETERULE; 26137c478bd9Sstevel@tonic-gate msg->spd_msg_len = SPD_8TO64(sizeof (spd_msg_t) 26147c478bd9Sstevel@tonic-gate + sizeof (struct spd_rule)); 26157c478bd9Sstevel@tonic-gate 26167c478bd9Sstevel@tonic-gate rule->spd_rule_type = SPD_EXT_RULE; 26177c478bd9Sstevel@tonic-gate rule->spd_rule_len = SPD_8TO64(sizeof (struct spd_rule)); 26187c478bd9Sstevel@tonic-gate rule->spd_rule_index = index; 26197c478bd9Sstevel@tonic-gate 26208810c16bSdanmcd msg->spd_msg_len += attach_tunname((spd_if_t *)(rule + 1)); 26217c478bd9Sstevel@tonic-gate 26228810c16bSdanmcd len = SPD_64TO8(msg->spd_msg_len); 26238810c16bSdanmcd cnt = write(sfd, msg, len); 26248810c16bSdanmcd 26258810c16bSdanmcd if (cnt != len) { 26267c478bd9Sstevel@tonic-gate if (cnt < 0) { 26277c478bd9Sstevel@tonic-gate (void) close(sfd); 26287c478bd9Sstevel@tonic-gate free(msg); 26297c478bd9Sstevel@tonic-gate warn(gettext("Delete failed: write")); 26307c478bd9Sstevel@tonic-gate return (-1); 26317c478bd9Sstevel@tonic-gate } else { 26327c478bd9Sstevel@tonic-gate (void) close(sfd); 26337c478bd9Sstevel@tonic-gate free(msg); 26347c478bd9Sstevel@tonic-gate warnx(gettext("Delete failed: short write")); 26357c478bd9Sstevel@tonic-gate return (-1); 26367c478bd9Sstevel@tonic-gate } 26377c478bd9Sstevel@tonic-gate } 26387c478bd9Sstevel@tonic-gate 26398810c16bSdanmcd cnt = read(sfd, msg, len); 26408810c16bSdanmcd if (cnt != len) { 26417c478bd9Sstevel@tonic-gate if (cnt < 0) { 26427c478bd9Sstevel@tonic-gate (void) close(sfd); 26437c478bd9Sstevel@tonic-gate free(msg); 26447c478bd9Sstevel@tonic-gate warn(gettext("Delete failed: read")); 26457c478bd9Sstevel@tonic-gate return (-1); 26467c478bd9Sstevel@tonic-gate } else { 26477c478bd9Sstevel@tonic-gate (void) close(sfd); 26487c478bd9Sstevel@tonic-gate free(msg); 26497c478bd9Sstevel@tonic-gate warnx(gettext("Delete failed while reading reply")); 26507c478bd9Sstevel@tonic-gate return (-1); 26517c478bd9Sstevel@tonic-gate } 26527c478bd9Sstevel@tonic-gate } 26537c478bd9Sstevel@tonic-gate (void) close(sfd); 26547c478bd9Sstevel@tonic-gate if (msg->spd_msg_errno != 0) { 26557c478bd9Sstevel@tonic-gate free(msg); 26567c478bd9Sstevel@tonic-gate errno = msg->spd_msg_errno; 26577c478bd9Sstevel@tonic-gate warn(gettext("Delete failed: SPD_FLUSH")); 26587c478bd9Sstevel@tonic-gate return (-1); 26597c478bd9Sstevel@tonic-gate } 26607c478bd9Sstevel@tonic-gate 26617c478bd9Sstevel@tonic-gate free(msg); 26627c478bd9Sstevel@tonic-gate return (0); 26637c478bd9Sstevel@tonic-gate } 26647c478bd9Sstevel@tonic-gate 26657c478bd9Sstevel@tonic-gate static int 26667c478bd9Sstevel@tonic-gate ipsec_conf_flush(int db) 26677c478bd9Sstevel@tonic-gate { 26688810c16bSdanmcd int pfd, cnt, len; 2669e3320f40Smarkfen int sfd; 26708810c16bSdanmcd struct spd_msg *msg; 26718810c16bSdanmcd /* 26728810c16bSdanmcd * Add an extra 8 bytes of space (+1 uint64_t) to avoid truncation 26738810c16bSdanmcd * issues. 26748810c16bSdanmcd */ 26758810c16bSdanmcd uint64_t buffer[ 26768810c16bSdanmcd SPD_8TO64(sizeof (*msg) + sizeof (spd_if_t) + LIFNAMSIZ) + 1]; 26777c478bd9Sstevel@tonic-gate 2678e3320f40Smarkfen sfd = get_pf_pol_socket(); 26797c478bd9Sstevel@tonic-gate if (sfd < 0) { 26807c478bd9Sstevel@tonic-gate warn(gettext("unable to open policy socket")); 26817c478bd9Sstevel@tonic-gate return (-1); 26827c478bd9Sstevel@tonic-gate } 26837c478bd9Sstevel@tonic-gate 26848810c16bSdanmcd (void) memset(buffer, 0, sizeof (buffer)); 26858810c16bSdanmcd msg = (struct spd_msg *)buffer; 26868810c16bSdanmcd msg->spd_msg_version = PF_POLICY_V1; 26878810c16bSdanmcd msg->spd_msg_type = SPD_FLUSH; 26888810c16bSdanmcd msg->spd_msg_len = SPD_8TO64(sizeof (*msg)); 26898810c16bSdanmcd msg->spd_msg_spdid = db; 26907c478bd9Sstevel@tonic-gate 26918810c16bSdanmcd msg->spd_msg_len += attach_tunname((spd_if_t *)(msg + 1)); 26928810c16bSdanmcd 26938810c16bSdanmcd len = SPD_64TO8(msg->spd_msg_len); 26948810c16bSdanmcd cnt = write(sfd, msg, len); 26958810c16bSdanmcd if (cnt != len) { 26967c478bd9Sstevel@tonic-gate if (cnt < 0) { 26977c478bd9Sstevel@tonic-gate warn(gettext("Flush failed: write")); 26987c478bd9Sstevel@tonic-gate return (-1); 26997c478bd9Sstevel@tonic-gate } else { 27007c478bd9Sstevel@tonic-gate warnx(gettext("Flush failed: short write")); 27017c478bd9Sstevel@tonic-gate return (-1); 27027c478bd9Sstevel@tonic-gate } 27037c478bd9Sstevel@tonic-gate } 27047c478bd9Sstevel@tonic-gate 27058810c16bSdanmcd cnt = read(sfd, msg, len); 27068810c16bSdanmcd if (cnt != len) { 27077c478bd9Sstevel@tonic-gate if (cnt < 0) { 27087c478bd9Sstevel@tonic-gate warn(gettext("Flush failed: read")); 27097c478bd9Sstevel@tonic-gate return (-1); 27107c478bd9Sstevel@tonic-gate } else { 27117c478bd9Sstevel@tonic-gate warnx(gettext("Flush failed while reading reply")); 27127c478bd9Sstevel@tonic-gate return (-1); 27137c478bd9Sstevel@tonic-gate } 27147c478bd9Sstevel@tonic-gate } 27157c478bd9Sstevel@tonic-gate (void) close(sfd); 27168810c16bSdanmcd if (msg->spd_msg_errno != 0) { 27177c478bd9Sstevel@tonic-gate warnx("%s: %s", gettext("Flush failed: SPD_FLUSH"), 27188810c16bSdanmcd sys_error_message(msg->spd_msg_errno)); 27197c478bd9Sstevel@tonic-gate return (-1); 27207c478bd9Sstevel@tonic-gate } 27217c478bd9Sstevel@tonic-gate 27227c478bd9Sstevel@tonic-gate /* Truncate the file */ 27237c478bd9Sstevel@tonic-gate if (db == SPD_ACTIVE) { 27247c478bd9Sstevel@tonic-gate if ((pfd = open(POLICY_CONF_FILE, O_TRUNC|O_RDWR)) == -1) { 27257c478bd9Sstevel@tonic-gate if (errno == ENOENT) { 27267c478bd9Sstevel@tonic-gate /* 27277c478bd9Sstevel@tonic-gate * The absence of POLICY_CONF_FILE should 27287c478bd9Sstevel@tonic-gate * not cause the command to exit with a 27297c478bd9Sstevel@tonic-gate * non-zero status, since this condition 27307c478bd9Sstevel@tonic-gate * is valid when no policies were previously 27317c478bd9Sstevel@tonic-gate * defined. 27327c478bd9Sstevel@tonic-gate */ 27337c478bd9Sstevel@tonic-gate return (0); 27347c478bd9Sstevel@tonic-gate } 27357c478bd9Sstevel@tonic-gate warn(gettext("%s cannot be truncated"), 27367c478bd9Sstevel@tonic-gate POLICY_CONF_FILE); 27377c478bd9Sstevel@tonic-gate return (-1); 27387c478bd9Sstevel@tonic-gate } 27397c478bd9Sstevel@tonic-gate (void) close(pfd); 27407c478bd9Sstevel@tonic-gate } 27417c478bd9Sstevel@tonic-gate return (0); 27427c478bd9Sstevel@tonic-gate } 27437c478bd9Sstevel@tonic-gate 27448810c16bSdanmcd /* 27458810c16bSdanmcd * function to send SPD_FLIP and SPD_CLONE messages 27468810c16bSdanmcd * Do it for ALL polheads for simplicity's sake. 27478810c16bSdanmcd */ 27487c478bd9Sstevel@tonic-gate static void 27497c478bd9Sstevel@tonic-gate ipsec_conf_admin(uint8_t type) 27507c478bd9Sstevel@tonic-gate { 27517c478bd9Sstevel@tonic-gate int cnt; 2752e3320f40Smarkfen int sfd; 27538810c16bSdanmcd struct spd_msg *msg; 27548810c16bSdanmcd uint64_t buffer[ 27558810c16bSdanmcd SPD_8TO64(sizeof (struct spd_msg) + sizeof (spd_if_t))]; 27568810c16bSdanmcd char *save_ifname; 27577c478bd9Sstevel@tonic-gate 2758e3320f40Smarkfen sfd = get_pf_pol_socket(); 27597c478bd9Sstevel@tonic-gate if (sfd < 0) { 27607c478bd9Sstevel@tonic-gate err(-1, gettext("unable to open policy socket")); 27617c478bd9Sstevel@tonic-gate } 27627c478bd9Sstevel@tonic-gate 27638810c16bSdanmcd (void) memset(buffer, 0, sizeof (buffer)); 27648810c16bSdanmcd msg = (struct spd_msg *)buffer; 27658810c16bSdanmcd msg->spd_msg_version = PF_POLICY_V1; 27668810c16bSdanmcd msg->spd_msg_type = type; 27678810c16bSdanmcd msg->spd_msg_len = SPD_8TO64(sizeof (buffer)); 27687c478bd9Sstevel@tonic-gate 27698810c16bSdanmcd save_ifname = interface_name; 27708810c16bSdanmcd /* Apply to all policy heads - global and tunnels. */ 27718810c16bSdanmcd interface_name = &all_polheads; 27728810c16bSdanmcd (void) attach_tunname((spd_if_t *)(msg + 1)); 27738810c16bSdanmcd interface_name = save_ifname; 27748810c16bSdanmcd 27758810c16bSdanmcd cnt = write(sfd, msg, sizeof (buffer)); 27768810c16bSdanmcd if (cnt != sizeof (buffer)) { 27777c478bd9Sstevel@tonic-gate if (cnt < 0) { 27787c478bd9Sstevel@tonic-gate err(-1, gettext("admin failed: write")); 27797c478bd9Sstevel@tonic-gate } else { 27807c478bd9Sstevel@tonic-gate errx(-1, gettext("admin failed: short write")); 27817c478bd9Sstevel@tonic-gate } 27827c478bd9Sstevel@tonic-gate } 27837c478bd9Sstevel@tonic-gate 27848810c16bSdanmcd cnt = read(sfd, msg, sizeof (buffer)); 27858810c16bSdanmcd if (cnt != sizeof (buffer)) { 27867c478bd9Sstevel@tonic-gate if (cnt < 0) { 27877c478bd9Sstevel@tonic-gate err(-1, gettext("admin failed: read")); 27887c478bd9Sstevel@tonic-gate } else { 27897c478bd9Sstevel@tonic-gate errx(-1, gettext("admin failed while reading reply")); 27907c478bd9Sstevel@tonic-gate } 27917c478bd9Sstevel@tonic-gate } 27927c478bd9Sstevel@tonic-gate (void) close(sfd); 27938810c16bSdanmcd if (msg->spd_msg_errno != 0) { 27948810c16bSdanmcd errno = msg->spd_msg_errno; 27957c478bd9Sstevel@tonic-gate err(-1, gettext("admin failed")); 27967c478bd9Sstevel@tonic-gate } 27977c478bd9Sstevel@tonic-gate } 27987c478bd9Sstevel@tonic-gate 27997c478bd9Sstevel@tonic-gate static void 28007c478bd9Sstevel@tonic-gate reconfigure() 28017c478bd9Sstevel@tonic-gate { 28027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2803d5751483Smarkfen "\tipsecconf -f \n " 2804d5751483Smarkfen "\tipsecconf -a policy_file\n")); 28057c478bd9Sstevel@tonic-gate } 28067c478bd9Sstevel@tonic-gate 28077c478bd9Sstevel@tonic-gate static void 28087c478bd9Sstevel@tonic-gate usage(void) 28097c478bd9Sstevel@tonic-gate { 28107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 28118810c16bSdanmcd "Usage: ipsecconf\n" 28128810c16bSdanmcd "\tipsecconf -a ([-]|<filename>) [-q]\n" 2813e3320f40Smarkfen "\tipsecconf -c <filename>\n" 28148810c16bSdanmcd "\tipsecconf -r ([-]|<filename>) [-q]\n" 28158810c16bSdanmcd "\tipsecconf -d [-i tunnel-interface] <index>\n" 28168810c16bSdanmcd "\tipsecconf -d <tunnel-interface,index>\n" 28178810c16bSdanmcd "\tipsecconf -l [-n] [-i tunnel-interface]\n" 28188810c16bSdanmcd "\tipsecconf -f [-i tunnel-interface]\n" 28198810c16bSdanmcd "\tipsecconf -L [-n]\n" 28208810c16bSdanmcd "\tipsecconf -F\n")); 28217c478bd9Sstevel@tonic-gate } 28227c478bd9Sstevel@tonic-gate 28237c478bd9Sstevel@tonic-gate /* 28247c478bd9Sstevel@tonic-gate * a type consists of 28257c478bd9Sstevel@tonic-gate * "type" <int>{ "-" <int>} 28267c478bd9Sstevel@tonic-gate * or 28277c478bd9Sstevel@tonic-gate * "type" keyword 28287c478bd9Sstevel@tonic-gate * 28297c478bd9Sstevel@tonic-gate * a code consists of 28307c478bd9Sstevel@tonic-gate * "code" <int>{ "-" <int>} 28317c478bd9Sstevel@tonic-gate * or 28327c478bd9Sstevel@tonic-gate * "code" keyword 28337c478bd9Sstevel@tonic-gate */ 28347c478bd9Sstevel@tonic-gate 28357c478bd9Sstevel@tonic-gate 28367c478bd9Sstevel@tonic-gate static int 28377c478bd9Sstevel@tonic-gate parse_type_code(const char *str, const str_val_t *table) 28387c478bd9Sstevel@tonic-gate { 28397c478bd9Sstevel@tonic-gate char *end1, *end2; 28407c478bd9Sstevel@tonic-gate int res1 = 0, res2 = 0; 28417c478bd9Sstevel@tonic-gate int i; 28427c478bd9Sstevel@tonic-gate 28437c478bd9Sstevel@tonic-gate if (isdigit(str[0])) { 28447c478bd9Sstevel@tonic-gate res1 = strtol(str, &end1, 0); 28457c478bd9Sstevel@tonic-gate 28467c478bd9Sstevel@tonic-gate if (end1 == str) { 28477c478bd9Sstevel@tonic-gate return (-1); 28487c478bd9Sstevel@tonic-gate } 28497c478bd9Sstevel@tonic-gate 28507c478bd9Sstevel@tonic-gate if (res1 > 255 || res1 < 0) { 28517c478bd9Sstevel@tonic-gate return (-1); 28527c478bd9Sstevel@tonic-gate } 28537c478bd9Sstevel@tonic-gate 28547c478bd9Sstevel@tonic-gate if (*end1 == '-') { 28557c478bd9Sstevel@tonic-gate end1++; 28567c478bd9Sstevel@tonic-gate res2 = strtol(end1, &end2, 0); 28577c478bd9Sstevel@tonic-gate if (res2 > 255 || res2 < 0) { 28587c478bd9Sstevel@tonic-gate return (-1); 28597c478bd9Sstevel@tonic-gate } 28607c478bd9Sstevel@tonic-gate } else { 28617c478bd9Sstevel@tonic-gate end2 = end1; 28627c478bd9Sstevel@tonic-gate } 28637c478bd9Sstevel@tonic-gate 28647c478bd9Sstevel@tonic-gate while (isspace(*end2)) 28657c478bd9Sstevel@tonic-gate end2++; 28667c478bd9Sstevel@tonic-gate 28677c478bd9Sstevel@tonic-gate if (*end2 != '\0') { 28687c478bd9Sstevel@tonic-gate return (-1); 28697c478bd9Sstevel@tonic-gate } 28707c478bd9Sstevel@tonic-gate 28717c478bd9Sstevel@tonic-gate return (res1 + (res2 << 8)); 28727c478bd9Sstevel@tonic-gate } 28737c478bd9Sstevel@tonic-gate 28747c478bd9Sstevel@tonic-gate for (i = 0; table[i].string; i++) { 28757c478bd9Sstevel@tonic-gate if (strcmp(str, table[i].string) == 0) { 28767c478bd9Sstevel@tonic-gate return (table[i].value); 28777c478bd9Sstevel@tonic-gate } 28787c478bd9Sstevel@tonic-gate } 28797c478bd9Sstevel@tonic-gate 28807c478bd9Sstevel@tonic-gate return (-1); 28817c478bd9Sstevel@tonic-gate } 28827c478bd9Sstevel@tonic-gate 28837c478bd9Sstevel@tonic-gate static int 28847c478bd9Sstevel@tonic-gate parse_int(const char *str) 28857c478bd9Sstevel@tonic-gate { 28867c478bd9Sstevel@tonic-gate char *end; 28877c478bd9Sstevel@tonic-gate int res; 28887c478bd9Sstevel@tonic-gate 28897c478bd9Sstevel@tonic-gate res = strtol(str, &end, 0); 28907c478bd9Sstevel@tonic-gate if (end == str) 28917c478bd9Sstevel@tonic-gate return (-1); 28927c478bd9Sstevel@tonic-gate while (isspace(*end)) 28937c478bd9Sstevel@tonic-gate end++; 28947c478bd9Sstevel@tonic-gate if (*end != '\0') 28957c478bd9Sstevel@tonic-gate return (-1); 28967c478bd9Sstevel@tonic-gate return (res); 28977c478bd9Sstevel@tonic-gate } 28987c478bd9Sstevel@tonic-gate 28997c478bd9Sstevel@tonic-gate /* 29008810c16bSdanmcd * Parses <interface>,<index>. Sets iname or the global interface_name (if 29018810c16bSdanmcd * iname == NULL) to <interface> and returns <index>. Calls exit() if we have 29028810c16bSdanmcd * an interface_name already set. 29037c478bd9Sstevel@tonic-gate */ 29048810c16bSdanmcd static int 29058810c16bSdanmcd parse_index(const char *str, char *iname) 29067c478bd9Sstevel@tonic-gate { 29078810c16bSdanmcd char *intf, *num, *copy; 29088810c16bSdanmcd int rc; 29097c478bd9Sstevel@tonic-gate 29108810c16bSdanmcd copy = strdup(str); 29118810c16bSdanmcd if (copy == NULL) { 2912e3320f40Smarkfen EXIT_FATAL("Out of memory."); 29137c478bd9Sstevel@tonic-gate } 29148810c16bSdanmcd 29158810c16bSdanmcd intf = strtok(copy, ","); 29168810c16bSdanmcd /* Just want the rest of the string unmolested, so use "" for arg2. */ 29178810c16bSdanmcd num = strtok(NULL, ""); 29188810c16bSdanmcd if (num == NULL) { 29198810c16bSdanmcd /* No comma found, just parse it like an int. */ 29208810c16bSdanmcd free(copy); 29218810c16bSdanmcd return (parse_int(str)); 29227c478bd9Sstevel@tonic-gate } 29238810c16bSdanmcd 29248810c16bSdanmcd if (iname != NULL) { 29258810c16bSdanmcd (void) strlcpy(iname, intf, LIFNAMSIZ); 29268810c16bSdanmcd } else { 29278810c16bSdanmcd if (interface_name != NULL) { 2928e3320f40Smarkfen EXIT_FATAL("Interface name already selected"); 29298810c16bSdanmcd } 29308810c16bSdanmcd 29318810c16bSdanmcd interface_name = strdup(intf); 29328810c16bSdanmcd if (interface_name == NULL) { 2933e3320f40Smarkfen EXIT_FATAL("Out of memory."); 29348810c16bSdanmcd } 29357c478bd9Sstevel@tonic-gate } 29368810c16bSdanmcd 29378810c16bSdanmcd rc = parse_int(num); 29388810c16bSdanmcd free(copy); 29398810c16bSdanmcd return (rc); 29407c478bd9Sstevel@tonic-gate } 29417c478bd9Sstevel@tonic-gate 29427c478bd9Sstevel@tonic-gate /* 29438810c16bSdanmcd * Convert a mask to a prefix length. 29448810c16bSdanmcd * Returns prefix length on success, -1 otherwise. 29457c478bd9Sstevel@tonic-gate */ 29467c478bd9Sstevel@tonic-gate static int 29478810c16bSdanmcd in_getprefixlen(char *mask) 29487c478bd9Sstevel@tonic-gate { 29498810c16bSdanmcd int prefixlen; 29508810c16bSdanmcd char *end; 29517c478bd9Sstevel@tonic-gate 29528810c16bSdanmcd prefixlen = (int)strtol(mask, &end, 10); 29538810c16bSdanmcd if (prefixlen < 0) { 29548810c16bSdanmcd return (-1); 29557c478bd9Sstevel@tonic-gate } 29568810c16bSdanmcd if (mask == end) { 29578810c16bSdanmcd return (-1); 29587c478bd9Sstevel@tonic-gate } 29598810c16bSdanmcd if (*end != '\0') { 29608810c16bSdanmcd return (-1); 29617c478bd9Sstevel@tonic-gate } 29628810c16bSdanmcd return (prefixlen); 29637c478bd9Sstevel@tonic-gate } 29647c478bd9Sstevel@tonic-gate 29657c478bd9Sstevel@tonic-gate /* 29667c478bd9Sstevel@tonic-gate * Convert a prefix length to a mask. 29677c478bd9Sstevel@tonic-gate * Assumes the mask array is zero'ed by the caller. 29687c478bd9Sstevel@tonic-gate */ 29697c478bd9Sstevel@tonic-gate static void 29707c478bd9Sstevel@tonic-gate in_prefixlentomask(unsigned int prefixlen, uchar_t *mask) 29717c478bd9Sstevel@tonic-gate { 29727c478bd9Sstevel@tonic-gate while (prefixlen > 0) { 29737c478bd9Sstevel@tonic-gate if (prefixlen >= 8) { 29747c478bd9Sstevel@tonic-gate *mask++ = 0xFF; 29757c478bd9Sstevel@tonic-gate prefixlen -= 8; 29767c478bd9Sstevel@tonic-gate continue; 29777c478bd9Sstevel@tonic-gate } 29787c478bd9Sstevel@tonic-gate *mask |= 1 << (8 - prefixlen); 29797c478bd9Sstevel@tonic-gate prefixlen--; 29807c478bd9Sstevel@tonic-gate } 29817c478bd9Sstevel@tonic-gate } 29827c478bd9Sstevel@tonic-gate 29837c478bd9Sstevel@tonic-gate 29847c478bd9Sstevel@tonic-gate static int 29857c478bd9Sstevel@tonic-gate parse_address(int type, char *addr_str) 29867c478bd9Sstevel@tonic-gate { 29877c478bd9Sstevel@tonic-gate char *ptr; 29888810c16bSdanmcd int prefix_len = 0; 29897c478bd9Sstevel@tonic-gate struct netent *ne = NULL; 29907c478bd9Sstevel@tonic-gate struct hostent *hp = NULL; 29917c478bd9Sstevel@tonic-gate int h_errno; 29927c478bd9Sstevel@tonic-gate struct in_addr netaddr; 29937c478bd9Sstevel@tonic-gate struct in6_addr *netaddr6; 29947c478bd9Sstevel@tonic-gate struct hostent *ne_hent; 29957c478bd9Sstevel@tonic-gate boolean_t has_mask = B_FALSE; 29967c478bd9Sstevel@tonic-gate 29977c478bd9Sstevel@tonic-gate ptr = strchr(addr_str, '/'); 29987c478bd9Sstevel@tonic-gate if (ptr != NULL) { 29997c478bd9Sstevel@tonic-gate has_mask = B_TRUE; 30007c478bd9Sstevel@tonic-gate *ptr++ = NULL; 30017c478bd9Sstevel@tonic-gate 30027c478bd9Sstevel@tonic-gate prefix_len = in_getprefixlen(ptr); 30038810c16bSdanmcd if (prefix_len < 0) 30047c478bd9Sstevel@tonic-gate return (-1); 30057c478bd9Sstevel@tonic-gate } 30067c478bd9Sstevel@tonic-gate 30077c478bd9Sstevel@tonic-gate /* 30087c478bd9Sstevel@tonic-gate * getipnodebyname() is thread safe. This allows us to hold on to the 30097c478bd9Sstevel@tonic-gate * returned hostent structure, which is pointed to by the shp and 30107c478bd9Sstevel@tonic-gate * dhp globals for the source and destination addresses, respectively. 30117c478bd9Sstevel@tonic-gate */ 30127c478bd9Sstevel@tonic-gate hp = getipnodebyname(addr_str, AF_INET6, AI_DEFAULT | AI_ALL, &h_errno); 30137c478bd9Sstevel@tonic-gate if (hp != NULL) { 30147c478bd9Sstevel@tonic-gate /* 30157c478bd9Sstevel@tonic-gate * We come here for both a hostname and 30167c478bd9Sstevel@tonic-gate * any host address /network address. 30177c478bd9Sstevel@tonic-gate */ 30187c478bd9Sstevel@tonic-gate assert(hp->h_addrtype == AF_INET6); 30197c478bd9Sstevel@tonic-gate } else if ((ne = getnetbyname(addr_str)) != NULL) { 30207c478bd9Sstevel@tonic-gate switch (ne->n_addrtype) { 30217c478bd9Sstevel@tonic-gate case AF_INET: 30227c478bd9Sstevel@tonic-gate /* 30237c478bd9Sstevel@tonic-gate * Allocate a struct hostent and initialize 30247c478bd9Sstevel@tonic-gate * it with the address corresponding to the 30257c478bd9Sstevel@tonic-gate * network number previously returned by 30267c478bd9Sstevel@tonic-gate * getnetbyname(). Freed by do_address_adds() 30277c478bd9Sstevel@tonic-gate * once the policy is defined. 30287c478bd9Sstevel@tonic-gate */ 30297c478bd9Sstevel@tonic-gate ne_hent = malloc(sizeof (struct hostent)); 30307c478bd9Sstevel@tonic-gate if (ne_hent == NULL) { 30317c478bd9Sstevel@tonic-gate warn("malloc"); 30327c478bd9Sstevel@tonic-gate return (-1); 30337c478bd9Sstevel@tonic-gate } 30347c478bd9Sstevel@tonic-gate ne_hent->h_addr_list = malloc(2*sizeof (char *)); 30357c478bd9Sstevel@tonic-gate if (ne_hent->h_addr_list == NULL) { 30367c478bd9Sstevel@tonic-gate warn("malloc"); 30377c478bd9Sstevel@tonic-gate free(ne_hent); 30387c478bd9Sstevel@tonic-gate return (-1); 30397c478bd9Sstevel@tonic-gate } 30407c478bd9Sstevel@tonic-gate netaddr6 = malloc(sizeof (struct in6_addr)); 30417c478bd9Sstevel@tonic-gate if (netaddr6 == NULL) { 30427c478bd9Sstevel@tonic-gate warn("malloc"); 30437c478bd9Sstevel@tonic-gate free(ne_hent->h_addr_list); 30447c478bd9Sstevel@tonic-gate free(ne_hent); 30457c478bd9Sstevel@tonic-gate return (-1); 30467c478bd9Sstevel@tonic-gate } 30477c478bd9Sstevel@tonic-gate ne_hent->h_addr_list[0] = (char *)netaddr6; 30487c478bd9Sstevel@tonic-gate ne_hent->h_addr_list[1] = NULL; 30497c478bd9Sstevel@tonic-gate netaddr = inet_makeaddr(ne->n_net, INADDR_ANY); 30507c478bd9Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&netaddr, netaddr6); 30517c478bd9Sstevel@tonic-gate hp = ne_hent; 30527c478bd9Sstevel@tonic-gate break; 30537c478bd9Sstevel@tonic-gate default: 30547c478bd9Sstevel@tonic-gate warnx("Address type %d not supported.", ne->n_addrtype); 30557c478bd9Sstevel@tonic-gate return (-1); 30567c478bd9Sstevel@tonic-gate } 30577c478bd9Sstevel@tonic-gate } else { 30587c478bd9Sstevel@tonic-gate return (-1); 30597c478bd9Sstevel@tonic-gate } 30607c478bd9Sstevel@tonic-gate 30617c478bd9Sstevel@tonic-gate if (type == IPSEC_CONF_SRC_ADDRESS) { 30627c478bd9Sstevel@tonic-gate shp = hp; 30637c478bd9Sstevel@tonic-gate if (has_mask) 30647c478bd9Sstevel@tonic-gate splen = prefix_len; 30657c478bd9Sstevel@tonic-gate has_saprefix = has_mask; 30667c478bd9Sstevel@tonic-gate } else { 30677c478bd9Sstevel@tonic-gate dhp = hp; 30687c478bd9Sstevel@tonic-gate if (has_mask) 30697c478bd9Sstevel@tonic-gate dplen = prefix_len; 30707c478bd9Sstevel@tonic-gate has_daprefix = has_mask; 30717c478bd9Sstevel@tonic-gate } 30727c478bd9Sstevel@tonic-gate 30737c478bd9Sstevel@tonic-gate return (0); 30747c478bd9Sstevel@tonic-gate } 30757c478bd9Sstevel@tonic-gate 30767c478bd9Sstevel@tonic-gate /* 30777c478bd9Sstevel@tonic-gate * Add port-only entries. Make sure to add them in both the V6 and V4 tables! 30787c478bd9Sstevel@tonic-gate */ 30797c478bd9Sstevel@tonic-gate static int 30807c478bd9Sstevel@tonic-gate do_port_adds(ips_conf_t *cptr) 30817c478bd9Sstevel@tonic-gate { 30828810c16bSdanmcd int ret, diag; 30837c478bd9Sstevel@tonic-gate 30847c478bd9Sstevel@tonic-gate assert(IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_addr_v6)); 30857c478bd9Sstevel@tonic-gate assert(IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_dst_addr_v6)); 30867c478bd9Sstevel@tonic-gate 30877c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 30887c478bd9Sstevel@tonic-gate (void) dump_conf(cptr); 30897c478bd9Sstevel@tonic-gate #endif 30907c478bd9Sstevel@tonic-gate 30918810c16bSdanmcd ret = send_pf_pol_message(SPD_ADDRULE, cptr, &diag); 309243c889d3Smarkfen if (ret != 0 && !ipsecconf_qflag) { 30937c478bd9Sstevel@tonic-gate warnx( 30948810c16bSdanmcd gettext("Could not add IPv4 policy for sport %d, dport %d " 3095d5751483Smarkfen "- diagnostic %d - %s"), ntohs(cptr->ips_src_port_min), 30968810c16bSdanmcd ntohs(cptr->ips_dst_port_min), diag, spdsock_diag(diag)); 30977c478bd9Sstevel@tonic-gate } 30987c478bd9Sstevel@tonic-gate 309943c889d3Smarkfen return (ret); 31007c478bd9Sstevel@tonic-gate } 31017c478bd9Sstevel@tonic-gate 31027c478bd9Sstevel@tonic-gate /* 31037c478bd9Sstevel@tonic-gate * Nuke a list of policy entries. 31047c478bd9Sstevel@tonic-gate * rewrite this to use flipping 31057c478bd9Sstevel@tonic-gate * d_list isn't freed because we will be 31067c478bd9Sstevel@tonic-gate * exiting the program soon. 31077c478bd9Sstevel@tonic-gate */ 31087c478bd9Sstevel@tonic-gate static void 31097c478bd9Sstevel@tonic-gate nuke_adds() 31107c478bd9Sstevel@tonic-gate { 31117c478bd9Sstevel@tonic-gate d_list_t *temp = d_list; 31127c478bd9Sstevel@tonic-gate FILE *policy_fp; 31137c478bd9Sstevel@tonic-gate 31147c478bd9Sstevel@tonic-gate policy_fp = fopen(POLICY_CONF_FILE, "a"); 31157c478bd9Sstevel@tonic-gate if (policy_fp == NULL) { 31167c478bd9Sstevel@tonic-gate warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 3117*3abcb969Spwernau } else { 3118*3abcb969Spwernau (void) fprintf(policy_fp, "\n\n"); 3119*3abcb969Spwernau (void) fflush(policy_fp); 31207c478bd9Sstevel@tonic-gate } 31217c478bd9Sstevel@tonic-gate 31227c478bd9Sstevel@tonic-gate while (temp != NULL) { 31237c478bd9Sstevel@tonic-gate (void) ipsec_conf_del(temp->index, B_TRUE); 31247c478bd9Sstevel@tonic-gate temp = temp->next; 31257c478bd9Sstevel@tonic-gate } 31267c478bd9Sstevel@tonic-gate } 31277c478bd9Sstevel@tonic-gate 31287c478bd9Sstevel@tonic-gate /* 31297c478bd9Sstevel@tonic-gate * Set mask info from the specified prefix len. Fail if multihomed. 31307c478bd9Sstevel@tonic-gate */ 31317c478bd9Sstevel@tonic-gate static int 31327c478bd9Sstevel@tonic-gate set_mask_info(struct hostent *hp, unsigned int plen, struct in6_addr *mask_v6) 31337c478bd9Sstevel@tonic-gate { 31347c478bd9Sstevel@tonic-gate struct in6_addr addr; 31357c478bd9Sstevel@tonic-gate struct in_addr mask_v4; 31367c478bd9Sstevel@tonic-gate 31377c478bd9Sstevel@tonic-gate if (hp->h_addr_list[1] != NULL) { 31388810c16bSdanmcd return (EOPNOTSUPP); 31397c478bd9Sstevel@tonic-gate } 31407c478bd9Sstevel@tonic-gate 31417c478bd9Sstevel@tonic-gate if (!IN6_IS_ADDR_UNSPECIFIED(mask_v6)) { 31427c478bd9Sstevel@tonic-gate return (EBUSY); 31437c478bd9Sstevel@tonic-gate } 31447c478bd9Sstevel@tonic-gate 31457c478bd9Sstevel@tonic-gate bcopy(hp->h_addr_list[0], &addr, sizeof (struct in6_addr)); 31467c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(&addr)) { 31477c478bd9Sstevel@tonic-gate if (plen > IP_ABITS) { 31487c478bd9Sstevel@tonic-gate return (ERANGE); 31497c478bd9Sstevel@tonic-gate } 31507c478bd9Sstevel@tonic-gate (void) memset(&mask_v4, 0, sizeof (mask_v4)); 31517c478bd9Sstevel@tonic-gate in_prefixlentomask(plen, (uchar_t *)&mask_v4); 31527c478bd9Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&mask_v4, mask_v6); 31537c478bd9Sstevel@tonic-gate } else { 31547c478bd9Sstevel@tonic-gate if (plen > IPV6_ABITS) { 31557c478bd9Sstevel@tonic-gate return (ERANGE); 31567c478bd9Sstevel@tonic-gate } 31577c478bd9Sstevel@tonic-gate /* mask_v6 is already zero (unspecified), see test above */ 31587c478bd9Sstevel@tonic-gate in_prefixlentomask(plen, (uchar_t *)mask_v6); 31597c478bd9Sstevel@tonic-gate } 31607c478bd9Sstevel@tonic-gate return (0); 31617c478bd9Sstevel@tonic-gate } 31627c478bd9Sstevel@tonic-gate 31637c478bd9Sstevel@tonic-gate /* 31647c478bd9Sstevel@tonic-gate * Initialize the specified IPv6 address with all f's. 31657c478bd9Sstevel@tonic-gate */ 31667c478bd9Sstevel@tonic-gate static void 31677c478bd9Sstevel@tonic-gate init_addr_wildcard(struct in6_addr *addr_v6, boolean_t isv4) 31687c478bd9Sstevel@tonic-gate { 31697c478bd9Sstevel@tonic-gate if (isv4) { 31707c478bd9Sstevel@tonic-gate uint32_t addr_v4 = 0xffffffff; 31717c478bd9Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED((struct in_addr *)&addr_v4, addr_v6); 31727c478bd9Sstevel@tonic-gate } else { 31737c478bd9Sstevel@tonic-gate (void) memset(addr_v6, 0xff, sizeof (struct in6_addr)); 31747c478bd9Sstevel@tonic-gate } 31757c478bd9Sstevel@tonic-gate } 31767c478bd9Sstevel@tonic-gate 31777c478bd9Sstevel@tonic-gate /* 31787c478bd9Sstevel@tonic-gate * Called at the end to actually add policy. Handles single and multi-homed 31797c478bd9Sstevel@tonic-gate * cases. 31807c478bd9Sstevel@tonic-gate */ 31817c478bd9Sstevel@tonic-gate static int 31828810c16bSdanmcd do_address_adds(ips_conf_t *cptr, int *diag) 31837c478bd9Sstevel@tonic-gate { 31847c478bd9Sstevel@tonic-gate int i, j; 31857c478bd9Sstevel@tonic-gate int ret = 0; /* For ioctl() call. */ 31867c478bd9Sstevel@tonic-gate int rc = 0; /* My own return code. */ 31877c478bd9Sstevel@tonic-gate struct in6_addr zeroes = {0, 0, 0, 0}; 31887c478bd9Sstevel@tonic-gate char *ptr[2]; 31897c478bd9Sstevel@tonic-gate struct hostent hent; 31907c478bd9Sstevel@tonic-gate boolean_t isv4; 31917c478bd9Sstevel@tonic-gate int add_count = 0; 31927c478bd9Sstevel@tonic-gate 31937c478bd9Sstevel@tonic-gate /* 31947c478bd9Sstevel@tonic-gate * dst_hent may not be initialized if a destination 31957c478bd9Sstevel@tonic-gate * address was not given. It will be initalized with just 31967c478bd9Sstevel@tonic-gate * one address if a destination address was given. In both 31977c478bd9Sstevel@tonic-gate * the cases, we initialize here with ipsc_dst_addr and enter 31987c478bd9Sstevel@tonic-gate * the loop below. 31997c478bd9Sstevel@tonic-gate */ 32007c478bd9Sstevel@tonic-gate if (dhp == NULL) { 32017c478bd9Sstevel@tonic-gate assert(shp != NULL); 32027c478bd9Sstevel@tonic-gate hent.h_addr_list = ptr; 32037c478bd9Sstevel@tonic-gate ptr[0] = (char *)&zeroes.s6_addr; 32047c478bd9Sstevel@tonic-gate ptr[1] = NULL; 32057c478bd9Sstevel@tonic-gate dhp = &hent; 32067c478bd9Sstevel@tonic-gate } else if (shp == NULL) { 32077c478bd9Sstevel@tonic-gate assert(dhp != NULL); 32087c478bd9Sstevel@tonic-gate hent.h_addr_list = ptr; 32097c478bd9Sstevel@tonic-gate ptr[0] = (char *)&zeroes.s6_addr; 32107c478bd9Sstevel@tonic-gate ptr[1] = NULL; 32117c478bd9Sstevel@tonic-gate shp = &hent; 32127c478bd9Sstevel@tonic-gate } 32137c478bd9Sstevel@tonic-gate 32147c478bd9Sstevel@tonic-gate /* 32157c478bd9Sstevel@tonic-gate * Set mask info here. Bail if multihomed and there's a prefix len. 32167c478bd9Sstevel@tonic-gate */ 32177c478bd9Sstevel@tonic-gate if (has_saprefix) { 32187c478bd9Sstevel@tonic-gate rc = set_mask_info(shp, splen, &cptr->ips_src_mask_v6); 32197c478bd9Sstevel@tonic-gate if (rc != 0) 32207c478bd9Sstevel@tonic-gate goto bail; 32217c478bd9Sstevel@tonic-gate cptr->ips_src_mask_len = splen; 32227c478bd9Sstevel@tonic-gate } 32237c478bd9Sstevel@tonic-gate 32247c478bd9Sstevel@tonic-gate if (has_daprefix) { 32257c478bd9Sstevel@tonic-gate rc = set_mask_info(dhp, dplen, &cptr->ips_dst_mask_v6); 32267c478bd9Sstevel@tonic-gate if (rc != 0) 32277c478bd9Sstevel@tonic-gate goto bail; 32287c478bd9Sstevel@tonic-gate cptr->ips_dst_mask_len = dplen; 32297c478bd9Sstevel@tonic-gate } 32307c478bd9Sstevel@tonic-gate 32317c478bd9Sstevel@tonic-gate for (i = 0; shp->h_addr_list[i] != NULL; i++) { 32327c478bd9Sstevel@tonic-gate bcopy(shp->h_addr_list[i], &cptr->ips_src_addr_v6, 32337c478bd9Sstevel@tonic-gate sizeof (struct in6_addr)); 32347c478bd9Sstevel@tonic-gate isv4 = cptr->ips_isv4 = 32357c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&cptr->ips_src_addr_v6); 32367c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_mask_v6) && 32377c478bd9Sstevel@tonic-gate shp != &hent) { 32387c478bd9Sstevel@tonic-gate init_addr_wildcard(&cptr->ips_src_mask_v6, isv4); 32397c478bd9Sstevel@tonic-gate } 32407c478bd9Sstevel@tonic-gate 32417c478bd9Sstevel@tonic-gate for (j = 0; dhp->h_addr_list[j] != NULL; j++) { 32427c478bd9Sstevel@tonic-gate bcopy(dhp->h_addr_list[j], &cptr->ips_dst_addr_v6, 32437c478bd9Sstevel@tonic-gate sizeof (struct in6_addr)); 32447c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_src_addr_v6)) { 32457c478bd9Sstevel@tonic-gate /* 32467c478bd9Sstevel@tonic-gate * Src was not specified, so update isv4 flag 32477c478bd9Sstevel@tonic-gate * for this policy according to the family 32487c478bd9Sstevel@tonic-gate * of the destination address. 32497c478bd9Sstevel@tonic-gate */ 32507c478bd9Sstevel@tonic-gate isv4 = cptr->ips_isv4 = 32517c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED( 3252d5751483Smarkfen &cptr->ips_dst_addr_v6); 32537c478bd9Sstevel@tonic-gate } else if ((dhp != &hent) && (isv4 != 32547c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&cptr->ips_dst_addr_v6))) { 32557c478bd9Sstevel@tonic-gate /* v6/v4 mismatch. */ 32567c478bd9Sstevel@tonic-gate continue; 32577c478bd9Sstevel@tonic-gate } 32587c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&cptr->ips_dst_mask_v6) && 32597c478bd9Sstevel@tonic-gate dhp != &hent) { 32607c478bd9Sstevel@tonic-gate init_addr_wildcard(&cptr->ips_dst_mask_v6, 32617c478bd9Sstevel@tonic-gate isv4); 32627c478bd9Sstevel@tonic-gate } 32637c478bd9Sstevel@tonic-gate 32648810c16bSdanmcd ret = send_pf_pol_message(SPD_ADDRULE, cptr, diag); 32657c478bd9Sstevel@tonic-gate 326643c889d3Smarkfen if (ret == 0) { 326743c889d3Smarkfen add_count++; 326843c889d3Smarkfen } else { 32697c478bd9Sstevel@tonic-gate /* For now, allow duplicate/overlap policies. */ 327043c889d3Smarkfen if (ret != EEXIST) { 32717c478bd9Sstevel@tonic-gate /* 32727c478bd9Sstevel@tonic-gate * We have an error where we added 32737c478bd9Sstevel@tonic-gate * some, but had errors with others. 32747c478bd9Sstevel@tonic-gate * Undo the previous adds, and 32757c478bd9Sstevel@tonic-gate * bail. 32767c478bd9Sstevel@tonic-gate */ 327743c889d3Smarkfen rc = ret; 32787c478bd9Sstevel@tonic-gate goto bail; 32797c478bd9Sstevel@tonic-gate } 32807c478bd9Sstevel@tonic-gate } 32817c478bd9Sstevel@tonic-gate 32827c478bd9Sstevel@tonic-gate bzero(&cptr->ips_dst_mask_v6, 32837c478bd9Sstevel@tonic-gate sizeof (struct in6_addr)); 32847c478bd9Sstevel@tonic-gate } 32857c478bd9Sstevel@tonic-gate 32867c478bd9Sstevel@tonic-gate bzero(&cptr->ips_src_mask_v6, sizeof (struct in6_addr)); 32877c478bd9Sstevel@tonic-gate } 32887c478bd9Sstevel@tonic-gate 32897c478bd9Sstevel@tonic-gate bail: 32907c478bd9Sstevel@tonic-gate if (shp != &hent) 32917c478bd9Sstevel@tonic-gate freehostent(shp); 32927c478bd9Sstevel@tonic-gate shp = NULL; 32937c478bd9Sstevel@tonic-gate if (dhp != &hent) 32947c478bd9Sstevel@tonic-gate freehostent(dhp); 32957c478bd9Sstevel@tonic-gate dhp = NULL; 32967c478bd9Sstevel@tonic-gate splen = 0; 32977c478bd9Sstevel@tonic-gate dplen = 0; 32987c478bd9Sstevel@tonic-gate 32997c478bd9Sstevel@tonic-gate if ((add_count == 0) && (rc == 0)) { 33007c478bd9Sstevel@tonic-gate /* 33017c478bd9Sstevel@tonic-gate * No entries were added. We failed all adds 33027c478bd9Sstevel@tonic-gate * because the entries already existed, or because 33037c478bd9Sstevel@tonic-gate * no v4 or v6 src/dst pairs were found. Either way, 33047c478bd9Sstevel@tonic-gate * we must fail here with an appropriate error 33057c478bd9Sstevel@tonic-gate * to avoid a corresponding entry from being added 33067c478bd9Sstevel@tonic-gate * to ipsecpolicy.conf. 33077c478bd9Sstevel@tonic-gate */ 330843c889d3Smarkfen if ((ret == EEXIST)) { 33097c478bd9Sstevel@tonic-gate /* All adds failed with EEXIST */ 33107c478bd9Sstevel@tonic-gate rc = EEXIST; 33117c478bd9Sstevel@tonic-gate } else { 33127c478bd9Sstevel@tonic-gate /* No matching v4 or v6 src/dst pairs */ 33137c478bd9Sstevel@tonic-gate rc = ESRCH; 33147c478bd9Sstevel@tonic-gate } 33157c478bd9Sstevel@tonic-gate } 33167c478bd9Sstevel@tonic-gate 33177c478bd9Sstevel@tonic-gate return (rc); 33187c478bd9Sstevel@tonic-gate } 33197c478bd9Sstevel@tonic-gate 33207c478bd9Sstevel@tonic-gate static int 33217c478bd9Sstevel@tonic-gate parse_mask(int type, char *mask_str, ips_conf_t *cptr) 33227c478bd9Sstevel@tonic-gate { 33237c478bd9Sstevel@tonic-gate struct in_addr mask; 33247c478bd9Sstevel@tonic-gate struct in6_addr *mask6; 33257c478bd9Sstevel@tonic-gate 33267c478bd9Sstevel@tonic-gate if (type == IPSEC_CONF_SRC_MASK) { 33277c478bd9Sstevel@tonic-gate mask6 = &cptr->ips_src_mask_v6; 33287c478bd9Sstevel@tonic-gate } else { 33297c478bd9Sstevel@tonic-gate mask6 = &cptr->ips_dst_mask_v6; 33307c478bd9Sstevel@tonic-gate } 33317c478bd9Sstevel@tonic-gate 33327c478bd9Sstevel@tonic-gate if ((strncasecmp(mask_str, "0x", 2) == 0) && 33337c478bd9Sstevel@tonic-gate (strchr(mask_str, '.') == NULL)) { 33347c478bd9Sstevel@tonic-gate /* Is it in the form 0xff000000 ? */ 33357c478bd9Sstevel@tonic-gate char *end; 33367c478bd9Sstevel@tonic-gate 33377c478bd9Sstevel@tonic-gate mask.s_addr = strtoul(mask_str, &end, 0); 33387c478bd9Sstevel@tonic-gate if (end == mask_str) { 33397c478bd9Sstevel@tonic-gate return (-1); 33407c478bd9Sstevel@tonic-gate } 33417c478bd9Sstevel@tonic-gate if (*end != '\0') { 33427c478bd9Sstevel@tonic-gate return (-1); 33437c478bd9Sstevel@tonic-gate } 33447c478bd9Sstevel@tonic-gate mask.s_addr = htonl(mask.s_addr); 33457c478bd9Sstevel@tonic-gate } else { 33467c478bd9Sstevel@tonic-gate /* 33477c478bd9Sstevel@tonic-gate * Since inet_addr() returns -1 on error, we have 33487c478bd9Sstevel@tonic-gate * to convert a broadcast address ourselves. 33497c478bd9Sstevel@tonic-gate */ 33507c478bd9Sstevel@tonic-gate if (strcmp(mask_str, "255.255.255.255") == 0) { 33517c478bd9Sstevel@tonic-gate mask.s_addr = 0xffffffff; 33527c478bd9Sstevel@tonic-gate } else { 33537c478bd9Sstevel@tonic-gate mask.s_addr = inet_addr(mask_str); 33547c478bd9Sstevel@tonic-gate if (mask.s_addr == (unsigned int)-1) 33557c478bd9Sstevel@tonic-gate return (-1); 33567c478bd9Sstevel@tonic-gate } 33577c478bd9Sstevel@tonic-gate } 33587c478bd9Sstevel@tonic-gate 33597c478bd9Sstevel@tonic-gate /* Should we check for non-contiguous masks ? */ 33607c478bd9Sstevel@tonic-gate if (mask.s_addr == 0) 33617c478bd9Sstevel@tonic-gate return (-1); 33627c478bd9Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(&mask, mask6); 33637c478bd9Sstevel@tonic-gate 33647c478bd9Sstevel@tonic-gate 33657c478bd9Sstevel@tonic-gate if (type == IPSEC_CONF_SRC_MASK) { 33667c478bd9Sstevel@tonic-gate cptr->ips_src_mask_len = in_masktoprefix(mask6->s6_addr, 33677c478bd9Sstevel@tonic-gate B_TRUE); 33687c478bd9Sstevel@tonic-gate } else { 33697c478bd9Sstevel@tonic-gate cptr->ips_dst_mask_len = in_masktoprefix(mask6->s6_addr, 33707c478bd9Sstevel@tonic-gate B_TRUE); 33717c478bd9Sstevel@tonic-gate } 33727c478bd9Sstevel@tonic-gate 33737c478bd9Sstevel@tonic-gate return (0); 33747c478bd9Sstevel@tonic-gate } 33757c478bd9Sstevel@tonic-gate 33767c478bd9Sstevel@tonic-gate static int 33777c478bd9Sstevel@tonic-gate parse_port(int type, char *port_str, ips_conf_t *conf) 33787c478bd9Sstevel@tonic-gate { 33797c478bd9Sstevel@tonic-gate struct servent *sent; 33807c478bd9Sstevel@tonic-gate in_port_t port; 33817c478bd9Sstevel@tonic-gate int ret; 33827c478bd9Sstevel@tonic-gate 33837c478bd9Sstevel@tonic-gate sent = getservbyname(port_str, NULL); 33847c478bd9Sstevel@tonic-gate if (sent == NULL) { 33857c478bd9Sstevel@tonic-gate ret = parse_int(port_str); 33867c478bd9Sstevel@tonic-gate if (ret < 0 || ret >= 65536) { 33877c478bd9Sstevel@tonic-gate return (-1); 33887c478bd9Sstevel@tonic-gate } 33897c478bd9Sstevel@tonic-gate port = htons((in_port_t)ret); 33907c478bd9Sstevel@tonic-gate } else { 33917c478bd9Sstevel@tonic-gate port = sent->s_port; 33927c478bd9Sstevel@tonic-gate } 33937c478bd9Sstevel@tonic-gate if (type == IPSEC_CONF_SRC_PORT) { 33947c478bd9Sstevel@tonic-gate conf->ips_src_port_min = conf->ips_src_port_max = port; 33957c478bd9Sstevel@tonic-gate } else { 33967c478bd9Sstevel@tonic-gate conf->ips_dst_port_min = conf->ips_dst_port_max = port; 33977c478bd9Sstevel@tonic-gate } 33987c478bd9Sstevel@tonic-gate return (0); 33997c478bd9Sstevel@tonic-gate } 34007c478bd9Sstevel@tonic-gate 34017c478bd9Sstevel@tonic-gate static int 34027c478bd9Sstevel@tonic-gate valid_algorithm(int proto_num, const char *str) 34037c478bd9Sstevel@tonic-gate { 34047c478bd9Sstevel@tonic-gate const char *tmp; 34057c478bd9Sstevel@tonic-gate int ret; 34067c478bd9Sstevel@tonic-gate struct ipsecalgent *alg; 34077c478bd9Sstevel@tonic-gate 3408c758f97fSpwernau /* Short-circuit "none" */ 3409c758f97fSpwernau if (strncasecmp("none", str, 5) == 0) 3410c758f97fSpwernau return (-2); 3411c758f97fSpwernau 34127c478bd9Sstevel@tonic-gate alg = getipsecalgbyname(str, proto_num, NULL); 34137c478bd9Sstevel@tonic-gate if (alg != NULL) { 34147c478bd9Sstevel@tonic-gate ret = alg->a_alg_num; 34157c478bd9Sstevel@tonic-gate freeipsecalgent(alg); 34167c478bd9Sstevel@tonic-gate return (ret); 34177c478bd9Sstevel@tonic-gate } 34187c478bd9Sstevel@tonic-gate 34197c478bd9Sstevel@tonic-gate /* 34207c478bd9Sstevel@tonic-gate * Look whether it could be a valid number. 34217c478bd9Sstevel@tonic-gate * We support numbers also so that users can 34227c478bd9Sstevel@tonic-gate * load algorithms as they need it. We can't 34237c478bd9Sstevel@tonic-gate * check for validity of numbers here. It will 34247c478bd9Sstevel@tonic-gate * be checked when the SA is negotiated/looked up. 34257c478bd9Sstevel@tonic-gate * parse_int uses strtol(str), which converts 3DES 34267c478bd9Sstevel@tonic-gate * to a valid number i.e looks only at initial 34277c478bd9Sstevel@tonic-gate * number part. If we come here we should expect 34287c478bd9Sstevel@tonic-gate * only a decimal number. 34297c478bd9Sstevel@tonic-gate */ 34307c478bd9Sstevel@tonic-gate tmp = str; 34317c478bd9Sstevel@tonic-gate while (*tmp) { 34327c478bd9Sstevel@tonic-gate if (!isdigit(*tmp)) 34337c478bd9Sstevel@tonic-gate return (-1); 34347c478bd9Sstevel@tonic-gate tmp++; 34357c478bd9Sstevel@tonic-gate } 34367c478bd9Sstevel@tonic-gate 34377c478bd9Sstevel@tonic-gate ret = parse_int(str); 34387c478bd9Sstevel@tonic-gate if (ret > 0 && ret <= 255) 34397c478bd9Sstevel@tonic-gate return (ret); 34407c478bd9Sstevel@tonic-gate else 34417c478bd9Sstevel@tonic-gate return (-1); 34427c478bd9Sstevel@tonic-gate } 34437c478bd9Sstevel@tonic-gate 34447c478bd9Sstevel@tonic-gate static int 34457c478bd9Sstevel@tonic-gate parse_ipsec_alg(char *str, ips_act_props_t *iap, int alg_type) 34467c478bd9Sstevel@tonic-gate { 34477c478bd9Sstevel@tonic-gate int alg_value; 34487c478bd9Sstevel@tonic-gate char tstr[VALID_ALG_LEN]; 34497c478bd9Sstevel@tonic-gate char *lens = NULL; 34507c478bd9Sstevel@tonic-gate char *l1_str; 34517c478bd9Sstevel@tonic-gate int l1 = 0; 34527c478bd9Sstevel@tonic-gate char *l2_str; 34537c478bd9Sstevel@tonic-gate int l2 = SPD_MAX_MAXBITS; 34547c478bd9Sstevel@tonic-gate algreq_t *ap; 34557c478bd9Sstevel@tonic-gate uint_t a_type; 34567c478bd9Sstevel@tonic-gate 34577c478bd9Sstevel@tonic-gate fetch_algorithms(); 34587c478bd9Sstevel@tonic-gate 34597c478bd9Sstevel@tonic-gate /* 34607c478bd9Sstevel@tonic-gate * Make sure that we get a null terminated string. 34617c478bd9Sstevel@tonic-gate * For a bad input, we truncate at VALID_ALG_LEN. 34627c478bd9Sstevel@tonic-gate */ 34638810c16bSdanmcd (void) strlcpy(tstr, str, VALID_ALG_LEN); 34647c478bd9Sstevel@tonic-gate lens = strtok(tstr, "()"); 34657c478bd9Sstevel@tonic-gate lens = strtok(NULL, "()"); 34667c478bd9Sstevel@tonic-gate 34677c478bd9Sstevel@tonic-gate if (lens != NULL) { 34687c478bd9Sstevel@tonic-gate int len1 = 0; 34697c478bd9Sstevel@tonic-gate int len2 = SPD_MAX_MAXBITS; 34707c478bd9Sstevel@tonic-gate int len_all = strlen(lens); 34717c478bd9Sstevel@tonic-gate int dot_start = (lens[0] == '.'); 34727c478bd9Sstevel@tonic-gate l1_str = strtok(lens, "."); 34737c478bd9Sstevel@tonic-gate l2_str = strtok(NULL, "."); 34747c478bd9Sstevel@tonic-gate if (l1_str != NULL) { 34757c478bd9Sstevel@tonic-gate l1 = parse_int(l1_str); 34767c478bd9Sstevel@tonic-gate len1 = strlen(l1_str); 34777c478bd9Sstevel@tonic-gate if (len1 < 0) 34787c478bd9Sstevel@tonic-gate return (1); 34797c478bd9Sstevel@tonic-gate } 34807c478bd9Sstevel@tonic-gate if (l2_str != NULL) { 34817c478bd9Sstevel@tonic-gate l2 = parse_int(l2_str); 34827c478bd9Sstevel@tonic-gate len2 = strlen(l2_str); 34837c478bd9Sstevel@tonic-gate if (len2 < 0) 34847c478bd9Sstevel@tonic-gate return (1); 34857c478bd9Sstevel@tonic-gate } 34867c478bd9Sstevel@tonic-gate 34877c478bd9Sstevel@tonic-gate if (len_all == len1) { 34887c478bd9Sstevel@tonic-gate /* alg(n) */ 34897c478bd9Sstevel@tonic-gate l2 = l1; 34907c478bd9Sstevel@tonic-gate } else if (dot_start) { 34917c478bd9Sstevel@tonic-gate /* alg(..n) */ 34927c478bd9Sstevel@tonic-gate l2 = l1; 34937c478bd9Sstevel@tonic-gate l1 = 0; 34947c478bd9Sstevel@tonic-gate } else if ((len_all - 2) == len1) { 34957c478bd9Sstevel@tonic-gate /* alg(n..) */ 34967c478bd9Sstevel@tonic-gate l2 = SPD_MAX_MAXBITS; 34977c478bd9Sstevel@tonic-gate } /* else alg(n..m) */ 34987c478bd9Sstevel@tonic-gate } 34997c478bd9Sstevel@tonic-gate 35007c478bd9Sstevel@tonic-gate if (alg_type == SPD_ATTR_AH_AUTH || 35017c478bd9Sstevel@tonic-gate alg_type == SPD_ATTR_ESP_AUTH) { 35027c478bd9Sstevel@tonic-gate alg_value = valid_algorithm(IPSEC_PROTO_AH, tstr); 35037c478bd9Sstevel@tonic-gate } else { 35047c478bd9Sstevel@tonic-gate alg_value = valid_algorithm(IPSEC_PROTO_ESP, tstr); 35057c478bd9Sstevel@tonic-gate } 3506c758f97fSpwernau if (alg_value < 0) { 3507c758f97fSpwernau /* Invalid algorithm or "none" */ 3508c758f97fSpwernau return (alg_value); 35097c478bd9Sstevel@tonic-gate } 35107c478bd9Sstevel@tonic-gate 35117c478bd9Sstevel@tonic-gate if (alg_type == SPD_ATTR_AH_AUTH) { 35127c478bd9Sstevel@tonic-gate a_type = AH_AUTH; 35137c478bd9Sstevel@tonic-gate iap->iap_attr |= SPD_APPLY_AH; 35147c478bd9Sstevel@tonic-gate ap = &(iap->iap_aauth); 35157c478bd9Sstevel@tonic-gate } else if (alg_type == SPD_ATTR_ESP_AUTH) { 35167c478bd9Sstevel@tonic-gate a_type = ESP_AUTH; 35177c478bd9Sstevel@tonic-gate iap->iap_attr |= SPD_APPLY_ESP|SPD_APPLY_ESPA; 35187c478bd9Sstevel@tonic-gate ap = &(iap->iap_eauth); 35197c478bd9Sstevel@tonic-gate } else { 35207c478bd9Sstevel@tonic-gate a_type = ESP_ENCR; 35217c478bd9Sstevel@tonic-gate iap->iap_attr |= SPD_APPLY_ESP; 35227c478bd9Sstevel@tonic-gate ap = &(iap->iap_eencr); 35237c478bd9Sstevel@tonic-gate } 35247c478bd9Sstevel@tonic-gate 35257c478bd9Sstevel@tonic-gate ap->alg_id = alg_value; 35267c478bd9Sstevel@tonic-gate ap->alg_minbits = l1; 35277c478bd9Sstevel@tonic-gate ap->alg_maxbits = l2; 35287c478bd9Sstevel@tonic-gate 35297c478bd9Sstevel@tonic-gate if (!alg_rangecheck(a_type, alg_value, ap)) 3530c758f97fSpwernau return (1); 35317c478bd9Sstevel@tonic-gate 35327c478bd9Sstevel@tonic-gate return (0); 35337c478bd9Sstevel@tonic-gate } 35347c478bd9Sstevel@tonic-gate 35358810c16bSdanmcd static char * 35368810c16bSdanmcd sys_error_message(int syserr) 35378810c16bSdanmcd { 35388810c16bSdanmcd char *mesg; 35398810c16bSdanmcd 35408810c16bSdanmcd switch (syserr) { 35418810c16bSdanmcd case EEXIST: 35428810c16bSdanmcd mesg = gettext("Entry already exists"); 35438810c16bSdanmcd break; 35448810c16bSdanmcd case ENOENT: 35458810c16bSdanmcd mesg = gettext("Tunnel not found"); 35468810c16bSdanmcd break; 35478810c16bSdanmcd case EINVAL: 35488810c16bSdanmcd mesg = gettext("Invalid entry"); 35498810c16bSdanmcd break; 35508810c16bSdanmcd default : 35518810c16bSdanmcd mesg = strerror(syserr); 35528810c16bSdanmcd } 35538810c16bSdanmcd return (mesg); 35548810c16bSdanmcd } 35558810c16bSdanmcd 35567c478bd9Sstevel@tonic-gate static void 35577c478bd9Sstevel@tonic-gate error_message(error_type_t error, int type, int line) 35587c478bd9Sstevel@tonic-gate { 35597c478bd9Sstevel@tonic-gate char *mesg; 35607c478bd9Sstevel@tonic-gate 35617c478bd9Sstevel@tonic-gate switch (type) { 35627c478bd9Sstevel@tonic-gate case IPSEC_CONF_SRC_ADDRESS: 35637c478bd9Sstevel@tonic-gate mesg = gettext("Source Address"); 35647c478bd9Sstevel@tonic-gate break; 35657c478bd9Sstevel@tonic-gate case IPSEC_CONF_DST_ADDRESS: 35667c478bd9Sstevel@tonic-gate mesg = gettext("Destination Address"); 35677c478bd9Sstevel@tonic-gate break; 35687c478bd9Sstevel@tonic-gate case IPSEC_CONF_SRC_PORT: 35697c478bd9Sstevel@tonic-gate mesg = gettext("Source Port"); 35707c478bd9Sstevel@tonic-gate break; 35717c478bd9Sstevel@tonic-gate case IPSEC_CONF_DST_PORT: 35727c478bd9Sstevel@tonic-gate mesg = gettext("Destination Port"); 35737c478bd9Sstevel@tonic-gate break; 35747c478bd9Sstevel@tonic-gate case IPSEC_CONF_SRC_MASK: 35757c478bd9Sstevel@tonic-gate mesg = gettext("Source Mask"); 35767c478bd9Sstevel@tonic-gate break; 35777c478bd9Sstevel@tonic-gate case IPSEC_CONF_DST_MASK: 35787c478bd9Sstevel@tonic-gate mesg = gettext("Destination Mask"); 35797c478bd9Sstevel@tonic-gate break; 35807c478bd9Sstevel@tonic-gate case IPSEC_CONF_ULP: 35817c478bd9Sstevel@tonic-gate mesg = gettext("Upper Layer Protocol"); 35827c478bd9Sstevel@tonic-gate break; 35837c478bd9Sstevel@tonic-gate case IPSEC_CONF_IPSEC_AALGS: 35847c478bd9Sstevel@tonic-gate mesg = gettext("Authentication Algorithm"); 35857c478bd9Sstevel@tonic-gate break; 35867c478bd9Sstevel@tonic-gate case IPSEC_CONF_IPSEC_EALGS: 35877c478bd9Sstevel@tonic-gate mesg = gettext("Encryption Algorithm"); 35887c478bd9Sstevel@tonic-gate break; 35897c478bd9Sstevel@tonic-gate case IPSEC_CONF_IPSEC_EAALGS: 35907c478bd9Sstevel@tonic-gate mesg = gettext("ESP Authentication Algorithm"); 35917c478bd9Sstevel@tonic-gate break; 35927c478bd9Sstevel@tonic-gate case IPSEC_CONF_IPSEC_SA: 35937c478bd9Sstevel@tonic-gate mesg = gettext("SA"); 35947c478bd9Sstevel@tonic-gate break; 35957c478bd9Sstevel@tonic-gate case IPSEC_CONF_IPSEC_DIR: 35967c478bd9Sstevel@tonic-gate mesg = gettext("Direction"); 35977c478bd9Sstevel@tonic-gate break; 35987c478bd9Sstevel@tonic-gate case IPSEC_CONF_ICMP_TYPE: 35997c478bd9Sstevel@tonic-gate mesg = gettext("ICMP type"); 36007c478bd9Sstevel@tonic-gate break; 36017c478bd9Sstevel@tonic-gate case IPSEC_CONF_ICMP_CODE: 36027c478bd9Sstevel@tonic-gate mesg = gettext("ICMP code"); 36037c478bd9Sstevel@tonic-gate break; 36048810c16bSdanmcd case IPSEC_CONF_NEGOTIATE: 36058810c16bSdanmcd mesg = gettext("Negotiate"); 36068810c16bSdanmcd break; 36078810c16bSdanmcd case IPSEC_CONF_TUNNEL: 36088810c16bSdanmcd mesg = gettext("Tunnel"); 36098810c16bSdanmcd break; 36107c478bd9Sstevel@tonic-gate default : 36117c478bd9Sstevel@tonic-gate return; 36127c478bd9Sstevel@tonic-gate } 36137c478bd9Sstevel@tonic-gate /* 36147c478bd9Sstevel@tonic-gate * If we never read a newline character, we don't want 36157c478bd9Sstevel@tonic-gate * to print 0. 36167c478bd9Sstevel@tonic-gate */ 3617eeda67c6Sjojemann warnx(gettext("%s%s%s %s on line: %d"), 3618eeda67c6Sjojemann (error == BAD_ERROR) ? gettext("Bad") : "", 3619eeda67c6Sjojemann (error == DUP_ERROR) ? gettext("Duplicate") : "", 3620eeda67c6Sjojemann (error == REQ_ERROR) ? gettext("Requires") : "", 3621eeda67c6Sjojemann mesg, 36227c478bd9Sstevel@tonic-gate (arg_indices[line] == 0) ? 1 : arg_indices[line]); 36237c478bd9Sstevel@tonic-gate } 36247c478bd9Sstevel@tonic-gate 36257c478bd9Sstevel@tonic-gate static int 36267c478bd9Sstevel@tonic-gate validate_properties(ips_act_props_t *cptr, boolean_t dir, boolean_t is_alg) 36277c478bd9Sstevel@tonic-gate { 36287c478bd9Sstevel@tonic-gate if (cptr->iap_action == SPD_ACTTYPE_PASS || 3629d5751483Smarkfen cptr->iap_action == SPD_ACTTYPE_DROP) { 36307c478bd9Sstevel@tonic-gate if (!dir) { 36317c478bd9Sstevel@tonic-gate warnx(gettext("dir string " 36327c478bd9Sstevel@tonic-gate "not found for bypass policy")); 36337c478bd9Sstevel@tonic-gate } 36347c478bd9Sstevel@tonic-gate 36357c478bd9Sstevel@tonic-gate if (is_alg) { 36367c478bd9Sstevel@tonic-gate warnx(gettext("Algorithms found for bypass policy")); 36377c478bd9Sstevel@tonic-gate return (-1); 36387c478bd9Sstevel@tonic-gate } 36397c478bd9Sstevel@tonic-gate return (0); 36407c478bd9Sstevel@tonic-gate } 36417c478bd9Sstevel@tonic-gate if (!is_alg) { 36428810c16bSdanmcd warnx(gettext("No IPsec algorithms given")); 36437c478bd9Sstevel@tonic-gate return (-1); 36447c478bd9Sstevel@tonic-gate } 36457c478bd9Sstevel@tonic-gate if (cptr->iap_attr == 0) { 36467c478bd9Sstevel@tonic-gate warnx(gettext("No SA attribute")); 36477c478bd9Sstevel@tonic-gate return (-1); 36487c478bd9Sstevel@tonic-gate } 36497c478bd9Sstevel@tonic-gate return (0); 36507c478bd9Sstevel@tonic-gate } 36517c478bd9Sstevel@tonic-gate 36527c478bd9Sstevel@tonic-gate /* 36537c478bd9Sstevel@tonic-gate * This function is called only to parse a single rule's worth of 36547c478bd9Sstevel@tonic-gate * action strings. This is called after parsing pattern and before 36557c478bd9Sstevel@tonic-gate * parsing properties. Thus we may have something in the leftover 36567c478bd9Sstevel@tonic-gate * buffer while parsing the pattern, which we need to handle here. 36577c478bd9Sstevel@tonic-gate */ 36587c478bd9Sstevel@tonic-gate static int 36597c478bd9Sstevel@tonic-gate parse_action(FILE *fp, char **action, char **leftover) 36607c478bd9Sstevel@tonic-gate { 36617c478bd9Sstevel@tonic-gate char *cp; 36627c478bd9Sstevel@tonic-gate char ibuf[MAXLEN]; 36637c478bd9Sstevel@tonic-gate char *tmp_buf; 36647c478bd9Sstevel@tonic-gate char *buf; 36657c478bd9Sstevel@tonic-gate boolean_t new_stuff; 36667c478bd9Sstevel@tonic-gate 36677c478bd9Sstevel@tonic-gate if (*leftover != NULL) { 36687c478bd9Sstevel@tonic-gate buf = *leftover; 36697c478bd9Sstevel@tonic-gate new_stuff = B_FALSE; 36707c478bd9Sstevel@tonic-gate goto scan; 36717c478bd9Sstevel@tonic-gate } 36727c478bd9Sstevel@tonic-gate while (fgets(ibuf, MAXLEN, fp) != NULL) { 36737c478bd9Sstevel@tonic-gate new_stuff = B_TRUE; 36747c478bd9Sstevel@tonic-gate if (ibuf[strlen(ibuf) - 1] == '\n') 36757c478bd9Sstevel@tonic-gate linecount++; 36767c478bd9Sstevel@tonic-gate buf = ibuf; 36777c478bd9Sstevel@tonic-gate scan: 36787c478bd9Sstevel@tonic-gate /* Truncate at the beginning of a comment */ 36797c478bd9Sstevel@tonic-gate cp = strchr(buf, '#'); 36807c478bd9Sstevel@tonic-gate if (cp != NULL) 36817c478bd9Sstevel@tonic-gate *cp = NULL; 36827c478bd9Sstevel@tonic-gate 36837c478bd9Sstevel@tonic-gate /* Skip any whitespace */ 36847c478bd9Sstevel@tonic-gate while (*buf != NULL && isspace(*buf)) 36857c478bd9Sstevel@tonic-gate buf++; 36867c478bd9Sstevel@tonic-gate 36877c478bd9Sstevel@tonic-gate /* Empty line */ 36887c478bd9Sstevel@tonic-gate if (*buf == NULL) 36897c478bd9Sstevel@tonic-gate continue; 36907c478bd9Sstevel@tonic-gate 36917c478bd9Sstevel@tonic-gate /* 36927c478bd9Sstevel@tonic-gate * Store the command for error reporting 36937c478bd9Sstevel@tonic-gate * and ipsec_conf_add(). 36947c478bd9Sstevel@tonic-gate */ 36957c478bd9Sstevel@tonic-gate if (new_stuff) { 36967c478bd9Sstevel@tonic-gate /* 36977c478bd9Sstevel@tonic-gate * Check for buffer overflow including the null 36987c478bd9Sstevel@tonic-gate * terminating character. 36997c478bd9Sstevel@tonic-gate */ 37007c478bd9Sstevel@tonic-gate int len = strlen(ibuf); 37017c478bd9Sstevel@tonic-gate if ((cbuf_offset + len + 1) >= CBUF_LEN) 37027c478bd9Sstevel@tonic-gate return (-1); 3703d5751483Smarkfen 37047c478bd9Sstevel@tonic-gate (void) strcpy(cbuf + cbuf_offset, ibuf); 37057c478bd9Sstevel@tonic-gate cbuf_offset += len; 37067c478bd9Sstevel@tonic-gate } 37077c478bd9Sstevel@tonic-gate /* 37087c478bd9Sstevel@tonic-gate * Start of the non-empty non-space character. 37097c478bd9Sstevel@tonic-gate */ 3710d5751483Smarkfen tmp_buf = buf; 37117c478bd9Sstevel@tonic-gate 37127c478bd9Sstevel@tonic-gate /* Skip until next whitespace or CURL_BEGIN */ 37137c478bd9Sstevel@tonic-gate while (*buf != NULL && !isspace(*buf) && 37147c478bd9Sstevel@tonic-gate *buf != CURL_BEGIN) 37157c478bd9Sstevel@tonic-gate buf++; 37167c478bd9Sstevel@tonic-gate 37177c478bd9Sstevel@tonic-gate if (*buf != NULL) { 3718d5751483Smarkfen if (tmp_buf == buf) /* No action token */ 3719d5751483Smarkfen goto error; 37207c478bd9Sstevel@tonic-gate if (*buf == CURL_BEGIN) { 37217c478bd9Sstevel@tonic-gate *buf = NULL; 37227c478bd9Sstevel@tonic-gate /* Allocate an extra byte for the null also */ 37237c478bd9Sstevel@tonic-gate if ((*action = malloc(strlen(tmp_buf) + 1)) == 37247c478bd9Sstevel@tonic-gate NULL) { 37257c478bd9Sstevel@tonic-gate warn("malloc"); 37267c478bd9Sstevel@tonic-gate return (ENOMEM); 37277c478bd9Sstevel@tonic-gate } 37287c478bd9Sstevel@tonic-gate (void) strcpy(*action, tmp_buf); 37297c478bd9Sstevel@tonic-gate *buf = CURL_BEGIN; 37307c478bd9Sstevel@tonic-gate } else { 37317c478bd9Sstevel@tonic-gate /* We have hit a space */ 37327c478bd9Sstevel@tonic-gate *buf++ = NULL; 37337c478bd9Sstevel@tonic-gate /* Allocate an extra byte for the null also */ 37347c478bd9Sstevel@tonic-gate if ((*action = malloc(strlen(tmp_buf) + 1)) == 37357c478bd9Sstevel@tonic-gate NULL) { 37367c478bd9Sstevel@tonic-gate warn("malloc"); 37377c478bd9Sstevel@tonic-gate return (ENOMEM); 37387c478bd9Sstevel@tonic-gate } 37397c478bd9Sstevel@tonic-gate (void) strcpy(*action, tmp_buf); 37407c478bd9Sstevel@tonic-gate } 37417c478bd9Sstevel@tonic-gate /* 37427c478bd9Sstevel@tonic-gate * Copy the rest of the line into the 37437c478bd9Sstevel@tonic-gate * leftover buffer. 37447c478bd9Sstevel@tonic-gate */ 37457c478bd9Sstevel@tonic-gate if (*buf != NULL) { 3746e3320f40Smarkfen (void) strlcpy(lo_buf, buf, sizeof (lo_buf)); 37477c478bd9Sstevel@tonic-gate *leftover = lo_buf; 37487c478bd9Sstevel@tonic-gate } else { 37497c478bd9Sstevel@tonic-gate *leftover = NULL; 37507c478bd9Sstevel@tonic-gate } 37517c478bd9Sstevel@tonic-gate } else { 37527c478bd9Sstevel@tonic-gate /* Allocate an extra byte for the null also */ 37537c478bd9Sstevel@tonic-gate if ((*action = malloc(strlen(tmp_buf) + 1)) == 37547c478bd9Sstevel@tonic-gate NULL) { 37557c478bd9Sstevel@tonic-gate warn("malloc"); 37567c478bd9Sstevel@tonic-gate return (ENOMEM); 37577c478bd9Sstevel@tonic-gate } 37587c478bd9Sstevel@tonic-gate (void) strcpy(*action, tmp_buf); 37597c478bd9Sstevel@tonic-gate *leftover = NULL; 37607c478bd9Sstevel@tonic-gate } 3761d5751483Smarkfen if (argindex >= ARG_BUF_LEN) { 3762d5751483Smarkfen warnx(gettext("(parsing one command) " 3763d5751483Smarkfen "Too many selectors before action.")); 37647c478bd9Sstevel@tonic-gate return (-1); 3765d5751483Smarkfen } 37667c478bd9Sstevel@tonic-gate arg_indices[argindex++] = linecount; 37677c478bd9Sstevel@tonic-gate return (PARSE_SUCCESS); 37687c478bd9Sstevel@tonic-gate } 37697c478bd9Sstevel@tonic-gate /* 37707c478bd9Sstevel@tonic-gate * Return error, on an empty action field. 37717c478bd9Sstevel@tonic-gate */ 3772d5751483Smarkfen error: 3773d5751483Smarkfen warnx(gettext("(parsing one command) " 3774d5751483Smarkfen "Missing action token.")); 37757c478bd9Sstevel@tonic-gate return (-1); 37767c478bd9Sstevel@tonic-gate } 37777c478bd9Sstevel@tonic-gate 37787c478bd9Sstevel@tonic-gate /* 37797c478bd9Sstevel@tonic-gate * This is called to parse pattern or properties that is enclosed 37807c478bd9Sstevel@tonic-gate * between CURL_BEGIN and CURL_END. 37817c478bd9Sstevel@tonic-gate */ 37827c478bd9Sstevel@tonic-gate static int 37837c478bd9Sstevel@tonic-gate parse_pattern_or_prop(FILE *fp, char *argvec[], char **leftover) 37847c478bd9Sstevel@tonic-gate { 37857c478bd9Sstevel@tonic-gate char *cp; 37867c478bd9Sstevel@tonic-gate int i = 0; 37877c478bd9Sstevel@tonic-gate boolean_t curl_begin_seen = B_FALSE; 37887c478bd9Sstevel@tonic-gate char ibuf[MAXLEN]; 37897c478bd9Sstevel@tonic-gate char *tmp_buf; 37907c478bd9Sstevel@tonic-gate char *buf; 37917c478bd9Sstevel@tonic-gate boolean_t new_stuff; 37927c478bd9Sstevel@tonic-gate 37937c478bd9Sstevel@tonic-gate /* 37947c478bd9Sstevel@tonic-gate * When parsing properties, leftover buffer could have the 37957c478bd9Sstevel@tonic-gate * leftovers of the previous fgets(). 37967c478bd9Sstevel@tonic-gate */ 37977c478bd9Sstevel@tonic-gate if (*leftover != NULL) { 37987c478bd9Sstevel@tonic-gate buf = *leftover; 37997c478bd9Sstevel@tonic-gate new_stuff = B_FALSE; 38007c478bd9Sstevel@tonic-gate goto scan; 38017c478bd9Sstevel@tonic-gate } 38027c478bd9Sstevel@tonic-gate while (fgets(ibuf, MAXLEN, fp) != NULL) { 38037c478bd9Sstevel@tonic-gate new_stuff = B_TRUE; 38047c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 38057c478bd9Sstevel@tonic-gate (void) printf("%s\n", ibuf); 38067c478bd9Sstevel@tonic-gate #endif 38077c478bd9Sstevel@tonic-gate if (ibuf[strlen(ibuf) - 1] == '\n') 38087c478bd9Sstevel@tonic-gate linecount++; 38097c478bd9Sstevel@tonic-gate buf = ibuf; 38107c478bd9Sstevel@tonic-gate scan: 38117c478bd9Sstevel@tonic-gate /* Truncate at the beginning of a comment */ 38127c478bd9Sstevel@tonic-gate cp = strchr(buf, '#'); 38137c478bd9Sstevel@tonic-gate if (cp != NULL) 38147c478bd9Sstevel@tonic-gate *cp = NULL; 38157c478bd9Sstevel@tonic-gate 38167c478bd9Sstevel@tonic-gate /* Skip any whitespace */ 38177c478bd9Sstevel@tonic-gate while (*buf != NULL && isspace(*buf)) 38187c478bd9Sstevel@tonic-gate buf++; 38197c478bd9Sstevel@tonic-gate 38207c478bd9Sstevel@tonic-gate /* Empty line */ 38217c478bd9Sstevel@tonic-gate if (*buf == NULL) 38227c478bd9Sstevel@tonic-gate continue; 38237c478bd9Sstevel@tonic-gate /* 38247c478bd9Sstevel@tonic-gate * Store the command for error reporting 38257c478bd9Sstevel@tonic-gate * and ipsec_conf_add(). 38267c478bd9Sstevel@tonic-gate */ 38277c478bd9Sstevel@tonic-gate if (new_stuff) { 38287c478bd9Sstevel@tonic-gate /* 38297c478bd9Sstevel@tonic-gate * Check for buffer overflow including the null 38307c478bd9Sstevel@tonic-gate * terminating character. 38317c478bd9Sstevel@tonic-gate */ 38327c478bd9Sstevel@tonic-gate int len = strlen(ibuf); 38337c478bd9Sstevel@tonic-gate if ((cbuf_offset + len + 1) >= CBUF_LEN) 38347c478bd9Sstevel@tonic-gate return (-1); 38357c478bd9Sstevel@tonic-gate (void) strcpy(cbuf + cbuf_offset, ibuf); 38367c478bd9Sstevel@tonic-gate cbuf_offset += len; 38377c478bd9Sstevel@tonic-gate } 38387c478bd9Sstevel@tonic-gate /* 38397c478bd9Sstevel@tonic-gate * First non-space character should be 38407c478bd9Sstevel@tonic-gate * a curly bracket. 38417c478bd9Sstevel@tonic-gate */ 38427c478bd9Sstevel@tonic-gate if (!curl_begin_seen) { 38437c478bd9Sstevel@tonic-gate if (*buf != CURL_BEGIN) { 38447c478bd9Sstevel@tonic-gate /* 38457c478bd9Sstevel@tonic-gate * If we never read a newline character, 38467c478bd9Sstevel@tonic-gate * we don't want to print 0. 38477c478bd9Sstevel@tonic-gate */ 3848d5751483Smarkfen warnx(gettext("line %d : pattern must start " 3849d5751483Smarkfen "with \"%c\" character"), 3850d5751483Smarkfen (linecount == 0) ? 1 : linecount, 3851d5751483Smarkfen CURL_BEGIN); 38527c478bd9Sstevel@tonic-gate return (-1); 38537c478bd9Sstevel@tonic-gate } 38547c478bd9Sstevel@tonic-gate buf++; 38557c478bd9Sstevel@tonic-gate curl_begin_seen = B_TRUE; 38567c478bd9Sstevel@tonic-gate } 38577c478bd9Sstevel@tonic-gate /* 38587c478bd9Sstevel@tonic-gate * Arguments are separated by white spaces or 38597c478bd9Sstevel@tonic-gate * newlines. Scan till you see a CURL_END. 38607c478bd9Sstevel@tonic-gate */ 38617c478bd9Sstevel@tonic-gate while (*buf != NULL) { 38627c478bd9Sstevel@tonic-gate if (*buf == CURL_END) { 38637c478bd9Sstevel@tonic-gate ret: 38647c478bd9Sstevel@tonic-gate *buf++ = NULL; 38657c478bd9Sstevel@tonic-gate /* 38667c478bd9Sstevel@tonic-gate * Copy the rest of the line into the 38677c478bd9Sstevel@tonic-gate * leftover buffer if any. 38687c478bd9Sstevel@tonic-gate */ 38697c478bd9Sstevel@tonic-gate if (*buf != NULL) { 3870e3320f40Smarkfen (void) strlcpy(lo_buf, buf, 3871e3320f40Smarkfen sizeof (lo_buf)); 38727c478bd9Sstevel@tonic-gate *leftover = lo_buf; 38737c478bd9Sstevel@tonic-gate } else { 38747c478bd9Sstevel@tonic-gate *leftover = NULL; 38757c478bd9Sstevel@tonic-gate } 38767c478bd9Sstevel@tonic-gate return (PARSE_SUCCESS); 38777c478bd9Sstevel@tonic-gate } 38787c478bd9Sstevel@tonic-gate /* 38797c478bd9Sstevel@tonic-gate * Skip any trailing whitespace until we see a 38807c478bd9Sstevel@tonic-gate * non white-space character. 38817c478bd9Sstevel@tonic-gate */ 38827c478bd9Sstevel@tonic-gate while (*buf != NULL && isspace(*buf)) 38837c478bd9Sstevel@tonic-gate buf++; 38847c478bd9Sstevel@tonic-gate 38857c478bd9Sstevel@tonic-gate if (*buf == CURL_END) 38867c478bd9Sstevel@tonic-gate goto ret; 38877c478bd9Sstevel@tonic-gate 38887c478bd9Sstevel@tonic-gate /* Scan the next line as this buffer is empty */ 38897c478bd9Sstevel@tonic-gate if (*buf == NULL) 38907c478bd9Sstevel@tonic-gate break; 38917c478bd9Sstevel@tonic-gate 38927c478bd9Sstevel@tonic-gate if (i >= MAXARGS) { 38937c478bd9Sstevel@tonic-gate warnx( 38947c478bd9Sstevel@tonic-gate gettext("Number of Arguments exceeded %d"), 38957c478bd9Sstevel@tonic-gate i); 38967c478bd9Sstevel@tonic-gate return (-1); 38977c478bd9Sstevel@tonic-gate } 38987c478bd9Sstevel@tonic-gate /* 38997c478bd9Sstevel@tonic-gate * Non-empty, Non-space buffer. 39007c478bd9Sstevel@tonic-gate */ 39017c478bd9Sstevel@tonic-gate tmp_buf = buf++; 39027c478bd9Sstevel@tonic-gate /* 39037c478bd9Sstevel@tonic-gate * Real scan of the argument takes place here. 39047c478bd9Sstevel@tonic-gate * Skip past till space or CURL_END. 39057c478bd9Sstevel@tonic-gate */ 39067c478bd9Sstevel@tonic-gate while (*buf != NULL && !isspace(*buf) && 39077c478bd9Sstevel@tonic-gate *buf != CURL_END) { 39087c478bd9Sstevel@tonic-gate buf++; 39097c478bd9Sstevel@tonic-gate } 39107c478bd9Sstevel@tonic-gate /* 39117c478bd9Sstevel@tonic-gate * Either a space or we have hit the CURL_END or 39127c478bd9Sstevel@tonic-gate * the real end. 39137c478bd9Sstevel@tonic-gate */ 39147c478bd9Sstevel@tonic-gate if (*buf != NULL) { 39157c478bd9Sstevel@tonic-gate if (*buf == CURL_END) { 39167c478bd9Sstevel@tonic-gate *buf++ = NULL; 39177c478bd9Sstevel@tonic-gate if ((argvec[i] = malloc(strlen(tmp_buf) 39187c478bd9Sstevel@tonic-gate + 1)) == NULL) { 39197c478bd9Sstevel@tonic-gate warn("malloc"); 39207c478bd9Sstevel@tonic-gate return (ENOMEM); 39217c478bd9Sstevel@tonic-gate } 39222eaf37a5Smarkfen if (strlen(tmp_buf) != 0) { 39232eaf37a5Smarkfen (void) strcpy(argvec[i], 39242eaf37a5Smarkfen tmp_buf); 39252eaf37a5Smarkfen if (argindex >= ARG_BUF_LEN) 3926d5751483Smarkfen goto toomanyargs; 39272eaf37a5Smarkfen arg_indices[argindex++] = 39282eaf37a5Smarkfen linecount; 39292eaf37a5Smarkfen } 39307c478bd9Sstevel@tonic-gate /* 39317c478bd9Sstevel@tonic-gate * Copy the rest of the line into the 39327c478bd9Sstevel@tonic-gate * leftover buffer. 39337c478bd9Sstevel@tonic-gate */ 39347c478bd9Sstevel@tonic-gate if (*buf != NULL) { 3935e3320f40Smarkfen (void) strlcpy(lo_buf, buf, 3936e3320f40Smarkfen sizeof (lo_buf)); 39377c478bd9Sstevel@tonic-gate *leftover = lo_buf; 39387c478bd9Sstevel@tonic-gate } else { 39397c478bd9Sstevel@tonic-gate *leftover = NULL; 39407c478bd9Sstevel@tonic-gate } 39417c478bd9Sstevel@tonic-gate return (PARSE_SUCCESS); 39427c478bd9Sstevel@tonic-gate } else { 39437c478bd9Sstevel@tonic-gate *buf++ = NULL; 39447c478bd9Sstevel@tonic-gate } 39457c478bd9Sstevel@tonic-gate } 39467c478bd9Sstevel@tonic-gate /* 39477c478bd9Sstevel@tonic-gate * Copy this argument and scan for the buffer more 39487c478bd9Sstevel@tonic-gate * if it is non-empty. If it is empty scan for 39497c478bd9Sstevel@tonic-gate * the next line. 39507c478bd9Sstevel@tonic-gate */ 39517c478bd9Sstevel@tonic-gate if ((argvec[i] = malloc(strlen(tmp_buf) + 1)) == 39527c478bd9Sstevel@tonic-gate NULL) { 39537c478bd9Sstevel@tonic-gate warn("malloc"); 39547c478bd9Sstevel@tonic-gate return (ENOMEM); 39557c478bd9Sstevel@tonic-gate } 39567c478bd9Sstevel@tonic-gate (void) strcpy(argvec[i++], tmp_buf); 3957d5751483Smarkfen if (argindex >= ARG_BUF_LEN) { 3958d5751483Smarkfen /* 3959d5751483Smarkfen * The number of tokens in a single policy entry 3960d5751483Smarkfen * exceeds the number of buffers available to fully 3961d5751483Smarkfen * parse the policy entry. 3962d5751483Smarkfen */ 3963d5751483Smarkfen toomanyargs: 3964d5751483Smarkfen warnx(gettext("(parsing one command) " 3965d5751483Smarkfen "Too many tokens in single policy entry.")); 39667c478bd9Sstevel@tonic-gate return (-1); 3967d5751483Smarkfen } 39687c478bd9Sstevel@tonic-gate arg_indices[argindex++] = linecount; 39697c478bd9Sstevel@tonic-gate } 39707c478bd9Sstevel@tonic-gate } 39717c478bd9Sstevel@tonic-gate /* 39727c478bd9Sstevel@tonic-gate * If nothing is given in the file, it is okay. 39737c478bd9Sstevel@tonic-gate * If something is given in the file and it is 39747c478bd9Sstevel@tonic-gate * not CURL_BEGIN, we would have returned error 39757c478bd9Sstevel@tonic-gate * above. If curl_begin_seen and we are here, 39767c478bd9Sstevel@tonic-gate * something is wrong. 39777c478bd9Sstevel@tonic-gate */ 3978d5751483Smarkfen if (curl_begin_seen) { 3979d5751483Smarkfen warnx(gettext("(parsing one command) " 3980d5751483Smarkfen "Pattern or Properties incomplete.")); 39817c478bd9Sstevel@tonic-gate return (-1); 3982d5751483Smarkfen } 39837c478bd9Sstevel@tonic-gate return (PARSE_EOF); /* Nothing more in the file */ 39847c478bd9Sstevel@tonic-gate } 39857c478bd9Sstevel@tonic-gate 39867c478bd9Sstevel@tonic-gate /* 39877c478bd9Sstevel@tonic-gate * Parse one command i.e {pattern} action {properties}. 39887c478bd9Sstevel@tonic-gate * 39897c478bd9Sstevel@tonic-gate * {pattern} ( action {prop} | pass | drop ) (or ...)* 39907c478bd9Sstevel@tonic-gate */ 39917c478bd9Sstevel@tonic-gate static int 39927c478bd9Sstevel@tonic-gate parse_one(FILE *fp, act_prop_t *act_props) 39937c478bd9Sstevel@tonic-gate { 39947c478bd9Sstevel@tonic-gate char *leftover; 39957c478bd9Sstevel@tonic-gate int ret; 39967c478bd9Sstevel@tonic-gate int i; 39977c478bd9Sstevel@tonic-gate int ap_num = 0; 39987c478bd9Sstevel@tonic-gate enum parse_state {pattern, action, prop } pstate; 39997c478bd9Sstevel@tonic-gate 40007c478bd9Sstevel@tonic-gate has_daprefix = has_saprefix = B_FALSE; 40017c478bd9Sstevel@tonic-gate 40027c478bd9Sstevel@tonic-gate (void) memset(act_props, 0, sizeof (act_prop_t)); 40037c478bd9Sstevel@tonic-gate pstate = pattern; 40047c478bd9Sstevel@tonic-gate 40057c478bd9Sstevel@tonic-gate ret = 0; 40067c478bd9Sstevel@tonic-gate leftover = NULL; 40077c478bd9Sstevel@tonic-gate argindex = 0; 40087c478bd9Sstevel@tonic-gate cbuf_offset = 0; 40097c478bd9Sstevel@tonic-gate assert(shp == NULL && dhp == NULL); 40107c478bd9Sstevel@tonic-gate 40117c478bd9Sstevel@tonic-gate for (;;) { 40127c478bd9Sstevel@tonic-gate switch (pstate) { 40137c478bd9Sstevel@tonic-gate case pattern: 40147c478bd9Sstevel@tonic-gate { 40157c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 40167c478bd9Sstevel@tonic-gate (void) printf("pattern\n"); 40177c478bd9Sstevel@tonic-gate #endif 40187c478bd9Sstevel@tonic-gate ret = parse_pattern_or_prop(fp, 40197c478bd9Sstevel@tonic-gate act_props->pattern, &leftover); 40207c478bd9Sstevel@tonic-gate if (ret == PARSE_EOF) { 40217c478bd9Sstevel@tonic-gate /* EOF reached */ 4022d5751483Smarkfen return (PARSE_EOF); 40237c478bd9Sstevel@tonic-gate } 40247c478bd9Sstevel@tonic-gate if (ret != 0) { 4025d5751483Smarkfen ret = -1; 40267c478bd9Sstevel@tonic-gate goto err; 40277c478bd9Sstevel@tonic-gate } 40287c478bd9Sstevel@tonic-gate pstate = action; 40297c478bd9Sstevel@tonic-gate break; 40307c478bd9Sstevel@tonic-gate } 40317c478bd9Sstevel@tonic-gate case action: 40327c478bd9Sstevel@tonic-gate { 40337c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 40347c478bd9Sstevel@tonic-gate (void) printf("action\n"); 40357c478bd9Sstevel@tonic-gate #endif 40367c478bd9Sstevel@tonic-gate ret = parse_action(fp, 40377c478bd9Sstevel@tonic-gate &act_props->ap[ap_num].act, &leftover); 40387c478bd9Sstevel@tonic-gate if (ret != 0) { 4039d5751483Smarkfen ret = -1; 40407c478bd9Sstevel@tonic-gate goto err; 40417c478bd9Sstevel@tonic-gate } 40427c478bd9Sstevel@tonic-gate 40437c478bd9Sstevel@tonic-gate /* 40447c478bd9Sstevel@tonic-gate * Validate action now itself so that we don't 40457c478bd9Sstevel@tonic-gate * proceed too much into the bad world. 40467c478bd9Sstevel@tonic-gate */ 40477c478bd9Sstevel@tonic-gate for (i = 0; action_table[i].string; i++) { 40487c478bd9Sstevel@tonic-gate if (strcmp(act_props->ap[ap_num].act, 40497c478bd9Sstevel@tonic-gate action_table[i].string) == 0) 40507c478bd9Sstevel@tonic-gate break; 40517c478bd9Sstevel@tonic-gate } 40527c478bd9Sstevel@tonic-gate 40537c478bd9Sstevel@tonic-gate if (action_table[i].tok_val == TOK_or) { 40547c478bd9Sstevel@tonic-gate /* hit an or, go again */ 40557c478bd9Sstevel@tonic-gate break; 40567c478bd9Sstevel@tonic-gate } 40577c478bd9Sstevel@tonic-gate 40587c478bd9Sstevel@tonic-gate if (action_table[i].string == NULL) { 40597c478bd9Sstevel@tonic-gate /* 40607c478bd9Sstevel@tonic-gate * If we never read a newline 40617c478bd9Sstevel@tonic-gate * character, we don't want 40627c478bd9Sstevel@tonic-gate * to print 0. 40637c478bd9Sstevel@tonic-gate */ 4064d5751483Smarkfen warnx(gettext("(parsing one command) " 40657c478bd9Sstevel@tonic-gate "Invalid action on line %d: %s"), 40667c478bd9Sstevel@tonic-gate (linecount == 0) ? 1 : linecount, 40677c478bd9Sstevel@tonic-gate act_props->ap[ap_num].act); 40687c478bd9Sstevel@tonic-gate return (-1); 40697c478bd9Sstevel@tonic-gate } 40707c478bd9Sstevel@tonic-gate 40717c478bd9Sstevel@tonic-gate pstate = prop; 40727c478bd9Sstevel@tonic-gate break; 40737c478bd9Sstevel@tonic-gate } 40747c478bd9Sstevel@tonic-gate case prop: 40757c478bd9Sstevel@tonic-gate { 40767c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 40777c478bd9Sstevel@tonic-gate (void) printf("prop\n"); 40787c478bd9Sstevel@tonic-gate #endif 40797c478bd9Sstevel@tonic-gate ret = parse_pattern_or_prop(fp, 40807c478bd9Sstevel@tonic-gate act_props->ap[ap_num].prop, &leftover); 40817c478bd9Sstevel@tonic-gate if (ret != 0) { 4082d5751483Smarkfen if (ret == PARSE_EOF) { 4083d5751483Smarkfen warnx(gettext("(parsing one command) " 4084d5751483Smarkfen "Missing properties.")); 4085d5751483Smarkfen } 4086d5751483Smarkfen ret = -1; 40877c478bd9Sstevel@tonic-gate goto err; 40887c478bd9Sstevel@tonic-gate } 40897c478bd9Sstevel@tonic-gate 40907c478bd9Sstevel@tonic-gate if (leftover != NULL) { 40917c478bd9Sstevel@tonic-gate /* Accomodate spaces at the end */ 40927c478bd9Sstevel@tonic-gate while (*leftover != NULL) { 4093d5751483Smarkfen if (*leftover == BACK_SLASH) { 4094d5751483Smarkfen warnx(gettext("Invalid line " 4095d5751483Smarkfen "continuation character.")); 4096d5751483Smarkfen ret = -1; 4097d5751483Smarkfen goto err; 4098d5751483Smarkfen } 40997c478bd9Sstevel@tonic-gate if (*leftover == 'o') { 41007c478bd9Sstevel@tonic-gate leftover++; 41017c478bd9Sstevel@tonic-gate if (*leftover == 'r') { 41027c478bd9Sstevel@tonic-gate leftover++; 41037c478bd9Sstevel@tonic-gate ap_num++; 41047c478bd9Sstevel@tonic-gate pstate = action; 41057c478bd9Sstevel@tonic-gate goto again; 41067c478bd9Sstevel@tonic-gate } 41077c478bd9Sstevel@tonic-gate } 41087c478bd9Sstevel@tonic-gate if (!isspace(*leftover)) { 41097c478bd9Sstevel@tonic-gate ret = -1; 41107c478bd9Sstevel@tonic-gate goto err; 41117c478bd9Sstevel@tonic-gate } 41127c478bd9Sstevel@tonic-gate leftover++; 41137c478bd9Sstevel@tonic-gate } 41147c478bd9Sstevel@tonic-gate return (0); 41157c478bd9Sstevel@tonic-gate } 41167c478bd9Sstevel@tonic-gate ap_num++; 41177c478bd9Sstevel@tonic-gate if (ap_num > MAXARGS) 41187c478bd9Sstevel@tonic-gate return (0); 41197c478bd9Sstevel@tonic-gate pstate = action; /* or */ 41207c478bd9Sstevel@tonic-gate break; 41217c478bd9Sstevel@tonic-gate } /* case prop: */ 41227c478bd9Sstevel@tonic-gate } /* switch(pstate) */ 41237c478bd9Sstevel@tonic-gate 41247c478bd9Sstevel@tonic-gate again: 4125d5751483Smarkfen if (ap_num > MAXARGS) { 4126d5751483Smarkfen warnx(gettext("Too many actions.")); 4127d5751483Smarkfen return (-1); 4128d5751483Smarkfen } 4129d5751483Smarkfen } /* for(;;) */ 41307c478bd9Sstevel@tonic-gate err: 41317c478bd9Sstevel@tonic-gate if (ret != 0) { 41327c478bd9Sstevel@tonic-gate /* 41337c478bd9Sstevel@tonic-gate * If we never read a newline character, we don't want 41347c478bd9Sstevel@tonic-gate * to print 0. 41357c478bd9Sstevel@tonic-gate */ 41367c478bd9Sstevel@tonic-gate warnx(gettext("Error before or at line %d"), 41377c478bd9Sstevel@tonic-gate (linecount == 0) ? 1 : linecount); 41387c478bd9Sstevel@tonic-gate } 41397c478bd9Sstevel@tonic-gate return (ret); 41407c478bd9Sstevel@tonic-gate } 41417c478bd9Sstevel@tonic-gate 41427c478bd9Sstevel@tonic-gate /* 41437c478bd9Sstevel@tonic-gate * convert an act_propts_t to an ips_conf_t 41447c478bd9Sstevel@tonic-gate */ 41457c478bd9Sstevel@tonic-gate 41467c478bd9Sstevel@tonic-gate static int 41477c478bd9Sstevel@tonic-gate form_ipsec_conf(act_prop_t *act_props, ips_conf_t *cptr) 41487c478bd9Sstevel@tonic-gate { 41497c478bd9Sstevel@tonic-gate int i, j, k; 41507c478bd9Sstevel@tonic-gate int tok_count = 0; 41517c478bd9Sstevel@tonic-gate struct protoent *pent; 41527c478bd9Sstevel@tonic-gate boolean_t saddr, daddr, ipsec_aalg, ipsec_ealg, ipsec_eaalg, dir; 41537c478bd9Sstevel@tonic-gate boolean_t old_style, new_style; 41547c478bd9Sstevel@tonic-gate struct in_addr mask; 41557c478bd9Sstevel@tonic-gate int line_no; 41567c478bd9Sstevel@tonic-gate int ret; 41577c478bd9Sstevel@tonic-gate int ap_num = 0; 41587c478bd9Sstevel@tonic-gate int type, code, type_end, code_end; 41597c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 41607c478bd9Sstevel@tonic-gate /* 41617c478bd9Sstevel@tonic-gate * pattern => act_props->pattern 41627c478bd9Sstevel@tonic-gate * action => act_props->ap[].act 41637c478bd9Sstevel@tonic-gate * properties => act_props->ap[].prop 41647c478bd9Sstevel@tonic-gate */ 41657c478bd9Sstevel@tonic-gate (void) printf("\npattern\n------------\n"); 41667c478bd9Sstevel@tonic-gate for (i = 0; act_props->pattern[i] != NULL; i++) 41677c478bd9Sstevel@tonic-gate (void) printf("%s\n", act_props->pattern[i]); 41687c478bd9Sstevel@tonic-gate (void) printf("apz\n----------\n"); 41697c478bd9Sstevel@tonic-gate for (j = 0; act_props->ap[j].act != NULL; j++) { 41707c478bd9Sstevel@tonic-gate 41717c478bd9Sstevel@tonic-gate (void) printf("act%d->%s\n", j, act_props->ap[j].act); 41727c478bd9Sstevel@tonic-gate for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 41737c478bd9Sstevel@tonic-gate (void) printf("%dprop%d->%s\n", 41747c478bd9Sstevel@tonic-gate j, i, act_props->ap[j].prop[i]); 41757c478bd9Sstevel@tonic-gate } 41767c478bd9Sstevel@tonic-gate (void) printf("------------\n\n"); 41777c478bd9Sstevel@tonic-gate #endif 41787c478bd9Sstevel@tonic-gate 41797c478bd9Sstevel@tonic-gate (void) memset(cptr, 0, sizeof (ips_conf_t)); 41807c478bd9Sstevel@tonic-gate saddr = daddr = ipsec_aalg = ipsec_ealg = ipsec_eaalg = dir = B_FALSE; 41817c478bd9Sstevel@tonic-gate old_style = new_style = B_FALSE; 41827c478bd9Sstevel@tonic-gate /* 41837c478bd9Sstevel@tonic-gate * Get the Pattern. NULL pattern is valid. 41847c478bd9Sstevel@tonic-gate */ 41857c478bd9Sstevel@tonic-gate for (i = 0, line_no = 0; act_props->pattern[i]; i++, line_no++) { 41867c478bd9Sstevel@tonic-gate for (j = 0; pattern_table[j].string; j++) { 41877c478bd9Sstevel@tonic-gate if (strcmp(act_props->pattern[i], 41887c478bd9Sstevel@tonic-gate pattern_table[j].string) == 0) 41897c478bd9Sstevel@tonic-gate break; 41907c478bd9Sstevel@tonic-gate } 41917c478bd9Sstevel@tonic-gate 41927c478bd9Sstevel@tonic-gate if (pattern_table[j].string == NULL) { 41937c478bd9Sstevel@tonic-gate /* 41947c478bd9Sstevel@tonic-gate * If we never read a newline character, we don't want 41957c478bd9Sstevel@tonic-gate * to print 0. 41967c478bd9Sstevel@tonic-gate */ 41977c478bd9Sstevel@tonic-gate warnx(gettext("Invalid pattern on line %d: %s"), 41987c478bd9Sstevel@tonic-gate (arg_indices[line_no] == 0) ? 1 : 41997c478bd9Sstevel@tonic-gate arg_indices[line_no], act_props->pattern[i]); 42007c478bd9Sstevel@tonic-gate return (-1); 42017c478bd9Sstevel@tonic-gate } 42027c478bd9Sstevel@tonic-gate 42037c478bd9Sstevel@tonic-gate cptr->patt_tok[tok_count++] = pattern_table[j].tok_val; 42047c478bd9Sstevel@tonic-gate 42057c478bd9Sstevel@tonic-gate switch (pattern_table[j].tok_val) { 42067c478bd9Sstevel@tonic-gate 42077c478bd9Sstevel@tonic-gate case TOK_dir: 42087c478bd9Sstevel@tonic-gate i++, line_no++; 42097c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 42107c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 42117c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_DIR, line_no); 42127c478bd9Sstevel@tonic-gate return (-1); 42137c478bd9Sstevel@tonic-gate } 42147c478bd9Sstevel@tonic-gate 42157c478bd9Sstevel@tonic-gate if (strncmp(act_props->pattern[i], "in", 2) == 0) { 42167c478bd9Sstevel@tonic-gate cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 42177c478bd9Sstevel@tonic-gate } else if (strncmp( 42187c478bd9Sstevel@tonic-gate act_props->pattern[i], "out", 3) == 0) { 42197c478bd9Sstevel@tonic-gate cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 42207c478bd9Sstevel@tonic-gate } else if (strncmp( 42217c478bd9Sstevel@tonic-gate act_props->pattern[i], "both", 4) == 0) { 42227c478bd9Sstevel@tonic-gate if (old_style) { 42237c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 42247c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_DIR, line_no); 42257c478bd9Sstevel@tonic-gate return (-1); 42267c478bd9Sstevel@tonic-gate } 42277c478bd9Sstevel@tonic-gate new_style = B_TRUE; 42287c478bd9Sstevel@tonic-gate cptr->ips_dir = 42297c478bd9Sstevel@tonic-gate SPD_RULE_FLAG_OUTBOUND | 42307c478bd9Sstevel@tonic-gate SPD_RULE_FLAG_INBOUND; 42317c478bd9Sstevel@tonic-gate } else { 42327c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 42337c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_DIR, line_no); 42347c478bd9Sstevel@tonic-gate return (-1); 42357c478bd9Sstevel@tonic-gate } 42367c478bd9Sstevel@tonic-gate dir = B_TRUE; 42377c478bd9Sstevel@tonic-gate break; 42387c478bd9Sstevel@tonic-gate 42397c478bd9Sstevel@tonic-gate case TOK_local: 42407c478bd9Sstevel@tonic-gate if (old_style) { 42417c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 42427c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_ADDRESS, line_no); 42437c478bd9Sstevel@tonic-gate return (-1); 42447c478bd9Sstevel@tonic-gate } 42457c478bd9Sstevel@tonic-gate new_style = B_TRUE; 42467c478bd9Sstevel@tonic-gate 42477c478bd9Sstevel@tonic-gate if (saddr) { 42487c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 42497c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_ADDRESS, line_no); 42507c478bd9Sstevel@tonic-gate return (-1); 42517c478bd9Sstevel@tonic-gate } 42527c478bd9Sstevel@tonic-gate /* 42537c478bd9Sstevel@tonic-gate * Use this to detect duplicates rather 42547c478bd9Sstevel@tonic-gate * than 0 like other cases, because 0 for 42557c478bd9Sstevel@tonic-gate * address means INADDR_ANY. 42567c478bd9Sstevel@tonic-gate */ 42577c478bd9Sstevel@tonic-gate saddr = B_TRUE; 42587c478bd9Sstevel@tonic-gate cptr->has_saddr = 1; 42597c478bd9Sstevel@tonic-gate /* 42607c478bd9Sstevel@tonic-gate * Advance to the string containing 42617c478bd9Sstevel@tonic-gate * the address. 42627c478bd9Sstevel@tonic-gate */ 42637c478bd9Sstevel@tonic-gate i++, line_no++; 42647c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 42657c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 42667c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_ADDRESS, line_no); 42677c478bd9Sstevel@tonic-gate return (-1); 42687c478bd9Sstevel@tonic-gate } 42697c478bd9Sstevel@tonic-gate if (parse_address(IPSEC_CONF_SRC_ADDRESS, 42707c478bd9Sstevel@tonic-gate act_props->pattern[i]) != 0) { 42717c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 42727c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_ADDRESS, line_no); 42737c478bd9Sstevel@tonic-gate return (-1); 42747c478bd9Sstevel@tonic-gate } 42757c478bd9Sstevel@tonic-gate if (!cptr->has_smask) 42767c478bd9Sstevel@tonic-gate cptr->has_smask = has_saprefix; 42777c478bd9Sstevel@tonic-gate 42787c478bd9Sstevel@tonic-gate break; 42797c478bd9Sstevel@tonic-gate case TOK_remote: 42807c478bd9Sstevel@tonic-gate if (old_style) { 42817c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 42827c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_ADDRESS, line_no); 42837c478bd9Sstevel@tonic-gate return (-1); 42847c478bd9Sstevel@tonic-gate } 42857c478bd9Sstevel@tonic-gate new_style = B_TRUE; 42867c478bd9Sstevel@tonic-gate 42877c478bd9Sstevel@tonic-gate if (daddr) { 42887c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 42897c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_ADDRESS, line_no); 42907c478bd9Sstevel@tonic-gate return (-1); 42917c478bd9Sstevel@tonic-gate } 42927c478bd9Sstevel@tonic-gate /* 42937c478bd9Sstevel@tonic-gate * Use this to detect duplicates rather 42947c478bd9Sstevel@tonic-gate * than 0 like other cases, because 0 for 42957c478bd9Sstevel@tonic-gate * address means INADDR_ANY. 42967c478bd9Sstevel@tonic-gate */ 42977c478bd9Sstevel@tonic-gate daddr = B_TRUE; 42987c478bd9Sstevel@tonic-gate cptr->has_daddr = 1; 42997c478bd9Sstevel@tonic-gate /* 43007c478bd9Sstevel@tonic-gate * Advance to the string containing 43017c478bd9Sstevel@tonic-gate * the address. 43027c478bd9Sstevel@tonic-gate */ 43037c478bd9Sstevel@tonic-gate i++, line_no++; 43047c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 43057c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 43067c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_ADDRESS, line_no); 43077c478bd9Sstevel@tonic-gate return (-1); 43087c478bd9Sstevel@tonic-gate } 43097c478bd9Sstevel@tonic-gate if (parse_address(IPSEC_CONF_DST_ADDRESS, 43107c478bd9Sstevel@tonic-gate act_props->pattern[i]) != 0) { 43117c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 43127c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_ADDRESS, line_no); 43137c478bd9Sstevel@tonic-gate return (-1); 43147c478bd9Sstevel@tonic-gate } 43157c478bd9Sstevel@tonic-gate if (!cptr->has_dmask) 43167c478bd9Sstevel@tonic-gate cptr->has_dmask = has_daprefix; 43177c478bd9Sstevel@tonic-gate break; 43187c478bd9Sstevel@tonic-gate 43197c478bd9Sstevel@tonic-gate case TOK_saddr: 43207c478bd9Sstevel@tonic-gate if (new_style) { 43217c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 43227c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_ADDRESS, line_no); 43237c478bd9Sstevel@tonic-gate return (-1); 43247c478bd9Sstevel@tonic-gate } 43257c478bd9Sstevel@tonic-gate old_style = B_TRUE; 43267c478bd9Sstevel@tonic-gate 43277c478bd9Sstevel@tonic-gate if (saddr) { 43287c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 43297c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_ADDRESS, line_no); 43307c478bd9Sstevel@tonic-gate return (-1); 43317c478bd9Sstevel@tonic-gate } 43327c478bd9Sstevel@tonic-gate /* 43337c478bd9Sstevel@tonic-gate * Use this to detect duplicates rather 43347c478bd9Sstevel@tonic-gate * than 0 like other cases, because 0 for 43357c478bd9Sstevel@tonic-gate * address means INADDR_ANY. 43367c478bd9Sstevel@tonic-gate */ 43377c478bd9Sstevel@tonic-gate saddr = B_TRUE; 43387c478bd9Sstevel@tonic-gate cptr->has_saddr = 1; 43397c478bd9Sstevel@tonic-gate /* 43407c478bd9Sstevel@tonic-gate * Advance to the string containing 43417c478bd9Sstevel@tonic-gate * the address. 43427c478bd9Sstevel@tonic-gate */ 43437c478bd9Sstevel@tonic-gate i++, line_no++; 43447c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 43457c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 43467c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_ADDRESS, line_no); 43477c478bd9Sstevel@tonic-gate return (-1); 43487c478bd9Sstevel@tonic-gate } 43497c478bd9Sstevel@tonic-gate 43507c478bd9Sstevel@tonic-gate if (parse_address(IPSEC_CONF_SRC_ADDRESS, 43517c478bd9Sstevel@tonic-gate act_props->pattern[i]) != 0) { 43527c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 43537c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_ADDRESS, line_no); 43547c478bd9Sstevel@tonic-gate return (-1); 43557c478bd9Sstevel@tonic-gate } 43567c478bd9Sstevel@tonic-gate /* shp or bhp? */ 43577c478bd9Sstevel@tonic-gate if (!cptr->has_smask) 43587c478bd9Sstevel@tonic-gate cptr->has_smask = has_saprefix; 43597c478bd9Sstevel@tonic-gate break; 43607c478bd9Sstevel@tonic-gate 43617c478bd9Sstevel@tonic-gate case TOK_daddr: 43627c478bd9Sstevel@tonic-gate if (new_style) { 43637c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 43647c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_ADDRESS, line_no); 43657c478bd9Sstevel@tonic-gate return (-1); 43667c478bd9Sstevel@tonic-gate } 43677c478bd9Sstevel@tonic-gate old_style = B_TRUE; 43687c478bd9Sstevel@tonic-gate 43697c478bd9Sstevel@tonic-gate if (daddr) { 43707c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 43717c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_ADDRESS, line_no); 43727c478bd9Sstevel@tonic-gate return (-1); 43737c478bd9Sstevel@tonic-gate } 43747c478bd9Sstevel@tonic-gate /* 43757c478bd9Sstevel@tonic-gate * Use this to detect duplicates rather 43767c478bd9Sstevel@tonic-gate * than 0 like other cases, because 0 for 43777c478bd9Sstevel@tonic-gate * address means INADDR_ANY. 43787c478bd9Sstevel@tonic-gate */ 43797c478bd9Sstevel@tonic-gate daddr = B_TRUE; 43807c478bd9Sstevel@tonic-gate cptr->has_daddr = 1; 43817c478bd9Sstevel@tonic-gate /* 43827c478bd9Sstevel@tonic-gate * Advance to the string containing 43837c478bd9Sstevel@tonic-gate * the address. 43847c478bd9Sstevel@tonic-gate */ 43857c478bd9Sstevel@tonic-gate i++, line_no++; 43867c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 43877c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 43887c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_ADDRESS, line_no); 43897c478bd9Sstevel@tonic-gate return (-1); 43907c478bd9Sstevel@tonic-gate } 43917c478bd9Sstevel@tonic-gate if (parse_address(IPSEC_CONF_DST_ADDRESS, 43927c478bd9Sstevel@tonic-gate act_props->pattern[i]) != 0) { 43937c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 43947c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_ADDRESS, line_no); 43957c478bd9Sstevel@tonic-gate return (-1); 43967c478bd9Sstevel@tonic-gate } 43977c478bd9Sstevel@tonic-gate if (!cptr->has_dmask) 43987c478bd9Sstevel@tonic-gate cptr->has_dmask = has_daprefix; 43997c478bd9Sstevel@tonic-gate break; 44007c478bd9Sstevel@tonic-gate 44017c478bd9Sstevel@tonic-gate case TOK_sport: 44027c478bd9Sstevel@tonic-gate if (new_style) { 44037c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 44047c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_PORT, line_no); 44057c478bd9Sstevel@tonic-gate return (-1); 44067c478bd9Sstevel@tonic-gate } 44077c478bd9Sstevel@tonic-gate old_style = B_TRUE; 44087c478bd9Sstevel@tonic-gate 44097c478bd9Sstevel@tonic-gate if (cptr->ips_src_port_min != 0) { 44107c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 44117c478bd9Sstevel@tonic-gate line_no); 44127c478bd9Sstevel@tonic-gate return (-1); 44137c478bd9Sstevel@tonic-gate } 44147c478bd9Sstevel@tonic-gate i++, line_no++; 44157c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 44167c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 44177c478bd9Sstevel@tonic-gate line_no); 44187c478bd9Sstevel@tonic-gate return (-1); 44197c478bd9Sstevel@tonic-gate } 44207c478bd9Sstevel@tonic-gate ret = parse_port(IPSEC_CONF_SRC_PORT, 44217c478bd9Sstevel@tonic-gate act_props->pattern[i], cptr); 44227c478bd9Sstevel@tonic-gate if (ret != 0) { 44237c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 44247c478bd9Sstevel@tonic-gate line_no); 44257c478bd9Sstevel@tonic-gate return (-1); 44267c478bd9Sstevel@tonic-gate } 44277c478bd9Sstevel@tonic-gate break; 44287c478bd9Sstevel@tonic-gate case TOK_dport: 44297c478bd9Sstevel@tonic-gate if (new_style) { 44307c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 44317c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_PORT, line_no); 44327c478bd9Sstevel@tonic-gate return (-1); 44337c478bd9Sstevel@tonic-gate } 44347c478bd9Sstevel@tonic-gate old_style = B_TRUE; 44357c478bd9Sstevel@tonic-gate 44367c478bd9Sstevel@tonic-gate if (cptr->ips_dst_port_min != 0) { 44377c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 44387c478bd9Sstevel@tonic-gate line_no); 44397c478bd9Sstevel@tonic-gate return (-1); 44407c478bd9Sstevel@tonic-gate } 44417c478bd9Sstevel@tonic-gate i++, line_no++; 44427c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 44437c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 44447c478bd9Sstevel@tonic-gate line_no); 44457c478bd9Sstevel@tonic-gate return (-1); 44467c478bd9Sstevel@tonic-gate } 44477c478bd9Sstevel@tonic-gate ret = parse_port(IPSEC_CONF_DST_PORT, 44487c478bd9Sstevel@tonic-gate act_props->pattern[i], 44497c478bd9Sstevel@tonic-gate cptr); 44507c478bd9Sstevel@tonic-gate if (ret != 0) { 44517c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 44527c478bd9Sstevel@tonic-gate line_no); 44537c478bd9Sstevel@tonic-gate return (-1); 44547c478bd9Sstevel@tonic-gate } 44557c478bd9Sstevel@tonic-gate break; 44567c478bd9Sstevel@tonic-gate 44577c478bd9Sstevel@tonic-gate case TOK_lport: 44587c478bd9Sstevel@tonic-gate if (old_style) { 44597c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 44607c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_PORT, line_no); 44617c478bd9Sstevel@tonic-gate return (-1); 44627c478bd9Sstevel@tonic-gate } 44637c478bd9Sstevel@tonic-gate new_style = B_TRUE; 44647c478bd9Sstevel@tonic-gate 44657c478bd9Sstevel@tonic-gate if (cptr->ips_src_port_min != 0) { 44667c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, IPSEC_CONF_SRC_PORT, 44677c478bd9Sstevel@tonic-gate line_no); 44687c478bd9Sstevel@tonic-gate return (-1); 44697c478bd9Sstevel@tonic-gate } 44707c478bd9Sstevel@tonic-gate i++, line_no++; 44717c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 44727c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 44737c478bd9Sstevel@tonic-gate line_no); 44747c478bd9Sstevel@tonic-gate return (-1); 44757c478bd9Sstevel@tonic-gate } 44767c478bd9Sstevel@tonic-gate ret = parse_port(IPSEC_CONF_SRC_PORT, 44777c478bd9Sstevel@tonic-gate act_props->pattern[i], 44787c478bd9Sstevel@tonic-gate cptr); 44797c478bd9Sstevel@tonic-gate if (ret != 0) { 44807c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_SRC_PORT, 44817c478bd9Sstevel@tonic-gate line_no); 44827c478bd9Sstevel@tonic-gate return (-1); 44837c478bd9Sstevel@tonic-gate } 44847c478bd9Sstevel@tonic-gate break; 44857c478bd9Sstevel@tonic-gate 44867c478bd9Sstevel@tonic-gate case TOK_rport: 44877c478bd9Sstevel@tonic-gate if (old_style) { 44887c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 44897c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_PORT, line_no); 44907c478bd9Sstevel@tonic-gate return (-1); 44917c478bd9Sstevel@tonic-gate } 44927c478bd9Sstevel@tonic-gate new_style = B_TRUE; 44937c478bd9Sstevel@tonic-gate 44947c478bd9Sstevel@tonic-gate if (cptr->ips_dst_port_min != 0) { 44957c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, IPSEC_CONF_DST_PORT, 44967c478bd9Sstevel@tonic-gate line_no); 44977c478bd9Sstevel@tonic-gate return (-1); 44987c478bd9Sstevel@tonic-gate } 44997c478bd9Sstevel@tonic-gate i++, line_no++; 45007c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 45017c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 45027c478bd9Sstevel@tonic-gate line_no); 45037c478bd9Sstevel@tonic-gate return (-1); 45047c478bd9Sstevel@tonic-gate } 45057c478bd9Sstevel@tonic-gate ret = parse_port(IPSEC_CONF_DST_PORT, 45067c478bd9Sstevel@tonic-gate act_props->pattern[i], 45077c478bd9Sstevel@tonic-gate cptr); 45087c478bd9Sstevel@tonic-gate if (ret != 0) { 45097c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_DST_PORT, 45107c478bd9Sstevel@tonic-gate line_no); 45117c478bd9Sstevel@tonic-gate return (-1); 45127c478bd9Sstevel@tonic-gate } 45137c478bd9Sstevel@tonic-gate break; 45147c478bd9Sstevel@tonic-gate 45157c478bd9Sstevel@tonic-gate case TOK_smask: 45167c478bd9Sstevel@tonic-gate if (new_style) { 45177c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 45187c478bd9Sstevel@tonic-gate IPSEC_CONF_SRC_MASK, line_no); 45197c478bd9Sstevel@tonic-gate return (-1); 45207c478bd9Sstevel@tonic-gate } 45217c478bd9Sstevel@tonic-gate old_style = B_TRUE; 45227c478bd9Sstevel@tonic-gate cptr->has_smask = B_TRUE; 45237c478bd9Sstevel@tonic-gate 45247c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR(&cptr->ips_src_mask_v6, &mask); 45257c478bd9Sstevel@tonic-gate if (mask.s_addr != 0) { 45267c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, IPSEC_CONF_SRC_MASK, 45277c478bd9Sstevel@tonic-gate line_no); 45287c478bd9Sstevel@tonic-gate return (-1); 45297c478bd9Sstevel@tonic-gate } 45307c478bd9Sstevel@tonic-gate i++, line_no++; 45317c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 45327c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 45337c478bd9Sstevel@tonic-gate line_no); 45347c478bd9Sstevel@tonic-gate return (-1); 45357c478bd9Sstevel@tonic-gate } 45367c478bd9Sstevel@tonic-gate ret = parse_mask(IPSEC_CONF_SRC_MASK, 45377c478bd9Sstevel@tonic-gate act_props->pattern[i], 45387c478bd9Sstevel@tonic-gate cptr); 45397c478bd9Sstevel@tonic-gate if (ret != 0) { 45407c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_SRC_MASK, 45417c478bd9Sstevel@tonic-gate line_no); 45427c478bd9Sstevel@tonic-gate return (-1); 45437c478bd9Sstevel@tonic-gate } 45447c478bd9Sstevel@tonic-gate break; 45457c478bd9Sstevel@tonic-gate case TOK_dmask: 45467c478bd9Sstevel@tonic-gate if (new_style) { 45477c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 45487c478bd9Sstevel@tonic-gate IPSEC_CONF_DST_MASK, line_no); 45497c478bd9Sstevel@tonic-gate return (-1); 45507c478bd9Sstevel@tonic-gate } 45517c478bd9Sstevel@tonic-gate old_style = B_TRUE; 45527c478bd9Sstevel@tonic-gate cptr->has_dmask = B_TRUE; 45537c478bd9Sstevel@tonic-gate 45547c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR(&cptr->ips_dst_mask_v6, &mask); 45557c478bd9Sstevel@tonic-gate if (mask.s_addr != 0) { 45567c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, IPSEC_CONF_DST_MASK, 45577c478bd9Sstevel@tonic-gate line_no); 45587c478bd9Sstevel@tonic-gate return (-1); 45597c478bd9Sstevel@tonic-gate } 45607c478bd9Sstevel@tonic-gate i++, line_no++; 45617c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 45627c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 45637c478bd9Sstevel@tonic-gate line_no); 45647c478bd9Sstevel@tonic-gate return (-1); 45657c478bd9Sstevel@tonic-gate } 45667c478bd9Sstevel@tonic-gate ret = parse_mask(IPSEC_CONF_DST_MASK, 45677c478bd9Sstevel@tonic-gate act_props->pattern[i], 45687c478bd9Sstevel@tonic-gate cptr); 45697c478bd9Sstevel@tonic-gate if (ret != 0) { 45707c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, IPSEC_CONF_DST_MASK, 45717c478bd9Sstevel@tonic-gate line_no); 45727c478bd9Sstevel@tonic-gate return (-1); 45737c478bd9Sstevel@tonic-gate } 45747c478bd9Sstevel@tonic-gate break; 45757c478bd9Sstevel@tonic-gate case TOK_ulp: 45767c478bd9Sstevel@tonic-gate if (cptr->ips_ulp_prot != 0) { 45777c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 45787c478bd9Sstevel@tonic-gate IPSEC_CONF_ULP, line_no); 45797c478bd9Sstevel@tonic-gate return (-1); 45807c478bd9Sstevel@tonic-gate } 45817c478bd9Sstevel@tonic-gate i++, line_no++; 45827c478bd9Sstevel@tonic-gate if (act_props->pattern[i] == NULL) { 45837c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 45847c478bd9Sstevel@tonic-gate IPSEC_CONF_ULP, line_no); 45857c478bd9Sstevel@tonic-gate return (-1); 45867c478bd9Sstevel@tonic-gate } 45877c478bd9Sstevel@tonic-gate pent = getprotobyname(act_props->pattern[i]); 45887c478bd9Sstevel@tonic-gate if (pent == NULL) { 45897c478bd9Sstevel@tonic-gate int ulp; 45907c478bd9Sstevel@tonic-gate ulp = parse_int(act_props->pattern[i]); 45917c478bd9Sstevel@tonic-gate if (ulp == -1) { 45927c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 45937c478bd9Sstevel@tonic-gate IPSEC_CONF_ULP, line_no); 45947c478bd9Sstevel@tonic-gate return (-1); 45957c478bd9Sstevel@tonic-gate } 45967c478bd9Sstevel@tonic-gate cptr->ips_ulp_prot = ulp; 45977c478bd9Sstevel@tonic-gate } else { 45987c478bd9Sstevel@tonic-gate cptr->ips_ulp_prot = pent->p_proto; 45997c478bd9Sstevel@tonic-gate } 46007c478bd9Sstevel@tonic-gate break; 46017c478bd9Sstevel@tonic-gate case TOK_type: 46027c478bd9Sstevel@tonic-gate if (cptr->has_type) { 46037c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 46047c478bd9Sstevel@tonic-gate IPSEC_CONF_ICMP_TYPE, line_no); 46057c478bd9Sstevel@tonic-gate return (-1); 46067c478bd9Sstevel@tonic-gate } 46077c478bd9Sstevel@tonic-gate 46087c478bd9Sstevel@tonic-gate i++, line_no++; 46097c478bd9Sstevel@tonic-gate type = parse_type_code(act_props->pattern[i], 46107c478bd9Sstevel@tonic-gate icmp_type_table); 46117c478bd9Sstevel@tonic-gate 46127c478bd9Sstevel@tonic-gate if (type > 65536 || type < 0) { 46137c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 46147c478bd9Sstevel@tonic-gate IPSEC_CONF_ICMP_TYPE, line_no); 46157c478bd9Sstevel@tonic-gate return (-1); 46167c478bd9Sstevel@tonic-gate } 46177c478bd9Sstevel@tonic-gate 46187c478bd9Sstevel@tonic-gate type_end = type / 256; 46197c478bd9Sstevel@tonic-gate type = type % 256; 46207c478bd9Sstevel@tonic-gate 46217c478bd9Sstevel@tonic-gate if (type_end < type) 46227c478bd9Sstevel@tonic-gate type_end = type; 46237c478bd9Sstevel@tonic-gate 46247c478bd9Sstevel@tonic-gate cptr->has_type = 1; 46257c478bd9Sstevel@tonic-gate cptr->ips_icmp_type = (uint8_t)type; 46267c478bd9Sstevel@tonic-gate cptr->ips_icmp_type_end = (uint8_t)type_end; 46277c478bd9Sstevel@tonic-gate break; 46287c478bd9Sstevel@tonic-gate case TOK_code: 46297c478bd9Sstevel@tonic-gate if (!cptr->has_type) { 46307c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 46317c478bd9Sstevel@tonic-gate IPSEC_CONF_ICMP_CODE, line_no); 46327c478bd9Sstevel@tonic-gate return (-1); 46337c478bd9Sstevel@tonic-gate } 46347c478bd9Sstevel@tonic-gate 46357c478bd9Sstevel@tonic-gate if (cptr->has_code) { 46367c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 46377c478bd9Sstevel@tonic-gate IPSEC_CONF_ICMP_CODE, line_no); 46387c478bd9Sstevel@tonic-gate return (-1); 46397c478bd9Sstevel@tonic-gate } 46407c478bd9Sstevel@tonic-gate 46417c478bd9Sstevel@tonic-gate i++, line_no++; 46427c478bd9Sstevel@tonic-gate 46437c478bd9Sstevel@tonic-gate code = parse_type_code(act_props->pattern[i], 46447c478bd9Sstevel@tonic-gate icmp_code_table); 46457c478bd9Sstevel@tonic-gate if (type > 65536 || type < 0) { 46467c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 46477c478bd9Sstevel@tonic-gate IPSEC_CONF_ICMP_CODE, line_no); 46487c478bd9Sstevel@tonic-gate return (-1); 46497c478bd9Sstevel@tonic-gate } 46507c478bd9Sstevel@tonic-gate code_end = code / 256; 46517c478bd9Sstevel@tonic-gate code = code % 256; 46527c478bd9Sstevel@tonic-gate 46537c478bd9Sstevel@tonic-gate if (code_end < code) 46547c478bd9Sstevel@tonic-gate code_end = code; 46557c478bd9Sstevel@tonic-gate 46567c478bd9Sstevel@tonic-gate cptr->has_code = 1; 46577c478bd9Sstevel@tonic-gate cptr->ips_icmp_code = (uint8_t)code; 46587c478bd9Sstevel@tonic-gate cptr->ips_icmp_code_end = (uint8_t)code_end; 46597c478bd9Sstevel@tonic-gate break; 46608810c16bSdanmcd case TOK_tunnel: 46618810c16bSdanmcd if (cptr->has_tunnel == 1) { 46628810c16bSdanmcd error_message(BAD_ERROR, 46638810c16bSdanmcd IPSEC_CONF_TUNNEL, line_no); 46648810c16bSdanmcd return (-1); 46658810c16bSdanmcd } 46668810c16bSdanmcd i++, line_no++; 46678810c16bSdanmcd if (act_props->pattern[i] == NULL) { 46688810c16bSdanmcd error_message(BAD_ERROR, 46698810c16bSdanmcd IPSEC_CONF_TUNNEL, line_no); 46708810c16bSdanmcd return (-1); 46718810c16bSdanmcd } 46728810c16bSdanmcd 46738810c16bSdanmcd if (strlcpy(tunif, act_props->pattern[i], 46748810c16bSdanmcd TUNNAMEMAXLEN) >= TUNNAMEMAXLEN) { 46758810c16bSdanmcd error_message(BAD_ERROR, 46768810c16bSdanmcd IPSEC_CONF_TUNNEL, line_no); 46778810c16bSdanmcd return (-1); 46788810c16bSdanmcd } 46798810c16bSdanmcd cptr->has_tunnel = 1; 46808810c16bSdanmcd break; 46818810c16bSdanmcd case TOK_negotiate: 46828810c16bSdanmcd if (cptr->has_negotiate == 1) { 46838810c16bSdanmcd error_message(BAD_ERROR, 46848810c16bSdanmcd IPSEC_CONF_NEGOTIATE, line_no); 46858810c16bSdanmcd return (-1); 46868810c16bSdanmcd } 46878810c16bSdanmcd i++, line_no++; 46888810c16bSdanmcd if (act_props->pattern[i] == NULL) { 46898810c16bSdanmcd error_message(BAD_ERROR, 46908810c16bSdanmcd IPSEC_CONF_NEGOTIATE, line_no); 46918810c16bSdanmcd return (-1); 46928810c16bSdanmcd } 46938810c16bSdanmcd 46948810c16bSdanmcd if (strncmp(act_props->pattern[i], "tunnel", 6) == 0) { 46958810c16bSdanmcd cptr->ips_tunnel = B_TRUE; 46968810c16bSdanmcd } else if (strncmp( 46978810c16bSdanmcd act_props->pattern[i], "transport", 9) != 0) { 46988810c16bSdanmcd error_message(BAD_ERROR, 46998810c16bSdanmcd IPSEC_CONF_NEGOTIATE, line_no); 47008810c16bSdanmcd return (-1); 47018810c16bSdanmcd } 47028810c16bSdanmcd cptr->has_negotiate = 1; 47038810c16bSdanmcd break; 47047c478bd9Sstevel@tonic-gate } 47058810c16bSdanmcd 47068810c16bSdanmcd } 47078810c16bSdanmcd 47088810c16bSdanmcd /* Sanity check that certain tokens occur together */ 47098810c16bSdanmcd if (cptr->has_tunnel + cptr->has_negotiate == 1) { 47108810c16bSdanmcd if (cptr->has_negotiate == 0) { 47118810c16bSdanmcd error_message(REQ_ERROR, IPSEC_CONF_NEGOTIATE, line_no); 47128810c16bSdanmcd } else { 47138810c16bSdanmcd error_message(REQ_ERROR, IPSEC_CONF_TUNNEL, line_no); 47148810c16bSdanmcd } 47158810c16bSdanmcd errx(1, gettext( 47168810c16bSdanmcd "tunnel and negotiate tokens must occur together")); 47178810c16bSdanmcd return (-1); 47187c478bd9Sstevel@tonic-gate } 47197c478bd9Sstevel@tonic-gate 47207c478bd9Sstevel@tonic-gate /* 47217c478bd9Sstevel@tonic-gate * Get the actions. 47227c478bd9Sstevel@tonic-gate */ 47237c478bd9Sstevel@tonic-gate 47247c478bd9Sstevel@tonic-gate for (ap_num = 0; act_props->ap[ap_num].act != NULL; ap_num++) { 47257c478bd9Sstevel@tonic-gate ips_act_props_t *iap; 47267c478bd9Sstevel@tonic-gate 47277c478bd9Sstevel@tonic-gate if (ap_num > 0) { 47287c478bd9Sstevel@tonic-gate /* or's only with new style */ 47297c478bd9Sstevel@tonic-gate if (old_style) { 47307c478bd9Sstevel@tonic-gate (void) printf("%s\n", gettext( 47317c478bd9Sstevel@tonic-gate "or's only with new style")); 47327c478bd9Sstevel@tonic-gate return (-1); 47337c478bd9Sstevel@tonic-gate } 47347c478bd9Sstevel@tonic-gate new_style = B_TRUE; 47357c478bd9Sstevel@tonic-gate } 47367c478bd9Sstevel@tonic-gate 47377c478bd9Sstevel@tonic-gate ipsec_aalg = ipsec_ealg = ipsec_eaalg = B_FALSE; 47387c478bd9Sstevel@tonic-gate tok_count = 0; 47397c478bd9Sstevel@tonic-gate 47407c478bd9Sstevel@tonic-gate for (k = 0; action_table[k].string; k++) { 47417c478bd9Sstevel@tonic-gate if (strcmp(act_props->ap[ap_num].act, 47427c478bd9Sstevel@tonic-gate action_table[k].string) == 0) 47437c478bd9Sstevel@tonic-gate break; 47447c478bd9Sstevel@tonic-gate } 47457c478bd9Sstevel@tonic-gate /* 47467c478bd9Sstevel@tonic-gate * The following thing should never happen as 47477c478bd9Sstevel@tonic-gate * we have already tested for its validity in parse. 47487c478bd9Sstevel@tonic-gate */ 47497c478bd9Sstevel@tonic-gate if (action_table[k].string == NULL) { 47507c478bd9Sstevel@tonic-gate warnx(gettext("(form act)Invalid action on line " 47517c478bd9Sstevel@tonic-gate "%d: %s"), (arg_indices[line_no] == 0) ? 1 : 47527c478bd9Sstevel@tonic-gate arg_indices[line_no], 47537c478bd9Sstevel@tonic-gate act_props->ap[ap_num].act); 47547c478bd9Sstevel@tonic-gate warnx("%s", act_props->ap[ap_num].act); 47557c478bd9Sstevel@tonic-gate return (-1); 47567c478bd9Sstevel@tonic-gate } 47577c478bd9Sstevel@tonic-gate 47587c478bd9Sstevel@tonic-gate /* we have a good action alloc an iap */ 47597c478bd9Sstevel@tonic-gate iap = alloc_iap(cptr); 47607c478bd9Sstevel@tonic-gate 47617c478bd9Sstevel@tonic-gate iap->iap_action = action_table[k].value; 47627c478bd9Sstevel@tonic-gate iap->iap_act_tok = action_table[k].tok_val; 47637c478bd9Sstevel@tonic-gate 47647c478bd9Sstevel@tonic-gate switch (action_table[k].tok_val) { 47657c478bd9Sstevel@tonic-gate case TOK_apply: 47667c478bd9Sstevel@tonic-gate cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 47677c478bd9Sstevel@tonic-gate break; 47687c478bd9Sstevel@tonic-gate case TOK_permit: 47697c478bd9Sstevel@tonic-gate cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 47707c478bd9Sstevel@tonic-gate break; 47717c478bd9Sstevel@tonic-gate case TOK_ipsec: 4772eeda67c6Sjojemann if (old_style) { 4773eeda67c6Sjojemann /* Using saddr/daddr with ipsec action. */ 4774eeda67c6Sjojemann if (!dir) { 4775eeda67c6Sjojemann /* No direction specified */ 4776eeda67c6Sjojemann error_message(REQ_ERROR, 4777eeda67c6Sjojemann IPSEC_CONF_IPSEC_DIR, line_no); 4778eeda67c6Sjojemann return (-1); 4779eeda67c6Sjojemann } 4780eeda67c6Sjojemann if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 4781eeda67c6Sjojemann /* 4782eeda67c6Sjojemann * Need to swap addresses if 4783eeda67c6Sjojemann * 'dir in' or translation to 4784eeda67c6Sjojemann * laddr/raddr will be incorrect. 4785eeda67c6Sjojemann */ 4786eeda67c6Sjojemann cptr->swap = 1; 4787eeda67c6Sjojemann } 47887c478bd9Sstevel@tonic-gate if (!dir) 47897c478bd9Sstevel@tonic-gate cptr->ips_dir = 47907c478bd9Sstevel@tonic-gate SPD_RULE_FLAG_INBOUND 47917c478bd9Sstevel@tonic-gate |SPD_RULE_FLAG_OUTBOUND; 47927c478bd9Sstevel@tonic-gate break; 47937c478bd9Sstevel@tonic-gate case TOK_bypass: 47947c478bd9Sstevel@tonic-gate /* do something? */ 47957c478bd9Sstevel@tonic-gate break; 47967c478bd9Sstevel@tonic-gate } 47977c478bd9Sstevel@tonic-gate 47987c478bd9Sstevel@tonic-gate line_no++; 47997c478bd9Sstevel@tonic-gate /* 48007c478bd9Sstevel@tonic-gate * Get the properties. NULL properties is not valid. 48017c478bd9Sstevel@tonic-gate * Later checks will catch it. 48027c478bd9Sstevel@tonic-gate */ 48037c478bd9Sstevel@tonic-gate for (i = 0; act_props->ap[ap_num].prop[i]; i++, line_no++) { 48047c478bd9Sstevel@tonic-gate for (j = 0; property_table[j].string; j++) { 48057c478bd9Sstevel@tonic-gate if (strcmp(act_props->ap[ap_num].prop[i], 48067c478bd9Sstevel@tonic-gate property_table[j].string) == 0) { 48077c478bd9Sstevel@tonic-gate break; 48087c478bd9Sstevel@tonic-gate } 48097c478bd9Sstevel@tonic-gate } 48107c478bd9Sstevel@tonic-gate if (property_table[j].string == NULL) { 48117c478bd9Sstevel@tonic-gate warnx(gettext("Invalid properties on line " 48127c478bd9Sstevel@tonic-gate "%d: %s"), 4813d5751483Smarkfen (arg_indices[line_no] == 0) ? 48147c478bd9Sstevel@tonic-gate 1 : arg_indices[line_no], 48157c478bd9Sstevel@tonic-gate act_props->ap[ap_num].prop[i]); 48167c478bd9Sstevel@tonic-gate return (-1); 48177c478bd9Sstevel@tonic-gate } 48187c478bd9Sstevel@tonic-gate 48197c478bd9Sstevel@tonic-gate iap->iap_attr_tok[tok_count++] 48207c478bd9Sstevel@tonic-gate = property_table[j].value; 48217c478bd9Sstevel@tonic-gate 48227c478bd9Sstevel@tonic-gate switch (property_table[j].value) { 48237c478bd9Sstevel@tonic-gate case SPD_ATTR_AH_AUTH: 48247c478bd9Sstevel@tonic-gate if (ipsec_aalg) { 48257c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 48267c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_AALGS, line_no); 48277c478bd9Sstevel@tonic-gate return (-1); 48287c478bd9Sstevel@tonic-gate } 48297c478bd9Sstevel@tonic-gate i++, line_no++; 48307c478bd9Sstevel@tonic-gate if (act_props->ap[ap_num].prop[i] == NULL) { 48317c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 48327c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_AALGS, line_no); 48337c478bd9Sstevel@tonic-gate return (-1); 48347c478bd9Sstevel@tonic-gate } 48357c478bd9Sstevel@tonic-gate ret = parse_ipsec_alg( 48367c478bd9Sstevel@tonic-gate act_props->ap[ap_num].prop[i], 48377c478bd9Sstevel@tonic-gate iap, SPD_ATTR_AH_AUTH); 4838c758f97fSpwernau if (ret == -2) { 4839c758f97fSpwernau /* "none" - ignore */ 4840c758f97fSpwernau break; 4841c758f97fSpwernau } 48427c478bd9Sstevel@tonic-gate if (ret != 0) { 48437c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 48447c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_AALGS, line_no); 48457c478bd9Sstevel@tonic-gate return (-1); 48467c478bd9Sstevel@tonic-gate } 48477c478bd9Sstevel@tonic-gate ipsec_aalg = B_TRUE; 48487c478bd9Sstevel@tonic-gate break; 48497c478bd9Sstevel@tonic-gate case SPD_ATTR_ESP_ENCR: 48507c478bd9Sstevel@tonic-gate /* 48517c478bd9Sstevel@tonic-gate * If this option was not given 48527c478bd9Sstevel@tonic-gate * and encr_auth_algs was given, 48537c478bd9Sstevel@tonic-gate * we provide null-encryption. We do the 48547c478bd9Sstevel@tonic-gate * setting after we parse all the options. 48557c478bd9Sstevel@tonic-gate */ 48567c478bd9Sstevel@tonic-gate if (ipsec_ealg) { 48577c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 48587c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_EALGS, line_no); 48597c478bd9Sstevel@tonic-gate return (-1); 48607c478bd9Sstevel@tonic-gate } 48617c478bd9Sstevel@tonic-gate i++, line_no++; 48627c478bd9Sstevel@tonic-gate if (act_props->ap[ap_num].prop[i] == NULL) { 48637c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 48647c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_EALGS, line_no); 48657c478bd9Sstevel@tonic-gate return (-1); 48667c478bd9Sstevel@tonic-gate } 48677c478bd9Sstevel@tonic-gate ret = parse_ipsec_alg( 48687c478bd9Sstevel@tonic-gate act_props->ap[ap_num].prop[i], 48697c478bd9Sstevel@tonic-gate iap, SPD_ATTR_ESP_ENCR); 4870c758f97fSpwernau if (ret == -2) { 4871c758f97fSpwernau /* "none" - ignore */ 4872c758f97fSpwernau break; 4873c758f97fSpwernau } 48747c478bd9Sstevel@tonic-gate if (ret != 0) { 48757c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 48767c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_EALGS, line_no); 48777c478bd9Sstevel@tonic-gate return (-1); 48787c478bd9Sstevel@tonic-gate } 48797c478bd9Sstevel@tonic-gate ipsec_ealg = B_TRUE; 48807c478bd9Sstevel@tonic-gate break; 48817c478bd9Sstevel@tonic-gate case SPD_ATTR_ESP_AUTH: 48827c478bd9Sstevel@tonic-gate /* 48837c478bd9Sstevel@tonic-gate * If this option was not given and encr_algs 48847c478bd9Sstevel@tonic-gate * option was given, we still pass a default 48857c478bd9Sstevel@tonic-gate * value in ipsc_esp_auth_algs. This is to 48867c478bd9Sstevel@tonic-gate * encourage the use of authentication with 48877c478bd9Sstevel@tonic-gate * ESP. 48887c478bd9Sstevel@tonic-gate */ 48897c478bd9Sstevel@tonic-gate if (ipsec_eaalg) { 48907c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 48917c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_EAALGS, line_no); 48927c478bd9Sstevel@tonic-gate return (-1); 48937c478bd9Sstevel@tonic-gate } 48947c478bd9Sstevel@tonic-gate i++, line_no++; 48957c478bd9Sstevel@tonic-gate if (act_props->ap[ap_num].prop[i] == NULL) { 48967c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 48977c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_EAALGS, line_no); 48987c478bd9Sstevel@tonic-gate return (-1); 48997c478bd9Sstevel@tonic-gate } 49007c478bd9Sstevel@tonic-gate ret = parse_ipsec_alg( 49017c478bd9Sstevel@tonic-gate act_props->ap[ap_num].prop[i], 49027c478bd9Sstevel@tonic-gate iap, SPD_ATTR_ESP_AUTH); 4903c758f97fSpwernau if (ret == -2) { 4904c758f97fSpwernau /* "none" - ignore */ 4905c758f97fSpwernau break; 4906c758f97fSpwernau } 49077c478bd9Sstevel@tonic-gate if (ret != 0) { 49087c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 49097c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_EAALGS, line_no); 49107c478bd9Sstevel@tonic-gate return (-1); 49117c478bd9Sstevel@tonic-gate } 49127c478bd9Sstevel@tonic-gate ipsec_eaalg = B_TRUE; 49137c478bd9Sstevel@tonic-gate break; 49147c478bd9Sstevel@tonic-gate case IPS_SA: 49157c478bd9Sstevel@tonic-gate i++, line_no++; 49167c478bd9Sstevel@tonic-gate if (act_props->ap[ap_num].prop[i] == NULL) { 49177c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 49187c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_SA, line_no); 49197c478bd9Sstevel@tonic-gate return (-1); 49207c478bd9Sstevel@tonic-gate } 49217c478bd9Sstevel@tonic-gate 49227c478bd9Sstevel@tonic-gate if (strcmp(act_props->ap[ap_num].prop[i], 49237c478bd9Sstevel@tonic-gate "unique") == 0) { 49247c478bd9Sstevel@tonic-gate iap->iap_attr |= SPD_APPLY_UNIQUE; 49257c478bd9Sstevel@tonic-gate } else if (strcmp(act_props->ap[ap_num].prop[i], 49267c478bd9Sstevel@tonic-gate "shared") != 0) { 49277c478bd9Sstevel@tonic-gate /* "shared" is default. */ 49287c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 49297c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_SA, line_no); 49307c478bd9Sstevel@tonic-gate return (-1); 49317c478bd9Sstevel@tonic-gate } 49327c478bd9Sstevel@tonic-gate 49337c478bd9Sstevel@tonic-gate break; 49347c478bd9Sstevel@tonic-gate case IPS_DIR: 49357c478bd9Sstevel@tonic-gate if (dir) { 49367c478bd9Sstevel@tonic-gate error_message(DUP_ERROR, 49377c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_DIR, line_no); 49387c478bd9Sstevel@tonic-gate return (-1); 49397c478bd9Sstevel@tonic-gate } 49407c478bd9Sstevel@tonic-gate if (new_style) { 49417c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 49427c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_DIR, line_no); 49437c478bd9Sstevel@tonic-gate return (-1); 49447c478bd9Sstevel@tonic-gate } 49457c478bd9Sstevel@tonic-gate old_style = B_TRUE; 49467c478bd9Sstevel@tonic-gate dir = B_TRUE; 49477c478bd9Sstevel@tonic-gate i++, line_no++; 49487c478bd9Sstevel@tonic-gate if (act_props->ap[ap_num].prop[i] == NULL) { 49497c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 49507c478bd9Sstevel@tonic-gate IPSEC_CONF_IPSEC_DIR, line_no); 49517c478bd9Sstevel@tonic-gate return (-1); 49527c478bd9Sstevel@tonic-gate } 49537c478bd9Sstevel@tonic-gate if (strcmp(act_props->ap[ap_num].prop[i], 49547c478bd9Sstevel@tonic-gate "out") == 0) { 49557c478bd9Sstevel@tonic-gate cptr->ips_dir = SPD_RULE_FLAG_OUTBOUND; 49567c478bd9Sstevel@tonic-gate } else if (strcmp(act_props->ap[ap_num].prop[i], 49577c478bd9Sstevel@tonic-gate "in") == 0) { 49587c478bd9Sstevel@tonic-gate cptr->ips_dir = SPD_RULE_FLAG_INBOUND; 49597c478bd9Sstevel@tonic-gate } else { 49607c478bd9Sstevel@tonic-gate error_message(BAD_ERROR, 4961d5751483Smarkfen IPSEC_CONF_IPSEC_DIR, line_no); 49627c478bd9Sstevel@tonic-gate return (-1); 49637c478bd9Sstevel@tonic-gate } 49647c478bd9Sstevel@tonic-gate if ((cptr->ips_dir & SPD_RULE_FLAG_INBOUND) && 4965d5751483Smarkfen iap->iap_act_tok == TOK_apply) { 49667c478bd9Sstevel@tonic-gate warnx(gettext("Direction" 49677c478bd9Sstevel@tonic-gate " in conflict with action")); 49687c478bd9Sstevel@tonic-gate return (-1); 49697c478bd9Sstevel@tonic-gate } 49707c478bd9Sstevel@tonic-gate if ((cptr->ips_dir & SPD_RULE_FLAG_OUTBOUND) && 4971d5751483Smarkfen iap->iap_act_tok == TOK_permit) { 49727c478bd9Sstevel@tonic-gate warnx(gettext("Direction" 49737c478bd9Sstevel@tonic-gate "in conflict with action")); 49747c478bd9Sstevel@tonic-gate return (-1); 49757c478bd9Sstevel@tonic-gate } 49767c478bd9Sstevel@tonic-gate 49777c478bd9Sstevel@tonic-gate break; 49787c478bd9Sstevel@tonic-gate } 49797c478bd9Sstevel@tonic-gate } 49807c478bd9Sstevel@tonic-gate 49817c478bd9Sstevel@tonic-gate if (!ipsec_ealg && ipsec_eaalg) { 49827c478bd9Sstevel@tonic-gate /* 49837c478bd9Sstevel@tonic-gate * If the user has specified the auth alg to be used 49847c478bd9Sstevel@tonic-gate * with encryption and did not provide a encryption 49857c478bd9Sstevel@tonic-gate * algorithm, provide null encryption. 49867c478bd9Sstevel@tonic-gate */ 49877c478bd9Sstevel@tonic-gate iap->iap_eencr.alg_id = SADB_EALG_NULL; 49887c478bd9Sstevel@tonic-gate ipsec_ealg = B_TRUE; 49897c478bd9Sstevel@tonic-gate } 49907c478bd9Sstevel@tonic-gate 49917c478bd9Sstevel@tonic-gate /* Set the level of IPSEC protection we want */ 49927c478bd9Sstevel@tonic-gate if (ipsec_aalg && (ipsec_ealg || ipsec_eaalg)) { 49937c478bd9Sstevel@tonic-gate iap->iap_attr |= SPD_APPLY_AH|SPD_APPLY_ESP; 49947c478bd9Sstevel@tonic-gate } else if (ipsec_aalg) { 49957c478bd9Sstevel@tonic-gate iap->iap_attr |= SPD_APPLY_AH; 49967c478bd9Sstevel@tonic-gate } else if (ipsec_ealg || ipsec_eaalg) { 49977c478bd9Sstevel@tonic-gate iap->iap_attr |= SPD_APPLY_ESP; 49987c478bd9Sstevel@tonic-gate } 49997c478bd9Sstevel@tonic-gate 50007c478bd9Sstevel@tonic-gate /* convert src/dst to local/remote */ 50017c478bd9Sstevel@tonic-gate if (!new_style) { 50027c478bd9Sstevel@tonic-gate switch (cptr->ips_acts->iap_act_tok) { 50037c478bd9Sstevel@tonic-gate case TOK_apply: 50047c478bd9Sstevel@tonic-gate /* outbound */ 50057c478bd9Sstevel@tonic-gate /* src=local, dst=remote */ 50067c478bd9Sstevel@tonic-gate /* this is ok. */ 50077c478bd9Sstevel@tonic-gate break; 50087c478bd9Sstevel@tonic-gate 50097c478bd9Sstevel@tonic-gate case TOK_permit: 50107c478bd9Sstevel@tonic-gate /* inbound */ 50117c478bd9Sstevel@tonic-gate /* src=remote, dst=local */ 50127c478bd9Sstevel@tonic-gate /* switch */ 50137c478bd9Sstevel@tonic-gate cptr->swap = 1; 50147c478bd9Sstevel@tonic-gate break; 50157c478bd9Sstevel@tonic-gate case TOK_bypass: 50167c478bd9Sstevel@tonic-gate case TOK_drop: 50177c478bd9Sstevel@tonic-gate /* check the direction for what to do */ 50187c478bd9Sstevel@tonic-gate if (cptr->ips_dir == SPD_RULE_FLAG_INBOUND) 50197c478bd9Sstevel@tonic-gate cptr->swap = 1; 50207c478bd9Sstevel@tonic-gate break; 50217c478bd9Sstevel@tonic-gate default: 50227c478bd9Sstevel@tonic-gate break; 50237c478bd9Sstevel@tonic-gate } 50247c478bd9Sstevel@tonic-gate } 50257c478bd9Sstevel@tonic-gate /* Validate the properties */ 50267c478bd9Sstevel@tonic-gate if (ret = validate_properties(iap, dir, 50277c478bd9Sstevel@tonic-gate (ipsec_aalg || ipsec_ealg || ipsec_eaalg))) { 50287c478bd9Sstevel@tonic-gate return (ret); 50297c478bd9Sstevel@tonic-gate } 50307c478bd9Sstevel@tonic-gate } 50317c478bd9Sstevel@tonic-gate 50327c478bd9Sstevel@tonic-gate return (0); 50337c478bd9Sstevel@tonic-gate 50347c478bd9Sstevel@tonic-gate } 50357c478bd9Sstevel@tonic-gate 50367c478bd9Sstevel@tonic-gate static int 503743c889d3Smarkfen print_cmd_buf(FILE *fp, int error) 50387c478bd9Sstevel@tonic-gate { 50397c478bd9Sstevel@tonic-gate *(cbuf + cbuf_offset) = '\0'; 50407c478bd9Sstevel@tonic-gate 50417c478bd9Sstevel@tonic-gate if (fp == stderr) { 5042e3320f40Smarkfen if (error != EEXIST) { 5043e3320f40Smarkfen warnx(gettext("Malformed command (fatal):\n%s"), cbuf); 504443c889d3Smarkfen return (0); 504543c889d3Smarkfen } 5046e3320f40Smarkfen if (ipsecconf_qflag) { 5047e3320f40Smarkfen return (0); 50487c478bd9Sstevel@tonic-gate } 5049e3320f40Smarkfen warnx(gettext("Duplicate policy entry (ignored):\n%s"), cbuf); 50507c478bd9Sstevel@tonic-gate } else { 50517c478bd9Sstevel@tonic-gate if (fprintf(fp, "%s", cbuf) == -1) { 50527c478bd9Sstevel@tonic-gate warn("fprintf"); 50537c478bd9Sstevel@tonic-gate return (-1); 50547c478bd9Sstevel@tonic-gate } 50557c478bd9Sstevel@tonic-gate } 50567c478bd9Sstevel@tonic-gate 50577c478bd9Sstevel@tonic-gate return (0); 50587c478bd9Sstevel@tonic-gate } 50597c478bd9Sstevel@tonic-gate 50607c478bd9Sstevel@tonic-gate #ifdef DEBUG 50617c478bd9Sstevel@tonic-gate 50627c478bd9Sstevel@tonic-gate static uchar_t * 50637c478bd9Sstevel@tonic-gate addr_ptr(int isv4, struct in6_addr *addr6, struct in_addr *addr4) 50647c478bd9Sstevel@tonic-gate { 50657c478bd9Sstevel@tonic-gate if (isv4) { 50667c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR(addr6, addr4); 50677c478bd9Sstevel@tonic-gate return ((uchar_t *)&addr4->s_addr); 50687c478bd9Sstevel@tonic-gate } else { 50697c478bd9Sstevel@tonic-gate return ((uchar_t *)&addr6->s6_addr); 50707c478bd9Sstevel@tonic-gate } 50717c478bd9Sstevel@tonic-gate } 50727c478bd9Sstevel@tonic-gate 50737c478bd9Sstevel@tonic-gate static void 50747c478bd9Sstevel@tonic-gate dump_algreq(const char *tag, algreq_t *alg) 50757c478bd9Sstevel@tonic-gate { 50767c478bd9Sstevel@tonic-gate (void) printf("%s algid %d, bits %d..%d\n", 50777c478bd9Sstevel@tonic-gate tag, alg->alg_id, alg->alg_minbits, alg->alg_maxbits); 50787c478bd9Sstevel@tonic-gate } 50797c478bd9Sstevel@tonic-gate 50807c478bd9Sstevel@tonic-gate static void 50817c478bd9Sstevel@tonic-gate dump_conf(ips_conf_t *conf) 50827c478bd9Sstevel@tonic-gate { 50837c478bd9Sstevel@tonic-gate boolean_t isv4 = conf->ips_isv4; 50847c478bd9Sstevel@tonic-gate struct in_addr addr; 50857c478bd9Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN]; 50867c478bd9Sstevel@tonic-gate int af; 50877c478bd9Sstevel@tonic-gate ips_act_props_t *iap = conf->ips_acts; 50887c478bd9Sstevel@tonic-gate 50897c478bd9Sstevel@tonic-gate af = isv4 ? AF_INET : AF_INET6; 50907c478bd9Sstevel@tonic-gate 50917c478bd9Sstevel@tonic-gate (void) printf("Source Addr is %s\n", 50927c478bd9Sstevel@tonic-gate inet_ntop(af, addr_ptr(isv4, &conf->ips_src_addr_v6, &addr), 5093d5751483Smarkfen buf, INET6_ADDRSTRLEN)); 50947c478bd9Sstevel@tonic-gate 50957c478bd9Sstevel@tonic-gate (void) printf("Dest Addr is %s\n", 50967c478bd9Sstevel@tonic-gate inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_addr_v6, &addr), 5097d5751483Smarkfen buf, INET6_ADDRSTRLEN)); 50987c478bd9Sstevel@tonic-gate 50997c478bd9Sstevel@tonic-gate (void) printf("Source Mask is %s\n", 51007c478bd9Sstevel@tonic-gate inet_ntop(af, addr_ptr(isv4, &conf->ips_src_mask_v6, &addr), 5101d5751483Smarkfen buf, INET6_ADDRSTRLEN)); 51027c478bd9Sstevel@tonic-gate 51037c478bd9Sstevel@tonic-gate (void) printf("Dest Mask is %s\n", 51047c478bd9Sstevel@tonic-gate inet_ntop(af, addr_ptr(isv4, &conf->ips_dst_mask_v6, &addr), 5105d5751483Smarkfen buf, INET6_ADDRSTRLEN)); 51067c478bd9Sstevel@tonic-gate 510792913378Spwernau (void) printf("Source port %d\n", ntohs(conf->ips_src_port_min)); 510892913378Spwernau (void) printf("Dest port %d\n", ntohs(conf->ips_dst_port_min)); 51097c478bd9Sstevel@tonic-gate (void) printf("ULP %d\n", conf->ips_ulp_prot); 51107c478bd9Sstevel@tonic-gate 51117c478bd9Sstevel@tonic-gate (void) printf("ICMP type %d-%d code %d-%d", conf->ips_icmp_type, 51127c478bd9Sstevel@tonic-gate conf->ips_icmp_type_end, 51137c478bd9Sstevel@tonic-gate conf->ips_icmp_code, 51147c478bd9Sstevel@tonic-gate conf->ips_icmp_code_end); 51157c478bd9Sstevel@tonic-gate 51167c478bd9Sstevel@tonic-gate while (iap != NULL) { 51177c478bd9Sstevel@tonic-gate (void) printf("------------------------------------\n"); 5118e3320f40Smarkfen (void) printf("IPsec act is %d\n", iap->iap_action); 5119e3320f40Smarkfen (void) printf("IPsec attr is %d\n", iap->iap_attr); 51207c478bd9Sstevel@tonic-gate dump_algreq("AH authentication", &iap->iap_aauth); 51217c478bd9Sstevel@tonic-gate dump_algreq("ESP authentication", &iap->iap_eauth); 51227c478bd9Sstevel@tonic-gate dump_algreq("ESP encryption", &iap->iap_eencr); 51237c478bd9Sstevel@tonic-gate (void) printf("------------------------------------\n"); 51247c478bd9Sstevel@tonic-gate iap = iap->iap_next; 51257c478bd9Sstevel@tonic-gate } 51267c478bd9Sstevel@tonic-gate 5127e3320f40Smarkfen (void) fflush(stdout); 51287c478bd9Sstevel@tonic-gate } 51297c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 51307c478bd9Sstevel@tonic-gate 51317c478bd9Sstevel@tonic-gate 51327c478bd9Sstevel@tonic-gate static int 5133e3320f40Smarkfen ipsec_conf_add(boolean_t just_check, boolean_t smf_managed) 51347c478bd9Sstevel@tonic-gate { 51357c478bd9Sstevel@tonic-gate act_prop_t *act_props = malloc(sizeof (act_prop_t)); 51367c478bd9Sstevel@tonic-gate ips_conf_t conf; 51377c478bd9Sstevel@tonic-gate FILE *fp, *policy_fp; 5138e3320f40Smarkfen int ret, flushret, i, j, diag, num_rules, good_rules; 51397c478bd9Sstevel@tonic-gate char *warning = gettext( 5140d5751483Smarkfen "\tWARNING : New policy entries that are being added may\n " 5141d5751483Smarkfen "\taffect the existing connections. Existing connections\n" 5142d5751483Smarkfen "\tthat are not subjected to policy constraints, may be\n" 5143d5751483Smarkfen "\tsubjected to policy constraints because of the new\n" 5144d5751483Smarkfen "\tpolicy. This can disrupt the communication of the\n" 5145d5751483Smarkfen "\texisting connections.\n\n"); 51467c478bd9Sstevel@tonic-gate 5147e3320f40Smarkfen boolean_t first_time = B_TRUE; 5148e3320f40Smarkfen num_rules = 0; 5149e3320f40Smarkfen good_rules = 0; 5150e3320f40Smarkfen 51517c478bd9Sstevel@tonic-gate if (act_props == NULL) { 51527c478bd9Sstevel@tonic-gate warn(gettext("memory")); 51537c478bd9Sstevel@tonic-gate return (-1); 51547c478bd9Sstevel@tonic-gate } 51557c478bd9Sstevel@tonic-gate 51567c478bd9Sstevel@tonic-gate if (strcmp(filename, "-") == 0) 51577c478bd9Sstevel@tonic-gate fp = stdin; 51587c478bd9Sstevel@tonic-gate else 51597c478bd9Sstevel@tonic-gate fp = fopen(filename, "r"); 51607c478bd9Sstevel@tonic-gate 5161e3320f40Smarkfen /* 5162e3320f40Smarkfen * Treat the non-existence of a policy file as a special 5163e3320f40Smarkfen * case when ipsecconf is being managed by smf(5). 5164e3320f40Smarkfen * The assumption is the administrator has not yet 5165e3320f40Smarkfen * created a policy file, this should not force the service 5166e3320f40Smarkfen * into maintenance mode. 5167e3320f40Smarkfen */ 5168e3320f40Smarkfen 51697c478bd9Sstevel@tonic-gate if (fp == NULL) { 5170e3320f40Smarkfen if (smf_managed) { 5171e3320f40Smarkfen (void) fprintf(stdout, gettext( 5172e3320f40Smarkfen "Policy configuration file (%s) does not exist.\n" 5173e3320f40Smarkfen "IPsec policy not configured.\n"), filename); 5174e3320f40Smarkfen return (0); 5175e3320f40Smarkfen } 5176e3320f40Smarkfen warn(gettext("%s : Policy config file cannot be opened"), 5177e3320f40Smarkfen filename); 51787c478bd9Sstevel@tonic-gate usage(); 51797c478bd9Sstevel@tonic-gate return (-1); 51807c478bd9Sstevel@tonic-gate } 51817c478bd9Sstevel@tonic-gate /* 51827c478bd9Sstevel@tonic-gate * This will create the file if it does not exist. 51837c478bd9Sstevel@tonic-gate * Make sure the umask is right. 51847c478bd9Sstevel@tonic-gate */ 51857c478bd9Sstevel@tonic-gate (void) umask(0022); 51867c478bd9Sstevel@tonic-gate policy_fp = fopen(POLICY_CONF_FILE, "a"); 51877c478bd9Sstevel@tonic-gate if (policy_fp == NULL) { 51887c478bd9Sstevel@tonic-gate warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 51897c478bd9Sstevel@tonic-gate return (-1); 51907c478bd9Sstevel@tonic-gate } 51917c478bd9Sstevel@tonic-gate 51927c478bd9Sstevel@tonic-gate /* 51937c478bd9Sstevel@tonic-gate * Pattern, action, and properties are allocated in 51947c478bd9Sstevel@tonic-gate * parse_pattern_or_prop and in parse_action (called by 51957c478bd9Sstevel@tonic-gate * parse_one) as we parse arguments. 51967c478bd9Sstevel@tonic-gate */ 5197d5751483Smarkfen while ((ret = parse_one(fp, act_props)) != PARSE_EOF) { 5198d5751483Smarkfen num_rules++; 5199d5751483Smarkfen if (ret != 0) { 5200d5751483Smarkfen (void) print_cmd_buf(stderr, NOERROR); 5201d5751483Smarkfen continue; 5202d5751483Smarkfen } 52037c478bd9Sstevel@tonic-gate 52047c478bd9Sstevel@tonic-gate /* 52057c478bd9Sstevel@tonic-gate * If there is no action and parse returned success, 52067c478bd9Sstevel@tonic-gate * it means that there is nothing to add. 52077c478bd9Sstevel@tonic-gate */ 52087c478bd9Sstevel@tonic-gate if (act_props->pattern[0] == NULL && 52097c478bd9Sstevel@tonic-gate act_props->ap[0].act == NULL) 52107c478bd9Sstevel@tonic-gate break; 52117c478bd9Sstevel@tonic-gate 52127c478bd9Sstevel@tonic-gate ret = form_ipsec_conf(act_props, &conf); 52137c478bd9Sstevel@tonic-gate if (ret != 0) { 52147c478bd9Sstevel@tonic-gate warnx(gettext("form_ipsec_conf error")); 5215e3320f40Smarkfen (void) print_cmd_buf(stderr, NOERROR); 5216eec550adSpwernau /* Reset globals before trying the next rule. */ 5217eec550adSpwernau if (shp != NULL) { 5218eec550adSpwernau freehostent(shp); 5219eec550adSpwernau shp = NULL; 5220eec550adSpwernau } 5221eec550adSpwernau if (dhp != NULL) { 5222eec550adSpwernau freehostent(dhp); 5223eec550adSpwernau dhp = NULL; 5224eec550adSpwernau } 5225eec550adSpwernau splen = 0; 5226eec550adSpwernau dplen = 0; 5227e3320f40Smarkfen continue; 5228e3320f40Smarkfen } 5229e3320f40Smarkfen 5230e3320f40Smarkfen good_rules++; 5231e3320f40Smarkfen 5232e3320f40Smarkfen if (first_time) { 5233e3320f40Smarkfen /* 5234e3320f40Smarkfen * Time to assume that there are valid policy entries. 5235e3320f40Smarkfen * If the IPsec kernel modules are not loaded this 5236e3320f40Smarkfen * will load them now. 5237e3320f40Smarkfen */ 5238e3320f40Smarkfen first_time = B_FALSE; 5239e3320f40Smarkfen fetch_algorithms(); 5240e3320f40Smarkfen ipsec_conf_admin(SPD_CLONE); 52417c478bd9Sstevel@tonic-gate } 52427c478bd9Sstevel@tonic-gate 52437c478bd9Sstevel@tonic-gate /* 52447c478bd9Sstevel@tonic-gate * shp, dhp, splen, and dplen are globals set by 52457c478bd9Sstevel@tonic-gate * form_ipsec_conf() while parsing the addresses. 52467c478bd9Sstevel@tonic-gate */ 52477c478bd9Sstevel@tonic-gate if (shp == NULL && dhp == NULL) { 52487c478bd9Sstevel@tonic-gate switch (do_port_adds(&conf)) { 52497c478bd9Sstevel@tonic-gate case 0: 52507c478bd9Sstevel@tonic-gate /* no error */ 52517c478bd9Sstevel@tonic-gate break; 52527c478bd9Sstevel@tonic-gate case EEXIST: 52537c478bd9Sstevel@tonic-gate /* duplicate entries, continue adds */ 525443c889d3Smarkfen (void) print_cmd_buf(stderr, EEXIST); 52557c478bd9Sstevel@tonic-gate goto next; 52567c478bd9Sstevel@tonic-gate default: 52577c478bd9Sstevel@tonic-gate /* other error, bail */ 52587c478bd9Sstevel@tonic-gate ret = -1; 52597c478bd9Sstevel@tonic-gate goto bail; 52607c478bd9Sstevel@tonic-gate } 52617c478bd9Sstevel@tonic-gate } else { 52628810c16bSdanmcd ret = do_address_adds(&conf, &diag); 52637c478bd9Sstevel@tonic-gate switch (ret) { 52647c478bd9Sstevel@tonic-gate case 0: 52657c478bd9Sstevel@tonic-gate /* no error. */ 52667c478bd9Sstevel@tonic-gate break; 52677c478bd9Sstevel@tonic-gate case EEXIST: 526843c889d3Smarkfen (void) print_cmd_buf(stderr, EEXIST); 52697c478bd9Sstevel@tonic-gate goto next; 52707c478bd9Sstevel@tonic-gate case EBUSY: 52717c478bd9Sstevel@tonic-gate warnx(gettext( 5272d5751483Smarkfen "Can't set mask and /NN prefix.")); 52737c478bd9Sstevel@tonic-gate ret = -1; 52747c478bd9Sstevel@tonic-gate break; 52758810c16bSdanmcd case ENOENT: 52768810c16bSdanmcd warnx(gettext("Cannot find tunnel " 52778810c16bSdanmcd "interface %s."), interface_name); 52788810c16bSdanmcd ret = -1; 52798810c16bSdanmcd break; 52807c478bd9Sstevel@tonic-gate case EINVAL: 52818810c16bSdanmcd /* 52828810c16bSdanmcd * PF_POLICY didn't like what we sent. We 52838810c16bSdanmcd * can't check all input up here, but we 52848810c16bSdanmcd * do in-kernel. 52858810c16bSdanmcd */ 52868810c16bSdanmcd warnx(gettext("PF_POLICY invalid input:\n\t%s"), 52878810c16bSdanmcd spdsock_diag(diag)); 52888810c16bSdanmcd break; 52898810c16bSdanmcd case EOPNOTSUPP: 52907c478bd9Sstevel@tonic-gate warnx(gettext("Can't set /NN" 5291d5751483Smarkfen " prefix on multi-host name.")); 52927c478bd9Sstevel@tonic-gate ret = -1; 52937c478bd9Sstevel@tonic-gate break; 52947c478bd9Sstevel@tonic-gate case ERANGE: 52957c478bd9Sstevel@tonic-gate warnx(gettext("/NN prefix is too big!")); 52967c478bd9Sstevel@tonic-gate ret = -1; 52977c478bd9Sstevel@tonic-gate break; 52987c478bd9Sstevel@tonic-gate case ESRCH: 52997c478bd9Sstevel@tonic-gate warnx(gettext("No matching IPv4 or " 5300d5751483Smarkfen "IPv6 saddr/daddr pairs")); 53017c478bd9Sstevel@tonic-gate ret = -1; 53027c478bd9Sstevel@tonic-gate break; 53037c478bd9Sstevel@tonic-gate default: 53047c478bd9Sstevel@tonic-gate /* Should never get here. */ 53057c478bd9Sstevel@tonic-gate errno = ret; 53067c478bd9Sstevel@tonic-gate warn(gettext("Misc. error")); 53077c478bd9Sstevel@tonic-gate ret = -1; 53087c478bd9Sstevel@tonic-gate } 53097c478bd9Sstevel@tonic-gate if (ret == -1) 53107c478bd9Sstevel@tonic-gate goto bail; 53117c478bd9Sstevel@tonic-gate } 53127c478bd9Sstevel@tonic-gate 53137c478bd9Sstevel@tonic-gate /* 531443c889d3Smarkfen * Go ahead and add policy entries to config file. 53157c478bd9Sstevel@tonic-gate * The # should help re-using the ipsecpolicy.conf 53167c478bd9Sstevel@tonic-gate * for input again as # will be treated as comment. 53177c478bd9Sstevel@tonic-gate */ 53187c478bd9Sstevel@tonic-gate if (fprintf(policy_fp, "%s %lld \n", INDEX_TAG, 53197c478bd9Sstevel@tonic-gate conf.ips_policy_index) == -1) { 53207c478bd9Sstevel@tonic-gate warn("fprintf"); 53217c478bd9Sstevel@tonic-gate warnx(gettext("Addition incomplete, Please " 53227c478bd9Sstevel@tonic-gate "flush all the entries and re-configure :")); 53237c478bd9Sstevel@tonic-gate reconfigure(); 53247c478bd9Sstevel@tonic-gate ret = -1; 53257c478bd9Sstevel@tonic-gate break; 53267c478bd9Sstevel@tonic-gate } 532743c889d3Smarkfen if (print_cmd_buf(policy_fp, NOERROR) == -1) { 53287c478bd9Sstevel@tonic-gate warnx(gettext("Addition incomplete. Please " 53297c478bd9Sstevel@tonic-gate "flush all the entries and re-configure :")); 53307c478bd9Sstevel@tonic-gate reconfigure(); 53317c478bd9Sstevel@tonic-gate ret = -1; 53327c478bd9Sstevel@tonic-gate break; 53337c478bd9Sstevel@tonic-gate } 53347c478bd9Sstevel@tonic-gate /* 53357c478bd9Sstevel@tonic-gate * We add one newline by default to separate out the 53367c478bd9Sstevel@tonic-gate * entries. If the last character is not a newline, we 53377c478bd9Sstevel@tonic-gate * insert a newline for free. This makes sure that all 53387c478bd9Sstevel@tonic-gate * entries look consistent in the file. 53397c478bd9Sstevel@tonic-gate */ 53407c478bd9Sstevel@tonic-gate if (*(cbuf + cbuf_offset - 1) == '\n') { 53417c478bd9Sstevel@tonic-gate if (fprintf(policy_fp, "\n") == -1) { 53427c478bd9Sstevel@tonic-gate warn("fprintf"); 53437c478bd9Sstevel@tonic-gate warnx(gettext("Addition incomplete. " 53447c478bd9Sstevel@tonic-gate "Please flush all the entries and " 53457c478bd9Sstevel@tonic-gate "re-configure :")); 53467c478bd9Sstevel@tonic-gate reconfigure(); 53477c478bd9Sstevel@tonic-gate ret = -1; 53487c478bd9Sstevel@tonic-gate break; 53497c478bd9Sstevel@tonic-gate } 53507c478bd9Sstevel@tonic-gate } else { 53517c478bd9Sstevel@tonic-gate if (fprintf(policy_fp, "\n\n") == -1) { 53527c478bd9Sstevel@tonic-gate warn("fprintf"); 53537c478bd9Sstevel@tonic-gate warnx(gettext("Addition incomplete. " 53547c478bd9Sstevel@tonic-gate "Please flush all the entries and " 53557c478bd9Sstevel@tonic-gate "re-configure :")); 53567c478bd9Sstevel@tonic-gate reconfigure(); 53577c478bd9Sstevel@tonic-gate ret = -1; 53587c478bd9Sstevel@tonic-gate break; 53597c478bd9Sstevel@tonic-gate } 53607c478bd9Sstevel@tonic-gate } 5361e3320f40Smarkfen next: 53627c478bd9Sstevel@tonic-gate /* 53637c478bd9Sstevel@tonic-gate * Make sure this gets to the disk before 53647c478bd9Sstevel@tonic-gate * we parse the next entry. 53657c478bd9Sstevel@tonic-gate */ 53667c478bd9Sstevel@tonic-gate (void) fflush(policy_fp); 53677c478bd9Sstevel@tonic-gate for (i = 0; act_props->pattern[i] != NULL; i++) 53687c478bd9Sstevel@tonic-gate free(act_props->pattern[i]); 53697c478bd9Sstevel@tonic-gate for (j = 0; act_props->ap[j].act != NULL; j++) { 53707c478bd9Sstevel@tonic-gate free(act_props->ap[j].act); 53717c478bd9Sstevel@tonic-gate for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 53727c478bd9Sstevel@tonic-gate free(act_props->ap[j].prop[i]); 53737c478bd9Sstevel@tonic-gate } 53747c478bd9Sstevel@tonic-gate } 5375d5751483Smarkfen if (ret == PARSE_EOF) 5376d5751483Smarkfen ret = 0; /* Not an error */ 53777c478bd9Sstevel@tonic-gate bail: 53787c478bd9Sstevel@tonic-gate if (ret == -1) { 537943c889d3Smarkfen (void) print_cmd_buf(stderr, EINVAL); 53807c478bd9Sstevel@tonic-gate for (i = 0; act_props->pattern[i] != NULL; i++) 53817c478bd9Sstevel@tonic-gate free(act_props->pattern[i]); 53827c478bd9Sstevel@tonic-gate for (j = 0; act_props->ap[j].act != NULL; j++) { 53837c478bd9Sstevel@tonic-gate free(act_props->ap[j].act); 53847c478bd9Sstevel@tonic-gate for (i = 0; act_props->ap[j].prop[i] != NULL; i++) 53857c478bd9Sstevel@tonic-gate free(act_props->ap[j].prop[i]); 53867c478bd9Sstevel@tonic-gate } 53877c478bd9Sstevel@tonic-gate } 53887c478bd9Sstevel@tonic-gate #ifdef DEBUG_HEAVY 53897c478bd9Sstevel@tonic-gate (void) printf("ipsec_conf_add: ret val = %d\n", ret); 5390e3320f40Smarkfen (void) fflush(stdout); 53917c478bd9Sstevel@tonic-gate #endif 5392d5751483Smarkfen if (num_rules == 0 && ret == 0) { 5393eec550adSpwernau nuke_adds(); 5394e3320f40Smarkfen (void) restore_all_signals(); 5395e3320f40Smarkfen (void) unlock(lfd); 5396e3320f40Smarkfen EXIT_OK("Policy file does not contain any valid rules."); 5397e3320f40Smarkfen } 5398e3320f40Smarkfen if (num_rules != good_rules) { 5399e3320f40Smarkfen /* This is an error */ 5400eec550adSpwernau nuke_adds(); 5401e3320f40Smarkfen (void) restore_all_signals(); 5402e3320f40Smarkfen (void) unlock(lfd); 5403e3320f40Smarkfen EXIT_BADCONFIG2("%d policy rule(s) contained errors.", 5404e3320f40Smarkfen num_rules - good_rules); 5405e3320f40Smarkfen } 54067c478bd9Sstevel@tonic-gate /* looks good, flip it in */ 5407e3320f40Smarkfen if (ret == 0 && !just_check) { 5408e3320f40Smarkfen if (!ipsecconf_qflag) { 5409e3320f40Smarkfen (void) printf("%s", warning); 5410e3320f40Smarkfen } 5411d5751483Smarkfen if (smf_managed) 5412d5751483Smarkfen warnx(gettext("%d policy rules added."), good_rules); 54137c478bd9Sstevel@tonic-gate ipsec_conf_admin(SPD_FLIP); 5414e3320f40Smarkfen } else { 54157c478bd9Sstevel@tonic-gate nuke_adds(); 5416e3320f40Smarkfen if (just_check) { 5417d5751483Smarkfen (void) fprintf(stdout, gettext("IPsec configuration " 5418d5751483Smarkfen "does not contain any errors.\n")); 5419e3320f40Smarkfen (void) fprintf(stdout, gettext( 5420e3320f40Smarkfen "IPsec policy was not modified.\n")); 5421e3320f40Smarkfen (void) fflush(stdout); 5422e3320f40Smarkfen } 5423e3320f40Smarkfen } 5424e3320f40Smarkfen flushret = ipsec_conf_flush(SPD_STANDBY); 5425e3320f40Smarkfen if (flushret != 0) 5426e3320f40Smarkfen return (flushret); 54277c478bd9Sstevel@tonic-gate return (ret); 54287c478bd9Sstevel@tonic-gate } 54297c478bd9Sstevel@tonic-gate 54307c478bd9Sstevel@tonic-gate 54317c478bd9Sstevel@tonic-gate static int 54327c478bd9Sstevel@tonic-gate ipsec_conf_sub() 54337c478bd9Sstevel@tonic-gate { 54347c478bd9Sstevel@tonic-gate act_prop_t *act_props = malloc(sizeof (act_prop_t)); 54357c478bd9Sstevel@tonic-gate FILE *remove_fp, *policy_fp; 54367c478bd9Sstevel@tonic-gate char rbuf[MAXLEN], pbuf[MAXLEN], /* remove buffer, and policy buffer */ 54377c478bd9Sstevel@tonic-gate *warning = gettext( 5438d5751483Smarkfen "\tWARNING: Policy entries that are being removed may\n" 5439d5751483Smarkfen "\taffect the existing connections. Existing connections\n" 5440d5751483Smarkfen "\tthat are subjected to policy constraints may no longer\n" 5441d5751483Smarkfen "\tbe subjected to policy contraints because of its\n" 5442d5751483Smarkfen "\tremoval. This can compromise security, and disrupt\n" 5443d5751483Smarkfen "\tthe communication of the existing connection.\n" 5444d5751483Smarkfen "\tConnections that are latched will remain unaffected\n" 5445d5751483Smarkfen "\tuntil they close.\n"); 54467c478bd9Sstevel@tonic-gate int ret = 0; 54477c478bd9Sstevel@tonic-gate int index_len, pindex = 0; /* init value in case of pfile error */ 54487c478bd9Sstevel@tonic-gate 54497c478bd9Sstevel@tonic-gate if (act_props == NULL) { 54507c478bd9Sstevel@tonic-gate warn(gettext("memory")); 54517c478bd9Sstevel@tonic-gate return (-1); 54527c478bd9Sstevel@tonic-gate } 54537c478bd9Sstevel@tonic-gate 54547c478bd9Sstevel@tonic-gate /* clone into standby DB */ 54557c478bd9Sstevel@tonic-gate (void) ipsec_conf_admin(SPD_CLONE); 54567c478bd9Sstevel@tonic-gate 54577c478bd9Sstevel@tonic-gate if (strcmp(filename, "-") == 0) 54587c478bd9Sstevel@tonic-gate remove_fp = stdin; 54597c478bd9Sstevel@tonic-gate else 54607c478bd9Sstevel@tonic-gate remove_fp = fopen(filename, "r"); 54617c478bd9Sstevel@tonic-gate 54627c478bd9Sstevel@tonic-gate if (remove_fp == NULL) { 54637c478bd9Sstevel@tonic-gate warn(gettext("%s : Input file cannot be opened"), filename); 54647c478bd9Sstevel@tonic-gate usage(); 54657c478bd9Sstevel@tonic-gate free(act_props); 54667c478bd9Sstevel@tonic-gate return (-1); 54677c478bd9Sstevel@tonic-gate } 54687c478bd9Sstevel@tonic-gate 54697c478bd9Sstevel@tonic-gate /* open policy file so we can locate the correct policy */ 54707c478bd9Sstevel@tonic-gate (void) umask(0022); /* in case it gets created! */ 54717c478bd9Sstevel@tonic-gate policy_fp = fopen(POLICY_CONF_FILE, "r+"); 54727c478bd9Sstevel@tonic-gate if (policy_fp == NULL) { 54737c478bd9Sstevel@tonic-gate warn(gettext("%s cannot be opened"), POLICY_CONF_FILE); 54747c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 54757c478bd9Sstevel@tonic-gate free(act_props); 54767c478bd9Sstevel@tonic-gate return (-1); 54777c478bd9Sstevel@tonic-gate } 54787c478bd9Sstevel@tonic-gate 54797c478bd9Sstevel@tonic-gate /* don't print the warning if we're in q[uiet] mode */ 54807c478bd9Sstevel@tonic-gate if (!ipsecconf_qflag) 54817c478bd9Sstevel@tonic-gate (void) printf("%s", warning); 54827c478bd9Sstevel@tonic-gate 54837c478bd9Sstevel@tonic-gate /* this bit is done primarily so we can read what we write */ 54847c478bd9Sstevel@tonic-gate index_len = strlen(INDEX_TAG); 54857c478bd9Sstevel@tonic-gate 54867c478bd9Sstevel@tonic-gate /* 54877c478bd9Sstevel@tonic-gate * We want to look for the policy in rbuf in the policy file. 54887c478bd9Sstevel@tonic-gate * Go through the list of policies to remove, locating each one. 54897c478bd9Sstevel@tonic-gate */ 54907c478bd9Sstevel@tonic-gate while (fgets(rbuf, MAXLEN, remove_fp) != NULL) { 54917c478bd9Sstevel@tonic-gate char *buf; 54927c478bd9Sstevel@tonic-gate int offset, prev_offset, prev_prev_offset, nlines; 54937c478bd9Sstevel@tonic-gate fpos_t ipos; 54947c478bd9Sstevel@tonic-gate int pbuf_len = 0; 54957c478bd9Sstevel@tonic-gate char *tmp; 54967c478bd9Sstevel@tonic-gate /* skip blanks here (so we don't need to do it below)! */ 5497d5751483Smarkfen for (tmp = rbuf; (*tmp != '\0') && isspace(*tmp); ) 5498d5751483Smarkfen tmp++; 5499d5751483Smarkfen 55007c478bd9Sstevel@tonic-gate if (*tmp == '\0') 5501d5751483Smarkfen continue; /* while(); */ 55027c478bd9Sstevel@tonic-gate 55037c478bd9Sstevel@tonic-gate /* skip the INDEX_TAG lines in the remove buffer */ 55047c478bd9Sstevel@tonic-gate if (strncasecmp(rbuf, INDEX_TAG, index_len) == 0) 55057c478bd9Sstevel@tonic-gate continue; 55067c478bd9Sstevel@tonic-gate 55077c478bd9Sstevel@tonic-gate /* skip commented lines */ 55087c478bd9Sstevel@tonic-gate if (*tmp == '#') 5509d5751483Smarkfen continue; /* while(); */ 55107c478bd9Sstevel@tonic-gate 55117c478bd9Sstevel@tonic-gate /* 55127c478bd9Sstevel@tonic-gate * We start by presuming only good policies are in the pfile, 55137c478bd9Sstevel@tonic-gate * and so only good policies from the rfile will match them. 55147c478bd9Sstevel@tonic-gate * ipsec_conf_del ensures this later by calling parse_one() on 55157c478bd9Sstevel@tonic-gate * pfile before it deletes the entry. 55167c478bd9Sstevel@tonic-gate */ 55177c478bd9Sstevel@tonic-gate for (offset = prev_offset = prev_prev_offset = 0; 55187c478bd9Sstevel@tonic-gate fgets(pbuf, MAXLEN, policy_fp) != NULL; 55197c478bd9Sstevel@tonic-gate offset += pbuf_len) { 55207c478bd9Sstevel@tonic-gate prev_offset = offset; 55217c478bd9Sstevel@tonic-gate pbuf_len = strlen(pbuf); 55227c478bd9Sstevel@tonic-gate 55237c478bd9Sstevel@tonic-gate /* skip blank lines which seperate policy entries */ 55247c478bd9Sstevel@tonic-gate if (pbuf[0] == '\n') 55257c478bd9Sstevel@tonic-gate continue; 55267c478bd9Sstevel@tonic-gate 55277c478bd9Sstevel@tonic-gate /* if we found an index, save it */ 55287c478bd9Sstevel@tonic-gate if (strncasecmp(pbuf, INDEX_TAG, index_len) == 0) { 55297c478bd9Sstevel@tonic-gate buf = pbuf + index_len; 55307c478bd9Sstevel@tonic-gate buf++; 55318810c16bSdanmcd if ((pindex = parse_index(buf, NULL)) == -1) { 55327c478bd9Sstevel@tonic-gate /* bad index, we can't continue */ 55337c478bd9Sstevel@tonic-gate warnx(gettext( 5534d5751483Smarkfen "Invalid index in the file")); 55357c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 55367c478bd9Sstevel@tonic-gate (void) fclose(policy_fp); 55377c478bd9Sstevel@tonic-gate free(act_props); 55387c478bd9Sstevel@tonic-gate return (-1); 55397c478bd9Sstevel@tonic-gate } 55407c478bd9Sstevel@tonic-gate 55417c478bd9Sstevel@tonic-gate /* save this position in case it's the one */ 55427c478bd9Sstevel@tonic-gate if (fgetpos(policy_fp, &ipos) != 0) { 55437c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 55447c478bd9Sstevel@tonic-gate (void) fclose(policy_fp); 55457c478bd9Sstevel@tonic-gate free(act_props); 55467c478bd9Sstevel@tonic-gate return (-1); 55477c478bd9Sstevel@tonic-gate } 55487c478bd9Sstevel@tonic-gate } 55497c478bd9Sstevel@tonic-gate 55507c478bd9Sstevel@tonic-gate /* Does pbuf contain the remove policy? */ 55517c478bd9Sstevel@tonic-gate if (strncasecmp(rbuf, pbuf, pbuf_len) == 0) { 55527c478bd9Sstevel@tonic-gate /* we found the one to remove! */ 55537c478bd9Sstevel@tonic-gate if (pindex == 0) { 55547c478bd9Sstevel@tonic-gate warnx(gettext("Didn't find a valid " 55557c478bd9Sstevel@tonic-gate "index for policy")); 55567c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 55577c478bd9Sstevel@tonic-gate (void) fclose(policy_fp); 55587c478bd9Sstevel@tonic-gate free(act_props); 55597c478bd9Sstevel@tonic-gate return (-1); 55607c478bd9Sstevel@tonic-gate } 55617c478bd9Sstevel@tonic-gate 55627c478bd9Sstevel@tonic-gate /* off it - back up to the last INDEX! */ 55637c478bd9Sstevel@tonic-gate if (fsetpos(policy_fp, &ipos) != 0) { 55647c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 55657c478bd9Sstevel@tonic-gate (void) fclose(policy_fp); 55667c478bd9Sstevel@tonic-gate free(act_props); 55677c478bd9Sstevel@tonic-gate return (-1); 55687c478bd9Sstevel@tonic-gate } 55697c478bd9Sstevel@tonic-gate 55707c478bd9Sstevel@tonic-gate /* parse_one sets linecount = #lines to off */ 55717c478bd9Sstevel@tonic-gate if (parse_one(policy_fp, act_props) == -1) { 55727c478bd9Sstevel@tonic-gate warnx(gettext("Invalid policy entry " 55737c478bd9Sstevel@tonic-gate "in the file")); 55747c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 55757c478bd9Sstevel@tonic-gate (void) fclose(policy_fp); 55767c478bd9Sstevel@tonic-gate free(act_props); 55777c478bd9Sstevel@tonic-gate return (-1); 55787c478bd9Sstevel@tonic-gate } 55797c478bd9Sstevel@tonic-gate 55807c478bd9Sstevel@tonic-gate nlines = linecount + 2; 55817c478bd9Sstevel@tonic-gate goto delete; 55827c478bd9Sstevel@tonic-gate } 55837c478bd9Sstevel@tonic-gate /* 55847c478bd9Sstevel@tonic-gate * When we find a match, we want to pass the offset 55857c478bd9Sstevel@tonic-gate * of the line that is before it - the INDEX_TAG line. 55867c478bd9Sstevel@tonic-gate */ 55877c478bd9Sstevel@tonic-gate prev_prev_offset = prev_offset; 55887c478bd9Sstevel@tonic-gate } 55897c478bd9Sstevel@tonic-gate /* Didn't find a match - look at the next remove policy */ 5590d5751483Smarkfen continue; /* while(); */ 55917c478bd9Sstevel@tonic-gate 55927c478bd9Sstevel@tonic-gate delete: 55937c478bd9Sstevel@tonic-gate (void) fclose(policy_fp); 55947c478bd9Sstevel@tonic-gate 55957c478bd9Sstevel@tonic-gate if (delete_from_file(prev_prev_offset, nlines) != 0) { 55967c478bd9Sstevel@tonic-gate warnx(gettext("delete_from_file failure. " 55977c478bd9Sstevel@tonic-gate "Please flush all entries and re-configure :")); 55987c478bd9Sstevel@tonic-gate reconfigure(); 55997c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 56007c478bd9Sstevel@tonic-gate free(act_props); 56017c478bd9Sstevel@tonic-gate return (-1); 56027c478bd9Sstevel@tonic-gate } 56037c478bd9Sstevel@tonic-gate 56047c478bd9Sstevel@tonic-gate if (pfp_delete_rule(pindex) != 0) { 56057c478bd9Sstevel@tonic-gate warnx(gettext("Deletion incomplete. Please flush" 56067c478bd9Sstevel@tonic-gate "all the entries and re-configure :")); 56077c478bd9Sstevel@tonic-gate reconfigure(); 56087c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 56097c478bd9Sstevel@tonic-gate free(act_props); 56107c478bd9Sstevel@tonic-gate return (-1); 56117c478bd9Sstevel@tonic-gate } 56127c478bd9Sstevel@tonic-gate 56137c478bd9Sstevel@tonic-gate /* reset the globals */ 56147c478bd9Sstevel@tonic-gate linecount = 0; 56157c478bd9Sstevel@tonic-gate pindex = 0; 56168810c16bSdanmcd /* free(NULL) also works. */ 56178810c16bSdanmcd free(interface_name); 56188810c16bSdanmcd interface_name = NULL; 56197c478bd9Sstevel@tonic-gate 56207c478bd9Sstevel@tonic-gate /* reopen for next pass, automagically starting over. */ 56217c478bd9Sstevel@tonic-gate policy_fp = fopen(POLICY_CONF_FILE, "r"); 56227c478bd9Sstevel@tonic-gate if (policy_fp == NULL) { 56237c478bd9Sstevel@tonic-gate warn(gettext("%s cannot be re-opened, can't continue"), 56247c478bd9Sstevel@tonic-gate POLICY_CONF_FILE); 56257c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 56267c478bd9Sstevel@tonic-gate free(act_props); 56277c478bd9Sstevel@tonic-gate return (-1); 56287c478bd9Sstevel@tonic-gate } 56297c478bd9Sstevel@tonic-gate 56307c478bd9Sstevel@tonic-gate } /* read next remove policy */ 56317c478bd9Sstevel@tonic-gate 56327c478bd9Sstevel@tonic-gate if ((ret = pfp_delete_rule(pindex)) != 0) { 56337c478bd9Sstevel@tonic-gate warnx(gettext("Removal incomplete. Please flush " 56347c478bd9Sstevel@tonic-gate "all the entries and re-configure :")); 56357c478bd9Sstevel@tonic-gate reconfigure(); 56367c478bd9Sstevel@tonic-gate free(act_props); 56377c478bd9Sstevel@tonic-gate return (ret); 56387c478bd9Sstevel@tonic-gate } 56397c478bd9Sstevel@tonic-gate 56407c478bd9Sstevel@tonic-gate /* nothing left to look for */ 56417c478bd9Sstevel@tonic-gate (void) fclose(remove_fp); 56427c478bd9Sstevel@tonic-gate free(act_props); 56437c478bd9Sstevel@tonic-gate 56447c478bd9Sstevel@tonic-gate return (0); 56457c478bd9Sstevel@tonic-gate } 56468810c16bSdanmcd 56478810c16bSdanmcd /* 56488810c16bSdanmcd * Constructs a tunnel interface ID extension. Returns the length 56498810c16bSdanmcd * of the extension in 64-bit-words. 56508810c16bSdanmcd */ 56518810c16bSdanmcd static int 56528810c16bSdanmcd attach_tunname(spd_if_t *tunname) 56538810c16bSdanmcd { 56548810c16bSdanmcd if (tunname == NULL || interface_name == NULL) 56558810c16bSdanmcd return (0); 56568810c16bSdanmcd 56578810c16bSdanmcd tunname->spd_if_exttype = SPD_EXT_TUN_NAME; 56588810c16bSdanmcd /* 56598810c16bSdanmcd * Use "-3" because there's 4 bytes in the message itself, and 56608810c16bSdanmcd * we lose one because of the '\0' terminator. 56618810c16bSdanmcd */ 56628810c16bSdanmcd tunname->spd_if_len = SPD_8TO64( 56638810c16bSdanmcd P2ROUNDUP(sizeof (*tunname) + strlen(interface_name) - 3, 8)); 56648810c16bSdanmcd (void) strlcpy((char *)tunname->spd_if_name, interface_name, LIFNAMSIZ); 56658810c16bSdanmcd return (tunname->spd_if_len); 56668810c16bSdanmcd } 5667