2 * Copyright (c) 2011-2014 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include "dmsg_local.h"
38 static void master_auth_signal(dmsg_iocom_t
*iocom
);
39 static void master_auth_rxmsg(dmsg_msg_t
*msg
);
40 static void master_link_signal(dmsg_iocom_t
*iocom
);
41 static void master_link_rxmsg(dmsg_msg_t
*msg
);
44 * Service an accepted connection (runs as a pthread)
46 * (also called from a couple of other places)
49 dmsg_master_service(void *data
)
51 dmsg_master_service_info_t
*info
= data
;
55 pthread_detach(pthread_self());
57 dmsg_iocom_init(&iocom
,
59 (info
->altmsg_callback
? info
->altfd
: -1),
62 info
->usrmsg_callback
,
63 info
->altmsg_callback
);
65 iocom
.flags
&= ~DMSG_IOCOMF_CLOSEALT
;
67 dmsg_iocom_label(&iocom
, "%s", info
->label
);
71 dmsg_iocom_core(&iocom
);
72 dmsg_iocom_done(&iocom
);
75 "iocom on fd %d terminated error rx=%d, tx=%d\n",
76 info
->fd
, iocom
.ioq_rx
.error
, iocom
.ioq_tx
.error
);
78 info
->fd
= -1; /* safety */
79 if (info
->exit_callback
)
80 info
->exit_callback(info
->handle
);
86 /************************************************************************
88 ************************************************************************
90 * Callback via dmsg_iocom_core().
92 * Additional messaging-based authentication must occur before normal
93 * message operation. The connection has already been encrypted at
96 static void master_auth_conn_rx(dmsg_msg_t
*msg
);
100 master_auth_signal(dmsg_iocom_t
*iocom
)
105 * Transmit LNK_CONN, enabling the SPAN protocol if both sides
108 * XXX put additional authentication states here?
110 msg
= dmsg_msg_alloc(&iocom
->state0
, 0,
111 DMSG_LNK_CONN
| DMSGF_CREATE
,
112 master_auth_conn_rx
, NULL
);
113 msg
->any
.lnk_conn
.peer_mask
= (uint64_t)-1;
114 msg
->any
.lnk_conn
.peer_type
= DMSG_PEER_ROUTER
;
115 msg
->any
.lnk_conn
.peer_mask
= (uint64_t)-1;
119 dmsg_iocom_restate(iocom
, master_link_signal
, master_link_rxmsg
);
124 master_auth_conn_rx(dmsg_msg_t
*msg
)
126 if (msg
->any
.head
.cmd
& DMSGF_DELETE
)
127 dmsg_msg_reply(msg
, 0);
132 master_auth_rxmsg(dmsg_msg_t
*msg __unused
)
136 /************************************************************************
137 * POST-AUTHENTICATION SERVICE MSGS *
138 ************************************************************************
140 * Callback via dmsg_iocom_core().
144 master_link_signal(dmsg_iocom_t
*iocom
)
146 dmsg_msg_lnk_signal(iocom
);
151 master_link_rxmsg(dmsg_msg_t
*msg
)
158 * If the message state has a function established we just
159 * call the function, otherwise we call the appropriate
160 * link-level protocol related to the original command and
161 * let it sort it out.
163 * Non-transactional one-off messages, on the otherhand,
164 * might have REPLY set.
167 iocom
= state
->iocom
;
168 cmd
= (state
!= &iocom
->state0
) ? state
->icmd
: msg
->any
.head
.cmd
;
172 * Call function or router
174 assert(state
!= &iocom
->state0
);
180 switch(cmd
& DMSGF_PROTOS
) {
188 iocom
->usrmsg_callback(msg
, 1);
195 * This is called from the master node to process a received debug
196 * shell command. We process the command, outputting the results,
197 * then finish up by outputting another prompt.
200 dmsg_msg_dbg(dmsg_msg_t
*msg
)
202 dmsg_iocom_t
*iocom
= msg
->state
->iocom
;
204 switch(msg
->tcmd
& DMSGF_CMDSWMASK
) {
207 * This is a command which we must process.
208 * When we are finished we generate a final reply.
211 msg
->aux_data
[msg
->aux_size
- 1] = 0;
212 iocom
->usrmsg_callback(msg
, 0);
214 case DMSG_DBG_SHELL
| DMSGF_REPLY
:
216 * A reply just prints out the string. No newline is added
217 * (it is expected to be embedded if desired).
220 msg
->aux_data
[msg
->aux_size
- 1] = 0;
222 write(2, msg
->aux_data
, strlen(msg
->aux_data
));
225 iocom
->usrmsg_callback(msg
, 1);
231 * Returns text debug output to the original defined by (msg). (msg) is
232 * not modified and stays intact. We use a one-way message with REPLY set
233 * to distinguish between a debug command and debug terminal output.
235 * To prevent loops dmsg_printf() can filter the message (cmd) related
236 * to the dmsg_printf(). We filter out DBG messages.
239 dmsg_printf(dmsg_iocom_t
*iocom
, const char *ctl
, ...)
247 vsnprintf(buf
, sizeof(buf
), ctl
, va
);
249 len
= strlen(buf
) + 1;
251 rmsg
= dmsg_msg_alloc(&iocom
->state0
, len
,
252 DMSG_DBG_SHELL
| DMSGF_REPLY
,
254 bcopy(buf
, rmsg
->aux_data
, len
);
256 dmsg_msg_write(rmsg
);