source: mainline/uspace/srv/net/ethip/ethip.c@ aab85d90

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since aab85d90 was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 8.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 ethip
30 * @{
31 */
32/**
33 * @file
34 * @brief IP link provider for Ethernet
35 *
36 * Based on the IETF RFC 894 standard.
37 */
38
39#include <async.h>
40#include <errno.h>
41#include <inet/iplink_srv.h>
42#include <io/log.h>
43#include <loc.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <task.h>
47#include "arp.h"
48#include "ethip.h"
49#include "ethip_nic.h"
50#include "pdu.h"
51#include "std.h"
52
53#define NAME "ethip"
54
55static errno_t ethip_open(iplink_srv_t *srv);
56static errno_t ethip_close(iplink_srv_t *srv);
57static errno_t ethip_send(iplink_srv_t *srv, iplink_sdu_t *sdu);
58static errno_t ethip_send6(iplink_srv_t *srv, iplink_sdu6_t *sdu);
59static errno_t ethip_get_mtu(iplink_srv_t *srv, size_t *mtu);
60static errno_t ethip_get_mac48(iplink_srv_t *srv, addr48_t *mac);
61static errno_t ethip_set_mac48(iplink_srv_t *srv, addr48_t *mac);
62static errno_t ethip_addr_add(iplink_srv_t *srv, inet_addr_t *addr);
63static errno_t ethip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr);
64
65static void ethip_client_conn(ipc_call_t *icall, void *arg);
66
67static iplink_ops_t ethip_iplink_ops = {
68 .open = ethip_open,
69 .close = ethip_close,
70 .send = ethip_send,
71 .send6 = ethip_send6,
72 .get_mtu = ethip_get_mtu,
73 .get_mac48 = ethip_get_mac48,
74 .set_mac48 = ethip_set_mac48,
75 .addr_add = ethip_addr_add,
76 .addr_remove = ethip_addr_remove
77};
78
79static errno_t ethip_init(void)
80{
81 async_set_fallback_port_handler(ethip_client_conn, NULL);
82
83 errno_t rc = loc_server_register(NAME);
84 if (rc != EOK) {
85 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server.");
86 return rc;
87 }
88
89 rc = ethip_nic_discovery_start();
90 if (rc != EOK)
91 return rc;
92
93 return EOK;
94}
95
96errno_t ethip_iplink_init(ethip_nic_t *nic)
97{
98 errno_t rc;
99 service_id_t sid;
100 category_id_t iplink_cat;
101 static unsigned link_num = 0;
102 char *svc_name = NULL;
103
104 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_iplink_init()");
105
106 iplink_srv_init(&nic->iplink);
107 nic->iplink.ops = &ethip_iplink_ops;
108 nic->iplink.arg = nic;
109
110 if (asprintf(&svc_name, "net/eth%u", ++link_num) < 0) {
111 log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
112 rc = ENOMEM;
113 goto error;
114 }
115
116 rc = loc_service_register(svc_name, &sid);
117 if (rc != EOK) {
118 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service %s.", svc_name);
119 goto error;
120 }
121
122 nic->iplink_sid = sid;
123
124 rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
125 if (rc != EOK) {
126 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'iplink'.");
127 goto error;
128 }
129
130 rc = loc_service_add_to_cat(sid, iplink_cat);
131 if (rc != EOK) {
132 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding %s to category.", svc_name);
133 goto error;
134 }
135
136 return EOK;
137
138error:
139 if (svc_name != NULL)
140 free(svc_name);
141 return rc;
142}
143
144static void ethip_client_conn(ipc_call_t *icall, void *arg)
145{
146 ethip_nic_t *nic;
147 service_id_t sid;
148
149 sid = (service_id_t) IPC_GET_ARG2(*icall);
150 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_client_conn(%u)", (unsigned)sid);
151 nic = ethip_nic_find_by_iplink_sid(sid);
152 if (nic == NULL) {
153 log_msg(LOG_DEFAULT, LVL_WARN, "Uknown service ID.");
154 return;
155 }
156
157 iplink_conn(icall, &nic->iplink);
158}
159
160static errno_t ethip_open(iplink_srv_t *srv)
161{
162 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_open()");
163 return EOK;
164}
165
166static errno_t ethip_close(iplink_srv_t *srv)
167{
168 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_close()");
169 return EOK;
170}
171
172static errno_t ethip_send(iplink_srv_t *srv, iplink_sdu_t *sdu)
173{
174 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_send()");
175
176 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
177 eth_frame_t frame;
178
179 errno_t rc = arp_translate(nic, sdu->src, sdu->dest, frame.dest);
180 if (rc != EOK) {
181 log_msg(LOG_DEFAULT, LVL_WARN, "Failed to look up IPv4 address 0x%"
182 PRIx32, sdu->dest);
183 return rc;
184 }
185
186 addr48(nic->mac_addr, frame.src);
187 frame.etype_len = ETYPE_IP;
188 frame.data = sdu->data;
189 frame.size = sdu->size;
190
191 void *data;
192 size_t size;
193 rc = eth_pdu_encode(&frame, &data, &size);
194 if (rc != EOK)
195 return rc;
196
197 rc = ethip_nic_send(nic, data, size);
198 free(data);
199
200 return rc;
201}
202
203static errno_t ethip_send6(iplink_srv_t *srv, iplink_sdu6_t *sdu)
204{
205 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_send6()");
206
207 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
208 eth_frame_t frame;
209
210 addr48(sdu->dest, frame.dest);
211 addr48(nic->mac_addr, frame.src);
212 frame.etype_len = ETYPE_IPV6;
213 frame.data = sdu->data;
214 frame.size = sdu->size;
215
216 void *data;
217 size_t size;
218 errno_t rc = eth_pdu_encode(&frame, &data, &size);
219 if (rc != EOK)
220 return rc;
221
222 rc = ethip_nic_send(nic, data, size);
223 free(data);
224
225 return rc;
226}
227
228errno_t ethip_received(iplink_srv_t *srv, void *data, size_t size)
229{
230 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_received(): srv=%p", srv);
231 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
232
233 log_msg(LOG_DEFAULT, LVL_DEBUG, " - eth_pdu_decode");
234
235 eth_frame_t frame;
236 errno_t rc = eth_pdu_decode(data, size, &frame);
237 if (rc != EOK) {
238 log_msg(LOG_DEFAULT, LVL_DEBUG, " - eth_pdu_decode failed");
239 return rc;
240 }
241
242 iplink_recv_sdu_t sdu;
243
244 switch (frame.etype_len) {
245 case ETYPE_ARP:
246 arp_received(nic, &frame);
247 break;
248 case ETYPE_IP:
249 log_msg(LOG_DEFAULT, LVL_DEBUG, " - construct SDU");
250 sdu.data = frame.data;
251 sdu.size = frame.size;
252 log_msg(LOG_DEFAULT, LVL_DEBUG, " - call iplink_ev_recv");
253 rc = iplink_ev_recv(&nic->iplink, &sdu, ip_v4);
254 break;
255 case ETYPE_IPV6:
256 log_msg(LOG_DEFAULT, LVL_DEBUG, " - construct SDU IPv6");
257 sdu.data = frame.data;
258 sdu.size = frame.size;
259 log_msg(LOG_DEFAULT, LVL_DEBUG, " - call iplink_ev_recv");
260 rc = iplink_ev_recv(&nic->iplink, &sdu, ip_v6);
261 break;
262 default:
263 log_msg(LOG_DEFAULT, LVL_DEBUG, "Unknown ethertype 0x%" PRIx16,
264 frame.etype_len);
265 }
266
267 free(frame.data);
268 return rc;
269}
270
271static errno_t ethip_get_mtu(iplink_srv_t *srv, size_t *mtu)
272{
273 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_get_mtu()");
274 *mtu = 1500;
275 return EOK;
276}
277
278static errno_t ethip_get_mac48(iplink_srv_t *srv, addr48_t *mac)
279{
280 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_get_mac48()");
281
282 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
283 addr48(nic->mac_addr, *mac);
284
285 return EOK;
286}
287
288static errno_t ethip_set_mac48(iplink_srv_t *srv, addr48_t *mac)
289{
290 log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_set_mac48()");
291
292 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
293 addr48(*mac, nic->mac_addr);
294
295 return EOK;
296}
297
298static errno_t ethip_addr_add(iplink_srv_t *srv, inet_addr_t *addr)
299{
300 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
301
302 return ethip_nic_addr_add(nic, addr);
303}
304
305static errno_t ethip_addr_remove(iplink_srv_t *srv, inet_addr_t *addr)
306{
307 ethip_nic_t *nic = (ethip_nic_t *) srv->arg;
308
309 return ethip_nic_addr_remove(nic, addr);
310}
311
312int main(int argc, char *argv[])
313{
314 errno_t rc;
315
316 printf(NAME ": HelenOS IP over Ethernet service\n");
317
318 if (log_init(NAME) != EOK) {
319 printf(NAME ": Failed to initialize logging.\n");
320 return 1;
321 }
322
323 rc = ethip_init();
324 if (rc != EOK)
325 return 1;
326
327 printf(NAME ": Accepting connections.\n");
328 task_retval(0);
329 async_manager();
330
331 /* Not reached */
332 return 0;
333}
334
335/** @}
336 */
Note: See TracBrowser for help on using the repository browser.