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
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
[02a09ed]52static void iplink_addr_add_srv(iplink_srv_t *srv, ipc_callid_t iid,
53 ipc_call_t *icall)
[962f03b]54{
[02a09ed]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);
[962f03b]78}
79
[02a09ed]80static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_callid_t iid,
81 ipc_call_t *icall)
[962f03b]82{
[02a09ed]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);
[962f03b]106}
107
[02a09ed]108static void iplink_send_srv(iplink_srv_t *srv, ipc_callid_t iid,
109 ipc_call_t *icall)
[f834f90d]110{
[02a09ed]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 }
[b5cf742a]120
[02a09ed]121 if (size != sizeof(inet_addr_t)) {
122 async_answer_0(callid, EINVAL);
123 async_answer_0(iid, EINVAL);
124 return;
125 }
[b5cf742a]126
[02a09ed]127 int rc = async_data_write_finalize(callid, &sdu.src, size);
[f834f90d]128 if (rc != EOK) {
[02a09ed]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);
[f834f90d]136 return;
137 }
[b5cf742a]138
[02a09ed]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
[4f64a523]156 rc = srv->ops->send(srv, &sdu);
[f834f90d]157 free(sdu.data);
[02a09ed]158 async_answer_0(iid, rc);
[f834f90d]159}
160
[4f64a523]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
[f834f90d]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;
[b5cf742a]174
[4f64a523]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 }
[b5cf742a]181
[4f64a523]182 srv->connected = true;
183 fibril_mutex_unlock(&srv->lock);
[b5cf742a]184
[f834f90d]185 /* Accept the connection */
186 async_answer_0(iid, EOK);
[b5cf742a]187
[f834f90d]188 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
189 if (sess == NULL)
190 return ENOMEM;
[b5cf742a]191
[4f64a523]192 srv->client_sess = sess;
[b5cf742a]193
[4f64a523]194 rc = srv->ops->open(srv);
[f834f90d]195 if (rc != EOK)
196 return rc;
[b5cf742a]197
[f834f90d]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);
[b5cf742a]202
[f834f90d]203 if (!method) {
204 /* The other side has hung up */
[a2e3ee6]205 fibril_mutex_lock(&srv->lock);
[4802dd7]206 srv->connected = false;
[a2e3ee6]207 fibril_mutex_unlock(&srv->lock);
[f834f90d]208 async_answer_0(callid, EOK);
209 break;
210 }
[b5cf742a]211
[f834f90d]212 switch (method) {
213 case IPLINK_GET_MTU:
[4f64a523]214 iplink_get_mtu_srv(srv, callid, &call);
[f834f90d]215 break;
216 case IPLINK_SEND:
[4f64a523]217 iplink_send_srv(srv, callid, &call);
[f834f90d]218 break;
[962f03b]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;
[f834f90d]225 default:
226 async_answer_0(callid, EINVAL);
227 }
228 }
[b5cf742a]229
[4f64a523]230 return srv->ops->close(srv);
[f834f90d]231}
232
[02a09ed]233int iplink_ev_recv(iplink_srv_t *srv, iplink_recv_sdu_t *sdu, uint16_t af)
[f834f90d]234{
[4f64a523]235 if (srv->client_sess == NULL)
236 return EIO;
[b5cf742a]237
[4f64a523]238 async_exch_t *exch = async_exchange_begin(srv->client_sess);
[b5cf742a]239
[f834f90d]240 ipc_call_t answer;
[02a09ed]241 aid_t req = async_send_1(exch, IPLINK_EV_RECV, (sysarg_t) af,
242 &answer);
243
[f834f90d]244 int rc = async_data_write_start(exch, sdu->data, sdu->size);
245 async_exchange_end(exch);
[b5cf742a]246
[f834f90d]247 if (rc != EOK) {
[50b581d]248 async_forget(req);
[f834f90d]249 return rc;
250 }
[b5cf742a]251
[f834f90d]252 sysarg_t retval;
253 async_wait_for(req, &retval);
254 if (retval != EOK)
255 return retval;
[b5cf742a]256
[f834f90d]257 return EOK;
258}
259
260/** @}
261 */
Note: See TracBrowser for help on using the repository browser.