4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Milan Jurik. All rights reserved.
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
44 static ilbadm_key_name_t rl_incoming_keys
[] = {
45 {ILB_KEY_VIP
, "vip", ""},
46 {ILB_KEY_PORT
, "port", ""},
47 {ILB_KEY_PROTOCOL
, "protocol", "prot"},
50 static ilbadm_key_name_t rl_method_keys
[] = {
51 {ILB_KEY_ALGORITHM
, "lbalg", "algo"},
52 {ILB_KEY_TYPE
, "type", "topo"},
53 {ILB_KEY_SRC
, "proxy-src", "nat-src"},
54 {ILB_KEY_STICKY
, "pmask", "persist"},
57 static ilbadm_key_name_t rl_outgoing_keys
[] = {
58 {ILB_KEY_SERVERGROUP
, "servergroup", "sg"},
61 static ilbadm_key_name_t rl_healthchk_keys
[] = {
62 {ILB_KEY_HEALTHCHECK
, "hc-name", "hcn"},
63 {ILB_KEY_HCPORT
, "hc-port", "hcp"},
66 static ilbadm_key_name_t rl_timer_keys
[] = {
67 {ILB_KEY_CONNDRAIN
, "conn-drain", ""},
68 {ILB_KEY_NAT_TO
, "nat-timeout", ""},
69 {ILB_KEY_STICKY_TO
, "persist-timeout", ""},
73 static ilbadm_key_name_t
*all_keys
[] = {
74 rl_incoming_keys
, rl_method_keys
, rl_outgoing_keys
,
75 rl_healthchk_keys
, rl_timer_keys
, NULL
79 /* field ids for of_* functions */
81 #define OF_IP_PROXYSRC 1
82 #define OF_IP_STICKYMASK 2
84 #define OF_STR_RNAME 0
85 #define OF_STR_HCNAME 1
86 #define OF_STR_SGNAME 2
87 #define OF_STR_INTERFACE 3
99 #define OF_SRV_STATUS 3
100 #define OF_SRV_RNAME 4
101 #define OF_SRV_SGNAME 5
102 #define OF_SRV_HOSTNAME 6
104 /* some field sizes of ofmt_field_t arrays */
105 #define IPv4_FIELDWIDTH 16
106 #define IPv6_FIELDWIDTH 39
107 #define ILB_HOSTNAMELEN 20
108 #define ILB_STATUSFIELD_LEN 7
110 typedef struct arg_struct
{
113 ofmt_field_t
*o_fields
;
115 } ilbadm_sh_rl_arg_t
;
117 typedef struct ilbadm_rl_exp_arg
{
119 } ilbadm_rl_exp_arg_t
;
121 typedef struct ilbadm_rl_list_arg
{
124 } ilbadm_rl_list_arg_t
;
126 typedef struct ilbadm_rl_srvlist_arg
{
128 ilb_server_data_t
*sd
;
132 ofmt_field_t
*o_fields
;
134 } ilbadm_rl_srvlist_arg_t
;
136 static ofmt_cb_t of_algo
;
137 static ofmt_cb_t of_proto
;
138 static ofmt_cb_t of_rl_ip
;
139 static ofmt_cb_t of_rl_mask
;
140 static ofmt_cb_t of_rport
;
141 static ofmt_cb_t of_rstatus
;
142 static ofmt_cb_t of_str
;
143 static ofmt_cb_t of_time
;
144 static ofmt_cb_t of_topo
;
145 static ofmt_cb_t of_rl_srvlist
;
147 static boolean_t
of_srv2str(ofmt_arg_t
*, char *, uint_t
);
148 static boolean_t
of_port2str(in_port_t
, in_port_t
, char *, uint_t
);
150 static ofmt_field_t rfields_v4
[] = {
151 {"RULENAME", ILB_NAMESZ
, OF_STR_RNAME
, of_str
},
152 {"STATUS", ILB_STATUSFIELD_LEN
, 0, of_rstatus
},
153 {"PORT", 10, OF_PORT
, of_rport
},
154 {"PROTOCOL", 5, 0, of_proto
},
155 {"LBALG", 12, 0, of_algo
},
156 {"TYPE", 8, 0, of_topo
},
157 {"PROXY-SRC", 2*IPv4_FIELDWIDTH
+1, OF_IP_PROXYSRC
, of_rl_ip
},
158 {"PMASK", 6, OF_IP_STICKYMASK
, of_rl_mask
},
159 {"HC-NAME", ILB_NAMESZ
, OF_STR_HCNAME
, of_str
},
160 {"HC-PORT", 8, OF_HCPORT
, of_rport
},
161 {"CONN-DRAIN", 11, OF_T_CONN
, of_time
},
162 {"NAT-TIMEOUT", 12, OF_T_NAT
, of_time
},
163 {"PERSIST-TIMEOUT", 16, OF_T_STICKY
, of_time
},
164 {"SERVERGROUP", ILB_SGNAME_SZ
, OF_STR_SGNAME
, of_str
},
165 {"VIP", IPv4_FIELDWIDTH
, OF_IP_VIP
, of_rl_ip
},
166 {"SERVERS", 20, 0, of_rl_srvlist
},
170 static ofmt_field_t rfields_v6
[] = {
171 {"RULENAME", ILB_NAMESZ
, OF_STR_RNAME
, of_str
},
172 {"STATUS", ILB_STATUSFIELD_LEN
, 0, of_rstatus
},
173 {"PORT", 10, OF_PORT
, of_rport
},
174 {"PROTOCOL", 5, 0, of_proto
},
175 {"LBALG", 12, 0, of_algo
},
176 {"TYPE", 8, 0, of_topo
},
177 {"PROXY-SRC", IPv6_FIELDWIDTH
, OF_IP_PROXYSRC
, of_rl_ip
},
178 {"PMASK", 6, OF_IP_STICKYMASK
, of_rl_mask
},
179 {"HC-NAME", ILB_NAMESZ
, OF_STR_HCNAME
, of_str
},
180 {"HC-PORT", 8, OF_HCPORT
, of_rport
},
181 {"CONN-DRAIN", 11, OF_T_CONN
, of_time
},
182 {"NAT-TIMEOUT", 12, OF_T_NAT
, of_time
},
183 {"PERSIST-TIMEOUT", 16, OF_T_STICKY
, of_time
},
184 {"SERVERGROUP", ILB_SGNAME_SZ
, OF_STR_SGNAME
, of_str
},
185 {"VIP", IPv6_FIELDWIDTH
, OF_IP_VIP
, of_rl_ip
},
186 {"SERVERS", 20, 0, of_rl_srvlist
},
190 static ofmt_field_t ssfields_v4
[] = {
191 {"SERVERID", ILB_NAMESZ
, OF_SRV_ID
, of_srv2str
},
192 {"ADDRESS", IPv4_FIELDWIDTH
, OF_SRV_ADDR
, of_srv2str
},
193 {"PORT", 5, OF_SRV_PORT
, of_srv2str
},
194 {"RULENAME", ILB_NAMESZ
, OF_SRV_RNAME
, of_srv2str
},
195 {"STATUS", ILB_STATUSFIELD_LEN
, OF_SRV_STATUS
, of_srv2str
},
196 {"SERVERGROUP", ILB_SGNAME_SZ
, OF_SRV_SGNAME
, of_srv2str
},
197 {"HOSTNAME", ILB_HOSTNAMELEN
, OF_SRV_HOSTNAME
, of_srv2str
},
201 static ofmt_field_t ssfields_v6
[] = {
202 {"SERVERID", ILB_NAMESZ
, OF_SRV_ID
, of_srv2str
},
203 {"ADDRESS", IPv6_FIELDWIDTH
, OF_SRV_ADDR
, of_srv2str
},
204 {"PORT", 5, OF_SRV_PORT
, of_srv2str
},
205 {"RULENAME", ILB_NAMESZ
, OF_SRV_RNAME
, of_srv2str
},
206 {"STATUS", ILB_STATUSFIELD_LEN
, OF_SRV_STATUS
, of_srv2str
},
207 {"SERVERGROUP", ILB_SGNAME_SZ
, OF_SRV_SGNAME
, of_srv2str
},
208 {"HOSTNAME", ILB_HOSTNAMELEN
, OF_SRV_HOSTNAME
, of_srv2str
},
212 extern int optind
, optopt
, opterr
;
215 extern ilbadm_val_type_t algo_types
[];
216 extern ilbadm_val_type_t topo_types
[];
219 i_key_to_opt(ilbadm_key_name_t
*n
, ilbadm_key_code_t k
)
223 for (i
= 0; n
[i
].k_key
!= ILB_KEY_BAD
; i
++)
227 return (n
[i
].k_name
);
231 ilbadm_key_to_opt(ilbadm_key_code_t k
)
236 for (i
= 0; all_keys
[i
] != NULL
; i
++) {
237 name
= i_key_to_opt(all_keys
[i
], k
);
246 * ports are in HOST byte order
249 ports2str(short port1
, short port2
, char *buf
, const int sz
)
252 (void) snprintf(buf
, sz
, "port=%d", port1
);
254 (void) snprintf(buf
, sz
, "port=%d-%d", port1
, port2
);
258 proto2str(short proto
, char *buf
, int sz
)
262 pe
= getprotobynumber((int)proto
);
264 (void) snprintf(buf
, sz
, "protocol=%s", pe
->p_name
);
266 (void) sprintf(buf
, "(bad proto %d)", proto
);
270 algo2str(ilb_algo_t algo
, char *buf
, int sz
)
272 char *s
= i_str_from_val((int)algo
, &algo_types
[0]);
274 (void) snprintf(buf
, sz
, "lbalg=%s", (s
&& *s
) ? s
: "(bad algo)");
278 algo2bare_str(ilb_algo_t algo
, char *buf
, int sz
)
280 char *s
= i_str_from_val((int)algo
, &algo_types
[0]);
282 return (snprintf(buf
, sz
, "%s", (s
&& *s
) ? s
: ""));
286 topo2str(ilb_topo_t topo
, char *buf
, int sz
)
288 char *s
= i_str_from_val((int)topo
, &topo_types
[0]);
290 (void) snprintf(buf
, sz
, "type=%s", (s
&& *s
) ? s
: "(bad type)");
294 topo2bare_str(ilb_topo_t topo
, char *buf
, int sz
)
296 char *s
= i_str_from_val((int)topo
, &topo_types
[0]);
298 return (snprintf(buf
, sz
, "%s", (s
&& *s
) ? s
: ""));
302 of_str(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
304 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
305 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
307 switch (of_arg
->ofmt_id
) {
309 (void) strlcpy(buf
, rd
->r_name
, bufsize
);
312 (void) strlcpy(buf
, rd
->r_sgname
, bufsize
);
315 if (rd
->r_hcname
!= NULL
&& *(rd
->r_hcname
) != '\0')
316 (void) strlcpy(buf
, rd
->r_hcname
, bufsize
);
324 of_proto(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
326 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
327 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
329 if (rd
->r_proto
== IPPROTO_TCP
)
330 (void) strlcpy(buf
, "TCP", bufsize
);
331 else if (rd
->r_proto
== IPPROTO_UDP
)
332 (void) strlcpy(buf
, "UDP", bufsize
);
339 of_rl_ip(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
341 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
342 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
343 ilb_ip_addr_t
*ip
= NULL
, *ip2
= NULL
;
345 switch (of_arg
->ofmt_id
) {
350 ip
= &rd
->r_nat_src_start
;
351 ip2
= &rd
->r_nat_src_end
;
353 case OF_IP_STICKYMASK
:
354 ip
= &rd
->r_stickymask
;
358 /* only print something valid */
359 if (ip
!= NULL
&& (ip
->ia_af
== AF_INET
|| ip
->ia_af
== AF_INET6
))
360 ip2str(ip
, buf
, bufsize
, V6_ADDRONLY
);
361 if (ip2
!= NULL
&& (ip2
->ia_af
== AF_INET
|| ip2
->ia_af
== AF_INET6
) &&
363 int sl
= strlen(buf
);
365 buf
+= sl
; bufsize
-= sl
;
366 *buf
++ = '-'; bufsize
--;
367 ip2str(ip2
, buf
, bufsize
, V6_ADDRONLY
);
374 of_rl_mask(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
376 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
377 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
378 ilb_ip_addr_t
*ip
= NULL
;
380 assert(of_arg
->ofmt_id
== OF_IP_STICKYMASK
);
381 if (!(rd
->r_flags
& ILB_FLAGS_RULE_STICKY
))
383 ip
= &rd
->r_stickymask
;
385 (void) snprintf(buf
, bufsize
, "/%d", ilbadm_mask_to_prefixlen(ip
));
390 hcport_print(ilb_rule_data_t
*rd
, char *buf
, uint_t bufsize
)
392 if (rd
->r_hcport
!= 0)
393 (void) snprintf(buf
, bufsize
, "%d", ntohs(rd
->r_hcport
));
394 else if (rd
->r_hcpflag
== ILB_HCI_PROBE_ANY
)
395 (void) snprintf(buf
, bufsize
, "ANY");
400 of_rport(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
402 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
403 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
405 if (of_arg
->ofmt_id
== OF_PORT
)
406 return (of_port2str(rd
->r_minport
, rd
->r_maxport
, buf
,
409 /* only print a hcport if there's a hc name as well */
410 if (of_arg
->ofmt_id
== OF_HCPORT
&& rd
->r_hcname
[0] != '\0')
411 hcport_print(rd
, buf
, bufsize
);
418 of_rstatus(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
420 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
421 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
423 if ((rd
->r_flags
& ILB_FLAGS_RULE_ENABLED
) == ILB_FLAGS_RULE_ENABLED
)
432 of_algo(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
434 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
435 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
437 if (algo2bare_str(rd
->r_algo
, buf
, bufsize
) == 0)
443 of_topo(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
445 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
446 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
448 if (topo2bare_str(rd
->r_topo
, buf
, bufsize
) == 0)
454 of_time(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
456 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
457 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
459 switch (of_arg
->ofmt_id
) {
461 (void) snprintf(buf
, bufsize
, "%u", rd
->r_conndrain
);
464 (void) snprintf(buf
, bufsize
, "%u", rd
->r_nat_timeout
);
467 (void) snprintf(buf
, bufsize
, "%u", rd
->r_sticky_timeout
);
473 typedef struct rl_showlist_arg
{
479 /* called by ilb_walk_servers(), cannot get rid of unused args */
481 srv2srvID(ilb_handle_t h
, ilb_server_data_t
*sd
, const char *sgname
, void *arg
)
483 rl_showlist_arg_t
*sla
= (rl_showlist_arg_t
*)arg
;
486 (void) snprintf(sla
->buf
, sla
->bufsize
, "%s,", sd
->sd_srvID
);
487 len
= strlen(sd
->sd_srvID
) + 1;
491 return (ILB_STATUS_OK
);
495 of_rl_srvlist(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
497 ilbadm_rl_list_arg_t
*ra
= (ilbadm_rl_list_arg_t
*)of_arg
->ofmt_cbarg
;
498 ilb_rule_data_t
*rd
= (ilb_rule_data_t
*)ra
->rd
;
499 rl_showlist_arg_t sla
;
502 sla
.bufsize
= bufsize
;
504 (void) ilb_walk_servers(ra
->h
, srv2srvID
, rd
->r_sgname
,
506 /* we're trailing a ',' which we need to remove */
512 #define RMAXCOLS 120 /* enough? */
513 #define SERVER_WIDTH (ILB_NAMESZ+1) /* 1st guess */
516 of_port2str(in_port_t minport
, in_port_t maxport
, char *buf
, uint_t bufsize
)
518 in_port_t h_min
, h_max
;
521 h_min
= ntohs(minport
);
522 h_max
= ntohs(maxport
);
525 return (B_FALSE
); /* print "unspec" == "all ports" */
527 len
= snprintf(buf
, bufsize
, "%d", h_min
);
529 (void) snprintf(buf
+ len
, bufsize
- len
, "-%d", h_max
);
533 static ilbadm_status_t
534 ip2hostname(ilb_ip_addr_t
*ip
, char *buf
, uint_t bufsize
)
541 he
= getipnodebyaddr((char *)&ip
->ia_v4
, sizeof (ip
->ia_v4
),
545 he
= getipnodebyaddr((char *)&ip
->ia_v6
, sizeof (ip
->ia_v6
),
548 default: return (ILBADM_INVAL_AF
);
551 /* if we can't resolve this, just return an empty name */
555 (void) strlcpy(buf
, he
->h_name
, bufsize
);
562 * Since this function is used by libilb routine ilb_walk_rules()
563 * it must return libilb errors
566 ilbadm_show_onerule(ilb_handle_t h
, ilb_rule_data_t
*rd
, void *arg
)
568 ilbadm_sh_rl_arg_t
*larg
= (ilbadm_sh_rl_arg_t
*)arg
;
571 int ocols
= RMAXCOLS
;
572 ilbadm_rl_list_arg_t ra
;
573 static ofmt_handle_t oh
= (ofmt_handle_t
)NULL
;
574 ofmt_field_t
*fields
;
575 boolean_t r_enabled
= rd
->r_flags
& ILB_FLAGS_RULE_ENABLED
;
577 if (larg
->o_str
== NULL
) {
578 ilbadm_err(gettext("internal error"));
579 return (ILB_STATUS_GENERIC
);
583 * only print rules (enabled/dis-) we're asked to
584 * note: both LIST_**ABLED flags can be set at the same time,
585 * whereas a rule has one state only. therefore the complicated
588 if (!((r_enabled
&& (larg
->flags
& ILBADM_LIST_ENABLED
)) ||
589 (!r_enabled
&& (larg
->flags
& ILBADM_LIST_DISABLED
))))
590 return (ILB_STATUS_OK
);
592 if (larg
->flags
& ILBADM_LIST_PARSE
)
593 oflags
|= OFMT_PARSABLE
;
595 if (larg
->flags
& ILBADM_LIST_FULL
)
596 oflags
|= OFMT_MULTILINE
;
598 bzero(&ra
, sizeof (ra
));
603 if (rd
->r_vip
.ia_af
== AF_INET
)
608 oerr
= ofmt_open(larg
->o_str
, fields
, oflags
, ocols
, &oh
);
609 if (oerr
!= OFMT_SUCCESS
) {
612 ilbadm_err(gettext("ofmt_open failed: %s"),
613 ofmt_strerror(oh
, oerr
, e
, sizeof (e
)));
614 return (ILB_STATUS_GENERIC
);
620 return (ILB_STATUS_OK
);
623 static char *full_list_rule_hdrs
=
624 "RULENAME,STATUS,PORT,PROTOCOL,LBALG,TYPE,PROXY-SRC,PMASK,"
625 "HC-NAME,HC-PORT,CONN-DRAIN,NAT-TIMEOUT,"
626 "PERSIST-TIMEOUT,SERVERGROUP,VIP,SERVERS";
627 static char *def_list_rule_hdrs
=
628 "RULENAME,STATUS,LBALG,TYPE,PROTOCOL,VIP,PORT";
632 ilbadm_show_rules(int argc
, char *argv
[])
634 ilb_handle_t h
= ILB_INVALID_HANDLE
;
636 ilb_status_t rclib
= ILB_STATUS_OK
;
637 ilbadm_status_t rc
= ILBADM_OK
;
638 boolean_t o_opt
= B_FALSE
, p_opt
= B_FALSE
;
639 boolean_t f_opt
= B_FALSE
;
640 ilbadm_sh_rl_arg_t larg
= {0, NULL
, NULL
, NULL
};
642 larg
.flags
= ILBADM_LIST_ENABLED
| ILBADM_LIST_DISABLED
;
643 while ((c
= getopt(argc
, argv
, ":fpedo:")) != -1) {
645 case 'f': larg
.flags
|= ILBADM_LIST_FULL
;
646 larg
.o_str
= full_list_rule_hdrs
;
649 case 'p': larg
.flags
|= ILBADM_LIST_PARSE
;
652 case 'o': larg
.o_str
= optarg
;
655 /* -e and -d may be repeated - make sure the last one wins */
656 case 'e': larg
.flags
&= ILBADM_LIST_NODISABLED
;
657 larg
.flags
|= ILBADM_LIST_ENABLED
;
659 case 'd': larg
.flags
&= ILBADM_LIST_NOENABLED
;
660 larg
.flags
|= ILBADM_LIST_DISABLED
;
662 case ':': ilbadm_err(gettext("missing option argument for %c"),
668 unknown_opt(argv
, optind
-1);
674 if (f_opt
&& o_opt
) {
675 ilbadm_err(gettext("options -o and -f are mutually"
680 if (p_opt
&& !o_opt
) {
681 ilbadm_err(gettext("option -p requires -o"));
685 if (p_opt
&& larg
.o_str
!= NULL
&&
686 (strcasecmp(larg
.o_str
, "all") == 0)) {
687 ilbadm_err(gettext("option -p requires explicit field"
692 /* no -o option, so we use std. fields */
693 if (!o_opt
&& !f_opt
)
694 larg
.o_str
= def_list_rule_hdrs
;
696 rclib
= ilb_open(&h
);
697 if (rclib
!= ILB_STATUS_OK
)
700 if (optind
>= argc
) {
701 rclib
= ilb_walk_rules(h
, ilbadm_show_onerule
, NULL
,
704 while (optind
< argc
) {
705 rclib
= ilb_walk_rules(h
, ilbadm_show_onerule
,
706 argv
[optind
++], (void*)&larg
);
707 if (rclib
!= ILB_STATUS_OK
)
712 if (h
!= ILB_INVALID_HANDLE
)
715 if (rclib
!= ILB_STATUS_OK
) {
717 * The show function returns ILB_STATUS_GENERIC after printing
718 * out an error message. So we don't need to print it again.
720 if (rclib
!= ILB_STATUS_GENERIC
)
721 ilbadm_err(ilb_errstr(rclib
));
728 of_srv2str(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
730 ilbadm_rl_srvlist_arg_t
*larg
=
731 (ilbadm_rl_srvlist_arg_t
*)of_arg
->ofmt_cbarg
;
732 ilb_server_data_t
*sd
= larg
->sd
;
733 uint_t op
= of_arg
->ofmt_id
;
734 boolean_t ret
= B_TRUE
;
742 (void) strlcpy(buf
, sd
->sd_srvID
, bufsize
);
745 if (ILB_IS_SRV_ENABLED(sd
->sd_flags
))
752 (void) strlcpy(buf
, larg
->rd
->r_name
, bufsize
);
755 (void) strlcpy(buf
, larg
->sgname
, bufsize
);
757 case OF_SRV_HOSTNAME
:
758 rc
= ip2hostname(&sd
->sd_addr
, buf
, bufsize
);
759 if (rc
!= ILBADM_OK
) {
765 ret
= of_port2str(sd
->sd_minport
, sd
->sd_maxport
,
769 ip2str(&sd
->sd_addr
, buf
, bufsize
, V6_ADDRONLY
);
778 i_show_rl_srv(ilb_handle_t h
, ilb_server_data_t
*sd
, const char *sgname
,
781 ilbadm_rl_srvlist_arg_t
*larg
= (ilbadm_rl_srvlist_arg_t
*)arg
;
784 ofmt_print(larg
->oh
, larg
);
785 return (ILB_STATUS_OK
);
790 * Since this function is used by libilb routine ilb_walk_rules()
791 * it must return libilb errors
794 ilbadm_show_rl_servers(ilb_handle_t h
, ilb_rule_data_t
*rd
, void *arg
)
798 int ocols
= RMAXCOLS
;
799 ofmt_field_t
*fields
;
800 static ofmt_handle_t oh
= (ofmt_handle_t
)NULL
;
801 ilbadm_rl_srvlist_arg_t
*larg
= (ilbadm_rl_srvlist_arg_t
*)arg
;
804 * in full mode, we currently re-open ofmt() for every rule; we use
805 * a variable number of lines, as we print one for every server
806 * attached to a rule.
808 if (larg
->o_str
== NULL
) {
809 ilbadm_err(gettext("internal error"));
810 return (ILB_STATUS_GENERIC
);
813 if (larg
->flags
& ILBADM_LIST_PARSE
)
814 oflags
|= OFMT_PARSABLE
;
816 if (rd
->r_vip
.ia_af
== AF_INET
)
817 fields
= ssfields_v4
;
819 fields
= ssfields_v6
;
822 oerr
= ofmt_open(larg
->o_str
, fields
, oflags
, ocols
, &oh
);
823 if (oerr
!= OFMT_SUCCESS
) {
826 ilbadm_err(gettext("ofmt_open failed: %s"),
827 ofmt_strerror(oh
, oerr
, e
, sizeof (e
)));
828 return (ILB_STATUS_GENERIC
);
834 larg
->sgname
= rd
->r_sgname
;
836 return (ilb_walk_servers(h
, i_show_rl_srv
, rd
->r_sgname
, (void *)larg
));
839 static char *def_show_srv_hdrs
=
840 "SERVERID,ADDRESS,PORT,RULENAME,STATUS,SERVERGROUP";
844 ilbadm_show_server(int argc
, char *argv
[])
846 ilb_handle_t h
= ILB_INVALID_HANDLE
;
848 ilb_status_t rclib
= ILB_STATUS_OK
;
849 ilbadm_status_t rc
= ILBADM_OK
;
850 boolean_t o_opt
= B_FALSE
, p_opt
= B_FALSE
;
851 ilbadm_rl_srvlist_arg_t larg
;
853 bzero(&larg
, sizeof (larg
));
854 while ((c
= getopt(argc
, argv
, ":po:")) != -1) {
856 case 'p': larg
.flags
|= ILBADM_LIST_PARSE
;
859 case 'o': larg
.o_str
= optarg
;
862 case ':': ilbadm_err(gettext("missing option argument for %c"),
868 unknown_opt(argv
, optind
-1);
874 if (p_opt
&& !o_opt
) {
875 ilbadm_err(gettext("option -p requires -o"));
879 if (p_opt
&& larg
.o_str
!= NULL
&&
880 (strcasecmp(larg
.o_str
, "all") == 0)) {
881 ilbadm_err(gettext("option -p requires explicit"
882 " field names for -o"));
886 /* no -o option, so we use default fields */
888 larg
.o_str
= def_show_srv_hdrs
;
890 rclib
= ilb_open(&h
);
891 if (rclib
!= ILB_STATUS_OK
)
894 if (optind
>= argc
) {
895 rclib
= ilb_walk_rules(h
, ilbadm_show_rl_servers
, NULL
,
898 while (optind
< argc
) {
899 rclib
= ilb_walk_rules(h
, ilbadm_show_rl_servers
,
900 argv
[optind
++], (void*)&larg
);
901 if (rclib
!= ILB_STATUS_OK
)
906 if (h
!= ILB_INVALID_HANDLE
)
909 if (rclib
!= ILB_STATUS_OK
) {
911 * The show function returns ILB_STATUS_GENERIC after printing
912 * out an error message. So we don't need to print it again.
914 if (rclib
!= ILB_STATUS_GENERIC
)
915 ilbadm_err(ilb_errstr(rclib
));
921 static ilbadm_status_t
922 i_parse_rl_arg(char *arg
, ilb_rule_data_t
*rd
, ilbadm_key_name_t
*keylist
)
926 rc
= i_parse_optstring(arg
, (void *) rd
, keylist
,
932 i_ilbadm_alloc_rule(ilb_rule_data_t
**rdp
)
936 *rdp
= rd
= (ilb_rule_data_t
*)calloc(sizeof (*rd
), 1);
939 rd
->r_proto
= IPPROTO_TCP
;
943 i_ilbadm_free_rule(ilb_rule_data_t
*rd
)
950 ilbadm_destroy_rule(int argc
, char *argv
[])
952 ilb_handle_t h
= ILB_INVALID_HANDLE
;
953 ilbadm_status_t rc
= ILBADM_OK
;
954 ilb_status_t rclib
= ILB_STATUS_OK
;
955 boolean_t all_rules
= B_FALSE
;
958 while ((c
= getopt(argc
, argv
, ":a")) != -1) {
965 unknown_opt(argv
, optind
-1);
971 if (optind
>= argc
&& !all_rules
) {
972 ilbadm_err(gettext("usage: delete-rule -a | name"));
973 return (ILBADM_LIBERR
);
976 /* either "-a" or rulename, not both */
977 if (optind
< argc
&& all_rules
) {
978 rc
= ILBADM_INVAL_ARGS
;
982 rclib
= ilb_open(&h
);
983 if (rclib
!= ILB_STATUS_OK
)
987 rclib
= ilb_destroy_rule(h
, NULL
);
991 for (i
= optind
; i
< argc
&& rclib
== ILB_STATUS_OK
; i
++)
992 rclib
= ilb_destroy_rule(h
, argv
[i
]);
995 if (h
!= ILB_INVALID_HANDLE
)
998 /* This prints the specific errors */
999 if (rclib
!= ILB_STATUS_OK
) {
1000 ilbadm_err(ilb_errstr(rclib
));
1003 /* This prints the generic errors */
1004 if ((rc
!= ILBADM_OK
) && (rc
!= ILBADM_LIBERR
))
1005 ilbadm_err(ilbadm_errstr(rc
));
1010 static ilbadm_status_t
1011 ilbadm_Xable_rule(int argc
, char *argv
[], ilbadm_cmd_t cmd
)
1013 ilb_handle_t h
= ILB_INVALID_HANDLE
;
1014 ilb_status_t rclib
= ILB_STATUS_OK
;
1015 ilbadm_status_t rc
= ILBADM_OK
;
1018 rclib
= ilb_open(&h
);
1019 if (rclib
!= ILB_STATUS_OK
)
1022 * by default, en/disable-rule mean "all", and not using
1023 * a rule name will cause this behaviour to kick in
1026 if (cmd
== cmd_enable_rule
)
1027 rclib
= ilb_enable_rule(h
, NULL
);
1029 rclib
= ilb_disable_rule(h
, NULL
);
1032 for (i
= optind
; i
< argc
&& rc
== ILBADM_OK
; i
++) {
1033 if (cmd
== cmd_enable_rule
)
1034 rclib
= ilb_enable_rule(h
, argv
[i
]);
1036 rclib
= ilb_disable_rule(h
, argv
[i
]);
1040 if (h
!= ILB_INVALID_HANDLE
)
1041 (void) ilb_close(h
);
1043 if (rclib
!= ILB_STATUS_OK
) {
1044 ilbadm_err(ilb_errstr(rclib
));
1051 ilbadm_enable_rule(int argc
, char *argv
[])
1054 return (ilbadm_Xable_rule(argc
, argv
, cmd_enable_rule
));
1058 ilbadm_disable_rule(int argc
, char *argv
[])
1060 return (ilbadm_Xable_rule(argc
, argv
, cmd_disable_rule
));
1064 * parse and create a rule
1067 ilbadm_create_rule(int argc
, char *argv
[])
1069 ilb_handle_t h
= ILB_INVALID_HANDLE
;
1071 ilb_status_t rclib
= ILB_STATUS_OK
;
1072 ilbadm_status_t rc
= ILBADM_OK
;
1073 ilb_rule_data_t
*rd
;
1074 boolean_t p_opt
= B_FALSE
;
1076 i_ilbadm_alloc_rule(&rd
);
1078 while ((c
= getopt(argc
, argv
, ":ei:m:o:t:h:p")) != -1) {
1081 rd
->r_flags
|= ILB_FLAGS_RULE_ENABLED
;
1085 * Default value of of r_hcpflag means that if there
1086 * is a port range, probe any port. If there is only
1087 * one port, probe that port.
1089 rd
->r_hcpflag
= ILB_HCI_PROBE_ANY
;
1090 rc
= i_parse_rl_arg(optarg
, rd
, &rl_healthchk_keys
[0]);
1093 rc
= i_parse_rl_arg(optarg
, rd
, &rl_outgoing_keys
[0]);
1096 rc
= i_parse_rl_arg(optarg
, rd
, &rl_method_keys
[0]);
1099 rc
= i_parse_rl_arg(optarg
, rd
, &rl_timer_keys
[0]);
1102 rc
= i_parse_rl_arg(optarg
, rd
, &rl_incoming_keys
[0]);
1108 ilbadm_err(gettext("missing option-argument"
1109 " for %c"), (char)optopt
);
1114 unknown_opt(argv
, optind
-1);
1119 if (rc
!= ILBADM_OK
)
1123 if (optind
>= argc
) {
1124 ilbadm_err(gettext("missing mandatory arguments - please refer"
1125 " to 'ilbadm create-rule' subcommand description in"
1134 * if user hasn't specified a mask, apply default
1136 if ((rd
->r_flags
& ILB_FLAGS_RULE_STICKY
) == 0) {
1139 switch (rd
->r_vip
.ia_af
) {
1147 rc
= ilbadm_set_netmask(maskstr
, &rd
->r_stickymask
,
1149 if (rc
!= ILBADM_OK
) {
1150 ilbadm_err(gettext("trouble seting default"
1151 " persistence mask"));
1157 /* use of sticky mask currently mandates "-p" */
1158 if ((rd
->r_flags
& ILB_FLAGS_RULE_STICKY
) != 0) {
1159 ilbadm_err(gettext("use of stickymask requires"
1166 if (strlen(argv
[optind
]) > ILBD_NAMESZ
-1) {
1167 ilbadm_err(gettext("rule name %s is too long -"
1168 " must not exceed %d chars"), argv
[optind
],
1174 (void) strlcpy(rd
->r_name
, argv
[optind
], sizeof (rd
->r_name
));
1176 rc
= i_check_rule_spec(rd
);
1177 if (rc
!= ILBADM_OK
)
1180 rclib
= ilb_open(&h
);
1181 if (rclib
!= ILB_STATUS_OK
)
1184 rclib
= ilb_create_rule(h
, rd
);
1187 i_ilbadm_free_rule(rd
);
1189 if (h
!= ILB_INVALID_HANDLE
)
1190 (void) ilb_close(h
);
1192 if (rclib
!= ILB_STATUS_OK
) {
1193 ilbadm_err(ilb_errstr(rclib
));
1196 if ((rc
!= ILBADM_OK
) && (rc
!= ILBADM_LIBERR
))
1197 ilbadm_err(ilbadm_errstr(rc
));
1205 * Since this function is used by libilb function, ilb_walk_rules()
1206 * it must return libilb errors
1209 ilbadm_export_rl(ilb_handle_t h
, ilb_rule_data_t
*rd
, void *arg
)
1211 char linebuf
[128]; /* should be enough */
1212 int sz
= sizeof (linebuf
);
1213 FILE *fp
= ((ilbadm_rl_exp_arg_t
*)arg
)->fp
;
1214 uint32_t conndrain
, nat_timeout
, sticky_timeout
;
1216 (void) fprintf(fp
, "create-rule ");
1217 if (rd
->r_flags
& ILB_FLAGS_RULE_ENABLED
)
1218 (void) fprintf(fp
, "-e ");
1219 if (rd
->r_flags
& ILB_FLAGS_RULE_STICKY
)
1220 (void) fprintf(fp
, "-p ");
1222 ip2str(&rd
->r_vip
, linebuf
, sz
, V6_ADDRONLY
);
1223 (void) fprintf(fp
, "-i vip=%s,", linebuf
);
1225 (void) ports2str(ntohs(rd
->r_minport
), ntohs(rd
->r_maxport
),
1227 (void) fprintf(fp
, "%s,", linebuf
);
1229 proto2str(rd
->r_proto
, linebuf
, sz
);
1230 (void) fprintf(fp
, "%s ", linebuf
);
1232 algo2str(rd
->r_algo
, linebuf
, sz
);
1233 (void) fprintf(fp
, "-m %s,", linebuf
);
1235 topo2str(rd
->r_topo
, linebuf
, sz
);
1236 (void) fprintf(fp
, "%s", linebuf
);
1238 if (rd
->r_nat_src_start
.ia_af
!= AF_UNSPEC
) {
1239 ip2str(&rd
->r_nat_src_start
, linebuf
, sz
, V6_ADDRONLY
);
1240 /* if the address is unspecified, skip it */
1241 if (linebuf
[0] != '\0') {
1242 (void) fprintf(fp
, ",proxy-src=%s", linebuf
);
1243 ip2str(&rd
->r_nat_src_end
, linebuf
, sz
, V6_ADDRONLY
);
1244 (void) fprintf(fp
, "-%s", linebuf
);
1248 if (rd
->r_flags
& ILB_FLAGS_RULE_STICKY
) {
1249 (void) fprintf(fp
, ",pmask=/%d",
1250 ilbadm_mask_to_prefixlen(&rd
->r_stickymask
));
1253 (void) fprintf(fp
, " ");
1255 if (*rd
->r_hcname
!= '\0') {
1256 (void) fprintf(fp
, "-h hc-name=%s", rd
->r_hcname
);
1257 hcport_print(rd
, linebuf
, sizeof (linebuf
));
1259 if (linebuf
[0] != '\0')
1260 (void) fprintf(fp
, ",hc-port=%s", linebuf
);
1261 (void) fprintf(fp
, " ");
1264 conndrain
= rd
->r_conndrain
;
1265 nat_timeout
= rd
->r_nat_timeout
;
1266 sticky_timeout
= rd
->r_sticky_timeout
;
1267 if (conndrain
!= 0 || nat_timeout
!= 0 || sticky_timeout
!= 0) {
1270 (void) fprintf(fp
, "-t ");
1271 if (conndrain
!= 0) {
1273 (void) fprintf(fp
, "conn-drain=%u", conndrain
);
1275 if (nat_timeout
!= 0) {
1277 (void) fprintf(fp
, ",");
1279 (void) fprintf(fp
, "nat-timeout=%u", nat_timeout
);
1281 if (sticky_timeout
!= 0) {
1283 (void) fprintf(fp
, ",");
1284 (void) fprintf(fp
, "persist-timeout=%u",
1287 (void) fprintf(fp
, " ");
1290 if (fprintf(fp
, "-o servergroup=%s %s\n", rd
->r_sgname
, rd
->r_name
)
1291 < 0 || fflush(fp
) == EOF
)
1292 return (ILB_STATUS_WRITE
);
1294 return (ILB_STATUS_OK
);
1298 ilbadm_export_rules(ilb_handle_t h
, FILE *fp
)
1301 ilbadm_status_t rc
= ILBADM_OK
;
1302 ilbadm_rl_exp_arg_t arg
;
1306 rclib
= ilb_walk_rules(h
, ilbadm_export_rl
, NULL
, (void *)&arg
);
1307 if (rclib
!= ILB_STATUS_OK
)