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.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
30 #include <sys/types.h>
31 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #include "libilb_impl.h"
50 static list_t ilbd_sg_hlist
;
52 static ilb_status_t
i_delete_srv(ilbd_sg_t
*, ilbd_srv_t
*, int);
53 static void i_ilbd_free_srvID(ilbd_sg_t
*, int32_t);
55 /* Last parameter to pass to i_find_srv(), specifying the matching mode */
59 static ilbd_srv_t
*i_find_srv(list_t
*, ilb_sg_srv_t
*, int);
62 i_setup_sg_hlist(void)
64 list_create(&ilbd_sg_hlist
, sizeof (ilbd_sg_t
),
65 offsetof(ilbd_sg_t
, isg_link
));
69 * allocate storage for a daemon-internal server group, init counters
72 i_ilbd_alloc_sg(char *name
)
76 d_sg
= calloc(sizeof (*d_sg
), 1);
80 (void) strlcpy(d_sg
->isg_name
, name
, sizeof (d_sg
->isg_name
));
82 list_create(&d_sg
->isg_srvlist
, sizeof (ilbd_srv_t
),
83 offsetof(ilbd_srv_t
, isv_srv_link
));
84 list_create(&d_sg
->isg_rulelist
, sizeof (ilbd_rule_t
),
85 offsetof(ilbd_rule_t
, irl_sglink
));
87 list_insert_tail(&ilbd_sg_hlist
, d_sg
);
93 i_ilbd_save_sg(ilbd_sg_t
*d_sg
, ilbd_scf_cmd_t scf_cmd
, const char *prop_name
,
98 return (ilbd_create_pg(ILBD_SCF_SG
, (void *)d_sg
));
99 case ILBD_SCF_DESTROY
:
100 return (ilbd_destroy_pg(ILBD_SCF_SG
, d_sg
->isg_name
));
101 case ILBD_SCF_ENABLE_DISABLE
:
102 if (prop_name
== NULL
)
103 return (ILB_STATUS_EINVAL
);
104 return (ilbd_change_prop(ILBD_SCF_SG
, d_sg
->isg_name
,
107 logdebug("i_ilbd_save_sg: invalid scf cmd %d", scf_cmd
);
108 return (ILB_STATUS_EINVAL
);
113 i_attach_rule2sg(ilbd_sg_t
*sg
, ilbd_rule_t
*irl
)
115 /* assert: the same rule is attached to any sg only once */
116 list_insert_tail(&sg
->isg_rulelist
, irl
);
117 return (ILB_STATUS_OK
);
121 i_ilbd_free_sg(ilbd_sg_t
*sg
)
127 list_remove(&ilbd_sg_hlist
, sg
);
128 while ((tmp_srv
= list_remove_tail(&sg
->isg_srvlist
)) != NULL
) {
129 i_ilbd_free_srvID(sg
, tmp_srv
->isv_id
);
137 i_find_sg_byname(const char *name
)
141 /* find position of sg in list */
142 for (sg
= list_head(&ilbd_sg_hlist
); sg
!= NULL
;
143 sg
= list_next(&ilbd_sg_hlist
, sg
)) {
144 if (strncmp(sg
->isg_name
, name
, sizeof (sg
->isg_name
)) == 0)
151 * Generates an audit record for enable-server, disable-server, remove-server
152 * delete-servergroup, create-servergroup and add-server subcommands.
155 ilbd_audit_server_event(audit_sg_event_data_t
*data
,
156 ilbd_cmd_t cmd
, ilb_status_t rc
, ucred_t
*ucredp
)
158 adt_session_data_t
*ah
;
159 adt_event_data_t
*event
;
163 if ((ucredp
== NULL
) && ((cmd
== ILBD_ADD_SERVER_TO_GROUP
) ||
164 (cmd
== ILBD_CREATE_SERVERGROUP
))) {
166 * We came here from the path where ilbd is
167 * incorporating the ILB configuration from
168 * SCF. In that case, we skip auditing
173 if (adt_start_session(&ah
, NULL
, 0) != 0) {
174 logerr("ilbd_audit_server_event: adt_start_session failed");
178 if (adt_set_from_ucred(ah
, ucredp
, ADT_NEW
) != 0) {
179 (void) adt_end_session(ah
);
180 logerr("ilbd_audit_server_event: adt_set_from_ucred failed");
184 if (cmd
== ILBD_ENABLE_SERVER
)
185 flag
= ADT_ilb_enable_server
;
186 else if (cmd
== ILBD_DISABLE_SERVER
)
187 flag
= ADT_ilb_disable_server
;
188 else if (cmd
== ILBD_REM_SERVER_FROM_GROUP
)
189 flag
= ADT_ilb_remove_server
;
190 else if (cmd
== ILBD_ADD_SERVER_TO_GROUP
)
191 flag
= ADT_ilb_add_server
;
192 else if (cmd
== ILBD_CREATE_SERVERGROUP
)
193 flag
= ADT_ilb_create_servergroup
;
194 else if (cmd
== ILBD_DESTROY_SERVERGROUP
)
195 flag
= ADT_ilb_delete_servergroup
;
197 if ((event
= adt_alloc_event(ah
, flag
)) == NULL
) {
198 logerr("ilbd_audit_server_event: adt_alloc_event failed");
201 (void) memset((char *)event
, 0, sizeof (adt_event_data_t
));
204 case ILBD_ENABLE_SERVER
:
205 event
->adt_ilb_enable_server
.auth_used
=
207 event
->adt_ilb_enable_server
.server_id
=
209 event
->adt_ilb_enable_server
.server_ipaddress_type
=
210 data
->ed_ipaddr_type
;
211 (void) memcpy(event
->adt_ilb_enable_server
.server_ipaddress
,
212 data
->ed_server_address
,
213 (sizeof (data
->ed_server_address
)));
215 case ILBD_DISABLE_SERVER
:
216 event
->adt_ilb_disable_server
.auth_used
=
218 event
->adt_ilb_disable_server
.server_id
=
220 event
->adt_ilb_disable_server
.server_ipaddress_type
=
221 data
->ed_ipaddr_type
;
222 (void) memcpy(event
->adt_ilb_disable_server
.server_ipaddress
,
223 data
->ed_server_address
,
224 (sizeof (data
->ed_server_address
)));
226 case ILBD_REM_SERVER_FROM_GROUP
:
227 event
->adt_ilb_remove_server
.auth_used
=
229 event
->adt_ilb_remove_server
.server_id
=
231 event
->adt_ilb_remove_server
.server_group
= data
->ed_sgroup
;
232 event
->adt_ilb_remove_server
.server_ipaddress_type
=
233 data
->ed_ipaddr_type
;
234 (void) memcpy(event
->adt_ilb_remove_server
.server_ipaddress
,
235 data
->ed_server_address
,
236 (sizeof (data
->ed_server_address
)));
238 case ILBD_CREATE_SERVERGROUP
:
239 event
->adt_ilb_create_servergroup
.auth_used
=
241 event
->adt_ilb_create_servergroup
.server_group
=
244 case ILBD_ADD_SERVER_TO_GROUP
:
245 event
->adt_ilb_add_server
.auth_used
=
247 event
->adt_ilb_add_server
.server_ipaddress_type
=
248 data
->ed_ipaddr_type
;
249 (void) memcpy(event
->adt_ilb_add_server
.server_ipaddress
,
250 data
->ed_server_address
,
251 (sizeof (data
->ed_server_address
)));
252 event
->adt_ilb_add_server
.server_id
=
254 event
->adt_ilb_add_server
.server_group
=
256 event
->adt_ilb_add_server
.server_minport
=
257 ntohs(data
->ed_minport
);
258 event
->adt_ilb_add_server
.server_maxport
=
259 ntohs(data
->ed_maxport
);
261 case ILBD_DESTROY_SERVERGROUP
:
262 event
->adt_ilb_delete_servergroup
.auth_used
=
264 event
->adt_ilb_delete_servergroup
.server_group
=
269 /* Fill in success/failure */
270 if (rc
== ILB_STATUS_OK
) {
271 if (adt_put_event(event
, ADT_SUCCESS
, ADT_SUCCESS
) != 0) {
272 logerr("ilbd_audit_server_event:"
273 " adt_put_event failed");
277 audit_error
= ilberror2auditerror(rc
);
278 if (adt_put_event(event
, ADT_FAILURE
, audit_error
) != 0) {
279 logerr("ilbd_audit_server_event:"
280 " adt_put_event failed");
284 adt_free_event(event
);
285 (void) adt_end_session(ah
);
289 ilbd_destroy_sg(const char *sg_name
, const struct passwd
*ps
,
294 audit_sg_event_data_t audit_sg_data
;
296 (void) memset(&audit_sg_data
, 0, sizeof (audit_sg_event_data_t
));
297 audit_sg_data
.ed_sgroup
= (char *)sg_name
;
299 rc
= ilbd_check_client_config_auth(ps
);
300 if (rc
!= ILB_STATUS_OK
) {
301 ilbd_audit_server_event(&audit_sg_data
,
302 ILBD_DESTROY_SERVERGROUP
, rc
, ucredp
);
306 tmp_sg
= i_find_sg_byname(sg_name
);
307 if (tmp_sg
== NULL
) {
308 logdebug("ilbd_destroy_sg: cannot find specified server"
309 " group %s", sg_name
);
310 ilbd_audit_server_event(&audit_sg_data
,
311 ILBD_DESTROY_SERVERGROUP
, ILB_STATUS_SGUNAVAIL
, ucredp
);
312 return (ILB_STATUS_SGUNAVAIL
);
316 * we only destroy SGs that don't have any rules associated with
319 if (list_head(&tmp_sg
->isg_rulelist
) != NULL
) {
320 logdebug("ilbd_destroy_sg: server group %s has rules"
321 " associated with it and thus cannot be"
322 " removed", tmp_sg
->isg_name
);
323 ilbd_audit_server_event(&audit_sg_data
,
324 ILBD_DESTROY_SERVERGROUP
, ILB_STATUS_SGINUSE
, ucredp
);
325 return (ILB_STATUS_SGINUSE
);
329 rc
= i_ilbd_save_sg(tmp_sg
, ILBD_SCF_DESTROY
, NULL
, NULL
);
330 if (rc
!= ILB_STATUS_OK
) {
331 ilbd_audit_server_event(&audit_sg_data
,
332 ILBD_DESTROY_SERVERGROUP
, rc
, ucredp
);
336 i_ilbd_free_sg(tmp_sg
);
337 ilbd_audit_server_event(&audit_sg_data
, ILBD_DESTROY_SERVERGROUP
,
344 * Parameter ev_port is not used but has to have for read persistent configure
345 * ilbd_create_sg(), ilbd_create_hc() and ilbd_create_rule() are callbacks
346 * for ilbd_scf_instance_walk_pg() which requires the same signature.
349 ilbd_create_sg(ilb_sg_info_t
*sg
, int ev_port
, const struct passwd
*ps
,
352 ilb_status_t rc
= ILB_STATUS_OK
;
354 audit_sg_event_data_t audit_sg_data
;
356 (void) memset(&audit_sg_data
, 0, sizeof (audit_sg_event_data_t
));
357 audit_sg_data
.ed_sgroup
= sg
->sg_name
;
360 rc
= ilbd_check_client_config_auth(ps
);
361 if (rc
!= ILB_STATUS_OK
) {
362 ilbd_audit_server_event(&audit_sg_data
,
363 ILBD_CREATE_SERVERGROUP
, rc
, ucredp
);
368 if (i_find_sg_byname(sg
->sg_name
) != NULL
) {
369 logdebug("ilbd_create_sg: server group %s already exists",
371 ilbd_audit_server_event(&audit_sg_data
,
372 ILBD_CREATE_SERVERGROUP
, ILB_STATUS_SGEXISTS
, ucredp
);
373 return (ILB_STATUS_SGEXISTS
);
376 d_sg
= i_ilbd_alloc_sg(sg
->sg_name
);
378 ilbd_audit_server_event(&audit_sg_data
,
379 ILBD_CREATE_SERVERGROUP
, ILB_STATUS_ENOMEM
, ucredp
);
380 return (ILB_STATUS_ENOMEM
);
384 * we've successfully created the sg in memory. Before we can
385 * return "success", we need to reflect this in persistent
389 rc
= i_ilbd_save_sg(d_sg
, ILBD_SCF_CREATE
, NULL
, NULL
);
390 if (rc
!= ILB_STATUS_OK
) {
391 i_ilbd_free_sg(d_sg
);
392 ilbd_audit_server_event(&audit_sg_data
,
393 ILBD_CREATE_SERVERGROUP
, rc
, ucredp
);
397 ilbd_audit_server_event(&audit_sg_data
,
398 ILBD_CREATE_SERVERGROUP
, rc
, ucredp
);
403 * This function checks whether tsrv should/can be inserted before lsrv
404 * and does so if possible.
405 * We keep the list in sorted order so we don't have to search it
406 * in its entirety for overlap every time we insert a new server.
408 * stop_found: don't continue searching because we found a place
409 * cont_search: continue with next element in the list
410 * fail_search: search failed (caller translates to ILB_STATUS_EEXIST)
413 i_test_and_insert(ilbd_srv_t
*tsrv
, ilbd_srv_t
*lsrv
, list_t
*srvlist
)
415 struct in6_addr
*t1
, *l1
;
418 t1
= &tsrv
->isv_addr
;
419 l1
= &lsrv
->isv_addr
;
421 if ((fnd
= ilb_cmp_in6_addr(t1
, l1
, NULL
)) == 1)
422 return (cont_search
); /* search can continue */
425 logdebug("i_test_and_insert: specified server already exists");
426 return (fail_search
);
428 /* the list is kept in ascending order */
429 list_insert_before(srvlist
, lsrv
, tsrv
);
435 * copy a server description [ip1,ip2,port1,port2,srvID,flags]
437 #define COPY_SERVER(src, dest) \
438 (dest)->sgs_addr = (src)->sgs_addr; \
439 (dest)->sgs_minport = (src)->sgs_minport; \
440 (dest)->sgs_maxport = (src)->sgs_maxport; \
441 (dest)->sgs_id = (src)->sgs_id; \
442 (void) strlcpy((dest)->sgs_srvID, (src)->sgs_srvID, \
443 sizeof ((dest)->sgs_srvID)); \
444 (dest)->sgs_flags = (src)->sgs_flags
447 i_add_srv2sg(ilbd_sg_t
*dsg
, ilb_sg_srv_t
*srv
, ilbd_srv_t
**ret_srv
)
449 ilb_sg_srv_t
*n_sg_srv
;
451 srch_ind_t search
= not_searched
;
452 ilb_status_t rc
= ILB_STATUS_OK
;
453 ilbd_srv_t
*nsrv
, *lsrv
;
454 in_port_t h_minport
, h_maxport
;
456 nsrv
= calloc(sizeof (*nsrv
), 1);
458 return (ILB_STATUS_ENOMEM
);
459 n_sg_srv
= &nsrv
->isv_srv
;
460 COPY_SERVER(srv
, n_sg_srv
);
463 * port info is in network byte order - we need host byte order
464 * for comparisons purposes
466 h_minport
= ntohs(n_sg_srv
->sgs_minport
);
467 h_maxport
= ntohs(n_sg_srv
->sgs_maxport
);
468 if (h_minport
!= 0 && h_minport
> h_maxport
)
469 n_sg_srv
->sgs_maxport
= n_sg_srv
->sgs_minport
;
471 srvlist
= &dsg
->isg_srvlist
;
473 lsrv
= list_head(srvlist
);
475 list_insert_head(srvlist
, nsrv
);
477 while (lsrv
!= NULL
) {
478 search
= i_test_and_insert(nsrv
, lsrv
,
481 if (search
!= cont_search
)
483 lsrv
= list_next(srvlist
, lsrv
);
485 /* if reaches the end of list, insert to the tail */
486 if (search
== cont_search
&& lsrv
== NULL
)
487 list_insert_tail(srvlist
, nsrv
);
489 if (search
== fail_search
)
490 rc
= ILB_STATUS_EEXIST
;
493 if (rc
== ILB_STATUS_OK
) {
504 * Allocate a server ID. The algorithm is simple. Just check the ID array
505 * of the server group and find an unused ID. If *set_id is given, it
506 * means that the ID is already allocated and the ID array needs to be
507 * updated. This is the case when ilbd reads from the persistent
511 i_ilbd_alloc_srvID(ilbd_sg_t
*sg
, int32_t *set_id
)
516 /* The server ID is already allocated, just update the ID array. */
517 if (set_id
!= NULL
) {
518 assert(sg
->isg_id_arr
[*set_id
] == 0);
519 sg
->isg_id_arr
[*set_id
] = 1;
523 /* if we're "full up", give back something invalid */
524 if (sg
->isg_srvcount
== MAX_SRVCOUNT
)
528 for (id
= 0; id
< MAX_SRVCOUNT
; id
++) {
529 if (sg
->isg_id_arr
[(id
+ i
) % MAX_SRVCOUNT
] == 0)
533 sg
->isg_max_id
= (id
+ i
) % MAX_SRVCOUNT
;
534 sg
->isg_id_arr
[sg
->isg_max_id
] = 1;
535 return (sg
->isg_max_id
);
539 * Free a server ID by updating the server group's ID array.
542 i_ilbd_free_srvID(ilbd_sg_t
*sg
, int32_t id
)
544 assert(sg
->isg_id_arr
[id
] == 1);
545 sg
->isg_id_arr
[id
] = 0;
549 * This function is called by ilbd_add_server_to_group() and
550 * ilb_remove_server_group() to create a audit record for a
551 * failed servicing of add-server/remove-server command
554 fill_audit_record(ilb_sg_info_t
*sg
, audit_sg_event_data_t
*audit_sg_data
,
555 ilbd_cmd_t cmd
, ilb_status_t rc
, ucred_t
*ucredp
)
560 for (i
= 0; i
< sg
->sg_srvcount
; i
++) {
561 tsrv
= &sg
->sg_servers
[i
];
562 if (cmd
== ILBD_ADD_SERVER_TO_GROUP
) {
564 audit_sg_data
->ed_serverid
= NULL
;
565 if (IN6_IS_ADDR_V4MAPPED(&tsrv
->sgs_addr
)) {
566 audit_sg_data
->ed_ipaddr_type
= ADT_IPv4
;
567 cvt_addr(audit_sg_data
->ed_server_address
,
568 ADT_IPv4
, tsrv
->sgs_addr
);
570 audit_sg_data
->ed_ipaddr_type
= ADT_IPv6
;
571 cvt_addr(audit_sg_data
->ed_server_address
,
572 ADT_IPv6
, tsrv
->sgs_addr
);
574 audit_sg_data
->ed_minport
= tsrv
->sgs_minport
;
575 audit_sg_data
->ed_maxport
= tsrv
->sgs_maxport
;
576 audit_sg_data
->ed_sgroup
= sg
->sg_name
;
577 } else if (cmd
== ILBD_REM_SERVER_FROM_GROUP
) {
578 audit_sg_data
->ed_serverid
= tsrv
->sgs_srvID
;
579 audit_sg_data
->ed_sgroup
= sg
->sg_name
;
581 audit_sg_data
->ed_minport
= 0;
582 audit_sg_data
->ed_maxport
= 0;
584 ilbd_audit_server_event(audit_sg_data
, cmd
, rc
, ucredp
);
589 * the name(s) of the server(s) are encoded in the sg.
592 ilbd_add_server_to_group(ilb_sg_info_t
*sg_info
, int ev_port
,
593 const struct passwd
*ps
, ucred_t
*ucredp
)
595 ilb_status_t rc
= ILB_STATUS_OK
;
598 int32_t new_id
= BAD_SRVID
;
599 int32_t af
= AF_UNSPEC
;
602 audit_sg_event_data_t audit_sg_data
;
605 rc
= ilbd_check_client_config_auth(ps
);
606 if (rc
!= ILB_STATUS_OK
) {
607 fill_audit_record(sg_info
, &audit_sg_data
,
608 ILBD_ADD_SERVER_TO_GROUP
, rc
, ucredp
);
613 tmp_sg
= i_find_sg_byname(sg_info
->sg_name
);
614 if (tmp_sg
== NULL
) {
615 logdebug("ilbd_add_server_to_group: server"
616 " group %s does not exist", sg_info
->sg_name
);
617 fill_audit_record(sg_info
, &audit_sg_data
,
618 ILBD_ADD_SERVER_TO_GROUP
, ILB_STATUS_ENOENT
, ucredp
);
619 return (ILB_STATUS_ENOENT
);
623 * we do the dance with address family below to make sure only
624 * IP addresses in the same AF get into an SG; the first one to get
626 * if this is the first server to join a group, check whether
627 * there's no mismatch with any *rules* already attached
629 if (tmp_sg
->isg_srvcount
> 0) {
630 ilbd_srv_t
*tsrv
= list_head(&tmp_sg
->isg_srvlist
);
632 af
= GET_AF(&tsrv
->isv_addr
);
634 ilbd_rule_t
*irl
= list_head(&tmp_sg
->isg_rulelist
);
637 af
= GET_AF(&irl
->irl_vip
);
640 for (i
= 0; i
< sg_info
->sg_srvcount
; i
++) {
641 srv
= &sg_info
->sg_servers
[i
];
643 (void) memset(&audit_sg_data
, 0, sizeof (audit_sg_data
));
644 if (IN6_IS_ADDR_V4MAPPED(&srv
->sgs_addr
)) {
645 audit_sg_data
.ed_ipaddr_type
= ADT_IPv4
;
646 cvt_addr(audit_sg_data
.ed_server_address
, ADT_IPv4
,
649 audit_sg_data
.ed_ipaddr_type
= ADT_IPv6
;
650 cvt_addr(audit_sg_data
.ed_server_address
, ADT_IPv6
,
653 audit_sg_data
.ed_minport
= srv
->sgs_minport
;
654 audit_sg_data
.ed_maxport
= srv
->sgs_maxport
;
655 audit_sg_data
.ed_sgroup
= sg_info
->sg_name
;
657 /* only test if we have sth to test against */
658 if (af
!= AF_UNSPEC
) {
659 int32_t sgs_af
= GET_AF(&srv
->sgs_addr
);
662 logdebug("address family mismatch with previous"
663 " hosts in servergroup or with rule");
664 rc
= ILB_STATUS_MISMATCHH
;
665 ilbd_audit_server_event(&audit_sg_data
,
666 ILBD_ADD_SERVER_TO_GROUP
, rc
, ucredp
);
672 * PS: NULL means daemon is loading configure from scf.
673 * ServerID is already assigned, just update the ID array.
676 new_id
= i_ilbd_alloc_srvID(tmp_sg
, NULL
);
677 if (new_id
== BAD_SRVID
) {
678 logdebug("ilbd_add_server_to_group: server"
679 "group %s is full, no more servers"
680 " can be added", sg_info
->sg_name
);
681 rc
= ILB_STATUS_SGFULL
;
682 ilbd_audit_server_event(&audit_sg_data
,
683 ILBD_ADD_SERVER_TO_GROUP
, rc
, ucredp
);
686 srv
->sgs_id
= new_id
;
688 new_id
= i_ilbd_alloc_srvID(tmp_sg
, &srv
->sgs_id
);
692 * here we implement the requirement that server IDs start
693 * with a character that is not legal in hostnames - in our
694 * case, a "_" (underscore).
696 (void) snprintf(srv
->sgs_srvID
,
697 sizeof (srv
->sgs_srvID
), "%c%s.%d", ILB_SRVID_PREFIX
,
698 tmp_sg
->isg_name
, srv
->sgs_id
);
699 audit_sg_data
.ed_serverid
= srv
->sgs_srvID
;
702 * Before we update the kernel rules by adding the server,
703 * we need to make checks and fail if any of the
706 * o if the server has single port and the servergroup
707 * is associated to a DSR rule with a port range
708 * o if the server has a port range and the servergroup
709 * is associated to a DSR rule with a port range and
710 * the rule's min and max port does not exactly
711 * match that of the server's.
712 * o if the the server has a port range and the servergroup
713 * is associated to a NAT/Half-NAT rule with a port range
714 * and the rule's port range size does not match that
716 * o if the rule has a fixed hc port, check that this port
717 * is valid in the server's port specification.
719 rc
= i_check_srv2rules(&tmp_sg
->isg_rulelist
, srv
);
720 if (rc
!= ILB_STATUS_OK
) {
721 ilbd_audit_server_event(&audit_sg_data
,
722 ILBD_ADD_SERVER_TO_GROUP
, rc
, ucredp
);
726 if ((rc
= i_add_srv2sg(tmp_sg
, srv
, &nsrv
)) != ILB_STATUS_OK
) {
727 ilbd_audit_server_event(&audit_sg_data
,
728 ILBD_ADD_SERVER_TO_GROUP
, rc
, ucredp
);
732 rc
= i_add_srv2krules(&tmp_sg
->isg_rulelist
, &nsrv
->isv_srv
,
734 if (rc
!= ILB_STATUS_OK
) {
735 ilbd_audit_server_event(&audit_sg_data
,
736 ILBD_ADD_SERVER_TO_GROUP
, rc
, ucredp
);
738 * The failure may be due to the serverid being on
739 * hold in kernel for connection draining. But ilbd
740 * has no way of knowing that. So we are freeing up
741 * the serverid, and may run into the risk of
742 * having this failure again, if we choose this
743 * serverid when processing the next add-server
744 * command for this servergroup, while connection
745 * draining is underway. We assume that the user
746 * will read the man page after they encounter
747 * this failure, and learn to not add any server
748 * to the servergroup until connection draining of
749 * all servers in the servergroup is complete.
750 * XXX Need to revisit this when connection draining
753 list_remove(&tmp_sg
->isg_srvlist
, nsrv
);
754 i_ilbd_free_srvID(tmp_sg
, nsrv
->isv_id
);
756 tmp_sg
->isg_srvcount
--;
760 rc
= ilbd_scf_add_srv(tmp_sg
, nsrv
);
761 if (rc
!= ILB_STATUS_OK
) {
763 * The following should not fail since the
764 * server is just added. Just in case, we
765 * pass in -1 as the event port to avoid
766 * roll back in i_rem_srv_frm_krules() called
769 ilbd_audit_server_event(&audit_sg_data
,
770 ILBD_ADD_SERVER_TO_GROUP
, rc
, ucredp
);
771 (void) i_delete_srv(tmp_sg
, nsrv
, -1);
777 if (rc
== ILB_STATUS_OK
) {
778 ilbd_audit_server_event(&audit_sg_data
,
779 ILBD_ADD_SERVER_TO_GROUP
, rc
, ucredp
);
785 * If ilbd is initializing based on the SCF data and something fails,
786 * the only choice is to transition the service to maintanence mode...
789 logerr("%s: failure during initialization -"
790 " entering maintenance mode", __func__
);
791 (void) smf_maintain_instance(ILB_FMRI
, SMF_IMMEDIATE
);
796 * we need to roll back all servers previous to the one
797 * that just caused the failure
799 for (j
= i
-1; j
>= 0; j
--) {
800 srv
= &sg_info
->sg_servers
[j
];
802 /* We should be able to find those servers just added. */
803 nsrv
= i_find_srv(&tmp_sg
->isg_srvlist
, srv
, MODE_SRVID
);
804 assert(nsrv
!= NULL
);
805 (void) i_delete_srv(tmp_sg
, nsrv
, -1);
811 i_match_srvID(ilb_sg_srv_t
*sg_srv
, ilbd_srv_t
*lsrv
)
813 if (strncmp(sg_srv
->sgs_srvID
, lsrv
->isv_srvID
,
814 sizeof (sg_srv
->sgs_srvID
)) == 0) {
817 return (cont_search
);
821 * Sanity check on a rule's port specification against all the servers'
822 * specification in its associated server group.
824 * 1. If the health check's probe port (hcport) is specified.
825 * - if server port range is specified, check if hcport is inside
827 * - if no server port is specified (meaning the port range is the same as
828 * the rule's port range), check if hcport is inside the rule's range.
830 * 2. If a server has no port specification, there is no conflict.
832 * 3. If the rule's load balance mode is DSR, a server port specification must
833 * be exactly the same as the rule's.
835 * 4. In other modes (NAT and half-NAT), the server's port range must be
836 * the same as the rule's, unless it is doing port collapsing (the server's
837 * port range is only 1).
840 ilbd_sg_check_rule_port(ilbd_sg_t
*sg
, ilb_rule_info_t
*rl
)
843 in_port_t r_minport
, r_maxport
;
845 /* Don't allow adding a rule to a sg with no server, for now... */
846 if (sg
->isg_srvcount
== 0)
847 return (ILB_STATUS_SGEMPTY
);
849 r_minport
= ntohs(rl
->rl_minport
);
850 r_maxport
= ntohs(rl
->rl_maxport
);
852 for (srv
= list_head(&sg
->isg_srvlist
); srv
!= NULL
;
853 srv
= list_next(&sg
->isg_srvlist
, srv
)) {
854 in_port_t srv_minport
, srv_maxport
;
857 srv_minport
= ntohs(srv
->isv_minport
);
858 srv_maxport
= ntohs(srv
->isv_maxport
);
859 range
= srv_maxport
- srv_minport
;
862 * If the rule has a specific probe port, check if that port is
863 * valid in all the servers' port specification.
865 if (rl
->rl_hcpflag
== ILB_HCI_PROBE_FIX
) {
866 in_port_t hcport
= ntohs(rl
->rl_hcport
);
868 /* No server port specified. */
869 if (srv_minport
== 0) {
870 if (hcport
> r_maxport
|| hcport
< r_minport
) {
871 return (ILB_STATUS_BADSG
);
874 if (hcport
> srv_maxport
||
875 hcport
< srv_minport
) {
876 return (ILB_STATUS_BADSG
);
882 * There is no server port specification, so there cannot be
885 if (srv_minport
== 0)
888 if (rl
->rl_topo
== ILB_TOPO_DSR
) {
889 if (r_minport
!= srv_minport
||
890 r_maxport
!= srv_maxport
) {
891 return (ILB_STATUS_BADSG
);
894 if ((range
!= r_maxport
- r_minport
) && range
!= 0)
895 return (ILB_STATUS_BADSG
);
899 return (ILB_STATUS_OK
);
903 i_match_srvIP(ilb_sg_srv_t
*sg_srv
, ilbd_srv_t
*lsrv
)
905 if (IN6_ARE_ADDR_EQUAL(&sg_srv
->sgs_addr
, &lsrv
->isv_addr
))
907 return (cont_search
);
911 i_find_srv(list_t
*srvlist
, ilb_sg_srv_t
*sg_srv
, int cmpmode
)
914 srch_ind_t srch_res
= cont_search
;
916 for (tmp_srv
= list_head(srvlist
); tmp_srv
!= NULL
;
917 tmp_srv
= list_next(srvlist
, tmp_srv
)) {
920 srch_res
= i_match_srvIP(sg_srv
, tmp_srv
);
923 srch_res
= i_match_srvID(sg_srv
, tmp_srv
);
926 if (srch_res
== stop_found
)
930 if (srch_res
== stop_found
)
936 i_delete_srv(ilbd_sg_t
*sg
, ilbd_srv_t
*srv
, int ev_port
)
940 rc
= i_rem_srv_frm_krules(&sg
->isg_rulelist
, &srv
->isv_srv
, ev_port
);
941 if (rc
!= ILB_STATUS_OK
)
943 list_remove(&sg
->isg_srvlist
, srv
);
944 i_ilbd_free_srvID(sg
, srv
->isv_id
);
947 return (ILB_STATUS_OK
);
951 * some people argue that returning anything here is
952 * useless - what *do* you do if you can't remove/destroy
956 ilbd_rem_server_from_group(ilb_sg_info_t
*sg_info
, int ev_port
,
957 const struct passwd
*ps
, ucred_t
*ucredp
)
959 ilb_status_t rc
= ILB_STATUS_OK
;
961 ilbd_srv_t
*srv
, tmp_srv
;
963 audit_sg_event_data_t audit_sg_data
;
965 rc
= ilbd_check_client_config_auth(ps
);
966 if (rc
!= ILB_STATUS_OK
) {
967 fill_audit_record(sg_info
, &audit_sg_data
,
968 ILBD_REM_SERVER_FROM_GROUP
, rc
, ucredp
);
972 tmp_sg
= i_find_sg_byname(sg_info
->sg_name
);
973 if (tmp_sg
== NULL
) {
974 logdebug("%s: server group %s\n does not exist", __func__
,
976 fill_audit_record(sg_info
, &audit_sg_data
,
977 ILBD_REM_SERVER_FROM_GROUP
, ILB_STATUS_SGUNAVAIL
, ucredp
);
978 return (ILB_STATUS_SGUNAVAIL
);
980 tsrv
= &sg_info
->sg_servers
[0];
981 audit_sg_data
.ed_serverid
= tsrv
->sgs_srvID
;
982 audit_sg_data
.ed_sgroup
= sg_info
->sg_name
;
984 assert(sg_info
->sg_srvcount
== 1);
985 srv
= i_find_srv(&tmp_sg
->isg_srvlist
, &sg_info
->sg_servers
[0],
988 logdebug("%s: cannot find server in server group %s", __func__
,
990 ilbd_audit_server_event(&audit_sg_data
,
991 ILBD_REM_SERVER_FROM_GROUP
, ILB_STATUS_SRVUNAVAIL
, ucredp
);
992 return (ILB_STATUS_SRVUNAVAIL
);
994 tsrv
= &srv
->isv_srv
;
995 if (IN6_IS_ADDR_V4MAPPED(&tsrv
->sgs_addr
)) {
996 audit_sg_data
.ed_ipaddr_type
= ADT_IPv4
;
997 cvt_addr(audit_sg_data
.ed_server_address
, ADT_IPv4
,
1000 audit_sg_data
.ed_ipaddr_type
= ADT_IPv6
;
1001 cvt_addr(audit_sg_data
.ed_server_address
, ADT_IPv6
,
1005 * i_delete_srv frees srv, therefore we need to save
1006 * this information for ilbd_scf_del_srv
1008 (void) memcpy(&tmp_srv
, srv
, sizeof (tmp_srv
));
1010 rc
= i_delete_srv(tmp_sg
, srv
, ev_port
);
1011 if (rc
!= ILB_STATUS_OK
) {
1012 ilbd_audit_server_event(&audit_sg_data
,
1013 ILBD_REM_SERVER_FROM_GROUP
, rc
, ucredp
);
1018 if ((rc
= ilbd_scf_del_srv(tmp_sg
, &tmp_srv
)) !=
1020 ilbd_audit_server_event(&audit_sg_data
,
1021 ILBD_REM_SERVER_FROM_GROUP
, rc
, ucredp
);
1022 logerr("%s: SCF update failed - entering maintenance"
1024 (void) smf_maintain_instance(ILB_FMRI
, SMF_IMMEDIATE
);
1027 ilbd_audit_server_event(&audit_sg_data
,
1028 ILBD_REM_SERVER_FROM_GROUP
, rc
, ucredp
);
1033 ilbd_retrieve_names(ilbd_cmd_t cmd
, uint32_t *rbuf
, size_t *rbufsz
)
1035 ilb_status_t rc
= ILB_STATUS_OK
;
1036 ilbd_namelist_t
*nlist
;
1039 tmp_rbufsz
= *rbufsz
;
1040 /* Set up the reply buffer. rbufsz will be set to the new size. */
1041 ilbd_reply_ok(rbuf
, rbufsz
);
1043 /* Calculate how much space is left for holding name info. */
1044 *rbufsz
+= sizeof (ilbd_namelist_t
);
1045 tmp_rbufsz
-= *rbufsz
;
1047 nlist
= (ilbd_namelist_t
*)&((ilb_comm_t
*)rbuf
)->ic_data
;
1048 nlist
->ilbl_count
= 0;
1051 case ILBD_RETRIEVE_SG_NAMES
: {
1054 for (sg
= list_head(&ilbd_sg_hlist
);
1055 sg
!= NULL
&& tmp_rbufsz
>= sizeof (ilbd_name_t
);
1056 sg
= list_next(&ilbd_sg_hlist
, sg
),
1057 tmp_rbufsz
-= sizeof (ilbd_name_t
)) {
1058 (void) strlcpy(nlist
->ilbl_name
[nlist
->ilbl_count
++],
1059 sg
->isg_name
, sizeof (ilbd_name_t
));
1063 case ILBD_RETRIEVE_RULE_NAMES
: {
1065 extern list_t ilbd_rule_hlist
;
1067 for (irl
= list_head(&ilbd_rule_hlist
);
1068 irl
!= NULL
&& tmp_rbufsz
>= sizeof (ilbd_name_t
);
1069 irl
= list_next(&ilbd_rule_hlist
, irl
),
1070 tmp_rbufsz
-= sizeof (ilbd_name_t
)) {
1071 (void) strlcpy(nlist
->ilbl_name
[nlist
->ilbl_count
++],
1072 irl
->irl_name
, sizeof (ilbd_name_t
));
1076 case ILBD_RETRIEVE_HC_NAMES
: {
1077 extern list_t ilbd_hc_list
;
1080 for (hc
= list_head(&ilbd_hc_list
);
1081 hc
!= NULL
&& tmp_rbufsz
>= sizeof (ilbd_name_t
);
1082 hc
= list_next(&ilbd_hc_list
, hc
)) {
1083 (void) strlcpy(nlist
->ilbl_name
[nlist
->ilbl_count
++],
1084 hc
->ihc_name
, sizeof (ilbd_name_t
));
1089 logdebug("ilbd_retrieve_names: unknown command");
1090 return (ILB_STATUS_INVAL_CMD
);
1093 *rbufsz
+= nlist
->ilbl_count
* sizeof (ilbd_name_t
);
1098 ilbd_retrieve_sg_hosts(const char *sg_name
, uint32_t *rbuf
, size_t *rbufsz
)
1103 ilb_sg_info_t
*sg_info
;
1106 dsg
= i_find_sg_byname(sg_name
);
1108 logdebug("ilbd_retrieve_sg_hosts: server group"
1109 " %s not found", sg_name
);
1110 return (ILB_STATUS_SGUNAVAIL
);
1113 srvlist
= &dsg
->isg_srvlist
;
1114 dsrv
= list_head(srvlist
);
1116 tmp_rbufsz
= *rbufsz
;
1117 ilbd_reply_ok(rbuf
, rbufsz
);
1119 /* Calculate the size to hold all the hosts info. */
1120 *rbufsz
+= sizeof (ilb_sg_info_t
);
1121 tmp_rbufsz
-= *rbufsz
;
1123 sg_info
= (ilb_sg_info_t
*)&((ilb_comm_t
*)rbuf
)->ic_data
;
1124 (void) strlcpy(sg_info
->sg_name
, sg_name
, sizeof (sg_info
->sg_name
));
1125 sg_info
->sg_srvcount
= 0;
1127 while (dsrv
!= NULL
&& tmp_rbufsz
>= sizeof (ilb_sg_srv_t
)) {
1128 sg_info
->sg_servers
[sg_info
->sg_srvcount
++] = dsrv
->isv_srv
;
1129 dsrv
= list_next(srvlist
, dsrv
);
1130 tmp_rbufsz
-= sizeof (ilb_sg_srv_t
);
1132 *rbufsz
+= sg_info
->sg_srvcount
* sizeof (ilb_sg_srv_t
);
1133 return (ILB_STATUS_OK
);
1137 * this mapping function works on the assumption that HC only is
1138 * active when a server is enabled.
1141 i_srvcmd_d2k(ilbd_srv_status_ind_t dcmd
)
1146 case stat_enable_server
:
1147 case stat_declare_srv_alive
:
1148 cmd
= ILB_ENABLE_SERVERS
;
1150 case stat_disable_server
:
1151 case stat_declare_srv_dead
:
1152 cmd
= ILB_DISABLE_SERVERS
;
1160 ilbd_k_Xable_server(const struct in6_addr
*addr
, const char *rlname
,
1161 ilbd_srv_status_ind_t cmd
)
1164 ilb_servers_cmd_t kcmd
;
1167 kcmd
.cmd
= i_srvcmd_d2k(cmd
);
1168 (void) strlcpy(kcmd
.name
, rlname
, sizeof (kcmd
.name
));
1169 kcmd
.num_servers
= 1;
1171 kcmd
.servers
[0].addr
= *addr
;
1172 kcmd
.servers
[0].err
= 0;
1174 rc
= do_ioctl(&kcmd
, 0);
1175 if (rc
!= ILB_STATUS_OK
)
1178 if ((e
= kcmd
.servers
[0].err
) != 0) {
1179 logdebug("ilbd_k_Xable_server: error %s occurred",
1181 return (ilb_map_errno2ilbstat(e
));
1187 #define IS_SRV_ENABLED(s) ILB_IS_SRV_ENABLED((s)->sgs_flags)
1188 #define IS_SRV_DISABLED(s) (!(IS_SRV_ENABLED(s)))
1190 #define SET_SRV_ENABLED(s) ILB_SET_ENABLED((s)->sgs_flags)
1191 #define SET_SRV_DISABLED(s) ILB_SET_DISABLED((s)->sgs_flags)
1194 ilbd_Xable_server(ilb_sg_info_t
*sg
, const struct passwd
*ps
,
1195 ilbd_srv_status_ind_t cmd
, ucred_t
*ucredp
)
1197 ilb_status_t rc
= ILB_STATUS_OK
;
1199 ilbd_srv_t
*tmp_srv
;
1203 int scf_name_len
= ILBD_MAX_NAME_LEN
;
1204 int scf_val_len
= ILBD_MAX_VALUE_LEN
;
1205 char *prop_name
= NULL
;
1206 ilb_ip_addr_t ipaddr
;
1208 char ipstr
[INET6_ADDRSTRLEN
], *valstr
= NULL
;
1210 char sgname
[ILB_NAMESZ
];
1212 ilbd_srv_status_ind_t u_cmd
;
1213 audit_sg_event_data_t audit_sg_data
;
1215 (void) memset(&audit_sg_data
, 0, sizeof (audit_sg_data
));
1217 /* we currently only implement a "list" of one */
1218 assert(sg
->sg_srvcount
== 1);
1220 srv
= &sg
->sg_servers
[0];
1221 audit_sg_data
.ed_serverid
= srv
->sgs_srvID
;
1223 rc
= ilbd_check_client_enable_auth(ps
);
1224 if (rc
!= ILB_STATUS_OK
) {
1225 ilbd_audit_server_event(&audit_sg_data
,
1226 ILBD_ENABLE_SERVER
, rc
, ucredp
);
1230 if (srv
->sgs_srvID
[0] != ILB_SRVID_PREFIX
) {
1232 case stat_disable_server
:
1233 ilbd_audit_server_event(&audit_sg_data
,
1234 ILBD_DISABLE_SERVER
,
1235 ILB_STATUS_EINVAL
, ucredp
);
1237 case stat_enable_server
:
1238 ilbd_audit_server_event(&audit_sg_data
,
1240 ILB_STATUS_EINVAL
, ucredp
);
1243 return (ILB_STATUS_EINVAL
);
1247 * the following asserts that serverIDs are constructed
1248 * along the pattern "_"<SG name>"."<number>
1249 * so we look for the final "." to recreate the SG name.
1251 (void) strlcpy(sgname
, srv
->sgs_srvID
+ 1, sizeof (sgname
));
1252 dot
= strrchr(sgname
, (int)'.');
1255 case stat_disable_server
:
1256 ilbd_audit_server_event(&audit_sg_data
,
1257 ILBD_DISABLE_SERVER
,
1258 ILB_STATUS_EINVAL
, ucredp
);
1260 case stat_enable_server
:
1261 ilbd_audit_server_event(&audit_sg_data
,
1263 ILB_STATUS_EINVAL
, ucredp
);
1266 return (ILB_STATUS_EINVAL
);
1269 /* make the non-sg_name part "invisible" */
1271 isg
= i_find_sg_byname(sgname
);
1274 case stat_disable_server
:
1275 ilbd_audit_server_event(&audit_sg_data
,
1276 ILBD_DISABLE_SERVER
,
1277 ILB_STATUS_ENOENT
, ucredp
);
1279 case stat_enable_server
:
1280 ilbd_audit_server_event(&audit_sg_data
,
1282 ILB_STATUS_ENOENT
, ucredp
);
1285 return (ILB_STATUS_ENOENT
);
1288 tmp_srv
= i_find_srv(&isg
->isg_srvlist
, srv
, MODE_SRVID
);
1289 if (tmp_srv
== NULL
) {
1291 case stat_disable_server
:
1292 ilbd_audit_server_event(&audit_sg_data
,
1293 ILBD_DISABLE_SERVER
,
1294 ILB_STATUS_ENOENT
, ucredp
);
1296 case stat_enable_server
:
1297 ilbd_audit_server_event(&audit_sg_data
,
1299 ILB_STATUS_ENOENT
, ucredp
);
1302 return (ILB_STATUS_ENOENT
);
1306 * if server's servergroup is not associated with
1307 * a rule, do not enable it.
1309 irl
= list_head(&isg
->isg_rulelist
);
1312 case stat_disable_server
:
1313 ilbd_audit_server_event(&audit_sg_data
,
1314 ILBD_DISABLE_SERVER
,
1315 ILB_STATUS_INVAL_ENBSRVR
, ucredp
);
1317 case stat_enable_server
:
1318 ilbd_audit_server_event(&audit_sg_data
,
1320 ILB_STATUS_INVAL_ENBSRVR
, ucredp
);
1323 return (ILB_STATUS_INVAL_ENBSRVR
);
1325 /* Fill in the server IP address for audit record */
1326 if (IN6_IS_ADDR_V4MAPPED(&tmp_srv
->isv_addr
)) {
1327 audit_sg_data
.ed_ipaddr_type
= ADT_IPv4
;
1328 cvt_addr(audit_sg_data
.ed_server_address
, ADT_IPv4
,
1331 audit_sg_data
.ed_ipaddr_type
= ADT_IPv6
;
1332 cvt_addr(audit_sg_data
.ed_server_address
, ADT_IPv6
,
1337 * We have found the server in memory, perform the following
1340 * 1. For every rule associated with this SG,
1343 * 2. Update our internal state and persistent configuration
1344 * if the new state is not the same as the old one.
1347 for (; irl
!= NULL
; irl
= list_next(&isg
->isg_rulelist
, irl
)) {
1348 rc
= ilbd_k_Xable_server(&tmp_srv
->isv_addr
,
1349 irl
->irl_name
, cmd
);
1350 if (rc
!= ILB_STATUS_OK
) {
1352 case stat_disable_server
:
1353 ilbd_audit_server_event(&audit_sg_data
,
1354 ILBD_DISABLE_SERVER
, rc
, ucredp
);
1356 case stat_enable_server
:
1357 ilbd_audit_server_event(&audit_sg_data
,
1358 ILBD_ENABLE_SERVER
, rc
, ucredp
);
1361 goto rollback_rules
;
1363 if (!RULE_HAS_HC(irl
))
1366 if (cmd
== stat_disable_server
) {
1367 rc
= ilbd_hc_disable_server(irl
,
1370 assert(cmd
== stat_enable_server
);
1371 rc
= ilbd_hc_enable_server(irl
,
1374 if (rc
!= ILB_STATUS_OK
) {
1375 logdebug("ilbd_Xable_server: cannot toggle srv "
1376 "timer, rc =%d, srv =%s%d\n", rc
,
1383 if ((cmd
== stat_disable_server
&&
1384 IS_SRV_DISABLED(&tmp_srv
->isv_srv
)) ||
1385 (cmd
== stat_enable_server
&&
1386 IS_SRV_ENABLED(&tmp_srv
->isv_srv
))) {
1388 case stat_disable_server
:
1389 ilbd_audit_server_event(&audit_sg_data
,
1390 ILBD_DISABLE_SERVER
, ILB_STATUS_OK
, ucredp
);
1392 case stat_enable_server
:
1393 ilbd_audit_server_event(&audit_sg_data
,
1394 ILBD_ENABLE_SERVER
, ILB_STATUS_OK
, ucredp
);
1397 return (ILB_STATUS_OK
);
1400 nflags
= tmp_srv
->isv_flags
;
1401 if (cmd
== stat_enable_server
)
1402 ILB_SET_ENABLED(nflags
);
1404 ILB_SET_DISABLED(nflags
);
1406 IP_COPY_IMPL_2_CLI(&tmp_srv
->isv_addr
, &ipaddr
);
1407 ipver
= GET_AF(&tmp_srv
->isv_addr
);
1408 vallen
= (ipver
== AF_INET
) ? INET_ADDRSTRLEN
:
1410 addrptr
= (ipver
== AF_INET
) ? (void *)&ipaddr
.ia_v4
:
1411 (void *)&ipaddr
.ia_v6
;
1412 if (inet_ntop(ipver
, addrptr
, ipstr
, vallen
) == NULL
) {
1413 logerr("ilbd_Xable_server: failed transfer ip addr to"
1415 if (errno
== ENOSPC
)
1416 rc
= ILB_STATUS_ENOMEM
;
1418 rc
= ILB_STATUS_GENERIC
;
1420 case stat_disable_server
:
1421 ilbd_audit_server_event(&audit_sg_data
,
1422 ILBD_DISABLE_SERVER
, rc
, ucredp
);
1424 case stat_enable_server
:
1425 ilbd_audit_server_event(&audit_sg_data
,
1426 ILBD_ENABLE_SERVER
, rc
, ucredp
);
1429 goto rollback_rules
;
1432 if ((prop_name
= malloc(scf_name_len
)) == NULL
)
1433 return (ILB_STATUS_ENOMEM
);
1434 if ((valstr
= malloc(scf_val_len
)) == NULL
) {
1436 return (ILB_STATUS_ENOMEM
);
1439 (void) snprintf(valstr
, scf_val_len
, "%s;%d;%d-%d;%d",
1441 ntohs(tmp_srv
->isv_minport
),
1442 ntohs(tmp_srv
->isv_maxport
), nflags
);
1443 (void) snprintf(prop_name
, scf_name_len
, "server%d",
1447 case stat_disable_server
:
1448 rc
= i_ilbd_save_sg(isg
, ILBD_SCF_ENABLE_DISABLE
,
1450 if (rc
== ILB_STATUS_OK
)
1451 SET_SRV_DISABLED(&tmp_srv
->isv_srv
);
1453 case stat_enable_server
:
1454 rc
= i_ilbd_save_sg(isg
, ILBD_SCF_ENABLE_DISABLE
,
1456 if (rc
== ILB_STATUS_OK
)
1457 SET_SRV_ENABLED(&tmp_srv
->isv_srv
);
1462 if (rc
== ILB_STATUS_OK
) {
1464 case stat_disable_server
:
1465 ilbd_audit_server_event(&audit_sg_data
,
1466 ILBD_DISABLE_SERVER
, ILB_STATUS_OK
, ucredp
);
1468 case stat_enable_server
:
1469 ilbd_audit_server_event(&audit_sg_data
,
1470 ILBD_ENABLE_SERVER
, ILB_STATUS_OK
, ucredp
);
1473 return (ILB_STATUS_OK
);
1477 if (cmd
== stat_disable_server
)
1478 u_cmd
= stat_enable_server
;
1480 u_cmd
= stat_disable_server
;
1483 irl
= list_tail(&isg
->isg_rulelist
);
1485 irl
= list_prev(&isg
->isg_rulelist
, irl
);
1487 for (; irl
!= NULL
; irl
= list_prev(&isg
->isg_rulelist
, irl
)) {
1488 (void) ilbd_k_Xable_server(&tmp_srv
->isv_addr
,
1489 irl
->irl_name
, u_cmd
);
1490 if (!RULE_HAS_HC(irl
))
1493 if (u_cmd
== stat_disable_server
)
1494 (void) ilbd_hc_disable_server(irl
, &tmp_srv
->isv_srv
);
1496 (void) ilbd_hc_enable_server(irl
, &tmp_srv
->isv_srv
);
1503 ilbd_disable_server(ilb_sg_info_t
*sg
, const struct passwd
*ps
,
1506 return (ilbd_Xable_server(sg
, ps
, stat_disable_server
, ucredp
));
1510 ilbd_enable_server(ilb_sg_info_t
*sg
, const struct passwd
*ps
,
1513 return (ilbd_Xable_server(sg
, ps
, stat_enable_server
, ucredp
));
1517 * fill in the srvID for the given IP address in the 0th server
1520 ilbd_address_to_srvID(ilb_sg_info_t
*sg
, uint32_t *rbuf
, size_t *rbufsz
)
1522 ilbd_srv_t
*tmp_srv
;
1526 ilbd_reply_ok(rbuf
, rbufsz
);
1527 tsrv
= (ilb_sg_srv_t
*)&((ilb_comm_t
*)rbuf
)->ic_data
;
1528 *rbufsz
+= sizeof (ilb_sg_srv_t
);
1530 tmp_sg
= i_find_sg_byname(sg
->sg_name
);
1532 return (ILB_STATUS_SGUNAVAIL
);
1533 tsrv
->sgs_addr
= sg
->sg_servers
[0].sgs_addr
;
1535 tmp_srv
= i_find_srv(&tmp_sg
->isg_srvlist
, tsrv
, MODE_ADDR
);
1536 if (tmp_srv
== NULL
)
1537 return (ILB_STATUS_ENOENT
);
1539 (void) strlcpy(tsrv
->sgs_srvID
, tmp_srv
->isv_srvID
,
1540 sizeof (tsrv
->sgs_srvID
));
1542 return (ILB_STATUS_OK
);
1546 * fill in the address for the given serverID in the 0th server
1549 ilbd_srvID_to_address(ilb_sg_info_t
*sg
, uint32_t *rbuf
, size_t *rbufsz
)
1551 ilbd_srv_t
*tmp_srv
;
1555 ilbd_reply_ok(rbuf
, rbufsz
);
1556 tsrv
= (ilb_sg_srv_t
*)&((ilb_comm_t
*)rbuf
)->ic_data
;
1558 tmp_sg
= i_find_sg_byname(sg
->sg_name
);
1560 return (ILB_STATUS_SGUNAVAIL
);
1561 (void) strlcpy(tsrv
->sgs_srvID
, sg
->sg_servers
[0].sgs_srvID
,
1562 sizeof (tsrv
->sgs_srvID
));
1564 tmp_srv
= i_find_srv(&tmp_sg
->isg_srvlist
, tsrv
, MODE_SRVID
);
1565 if (tmp_srv
== NULL
)
1566 return (ILB_STATUS_ENOENT
);
1568 tsrv
->sgs_addr
= tmp_srv
->isv_addr
;
1569 *rbufsz
+= sizeof (ilb_sg_srv_t
);
1571 return (ILB_STATUS_OK
);
1575 * Map ilb_status errors to similar errno values from errno.h or
1576 * adt_event.h to be used for audit record
1579 ilberror2auditerror(ilb_status_t rc
)
1584 case ILB_STATUS_CFGAUTH
:
1585 audit_error
= ADT_FAIL_VALUE_AUTH
;
1587 case ILB_STATUS_ENOMEM
:
1588 audit_error
= ENOMEM
;
1590 case ILB_STATUS_ENOENT
:
1591 case ILB_STATUS_ENOHCINFO
:
1592 case ILB_STATUS_INVAL_HCTESTTYPE
:
1593 case ILB_STATUS_INVAL_CMD
:
1594 case ILB_STATUS_DUP_RULE
:
1595 case ILB_STATUS_ENORULE
:
1596 case ILB_STATUS_SGUNAVAIL
:
1597 audit_error
= ENOENT
;
1599 case ILB_STATUS_EINVAL
:
1600 case ILB_STATUS_MISMATCHSG
:
1601 case ILB_STATUS_MISMATCHH
:
1602 case ILB_STATUS_BADSG
:
1603 case ILB_STATUS_INVAL_SRVR
:
1604 case ILB_STATUS_INVAL_ENBSRVR
:
1605 case ILB_STATUS_BADPORT
:
1606 audit_error
= EINVAL
;
1608 case ILB_STATUS_EEXIST
:
1609 case ILB_STATUS_SGEXISTS
:
1610 audit_error
= EEXIST
;
1612 case ILB_STATUS_EWOULDBLOCK
:
1613 audit_error
= EWOULDBLOCK
;
1615 case ILB_STATUS_INPROGRESS
:
1616 audit_error
= EINPROGRESS
;
1618 case ILB_STATUS_INTERNAL
:
1619 case ILB_STATUS_CALLBACK
:
1620 case ILB_STATUS_PERMIT
:
1621 case ILB_STATUS_RULE_NO_HC
:
1622 audit_error
= ADT_FAIL_VALUE_PROGRAM
;
1624 case ILB_STATUS_SOCKET
:
1625 audit_error
= ENOTSOCK
;
1627 case ILB_STATUS_READ
:
1628 case ILB_STATUS_WRITE
:
1629 audit_error
= ENOTCONN
;
1631 case ILB_STATUS_SGINUSE
:
1632 audit_error
= EADDRINUSE
;
1634 case ILB_STATUS_SEND
:
1635 audit_error
= ECOMM
;
1637 case ILB_STATUS_SGFULL
:
1638 audit_error
= EOVERFLOW
;
1640 case ILB_STATUS_NAMETOOLONG
:
1641 audit_error
= ENAMETOOLONG
;
1643 case ILB_STATUS_SRVUNAVAIL
:
1644 audit_error
= EHOSTUNREACH
;
1647 audit_error
= ADT_FAIL_VALUE_UNKNOWN
;
1650 return (audit_error
);