source: mainline/uspace/lib/c/generic/iplink_srv.c@ 1be7bee

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