source: mainline/uspace/srv/net/loopip/loopip.c@ 4c6fd56

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4c6fd56 was 4c6fd56, checked in by Jiri Svoboda <jiri@…>, 22 months ago

loc_server_register() should be callable more than once (API only)

Now loc_server_register() returns a pointer to a loc_srv_t object,
that is then passed to loc_service_register() and
loc_service_add_to_cat().

Added loc_server_unregister() that unregisters the server
and frees the loc_srv_t object.

Updated all callers. The implementation, however, is a stub.
It is not actually possible to call loc_server_register() more
than once, yet.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
2 * Copyright (c) 2023 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 loopip
30 * @{
31 */
32/**
33 * @file
34 * @brief Loopback IP link provider
35 */
36
37#include <adt/prodcons.h>
38#include <async.h>
39#include <errno.h>
40#include <str_error.h>
41#include <inet/iplink_srv.h>
42#include <inet/addr.h>
43#include <inet/eth_addr.h>
44#include <io/log.h>
45#include <loc.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <str.h>
49#include <task.h>
50
51#define NAME "loopip"
52
53static errno_t loopip_open(iplink_srv_t *srv);
54static errno_t loopip_close(iplink_srv_t *srv);
55static errno_t loopip_send(iplink_srv_t *srv, iplink_sdu_t *sdu);
56static errno_t loopip_send6(iplink_srv_t *srv, iplink_sdu6_t *sdu);
57static errno_t loopip_get_mtu(iplink_srv_t *srv, size_t *mtu);
58static errno_t loopip_get_mac48(iplink_srv_t *srv, eth_addr_t *mac);
59static errno_t loopip_addr_add(iplink_srv_t *srv, inet_addr_t *addr);
60static errno_t loopip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr);
61
62static void loopip_client_conn(ipc_call_t *icall, void *arg);
63
64static iplink_ops_t loopip_iplink_ops = {
65 .open = loopip_open,
66 .close = loopip_close,
67 .send = loopip_send,
68 .send6 = loopip_send6,
69 .get_mtu = loopip_get_mtu,
70 .get_mac48 = loopip_get_mac48,
71 .addr_add = loopip_addr_add,
72 .addr_remove = loopip_addr_remove
73};
74
75static iplink_srv_t loopip_iplink;
76static prodcons_t loopip_rcv_queue;
77
78typedef struct {
79 link_t link;
80
81 /* XXX Version should be part of SDU */
82 ip_ver_t ver;
83 iplink_recv_sdu_t sdu;
84} rqueue_entry_t;
85
86static errno_t loopip_recv_fibril(void *arg)
87{
88 while (true) {
89 log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_recv_fibril(): Wait for one item");
90 link_t *link = prodcons_consume(&loopip_rcv_queue);
91 rqueue_entry_t *rqe =
92 list_get_instance(link, rqueue_entry_t, link);
93
94 (void) iplink_ev_recv(&loopip_iplink, &rqe->sdu, rqe->ver);
95
96 free(rqe->sdu.data);
97 free(rqe);
98 }
99
100 return 0;
101}
102
103static errno_t loopip_init(void)
104{
105 loc_srv_t *srv;
106
107 async_set_fallback_port_handler(loopip_client_conn, NULL);
108
109 errno_t rc = loc_server_register(NAME, &srv);
110 if (rc != EOK) {
111 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
112 return rc;
113 }
114
115 iplink_srv_init(&loopip_iplink);
116 loopip_iplink.ops = &loopip_iplink_ops;
117 loopip_iplink.arg = NULL;
118
119 prodcons_initialize(&loopip_rcv_queue);
120
121 const char *svc_name = "net/loopback";
122 service_id_t sid;
123 rc = loc_service_register(srv, svc_name, &sid);
124 if (rc != EOK) {
125 loc_server_unregister(srv);
126 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service %s.",
127 svc_name);
128 return rc;
129 }
130
131 category_id_t iplink_cat;
132 rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
133 if (rc != EOK) {
134 loc_service_unregister(srv, sid);
135 loc_server_unregister(srv);
136 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'iplink'.");
137 return rc;
138 }
139
140 rc = loc_service_add_to_cat(srv, sid, iplink_cat);
141 if (rc != EOK) {
142 loc_service_unregister(srv, sid);
143 loc_server_unregister(srv);
144 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding %s to category.",
145 svc_name);
146 return rc;
147 }
148
149 fid_t fid = fibril_create(loopip_recv_fibril, NULL);
150 if (fid == 0) {
151 loc_service_unregister(srv, sid);
152 loc_server_unregister(srv);
153 return ENOMEM;
154 }
155
156 fibril_add_ready(fid);
157
158 return EOK;
159}
160
161static void loopip_client_conn(ipc_call_t *icall, void *arg)
162{
163 log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_client_conn()");
164 iplink_conn(icall, &loopip_iplink);
165}
166
167static errno_t loopip_open(iplink_srv_t *srv)
168{
169 log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_open()");
170 return EOK;
171}
172
173static errno_t loopip_close(iplink_srv_t *srv)
174{
175 log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_close()");
176 return EOK;
177}
178
179static errno_t loopip_send(iplink_srv_t *srv, iplink_sdu_t *sdu)
180{
181 log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_send()");
182
183 rqueue_entry_t *rqe = calloc(1, sizeof(rqueue_entry_t));
184 if (rqe == NULL)
185 return ENOMEM;
186
187 /*
188 * Clone SDU
189 */
190 rqe->ver = ip_v4;
191 rqe->sdu.data = malloc(sdu->size);
192 if (rqe->sdu.data == NULL) {
193 free(rqe);
194 return ENOMEM;
195 }
196
197 memcpy(rqe->sdu.data, sdu->data, sdu->size);
198 rqe->sdu.size = sdu->size;
199
200 /*
201 * Insert to receive queue
202 */
203 prodcons_produce(&loopip_rcv_queue, &rqe->link);
204
205 return EOK;
206}
207
208static errno_t loopip_send6(iplink_srv_t *srv, iplink_sdu6_t *sdu)
209{
210 log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip6_send()");
211
212 rqueue_entry_t *rqe = calloc(1, sizeof(rqueue_entry_t));
213 if (rqe == NULL)
214 return ENOMEM;
215
216 /*
217 * Clone SDU
218 */
219 rqe->ver = ip_v6;
220 rqe->sdu.data = malloc(sdu->size);
221 if (rqe->sdu.data == NULL) {
222 free(rqe);
223 return ENOMEM;
224 }
225
226 memcpy(rqe->sdu.data, sdu->data, sdu->size);
227 rqe->sdu.size = sdu->size;
228
229 /*
230 * Insert to receive queue
231 */
232 prodcons_produce(&loopip_rcv_queue, &rqe->link);
233
234 return EOK;
235}
236
237static errno_t loopip_get_mtu(iplink_srv_t *srv, size_t *mtu)
238{
239 log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_get_mtu()");
240 *mtu = 1500;
241 return EOK;
242}
243
244static errno_t loopip_get_mac48(iplink_srv_t *src, eth_addr_t *mac)
245{
246 log_msg(LOG_DEFAULT, LVL_DEBUG, "loopip_get_mac48()");
247 return ENOTSUP;
248}
249
250static errno_t loopip_addr_add(iplink_srv_t *srv, inet_addr_t *addr)
251{
252 return EOK;
253}
254
255static errno_t loopip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr)
256{
257 return EOK;
258}
259
260int main(int argc, char *argv[])
261{
262 printf("%s: HelenOS loopback IP link provider\n", NAME);
263
264 errno_t rc = log_init(NAME);
265 if (rc != EOK) {
266 printf("%s: Failed to initialize logging: %s.\n", NAME, str_error(rc));
267 return rc;
268 }
269
270 rc = loopip_init();
271 if (rc != EOK) {
272 printf("%s: Failed to initialize loopip: %s.\n", NAME, str_error(rc));
273 return rc;
274 }
275
276 printf("%s: Accepting connections.\n", NAME);
277 task_retval(0);
278 async_manager();
279
280 /* Not reached */
281 return 0;
282}
283
284/** @}
285 */
Note: See TracBrowser for help on using the repository browser.