source: mainline/uspace/lib/inet/src/iplink_srv.c

Last change on this file was cdd6fc9, checked in by Jiri Svoboda <jiri@…>, 2 years ago

Add missing replies in IPC error paths

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 * Copyright (c) 2023 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29/** @addtogroup libinet
30 * @{
31 */
32/**
33 * @file
34 * @brief IP link server stub
35 */
36
37#include <errno.h>
38#include <inet/eth_addr.h>
39#include <ipc/iplink.h>
40#include <stdlib.h>
41#include <stddef.h>
42#include <inet/addr.h>
43#include <inet/iplink_srv.h>
44
45static void iplink_get_mtu_srv(iplink_srv_t *srv, ipc_call_t *call)
46{
47 size_t mtu;
48 errno_t rc = srv->ops->get_mtu(srv, &mtu);
49 async_answer_1(call, rc, mtu);
50}
51
52static void iplink_get_mac48_srv(iplink_srv_t *srv, ipc_call_t *icall)
53{
54 eth_addr_t mac;
55 errno_t rc = srv->ops->get_mac48(srv, &mac);
56 if (rc != EOK) {
57 async_answer_0(icall, rc);
58 return;
59 }
60
61 ipc_call_t call;
62 size_t size;
63 if (!async_data_read_receive(&call, &size)) {
64 async_answer_0(&call, EREFUSED);
65 async_answer_0(icall, EREFUSED);
66 return;
67 }
68
69 if (size != sizeof(eth_addr_t)) {
70 async_answer_0(&call, EINVAL);
71 async_answer_0(icall, EINVAL);
72 return;
73 }
74
75 rc = async_data_read_finalize(&call, &mac, size);
76 if (rc != EOK) {
77 async_answer_0(&call, rc);
78 async_answer_0(icall, rc);
79 return;
80 }
81
82 async_answer_0(icall, rc);
83}
84
85static void iplink_set_mac48_srv(iplink_srv_t *srv, ipc_call_t *icall)
86{
87 errno_t rc;
88 size_t size;
89 eth_addr_t mac;
90
91 ipc_call_t call;
92 if (!async_data_write_receive(&call, &size)) {
93 async_answer_0(&call, EREFUSED);
94 async_answer_0(icall, EREFUSED);
95 }
96
97 rc = srv->ops->set_mac48(srv, &mac);
98 if (rc != EOK) {
99 async_answer_0(&call, rc);
100 async_answer_0(icall, rc);
101 return;
102 }
103
104 rc = async_data_read_finalize(&call, &mac, sizeof(eth_addr_t));
105 if (rc != EOK) {
106 async_answer_0(&call, rc);
107 async_answer_0(icall, rc);
108 return;
109 }
110
111 async_answer_0(icall, rc);
112}
113
114static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_call_t *icall)
115{
116 ipc_call_t call;
117 size_t size;
118
119 if (!async_data_write_receive(&call, &size)) {
120 async_answer_0(&call, EREFUSED);
121 async_answer_0(icall, EREFUSED);
122 return;
123 }
124
125 if (size != sizeof(inet_addr_t)) {
126 async_answer_0(&call, EINVAL);
127 async_answer_0(icall, EINVAL);
128 return;
129 }
130
131 inet_addr_t addr;
132 errno_t rc = async_data_write_finalize(&call, &addr, size);
133 if (rc != EOK) {
134 async_answer_0(&call, rc);
135 async_answer_0(icall, rc);
136 return;
137 }
138
139 rc = srv->ops->addr_add(srv, &addr);
140 async_answer_0(icall, rc);
141}
142
143static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_call_t *icall)
144{
145 ipc_call_t call;
146 size_t size;
147
148 if (!async_data_write_receive(&call, &size)) {
149 async_answer_0(&call, EREFUSED);
150 async_answer_0(icall, EREFUSED);
151 return;
152 }
153
154 if (size != sizeof(inet_addr_t)) {
155 async_answer_0(&call, EINVAL);
156 async_answer_0(icall, EINVAL);
157 return;
158 }
159
160 inet_addr_t addr;
161 errno_t rc = async_data_write_finalize(&call, &addr, size);
162 if (rc != EOK) {
163 async_answer_0(&call, rc);
164 async_answer_0(icall, rc);
165 return;
166 }
167
168 rc = srv->ops->addr_remove(srv, &addr);
169 async_answer_0(icall, rc);
170}
171
172static void iplink_send_srv(iplink_srv_t *srv, ipc_call_t *icall)
173{
174 iplink_sdu_t sdu;
175
176 sdu.src = ipc_get_arg1(icall);
177 sdu.dest = ipc_get_arg2(icall);
178
179 errno_t rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
180 &sdu.size);
181 if (rc != EOK) {
182 async_answer_0(icall, rc);
183 return;
184 }
185
186 rc = srv->ops->send(srv, &sdu);
187 free(sdu.data);
188 async_answer_0(icall, rc);
189}
190
191static void iplink_send6_srv(iplink_srv_t *srv, ipc_call_t *icall)
192{
193 iplink_sdu6_t sdu;
194 ipc_call_t call;
195 size_t size;
196
197 if (!async_data_write_receive(&call, &size)) {
198 async_answer_0(&call, EREFUSED);
199 async_answer_0(icall, EREFUSED);
200 return;
201 }
202
203 if (size != sizeof(eth_addr_t)) {
204 async_answer_0(&call, EINVAL);
205 async_answer_0(icall, EINVAL);
206 return;
207 }
208
209 errno_t rc = async_data_write_finalize(&call, &sdu.dest, size);
210 if (rc != EOK) {
211 async_answer_0(&call, rc);
212 async_answer_0(icall, rc);
213 }
214
215 rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
216 &sdu.size);
217 if (rc != EOK) {
218 async_answer_0(icall, rc);
219 return;
220 }
221
222 rc = srv->ops->send6(srv, &sdu);
223 free(sdu.data);
224 async_answer_0(icall, rc);
225}
226
227void iplink_srv_init(iplink_srv_t *srv)
228{
229 fibril_mutex_initialize(&srv->lock);
230 srv->connected = false;
231 srv->ops = NULL;
232 srv->arg = NULL;
233 srv->client_sess = NULL;
234}
235
236errno_t iplink_conn(ipc_call_t *icall, void *arg)
237{
238 iplink_srv_t *srv = (iplink_srv_t *) arg;
239 errno_t rc;
240
241 fibril_mutex_lock(&srv->lock);
242 if (srv->connected) {
243 fibril_mutex_unlock(&srv->lock);
244 async_answer_0(icall, EBUSY);
245 return EBUSY;
246 }
247
248 srv->connected = true;
249 fibril_mutex_unlock(&srv->lock);
250
251 /* Accept the connection */
252 async_accept_0(icall);
253
254 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
255 if (sess == NULL)
256 return ENOMEM;
257
258 srv->client_sess = sess;
259
260 rc = srv->ops->open(srv);
261 if (rc != EOK)
262 return rc;
263
264 while (true) {
265 ipc_call_t call;
266 async_get_call(&call);
267 sysarg_t method = ipc_get_imethod(&call);
268
269 if (!method) {
270 /* The other side has hung up */
271 fibril_mutex_lock(&srv->lock);
272 srv->connected = false;
273 fibril_mutex_unlock(&srv->lock);
274 async_answer_0(&call, EOK);
275 break;
276 }
277
278 switch (method) {
279 case IPLINK_GET_MTU:
280 iplink_get_mtu_srv(srv, &call);
281 break;
282 case IPLINK_GET_MAC48:
283 iplink_get_mac48_srv(srv, &call);
284 break;
285 case IPLINK_SET_MAC48:
286 iplink_set_mac48_srv(srv, &call);
287 break;
288 case IPLINK_SEND:
289 iplink_send_srv(srv, &call);
290 break;
291 case IPLINK_SEND6:
292 iplink_send6_srv(srv, &call);
293 break;
294 case IPLINK_ADDR_ADD:
295 iplink_addr_add_srv(srv, &call);
296 break;
297 case IPLINK_ADDR_REMOVE:
298 iplink_addr_remove_srv(srv, &call);
299 break;
300 default:
301 async_answer_0(&call, EINVAL);
302 }
303 }
304
305 return srv->ops->close(srv);
306}
307
308/* XXX Version should be part of @a sdu */
309errno_t iplink_ev_recv(iplink_srv_t *srv, iplink_recv_sdu_t *sdu, ip_ver_t ver)
310{
311 if (srv->client_sess == NULL)
312 return EIO;
313
314 async_exch_t *exch = async_exchange_begin(srv->client_sess);
315
316 ipc_call_t answer;
317 aid_t req = async_send_1(exch, IPLINK_EV_RECV, (sysarg_t)ver,
318 &answer);
319
320 errno_t rc = async_data_write_start(exch, sdu->data, sdu->size);
321 async_exchange_end(exch);
322
323 if (rc != EOK) {
324 async_forget(req);
325 return rc;
326 }
327
328 errno_t retval;
329 async_wait_for(req, &retval);
330 if (retval != EOK)
331 return retval;
332
333 return EOK;
334}
335
336errno_t iplink_ev_change_addr(iplink_srv_t *srv, eth_addr_t *addr)
337{
338 if (srv->client_sess == NULL)
339 return EIO;
340
341 async_exch_t *exch = async_exchange_begin(srv->client_sess);
342
343 ipc_call_t answer;
344 aid_t req = async_send_0(exch, IPLINK_EV_CHANGE_ADDR, &answer);
345
346 errno_t rc = async_data_write_start(exch, addr, sizeof(eth_addr_t));
347 async_exchange_end(exch);
348
349 if (rc != EOK) {
350 async_forget(req);
351 return rc;
352 }
353
354 errno_t retval;
355 async_wait_for(req, &retval);
356 if (retval != EOK)
357 return retval;
358
359 return EOK;
360}
361
362/** @}
363 */
Note: See TracBrowser for help on using the repository browser.