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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
41 #include "libilb_impl.h"
44 /* until we all use AF_* macros ... */
45 #define AF_2_IPPROTO(_af) (_af == AF_INET)?IPPROTO_IP:IPPROTO_IPV6
46 #define IPPROTO_2_AF(_i) (_i == IPPROTO_IP)?AF_INET:AF_INET6
48 #define PROTOCOL_LEN 16 /* protocol type */
49 #define ADDR_LEN (2 * INET6_ADDRSTRLEN + 1) /* prxy src range */
50 #define PORT_LEN 6 /* hcport:1-65535 or "ANY" */
52 static ilb_status_t
ilbd_disable_one_rule(ilbd_rule_t
*, boolean_t
);
53 static uint32_t i_flags_d2k(int);
55 #define ILB_SGSRV_2_KSRV(s, k) \
56 (k)->addr = (s)->sgs_addr; \
57 (k)->min_port = (s)->sgs_minport; \
58 (k)->max_port = (s)->sgs_maxport; \
59 (k)->flags = i_flags_d2k((s)->sgs_flags); \
61 (void) strlcpy((k)->name, (s)->sgs_srvID, sizeof ((k)->name))
63 list_t ilbd_rule_hlist
;
66 algo_impl2lib(ilb_algo_impl_t a
)
69 case ILB_ALG_IMPL_ROUNDROBIN
:
70 return (ILB_ALG_ROUNDROBIN
);
71 case ILB_ALG_IMPL_HASH_IP
:
72 return (ILB_ALG_HASH_IP
);
73 case ILB_ALG_IMPL_HASH_IP_SPORT
:
74 return (ILB_ALG_HASH_IP_SPORT
);
75 case ILB_ALG_IMPL_HASH_IP_VIP
:
76 return (ILB_ALG_HASH_IP_VIP
);
82 topo_impl2lib(ilb_topo_impl_t t
)
85 case ILB_TOPO_IMPL_DSR
:
86 return (ILB_TOPO_DSR
);
87 case ILB_TOPO_IMPL_NAT
:
88 return (ILB_TOPO_NAT
);
89 case ILB_TOPO_IMPL_HALF_NAT
:
90 return (ILB_TOPO_HALF_NAT
);
96 algo_lib2impl(ilb_algo_t a
)
99 case ILB_ALG_ROUNDROBIN
:
100 return (ILB_ALG_IMPL_ROUNDROBIN
);
101 case ILB_ALG_HASH_IP
:
102 return (ILB_ALG_IMPL_HASH_IP
);
103 case ILB_ALG_HASH_IP_SPORT
:
104 return (ILB_ALG_IMPL_HASH_IP_SPORT
);
105 case ILB_ALG_HASH_IP_VIP
:
106 return (ILB_ALG_IMPL_HASH_IP_VIP
);
112 topo_lib2impl(ilb_topo_t t
)
116 return (ILB_TOPO_IMPL_DSR
);
118 return (ILB_TOPO_IMPL_NAT
);
119 case ILB_TOPO_HALF_NAT
:
120 return (ILB_TOPO_IMPL_HALF_NAT
);
126 * Walk the list of rules and check if its safe to add the
127 * the server to the rule (this is a list of rules hanging
128 * off of a server group)
131 i_check_srv2rules(list_t
*rlist
, ilb_sg_srv_t
*srv
)
133 ilb_status_t rc
= ILB_STATUS_OK
;
135 int server_portrange
, rule_portrange
;
136 int srv_minport
, srv_maxport
;
137 int r_minport
, r_maxport
;
140 return (ILB_STATUS_OK
);
142 srv_minport
= ntohs(srv
->sgs_minport
);
143 srv_maxport
= ntohs(srv
->sgs_maxport
);
145 for (rl
= list_head(rlist
); rl
!= NULL
; rl
= list_next(rlist
, rl
)) {
146 r_minport
= ntohs(rl
->irl_minport
);
147 r_maxport
= ntohs(rl
->irl_maxport
);
149 if ((srv_minport
!= 0) && (srv_minport
== srv_maxport
)) {
150 /* server has single port */
151 if (rl
->irl_topo
== ILB_TOPO_DSR
) {
153 * either we have a DSR rule with a port
154 * range, or both server and rule
155 * have single ports but their values
156 * don't match - this is incompatible
158 if (r_maxport
> r_minport
) {
159 rc
= ILB_STATUS_INVAL_SRVR
;
161 } else if (srv_minport
!= r_minport
) {
162 rc
= ILB_STATUS_BADPORT
;
166 if (rl
->irl_hcpflag
== ILB_HCI_PROBE_FIX
&&
167 rl
->irl_hcport
!= srv_minport
) {
168 rc
= ILB_STATUS_BADPORT
;
171 } else if (srv_maxport
> srv_minport
) {
172 /* server has a port range */
173 if ((rl
->irl_topo
== ILB_TOPO_DSR
) &&
174 (r_maxport
> r_minport
)) {
175 if ((r_minport
!= srv_minport
) ||
176 (r_maxport
!= srv_maxport
)) {
178 * we have a DSR rule with a port range
179 * and its min and max port values
180 * does not meet that of server's
181 * - this is incompatible
183 rc
= ILB_STATUS_BADPORT
;
186 } else if ((rl
->irl_topo
== ILB_TOPO_DSR
) &&
187 (r_maxport
== r_minport
)) {
189 * we have a DSR rule with a single
190 * port and a server with a port range
191 * - this is incompatible
193 rc
= ILB_STATUS_INVAL_SRVR
;
195 } else if (((rl
->irl_topo
== ILB_TOPO_NAT
) ||
196 (rl
->irl_topo
== ILB_TOPO_HALF_NAT
)) &&
197 (r_maxport
> r_minport
)) {
198 server_portrange
= srv_maxport
- srv_minport
;
199 rule_portrange
= r_maxport
- r_minport
;
200 if (rule_portrange
!= server_portrange
) {
202 * we have a NAT/Half-NAT rule with
203 * a port range and server with a port
204 * range and there is a mismatch in the
205 * sizes of the port ranges - this is
208 rc
= ILB_STATUS_INVAL_SRVR
;
212 if (rl
->irl_hcpflag
== ILB_HCI_PROBE_FIX
&&
213 (rl
->irl_hcport
> srv_maxport
||
214 rl
->irl_hcport
< srv_minport
)) {
215 rc
= ILB_STATUS_BADPORT
;
225 i_setup_rule_hlist(void)
227 list_create(&ilbd_rule_hlist
, sizeof (ilbd_rule_t
),
228 offsetof(ilbd_rule_t
, irl_link
));
232 i_ilbd_save_rule(ilbd_rule_t
*irl
, ilbd_scf_cmd_t scf_cmd
)
234 boolean_t enable
= irl
->irl_flags
& ILB_FLAGS_RULE_ENABLED
;
237 case ILBD_SCF_CREATE
:
238 return (ilbd_create_pg(ILBD_SCF_RULE
, (void *)irl
));
239 case ILBD_SCF_DESTROY
:
240 return (ilbd_destroy_pg(ILBD_SCF_RULE
, irl
->irl_name
));
241 case ILBD_SCF_ENABLE_DISABLE
:
242 return (ilbd_change_prop(ILBD_SCF_RULE
, irl
->irl_name
,
245 logdebug("i_ilbd_save_rule: invalid scf cmd %d", scf_cmd
);
246 return (ILB_STATUS_INVAL_CMD
);
251 * allocate a new daemon-specific rule from the "template" passed
255 i_alloc_ilbd_rule(ilb_rule_info_t
*r
)
259 rl
= calloc(sizeof (*rl
), 1);
260 if (rl
!= NULL
&& r
!= NULL
)
261 bcopy(r
, &rl
->irl_info
, sizeof (*r
));
267 i_find_rule_byname(const char *name
)
271 /* find position of rule in list */
272 rl
= list_head(&ilbd_rule_hlist
);
274 strncmp(rl
->irl_name
, name
, sizeof (rl
->irl_name
)) != 0) {
275 rl
= list_next(&ilbd_rule_hlist
, rl
);
282 * get exactly one rule (named in rl->irl_name) data from kernel
285 ilb_get_krule(ilb_rule_info_t
*rl
)
290 kcmd
.cmd
= ILB_LIST_RULE
;
291 (void) strlcpy(kcmd
.name
, rl
->rl_name
, sizeof (kcmd
.name
));
294 rc
= do_ioctl(&kcmd
, 0);
295 if (rc
!= ILB_STATUS_OK
)
298 rl
->rl_flags
= kcmd
.flags
;
299 rl
->rl_ipversion
= IPPROTO_2_AF(kcmd
.ip_ver
);
300 rl
->rl_vip
= kcmd
.vip
;
301 rl
->rl_proto
= kcmd
.proto
;
302 rl
->rl_minport
= kcmd
.min_port
;
303 rl
->rl_maxport
= kcmd
.max_port
;
304 rl
->rl_algo
= algo_impl2lib(kcmd
.algo
);
305 rl
->rl_topo
= topo_impl2lib(kcmd
.topo
);
306 rl
->rl_stickymask
= kcmd
.sticky_mask
;
307 rl
->rl_nat_src_start
= kcmd
.nat_src_start
;
308 rl
->rl_nat_src_end
= kcmd
.nat_src_end
;
309 (void) strlcpy(rl
->rl_name
, kcmd
.name
, sizeof (rl
->rl_name
));
310 rl
->rl_conndrain
= kcmd
.conn_drain_timeout
;
311 rl
->rl_nat_timeout
= kcmd
.nat_expiry
;
312 rl
->rl_sticky_timeout
= kcmd
.sticky_expiry
;
314 return (ILB_STATUS_OK
);
318 ilbd_retrieve_rule(ilbd_name_t rl_name
, uint32_t *rbuf
, size_t *rbufsz
)
320 ilbd_rule_t
*irl
= NULL
;
322 ilb_rule_info_t
*rinfo
;
324 irl
= i_find_rule_byname(rl_name
);
326 return (ILB_STATUS_ENOENT
);
328 ilbd_reply_ok(rbuf
, rbufsz
);
329 rinfo
= (ilb_rule_info_t
*)&((ilb_comm_t
*)rbuf
)->ic_data
;
330 bcopy(&irl
->irl_info
, rinfo
, sizeof (*rinfo
));
333 * Check if the various timeout values are 0. If one is, get the
334 * default values from kernel.
336 if (rinfo
->rl_conndrain
== 0 || rinfo
->rl_nat_timeout
== 0 ||
337 rinfo
->rl_sticky_timeout
== 0) {
338 ilb_rule_info_t tmp_info
;
340 (void) strcpy(tmp_info
.rl_name
, rinfo
->rl_name
);
341 rc
= ilb_get_krule(&tmp_info
);
342 if (rc
!= ILB_STATUS_OK
)
344 if (rinfo
->rl_conndrain
== 0)
345 rinfo
->rl_conndrain
= tmp_info
.rl_conndrain
;
346 if ((rinfo
->rl_topo
== ILB_TOPO_NAT
||
347 rinfo
->rl_topo
== ILB_TOPO_HALF_NAT
) &&
348 rinfo
->rl_nat_timeout
== 0) {
349 rinfo
->rl_nat_timeout
= tmp_info
.rl_nat_timeout
;
351 if ((rinfo
->rl_flags
& ILB_FLAGS_RULE_STICKY
) &&
352 rinfo
->rl_sticky_timeout
== 0) {
353 rinfo
->rl_sticky_timeout
= tmp_info
.rl_sticky_timeout
;
356 *rbufsz
+= sizeof (ilb_rule_info_t
);
358 return (ILB_STATUS_OK
);
362 ilbd_destroy_one_rule(ilbd_rule_t
*irl
)
368 * as far as talking to the kernel is concerned, "all rules"
369 * is handled in one go somewhere else, so we only
370 * tell the kernel about single rules here.
372 if ((irl
->irl_flags
& ILB_FLAGS_RULE_ALLRULES
) == 0) {
373 kcmd
.cmd
= ILB_DESTROY_RULE
;
374 (void) strlcpy(kcmd
.name
, irl
->irl_name
, sizeof (kcmd
.name
));
377 rc
= do_ioctl(&kcmd
, 0);
378 if (rc
!= ILB_STATUS_OK
)
382 list_remove(&irl
->irl_sg
->isg_rulelist
, irl
);
383 list_remove(&ilbd_rule_hlist
, irl
);
386 * When dissociating a rule, only two errors can happen. The hc
387 * name is incorrect or the rule is not associated with the hc
388 * object. Both should not happen.... The check is for debugging
391 if (RULE_HAS_HC(irl
) && (rc
= ilbd_hc_dissociate_rule(irl
)) !=
393 logerr("ilbd_destroy_one_rule: cannot "
394 "dissociate %s from hc object %s: %d",
395 irl
->irl_name
, irl
->irl_hcname
, rc
);
398 rc
= i_ilbd_save_rule(irl
, ILBD_SCF_DESTROY
);
399 if (rc
!= ILB_STATUS_OK
)
400 logdebug("ilbd_destroy_rule: save rule failed");
407 * the following two functions are the other's opposite, and can
408 * call into each other for roll back purposes in case of error.
409 * To avoid endless recursion, the 'is_rollback' parameter must be
410 * set to B_TRUE in the roll back case.
413 ilbd_enable_one_rule(ilbd_rule_t
*irl
, boolean_t is_rollback
)
415 ilb_status_t rc
= ILB_STATUS_OK
;
418 /* no use sending a no-op to the kernel */
419 if ((irl
->irl_flags
& ILB_FLAGS_RULE_ENABLED
) != 0)
420 return (ILB_STATUS_OK
);
422 irl
->irl_flags
|= ILB_FLAGS_RULE_ENABLED
;
424 /* "all rules" is handled in one go somewhere else, not here */
425 if ((irl
->irl_flags
& ILB_FLAGS_RULE_ALLRULES
) == 0) {
426 kcmd
.cmd
= ILB_ENABLE_RULE
;
427 (void) strlcpy(kcmd
.name
, irl
->irl_name
, sizeof (kcmd
.name
));
430 rc
= do_ioctl(&kcmd
, 0);
431 if (rc
!= ILB_STATUS_OK
)
434 if (RULE_HAS_HC(irl
) && (rc
= ilbd_hc_enable_rule(irl
)) !=
436 /* Undo the kernel work */
437 kcmd
.cmd
= ILB_DISABLE_RULE
;
438 /* Cannot do much if ioctl fails... */
439 (void) do_ioctl(&kcmd
, 0);
444 if (rc
== ILB_STATUS_OK
)
445 rc
= i_ilbd_save_rule(irl
, ILBD_SCF_ENABLE_DISABLE
);
446 if (rc
!= ILB_STATUS_OK
)
447 /* ignore rollback return code */
448 (void) ilbd_disable_one_rule(irl
, B_TRUE
);
455 ilbd_disable_one_rule(ilbd_rule_t
*irl
, boolean_t is_rollback
)
457 ilb_status_t rc
= ILB_STATUS_OK
;
460 /* no use sending a no-op to the kernel */
461 if ((irl
->irl_flags
& ILB_FLAGS_RULE_ENABLED
) == 0)
462 return (ILB_STATUS_OK
);
464 irl
->irl_flags
&= ~ILB_FLAGS_RULE_ENABLED
;
466 /* "all rules" is handled in one go somewhere else, not here */
467 if ((irl
->irl_flags
& ILB_FLAGS_RULE_ALLRULES
) == 0) {
468 kcmd
.cmd
= ILB_DISABLE_RULE
;
469 (void) strlcpy(kcmd
.name
, irl
->irl_name
, sizeof (kcmd
.name
));
472 rc
= do_ioctl(&kcmd
, 0);
473 if (rc
!= ILB_STATUS_OK
)
477 if (RULE_HAS_HC(irl
) && (rc
= ilbd_hc_disable_rule(irl
)) !=
479 /* Undo the kernel work */
480 kcmd
.cmd
= ILB_ENABLE_RULE
;
481 /* Cannot do much if ioctl fails... */
482 (void) do_ioctl(&kcmd
, 0);
487 if (rc
== ILB_STATUS_OK
)
488 rc
= i_ilbd_save_rule(irl
, ILBD_SCF_ENABLE_DISABLE
);
489 if (rc
!= ILB_STATUS_OK
)
490 /* ignore rollback return code */
491 (void) ilbd_enable_one_rule(irl
, B_TRUE
);
498 * Generates an audit record for a supplied rule name
499 * Used for enable_rule, disable_rule, delete_rule,
500 * and create_rule subcommands
503 ilbd_audit_rule_event(const char *audit_rule_name
,
504 ilb_rule_info_t
*rlinfo
, ilbd_cmd_t cmd
, ilb_status_t rc
,
507 adt_session_data_t
*ah
;
508 adt_event_data_t
*event
;
510 int scf_val_len
= ILBD_MAX_VALUE_LEN
;
511 char *aobuf
= NULL
; /* algo:topo */
512 char *valstr1
= NULL
;
513 char *valstr2
= NULL
;
514 char pbuf
[PROTOCOL_LEN
]; /* protocol */
515 char hcpbuf
[PORT_LEN
]; /* hcport */
518 if ((ucredp
== NULL
) && (cmd
== ILBD_CREATE_RULE
)) {
520 * we came here from the path where ilbd incorporates
521 * the configuration that is listed in SCF :
522 * i_ilbd_read_config->ilbd_walk_rule_pgs->
523 * ->ilbd_scf_instance_walk_pg->ilbd_create_rule
524 * We skip auditing in that case
528 if (adt_start_session(&ah
, NULL
, 0) != 0) {
529 logerr("ilbd_audit_rule_event: adt_start_session failed");
532 if (adt_set_from_ucred(ah
, ucredp
, ADT_NEW
) != 0) {
533 (void) adt_end_session(ah
);
534 logerr("ilbd_audit_rule_event: adt_set_from_ucred failed");
537 if (cmd
== ILBD_ENABLE_RULE
)
538 flag
= ADT_ilb_enable_rule
;
539 else if (cmd
== ILBD_DISABLE_RULE
)
540 flag
= ADT_ilb_disable_rule
;
541 else if (cmd
== ILBD_DESTROY_RULE
)
542 flag
= ADT_ilb_delete_rule
;
543 else if (cmd
== ILBD_CREATE_RULE
)
544 flag
= ADT_ilb_create_rule
;
546 if ((event
= adt_alloc_event(ah
, flag
)) == NULL
) {
547 logerr("ilbd_audit_rule_event: adt_alloc_event failed");
551 (void) memset((char *)event
, 0, sizeof (adt_event_data_t
));
554 case ILBD_DESTROY_RULE
:
555 event
->adt_ilb_delete_rule
.auth_used
= NET_ILB_CONFIG_AUTH
;
556 event
->adt_ilb_delete_rule
.rule_name
= (char *)audit_rule_name
;
558 case ILBD_ENABLE_RULE
:
559 event
->adt_ilb_enable_rule
.auth_used
= NET_ILB_ENABLE_AUTH
;
560 event
->adt_ilb_enable_rule
.rule_name
= (char *)audit_rule_name
;
562 case ILBD_DISABLE_RULE
:
563 event
->adt_ilb_disable_rule
.auth_used
= NET_ILB_ENABLE_AUTH
;
564 event
->adt_ilb_disable_rule
.rule_name
= (char *)audit_rule_name
;
566 case ILBD_CREATE_RULE
:
567 if (((aobuf
= malloc(scf_val_len
)) == NULL
) ||
568 ((valstr1
= malloc(scf_val_len
)) == NULL
) ||
569 ((valstr2
= malloc(scf_val_len
)) == NULL
)) {
570 logerr("ilbd_audit_rule_event: could not"
575 event
->adt_ilb_create_rule
.auth_used
= NET_ILB_CONFIG_AUTH
;
577 /* Fill in virtual IP address type */
578 if (IN6_IS_ADDR_V4MAPPED(&rlinfo
->rl_vip
)) {
579 event
->adt_ilb_create_rule
.virtual_ipaddress_type
=
581 cvt_addr(event
->adt_ilb_create_rule
.virtual_ipaddress
,
582 ADT_IPv4
, rlinfo
->rl_vip
);
584 event
->adt_ilb_create_rule
.virtual_ipaddress_type
=
586 cvt_addr(event
->adt_ilb_create_rule
.virtual_ipaddress
,
587 ADT_IPv6
, rlinfo
->rl_vip
);
589 /* Fill in port - could be a single value or a range */
590 event
->adt_ilb_create_rule
.min_port
= ntohs(rlinfo
->rl_minport
);
591 if (ntohs(rlinfo
->rl_maxport
) > ntohs(rlinfo
->rl_minport
)) {
593 event
->adt_ilb_create_rule
.max_port
=
594 ntohs(rlinfo
->rl_maxport
);
596 /* in audit record, max=min when single port */
597 event
->adt_ilb_create_rule
.max_port
=
598 ntohs(rlinfo
->rl_minport
);
602 * Fill in protocol - if user does not specify it,
605 if (rlinfo
->rl_proto
== IPPROTO_UDP
)
606 (void) snprintf(pbuf
, PROTOCOL_LEN
, "UDP");
608 (void) snprintf(pbuf
, PROTOCOL_LEN
, "TCP");
609 event
->adt_ilb_create_rule
.protocol
= pbuf
;
611 /* Fill in algorithm and operation type */
612 ilbd_algo_to_str(rlinfo
->rl_algo
, valstr1
);
613 ilbd_topo_to_str(rlinfo
->rl_topo
, valstr2
);
614 (void) snprintf(aobuf
, scf_val_len
, "%s:%s",
616 event
->adt_ilb_create_rule
.algo_optype
= aobuf
;
618 /* Fill in proxy-src for the NAT case */
619 if (rlinfo
->rl_topo
== ILB_TOPO_NAT
) {
620 /* copy starting proxy-src address */
621 if (IN6_IS_ADDR_V4MAPPED(&rlinfo
->rl_nat_src_start
)) {
623 event
->adt_ilb_create_rule
.proxy_src_min_type
=
626 event
->adt_ilb_create_rule
.proxy_src_min
,
627 ADT_IPv4
, rlinfo
->rl_nat_src_start
);
630 event
->adt_ilb_create_rule
.proxy_src_min_type
=
633 event
->adt_ilb_create_rule
.proxy_src_min
,
634 ADT_IPv6
, rlinfo
->rl_nat_src_start
);
637 /* copy ending proxy-src address */
638 if (&rlinfo
->rl_nat_src_end
== 0) {
639 /* proxy-src is a single address */
640 event
->adt_ilb_create_rule
.proxy_src_max_type
=
642 adt_ilb_create_rule
.proxy_src_min_type
;
644 event
->adt_ilb_create_rule
.proxy_src_max
,
645 event
->adt_ilb_create_rule
.proxy_src_min
,
646 (4 * sizeof (uint32_t)));
648 IN6_IS_ADDR_V4MAPPED(&rlinfo
->rl_nat_src_end
)) {
650 * proxy-src is a address range - copy ending
654 event
->adt_ilb_create_rule
.proxy_src_max_type
=
657 event
->adt_ilb_create_rule
.proxy_src_max
,
658 ADT_IPv4
, rlinfo
->rl_nat_src_end
);
661 event
->adt_ilb_create_rule
.proxy_src_max_type
=
664 event
->adt_ilb_create_rule
.proxy_src_max
,
665 ADT_IPv6
, rlinfo
->rl_nat_src_end
);
670 * Fill in pmask if user has specified one - 0 means
674 ilbd_ip_to_str(rlinfo
->rl_ipversion
, &rlinfo
->rl_stickymask
,
676 event
->adt_ilb_create_rule
.persist_mask
= valstr1
;
678 /* If there is a hcname */
679 if (rlinfo
->rl_hcname
[0] != '\0')
680 event
->adt_ilb_create_rule
.hcname
= rlinfo
->rl_hcname
;
683 if (rlinfo
->rl_hcpflag
== ILB_HCI_PROBE_FIX
) {
684 /* hcport is specified by user */
685 (void) snprintf(hcpbuf
, PORT_LEN
, "%d",
687 event
->adt_ilb_create_rule
.hcport
= hcpbuf
;
688 } else if (rlinfo
->rl_hcpflag
== ILB_HCI_PROBE_ANY
) {
689 /* user has specified "ANY" */
690 (void) snprintf(hcpbuf
, PORT_LEN
, "ANY");
691 event
->adt_ilb_create_rule
.hcport
= hcpbuf
;
694 * Fill out the conndrain, nat_timeout and persist_timeout
695 * If the user does not specify them, the default value
696 * is set in the kernel. Userland does not know what
697 * the values are. So if the user
698 * does not specify these values they will show up as
699 * 0 in the audit record.
701 event
->adt_ilb_create_rule
.conndrain_timeout
=
702 rlinfo
->rl_conndrain
;
703 event
->adt_ilb_create_rule
.nat_timeout
=
704 rlinfo
->rl_nat_timeout
;
705 event
->adt_ilb_create_rule
.persist_timeout
=
706 rlinfo
->rl_sticky_timeout
;
708 /* Fill out servergroup and rule name */
709 event
->adt_ilb_create_rule
.server_group
= rlinfo
->rl_sgname
;
710 event
->adt_ilb_create_rule
.rule_name
= rlinfo
->rl_name
;
713 if (rc
== ILB_STATUS_OK
) {
714 if (adt_put_event(event
, ADT_SUCCESS
, ADT_SUCCESS
) != 0) {
715 logerr("ilbd_audit_rule_event:adt_put_event failed");
719 audit_error
= ilberror2auditerror(rc
);
720 if (adt_put_event(event
, ADT_FAILURE
, audit_error
) != 0) {
721 logerr("ilbd_audit_rule_event: adt_put_event failed");
725 adt_free_event(event
);
729 (void) adt_end_session(ah
);
732 * converts IP address from in6_addr format to uint32_t[4]
733 * This conversion is needed for recording IP address in
737 cvt_addr(uint32_t *audit
, int32_t type
, struct in6_addr address
)
740 if (type
== ADT_IPv4
) {
741 /* address is IPv4 */
742 audit
[0] = address
._S6_un
._S6_u32
[3];
744 /* address is IPv6 */
745 (void) memcpy(audit
, address
._S6_un
._S6_u32
,
746 (4 * sizeof (uint32_t)));
751 i_ilbd_action_switch(ilbd_rule_t
*irl
, ilbd_cmd_t cmd
,
752 boolean_t is_rollback
, ucred_t
*ucredp
)
757 case ILBD_DESTROY_RULE
:
758 rc
= ilbd_destroy_one_rule(irl
);
760 ilbd_audit_rule_event(irl
->irl_name
, NULL
,
764 case ILBD_ENABLE_RULE
:
765 rc
= ilbd_enable_one_rule(irl
, is_rollback
);
767 ilbd_audit_rule_event(irl
->irl_name
, NULL
, cmd
,
771 case ILBD_DISABLE_RULE
:
772 rc
= ilbd_disable_one_rule(irl
, is_rollback
);
774 ilbd_audit_rule_event(irl
->irl_name
, NULL
, cmd
,
779 return (ILB_STATUS_INVAL_CMD
);
783 i_ilbd2ilb_cmd(ilbd_cmd_t c
)
788 case ILBD_CREATE_RULE
:
791 case ILBD_DESTROY_RULE
:
792 r
= ILB_DESTROY_RULE
;
794 case ILBD_ENABLE_RULE
:
797 case ILBD_DISABLE_RULE
:
798 r
= ILB_DISABLE_RULE
;
805 get_undo_cmd(ilbd_cmd_t cmd
)
810 case ILBD_DESTROY_RULE
:
811 u_cmd
= ILBD_BAD_CMD
;
813 case ILBD_ENABLE_RULE
:
814 u_cmd
= ILBD_DISABLE_RULE
;
816 case ILBD_DISABLE_RULE
:
817 u_cmd
= ILBD_ENABLE_RULE
;
825 i_ilbd_rule_action(const char *rule_name
, const struct passwd
*ps
,
826 ilbd_cmd_t cmd
, ucred_t
*ucredp
)
828 ilbd_rule_t
*irl
, *irl_next
;
829 boolean_t is_all_rules
= B_FALSE
;
830 ilb_status_t rc
= ILB_STATUS_OK
;
833 char rulename
[ILB_NAMESZ
];
836 if ((cmd
== ILBD_ENABLE_RULE
) || (cmd
== ILBD_DISABLE_RULE
))
837 rc
= ilbd_check_client_enable_auth(ps
);
839 rc
= ilbd_check_client_config_auth(ps
);
840 /* generate the audit record before bailing out */
841 if (rc
!= ILB_STATUS_OK
) {
842 if (rule_name
!= '\0') {
843 ilbd_audit_rule_event(rule_name
, NULL
,
846 (void) snprintf(rulename
, sizeof (rulename
),
848 ilbd_audit_rule_event(rulename
, NULL
, cmd
, rc
,
854 is_all_rules
= rule_name
[0] == 0;
858 irl
= i_find_rule_byname(rule_name
);
860 rc
= ILB_STATUS_ENORULE
;
861 ilbd_audit_rule_event(rule_name
, NULL
, cmd
, rc
, ucredp
);
864 /* auditing will be done by i_ilbd_action_switch() */
865 rc
= i_ilbd_action_switch(irl
, cmd
, B_FALSE
, ucredp
);
869 /* all rules: first tell the kernel, then walk the daemon's list */
870 kcmd
.cmd
= i_ilbd2ilb_cmd(cmd
);
871 kcmd
.flags
= ILB_RULE_ALLRULES
;
873 rc
= do_ioctl(&kcmd
, 0);
874 if (rc
!= ILB_STATUS_OK
) {
875 (void) snprintf(rulename
, sizeof (rulename
), "all");
876 ilbd_audit_rule_event(rulename
, NULL
, cmd
, rc
, ucredp
);
880 irl
= list_head(&ilbd_rule_hlist
);
881 while (irl
!= NULL
) {
882 irl_next
= list_next(&ilbd_rule_hlist
, irl
);
883 irl
->irl_flags
|= ILB_FLAGS_RULE_ALLRULES
;
884 /* auditing will be done by i_ilbd_action_switch() */
885 rc
= i_ilbd_action_switch(irl
, cmd
, B_FALSE
, ucredp
);
886 irl
->irl_flags
&= ~ILB_FLAGS_RULE_ALLRULES
;
887 if (rc
!= ILB_STATUS_OK
)
894 u_cmd
= get_undo_cmd(cmd
);
895 if (u_cmd
== ILBD_BAD_CMD
)
899 kcmd
.cmd
= i_ilbd2ilb_cmd(u_cmd
);
900 (void) do_ioctl(&kcmd
, 0);
902 /* current list element failed, so we start with previous one */
903 irl
= list_prev(&ilbd_rule_hlist
, irl
);
904 while (irl
!= NULL
) {
906 irl
->irl_flags
|= ILB_FLAGS_RULE_ALLRULES
;
909 * When the processing of a command consists of
910 * multiple sequential steps, and one of them fails,
911 * ilbd performs rollback to undo the steps taken before the
912 * failing step. Since ilbd is initiating these steps
913 * there is not need to audit them.
915 rc
= i_ilbd_action_switch(irl
, u_cmd
, B_TRUE
, NULL
);
916 irl
->irl_flags
&= ~ILB_FLAGS_RULE_ALLRULES
;
918 irl
= list_prev(&ilbd_rule_hlist
, irl
);
925 ilbd_destroy_rule(ilbd_name_t rule_name
, const struct passwd
*ps
,
928 return (i_ilbd_rule_action(rule_name
, ps
, ILBD_DESTROY_RULE
, ucredp
));
932 ilbd_enable_rule(ilbd_name_t rule_name
, const struct passwd
*ps
,
935 return (i_ilbd_rule_action(rule_name
, ps
, ILBD_ENABLE_RULE
, ucredp
));
940 ilbd_disable_rule(ilbd_name_t rule_name
, const struct passwd
*ps
,
943 return (i_ilbd_rule_action(rule_name
, ps
, ILBD_DISABLE_RULE
, ucredp
));
947 * allocate storage for a kernel rule command and fill from
948 * "template" irl, if non-NULL
950 static ilb_rule_cmd_t
*
951 i_alloc_kernel_rule_cmd(ilbd_rule_t
*irl
)
953 ilb_rule_cmd_t
*kcmd
;
955 kcmd
= (ilb_rule_cmd_t
*)malloc(sizeof (*kcmd
));
959 bzero(kcmd
, sizeof (*kcmd
));
962 kcmd
->flags
= irl
->irl_flags
;
963 kcmd
->ip_ver
= AF_2_IPPROTO(irl
->irl_ipversion
);
964 kcmd
->vip
= irl
->irl_vip
;
965 kcmd
->proto
= irl
->irl_proto
;
966 kcmd
->min_port
= irl
->irl_minport
;
967 kcmd
->max_port
= irl
->irl_maxport
;
968 kcmd
->algo
= algo_lib2impl(irl
->irl_algo
);
969 kcmd
->topo
= topo_lib2impl(irl
->irl_topo
);
970 kcmd
->sticky_mask
= irl
->irl_stickymask
;
971 kcmd
->nat_src_start
= irl
->irl_nat_src_start
;
972 kcmd
->nat_src_end
= irl
->irl_nat_src_end
;
973 kcmd
->conn_drain_timeout
= irl
->irl_conndrain
;
974 kcmd
->nat_expiry
= irl
->irl_nat_timeout
;
975 kcmd
->sticky_expiry
= irl
->irl_sticky_timeout
;
976 (void) strlcpy(kcmd
->name
, irl
->irl_name
,
977 sizeof (kcmd
->name
));
983 * ncount is the next to be used index into (*kcmdp)->servers
986 adjust_srv_info_cmd(ilb_servers_info_cmd_t
**kcmdp
, int index
)
988 ilb_servers_info_cmd_t
*kcmd
= *kcmdp
;
991 if (kcmd
!= NULL
&& kcmd
->num_servers
> index
+ 1)
992 return (ILB_STATUS_OK
);
995 * the first ilb_server_info_t is part of *kcmd, so
996 * by using index (which is one less than the total needed) here,
997 * we allocate exactly the amount we need.
999 sz
= sizeof (*kcmd
) + (index
* sizeof (ilb_server_info_t
));
1000 kcmd
= (ilb_servers_info_cmd_t
*)realloc(kcmd
, sz
);
1002 return (ILB_STATUS_ENOMEM
);
1005 * we don't count the slot we newly allocated yet.
1007 kcmd
->num_servers
= index
;
1010 return (ILB_STATUS_OK
);
1014 * this function adds all servers in srvlist to the kernel(!) rule
1015 * the name of which is passed as argument.
1018 i_update_ksrv_rules(char *name
, ilbd_sg_t
*sg
, ilbd_rule_t
*rl
)
1022 ilb_servers_info_cmd_t
*kcmd
= NULL
;
1026 * If the servergroup doesn't have any servers associated with
1027 * it yet, there's nothing more to do here.
1029 if (sg
->isg_srvcount
== 0)
1030 return (ILB_STATUS_OK
);
1033 * walk the list of servers attached to this SG
1035 srvp
= list_head(&sg
->isg_srvlist
);
1036 for (i
= 0; srvp
!= NULL
; srvp
= list_next(&sg
->isg_srvlist
, srvp
)) {
1037 rc
= adjust_srv_info_cmd(&kcmd
, i
);
1038 if (rc
!= ILB_STATUS_OK
)
1041 ILB_SGSRV_2_KSRV(&srvp
->isv_srv
, &kcmd
->servers
[i
]);
1043 * "no port" means "copy rule's port" (for kernel rule)
1045 if (kcmd
->servers
[i
].min_port
== 0) {
1046 kcmd
->servers
[i
].min_port
= rl
->irl_minport
;
1047 kcmd
->servers
[i
].max_port
= rl
->irl_maxport
;
1051 assert(kcmd
!= NULL
);
1053 kcmd
->cmd
= ILB_ADD_SERVERS
;
1054 kcmd
->num_servers
= i
;
1055 (void) strlcpy(kcmd
->name
, name
, sizeof (kcmd
->name
));
1057 rc
= do_ioctl(kcmd
, 0);
1058 if (rc
!= ILB_STATUS_OK
)
1061 for (i
= 0; i
< kcmd
->num_servers
; i
++) {
1064 if ((e
= kcmd
->servers
[i
].err
) != 0) {
1065 logerr("i_update_ksrv_rules "
1066 "ioctl indicates failure: %s", strerror(e
));
1067 rc
= ilb_map_errno2ilbstat(e
);
1069 * if adding even a single server failed, we need to
1070 * roll back the whole wad. We ignore any errors and
1071 * return the one that was returned by the first ioctl.
1073 kcmd
->cmd
= ILB_DEL_SERVERS
;
1074 (void) do_ioctl(kcmd
, 0);
1084 /* convert a struct in6_addr to valstr */
1086 ilbd_ip_to_str(uint16_t ipversion
, struct in6_addr
*addr
, char *valstr
)
1089 ilb_ip_addr_t ipaddr
;
1092 vallen
= (ipversion
== AF_INET
) ? INET_ADDRSTRLEN
: INET6_ADDRSTRLEN
;
1094 IP_COPY_IMPL_2_CLI(addr
, &ipaddr
);
1095 addrptr
= (ipversion
== AF_INET
) ?
1096 (void *)&ipaddr
.ia_v4
: (void *)&ipaddr
.ia_v6
;
1097 if (inet_ntop(ipversion
, (void *)addrptr
, valstr
, vallen
== 0))
1098 logerr("ilbd_ip_to_str: inet_ntop failed");
1104 ilbd_create_rule(ilb_rule_info_t
*rl
, int ev_port
,
1105 const struct passwd
*ps
, ucred_t
*ucredp
)
1108 ilbd_rule_t
*irl
= NULL
;
1110 ilb_rule_cmd_t
*kcmd
= NULL
;
1113 if ((rc
= ilbd_check_client_config_auth(ps
)) != ILB_STATUS_OK
)
1117 if (i_find_rule_byname(rl
->rl_name
) != NULL
) {
1118 logdebug("ilbd_create_rule: rule %s"
1119 " already exists", rl
->rl_name
);
1120 ilbd_audit_rule_event(NULL
, rl
, ILBD_CREATE_RULE
,
1121 ILB_STATUS_DUP_RULE
, ucredp
);
1122 return (ILB_STATUS_DUP_RULE
);
1125 sg
= i_find_sg_byname(rl
->rl_sgname
);
1127 logdebug("ilbd_create_rule: rule %s uses non-existent"
1128 " servergroup name %s", rl
->rl_name
, rl
->rl_sgname
);
1129 ilbd_audit_rule_event(NULL
, rl
, ILBD_CREATE_RULE
,
1130 ILB_STATUS_SGUNAVAIL
, ucredp
);
1131 return (ILB_STATUS_SGUNAVAIL
);
1134 if ((rc
= ilbd_sg_check_rule_port(sg
, rl
)) != ILB_STATUS_OK
) {
1135 ilbd_audit_rule_event(NULL
, rl
, ILBD_CREATE_RULE
, rc
, ucredp
);
1139 /* allocs and copies contents of arg (if != NULL) into new rule */
1140 irl
= i_alloc_ilbd_rule(rl
);
1142 ilbd_audit_rule_event(NULL
, rl
, ILBD_CREATE_RULE
,
1143 ILB_STATUS_ENOMEM
, ucredp
);
1144 return (ILB_STATUS_ENOMEM
);
1147 /* make sure rule's IPversion (via vip) and SG's match */
1148 if (sg
->isg_srvcount
> 0) {
1149 ilbd_srv_t
*srv
= list_head(&sg
->isg_srvlist
);
1150 int32_t r_af
= rl
->rl_ipversion
;
1151 int32_t s_af
= GET_AF(&srv
->isv_addr
);
1154 logdebug("address family mismatch with servergroup");
1155 rc
= ILB_STATUS_MISMATCHSG
;
1161 /* Try associating the rule with the given hc oject. */
1162 if (RULE_HAS_HC(irl
)) {
1163 if ((rc
= ilbd_hc_associate_rule(irl
, ev_port
)) !=
1169 * checks are done, now:
1170 * 1. create rule in kernel
1171 * 2. tell it about the backend server (which we maintain in SG)
1172 * 3. attach the rule in memory
1175 /* allocs and copies contents of arg (if != NULL) into new rule */
1176 kcmd
= i_alloc_kernel_rule_cmd(irl
);
1178 rc
= ILB_STATUS_ENOMEM
;
1181 kcmd
->cmd
= ILB_CREATE_RULE
;
1183 rc
= do_ioctl(kcmd
, 0);
1184 if (rc
!= ILB_STATUS_OK
)
1188 rc
= i_update_ksrv_rules(kcmd
->name
, sg
, irl
);
1189 if (rc
!= ILB_STATUS_OK
)
1193 (void) i_attach_rule2sg(sg
, irl
);
1194 list_insert_tail(&ilbd_rule_hlist
, irl
);
1197 rc
= i_ilbd_save_rule(irl
, ILBD_SCF_CREATE
);
1198 if (rc
!= ILB_STATUS_OK
)
1203 ilbd_audit_rule_event(NULL
, rl
, ILBD_CREATE_RULE
,
1204 ILB_STATUS_OK
, ucredp
);
1205 return (ILB_STATUS_OK
);
1209 * ilbd_destroy_one_rule() also frees irl, as well as dissociate
1210 * rule and HC, so all we need to do afterwards is free the kcmd
1213 (void) ilbd_destroy_one_rule(irl
);
1214 ilbd_audit_rule_event(NULL
, rl
, ILBD_CREATE_RULE
, rc
, ucredp
);
1221 /* Cannot fail since the rule is just associated with the hc object. */
1222 if (RULE_HAS_HC(irl
))
1223 (void) ilbd_hc_dissociate_rule(irl
);
1225 ilbd_audit_rule_event(NULL
, rl
, ILBD_CREATE_RULE
, rc
, ucredp
);
1235 if (ILB_IS_SRV_ENABLED(f
))
1236 r
|= ILB_SERVER_ENABLED
;
1237 /* more as they are defined */
1243 * walk the list of rules and add srv to the *kernel* rule
1244 * (this is a list of rules hanging off of a server group)
1247 i_add_srv2krules(list_t
*rlist
, ilb_sg_srv_t
*srv
, int ev_port
)
1249 ilb_status_t rc
= ILB_STATUS_OK
;
1250 ilbd_rule_t
*rl
, *del_rl
;
1251 ilb_servers_info_cmd_t kcmd
;
1252 ilb_servers_cmd_t del_kcmd
;
1254 kcmd
.cmd
= ILB_ADD_SERVERS
;
1255 kcmd
.num_servers
= 1;
1256 kcmd
.servers
[0].err
= 0;
1257 kcmd
.servers
[0].addr
= srv
->sgs_addr
;
1258 kcmd
.servers
[0].flags
= i_flags_d2k(srv
->sgs_flags
);
1259 (void) strlcpy(kcmd
.servers
[0].name
, srv
->sgs_srvID
,
1260 sizeof (kcmd
.servers
[0].name
));
1263 * a note about rollback: since we need to start rollback with the
1264 * current list element in some case, and with the previous one
1265 * in others, we must "go back" in this latter case before
1266 * we jump to the rollback code.
1268 for (rl
= list_head(rlist
); rl
!= NULL
; rl
= list_next(rlist
, rl
)) {
1269 (void) strlcpy(kcmd
.name
, rl
->irl_name
, sizeof (kcmd
.name
));
1271 * sgs_minport == 0 means "no port specified"; this
1272 * indicates that the server matches anything the rule
1274 * NOTE: this can be different for different rules
1275 * using the same server group, therefore we don't modify
1276 * this information in the servergroup, but *only* in
1277 * the kernel's rule.
1279 if (srv
->sgs_minport
== 0) {
1280 kcmd
.servers
[0].min_port
= rl
->irl_minport
;
1281 kcmd
.servers
[0].max_port
= rl
->irl_maxport
;
1283 kcmd
.servers
[0].min_port
= srv
->sgs_minport
;
1284 kcmd
.servers
[0].max_port
= srv
->sgs_maxport
;
1286 rc
= do_ioctl((void *)&kcmd
, 0);
1287 if (rc
!= ILB_STATUS_OK
) {
1288 logdebug("i_add_srv2krules: do_ioctl call failed");
1289 del_rl
= list_prev(rlist
, rl
);
1294 * if ioctl() returns != 0, it doesn't perform the copyout
1295 * necessary to indicate *which* server failed (we could be
1296 * adding more than one); therefore we must check this
1297 * 'err' field even if ioctl() returns 0.
1299 if (kcmd
.servers
[0].err
!= 0) {
1300 logerr("i_add_srv2krules: SIOCILB ioctl returned"
1301 " error %d", kcmd
.servers
[0].err
);
1302 rc
= ilb_map_errno2ilbstat(kcmd
.servers
[0].err
);
1303 del_rl
= list_prev(rlist
, rl
);
1306 if (RULE_HAS_HC(rl
)) {
1307 if ((rc
= ilbd_hc_add_server(rl
, srv
, ev_port
)) !=
1309 logerr("i_add_srv2krules: cannot start timer "
1310 " for rules %s server %s", rl
->irl_name
,
1323 * this is almost, but not quite, the same as i_rem_srv_frm_krules()
1324 * therefore we keep it seperate.
1326 del_kcmd
.cmd
= ILB_DEL_SERVERS
;
1327 del_kcmd
.num_servers
= 1;
1328 del_kcmd
.servers
[0].addr
= srv
->sgs_addr
;
1329 while (del_rl
!= NULL
) {
1330 if (RULE_HAS_HC(del_rl
))
1331 (void) ilbd_hc_del_server(del_rl
, srv
);
1332 (void) strlcpy(del_kcmd
.name
, del_rl
->irl_name
,
1333 sizeof (del_kcmd
.name
));
1334 (void) do_ioctl((void *)&del_kcmd
, 0);
1335 del_rl
= list_prev(rlist
, del_rl
);
1342 * ev_port is only used for rollback purposes in this function
1345 i_rem_srv_frm_krules(list_t
*rlist
, ilb_sg_srv_t
*srv
, int ev_port
)
1347 ilb_status_t rc
= ILB_STATUS_OK
;
1348 ilbd_rule_t
*rl
, *add_rl
;
1349 ilb_servers_cmd_t kcmd
;
1350 ilb_servers_info_cmd_t add_kcmd
;
1352 kcmd
.cmd
= ILB_DEL_SERVERS
;
1353 kcmd
.num_servers
= 1;
1354 kcmd
.servers
[0].err
= 0;
1355 kcmd
.servers
[0].addr
= srv
->sgs_addr
;
1357 for (rl
= list_head(rlist
); rl
!= NULL
; rl
= list_next(rlist
, rl
)) {
1358 (void) strlcpy(kcmd
.name
, rl
->irl_name
, sizeof (kcmd
.name
));
1359 rc
= do_ioctl((void *)&kcmd
, 0);
1360 if (rc
!= ILB_STATUS_OK
) {
1361 logdebug("i_rem_srv_frm_krules: do_ioctl"
1363 add_rl
= list_prev(rlist
, rl
);
1367 * if ioctl() returns != 0, it doesn't perform the copyout
1368 * necessary to indicate *which* server failed (we could be
1369 * removing more than one); therefore we must check this
1370 * 'err' field even if ioctl() returns 0.
1372 if (kcmd
.servers
[0].err
!= 0) {
1373 logerr("i_rem_srv_frm_krules: SIOCILB ioctl"
1374 " returned error %s",
1375 strerror(kcmd
.servers
[0].err
));
1376 rc
= ilb_map_errno2ilbstat(kcmd
.servers
[0].err
);
1377 add_rl
= list_prev(rlist
, rl
);
1380 if (RULE_HAS_HC(rl
) &&
1381 (rc
= ilbd_hc_del_server(rl
, srv
)) != ILB_STATUS_OK
) {
1382 logerr("i_rem_srv_frm_krules: cannot delete "
1383 "timer for rules %s server %s", rl
->irl_name
,
1393 /* Don't do roll back if ev_port == -1. */
1397 add_kcmd
.cmd
= ILB_ADD_SERVERS
;
1398 add_kcmd
.num_servers
= 1;
1399 add_kcmd
.servers
[0].err
= 0;
1400 add_kcmd
.servers
[0].addr
= srv
->sgs_addr
;
1401 add_kcmd
.servers
[0].flags
= i_flags_d2k(srv
->sgs_flags
);
1402 (void) strlcpy(add_kcmd
.servers
[0].name
, srv
->sgs_srvID
,
1403 sizeof (add_kcmd
.servers
[0].name
));
1404 while (add_rl
!= NULL
) {
1405 if (srv
->sgs_minport
== 0) {
1406 add_kcmd
.servers
[0].min_port
= add_rl
->irl_minport
;
1407 add_kcmd
.servers
[0].max_port
= add_rl
->irl_maxport
;
1409 add_kcmd
.servers
[0].min_port
= srv
->sgs_minport
;
1410 add_kcmd
.servers
[0].max_port
= srv
->sgs_maxport
;
1412 if (RULE_HAS_HC(add_rl
))
1413 (void) ilbd_hc_add_server(add_rl
, srv
, ev_port
);
1414 (void) strlcpy(add_kcmd
.name
, add_rl
->irl_name
,
1415 sizeof (add_kcmd
.name
));
1416 (void) do_ioctl((void *)&add_kcmd
, 0);
1417 add_rl
= list_prev(rlist
, add_rl
);