source: mainline/uspace/lib/c/generic/iplink_srv.c@ 98abd40

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 98abd40 was 02a09ed, checked in by Martin Decky <martin@…>, 12 years ago

add basic infrastructure for IPv6 (inactive)
make inet_addr_t a universal address type

  • Property mode set to 100644
File size: 6.2 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_addr_add_srv(iplink_srv_t *srv, ipc_callid_t iid,
53 ipc_call_t *icall)
54{
55 ipc_callid_t callid;
56 size_t size;
57 if (!async_data_write_receive(&callid, &size)) {
58 async_answer_0(callid, EREFUSED);
59 async_answer_0(iid, EREFUSED);
60 return;
61 }
62
63 if (size != sizeof(inet_addr_t)) {
64 async_answer_0(callid, EINVAL);
65 async_answer_0(iid, EINVAL);
66 return;
67 }
68
69 inet_addr_t addr;
70 int rc = async_data_write_finalize(callid, &addr, size);
71 if (rc != EOK) {
72 async_answer_0(callid, (sysarg_t) rc);
73 async_answer_0(iid, (sysarg_t) rc);
74 }
75
76 rc = srv->ops->addr_add(srv, &addr);
77 async_answer_0(iid, (sysarg_t) rc);
78}
79
80static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_callid_t iid,
81 ipc_call_t *icall)
82{
83 ipc_callid_t callid;
84 size_t size;
85 if (!async_data_write_receive(&callid, &size)) {
86 async_answer_0(callid, EREFUSED);
87 async_answer_0(iid, EREFUSED);
88 return;
89 }
90
91 if (size != sizeof(inet_addr_t)) {
92 async_answer_0(callid, EINVAL);
93 async_answer_0(iid, EINVAL);
94 return;
95 }
96
97 inet_addr_t addr;
98 int rc = async_data_write_finalize(callid, &addr, size);
99 if (rc != EOK) {
100 async_answer_0(callid, (sysarg_t) rc);
101 async_answer_0(iid, (sysarg_t) rc);
102 }
103
104 rc = srv->ops->addr_remove(srv, &addr);
105 async_answer_0(iid, (sysarg_t) rc);
106}
107
108static void iplink_send_srv(iplink_srv_t *srv, ipc_callid_t iid,
109 ipc_call_t *icall)
110{
111 iplink_sdu_t sdu;
112
113 ipc_callid_t callid;
114 size_t size;
115 if (!async_data_write_receive(&callid, &size)) {
116 async_answer_0(callid, EREFUSED);
117 async_answer_0(iid, EREFUSED);
118 return;
119 }
120
121 if (size != sizeof(inet_addr_t)) {
122 async_answer_0(callid, EINVAL);
123 async_answer_0(iid, EINVAL);
124 return;
125 }
126
127 int rc = async_data_write_finalize(callid, &sdu.src, size);
128 if (rc != EOK) {
129 async_answer_0(callid, (sysarg_t) rc);
130 async_answer_0(iid, (sysarg_t) rc);
131 }
132
133 if (!async_data_write_receive(&callid, &size)) {
134 async_answer_0(callid, EREFUSED);
135 async_answer_0(iid, EREFUSED);
136 return;
137 }
138
139 if (size != sizeof(inet_addr_t)) {
140 async_answer_0(callid, EINVAL);
141 async_answer_0(iid, EINVAL);
142 return;
143 }
144
145 rc = async_data_write_finalize(callid, &sdu.dest, size);
146 if (rc != EOK) {
147 async_answer_0(callid, (sysarg_t) rc);
148 async_answer_0(iid, (sysarg_t) rc);
149 }
150
151 rc = async_data_write_accept(&sdu.data, false, 0, 0, 0,
152 &sdu.size);
153 if (rc != EOK)
154 return;
155
156 rc = srv->ops->send(srv, &sdu);
157 free(sdu.data);
158 async_answer_0(iid, rc);
159}
160
161void iplink_srv_init(iplink_srv_t *srv)
162{
163 fibril_mutex_initialize(&srv->lock);
164 srv->connected = false;
165 srv->ops = NULL;
166 srv->arg = NULL;
167 srv->client_sess = NULL;
168}
169
170int iplink_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
171{
172 iplink_srv_t *srv = (iplink_srv_t *)arg;
173 int rc;
174
175 fibril_mutex_lock(&srv->lock);
176 if (srv->connected) {
177 fibril_mutex_unlock(&srv->lock);
178 async_answer_0(iid, EBUSY);
179 return EBUSY;
180 }
181
182 srv->connected = true;
183 fibril_mutex_unlock(&srv->lock);
184
185 /* Accept the connection */
186 async_answer_0(iid, EOK);
187
188 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
189 if (sess == NULL)
190 return ENOMEM;
191
192 srv->client_sess = sess;
193
194 rc = srv->ops->open(srv);
195 if (rc != EOK)
196 return rc;
197
198 while (true) {
199 ipc_call_t call;
200 ipc_callid_t callid = async_get_call(&call);
201 sysarg_t method = IPC_GET_IMETHOD(call);
202
203 if (!method) {
204 /* The other side has hung up */
205 fibril_mutex_lock(&srv->lock);
206 srv->connected = false;
207 fibril_mutex_unlock(&srv->lock);
208 async_answer_0(callid, EOK);
209 break;
210 }
211
212 switch (method) {
213 case IPLINK_GET_MTU:
214 iplink_get_mtu_srv(srv, callid, &call);
215 break;
216 case IPLINK_SEND:
217 iplink_send_srv(srv, callid, &call);
218 break;
219 case IPLINK_ADDR_ADD:
220 iplink_addr_add_srv(srv, callid, &call);
221 break;
222 case IPLINK_ADDR_REMOVE:
223 iplink_addr_remove_srv(srv, callid, &call);
224 break;
225 default:
226 async_answer_0(callid, EINVAL);
227 }
228 }
229
230 return srv->ops->close(srv);
231}
232
233int iplink_ev_recv(iplink_srv_t *srv, iplink_recv_sdu_t *sdu, uint16_t af)
234{
235 if (srv->client_sess == NULL)
236 return EIO;
237
238 async_exch_t *exch = async_exchange_begin(srv->client_sess);
239
240 ipc_call_t answer;
241 aid_t req = async_send_1(exch, IPLINK_EV_RECV, (sysarg_t) af,
242 &answer);
243
244 int rc = async_data_write_start(exch, sdu->data, sdu->size);
245 async_exchange_end(exch);
246
247 if (rc != EOK) {
248 async_forget(req);
249 return rc;
250 }
251
252 sysarg_t retval;
253 async_wait_for(req, &retval);
254 if (retval != EOK)
255 return retval;
256
257 return EOK;
258}
259
260/** @}
261 */
Note: See TracBrowser for help on using the repository browser.