source: mainline/uspace/srv/net/ethip/ethip.c@ 95658c9

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

Rename and move addr48_t to eth_addr_t

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