source: mainline/uspace/lib/c/generic/iplink_srv.c@ d7f2cd6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d7f2cd6 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
Line 
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 */
36
37#include <errno.h>
38#include <ipc/iplink.h>
39#include <stdlib.h>
40#include <sys/types.h>
41#include <inet/addr.h>
42#include <inet/iplink_srv.h>
43
44static void iplink_get_mtu_srv(iplink_srv_t *srv, ipc_callid_t callid,
45 ipc_call_t *call)
46{
47 size_t mtu;
48 int rc = srv->ops->get_mtu(srv, &mtu);
49 async_answer_1(callid, rc, mtu);
50}
51
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
83static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_callid_t iid,
84 ipc_call_t *icall)
85{
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);
109}
110
111static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_callid_t iid,
112 ipc_call_t *icall)
113{
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);
137}
138
139static void iplink_send_srv(iplink_srv_t *srv, ipc_callid_t iid,
140 ipc_call_t *icall)
141{
142 iplink_sdu_t sdu;
143
144 sdu.src = IPC_GET_ARG1(*icall);
145 sdu.dest = IPC_GET_ARG2(*icall);
146
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);
151 return;
152 }
153
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;
163
164 ipc_callid_t callid;
165 size_t size;
166 if (!async_data_write_receive(&callid, &size)) {
167 async_answer_0(callid, EREFUSED);
168 async_answer_0(iid, EREFUSED);
169 return;
170 }
171
172 if (size != sizeof(addr48_t)) {
173 async_answer_0(callid, EINVAL);
174 async_answer_0(iid, EINVAL);
175 return;
176 }
177
178 int rc = async_data_write_finalize(callid, &sdu.dest, size);
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);
186 if (rc != EOK) {
187 async_answer_0(iid, rc);
188 return;
189 }
190
191 rc = srv->ops->send6(srv, &sdu);
192 free(sdu.data);
193 async_answer_0(iid, rc);
194}
195
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
205int iplink_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
206{
207 iplink_srv_t *srv = (iplink_srv_t *) arg;
208 int rc;
209
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 }
216
217 srv->connected = true;
218 fibril_mutex_unlock(&srv->lock);
219
220 /* Accept the connection */
221 async_answer_0(iid, EOK);
222
223 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
224 if (sess == NULL)
225 return ENOMEM;
226
227 srv->client_sess = sess;
228
229 rc = srv->ops->open(srv);
230 if (rc != EOK)
231 return rc;
232
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);
237
238 if (!method) {
239 /* The other side has hung up */
240 fibril_mutex_lock(&srv->lock);
241 srv->connected = false;
242 fibril_mutex_unlock(&srv->lock);
243 async_answer_0(callid, EOK);
244 break;
245 }
246
247 switch (method) {
248 case IPLINK_GET_MTU:
249 iplink_get_mtu_srv(srv, callid, &call);
250 break;
251 case IPLINK_GET_MAC48:
252 iplink_get_mac48_srv(srv, callid, &call);
253 break;
254 case IPLINK_SEND:
255 iplink_send_srv(srv, callid, &call);
256 break;
257 case IPLINK_SEND6:
258 iplink_send6_srv(srv, callid, &call);
259 break;
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;
266 default:
267 async_answer_0(callid, EINVAL);
268 }
269 }
270
271 return srv->ops->close(srv);
272}
273
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)
276{
277 if (srv->client_sess == NULL)
278 return EIO;
279
280 async_exch_t *exch = async_exchange_begin(srv->client_sess);
281
282 ipc_call_t answer;
283 aid_t req = async_send_1(exch, IPLINK_EV_RECV, (sysarg_t)ver,
284 &answer);
285
286 int rc = async_data_write_start(exch, sdu->data, sdu->size);
287 async_exchange_end(exch);
288
289 if (rc != EOK) {
290 async_forget(req);
291 return rc;
292 }
293
294 sysarg_t retval;
295 async_wait_for(req, &retval);
296 if (retval != EOK)
297 return retval;
298
299 return EOK;
300}
301
302/** @}
303 */
Note: See TracBrowser for help on using the repository browser.