source: mainline/uspace/lib/c/generic/iplink_srv.c@ 5e801dc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5e801dc was fafb8e5, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Mechanically lowercase IPC_SET_*/IPC_GET_*

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