source: mainline/uspace/lib/c/generic/iplink_srv.c@ 0c322fa

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

iplink_ev_recv() should use ip_ver_t instead of AF.

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