2
* Copyright (c) 2012 Jiri Svoboda
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* - Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
* - The name of the author may not be used to endorse or promote products
15
* derived from this software without specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
#include <fibril_synch.h>
44
#include <sys/types.h>
51
static FIBRIL_MUTEX_INITIALIZE(client_list_lock);
52
static LIST_INITIALIZE(client_list);
54
/** Last used session identifier. Protected by @c client_list_lock */
55
static uint16_t inetping_ident = 0;
57
static inetping_client_t *inetping_client_find(uint16_t);
59
static int inetping_send(inetping_client_t *client, inetping_sdu_t *sdu)
61
return icmp_ping_send(client->ident, sdu);
64
static int inetping_get_srcaddr(inetping_client_t *client, inet_addr_t *remote,
67
return inet_get_srcaddr(remote, ICMP_TOS, local);
70
int inetping_recv(uint16_t ident, inetping_sdu_t *sdu)
72
inetping_client_t *client;
76
client = inetping_client_find(ident);
78
log_msg(LVL_DEBUG, "Unknown ICMP ident. Dropping.");
82
exch = async_exchange_begin(client->sess);
84
aid_t req = async_send_3(exch, INETPING_EV_RECV, sdu->src.ipv4,
85
sdu->dest.ipv4, sdu->seq_no, &answer);
86
int rc = async_data_write_start(exch, sdu->data, sdu->size);
87
async_exchange_end(exch);
95
async_wait_for(req, &retval);
103
static void inetping_send_srv(inetping_client_t *client, ipc_callid_t callid,
109
log_msg(LVL_DEBUG, "inetping_send_srv()");
111
rc = async_data_write_accept((void **) &sdu.data, false, 0, 0, 0,
114
async_answer_0(callid, rc);
118
sdu.src.ipv4 = IPC_GET_ARG1(*call);
119
sdu.dest.ipv4 = IPC_GET_ARG2(*call);
120
sdu.seq_no = IPC_GET_ARG3(*call);
122
rc = inetping_send(client, &sdu);
125
async_answer_0(callid, rc);
128
static void inetping_get_srcaddr_srv(inetping_client_t *client,
129
ipc_callid_t callid, ipc_call_t *call)
135
log_msg(LVL_DEBUG, "inetping_get_srcaddr_srv()");
137
remote.ipv4 = IPC_GET_ARG1(*call);
140
rc = inetping_get_srcaddr(client, &remote, &local);
141
async_answer_1(callid, rc, local.ipv4);
144
static int inetping_client_init(inetping_client_t *client)
146
async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
151
link_initialize(&client->client_list);
153
fibril_mutex_lock(&client_list_lock);
154
client->ident = ++inetping_ident;
155
list_append(&client->client_list, &client_list);
156
fibril_mutex_unlock(&client_list_lock);
161
static void inetping_client_fini(inetping_client_t *client)
163
async_hangup(client->sess);
166
fibril_mutex_lock(&client_list_lock);
167
list_remove(&client->client_list);
168
fibril_mutex_unlock(&client_list_lock);
171
static inetping_client_t *inetping_client_find(uint16_t ident)
173
fibril_mutex_lock(&client_list_lock);
175
list_foreach(client_list, link) {
176
inetping_client_t *client = list_get_instance(link,
177
inetping_client_t, client_list);
179
if (client->ident == ident) {
180
fibril_mutex_unlock(&client_list_lock);
185
fibril_mutex_unlock(&client_list_lock);
189
void inetping_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
191
inetping_client_t client;
194
log_msg(LVL_DEBUG, "inetping_conn()");
196
/* Accept the connection */
197
async_answer_0(iid, EOK);
199
rc = inetping_client_init(&client);
205
ipc_callid_t callid = async_get_call(&call);
206
sysarg_t method = IPC_GET_IMETHOD(call);
209
/* The other side has hung up */
210
async_answer_0(callid, EOK);
216
inetping_send_srv(&client, callid, &call);
218
case INETPING_GET_SRCADDR:
219
inetping_get_srcaddr_srv(&client, callid, &call);
222
async_answer_0(callid, EINVAL);
226
inetping_client_fini(&client);