xref: /titanic_41/usr/src/cmd/cmd-inet/usr.sbin/ilbadm/ilbadm_rules.c (revision 33f5ff17089e3a43e6e730bf80384c233123dbd9)
1dbed73cbSSangeeta Misra /*
2dbed73cbSSangeeta Misra  * CDDL HEADER START
3dbed73cbSSangeeta Misra  *
4dbed73cbSSangeeta Misra  * The contents of this file are subject to the terms of the
5dbed73cbSSangeeta Misra  * Common Development and Distribution License (the "License").
6dbed73cbSSangeeta Misra  * You may not use this file except in compliance with the License.
7dbed73cbSSangeeta Misra  *
8dbed73cbSSangeeta Misra  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9dbed73cbSSangeeta Misra  * or http://www.opensolaris.org/os/licensing.
10dbed73cbSSangeeta Misra  * See the License for the specific language governing permissions
11dbed73cbSSangeeta Misra  * and limitations under the License.
12dbed73cbSSangeeta Misra  *
13dbed73cbSSangeeta Misra  * When distributing Covered Code, include this CDDL HEADER in each
14dbed73cbSSangeeta Misra  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15dbed73cbSSangeeta Misra  * If applicable, add the following below this CDDL HEADER, with the
16dbed73cbSSangeeta Misra  * fields enclosed by brackets "[]" replaced with your own identifying
17dbed73cbSSangeeta Misra  * information: Portions Copyright [yyyy] [name of copyright owner]
18dbed73cbSSangeeta Misra  *
19dbed73cbSSangeeta Misra  * CDDL HEADER END
20dbed73cbSSangeeta Misra  */
21dbed73cbSSangeeta Misra 
22dbed73cbSSangeeta Misra /*
23dbed73cbSSangeeta Misra  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24dbed73cbSSangeeta Misra  * Use is subject to license terms.
25*33f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
26dbed73cbSSangeeta Misra  */
27dbed73cbSSangeeta Misra 
28dbed73cbSSangeeta Misra #include <stdio.h>
29dbed73cbSSangeeta Misra #include <unistd.h>
30dbed73cbSSangeeta Misra #include <stdlib.h>
31dbed73cbSSangeeta Misra #include <strings.h>
32dbed73cbSSangeeta Misra #include <errno.h>
33dbed73cbSSangeeta Misra #include <sys/types.h>
34dbed73cbSSangeeta Misra #include <sys/socket.h>
35dbed73cbSSangeeta Misra #include <netinet/in.h>
36dbed73cbSSangeeta Misra #include <arpa/inet.h>
37dbed73cbSSangeeta Misra #include <sys/list.h>
38dbed73cbSSangeeta Misra #include <netdb.h>
39dbed73cbSSangeeta Misra #include <ofmt.h>
40dbed73cbSSangeeta Misra #include <assert.h>
41dbed73cbSSangeeta Misra #include <libilb.h>
42dbed73cbSSangeeta Misra #include "ilbadm.h"
43dbed73cbSSangeeta Misra 
44dbed73cbSSangeeta Misra static ilbadm_key_name_t rl_incoming_keys[] = {
45dbed73cbSSangeeta Misra 	{ILB_KEY_VIP, "vip", ""},
46dbed73cbSSangeeta Misra 	{ILB_KEY_PORT, "port", ""},
47dbed73cbSSangeeta Misra 	{ILB_KEY_PROTOCOL, "protocol", "prot"},
48dbed73cbSSangeeta Misra 	{ILB_KEY_BAD, "", ""}
49dbed73cbSSangeeta Misra };
50dbed73cbSSangeeta Misra static ilbadm_key_name_t rl_method_keys[] = {
51dbed73cbSSangeeta Misra 	{ILB_KEY_ALGORITHM, "lbalg", "algo"},
52dbed73cbSSangeeta Misra 	{ILB_KEY_TYPE, "type", "topo"},
53dbed73cbSSangeeta Misra 	{ILB_KEY_SRC, "proxy-src", "nat-src"},
54dbed73cbSSangeeta Misra 	{ILB_KEY_STICKY, "pmask", "persist"},
55dbed73cbSSangeeta Misra 	{ILB_KEY_BAD, "", ""}
56dbed73cbSSangeeta Misra };
57dbed73cbSSangeeta Misra static ilbadm_key_name_t rl_outgoing_keys[] = {
58dbed73cbSSangeeta Misra 	{ILB_KEY_SERVERGROUP, "servergroup", "sg"},
59dbed73cbSSangeeta Misra 	{ILB_KEY_BAD, "", ""}
60dbed73cbSSangeeta Misra };
61dbed73cbSSangeeta Misra static ilbadm_key_name_t rl_healthchk_keys[] = {
62dbed73cbSSangeeta Misra 	{ILB_KEY_HEALTHCHECK, "hc-name", "hcn"},
63dbed73cbSSangeeta Misra 	{ILB_KEY_HCPORT, "hc-port", "hcp"},
64dbed73cbSSangeeta Misra 	{ILB_KEY_BAD, "", ""}
65dbed73cbSSangeeta Misra };
66dbed73cbSSangeeta Misra static ilbadm_key_name_t rl_timer_keys[] = {
67dbed73cbSSangeeta Misra 	{ILB_KEY_CONNDRAIN, "conn-drain", ""},
68dbed73cbSSangeeta Misra 	{ILB_KEY_NAT_TO, "nat-timeout", ""},
69dbed73cbSSangeeta Misra 	{ILB_KEY_STICKY_TO, "persist-timeout", ""},
70dbed73cbSSangeeta Misra 	{ILB_KEY_BAD, "", ""}
71dbed73cbSSangeeta Misra };
72dbed73cbSSangeeta Misra 
73dbed73cbSSangeeta Misra static ilbadm_key_name_t *all_keys[] = {
74dbed73cbSSangeeta Misra 	rl_incoming_keys, rl_method_keys, rl_outgoing_keys,
75dbed73cbSSangeeta Misra 	rl_healthchk_keys, rl_timer_keys, NULL
76dbed73cbSSangeeta Misra };
77dbed73cbSSangeeta Misra 
78dbed73cbSSangeeta Misra 
79dbed73cbSSangeeta Misra /* field ids for of_* functions */
80dbed73cbSSangeeta Misra #define	OF_IP_VIP		0
81dbed73cbSSangeeta Misra #define	OF_IP_PROXYSRC		1
82dbed73cbSSangeeta Misra #define	OF_IP_STICKYMASK	2
83dbed73cbSSangeeta Misra 
84dbed73cbSSangeeta Misra #define	OF_STR_RNAME		0
85dbed73cbSSangeeta Misra #define	OF_STR_HCNAME		1
86dbed73cbSSangeeta Misra #define	OF_STR_SGNAME		2
87dbed73cbSSangeeta Misra #define	OF_STR_INTERFACE	3
88dbed73cbSSangeeta Misra 
89dbed73cbSSangeeta Misra #define	OF_PORT			0
90dbed73cbSSangeeta Misra #define	OF_HCPORT		1
91dbed73cbSSangeeta Misra 
92dbed73cbSSangeeta Misra #define	OF_T_CONN		0
93dbed73cbSSangeeta Misra #define	OF_T_NAT		1
94dbed73cbSSangeeta Misra #define	OF_T_STICKY		2
95dbed73cbSSangeeta Misra 
96dbed73cbSSangeeta Misra #define	OF_SRV_ID		0
97dbed73cbSSangeeta Misra #define	OF_SRV_ADDR		1
98dbed73cbSSangeeta Misra #define	OF_SRV_PORT		2
99dbed73cbSSangeeta Misra #define	OF_SRV_STATUS		3
100dbed73cbSSangeeta Misra #define	OF_SRV_RNAME		4
101dbed73cbSSangeeta Misra #define	OF_SRV_SGNAME		5
102dbed73cbSSangeeta Misra #define	OF_SRV_HOSTNAME		6
103dbed73cbSSangeeta Misra 
104dbed73cbSSangeeta Misra /* some field sizes of ofmt_field_t arrays */
105dbed73cbSSangeeta Misra #define	IPv4_FIELDWIDTH		16
106dbed73cbSSangeeta Misra #define	IPv6_FIELDWIDTH		39
107dbed73cbSSangeeta Misra #define	ILB_HOSTNAMELEN		20
108dbed73cbSSangeeta Misra #define	ILB_STATUSFIELD_LEN	7
109dbed73cbSSangeeta Misra 
110dbed73cbSSangeeta Misra typedef struct arg_struct {
111dbed73cbSSangeeta Misra 	int		flags;
112dbed73cbSSangeeta Misra 	char		*o_str;
113dbed73cbSSangeeta Misra 	ofmt_field_t	*o_fields;
114dbed73cbSSangeeta Misra 	ofmt_handle_t	oh;
115dbed73cbSSangeeta Misra } ilbadm_sh_rl_arg_t;
116dbed73cbSSangeeta Misra 
117dbed73cbSSangeeta Misra typedef struct ilbadm_rl_exp_arg {
118dbed73cbSSangeeta Misra 	FILE	*fp;
119dbed73cbSSangeeta Misra } ilbadm_rl_exp_arg_t;
120dbed73cbSSangeeta Misra 
121dbed73cbSSangeeta Misra typedef struct ilbadm_rl_list_arg {
122dbed73cbSSangeeta Misra 	ilb_handle_t	h;
123dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd;
124dbed73cbSSangeeta Misra } ilbadm_rl_list_arg_t;
125dbed73cbSSangeeta Misra 
126dbed73cbSSangeeta Misra typedef struct ilbadm_rl_srvlist_arg {
127dbed73cbSSangeeta Misra 	char		*sgname;
128dbed73cbSSangeeta Misra 	ilb_server_data_t	*sd;
129dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd;
130dbed73cbSSangeeta Misra 	int		flags;
131dbed73cbSSangeeta Misra 	char		*o_str;
132dbed73cbSSangeeta Misra 	ofmt_field_t	*o_fields;
133dbed73cbSSangeeta Misra 	ofmt_handle_t	oh;
134dbed73cbSSangeeta Misra } ilbadm_rl_srvlist_arg_t;
135dbed73cbSSangeeta Misra 
136dbed73cbSSangeeta Misra static ofmt_cb_t of_algo;
137dbed73cbSSangeeta Misra static ofmt_cb_t of_proto;
138dbed73cbSSangeeta Misra static ofmt_cb_t of_rl_ip;
139dbed73cbSSangeeta Misra static ofmt_cb_t of_rl_mask;
140dbed73cbSSangeeta Misra static ofmt_cb_t of_rport;
141dbed73cbSSangeeta Misra static ofmt_cb_t of_rstatus;
142dbed73cbSSangeeta Misra static ofmt_cb_t of_str;
143dbed73cbSSangeeta Misra static ofmt_cb_t of_time;
144dbed73cbSSangeeta Misra static ofmt_cb_t of_topo;
145dbed73cbSSangeeta Misra static ofmt_cb_t of_rl_srvlist;
146dbed73cbSSangeeta Misra 
147dbed73cbSSangeeta Misra static boolean_t of_srv2str(ofmt_arg_t *, char *, uint_t);
148dbed73cbSSangeeta Misra static boolean_t of_port2str(in_port_t, in_port_t, char *, uint_t);
149dbed73cbSSangeeta Misra 
150dbed73cbSSangeeta Misra static ofmt_field_t rfields_v4[] = {
151dbed73cbSSangeeta Misra 	{"RULENAME",	ILB_NAMESZ,	OF_STR_RNAME,	of_str},
152dbed73cbSSangeeta Misra 	{"STATUS",	ILB_STATUSFIELD_LEN,	0,	of_rstatus},
153dbed73cbSSangeeta Misra 	{"PORT",	10,		OF_PORT,	of_rport},
154dbed73cbSSangeeta Misra 	{"PROTOCOL",	5,		0,	of_proto},
155dbed73cbSSangeeta Misra 	{"LBALG",	12,		0,	of_algo},
156dbed73cbSSangeeta Misra 	{"TYPE",	8,		0,	of_topo},
157dbed73cbSSangeeta Misra 	{"PROXY-SRC",	2*IPv4_FIELDWIDTH+1,	OF_IP_PROXYSRC,	of_rl_ip},
158dbed73cbSSangeeta Misra 	{"PMASK",	6,	OF_IP_STICKYMASK, of_rl_mask},
159dbed73cbSSangeeta Misra 	{"HC-NAME",	ILB_NAMESZ,	OF_STR_HCNAME,	of_str},
160dbed73cbSSangeeta Misra 	{"HC-PORT",	8,		OF_HCPORT,	of_rport},
161dbed73cbSSangeeta Misra 	{"CONN-DRAIN",	11,		OF_T_CONN,	of_time},
162dbed73cbSSangeeta Misra 	{"NAT-TIMEOUT",	12,		OF_T_NAT,	of_time},
163dbed73cbSSangeeta Misra 	{"PERSIST-TIMEOUT",		16,	OF_T_STICKY,	of_time},
164dbed73cbSSangeeta Misra 	{"SERVERGROUP",	ILB_SGNAME_SZ,	OF_STR_SGNAME,	of_str},
165dbed73cbSSangeeta Misra 	{"VIP",		IPv4_FIELDWIDTH,	OF_IP_VIP,	of_rl_ip},
166dbed73cbSSangeeta Misra 	{"SERVERS",	20,		0,	of_rl_srvlist},
167dbed73cbSSangeeta Misra 	{NULL,		0,		0,	NULL}
168dbed73cbSSangeeta Misra };
169dbed73cbSSangeeta Misra 
170dbed73cbSSangeeta Misra static ofmt_field_t rfields_v6[] = {
171dbed73cbSSangeeta Misra 	{"RULENAME",	ILB_NAMESZ,	OF_STR_RNAME,	of_str},
172dbed73cbSSangeeta Misra 	{"STATUS",	ILB_STATUSFIELD_LEN,	0,	of_rstatus},
173dbed73cbSSangeeta Misra 	{"PORT",	10,		OF_PORT,	of_rport},
174dbed73cbSSangeeta Misra 	{"PROTOCOL",	5,		0,	of_proto},
175dbed73cbSSangeeta Misra 	{"LBALG",	12,		0,	of_algo},
176dbed73cbSSangeeta Misra 	{"TYPE",	8,		0,	of_topo},
177dbed73cbSSangeeta Misra 	{"PROXY-SRC",	IPv6_FIELDWIDTH,	OF_IP_PROXYSRC,	of_rl_ip},
178dbed73cbSSangeeta Misra 	{"PMASK",	6,		OF_IP_STICKYMASK, of_rl_mask},
179dbed73cbSSangeeta Misra 	{"HC-NAME",	ILB_NAMESZ,	OF_STR_HCNAME,	of_str},
180dbed73cbSSangeeta Misra 	{"HC-PORT",	8,		OF_HCPORT,	of_rport},
181dbed73cbSSangeeta Misra 	{"CONN-DRAIN",	11,		OF_T_CONN,	of_time},
182dbed73cbSSangeeta Misra 	{"NAT-TIMEOUT",	12,		OF_T_NAT,	of_time},
183dbed73cbSSangeeta Misra 	{"PERSIST-TIMEOUT",		16,	OF_T_STICKY,	of_time},
184dbed73cbSSangeeta Misra 	{"SERVERGROUP",	ILB_SGNAME_SZ,	OF_STR_SGNAME,	of_str},
185dbed73cbSSangeeta Misra 	{"VIP",		IPv6_FIELDWIDTH,	OF_IP_VIP,	of_rl_ip},
186dbed73cbSSangeeta Misra 	{"SERVERS",	20,		0,	of_rl_srvlist},
187dbed73cbSSangeeta Misra 	{NULL,		0,		0,	NULL}
188dbed73cbSSangeeta Misra };
189dbed73cbSSangeeta Misra 
190dbed73cbSSangeeta Misra static ofmt_field_t ssfields_v4[] = {
191dbed73cbSSangeeta Misra 	{"SERVERID",	ILB_NAMESZ,	OF_SRV_ID,	of_srv2str},
192dbed73cbSSangeeta Misra 	{"ADDRESS",	IPv4_FIELDWIDTH,	OF_SRV_ADDR,	of_srv2str},
193dbed73cbSSangeeta Misra 	{"PORT",	5,			OF_SRV_PORT,	of_srv2str},
194dbed73cbSSangeeta Misra 	{"RULENAME",	ILB_NAMESZ,	OF_SRV_RNAME,	of_srv2str},
195dbed73cbSSangeeta Misra 	{"STATUS",	ILB_STATUSFIELD_LEN,	OF_SRV_STATUS,	of_srv2str},
196dbed73cbSSangeeta Misra 	{"SERVERGROUP",	ILB_SGNAME_SZ,	OF_SRV_SGNAME,	of_srv2str},
197dbed73cbSSangeeta Misra 	{"HOSTNAME",	ILB_HOSTNAMELEN,	OF_SRV_HOSTNAME, of_srv2str},
198dbed73cbSSangeeta Misra 	{NULL,		0,		0,	NULL}
199dbed73cbSSangeeta Misra };
200dbed73cbSSangeeta Misra 
201dbed73cbSSangeeta Misra static ofmt_field_t ssfields_v6[] = {
202dbed73cbSSangeeta Misra 	{"SERVERID",	ILB_NAMESZ,	OF_SRV_ID,	of_srv2str},
203dbed73cbSSangeeta Misra 	{"ADDRESS",	IPv6_FIELDWIDTH,	OF_SRV_ADDR,	of_srv2str},
204dbed73cbSSangeeta Misra 	{"PORT",	5,			OF_SRV_PORT,	of_srv2str},
205dbed73cbSSangeeta Misra 	{"RULENAME",	ILB_NAMESZ,	OF_SRV_RNAME,	of_srv2str},
206dbed73cbSSangeeta Misra 	{"STATUS",	ILB_STATUSFIELD_LEN,	OF_SRV_STATUS,	of_srv2str},
207dbed73cbSSangeeta Misra 	{"SERVERGROUP",	ILB_SGNAME_SZ,	OF_SRV_SGNAME,	of_srv2str},
208dbed73cbSSangeeta Misra 	{"HOSTNAME",	ILB_HOSTNAMELEN,	OF_SRV_HOSTNAME, of_srv2str},
209dbed73cbSSangeeta Misra 	{NULL,		0,		0,	NULL}
210dbed73cbSSangeeta Misra };
211dbed73cbSSangeeta Misra 
212dbed73cbSSangeeta Misra extern int	optind, optopt, opterr;
213dbed73cbSSangeeta Misra extern char	*optarg;
214dbed73cbSSangeeta Misra 
215dbed73cbSSangeeta Misra extern ilbadm_val_type_t algo_types[];
216dbed73cbSSangeeta Misra extern ilbadm_val_type_t topo_types[];
217dbed73cbSSangeeta Misra 
218dbed73cbSSangeeta Misra static char *
i_key_to_opt(ilbadm_key_name_t * n,ilbadm_key_code_t k)219dbed73cbSSangeeta Misra i_key_to_opt(ilbadm_key_name_t *n, ilbadm_key_code_t k)
220dbed73cbSSangeeta Misra {
221dbed73cbSSangeeta Misra 	int i;
222dbed73cbSSangeeta Misra 
223dbed73cbSSangeeta Misra 	for (i = 0; n[i].k_key != ILB_KEY_BAD; i++)
224dbed73cbSSangeeta Misra 		if (n[i].k_key == k)
225dbed73cbSSangeeta Misra 			break;
226dbed73cbSSangeeta Misra 
227dbed73cbSSangeeta Misra 	return (n[i].k_name);
228dbed73cbSSangeeta Misra }
229dbed73cbSSangeeta Misra 
230dbed73cbSSangeeta Misra char *
ilbadm_key_to_opt(ilbadm_key_code_t k)231dbed73cbSSangeeta Misra ilbadm_key_to_opt(ilbadm_key_code_t k)
232dbed73cbSSangeeta Misra {
233dbed73cbSSangeeta Misra 	char 	*name;
234dbed73cbSSangeeta Misra 	int	i;
235dbed73cbSSangeeta Misra 
236dbed73cbSSangeeta Misra 	for (i = 0; all_keys[i] != NULL; i++) {
237dbed73cbSSangeeta Misra 		name = i_key_to_opt(all_keys[i], k);
238dbed73cbSSangeeta Misra 		if (*name != '\0')
239dbed73cbSSangeeta Misra 			return (name);
240dbed73cbSSangeeta Misra 	}
241dbed73cbSSangeeta Misra 
242dbed73cbSSangeeta Misra 	return (NULL);
243dbed73cbSSangeeta Misra }
244dbed73cbSSangeeta Misra 
245dbed73cbSSangeeta Misra /*
246dbed73cbSSangeeta Misra  * ports are in HOST byte order
247dbed73cbSSangeeta Misra  */
248dbed73cbSSangeeta Misra static void
ports2str(short port1,short port2,char * buf,const int sz)249dbed73cbSSangeeta Misra ports2str(short port1, short port2, char *buf, const int sz)
250dbed73cbSSangeeta Misra {
251dbed73cbSSangeeta Misra 	if (port2 <= port1)
252dbed73cbSSangeeta Misra 		(void) snprintf(buf, sz, "port=%d", port1);
253dbed73cbSSangeeta Misra 	else
254dbed73cbSSangeeta Misra 		(void) snprintf(buf, sz, "port=%d-%d", port1, port2);
255dbed73cbSSangeeta Misra }
256dbed73cbSSangeeta Misra 
257dbed73cbSSangeeta Misra static void
proto2str(short proto,char * buf,int sz)258dbed73cbSSangeeta Misra proto2str(short proto, char *buf, int sz)
259dbed73cbSSangeeta Misra {
260dbed73cbSSangeeta Misra 	struct protoent *pe;
261dbed73cbSSangeeta Misra 
262dbed73cbSSangeeta Misra 	pe = getprotobynumber((int)proto);
263dbed73cbSSangeeta Misra 	if (pe != NULL)
264dbed73cbSSangeeta Misra 		(void) snprintf(buf, sz, "protocol=%s", pe->p_name);
265dbed73cbSSangeeta Misra 	else
266dbed73cbSSangeeta Misra 		(void) sprintf(buf, "(bad proto %d)", proto);
267dbed73cbSSangeeta Misra }
268dbed73cbSSangeeta Misra 
269dbed73cbSSangeeta Misra static void
algo2str(ilb_algo_t algo,char * buf,int sz)270dbed73cbSSangeeta Misra algo2str(ilb_algo_t algo, char *buf, int sz)
271dbed73cbSSangeeta Misra {
272dbed73cbSSangeeta Misra 	char 	*s = i_str_from_val((int)algo, &algo_types[0]);
273dbed73cbSSangeeta Misra 
274dbed73cbSSangeeta Misra 	(void) snprintf(buf, sz, "lbalg=%s", (s && *s) ? s : "(bad algo)");
275dbed73cbSSangeeta Misra }
276dbed73cbSSangeeta Misra 
277dbed73cbSSangeeta Misra static int
algo2bare_str(ilb_algo_t algo,char * buf,int sz)278dbed73cbSSangeeta Misra algo2bare_str(ilb_algo_t algo, char *buf, int sz)
279dbed73cbSSangeeta Misra {
280dbed73cbSSangeeta Misra 	char 	*s = i_str_from_val((int)algo, &algo_types[0]);
281dbed73cbSSangeeta Misra 
282dbed73cbSSangeeta Misra 	return (snprintf(buf, sz, "%s", (s && *s) ? s : ""));
283dbed73cbSSangeeta Misra }
284dbed73cbSSangeeta Misra 
285dbed73cbSSangeeta Misra static void
topo2str(ilb_topo_t topo,char * buf,int sz)286dbed73cbSSangeeta Misra topo2str(ilb_topo_t topo, char *buf, int sz)
287dbed73cbSSangeeta Misra {
288dbed73cbSSangeeta Misra 	char 	*s = i_str_from_val((int)topo, &topo_types[0]);
289dbed73cbSSangeeta Misra 
290dbed73cbSSangeeta Misra 	(void) snprintf(buf, sz, "type=%s", (s && *s) ? s : "(bad type)");
291dbed73cbSSangeeta Misra }
292dbed73cbSSangeeta Misra 
293dbed73cbSSangeeta Misra static int
topo2bare_str(ilb_topo_t topo,char * buf,int sz)294dbed73cbSSangeeta Misra topo2bare_str(ilb_topo_t topo, char *buf, int sz)
295dbed73cbSSangeeta Misra {
296dbed73cbSSangeeta Misra 	char 	*s = i_str_from_val((int)topo, &topo_types[0]);
297dbed73cbSSangeeta Misra 
298dbed73cbSSangeeta Misra 	return (snprintf(buf, sz, "%s", (s && *s) ? s : ""));
299dbed73cbSSangeeta Misra }
300dbed73cbSSangeeta Misra 
301dbed73cbSSangeeta Misra static boolean_t
of_str(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)302dbed73cbSSangeeta Misra of_str(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
303dbed73cbSSangeeta Misra {
304dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
305dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
306dbed73cbSSangeeta Misra 
307dbed73cbSSangeeta Misra 	switch (of_arg->ofmt_id) {
308dbed73cbSSangeeta Misra 	case OF_STR_RNAME:
309dbed73cbSSangeeta Misra 		(void) strlcpy(buf, rd->r_name, bufsize);
310dbed73cbSSangeeta Misra 		break;
311dbed73cbSSangeeta Misra 	case OF_STR_SGNAME:
312dbed73cbSSangeeta Misra 		(void) strlcpy(buf, rd->r_sgname, bufsize);
313dbed73cbSSangeeta Misra 		break;
314dbed73cbSSangeeta Misra 	case OF_STR_HCNAME:
315dbed73cbSSangeeta Misra 		if (rd->r_hcname != NULL && *(rd->r_hcname) != '\0')
316dbed73cbSSangeeta Misra 			(void) strlcpy(buf, rd->r_hcname, bufsize);
317dbed73cbSSangeeta Misra 		break;
318dbed73cbSSangeeta Misra 	}
319dbed73cbSSangeeta Misra 	return (B_TRUE);
320dbed73cbSSangeeta Misra }
321dbed73cbSSangeeta Misra 
322dbed73cbSSangeeta Misra /* ARGSUSED */
323dbed73cbSSangeeta Misra static boolean_t
of_proto(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)324dbed73cbSSangeeta Misra of_proto(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
325dbed73cbSSangeeta Misra {
326dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
327dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
328dbed73cbSSangeeta Misra 
329dbed73cbSSangeeta Misra 	if (rd->r_proto == IPPROTO_TCP)
330dbed73cbSSangeeta Misra 		(void) strlcpy(buf, "TCP", bufsize);
331dbed73cbSSangeeta Misra 	else if (rd->r_proto == IPPROTO_UDP)
332dbed73cbSSangeeta Misra 		(void) strlcpy(buf, "UDP", bufsize);
333dbed73cbSSangeeta Misra 	else
334dbed73cbSSangeeta Misra 		return (B_FALSE);
335dbed73cbSSangeeta Misra 	return (B_TRUE);
336dbed73cbSSangeeta Misra }
337dbed73cbSSangeeta Misra 
338dbed73cbSSangeeta Misra static boolean_t
of_rl_ip(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)339dbed73cbSSangeeta Misra of_rl_ip(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
340dbed73cbSSangeeta Misra {
341dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
342dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
343dbed73cbSSangeeta Misra 	ilb_ip_addr_t	*ip = NULL, *ip2 = NULL;
344dbed73cbSSangeeta Misra 
345dbed73cbSSangeeta Misra 	switch (of_arg->ofmt_id) {
346dbed73cbSSangeeta Misra 	case OF_IP_VIP:
347dbed73cbSSangeeta Misra 		ip = &rd->r_vip;
348dbed73cbSSangeeta Misra 		break;
349dbed73cbSSangeeta Misra 	case OF_IP_PROXYSRC:
350dbed73cbSSangeeta Misra 		ip = &rd->r_nat_src_start;
351dbed73cbSSangeeta Misra 		ip2 = &rd->r_nat_src_end;
352dbed73cbSSangeeta Misra 		break;
353dbed73cbSSangeeta Misra 	case OF_IP_STICKYMASK:
354dbed73cbSSangeeta Misra 		ip = &rd->r_stickymask;
355dbed73cbSSangeeta Misra 		break;
356dbed73cbSSangeeta Misra 	}
357dbed73cbSSangeeta Misra 
358dbed73cbSSangeeta Misra 	/* only print something valid */
359dbed73cbSSangeeta Misra 	if (ip != NULL && (ip->ia_af == AF_INET || ip->ia_af == AF_INET6))
360dbed73cbSSangeeta Misra 		ip2str(ip, buf, bufsize, V6_ADDRONLY);
361dbed73cbSSangeeta Misra 	if (ip2 != NULL && (ip2->ia_af == AF_INET || ip2->ia_af == AF_INET6) &&
362dbed73cbSSangeeta Misra 	    buf[0] != '\0') {
363dbed73cbSSangeeta Misra 		int	sl = strlen(buf);
364dbed73cbSSangeeta Misra 
365dbed73cbSSangeeta Misra 		buf += sl; bufsize -= sl;
366dbed73cbSSangeeta Misra 		*buf++ = '-'; bufsize--;
367dbed73cbSSangeeta Misra 		ip2str(ip2, buf, bufsize, V6_ADDRONLY);
368dbed73cbSSangeeta Misra 	}
369dbed73cbSSangeeta Misra 
370dbed73cbSSangeeta Misra 	return (B_TRUE);
371dbed73cbSSangeeta Misra }
372dbed73cbSSangeeta Misra 
373dbed73cbSSangeeta Misra static boolean_t
of_rl_mask(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)374dbed73cbSSangeeta Misra of_rl_mask(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
375dbed73cbSSangeeta Misra {
376dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
377dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
378dbed73cbSSangeeta Misra 	ilb_ip_addr_t	*ip = NULL;
379dbed73cbSSangeeta Misra 
380dbed73cbSSangeeta Misra 	assert(of_arg->ofmt_id == OF_IP_STICKYMASK);
381dbed73cbSSangeeta Misra 	if (!(rd->r_flags & ILB_FLAGS_RULE_STICKY))
382dbed73cbSSangeeta Misra 		return (B_TRUE);
383dbed73cbSSangeeta Misra 	ip = &rd->r_stickymask;
384dbed73cbSSangeeta Misra 
385dbed73cbSSangeeta Misra 	(void) snprintf(buf, bufsize, "/%d", ilbadm_mask_to_prefixlen(ip));
386dbed73cbSSangeeta Misra 	return (B_TRUE);
387dbed73cbSSangeeta Misra }
388dbed73cbSSangeeta Misra 
389dbed73cbSSangeeta Misra static void
hcport_print(ilb_rule_data_t * rd,char * buf,uint_t bufsize)390dbed73cbSSangeeta Misra hcport_print(ilb_rule_data_t *rd, char *buf, uint_t bufsize)
391dbed73cbSSangeeta Misra {
392dbed73cbSSangeeta Misra 	if (rd->r_hcport != 0)
393dbed73cbSSangeeta Misra 		(void) snprintf(buf, bufsize, "%d", ntohs(rd->r_hcport));
394dbed73cbSSangeeta Misra 	else if (rd->r_hcpflag == ILB_HCI_PROBE_ANY)
395dbed73cbSSangeeta Misra 		(void) snprintf(buf, bufsize, "ANY");
396dbed73cbSSangeeta Misra 	else
397dbed73cbSSangeeta Misra 		buf[0] = '\0';
398dbed73cbSSangeeta Misra }
399dbed73cbSSangeeta Misra static boolean_t
of_rport(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)400dbed73cbSSangeeta Misra of_rport(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
401dbed73cbSSangeeta Misra {
402dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
403dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
404dbed73cbSSangeeta Misra 
405dbed73cbSSangeeta Misra 	if (of_arg->ofmt_id == OF_PORT)
406dbed73cbSSangeeta Misra 		return (of_port2str(rd->r_minport, rd->r_maxport, buf,
407dbed73cbSSangeeta Misra 		    bufsize));
408dbed73cbSSangeeta Misra 
409dbed73cbSSangeeta Misra 	/* only print a hcport if there's a hc name as well */
410dbed73cbSSangeeta Misra 	if (of_arg->ofmt_id == OF_HCPORT && rd->r_hcname[0] != '\0')
411dbed73cbSSangeeta Misra 		hcport_print(rd, buf, bufsize);
412dbed73cbSSangeeta Misra 
413dbed73cbSSangeeta Misra 	return (B_TRUE);
414dbed73cbSSangeeta Misra }
415dbed73cbSSangeeta Misra 
416dbed73cbSSangeeta Misra /* ARGSUSED */
417dbed73cbSSangeeta Misra static boolean_t
of_rstatus(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)418dbed73cbSSangeeta Misra of_rstatus(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
419dbed73cbSSangeeta Misra {
420dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
421dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
422dbed73cbSSangeeta Misra 
423dbed73cbSSangeeta Misra 	if ((rd->r_flags & ILB_FLAGS_RULE_ENABLED) == ILB_FLAGS_RULE_ENABLED)
424dbed73cbSSangeeta Misra 		buf[0] = 'E';
425dbed73cbSSangeeta Misra 	else
426dbed73cbSSangeeta Misra 		buf[0] = 'D';
427dbed73cbSSangeeta Misra 	buf[1] = '\0';
428dbed73cbSSangeeta Misra 	return (B_TRUE);
429dbed73cbSSangeeta Misra }
430dbed73cbSSangeeta Misra 
431dbed73cbSSangeeta Misra static boolean_t
of_algo(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)432dbed73cbSSangeeta Misra of_algo(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
433dbed73cbSSangeeta Misra {
434dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
435dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
436dbed73cbSSangeeta Misra 
437dbed73cbSSangeeta Misra 	if (algo2bare_str(rd->r_algo, buf, bufsize) == 0)
438dbed73cbSSangeeta Misra 		return (B_FALSE);
439dbed73cbSSangeeta Misra 	return (B_TRUE);
440dbed73cbSSangeeta Misra }
441dbed73cbSSangeeta Misra 
442dbed73cbSSangeeta Misra static boolean_t
of_topo(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)443dbed73cbSSangeeta Misra of_topo(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
444dbed73cbSSangeeta Misra {
445dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
446dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
447dbed73cbSSangeeta Misra 
448dbed73cbSSangeeta Misra 	if (topo2bare_str(rd->r_topo, buf, bufsize) == 0)
449dbed73cbSSangeeta Misra 		return (B_FALSE);
450dbed73cbSSangeeta Misra 	return (B_TRUE);
451dbed73cbSSangeeta Misra }
452dbed73cbSSangeeta Misra 
453dbed73cbSSangeeta Misra static boolean_t
of_time(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)454dbed73cbSSangeeta Misra of_time(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
455dbed73cbSSangeeta Misra {
456dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
457dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
458dbed73cbSSangeeta Misra 
459dbed73cbSSangeeta Misra 	switch (of_arg->ofmt_id) {
460dbed73cbSSangeeta Misra 	case OF_T_CONN:
461dbed73cbSSangeeta Misra 		(void) snprintf(buf, bufsize, "%u", rd->r_conndrain);
462dbed73cbSSangeeta Misra 		break;
463dbed73cbSSangeeta Misra 	case OF_T_NAT:
464dbed73cbSSangeeta Misra 		(void) snprintf(buf, bufsize, "%u", rd->r_nat_timeout);
465dbed73cbSSangeeta Misra 		break;
466dbed73cbSSangeeta Misra 	case OF_T_STICKY:
467dbed73cbSSangeeta Misra 		(void) snprintf(buf, bufsize, "%u", rd->r_sticky_timeout);
468dbed73cbSSangeeta Misra 		break;
469dbed73cbSSangeeta Misra 	}
470dbed73cbSSangeeta Misra 	return (B_TRUE);
471dbed73cbSSangeeta Misra }
472dbed73cbSSangeeta Misra 
473dbed73cbSSangeeta Misra typedef struct rl_showlist_arg {
474dbed73cbSSangeeta Misra 	char	*buf;
475dbed73cbSSangeeta Misra 	uint_t	bufsize;
476dbed73cbSSangeeta Misra } rl_showlist_arg_t;
477dbed73cbSSangeeta Misra 
478dbed73cbSSangeeta Misra /* ARGSUSED */
479dbed73cbSSangeeta Misra /* called by ilb_walk_servers(), cannot get rid of unused args */
480dbed73cbSSangeeta Misra static ilb_status_t
srv2srvID(ilb_handle_t h,ilb_server_data_t * sd,const char * sgname,void * arg)481dbed73cbSSangeeta Misra srv2srvID(ilb_handle_t h, ilb_server_data_t *sd, const char *sgname, void *arg)
482dbed73cbSSangeeta Misra {
483dbed73cbSSangeeta Misra 	rl_showlist_arg_t	*sla = (rl_showlist_arg_t *)arg;
484dbed73cbSSangeeta Misra 	int			len;
485dbed73cbSSangeeta Misra 
486dbed73cbSSangeeta Misra 	(void) snprintf(sla->buf, sla->bufsize, "%s,", sd->sd_srvID);
487dbed73cbSSangeeta Misra 	len = strlen(sd->sd_srvID) + 1;
488dbed73cbSSangeeta Misra 	sla->buf += len;
489dbed73cbSSangeeta Misra 	sla->bufsize -= len;
490dbed73cbSSangeeta Misra 
491dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
492dbed73cbSSangeeta Misra }
493dbed73cbSSangeeta Misra 
494dbed73cbSSangeeta Misra static boolean_t
of_rl_srvlist(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)495dbed73cbSSangeeta Misra of_rl_srvlist(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
496dbed73cbSSangeeta Misra {
497dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t *ra = (ilbadm_rl_list_arg_t *)of_arg->ofmt_cbarg;
498dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd = (ilb_rule_data_t *)ra->rd;
499dbed73cbSSangeeta Misra 	rl_showlist_arg_t	sla;
500dbed73cbSSangeeta Misra 
501dbed73cbSSangeeta Misra 	sla.buf = buf;
502dbed73cbSSangeeta Misra 	sla.bufsize = bufsize;
503dbed73cbSSangeeta Misra 
504dbed73cbSSangeeta Misra 	(void) ilb_walk_servers(ra->h, srv2srvID, rd->r_sgname,
505dbed73cbSSangeeta Misra 	    (void *)&sla);
506dbed73cbSSangeeta Misra 	/* we're trailing a ',' which we need to remove */
507dbed73cbSSangeeta Misra 	*--sla.buf = '\0';
508dbed73cbSSangeeta Misra 
509dbed73cbSSangeeta Misra 	return (B_TRUE);
510dbed73cbSSangeeta Misra }
511dbed73cbSSangeeta Misra 
512dbed73cbSSangeeta Misra #define	RMAXCOLS 120	/* enough? */
513dbed73cbSSangeeta Misra #define	SERVER_WIDTH	(ILB_NAMESZ+1)	/* 1st guess */
514dbed73cbSSangeeta Misra 
515dbed73cbSSangeeta Misra static boolean_t
of_port2str(in_port_t minport,in_port_t maxport,char * buf,uint_t bufsize)516dbed73cbSSangeeta Misra of_port2str(in_port_t minport, in_port_t maxport, char *buf, uint_t bufsize)
517dbed73cbSSangeeta Misra {
518dbed73cbSSangeeta Misra 	in_port_t	h_min, h_max;
519dbed73cbSSangeeta Misra 	int		len;
520dbed73cbSSangeeta Misra 
521dbed73cbSSangeeta Misra 	h_min = ntohs(minport);
522dbed73cbSSangeeta Misra 	h_max = ntohs(maxport);
523dbed73cbSSangeeta Misra 
524dbed73cbSSangeeta Misra 	if (h_min == 0)
525dbed73cbSSangeeta Misra 		return (B_FALSE); /* print "unspec" == "all ports" */
526dbed73cbSSangeeta Misra 
527dbed73cbSSangeeta Misra 	len = snprintf(buf, bufsize, "%d", h_min);
528dbed73cbSSangeeta Misra 	if (h_max > h_min)
529dbed73cbSSangeeta Misra 		(void) snprintf(buf + len, bufsize - len, "-%d", h_max);
530dbed73cbSSangeeta Misra 	return (B_TRUE);
531dbed73cbSSangeeta Misra }
532dbed73cbSSangeeta Misra 
533dbed73cbSSangeeta Misra static ilbadm_status_t
ip2hostname(ilb_ip_addr_t * ip,char * buf,uint_t bufsize)534dbed73cbSSangeeta Misra ip2hostname(ilb_ip_addr_t *ip, char *buf, uint_t bufsize)
535dbed73cbSSangeeta Misra {
536dbed73cbSSangeeta Misra 	int		ret;
537dbed73cbSSangeeta Misra 	struct hostent	*he;
538dbed73cbSSangeeta Misra 
539dbed73cbSSangeeta Misra 	switch (ip->ia_af) {
540dbed73cbSSangeeta Misra 	case AF_INET:
541dbed73cbSSangeeta Misra 		he = getipnodebyaddr((char *)&ip->ia_v4, sizeof (ip->ia_v4),
542dbed73cbSSangeeta Misra 		    ip->ia_af, &ret);
543dbed73cbSSangeeta Misra 		break;
544dbed73cbSSangeeta Misra 	case AF_INET6:
545dbed73cbSSangeeta Misra 		he = getipnodebyaddr((char *)&ip->ia_v6, sizeof (ip->ia_v6),
546dbed73cbSSangeeta Misra 		    ip->ia_af, &ret);
547dbed73cbSSangeeta Misra 		break;
548dbed73cbSSangeeta Misra 	default: return (ILBADM_INVAL_AF);
549dbed73cbSSangeeta Misra 	}
550dbed73cbSSangeeta Misra 
551dbed73cbSSangeeta Misra 	/* if we can't resolve this, just return an empty name */
552dbed73cbSSangeeta Misra 	if (he == NULL)
553dbed73cbSSangeeta Misra 		buf[0] = '\0';
554dbed73cbSSangeeta Misra 	else
555dbed73cbSSangeeta Misra 		(void) strlcpy(buf, he->h_name, bufsize);
556dbed73cbSSangeeta Misra 
557dbed73cbSSangeeta Misra 	return (ILBADM_OK);
558dbed73cbSSangeeta Misra }
559dbed73cbSSangeeta Misra 
560dbed73cbSSangeeta Misra /* ARGSUSED */
561dbed73cbSSangeeta Misra /*
562dbed73cbSSangeeta Misra  * Since this function is used by libilb routine ilb_walk_rules()
563dbed73cbSSangeeta Misra  * it must return libilb errors
564dbed73cbSSangeeta Misra  */
565dbed73cbSSangeeta Misra static ilb_status_t
ilbadm_show_onerule(ilb_handle_t h,ilb_rule_data_t * rd,void * arg)566dbed73cbSSangeeta Misra ilbadm_show_onerule(ilb_handle_t h, ilb_rule_data_t *rd, void *arg)
567dbed73cbSSangeeta Misra {
568dbed73cbSSangeeta Misra 	ilbadm_sh_rl_arg_t	*larg = (ilbadm_sh_rl_arg_t *)arg;
569dbed73cbSSangeeta Misra 	ofmt_status_t	oerr;
570dbed73cbSSangeeta Misra 	int		oflags = 0;
571dbed73cbSSangeeta Misra 	int		ocols = RMAXCOLS;
572dbed73cbSSangeeta Misra 	ilbadm_rl_list_arg_t	ra;
573dbed73cbSSangeeta Misra 	static ofmt_handle_t	oh = (ofmt_handle_t)NULL;
574dbed73cbSSangeeta Misra 	ofmt_field_t	*fields;
575dbed73cbSSangeeta Misra 	boolean_t	r_enabled = rd->r_flags & ILB_FLAGS_RULE_ENABLED;
576dbed73cbSSangeeta Misra 
577dbed73cbSSangeeta Misra 	if (larg->o_str == NULL) {
578dbed73cbSSangeeta Misra 		ilbadm_err(gettext("internal error"));
579dbed73cbSSangeeta Misra 		return (ILB_STATUS_GENERIC);
580dbed73cbSSangeeta Misra 	}
581dbed73cbSSangeeta Misra 
582dbed73cbSSangeeta Misra 	/*
583dbed73cbSSangeeta Misra 	 * only print rules (enabled/dis-) we're asked to
584dbed73cbSSangeeta Misra 	 * note: both LIST_**ABLED flags can be set at the same time,
585dbed73cbSSangeeta Misra 	 * whereas a rule has one state only. therefore the complicated
586dbed73cbSSangeeta Misra 	 * statement.
587dbed73cbSSangeeta Misra 	 */
588dbed73cbSSangeeta Misra 	if (!((r_enabled && (larg->flags & ILBADM_LIST_ENABLED)) ||
589dbed73cbSSangeeta Misra 	    (!r_enabled && (larg->flags & ILBADM_LIST_DISABLED))))
590dbed73cbSSangeeta Misra 		return (ILB_STATUS_OK);
591dbed73cbSSangeeta Misra 
592dbed73cbSSangeeta Misra 	if (larg->flags & ILBADM_LIST_PARSE)
593dbed73cbSSangeeta Misra 		oflags |= OFMT_PARSABLE;
594dbed73cbSSangeeta Misra 
595dbed73cbSSangeeta Misra 	if (larg->flags & ILBADM_LIST_FULL)
596dbed73cbSSangeeta Misra 		oflags |= OFMT_MULTILINE;
597dbed73cbSSangeeta Misra 
598dbed73cbSSangeeta Misra 	bzero(&ra, sizeof (ra));
599dbed73cbSSangeeta Misra 	ra.rd = rd;
600dbed73cbSSangeeta Misra 	ra.h = h;
601dbed73cbSSangeeta Misra 
602dbed73cbSSangeeta Misra 	if (oh == NULL) {
603dbed73cbSSangeeta Misra 		if (rd->r_vip.ia_af == AF_INET)
604dbed73cbSSangeeta Misra 			fields = rfields_v4;
605dbed73cbSSangeeta Misra 		else
606dbed73cbSSangeeta Misra 			fields = rfields_v6;
607dbed73cbSSangeeta Misra 
608dbed73cbSSangeeta Misra 		oerr = ofmt_open(larg->o_str, fields, oflags, ocols, &oh);
609dbed73cbSSangeeta Misra 		if (oerr != OFMT_SUCCESS) {
610dbed73cbSSangeeta Misra 			char	e[80];
611dbed73cbSSangeeta Misra 
612dbed73cbSSangeeta Misra 			ilbadm_err(gettext("ofmt_open failed: %s"),
613dbed73cbSSangeeta Misra 			    ofmt_strerror(oh, oerr, e, sizeof (e)));
614dbed73cbSSangeeta Misra 			return (ILB_STATUS_GENERIC);
615dbed73cbSSangeeta Misra 		}
616dbed73cbSSangeeta Misra 	}
617dbed73cbSSangeeta Misra 
618dbed73cbSSangeeta Misra 	ofmt_print(oh, &ra);
619dbed73cbSSangeeta Misra 
620dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
621dbed73cbSSangeeta Misra }
622dbed73cbSSangeeta Misra 
623dbed73cbSSangeeta Misra static char *full_list_rule_hdrs =
624dbed73cbSSangeeta Misra 	"RULENAME,STATUS,PORT,PROTOCOL,LBALG,TYPE,PROXY-SRC,PMASK,"
625dbed73cbSSangeeta Misra 	"HC-NAME,HC-PORT,CONN-DRAIN,NAT-TIMEOUT,"
626dbed73cbSSangeeta Misra 	"PERSIST-TIMEOUT,SERVERGROUP,VIP,SERVERS";
627dbed73cbSSangeeta Misra static char *def_list_rule_hdrs =
628dbed73cbSSangeeta Misra 	"RULENAME,STATUS,LBALG,TYPE,PROTOCOL,VIP,PORT";
629dbed73cbSSangeeta Misra 
630dbed73cbSSangeeta Misra /* ARGSUSED */
631dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_show_rules(int argc,char * argv[])632dbed73cbSSangeeta Misra ilbadm_show_rules(int argc, char *argv[])
633dbed73cbSSangeeta Misra {
634dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
635dbed73cbSSangeeta Misra 	int		c;
636dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
637dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
638dbed73cbSSangeeta Misra 	boolean_t	o_opt = B_FALSE, p_opt = B_FALSE;
639dbed73cbSSangeeta Misra 	boolean_t	f_opt = B_FALSE;
640dbed73cbSSangeeta Misra 	ilbadm_sh_rl_arg_t	larg = {0, NULL, NULL, NULL};
641dbed73cbSSangeeta Misra 
642dbed73cbSSangeeta Misra 	larg.flags = ILBADM_LIST_ENABLED | ILBADM_LIST_DISABLED;
643dbed73cbSSangeeta Misra 	while ((c = getopt(argc, argv, ":fpedo:")) != -1) {
644dbed73cbSSangeeta Misra 		switch ((char)c) {
645dbed73cbSSangeeta Misra 		case 'f': larg.flags |= ILBADM_LIST_FULL;
646dbed73cbSSangeeta Misra 			larg.o_str = full_list_rule_hdrs;
647dbed73cbSSangeeta Misra 			f_opt = B_TRUE;
648dbed73cbSSangeeta Misra 			break;
649dbed73cbSSangeeta Misra 		case 'p': larg.flags |= ILBADM_LIST_PARSE;
650dbed73cbSSangeeta Misra 			p_opt = B_TRUE;
651dbed73cbSSangeeta Misra 			break;
652dbed73cbSSangeeta Misra 		case 'o': larg.o_str = optarg;
653dbed73cbSSangeeta Misra 			o_opt = B_TRUE;
654dbed73cbSSangeeta Misra 			break;
655dbed73cbSSangeeta Misra 		/* -e and -d may be repeated - make sure the last one wins */
656dbed73cbSSangeeta Misra 		case 'e': larg.flags &= ILBADM_LIST_NODISABLED;
657dbed73cbSSangeeta Misra 			larg.flags |= ILBADM_LIST_ENABLED;
658dbed73cbSSangeeta Misra 			break;
659dbed73cbSSangeeta Misra 		case 'd': larg.flags &= ILBADM_LIST_NOENABLED;
660dbed73cbSSangeeta Misra 			larg.flags |= ILBADM_LIST_DISABLED;
661dbed73cbSSangeeta Misra 			break;
662dbed73cbSSangeeta Misra 		case ':': ilbadm_err(gettext("missing option argument for %c"),
663dbed73cbSSangeeta Misra 			    (char)optopt);
664dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
665dbed73cbSSangeeta Misra 			goto out;
666dbed73cbSSangeeta Misra 		case '?':
667dbed73cbSSangeeta Misra 		default:
668dbed73cbSSangeeta Misra 			unknown_opt(argv, optind-1);
669dbed73cbSSangeeta Misra 			/* not reached */
670dbed73cbSSangeeta Misra 			break;
671dbed73cbSSangeeta Misra 		}
672dbed73cbSSangeeta Misra 	}
673dbed73cbSSangeeta Misra 
674dbed73cbSSangeeta Misra 	if (f_opt && o_opt) {
675dbed73cbSSangeeta Misra 		ilbadm_err(gettext("options -o and -f are mutually"
676dbed73cbSSangeeta Misra 		    " exclusive"));
677dbed73cbSSangeeta Misra 		exit(1);
678dbed73cbSSangeeta Misra 	}
679dbed73cbSSangeeta Misra 
680dbed73cbSSangeeta Misra 	if (p_opt && !o_opt) {
681dbed73cbSSangeeta Misra 		ilbadm_err(gettext("option -p requires -o"));
682dbed73cbSSangeeta Misra 		exit(1);
683dbed73cbSSangeeta Misra 	}
684dbed73cbSSangeeta Misra 
685dbed73cbSSangeeta Misra 	if (p_opt && larg.o_str != NULL &&
686dbed73cbSSangeeta Misra 	    (strcasecmp(larg.o_str, "all") == 0)) {
687dbed73cbSSangeeta Misra 		ilbadm_err(gettext("option -p requires explicit field"
688dbed73cbSSangeeta Misra 		    " names for -o"));
689dbed73cbSSangeeta Misra 		exit(1);
690dbed73cbSSangeeta Misra 	}
691dbed73cbSSangeeta Misra 
692dbed73cbSSangeeta Misra 	/* no -o option, so we use std. fields */
693dbed73cbSSangeeta Misra 	if (!o_opt && !f_opt)
694dbed73cbSSangeeta Misra 		larg.o_str = def_list_rule_hdrs;
695dbed73cbSSangeeta Misra 
696dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
697dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
698dbed73cbSSangeeta Misra 		goto out;
699dbed73cbSSangeeta Misra 
700dbed73cbSSangeeta Misra 	if (optind >= argc) {
701dbed73cbSSangeeta Misra 		rclib = ilb_walk_rules(h, ilbadm_show_onerule, NULL,
702dbed73cbSSangeeta Misra 		    (void*)&larg);
703dbed73cbSSangeeta Misra 	} else {
704dbed73cbSSangeeta Misra 		while (optind < argc) {
705dbed73cbSSangeeta Misra 			rclib = ilb_walk_rules(h, ilbadm_show_onerule,
706dbed73cbSSangeeta Misra 			    argv[optind++], (void*)&larg);
707dbed73cbSSangeeta Misra 			if (rclib != ILB_STATUS_OK)
708dbed73cbSSangeeta Misra 				break;
709dbed73cbSSangeeta Misra 		}
710dbed73cbSSangeeta Misra 	}
711dbed73cbSSangeeta Misra out:
712dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
713dbed73cbSSangeeta Misra 		(void) ilb_close(h);
714dbed73cbSSangeeta Misra 
715dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
716dbed73cbSSangeeta Misra 		/*
717dbed73cbSSangeeta Misra 		 * The show function returns ILB_STATUS_GENERIC after printing
718dbed73cbSSangeeta Misra 		 * out an error message.  So we don't need to print it again.
719dbed73cbSSangeeta Misra 		 */
720dbed73cbSSangeeta Misra 		if (rclib != ILB_STATUS_GENERIC)
721dbed73cbSSangeeta Misra 			ilbadm_err(ilb_errstr(rclib));
722dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
723dbed73cbSSangeeta Misra 	}
724dbed73cbSSangeeta Misra 	return (rc);
725dbed73cbSSangeeta Misra }
726dbed73cbSSangeeta Misra 
727dbed73cbSSangeeta Misra static boolean_t
of_srv2str(ofmt_arg_t * of_arg,char * buf,uint_t bufsize)728dbed73cbSSangeeta Misra of_srv2str(ofmt_arg_t *of_arg, char *buf, uint_t bufsize)
729dbed73cbSSangeeta Misra {
730dbed73cbSSangeeta Misra 	ilbadm_rl_srvlist_arg_t  *larg =
731dbed73cbSSangeeta Misra 	    (ilbadm_rl_srvlist_arg_t *)of_arg->ofmt_cbarg;
732dbed73cbSSangeeta Misra 	ilb_server_data_t	*sd = larg->sd;
733dbed73cbSSangeeta Misra 	uint_t		op = of_arg->ofmt_id;
734dbed73cbSSangeeta Misra 	boolean_t	ret = B_TRUE;
735dbed73cbSSangeeta Misra 	ilbadm_status_t	rc;
736dbed73cbSSangeeta Misra 
737dbed73cbSSangeeta Misra 	if (sd == NULL)
738dbed73cbSSangeeta Misra 		return (B_FALSE);
739dbed73cbSSangeeta Misra 
740dbed73cbSSangeeta Misra 	switch (op) {
741dbed73cbSSangeeta Misra 	case OF_SRV_ID:
742dbed73cbSSangeeta Misra 		(void) strlcpy(buf, sd->sd_srvID, bufsize);
743dbed73cbSSangeeta Misra 		break;
744dbed73cbSSangeeta Misra 	case OF_SRV_STATUS:
745dbed73cbSSangeeta Misra 		if (ILB_IS_SRV_ENABLED(sd->sd_flags))
746dbed73cbSSangeeta Misra 			buf[0] = 'E';
747dbed73cbSSangeeta Misra 		else
748dbed73cbSSangeeta Misra 			buf[0] = 'D';
749dbed73cbSSangeeta Misra 		buf[1] = '\0';
750dbed73cbSSangeeta Misra 		break;
751dbed73cbSSangeeta Misra 	case OF_SRV_RNAME:
752dbed73cbSSangeeta Misra 		(void) strlcpy(buf, larg->rd->r_name, bufsize);
753dbed73cbSSangeeta Misra 		break;
754dbed73cbSSangeeta Misra 	case OF_SRV_SGNAME:
755dbed73cbSSangeeta Misra 		(void) strlcpy(buf, larg->sgname, bufsize);
756dbed73cbSSangeeta Misra 		break;
757dbed73cbSSangeeta Misra 	case OF_SRV_HOSTNAME:
758dbed73cbSSangeeta Misra 		rc = ip2hostname(&sd->sd_addr, buf, bufsize);
759dbed73cbSSangeeta Misra 		if (rc != ILBADM_OK) {
760dbed73cbSSangeeta Misra 			buf[0] = '\0';
761dbed73cbSSangeeta Misra 			ret = B_FALSE;
762dbed73cbSSangeeta Misra 		}
763dbed73cbSSangeeta Misra 		break;
764dbed73cbSSangeeta Misra 	case OF_SRV_PORT:
765dbed73cbSSangeeta Misra 		ret = of_port2str(sd->sd_minport, sd->sd_maxport,
766dbed73cbSSangeeta Misra 		    buf, bufsize);
767dbed73cbSSangeeta Misra 		break;
768dbed73cbSSangeeta Misra 	case OF_SRV_ADDR:
769dbed73cbSSangeeta Misra 		ip2str(&sd->sd_addr, buf, bufsize, V6_ADDRONLY);
770dbed73cbSSangeeta Misra 		break;
771dbed73cbSSangeeta Misra 	}
772dbed73cbSSangeeta Misra 
773dbed73cbSSangeeta Misra 	return (ret);
774dbed73cbSSangeeta Misra }
775dbed73cbSSangeeta Misra 
776dbed73cbSSangeeta Misra /* ARGSUSED */
777dbed73cbSSangeeta Misra static ilb_status_t
i_show_rl_srv(ilb_handle_t h,ilb_server_data_t * sd,const char * sgname,void * arg)778dbed73cbSSangeeta Misra i_show_rl_srv(ilb_handle_t h, ilb_server_data_t *sd, const char *sgname,
779dbed73cbSSangeeta Misra     void *arg)
780dbed73cbSSangeeta Misra {
781dbed73cbSSangeeta Misra 	ilbadm_rl_srvlist_arg_t	*larg = (ilbadm_rl_srvlist_arg_t *)arg;
782dbed73cbSSangeeta Misra 
783dbed73cbSSangeeta Misra 	larg->sd = sd;
784dbed73cbSSangeeta Misra 	ofmt_print(larg->oh, larg);
785dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
786dbed73cbSSangeeta Misra }
787dbed73cbSSangeeta Misra 
788dbed73cbSSangeeta Misra /* ARGSUSED */
789dbed73cbSSangeeta Misra /*
790dbed73cbSSangeeta Misra  * Since this function is used by libilb routine ilb_walk_rules()
791dbed73cbSSangeeta Misra  * it must return libilb errors
792dbed73cbSSangeeta Misra  */
793dbed73cbSSangeeta Misra ilb_status_t
ilbadm_show_rl_servers(ilb_handle_t h,ilb_rule_data_t * rd,void * arg)794dbed73cbSSangeeta Misra ilbadm_show_rl_servers(ilb_handle_t h, ilb_rule_data_t *rd, void *arg)
795dbed73cbSSangeeta Misra {
796dbed73cbSSangeeta Misra 	ofmt_status_t	oerr;
797dbed73cbSSangeeta Misra 	int		oflags = 0;
798dbed73cbSSangeeta Misra 	int		ocols = RMAXCOLS;
799dbed73cbSSangeeta Misra 	ofmt_field_t	*fields;
800dbed73cbSSangeeta Misra 	static ofmt_handle_t	oh = (ofmt_handle_t)NULL;
801dbed73cbSSangeeta Misra 	ilbadm_rl_srvlist_arg_t	*larg = (ilbadm_rl_srvlist_arg_t *)arg;
802dbed73cbSSangeeta Misra 
803dbed73cbSSangeeta Misra 	/*
804dbed73cbSSangeeta Misra 	 * in full mode, we currently re-open ofmt() for every rule; we use
805dbed73cbSSangeeta Misra 	 * a variable number of lines, as we print one for every server
806dbed73cbSSangeeta Misra 	 * attached to a rule.
807dbed73cbSSangeeta Misra 	 */
808dbed73cbSSangeeta Misra 	if (larg->o_str == NULL) {
809dbed73cbSSangeeta Misra 		ilbadm_err(gettext("internal error"));
810dbed73cbSSangeeta Misra 		return (ILB_STATUS_GENERIC);
811dbed73cbSSangeeta Misra 	}
812dbed73cbSSangeeta Misra 
813dbed73cbSSangeeta Misra 	if (larg->flags & ILBADM_LIST_PARSE)
814dbed73cbSSangeeta Misra 		oflags |= OFMT_PARSABLE;
815dbed73cbSSangeeta Misra 
816dbed73cbSSangeeta Misra 	if (rd->r_vip.ia_af == AF_INET)
817dbed73cbSSangeeta Misra 		fields = ssfields_v4;
818dbed73cbSSangeeta Misra 	else
819dbed73cbSSangeeta Misra 		fields = ssfields_v6;
820dbed73cbSSangeeta Misra 
821dbed73cbSSangeeta Misra 	if (oh == NULL) {
822dbed73cbSSangeeta Misra 		oerr = ofmt_open(larg->o_str, fields, oflags, ocols, &oh);
823dbed73cbSSangeeta Misra 		if (oerr != OFMT_SUCCESS) {
824dbed73cbSSangeeta Misra 			char	e[80];
825dbed73cbSSangeeta Misra 
826dbed73cbSSangeeta Misra 			ilbadm_err(gettext("ofmt_open failed: %s"),
827dbed73cbSSangeeta Misra 			    ofmt_strerror(oh, oerr, e, sizeof (e)));
828dbed73cbSSangeeta Misra 			return (ILB_STATUS_GENERIC);
829dbed73cbSSangeeta Misra 		}
830dbed73cbSSangeeta Misra 		larg->oh = oh;
831dbed73cbSSangeeta Misra 	}
832dbed73cbSSangeeta Misra 
833dbed73cbSSangeeta Misra 	larg->rd = rd;
834dbed73cbSSangeeta Misra 	larg->sgname = rd->r_sgname;
835dbed73cbSSangeeta Misra 
836dbed73cbSSangeeta Misra 	return (ilb_walk_servers(h, i_show_rl_srv, rd->r_sgname, (void *)larg));
837dbed73cbSSangeeta Misra }
838dbed73cbSSangeeta Misra 
839dbed73cbSSangeeta Misra static char *def_show_srv_hdrs =
840dbed73cbSSangeeta Misra 	"SERVERID,ADDRESS,PORT,RULENAME,STATUS,SERVERGROUP";
841dbed73cbSSangeeta Misra 
842dbed73cbSSangeeta Misra /* ARGSUSED */
843dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_show_server(int argc,char * argv[])844dbed73cbSSangeeta Misra ilbadm_show_server(int argc, char *argv[])
845dbed73cbSSangeeta Misra {
846dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
847dbed73cbSSangeeta Misra 	int		c;
848dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
849dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
850dbed73cbSSangeeta Misra 	boolean_t	o_opt = B_FALSE, p_opt = B_FALSE;
851dbed73cbSSangeeta Misra 	ilbadm_rl_srvlist_arg_t	larg;
852dbed73cbSSangeeta Misra 
853dbed73cbSSangeeta Misra 	bzero(&larg, sizeof (larg));
854dbed73cbSSangeeta Misra 	while ((c = getopt(argc, argv, ":po:")) != -1) {
855dbed73cbSSangeeta Misra 		switch ((char)c) {
856dbed73cbSSangeeta Misra 		case 'p': larg.flags |= ILBADM_LIST_PARSE;
857dbed73cbSSangeeta Misra 			p_opt = B_TRUE;
858dbed73cbSSangeeta Misra 			break;
859dbed73cbSSangeeta Misra 		case 'o': larg.o_str = optarg;
860dbed73cbSSangeeta Misra 			o_opt = B_TRUE;
861dbed73cbSSangeeta Misra 			break;
862dbed73cbSSangeeta Misra 		case ':': ilbadm_err(gettext("missing option argument for %c"),
863dbed73cbSSangeeta Misra 			    (char)optopt);
864dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
865dbed73cbSSangeeta Misra 			goto out;
866dbed73cbSSangeeta Misra 		case '?':
867dbed73cbSSangeeta Misra 		default:
868dbed73cbSSangeeta Misra 			unknown_opt(argv, optind-1);
869dbed73cbSSangeeta Misra 			/* not reached */
870dbed73cbSSangeeta Misra 			break;
871dbed73cbSSangeeta Misra 		}
872dbed73cbSSangeeta Misra 	}
873dbed73cbSSangeeta Misra 
874dbed73cbSSangeeta Misra 	if (p_opt && !o_opt) {
875dbed73cbSSangeeta Misra 		ilbadm_err(gettext("option -p requires -o"));
876dbed73cbSSangeeta Misra 		exit(1);
877dbed73cbSSangeeta Misra 	}
878dbed73cbSSangeeta Misra 
879dbed73cbSSangeeta Misra 	if (p_opt && larg.o_str != NULL &&
880dbed73cbSSangeeta Misra 	    (strcasecmp(larg.o_str, "all") == 0)) {
881dbed73cbSSangeeta Misra 		ilbadm_err(gettext("option -p requires explicit"
882dbed73cbSSangeeta Misra 		    "  field names for -o"));
883dbed73cbSSangeeta Misra 		exit(1);
884dbed73cbSSangeeta Misra 	}
885dbed73cbSSangeeta Misra 
886dbed73cbSSangeeta Misra 	/* no -o option, so we use default fields */
887dbed73cbSSangeeta Misra 	if (!o_opt)
888dbed73cbSSangeeta Misra 		larg.o_str = def_show_srv_hdrs;
889dbed73cbSSangeeta Misra 
890dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
891dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
892dbed73cbSSangeeta Misra 		goto out;
893dbed73cbSSangeeta Misra 
894dbed73cbSSangeeta Misra 	if (optind >= argc) {
895dbed73cbSSangeeta Misra 		rclib = ilb_walk_rules(h, ilbadm_show_rl_servers, NULL,
896dbed73cbSSangeeta Misra 		    (void*)&larg);
897dbed73cbSSangeeta Misra 	} else {
898dbed73cbSSangeeta Misra 		while (optind < argc) {
899dbed73cbSSangeeta Misra 			rclib = ilb_walk_rules(h, ilbadm_show_rl_servers,
900dbed73cbSSangeeta Misra 			    argv[optind++], (void*)&larg);
901dbed73cbSSangeeta Misra 			if (rclib != ILB_STATUS_OK)
902dbed73cbSSangeeta Misra 				break;
903dbed73cbSSangeeta Misra 		}
904dbed73cbSSangeeta Misra 	}
905dbed73cbSSangeeta Misra out:
906dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
907dbed73cbSSangeeta Misra 		(void) ilb_close(h);
908dbed73cbSSangeeta Misra 
909dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
910dbed73cbSSangeeta Misra 		/*
911dbed73cbSSangeeta Misra 		 * The show function returns ILB_STATUS_GENERIC after printing
912dbed73cbSSangeeta Misra 		 * out an error message.  So we don't need to print it again.
913dbed73cbSSangeeta Misra 		 */
914dbed73cbSSangeeta Misra 		if (rclib != ILB_STATUS_GENERIC)
915dbed73cbSSangeeta Misra 			ilbadm_err(ilb_errstr(rclib));
916dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
917dbed73cbSSangeeta Misra 	}
918dbed73cbSSangeeta Misra 	return (rc);
919dbed73cbSSangeeta Misra }
920dbed73cbSSangeeta Misra 
921dbed73cbSSangeeta Misra static ilbadm_status_t
i_parse_rl_arg(char * arg,ilb_rule_data_t * rd,ilbadm_key_name_t * keylist)922dbed73cbSSangeeta Misra i_parse_rl_arg(char *arg, ilb_rule_data_t *rd, ilbadm_key_name_t *keylist)
923dbed73cbSSangeeta Misra {
924dbed73cbSSangeeta Misra 	ilbadm_status_t	rc;
925dbed73cbSSangeeta Misra 
926dbed73cbSSangeeta Misra 	rc = i_parse_optstring(arg, (void *) rd, keylist,
927dbed73cbSSangeeta Misra 	    OPT_PORTS, NULL);
928dbed73cbSSangeeta Misra 	return (rc);
929dbed73cbSSangeeta Misra }
930dbed73cbSSangeeta Misra 
931dbed73cbSSangeeta Misra static void
i_ilbadm_alloc_rule(ilb_rule_data_t ** rdp)932dbed73cbSSangeeta Misra i_ilbadm_alloc_rule(ilb_rule_data_t **rdp)
933dbed73cbSSangeeta Misra {
934dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd;
935dbed73cbSSangeeta Misra 
936dbed73cbSSangeeta Misra 	*rdp = rd = (ilb_rule_data_t *)calloc(sizeof (*rd), 1);
937dbed73cbSSangeeta Misra 	if (rd == NULL)
938dbed73cbSSangeeta Misra 		return;
939dbed73cbSSangeeta Misra 	rd->r_proto = IPPROTO_TCP;
940dbed73cbSSangeeta Misra }
941dbed73cbSSangeeta Misra 
942dbed73cbSSangeeta Misra static void
i_ilbadm_free_rule(ilb_rule_data_t * rd)943dbed73cbSSangeeta Misra i_ilbadm_free_rule(ilb_rule_data_t *rd)
944dbed73cbSSangeeta Misra {
945dbed73cbSSangeeta Misra 	free(rd);
946dbed73cbSSangeeta Misra }
947dbed73cbSSangeeta Misra 
948dbed73cbSSangeeta Misra /* ARGSUSED */
949dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_destroy_rule(int argc,char * argv[])950dbed73cbSSangeeta Misra ilbadm_destroy_rule(int argc, char *argv[])
951dbed73cbSSangeeta Misra {
952dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
953dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
954dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
955dbed73cbSSangeeta Misra 	boolean_t	all_rules = B_FALSE;
956dbed73cbSSangeeta Misra 	int		c, i;
957dbed73cbSSangeeta Misra 
958dbed73cbSSangeeta Misra 	while ((c = getopt(argc, argv, ":a")) != -1) {
959dbed73cbSSangeeta Misra 		switch ((char)c) {
960dbed73cbSSangeeta Misra 		case 'a':
961dbed73cbSSangeeta Misra 			all_rules = B_TRUE;
962dbed73cbSSangeeta Misra 			break;
963dbed73cbSSangeeta Misra 		case '?':
964dbed73cbSSangeeta Misra 		default:
965dbed73cbSSangeeta Misra 			unknown_opt(argv, optind-1);
966dbed73cbSSangeeta Misra 			/* not reached */
967dbed73cbSSangeeta Misra 			break;
968dbed73cbSSangeeta Misra 		}
969dbed73cbSSangeeta Misra 	}
970dbed73cbSSangeeta Misra 
971dbed73cbSSangeeta Misra 	if (optind >= argc && !all_rules) {
972dbed73cbSSangeeta Misra 		ilbadm_err(gettext("usage: delete-rule -a | name"));
973dbed73cbSSangeeta Misra 		return (ILBADM_LIBERR);
974dbed73cbSSangeeta Misra 	}
975dbed73cbSSangeeta Misra 
976dbed73cbSSangeeta Misra 	/* either "-a" or rulename, not both */
977dbed73cbSSangeeta Misra 	if (optind < argc && all_rules) {
978dbed73cbSSangeeta Misra 		rc = ILBADM_INVAL_ARGS;
979dbed73cbSSangeeta Misra 		goto out;
980dbed73cbSSangeeta Misra 	}
981dbed73cbSSangeeta Misra 
982dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
983dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
984dbed73cbSSangeeta Misra 		goto out;
985dbed73cbSSangeeta Misra 
986dbed73cbSSangeeta Misra 	if (all_rules) {
987dbed73cbSSangeeta Misra 		rclib = ilb_destroy_rule(h, NULL);
988dbed73cbSSangeeta Misra 		goto out;
989dbed73cbSSangeeta Misra 	}
990dbed73cbSSangeeta Misra 
991dbed73cbSSangeeta Misra 	for (i = optind; i < argc && rclib == ILB_STATUS_OK; i++)
992dbed73cbSSangeeta Misra 		rclib = ilb_destroy_rule(h, argv[i]);
993dbed73cbSSangeeta Misra 
994dbed73cbSSangeeta Misra out:
995dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
996dbed73cbSSangeeta Misra 		(void) ilb_close(h);
997dbed73cbSSangeeta Misra 
998dbed73cbSSangeeta Misra 	/* This prints the specific errors */
999dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
1000dbed73cbSSangeeta Misra 		ilbadm_err(ilb_errstr(rclib));
1001dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
1002dbed73cbSSangeeta Misra 	}
1003dbed73cbSSangeeta Misra 	/* This prints the generic errors */
1004dbed73cbSSangeeta Misra 	if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR))
1005dbed73cbSSangeeta Misra 		ilbadm_err(ilbadm_errstr(rc));
1006dbed73cbSSangeeta Misra 	return (rc);
1007dbed73cbSSangeeta Misra }
1008dbed73cbSSangeeta Misra 
1009dbed73cbSSangeeta Misra /* ARGSUSED */
1010dbed73cbSSangeeta Misra static ilbadm_status_t
ilbadm_Xable_rule(int argc,char * argv[],ilbadm_cmd_t cmd)1011dbed73cbSSangeeta Misra ilbadm_Xable_rule(int argc, char *argv[], ilbadm_cmd_t cmd)
1012dbed73cbSSangeeta Misra {
1013dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
1014dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
1015dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
1016dbed73cbSSangeeta Misra 	int		i;
1017dbed73cbSSangeeta Misra 
1018dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
1019dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
1020dbed73cbSSangeeta Misra 		goto out;
1021dbed73cbSSangeeta Misra 	/*
1022dbed73cbSSangeeta Misra 	 * by default, en/disable-rule mean "all", and not using
1023dbed73cbSSangeeta Misra 	 * a rule name will cause this behaviour to kick in
1024dbed73cbSSangeeta Misra 	 */
1025dbed73cbSSangeeta Misra 	if (argc < 2) {
1026dbed73cbSSangeeta Misra 		if (cmd == cmd_enable_rule)
1027dbed73cbSSangeeta Misra 			rclib = ilb_enable_rule(h, NULL);
1028dbed73cbSSangeeta Misra 		else
1029dbed73cbSSangeeta Misra 			rclib = ilb_disable_rule(h, NULL);
1030dbed73cbSSangeeta Misra 	} else {
1031dbed73cbSSangeeta Misra 
1032dbed73cbSSangeeta Misra 		for (i = optind; i < argc && rc == ILBADM_OK; i++) {
1033dbed73cbSSangeeta Misra 			if (cmd == cmd_enable_rule)
1034dbed73cbSSangeeta Misra 				rclib = ilb_enable_rule(h, argv[i]);
1035dbed73cbSSangeeta Misra 			else
1036dbed73cbSSangeeta Misra 				rclib = ilb_disable_rule(h, argv[i]);
1037dbed73cbSSangeeta Misra 		}
1038dbed73cbSSangeeta Misra 	}
1039dbed73cbSSangeeta Misra out:
1040dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
1041dbed73cbSSangeeta Misra 		(void) ilb_close(h);
1042dbed73cbSSangeeta Misra 
1043dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
1044dbed73cbSSangeeta Misra 		ilbadm_err(ilb_errstr(rclib));
1045dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
1046dbed73cbSSangeeta Misra 	}
1047dbed73cbSSangeeta Misra 	return (rc);
1048dbed73cbSSangeeta Misra }
1049dbed73cbSSangeeta Misra 
1050dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_enable_rule(int argc,char * argv[])1051dbed73cbSSangeeta Misra ilbadm_enable_rule(int argc, char *argv[])
1052dbed73cbSSangeeta Misra {
1053dbed73cbSSangeeta Misra 
1054dbed73cbSSangeeta Misra 	return (ilbadm_Xable_rule(argc, argv, cmd_enable_rule));
1055dbed73cbSSangeeta Misra }
1056dbed73cbSSangeeta Misra 
1057dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_disable_rule(int argc,char * argv[])1058dbed73cbSSangeeta Misra ilbadm_disable_rule(int argc, char *argv[])
1059dbed73cbSSangeeta Misra {
1060dbed73cbSSangeeta Misra 	return (ilbadm_Xable_rule(argc, argv, cmd_disable_rule));
1061dbed73cbSSangeeta Misra }
1062dbed73cbSSangeeta Misra 
1063dbed73cbSSangeeta Misra /*
1064dbed73cbSSangeeta Misra  * parse and create a rule
1065dbed73cbSSangeeta Misra  */
1066dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_create_rule(int argc,char * argv[])1067dbed73cbSSangeeta Misra ilbadm_create_rule(int argc, char *argv[])
1068dbed73cbSSangeeta Misra {
1069dbed73cbSSangeeta Misra 	ilb_handle_t	h = ILB_INVALID_HANDLE;
1070dbed73cbSSangeeta Misra 	int		c;
1071dbed73cbSSangeeta Misra 	ilb_status_t	rclib = ILB_STATUS_OK;
1072dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
1073dbed73cbSSangeeta Misra 	ilb_rule_data_t	*rd;
1074dbed73cbSSangeeta Misra 	boolean_t	p_opt = B_FALSE;
1075dbed73cbSSangeeta Misra 
1076dbed73cbSSangeeta Misra 	i_ilbadm_alloc_rule(&rd);
1077dbed73cbSSangeeta Misra 
1078dbed73cbSSangeeta Misra 	while ((c = getopt(argc, argv, ":ei:m:o:t:h:p")) != -1) {
1079dbed73cbSSangeeta Misra 		switch ((char)c) {
1080dbed73cbSSangeeta Misra 		case 'e':
1081dbed73cbSSangeeta Misra 			rd->r_flags |= ILB_FLAGS_RULE_ENABLED;
1082dbed73cbSSangeeta Misra 			break;
1083dbed73cbSSangeeta Misra 		case 'h':
1084dbed73cbSSangeeta Misra 			/*
1085dbed73cbSSangeeta Misra 			 * Default value of of r_hcpflag means that if there
1086dbed73cbSSangeeta Misra 			 * is a port range, probe any port.  If there is only
1087dbed73cbSSangeeta Misra 			 * one port, probe that port.
1088dbed73cbSSangeeta Misra 			 */
1089dbed73cbSSangeeta Misra 			rd->r_hcpflag = ILB_HCI_PROBE_ANY;
1090dbed73cbSSangeeta Misra 			rc = i_parse_rl_arg(optarg, rd, &rl_healthchk_keys[0]);
1091dbed73cbSSangeeta Misra 			break;
1092dbed73cbSSangeeta Misra 		case 'o':
1093dbed73cbSSangeeta Misra 			rc = i_parse_rl_arg(optarg, rd, &rl_outgoing_keys[0]);
1094dbed73cbSSangeeta Misra 			break;
1095dbed73cbSSangeeta Misra 		case 'm':
1096dbed73cbSSangeeta Misra 			rc = i_parse_rl_arg(optarg, rd, &rl_method_keys[0]);
1097dbed73cbSSangeeta Misra 			break;
1098dbed73cbSSangeeta Misra 		case 't':
1099dbed73cbSSangeeta Misra 			rc = i_parse_rl_arg(optarg, rd, &rl_timer_keys[0]);
1100dbed73cbSSangeeta Misra 			break;
1101dbed73cbSSangeeta Misra 		case 'i':
1102dbed73cbSSangeeta Misra 			rc = i_parse_rl_arg(optarg, rd, &rl_incoming_keys[0]);
1103dbed73cbSSangeeta Misra 			break;
1104dbed73cbSSangeeta Misra 		case 'p':
1105dbed73cbSSangeeta Misra 			p_opt = B_TRUE;
1106dbed73cbSSangeeta Misra 			break;
1107dbed73cbSSangeeta Misra 		case ':':
1108dbed73cbSSangeeta Misra 			ilbadm_err(gettext("missing option-argument"
1109dbed73cbSSangeeta Misra 			    " for %c"), (char)optopt);
1110dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
1111dbed73cbSSangeeta Misra 			break;
1112dbed73cbSSangeeta Misra 		case '?':
1113dbed73cbSSangeeta Misra 		default:
1114dbed73cbSSangeeta Misra 			unknown_opt(argv, optind-1);
1115dbed73cbSSangeeta Misra 			/* not reached */
1116dbed73cbSSangeeta Misra 			break;
1117dbed73cbSSangeeta Misra 
1118dbed73cbSSangeeta Misra 		}
1119dbed73cbSSangeeta Misra 		if (rc != ILBADM_OK)
1120dbed73cbSSangeeta Misra 			goto out;
1121dbed73cbSSangeeta Misra 	}
1122dbed73cbSSangeeta Misra 
1123dbed73cbSSangeeta Misra 	if (optind >= argc) {
1124dbed73cbSSangeeta Misra 		ilbadm_err(gettext("missing mandatory arguments - please refer"
1125dbed73cbSSangeeta Misra 		    " to 'ilbadm create-rule' subcommand description in"
1126dbed73cbSSangeeta Misra 		    " ilbadm(1M)"));
1127dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
1128dbed73cbSSangeeta Misra 		goto out;
1129dbed73cbSSangeeta Misra 
1130dbed73cbSSangeeta Misra 	}
1131dbed73cbSSangeeta Misra 
1132dbed73cbSSangeeta Misra 	if (p_opt) {
1133dbed73cbSSangeeta Misra 		/*
1134dbed73cbSSangeeta Misra 		 * if user hasn't specified a mask, apply default
1135dbed73cbSSangeeta Misra 		 */
1136dbed73cbSSangeeta Misra 		if ((rd->r_flags & ILB_FLAGS_RULE_STICKY) == 0) {
1137dbed73cbSSangeeta Misra 			char 	*maskstr;
1138dbed73cbSSangeeta Misra 
1139dbed73cbSSangeeta Misra 			switch (rd->r_vip.ia_af) {
1140dbed73cbSSangeeta Misra 			case AF_INET:
1141dbed73cbSSangeeta Misra 				maskstr = "32";
1142dbed73cbSSangeeta Misra 				break;
1143dbed73cbSSangeeta Misra 			case AF_INET6:
1144dbed73cbSSangeeta Misra 				maskstr = "128";
1145dbed73cbSSangeeta Misra 				break;
1146dbed73cbSSangeeta Misra 			}
1147dbed73cbSSangeeta Misra 			rc = ilbadm_set_netmask(maskstr, &rd->r_stickymask,
1148dbed73cbSSangeeta Misra 			    rd->r_vip.ia_af);
1149dbed73cbSSangeeta Misra 			if (rc != ILBADM_OK) {
1150dbed73cbSSangeeta Misra 				ilbadm_err(gettext("trouble seting default"
1151dbed73cbSSangeeta Misra 				    " persistence mask"));
1152dbed73cbSSangeeta Misra 				rc = ILBADM_LIBERR;
1153dbed73cbSSangeeta Misra 				goto out;
1154dbed73cbSSangeeta Misra 			}
1155dbed73cbSSangeeta Misra 		}
1156dbed73cbSSangeeta Misra 	} else {
1157dbed73cbSSangeeta Misra 		/* use of sticky mask currently mandates "-p" */
1158dbed73cbSSangeeta Misra 		if ((rd->r_flags & ILB_FLAGS_RULE_STICKY) != 0) {
1159dbed73cbSSangeeta Misra 			ilbadm_err(gettext("use of stickymask requires"
1160dbed73cbSSangeeta Misra 			    " -p option"));
1161dbed73cbSSangeeta Misra 			rc = ILBADM_LIBERR;
1162dbed73cbSSangeeta Misra 			goto out;
1163dbed73cbSSangeeta Misra 		}
1164dbed73cbSSangeeta Misra 	}
1165dbed73cbSSangeeta Misra 
1166dbed73cbSSangeeta Misra 	if (strlen(argv[optind]) > ILBD_NAMESZ -1) {
1167dbed73cbSSangeeta Misra 		ilbadm_err(gettext("rule name %s is too long -"
1168dbed73cbSSangeeta Misra 		    " must not exceed %d chars"), argv[optind],
1169dbed73cbSSangeeta Misra 		    ILBD_NAMESZ - 1);
1170dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
1171dbed73cbSSangeeta Misra 		goto out;
1172dbed73cbSSangeeta Misra 	}
1173dbed73cbSSangeeta Misra 
1174dbed73cbSSangeeta Misra 	(void) strlcpy(rd->r_name, argv[optind], sizeof (rd->r_name));
1175dbed73cbSSangeeta Misra 
1176dbed73cbSSangeeta Misra 	rc = i_check_rule_spec(rd);
1177dbed73cbSSangeeta Misra 	if (rc != ILBADM_OK)
1178dbed73cbSSangeeta Misra 		goto out;
1179dbed73cbSSangeeta Misra 
1180dbed73cbSSangeeta Misra 	rclib = ilb_open(&h);
1181dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
1182dbed73cbSSangeeta Misra 		goto out;
1183dbed73cbSSangeeta Misra 
1184dbed73cbSSangeeta Misra 	rclib = ilb_create_rule(h, rd);
1185dbed73cbSSangeeta Misra 
1186dbed73cbSSangeeta Misra out:
1187dbed73cbSSangeeta Misra 	i_ilbadm_free_rule(rd);
1188dbed73cbSSangeeta Misra 
1189dbed73cbSSangeeta Misra 	if (h != ILB_INVALID_HANDLE)
1190dbed73cbSSangeeta Misra 		(void) ilb_close(h);
1191dbed73cbSSangeeta Misra 
1192dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK) {
1193dbed73cbSSangeeta Misra 		ilbadm_err(ilb_errstr(rclib));
1194dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
1195dbed73cbSSangeeta Misra 	}
1196dbed73cbSSangeeta Misra 	if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR))
1197dbed73cbSSangeeta Misra 		ilbadm_err(ilbadm_errstr(rc));
1198dbed73cbSSangeeta Misra 
1199dbed73cbSSangeeta Misra 	return (rc);
1200dbed73cbSSangeeta Misra }
1201dbed73cbSSangeeta Misra 
1202dbed73cbSSangeeta Misra /* ARGSUSED */
1203dbed73cbSSangeeta Misra 
1204dbed73cbSSangeeta Misra /*
1205dbed73cbSSangeeta Misra  * Since this function is used by libilb function, ilb_walk_rules()
1206dbed73cbSSangeeta Misra  * it must return libilb errors
1207dbed73cbSSangeeta Misra  */
1208dbed73cbSSangeeta Misra static ilb_status_t
ilbadm_export_rl(ilb_handle_t h,ilb_rule_data_t * rd,void * arg)1209dbed73cbSSangeeta Misra ilbadm_export_rl(ilb_handle_t h, ilb_rule_data_t *rd, void *arg)
1210dbed73cbSSangeeta Misra {
1211dbed73cbSSangeeta Misra 	char	linebuf[128];	/* should be enough */
1212dbed73cbSSangeeta Misra 	int	sz = sizeof (linebuf);
1213dbed73cbSSangeeta Misra 	FILE	*fp = ((ilbadm_rl_exp_arg_t *)arg)->fp;
1214dbed73cbSSangeeta Misra 	uint32_t	conndrain, nat_timeout, sticky_timeout;
1215dbed73cbSSangeeta Misra 
1216dbed73cbSSangeeta Misra 	(void) fprintf(fp, "create-rule ");
1217dbed73cbSSangeeta Misra 	if (rd->r_flags & ILB_FLAGS_RULE_ENABLED)
1218dbed73cbSSangeeta Misra 		(void) fprintf(fp, "-e ");
1219dbed73cbSSangeeta Misra 	if (rd->r_flags & ILB_FLAGS_RULE_STICKY)
1220dbed73cbSSangeeta Misra 		(void) fprintf(fp, "-p ");
1221dbed73cbSSangeeta Misra 
1222dbed73cbSSangeeta Misra 	ip2str(&rd->r_vip, linebuf, sz, V6_ADDRONLY);
1223dbed73cbSSangeeta Misra 	(void) fprintf(fp, "-i vip=%s,", linebuf);
1224dbed73cbSSangeeta Misra 
1225dbed73cbSSangeeta Misra 	(void) ports2str(ntohs(rd->r_minport), ntohs(rd->r_maxport),
1226dbed73cbSSangeeta Misra 	    linebuf, sz);
1227dbed73cbSSangeeta Misra 	(void) fprintf(fp, "%s,", linebuf);
1228dbed73cbSSangeeta Misra 
1229dbed73cbSSangeeta Misra 	proto2str(rd->r_proto, linebuf, sz);
1230dbed73cbSSangeeta Misra 	(void) fprintf(fp, "%s ", linebuf);
1231dbed73cbSSangeeta Misra 
1232dbed73cbSSangeeta Misra 	algo2str(rd->r_algo, linebuf, sz);
1233dbed73cbSSangeeta Misra 	(void) fprintf(fp, "-m %s,", linebuf);
1234dbed73cbSSangeeta Misra 
1235dbed73cbSSangeeta Misra 	topo2str(rd->r_topo, linebuf, sz);
1236dbed73cbSSangeeta Misra 	(void) fprintf(fp, "%s", linebuf);
1237dbed73cbSSangeeta Misra 
1238dbed73cbSSangeeta Misra 	if (rd->r_nat_src_start.ia_af != AF_UNSPEC) {
1239dbed73cbSSangeeta Misra 		ip2str(&rd->r_nat_src_start, linebuf, sz, V6_ADDRONLY);
1240dbed73cbSSangeeta Misra 		/* if the address is unspecified, skip it */
1241dbed73cbSSangeeta Misra 		if (linebuf[0] != '\0') {
1242dbed73cbSSangeeta Misra 			(void) fprintf(fp, ",proxy-src=%s", linebuf);
1243dbed73cbSSangeeta Misra 			ip2str(&rd->r_nat_src_end, linebuf, sz, V6_ADDRONLY);
1244dbed73cbSSangeeta Misra 			(void) fprintf(fp, "-%s", linebuf);
1245dbed73cbSSangeeta Misra 		}
1246dbed73cbSSangeeta Misra 	}
1247dbed73cbSSangeeta Misra 
1248dbed73cbSSangeeta Misra 	if (rd->r_flags & ILB_FLAGS_RULE_STICKY) {
1249dbed73cbSSangeeta Misra 		(void) fprintf(fp, ",pmask=/%d",
1250dbed73cbSSangeeta Misra 		    ilbadm_mask_to_prefixlen(&rd->r_stickymask));
1251dbed73cbSSangeeta Misra 	}
1252dbed73cbSSangeeta Misra 
1253dbed73cbSSangeeta Misra 	(void) fprintf(fp, " ");
1254dbed73cbSSangeeta Misra 
1255dbed73cbSSangeeta Misra 	if (*rd->r_hcname != '\0') {
1256dbed73cbSSangeeta Misra 		(void) fprintf(fp, "-h hc-name=%s", rd->r_hcname);
1257dbed73cbSSangeeta Misra 		hcport_print(rd, linebuf, sizeof (linebuf));
1258dbed73cbSSangeeta Misra 
1259dbed73cbSSangeeta Misra 		if (linebuf[0] != '\0')
1260dbed73cbSSangeeta Misra 			(void) fprintf(fp, ",hc-port=%s", linebuf);
1261dbed73cbSSangeeta Misra 		(void) fprintf(fp, " ");
1262dbed73cbSSangeeta Misra 	}
1263dbed73cbSSangeeta Misra 
1264dbed73cbSSangeeta Misra 	conndrain = rd->r_conndrain;
1265dbed73cbSSangeeta Misra 	nat_timeout = rd->r_nat_timeout;
1266dbed73cbSSangeeta Misra 	sticky_timeout = rd->r_sticky_timeout;
1267dbed73cbSSangeeta Misra 	if (conndrain != 0 || nat_timeout != 0 || sticky_timeout != 0) {
1268dbed73cbSSangeeta Misra 		int	cnt = 0;
1269dbed73cbSSangeeta Misra 
1270dbed73cbSSangeeta Misra 		(void) fprintf(fp, "-t ");
1271dbed73cbSSangeeta Misra 		if (conndrain != 0) {
1272dbed73cbSSangeeta Misra 			cnt++;
1273dbed73cbSSangeeta Misra 			(void) fprintf(fp, "conn-drain=%u", conndrain);
1274dbed73cbSSangeeta Misra 		}
1275dbed73cbSSangeeta Misra 		if (nat_timeout != 0) {
1276dbed73cbSSangeeta Misra 			if (cnt > 0)
1277dbed73cbSSangeeta Misra 				(void) fprintf(fp, ",");
1278dbed73cbSSangeeta Misra 			cnt++;
1279dbed73cbSSangeeta Misra 			(void) fprintf(fp, "nat-timeout=%u", nat_timeout);
1280dbed73cbSSangeeta Misra 		}
1281dbed73cbSSangeeta Misra 		if (sticky_timeout != 0) {
1282dbed73cbSSangeeta Misra 			if (cnt > 0)
1283dbed73cbSSangeeta Misra 				(void) fprintf(fp, ",");
1284dbed73cbSSangeeta Misra 			(void) fprintf(fp, "persist-timeout=%u",
1285dbed73cbSSangeeta Misra 			    sticky_timeout);
1286dbed73cbSSangeeta Misra 		}
1287dbed73cbSSangeeta Misra 		(void) fprintf(fp, " ");
1288dbed73cbSSangeeta Misra 	}
1289dbed73cbSSangeeta Misra 
1290dbed73cbSSangeeta Misra 	if (fprintf(fp, "-o servergroup=%s %s\n", rd->r_sgname, rd->r_name)
1291dbed73cbSSangeeta Misra 	    < 0 || fflush(fp) == EOF)
1292dbed73cbSSangeeta Misra 		return (ILB_STATUS_WRITE);
1293dbed73cbSSangeeta Misra 
1294dbed73cbSSangeeta Misra 	return (ILB_STATUS_OK);
1295dbed73cbSSangeeta Misra }
1296dbed73cbSSangeeta Misra 
1297dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_export_rules(ilb_handle_t h,FILE * fp)1298dbed73cbSSangeeta Misra ilbadm_export_rules(ilb_handle_t h, FILE *fp)
1299dbed73cbSSangeeta Misra {
1300dbed73cbSSangeeta Misra 	ilb_status_t	rclib;
1301dbed73cbSSangeeta Misra 	ilbadm_status_t	rc = ILBADM_OK;
1302dbed73cbSSangeeta Misra 	ilbadm_rl_exp_arg_t	arg;
1303dbed73cbSSangeeta Misra 
1304dbed73cbSSangeeta Misra 	arg.fp = fp;
1305dbed73cbSSangeeta Misra 
1306dbed73cbSSangeeta Misra 	rclib = ilb_walk_rules(h, ilbadm_export_rl, NULL, (void *)&arg);
1307dbed73cbSSangeeta Misra 	if (rclib != ILB_STATUS_OK)
1308dbed73cbSSangeeta Misra 		rc = ILBADM_LIBERR;
1309dbed73cbSSangeeta Misra 	return (rc);
1310dbed73cbSSangeeta Misra }
1311