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

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