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

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since edeee9f was edeee9f, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Fix header guards and doxy groups of stuff moved out of libc

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Copyright (c) 2021 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
79 async_answer_0(icall, rc);
80}
81
82static void iplink_set_mac48_srv(iplink_srv_t *srv, ipc_call_t *icall)
83{
84 errno_t rc;
85 size_t size;
86 eth_addr_t mac;
87
88 ipc_call_t call;
89 if (!async_data_write_receive(&call, &size)) {
90 async_answer_0(&call, EREFUSED);
91 async_answer_0(icall, EREFUSED);
92 }
93
94 rc = srv->ops->set_mac48(srv, &mac);
95 if (rc != EOK) {
96 async_answer_0(icall, rc);
97 return;
98 }
99
100 rc = async_data_read_finalize(&call, &mac, sizeof(eth_addr_t));
101 if (rc != EOK)
102 async_answer_0(&call, rc);
103
104 async_answer_0(icall, rc);
105}
106
107static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_call_t *icall)
108{
109 ipc_call_t call;
110 size_t size;
111 if (!async_data_write_receive(&call, &size)) {
112 async_answer_0(&call, EREFUSED);
113 async_answer_0(icall, EREFUSED);
114 return;
115 }
116
117 if (size != sizeof(inet_addr_t)) {
118 async_answer_0(&call, EINVAL);
119 async_answer_0(icall, EINVAL);
120 return;
121 }
122
123 inet_addr_t addr;
124 errno_t rc = async_data_write_finalize(&call, &addr, size);
125 if (rc != EOK) {
126 async_answer_0(&call, rc);
127 async_answer_0(icall, rc);
128 }
129
130 rc = srv->ops->addr_add(srv, &addr);
131 async_answer_0(icall, rc);
132}
133
134static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_call_t *icall)
135{
136 ipc_call_t call;
137 size_t size;
138 if (!async_data_write_receive(&call, &size)) {
139 async_answer_0(&call, EREFUSED);
140 async_answer_0(icall, EREFUSED);
141 return;
142 }
143
144 if (size != sizeof(inet_addr_t)) {
145 async_answer_0(&call, EINVAL);
146 async_answer_0(icall, EINVAL);
147 return;
148 }
149
150 inet_addr_t addr;
151 errno_t rc = async_data_write_finalize(&call, &addr, size);
152 if (rc != EOK) {
153 async_answer_0(&call, rc);
154 async_answer_0(icall, rc);
155 }
156
157 rc = srv->ops->addr_remove(srv, &addr);
158 async_answer_0(icall, rc);
159}
160
161static void iplink_send_srv(iplink_srv_t *srv, ipc_call_t *icall)
162{
163 iplink_sdu_t sdu;
164
165 sdu.src = ipc_get_arg1(icall);
166 sdu.dest = ipc_get_arg2(icall);
167
168 errno_t rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
169 &sdu.size);
170 if (rc != EOK) {
171 async_answer_0(icall, rc);
172 return;
173 }
174
175 rc = srv->ops->send(srv, &sdu);
176 free(sdu.data);
177 async_answer_0(icall, rc);
178}
179
180static void iplink_send6_srv(iplink_srv_t *srv, ipc_call_t *icall)
181{
182 iplink_sdu6_t sdu;
183
184 ipc_call_t call;
185 size_t size;
186 if (!async_data_write_receive(&call, &size)) {
187 async_answer_0(&call, EREFUSED);
188 async_answer_0(icall, EREFUSED);
189 return;
190 }
191
192 if (size != sizeof(eth_addr_t)) {
193 async_answer_0(&call, EINVAL);
194 async_answer_0(icall, EINVAL);
195 return;
196 }
197
198 errno_t rc = async_data_write_finalize(&call, &sdu.dest, size);
199 if (rc != EOK) {
200 async_answer_0(&call, rc);
201 async_answer_0(icall, rc);
202 }
203
204 rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
205 &sdu.size);
206 if (rc != EOK) {
207 async_answer_0(icall, rc);
208 return;
209 }
210
211 rc = srv->ops->send6(srv, &sdu);
212 free(sdu.data);
213 async_answer_0(icall, rc);
214}
215
216void iplink_srv_init(iplink_srv_t *srv)
217{
218 fibril_mutex_initialize(&srv->lock);
219 srv->connected = false;
220 srv->ops = NULL;
221 srv->arg = NULL;
222 srv->client_sess = NULL;
223}
224
225errno_t iplink_conn(ipc_call_t *icall, void *arg)
226{
227 iplink_srv_t *srv = (iplink_srv_t *) arg;
228 errno_t rc;
229
230 fibril_mutex_lock(&srv->lock);
231 if (srv->connected) {
232 fibril_mutex_unlock(&srv->lock);
233 async_answer_0(icall, EBUSY);
234 return EBUSY;
235 }
236
237 srv->connected = true;
238 fibril_mutex_unlock(&srv->lock);
239
240 /* Accept the connection */
241 async_accept_0(icall);
242
243 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
244 if (sess == NULL)
245 return ENOMEM;
246
247 srv->client_sess = sess;
248
249 rc = srv->ops->open(srv);
250 if (rc != EOK)
251 return rc;
252
253 while (true) {
254 ipc_call_t call;
255 async_get_call(&call);
256 sysarg_t method = ipc_get_imethod(&call);
257
258 if (!method) {
259 /* The other side has hung up */
260 fibril_mutex_lock(&srv->lock);
261 srv->connected = false;
262 fibril_mutex_unlock(&srv->lock);
263 async_answer_0(&call, EOK);
264 break;
265 }
266
267 switch (method) {
268 case IPLINK_GET_MTU:
269 iplink_get_mtu_srv(srv, &call);
270 break;
271 case IPLINK_GET_MAC48:
272 iplink_get_mac48_srv(srv, &call);
273 break;
274 case IPLINK_SET_MAC48:
275 iplink_set_mac48_srv(srv, &call);
276 break;
277 case IPLINK_SEND:
278 iplink_send_srv(srv, &call);
279 break;
280 case IPLINK_SEND6:
281 iplink_send6_srv(srv, &call);
282 break;
283 case IPLINK_ADDR_ADD:
284 iplink_addr_add_srv(srv, &call);
285 break;
286 case IPLINK_ADDR_REMOVE:
287 iplink_addr_remove_srv(srv, &call);
288 break;
289 default:
290 async_answer_0(&call, EINVAL);
291 }
292 }
293
294 return srv->ops->close(srv);
295}
296
297/* XXX Version should be part of @a sdu */
298errno_t iplink_ev_recv(iplink_srv_t *srv, iplink_recv_sdu_t *sdu, ip_ver_t ver)
299{
300 if (srv->client_sess == NULL)
301 return EIO;
302
303 async_exch_t *exch = async_exchange_begin(srv->client_sess);
304
305 ipc_call_t answer;
306 aid_t req = async_send_1(exch, IPLINK_EV_RECV, (sysarg_t)ver,
307 &answer);
308
309 errno_t rc = async_data_write_start(exch, sdu->data, sdu->size);
310 async_exchange_end(exch);
311
312 if (rc != EOK) {
313 async_forget(req);
314 return rc;
315 }
316
317 errno_t retval;
318 async_wait_for(req, &retval);
319 if (retval != EOK)
320 return retval;
321
322 return EOK;
323}
324
325errno_t iplink_ev_change_addr(iplink_srv_t *srv, eth_addr_t *addr)
326{
327 if (srv->client_sess == NULL)
328 return EIO;
329
330 async_exch_t *exch = async_exchange_begin(srv->client_sess);
331
332 ipc_call_t answer;
333 aid_t req = async_send_0(exch, IPLINK_EV_CHANGE_ADDR, &answer);
334
335 errno_t rc = async_data_write_start(exch, addr, sizeof(eth_addr_t));
336 async_exchange_end(exch);
337
338 if (rc != EOK) {
339 async_forget(req);
340 return rc;
341 }
342
343 errno_t retval;
344 async_wait_for(req, &retval);
345 if (retval != EOK)
346 return retval;
347
348 return EOK;
349}
350
351/** @}
352 */
Note: See TracBrowser for help on using the repository browser.