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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
31 #include <dhcpagent_ipc.h>
35 #include "interface.h"
36 #include "ipc_action.h"
39 static iu_tq_callback_t ipc_action_timeout
;
42 * ipc_action_init(): initializes the ipc_action structure
44 * input: ipc_action_t *: the structure to initialize
49 ipc_action_init(ipc_action_t
*ia
)
55 ia
->ia_request
= NULL
;
59 * ipc_action_start(): starts an ipc_action request on a DHCP state machine
61 * input: dhcp_smach_t *: the state machine to start the action on
62 * ipc_action_t *: request structure
63 * output: B_TRUE if the request is started successfully, B_FALSE otherwise
64 * original request is still valid on failure, consumed otherwise.
68 ipc_action_start(dhcp_smach_t
*dsmp
, ipc_action_t
*iareq
)
70 struct ipc_action
*ia
= &dsmp
->dsm_ia
;
72 if (ia
->ia_fd
!= -1 || ia
->ia_tid
!= -1 || iareq
->ia_fd
== -1) {
73 dhcpmsg(MSG_CRIT
, "ipc_action_start: attempted restart on %s",
78 if (!async_cancel(dsmp
)) {
79 dhcpmsg(MSG_WARNING
, "ipc_action_start: unable to cancel "
80 "action on %s", dsmp
->dsm_name
);
84 if (iareq
->ia_request
->timeout
== DHCP_IPC_WAIT_DEFAULT
)
85 iareq
->ia_request
->timeout
= DHCP_IPC_DEFAULT_WAIT
;
87 if (iareq
->ia_request
->timeout
== DHCP_IPC_WAIT_FOREVER
) {
90 iareq
->ia_tid
= iu_schedule_timer(tq
,
91 iareq
->ia_request
->timeout
, ipc_action_timeout
, dsmp
);
93 if (iareq
->ia_tid
== -1) {
94 dhcpmsg(MSG_ERROR
, "ipc_action_start: failed to set "
96 dhcp_ipc_type_to_string(iareq
->ia_cmd
),
106 /* We've taken ownership, so the input request is now invalid */
107 ipc_action_init(iareq
);
109 dhcpmsg(MSG_DEBUG
, "ipc_action_start: started %s (command %d) on %s",
110 dhcp_ipc_type_to_string(ia
->ia_cmd
), ia
->ia_cmd
, dsmp
->dsm_name
);
112 dsmp
->dsm_dflags
|= DHCP_IF_BUSY
;
114 /* This cannot fail due to the async_cancel above */
115 (void) async_start(dsmp
, ia
->ia_cmd
, B_TRUE
);
121 * ipc_action_finish(): completes an ipc_action request on an interface
123 * input: dhcp_smach_t *: the state machine to complete the action on
124 * int: the reason why the action finished (nonzero on error)
129 ipc_action_finish(dhcp_smach_t
*dsmp
, int reason
)
131 struct ipc_action
*ia
= &dsmp
->dsm_ia
;
133 dsmp
->dsm_dflags
&= ~DHCP_IF_BUSY
;
135 if (dsmp
->dsm_ia
.ia_fd
== -1) {
137 "ipc_action_finish: attempted to finish unknown action "
138 "on %s", dsmp
->dsm_name
);
143 "ipc_action_finish: finished %s (command %d) on %s: %d",
144 dhcp_ipc_type_to_string(ia
->ia_cmd
), (int)ia
->ia_cmd
,
145 dsmp
->dsm_name
, reason
);
148 * if we can't cancel this timer, we're really in the
149 * twilight zone. however, as long as we don't drop the
150 * reference to the state machine, it shouldn't hurt us
153 if (dsmp
->dsm_ia
.ia_tid
!= -1 &&
154 iu_cancel_timer(tq
, dsmp
->dsm_ia
.ia_tid
, NULL
) == 1) {
155 dsmp
->dsm_ia
.ia_tid
= -1;
162 send_error_reply(ia
, reason
);
168 * ipc_action_timeout(): times out an ipc_action on a state machine (the
169 * request continues asynchronously, however)
171 * input: iu_tq_t *: unused
172 * void *: the dhcp_smach_t * the ipc_action was pending on
178 ipc_action_timeout(iu_tq_t
*tq
, void *arg
)
180 dhcp_smach_t
*dsmp
= arg
;
181 struct ipc_action
*ia
= &dsmp
->dsm_ia
;
183 dsmp
->dsm_dflags
&= ~DHCP_IF_BUSY
;
187 dhcpmsg(MSG_VERBOSE
, "ipc timeout waiting for agent to complete "
188 "%s (command %d) for %s", dhcp_ipc_type_to_string(ia
->ia_cmd
),
189 ia
->ia_cmd
, dsmp
->dsm_name
);
191 send_error_reply(ia
, DHCP_IPC_E_TIMEOUT
);
198 * send_ok_reply(): sends an "ok" reply to a request and closes the ipc
201 * input: ipc_action_t *: the request to reply to
203 * note: the request is freed (thus the request must be on the heap).
207 send_ok_reply(ipc_action_t
*ia
)
209 send_error_reply(ia
, 0);
213 * send_error_reply(): sends an "error" reply to a request and closes the ipc
216 * input: ipc_action_t *: the request to reply to
217 * int: the error to send back on the ipc connection
219 * note: the request is freed (thus the request must be on the heap).
223 send_error_reply(ipc_action_t
*ia
, int error
)
225 send_data_reply(ia
, error
, DHCP_TYPE_NONE
, NULL
, 0);
229 * send_data_reply(): sends a reply to a request and closes the ipc connection
231 * input: ipc_action_t *: the request to reply to
232 * int: the status to send back on the ipc connection (zero for
233 * success, DHCP_IPC_E_* otherwise).
234 * dhcp_data_type_t: the type of the payload in the reply
235 * const void *: the payload for the reply, or NULL if there is no
237 * size_t: the size of the payload
239 * note: the request is freed (thus the request must be on the heap).
243 send_data_reply(ipc_action_t
*ia
, int error
, dhcp_data_type_t type
,
244 const void *buffer
, size_t size
)
246 dhcp_ipc_reply_t
*reply
;
249 if (ia
->ia_fd
== -1 || ia
->ia_request
== NULL
)
252 reply
= dhcp_ipc_alloc_reply(ia
->ia_request
, error
, buffer
, size
,
255 dhcpmsg(MSG_ERR
, "send_data_reply: cannot allocate reply");
257 } else if ((retval
= dhcp_ipc_send_reply(ia
->ia_fd
, reply
)) != 0) {
258 dhcpmsg(MSG_ERROR
, "send_data_reply: dhcp_ipc_send_reply: %s",
259 dhcp_ipc_strerror(retval
));
263 * free the request since we've now used it to send our reply.
264 * we can also close the socket since the reply has been sent.
268 free(ia
->ia_request
);
269 if (ia
->ia_eid
!= -1)
270 (void) iu_unregister_event(eh
, ia
->ia_eid
, NULL
);
271 (void) dhcp_ipc_close(ia
->ia_fd
);
272 ia
->ia_request
= NULL
;